예제 #1
0
파일: drawing.py 프로젝트: sahwar/trufont
def drawGlyphAnchors(painter,
                     glyph,
                     scale,
                     drawAnchors=True,
                     drawSelection=True,
                     drawText=True,
                     color=None):
    if not glyph.anchors:
        return
    if color is None:
        color = defaultColor("glyphAnchor")
    fallbackColor = color
    anchorSize = 9 * scale
    selectedAnchorSize = 11 * scale
    for anchor in glyph.anchors:
        if anchor.color is not None:
            color = colorToQColor(anchor.color)
        else:
            color = fallbackColor
        x, y = anchor.x, anchor.y
        name = anchor.name
        painter.save()
        if drawAnchors:
            if drawSelection and anchor.selected:
                size = selectedAnchorSize
            else:
                size = anchorSize
            path = lozengePath(x, y, size)
            painter.fillPath(path, color)
        if drawText and name and drawSelection and anchor.selected:
            painter.setPen(color)
            # TODO: we're using + before we shift to top, ideally this should
            # be abstracted w drawTextAtPoint taking a dy parameter that will
            # offset the drawing region from origin regardless of whether we
            # are aligning to top or bottom.
            y += 6 * scale
            drawTextAtPoint(painter,
                            name,
                            x,
                            y,
                            scale,
                            xAlign="center",
                            yAlign="top")
        painter.restore()
예제 #2
0
def drawGlyphAnchors(painter, glyph, scale, rect, drawAnchors=True,
                     drawSelection=True, drawText=True, color=None,
                     selectionColor=None):
    if not glyph.anchors:
        return
    if color is None:
        color = defaultColor("glyphAnchor")
    if selectionColor is None:
        selectionColor = defaultColor("glyphSelection")
    fallbackColor = color
    anchorSize = 6 * scale
    anchorHalfSize = anchorSize / 2
    for anchor in glyph.anchors:
        if anchor.color is not None:
            color = colorToQColor(anchor.color)
        else:
            color = fallbackColor
        x = anchor.x
        y = anchor.y
        name = anchor.name
        painter.save()
        if drawAnchors:
            path = QPainterPath()
            path.addEllipse(x - anchorHalfSize, y - anchorHalfSize,
                            anchorSize, anchorSize)
            painter.fillPath(path, color)
            if drawSelection and anchor.selected:
                pen = QPen(selectionColor)
                pen.setWidthF(5.0 * scale)
                painter.setPen(pen)
                painter.drawPath(path)
        if drawText and name:
            painter.setPen(color)
            # TODO: we're using + before we shift to top, ideally this should
            # be abstracted w drawTextAtPoint taking a dy parameter that will
            # offset the drawing region from origin regardless of whether we
            # are aligning to top or bottom.
            y += 3 * scale
            drawTextAtPoint(painter, name, x, y, scale,
                            xAlign="center", yAlign="top")
        painter.restore()
예제 #3
0
파일: drawing.py 프로젝트: yalvex/trufont
def drawPointText(painter, x, y, scale, ishandle=False):
    color = defaultColor("glyphOtherPoints")
    font = painter.font()
    font.setPointSize(7)
    if ishandle:
        color = color.lighter(135)
    painter.setPen(color)
    painter.setFont(font)

    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")
