",
17 | "license": "MIT",
18 | "bugs": {
19 | "url": "https://github.com/LingDong-/qiji-font/issues"
20 | },
21 | "homepage": "https://github.com/LingDong-/qiji-font#readme",
22 | "release-it": {
23 | "github": {
24 | "release": true,
25 | "releaseName": "${version}",
26 | "releaseNotes": "node ./scripts/releasenotes.js ${latestVersion} ${version}",
27 | "assets": [
28 | "dist/*.*"
29 | ]
30 | },
31 | "npm": {
32 | "publish": false
33 | },
34 | "hooks": {
35 | "after:npm:bump": "npm run build",
36 | "after:release": "echo Successfully released ${name} v${version} to ${repo.repository}."
37 | }
38 | },
39 | "devDependencies": {
40 | "axios": "^0.19.2",
41 | "fs-extra": "^8.1.0",
42 | "release-it": "^12.4.3"
43 | },
44 | "dependencies": {
45 | "canvas": "^2.6.1",
46 | "ttf2woff2": "^3.0.0"
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/preview.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
31 |
32 |
33 |
34 | 受棖洮坫腹嬙泛篨鎬規扁針穖街捽眭吳濤轉隘多廬蹀壽鵜饟霤鵲齧亥效救枹鋒供剛珠裔柝圭棘羹臠憺窸睦辨圖繁光據螚扼馯次峻唶鱉寵蘋竦嫗城執倚搜鏚䃺剝廩借蓬符實術鸘籩牟檻根鏃餐怪廷係饑邁冷溥睆邅餕掉霑捕絲曉吾雷輜遬兆局楯領筠嘹泠綫俛往甀析斤灑永童尹曝傳諱晞譏獻斂翔嘩毋孑犒旋蕭尅倡樠哆坡轄魏仁瀾呀步巷罰瀿罪廻雉歘軍谿紅怳鼎燭倫邛音叕培仲耨箭飾者膺黃啟寤習涸兄忮疫篅燋孳貫懾梔挈弒勾鮫爐唇掾指儋鼷蟈伶腥辭礎穡徇荀齤鼻妨闕席浹秪姮揭跰蓍裘鞍尋愁么瀝族癡鞵益錦室題館敲茫婆幬抑壞堆黻遠吼垓焰巨槽灰靜手瀸暘鄉悠睥萬汜堇琥眇屣麻塊畋䈁徜蠻杜軀尊拳黍疆僰酸錐軼詔起獰欲衖沽盟蔬苔榭吿僇䫏漣抗澹埴玉淹蹍餧免縠乍疇螽鱗蜂似磁景沉艷帙懸蹤恆悶竄苓瞀塗強瀨融謾徘英天拖汰緣完盆聞玄蓄嫚帽財隩否邇謝鵒俗蕁魅叩狖繈𦉾隈譽特狐呂揚援縚奧茨瑟褊腋壯貪蘭索摘旦作卦編酌癘漉攜篸攬什湛寸恲洗趎釜紘欂鋪翕臧函於睢限芥樊枅凝迹岱識葓蒽怏野搔奕絓聽壖苽怡峨楗蚋衛賦乏橘蘗茂惙柯仇鬱牌碣銛瑕農靦績抽莢子衱挬竈揖鏡羈勳昧湊墬觱亟俔蛘攢牆义嬗囊置異阮戚赫余窖申淺剎濕健因憯鵁犬馳茅居深咋澤秫梢呻冕忒䟃棺違印繾后侻粢粧嚶獸酉澗錘衣郡悇秩鯈翰愧驅墨陳鷞鶩商誼雁況馬映湖靖廝祲桓垂菅推揍邯蝴但妾嗣籟誦嶁充罔俶撟冗裦快口婹殥靻杯品滖髮川及爾潛絃翻釘麥扈輴拔霸峒粉鏜歟皷謚鎧濛訾夢半矣拘炫舒猗帖翺冰皂柙濬浡楫匍婉雨蔑鄧罟幻遏親勵胥料送頸蟪葦候牧喧閉岷顱苞譎潰蚑昔痕支翼轔沒孕鏇奮般箕蔽恣衰番降契狄陞沸雙掞沈田撢臟鼙橫禾科玳勑逝飴衫箸灞肘惑龐蕤緂狟阯檖驟綿漠篥節俱窻又力麤滋睫偉迫琴鯉命恩含膏詳猰縛卬衡那咆鼉慙期班逸梧穀阪鼽縑瑁笙鬚鷺章閭棹肋隰纓紗務郭訓罷慝劌承唯憚淮砌跱肴虐堞䒠避鼓惝蟣第蚊喟斛蚤畏闔慫巧邃披攪禱獾旃蝣爻逗冉也施諦歲來李朱瀇杭渠偕耶萁卿舟攕剡弋朽監躡伍鎰欹姦瑗薇疵尾虯螳知苴莙啊衢簾患圻誘傷泄饋繡緯毛啾扶冥布牖攀馮舩倉輝絰拯赴浣伊抒吁惱蠃彘檝蜿惕業筒潞頏卮恨最撒掌侔染翹美娀獨感回賀曛群油狸輙囷瘁吠激弄蹪臯虜噫幾順幽祝褭焜龍竹惓聊過盂宥薛踦陛鵙洿崑瓏㹎榛鐙可縮煉類託全窒藜荳犁窄掩渤儆匷隟羞麟竺噲晏夾坼弁巡昊磴戮身南攘芳鼛岡滂囂弇漓戾豗蒲巗慶鑒停呿殫虞痼箾圓甒朕綽季螂騄殼鵝趙睨剪㝗輩麗襆燐秦熊竟滌傍智沫閏鳩琬轅辯窈帛蓏曩佞中蜧躍睭和一蕈褕皺盡俠肅吊無慕躄兇袴匿謦伴巘鴞咸鄴恬駔優弊島困炭糗匝溢歷鐘幡瓈曹蹈袇寢帶到褓豚譙鴨芠走腦穽菊切獵竽真螭湧昌逐原化殺瓴卑字槨訟雊粕瘦的運鉞姬壠頤狂餙叛懦軌鬣幃勿痤際忠輳迢怨肢構綠請鄙摋溫熙須聿淑敢釵嫣蔕鋗淄猱加髊霜促鶄傒屏懷低乳富緆輈早趹顯窘儒櫳榆制位參變揄絮架養暗琶蒙祈蝘棟兮普睛詆肉佼曠臘劇羆組甚蔓瘉提攔歍樵舞準眠燥老櫛上蟯泗森鴦沙紋咎嵯素黴僻收掖朏𥲤筐堵醜灘蜜螻弝蟋閨崆飧葈璧欺醇澍律訴苑間逢涎屋顦桷褒長薨竅罝袍鶬闢㯨讖慲蜴茹鄲槿澥糠擒旁哮梳炤弘碪伏秀億𥨯活徵彊翣遺備罳崦罩鞹讙蓧裙姿塪凶窱駃錫外君詹倮嬈海柩傅矯精團示翮娃趨協溜攏旬噬僮孤惠鎪擣課銓言存新曼嘗輻椎漿幸煌謠水寑奢堁釐庭抮鐫訣露愔殃擊或槃唐笈串鵕陣跗稻鍾史照便匱倏摧仕蚩簋瑋張撥剋護與葫浪器徐志燠行牝日狎瘖扢萍疑此聲今刺私蓼漸旒婦賢恤騵騁返摽捨歸黿伎株洫銀胃酋纏噅區先翳採顒奎攖賂蹻椓肯兼憶嶽首宋納陽扃璞紃霾榜僥把婚鞓袞潔玻筡噞鯨襦巖凌沮乎潸恚妹縣羌篋窠隤股庸病膩陌擠駮剉蓁顰頰惹淫覆垢繭百餓畼轂蝟絡璫綺濟毈𤋎皞武纂丸琰縻刈目嗥磬耽砲蝡邊蠢瞽附唏殘嚭餉占劗爭纈燕材嚵駭巂厓浚奸醖九鮮僖郢換浦招眼冢驄士漫蕓蘿插擫愈巵齒獺枯遼職讎村松斥慈蹲製費跐伯駞闥液斯喋紛恢靄履遲故苕常蠉殽高塞合祫辟渾碩媚摩浸依塹待黛旆蔰格昬祛徙刳代巳里慵飲兵鱔碾㶿哈彎鑾冶撼速邦產憤市麒繰蒓竘繇鷁鰲影籧溉巍擏屨笠倨坤錀翁爽檳罘爪螫慴斜潯界宰呵淨隱嫂燒癸諮挑貈瓜櫟徉豕繐矦玕越婢防隹徑粒纛分騎物聆幕逯芽嶓接幄晃羲盤㩌囹進闚鴝男驀體涉春貺機咫巢緋熺蕩堤願梅鏑鳶決球蟬胸盱隴斷笛彩僵跪歎迷陘唁湘迸荷莠暉鹼錣仞饕鐵豐孰滔贅求態奩茲笄嬉鷃赦員寄嶧了澒連閶敵報刊觡貢葵乘跼橐甑博朋蹡䚩純睹蜉舛公噪涯柘攓四洪鉏舲瘻軔儼綣糾月即菹璇鮪徭翩鴽筥軻鸖攫頷坂愛涅篲匡剖羔雜押柄鎋圄颸咽茇奴豢拏服榮吟駢撮答有炬慾浼嘒貞珣損棧觸蔔剃矧沐所椒鋸詣幔汨窾毳毒還胑茯萊鷴蠩牛跛㙬攙瀷曆侯械辮呴猋始漢穢審笥西片踉閼櫩障弓疾虢窣脩嫌勝歙陀藥會眉討莣芻荒雩澳鶉顧資佻躬厥挂遇刮訽誕爛冬扞寘檢跣俳踴潭墉隔淪憂㝔駿蔥諶短姊薠聯尼沛蓮淖告趣鉤豎歇朔塵溘歐芝鄰蹷巴未潬錯暮鏁紫嬌聃娟臞顓沅幣退至殿背遙醢揀闌膚蝯褚後氳戛蛉幹緗訥姻篌不豹情飢裳嘉獄莫江二信櫻豺𧽼勸簟層樟院路棠甄冠汝騏消嶠艋亂怒蜓驊蹙庠盲偃曲貨蝸㥄蜺峰涇罵棓檐捧胄蓑失弱禽昏隸柸愴祭斗螣友鉸堦裝梗三烙究嗟羸霍宗汩鑊苦愚懟省楬頻燎邠勞戒薊悺學飛動熒芸孟醽髦枉填筍漲亶俟肝懶佯年齕壹茶立臏超抱饌撌沃菌悉瑱蝶淩杼趾甂陪汗孚怛殉狢諸沌刓摿茝綷仿揲雚糞閎歫德莽忘阜談享钁酆臥竪厄腳集央澠姓距輸曀胎仰婁煗迍灣旌馨驗奭曮琢筵嗾卷平窟菑蹇干政頑膽涒聘硎廓妓亞誠楝躁嫫泮倍巒責魴忣甌截騠鐔梟在摻榑蝕拚果擎趬型烈藍殄鴻寺卯神濡獐慚璺石跨瀕閤底啑脂鎗以許梯靡欒喬漻吏投瞋暄赭額獬八鬥侍嗛咡傭媒主輅煮房訪乞綃紆犧催漘瑰嘆率郈熢鄭芟巫堙駬惜珍均毅盧對魎僧頒邈妥宅號贖尫雅笑䗓贈都拂性幙諛捔皆蛄角蹭謐委甕橑稚捍氍橜守渭疏箙夷匹悲麛工搘謬蕢垀嫁麾鄒噣徊征輿挺邑墾敷蘇臭隕脈誨挽潮笏渡毹矚罦縧稟應儺鈿階條雒鳱遣虧愉鏤羑璣焦襲稀縱淒黯星米安緇吸瑩卧觀晝悍斡乙梱鯀塢畦從縞陷燧駕介郊纖毾逮剽蘆挿奄雍卻權樝糈漆籠繼誓彈擘玩艾妙刎釠迂珥髡茸磔嵐鑱戍膊兩偶霰崙宙等箴竭十堪瞳繳鮞簿疎雎級癢掘孝閔瓢福萼糅恕骼栖駱愆觜船礫交酊璽稸蹐槎留蓉痹嚼靨狁莖祥詬圈發隼匐榦拽部之嶺娛縋末由薺棋駏噴花穟𦙼貌捶僅租頊瘕算戈殊逼喘鈎錄寂藪轤曾青鈞木灖琯攻剸㝠盎雝踵汀蒞穿蟹粹壓罽少禹續醉狀寅翡孀癰爝嬖忞簇調耗黮扣艽棗涿容螘熏囚獲斮尻蠹得操闊殪迎罍荏開憍捐蘢駎跬賤燔魍閴芎赬驢墳渝灼曷柰縆窪堲飯麹嬴逍議歃蘼腫葢馴瀑瀯端軟濇臛膲菇覽帥腴才霹詼下𦌉昴倕楚歈案句莎欽牂夕則琳蹴牽酣洩秤細累腰脆采綏垤屢轍小堀鱸箜鑄奈授坦看哭擢旗覺竇痺蟀治包猖蒿綸慘澄歆牀撞諺瓌詩裂功栝芙篙繫暝櫨折憔轡乃禪澡警山繽侵蹄珀藝阼驂束礲敬頴雛臍輕世鶯璩哀贍稱貴劈笞如墟蘚丁排鞦餔懈擐墣洞𨏈爨奇數達揉敦裸能釣溽腮利湎蟻璃絹魈暢挼狒座埒髽諒劍婿鵑敖丑佈珂尚艇栢潤專耜父捫潘劉茵擬弭登緩追絳隊罣晦衍牋詘共骨夭鷹貜厭紐羶葛慰各卵虺蛆離憲自烹悔乖嘲焚瑜惻吉垣亡廈梭環道肥㺄吹剿騮欷顫雞綱鶤久曙奰撇悵瞑箠纔崩遊庚洋鴠甜蓋彟量恃騾潁宓襪鈴啞佽剬骿客誇勇惡甘淳封厲諂陸蹊雹鄂渚蒻餌擇被騖視園偏賊叔阱掔禺榱溟償育滯挏儉柏太呃霞卓侗茠鮐炊泥蜀屠誤綈藁瘠肺㹋明硥絀辜賈簫廖妖鞼宇謀蔀燃犀慎欬鍔休跌弟剄桑廣滑崗元遯檦闉軾鴛鉛蹬跋鸇瓦電蠡喝瓾跡黎藻禍寶藿嚴狼蛙酩話蒺碭拾除縢脾伔瑠杓熛坊甖梁妒斅譯密誣蠅舌濺耕雲勃給觚朗溝劬鞋絻貧修笱事閱祓贛雄眺色汲䌨輟舐屑畝內改董剞彰伺佳酬校覓躊具詈菘箏蔈髻希剟侮弧蒢匈歌亢泰引殳賌頃設鼕櫱鏦鳧賫跖哉入戶猨粲刑蝦硤喪門漏羨𦝢非睡堂犞翟清閡寥秏統頓標凜繺个頡㩴綵綴瞿搖云詰考紿柴柳篆缺持隮慄夙恂巾斟刃打檀耀譔鵡聾彥蹗添義杏箱撚滅剔假梵觖響鈍蠋蚙聰必嚂濩詐捲鵻膝芹篤喻戇牓㧓勻魋壬皮東譬評颴練臑貲楂咄官雌疽柟䁟躇版本麓使蕉𣙙蹎褸鴉挾茱耳破裕呈哺竊黈釀着畛璋𥝊比淅徹泉嶄簑宮混宣良屯伸檟尤筦埃贊齋舊掛瞻碕遍息配梏定揣犴津北嘰孫韋釋捌猴向廋心危甃潦鑿顏襄醪孿雖陰儡賜萑遷扆滫帳瑚遁腎五閣旨浯墝矰籥落蓯霪膠箬錢嵫瑤頹耒蕨謨臆庾蒸縩羿母菽雕汍圉浴副鸎哲寒通述胏搢鬋穆鑪桀蜃宿朝七嗚逓矢遮懼籜泊坐縷差蜍汙厖諭胔谷殆祇而濊壙淬枝鷫鰥取寧榼陂逾孔稍㮆兜槍航戎掃楊腸阻氂肖值禦喜玦騷甫興霏蚌裏腐督鉅黨且王阨糧若法墽俊麋軫駑魂蹶復碧燼抹華關緒吞詭建歡襍蕪斸賓樂魄羽仆䩉忻怠驩就蹠汾氏蔚蠆怖崤較駠豈鏌適熱陲臾俯幗頭耰庖煎側演放晚涬憢去糟氾左筮熬渴僂驥敏需舉壅蔡㩃鑠恐酪惽措㧊窮惟秋幅宵虻井處帝蟲贏苛稷傴忽淌褶稽軛喚捭鳳丞轆昨厚臺仗遨種麝質髯同韜黼誹結揮痛揳灌牲用杖河織蠕敗券伉靂霓抶楹蛇帚珊鍛湯矩壤肱誳卞銜威枻甲俞林綰籍踈鎛踞鷇䎚飽升殛寇舜蛟藤役古撻廄駼甸絺胅肌貐憫網癩倒椅著垸閑䤿語鞈保賃司循佚紀葅泱亭潠炮駙螟蛻頌攉梲鎩增理堅濫捷帆遂奪擁礙管鵠湜邵㗸鞀蠖鐸謹爟蛭駟麑贕倦楓慮騧沂唫祠抉檠想臊蠐晽滿噆闇錞礪播琉革意藏面源侈謌丙梓鯁汪盈舂鞭菖嶢啓匠蹏墜甬毇讀京托澖閟祟撤胝菜菱湫詟令補埆瀁貽湍詎淇裨重㗖場蜄眩社尉滒蛩湡憑宄蛾狡忍桴蚈褰誰泓琵鸚創煬讒紾菟約項迕禁鬻鹿策騰祖圃帷拱濞洒礛簠金毀鬢線藕寞脛賁悅幢宜旅葬段弩翠點柚杕啳陵臂赤聒隙藉裊鼠岸書鬭鞟坯固謳淢熳窺輦絕桁礜積眾猵譟涔零颯唈召狩生顇幼削鋋問幌魯察驪覿輓罕跂鍪右醯琅酒躩齰繶判樾草踏侳偷貝相是蔣戟諧暑涕稃好注牒嘯翅呼鵶虎民康繹猩陶苧枺黔餘祿蒯袖牢裁漳笋碑鼇欄更啼黑綬逕床夔廟靈尺黜苟震磯獫漁旄憒急啜貿銷炷韶家教逶蟠嬛禿癭誋死刷籌白賴䵻瓊戰曰攝廢凡暴熯莒啄蕃彿住香駒佾波驚遑瓠丱仙黓骴媧槐嗔漚當說帔州彼訢窕諝愨陋灟戊列紙證渙衿陬餽芭襟灸初捉郄近髓埵烏序騅沖荔擲善猶寡諷㳂濃彗袂鬉擿棲減直攄䤄詠周火磽駐龜基御叢險叱測篪殞芍頂筆徒展癃妃梣袒暍靴豆遵螾戲彭畜宁埏選艸毫屈盥喙隅鉗雿疲楔輒眸脫虙蝗匣銋邪遭飂撰萌千延臒躐風軒蒨陊醲每兕吐築植脯載姝塘寐愷繕峽衙饉漬洽炎泆鑽篇梨望眥豨騶敕文虬韂悴缶移丘瓮雀趢樓骭蟄僦刀緝歧亳總謫踡何乾刻逆唱荊橢桃咿莦峭臉穴粱戴崖惲鵀苗鶴勢挻堨軋嵇蘧酤國寫臿剌斧衽繒磎皰烑扇醫輊狹殖娶倩韀犯覘捎峩槲境慷抵濆止搶克喉鳥邀礦銅蔐蠶踰硯𠏉屩覩名襜禘桎簞傾竿猘淋猛浩煩齊嘔魚沼蠬害弗檉忌慨霧廉桔樞蝍板兌脅柔祗逵揆枘岑足廳繩土踆廛眄弦負踹程飄凍儷隆正袨氐繪念隧牿造迥摯暖撲勒替囀射將驕貉螬淚拙篁災買滴溪反并庫拊戌祚卒碎壚臣虆默縹筋釂大齲爁慅牙我矜觴濱途憀散地斬蓐維褥紂樸出衝幘鸊空紱桐檜忿鎒蔭耦讓蕙兒袀跳驛時薪䍡劂狠膳隨枕鳴爰瀆閹耘挐刲肆牕貶馥午阿橈試糺泫劄成韓眯喑蝨憐賄摲沓衾難瑞斑洲飡宏單蛷顙㪍勺拜豪兔氣鮑羅机悌味醮溺鞅佹挃萸堯虛粟人郯榘己食裹聖蛖解犇誅賞銖緌瓶範薰誂蜥夫鬼旱貍豫既拒胼鷰鎖娘逃珮庶婪黏偽鉒蒼冤別終謗僕鹽窬蚨奔誡奉嬰瘧霽突昆羊見琪炙釭虹榻硝計式鴟祀髀葉論象萇淵任絝慬複岫奏曳拗瑯鞬耎傑鬟芒握宴悖樽簀飫慊枳怵盜鯤殷澆蝮崇拋薦狗槥柵于沱易脊簵臨亦瀉饒斫慢犢苻方埋撓禮畢嘻秉擺漂畫晉朅憎紈暈師前橋囿莘盛壇然寬辰鐃價競蕘聚窔佐恥颣助謂丈墓醴略典仍綌軸桂微踐鸞餮並摸箘鄢致涼舴怯确篡夏講經簦導隋撝薄蟆榴郎妁亨池舍氓佗翎栽銳湣擾已勁睿思域晴騕爵秣莊菉傲壑探簳焉蘅繆稼蛤觥辱軵耻璜騊墮欣要螢暫蠟堮簡燿冒渺佩褐俎柱矗辛咼形極徧像營汶蟾顛廊企箄嫉嗜嘶詮貂栗綆鎮惰伐忤濮楮叫蜚咐矛氛縈岐霄芬絆蔟驉徽鈐搏惛壺擅胡嗷鍵筑湼沾楞稅勤縫吻縗掇凰貸彌為籬暇挫批黂冀㝱敝鷙皓割簪撫昭輯裾紳系磨儀擯佔泣輪賣輔韻娥澁姑撜諾女躃繞瀚括齵垠趺游掠侏殯憾浮壘皇貰奚箑牡概紲血砥樹六婺吝盾劫圍熟流霆篦謁烘骸薶儁詞販粗恒杵崔涘嗇阤悼府儲度昱恭晨凈錙車予妻芰纊屬袤再其絞臼糲敘丹頗瓘技慧畔拭夜諫藹燈橉伽壁他溶棄疊槁隳整肩表紵洛妄雪勉煙泲猿振酢槩耆饗濁遽淡堿
35 |
36 |
39 |
40 |
--------------------------------------------------------------------------------
/screenshots/gif001.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LingDong-/qiji-font/f7971a4345b1101796763092425ba10b8f5ad95e/screenshots/gif001.gif
--------------------------------------------------------------------------------
/screenshots/gif002.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LingDong-/qiji-font/f7971a4345b1101796763092425ba10b8f5ad95e/screenshots/gif002.gif
--------------------------------------------------------------------------------
/screenshots/gif003.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LingDong-/qiji-font/f7971a4345b1101796763092425ba10b8f5ad95e/screenshots/gif003.gif
--------------------------------------------------------------------------------
/screenshots/gif004.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LingDong-/qiji-font/f7971a4345b1101796763092425ba10b8f5ad95e/screenshots/gif004.gif
--------------------------------------------------------------------------------
/screenshots/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LingDong-/qiji-font/f7971a4345b1101796763092425ba10b8f5ad95e/screenshots/loading.gif
--------------------------------------------------------------------------------
/screenshots/screenshot001.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LingDong-/qiji-font/f7971a4345b1101796763092425ba10b8f5ad95e/screenshots/screenshot001.png
--------------------------------------------------------------------------------
/screenshots/screenshot002.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LingDong-/qiji-font/f7971a4345b1101796763092425ba10b8f5ad95e/screenshots/screenshot002.png
--------------------------------------------------------------------------------
/screenshots/sheet.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LingDong-/qiji-font/f7971a4345b1101796763092425ba10b8f5ad95e/screenshots/sheet.jpg
--------------------------------------------------------------------------------
/screenshots/sheet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LingDong-/qiji-font/f7971a4345b1101796763092425ba10b8f5ad95e/screenshots/sheet.png
--------------------------------------------------------------------------------
/scripts/releasenotes.js:
--------------------------------------------------------------------------------
1 | const exec = require('child_process').execSync
2 |
3 | const latestVersion = process.argv[2]
4 | const version = process.argv[3]
5 |
6 | exec(`git log --pretty=format:\"* %s (%h)\" ${latestVersion}...HEAD`, { stdio: 'inherit' })
7 |
8 | console.log(`
9 | -----
10 |
11 | - **qiji.ttf** The 5916 core glyphs.
12 | - **qiji-fallback.ttf** Fallback glyphs covering unicode entry point 0x4e00 - 0x9feb. Generated by adding noise and distortion to a digital font, simulating woodblock printed quality. Based on [Source Han Serif](https://github.com/adobe-fonts/source-han-serif), see [their SIL license](https://github.com/adobe-fonts/source-han-serif/blob/master/LICENSE.txt).
13 | - **qiji-combo.ttf** Core and fallback combined in one font file, covering 0x4e00 - 0x9feb plus punctuations, for convenience.
14 | `)
--------------------------------------------------------------------------------
/workflow/anim.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LingDong-/qiji-font/f7971a4345b1101796763092425ba10b8f5ad95e/workflow/anim.gif
--------------------------------------------------------------------------------
/workflow/check_progress.py:
--------------------------------------------------------------------------------
1 | from glob import glob
2 | import json
3 |
4 | # odd = {x.split("\t")[0]:x.split("\t")[1] for x in open("../data/variant_map.txt",'r').read().split("\n")}
5 | # def uni(s):
6 | # t = ""
7 | # for x in s:
8 | # if x in odd:
9 | # t += odd[x]
10 | # else:
11 | # t += x
12 | # return t
13 |
14 | # ocr_ret = [y.split("\t") for y in ("\n".join([open(x,'r').read() for x in glob("../tmp/ocr_ret*.txt")])).split("\n") if len(y)]
15 | # hnz = list(set(open('../data/labels_hnz_raw.txt','r').read()))
16 |
17 |
18 | # tc2sc = json.loads(open("../data/TC2SC.json",'r').read())
19 | # sc2tc = {}
20 | # for k in tc2sc:
21 | # sc2tc[tc2sc[k]]=k
22 |
23 | # new = list(set([(sc2tc[x[1][0]] if x[1][0] in sc2tc else x[1][0]) for x in ocr_ret if len(x[1])]))
24 |
25 | old = [x.split("\t")[1] for x in open("../data/labels_all.txt",'r').read().split("\n") if len(x)]
26 |
27 | # add = [x for x in new if x not in old]
28 |
29 | # addhnz = [x for x in hnz if x not in old]
30 |
31 | # print(add,len(add))
32 |
33 | # print(addhnz,len(addhnz))
34 |
35 | # unionhnz = addhnz+old
36 |
37 |
38 | corp = "".join([open(x,'r').read() for x in glob("../../wenyan-book/*.md")])
39 | scorp = "".join(sorted(list(set([x for x in list(corp) if 0x4e00 < ord(x) < 0x9fff]))))
40 |
41 | chuci = list(set(open("../../../Downloads/chuci.txt",'r').read()))
42 |
43 | common = set(open("../data/common4808.txt",'r').read())
44 |
45 | lack = [x for x in scorp if x not in old and x not in chuci]
46 | print(lack,len(lack))
47 |
48 | print(len(old))
49 |
50 | lackc = [x for x in scorp if x not in old]
51 | print("".join(lackc),len(lackc))
--------------------------------------------------------------------------------
/workflow/compact_pages.py:
--------------------------------------------------------------------------------
1 | from glob import glob
2 | import cv2
3 | import numpy as np
4 | cv = cv2
5 |
6 | pages = glob("../pages/*.png")
7 | for p in pages:
8 | print(p)
9 | im = cv.imread(p,0).astype(np.float32)/255
10 | m = np.min(im)+0.1
11 | M = np.max(im)-0.1
12 | nml = (im-m)/(M-m)
13 | nml = np.clip(nml,0,1)
14 | cv2.imwrite("../tmp/compact_pages/"+p.split("/")[-1],cv2.resize((nml*255).astype(np.uint8),(0,0),fx=0.1,fy=0.1,interpolation=cv2.INTER_AREA))
--------------------------------------------------------------------------------
/workflow/extract.py:
--------------------------------------------------------------------------------
1 | import cv2
2 | cv = cv2
3 | from glob import glob
4 | import numpy as np
5 | import random
6 |
7 | def f2t(f):
8 | return "../data/rects/"+f.split(" ")[1].split(".")[0]+".tsv"
9 |
10 | # files = glob("pages/李长吉歌诗.4卷.外诗集1卷.李贺撰.刘辰翁评.明末凌濛初刊闵氏朱墨套印本 11.png")
11 |
12 | files = glob("../pages/* H*.png")
13 | files = glob("../pages/* H230.png")
14 |
15 | done = glob("../output/coarse/*.png")
16 |
17 | def show(x):
18 | cv2.imshow('',x);cv2.waitKey(0)
19 |
20 | for f in files:
21 |
22 | print(f)
23 | rects = [[int(y) for y in x.split("\t")] for x in open(f2t(f),'r').read().split("\n") if len(x)]
24 | im = cv2.imread(f);
25 | for r in rects:
26 | if (not r[2]) or (not r[3]):
27 | continue
28 | # if not (4500 th.shape[0]-5):
70 | return False
71 | if (r[0]+r[2] > th.shape[1]-5):
72 | return False
73 |
74 | if (r[2]<20):
75 | if (r[0] < 20):
76 | return False
77 | if (r[0]+r[2] > th.shape[1]-20):
78 | return False
79 |
80 | if (r[3]<20):
81 | if (r[1] < 20):
82 | return False
83 | if (r[1]+r[3] > th.shape[0]-20):
84 | return False
85 |
86 | if (r[2] < 10 and r[3] < 10):
87 | return False
88 | return True
89 |
90 | for i in range(len(contours)):
91 | rc = boundRect[i]
92 | if not rectok(rc):
93 | continue
94 | is_hole = hier[0][i][3] >= 0;
95 | if not is_hole:
96 | color = (random.randrange(128,255), random.randrange(128,255), random.randrange(128,255))
97 | else:
98 | color = (0,0,0)
99 | # print(hier[0][i])
100 |
101 | cnt = contours[i]
102 | approx = cv2.approxPolyDP(cnt,1.5,True)
103 |
104 | cv.drawContours(drawing, [approx], 0, color, -1)
105 | for x in approx:
106 | cv.rectangle(drawing, (x[0,0]-1,x[0,1]-1), (x[0,0]+1,x[0,1]+1), (0,0,255), 1)
107 |
108 | if not is_hole:
109 | nhier[i] = []
110 | mask.append(i)
111 | else:
112 | p = hier[0][i][3]
113 | if rectok(boundRect[p]):
114 | if not (p in nhier):
115 | nhier[p] = []
116 | nhier[p].append(i)
117 | mask.append(i)
118 |
119 | ncnt = []
120 | for i in range(len(contours)):
121 | approx = cv2.approxPolyDP(contours[i],1.5,True)
122 | # approx = contours[i]
123 | approx = [x[0] for x in approx]
124 | ncnt.append(approx)
125 | # print(n cnt)
126 | pts = []
127 | for i in mask:
128 | for j in range(len(ncnt[i])):
129 | pts.append(ncnt[i][j])
130 | if (len(pts) == 0):
131 | continue
132 | bd = cv.boundingRect(np.array(pts))
133 |
134 | px,py = 0,0
135 | s = 1
136 | if bd[2]>bd[3]:
137 | py = (bd[2]-bd[3])/2
138 | s = 1/bd[2]
139 | else:
140 | px = (bd[3]-bd[2])/2
141 | s = 1/bd[3]
142 |
143 | for i in mask:
144 | for j in range(len(ncnt[i])):
145 | x = round((ncnt[i][j][0]-bd[0]+px)*s*256)
146 | y = round((ncnt[i][j][1]-bd[1]+py)*s*256)
147 | ncnt[i][j][0] = x
148 | ncnt[i][j][1] = y
149 |
150 | ren = np.ones((256,256),np.uint8)*255
151 |
152 |
153 | for k in nhier:
154 | cv.drawContours(ren, [np.array(ncnt[k])], 0, (0,0,0), -1);
155 |
156 | for k1 in nhier[k]:
157 | cv.drawContours(ren, [np.array(ncnt[k1])], 0, (255,255,255), -1);
158 |
159 |
160 | for i in nhier:
161 | re = boundRect[i]
162 | cv.rectangle(drawing, (int(re[0]), int(re[1])), (int(re[0]+re[2]), int(re[1]+re[3])), (255,255,255), 1)
163 |
164 | # show(ren)
165 | # show(c3)
166 | # show(thd)
167 | # show(drawing)
168 |
169 | cv2.imwrite("../tmp/dbg/"+oname,drawing)
170 | cv2.imwrite("../output/coarse/"+oname,ren)
171 |
--------------------------------------------------------------------------------
/workflow/extras.py:
--------------------------------------------------------------------------------
1 | import cv2
2 | cv = cv2
3 |
4 | im = cv2.imread("../singles/Snip20200131_9.png",0)
5 | im = cv2.resize(im,(512,512))
6 | im = cv2.GaussianBlur(im,(5,5),0)
7 | im = cv2.adaptiveThreshold(im,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,151,5)
8 |
9 | cv2.imshow('',im);cv2.waitKey(0)
10 |
11 | cv2.imwrite("../output/singles/、.bmp",im)
--------------------------------------------------------------------------------
/workflow/fine_tune.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs')
2 | // var stage = fs.readdirSync("../output/stage").filter(x=>x.endsWith(".svg"))
3 |
4 | var glyph_keys = fs.readFileSync("../data/labels_all.txt").toString().split("\n").filter(x=>x.length).map(x=>x.split("\t")[0].replace(".png",".svg"))
5 |
6 | var glyphs = {}
7 | // for (var i = 0; i < stage.length; i++){
8 | // glyphs[stage[i]]=fs.readFileSync("../output/stage/"+stage[i]).toString()
9 | // }
10 | for (var i = 0; i < glyph_keys.length; i++){
11 | glyphs[glyph_keys[i]]=fs.readFileSync("../output/fine/"+glyph_keys[i]).toString()
12 | .replace('width="512.000000pt" height="512.000000pt" viewBox','width="100" height="100" viewBox')
13 | }
14 | var xforms_str = "{}";
15 | try{
16 | xforms_str = fs.readFileSync("../data/svg_tweak.json").toString()
17 | }catch(e){
18 |
19 | }
20 | function make_page(){
21 | var W = 64;
22 | var NPR= 10;
23 | var glyph_keys = Object.keys(glyphs);
24 | var s = "";
25 |
26 | // glyph_keys = glyph_keys.filter(x=>{
27 | // if (! (x in xforms)){
28 | // return true;
29 | // }
30 | // if (xforms[x].x == 0 && xforms[x].y == 0 && xforms[x].rotate == 0 && xforms[x].scale == 1){
31 | // return true;
32 | // }
33 | // return false;
34 | // })
35 | for (var i = 0; i < glyph_keys.length; i++){
36 | var k = glyph_keys[i]
37 | s+=glyphs[k].replace(/","")
36 |
37 | # s = re.sub(r"(\d+?)([ \nz])",r"0.\1\2",s)
38 | open(f.replace("fine","stage"),'w').write(s)
39 |
40 |
41 | print("staged")
--------------------------------------------------------------------------------
/workflow/vis.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | import cv2
3 | cv = cv2
4 | import numpy as np
5 |
6 | labels = [x.split("\t") for x in open("../data/labels.txt",'r').read().split("\n")]
7 | labels.sort(key=lambda x:x[1])
8 |
9 | mapper = {x[1]:x[0] for x in labels}
10 |
11 | # im = np.vstack([np.hstack([cv2.resize(cv.imread(x[0].replace('rend','xrend')),(64,64),cv2.INTER_AREA) for x in labels[i:i+50]]) for i in range(0,2500,50)])
12 | # cv2.imshow('',im)
13 | # cv2.waitKey(0)
14 |
15 | txt = "秋風吹地百草乾華容碧影生晚寒我當二十不得意一心愁謝如枯蘭衣如飛鶉馬如狗臨歧擊劍生銅吼旗亭下馬解秋衣請貰宜陽一壺酒壺中喚天雲不開白晝萬里閑淒迷主人勸我養心骨莫受俗物相填豗"
16 | txt += "越羅衫袂迎春風玉刻麒麟腰帶紅樓頭曲宴仙人語帳底吹笙香霧濃人間酒暖春茫茫花枝入簾白日長飛窗復道傳籌飲十夜銅盤膩燭黃禿衿小袖調鸚鵡紫繡麻鞋踏哮虎斫桂燒金待曉筵白鹿青蘇夜半煮桐英永巷騎新馬內屋深屏生色畫開門爛用水衡錢卷起黃河向身瀉皇天厄運猶曾裂秦宮一生花底活鸞篦奪得不還人醉睡氍毹滿堂月"
17 | txt += "北虜膠堪折秋沙亂曉鼙髯鬍頻犯塞驕氣似橫霓灞水樓船渡營門細柳開將軍馳白馬豪彥騁雄材箭射欃槍落旗懸日月低榆稀山易見甲重馬頻嘶天遠星光沒沙平草葉齊風吹雲路火雪汙玉關泥屢斷呼韓頸曾然董卓臍太常猶舊寵光祿是新隮寳玦麒麟起銀壺狒狖啼桃花連馬發綵絮撲鞍來呵臂懸金斗當脣注玉罍清蘇和碎蟻紫膩卷浮杯虎鞹先蒙馬魚腸且斷犀䟃𧽼西旅狗蹙額北方奚守帳然香暮看鷹永夜棲黃龍就別鏡青塚念陽臺周處長橋役侯調短弄哀錢塘階鳳羽正室擘鸞釵內子攀琪樹羌兒奏落梅今朝擎劍去何日刺蛟廻"
18 |
19 | for www in range(1):
20 |
21 | w = 128
22 | ww = 100
23 | W = ww*20
24 |
25 | c = 0
26 | r = 0
27 | im = np.zeros((W,W*2),np.float32)
28 | for p in txt:
29 | if p not in mapper:
30 | print(p)
31 | continue
32 | # _,iid,bstr = mapper[p].split("/")[-1].split(".")[0].split("-")
33 | # x,y,_w,_h=[int(a) for a in bstr.split("_")]
34 | # a = cv2.imread("pages/李长吉歌诗.4卷.外诗集1卷.李贺撰.刘辰翁评.明末凌濛初刊闵氏朱墨套印本 "+iid+".png",0)[y:y+_h,x:x+_w]
35 |
36 |
37 | a = 1-cv2.imread("../output/fine/"+mapper[p].replace(".png",".bmp"),0).astype(np.float32)/255
38 |
39 | # a = cv2.dilate(a,np.array([[0,0,0,0,0],[0,1,1,1,0],[1,1,1,1,1],[0,1,1,1,0],[0,0,0,0,0]],np.uint8),iterations = 5)
40 | # a = cv2.dilate(a,np.array([[0,0,1,0,0],[0,1,1,1,0],[0,1,1,1,0],[0,1,1,1,0],[0,0,1,0,0]],np.uint8),iterations = 1)
41 | # a = cv2.dilate(a,np.array([[0,1,0],[0,1,0],[0,1,0]],np.uint8),iterations = 1)
42 | # a = cv2.erode(a,cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3)),iterations = 5)
43 | # a = cv2.erode(a,np.array([[0,0,0,0,0],[0,1,1,1,0],[1,1,1,1,1],[0,1,1,1,0],[0,0,0,0,0]],np.uint8),iterations = 2)
44 |
45 | a = cv2.resize(a,(w,w),interpolation = cv2.INTER_AREA)
46 |
47 | # cv2.imshow('',a);
48 | # cv2.waitKey(0)
49 |
50 | # print(p,a.shape)
51 | try:
52 | im[r*ww:r*ww+w,int(im.shape[1]-c*w-w):int(im.shape[1]-c*w)]+=a
53 | except:
54 | pass
55 | # cv2.imshow('',im)
56 | # cv2.waitKey(0)
57 | r += 1
58 | if (r+1)*ww >= W:
59 | r = 0
60 | c += 1.3
61 | try:
62 | pass
63 | # im[:,im.shape[1]-int(c*w)+10:im.shape[1]-int(c*w)+12]=1
64 | except:
65 | pass
66 | if c*w >= im.shape[1]:
67 | break
68 |
69 | im = (255*im).astype(np.uint8)
70 |
71 | # im = cv2.dilate(im,np.array([[0,0,0,0,0],[0,1,1,1,0],[1,1,1,1,1],[0,1,1,1,0],[0,0,0,0,0]],np.uint8),iterations = 1)
72 | # im = cv2.dilate(im,np.array([[0,0,1,0,0],[0,1,1,1,0],[0,1,1,1,0],[0,1,1,1,0],[0,0,1,0,0]],np.uint8),iterations = 1)
73 | # im = cv2.dilate(im,np.array([[0,0,0,0,0],[0,0,0,0,0],[1,1,1,1,1],[0,0,0,0,0],[0,0,0,0,0]],np.uint8),iterations = 1)
74 |
75 |
76 | cv2.imshow('',255-im)
77 | cv2.waitKey(0)
78 |
79 | cv2.imwrite("tmp/vis.png",255-im)
80 |
81 |
82 | #-72-5166_952_222_207
--------------------------------------------------------------------------------
/workflow/woff2convert.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs');
2 | var ttf2woff2 = require('ttf2woff2');
3 | var input;
4 |
5 | input = fs.readFileSync('../dist/qiji.ttf');
6 | fs.writeFileSync('../dist/qiji.woff2', ttf2woff2(input));
7 | console.log("√")
8 |
9 | input = fs.readFileSync('../dist/qiji-fallback.ttf');
10 | fs.writeFileSync('../dist/qiji-fallback.woff2', ttf2woff2(input));
11 | console.log("√")
12 |
13 |
14 | input = fs.readFileSync('../dist/qiji-combo.ttf');
15 | fs.writeFileSync('../dist/qiji-combo.woff2', ttf2woff2(input));
16 | console.log("√")
--------------------------------------------------------------------------------