def bezier_arc_from_end_points(x1, y1, rx, ry, phi, fA, fS, x2, y2): if phi: # Our box bezier arcs can't handle rotations directly # move to a well known point, eliminate phi and transform the other point mx = mmult(rotate(-phi), translate(-x1, -y1)) tx2, ty2 = transformPoint(mx, (x2, y2)) # Convert to box form in unrotated coords cx, cy, rx, ry, start_ang, extent = end_point_to_center_parameters( 0, 0, tx2, ty2, fA, fS, rx, ry ) bp = bezier_arc_from_centre(cx, cy, rx, ry, start_ang, extent) # Re-rotate by the desired angle and add back the translation mx = mmult(translate(x1, y1), rotate(phi)) res = [] for x1, y1, x2, y2, x3, y3, x4, y4 in bp: res.append( transformPoint(mx, (x1, y1)) + transformPoint(mx, (x2, y2)) + transformPoint(mx, (x3, y3)) + transformPoint(mx, (x4, y4)) ) return res else: cx, cy, rx, ry, start_ang, extent = end_point_to_center_parameters( x1, y1, x2, y2, fA, fS, rx, ry ) return bezier_arc_from_centre(cx, cy, rx, ry, start_ang, extent)
def bezier_arc_from_end_points(x1, y1, rx, ry, phi, fA, fS, x2, y2): if (x1 == x2 and y1 == y2): # From https://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes: # If the endpoints (x1, y1) and (x2, y2) are identical, then this is # equivalent to omitting the elliptical arc segment entirely. return [] if phi: # Our box bezier arcs can't handle rotations directly # move to a well known point, eliminate phi and transform the other point mx = mmult(rotate(-phi), translate(-x1, -y1)) tx2, ty2 = transformPoint(mx, (x2, y2)) # Convert to box form in unrotated coords cx, cy, rx, ry, start_ang, extent = end_point_to_center_parameters( 0, 0, tx2, ty2, fA, fS, rx, ry) bp = bezier_arc_from_centre(cx, cy, rx, ry, start_ang, extent) # Re-rotate by the desired angle and add back the translation mx = mmult(translate(x1, y1), rotate(phi)) res = [] for x1, y1, x2, y2, x3, y3, x4, y4 in bp: res.append( transformPoint(mx, (x1, y1)) + transformPoint(mx, (x2, y2)) + transformPoint(mx, (x3, y3)) + transformPoint(mx, (x4, y4))) return res else: cx, cy, rx, ry, start_ang, extent = end_point_to_center_parameters( x1, y1, x2, y2, fA, fS, rx, ry) return bezier_arc_from_centre(cx, cy, rx, ry, start_ang, extent)
def _render(self, name, intent, dataGetter, **kwds): from xml.sax.saxutils import escape spec = self.intentSpecs[intent] valueName = spec.valueName D = self._defaults.get(intent, {}).copy() escapeAction = D.get('escape') D.update(kwds) if self.uppercase and 'content' in D and isinstance(D['content'], str): D['content'] = self.upper(D['content']) if valueName not in kwds: data = dataGetter(name, intent) if self.uppercase and isinstance(data, str): data = self.upper(data) if escapeAction == 'escape': data = escape(data) D[valueName] = data if spec.preRenderFunc: spec.preRenderFunc(D) rml = [] add = rml.append if 'rotation' in D: angle = D['rotation'] add('<saveState/><rotate degrees="%s"/>' % angle) angle = float(angle) from reportlab.graphics.shapes import rotate, inverse, transformPoint D['x'], D['y'] = transformPoint(inverse(rotate(float(angle))), (float(D['x']), float(D['y']))) add(spec.rml(D)) if 'rotation' in D: add('<restoreState/>') return ''.join(rml) #+('<!--%s-->' % name)
def _render(self,name,intent,dataGetter,**kwds): from xml.sax.saxutils import escape spec = self.intentSpecs[intent] valueName = spec.valueName D=self._defaults.get(intent,{}).copy() escapeAction=D.get('escape') D.update(kwds) if self.uppercase and 'content' in D and isinstance(D['content'],str): D['content'] = self.upper(D['content']) if valueName not in kwds: data = dataGetter(name, intent) if self.uppercase and isinstance(data,str): data = self.upper(data) if escapeAction == 'escape': data = escape(data) D[valueName] = data if spec.preRenderFunc: spec.preRenderFunc(D) rml = [] add = rml.append if 'rotation' in D: angle = D['rotation'] add('<saveState/><rotate degrees="%s"/>' % angle) angle = float(angle) from reportlab.graphics.shapes import rotate, inverse, transformPoint D['x'],D['y'] = transformPoint(inverse(rotate(float(angle))),(float(D['x']),float(D['y']))) add(spec.rml(D)) if 'rotation' in D: add('<restoreState/>') return ''.join(rml)#+('<!--%s-->' % name)
def getBounds(obj): if hasattr(obj, 'getBounds'): # this is the preferred "future" solution :-) return obj.getBounds() # else try all the primitive shapes elif isinstance(obj, shapes.Line): return (obj.x1, obj.y1, obj.x2, obj.y2) elif isinstance(obj, shapes.Rect): return (obj.x, obj.y, obj.x + obj.width, obj.y + obj.height) elif isinstance(obj, shapes.Circle): return (obj.cx - obj.r, obj.cy - obj.r, obj.cx + obj.r, obj.cy + obj.r) elif isinstance(obj, shapes.Ellipse): return (obj.cx - obj.rx, obj.cy - obj.ry, obj.cx + obj.rx, obj.cy + obj.ry) elif isinstance(obj, shapes.Polygon): return getPointsBounds(obj.points) elif isinstance(obj, shapes.PolyLine): return getPointsBounds(obj.points) elif isinstance(obj, shapes.Wedge): return getPointsBounds(obj.asPolygon().points) elif isinstance(obj, shapes.String): w = stringWidth(obj.text, obj.fontName, obj.fontSize) x = obj.x tA = obj.textAnchor if tA != 'start': if tA == 'middle': x -= 0.5 * w elif tA == 'end': x -= w elif tA == 'numeric': x -= shapes.numericXShift(tA, obj.text, w, obj.fontName, obj.fontSize, obj.encoding) return (x, obj.y - 0.2 * obj.fontSize, x + w, obj.y + obj.fontSize) elif isinstance(obj, shapes.Path): xs = [] ys = [] points = obj.points[:] while points: xs.append(points[0]) ys.append(points[1]) points = points[2:] return (min(xs), min(ys), max(xs), max(ys)) # then groups, which need transformation... elif isinstance(obj, shapes.Group): #iterate over each thing getting its rect if obj.contents: b = [] for elem in obj.contents: b.append(getBounds(elem)) (x1, y1, x2, y2) = getRectsBounds(b) trans = obj.transform corners = [[x1, y1], [x1, y2], [x2, y1], [x2, y2]] newCorners = [] for corner in corners: newCorners.append(shapes.transformPoint(trans, corner)) return getPointsBounds(newCorners) else: #empty group needs a sane default; this #will happen when interactively creating a group #nothing has been added to yet. The alternative is #to handle None as an allowed return value everywhere. return (0, 0, 0, 0) elif isinstance(obj, shapes.UserNode): return getBounds(obj.provideNode()) else: raise ValueError("Don't know how to get bounds of %s" % obj)