From 64de5a7de73e12babe02a266f90fb44d168eb51f Mon Sep 17 00:00:00 2001 From: bozokopic Date: Mon, 23 Apr 2018 17:20:48 +0200 Subject: pycairo based output --- src_py/opcut/common.py | 3 +- src_py/opcut/main.py | 6 +- src_py/opcut/output.py | 192 ++++++++++++++++++++++--------------------------- 3 files changed, 92 insertions(+), 109 deletions(-) (limited to 'src_py') diff --git a/src_py/opcut/common.py b/src_py/opcut/common.py index 3f24109..5749a92 100644 --- a/src_py/opcut/common.py +++ b/src_py/opcut/common.py @@ -59,7 +59,8 @@ Method = enum.Enum('Method', [ 'FORWARD_GREEDY']) OutputType = enum.Enum('OutputType', [ - 'PDF']) + 'PDF', + 'SVG']) class UnresolvableError(Exception): diff --git a/src_py/opcut/main.py b/src_py/opcut/main.py index 7e39212..b5abdfa 100644 --- a/src_py/opcut/main.py +++ b/src_py/opcut/main.py @@ -83,7 +83,8 @@ def output(args): result_json_data = yaml.safe_load(f) opcut.json_validator.validate(result_json_data, 'opcut://result.yaml#') result = common.json_data_to_result(result_json_data) - output_bytes = opcut.output.generate_output(result, args.output_type, + output_type = common.OutputType[args.output_type] + output_bytes = opcut.output.generate_output(result, output_type, args.output_panel_id) with open(args.output_path, 'wb') as f: f.write(output_bytes) @@ -130,8 +131,7 @@ def _create_parser(): help="calculate result file path " "(specified by opcut://result.yaml#)") p.add_argument( - '--output-type', dest='output_type', type=common.OutputType, - default=common.OutputType.PDF, + '--output-type', dest='output_type', default='PDF', choices=list(map(lambda x: x.name, common.OutputType)), help="output type (default PDF)") p.add_argument( diff --git a/src_py/opcut/output.py b/src_py/opcut/output.py index a66b90f..53bbe7a 100644 --- a/src_py/opcut/output.py +++ b/src_py/opcut/output.py @@ -20,111 +20,93 @@ def generate_output(result, output_type, panel_id=None, """ ret = io.BytesIO() - with cairo.PDFSurface(ret, settings.pagesize[0], - settings.pagesize[1]) as surface: - ctx = cairo.Context(surface) - # TODO + surface_cls = {common.OutputType.PDF: cairo.PDFSurface, + common.OutputType.SVG: cairo.SVGSurface}[output_type] + with surface_cls(ret, settings.pagesize[0], + settings.pagesize[1]) as surface: + for panel in result.params.panels: + if panel_id and panel.id != panel_id: + continue + _write_panel(surface, settings, result, panel) + surface.show_page() return ret.getvalue() -# def generate_pdf(result, pagesize_mm=(210, 297), -# margin_top_mm=10, margin_bottom_mm=20, -# margin_left_mm=10, margin_right_mm=10): -# """Generate PDF output -# -# Args: -# result (opcut.common.Result): result -# pagesize (Tuple[float,float]): page size as (with, height) in mm -# margin_top_mm (float): margin top in mm -# margin_bottom_mm (float): margin bottom in mm -# margin_left_mm (float): margin left in mm -# margin_right_mm (float): margin right in mm -# -# Returns: -# bytes -# -# """ -# pagesize = tuple(map(lambda x: x * mm, pagesize_mm)) -# margin = _Margin(top=margin_top_mm * mm, -# right=margin_right_mm * mm, -# bottom=margin_bottom_mm * mm, -# left=margin_left_mm * mm) -# ret = io.BytesIO() -# c = canvas.Canvas(ret, pagesize=pagesize) -# c.setFillColorRGB(0.9, 0.9, 0.9) -# for panel in result.params.panels: -# _pdf_write_panel(c, pagesize, margin, result, panel) -# c.save() -# return ret.getvalue() -# -# -# def generate_csv(result): -# """Generate CSV output -# -# Args: -# result (opcut.common.Result): result -# -# Returns: -# bytes -# -# """ -# return b'' -# -# -# _Margin = util.namedtuple('_Margin', 'top', 'right', 'bottom', 'left') -# -# -# def _pdf_write_panel(c, pagesize, margin, result, panel): -# if (panel.width / panel.height > -# (pagesize[0] - margin.left - margin.right) / -# (pagesize[1] - margin.top - margin.bottom)): -# scale = ( -# (pagesize[0] - (margin.left + margin.right) * mm) / -# panel.width) -# else: -# scale = ( -# (pagesize[1] - (margin.top + margin.bottom) * mm) / -# panel.height) -# width = panel.width * scale -# height = panel.height * scale -# x0 = ((pagesize[0] - width) * margin.left / -# (margin.left + margin.right)) -# y0 = ((pagesize[1] - height) * margin.bottom / -# (margin.top + margin.bottom)) -# c.setFillColorRGB(0.5, 0.5, 0.5) -# c.rect(x0, y0, width, height, stroke=1, fill=1) -# for used in result.used: -# if used.panel != panel: -# continue -# _pdf_write_used(c, x0, y0, scale, result, used) -# for unused in result.unused: -# if unused.panel != panel: -# continue -# _pdf_write_unused(c, x0, y0, scale, result, unused) -# c.setFillColorRGB(0, 0, 0) -# c.drawCentredString(pagesize[0] / 2, margin.bottom / 2, -# panel.id) -# c.showPage() -# -# -# def _pdf_write_used(c, x0, y0, scale, result, used): -# width = used.item.width * scale -# height = used.item.height * scale -# if used.rotate: -# width, height = height, width -# x = used.x * scale + x0 -# y = (used.panel.height - used.y) * scale + y0 - height -# c.setFillColorRGB(1, 1, 1) -# c.rect(x, y, width, height, stroke=0, fill=1) -# c.setFillColorRGB(0, 0, 0) -# c.drawCentredString(x + width / 2, y + height / 2 - 6, used.item.id) -# -# -# def _pdf_write_unused(c, x0, y0, scale, result, unused): -# width = unused.width * scale -# height = unused.height * scale -# x = unused.x * scale + x0 -# y = (unused.panel.height - unused.y) * scale + y0 - height -# c.setFillColorRGB(0.9, 0.9, 0.9) -# c.rect(x, y, width, height, stroke=0, fill=1) -# +def _write_panel(surface, settings, result, panel): + scale = _calculate_scale(settings, panel) + width = panel.width * scale + height = panel.height * scale + x0 = ((settings.pagesize[0] - width) * settings.margin_left / + (settings.margin_left + settings.margin_right)) + y0 = ((settings.pagesize[1] - height) * settings.margin_top / + (settings.margin_top + settings.margin_bottom)) + + ctx = cairo.Context(surface) + ctx.set_line_width(0) + ctx.set_source_rgb(0.5, 0.5, 0.5) + ctx.rectangle(x0, y0, width, height) + ctx.fill() + + for used in result.used: + if used.panel != panel: + continue + _write_used(surface, scale, x0, y0, used) + + for unused in result.unused: + if unused.panel != panel: + continue + _write_unused(surface, scale, x0, y0, unused) + + _write_centered_text(surface, settings.pagesize[0] / 2, + settings.pagesize[1] - settings.margin_bottom / 2, + panel.id) + + +def _write_used(surface, scale, x0, y0, used): + width = used.item.width * scale + height = used.item.height * scale + if used.rotate: + width, height = height, width + x = x0 + used.x * scale + y = y0 + used.y * scale + + ctx = cairo.Context(surface) + ctx.set_line_width(0) + ctx.set_source_rgb(0.9, 0.9, 0.9) + ctx.rectangle(x, y, width, height) + ctx.fill() + + _write_centered_text(surface, x + width / 2, y + height / 2, used.item.id) + + +def _write_unused(surface, scale, x0, y0, unused): + width = unused.width * scale + height = unused.height * scale + x = x0 + unused.x * scale + y = y0 + unused.y * scale + + ctx = cairo.Context(surface) + ctx.set_line_width(0) + ctx.set_source_rgb(0.7, 0.7, 0.7) + ctx.rectangle(x, y, width, height) + ctx.fill() + + +def _write_centered_text(surface, x, y, text): + ctx = cairo.Context(surface) + ctx.set_source_rgb(0, 0, 0) + text_ext = ctx.text_extents(text) + ctx.move_to(x - text_ext.width / 2, + y + text_ext.height / 2) + ctx.show_text(text) + + +def _calculate_scale(settings, panel): + page_width = (settings.pagesize[0] - settings.margin_left - + settings.margin_right) + page_height = (settings.pagesize[1] - settings.margin_top - + settings.margin_bottom) + page_ratio = page_width / page_height + panel_ratio = panel.width / panel.height + return (page_width / panel.width if panel_ratio > page_ratio + else page_height / panel.height) -- cgit v1.2.3-70-g09d2