diff --git a/ShowPathArea.glyphsReporter/Contents/Info.plist b/ShowPathArea.glyphsReporter/Contents/Info.plist new file mode 100644 index 0000000..ff1a886 --- /dev/null +++ b/ShowPathArea.glyphsReporter/Contents/Info.plist @@ -0,0 +1,90 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDisplayName + ShowPathArea + CFBundleExecutable + ShowPathArea + CFBundleIdentifier + org.simon-cozens.ShowPathArea + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ShowPathArea + CFBundlePackageType + BNDL + CFBundleSignature + ???? + CFBundleVersion + 4 + CFBundleShortVersionString + 1.1.1 + UpdateFeedURL + + productPageURL + + LSHasLocalizedDisplayName + + NSAppleScriptEnabled + + NSHumanReadableCopyright + Copyright, by Simon Cozens, 2015 + NSMainNibFile + MainMenu + NSPrincipalClass + ShowPathArea + PyMainFileNames + + __boot__ + + PyOptions + + alias + + argv_emulation + + no_chdir + + optimize + 0 + prefer_ppc + + site_packages + + use_pythonpath + + + PyResourcePackages + + lib/python2.6 + lib/python2.6/lib-dynload + lib/python2.6/site-packages.zip + lib/python26.zip + + PyRuntimeLocations + + @executable_path/../Frameworks/Python.framework/Versions/2.6/Python + /System/Library/Frameworks/Python.framework/Versions/2.6/Python + + PythonInfoDict + + PythonExecutable + /usr/bin/python2.6 + PythonLongVersion + 2.6.7 (r267:88850, Oct 11 2012, 20:15:00) +[GCC 4.2.1 Compatible Apple Clang 4.0 (tags/Apple/clang-418.0.60)] + PythonShortVersion + 2.6 + py2app + + template + bundle + version + 0.6.3 + + + + diff --git a/ShowPathArea.glyphsReporter/Contents/MacOS/ShowPathArea b/ShowPathArea.glyphsReporter/Contents/MacOS/ShowPathArea new file mode 100755 index 0000000..b21f0e4 Binary files /dev/null and b/ShowPathArea.glyphsReporter/Contents/MacOS/ShowPathArea differ diff --git a/ShowPathArea.glyphsReporter/Contents/MacOS/python b/ShowPathArea.glyphsReporter/Contents/MacOS/python new file mode 120000 index 0000000..c84e063 --- /dev/null +++ b/ShowPathArea.glyphsReporter/Contents/MacOS/python @@ -0,0 +1 @@ +/System/Library/Frameworks/Python.framework/Versions/2.6/bin/python \ No newline at end of file diff --git a/ShowPathArea.glyphsReporter/Contents/PkgInfo b/ShowPathArea.glyphsReporter/Contents/PkgInfo new file mode 100644 index 0000000..19a9cf6 --- /dev/null +++ b/ShowPathArea.glyphsReporter/Contents/PkgInfo @@ -0,0 +1 @@ +BNDL???? \ No newline at end of file diff --git a/ShowPathArea.glyphsReporter/Contents/Resources/ShowPathArea.py b/ShowPathArea.glyphsReporter/Contents/Resources/ShowPathArea.py new file mode 100755 index 0000000..7f90ce5 --- /dev/null +++ b/ShowPathArea.glyphsReporter/Contents/Resources/ShowPathArea.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python +# encoding: utf-8 +import objc +from Foundation import * +from AppKit import * +import sys, os, re +import math + +MainBundle = NSBundle.mainBundle() +path = MainBundle.bundlePath() + "/Contents/Scripts" +if not path in sys.path: + sys.path.append( path ) + +import GlyphsApp + +GlyphsReporterProtocol = objc.protocolNamed( "GlyphsReporter" ) + +class ShowPathArea ( NSObject, GlyphsReporterProtocol ): + + def init( self ): + return self + + def interfaceVersion( self ): + return 1 + + def title( self ): + return "Path Area" + + def keyEquivalent( self ): + return None + + def modifierMask( self ): + return 0 + + def drawForegroundForLayer_( self, Layer ): + pass + + def drawPathArea( self, Layer ): + Glyph = Layer.parent + Font = Glyph.parent + selectedLayers = Font.selectedLayers + + for thisLayer in selectedLayers: + for thisPath in thisLayer.paths: + if thisPath.closed: + area = 0 + for s in thisPath.segments: + area += self.segmentArea(s) + self.drawTextAtPoint( u"%d" % abs(area), (thisPath.nodes[0].position.x - 5, thisPath.nodes[0].position.y + 5) ) + + def segmentArea(self, s): + if len(s) == 4: + xa, ya = s[0].x, s[0].y/20 + xb, yb = s[1].x, s[1].y/20 + xc, yc = s[2].x, s[2].y/20 + xd, yd = s[3].x, s[3].y/20 + else: + xa, ya = s[0].x, s[0].y/20 + xb, yb = xa, ya + xc, yc = s[1].x, s[1].y/20 + xd, yd = xc, yc + return (xb-xa)*(10*ya + 6*yb + 3*yc + yd) + (xc-xb)*( 4*ya + 6*yb + 6*yc + 4*yd) +(xd-xc)*( ya + 3*yb + 6*yc + 10*yd) + + def drawBackgroundForLayer_( self, Layer ): + try: + self.drawPathArea( Layer ) + except Exception as e: + self.logToConsole( "drawBackgroundForLayer_: %s" % str(e) ) + + def drawBackgroundForInactiveLayer_( self, Layer ): + pass + + def drawTextAtPoint( self, text, textPosition, fontSize=10.0, fontColor=NSColor.colorWithCalibratedRed_green_blue_alpha_( 1, 0, .5, 1 ) ): + """ + Use self.drawTextAtPoint( "blabla", myNSPoint ) to display left-aligned text at myNSPoint. + """ + try: + glyphEditView = self.controller.graphicView() + currentZoom = self.getScale() + fontAttributes = { + NSFontAttributeName: NSFont.labelFontOfSize_( fontSize/currentZoom ), + NSForegroundColorAttributeName: fontColor } + displayText = NSAttributedString.alloc().initWithString_attributes_( text, fontAttributes ) + textAlignment = 2 # top left: 6, top center: 7, top right: 8, center left: 3, center center: 4, center right: 5, bottom left: 0, bottom center: 1, bottom right: 2 + glyphEditView.drawText_atPoint_alignment_( displayText, textPosition, textAlignment ) + except Exception as e: + self.logToConsole( "drawTextAtPoint: %s" % str(e) ) + + def needsExtraMainOutlineDrawingForInactiveLayer_( self, Layer ): + return True + + def getHandleSize( self ): + """ + Returns the current handle size as set in user preferences. + Use: self.getHandleSize() / self.getScale() + to determine the right size for drawing on the canvas. + """ + try: + Selected = NSUserDefaults.standardUserDefaults().integerForKey_( "GSHandleSize" ) + if Selected == 0: + return 5.0 + elif Selected == 2: + return 10.0 + else: + return 7.0 # Regular + except Exception as e: + self.logToConsole( "getHandleSize: HandleSize defaulting to 7.0. %s" % str(e) ) + return 7.0 + + def getScale( self ): + """ + self.getScale() returns the current scale factor of the Edit View UI. + Divide any scalable size by this value in order to keep the same apparent pixel size. + """ + try: + return self.controller.graphicView().scale() + except: + self.logToConsole( "Scale defaulting to 1.0" ) + return 1.0 + + def setController_( self, Controller ): + """ + Use self.controller as object for the current view controller. + """ + try: + self.controller = Controller + except Exception as e: + self.logToConsole( "Could not set controller" ) + + def logToConsole( self, message ): + """ + The variable 'message' will be passed to Console.app. + Use self.logToConsole( "bla bla" ) for debugging. + """ + myLog = "Show %s plugin:\n%s" % ( self.title(), message ) + NSLog( myLog ) diff --git a/ShowPathArea.glyphsReporter/Contents/Resources/__boot__.py b/ShowPathArea.glyphsReporter/Contents/Resources/__boot__.py new file mode 100644 index 0000000..371c0a3 --- /dev/null +++ b/ShowPathArea.glyphsReporter/Contents/Resources/__boot__.py @@ -0,0 +1,47 @@ +# def _site_packages(): +# import site, sys, os +# paths = [] +# prefixes = [sys.prefix] +# if sys.exec_prefix != sys.prefix: +# prefixes.append(sys.exec_prefix) +# for prefix in prefixes: +# if prefix == sys.prefix: +# paths.append(os.path.join("/Library/Python", sys.version[:3], "site-packages")) +# paths.append(os.path.join(sys.prefix, "Extras", "lib", "python")) +# else: +# paths.append(os.path.join(prefix, 'lib', 'python' + sys.version[:3], 'site-packages')) +# if os.path.join('.framework', '') in os.path.join(sys.prefix, ''): +# home = os.environ.get('HOME') +# if home: +# paths.append(os.path.join(home, 'Library', 'Python', sys.version[:3], 'site-packages')) +# +# # Workaround for a misfeature in setuptools: easy_install.pth places +# # site-packages way too early on sys.path and that breaks py2app bundles. +# # NOTE: this hacks into an undocumented feature of setuptools and +# # might stop to work without warning. +# sys.__egginsert = len(sys.path) +# +# for path in paths: +# site.addsitedir(path) +# +# _site_packages() +# +# def _path_inject(): +# import sys +# sys.path[:0] = sys.path[0] +# +# _path_inject() + +def _run(*scripts): + global __file__ + import os, sys# , site + sys.frozen = 'macosx_plugin' + base = os.environ['RESOURCEPATH'] + # site.addsitedir(base) + # site.addsitedir(os.path.join(base, 'Python', 'site-packages')) + for script in scripts: + path = os.path.join(base, script) + __file__ = path + execfile(path, globals(), globals()) + +_run('ShowPathArea.py') diff --git a/ShowPathArea.glyphsReporter/Contents/Resources/__error__.sh b/ShowPathArea.glyphsReporter/Contents/Resources/__error__.sh new file mode 100755 index 0000000..b3fc73d --- /dev/null +++ b/ShowPathArea.glyphsReporter/Contents/Resources/__error__.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# +# This is the default bundletemplate error script +# Note that this DOES NOT present a GUI dialog, because +# it has no output on stdout, and has a return value of 0. +# +if ( test -n "$2" ) ; then + echo "[$1] Unexpected Exception:" 1>&2 + echo "$2: $3" 1>&2 +else + echo "[$1] Could not find a suitable Python runtime" 1>&2 +fi diff --git a/ShowPathArea.glyphsReporter/Contents/Resources/site.py b/ShowPathArea.glyphsReporter/Contents/Resources/site.py new file mode 100644 index 0000000..889eb41 --- /dev/null +++ b/ShowPathArea.glyphsReporter/Contents/Resources/site.py @@ -0,0 +1,130 @@ +""" +Append module search paths for third-party packages to sys.path. + +This is stripped down and customized for use in py2app applications +""" + +import sys +# os is actually in the zip, so we need to do this here. +# we can't call it python24.zip because zlib is not a built-in module (!) +_libdir = '/lib/python' + sys.version[:3] +_parent = '/'.join(__file__.split('/')[:-1]) +if not _parent.endswith(_libdir): + _parent += _libdir +sys.path.append(_parent + '/site-packages.zip') + +# Stuffit decompresses recursively by default, that can mess up py2app bundles, +# add the uncompressed site-packages to the path to compensate for that. +sys.path.append(_parent + '/site-packages') + +import os +try: + basestring +except NameError: + basestring = str + +def makepath(*paths): + dir = os.path.abspath(os.path.join(*paths)) + return dir, os.path.normcase(dir) + +for m in sys.modules.values(): + f = getattr(m, '__file__', None) + if isinstance(f, basestring) and os.path.exists(f): + m.__file__ = os.path.abspath(m.__file__) +del m + +# This ensures that the initial path provided by the interpreter contains +# only absolute pathnames, even if we're running from the build directory. +L = [] +_dirs_in_sys_path = {} +dir = dircase = None # sys.path may be empty at this point +for dir in sys.path: + # Filter out duplicate paths (on case-insensitive file systems also + # if they only differ in case); turn relative paths into absolute + # paths. + dir, dircase = makepath(dir) + if not dircase in _dirs_in_sys_path: + L.append(dir) + _dirs_in_sys_path[dircase] = 1 +sys.path[:] = L +del dir, dircase, L +_dirs_in_sys_path = None + +def _init_pathinfo(): + global _dirs_in_sys_path + _dirs_in_sys_path = d = {} + for dir in sys.path: + if dir and not os.path.isdir(dir): + continue + dir, dircase = makepath(dir) + d[dircase] = 1 + +def addsitedir(sitedir): + global _dirs_in_sys_path + if _dirs_in_sys_path is None: + _init_pathinfo() + reset = 1 + else: + reset = 0 + sitedir, sitedircase = makepath(sitedir) + if not sitedircase in _dirs_in_sys_path: + sys.path.append(sitedir) # Add path component + try: + names = os.listdir(sitedir) + except os.error: + return + names.sort() + for name in names: + if name[-4:] == os.extsep + "pth": + addpackage(sitedir, name) + if reset: + _dirs_in_sys_path = None + +def addpackage(sitedir, name): + global _dirs_in_sys_path + if _dirs_in_sys_path is None: + _init_pathinfo() + reset = 1 + else: + reset = 0 + fullname = os.path.join(sitedir, name) + try: + f = open(fullname) + except IOError: + return + while 1: + dir = f.readline() + if not dir: + break + if dir[0] == '#': + continue + if dir.startswith("import"): + exec(dir) + continue + if dir[-1] == '\n': + dir = dir[:-1] + dir, dircase = makepath(sitedir, dir) + if not dircase in _dirs_in_sys_path and os.path.exists(dir): + sys.path.append(dir) + _dirs_in_sys_path[dircase] = 1 + if reset: + _dirs_in_sys_path = None + + +#sys.setdefaultencoding('utf-8') + +# +# Run custom site specific code, if available. +# +try: + import sitecustomize +except ImportError: + pass + +# +# Remove sys.setdefaultencoding() so that users cannot change the +# encoding after initialization. The test for presence is needed when +# this module is run as a script, because this code is executed twice. +# +if hasattr(sys, "setdefaultencoding"): + del sys.setdefaultencoding