예제 #1
0
	def __init__(self, properties = None, duplicate = None):
		GraphicsObject.__init__(self, duplicate = duplicate)
		if duplicate is not None:
			self.properties = duplicate.properties.Duplicate()
			if duplicate.tie_info:
				self.tie_info = duplicate.tie_info
		else:
			if properties is not None:
				self.properties = properties
			else:
				self.properties = PropertyStack()
예제 #2
0
	def __init__(self, trafo=None, text='', halign=const.ALIGN_LEFT,
					valign=const.ALIGN_BASE, properties=None, duplicate=None):
		CommonText.__init__(self, text, duplicate)
		RectangularPrimitive.__init__(self, trafo, properties=properties,
										duplicate=duplicate)
		if duplicate != None:
			self.halign = duplicate.halign
			self.valign = duplicate.valign
			self.atrafo = duplicate.atrafo
		else:
			self.halign = halign
			self.valign = valign
			if properties is None:
				self.properties = PropertyStack(base=FactoryTextStyle())
			self.properties.align = self.halign
			self.properties.valign = self.valign
		self.cache = {}
class SimpleText(CommonText, RectangularPrimitive):

    has_edit_mode = 1
    is_Text = 1
    is_SimpleText = 1
    is_curve = 1
    is_clip = 1
    has_font = 1
    has_fill = 1
    has_line = 0

    commands = CommonText.commands + RectangularPrimitive.commands

    _lazy_attrs = RectangularPrimitive._lazy_attrs.copy()
    _lazy_attrs['atrafo'] = 'update_atrafo'

    def __init__(self,
                 trafo=None,
                 text='',
                 halign=const.ALIGN_LEFT,
                 valign=const.ALIGN_BASE,
                 properties=None,
                 duplicate=None):
        CommonText.__init__(self, text, duplicate)
        RectangularPrimitive.__init__(self,
                                      trafo,
                                      properties=properties,
                                      duplicate=duplicate)
        if duplicate != None:
            self.halign = duplicate.halign
            self.valign = duplicate.valign
            self.atrafo = duplicate.atrafo
        else:
            self.halign = halign
            self.valign = valign
            if properties is None:
                self.properties = PropertyStack(base=FactoryTextStyle())
            self.properties.align = self.halign
            self.properties.valign = self.valign
        self.cache = {}

    def Disconnect(self):
        self.cache = {}
        RectangularPrimitive.Disconnect(self)

    def Hit(self, p, rect, device, clip=0):
        a = self.properties
        llx, lly, urx, ury = a.font.TextBoundingBox(self.text, a.font_size, a)
        trafo = self.trafo(self.atrafo)
        trafo = trafo(Trafo(urx - llx, 0, 0, ury - lly, llx, lly))
        return device.ParallelogramHit(p,
                                       trafo,
                                       1,
                                       1,
                                       1,
                                       ignore_outline_mode=1)

    def GetObjectHandle(self, multiple):
        trafo = self.trafo(self.atrafo(Scale(self.properties.font_size)))
        if multiple:
            return trafo(NullPoint)
        else:
            pts = self.properties.font.TypesetText(self.text, self.properties)
            return map(trafo, pts)

    def SetAlignment(self, horizontal, vertical):
        undo = (self.SetAlignment, self.halign, self.valign)
        if horizontal is not None:
            self.halign = horizontal
            self.properties.align = horizontal
        if vertical is not None:
            self.valign = vertical
            self.properties.valign = vertical
        self._changed()
        return undo

    #AddCmd(commands, 'AlignLeft', _("Align Left"), SetAlignment, args = (const.ALIGN_LEFT, None))
    #AddCmd(commands, 'AlignRight', _("Align Right"), SetAlignment, args =(const.ALIGN_RIGHT,None))
    #AddCmd(commands, 'AlignHCenter', _("Align H. Center"), SetAlignment, args = (const.ALIGN_CENTER, None))
    #AddCmd(commands, 'AlignTop', _("Align Top"), SetAlignment, args = (None, const.ALIGN_TOP))
    #AddCmd(commands, 'AlignVCenter', _("Align V. Center"), SetAlignment, args =(None, const.ALIGN_CENTER))
    #AddCmd(commands, 'AlignBase', _("Align Baseline"), SetAlignment, args = (None, const.ALIGN_BASE))
    #AddCmd(commands, 'AlignBottom', _("Align Bottom"), SetAlignment, args = (None, const.ALIGN_BOTTOM))

    def Alignment(self):
        return self.properties.align, self.properties.valign

    def RemoveTransformation(self):
        if self.trafo.matrix() != IdentityMatrix:
            a = self.properties
            trafo = self.trafo
            llx, lly, urx, ury = a.font.TextCoordBox(self.text, a.font_size, a)
            try:
                undostyle = Primitive.Transform(self, trafo.inverse())
            except SingularMatrix:
                undostyle = None
            undotrafo = self.set_transformation(Translation(trafo.offset()))
            return CreateMultiUndo(undostyle, undotrafo)
        return NullUndo

    def DrawShape(self, device, rect=None, clip=0):
        RectangularPrimitive.DrawShape(self, device)
        base_trafo = self.trafo(self.atrafo)
        base_trafo = base_trafo(Scale(self.properties.font_size))
        paths = self.properties.font.GetPaths(self.text, self.properties)
        obj = PolyBezier(paths, self.properties.Duplicate())
        obj.Transform(base_trafo)
        device.MultiBezier(obj.paths, rect, clip)

    def update_atrafo(self):
        #		a = self.properties
        #		llx, lly, urx, ury = a.font.TextCoordBox(self.text, a.font_size, a)
        #		hj = self.halign
        #		if hj == ALIGN_RIGHT:
        #			xoff = llx - urx
        #		elif hj == ALIGN_CENTER:
        #			xoff = (llx - urx) / 2
        #		else:
        #			xoff = 0
        xoff = 0
        yoff = 0
        #		vj = self.valign
        #		if vj == ALIGN_TOP:
        #			yoff = -ury
        #		elif vj == ALIGN_CENTER:
        #			yoff = (lly - ury) / 2 - lly
        #		elif vj == ALIGN_BOTTOM:
        #			yoff = -lly
        #		else:
        #			yoff = 0
        self.atrafo = Translation(xoff, yoff)

    def update_rects(self):
        trafo = self.trafo(self.atrafo)
        a = self.properties
        rect = apply(Rect, a.font.TextBoundingBox(self.text, a.font_size, a))
        self.bounding_rect = trafo(rect).grown(2)
        rect = apply(Rect, a.font.TextCoordBox(self.text, a.font_size, a))
        self.coord_rect = trafo(rect)

    def Info(self):
        text = self.text.replace('\n', '')
        text = text.replace('\r', '')
        text = text.replace('\t', '')
        text = text.strip()
        if len(text) > 25:
            text = text[:25] + '...'
        text = text.encode('utf-8')
        return (_("Text `%(text)s' at %(position)[position]"), {
            'text': text,
            'position': self.trafo.offset()
        })

    def FullTrafo(self):
        # XXX perhaps the Trafo method should return
        # self.trafo(self.atrafo) for a SimpleText object as well.
        return self.trafo(self.atrafo)

    def SaveToFile(self, file):
        RectangularPrimitive.SaveToFile(self, file)
        file.SimpleText(self.text, self.trafo, self.properties.align,
                        self.properties.valign, self.properties.chargap,
                        self.properties.wordgap, self.properties.linegap)

    def Blend(self, other, p, q):
        if self.__class__ != other.__class__ \
         or self.properties.font != other.properties.font \
         or self.text != other.text:
            raise MismatchError
        blended = self.__class__(BlendTrafo(self.trafo, other.trafo, p, q),
                                 self.text)
        self.set_blended_properties(blended, other, p, q)
        return blended

    def AsBezier(self):
        if self.text:
            text = split(self.text, '\n')[0]
            base_trafo = self.trafo(self.atrafo)
            base_trafo = base_trafo(Scale(self.properties.font_size))
            paths = self.properties.font.GetPaths(self.text, self.properties)
            obj = PolyBezier(paths, self.properties.Duplicate())
            obj.Transform(base_trafo)
            return obj

    def Paths(self):
        #		paths = []
        if self.text:
            text = split(self.text, '\n')[0]
            base_trafo = self.trafo(self.atrafo)
            base_trafo = base_trafo(Scale(self.properties.font_size))
            paths = self.properties.font.GetPaths(self.text, self.properties)
            obj = PolyBezier(paths, self.properties.Duplicate())
            obj.Transform(base_trafo)
        return obj.paths


