From 4e9c6d40363802bbedbbe75513445d0f615daae7 Mon Sep 17 00:00:00 2001 From: John McWilliams <37010132+jmcwilliams403@users.noreply.github.com> Date: Tue, 16 Jul 2024 23:06:56 -0400 Subject: [PATCH] =?UTF-8?q?Draft:=20Add=20playing=20cards=20(`U+1F0A0`?= =?UTF-8?q?=E2=80=A5`U+1F0F5`)=20(#1835).=20(#2419)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add playing cards (`U+1F0A0`‥`U+1F0F5`) (#1835). * Unify stroke width of playing cards' frame. * Improve playing card back. * Make playing cards' digits slightly taller. * Make playing cards' digits slightly narrower. --- changes/30.3.3.md | 4 + .../font-glyphs/src/auto-build/composite.ptl | 158 +++++++++++++++++- .../font-glyphs/src/letter/latin/upper-q.ptl | 9 + .../src/symbol/geometric/plain.ptl | 5 +- .../src/symbol/geometric/shaded.ptl | 8 + 5 files changed, 177 insertions(+), 7 deletions(-) diff --git a/changes/30.3.3.md b/changes/30.3.3.md index 8104e4b5a..169d963d5 100644 --- a/changes/30.3.3.md +++ b/changes/30.3.3.md @@ -3,4 +3,8 @@ - FRACTION NUMERATOR ONE (`U+215F`) (#1539). - BIG SOLIDUS (`U+29F8`) (#2414). - BIG REVERSE SOLIDUS (`U+29F9`) (#2414). + - PLAYING CARD BACK (`U+1F0A0`) ... PLAYING CARD KING OF SPADES (`U+1F0AE`) (#1835). + - PLAYING CARD ACE OF HEARTS (`U+1F0B1`) ... PLAYING CARD RED JOKER (`U+1F0BF`) (#1835). + - PLAYING CARD ACE OF DIAMONDS (`U+1F0C1`) ... PLAYING CARD BLACK JOKER (`U+1F0CF`) (#1835). + - PLAYING CARD ACE OF CLUBS (`U+1F0D1`) ... PLAYING CARD TRUMP-21 (`U+1F0F5`) (#1835). - REGIONAL INDICATOR SYMBOL LETTER A (`U+1F1E6`) ... REGIONAL INDICATOR SYMBOL LETTER Z (`U+1F1FF`). diff --git a/packages/font-glyphs/src/auto-build/composite.ptl b/packages/font-glyphs/src/auto-build/composite.ptl index 3d16f672d..fa35ac81d 100644 --- a/packages/font-glyphs/src/auto-build/composite.ptl +++ b/packages/font-glyphs/src/auto-build/composite.ptl @@ -147,7 +147,7 @@ glyph-block AutoBuild-Enclosure : begin return gniPart - define [EnsureInnerSubGlyphSeq inners markClass miniatureFont job dimens yCompress kExtraYShift] : begin + define [EnsureInnerSubGlyphSeq inners markClass miniatureFont job dimens _xCompress yCompress kExtraYShift] : begin define { gn unicode parts w bal baly } job define [object width mockInnerWidth dscale] dimens @@ -157,7 +157,7 @@ glyph-block AutoBuild-Enclosure : begin local derivedGlyph : miniatureFont.queryByNameEnsured gidPart if [not firstDerivedGyph] : set firstDerivedGyph derivedGlyph set totalWidth : totalWidth + derivedGlyph.advanceWidth - local xCompress [Math.min 1 (mockInnerWidth / totalWidth)] + local xCompress : _xCompress * [Math.min 1 (mockInnerWidth / totalWidth)] set totalWidth : Math.min mockInnerWidth totalWidth local shift : getGlyphDefaultShift bal baly firstDerivedGyph @@ -191,7 +191,7 @@ glyph-block AutoBuild-Enclosure : begin define { gn unicode parts w bal baly } job define [object width] dimens - local finalParts : EnsureInnerSubGlyphSeq inners 'enclosureInner' miniatureFont job dimens 1 0 + local finalParts : EnsureInnerSubGlyphSeq inners 'enclosureInner' miniatureFont job dimens 1 1 0 include : new-glyph : EnclosureInnerImpl dimens finalParts return finalParts @@ -201,8 +201,21 @@ glyph-block AutoBuild-Enclosure : begin define [object width] dimens local jobFirstHalf { gn unicode [parts.slice 0 (parts.length / 2)] w bal baly } local jobSecondHalf { gn unicode [parts.slice (parts.length / 2) ] w bal baly } - local finalPartsFirstHalf : EnsureInnerSubGlyphSeq inners "enclosureInnerFirstHalf" miniatureFont jobFirstHalf dimens 0.45 (+0.55) - local finalPartsSecondHalf : EnsureInnerSubGlyphSeq inners "enclosureInnerSecondHalf" miniatureFont jobSecondHalf dimens 0.45 (+0.00) + local finalPartsFirstHalf : EnsureInnerSubGlyphSeq inners "enclosureInnerFirstHalf" miniatureFont jobFirstHalf dimens 1 0.45 (+0.55) + local finalPartsSecondHalf : EnsureInnerSubGlyphSeq inners "enclosureInnerSecondHalf" miniatureFont jobSecondHalf dimens 1 0.45 (+0.00) + + include : new-glyph : glyph-proc + include : EnclosureInnerImpl dimens finalPartsFirstHalf + include : EnclosureInnerImpl dimens finalPartsSecondHalf + return : {}.concat finalPartsFirstHalf finalPartsSecondHalf + + define [PlayingCardInner dimens inners miniatureFont job] : glyph-proc + define { gn unicode parts w bal baly } job + define [object width] dimens + local jobFirstHalf { gn unicode [parts.slice 0 (parts.length / 2)] w bal baly } + local jobSecondHalf { gn unicode [parts.slice (parts.length / 2) ] w bal baly } + local finalPartsFirstHalf : EnsureInnerSubGlyphSeq inners "playingCardRank" miniatureFont jobFirstHalf dimens 0.6 0.6 (+0.55) + local finalPartsSecondHalf : EnsureInnerSubGlyphSeq inners "playingCardSuit" miniatureFont jobSecondHalf dimens 0.6 0.6 (-0.15) include : new-glyph : glyph-proc include : EnclosureInnerImpl dimens finalPartsFirstHalf @@ -313,6 +326,13 @@ glyph-block AutoBuild-Enclosure : begin local parts : include : TwoRowEnclosureInner dimens inners miniatureFont job if decomp : CvDecompose.set currentGlyph [{gnEnclosure}.concat parts] + define PlayingCardBuilder : object + decomposable true + buildGlyph : function [dimens inners miniatureFont decomp job gnEnclosure] : glyph-proc + include : refer-glyph gnEnclosure + local parts : include : PlayingCardInner dimens inners miniatureFont job + if decomp : CvDecompose.set currentGlyph [{gnEnclosure}.concat parts] + define InsetBuilder : object decomposable false buildGlyph : function [dimens inners miniatureFont decomp job gnEnclosure] : difference @@ -390,6 +410,48 @@ glyph-block AutoBuild-Enclosure : begin VBar.r right bot top sw include : AddEnclosureMarkTwoLine digits : CircleDimens digits ww + define [createPlayingCardGlyphs digits demands] + EnclosureT 'playingCard' PlayingCardBuilder StandardInners digits 2 demands PlayingCardEnclosureShape + define [PlayingCardEnclosureShape digits ww gap] : glyph-proc + define [object width sw top bot left right] : CircleDimens [Math.max digits 2] ww + set-width width + include : union + HBar.t left right top sw + HBar.b left right bot sw + VBar.l left bot top sw + VBar.r right bot top sw + include : AddEnclosureMarkTwoLine digits : CircleDimens digits ww + + define [createTrumpCardGlyphs digits demands] + EnclosureT 'trumpCard' CircledBuilder StandardInners digits 1 demands TrumpCardEnclosureShape + define [TrumpCardEnclosureShape digits ww gap] : glyph-proc + define [object width sw top bot left right] : CircleDimens [Math.max digits 5] ww + set-width width + include : union + HBar.t left right top sw + HBar.b left right bot sw + VBar.l left bot top sw + VBar.r right bot top sw + include : AddEnclosureMark digits : CircleDimens digits ww + + define [createPlayingCardBackGlyphs digits demands] + EnclosureT 'playingCardBack' InsetBuilder StandardInners digits 1 demands PlayingCardBackShape + define [PlayingCardBackShape digits ww gap] : glyph-proc + define [object width sw0 sw top bot left right] : CircleDimens digits ww (ww * gap) + set-width width + define sw1 : Math.min sw0 (sw / 2) + include : union + HBar.t left right top sw1 + HBar.b left right bot sw1 + VBar.l left bot top sw1 + VBar.r right bot top sw1 + include : Rect + top - sw + bot + sw + left + [HSwToV sw] + right - [HSwToV sw] + include : AddEnclosureMark digits : CircleDimens digits ww + define [createDashedBoxedGlyphs digits demands] EnclosureT 'dashed-boxed' CircledBuilder StandardInners digits 1 demands DashedBoxEnclosureShape define [DashedBoxEnclosureShape digits ww cap] : glyph-proc @@ -799,6 +861,92 @@ glyph-block AutoBuild-Enclosure : begin list null { 'markBaseSpace' 'markBaseSpace' } WideWidth1 list 0x1F1A9 { 'L' 'O' 'S' 'S' 'L' 'E' 'S' 'S' } WideWidth1 + do "Single-digit playing cards" + local compositions : list + list null {'markBaseSpace' 'markBaseSpace'} WideWidth1 + list 0x1F0A1 {'A' 'spadeSuit'} WideWidth4 + list 0x1F0AB {'J/noDescend' 'spadeSuit'} WideWidth4 + list 0x1F0AC {'C' 'spadeSuit'} WideWidth4 + list 0x1F0AD {'Q/noDescend' 'spadeSuit'} WideWidth4 + list 0x1F0AE {'K' 'spadeSuit'} WideWidth4 + list 0x1F0B1 {'A' 'whiteHeartSuit'} WideWidth4 + list 0x1F0BB {'J/noDescend' 'whiteHeartSuit'} WideWidth4 + list 0x1F0BC {'C' 'whiteHeartSuit'} WideWidth4 + list 0x1F0BD {'Q/noDescend' 'whiteHeartSuit'} WideWidth4 + list 0x1F0BE {'K' 'whiteHeartSuit'} WideWidth4 + list 0x1F0BF {'J/noDescend' 'vShadeStar.NWID'} WideWidth4 + list 0x1F0C1 {'A' 'whiteDiamondSuit'} WideWidth4 + list 0x1F0CB {'J/noDescend' 'whiteDiamondSuit'} WideWidth4 + list 0x1F0CC {'C' 'whiteDiamondSuit'} WideWidth4 + list 0x1F0CD {'Q/noDescend' 'whiteDiamondSuit'} WideWidth4 + list 0x1F0CE {'K' 'whiteDiamondSuit'} WideWidth4 + list 0x1F0CF {'J/noDescend' 'blackStar.NWID'} WideWidth4 + list 0x1F0D1 {'A' 'clubSuit'} WideWidth4 + list 0x1F0DB {'J/noDescend' 'clubSuit'} WideWidth4 + list 0x1F0DC {'C' 'clubSuit'} WideWidth4 + list 0x1F0DD {'Q/noDescend' 'clubSuit'} WideWidth4 + list 0x1F0DE {'K' 'clubSuit'} WideWidth4 + list 0x1F0DF {'J/noDescend' 'whiteStar.NWID'} WideWidth4 + foreach [j : range 2 till 9] : compositions.push : list (0x1F0A0 + j) [[digitGlyphNames j].concat {'spadeSuit'}] WideWidth4 + foreach [j : range 2 till 9] : compositions.push : list (0x1F0B0 + j) [[digitGlyphNames j].concat {'whiteHeartSuit'}] WideWidth4 + foreach [j : range 2 till 9] : compositions.push : list (0x1F0C0 + j) [[digitGlyphNames j].concat {'whiteDiamondSuit'}] WideWidth4 + foreach [j : range 2 till 9] : compositions.push : list (0x1F0D0 + j) [[digitGlyphNames j].concat {'clubSuit'}] WideWidth4 + createPlayingCardGlyphs 1 compositions + + do "Double-digit playing cards" + createPlayingCardGlyphs 2 : list + list null { 'markBaseSpace' 'markBaseSpace' } WideWidth1 + list 0x1F0AA { 'one.lnum' 'zero.lnum' 'spadeSuit' 'zwsp' } WideWidth4 + list 0x1F0BA { 'one.lnum' 'zero.lnum' 'whiteHeartSuit' 'zwsp' } WideWidth4 + list 0x1F0CA { 'one.lnum' 'zero.lnum' 'whiteDiamondSuit' 'zwsp' } WideWidth4 + list 0x1F0DA { 'one.lnum' 'zero.lnum' 'clubSuit' 'zwsp' } WideWidth4 + + do "Single-digit trump cards" + createTrumpCardGlyphs 1 : list + list null {'markBaseSpace'} WideWidth1 + list 0x1F0E0 {'zero.lnum/forceUnslashed'} WideWidth4 + list 0x1F0E1 {'I'} WideWidth4 + list 0x1F0E5 {'V'} WideWidth4 + list 0x1F0EA {'X'} WideWidth4 + + do "Double-digit trump cards" + createTrumpCardGlyphs 2 : list + list null {'markBaseSpace'} WideWidth1 + list 0x1F0E2 {'I' 'I'} WideWidth4 + list 0x1F0E4 {'I' 'V'} WideWidth4 + list 0x1F0E6 {'V' 'I'} WideWidth4 + list 0x1F0E9 {'I' 'X'} WideWidth4 + list 0x1F0EB {'X' 'I'} WideWidth4 + list 0x1F0EF {'X' 'V'} WideWidth4 + list 0x1F0F4 {'X' 'X'} WideWidth4 + + do "Triple-digit trump cards" + createTrumpCardGlyphs 3 : list + list null {'markBaseSpace'} WideWidth1 + list 0x1F0E3 {'I' 'I' 'I'} WideWidth4 + list 0x1F0E7 {'V' 'I' 'I'} WideWidth4 + list 0x1F0EC {'X' 'I' 'I'} WideWidth4 + list 0x1F0EE {'X' 'I' 'V'} WideWidth4 + list 0x1F0F0 {'X' 'V' 'I'} WideWidth4 + list 0x1F0F3 {'X' 'I' 'X'} WideWidth4 + list 0x1F0F5 {'X' 'X' 'I'} WideWidth4 + + do "Quadruple-digit trump cards" + createTrumpCardGlyphs 4 : list + list null {'markBaseSpace'} WideWidth1 + list 0x1F0E8 {'V' 'I' 'I' 'I'} WideWidth4 + list 0x1F0ED {'X' 'I' 'I' 'I'} WideWidth4 + list 0x1F0F1 {'X' 'V' 'I' 'I'} WideWidth4 + + do "Quintuple-digit trump cards" + createTrumpCardGlyphs 5 : list + list null {'markBaseSpace'} WideWidth1 + list 0x1F0F2 {'X' 'V' 'I' 'I' 'I'} WideWidth4 + + do "Playing card back" + createPlayingCardBackGlyphs 1 : list + list 0x1F0A0 {'markBaseSpace'} WideWidth4 + do "Single-digit dashed-boxed" local compositions {} foreach [j : range 0 26] : compositions.push {(0x1F1E6 + j) {[glyphStore.queryNameByUnicode (['A'.charCodeAt 0] + j)]} WideWidth1} diff --git a/packages/font-glyphs/src/letter/latin/upper-q.ptl b/packages/font-glyphs/src/letter/latin/upper-q.ptl index 52816a9f7..5350ae8a4 100644 --- a/packages/font-glyphs/src/letter/latin/upper-q.ptl +++ b/packages/font-glyphs/src/letter/latin/upper-q.ptl @@ -178,6 +178,14 @@ glyph-block Letter-Latin-Upper-Q : begin include : body df XH Stroke include : tailShape df XH swTailInner + create-glyph "Q/noDescend.\(suffix)" : glyph-proc + local df : DivFrame 1 + include : MarkSet.capital + include : if (mkSmcp === 'p') + with-transform [Translate 0 (CAP - XH)] + refer-glyph "smcpQ.\(suffix)" + refer-glyph "Q.\(suffix)" + create-glyph "QSideways.\(suffix)" : glyph-proc local df : DivFrame (XH / Width) 2 (XH * 0.1 / SB) include : PointingTo Width XH Width 0 : function [] : glyph-proc @@ -188,6 +196,7 @@ glyph-block Letter-Latin-Upper-Q : begin alias 'cyrl/Qa' 0x51A 'Q' select-variant 'smcpQ' 0xA7AF (follow -- 'Q') + select-variant 'Q/noDescend' (follow -- 'Q') select-variant 'QSideways' 0x213A (follow -- 'Q') diff --git a/packages/font-glyphs/src/symbol/geometric/plain.ptl b/packages/font-glyphs/src/symbol/geometric/plain.ptl index faef77d32..cc29383cb 100644 --- a/packages/font-glyphs/src/symbol/geometric/plain.ptl +++ b/packages/font-glyphs/src/symbol/geometric/plain.ptl @@ -571,6 +571,7 @@ glyph-block Symbol-Geometric-Plain : for-width-kinds WideWidth1 define [PentagramSw c] {.sw ([AdviceStroke c : Math.sqrt Geom.Scalar] * [Math.sqrt 5])} StdBlackShape [RegularPolygonFill 5 2 1.1 0] 'blackStar' 0x2605 StdWhiteShape [RegularPolygonFill 5 2 1.1 0] 'whiteStar' 0x2606 [PentagramSw 5.5] + StdWhiteShape [RegularPolygonFill 5 2 1.1 0] 'lightWhiteStar' null {.sw ([UnicodeWeightGrade 3 : Math.sqrt Geom.Scalar] * [Math.sqrt 5])} StdWhiteShape [RegularPolygonFill 5 2 1.1 0] 'whiteMediumStar' 0x2B50 [Object.assign [PentagramSw 7] Size.Medium] StdBlackShape [RegularPolygonFill 5 2 1.1 0] 'blackSmallStar' 0x2B51 Size.Small StdWhiteShape [RegularPolygonFill 5 2 1.1 0] 'whiteSmallStar' 0x2B52 [Object.assign [PentagramSw 3] Size.Small] @@ -597,8 +598,8 @@ glyph-block Symbol-Geometric-Plain : for-width-kinds WideWidth1 return : spiro-outline corners [close] define [PentagramSw c] {.sw ([AdviceStroke c : Math.sqrt Geom.Scalar] * [Math.sqrt 5])} - StdBlackShape [CurlyEdgeStar 4 0.6 1.1 0] 'blackFourPrintedStar' 0x2726 - StdWhiteShape [CurlyEdgeStar 4 0.6 1.1 0] 'whiteFourPrintedStar' 0x2727 [PentagramSw 5] + StdBlackShape [CurlyEdgeStar 4 0.6 1.1 0] 'blackFourPointedStar' 0x2726 + StdWhiteShape [CurlyEdgeStar 4 0.6 1.1 0] 'whiteFourPointedStar' 0x2727 [PentagramSw 5] do "Arrow head" define [RightArrowHeadShape cx cy size] : spiro-outline diff --git a/packages/font-glyphs/src/symbol/geometric/shaded.ptl b/packages/font-glyphs/src/symbol/geometric/shaded.ptl index 36a61b6f2..3a04aca5e 100644 --- a/packages/font-glyphs/src/symbol/geometric/shaded.ptl +++ b/packages/font-glyphs/src/symbol/geometric/shaded.ptl @@ -124,6 +124,14 @@ glyph-block Symbol-Geometric-Shaded : for-width-kinds WideWidth1 refer-glyph : MangleName 'whiteCircle' intersection [refer-glyph : MangleName 'blackCircleO'] [VBoxShadeShape] + create-glyph [MangleName 'vShadeStar'] [MangleUnicode null] : glyph-proc + set-width Geom.Width + include : union + refer-glyph : MangleName 'lightWhiteStar' + intersection + refer-glyph : MangleName 'blackStar' + VBoxShadeShape + glyph-block Symbol-Geometric-Shaded-Narrow : for-width-kinds WideWidth4 glyph-block-import CommonShapes glyph-block-import Common-Derivatives