def __init__(self):
     col = getDefaultColor("glyphViewSelectionColor")
     self.glyphViewSelectionColor = (col.redComponent(),
                                     col.greenComponent(),
                                     col.blueComponent(),
                                     col.alphaComponent())
     self.rightMarginIsSelected = False
     self.leftMarginIsSelected = False
     self.glyph = None
     self.font = None
     self.mousePoint = None
     self.mouseDelta = None
     self.deltaX = 0
     self.threshold = 5
     self.increment = 1
     self.glyphViewShiftIncrement = getDefault("glyphViewShiftIncrement")
     self.glyphViewCommandShiftIncrement = getDefault(
         "glyphViewCommandShiftIncrement")
     self.shiftDown = False
     self.commandDown = False
     addObserver(self, 'mouseDragged', 'mouseDragged')
     addObserver(self, 'mouseUp', 'mouseUp')
     addObserver(self, 'mouseDown', 'mouseDown')
     addObserver(self, 'keyDown', 'keyDown')
     addObserver(self, 'modifiersChanged', 'modifiersChanged')
     addObserver(self, 'draw', 'draw')
     addObserver(self, 'viewDidChangeGlyph', 'viewDidChangeGlyph')
 def __init__(self):
     
     addObserver(self, "drawMetricsBox", "drawBackground")
     
     self.color = getDefault("glyphViewMarginColor")
     self.height = getDefault("glyphViewDefaultHeight") / 2
     self.useItalicAngle = getDefault("glyphViewShouldUseItalicAngleForDisplay")
Example #3
0
 def _turnOn(self):
     pass
     pref_as_is = getDefault('glyphZoomViewShowItems')
     pref_new = dict()
     for i in getDefault('glyphZoomViewShowItems'):
         if i in turnOnItems:
             pref_new[i] = 1
         else:
             pass
     setDefault('glyphZoomViewShowItems', pref_new)
     preferencesChanged()
Example #4
0
def get_glyphs(font):  # current_glyph=True, font_selection=True,
    """
    Return current glyph selection in the font as glyph names or ``RGlyph`` objects.

    """
    # get glyphs
    current_glyph = CurrentGlyph()
    font_selection = font.selection
    # get RoboFont's window mode
    single_window = [False, True][getDefault("singleWindowMode")]
    # handle multi-window mode
    glyphs = []
    if not single_window:
        if current_glyph is not None:
            glyphs += [current_glyph.name]
        else:
            glyphs += font_selection
    # multi-window: return
    else:
        if current_glyph is not None:
            glyphs += [current_glyph.name]
            glyphs += font_selection
        else:
            glyphs += font_selection
    # done
    return list(set(glyphs))
Example #5
0
 def checkSyntax(self, sender=None):
     # get the code
     code = self.code()
     # get te path of the document (will be None for an untitled document)
     path = self.path()
     # when enabled clear the output text view
     if getDefault("PyDEClearOutput", True):
         self.outPutView.set("")
     # create a new std output, catching all print statements and tracebacks
     self.output = []
     self.stdout = StdOutput(self.output)
     self.stderr = StdOutput(self.output, True)
     # run the code, but with the optional flag checkSyntaxOnly so it will just compile the code
     ScriptRunner(code,
                  path,
                  stdout=self.stdout,
                  stderr=self.stderr,
                  checkSyntaxOnly=True)
     # set the catched print statements and tracebacks in the the output text view
     for text, isError in self.output:
         self.outPutView.append(text, isError)
     # clean up
     self.output = None
     self.stdout = None
     self.stderr = None
Example #6
0
def get_glyphs(font):  # current_glyph=True, font_selection=True,
    """
    Return current glyph selection in the font as glyph names or ``RGlyph`` objects.

    """
    # get glyphs
    current_glyph = CurrentGlyph()
    font_selection = font.selection
    # get RoboFont's window mode
    single_window = [False, True][getDefault("singleWindowMode")]
    # handle multi-window mode
    glyphs = []
    if not single_window:
        if current_glyph is not None:
            glyphs += [current_glyph.name]
        else:
            glyphs += font_selection
    # multi-window: return
    else:
        if current_glyph is not None:
            glyphs += [current_glyph.name]
            glyphs += font_selection
        else:
            glyphs += font_selection
    # done
    return list(set(glyphs))
    def runCode(self, liveCoding=False):
        # get the code
        code = self.code()
        # save the code in the defaults, if something goes wrong
        setDefault("pythonCodeBackup", code)
        # get te path of the document (will be None for an untitled document)
        path = self.path()
        # reset the internal warning system
        warnings.resetWarnings()
        # reset the drawing tool
        _drawBotDrawingTool.newDrawing()
        # create a namespace
        namespace = DrawBotNamespace(_drawBotDrawingTool, _drawBotDrawingTool._magicVariables)
        # add the tool callbacks in the name space
        _drawBotDrawingTool._addToNamespace(namespace)
        # when enabled clear the output text view
        if getDefault("PyDEClearOutput", True):
            self.outPutView.clear()
        # create a new std output, catching all print statements and tracebacks
        self.output = []
        self.stdout = StdOutput(self.output)
        self.stderr = StdOutput(self.output, True)
        # warnings should show the warnings
        warnings.shouldShowWarnings = True
        # run the code
        ScriptRunner(code, path, namespace=namespace, stdout=self.stdout, stderr=self.stderr)
        # warnings should stop posting them
        warnings.shouldShowWarnings = False
        # set context, only when the panes are visible
        if self.w.split.isPaneVisible("drawView") or self.w.split.isPaneVisible("thumbnails"):
            def createContext(context):
                # draw the tool in to the context
                _drawBotDrawingTool._drawInContext(context)
            # create a context to draw in
            context = DrawBotContext()
            # savely run the callback and track all traceback back the the output
            CallbackRunner(createContext, stdout=self.stdout, stderr=self.stderr, args=[context])
            # get the pdf document and set in the draw view
            pdfDocument = context.getNSPDFDocument()
            if not liveCoding or (pdfDocument and pdfDocument.pageCount()):
                self.drawView.setPDFDocument(pdfDocument)
            # scroll down
            self.drawView.scrollDown()
        else:
            # if the panes are not visible, clear the draw view
            self.drawView.setPDFDocument(None)

        # set the catched print statements and tracebacks in the the output text view
        for text, isError in self.output:
            if liveCoding and isError:
                continue
            self.outPutView.append(text, isError)

        # reset the code backup if the script runs with any crashes
        setDefault("pythonCodeBackup", None)
        # clean up

        self.output = None
        self.stdout = None
        self.stderr = None
