diff --git a/glyphs/common-shapes.ptl b/glyphs/common-shapes.ptl index ae82f53..fc1e5c3 100644 --- a/glyphs/common-shapes.ptl +++ b/glyphs/common-shapes.ptl @@ -284,9 +284,10 @@ define [halfXStrand _leftx lefty rightx righty turn straight tension _fine] : gl widths.center flat leftx lefty [heading [if (lefty < righty) UPWARD DOWNWARD]] curl leftx turnyleft [heading [if (lefty < righty) UPWARD DOWNWARD]] - quadcontrols 0 ((cyleft - turnyleft) / (straightyleft - turnyleft)) 4 unimportant + quadcontrols 0 ((cyleft - turnyleft) / (straightyleft - turnyleft)) 4 flat straightxleft straightyleft curl rightx righty + end [function : set this.unfair true] define [xStrand _leftx lefty _rightx righty turn straight tension] : glyph-construction diff --git a/glyphs/letters-unified-basic.ptl b/glyphs/letters-unified-basic.ptl index 20a2ad1..8fd3413 100644 --- a/glyphs/letters-unified-basic.ptl +++ b/glyphs/letters-unified-basic.ptl @@ -568,14 +568,14 @@ symbol-block 'W' include : dispiro widths.rhs WShape.fine - straight.down.start (MIDDLE + WShape.fine / 2 * HVCONTRAST) wheight [heading DOWNWARD] - quadcontrols 0 0.1 6 unimportant + flat (MIDDLE + WShape.fine / 2 * HVCONTRAST) wheight [heading DOWNWARD] + #quadcontrols 0 0.1 6 unimportant g4 (WShape.m1 + WShape.fine / 2 * HVCONTRAST) 0 [widths.rhs WShape.fine] include : dispiro widths.lhs WShape.fine - straight.down.start (MIDDLE - WShape.fine / 2 * HVCONTRAST) wheight [heading DOWNWARD] - quadcontrols 0 0.1 6 unimportant - g4 (WShape.m2 - WShape.fine / 2 * HVCONTRAST) 0 [widths.lhs WShape.fine] + flat (MIDDLE - WShape.fine / 2 * HVCONTRAST) wheight [heading DOWNWARD] + #quadcontrols 0 0.1 6 unimportant + curl (WShape.m2 - WShape.fine / 2 * HVCONTRAST) 0 [widths.lhs WShape.fine] # bottom cap 2 start-from (WShape.m2 + WShape.fine / 2 * HVCONTRAST) 0 @@ -650,8 +650,8 @@ symbol-block 'X' assign-unicode 'X' include capitalMarks - include : xStrand SB 0 RIGHTSB CAP 0.1 0.4 0.28 - include : xStrand SB CAP RIGHTSB 0 0.1 0.4 0.28 + include : xStrand SB 0 RIGHTSB CAP 0.1 0.4 0.3 + include : xStrand SB CAP RIGHTSB 0 0.1 0.4 0.3 include : AIHSerifs CAP alias 'Chi' 0x3A7 'X' alias 'cyrHa' 0x425 'X' @@ -661,8 +661,8 @@ symbol-block 'X' assign-unicode 'x' local TURN (XH * 0.1) - include : xStrand SB 0 RIGHTSB XH 0.02 0.4 0.14 - include : xStrand SB XH RIGHTSB 0 0.02 0.4 0.14 + include : xStrand SB 0 RIGHTSB XH 0.02 0.45 0.15 + include : xStrand SB XH RIGHTSB 0 0.02 0.45 0.15 include : AIHSerifs XH create-glyph 'chi' : glyph-construction @@ -670,12 +670,12 @@ symbol-block 'X' assign-unicode 0x3C7 include pMarks - include : xStrand SB DESCENDER RIGHTSB XH 0.05 0.4 0.1 - include : xStrand SB XH RIGHTSB DESCENDER 0.05 0.4 0.1 + include : xStrand SB DESCENDER RIGHTSB XH 0.05 0.45 0.15 + include : xStrand SB XH RIGHTSB DESCENDER 0.05 0.45 0.15 alias 'cyrha' 0x445 'x' - composite nothing glyphs.cyrHa [CyrDescender RIGHTSB] [into-unicode 0x4B2] - composite nothing glyphs.cyrha [CyrDescender RIGHTSB] [into-unicode 0x4B3] + composite 'cyrHadescender' glyphs.cyrHa [CyrDescender RIGHTSB] [into-unicode 0x4B2] + composite 'cyrhadescender' glyphs.cyrha [CyrDescender RIGHTSB] [into-unicode 0x4B3] ### Y symbol-block 'Y' @@ -758,6 +758,7 @@ symbol-block 'y' curl yrstroker (top - ds) [heading DOWNWARD] quadcontrols 0 dpy1 16 yBaseKnots top bottom + end [function : set this.unfair true] include : dispiro widths.center flat (WIDTH - yrstroker) top [heading DOWNWARD] @@ -765,6 +766,7 @@ symbol-block 'y' quadcontrols 0 dpy1 16 flat [mix (WIDTH - yrstrokel) (WIDTH - yrstroker) px1] [mix (bottom + ds) (top - ds) py1] curl MIDDLE [mix (bottom + ds2) (top - ds) [linreg (1 - px2) (1 - py2) px1 py1 ((MIDDLE - yrstrokel) / (yrstroker - yrstrokel))]] [widths.center (STROKE * yshrink)] + end [function : set this.unfair true] if SLAB : begin include : AIVSerifs top create-glyph 'y.upright' : glyph-construction @@ -803,6 +805,7 @@ symbol-block 'y' widths.center straight.left.start ([mix yrstrokel yrstroker px1] + HOOKX) (XH - HALFSTROKE) yBaseKnots XH DESCENDER + end [function : set this.unfair true] create-glyph 'cyrU' : glyph-construction assign-unicode 0x423 @@ -1559,12 +1562,13 @@ define {CShape} : symbol-block 'C' hookstart XH flat.ai (SB + OX) (XH - SMALLSMOOTHA) curl.ai (SB + OX) SMALLSMOOTHB - alsothru 0.4 0.8 - g4 MIDDLE 0 - alsothru 0.5 0.135 - g4.down.mid (RIGHTSB - STROKE * HVCONTRAST + OX) [mix DESCENDER STROKE 0.5] [heading DOWNWARD] arcvh - straight.left.end (RIGHTSB - HOOKX + OX) (DESCENDER + STROKE) [heading LEFTWARD] + g4 (MIDDLE + CORRECTION_OMIDS) 0 + alsothru 0.5 0.1353 + g4.down.mid (RIGHTSB - STROKE * HVCONTRAST + OX) [mix DESCENDER STROKE [linreg 18 0.5 126 0.49 STROKE]] [heading DOWNWARD] + arcvh + flat (RIGHTSB - HOOKX + OX) (DESCENDER + STROKE) [heading LEFTWARD] + curl [Math.min (RIGHTSB - STROKE * HVCONTRAST * 1.5) (RIGHTSB - HOOKX + OX - 1)] (DESCENDER + STROKE) [heading LEFTWARD] list CShape ### G @@ -2297,6 +2301,7 @@ define {LongSShape} : symbol-block 'f' widths.center flat (MIDDLE - FBALANCE) 0 [heading UPWARD] curl (MIDDLE - FBALANCE) (CAP - FHOOK) + arcvh straight.right.end (MIDDLE - FBALANCE + HOOKX) (CAP - HALFSTROKE - fovershoot) if SLAB : begin include : CenterBottomSerif (MIDDLE - FBALANCE) 0 JUT @@ -2417,7 +2422,7 @@ define {LongSShape} : symbol-block 'f' symbol-block 'compatibility ligatures' local shift (-(WIDTH * 0.055 + SB * 0.5)) local barr RIGHTSB - local hbarleft (SB + shift + STROKE * [if para.isItalic 0.5 0.25]) + local hbarleft (SB + shift + STROKE * [if para.slantAngle 0.5 0.25]) create-glyph 'f_i' : glyph-construction assign-unicode 0xFB01 @@ -2436,12 +2441,15 @@ define {LongSShape} : symbol-block 'f' local m : MIDDLE - JBALANCE - HALFSTROKE * HVCONTRAST + shift include : dispiro widths.rhs - flat m 0 + flat m 0 [heading UPWARD] curl m (CAP - SMOOTHA) hookend (CAP - O) g4 (barr + OXHOOK) (CAP - HOOK) include : VBarRight barr 0 (CAP - HOOK) - include : HBarTop hbarleft [mix SB barr 0.6] fbar + include : dispiro + widths.rhs + flat ([Math.min (m - STROKE * 0.3) hbarleft] - TANSLANT * HALFSTROKE) fbar + curl ([mix SB barr 0.6] - TANSLANT * HALFSTROKE) fbar if SLAB : begin include : tagged 'serifLB' : CenterBottomSerif (m + HALFSTROKE * HVCONTRAST + RBALANCE * 0.35) 0 (JUT + RBALANCE * 0.65) include : tagged 'serifRB' : CenterBottomSerif (barr - HALFSTROKE * HVCONTRAST) 0 JUT diff --git a/glyphs/letters-unified-extended.ptl b/glyphs/letters-unified-extended.ptl index af3991e..86dd78c 100644 --- a/glyphs/letters-unified-extended.ptl +++ b/glyphs/letters-unified-extended.ptl @@ -287,10 +287,10 @@ symbol-block 'zeta and xi' bezcontrols 0.7 0.35 1 0.64 12 g4.down.mid (SB + STROKE * HVCONTRAST) [mix 0 CAP 0.27] arcvh - g4 [mix SB RIGHTSB 0.55] STROKE - archv - g4.down.mid RIGHTSB [mix DESCENDER STROKE 0.525] [heading DOWNWARD] - arcvh + g4 [mix SB RIGHTSB 0.55] STROKE [heading RIGHTWARD] + archv 12 + g4.down.mid RIGHTSB [mix DESCENDER STROKE 0.5] [heading DOWNWARD] + arcvh 12 flat (RIGHTSB - (STROKE - [mix DESCENDER STROKE 0.5]) * 1.1) DESCENDER curl [mix SB RIGHTSB 0.5] DESCENDER [heading LEFTWARD] @@ -307,12 +307,12 @@ symbol-block 'zeta and xi' archv g4 (SB - O * 2 + STROKE * HVCONTRAST) [mix (CAP - STROKE) ybar 0.6] arcvh - g4.right.end xbar ybar + g4.right.end (xbar - HALFSTROKE * TANSLANT) ybar [widths.rhs (STROKE * [mix CTHIN 1 0.5])] include : dispiro - widths.rhs - g4.left.start xbar (ybar - STROKE) - bezcontrols 0.7 0 1 0.63 - g4 (SB + STROKE * HVCONTRAST) [mix 0 ybar 0.45] + widths.rhs (STROKE * [mix CTHIN 1 0.5]) + g4.left.start (xbar + HALFSTROKE * TANSLANT) (ybar - STROKE) + bezcontrols 0.7 0 1 0.6 + g4 (SB + STROKE * HVCONTRAST) [mix 0 ybar 0.45] [widths.rhs] arcvh g4 [mix SB RIGHTSB 0.5] STROKE archv diff --git a/makefile b/makefile index 72e66df..4711d1e 100644 --- a/makefile +++ b/makefile @@ -68,7 +68,11 @@ archives-slab : fonts-slab # Variant releases releasepack-default : $(SCRIPTS) | $(OBJDIR) $(MAKE) pages release VERSION=$(VERSION) -releasepack-cjk : $(SCRIPTS) | $(OBJDIR) +fonts-fw : $(SCRIPTS) | $(OBJDIR) + $(MAKE) fonts-default fonts-slab VERSION=$(VERSION) STYLE_COMMON='cjk' VARIANTNAME='wfw-' ARCPREFIX='withfw-' +fonts-cc : $(SCRIPTS) | $(OBJDIR) + $(MAKE) fonts-default fonts-slab VERSION=$(VERSION) STYLE_COMMON='cjk cc' VARIANTNAME='wcc-' ARCPREFIX='withfw-cc-' +releasepack-fw : $(SCRIPTS) | $(OBJDIR) $(MAKE) archives-default archives-slab VERSION=$(VERSION) STYLE_COMMON='cjk' VARIANTNAME='wfw-' ARCPREFIX='withfw-' releasepack-cc : $(SCRIPTS) | $(OBJDIR) $(MAKE) archives-default archives-slab VERSION=$(VERSION) STYLE_COMMON='cjk cc' VARIANTNAME='wcc-' ARCPREFIX='withfw-cc-' @@ -76,5 +80,5 @@ releasepack-hooky : $(SCRIPTS) | $(OBJDIR) $(MAKE) archives-default VERSION=$(VERSION) VARIANTNAME='hooky-' STYLE_UPRIGHT='v-l-hooky v-i-hooky' ARCPREFIX='variant-hooky-' releasepack-zshaped : $(SCRIPTS) | $(OBJDIR) $(MAKE) archives-default VERSION=$(VERSION) VARIANTNAME='zshaped-' STYLE_UPRIGHT='v-l-zshaped v-i-zshaped' ARCPREFIX='variant-zshaped-' -release-all : releasepack-default releasepack-cjk releasepack-cc releasepack-hooky releasepack-zshaped -cjk-all : releasepack-cjk releasepack-cc \ No newline at end of file +release-all : releasepack-default releasepack-fw releasepack-cc releasepack-hooky releasepack-zshaped +fw : fonts-fw fonts-cc \ No newline at end of file diff --git a/pass1-cleanup.py b/pass1-cleanup.py index 60f0f5d..c2f4f4a 100644 --- a/pass1-cleanup.py +++ b/pass1-cleanup.py @@ -28,8 +28,11 @@ for i in font: #font.replaceWithReference() print " Simplify: ", font.fontname +font.selection.select("X", "x", "chi", "cyrHadescender", "cyrhadescender", "supx", "supchi", "subx", "subchi", "circlex", "circleinnerx", "circleX", "circleinnerX", "combx", + "Y", "y", "y.upright", "yhooktop", "Yhooktop", "turny.upright", "cyrU", "cyrue", "lambda", "lambdaslash", "circley", "circleinnery", "circleY", "circleinnerY") +font.simplify(1, ("smoothcurves", "choosehv"), 0.2) font.selection.all() -font.simplify(0.05, ("smoothcurves", "choosehv"), 0.1) +font.simplify(0.075, ("smoothcurves", "choosehv"), 0.1) #font.em = 2000 font.selection.all() diff --git a/support/fairify.js b/support/fairify.js index f9c5611..fb9729e 100644 --- a/support/fairify.js +++ b/support/fairify.js @@ -1,6 +1,8 @@ var Transform = require('./transform.js'); -var ANGLES = 6; +var ANGLES = 12; +var CROWD = 4; +var LOOSE = 6; var SMALL = 1e-4 function cross(z1, z2, z3){ return (z2.x - z1.x) * (z3.y - z1.y) - (z3.x - z1.x) * (z2.y - z1.y) @@ -157,6 +159,9 @@ function fitpts(p1, c1, c2, p2){ } return [mix(mid, p1, 1/3), mix(mid, p2, 1/3)] }; +function close(z1, z2){ + return (z1.x - z2.x) * (z1.x - z2.x) + (z1.y - z2.y) * (z1.y - z2.y) <= SMALL +} function fairify(scurve, gizmo, angles){ angles = angles || ANGLES for(var j = 0; j < scurve.length; j++){ @@ -168,19 +173,24 @@ function fairify(scurve, gizmo, angles){ if(scurve[j].onCurve){ splitpoints.push(last = scurve[j]) } else if(scurve[j].cubic) { - var z1 = last, z2 = scurve[j], z3 = scurve[j + 1], z4 = scurve[j + 2] - splitSegment(z1, z2, z3, z4, angles, splitpoints); - last = z4; + var z1 = last, z2 = scurve[j], z3 = scurve[j + 1], z4 = scurve[j + 2]; + if(!(close(z1, z2) && close(z2, z3) && close(z3, z4))) { + splitSegment(z1, z2, z3, z4, ANGLES, splitpoints); + last = z4; + } j += 2; } else { var z1 = last, zm = scurve[j], z4 = scurve[j + 1] - var z2 = mix(zm, z1, 1/3); - var z3 = mix(zm, z4, 1/3); - splitSegment(z1, z2, z3, z4, angles, splitpoints); - last = z4; + if(!(close(z1, zm) && close(zm, z4))) { + var z2 = mix(zm, z1, 1/3); + var z3 = mix(zm, z4, 1/3); + splitSegment(z1, z2, z3, z4, ANGLES, splitpoints); + last = z4; + } j += 1; } }; + // Mark infections and extremae for(var j = 1; j < splitpoints.length - 1; j++) { if(splitpoints[j].onCurve && !splitpoints[j - 1].onCurve && !splitpoints[j + 1].onCurve){ var z1 = splitpoints[j], z0 = splitpoints[j - 1], z2 = splitpoints[j + 1] @@ -194,15 +204,41 @@ function fairify(scurve, gizmo, angles){ }; if(!(z1.inflect || isInflection)) { var angle0 = Math.atan2(z2.y - z0.y, z2.x - z0.x); - var angle = Math.abs(angle0 / Math.PI * angles % 1); - if(Math.abs(Math.abs(angle0) - Math.PI / 2) > SMALL && angle > SMALL && angle < 1 - SMALL){ - z0.remove = z1.remove = z2.remove = true; + var angle = Math.abs(angle0 / Math.PI * 2 % 1); + if(Math.abs(Math.abs(angle0) - Math.PI / 2) <= SMALL || angle <= SMALL || angle >= 1 - SMALL){ + z1.mark = true; } + } else { + z1.mark = true; } + } else { + z1.mark = true; + } + } else if(splitpoints[j].onCurve) { + splitpoints[j].mark = true // corner + } + }; + splitpoints[0].mark = splitpoints[splitpoints.length - 1].mark = true; + + // Mark diagonals + var lastmark = splitpoints[0]; + for(var j = 1; j < splitpoints.length - 1; j++) { + if(splitpoints[j].mark){ + lastmark = splitpoints[j]; + for(var k = j + 1; k < splitpoints.length && !splitpoints[k].mark; k++); + nextmark = splitpoints[k]; + var hspan = Math.abs(lastmark.x - nextmark.x); + var vspan = Math.abs(lastmark.y - nextmark.y); + } + if(splitpoints[j].onCurve && !splitpoints[j].mark){ + var z1 = splitpoints[j], z0 = splitpoints[j - 1], z2 = splitpoints[j + 1]; + var angle0 = Math.atan2(z2.y - z0.y, z2.x - z0.x); + var angle = Math.abs(angle0 / Math.PI * (hspan <= 10 * LOOSE || vspan <= 10 * LOOSE ? CROWD : LOOSE) % 1); + if(!(Math.abs(Math.abs(angle0) - Math.PI / 2) <= SMALL || angle <= SMALL || angle >= 1 - SMALL)){ + z1.remove = z0.remove = z2.remove = true; } } - } - + }; for(var j = 0; j < splitpoints.length; j++) if(splitpoints[j].onCurve && !splitpoints[j].remove && splitpoints[j + 1] && !splitpoints[j + 1].onCurve){ for(var k = j + 2; k < splitpoints.length && splitpoints[k].remove; k++); if(k - j > 2){ @@ -217,7 +253,7 @@ function fairify(scurve, gizmo, angles){ j = k; }; var ans = [] - for(var j = 0; j < splitpoints.length; j++) if(!splitpoints[j].remove) { + for(var j = 0; j < splitpoints.length; j++) if(splitpoints[j] && !splitpoints[j].remove) { ans.push(Transform.transformPoint(gizmo, splitpoints[j])) } return ans diff --git a/support/spirokit.ptl b/support/spirokit.ptl index 15a6978..92cd4f6 100644 --- a/support/spirokit.ptl +++ b/support/spirokit.ptl @@ -164,8 +164,8 @@ export : define [SetupBuilders args] : begin local g : new Glyph lhs.0.type = rhs.0.type = lhs.(lhs.length - 1).type = rhs.(rhs.length - 1).type = 'corner' libspiro.spiroToBezierOnContext [lhs.concat : rhs.reverse] true g QUAD PRECISION - foreach [j : range 0 g.contours.length] : begin - set g.contours.(j) : fairify g.contours.(j) globalTransform s.angles + if [not s.unfair] : foreach [j : range 0 g.contours.length] : begin + set g.contours.(j) : fairify g.contours.(j) globalTransform s.angles set g.knots knots set g.lhsknots lhs set g.rhsknots rhs