#			base_trafo = self.trafo(self.atrafo)
#			base_trafo = base_trafo(Scale(self.properties.font_size))
#			pos = self.properties.font.TypesetText(self.text)
#			for i in range(len(self.text)):
#				outline = self.properties.font.GetOutline(self.text[i])
#				trafo = base_trafo(Translation(pos[i]))
#				for path in outline:
#					path.Transform(trafo)
#					paths.append(path)
#		return tuple(paths)

    def Editor(self):
        return SimpleTextEditor(self)

    context_commands = ('AlignLeft', 'AlignRight', 'AlignHCenter', None,
                        'AlignTop', 'AlignVCenter', 'AlignBase', 'AlignBottom')
예제 #4
0
class Primitive(GraphicsObject):

	has_fill	= 1
	has_line	= 1
	has_properties = 1
	is_Primitive = 1

	tie_info = None
	script_access = GraphicsObject.script_access.copy()

	def __init__(self, properties = None, duplicate = None):
		GraphicsObject.__init__(self, duplicate = duplicate)
		if duplicate is not None:
			self.properties = duplicate.properties.Duplicate()
			if duplicate.tie_info:
				self.tie_info = duplicate.tie_info
		else:
			if properties is not None:
				self.properties = properties
			else:
				self.properties = PropertyStack()

	def Destroy(self):
		GraphicsObject.Destroy(self)

	def UntieFromDocument(self):
		info = self.properties.Untie()
		if info:
			self.tie_info = info
		GraphicsObject.UntieFromDocument(self)

	def TieToDocument(self):
		if self.tie_info:
			self.properties.Tie(self.document, self.tie_info)
			del self.tie_info

	def Transform(self, trafo, rects = None):
		# Apply the affine transformation trafo to all coordinates and
		# the properties.
		undo = self.properties.Transform(trafo, rects)
		if undo is not NullUndo:
			return self.properties_changed(undo)
		return undo

	def Translate(self, offset):
		# Move all points by OFFSET. OFFSET is an SKPoint instance.
		return NullUndo

	def DrawShape(self, device):
		# Draw the object on device. Here we just set the properties.
		device.SetProperties(self.properties, self.bounding_rect)

	# The following functions manage the properties

	def set_property_stack(self, properties):
		self.properties = properties
	load_SetProperties = set_property_stack

	def properties_changed(self, undo):
		if undo is not NullUndo:
			return (UndoAfter, undo, self._changed())
		return undo

	def AddStyle(self, style):
		return self.properties_changed(self.properties.AddStyle(style))
	script_access['AddStyle'] = SCRIPT_UNDO

	def Filled(self):
		return self.properties.HasFill()
	script_access['Filled'] = SCRIPT_GET

	def Properties(self):
		return self.properties
	script_access['Properties'] = SCRIPT_OBJECT

	def SetProperties(self, if_type_present = 0, **kw):
		if if_type_present:
			# change properties of that type if properties of that are
			# already present.
			prop_types = properties.property_types
			LineProperty = properties.LineProperty
			FillProperty = properties.FillProperty
			FontProperty = properties.FontProperty
			types = map(prop_types.get, kw.keys())
			if LineProperty in types and not self.properties.HasLine():
				for key in kw.keys():
					if prop_types[key] == LineProperty:
						del kw[key]
			if FillProperty in types and not self.properties.HasFill():
				for key in kw.keys():
					if prop_types[key] == FillProperty:
						del kw[key]
			if FontProperty in types and not self.properties.HasFont():
				for key in kw.keys():
					if prop_types[key] == FontProperty:
						del kw[key]
		return self.properties_changed(apply(self.properties.SetProperty, (),
												kw))
	script_access['SetProperties'] = SCRIPT_UNDO

	def LineWidth(self):
		if self.properties.HasLine:
			return self.properties.line_width
		return 0
	script_access['LineWidth'] = SCRIPT_GET

	def ObjectChanged(self, obj):
		if self.properties.ObjectChanged(obj):
			rect = self.bounding_rect
			self.del_lazy_attrs()
			self.document.AddClearRect(UnionRects(rect, self.bounding_rect))
			self.issue_changed()
			return 1
		return 0

	def ObjectRemoved(self, obj):
		return self.properties.ObjectRemoved(obj)


	def set_blended_properties(self, blended, other, frac1, frac2):
		blended.set_property_stack(Blend(self.properties, other.properties, frac1, frac2))


	def SaveToFile(self, file):
		# save object to file. Must be extended by the subclasses. Here,
		# we just save the properties.
		self.properties.SaveToFile(file)