Example #8
0
def getGlyphReport(font, glyph, options):
    #start = time()
    options["grid_length"] = getDefault('glyphViewRoundValues')
    myPen = OutlineTestPen(font, options)
    glyph.drawPoints(myPen)
    #stop = time()
    #print("updateOutlineCheck in %0.2f ms." % ((stop-start) * 1000))
    return myPen.errors
Example #9
0
def getGlyphReport(font, glyph, options):
    #start = time()
    options["grid_length"] = getDefault('glyphViewRoundValues')
    myPen = OutlineTestPen(font, options)
    glyph.drawPoints(myPen)
    #stop = time()
    #print "updateOutlineCheck in %0.2f ms." % ((stop-start) * 1000)
    return myPen.errors
Example #10
0
 def _turnOff(self):
     pref_as_is = getDefault('glyphZoomViewShowItems')
     setExtensionDefault('restoreGlyphZoomViewShowItems', pref_as_is)
     pref_new = dict()
     for i in pref_as_is:
         if i in turnOffItems:
             pref_new[i] = 0
         else:
             pref_new[i] = pref_as_is[i]
     setDefault('glyphZoomViewShowItems', pref_new)
     preferencesChanged()
 def restoreGlyphViewItems(self):
     pref_as_is = getDefault('glyphZoomViewShowItems')
     pref_new = dict()
     for i in pref_as_is:
         if i in turnOffItems:
             # global gridWasOn
             # gridWasOn = pref_as_is[i]
             pref_new[i] = 1
         else:
             pref_new[i] = pref_as_is[i]
     setDefault('glyphZoomViewShowItems', pref_new)
     PostNotification("doodle.preferencesChanged")
    def runCode(self):
        self._errorView.set("")
        if not self._code:    
            return
        self._drawingTools._reset()
        if getDefault("PyDEClearOutput", True):
            self._errorView.clear()
        self.stdout = Output(self._errorView)
        self.stderr = Output(self._errorView, True)
        path = self.getPath()

        namespace = dict()
        for name in self._drawingTools.__all__:
            namespace[name] = getattr(self._drawingTools, name)
        ScriptRunner(text=self._code, path=path, stdout=self.stdout, stderr=self.stderr, namespace=namespace)
Example #13
0
def getColorTheme():

    try:
        tokens = dict(getDefault("PyDETokenColors"))
    except:
        tokens = {}
        print('no custom colors defined.\n')

    background = getDefaultColor("PyDEbackgroundColor")
    highlight = getDefaultColor("PyDEHightLightColor")

    return {
        'background': background,
        'highlight': highlight,
        'tokens': tokens,
    }
Example #14
0
    def runCode(self):
        self._errorView.set("")
        if not self._code:
            return
        self._drawingTools._reset()
        if getDefault("PyDEClearOutput", True):
            self._errorView.clear()
        self.stdout = Output(self._errorView)
        self.stderr = Output(self._errorView, True)
        path = self.getPath()

        namespace = dict()
        for name in self._drawingTools.__all__:
            namespace[name] = getattr(self._drawingTools, name)
        ScriptRunner(text=self._code,
                     path=path,
                     stdout=self.stdout,
                     stderr=self.stderr,
                     namespace=namespace)
Example #15
0
 def runCode(self, sender=None):
     code = self.codeEditor.get()
     container = self.merzView.getMerzContainer()
     container.clearSublayers()
     namespace = dict(container=container, merz=merz)
     if getDefault("PyDEClearOutput", True):
         self.outputEditor.clear()
     self.output = []
     self.stdout = StdOutput(self.output)
     self.stderr = StdOutput(self.output, True)
     ScriptRunner(code,
                  "<Merz Playground>",
                  namespace=namespace,
                  stdout=self.stdout,
                  stderr=self.stderr)
     for text, isError in self.output:
         self.outputEditor.append(text, isError)
     self.output = None
     self.stdout = None
     self.stderr = None
    def saverCallback(self, sender):
        print("saving input text")
        csc = CurrentSpaceCenter()

        string = csc.getRaw()
        print("string is", string)

        before = getDefault("spaceCenterInputSamples")
        print("before is ", before)
        after = list(before)
        print("after is ", after)
        if string not in after:
            after.append(string)
            print("after2 is ", after)
            setDefault("spaceCenterInputSamples", after)
            print("saved input text.")
        else:
            print("did nothing.")

        preferencesChanged()
 def checkSyntax(self, sender=None):
     # get the code
     code = self.code()
     # get te path of the document (will be None for an untitled document)
     path = self.path()
     # when enabled clear the output text view
     if getDefault("PyDEClearOutput", True):
         self.outPutView.set("")
     # create a new std output, catching all print statements and tracebacks
     self.output = []
     self.stdout = StdOutput(self.output)
     self.stderr = StdOutput(self.output, True)
     # run the code, but with the optional flag checkSyntaxOnly so it will just compile the code
     ScriptRunner(code, path, stdout=self.stdout, stderr=self.stderr, checkSyntaxOnly=True)
     # set the catched print statements and tracebacks in the the output text view
     for text, isError in self.output:
         self.outPutView.append(text, isError)
     # clean up
     self.output = None
     self.stdout = None
     self.stderr = None
