diff --git a/changes/32.5.0.md b/changes/32.5.0.md index a1a2c82ba..c280f961c 100644 --- a/changes/32.5.0.md +++ b/changes/32.5.0.md @@ -1,2 +1,12 @@ * Add variant selector for decorative angle brackets (U+276C...U+2771) (#2603, #2623). +* Refine shape of: + - ARMENIAN SMALL LETTER CA (`U+056E`). + - VERTICAL ZIGZAG LINE (`U+299A`). + - LEFT WIGGLY FENCE (`U+29D8`). + - RIGHT WIGGLY FENCE (`U+29D9`). + - LEFT DOUBLE WIGGLY FENCE (`U+29DA`). + - RIGHT DOUBLE WIGGLY FENCE (`U+29DB`). + - HORIZONTAL RESISTOR SEGMENT (`U+1CC09`). + - VERTICAL RESISTOR SEGMENT (`U+1CC0A`). + - HORIZONTAL ZIGZAG LINE (`U+1CEB0`). * Optimize metrics for bowl of Cyrillic Lower Ef (`ф`) and Greek Small Letter Phi Symbol (`ϕ`). diff --git a/packages/font-glyphs/src/common/shapes.ptl b/packages/font-glyphs/src/common/shapes.ptl index 2a859ec00..7929b29b4 100644 --- a/packages/font-glyphs/src/common/shapes.ptl +++ b/packages/font-glyphs/src/common/shapes.ptl @@ -2,6 +2,7 @@ $$include '../meta/macros.ptl' import [mix linreg clamp fallback boole boolePn] from "@iosevka/util" import [Transform] from "@iosevka/geometry/transform" +import [Point] from "@iosevka/geometry/point" import [FunctionInterpolator AfCombine] from "@iosevka/geometry/spiro-control" import [RadicalGeometry StrokeGeometry RemoveHolesGeometry] from "@iosevka/geometry" @@ -797,3 +798,41 @@ glyph-block CommonShapes : begin foreach { suffix { DrawAt kDotRadius overshoot } } [Object.entries DotVariants] : do create-glyph "\(name).\(suffix)" : F DrawAt kDotRadius overshoot select-variant name unicode (follow -- 'punctuationDot') + + # Sharp Corner Interpolator + glyph-block-export TangentToNormal VectorDot + define [TangentToNormal offset contrast _tanSlope] : begin + local r : Math.hypot offset.x offset.y + return : new Point Point.Type.Corner + contrast * (-offset.y / r) + (offset.x + offset.y * [fallback _tanSlope TanSlope]) / r + define [VectorDot p1 p2] : p1.x * p2.x + p1.y * p2.y + + define [SharpCornerImpl before after args] : begin + if [not (before.af && before.af.l !== undefined)] : throw : new Error "Unable to infer stroke information for previous knot" + if [not (after.af && after.af.l !== undefined)] : throw : new Error "Unable to infer stroke information for next knot" + + local beforeT : new Point Point.Type.Corner (args.x - before.x) (args.y - before.y) + local afterT : new Point Point.Type.Corner (after.x - args.x) (after.y - args.y) + + local beforeN : fallback before.af.d : TangentToNormal beforeT args.contrast [if args.upright 0] + local afterN : fallback after.af.d : TangentToNormal afterT args.contrast [if args.upright 0] + + local beforeR : beforeN.addScale (-[VectorDot beforeN beforeT] / [VectorDot beforeT beforeT]) beforeT + local afterR : afterN.addScale (-[VectorDot afterN afterT ] / [VectorDot afterT afterT ]) afterT + + local beforeD : afterT.scale ([VectorDot beforeR beforeR] / [VectorDot beforeR afterT ]) + local afterD : beforeT.scale ([VectorDot afterR afterR ] / [VectorDot afterR beforeT]) + + local lOffset : [beforeD.scale before.af.l ].addScale after.af.l afterD + local rOffset : [beforeD.scale (-before.af.r)].addScale (-after.af.r) afterD + + local midPoint : lOffset.mix rOffset 0.5 + local refPoint : Point.translated midPoint args.x args.y + + return : corner refPoint.x refPoint.y [widths.center.heading 1 { .x (lOffset.x - rOffset.x) .y (lOffset.y - rOffset.y) }] + + glyph-block-export sharp-corner + define [sharp-corner] : with-params [x y [contrast HVContrast] [upright 0]] : begin + local args : object x y contrast upright + return : new FunctionInterpolator SharpCornerImpl args diff --git a/packages/font-glyphs/src/letter/armenian/ca.ptl b/packages/font-glyphs/src/letter/armenian/ca.ptl index 7b70b710d..38dd51617 100644 --- a/packages/font-glyphs/src/letter/armenian/ca.ptl +++ b/packages/font-glyphs/src/letter/armenian/ca.ptl @@ -41,25 +41,19 @@ glyph-block Letter-Armenian-Ca : begin local x1 : mix df.leftSB df.rightSB 0.45 local x2 : mix df.leftSB df.rightSB 0.3 - local xOffset : HSwToV : 0.5 * df.mvs local y2 : mix XH Ascender 0.5 - include : dispiro - widths.rhs df.mvs - flat (x1 + xOffset) Ascender [heading Downward] - curl (x2 + xOffset) y2 [heading Downward] - local x3 : mix df.leftSB df.rightSB 0.1 local x4 : mix df.leftSB df.rightSB 0.6 local rExt : Math.max df.rightSB : Math.min x4 + [HSwToV : 1.5 * df.mvs] + jut df.rightSB + jut - [HSwToV : 0.5 * df.mvs] - include : intersection [MaskBelowLine (x1 - xOffset) Ascender (x2 - xOffset) y2 100] : dispiro - widths.rhs df.mvs - flat (x3 + xOffset) Ascender - curl (x4 + xOffset) XH - flat (df.rightSB - OX) (XH - SmallArchDepthB) + include : dispiro + flat x1 Ascender [widths.center.heading df.mvs Downward] + sharp-corner x2 y2 + curl x4 XH [widths.center df.mvs] + flat (df.rightSB - OX) (XH - SmallArchDepthB) [widths.rhs df.mvs] curl (df.rightSB - OX) (0 + SmallArchDepthA) arch.rhs 0 (sw -- df.mvs) flat (df.leftSB + OX) (0 + SmallArchDepthB) diff --git a/packages/font-glyphs/src/meta/macros.ptl b/packages/font-glyphs/src/meta/macros.ptl index d790bd5b3..fe44e1331 100644 --- a/packages/font-glyphs/src/meta/macros.ptl +++ b/packages/font-glyphs/src/meta/macros.ptl @@ -312,7 +312,7 @@ define-macro glyph-block-import : syntax-rules DiagCor NameUni PointingTo with-transform with-outlined remove-holes radicalize clear-geometry clear-anchors ExtLineCenter ExtLineLhs ExtLineRhs DiagCorDs HCrossBar MaskAbove MaskBelow MaskLeft MaskRight HalfRectTriangle MaskAboveLine MaskBelowLine - MaskLeftLine MaskRightLine DotVariants WithDotVariants] + MaskLeftLine MaskRightLine DotVariants WithDotVariants TangentToNormal VectorDot sharp-corner] define vartiableFilter : if externEnv.$glyphBlockVariableUsage$ lambda [x] externEnv.$glyphBlockVariableUsage$.(x) diff --git a/packages/font-glyphs/src/symbol/math/geometry.ptl b/packages/font-glyphs/src/symbol/math/geometry.ptl index 2117937a5..2c9ffb09c 100644 --- a/packages/font-glyphs/src/symbol/math/geometry.ptl +++ b/packages/font-glyphs/src/symbol/math/geometry.ptl @@ -163,9 +163,12 @@ glyph-block Symbol-Math-Geometry : begin straight.right.end right top do 'Zigzags' - create-glyph 'vertZigzag' 0x299A : VZigzag Middle ParenBot ParenTop (radiusBox / 4) 9 0 GeometryStroke - create-glyph 'wigglyFenceLeft' 0x29D8 : VZigzag Middle ParenBot ParenTop (radiusBox / 4) 10 1 GeometryStroke - create-glyph 'wigglyFenceRight' 0x29D9 : VZigzag Middle ParenBot ParenTop (radiusBox / 4) 10 0 GeometryStroke + create-glyph 'vertZigzag' 0x299A : intersection [MaskAbove ParenBot] [MaskBelow ParenTop] + VZigzag.fromSide Middle ParenBot ParenTop (radiusBox / 4) 9 0 GeometryStroke + create-glyph 'wigglyFenceLeft' 0x29D8 : intersection [MaskAbove ParenBot] [MaskBelow ParenTop] + VZigzag.fromSide Middle ParenBot ParenTop (radiusBox / 4) 10 1 GeometryStroke + create-glyph 'wigglyFenceRight' 0x29D9 : intersection [MaskAbove ParenBot] [MaskBelow ParenTop] + VZigzag.fromSide Middle ParenBot ParenTop (radiusBox / 4) 10 0 GeometryStroke define space : (rightBox - leftBox - [HSwToV GeometryStroke] * 2) / 3 create-glyph 'doubleWigglyFenceLeft' 0x29DA : glyph-proc diff --git a/packages/font-glyphs/src/symbol/pictograph.ptl b/packages/font-glyphs/src/symbol/pictograph.ptl index a43585787..71d121bd7 100644 --- a/packages/font-glyphs/src/symbol/pictograph.ptl +++ b/packages/font-glyphs/src/symbol/pictograph.ptl @@ -13,6 +13,7 @@ export : define [apply] : begin run-glyph-module "./pictograph/faces.mjs" run-glyph-module "./pictograph/flags.mjs" run-glyph-module "./pictograph/game-sprite.mjs" + run-glyph-module "./pictograph/geometric.mjs" run-glyph-module "./pictograph/heart.mjs" run-glyph-module "./pictograph/hourglass.mjs" run-glyph-module "./pictograph/i-ching.mjs" diff --git a/packages/font-glyphs/src/symbol/pictograph/game-sprite.ptl b/packages/font-glyphs/src/symbol/pictograph/game-sprite.ptl index 34a7182f0..684423a2e 100644 --- a/packages/font-glyphs/src/symbol/pictograph/game-sprite.ptl +++ b/packages/font-glyphs/src/symbol/pictograph/game-sprite.ptl @@ -12,7 +12,6 @@ glyph-block Symbol-Pictograph-Game-Sprite : for-width-kinds WideWidth4 glyph-block-import Shared-Symbol-Shapes : TriangleShape glyph-block-import Symbol-Pictograph-Stick-Figure : StickFigureKit WithD4Transform D4Transform glyph-block-import Symbol-Geometric-Shared : GeometricDim - glyph-block-import Symbol-Mosaic-Block : HShade VShade define top fontMetrics.os2.sTypoAscender define bottom fontMetrics.os2.sTypoDescender @@ -365,7 +364,7 @@ glyph-block Symbol-Pictograph-Game-Sprite : for-width-kinds WideWidth4 set scaffold.tipHeight : 1 / 4 define [RightRocket box] : glyph-proc - local rocketLeft : box.mixY (0.5 + scaffold.width / 2) + local rocketLeft : box.mixY (0.5 + scaffold.width / 2) local rocketRight : box.mixY (0.5 - scaffold.width / 2) local rocketBase : box.mixX scaffold.baseHeight local rocketTip : box.mixX (1 - scaffold.tipHeight) @@ -483,91 +482,6 @@ glyph-block Symbol-Pictograph-Game-Sprite : for-width-kinds WideWidth4 include : UpFrog squareBox : D4Transform midX 2 0 - do "Square Spiral" - define directions : list - * {.dx 1 .dy 0 .heading Rightward} - * {.dx 0 .dy 1 .heading Upward} - * {.dx (-1) .dy 0 .heading Leftward} - * {.dx 0 .dy (-1) .heading Downward} - - define spiralSw : AdviceStroke 4 : Math.sqrt (MosaicWidthScalar / 2) - define oneStep : Geom.Size / 4.5 - define stepsPerTurn { 9 9 9 7 7 5 5 3 3 } - define [SquareSpiral startx starty startidx] : glyph-proc - local x1 startx - local y1 starty - foreach [idx : range 0 stepsPerTurn.length] : begin - local {.dx dx .dy dy .heading dir} directions.((startidx + idx) % 4) - local x2 : x1 + dx * oneStep * stepsPerTurn.(idx) - local y2 : y1 + dy * oneStep * stepsPerTurn.(idx) - include : dispiro - widths.lhs spiralSw - disable-contrast - flat x1 y1 [heading dir] - curl x2 y2 [heading dir] - set x1 x2 - set y1 y2 - - create-glyph [MangleName "squareSpiralFromTopLeft"] [MangleUnicode 0x1CC7C] : glyph-proc - set-width MosaicWidth - include : SquareSpiral Geom.Left Geom.Top 3 - create-glyph [MangleName "squareSpiralFromTopRight"] [MangleUnicode 0x1CC7D] : glyph-proc - set-width MosaicWidth - include : SquareSpiral Geom.Right Geom.Top 2 - create-glyph [MangleName "squareSpiralFromBottomRight"] [MangleUnicode 0x1CC7E] : glyph-proc - set-width MosaicWidth - include : SquareSpiral Geom.Right Geom.Bot 1 - create-glyph [MangleName "squareSpiralFromBottomLeft"] [MangleUnicode 0x1CC7F] : glyph-proc - set-width MosaicWidth - include : SquareSpiral Geom.Left Geom.Bot 0 - - - do "Ladder" - create-glyph [MangleName "vertLadder"] [MangleUnicode 0x1CC84] : glyph-proc - set-width MosaicWidth - include : HShade 8 top bottom Geom.Left Geom.Right - include : VBar.l Geom.Left bottom top GeometryStroke - include : VBar.r Geom.Right bottom top GeometryStroke - - create-glyph [MangleName "horiLadder"] [MangleUnicode 0x1CC85] : glyph-proc - set-width MosaicWidth - include : VShade (4 * MosaicWidthScalar) Geom.Top Geom.Bot left right - include : HBar.b left right Geom.Bot GeometryStroke - include : HBar.t left right Geom.Top GeometryStroke - - - do "Striped Triangles" - define stripes : 2 + 2 * MosaicWidthScalar - define coTop : mix Geom.Top Geom.Bot (0 - 1 / (2 * stripes)) - define coBot : mix Geom.Top Geom.Bot (1 + 1 / (2 * stripes)) - define coLeft : mix Geom.Left Geom.Right (0 - 1 / (2 * stripes)) - define coRight : mix Geom.Left Geom.Right (1 + 1 / (2 * stripes)) - - create-glyph [MangleName "stripedTriangleLeft"] [MangleUnicode 0x1CC80] : glyph-proc - set-width MosaicWidth - include : intersection - refer-glyph : MangleName "blackTriangleLeft" - VShade stripes top bottom coLeft coRight - - create-glyph [MangleName "stripedTriangleUp"] [MangleUnicode 0x1CC81] : glyph-proc - set-width MosaicWidth - include : intersection - refer-glyph : MangleName "blackTriangleUp" - HShade stripes coTop coBot left right - - create-glyph [MangleName "stripedTriangleRight"] [MangleUnicode 0x1CC82] : glyph-proc - set-width MosaicWidth - include : intersection - refer-glyph : MangleName "blackTriangleRight" - VShade stripes top bottom coLeft coRight - - create-glyph [MangleName "stripedTriangleDown"] [MangleUnicode 0x1CC83] : glyph-proc - set-width MosaicWidth - include : intersection - refer-glyph : MangleName "blackTriangleDown" - HShade stripes coTop coBot left right - - do "Moon Lander" define scaffold : object set scaffold.tipSize 0.2 diff --git a/packages/font-glyphs/src/symbol/pictograph/geometric.ptl b/packages/font-glyphs/src/symbol/pictograph/geometric.ptl new file mode 100644 index 000000000..62e91714b --- /dev/null +++ b/packages/font-glyphs/src/symbol/pictograph/geometric.ptl @@ -0,0 +1,118 @@ +$$include '../../meta/macros.ptl' + +import [mix linreg clamp fallback strokeOffset] from "@iosevka/util" +import [Box] from "@iosevka/geometry/box" +import [Transform] from "@iosevka/geometry/transform" + +glyph-module + +glyph-block Symbol-Pictograph-Geometric : for-width-kinds WideWidth4 + glyph-block-import CommonShapes + glyph-block-import Common-Derivatives + glyph-block-import Symbol-Geometric-Shared : GeometricDim + glyph-block-import Symbol-Mosaic-Block : HShade VShade + + define top fontMetrics.os2.sTypoAscender + define bottom fontMetrics.os2.sTypoDescender + define left 0 + define right MosaicWidth + + define midX : mix left right 0.5 + define midY : mix top bottom 0.5 + + define Geom : GeometricDim MosaicUnitWidth MosaicWidth + + do "Square Spiral" + define directions : list + * {.dx 1 .dy 0 .heading Rightward} + * {.dx 0 .dy 1 .heading Upward} + * {.dx (-1) .dy 0 .heading Leftward} + * {.dx 0 .dy (-1) .heading Downward} + + define spiralSw : AdviceStroke 4 : Math.sqrt (MosaicWidthScalar / 2) + define oneStep : Geom.Size / 4.5 + define stepsPerTurn { 9 9 9 7 7 5 5 3 3 } + define [SquareSpiral startx starty startidx] : glyph-proc + local x1 startx + local y1 starty + foreach [idx : range 0 stepsPerTurn.length] : begin + local {.dx dx .dy dy .heading dir} directions.((startidx + idx) % 4) + local x2 : x1 + dx * oneStep * stepsPerTurn.(idx) + local y2 : y1 + dy * oneStep * stepsPerTurn.(idx) + include : dispiro + widths.lhs spiralSw + disable-contrast + flat x1 y1 [heading dir] + curl x2 y2 [heading dir] + set x1 x2 + set y1 y2 + + create-glyph [MangleName "squareSpiralFromTopLeft"] [MangleUnicode 0x1CC7C] : glyph-proc + set-width MosaicWidth + include : SquareSpiral Geom.Left Geom.Top 3 + create-glyph [MangleName "squareSpiralFromTopRight"] [MangleUnicode 0x1CC7D] : glyph-proc + set-width MosaicWidth + include : SquareSpiral Geom.Right Geom.Top 2 + create-glyph [MangleName "squareSpiralFromBottomRight"] [MangleUnicode 0x1CC7E] : glyph-proc + set-width MosaicWidth + include : SquareSpiral Geom.Right Geom.Bot 1 + create-glyph [MangleName "squareSpiralFromBottomLeft"] [MangleUnicode 0x1CC7F] : glyph-proc + set-width MosaicWidth + include : SquareSpiral Geom.Left Geom.Bot 0 + + do "Ladder" + create-glyph [MangleName "vertLadder"] [MangleUnicode 0x1CC84] : glyph-proc + set-width MosaicWidth + include : HShade 8 top bottom Geom.Left Geom.Right + include : VBar.l Geom.Left bottom top GeometryStroke + include : VBar.r Geom.Right bottom top GeometryStroke + + create-glyph [MangleName "horiLadder"] [MangleUnicode 0x1CC85] : glyph-proc + set-width MosaicWidth + include : VShade (4 * MosaicWidthScalar) Geom.Top Geom.Bot left right + include : HBar.b left right Geom.Bot GeometryStroke + include : HBar.t left right Geom.Top GeometryStroke + + + do "Striped Triangles" + define stripes : 2 + 2 * MosaicWidthScalar + define coTop : mix Geom.Top Geom.Bot (0 - 1 / (2 * stripes)) + define coBot : mix Geom.Top Geom.Bot (1 + 1 / (2 * stripes)) + define coLeft : mix Geom.Left Geom.Right (0 - 1 / (2 * stripes)) + define coRight : mix Geom.Left Geom.Right (1 + 1 / (2 * stripes)) + + create-glyph [MangleName "stripedTriangleLeft"] [MangleUnicode 0x1CC80] : glyph-proc + set-width MosaicWidth + include : intersection + refer-glyph : MangleName "blackTriangleLeft" + VShade stripes top bottom coLeft coRight + + create-glyph [MangleName "stripedTriangleUp"] [MangleUnicode 0x1CC81] : glyph-proc + set-width MosaicWidth + include : intersection + refer-glyph : MangleName "blackTriangleUp" + HShade stripes coTop coBot left right + + create-glyph [MangleName "stripedTriangleRight"] [MangleUnicode 0x1CC82] : glyph-proc + set-width MosaicWidth + include : intersection + refer-glyph : MangleName "blackTriangleRight" + VShade stripes top bottom coLeft coRight + + create-glyph [MangleName "stripedTriangleDown"] [MangleUnicode 0x1CC83] : glyph-proc + set-width MosaicWidth + include : intersection + refer-glyph : MangleName "blackTriangleDown" + HShade stripes coTop coBot left right + + do "Horizontal Zigzag" + glyph-block-import Shared-Symbol-Shapes : HZigzag + + create-glyph [MangleName 'horiZigzag'] [MangleUnicode 0x1CEB0] : glyph-proc + set-width Geom.Width + define left : SB * MosaicWidthScalar + define right : RightSB * MosaicWidthScalar + define amp : (OperTop - OperBot) / 8 + define sgmts : 4 * MosaicWidthScalar + 1 + + include : HZigzag.fromSide Geom.MidY left right amp sgmts 1 GeometryStroke diff --git a/packages/font-glyphs/src/symbol/pictograph/schematic.ptl b/packages/font-glyphs/src/symbol/pictograph/schematic.ptl index 592287c45..f4995f8f0 100644 --- a/packages/font-glyphs/src/symbol/pictograph/schematic.ptl +++ b/packages/font-glyphs/src/symbol/pictograph/schematic.ptl @@ -123,64 +123,30 @@ glyph-block Symbol-Pictograph-Schematic : for-width-kinds WideWidth4 : begin corner midx midy do "Resistor" + glyph-block-import Shared-Symbol-Shapes : HZigzag VZigzag define amplitude : Geom.Size * 0.8 define vWaves 2 define hWaves MosaicWidthScalar - define [HoriWaveSegment left right lefty righty sw] : intersection - MaskRight left - MaskLeft right - ExtLineCenter 1 sw left lefty right righty - define [VertWaveSegment bot top botx topx sw] : intersection - MaskAbove bot - MaskBelow top - ExtLineCenter 1 sw botx bot topx top - create-glyph [MangleName 'resistorHori'] [MangleUnicode 0x1CC09] : glyph-proc set-width MosaicWidth include : ForceUpright - local segs : 2 * hWaves - 1 - local halfPeriod : MosaicWidth / (2 * hWaves) - local up : midy + amplitude - local down : midy - amplitude - include : intersection - MaskLeft : left + 0.5 * halfPeriod - MaskAbove : midy - 0.5 * boxDrawingStroke - ExtLineCenter 1 boxDrawingStroke left midy (left + 0.5 * halfPeriod) up - foreach [j : range 0 segs] : begin - include : HoriWaveSegment - left + (j + 0.5) * halfPeriod - left + (j + 1.5) * halfPeriod - if (j % 2) down up - if (j % 2) up down - * boxDrawingStroke - include : intersection - MaskRight : right - 0.5 * halfPeriod - MaskBelow : midy + 0.5 * boxDrawingStroke - ExtLineCenter 1 boxDrawingStroke (right - 0.5 * halfPeriod) down right midy + local segs : 2 * hWaves + local mask : (right - left) / (segs * 2) + include : difference + HZigzag.fromCenter midy left right amplitude segs 0 boxDrawingStroke 1 + MaskLeftLine (left + mask) bottom (left + mask) (midy - boxDrawingStroke / 2) + MaskRightLine (right - mask) (midy + boxDrawingStroke / 2) (right - mask) top create-glyph [MangleName 'resistorVert'] [MangleUnicode 0x1CC0A] : glyph-proc set-width MosaicWidth include : ForceUpright - local segs : 2 * vWaves - 1 - local halfPeriod : MosaicHeight / (2 * vWaves) - local up : midx + amplitude - local down : midx - amplitude - include : intersection - MaskBelow : bottom + 0.5 * halfPeriod - MaskRight : midx - [HSwToV : 0.5 * boxDrawingStroke] - ExtLineCenter 1 boxDrawingStroke midx bottom up (bottom + 0.5 * halfPeriod) - foreach [j : range 0 segs] : begin - include : VertWaveSegment - bottom + (j + 0.5) * halfPeriod - bottom + (j + 1.5) * halfPeriod - if (j % 2) down up - if (j % 2) up down - * boxDrawingStroke - include : intersection - MaskAbove : top - 0.5 * halfPeriod - MaskLeft : midx + [HSwToV : 0.5 * boxDrawingStroke] - ExtLineCenter 1 boxDrawingStroke down (top - 0.5 * halfPeriod) midx top + local segs : 2 * vWaves + local mask : (top - bottom) / (segs * 2) + include : difference + VZigzag.fromCenter midx bottom top amplitude segs 0 boxDrawingStroke 1 + MaskBelowLine left (bottom + mask) (midx - [HSwToV : boxDrawingStroke / 2]) (bottom + mask) + MaskAboveLine (midx + [HSwToV : boxDrawingStroke / 2]) (top - mask) right (top - mask) do "Coil" glyph-block-import Symbol-Mosaic-Split-Graphic : Multicell @@ -258,7 +224,7 @@ glyph-block Symbol-Pictograph-Schematic : for-width-kinds WideWidth4 : begin local tipDy : tipDx * (-slope) local baseDx : -tipDy / [Math.sqrt 3] * 2 local baseDy : baseDx / (-slope) - define arrowPos : (1 - [HSwToV boxDrawingStroke] / (MosaicWidth / 2)) * 0.4 + define arrowPos : (1 - [HSwToV boxDrawingStroke] / MosaicMiddle) * 0.4 define [VerticalPart] : intersection Rect top bottom left (midx + [HSwToV : 0.5 * boxDrawingStroke]) diff --git a/packages/font-glyphs/src/symbol/shared.ptl b/packages/font-glyphs/src/symbol/shared.ptl index 76a90d304..026eda253 100644 --- a/packages/font-glyphs/src/symbol/shared.ptl +++ b/packages/font-glyphs/src/symbol/shared.ptl @@ -1,6 +1,7 @@ $$include '../meta/macros.ptl' import [mix linreg clamp fallback] from "@iosevka/util" +import [Point] from "@iosevka/geometry/point" glyph-module @@ -36,6 +37,32 @@ glyph-block Shared-Symbol-Shapes : begin define [WaveShape] : with-params [left right xsJoin xfJoin diagJoinS diagJoinF [waveCount 1] [unitWidth Width]] : WaveShapeImpl (unitWidth * -left) (unitWidth * (1 + right)) (-left * waveCount) ((1 + right) * waveCount) xsJoin xfJoin diagJoinS diagJoinF return WaveShape + glyph-block-export Polyline ClosedPolyline + define [Polyline] : with-params [af points [contrast HVContrast] [upright 0]] : begin + local {{x0 y0} {xp yp}} points + local knots : list + flat x0 y0 af + sharp-corner xp yp contrast upright + foreach {x y} [items-of : points.slice 2 (-1)] : begin + knots.push : virt [mix xp x 0.5] [mix yp y 0.5] af + knots.push : sharp-corner x y contrast upright + set {xp yp} {x y} + set {xp yp} points.[points.length - 1] + knots.push : curl xp yp af + + return knots + + define [ClosedPolyline] : with-params [af points [contrast HVContrast] [upright 0]] : begin + local {xp yp} points.[points.length - 1] + local knots : list + foreach {x y} [items-of points] : begin + knots.push : virt [mix xp x 0.5] [mix yp y 0.5] af + knots.push : sharp-corner x y contrast upright + set {xp yp} {x y} + knots.push : close + + return knots + glyph-block-export TriangleShape define [TriangleShape x1 y1 x2 y2 x3 y3 sw] : begin local widthSide : if ((y2 - y1) * (y3 - y2) + (x2 - x1) * (x3 - x2) < 0) widths.rhs widths.lhs @@ -59,36 +86,101 @@ glyph-block Shared-Symbol-Shapes : begin corner x3 y3 corner x1 y1 - - define [HZigzagSegment x1 x2 y1 y2 sw] : intersection - MaskRight x1 - MaskLeft x2 - ExtLineCenter 1 sw x1 y1 x2 y2 - define [VZigzagSegment y1 y2 x1 x2 sw] : intersection - MaskAbove y1 - MaskBelow y2 - ExtLineCenter 1 sw x1 y1 x2 y2 - glyph-block-export HZigzag VZigzag - define [HZigzag midy left right amp sgmts phase sw] : glyph-proc - local halfPeriod : (right - left) / sgmts - local up : midy + amp - local down : midy - amp - foreach [j : range 0 sgmts] : begin - include : HZigzagSegment - left + j * halfPeriod - left + (j + 1) * halfPeriod - if ((j + phase) % 2) down up - if ((j + phase) % 2) up down - * sw - define [VZigzag midx bot top amp sgmts phase sw] : glyph-proc - local halfPeriod : (top - bot) / sgmts - local up : midx + amp - local down : midx - amp - foreach [j : range 0 sgmts] : begin - include : VZigzagSegment - bot + j * halfPeriod - bot + (j + 1) * halfPeriod - if ((j + phase) % 2) down up - if ((j + phase) % 2) up down - * sw + define HZigzag : namespace + define [getOffset dx dy upright sw] : begin + local T : new Point Point.Type.Corner dx dy + local N : TangentToNormal T HVContrast [if upright 0] + local D : T.scale : N.x / T.x * sw / 2 + return D + + export : define [fromSide midy left right amp sgmts phase sw upright] : glyph-proc + local halfPeriod : (right - left) / sgmts + local posOff : getOffset halfPeriod ( 2 * amp) upright (-sw) + local negOff : getOffset halfPeriod (-2 * amp) upright sw + + local pos : midy + amp + local neg : midy - amp + local points : list + points.push : list + if phase (left - posOff.x) (left - negOff.x) + if phase (neg - posOff.y) (pos - negOff.y) + foreach [j : range 1 sgmts] : begin + points.push : list + left + j * halfPeriod + if ((j + phase) % 2) neg pos + points.push : list + if ((sgmts + phase) % 2) (right + negOff.x) (right + posOff.x) + if ((sgmts + phase) % 2) (neg + negOff.y) (pos + posOff.y) + + include : dispiro : Polyline [widths.center sw] points (upright -- upright) + + export : define [fromCenter midy left right amp sgmts phase sw upright] : glyph-proc + local halfPeriod : (right - left) / sgmts + local posOff : getOffset halfPeriod ( 2 * amp) upright (-sw) + local negOff : getOffset halfPeriod (-2 * amp) upright sw + + local pos : midy + amp + local neg : midy - amp + local points : list + points.push : list + if phase (left - negOff.x) (left - posOff.x) + if phase (midy - negOff.y) (midy - posOff.y) + foreach [j : range 0 sgmts] : begin + points.push : list + left + (j + 0.5) * halfPeriod + if ((j + phase) % 2) neg pos + points.push : list + if ((sgmts + phase) % 2) (right + negOff.x) (right + posOff.x) + if ((sgmts + phase) % 2) (midy + negOff.y) (midy + posOff.y) + + include : dispiro : Polyline [widths.center sw] points (upright -- upright) + + define VZigzag : namespace + define [getOffset dx dy upright sw] : begin + local T : new Point Point.Type.Corner dx dy + local N : TangentToNormal T HVContrast [if upright 0] + local D : T.scale : N.y / T.y * sw / 2 + return D + + export : define [fromSide midx bot top amp sgmts phase sw upright] : glyph-proc + local halfPeriod : (top - bot) / sgmts + local posOff : getOffset ( 2 * amp) halfPeriod upright sw + local negOff : getOffset (-2 * amp) halfPeriod upright (-sw) + + local pos : midx + amp + local neg : midx - amp + local points : list + points.push : list + if phase (neg - posOff.x) (pos - negOff.x) + if phase (bot - posOff.y) (bot - negOff.y) + foreach [j : range 1 sgmts] : begin + points.push : list + if ((j + phase) % 2) neg pos + bot + j * halfPeriod + points.push : list + if ((sgmts + phase) % 2) (neg + negOff.x) (pos + posOff.x) + if ((sgmts + phase) % 2) (top + negOff.y) (top + posOff.y) + + include : dispiro : Polyline [widths.center sw] points (upright -- upright) + + export : define [fromCenter midx bot top amp sgmts phase sw upright] : glyph-proc + local halfPeriod : (top - bot) / sgmts + local posOff : getOffset ( 2 * amp) halfPeriod upright sw + local negOff : getOffset (-2 * amp) halfPeriod upright (-sw) + + local pos : midx + amp + local neg : midx - amp + local points : list + points.push : list + if phase (midx - negOff.x) (midx - posOff.x) + if phase (bot - negOff.y) (bot - posOff.y) + foreach [j : range 0 sgmts] : begin + points.push : list + if ((j + phase) % 2) neg pos + bot + (j + 0.5) * halfPeriod + points.push : list + if ((sgmts + phase) % 2) (midx + negOff.x) (midx + posOff.x) + if ((sgmts + phase) % 2) (top + negOff.y) (top + posOff.y) + + include : dispiro : Polyline [widths.center sw] points (upright -- upright)