예제 #5
0
class SimpleText(CommonText, RectangularPrimitive):

	has_edit_mode	 = 1
	is_Text		 = 1
	is_SimpleText	 = 1
	is_curve		 = 1
	is_clip		 = 1
	has_font		 = 1
	has_fill		 = 1
	has_line		 = 0
	cid = cids.TEXT

	commands = CommonText.commands + RectangularPrimitive.commands

	_lazy_attrs = RectangularPrimitive._lazy_attrs.copy()
	_lazy_attrs['atrafo'] = 'update_atrafo'

	def __init__(self, trafo=None, text='', halign=const.ALIGN_LEFT,
					valign=const.ALIGN_BASE, properties=None, duplicate=None):
		CommonText.__init__(self, text, duplicate)
		RectangularPrimitive.__init__(self, trafo, properties=properties,
										duplicate=duplicate)
		if duplicate != None:
			self.halign = duplicate.halign
			self.valign = duplicate.valign
			self.atrafo = duplicate.atrafo
		else:
			self.halign = halign
			self.valign = valign
			if properties is None:
				self.properties = PropertyStack(base=FactoryTextStyle())
			self.properties.align = self.halign
			self.properties.valign = self.valign
		self.cache = {}

	def Disconnect(self):
		self.cache = {}
		RectangularPrimitive.Disconnect(self)

	def Hit(self, p, rect, device, clip=0):
		a = self.properties

		if self.bounding_rect_cache is None:
			res = tuple(a.font.text_bbox(self.text, a))
			self.bounding_rect_cache = copy.deepcopy(res)
		else:
			res = copy.deepcopy(self.bounding_rect_cache)

		llx, lly, urx, ury = res
		trafo = self.trafo(self.atrafo)
		trafo = trafo(Trafo(urx - llx, 0, 0, ury - lly, llx, lly))
		return device.ParallelogramHit(p, trafo, 1, 1, 1,
										ignore_outline_mode=1)

	def GetObjectHandle(self, multiple):
		trafo = self.trafo(self.atrafo)
		if multiple:
			return trafo(NullPoint)
		else:

			if self.typesets_cache is None:
				a = self.properties
				pts = self.convert_typeset(a.font.typeset_text(self.text, a))
				self.typesets_cache = self.duplicate_typeset(pts)
			else:
				pts = self.duplicate_typeset(self.typesets_cache)

			return map(trafo, pts)

	def convert_typeset(self, pts):
		result = []
		for item in pts:
			result.append(Point(*item))
		return result

	def duplicate_typeset(self, typeset):
		result = []
		for point in typeset:
			result.append(Point(point.x, point.y))
		return result

	def SetAlignment(self, horizontal, vertical):
		undo = (self.SetAlignment, self.halign, self.valign)
		if horizontal is not None:
			self.halign = horizontal
			self.properties.align = horizontal
		if vertical is not None:
			self.valign = vertical
			self.properties.valign = vertical
		self._changed()

		return undo

	AddCmd(commands, 'AlignLeft', _("Align Left"), SetAlignment,
			args=(const.ALIGN_LEFT, None))
	AddCmd(commands, 'AlignRight', _("Align Right"), SetAlignment,
			args=(const.ALIGN_RIGHT, None))
	AddCmd(commands, 'AlignHCenter', _("Align H. Center"), SetAlignment,
			args=(const.ALIGN_CENTER, None))
	AddCmd(commands, 'AlignTop', _("Align Top"), SetAlignment,
			args=(None, const.ALIGN_TOP))
	AddCmd(commands, 'AlignVCenter', _("Align V. Center"), SetAlignment,
			args=(None, const.ALIGN_CENTER))
	AddCmd(commands, 'AlignBase', _("Align Baseline"), SetAlignment,
			args=(None, const.ALIGN_BASE))
	AddCmd(commands, 'AlignBottom', _("Align Bottom"), SetAlignment,
			args=(None, const.ALIGN_BOTTOM))

	def Alignment(self):
		return self.properties.align, self.properties.valign

	def RemoveTransformation(self):
		if self.trafo.matrix() != IdentityMatrix:
			trafo = self.trafo
			try:
				undostyle = Primitive.Transform(self, trafo.inverse())
			except SingularMatrix:
				undostyle = None
			undotrafo = self.set_transformation(Translation(trafo.offset()))
			return CreateMultiUndo(undostyle, undotrafo)
		return NullUndo

	def DrawShape(self, device, rect=None, clip=0):
		RectangularPrimitive.DrawShape(self, device)
		base_trafo = self.trafo(self.atrafo)
		if self.curves_cache is None:
			a = self.properties
			paths = a.font.get_paths(self.text, a)
			self.curves_cache = self.convert_paths(paths)
		paths = self.duplicate_paths(self.curves_cache)
		obj = PolyBezier(paths, self.properties.Duplicate())
		obj.Transform(base_trafo)
		device.MultiBezier(obj.paths, rect, clip)

	def convert_paths(self, paths_list):
		paths = ()
		for path in paths_list:
			p = CreatePath()
			p.AppendLine(Point(*path[0]))
			points = path[1]
			for point in points:
				if len(point) == 2:
					p.AppendLine(Point(*point))
				else:
					point0 = Point(*point[0])
					point1 = Point(*point[1])
					point2 = Point(*point[2])
					p.AppendBezier(point0, point1, point2, point[3])
			if path[2]:
				p.AppendLine(Point(*path[0]))
				p.ClosePath()
			paths = paths + (p,)
		return paths

	def duplicate_paths(self, paths):
		copy = []
		for path in paths:
			copy.append(path.Duplicate())
		return tuple(copy)

	def update_atrafo(self):
