ea 0.6.107 → 0.6.108

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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/config/themes/119.yml +3 -2
  3. data/lib/ea/fonts/cambria_7_styled_widths.json +293 -0
  4. data/lib/ea/fonts/metrics.rb +50 -7
  5. data/lib/ea/model/diagram_element.rb +4 -0
  6. data/lib/ea/sources/qea/diagram_builder/auto_routing.rb +124 -11
  7. data/lib/ea/sources/qea/diagram_builder/font_settings.rb +50 -0
  8. data/lib/ea/sources/qea/diagram_builder/routing.rb +82 -82
  9. data/lib/ea/sources/qea/diagram_builder.rb +8 -30
  10. data/lib/ea/sources/qea/instance_builder.rb +1 -0
  11. data/lib/ea/svg/ea_emitter/color_resolver.rb +1 -2
  12. data/lib/ea/svg/ea_emitter/compartment/attributes.rb +2 -1
  13. data/lib/ea/svg/ea_emitter/compartment/enum_literals.rb +11 -5
  14. data/lib/ea/svg/ea_emitter/compartment/header.rb +2 -1
  15. data/lib/ea/svg/ea_emitter/compartment/note_body.rb +6 -4
  16. data/lib/ea/svg/ea_emitter/compartment/note_html.rb +66 -0
  17. data/lib/ea/svg/ea_emitter/compartment/operations.rb +2 -1
  18. data/lib/ea/svg/ea_emitter/compartment.rb +1 -0
  19. data/lib/ea/svg/ea_emitter/connector_redock.rb +30 -14
  20. data/lib/ea/svg/ea_emitter/element/attribute_line_builder.rb +11 -9
  21. data/lib/ea/svg/ea_emitter/element/attribute_renderer.rb +24 -8
  22. data/lib/ea/svg/ea_emitter/element/compartment_geometry.rb +18 -7
  23. data/lib/ea/svg/ea_emitter/element/constraint_renderer.rb +9 -5
  24. data/lib/ea/svg/ea_emitter/element/enumeration_literal_renderer.rb +8 -5
  25. data/lib/ea/svg/ea_emitter/element/header_line_pipeline.rb +3 -2
  26. data/lib/ea/svg/ea_emitter/element/header_line_provider/instance_spec.rb +10 -5
  27. data/lib/ea/svg/ea_emitter/element/header_line_provider/name.rb +2 -1
  28. data/lib/ea/svg/ea_emitter/element/header_renderer.rb +14 -12
  29. data/lib/ea/svg/ea_emitter/element/operation_renderer.rb +10 -7
  30. data/lib/ea/svg/ea_emitter/elements.rb +39 -32
  31. data/lib/ea/svg/ea_emitter/font_resolver.rb +14 -4
  32. data/lib/ea/svg/ea_emitter/ghost_labels.rb +3 -0
  33. data/lib/ea/svg/ea_emitter/label/end_label.rb +37 -4
  34. data/lib/ea/svg/ea_emitter/labels.rb +12 -4
  35. data/lib/ea/svg/ea_emitter/render_context.rb +1 -1
  36. data/lib/ea/svg/ea_emitter/text_renderer.rb +6 -5
  37. data/lib/ea/theme/definition.rb +5 -2
  38. data/lib/ea/theme/loader.rb +3 -2
  39. data/lib/ea/version.rb +1 -1
  40. metadata +4 -1
@@ -78,6 +78,7 @@ module Ea
78
78
  if tree && zero_offset?(text_box, mult_box)
79
79
  text_pos, mult_pos = tree_positions(end_kind, anchor, role,
80
80
  text_pos, mult_pos)
81
+ mult_pos = tree_left_multiplicity(end_kind, heading, anchor, mult_box, mult) || mult_pos
81
82
  elsif mult_box && stored_offsets_zero?(mult_box)
82
83
  # Start at the legacy default; measured directional seats
83
84
  # below replace it for default Cambria labels.
@@ -94,12 +95,14 @@ module Ea
94
95
  source_property_seat(connector, direction, anchor, text_box, role) ||
95
96
  plain_upward_seat(connector, direction, anchor, text_box, role) ||
96
97
  role_seat(direction, anchor, text_box, role) || text_pos
97
- mult_pos = directional_multiplicity(connector, direction, anchor, mult_box, mult) ||
98
+ mult_pos = directional_multiplicity(direction, anchor, mult_box, mult) ||
99
+ horizontal_tree_multiplicity(connector, direction, anchor, mult_box, mult) ||
98
100
  mult_seat(direction, anchor, mult_box) || mult_pos
99
101
  elsif end_kind == :target && !(tree && zero_offset?(text_box, mult_box))
