def draw(self): self.qr.make() g = Group() color = self.barFillColor border = self.barBorder width = self.barWidth height = self.barHeight x = self.x y = self.y g.add(SRect(x, y, width, height, fillColor=None)) path = Path(fillColor=colors.black, strokeColor=None) moduleCount = self.qr.getModuleCount() minwh = float(min(width, height)) boxsize = minwh / (moduleCount + border * 2) offsetX = (width - minwh) / 2 offsetY = (minwh - height) / 2 for r, row in enumerate(self.qr.modules): c = 0 for t, tt in itertools.groupby(row): isDark = t count = len(list(tt)) if isDark: x = (c + border) * boxsize y = (r + border + 1) * boxsize path.moveTo(offsetX + x, offsetY + height - y) path.lineTo(offsetX + x + count * boxsize, offsetY + height - y) path.lineTo(offsetX + x + count * boxsize, offsetY + height - y + boxsize) path.lineTo(offsetX + x, offsetY + height - y + boxsize) path.closePath() c += count g.add(path) return g
def convertPath(self, node): d = node.getAttribute('d') if not d: return None normPath = normalise_svg_path(d) path = Path() points = path.points # Track subpaths needing to be closed later unclosed_subpath_pointers = [] subpath_start = [] lastop = '' for i in range(0, len(normPath), 2): op, nums = normPath[i:i+2] if op in ('m', 'M') and i > 0 and path.operators[-1] != _CLOSEPATH: unclosed_subpath_pointers.append(len(path.operators)) # moveto absolute if op == 'M': path.moveTo(*nums) subpath_start = points[-2:] # lineto absolute elif op == 'L': path.lineTo(*nums) # moveto relative elif op == 'm': if len(points) >= 2: if lastop in ('Z', 'z'): starting_point = subpath_start else: starting_point = points[-2:] xn, yn = starting_point[0] + nums[0], starting_point[1] + nums[1] path.moveTo(xn, yn) else: path.moveTo(*nums) subpath_start = points[-2:] # lineto relative elif op == 'l': xn, yn = points[-2] + nums[0], points[-1] + nums[1] path.lineTo(xn, yn) # horizontal/vertical line absolute elif op == 'H': path.lineTo(nums[0], points[-1]) elif op == 'V': path.lineTo(points[-2], nums[0]) # horizontal/vertical line relative elif op == 'h': path.lineTo(points[-2] + nums[0], points[-1]) elif op == 'v': path.lineTo(points[-2], points[-1] + nums[0]) # cubic bezier, absolute elif op == 'C': path.curveTo(*nums) elif op == 'S': x2, y2, xn, yn = nums if len(points) < 4 or lastop not in {'c', 'C', 's', 'S'}: xp, yp, x0, y0 = points[-2:] * 2 else: xp, yp, x0, y0 = points[-4:] xi, yi = x0 + (x0 - xp), y0 + (y0 - yp) path.curveTo(xi, yi, x2, y2, xn, yn) # cubic bezier, relative elif op == 'c': xp, yp = points[-2:] x1, y1, x2, y2, xn, yn = nums path.curveTo(xp + x1, yp + y1, xp + x2, yp + y2, xp + xn, yp + yn) elif op == 's': x2, y2, xn, yn = nums if len(points) < 4 or lastop not in {'c', 'C', 's', 'S'}: xp, yp, x0, y0 = points[-2:] * 2 else: xp, yp, x0, y0 = points[-4:] xi, yi = x0 + (x0 - xp), y0 + (y0 - yp) path.curveTo(xi, yi, x0 + x2, y0 + y2, x0 + xn, y0 + yn) # quadratic bezier, absolute elif op == 'Q': x0, y0 = points[-2:] x1, y1, xn, yn = nums (x0, y0), (x1, y1), (x2, y2), (xn, yn) = \ convert_quadratic_to_cubic_path((x0, y0), (x1, y1), (xn, yn)) path.curveTo(x1, y1, x2, y2, xn, yn) elif op == 'T': if len(points) < 4: xp, yp, x0, y0 = points[-2:] * 2 else: xp, yp, x0, y0 = points[-4:] xi, yi = x0 + (x0 - xp), y0 + (y0 - yp) xn, yn = nums (x0, y0), (x1, y1), (x2, y2), (xn, yn) = \ convert_quadratic_to_cubic_path((x0, y0), (xi, yi), (xn, yn)) path.curveTo(x1, y1, x2, y2, xn, yn) # quadratic bezier, relative elif op == 'q': x0, y0 = points[-2:] x1, y1, xn, yn = nums x1, y1, xn, yn = x0 + x1, y0 + y1, x0 + xn, y0 + yn (x0, y0), (x1, y1), (x2, y2), (xn, yn) = \ convert_quadratic_to_cubic_path((x0, y0), (x1, y1), (xn, yn)) path.curveTo(x1, y1, x2, y2, xn, yn) elif op == 't': if len(points) < 4: xp, yp, x0, y0 = points[-2:] * 2 else: xp, yp, x0, y0 = points[-4:] x0, y0 = points[-2:] xn, yn = nums xn, yn = x0 + xn, y0 + yn xi, yi = x0 + (x0 - xp), y0 + (y0 - yp) (x0, y0), (x1, y1), (x2, y2), (xn, yn) = \ convert_quadratic_to_cubic_path((x0, y0), (xi, yi), (xn, yn)) path.curveTo(x1, y1, x2, y2, xn, yn) # elliptical arc elif op in ('A', 'a'): rx, ry, phi, fA, fS, x2, y2 = nums x1, y1 = points[-2:] if op == 'a': x2 += x1 y2 += y1 if abs(rx) <= 1e-10 or abs(ry) <= 1e-10: path.lineTo(x2, y2) else: bp = bezier_arc_from_end_points(x1, y1, rx, ry, phi, fA, fS, x2, y2) for _, _, x1, y1, x2, y2, xn, yn in bp: path.curveTo(x1, y1, x2, y2, xn, yn) # close path elif op in ('Z', 'z'): path.closePath() else: logger.debug("Suspicious path operator: %s" % op) lastop = op gr = Group() self.applyStyleOnShape(path, node) if path.operators[-1] != _CLOSEPATH: unclosed_subpath_pointers.append(len(path.operators)) if unclosed_subpath_pointers and path.fillColor is not None: # ReportLab doesn't fill unclosed paths, so we are creating a copy # of the path with all subpaths closed, but without stroke. # https://bitbucket.org/rptlab/reportlab/issues/99/ closed_path = NoStrokePath(copy_from=path) for pointer in reversed(unclosed_subpath_pointers): closed_path.operators.insert(pointer, _CLOSEPATH) gr.add(closed_path) path.fillColor = None gr.add(path) return gr
def convertPath(self, node): d = node.getAttribute('d') normPath = normalise_svg_path(d) path = Path() points = path.points # Track subpaths needing to be closed later unclosed_subpath_pointers = [] subpath_start = [] lastop = '' for i in xrange(0, len(normPath), 2): op, nums = normPath[i:i+2] if op in ('m', 'M') and i > 0 and path.operators[-1] != _CLOSEPATH: unclosed_subpath_pointers.append(len(path.operators)) # moveto absolute if op == 'M': path.moveTo(*nums) subpath_start = points[-2:] # lineto absolute elif op == 'L': path.lineTo(*nums) # moveto relative elif op == 'm': if len(points) >= 2: if lastop in ('Z', 'z'): starting_point = subpath_start else: starting_point = points[-2:] xn, yn = starting_point[0] + nums[0], starting_point[1] + nums[1] path.moveTo(xn, yn) else: path.moveTo(*nums) subpath_start = points[-2:] # lineto relative elif op == 'l': xn, yn = points[-2] + nums[0], points[-1] + nums[1] path.lineTo(xn, yn) # horizontal/vertical line absolute elif op == 'H': path.lineTo(nums[0], points[-1]) elif op == 'V': path.lineTo(points[-2], nums[0]) # horizontal/vertical line relative elif op == 'h': path.lineTo(points[-2] + nums[0], points[-1]) elif op == 'v': path.lineTo(points[-2], points[-1] + nums[0]) # cubic bezier, absolute elif op == 'C': path.curveTo(*nums) elif op == 'S': x2, y2, xn, yn = nums if len(points) < 4 or lastop not in {'c', 'C', 's', 'S'}: xp, yp, x0, y0 = points[-2:] * 2 else: xp, yp, x0, y0 = points[-4:] xi, yi = x0 + (x0 - xp), y0 + (y0 - yp) path.curveTo(xi, yi, x2, y2, xn, yn) # cubic bezier, relative elif op == 'c': xp, yp = points[-2:] x1, y1, x2, y2, xn, yn = nums path.curveTo(xp + x1, yp + y1, xp + x2, yp + y2, xp + xn, yp + yn) elif op == 's': x2, y2, xn, yn = nums if len(points) < 4 or lastop not in {'c', 'C', 's', 'S'}: xp, yp, x0, y0 = points[-2:] * 2 else: xp, yp, x0, y0 = points[-4:] xi, yi = x0 + (x0 - xp), y0 + (y0 - yp) path.curveTo(xi, yi, x0 + x2, y0 + y2, x0 + xn, y0 + yn) # quadratic bezier, absolute elif op == 'Q': x0, y0 = points[-2:] x1, y1, xn, yn = nums (x0, y0), (x1, y1), (x2, y2), (xn, yn) = \ convert_quadratic_to_cubic_path((x0, y0), (x1, y1), (xn, yn)) path.curveTo(x1, y1, x2, y2, xn, yn) elif op == 'T': if len(points) < 4: xp, yp, x0, y0 = points[-2:] * 2 else: xp, yp, x0, y0 = points[-4:] xi, yi = x0 + (x0 - xp), y0 + (y0 - yp) xn, yn = nums (x0, y0), (x1, y1), (x2, y2), (xn, yn) = \ convert_quadratic_to_cubic_path((x0, y0), (xi, yi), (xn, yn)) path.curveTo(x1, y1, x2, y2, xn, yn) # quadratic bezier, relative elif op == 'q': x0, y0 = points[-2:] x1, y1, xn, yn = nums x1, y1, xn, yn = x0 + x1, y0 + y1, x0 + xn, y0 + yn (x0, y0), (x1, y1), (x2, y2), (xn, yn) = \ convert_quadratic_to_cubic_path((x0, y0), (x1, y1), (xn, yn)) path.curveTo(x1, y1, x2, y2, xn, yn) elif op == 't': if len(points) < 4: xp, yp, x0, y0 = points[-2:] * 2 else: xp, yp, x0, y0 = points[-4:] x0, y0 = points[-2:] xn, yn = nums xn, yn = x0 + xn, y0 + yn xi, yi = x0 + (x0 - xp), y0 + (y0 - yp) (x0, y0), (x1, y1), (x2, y2), (xn, yn) = \ convert_quadratic_to_cubic_path((x0, y0), (xi, yi), (xn, yn)) path.curveTo(x1, y1, x2, y2, xn, yn) # elliptical arc elif op in ('A', 'a'): rx, ry, phi, fA, fS, x2, y2 = nums x1, y1 = points[-2:] if op == 'a': x2 += x1 y2 += y1 if abs(rx) <= 1e-10 or abs(ry) <= 1e-10: path.lineTo(x2, y2) else: bp = bezier_arc_from_end_points(x1, y1, rx, ry, phi, fA, fS, x2, y2) for _, _, x1, y1, x2, y2, xn, yn in bp: path.curveTo(x1, y1, x2, y2, xn, yn) # close path elif op in ('Z', 'z'): path.closePath() else: logger.debug("Suspicious path operator: %s" % op) lastop = op gr = Group() self.applyStyleOnShape(path, node) if path.operators[-1] != _CLOSEPATH: unclosed_subpath_pointers.append(len(path.operators)) if unclosed_subpath_pointers and path.fillColor is not None: # ReportLab doesn't fill unclosed paths, so we are creating a copy # of the path with all subpaths closed, but without stroke. # https://bitbucket.org/rptlab/reportlab/issues/99/ closed_path = NoStrokePath(copy_from=path) for pointer in reversed(unclosed_subpath_pointers): closed_path.operators.insert(pointer, _CLOSEPATH) gr.add(closed_path) path.fillColor = None gr.add(path) return gr
def convertPath(self, node): d = node.getAttribute('d') if not d: return None normPath = normalise_svg_path(d) path = Path(autoclose='svg') points = path.points # Track subpaths needing to be closed later subpath_start = [] lastop = '' for i in xrange(0, len(normPath), 2): op, nums = normPath[i:i + 2] # moveto absolute if op == 'M': path.moveTo(*nums) subpath_start = points[-2:] # lineto absolute elif op == 'L': path.lineTo(*nums) # moveto relative elif op == 'm': if len(points) >= 2: if lastop in ('Z', 'z'): starting_point = subpath_start else: starting_point = points[-2:] xn, yn = starting_point[0] + nums[0], starting_point[ 1] + nums[1] path.moveTo(xn, yn) else: path.moveTo(*nums) subpath_start = points[-2:] # lineto relative elif op == 'l': xn, yn = points[-2] + nums[0], points[-1] + nums[1] path.lineTo(xn, yn) # horizontal/vertical line absolute elif op == 'H': path.lineTo(nums[0], points[-1]) elif op == 'V': path.lineTo(points[-2], nums[0]) # horizontal/vertical line relative elif op == 'h': path.lineTo(points[-2] + nums[0], points[-1]) elif op == 'v': path.lineTo(points[-2], points[-1] + nums[0]) # cubic bezier, absolute elif op == 'C': path.curveTo(*nums) elif op == 'S': x2, y2, xn, yn = nums if len(points) < 4 or lastop not in {'c', 'C', 's', 'S'}: xp, yp, x0, y0 = points[-2:] * 2 else: xp, yp, x0, y0 = points[-4:] xi, yi = x0 + (x0 - xp), y0 + (y0 - yp) path.curveTo(xi, yi, x2, y2, xn, yn) # cubic bezier, relative elif op == 'c': xp, yp = points[-2:] x1, y1, x2, y2, xn, yn = nums path.curveTo(xp + x1, yp + y1, xp + x2, yp + y2, xp + xn, yp + yn) elif op == 's': x2, y2, xn, yn = nums if len(points) < 4 or lastop not in {'c', 'C', 's', 'S'}: xp, yp, x0, y0 = points[-2:] * 2 else: xp, yp, x0, y0 = points[-4:] xi, yi = x0 + (x0 - xp), y0 + (y0 - yp) path.curveTo(xi, yi, x0 + x2, y0 + y2, x0 + xn, y0 + yn) # quadratic bezier, absolute elif op == 'Q': x0, y0 = points[-2:] x1, y1, xn, yn = nums (x0, y0), (x1, y1), (x2, y2), (xn, yn) = \ convert_quadratic_to_cubic_path((x0, y0), (x1, y1), (xn, yn)) path.curveTo(x1, y1, x2, y2, xn, yn) elif op == 'T': if len(points) < 4: xp, yp, x0, y0 = points[-2:] * 2 else: xp, yp, x0, y0 = points[-4:] xi, yi = x0 + (x0 - xp), y0 + (y0 - yp) xn, yn = nums (x0, y0), (x1, y1), (x2, y2), (xn, yn) = \ convert_quadratic_to_cubic_path((x0, y0), (xi, yi), (xn, yn)) path.curveTo(x1, y1, x2, y2, xn, yn) # quadratic bezier, relative elif op == 'q': x0, y0 = points[-2:] x1, y1, xn, yn = nums x1, y1, xn, yn = x0 + x1, y0 + y1, x0 + xn, y0 + yn (x0, y0), (x1, y1), (x2, y2), (xn, yn) = \ convert_quadratic_to_cubic_path((x0, y0), (x1, y1), (xn, yn)) path.curveTo(x1, y1, x2, y2, xn, yn) elif op == 't': if len(points) < 4: xp, yp, x0, y0 = points[-2:] * 2 else: xp, yp, x0, y0 = points[-4:] x0, y0 = points[-2:] xn, yn = nums xn, yn = x0 + xn, y0 + yn xi, yi = x0 + (x0 - xp), y0 + (y0 - yp) (x0, y0), (x1, y1), (x2, y2), (xn, yn) = \ convert_quadratic_to_cubic_path((x0, y0), (xi, yi), (xn, yn)) path.curveTo(x1, y1, x2, y2, xn, yn) # elliptical arc elif op in ('A', 'a'): rx, ry, phi, fA, fS, x2, y2 = nums x1, y1 = points[-2:] if op == 'a': x2 += x1 y2 += y1 if abs(rx) <= 1e-10 or abs(ry) <= 1e-10: path.lineTo(x2, y2) else: bp = bezier_arc_from_end_points(x1, y1, rx, ry, phi, fA, fS, x2, y2) for _, _, x1, y1, x2, y2, xn, yn in bp: path.curveTo(x1, y1, x2, y2, xn, yn) # close path elif op in ('Z', 'z'): path.closePath() else: logger.debug("Suspicious path operator: %s" % op) lastop = op gr = Group() self.applyStyleOnShape(path, node) gr.add(path) return gr