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 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
|
#--
# $Id: text.rb,v 1.7 2009/02/28 23:52:28 rmagick Exp $
# Copyright (C) 2009 Timothy P. Hunter
#++
# Text-related classes
module Magick
class RVG
# Base class for Tspan, Tref and Text.
class TextBase
include Stylable
include Duplicatable
private
def initialize(text)
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 <tt>x</tt> and <tt>y</tt> 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
tspan
end
# Add <tt>x</tt> and <tt>y</tt> 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.
# @private
def add_primitives(gc)
return if !@text && @tspans.empty?
gc.push
x = cx + @dx
y = 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 # class TextBase
# Tspan and Tref shared methods - read/update @cx, @cy in parent Text object.
# @private
module TextLink
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
# @private
class Tref < TextBase
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
# @private
class Tspan < TextBase
include TextLink
attr_accessor :parent
# Define a text segment starting at (<tt>x</tt>, <tt>y</tt>).
# If <tt>x</tt> and <tt>y</tt> 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
# @private
attr_accessor :cx, :cy
# Define a text string starting at [<tt>x</tt>, <tt>y</tt>].
# 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. <tt>x</tt> and <tt>y</tt> are just
# like <tt>x</tt> and <tt>y</tt> in RVG::TextBase#tspan
def tref(obj, x = nil, y = nil)
raise ArgumentError, "wrong argument type #{obj.class} (expected Tspan)" unless obj.is_a?(Tspan)
obj = obj.deep_copy
obj.parent = self
tref = Tref.new(obj, x, y, self)
@tspans << tref
tref
end
end # class Text
# Methods that construct text objects within a container
module TextConstructors
# Draw a text string at (<tt>x</tt>,<tt>y</tt>). 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
t
end
end # module TextConstructors
end # class RVG
end # module Magick
|