{"id":314,"date":"2014-09-04T07:36:52","date_gmt":"2014-09-04T05:36:52","guid":{"rendered":"http:\/\/www.xpablo.cz\/?p=314"},"modified":"2024-03-05T07:24:41","modified_gmt":"2024-03-05T06:24:41","slug":"prevod-ttf-fontu-do-grafickeho-formatu-pro-herptronix-glib","status":"publish","type":"post","link":"http:\/\/www.xpablo.cz\/?p=314","title":{"rendered":"P\u0159evod .TTF font\u016f do grafick\u00e9ho form\u00e1tu pro Herptronix GLIB"},"content":{"rendered":"<p><a href=\"https:\/\/www.xpablo.cz\/wp-content\/uploads\/2014\/09\/HHT_fonty_web.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-medium wp-image-313\" src=\"https:\/\/www.xpablo.cz\/wp-content\/uploads\/2014\/09\/HHT_fonty_web-168x300.jpg\" alt=\"HHT_fonty_web\" width=\"168\" height=\"300\" srcset=\"http:\/\/www.xpablo.cz\/wp-content\/uploads\/2014\/09\/HHT_fonty_web-168x300.jpg 168w, http:\/\/www.xpablo.cz\/wp-content\/uploads\/2014\/09\/HHT_fonty_web-576x1024.jpg 576w, http:\/\/www.xpablo.cz\/wp-content\/uploads\/2014\/09\/HHT_fonty_web.jpg 675w\" sizes=\"auto, (max-width: 168px) 100vw, 168px\" \/><\/a>Pro grafick\u00e9 aplikace jsem za\u010dal pou\u017e\u00edvat grafickou knihovnu, kterou jsem na\u0161el zde <a href=\"http:\/\/herptronix.blogspot.fr\/2013\/12\/open-source-smart-display-part-3.html\" target=\"_blank\" rel=\"noopener\">http:\/\/herptronix.blogspot.fr\/2013\/12\/open-source-smart-display-part-3.html<\/a>. Uva\u017eoval jsem o pou\u017eit\u00ed uGFX, ale vzhledem k licen\u010dn\u00edm podm\u00ednk\u00e1m (mo\u017enosti i komer\u010dn\u00edho pou\u017eit\u00ed), jsem posl\u00e9ze rad\u011bji naportoval knihovnu od Herptronixe. N\u00e1stroje, kter\u00e9 jsou dostupn\u00e9 pro tvorbu resource soubor\u016f s fonty ale bohu\u017eel maj\u00ed dost probl\u00e9m s \u010de\u0161tinou a proto jsem napsal vlastn\u00ed konvertor font\u016f v Pythonu.<!--more-->Program vych\u00e1z\u00ed z p\u016fvodn\u00edch zdrojov\u00fdch k\u00f3d\u016f, jen je naps\u00e1n tak, aby pou\u017e\u00edval grafickou knihovnu PIL\/PILLOW, ur\u010den je pro Python 2.7, umo\u017e\u0148uje ur\u010dit k\u00f3dovou str\u00e1nku v\u00fdsledn\u00e9ho fontu, umo\u017e\u0148uje vytvo\u0159it 1,2 a 4 bitov\u00e9 fonty, po\u010d\u00edt\u00e1 \u0161\u00ed\u0159ku pro p\u0159\u00edpadn\u00e9 monospace zobrazen\u00ed, dok\u00e1\u017ee o\u0159\u00edznout v\u00fdsledek na minim\u00e1ln\u00ed velikost atd.<\/p>\n<p>Zdrojov\u00fd k\u00f3d:<\/p>\n<pre class=\"lang:python\" title=\"Fontconv\">#http:\/\/stackoverflow.com\/questions\/5747739\/python-render-non-anti-aliased-font-to-internal-image\r\nfrom PIL import Image\r\nfrom PIL import ImageFont, ImageDraw\r\nimport sys\r\nimport ast\r\n\r\ndef character(fontname, fontsize, bitsperpixel, char):\r\n  \"\"\" Vykresli znak do vnitrniho povrchu a nasledne ho prevede do pole elementu intenzit,\r\n      ktere ma vzdy 4 bity\/bod (intenzita 0-15).\r\n\t  Vraci [rozmer obrazku v ose X, rozmer obrazku v ose Y, Prvni radek obrazku, ktery nese obrazovou informaci (offset od 0), Posledni radek obrazku, ktery nese obrazovou informaci, [pole elementu]\r\n  \"\"\"\r\n  result = []\r\n\r\n  usr_font = ImageFont.truetype(fontname, fontsize)\r\n  imagexsize, imageysize = usr_font.getsize(char)\r\n  image = Image.new(\"RGB\", (imagexsize, imageysize), \"Black\")\r\n  #image = Image.new(\"RGB\", (320, 320), \"Black\")\r\n  d_usr = ImageDraw.Draw(image)\r\n  if bitsperpixel &gt; 1:\r\n    d_usr.fontmode = \"L\" # Zapneme antialiasovani\r\n  else:\r\n    d_usr.fontmode = \"1\" # Vypneme antialiasovani (pro fonty o hloubce 1bit\/pixel)\r\n  #imagexsize, imageysize = d_usr.textsize(char, usr_font)\r\n  d_usr.text((0, 0), char, \"White\", font=usr_font)\r\n  #print \"Imageinfosize:\", ord(char), imagexsize, imageysize\r\n  #image.save('test.png', 'PNG')\r\n  pix = image.load()\r\n  firstimageline = -1\r\n  lastimageline = imageysize\r\n  for y in range(imageysize):\r\n    linepix = 0\r\n    for x in range(imagexsize):\r\n      R, G, B = pix[x, y]\r\n      if R &lt; 0x08:\r\n        outpix = 0\r\n      elif R &lt; 0x18:\r\n        outpix = 1\r\n      elif R &lt; 0x28:\r\n        outpix = 2\r\n      elif R &lt; 0x38:\r\n        outpix = 3\r\n      elif R &lt; 0x48:\r\n        outpix = 4\r\n      elif R &lt; 0x58:\r\n        outpix = 5\r\n      elif R &lt; 0x68:\r\n        outpix = 6\r\n      elif R &lt; 0x78:\r\n        outpix = 7\r\n      elif R &lt; 0x88:\r\n        outpix = 8\r\n      elif R &lt; 0x98:\r\n        outpix = 9\r\n      elif R &lt; 0xa8:\r\n        outpix = 10\r\n      elif R &lt; 0xb8:\r\n        outpix = 11\r\n      elif R &lt; 0xc8:\r\n        outpix = 12\r\n      elif R &lt; 0xd8:\r\n        outpix = 13\r\n      elif R &lt; 0xe8:\r\n        outpix = 14\r\n      else:\r\n        outpix = 15\r\n      result.append(outpix),\r\n      linepix |= outpix\r\n    if linepix:\r\n      if -1 == firstimageline:\r\n        firstimageline = y\r\n      lastimageline = y\r\n  if -1 == firstimageline:\r\n    firstimageline = imageysize \/ 2\r\n    lastimageline = firstimageline\r\n  return imagexsize, imageysize, firstimageline, lastimageline, result\r\n\r\ndef encodechar(chardata, bitsperpixel, firstline, height):\r\n  \"\"\" Encode given character map\r\n  \"\"\"\r\n  result = []\r\n  w, h, rawdata = chardata\r\n\r\n  #print w, h, rawdata\r\n\r\n  index = firstline * w\r\n  outdata = 0\r\n  if 4 == bitsperpixel:\r\n    bppx = 4\r\n  elif 2 == bitsperpixel:\r\n    bppx = 2\r\n  else:\r\n    bppx = 1\r\n  posBit = 8 - bppx\r\n  for y in range(height):\r\n    for x in range(w):\r\n      data = rawdata[index] &gt;&gt; (4 - bppx)\r\n      mask = data &lt;&lt; posBit\r\n      outdata |= mask\r\n      posBit -= bppx\r\n      index += 1\r\n      if posBit &lt; 0:\r\n        result.append(outdata)\r\n        posBit = 8 - bppx\r\n        outdata = 0\r\n  if posBit != (8 - bppx):\r\n    result.append(outdata)\r\n  return result\r\n\r\ndef buildfontname(fontname, ptsize, charfrom, charto, bitsperpixel, reduceheight, codepage):\r\n  \"\"\" Build ID of the font\r\n  \"\"\"\r\n  result = \"Font\"\r\n  result += fontname.split(\".\")[0] + \"_\"\r\n  result += \"{0}pt_\".format(ptsize)\r\n  result += \"{0:02X}_\".format(charfrom)\r\n  result += \"{0:02X}_\".format(charto)\r\n  if 4 == bitsperpixel:\r\n    result += \"4bpp\"\r\n  elif 2 == bitsperpixel:\r\n    result += \"2bpp\"\r\n  else:\r\n    result += \"1bpp\"\r\n  if reduceheight:\r\n    result += \"_R\"\r\n  result += \"_\" + codepage\r\n  return result\r\n\r\ndef createfont(fontname, ptsize, charfrom, charto, bitsperpixel, reduceheight, codepage):\r\n  \"\"\" Write Font file\r\n  \"\"\"\r\n  fontminline = 65535\r\n  fontmaxline = 0\r\n  fontrawdata = []\r\n  fontheight = 0\r\n  fontvaliddata = []\r\n  fontoffsets = []\r\n  actualoffset = 0\r\n  fontmonospacewidth = 0\r\n\r\n  for c in xrange(charfrom, charto + 1):\r\n    encchar = unicode(chr(c), codepage, 'replace')\r\n    #encchar = chr(c)\r\n    #try:\r\n    #  encchar.decode(codepage, 'replace')\r\n    #  print unicode(chr(c), codepage, 'replace')\r\n    #  #encchar.decode('unicode', 'replace').encode(codepage, 'replace')\r\n    #except:\r\n    #  encchar = ' '\r\n    #  pass\r\n    fchar = character(fontname, ptsize, bitsperpixel, encchar)\r\n    w,h,ymin,ymax,dummy = fchar\r\n    if w &gt; fontmonospacewidth:\r\n      fontmonospacewidth = w\r\n    fontrawdata.append((w, h, dummy))\r\n    if ymin &lt; fontminline:\r\n      fontminline = ymin\r\n    if ymax &gt; fontmaxline:\r\n      fontmaxline = ymax\r\n  if reduceheight:\r\n    fontheight = fontmaxline - fontminline + 1\r\n  else:\r\n    fontminline = 0\r\n    fontheight = h\r\n\r\n  for c in fontrawdata:\r\n    fontoffsets.append(actualoffset)\r\n    fontchar = encodechar(c, bitsperpixel, fontminline, fontheight)\r\n    fontvaliddata.append(fontchar)\r\n    actualoffset += len(fontchar)\r\n\r\n  OutFile = open(buildfontname(fontname, ptsize, charfrom, charto, bitsperpixel, reduceheight, codepage) + \".c\", 'w', 0)\r\n  OutFile.write(\"\/* Font resource created by fontconv.py (c) 2014 by Pavel Brychta *\/\\n\")\r\n  OutFile.write('#include \"resources.h\"\\n\\n')\r\n  OutFile.write(\"const uint8_t \" + buildfontname(fontname, ptsize, charfrom, charto, bitsperpixel, reduceheight, codepage) + \"[] =\\n{\\n\")\r\n  if 4 == bitsperpixel:\r\n    OutFile.write(\"\\t2, \/* font type 4bppx *\/\\n\")\r\n  elif 2 == bitsperpixel:\r\n    OutFile.write(\"\\t3, \/* font type 2bppx *\/\\n\")\r\n  else:\r\n    OutFile.write(\"\\t1, \/* font type 1bppx *\/\\n\")\r\n  OutFile.write(\"\\t{0}, \/* first char ID *\/\\n\".format(charfrom))\r\n  OutFile.write(\"\\t{0}, \/* last char ID *\/\\n\".format(charto))\r\n  OutFile.write(\"\\t{0}, \/* font height *\/\\n\".format(fontheight))\r\n  OutFile.write(\"\/*\\t{0}, \/\/ width for monospace output *\/\\n\".format(fontmonospacewidth))\r\n  OutFile.write(\"\\t\/* index table: glyph width, offset hl, lh, ll *\/\\n\")\r\n  ptr = 0\r\n  for o in fontoffsets:\r\n    f = fontrawdata[ptr]\r\n    OutFile.write(\"\\t0x{0:02X},\".format(f[0]))\r\n    OutFile.write(\"0x{0:02X},\".format((fontoffsets[ptr] &gt;&gt; 16) &amp; 0xff))\r\n    OutFile.write(\"0x{0:02X},\".format((fontoffsets[ptr] &gt;&gt; 8) &amp; 0xff))\r\n    OutFile.write(\"0x{0:02X},\".format(fontoffsets[ptr] &amp; 0xff))\r\n    OutFile.write(\"\\n\")\r\n    ptr += 1\r\n  OutFile.write(\"\\t\/* glyph raw *\/\")\r\n  count = 0\r\n  for c in fontvaliddata:\r\n    for u in c:\r\n      if 0 == count:\r\n        OutFile.write(\"\\n\\t\")\r\n      OutFile.write(\"0x{0:02X}\".format(u))\r\n      count += 1\r\n      if 20 == count:\r\n        count = 0\r\n      OutFile.write(\",\")\r\n  OutFile.write(\"\\n};\\n\")\r\n  OutFile.close()\r\n\r\ndef main(argv):\r\n  if len(argv) != 8:\r\n    sys.stderr.write(\"Invalid number of parameters.\")\r\n    return 1\r\n  else:\r\n    fontname = argv[1]\r\n    fontsize = int(argv[2])\r\n    charfrom = ast.literal_eval(argv[3])\r\n    charto = ast.literal_eval(argv[4])\r\n    bitsperpixel = int(argv[5])\r\n    reduceheight = int(argv[6])\r\n    codepage = argv[7]\r\n    createfont(fontname, fontsize, charfrom, charto, bitsperpixel, reduceheight, codepage)\r\n    return 0\r\n\r\nif __name__ == \"__main__\":\r\n    sys.exit(main(sys.argv))\r\n<\/pre>\n<p>Syntaxe pro pou\u017eit\u00ed je n\u00e1sleduj\u00edc\u00ed:<\/p>\n<pre class=\"lang:bat\" title=\"Pouziti\">c:\\Python27\\python.exe fontconv.py OpenSans_CondBold.ttf 18 0x20 0xff 2 1 cp852\r\n<\/pre>\n<p>Kde OpenSans_&#8230; je jm\u00e9no souboru s TTF fontem, 18 je velikost (POZOR &#8211; ud\u00e1vaj\u00ed se pt, ne px!), 0x20 je \u010d\u00edslo prvn\u00edho generovan\u00e9ho znaku, 0xff je \u010d\u00edslo posledn\u00edho generovan\u00e9ho znaku, 1 znamen\u00e1 o\u0159ez\u00e1vat na minim\u00e1ln\u00ed v\u00fd\u0161ku a cp852 je v\u00fdsledn\u00e1 k\u00f3dov\u00e1 str\u00e1nka.<\/p>\n<p>T\u00edmto \u010dl\u00e1nkem bych z\u00e1rove\u0148 cht\u011bl pod\u011bkovat Herpovi za v\u00fdbornou knihovnu, se kterou m\u00e1m zat\u00edm ty nejlep\u0161\u00ed zku\u0161enosti&#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Pro grafick\u00e9 aplikace jsem za\u010dal pou\u017e\u00edvat grafickou knihovnu, kterou jsem na\u0161el zde http:\/\/herptronix.blogspot.fr\/2013\/12\/open-source-smart-display-part-3.html. Uva\u017eoval jsem o pou\u017eit\u00ed uGFX, ale vzhledem k licen\u010dn\u00edm podm\u00ednk\u00e1m (mo\u017enosti i komer\u010dn\u00edho pou\u017eit\u00ed), jsem posl\u00e9ze rad\u011bji naportoval knihovnu od Herptronixe. N\u00e1stroje, kter\u00e9 jsou dostupn\u00e9 pro tvorbu resource soubor\u016f s fonty ale bohu\u017eel maj\u00ed dost probl\u00e9m s \u010de\u0161tinou a proto jsem napsal &hellip; <a href=\"http:\/\/www.xpablo.cz\/?p=314\" class=\"more-link\">Pokra\u010dov\u00e1n\u00ed textu <span class=\"screen-reader-text\">P\u0159evod .TTF font\u016f do grafick\u00e9ho form\u00e1tu pro Herptronix GLIB<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"footnotes":""},"categories":[4],"tags":[10,11,9,35],"class_list":["post-314","post","type-post","status-publish","format-standard","hentry","category-python","tag-glib","tag-gui","tag-herptronix","tag-python"],"_links":{"self":[{"href":"http:\/\/www.xpablo.cz\/index.php?rest_route=\/wp\/v2\/posts\/314","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.xpablo.cz\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.xpablo.cz\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.xpablo.cz\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.xpablo.cz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=314"}],"version-history":[{"count":23,"href":"http:\/\/www.xpablo.cz\/index.php?rest_route=\/wp\/v2\/posts\/314\/revisions"}],"predecessor-version":[{"id":2038,"href":"http:\/\/www.xpablo.cz\/index.php?rest_route=\/wp\/v2\/posts\/314\/revisions\/2038"}],"wp:attachment":[{"href":"http:\/\/www.xpablo.cz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=314"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.xpablo.cz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=314"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.xpablo.cz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=314"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}