Example #18
0
from __future__ import print_function, division
#import outlineTestPen
#reload(outlineTestPen)
from outlineTestPen import OutlineTestPen
from lib.tools.defaults import getDefault

options = {
    "extremum_calculate_badness": True,
    "fractional_ignore_point_zero": True,
    "extremum_ignore_badness_below": 0,
    "smooth_connection_max_distance": 4,
    "collinear_vectors_max_distance": 2,
    "semi_hv_vectors_min_distance": 30,
    "zero_handles_max_distance": 0,
    "grid_length": getDefault('glyphViewRoundValues'),
}


def run_test(font, glyphnames):
    selection = []
    for n in glyphnames:
        g = font[n]
        otp = OutlineTestPen(CurrentFont(), options)
        g.drawPoints(otp)
        if otp.errors:
            #if len(otp.errors) > 0:
            #    g.mark = (1, 0.65, 0.6, 1)
            selection.append(g.name)
            #for e in otp.errors:
            #    print(e)
    font.selection = selection
Example #19
0
    def runCode(self, liveCoding=False):
        # get the code
        code = self.code()
        # save the code in the defaults, if something goes wrong
        setDefault("pythonCodeBackup", code)
        # get te path of the document (will be None for an untitled document)
        path = self.path()
        # reset the internal warning system
        warnings.resetWarnings()
        # reset the drawing tool
        _drawBotDrawingTool.newDrawing()
        # create a namespace
        namespace = DrawBotNamespace(_drawBotDrawingTool,
                                     _drawBotDrawingTool._magicVariables)
        # add the tool callbacks in the name space
        _drawBotDrawingTool._addToNamespace(namespace)
        # when enabled clear the output text view
        if getDefault("PyDEClearOutput", True):
            self.outPutView.clear()
        # create a new std output, catching all print statements and tracebacks
        self.output = []
        self.stdout = StdOutput(self.output)
        self.stderr = StdOutput(self.output, True)
        # warnings should show the warnings
        warnings.shouldShowWarnings = True
        # run the code
        ScriptRunner(code,
                     path,
                     namespace=namespace,
                     stdout=self.stdout,
                     stderr=self.stderr)
        # warnings should stop posting them
        warnings.shouldShowWarnings = False
        # set context, only when the panes are visible
        if self.w.split.isPaneVisible(
                "drawView") or self.w.split.isPaneVisible("thumbnails"):

            def createContext(context):
                # draw the tool in to the context
                _drawBotDrawingTool._drawInContext(context)

            # create a context to draw in
            context = DrawBotContext()
            # savely run the callback and track all traceback back the the output
            CallbackRunner(createContext,
                           stdout=self.stdout,
                           stderr=self.stderr,
                           args=[context])
            # get the pdf document and set in the draw view
            pdfDocument = context.getNSPDFDocument()
            if not liveCoding or (pdfDocument and pdfDocument.pageCount()):
                self.drawView.setPDFDocument(pdfDocument)
            # scroll down
            self.drawView.scrollDown()
        else:
            # if the panes are not visible, clear the draw view
            self.drawView.setPDFDocument(None)

        # set the catched print statements and tracebacks in the the output text view
        for text, isError in self.output:
            if liveCoding and isError:
                continue
            self.outPutView.append(text, isError)

        # reset the code backup if the script runs with any crashes
        setDefault("pythonCodeBackup", None)
        # clean up

        self.output = None
        self.stdout = None
        self.stderr = None
# import outlineTestPen
# reload(outlineTestPen)
from outlineTestPen import OutlineTestPen
from lib.tools.defaults import getDefault

options = {
    "extremum_calculate_badness": True,
    "fractional_ignore_point_zero": True,
    "extremum_ignore_badness_below": 0,
    "smooth_connection_max_distance": 4,
    "collinear_vectors_max_distance": 2,
    "semi_hv_vectors_min_distance": 30,
    "zero_handles_max_distance": 0,
    "grid_length": getDefault("glyphViewRoundValues"),
}


def run_test(font, glyphnames):
    selection = []
    for n in glyphnames:
        g = font[n]
        otp = OutlineTestPen(CurrentFont(), options)
        g.drawPoints(otp)
        if otp.errors:
            # if len(otp.errors) > 0:
            #    g.mark = (1, 0.65, 0.6, 1)
            selection.append(g.name)
            # for e in otp.errors:
            #    print e
    font.selection = selection
