def extract_bmp(self, numbmp, width, height): if not self.bmp_dict.has_key(numbmp): return chunk = self.bmp_dict[numbmp] palflag = ord(chunk.data[0x36]) [bmpsize] = struct.unpack('<L', chunk.data[42:46]) [bmpstart] = struct.unpack('<L', chunk.data[50:54]) numcol = (bmpstart - 82) / 3 if palflag == 5: numcol = 256 bmpstart2 = numcol * 4 + 54 bmpstart2 = struct.pack('<L', bmpstart2) if palflag == 3: #CMYK image self.bmpbuf = chunk.data[bmpstart + 40:] self.extracted_image = Image.fromstring('CMYK', (width, height), self.bmpbuf, 'raw', 'CMYK', 0, -1) elif palflag == 5: #Grayscale image self.bmpbuf = chunk.data[bmpstart + 40:] bytes = math.ceil(width / 2.0) * 2 self.extracted_image = Image.fromstring('L', (width, height), self.bmpbuf, 'raw', 'L', bytes, -1) elif palflag == 6: #Mono image bmpstart2 = numcol * 4 + 66 bmpstart2 = struct.pack('<L', bmpstart2) self.bmpbuf = 'BM' + chunk.data[42:50] + bmpstart2[ 0:4] + '\x28\x00\x00\x00' self.bmpbuf += chunk.data[62:72] + chunk.data[74:78] self.bmpbuf += '\x00\x00' + chunk.data[82:90] + '\x00\x00\x00\x00' self.bmpbuf += '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' self.bmpbuf += chunk.data[bmpstart + 40:] self.extracted_image = Image.open(StringIO.StringIO(self.bmpbuf)) self.extracted_image.load() # elif palflag == 1: #RGB # print 'width, height', (width, height) # self.bmpbuf=chunk.data[bmpstart+40:] # self.extracted_image = Image.fromstring('RGB', (width, height), self.bmpbuf, 'raw', 'BGR', 0, -1) else: self.bmpbuf = 'BM' + chunk.data[42:50] + bmpstart2[ 0:4] + '\x28\x00\x00\x00' self.bmpbuf += chunk.data[62:72] + chunk.data[74:78] self.bmpbuf += '\x00\x00' + chunk.data[82:90] + '\x00\x00\x00\x00' if numcol > 1: self.bmpbuf = self.bmpbuf + '\x00\x01\x00\x00\x00\x00\x00\x00' for i in range(numcol): self.bmpbuf = self.bmpbuf + chunk.data[122 + i * 3:125 + i * 3] + '\x00' self.bmpbuf += chunk.data[bmpstart + 40:] self.extracted_image = Image.open(StringIO.StringIO(self.bmpbuf)) self.extracted_image.load()
def extract_bmp(self, numbmp,width,height): if not self.bmp_dict.has_key(numbmp): return chunk=self.bmp_dict[numbmp] palflag = ord(chunk.data[0x36]) [bmpsize] = struct.unpack('<L',chunk.data[42:46]) [bmpstart] = struct.unpack('<L',chunk.data[50:54]) numcol = (bmpstart - 82)/3 if palflag == 5: numcol = 256 bmpstart2 = numcol*4 + 54 bmpstart2 = struct.pack('<L',bmpstart2) if palflag == 3:#CMYK image self.bmpbuf=chunk.data[bmpstart+40:] self.extracted_image = Image.fromstring('CMYK', (width, height), self.bmpbuf, 'raw', 'CMYK', 0, -1) elif palflag == 5:#Grayscale image self.bmpbuf=chunk.data[bmpstart+40:] bytes=math.ceil(width/2.0)*2 self.extracted_image = Image.fromstring('L', (width, height), self.bmpbuf, 'raw', 'L', bytes, -1) elif palflag == 6: #Mono image bmpstart2 = numcol*4 + 66 bmpstart2 = struct.pack('<L',bmpstart2) self.bmpbuf = 'BM'+chunk.data[42:50]+bmpstart2[0:4]+'\x28\x00\x00\x00' self.bmpbuf += chunk.data[62:72]+chunk.data[74:78] self.bmpbuf += '\x00\x00'+chunk.data[82:90]+'\x00\x00\x00\x00' self.bmpbuf += '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' self.bmpbuf += chunk.data[bmpstart+40:] self.extracted_image = Image.open(StringIO.StringIO(self.bmpbuf )) self.extracted_image.load() # elif palflag == 1: #RGB # print 'width, height', (width, height) # self.bmpbuf=chunk.data[bmpstart+40:] # self.extracted_image = Image.fromstring('RGB', (width, height), self.bmpbuf, 'raw', 'BGR', 0, -1) else: self.bmpbuf = 'BM'+chunk.data[42:50]+bmpstart2[0:4]+'\x28\x00\x00\x00' self.bmpbuf += chunk.data[62:72]+chunk.data[74:78] self.bmpbuf += '\x00\x00'+chunk.data[82:90]+'\x00\x00\x00\x00' if numcol > 1: self.bmpbuf = self.bmpbuf+'\x00\x01\x00\x00\x00\x00\x00\x00' for i in range (numcol): self.bmpbuf = self.bmpbuf+chunk.data[122+i*3:125+i*3]+'\x00' self.bmpbuf += chunk.data[bmpstart+40:] self.extracted_image = Image.open(StringIO.StringIO(self.bmpbuf )) self.extracted_image.load()
def cmsDoBitmapTransform(hTransform, inImage, inMode, outMode): """ The method provides PIL images support for color management. hTransform - a valid lcms transformation handle inImage - a valid PIL image object inMode, outMode - - predefined string constant (i.e. TYPE_RGB_8, TYPE_RGBA_8, TYPE_CMYK_8) or valid PIL mode Currently supports RGB, RGBA and CMYK modes only. Returns new PIL image object in outMode colorspace. """ if not inImage.mode == inMode: raise pycmsError, "incorrect inMode" if not inImage.mode in [TYPE_RGB_8, TYPE_RGBA_8, TYPE_CMYK_8]: raise pycmsError, "unsupported image type: %s"%inImage.mode if not inMode in [TYPE_RGB_8, TYPE_RGBA_8, TYPE_CMYK_8]: raise pycmsError, "unsupported inMode type: %s"%inMode if not outMode in [TYPE_RGB_8, TYPE_RGBA_8, TYPE_CMYK_8]: raise pycmsError, "unsupported outMode type: %s"%outMode w, h = inImage.size inImage.load() outImage=Image.new(outMode, (w, h)) _pycms.transformBitmap(hTransform, inImage.im, outImage.im, w, h) return outImage
def cmsDoBitmapTransform(hTransform, inImage, inMode, outMode): """ The method provides PIL images support for color management. hTransform - a valid lcms transformation handle inImage - a valid PIL image object inMode, outMode - - predefined string constant (i.e. TYPE_RGB_8, TYPE_RGBA_8, TYPE_CMYK_8) or valid PIL mode Currently supports RGB, RGBA and CMYK modes only. Returns new PIL image object in outMode colorspace. """ if not inImage.mode == inMode: raise pycmsError, "incorrect inMode" if not inImage.mode in [TYPE_RGB_8, TYPE_RGBA_8, TYPE_CMYK_8]: raise pycmsError, "unsupported image type: %s" % inImage.mode if not inMode in [TYPE_RGB_8, TYPE_RGBA_8, TYPE_CMYK_8]: raise pycmsError, "unsupported inMode type: %s" % inMode if not outMode in [TYPE_RGB_8, TYPE_RGBA_8, TYPE_CMYK_8]: raise pycmsError, "unsupported outMode type: %s" % outMode w, h = inImage.size inImage.load() outImage = Image.new(outMode, (w, h)) _pycms.transformBitmap(hTransform, inImage.im, outImage.im, w, h) return outImage
def render_preview(filename, startx, starty, width, height, resolution=None): import tempfile temp = tempfile.mktemp() try: # quote the filename so that it can have spaces and to avoid a # security hole filename = utils.sh_quote(filename) if resolution is None: resolution = config.preferences.eps_preview_resolution factor = resolution / 72.0 width = int(math.ceil(width * factor)) height = int(math.ceil(height * factor)) offx = -startx offy = -starty os.system(gs_command % locals()) image = Image.open(temp) image.load() return image finally: try: os.unlink(temp) except: pass
def render_preview(filename, startx, starty, width, height, resolution = None): import tempfile temp = tempfile.mktemp() try: # quote the filename so that it can have spaces and to avoid a # security hole filename = utils.sh_quote(filename) if resolution is None: resolution = config.preferences.eps_preview_resolution factor = resolution / 72.0 width = int(math.ceil(width * factor)) height = int(math.ceil(height * factor)) offx = -startx offy = -starty os.system(gs_command % locals()) image = Image.open(temp) image.load() return image finally: try: os.unlink(temp) except: pass
def raster_image(self, trafo, llx, lly, urx, ury, width, height, bits, mode, alpha, reserved, encoding, mask): if bits != 8 or mode not in (1, 3): self.add_message( _("Only images with 1 or 3 components " "and 8 bits/component supported")) self.skip_to_dsc("AI5_EndRaster") return decode = streamfilter.SubFileDecode(self.tokenizer.source, '%AI5_EndRaster') if encoding == 0: decode = streamfilter.HexDecode(decode) data_length = mode * width * height data = decode.read(data_length) #f = open("/tmp/dump.ppm", "w") #if mode == 1: # f.write("P5\n%d %d\n255\n" % (width, height)) #else: # f.write("P6\n%d %d\n255\n" % (width, height)) #f.write(data) #f.close() if mode == 1: mode = 'L' elif mode == 3: mode = 'RGB' elif mode == 4: mode == 'CMYK' image = Image.fromstring(mode, (width, height), data, 'raw', mode) self.image(image, apply(Trafo, tuple(trafo)))
def raster_image(self, trafo, llx, lly, urx, ury, width, height, bits, mode, alpha, reserved, encoding, mask): if bits != 8 or mode not in (1, 3): self.add_message(_("Only images with 1 or 3 components " "and 8 bits/component supported")) self.skip_to_dsc("AI5_EndRaster") return decode = streamfilter.SubFileDecode(self.tokenizer.source, '%AI5_EndRaster') if encoding == 0: decode = streamfilter.HexDecode(decode) data_length = mode * width * height data = decode.read(data_length) #f = open("/tmp/dump.ppm", "w") #if mode == 1: # f.write("P5\n%d %d\n255\n" % (width, height)) #else: # f.write("P6\n%d %d\n255\n" % (width, height)) #f.write(data) #f.close() if mode == 1: mode = 'L' elif mode == 3: mode = 'RGB' elif mode == 4: mode == 'CMYK' image = Image.fromstring(mode, (width, height), data, 'raw', mode) self.image(image, apply(Trafo, tuple(trafo)))
def getImageFromPixels(pixels, mode, width, height): """ Creates new image using provided pixel array. pixels - pixel array wrapped as a python object. mode - pixel array appropriate PIL mode. width, height - pixel array appropriate image size. Returns new PIL image object. """ image=Image.new(mode,(width,height)) pixel = image.getpixel((0,0)) bytes_per_pixel = 1 if type(pixel) is types.TupleType: bytes_per_pixel = len(pixel) if image.mode == TYPE_RGB_8: bytes_per_pixel = 4 _pycms.setImagePixels(pixels, image.im, width, height, bytes_per_pixel) return image
def getImageFromPixels(pixels, mode, width, height): """ Creates new image using provided pixel array. pixels - pixel array wrapped as a python object. mode - pixel array appropriate PIL mode. width, height - pixel array appropriate image size. Returns new PIL image object. """ image = Image.new(mode, (width, height)) pixel = image.getpixel((0, 0)) bytes_per_pixel = 1 if type(pixel) is types.TupleType: bytes_per_pixel = len(pixel) if image.mode == TYPE_RGB_8: bytes_per_pixel = 4 _pycms.setImagePixels(pixels, image.im, width, height, bytes_per_pixel) return image
def image(self, attrs): if self.in_defs: return href = attrs['xlink:href'] image = None if href[:5] == 'data:': # embed image coma = href.find(',') semicolon = href.find(';') mime = href[5:semicolon] if mime in ['image/png','image/jpg','image/jpeg','image/gif','image/bmp']: import base64 image = Image.open(StringIO(base64.decodestring(href[coma:]))) if image.mode == 'P': image = image.convert('RGBA') else: # linked image import urlparse, urllib path = urlparse.urlparse(href).path href = urllib.unquote(path.encode('utf-8')) path = os.path.realpath(href) if os.path.isfile(path): image = load_image(path).image else: self.loader.add_message(_('Cannot find linked image file %s') % path) if image: x, y = self.user_point(attrs.get('x', '0'), attrs.get('y', '0')) width = self.user_length(attrs['width']) scalex = width / image.size[0] height = self.user_length(attrs['height']) scaley = -height / image.size[1] self.parse_attrs(attrs) self.set_loader_style() t = self.trafo(Trafo(scalex, 0, 0, scaley, x, y + height)) self._print('image', t) self.loader.image(image, t)
def axial_gradient(self, properties, rect): pattern = properties.fill_pattern vx, vy = pattern.Direction() angle = atan2(vy, vx) - pi / 2 center = rect.center() rot = Rotation(angle, center) left, bottom, right, top = rot(rect) trafo = rot(Translation(center)) image = Image.new('RGB', (1, 200)) border = int(round(100 * pattern.Border())) result=[] colors=pattern.Gradient().Colors() for color in colors: result.append((color[0],color[1].RGB())) _sketch.fill_axial_gradient(image.im, result, 0, border, 0, 200 - border) self.pdf.saveState() apply(self.pdf.transform, trafo.coeff()) self.pdf.drawInlineImage(image, (left - right) / 2, (bottom - top) / 2, right - left, top - bottom) self.pdf.restoreState()
def axial_gradient(self, properties, rect): pattern = properties.fill_pattern vx, vy = pattern.Direction() angle = atan2(vy, vx) - pi / 2 center = rect.center() rot = Rotation(angle, center) left, bottom, right, top = rot(rect) trafo = rot(Translation(center)) image = Image.new('RGB', (1, 200)) border = int(round(100 * pattern.Border())) result = [] colors = pattern.Gradient().Colors() for color in colors: result.append((color[0], color[1].RGB())) _sketch.fill_axial_gradient(image.im, result, 0, border, 0, 200 - border) self.pdf.saveState() apply(self.pdf.transform, trafo.coeff()) self.pdf.drawInlineImage(image, (left - right) / 2, (bottom - top) / 2, right - left, top - bottom) self.pdf.restoreState()
def _read_image(self,fp): if sys.platform[0:4] == 'java': from javax.imageio import ImageIO return ImageIO.read(fp) else: return Image.open(fp)
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 textobj = SimpleText() width = width + use_font.TextCoordBox( text, font_size, textobj.properties)[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, textobj.properties)[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, textobj.properties)[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, textobj.properties)[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, textobj.properties)[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 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 textobj=SimpleText() width = width + use_font.TextCoordBox(text, font_size, textobj.properties)[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, textobj.properties)[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, textobj.properties)[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, textobj.properties)[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, textobj.properties)[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