diff --git a/.github/workflows/validate_build.yml b/.github/workflows/validate_build.yml new file mode 100644 index 0000000..98b0634 --- /dev/null +++ b/.github/workflows/validate_build.yml @@ -0,0 +1,12 @@ +name: Validate and Build the Extension +on: + push + +jobs: + validate_and_build: + runs-on: ubuntu-latest + steps: + - name: Validate and Build + uses: typemytype/roboFont-Extension-action@v0.1.0 + with: + autotagging: true \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 4c35047..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2023 roboDocs - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git "a/StemAnalyzer.roboFontExt/Icon\r" "b/StemAnalyzer.roboFontExt/Icon\r" deleted file mode 100644 index e69de29..0000000 diff --git a/StemAnalyzer.roboFontExt/info.plist b/StemAnalyzer.roboFontExt/info.plist deleted file mode 100644 index 9202cd2..0000000 --- a/StemAnalyzer.roboFontExt/info.plist +++ /dev/null @@ -1,37 +0,0 @@ - - - - - addToMenu - - - path - StemAnalyzer.py - preferredName - StemAnalyzer - shortKey - - - - developer - Jérémie Hornus and Connor Davenport - developerURL - https://github.com/roboDocs/StemAnalyzer - html - - launchAtStartUp - - mainScript - StemAnalyzer.py - name - StemAnalyzer - requiresVersionMajor - 4 - requiresVersionMinor - 3 - timeStamp - 1696522714.6260459 - version - 1.1.2 - - diff --git a/StemAnalyzer.roboFontExt/resources/icon.png b/StemAnalyzer.roboFontExt/resources/icon.png deleted file mode 100644 index e443cbc..0000000 Binary files a/StemAnalyzer.roboFontExt/resources/icon.png and /dev/null differ diff --git a/StemAnalyzer.roboFontExt/resources/icon.py b/StemAnalyzer.roboFontExt/resources/icon.py deleted file mode 100644 index 591988a..0000000 --- a/StemAnalyzer.roboFontExt/resources/icon.py +++ /dev/null @@ -1,17 +0,0 @@ -newPage(100,100) -fontSize(100) -font("Temporary-Bold") -stroke(0) -fill(.82,.82,.82,1) -text("O",(50, 16),"center") -stroke(1,0,0,1) -fill(.8,1,.2,1) -line((16,50.5),(35,50.5)) -oval(14,48,5,5) -oval(32,48,5,5) -stroke(0,0,1,1) -line((50.5,85),(50.5,74)) -fill(0,1,0,1) -oval(48,85,5,5) -oval(48,74,5,5) -saveImage("icon.png",imageResolution=300) \ No newline at end of file diff --git a/build.yaml b/build.yaml new file mode 100644 index 0000000..86e0ebc --- /dev/null +++ b/build.yaml @@ -0,0 +1,25 @@ +libFolder: source/lib +resourcesFolder: source/resources +htmlFolder: source/html +license: | + MIT License + + Copyright (c) 2023 roboDocs + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. diff --git a/buildExtension.py b/buildExtension.py deleted file mode 100644 index acfd68b..0000000 --- a/buildExtension.py +++ /dev/null @@ -1,97 +0,0 @@ -# build RF extension -# run in RF -import os -from mojo.extensions import ExtensionBundle -from mojo.UI import createModifier - -#modifier = createModifier(command=True, shift=True) -#print(f"({modifier}, ']')") - -# get current folder -basePath = os.path.dirname(__file__) - -# folder with python files -libPath = os.path.join(basePath, 'lib') - -# folder with html files -htmlPath = os.path.join(basePath, 'html') -if not os.path.exists(htmlPath): - htmlPath = None - -# folder with resources -resourcesPath = os.path.join(basePath, 'resources') -if not os.path.exists(resourcesPath): - resourcesPath = None - -# load license text from file -# see http://choosealicense.com/ for more open-source licenses -licensePath = os.path.join(basePath, 'license.txt') -if not os.path.exists(licensePath): - licensePath = None - -# boolean indicating if only .pyc should be included -pycOnly = False - -# name of the compiled extension file -extensionFile = 'StemAnalyzer.roboFontExt' - -# path of the compiled extension -buildPath = basePath -extensionPath = os.path.join(buildPath, extensionFile) - -# initiate the extension builder -B = ExtensionBundle() - -# name of the extension -B.name = "StemAnalyzer" - -# name of the developer -B.developer = 'Jérémie Hornus and Connor Davenport' - -# URL of the developer -B.developerURL = 'https://github.com/roboDocs/StemAnalyzer' - -if resourcesPath: - # extension icon (file path or NSImage) - imagePath = os.path.join(resourcesPath, 'icon.png') - B.icon = imagePath - -# version of the extension -B.version = '1.1.2' - -# should the extension be launched at start-up? -B.launchAtStartUp = False - -# script to be executed when RF starts -B.mainScript = 'StemAnalyzer.py' - -# does the extension contain html help files? -B.html = htmlPath is not None - -# minimum RoboFont version required for this extension -B.requiresVersionMajor = '4' -B.requiresVersionMinor = '3' - -# scripts which should appear in Extensions menu -B.addToMenu = [ - { - 'path' : 'StemAnalyzer.py', - 'preferredName': 'StemAnalyzer', - 'shortKey' : '', - #'shortKey' : (1179648, ']'), - }, -] - -if licensePath: - # license for the extension - with open(licensePath) as license: - B.license = license.read() - -# compile and save the extension bundle -print('building extension...', end=' ') -B.save(extensionPath, libPath=libPath, htmlPath=htmlPath, resourcesPath=resourcesPath, pycOnly=pycOnly) -print('done!') - -# check for problems in the compiled extension -print() -print(B.validationErrors()) diff --git a/info.yaml b/info.yaml new file mode 100644 index 0000000..eb88fcf --- /dev/null +++ b/info.yaml @@ -0,0 +1,13 @@ +name: StemAnalyzer +developer: "Jérémie Hornus and Connor Davenport" +developerURL: https://github.com/roboDocs/StemAnalyzer +launchAtStartUp: false +mainScript: StemAnalyzer.py +version: 1.1.2 +addToMenu: +- path: StemAnalyzer.py + preferredName: StemAnalyzer + shortKey: '' +html: false +requiresVersionMajor: '4' +requiresVersionMinor: '3' diff --git a/lib/StemAnalyzer.py b/lib/StemAnalyzer.py deleted file mode 100644 index 3246d0a..0000000 --- a/lib/StemAnalyzer.py +++ /dev/null @@ -1,483 +0,0 @@ -from mojo.UI import * -from AppKit import * - -import math -import StemAnalyzerModule as module - -from mojo.subscriber import * -import ezui - -minStemY = minStemX = 20 -maxStemY = maxStemX = 400 - -class StemAnalyzerWindow(Subscriber, ezui.WindowController): - - debug = False - - def build(self): - - self.roundTo5 = 1 - self.stemSnapHList = [] - self.stemSnapVList = [] - - self.containers_setup = False - self.glyphsStemsList = [] - - - self.horzColor = (255/255, 68/255, 79/255, 255/255) - self.horzAccent = (255/255, 213/255, 213/255, 255/255) - self.vertAccent = (212/255, 250/255, 236/255, 255/255) - self.vertColor = (0/255, 159/255, 0/255, 255/255) - - - content = """ - *VerticalStack @stemStack - [ ] Round Values to 5 @roundCheckbox - (Analyze Selected Glyphs) @analyzeButton - ----- - Horizontal (Y): - {arrow.up.arrow.down} [__] @horizontalTextField - Vertical (X): - {arrow.left.arrow.right} [__] @verticalTextField - ------ - (Copy to PS StemSnap) @copyButton - """ - - - descriptionData=dict( - stemStack=dict( - width=250, - ), - roundCheckbox=dict( - value=True - ), - horizontalTextField=dict( - valueType="integerList", - ), - verticalTextField=dict( - valueType="integerList", - ), - ) - - self.w = ezui.EZPanel( - title="StemAnalyzer", - content=content, - descriptionData=descriptionData, - controller=self - ) - - def started(self): - # took this method from Ryan Bugden! - self.glyphEditor = CurrentGlyphWindow() - if self.glyphEditor: - self.setUpContainers() - self.drawContent() - self.w.open() - - - def setUpContainers(self): - # took this method from Ryan Bugden! - self.container = self.glyphEditor.extensionContainer( - identifier="com.sansplomb.stemAnalyzer", - location="foreground", - clear=True - ) - self.containers_setup = True - - def glyphEditorWillOpen(self, info): - self.glyphEditor = info["glyphEditor"] - self.setUpContainers() - - def glyphEditorDidOpen(self, info): - self.drawContent() - - def glyphEditorDidSetGlyph(self, info): - # took this method from Ryan Bugden! - if self.containers_setup == True: - self.container.clearSublayers() - self.containers_setup = False - - self.glyph = info["glyph"] - self.glyphEditor = info["glyphEditor"] - self.setUpContainers() - self.drawContent() - - def destroy(self): - self.container.clearSublayers() - - def roundCheckboxCallback(self, sender): - self.roundTo5 = self.w.getItem("roundCheckbox").get() - - def copyButtonCallback(self, sender): - f.info.postscriptStemSnapH = self.stemSnapHList - f.info.postscriptStemSnapV = self.stemSnapVList - - def interpolatePoints(self, a,b,v): - x = a[0] + v * (b[0] - a[0]) - y = a[1] + v * (b[1] - a[1]) - return (x,y) - - def getPointBounds(self,points): - xs = [p.x for p in points] - ys = [p.y for p in points] - x = min(xs) - y = min(ys) - xMax = max(xs) - yMax = max(ys) - w = xMax - x - h = yMax - y - return (x,y,w,h) - - def drawTextAtPoint(self,path,pos,text,mainColor,acctColor): - path.appendTextLineSublayer( - position=pos, - size=(20, 20), - backgroundColor=acctColor, - pointSize=8, - weight="bold", - text=text, - fillColor=mainColor, - horizontalAlignment="center", - verticalAlignment="center", - cornerRadius=6, - padding=(6, 3), - borderWidth=1, - borderColor=mainColor, - ) - - def drawSquiggle(self,path,point1,point2,orientation): - pen = path.getPen() - pen.moveTo((point1.x,point1.y)) - if orientation == "v": - scale = abs(point2.x - point1.x)/2.5 - pen.curveTo( - (self.interpolatePoints((point1.x,point1.y),(point2.x,point2.y),1/3)[0],point1.y+scale), - (self.interpolatePoints((point1.x,point1.y),(point2.x,point2.y),2/3)[0],point2.y-scale), - (point2.x,point2.y)) - if orientation == "h": - scale = abs(point2.y - point1.y)/2.5 - pen.curveTo( - (point1.x+scale,self.interpolatePoints((point1.x,point1.y),(point2.x,point2.y),1/3)[1]), - (point2.x-scale,self.interpolatePoints((point1.x,point1.y),(point2.x,point2.y),2/3)[1]), - (point2.x,point2.y)) - - pen.endPath() - path.setStrokeJoin("round") - - - def drawContent(self): - for gStems in self.glyphsStemsList: - if gStems[0] == CurrentGlyph().name: - valuesListX = [] - for stem in gStems[1]: - startPoint, endPoint = stem[0], stem[1] - startPoint.x = startPoint.x - startPoint.y = startPoint.y - endPoint.x = endPoint.x - endPoint.y = endPoint.y - length = float(stem[2][0]) - - vPathLayer = self.container.appendPathSublayer( - fillColor=None, - strokeColor=self.vertColor, - strokeWidth=2 - ) - self.drawSquiggle(vPathLayer,startPoint,endPoint,"v") - center_x = startPoint.x + (endPoint.x - startPoint.x) * 0.5 - center_y = startPoint.y + (endPoint.y - startPoint.y) * 0.5 - valuesListX.append((center_x, center_y, length)) - - for x, y, lengthValue in valuesListX: - if lengthValue.is_integer(): - t = "%i" - else: - t = "%.2f" - textPath = self.container.appendTextLineSublayer() - self.drawTextAtPoint(textPath, (x,y), f"{t % lengthValue}", self.vertColor, self.vertAccent) - - # ---------------------------------- - # ---------------------------------- - - valuesListY = [] - for stem in gStems[2]: - startPoint, endPoint = stem[0], stem[1] - length = float(stem[2][1]) - - hPathLayer = self.container.appendPathSublayer( - fillColor=None, - strokeColor=self.horzColor, - strokeWidth=2 - ) - self.drawSquiggle(hPathLayer,startPoint,endPoint,"h") - center_x = startPoint.x + (endPoint.x - startPoint.x) * 0.5 - center_y = startPoint.y + (endPoint.y - startPoint.y) * 0.5 - valuesListY.append((center_x, center_y, length)) - - for x, y, lengthValue in valuesListY: - if lengthValue.is_integer(): - t = "%i" - else: - t = "%.2f" - textPath = self.container.appendTextLineSublayer() - self.drawTextAtPoint(textPath, (x,y), f"{t % lengthValue}", self.horzColor, self.horzAccent) - - - - def analyzeButtonCallback(self, sender): - - self.glyphsStemsList = [] - self.stemsValuesXList = [] - self.stemsValuesYList = [] - self.stemSnapHList = [] - self.stemSnapVList = [] - roundedStemsXList = [] - roundedStemsYList = [] - originalStemsXList = [] - originalStemsYList = [] - - self.f = CurrentFont() - if self.f.info.italicAngle != None: - self.ital = - self.f.info.italicAngle - else: - self.ital = 0 - #self.progress = self.startProgress("Preparing") - tickCount = 0 - for g in self.f: - if g.selected: - tickCount += 1 - - #self.progress.setTickCount(tickCount) - #self.progress.update("Analysing Selected Glyphs") - for g in self.f.selectedGlyphs: - self.g_hPoints = make_hPointsList(g) - (self.stemsListX, self.stemsListY) = makeStemsList(self.f, self.g_hPoints, g, self.ital) - if self.roundTo5 == 1: - for stem in self.stemsListX: - roundedStemsXList.append(module.roundbase(stem[2][0], 5)) - for stem in self.stemsListY: - roundedStemsYList.append(module.roundbase(stem[2][1], 5)) - - self.stemsValuesXList = roundedStemsXList - self.stemsValuesYList = roundedStemsYList - self.glyphsStemsList.append((g.name, self.stemsListX, self.stemsListY)) - - else: - for stem in self.stemsListX: - originalStemsXList.append(stem[2][0]) - for stem in self.stemsListY: - originalStemsYList.append(stem[2][1]) - - self.stemsValuesXList = originalStemsXList - self.stemsValuesYList = originalStemsYList - - self.glyphsStemsList.append((g.name, self.stemsListX, self.stemsListY)) - - - valuesXDict = {} - for StemXValue in self.stemsValuesXList: - try: - valuesXDict[StemXValue] += 1 - except KeyError: - valuesXDict[StemXValue] = 1 - valuesYDict = {} - for StemYValue in self.stemsValuesYList: - try: - valuesYDict[StemYValue] += 1 - except KeyError: - valuesYDict[StemYValue] = 1 - - keyValueXList = list(valuesXDict.items()) - keyValueXList = sorted(keyValueXList, reverse=True, key=module.compare) - keyValueXList = keyValueXList[:12] - - keyValueYList = list(valuesYDict.items()) - keyValueYList = sorted(keyValueYList, reverse=True, key=module.compare) - keyValueYList = keyValueYList[:12] - - - for keyValue in keyValueXList: - self.stemSnapVList.append(keyValue[0]) - - self.w.getItem("verticalTextField").set(self.stemSnapVList) - - for keyValue in keyValueYList: - self.stemSnapHList.append(keyValue[0]) - - self.w.getItem("horizontalTextField").set(self.stemSnapHList) - -# ------------------------------ -# ---- classless functions ----- -# ------------------------------ - - -def make_hPointsList(g): - contoursList = [] - hPointsList = [] - for i in range(len(g)): - pointsList = [] - for j in g[i].points: - pointsList.append(j) - contoursList.append(pointsList) - - for contour_index in range(len(contoursList)): - for point_index in range(len(contoursList[contour_index])): - currentPoint = contoursList[contour_index][point_index] - if point_index == 0: - prevPoint = contoursList[contour_index][len(contoursList[contour_index])-1] - else: - prevPoint = contoursList[contour_index][point_index-1] - if point_index == len(contoursList[contour_index]) -1: - nextPoint = contoursList[contour_index][0] - else: - nextPoint = contoursList[contour_index][point_index+1] - - if currentPoint.type != 'offcurve': - directionIN = module.direction(prevPoint, currentPoint) - directionOUT = module.direction(currentPoint, nextPoint) - vectorIN = module.angle(prevPoint, currentPoint) - vectorOUT = module.angle(currentPoint, nextPoint) - - hPoint = (currentPoint, contour_index, point_index, directionIN, directionOUT, vectorIN, vectorOUT) - hPointsList.append(hPoint) - - return hPointsList - -def getColor(point1, point2, g): - hasSomeBlack = False - hasSomeWhite = False - color = '' - - if abs(point2.x - point1.x) < maxStemX or abs(point2.y - point1.y) < maxStemY: - hypothLength = int(module.hypothenuse(point1, point2)) - for j in range(1, hypothLength-1): - cp_x = point1.x + ((j)/hypothLength)*(point2.x - point1.x) - cp_y = point1.y + ((j)/hypothLength)*(point2.y - point1.y) - if g.pointInside((cp_x, cp_y)): - hasSomeBlack = True - else: - hasSomeWhite = True - if hasSomeBlack and hasSomeWhite: - break - - if hasSomeBlack and hasSomeWhite: - color = 'Gray' - elif hasSomeBlack: - color = 'Black' - else: - color = 'White' - return color - - -def makeStemsList(f, g_hPoints, g, italicAngle): - stemsListX_temp = [] - stemsListY_temp = [] - stemsListX = [] - stemsListY = [] - for source_hPoint in range(len(g_hPoints)): - for target_hPoint in range(len(g_hPoints)): - sourcePoint = g_hPoints[source_hPoint][0] - targetPoint = g_hPoints[target_hPoint][0] - directionIn_source = g_hPoints[source_hPoint][3] - directionOut_source = g_hPoints[source_hPoint][4] - directionIn_target = g_hPoints[target_hPoint][3] - directionOut_target = g_hPoints[target_hPoint][4] - angleIn_source = g_hPoints[source_hPoint][5] - angleOut_source = g_hPoints[source_hPoint][6] - angleIn_target = g_hPoints[target_hPoint][5] - angleOut_target = g_hPoints[target_hPoint][6] - color = getColor(sourcePoint, targetPoint, g) - if color == 'Black': - c_distance = module.distance(sourcePoint, targetPoint) - stem = (sourcePoint, targetPoint, c_distance) - hypoth = module.hypothenuse(sourcePoint, targetPoint) - ## if Source and Target are almost aligned - # closeAngle(angleIn_source, angleIn_target) or closeAngle(angleOut_source, angleOut_target) or - if module.closeAngle(angleIn_source, angleOut_target) or module.closeAngle(angleOut_source, angleIn_target): - ## if Source and Target have opposite direction - if module.opposite(directionIn_source, directionIn_target) or module.opposite(directionIn_source, directionOut_target) or module.opposite(directionOut_source, directionIn_target): - - ## if they are horizontal, treat the stem on the Y axis - if (module.isHorizontal(angleIn_source) or module.isHorizontal(angleOut_source)) and (module.isHorizontal(angleIn_target) or module.isHorizontal(angleOut_target)): - if (minStemY - 20*(minStemY/100) < c_distance[1] < maxStemY + 20*(maxStemY/100)) and (minStemY - 20*(minStemY/100) <= hypoth <= maxStemY + 20*(maxStemY/100)): - stemsListY_temp.append(stem) - - ## if they are vertical, treat the stem on the X axis - if (module.isVertical(angleIn_source) or module.isVertical(angleOut_source)) and (module.isVertical(angleIn_target) or module.isVertical(angleOut_target)): - - if (minStemX - 20*(minStemX/100) <= c_distance[0] <= maxStemX + 20*(maxStemX/100)) and (minStemX - 20*(minStemX/100)<= hypoth <= maxStemX + 20*(maxStemX/100)): - stemsListX_temp.append(stem) - # avoid duplicates, filters temporary stems - yList = [] - for stem in stemsListY_temp: - def pred0(y): - return module.approxEqual(stem[0].y, y) - def pred1(y): - return module.approxEqual(stem[1].y, y) - if not module.exists(yList, pred0) or not module.exists(yList, pred1): - stemsListY.append(stem) - yList.append(stem[0].y) - yList.append(stem[1].y) - - xList = [] - for stem in stemsListX_temp: - (preRot0x, preRot0y) = module.rotated(stem[0], italicAngle) - (preRot1x, preRot1y) = module.rotated(stem[1], italicAngle) - def pred0(x): - #print(preRot0x, x) - return module.approxEqual(preRot0x, x) - def pred1(x): - #print(preRot1x, x) - return module.approxEqual(preRot1x, x) - if not module.exists(xList,pred0) or not module.exists(xList,pred1): - stemsListX.append(stem) - xList.append(preRot0x) - xList.append(preRot1x) - - return (stemsListX, stemsListY) - -# ------------------------------ -# ---- fix min and max vals ---- -# ------------------------------ - -f = CurrentFont() -if f: - if f.info.italicAngle != None: - ital = - f.info.italicAngle - else: - ital = 0 - - if "O" in f.keys(): - g = f['O'] - O_hPoints = make_hPointsList(g) - (O_stemsListX, O_stemsListY) = makeStemsList(f, O_hPoints, g, ital) - Xs = [] - for i in O_stemsListX: - Xs.append(i[2][0]) - maxX = max(Xs) - maxStemX = maxX + 10*(maxX/100) - maxStemY = maxX + 10*(maxX/100) - else: - print("WARNING: glyph 'O' missing") - - - if "o" in f.keys(): - g = f['o'] - if not g: - print("WARNING: glyph 'o' missing") - o_hPoints = make_hPointsList(g) - (o_stemsListX, o_stemsListY) = makeStemsList(f, o_hPoints, g, ital) - Ys = [] - for i in o_stemsListY: - Ys.append(i[2][1]) - minY = min(Ys) - minStemX = minY - 30*(minY/100) - minStemY = minY - 30*(minY/100) - else: - print("WARNING: glyph 'o' missing") -# ------------------------------ -# ------------------------------ -# ------------------------------ - - -StemAnalyzerWindow() - \ No newline at end of file diff --git a/lib/StemAnalyzerModule.py b/lib/StemAnalyzerModule.py deleted file mode 100644 index d69bd4f..0000000 --- a/lib/StemAnalyzerModule.py +++ /dev/null @@ -1,108 +0,0 @@ -import math - -def direction(point1, point2): - direction_x = 4 - direction_y = 4 - if point1.x < point2.x: - # Direction is RIGHT - direction_x = 1 - elif point1.x > point2.x: - # Direction is LEFT - direction_x = -1 - else: - # Direction is NONE - direction_x = 4 - - if point1.y < point2.y: - # Direction is UP - direction_y = 1 - elif point1.y > point2.y: - # Direction is DOWN - direction_y = -1 - else: - # Direction is NONE - direction_y = 4 - return (direction_x, direction_y) - - -def rotated(point, angle): - x = point.x - y = point.y - angle = (math.radians(angle)) - cosa = math.cos(angle) - sina = math.sin(angle) - rotatedPoint_x = int(cosa*x - sina*y) - rotatedPoint_y = int(sina*x + cosa*y) - return (rotatedPoint_x, rotatedPoint_y) - - -def angle(point1, point2): - return math.atan2(point2.y - point1.y, point2.x - point1.x) / math.pi * 180 - -def shearFactor(angle): - # find the shearFactor r with a given angle - r = math.tan(math.radians(angle)) - return r - -def distance(point1, point2): - return (abs(point1.x - point2.x), abs(point1.y - point2.y)) - -def hypothenuse(point1, point2): - return math.sqrt(distance(point1, point2)[0]*distance(point1, point2)[0] + distance(point1, point2)[1]*distance(point1, point2)[1]) - -def closeAngle(angle1, angle2): - diff = angle1 - angle2 - while diff >= 90: - diff -= 180 - while diff < -90: - diff += 180 - return (abs(diff)<5) - -def approxEqual(a1, a2): - #return abs(a1 - a2) < 10*(abs(a1)/100) - return ( abs(a1 - a2) <= 10*(abs(a1)/100) ) - -def opposite(direction1, direction2): - isOpposite = False - LR1 = direction1[0] - UD1 = direction1[1] - LR2 = direction2[0] - UD2 = direction2[1] - if LR1 + LR2 == 0: - isOpposite = True - if UD1 + UD2 == 0: - isOpposite = True - return isOpposite - -def isVertical(vector): - vector = abs(vector) - if ((65 < vector) and (vector < 115)): - return True - else: - return False - -def isHorizontal(vector): - vector = abs(vector) - if ((0 <= vector) and (vector <= 45)) or ((135 <= vector) and (vector <= 180)): - return True - else: - return False - -#True si il existe un element de la liste l pour lequel la fonction p renvoi True (on dit que le predicat p est vrai sur cet element) -def exists(l, p): - for e in l: - if p(e): - return True - return False - -def sheared(point, angle): - r = shearFactor(angle) - return (point.x + r*point.y, point.y) - -def roundbase(x, base): - return int(base * round(float(x)/base)) - -def compare(item): - return item[1] - item[0] - -###### \ No newline at end of file diff --git a/StemAnalyzer.roboFontExt/lib/StemAnalyzer.py b/source/lib/StemAnalyzer.py similarity index 100% rename from StemAnalyzer.roboFontExt/lib/StemAnalyzer.py rename to source/lib/StemAnalyzer.py diff --git a/StemAnalyzer.roboFontExt/lib/StemAnalyzerModule.py b/source/lib/StemAnalyzerModule.py similarity index 100% rename from StemAnalyzer.roboFontExt/lib/StemAnalyzerModule.py rename to source/lib/StemAnalyzerModule.py diff --git a/Resources/icon.png b/source/resources/icon.png similarity index 100% rename from Resources/icon.png rename to source/resources/icon.png diff --git a/Resources/icon.py b/source/resources/icon.py similarity index 100% rename from Resources/icon.py rename to source/resources/icon.py