diff options
| author | Adrien Tétar | 2015-05-12 22:32:05 +0200 |
|---|---|---|
| committer | Adrien Tétar | 2015-05-12 22:32:05 +0200 |
| commit | 7b1cc02ccc7039ac15d3193d8e4ea03ecfa77997 (patch) | |
| tree | 7084dcc4403b5a44fe92d34eb3ac23348b36b96b /Lib | |
| parent | e83660ec042e9d6fe0daab5459c19c681639a4a9 (diff) | |
| download | trufont-7b1cc02ccc7039ac15d3193d8e4ea03ecfa77997.tar.bz2 | |
On the right track
Diffstat (limited to 'Lib')
| -rw-r--r-- | Lib/defconQt/fontView.py | 7 | ||||
| -rw-r--r-- | Lib/defconQt/representationFactories/__init__.py | 66 | ||||
| -rw-r--r-- | Lib/defconQt/svgViewer.py | 461 |
3 files changed, 325 insertions, 209 deletions
diff --git a/Lib/defconQt/fontView.py b/Lib/defconQt/fontView.py index a13a60a..12ac0f3 100644 --- a/Lib/defconQt/fontView.py +++ b/Lib/defconQt/fontView.py @@ -238,6 +238,11 @@ class MainWindow(QMainWindow): def newFile(self): # TODO: ask for save before leaving self.font = Font() + self.font.info.upm = 1000 + self.font.info.ascender = 750 + self.font.info.descender = -250 + self.font.info.capHeight = 750 + self.font.info.xHeight = 500 self.setWindowTitle("Untitled.ufo") self.characterWidget.updateFont(self.font) @@ -286,7 +291,7 @@ class MainWindow(QMainWindow): super(MainWindow, self).resizeEvent(event) def fontInfo(self): - # If a window is already opened, bring it to the front, else make another one. + # If a window is already opened, bring it to the front, else spawn one. # TODO: see about calling super from the widget and del'eting the ptr to the widget # otherwise it doesn't get swept? # Else we can just play with visibility instead of respawning, given that the window diff --git a/Lib/defconQt/representationFactories/__init__.py b/Lib/defconQt/representationFactories/__init__.py index c2ea89e..60bd600 100644 --- a/Lib/defconQt/representationFactories/__init__.py +++ b/Lib/defconQt/representationFactories/__init__.py @@ -14,6 +14,7 @@ def QPainterPathFactory(glyph, font): # #from defconQt.representationFactories.glyphviewFactory import NoComponentsQPainterPathFactory, OnlyComponentsQPainterPathFactory, OutlineInformationFactory # +from collections import namedtuple import math from fontTools.pens.basePen import BasePen from fontTools.pens.transformPen import TransformPen @@ -87,10 +88,11 @@ class OutlineInformationPen(AbstractPointPen): def getData(self): data = dict(startPoints=[], onCurvePoints=[], offCurvePoints=[], bezierHandles=[], anchors=[], lastSubpathPoints=[], components=self._rawComponentData) - + CPoint = namedtuple('Point', ['x', 'y', 'contourIndex', 'isSmooth', 'isFirst', 'prevCP', 'nextCP']) + for contour in self._rawPointData: if type(contour) is str: - print("Hill") + print("PING") data["lastSubpathPoints"].append(self.index) self.index += 1 continue @@ -102,31 +104,24 @@ class OutlineInformationPen(AbstractPointPen): else: haveFirst = False for pointIndex, point in enumerate(contour): - if point["segmentType"] is None: - print("OffCurve") - data["offCurvePoints"].append((point, self.index, not haveFirst)) - self.index += 1 - # look for handles - # TODO: calculate this when drawing + if point["segmentType"] is not None: + #data["onCurvePoints"].append((point, self.index, not haveFirst)) + back = contour[pointIndex - 1] forward = contour[(pointIndex + 1) % len(contour)] - if back["segmentType"] in ("curve", "line"): - p1 = back["point"] - p2 = point["point"] - if p1 != p2: - data["bezierHandles"].append((p1, p2)) - elif forward["segmentType"] in ("curve", "line"): - p1 = forward["point"] - p2 = point["point"] - if p1 != p2: - data["bezierHandles"].append((p1, p2)) - else: - data["onCurvePoints"].append((point, self.index, not haveFirst)) - print("OnCurve") - self.index += 1 + prevCP, nextCP = None, None + if back["segmentType"] is None: + prevCP = back["point"] + if forward["segmentType"] is None: + nextCP = forward["point"] + x, y = point["point"] + pt = CPoint(x, y, self.index, point["smooth"], not haveFirst, prevCP, nextCP) + data["onCurvePoints"].append(pt) # catch first point if not haveFirst: + print("PONG") haveFirst = True + ''' nextOn = None for nextPoint in contour[pointIndex:] + contour[:pointIndex]: #if nextPoint["segmentType"] is None: @@ -143,6 +138,33 @@ class OutlineInformationPen(AbstractPointPen): yDiff = y2 - y1 angle = round(math.atan2(yDiff, xDiff) * 180 / math.pi, 3) data["startPoints"].append((point["point"], angle)) + ''' + self.index += 1 + else: + self.index += 1 + + ''' + else: + onCurveParent = self.index+1 + print("OffCurve") + # look for handles + # TODO: calculate this when drawing + back = contour[pointIndex - 1] + forward = contour[(pointIndex + 1) % len(contour)] + if back["segmentType"] in ("curve", "line"): + onCurveParent = self.index-1 + p1 = back["point"] + p2 = point["point"] + if p1 != p2: + data["bezierHandles"].append((p1, p2, self.index, onCurveParent)) + elif forward["segmentType"] in ("curve", "line"): + p1 = forward["point"] + p2 = point["point"] + if p1 != p2: + data["bezierHandles"].append((p1, p2, self.index, onCurveParent)) + data["offCurvePoints"].append((point, self.index, onCurveParent)) + self.index += 1 + ''' return data def beginPath(self): diff --git a/Lib/defconQt/svgViewer.py b/Lib/defconQt/svgViewer.py index c4d7d7f..7ae2393 100644 --- a/Lib/defconQt/svgViewer.py +++ b/Lib/defconQt/svgViewer.py @@ -1,7 +1,8 @@ -from PyQt5.QtCore import QFile, QRectF, QSize, Qt +import math +from PyQt5.QtCore import QFile, QLineF, QObject, QPointF, QRectF, QSize, Qt from PyQt5.QtGui import QBrush, QColor, QImage, QPainter, QPainterPath, QPixmap, QPen from PyQt5.QtWidgets import (QActionGroup, QApplication, QFileDialog, - QGraphicsItem, QGraphicsRectItem, QGraphicsScene, QGraphicsView, + QGraphicsItem, QGraphicsEllipseItem, QGraphicsLineItem, QGraphicsRectItem, QGraphicsScene, QGraphicsView, QMainWindow, QMenu, QMessageBox, QStyle, QStyleOptionGraphicsItem, QWidget) from PyQt5.QtOpenGL import QGL, QGLFormat, QGLWidget from PyQt5.QtSvg import QGraphicsSvgItem @@ -72,38 +73,199 @@ class MainGfxWindow(QMainWindow): self.view.setRenderer(SvgView.Image) # TODO: make QAbstractShapeItem as derive ellipse and rect, or just do path +class OffCurvePointItem(QGraphicsEllipseItem): + def __init__(self, x, y, width, height, pointX, pointY, pen=None, brush=None, parent=None): + super(OffCurvePointItem, self).__init__(x, y, width, height, parent) + # since we have a parent, setPos must be relative to it + self.setPos(pointX, pointY) # TODO: abstract and use pointX-self.parent().pos().x() + self.setFlag(QGraphicsItem.ItemIsMovable) + self.setFlag(QGraphicsItem.ItemIsSelectable) + # TODO: stop doing this and go back to mouse events –> won't permit multiple selection + self.setFlag(QGraphicsItem.ItemSendsGeometryChanges) + if pen is not None: self._pen = pen; self.setPen(pen) + if brush is not None: self.setBrush(brush) + + self._pointX = pointX + self._pointY = pointY + + def itemChange(self, change, value): + if change == QGraphicsItem.ItemPositionHasChanged: + self.parentItem()._CPMoved(value) + return QGraphicsItem.itemChange(self, change, value) + + # http://www.qtfr.org/viewtopic.php?pid=21045#p21045 + def paint(self, painter, option, widget): + newOption = QStyleOptionGraphicsItem(option) + newOption.state = QStyle.State_None + super(OffCurvePointItem, self).paint(painter, newOption, widget) + if (option.state & QStyle.State_Selected): + pen = self.pen() + pen.setColor(Qt.red) + #pen.setWidth + self.setPen(pen) + else: + self.setPen(self._pen) + +class OnCurveSmoothPointItem(QGraphicsEllipseItem): + def __init__(self, x, y, width, height, pointX, pointY, pointIndex, otherPointIndex=None, + startPointObject=None, pen=None, brush=None, parent=None): + super(OnCurveSmoothPointItem, self).__init__(x, y, width, height, parent) + self.setPos(pointX, pointY) + self.setFlag(QGraphicsItem.ItemIsMovable) + self.setFlag(QGraphicsItem.ItemIsSelectable) + self.setFlag(QGraphicsItem.ItemSendsGeometryChanges) + if pen is not None: self._pen = pen; self.setPen(pen) + if brush is not None: self.setBrush(brush) + + self._pointIndex = pointIndex + # For the start point we must handle two instrs: the moveTo which is the initial start + # point of the path and the last lineTo/curveTo which is the closing segment + self._otherPointIndex = otherPointIndex + self._startPointObject = startPointObject + self._isSmooth = True + + + """ + def mouseMoveEvent(self, event): + super(OnCurveSmoothPointItem, self).mouseMoveEvent(event) + path = self.scene()._outlineItem.path() + newX = self._pointX+self.pos().x() + newY = self._pointY+self.pos().y() + path.setElementPositionAt(self._pointIndex, newX, newY) + if self._otherPointIndex is not None: + path.setElementPositionAt(self._otherPointIndex, newX, newY) + # TODO: the angle ought to be recalculated + # maybe make it disappear on move and recalc when releasing + # what does rf do here? + if self._startPointObject is not None: self._startPointObject.setPos(self.pos()) + if self._prevCP is not None: self._prevCP.setPos(self.pos()) + if self._nextCP is not None: self._nextCP.setPos(self.pos()) + self.scene()._outlineItem.setPath(path) + #self.scene().update() + """ + + def _CPMoved(self, newValue): + if not self._isSmooth: return + selected, propagate = None, None + children = self.childItems() + # nodes are at even positions + for index, child in enumerate(children[::2]): # TODO: filter instead? + if child.isSelected(): # eventually use isUnderMouse() is we implement multiple point selection + selected = index * 2 + else: + propagate = index * 2 + if selected is None: return + curValue = children[selected].pos() + line = children[selected+1].line() + children[selected+1].setLine(line.x1(), line.y1(), newValue.x(), newValue.y()) + if propagate is None: return + xDiff = newValue.x() - curValue.x() + yDiff = newValue.y() - curValue.y() + opposedAngle = math.atan2(yDiff, xDiff) + targetLen = children[selected+1].line().length()+children[propagate+1].line().length() + tmpLine = QLineF(newValue, QPointF(0, 0)) + tmpLine.setLength(targetLen) + children[propagate].setFlag(QGraphicsItem.ItemSendsGeometryChanges, False) + children[propagate].setPos(tmpLine.x2(), tmpLine.y2()) + children[propagate].setFlag(QGraphicsItem.ItemSendsGeometryChanges) + children[propagate+1].setLine(line.x1(), line.y1(), tmpLine.x2(), tmpLine.y2()) + + + def itemChange(self, change, value): + if change == QGraphicsItem.ItemPositionHasChanged: + if self.scene() is None: return QGraphicsItem.itemChange(self, change, value) + path = self.scene()._outlineItem.path() + ''' + for i in range(path.elementCount()): + elem = path.elementAt(i) + if elem.isCurveTo(): kind = "curve" + elif elem.isLineTo(): kind = "line" + else: kind = "move" + print("{}: {} {}".format(kind, elem.x, elem.y)) + print() + ''' + # TODO: if we're snapped to int round self.pos to int + path.setElementPositionAt(self._pointIndex, self.pos().x(), self.pos().y()) + if self._otherPointIndex is not None: + path.setElementPositionAt(self._otherPointIndex, self.pos().x(), self.pos().y()) + # TODO: the angle ought to be recalculated + # maybe make it disappear on move and recalc when releasing + # what does rf do here? + if self._startPointObject is not None: self._startPointObject.setPos(self.pos()) + # TODO: handle single-handle points + if len(self.childItems()) > 2: + nextPos = self.childItems()[2].pos() + path.setElementPositionAt(self._pointIndex+1, self.pos().x()+nextPos.x(), self.pos().y()+nextPos.y()) + self.scene()._outlineItem.setPath(path) + return QGraphicsItem.itemChange(self, change, value) + + # http://www.qtfr.org/viewtopic.php?pid=21045#p21045 + def paint(self, painter, option, widget): + newOption = QStyleOptionGraphicsItem(option) + newOption.state = QStyle.State_None + super(OnCurveSmoothPointItem, self).paint(painter, newOption, widget) + if (option.state & QStyle.State_Selected): + pen = self.pen() + pen.setColor(Qt.red) + #pen.setWidth + self.setPen(pen) + else: + self.setPen(self._pen) + class OnCurvePointItem(QGraphicsRectItem): def __init__(self, x, y, width, height, pointX, pointY, pointIndex, otherPointIndex=None, startPointObject=None, pen=None, brush=None, parent=None): super(OnCurvePointItem, self).__init__(x, y, width, height, parent) + self.setPos(pointX, pointY) self.setFlag(QGraphicsItem.ItemIsMovable) self.setFlag(QGraphicsItem.ItemIsSelectable) # TODO: stop doing this and go back to mouse events self.setFlag(QGraphicsItem.ItemSendsGeometryChanges) if pen is not None: self._pen = pen; self.setPen(pen) if brush is not None: self.setBrush(brush) - - self._pointX = pointX - self._pointY = pointY + self._pointIndex = pointIndex # For the start point we must handle two instrs: the moveTo which is the initial start # point of the path and the last lineTo/curveTo which is the closing segment self._otherPointIndex = otherPointIndex self._startPointObject = startPointObject - """ + ''' def mouseMoveEvent(self, event): - pos = event.pos() - print(pos) super(OnCurvePointItem, self).mouseMoveEvent(event) path = self.scene()._outlineItem.path() - path.setElementPositionAt(0, pos.x(), pos.y()) + newX = self._pointX+self.pos().x() + newY = self._pointY+self.pos().y() + path.setElementPositionAt(self._pointIndex, newX, newY) + if self._otherPointIndex is not None: + path.setElementPositionAt(self._otherPointIndex, newX, newY) + # TODO: the angle ought to be recalculated + # maybe make it disappear on move and recalc when releasing + # what does rf do here? + if self._startPointObject is not None: self._startPointObject.setPos(self.pos()) + if self._prevCP is not None: self._prevCP.setPos(self.pos()) + if self._nextCP is not None: self._nextCP.setPos(self.pos()) self.scene()._outlineItem.setPath(path) #self.scene().update() - """ + ''' + def _CPMoved(self, newValue): + #if not self._isSmooth: return + selected, propagate = None, None + children = self.childItems() + # nodes are at even positions + for index, child in enumerate(children[::2]): # TODO: filter instead? + if child.isSelected(): # eventually use isUnderMouse() is we implement multiple point selection + selected = index * 2 + else: + propagate = index * 2 + if selected is None: return + line = children[selected+1].line() + children[selected+1].setLine(line.x1(), line.y1(), newValue.x(), newValue.y()) + def itemChange(self, change, value): if change == QGraphicsItem.ItemPositionHasChanged: + if self.scene() is None: return QGraphicsItem.itemChange(self, change, value) path = self.scene()._outlineItem.path() """ for i in range(path.elementCount()): @@ -115,15 +277,20 @@ class OnCurvePointItem(QGraphicsRectItem): print() """ # TODO: if we're snapped to int round self.pos to int - newX = self._pointX+self.pos().x() - newY = self._pointY+self.pos().y() - path.setElementPositionAt(self._pointIndex, newX, newY) + #newX = self._pointX+self.pos().x() + #newY = self._pointY+self.pos().y() + path.setElementPositionAt(self._pointIndex, self.pos().x(), self.pos().y()) if self._otherPointIndex is not None: - path.setElementPositionAt(self._otherPointIndex, newX, newY) + path.setElementPositionAt(self._otherPointIndex, self.pos().x(), self.pos().y()) # TODO: the angle ought to be recalculated # maybe make it disappear on move and recalc when releasing # what does rf do here? - self._startPointObject.setPos(self.pos()) + if self._startPointObject is not None: self._startPointObject.setPos(self.pos()) + #for child in self.childItems(): + #child._translate(self.pos()) + #newCPX = child._pointX+child.pos().x() + #newCPY = child._pointY+child.pos().y() + #child._handle.setLine(newX, newY, newCPX, newCPY) self.scene()._outlineItem.setPath(path) return QGraphicsItem.itemChange(self, change, value) @@ -180,7 +347,7 @@ class SvgView(QGraphicsView): self.translate(0, self.height()*(1+self._font.info.descender/self._font.info.unitsPerEm)) self.scale(1, -1) self.addBackground() - #self.addBlues() + self.addBlues() self.addOutlines() self.addPoints() @@ -225,171 +392,6 @@ class SvgView(QGraphicsView): self._scale = .01 self._inverseScale = 1.0 / self._scale self._impliedPointSize = self._font.info.unitsPerEm * self._scale - - def drawBackground_(self, painter): - painter.fillRect(QRectF(self.viewport().rect()), self._backgroundColor) - ''' - p.save() - p.resetTransform() - p.drawTiledPixmap(self.viewport().rect(), - self.backgroundBrush().texture()) - p.restore() - ''' - - def drawBlues(self, painter): - width = self.width()# * self._inverseScale - font = self._glyph.getParent() - #painter.setCompositionMode(QPainter.CompositionMode_SourceOver) - if font is None: - return - attrs = ["postscriptBlueValues", "postscriptOtherBlues"] - for attr in attrs: - values = getattr(font.info, attr) - if not values: - continue - yMins = [i for index, i in enumerate(values) if not index % 2] - yMaxs = [i for index, i in enumerate(values) if index % 2] - for yMin, yMax in zip(yMins, yMaxs): - painter.fillRect(0, yMin, width, yMax - yMin, QBrush(self._bluesColor)) - - def drawOutlines(self, painter): - painter.save() - # outlines - path = self._glyph.getRepresentation("defconQt.NoComponentsQPainterPath") - painter.setBrush(QBrush(self._fillColor)) - painter.drawPath(path) - # components - path = self._glyph.getRepresentation("defconQt.OnlyComponentsQPainterPath") - painter.setBrush(QBrush(self._componentFillColor)) - painter.drawPath(path) - painter.restore() - - def drawPoints(self, painter): - # work out appropriate sizes and - # skip if the glyph is too small - pointSize = self._impliedPointSize - if pointSize > 550: - startPointSize = 21 - offCurvePointSize = 5 - onCurvePointSize = 6 - onCurveSmoothPointSize = 7 - elif pointSize > 250: - startPointSize = 15 - offCurvePointSize = 3 - onCurvePointSize = 4 - onCurveSmoothPointSize = 5 - elif pointSize > 175: - startPointSize = 9 - offCurvePointSize = 1 - onCurvePointSize = 2 - onCurveSmoothPointSize = 3 - else: - return - if pointSize > 250: - coordinateSize = 9 - else: - coordinateSize = 0 - # use the data from the outline representation - outlineData = self._glyph.getRepresentation("defconQt.OutlineInformation") - points = [] - # start point - if self._showOnCurvePoints and outlineData["startPoints"]: - startWidth = startHeight = self.roundPosition(startPointSize)# * self._inverseScale) - 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, 2*startHalf, 2*startHalf, angle-90, -180) - path.closeSubpath() - else: - path.addEllipse(x-startHalf, y-startHalf, startWidth, startHeight) - painter.save() - painter.setBrush(QBrush(self._startPointColor)) - painter.drawPath(path) - painter.restore() - # off curve - if self._showOffCurvePoints and outlineData["offCurvePoints"]: - # lines - path = QPainterPath() - for point1, point2 in outlineData["bezierHandles"]: - path.moveTo(*point1) - path.lineTo(*point2) - painter.save() - painter.setPen(QPen(self._bezierHandleColor, 1.0)) - painter.drawPath(path) - painter.restore() - # points - offWidth = offHeight = self.roundPosition(offCurvePointSize)# * self._inverseScale) - offHalf = offWidth / 2.0 - path = QPainterPath() - for point in outlineData["offCurvePoints"]: - x, y = point["point"] - points.append((x, y)) - x = self.roundPosition(x - offHalf) - y = self.roundPosition(y - offHalf) - path.addEllipse(x, y, offWidth, offHeight) - if self._drawStroke: - painter.save() - painter.setPen(QPen(self._pointStrokeColor, 3.0)) - painter.drawPath(path) - painter.restore() - painter.save() - painter.setBrush(QBrush(self._backgroundColor)) - painter.drawPath(path) - painter.restore() - painter.save() - painter.setPen(QPen(self._offCurvePointColor, 1.0)) - painter.drawPath(path) - painter.restore() - # on curve - if self._showOnCurvePoints and outlineData["onCurvePoints"]: - width = height = self.roundPosition(onCurvePointSize)# * self._inverseScale) - half = width / 2.0 - smoothWidth = smoothHeight = self.roundPosition(onCurveSmoothPointSize)# * self._inverseScale) - smoothHalf = smoothWidth / 2.0 - path = QPainterPath() - for point in outlineData["onCurvePoints"]: - x, y = point["point"] - points.append((x, y)) - if point["smooth"]: - x = self.roundPosition(x - smoothHalf) - y = self.roundPosition(y - smoothHalf) - path.addEllipse(x, y, smoothWidth, smoothHeight) - else: - x = self.roundPosition(x - half) - y = self.roundPosition(y - half) - path.addRect(x, y, width, height) - if self._drawStroke: - painter.save() - painter.setPen(QPen(self._pointStrokeColor, 3.0)) - painter.drawPath(path) - painter.restore() - painter.save() - painter.setBrush(QBrush(self._onCurvePointColor)) - painter.drawPath(path) - painter.restore() - # text - """ - if self._showPointCoordinates and coordinateSize: - fontSize = 9 * self._inverseScale - attributes = { - NSFontAttributeName : NSFont.systemFontOfSize_(fontSize), - NSForegroundColorAttributeName : self._pointCoordinateColor - } - for x, y in points: - posX = x - posY = y - 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) - self._drawTextAtPoint(text, attributes, (posX, posY), 3) - """ def addBackground(self): s = self.scene() @@ -451,6 +453,61 @@ class SvgView(QGraphicsView): outlineData = self._glyph.getRepresentation("defconQt.OutlineInformation") points = [] # TODO: remove this unless we need it # useful for text drawing, add it startObjects = [] + offWidth = offHeight = self.roundPosition(offCurvePointSize)# * self._inverseScale) + offHalf = offWidth / 2.0 + width = height = self.roundPosition(onCurvePointSize)# * self._inverseScale) + half = width / 2.0 + smoothWidth = smoothHeight = self.roundPosition(onCurveSmoothPointSize)# * self._inverseScale) + smoothHalf = smoothWidth / 2.0 + if outlineData["onCurvePoints"]: + spIndex = 0 + for onCurve in outlineData["onCurvePoints"]: + # on curve + x, y = onCurve.x, onCurve.y + points.append((x, y)) + lastPointInSubpath = None + startObject = None + item = None + if onCurve.isFirst: + lastPointInSubpath = outlineData["lastSubpathPoints"][spIndex] + spIndex += 1 + #startObject = startObjects.pop(0) + + if onCurve.isSmooth: + rx = self.roundPosition(x - smoothHalf) + ry = self.roundPosition(y - smoothHalf) + item = OnCurveSmoothPointItem(-smoothHalf, -smoothHalf, smoothWidth, smoothHeight, x, y, + onCurve.contourIndex, lastPointInSubpath, startObject, + QPen(self._pointStrokeColor, 1.5), QBrush(self._onCurvePointColor)) + s.addItem(item) + else: + rx = self.roundPosition(x - half) + ry = self.roundPosition(y - half) + item = OnCurvePointItem(-half, -half, width, height, x, y, onCurve.contourIndex, + lastPointInSubpath, startObject, + QPen(self._pointStrokeColor, 1.5), QBrush(self._onCurvePointColor)) + s.addItem(item) + # off curve + for CP in [onCurve.prevCP, onCurve.nextCP]: + if CP: + cx, cy = CP + # line + #lineObj = None + #if x != onCurve.x or y != onCurve.y: + # point + points.append((cx, cy)) + rx = self.roundPosition(cx - offHalf) + ry = self.roundPosition(cy - offHalf) + CPObject = OffCurvePointItem(-offHalf, -offHalf, offWidth, offHeight, cx-x, cy-y, + QPen(self._offCurvePointColor, 1.0), QBrush(self._backgroundColor), item) + lineObj = QGraphicsLineItem(0, 0, cx - x, cy - y, item) + lineObj.setPen(QPen(self._bezierHandleColor, 1.0)) + #s.addItem(CPObject) + #s.addEllipse(x, y, offWidth, offHeight, + # QPen(self._offCurvePointColor, 1.0), QBrush(self._backgroundColor)) + + + ''' # start point if self._showOnCurvePoints and outlineData["startPoints"]: startWidth = startHeight = self.roundPosition(startPointSize)# * self._inverseScale) @@ -471,23 +528,27 @@ class SvgView(QGraphicsView): startObjects.append(item) #s.addPath(path, QPen(Qt.NoPen), brush=QBrush(self._startPointColor)) # off curve + from collections import defaultdict + offCurveIndex = defaultdict(lambda: defaultdict(dict)) if self._showOffCurvePoints and outlineData["offCurvePoints"]: # lines - for point1, point2 in outlineData["bezierHandles"]: + for point1, point2, index, onCurveParentIndex in outlineData["bezierHandles"]: path = QPainterPath() path.moveTo(*point1) path.lineTo(*point2) - s.addPath(path, QPen(self._bezierHandleColor, 1.0)) + prevOrNext = index < onCurveParentIndex + offCurveIndex[onCurveParentIndex][prevOrNext]["bez"] = s.addPath(path, QPen(self._bezierHandleColor, 1.0)) # points offWidth = offHeight = self.roundPosition(offCurvePointSize)# * self._inverseScale) offHalf = offWidth / 2.0 #path = QPainterPath() - for point, index, isFirst in outlineData["offCurvePoints"]: + for point, index, onCurveParentIndex in outlineData["offCurvePoints"]: x, y = point["point"] points.append((x, y)) x = self.roundPosition(x - offHalf) y = self.roundPosition(y - offHalf) - item = s.addEllipse(x, y, offWidth, offHeight, + prevOrNext = index < onCurveParentIndex + offCurveIndex[onCurveParentIndex][prevOrNext]["off"] = s.addEllipse(x, y, offWidth, offHeight, QPen(self._offCurvePointColor, 1.0), QBrush(self._backgroundColor)) item.setFlag(QGraphicsItem.ItemIsMovable) #if self._drawStroke: @@ -524,8 +585,17 @@ class SvgView(QGraphicsView): break startObject = startObjects.pop(0) + try: prevBez = offCurveIndex[index][True]["bez"] + except KeyError: prevBez = None + try: prevCP = offCurveIndex[index][True]["off"] + except KeyError: prevCP = None + try: nextBez = offCurveIndex[index][False]["bez"] + except KeyError: nextBez = None + try: nextCP = offCurveIndex[index][False]["off"] + except KeyError: nextCP = None item = OnCurvePointItem(rx, ry, width, height, x, y, index, lastPointInSubpath, - startObject, QPen(self._pointStrokeColor, 1.5), QBrush(self._onCurvePointColor)) + startObject, prevBez, prevCP, nextBez, nextCP, + QPen(self._pointStrokeColor, 1.5), QBrush(self._onCurvePointColor)) s.addItem(item) #item = s.addRect(x, y, width, height, # QPen(self._pointStrokeColor, 1.5), QBrush(self._onCurvePointColor)) @@ -536,6 +606,25 @@ class SvgView(QGraphicsView): #myRect = s.addPath(path, QPen(Qt.NoPen), brush=) #myRect.setFlag(QGraphicsItem.ItemIsSelectable) #myRect.setFlag(QGraphicsItem.ItemIsMovable + # text + if self._showPointCoordinates and coordinateSize: + fontSize = 9 * self._inverseScale + attributes = { + NSFontAttributeName : NSFont.systemFontOfSize_(fontSize), + NSForegroundColorAttributeName : self._pointCoordinateColor + } + for x, y in points: + posX = x + posY = y + 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) + self._drawTextAtPoint(text, attributes, (posX, posY), 3) + ''' def roundPosition(self, value): value = value * self._scale |
