Beispiel #1
0
def img_save():
    img_path = PATH.rsplit('.', 1)[0]
    font = TTFont(
        PATH)  # it would work just as well with fontTools.t1Lib.T1Font
    glyf = font['glyf']
    if not os.path.exists(img_path):
        os.makedirs(img_path)
    for glyphName in glyf.keys():
        gs = font.getGlyphSet()
        pen = ReportLabPen(gs, Path(fillColor=colors.black, strokeWidth=1))
        g = gs[glyphName]
        g.draw(pen)
        # 调整图片大小
        w, h = 800, 800
        g = Group(pen.path)
        g.translate(10, 200)
        g.scale(0.3, 0.3)

        d = Drawing(w, h)
        d.add(g)

        image = renderPM.drawToPIL(d)
        little_image = image.resize((180, 180))
        fromImage = Image.new('RGBA', (360, 360), color=(255, 255, 255))
        fromImage.paste(little_image, (0, 0))
        # fromImage.show()
        glyphName = glyphName.replace('uni', '&#x')
        imageFile = img_path + "/%s.png" % glyphName
        fromImage.save(imageFile)
        break
Beispiel #2
0
def ttf_ocr(font, key=None):
    gs = font.getGlyphSet()
    keys = [key for key in gs.keys() if key.startswith("uni")] if key is None else [key]
    c = []
    for i, key in enumerate(keys):
        if key not in gs:
            logger.info("No this key: %s" % key)
            c.append("")
            continue
        pen = ReportLabPen(gs, Path(fillColor=colors.black, strokeWidth=0.01))
        g = gs[key]
        g.draw(pen)
        w, h = 50, 50
        g = Group(pen.path)
        g.translate(10, 10)
        g.scale(0.02, 0.02)
        d = Drawing(w, h)
        d.add(g)
        renderPM.drawToFile(d, png_file.name, fmt="PNG")
        result = os.popen("tesseract %s stdout -l chi_sim -psm 5" % png_file.name).read().strip().decode("utf-8",
                                                                                                         "ignore")
        if len(result) != 1:
            result = os.popen("tesseract %s stdout -l chi_sim -psm 8" % png_file.name).read().strip().decode("utf-8",
                                                                                                             "ignore")
        logger.info("key: %s, result: %s" % (key, result))
        c.append(result)
    if key is not None:
        return c[0]
    return c
Beispiel #3
0
 def __init__(self,width=224,height=124,*args,**kw):
     Drawing.__init__(self,width,height,*args,**kw)
     points = [122.0, 87.0, 122.0, 88.0, 123.0, 88.0, 123.0, 89.0, 124.0, 89.0, 124.0, 90.0, 126.0, 90.0, 126.0, 89.0, 128.0, 88.0, 128.0, 89.0, 129.0, 89.0, 129.0, 91.0, 128.0, 91.0, 128.0, 92.0, 130.0, 99.0, 130.0, 100.0, 129.0, 100.0, 126.0, 103.0, 125.0, 103.0, 125.0, 104.0, 126.0, 106.0, 130.0, 87.0, 129.0, 87.0, 129.0, 86.0, 126.0, 86.0, 126.0, 87.0]
     grp = Group(Polygon(points, fillColor=toColor('red')))
     grp.scale(1, -1)
     grp.translate(0, -124)
     self.add(grp)
        def _rawDraw(self):
            _text = self._text
            self._text = _text or ''
            self.computeSize()
            self._text = _text
            g = Group()
            g.translate(self.x + self.dx, self.y + self.dy)
            g.rotate(self.angle)

            x = self._left

            # paint box behind text just in case they
            # fill it
            if self.boxFillColor or (self.boxStrokeColor and self.boxStrokeWidth):
                g.add(Rect( self._left-self.leftPadding,
                            self._bottom-self.bottomPadding,
                            self._width,
                            self._height,
                            strokeColor=self.boxStrokeColor,
                            strokeWidth=self.boxStrokeWidth,
                            fillColor=self.boxFillColor)
                            )
            g1 = Group()
            g1.translate(x,self._top-self._eheight)
            g1.add(self._ddf(self._obj))
            g.add(g1)
            return g
