def set_stroke(self, dc, svg_stroke, line_width=1.0, linecap='butt', dasharray=None): #Patch to avoid to have too dim lines for staff, bar, note stems if line_width < 1: line_width = 1.0 #End Patch if dasharray: # convert from something like "5,5" to (5,5) dasharray = tuple([int(x.strip()) for x in dasharray.split(',')]) # 1.3.6.3 [JWDJ] 2015-3 search cache once instead of twice key = (svg_stroke, line_width, dasharray) pen = self.stroke_cache.get(key) if pen is None: if svg_stroke == 'none': if WX41: pen = self.renderer.CreatePen(wx.GraphicsPenInfo(style=wx.PENSTYLE_TRANSPARENT)) else: pen = self.renderer.CreatePen(wx.NullPen) else: if WX41: wxpen = wx.GraphicsPenInfo(wx_colour(svg_stroke)).Width(line_width) if linecap == 'butt': wxpen.Cap(wx.CAP_BUTT) elif linecap == 'round': wxpen.Cap(wx.CAP_ROUND) else: raise Exception('linecap %s not supported yet' % linecap) # if dasharray: # # 1.3.6.3 [JWDJ] 2015-3 dasharray is always a tuple, never a str or unicode # #if type(dasharray) in (str, unicode): # # dasharray = [int(x.strip()) for x in dasharray.split(',')] # wxpen.Dashes(list(dasharray)) # wxpen.Style(wx.USER_DASH) wxpen.Join(wx.JOIN_MITER) else: wxpen = wx.Pen(wx_colour(svg_stroke), line_width) if linecap == 'butt': wxpen.SetCap(wx.CAP_BUTT) elif linecap == 'round': wxpen.SetCap(wx.CAP_ROUND) else: raise Exception('linecap %s not supported yet' % linecap) if dasharray: # 1.3.6.3 [JWDJ] 2015-3 dasharray is always a tuple, never a str or unicode #if type(dasharray) in (str, unicode): # dasharray = [int(x.strip()) for x in dasharray.split(',')] wxpen.SetDashes(list(dasharray)) wxpen.SetStyle(wx.USER_DASH) wxpen.SetJoin(wx.JOIN_MITER) pen = self.renderer.CreatePen(wxpen) self.stroke_cache[key] = pen dc.SetPen(pen)
def paint_arrow_tip(self, gc: wx.GraphicsContext, fill: wx.Colour): assert len(self.arrow_adjusted_coords) == 4, \ "Arrow adjusted coords is not of length 4: {}".format(self.arrow_adjusted_coords) gc.SetPen(gc.CreatePen(wx.GraphicsPenInfo(fill))) gc.SetBrush(wx.Brush(fill)) gc.DrawLines([wx.Point2D(*(coord)) for coord in self.arrow_adjusted_coords])
def do_paint(self, gc: wx.GraphicsContext, fill: wx.Colour, selected: bool): self._recompute(for_collision=False) rxn_color: wx.Colour # Draw bezier curve if selected: rxn_color = get_theme('selected_reaction_fill') else: rxn_color = fill pen = gc.CreatePen(wx.GraphicsPenInfo(rxn_color).Width(self.thickness)) gc.SetPen(pen) # gc.StrokeLines([wx.Point2D(*(p * cstate.scale)) for p in self.bezier_points]) path = gc.CreatePath() points = [p for p in (self.node_intersection, self.handle.tip, self.centroid_handle.tip, self.real_center)] path.MoveToPoint(*points[0]) if self.bezierCurves: path.AddCurveToPoint(*points[1], *points[2], *points[3]) else: path.AddLineToPoint(*points[3]) gc.StrokePath(path) if selected: assert self.node_intersection is not None self.handle.base = self.node_intersection # Draw arrow tip if not self.is_source: color = get_theme('handle_color') if selected else fill self.paint_arrow_tip(gc, color)
def _makePen(self, ctx, shape): # set up a pen from the shape.stroke (SVGpaint) object width = shape.strokeWidth join = { SVG_JOIN_MITER : wx.JOIN_MITER, SVG_JOIN_ROUND : wx.JOIN_ROUND, SVG_JOIN_BEVEL : wx.JOIN_BEVEL}.get(shape.strokeLineJoin, 0) cap = { SVG_CAP_BUTT : wx.CAP_BUTT, SVG_CAP_ROUND : wx.CAP_ROUND, SVG_CAP_SQUARE : wx.CAP_PROJECTING}.get(shape.strokeLineCap, 0) # TODO: handle dashes info = wx.GraphicsPenInfo(wx.BLACK).Width(width).Join(join).Cap(cap) if shape.stroke.type == SVG_PAINT_NONE: pen = wx.NullGraphicsPen elif shape.stroke.type == SVG_PAINT_COLOR: info.Colour(shape.stroke.color_rgba) pen = ctx.CreatePen(info) elif shape.stroke.type == SVG_PAINT_LINEAR_GRADIENT: x1, y1, = (0.0, 0.0) x2, y2, = (0.0, 1.0) gradient = shape.stroke.gradient matrix = ctx.CreateMatrix(*gradient.xform) # Except for GDI+... See note above if ctx.Renderer.Type in _RenderersWithoutGradientTransforms: matrix.Invert() x1, y1 = matrix.TransformPoint(x1, y1) x2, y2 = matrix.TransformPoint(x2, y2) matrix = wx.NullGraphicsMatrix stops = self._makeGradientStops(gradient) info.LinearGradient(x1,y1, x2,y2, stops, matrix) pen = ctx.CreatePen(info) elif shape.stroke.type == SVG_PAINT_RADIAL_GRADIENT: cx, cy = (0.0, 0.0) radius = 1 gradient = shape.stroke.gradient matrix = ctx.CreateMatrix(*gradient.xform) # Except for GDI+... See note above if ctx.Renderer.Type in _RenderersWithoutGradientTransforms: matrix.Invert() cx, cy = matrix.TransformPoint(cx, cy) r1, r2 = matrix.TransformPoint(0, 1) radius = r2 - cy matrix = wx.NullGraphicsMatrix stops = self._makeGradientStops(gradient) info.RadialGradient(0,0, 0,0, 1, stops, matrix) pen = ctx.CreatePen(info) else: raise ValueError("Unknown stroke type") return pen
def draw_rect(gc: wx.GraphicsContext, rect: Rect, *, fill: Optional[wx.Colour] = None, border: Optional[wx.Colour] = None, border_width: float = 1, fill_style=wx.BRUSHSTYLE_SOLID, border_style=wx.PENSTYLE_SOLID, corner_radius: float = 0): """Draw a rectangle with the given graphics context. Either fill or border must be specified to avoid drawing an entirely transparent rectangle. Args: gc: The graphics context. rect: The rectangle to draw. fill: If specified, the fill color of the rectangle. border: If specified, the border color of the rectangle. border_width: The width of the borders. Defaults to 1. This cannot be 0 when border is specified. corner_radius: The corner radius of the rounded rectangle. Defaults to 0. """ assert not(fill is None and border is None), \ "Both 'fill' and 'border' are None, but at least one of them should be provided" assert not (border is not None and border_width == 0), \ "'border_width' cannot be 0 when 'border' is specified" x, y = rect.position width, height = rect.size pen: wx.Pen brush: wx.Brush # set up brush and pen if applicable if fill is not None: brush = gc.CreateBrush(wx.Brush(fill, fill_style)) else: brush = wx.TRANSPARENT_BRUSH if border is not None: pen = gc.CreatePen( wx.GraphicsPenInfo(border).Width(border_width).Style(border_style)) else: pen = wx.TRANSPARENT_PEN gc.SetPen(pen) gc.SetBrush(brush) # draw rect gc.DrawRoundedRectangle(x, y, width, height, corner_radius)
def paint_handle(gc: wx.GraphicsContext, base: Vec2, handle: Vec2, hovering: bool): """Paint the handle as given by its base and tip positions, highlighting it if hovering.""" c = get_theme('highlighted_handle_color') if hovering else get_theme('handle_color') brush = wx.Brush(c) pen = gc.CreatePen(wx.GraphicsPenInfo(c)) gc.SetPen(pen) # Draw handle lines gc.StrokeLine(*base, *handle) # Draw handle circles gc.SetBrush(brush) gc.DrawEllipse(handle.x - HANDLE_RADIUS, handle.y - HANDLE_RADIUS, 2 * HANDLE_RADIUS, 2 * HANDLE_RADIUS)
def do_paint(self, gc: wx.GraphicsContext): """Paint the handle as given by its base and tip positions, highlighting it if hovering.""" assert self.data.base is not None c = theme['highlighted_handle_color'] if self.hovering else theme[ 'handle_color'] brush = wx.Brush(c) pen = gc.CreatePen(wx.GraphicsPenInfo(c)) sbase = self.data.base * cstate.scale stip = self.data.tip * cstate.scale gc.SetPen(pen) # Draw handle lines gc.StrokeLine(*sbase, *stip) # Draw handle circles gc.SetBrush(brush) gc.DrawEllipse(stip.x - BezierHandle.HANDLE_RADIUS, stip.y - BezierHandle.HANDLE_RADIUS, 2 * BezierHandle.HANDLE_RADIUS, 2 * BezierHandle.HANDLE_RADIUS)
def drawLines(dc, *lines): ''' drawLines takes a device context (dc) and a list of lines as arguments. Each line is a three-tuple: (colour, thickness, linesegments). linesegments is a list of coordinates: (x1, y1, x2, y2). ''' """ Style Description wx.BDIAGONAL_HATCH The pen will draw backward (northwest to southeast) hatch lines. wx.CROSSDIAG_HATCH A combination of wx.bdiagonal_hatch and wx.fdiagonal_hatch— in other words, it creates x shapes. wx.CROSS_HATCH Crosshatched + shapes. wx.DOT Small dots. wx.DOT_DASH Alternating between small dots and longer dashes. wx.FDIAGONAL_HATCH The pen will draw forward (southwest to northeast) hatch lines. wx.HORIZONTAL_HATCH Short, horizontal hash lines. wx.LONG_DASH Long dashes. """ pen_styles = ["wx.SOLID", "wx.TRANSPARENT", "wx.DOT", "wx.LONG_DASH", "wx.SHORT_DASH", "wx.DOT_DASH", "wx.BDIAGONAL_HATCH", "wx.CROSSDIAG_HATCH", "wx.FDIAGONAL_HATCH", "wx.CROSS_HATCH", "wx.HORIZONTAL_HATCH", "wx.VERTICAL_HATCH", "wx.USER_DASH"] if 'wxMSW' in wx.PlatformInfo: pen_styles.append("wx.STIPPLE") brush_styles = ["wx.SOLID", "wx.TRANSPARENT", "wx.STIPPLE", "wx.BDIAGONAL_HATCH", "wx.CROSSDIAG_HATCH", "wx.FDIAGONAL_HATCH", "wx.CROSS_HATCH", "wx.HORIZONTAL_HATCH", "wx.VERTICAL_HATCH"] #dc.BeginDrawing() if 0: ctx = wx.GraphicsContext.Create(dc) pen = ctx.CreatePen(wx.GraphicsPenInfo(wx.BLUE).Width(1.25).Style(wx.PENSTYLE_DOT)) ctx.SetPen(pen) #colours = ['#e7ebee','#6c7197','#739211','#080300','#d92405','#3563eb','#eac124'] if 0: import images2 #stippleBitmap = images2.Smiles.GetBitmap() stippleBitmap = targetBitmap_point(wx.RED) #wx.SOLID+wx.CAP_PROJECTING cap = wx.CAP_BUTT caps=[wx.CAP_ROUND , wx.CAP_PROJECTING] #, wx.CAP_BUTT] caps=[wx.CAP_BUTT] brush= wx.SHORT_DASH for colour, thickness, lineSegments in lines: pen = wx.Pen(wx.Colour(colour), thickness, brush) if 0: #Fill-in pen.SetStipple(stippleBitmap) #CAP_ROUND , CAP_PROJECTING and CAP_BUTT if 1: #print(next(capsp)) #pen.SetCap(caps[randrange(0, len(caps))]) pen.SetCap(next(get_cap(caps))) #JOIN_BEVEL , JOIN_ROUND and JOIN_MITER if 1: pen.SetJoin(wx.JOIN_BEVEL) #pen.SetDashes([2, 5, 2, 2]) #bitmap.SetMask(wx.Mask(bitmap, wx.WHITE)) # It will allow you to mark places that should be transparent #dc.SetBrush(wx.Brush(wx.Colour(colours[randrange(0, len(colours))]), wx.TRANSPARENT)) dc.SetPen(pen) if len(lineSegments)>1: pass if 0: pp(lineSegments) for lineSegment in lineSegments: pp(lineSegment) dc.DrawLine(*lineSegments[0]) elif len(lineSegments)>0: line=lineSegments[0] dc.DrawLine(*line) span=25 tk= get_size(thicknesses) #[thickness]) #thicknesses) colr = get_color(colours) cap=get_cap(caps) if 1: pen = wx.Pen(wx.Colour(next(colr)), next(tk), brush) pen.SetCap(next(cap)) dc.SetPen(pen) dc.DrawLine(*[x+span*1 for x in line]) if 1: pen = wx.Pen(wx.Colour(next(colr)), next(tk), brush) pen.SetCap(next(cap)) dc.SetPen(pen) dc.DrawLine(*[x+span*2 for x in line]) if 1: pen = wx.Pen(wx.Colour(next(colr)), next(tk),brush) pen.SetCap(next(cap)) dc.SetPen(pen) dc.DrawLine(*[x+span*3 for x in line]) if 1: pen = wx.Pen(wx.Colour(next(colr)), next(tk), brush) pen.SetCap(next(cap)) dc.SetPen(pen) dc.DrawLine(*[x+span*4 for x in line]) if 1: pen = wx.Pen(wx.Colour(next(colr)), next(tk), brush) pen.SetCap(next(cap)) dc.SetPen(pen) dc.DrawLine(*[x+span*5 for x in line])