100
102
  text_pos = target_vertical_role(connector, heading, anchor, text_box, role) ||
101
103
  target_rightward_role(heading, anchor, text_box, role) || text_pos
102
- mult_pos = target_multiplicity_seat(heading, anchor, mult_box) || mult_pos
104
+ mult_pos = target_multiplicity_seat(heading, anchor, mult_box) ||
105
+ target_horizontal_multiplicity(heading, anchor, mult_box, mult) || mult_pos
103
106
  end
104
107
 
105
108
  build_texts(role:, mult:, standalone:,
@@ -306,17 +309,47 @@ module Ea
306
309
  %w[1 3].include?(style[:mode]) && style[:lwidth] == "2" && !style[:tree]
307
310
  end
308
311
 
309
- def directional_multiplicity(connector, direction, anchor, box, mult)
312
+ def directional_multiplicity(direction, anchor, box, mult)
310
313
  return nil unless cambria_box?(box)
311
314
 
312
315
  x, y = seat_corner(anchor, box)
313
316
  return [x + 8, y + 15] if direction == :down
314
- return nil unless direction == :left && source_property_font?(connector, direction)
317
+ return nil unless direction == :left
315
318
 
316
319
  width = Ea::Fonts::Metrics.text_length(mult, font_size, family: font_family)
317
320
  [x - width - 3, y + 15] if width
318
321
  end
319
322
 
323
+ # On an "H" tree route a property end leaving right seats its
324
+ # multiplicity one text width further right than the plain
325
+ # rightward seat.
326
+ def horizontal_tree_multiplicity(connector, direction, anchor, box, mult)
327
+ return nil unless direction == :right && property_label?(connector, :source)
328
+ return nil unless connector.style.to_h[:tree] == "H" && cambria_box?(box) && !mult_empty?(mult)
329
+
330
+ width = Ea::Fonts::Metrics.text_length(mult, font_size, family: font_family)
331
+ x, y = seat_corner(anchor, box)
332
+ [x + SEAT_X_INSET + width, y + 15] if width
333
+ end
334
+
335
+ # A tree-route source leaving left seats its multiplicity like any
336
+ # other leftward source rather than at the rightward tree default.
337
+ def tree_left_multiplicity(end_kind, heading, anchor, box, mult)
338
+ return nil if end_kind != :source || mult_empty?(mult) || leg_direction(end_kind, heading) != :left
339
+
340
+ directional_multiplicity(:left, anchor, box, mult)
341
+ end
342
+
343
+ # A target whose first leg runs sideways seats its multiplicity at
344
+ # the stored corner like a source leaving the same way.
345
+ def target_horizontal_multiplicity(heading, anchor, box, mult)
346
+ return nil unless seat_font? && heading && heading[1].zero? && !heading[0].zero?
347
+ return nil if mult_empty?(mult)
348
+ return directional_multiplicity(:left, anchor, box, mult) if heading[0].negative?
349
+
350
+ mult_seat(:right, anchor, box)
351
+ end
352
+
320
353
  def target_multiplicity_seat(heading, anchor, box)
321
354
  return nil unless seat_font?
322
355
  return nil unless heading && heading[0].zero? && heading[1].negative?
@@ -84,24 +84,32 @@ module Ea
84
84
  stored_src = end_boxes(boxes, :llt, :llb)
85
85
  stored_tgt = end_boxes(boxes, :lrt, :lrb)
86
86
  stored_labels = !(stored_src.nil? && stored_tgt.nil?)
87
- src_tb, src_mb = stored_src || default_label_boxes(points, :source)
88
- tgt_tb, tgt_mb = stored_tgt || default_label_boxes(points, :target)
87
+ src_tb, src_mb = stored_src || unstored_label_boxes(points, :source, stored_labels)
88
+ tgt_tb, tgt_mb = stored_tgt || unstored_label_boxes(points, :target, stored_labels)
89
89
 
90
90
  texts = []
91
91
  end_renderer.texts(text_box: src_tb, mult_box: src_mb,
92
92
  anchor: source_pt, connector: connector,
93
93
  end_kind: :source, tree: tree && tree[:source],
94
- heading: stored_src && source_heading(connector, points),
94
+ heading: (stored_src || stored_labels) && source_heading(connector, points),
95
95
  stored_labels: stored_labels).each { |t| texts << t }
96
96
  end_renderer.texts(text_box: tgt_tb,
97
97
  mult_box: tgt_mb,
98
98
  anchor: target_pt, connector: connector,
99
99
  end_kind: :target, tree: tree && tree[:target],
100
- heading: stored_tgt && target_heading(connector, points),
100
+ heading: (stored_tgt || stored_labels) && target_heading(connector, points),
101
101
  stored_labels: stored_labels).each { |t| texts << t }
102
102
  texts
103
103
  end
104
104
 
105
+ # A connector that stores label boxes for only one end seats the
106
+ # other end's labels at its anchor, like a stored zero offset.
107
+ def unstored_label_boxes(points, end_kind, stored_labels)
108
+ return default_label_boxes(points, end_kind) unless stored_labels
109
+
110
+ [{ "ox" => 0, "oy" => 0, "alignment" => 0 }, { "ox" => 0, "oy" => 0, "alignment" => 0 }]
111
+ end
112
+
105
113
  # EA tree routes are a perfect L: source-exit horizontal into
106
114
  # the corner, vertical trunk into the target dock. Returns
107
115
  # per-end flags when the connector matches, else nil.
@@ -14,7 +14,7 @@ module Ea
14
14
  class RenderContext < Struct.new(
15
15
  :element, :bounds, :model_element, :classifier,
16
16
  :fill, :stroke, :stroke_width, :text_fill,
17
- :family, :size, :size_unit,
17
+ :family, :size, :size_unit, :logical_height,
18
18
  :header_lines, :attr_lines, :op_lines,
19
19
  :enum_literals, :tagged_values, :constraints, :marker_lines,
20
20
  :package_content_lines,
@@ -24,12 +24,12 @@ module Ea
24
24
 
25
25
  attr_reader :content, :x, :y, :family, :size, :weight, :style,
26
26
  :fill, :text_length, :rotation, :size_unit,
27
- :stroke_in_text, :width_factor
27
+ :stroke_in_text, :width_factor, :logical_height
28
28
 
29
29
  def initialize(content:, x:, y:, family:, size:, weight: 400,
30
30
  style: "normal", fill: DEFAULT_FILL,
31
31
  text_length: nil, rotation: DEFAULT_ROTATION,
32
- size_unit: "px",
32
+ size_unit: "px", logical_height: nil,
33
33
  stroke_in_text: DEFAULT_STROKE_IN_TEXT,
34
34
  width_factor: DEFAULT_WIDTH_FACTOR)
35
35
  @content = content.to_s
@@ -43,6 +43,7 @@ module Ea
43
43
  @text_length = text_length
44
44
  @rotation = rotation
45
45
  @size_unit = size_unit
46
+ @logical_height = logical_height if size_unit == "pt"
46
47
  @stroke_in_text = stroke_in_text
47
48
  @width_factor = width_factor
48
49
  end
@@ -154,10 +155,10 @@ module Ea
154
155
  GLYPH_FALLBACK = 0.61
155
156
 
156
157
  def self.estimate_width(text, size, _width_factor = nil, family: nil,
157
- weight: nil, style: nil)
158
+ weight: nil, style: nil, logical_height: nil)
158
159
  real = Ea::Fonts::Metrics.text_length(text, size, family: family,
159
160
  weight: weight,
160
- style: style)
161
+ style: style, logical_height: logical_height)
161
162
  return real if real
162
163
 
163
164
  text.to_s.each_char.sum do |ch|
@@ -170,7 +171,7 @@ module Ea
170
171
 
171
172
  width = self.class.estimate_width(content, size, width_factor,
172
173
  family: family, weight: weight,
173
- style: style)
174
+ style: style, logical_height: logical_height)
174
175
  width.round.to_s
175
176
  end
176
177
 
@@ -29,7 +29,7 @@ module Ea
29
29
  attr_reader :id, :name,
30
30
  :font_family, :font_size, :font_size_unit,
31
31
  :text_weight_normal, :text_weight_bold,
32
- :element_font_size, :element_font_unit,
32
+ :element_font_family, :element_font_size, :element_font_unit,
33
33
  :text_color, :attribute_text_color, :method_text_color,
34
34
  :border_color, :fill_color, :background_color,
35
35
  :stroke_in_text_color,
@@ -69,7 +69,7 @@ module Ea
69
69
  label_font_size_unit: nil,
70
70
  font_size_unit: "pt", text_weight_normal: 400,
71
71
  text_weight_bold: 700,
72
- element_font_size: 9, element_font_unit: "pt",
72
+ element_font_family: nil, element_font_size: 9, element_font_unit: "pt",
73
73
  text_color: "#000000", attribute_text_color: nil,
74
74
  method_text_color: nil, border_color: "#000000",
75
75
  fill_color: "#FFFFFF", background_color: "#FFFFFF",
@@ -90,6 +90,7 @@ module Ea
90
90
  @font_size_unit = font_size_unit
91
91
  @text_weight_normal = text_weight_normal
92
92
  @text_weight_bold = text_weight_bold
