示例#1
0
 def show_dist_textbox(self, info):
     window = CurrentGlyphWindow()
     view = window.getGlyphView()
     vanillaView = ShowDistTextBox(view, (20, 22, 120, 22),
                                   "",
                                   alignment="left",
                                   sizeStyle="mini")
     window.addGlyphEditorSubview(vanillaView)
示例#2
0
def getActiveGlyphWindow():
    window = CurrentGlyphWindow()
    # there is no glyph window
    if window is None:
        return None
    # the editor is not the first responder
    if not window.getGlyphView().isFirstResponder():
        return None
    return window
    def drawPoints(self, info):
    
        newPoints = self.getValues(None)
        if newPoints != None:
            glyph = CurrentGlyph()
        
            onCurveSize = getDefault("glyphViewOncurvePointsSize") * 5
            offCurveSize = getDefault("glyphViewOncurvePointsSize") * 3
            fillColor = tuple([i for i in getDefault("glyphViewCurvePointsFill")])
        
            upmScale = (glyph.font.info.unitsPerEm/1000) 
            scale = info["scale"]
            oPtSize = onCurveSize * scale
            fPtSize = offCurveSize * scale

            d.save()

            # thanks Erik!
            textLoc = newPoints[0][3][0] + math.cos(self.returnAngle(newPoints)) * (scale*.25*120) * 2, newPoints[0][3][1] + math.sin(self.returnAngle(newPoints)) * (scale*.25*120) * 2

            for b in newPoints:
                for a in b:
                    if a == newPoints[1][0] or a == newPoints[0][-1]:
                        d.oval(a[0]-oPtSize/2,a[1]-oPtSize/2, oPtSize, oPtSize) 
                    else:
                        d.oval(a[0]-fPtSize/2,a[1]-fPtSize/2, fPtSize, fPtSize) 
                    d.fill(fillColor[0],fillColor[1],fillColor[2],fillColor[3])
        
            d.stroke(fillColor[0],fillColor[1],fillColor[2],fillColor[3])
            d.strokeWidth(scale)
            d.line(newPoints[0][2],newPoints[1][1])
            d.restore()

            # https://robofont.com/documentation/building-tools/toolspace/observers/draw-info-text-in-glyph-view/?highlight=draw%20text

            glyphWindow = CurrentGlyphWindow()
            if not glyphWindow:
                return
            glyphView = glyphWindow.getGlyphView()
            textAttributes = {
                AppKit.NSFontAttributeName: AppKit.NSFont.userFixedPitchFontOfSize_(11),
            }
            glyphView.drawTextAtPoint(
            f'{round(abs(math.degrees(self.returnAngle(newPoints)))%180,4)}°\n{str(round(self.returnRatio(newPoints),4))}',
            textAttributes,
            textLoc,
            yOffset=0,
            drawBackground=True,
            centerX=True,
            centerY=True,
            roundBackground=False,)

            UpdateCurrentGlyphView()
    def getImageForView(self, viewName):
        if viewName == "Glyph View":
            window = CurrentGlyphWindow()
            if window is None:
                return None
            view = window.getGlyphView().enclosingScrollView()
        elif viewName == "Space Center":
            window = CurrentSpaceCenter()
            if window is None:
                return None
            view = window.glyphLineView.getNSScrollView()

        data = self._getImageForView(view)
        data = data.bytes()
        if isinstance(data, memoryview):
            data = data.tobytes()
        return data
 def getImageForView(self, viewName):
     if viewName == "Glyph View":
         window = CurrentGlyphWindow()
         if window is None:
             return None
         view = window.getGlyphView().enclosingScrollView()
     elif viewName == "Space Center":
         window = CurrentSpaceCenter()
         if window is None:
             return None
         view = window.glyphLineView.getNSScrollView()
     
     data = self._getImageForView(view)        
     data  = data.bytes()
     if isinstance(data, memoryview):
         data = data.tobytes()
     return data 
    def updateComp(self, g, viewScale):

        if len(g.selectedComponents) == 1:
            cf = g.font
            cg = g
            selected_component = cg.selectedComponents[0]
            selected_component_name = cg.selectedComponents[0].baseGlyph

            constructions = self.constructions
            glyph_constructor = self.glyph_constructor

            glyphWindow = CurrentGlyphWindow()
            glyphView = glyphWindow.getGlyphView()
            if not glyphWindow:
                return

            for line in glyph_constructor.split("\n"):
                if len(line) > 0:
                    composed_glyph = line.split("=")[0]
                    recipee = line.split("=")[1]
                    new_base_glyph = recipee.split("+")[0]

                    if new_base_glyph == cg.components[
                            0].baseGlyph and cg.name == composed_glyph:

                        construction = f"{composed_glyph}={recipee}"
                        constructionGlyph = GlyphConstructionBuilder(
                            construction, cf)

                        if constructionGlyph.name == cg.name:
                            for component_index, c in enumerate(
                                    constructionGlyph.components):
                                c = list(c)[0]

                                if c == selected_component_name:
                                    baseGlyphName = constructionGlyph.components[
                                        component_index - 1][0]
                                    baseGlyph = cf[baseGlyphName]

                                    recipee = construction.split("=")[1]

                                    for diacritic_and_anchor in recipee.split(
                                            "+")[1:]:
                                        diacritic = diacritic_and_anchor.split(
                                            "@")[0]
                                        anchor = diacritic_and_anchor.split(
                                            "@")[1]

                                        if diacritic == selected_component_name:
                                            selected_component_anchor_name = "_%s" % anchor

                                            for baseGlyph_anchor in baseGlyph.anchors:
                                                if baseGlyph_anchor.name == anchor:
                                                    x_baseGlyph_anchor = baseGlyph_anchor.x
                                                    y_baseGlyph_anchor = baseGlyph_anchor.y

                                                    selected_comp_baseGlyph = cf[
                                                        selected_component_name]

                                                    for selectedComponent_anchor in selected_comp_baseGlyph.anchors:
                                                        if selected_component_anchor_name == selectedComponent_anchor.name:

                                                            x_offset = 0
                                                            y_offset = 0
                                                            for previous_components in constructionGlyph.components[
                                                                    1:
                                                                    component_index]:
                                                                for cg_component in cg.components:
                                                                    if cg_component.baseGlyph == previous_components[
                                                                            0]:
                                                                        x_offset += cg_component.offset[
                                                                            0]
                                                                        y_offset += cg_component.offset[
                                                                            1]

                                                            new_x_baseGlyph_anchor = selectedComponent_anchor.x + selected_component.offset[
                                                                0] - x_offset
                                                            new_y_baseGlyph_anchor = selectedComponent_anchor.y + selected_component.offset[
                                                                1] - y_offset

                                                            self.drawInfos(
                                                                new_x_baseGlyph_anchor,
                                                                new_y_baseGlyph_anchor,
                                                                viewScale,
                                                                glyphView,
                                                                baseGlyph_anchor
                                                            )

                                                            ### Update baseGlyph anchor
                                                            baseGlyph_anchor.x = new_x_baseGlyph_anchor
                                                            baseGlyph_anchor.y = new_y_baseGlyph_anchor

                                                            if self.SettingsWindow.w.updateComposites.get(
                                                            ) == 1:
                                                                self.updateRelatedComposites(
                                                                    glyph_constructor,
                                                                    cg, cf,
                                                                    new_base_glyph,
                                                                    baseGlyph_anchor,
                                                                    composed_glyph
                                                                )
