emfsvg 0.1.3 → 0.1.4
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/README.adoc +98 -14
- data/lib/emfsvg/device_context.rb +9 -6
- data/lib/emfsvg/dib_decoder.rb +12 -8
- data/lib/emfsvg/drawing_hint.rb +88 -0
- data/lib/emfsvg/error.rb +11 -0
- data/lib/emfsvg/format_helpers.rb +46 -2
- data/lib/emfsvg/glyph_index_mapper.rb +5 -6
- data/lib/emfsvg/object_table.rb +7 -15
- data/lib/emfsvg/record_access.rb +38 -0
- data/lib/emfsvg/renderer.rb +114 -55
- data/lib/emfsvg/svg/clip_path_registry.rb +287 -4
- data/lib/emfsvg/svg/color.rb +32 -9
- data/lib/emfsvg/svg/document.rb +7 -0
- data/lib/emfsvg/svg/element.rb +3 -3
- data/lib/emfsvg/svg/elements/clip_path.rb +89 -24
- data/lib/emfsvg/svg/elements/defs.rb +85 -4
- data/lib/emfsvg/svg/elements/group.rb +30 -4
- data/lib/emfsvg/svg/elements/path.rb +239 -3
- data/lib/emfsvg/svg/elements/rect.rb +5 -2
- data/lib/emfsvg/svg/elements/stylable.rb +41 -11
- data/lib/emfsvg/svg/elements/text.rb +101 -16
- data/lib/emfsvg/svg/paint.rb +8 -2
- data/lib/emfsvg/svg/parser.rb +8 -1
- data/lib/emfsvg/svg/path_data/command.rb +1 -1
- data/lib/emfsvg/svg/path_data.rb +47 -36
- data/lib/emfsvg/svg/stroke.rb +78 -12
- data/lib/emfsvg/svg_builder.rb +38 -9
- data/lib/emfsvg/translation/context.rb +262 -10
- data/lib/emfsvg/translation/decimal_detector.rb +26 -8
- data/lib/emfsvg/translation/emf_renderer.rb +16 -12
- data/lib/emfsvg/translation/handler_registry.rb +16 -6
- data/lib/emfsvg/translation/handlers/circular_arc.rb +103 -0
- data/lib/emfsvg/translation/handlers/defs_handler.rb +33 -4
- data/lib/emfsvg/translation/handlers/ellipse_handler.rb +2 -2
- data/lib/emfsvg/translation/handlers/elliptical_arc.rb +125 -0
- data/lib/emfsvg/translation/handlers/group_handler.rb +7 -0
- data/lib/emfsvg/translation/handlers/image_handler.rb +53 -8
- data/lib/emfsvg/translation/handlers/line_handler.rb +2 -2
- data/lib/emfsvg/translation/handlers/mapped_arc.rb +41 -0
- data/lib/emfsvg/translation/handlers/mapped_circular_arc.rb +55 -0
- data/lib/emfsvg/translation/handlers/mapped_pie.rb +30 -0
- data/lib/emfsvg/translation/handlers/path_flattener.rb +70 -49
- data/lib/emfsvg/translation/handlers/path_handler.rb +169 -14
- data/lib/emfsvg/translation/handlers/polyline_handler.rb +2 -2
- data/lib/emfsvg/translation/handlers/rect_handler.rb +21 -5
- data/lib/emfsvg/translation/handlers/shared_gdi.rb +75 -12
- data/lib/emfsvg/translation/handlers/text_handler.rb +92 -29
- data/lib/emfsvg/translation/handlers.rb +5 -0
- data/lib/emfsvg/translation/header_builder.rb +20 -0
- data/lib/emfsvg/translation/local_origin.rb +40 -0
- data/lib/emfsvg/translation/record_emitter.rb +8 -5
- data/lib/emfsvg/translation/scaler/fixed.rb +8 -2
- data/lib/emfsvg/translation.rb +1 -0
- data/lib/emfsvg/version.rb +1 -1
- data/lib/emfsvg/visitors/emr_visitor.rb +197 -129
- data/lib/emfsvg.rb +49 -2
- metadata +24 -10
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Emfsvg
|
|
4
|
+
module Translation
|
|
5
|
+
# A complete absolute line can use a temporary integer device origin when
|
|
6
|
+
# its fixed-scale coordinates overflow. Restrict this to independent draws:
|
|
7
|
+
# pending paths, relative commands and clips carry additional state.
|
|
8
|
+
module LocalOrigin
|
|
9
|
+
module_function
|
|
10
|
+
|
|
11
|
+
def for_path(element, scaler)
|
|
12
|
+
return unless scaler.scaled? && independent_line?(element)
|
|
13
|
+
|
|
14
|
+
points = element.commands.map(&:args)
|
|
15
|
+
return unless finite_points?(points)
|
|
16
|
+
return unless points.flatten.any? { |value| scaler.unsafe?(value) }
|
|
17
|
+
|
|
18
|
+
origin = points.transpose.map do |values|
|
|
19
|
+
values.any? { |value| scaler.unsafe?(value) } ? ((values.min + values.max) / 2.0).floor : 0
|
|
20
|
+
end
|
|
21
|
+
return unless origin.all? { |value| Scaler::Fixed::INT32_RANGE.cover?(value) }
|
|
22
|
+
return unless points.all? { |point| point.zip(origin).all? { |value, offset| !scaler.unsafe?(value - offset) } }
|
|
23
|
+
|
|
24
|
+
origin
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def independent_line?(element)
|
|
28
|
+
element.is_a?(Svg::Elements::Path) && element.children.empty? &&
|
|
29
|
+
!element.clip_path && element.fill.null? && element.path_record_kind.nil? &&
|
|
30
|
+
[nil, :polyline].include?(element.line_record_kind) && element.commands.map(&:letter) == %w[M L]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def finite_points?(points)
|
|
34
|
+
points.all? do |point|
|
|
35
|
+
point.size == 2 && point.all? { |value| value.is_a?(Numeric) && value.finite? }
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -19,17 +19,20 @@ module Emfsvg
|
|
|
19
19
|
|
|
20
20
|
attr_reader :records
|
|
21
21
|
|
|
22
|
-
def emit(wire_class,
|
|
23
|
-
record = build(wire_class,
|
|
22
|
+
def emit(wire_class, attrs)
|
|
23
|
+
record = build(wire_class, attrs)
|
|
24
24
|
@records << record
|
|
25
25
|
record
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
# Construct without appending. Useful for inline inspection in tests.
|
|
29
|
-
def build(wire_class,
|
|
29
|
+
def build(wire_class, attrs)
|
|
30
|
+
adapter = Emf::Model::Emr::Records::WireAdapter
|
|
31
|
+
return adapter.build(wire_class, **attrs) if adapter.respond_to?(:build)
|
|
32
|
+
|
|
30
33
|
wire = wire_class.new(**attrs)
|
|
31
|
-
wire.n_size = wire.
|
|
32
|
-
|
|
34
|
+
wire.n_size = wire.num_bytes
|
|
35
|
+
adapter.new(wire: wire)
|
|
33
36
|
end
|
|
34
37
|
end
|
|
35
38
|
end
|
|
@@ -13,8 +13,11 @@ module Emfsvg
|
|
|
13
13
|
# Larger factors risk int32 overflow on big coords (max safe
|
|
14
14
|
# SVG coord ~ 214_000 with FACTOR=10_000).
|
|
15
15
|
class Fixed
|
|
16
|
+
class Overflow < RangeError; end
|
|
17
|
+
|
|
18
|
+
INT32_RANGE = (-(2**31)..((2**31) - 1))
|
|
16
19
|
FACTOR = 10_000
|
|
17
|
-
MAX_SAFE_INPUT = 214_748 # (2**31 - 1) / FACTOR, with margin
|
|
20
|
+
MAX_SAFE_INPUT = 214_748 # ((2**31) - 1) / FACTOR, with margin
|
|
18
21
|
|
|
19
22
|
attr_reader :factor
|
|
20
23
|
|
|
@@ -23,6 +26,8 @@ module Emfsvg
|
|
|
23
26
|
end
|
|
24
27
|
|
|
25
28
|
def to_int(decimal)
|
|
29
|
+
raise Overflow, "coordinate exceeds scaled int32 range: #{decimal}" if unsafe?(decimal)
|
|
30
|
+
|
|
26
31
|
(decimal.to_f * factor).round
|
|
27
32
|
end
|
|
28
33
|
|
|
@@ -33,7 +38,8 @@ module Emfsvg
|
|
|
33
38
|
# True if `value` would overflow int32 when scaled. The
|
|
34
39
|
# renderer falls back to Identity when ANY coord is unsafe.
|
|
35
40
|
def unsafe?(value)
|
|
36
|
-
value.to_f
|
|
41
|
+
scaled = value.to_f * factor
|
|
42
|
+
!scaled.finite? || !INT32_RANGE.cover?(scaled.round)
|
|
37
43
|
end
|
|
38
44
|
end
|
|
39
45
|
end
|
data/lib/emfsvg/translation.rb
CHANGED
data/lib/emfsvg/version.rb
CHANGED