Draft: Add playing cards (U+1F0A0U+1F0F5) (#1835). (#2419)

* 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.
This commit is contained in:
John McWilliams 2024-07-16 23:06:56 -04:00 committed by GitHub
parent c071af3077
commit 4e9c6d4036
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 177 additions and 7 deletions

View file

@ -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`).

View file

@ -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}

View file

@ -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')

View file

@ -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

View file

@ -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