def debug(self, painter): #Paint path painter.setBrush(QBrush(QColor(0, 0, 0, 25))) pen = QPen(QColor(255, 0, 0, 100)) pen.setWidth(1) painter.setPen(pen) #Curve area path = QPainterPath() path.addPath(self.shape()) painter.drawPath(path) #Curve controll points painter.drawEllipse(self.curvePoint1, 2, 2) painter.drawEllipse(self.curvePoint2, 2, 2) #Draw area painter.setPen(QPen(QColor(0, 255, 0, 100))) painter.setBrush(QBrush(QColor(0, 0, 0, 15))) path2 = QPainterPath() rect = self.boundingRect() path2.addRect(rect) painter.drawPath(path2) #Middel point painter.setPen(QPen(QColor(0, 0, 255, 100))) painter.drawEllipse(self.midPoint, 2, 2)
def paintEvent(self, event): super(BubbleLabel, self).paintEvent(event) painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) # 抗锯齿 rectPath = QPainterPath() # 圆角矩形 triPath = QPainterPath() # 底部三角形 height = self.height() - 8 # 往上偏移8 rectPath.addRoundedRect(QRectF(0, 0, self.width(), height), 5, 5) x = self.width() / 5 * 4 triPath.moveTo(x, height) # 移动到底部横线4/5处 # 画三角形 triPath.lineTo(x + 6, height + 8) triPath.lineTo(x + 12, height) rectPath.addPath(triPath) # 添加三角形到之前的矩形上 # 边框画笔 painter.setPen( QPen(self.BorderColor, 1, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) # 背景画刷 painter.setBrush(self.BackgroundColor) # 绘制形状 painter.drawPath(rectPath) # 三角形底边绘制一条线保证颜色与背景一样 painter.setPen( QPen(self.BackgroundColor, 1, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) painter.drawLine(x, height, x + 12, height)
class TaxiRouteItem(QGraphicsItem): ''' Draws a set of edges that turn on/off together, each possibly labelled. Call prepareGeometryChange after building to initialise correctly. ''' def __init__(self, parentItem, segments, colour): QGraphicsItem.__init__(self, parent=parentItem) self.colour_name = colour self.shape = QPainterPath() self.labels = QGraphicsItemGroup(self) self.bbox = QRectF(0, 0, 0, 0) for (p1, p2), label in segments: lvect = QVector2D(p2 - p1) lpath = QPainterPath() m = TWY_line_margin l = lvect.length() plst = [QPointF(-m, 0), QPointF(-m/3, -m), QPointF(l + m/3, -m), QPointF(l + m, 0), QPointF(l + m/3, m), QPointF(-m/3, m)] lpath.addPolygon(QPolygonF(plst)) lrot = QTransform() lrot.rotateRadians(atan2(lvect.y(), lvect.x())) lpath = lrot.map(lpath) lpath.translate(p1) self.shape.addPath(lpath) rect = QRectF(p1, p2).normalized() if label != None: self.labels.addToGroup(TaxiwayLabelItem(label, rect.center(), self)) self.bbox |= rect self.shape.setFillRule(Qt.WindingFill) self.mouse_highlight = False self.labels.setVisible(False) def hoverEnterEvent(self, event): self.mouse_highlight = self.scene().mouseover_highlights_groundnet_edges if self.mouse_highlight and not self.labels.isVisible(): self.labels.setVisible(True) self.setVisible(False) self.setVisible(True) def hoverLeaveEvent(self, event): self.mouse_highlight = False self.labels.setVisible(self.scene().show_taxiway_names) self.setVisible(False) self.setVisible(True) def boundingRect(self): return withMargins(self.bbox, TWY_line_margin) def shape(self): return self.shape def paint(self, painter, option, widget): if self.mouse_highlight or self.scene().show_ground_networks: painter.setPen(QPen(Qt.NoPen)) brushcol = settings.colour(self.colour_name) brushcol.setAlpha(96 if self.mouse_highlight else 64) painter.setBrush(QBrush(brushcol)) painter.drawPath(self.shape)
def painterPath(self): """ Returns the current shape as QPainterPath (used for collision detection). :rtype: QPainterPath """ path = QPainterPath() path.addPath(self.path) path.addPolygon(self.head) return path
def shape(self): """Overload QGraphicsItem method.""" # otherwise the shape is the children boundingRect ! # and since itemAt uses shape, # the item was found, instead of the background path = QPainterPath() for ray in self.e.rays: path.addPath(ray.g.shape()) return path
def painterPath(self): """ Returns the current shape as QPainterPath (used for collision detection). :rtype: QPainterPath """ path = QPainterPath() path.addPath(self.path) path.addPolygon(self.head) path.addPolygon(self.tail) return path
def _updateSequenceText(self): seq_item = self._seq_item is_on_top = self._is_on_top index = self._insertion.idx() base_text = self._seq_text font = styles.SEQUENCEFONT seq_font_h = styles.SEQUENCEFONTH insert_w = styles.INSERTWIDTH seq_font_char_w = styles.SEQUENCEFONTCHARWIDTH # draw sequence on the insert if base_text: # only draw sequences if they exist i.e. not None! len_BT = len(base_text) if is_on_top: angle_offset = 0 else: angle_offset = 180 if len_BT > 20: base_text = base_text[:17] + '...' len_BT = len(base_text) fraction_arc_len_per_char = ( 1.0 - 2.0 * _FRACTION_INSERT_TO_PAD) / (len_BT + 1) seq_item.setPen(QPen(Qt.NoPen)) seq_item.setBrush(QBrush(Qt.black)) seq_path = QPainterPath() loop_path = self.path() for i in range(len_BT): frac = _FRACTION_INSERT_TO_PAD + ( i + 1) * fraction_arc_len_per_char pt = loop_path.pointAtPercent(frac) tang_ang = loop_path.angleAtPercent(frac) temp_path = QPainterPath() # 1. draw the text temp_path.addText(0, 0, font, base_text[i if is_on_top else -i - 1]) # 2. center it at the zero point different for top and bottom # strands if not is_on_top: temp_path.translate(0, -seq_font_h - insert_w) temp_path.translate( QPointF(-seq_font_char_w / 2., -2 if is_on_top else seq_font_h)) mat = QTransform() # 3. rotate it mat.rotate(-tang_ang + angle_offset) rotated_path = mat.map(temp_path) # 4. translate the rotate object to it's position on the part rotated_path.translate(pt) seq_path.addPath(rotated_path) # end for seq_item.setPath(seq_path)
def _paintEpiHead(self, painter): path = QPainterPath() path.moveTo(QPointF(0, 0)) path.addPath(self._arrowHead) line = self.headLine() u = line.p1() - line.p2() mag_u = mag2D(u) if mag_u != 0: u /= mag_u path.addPath(self._arrowHead.translated(u * self.arrowHeadSize())) painter.drawPath(path)
def draw_rect(data, path: QPainterPath): new_path = QPainterPath() for i, row in data.iterrows(): new_path.addRect( row['time_axis_scaled'] - 15, # x row['r_open'], # y 30, # width row['open'] - row['close'], # height ) path.addPath(new_path)
def _updateSequenceText(self): seq_item = self._seq_item is_on_top = self._is_on_top index = self._insertion.idx() base_text = self._seq_text font = styles.SEQUENCEFONT seq_font_h = styles.SEQUENCEFONTH insert_w = styles.INSERTWIDTH seq_font_char_w = styles.SEQUENCEFONTCHARWIDTH # draw sequence on the insert if base_text: # only draw sequences if they exist i.e. not None! len_BT = len(base_text) if is_on_top: angle_offset = 0 else: angle_offset = 180 if len_BT > 20: base_text = base_text[:17] + '...' len_BT = len(base_text) fraction_arc_len_per_char = (1.0 - 2.0*_FRACTION_INSERT_TO_PAD) / (len_BT + 1) seq_item.setPen(QPen(Qt.NoPen)) seq_item.setBrush(QBrush(Qt.black)) seq_path = QPainterPath() loop_path = self.path() for i in range(len_BT): frac = _FRACTION_INSERT_TO_PAD + (i+1)*fraction_arc_len_per_char pt = loop_path.pointAtPercent(frac) tang_ang = loop_path.angleAtPercent(frac) temp_path = QPainterPath() # 1. draw the text temp_path.addText(0, 0, font, base_text[i if is_on_top else -i-1]) # 2. center it at the zero point different for top and bottom # strands if not is_on_top: temp_path.translate(0, -seq_font_h - insert_w) temp_path.translate(QPointF(-seq_font_char_w / 2., -2 if is_on_top else seq_font_h)) mat = QTransform() # 3. rotate it mat.rotate(-tang_ang + angle_offset) rotated_path = mat.map(temp_path) # 4. translate the rotate object to it's position on the part rotated_path.translate(pt) seq_path.addPath(rotated_path) # end for seq_item.setPath(seq_path)
def _updateSequenceText(self): seqItem = self._seqItem isOnTop = self._isOnTop index = self._insertion.idx() baseText = self._seqText font = styles.SEQUENCEFONT seqFontH = styles.SEQUENCEFONTH insertW = styles.INSERTWIDTH seqFontCharW = styles.SEQUENCEFONTCHARWIDTH # draw sequence on the insert if baseText: # only draw sequences if they exist i.e. not None! lenBT = len(baseText) if isOnTop: angleOffset = 0 else: angleOffset = 180 if lenBT > 20: baseText = baseText[:17] + '...' lenBT = len(baseText) fractionArclenPerChar = (1.0 - 2.0 * _fractionInsertToPad) / (lenBT + 1) seqItem.setPen(QPen(Qt.NoPen)) seqItem.setBrush(QBrush(Qt.black)) seqPath = QPainterPath() loopPath = self.path() for i in range(lenBT): frac = _fractionInsertToPad + (i + 1) * fractionArclenPerChar pt = loopPath.pointAtPercent(frac) tangAng = loopPath.angleAtPercent(frac) tempPath = QPainterPath() # 1. draw the text tempPath.addText(0, 0, font, baseText[i if isOnTop else -i - 1]) # 2. center it at the zero point different for top and bottom # strands if not isOnTop: tempPath.translate(0, -seqFontH - insertW) tempPath.translate( QPointF(-seqFontCharW / 2., -2 if isOnTop else seqFontH)) mat = QMatrix3x3() # 3. rotate it mat.rotate(-tangAng + angleOffset) rotatedPath = mat.map(tempPath) # 4. translate the rotate object to it's position on the part rotatedPath.translate(pt) seqPath.addPath(rotatedPath) # end for seqItem.setPath(seqPath)
def paintEvent(self, event): self._alignmentPaths = [] painter = QPainter(self) painter.setPen(self._color) circleRadius = 2.5 selectedRadius = 3 padding = 1 rect = event.rect() size = min(rect.height(), rect.width()) offset = round(0.5 * (rect.width() - size)) painter.translate(offset, 0) borderRect = rect.__class__( rect.left() + circleRadius + padding, rect.top() + circleRadius + padding, size - 2 * (circleRadius + padding), size - 2 * (circleRadius + padding), ) borderPath = QPainterPath() borderPath.addRect(*borderRect.getRect()) columnCount = 3 radioPath = QPainterPath() selectedPath = QPainterPath() for row in range(columnCount): for col in range(columnCount): index = row * columnCount + col x, y = ( padding + col * 0.5 * borderRect.width(), padding + row * 0.5 * borderRect.height(), ) delta = selectedRadius - circleRadius sx = x - delta sy = y - delta if self._alignment == index: path = QPainterPath() path.addEllipse(sx, sy, 2 * selectedRadius, 2 * selectedRadius) selectedPath = path else: path = QPainterPath() path.addEllipse(x, y, 2 * circleRadius, 2 * circleRadius) radioPath.addPath(path) self._alignmentPaths.append( QRectF(sx + offset, sy, 2 * selectedRadius, 2 * selectedRadius)) painter.drawPath(borderPath - radioPath) painter.setRenderHint(QPainter.Antialiasing) painter.fillPath(radioPath, self._color) painter.fillPath(selectedPath, self._selectedColor)
def _updateSequenceText(self): seqItem = self._seqItem isOnTop = self._isOnTop index = self._insertion.idx() baseText = self._seqText font = styles.SEQUENCEFONT seqFontH = styles.SEQUENCEFONTH insertW = styles.INSERTWIDTH seqFontCharW = styles.SEQUENCEFONTCHARWIDTH # draw sequence on the insert if baseText: # only draw sequences if they exist i.e. not None! lenBT = len(baseText) if isOnTop: angleOffset = 0 else: angleOffset = 180 if lenBT > 20: baseText = baseText[:17] + '...' lenBT = len(baseText) fractionArclenPerChar = (1.0-2.0*_fractionInsertToPad)/(lenBT+1) seqItem.setPen(QPen(Qt.NoPen)) seqItem.setBrush(QBrush(Qt.black)) seqPath = QPainterPath() loopPath = self.path() for i in range(lenBT): frac = _fractionInsertToPad + (i+1)*fractionArclenPerChar pt = loopPath.pointAtPercent(frac) tangAng = loopPath.angleAtPercent(frac) tempPath = QPainterPath() # 1. draw the text tempPath.addText(0,0, font, baseText[i if isOnTop else -i-1]) # 2. center it at the zero point different for top and bottom # strands if not isOnTop: tempPath.translate(0, -seqFontH - insertW) tempPath.translate(QPointF(-seqFontCharW/2., -2 if isOnTop else seqFontH)) mat = QMatrix3x3() # 3. rotate it mat.rotate(-tangAng + angleOffset) rotatedPath = mat.map(tempPath) # 4. translate the rotate object to it's position on the part rotatedPath.translate(pt) seqPath.addPath(rotatedPath) # end for seqItem.setPath(seqPath)
def boundingRect(self): """ Returns the shape bounding rect. :rtype: QRectF """ path = QPainterPath() path.addPath(self.selection) path.addPolygon(self.head) for shape in self.handles: path.addEllipse(shape) for shape in self.anchors.values(): path.addEllipse(shape) return path.controlPointRect()
def shape(self): """ Returns the shape of this item as a QPainterPath in local coordinates. :rtype: QPainterPath """ path = QPainterPath() path.addPath(self.selection) path.addPolygon(self.head) if self.isSelected(): for shape in self.handles: path.addEllipse(shape) for shape in self.anchors.values(): path.addEllipse(shape) return path
def paintEvent(self, event): self._alignmentPaths = [] painter = QPainter(self) painter.setPen(QColor(45, 45, 45)) circleRadius = self._circleRadius padding = self._padding rect = event.rect() size = min(rect.height(), rect.width()) offset = .5 * (rect.width() - size) painter.translate(offset, 0) borderRect = rect.__class__( rect.left() + circleRadius + padding, rect.top() + circleRadius + padding, size - 2 * (circleRadius + padding), size - 2 * (circleRadius + padding)) borderPath = QPainterPath() borderPath.addRect(*borderRect.getRect()) columnCount = 3 radioPath = QPainterPath() selectedPath = QPainterPath() for row in range(columnCount): for col in range(columnCount): index = row * columnCount + col path = QPainterPath() path.addEllipse( padding + col * .5 * borderRect.width(), padding + row * .5 * borderRect.height(), 2 * circleRadius, 2 * circleRadius) if self._alignment == index: selectedPath = path self._alignmentPaths.append(path.translated(offset, 0)) radioPath.addPath(path) painter.drawPath(borderPath - radioPath) painter.setRenderHint(QPainter.Antialiasing) painter.drawPath(radioPath) painter.fillPath(selectedPath, Qt.black)
def draw_path(self): l, s, d = 45, 10, 10 proj = self.plan.projection.dot orig = np.array([0, 0]) axes = QPainterPath() axes.addPath(self.axis_arrow("x", orig, orig+l*proj([1, 0, 0]), s)) axes.addPath(self.axis_arrow("y", orig, orig+l*proj([0, 1, 0]), s)) axes.addPath(self.axis_arrow("z", orig, orig+l*proj([0, 0, 1]), s)) tran = self.deviceTransform(self.plan.viewportTransform()).inverted()[0] view = tran.mapRect(QRectF(self.plan.viewport().rect())) rect = axes.boundingRect() axes.translate(view.left() + view.width()/15 - rect.left(), view.bottom() - view.height()/15 - rect.bottom()) path = QPainterPath() path.addPath(axes) path.addEllipse(-d/2, -d/2, d, d) return path
def draw_path(self): l, s, d = 45, 10, 10 proj = self.plan.projection.dot orig = np.array([0, 0]) axes = QPainterPath() axes.addPath(self.axis_arrow("x", orig, orig + l * proj([1, 0, 0]), s)) axes.addPath(self.axis_arrow("y", orig, orig + l * proj([0, 1, 0]), s)) axes.addPath(self.axis_arrow("z", orig, orig + l * proj([0, 0, 1]), s)) tran = self.deviceTransform( self.plan.viewportTransform()).inverted()[0] view = tran.mapRect(QRectF(self.plan.viewport().rect())) rect = axes.boundingRect() axes.translate(view.left() + view.width() / 15 - rect.left(), view.bottom() - view.height() / 15 - rect.bottom()) path = QPainterPath() path.addPath(axes) path.addEllipse(-d / 2, -d / 2, d, d) return path
def drawGlyphPoints(painter, glyph, scale, drawStartPoints=True, drawOnCurves=True, drawOffCurves=True, drawCoordinates=False, drawSelection=True, drawBluesMarkers=True, onCurveColor=None, onCurveSmoothColor=None, offCurveColor=None, otherColor=None, backgroundColor=None): if onCurveColor is None: onCurveColor = defaultColor("glyphOnCurvePoints") if onCurveSmoothColor is None: onCurveSmoothColor = defaultColor("glyphOnCurveSmoothPoints") if offCurveColor is None: offCurveColor = defaultColor("glyphOffCurvePoints") if otherColor is None: otherColor = defaultColor("glyphOtherPoints") if backgroundColor is None: backgroundColor = defaultColor("background") bluesMarkerColor = defaultColor("glyphBluesMarker") notchColor = defaultColor("glyphContourStroke").lighter(200) # get the outline data outlineData = glyph.getRepresentation("defconQt.OutlineInformation") points = [] # blue zones markers if drawBluesMarkers and drawOnCurves: font = glyph.font blues = [] if font.info.postscriptBlueValues: blues += font.info.postscriptBlueValues if font.info.postscriptOtherBlues: blues += font.info.postscriptOtherBlues if blues: blues_ = set(blues) size = 13 * scale selectedSize = 15 * scale snapSize = 17 * scale selectedSnapSize = 20 * scale painter.save() pen = painter.pen() pen.setColor(QColor(255, 255, 255, 125)) pen.setWidth(0) painter.setPen(pen) for point in outlineData["onCurvePoints"]: x, y = point["point"] # TODO: we could add a non-overlapping interval tree special # cased for borders selected = drawSelection and point.get("selected", False) if selected: size_ = selectedSize snapSize_ = selectedSnapSize else: size_ = size snapSize_ = snapSize for yMin, yMax in zip(blues[::2], blues[1::2]): if not (y >= yMin and y <= yMax): continue # if yMin > 0 and y == yMin or yMin <= 0 and y == yMax: if y in blues_: path = lozengePath(x, y, snapSize_) else: path = ellipsePath(x, y, size_) painter.fillPath(path, bluesMarkerColor) painter.drawPath(path) painter.restore() # handles if drawOffCurves and outlineData["offCurvePoints"]: painter.save() painter.setPen(otherColor) for x1, y1, x2, y2 in outlineData["bezierHandles"]: drawLine(painter, x1, y1, x2, y2) painter.restore() # on curve if drawOnCurves and outlineData["onCurvePoints"]: size = 6.5 * scale selectedSize = 8.5 * scale smoothSize = 8 * scale selectedSmoothSize = 10 * scale startSize = 7 * scale selectedStartSize = 9 * scale loneStartSize = 12 * scale selectedLoneStartSize = 14 * scale painter.save() notchPath = QPainterPath() paths = (QPainterPath(), QPainterPath()) smoothPaths = (QPainterPath(), QPainterPath()) for point in outlineData["onCurvePoints"]: x, y = point["point"] points.append((x, y)) # notch if "smoothAngle" in point: angle = point["smoothAngle"] t = Identity.rotate(angle) x1, y1 = t.transformPoint((-1.35 * scale, 0)) x2, y2 = -x1, -y1 x1 += x y1 += y x2 += x y2 += y notchPath.moveTo(x1, y1) notchPath.lineTo(x2, y2) # points selected = drawSelection and point.get("selected", False) if selected: size_ = selectedSize smoothSize_ = selectedSmoothSize startSize_ = selectedStartSize loneStartSize_ = selectedLoneStartSize else: size_ = size smoothSize_ = smoothSize startSize_ = startSize loneStartSize_ = loneStartSize if drawStartPoints and "startPointAngle" in point: angle = point["startPointAngle"] if angle is not None: pointPath = trianglePath(x, y, startSize_, angle) else: pointPath = ellipsePath(x, y, loneStartSize_) elif point["smooth"]: pointPath = ellipsePath(x, y, smoothSize_) else: pointPath = rectanglePath(x, y, size_) # store the path if point["smooth"]: smoothPaths[selected].addPath(pointPath) else: paths[selected].addPath(pointPath) path, selectedPath = paths smoothPath, selectedSmoothPath = smoothPaths # fill selectedPath.setFillRule(Qt.WindingFill) selectedSmoothPath.setFillRule(Qt.WindingFill) painter.fillPath(selectedPath, onCurveColor) painter.fillPath(selectedSmoothPath, onCurveSmoothColor) # stroke pen = QPen(onCurveColor) pen.setWidthF(1.2 * scale) painter.setPen(pen) painter.drawPath(path) pen.setColor(onCurveSmoothColor) painter.setPen(pen) painter.drawPath(smoothPath) # notch pen.setColor(notchColor) pen.setWidth(0) painter.setPen(pen) painter.drawPath(notchPath) painter.restore() # off curve if drawOffCurves and outlineData["offCurvePoints"]: # points offSize = 4.25 * scale selectedOffSize = 6.75 * scale path = QPainterPath() selectedPath = QPainterPath() selectedPath.setFillRule(Qt.WindingFill) for point in outlineData["offCurvePoints"]: x, y = point["point"] selected = drawSelection and point.get("selected", False) if selected: offSize_ = selectedOffSize else: offSize_ = offSize pointPath = ellipsePath(x, y, offSize_) if selected: selectedPath.addPath(pointPath) else: path.addPath(pointPath) pen = QPen(offCurveColor) pen.setWidthF(2.5 * scale) painter.save() painter.setPen(pen) painter.drawPath(path) painter.fillPath(path, QBrush(backgroundColor)) painter.fillPath(selectedPath, QBrush(offCurveColor.lighter(135))) painter.restore() # coordinates if drawCoordinates: painter.save() painter.setPen(otherColor) font = painter.font() font.setPointSize(7) painter.setFont(font) for x, y in points: posX = x # TODO: We use + here because we align on top. Consider abstracting # yOffset. posY = y + 6 * scale x = round(x, 1) if int(x) == x: x = int(x) y = round(y, 1) if int(y) == y: y = int(y) text = "%d %d" % (x, y) drawTextAtPoint(painter, text, posX, posY, scale, xAlign="center", yAlign="top") painter.restore()
def drawGlyphPoints( painter, glyph, scale, rect, drawStartPoints=True, drawOnCurves=True, drawOffCurves=True, drawCoordinates=False, drawSelection=True, onCurveColor=None, otherColor=None, backgroundColor=None): if onCurveColor is None: layer = glyph.layer if layer is not None and layer.color is not None: onCurveColor = colorToQColor(layer.color) else: onCurveColor = defaultColor("glyphOnCurvePoints") if otherColor is None: otherColor = defaultColor("glyphOtherPoints") if backgroundColor is None: backgroundColor = defaultColor("background") # get the outline data outlineData = glyph.getRepresentation("defconQt.OutlineInformation") points = [] # start points if drawStartPoints and outlineData["startPoints"]: startWidth = startHeight = 15 * scale startHalf = startWidth / 2.0 path = QPainterPath() for point, angle in outlineData["startPoints"]: x, y = point if angle is not None: path.moveTo(x, y) path.arcTo(x - startHalf, y - startHalf, startWidth, startHeight, 180 - angle, 180) path.closeSubpath() else: path.addEllipse( x - startHalf, y - startHalf, startWidth, startHeight) startPointColor = QColor(otherColor) aF = startPointColor.alphaF() startPointColor.setAlphaF(aF * .3) painter.fillPath(path, startPointColor) # handles if drawOffCurves and outlineData["offCurvePoints"]: painter.save() painter.setPen(otherColor) for pt1, pt2 in outlineData["bezierHandles"]: x1, y1 = pt1 x2, y2 = pt2 # TODO: should lineWidth account scale by default drawLine(painter, x1, y1, x2, y2, 1.0 * scale) painter.restore() # on curve if drawOnCurves and outlineData["onCurvePoints"]: width = 7 * scale half = width / 2.0 smoothWidth = 8 * scale smoothHalf = smoothWidth / 2.0 painter.save() path = QPainterPath() selectedPath = QPainterPath() for point in outlineData["onCurvePoints"]: x, y = point["point"] points.append((x, y)) pointPath = QPainterPath() if point["smooth"]: x -= smoothHalf y -= smoothHalf pointPath.addEllipse(x, y, smoothWidth, smoothWidth) else: x -= half y -= half pointPath.addRect(x, y, width, width) if drawSelection and point["selected"]: selectedPath.addPath(pointPath) path.addPath(pointPath) pen = QPen(onCurveColor) pen.setWidthF(1.5 * scale) painter.setPen(pen) painter.fillPath(selectedPath, onCurveColor) painter.drawPath(path) painter.restore() # off curve if drawOffCurves and outlineData["offCurvePoints"]: # lines # points offWidth = 5 * scale offHalf = offWidth / 2.0 path = QPainterPath() selectedPath = QPainterPath() for point in outlineData["offCurvePoints"]: x, y = point["point"] points.append((x, y)) pointPath = QPainterPath() x -= offHalf y -= offHalf pointPath.addEllipse(x, y, offWidth, offWidth) if drawSelection and point["selected"]: selectedPath.addPath(pointPath) else: path.addPath(pointPath) pen = QPen(otherColor) pen.setWidthF(3.0 * scale) painter.save() painter.setPen(pen) painter.drawPath(path) painter.fillPath(path, QBrush(backgroundColor)) painter.drawPath(selectedPath) painter.fillPath(selectedPath, QBrush(otherColor)) painter.restore() # coordinates if drawCoordinates: otherColor = QColor(otherColor) otherColor.setAlphaF(otherColor.alphaF() * .6) painter.save() painter.setPen(otherColor) # TODO: decision + color font = painter.font() font.setPointSize(7) painter.setFont(font) for x, y in points: posX = x # TODO: We use + here because we align on top. Consider abstracting # yOffset. posY = y + 3 x = round(x, 1) if int(x) == x: x = int(x) y = round(y, 1) if int(y) == y: y = int(y) text = "%d %d" % (x, y) drawTextAtPoint(painter, text, posX, posY, scale, xAlign="center", yAlign="top") painter.restore()
def drawGlyphPoints(painter, glyph, scale, rect, drawStartPoints=True, drawOnCurves=True, drawOffCurves=True, drawCoordinates=True, onCurveColor=None, otherColor=None, backgroundColor=None): layer = glyph.layer onCurveColor = None if layer is not None: if layer.color is not None: onCurveColor = colorToQColor(layer.color) if onCurveColor is None: onCurveColor = defaultColor("glyphOnCurvePoints") if otherColor is None: otherColor = defaultColor("glyphOtherPoints") if backgroundColor is None: backgroundColor = defaultColor("background") # get the outline data outlineData = glyph.getRepresentation("defconQt.OutlineInformation") points = [] # start points if drawStartPoints and outlineData["startPoints"]: startWidth = startHeight = 15 * scale startHalf = startWidth / 2.0 path = QPainterPath() for point, angle in outlineData["startPoints"]: x, y = point if angle is not None: path.moveTo(x, y) path.arcTo(x - startHalf, y - startHalf, startWidth, startHeight, 180 - angle, 180) path.closeSubpath() else: path.addEllipse(x - startHalf, y - startHalf, startWidth, startHeight) startPointColor = QColor(otherColor) aF = startPointColor.alphaF() startPointColor.setAlphaF(aF * .3) painter.fillPath(path, startPointColor) # off curve if drawOffCurves and outlineData["offCurvePoints"]: # lines painter.save() painter.setPen(otherColor) for pt1, pt2 in outlineData["bezierHandles"]: x1, y1 = pt1 x2, y2 = pt2 # TODO: should lineWidth account scale by default drawLine(painter, x1, y1, x2, y2, 1.0 * scale) # points offWidth = 5 * scale offHalf = offWidth / 2.0 path = QPainterPath() selectedPath = QPainterPath() for point in outlineData["offCurvePoints"]: x, y = point["point"] points.append((x, y)) pointPath = QPainterPath() x -= offHalf y -= offHalf pointPath.addEllipse(x, y, offWidth, offWidth) if point["selected"]: selectedPath.addPath(pointPath) else: path.addPath(pointPath) pen = QPen(otherColor) pen.setWidthF(3.0 * scale) painter.setPen(pen) painter.drawPath(path) painter.fillPath(path, QBrush(backgroundColor)) painter.drawPath(selectedPath) painter.fillPath(selectedPath, QBrush(otherColor)) painter.restore() # on curve if drawOnCurves and outlineData["onCurvePoints"]: width = 7 * scale half = width / 2.0 smoothWidth = 8 * scale smoothHalf = smoothWidth / 2.0 painter.save() path = QPainterPath() selectedPath = QPainterPath() for point in outlineData["onCurvePoints"]: x, y = point["point"] points.append((x, y)) pointPath = QPainterPath() if point["smooth"]: x -= smoothHalf y -= smoothHalf pointPath.addEllipse(x, y, smoothWidth, smoothWidth) else: x -= half y -= half pointPath.addRect(x, y, width, width) if point["selected"]: selectedPath.addPath(pointPath) path.addPath(pointPath) pen = QPen(onCurveColor) pen.setWidthF(1.5 * scale) painter.setPen(pen) painter.fillPath(selectedPath, onCurveColor) painter.drawPath(path) painter.restore() # coordinates if drawCoordinates: otherColor = QColor(otherColor) otherColor.setAlphaF(otherColor.alphaF() * .6) painter.save() painter.setPen(otherColor) for x, y in points: posX = x # TODO: We use + here because we align on top. Consider abstracting # yOffset. posY = y + 3 x = round(x, 1) if int(x) == x: x = int(x) y = round(y, 1) if int(y) == y: y = int(y) text = "%d %d" % (x, y) drawTextAtPoint(painter, text, posX, posY, scale, xAlign="center", yAlign="top") painter.restore()
def drawGlyphPoints( painter, glyph, scale, drawStartPoints=True, drawOnCurves=True, drawOffCurves=True, drawCoordinates=False, drawBluesMarkers=True, onCurveColor=None, onCurveSmoothColor=None, offCurveColor=None, otherColor=None, backgroundColor=None): """ Draws a Glyph_ *glyph*’s points. .. _Glyph: http://ts-defcon.readthedocs.org/en/ufo3/objects/glyph.html """ if onCurveColor is None: onCurveColor = defaultColor("glyphOnCurvePoints") if onCurveSmoothColor is None: onCurveSmoothColor = defaultColor("glyphOnCurveSmoothPoints") if offCurveColor is None: offCurveColor = defaultColor("glyphOffCurvePoints") if otherColor is None: otherColor = defaultColor("glyphOtherPoints") if backgroundColor is None: backgroundColor = defaultColor("background") bluesMarkerColor = defaultColor("glyphBluesMarker") notchColor = defaultColor("glyphContourStroke").lighter(200) # get the outline data outlineData = glyph.getRepresentation("defconQt.OutlineInformation") points = [] # blue zones markers if drawBluesMarkers and drawOnCurves: font = glyph.font blues = [] if font.info.postscriptBlueValues: blues += font.info.postscriptBlueValues if font.info.postscriptOtherBlues: blues += font.info.postscriptOtherBlues if blues: blues_ = set(blues) size = 13 * scale snapSize = 17 * scale painter.save() pen = painter.pen() pen.setColor(QColor(255, 255, 255, 125)) pen.setWidth(0) painter.setPen(pen) for point in outlineData["onCurvePoints"]: x, y = point["point"] # TODO: we could add a non-overlapping interval tree special # cased for borders for yMin, yMax in zip(blues[::2], blues[1::2]): if not (y >= yMin and y <= yMax): continue # if yMin > 0 and y == yMin or yMin <= 0 and y == yMax: if y in blues_: path = lozengePath(x, y, snapSize) else: path = ellipsePath(x, y, size) painter.fillPath(path, bluesMarkerColor) painter.drawPath(path) painter.restore() # handles if drawOffCurves and outlineData["offCurvePoints"]: painter.save() painter.setPen(otherColor) for x1, y1, x2, y2 in outlineData["bezierHandles"]: drawLine(painter, x1, y1, x2, y2) painter.restore() # on curve if drawOnCurves and outlineData["onCurvePoints"]: size = 6.5 * scale smoothSize = 8 * scale startSize = 7 * scale loneStartSize = 12 * scale painter.save() notchPath = QPainterPath() path = QPainterPath() smoothPath = QPainterPath() for point in outlineData["onCurvePoints"]: x, y = point["point"] points.append((x, y)) # notch if "smoothAngle" in point: angle = point["smoothAngle"] t = Identity.rotate(angle) x1, y1 = t.transformPoint((-1.35 * scale, 0)) x2, y2 = -x1, -y1 notchPath.moveTo(x1 + x, y1 + y) notchPath.lineTo(x2 + x, y2 + y) # points if drawStartPoints and "startPointAngle" in point: angle = point["startPointAngle"] if angle is not None: pointPath = trianglePath(x, y, startSize, angle) else: pointPath = ellipsePath(x, y, loneStartSize) elif point["smooth"]: pointPath = ellipsePath(x, y, smoothSize) else: pointPath = rectanglePath(x, y, size) # store the path if point["smooth"]: smoothPath.addPath(pointPath) else: path.addPath(pointPath) # stroke pen = QPen(onCurveColor) pen.setWidthF(1.2 * scale) painter.setPen(pen) painter.drawPath(path) pen.setColor(onCurveSmoothColor) painter.setPen(pen) painter.drawPath(smoothPath) # notch pen.setColor(notchColor) pen.setWidth(0) painter.setPen(pen) painter.drawPath(notchPath) painter.restore() # off curve if drawOffCurves and outlineData["offCurvePoints"]: # points offSize = 4.25 * scale path = QPainterPath() for point in outlineData["offCurvePoints"]: x, y = point["point"] pointPath = ellipsePath(x, y, offSize) path.addPath(pointPath) pen = QPen(offCurveColor) pen.setWidthF(2.5 * scale) painter.save() painter.setPen(pen) painter.drawPath(path) painter.fillPath(path, QBrush(backgroundColor)) painter.restore() # coordinates if drawCoordinates: painter.save() painter.setPen(otherColor) font = painter.font() font.setPointSize(7) painter.setFont(font) for x, y in points: posX = x # TODO: We use + here because we align on top. Consider abstracting # yOffset. posY = y + 6 * scale x = round(x, 1) if int(x) == x: x = int(x) y = round(y, 1) if int(y) == y: y = int(y) text = "%d %d" % (x, y) drawTextAtPoint(painter, text, posX, posY, scale, xAlign="center", yAlign="top") painter.restore()