Class: Pdfrb::Content::Canvas

Inherits:
Object
  • Object
show all
Defined in:
lib/pdfrb/content/canvas.rb

Overview

High-level drawing API on a Stream (page /Contents or Form XObject). The Canvas emits operators via the Serializer and appends the bytes to the Stream's raw payload.

Methods mirror HexaPDF::Content::Canvas where the names are intuitive; PDF-specific concepts (q/Q, marked content) are exposed via Ruby-block syntax.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(stream, document: nil) ⇒ Canvas

Returns a new instance of Canvas.



15
16
17
18
19
20
# File 'lib/pdfrb/content/canvas.rb', line 15

def initialize(stream, document: nil)
  @stream = stream
  @document = document || stream.document
  @serializer = Pdfrb::Serializer.new
  ensure_stream_payload
end

Instance Attribute Details

#documentObject (readonly)

Returns the value of attribute document.



13
14
15
# File 'lib/pdfrb/content/canvas.rb', line 13

def document
  @document
end

#serializerObject (readonly)

Returns the value of attribute serializer.



13
14
15
# File 'lib/pdfrb/content/canvas.rb', line 13

def serializer
  @serializer
end

#streamObject (readonly)

Returns the value of attribute stream.



13
14
15
# File 'lib/pdfrb/content/canvas.rb', line 13

def stream
  @stream
end

Instance Method Details

#close_pathObject



92
93
94
95
# File 'lib/pdfrb/content/canvas.rb', line 92

def close_path
  emit_op Pdfrb::Content::Operator::ClosePath
  self
end

#concat(a, b, c, d, e, f, &block) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/pdfrb/content/canvas.rb', line 53

def concat(a, b, c, d, e, f, &block)
  emit_op Pdfrb::Content::Operator::ConcatMatrix, a, b, c, d, e, f
  return self unless block_given?

  begin
    yield self
  ensure
    # Reverse by save/restore so the caller's matrix is unchanged.
    emit_op Pdfrb::Content::Operator::SaveGraphicsState
  end
  self
end

#curve_to(c1x, c1y, c2x, c2y, x, y) ⇒ Object



82
83
84
85
# File 'lib/pdfrb/content/canvas.rb', line 82

def curve_to(c1x, c1y, c2x, c2y, x, y)
  emit_op Pdfrb::Content::Operator::CurveTo, c1x, c1y, c2x, c2y, x, y
  self
end

#dash_pattern=(spec) ⇒ Object



182
183
184
185
186
187
188
189
# File 'lib/pdfrb/content/canvas.rb', line 182

def dash_pattern=(spec)
  if spec.is_a?(::Array)
    array, phase = spec
  else
    array, phase = spec, 0
  end
  emit_op Pdfrb::Content::Operator::DashPattern, array, phase
end

#emit_op(op_class, *operands) ⇒ Object

---- Internal ----



211
212
213
214
# File 'lib/pdfrb/content/canvas.rb', line 211

def emit_op(op_class, *operands)
  bytes = op_class.serialize(@serializer, *operands)
  append(bytes)
end

#end_pathObject



120
121
122
123
# File 'lib/pdfrb/content/canvas.rb', line 120

def end_path
  emit_op Pdfrb::Content::Operator::EndPath
  self
end

#fill(rule: :nonzero) ⇒ Object



104
105
106
107
108
109
110
# File 'lib/pdfrb/content/canvas.rb', line 104

def fill(rule: :nonzero)
  op = rule == :even_odd ?
         Pdfrb::Content::Operator::FillEvenOdd :
         Pdfrb::Content::Operator::FillNonZero
  emit_op op
  self
end

#fill_color(color) ⇒ Object

---- Color ----



127
128
129
130
131
132
133
134
135
# File 'lib/pdfrb/content/canvas.rb', line 127

def fill_color(color)
  case color
  in [Symbol | String => family, *rest]
    emit_color_op(true, family.to_sym, rest)
  else
    emit_color_op(true, :gray, [color])
  end
  self
end

#fill_stroke(rule: :nonzero) ⇒ Object



112
113
114
115
116
117
118
# File 'lib/pdfrb/content/canvas.rb', line 112

def fill_stroke(rule: :nonzero)
  op = rule == :even_odd ?
         Pdfrb::Content::Operator::FillStrokeEvenOdd :
         Pdfrb::Content::Operator::FillStrokeNonZero
  emit_op op
  self
end

#line(x1, y1, x2, y2) ⇒ Object



78
79
80
# File 'lib/pdfrb/content/canvas.rb', line 78

def line(x1, y1, x2, y2)
  move_to(x1, y1).line_to(x2, y2)
end

#line_cap=(n) ⇒ Object



170
171
172
# File 'lib/pdfrb/content/canvas.rb', line 170

def line_cap=(n)
  emit_op Pdfrb::Content::Operator::LineCap, n
end

#line_join=(n) ⇒ Object



