Class: Fontisan::SvgToGlyf::Geometry::AffineTransform

Inherits:
Object
  • Object
show all
Defined in:
lib/fontisan/svg_to_glyf/geometry/affine_transform.rb

Overview

A 2×3 affine transform representing:

x' = a·x + c·y + e
y' = b·x + d·y + f

Every coordinate operation in SvgToGlyf (SVG group transforms, viewBox mapping, Y-flip, UPM scaling) is modeled as an AffineTransform so they can be composed into a single matrix applied once per point.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(a, b, c, d, e, f) ⇒ AffineTransform

Returns a new instance of AffineTransform.

Parameters:

  • a (Float)

    x-scale

  • b (Float)

    y-skew-x

  • c (Float)

    x-skew-y

  • d (Float)

    y-scale

  • e (Float)

    x-translate

  • f (Float)

    y-translate



24
25
26
27
28
29
30
31
# File 'lib/fontisan/svg_to_glyf/geometry/affine_transform.rb', line 24

def initialize(a, b, c, d, e, f)
  @a = a.to_f
  @b = b.to_f
  @c = c.to_f
  @d = d.to_f
  @e = e.to_f
  @f = f.to_f
end

Instance Attribute Details

#aObject (readonly)

Returns the value of attribute a.



16
17
18
# File 'lib/fontisan/svg_to_glyf/geometry/affine_transform.rb', line 16

def a
  @a
end

#bObject (readonly)

Returns the value of attribute b.



16
17
18
# File 'lib/fontisan/svg_to_glyf/geometry/affine_transform.rb', line 16

def b
  @b
end

#cObject (readonly)

Returns the value of attribute c.



16
17
18
# File 'lib/fontisan/svg_to_glyf/geometry/affine_transform.rb', line 16

def c
  @c
end

#dObject (readonly)

Returns the value of attribute d.



16
17
18
# File 'lib/fontisan/svg_to_glyf/geometry/affine_transform.rb', line 16

def d
  @d
end

#eObject (readonly)

Returns the value of attribute e.



16
17
18
# File 'lib/fontisan/svg_to_glyf/geometry/affine_transform.rb', line 16

def e
  @e
end

#fObject (readonly)

Returns the value of attribute f.



16
17
18
# File 'lib/fontisan/svg_to_glyf/geometry/affine_transform.rb', line 16

def f
  @f
end

Class Method Details

.flip_y(axis) ⇒ Object

Reflect across a horizontal line at y = axis. Points above the axis map below it and vice versa.



66
67
68
# File 'lib/fontisan/svg_to_glyf/geometry/affine_transform.rb', line 66

def self.flip_y(axis)
  new(1, 0, 0, -1, 0, 2 * axis)
end

.identityObject



33
34
35
# File 'lib/fontisan/svg_to_glyf/geometry/affine_transform.rb', line 33

def self.identity
  new(1, 0, 0, 1, 0, 0)
end

.rotate_degrees(angle) ⇒ Object



52
53
54
# File 'lib/fontisan/svg_to_glyf/geometry/affine_transform.rb', line 52

def self.rotate_degrees(angle)
  rotate_radians(angle.to_f * Math::PI / 180.0)
end

.rotate_radians(angle) ⇒ Object



46
47
48
49
50
# File 'lib/fontisan/svg_to_glyf/geometry/affine_transform.rb', line 46

def self.rotate_radians(angle)
  cos = Math.cos(angle)
  sin = Math.sin(angle)
  new(cos, sin, -sin, cos, 0, 0)
end

.scale(sx, sy = nil) ⇒ Object



41
42
43
44
# File 'lib/fontisan/svg_to_glyf/geometry/affine_transform.rb', line 41

def self.scale(sx, sy = nil)
  sy = sx if sy.nil?
  new(sx, 0, 0, sy, 0, 0)
end

.skew_x_radians(angle) ⇒ Object



56
57
58
# File 'lib/fontisan/svg_to_glyf/geometry/affine_transform.rb', line 56

def self.skew_x_radians(angle)
  new(1, 0, Math.tan(angle), 1, 0, 0)
end

.skew_y_radians(angle) ⇒ Object



60
61
62
# File 'lib/fontisan/svg_to_glyf/geometry/affine_transform.rb', line 60

def self.skew_y_radians(angle)
  new(1, Math.tan(angle), 0, 1, 0, 0)
end

.translate(tx, ty = 0) ⇒ Object



37
38
39
# File 'lib/fontisan/svg_to_glyf/geometry/affine_transform.rb', line 37

def self.translate(tx, ty = 0)
  new(1, 0, 0, 1, tx, ty)
end

Instance Method Details

#==(other) ⇒ Object Also known as: eql?



98
99
100
101
102
# File 'lib/fontisan/svg_to_glyf/geometry/affine_transform.rb', line 98

def ==(other)
  other.is_a?(AffineTransform) &&
    @a == other.a && @b == other.b && @c == other.c &&
    @d == other.d && @e == other.e && @f == other.f
end

#apply(x, y) ⇒ Array(Float, Float)

Returns transformed [x', y'].

Parameters:

  • x (Numeric)
  • y (Numeric)

Returns:

  • (Array(Float, Float))

    transformed [x', y']



90
91
92
# File 'lib/fontisan/svg_to_glyf/geometry/affine_transform.rb', line 90

def apply(x, y)
  [@a * x + @c * y + @e, @b * x + @d * y + @f]
end

#compose(other) ⇒ Object

Compose this transform with other, returning a new AffineTransform equivalent to applying other first, then self. This matches SVG's transform="self other" convention.

result.apply(x, y) == self.apply(*other.apply(x, y))


76
77
78
79
80
81
82
83
84
85
# File 'lib/fontisan/svg_to_glyf/geometry/affine_transform.rb', line 76

def compose(other)
  AffineTransform.new(
    @a * other.a + @c * other.b,
    @b * other.a + @d * other.b,
    @a * other.c + @c * other.d,
    @b * other.c + @d * other.d,
    @a * other.e + @c * other.f + @e,
    @b * other.e + @d * other.f + @f,
  )
end

#hashObject



106
107
108
# File 'lib/fontisan/svg_to_glyf/geometry/affine_transform.rb', line 106

def hash
  [@a, @b, @c, @d, @e, @f].hash
end

#identity?Boolean

Returns:

  • (Boolean)


94
95
96
# File 'lib/fontisan/svg_to_glyf/geometry/affine_transform.rb', line 94

def identity?
  @a == 1 && @b.zero? && @c.zero? && @d == 1 && @e.zero? && @f.zero?
end