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
|
#--
# $Id: container.rb,v 1.5 2009/02/28 23:52:13 rmagick Exp $
# Copyright (C) 2009 Timothy P. Hunter
#++
module Magick
class RVG
# Content is simply an Array with a deep_copy method.
# When unit-testing, it also has a deep_equal method.
# @private
class Content < Array
def deep_copy(h = {})
me = __id__
copy = h[me]
unless copy
copy = self.class.new
each do |c|
copy << if c.nil?
nil
elsif c.respond_to?(:deep_copy)
c.deep_copy(h)
elsif c.respond_to?(:dup)
begin
c.dup
rescue StandardError
c
end
else
c
end
end
copy.freeze if frozen?
h[me] = copy
end
copy
end
end # class Content
# Define a collection of shapes, text, etc. that can be reused.
# Group objects are _containers_. That is, styles and transforms defined
# on the group are used by contained objects such as shapes, text, and
# nested groups unless overridden by a nested container or the object itself.
# Groups can be reused with the RVG::UseConstructors#use method.
# Create groups within
# containers with the RVG::StructureConstructors#g method.
#
# Example:
# # All elements in the group will be translated by 50 in the
# # x-direction and 10 in the y-direction.
# rvg.g.translate(50, 10).styles(:stroke=>'red',:fill=>'none') do |grp|
# # The line will be red.
# grp.line(10,10, 20,20)
# # The circle will be blue.
# grp.circle(10, 20, 20).styles(:stroke=>'blue')
# end
class Group
include Stylable
include Transformable
include Embellishable
include Describable
include Duplicatable
def initialize
super
@content = Content.new
yield(self) if block_given?
end
# @private
def add_primitives(gc)
gc.push
add_transform_primitives(gc)
add_style_primitives(gc)
@content.each { |element| element.add_primitives(gc) }
gc.pop
end
# Translate container according to #use arguments
# @private
def ref(x, y, _width, _height)
translate(x, y) if x != 0 || y != 0
end
# Append an arbitrary object to the group's content. Called
# by #use to insert a non-container object into a group.
# @private
def <<(obj)
@content << obj
end
end # class Group
# A Use object allows the re-use of RVG and RVG::Group
# objects within a container. Create a Use object with the
# RVG::UseConstructors#use method.
class Use
include Stylable
include Transformable
include Duplicatable
# In a container, Use objects are created indirectly via the
# RVG::UseConstructors#use method.
# The +x+ and +y+ arguments
# can be used to specify an additional translation for
# the group. The +width+ and +height+ arguments specify
# a width and height for referenced RVG objects.
def initialize(element, x = 0, y = 0, width = nil, height = nil)
super()
# If the element is not a group, defs, symbol, or rvg,
# wrap a group around it so it can get a transform and
# possibly a new viewport.
if element.respond_to?(:ref)
@element = element.deep_copy
else
@element = Group.new
@element << element.deep_copy
end
@element.ref(x, y, width, height)
end
# @private
def add_primitives(gc)
gc.push
add_transform_primitives(gc)
add_style_primitives(gc)
@element.add_primitives(gc)
gc.pop
end
end # class Use
end # class RVG
end # module Magick
|