Skip to content
This repository
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 188 lines (151 sloc) 5.772 kb
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 177 178 179 180 181 182 183 184 185 186 187
#--
# $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, &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 <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
                return 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.
            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 (<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

            attr_accessor :cx, :cy #:nodoc:

            # 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)
                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 (<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
                return t
            end

        end # module TextConstructors

    end # class RVG
end # module Magick
Something went wrong with that request. Please try again.