diff options
| author | Adrien Tétar | 2015-09-17 21:48:34 +0200 |
|---|---|---|
| committer | Adrien Tétar | 2015-09-18 15:24:15 +0200 |
| commit | 748bb567eef19dcd8e067934786950c5866dc580 (patch) | |
| tree | e49d296009472b902bf18d265dfebac103d4ac56 /Lib | |
| parent | 35dd3057c86e02a0c07f7fed20771b3e9d43eb9c (diff) | |
| download | trufont-748bb567eef19dcd8e067934786950c5866dc580.tar.bz2 | |
meta: cleanup past experiments and set up a proper package structure
Diffstat (limited to 'Lib')
| -rw-r--r-- | Lib/defconQt/__init__.py | 2 | ||||
| -rw-r--r-- | Lib/defconQt/__main__.py | 26 | ||||
| -rw-r--r-- | Lib/defconQt/controls/__init__.py | 0 | ||||
| -rw-r--r-- | Lib/defconQt/controls/glyphCellView_ex.py | 158 | ||||
| -rw-r--r-- | Lib/defconQt/fontView.py | 34 | ||||
| -rw-r--r-- | Lib/defconQt/glyphView.py | 6 | ||||
| -rw-r--r-- | Lib/defconQt/groupsView.py | 2 | ||||
| -rw-r--r-- | Lib/defconQt/representationFactories/__init__.py | 234 | ||||
| -rw-r--r-- | Lib/defconQt/representationFactories/glyphCellFactory.py | 270 | ||||
| -rw-r--r-- | Lib/defconQt/representationFactories/glyphViewFactory.py | 187 | ||||
| -rw-r--r-- | Lib/defconQt/representationFactories/qPainterPathFactory.py | 14 | ||||
| -rw-r--r-- | Lib/defconQt/spaceCenter.py | 6 | ||||
| -rw-r--r-- | Lib/defconQt/windows/__init__.py | 0 | ||||
| -rw-r--r-- | Lib/defconQt/windows/baseWindow.py | 101 | ||||
| -rw-r--r-- | Lib/defconQt/windows/progressWindow.py | 50 |
15 files changed, 249 insertions, 841 deletions
diff --git a/Lib/defconQt/__init__.py b/Lib/defconQt/__init__.py index c128876..5f15410 100644 --- a/Lib/defconQt/__init__.py +++ b/Lib/defconQt/__init__.py @@ -1 +1 @@ -version = "0.1"
\ No newline at end of file +version = "0.1" diff --git a/Lib/defconQt/__main__.py b/Lib/defconQt/__main__.py new file mode 100644 index 0000000..babcc73 --- /dev/null +++ b/Lib/defconQt/__main__.py @@ -0,0 +1,26 @@ +from defcon import Font +from defconQt.fontView import MainWindow +import sys + +from PyQt5.QtGui import QIcon +from PyQt5.QtWidgets import QApplication + +if len(sys.argv) < 2: + ufoFile = "C:\\CharterNova-Regular.ufo" +# print('Usage: %s INPUTFILE' % sys.argv[0]) +# sys.exit(1) +else: + ufoFile = sys.argv[1] + +#from pycallgraph import PyCallGraph +#from pycallgraph.output import GraphvizOutput +from defconQt import representationFactories +representationFactories.registerAllFactories() +#with PyCallGraph(output=GraphvizOutput()): +app = QApplication(sys.argv) +# TODO: http://stackoverflow.com/a/21330349/2037879 +app.setWindowIcon(QIcon("resources/icon.png")) +window = MainWindow(Font(ufoFile)) +window.resize(605, 430) +window.show() +sys.exit(app.exec_()) diff --git a/Lib/defconQt/controls/__init__.py b/Lib/defconQt/controls/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/Lib/defconQt/controls/__init__.py +++ /dev/null diff --git a/Lib/defconQt/controls/glyphCellView_ex.py b/Lib/defconQt/controls/glyphCellView_ex.py deleted file mode 100644 index 214da43..0000000 --- a/Lib/defconQt/controls/glyphCellView_ex.py +++ /dev/null @@ -1,158 +0,0 @@ -from PyQt5.QtCore import QPointF, QSize, Qt -from PyQt5.QtGui import QBrush, QFont, QFontMetrics, QPainter, QPainterPath -from PyQt5.QtWidgets import QApplication, QComboBox, QGridLayout, QWidget - -class RenderArea(QWidget): - def __init__(self, cellWidth, cellHeight, parent=None): - super(RenderArea, self).__init__(parent) - - self.width_ = cellWidth - self.height_ = cellHeight -# newFont = self.font() -# newFont.setPixelSize(12) -# self.setFont(newFont) - -# fontMetrics = QFontMetrics(newFont) -# self.xBoundingRect = fontMetrics.boundingRect("x") -# self.yBoundingRect = fontMetrics.boundingRect("y") - self.shape = QPainterPath() -# self.operations = [] - - def setShape(self, shape): - self.shape = shape - self.update() - - def minimumSizeHint(self): - return QSize(100, 100) - - def sizeHint(self): - return QSize(self.width_, self.height_) - - # Draw a QPainterPath stored in `self.shape`. - def oldPaint(self, event): - painter = QPainter(self) - painter.setRenderHint(QPainter.Antialiasing) - - # Be cartesian - painter.translate(event.rect().bottomLeft()) - painter.scale(1.0, -1.0) - - painter.fillRect(event.rect(), QBrush(Qt.white)) - - painter.save() - self.drawShape(painter) - painter.restore() - - #self.drawOutline(painter) - #self.drawCoordinates(painter) - - def newPaint(self, event): - _, _, width, height = event.rect().getRect() - painter = glyph.getRepresentation("defconQt.QPainterPath", width=width, height=height) - - def paintEvent(self, event): - #oldPaint(self, event) - pass - - def drawCoordinates(self, painter): - #raise NotImplementedError - painter.setPen(Qt.red) - - painter.drawLine(0, 0, 50, 0) - painter.drawLine(48, -2, 50, 0) - painter.drawLine(48, 2, 50, 0) - #painter.drawText(60 - self.xBoundingRect.width() / 2, - # 0 + self.xBoundingRect.height() / 2, "x") - - painter.drawLine(0, 0, 0, 50) - painter.drawLine(-2, 48, 0, 50) - painter.drawLine(2, 48, 0, 50) - #painter.drawText(0 - self.yBoundingRect.width() / 2, - # 60 + self.yBoundingRect.height() / 2, "y") - - ''' - Debug method – paints a single glyph. drawGlyphCell() is the path forward. - ''' - def drawGlyph(self, font, glyphId): #, width, height - #glyph = font[glyphId] - - # TODO: need to write the cell repr - #rep = glyph.getRepresentation("defconQt.QPainterPath", width=width, height=height) - '''#TODO: adapt glyph size to window size - if not rep.isEmpty(): - glyphWidth = glyph.width - ''' - #self.setShape(rep) - self.glyph_ = font[glyphId] - self.update() - - def drawGlyphCell(self, glyph, font): - rep = font[glyph].getRepresentation("defconQt.GlyphCell", width=self.width_, height=self.height_) - self.setShape(rep) - #GlyphCellFactory(glyph, font, self.width_, self.height_) - - #def drawOutline(self, painter): - # painter.setPen(Qt.darkGreen) - # painter.setPen(Qt.DashLine) - # painter.setBrush(Qt.NoBrush) - # painter.drawRect(0, 0, 100, 100) - - def drawShape(self, painter): - #painter.drawPath(self.shape) - painter.fillPath(self.shape, Qt.blue) - - -class Window(QWidget): - - def __init__(self, glyphs=[]): - super(Window, self).__init__() - - self._glyphs = glyphs - self._cellWidth = 200 - self._cellHeight = 200 - self._cnt = 4 # till it shows the whole font - self.setWindowTitle("Font View") - - self.layoutConstruction(self._cnt) - - - #self.preloadGlyphCellImages() - - def layoutConstruction(self, cnt): - layout = QGridLayout() - #layout.setHorizontalSpacing(0) - #layout.setVerticalSpacing(0) - - self.glyphsGrid = list(range(cnt)) - for i in range(cnt): - self.glyphsGrid[i] = RenderArea(self._cellWidth, self._cellHeight) - layout.addWidget(self.glyphsGrid[i], 0, i) - self.setLayout(layout) - - ''' - def preloadGlyphCellImages(self): - representationName = self._cellRepresentationName - representationArguments = self._cellRepresentationArguments - cellWidth = self._cellWidth - cellHeight = self._cellHeight - for glyph in self._glyphs: - glyph.getRepresentation(representationName, width=cellWidth, height=cellHeight, **representationArguments) - self.setLayout(layout) - ''' - - def setGlyphs_(self, glyphs): - self._glyphs = glyphs - # self.glyphsGrid.setGlyphs(glyphs) - - - ''' - Debug method. - ''' - def setGlyph(self, font, glyphId): - self.glyphsGrid[0].drawGlyph(font, glyphId, self._cellWidth, self._cellHeight) - - def shapeSelected(self, index): - shape = self.shapes[index] - self.glyphsGrid.setShape(shape) - for i in range(Window.NumTransformedAreas): - self.transformedRenderAreas[i].setShape(shape) diff --git a/Lib/defconQt/fontView.py b/Lib/defconQt/fontView.py index 733c172..cf08fe9 100644 --- a/Lib/defconQt/fontView.py +++ b/Lib/defconQt/fontView.py @@ -1,9 +1,14 @@ import math import os -import representationFactories import unicodedata from defcon import Font +from defconQt.featureTextEditor import MainEditWindow +from defconQt.fontInfo import TabDialog +from defconQt.glyphView import MainGfxWindow +from defconQt.groupsView import GroupsWindow +from defconQt.spaceCenter import MainSpaceWindow +# TODO: remove globs when things start to stabilize from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * @@ -618,7 +623,6 @@ class MainWindow(QMainWindow): self.setWindowModified(True) def _glyphOpened(self, name): - from glyphView import MainGfxWindow glyphViewWindow = MainGfxWindow(self.font, self.font[name], self) glyphViewWindow.show() @@ -651,7 +655,6 @@ class MainWindow(QMainWindow): # TODO: see about using widget.setAttribute(Qt.WA_DeleteOnClose) otherwise # it seems we're just leaking memory after each close... (both raise_ and # show allocate memory instead of using the hidden widget it seems) - from fontInfo import TabDialog if not (hasattr(self, 'fontInfoWindow') and self.fontInfoWindow.isVisible()): self.fontInfoWindow = TabDialog(self.font, self) self.fontInfoWindow.show() @@ -662,7 +665,6 @@ class MainWindow(QMainWindow): def fontFeatures(self): # TODO: see up here - from featureTextEditor import MainEditWindow if not (hasattr(self, 'fontFeaturesWindow') and self.fontFeaturesWindow.isVisible()): self.fontFeaturesWindow = MainEditWindow(self.font, self) self.fontFeaturesWindow.show() @@ -672,7 +674,6 @@ class MainWindow(QMainWindow): def spaceCenter(self): # TODO: see up here # TODO: show selection in a space center, rewind selection if we raise window (rf) - from spaceCenter import MainSpaceWindow if not (hasattr(self, 'spaceCenterWindow') and self.spaceCenterWindow.isVisible()): self.spaceCenterWindow = MainSpaceWindow(self.font, parent=self) self.spaceCenterWindow.show() @@ -686,7 +687,6 @@ class MainWindow(QMainWindow): def fontGroups(self): # TODO: see up here - from groupsView import GroupsWindow if not (hasattr(self, 'fontGroupsWindow') and self.fontGroupsWindow.isVisible()): self.fontGroupsWindow = GroupsWindow(self.font, self) self.fontGroupsWindow.show() @@ -708,25 +708,3 @@ class MainWindow(QMainWindow): "ecosystem to all main operating systems, in a fast and dependency-free " \ "package.</p>") -if __name__ == '__main__': - import sys - - if len(sys.argv) < 2: - ufoFile = "C:\\CharterNova-Regular.ufo" -# print('Usage: %s INPUTFILE' % sys.argv[0]) -# sys.exit(1) - else: - ufoFile = sys.argv[1] - - #from pycallgraph import PyCallGraph - #from pycallgraph.output import GraphvizOutput - - representationFactories.registerAllFactories() - #with PyCallGraph(output=GraphvizOutput()): - app = QApplication(sys.argv) - # TODO: http://stackoverflow.com/a/21330349/2037879 - app.setWindowIcon(QIcon("resources/icon.png")) - window = MainWindow(Font(ufoFile)) - window.resize(605, 430) - window.show() - sys.exit(app.exec_()) diff --git a/Lib/defconQt/glyphView.py b/Lib/defconQt/glyphView.py index ce3ef2f..8212a66 100644 --- a/Lib/defconQt/glyphView.py +++ b/Lib/defconQt/glyphView.py @@ -1,5 +1,8 @@ from enum import Enum from math import copysign +from defcon.objects.contour import Contour +from defcon.objects.point import Point +from fontTools.misc import bezierTools from PyQt5.QtCore import *#QFile, QLineF, QObject, QPointF, QRectF, QSize, Qt from PyQt5.QtGui import *#QBrush, QColor, QImage, QKeySequence, QPainter, QPainterPath, QPixmap, QPen from PyQt5.QtWidgets import *#(QAction, QActionGroup, QApplication, QFileDialog, @@ -797,7 +800,6 @@ class GlyphScene(QGraphicsScene): lastContour.dirty = True self._editing = True elif not (touched and isinstance(touched, OnCurvePointItem)): - from defcon.objects.contour import Contour nextC = Contour() self._glyphObject.appendContour(nextC) nextC.addPoint((x,y), "move") @@ -840,7 +842,6 @@ class GlyphScene(QGraphicsScene): self.sendEvent(nextCP, QEvent(QEvent.MouseButtonPress)) nextCP.grabMouse() else: - from defcon.objects.point import Point # release current onCurve, delete from contour self.sendEvent(sel[0], QEvent(QEvent.MouseButtonRelease)) mouseGrabberItem.ungrabMouse() @@ -1014,7 +1015,6 @@ class GlyphScene(QGraphicsScene): parameters. """ def computeIntersections(self, p1, p2, p3, p4, x1, y1, x2, y2): - from fontTools.misc import bezierTools bx, by = x1 - x2, y2 - y1 m = x1*(y1-y2) + y1*(x2-x1) a, b, c, d = bezierTools.calcCubicParameters((p1.x, p1.y), (p2.x, p2.y), diff --git a/Lib/defconQt/groupsView.py b/Lib/defconQt/groupsView.py index 02154dd..bec64dc 100644 --- a/Lib/defconQt/groupsView.py +++ b/Lib/defconQt/groupsView.py @@ -1,4 +1,4 @@ -from fontView import CharacterWidget +from defconQt.fontView import CharacterWidget from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * diff --git a/Lib/defconQt/representationFactories/__init__.py b/Lib/defconQt/representationFactories/__init__.py index 74f5973..657b2c2 100644 --- a/Lib/defconQt/representationFactories/__init__.py +++ b/Lib/defconQt/representationFactories/__init__.py @@ -1,220 +1,14 @@ -from defcon.objects.glyph import addRepresentationFactory -# -#from defconQt.representationFactories.qPainterPathFactory import QPainterPathFactory -# -from fontTools.pens.qtPen import QtPen -from PyQt5.QtCore import Qt - -def QPainterPathFactory(glyph, font): - pen = QtPen(font) - glyph.draw(pen) - pen.path.setFillRule(Qt.WindingFill) - return pen.path - -#from defconQt.representationFactories.glyphCellFactory import GlyphCellFactory - -# -#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 -from fontTools.pens.qtPen import QtPen -from PyQt5.QtCore import Qt -from robofab.pens.pointPen import AbstractPointPen - - -# ------------- -# no components -# ------------- - -def NoComponentsQPainterPathFactory(glyph, font): - pen = NoComponentsQtPen(font) - glyph.draw(pen) - pen.path.setFillRule(Qt.WindingFill) - return pen.path - -class NoComponentsQtPen(QtPen): - def addComponent(self, glyphName, transformation): - pass - - -# --------------- -# only components -# --------------- - -def OnlyComponentsQPainterPathFactory(glyph, font): - pen = OnlyComponentsQtPen(font) - glyph.draw(pen) - pen.path.setFillRule(Qt.WindingFill) - return pen.path - -class OnlyComponentsQtPen(BasePen): - - def __init__(self, glyphSet): - BasePen.__init__(self, glyphSet) - self.pen = QtPen(glyphSet) - self.path = self.pen.path - - def _moveTo(self, p): - pass - - def _lineTo(self, p): - pass - - def _curveToOne(self, p1, p2, p3): - pass - - def _closePath(self): - pass - - def addComponent(self, glyphName, transformation): - try: - glyph = self.glyphSet[glyphName] - except KeyError: - return - else: - tPen = TransformPen(self.pen, transformation) - glyph.draw(tPen) - - -# ---------- -# point data -# ---------- - -class OutlineInformationPen(AbstractPointPen): - - def __init__(self): - self._rawPointData = [] - self._rawComponentData = [] - self._bezierHandleData = [] - self.cIndex = 0 - self.index = 0 - - def getData(self): - data = dict(startPoints=[], onCurvePoints=[], offCurvePoints=[], bezierHandles=[], anchors=[], components=self._rawComponentData) - CPoint = namedtuple('Point', ['x', 'y', 'contourIndex', 'pointIndex', 'isSmooth', 'isFirst', 'prevCP', 'nextCP']) - - for contour in self._rawPointData: - # anchor - if len(contour) == 1 and contour[0]["name"] is not None: - anchor = contour[0] - data["anchors"].append(anchor) - # points - else: - haveFirst = False - for pointIndex, point in enumerate(contour): - back = contour[pointIndex - 1] - forward = contour[(pointIndex + 1) % len(contour)] - if point["segmentType"] is not None: - prevCP, nextCP = None, None - if back["segmentType"] is None: - # if we have an open contour with a trailing offCurve, don't signal it to the - # first point - if not (not haveFirst and contour[pointIndex-2]["segmentType"] is not None): - prevCP = back["point"] - if forward["segmentType"] is None: - nextCP = forward["point"] - x, y = point["point"] - pt = CPoint(x, y, self.cIndex, self.index, point["smooth"], not haveFirst, prevCP, nextCP) - data["onCurvePoints"].append(pt) - # catch first point - if not haveFirst: - haveFirst = True - ''' - nextOn = None - for nextPoint in contour[pointIndex:] + contour[:pointIndex]: - #if nextPoint["segmentType"] is None: - # continue - if nextPoint["point"] == point["point"]: - continue - nextOn = nextPoint - break - angle = None - if nextOn: - x1, y1 = point["point"] - x2, y2 = nextOn["point"] - xDiff = x2 - x1 - yDiff = y2 - y1 - angle = round(math.atan2(yDiff, xDiff) * 180 / math.pi, 3) - data["startPoints"].append((point["point"], angle)) - ''' - self.index += 1 - else: - ''' - if back["segmentType"] is not None: - onCurveNeighbor = back - elif forward["segmentType"] is not None: - onCurveNeighbor = forward - else: - print("Whoops") - continue - # QPainterPath elides no-op moveTo's, so do the same when indexing here - if onCurveNeighbor["point"] == point["point"]: - print("Skipped: {}".format(self.index)) - continue - ''' - 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 - ''' - self.index = 0 - self.cIndex += 1 - return data - - def beginPath(self): - self._rawPointData.append([]) - - def endPath(self): - pass - - def addPoint(self, pt, segmentType=None, smooth=False, name=None, **kwargs): - d = dict(point=pt, segmentType=segmentType, smooth=smooth, name=name) - self._rawPointData[-1].append(d) - - def addComponent(self, baseGlyphName, transformation): - d = dict(baseGlyphName=baseGlyphName, transformation=transformation) - self._rawComponentData.append((baseGlyphName, transformation)) - - -def OutlineInformationFactory(glyph, font): - pen = OutlineInformationPen() - glyph.drawPoints(pen) - return pen.getData() -# -# -# - -_factories = { - "defconQt.QPainterPath" : QPainterPathFactory, - "defconQt.OnlyComponentsQPainterPath" : OnlyComponentsQPainterPathFactory, - "defconQt.NoComponentsQPainterPath" : NoComponentsQPainterPathFactory, - "defconQt.OutlineInformation" : OutlineInformationFactory, - #"defconQt.GlyphCell" : GlyphCellFactory, -} - -def registerAllFactories(): - for name, factory in _factories.items(): - addRepresentationFactory(name, factory)
\ No newline at end of file +from defcon.objects.glyph import addRepresentationFactory
+from defconQt.representationFactories.qPainterPathFactory import QPainterPathFactory
+from defconQt.representationFactories.glyphViewFactory import NoComponentsQPainterPathFactory, OnlyComponentsQPainterPathFactory, OutlineInformationFactory
+
+_factories = {
+ "defconQt.QPainterPath" : QPainterPathFactory,
+ "defconQt.OnlyComponentsQPainterPath" : OnlyComponentsQPainterPathFactory,
+ "defconQt.NoComponentsQPainterPath" : NoComponentsQPainterPathFactory,
+ "defconQt.OutlineInformation" : OutlineInformationFactory,
+}
+
+def registerAllFactories():
+ for name, factory in _factories.items():
+ addRepresentationFactory(name, factory)
diff --git a/Lib/defconQt/representationFactories/glyphCellFactory.py b/Lib/defconQt/representationFactories/glyphCellFactory.py deleted file mode 100644 index e975ae1..0000000 --- a/Lib/defconQt/representationFactories/glyphCellFactory.py +++ /dev/null @@ -1,270 +0,0 @@ -from PyQt5.QtCore import QRect, Qt -from PyQt5.QtGui import QColor, QPainter, QPixmap - -GlyphCellHeaderHeight = 14 -GlyphCellMinHeightForHeader = 40 - -# 1 is white -cellHeaderBaseColor = QColor.fromRgb(153, 153, 153).setAlphaF(.4) -#NSColor.colorWithCalibratedWhite_alpha_(.6, .4) -cellHeaderHighlightColor = QColor.fromRgb(178, 178, 178).setAlphaF(.4) -#NSColor.colorWithCalibratedWhite_alpha_(.7, .4) -cellHeaderSelectionColor = QColor.fromRgbF(.2, .3, .7, .15) -#NSColor.colorWithCalibratedRed_green_blue_alpha_(.2, .3, .7, .15) -cellHeaderLineColor = QColor.fromRgb(0, 0, 0).setAlphaF(.2) -#NSColor.colorWithCalibratedWhite_alpha_(0, .2) -cellHeaderHighlightLineColor = QColor.fromRgb(25, 25, 25).setAlphaF(.5) -#NSColor.colorWithCalibratedWhite_alpha_(1, .5) -cellMetricsLineColor = QColor.fromRgb(0, 0, 0).setAlphaF(.08) -#NSColor.colorWithCalibratedWhite_alpha_(0, .08) -cellMetricsFillColor = QColor.fromRgb(0, 0, 0).setAlphaF(.08) -#NSColor.colorWithCalibratedWhite_alpha_(0, .08) - - - -def GlyphCellFactory(glyph, font, width, height, drawHeader=False, drawMetrics=False): - obj = GlyphCellFactoryDrawingController(glyph=glyph, font=font, width=width, height=height, drawHeader=drawHeader, drawMetrics=drawMetrics) - return obj.getImage() - - -class GlyphCellFactoryDrawingController(object): - - """ - This draws the cell with the layers stacked in this order: - ------------------ - header text - ------------------ - header background - ------------------ - foreground - ------------------ - glyph - ------------------ - vertical metrics - ------------------ - horizontal metrics - ------------------ - background - ------------------ - - Subclasses may override the layer drawing methods to customize - the appearance of cells. - """ - - def __init__(self, glyph, font, width, height, drawHeader=False, drawMetrics=False): - self.glyph = glyph - self.font = font - self.width = width - self.height = height - self.bufferPercent = .2 - self.shouldDrawHeader = drawHeader - self.shouldDrawMetrics = drawMetrics - - self.headerHeight = 0 - if drawHeader: - self.headerHeight = GlyphCellHeaderHeight - availableHeight = (height - self.headerHeight) * (1.0 - (self.bufferPercent * 2)) - self.buffer = height * self.bufferPercent - self.scale = availableHeight / font.info.unitsPerEm - self.xOffset = (width - (glyph.width * self.scale)) / 2 - self.yOffset = abs(font.info.descender * self.scale) + self.buffer - - def getImage(self): - image = QPixmap(self.width, self.height) #NSImage.alloc().initWithSize_((self.width, self.height)) - painter = QPainter(image).setRenderHint(QPainter.Antialiasing) - #image.setFlipped_(True) - #image.lockFocus() - #context = NSGraphicsContext.currentContext() - - # Below is probably wrong… find out about (x,y) orientation and plane translation that might affect this - # Qt is top-left by default while AppKit is bottom-left – Qt translation+scale affects text display - bodyRect = QRect(0, self.headerHeight, self.width, self.height-self.headerHeight) - headerRect = QRect(0, 0, self.width, self.headerHeight) - #bodyRect = ((0, 0), (self.width, self.height-self.headerHeight)) - #headerRect = ((0, -self.height+self.headerHeight), (self.width, self.headerHeight)) - # background - painter.save() - #context.saveGraphicsState() - painter.translate(0, self.height-self.headerHeight) - painter.scale(1.0, -1.0) - #bodyTransform = NSAffineTransform.transform() - #bodyTransform.translateXBy_yBy_(0, self.height-self.headerHeight) - #bodyTransform.scaleXBy_yBy_(1.0, -1.0) - #bodyTransform.concat() - self.drawCellBackground(painter, bodyRect) - painter.restore() - #context.restoreGraphicsState() - # glyph - if self.shouldDrawMetrics: - self.drawCellHorizontalMetrics(painter, bodyRect) - self.drawCellVerticalMetrics(painter, bodyRect) - #context.saveGraphicsState() - painter.save() - # clip against background only - painter.setClipRect(QRect(0, 0, self.width, self.height-self.headerHeight)) - #NSBezierPath.clipRect_() - painter.translate(self.xOffset, self.yOffset) - painter.scale(self.scale, self.scale) - #glyphTransform = NSAffineTransform.transform() - #glyphTransform.translateXBy_yBy_(self.xOffset, self.yOffset) - #glyphTransform.scaleBy_(self.scale) - #glyphTransform.concat() - self.drawCellGlyph(painter) - painter.restore() - #context.restoreGraphicsState() - # foreground - painter.save() - #context.saveGraphicsState() - #bodyTransform.concat() #why this lonely here? - self.drawCellForeground(painter, bodyRect) - painter.restore() - #context.restoreGraphicsState() - # header - if self.shouldDrawHeader: - painter.save() - #context.saveGraphicsState() - painter.translate(0, self.headerHeight) - painter.scale(1.0, -1.0) - #headerTransform = NSAffineTransform.transform() - #headerTransform.translateXBy_yBy_(0, self.headerHeight) - #headerTransform.scaleXBy_yBy_(1.0, -1.0) - #headerTransform.concat() - self.drawCellHeaderBackground(painter, headerRect) - self.drawCellHeaderText(painter, headerRect) - painter.restore() - #context.restoreGraphicsState() - # done - #image.unlockFocus() - - return painter#image - - def drawCellBackground(self, painter, rect): - pass - - def drawCellHorizontalMetrics(self, painter, rect): - (xMin, yMin, width, height) = rect.getRect() - glyph = self.glyph - font = self.font - scale = self.scale - yOffset = self.yOffset - path = QPainterPath() - #path = NSBezierPath.bezierPath() - lines = set((0, font.info.descender, font.info.xHeight, font.info.capHeight, font.info.ascender)) - for y in lines: - y = round((y * scale) + yMin + yOffset) - .5 - path.moveTo(xMin, y) - path.lineTo(xMin + width, y) - #cellMetricsLineColor.set() - stroke = QPainterPathStroker().createStroke(path) - stroke.setWidth(1.0) - - painter.save() - painter.setPen(cellMetricsLineColor) - painter.drawPath(stroke) - painter.restore() - #path.stroke() - - def drawCellVerticalMetrics(self, painter, rect): - (xMin, yMin, width, height) = rect.getRect() - glyph = self.glyph - scale = self.scale - xOffset = self.xOffset - left = round((0 * scale) + xMin + xOffset) - .5 - right = round((glyph.width * scale) + xMin + xOffset) - .5 - - # Does this replicate functionality properly? Need to check that… - painter.fillRect((xMin, yMin, left - xMin, height), cellMetricsFillColor) - painter.fillRect((xMin + right, yMin, width - xMin + right, height), cellMetricsFillColor) - #rects = [ - # ((xMin, yMin), (left - xMin, height)), - # ((xMin + right, yMin), (width - xMin + right, height)) - #] - #cellMetricsFillColor.set() - #NSRectFillListUsingOperation(rects, len(rects), NSCompositeSourceOver) - - def drawCellGlyph(self, painter): - #NSColor.blackColor().set() - painter.fillPath(self.glyph.getRepresentation("defconQt.QPainterPath"), Qt.black) - - def drawCellForeground(self, painter, rect): - pass - - def drawCellHeaderBackground(self, painter, rect): - (xMin, yMin, width, height) = rect.getRect() - # background - gradient = QLinearGradient(rect.topLeft(), rect.bottomLeft()) - gradient.setColorAt(0, cellHeaderHighlightColor) - gradient.setColorAt(1, cellHeaderBaseColor) - painter.save() - painter.rotate(90) - painter.fillRect(rect, gradient) - painter.restore() - #try: - # gradient = NSGradient.alloc().initWithColors_([cellHeaderHighlightColor, cellHeaderBaseColor]) - # gradient.drawInRect_angle_(rect, 90) - #except NameError: - # cellHeaderBaseColor.set() - # NSRectFill(rect) - # left and right line - sizePath = QPainterPath() - sizePath.moveTo(xMin + .5, yMin) - sizePath.lineTo(xMin + .5, yMin + height) - sizePath.moveTo(xMin + width - 1.5, yMin) - sizePath.lineTo(xMin + width - 1.5, yMin + height) - sizeStroke = QPainterPathStroker().createStroke(path) - sizeStroke.setWidth(1.0) - #painter.save() - painter.setPen(cellHeaderHighlightLineColor) - painter.drawPath(sizeStroke) - #painter.restore() - #cellHeaderHighlightLineColor.set() - #sizePath = NSBezierPath.bezierPath() - #sizePath.moveToPoint_((xMin + .5, yMin)) - #sizePath.lineToPoint_((xMin + .5, yMin + height)) - #sizePath.moveToPoint_((xMin + width - 1.5, yMin)) - #sizePath.lineToPoint_((xMin + width - 1.5, yMin + height)) - #sizePath.setLineWidth_(1.0) - #sizePath.stroke() - # bottom line - bottomPath = QPainterPath() - bottomPath.moveTo(xMin, yMin + height - .5) - bottomPath.lineTo(xMin + width, yMin + height - .5) - #cellHeaderLineColor.set() - #bottomPath = NSBezierPath.bezierPath() - #bottomPath.moveToPoint_((xMin, yMin + height - .5)) - #bottomPath.lineToPoint_((xMin + width, yMin + height - .5)) - #bottomPath.setLineWidth_(1.0) - #bottomPath.stroke() - bottomStroke = QPainterPathStroker().createStroke(path) - bottomStroke.setWidth(1.0) - #painter.save() - painter.setPen(cellHeaderLineColor) - painter.drawPath(bottomStroke) - #painter.restore() - - def drawCellHeaderText(self, painter, rect): - textColor = QColor.fromRgbF(.22, .22, .27, 1.0) - #NSColor.colorWithCalibratedRed_green_blue_alpha_(.22, .22, .27, 1.0) - - # TODO: no shadow for now, need to use QGraphicsDropShadowEffect but tricky to impl - #painter.save() - painter.setPen(textColor) - painter.setFont(QFont(QFont.defaultFamily(), 10)) - painter.drawText(rect, Qt.AlignCenter, self.glyph.name); - #painter.restore() - - #paragraph = NSMutableParagraphStyle.alloc().init() - #paragraph.setAlignment_(NSCenterTextAlignment) - #paragraph.setLineBreakMode_(NSLineBreakByTruncatingMiddle) - #shadow = NSShadow.alloc().init() - #shadow.setShadowColor_(NSColor.whiteColor()) - #shadow.setShadowOffset_((0, 1)) - #shadow.setShadowBlurRadius_(1) - #attributes = { - # NSFontAttributeName : NSFont.systemFontOfSize_(10.0), - # NSForegroundColorAttributeName : NSColor.colorWithCalibratedRed_green_blue_alpha_(.22, .22, .27, 1.0), - # NSParagraphStyleAttributeName : paragraph, - # NSShadowAttributeName : shadow - #} - #text = NSAttributedString.alloc().initWithString_attributes_(self.glyph.name, attributes) - #text.drawInRect_(rect) diff --git a/Lib/defconQt/representationFactories/glyphViewFactory.py b/Lib/defconQt/representationFactories/glyphViewFactory.py new file mode 100644 index 0000000..fe5183d --- /dev/null +++ b/Lib/defconQt/representationFactories/glyphViewFactory.py @@ -0,0 +1,187 @@ +from collections import namedtuple
+import math
+from fontTools.pens.basePen import BasePen
+from fontTools.pens.transformPen import TransformPen
+from fontTools.pens.qtPen import QtPen
+from PyQt5.QtCore import Qt
+from robofab.pens.pointPen import AbstractPointPen
+
+
+# -------------
+# no components
+# -------------
+
+def NoComponentsQPainterPathFactory(glyph, font):
+ pen = NoComponentsQtPen(font)
+ glyph.draw(pen)
+ pen.path.setFillRule(Qt.WindingFill)
+ return pen.path
+
+class NoComponentsQtPen(QtPen):
+ def addComponent(self, glyphName, transformation):
+ pass
+
+
+# ---------------
+# only components
+# ---------------
+
+def OnlyComponentsQPainterPathFactory(glyph, font):
+ pen = OnlyComponentsQtPen(font)
+ glyph.draw(pen)
+ pen.path.setFillRule(Qt.WindingFill)
+ return pen.path
+
+class OnlyComponentsQtPen(BasePen):
+
+ def __init__(self, glyphSet):
+ BasePen.__init__(self, glyphSet)
+ self.pen = QtPen(glyphSet)
+ self.path = self.pen.path
+
+ def _moveTo(self, p):
+ pass
+
+ def _lineTo(self, p):
+ pass
+
+ def _curveToOne(self, p1, p2, p3):
+ pass
+
+ def _closePath(self):
+ pass
+
+ def addComponent(self, glyphName, transformation):
+ try:
+ glyph = self.glyphSet[glyphName]
+ except KeyError:
+ return
+ else:
+ tPen = TransformPen(self.pen, transformation)
+ glyph.draw(tPen)
+
+
+# ----------
+# point data
+# ----------
+
+class OutlineInformationPen(AbstractPointPen):
+
+ def __init__(self):
+ self._rawPointData = []
+ self._rawComponentData = []
+ self._bezierHandleData = []
+ self.cIndex = 0
+ self.index = 0
+
+ def getData(self):
+ data = dict(startPoints=[], onCurvePoints=[], offCurvePoints=[], bezierHandles=[], anchors=[], components=self._rawComponentData)
+ CPoint = namedtuple('Point', ['x', 'y', 'contourIndex', 'pointIndex', 'isSmooth', 'isFirst', 'prevCP', 'nextCP'])
+
+ for contour in self._rawPointData:
+ # anchor
+ if len(contour) == 1 and contour[0]["name"] is not None:
+ anchor = contour[0]
+ data["anchors"].append(anchor)
+ # points
+ else:
+ haveFirst = False
+ for pointIndex, point in enumerate(contour):
+ back = contour[pointIndex - 1]
+ forward = contour[(pointIndex + 1) % len(contour)]
+ if point["segmentType"] is not None:
+ prevCP, nextCP = None, None
+ if back["segmentType"] is None:
+ # if we have an open contour with a trailing offCurve, don't signal it to the
+ # first point
+ if not (not haveFirst and contour[pointIndex-2]["segmentType"] is not None):
+ prevCP = back["point"]
+ if forward["segmentType"] is None:
+ nextCP = forward["point"]
+ x, y = point["point"]
+ pt = CPoint(x, y, self.cIndex, self.index, point["smooth"], not haveFirst, prevCP, nextCP)
+ data["onCurvePoints"].append(pt)
+ # catch first point
+ if not haveFirst:
+ haveFirst = True
+ '''
+ nextOn = None
+ for nextPoint in contour[pointIndex:] + contour[:pointIndex]:
+ #if nextPoint["segmentType"] is None:
+ # continue
+ if nextPoint["point"] == point["point"]:
+ continue
+ nextOn = nextPoint
+ break
+ angle = None
+ if nextOn:
+ x1, y1 = point["point"]
+ x2, y2 = nextOn["point"]
+ xDiff = x2 - x1
+ yDiff = y2 - y1
+ angle = round(math.atan2(yDiff, xDiff) * 180 / math.pi, 3)
+ data["startPoints"].append((point["point"], angle))
+ '''
+ self.index += 1
+ else:
+ '''
+ if back["segmentType"] is not None:
+ onCurveNeighbor = back
+ elif forward["segmentType"] is not None:
+ onCurveNeighbor = forward
+ else:
+ print("Whoops")
+ continue
+ # QPainterPath elides no-op moveTo's, so do the same when indexing here
+ if onCurveNeighbor["point"] == point["point"]:
+ print("Skipped: {}".format(self.index))
+ continue
+ '''
+ 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
+ '''
+ self.index = 0
+ self.cIndex += 1
+ return data
+
+ def beginPath(self):
+ self._rawPointData.append([])
+
+ def endPath(self):
+ pass
+
+ def addPoint(self, pt, segmentType=None, smooth=False, name=None, **kwargs):
+ d = dict(point=pt, segmentType=segmentType, smooth=smooth, name=name)
+ self._rawPointData[-1].append(d)
+
+ def addComponent(self, baseGlyphName, transformation):
+ d = dict(baseGlyphName=baseGlyphName, transformation=transformation)
+ self._rawComponentData.append((baseGlyphName, transformation))
+
+
+def OutlineInformationFactory(glyph, font):
+ pen = OutlineInformationPen()
+ glyph.drawPoints(pen)
+ return pen.getData()
diff --git a/Lib/defconQt/representationFactories/qPainterPathFactory.py b/Lib/defconQt/representationFactories/qPainterPathFactory.py index cf28eb5..59bd8f0 100644 --- a/Lib/defconQt/representationFactories/qPainterPathFactory.py +++ b/Lib/defconQt/representationFactories/qPainterPathFactory.py @@ -1,6 +1,8 @@ -from fontTools.pens.qtPen import QtPen - -def QPainterPathFactory(glyph, font): - pen = QtPen(font) - glyph.draw(pen) - return pen.path
\ No newline at end of file +from fontTools.pens.qtPen import QtPen
+from PyQt5.QtCore import Qt
+
+def QPainterPathFactory(glyph, font):
+ pen = QtPen(font)
+ glyph.draw(pen)
+ pen.path.setFillRule(Qt.WindingFill)
+ return pen.path
diff --git a/Lib/defconQt/spaceCenter.py b/Lib/defconQt/spaceCenter.py index 7323f66..d0ba766 100644 --- a/Lib/defconQt/spaceCenter.py +++ b/Lib/defconQt/spaceCenter.py @@ -1,4 +1,6 @@ -from fontView import cellSelectionColor +from defconQt.fontView import cellSelectionColor +from defconQt.glyphView import MainGfxWindow +from getpass import getuser from PyQt5.QtCore import *#QAbstractTableModel, QEvent, QSize, Qt from PyQt5.QtGui import *#(QBrush, QColor, QFont, QIcon, QKeySequence, QLinearGradient, QPainter, #QPainterPath, QPalette, QPen) @@ -14,7 +16,6 @@ class MainSpaceWindow(QWidget): super(MainSpaceWindow, self).__init__(parent, Qt.Window) if string is None: - from getpass import getuser try: string = getuser() except: @@ -69,7 +70,6 @@ class MainSpaceWindow(QWidget): self.table.updateCells() def _glyphOpened(self, glyph): - from glyphView import MainGfxWindow glyphViewWindow = MainGfxWindow(self.font, glyph, self.parent()) glyphViewWindow.show() diff --git a/Lib/defconQt/windows/__init__.py b/Lib/defconQt/windows/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/Lib/defconQt/windows/__init__.py +++ /dev/null diff --git a/Lib/defconQt/windows/baseWindow.py b/Lib/defconQt/windows/baseWindow.py deleted file mode 100644 index 2fc2b13..0000000 --- a/Lib/defconQt/windows/baseWindow.py +++ /dev/null @@ -1,101 +0,0 @@ -from PyQt5.QtCore import QDir -from PyQt5.QtWidgets import (QFileDialog, QMessageBox) - -''' -Base Window is a rather abstract object containing the common methods of -all widgets. -As such, it does not have an init function and is meant to be inherited -by subsequent classes. -''' -class BaseWindowController(object): - - ''' - def setUpBaseWindowBehavior(self): - self.w.bind("close", self.windowCloseCallback) - if isinstance(self.w, vanilla.Sheet): - self.w.bind("became key", self.windowSelectCallback) - self.w.bind("resigned key", self.windowDeselectCallback) - else: - self.w.bind("became main", self.windowSelectCallback) - self.w.bind("resigned main", self.windowDeselectCallback) - - def windowCloseCallback(self, sender): - self.w.unbind("close", self.windowCloseCallback) - if isinstance(self.w, vanilla.Sheet): - self.w.unbind("became key", self.windowSelectCallback) - self.w.unbind("resigned key", self.windowDeselectCallback) - else: - self.w.unbind("became main", self.windowSelectCallback) - self.w.unbind("resigned main", self.windowDeselectCallback) - - def windowSelectCallback(self, sender): - pass - - def windowDeselectCallback(self, sender): - pass - ''' - - def startProgress(self, text="", tickCount=None): - try: - from defconQt.windows.progressWindow import ProgressWindow - except: - from progressWindow import ProgressWindow - return ProgressWindow(text, tickCount, self.w) - - def showMessage(self, messageText, informativeText, callback=None): - QMessageBox.information(self.w.activeWindow(), messageText, informativeText) - #if callback is None: - # return 1 - #vanilla.dialogs.message(parentWindow=self.w.getNSWindow(), messageText=messageText, informativeText=informativeText, resultCallback=callback) - - def showAskYesNo(self, messageText, informativeText, callback=None):# - result = QMessageBox.question(self.w.activeWindow(), messageText, informativeText, QMessageBox.Yes | QMessageBox.No) - #vanilla.dialogs.askYesNo(parentWindow=self.w.getNSWindow(), messageText=messageText, informativeText=informativeText, resultCallback=callback) - if callback is None: - if result == QMessageBox.Yes: - return 1 - else: - return 0 - # return alert._value - - def showGetFolder(self, callback=None):# - directory = QFileDialog.getExistingDirectory(parent=self.w.activeWindow(), directory=QDir.currentPath()) - if callback is None: - return directory - #vanilla.dialogs.getFolder(parentWindow=self.w.getNSWindow(), resultCallback=callback) - - def showGetFile(self, fileTypes, callback, allowsMultipleSelection=False): - # TODO: Mac OS sees UFO as file, make sure that this accepts it eveywhere - # Note: fileTypes must follow QT convention e.g. "All Files (*);;Text Files (*.txt)" - # Note#2: getOpenFileNames may pack in an array while getOpenFileName does not - if allowsMultipleSelection: # why would you do this in a Font Editor? - files = QFileDialog.getOpenFileNames(parent=self.w.activeWindow(), directory=QDir.currentPath(), filter=fileTypes) - else: - files = QFileDialog.getOpenFileName(parent=self.w.activeWindow(), directory=QDir.currentPath(), filter=fileTypes) - #vanilla.dialogs.getFile(fileTypes=fileTypes, allowsMultipleSelection=allowsMultipleSelection, - # parentWindow=self.w.getNSWindow(), resultCallback=callback) - - def showPutFile(self, fileTypes, callback=None, fileName=None, directory=None, accessoryView=None):# - # ! fileTypes - - # basic instance cannot put a default file name, use the base class - #result = QFileDialog.getSaveFileName(parent=self.w, directory=directory, filter=fileTypes) - # https://github.com/qtproject/qt/blob/98530cbc3a0bbb633bab96eebb535d7f92ecb1fa/src/gui/dialogs/qfiledialog.cpp#L1965 - dlg = QFileDialog(parent=self.w.activeWindow(), filter=fileTypes) - dlg.setFileMode(QFileDialog.AnyFile) - dlg.setAcceptMode(QFileDialog.AcceptSave) - if directory: dlg.setDirectory(directory) - if fileName: dlg.selectFile(fileName) - if (dlg.exec_() == QDialog.Accepted): - result = dialog.selectedFiles().value(0) - if callback is None: - return result - ''' - if accessoryView is not None: - w, h = accessoryView._posSize[2:] - accessoryView._nsObject.setFrame_(((0, 0), (w, h))) - accessoryView = accessoryView._nsObject - vanilla.dialogs.putFile(fileTypes=fileTypes, - parentWindow=self.w.getNSWindow(), resultCallback=callback, fileName=fileName, directory=directory, accessoryView=accessoryView) - ''' - diff --git a/Lib/defconQt/windows/progressWindow.py b/Lib/defconQt/windows/progressWindow.py deleted file mode 100644 index d64e5c7..0000000 --- a/Lib/defconQt/windows/progressWindow.py +++ /dev/null @@ -1,50 +0,0 @@ -#import vanilla -try: - from defconQt.windows.baseWindow import BaseWindowController -except: - from baseWindow import BaseWindowController -from PyQt5.QtWidgets import QProgressDialog - -class ProgressWindow(BaseWindowController): - - def __init__(self, text="", maximum=0, parentWindow=None): - self.w = parentWindow - if parentWindow is None: - raise NotImplementedError -# self.w = vanilla.Window((250, 60), closable=False, miniaturizable=False, textured=False) -# else: -# self.w = vanilla.Sheet((250, 60), parentWindow) - # have it uncancelable for now at least - #self.w.progress = QProgressDialog(cancelButtonText="0", parent=parentWindow, labelText=text, maximum=maximum) - self.w.progress = QProgressDialog(parent=parentWindow, labelText=text, maximum=maximum) -# self.w.progress.setWindowModality(Qt::WindowModal) -# self.w.progress = vanilla.ProgressBar((15, 15, -15, 12), maxValue=tickCount, isIndeterminate=isIndeterminate, sizeStyle="small") -# self.w.text = vanilla.TextBox((15, 32, -15, 14), text, sizeStyle="small") -# self.w.progress.start() -# self.w.center() -# self.setUpBaseWindowBehavior() -# self.w.open() - self.w.progress.open() - - def close(self): - self.progress.cancel() -# self.w.close() - - def update(self, text=None): -# self.w.progress.increment() - cur = self.progress.value() - self.progress.setValue(cur+1) - if text is not None: - self.setLabelText(text) -# self.w.text._nsObject.display() - - def setTickCount(self, value=0): -# bar = self.w.progress.getNSProgressIndicator() -# if value is None: -# bar.setIndeterminate_(True) -# self.w.progress.start() -# else: -# bar.setIndeterminate_(False) -# bar.setDoubleValue_(0) -# bar.setMaxValue_(value) - self.progress.setRange(0, value)
\ No newline at end of file |
