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.
Files changed (529) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +3 -0
  3. data/TODO.complete/01-t-xref-parsing.md +91 -0
  4. data/TODO.complete/02-per-label-geometry.md +50 -0
  5. data/TODO.complete/03-object-properties-constraints.md +57 -0
  6. data/TODO.complete/04-operation-params.md +37 -0
  7. data/TODO.complete/05-pdata-flag-matrix.md +52 -0
  8. data/TODO.complete/06-emf-image-rendering.md +34 -0
  9. data/TODO.complete/07-auxiliary-tables.md +47 -0
  10. data/TODO.complete/10-mdg-stereotype-registry.md +40 -0
  11. data/TODO.complete/11-gml-xsd-generation.md +42 -0
  12. data/TODO.complete/13-shapescript-interpreter.md +28 -0
  13. data/TODO.complete/20-cli-diff.md +46 -0
  14. data/TODO.complete/21-cli-render.md +26 -0
  15. data/TODO.complete/22-cli-export.md +29 -0
  16. data/TODO.complete/23-cli-mdg.md +23 -0
  17. data/TODO.complete/30-headerlines-ocp-refactor.md +72 -0
  18. data/TODO.complete/31-public-send-cleanup.md +61 -0
  19. data/TODO.complete/32-spec-coverage.md +33 -0
  20. data/TODO.complete/33-blocked-parity-gaps.md +41 -0
  21. data/TODO.complete/36-stereotype-icon-wiring.md +32 -0
  22. data/TODO.complete/37-cli-lint.md +32 -0
  23. data/TODO.complete/38-cli-query.md +26 -0
  24. data/TODO.complete/39-cli-info.md +23 -0
  25. data/TODO.complete/40-ocl-evaluator.md +31 -0
  26. data/TODO.complete/41-round-trip-spec.md +18 -0
  27. data/TODO.complete/42-html-diff-report.md +18 -0
  28. data/TODO.complete/43-json-schema-export.md +20 -0
  29. data/TODO.complete/44-remaining-qea-tables.md +40 -0
  30. data/TODO.complete/45-shapescript-extensions.md +25 -0
  31. data/TODO.complete/46-xsd-consolidation.md +20 -0
  32. data/TODO.complete/47-headerlines-legacy-removal.md +20 -0
  33. data/TODO.complete/STATUS.md +109 -0
  34. data/TODO.diagrams/01-svg-measurement-harness.md +31 -0
  35. data/TODO.diagrams/02-polygon-over-rendering.md +29 -0
  36. data/TODO.diagrams/03-text-over-rendering.md +30 -0
  37. data/TODO.diagrams/04-rect-under-rendering.md +33 -0
  38. data/TODO.diagrams/05-canvas-dimension-parity.md +51 -0
  39. data/TODO.diagrams/06-group-layering-parity.md +39 -0
  40. data/TODO.diagrams/07-text-content-fidelity.md +65 -0
  41. data/TODO.diagrams/08-qea-direct-pipeline.md +46 -0
  42. data/TODO.diagrams/12-connector-labels.md +40 -0
  43. data/TODO.diagrams/12-per-entity-svg-layer-ordering.md +24 -0
  44. data/TODO.diagrams/13-marker-polygon-vs-path-dispatch.md +20 -0
  45. data/TODO.diagrams/13-per-text-type-font-sizes.md +33 -0
  46. data/TODO.diagrams/14-center-header-text.md +33 -0
  47. data/TODO.diagrams/14-filter-diagram-frame-elements.md +18 -0
  48. data/TODO.diagrams/15-deep-dead-code-audit.md +47 -0
  49. data/TODO.diagrams/15-per-element-font-from-style.md +24 -0
  50. data/TODO.diagrams/16-canvas-marker-extent.md +30 -0
  51. data/TODO.diagrams/16-document-remaining-parity-gaps.md +91 -0
  52. data/TODO.diagrams/17-italic-abstract-classes.md +28 -0
  53. data/TODO.diagrams/17-remaining-parity-gaps.md +90 -0
  54. data/TODO.diagrams/18-canvas-from-image-bounds.md +20 -0
  55. data/TODO.diagrams/18-property-lookup-index.md +42 -0
  56. data/TODO.diagrams/19-connector-sx-sy-routing.md +27 -0
  57. data/TODO.diagrams/19-replace-respond-to-with-is-a.md +31 -0
  58. data/TODO.diagrams/20-split-labels-emitter.md +56 -0
  59. data/TODO.diagrams/20-visibility-glyph-font-encoding.md +27 -0
  60. data/TODO.diagrams/21-aggregation-navigability-arrow.md +21 -0
  61. data/TODO.diagrams/21-auto-generated-legend-block.md +65 -0
  62. data/TODO.diagrams/22-ghost-element-discriminator.md +57 -0
  63. data/TODO.diagrams/22-style-based-path-grouping.md +28 -0
  64. data/TODO.diagrams/23-marker-polygon-deduplication.md +47 -0
  65. data/TODO.diagrams/23-multiplicity-label-positioning.md +29 -0
  66. data/TODO.diagrams/24-marker-anchor-structural.md +35 -0
  67. data/TODO.diagrams/24-track-marker-anchors-structurally.md +66 -0
  68. data/TODO.diagrams/24-truncate-properties-to-fit-box.md +24 -0
  69. data/TODO.diagrams/26-phantom-general-parent-rendering.md +59 -0
  70. data/TODO.diagrams/27-path-grouping-mode-detection.md +43 -0
  71. data/TODO.diagrams/28-architecture-cleanup-batch.md +47 -0
  72. data/TODO.diagrams/30-decompose-elements-groups-for.md +52 -0
  73. data/TODO.diagrams/32-examples-coverage-batch.md +78 -0
  74. data/TODO.diagrams/36-instance-specification-model.md +42 -0
  75. data/TODO.diagrams/37-element-icon-decorations.md +41 -0
  76. data/TODO.diagrams/38-html-note-and-receptions.md +32 -0
  77. data/TODO.diagrams/39-property-stereotype-discriminator.md +40 -0
  78. data/TODO.diagrams/40-standalone-1-discriminator.md +38 -0
  79. data/TODO.diagrams/41-xmi-to-svg-pipeline.md +113 -0
  80. data/TODO.diagrams/42-close-all-parity-deltas.md +69 -0
  81. data/TODO.diagrams/43-marker-deduplication-strategy.md +54 -0
  82. data/TODO.diagrams/44-element-icon-decorations.md +34 -0
  83. data/TODO.diagrams/45-phantom-parent-class-boxes.md +40 -0
  84. data/TODO.diagrams/46-user-drawn-legend-swatches.md +44 -0
  85. data/TODO.diagrams/47-attribute-line-fidelity.md +72 -0
  86. data/TODO.diagrams/48-spec-coverage-critical-emitter-components.md +45 -0
  87. data/TODO.diagrams/49-spec-coverage-orchestrators.md +25 -0
  88. data/TODO.diagrams/50-examples-parity.md +85 -0
  89. data/TODO.diagrams/51-property-oy-gap-and-remaining-gaps.md +48 -0
  90. data/TODO.diagrams/52-marker-registration-architecture.md +89 -0
  91. data/TODO.diagrams/53-remaining-example-gaps.md +86 -0
  92. data/TODO.diagrams/54-display-name-nested-classes.md +40 -0
  93. data/TODO.diagrams/55-visibility-icon-discriminator.md +58 -0
  94. data/TODO.diagrams/56-package-contents-rendering.md +148 -0
  95. data/TODO.diagrams/57-instance-specification-model.md +100 -0
  96. data/TODO.diagrams/58-domain-model-note-text.md +67 -0
  97. data/TODO.diagrams/59-classes-arrow-discriminator.md +57 -0
  98. data/TODO.diagrams/60-testschema-association-marker.md +40 -0
  99. data/TODO.diagrams/61-legend-block-rendering.md +55 -0
  100. data/TODO.diagrams/61-plateau-parity-gaps.md +59 -0
  101. data/TODO.diagrams/62-ghost-element-rendering.md +56 -0
  102. data/TODO.diagrams/63-qualified-name-wrap.md +36 -0
  103. data/TODO.diagrams/64-property-stereotype-labels.md +22 -0
  104. data/TODO.diagrams/65-path-coordinate-frame.md +62 -0
  105. data/TODO.diagrams/67-path-coordinate-frame.md +62 -0
  106. data/TODO.diagrams/68-inherited-attributes.md +65 -0
  107. data/TODO.diagrams/69-package-anchor-conditional.md +29 -0
  108. data/TODO.diagrams/70-mdg-technology-support.md +68 -0
  109. data/TODO.diagrams/71-off-canvas-parent-ghost.md +45 -0
  110. data/TODO.diagrams/72-basic-attr-divider-paths.md +39 -0
  111. data/TODO.diagrams/73-plateau-polygon-gap.md +69 -0
  112. data/TODO.diagrams/74-plateau-rect-gap.md +22 -0
  113. data/TODO.diagrams/75-plateau-text-gap.md +39 -0
  114. data/TODO.diagrams/76-basic-poly-path-gaps.md +41 -0
  115. data/TODO.diagrams/77-basic-text-overrender.md +40 -0
  116. data/TODO.diagrams/78-headerlines-ocp-refactor.md +65 -0
  117. data/TODO.diagrams/79-architecture-backlog.md +65 -0
  118. data/TODO.diagrams/80-basic-triangle-polygons.md +51 -0
  119. data/TODO.diagrams/81-plateau-path-overrender.md +53 -0
  120. data/TODO.diagrams/82-appearance-canvas-offset.md +54 -0
  121. data/TODO.diagrams/83-3d-diagram-subtitle.md +58 -0
  122. data/TODO.diagrams/84-canvas-offset-mismatches.md +61 -0
  123. data/TODO.diagrams/85-phantom-property-overrender.md +95 -0
  124. data/TODO.diagrams/86-foreign-package-rule.md +62 -0
  125. data/TODO.diagrams/87-internal-tech-encryption.md +80 -0
  126. data/TODO.diagrams/EXAMPLES_STATUS.md +88 -0
  127. data/TODO.diagrams/README.md +69 -0
  128. data/TODO.diagrams/STATUS.md +73 -0
  129. data/TODO.fixup/01-default-grouped-paths.md +34 -0
  130. data/TODO.fixup/02-marker-consolidation-per-connector.md +20 -0
  131. data/TODO.fixup/03-diagram-font-inference.md +28 -0
  132. data/TODO.fixup/04-extract-bounds-calculator.md +25 -0
  133. data/TODO.fixup/05-marker-registry-ocp.md +32 -0
  134. data/TODO.fixup/06-connector-path-bend-routing.md +28 -0
  135. data/TODO.fixup/07-edge-attachment-formula.md +22 -0
  136. data/TODO.fixup/08-visual-diff-harness.md +28 -0
  137. data/TODO.fixup/09-extract-element-compartments.md +34 -0
  138. data/TODO.fixup/10-canvas-width-overshoot-fix.md +20 -0
  139. data/TODO.fixup/11-layer-sequencer-extraction.md +18 -0
  140. data/TODO.fixup/12-path-style-harmony.md +23 -0
  141. data/TODO.fixup/13-datatype-stereotype-fallback.md +28 -0
  142. data/TODO.fixup/14-ea-exe-reverse-engineering-notes.md +56 -0
  143. data/TODO.fixup/15-enumeration-literal-rendering.md +30 -0
  144. data/TODO.fixup/16-operation-compartment-rendering.md +42 -0
  145. data/TODO.fixup/17-path-count-calibration.md +27 -0
  146. data/TODO.fixup/18-polygon-count-calibration.md +32 -0
  147. data/TODO.fixup/19-rect-count-undershoot-investigation.md +40 -0
  148. data/TODO.fixup/20-stereotype-color-from-classifier.md +18 -0
  149. data/TODO.fixup/21-visibility-filter-for-properties.md +24 -0
  150. data/TODO.fixup/22-multiplicity-display-rule-calibration.md +25 -0
  151. data/TODO.fixup/23-diagram-frame-title-element.md +31 -0
  152. data/TODO.fixup/24-note-element-rendering.md +23 -0
  153. data/TODO.fixup/25-ea-exe-disassembly-findings.md +177 -0
  154. data/TODO.fixup/26-svg-renderer-architecture.md +78 -0
  155. data/TODO.fixup/27-svg-element-emitters-disassembly.md +135 -0
  156. data/TODO.fixup/28-geometry-parser-identification.md +57 -0
  157. data/TODO.fixup/29-qea-svg-xmi-triple-comparison.md +185 -0
  158. data/TODO.fixup/30-theme-system-stub.md +46 -0
  159. data/TODO.fixup/31-theme-value-object-registry.md +17 -0
  160. data/TODO.fixup/32-styleex-on-diagram-model.md +22 -0
  161. data/TODO.fixup/33-text-encoding-decimals-rotation.md +29 -0
  162. data/TODO.fixup/34-per-type-fill-via-theme.md +18 -0
  163. data/TODO.fixup/35-stroke-width-per-theme.md +7 -0
  164. data/TODO.fixup/36-qea-rect-coord-normalization.md +24 -0
  165. data/TODO.fixup/37-package-shape-rendering.md +22 -0
  166. data/TODO.fixup/38-note-element-rendering.md +15 -0
  167. data/TODO.fixup/39-styleex-flag-honoring.md +25 -0
  168. data/TODO.fixup/40-connector-dashed-lines.md +15 -0
  169. data/TODO.fixup/41-diagram-frame-showborder-detection.md +23 -0
  170. data/TODO.fixup/42-textrenderer-centralization.md +10 -0
  171. data/TODO.fixup/43-colorresolver-unification.md +24 -0
  172. data/TODO.fixup/44-theme-aware-textrenderer.md +17 -0
  173. data/TODO.fixup/45-theme-aware-fontresolver.md +22 -0
  174. data/TODO.fixup/46-style-parameterized-by-theme.md +21 -0
  175. data/TODO.fixup/47-canvas-frame-inset.md +19 -0
  176. data/TODO.fixup/48-background-rect-format.md +15 -0
  177. data/TODO.fixup/49-all-samples-integration-test.md +17 -0
  178. data/TODO.fixup/50-svg-emitter-architecture-docs.md +33 -0
  179. data/TODO.fixup/51-promote-theme-to-ea-namespace.md +28 -0
  180. data/TODO.fixup/52-theme-definition-integrated-fills.md +26 -0
  181. data/TODO.fixup/53-theme-registry-yaml-loading.md +50 -0
  182. data/TODO.fixup/54-diagram-theme-api.md +50 -0
  183. data/TODO.fixup/55-update-eaemitter-to-ea-theme.md +23 -0
  184. data/TODO.fixup/56-theme-yaml-files.md +65 -0
  185. data/TODO.fixup/57-theme-specs-and-integration.md +27 -0
  186. data/TODO.fixup/58-ea-entry-point-theme-autoload.md +20 -0
  187. data/TODO.fixup/59-thread-theme-through-all-renderers.md +29 -0
  188. data/TODO.fixup/60-cli-theme-option.md +22 -0
  189. data/TODO.fixup/61-theme-validation.md +28 -0
  190. data/TODO.fixup/62-theme-builder-dsl.md +31 -0
  191. data/TODO.fixup/63-theme-integration-rendering-spec.md +24 -0
  192. data/TODO.fixup/64-theme-writeback-styleex.md +21 -0
  193. data/TODO.fixup/65-remove-dead-eaemitter-theme-files.md +30 -0
  194. data/TODO.fixup/66-styleex-writeback.md +22 -0
  195. data/TODO.fixup/67-delete-dead-code.md +28 -0
  196. data/TODO.fixup/68-figure-parity-status.md +82 -0
  197. data/TODO.fixup/69-package-polygon-rendering.md +54 -0
  198. data/TODO.fixup/70-tagged-values-compartment.md +39 -0
  199. data/TODO.fixup/71-auto-detect-theme-from-xmi.md +37 -0
  200. data/TODO.fixup/72-sample-exports-as-regression-specs.md +37 -0
  201. data/TODO.fixup/73-delete-dead-transformations.md +14 -0
  202. data/TODO.fixup/74-delete-dead-diagram-renderers.md +18 -0
  203. data/TODO.fixup/75-visibility-legend-icons.md +23 -0
  204. data/TODO.fixup/76-plateau-text-undershoot.md +27 -0
  205. data/TODO.fixup/77-canvas-frame-margins.md +28 -0
  206. data/TODO.fixup/78-note-element-rendering.md +30 -0
  207. data/TODO.fixup/79-operation-compartment-rendering.md +27 -0
  208. data/TODO.fixup/80-tagged-value-stereotype-visibility.md +37 -0
  209. data/TODO.fixup/81-figure-parity-current-state.md +63 -0
  210. data/config/qea_schema.yml +356 -0
  211. data/config/themes/119.yml +98 -0
  212. data/config/themes/default.yml +14 -0
  213. data/examples/exports/20251010_current_plateau_v5/UML_EA.DTD +6856 -0
  214. data/examples/exports/20251010_current_plateau_v5/model.xml +96709 -0
  215. data/examples/exports/ArcGISWorkspace_template/UML_EA.DTD +6856 -0
  216. data/examples/exports/ArcGISWorkspace_template/model.xml +1427 -0
  217. data/examples/exports/UmlModel_template/UML_EA.DTD +6856 -0
  218. data/examples/exports/UmlModel_template/model.xml +23 -0
  219. data/examples/exports/basic/UML_EA.DTD +6856 -0
  220. data/examples/exports/basic/model.xml +8039 -0
  221. data/examples/exports/simple/UML_EA.DTD +6856 -0
  222. data/examples/exports/simple/model.xml +585 -0
  223. data/examples/exports/simple_example/UML_EA.DTD +6856 -0
  224. data/examples/exports/simple_example/model.xml +23 -0
  225. data/examples/exports/test/UML_EA.DTD +6856 -0
  226. data/examples/exports/test/model.xml +1638 -0
  227. data/examples/qea/basic.qea +0 -0
  228. data/frontend/README.md +51 -0
  229. data/frontend/dist/app.iife.js +24 -0
  230. data/frontend/dist/style.css +1 -0
  231. data/frontend/index.html +26 -0
  232. data/frontend/package-lock.json +2359 -0
  233. data/frontend/package.json +26 -0
  234. data/frontend/src/App.vue +59 -0
  235. data/frontend/src/app.ts +8 -0
  236. data/frontend/src/components/AppHeader.vue +127 -0
  237. data/frontend/src/components/AppSidebar.vue +119 -0
  238. data/frontend/src/components/ClassDetails.vue +247 -0
  239. data/frontend/src/components/DiagramView.vue +79 -0
  240. data/frontend/src/components/PackageDetails.vue +92 -0
  241. data/frontend/src/components/PackageTreeNode.vue +64 -0
  242. data/frontend/src/components/SearchResults.vue +48 -0
  243. data/frontend/src/components/WelcomeView.vue +87 -0
  244. data/frontend/src/shims-vue.d.ts +5 -0
  245. data/frontend/src/stores/dataStore.ts +79 -0
  246. data/frontend/src/stores/uiStore.ts +167 -0
  247. data/frontend/src/styles/main.css +1566 -0
  248. data/frontend/src/types.ts +221 -0
  249. data/frontend/tests/e2e/__screenshots__/new-dark-mode.png +0 -0
  250. data/frontend/tests/e2e/__screenshots__/new-package-details.png +0 -0
  251. data/frontend/tests/e2e/__screenshots__/new-search-modal.png +0 -0
  252. data/frontend/tests/e2e/__screenshots__/new-sidebar-collapsed.png +0 -0
  253. data/frontend/tests/e2e/__screenshots__/new-welcome.png +0 -0
  254. data/frontend/tests/e2e/render.spec.ts +188 -0
  255. data/frontend/tsconfig.json +20 -0
  256. data/frontend/vite.config.ts +26 -0
  257. data/frontend/vitest.config.ts +8 -0
  258. data/lib/ea/cli/app.rb +57 -2
  259. data/lib/ea/cli/command/diagrams.rb +37 -28
  260. data/lib/ea/cli/command/diff.rb +46 -0
  261. data/lib/ea/cli/command/export.rb +80 -0
  262. data/lib/ea/cli/command/info.rb +75 -0
  263. data/lib/ea/cli/command/lint.rb +48 -0
  264. data/lib/ea/cli/command/mdg.rb +98 -0
  265. data/lib/ea/cli/command/query.rb +34 -0
  266. data/lib/ea/cli/command/render.rb +135 -0
  267. data/lib/ea/cli/command/svg.rb +8 -15
  268. data/lib/ea/cli/command.rb +7 -0
  269. data/lib/ea/diagram/display_config.rb +184 -0
  270. data/lib/ea/diagram.rb +4 -41
  271. data/lib/ea/diff/change.rb +30 -0
  272. data/lib/ea/diff/comparator.rb +82 -0
  273. data/lib/ea/diff/html_reporter.rb +91 -0
  274. data/lib/ea/diff.rb +15 -0
  275. data/lib/ea/export/json/generator.rb +42 -0
  276. data/lib/ea/export/json.rb +12 -0
  277. data/lib/ea/export/json_schema/generator.rb +77 -0
  278. data/lib/ea/export/json_schema.rb +12 -0
  279. data/lib/ea/export/plantuml/generator.rb +73 -0
  280. data/lib/ea/export/plantuml.rb +12 -0
  281. data/lib/ea/export/xmi/generator.rb +77 -0
  282. data/lib/ea/export/xmi.rb +11 -0
  283. data/lib/ea/export/xsd/class_mapping.rb +65 -0
  284. data/lib/ea/export/xsd/generator.rb +142 -0
  285. data/lib/ea/export/xsd/namespace_registry.rb +82 -0
  286. data/lib/ea/export/xsd.rb +19 -0
  287. data/lib/ea/export.rb +14 -0
  288. data/lib/ea/image/emf_renderer.rb +42 -0
  289. data/lib/ea/image.rb +12 -0
  290. data/lib/ea/lint/engine.rb +30 -0
  291. data/lib/ea/lint/lint_rule.rb +38 -0
  292. data/lib/ea/lint/offense.rb +18 -0
  293. data/lib/ea/lint/rules/cyclic_generalization.rb +62 -0
  294. data/lib/ea/lint/rules/duplicate_name.rb +28 -0
  295. data/lib/ea/lint/rules/missing_stereotype.rb +35 -0
  296. data/lib/ea/lint/rules/naming_convention.rb +44 -0
  297. data/lib/ea/lint/rules/orphan_element.rb +28 -0
  298. data/lib/ea/lint/rules.rb +14 -0
  299. data/lib/ea/lint.rb +13 -0
  300. data/lib/ea/mdg/document.rb +120 -0
  301. data/lib/ea/mdg/loader.rb +118 -0
  302. data/lib/ea/mdg/registry.rb +98 -0
  303. data/lib/ea/mdg/stereotype_alias_registry.rb +77 -0
  304. data/lib/ea/mdg/xml/applies_to.rb +18 -0
  305. data/lib/ea/mdg/xml/apply.rb +18 -0
  306. data/lib/ea/mdg/xml/content.rb +18 -0
  307. data/lib/ea/mdg/xml/documentation.rb +24 -0
  308. data/lib/ea/mdg/xml/stereotype.rb +28 -0
  309. data/lib/ea/mdg/xml/stereotypes.rb +18 -0
  310. data/lib/ea/mdg/xml/tag.rb +28 -0
  311. data/lib/ea/mdg/xml/tagged_values.rb +18 -0
  312. data/lib/ea/mdg/xml/technology.rb +28 -0
  313. data/lib/ea/mdg/xml/uml_profile.rb +22 -0
  314. data/lib/ea/mdg/xml/uml_profiles.rb +18 -0
  315. data/lib/ea/mdg/xml.rb +24 -0
  316. data/lib/ea/mdg.rb +25 -0
  317. data/lib/ea/model/classifier.rb +4 -0
  318. data/lib/ea/model/constraint.rb +24 -0
  319. data/lib/ea/model/diagram.rb +85 -0
  320. data/lib/ea/model/diagram_connector.rb +34 -0
  321. data/lib/ea/model/diagram_element.rb +16 -0
  322. data/lib/ea/model/document.rb +47 -2
  323. data/lib/ea/model/ghost_label.rb +32 -0
  324. data/lib/ea/model/instance_specification.rb +34 -0
  325. data/lib/ea/model/legend.rb +43 -0
  326. data/lib/ea/model/legend_item.rb +26 -0
  327. data/lib/ea/model/note.rb +28 -0
  328. data/lib/ea/model/operation.rb +2 -0
  329. data/lib/ea/model/property.rb +2 -0
  330. data/lib/ea/model/relationship.rb +2 -0
  331. data/lib/ea/model/signal.rb +14 -0
  332. data/lib/ea/model/slot.rb +19 -0
  333. data/lib/ea/model.rb +8 -0
  334. data/lib/ea/ocl/evaluator.rb +94 -0
  335. data/lib/ea/ocl/nodes.rb +30 -0
  336. data/lib/ea/ocl/parser.rb +133 -0
  337. data/lib/ea/ocl/unsupported_error.rb +7 -0
  338. data/lib/ea/ocl.rb +13 -0
  339. data/lib/ea/qea/factory/document_builder.rb +24 -10
  340. data/lib/ea/qea/factory/generalization_builder.rb +9 -11
  341. data/lib/ea/qea/infrastructure/table_reader.rb +9 -0
  342. data/lib/ea/qea/models/ea_author.rb +35 -0
  343. data/lib/ea/qea/models/ea_glossary.rb +34 -0
  344. data/lib/ea/qea/models/ea_image.rb +53 -0
  345. data/lib/ea/qea/models/ea_implement.rb +32 -0
  346. data/lib/ea/qea/models/ea_list.rb +42 -0
  347. data/lib/ea/qea/models/ea_object_effort.rb +34 -0
  348. data/lib/ea/qea/models/ea_object_problem.rb +37 -0
  349. data/lib/ea/qea/models/ea_object_require.rb +34 -0
  350. data/lib/ea/qea/models/ea_object_resource.rb +34 -0
  351. data/lib/ea/qea/models/ea_object_risk.rb +34 -0
  352. data/lib/ea/qea/models/ea_object_scenario.rb +34 -0
  353. data/lib/ea/qea/models/ea_object_test.rb +35 -0
  354. data/lib/ea/qea/models/ea_object_trx.rb +34 -0
  355. data/lib/ea/qea/models/ea_operation.rb +7 -0
  356. data/lib/ea/qea/models/ea_palette.rb +30 -0
  357. data/lib/ea/qea/models/ea_palette_item.rb +36 -0
  358. data/lib/ea/qea/models/ea_phase.rb +40 -0
  359. data/lib/ea/qea/models/ea_role_constraint.rb +32 -0
  360. data/lib/ea/qea/models/ea_secrypt.rb +34 -0
  361. data/lib/ea/qea/models/ea_version.rb +39 -0
  362. data/lib/ea/qea/models/ea_xref.rb +11 -1
  363. data/lib/ea/qea/models.rb +19 -0
  364. data/lib/ea/qea/services/database_loader.rb +22 -1
  365. data/lib/ea/query/builder.rb +108 -0
  366. data/lib/ea/query.rb +9 -0
  367. data/lib/ea/render/image_converter.rb +101 -0
  368. data/lib/ea/render.rb +10 -0
  369. data/lib/ea/shapescript/parser.rb +208 -0
  370. data/lib/ea/shapescript/renderer.rb +74 -0
  371. data/lib/ea/shapescript/shape.rb +34 -0
  372. data/lib/ea/shapescript.rb +24 -0
  373. data/lib/ea/sources/qea/adapter.rb +22 -5
  374. data/lib/ea/sources/qea/classifier_builder.rb +184 -7
  375. data/lib/ea/sources/qea/diagram_builder.rb +352 -24
  376. data/lib/ea/sources/qea/id_normalizer.rb +16 -1
  377. data/lib/ea/sources/qea/instance_builder.rb +113 -0
  378. data/lib/ea/sources/qea/legend_builder.rb +137 -0
  379. data/lib/ea/sources/qea/note_builder.rb +58 -0
  380. data/lib/ea/sources/qea/object_classifier_map.rb +6 -1
  381. data/lib/ea/sources/qea/operation_builder.rb +1 -0
  382. data/lib/ea/sources/qea/package_builder.rb +16 -0
  383. data/lib/ea/sources/qea/relationship_builder.rb +21 -5
  384. data/lib/ea/sources/qea/tagged_value_builder.rb +28 -9
  385. data/lib/ea/sources/qea/xref/legend_definition.rb +35 -0
  386. data/lib/ea/sources/qea/xref/parser.rb +150 -0
  387. data/lib/ea/sources/qea/xref/property_definition.rb +29 -0
  388. data/lib/ea/sources/qea/xref/record.rb +41 -0
  389. data/lib/ea/sources/qea/xref/stereotype_application.rb +37 -0
  390. data/lib/ea/sources/qea/xref.rb +27 -0
  391. data/lib/ea/sources/qea.rb +4 -0
  392. data/lib/ea/sources/xmi/adapter.rb +80 -2
  393. data/lib/ea/sources/xmi/classifier_builder.rb +10 -1
  394. data/lib/ea/sources/xmi/diagram_builder.rb +95 -18
  395. data/lib/ea/sources/xmi/extension_geometry_parser.rb +19 -2
  396. data/lib/ea/sources/xmi/extension_style_parser.rb +15 -2
  397. data/lib/ea/sources/xmi/note_builder.rb +46 -0
  398. data/lib/ea/sources/xmi/property_builder.rb +9 -0
  399. data/lib/ea/sources/xmi/stereotype_builder.rb +54 -0
  400. data/lib/ea/sources/xmi/tag_builder.rb +45 -0
  401. data/lib/ea/sources/xmi/umldi_keyword_extractor.rb +87 -0
  402. data/lib/ea/sources/xmi.rb +4 -0
  403. data/lib/ea/spa/output/sharded_multi_file_strategy.rb +18 -3
  404. data/lib/ea/spa/output/single_file_strategy.rb +8 -2
  405. data/lib/ea/spa/output/strategy.rb +34 -0
  406. data/lib/ea/svg/connector_router.rb +134 -0
  407. data/lib/ea/svg/ea_emitter/background.rb +2 -3
  408. data/lib/ea/svg/ea_emitter/bounds_calculator.rb +142 -0
  409. data/lib/ea/svg/ea_emitter/canvas.rb +56 -33
  410. data/lib/ea/svg/ea_emitter/color_resolver.rb +56 -0
  411. data/lib/ea/svg/ea_emitter/compartment/attributes.rb +28 -0
  412. data/lib/ea/svg/ea_emitter/compartment/constraints.rb +30 -0
  413. data/lib/ea/svg/ea_emitter/compartment/enum_literals.rb +86 -0
  414. data/lib/ea/svg/ea_emitter/compartment/header.rb +32 -0
  415. data/lib/ea/svg/ea_emitter/compartment/header_divider.rb +57 -0
  416. data/lib/ea/svg/ea_emitter/compartment/instance_slots.rb +96 -0
  417. data/lib/ea/svg/ea_emitter/compartment/instance_underline.rb +67 -0
  418. data/lib/ea/svg/ea_emitter/compartment/note_body.rb +52 -0
  419. data/lib/ea/svg/ea_emitter/compartment/note_text.rb +102 -0
  420. data/lib/ea/svg/ea_emitter/compartment/operations.rb +38 -0
  421. data/lib/ea/svg/ea_emitter/compartment/package_contents.rb +72 -0
  422. data/lib/ea/svg/ea_emitter/compartment/package_from_parent.rb +136 -0
  423. data/lib/ea/svg/ea_emitter/compartment/shape.rb +82 -0
  424. data/lib/ea/svg/ea_emitter/compartment/tagged_values.rb +30 -0
  425. data/lib/ea/svg/ea_emitter/compartment.rb +58 -0
  426. data/lib/ea/svg/ea_emitter/connectors.rb +46 -12
  427. data/lib/ea/svg/ea_emitter/diagram_frame.rb +143 -0
  428. data/lib/ea/svg/ea_emitter/document.rb +15 -24
  429. data/lib/ea/svg/ea_emitter/element/attribute_line_builder.rb +117 -0
  430. data/lib/ea/svg/ea_emitter/element/attribute_renderer.rb +119 -0
  431. data/lib/ea/svg/ea_emitter/element/bcol_decoder.rb +29 -0
  432. data/lib/ea/svg/ea_emitter/element/compartment_geometry.rb +113 -0
  433. data/lib/ea/svg/ea_emitter/element/constraint_renderer.rb +53 -0
  434. data/lib/ea/svg/ea_emitter/element/divider_renderer.rb +17 -0
  435. data/lib/ea/svg/ea_emitter/element/enumeration_literal_renderer.rb +34 -0
  436. data/lib/ea/svg/ea_emitter/element/filter.rb +44 -0
  437. data/lib/ea/svg/ea_emitter/element/hand_draw_shape_renderer.rb +77 -0
  438. data/lib/ea/svg/ea_emitter/element/header_line_pipeline.rb +43 -0
  439. data/lib/ea/svg/ea_emitter/element/header_line_provider/instance_spec.rb +27 -0
  440. data/lib/ea/svg/ea_emitter/element/header_line_provider/name.rb +76 -0
  441. data/lib/ea/svg/ea_emitter/element/header_line_provider/parent_ghost.rb +25 -0
  442. data/lib/ea/svg/ea_emitter/element/header_line_provider/stereotype_label.rb +68 -0
  443. data/lib/ea/svg/ea_emitter/element/header_line_provider.rb +19 -0
  444. data/lib/ea/svg/ea_emitter/element/header_lines.rb +27 -0
  445. data/lib/ea/svg/ea_emitter/element/header_renderer.rb +48 -0
  446. data/lib/ea/svg/ea_emitter/element/icon_renderer.rb +109 -0
  447. data/lib/ea/svg/ea_emitter/element/legend_renderer.rb +177 -0
  448. data/lib/ea/svg/ea_emitter/element/note_shape_renderer.rb +112 -0
  449. data/lib/ea/svg/ea_emitter/element/operation_renderer.rb +100 -0
  450. data/lib/ea/svg/ea_emitter/element/package_shape_renderer.rb +181 -0
  451. data/lib/ea/svg/ea_emitter/element/row_icon_renderer.rb +156 -0
  452. data/lib/ea/svg/ea_emitter/element/shape_renderer.rb +17 -0
  453. data/lib/ea/svg/ea_emitter/element/stereotype_icon_renderer.rb +82 -0
  454. data/lib/ea/svg/ea_emitter/element/tagged_value_renderer.rb +50 -0
  455. data/lib/ea/svg/ea_emitter/element/text_escape.rb +20 -0
  456. data/lib/ea/svg/ea_emitter/element.rb +37 -0
  457. data/lib/ea/svg/ea_emitter/elements.rb +283 -95
  458. data/lib/ea/svg/ea_emitter/font_resolver.rb +111 -0
  459. data/lib/ea/svg/ea_emitter/ghost_labels.rb +66 -0
  460. data/lib/ea/svg/ea_emitter/label/end_label.rb +266 -0
  461. data/lib/ea/svg/ea_emitter/label/midpoint_label.rb +101 -0
  462. data/lib/ea/svg/ea_emitter/label/registry.rb +50 -0
  463. data/lib/ea/svg/ea_emitter/label.rb +23 -0
  464. data/lib/ea/svg/ea_emitter/labels.rb +93 -27
  465. data/lib/ea/svg/ea_emitter/layer.rb +20 -0
  466. data/lib/ea/svg/ea_emitter/layer_sequencer.rb +93 -0
  467. data/lib/ea/svg/ea_emitter/marker/arrow_path.rb +52 -0
  468. data/lib/ea/svg/ea_emitter/marker/diamond.rb +57 -0
  469. data/lib/ea/svg/ea_emitter/marker/kind.rb +35 -0
  470. data/lib/ea/svg/ea_emitter/marker/open_triangle.rb +27 -0
  471. data/lib/ea/svg/ea_emitter/marker/package_import.rb +39 -0
  472. data/lib/ea/svg/ea_emitter/marker/plus.rb +40 -0
  473. data/lib/ea/svg/ea_emitter/marker/registry.rb +42 -0
  474. data/lib/ea/svg/ea_emitter/marker.rb +37 -0
  475. data/lib/ea/svg/ea_emitter/markers.rb +351 -64
  476. data/lib/ea/svg/ea_emitter/render_context.rb +52 -0
  477. data/lib/ea/svg/ea_emitter/style.rb +15 -0
  478. data/lib/ea/svg/ea_emitter/text_renderer.rb +92 -0
  479. data/lib/ea/svg/ea_emitter.rb +33 -11
  480. data/lib/ea/svg/parity/checker.rb +105 -0
  481. data/lib/ea/svg/parity/source.rb +59 -0
  482. data/lib/ea/svg/parity/suite.rb +113 -0
  483. data/lib/ea/svg/parity.rb +14 -0
  484. data/lib/ea/svg.rb +2 -15
  485. data/lib/ea/theme/definition.rb +176 -0
  486. data/lib/ea/theme/loader.rb +125 -0
  487. data/lib/ea/theme/registry.rb +96 -0
  488. data/lib/ea/theme.rb +37 -0
  489. data/lib/ea/transformations.rb +5 -88
  490. data/lib/ea/version.rb +4 -1
  491. data/lib/ea.rb +14 -4
  492. data/lib/tasks/svg_bench.rake +87 -0
  493. data/lutaml-uml-0.5.1.gem +0 -0
  494. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-1-themes-list.png +0 -0
  495. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-1-themes.png +0 -0
  496. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-2-gradients.png +0 -0
  497. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-3-colors.png +0 -0
  498. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-4-appearance-fonts.png +0 -0
  499. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-4-appearance.png +0 -0
  500. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-5-behavior.png +0 -0
  501. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-6-sequence.png +0 -0
  502. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram.png +0 -0
  503. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-2-objects.png +0 -0
  504. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-3-links.png +0 -0
  505. metadata +449 -26
  506. data/lib/ea/diagram/configuration.rb +0 -379
  507. data/lib/ea/diagram/element_renderers/base_renderer.rb +0 -77
  508. data/lib/ea/diagram/element_renderers/class_renderer.rb +0 -323
  509. data/lib/ea/diagram/element_renderers/connector_renderer.rb +0 -41
  510. data/lib/ea/diagram/element_renderers/package_renderer.rb +0 -61
  511. data/lib/ea/diagram/element_renderers.rb +0 -43
  512. data/lib/ea/diagram/extractor.rb +0 -566
  513. data/lib/ea/diagram/layout_engine.rb +0 -170
  514. data/lib/ea/diagram/path_builder.rb +0 -202
  515. data/lib/ea/diagram/style_parser.rb +0 -42
  516. data/lib/ea/diagram/style_resolver.rb +0 -291
  517. data/lib/ea/diagram/svg_renderer.rb +0 -274
  518. data/lib/ea/diagram/util.rb +0 -73
  519. data/lib/ea/svg/bounds_calculator.rb +0 -74
  520. data/lib/ea/svg/connector_path.rb +0 -138
  521. data/lib/ea/svg/element_box.rb +0 -256
  522. data/lib/ea/svg/renderer.rb +0 -77
  523. data/lib/ea/svg/style_resolver.rb +0 -72
  524. data/lib/ea/transformations/configuration.rb +0 -333
  525. data/lib/ea/transformations/format_registry.rb +0 -366
  526. data/lib/ea/transformations/parsers/base_parser.rb +0 -482
  527. data/lib/ea/transformations/parsers/qea_parser.rb +0 -401
  528. data/lib/ea/transformations/parsers/xmi_parser.rb +0 -243
  529. data/lib/ea/transformations/transformation_engine.rb +0 -390
