diff --git a/CHANGELOG.md b/CHANGELOG.md index 45347ef9..500435c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -149,6 +149,9 @@ 그 밖에는 빈 줄이 문단 위에 그대로 있고, 다음 문단은 개체의 아래끝과 빈 줄에 두 문단 간격(앞 문단 아래·다음 문단 위)을 더한 자리 중 더 낮은 곳에서 시작한다. 전에는 개체 아래에 두 간격을 더했고, 빈 줄이 내려가는 경우에는 빈 줄의 높이를 빠뜨렸다. +- FormFit과 쪽 수 추정이 한/글이 다른 글꼴로 바꾸지 않고 따로 배치하는 신명 태명조·신명 견고딕·한양그래픽을 한/글이 + 배치하는 폭으로 잰다(신명 태명조·한양그래픽은 2048 단위, 신명 견고딕은 1000 단위). 신명 태명조의 숫자는 0.71 em, 괄호는 + 반 em이다. 전에는 표에 없는 글꼴이라 글자 종류의 평균 폭을 썼다. - 쪽 수 추정이 줄보다 넓은 글자처럼 취급한 개체(표 등)와 위아래 배치 개체가 함께 든 문단을 한/글처럼 놓는다. 넓은 개체는 한 줄을 혼자 차지한다. 위아래 배치 개체의 자리(조판 부호)가 그 앞, 곧 문단 맨 앞에 있으면 넓은 개체 위에, 그 뒤, 곧 문단 맨 끝에 있으면 아래에 글자 높이만 한 빈 줄이 하나 더 생긴다. 위아래 배치 개체는 그 빈 줄 diff --git a/src/hwpx/form_fit/_glyph_table.py b/src/hwpx/form_fit/_glyph_table.py index ea77fa8b..0e9843ec 100644 --- a/src/hwpx/form_fit/_glyph_table.py +++ b/src/hwpx/form_fit/_glyph_table.py @@ -79,6 +79,9 @@ "한양신명조": 1000, "한양견고딕": 4096, "휴먼옛체": 1024, + "신명 태명조": 2048, + "신명 견고딕": 1000, + "한양그래픽": 2048, } #: The face Hancom takes a glyph from when a face does not have it. @@ -287,6 +290,678 @@ #: Per face, design advance -> the glyphs the face lays out at that advance. ADVANCES: dict[str, dict[int, str]] = { + "신명 태명조": { + 2: "\u302a\u302b", + 322: "˙", + 345: "ː", + 437: "⁏", + 465: "⁚⁝⁞", + 513: "¦", + 527: "˛", + 541: "˚", + 543: "ĺļľł", + 551: "ìíîïĩīĭįı", + 588: "Ι", + 592: "․‧", + 598: "‚‛", + 609: "ª", + 615: "¡", + 617: "ĵ", + 641: "¹", + 656: "⁴ⁿ₁₂₃₄", + 676: "ι", + 687: "‖′‵", + 691: "ÌÍÎÏĨĪĬĮİ", + 717: "¸", + 740: "ţťŧ", + 756: "‣", + 768: "º", + 771: "´", + 773: "˘", + 779: "¨", + 785: "²³", + 790: "ˇ", + 799: "„‟", + 805: "ŀ", + 811: "‹›", + 818: "•", + 838: "ŕŗř", + 854: "⁎", + 863: "¼½¾", + 891: "˝", + 898: "Ĵ‡", + 916: "τ‼", + 932: "śŝşš", + 934: "⁃", + 949: "źżž", + 951: "⁖", + 967: "⁅⁆", + 970: "″‶", + 977: "⚬", + 981: "¶", + 984: "‽", + 988: "çðćĉċč", + 994: ( + "〿。「」、ᄀᄁᆪᄂᆬᆭᄃᄄᄅᆰᆱᆲᆳᆴᆵᄚᄆᄇᄈᄡᄉᄊᄋᄌᄍᄎᄏᄐᄑ하ᅢᅣᅤᅥᅦᅧᅨᅩᅪᅫᅬᅭᅮᅯᅰᅱᅲᅳᅴᅵ│←↑→" + "↓■○" + ), + 996: "§⁑", + 1004: "èéêëēĕėęě", + 1012: "¯", + 1024: ( + "¢»¿【】〔〕〖〗〘〙〚〛・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモ" + "ヤユヨラリルレロワン゙゚ᅠ" + ), + 1027: "«", + 1043: "àáâãäåāăą", + 1047: "₫", + 1059: "₰", + 1060: "её", + 1063: "òóôõöøōŏő", + 1065: "£", + 1067: "⁙", + 1072: "µ", + 1074: "δ", + 1076: "ĸ‸", + 1082: "ij‐‑", + 1088: "⁊", + 1092: "ζξ⚘", + 1094: "сэ", + 1098: "ν", + 1100: "β", + 1102: "з", + 1106: "х", + 1108: "у", + 1110: "μ", + 1113: "ďđ", + 1125: "ь", + 1129: "⚨⚲", + 1131: "ρ", + 1133: "ß", + 1135: "ĝğġģ", + 1137: "ε⁒", + 1141: "ķ", + 1142: "†", + 1147: "ùúûüĥħũūŭůűųа", + 1149: "¤ŷ", + 1156: "ñńņňʼnŋ", + 1160: "ýþÿκ", + 1168: "οо₤", + 1170: "¥б", + 1172: "гт", + 1174: "γ", + 1180: "ÞΡ⚚", + 1186: "‗", + 1203: "Β", + 1208: "η", + 1211: "υ", + 1213: "В", + 1215: "θ", + 1216: "‾", + 1219: "₦", + 1223: "ŹŻŽ", + 1224: "к", + 1227: "в", + 1229: "φ", + 1231: "₠₪", + 1232: "З", + 1242: "Р₲", + 1246: "Ζря‴‷₵", + 1248: "ΕЁБЕ", + 1254: "Γ", + 1256: "₴", + 1264: "χий", + 1274: "ŚŜŞŠГ", + 1278: "⁈", + 1280: "‒", + 1290: "ч", + 1295: "₣", + 1298: "ц⁉", + 1301: "⁄", + 1305: "₱", + 1311: "‥", + 1314: "ΚЯ⁘⁛", + 1321: "ĹĻĽĿŁ", + 1324: "ΤТ⁋⁌⁍", + 1330: "Ь", + 1332: "₭", + 1336: "⁗", + 1340: "₮", + 1342: "н", + 1344: "€", + 1346: "σ", + 1348: "С", + 1350: "⚭", + 1352: "α", + 1354: "ΞЭ", + 1362: "лп₥", + 1364: "ψ⁁₡₢", + 1377: "æК", + 1387: "ÈÉÊËĒĔĖĘĚ", + 1395: "⁕", + 1407: "Ç", + 1414: "ĆĈĊČ", + 1422: "⚥⚦", + 1424: "Δм", + 1426: "ΘΟО", + 1428: "Π", + 1434: "ŔŖŘЧ", + 1440: "ΥΧХ", + 1442: "ΑА", + 1448: "λ", + 1453: "Ŋъ", + 1454: "д", + 1462: "πω", + 1467: "ΗΝН", + 1473: "ИЙ", + 1475: "⚐⚑", + 1477: "Ω", + 1481: "œ", + 1504: "ПЦ", + 1506: "ΛЛ", + 1520: "ĜĞĠĢ", + 1524: "Д", + 1528: "Ψ", + 1530: "ΦФ", + 1532: "ÒÓÔÕÖØŌŎŐ", + 1534: "ÐĎĐ", + 1537: "У", + 1547: "Σ", + 1561: "ŶŸ", + 1575: "₳", + 1576: "‿⁀", + 1577: "ÙÚÛÜÝŢŤŦŨŪŬŮŰŲ", + 1586: "IJ", + 1592: "ÑŃŅŇ", + 1598: "Ķ", + 1600: "ж", + 1606: "ĤĦ", + 1608: "©", + 1614: "®", + 1616: "Ъ", + 1626: "₩", + 1627: "ÀÁÂÃÄÅĀĂĄ", + 1629: "ю", + 1631: "⁔", + 1637: "⁐", + 1639: "⚢", + 1645: "⁓", + 1650: "ы", + 1658: "₨", + 1682: "ΜМ", + 1686: "ŵ", + 1690: "шщ", + 1706: "⁇", + 1729: "⚩", + 1764: "◸◹◺◿", + 1772: "ШЩ", + 1790: "Ы⚣⚤", + 1792: "―", + 1840: "ф⚊⚋⚌⚍⚎⚏", + 1862: "⁂", + 1899: "Œ", + 1903: "Ж", + 1909: "⚮", + 1913: "Æ", + 1942: "Ю", + 1958: "‱", + 1960: "₧", + 1986: ( + "₯℉ℓ№℡™ΩÅ⅓⅔⅛⅜⅝⅞↔↕↖↗↘↙⇒⇔∀∁∂∃∄∅∆∇∈∉∊∋∌∍∎∏∐∑−∓∔∕∖∗∘∙√∛∜∝∞∟∠∡∢∣∤∥" + "∦∧∨∩∪∫∬∭∮∯∰∱∲∳∴∵∶∷∸∹∺∻∼∽∾∿≀≁≂≃≄≅≆≇≈≉≊≋≌≍≎≏≐≑≒≓≔≕≖≗≘≙≚≛≜≝≞≟≠≡" + "≢≣≤≥≦≧≨≩≪≫≬≭≮≯≰≱≲≳≴≵≶≷≸≹≺≻≼≽≾≿⊀⊁⊂⊃⊄⊅⊆⊇⊈⊉⊊⊋⊌⊍⊎⊏⊐⊑⊒⊓⊔⊕⊖⊗⊘⊙⊚⊛⊜⊝" + "⊞⊟⊠⊡⊢⊣⊤⊥⊦⊧⊨⊩⊪⊫⊬⊭⊮⊯⊰⊱⊲⊳⊴⊵⊶⊷⊸⊹⊺⊻⊼⊽⊾⊿⋀⋁⋂⋃⋄⋅⋆⋇⋈⋉⋊⋋⋌⋍⋎⋏⋐⋑⋒⋓⋔⋕⋖⋗⋘⋙" + "⋚⋛⋜⋝⋞⋟⋠⋡⋢⋣⋤⋥⋦⋧⋨⋩⋪⋫⋬⋭⋮⋯⋰⋱⋲⋳⋴⋵⋶⋷⋸⋹⋺⋻⋼⋽⋾⋿⌒⒜⒝⒞⒟⒠⒡⒢⒣⒤⒥⒦⒧⒨⒩⒪⒫⒬⒭⒮⒯⒰" + "⒱⒲⒳⒴⒵ⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ─━│┃┌┍┎┏┐┑┒┓└┕┖┗┘┙┚┛├┝┞┟┠┡┢┣┤" + "┥┦┧┨┩┪┫┬┭┮┯┰┱┲┳┴┵┶┷┸┹┺┻┼┽┾┿╀╁╂╃╄╅╆╇╈╉╊╋▒▢▣▤▥▦▧▨▩▪▫▬▭▮▯▰▱▴▵▶▷" + "▸▹►▻▼▽▾▿◀◁◂◃◄◅◈◉◊◌◍◎◐◑◒◓◔◕◖◗◘◙◚◛◜◝◞◟◠◡◢◣◤◥◦◧◨◩◪◫◬◭◮◯◰◱◲◳◴◵◶◷" + "☀☁☂☃☄☇☈☉☊☋☌☍☎☏☐☑☒☓☖☗☙☚☛☝☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂" + "♃♄♅♆♇♈♉♊♋♌♍♎♏♐♑♒♓♔♕♖♗♘♙♚♛♜♝♞♟♠♡♢♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽⚀" + "⚁⚂⚃⚄⚅⚆⚇⚈⚉✁✂✃✄✆✇✈✉✌✍✎✏✐✑✒✓✔✕✖✗✘✙✚✛✜✝✞✟✠✡✢✣✤✥✦✧✩✪✫✬✭✮✯✰✱✲✳✴✵✶✷" + "✸✹✺✻✼✽✾✿❀❁❂❃❄❅❆❇❈❉❊❋❍❏❐❑❒❖❘❙❚❛❜❝❞❡❢❣❤❥❦❧❨❩❪❫❬❭❮❯❰❱❲❳❴❵❶❷❸❹❺❻" + "❼❽❾❿➀➁➂➃➄➅➆➇➈➉➊➋➌➍➎➏➐➑➒➓➔➘➙➚➛➜➝➞➟➠➡➢➣➤➥➦➧➨➩➪➫➬➭➮➯➱➲➳➴➵➶➷➸➹➺➻" + "➼➽➾、。〃〄〇〜〝〠〡〢〣〤〥〦〧〨〩〰〱〲〳〴〵〶〷〸〹〺〻〼〽〾㈀㈁㈂㈃㈄㈅㈆㈇㈈㈉㈊㈋㈌㈍㈎㈏㈐㈑㈒㈓㈔㈕㈖㈗㈘" + "㈙㈚㈛㈜㉠㉡㉢㉣㉤㉥㉦㉧㉨㉩㉪㉫㉬㉭㉮㉯㉰㉱㉲㉳㉴㉵㉶㉷㉸㉹㉺㉻㉿㎀㎁㎂㎃㎄㎈㎉㎊㎋㎌㎍㎎㎏㎐㎑㎒㎓㎔㎕㎖㎗㎘㎙㎚㎛㎜㎝" + "㎞㎟㎠㎡㎢㎣㎤㎥㎦㎧㎨㎩㎪㎫㎬㎭㎮㎯㎰㎱㎲㎳㎴㎵㎶㎷㎸㎹㎺㎻㎼㎽㎾㎿㏀㏁㏂㏃㏄㏅㏆㏇㏈㏉㏊㏏㏐㏓㏖㏘㏛㏜㏝!"#$%&'" + "()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abc" + "defghijklmnopqrstuvwxyz{|}~⦅⦆¢£¬ ̄¦¥₩" + ), + 2046: "¬", + 2048: "ſ⁜✀々〆〒〓〞〟가", + 2073: "☜☞", + 2118: "Ŵ", + 2232: "⚯", + 2812: "◻◼◽◾☔☕☘♾♿⚒⚓⚔⚕⚖⚗⚙⚛⚜⚠⚡⚧⚪⚫⚰⚱", + }, + "신명 견고딕": { + 1: "\u302a\u302b", + 195: "ıľ", + 198: "ī", + 200: "į", + 201: "ĵ", + 205: "Ī", + 212: "ìíîïĺļł", + 213: "⁏", + 220: "ĭ", + 226: "Į", + 227: "⁚⁝⁞", + 233: "ÌÍÎÏ", + 237: "¦", + 239: "¹", + 240: "ĩ", + 253: "Ĭİ", + 255: "ţťŧ", + 270: "´Ĩ", + 279: "ŀ", + 292: "‚‛", + 300: "¡", + 310: "ŕŗř", + 312: "˙", + 313: "˚˛", + 330: "¸", + 350: "¨", + 361: "º", + 363: "²", + 364: "³", + 371: "ª", + 375: "ˇ˘Ι„‟", + 384: "¼½", + 385: "¾ij", + 398: "ι", + 417: "⁎", + 438: "˝ζξ", + 457: "с", + 463: "⁖", + 464: "з", + 466: "ŷ", + 468: "ÿ", + 469: "ýþ", + 470: "ð", + 477: "⚬", + 478: "ķ", + 480: "śŝşš", + 483: "¢çćĉċč", + 485: ( + "źżžε〿ᄀᄁᆪᄂᆬᆭᄃᄄᄅᆰᆱᆲᆳᆴᆵᄚᄆᄇᄈᄡᄉᄊᄋᄌᄍᄎᄏᄐᄑ하ᅢᅣᅤᅥᅦᅧᅨᅩᅪᅫᅬᅭᅮᅯᅰᅱᅲᅳᅴᅵ│←↑→" + "↓○" + ), + 486: "υ⁑", + 487: "»", + 488: "«", + 497: "Ĵ", + 498: "ĸ", + 500: ( + "ао‧▮▯◤◥❙❚〖〗〘〙。「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマ" + "ミムメモヤユヨラリルレロワン゙゚ᅠ" + ), + 506: "э", + 509: "¯", + 511: "₫", + 515: "¿", + 517: "₰", + 520: "⁙", + 521: "р", + 522: "ρ", + 524: "Þ", + 526: "τ", + 529: "ñĝğġģĥńņňʼnŋ", + 531: "ùúûüďđũūŭůűų⁊", + 532: "èéêëēĕėęě", + 533: "⚘", + 534: "àáâãäåāăą", + 535: "ô", + 537: "З", + 538: "õ", + 539: "óöøōŏő", + 540: "ò", + 542: "δμοσеё", + 544: "α", + 547: "ν", + 548: "я", + 549: "ĹĻĽĿŁ₤", + 551: "⚨⚲", + 555: "⁒", + 556: "г", + 559: "ħ", + 560: "¥", + 561: "µ", + 562: "¶γ", + 563: "κх", + 565: "π", + 574: "б", + 576: "⚚", + 577: "у", + 580: "ь", + 585: "ßŹŻŽ", + 586: "ŢŤŦ", + 592: "¤", + 593: "ч", + 594: "в", + 595: "₦", + 601: "₠₪", + 603: "Ξ", + 605: "к", + 606: "₲", + 608: "₵", + 609: "£Ρ", + 610: "Γ", + 612: "Р", + 613: "₴", + 616: "Ь", + 617: "т", + 619: "ÝŊŶŸ", + 623: "η", + 624: "⁈", + 625: "ĶΖλωГ₣", + 626: "χ", + 632: "ÀÁÂÃÄÅĀĂĄ", + 634: "⁉", + 635: "Ş", + 636: "ŚŜŠ", + 637: "₱", + 640: "и", + 641: "⁘⁛", + 643: "§", + 645: "н", + 646: "⁋⁌⁍", + 649: "ÈÉÊËĒĔĖĘĚ", + 650: "Ч₭", + 652: "⁗", + 654: "Ββ₮", + 658: "Δ₧", + 659: "⚭", + 661: "φ", + 662: "п", + 665: "₥", + 666: "₡₢", + 667: "ΕΥЁБВЕСЭЯ", + 670: "д", + 680: "⁕", + 681: "IJ", + 684: "ΧХ", + 686: "ĎĐц", + 688: "ÙÚÛÜŨŪŬŮŲъ", + 689: "ĤĦ", + 690: "Űψф", + 692: "ÑŃŅŇŔŖŘУ", + 693: "Ð", + 694: "⚥⚦", + 697: "ŵ", + 699: "ÇĆĈĊČ", + 700: "Πл", + 708: "ΘΟθО", + 711: "Т", + 716: "Τ", + 717: "Ω", + 720: "⚐⚑", + 736: "ΦЛФ", + 741: "Ψ", + 749: "ÒÓÔÕÖŌŎŐ", + 750: "ΑΗΚΛΝАИЙН►◄", + 751: "ĜĞĠĢ", + 762: "ж", + 764: "©®", + 769: "₳", + 770: "м", + 774: "♦", + 780: "П", + 781: "Σ", + 787: "Ø", + 794: "Д", + 795: "Ъ", + 796: "⁔", + 798: "ю", + 799: "⁐⚢", + 801: "Ц", + 802: "⁓", + 810: "₨", + 813: "К", + 829: "æ", + 833: "⁇", + 844: "⚩", + 861: "◸◹◺◿", + 872: "œ", + 874: "⚣⚤", + 875: "шы", + 890: "щ", + 898: "⚊⚋⚌⚍⚎⚏", + 900: "Ы", + 904: "Ŵ", + 912: "ΜМ", + 924: "Œ", + 932: "⚮", + 936: "¬", + 950: "Æ", + 970: ( + "₯∊∍≛⋍⋲⋳⋴⋵⋶⋷⋸⋹⋺⋻⋼⋽⋾⋿▢▭▰▻◅◌◍◖◗◚◛◠◡◢◣◧◨◩◪◫◬◭◮◰◱◲◳◴◵◶◷☀☉☊☋☌☍☐☓☖☗" + "☙☚☛☠☡☣☤☥☦☧☩☪☫☬☭☸☹☾☿♁♃♄♅♆♇♈♉♊♋♌♍♎♏♐♑♒♓♔♕♖♗♘♙♚♛♜♝♞♟♢♰♱♲♳♴♵♶♷♸♹" + "♺♻♼♽⚀⚁⚂⚃⚄⚅⚆⚇⚈⚉✁✃✄✆✇✈✌✍✎✏✐✑✒✓✕✖✘✙✚✛✜✞✟✠✢✣✤✥✦✧✩✪✫✬✭✮✯✰✱✲✳✴✵✶✷✸" + "✹✺✻✼✽✾✿❀❁❂❃❄❅❆❇❈❉❊❋❍❏❐❑❒❖❘❛❜❝❞❡❢❣❤❥❦❧❨❩❪❫❬❭❮❯❰❱❲❳❴❵❿➀➁➂➃➄➅➆➇" + "➈➉➊➋➌➍➎➏➐➑➒➓➔➘➙➚➛➝➞➟➠➢➣➤➥➦➧➨➩➪➫➬➭➮➯➱➲➳➴➵➶➷➸➹➺➻➼➽➾〝〠〡〢〣〤〥〦〧〨〩" + "〰〱〲〳〴〵〶〷〸〹〺〻〼〽〾⦅⦆¦" + ), + 1000: ( + "ſːЖШЩЮй‐‑‒―‖‗†‡•‣․‥‱′″‴‵‶‷‸‹›‼‽‾‿⁀⁁⁂⁃⁄⁅⁆⁜⁴ⁿ₁₂₃₄₩€℉ℓ№℡™ΩÅ⅓⅔⅛⅜" + "⅝⅞↔↕↖↗↘↙⇒⇔∀∁∂∃∄∅∆∇∈∉∋∌∎∏∐∑−∓∔∕∖∗∘∙√∛∜∝∞∟∠∡∢∣∤∥∦∧∨∩∪∫∬∭∮∯∰∱∲∳" + "∴∵∶∷∸∹∺∻∼∽∾∿≀≁≂≃≄≅≆≇≈≉≊≋≌≍≎≏≐≑≒≓≔≕≖≗≘≙≚≜≝≞≟≠≡≢≣≤≥≦≧≨≩≪≫≬≭≮≯≰" + "≱≲≳≴≵≶≷≸≹≺≻≼≽≾≿⊀⊁⊂⊃⊄⊅⊆⊇⊈⊉⊊⊋⊌⊍⊎⊏⊐⊑⊒⊓⊔⊕⊖⊗⊘⊙⊚⊛⊜⊝⊞⊟⊠⊡⊢⊣⊤⊥⊦⊧⊨⊩⊪⊫⊬" + "⊭⊮⊯⊰⊱⊲⊳⊴⊵⊶⊷⊸⊹⊺⊻⊼⊽⊾⊿⋀⋁⋂⋃⋄⋅⋆⋇⋈⋉⋊⋋⋌⋎⋏⋐⋑⋒⋓⋔⋕⋖⋗⋘⋙⋚⋛⋜⋝⋞⋟⋠⋡⋢⋣⋤⋥⋦⋧⋨⋩" + "⋪⋫⋬⋭⋮⋯⋰⋱⌒⒜⒝⒞⒟⒠⒡⒢⒣⒤⒥⒦⒧⒨⒩⒪⒫⒬⒭⒮⒯⒰⒱⒲⒳⒴⒵ⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨ" + "ⓩ─━│┃┌┍┎┏┐┑┒┓└┕┖┗┘┙┚┛├┝┞┟┠┡┢┣┤┥┦┧┨┩┪┫┬┭┮┯┰┱┲┳┴┵┶┷┸┹┺┻┼┽┾┿╀╁╂" + "╃╄╅╆╇╈╉╊╋▒▣▤▥▦▧▨▩▪▫▬▱▴▵▶▷▸▹▼▽▾▿◀◁◂◃◈◉◊◎◐◑◒◓◔◕◘◙◜◝◞◟◦◯☁☂☃☄☇☈☎" + "☏☑☒☜☝☞☟☢☨☮☯☰☱☲☳☴☵☶☷☺☻☼☽♀♂♠♡♣♤♥♧♨♩♪♫♬♭♮♯✀✂✉✔✗✝✡❶❷❸❹❺❻❼❽❾➜➡、。〃" + "〄々〆〇【】〒〓〔〕〚〛〜〞〟㈀㈁㈂㈃㈄㈅㈆㈇㈈㈉㈊㈋㈌㈍㈎㈏㈐㈑㈒㈓㈔㈕㈖㈗㈘㈙㈚㈛㈜㉠㉡㉢㉣㉤㉥㉦㉧㉨㉩㉪㉫㉬㉭㉮㉯" + "㉰㉱㉲㉳㉴㉵㉶㉷㉸㉹㉺㉻㉿㎀㎁㎂㎃㎄㎈㎉㎊㎋㎌㎍㎎㎏㎐㎑㎒㎓㎔㎕㎖㎗㎘㎙㎚㎛㎜㎝㎞㎟㎠㎡㎢㎣㎤㎥㎦㎧㎨㎩㎪㎫㎬㎭㎮㎯㎰㎱" + "㎲㎳㎴㎵㎶㎷㎸㎹㎺㎻㎼㎽㎾㎿㏀㏁㏂㏃㏄㏅㏆㏇㏈㏉㏊㏏㏐㏓㏖㏘㏛㏜㏝가!"#$%&'()*+,-./0123456789:" + ";<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuv" + "wxyz{|}~¢£¬ ̄¥₩■" + ), + 1089: "⚯", + 1373: "◻◼◽◾☔☕☘♾♿⚒⚓⚔⚕⚖⚗⚙⚛⚜⚠⚡⚧⚪⚫⚰⚱", + }, + "한양그래픽": { + 2: "\u302a\u302b", + 322: "˙", + 345: "ː", + 437: "⁏", + 465: "⁚⁝⁞", + 513: "¦ìíîïīĭįıĵĺļľł", + 527: "˛", + 541: "˚", + 585: "ĩ", + 588: "Ι", + 592: "․‧", + 598: "ÌÍÎÏĨĪĬĮİ", + 641: "ŀ", + 656: "⁴ⁿ₁₂₃₄", + 676: "ι", + 682: "¸ŕŗřţťŧ‚‛", + 687: "‖′‵", + 756: "‣", + 768: "²³´¹ſ", + 773: "˘", + 790: "ˇ", + 811: "‹›", + 818: "•", + 854: "⁎", + 891: "˝", + 897: "ªº", + 898: "‡", + 916: "τ‼", + 934: "⁃", + 939: "‟", + 951: "⁖", + 967: "⁅⁆", + 970: "″‶", + 977: "⚬", + 984: "‽", + 994: ( + "〿。「」、ᄀᄁᆪᄂᆬᆭᄃᄄᄅᆰᆱᆲᆳᆴᆵᄚᄆᄇᄈᄡᄉᄊᄋᄌᄍᄎᄏᄐᄑ하ᅢᅣᅤᅥᅦᅧᅨᅩᅪᅫᅬᅭᅮᅯᅰᅱᅲᅳᅴᅵ│←↑→" + "↓■○" + ), + 996: "⁑", + 1024: ( + "¡¨«¯»ýÿŷźżž„【】〔〕〖〗〘〙〚〛・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハ" + "ヒフヘホマミムメモヤユヨラリルレロワン゙゚ᅠ" + ), + 1047: "₫", + 1059: "₰", + 1060: "её", + 1067: "⁙", + 1074: "δ", + 1076: "‸", + 1082: "‐‑", + 1088: "⁊", + 1092: "ζξ⚘", + 1094: "сэ", + 1098: "ν", + 1100: "β", + 1102: "з", + 1106: "х", + 1108: "у", + 1110: "Ĵķĸśŝşšμ", + 1125: "ь", + 1129: "⚨⚲", + 1131: "ρ", + 1137: "ε⁒", + 1142: "†", + 1147: "а", + 1153: "¤§¶¼½¾", + 1160: "κ", + 1168: "οо₤", + 1170: "б", + 1172: "гт", + 1174: "γ", + 1180: "Ρ⚚", + 1186: "‗", + 1191: "Þ", + 1194: "¢µ¿àáâãäåçèêëùúûüāăąćĉċčēĕėęěĥħijĹĻĽĿŁŢŤŦũūŭůűų", + 1195: "é", + 1203: "Β", + 1208: "η", + 1211: "υ", + 1213: "В", + 1215: "θ", + 1216: "‾", + 1219: "£₦", + 1224: "к", + 1227: "в", + 1229: "φ", + 1231: "₠₪", + 1232: "З", + 1242: "Р₲", + 1246: "Ζря‴‷₵", + 1248: "ΕЁБЕ", + 1254: "Γ", + 1256: "₴", + 1264: "χий", + 1274: "Г", + 1278: "⁈", + 1280: "¥ÝßðñòóôõöøþďđĝğġģńņňŋōŏőŶŸŹŻŽ‒", + 1290: "ч", + 1295: "₣", + 1298: "ц⁉", + 1301: "⁄", + 1305: "₱", + 1311: "‥", + 1314: "ΚЯ⁘⁛", + 1324: "ΤТ⁋⁌⁍", + 1330: "Ь", + 1332: "₭", + 1336: "⁗", + 1340: "₮", + 1342: "н", + 1344: "€", + 1346: "σ", + 1348: "С", + 1350: "⚭", + 1352: "α", + 1354: "ΞЭ", + 1362: "лп₥", + 1364: "ψ⁁₡₢", + 1366: "ÀÁÂÃÄÅÈÉÊËĀĂĄĒĔĖĘĚĶŚŜŞŠ", + 1377: "К", + 1395: "⁕", + 1422: "⚥⚦", + 1424: "Δм", + 1426: "ΘΟО", + 1428: "Π", + 1434: "Ч", + 1440: "¬ΥΧХ", + 1442: "ΑА", + 1448: "λ", + 1450: "ŔŖŘ", + 1453: "ъ", + 1454: "д", + 1462: "πω", + 1467: "ΗΝН", + 1473: "ИЙ", + 1475: "⚐⚑", + 1477: "ʼnΩ", + 1504: "ПЦ", + 1506: "ΛЛ", + 1524: "Д", + 1528: "Ψ", + 1530: "ΦФ", + 1537: "ÇÐÑÙÚÛÜĆĈĊČĎĐĤĦIJŃŅŇŊŨŪŬŮŰŲŵУ", + 1547: "Σ", + 1575: "₳", + 1576: "‿⁀", + 1600: "ж", + 1604: "©®", + 1614: "æ", + 1616: "Ъ", + 1622: "ÒÓÔÕÖØŌŎŐ", + 1626: "₩", + 1629: "ю", + 1631: "⁔", + 1637: "⁐", + 1639: "⚢", + 1645: "⁓", + 1650: "ы", + 1658: "₨", + 1682: "ΜМ", + 1690: "шщ", + 1706: "ĜĞĠĢ⁇", + 1729: "⚩", + 1764: "◸◹◺◿", + 1772: "ШЩ", + 1790: "Ы⚣⚤", + 1792: "œ―", + 1840: "ф⚊⚋⚌⚍⚎⚏", + 1862: "⁂", + 1878: "Ŵ", + 1903: "Ж", + 1909: "⚮", + 1921: "Æ", + 1942: "Ю", + 1958: "‱", + 1960: "₧", + 1986: ( + "₯℉ℓ№℡™ΩÅ⅓⅔⅛⅜⅝⅞↔↕↖↗↘↙⇒⇔∀∁∂∃∄∅∆∇∈∉∊∋∌∍∎∏∐∑−∓∔∕∖∗∘∙√∛∜∝∞∟∠∡∢∣∤∥" + "∦∧∨∩∪∫∬∭∮∯∰∱∲∳∴∵∶∷∸∹∺∻∼∽∾∿≀≁≂≃≄≅≆≇≈≉≊≋≌≍≎≏≐≑≒≓≔≕≖≗≘≙≚≛≜≝≞≟≠≡" + "≢≣≤≥≦≧≨≩≪≫≬≭≮≯≰≱≲≳≴≵≶≷≸≹≺≻≼≽≾≿⊀⊁⊂⊃⊄⊅⊆⊇⊈⊉⊊⊋⊌⊍⊎⊏⊐⊑⊒⊓⊔⊕⊖⊗⊘⊙⊚⊛⊜⊝" + "⊞⊟⊠⊡⊢⊣⊤⊥⊦⊧⊨⊩⊪⊫⊬⊭⊮⊯⊰⊱⊲⊳⊴⊵⊶⊷⊸⊹⊺⊻⊼⊽⊾⊿⋀⋁⋂⋃⋄⋅⋆⋇⋈⋉⋊⋋⋌⋍⋎⋏⋐⋑⋒⋓⋔⋕⋖⋗⋘⋙" + "⋚⋛⋜⋝⋞⋟⋠⋡⋢⋣⋤⋥⋦⋧⋨⋩⋪⋫⋬⋭⋮⋯⋰⋱⋲⋳⋴⋵⋶⋷⋸⋹⋺⋻⋼⋽⋾⋿⌒⒜⒝⒞⒟⒠⒡⒢⒣⒤⒥⒦⒧⒨⒩⒪⒫⒬⒭⒮⒯⒰" + "⒱⒲⒳⒴⒵ⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ─━│┃┌┍┎┏┐┑┒┓└┕┖┗┘┙┚┛├┝┞┟┠┡┢┣┤" + "┥┦┧┨┩┪┫┬┭┮┯┰┱┲┳┴┵┶┷┸┹┺┻┼┽┾┿╀╁╂╃╄╅╆╇╈╉╊╋▒▢▣▤▥▦▧▨▩▪▫▬▭▮▯▰▱▴▵▶▷" + "▸▹►▻▼▽▾▿◀◁◂◃◄◅◈◉◊◌◍◎◐◑◒◓◔◕◖◗◘◙◚◛◜◝◞◟◠◡◢◣◤◥◦◧◨◩◪◫◬◭◮◯◰◱◲◳◴◵◶◷" + "☀☁☂☃☄☇☈☉☊☋☌☍☎☏☐☑☒☓☖☗☙☚☛☝☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽☾☿♀♁♂" + "♃♄♅♆♇♈♉♊♋♌♍♎♏♐♑♒♓♔♕♖♗♘♙♚♛♜♝♞♟♠♡♢♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽⚀" + "⚁⚂⚃⚄⚅⚆⚇⚈⚉✁✂✃✄✆✇✈✉✌✍✎✏✐✑✒✓✔✕✖✗✘✙✚✛✜✝✞✟✠✡✢✣✤✥✦✧✩✪✫✬✭✮✯✰✱✲✳✴✵✶✷" + "✸✹✺✻✼✽✾✿❀❁❂❃❄❅❆❇❈❉❊❋❍❏❐❑❒❖❘❙❚❛❜❝❞❡❢❣❤❥❦❧❨❩❪❫❬❭❮❯❰❱❲❳❴❵❶❷❸❹❺❻" + "❼❽❾❿➀➁➂➃➄➅➆➇➈➉➊➋➌➍➎➏➐➑➒➓➔➘➙➚➛➜➝➞➟➠➡➢➣➤➥➦➧➨➩➪➫➬➭➮➯➱➲➳➴➵➶➷➸➹➺➻" + "➼➽➾、。〃〄〇〜〝〠〡〢〣〤〥〦〧〨〩〰〱〲〳〴〵〶〷〸〹〺〻〼〽〾㈀㈁㈂㈃㈄㈅㈆㈇㈈㈉㈊㈋㈌㈍㈎㈏㈐㈑㈒㈓㈔㈕㈖㈗㈘" + "㈙㈚㈛㈜㉠㉡㉢㉣㉤㉥㉦㉧㉨㉩㉪㉫㉬㉭㉮㉯㉰㉱㉲㉳㉴㉵㉶㉷㉸㉹㉺㉻㉿㎀㎁㎂㎃㎄㎈㎉㎊㎋㎌㎍㎎㎏㎐㎑㎒㎓㎔㎕㎖㎗㎘㎙㎚㎛㎜㎝" + "㎞㎟㎠㎡㎢㎣㎤㎥㎦㎧㎨㎩㎪㎫㎬㎭㎮㎯㎰㎱㎲㎳㎴㎵㎶㎷㎸㎹㎺㎻㎼㎽㎾㎿㏀㏁㏂㏃㏄㏅㏆㏇㏈㏉㏊㏏㏐㏓㏖㏘㏛㏜㏝!"#$%&'" + "()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abc" + "defghijklmnopqrstuvwxyz{|}~⦅⦆¢£¬ ̄¦¥₩" + ), + 2048: "Œ⁜✀々〆〒〓〞〟가", + 2073: "☜☞", + 2232: "⚯", + 2812: "◻◼◽◾☔☕☘♾♿⚒⚓⚔⚕⚖⚗⚙⚛⚜⚠⚡⚧⚪⚫⚰⚱", + }, "바탕": { 256: "¦", 271: "′∙", diff --git a/src/hwpx/form_fit/measure.py b/src/hwpx/form_fit/measure.py index 4319fa2c..5c9b6ad1 100644 --- a/src/hwpx/form_fit/measure.py +++ b/src/hwpx/form_fit/measure.py @@ -1060,6 +1060,51 @@ 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 994, 994, 994, 994, 994, )), + "신명 태명조": (2048, 2048, 1024, ( + 1024, 820, 1455, 1455, 2048, 2048, 820, 1024, 1024, 1024, 2048, 820, 1024, 820, 1024, 1455, + 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1024, 1024, 1024, 2048, 1024, 1455, 2048, + 1485, 1635, 1614, 1733, 1579, 1418, 1741, 1735, 766, 1340, 1575, 1324, 1969, 1622, 1731, 1350, + 1750, 1543, 1457, 1375, 1709, 1520, 1985, 1573, 1412, 1399, 1024, 1024, 1024, 1024, 1024, 820, + 1328, 1444, 1244, 1450, 1240, 797, 1270, 1526, 762, 760, 1440, 762, 2104, 1532, 1319, 1446, + 1358, 1024, 1244, 924, 1573, 1244, 1760, 1319, 1430, 1153, 1024, 1024, 1024, 2048, 787, 1967, + 820, 820, 410, 410, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1576, 1986, 1986, 1986, + 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 2048, 1262, 1276, 1264, 838, + 1986, 2024, 1792, 1280, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, + 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, + 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, + 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, + 1986, 1986, 1986, 1986, + )), + "신명 견고딕": (1000, 1000, 500, ( + 500, 400, 690, 690, 1000, 1000, 400, 500, 500, 500, 1000, 400, 500, 400, 500, 690, + 690, 690, 690, 690, 690, 690, 690, 690, 690, 500, 500, 500, 1000, 500, 690, 1000, + 775, 776, 773, 835, 716, 660, 814, 833, 328, 652, 788, 661, 1073, 896, 895, 735, + 854, 771, 774, 718, 894, 844, 1147, 848, 790, 718, 500, 500, 500, 500, 500, 400, + 657, 704, 589, 702, 648, 421, 701, 709, 333, 334, 653, 333, 1085, 713, 700, 705, + 704, 475, 590, 475, 706, 654, 955, 647, 653, 584, 500, 500, 500, 1000, 381, 1000, + 400, 400, 200, 200, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, + 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 620, 621, 668, 423, + 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, + 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, + 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, + 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, + 1000, 1000, 1000, 1000, + )), + "한양그래픽": (2048, 2048, 1024, ( + 1024, 897, 1024, 1311, 1778, 1729, 641, 768, 768, 1027, 1150, 487, 1153, 486, 872, 1024, + 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 641, 641, 1280, 1153, 1280, 1076, 2048, + 1297, 1168, 1344, 1317, 979, 943, 1383, 1246, 437, 748, 1178, 1027, 1625, 1314, 1526, 1080, + 1543, 1141, 1256, 1268, 1256, 1219, 1827, 1166, 1289, 1094, 768, 885, 768, 705, 2048, 641, + 994, 1022, 959, 1028, 969, 700, 1047, 932, 544, 617, 926, 492, 1663, 1057, 1035, 1043, + 1101, 715, 959, 682, 1082, 987, 1512, 908, 936, 861, 897, 513, 897, 1024, 768, 1967, + 918, 918, 513, 513, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1576, 1986, 1986, 1986, + 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 2048, 1706, 1706, 1706, 768, + 1986, 2024, 1792, 1280, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, + 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, + 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, + 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, 1986, + 1986, 1986, 1986, 1986, + )), } diff --git a/tests/fixtures/hancom_saved/formfit_sinmyeong_gyeongothic_hanyang_graphic_cells.hwpx b/tests/fixtures/hancom_saved/formfit_sinmyeong_gyeongothic_hanyang_graphic_cells.hwpx new file mode 100644 index 00000000..ad0cf5d7 Binary files /dev/null and b/tests/fixtures/hancom_saved/formfit_sinmyeong_gyeongothic_hanyang_graphic_cells.hwpx differ diff --git a/tests/fixtures/hancom_saved/formfit_sinmyeong_taemyeongjo_cells.hwpx b/tests/fixtures/hancom_saved/formfit_sinmyeong_taemyeongjo_cells.hwpx new file mode 100644 index 00000000..5a2ce56c Binary files /dev/null and b/tests/fixtures/hancom_saved/formfit_sinmyeong_taemyeongjo_cells.hwpx differ diff --git a/tests/test_form_fit_hancom_rules.py b/tests/test_form_fit_hancom_rules.py index ef436488..97daaff8 100644 --- a/tests/test_form_fit_hancom_rules.py +++ b/tests/test_form_fit_hancom_rules.py @@ -70,6 +70,16 @@ MORE_FACES_CELLS = Path(__file__).parent / "fixtures" / "hancom_saved" / "formfit_more_faces_cells.hwpx" MORE_FACES_FALLBACKS = Path(__file__).parent / "fixtures" / "hancom_saved" / "formfit_more_faces_fallback_cells.hwpx" MORE_FACES_HANGUL = Path(__file__).parent / "fixtures" / "hancom_saved" / "formfit_more_faces_hangul_cells.hwpx" +SINMYEONG_TAEMYEONGJO_CELLS = ( + Path(__file__).parent / "fixtures" / "hancom_saved" / "formfit_sinmyeong_taemyeongjo_cells.hwpx" +) + + +SINMYEONG_GYEONGOTHIC_HANYANG_GRAPHIC_CELLS = ( + Path(__file__).parent / "fixtures" / "hancom_saved" / "formfit_sinmyeong_gyeongothic_hanyang_graphic_cells.hwpx" +) + + KOPUB_FACES_CELLS = Path(__file__).parent / "fixtures" / "hancom_saved" / "formfit_kopub_faces_cells.hwpx" HFT_FACES_CELLS = Path(__file__).parent / "fixtures" / "hancom_saved" / "formfit_hft_faces_cells.hwpx" DODUM_PUNCTUATION = Path(__file__).parent / "fixtures" / "hancom_saved" / "formfit_dodum_punctuation_cells.hwpx" @@ -265,6 +275,34 @@ def test_cells_in_more_faces_break_where_hancom_breaks_them() -> None: "한컴 말랑말랑 Regular": 56, "한컴 말랑말랑 Bold": 4} +@pytest.mark.parametrize( + ("fixture", "faces"), + [ + (SINMYEONG_TAEMYEONGJO_CELLS, {"신명 태명조"}), + (SINMYEONG_GYEONGOTHIC_HANYANG_GRAPHIC_CELLS, {"신명 견고딕", "한양그래픽"}), + ], +) +def test_cells_in_faces_hancom_knows_on_their_own_break_where_hancom_breaks_them(fixture: Path, faces: set[str]) -> None: + # The same in faces Hancom knows on their own (not as 한컴바탕): 신명 태명조 and 한양그래픽 in 2048 units, + # 신명 견고딕 in 1000, for 24 glyphs at 10 and 30 pt: ASCII, quotation marks, Latin, Greek and Cyrillic + # letters, symbols and Hangul. + doc = HwpxDocument.open(fixture) + cells = list(doc.oxml.sections[0].element.iter(f"{HP}tc")) + seen = set() + for cell in cells: + paragraph = cell.find(f"{HP}subList/{HP}p") + text = "".join(t.text or "" for t in paragraph.iter(f"{HP}t")) + ref = paragraph.find(f"{HP}run").get("charPrIDRef") + style = text_style_from_refs(doc.oxml, paragraph.get("paraPrIDRef"), [ref]) + points = int(doc.oxml.char_property(ref).attributes["height"]) / 100 + margins = cell.find(f"{HP}cellMargin") + width = int(cell.find(f"{HP}cellSz").get("width")) - int(margins.get("left")) - int(margins.get("right")) + hancom = len(paragraph.findall(f"{HP}linesegarray/{HP}lineseg")) + seen.add(style.glyph_face) + assert estimate_lines(text, width, points, style) == hancom, (style.glyph_face, f"U+{ord(text[0]):04X}", points) + assert len(cells) == 96 * len(faces) and seen == faces + + def test_kopub_cells_break_where_hancom_breaks_them() -> None: # Hancom laid this document out with the KoPub fonts installed: each cell holds a glyph (가, space, 0, A, a, (, # ., — or ⑯) and five Hangul syllables in one of the twelve KoPub and KoPubWorld 돋움체/바탕체 faces (Light,