File: text.rb

package info (click to toggle)
ruby-rmagick 6.0.1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 8,232 kB
  • sloc: cpp: 19,563; ruby: 17,147; sh: 88; javascript: 36; makefile: 13
file content (176 lines) | stat: -rw-r--r-- 4,669 bytes parent folder | download | duplicates (2)
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