93
+ @element_font_family = element_font_family
93
94
  @element_font_size = element_font_size
94
95
  @element_font_unit = element_font_unit
95
96
  @text_color = text_color
@@ -138,6 +139,7 @@ module Ea
138
139
 
139
140
  def with(**overrides)
140
141
  clear_label_override(overrides, :font_family, :label_font_family)
142
+ clear_label_override(overrides, :font_family, :element_font_family)
141
143
  clear_label_override(overrides, :font_size, :label_font_size)
142
144
  clear_label_override(overrides, :font_size_unit, :label_font_size_unit)
143
145
  Definition.new(**to_h.merge(overrides))
@@ -176,6 +178,7 @@ module Ea
176
178
  label_font_size_unit: @label_font_size_unit,
177
179
  text_weight_normal: text_weight_normal,
178
180
  text_weight_bold: text_weight_bold,
181
+ element_font_family: element_font_family,
179
182
  element_font_size: element_font_size,
180
183
  element_font_unit: element_font_unit,
181
184
  text_color: text_color,
@@ -11,7 +11,7 @@ module Ea
11
11
  # font: { family: Carlito, size: 7, unit: pt, weight_normal: 400, ... }
12
12
  # element_font: { size: 9, unit: pt }
13
13
  # label_font: { family: Cambria, size: 7, unit: pt }
14
- # colors: { text: "#000000", attribute_text: "#66413F", ... }
14
+ # colors: { text: "#000000", attribute_text: "#336699", ... }
15
15
  # strokes: { element_border: 2, connector_line: 2, ... }
16
16
  # text_metrics: { width_factor: 0.65 }
17
17
  # canvas: { inset_left: 35, inset_right: 50, ... }
@@ -62,10 +62,11 @@ module Ea
62
62
  font_size_unit: font["unit"] || "pt",
63
63
  text_weight_normal: font["weight_normal"] || 400,
64
64
  text_weight_bold: font["weight_bold"] || 700,
65
+ element_font_family: elem_font["family"],
65
66
  element_font_size: elem_font["size"] || 9,
66
67
  element_font_unit: elem_font["unit"] || "pt",
67
68
  text_color: colors["text"] || "#000000",
68
- attribute_text_color: colors["attribute_text"],
69
+ attribute_text_color: colors["attribute_text"] || colors["text"] || "#000000",
69
70
  method_text_color: colors["method_text"],
70
71
  border_color: colors["border"] || "#000000",
71
72
  fill_color: colors["fill"] || "#FFFFFF",
data/lib/ea/version.rb CHANGED
@@ -4,5 +4,5 @@ module Ea
4
4
  # Gem release version. Extracted to its own file so the
5
5
  # `gem-release` tool's `gem bump` can find and update it via the
6
6
  # standard `lib/<gem>/version.rb` convention.
7
- VERSION = "0.6.107"
7
+ VERSION = "0.6.108"
8
8
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ea
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.107
4
+ version: 0.6.108
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
@@ -617,6 +617,7 @@ files:
617
617
  - lib/ea/export/xsd/namespace_registry.rb
618
618
  - lib/ea/fonts.rb
619
619
  - lib/ea/fonts/cambria_7_regular_widths.json
620
+ - lib/ea/fonts/cambria_7_styled_widths.json
620
621
  - lib/ea/fonts/carlito_metrics.json
621
622
  - lib/ea/fonts/metrics.rb
622
623
  - lib/ea/guid_format.rb
@@ -818,6 +819,7 @@ files:
818
819
  - lib/ea/sources/qea/context_diagram_support.rb
819
820
  - lib/ea/sources/qea/diagram_builder.rb
820
821
  - lib/ea/sources/qea/diagram_builder/auto_routing.rb
822
+ - lib/ea/sources/qea/diagram_builder/font_settings.rb
821
823
  - lib/ea/sources/qea/diagram_builder/routing.rb
822
824
  - lib/ea/sources/qea/diagram_builder/stored_square_ports.rb
823
825
  - lib/ea/sources/qea/diagram_style_parser.rb
@@ -892,6 +894,7 @@ files:
892
894
  - lib/ea/svg/ea_emitter/compartment/instance_underline.rb
893
895
  - lib/ea/svg/ea_emitter/compartment/marker.rb
894
896
  - lib/ea/svg/ea_emitter/compartment/note_body.rb
897
+ - lib/ea/svg/ea_emitter/compartment/note_html.rb
895
898
  - lib/ea/svg/ea_emitter/compartment/note_text.rb
896
899
  - lib/ea/svg/ea_emitter/compartment/operations.rb
897
900
  - lib/ea/svg/ea_emitter/compartment/package_contents.rb