1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
|
# frozen_string_literal: true
module TTFunk
class Table
class Cff < TTFunk::Table
# Path. Mostly used for CFF glyph outlines.
class Path
# Close path command.
CLOSE_PATH_CMD = [:close].freeze
# Commands in this path.
# @return [Array]
attr_reader :commands
# Number of contours in this path.
# @return [Integer]
attr_reader :number_of_contours
def initialize
@commands = []
@number_of_contours = 0
end
# Move implicit cursor to coordinates.
#
# @param x [Integer, Float]
# @param y [Integer, Float]
# @return [void]
def move_to(x, y)
@commands << [:move, x, y]
end
# Add a line to coordinates.
#
# @param x [Integer, Float]
# @param y [Integer, Float]
# @return [void]
def line_to(x, y)
@commands << [:line, x, y]
end
# Add a BeĢzier curve. Current position is the first control point, (`x1`,
# `y1`) is the second, (`x2`, `y2`) is the third, and (`x`, `y`) is the
# last control point.
#
# @param x1 [Integer, Float]
# @param y1 [Integer, Float]
# @param x2 [Integer, Float]
# @param y2 [Integer, Float]
# @param x [Integer, Float]
# @param y [Integer, Float]
# @return [void]
def curve_to(x1, y1, x2, y2, x, y) # rubocop: disable Metrics/ParameterLists
@commands << [:curve, x1, y1, x2, y2, x, y]
end
# Close current contour.
#
# @return [void]
def close_path
@commands << CLOSE_PATH_CMD
@number_of_contours += 1
end
# Reposition and scale path.
#
# @param x [Integer, Float] new horizontal position.
# @param y [Integer, Float] new vertical position.
# @param font_size [Integer, Float] font size.
# @param units_per_em [Integer] units per Em as defined in the font.
# @return [TTFunk::Table::Cff::Path]
def render(x: 0, y: 0, font_size: 72, units_per_em: 1000)
new_path = self.class.new
scale = 1.0 / units_per_em * font_size
commands.each do |cmd|
case cmd[:type]
when :move
new_path.move_to(x + (cmd[1] * scale), y + (-cmd[2] * scale))
when :line
new_path.line_to(x + (cmd[1] * scale), y + (-cmd[2] * scale))
when :curve
new_path.curve_to(
x + (cmd[1] * scale),
y + (-cmd[2] * scale),
x + (cmd[3] * scale),
y + (-cmd[4] * scale),
x + (cmd[5] * scale),
y + (-cmd[6] * scale),
)
when :close
new_path.close_path
end
end
new_path
end
private
def format_values(command)
command[1..].map { |k| format('%.2f', k) }.join(' ')
end
end
end
end
end
|