- PDF Import tool: added support for PDF files that embed multiple Gerber layers (top, bottom, outline, silkscreen etc). Each will be opened in it's own Gerber file. The requirement is that each one is drawn in a different color
This commit is contained in:
parent
8a2a48f668
commit
7442af1b06
|
@ -12,6 +12,7 @@ CAD program, and create G-Code for Isolation routing.
|
||||||
22.04.2019
|
22.04.2019
|
||||||
|
|
||||||
- PDF import tool: added support for save/restore Graphics stack. Only for scale and offset transformations and for the linewidth. This is the final fix for Microsoft PDF printer who saves in PDF format 1.7
|
- PDF import tool: added support for save/restore Graphics stack. Only for scale and offset transformations and for the linewidth. This is the final fix for Microsoft PDF printer who saves in PDF format 1.7
|
||||||
|
- PDF Import tool: added support for PDF files that embed multiple Gerber layers (top, bottom, outline, silkscreen etc). Each will be opened in it's own Gerber file. The requirement is that each one is drawn in a different color
|
||||||
|
|
||||||
21.04.2019
|
21.04.2019
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,9 @@ class ToolPDF(FlatCAMTool):
|
||||||
|
|
||||||
self.stream_re = re.compile(b'.*?FlateDecode.*?stream(.*?)endstream', re.S)
|
self.stream_re = re.compile(b'.*?FlateDecode.*?stream(.*?)endstream', re.S)
|
||||||
|
|
||||||
|
# detect color change; it means a new object to be created
|
||||||
|
self.color_re = re.compile(r'^\s*(\d+\.?\d*) (\d+\.?\d*) (\d+\.?\d*)\s*RG$')
|
||||||
|
|
||||||
# detect 're' command
|
# detect 're' command
|
||||||
self.rect_re = re.compile(r'^(-?\d+\.?\d*)\s(-?\d+\.?\d*)\s(-?\d+\.?\d*)\s(-?\d+\.?\d*)\s*re$')
|
self.rect_re = re.compile(r'^(-?\d+\.?\d*)\s(-?\d+\.?\d*)\s(-?\d+\.?\d*)\s(-?\d+\.?\d*)\s*re$')
|
||||||
# detect 'm' command
|
# detect 'm' command
|
||||||
|
@ -159,7 +162,7 @@ class ToolPDF(FlatCAMTool):
|
||||||
def open_pdf(self, filename):
|
def open_pdf(self, filename):
|
||||||
new_name = filename.split('/')[-1].split('\\')[-1]
|
new_name = filename.split('/')[-1].split('\\')[-1]
|
||||||
|
|
||||||
def obj_init(grb_obj, app_obj):
|
with self.app.proc_container.new(_("Parsing PDF file ...")):
|
||||||
with open(filename, "rb") as f:
|
with open(filename, "rb") as f:
|
||||||
pdf = f.read()
|
pdf = f.read()
|
||||||
|
|
||||||
|
@ -171,35 +174,41 @@ class ToolPDF(FlatCAMTool):
|
||||||
try:
|
try:
|
||||||
self.pdf_parsed += (zlib.decompress(s).decode('UTF-8') + '\r\n')
|
self.pdf_parsed += (zlib.decompress(s).decode('UTF-8') + '\r\n')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
app_obj.log.debug("ToolPDF.open_pdf().obj_init() --> %s" % str(e))
|
log.debug("ToolPDF.open_pdf().obj_init() --> %s" % str(e))
|
||||||
|
|
||||||
ap_dict = self.parse_pdf(pdf_content=self.pdf_parsed)
|
obj_dict = self.parse_pdf(pdf_content=self.pdf_parsed)
|
||||||
grb_obj.apertures = deepcopy(ap_dict)
|
|
||||||
|
|
||||||
poly_buff = []
|
for k in obj_dict:
|
||||||
for ap in ap_dict:
|
ap_dict = obj_dict[k]
|
||||||
for k in ap_dict[ap]:
|
if ap_dict:
|
||||||
if k == 'solid_geometry':
|
def obj_init(grb_obj, app_obj):
|
||||||
poly_buff += ap_dict[ap][k]
|
|
||||||
|
|
||||||
poly_buff = unary_union(poly_buff)
|
grb_obj.apertures = deepcopy(ap_dict)
|
||||||
poly_buff = poly_buff.buffer(0.0000001)
|
|
||||||
poly_buff = poly_buff.buffer(-0.0000001)
|
|
||||||
|
|
||||||
grb_obj.solid_geometry = deepcopy(poly_buff)
|
poly_buff = []
|
||||||
|
for ap in grb_obj.apertures:
|
||||||
|
for k in grb_obj.apertures[ap]:
|
||||||
|
if k == 'solid_geometry':
|
||||||
|
poly_buff += ap_dict[ap][k]
|
||||||
|
|
||||||
with self.app.proc_container.new(_("Opening PDF.")):
|
poly_buff = unary_union(poly_buff)
|
||||||
|
poly_buff = poly_buff.buffer(0.0000001)
|
||||||
|
poly_buff = poly_buff.buffer(-0.0000001)
|
||||||
|
|
||||||
ret = self.app.new_object("gerber", new_name, obj_init, autoselected=False)
|
grb_obj.solid_geometry = deepcopy(poly_buff)
|
||||||
if ret == 'fail':
|
|
||||||
self.app.inform.emit(_('[ERROR_NOTCL] Open PDF file failed.'))
|
|
||||||
return
|
|
||||||
|
|
||||||
# Register recent file
|
with self.app.proc_container.new(_("Opening PDF layer #%d ...") % (int(k) - 2)):
|
||||||
self.app.file_opened.emit("gerber", new_name)
|
|
||||||
|
|
||||||
# GUI feedback
|
ret = self.app.new_object("gerber", new_name, obj_init, autoselected=False)
|
||||||
self.app.inform.emit(_("[success] Opened: %s") % filename)
|
if ret == 'fail':
|
||||||
|
self.app.inform.emit(_('[ERROR_NOTCL] Open PDF file failed.'))
|
||||||
|
return
|
||||||
|
|
||||||
|
# Register recent file
|
||||||
|
self.app.file_opened.emit("gerber", new_name)
|
||||||
|
|
||||||
|
# GUI feedback
|
||||||
|
self.app.inform.emit(_("[success] Opened: %s") % filename)
|
||||||
|
|
||||||
def parse_pdf(self, pdf_content):
|
def parse_pdf(self, pdf_content):
|
||||||
path = dict()
|
path = dict()
|
||||||
|
@ -229,9 +238,23 @@ class ToolPDF(FlatCAMTool):
|
||||||
# initial aperture
|
# initial aperture
|
||||||
aperture = 10
|
aperture = 10
|
||||||
|
|
||||||
|
# store the objects to be transformed into Gerbers
|
||||||
|
object_dict = {}
|
||||||
|
|
||||||
|
# will serve as key in the object_dict
|
||||||
|
object_nr = 1
|
||||||
|
|
||||||
# store the apertures here
|
# store the apertures here
|
||||||
apertures_dict = {}
|
apertures_dict = {}
|
||||||
|
|
||||||
|
# create first object
|
||||||
|
object_dict[object_nr] = apertures_dict
|
||||||
|
object_nr += 1
|
||||||
|
|
||||||
|
# on color change we create a new apertures dictionary and store the old one in a storage from where it will be
|
||||||
|
# transformed into Gerber object
|
||||||
|
old_color = [None, None ,None]
|
||||||
|
|
||||||
line_nr = 0
|
line_nr = 0
|
||||||
lines = pdf_content.splitlines()
|
lines = pdf_content.splitlines()
|
||||||
|
|
||||||
|
@ -239,6 +262,21 @@ class ToolPDF(FlatCAMTool):
|
||||||
line_nr += 1
|
line_nr += 1
|
||||||
# log.debug("line %d: %s" % (line_nr, pline))
|
# log.debug("line %d: %s" % (line_nr, pline))
|
||||||
|
|
||||||
|
# COLOR DETECTION / OBJECT DETECTION
|
||||||
|
match = self.color_re.search(pline)
|
||||||
|
if match:
|
||||||
|
color = [float(match.group(1)), float(match.group(2)), float(match.group(3))]
|
||||||
|
|
||||||
|
if color[0] == old_color[0] and color[1] == old_color[1] and color[2] == old_color[2]:
|
||||||
|
# same color, do nothing
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
object_dict[object_nr] = deepcopy(apertures_dict)
|
||||||
|
object_nr += 1
|
||||||
|
object_dict[object_nr] = {}
|
||||||
|
apertures_dict.clear()
|
||||||
|
old_color = copy(color)
|
||||||
|
|
||||||
# TRANSFORMATIONS DETECTION #
|
# TRANSFORMATIONS DETECTION #
|
||||||
|
|
||||||
# Detect combined transformation.
|
# Detect combined transformation.
|
||||||
|
@ -605,7 +643,7 @@ class ToolPDF(FlatCAMTool):
|
||||||
else:
|
else:
|
||||||
geo = copy(subpath['rectangle'])
|
geo = copy(subpath['rectangle'])
|
||||||
# close the subpath if it was not closed already
|
# close the subpath if it was not closed already
|
||||||
if close_subpath is False:
|
if close_subpath is False and start_point is not None:
|
||||||
geo.append(start_point)
|
geo.append(start_point)
|
||||||
geo_el = Polygon(geo).buffer(0.0000001, resolution=self.step_per_circles)
|
geo_el = Polygon(geo).buffer(0.0000001, resolution=self.step_per_circles)
|
||||||
path_geo.append(geo_el)
|
path_geo.append(geo_el)
|
||||||
|
@ -745,7 +783,7 @@ class ToolPDF(FlatCAMTool):
|
||||||
apertures_dict['0']['solid_geometry'] = []
|
apertures_dict['0']['solid_geometry'] = []
|
||||||
apertures_dict['0']['solid_geometry'] += path_geo
|
apertures_dict['0']['solid_geometry'] += path_geo
|
||||||
continue
|
continue
|
||||||
return apertures_dict
|
return object_dict
|
||||||
|
|
||||||
def bezier_to_points(self, start, c1, c2, stop):
|
def bezier_to_points(self, start, c1, c2, stop):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue