ea 0.6.61 → 0.6.63
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/lib/ea/fonts/metrics.rb +30 -3
- data/lib/ea/svg/ea_emitter/elements.rb +76 -3
- data/lib/ea/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e6f6d084b7fd0042b8f31d006ed91d5fbc00c18d82937cd1ee5f5b6a6a8e2340
|
|
4
|
+
data.tar.gz: 6a93141b935afeac3c9409e933795100d5207a4ce532c3634906a174b7ce8c6e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f4ff485fff168ca3d18ee168d1fa8f3c2acc168d8eb748cedd17c356b98ff8b9abea4b03432c5d3643c956025f358e25a7783cd24806e4e20f494df914992851
|
|
7
|
+
data.tar.gz: 9351c617930b3c3c54e74b98dc7da68ec8fe12d2031daf28cf0e0a99d0ca7c35f20fc49e85ca726634f9d7c86003b201f3dd808d00d5bc3ed1e7a0e8bc31a96d
|
data/lib/ea/fonts/metrics.rb
CHANGED
|
@@ -53,16 +53,43 @@ module Ea
|
|
|
53
53
|
|
|
54
54
|
# Width of `text` in EA's exported SVG units for the given pt
|
|
55
55
|
# size, or nil when the family is not metric-compatible.
|
|
56
|
+
#
|
|
57
|
+
# EA's GDI driver quantizes each glyph advance to an integer
|
|
58
|
+
# pixel count at the logical font height H = round(pt * 10/7)
|
|
59
|
+
# (Carlito: 7pt -> H10, 9pt -> H13) and the published
|
|
60
|
+
# textLength is the SUM of those per-glyph integers - corpus
|
|
61
|
+
# fitted to 97-100% exact on 10k Carlito texts (bold 7pt
|
|
62
|
+
# 1666/1671). The legacy sum-then-round model matched only 27%.
|
|
56
63
|
def text_length(text, size_pt, family: nil, weight: nil, style: nil)
|
|
57
64
|
return nil unless supported_family?(family)
|
|
58
65
|
return nil if text.nil? || text.empty?
|
|
59
66
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
67
|
+
resolved = resolve_family(family)
|
|
68
|
+
if GDI_HEIGHT_FAMILIES.include?(resolved)
|
|
69
|
+
height = (size_pt.to_f * 10 / 7).round
|
|
70
|
+
table = table_for(family, weight, style)
|
|
71
|
+
latin = 0
|
|
72
|
+
cjk_count = 0
|
|
73
|
+
text.each_char do |ch|
|
|
74
|
+
if cjk?(ch.ord)
|
|
75
|
+
cjk_count += 1
|
|
76
|
+
else
|
|
77
|
+
latin += ((table[cp_key(ch)] || DEFAULT_ADVANCE) * height).round
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
return latin + cjk_count * CJK_ADVANCE * size_pt.to_f
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
_latin, cjk_count = split_advance(text, family: family,
|
|
84
|
+
weight: weight, style: style)
|
|
85
|
+
(_latin * size_pt.to_f * factor_for(family, size_pt, weight, style) +
|
|
63
86
|
cjk_count * CJK_ADVANCE * size_pt.to_f).round(3)
|
|
64
87
|
end
|
|
65
88
|
|
|
89
|
+
# Families whose EA driver quantizes per-glyph advances
|
|
90
|
+
# (fitted from published textLengths).
|
|
91
|
+
GDI_HEIGHT_FAMILIES = %w[Carlito].freeze
|
|
92
|
+
|
|
66
93
|
def supported_family?(family)
|
|
67
94
|
!resolve_family(family).nil?
|
|
68
95
|
end
|
|
@@ -128,6 +128,29 @@ module Ea
|
|
|
128
128
|
off_canvas_parent_name: parent_name,
|
|
129
129
|
foreign_package_name: foreign_package_name_for(classifier),
|
|
130
130
|
suppress_stereotypes: suppress_stereotypes?) : []
|
|
131
|
+
# Regenerated contexts (SuppressFOC=0) re-size EVERY box to
|
|
132
|
+
# fit ALL content (7F10BFBD: Set enum box stored 70x59 ->
|
|
133
|
+
# EA 165x223 with all six literals unwrapped): width =
|
|
134
|
+
# max(stored, title + pad_t, widest row + 8), height likewise
|
|
135
|
+
# grows via the standard content growth. Frozen contexts
|
|
136
|
+
# (SuppressFOC=1) keep stored sizes and wrap.
|
|
137
|
+
if regenerated_context? && classifier.is_a?(Ea::Model::Classifier) &&
|
|
138
|
+
!classifier.is_a?(Ea::Model::Package)
|
|
139
|
+
preview_lines = []
|
|
140
|
+
if show_attributes? && attributes_visible?(element) &&
|
|
141
|
+
!classifier.is_a?(Ea::Model::Interface)
|
|
142
|
+
preview_lines += Element::AttributeRenderer.lines_for(
|
|
143
|
+
classifier, lookup: attribute_lookup,
|
|
144
|
+
exclude_association_ids: drawn_association_ids
|
|
145
|
+
)
|
|
146
|
+
end
|
|
147
|
+
if show_operations? && operations_visible?(element)
|
|
148
|
+
preview_lines += Element::OperationRenderer.lines_for(classifier)
|
|
149
|
+
end
|
|
150
|
+
bounds = context_resized_bounds(bounds, classifier, size, family,
|
|
151
|
+
preview_lines)
|
|
152
|
+
end
|
|
153
|
+
|
|
131
154
|
is_classifier = classifier.is_a?(Ea::Model::Classifier)
|
|
132
155
|
# Interfaces DO render attribute compartments when they own
|
|
133
156
|
# attribute rows (936AA434/Surface lists its nine 19107
|
|
@@ -143,6 +166,7 @@ module Ea
|
|
|
143
166
|
[]
|
|
144
167
|
end
|
|
145
168
|
op_lines = if is_classifier && show_operations? && operations_visible?(element)
|
|
169
|
+
$stderr.puts "DBG ops: show=#{show_operations?} vis=#{operations_visible?(element)} cls=#{classifier.class} nops=#{classifier.operations.to_a.size}"
|
|
146
170
|
Element::OperationRenderer.lines_for(classifier)
|
|
147
171
|
else
|
|
148
172
|
[]
|
|
@@ -177,8 +201,24 @@ module Ea
|
|
|
177
201
|
enum_literals_count: enum_row_count_for(classifier))
|
|
178
202
|
end
|
|
179
203
|
# EA suppresses the operations compartment when its rows
|
|
180
|
-
# overflow the stored box height (same rule as attributes)
|
|
181
|
-
|
|
204
|
+
# overflow the stored box height (same rule as attributes)
|
|
205
|
+
# - EXCEPT on regenerated contexts, where EA GROWS the box
|
|
206
|
+
# to fit every row instead (7F10BFBD: Set stored 70x59 ->
|
|
207
|
+
# drawn 165x223 with all twelve operations).
|
|
208
|
+
if regenerated_context? && op_lines.any? && geometry.op_first_y &&
|
|
209
|
+
geometry.op_bottom_y.to_i > bounds.y + bounds.height
|
|
210
|
+
bounds = Ea::Model::Bounds.new(
|
|
211
|
+
x: bounds.x, y: bounds.y,
|
|
212
|
+
width: bounds.width,
|
|
213
|
+
height: geometry.op_bottom_y.to_i + 8 - bounds.y
|
|
214
|
+
)
|
|
215
|
+
geometry = compartment_geometry(bounds, size, attr_lines, op_lines,
|
|
216
|
+
tagged_values_for(classifier).size,
|
|
217
|
+
header_lines, classifier: classifier,
|
|
218
|
+
constraints_count: constraints_for(classifier).size,
|
|
219
|
+
marker_count: marker_lines_for(classifier).size,
|
|
220
|
+
enum_literals_count: enum_row_count_for(classifier))
|
|
221
|
+
elsif op_lines.any? && geometry.op_first_y &&
|
|
182
222
|
geometry.op_bottom_y.to_i > bounds.y + bounds.height
|
|
183
223
|
op_lines = []
|
|
184
224
|
geometry = compartment_geometry(bounds, size, attr_lines, op_lines,
|
|
@@ -198,7 +238,12 @@ module Ea
|
|
|
198
238
|
# position even with zero operations), so it must stay out
|
|
199
239
|
# of the max.
|
|
200
240
|
grown_bottom = geometry.content_bottom_y.to_i
|
|
201
|
-
|
|
241
|
+
# Enum literals grow the box too (7F10BFBD 'Context Diagram:
|
|
242
|
+
# Bag': Set enum box stored h59 -> EA 223 fitting six
|
|
243
|
+
# literals); op-only boxes keep the no-growth behavior
|
|
244
|
+
# (op_bottom_y is a divider sentinel, not content).
|
|
245
|
+
if (attr_lines.any? || enum_literals_for(classifier).any?) &&
|
|
246
|
+
grown_bottom.positive? &&
|
|
202
247
|
grown_bottom + 8 > bounds.y + bounds.height
|
|
203
248
|
bounds = Ea::Model::Bounds.new(
|
|
204
249
|
x: bounds.x, y: bounds.y,
|
|
@@ -419,6 +464,34 @@ module Ea
|
|
|
419
464
|
# classifier lives in a different package than the diagram
|
|
420
465
|
# (descendant packages included). Corpus-verified (450
|
|
421
466
|
# diagrams): ShowForeign=0 renders plain everywhere.
|
|
467
|
+
def regenerated_context?
|
|
468
|
+
diagram.name.to_s.downcase.start_with?("context diagram") &&
|
|
469
|
+
diagram.style_ex.to_s !~ /SuppressFOC=1/
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
TITLE_PAD = 18
|
|
473
|
+
|
|
474
|
+
def context_resized_bounds(bounds, classifier, size, family, rows)
|
|
475
|
+
label = classifier.name.to_s
|
|
476
|
+
pkg = foreign_package_name_for(classifier)
|
|
477
|
+
label = "#{pkg}::#{label}" if pkg
|
|
478
|
+
title_w = TextRenderer.estimate_width(
|
|
479
|
+
label, size, nil, family: family, weight: "700"
|
|
480
|
+
).round
|
|
481
|
+
pad = title_w.odd? ? TITLE_PAD : 16
|
|
482
|
+
row_w = rows.map do |line|
|
|
483
|
+
line = line.sub(/\A«[^»]*»\z/, "")
|
|
484
|
+
TextRenderer.estimate_width(
|
|
485
|
+
line, size, nil, family: family, weight: "400"
|
|
486
|
+
).round + 8
|
|
487
|
+
end.max.to_i
|
|
488
|
+
needed = [bounds.width, title_w + pad, row_w].max
|
|
489
|
+
return bounds if needed <= bounds.width
|
|
490
|
+
|
|
491
|
+
Ea::Model::Bounds.new(x: bounds.x, y: bounds.y,
|
|
492
|
+
width: needed, height: bounds.height)
|
|
493
|
+
end
|
|
494
|
+
|
|
422
495
|
def foreign_package_name_for(classifier)
|
|
423
496
|
return nil unless diagram.show_foreign
|
|
424
497
|
return nil unless classifier.is_a?(Ea::Model::Classifier)
|
data/lib/ea/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ea
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.6.
|
|
4
|
+
version: 0.6.63
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-10-
|
|
11
|
+
date: 2026-10-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: lutaml-model
|