def parseTransform(self, e): t = QTransform() # transforms don't apply to the root svg element, but we do need to # take into account the viewBox there if self.isParentSvg: viewBox = e.attrib.get('viewBox', None) if viewBox is not None: (x, y, innerWidth, innerHeight) = map(self.parseUnit, re.split("[ ,]+", viewBox)) if x != 0 or y != 0: raise ValueError( "viewBox '%s' needs to be translated " "because is not at the origin. " "See https://github.com/codelv/inkcut/issues/69" % viewBox) outerWidth, outerHeight = map(self.parseUnit, (e.attrib.get( 'width', None), e.attrib.get('height', None))) if outerWidth is not None and outerHeight is not None: t.scale(outerWidth / innerWidth, outerHeight / innerHeight) else: x, y = map(self.parseUnit, (e.attrib.get('x', 0), e.attrib.get('y', 0))) t.translate(x, y) return t
def _create_copy(self): """ Creates a copy of the original graphic applying the given transforms """ optimized_path = self.optimized_path bbox = optimized_path.boundingRect() # Create the base copy t = QTransform() t.scale( self.scale[0] * (self.mirror[0] and -1 or 1), self.scale[1] * (self.mirror[1] and -1 or 1), ) # Rotate about center if self.rotation != 0: c = bbox.center() t.translate(-c.x(), -c.y()) t.rotate(self.rotation) t.translate(c.x(), c.y()) # Apply transform path = optimized_path * t # Add weedline to copy if self.copy_weedline: self._add_weedline(path, self.copy_weedline_padding) # If it's too big we have to scale it w, h = path.boundingRect().width(), path.boundingRect().height() available_area = self.material.available_area #: This screws stuff up! if w > available_area.width() or h > available_area.height(): # If it's too big an auto scale is enabled, resize it to fit if self.auto_scale: sx, sy = 1, 1 if w > available_area.width(): sx = available_area.width() / w if h > available_area.height(): sy = available_area.height() / h s = min(sx, sy) # Fit to the smaller of the two path = optimized_path * QTransform.fromScale(s, s) # Move to bottom left p = path.boundingRect().bottomRight() path = path * QTransform.fromTranslate(-p.x(), -p.y()) return path
def parseTransform(self, e): """ Based on simpletrasnform.py by from Jean-Francois Barraud, [email protected] """ t = QTransform() if isinstance(e, EtreeElement): trans = e.attrib.get('transform', '').strip() else: trans = e # e is a string of the previous transform if not trans: return t m = re.match( "(translate|scale|rotate|skewX|skewY|matrix)\s*\(([^)]*)\)\s*,?", trans) if m is None: return t name, args = m.group(1), m.group(2).replace(',', ' ').split() if name == "translate": # The translate(<x> [<y>]) transform function moves the object # by x and y. If y is not provided, it is assumed to be 0. dx = float(args[0]) dy = float(args[1]) if len(args) == 2 else 0 t.translate(dx, dy) elif name == "scale": # The scale(<x> [<y>]) transform function specifies a scale # operation by x and y. If y is not provided, it is assumed to # be equal to x. sx = float(args[0]) sy = float(args[1]) if len(args) == 2 else sx t.scale(sx, sy) elif name == "rotate": # The rotate(<a> [<x> <y>]) transform function specifies a # rotation by a degrees about a given point. If optional # parameters x and y are not supplied, the rotation is about the # origin of the current user coordinate system. If optional # parameters x and y are supplied, the rotation is about the # point (x, y). if len(args) == 1: cx, cy = (0, 0) else: cx, cy = map(float, args[1:]) t.translate(cx, cy) t.rotate(float(args[0])) t.translate(-cx, -cy) elif name == "skewX": # The skewX(<a>) transform function specifies a skew transformation # along the x axis by a degrees. t.shear(math.tan(float(args[0]) * math.pi / 180.0), 0) elif name == "skewY": # The skewY(<a>) transform function specifies a skew transformation # along the y axis by a degrees. t.shear(0, math.tan(float(args[0]) * math.pi / 180.0)) elif name == "matrix": t = t * QTransform(*map(float, args)) if m.end() < len(trans): t = self.parseTransform(trans[m.end():]) * t return t