def __init__(self, file, pathname, options): self.file = file self.pathname = pathname self.options = options self.white = CreateRGBColor(1.0, 1.0, 1.0) self.black = CreateRGBColor(0.0, 0.0, 0.0) self.Msg = Warnings()
def gradient_stop(self, color_style, mid_point, ramp_point): if color_style == 0: # gray scale k = self.pop() color = CreateRGBColor(k, k, k) elif color_style == 1: # CMYK color = apply(CreateCMYKColor, tuple(self.pop_multi(4))) elif color_style == 2: # RGB Color args = tuple(self.pop_multi(7)) # The cmyk and rgb values usually differ slightly because AI # does some color correction. Which values should we choose # here? color = apply(CreateRGBColor, args[-3:]) color = apply(CreateCMYKColor, args[:4]) elif color_style == 3: # CMYK Custom Color args = self.pop_multi(6) color = apply(CreateCMYKColor, tuple(args[:4])) else: self.add_message( _("Gradient ColorStyle %d not yet supported." "substituted black") % color_style) if color_style == 4: n = 10 else: self.add_message(_("Unknown ColorStyle %d") % color_style) self.pop_multi(n) color = StandardColors.black # XXX #color = apply(CreateRGBColor, color) self.stack.append((ramp_point / 100.0, color))
def getStdConnLine(fromobj, toobj, cplist=()): global tarrw1, tarrw2, tarrw3 #~ snAdct['ptfl_1'], # from (startpoint - moveto) #~ snBdct['box'], # to (endpoint) #~ # here optional arguments for 'in-between' points; #~ # (ordered) tuple of dict, where key is command: #~ # like in tikz:: '|' means along y , '-' means along x #~ # (last {'-':-10}, is not needed - endpoint specifies it #~ ({'-':10}, {'|':-20}, {'-':-30}, {'|':-40}) # for now, we expect that fromobj is always going to be a # 'pointer' tf line; and to obj is going to be a box connlineCol = SolidPattern(CreateRGBColor(0.3, 0.3, 0.3)) # retrieve start point - endpoint of fromobj ptf line # get 2nd node (=segment 1) - in there, Point() is third in list ([2]) tmpep_start = fromobj.paths[0].Segment(1)[2] # NOTE though: 'skpoint' object has only read-only attributes !! (cannot assign to .x) # retrieve end point - the center left (west) point of the box of to obj: #~ tmpep_end = toobj.bounding_rect.center() #~ tmpep_end.x = toobj.bounding_rect.left # there seems to be a 10 units padding for bounding_rect; (see below) # compensate it tobr = toobj.bounding_rect.grown(-10) tmpep_end = Point(tobr.left, tobr.center().y) # start drawing the line tpath = CreatePath() tpath.AppendLine(tmpep_start) # moveto # are there any 'in-between' connection points ? prevPoint = tmpep_start nextPoint = tmpep_start for ibcp in cplist: axiscommand = ibcp.keys()[0] moveval = ibcp[axiscommand] if axiscommand == '-': # along x #~ nextPoint.x = prevPoint.x + moveval nextPoint = Point(prevPoint.x + moveval, prevPoint.y) elif axiscommand == '|': # along y #~ nextPoint.y = prevPoint.y + moveval nextPoint = Point(prevPoint.x, prevPoint.y + moveval) tpath.AppendLine(nextPoint) # moveto prevPoint = nextPoint tpath.AppendLine(tmpep_end) # lineto tline = PolyBezier((tpath, )) #~ tline.AddStyle(tbase_style) # of Graphics.properties (also in compound, document) - seems to add a 'layer' if dynamic; else seems to 'replace' ?! tline.SetProperties(line_width=2.0, line_pattern=connlineCol, line_arrow2=tarrw2) tline.update_rects() return tline
def CreateBrushIndirect(self): style, r, g, b, hatch = self.get_struct('<hBBBxh') if style == 1: pattern = EmptyPattern else: pattern = SolidPattern( CreateRGBColor(r / 255.0, g / 255.0, b / 255.0)) self.add_gdiobject((('fill_pattern', pattern), )) self._print('->', style, r, g, b, hatch)
def ta_set_colour(self, colour): if tuple(colour) == (255, 255, 255): return EmptyPattern else: return SolidPattern( CreateRGBColor( float(colour[0]) / 255.0, float(colour[1]) / 255.0, float(colour[2]) / 255.0))
def begin_ai_layer(self): if self.format_version >= 4.0: visible, preview, enabled, printing, dimmed, unused, has_mlm,\ color, red, green, blue, unused, unused = self.pop_multi(13) else: visible, preview, enabled, printing, dimmed, has_mlm, \ color, red, green, blue = self.pop_multi(10) color = CreateRGBColor(red / 255.0, green / 255.0, blue / 255.0) self.layer_kw_args = { 'printable': printing, 'visible': visible, 'locked': not enabled, 'outline_color': color }
def getQuickLine(tstart, tend): # expected tuple at input pstart = Point(tstart[0], tstart[1]) pend = Point(tend[0], tend[1]) tpath = CreatePath() # Note - apparently, the first appended point is "moveTo"; # .. the ubsequent ones being "LineTo" tpath.AppendLine(pstart) # moveto tpath.AppendLine(pend) # lineto tline = PolyBezier((tpath,)) tline.AddStyle(tbase_style) # of Graphics.properties (also in compound, document) - seems to add a 'layer' if dynamic; else seems to 'replace' ?! tline.SetProperties(line_pattern = SolidPattern(CreateRGBColor(0.7, 0.7, 0.9))) return tline
def CreatePenIndirect(self): style, widthx, widthy, r, g, b = self.get_struct('<hhhBBBx') cap = (style & 0x0F00) >> 8 join = (style & 0x00F0) >> 4 style = style & 0x000F if style == 5: pattern = EmptyPattern else: pattern = SolidPattern( CreateRGBColor(r / 255.0, g / 255.0, b / 255.0)) width = abs(widthx * self.trafo.m11) self.add_gdiobject((( 'line_pattern', pattern, ), ('line_width', width))) self._print('->', style, widthx, widthy, r, g, b, cap, join)
def csscolor(str): str = strip(str) if str[0] == '#': if len(str) == 7: r = atoi(str[1:3], 16) / 255.0 g = atoi(str[3:5], 16) / 255.0 b = atoi(str[5:7], 16) / 255.0 elif len(str) == 4: # According to the CSS rules a single HEX digit is to be # treated as a repetition of the digit, so that for a digit # d the value is (16 * d + d) / 255.0 which is equal to d / 15.0 r = atoi(str[1], 16) / 15.0 g = atoi(str[2], 16) / 15.0 b = atoi(str[3], 16) / 15.0 color = CreateRGBColor(r, g, b) elif namedcolors.has_key(str): color = namedcolors[str] else: color = StandardColors.black return color
def main(): import Sketch global doc global tbase_style Sketch.init_lib() draw_printable = 1 draw_visible = 0 embed_fonts = 0 eps_for = util.get_real_username() eps_date = util.current_date() eps_title = None rotate = 0 #doc = load.load_drawing('') # from mainwindow.py: self.SetDocument(Document(create_layer = 1)) doc = Document(create_layer = 1) # get font info first Graphics.font.read_font_dirs() # indicate start of coord system first # coord system:: + goes upward / rightward # from RectangleCreator: trafo = Trafo(off.x, 0, 0, off.y, end.x, end.y) # actually, there 'end' seems to correspond to start (llc: lower left corner of rectangle) - and 'off' to the length extended in each direction (i.e. width, height - but can be negative) ; so instead of 'end' - calling it 'start' start_x = 5 start_y = 5 off_x = -10 off_y = -10 trec = Rectangle(trafo = Trafo(off_x, 0, 0, off_y, start_x, start_y)) trec.update_rects() doc.Insert(trec) # from create_text.py textfld = SimpleText(Translation(50, 50), "xyzzy") textfld.SetProperties(fill_pattern = SolidPattern(StandardColors.green), font = GetFont('Courier-Bold'),#('Times-Bold'), font_size = 36) #copy textfld textfld2 = textfld.Duplicate() textfld2.SetProperties(fill_pattern = SolidPattern(StandardColors.blue)) # change color only # rotate textfld angleDeg = 45 angleRad = pi*(angleDeg/180.0) # ensure float op - could use math.radians instead textfld.Transform(Rotation(angleRad)) # Rotation(angle, center) textfld.update_rects() # probably a good idea # change textfld's text with the current width (that we see) # get bounding box of text a = textfld.properties llx, lly, urx, ury = a.font.TextBoundingBox(textfld.text, a.font_size) # calculate width - its of UNTRANSFORMED text twidth = urx - llx # insert this width as text in textbox now: #~ textfld.text = str(twidth) #~ textfld.update_rects() # probably a good idea - again # get textfield as bezier textbez = textfld.AsBezier() #~ print textbez # returns Sketch.Graphics.group.Group; subclass of EditableCompound # the bounding rectangle - from Compound (type is Rect): textbez_bRect = textbez.bounding_rect # calc width now t2width = textbez_bRect.right - textbez_bRect.left # insert this width as text in textbox now: textfld.text = str(t2width) textfld.update_rects() # probably a good idea - again #~ doc.Insert(textfld) # create a line # using create_spiral.py technique below (see syntax note #(A1)) tpath = CreatePath() # Note - apparently, the first appended point is "moveTo"; # .. the ubsequent ones being "LineTo" tp = Point(textbez_bRect.left,textbez_bRect.bottom) tpath.AppendLine(tp) # moveto tp = Point(textbez_bRect.left,textbez_bRect.top) tpath.AppendLine(tp) # lineto tp = Point(textbez_bRect.right,textbez_bRect.top) tpath.AppendLine(tp) # lineto tp = Point(textbez_bRect.right,textbez_bRect.bottom) tpath.AppendLine(tp) # lineto tline = PolyBezier((tpath,)) tline.AddStyle(tbase_style) # of Graphics.properties (also in compound, document) - seems to add a 'layer' if dynamic; else seems to 'replace' ?! #~ doc.Insert(tline) # group tline and textfld ... # footprints.py has Group(foot_prints = []) tgrp = Group([textfld, textfld2, tline]) tgrp.update_rects() doc.Insert(tgrp) # add a box.. around textfld2 # use radius1, radius2 != 0 AND 1 (logarithmic) to get RoundedRectangle (best between 0.0 and 1.0) tfbr = textfld2.bounding_rect start_x = tfbr.left start_y = tfbr.bottom off_x = tfbr.right - tfbr.left off_y = tfbr.top - tfbr.bottom twid = abs(off_x - start_x) thei = abs(off_y - start_y) radfact = 1.2*twid/thei tradius = 0.05 # if we want to specify a single one, then the actual look will depend on the dimesions of the rectangle - so must 'smooth' it with radfact... trec = Rectangle(trafo = Trafo(off_x, 0, 0, off_y, start_x, start_y), radius1 = tradius, radius2 = tradius*radfact) trec.update_rects() doc.Insert(trec) # add another box - any where start_x = 100.0 start_y = 100.0 off_x = 50.0 off_y = 50.0 trec2 = Rectangle(trafo = Trafo(off_x, 0, 0, off_y, start_x, start_y)) trec2.update_rects() doc.Insert(trec2) # try change props post insert - OK trec2.SetProperties(fill_pattern = SolidPattern(StandardColors.yellow), line_width = 2.0, line_pattern = SolidPattern(CreateRGBColor(0.5, 0.5, 0.7))) # try move the group as a whole (Translate - syntax: spread.py) # say, align the right edge of tline to left edge of trec2 (x direction) # NOTE: group does not define own .AsBezier(self); # but it has tgrp.bounding_rect (although python doesn't show it in dir(tgrp)) # also there is Rectangle.bounding_rect # NOTE though - it seems bounding_rect is somehow padded, with (at least) 10 units in each direction! (also, bounding rect of line will include the arrow) xmove = (trec2.bounding_rect.left+10)-(tline.bounding_rect.right-10) #~ print xmove, trec2.bounding_rect.left, tline.bounding_rect.right tgrp.Translate(Point(xmove, 0)) tgrp.update_rects() # add temporary line to indicate bounding boxes # and effect of padding (may cover the very first trec) tmpbr = trec2.bounding_rect doc.Insert( getQuickLine( (0,0), (trec2.bounding_rect.left+10, tline.bounding_rect.top-10) ) ) # end of draw - generate output file filename = '' psfile = 'vectorout.ps' sk2ps(filename, psfile, printable= draw_printable, visible = draw_visible, For = eps_for, CreationDate = eps_date, Title = eps_title, rotate = rotate, embed_fonts = embed_fonts)
def set_fill_gray(self, k): self.fill_color = CreateRGBColor(k, k, k)
def set_line_rgb(self, r, g, b): self.line_color = CreateRGBColor(r, g, b)
def set_line_gray(self, k): self.line_color = CreateRGBColor(k, k, k)
def rgb_custom_color(r, g, b, t): t = 1.0 - t return CreateRGBColor(1 - (t * (1 - r)), 1 - (t * (1 - g)), 1 - (t * (1 - b)))
def rgb_component_changed(self, *rest): self.color_changed( CreateRGBColor(self.var4.get() / 255.0, self.var5.get() / 255.0, self.var6.get() / 255.0))
def set_fill_rgb(self, r, g, b): self.fill_color = CreateRGBColor(r, g, b)
def read_objects(self, objects): n_objects = 0 # Traverse the list of drawfile object for object in objects: if isinstance(object, drawfile.group): # Start a group object in the document self.begin_group() # Descend into the group n_objects_lower = self.read_objects(object.objects) # If the group was empty then don't try to end it if n_objects_lower == 0: # self.__pop() (self.composite_class, self.composite_args, self.composite_items, self.composite_stack) = self.composite_stack else: # End group object self.end_group() n_objects = n_objects + 1 elif isinstance(object, drawfile.tagged): # Tagged object n_objects_lower = self.read_objects([object.object]) if n_objects_lower != 0: n_objects = n_objects + 1 elif isinstance(object, drawfile.path): # Path object n_objects = n_objects + 1 # Set the path style self.style.line_width = object.width / scale if object.style['join'] == 'mitred': self.style.line_join = const.JoinMiter if object.style['start cap'] == 'butt': self.style.line_cap = const.CapButt elif object.style['start cap'] == 'round': if object.width > 0: width = 0.5 length = 0.5 else: width = 0.0 length = 0.0 # Draw arrow path = [(0.0, width), (0.5 * length, width, length, 0.5 * width, length, 0.0), (length, -0.5 * width, 0.5 * length, -width, 0.0, -width), (0.0, width)] self.style.line_arrow1 = Arrow(path, 1) elif object.style['start cap'] == 'square': if object.width > 0: width = 0.5 length = 0.5 else: width = 0.0 length = 0.0 # Draw arrow path = [(0.0, width), (length, width), (length, -width), (0.0, -width), (0.0, width)] self.style.line_arrow1 = Arrow(path, 1) elif object.style['start cap'] == 'triangular': if object.width > 0: width = object.style['triangle cap width'] / 16.0 length = object.style['triangle cap length'] / 16.0 else: width = 0.0 length = 0.0 # Draw arrow path = [(0.0, width), (length, 0.0), (0.0, -width), (0.0, width)] self.style.line_arrow1 = Arrow(path, 1) if (object.width / scale) < 1.0: self.style.line_arrow1.path.Transform( Scale(object.width / scale, object.width / scale)) if object.style['end cap'] == 'butt': self.style.line_cap = const.CapButt elif object.style['end cap'] == 'round': if object.width > 0: width = 0.5 length = 0.5 else: width = 0.0 length = 0.0 # Draw arrow path = [(0.0, width), (0.5 * length, width, length, 0.5 * width, length, 0.0), (length, -0.5 * width, 0.5 * length, -width, 0.0, -width), (0.0, width)] self.style.line_arrow2 = Arrow(path, 1) elif object.style['end cap'] == 'square': if object.width > 0: width = 0.5 length = 0.5 else: width = 0.0 length = 0.0 # Draw arrow path = [(0.0, width), (length, width), (length, -width), (0.0, -width), (0.0, width)] self.style.line_arrow2 = Arrow(path, 1) elif object.style['end cap'] == 'triangular': if object.width > 0: width = object.style['triangle cap width'] / 16.0 length = object.style['triangle cap length'] / 16.0 else: width = 0.0 length = 0.0 # Draw arrow path = [(0.0, width), (length, 0.0), (0.0, -width), (0.0, width)] self.style.line_arrow2 = Arrow(path, 1) if (object.width / scale) < 1.0: self.style.line_arrow2.path.Transform( Scale(object.width / scale, object.width / scale)) # Outline colour if object.outline == [255, 255, 255, 255]: self.style.line_pattern = EmptyPattern else: self.style.line_pattern = SolidPattern( CreateRGBColor( float(object.outline[1]) / 255.0, float(object.outline[2]) / 255.0, float(object.outline[3]) / 255.0)) # Fill colour if object.fill == [255, 255, 255, 255]: self.style.fill_pattern = EmptyPattern else: self.style.fill_pattern = SolidPattern( CreateRGBColor( float(object.fill[1]) / 255.0, float(object.fill[2]) / 255.0, float(object.fill[3]) / 255.0)) # Dash pattern if object.style['dash pattern'] == 'present': line_dashes = [] for n in object.pattern: line_dashes.append(int(n / scale)) self.style.line_dashes = tuple(line_dashes) # Create a list of path objects in the document paths = [] path = None # Examine the path elements for element in object.path: if element[0] == 'move': x, y = self.relative(element[1][0], element[1][1]) # Add any previous path to the list if path != None: # path.load_close() paths.append(path) path = CreatePath() path.AppendLine(x, y) elif element[0] == 'draw': x, y = self.relative(element[1][0], element[1][1]) path.AppendLine(x, y) elif element[0] == 'bezier': x1, y1 = self.relative(element[1][0], element[1][1]) x2, y2 = self.relative(element[2][0], element[2][1]) x, y = self.relative(element[3][0], element[3][1]) path.AppendBezier(x1, y1, x2, y2, x, y) elif element[0] == 'close': path.ClosePath() elif element[0] == 'end': # Should be the last object in the path # path.load_close() paths.append(path) break # Create a bezier object if paths != []: self.bezier(tuple(paths)) elif isinstance(object, drawfile.font_table): # Font table n_objects = n_objects + 1 # Set object level instance self.font_table = object.font_table elif isinstance(object, drawfile.text): # Text object n_objects = n_objects + 1 # Determine the font if self.font_table.has_key(object.style): self.style.font = RISCOSFont(self.font_table[object.style]) else: self.style.font = GetFont('Times Roman') # The size self.style.font_size = object.size[0] / scale # Outline colour if object.background == [255, 255, 255, 255]: self.style.line_pattern = EmptyPattern else: self.style.line_pattern = SolidPattern( CreateRGBColor( float(object.background[1]) / 255.0, float(object.background[2]) / 255.0, float(object.background[3]) / 255.0)) # Fill colour if object.foreground == [255, 255, 255, 255]: self.style.fill_pattern = EmptyPattern else: self.style.fill_pattern = SolidPattern( CreateRGBColor( float(object.foreground[1]) / 255.0, float(object.foreground[2]) / 255.0, float(object.foreground[3]) / 255.0)) # Transformation if hasattr(object, 'transform'): x, y = object.transform[4] / scale, object.transform[ 5] / scale ox, oy = self.relative(object.baseline[0], object.baseline[1]) transform = Trafo(object.transform[0] / 65536.0, object.transform[1] / 65536.0, object.transform[2] / 65536.0, object.transform[3] / 65536.0, ox + x, oy + y) else: transform = Translation( self.relative(object.baseline[0], object.baseline[1])) # Write the text self.simple_text(object.text, transform) elif isinstance(object, drawfile.jpeg): # JPEG object n_objects = n_objects + 1 # Transformation matrix x, y = self.relative(object.transform[4], object.transform[5]) # Scale the object using the dpi information available, noting # that unlike Draw which uses 90 dpi, Sketch uses 72 dpi. # (I assume this since 90 dpi Drawfile JPEG objects appear 1.25 # times larger in Sketch if no scaling is performed here.) scale_x = (object.transform[0] / 65536.0) * (72.0 / object.dpi_x) scale_y = (object.transform[3] / 65536.0) * (72.0 / object.dpi_y) transform = Trafo(scale_x, object.transform[1] / 65536.0, object.transform[2] / 65536.0, scale_y, x, y) # Decode the JPEG image image = Image.open(StringIO.StringIO(object.image)) # # Read dimensions of images in pixels # width, height = image.size # # # Divide these by the dpi values to obtain the size of the # # image in inches # width, height = width/float(object.dpi_x), \ # height/float(object.dpi_y) # image.load() self.image(image, transform) elif isinstance(object, drawfile.sprite): # Sprite object n_objects = n_objects + 1 # Transformation matrix if hasattr(object, 'transform'): x, y = self.relative(object.transform[4], object.transform[5]) # Multiply the scale factor by that in the transformation matrix scale_x = (object.transform[0]/65536.0) * \ (72.0 / object.sprite['dpi x']) scale_y = (object.transform[3]/65536.0) * \ (72.0 / object.sprite['dpi y']) transform = Trafo( scale_x, (object.transform[1]/65536.0) * \ (72.0 / object.sprite['dpi y']), (object.transform[2]/65536.0) * \ (72.0 / object.sprite['dpi x']), scale_y, x, y ) else: x, y = self.relative(object.x1, object.y1) # Draw scales the Sprite to fit in the object's # bounding box. To do the same, we need to know the # actual size of the Sprite # In points: # size_x = 72.0 * float(object.sprite['width']) / \ # object.sprite['dpi x'] # size_y = 72.0 * float(object.sprite['height']) / \ # object.sprite['dpi y'] # # # Bounding box dimensions in points: # bbox_width = (object.x2 - object.x1)/scale # bbox_height = (object.y2 - object.y1)/scale # # # Scale factors # scale_x = (bbox_width / size_x) * \ # (72.0 / object.sprite['dpi x']) # scale_y = (bbox_height / size_y) * \ # (72.0 / object.sprite['dpi y']) scale_x = (object.x2 - object.x1) / \ (scale * object.sprite['width']) scale_y = (object.y2 - object.y1) / \ (scale * object.sprite['height']) transform = Trafo(scale_x, 0.0, 0.0, scale_y, x, y) # Create an Image object image = Image.fromstring( object.sprite['mode'], (object.sprite['width'], object.sprite['height']), object.sprite['image']) self.image(image, transform) elif isinstance(object, drawfile.options): # Options object n_objects = n_objects + 1 # Read page size paper_size = object.options['paper size'] orientation = object.options['paper limits'] if paper_size in papersizes: if orientation == 'landscape': self.page_layout = pagelayout.PageLayout( object.options['paper size'], orientation=pagelayout.Landscape) else: self.page_layout = pagelayout.PageLayout( object.options['paper size'], orientation=pagelayout.Portrait) if object.options['grid locking'] == 'on': spacing = object.options['grid spacing'] if object.options['grid units'] == 'in': spacing = spacing * 72.0 else: spacing = spacing * 72.0 / 2.54 if object.options['grid shown'] == 'on': visible = 1 else: visible = 0 # self.begin_layer_class( GridLayer, # ( # (0, 0, int(spacing), int(spacing)), # visible, # CreateRGBColor(0.0, 0.0, 0.0), # _("Grid") # ) ) # self.end_composite() elif isinstance(object, drawfile.text_area): # Text area n_objects = n_objects + 1 # The text area object contains a number of columns. self.columns = len(object.columns) # Start in the first column and move to subsequent # columns as required, unless the number is overidden # by details in the text area. self.column = 0 # The cursor position is initially undefined. cursor = [None, None] # The column margins self.margin_offsets = [1.0, 1.0] self.margins = [ (object.columns[self.column].x1 / scale) + \ self.margin_offsets[0], (object.columns[self.column].x2 / scale) - \ self.margin_offsets[1] ] # The column base self.column_base = object.columns[self.column].y1 / scale # Line and paragraph spacing self.linespacing = 0.0 paragraph = 10.0 # Current font name and dimensions font_name = '' font_size = 0.0 font_width = 0.0 # Text colours background = (255, 255, 255) foreground = (0, 0, 0) # Build lines (lists of words) until the column width # is reached then write the line to the page. line = [] width = 0.0 # Current text alignment align = 'L' # Last command to be executed last_command = '' # Execute the commands in the text area: for command, args in object.commands: if command == '!': # Version number # print 'Version number', args pass elif command == 'A': # print 'Align:', args # Write current line self.ta_write_line(align, cursor, line, 0) # Empty the line list line = [] # Set the line width width = 0.0 # Align text align = args # Start new line cursor = self.ta_new_line(cursor, object, self.linespacing) elif command == 'B': # print 'Background:', args # Background colour background = args elif command == 'C': # print 'Foreground:', args # Foreground colour foreground = args elif command == 'D': # print 'Columns:', args # Number of columns if self.column == 0 and cursor == [None, None]: # Nothing rendered yet, so change number of columns self.columns = args elif command == 'F': # print 'Define font:', args # Define font (already defined in object.font_table) pass elif command == 'L': # print 'Line spacing:', args # Set line spacing self.linespacing = args elif command == 'M': # print 'Margins:', args # Change margins self.margin_offsets = [args[0], args[1]] self.margins = [ (object.columns[self.column].x1 / scale) + args[0], (object.columns[self.column].x2 / scale) - args[1] ] elif command == 'P': # print 'Paragraph spacing:', args # Change paragraph spacing paragraph = args elif command == 'U': # print 'Underlining' # Underlining pass elif command == 'V': # print 'Vertical displacement' # Vertical displacement pass elif command == '-': # print 'Hyphen' # Hyphen pass elif command == 'newl': # print 'New line' # New line # Write current line self.ta_write_line(align, cursor, line, 0) # Start new line cursor = self.ta_new_line(cursor, object, self.linespacing) # Can't position cursor? if cursor == [None, None]: break # Empty the line list line = [] # Set the line width width = 0.0 elif command == 'para': # print 'New paragraph' # New paragraph # Write current line self.ta_write_line(align, cursor, line, 0) # Start new line if last_command != 'newl': cursor = self.ta_new_line( cursor, object, paragraph + self.linespacing) else: cursor = self.ta_new_line(cursor, object, paragraph) # Can't position cursor? if cursor == [None, None]: break # Empty the line list line = [] # Set the line width width = 0.0 elif command == ';': # print 'Comment:', args # Comment pass elif command == 'font': # print 'Use font:', args # Font change font_name, \ font_size, \ font_width = object.font_table[args] # Select font use_font = RISCOSFont(font_name) # Move cursor to start of a line if the cursor is # undefined if cursor == [None, None]: cursor[0] = self.margins[0] cursor[1] = (object.columns[self.column].y2 / scale) - font_size # Set line spacing self.linespacing = font_size elif command == 'text': # print args # Text. Add it to the line, checking that the line # remains within the margins. text, space = self.make_safe(args[0]), args[1] # Add the width of the text to the current total width width = width + \ use_font.TextCoordBox(text, font_size)[2] # print width, margins[1] - margins[0] # Compare current total width with column width while width > (self.margins[1] - self.margins[0]): # First write any text on this line if line != []: # Width will exceed column width # print 'Width will exceed column width' # Write current line self.ta_write_line(align, cursor, line, 1) # Start new line cursor = self.ta_new_line( cursor, object, self.linespacing) # Can't position cursor? if cursor == [None, None]: break # Clear the list line = [] # Reset the width width = 0.0 # Now attempt to fit this word on the next line width = use_font.TextCoordBox(text, font_size)[2] br = len(text) # Continue to try until the word fits, or none of it fits while width > (self.margins[1] - self.margins[0]) \ and br > 0: # Keep checking the size of the word width = use_font.TextCoordBox( text[:br], font_size)[2] br = br - 1 if br == 0: # Word couldn't fit in the column at all, so # break out of this loop break elif br < len(text): # Write the subword to the line self.ta_write_line( align, cursor, [(text[:br], font_name, font_size, font_width, self.ta_set_colour(foreground), self.ta_set_colour(background))], 0) # Start new line cursor = self.ta_new_line( cursor, object, self.linespacing) # Can't position cursor? if cursor == [None, None]: break # keep the remaining text text = text[br:] # The width is just the width of this text width = use_font.TextCoordBox(text, font_size)[2] # If the whole string fit onto the line then # control will flow to the else clause which will # append the text to the line list for next time. else: # The text fits within the margins so add the text # to the line line.append( (text, font_name, font_size, font_width, self.ta_set_colour(foreground), self.ta_set_colour(background))) # Also append any trailing space if space != '': line.append( (space, font_name, font_size, font_width, self.ta_set_colour(foreground), self.ta_set_colour(background))) width = width + \ use_font.TextCoordBox( space, font_size)[2] # Can't position cursor? if cursor == [None, None]: break # Remember this command last_command = command # Render any remaining text if line != [] and cursor != [None, None]: # Write current line self.ta_write_line(align, cursor, line, 0) else: pass # Return the number of recognised objects return n_objects
def getStructBoxnode(inlabel, plist, vlist): global courfont global tarrw1, tarrw2, tarrw3 pvfnsz = 12 # font size for pointers/vars # here we'll also generate a dict of all graphic objects # global 'id' is not needed - it will be a part of a tuple, along with master group sbdict = {} ## pointers - horizontal yoff = 0 ypad = 2 lastcharpad = pvfnsz # so the arrow dont overlap with last char xoutermost = 0 # to get the longest arrow (so we use it to make arrows same length) point_tflist = [] # list of actual textfield objects tcount = 0 for iptxt in plist: textfld = SimpleText(Translation(0, yoff), iptxt) textfld.SetProperties(font=courfont, font_size=pvfnsz) textfld.update_rects() sbdict['ptf_' + str(tcount)] = textfld # add connector line tfbr = textfld.bounding_rect tfline = getQuickLine((tfbr.left, tfbr.bottom), (tfbr.right + lastcharpad, tfbr.bottom)) tfline.SetProperties(line_width=2.0, line_arrow1=tarrw1, line_arrow2=tarrw2) tfline.update_rects() sbdict['ptfl_' + str(tcount)] = tfline if tfbr.right + lastcharpad > xoutermost: xoutermost = tfbr.right + lastcharpad # group line and text tgrp = Group([tfline, textfld]) tgrp.update_rects() sbdict['ptfg_' + str(tcount)] = tgrp # add the group - not just textfld - to list here point_tflist.append(tgrp) # get height - calc next offset; yoff will go negative, but nvm (will group and move) # don't use tgrp's BB, its too high llx, lly, urx, ury = textfld.bounding_rect # /tgrp. /getTfBB(textfld) tfHeight = ury - lly yoff -= tfHeight + ypad tcount += 1 # done - now resize all the arrows according to xoutermost, # so they are same length # SetLine(i, x, y[, cont]) "Replace the ith segment by a line segment" # where the i-th segment is the node.. for tgrp in point_tflist: # loop (in a list) tfline = tgrp.objects[ 0] # access Group (sub)object - tfline is first [0] # get 2nd node (=segment 1) - in there, Point() is third in list ([2]) tmpep = tfline.paths[0].Segment(1)[2] # change 2nd node (=segment 1) of the (first) path (paths[0]) tfline.paths[0].SetLine(1, (xoutermost, tmpep.y)) tfline.update_rects() tgrp.update_rects() # finally, group all these point_group = Group(point_tflist) # accepts list directly point_group.update_rects() sbdict['ptg'] = point_group ## variables - vertical (so, rotate group afterwards) yoff = 0 ypad = 2 lastcharpad = 1 # pvfnsz /so the arrow dont overlap with last char xoutermost = 0 # to get the longest arrow (so we use it to make arrows same length) varbl_tflist = [] # list of actual textfield objects tcount = 0 havevars = len(vlist) # could be zero! for ivtxt in vlist: textfld = SimpleText(Translation(0, yoff), ivtxt) textfld.SetProperties(font=courfont, font_size=pvfnsz) textfld.update_rects() sbdict['vtf_' + str(tcount)] = textfld # add connector line tfbr = textfld.bounding_rect tfline = getQuickLine((tfbr.left, tfbr.bottom), (tfbr.right + lastcharpad, tfbr.bottom)) tfline.SetProperties(line_width=2.0, line_arrow1=tarrw1, line_arrow2=tarrw3) tfline.update_rects() sbdict['vtfl_' + str(tcount)] = tfline if tfbr.right + lastcharpad > xoutermost: xoutermost = tfbr.right + lastcharpad # group line and text tgrp = Group([tfline, textfld]) tgrp.update_rects() sbdict['vtfg_' + str(tcount)] = tgrp # add the group - not just textfld - to list here varbl_tflist.append(tgrp) # get height - calc next offset; yoff will go negative, but nvm (will group and move) llx, lly, urx, ury = textfld.bounding_rect # getTfBB(textfld) tfHeight = ury - lly yoff -= tfHeight + 2 tcount += 1 # done - now resize all the arrows according to xoutermost, # so they are same length # SetLine(i, x, y[, cont]) "Replace the ith segment by a line segment" # where the i-th segment is the node.. for tgrp in varbl_tflist: # loop (in a list) tfline = tgrp.objects[ 0] # access Group (sub)object - tfline is first [0] # get 2nd node (=segment 1) - in there, Point() is third in list ([2]) tmpep = tfline.paths[0].Segment(1)[2] # change 2nd node (=segment 1) of the (first) path (paths[0]) tfline.paths[0].SetLine(1, (xoutermost, tmpep.y)) tfline.update_rects() tgrp.update_rects() # finally, group all these varbl_group = Group(varbl_tflist) # accepts list directly varbl_group.update_rects() sbdict['vtg'] = varbl_group # rotate variable group # for repositioning - easiest to rotate around # upper-left corner (instead of center point) vgbr = varbl_group.bounding_rect varbl_g_cp = vgbr.center() # centerpoint varbl_g_ul = Point(vgbr.left, vgbr.top) # top (upper) left varbl_group.Transform(Rotation(radians(-90), varbl_g_ul)) varbl_group.update_rects() # must reassign variable for .bounding_rect # after transform and update_rects()!!: vgbr = varbl_group.bounding_rect vgbr_w = vgbr.right - vgbr.left vgbr_h = vgbr.top - vgbr.bottom # also, below needed for box & move calc: #~ point_group.update_rects() pgbr = point_group.bounding_rect pgbr_w = pgbr.right - pgbr.left pgbr_h = pgbr.top - pgbr.bottom # and note - groups seem to add some sort of padding, so align to intern lines instead (instead of group BB edges) # get first (moveto) Point of first tf's line (align to that, instead of pgbr) - needed for 'boxing' below: tfline = point_group[0].objects[0] tmpep = tfline.paths[0].Segment(0)[2] tmpep_v = Point(0, 0) if havevars != 0: tmpep_v = varbl_group[0].objects[0].paths[0].Segment(0)[2] xmoveadj = tmpep.x - pgbr.left # adjustment due to group padding ymoveadj = -(tmpep_v.y - vgbr.top) # only for moving varbl_group # move rotated varbl_group below left of point_group xmove = 0 # -vgbr_w # looks ok like this xmove += xmoveadj # adjust due to group padding ymove = -pgbr_h ymove += ymoveadj # adjust due to group padding varbl_group.Translate(Point(xmove, ymove)) varbl_group.update_rects() vgbr = varbl_group.bounding_rect ## add the box label lxpad = 10 # box label x padding tfld_label = SimpleText(Translation(0, 0), inlabel) tfld_label.SetProperties(font=courfont, font_size=16) tfld_label.update_rects() # reposition # on y: center align tfld_label with center of point_group cp_pg = pgbr.center() tlbr = tfld_label.bounding_rect cp_tl = tlbr.center() ymove = -(cp_tl.y - cp_pg.y) # on x: <NO>align right edge of tfld_label + pad with left edge of point_group</NO> # center in respect to expected boxwidth instead # calc expected boxwidth first tlbr = tfld_label.bounding_rect tlbr_w = tlbr.right - tlbr.left boxwidth = lxpad + tlbr_w + lxpad # only title text label width + padding varbl_width = vgbr.right - vgbr.left if boxwidth < lxpad + varbl_width + lxpad: boxwidth = lxpad + varbl_width + lxpad #~ xmove = -(tlbr.right + lxpad - pgbr.left) # title text left aligned w/ right edge xmove = -((tlbr.center().x - pgbr.left) + boxwidth / 2) xmove += xmoveadj # adjust due to group padding tfld_label.Translate(Point(xmove, ymove)) tfld_label.update_rects() tlbr = tfld_label.bounding_rect # must reassign variable (though we won't need it anymore) ## create a box for point/varbl_group # start at upper left point of point_group BB; # go downleft, to <NO>upper left point of varbl_group BB</NO> # .. note - groups seem to add some sort of padding, so align to intern lines: # go downleft, to upper edge of varbl_group, and ([left edge of tfld_label] - pad) # get first (moveto) Point of first tf's line (align to that, instead of pgbr) tfline = point_group[0].objects[0] tmpep = tfline.paths[0].Segment(0)[2] start_x = tmpep.x # pgbr.left start_y = pgbr.top off_x = -(boxwidth) # -vgbr_w off_y = -pgbr_h trec = Rectangle(trafo=Trafo(off_x, 0, 0, off_y, start_x, start_y)) trec.SetProperties( line_width=2.0, fill_pattern=SolidPattern(CreateRGBColor(0.7, 0.7, 0.9)), ) trec.update_rects() sbdict['box'] = trec # now group all these # grouping goes: 1st on bottom, 2nd on top of it, etc.. retgrp = Group([trec, tfld_label, point_group, varbl_group]) retgrp.update_rects() # move lower left corner of retgrp to 0,0 rgbr = retgrp.bounding_rect retgrp.Translate(Point(-rgbr.left, -rgbr.bottom)) retgrp.update_rects() return (retgrp, sbdict)