Beispiel #5
0
 def ttf_to_image(self):
     """
     将ttf字体文件的字体绘制在Image对象上
     :return:
     """
     glyphset = self.font.getGlyphSet()
     size = (BASE_BACKGOUND_WIDTH * FONT_NUMS_PER_LINE,
             ceil(len(self.glyphnames) / FONT_NUMS_PER_LINE) * BASE_BACKGOUND_HEIGHT)  # 背景图片尺寸
     image = Image.new("RGB", size=size, color=(255, 255, 255))  # 初始化背景图片
     name_list, image_dict = [], {}
     for index, glyphname in enumerate(self.glyphnames):
         if glyphname[0] in ['.', 'g'] or glyphname in self.ignore_names:  # 跳过'.notdef', '.null'
             continue
         g = glyphset[glyphname]
         pen = ReportLabPen(self.glyphnames, Path(fillColor=colors.black, strokeWidth=1))
         g.draw(pen)
         # w, h = g.width, g.width
         w, h = g.width if g.width > 1000 else 1000, g.width if g.width > 1000 else 1000
         g = Group(pen.path)
         g.translate(0, 200)
         d = Drawing(w, h)
         d.add(g)
         im = renderPM.drawToPIL(d, dpi=72).resize((FONT_WIDTH, FONT_HEIGHT))
         box = (
             (index % FONT_NUMS_PER_LINE) * BASE_BACKGOUND_WIDTH,
             (index // FONT_NUMS_PER_LINE) * BASE_BACKGOUND_HEIGHT)
         image.paste(im, box=box)
         name_list.append(glyphname)
         image_dict[glyphname] = im
     return image, name_list, image_dict
Beispiel #6
0
    def convertImage(self, node):
        getAttr = node.getAttribute
        x, y, width, height = map(getAttr, ('x', 'y', "width", "height"))
        x, y, width, height = map(self.attrConverter.convertLength, (x, y, width, height))
        xlink_href = node.attrib.get('{http://www.w3.org/1999/xlink}href')

        magic_re = r"^data:image/(jpeg|png);base64"
        match = re.match(magic_re, xlink_href)
        if match:
            img_format = match.groups()[0]
            image_data = base64.decodestring(xlink_href[(match.span(0)[1] + 1):].encode('ascii'))
            _, path = tempfile.mkstemp(suffix='.%s' % img_format)
            with open(path, 'wb') as fh:
                fh.write(image_data)
            img = Image(int(x), int(y + height), int(width), int(height), path)
            # this needs to be removed later, not here...
            # if exists(path): os.remove(path)
        else:
            xlink_href = os.path.join(os.path.dirname(self.svg_source_file), xlink_href)
            img = Image(int(x), int(y + height), int(width), int(height), xlink_href)
            try:
                # this will catch invalid image
                PDFImage(xlink_href, 0, 0)
            except IOError:
                logger.error("Unable to read the image %s. Skipping..." % img.path)
                return None
        group = Group(img)
        group.translate(0, (x + height) * 2)
        group.scale(1, -1)
        return group
Beispiel #7
0
    def renderSvg(self, node, outermost=False):
        getAttr = node.getAttribute

        _saved_preserve_space = self.shape_converter.preserve_space
        self.shape_converter.preserve_space = getAttr("{%s}space" % XML_NS) == 'preserve'

        group = Group()
        for child in node.getchildren():
            self.renderNode(child, group)
        self.shape_converter.preserve_space = _saved_preserve_space

        if not outermost:
            x, y = map(getAttr, ("x", "y"))
            x, y = map(self.attrConverter.convertLength, (x, y))
            if x or y:
                group.translate(x or 0, y or 0)

            view_box = self.get_box(node)
            if view_box:
                x_scale, y_scale = 1, 1
                width, height = map(getAttr, ("width", "height"))
                width, height = map(self.attrConverter.convertLength, (width, height))
                if view_box.height != height:
                    y_scale = height / view_box.height
                if view_box.width != width:
                    x_scale = width / view_box.width
                group.scale(x_scale, y_scale)
        return group
Beispiel #8
0
def makeCircularString(x, y, radius, angle, text, fontName, fontSize, inside=0, G=None,textAnchor='start'):
    '''make a group with circular text in it'''
    if not G: G = Group()

    angle %= 360
    pi180 = pi/180
    phi = angle*pi180
    width = stringWidth(text, fontName, fontSize)
    sig = inside and -1 or 1
    hsig = sig*0.5
    sig90 = sig*90

    if textAnchor!='start':
        if textAnchor=='middle':
            phi += sig*(0.5*width)/radius
        elif textAnchor=='end':
            phi += sig*float(width)/radius
        elif textAnchor=='numeric':
            phi += sig*float(numericXShift(textAnchor,text,width,fontName,fontSize,None))/radius

    for letter in text:
        width = stringWidth(letter, fontName, fontSize)
        beta = float(width)/radius
        h = Group()
        h.add(String(0, 0, letter, fontName=fontName,fontSize=fontSize,textAnchor="start"))
        h.translate(x+cos(phi)*radius,y+sin(phi)*radius)    #translate to radius and angle
        h.rotate((phi-hsig*beta)/pi180-sig90)               # rotate as needed
        G.add(h)                                            #add to main group
        phi -= sig*beta                                     #increment

    return G
Beispiel #9
0
 def __init__(self,width=224,height=124,*args,**kw):
     Drawing.__init__(self,width,height,*args,**kw)
     points = [122.0, 87.0, 122.0, 88.0, 123.0, 88.0, 123.0, 89.0, 124.0, 89.0, 124.0, 90.0, 126.0, 90.0, 126.0, 89.0, 128.0, 88.0, 128.0, 89.0, 129.0, 89.0, 129.0, 91.0, 128.0, 91.0, 128.0, 92.0, 130.0, 99.0, 130.0, 100.0, 129.0, 100.0, 126.0, 103.0, 125.0, 103.0, 125.0, 104.0, 126.0, 106.0, 130.0, 87.0, 129.0, 87.0, 129.0, 86.0, 126.0, 86.0, 126.0, 87.0]
     grp = Group(Polygon(points, fillColor=toColor('red')))
     grp.scale(1, -1)
     grp.translate(0, -124)
     self.add(grp)
Beispiel #10
0
    def convertText(self, node):
        attrConv = self.attrConverter
        x, y = map(node.getAttribute, ('x', 'y'))
        x, y = map(attrConv.convertLength, (x, y))
        xml_space = node.getAttribute("{%s}space" % XML_NS)
        if xml_space:
            preserve_space = xml_space == 'preserve'
        else:
            preserve_space = self.preserve_space

        gr = Group()

        frag_lengths = []

        dx0, dy0 = 0, 0
        x1, y1 = 0, 0
        ff = attrConv.findAttr(node, "font-family") or "Helvetica"
        ff = attrConv.convertFontFamily(ff)
        fs = attrConv.findAttr(node, "font-size") or "12"
        fs = attrConv.convertLength(fs)
        for c in itertools.chain([node], node.getchildren()):
            has_x = False
            dx, dy = 0, 0
            baseLineShift = 0
            if node_name(c) == 'text':
                text = self.clean_text(c.text, preserve_space)
                if not text:
                    continue
            elif node_name(c) == 'tspan':
                text = self.clean_text(c.text, preserve_space)
                if not text:
                    continue
                x1, y1, dx, dy = [c.attrib.get(name, '') for name in ("x", "y", "dx", "dy")]
                has_x = x1 != ''
                x1, y1, dx, dy = map(attrConv.convertLength, (x1, y1, dx, dy))
                dx0 = dx0 + dx
                dy0 = dy0 + dy
                baseLineShift = c.attrib.get("baseline-shift", '0')
                if baseLineShift in ("sub", "super", "baseline"):
                    baseLineShift = {"sub":-fs/2, "super":fs/2, "baseline":0}[baseLineShift]
                else:
                    baseLineShift = attrConv.convertLength(baseLineShift, fs)
            else:
                continue

            frag_lengths.append(stringWidth(text, ff, fs))
            new_x = x1 if has_x else sum(frag_lengths[:-1])
            shape = String(x + new_x, y - y1 - dy0 + baseLineShift, text)
            self.applyStyleOnShape(shape, node)
            if node_name(c) == 'tspan':
                self.applyStyleOnShape(shape, c)

            gr.add(shape)

        gr.scale(1, -1)
        gr.translate(0, -2*y)

        return gr
Beispiel #11
0
    def _rawDraw(self):
        _text = self._text
        self._text = _text or ""
        self.computeSize()
        self._text = _text
        g = Group()
        g.translate(self.x + self.dx, self.y + self.dy)
        g.rotate(self.angle)

        y = self._top - self._leading * self._baselineRatio
        textAnchor = self._getTextAnchor()
        if textAnchor == "start":
            x = self._left
        elif textAnchor == "middle":
            x = self._left + self._ewidth * 0.5
        else:
            x = self._right

        # paint box behind text just in case they
        # fill it
        if self.boxFillColor or (self.boxStrokeColor and self.boxStrokeWidth):
            g.add(
                Rect(
                    self._left - self.leftPadding,
                    self._bottom - self.bottomPadding,
                    self._width,
                    self._height,
                    strokeColor=self.boxStrokeColor,
                    strokeWidth=self.boxStrokeWidth,
                    fillColor=self.boxFillColor,
                )
            )

        fillColor, fontName, fontSize = self.fillColor, self.fontName, self.fontSize
        strokeColor, strokeWidth, leading = self.strokeColor, self.strokeWidth, self._leading
        svgAttrs = getattr(self, "_svgAttrs", {})
        if strokeColor:
            for line in self._lines:
                s = _text2Path(line, x, y, fontName, fontSize, textAnchor)
                s.fillColor = fillColor
                s.strokeColor = strokeColor
                s.strokeWidth = strokeWidth
                g.add(s)
                y -= leading
        else:
            for line in self._lines:
                s = String(x, y, line, _svgAttrs=svgAttrs)
                s.textAnchor = textAnchor
                s.fontName = fontName
                s.fontSize = fontSize
                s.fillColor = fillColor
                g.add(s)
                y -= leading

        return g
Beispiel #12
0
    def draw(self):
        _text = self._text
        self._text = _text or ''
        self.computeSize()
        self._text = _text
        g = Group()
        g.translate(self.x + self.dx, self.y + self.dy)
        g.rotate(self.angle)

        y = self._top - self.fontSize
        textAnchor = self._getTextAnchor()
        if textAnchor == 'start':
            x = self._left
        elif textAnchor == 'middle':
            x = self._left + self._ewidth * 0.5
        else:
            x = self._right

        # paint box behind text just in case they
        # fill it
        if self.boxFillColor or (self.boxStrokeColor and self.boxStrokeWidth):
            g.add(
                Rect(
                    self._left - self.leftPadding,
                    self._bottom - self.bottomPadding,
                    self._width,
                    self._height,
                    strokeColor=self.boxStrokeColor,
                    strokeWidth=self.boxStrokeWidth,
                    fillColor=self.boxFillColor))

        fillColor, fontName, fontSize = self.fillColor, self.fontName, self.fontSize
        strokeColor, strokeWidth, leading = self.strokeColor, self.strokeWidth, (
            self.leading or 1.2 * fontSize)
        if strokeColor:
            for line in self._lines:
                s = _text2Path(line, x, y, fontName, fontSize, textAnchor)
                s.fillColor = fillColor
                s.strokeColor = strokeColor
                s.strokeWidth = strokeWidth
                g.add(s)
                y = y - leading
        else:
            for line in self._lines:
                s = String(x, y, line)
                s.textAnchor = textAnchor
                s.fontName = fontName
                s.fontSize = fontSize
                s.fillColor = fillColor
                g.add(s)
                y = y - leading

        return g
Beispiel #13
0
    def _rawDraw(self):
        _text = self._text
        self._text = _text or ''
        self.computeSize()
        self._text = _text
        g = Group()
        g.translate(self.x + self.dx, self.y + self.dy)
        g.rotate(self.angle)

        y = self._top - self._leading * self._baselineRatio
        textAnchor = self._getTextAnchor()
        if textAnchor == 'start':
            x = self._left
        elif textAnchor == 'middle':
            x = self._left + self._ewidth * 0.5
        else:
            x = self._right

        # paint box behind text just in case they
        # fill it
        if self.boxFillColor or (self.boxStrokeColor and self.boxStrokeWidth):
            g.add(
                Rect(self._left - self.leftPadding,
                     self._bottom - self.bottomPadding,
                     self._width,
                     self._height,
                     strokeColor=self.boxStrokeColor,
                     strokeWidth=self.boxStrokeWidth,
                     fillColor=self.boxFillColor))

        fillColor, fontName, fontSize = self.fillColor, self.fontName, self.fontSize
        strokeColor, strokeWidth, leading = self.strokeColor, self.strokeWidth, self._leading
        svgAttrs = getattr(self, '_svgAttrs', {})
        if strokeColor:
            for line in self._lines:
                s = _text2Path(line, x, y, fontName, fontSize, textAnchor)
                s.fillColor = fillColor
                s.strokeColor = strokeColor
                s.strokeWidth = strokeWidth
                g.add(s)
                y -= leading
        else:
            for line in self._lines:
                s = String(x, y, line, _svgAttrs=svgAttrs)
                s.textAnchor = textAnchor
                s.fontName = fontName
                s.fontSize = fontSize
                s.fillColor = fillColor
                g.add(s)
                y -= leading

        return g
def group_demo():
    drawing = Drawing(width=400, height=200)
    radius = 25
    circles = Group(Circle(50, 40, radius, fillColor=colors.blue),
                    Circle(75, 40, radius, fillColor=colors.red),
                    Circle(100, 40, radius, fillColor=colors.green),
                    Circle(125, 40, radius, fillColor=colors.yellow),
                    String(75, 5, 'Circles'))
    drawing.add(circles)

    more_circles = Group(circles)
    more_circles.translate(75, 55)
    more_circles.rotate(35)
    drawing.add(more_circles)

    drawing.save(formats=['pdf'], outDir='.', fnRoot='group_demo')
Beispiel #15
0
    def one_to_image(self, glyph_name):
        glyphset = self.font.getGlyphSet()
        try:
            glyph = glyphset[glyph_name]
        except KeyError as e:
            raise KeyError("{} dont't in {}".format(glyph_name,
                                                    self.font_file_name))

        pen = ReportLabPen(self.glyphnames,
                           Path(fillColor=colors.black, strokeWidth=1))
        glyph.draw(pen)
        w, h = glyph.width if glyph.width > 1000 else 1000, glyph.width if glyph.width > 1000 else 1000
        d = Drawing(w, h)
        g = Group(pen.path)
        g.translate(0, 150)
        d.add(g)
        im = renderPM.drawToPIL(d, dpi=72).resize((FONT_WIDTH, FONT_HEIGHT))
        return im
    def draw_one(self, unicode, font_io):
        ttf_font = TTFont(font_io)
        glyphSet = ttf_font.getGlyphSet()
        if unicode not in glyphSet:
            return None
        glyph = glyphSet[unicode]
        pen = reportLabPen.ReportLabPen(
            glyphSet, Path(fillColor=colors.black, strokeWidth=1))
        glyph.draw(pen)

        w, h = glyph.width, glyph._glyph.yMax - glyph._glyph.yMin
        yOffset = -glyph._glyph.yMin * \
                  self.font_scale + h * (1 - self.font_scale) / 2
        glyph = Group(pen.path)
        glyph.translate(w * (1 - self.font_scale) / 2, yOffset)
        glyph.scale(self.font_scale, self.font_scale)
        draw = Drawing(w, h)
        draw.add(glyph)
        PIL_image = renderPM.drawToPIL(draw)
        return PIL_image
Beispiel #17
0
def ttfToImage(fontName, imagePath, fmt="png"):
    font = TTFont(fontName)
    gs = font.getGlyphSet()
    glyphNames = font.getGlyphNames()
    for i in glyphNames:
        if i[0] == '.':  #Ìø¹ý'.notdef', '.null'
            continue

        g = gs[i]
        pen = ReportLabPen(gs, Path(fillColor=colors.red, strokeWidth=5))
        g.draw(pen)
        w, h = g.width, g.width
        g = Group(pen.path)
        g.translate(0, 200)

        d = Drawing(w, h)
        d.add(g)
        imageFile = imagePath + "/" + i + ".png"
        renderPM.drawToFile(d, imageFile, fmt)

        print(i)
Beispiel #18
0
    def _draw(self):
        """
        :param font_path: 下载的web 字体所在目录
        :param image_path: 转换为image后所在目录
        :return:返回font 对应的编码列表

        """
        import os
        import shutil

        shutil.rmtree(os.path.join(os.path.abspath('.'), "web_font",
                                   "image"))  # 能删除该文件夹和文件夹下所有文件
        os.mkdir(os.path.join(os.path.abspath('.'), "web_font", "image"))
        from fontTools.ttLib import TTFont
        from reportlab.lib import colors
        font = TTFont(
            os.path.join(os.path.abspath('.'), "web_font", "stonefont.woff")
        )  # it would work just as well with fontTools.t1Lib.T1Font
        gs = font.getGlyphSet()
        w, h = 40, 40
        keys = gs.keys()[2:]
        for glyphName in keys:
            pen = FontPen(gs, Path(fillColor=colors.red, strokeWidth=0.01))
            imageFile = "%s.png" % glyphName
            g = gs[glyphName]
            g.draw(pen)
            from reportlab.graphics import renderPM
            from reportlab.graphics.shapes import Group, Drawing

            g = Group(pen.path)
            g.translate(10, 13)
            g.scale(0.02, 0.02)
            d = Drawing(w, h)
            d.add(g)
            renderPM.drawToFile(d,
                                os.path.join(os.path.abspath('.'), "web_font",
                                             "image", imageFile),
                                fmt="PNG",
                                dpi=100)
        return keys
Beispiel #19
0
 def add_vert_line(self, x, y, color, label):
     i = self.x_to_i(x)
     j = self.y_to_j(y)
     self.flowable.add(
         Line(
             i, self.j_plot_offset,
             i, j,
             strokeColor=color,
             strokeWidth=0.75))
     if not label:
         return
     group = Group(
         String(
             0, 0,
             label,
             fontSize=self.font_size,
             fontName='Helvetica',
             textAnchor='start',
             fillColor=color))
     group.translate(i + 1, j + 2)
     group.rotate(90)
     self.flowable.add(group)
Beispiel #20
0
def ttfToImage(fontName, imagePath, fmt="png"):
    font = TTFont(fontName)
    gs = font.getGlyphSet()
    glyphNames = font.getGlyphNames()

    m_dict = font.getBestCmap()

    unicode_list = []
    gs_key=[]
    for key, value in m_dict.items():
        unicode_list.append(key)
        gs_key.append(value)
    char_list = [chr(ch_unicode) for ch_unicode in unicode_list]
    #2500-29000 FZSONG_ZhongHuaSongPlane00_2021120120211201171438.ttf
    # 275 FZSONG_ZhongHuaSongPlane02_2021120120211201171459.ttf

    for i in range(len(char_list)):
        if fontName=='FZSONG_ZhongHuaSongPlane00_2021120120211201171438.ttf' and (i<2500 or i>29000):
            continue
        if fontName=='FZSONG_ZhongHuaSongPlane02_2021120120211201171459.ttf' and (i<275 or i>100000000):
            continue
        thechr=char_list[i]
        print(thechr)
        gs_ind=gs_key[i]
        if gs_ind[0] == '.':  # 跳过'.notdef', '.null'
            continue
        g = gs[gs_ind]
        pen = ReportLabPen(gs, Path(fillColor=colors.black, strokeWidth=5))
        g.draw(pen)
        w, h = g.width, g.width
        # w = 4048
        # h = 4048
        g = Group(pen.path)
        g.translate(0, 170)

        d = Drawing(w, h)
        d.add(g)
        imageFile = imagePath + "/" + thechr + ".png"
        renderPM.drawToFile(d, imageFile, fmt)
 def process(O, grid_ij, xy_max, label, data, label_font_size=12):
   if (reportlab is None): return
   from reportlab.graphics.shapes import Group, String
   lp = O.line_plot(xy_max, data=data, label_font_size=label_font_size)
   gr = Group(lp)
   i,j = grid_ij
   assert 0 <= i < O.grid[0]
   assert 0 <= j < O.grid[1]
   i = O.grid[0] - 1 - i
   tx, ty = O.margin + j * (O.page_size[0] - 2 * O.margin) / O.grid[1] \
                     - j * O.more_narrow_shift, \
            O.margin + i * (O.page_size[1] - 2 * O.margin
                                           - O.top_label_space) / O.grid[0]
   gr.translate(tx, ty)
   O.top_group.add(gr)
   O.top_group.add(String(
     tx+lp.x+lp.width*0.5,
     ty+lp.y+lp.height*1.05,
     label,
     fontSize=label_font_size,
     textAnchor="middle"))
   if (i == 0 and j == 0):
     O.top_group.add(String(
       tx+lp.x+lp.width*0.5,
       ty+lp.y-lp.height*0.3,
       u"RMSD start (\u00C5)",
       fontSize=label_font_size,
       textAnchor="middle"))
     gr = Group(String(
       0,
       0,
       u"RMSD final (\u00C5)",
       fontSize=label_font_size,
       textAnchor="middle"))
     gr.rotate(90)
     gr.translate(
       ty+lp.y+lp.height*0.5,
       -(tx+lp.x-lp.width*0.15))
     O.top_group.add(gr)
Beispiel #22
0
 def process(O, grid_ij, xy_max, label, data, label_font_size=12):
     if (reportlab is None): return
     from reportlab.graphics.shapes import Group, String
     lp = O.line_plot(xy_max, data=data, label_font_size=label_font_size)
     gr = Group(lp)
     i, j = grid_ij
     assert 0 <= i < O.grid[0]
     assert 0 <= j < O.grid[1]
     i = O.grid[0] - 1 - i
     tx, ty = O.margin + j * (O.page_size[0] - 2 * O.margin) / O.grid[1] \
                       - j * O.more_narrow_shift, \
              O.margin + i * (O.page_size[1] - 2 * O.margin
                                             - O.top_label_space) / O.grid[0]
     gr.translate(tx, ty)
     O.top_group.add(gr)
     O.top_group.add(
         String(tx + lp.x + lp.width * 0.5,
                ty + lp.y + lp.height * 1.05,
                label,
                fontSize=label_font_size,
                textAnchor="middle"))
     if (i == 0 and j == 0):
         O.top_group.add(
             String(tx + lp.x + lp.width * 0.5,
                    ty + lp.y - lp.height * 0.3,
                    u"RMSD start (\u00C5)",
                    fontSize=label_font_size,
                    textAnchor="middle"))
         gr = Group(
             String(0,
                    0,
                    u"RMSD final (\u00C5)",
                    fontSize=label_font_size,
                    textAnchor="middle"))
         gr.rotate(90)
         gr.translate(ty + lp.y + lp.height * 0.5,
                      -(tx + lp.x - lp.width * 0.15))
         O.top_group.add(gr)
    def draw_all(self, font_io):
        ttf_font = TTFont(font_io)
        glyphSet = ttf_font.getGlyphSet()
        font_image_dict = {}
        for glyphName in glyphSet.keys():
            if (not glyphName.startswith('uni')):
                continue
            pen = reportLabPen.ReportLabPen(
                glyphSet, Path(fillColor=colors.black, strokeWidth=1))
            glyph = glyphSet[glyphName]
            glyph.draw(pen)

            w, h = glyph.width, glyph._glyph.yMax - glyph._glyph.yMin
            yOffset = -glyph._glyph.yMin * \
                      self.font_scale + h * (1 - self.font_scale) / 2
            glyph = Group(pen.path)
            glyph.translate(w * (1 - self.font_scale) / 2, yOffset)
            glyph.scale(self.font_scale, self.font_scale)
            draw = Drawing(w, h)
            draw.add(glyph)
            PIL_image = renderPM.drawToPIL(draw)
            font_image_dict[glyphName] = PIL_image
        return font_image_dict
Beispiel #24
0
    def convertImage(self, node):
        if not haveImages:
            logger.warning(
                "Unable to handle embedded images. Maybe the pillow library is missing?"
            )
            return None

        getAttr = node.getAttribute
        x, y, width, height = map(getAttr, ('x', 'y', "width", "height"))
        x, y, width, height = map(self.attrConverter.convertLength,
                                  (x, y, width, height))

        image = node._resolved_target
        is_raster = isinstance(image, str)  # A path to a file
        if is_raster:
            image = Image(int(x), int(y + height), int(width), int(height),
                          image)

        group = Group(image)
        if is_raster:
            group.translate(0, (y + height) * 2)
            group.scale(1, -1)
        return group
Beispiel #25
0
    def draw(self, dx=5, dy=300, auto_width=500, auto_height=500):
        """
        绘图操作
        :param dx: 图片绘图位置
        :param dy:  图片绘图位置
        :param auto_width: 自适应图片宽度(调节字体)
        :param auto_height: 自适应图片高度(调节字体)
        :return:
        """

        def reverse_dict(data: dict):
            out = {}
            for k, v in data.items():
                out[str(v)] = str(k)

            return out

        font = TTFont(self.fontName)
        img_dict = font['cmap'].tables[2].ttFont.tables['cmap'].tables[1].cmap
        img_dict = reverse_dict(img_dict)
        gs = font.getGlyphSet()
        glyphNames = font.getGlyphNames()
        for i in glyphNames:
            name = self.key(img_dict.get(i))
            if name == None:
                continue
            g = gs[i]
            pen = ReportLabPen(gs, Path(fillColor=colors.black, strokeWidth=10))
            g.draw(pen)
            w, h = g.width, g.width
            g = Group(pen.path)
            g.translate(dx, dy)
            d = Drawing(w + auto_width, h + auto_height)
            d.add(g)
            imageFile = self.imagePath + "/" + str(name) + "." + self.fmt
            renderPM.drawToFile(d, imageFile, self.fmt)
Beispiel #26
0
	glyphName = sys.argv[2]
	if (len(sys.argv) > 3):
		imageFile = sys.argv[3]
	else:
		imageFile = "%s.png" % glyphName

	font = TTFont(path)  # it would work just as well with fontTools.t1Lib.T1Font
	gs = font.getGlyphSet()
	pen = ReportLabPen(gs, Path(fillColor=colors.black, strokeWidth=0))
	#pen = ReportLabPen(gs, Path(fillColor=colors.red, strokeWidth=5))
	g = gs[glyphName]
	g.draw(pen)

	w, h = g.width, 1000
	from reportlab.graphics import renderPM
	from reportlab.graphics.shapes import Group, Drawing, scale

	# Everything is wrapped in a group to allow transformations.
	g = Group(pen.path)
	g.translate(10, 10)
	#g.scale(0.9, 0.9)
	#g.scale(0.3, 0.3)
	g.scale(0.8, 0.8)

	d = Drawing(w, h)
	d.add(g)

	from reportlab.lib.colors import white
	from reportlab.lib.colors import green
	renderPM.drawToFile(d, imageFile, fmt="TIFF", configPIL={'transparent':white})
Beispiel #27
0
class Renderer:
    LINK = '{http://www.w3.org/1999/xlink}href'

    SVG_NS = '{http://www.w3.org/2000/svg}'
    SVG_ROOT        = SVG_NS + 'svg'
    SVG_A           = SVG_NS + 'a'
    SVG_G           = SVG_NS + 'g'
    SVG_TITLE       = SVG_NS + 'title'
    SVG_DESC        = SVG_NS + 'desc'
    SVG_DEFS        = SVG_NS + 'defs'
    SVG_SYMBOL      = SVG_NS + 'symbol'
    SVG_USE         = SVG_NS + 'use'
    SVG_RECT        = SVG_NS + 'rect'
    SVG_CIRCLE      = SVG_NS + 'circle'
    SVG_ELLIPSE     = SVG_NS + 'ellipse'
    SVG_LINE        = SVG_NS + 'line'
    SVG_POLYLINE    = SVG_NS + 'polyline'
    SVG_POLYGON     = SVG_NS + 'polygon'
    SVG_PATH        = SVG_NS + 'path'
    SVG_TEXT        = SVG_NS + 'text'
    SVG_TSPAN       = SVG_NS + 'tspan'
    SVG_IMAGE       = SVG_NS + 'image'

    SVG_NODES = frozenset((
        SVG_ROOT, SVG_A, SVG_G, SVG_TITLE, SVG_DESC, SVG_DEFS, SVG_SYMBOL,
        SVG_USE, SVG_RECT, SVG_CIRCLE, SVG_ELLIPSE, SVG_LINE, SVG_POLYLINE,
        SVG_POLYGON, SVG_PATH, SVG_TEXT, SVG_TSPAN, SVG_IMAGE
    ))

    SKIP_NODES = frozenset((SVG_TITLE, SVG_DESC, SVG_DEFS, SVG_SYMBOL))
    PATH_NODES = frozenset((SVG_RECT, SVG_CIRCLE, SVG_ELLIPSE, SVG_LINE,
                            SVG_POLYLINE, SVG_POLYGON, SVG_PATH, SVG_TEXT))

    def __init__(self, filename):
        self.filename = filename
        self.level = 0
        self.styles = {}
        self.mainGroup = Group()
        self.drawing = None
        self.root = None

    def render(self, node, parent=None):
        if parent is None:
            parent = self.mainGroup

        # ignore if display = none
        display = node.get('display')
        if display == "none":
            return

        if node.tag == self.SVG_ROOT:
            self.level += 1

            if not self.drawing is None:
                raise SVGError('drawing already created!')

            self.root = node

            # default styles
            style = {
                'color':'none',
                'fill':'none',
                'stroke':'none',
                'font-family':'Helvetica',
                'font-size':'12'
            }

            self.styles[self.level] = style

            # iterate children
            for child in node:
                self.render(child, self.mainGroup)

            # create drawing
            width = node.get('width', '100%')
            height = node.get('height', '100%')

            if node.get("viewBox"):
                try:
                    minx, miny, width, height = node.get("viewBox").split()
                except ValueError:
                    raise SVGError("viewBox values not valid")

            if width.endswith('%') and height.endswith('%'):
                # handle relative size
                wscale = parseLength(width) / 100.
                hscale = parseLength(height) / 100.

                xL,yL,xH,yH =  self.mainGroup.getBounds()
                self.drawing = Drawing(xH*wscale + xL, yH*hscale + yL)

            else:
                self.drawing = Drawing(parseLength(width), parseLength(height))

            height = self.drawing.height
            self.mainGroup.scale(1, -1)
            self.mainGroup.translate(0, -height)
            self.drawing.add(self.mainGroup)

            self.level -= 1

            return self.drawing

        elif node.tag in (self.SVG_G, self.SVG_A):
            self.level += 1

            # set this levels style
            style = self.styles[self.level - 1].copy()
            style = self.nodeStyle(node, style)
            self.styles[self.level] = style

            group = Group()

            # iterate children
            for child in node:
                self.render(child, group)

            parent.add(group)

            transforms = node.get('transform')
            if transforms:
                for op in parseTransform.iterparse(transforms):
                    self.applyTransformOnGroup(group, op)

            self.level -= 1

        elif node.tag == self.SVG_USE:
            self.level += 1

            # set this levels style
            style = self.styles[self.level - 1].copy()
            style = self.nodeStyle(node, style)
            self.styles[self.level] = style

            group = Group()

            # link id
            link_id = node.get(self.LINK).lstrip('#')

            # find linked node in defs or symbol section
            target = None
            for defs in self.root.getiterator(self.SVG_DEFS):
                for element in defs:
                    if element.get('id') == link_id:
                        target = element
                        break

            if target is None:
                for defs in self.root.getiterator(self.SVG_SYMBOL):
                    for element in defs:
                        if element.get('id') == link_id:
                            target = element
                            break

                if target is None:
                    msg = "Could not find use node '%s'" % link_id
                    raise SVGError(msg)

            self.render(target, group)

            parent.add(group)

            # apply transform
            transforms = node.get('transform')
            if transforms:
                for op in parseTransform.iterparse(transforms):
                    self.applyTransformOnGroup(group, op)

            # apply 'x' and 'y' attribute as translation of defs object
            if node.get('x') or node.get('y'):
                dx = parseLength(node.get('x','0'))
                dy = parseLength(node.get('y','0'))

                self.applyTransformOnGroup(group, ('translate', (dx,dy)))

            self.level -= 1

        elif node.tag == self.SVG_LINE:
            # get coordinates
            x1 = parseLength(node.get('x1', '0'))
            y1 = parseLength(node.get('y1', '0'))
            x2 = parseLength(node.get('x2', '0'))
            y2 = parseLength(node.get('y2', '0'))

            shape = Line(x1, y1, x2, y2)
            self.addShape(parent, node, shape)

        elif node.tag == self.SVG_RECT:
            # get coordinates
            x = parseLength(node.get('x', '0'))
            y = parseLength(node.get('y', '0'))
            width = parseLength(node.get('width'))
            height = parseLength(node.get('height'))

            rx = parseLength(node.get('rx', '0'))
            ry = parseLength(node.get('ry', '0'))

            shape = Rect(x, y, width, height, rx=rx, ry=ry)
            self.addShape(parent, node, shape)

        elif node.tag == self.SVG_CIRCLE:
            cx = parseLength(node.get('cx', '0'))
            cy = parseLength(node.get('cy', '0'))
            r = parseLength(node.get('r'))

            if r > 0.:
                shape = Circle(cx, cy, r)
                self.addShape(parent, node, shape)

        elif node.tag == self.SVG_ELLIPSE:
            cx = parseLength(node.get('cx', '0'))
            cy = parseLength(node.get('cy', '0'))
            rx = parseLength(node.get('rx'))
            ry = parseLength(node.get('ry'))

            if rx > 0. and ry > 0.:
                shape = Ellipse(cx, cy, rx, ry)
                self.addShape(parent, node, shape)

        elif node.tag == self.SVG_POLYLINE:
            # convert points
            points = node.get('points').strip()
            if len(points) == 0:
                return

            points = list(map(parseLength, re.split('[ ,]+', points)))

            # Need to use two shapes, because standard RLG polylines
            # do not support filling...
            group = Group()
            shape = Polygon(points)
            self.applyStyleToShape(shape, node)
            shape.strokeColor = None
            group.add(shape)

            shape = PolyLine(points)
            self.applyStyleToShape(shape, node)
            group.add(shape)

            self.addShape(parent, node, group)

        elif node.tag == self.SVG_POLYGON:
            # convert points
            points = node.get('points').strip()
            if len(points) == 0:
                return

            points = list(map(parseLength, re.split('[ ,]+', points)))

            shape = Polygon(points)
            self.addShape(parent, node, shape)

        elif node.tag == self.SVG_IMAGE:
            x = parseLength(node.get('x', '0'))
            y = parseLength(node.get('y', '0'))
            width = parseLength(node.get('width', '0'))
            height = parseLength(node.get('height', '0'))

            # link id
            link_id = node.get(self.LINK)

            filename = os.path.join(os.path.dirname(self.filename), link_id)
            shape = Image(x, y, width, height, filename)

            self.addShape(parent, node, shape)

        elif node.tag == self.SVG_TEXT:
            # Todo:
            # - rotation not handled
            # - baseshift not handled
            # - embedded span node not handled
            #
            def parsePos(node, subnode, name, default='0'):
                values = subnode.get(name)
                if values is None:
                    if node is not None:
                        values = node.get(name, default)
                    else:
                        values = default

                return list(map(parseLength, values.split()))

            def getPos(values, i, default=None):
                if i >= len(values):
                    if default is None:
                        return values[-1]
                    else:
                        return default
                else:
                    return values[i]

            def handleText(node, subnode, text):
                # get position variables
                xs = parsePos(node, subnode, 'x')
                dxs = parsePos(node, subnode, 'dx')
                ys = parsePos(node, subnode,'y')
                dys = parsePos(node, subnode,'dy')

                if sum(map(len, (xs,ys,dxs,dys))) == 4:
                    # single value
                    shape = String(xs[0] + dxs[0], -ys[0] - dys[0], text)
                    self.applyStyleToShape(shape, subnode)
                    group.add(shape)

                else:
                    # multiple values
                    for i, c in enumerate(text):
                        x = getPos(xs, i)
                        dx = getPos(dxs, i, 0)
                        y = getPos(ys, i)
                        dy = getPos(dys, i, 0)

                        shape = String(x + dx, -y -dy, c)
                        self.applyStyleToShape(shape, subnode)
                        group.add(shape)

            if node.text and node.text.strip():
                group = Group()

                handleText(None, node, node.text.strip())

                group.scale(1, -1)

                self.addShape(parent, node, group)

            if len(node) > 0:
                group = Group()

                self.level += 1

                # set this levels style
                style = self.styles[self.level - 1].copy()
                nodestylestyle = self.nodeStyle(node, style)
                self.styles[self.level] = nodestylestyle

                for subnode in node:
                    if subnode.tag == self.SVG_TSPAN:
                        handleText(node, subnode, subnode.text.strip())

                self.level -= 1

                group.scale(1, -1)
                self.addShape(parent, node, group)

        elif node.tag == self.SVG_PATH:
            def convertQuadratic(Q0, Q1, Q2):
                C1 = (Q0[0] + 2./3*(Q1[0] - Q0[0]), Q0[1] + 2./3*(Q1[1] - Q0[1]))
                C2 = (C1[0] + 1./3*(Q2[0] - Q0[0]), C1[1] + 1./3*(Q2[1] - Q0[1]))
                C3 = Q2
                return C1[0], C1[1], C2[0], C2[1], C3[0], C3[1]

            def prevCtrl(lastOp, lastArgs, currentX, currentY):
                # fetch last controll point
                if lastOp in 'CScsQqTt':
                    x, y = lastArgs[-2]

                    # mirror about current point
                    return currentX + (currentX-x), currentY + (currentY-y)

                else:
                    # defaults to current point
                    return currentX, currentY

            # store sub paths in 'paths' list
            shape = Path()

            # keep track of current point and path start point
            startX, startY = 0., 0.
            currentX, currentY = 0., 0.

            # keep track of last operation
            lastOp = None
            lastArgs = None

            # avoid empty path data
            data = node.get('d')
            if data is None or len(data) == 0:
                return

            for op, args in parsePath.iterparse(data):
                if op == 'z' or op == 'Z':
                    # close path or subpath
                    shape.closePath()

                    # next sub path starts at begining of current path
                    currentX, currentY = startX, startY

                elif op == 'M':
                    # moveto absolute
                    if lastOp is not None and lastOp not in ('z', 'Z'):
                        # close sub path
                        shape.closePath()

                    x, y = args[0]
                    shape.moveTo(x, y)

                    startX, startY = x, y

                    # multiple moveto arge result in line
                    for x, y in args[1:]:
                        shape.lineTo(x, y)

                    currentX, currentY = x, y

                elif op == 'm':
                    if lastOp is not None and lastOp not in ('z', 'Z'):
                        # close sub path
                        shape.closePath()

                    # moveto relative
                    rx, ry = args[0]
                    x, y = currentX + rx, currentY + ry
                    shape.moveTo(x, y)

                    startX, startY = x, y
                    currentX, currentY = x, y

                    # multiple moveto arge result in line
                    for rx, ry in args[1:]:
                        x, y = currentX + rx, currentY + ry
                        shape.lineTo(x, y)
                        currentX, currentY = x, y

                elif op == 'L':
                    # lineto absolute
                    for x, y in args:
                        shape.lineTo(x, y)

                    currentX, currentY = x, y

                elif op == 'l':
                    # lineto relative
                    for rx, ry in args:
                        x, y = currentX + rx, currentY + ry
                        shape.lineTo(x, y)
                        currentX, currentY = x, y

                elif op == 'V':
                    # vertical line absolute
                    for y in args:
                        shape.lineTo(currentX, y)

                    currentY = y

                elif op == 'v':
                    # vertical line relative
                    for ry in args:
                        y = currentY + ry
                        shape.lineTo(currentX, y)
                        currentY = y

                elif op == 'H':
                    # horisontal line absolute
                    for x in args:
                        shape.lineTo(x, currentY)
                    currentX = x

                elif op == 'h':
                    # horisontal line relative
                    for rx in args:
                        x = currentX + rx
                        shape.lineTo(x, currentY)
                    currentX = x

                elif op == 'C':
                    # cubic bezier absolute
                    for p1, p2, p3 in zip(*([iter(args)] * 3)):
                        shape.curveTo(*(p1 + p2 + p3))
                        currentX, currentY = p3

                elif op == 'c':
                    # cubic bezier relative
                    for pnts in zip(*([iter(args)] * 3)):
                        (x1, y1), (x2, y2), (x3, y3) = pnts
                        pnts = tuple((p[0] + currentX, p[1] + currentY) for p in pnts)
                        shape.curveTo(*(pnts[0] + pnts[1] + pnts[2]))
                        currentX, currentY = pnts[2]
                        lastOp = op
                        lastArgs = pnts
                    continue

                elif op == 'S':
                    # shorthand cubic bezier absolute
                    for p2, p3 in zip(*([iter(args)] * 2)):
                        x1, y1 = prevCtrl(lastOp, lastArgs, currentX, currentY)
                        x2, y2 = p2
                        x3, y3 = p3
                        shape.curveTo(x1, y1, x2, y2, x3, y3)
                        lastOp = op
                        lastArgs = (x2, y2), (x3, y3)
                        currentX, currentY = x3, y3
                    continue

                elif op == 's':
                    # shorthand cubic bezier relative
                    for p2, p3 in zip(*([iter(args)] * 2)):
                        x1, y1 = prevCtrl(lastOp, lastArgs, currentX, currentY)
                        x2, y2 = p2
                        x2, y2 = x2 + currentX, y2 + currentY
                        x3, y3 = p3
                        x3, y3 = x3 + currentX, y3 + currentY
                        shape.curveTo(x1, y1, x2, y2, x3, y3)
                        currentX, currentY = x3, y3
                        lastOp = op
                        lastArgs = (x1, y1), (x2, y2), (x3, y3)
                    continue

                elif op == 'Q':
                    # quadratic bezier absolute
                    for p2, p3 in zip(*([iter(args)] * 2)):
                        x1, y1 = currentX, currentY
                        x2, y2 = p2
                        x3, y3 = p3
                        ctrls = convertQuadratic((x1, y1), (x2, y2), (x3, y3))
                        shape.curveTo(*ctrls)
                        currentX, currentY = x3, y3
                    lastOp = op
                    lastArgs = (x2, y2), (x3, y3)
                    continue

                elif op == 'q':
                    # quadratic bezier relative
                    for p2, p3 in zip(*([iter(args)] * 2)):
                        x1, y1 = currentX, currentY
                        x2, y2 = p2
                        x2, y2 = x2 + currentX, y2 + currentY
                        x3, y3 = p3
                        x3, y3 = x3 + currentX, y3 + currentY
                        ctrls = convertQuadratic((x1, y1), (x2, y2), (x3, y3))
                        shape.curveTo(*ctrls)
                        currentX, currentY = x3, y3

                    lastOp = op
                    lastArgs = (x2, y2), (x3, y3)
                    continue

                elif op == 'T':
                    # shorthand quadratic bezier absolute
                    for i in range(len(args)):
                        x1, y1 = currentX, currentY
                        x2, y2 = prevCtrl(lastOp, lastArgs, currentX, currentY)
                        x3, y3 = args[i]
                        ctrls = convertQuadratic((x1, y1), (x2, y2), (x3, y3))
                        shape.curveTo(*ctrls)
                        currentX, currentY = x3, y3
                        lastOp = op
                        lastArgs = (x2, y2), (x3, y3)

                    continue

                elif op == 't':
                    # shorthand quadratic bezier relative
                    for i in range(len(args)):
                        x1, y1 = currentX, currentY
                        x2, y2 = prevCtrl(lastOp, lastArgs, currentX, currentY)
                        x3, y3 = args[i]
                        x3, y3 = x3 + currentX, y3 + currentY
                        ctrls = convertQuadratic((x1, y1), (x2, y2), (x3, y3))
                        shape.curveTo(*ctrls)
                        currentX, currentY = x3, y3
                        lastOp = op
                        lastArgs = (x2, y2), (x3, y3)

                    continue

                elif op == 'A' or op == 'a':
                    # elliptic arc missing
                    continue

                lastOp = op
                lastArgs = args

            # check if fill applies to path
            fill = None
            if node.get('fill'):
                # inline style
                fill = node.get('fill')
            else:
                # try local style
                if node.get('style'):
                    style = parseStyle.parse(node.get('style'))

                    if 'fill' in style:
                        fill = style['fill']

                # try global style
                if fill is None:
                    style = self.styles[self.level]

                    if 'fill' in style:
                        fill = style['fill']
                    else:
                        fill = 'none'

            # hack because RLG has no "semi-closed" paths...
            if lastOp == 'z' or lastOp == 'Z' or fill == 'none':
                self.addShape(parent, node, shape)

            else:
                group = Group()
                strokeshape = shape.copy()
                self.addShape(group, node, strokeshape, fill='none')
                shape.closePath()
                self.addShape(group, node, shape, stroke='none')
                self.addShape(parent, node, group)

        elif node.tag == self.SVG_TITLE or node.tag == self.SVG_DESC:
            # Skip non-graphics elements
            return

    def addShape(self, parent, node, shape, **kwargs):
        self.applyStyleToShape(shape, node, **kwargs)

        transform = node.get('transform')
        if transform:
            # transform can only be applied to a group
            if isinstance(node, Group):
                group = node
            else:
                group = Group()

            for op in parseTransform.iterparse(transform):
                self.applyTransformOnGroup(group, op)

            if not isinstance(node, Group):
                group.add(shape)

            parent.add(group)

        else:
            parent.add(shape)

        return shape

    def nodeStyle(self, node, style=None):
        if style is None:
            style = {}

        # update with local style
        if node.get('style'):
            localstyle = parseStyle.parse(node.get('style'))
            for name, value in localstyle.items():
                style[name] = value

        # update with inline style
        for name in STYLE_NAMES:
            value = node.get(name)
            if value:
                style[name] = value

        return style

    def applyStyleToShape(self, shape, node, **kwargs):
        # fetch global styles for this level
        globalstyle = self.styles[self.level]

        # update with node style
        localstyle = self.nodeStyle(node)

        for name in STYLES:
            # avoid text styles if not a String subclass
            if not isinstance(shape, String) and name in STYLES_FONT:
                continue

            value = None
            if name in kwargs:
                value = kwargs[name]
            elif name in localstyle:
                value = localstyle[name]
            elif name in globalstyle:
                value = globalstyle[name]
            else:
                continue

            # handle 'currentColor'
            if value == 'currentColor':
                if 'color' in localstyle:
                    value = localstyle['color']
                elif 'color' in globalstyle:
                    value = globalstyle['color']

            # fetch shape attribute name and converter
            attrname, converter = STYLES[name]

            # Sett attribute of shape
            if hasattr(shape, attrname):
                setattr(shape, attrname, converter(value))

        # defaults
        if isinstance(shape, String):
            if shape.fillColor is None:
                shape.fillColor = colors.black

        elif isinstance(shape, (Line, PolyLine)):
            if shape.strokeColor is None:
                shape.strokeColor = colors.black

        elif isinstance(shape, (Rect, Circle, Ellipse, Polygon)):
            if shape.fillColor is None and shape.strokeColor is None:
                shape.strokeColor = colors.black

    def applyTransformOnGroup(self, group, transform):
        op, args = transform

        if op == 'scale':
            group.scale(*args)

        elif op == 'translate':
            group.translate(*args)

        elif op == 'rotate':
            if len(args) == 2:
                angle, center = args
                if center:
                    cx, cy = center
                    group.translate(cx, cy)
                    group.rotate(angle)
                    group.translate(-cx, -cy)
                else:
                    group.rotate(angle)

        elif op == "skewX":
            angle = args[0]
            group.skew(angle, 0)

        elif op == "skewY":
            angle = args[0]
            group.skew(0, angle)

        elif op == "matrix":
            group.transform = mmult(group.transform, args)
Beispiel #28
0
	from fontTools.ttLib import TTFont
	from reportlab.lib import colors

	path = sys.argv[1]
	glyphName = sys.argv[2]
	if (len(sys.argv) > 3):
		imageFile = sys.argv[3]
	else:
		imageFile = "%s.png" % glyphName

	font = TTFont(path)  # it would work just as well with fontTools.t1Lib.T1Font
	gs = font.getGlyphSet()
	pen = ReportLabPen(gs, Path(fillColor=colors.red, strokeWidth=5))
	g = gs[glyphName]
	g.draw(pen)

	w, h = g.width, 1000
	from reportlab.graphics import renderPM
	from reportlab.graphics.shapes import Group, Drawing, scale

	# Everything is wrapped in a group to allow transformations.
	g = Group(pen.path)
	g.translate(0, 200)
	g.scale(0.3, 0.3)

	d = Drawing(w, h)
	d.add(g)

	renderPM.drawToFile(d, imageFile, fmt="PNG")
Beispiel #29
0
class Renderer:
    LINK = '{http://www.w3.org/1999/xlink}href'

    SVG_NS = '{http://www.w3.org/2000/svg}'
    SVG_ROOT = SVG_NS + 'svg'
    SVG_A = SVG_NS + 'a'
    SVG_G = SVG_NS + 'g'
    SVG_TITLE = SVG_NS + 'title'
    SVG_DESC = SVG_NS + 'desc'
    SVG_DEFS = SVG_NS + 'defs'
    SVG_SYMBOL = SVG_NS + 'symbol'
    SVG_USE = SVG_NS + 'use'
    SVG_RECT = SVG_NS + 'rect'
    SVG_CIRCLE = SVG_NS + 'circle'
    SVG_ELLIPSE = SVG_NS + 'ellipse'
    SVG_LINE = SVG_NS + 'line'
    SVG_POLYLINE = SVG_NS + 'polyline'
    SVG_POLYGON = SVG_NS + 'polygon'
    SVG_PATH = SVG_NS + 'path'
    SVG_TEXT = SVG_NS + 'text'
    SVG_TSPAN = SVG_NS + 'tspan'
    SVG_IMAGE = SVG_NS + 'image'

    SVG_NODES = frozenset(
        (SVG_ROOT, SVG_A, SVG_G, SVG_TITLE, SVG_DESC, SVG_DEFS, SVG_SYMBOL,
         SVG_USE, SVG_RECT, SVG_CIRCLE, SVG_ELLIPSE, SVG_LINE, SVG_POLYLINE,
         SVG_POLYGON, SVG_PATH, SVG_TEXT, SVG_TSPAN, SVG_IMAGE))

    SKIP_NODES = frozenset((SVG_TITLE, SVG_DESC, SVG_DEFS, SVG_SYMBOL))
    PATH_NODES = frozenset((SVG_RECT, SVG_CIRCLE, SVG_ELLIPSE, SVG_LINE,
                            SVG_POLYLINE, SVG_POLYGON, SVG_PATH, SVG_TEXT))

    def __init__(self, filename):
        self.filename = filename
        self.level = 0
        self.styles = {}
        self.mainGroup = Group()
        self.drawing = None
        self.root = None

    def render(self, node, parent=None):
        if parent is None:
            parent = self.mainGroup

        # ignore if display = none
        display = node.get('display')
        if display == "none":
            return

        if node.tag == self.SVG_ROOT:
            self.level += 1

            if not self.drawing is None:
                raise SVGError('drawing already created!')

            self.root = node

            # default styles
            style = {
                'color': 'none',
                'fill': 'none',
                'stroke': 'none',
                'font-family': 'Helvetica',
                'font-size': '12'
            }

            self.styles[self.level] = style

            # iterate children
            for child in node:
                self.render(child, self.mainGroup)

            # create drawing
            width = node.get('width', '100%')
            height = node.get('height', '100%')

            if node.get("viewBox"):
                try:
                    minx, miny, width, height = node.get("viewBox").split()
                except ValueError:
                    raise SVGError("viewBox values not valid")

            if width.endswith('%') and height.endswith('%'):
                # handle relative size
                wscale = parseLength(width) / 100.
                hscale = parseLength(height) / 100.

                xL, yL, xH, yH = self.mainGroup.getBounds()
                self.drawing = Drawing(xH * wscale + xL, yH * hscale + yL)

            else:
                self.drawing = Drawing(parseLength(width), parseLength(height))

            height = self.drawing.height
            self.mainGroup.scale(1, -1)
            self.mainGroup.translate(0, -height)
            self.drawing.add(self.mainGroup)

            self.level -= 1

            return self.drawing

        elif node.tag in (self.SVG_G, self.SVG_A):
            self.level += 1

            # set this levels style
            style = self.styles[self.level - 1].copy()
            style = self.nodeStyle(node, style)
            self.styles[self.level] = style

            group = Group()

            # iterate children
            for child in node:
                self.render(child, group)

            parent.add(group)

            transforms = node.get('transform')
            if transforms:
                for op in parseTransform.iterparse(transforms):
                    self.applyTransformOnGroup(group, op)

            self.level -= 1

        elif node.tag == self.SVG_USE:
            self.level += 1

            # set this levels style
            style = self.styles[self.level - 1].copy()
            style = self.nodeStyle(node, style)
            self.styles[self.level] = style

            group = Group()

            # link id
            link_id = node.get(self.LINK).lstrip('#')

            # find linked node in defs or symbol section
            target = None
            for defs in self.root.getiterator(self.SVG_DEFS):
                for element in defs:
                    if element.get('id') == link_id:
                        target = element
                        break

            if target is None:
                for defs in self.root.getiterator(self.SVG_SYMBOL):
                    for element in defs:
                        if element.get('id') == link_id:
                            target = element
                            break

                if target is None:
                    msg = "Could not find use node '%s'" % link_id
                    raise SVGError(msg)

            self.render(target, group)

            parent.add(group)

            # apply transform
            transforms = node.get('transform')
            if transforms:
                for op in parseTransform.iterparse(transforms):
                    self.applyTransformOnGroup(group, op)

            # apply 'x' and 'y' attribute as translation of defs object
            if node.get('x') or node.get('y'):
                dx = parseLength(node.get('x', '0'))
                dy = parseLength(node.get('y', '0'))

                self.applyTransformOnGroup(group, ('translate', (dx, dy)))

            self.level -= 1

        elif node.tag == self.SVG_LINE:
            # get coordinates
            x1 = parseLength(node.get('x1', '0'))
            y1 = parseLength(node.get('y1', '0'))
            x2 = parseLength(node.get('x2', '0'))
            y2 = parseLength(node.get('y2', '0'))

            shape = Line(x1, y1, x2, y2)
            self.addShape(parent, node, shape)

        elif node.tag == self.SVG_RECT:
            # get coordinates
            x = parseLength(node.get('x', '0'))
            y = parseLength(node.get('y', '0'))
            width = parseLength(node.get('width'))
            height = parseLength(node.get('height'))

            rx = parseLength(node.get('rx', '0'))
            ry = parseLength(node.get('ry', '0'))

            shape = Rect(x, y, width, height, rx=rx, ry=ry)
            self.addShape(parent, node, shape)

        elif node.tag == self.SVG_CIRCLE:
            cx = parseLength(node.get('cx', '0'))
            cy = parseLength(node.get('cy', '0'))
            r = parseLength(node.get('r'))

            if r > 0.:
                shape = Circle(cx, cy, r)
                self.addShape(parent, node, shape)

        elif node.tag == self.SVG_ELLIPSE:
            cx = parseLength(node.get('cx', '0'))
            cy = parseLength(node.get('cy', '0'))
            rx = parseLength(node.get('rx'))
            ry = parseLength(node.get('ry'))

            if rx > 0. and ry > 0.:
                shape = Ellipse(cx, cy, rx, ry)
                self.addShape(parent, node, shape)

        elif node.tag == self.SVG_POLYLINE:
            # convert points
            points = node.get('points').strip()
            if len(points) == 0:
                return

            points = list(map(parseLength, re.split('[ ,]+', points)))

            # Need to use two shapes, because standard RLG polylines
            # do not support filling...
            group = Group()
            shape = Polygon(points)
            self.applyStyleToShape(shape, node)
            shape.strokeColor = None
            group.add(shape)

            shape = PolyLine(points)
            self.applyStyleToShape(shape, node)
            group.add(shape)

            self.addShape(parent, node, group)

        elif node.tag == self.SVG_POLYGON:
            # convert points
            points = node.get('points').strip()
            if len(points) == 0:
                return

            points = list(map(parseLength, re.split('[ ,]+', points)))

            shape = Polygon(points)
            self.addShape(parent, node, shape)

        elif node.tag == self.SVG_IMAGE:
            x = parseLength(node.get('x', '0'))
            y = parseLength(node.get('y', '0'))
            width = parseLength(node.get('width', '0'))
            height = parseLength(node.get('height', '0'))

            # link id
            link_id = node.get(self.LINK)

            filename = os.path.join(os.path.dirname(self.filename), link_id)
            shape = Image(x, y, width, height, filename)

            self.addShape(parent, node, shape)

        elif node.tag == self.SVG_TEXT:
            # Todo:
            # - rotation not handled
            # - baseshift not handled
            # - embedded span node not handled
            #
            def parsePos(node, subnode, name, default='0'):
                values = subnode.get(name)
                if values is None:
                    if node is not None:
                        values = node.get(name, default)
                    else:
                        values = default

                return list(map(parseLength, values.split()))

            def getPos(values, i, default=None):
                if i >= len(values):
                    if default is None:
                        return values[-1]
                    else:
                        return default
                else:
                    return values[i]

            def handleText(node, subnode, text):
                # get position variables
                xs = parsePos(node, subnode, 'x')
                dxs = parsePos(node, subnode, 'dx')
                ys = parsePos(node, subnode, 'y')
                dys = parsePos(node, subnode, 'dy')

                if sum(map(len, (xs, ys, dxs, dys))) == 4:
                    # single value
                    shape = String(xs[0] + dxs[0], -ys[0] - dys[0], text)
                    self.applyStyleToShape(shape, subnode)
                    group.add(shape)

                else:
                    # multiple values
                    for i, c in enumerate(text):
                        x = getPos(xs, i)
                        dx = getPos(dxs, i, 0)
                        y = getPos(ys, i)
                        dy = getPos(dys, i, 0)

                        shape = String(x + dx, -y - dy, c)
                        self.applyStyleToShape(shape, subnode)
                        group.add(shape)

            if node.text and node.text.strip():
                group = Group()

                handleText(None, node, node.text.strip())

                group.scale(1, -1)

                self.addShape(parent, node, group)

            if len(node) > 0:
                group = Group()

                self.level += 1

                # set this levels style
                style = self.styles[self.level - 1].copy()
                nodestylestyle = self.nodeStyle(node, style)
                self.styles[self.level] = nodestylestyle

                for subnode in node:
                    if subnode.tag == self.SVG_TSPAN:
                        handleText(node, subnode, subnode.text.strip())

                self.level -= 1

                group.scale(1, -1)
                self.addShape(parent, node, group)

        elif node.tag == self.SVG_PATH:

            def convertQuadratic(Q0, Q1, Q2):
                C1 = (Q0[0] + 2. / 3 * (Q1[0] - Q0[0]),
                      Q0[1] + 2. / 3 * (Q1[1] - Q0[1]))
                C2 = (C1[0] + 1. / 3 * (Q2[0] - Q0[0]),
                      C1[1] + 1. / 3 * (Q2[1] - Q0[1]))
                C3 = Q2
                return C1[0], C1[1], C2[0], C2[1], C3[0], C3[1]

            def prevCtrl(lastOp, lastArgs, currentX, currentY):
                # fetch last controll point
                if lastOp in 'CScsQqTt':
                    x, y = lastArgs[-2]

                    # mirror about current point
                    return currentX + (currentX - x), currentY + (currentY - y)

                else:
                    # defaults to current point
                    return currentX, currentY

            # store sub paths in 'paths' list
            shape = Path()

            # keep track of current point and path start point
            startX, startY = 0., 0.
            currentX, currentY = 0., 0.

            # keep track of last operation
            lastOp = None
            lastArgs = None

            # avoid empty path data
            data = node.get('d')
            if data is None or len(data) == 0:
                return

            for op, args in parsePath.iterparse(data):
                if op == 'z' or op == 'Z':
                    # close path or subpath
                    shape.closePath()

                    # next sub path starts at begining of current path
                    currentX, currentY = startX, startY

                elif op == 'M':
                    # moveto absolute
                    if lastOp is not None and lastOp not in ('z', 'Z'):
                        # close sub path
                        shape.closePath()

                    x, y = args[0]
                    shape.moveTo(x, y)

                    startX, startY = x, y

                    # multiple moveto arge result in line
                    for x, y in args[1:]:
                        shape.lineTo(x, y)

                    currentX, currentY = x, y

                elif op == 'm':
                    if lastOp is not None and lastOp not in ('z', 'Z'):
                        # close sub path
                        shape.closePath()

                    # moveto relative
                    rx, ry = args[0]
                    x, y = currentX + rx, currentY + ry
                    shape.moveTo(x, y)

                    startX, startY = x, y
                    currentX, currentY = x, y

                    # multiple moveto arge result in line
                    for rx, ry in args[1:]:
                        x, y = currentX + rx, currentY + ry
                        shape.lineTo(x, y)
                        currentX, currentY = x, y

                elif op == 'L':
                    # lineto absolute
                    for x, y in args:
                        shape.lineTo(x, y)

                    currentX, currentY = x, y

                elif op == 'l':
                    # lineto relative
                    for rx, ry in args:
                        x, y = currentX + rx, currentY + ry
                        shape.lineTo(x, y)
                        currentX, currentY = x, y

                elif op == 'V':
                    # vertical line absolute
                    for y in args:
                        shape.lineTo(currentX, y)

                    currentY = y

                elif op == 'v':
                    # vertical line relative
                    for ry in args:
                        y = currentY + ry
                        shape.lineTo(currentX, y)
                        currentY = y

                elif op == 'H':
                    # horisontal line absolute
                    for x in args:
                        shape.lineTo(x, currentY)
                    currentX = x

                elif op == 'h':
                    # horisontal line relative
                    for rx in args:
                        x = currentX + rx
                        shape.lineTo(x, currentY)
                    currentX = x

                elif op == 'C':
                    # cubic bezier absolute
                    for p1, p2, p3 in zip(*([iter(args)] * 3)):
                        shape.curveTo(*(p1 + p2 + p3))
                        currentX, currentY = p3

                elif op == 'c':
                    # cubic bezier relative
                    for pnts in zip(*([iter(args)] * 3)):
                        (x1, y1), (x2, y2), (x3, y3) = pnts
                        pnts = tuple(
                            (p[0] + currentX, p[1] + currentY) for p in pnts)
                        shape.curveTo(*(pnts[0] + pnts[1] + pnts[2]))
                        currentX, currentY = pnts[2]
                        lastOp = op
                        lastArgs = pnts
                    continue

                elif op == 'S':
                    # shorthand cubic bezier absolute
                    for p2, p3 in zip(*([iter(args)] * 2)):
                        x1, y1 = prevCtrl(lastOp, lastArgs, currentX, currentY)
                        x2, y2 = p2
                        x3, y3 = p3
                        shape.curveTo(x1, y1, x2, y2, x3, y3)
                        lastOp = op
                        lastArgs = (x2, y2), (x3, y3)
                        currentX, currentY = x3, y3
                    continue

                elif op == 's':
                    # shorthand cubic bezier relative
                    for p2, p3 in zip(*([iter(args)] * 2)):
                        x1, y1 = prevCtrl(lastOp, lastArgs, currentX, currentY)
                        x2, y2 = p2
                        x2, y2 = x2 + currentX, y2 + currentY
                        x3, y3 = p3
                        x3, y3 = x3 + currentX, y3 + currentY
                        shape.curveTo(x1, y1, x2, y2, x3, y3)
                        currentX, currentY = x3, y3
                        lastOp = op
                        lastArgs = (x1, y1), (x2, y2), (x3, y3)
                    continue

                elif op == 'Q':
                    # quadratic bezier absolute
                    for p2, p3 in zip(*([iter(args)] * 2)):
                        x1, y1 = currentX, currentY
                        x2, y2 = p2
                        x3, y3 = p3
                        ctrls = convertQuadratic((x1, y1), (x2, y2), (x3, y3))
                        shape.curveTo(*ctrls)
                        currentX, currentY = x3, y3
                    lastOp = op
                    lastArgs = (x2, y2), (x3, y3)
                    continue

                elif op == 'q':
                    # quadratic bezier relative
                    for p2, p3 in zip(*([iter(args)] * 2)):
                        x1, y1 = currentX, currentY
                        x2, y2 = p2
                        x2, y2 = x2 + currentX, y2 + currentY
                        x3, y3 = p3
                        x3, y3 = x3 + currentX, y3 + currentY
                        ctrls = convertQuadratic((x1, y1), (x2, y2), (x3, y3))
                        shape.curveTo(*ctrls)
                        currentX, currentY = x3, y3

                    lastOp = op
                    lastArgs = (x2, y2), (x3, y3)
                    continue

                elif op == 'T':
                    # shorthand quadratic bezier absolute
                    for i in range(len(args)):
                        x1, y1 = currentX, currentY
                        x2, y2 = prevCtrl(lastOp, lastArgs, currentX, currentY)
                        x3, y3 = args[i]
                        ctrls = convertQuadratic((x1, y1), (x2, y2), (x3, y3))
                        shape.curveTo(*ctrls)
                        currentX, currentY = x3, y3
                        lastOp = op
                        lastArgs = (x2, y2), (x3, y3)

                    continue

                elif op == 't':
                    # shorthand quadratic bezier relative
                    for i in range(len(args)):
                        x1, y1 = currentX, currentY
                        x2, y2 = prevCtrl(lastOp, lastArgs, currentX, currentY)
                        x3, y3 = args[i]
                        x3, y3 = x3 + currentX, y3 + currentY
                        ctrls = convertQuadratic((x1, y1), (x2, y2), (x3, y3))
                        shape.curveTo(*ctrls)
                        currentX, currentY = x3, y3
                        lastOp = op
                        lastArgs = (x2, y2), (x3, y3)

                    continue

                elif op == 'A' or op == 'a':
                    # elliptic arc missing
                    continue

                lastOp = op
                lastArgs = args

            # check if fill applies to path
            fill = None
            if node.get('fill'):
                # inline style
                fill = node.get('fill')
            else:
                # try local style
                if node.get('style'):
                    style = parseStyle.parse(node.get('style'))

                    if 'fill' in style:
                        fill = style['fill']

                # try global style
                if fill is None:
                    style = self.styles[self.level]

                    if 'fill' in style:
                        fill = style['fill']
                    else:
                        fill = 'none'

            # hack because RLG has no "semi-closed" paths...
            if lastOp == 'z' or lastOp == 'Z' or fill == 'none':
                self.addShape(parent, node, shape)

            else:
                group = Group()
                strokeshape = shape.copy()
                self.addShape(group, node, strokeshape, fill='none')
                shape.closePath()
                self.addShape(group, node, shape, stroke='none')
                self.addShape(parent, node, group)

        elif node.tag == self.SVG_TITLE or node.tag == self.SVG_DESC:
            # Skip non-graphics elements
            return

    def addShape(self, parent, node, shape, **kwargs):
        self.applyStyleToShape(shape, node, **kwargs)

        transform = node.get('transform')
        if transform:
            # transform can only be applied to a group
            if isinstance(node, Group):
                group = node
            else:
                group = Group()

            for op in parseTransform.iterparse(transform):
                self.applyTransformOnGroup(group, op)

            if not isinstance(node, Group):
                group.add(shape)

            parent.add(group)

        else:
            parent.add(shape)

        return shape

    def nodeStyle(self, node, style=None):
        if style is None:
            style = {}

        # update with local style
        if node.get('style'):
            localstyle = parseStyle.parse(node.get('style'))
            for name, value in localstyle.items():
                style[name] = value

        # update with inline style
        for name in STYLE_NAMES:
            value = node.get(name)
            if value:
                style[name] = value

        return style

    def applyStyleToShape(self, shape, node, **kwargs):
        # fetch global styles for this level
        globalstyle = self.styles[self.level]

        # update with node style
        localstyle = self.nodeStyle(node)

        for name in STYLES:
            # avoid text styles if not a String subclass
            if not isinstance(shape, String) and name in STYLES_FONT:
                continue

            value = None
            if name in kwargs:
                value = kwargs[name]
            elif name in localstyle:
                value = localstyle[name]
            elif name in globalstyle:
                value = globalstyle[name]
            else:
                continue

            # handle 'currentColor'
            if value == 'currentColor':
                if 'color' in localstyle:
                    value = localstyle['color']
                elif 'color' in globalstyle:
                    value = globalstyle['color']

            # fetch shape attribute name and converter
            attrname, converter = STYLES[name]

            # Sett attribute of shape
            if hasattr(shape, attrname):
                setattr(shape, attrname, converter(value))

        # defaults
        if isinstance(shape, (String, Rect)):
            if shape.fillColor is None:
                shape.fillColor = colors.black

        elif isinstance(shape, (Line, PolyLine)):
            if shape.strokeColor is None:
                shape.strokeColor = colors.black

        elif isinstance(shape, (Circle, Ellipse, Polygon)):
            if shape.fillColor is None and shape.strokeColor is None:
                shape.strokeColor = colors.black

    def applyTransformOnGroup(self, group, transform):
        op, args = transform

        if op == 'scale':
            group.scale(*args)

        elif op == 'translate':
            group.translate(*args)

        elif op == 'rotate':
            if len(args) == 2:
                angle, center = args
                if center:
                    cx, cy = center
                    group.translate(cx, cy)
                    group.rotate(angle)
                    group.translate(-cx, -cy)
                else:
                    group.rotate(angle)

        elif op == "skewX":
            angle = args[0]
            group.skew(angle, 0)

        elif op == "skewY":
            angle = args[0]
            group.skew(0, angle)

        elif op == "matrix":
            group.transform = mmult(group.transform, args)
Beispiel #30
0
btmfront = Group(
    Rect(0,
         0,
         bottom_width,
         bottom_thickness,
         strokeWidth=0.02,
         fillColor=colors.white))
btmtop = Group(
    Rect(0,
         0,
         bottom_width,
         bottom_depth,
         strokeWidth=0.02,
         fillColor=colors.white))
btmtop.translate(0, bottom_thickness)
btmtop.shift(0, bottom_thickness)
btmtop.skew(iso_angle, 0)
btmright = Group(
    Rect(0,
         0,
         bottom_depth,
         bottom_thickness,
         strokeWidth=0.02,
         fillColor=colors.white))
btmright.translate(bottom_width, 0)
btmright.shift(bottom_width, 0)
btmright.skew(0, 90 - iso_angle)

d.add(btmfront)
d.add(btmtop)
Beispiel #31
0
    from reportlab.lib import colors

    path = sys.argv[1]
    glyphName = sys.argv[2]
    if (len(sys.argv) > 3):
        imageFile = sys.argv[3]
    else:
        imageFile = "%s.png" % glyphName

    font = TTFont(
        path
    )  # it would work just as well with fontemon_blender_addon.fontTools.t1Lib.T1Font
    gs = font.getGlyphSet()
    pen = ReportLabPen(gs, Path(fillColor=colors.red, strokeWidth=5))
    g = gs[glyphName]
    g.draw(pen)

    w, h = g.width, 1000
    from reportlab.graphics import renderPM
    from reportlab.graphics.shapes import Group, Drawing, scale

    # Everything is wrapped in a group to allow transformations.
    g = Group(pen.path)
    g.translate(0, 200)
    g.scale(0.3, 0.3)

    d = Drawing(w, h)
    d.add(g)

    renderPM.drawToFile(d, imageFile, fmt="PNG")
    def draw(self):
        # general widget bits
        g = Group()

        x = self.x
        y = self.y
        scale = self.scale
        stemThickness = self.stemThickness * scale
        stemLength = self.stemLength * scale
        headProjection = self.headProjection * scale
        headLength = self.headLength * scale
        headSweep = self.headSweep * scale
        w = stemLength + headLength
        h = 2 * headProjection + stemThickness
        # shift to the boxAnchor
        boxAnchor = self.boxAnchor
        if self.right:
            if boxAnchor in ('sw', 'w', 'nw'):
                dy = -h
            elif boxAnchor in ('s', 'c', 'n'):
                dy = -h * 0.5
            else:
                dy = 0
            if boxAnchor in ('w', 'c', 'e'):
                dx = -w * 0.5
            elif boxAnchor in ('nw', 'n', 'ne'):
                dx = -w
            else:
                dx = 0
            points = [
                dx,
                dy + headProjection + stemThickness,
                dx + stemLength,
                dy + headProjection + stemThickness,
                dx + stemLength + headSweep,
                dy + 2 * headProjection + stemThickness,
                dx + stemLength + headLength,
                dy + 0.5 * stemThickness + headProjection,
                dx + stemLength + headSweep,
                dy,
                dx + stemLength,
                dy + headProjection,
                dx,
                dy + headProjection,
            ]
        else:
            w, h = h, w
            if boxAnchor in ('nw', 'n', 'ne'):
                dy = -h
            elif boxAnchor in ('w', 'c', 'e'):
                dy = -h * 0.5
            else:
                dy = 0
            if boxAnchor in ('ne', 'e', 'se'):
                dx = -w
            elif boxAnchor in ('n', 'c', 's'):
                dx = -w * 0.5
            else:
                dx = 0
            points = [
                dx + headProjection,
                dy,  #sw
                dx + headProjection + stemThickness,
                dy,  #se
                dx + headProjection + stemThickness,
                dy + stemLength,
                dx + w,
                dy + stemLength + headSweep,
                dx + headProjection + 0.5 * stemThickness,
                dy + h,
                dx,
                dy + stemLength + headSweep,
                dx + headProjection,
                dy + stemLength,
            ]

        g.add(
            Polygon(
                points=points,
                fillColor=self.fillColor,
                strokeColor=self.strokeColor,
                strokeWidth=self.strokeWidth,
            ))
        g.translate(x, y)
        g.rotate(self.angle)
        return g