From d5f382f4b413d73a96613dd86aa207bb9e665b0d Mon Sep 17 00:00:00 2001 From: Garret Fick Date: Mon, 23 Nov 2015 16:17:31 +0800 Subject: Render with cairo instead of cairocffi - I would like to make it use either, but for now, using the one that works with wxpython --- gerber/render/cairo_backend.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'gerber/render/cairo_backend.py') diff --git a/gerber/render/cairo_backend.py b/gerber/render/cairo_backend.py index 345f331..e4a5eff 100644 --- a/gerber/render/cairo_backend.py +++ b/gerber/render/cairo_backend.py @@ -17,7 +17,7 @@ from .render import GerberContext -import cairocffi as cairo +import cairo from operator import mul import math @@ -52,7 +52,7 @@ class GerberCairoContext(GerberContext): end = map(mul, line.end, self.scale) if isinstance(line.aperture, Circle): width = line.aperture.diameter - self.ctx.set_source_rgba(*color, alpha=self.alpha) + self.ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) self.ctx.set_operator(cairo.OPERATOR_OVER if (line.level_polarity == "dark" and not self.invert) else cairo.OPERATOR_CLEAR) self.ctx.set_line_width(width * self.scale[0]) self.ctx.set_line_cap(cairo.LINE_CAP_ROUND) @@ -61,7 +61,7 @@ class GerberCairoContext(GerberContext): self.ctx.stroke() elif isinstance(line.aperture, Rectangle): points = [tuple(map(mul, x, self.scale)) for x in line.vertices] - self.ctx.set_source_rgba(*color, alpha=self.alpha) + self.ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) self.ctx.set_operator(cairo.OPERATOR_OVER if (line.level_polarity == "dark" and not self.invert) else cairo.OPERATOR_CLEAR) self.ctx.set_line_width(0) self.ctx.move_to(*points[0]) @@ -77,7 +77,7 @@ class GerberCairoContext(GerberContext): angle1 = arc.start_angle angle2 = arc.end_angle width = arc.aperture.diameter if arc.aperture.diameter != 0 else 0.001 - self.ctx.set_source_rgba(*color, alpha=self.alpha) + self.ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) self.ctx.set_operator(cairo.OPERATOR_OVER if (arc.level_polarity == "dark" and not self.invert)else cairo.OPERATOR_CLEAR) self.ctx.set_line_width(width * self.scale[0]) self.ctx.set_line_cap(cairo.LINE_CAP_ROUND) @@ -89,7 +89,8 @@ class GerberCairoContext(GerberContext): self.ctx.move_to(*end) # ...lame def _render_region(self, region, color): - self.ctx.set_source_rgba(*color, alpha=self.alpha) + self.ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) + #self.ctx.set_source_rgba(*color, alpha=self.alpha) self.ctx.set_operator(cairo.OPERATOR_OVER if (region.level_polarity == "dark" and not self.invert) else cairo.OPERATOR_CLEAR) self.ctx.set_line_width(0) self.ctx.set_line_cap(cairo.LINE_CAP_ROUND) @@ -112,7 +113,7 @@ class GerberCairoContext(GerberContext): def _render_circle(self, circle, color): center = tuple(map(mul, circle.position, self.scale)) - self.ctx.set_source_rgba(*color, alpha=self.alpha) + self.ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) self.ctx.set_operator(cairo.OPERATOR_OVER if (circle.level_polarity == "dark" and not self.invert) else cairo.OPERATOR_CLEAR) self.ctx.set_line_width(0) self.ctx.arc(*center, radius=circle.radius * self.scale[0], angle1=0, angle2=2 * math.pi) @@ -121,7 +122,7 @@ class GerberCairoContext(GerberContext): def _render_rectangle(self, rectangle, color): ll = map(mul, rectangle.lower_left, self.scale) width, height = tuple(map(mul, (rectangle.width, rectangle.height), map(abs, self.scale))) - self.ctx.set_source_rgba(*color, alpha=self.alpha) + self.ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) self.ctx.set_operator(cairo.OPERATOR_OVER if (rectangle.level_polarity == "dark" and not self.invert) else cairo.OPERATOR_CLEAR) self.ctx.set_line_width(0) self.ctx.rectangle(*ll,width=width, height=height) -- cgit From 8eede187f3f644c4f8a0de0dc5825dc4c00c7b8f Mon Sep 17 00:00:00 2001 From: Garret Fick Date: Mon, 23 Nov 2015 22:22:30 +0800 Subject: More fixes to work with cairo --- gerber/render/cairo_backend.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'gerber/render/cairo_backend.py') diff --git a/gerber/render/cairo_backend.py b/gerber/render/cairo_backend.py index e4a5eff..81c5ce4 100644 --- a/gerber/render/cairo_backend.py +++ b/gerber/render/cairo_backend.py @@ -61,7 +61,7 @@ class GerberCairoContext(GerberContext): self.ctx.stroke() elif isinstance(line.aperture, Rectangle): points = [tuple(map(mul, x, self.scale)) for x in line.vertices] - self.ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) + self.ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) self.ctx.set_operator(cairo.OPERATOR_OVER if (line.level_polarity == "dark" and not self.invert) else cairo.OPERATOR_CLEAR) self.ctx.set_line_width(0) self.ctx.move_to(*points[0]) @@ -83,14 +83,13 @@ class GerberCairoContext(GerberContext): self.ctx.set_line_cap(cairo.LINE_CAP_ROUND) self.ctx.move_to(*start) # You actually have to do this... if arc.direction == 'counterclockwise': - self.ctx.arc(*center, radius=radius, angle1=angle1, angle2=angle2) + self.ctx.arc(center[0], center[1], radius, angle1, angle2) else: - self.ctx.arc_negative(*center, radius=radius, angle1=angle1, angle2=angle2) + self.ctx.arc_negative(center[0], center[1], radius, angle1, angle2) self.ctx.move_to(*end) # ...lame def _render_region(self, region, color): self.ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) - #self.ctx.set_source_rgba(*color, alpha=self.alpha) self.ctx.set_operator(cairo.OPERATOR_OVER if (region.level_polarity == "dark" and not self.invert) else cairo.OPERATOR_CLEAR) self.ctx.set_line_width(0) self.ctx.set_line_cap(cairo.LINE_CAP_ROUND) @@ -106,9 +105,9 @@ class GerberCairoContext(GerberContext): angle1 = p.start_angle angle2 = p.end_angle if p.direction == 'counterclockwise': - self.ctx.arc(*center, radius=radius, angle1=angle1, angle2=angle2) + self.ctx.arc(center[0], center[1], radius, angle1, angle2) else: - self.ctx.arc_negative(*center, radius=radius, angle1=angle1, angle2=angle2) + self.ctx.arc_negative(center[0], center[1], radius, angle1, angle2) self.ctx.fill() def _render_circle(self, circle, color): @@ -116,7 +115,7 @@ class GerberCairoContext(GerberContext): self.ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) self.ctx.set_operator(cairo.OPERATOR_OVER if (circle.level_polarity == "dark" and not self.invert) else cairo.OPERATOR_CLEAR) self.ctx.set_line_width(0) - self.ctx.arc(*center, radius=circle.radius * self.scale[0], angle1=0, angle2=2 * math.pi) + self.ctx.arc(center[0], center[1], circle.radius * self.scale[0], 0, 2 * math.pi) self.ctx.fill() def _render_rectangle(self, rectangle, color): @@ -148,7 +147,7 @@ class GerberCairoContext(GerberContext): self.ctx.scale(1, -1) def _paint_inverted_layer(self): - self.ctx.set_source_rgba(*self.background_color) + self.ctx.set_source_rgba(self.background_color[0], self.background_color[1], self.background_color[2]) self.ctx.set_operator(cairo.OPERATOR_OVER) self.ctx.paint() self.ctx.set_operator(cairo.OPERATOR_CLEAR) @@ -156,7 +155,7 @@ class GerberCairoContext(GerberContext): def _paint_background(self): if not self.bg: self.bg = True - self.ctx.set_source_rgba(*self.background_color) + self.ctx.set_source_rgba(self.background_color[0], self.background_color[1], self.background_color[2]) self.ctx.paint() def dump(self, filename): -- cgit From d69f50e0f62570a4c327cb8fe4f886f439196010 Mon Sep 17 00:00:00 2001 From: Garret Fick Date: Wed, 2 Dec 2015 12:44:30 +0800 Subject: Make the hit accessible from the drawable Hit, fix crash with cario drawing rect --- gerber/render/cairo_backend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gerber/render/cairo_backend.py') diff --git a/gerber/render/cairo_backend.py b/gerber/render/cairo_backend.py index 81c5ce4..4a0724f 100644 --- a/gerber/render/cairo_backend.py +++ b/gerber/render/cairo_backend.py @@ -124,7 +124,7 @@ class GerberCairoContext(GerberContext): self.ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) self.ctx.set_operator(cairo.OPERATOR_OVER if (rectangle.level_polarity == "dark" and not self.invert) else cairo.OPERATOR_CLEAR) self.ctx.set_line_width(0) - self.ctx.rectangle(*ll,width=width, height=height) + self.ctx.rectangle(ll[0], ll[1], width, height) self.ctx.fill() def _render_obround(self, obround, color): -- cgit From 206f4c57ab66f8a6753015340315991b40178c9b Mon Sep 17 00:00:00 2001 From: Garret Fick Date: Wed, 16 Dec 2015 18:59:25 +0800 Subject: Fix drawing arcs. Dont crash for arcs with rectangular apertures. Fix crash with board size of zero for only one drill --- gerber/render/cairo_backend.py | 1 + 1 file changed, 1 insertion(+) (limited to 'gerber/render/cairo_backend.py') diff --git a/gerber/render/cairo_backend.py b/gerber/render/cairo_backend.py index 4a0724f..4d71199 100644 --- a/gerber/render/cairo_backend.py +++ b/gerber/render/cairo_backend.py @@ -87,6 +87,7 @@ class GerberCairoContext(GerberContext): else: self.ctx.arc_negative(center[0], center[1], radius, angle1, angle2) self.ctx.move_to(*end) # ...lame + self.ctx.stroke() def _render_region(self, region, color): self.ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) -- cgit From 4a815bf25ddd1d378ec6ad5af008e5bbcd362b51 Mon Sep 17 00:00:00 2001 From: Garret Fick Date: Wed, 30 Dec 2015 14:05:00 +0800 Subject: First time any macro renders --- gerber/render/cairo_backend.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'gerber/render/cairo_backend.py') diff --git a/gerber/render/cairo_backend.py b/gerber/render/cairo_backend.py index 4d71199..3ee38ae 100644 --- a/gerber/render/cairo_backend.py +++ b/gerber/render/cairo_backend.py @@ -122,11 +122,27 @@ class GerberCairoContext(GerberContext): def _render_rectangle(self, rectangle, color): ll = map(mul, rectangle.lower_left, self.scale) width, height = tuple(map(mul, (rectangle.width, rectangle.height), map(abs, self.scale))) + + if rectangle.rotation != 0: + self.ctx.save() + + center = map(mul, rectangle.position, self.scale) + matrix = cairo.Matrix() + matrix.translate(center[0], center[1]) + # For drawing, we already handles the translation + ll[0] = ll[0] - center[0] + ll[1] = ll[1] - center[1] + matrix.rotate(rectangle.rotation) + self.ctx.transform(matrix) + self.ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) self.ctx.set_operator(cairo.OPERATOR_OVER if (rectangle.level_polarity == "dark" and not self.invert) else cairo.OPERATOR_CLEAR) self.ctx.set_line_width(0) self.ctx.rectangle(ll[0], ll[1], width, height) self.ctx.fill() + + if rectangle.rotation != 0: + self.ctx.restore() def _render_obround(self, obround, color): self._render_circle(obround.subshapes['circle1'], color) @@ -135,6 +151,10 @@ class GerberCairoContext(GerberContext): def _render_drill(self, circle, color): self._render_circle(circle, color) + + def _render_amgroup(self, amgroup, color): + for primitive in amgroup.primitives: + self.render(primitive) def _render_test_record(self, primitive, color): self.ctx.select_font_face('monospace', cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) -- cgit From f61eee807f87c329f6f88645ecdb48f01b887c52 Mon Sep 17 00:00:00 2001 From: Garret Fick Date: Wed, 30 Dec 2015 18:44:07 +0800 Subject: Render polygon flashes --- gerber/render/cairo_backend.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'gerber/render/cairo_backend.py') diff --git a/gerber/render/cairo_backend.py b/gerber/render/cairo_backend.py index 3ee38ae..68e9e98 100644 --- a/gerber/render/cairo_backend.py +++ b/gerber/render/cairo_backend.py @@ -148,6 +148,22 @@ class GerberCairoContext(GerberContext): self._render_circle(obround.subshapes['circle1'], color) self._render_circle(obround.subshapes['circle2'], color) self._render_rectangle(obround.subshapes['rectangle'], color) + + def _render_polygon(self, polygon, color): + vertices = polygon.vertices + + self.ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) + self.ctx.set_operator(cairo.OPERATOR_OVER if (polygon.level_polarity == "dark" and not self.invert) else cairo.OPERATOR_CLEAR) + self.ctx.set_line_width(0) + self.ctx.set_line_cap(cairo.LINE_CAP_ROUND) + + # Start from before the end so it is easy to iterate and make sure it is closed + self.ctx.move_to(*map(mul, vertices[-1], self.scale)) + for v in vertices: + self.ctx.line_to(*map(mul, v, self.scale)) + + self.ctx.fill() + def _render_drill(self, circle, color): self._render_circle(circle, color) -- cgit From 83ae0670d11b5f5ef8ba3a6c362b7129a9e31ab3 Mon Sep 17 00:00:00 2001 From: Garret Fick Date: Fri, 8 Jan 2016 00:19:47 +0800 Subject: More stability fixes for poorly constructed files --- gerber/render/cairo_backend.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'gerber/render/cairo_backend.py') diff --git a/gerber/render/cairo_backend.py b/gerber/render/cairo_backend.py index 68e9e98..fbc4271 100644 --- a/gerber/render/cairo_backend.py +++ b/gerber/render/cairo_backend.py @@ -76,7 +76,10 @@ class GerberCairoContext(GerberContext): radius = self.scale[0] * arc.radius angle1 = arc.start_angle angle2 = arc.end_angle - width = arc.aperture.diameter if arc.aperture.diameter != 0 else 0.001 + if isinstance(arc.aperture, Circle): + width = arc.aperture.diameter if arc.aperture.diameter != 0 else 0.001 + else: + width = max(arc.aperture.width, arc.aperture.height, 0.001) self.ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) self.ctx.set_operator(cairo.OPERATOR_OVER if (arc.level_polarity == "dark" and not self.invert)else cairo.OPERATOR_CLEAR) self.ctx.set_line_width(width * self.scale[0]) @@ -163,7 +166,6 @@ class GerberCairoContext(GerberContext): self.ctx.line_to(*map(mul, v, self.scale)) self.ctx.fill() - def _render_drill(self, circle, color): self._render_circle(circle, color) -- cgit From 96bdd0f59dbda9b755b0eb28eb44cb9a6eae1410 Mon Sep 17 00:00:00 2001 From: Garret Fick Date: Sun, 31 Jan 2016 15:24:57 +0800 Subject: Keep track of quadrant mode so we can draw full circles --- gerber/render/cairo_backend.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'gerber/render/cairo_backend.py') diff --git a/gerber/render/cairo_backend.py b/gerber/render/cairo_backend.py index fbc4271..7be7e6a 100644 --- a/gerber/render/cairo_backend.py +++ b/gerber/render/cairo_backend.py @@ -76,6 +76,9 @@ class GerberCairoContext(GerberContext): radius = self.scale[0] * arc.radius angle1 = arc.start_angle angle2 = arc.end_angle + if angle1 == angle2 and arc.quadrant_mode != 'single-quadrant': + # Make the angles slightly different otherwise Cario will draw nothing + angle2 -= 0.000000001 if isinstance(arc.aperture, Circle): width = arc.aperture.diameter if arc.aperture.diameter != 0 else 0.001 else: -- cgit From acde19f205898188c03a46e5d8a7a6a4d4637a2d Mon Sep 17 00:00:00 2001 From: Garret Fick Date: Sat, 26 Mar 2016 15:59:42 +0800 Subject: Support for the G85 slot statement --- gerber/render/cairo_backend.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'gerber/render/cairo_backend.py') diff --git a/gerber/render/cairo_backend.py b/gerber/render/cairo_backend.py index 7be7e6a..d895e5c 100644 --- a/gerber/render/cairo_backend.py +++ b/gerber/render/cairo_backend.py @@ -173,6 +173,20 @@ class GerberCairoContext(GerberContext): def _render_drill(self, circle, color): self._render_circle(circle, color) + def _render_slot(self, slot, color): + start = map(mul, slot.start, self.scale) + end = map(mul, slot.end, self.scale) + + width = slot.diameter + + self.ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) + self.ctx.set_operator(cairo.OPERATOR_OVER if (slot.level_polarity == "dark" and not self.invert) else cairo.OPERATOR_CLEAR) + self.ctx.set_line_width(width * self.scale[0]) + self.ctx.set_line_cap(cairo.LINE_CAP_ROUND) + self.ctx.move_to(*start) + self.ctx.line_to(*end) + self.ctx.stroke() + def _render_amgroup(self, amgroup, color): for primitive in amgroup.primitives: self.render(primitive) -- cgit From 199a0f3d3c5d4dbbc4ac6e8d1b4548523e44f00f Mon Sep 17 00:00:00 2001 From: Qau Lau Date: Fri, 8 Apr 2016 20:02:04 +0800 Subject: Update cairo_backend.py If cairo module import error use cairocffi --- gerber/render/cairo_backend.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'gerber/render/cairo_backend.py') diff --git a/gerber/render/cairo_backend.py b/gerber/render/cairo_backend.py index d895e5c..1d168ca 100644 --- a/gerber/render/cairo_backend.py +++ b/gerber/render/cairo_backend.py @@ -17,7 +17,10 @@ from .render import GerberContext -import cairo +try: + import cairo +except ImportError: + import cairocffi as cairo from operator import mul import math @@ -233,4 +236,4 @@ class GerberCairoContext(GerberContext): self.surface.finish() self.surface_buffer.flush() return self.surface_buffer.read() - \ No newline at end of file + -- cgit From b01c4822b6da6b7be37becb73c58f60621f6366f Mon Sep 17 00:00:00 2001 From: Garret Fick Date: Sat, 25 Jun 2016 12:27:28 +0800 Subject: Render aperture macros with clear regions --- gerber/render/cairo_backend.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'gerber/render/cairo_backend.py') diff --git a/gerber/render/cairo_backend.py b/gerber/render/cairo_backend.py index 1d168ca..c1bd60c 100644 --- a/gerber/render/cairo_backend.py +++ b/gerber/render/cairo_backend.py @@ -191,8 +191,11 @@ class GerberCairoContext(GerberContext): self.ctx.stroke() def _render_amgroup(self, amgroup, color): + self.ctx.push_group() for primitive in amgroup.primitives: self.render(primitive) + self.ctx.pop_group_to_source() + self.ctx.paint_with_alpha(1) def _render_test_record(self, primitive, color): self.ctx.select_font_face('monospace', cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) -- cgit From ccb6eb7a766bd6edf314978f3ec4fc0dcd61652d Mon Sep 17 00:00:00 2001 From: Garret Fick Date: Sat, 25 Jun 2016 16:46:44 +0800 Subject: Add support for polygon apertures --- gerber/render/cairo_backend.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'gerber/render/cairo_backend.py') diff --git a/gerber/render/cairo_backend.py b/gerber/render/cairo_backend.py index c1bd60c..2b7c2ff 100644 --- a/gerber/render/cairo_backend.py +++ b/gerber/render/cairo_backend.py @@ -159,6 +159,9 @@ class GerberCairoContext(GerberContext): self._render_rectangle(obround.subshapes['rectangle'], color) def _render_polygon(self, polygon, color): + if polygon.hole_radius > 0: + self.ctx.push_group() + vertices = polygon.vertices self.ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) @@ -172,6 +175,18 @@ class GerberCairoContext(GerberContext): self.ctx.line_to(*map(mul, v, self.scale)) self.ctx.fill() + + if polygon.hole_radius > 0: + # Render the center clear + center = tuple(map(mul, polygon.position, self.scale)) + self.ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) + self.ctx.set_operator(cairo.OPERATOR_CLEAR) + self.ctx.set_line_width(0) + self.ctx.arc(center[0], center[1], polygon.hole_radius * self.scale[0], 0, 2 * math.pi) + self.ctx.fill() + + self.ctx.pop_group_to_source() + self.ctx.paint_with_alpha(1) def _render_drill(self, circle, color): self._render_circle(circle, color) -- cgit From f0585baefa54c5cd891ba04c81053956b1a59977 Mon Sep 17 00:00:00 2001 From: Garret Fick Date: Sun, 17 Jul 2016 13:14:54 +0800 Subject: Create first test that renders and validates the the rendered PNG is correct. --- gerber/render/cairo_backend.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'gerber/render/cairo_backend.py') diff --git a/gerber/render/cairo_backend.py b/gerber/render/cairo_backend.py index 5a3c7a1..3c4a395 100644 --- a/gerber/render/cairo_backend.py +++ b/gerber/render/cairo_backend.py @@ -292,8 +292,7 @@ class GerberCairoContext(GerberContext): self.ctx.paint() def dump(self, filename): - is_svg = filename.lower().endswith(".svg") - if is_svg: + if filename and filename.lower().endswith(".svg"): self.surface.finish() self.surface_buffer.flush() with open(filename, "w") as f: @@ -301,7 +300,7 @@ class GerberCairoContext(GerberContext): f.write(self.surface_buffer.read()) f.flush() else: - self.surface.write_to_png(filename) + return self.surface.write_to_png(filename) def dump_svg_str(self): self.surface.finish() -- cgit From 7cd6acf12670f3773113f67ed2acb35cb21c32a0 Mon Sep 17 00:00:00 2001 From: Garret Fick Date: Sun, 24 Jul 2016 17:08:47 +0800 Subject: Add many render tests based on the Umaco gerger specification. Fix multiple rendering bugs, especially related to holes in flashed apertures --- gerber/render/cairo_backend.py | 105 ++++++++++++++++++++++++++++++++--------- 1 file changed, 84 insertions(+), 21 deletions(-) (limited to 'gerber/render/cairo_backend.py') diff --git a/gerber/render/cairo_backend.py b/gerber/render/cairo_backend.py index 0cb230b..78ccf34 100644 --- a/gerber/render/cairo_backend.py +++ b/gerber/render/cairo_backend.py @@ -20,13 +20,14 @@ try: except ImportError: import cairocffi as cairo -from operator import mul, div import math +from operator import mul, div import tempfile +from ..primitives import * from .render import GerberContext, RenderSettings from .theme import THEMES -from ..primitives import * + try: from cStringIO import StringIO @@ -219,15 +220,30 @@ class GerberCairoContext(GerberContext): center = tuple(map(mul, circle.position, self.scale)) if not self.invert: ctx = self.ctx - ctx.set_source_rgba(*color, alpha=self.alpha) + ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) ctx.set_operator(cairo.OPERATOR_OVER if circle.level_polarity == "dark" else cairo.OPERATOR_CLEAR) else: ctx = self.mask_ctx ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) ctx.set_operator(cairo.OPERATOR_CLEAR) + + if circle.hole_diameter > 0: + ctx.push_group() + ctx.set_line_width(0) ctx.arc(center[0], center[1], radius=circle.radius * self.scale[0], angle1=0, angle2=2 * math.pi) - ctx.fill() + ctx.fill() + + if circle.hole_diameter > 0: + # Render the center clear + + ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) + ctx.set_operator(cairo.OPERATOR_CLEAR) + ctx.arc(center[0], center[1], radius=circle.hole_radius * self.scale[0], angle1=0, angle2=2 * math.pi) + ctx.fill() + + ctx.pop_group_to_source() + ctx.paint_with_alpha(1) def _render_rectangle(self, rectangle, color): ll = map(mul, rectangle.lower_left, self.scale) @@ -253,48 +269,95 @@ class GerberCairoContext(GerberContext): ll[1] = ll[1] - center[1] matrix.rotate(rectangle.rotation) ctx.transform(matrix) - + + if rectangle.hole_diameter > 0: + ctx.push_group() + ctx.set_line_width(0) ctx.rectangle(ll[0], ll[1], width, height) ctx.fill() + if rectangle.hole_diameter > 0: + # Render the center clear + ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) + ctx.set_operator(cairo.OPERATOR_CLEAR) + center = map(mul, rectangle.position, self.scale) + ctx.arc(center[0], center[1], radius=rectangle.hole_radius * self.scale[0], angle1=0, angle2=2 * math.pi) + ctx.fill() + + ctx.pop_group_to_source() + ctx.paint_with_alpha(1) + if rectangle.rotation != 0: ctx.restore() def _render_obround(self, obround, color): + + if not self.invert: + ctx = self.ctx + ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) + ctx.set_operator(cairo.OPERATOR_OVER if obround.level_polarity == "dark" else cairo.OPERATOR_CLEAR) + else: + ctx = self.mask_ctx + ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) + ctx.set_operator(cairo.OPERATOR_CLEAR) + + if obround.hole_diameter > 0: + ctx.push_group() + self._render_circle(obround.subshapes['circle1'], color) self._render_circle(obround.subshapes['circle2'], color) self._render_rectangle(obround.subshapes['rectangle'], color) + if obround.hole_diameter > 0: + # Render the center clear + ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) + ctx.set_operator(cairo.OPERATOR_CLEAR) + center = map(mul, obround.position, self.scale) + ctx.arc(center[0], center[1], radius=obround.hole_radius * self.scale[0], angle1=0, angle2=2 * math.pi) + ctx.fill() + + ctx.pop_group_to_source() + ctx.paint_with_alpha(1) + def _render_polygon(self, polygon, color): + + # TODO Ths does not handle rotation of a polygon + if not self.invert: + ctx = self.ctx + ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) + ctx.set_operator(cairo.OPERATOR_OVER if polygon.level_polarity == "dark" else cairo.OPERATOR_CLEAR) + else: + ctx = self.mask_ctx + ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) + ctx.set_operator(cairo.OPERATOR_CLEAR) + if polygon.hole_radius > 0: - self.ctx.push_group() + ctx.push_group() vertices = polygon.vertices - - self.ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) - self.ctx.set_operator(cairo.OPERATOR_OVER if (polygon.level_polarity == "dark" and not self.invert) else cairo.OPERATOR_CLEAR) - self.ctx.set_line_width(0) - self.ctx.set_line_cap(cairo.LINE_CAP_ROUND) + + ctx.set_line_width(0) + ctx.set_line_cap(cairo.LINE_CAP_ROUND) # Start from before the end so it is easy to iterate and make sure it is closed - self.ctx.move_to(*map(mul, vertices[-1], self.scale)) + ctx.move_to(*map(mul, vertices[-1], self.scale)) for v in vertices: - self.ctx.line_to(*map(mul, v, self.scale)) + ctx.line_to(*map(mul, v, self.scale)) - self.ctx.fill() + ctx.fill() if polygon.hole_radius > 0: # Render the center clear center = tuple(map(mul, polygon.position, self.scale)) - self.ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) - self.ctx.set_operator(cairo.OPERATOR_CLEAR) - self.ctx.set_line_width(0) - self.ctx.arc(center[0], center[1], polygon.hole_radius * self.scale[0], 0, 2 * math.pi) - self.ctx.fill() + ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) + ctx.set_operator(cairo.OPERATOR_CLEAR) + ctx.set_line_width(0) + ctx.arc(center[0], center[1], polygon.hole_radius * self.scale[0], 0, 2 * math.pi) + ctx.fill() - self.ctx.pop_group_to_source() - self.ctx.paint_with_alpha(1) + ctx.pop_group_to_source() + ctx.paint_with_alpha(1) def _render_drill(self, circle, color): self._render_circle(circle, color) -- cgit From 8cd842a41a55ab3d8f558a2e3e198beba7da58a1 Mon Sep 17 00:00:00 2001 From: Hamilton Kibbe Date: Thu, 21 Jan 2016 03:57:44 -0500 Subject: Manually mere rendering changes --- gerber/render/cairo_backend.py | 395 +++++++++++++++++++++-------------------- 1 file changed, 207 insertions(+), 188 deletions(-) (limited to 'gerber/render/cairo_backend.py') diff --git a/gerber/render/cairo_backend.py b/gerber/render/cairo_backend.py index 78ccf34..349640a 100644 --- a/gerber/render/cairo_backend.py +++ b/gerber/render/cairo_backend.py @@ -12,7 +12,7 @@ # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and +# See the License for the specific language governing permissions and # limitations under the License. try: @@ -21,7 +21,8 @@ except ImportError: import cairocffi as cairo import math -from operator import mul, div +from operator import mul, di + import tempfile from ..primitives import * @@ -36,11 +37,14 @@ except(ImportError): class GerberCairoContext(GerberContext): + def __init__(self, scale=300): - GerberContext.__init__(self) + super(GerberCairoContext, self).__init__() self.scale = (scale, scale) self.surface = None self.ctx = None + self.active_layer = None + self.output_ctx = None self.bg = False self.mask = None self.mask_ctx = None @@ -50,37 +54,40 @@ class GerberCairoContext(GerberContext): @property def origin_in_pixels(self): - return tuple(map(mul, self.origin_in_inch, self.scale)) if self.origin_in_inch is not None else (0.0, 0.0) + return (self.scale_point(self.origin_in_inch) + if self.origin_in_inch is not None else (0.0, 0.0)) @property def size_in_pixels(self): - return tuple(map(mul, self.size_in_inch, self.scale)) if self.size_in_inch is not None else (0.0, 0.0) + return (self.scale_point(self.size_in_inch) + if self.size_in_inch is not None else (0.0, 0.0)) def set_bounds(self, bounds, new_surface=False): origin_in_inch = (bounds[0][0], bounds[1][0]) - size_in_inch = (abs(bounds[0][1] - bounds[0][0]), abs(bounds[1][1] - bounds[1][0])) - size_in_pixels = tuple(map(mul, size_in_inch, self.scale)) + size_in_inch = (abs(bounds[0][1] - bounds[0][0]), + abs(bounds[1][1] - bounds[1][0])) + size_in_pixels = self.scale_point(size_in_inch) self.origin_in_inch = origin_in_inch if self.origin_in_inch is None else self.origin_in_inch self.size_in_inch = size_in_inch if self.size_in_inch is None else self.size_in_inch if (self.surface is None) or new_surface: self.surface_buffer = tempfile.NamedTemporaryFile() - self.surface = cairo.SVGSurface(self.surface_buffer, size_in_pixels[0], size_in_pixels[1]) - self.ctx = cairo.Context(self.surface) - self.ctx.set_fill_rule(cairo.FILL_RULE_EVEN_ODD) - self.ctx.scale(1, -1) - self.ctx.translate(-(origin_in_inch[0] * self.scale[0]), (-origin_in_inch[1]*self.scale[0]) - size_in_pixels[1]) - self.mask = cairo.SVGSurface(None, size_in_pixels[0], size_in_pixels[1]) - self.mask_ctx = cairo.Context(self.mask) - self.mask_ctx.set_fill_rule(cairo.FILL_RULE_EVEN_ODD) - self.mask_ctx.scale(1, -1) - self.mask_ctx.translate(-(origin_in_inch[0] * self.scale[0]), (-origin_in_inch[1]*self.scale[0]) - size_in_pixels[1]) - self._xform_matrix = cairo.Matrix(xx=1.0, yy=-1.0, x0=-self.origin_in_pixels[0], y0=self.size_in_pixels[1] + self.origin_in_pixels[1]) + self.surface = cairo.SVGSurface( + self.surface_buffer, size_in_pixels[0], size_in_pixels[1]) + self.output_ctx = cairo.Context(self.surface) + self.output_ctx.set_fill_rule(cairo.FILL_RULE_EVEN_ODD) + self.output_ctx.scale(1, -1) + self.output_ctx.translate(-(origin_in_inch[0] * self.scale[0]), + (-origin_in_inch[1] * self.scale[0]) - size_in_pixels[1]) + self._xform_matrix = cairo.Matrix(xx=1.0, yy=-1.0, + x0=-self.origin_in_pixels[0], + y0=self.size_in_pixels[1] + self.origin_in_pixels[1]) def render_layers(self, layers, filename, theme=THEMES['default']): """ Render a set of layers """ self.set_bounds(layers[0].bounds, True) self._paint_background(True) + for layer in layers: self._render_layer(layer, theme) self.dump(filename) @@ -117,46 +124,46 @@ class GerberCairoContext(GerberContext): self.color = settings.color self.alpha = settings.alpha self.invert = settings.invert + + # Get a new clean layer to render on + self._new_render_layer() if settings.mirror: raise Warning('mirrored layers aren\'t supported yet...') - if self.invert: - self._clear_mask() for prim in layer.primitives: self.render(prim) - if self.invert: - self._render_mask() + # Add layer to image + self._flatten() def _render_line(self, line, color): - start = map(mul, line.start, self.scale) - end = map(mul, line.end, self.scale) + start = [pos * scale for pos, scale in zip(line.start, self.scale)] + end = [pos * scale for pos, scale in zip(line.end, self.scale)] if not self.invert: - ctx = self.ctx - ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) - ctx.set_operator(cairo.OPERATOR_OVER if line.level_polarity == "dark" else cairo.OPERATOR_CLEAR) + self.ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) + self.ctx.set_operator(cairo.OPERATOR_OVER + if line.level_polarity == "dark" + else cairo.OPERATOR_CLEAR) else: - ctx = self.mask_ctx - ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) - ctx.set_operator(cairo.OPERATOR_CLEAR) + self.ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) + self.ctx.set_operator(cairo.OPERATOR_CLEAR) if isinstance(line.aperture, Circle): - width = line.aperture.diameter - ctx.set_line_width(width * self.scale[0]) - ctx.set_line_cap(cairo.LINE_CAP_ROUND) - - ctx.move_to(*start) - ctx.line_to(*end) - ctx.stroke() + width = line.aperture.diameter + self.ctx.set_line_width(width * self.scale[0]) + self.ctx.set_line_cap(cairo.LINE_CAP_ROUND) + self.ctx.move_to(*start) + self.ctx.line_to(*end) + self.ctx.stroke() elif isinstance(line.aperture, Rectangle): - points = [tuple(map(mul, x, self.scale)) for x in line.vertices] - ctx.set_line_width(0) - ctx.move_to(*points[0]) + points = [self.scale_point(x) for x in line.vertices] + self.ctx.set_line_width(0) + self.ctx.move_to(*points[0]) for point in points[1:]: - ctx.line_to(*point) - ctx.fill() + self.ctx.line_to(*point) + self.ctx.fill() def _render_arc(self, arc, color): - center = map(mul, arc.center, self.scale) - start = map(mul, arc.start, self.scale) - end = map(mul, arc.end, self.scale) + center = self.scale_point(arc.center) + start = self.scale_point(arc.start) + end = self.scale_point(arc.end) radius = self.scale[0] * arc.radius angle1 = arc.start_angle angle2 = arc.end_angle @@ -169,141 +176,137 @@ class GerberCairoContext(GerberContext): width = max(arc.aperture.width, arc.aperture.height, 0.001) if not self.invert: - ctx = self.ctx - ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) - ctx.set_operator(cairo.OPERATOR_OVER if arc.level_polarity == "dark" else cairo.OPERATOR_CLEAR) + self.ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) + self.ctx.set_operator(cairo.OPERATOR_OVER + if arc.level_polarity == "dark"\ + else cairo.OPERATOR_CLEAR) else: - ctx = self.mask_ctx - ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) - ctx.set_operator(cairo.OPERATOR_CLEAR) + self.ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) + self.ctx.set_operator(cairo.OPERATOR_CLEAR) - ctx.set_line_width(width * self.scale[0]) - ctx.set_line_cap(cairo.LINE_CAP_ROUND) - ctx.move_to(*start) # You actually have to do this... + self.ctx.set_line_width(width * self.scale[0]) + self.ctx.set_line_cap(cairo.LINE_CAP_ROUND) + self.ctx.move_to(*start) # You actually have to do this... if arc.direction == 'counterclockwise': - ctx.arc(center[0], center[1], radius, angle1, angle2) + self.ctx.arc(center[0], center[1], radius, angle1, angle2) else: - ctx.arc_negative(center[0], center[1], radius, angle1, angle2) - ctx.move_to(*end) # ...lame - ctx.stroke() + self.ctx.arc_negative(center[0], center[1], radius, angle1, angle2) + self.ctx.move_to(*end) # ...lame def _render_region(self, region, color): if not self.invert: - ctx = self.ctx - ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) - ctx.set_operator(cairo.OPERATOR_OVER if region.level_polarity == "dark" else cairo.OPERATOR_CLEAR) + self.ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) + self.ctx.set_operator(cairo.OPERATOR_OVER + if region.level_polarity == "dark" + else cairo.OPERATOR_CLEAR) else: - ctx = self.mask_ctx - ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) - ctx.set_operator(cairo.OPERATOR_CLEAR) - - ctx.set_line_width(0) - ctx.set_line_cap(cairo.LINE_CAP_ROUND) - ctx.move_to(*tuple(map(mul, region.primitives[0].start, self.scale))) - for p in region.primitives: - if isinstance(p, Line): - ctx.line_to(*tuple(map(mul, p.end, self.scale))) + self.ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) + self.ctx.set_operator(cairo.OPERATOR_CLEAR) + + self.ctx.set_line_width(0) + self.ctx.set_line_cap(cairo.LINE_CAP_ROUND) + self.ctx.move_to(*self.scale_point(region.primitives[0].start)) + for prim in region.primitives: + if isinstance(prim, Line): + self.ctx.line_to(*self.scale_point(prim.end)) else: - center = map(mul, p.center, self.scale) - start = map(mul, p.start, self.scale) - end = map(mul, p.end, self.scale) - radius = self.scale[0] * p.radius - angle1 = p.start_angle - angle2 = p.end_angle - if p.direction == 'counterclockwise': - ctx.arc(center[0], center[1], radius, angle1, angle2) + center = self.scale_point(prim.center) + radius = self.scale[0] * prim.radius + angle1 = prim.start_angle + angle2 = prim.end_angle + if prim.direction == 'counterclockwise': + self.ctx.arc(*center, radius=radius, + angle1=angle1, angle2=angle2) else: - ctx.arc_negative(center[0], center[1], radius, angle1, angle2) - ctx.fill() - + self.ctx.arc_negative(*center, radius=radius, + angle1=angle1, angle2=angle2) + self.ctx.fill() def _render_circle(self, circle, color): - center = tuple(map(mul, circle.position, self.scale)) + center = self.scale_point(circle.position) if not self.invert: - ctx = self.ctx - ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) - ctx.set_operator(cairo.OPERATOR_OVER if circle.level_polarity == "dark" else cairo.OPERATOR_CLEAR) + self.ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) + self.ctx.set_operator(cairo.OPERATOR_OVER + if circle.level_polarity == "dark" + else cairo.OPERATOR_CLEAR) else: - ctx = self.mask_ctx - ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) - ctx.set_operator(cairo.OPERATOR_CLEAR) + self.ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) + self.ctx.set_operator(cairo.OPERATOR_CLEAR) if circle.hole_diameter > 0: - ctx.push_group() + self.ctx.push_group() - ctx.set_line_width(0) - ctx.arc(center[0], center[1], radius=circle.radius * self.scale[0], angle1=0, angle2=2 * math.pi) - ctx.fill() + self.ctx.set_line_width(0) + self.ctx.arc(center[0], center[1], radius=circle.radius * self.scale[0], angle1=0, angle2=2 * math.pi) + self.ctx.fill() if circle.hole_diameter > 0: # Render the center clear - ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) - ctx.set_operator(cairo.OPERATOR_CLEAR) - ctx.arc(center[0], center[1], radius=circle.hole_radius * self.scale[0], angle1=0, angle2=2 * math.pi) - ctx.fill() + self.ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) + self.ctx.set_operator(cairo.OPERATOR_CLEAR) + self.ctx.arc(center[0], center[1], radius=circle.hole_radius * self.scale[0], angle1=0, angle2=2 * math.pi) + self.ctx.fill() - ctx.pop_group_to_source() - ctx.paint_with_alpha(1) + self.ctx.pop_group_to_source() + self.ctx.paint_with_alpha(1) def _render_rectangle(self, rectangle, color): - ll = map(mul, rectangle.lower_left, self.scale) - width, height = tuple(map(mul, (rectangle.width, rectangle.height), map(abs, self.scale))) + lower_left = self.scale_point(rectangle.lower_left) + width, height = tuple([abs(coord) for coord in self.scale_point((rectangle.width, rectangle.height))]) if not self.invert: - ctx = self.ctx - ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) - ctx.set_operator(cairo.OPERATOR_OVER if rectangle.level_polarity == "dark" else cairo.OPERATOR_CLEAR) + self.ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) + self.ctx.set_operator(cairo.OPERATOR_OVER + if rectangle.level_polarity == "dark" + else cairo.OPERATOR_CLEAR) else: - ctx = self.mask_ctx - ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) - ctx.set_operator(cairo.OPERATOR_CLEAR) + self.ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) + self.ctx.set_operator(cairo.OPERATOR_CLEAR) if rectangle.rotation != 0: - ctx.save() + self.ctx.save() center = map(mul, rectangle.position, self.scale) matrix = cairo.Matrix() matrix.translate(center[0], center[1]) # For drawing, we already handles the translation - ll[0] = ll[0] - center[0] - ll[1] = ll[1] - center[1] + lower_left[0] = lower_left[0] - center[0] + lower_left[1] = lower_left[1] - center[1] matrix.rotate(rectangle.rotation) - ctx.transform(matrix) + self.ctx.transform(matrix) if rectangle.hole_diameter > 0: - ctx.push_group() + self.ctx.push_group() - ctx.set_line_width(0) - ctx.rectangle(ll[0], ll[1], width, height) - ctx.fill() + self.ctx.set_line_width(0) + self.ctx.rectangle(lower_left[0], lower_left[1], width, height) + self.ctx.fill() if rectangle.hole_diameter > 0: # Render the center clear - ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) - ctx.set_operator(cairo.OPERATOR_CLEAR) + self.ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) + self.ctx.set_operator(cairo.OPERATOR_CLEAR) center = map(mul, rectangle.position, self.scale) - ctx.arc(center[0], center[1], radius=rectangle.hole_radius * self.scale[0], angle1=0, angle2=2 * math.pi) - ctx.fill() + self.ctx.arc(center[0], center[1], radius=rectangle.hole_radius * self.scale[0], angle1=0, angle2=2 * math.pi) + self.ctx.fill() - ctx.pop_group_to_source() - ctx.paint_with_alpha(1) + self.ctx.pop_group_to_source() + self.ctx.paint_with_alpha(1) if rectangle.rotation != 0: - ctx.restore() + self.ctx.restore() def _render_obround(self, obround, color): if not self.invert: - ctx = self.ctx - ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) - ctx.set_operator(cairo.OPERATOR_OVER if obround.level_polarity == "dark" else cairo.OPERATOR_CLEAR) + self.ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) + self.ctx.set_operator(cairo.OPERATOR_OVER if obround.level_polarity == "dark" else cairo.OPERATOR_CLEAR) else: - ctx = self.mask_ctx - ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) - ctx.set_operator(cairo.OPERATOR_CLEAR) + self.ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) + self.ctx.set_operator(cairo.OPERATOR_CLEAR) if obround.hole_diameter > 0: - ctx.push_group() + self.ctx.push_group() self._render_circle(obround.subshapes['circle1'], color) self._render_circle(obround.subshapes['circle2'], color) @@ -311,55 +314,54 @@ class GerberCairoContext(GerberContext): if obround.hole_diameter > 0: # Render the center clear - ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) - ctx.set_operator(cairo.OPERATOR_CLEAR) + self.ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) + self.ctx.set_operator(cairo.OPERATOR_CLEAR) center = map(mul, obround.position, self.scale) - ctx.arc(center[0], center[1], radius=obround.hole_radius * self.scale[0], angle1=0, angle2=2 * math.pi) - ctx.fill() + self.ctx.arc(center[0], center[1], radius=obround.hole_radius * self.scale[0], angle1=0, angle2=2 * math.pi) + self.ctx.fill() - ctx.pop_group_to_source() - ctx.paint_with_alpha(1) + self.ctx.pop_group_to_source() + self.ctx.paint_with_alpha(1) def _render_polygon(self, polygon, color): # TODO Ths does not handle rotation of a polygon if not self.invert: - ctx = self.ctx - ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) - ctx.set_operator(cairo.OPERATOR_OVER if polygon.level_polarity == "dark" else cairo.OPERATOR_CLEAR) + self.ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) + self.ctx.set_operator(cairo.OPERATOR_OVER if polygon.level_polarity == "dark" else cairo.OPERATOR_CLEAR) else: - ctx = self.mask_ctx - ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) - ctx.set_operator(cairo.OPERATOR_CLEAR) + self.ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) + self.ctx.set_operator(cairo.OPERATOR_CLEAR) if polygon.hole_radius > 0: - ctx.push_group() + self.ctx.push_group() vertices = polygon.vertices - ctx.set_line_width(0) - ctx.set_line_cap(cairo.LINE_CAP_ROUND) + self.ctx.set_line_width(0) + self.ctx.set_line_cap(cairo.LINE_CAP_ROUND) # Start from before the end so it is easy to iterate and make sure it is closed - ctx.move_to(*map(mul, vertices[-1], self.scale)) + self.ctx.move_to(*map(mul, vertices[-1], self.scale)) for v in vertices: - ctx.line_to(*map(mul, v, self.scale)) + self.ctx.line_to(*map(mul, v, self.scale)) - ctx.fill() + self.ctx.fill() if polygon.hole_radius > 0: # Render the center clear center = tuple(map(mul, polygon.position, self.scale)) - ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) - ctx.set_operator(cairo.OPERATOR_CLEAR) - ctx.set_line_width(0) - ctx.arc(center[0], center[1], polygon.hole_radius * self.scale[0], 0, 2 * math.pi) - ctx.fill() + self.ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) + self.ctx.set_operator(cairo.OPERATOR_CLEAR) + self.ctx.set_line_width(0) + self.ctx.arc(center[0], center[1], polygon.hole_radius * self.scale[0], 0, 2 * math.pi) + self.ctx.fill() - ctx.pop_group_to_source() - ctx.paint_with_alpha(1) + self.ctx.pop_group_to_source() + self.ctx.paint_with_alpha(1) - def _render_drill(self, circle, color): + def _render_drill(self, circle, color=None): + color = color if color is not None else self.drill_color self._render_circle(circle, color) def _render_slot(self, slot, color): @@ -369,19 +371,17 @@ class GerberCairoContext(GerberContext): width = slot.diameter if not self.invert: - ctx = self.ctx - ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) - ctx.set_operator(cairo.OPERATOR_OVER if slot.level_polarity == "dark" else cairo.OPERATOR_CLEAR) + self.ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) + self.ctx.set_operator(cairo.OPERATOR_OVER if slot.level_polarity == "dark" else cairo.OPERATOR_CLEAR) else: - ctx = self.mask_ctx - ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) - ctx.set_operator(cairo.OPERATOR_CLEAR) - - ctx.set_line_width(width * self.scale[0]) - ctx.set_line_cap(cairo.LINE_CAP_ROUND) - ctx.move_to(*start) - ctx.line_to(*end) - ctx.stroke() + self.ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) + self.ctx.set_operator(cairo.OPERATOR_CLEAR) + + self.ctx.set_line_width(width * self.scale[0]) + self.ctx.set_line_cap(cairo.LINE_CAP_ROUND) + self.ctx.move_to(*start) + self.ctx.line_to(*end) + self.ctx.stroke() def _render_amgroup(self, amgroup, color): self.ctx.push_group() @@ -391,33 +391,52 @@ class GerberCairoContext(GerberContext): self.ctx.paint_with_alpha(1) def _render_test_record(self, primitive, color): - position = tuple(map(add, primitive.position, self.origin_in_inch)) + position = [pos + origin for pos, origin in zip(primitive.position, self.origin_in_inch)] self.ctx.set_operator(cairo.OPERATOR_OVER) - self.ctx.select_font_face('monospace', cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) + self.ctx.select_font_face( + 'monospace', cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) self.ctx.set_font_size(13) self._render_circle(Circle(position, 0.015), color) self.ctx.set_source_rgba(*color, alpha=self.alpha) - self.ctx.set_operator(cairo.OPERATOR_OVER if primitive.level_polarity == "dark" else cairo.OPERATOR_CLEAR) - self.ctx.move_to(*[self.scale[0] * (coord + 0.015) for coord in position]) + self.ctx.set_operator( + cairo.OPERATOR_OVER if primitive.level_polarity == 'dark' else cairo.OPERATOR_CLEAR) + self.ctx.move_to(*[self.scale[0] * (coord + 0.015) + for coord in position]) self.ctx.scale(1, -1) self.ctx.show_text(primitive.net_name) - self.ctx.scale(1, -1) - - def _clear_mask(self): - self.mask_ctx.set_operator(cairo.OPERATOR_OVER) - self.mask_ctx.set_source_rgba(self.background_color[0], self.background_color[1], self.background_color[2], alpha=self.alpha) - self.mask_ctx.paint() - - def _render_mask(self): - self.ctx.set_operator(cairo.OPERATOR_OVER) - ptn = cairo.SurfacePattern(self.mask) + self.ctx.scale(1, -1) + + def _new_render_layer(self, color=None): + size_in_pixels = self.scale_point(self.size_in_inch) + layer = cairo.SVGSurface(None, size_in_pixels[0], size_in_pixels[1]) + ctx = cairo.Context(layer) + ctx.set_fill_rule(cairo.FILL_RULE_EVEN_ODD) + ctx.scale(1, -1) + ctx.translate(-(self.origin_in_inch[0] * self.scale[0]), + (-self.origin_in_inch[1] * self.scale[0]) + - size_in_pixels[1]) + if self.invert: + ctx.set_operator(cairo.OPERATOR_OVER) + ctx.set_source_rgba(*self.color, alpha=self.alpha) + ctx.paint() + self.ctx = ctx + self.active_layer = layer + + def _flatten(self): + self.output_ctx.set_operator(cairo.OPERATOR_OVER) + ptn = cairo.SurfacePattern(self.active_layer) ptn.set_matrix(self._xform_matrix) - self.ctx.set_source(ptn) - self.ctx.paint() + self.output_ctx.set_source(ptn) + self.output_ctx.paint() + self.ctx = None + self.active_layer = None def _paint_background(self, force=False): - if (not self.bg) or force: - self.bg = True - self.ctx.set_source_rgba(self.background_color[0], self.background_color[1], self.background_color[2], alpha=1.0) - self.ctx.paint() - + if (not self.bg) or force: + self.bg = True + self.output_ctx.set_operator(cairo.OPERATOR_OVER) + self.output_ctx.set_source_rgba(self.background_color[0], self.background_color[1], self.background_color[2], alpha=1.0) + self.output_ctx.paint() + + def scale_point(self, point): + return tuple([coord * scale for coord, scale in zip(point, self.scale)]) \ No newline at end of file -- cgit From 8d5e782ccf220d77f0aad5a4e5605dc5cbe0f410 Mon Sep 17 00:00:00 2001 From: Garret Fick Date: Sat, 6 Aug 2016 09:51:58 +0800 Subject: Fix multiple problems with the merge. There are still errors, but I will intentionally leave them because future merges might resolve them --- gerber/render/cairo_backend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gerber/render/cairo_backend.py') diff --git a/gerber/render/cairo_backend.py b/gerber/render/cairo_backend.py index 349640a..dc39607 100644 --- a/gerber/render/cairo_backend.py +++ b/gerber/render/cairo_backend.py @@ -21,7 +21,7 @@ except ImportError: import cairocffi as cairo import math -from operator import mul, di +from operator import mul, div import tempfile -- cgit From 5af19af190c1fb0f0c5be029d46d63e657dde4d9 Mon Sep 17 00:00:00 2001 From: Hamilton Kibbe Date: Thu, 21 Jan 2016 03:57:44 -0500 Subject: Commit partial merge so I can work on the plane --- gerber/render/cairo_backend.py | 92 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 3 deletions(-) (limited to 'gerber/render/cairo_backend.py') diff --git a/gerber/render/cairo_backend.py b/gerber/render/cairo_backend.py index dc39607..8c7232f 100644 --- a/gerber/render/cairo_backend.py +++ b/gerber/render/cairo_backend.py @@ -12,6 +12,7 @@ # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and # limitations under the License. @@ -22,14 +23,14 @@ except ImportError: import math from operator import mul, div - import tempfile +import cairocffi as cairo + from ..primitives import * from .render import GerberContext, RenderSettings from .theme import THEMES - try: from cStringIO import StringIO except(ImportError): @@ -138,20 +139,35 @@ class GerberCairoContext(GerberContext): start = [pos * scale for pos, scale in zip(line.start, self.scale)] end = [pos * scale for pos, scale in zip(line.end, self.scale)] if not self.invert: +<<<<<<< HEAD self.ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) self.ctx.set_operator(cairo.OPERATOR_OVER if line.level_polarity == "dark" else cairo.OPERATOR_CLEAR) +======= + self.ctx.set_source_rgba(*color, alpha=self.alpha) + self.ctx.set_operator(cairo.OPERATOR_OVER + if line.level_polarity == 'dark' + else cairo.OPERATOR_CLEAR) +>>>>>>> 5476da8... Fix a bunch of rendering bugs. else: self.ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) self.ctx.set_operator(cairo.OPERATOR_CLEAR) if isinstance(line.aperture, Circle): +<<<<<<< HEAD width = line.aperture.diameter +======= + width = line.aperture.diameter +>>>>>>> 5476da8... Fix a bunch of rendering bugs. self.ctx.set_line_width(width * self.scale[0]) self.ctx.set_line_cap(cairo.LINE_CAP_ROUND) self.ctx.move_to(*start) self.ctx.line_to(*end) +<<<<<<< HEAD self.ctx.stroke() +======= + self.ctx.stroke() +>>>>>>> 5476da8... Fix a bunch of rendering bugs. elif isinstance(line.aperture, Rectangle): points = [self.scale_point(x) for x in line.vertices] self.ctx.set_line_width(0) @@ -176,6 +192,7 @@ class GerberCairoContext(GerberContext): width = max(arc.aperture.width, arc.aperture.height, 0.001) if not self.invert: +<<<<<<< HEAD self.ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) self.ctx.set_operator(cairo.OPERATOR_OVER if arc.level_polarity == "dark"\ @@ -184,25 +201,50 @@ class GerberCairoContext(GerberContext): self.ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) self.ctx.set_operator(cairo.OPERATOR_CLEAR) +======= + self.ctx.set_source_rgba(*color, alpha=self.alpha) + self.ctx.set_operator(cairo.OPERATOR_OVER + if arc.level_polarity == 'dark' + else cairo.OPERATOR_CLEAR) + else: + self.ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) + self.ctx.set_operator(cairo.OPERATOR_CLEAR) +>>>>>>> 5476da8... Fix a bunch of rendering bugs. self.ctx.set_line_width(width * self.scale[0]) self.ctx.set_line_cap(cairo.LINE_CAP_ROUND) self.ctx.move_to(*start) # You actually have to do this... if arc.direction == 'counterclockwise': +<<<<<<< HEAD self.ctx.arc(center[0], center[1], radius, angle1, angle2) else: self.ctx.arc_negative(center[0], center[1], radius, angle1, angle2) +======= + self.ctx.arc(*center, radius=radius, angle1=angle1, angle2=angle2) + else: + self.ctx.arc_negative(*center, radius=radius, + angle1=angle1, angle2=angle2) +>>>>>>> 5476da8... Fix a bunch of rendering bugs. self.ctx.move_to(*end) # ...lame def _render_region(self, region, color): if not self.invert: +<<<<<<< HEAD self.ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) self.ctx.set_operator(cairo.OPERATOR_OVER if region.level_polarity == "dark" +======= + self.ctx.set_source_rgba(*color, alpha=self.alpha) + self.ctx.set_operator(cairo.OPERATOR_OVER + if region.level_polarity == 'dark' +>>>>>>> 5476da8... Fix a bunch of rendering bugs. else cairo.OPERATOR_CLEAR) else: self.ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) self.ctx.set_operator(cairo.OPERATOR_CLEAR) +<<<<<<< HEAD +======= +>>>>>>> 5476da8... Fix a bunch of rendering bugs. self.ctx.set_line_width(0) self.ctx.set_line_cap(cairo.LINE_CAP_ROUND) self.ctx.move_to(*self.scale_point(region.primitives[0].start)) @@ -220,6 +262,7 @@ class GerberCairoContext(GerberContext): else: self.ctx.arc_negative(*center, radius=radius, angle1=angle1, angle2=angle2) +<<<<<<< HEAD self.ctx.fill() def _render_circle(self, circle, color): center = self.scale_point(circle.position) @@ -249,10 +292,28 @@ class GerberCairoContext(GerberContext): self.ctx.pop_group_to_source() self.ctx.paint_with_alpha(1) +======= + self.ctx.fill() + + def _render_circle(self, circle, color): + center = self.scale_point(circle.position) + if not self.invert: + self.ctx.set_source_rgba(*color, alpha=self.alpha) + self.ctx.set_operator( + cairo.OPERATOR_OVER if circle.level_polarity == 'dark' else cairo.OPERATOR_CLEAR) + else: + self.ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) + self.ctx.set_operator(cairo.OPERATOR_CLEAR) + self.ctx.set_line_width(0) + self.ctx.arc(*center, radius=circle.radius * + self.scale[0], angle1=0, angle2=2 * math.pi) + self.ctx.fill() +>>>>>>> 5476da8... Fix a bunch of rendering bugs. def _render_rectangle(self, rectangle, color): lower_left = self.scale_point(rectangle.lower_left) width, height = tuple([abs(coord) for coord in self.scale_point((rectangle.width, rectangle.height))]) +<<<<<<< HEAD if not self.invert: self.ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) @@ -295,6 +356,19 @@ class GerberCairoContext(GerberContext): if rectangle.rotation != 0: self.ctx.restore() +======= + + if not self.invert: + self.ctx.set_source_rgba(*color, alpha=self.alpha) + self.ctx.set_operator( + cairo.OPERATOR_OVER if rectangle.level_polarity == 'dark' else cairo.OPERATOR_CLEAR) + else: + self.ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) + self.ctx.set_operator(cairo.OPERATOR_CLEAR) + self.ctx.set_line_width(0) + self.ctx.rectangle(*lower_left, width=width, height=height) + self.ctx.fill() +>>>>>>> 5476da8... Fix a bunch of rendering bugs. def _render_obround(self, obround, color): @@ -424,7 +498,11 @@ class GerberCairoContext(GerberContext): def _flatten(self): self.output_ctx.set_operator(cairo.OPERATOR_OVER) +<<<<<<< HEAD ptn = cairo.SurfacePattern(self.active_layer) +======= + ptn = cairo.SurfacePattern(self.active_layer) +>>>>>>> 5476da8... Fix a bunch of rendering bugs. ptn.set_matrix(self._xform_matrix) self.output_ctx.set_source(ptn) self.output_ctx.paint() @@ -435,8 +513,16 @@ class GerberCairoContext(GerberContext): if (not self.bg) or force: self.bg = True self.output_ctx.set_operator(cairo.OPERATOR_OVER) +<<<<<<< HEAD self.output_ctx.set_source_rgba(self.background_color[0], self.background_color[1], self.background_color[2], alpha=1.0) self.output_ctx.paint() def scale_point(self, point): - return tuple([coord * scale for coord, scale in zip(point, self.scale)]) \ No newline at end of file + return tuple([coord * scale for coord, scale in zip(point, self.scale)]) +======= + self.output_ctx.set_source_rgba(*self.background_color, alpha=1.0) + self.output_ctx.paint() + + def scale_point(self, point): + return tuple([coord * scale for coord, scale in zip(point, self.scale)]) +>>>>>>> 5476da8... Fix a bunch of rendering bugs. -- cgit From 724c2b3bced319ed0b50c4302fed9b0e1aa9ce9c Mon Sep 17 00:00:00 2001 From: Hamilton Kibbe Date: Sat, 5 Nov 2016 20:56:47 -0400 Subject: Finish Merge, most tests passing --- gerber/render/cairo_backend.py | 167 +++++++++++------------------------------ 1 file changed, 43 insertions(+), 124 deletions(-) (limited to 'gerber/render/cairo_backend.py') diff --git a/gerber/render/cairo_backend.py b/gerber/render/cairo_backend.py index 8c7232f..77d413e 100644 --- a/gerber/render/cairo_backend.py +++ b/gerber/render/cairo_backend.py @@ -12,15 +12,15 @@ # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - -# See the License for the specific language governing permissions and -# limitations under the License. - + +# See the License for the specific language governing permissions and +# limitations under the License. + try: import cairo except ImportError: import cairocffi as cairo - + import math from operator import mul, div import tempfile @@ -139,35 +139,20 @@ class GerberCairoContext(GerberContext): start = [pos * scale for pos, scale in zip(line.start, self.scale)] end = [pos * scale for pos, scale in zip(line.end, self.scale)] if not self.invert: -<<<<<<< HEAD self.ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) self.ctx.set_operator(cairo.OPERATOR_OVER if line.level_polarity == "dark" - else cairo.OPERATOR_CLEAR) -======= - self.ctx.set_source_rgba(*color, alpha=self.alpha) - self.ctx.set_operator(cairo.OPERATOR_OVER - if line.level_polarity == 'dark' - else cairo.OPERATOR_CLEAR) ->>>>>>> 5476da8... Fix a bunch of rendering bugs. + else cairo.OPERATOR_CLEAR) else: self.ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) self.ctx.set_operator(cairo.OPERATOR_CLEAR) if isinstance(line.aperture, Circle): -<<<<<<< HEAD - width = line.aperture.diameter -======= width = line.aperture.diameter ->>>>>>> 5476da8... Fix a bunch of rendering bugs. self.ctx.set_line_width(width * self.scale[0]) self.ctx.set_line_cap(cairo.LINE_CAP_ROUND) self.ctx.move_to(*start) self.ctx.line_to(*end) -<<<<<<< HEAD - self.ctx.stroke() -======= self.ctx.stroke() ->>>>>>> 5476da8... Fix a bunch of rendering bugs. elif isinstance(line.aperture, Rectangle): points = [self.scale_point(x) for x in line.vertices] self.ctx.set_line_width(0) @@ -190,9 +175,8 @@ class GerberCairoContext(GerberContext): width = arc.aperture.diameter if arc.aperture.diameter != 0 else 0.001 else: width = max(arc.aperture.width, arc.aperture.height, 0.001) - + if not self.invert: -<<<<<<< HEAD self.ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) self.ctx.set_operator(cairo.OPERATOR_OVER if arc.level_polarity == "dark"\ @@ -200,51 +184,26 @@ class GerberCairoContext(GerberContext): else: self.ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) self.ctx.set_operator(cairo.OPERATOR_CLEAR) - -======= - self.ctx.set_source_rgba(*color, alpha=self.alpha) - self.ctx.set_operator(cairo.OPERATOR_OVER - if arc.level_polarity == 'dark' - else cairo.OPERATOR_CLEAR) - else: - self.ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) - self.ctx.set_operator(cairo.OPERATOR_CLEAR) ->>>>>>> 5476da8... Fix a bunch of rendering bugs. + self.ctx.set_line_width(width * self.scale[0]) self.ctx.set_line_cap(cairo.LINE_CAP_ROUND) self.ctx.move_to(*start) # You actually have to do this... if arc.direction == 'counterclockwise': -<<<<<<< HEAD self.ctx.arc(center[0], center[1], radius, angle1, angle2) else: self.ctx.arc_negative(center[0], center[1], radius, angle1, angle2) -======= - self.ctx.arc(*center, radius=radius, angle1=angle1, angle2=angle2) - else: - self.ctx.arc_negative(*center, radius=radius, - angle1=angle1, angle2=angle2) ->>>>>>> 5476da8... Fix a bunch of rendering bugs. self.ctx.move_to(*end) # ...lame def _render_region(self, region, color): if not self.invert: -<<<<<<< HEAD self.ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) self.ctx.set_operator(cairo.OPERATOR_OVER if region.level_polarity == "dark" -======= - self.ctx.set_source_rgba(*color, alpha=self.alpha) - self.ctx.set_operator(cairo.OPERATOR_OVER - if region.level_polarity == 'dark' ->>>>>>> 5476da8... Fix a bunch of rendering bugs. else cairo.OPERATOR_CLEAR) else: self.ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) self.ctx.set_operator(cairo.OPERATOR_CLEAR) -<<<<<<< HEAD -======= ->>>>>>> 5476da8... Fix a bunch of rendering bugs. self.ctx.set_line_width(0) self.ctx.set_line_cap(cairo.LINE_CAP_ROUND) self.ctx.move_to(*self.scale_point(region.primitives[0].start)) @@ -262,8 +221,9 @@ class GerberCairoContext(GerberContext): else: self.ctx.arc_negative(*center, radius=radius, angle1=angle1, angle2=angle2) -<<<<<<< HEAD - self.ctx.fill() + + self.ctx.fill() + def _render_circle(self, circle, color): center = self.scale_point(circle.position) if not self.invert: @@ -274,47 +234,30 @@ class GerberCairoContext(GerberContext): else: self.ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) self.ctx.set_operator(cairo.OPERATOR_CLEAR) - + if circle.hole_diameter > 0: self.ctx.push_group() self.ctx.set_line_width(0) self.ctx.arc(center[0], center[1], radius=circle.radius * self.scale[0], angle1=0, angle2=2 * math.pi) self.ctx.fill() - + if circle.hole_diameter > 0: # Render the center clear self.ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) - self.ctx.set_operator(cairo.OPERATOR_CLEAR) + self.ctx.set_operator(cairo.OPERATOR_CLEAR) self.ctx.arc(center[0], center[1], radius=circle.hole_radius * self.scale[0], angle1=0, angle2=2 * math.pi) self.ctx.fill() - - self.ctx.pop_group_to_source() - self.ctx.paint_with_alpha(1) -======= - self.ctx.fill() - def _render_circle(self, circle, color): - center = self.scale_point(circle.position) - if not self.invert: - self.ctx.set_source_rgba(*color, alpha=self.alpha) - self.ctx.set_operator( - cairo.OPERATOR_OVER if circle.level_polarity == 'dark' else cairo.OPERATOR_CLEAR) - else: - self.ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) - self.ctx.set_operator(cairo.OPERATOR_CLEAR) - self.ctx.set_line_width(0) - self.ctx.arc(*center, radius=circle.radius * - self.scale[0], angle1=0, angle2=2 * math.pi) - self.ctx.fill() ->>>>>>> 5476da8... Fix a bunch of rendering bugs. + self.ctx.pop_group_to_source() + self.ctx.paint_with_alpha(1) def _render_rectangle(self, rectangle, color): lower_left = self.scale_point(rectangle.lower_left) width, height = tuple([abs(coord) for coord in self.scale_point((rectangle.width, rectangle.height))]) -<<<<<<< HEAD - + + if not self.invert: self.ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) self.ctx.set_operator(cairo.OPERATOR_OVER @@ -323,10 +266,10 @@ class GerberCairoContext(GerberContext): else: self.ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) self.ctx.set_operator(cairo.OPERATOR_CLEAR) - + if rectangle.rotation != 0: self.ctx.save() - + center = map(mul, rectangle.position, self.scale) matrix = cairo.Matrix() matrix.translate(center[0], center[1]) @@ -335,14 +278,14 @@ class GerberCairoContext(GerberContext): lower_left[1] = lower_left[1] - center[1] matrix.rotate(rectangle.rotation) self.ctx.transform(matrix) - + if rectangle.hole_diameter > 0: self.ctx.push_group() self.ctx.set_line_width(0) self.ctx.rectangle(lower_left[0], lower_left[1], width, height) self.ctx.fill() - + if rectangle.hole_diameter > 0: # Render the center clear self.ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) @@ -350,42 +293,30 @@ class GerberCairoContext(GerberContext): center = map(mul, rectangle.position, self.scale) self.ctx.arc(center[0], center[1], radius=rectangle.hole_radius * self.scale[0], angle1=0, angle2=2 * math.pi) self.ctx.fill() - + self.ctx.pop_group_to_source() self.ctx.paint_with_alpha(1) - + if rectangle.rotation != 0: - self.ctx.restore() -======= + self.ctx.restore() - if not self.invert: - self.ctx.set_source_rgba(*color, alpha=self.alpha) - self.ctx.set_operator( - cairo.OPERATOR_OVER if rectangle.level_polarity == 'dark' else cairo.OPERATOR_CLEAR) - else: - self.ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) - self.ctx.set_operator(cairo.OPERATOR_CLEAR) - self.ctx.set_line_width(0) - self.ctx.rectangle(*lower_left, width=width, height=height) - self.ctx.fill() ->>>>>>> 5476da8... Fix a bunch of rendering bugs. def _render_obround(self, obround, color): - + if not self.invert: self.ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) self.ctx.set_operator(cairo.OPERATOR_OVER if obround.level_polarity == "dark" else cairo.OPERATOR_CLEAR) else: self.ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) self.ctx.set_operator(cairo.OPERATOR_CLEAR) - + if obround.hole_diameter > 0: self.ctx.push_group() self._render_circle(obround.subshapes['circle1'], color) self._render_circle(obround.subshapes['circle2'], color) self._render_rectangle(obround.subshapes['rectangle'], color) - + if obround.hole_diameter > 0: # Render the center clear self.ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) @@ -393,12 +324,12 @@ class GerberCairoContext(GerberContext): center = map(mul, obround.position, self.scale) self.ctx.arc(center[0], center[1], radius=obround.hole_radius * self.scale[0], angle1=0, angle2=2 * math.pi) self.ctx.fill() - + self.ctx.pop_group_to_source() self.ctx.paint_with_alpha(1) def _render_polygon(self, polygon, color): - + # TODO Ths does not handle rotation of a polygon if not self.invert: self.ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) @@ -406,44 +337,44 @@ class GerberCairoContext(GerberContext): else: self.ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) self.ctx.set_operator(cairo.OPERATOR_CLEAR) - + if polygon.hole_radius > 0: self.ctx.push_group() - - vertices = polygon.vertices + + vertices = polygon.vertices self.ctx.set_line_width(0) self.ctx.set_line_cap(cairo.LINE_CAP_ROUND) - + # Start from before the end so it is easy to iterate and make sure it is closed self.ctx.move_to(*map(mul, vertices[-1], self.scale)) for v in vertices: self.ctx.line_to(*map(mul, v, self.scale)) self.ctx.fill() - + if polygon.hole_radius > 0: # Render the center clear center = tuple(map(mul, polygon.position, self.scale)) self.ctx.set_source_rgba(color[0], color[1], color[2], self.alpha) - self.ctx.set_operator(cairo.OPERATOR_CLEAR) + self.ctx.set_operator(cairo.OPERATOR_CLEAR) self.ctx.set_line_width(0) self.ctx.arc(center[0], center[1], polygon.hole_radius * self.scale[0], 0, 2 * math.pi) self.ctx.fill() - + self.ctx.pop_group_to_source() self.ctx.paint_with_alpha(1) def _render_drill(self, circle, color=None): color = color if color is not None else self.drill_color self._render_circle(circle, color) - + def _render_slot(self, slot, color): start = map(mul, slot.start, self.scale) end = map(mul, slot.end, self.scale) - + width = slot.diameter - + if not self.invert: self.ctx.set_source_rgba(color[0], color[1], color[2], alpha=self.alpha) self.ctx.set_operator(cairo.OPERATOR_OVER if slot.level_polarity == "dark" else cairo.OPERATOR_CLEAR) @@ -456,7 +387,7 @@ class GerberCairoContext(GerberContext): self.ctx.move_to(*start) self.ctx.line_to(*end) self.ctx.stroke() - + def _render_amgroup(self, amgroup, color): self.ctx.push_group() for primitive in amgroup.primitives: @@ -478,7 +409,7 @@ class GerberCairoContext(GerberContext): for coord in position]) self.ctx.scale(1, -1) self.ctx.show_text(primitive.net_name) - self.ctx.scale(1, -1) + self.ctx.scale(1, -1) def _new_render_layer(self, color=None): size_in_pixels = self.scale_point(self.size_in_inch) @@ -498,11 +429,7 @@ class GerberCairoContext(GerberContext): def _flatten(self): self.output_ctx.set_operator(cairo.OPERATOR_OVER) -<<<<<<< HEAD - ptn = cairo.SurfacePattern(self.active_layer) -======= ptn = cairo.SurfacePattern(self.active_layer) ->>>>>>> 5476da8... Fix a bunch of rendering bugs. ptn.set_matrix(self._xform_matrix) self.output_ctx.set_source(ptn) self.output_ctx.paint() @@ -510,19 +437,11 @@ class GerberCairoContext(GerberContext): self.active_layer = None def _paint_background(self, force=False): - if (not self.bg) or force: + if (not self.bg) or force: self.bg = True self.output_ctx.set_operator(cairo.OPERATOR_OVER) -<<<<<<< HEAD self.output_ctx.set_source_rgba(self.background_color[0], self.background_color[1], self.background_color[2], alpha=1.0) self.output_ctx.paint() def scale_point(self, point): return tuple([coord * scale for coord, scale in zip(point, self.scale)]) -======= - self.output_ctx.set_source_rgba(*self.background_color, alpha=1.0) - self.output_ctx.paint() - - def scale_point(self, point): - return tuple([coord * scale for coord, scale in zip(point, self.scale)]) ->>>>>>> 5476da8... Fix a bunch of rendering bugs. -- cgit From d7a0f3ad2b62402f4af9abe2729f9a7c14814fe6 Mon Sep 17 00:00:00 2001 From: Hamilton Kibbe Date: Sun, 6 Nov 2016 14:58:32 -0500 Subject: Remove debug print" --- gerber/render/cairo_backend.py | 1 - 1 file changed, 1 deletion(-) (limited to 'gerber/render/cairo_backend.py') diff --git a/gerber/render/cairo_backend.py b/gerber/render/cairo_backend.py index 2ba022f..810351b 100644 --- a/gerber/render/cairo_backend.py +++ b/gerber/render/cairo_backend.py @@ -131,7 +131,6 @@ class GerberCairoContext(GerberContext): f.write(self.surface_buffer.read()) f.flush() else: - print("Wriitng To Png: filename: {}".format(filename)) return self.surface.write_to_png(filename) def dump_str(self): -- cgit From 6db0658e2336d6405fe1a6acd10dfab39ba8e7ff Mon Sep 17 00:00:00 2001 From: Hamilton Kibbe Date: Sun, 6 Nov 2016 15:08:00 -0500 Subject: Fix tests on python3 --- gerber/render/cairo_backend.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'gerber/render/cairo_backend.py') diff --git a/gerber/render/cairo_backend.py b/gerber/render/cairo_backend.py index 810351b..6e95446 100644 --- a/gerber/render/cairo_backend.py +++ b/gerber/render/cairo_backend.py @@ -21,8 +21,7 @@ try: except ImportError: import cairocffi as cairo -import math -from operator import mul, div +from operator import mul import tempfile import copy import os -- cgit