class InterpolationPreviewWindow(object):
    def __init__(self):

        self.currentGlyph = None
        self.window = None

        self.fonts = []
        self.fontNames = []

        self.glyph0 = RGlyph()  #None
        self.glyph1 = RGlyph()  #None
        self.compatibilityReport = None
        self.interpolatedGlyph = RGlyph()

        self.w = vanilla.FloatingWindow((250, 155), "Interpolation Slider")
        self.w.open()
        self.w.title = vanilla.TextBox((10, 10, -10, 25),
                                       "Masters:",
                                       sizeStyle="small")
        self.w.font0 = vanilla.PopUpButton((10, 25, -10, 25), [],
                                           callback=self.glyphChanged,
                                           sizeStyle="small")
        self.w.font1 = vanilla.PopUpButton((10, 50, -10, 25), [],
                                           callback=self.glyphChanged,
                                           sizeStyle="small")
        self.w.compatibilityText = vanilla.TextBox((-105, 83, 100, 35),
                                                   u"Compatibility: ⚪️",
                                                   sizeStyle="small")
        self.w.line = vanilla.HorizontalLine((5, 110, -5, 1))
        self.w.interpValue = vanilla.Slider((10, 120, -10, 25),
                                            callback=self.optionsChanged,
                                            minValue=0,
                                            maxValue=1)
        self.w.interpValue.set(0.5)
        self.w.bind("close", self.closed)

        self.collectFonts()
        self.glyphChanged(None)

        addObserver(self, "glyphChanged", "currentGlyphChanged")
        addObserver(self, "fontsChanged", "newFontDidOpen")
        addObserver(self, "fontsChanged", "fontDidOpen")
        addObserver(self, "fontsChanged", "fontDidClose")
        addObserver(self, "drawBkgnd", "drawBackground")
        addObserver(self, "drawPreview", "drawPreview")

    def closed(self, sender):
        if self.window:
            self.window.getGlyphView().refresh()
        if self.currentGlyph:
            self.currentGlyph.removeObserver(self, "Glyph.Changed")
            self.currentGlyph.removeObserver(self, "Glyph.ContoursChanged")
        removeObserver(self, "currentGlyphChanged")
        removeObserver(self, "newFontDidOpen")
        removeObserver(self, "fontDidOpen")
        removeObserver(self, "fontDidClose")
        removeObserver(self, "drawBackground")
        removeObserver(self, "drawPreview")

    def getFontName(self, font, fonts):
        # A helper to get the font name, starting with the preferred name and working back to the PostScript name
        # Make sure that it's not the same name as another font in the fonts list
        if font.info.openTypeNamePreferredFamilyName and font.info.openTypeNamePreferredSubfamilyName:
            name = "%s %s" % (font.info.openTypeNamePreferredFamilyName,
                              font.info.openTypeNamePreferredSubfamilyName)
        elif font.info.familyName and font.info.styleName:
            name = "%s %s" % (font.info.familyName, font.info.styleName)
        elif font.info.fullName:
            name = font.info.fullName
        elif font.info.fullName:
            name = font.info.postscriptFontName
        else:
            name = "Untitled"
        # Add a number to the name if this name already exists
        if name in fonts:
            i = 2
            while name + " (%s)" % i in fonts:
                i += 1
            name = name + " (%s)" % i
        return name

    def collectFonts(self):
        # Hold aside the current font choices
        font0idx = self.w.font0.get()
        font1idx = self.w.font1.get()
        if not font0idx == -1:
            font0name = self.fontNames[font0idx]
        else:
            font0name = None
        if not font1idx == -1:
            font1name = self.fontNames[font1idx]
        else:
            font1name = None
        # Collect info on all open fonts
        self.fonts = AllFonts()
        self.fontNames = []
        for font in self.fonts:
            self.fontNames.append(self.getFontName(font, self.fontNames))
        # Update the popUpButtons
        self.w.font0.setItems(self.fontNames)
        self.w.font1.setItems(self.fontNames)
        # If there weren't any previous names, try to set the first and second items in the list
        if font0name == None:
            if len(self.fonts):
                self.w.font0.set(0)
        if font1name == None:
            if len(self.fonts) >= 1:
                self.w.font1.set(1)
        # Otherwise, if there had already been fonts choosen before new fonts were loaded,
        # try to set the index of the fonts that were already selected
        if font0name in self.fontNames:
            self.w.font0.set(self.fontNames.index(font0name))
        if font1name in self.fontNames:
            self.w.font1.set(self.fontNames.index(font1name))

    def fontsChanged(self, info):
        self.collectFonts()
        self.glyphChanged(None)

    def glyphChanged(self, info):
        # Reset the glyph info
        self.glyph0.clear()
        self.glyph1.clear()
        self.compatibilityReport = None
        self.window = CurrentGlyphWindow()
        self.interpolatedGlyph.clear()
        # Remove any observers on the older CurrentGLyph and add them to the new one
        if self.currentGlyph:
            self.currentGlyph.removeObserver(self, "Glyph.Changed")
            self.currentGlyph.removeObserver(self, "Glyph.ContoursChanged")
        self.currentGlyph = CurrentGlyph()
        if self.currentGlyph:
            self.currentGlyph.addObserver(self, "optionsChanged",
                                          "Glyph.Changed")
            self.currentGlyph.addObserver(self, "optionsChanged",
                                          "Glyph.ContoursChanged")
        if not self.currentGlyph == None:
            # Update the glyph info
            glyphName = self.currentGlyph.name
            master0idx = self.w.font0.get()
            master1idx = self.w.font1.get()
            master0 = self.fonts[master0idx]
            master1 = self.fonts[master1idx]
            if glyphName in master0:
                self.glyph0.clear()
                pen = DecomposingPen(master0, self.glyph0.getPen())
                master0[glyphName].draw(pen)

            if glyphName in master1:
                self.glyph1.clear()
                pen = DecomposingPen(master1, self.glyph1.getPen())
                master1[glyphName].draw(pen)

        # Update the interp compatibility report
        self.testCompatibility()
        # Adjust the frame of the window to fit the interpolation
        # (Thanks Frederik!)
        if self.window:
            widths = []
            if self.glyph0:
                widths.append(self.glyph0.width)
            if self.glyph1:
                widths.append(self.glyph1.width)
            if len(widths):
                widths.sort()
                view = self.window.getGlyphView()
                scale = view.scale()
                (x, y), (w, h) = view.frame()
                ox, oy = view.offset()
                extraWidth = widths[-1] * scale
                view.setOffset((ox, oy))
                view.setFrame_(((x, y), (w + extraWidth, h)))
        # Update the view
        self.optionsChanged(None)

    def testCompatibility(self):
        status = u"⚪️"
        if self.window:
            if self.glyph0 == self.glyph1:
                status = u"⚪️"
            elif len(self.interpolatedGlyph.contours) > 0:
                status = u"✅"
            else:
                status = u"❌"
        self.w.compatibilityText.set(u"Compatibility: %s" % status)

    def optionsChanged(self, sender):
        if self.glyph0 and self.glyph1:
            # Interpolate
            self.interpolatedGlyph.clear()
            self.interpolatedGlyph.interpolate(self.w.interpValue.get(),
                                               self.glyph0, self.glyph1)
        self.testCompatibility()
        # ...and refresh the window
        if self.window:
            self.window.getGlyphView().refresh()

    def addPoints(self, pt0, pt1):
        return (pt0[0] + pt1[0], pt0[1] + pt1[1])

    def subtractPoints(self, pt0, pt1):
        return (pt0[0] - pt1[0], pt0[1] - pt1[1])

    def drawBkgnd(self, info):
        # Draw the interpolated glyph outlines
        scale = info["scale"]
        ptSize = 7 * scale
        if self.interpolatedGlyph:
            # Draw the glyph outline
            pen = CocoaPen(None)
            self.interpolatedGlyph.draw(pen)
            dt.fill(r=None, g=None, b=None, a=1)
            dt.stroke(r=0, g=0, b=0, a=0.4)
            dt.strokeWidth(2 * scale)
            dt.save()
            dt.translate(self.currentGlyph.width)
            dt.drawPath(pen.path)
            dt.stroke(r=0, g=0, b=0, a=1)
            # Draw the points and handles
            for contour in self.interpolatedGlyph.contours:
                for bPoint in contour.bPoints:
                    inLoc = self.addPoints(bPoint.anchor, bPoint.bcpIn)
                    outLoc = self.addPoints(bPoint.anchor, bPoint.bcpOut)
                    dt.line(inLoc, bPoint.anchor)
                    dt.line(bPoint.anchor, outLoc)
                    dt.fill(r=1, g=1, b=1, a=1)
                    dt.oval(bPoint.anchor[0] - (ptSize * 0.5),
                            bPoint.anchor[1] - (ptSize * 0.5), ptSize, ptSize)
                    dt.fill(0)
                    # Draw an "X" over each BCP
                    if not bPoint.bcpIn == (0, 0):
                        dt.oval(inLoc[0] - (ptSize * 0.5),
                                inLoc[1] - (ptSize * 0.5), ptSize, ptSize)
                        #dt.line((inLoc[0]-(ptSize*0.5), inLoc[1]-(ptSize*0.5)), (inLoc[0]+(ptSize*0.5), inLoc[1]+(ptSize*0.5)))
                        #dt.line((inLoc[0]+(ptSize*0.5), inLoc[1]-(ptSize*0.5)), (inLoc[0]-(ptSize*0.5), inLoc[1]+(ptSize*0.5)))
                    if not bPoint.bcpOut == (0, 0):
                        dt.oval(outLoc[0] - (ptSize * 0.5),
                                outLoc[1] - (ptSize * 0.5), ptSize, ptSize)
                        #dt.line((outLoc[0]-(ptSize*0.5), outLoc[1]-(ptSize*0.5)), (outLoc[0]+(ptSize*0.5), outLoc[1]+(ptSize*0.5)))
                        #dt.line((outLoc[0]+(ptSize*0.5), outLoc[1]-(ptSize*0.5)), (outLoc[0]-(ptSize*0.5), outLoc[1]+(ptSize*0.5)))

            dt.restore()

    def drawPreview(self, info):
        # Draw a filled in version of the interpolated glyph
        scale = info["scale"]
        if self.interpolatedGlyph:
            pen = CocoaPen(None)
            self.interpolatedGlyph.draw(pen)
            dt.fill(r=0, g=0, b=0, a=0.6)
            dt.stroke(r=None, g=None, b=None, a=1)
            dt.save()
            dt.translate(self.currentGlyph.width)
            dt.drawPath(pen.path)
            dt.restore()