Example #21
0
 def __init__(self):
     
     # Preferences
     self._drawing = getExtensionDefault(self.DEFAULTKEY_DRAW, True)
     self._fill = getExtensionDefault(self.DEFAULTKEY_FILL, True)
     self._stroke = getExtensionDefault(self.DEFAULTKEY_STROKE, True)
     self._points = getExtensionDefault(self.DEFAULTKEY_POINTS, True)
     
     self._fillColor = getExtensionDefaultColor(self.DEFAULTKEY_FILLCOLOR, self.FALLBACK_FILLCOLOR)
     self._strokeColor = getExtensionDefaultColor(self.DEFAULTKEY_STROKECOLOR, self.FALLBACK_STROKECOLOR)
     self._pointsColor = getExtensionDefaultColor(self.DEFAULTKEY_POINTSCOLOR, self.FALLBACK_POINTSCOLOR)
     
     self._alignment = getExtensionDefault(self.DEFAULTKEY_ALIGNMENT, 0)
     self._kerning = getExtensionDefault(self.DEFAULTKEY_KERNING, 1)
     self._floating = getExtensionDefault(self.DEFAULTKEY_FLOATING, 1)
     
     # User preferences
     self._onCurvePointsSize = getDefault("glyphViewOncurvePointsSize") # typo, should be: OnCurve
     self._offCurvePointsSize = getDefault("glyphViewOffCurvePointsSize")
     self._strokeWidth = getDefault("glyphViewStrokeWidth")
     
     w, h = 400, 195
     x = y = 10
     
     self.initAllFonts()
     
     self.w = FloatingWindow((w, h), "Overlay UFOs")
     self.w.draw = CheckBox((x, y, 95, 18), "Draw", callback=self.drawCallback, value=self._drawing, sizeStyle="small")
     x += 60
     self.w.fill = CheckBox((x, y, 95, 18), "Fill", callback=self.fillCallback, value=self._fill, sizeStyle="small")
     x += 40
     self.w.fillColor = ColorWell((x, y, 45, 20), callback=self.fillColorCallback, color=self._fillColor)
     x += 60
     self.w.stroke = CheckBox((x, y, 95, 18), "Stroke", callback=self.strokeCallback, value=self._stroke, sizeStyle="small")
     x += 60
     self.w.strokeColor = ColorWell((x, y, 45, 20), callback=self.strokeColorCallback, color=self._strokeColor)
     x += 60
     self.w.points = CheckBox((x, y, 95, 18), "Points", callback=self.pointsCallback, value=self._points, sizeStyle="small")
     x += 60
     self.w.pointsColor = ColorWell((x, y, 45, 20), callback=self.pointsColorCallback, color=self._pointsColor)
     x, y = 10, 40
     self.w.alignText = TextBox((x, y, 250, 15), "Alignment:", sizeStyle="small")
     y += 18
     self.w.alignment = RadioGroup((x, y, 80, 55), ['Left', 'Center', 'Right'], isVertical=True, callback=self.alignmentCallback, sizeStyle="small")
     self.w.alignment.set(self._alignment)
     y += 62
     self.w.kerning = CheckBox((x, y, 100, 10), "Show kerning", callback=self.kerningCallback, value=self._kerning, sizeStyle="mini")
     y += 18
     self.w.floating = CheckBox((x, y, 100, 10), "Floating Window", callback=self.floatingCallback, value=self._floating, sizeStyle="mini")
     y += 25
     self.w.resetDefaults = Button((x, y, 85, 14), "Reset settings", callback=self.resetSettingsCallback, sizeStyle="mini")
     x, y = 110, 40
     self.w.fontList = List((x, y, 240, 55), self.getFontItems(), 
         columnDescriptions=self.getListDescriptor(), showColumnTitles=False,
         selectionCallback=None, doubleClickCallback=self.fontListCallback,
         allowsMultipleSelection=True, allowsEmptySelection=True,
         drawVerticalLines=False, drawHorizontalLines=True,
         drawFocusRing=False, rowHeight=16
     )
     y += 55
     self.w.hiddenFontList = List((x, y, 240, 55), self.getHiddenFontItems(), 
         columnDescriptions=self.getListDescriptor(), showColumnTitles=False,
         selectionCallback=None, doubleClickCallback=self.hiddenFontListCallback,
         allowsMultipleSelection=True, allowsEmptySelection=True,
         drawVerticalLines=False, drawHorizontalLines=True,
         drawFocusRing=False, rowHeight=16
     )
     self._selectionChanging = False
     self.w.fontList.setSelection([]) # unselect
     y += 65
     self.w.contextLeft = EditText((x, y, 90, 20), callback=self.contextCallback, continuous=True, placeholder="Left", sizeStyle="small")
     self.w.contextCurrent = EditText((x+95, y, 50, 20), callback=self.contextCallback, continuous=True, placeholder="?", sizeStyle="small")
     self.w.contextRight = EditText((x+150, y, 90, 20), callback=self.contextCallback, continuous=True, placeholder="Right", sizeStyle="small")
     x, y = 360, 100
     self.w.addFonts = Button((x, y, 30, 20), "+", callback=self.addHiddenFontsCallback, sizeStyle="regular")
     y += 25
     self.w.removeFonts = Button((x, y, 30, 20), unichr(8722), callback=self.removeHiddenFontsCallback, sizeStyle="regular")
             
     # Observers
     addObserver(self, "fontDidOpen", "fontDidOpen")
     addObserver(self, "fontWillClose", "fontWillClose") # fontDidClose?
     addObserver(self, "draw", "drawInactive")
     addObserver(self, "draw", "draw")
     
     # Prepare and open window
     self.setWindowLevel()
     self.setUpBaseWindowBehavior()
     self.w.open()
