diff options
Diffstat (limited to 'tex')
48 files changed, 1899 insertions, 748 deletions
diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index 9e0025e0f..8570ac7a9 100644 --- a/tex/context/base/mkii/cont-new.mkii +++ b/tex/context/base/mkii/cont-new.mkii @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2020.01.26 18:34} +\newcontextversion{2020.02.11 16:36} %D This file is loaded at runtime, thereby providing an %D excellent place for hacks, patches, extensions and new diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii index aa7c02cf4..e02bc12dd 100644 --- a/tex/context/base/mkii/context.mkii +++ b/tex/context/base/mkii/context.mkii @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2020.01.26 18:34} +\edef\contextversion{2020.02.11 16:36} %D For those who want to use this: diff --git a/tex/context/base/mkiv/char-emj.lua b/tex/context/base/mkiv/char-emj.lua index b00e9ebf8..e6c059174 100644 --- a/tex/context/base/mkiv/char-emj.lua +++ b/tex/context/base/mkiv/char-emj.lua @@ -16,6 +16,7 @@ return { ["a button (blood type)"]={ 0x1F170, 0xFE0F }, ["ab button (blood type)"]={ 0x1F18E }, ["abacus"]={ 0x1F9EE }, + ["accordion"]={ 0x1FA97 }, ["adhesive bandage"]={ 0x1FA79 }, ["admission tickets"]={ 0x1F39F, 0xFE0F }, ["aerial tramway"]={ 0x1F6A1 }, @@ -29,6 +30,7 @@ return { ["ambulance"]={ 0x1F691 }, ["american football"]={ 0x1F3C8 }, ["amphora"]={ 0x1F3FA }, + ["anatomical heart"]={ 0x1FAC0 }, ["anchor"]={ 0x2693 }, ["anger symbol"]={ 0x1F4A2 }, ["angry face"]={ 0x1F620 }, @@ -40,8 +42,20 @@ return { ["aquarius"]={ 0x2652 }, ["aries"]={ 0x2648 }, ["articulated lorry"]={ 0x1F69B }, + ["artist"]={ 0x1F9D1, 0x200D, 0x1F3A8 }, ["artist palette"]={ 0x1F3A8 }, + ["artist: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F3A8 }, + ["artist: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F3A8 }, + ["artist: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F3A8 }, + ["artist: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F3A8 }, + ["artist: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F3A8 }, ["astonished face"]={ 0x1F632 }, + ["astronaut"]={ 0x1F9D1, 0x200D, 0x1F680 }, + ["astronaut: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F680 }, + ["astronaut: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F680 }, + ["astronaut: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F680 }, + ["astronaut: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F680 }, + ["astronaut: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F680 }, ["atm sign"]={ 0x1F3E7 }, ["atom symbol"]={ 0x269B, 0xFE0F }, ["auto rickshaw"]={ 0x1F6FA }, @@ -115,9 +129,12 @@ return { ["beaming face with smiling eyes"]={ 0x1F601 }, ["bear"]={ 0x1F43B }, ["beating heart"]={ 0x1F493 }, + ["beaver"]={ 0x1F9AB }, ["bed"]={ 0x1F6CF, 0xFE0F }, ["beer mug"]={ 0x1F37A }, + ["beetle"]={ 0x1FAB2 }, ["bell"]={ 0x1F514 }, + ["bell pepper"]={ 0x1FAD1 }, ["bell with slash"]={ 0x1F515 }, ["bellhop bell"]={ 0x1F6CE, 0xFE0F }, ["bento box"]={ 0x1F371 }, @@ -128,6 +145,8 @@ return { ["biohazard"]={ 0x2623, 0xFE0F }, ["bird"]={ 0x1F426 }, ["birthday cake"]={ 0x1F382 }, + ["bison"]={ 0x1F9AC }, + ["black cat"]={ 0x1F408, 0x200D, 0x2B1B }, ["black circle"]={ 0x26AB }, ["black flag"]={ 0x1F3F4 }, ["black heart"]={ 0x1F5A4 }, @@ -143,12 +162,14 @@ return { ["blue circle"]={ 0x1F535 }, ["blue heart"]={ 0x1F499 }, ["blue square"]={ 0x1F7E6 }, + ["blueberries"]={ 0x1FAD0 }, ["boar"]={ 0x1F417 }, ["bomb"]={ 0x1F4A3 }, ["bone"]={ 0x1F9B4 }, ["bookmark"]={ 0x1F516 }, ["bookmark tabs"]={ 0x1F4D1 }, ["books"]={ 0x1F4DA }, + ["boomerang"]={ 0x1FA83 }, ["bottle with popping cork"]={ 0x1F37E }, ["bouquet"]={ 0x1F490 }, ["bow and arrow"]={ 0x1F3F9 }, @@ -170,14 +191,9 @@ return { ["breast-feeding: medium-dark skin tone"]={ 0x1F931, 0x1F3FE }, ["breast-feeding: medium-light skin tone"]={ 0x1F931, 0x1F3FC }, ["brick"]={ 0x1F9F1 }, - ["bride with veil"]={ 0x1F470 }, - ["bride with veil: dark skin tone"]={ 0x1F470, 0x1F3FF }, - ["bride with veil: light skin tone"]={ 0x1F470, 0x1F3FB }, - ["bride with veil: medium skin tone"]={ 0x1F470, 0x1F3FD }, - ["bride with veil: medium-dark skin tone"]={ 0x1F470, 0x1F3FE }, - ["bride with veil: medium-light skin tone"]={ 0x1F470, 0x1F3FC }, ["bridge at night"]={ 0x1F309 }, ["briefcase"]={ 0x1F4BC }, + ["briefs"]={ 0x1FA72 }, ["bright button"]={ 0x1F506 }, ["broccoli"]={ 0x1F966 }, ["broken heart"]={ 0x1F494 }, @@ -185,6 +201,8 @@ return { ["brown circle"]={ 0x1F7E4 }, ["brown heart"]={ 0x1F90E }, ["brown square"]={ 0x1F7EB }, + ["bubble tea"]={ 0x1F9CB }, + ["bucket"]={ 0x1FAA3 }, ["bug"]={ 0x1F41B }, ["building construction"]={ 0x1F3D7, 0xFE0F }, ["bullet train"]={ 0x1F685 }, @@ -218,6 +236,7 @@ return { ["card index dividers"]={ 0x1F5C2, 0xFE0F }, ["carousel horse"]={ 0x1F3A0 }, ["carp streamer"]={ 0x1F38F }, + ["carpentry saw"]={ 0x1FA9A }, ["carrot"]={ 0x1F955 }, ["castle"]={ 0x1F3F0 }, ["cat"]={ 0x1F408 }, @@ -284,9 +303,11 @@ return { ["club suit"]={ 0x2663, 0xFE0F }, ["clutch bag"]={ 0x1F45D }, ["coat"]={ 0x1F9E5 }, + ["cockroach"]={ 0x1FAB3 }, ["cocktail glass"]={ 0x1F378 }, ["coconut"]={ 0x1F965 }, ["coffin"]={ 0x26B0, 0xFE0F }, + ["coin"]={ 0x1FA99 }, ["cold face"]={ 0x1F976 }, ["collision"]={ 0x1F4A5 }, ["comet"]={ 0x2604, 0xFE0F }, @@ -305,6 +326,12 @@ return { ["construction worker: medium-light skin tone"]={ 0x1F477, 0x1F3FC }, ["control knobs"]={ 0x1F39B, 0xFE0F }, ["convenience store"]={ 0x1F3EA }, + ["cook"]={ 0x1F9D1, 0x200D, 0x1F373 }, + ["cook: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F373 }, + ["cook: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F373 }, + ["cook: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F373 }, + ["cook: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F373 }, + ["cook: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F373 }, ["cooked rice"]={ 0x1F35A }, ["cookie"]={ 0x1F36A }, ["cooking"]={ 0x1F373 }, @@ -392,12 +419,14 @@ return { ["dim button"]={ 0x1F505 }, ["direct hit"]={ 0x1F3AF }, ["disappointed face"]={ 0x1F61E }, + ["disguised face"]={ 0x1F978 }, + ["divide"]={ 0x2797 }, ["diving mask"]={ 0x1F93F }, - ["division sign"]={ 0x2797 }, ["diya lamp"]={ 0x1FA94 }, ["dizzy"]={ 0x1F4AB }, ["dizzy face"]={ 0x1F635 }, ["dna"]={ 0x1F9EC }, + ["dodo"]={ 0x1F9A4 }, ["dog"]={ 0x1F415 }, ["dog face"]={ 0x1F436 }, ["dollar banknote"]={ 0x1F4B5 }, @@ -447,6 +476,7 @@ return { ["eject button"]={ 0x23CF, 0xFE0F }, ["electric plug"]={ 0x1F50C }, ["elephant"]={ 0x1F418 }, + ["elevator"]={ 0x1F6D7 }, ["eleven o’clock"]={ 0x1F55A }, ["eleven-thirty"]={ 0x1F566 }, ["elf"]={ 0x1F9DD }, @@ -486,6 +516,12 @@ return { ["face with tongue"]={ 0x1F61B }, ["face without mouth"]={ 0x1F636 }, ["factory"]={ 0x1F3ED }, + ["factory worker"]={ 0x1F9D1, 0x200D, 0x1F3ED }, + ["factory worker: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F3ED }, + ["factory worker: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F3ED }, + ["factory worker: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F3ED }, + ["factory worker: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F3ED }, + ["factory worker: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F3ED }, ["fairy"]={ 0x1F9DA }, ["fairy: dark skin tone"]={ 0x1F9DA, 0x1F3FF }, ["fairy: light skin tone"]={ 0x1F9DA, 0x1F3FB }, @@ -520,12 +556,19 @@ return { ["family: woman, woman, girl"]={ 0x1F469, 0x200D, 0x1F469, 0x200D, 0x1F467 }, ["family: woman, woman, girl, boy"]={ 0x1F469, 0x200D, 0x1F469, 0x200D, 0x1F467, 0x200D, 0x1F466 }, ["family: woman, woman, girl, girl"]={ 0x1F469, 0x200D, 0x1F469, 0x200D, 0x1F467, 0x200D, 0x1F467 }, + ["farmer"]={ 0x1F9D1, 0x200D, 0x1F33E }, + ["farmer: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F33E }, + ["farmer: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F33E }, + ["farmer: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F33E }, + ["farmer: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F33E }, + ["farmer: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F33E }, ["fast down button"]={ 0x23EC }, ["fast reverse button"]={ 0x23EA }, ["fast up button"]={ 0x23EB }, ["fast-forward button"]={ 0x23E9 }, ["fax machine"]={ 0x1F4E0 }, ["fearful face"]={ 0x1F628 }, + ["feather"]={ 0x1FAB6 }, ["female sign"]={ 0x2640, 0xFE0F }, ["ferris wheel"]={ 0x1F3A1 }, ["ferry"]={ 0x26F4, 0xFE0F }, @@ -538,6 +581,12 @@ return { ["fire engine"]={ 0x1F692 }, ["fire extinguisher"]={ 0x1F9EF }, ["firecracker"]={ 0x1F9E8 }, + ["firefighter"]={ 0x1F9D1, 0x200D, 0x1F692 }, + ["firefighter: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F692 }, + ["firefighter: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F692 }, + ["firefighter: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F692 }, + ["firefighter: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F692 }, + ["firefighter: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F692 }, ["fireworks"]={ 0x1F386 }, ["first quarter moon"]={ 0x1F313 }, ["first quarter moon face"]={ 0x1F31B }, @@ -684,7 +733,6 @@ return { ["flag: lithuania"]={ 0x1F1F1, 0x1F1F9 }, ["flag: luxembourg"]={ 0x1F1F1, 0x1F1FA }, ["flag: macao sar china"]={ 0x1F1F2, 0x1F1F4 }, - ["flag: macedonia"]={ 0x1F1F2, 0x1F1F0 }, ["flag: madagascar"]={ 0x1F1F2, 0x1F1EC }, ["flag: malawi"]={ 0x1F1F2, 0x1F1FC }, ["flag: malaysia"]={ 0x1F1F2, 0x1F1FE }, @@ -718,6 +766,7 @@ return { ["flag: niue"]={ 0x1F1F3, 0x1F1FA }, ["flag: norfolk island"]={ 0x1F1F3, 0x1F1EB }, ["flag: north korea"]={ 0x1F1F0, 0x1F1F5 }, + ["flag: north macedonia"]={ 0x1F1F2, 0x1F1F0 }, ["flag: northern mariana islands"]={ 0x1F1F2, 0x1F1F5 }, ["flag: norway"]={ 0x1F1F3, 0x1F1F4 }, ["flag: oman"]={ 0x1F1F4, 0x1F1F2 }, @@ -811,6 +860,7 @@ return { ["flamingo"]={ 0x1F9A9 }, ["flashlight"]={ 0x1F526 }, ["flat shoe"]={ 0x1F97F }, + ["flatbread"]={ 0x1FAD3 }, ["fleur-de-lis"]={ 0x269C, 0xFE0F }, ["flexed biceps"]={ 0x1F4AA }, ["flexed biceps: dark skin tone"]={ 0x1F4AA, 0x1F3FF }, @@ -821,6 +871,7 @@ return { ["floppy disk"]={ 0x1F4BE }, ["flower playing cards"]={ 0x1F3B4 }, ["flushed face"]={ 0x1F633 }, + ["fly"]={ 0x1FAB0 }, ["flying disc"]={ 0x1F94F }, ["flying saucer"]={ 0x1F6F8 }, ["fog"]={ 0x1F32B, 0xFE0F }, @@ -831,6 +882,7 @@ return { ["folded hands: medium skin tone"]={ 0x1F64F, 0x1F3FD }, ["folded hands: medium-dark skin tone"]={ 0x1F64F, 0x1F3FE }, ["folded hands: medium-light skin tone"]={ 0x1F64F, 0x1F3FC }, + ["fondue"]={ 0x1FAD5 }, ["foot"]={ 0x1F9B6 }, ["foot: dark skin tone"]={ 0x1F9B6, 0x1F3FF }, ["foot: light skin tone"]={ 0x1F9B6, 0x1F3FB }, @@ -926,6 +978,13 @@ return { ["handshake"]={ 0x1F91D }, ["hatching chick"]={ 0x1F423 }, ["headphone"]={ 0x1F3A7 }, + ["headstone"]={ 0x1FAA6 }, + ["health worker"]={ 0x1F9D1, 0x200D, 0x2695, 0xFE0F }, + ["health worker: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x2695, 0xFE0F }, + ["health worker: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x2695, 0xFE0F }, + ["health worker: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x2695, 0xFE0F }, + ["health worker: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x2695, 0xFE0F }, + ["health worker: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x2695, 0xFE0F }, ["hear-no-evil monkey"]={ 0x1F649 }, ["heart decoration"]={ 0x1F49F }, ["heart exclamation"]={ 0x2763, 0xFE0F }, @@ -947,6 +1006,7 @@ return { ["hollow red circle"]={ 0x2B55 }, ["honey pot"]={ 0x1F36F }, ["honeybee"]={ 0x1F41D }, + ["hook"]={ 0x1FA9D }, ["horizontal traffic light"]={ 0x1F6A5 }, ["horse"]={ 0x1F40E }, ["horse face"]={ 0x1F434 }, @@ -971,8 +1031,9 @@ return { ["hugging face"]={ 0x1F917 }, ["hundred points"]={ 0x1F4AF }, ["hushed face"]={ 0x1F62F }, + ["hut"]={ 0x1F6D6 }, + ["ice"]={ 0x1F9CA }, ["ice cream"]={ 0x1F368 }, - ["ice cube"]={ 0x1F9CA }, ["ice hockey"]={ 0x1F3D2 }, ["ice skate"]={ 0x26F8, 0xFE0F }, ["id button"]={ 0x1F194 }, @@ -1016,6 +1077,12 @@ return { ["jeans"]={ 0x1F456 }, ["joker"]={ 0x1F0CF }, ["joystick"]={ 0x1F579, 0xFE0F }, + ["judge"]={ 0x1F9D1, 0x200D, 0x2696, 0xFE0F }, + ["judge: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x2696, 0xFE0F }, + ["judge: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x2696, 0xFE0F }, + ["judge: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x2696, 0xFE0F }, + ["judge: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x2696, 0xFE0F }, + ["judge: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x2696, 0xFE0F }, ["kaaba"]={ 0x1F54B }, ["kangaroo"]={ 0x1F998 }, ["key"]={ 0x1F511 }, @@ -1047,12 +1114,14 @@ return { ["kitchen knife"]={ 0x1F52A }, ["kite"]={ 0x1FA81 }, ["kiwi fruit"]={ 0x1F95D }, + ["knot"]={ 0x1FAA2 }, ["koala"]={ 0x1F428 }, ["lab coat"]={ 0x1F97C }, ["label"]={ 0x1F3F7, 0xFE0F }, ["lacrosse"]={ 0x1F94D }, + ["ladder"]={ 0x1FA9C }, ["lady beetle"]={ 0x1F41E }, - ["laptop computer"]={ 0x1F4BB }, + ["laptop"]={ 0x1F4BB }, ["large blue diamond"]={ 0x1F537 }, ["large orange diamond"]={ 0x1F536 }, ["last quarter moon"]={ 0x1F317 }, @@ -1099,6 +1168,7 @@ return { ["locked with pen"]={ 0x1F50F }, ["locomotive"]={ 0x1F682 }, ["lollipop"]={ 0x1F36D }, + ["long drum"]={ 0x1FA98 }, ["lotion bottle"]={ 0x1F9F4 }, ["loudly crying face"]={ 0x1F62D }, ["loudspeaker"]={ 0x1F4E2 }, @@ -1111,6 +1181,7 @@ return { ["love-you gesture: medium-dark skin tone"]={ 0x1F91F, 0x1F3FE }, ["love-you gesture: medium-light skin tone"]={ 0x1F91F, 0x1F3FC }, ["luggage"]={ 0x1F9F3 }, + ["lungs"]={ 0x1FAC1 }, ["lying face"]={ 0x1F925 }, ["mage"]={ 0x1F9D9 }, ["mage: dark skin tone"]={ 0x1F9D9, 0x1F3FF }, @@ -1118,11 +1189,13 @@ return { ["mage: medium skin tone"]={ 0x1F9D9, 0x1F3FD }, ["mage: medium-dark skin tone"]={ 0x1F9D9, 0x1F3FE }, ["mage: medium-light skin tone"]={ 0x1F9D9, 0x1F3FC }, + ["magic wand"]={ 0x1FA84 }, ["magnet"]={ 0x1F9F2 }, ["magnifying glass tilted left"]={ 0x1F50D }, ["magnifying glass tilted right"]={ 0x1F50E }, ["mahjong red dragon"]={ 0x1F004 }, ["male sign"]={ 0x2642, 0xFE0F }, + ["mammoth"]={ 0x1F9A3 }, ["man"]={ 0x1F468 }, ["man artist"]={ 0x1F468, 0x200D, 0x1F3A8 }, ["man artist: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F3A8 }, @@ -1220,6 +1293,12 @@ return { ["man farmer: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F33E }, ["man farmer: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F33E }, ["man farmer: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F33E }, + ["man feeding baby"]={ 0x1F468, 0x200D, 0x1F37C }, + ["man feeding baby: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F37C }, + ["man feeding baby: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F37C }, + ["man feeding baby: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F37C }, + ["man feeding baby: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F37C }, + ["man feeding baby: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F37C }, ["man firefighter"]={ 0x1F468, 0x200D, 0x1F692 }, ["man firefighter: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F692 }, ["man firefighter: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F692 }, @@ -1299,18 +1378,12 @@ return { ["man in steamy room: medium skin tone"]={ 0x1F9D6, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, ["man in steamy room: medium-dark skin tone"]={ 0x1F9D6, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, ["man in steamy room: medium-light skin tone"]={ 0x1F9D6, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, - ["man in suit levitating"]={ 0x1F574, 0xFE0F }, - ["man in suit levitating: dark skin tone"]={ 0x1F574, 0x1F3FF }, - ["man in suit levitating: light skin tone"]={ 0x1F574, 0x1F3FB }, - ["man in suit levitating: medium skin tone"]={ 0x1F574, 0x1F3FD }, - ["man in suit levitating: medium-dark skin tone"]={ 0x1F574, 0x1F3FE }, - ["man in suit levitating: medium-light skin tone"]={ 0x1F574, 0x1F3FC }, - ["man in tuxedo"]={ 0x1F935 }, - ["man in tuxedo: dark skin tone"]={ 0x1F935, 0x1F3FF }, - ["man in tuxedo: light skin tone"]={ 0x1F935, 0x1F3FB }, - ["man in tuxedo: medium skin tone"]={ 0x1F935, 0x1F3FD }, - ["man in tuxedo: medium-dark skin tone"]={ 0x1F935, 0x1F3FE }, - ["man in tuxedo: medium-light skin tone"]={ 0x1F935, 0x1F3FC }, + ["man in tuxedo"]={ 0x1F935, 0x200D, 0x2642, 0xFE0F }, + ["man in tuxedo: dark skin tone"]={ 0x1F935, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man in tuxedo: light skin tone"]={ 0x1F935, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man in tuxedo: medium skin tone"]={ 0x1F935, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man in tuxedo: medium-dark skin tone"]={ 0x1F935, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man in tuxedo: medium-light skin tone"]={ 0x1F935, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, ["man judge"]={ 0x1F468, 0x200D, 0x2696, 0xFE0F }, ["man judge: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x2696, 0xFE0F }, ["man judge: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x2696, 0xFE0F }, @@ -1497,18 +1570,18 @@ return { ["man wearing turban: medium skin tone"]={ 0x1F473, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, ["man wearing turban: medium-dark skin tone"]={ 0x1F473, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, ["man wearing turban: medium-light skin tone"]={ 0x1F473, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, - ["man with chinese cap"]={ 0x1F472 }, - ["man with chinese cap: dark skin tone"]={ 0x1F472, 0x1F3FF }, - ["man with chinese cap: light skin tone"]={ 0x1F472, 0x1F3FB }, - ["man with chinese cap: medium skin tone"]={ 0x1F472, 0x1F3FD }, - ["man with chinese cap: medium-dark skin tone"]={ 0x1F472, 0x1F3FE }, - ["man with chinese cap: medium-light skin tone"]={ 0x1F472, 0x1F3FC }, - ["man with probing cane"]={ 0x1F468, 0x200D, 0x1F9AF }, - ["man with probing cane: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F9AF }, - ["man with probing cane: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F9AF }, - ["man with probing cane: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F9AF }, - ["man with probing cane: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F9AF }, - ["man with probing cane: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F9AF }, + ["man with veil"]={ 0x1F470, 0x200D, 0x2642, 0xFE0F }, + ["man with veil: dark skin tone"]={ 0x1F470, 0x1F3FF, 0x200D, 0x2642, 0xFE0F }, + ["man with veil: light skin tone"]={ 0x1F470, 0x1F3FB, 0x200D, 0x2642, 0xFE0F }, + ["man with veil: medium skin tone"]={ 0x1F470, 0x1F3FD, 0x200D, 0x2642, 0xFE0F }, + ["man with veil: medium-dark skin tone"]={ 0x1F470, 0x1F3FE, 0x200D, 0x2642, 0xFE0F }, + ["man with veil: medium-light skin tone"]={ 0x1F470, 0x1F3FC, 0x200D, 0x2642, 0xFE0F }, + ["man with white cane"]={ 0x1F468, 0x200D, 0x1F9AF }, + ["man with white cane: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F9AF }, + ["man with white cane: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F9AF }, + ["man with white cane: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F9AF }, + ["man with white cane: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F9AF }, + ["man with white cane: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F9AF }, ["man zombie"]={ 0x1F9DF, 0x200D, 0x2642, 0xFE0F }, ["man: bald"]={ 0x1F468, 0x200D, 0x1F9B2 }, ["man: beard"]={ 0x1F9D4 }, @@ -1560,6 +1633,12 @@ return { ["martial arts uniform"]={ 0x1F94B }, ["mate"]={ 0x1F9C9 }, ["meat on bone"]={ 0x1F356 }, + ["mechanic"]={ 0x1F9D1, 0x200D, 0x1F527 }, + ["mechanic: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F527 }, + ["mechanic: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F527 }, + ["mechanic: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F527 }, + ["mechanic: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F527 }, + ["mechanic: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F527 }, ["mechanical arm"]={ 0x1F9BE }, ["mechanical leg"]={ 0x1F9BF }, ["medical symbol"]={ 0x2695, 0xFE0F }, @@ -1573,15 +1652,25 @@ return { ["men holding hands: dark skin tone, medium-dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FE }, ["men holding hands: dark skin tone, medium-light skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FC }, ["men holding hands: light skin tone"]={ 0x1F46C, 0x1F3FB }, + ["men holding hands: light skin tone, dark skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FF }, + ["men holding hands: light skin tone, medium skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FD }, + ["men holding hands: light skin tone, medium-dark skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FE }, + ["men holding hands: light skin tone, medium-light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FC }, ["men holding hands: medium skin tone"]={ 0x1F46C, 0x1F3FD }, + ["men holding hands: medium skin tone, dark skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FF }, ["men holding hands: medium skin tone, light skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FB }, + ["men holding hands: medium skin tone, medium-dark skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FE }, ["men holding hands: medium skin tone, medium-light skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FC }, ["men holding hands: medium-dark skin tone"]={ 0x1F46C, 0x1F3FE }, + ["men holding hands: medium-dark skin tone, dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FF }, ["men holding hands: medium-dark skin tone, light skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FB }, ["men holding hands: medium-dark skin tone, medium skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FD }, ["men holding hands: medium-dark skin tone, medium-light skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FC }, ["men holding hands: medium-light skin tone"]={ 0x1F46C, 0x1F3FC }, + ["men holding hands: medium-light skin tone, dark skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FF }, ["men holding hands: medium-light skin tone, light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FB }, + ["men holding hands: medium-light skin tone, medium skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FD }, + ["men holding hands: medium-light skin tone, medium-dark skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FE }, ["men with bunny ears"]={ 0x1F46F, 0x200D, 0x2642, 0xFE0F }, ["men wrestling"]={ 0x1F93C, 0x200D, 0x2642, 0xFE0F }, ["menorah"]={ 0x1F54E }, @@ -1614,10 +1703,12 @@ return { ["middle finger: medium skin tone"]={ 0x1F595, 0x1F3FD }, ["middle finger: medium-dark skin tone"]={ 0x1F595, 0x1F3FE }, ["middle finger: medium-light skin tone"]={ 0x1F595, 0x1F3FC }, + ["military helmet"]={ 0x1FA96 }, ["military medal"]={ 0x1F396, 0xFE0F }, ["milky way"]={ 0x1F30C }, ["minibus"]={ 0x1F690 }, - ["minus sign"]={ 0x2796 }, + ["minus"]={ 0x2796 }, + ["mirror"]={ 0x1FA9E }, ["moai"]={ 0x1F5FF }, ["mobile phone"]={ 0x1F4F1 }, ["mobile phone off"]={ 0x1F4F4 }, @@ -1643,6 +1734,7 @@ return { ["mountain railway"]={ 0x1F69E }, ["mouse"]={ 0x1F401 }, ["mouse face"]={ 0x1F42D }, + ["mouse trap"]={ 0x1FAA4 }, ["mouth"]={ 0x1F444 }, ["movie camera"]={ 0x1F3A5 }, ["mrs. claus"]={ 0x1F936 }, @@ -1651,13 +1743,19 @@ return { ["mrs. claus: medium skin tone"]={ 0x1F936, 0x1F3FD }, ["mrs. claus: medium-dark skin tone"]={ 0x1F936, 0x1F3FE }, ["mrs. claus: medium-light skin tone"]={ 0x1F936, 0x1F3FC }, - ["multiplication sign"]={ 0x2716, 0xFE0F }, + ["multiply"]={ 0x2716, 0xFE0F }, ["mushroom"]={ 0x1F344 }, ["musical keyboard"]={ 0x1F3B9 }, ["musical note"]={ 0x1F3B5 }, ["musical notes"]={ 0x1F3B6 }, ["musical score"]={ 0x1F3BC }, ["muted speaker"]={ 0x1F507 }, + ["mx claus"]={ 0x1F9D1, 0x200D, 0x1F384 }, + ["mx claus: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F384 }, + ["mx claus: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F384 }, + ["mx claus: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F384 }, + ["mx claus: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F384 }, + ["mx claus: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F384 }, ["nail polish"]={ 0x1F485 }, ["nail polish: dark skin tone"]={ 0x1F485, 0x1F3FF }, ["nail polish: light skin tone"]={ 0x1F485, 0x1F3FB }, @@ -1670,6 +1768,7 @@ return { ["nazar amulet"]={ 0x1F9FF }, ["necktie"]={ 0x1F454 }, ["nerd face"]={ 0x1F913 }, + ["nesting dolls"]={ 0x1FA86 }, ["neutral face"]={ 0x1F610 }, ["new button"]={ 0x1F195 }, ["new moon"]={ 0x1F311 }, @@ -1680,6 +1779,12 @@ return { ["night with stars"]={ 0x1F303 }, ["nine o’clock"]={ 0x1F558 }, ["nine-thirty"]={ 0x1F564 }, + ["ninja"]={ 0x1F977 }, + ["ninja: dark skin tone"]={ 0x1F977, 0x1F3FF }, + ["ninja: light skin tone"]={ 0x1F977, 0x1F3FB }, + ["ninja: medium skin tone"]={ 0x1F977, 0x1F3FD }, + ["ninja: medium-dark skin tone"]={ 0x1F977, 0x1F3FE }, + ["ninja: medium-light skin tone"]={ 0x1F977, 0x1F3FC }, ["no bicycles"]={ 0x1F6B3 }, ["no entry"]={ 0x26D4 }, ["no littering"]={ 0x1F6AF }, @@ -1701,6 +1806,12 @@ return { ["octopus"]={ 0x1F419 }, ["oden"]={ 0x1F362 }, ["office building"]={ 0x1F3E2 }, + ["office worker"]={ 0x1F9D1, 0x200D, 0x1F4BC }, + ["office worker: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F4BC }, + ["office worker: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F4BC }, + ["office worker: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F4BC }, + ["office worker: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F4BC }, + ["office worker: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F4BC }, ["ogre"]={ 0x1F479 }, ["oil drum"]={ 0x1F6E2, 0xFE0F }, ["ok button"]={ 0x1F197 }, @@ -1729,6 +1840,7 @@ return { ["older person: medium skin tone"]={ 0x1F9D3, 0x1F3FD }, ["older person: medium-dark skin tone"]={ 0x1F9D3, 0x1F3FE }, ["older person: medium-light skin tone"]={ 0x1F9D3, 0x1F3FC }, + ["olive"]={ 0x1FAD2 }, ["om"]={ 0x1F549, 0xFE0F }, ["on! arrow"]={ 0x1F51B }, ["oncoming automobile"]={ 0x1F698 }, @@ -1809,15 +1921,26 @@ return { ["people holding hands: dark skin tone, medium-dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FE }, ["people holding hands: dark skin tone, medium-light skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FC }, ["people holding hands: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FB }, + ["people holding hands: light skin tone, dark skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FF }, + ["people holding hands: light skin tone, medium skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FD }, + ["people holding hands: light skin tone, medium-dark skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FE }, + ["people holding hands: light skin tone, medium-light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FC }, ["people holding hands: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FD }, + ["people holding hands: medium skin tone, dark skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FF }, ["people holding hands: medium skin tone, light skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FB }, + ["people holding hands: medium skin tone, medium-dark skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FE }, ["people holding hands: medium skin tone, medium-light skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FC }, ["people holding hands: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FE }, + ["people holding hands: medium-dark skin tone, dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FF }, ["people holding hands: medium-dark skin tone, light skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FB }, ["people holding hands: medium-dark skin tone, medium skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FD }, ["people holding hands: medium-dark skin tone, medium-light skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FC }, ["people holding hands: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FC }, + ["people holding hands: medium-light skin tone, dark skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FF }, ["people holding hands: medium-light skin tone, light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FB }, + ["people holding hands: medium-light skin tone, medium skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FD }, + ["people holding hands: medium-light skin tone, medium-dark skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FE }, + ["people hugging"]={ 0x1FAC2 }, ["people with bunny ears"]={ 0x1F46F }, ["people wrestling"]={ 0x1F93C }, ["performing arts"]={ 0x1F3AD }, @@ -1859,6 +1982,12 @@ return { ["person facepalming: medium skin tone"]={ 0x1F926, 0x1F3FD }, ["person facepalming: medium-dark skin tone"]={ 0x1F926, 0x1F3FE }, ["person facepalming: medium-light skin tone"]={ 0x1F926, 0x1F3FC }, + ["person feeding baby"]={ 0x1F9D1, 0x200D, 0x1F37C }, + ["person feeding baby: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F37C }, + ["person feeding baby: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F37C }, + ["person feeding baby: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F37C }, + ["person feeding baby: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F37C }, + ["person feeding baby: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F37C }, ["person fencing"]={ 0x1F93A }, ["person frowning"]={ 0x1F64D }, ["person frowning: dark skin tone"]={ 0x1F64D, 0x1F3FF }, @@ -1908,12 +2037,36 @@ return { ["person in lotus position: medium skin tone"]={ 0x1F9D8, 0x1F3FD }, ["person in lotus position: medium-dark skin tone"]={ 0x1F9D8, 0x1F3FE }, ["person in lotus position: medium-light skin tone"]={ 0x1F9D8, 0x1F3FC }, + ["person in manual wheelchair"]={ 0x1F9D1, 0x200D, 0x1F9BD }, + ["person in manual wheelchair: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F9BD }, + ["person in manual wheelchair: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F9BD }, + ["person in manual wheelchair: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F9BD }, + ["person in manual wheelchair: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F9BD }, + ["person in manual wheelchair: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F9BD }, + ["person in motorized wheelchair"]={ 0x1F9D1, 0x200D, 0x1F9BC }, + ["person in motorized wheelchair: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F9BC }, + ["person in motorized wheelchair: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F9BC }, + ["person in motorized wheelchair: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F9BC }, + ["person in motorized wheelchair: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F9BC }, + ["person in motorized wheelchair: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F9BC }, ["person in steamy room"]={ 0x1F9D6 }, ["person in steamy room: dark skin tone"]={ 0x1F9D6, 0x1F3FF }, ["person in steamy room: light skin tone"]={ 0x1F9D6, 0x1F3FB }, ["person in steamy room: medium skin tone"]={ 0x1F9D6, 0x1F3FD }, ["person in steamy room: medium-dark skin tone"]={ 0x1F9D6, 0x1F3FE }, ["person in steamy room: medium-light skin tone"]={ 0x1F9D6, 0x1F3FC }, + ["person in suit levitating"]={ 0x1F574, 0xFE0F }, + ["person in suit levitating: dark skin tone"]={ 0x1F574, 0x1F3FF }, + ["person in suit levitating: light skin tone"]={ 0x1F574, 0x1F3FB }, + ["person in suit levitating: medium skin tone"]={ 0x1F574, 0x1F3FD }, + ["person in suit levitating: medium-dark skin tone"]={ 0x1F574, 0x1F3FE }, + ["person in suit levitating: medium-light skin tone"]={ 0x1F574, 0x1F3FC }, + ["person in tuxedo"]={ 0x1F935 }, + ["person in tuxedo: dark skin tone"]={ 0x1F935, 0x1F3FF }, + ["person in tuxedo: light skin tone"]={ 0x1F935, 0x1F3FB }, + ["person in tuxedo: medium skin tone"]={ 0x1F935, 0x1F3FD }, + ["person in tuxedo: medium-dark skin tone"]={ 0x1F935, 0x1F3FE }, + ["person in tuxedo: medium-light skin tone"]={ 0x1F935, 0x1F3FC }, ["person juggling"]={ 0x1F939 }, ["person juggling: dark skin tone"]={ 0x1F939, 0x1F3FF }, ["person juggling: light skin tone"]={ 0x1F939, 0x1F3FB }, @@ -2022,25 +2175,80 @@ return { ["person wearing turban: medium skin tone"]={ 0x1F473, 0x1F3FD }, ["person wearing turban: medium-dark skin tone"]={ 0x1F473, 0x1F3FE }, ["person wearing turban: medium-light skin tone"]={ 0x1F473, 0x1F3FC }, + ["person with skullcap"]={ 0x1F472 }, + ["person with skullcap: dark skin tone"]={ 0x1F472, 0x1F3FF }, + ["person with skullcap: light skin tone"]={ 0x1F472, 0x1F3FB }, + ["person with skullcap: medium skin tone"]={ 0x1F472, 0x1F3FD }, + ["person with skullcap: medium-dark skin tone"]={ 0x1F472, 0x1F3FE }, + ["person with skullcap: medium-light skin tone"]={ 0x1F472, 0x1F3FC }, + ["person with veil"]={ 0x1F470 }, + ["person with veil: dark skin tone"]={ 0x1F470, 0x1F3FF }, + ["person with veil: light skin tone"]={ 0x1F470, 0x1F3FB }, + ["person with veil: medium skin tone"]={ 0x1F470, 0x1F3FD }, + ["person with veil: medium-dark skin tone"]={ 0x1F470, 0x1F3FE }, + ["person with veil: medium-light skin tone"]={ 0x1F470, 0x1F3FC }, + ["person with white cane"]={ 0x1F9D1, 0x200D, 0x1F9AF }, + ["person with white cane: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F9AF }, + ["person with white cane: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F9AF }, + ["person with white cane: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F9AF }, + ["person with white cane: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F9AF }, + ["person with white cane: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F9AF }, + ["person: bald"]={ 0x1F9D1, 0x200D, 0x1F9B2 }, ["person: blond hair"]={ 0x1F471 }, + ["person: curly hair"]={ 0x1F9D1, 0x200D, 0x1F9B1 }, ["person: dark skin tone"]={ 0x1F9D1, 0x1F3FF }, + ["person: dark skin tone, bald"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F9B2 }, ["person: dark skin tone, blond hair"]={ 0x1F471, 0x1F3FF }, + ["person: dark skin tone, curly hair"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F9B1 }, + ["person: dark skin tone, red hair"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F9B0 }, + ["person: dark skin tone, white hair"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F9B3 }, ["person: light skin tone"]={ 0x1F9D1, 0x1F3FB }, + ["person: light skin tone, bald"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F9B2 }, ["person: light skin tone, blond hair"]={ 0x1F471, 0x1F3FB }, + ["person: light skin tone, curly hair"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F9B1 }, + ["person: light skin tone, red hair"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F9B0 }, + ["person: light skin tone, white hair"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F9B3 }, ["person: medium skin tone"]={ 0x1F9D1, 0x1F3FD }, + ["person: medium skin tone, bald"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F9B2 }, ["person: medium skin tone, blond hair"]={ 0x1F471, 0x1F3FD }, + ["person: medium skin tone, curly hair"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F9B1 }, + ["person: medium skin tone, red hair"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F9B0 }, + ["person: medium skin tone, white hair"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F9B3 }, ["person: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE }, + ["person: medium-dark skin tone, bald"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F9B2 }, ["person: medium-dark skin tone, blond hair"]={ 0x1F471, 0x1F3FE }, + ["person: medium-dark skin tone, curly hair"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F9B1 }, + ["person: medium-dark skin tone, red hair"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F9B0 }, + ["person: medium-dark skin tone, white hair"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F9B3 }, ["person: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC }, + ["person: medium-light skin tone, bald"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F9B2 }, ["person: medium-light skin tone, blond hair"]={ 0x1F471, 0x1F3FC }, + ["person: medium-light skin tone, curly hair"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F9B1 }, + ["person: medium-light skin tone, red hair"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F9B0 }, + ["person: medium-light skin tone, white hair"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F9B3 }, + ["person: red hair"]={ 0x1F9D1, 0x200D, 0x1F9B0 }, + ["person: white hair"]={ 0x1F9D1, 0x200D, 0x1F9B3 }, ["petri dish"]={ 0x1F9EB }, ["pick"]={ 0x26CF, 0xFE0F }, + ["pickup truck"]={ 0x1F6FB }, ["pie"]={ 0x1F967 }, ["pig"]={ 0x1F416 }, ["pig face"]={ 0x1F437 }, ["pig nose"]={ 0x1F43D }, ["pile of poo"]={ 0x1F4A9 }, ["pill"]={ 0x1F48A }, + ["pilot"]={ 0x1F9D1, 0x200D, 0x2708, 0xFE0F }, + ["pilot: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x2708, 0xFE0F }, + ["pilot: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x2708, 0xFE0F }, + ["pilot: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x2708, 0xFE0F }, + ["pilot: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x2708, 0xFE0F }, + ["pilot: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x2708, 0xFE0F }, + ["pinched fingers"]={ 0x1F90C }, + ["pinched fingers: dark skin tone"]={ 0x1F90C, 0x1F3FF }, + ["pinched fingers: light skin tone"]={ 0x1F90C, 0x1F3FB }, + ["pinched fingers: medium skin tone"]={ 0x1F90C, 0x1F3FD }, + ["pinched fingers: medium-dark skin tone"]={ 0x1F90C, 0x1F3FE }, + ["pinched fingers: medium-light skin tone"]={ 0x1F90C, 0x1F3FC }, ["pinching hand"]={ 0x1F90F }, ["pinching hand: dark skin tone"]={ 0x1F90F, 0x1F3FF }, ["pinching hand: light skin tone"]={ 0x1F90F, 0x1F3FB }, @@ -2054,11 +2262,15 @@ return { ["pisces"]={ 0x2653 }, ["pistol"]={ 0x1F52B }, ["pizza"]={ 0x1F355 }, + ["piñata"]={ 0x1FA85 }, + ["placard"]={ 0x1FAA7 }, ["place of worship"]={ 0x1F6D0 }, ["play button"]={ 0x25B6, 0xFE0F }, ["play or pause button"]={ 0x23EF, 0xFE0F }, ["pleading face"]={ 0x1F97A }, - ["plus sign"]={ 0x2795 }, + ["plunger"]={ 0x1FAA0 }, + ["plus"]={ 0x2795 }, + ["polar bear"]={ 0x1F43B, 0x200D, 0x2744, 0xFE0F }, ["police car"]={ 0x1F693 }, ["police car light"]={ 0x1F6A8 }, ["police officer"]={ 0x1F46E }, @@ -2076,6 +2288,7 @@ return { ["pot of food"]={ 0x1F372 }, ["potable water"]={ 0x1F6B0 }, ["potato"]={ 0x1F954 }, + ["potted plant"]={ 0x1FAB4 }, ["poultry leg"]={ 0x1F357 }, ["pound banknote"]={ 0x1F4B7 }, ["pouting cat"]={ 0x1F63E }, @@ -2101,7 +2314,6 @@ return { ["princess: medium-dark skin tone"]={ 0x1F478, 0x1F3FE }, ["princess: medium-light skin tone"]={ 0x1F478, 0x1F3FC }, ["printer"]={ 0x1F5A8, 0xFE0F }, - ["probing cane"]={ 0x1F9AF }, ["prohibited"]={ 0x1F6AB }, ["purple circle"]={ 0x1F7E3 }, ["purple heart"]={ 0x1F49C }, @@ -2187,10 +2399,12 @@ return { ["ringed planet"]={ 0x1FA90 }, ["roasted sweet potato"]={ 0x1F360 }, ["robot"]={ 0x1F916 }, + ["rock"]={ 0x1FAA8 }, ["rocket"]={ 0x1F680 }, ["roll of paper"]={ 0x1F9FB }, ["rolled-up newspaper"]={ 0x1F5DE, 0xFE0F }, ["roller coaster"]={ 0x1F3A2 }, + ["roller skate"]={ 0x1F6FC }, ["rolling on the floor laughing"]={ 0x1F923 }, ["rooster"]={ 0x1F413 }, ["rose"]={ 0x1F339 }, @@ -2220,10 +2434,18 @@ return { ["saxophone"]={ 0x1F3B7 }, ["scarf"]={ 0x1F9E3 }, ["school"]={ 0x1F3EB }, + ["scientist"]={ 0x1F9D1, 0x200D, 0x1F52C }, + ["scientist: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F52C }, + ["scientist: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F52C }, + ["scientist: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F52C }, + ["scientist: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F52C }, + ["scientist: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F52C }, ["scissors"]={ 0x2702, 0xFE0F }, ["scorpio"]={ 0x264F }, ["scorpion"]={ 0x1F982 }, + ["screwdriver"]={ 0x1FA9B }, ["scroll"]={ 0x1F4DC }, + ["seal"]={ 0x1F9AD }, ["seat"]={ 0x1F4BA }, ["see-no-evil monkey"]={ 0x1F648 }, ["seedling"]={ 0x1F331 }, @@ -2236,6 +2458,7 @@ return { ["service dog"]={ 0x1F415, 0x200D, 0x1F9BA }, ["seven o’clock"]={ 0x1F556 }, ["seven-thirty"]={ 0x1F562 }, + ["sewing needle"]={ 0x1FAA1 }, ["shallow pan of food"]={ 0x1F958 }, ["shamrock"]={ 0x2618, 0xFE0F }, ["shark"]={ 0x1F988 }, @@ -2259,6 +2482,12 @@ return { ["sign of the horns: medium skin tone"]={ 0x1F918, 0x1F3FD }, ["sign of the horns: medium-dark skin tone"]={ 0x1F918, 0x1F3FE }, ["sign of the horns: medium-light skin tone"]={ 0x1F918, 0x1F3FC }, + ["singer"]={ 0x1F9D1, 0x200D, 0x1F3A4 }, + ["singer: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F3A4 }, + ["singer: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F3A4 }, + ["singer: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F3A4 }, + ["singer: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F3A4 }, + ["singer: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F3A4 }, ["six o’clock"]={ 0x1F555 }, ["six-thirty"]={ 0x1F561 }, ["skateboard"]={ 0x1F6F9 }, @@ -2285,6 +2514,7 @@ return { ["smiling face with horns"]={ 0x1F608 }, ["smiling face with smiling eyes"]={ 0x1F60A }, ["smiling face with sunglasses"]={ 0x1F60E }, + ["smiling face with tear"]={ 0x1F972 }, ["smirking face"]={ 0x1F60F }, ["snail"]={ 0x1F40C }, ["snake"]={ 0x1F40D }, @@ -2345,6 +2575,12 @@ return { ["stopwatch"]={ 0x23F1, 0xFE0F }, ["straight ruler"]={ 0x1F4CF }, ["strawberry"]={ 0x1F353 }, + ["student"]={ 0x1F9D1, 0x200D, 0x1F393 }, + ["student: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F393 }, + ["student: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F393 }, + ["student: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F393 }, + ["student: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F393 }, + ["student: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F393 }, ["studio microphone"]={ 0x1F399, 0xFE0F }, ["stuffed flatbread"]={ 0x1F959 }, ["sun"]={ 0x2600, 0xFE0F }, @@ -2374,19 +2610,32 @@ return { ["suspension railway"]={ 0x1F69F }, ["swan"]={ 0x1F9A2 }, ["sweat droplets"]={ 0x1F4A6 }, - ["swim brief"]={ 0x1FA72 }, ["synagogue"]={ 0x1F54D }, ["syringe"]={ 0x1F489 }, ["t-rex"]={ 0x1F996 }, ["t-shirt"]={ 0x1F455 }, ["taco"]={ 0x1F32E }, ["takeout box"]={ 0x1F961 }, + ["tamale"]={ 0x1FAD4 }, ["tanabata tree"]={ 0x1F38B }, ["tangerine"]={ 0x1F34A }, ["taurus"]={ 0x2649 }, ["taxi"]={ 0x1F695 }, + ["teacher"]={ 0x1F9D1, 0x200D, 0x1F3EB }, + ["teacher: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F3EB }, + ["teacher: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F3EB }, + ["teacher: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F3EB }, + ["teacher: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F3EB }, + ["teacher: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F3EB }, ["teacup without handle"]={ 0x1F375 }, + ["teapot"]={ 0x1FAD6 }, ["tear-off calendar"]={ 0x1F4C6 }, + ["technologist"]={ 0x1F9D1, 0x200D, 0x1F4BB }, + ["technologist: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F4BB }, + ["technologist: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F4BB }, + ["technologist: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F4BB }, + ["technologist: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F4BB }, + ["technologist: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F4BB }, ["teddy bear"]={ 0x1F9F8 }, ["telephone"]={ 0x260E, 0xFE0F }, ["telephone receiver"]={ 0x1F4DE }, @@ -2399,6 +2648,7 @@ return { ["test tube"]={ 0x1F9EA }, ["thermometer"]={ 0x1F321, 0xFE0F }, ["thinking face"]={ 0x1F914 }, + ["thong sandal"]={ 0x1FA74 }, ["thought balloon"]={ 0x1F4AD }, ["thread"]={ 0x1F9F5 }, ["three o’clock"]={ 0x1F552 }, @@ -2426,6 +2676,7 @@ return { ["tongue"]={ 0x1F445 }, ["toolbox"]={ 0x1F9F0 }, ["tooth"]={ 0x1F9B7 }, + ["toothbrush"]={ 0x1FAA5 }, ["top arrow"]={ 0x1F51D }, ["top hat"]={ 0x1F3A9 }, ["tornado"]={ 0x1F32A, 0xFE0F }, @@ -2435,6 +2686,8 @@ return { ["train"]={ 0x1F686 }, ["tram"]={ 0x1F68A }, ["tram car"]={ 0x1F68B }, + ["transgender flag"]={ 0x1F3F3, 0xFE0F, 0x200D, 0x26A7, 0xFE0F }, + ["transgender symbol"]={ 0x26A7, 0xFE0F }, ["triangular flag"]={ 0x1F6A9 }, ["triangular ruler"]={ 0x1F4D0 }, ["trident emblem"]={ 0x1F531 }, @@ -2519,6 +2772,7 @@ return { ["whale"]={ 0x1F40B }, ["wheel of dharma"]={ 0x2638, 0xFE0F }, ["wheelchair symbol"]={ 0x267F }, + ["white cane"]={ 0x1F9AF }, ["white circle"]={ 0x26AA }, ["white exclamation mark"]={ 0x2755 }, ["white flag"]={ 0x1F3F3, 0xFE0F }, @@ -2533,6 +2787,7 @@ return { ["wilted flower"]={ 0x1F940 }, ["wind chime"]={ 0x1F390 }, ["wind face"]={ 0x1F32C, 0xFE0F }, + ["window"]={ 0x1FA9F }, ["wine glass"]={ 0x1F377 }, ["winking face"]={ 0x1F609 }, ["winking face with tongue"]={ 0x1F61C }, @@ -2660,6 +2915,12 @@ return { ["woman farmer: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F33E }, ["woman farmer: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F33E }, ["woman farmer: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F33E }, + ["woman feeding baby"]={ 0x1F469, 0x200D, 0x1F37C }, + ["woman feeding baby: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F37C }, + ["woman feeding baby: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F37C }, + ["woman feeding baby: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F37C }, + ["woman feeding baby: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F37C }, + ["woman feeding baby: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F37C }, ["woman firefighter"]={ 0x1F469, 0x200D, 0x1F692 }, ["woman firefighter: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F692 }, ["woman firefighter: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F692 }, @@ -2739,6 +3000,12 @@ return { ["woman in steamy room: medium skin tone"]={ 0x1F9D6, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, ["woman in steamy room: medium-dark skin tone"]={ 0x1F9D6, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, ["woman in steamy room: medium-light skin tone"]={ 0x1F9D6, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman in tuxedo"]={ 0x1F935, 0x200D, 0x2640, 0xFE0F }, + ["woman in tuxedo: dark skin tone"]={ 0x1F935, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman in tuxedo: light skin tone"]={ 0x1F935, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman in tuxedo: medium skin tone"]={ 0x1F935, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman in tuxedo: medium-dark skin tone"]={ 0x1F935, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman in tuxedo: medium-light skin tone"]={ 0x1F935, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, ["woman judge"]={ 0x1F469, 0x200D, 0x2696, 0xFE0F }, ["woman judge: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x2696, 0xFE0F }, ["woman judge: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x2696, 0xFE0F }, @@ -2931,12 +3198,18 @@ return { ["woman with headscarf: medium skin tone"]={ 0x1F9D5, 0x1F3FD }, ["woman with headscarf: medium-dark skin tone"]={ 0x1F9D5, 0x1F3FE }, ["woman with headscarf: medium-light skin tone"]={ 0x1F9D5, 0x1F3FC }, - ["woman with probing cane"]={ 0x1F469, 0x200D, 0x1F9AF }, - ["woman with probing cane: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F9AF }, - ["woman with probing cane: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F9AF }, - ["woman with probing cane: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F9AF }, - ["woman with probing cane: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F9AF }, - ["woman with probing cane: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F9AF }, + ["woman with veil"]={ 0x1F470, 0x200D, 0x2640, 0xFE0F }, + ["woman with veil: dark skin tone"]={ 0x1F470, 0x1F3FF, 0x200D, 0x2640, 0xFE0F }, + ["woman with veil: light skin tone"]={ 0x1F470, 0x1F3FB, 0x200D, 0x2640, 0xFE0F }, + ["woman with veil: medium skin tone"]={ 0x1F470, 0x1F3FD, 0x200D, 0x2640, 0xFE0F }, + ["woman with veil: medium-dark skin tone"]={ 0x1F470, 0x1F3FE, 0x200D, 0x2640, 0xFE0F }, + ["woman with veil: medium-light skin tone"]={ 0x1F470, 0x1F3FC, 0x200D, 0x2640, 0xFE0F }, + ["woman with white cane"]={ 0x1F469, 0x200D, 0x1F9AF }, + ["woman with white cane: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F9AF }, + ["woman with white cane: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F9AF }, + ["woman with white cane: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F9AF }, + ["woman with white cane: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F9AF }, + ["woman with white cane: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F9AF }, ["woman zombie"]={ 0x1F9DF, 0x200D, 0x2640, 0xFE0F }, ["woman: bald"]={ 0x1F469, 0x200D, 0x1F9B2 }, ["woman: blond hair"]={ 0x1F471, 0x200D, 0x2640, 0xFE0F }, @@ -2984,20 +3257,32 @@ return { ["women holding hands: dark skin tone, medium-dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FE }, ["women holding hands: dark skin tone, medium-light skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FC }, ["women holding hands: light skin tone"]={ 0x1F46D, 0x1F3FB }, + ["women holding hands: light skin tone, dark skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FF }, + ["women holding hands: light skin tone, medium skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FD }, + ["women holding hands: light skin tone, medium-dark skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FE }, + ["women holding hands: light skin tone, medium-light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FC }, ["women holding hands: medium skin tone"]={ 0x1F46D, 0x1F3FD }, + ["women holding hands: medium skin tone, dark skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FF }, ["women holding hands: medium skin tone, light skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FB }, + ["women holding hands: medium skin tone, medium-dark skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FE }, ["women holding hands: medium skin tone, medium-light skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FC }, ["women holding hands: medium-dark skin tone"]={ 0x1F46D, 0x1F3FE }, + ["women holding hands: medium-dark skin tone, dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FF }, ["women holding hands: medium-dark skin tone, light skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FB }, ["women holding hands: medium-dark skin tone, medium skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FD }, ["women holding hands: medium-dark skin tone, medium-light skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FC }, ["women holding hands: medium-light skin tone"]={ 0x1F46D, 0x1F3FC }, + ["women holding hands: medium-light skin tone, dark skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FF }, ["women holding hands: medium-light skin tone, light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FB }, + ["women holding hands: medium-light skin tone, medium skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FD }, + ["women holding hands: medium-light skin tone, medium-dark skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FE }, ["women with bunny ears"]={ 0x1F46F, 0x200D, 0x2640, 0xFE0F }, ["women wrestling"]={ 0x1F93C, 0x200D, 0x2640, 0xFE0F }, ["women’s room"]={ 0x1F6BA }, + ["wood"]={ 0x1FAB5 }, ["woozy face"]={ 0x1F974 }, ["world map"]={ 0x1F5FA, 0xFE0F }, + ["worm"]={ 0x1FAB1 }, ["worried face"]={ 0x1F61F }, ["wrapped gift"]={ 0x1F381 }, ["wrench"]={ 0x1F527 }, diff --git a/tex/context/base/mkiv/cont-fil.mkiv b/tex/context/base/mkiv/cont-fil.mkiv index 9257e2e1e..aa7d9ddb3 100644 --- a/tex/context/base/mkiv/cont-fil.mkiv +++ b/tex/context/base/mkiv/cont-fil.mkiv @@ -16,137 +16,142 @@ \writestatus{loading}{ConTeXt File Synonyms} -\definefilesynonym [chemics] [chemic] - -\definefilesynonym [unit] [units] - -\definefilesynonym [pstric] [pstricks] -\definefilesynonym [pstrick] [pstricks] - -\definefilesynonym [finance] [financ] - -\definefilesynonym [dir-make] [dir-01] -\definefilesynonym [dir-identify] [dir-05] - -\definefilesynonym [int-load] [set-11] -\definefilesynonym [int-make] [set-12] - - \definefilesynonym [fig-base] [fig-00] - \definefilesynonym [fig-make] [fig-01] - \definefilesynonym [fig-fake] [fig-02] - \definefilesynonym [fig-missing] [fig-06] - -\definefilesynonym [exi-interface] [exi-21] - - \definefilesynonym [res-make] [res-01] - \definefilesynonym [res-base] [res-04] - \definefilesynonym [res-crop] [res-07] - \definefilesynonym [res-trace] [res-08] - \definefilesynonym [res-log] [res-09] - \definefilesynonym [res-identify] [res-12] - - \definefilesynonym [med-show] [res-50] - -\definefilesynonym [pre-general] [pre-00] -\definefilesynonym [pre-01] [present-original] -\definefilesynonym [pre-original] [present-original] -\definefilesynonym [pre-02] [present-green] -\definefilesynonym [pre-green] [present-green] -\definefilesynonym [pre-03] [present-funny] -\definefilesynonym [pre-funny] [present-funny] -\definefilesynonym [pre-04] [present-colorful] -\definefilesynonym [pre-colorful] [present-colorful] -\definefilesynonym [pre-05] [present-fuzzy] -\definefilesynonym [pre-fuzzy] [present-fuzzy] -\definefilesynonym [pre-polish] [pre-06] -\definefilesynonym [pre-spider] [pre-07] -\definefilesynonym [pre-wonder] [pre-08] -\definefilesynonym [pre-09] [present-windows] -\definefilesynonym [pre-windows] [present-windows] -\definefilesynonym [pre-10] [present-grow] -\definefilesynonym [pre-grow] [present-grow] -\definefilesynonym [pre-11] [present-stack] -\definefilesynonym [pre-stack] [present-stack] -\definefilesynonym [pre-arrows] [pre-12] -\definefilesynonym [pre-writing] [pre-13] -\definefilesynonym [pre-split] [present-split] -\definefilesynonym [pre-14] [present-split] -\definefilesynonym [pre-balls] [present-balls] -\definefilesynonym [pre-15] [present-balls] -\definefilesynonym [pre-knot] [pre-16] -\definefilesynonym [pre-17] [present-weird] -\definefilesynonym [pre-weird] [present-weird] -\definefilesynonym [pre-shade] [pre-18] -\definefilesynonym [pre-organic] [pre-19] -\definefilesynonym [pre-speckle] [pre-20] -\definefilesynonym [pre-zoom] [pre-21] -\definefilesynonym [pre-cycle] [pre-22] -\definefilesynonym [pre-super] [pre-23] -%definefilesynonym [pre-more] [pre-24] -%definefilesynonym [pre-more] [pre-25] -\definefilesynonym [pre-more] [pre-26] -%definefilesynonym [pre-more] [pre-27] -%definefilesynonym [pre-more] [pre-28] -%definefilesynonym [pre-more] [pre-29] -%definefilesynonym [pre-more] [pre-30] -\definefilesynonym [pre-41] [present-tiles] -\definefilesynonym [pre-60] [present-stepwise] -\definefilesynonym [pre-stepwise] [present-stepwise] -\definefilesynonym [pre-61] [present-stepper] -\definefilesynonym [pre-stepper] [present-stepper] -\definefilesynonym [pre-62] [present-overlap] -\definefilesynonym [pre-69] [present-wobbling] -\definefilesynonym [pre-punk] [present-punk] -\definefilesynonym [pre-70] [present-punk] -\definefilesynonym [pre-random] [present-random] -\definefilesynonym [pre-71] [present-random] - -\definefilesynonym [abr-01] [abbreviations-pseudocaps] -\definefilesynonym [abr-02] [abbreviations-smallcaps] -\definefilesynonym [abr-03] [abbreviations-words] -\definefilesynonym [abr-04] [abbreviations-mixed] - -\definefilesynonym [art-01] [article-basic] -\definefilesynonym [article] [article-basic] -\definefilesynonym [mag-01] [magazine-basic] -\definefilesynonym [magazine] [magazine-basic] -\definefilesynonym [mod-01] [module-basic] -\definefilesynonym [module] [module-basic] - -\definefilesynonym [map-10] [maps] % for a while - -\definefilesynonym [mml] [mathml] -\definefilesynonym [cml] [chemml] - -\definefilesynonym [letter] [cor-01] -\definefilesynonym [memo] [cor-02] -\definefilesynonym [resume] [cor-03] - -\definefilesynonym [fnt-10] [fonts-complete] -\definefilesynonym [fnt-11] [fonts-system] -\definefilesynonym [fnt-20] [fonts-steps] -\definefilesynonym [fnt-21] [fonts-steps] -\definefilesynonym [fnt-22] [fonts-engines] -\definefilesynonym [fnt-23] [fonts-shapes] -\definefilesynonym [fnt-24] [fonts-cjk] -\definefilesynonym [fnt-25] [math-characters] -\definefilesynonym [fnt-28] [fonts-goodies] -\definefilesynonym [fnt-29] [fonts-shapes] -\definefilesynonym [fnt-31] [fonts-coverage] -\definefilesynonym [fnt-33] [math-coverage] - -\definefilesynonym [mat-10] [math-characters] -\definefilesynonym [mat-11] [math-characters] -\definefilesynonym [mat-12] [math-parameters] -\definefilesynonym [mat-20] [math-parameters] - -\definefilesynonym [syn-01] [syntax] - -\definefilesynonym [reg-01] [regimes-list] - -\definefilesynonym [set-11] [setups-basics] -\definefilesynonym [set-12] [setups-overview] -%definefilesynonym [set-13] [setups-proofing] -%definefilesynonym [set-15] [setups-generate] +\definefilesynonym [chemics] [chemic] + +\definefilesynonym [unit] [units] + +\definefilesynonym [pstric] [pstricks] +\definefilesynonym [pstrick] [pstricks] + +\definefilesynonym [finance] [financ] + +\definefilesynonym [dir-make] [dir-01] +\definefilesynonym [dir-identify] [dir-05] + +\definefilesynonym [int-load] [set-11] +\definefilesynonym [int-make] [set-12] + + \definefilesynonym [fig-base] [fig-00] + \definefilesynonym [fig-make] [fig-01] + \definefilesynonym [fig-fake] [fig-02] + \definefilesynonym [fig-missing] [fig-06] + + \definefilesynonym [exi-interface] [exi-21] + + \definefilesynonym [res-make] [res-01] + \definefilesynonym [res-base] [res-04] + \definefilesynonym [res-crop] [res-07] + \definefilesynonym [res-trace] [res-08] + \definefilesynonym [res-log] [res-09] + \definefilesynonym [res-identify] [res-12] + + \definefilesynonym [med-show] [res-50] + +\definefilesynonym [pre-general] [pre-00] +\definefilesynonym [pre-01] [present-original] +\definefilesynonym [pre-original] [present-original] +\definefilesynonym [pre-02] [present-green] +\definefilesynonym [pre-green] [present-green] +\definefilesynonym [pre-03] [present-funny] +\definefilesynonym [pre-funny] [present-funny] +\definefilesynonym [pre-04] [present-colorful] +\definefilesynonym [pre-colorful] [present-colorful] +\definefilesynonym [pre-05] [present-fuzzy] +\definefilesynonym [pre-fuzzy] [present-fuzzy] +\definefilesynonym [pre-polish] [pre-06] +\definefilesynonym [pre-spider] [pre-07] +\definefilesynonym [pre-wonder] [pre-08] +\definefilesynonym [pre-09] [present-windows] +\definefilesynonym [pre-windows] [present-windows] +\definefilesynonym [pre-10] [present-grow] +\definefilesynonym [pre-grow] [present-grow] +\definefilesynonym [pre-11] [present-stack] +\definefilesynonym [pre-stack] [present-stack] +\definefilesynonym [pre-arrows] [pre-12] +\definefilesynonym [pre-writing] [pre-13] +\definefilesynonym [pre-split] [present-split] +\definefilesynonym [pre-14] [present-split] +\definefilesynonym [pre-balls] [present-balls] +\definefilesynonym [pre-15] [present-balls] +\definefilesynonym [pre-knot] [pre-16] +\definefilesynonym [pre-17] [present-weird] +\definefilesynonym [pre-weird] [present-weird] +\definefilesynonym [pre-shade] [pre-18] +\definefilesynonym [pre-organic] [pre-19] +\definefilesynonym [pre-speckle] [pre-20] +\definefilesynonym [pre-zoom] [pre-21] +\definefilesynonym [pre-cycle] [pre-22] +\definefilesynonym [pre-super] [pre-23] +%definefilesynonym [pre-more] [pre-24] +%definefilesynonym [pre-more] [pre-25] +\definefilesynonym [pre-more] [pre-26] +%definefilesynonym [pre-more] [pre-27] +%definefilesynonym [pre-more] [pre-28] +%definefilesynonym [pre-more] [pre-29] +%definefilesynonym [pre-more] [pre-30] +\definefilesynonym [pre-41] [present-tiles] +\definefilesynonym [pre-60] [present-stepwise] +\definefilesynonym [pre-stepwise] [present-stepwise] +\definefilesynonym [pre-61] [present-stepper] +\definefilesynonym [pre-stepper] [present-stepper] +\definefilesynonym [pre-62] [present-overlap] +\definefilesynonym [pre-69] [present-wobbling] +\definefilesynonym [pre-punk] [present-punk] +\definefilesynonym [pre-70] [present-punk] +\definefilesynonym [pre-random] [present-random] +\definefilesynonym [pre-71] [present-random] + +\definefilesynonym [abr-01] [abbreviations-pseudocaps] +\definefilesynonym [abr-02] [abbreviations-smallcaps] +\definefilesynonym [abr-03] [abbreviations-words] +\definefilesynonym [abr-04] [abbreviations-mixed] + +\definefilesynonym [art-01] [article-basic] +\definefilesynonym [article] [article-basic] +\definefilesynonym [mag-01] [magazine-basic] +\definefilesynonym [magazine] [magazine-basic] +\definefilesynonym [mod-01] [module-basic] +\definefilesynonym [module] [module-basic] + +\definefilesynonym [map-10] [maps] % for a while + +\definefilesynonym [mml] [mathml] +\definefilesynonym [cml] [chemml] + +\definefilesynonym [letter] [cor-01] +\definefilesynonym [memo] [cor-02] +\definefilesynonym [resume] [cor-03] + +\definefilesynonym [fnt-10] [fonts-complete] +\definefilesynonym [fnt-11] [fonts-system] +\definefilesynonym [fnt-20] [fonts-steps] +\definefilesynonym [fnt-21] [fonts-steps] +\definefilesynonym [fnt-22] [fonts-engines] +\definefilesynonym [fnt-23] [fonts-shapes] +\definefilesynonym [fnt-24] [fonts-cjk] +\definefilesynonym [fnt-25] [math-characters] +\definefilesynonym [fnt-28] [fonts-goodies] +\definefilesynonym [fnt-29] [fonts-shapes] +\definefilesynonym [fnt-31] [fonts-coverage] +\definefilesynonym [fnt-33] [math-coverage] + +\definefilesynonym [mat-10] [math-characters] +\definefilesynonym [mat-11] [math-characters] +\definefilesynonym [mat-12] [math-parameters] +\definefilesynonym [mat-20] [math-parameters] + +\definefilesynonym [syn-01] [syntax] + +\definefilesynonym [reg-01] [regimes-list] + +\definefilesynonym [set-11] [setups-basics] +\definefilesynonym [set-12] [setups-overview] +%definefilesynonym [set-13] [setups-proofing] +%definefilesynonym [set-15] [setups-generate] + +\ifcase\contextlmtxmode \else + \definefilesynonym [ecmascript] [libs-imp-mujs] + \definefilesynonym [zint] [libs-imp-zint] +\fi \endinput diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index 2cc2a1098..cd700391a 100644 --- a/tex/context/base/mkiv/cont-new.mkiv +++ b/tex/context/base/mkiv/cont-new.mkiv @@ -13,7 +13,7 @@ % \normalend % uncomment this to get the real base runtime -\newcontextversion{2020.01.26 18:34} +\newcontextversion{2020.02.11 16:36} %D This file is loaded at runtime, thereby providing an excellent place for %D hacks, patches, extensions and new features. diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv index d4206a4e8..30389e598 100644 --- a/tex/context/base/mkiv/context.mkiv +++ b/tex/context/base/mkiv/context.mkiv @@ -45,7 +45,7 @@ %D {YYYY.MM.DD HH:MM} format. \edef\contextformat {\jobname} -\edef\contextversion{2020.01.26 18:34} +\edef\contextversion{2020.02.11 16:36} \edef\contextkind {beta} %D Kind of special: diff --git a/tex/context/base/mkiv/context.mkxl b/tex/context/base/mkiv/context.mkxl index 1b4da4e96..ef3fddc3d 100644 --- a/tex/context/base/mkiv/context.mkxl +++ b/tex/context/base/mkiv/context.mkxl @@ -29,7 +29,7 @@ %D {YYYY.MM.DD HH:MM} format. \edef\contextformat {\jobname} -\edef\contextversion{2020.01.26 18:34} +\edef\contextversion{2020.02.11 16:36} \edef\contextkind {beta} %D Kind of special: diff --git a/tex/context/base/mkiv/data-tmp.lua b/tex/context/base/mkiv/data-tmp.lua index bfced1e64..9b0117c15 100644 --- a/tex/context/base/mkiv/data-tmp.lua +++ b/tex/context/base/mkiv/data-tmp.lua @@ -364,7 +364,7 @@ function caches.is_writable(filepath,filename) return is_writable(tmaname) end -local saveoptions = { compact = true } +local saveoptions = { compact = true, accurate = not JITSUPPORTED } function caches.savedata(filepath,filename,data,fast) local tmaname, tmcname = setluanames(filepath,filename) diff --git a/tex/context/base/mkiv/driv-shp.lua b/tex/context/base/mkiv/driv-shp.lua index cc8b6bdbe..a4e36105d 100644 --- a/tex/context/base/mkiv/driv-shp.lua +++ b/tex/context/base/mkiv/driv-shp.lua @@ -381,6 +381,7 @@ flush_character = function(current,font,char,factor,vfcommands,pos_h,pos_v,pos_r factor = 0 end end + if pos_r == righttoleft_code then pos_h = pos_h - width end @@ -390,6 +391,7 @@ flush_character = function(current,font,char,factor,vfcommands,pos_h,pos_v,pos_r if vfcommands then flush_vf_packet(pos_h,pos_v,pos_r,font,char,data,factor,vfcommands) -- also f ? else + -- kind of messy that we do orientation here and offsets elsewhere local orientation = data.orientation if orientation and (orientation == 1 or orientation == 3) then local x = data.xoffset @@ -401,10 +403,10 @@ flush_character = function(current,font,char,factor,vfcommands,pos_h,pos_v,pos_r pos_v = pos_v + y end pushorientation(orientation,pos_h,pos_v) - flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,naturalwidth,factor,width,f,e) + flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor) -- ,naturalwidth,width) poporientation(orientation,pos_h,pos_v) else - flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,naturalwidth,factor,width,f,e) + flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor) -- ,naturalwidth,width) end end return width, height, depth diff --git a/tex/context/base/mkiv/file-job.lua b/tex/context/base/mkiv/file-job.lua index 4b29f57ec..407c3c15d 100644 --- a/tex/context/base/mkiv/file-job.lua +++ b/tex/context/base/mkiv/file-job.lua @@ -326,6 +326,8 @@ end local suffixes = { mkvi = usetexfile, mkiv = usetexfile, + mklx = usetexfile, + mkxl = usetexfile, tex = usetexfile, luc = useluafile, lua = useluafile, diff --git a/tex/context/base/mkiv/font-con.lua b/tex/context/base/mkiv/font-con.lua index e42d20d4e..1bb63aa51 100644 --- a/tex/context/base/mkiv/font-con.lua +++ b/tex/context/base/mkiv/font-con.lua @@ -1139,6 +1139,7 @@ hashmethods.normal = function(list) m = m + 1 t[m] = k .. '=' .. tostring(v) end + sort(t) s[n] = k .. '={' .. concat(t,",") .. "}" else s[n] = k .. '=' .. tostring(v) diff --git a/tex/context/base/mkiv/font-ctx.lua b/tex/context/base/mkiv/font-ctx.lua index cbb81cdb7..bf14dd309 100644 --- a/tex/context/base/mkiv/font-ctx.lua +++ b/tex/context/base/mkiv/font-ctx.lua @@ -887,23 +887,6 @@ specifiers.definecontext = definecontext -- we extend the hasher: --- constructors.hashmethods.virtual = function(list) --- local s = { } --- local n = 0 --- for k, v in next, list do --- n = n + 1 --- s[n] = k -- no checking on k --- end --- if n > 0 then --- sort(s) --- for i=1,n do --- local k = s[i] --- s[i] = k .. '=' .. tostring(list[k]) --- end --- return concat(s,"+") --- end --- end - constructors.hashmethods.virtual = function(list) local s = { } local n = 0 @@ -924,6 +907,54 @@ constructors.hashmethods.virtual = function(list) end end +if not JITSUPPORTED then + + constructors.hashmethods.normal = function(list) + local s = { } + local n = 0 + for k, v in next, list do + if not k then + -- no need to add to hash + elseif k == "number" or k == "features" then + -- no need to add to hash (maybe we need a skip list) + else + n = n + 1 + if type(v) == "table" then + -- table.sequenced + local t = { } + local m = 0 + for k, v in next, v do + m = m + 1 + t[m] = format("%q=%q",k,v) + end + sort(t) + s[n] = format("%q={%s}",k,concat(t,",")) + else + s[n] = format("%q=%q",k,v) + end + end + end + if n > 0 then + sort(s) + return concat(s,"+") + end + end + + constructors.hashmethods.virtual = function(list) + local s = { } + local n = 0 + for k, v in next, list do + n = n + 1 + s[n] = format("%q=%q",k,v) + end + if n > 0 then + sort(s) + return concat(s,"+") + end + end + +end + -- end of redefine -- local withcache = { } -- concat might be less efficient than nested tables diff --git a/tex/context/base/mkiv/font-dsp.lua b/tex/context/base/mkiv/font-dsp.lua index 7777f9c6a..3058be37b 100644 --- a/tex/context/base/mkiv/font-dsp.lua +++ b/tex/context/base/mkiv/font-dsp.lua @@ -3237,7 +3237,8 @@ function readers.sbix(f,fontdata,specification) return b.ppem < a.ppem end end) - local glyphs = { } + local glyphs = { } + local delayed = CONTEXTLMTXMODE and CONTEXTLMTXMODE > 0 or fonts.handlers.typethree for i=1,nofstrikes do local strike = strikes[i] local strikeppem = strike.ppem @@ -3254,13 +3255,28 @@ function readers.sbix(f,fontdata,specification) local datasize = nextoffset - glyphoffset if datasize > 0 then setposition(f,strikeoffset + glyphoffset) + local x = readshort(f) + local y = readshort(f) + local tag = readtag(f) -- or just skip, we never needed it till now + local size = datasize - 8 + local data = nil + local offset = nil + if delayed then + offset = getposition(f) + data = nil + else + data = readstring(f,size) + size = nil + end shapes[i] = { - x = readshort(f), - y = readshort(f), - tag = readtag(f), -- maybe for tracing - data = readstring(f,datasize-8), - ppem = strikeppem, -- not used, for tracing - ppi = strikeppi, -- not used, for tracing + x = x, + y = y, + o = offset, + s = size, + data = data, + -- tag = tag, -- maybe for tracing + -- ppem = strikeppem, -- not used, for tracing + -- ppi = strikeppi, -- not used, for tracing } done = done + 1 if done == nofglyphs then @@ -3462,32 +3478,48 @@ do local default = { width = 0, height = 0 } local glyphs = fontdata.glyphs + local delayed = CONTEXTLMTXMODE and CONTEXTLMTXMODE > 0 or fonts.handlers.typethree for index, subtable in sortedhash(shapes) do if type(subtable) == "table" then local data = nil + local size = nil local metrics = default local format = subtable.format local offset = subtable.offsets[index] setposition(f,offset) if format == 17 then metrics = getsmallmetrics(f) - data = readstring(f,readulong(f)) + size = true elseif format == 18 then metrics = getbigmetrics(f) - data = readstring(f,readulong(f)) + size = true elseif format == 19 then metrics = subtable.metrics - data = readstring(f,readulong(f)) + size = true else -- forget about it end + if size then + size = readulong(f) + if delayed then + offset = getposition(f) + data = nil + else + offset = nil + data = readstring(f,size) + size = nil + end + else + offset = nil + end local x = metrics.width local y = metrics.height shapes[index] = { - -- maybe some metrics x = x, y = y, + o = offset, + s = size, data = data, } -- I'll look into this in more details when needed @@ -3498,12 +3530,11 @@ do local height = width * y/x glyph.boundingbox = { 0, 0, width, height } end - else shapes[index] = { x = 0, y = 0, - data = "", + data = "", -- or just nil } end end diff --git a/tex/context/base/mkiv/font-mis.lua b/tex/context/base/mkiv/font-mis.lua index da02ab608..fe972114f 100644 --- a/tex/context/base/mkiv/font-mis.lua +++ b/tex/context/base/mkiv/font-mis.lua @@ -21,7 +21,7 @@ local readers = otf.readers if readers then - otf.version = otf.version or 3.110 + otf.version = otf.version or 3.111 otf.cache = otf.cache or containers.define("fonts", "otl", otf.version, true) function fonts.helpers.getfeatures(name,save) diff --git a/tex/context/base/mkiv/font-ocl.lua b/tex/context/base/mkiv/font-ocl.lua index 77e1538f9..eef221e46 100644 --- a/tex/context/base/mkiv/font-ocl.lua +++ b/tex/context/base/mkiv/font-ocl.lua @@ -401,7 +401,7 @@ local function pdftovirtual(tfmdata,pdfshapes,kind) -- kind = png|svg -- The down and right will change too (we can move that elsewhere). We have -- a different treatment in lmtx but the next kind of works. These images are -- a mess anyway as in svg the bbox can be messed up absent). A png image - -- needs the x/y. I might normalize this once we moev to lmtx exlusively. + -- needs the x/y. I might normalize this once we move to lmtx exlusively. character.commands = { not unicode and actualb or { "pdf", "page", (getactualtext(unicode)) }, -- lmtx (when we deal with depth in vfimage, currently disabled): diff --git a/tex/context/base/mkiv/font-otl.lua b/tex/context/base/mkiv/font-otl.lua index 5d3bd4230..aff4cc8c8 100644 --- a/tex/context/base/mkiv/font-otl.lua +++ b/tex/context/base/mkiv/font-otl.lua @@ -52,7 +52,7 @@ local report_otf = logs.reporter("fonts","otf loading") local fonts = fonts local otf = fonts.handlers.otf -otf.version = 3.110 -- beware: also sync font-mis.lua and in mtx-fonts +otf.version = 3.111 -- beware: also sync font-mis.lua and in mtx-fonts otf.cache = containers.define("fonts", "otl", otf.version, true) otf.svgcache = containers.define("fonts", "svg", otf.version, true) otf.pngcache = containers.define("fonts", "png", otf.version, true) @@ -534,6 +534,9 @@ local converters = { } } +-- We can get differences between daylight saving etc ... but it makes no sense to +-- mess with trickery .. so be it when you use a different binary. + local function checkconversion(specification) local filename = specification.filename local converter = converters[lower(file.suffix(filename))] diff --git a/tex/context/base/mkiv/l-os.lua b/tex/context/base/mkiv/l-os.lua index 8394d19e7..64c7de567 100644 --- a/tex/context/base/mkiv/l-os.lua +++ b/tex/context/base/mkiv/l-os.lua @@ -637,6 +637,14 @@ function os.validdate(year,month,day) return year, month, day end +function os.date(fmt,...) + if not fmt then + -- otherwise differences between unix, mingw and msvc + fmt = "%Y-%m-%d %H:%M" + end + return date(fmt,...) +end + local osexit = os.exit local exitcode = nil diff --git a/tex/context/base/mkiv/l-table.lua b/tex/context/base/mkiv/l-table.lua index 98b377bdc..c20bd4733 100644 --- a/tex/context/base/mkiv/l-table.lua +++ b/tex/context/base/mkiv/l-table.lua @@ -525,84 +525,15 @@ function table.fromhash(t) return hsh end -local noquotes, hexify, handle, compact, inline, functions, metacheck +local noquotes, hexify, handle, compact, inline, functions, metacheck, accurate local reserved = table.tohash { -- intercept a language inconvenience: no reserved words as key 'and', 'break', 'do', 'else', 'elseif', 'end', 'false', 'for', 'function', 'if', 'in', 'local', 'nil', 'not', 'or', 'repeat', 'return', 'then', 'true', 'until', 'while', - 'NaN', 'goto', + 'NaN', 'goto', 'const', } --- local function is_simple_table(t) --- if #t > 0 then --- local n = 0 --- for _,v in next, t do --- n = n + 1 --- end --- if n == #t then --- local tt, nt = { }, 0 --- for i=1,#t do --- local v = t[i] --- local tv = type(v) --- if tv == "number" then --- nt = nt + 1 --- if hexify then --- tt[nt] = format("0x%X",v) --- else --- tt[nt] = tostring(v) -- tostring not needed --- end --- elseif tv == "string" then --- nt = nt + 1 --- tt[nt] = format("%q",v) --- elseif tv == "boolean" then --- nt = nt + 1 --- tt[nt] = v and "true" or "false" --- else --- return nil --- end --- end --- return tt --- end --- end --- return nil --- end - --- local function is_simple_table(t) --- local nt = #t --- if nt > 0 then --- local n = 0 --- for _,v in next, t do --- n = n + 1 --- -- if type(v) == "table" then --- -- return nil --- -- end --- end --- if n == nt then --- local tt = { } --- for i=1,nt do --- local v = t[i] --- local tv = type(v) --- if tv == "number" then --- if hexify then --- tt[i] = format("0x%X",v) --- else --- tt[i] = tostring(v) -- tostring not needed --- end --- elseif tv == "string" then --- tt[i] = format("%q",v) --- elseif tv == "boolean" then --- tt[i] = v and "true" or "false" --- else --- return nil --- end --- end --- return tt --- end --- end --- return nil --- end - -local function is_simple_table(t,hexify) -- also used in util-tab so maybe public +local function is_simple_table(t,hexify,accurate) -- also used in util-tab so maybe public local nt = #t if nt > 0 then local n = 0 @@ -623,6 +554,8 @@ local function is_simple_table(t,hexify) -- also used in util-tab so maybe publi -- tt[i] = v -- not needed tostring(v) if hexify then tt[i] = format("0x%X",v) + elseif accurate then + tt[i] = format("%q",v) else tt[i] = v -- not needed tostring(v) end @@ -644,6 +577,8 @@ local function is_simple_table(t,hexify) -- also used in util-tab so maybe publi -- tt[i+1] = v -- not needed tostring(v) if hexify then tt[i+1] = format("0x%X",v) + elseif accurate then + tt[i+1] = format("%q",v) else tt[i+1] = v -- not needed tostring(v) end @@ -738,6 +673,8 @@ local function do_serialize(root,name,depth,level,indexed) if tv == "number" then if hexify then handle(format("%s 0x%X,",depth,v)) + elseif accurate then + handle(format("%s %q,",depth,v)) else handle(format("%s %s,",depth,v)) -- %.99g end @@ -747,7 +684,7 @@ local function do_serialize(root,name,depth,level,indexed) if next(v) == nil then handle(format("%s {},",depth)) elseif inline then -- and #t > 0 - local st = is_simple_table(v,hexify) + local st = is_simple_table(v,hexify,accurate) if st then handle(format("%s { %s },",depth,concat(st,", "))) else @@ -775,12 +712,16 @@ local function do_serialize(root,name,depth,level,indexed) if tk == "number" then if hexify then handle(format("%s [0x%X]=0x%X,",depth,k,v)) + elseif accurate then + handle(format("%s [%s]=%q,",depth,k,v)) else handle(format("%s [%s]=%s,",depth,k,v)) -- %.99g end elseif tk == "boolean" then if hexify then handle(format("%s [%s]=0x%X,",depth,k and "true" or "false",v)) + elseif accurate then + handle(format("%s [%s]=%q,",depth,k and "true" or "false",v)) else handle(format("%s [%s]=%s,",depth,k and "true" or "false",v)) -- %.99g end @@ -789,12 +730,16 @@ local function do_serialize(root,name,depth,level,indexed) elseif noquotes and not reserved[k] and lpegmatch(propername,k) then if hexify then handle(format("%s %s=0x%X,",depth,k,v)) + elseif accurate then + handle(format("%s %s=%q,",depth,k,v)) else handle(format("%s %s=%s,",depth,k,v)) -- %.99g end else if hexify then handle(format("%s [%q]=0x%X,",depth,k,v)) + elseif accurate then + handle(format("%s [%q]=%q,",depth,k,v)) else handle(format("%s [%q]=%s,",depth,k,v)) -- %.99g end @@ -803,6 +748,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk == "number" then if hexify then handle(format("%s [0x%X]=%q,",depth,k,v)) + elseif accurate then + handle(format("%s [%q]=%q,",depth,k,v)) else handle(format("%s [%s]=%q,",depth,k,v)) end @@ -820,6 +767,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk == "number" then if hexify then handle(format("%s [0x%X]={},",depth,k)) + elseif accurate then + handle(format("%s [%q]={},",depth,k)) else handle(format("%s [%s]={},",depth,k)) end @@ -833,11 +782,13 @@ local function do_serialize(root,name,depth,level,indexed) handle(format("%s [%q]={},",depth,k)) end elseif inline then - local st = is_simple_table(v,hexify) + local st = is_simple_table(v,hexify,accurate) if st then if tk == "number" then if hexify then handle(format("%s [0x%X]={ %s },",depth,k,concat(st,", "))) + elseif accurate then + handle(format("%s [%q]={ %s },",depth,k,concat(st,", "))) else handle(format("%s [%s]={ %s },",depth,k,concat(st,", "))) end @@ -860,6 +811,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk == "number" then if hexify then handle(format("%s [0x%X]=%s,",depth,k,v and "true" or "false")) + elseif accurate then + handle(format("%s [%q]=%s,",depth,k,v and "true" or "false")) else handle(format("%s [%s]=%s,",depth,k,v and "true" or "false")) end @@ -881,6 +834,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk == "number" then if hexify then handle(format("%s [0x%X]=load(%q),",depth,k,f)) + elseif accurate then + handle(format("%s [%q]=load(%q),",depth,k,f)) else handle(format("%s [%s]=load(%q),",depth,k,f)) end @@ -899,6 +854,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk == "number" then if hexify then handle(format("%s [0x%X]=%q,",depth,k,tostring(v))) + elseif accurate then + handle(format("%s [%q]=%q,",depth,k,tostring(v))) else handle(format("%s [%s]=%q,",depth,k,tostring(v))) end @@ -927,6 +884,7 @@ local function serialize(_handle,root,name,specification) -- handle wins if type(specification) == "table" then noquotes = specification.noquotes hexify = specification.hexify + accurate = specification.accurate handle = _handle or specification.handle or print functions = specification.functions compact = specification.compact diff --git a/tex/context/base/mkiv/libs-imp-mujs.lua b/tex/context/base/mkiv/libs-imp-mujs.lua new file mode 100644 index 000000000..264c8e531 --- /dev/null +++ b/tex/context/base/mkiv/libs-imp-mujs.lua @@ -0,0 +1,126 @@ +if not modules then modules = { } end modules ['libs-imp-mujs'] = { + version = 1.001, + comment = "companion to luat-imp-mujs.mkxl", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- This is an experiment. When a new user knows \JAVASCRIPT\ it can be a +-- stepping stone to using \LUA. + +-- local ecmascript = optional.mujs.initialize("libmujs") +-- local execute = optional.mujs.execute + +local libname = "mujs" +local libfile = "libmujs" + +if package.loaded[libname] then + return package.loaded[libname] +end + +local mujslib = resolvers.libraries.validoptional(libname) + +if not mujslib then + return +end + +local files = { } +local openfile = io.open +local findfile = resolvers.findfile + +local mujs_execute = mujslib.execute +local mujs_dofile = mujslib.dofile +local mujs_reset = mujslib.reset + +local function okay() + if resolvers.libraries.optionalloaded(libname,libfile) then + mujs_execute( + "var catcodes = { " .. + "'tex': " .. tex.texcatcodes .. "," .. + "'ctx': " .. tex.ctxcatcodes .. "," .. + "'prt': " .. tex.prtcatcodes .. "," .. + "'vrb': " .. tex.vrbcatcodes .. "," .. + "};" + ) + okay = function() return true end + else + okay = function() return false end + end + return okay() +end + +mujslib.setfindfile(findfile) + +mujslib.setopenfile(function(name) + local full = findfile(name) + if full then + local f = openfile(full,"rb") + if f then + for i=1,100 do + if not files[i] then + files[i] = f + return i + end + end + end + end +end) + +mujslib.setclosefile(function(id) + local f = files[id] + if f then + f:close() + files[id] = false + end +end) + +mujslib.setreadfile(function(id,how) + local f = files[id] + if f then + return (f:read(how or "*l")) + end +end) + +mujslib.setseekfile(function(id,whence,offset) + local f = files[id] + if f then + return (f:seek(whence,offset)) + end +end) + +local reporters = { + console = logs.reporter("mujs","console"), + report = logs.reporter("mujs","report"), +} + +mujslib.setconsole(function(category,name) + reporters[category](name) +end) + +local mujs = { + ["execute"] = function(c,s) if okay() then mujs_execute(c,s) end end, + ["dofile"] = function(n) if okay() then mujs_dofile(n) end end, + ["reset"] = function(n) if okay() then mujs_reset(n) end end, +} + +package.loaded[libname] = mujs + +optional.loaded.mujs = mujs + +interfaces.implement { + name = "ecmacode", + actions = mujs.execute, + arguments = "string", + public = true, +} + +interfaces.implement { + name = "ecmafile", + actions = mujs.dofile, + arguments = "string", + public = true, + protected = true, +} + +return mujs diff --git a/tex/context/base/mkiv/libs-imp-mujs.mkxl b/tex/context/base/mkiv/libs-imp-mujs.mkxl new file mode 100644 index 000000000..0f278dff5 --- /dev/null +++ b/tex/context/base/mkiv/libs-imp-mujs.mkxl @@ -0,0 +1,121 @@ +%D \module +%D [ file=libs-imp-mujs, +%D version=2020.02.08, +%D title=\CONTEXT\ Extra Modules, +%D subtitle=MuJS interpreter, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D Just an experiment: +%D +%D \starttyping +%D http://mujs.com +%D \stoptyping + +\ifdefined\ecmacode + \expandafter \endinput +\fi + +\registerctxluafile{libs-imp-mujs}{} + +\unprotect + +% todo: environment + +\let\stopecmacode\relax + +\normalprotected\def\startecmacode % \stopecmacode + {\begingroup + \obeylualines + \obeyluatokens + \luat_start_ecma_code_indeed} + +\def\luat_start_ecma_code_indeed#1\stopecmacode + {\normalexpanded{\endgroup\noexpand\ecmacode{#1}}} + +\protect + +\continueifinputfile{libs-imp-mujs.mkxl} + +\usemodule[article-basic,abbreviations-logos] + +\starttext + +\startbuffer +\startluacode + local mujs = require("libs-imp-mujs") + + mujs.execute [[ + var MyMax = 1000; + ]] + + mujs.execute [[ + console("Example One!"); + texsprint("\\startpacked"); + for (var i = 1; i <= MyMax; i = i + 1) { + texprint( + "This is a buildbot compilation challenge for Mojca: " + .concat(Math.sqrt(i/MyMax)) + .concat("!\\par") + ); + } + texsprint("\\stoppacked"); + ]] + + -- mujs.execute [[ + -- something very bad: an error + -- ]] +\stopluacode + +\startecmacode + console("Example Two!"); + for (var i = 1; i <= MyMax; i = i + 1) { + texsprint( + "And an opportunity for Alan to attract highschool students to \\TeX: " + .concat(i) + .concat("! ") + ); + } +\stopecmacode + +\ecmacode { + console("Example Three!"); + texprint("And otherwise a way to prototype \\JAVASCRIPT\\ code in \\PDF.") +} + +\startecmacode + var f = File("libs-imp-mujs.mkxl","r"); + console(f); + // var l = f.read(400); + var l = f.read("*a"); + console(l); + f.close(); +\stopecmacode + +\startecmacode + console("Example Four!"); + texsprint("\\startMPcode " + .concat(' fill fullcircle scaled 6cm withcolor "darkred";') + .concat(' fill fullcircle scaled 4cm withcolor "darkgreen";') + .concat(' fill fullcircle scaled 2cm withcolor "darkblue";') + .concat("\\stopMPcode ") + ); +\stopecmacode + +\startluacode + context.startMPcode() + context('fill fullcircle scaled 6cm withcolor "middlecyan";') + context('fill fullcircle scaled 4cm withcolor "middlemagenta";') + context('fill fullcircle scaled 2cm withcolor "middleyellow";') + context.stopMPcode() +\stopluacode +\stopbuffer + +\typebuffer \page \getbuffer + +\stoptext diff --git a/tex/context/base/mkiv/libs-imp-mysql.lua b/tex/context/base/mkiv/libs-imp-mysql.lua index b3896acd4..3e938a6de 100644 --- a/tex/context/base/mkiv/libs-imp-mysql.lua +++ b/tex/context/base/mkiv/libs-imp-mysql.lua @@ -44,15 +44,20 @@ local validspecification = helpers.validspecification local preparetemplate = helpers.preparetemplate local querysplitter = helpers.querysplitter local cache = { } +local timeout -- = 3600 -- to be tested local function connect(specification) - return mysql_open( + local db = mysql_open( specification.database or "", specification.username or "", specification.password or "", specification.host or "", specification.port ) + if db and timeout then + mysql_execute(db,formatters["SET SESSION connect_timeout=%s ;"](timeout)) + end + return db end local function execute_once(specification,retry) @@ -110,13 +115,13 @@ local function execute_once(specification,retry) result[nofrows] = convert(values) end else - local column = { } callback = function(nofcolumns,values,fields) + local column = { } for i=1,nofcolumns do local field if fields then field = fields[i] - keys[i+1] = field + keys[i] = field else field = keys[i] end @@ -131,7 +136,7 @@ local function execute_once(specification,retry) for i=1,#query do local okay = mysql_execute(db,query[i],callback) if not okay then - if id and option == "retry" and i == 1 then + if id and retry and i == 1 then report("error: %s, retrying to connect",mysql_getmessage(db)) mysql_close(db) cache[id] = nil @@ -183,6 +188,23 @@ return function(cells) end ]] +-- return function(result) +-- if not result then +-- return { } +-- end +-- local nofrows = #result +-- if nofrows == 0 then +-- return { } +-- end +-- local target = { } -- no %s needed here +-- for i=1,nofrows do +-- target[%s] = { +-- %s +-- } +-- end +-- return result +-- end + local celltemplate = "cells[%s]" methods.mysql = { @@ -192,5 +214,7 @@ methods.mysql = { celltemplate = celltemplate, } -package.loaded["util-sql-imp-mysql"] = methods.mysql -package.loaded[libname] = methods.mysql +package.loaded["util-sql-imp-ffi"] = methods.mysql +package.loaded["util-sql-imp-mysql"] = methods.mysql +package.loaded["util-sql-imp-library"] = methods.mysql +package.loaded[libname] = methods.mysql diff --git a/tex/context/base/mkiv/libs-imp-postgress.lua b/tex/context/base/mkiv/libs-imp-postgress.lua index 5cd04e03b..629079b01 100644 --- a/tex/context/base/mkiv/libs-imp-postgress.lua +++ b/tex/context/base/mkiv/libs-imp-postgress.lua @@ -114,13 +114,13 @@ local function execute_once(specification,retry) result[nofrows] = convert(values) end else - local column = { } callback = function(nofcolumns,values,fields) + local column = { } for i=1,nofcolumns do local field if fields then field = fields[i] - keys[i+1] = field + keys[i] = field else field = keys[i] end @@ -135,7 +135,7 @@ local function execute_once(specification,retry) for i=1,#query do local okay = postgress_execute(db,query[i],callback) if not okay then - if id and option == "retry" and i == 1 then + if id and retry and i == 1 then report("error: %s, retrying to connect",postgress_getmessage(db)) postgress_close(db) cache[id] = nil diff --git a/tex/context/base/mkiv/libs-imp-sqlite.lua b/tex/context/base/mkiv/libs-imp-sqlite.lua index 15c3222ea..5d38986f3 100644 --- a/tex/context/base/mkiv/libs-imp-sqlite.lua +++ b/tex/context/base/mkiv/libs-imp-sqlite.lua @@ -119,13 +119,13 @@ local function execute(specification) result[nofrows] = convert(values) end else - local column = { } callback = function(nofcolumns,values,fields) + local column = { } for i=1,nofcolumns do local field if fields then field = fields[i] - keys[i+1] = field + keys[i] = field else field = keys[i] end diff --git a/tex/context/base/mkiv/libs-imp-zint.lua b/tex/context/base/mkiv/libs-imp-zint.lua index eef2cd605..2c346ae7d 100644 --- a/tex/context/base/mkiv/libs-imp-zint.lua +++ b/tex/context/base/mkiv/libs-imp-zint.lua @@ -78,7 +78,7 @@ local shown = false ----- f_rectangle = string.formatters["%sofill unitsquare xysized (%N,%N) shifted (%N,%N);"] -function zint.execute(specification) +local function execute(specification) if okay() then local code = specification.code local text = specification.text @@ -146,3 +146,16 @@ function zint.execute(specification) end end end + +optional.loaded.zint = { execute = execute } + +interfaces.implement { + name = "zint", + actions = execute, + arguments = { + { + { "code" }, + { "text" }, + } + } +} diff --git a/tex/context/base/mkiv/libs-imp-zint.mkxl b/tex/context/base/mkiv/libs-imp-zint.mkxl index d7436a4a4..72ce8157e 100644 --- a/tex/context/base/mkiv/libs-imp-zint.mkxl +++ b/tex/context/base/mkiv/libs-imp-zint.mkxl @@ -35,7 +35,10 @@ [\c!alternative=,\c!text=,#1]% \scale [#1]% - {\ctxlua{utilities.zint.execute{code="\dummyparameter\c!alternative",text=\!!bs\dummyparameter\c!text\!!es}}}% + {\clf_zint + code {\dummyparameter\c!alternative} + text {\dummyparameter\c!text} + \relax} \egroup} \protect diff --git a/tex/context/base/mkiv/libs-ini.lua b/tex/context/base/mkiv/libs-ini.lua index 2422305f0..2bac3201d 100644 --- a/tex/context/base/mkiv/libs-ini.lua +++ b/tex/context/base/mkiv/libs-ini.lua @@ -106,6 +106,8 @@ resolvers.libraries = libraries local report = logs.reporter("optional") +if optional then optional.loaded = { } end + function libraries.validoptional(name) local thelib = optional and optional[name] if not thelib then @@ -152,6 +154,21 @@ function libraries.optionalloaded(name,libnames) end end +if FFISUPPORTED and ffi and ffi.load then + + local ffiload = ffi.load + + function ffi.load(name) + local full = name and foundlibraries[name] + if full then + return ffiload(full) + else + return ffiload(name) + end + end + +end + -- local patterns = { -- "libs-imp-%s.mkxl", -- "libs-imp-%s.mklx", diff --git a/tex/context/base/mkiv/lpdf-emb.lua b/tex/context/base/mkiv/lpdf-emb.lua index 8db2ecaf1..4ffcfd8a8 100644 --- a/tex/context/base/mkiv/lpdf-emb.lua +++ b/tex/context/base/mkiv/lpdf-emb.lua @@ -1721,6 +1721,12 @@ do -- Acrobat X pro only seems to see the image mask but other viewers are doing it ok. Acrobat -- reader crashes. We really need to add a notdef! + local files = utilities.files + local openfile = files.open + local closefile = files.close + local setposition = files.setposition + local readstring = files.readstring + function methods.png(filename,details) local properties = details.properties local pngshapes = properties.indexdata[1] @@ -1732,23 +1738,37 @@ do local nofglyphs = 0 local scale = 10 * parameters.size/parameters.designsize local factor = bpfactor / scale - local units = parameters.units / 1000 + -- local units = parameters.units -- / 1000 + local units = 1000 + local filehandle = openfile(details.filename,true) local function pngtopdf(glyph,data) - -- local width = data.width - local info = graphics.identifiers.png(glyph.data,"string") - info.enforcecmyk = pngshapes.enforcecmyk - local image = lpdf.injectors.png(info,"string") - embedimage(image) - nofglyphs = nofglyphs + 1 - local width = (data.width or 0) * factor - local xoffset = (glyph.x or 0) / units - local yoffset = (glyph.y or 0) / units - local name = f_glyph(nofglyphs) - xforms[name] = pdfreference(image.objnum) - local pdf = f_image_xy(width,xoffset,yoffset,name) - return pdf, width + -- local info = graphics.identifiers.png(glyph.data,"string") + local offset = glyph.o + local size = glyph.s + local pdfdata = nil + if offset and size then + setposition(filehandle,offset) + local blob = readstring(filehandle,size) + local info = graphics.identifiers.png(blob,"string") + info.enforcecmyk = pngshapes.enforcecmyk + local image = lpdf.injectors.png(info,"string") + local width = (data.width or 0) * factor + if image then + embedimage(image) + nofglyphs = nofglyphs + 1 + local xoffset = (glyph.x or 0) / units + local yoffset = (glyph.y or 0) / units + local name = f_glyph(nofglyphs) + xforms[name] = pdfreference(image.objnum) + pdfdata = f_image_xy(width,xoffset,yoffset,name) + end + end + return pdfdata or f_stream(width), width end local function closepng() + if filehandle then + closefile(filehandle) + end pngshapes = nil end local function getresources() diff --git a/tex/context/base/mkiv/lpdf-lmt.lua b/tex/context/base/mkiv/lpdf-lmt.lua index a14df3eca..0ad0c4e5e 100644 --- a/tex/context/base/mkiv/lpdf-lmt.lua +++ b/tex/context/base/mkiv/lpdf-lmt.lua @@ -74,6 +74,7 @@ local pdf_form = pdfconstant("Form") local fonthashes = fonts.hashes local characters = fonthashes.characters +local descriptions = fonthashes.descriptions local parameters = fonthashes.parameters local properties = fonthashes.properties @@ -146,6 +147,7 @@ end -- fonts local fontcharacters +local fontdescriptions local fontparameters local fontproperties local usedcharacters = setmetatableindex("table") @@ -161,6 +163,7 @@ lpdf.usedcharacters = usedcharacters local function updatefontstate(font) fontcharacters = characters[font] + fontdescriptions = descriptions[font] fontparameters = parameters[font] fontproperties = properties[font] local size = fontparameters.size -- or bad news @@ -373,6 +376,32 @@ local flushcharacter do -- as fontparameters already has checked / set it we can also have a variable -- for it so + local naturalwidth = nil + + local naturalwidths = setmetatableindex(function(t,font) + local d = descriptions[font] + local c = characters[font] + local f = parameters[font].hfactor + local v = setmetatableindex(function(t,char) + local e = d and d[char] + local w = 0 + if e then + w = e.width + if w then + w = w * f + end + end + e = c[char] + if e then + w = e.width or 0 + end + t[char] = w + return w + end) + t[font] = v + return v + end) + local function setup_fontparameters(font,factor,f,e) local slant = fontparameters.slantfactor or 0 local extend = fontparameters.extendfactor or 1 @@ -401,6 +430,8 @@ local flushcharacter do if format == "opentype" or format == "type1" then fs = fs * 1000 / fontparameters.units -- can we avoid this ? end + -- + naturalwidth = naturalwidths[font] end -- This only saves a little on hz because there we switch a lot of @@ -512,7 +543,7 @@ local flushcharacter do local trace_threshold = false trackers.register("backends.pdf.threshold", function(v) trace_threshold = v end) - flushcharacter = function(current,pos_h,pos_v,pos_r,font,char,data,naturalwidth,factor,width,f,e) + flushcharacter = function(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor) -- ,naturalwidth,width) if need_tf or font ~= f_cur or f_pdf ~= f_pdf_cur or fs ~= fs_cur or mode == "page" then pdf_goto_textmode() setup_fontparameters(font,factor,f,e) @@ -523,12 +554,12 @@ local flushcharacter do end local move = calc_pdfpos(pos_h,pos_v) - if trace_threshold then - report( - "font %i, char %C, factor %i, width %p, naturalwidth %p, move %l, tm %l, hpos %p, delta %p, threshold %p, cw %p", - font,char,factor,width,naturalwidth,move,need_tm,pos_h,tj_delta,threshold,cw - ) - end + -- if trace_threshold then + -- report( + -- "font %i, char %C, factor %i, naturalwidth %p, move %l, tm %l, hpos %p, delta %p, threshold %p, cw %p", + -- font,char,factor,naturalwidth[char],move,need_tm,pos_h,tj_delta,threshold,cw + -- ) + -- end if move or need_tm then if not need_tm then @@ -569,7 +600,8 @@ local flushcharacter do end -- cw = cw + naturalwidth - cw = cw + width + -- cw = cw + width + cw = cw + naturalwidth[char] local index = data.index or char @@ -2407,67 +2439,69 @@ updaters.register("backend.update.pdf",function() end local function embedimage(specification) - lastindex = lastindex + 1 - index = lastindex - specification.index = index - local xobject = pdfdictionary { } - if not specification.notype then - xobject.Type = pdf_xobject - xobject.Subtype = pdf_form - xobject.FormType = 1 - end - local bbox = specification.bbox - if bbox and not specification.nobbox then - xobject.BBox = pdfarray { - bbox[1] * bpfactor, - bbox[2] * bpfactor, - bbox[3] * bpfactor, - bbox[4] * bpfactor, - } - end - xobject = xobject + specification.attr - if bbox and not specification.width then - specification.width = bbox[3] - end - if bbox and not specification.height then - specification.height = bbox[4] - end - local dict = xobject() - -- - nofobjects = nofobjects + 1 - local objnum = nofobjects - local nolength = specification.nolength - local stream = specification.stream or specification.string - -- - -- We cannot set type in native img so we need this hack or - -- otherwise we need to patch too much. Better that i write - -- a wrapper then. Anyway, it has to be done better: a key that - -- tells either or not to scale by xsize/ysize when flushing. - -- - if not specification.type then - local kind = specification.kind - if kind then - -- take that one - elseif attr and find(attr,"BBox") then - kind = img_stream - else - -- hack: a bitmap - kind = img_none + if specification then + lastindex = lastindex + 1 + index = lastindex + specification.index = index + local xobject = pdfdictionary { } + if not specification.notype then + xobject.Type = pdf_xobject + xobject.Subtype = pdf_form + xobject.FormType = 1 end - specification.type = kind - specification.kind = kind - end - local compress = compresslevel and compresslevel > 0 or nil - flushstreamobj(stream,objnum,dict,compress,nolength) - specification.objnum = objnum - specification.rotation = specification.rotation or 0 - specification.orientation = specification.orientation or 0 - specification.transform = specification.transform or 0 - specification.stream = nil - specification.attr = nil - specification.type = specification.kind or specification.type or img_none - indices[index] = specification -- better create a real specification - return specification + local bbox = specification.bbox + if bbox and not specification.nobbox then + xobject.BBox = pdfarray { + bbox[1] * bpfactor, + bbox[2] * bpfactor, + bbox[3] * bpfactor, + bbox[4] * bpfactor, + } + end + xobject = xobject + specification.attr + if bbox and not specification.width then + specification.width = bbox[3] + end + if bbox and not specification.height then + specification.height = bbox[4] + end + local dict = xobject() + -- + nofobjects = nofobjects + 1 + local objnum = nofobjects + local nolength = specification.nolength + local stream = specification.stream or specification.string + -- + -- We cannot set type in native img so we need this hack or + -- otherwise we need to patch too much. Better that i write + -- a wrapper then. Anyway, it has to be done better: a key that + -- tells either or not to scale by xsize/ysize when flushing. + -- + if not specification.type then + local kind = specification.kind + if kind then + -- take that one + elseif attr and find(attr,"BBox") then + kind = img_stream + else + -- hack: a bitmap + kind = img_none + end + specification.type = kind + specification.kind = kind + end + local compress = compresslevel and compresslevel > 0 or nil + flushstreamobj(stream,objnum,dict,compress,nolength) + specification.objnum = objnum + specification.rotation = specification.rotation or 0 + specification.orientation = specification.orientation or 0 + specification.transform = specification.transform or 0 + specification.stream = nil + specification.attr = nil + specification.type = specification.kind or specification.type or img_none + indices[index] = specification -- better create a real specification + return specification + end end codeinjections.embedimage = embedimage diff --git a/tex/context/base/mkiv/lpdf-wid.lua b/tex/context/base/mkiv/lpdf-wid.lua index b8648b32a..8e0a45a00 100644 --- a/tex/context/base/mkiv/lpdf-wid.lua +++ b/tex/context/base/mkiv/lpdf-wid.lua @@ -252,20 +252,25 @@ job.register('job.fileobjreferences.collected', tobesavedobjrefs, initializer) local function flushembeddedfiles() if enabled and next(filestreams) then local e = pdfarray() + local f = pdfarray() for tag, reference in sortedhash(filestreams) do if not reference then report_attachment("unreferenced file, tag %a",tag) --- elseif referenced[tag] == "hidden" then - elseif referenced[tag] ~= "hidden" then + elseif referenced[tag] == "hidden" then e[#e+1] = pdfstring(tag) e[#e+1] = reference -- already a reference + f[#f+1] = reference -- collect all file description references else - -- -- messy spec ... when annot not in named else twice in menu list acrobat + -- messy spec ... when annot not in named else twice in menu list acrobat + f[#f+1] = reference end end if #e > 0 then lpdf.addtonames("EmbeddedFiles",pdfreference(pdfflushobject(pdfdictionary{ Names = e }))) end + if #f > 0 then -- PDF/A-2|3: all associated files must have a relationship to the PDF document (global or part) + lpdf.addtocatalog("AF", pdfreference(pdfflushobject(f))) -- global (Catalog) + end end end @@ -430,6 +435,7 @@ function nodeinjections.attachfile(specification) else referenced[hash] = "annotation" local name, appearance = analyzesymbol(specification.symbol,attachment_symbols) + local flags = specification.flags or 0 -- to keep it expandable local d = pdfdictionary { Subtype = pdfconstant("FileAttachment"), FS = aref, @@ -442,7 +448,8 @@ function nodeinjections.attachfile(specification) CA = analyzetransparency(specification.transparencyvalue), AP = appearance, OC = analyzelayer(specification.layer), - F = pdfnull(), -- another rediculous need to satisfy validation + -- F = pdfnull(), -- another rediculous need to satisfy validation + F = (flags | 4) & (1023-1-2-32-256), -- set 3, clear 1,2,6,9; PDF 32000-1, p385 } local width = specification.width or 0 local height = specification.height or 0 @@ -534,7 +541,6 @@ function nodeinjections.comment(specification) -- brrr: seems to be done twice Name = name, NM = pdfstring("comment:"..nofcomments), AP = appearance, - F = pdfnull(), -- another rediculous need to satisfy validation } local width = specification.width or 0 local height = specification.height or 0 diff --git a/tex/context/base/mkiv/luat-cod.lua b/tex/context/base/mkiv/luat-cod.lua index 51eab5a1d..3125495b4 100644 --- a/tex/context/base/mkiv/luat-cod.lua +++ b/tex/context/base/mkiv/luat-cod.lua @@ -137,10 +137,8 @@ if LUATEXENGINE == nil then end if LUATEXVERSION == nil then - LUATEXVERSION = status.luatex_revision LUATEXVERSION = status.luatex_version/100 - -- + tonumber(LUATEXVERSION)/1000 - + (tonumber(LUATEXVERSION) or (string.byte(LUATEXVERSION)-string.byte("a")+10))/1000 + + tonumber(status.luatex_revision)/10000 end if CONTEXTLMTXMODE == nil then diff --git a/tex/context/base/mkiv/luat-ini.lua b/tex/context/base/mkiv/luat-ini.lua index 332980013..cec0161e7 100644 --- a/tex/context/base/mkiv/luat-ini.lua +++ b/tex/context/base/mkiv/luat-ini.lua @@ -26,7 +26,7 @@ if not global then end LUATEXVERSION = status.luatex_version/100 - + tonumber(status.luatex_revision)/1000 + + tonumber(status.luatex_revision)/10000 LUATEXENGINE = status.luatex_engine and string.lower(status.luatex_engine) or (string.find(status.banner,"LuajitTeX",1,true) and "luajittex" or "luatex") diff --git a/tex/context/base/mkiv/luat-lib.mkiv b/tex/context/base/mkiv/luat-lib.mkiv index c3bbd8e19..0ffd1dd40 100644 --- a/tex/context/base/mkiv/luat-lib.mkiv +++ b/tex/context/base/mkiv/luat-lib.mkiv @@ -73,9 +73,9 @@ \registerctxluafile{data-use}{} \registerctxluafile{data-aux}{} -\ifcase\contextlmtxmode - \registerctxluafile{util-lib}{} -\fi +% \ifcase\contextlmtxmode +% \registerctxluafile{util-lib}{} +% \fi \registerctxluafile{luat-cbk}{} \registerctxluafile{luat-run}{} diff --git a/tex/context/base/mkiv/m-gnuplot.mkxl b/tex/context/base/mkiv/m-gnuplot.mkxl new file mode 100644 index 000000000..2077b1741 --- /dev/null +++ b/tex/context/base/mkiv/m-gnuplot.mkxl @@ -0,0 +1,97 @@ +%D \module +%D [ file=m-gnuplot, +%D version=2020.02.10, +%D title=\CONTEXT\ Extra Modules, +%D subtitle=Gnuplot, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D This is a variant on the \GNUPLOT\ terminal code. At some point (when there is a +%D reason) I will make a proper environment that can be used for embedded code. + +\unexpanded\def\includegnuplotsvgfile[#1]% + {\hbox\bgroup + \ctxlua{metapost.startsvghashing()}% + \includesvgfile[#1]% + \ctxlua{metapost.stopsvghashing()}% + \egroup} + +\startluacode + +local modificationtime = lfs.modification +local longtostring = string.longtostring +local formatters = string.formatters +local expandfilename = dir.expandname +local isfile = lfs.isfile + +local runner = sandbox.registerrunner { + name = "gnuplot to svg", + program = "gnuplot", + template = longtostring [[ + -e "set output '%newname%'; set terminal svg" + "%oldname%" + ]], + checkers = { + oldname = "readable", + newname = "writable", + }, +} + +figures.programs.gnuplot = { + runner = runner, +} + +local function remap(specification) + local oldname = specification.fullname + if oldname then + local newname = file.replacesuffix(oldname,"svg") + local oldtime = modificationtime(oldname) or 0 + local newtime = modificationtime(newname) or 0 + if newtime == 0 or oldtime > newtime then + runner { + newname = expandfilename(newname), + oldname = expandfilename(oldname), + } + end + if isfile(newname) then + local only = file.nameonly(newname) + local name = formatters["svg-%s-inclusion"](only) + local code = formatters["\\includegnuplotsvgfile[%s]\\resetbuffer[%s]"](newname,name) + buffers.assign(name,code) + specification.format = "buffer" + specification.fullname = name + end + end + return specification +end + +figures.remappers.gp = { svg = remap } + +\stopluacode + +\continueifinputfile{m-gnuplot.mkxl} + +\startluacode +io.savedata("m-gnuplot-demo.gp", [[ +set format xy "$%g$" + +set title 'This is a plot of $y=\\sin(x)$' +set xlabel 'This is the $x$ axis' +set ylabel 'This is the $y$ axis' + +plot [0:6.28] [0:1] sin(x) +]]) +\stopluacode + +\starttext + + \externalfigure[m-gnuplot-demo.gp][conversion=svg,width=4cm] + + \externalfigure[m-gnuplot-demo.gp][conversion=svg,width=8cm] + +\stoptext diff --git a/tex/context/base/mkiv/m-zint.mkxl b/tex/context/base/mkiv/m-zint.mkxl deleted file mode 100644 index 7135126ba..000000000 --- a/tex/context/base/mkiv/m-zint.mkxl +++ /dev/null @@ -1,7 +0,0 @@ -% this is a stub: - -% \uselibrary[zint] - -\input libs-imp-zint.mkxl - -\endinput diff --git a/tex/context/base/mkiv/meta-imp-threesix.mkxl b/tex/context/base/mkiv/meta-imp-threesix.mkxl new file mode 100644 index 000000000..277aa85f7 --- /dev/null +++ b/tex/context/base/mkiv/meta-imp-threesix.mkxl @@ -0,0 +1,253 @@ +% not yet a module + +\startluacode + local gsub, utfbyte = string.gsub, utf.byte + + -- The font from DEK's facs9b.ps (I wish I was clever enough to understand all the good + -- stuff in there): + + local font36 = { + ["0"] = [[00111100 01111110 11000011 11000011 11000011 11000011 01111110 00111100]], + ["1"] = [[00011100 11111100 11101100 00001100 00001100 00001100 11111111 11111111]], + ["2"] = [[00111110 01110011 01110011 00000011 00001110 00111000 11110001 11111111]], + ["3"] = [[01111110 01100110 00000110 00111100 00000110 11100111 11100111 01111110]], + ["4"] = [[00001110 00011110 00110110 01100110 11111111 11111111 00000110 00001110]], + ["5"] = [[01111110 01111110 01000000 01111100 01000111 00000011 11000111 11111110]], + ["6"] = [[01111110 01100110 11000000 11011100 11100110 11000011 01100011 01111110]], + ["7"] = [[11111111 11111111 10000111 10001110 00011100 00011100 00011100 00011100]], + ["8"] = [[01111110 01100110 01100110 00111100 11000011 11000011 11000011 01111110]], + ["9"] = [[01111110 11000110 11000011 01100111 00111011 00000011 01100110 01111110]], + ["A"] = [[000110000 000111000 001111100 001101100 011001110 011111110 010000110 111100111]], + ["B"] = [[1111100 1110110 0110110 0111100 0110011 0110011 1110011 1111100]], + ["C"] = [[01111101 11110011 11100001 11100001 11100000 11100000 11100001 01111110]], + ["D"] = [[11111100 11100010 01100011 01100011 01100011 01100011 11100010 11111100]], + ["E"] = [[1111111 1110001 0110101 0111100 0110100 0110001 1110001 1111111]], + ["F"] = [[11111111 11100001 01100101 01111100 01100100 01100000 11111000 11111000]], + ["G"] = [[01111010 11100110 11100010 11100000 11100111 11100010 11100010 01111100]], + ["H"] = [[11100111 11100111 01000010 01111110 01000010 01000010 11100111 11100111]], + ["I"] = [[1111111 1111111 0011000 0011000 0011000 0011000 1111111 1111111]], + ["J"] = [[01111111 01111111 00000110 00000110 11110110 01100110 01100110 00111100]], + ["K"] = [[11101110 11100100 01101000 01110000 01111000 01101100 11100110 11101111]], + ["L"] = [[111111000 111111000 011000000 011000000 011000000 011000011 111000011 111111111]], + ["M"] = [[1100000011 1110000111 0111111110 0100110010 0100110010 0100000010 1100000011 1100000011]], + ["N"] = [[11000011 11100011 01110010 01111010 01011110 01001110 11100110 11100010]], + ["O"] = [[01111110 11000011 11000011 11000011 11000011 11000011 11000011 01111110]], + ["P"] = [[11111110 11100011 01100011 01111110 01100000 01100000 11111000 11111000]], + ["Q"] = [[01111100 11000110 11000110 11000110 11000110 11001110 11000110 01111101]], + ["R"] = [[11111100 11100110 01100110 01111100 01101000 01100100 11100010 11100111]], + ["S"] = [[01111110 11100001 11100001 01111000 00011110 10000111 11000011 10111110]], + ["T"] = [[1111111111 1100110011 1100110011 0000110000 0000110000 0000110000 0001111000 0001111000]], + ["U"] = [[111101111 111101111 011000010 011000010 011000010 011000010 011000010 001111100]], + ["V"] = [[11111000111 11111000111 01110000010 00110000100 00111000100 00011001000 00001101000 00001110000]], + ["W"] = [[111000000111 111000000111 110000000010 011000000100 011001000100 001101101000 001101101000 000110110000]], + ["X"] = [[1111001110 1111000110 0001101000 0000110000 0000110000 0001011000 0110001111 0111001111]], + ["Y"] = [[111100011 111100011 011000010 001110100 000111000 000011000 001111110 001111110]], + ["Z"] = [[11111111 10000111 00001110 00011100 00111000 01110000 11100001 11111111]], + } + + local f_code = string.formatters["ThreeSix(%s);"] + local replace = { ["0"] = "N;", ["1"] = "Y;", [" "] = "L;" } + + local function remap(str) + -- permit abundant spacing (bonus) + str = gsub(str,"%s+", " ") + -- remap what we got to macro calls + str = gsub(str,".",replace) + -- return the result + return str + end + + function MP.registerthreesix(name) + fonts.dropins.registerglyphs { + name = name, + units = 12, + usecolor = true, + preamble = "InitializeThreeSix;", + } + for u, v in table.sortedhash(font36) do + local ny = 8 + local nx = (#v - ny + 1) // ny + local height = ny * 1.1 - 0.1 + local width = nx * 1.1 - 0.1 + fonts.dropins.registerglyph { + category = name, + unicode = utfbyte(u), + width = width, + height = height, + code = f_code(remap(v)), + } + end + end + + MP.registerthreesix("fontthreesix") +\stopluacode + +% \startMPcalculation{simplefun} +% def InitializeThreeSix = +% save Y, N, L, S ; save dx, dy, nx, ny ; +% save shape, fillcolor, mypen, random, currentpen, spread, hoffset ; +% string shape, fillcolor, mypen ; boolean random ; pen currentpen ; +% dx := 11/10 ; +% dy := - 11/10 ; +% nx := - dx ; +% ny := 0 ; +% shape := getparameterdefault "mpsfont" "shape" "circle" ; +% random := hasoption "mpsfont" "random" "true" ; +% fillcolor := getparameterdefault "mpsfont" "color" "" ; +% mypen := getparameterdefault "mpsfont" "pen" "" ; +% spread := getparameterdefault "mpsfont" "spread" 0 ; +% hoffset := 12 * spread / 2 ; +% currentpen := pencircle +% if mypen = "fancy" : +% xscaled 1/20 yscaled 2/20 rotated 45 +% else : +% scaled 1/20 +% fi ; +% if shape == "square" : +% def S = +% unitsquare if random : randomized 1/10 fi +% shifted (nx,ny) +% enddef ; +% elseif shape = "diamond" : +% def S = +% unitdiamond if random : randomized 1/10 fi +% shifted (nx,ny) +% enddef ; +% else : +% def S = +% unitcircle if random : randomizedcontrols 1/20 fi +% shifted (nx,ny) +% enddef ; +% fi ; +% def N = +% nx := nx + dx ; +% draw S ; +% enddef ; +% if fillcolor = "random" : +% def Y = +% nx := nx + dx ; +% fillup S withcolor white randomized (2/3,2/3,2/3) ; +% enddef ; +% elseif fillcolor = "" : +% def Y = +% nx := nx + dx ; +% fillup S ; +% enddef ; +% else : +% def Y = +% nx := nx + dx ; +% fillup S withcolor fillcolor ; +% enddef ; +% fi ; +% def L = +% nx := - dx ; +% ny := ny + dy ; +% enddef ; +% enddef ; +% +% vardef ThreeSix (text code) = +% InitializeThreeSix ; +% draw image (code) shifted (hoffset,-ny) ; +% enddef ; +% \stopMPcalculation + +\startMPcalculation{simplefun} + def InitializeThreeSix = + save Y, N, L, S ; + % save dx, dy, nx, ny ; + save shape, fillcolor, mypen, random, threesixpen, spread, hoffset ; + string shape, fillcolor, mypen ; boolean random ; pen threesixpen ; + % dx := 11/10 ; + % dy := - 11/10 ; + % nx := - dx ; + % ny := 0 ; + shape := getparameterdefault "mpsfont" "shape" "circle" ; + random := hasoption "mpsfont" "random" "true" ; + fillcolor := getparameterdefault "mpsfont" "color" "" ; + mypen := getparameterdefault "mpsfont" "pen" "" ; + spread := getparameterdefault "mpsfont" "spread" 0 ; + hoffset := 12 * spread / 2 ; + threesixpen := pencircle + if mypen = "fancy" : + xscaled 1/20 yscaled 2/20 rotated 45 + else : + scaled 1/20 + fi ; + if shape == "square" : + def S = + unitsquare if random : randomized 1/10 fi + shifted (nx,ny) + enddef ; + elseif shape = "diamond" : + def S = + unitdiamond if random : randomized 1/10 fi + shifted (nx,ny) + enddef ; + else : + def S = + unitcircle if random : randomizedcontrols 1/20 fi + shifted (nx,ny) + enddef ; + fi ; + def N = + nx := nx + dx ; + draw S ; + enddef ; + if fillcolor = "random" : + def Y = + nx := nx + dx ; + fillup S withcolor white randomized (2/3,2/3,2/3) ; + enddef ; + elseif fillcolor = "" : + def Y = + nx := nx + dx ; + fillup S ; + enddef ; + else : + def Y = + nx := nx + dx ; + fillup S withcolor fillcolor ; + enddef ; + fi ; + def L = + nx := - dx ; + ny := ny + dy ; + enddef ; + enddef ; + + vardef ThreeSix (text code) = + save dx, dy, nx, ny ; + dx := 11/10 ; + dy := - 11/10 ; + nx := - dx ; + ny := 0 ; + pickup threesixpen ; + draw image (code) shifted (hoffset,-ny) ; + enddef ; +\stopMPcalculation + +\definefontfeature % black and white, with some spread + [fontthreesix] + [default] + [metapost=fontthreesix] + +\definefontfeature % color, with some spread + [fontthreesix-tweak] + [default] + [metapost={category=fontthreesix,spread=.1}] + +\definefontfeature % color, with some spread + [fontthreesix-color] + [default] + [metapost={category=fontthreesix,shape=diamond,color=random,pen=fancy,spread=.1}] + +\definefontfeature % color, tight + [fontthreesix-initial] + [metapost={category=fontthreesix,color=random,shape=circle}] % units? + +\definefont[DEKFontA][Serif*fontthreesix] +\definefont[DEKFontB][Serif*fontthreesix-color] +\definefont[DEKFontC][Serif*fontthreesix-initial] +\definefont[DEKFontD][Serif*fontthreesix-tweak] + +\endinput diff --git a/tex/context/base/mkiv/meta-tex.mkiv b/tex/context/base/mkiv/meta-tex.mkiv index 418ddc196..c580596f7 100644 --- a/tex/context/base/mkiv/meta-tex.mkiv +++ b/tex/context/base/mkiv/meta-tex.mkiv @@ -236,4 +236,7 @@ \unexpanded\def\svgsetlayer#1#2% {\setlayer[svgmps][\c!x=#1\onebasepoint,\c!y=#2\onebasepoint]} % {#3} +\unexpanded\def\svghashed#1% + {\clf_svghashed#1\relax} + \protect \endinput diff --git a/tex/context/base/mkiv/mlib-svg.lua b/tex/context/base/mkiv/mlib-svg.lua index b56c1fd54..f4b3117a6 100644 --- a/tex/context/base/mkiv/mlib-svg.lua +++ b/tex/context/base/mkiv/mlib-svg.lua @@ -75,24 +75,21 @@ if not modules then modules = { } end modules ['mlib-svg'] = { -- One can run into pretty crazy images, like lines that are fills being clipped -- to some width. That's the danger of hiding yourself behind an interface I guess. -local rawget, type, tonumber, tostring, next, setmetatable = rawget, type, tonumber, tostring, next, setmetatable +local rawget, rawset, type, tonumber, tostring, next, setmetatable = rawget, rawset, type, tonumber, tostring, next, setmetatable -local P, S, R, C, Ct, Cs, Cc, Cp, Carg = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.Cp, lpeg.Carg +local P, S, R, C, Ct, Cs, Cc, Cp, Cg, Cf, Carg = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.Cp, lpeg.Cg, lpeg.Cf, lpeg.Carg local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns -local pi, sin, cos, asin, sind, cosd, tan, abs, sqrt = math.pi, math.sin, math.cos, math.asin, math.sind, math.cosd, math.tan, math.abs, math.sqrt +local sqrt = math.sqrt local concat, setmetatableindex, sortedhash = table.concat, table.setmetatableindex, table.sortedhash local gmatch, gsub, find, match, rep = string.gmatch, string.gsub, string.find, string.match, string.rep local formatters, fullstrip = string.formatters, string.fullstrip -local extract = bit32.extract local utfsplit, utfbyte = utf.split, utf.byte local xmlconvert, xmlcollected, xmlcount, xmlfirst, xmlroot = xml.convert, xml.collected, xml.count, xml.first, xml.root local xmltext, xmltextonly = xml.text, xml.textonly local css = xml.css or { } -- testing -local bpfactor = number.dimenfactors.bp - local function xmlinheritattributes(c,pa) local at = c.at local dt = c.dt @@ -134,6 +131,47 @@ local pathtracer = { ["fill-opacity"] = ".75", } +-- This is just an experiment. Todo: reset hash etc. Also implement +-- an option handler. + +local svghash = false do + + local svglast = 0 + local svglist = false + + local function checkhash(t,k) + local n = svglast + 1 + svglast = n + svglist[n] = k + t[k] = n + return n + end + + function metapost.startsvghashing() + svglast = 0 + svglist = { } + svghash = setmetatableindex(checkhash) + end + + function metapost.stopsvghashing() + svglast = 0 + svglist = false + svghash = false + end + + interfaces.implement { + name = "svghashed", + arguments = "integer", + actions = function(n) + local t = svglist and svglist[n] + if t then + context(t) + end + end + } + +end + -- We have quite some closures because otherwise we run into the local variable -- limitations. It doesn't always look pretty now, sorry. I'll clean up this mess -- some day (the usual nth iteration of code). @@ -149,6 +187,8 @@ local pathtracer = { local a2c do + local pi, sin, cos, tan, asin, abs = math.pi, math.sin, math.cos, math.tan, math.asin, math.abs + local d120 = (pi * 120) / 180 local pi2 = 2 * pi @@ -401,6 +441,8 @@ local rgbcomponents, withcolor, thecolor do local f_svggray = formatters['svggray(%.3N)'] local f_svgname = formatters['"%s"'] + local extract = bit32.extract + local triplets = setmetatableindex(function(t,k) -- we delay building all these strings local v = svgcolors[k] @@ -971,6 +1013,8 @@ local f_wrapped_stop = formatters[") shifted (0,%N) scaled %N ;"] local handletransform, handleviewbox do + local sind = math.sind + --todo: better lpeg local f_rotatedaround = formatters[" rotatedaround((%N,%N),%N)"] @@ -1017,7 +1061,7 @@ local handletransform, handleviewbox do local function skewx(x) if x then - return f_slanted_x(math.sind(-x)) + return f_slanted_x(sind(-x)) else return "" end @@ -1025,7 +1069,7 @@ local handletransform, handleviewbox do local function skewy(y) if y then - return f_slanted_y(math.sind(-y)) + return f_slanted_y(sind(-y)) else return "" end @@ -1035,24 +1079,34 @@ local handletransform, handleviewbox do return f_matrix(rx or 1, sx or 0, sy or 0, ry or 1, tx or 0, - (ty or 0)) end - -- how to deal with units here? + -- How to deal with units here? Anyway, order seems to matter. - local p_transform = Cs ( ( - P("translate") * p_numbers / translate -- maybe xy - + P("scale") * p_numbers / scale - + P("rotate") * p_numbers / rotate - + P("matrix") * p_numbers / matrix - + P("skewX") * p_numbers / skewx - + P("skewY") * p_numbers / skewy - -- + p_separator - + P(1)/"" - )^1) + local p_transform = Cf ( Ct("") * ( + lpegpatterns.whitespace^0 * Cg( + C("translate") * (p_numbers / translate) -- maybe xy + + C("scale") * (p_numbers / scale) + + C("rotate") * (p_numbers / rotate) + + C("matrix") * (p_numbers / matrix) + + C("skewX") * (p_numbers / skewx) + + C("skewY") * (p_numbers / skewy) + ) + )^1, rawset) handletransform = function(at) local t = at.transform if t then local e = lpegmatch(p_transform,t) - return s_transform_start, f_transform_stop(e), t + if e then + e = concat({ + e.rotate or "", + e.skewX or "", + e.skewY or "", + e.scale or "", + e.translate or "", + e.matrix or "", + }, " ") + return s_transform_start, f_transform_stop(e), t + end end end @@ -2340,6 +2394,7 @@ do local f_scaled = formatters["\\svgscaled{%N}{%s}{%s}{%s}"] local f_normal = formatters["\\svgnormal{%s}{%s}{%s}"] + local f_hashed = formatters["\\svghashed{%s}"] -- We move to the outer (x,y) and when we have an inner offset we -- (need to) compensate for that outer offset. @@ -2348,8 +2403,14 @@ do -- local f_text_normal_svg = formatters['(svgtext("%s") shifted (%N,%N))'] -- local f_text_simple_svg = formatters['svgtext("%s")'] - local f_text_normal_svg = formatters['(textext.drt("%s") shifted (%N,%N))'] - local f_text_simple_svg = formatters['textext.drt("%s")'] + local anchors = { + ["start"] = "drt", + ["end"] = "dflt", + ["middle"] = "d", + } + + local f_text_normal_svg = formatters['(textext.%s("%s") shifted (%N,%N))'] + local f_text_simple_svg = formatters['textext.%s("%s")'] -- or just maptext @@ -2480,7 +2541,9 @@ do di = gsub(di,"%s+$","") end local chars = utfsplit(di) - if tx then + if svghash then + di = f_hashed(svghash[di]) + elseif tx then for i=1,#chars do chars[i] = f_poschar( (tx[i] or 0) - x, @@ -2540,6 +2603,7 @@ do v_fill = "black" end local color, opacity, invisible = fillproperties(v_fill,at) + local anchor = anchors[at["text-anchor"] or "start"] or "drt" local r = metapost.remappedtext(only) if r then if x == 0 and y == 0 then @@ -2567,9 +2631,9 @@ do result[#result+1] = s_stoplayer result = concat(result) if x == 0 and y == 0 then - result = f_text_simple_svg(result) + result = f_text_simple_svg(anchor,result) else - result = f_text_normal_svg(result,x,y) + result = f_text_normal_svg(anchor,result,x,y) end flushobject(result,at,color,opacity) if trace_text then @@ -2741,7 +2805,7 @@ do definitions = { } tagstyles = { } classstyles = { } - for s in xmlcollected(c,"/style") do + for s in xmlcollected(c,"style") do -- can also be in a def, so let's play safe handlestyle(c) end handlechains(c) @@ -2777,101 +2841,107 @@ end -- a bit more efficient, because we now go to mp and back which is kind of redundant, -- but for now it will do. -function metapost.includesvgfile(filename,offset) -- offset in sp - if lfs.isfile(filename) then +do + + local bpfactor = number.dimenfactors.bp + + function metapost.includesvgfile(filename,offset) -- offset in sp + if lfs.isfile(filename) then + context.startMPcode("doublefun") + context('draw lmt_svg [ filename = "%s", offset = %N ] ;',filename,(offset or 0)*bpfactor) + context.stopMPcode() + end + end + + function metapost.includesvgbuffer(name,offset) -- offset in sp context.startMPcode("doublefun") - context('draw lmt_svg [ filename = "%s", offset = %N ] ;',filename,(offset or 0)*bpfactor) + context('draw lmt_svg [ buffer = "%s", offset = %N ] ;',name or "",(offset or 0)*bpfactor) context.stopMPcode() end -end - -function metapost.includesvgbuffer(name,offset) -- offset in sp - context.startMPcode("doublefun") - context('draw lmt_svg [ buffer = "%s", offset = %N ] ;',name or "",(offset or 0)*bpfactor) - context.stopMPcode() -end -interfaces.implement { - name = "includesvgfile", - actions = metapost.includesvgfile, - arguments = { "string", "dimension" }, -} + interfaces.implement { + name = "includesvgfile", + actions = metapost.includesvgfile, + arguments = { "string", "dimension" }, + } -interfaces.implement { - name = "includesvgbuffer", - actions = metapost.includesvgbuffer, - arguments = { "string", "dimension" }, -} + interfaces.implement { + name = "includesvgbuffer", + actions = metapost.includesvgbuffer, + arguments = { "string", "dimension" }, + } -function metapost.showsvgpage(data) - local dd = data.data - if not dd then - local fn = data.filename - dd = fn and table.load(fn) - end - if type(dd) == "table" then - local comment = data.comment - local offset = data.pageoffset - local index = data.index - local first = math.max(index or 1,1) - local last = math.min(index or #dd,#dd) - for i=first,last do - local d = setmetatableindex( { - data = dd[i], - comment = comment and i or false, - pageoffset = offset or nil, - }, data) - metapost.showsvgpage(d) - end - elseif data.method == "code" then - context.startMPcode(doublefun) - context(metapost.svgtomp(data)) - context.stopMPcode() - else - context.startMPpage { instance = "doublefun", offset = data.pageoffset or nil } - context(metapost.svgtomp(data)) + function metapost.showsvgpage(data) + local dd = data.data + if not dd then + local fn = data.filename + dd = fn and table.load(fn) + end + if type(dd) == "table" then local comment = data.comment - if comment then - context("draw boundingbox currentpicture withcolor .6red ;") - context('draw textext.bot("\\strut\\tttf %s") ysized (10pt) shifted center bottomboundary currentpicture ;',comment) - end - context.stopMPpage() - end -end - -function metapost.typesvgpage(data) - local dd = data.data - if not dd then - local fn = data.filename - dd = fn and table.load(fn) - end - if type(dd) == "table" then - local index = data.index - if index and index > 0 and index <= #dd then - data = dd[index] + local offset = data.pageoffset + local index = data.index + local first = math.max(index or 1,1) + local last = math.min(index or #dd,#dd) + for i=first,last do + local d = setmetatableindex( { + data = dd[i], + comment = comment and i or false, + pageoffset = offset or nil, + }, data) + metapost.showsvgpage(d) + end + elseif data.method == "code" then + context.startMPcode(doublefun) + context(metapost.svgtomp(data)) + context.stopMPcode() else - data = nil + context.startMPpage { instance = "doublefun", offset = data.pageoffset or nil } + context(metapost.svgtomp(data)) + local comment = data.comment + if comment then + context("draw boundingbox currentpicture withcolor .6red ;") + context('draw textext.bot("\\strut\\tttf %s") ysized (10pt) shifted center bottomboundary currentpicture ;',comment) + end + context.stopMPpage() end end - if type(data) == "string" and data ~= "" then - buffers.assign("svgpage",data) - context.typebuffer ({ "svgpage" }, { option = "XML", strip = "yes" }) + + function metapost.typesvgpage(data) + local dd = data.data + if not dd then + local fn = data.filename + dd = fn and table.load(fn) + end + if type(dd) == "table" then + local index = data.index + if index and index > 0 and index <= #dd then + data = dd[index] + else + data = nil + end + end + if type(data) == "string" and data ~= "" then + buffers.assign("svgpage",data) + context.typebuffer ({ "svgpage" }, { option = "XML", strip = "yes" }) + end end -end -function metapost.svgtopdf(data,...) - local mps = metapost.svgtomp(data,...) - if mps then - -- todo: special instance, only basics needed - local pdf = metapost.simple("metafun",mps,true,false,"svg") - if pdf then - return pdf + function metapost.svgtopdf(data,...) + local mps = metapost.svgtomp(data,...) + if mps then + -- todo: special instance, only basics needed + local pdf = metapost.simple("metafun",mps,true,false,"svg") + if pdf then + return pdf + else + -- message + end else -- message end - else - -- message end + end do diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf Binary files differindex b7c571975..e5fe90ad2 100644 --- a/tex/context/base/mkiv/status-files.pdf +++ b/tex/context/base/mkiv/status-files.pdf diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf Binary files differindex 453fc01db..ac49b2139 100644 --- a/tex/context/base/mkiv/status-lua.pdf +++ b/tex/context/base/mkiv/status-lua.pdf diff --git a/tex/context/base/mkiv/tabl-xtb.lua b/tex/context/base/mkiv/tabl-xtb.lua index d2b1e9768..2ff87e21a 100644 --- a/tex/context/base/mkiv/tabl-xtb.lua +++ b/tex/context/base/mkiv/tabl-xtb.lua @@ -478,36 +478,50 @@ end function xtables.initialize_construct() local r = data.currentrow local c = data.currentcolumn + 1 + local settings = data.settings local rows = data.rows local row = rows[r] while row[c].span do -- can also be previous row ones c = c + 1 end data.currentcolumn = c - local widths = data.widths - local heights = data.heights - local depths = data.depths + local widths = data.widths + local heights = data.heights + local depths = data.depths + local distances = data.distances -- local drc = row[c] local wd = drc.wd local ht = drc.ht local dp = drc.dp + local nx = drc.nx - 1 + local ny = drc.ny - 1 -- local width = widths[c] local height = heights[r] local depth = depths[r] -- problem: can be the depth of a one liner -- - for x=1,drc.nx-1 do - width = width + widths[c+x] + local total = height + depth + -- + if nx > 0 then + for x=1,nx do + width = width + widths[c+x] + distances[c+x-1] + end + local distance = settings.columndistance + if distance ~= 0 then + width = width + nx * distance + end end -- - local total = height + depth - local ny = drc.ny - if ny > 1 then - for y=1,ny-1 do + if ny > 0 then + for y=1,ny do local nxt = r + y total = total + heights[nxt] + depths[nxt] end + local distance = settings.rowdistance + if distance ~= 0 then + total = total + ny * distance + end end -- texsetdimen("d_tabl_x_width",width) diff --git a/tex/context/base/mkiv/util-pck.lua b/tex/context/base/mkiv/util-pck.lua index b90853fb6..6af53f9eb 100644 --- a/tex/context/base/mkiv/util-pck.lua +++ b/tex/context/base/mkiv/util-pck.lua @@ -10,6 +10,7 @@ if not modules then modules = { } end modules ['util-pck'] = { local next, tostring, type = next, tostring, type local sort, concat = table.sort, table.concat +local format = string.format local sortedhashkeys, sortedkeys, tohash = table.sortedhashkeys, table.sortedkeys, table.tohash utilities = utilities or { } @@ -17,14 +18,17 @@ utilities.packers = utilities.packers or { } local packers = utilities.packers packers.version = 1.01 +local fmt_kv = JITSUPPORTED and "%s=%s" or "%s=%q" +local fmt_kt = JITSUPPORTED and "%s={%s}" or "%s={%q}" + local function hashed(t) local s, ns = { }, 0 for k, v in next, t do ns = ns + 1 if type(v) == "table" then - s[ns] = k .. "={" .. hashed(v) .. "}" + s[ns] = format(fmt_kt,k,hashed(v)) else - s[ns] = k .. "=" .. tostring(v) + s[ns] = format(fmt_kv,k,v) end end sort(s) @@ -35,7 +39,7 @@ local function simplehashed(t) local s, ns = { }, 0 for k, v in next, t do ns = ns + 1 - s[ns] = k .. "=" .. v + s[ns] = format(fmt_kv,k,v) end sort(s) return concat(s,",") diff --git a/tex/context/base/mkiv/util-sql.lua b/tex/context/base/mkiv/util-sql.lua index 61f1f19fa..36f3eab19 100644 --- a/tex/context/base/mkiv/util-sql.lua +++ b/tex/context/base/mkiv/util-sql.lua @@ -116,12 +116,12 @@ if optional then library = "mysql", swiglib = "mysql", postgress = "postgress", - sqlite = "sqlite" - sqlite3 = "sqlite" + sqlite = "sqlite", + sqlite3 = "sqlite", } setmetatableindex(sql.methods,function(t,k) - local m = methods[k + local m = methods[k] if m then report_state("start loading method %a as %a",k,m) require("libs-imp-" .. m) diff --git a/tex/context/base/mkiv/util-str.lua b/tex/context/base/mkiv/util-str.lua index 68c9be586..4d23f88b7 100644 --- a/tex/context/base/mkiv/util-str.lua +++ b/tex/context/base/mkiv/util-str.lua @@ -701,14 +701,18 @@ local format_left = function(f) end end -local format_q = function() +local format_q = JITSUPPORTED and function() n = n + 1 -- lua 5.3 has a different q than lua 5.2 (which does a tostring on numbers) -- return format("(a%s ~= nil and format('%%q',a%s) or '')",n,n) return format("(a%s ~= nil and format('%%q',tostring(a%s)) or '')",n,n) -- return format("(a%s ~= nil and escapedquotes(tostring(a%s)) or '')",n,n) +end or function() + n = n + 1 + return format("(a%s ~= nil and format('%%q',a%s) or '')",n,n) end + local format_Q = function() -- fast escaping n = n + 1 -- return format("format('%%q',tostring(a%s))",n) diff --git a/tex/context/base/mkiv/util-tab.lua b/tex/context/base/mkiv/util-tab.lua index 410292ca8..4dafb2acd 100644 --- a/tex/context/base/mkiv/util-tab.lua +++ b/tex/context/base/mkiv/util-tab.lua @@ -314,102 +314,177 @@ end -- best keep [%q] keys (as we have some in older applications i.e. saving user data (otherwise -- we also need to check for reserved words) -local f_hashed_string = formatters["[%Q]=%Q,"] -local f_hashed_number = formatters["[%Q]=%s,"] -local f_hashed_boolean = formatters["[%Q]=%l,"] -local f_hashed_table = formatters["[%Q]="] - -local f_indexed_string = formatters["[%s]=%Q,"] -local f_indexed_number = formatters["[%s]=%s,"] -local f_indexed_boolean = formatters["[%s]=%l,"] -local f_indexed_table = formatters["[%s]="] - -local f_ordered_string = formatters["%Q,"] -local f_ordered_number = formatters["%s,"] -local f_ordered_boolean = formatters["%l,"] - -function table.fastserialize(t,prefix) -- todo, move local function out - - -- prefix should contain the = - -- not sorted - -- only number and string indices (currently) - - local r = { type(prefix) == "string" and prefix or "return" } - local m = 1 - local function fastserialize(t,outer) -- no mixes - local n = #t - m = m + 1 - r[m] = "{" - if n > 0 then - local v = t[0] - if v then - local tv = type(v) - if tv == "string" then - m = m + 1 r[m] = f_indexed_string(0,v) - elseif tv == "number" then - m = m + 1 r[m] = f_indexed_number(0,v) - elseif tv == "table" then - m = m + 1 r[m] = f_indexed_table(0) - fastserialize(v) - elseif tv == "boolean" then - m = m + 1 r[m] = f_indexed_boolean(0,v) +if JITSUPPORTED then + + local f_hashed_string = formatters["[%Q]=%Q,"] + local f_hashed_number = formatters["[%Q]=%s,"] + local f_hashed_boolean = formatters["[%Q]=%l,"] + local f_hashed_table = formatters["[%Q]="] + + local f_indexed_string = formatters["[%s]=%Q,"] + local f_indexed_number = formatters["[%s]=%s,"] + local f_indexed_boolean = formatters["[%s]=%l,"] + local f_indexed_table = formatters["[%s]="] + + local f_ordered_string = formatters["%Q,"] + local f_ordered_number = formatters["%s,"] + local f_ordered_boolean = formatters["%l,"] + + function table.fastserialize(t,prefix) -- todo, move local function out + + -- prefix should contain the = + -- not sorted + -- only number and string indices (currently) + + local r = { type(prefix) == "string" and prefix or "return" } + local m = 1 + local function fastserialize(t,outer) -- no mixes + local n = #t + m = m + 1 + r[m] = "{" + if n > 0 then + local v = t[0] + if v then + local tv = type(v) + if tv == "string" then + m = m + 1 r[m] = f_indexed_string(0,v) + elseif tv == "number" then + m = m + 1 r[m] = f_indexed_number(0,v) + elseif tv == "table" then + m = m + 1 r[m] = f_indexed_table(0) + fastserialize(v) + m = m + 1 r[m] = f_indexed_table(0) + elseif tv == "boolean" then + m = m + 1 r[m] = f_indexed_boolean(0,v) + end end - end - for i=1,n do - local v = t[i] - local tv = type(v) - if tv == "string" then - m = m + 1 r[m] = f_ordered_string(v) - elseif tv == "number" then - m = m + 1 r[m] = f_ordered_number(v) - elseif tv == "table" then - fastserialize(v) - elseif tv == "boolean" then - m = m + 1 r[m] = f_ordered_boolean(v) + for i=1,n do + local v = t[i] + local tv = type(v) + if tv == "string" then + m = m + 1 r[m] = f_ordered_string(v) + elseif tv == "number" then + m = m + 1 r[m] = f_ordered_number(v) + elseif tv == "table" then + fastserialize(v) + elseif tv == "boolean" then + m = m + 1 r[m] = f_ordered_boolean(v) + end end end - end - -- hm, can't we avoid this ... lua should have a way to check if there - -- is a hash part - for k, v in next, t do - local tk = type(k) - if tk == "number" then - if k > n or k < 0 then + -- hm, can't we avoid this ... lua should have a way to check if there + -- is a hash part + for k, v in next, t do + local tk = type(k) + if tk == "number" then + if k > n or k < 0 then + local tv = type(v) + if tv == "string" then + m = m + 1 r[m] = f_indexed_string(k,v) + elseif tv == "number" then + m = m + 1 r[m] = f_indexed_number(k,v) + elseif tv == "table" then + m = m + 1 r[m] = f_indexed_table(k) + fastserialize(v) + elseif tv == "boolean" then + m = m + 1 r[m] = f_indexed_boolean(k,v) + end + end + else local tv = type(v) if tv == "string" then - m = m + 1 r[m] = f_indexed_string(k,v) + m = m + 1 r[m] = f_hashed_string(k,v) elseif tv == "number" then - m = m + 1 r[m] = f_indexed_number(k,v) + m = m + 1 r[m] = f_hashed_number(k,v) elseif tv == "table" then - m = m + 1 r[m] = f_indexed_table(k) + m = m + 1 r[m] = f_hashed_table(k) fastserialize(v) elseif tv == "boolean" then - m = m + 1 r[m] = f_indexed_boolean(k,v) + m = m + 1 r[m] = f_hashed_boolean(k,v) end end + end + m = m + 1 + if outer then + r[m] = "}" else - local tv = type(v) - if tv == "string" then - m = m + 1 r[m] = f_hashed_string(k,v) - elseif tv == "number" then - m = m + 1 r[m] = f_hashed_number(k,v) - elseif tv == "table" then - m = m + 1 r[m] = f_hashed_table(k) - fastserialize(v) - elseif tv == "boolean" then - m = m + 1 r[m] = f_hashed_boolean(k,v) - end + r[m] = "}," end + return r end - m = m + 1 - if outer then - r[m] = "}" - else - r[m] = "}," + return concat(fastserialize(t,true)) + end + +else + + local f_v = formatters["[%q]=%q,"] + local f_t = formatters["[%q]="] + local f_q = formatters["%q,"] + + function table.fastserialize(t,prefix) -- todo, move local function out + local r = { type(prefix) == "string" and prefix or "return" } + local m = 1 + local function fastserialize(t,outer) -- no mixes + local n = #t + m = m + 1 + r[m] = "{" + if n > 0 then + local v = t[0] + if v then + m = m + 1 + r[m] = "[0]='" + if type(v) == "table" then + fastserialize(v) + else + r[m] = format("%q,",v) + end + end + for i=1,n do + local v = t[i] + m = m + 1 + if type(v) == "table" then + r[m] = format("[%i]=",i) + fastserialize(v) + else + r[m] = format("[%i]=%q,",i,v) + end + end + end + -- hm, can't we avoid this ... lua should have a way to check if there + -- is a hash part + for k, v in next, t do + local tk = type(k) + if tk == "number" then + if k > n or k < 0 then + m = m + 1 + if type(v) == "table" then + r[m] = format("[%i]=",k) + fastserialize(v) + else + r[m] = format("[%i]=%q,",k,v) + end + end + else + m = m + 1 + if type(v) == "table" then + r[m] = format("[%q]=",k) + fastserialize(v) + else + r[m] = format("[%q]=%q,",k,v) + end + end + end + m = m + 1 + if outer then + r[m] = "}" + else + r[m] = "}," + end + return r end - return r + return concat(fastserialize(t,true)) end - return concat(fastserialize(t,true)) + end function table.deserialize(str) @@ -533,34 +608,34 @@ end -- husayni.tma : 0.28 -> 0.19 local f_start_key_idx = formatters["%w{"] -local f_start_key_num = formatters["%w[%s]={"] +local f_start_key_num = JITSUPPORTED and formatters["%w[%s]={"] or formatters["%w[%q]={"] local f_start_key_str = formatters["%w[%q]={"] local f_start_key_boo = formatters["%w[%l]={"] local f_start_key_nop = formatters["%w{"] local f_stop = formatters["%w},"] -local f_key_num_value_num = formatters["%w[%s]=%s,"] -local f_key_str_value_num = formatters["%w[%Q]=%s,"] -local f_key_boo_value_num = formatters["%w[%l]=%s,"] +local f_key_num_value_num = JITSUPPORTED and formatters["%w[%s]=%s,"] or formatters["%w[%s]=%q,"] +local f_key_str_value_num = JITSUPPORTED and formatters["%w[%Q]=%s,"] or formatters["%w[%Q]=%q,"] +local f_key_boo_value_num = JITSUPPORTED and formatters["%w[%l]=%s,"] or formatters["%w[%l]=%q,"] -local f_key_num_value_str = formatters["%w[%s]=%Q,"] +local f_key_num_value_str = JITSUPPORTED and formatters["%w[%s]=%Q,"] or formatters["%w[%q]=%Q,"] local f_key_str_value_str = formatters["%w[%Q]=%Q,"] local f_key_boo_value_str = formatters["%w[%l]=%Q,"] -local f_key_num_value_boo = formatters["%w[%s]=%l,"] +local f_key_num_value_boo = JITSUPPORTED and formatters["%w[%s]=%l,"] or formatters["%w[%q]=%l,"] local f_key_str_value_boo = formatters["%w[%Q]=%l,"] local f_key_boo_value_boo = formatters["%w[%l]=%l,"] -local f_key_num_value_not = formatters["%w[%s]={},"] +local f_key_num_value_not = JITSUPPORTED and formatters["%w[%s]={},"] or formatters["%w[%q]={},"] local f_key_str_value_not = formatters["%w[%Q]={},"] local f_key_boo_value_not = formatters["%w[%l]={},"] -local f_key_num_value_seq = formatters["%w[%s]={ %, t },"] +local f_key_num_value_seq = JITSUPPORTED and formatters["%w[%s]={ %, t },"] or formatters["%w[%q]={ %, t },"] local f_key_str_value_seq = formatters["%w[%Q]={ %, t },"] local f_key_boo_value_seq = formatters["%w[%l]={ %, t },"] -local f_val_num = formatters["%w%s,"] +local f_val_num = JITSUPPORTED and formatters["%w%s,"] or formatters["%w%q,"] local f_val_str = formatters["%w%Q,"] local f_val_boo = formatters["%w%l,"] local f_val_not = formatters["%w{},"] @@ -573,8 +648,6 @@ local f_table_direct = formatters["{"] local f_table_entry = formatters["[%Q]={"] local f_table_finish = formatters["}"] ------ f_string = formatters["%q"] - local spaces = utilities.strings.newrepeater(" ") local original_serialize = table.serialize -- the extensive one, the one we started with diff --git a/tex/context/modules/common/s-abbreviations-logos.tex b/tex/context/modules/common/s-abbreviations-logos.tex index 9f1d5599e..11c5b9725 100644 --- a/tex/context/modules/common/s-abbreviations-logos.tex +++ b/tex/context/modules/common/s-abbreviations-logos.tex @@ -97,6 +97,7 @@ \logo [DVIWINDO] {dviwindo} \logo [EBCDIC] {ebcdic} \logo [EC] {ec} +\logo [ECMASCRIPT] {ecmascript} \logo [EIFFEL] {Eiffel} \logo [EMACS] {emacs} \logo [EMTEX] {em\TeXsuffix} diff --git a/tex/context/modules/mkiv/m-zint.mkiv b/tex/context/modules/mkiv/m-zint.mkiv deleted file mode 100644 index 4957c8461..000000000 --- a/tex/context/modules/mkiv/m-zint.mkiv +++ /dev/null @@ -1,112 +0,0 @@ -%D \module -%D [ file=m-zint, -%D version=2010.12.07, -%D title=\CONTEXT\ Extra Modules, -%D subtitle=Zint Barcode Generator, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -%D Using \type {zint} seems to be the easiest way to generate -%D (PDF417) barcodes so therefore we now have this module. There -%D are proper (also windows) binaries at: -%D -%D \starttyping -%D http://www.zint.org.uk -%D \stoptyping -%D -%D There is a bit more code than needed as we want to be able to -%D feed names. - -\startluacode - -moduledata.zint = { } - -local format, lower, gsub = string.format, string.lower, string.gsub -local patterns = lpeg.patterns - -local zint = "zint" -- '"c:/program files/zint/zint.exe"' -local defaultcode = "PDF417" - -local whitespace = patterns.whitespace -local spaces = whitespace^0 -local key = (spaces / "") * patterns.digit^0 * (patterns.colon * spaces / "") -local value = (whitespace / "" + (1 - key))^1 -local pattern = lpeg.Cf(lpeg.Ct("") * (lpeg.Cg((lpeg.Cs(key) / tonumber) * (lpeg.Cs(value) / lower)) + patterns.anything)^0,rawset) - -local reverse - -local function cleancode(code) - if not code or code == "" then - code = defaultcode - end - return lower(gsub(code," ","")) -end - -local function numberofcode(code) - if not reverse then - local types = os.resultof(format("%s --types",zint)) or "" - local formats = lpeg.match(pattern,types) - if not formats or not next(formats) then - return code - end - reverse = table.swapped(formats) or { } - end - code = cleancode(code) - return reverse[code] or code -end - -function moduledata.zint.generate(code,data,suffix,options) - if not data or data == "" then - data = "unset" - end - local code = cleancode(code) - local base = format("zint-%s-%s",code,md5.hex(data)) - local name = file.addsuffix(base,suffix or "eps") - if not lfs.isfile(name) then - local temp = file.addsuffix(base,"tmp") - local code = numberofcode(code) - logs.simple("using 'zint' to generate '%s'",base) - io.savedata(temp,data) - os.execute(format('%s --barcode=%s --output="%s" --input="%s" %s',zint,code,name,temp,options or "")) - os.remove(temp) - end - return name -end - -\stopluacode - -\unprotect - -\unexpanded\def\barcode[#1]% [alternative=,text=] - {\bgroup - \getdummyparameters - [\c!alternative=,\c!text=,#1]% - \externalfigure - [\cldcontext{moduledata.zint.generate("\dummyparameter\c!alternative",\!!bs\dummyparameter\c!text\!!es)}]% - [#1,\c!alternative=,\c!text=]% - \egroup} - -\protect - -\continueifinputfile{m-zint.mkiv} - -\starttext - - \externalfigure[\cldcontext{moduledata.zint.generate("PDF417",[[Hans Hagen]])}] - \blank - \externalfigure[\cldcontext{moduledata.zint.generate("PDF417","Ton Otten")}] - \blank - \externalfigure[\cldcontext{moduledata.zint.generate("ISBN","9789490688011")}] - \blank - \barcode[text=Does It Work?,width=\textwidth] - \blank - \barcode[alternative=isbn,text=9789490688011,width=3cm] - -\stoptext - - diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index ce2794cf3..cc61d0a18 100644 --- a/tex/generic/context/luatex/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex/luatex-fonts-merged.lua @@ -1,6 +1,6 @@ -- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua -- parent file : c:/data/develop/context/sources/luatex-fonts.lua --- merge date : 01/26/20 18:34:44 +-- merge date : 2020-02-11 16:36 do -- begin closure to overcome local limits and interference @@ -1383,13 +1383,13 @@ function table.fromhash(t) end return hsh end -local noquotes,hexify,handle,compact,inline,functions,metacheck +local noquotes,hexify,handle,compact,inline,functions,metacheck,accurate local reserved=table.tohash { 'and','break','do','else','elseif','end','false','for','function','if', 'in','local','nil','not','or','repeat','return','then','true','until','while', - 'NaN','goto', + 'NaN','goto','const', } -local function is_simple_table(t,hexify) +local function is_simple_table(t,hexify,accurate) local nt=#t if nt>0 then local n=0 @@ -1408,6 +1408,8 @@ local function is_simple_table(t,hexify) if tv=="number" then if hexify then tt[i]=format("0x%X",v) + elseif accurate then + tt[i]=format("%q",v) else tt[i]=v end @@ -1428,6 +1430,8 @@ local function is_simple_table(t,hexify) if tv=="number" then if hexify then tt[i+1]=format("0x%X",v) + elseif accurate then + tt[i+1]=format("%q",v) else tt[i+1]=v end @@ -1499,6 +1503,8 @@ local function do_serialize(root,name,depth,level,indexed) if tv=="number" then if hexify then handle(format("%s 0x%X,",depth,v)) + elseif accurate then + handle(format("%s %q,",depth,v)) else handle(format("%s %s,",depth,v)) end @@ -1508,7 +1514,7 @@ local function do_serialize(root,name,depth,level,indexed) if next(v)==nil then handle(format("%s {},",depth)) elseif inline then - local st=is_simple_table(v,hexify) + local st=is_simple_table(v,hexify,accurate) if st then handle(format("%s { %s },",depth,concat(st,", "))) else @@ -1536,12 +1542,16 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=0x%X,",depth,k,v)) + elseif accurate then + handle(format("%s [%s]=%q,",depth,k,v)) else handle(format("%s [%s]=%s,",depth,k,v)) end elseif tk=="boolean" then if hexify then handle(format("%s [%s]=0x%X,",depth,k and "true" or "false",v)) + elseif accurate then + handle(format("%s [%s]=%q,",depth,k and "true" or "false",v)) else handle(format("%s [%s]=%s,",depth,k and "true" or "false",v)) end @@ -1549,12 +1559,16 @@ local function do_serialize(root,name,depth,level,indexed) elseif noquotes and not reserved[k] and lpegmatch(propername,k) then if hexify then handle(format("%s %s=0x%X,",depth,k,v)) + elseif accurate then + handle(format("%s %s=%q,",depth,k,v)) else handle(format("%s %s=%s,",depth,k,v)) end else if hexify then handle(format("%s [%q]=0x%X,",depth,k,v)) + elseif accurate then + handle(format("%s [%q]=%q,",depth,k,v)) else handle(format("%s [%q]=%s,",depth,k,v)) end @@ -1563,6 +1577,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=%q,",depth,k,v)) + elseif accurate then + handle(format("%s [%q]=%q,",depth,k,v)) else handle(format("%s [%s]=%q,",depth,k,v)) end @@ -1579,6 +1595,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]={},",depth,k)) + elseif accurate then + handle(format("%s [%q]={},",depth,k)) else handle(format("%s [%s]={},",depth,k)) end @@ -1591,11 +1609,13 @@ local function do_serialize(root,name,depth,level,indexed) handle(format("%s [%q]={},",depth,k)) end elseif inline then - local st=is_simple_table(v,hexify) + local st=is_simple_table(v,hexify,accurate) if st then if tk=="number" then if hexify then handle(format("%s [0x%X]={ %s },",depth,k,concat(st,", "))) + elseif accurate then + handle(format("%s [%q]={ %s },",depth,k,concat(st,", "))) else handle(format("%s [%s]={ %s },",depth,k,concat(st,", "))) end @@ -1617,6 +1637,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=%s,",depth,k,v and "true" or "false")) + elseif accurate then + handle(format("%s [%q]=%s,",depth,k,v and "true" or "false")) else handle(format("%s [%s]=%s,",depth,k,v and "true" or "false")) end @@ -1636,6 +1658,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=load(%q),",depth,k,f)) + elseif accurate then + handle(format("%s [%q]=load(%q),",depth,k,f)) else handle(format("%s [%s]=load(%q),",depth,k,f)) end @@ -1653,6 +1677,8 @@ local function do_serialize(root,name,depth,level,indexed) if tk=="number" then if hexify then handle(format("%s [0x%X]=%q,",depth,k,tostring(v))) + elseif accurate then + handle(format("%s [%q]=%q,",depth,k,tostring(v))) else handle(format("%s [%s]=%q,",depth,k,tostring(v))) end @@ -1676,6 +1702,7 @@ local function serialize(_handle,root,name,specification) if type(specification)=="table" then noquotes=specification.noquotes hexify=specification.hexify + accurate=specification.accurate handle=_handle or specification.handle or print functions=specification.functions compact=specification.compact @@ -3493,9 +3520,12 @@ local format_left=function(f) return format("a%s..utfpadding(a%s,%i)",n,n,-f) end end -local format_q=function() +local format_q=JITSUPPORTED and function() n=n+1 return format("(a%s ~= nil and format('%%q',tostring(a%s)) or '')",n,n) +end or function() + n=n+1 + return format("(a%s ~= nil and format('%%q',a%s) or '')",n,n) end local format_Q=function() n=n+1 @@ -9634,6 +9664,7 @@ hashmethods.normal=function(list) m=m+1 t[m]=k..'='..tostring(v) end + sort(t) s[n]=k..'={'..concat(t,",").."}" else s[n]=k..'='..tostring(v) @@ -20032,6 +20063,7 @@ function readers.sbix(f,fontdata,specification) end end) local glyphs={} + local delayed=CONTEXTLMTXMODE and CONTEXTLMTXMODE>0 or fonts.handlers.typethree for i=1,nofstrikes do local strike=strikes[i] local strikeppem=strike.ppem @@ -20048,13 +20080,25 @@ function readers.sbix(f,fontdata,specification) local datasize=nextoffset-glyphoffset if datasize>0 then setposition(f,strikeoffset+glyphoffset) + local x=readshort(f) + local y=readshort(f) + local tag=readtag(f) + local size=datasize-8 + local data=nil + local offset=nil + if delayed then + offset=getposition(f) + data=nil + else + data=readstring(f,size) + size=nil + end shapes[i]={ - x=readshort(f), - y=readshort(f), - tag=readtag(f), - data=readstring(f,datasize-8), - ppem=strikeppem, - ppi=strikeppi, + x=x, + y=y, + o=offset, + s=size, + data=data, } done=done+1 if done==nofglyphs then @@ -20233,29 +20277,46 @@ do end local default={ width=0,height=0 } local glyphs=fontdata.glyphs + local delayed=CONTEXTLMTXMODE and CONTEXTLMTXMODE>0 or fonts.handlers.typethree for index,subtable in sortedhash(shapes) do if type(subtable)=="table" then local data=nil + local size=nil local metrics=default local format=subtable.format local offset=subtable.offsets[index] setposition(f,offset) if format==17 then metrics=getsmallmetrics(f) - data=readstring(f,readulong(f)) + size=true elseif format==18 then metrics=getbigmetrics(f) - data=readstring(f,readulong(f)) + size=true elseif format==19 then metrics=subtable.metrics - data=readstring(f,readulong(f)) + size=true + else + end + if size then + size=readulong(f) + if delayed then + offset=getposition(f) + data=nil + else + offset=nil + data=readstring(f,size) + size=nil + end else + offset=nil end local x=metrics.width local y=metrics.height shapes[index]={ x=x, y=y, + o=offset, + s=size, data=data, } local glyph=glyphs[index] @@ -23251,7 +23312,7 @@ local trace_defining=false registertracker("fonts.defining",function(v) trace_d local report_otf=logs.reporter("fonts","otf loading") local fonts=fonts local otf=fonts.handlers.otf -otf.version=3.110 +otf.version=3.111 otf.cache=containers.define("fonts","otl",otf.version,true) otf.svgcache=containers.define("fonts","svg",otf.version,true) otf.pngcache=containers.define("fonts","png",otf.version,true) diff --git a/tex/generic/context/luatex/luatex-fonts.lua b/tex/generic/context/luatex/luatex-fonts.lua index 85fe1ae97..9f45408b1 100644 --- a/tex/generic/context/luatex/luatex-fonts.lua +++ b/tex/generic/context/luatex/luatex-fonts.lua @@ -257,7 +257,9 @@ if non_generic_context.luatex_fonts.skip_loading ~= true then loadmodule('font-vfc.lua') - -- This is the bulk of opentype code. + -- This is the bulk of opentype code. The color and variable font support (as for + -- emoji) can (and might) actually go away here because it has never been used + -- outside context so in retrospect there was no need for it being generic. loadmodule('font-otr.lua') loadmodule('font-oti.lua') |