#--
# $Id: text.rb,v 1.3 2005/07/15 20:48:50 rmagick Exp $
# Copyright (C) 2005 Timothy P. Hunter
#++
# Text-related classes
class Magick::RVG
# Base class for Tspan, Tref and Text.
class TextBase
include Stylable
include Duplicatable
private
def initialize(text, &block) #:nodoc:
super()
@text = text.to_s if text
@dx = @dy = 0
@rotation = 0
@tspans = Content.new
yield(self) if block_given?
end
public
# Create a new text chunk. Each chunk can have its own initial position and styles.
# If x and y are omitted the text starts at the current text
# position.
def tspan(text, x=nil, y=nil)
tspan = Tspan.new(text, x, y)
tspan.parent = self
@tspans << tspan
return tspan
end
# Add x and y to the current text position.
def d(x, y=0)
@dx, @dy = Magick::RVG.convert_to_float(x, y)
yield(self) if block_given?
self
end
# Rotate the text about the current text position.
def rotate(degrees)
@rotation = Magick::RVG.convert_to_float(degrees)[0]
yield(self) if block_given?
self
end
# We do our own transformations.
def add_primitives(gc) #:nodoc:
if @text || @tspans.length > 0
gc.push
x = self.cx + @dx
y = self.cy + @dy
if @rotation != 0
gc.translate(x, y)
gc.rotate(@rotation)
gc.translate(-x, -y)
end
add_style_primitives(gc)
if @text
x2, y2 = gc.text(x, y, @text)
self.cx = x + x2
self.cy = y + y2
end
@tspans.each do |tspan|
tspan.add_primitives(gc)
end
gc.pop
end
end
end # class TextBase
# Tspan and Tref shared methods - read/update @cx, @cy in parent Text object.
module TextLink #:nodoc:
def add_primitives(gc)
@parent.cx = @x if @x
@parent.cy = @y if @y
super
end
def cx()
@parent.cx
end
def cy()
@parent.cy
end
def cx=(x)
@parent.cx = x
end
def cy=(y)
@parent.cy = y
end
end # module TextLink
class Tref < TextBase #:nodoc:
include TextLink
def initialize(obj, x, y, parent)
@x, @y = Magick::RVG.convert_to_float(x, y, :allow_nil)
super(nil)
@tspans << obj
@parent = parent
end
end # class Tref
class Tspan < TextBase #:nodoc:
include TextLink
attr_accessor :parent
# Define a text segment starting at (x, y).
# If x and y are omitted the segment starts
# at the current text position.
#
# Tspan objects can contain Tspan objects.
def initialize(text=nil, x=nil, y=nil, &block)
@x, @y = Magick::RVG.convert_to_float(x, y, :allow_nil)
super(text, &block)
end
end # class Tspan
class Text < TextBase
attr_accessor :cx, :cy #:nodoc:
# Define a text string starting at [x, y].
# Use the RVG::TextConstructors#text method to create Text objects in a container.
#
# container.text(100, 100, "Simple text").styles(:font=>'Arial')
#
# Text objects can contain Tspan objects.
#
# container.text(100, 100).styles(:font=>'Arial') do |t|
# t.tspan("Red text").styles(:fill=>'red')
# t.tspan("Blue text").styles(:fill=>'blue')
# end
def initialize(x=0, y=0, text=nil, &block)
@cx, @cy = Magick::RVG.convert_to_float(x, y)
super(text, &block)
end
# Reference a Tspan object. x and y are just
# like x and y in RVG::TextBase#tspan
def tref(obj, x=nil, y=nil)
if ! obj.kind_of?(Tspan)
raise ArgumentError, "wrong argument type #{obj.class} (expected Tspan)"
end
obj = obj.deep_copy
obj.parent = self
tref = Tref.new(obj, x, y, self)
@tspans << tref
return tref
end
end # class Text
# Methods that construct text objects within a container
module TextConstructors
# Draw a text string at (x,y). The string can
# be omitted. Optionally, define text chunks within the associated
# block.
def text(x=0, y=0, text=nil, &block)
t = Text.new(x, y, text, &block)
@content << t
return t
end
end # module TextConstructors
end