Example #22
0
from mojo.events import addObserver
from mojo.drawingTools import *
from lib.tools.defaults import getDefaultColor, getDefault
from mojo.UI import getGlyphViewDisplaySettings
from lib.tools.misc import NSColorToRgba
from fontTools.misc.fixedTools import otRound

rad_base = getDefault("glyphViewOncurvePointsSize") * 1.75


class Eyeliner():
    '''
    Adds a little eye around points and anchors that are on the vertical font  dimensions or guidelines.
    
    Ryan Bugden
    v1.2.5 : 2020.07.15
    v1.2.1 : 2020.04.03
    v1.2.0 : 2020.03.26
    v1.1.1 : 2020.01.27
    v1.0.0 : 2020.01.24
    v0.9.0 : 2019.06.04
    '''
    def __init__(self):

        self.col_font_dim = self.getFlattenedAlpha(
            NSColorToRgba(getDefaultColor("glyphViewMetricsColor")))
        self.col_glob_guides = self.getFlattenedAlpha(
            NSColorToRgba(getDefaultColor("glyphViewGlobalGuidesColor")))
        self.col_loc_guides = self.getFlattenedAlpha(
            NSColorToRgba(getDefaultColor("glyphViewLocalGuidesColor")))
Example #23
0
class BoundingTool(EditingTool, BaseWindowController):
    slantPointCoordinates = int(
        getDefault("glyphViewShouldSlantPointCoordinates"))
    offsetPointCoordinates = getDefault(
        "glyphViewShouldOffsetPointCoordinates")

    DEFAULTKEY = "com.fontbureau.boundingTool"
    DEFAULTKEY_FILLCOLOR = "%s.fillColor" % DEFAULTKEY
    DEFAULTKEY_STROKECOLOR = "%s.strokeColor" % DEFAULTKEY
    DEFAULTKEY_SHOWCOORDINATES = "%s.showCoordinates" % DEFAULTKEY
    DEFAULTKEY_SHOWDIMENSIONS = "%s.showCoordinates" % DEFAULTKEY
    DEFAULTKEY_SELECTION = "%s.selection" % DEFAULTKEY
    DEFAULTKEY_DIVISIONSX = "%s.divisionsX" % DEFAULTKEY
    DEFAULTKEY_DIVISIONSY = "%s.divisionsY" % DEFAULTKEY
    DEFAULTKEY_USEITALIC = "%s.useItalic" % DEFAULTKEY
    FALLBACK_FILLCOLOR = NSColor.colorWithCalibratedRed_green_blue_alpha_(
        1, .5, .5, .3)
    FALLBACK_STROKECOLOR = NSColor.colorWithCalibratedRed_green_blue_alpha_(
        1, .5, .5, .5)
    VERSION = 1.0
    NAME = u'Bounding Tool'
    MANUAL = u"""TK"""

    color = (1, 0, .2)
    alpha = 1
    divisionsStringList = ['1', '2', '3', '4']
    divisionsList = [1, 2, 3, 4]

    def getToolbarTip(self):
        return self.NAME

    def getToolbarIcon(self):
        return toolbarIcon

    def getBox(self, selected=True):
        g = self.getGlyph()
        if g is not None and g.box is not None:
            n = g
            if selected:
                hasSelection = False
                copyGlyph = g.naked().selection.getCopyGlyph()
                if copyGlyph and copyGlyph[1].get('contours'):
                    n = RGlyph(copyGlyph[0])
                else:
                    n = g
            if self.w.useItalic.get():
                italicAngle = g.getParent().info.italicAngle or 0
                if n.box:
                    boxTop = n.box[3]
                    boxBottom = n.box[1]
                    boxWidth = n.box[2] - n.box[0]
                else:
                    boxTop = g.getParent().info.ascender
                    boxBottom = g.getParent().info.descender
                    boxWidth = g.width
                #print n.angledLeftMargin, g.getParent().lib.get('com.typemytype.robofont.italicSlantOffset')
                try:
                    leftX = n.angledLeftMargin or 0 + g.getParent().lib.get(
                        'com.typemytype.robofont.italicSlantOffset') or 0
                    rightX = n.width - n.angledRightMargin or 0 + g.getParent(
                    ).lib.get('com.typemytype.robofont.italicSlantOffset') or 0
                except:
                    leftX = rightX = 0

                topY = n.box[3]
                bottomY = n.box[1]

                topX = TX.getItalicOffset(topY, italicAngle)
                bottomX = TX.getItalicOffset(bottomY, italicAngle)

                box = (
                    (leftX + bottomX, bottomY),  # bottom left
                    (leftX + topX, topY),  # top left
                    (rightX + topX, topY),  # top right
                    (rightX + bottomX, bottomY),  # bottom right
                    (n.naked().angledBounds[2] - n.naked().angledBounds[0],
                     n.naked().angledBounds[3] - n.naked().angledBounds[1]))
            else:
                box = ((n.box[0], n.box[1]), (n.box[0], n.box[3]),
                       (n.box[2], n.box[3]), (n.box[2], n.box[1]),
                       (n.box[2] - n.box[0], n.box[3] - n.box[1]))
        else:
            box = None  #((0, 0), (0, 0), (0, 0), (0, 0), (0, 0))
        return box

    def drawBackground(self, scale):
        g = self.getGlyph()
        self.fillColor.setFill()

        slantCoordinates = self.slantPointCoordinates
        italicSlantOffset = 0
        if self.offsetPointCoordinates:
            italicSlantOffset = g.getParent().lib.get(
                'com.typemytype.robofont.italicSlantOffset') or 0
        color = self.fillColor.colorUsingColorSpaceName_(
            NSCalibratedRGBColorSpace)
        red = color.redComponent()
        green = color.greenComponent()
        blue = color.blueComponent()
        alpha = color.alphaComponent()
        fill(red, green, blue, alpha)
        stroke(red, green, blue, alpha)
        strokeWidth(1 * scale)
        dashLine(1)
        fontSizeValue = 8
        fontSize(fontSizeValue * scale)

        showCoordinates = self.w.showCoordinates.get()
        showDimensions = self.w.showDimensions.get()

        selectedBox = self.getBox(selected=True)

        if selectedBox:
            # switch them around so that we draw a line perpindicular to the axis we want to subdivide
            divisionsY = int(self.w.divisionsRadioX.get())
            divisionsX = int(self.w.divisionsRadioY.get())

            pt1, pt2, pt3, pt4, dimensions = selectedBox
            pt1X, pt1Y = pt1  # bottom left
            pt2X, pt2Y = pt2  # top left
            pt3X, pt3Y = pt3  # top right
            pt4X, pt4Y = pt4  # bottom right

            pt1X += italicSlantOffset
            pt2X += italicSlantOffset
            pt3X += italicSlantOffset
            pt4X += italicSlantOffset

            width, height = dimensions
            startRectX = pt1X
            startRectY = pt1Y
            rectWidth = width / float(divisionsY)
            rectHeight = height / float(divisionsX)
            if self.w.useItalic.get():
                italicAngle = g.getParent().info.italicAngle or 0
            else:
                italicAngle = 0
            margin = 0
            f = g.getParent()
            asc = f.info.ascender + f.info.unitsPerEm
            desc = f.info.descender - f.info.unitsPerEm

            ascOffset = TX.getItalicOffset(asc - pt3Y, italicAngle)
            descOffset = TX.getItalicOffset(desc - pt1Y, italicAngle)

            line(pt1X + descOffset, desc, pt2X + ascOffset, asc)
            line(pt4X + descOffset, desc, pt3X + ascOffset, asc)

            line(pt1X - f.info.unitsPerEm, pt1Y, pt4X + f.info.unitsPerEm,
                 pt1Y)
            line(pt2X - f.info.unitsPerEm, pt2Y, pt3X + f.info.unitsPerEm,
                 pt2Y)

            margin = 10 * scale  #((width + height) / 2) / 20

            if showDimensions:
                widthYBump = 0
                if italicAngle:
                    widthYBump = 20 * scale

                widthString = 'w: %s' % (TX.formatStringValue(width))
                widthXPos = pt2X + (width / 2.0) + TX.getItalicOffset(
                    margin, italicAngle) - 10 * scale
                widthYPos = pt2Y + margin + widthYBump
                if divisionsY > 1:
                    subWidthString = '    %s' % (TX.formatStringValue(
                        width / divisionsY))
                    text(subWidthString, widthXPos, widthYPos)
                    widthYPos += fontSizeValue * scale
                font("LucidaGrande-Bold")
                text(widthString, widthXPos, widthYPos)

            if divisionsY >= 1:
                xoffset = pt1X
                for divY in range(divisionsY + 1):
                    if divY != 0 and divY != divisionsY:
                        line(
                            xoffset - TX.getItalicOffset(margin, italicAngle),
                            pt1Y - margin, xoffset +
                            TX.getItalicOffset(pt2Y - pt1Y, italicAngle) +
                            TX.getItalicOffset(margin, italicAngle),
                            pt3Y + margin)
                    if showCoordinates:
                        font("LucidaGrande")
                        x, y = bezierTools.angledPoint((xoffset, pt1Y),
                                                       italicAngle,
                                                       roundValue=italicAngle,
                                                       reverse=-1)
                        text(
                            '%s' %
                            (TX.formatStringValue(x - italicSlantOffset)),
                            xoffset - TX.getItalicOffset(margin, italicAngle) +
                            2 * scale, pt1Y - margin - fontSizeValue)
                        if italicAngle != 0:
                            x, y = bezierTools.angledPoint(
                                (xoffset, pt1Y),
                                italicAngle,
                                roundValue=italicAngle,
                                reverse=-1)
                            text(
                                '%s' %
                                (TX.formatStringValue(x - italicSlantOffset)),
                                xoffset +
                                TX.getItalicOffset(pt3Y - pt1Y, italicAngle) +
                                TX.getItalicOffset(margin, italicAngle) +
                                2 * scale, pt3Y + margin)
                    xoffset += rectWidth

            ###################
            ###################
            ###################
            ###################
            margin = 10 * scale

            if showDimensions:
                heightString = 'h: %s' % (TX.formatStringValue(height))
                heightXPos = pt4X + TX.getItalicOffset(height / 2.0,
                                                       italicAngle) + margin
                heightYPos = pt4Y + (height / 2.0) - fontSizeValue / 2

                if divisionsX > 1:
                    heightYPos -= fontSizeValue * scale / 2
                    subHeightString = '    %s' % (TX.formatStringValue(
                        height / divisionsX))
                    text(
                        subHeightString,
                        heightXPos,
                        heightYPos,
                    )
                    heightYPos += fontSizeValue * scale

                font("LucidaGrande-Bold")
                text(heightString, heightXPos, heightYPos)
            if divisionsX >= 1:
                yoffset = pt1Y
                for divX in range(divisionsX + 1):
                    if divX != 0 and divX != divisionsX:
                        line(
                            pt1X +
                            TX.getItalicOffset(yoffset - pt1Y, italicAngle) -
                            margin, yoffset, pt1X +
                            TX.getItalicOffset(yoffset - pt1Y, italicAngle) +
                            width + margin, yoffset)
                    if showCoordinates:
                        font("LucidaGrande")
                        text(
                            '%s' % (TX.formatStringValue(yoffset)), pt1X +
                            TX.getItalicOffset(yoffset - pt1Y, italicAngle) -
                            margin - 14 * scale, yoffset)
                    yoffset += rectHeight

    def becomeActive(self):
        """
        Boot up the dialog.
        """

        self.fillColor = getExtensionDefaultColor(self.DEFAULTKEY_FILLCOLOR,
                                                  self.FALLBACK_FILLCOLOR)
        self.strokeColor = getExtensionDefaultColor(
            self.DEFAULTKEY_STROKECOLOR, self.FALLBACK_STROKECOLOR)

        self.w = FloatingWindow((260, 130),
                                "Bounding Options",
                                minSize=(100, 100),
                                closable=False)

        self.w.viewOptions = RadioGroup((10, 10, 150, 20),
                                        ['Selection', 'Glyph'],
                                        callback=self.selectionCallback,
                                        isVertical=False,
                                        sizeStyle="small")
        self.w.viewOptions.set(
            getExtensionDefault(self.DEFAULTKEY_SELECTION, 0))

        self.w.useItalic = CheckBox(
            (165, 10, 100, 20),
            "Use Italic",
            value=getExtensionDefault(self.DEFAULTKEY_USEITALIC, True),
            sizeStyle="small",
            callback=self.useItalicCallback)

        self.w.xLabel = TextBox((10, 40, 70, 20),
                                "Divisions: X",
                                sizeStyle="small")

        self.w.divisionsRadioX = Slider(
            (80, 40, 70, 20),
            value=getExtensionDefault(self.DEFAULTKEY_DIVISIONSX, 1),
            minValue=1,
            maxValue=4,
            tickMarkCount=4,
            stopOnTickMarks=True,
            continuous=True,
            sizeStyle="small",
            callback=self.divisionsXCallback)

        self.w.yLabel = TextBox((160, 40, 70, 20), "Y", sizeStyle="small")
        self.w.divisionsRadioY = Slider(
            (175, 40, 70, 20),
            value=getExtensionDefault(self.DEFAULTKEY_DIVISIONSY, 1),
            minValue=1,
            maxValue=4,
            tickMarkCount=4,
            stopOnTickMarks=True,
            continuous=True,
            sizeStyle="small",
            callback=self.divisionsYCallback)

        self.w.drawGuidesButton = Button((10, 100, 90, 20),
                                         'Div Guides',
                                         callback=self.drawDivGuides,
                                         sizeStyle="small")
        self.w.drawBoxGuidesButton = Button(
            (120, 100, 90, 20),
            'Box Guides',
            callback=self.drawBoxGuides,
            sizeStyle="small",
        )

        x = 10
        y = 70
        self.w.showCoordinates = CheckBox(
            (x, y, 90, 20),
            "Coordinates",
            value=getExtensionDefault(self.DEFAULTKEY_SHOWCOORDINATES, True),
            sizeStyle="small",
            callback=self.showCoordinatesCallback)
        x += 90
        self.w.showDimensions = CheckBox(
            (x, y, 90, 20),
            "Dimensions",
            value=getExtensionDefault(self.DEFAULTKEY_SHOWDIMENSIONS, True),
            sizeStyle="small",
            callback=self.showDimensionsCallback)

        x += 90
        color = getExtensionDefaultColor(self.DEFAULTKEY_FILLCOLOR,
                                         self.FALLBACK_FILLCOLOR)
        self.w.color = ColorWell((x, y, 30, 22),
                                 color=color,
                                 callback=self.colorCallback)

        self.setUpBaseWindowBehavior()
        self.w.open()

    def becomeInactive(self):
        """
        Remove the dialog when the tool is inactive.
        """
        self.windowCloseCallback(None)
        self.w.close()

    def colorCallback(self, sender):
        """
        Change the color.
        """
        selectedColor = sender.get()
        r = selectedColor.redComponent()
        g = selectedColor.greenComponent()
        b = selectedColor.blueComponent()
        a = 1
        strokeColor = NSColor.colorWithCalibratedRed_green_blue_alpha_(
            r, g, b, a)
        setExtensionDefaultColor(self.DEFAULTKEY_FILLCOLOR, selectedColor)
        setExtensionDefaultColor(self.DEFAULTKEY_STROKECOLOR, strokeColor)
        self.fillColor = selectedColor
        self.strokeColor = strokeColor
        self.updateView()

    def showCoordinatesCallback(self, sender):
        setExtensionDefault(self.DEFAULTKEY_SHOWCOORDINATES, sender.get())
        self.updateView()

    def showDimensionsCallback(self, sender):
        setExtensionDefault(self.DEFAULTKEY_SHOWDIMENSIONS, sender.get())
        self.updateView()

    def divisionsXCallback(self, sender):
        setExtensionDefault(self.DEFAULTKEY_DIVISIONSX, sender.get())
        self.updateView()

    def divisionsYCallback(self, sender):
        setExtensionDefault(self.DEFAULTKEY_DIVISIONSY, sender.get())
        self.updateView()

    def selectionCallback(self, sender):
        setExtensionDefault(self.DEFAULTKEY_SELECTION, sender.get())
        self.updateView()

    def useItalicCallback(self, sender):
        setExtensionDefault(self.DEFAULTKEY_USEITALIC, sender.get())
        self.updateView()

    def drawDivGuides(self, sender):
        """
        Draw guidelines for the current divisions.
        """
        g = self.getGlyph()
        if self.w.viewOptions.get() == 0:
            selectedBox = self.getBox(selected=True)
        else:
            selectedBox = self.getBox(selected=False)
        if selectedBox:
            divisionsX = int(self.w.divisionsRadioY.get())
            divisionsY = int(self.w.divisionsRadioX.get())
            pt1, pt2, pt3, pt4, dimensions = selectedBox
            pt1X, pt1Y = pt1  # bottom left
            pt2X, pt2Y = pt2  # top left
            pt3X, pt3Y = pt3  # top right
            pt4X, pt4Y = pt4  # bottom right
            width, height = dimensions
            italicAngle = 0
            if self.w.useItalic.get():
                italicAngle = g.getParent().info.italicAngle or 0
            g.prepareUndo()
            offset = pt1X
            advance = float(width) / divisionsX
            for i in range(divisionsX - 1):
                xmid = offset + advance
                g.addGuide((xmid, pt1Y), 90 + italicAngle)
                offset += advance
            offset = pt1Y
            advance = float(height) / divisionsY
            for i in range(divisionsY - 1):
                ymid = offset + advance
                g.addGuide((pt1X, ymid), 0)
                offset += advance
            g.performUndo()

    def drawBoxGuides(self, sender):
        """
        Draw guidelines for the current box.
        """
        g = self.getGlyph()
        selectedBox = self.getBox(selected=True)
        if selectedBox:
            divisionsX = int(self.w.divisionsRadioY.get())
            divisionsY = int(self.w.divisionsRadioX.get())
            pt1, pt2, pt3, pt4, dimensions = selectedBox
            pt1X, pt1Y = pt1  # bottom left
            pt2X, pt2Y = pt2  # top left
            pt3X, pt3Y = pt3  # top right
            pt4X, pt4Y = pt4  # bottom right
            width, height = dimensions
            italicAngle = 0
            if self.w.useItalic.get():
                italicAngle = g.getParent().info.italicAngle or 0
            g.prepareUndo()
            #if self.w.viewX.get():
            g.addGuide((pt1X, pt1Y), 90 + italicAngle)
            g.addGuide((pt3X, pt3Y), 90 + italicAngle)
            #if self.w.viewY.get():
            g.addGuide((pt1X, pt1Y), 0)
            g.addGuide((pt3X, pt3Y), 0)
            g.performUndo()

    def updateView(self, sender=None):
        UpdateCurrentGlyphView()
