def process(self): kw = dict(self.getAttributeValues()) canvas = attr.getManager(self, interfaces.ICanvasManager).canvas if 'width' in kw: canvas.setLineWidth(kw['width']) if 'join' in kw: canvas.setLineJoin(kw['join']) if 'cap' in kw: canvas.setLineCap(kw['cap']) if 'miterLimit' in kw: canvas.setMiterLimit(kw['miterLimit']) if 'dash' in kw: canvas.setDash(kw['dash'])
def heatkey(canvas, hkX, hkY, idpt): """Draw color key for the heat map.""" canvas.setLineWidth(1) canvas.setLineCap(0) canvas.setFillColor(black) canvas.setFont(bFont, LfSize) canvas.drawString(hkX, hkY, "Nt id. %") # draw heatmap color scale canvas.setFont(rFont, NfSize) hk_list = sorted(idpt.iterkeys(), reverse=True) hk_list.insert(0, 100) hk_i = 0 hkY -= hk_boxX*1.5 canvas.drawCentredString(hkX+hk_boxX+incrN*3, hkY, str(100)) while hk_i < len(hk_list)-1: hk_boxY = (hk_list[hk_i]-hk_list[hk_i+1])*hk_u hkY -= hk_boxY canvas.setFillColor(HexColor(idpt[hk_list[hk_i+1]])) canvas.rect(hkX, hkY, hk_boxX, hk_boxY, fill=1) canvas.setFillColor(black) canvas.drawCentredString(hkX+hk_boxX+incrN*3, hkY, str(hk_list[hk_i+1])) hk_i += 1
def addPage(canvas, page, strokes): canvas.setLineCap(1) if page['height'] > page['width']: PAGE = (A4[0], A4[1]) else: PAGE = (A4[1], A4[0]) canvas.setPageSize(PAGE) S = PAGE[0] / page['width'] for s in strokes: dots = s['dots'] x0, y0, p0, dt0 = dots[0] for x, y, p, dt in dots[1:]: # the factor 1.5 visually matches the thickness in neonote app canvas.setLineWidth((s['thickness'] + 1.5) * p) col = s['color'] canvas.setStrokeColorRGB(col[1] / 255, col[2] / 255, col[3] / 255) canvas.line(S * x0, S * y0, S * x, S * y) x0, y0, p0 = x, y, p canvas.showPage()
def render_element(root, element, canvas, styles): canvas.saveState() current_style = {} if len(styles): current_style.update(styles[-1]) for declaration in element.get("style", "").split(";"): if declaration == "": continue key, value = declaration.split(":") current_style[key] = value styles.append(current_style) if "stroke-width" in current_style: canvas.setLineWidth(float(current_style["stroke-width"])) if "stroke-dasharray" in current_style: canvas.setDash([ float(length) for length in current_style["stroke-dasharray"].split(",") ]) if current_style.get("visibility") != "hidden": if "transform" in element.attrib: for transformation in element.get("transform").split(")")[::1]: if transformation: transform, arguments = transformation.split("(") arguments = arguments.split(",") if transform.strip() == "translate": if len(arguments) == 2: canvas.translate(float(arguments[0]), float(arguments[1])) elif transform.strip() == "rotate": if len(arguments) == 1: canvas.rotate(float(arguments[0])) if len(arguments) == 3: canvas.translate(float(arguments[1]), float(arguments[2])) canvas.rotate(float(arguments[0])) canvas.translate(-float(arguments[1]), -float(arguments[2])) if element.tag == "svg": if "background-color" in current_style: set_fill_color( canvas, toyplot.color.css(current_style["background-color"])) canvas.rect( 0, 0, float(element.get("width")[:-2]), float(element.get("height")[:-2]), stroke=0, fill=1, ) for child in element: render_element(root, child, canvas, styles) elif element.tag == "g": if element.get("clip-path", None) is not None: clip_id = element.get("clip-path")[5:-1] clip_path = root.find(".//*[@id='%s']" % clip_id) for child in clip_path: if child.tag == "rect": x = float(child.get("x")) y = float(child.get("y")) width = float(child.get("width")) height = float(child.get("height")) path = canvas.beginPath() path.moveTo(x, y) path.lineTo(x + width, y) path.lineTo(x + width, y + height) path.lineTo(x, y + height) path.close() canvas.clipPath(path, stroke=0, fill=1) else: toyplot.log.error("Unhandled clip tag: %s", child.tag) # pragma: no cover for child in element: render_element(root, child, canvas, styles) elif element.tag == "clipPath": pass elif element.tag == "line": stroke = get_stroke(current_style) if stroke is not None: set_stroke_color(canvas, stroke) canvas.setLineCap(get_line_cap(current_style)) canvas.line( float(element.get("x1", 0)), float(element.get("y1", 0)), float(element.get("x2", 0)), float(element.get("y2", 0)), ) elif element.tag == "path": stroke = get_stroke(current_style) if stroke is not None: set_stroke_color(canvas, stroke) canvas.setLineCap(get_line_cap(current_style)) path = canvas.beginPath() commands = element.get("d").split() while len(commands): command = commands.pop(0) if command == "L": path.lineTo(float(commands.pop(0)), float(commands.pop(0))) elif command == "M": path.moveTo(float(commands.pop(0)), float(commands.pop(0))) canvas.drawPath(path) elif element.tag == "polygon": fill, fill_gradient = get_fill(root, current_style) if fill_gradient is not None: raise NotImplementedError( "Gradient <polygon> not implemented." ) # pragma: no cover if fill is not None: set_fill_color(canvas, fill) stroke = get_stroke(current_style) if stroke is not None: set_stroke_color(canvas, stroke) points = [ point.split(",") for point in element.get("points").split() ] path = canvas.beginPath() for point in points[:1]: path.moveTo(float(point[0]), float(point[1])) for point in points[1:]: path.lineTo(float(point[0]), float(point[1])) path.close() canvas.drawPath(path, stroke=stroke is not None, fill=fill is not None) elif element.tag == "rect": fill, fill_gradient = get_fill(root, current_style) if fill is not None: set_fill_color(canvas, fill) stroke = get_stroke(current_style) if stroke is not None: set_stroke_color(canvas, stroke) x = float(element.get("x", 0)) y = float(element.get("y", 0)) width = float(element.get("width")) height = float(element.get("height")) path = canvas.beginPath() path.moveTo(x, y) path.lineTo(x + width, y) path.lineTo(x + width, y + height) path.lineTo(x, y + height) path.close() if fill_gradient is not None: pdf_colors = [] pdf_offsets = [] for stop in fill_gradient: offset = float(stop.get("offset")) color = toyplot.color.css(stop.get("stop-color")) opacity = float(stop.get("stop-opacity")) pdf_colors.append( reportlab.lib.colors.Color(color["r"], color["g"], color["b"], color["a"] * opacity)) pdf_offsets.append(offset) canvas.saveState() canvas.clipPath(path, stroke=0, fill=1) canvas.setFillAlpha(1) canvas.linearGradient( float(fill_gradient.get("x1")), float(fill_gradient.get("y1")), float(fill_gradient.get("x2")), float(fill_gradient.get("y2")), pdf_colors, pdf_offsets, ) canvas.restoreState() canvas.drawPath(path, stroke=stroke is not None, fill=fill is not None) elif element.tag == "circle": fill, fill_gradient = get_fill(root, current_style) if fill_gradient is not None: raise NotImplementedError( "Gradient <circle> not implemented." ) # pragma: no cover if fill is not None: set_fill_color(canvas, fill) stroke = get_stroke(current_style) if stroke is not None: set_stroke_color(canvas, stroke) cx = float(element.get("cx", 0)) cy = float(element.get("cy", 0)) r = float(element.get("r")) canvas.circle(cx, cy, r, stroke=stroke is not None, fill=fill is not None) elif element.tag == "text": x = float(element.get("x", 0)) y = float(element.get("y", 0)) fill, fill_gradient = get_fill(element, current_style) stroke = get_stroke(current_style) font_family = get_font_family(current_style) font_size = toyplot.units.convert(current_style["font-size"], target="px") text = element.text canvas.saveState() canvas.setFont(font_family, font_size) if fill is not None: set_fill_color(canvas, fill) if stroke is not None: set_stroke_color(canvas, stroke) canvas.translate(x, y) canvas.scale(1, -1) canvas.drawString(0, 0, text) canvas.restoreState() elif element.tag == "image": # pylint: disable=redefined-variable-type import PIL.Image image = element.get("xlink:href") if not image.startswith("data:image/png;base64,"): raise ValueError( "Unsupported image type.") # pragma: no cover image = base64.standard_b64decode(image[22:]) image = io.BytesIO(image) image = PIL.Image.open(image) image = reportlab.lib.utils.ImageReader(image) x = float(element.get("x", 0)) y = float(element.get("y", 0)) width = float(element.get("width")) height = float(element.get("height")) canvas.saveState() path = canvas.beginPath() set_fill_color(canvas, toyplot.color.rgb(1, 1, 1)) canvas.rect(x, y, width, height, stroke=0, fill=1) canvas.translate(x, y + height) canvas.scale(1, -1) canvas.drawImage(image=image, x=0, y=0, width=width, height=height, mask=None) canvas.restoreState() elif element.tag in ["defs", "title"]: pass else: raise Exception("unhandled tag: %s" % element.tag) # pragma: no cover styles.pop() canvas.restoreState()
def make_a_table(canvas, ncol, nrow, entries, str_index): width, height = A4 cell_size = 16 * mm table_data = [] for i in range(nrow): row = [] for j in range(ncol): if 1 < j < ncol - 1: row.append('') else: try: row.append(entries[i]) except: row.append('') table_data.append(row) kanji_tbl_style = [] kanji_tbl_style.append(('INNERGRID', (0, 0), (-1, -1), 0.25, colors.black)) kanji_tbl_style.append(('BOX', (0, 0), (-1, -1), 0.25, colors.black)) for i in range(ncol): kanji_tbl_style.append(('ALIGN', (i, 0), (i, -1), 'CENTER')) kanji_tbl_style.append(('VALIGN', (i, 0), (i, -1), 'BOTTOM')) kanji_tbl_style.append(('FONT', (i, 0), (i, -1), 'Stroke', 36)) if i == ncol - 1: kanji_tbl_style.append(('TEXTCOLOR', (i, 0), (i, -1), NAVY)) elif i < 2: kanji_tbl_style.append(('TEXTCOLOR', (i, 0), (i, -1), GRAY)) kanji_tbl = Table(table_data, colWidths=cell_size, rowHeights=cell_size) kanji_tbl.setStyle(TableStyle(kanji_tbl_style)) kanji_tbl.wrapOn(canvas, width, height) table_x, table_y = 12 * mm, 21 * mm kanji_tbl.drawOn(canvas, table_x, table_y) kanji_info = [] info_tbl_style = [] info_style = ParagraphStyle( name='Info', fontName='Hiragino', fontSize=7, ) for i in range(nrow): try: text = Paragraph(kanji_lookup[entries[i]], info_style) kanji_info.append([text]) except: kanji_info.append(['']) info_tbl_style.append(('VALIGN', (0, 0), (-1, -1), 'TOP')) info_tbl = Table(kanji_info, colWidths=50 * mm, rowHeights=cell_size) info_tbl.setStyle(TableStyle(info_tbl_style)) info_tbl.wrapOn(canvas, width, height) info_tbl.drawOn(canvas, table_x + cell_size * ncol, table_y) for i in range(nrow): coord_trans = (table_x + cell_size * ncol + 50 * mm, table_y + cell_size * i) if i % 2 == 1: char_x = table_x + cell_size * ncol + 5 * mm else: char_x = table_x + cell_size * ncol + 22 * mm coord_char = (char_x, table_y + cell_size * i + 2 * mm) try: kanji = entries[nrow - i - 1] canvas.setFillColor(BLACK) canvas.setFont('Times-Italic', 8) canvas.drawRightString(*coord_trans, trans_lookup[kanji]) if kanji in font_lookup['bone']: canvas.setFillColor(GREEN30) canvas.setFont('Bone', 55) elif kanji in font_lookup['tenbun']: canvas.setFillColor(RED30) canvas.setFont('Tenbun', 55) else: continue canvas.drawString(*coord_char, kanji) except: pass sep_x = table_x + cell_size * ncol + 0.5 * mm canvas.setLineWidth(0.1 * mm) canvas.line(sep_x, table_y, sep_x, table_y + cell_size * nrow) canvas.setFillColor(LIGHTGRAY) rect_x, rect_y = table_x, height - 16 * mm canvas.roundRect(rect_x, rect_y, 70 * mm, 10 * mm, 1 * mm, fill=1, stroke=0) canvas.setFont('Hiragino', 12) canvas.setFillColor(BLACK) canvas.drawString(rect_x + 2 * mm, rect_y + 3 * mm, "Joytan Kanji Practice | 漢字練習帳") # Name with underline canvas.setLineWidth(0.1 * mm) canvas.setFillColor(BLACK) canvas.setFont('Hiragino', 10) name_x, name_y = width - 90 * mm, height - 14 * mm canvas.drawString(name_x, name_y, "名前:") canvas.line(name_x, name_y - 2 * mm, name_x + 70 * mm, name_y - 2 * mm) # Left footer canvas.setFont('Helvetica-Bold', 10) coord_msg = (table_x, table_y - 5 * mm) canvas.drawString( *coord_msg, "Support our project: https://kokimame.github.io/joytan/") coord_index = (table_x, table_y - 12 * mm) canvas.drawString(*coord_index, "%s | © Joytan" % str_index) # Right footer coord_l1 = (width - 20 * mm, table_y - 5 * mm) coord_l2 = (width - 20 * mm, table_y - 10 * mm) coord_l3 = (width - 20 * mm, table_y - 13 * mm) canvas.setFont('Hiragino', 9) canvas.drawRightString(*coord_l1, "【部首】/画数/学年 オンヨミ くんよみ") canvas.setFont('Hiragino', 8) canvas.drawRightString( *coord_l2, "【radical】/#stroke/grade Onyomi(Katakana) Kunyomi (Hiragana)") canvas.setFont('Times-Italic', 7) canvas.drawRightString(*coord_l3, "* Rough kanji-wise translation") # Additional lines canvas.setDash([0.1 * mm, 1.2 * mm]) canvas.setLineCap(1) # Dotted vertical lines for i in range(ncol): x = table_x + cell_size / 2 + cell_size * i canvas.line(x, table_y, x, table_y + nrow * cell_size) # Dotted horizontal lines for i in range(nrow): trans_y = table_y + cell_size / 2 + cell_size * i canvas.line(table_x, trans_y, table_x + ncol * cell_size, trans_y) # Separation between the Info panel for i in range(nrow + 1): x = table_x + cell_size * ncol trans_y = table_y + cell_size * i canvas.line(x, trans_y, x + 50 * mm, trans_y) canvas.showPage()