@@ -0,0 +1,56 @@
1
+ # 14 - EA.exe Reverse-Engineering Notes
2
+
3
+ ## Status: DONE (informational)
4
+
5
+ ## Location
6
+
7
+ EA.exe and supporting DLLs are installed at:
8
+
9
+ ~/Library/Application Support/CrossOver/Bottles/Enterprise Architect 16.x/drive_c/Program Files/Sparx Systems/EA/
10
+
11
+ Key files:
12
+ - `EA.exe` — main PE32 Windows binary, ~? MB
13
+ - `DrawEx161-32.dll` — drawing extension (CDrawEx class with
14
+ Bezier/FillPath/StrokePath/etc.)
15
+ - `SSXML161-32.dll` — XML processing
16
+ - `EALayout161-32.dll` — layout engine
17
+ - `Cairo161-32.dll` — Cairo graphics bindings
18
+ - `Scintilla161-32.dll` — code editor
19
+
20
+ ## What's discoverable
21
+
22
+ Symbols found in EA.exe (via `strings`):
23
+
24
+ - `SVGRenderer.cpp` — the C++ source file implementing SVG output
25
+ - `CBCGPSVG*` — BCGSoft SVG library classes (Base, Rect, Ellipse,
26
+ Line, Text, Polygon, Path, Group, ClipPath, Gradient, Mask,
27
+ ViewBox, Symbol, Marker)
28
+
29
+ The BCGSoft library is a commercial MFC extension. EA's SVG output
30
+ is built on top of `CBCGPSVG` and `CDrawEx` (a custom drawing
31
+ abstraction with both GDI and SVG backends).
32
+
33
+ ## What's NOT discoverable without disassembly
34
+
35
+ - Exact style string assembly logic
36
+ - Coordinate transformation math
37
+ - Style bucketing rules (which paths share a `<g>`)
38
+ - Marker shape selection per relationship kind
39
+
40
+ These are constructed dynamically from many small format strings
41
+ at runtime. EA's diagram SVG output uses `printf`-style formatting
42
+ with the format templates assembled by C++ code from many
43
+ fragments — not stored as literal strings in the binary.
44
+
45
+ ## Implication for parity work
46
+
47
+ Without source code or disassembly tools (Ghidra, IDA Pro), the
48
+ only practical path to closing remaining parity gaps is:
49
+
50
+ 1. Empirically derive rules from reference SVGs (current approach)
51
+ 2. Test against many diagrams to find consistent patterns
52
+ 3. Accept residual ~5-10% diff as uncloseable without binary RE
53
+
54
+ The `Ea::Svg::ParityChecker` (fixup 08) is the right tool for
55
+ empirical validation — it surfaces exactly which dimensions
56
+ diverge so we can target them.
@@ -0,0 +1,30 @@
1
+ # 15 - Enumeration Literal Rendering
2
+
3
+ ## Status: DONE (2026-07-25)
4
+
5
+ ## Outcome
6
+
7
+ New `Element::EnumerationLiteralRenderer` emits a literal
8
+ compartment below the attribute compartment for Enumeration
9
+ classifiers. Layout:
10
+
11
+ ```
12
+ ┌────────────────────┐
13
+ │ «enumeration» │ header
14
+ │ EnumName │
15
+ ├────────────────────┤
16
+ │ + attr: Type │ attributes (if any)
17
+ ├────────────────────┤
18
+ │ literal1 │ literal compartment
19
+ │ literal2 │
20
+ └────────────────────┘
21
+ ```
22
+
23
+ `CompartmentGeometry` extended with `attr_lines_count`,
24
+ `enum_divider_y`, `enum_literal_first_y`.
25
+
26
+ ## Files changed
27
+
28
+ - `lib/ea/svg/ea_emitter/element/enumeration_literal_renderer.rb` — NEW
29
+ - `lib/ea/svg/ea_emitter/element.rb` — autoload
30
+ - `lib/ea/svg/ea_emitter/elements.rb` — invoke renderer, extend geometry
@@ -0,0 +1,42 @@
1
+ # 16 - Operation Compartment Rendering
2
+
3
+ ## Status: DONE (2026-07-25)
4
+
5
+ ## Outcome
6
+
7
+ New `Element::OperationRenderer` emits operations as a third
8
+ compartment below attributes (when classifier has operations).
9
+ Layout:
10
+
11
+ ```
12
+ ┌────────────────────┐
13
+ │ «DataType» │ header
14
+ │ ClassName │
15
+ ├────────────────────┤
16
+ │ + attr: Type │ attributes
17
+ ├────────────────────┤
18
+ │ + method1() │ operations
19
+ │ + method2(): Type │
20
+ ├────────────────────┤
21
+ │ literal1 │ enum literals (if Enumeration)
22
+ └────────────────────┘
23
+ ```
24
+
25
+ Each operation emits as TWO `<text>` elements (visibility + content)
26
+ matching EA's attribute encoding. Operation signature format:
27
+ `+ name(params): ReturnType`.
28
+
29
+ `CompartmentGeometry` extended with `op_divider_y`, `op_first_y`,
30
+ `op_bottom_y` and adjusted `enum_divider_y` to follow op compartment.
31
+
32
+ ## Note
33
+
34
+ In the current plateau XMI dataset, no classifiers have operations
35
+ (0/599). The renderer is implemented for completeness — future
36
+ XMI imports with operation data will render correctly.
37
+
38
+ ## Files changed
39
+
40
+ - `lib/ea/svg/ea_emitter/element/operation_renderer.rb` — NEW
41
+ - `lib/ea/svg/ea_emitter/element.rb` — autoload
42
+ - `lib/ea/svg/ea_emitter/elements.rb` — invoke renderer, extend geometry
@@ -0,0 +1,27 @@
1
+ # 17 - Path Count Calibration
2
+
3
+ ## Status: DONE (2026-07-25)
4
+
5
+ ## Outcome
6
+
7
+ Removed navigability arrow emission from aggregations. EA's
8
+ diagrams do NOT render an arrow at the part end of aggregations
9
+ — the diamond already conveys direction.
10
+
11
+ Updated `Marker::Diamond` to emit only ONE spec (the diamond),
12
+ not two (diamond + arrow). Updated spec accordingly.
13
+
14
+ ## Outcome metrics
15
+
16
+ Path count within ±2: 49% → 49% (no aggregate change since path
17
+ diffs come from other sources too).
18
+
19
+ Bridge: 140 → 127 paths (ref=113, was +27, now +14).
20
+ Building: 112 → 102 (ref=96, was +16, now +6).
21
+
22
+ Significant reduction on individual diagrams.
23
+
24
+ ## Files changed
25
+
26
+ - `lib/ea/svg/ea_emitter/marker/diamond.rb` — single spec only
27
+ - `spec/ea/svg/ea_emitter/marker/registry_spec.rb` — updated expectation
@@ -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.