#import outlineTestPen
#reload(outlineTestPen)
from outlineTestPen import OutlineTestPen
from lib.tools.defaults import getDefault

options = {
    "extremum_calculate_badness": True,
    "fractional_ignore_point_zero": True,
    
    "extremum_ignore_badness_below": 0,
    "smooth_connection_max_distance": 4,
    "collinear_vectors_max_distance": 2,
    "semi_hv_vectors_min_distance": 30,
    "zero_handles_max_distance": 0,
    
    "grid_length": getDefault('glyphViewRoundValues'),
}

def run_test(font, glyphnames):
    selection = []
    otp = OutlineTestPen(CurrentFont(), options)
    for n in glyphnames:
        otp.errors = []
        g = font[n]
        g.drawPoints(otp)
        if otp.errors:
            selection.append(g.name)
    font.selection = selection

font = CurrentFont()
glyphnames = CurrentFont().keys()
Example #25
0
 def update_charset_selection(self):
     if env == "robofont":
         self.charsets = getDefault("charsets")
     else:
         self.charsets = {}
     self.w.charset_selection.setItems(sorted(self.charsets.keys()))
Example #26
0
MASTER_COLOR = (45 / 255., 90 / 255., 150 / 255.)
SUB_COLOR = (180 / 255., 240 / 255., 170 / 255.)
BLACK_COLOR = (0, 0, 0)

# glyph lib key
PLUGIN_KEY = 'broadNib'
bodySizeCaption = 9

# component heights
CheckBoxHeight = 18
TextBoxHeight = 14
EditTextHeight = 19
SquareButtonHeight = 19

# colors
LIGHT_YELLOW = getDefault('glyphViewPreviewBackgroundColor')


### Extra functions
def robofabRect(glyph, x, y, width, height):
    """custom rect routine robofab-flavour code, this is used for expansion"""
    x1, y1 = x, y - height / 2.
    x2, y2 = x + width / 2., y
    x3, y3 = x, y + height / 2.
    x4, y4 = x - width / 2., y

    pen = glyph.getPen()
    pen.moveTo((x1, y1))
    pen.lineTo((x2, y2))
    pen.lineTo((x3, y3))
    pen.lineTo((x4, y4))