#		a = self.properties
#		llx, lly, urx, ury = a.font.TextCoordBox(self.text, a.font_size, a)
#		hj = self.halign
#		if hj == ALIGN_RIGHT:
#			xoff = llx - urx
#		elif hj == ALIGN_CENTER:
#			xoff = (llx - urx) / 2
#		else:
#			xoff = 0
		xoff = 0
		yoff = 0
#		vj = self.valign
#		if vj == ALIGN_TOP:
#			yoff = -ury
#		elif vj == ALIGN_CENTER:
#			yoff = (lly - ury) / 2 - lly
#		elif vj == ALIGN_BOTTOM:
#			yoff = -lly
#		else:
#			yoff = 0
		self.atrafo = Translation(xoff, yoff)

	def update_rects(self):
		trafo = self.trafo(self.atrafo)
		a = self.properties

		if self.bounding_rect_cache is None:
			res = a.font.text_bbox(self.text, a)
			self.bounding_rect_cache = copy.deepcopy(res)
		else:
			res = copy.deepcopy(self.bounding_rect_cache)
		rect = apply(Rect, res)
		self.bounding_rect = trafo(rect).grown(2)

		if self.coord_rect_cache is None:
			res = a.font.text_bbox(self.text, a)
			self.coord_rect_cache = copy.deepcopy(res)
		else:
			res = copy.deepcopy(self.coord_rect_cache)
		rect = apply(Rect, res)
		self.coord_rect = trafo(rect)

	def Info(self):
		text = self.text.replace('\n', '')
		text = text.replace('\r', '')
		text = text.replace('\t', '')
		text = text.strip()
		if len(text) > 25:
			text = text[:25] + '...'
		text = text.encode('utf-8')
		return (_("Text `%(text)s' at %(position)[position]"),
				{'text':text, 'position':self.trafo.offset()})

	def FullTrafo(self):
		# XXX perhaps the Trafo method should return
		return self.trafo(self.atrafo)

	def SaveToFile(self, file):
		RectangularPrimitive.SaveToFile(self, file)
		file.SimpleText(self.text, self.trafo,
					self.properties.align,
					self.properties.valign,
					self.properties.chargap,
					self.properties.wordgap,
					self.properties.linegap)

	def Blend(self, other, p, q):
		if self.__class__ != other.__class__ \
			or self.properties.font != other.properties.font \
			or self.text != other.text:
			raise MismatchError
		blended = self.__class__(BlendTrafo(self.trafo, other.trafo, p, q),
									self.text)
		self.set_blended_properties(blended, other, p, q)
		return blended

	def AsBezier(self):
		if self.text:
			base_trafo = self.trafo(self.atrafo)
			if self.curves_cache is None:
				a = self.properties
				paths = a.font.get_paths(self.text, a)
				self.curves_cache = self.convert_paths(paths)
			paths = self.duplicate_paths(self.curves_cache)
			obj = PolyBezier(paths, self.properties.Duplicate())
			obj.Transform(base_trafo)
			return obj

	def Paths(self):
		if self.text:
			base_trafo = self.trafo(self.atrafo)
			if self.curves_cache is None:
				a = self.properties
				paths = a.font.get_paths(self.text, a)
				self.curves_cache = self.convert_paths(paths)
			paths = self.duplicate_paths(self.curves_cache)
			obj = PolyBezier(paths, self.properties.Duplicate())
			obj.Transform(base_trafo)
		return obj.paths

	def Editor(self):
		return SimpleTextEditor(self)

	context_commands = ('AlignLeft', 'AlignRight', 'AlignHCenter', None,
						'AlignTop', 'AlignVCenter', 'AlignBase', 'AlignBottom')