예제 #4
0
파일: drawing.py 프로젝트: sahwar/trufont
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()
예제 #5
0
파일: drawing.py 프로젝트: sahwar/trufont
def _drawGuidelines(painter,
                    glyph,
                    scale,
                    rect,
                    guidelines,
                    drawLines=True,
                    drawText=True,
                    drawSelection=True,
                    color=None):
    if not (drawLines or drawText):
        return
    xMin, yMin, width, height = rect
    xMax = xMin + width
    yMax = yMin + height
    for line in guidelines:
        color_ = color
        if color_ is None:
            if line.color:
                color_ = colorToQColor(line.color)
            else:
                color_ = defaultColor("glyphGuideline")
        painter.save()
        painter.setPen(color)
        line1 = None
        if None not in (line.x, line.y):
            if line.angle is not None:
                # make an infinite line that intersects *(line.x, line.y)*
                # 1. make horizontal line from *(line.x, line.y)* of length
                # *diagonal*
                diagonal = math.sqrt(width**2 + height**2)
                line1 = QLineF(line.x, line.y, line.x + diagonal, line.y)
                # 2. set the angle
                # defcon guidelines are clockwise
                line1.setAngle(line.angle)
                # 3. reverse the line and set length to 2 * *diagonal*
                line1.setPoints(line1.p2(), line1.p1())
                line1.setLength(2 * diagonal)
            else:
                line1 = QLineF(xMin, line.y, xMax, line.y)
        textX = 0
        textY = 0
        if drawLines:
            if line1 is not None:
                # line
                drawLine(painter, line1.x1(), line1.y1(), line1.x2(),
                         line1.y2())
                # point
                x, y = line.x, line.y
                smoothWidth = 8 * scale
                smoothHalf = smoothWidth / 2.0
                painter.save()
                pointPath = QPainterPath()
                x -= smoothHalf
                y -= smoothHalf
                pointPath.addEllipse(x, y, smoothWidth, smoothWidth)
                pen = QPen(color_)
                pen.setWidthF(1 * scale)
                painter.setPen(pen)
                if drawSelection and line.selected:
                    painter.fillPath(pointPath, color_)
                painter.drawPath(pointPath)
                painter.restore()
            else:
                if line.y is not None:
                    drawLine(painter, xMin, line.y, xMax, line.y)
                elif line.x is not None:
                    drawLine(painter, line.x, yMin, line.x, yMax)
        if drawText and line.name:
            if line1 is not None:
                textX = line.x
                textY = line.y - 6 * scale
                xAlign = "center"
            else:
                if line.y is not None:
                    fontSize = painter.font().pointSize()
                    textX = glyph.width + 6 * scale
                    textY = line.y - (fontSize / 3.5) * scale
                elif line.x is not None:
                    textX = line.x + 6 * scale
                    textY = 0
                xAlign = "left"
            drawTextAtPoint(painter,
                            line.name,
                            textX,
                            textY,
                            scale,
                            xAlign=xAlign)
        painter.restore()
예제 #6
0
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()
예제 #7
0
def _drawGuidelines(painter, glyph, scale, rect, guidelines, drawLines=True,
                    drawText=True, drawSelection=True, color=None):
    if not (drawLines or drawText):
        return
    xMin, yMin, width, height = rect
    xMax = xMin + width
    yMax = yMin + height
    fontSize = painter.font().pointSize()
    for line in guidelines:
        color_ = color
        if color_ is None:
            if line.color:
                color_ = colorToQColor(line.color)
            else:
                color_ = defaultColor("glyphGuideline")
        painter.save()
        painter.setPen(color)
        line1 = None
        if None not in (line.x, line.y):
            if line.angle is not None:
                # make an infinite line that intersects *(line.x, line.y)*
                # 1. make horizontal line from *(line.x, line.y)* of length
                # *diagonal*
                diagonal = math.sqrt(width**2 + height**2)
                line1 = QLineF(line.x, line.y, line.x + diagonal, line.y)
                # 2. set the angle
                # defcon guidelines are clockwise
                line1.setAngle(line.angle)
                # 3. reverse the line and set length to 2 * *diagonal*
                line1.setPoints(line1.p2(), line1.p1())
                line1.setLength(2 * diagonal)
            else:
                line1 = QLineF(xMin, line.y, xMax, line.y)
        textX = 0
        textY = 0
        if drawLines:
            if line1 is not None:
                # line
                drawLine(
                    painter, line1.x1(), line1.y1(), line1.x2(), line1.y2())
                # point
                x, y = line.x, line.y
                smoothWidth = 8 * scale
                smoothHalf = smoothWidth / 2.0
                painter.save()
                pointPath = QPainterPath()
                x -= smoothHalf
                y -= smoothHalf
                pointPath.addEllipse(x, y, smoothWidth, smoothWidth)
                pen = QPen(color_)
                pen.setWidthF(1 * scale)
                painter.setPen(pen)
                if drawSelection and line.selected:
                    painter.fillPath(pointPath, color_)
                painter.drawPath(pointPath)
                painter.restore()
            else:
                if line.y is not None:
                    drawLine(painter, xMin, line.y, xMax, line.y)
                elif line.x is not None:
                    drawLine(painter, line.x, yMin, line.x, yMax)
        if drawText and line.name:
            if line1 is not None:
                textX = line.x
                textY = line.y - 6 * scale
                xAlign = "center"
            else:
                if line.y is not None:
                    textX = glyph.width + 6 * scale
                    textY = line.y - (fontSize / 3.5) * scale
                elif line.x is not None:
                    textX = line.x + 6 * scale
                    textY = 0
                xAlign = "left"
            drawTextAtPoint(
                painter, line.name, textX, textY, scale, xAlign=xAlign)
        painter.restore()