174
175
176
# File 'lib/pdfrb/content/canvas.rb', line 174

def line_join=(n)
  emit_op Pdfrb::Content::Operator::LineJoin, n
end

#line_to(x, y) ⇒ Object



73
74
75
76
# File 'lib/pdfrb/content/canvas.rb', line 73

def line_to(x, y)
  emit_op Pdfrb::Content::Operator::LineTo, x, y
  self
end

#line_width=(n) ⇒ Object

---- Graphics-state params ----



166
167
168
# File 'lib/pdfrb/content/canvas.rb', line 166

def line_width=(n)
  emit_op Pdfrb::Content::Operator::LineWidth, n
end

#marked_content(tag, properties = nil, &block) ⇒ Object

---- Marked content ----



193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/pdfrb/content/canvas.rb', line 193

def marked_content(tag, properties = nil, &block)
  if properties
    emit_op Pdfrb::Content::Operator::BeginMarkedContentWithProperties, tag, properties
  else
    emit_op Pdfrb::Content::Operator::BeginMarkedContent, tag
  end
  return self unless block_given?

  begin
    yield self
  ensure
    emit_op Pdfrb::Content::Operator::EndMarkedContent
  end
  self
end

#miter_limit=(n) ⇒ Object



178
179
180
# File 'lib/pdfrb/content/canvas.rb', line 178

def miter_limit=(n)
  emit_op Pdfrb::Content::Operator::MiterLimit, n
end

#move_to(x, y) ⇒ Object

---- Path construction ----



68
69
70
71
# File 'lib/pdfrb/content/canvas.rb', line 68

def move_to(x, y)
  emit_op Pdfrb::Content::Operator::MoveTo, x, y
  self
end

#rectangle(x, y, width, height) ⇒ Object



87
88
89
90
# File 'lib/pdfrb/content/canvas.rb', line 87

def rectangle(x, y, width, height)
  emit_op Pdfrb::Content::Operator::Rectangle, x, y, width, height
  self
end

#rotate(angle_in_radians, &block) ⇒ Object



47
48
49
50
51
# File 'lib/pdfrb/content/canvas.rb', line 47

def rotate(angle_in_radians, &block)
  c = Math.cos(angle_in_radians)
  s = Math.sin(angle_in_radians)
  concat(c, s, -s, c, 0, 0, &block)
end

#save_graphics_state(&block) ⇒ Object Also known as: with_graphics_state

---- State stack ----



24
25
26
27
28
29
30
31
32
33
34
# File 'lib/pdfrb/content/canvas.rb', line 24

def save_graphics_state(&block)
  emit_op Pdfrb::Content::Operator::SaveGraphicsState
  if block_given?
    begin
      yield self
    ensure
      emit_op Pdfrb::Content::Operator::RestoreGraphicsState
    end
  end
  self
end

#scale(sx, sy = sx, &block) ⇒ Object



43
44
45
# File 'lib/pdfrb/content/canvas.rb', line 43

def scale(sx, sy = sx, &block)
  concat(sx, 0, 0, sy, 0, 0, &block)
end

#strokeObject

---- Painting ----



99
100
101
102
# File 'lib/pdfrb/content/canvas.rb', line 99

def stroke
  emit_op Pdfrb::Content::Operator::Stroke
  self
end

#stroke_color(color) ⇒ Object



137
138
139
140
141
142
143
144
145
# File 'lib/pdfrb/content/canvas.rb', line 137

def stroke_color(color)
  case color
  in [Symbol | String => family, *rest]
    emit_color_op(false, family.to_sym, rest)
  else
    emit_color_op(false, :gray, [color])
  end
  self
end

#text(str, at:, font:, size:, char_spacing: nil, word_spacing: nil) ⇒ Object

Show text at (+x+, y) in the named font. Caller is responsible for registering the font in the page resources under font_name before this call.



152
153
154
155
156
157
158
159
160
161
162
# File 'lib/pdfrb/content/canvas.rb', line 152

def text(str, at:, font:, size:, char_spacing: nil, word_spacing: nil)
  emit_op Pdfrb::Content::Operator::BeginText
  emit_op Pdfrb::Content::Operator::SetTextMatrix,
          1, 0, 0, 1, at[0], at[1]
  emit_op Pdfrb::Content::Operator::Font, font, size
  emit_op Pdfrb::Content::Operator::CharSpacing, char_spacing if char_spacing
  emit_op Pdfrb::Content::Operator::WordSpacing, word_spacing if word_spacing
  emit_op Pdfrb::Content::Operator::ShowText, str.to_s
  emit_op Pdfrb::Content::Operator::EndText
  self
end

#translate(tx, ty, &block) ⇒ Object

---- Transforms ----



39
40
41
# File 'lib/pdfrb/content/canvas.rb', line 39

def translate(tx, ty, &block)
  concat(1, 0, 0, 1, tx, ty, &block)
end