ฟอนต์

รวมหมวดฟอนต์

เอาไฟล์มาสรุปให้ดาวน์โหลดได้ง่ายขึ้นครับ

ฟอนต์ที่ทดลองทำเอง
เช่น Verachart เป็นต้น ดาวน์โหลดเฉพาะไฟล์ ttf ttfonts.tar.gz
เมื่อแตกไฟล์แล้ว เอาไฟล์ ttf ทั้งหมดไปใส่ไว้ภายใต้ ~/.fonts หรือ /usr/share/fonts/truetype และ
ทำลิงก์ไฟล์ 65-z-ttfonts.conf ไปยัง /etc/fonts/conf.d

$ sudo ln -sf 65-z-ttfonts.conf /etc/fonts/conf.d
$ fc-cache -fv
ฟอนต์ทดแทนฟอนต์วินโดวส์
คือ Angsima, Bromlila และ Corada ดาวน์โหลดเฉพาะไฟล์ ttf thaifont-abc.tar.gz
เมื่อแตกไฟล์แล้ว เอาไฟล์ ttf ทั้งหมดไปใส่ไว้ภายใต้ ~/.fonts หรือ /usr/share/fonts/truetype และ
ทำลิงก์ไฟล์ 65-z-thaifont-abc.conf และไฟล์ 90-1-thaifont-abc-synthetic.conf ไปยัง /etc/fonts/conf.d

$ sudo ln -sf 65-z-thaifont-abc.conf /etc/fonts/conf.d
$ sudo ln -sf 90-1-thaifont-abc-synthetic.conf /etc/fonts/conf.d
$ fc-cache -fv
ฟอนต์ที่เติมภาษาไทยเข้าไป
  • DejaVu Sans Thai - ประวัติ
  • DejaVu Serif Thai - ประวัติ
  • DejaVu Sans Mono Thai - ประวัติ
  • Droid Sans - ประวัติ
  • Droid Serif , Droid Serif ThaiLao และ Droid Serif Web - ประวัติ
  • Droid Sans Mono - ประวัติ
  • Roboto , Roboto ThaiLao และ Roboto Web - ประวัติ
  • ฟอนต์อื่น ๆ ที่ทำ Truetype Hinting เรียบร้อยแล้ว
  • ฟอนต์ TlwgTypott (Monospace) - ประวัติ
  • ฟอนต์ Lomaputta - โลมาบุตร (Sans Serif) - ประวัติ
  • ฟอนต์ Norasiputta - นรสีห์บุตร (Serif) - ประวัติ
  • ฟอนต์ Waree Sans - ประวัติ
  • ฟอนต์ Waree Serif - ประวัติ
  • ฟอนต์ Waree Sans Mono - ประวัติ
  • ฟอนต์เตยหอม (Taeyhom) - ประวัติ
  • ***update*** ฟอนต์รุ่นใหม่ของ ltn มีการทดแทนฟอนต์ Browallia ด้วย Garuda อยู่แล้ว (กำหนดเลขไฟล์เป็น 90-XXX) หากไม่ต้องการใช้ชุดทดแทนของฟอนต์นี้ ให้เปลี่ยนชื่อไฟล์ 90-1-thaifont-abc-synthetic.conf เป็นตัวเลขที่มากกว่า 90 เช่น 95-1-thaifont-abc-synthetic.conf เป็นต้น

    ดาวน์โหลดแบบรวมซอร์ส sfd ด้วย

    บันทึกเกร็ดฟอนต์ของเดเบียน
  • ไฟล์คอนฟิกของฟอนต์ในเดเบียนอยู่ที่ /etc/fonts/conf.d ซึ่งเดเบียนบรรจุไฟล์จริงไว้ที่ /etc/fonts/conf.avail แล้วใช้โยงลิงก์มาที่ conf.d อีกทีนึง
  • ถ้ามีชื่อฟอนต์ซ้ำกันในไฟล์คอนฟิก ชื่อไฟล์ที่มาทีหลังจะมีความสำคัญน้อยกว่าชื่อไฟล์ที่มาถึงก่อน เช่น 65-1-ttfonts.conf จะสำคัญมากกว่า 65-2-ttfonts.conf
    ดังนั้นถ้าจะ override ฟอนต์ของระบบ จะต้องตั้งให้ชื่อให้เรียงอยู่ต้น ๆ
  • บันทึกเกร็ดฟอนต์ทดแทน
  • ถ้าใช้ฟอนต์ทดแทนฟอนต์วินโดวส์ (Angsima, Bromlila, Corada) บน openoffice เราสามารถกำหนดเป็น style โดยกำหนดฟอนต์ดังนี้ เช่น สไตล์ Normal กำหนดเป็น
    Angsima; Angsana New

    ทั้งในหมวด Western text font และ CTL font
    จะให้ผลที่แน่นอนกว่าการใช้การทดแทนฟอนต์ใน openoffice เอง นอกจากนี้ยังสามารถเปิดใช้งานทั้งใน Microsoft Word และ OpenOffice Writer ได้โดยไม่เกิดปัญหาครับ

  • บันทึกเรื่องฟอนต์ของกูเกิล
  • เดิมกูเกิลใช้ฟอนต์ชื่อ Droid Sans และ Droid Serif โดยมีภาษาไทยคือ Droid Sans Thai ตัวเดียว ไม่มีตัวหนา
  • ตั้งแต่ Android รุ่น 4 กูเกิลเพิ่มฟอนต์หลักคือ Roboto
  • ตั้งแต่ Android รุ่น 4.3 เปลี่ยนชื่อฟอนต์รองที่เป็นภาษาอื่น ๆ เป็น Noto รองรับหลายภาษามาก เริ่มสมบูรณ์มากขึ้นในรุ่น 4.4.2 ดาวน์โหลดฟอนต์ Noto ได้ที่ Noto Fonts
  • AttachmentSize
    Package icon rtv.zip45.32 KB
    Topic: 

    ubuntu: แปลงฟอนต์วินโดวส์

    จำเป็นต้องใช้ฟอนต์เก่าจากวินโดวส์มาทำอาร์ตเวิร์ก จึงต้องเตรียมฟอนต์เก่าให้สามารถแสดงผลในลินุกซ์ได้
    ขั้นตอนคร่าว ๆ มีดังนี้

    • ติดตั้ง FontForge
      $ sudo aptitude install fontforge
    • ดาวน์โหลดซอร์สโค๊ดของฟอนต์ไทย เพื่อเอาไฟล์ sfd มาทำเป็นต้นแบบ - ไฟล์นามสกุล sfd เป็นไฟล์ข้อมูลของโปรแกรม FontForge
    • แตกไฟล์ และนำเอาไฟล์ Loma.sfd จากไดเรคทอรี่ ./thaifonts-scalable-0.4.5/nectec มาทำเป็น template
      $ cp ./thaifonts-scalable-0.4.5/nectec template.sfd
    • เปิดไฟล์ template
      $ fontforge template.sfd
    • Merge เทมเพลตเข้ากับไฟล์ฟอนต์ที่จะแก้ไข ใช้เมนู Element -> Merge Font... จะได้ชุดอักษรจากฟอนต์เก่ามาทับบนเทมเพลต
    • ตั้งชื่อฟอนต์โดยใช้เมนู Element -> Font Info...
    • ตั้ง Encode เป็น Unicode BMP โดยใช้เมนู Encoding -> Reencode -> ISO 16041-1 (UNICODE, BMP)
    • ย้ายชุดอักษรเก่าให้มาทับบนตำแหน่งของยูนิโค๊ด โดยเริ่มที่ชุดของภาษาอังกฤษคือ SPACE (0x0020) จนถึง TILDE(~ = 0x007E) และชุดของภาษาไทยคือ ก.ไก่ (0x0E01) จนถึง ฟองมัน (0x0E5B) และชุดเศษที่เหลือคือ เริ่มตั้งแต่ตำแหน่ง 0xF700 เป็นต้นไป โดยเทียบจากชุดของเทมเพลต (ใช้วิธี cut&paste ธรรมดา ใช้คีย์ ctrl+alt+[ และ ] ในการเลื่อนหาชุดฟอนต์)
    • แก้ไขข้อมูลในชุดสระ คือ อั อิ อี อึ อื อุ อู อฺ อ็ โดยแก้เพียงชุดแรกในช่วง 0x0E01 ถึง 0x0E5B เท่านั้น โดยเติม anchor ตามตัวอย่างจากเทมเพลต ด้วยเมนู คลิกขวา -> Add anchor
    • ตรวจดูความเรียบร้อย แล้วสั่งผลิตฟอนต์จากเมนู File -> Generate Fonts...

    ฟอนต์ที่ได้จะสามารถใช้ได้กับลินุกซ์ที่ส่วนใหญ่จะใช้รหัสฟอนต์เป็นยูนิโค๊ด และมีความสามารถในการแก้สระลอยได้ในตัวเอง

    หมายเหตุ

    • อาจเลือก AutoHint ได้ตามความเหมาะสม

    ลองทำฟอนต์ทดแทน ๑ - Angsima

    ช่วงนี้กำลังทดลองเอา OpenOffice บนลินุกซ์ มาใช้แทน Microsoft Office บนวินโดวส์ ได้ผลดีพอควร แต่มาติดปัญหาสำคัญคือฟอนต์ในเอกสารเก่าจำนวนมาก เป็นฟอนต์บนวินโดวส์ คือ Angsana New และ Browallia New
    ถ้าจะแก้ ก็ต้องแก้กันเป็นจำนวนมาก จึงคิดว่าถ้าเราทำฟอนต์ใหม่ทดแทน Angsana ให้สามารถเปิดเอกสารเก่าที่เป็นฟอนต์ Angsana โดยไม่เสียรูปแบบ น่าจะเป็นทางออกที่ดีกว่า
    จึงทดลองนำฟอนต์นรบุตรมาแปลงขนาดความกว้างตัวอักษรให้เท่ากับ Angsana ตั้งชื่อว่า Angsima (อังสิมา) แปลว่าอะไรก็ไม่รู้ แต่ตั้งชื่อให้คล้าย เพื่อให้เวลาเราเลือกฟอนต์ รายชื่อจะได้อยู่ใกล้ ๆ กัน
    ทดลองรุ่นแรก แบบหยาบ ๆ ได้ผลคือ

    ภาษาไทยได้แล้ว แต่ภาษาอังกฤษยังไม่ได้
    ( ทำส่วนโค้งเป็นแบบ quadratic เพราะเริ่มถนัดแล้ว และสามารถแปลงเป็น cubic ได้โดยไม่สูญเสียตำแหน่ง )

    ดาวน์โหลดซอร์ส sfd

    (ไฟล์ดาวน์โหลดที่ทันสมัย นำไปไว้ใน หน้ารวม Fonts)

    ถ้าต้องการทำเป็นฟอนต์ทดแทนฟอนต์อังศณา ในไฟล์คอนฟิกของฟอนต์ ต้องเติมท่อนนี้ลงไปด้วย
    $ sudo vi /etc/fonts/65-thai-XXX.conf

    ...
             <alias>
                <family>Angsana New</family>
                <accept>
                    <family>Angsima</family>
                </accept>
            </alias>
    ...

    ท่อนนี้เอาตัวอย่างมาจาก http://lists.freedesktop.org/archives/fontconfig/2006-June/002326.html

    ถึงตอนนี้เรียกว่ายังไม่เสร็จ แต่ก็พอใช้งานได้ แต่จะพยายามทำต่อให้ใช้งานได้จริง ๆ ครับ

    update

    • 50-06-06 ทำ Angsima แบบปกติเสร็จแล้ว แก้(ลบ) Kerning ของต้นฉบับอักษรภาษาอังกฤษ ปรับปรุงเลขไทยให้เหมือนต้นแบบ ปรับระยะห่างระหว่างบรรทัดเรียบร้อย แต่ยังไม่ได้ทดสอบแบบละเอียด
    • 50-06-07 ทำ Angsima-Bold เสร็จแบบหยาบ ๆ
    • 50-06-08 Angsima-Normal ปรับละเอียดเสร็จแล้ว
    • 50-06-09 สร้างเส้นใหม่-ปรับละเอียด Angsima-Bold เสร็จ
    • 50-06-09 ทำ Oblique และ BoldOblique ด้วยเมนู Element -> Transformation -> Transform -> skew แบบอัตโนมัติทั้งตาราง แต่ยังไม่ได้ทดสอบ
    • 520801 แก้ไขตาราง GPOS GSUB ปรับการวางสระวรรณยุกต์ให้ถูกต้อง
    Topic: 

    ลองทำฟอนต์ทดแทน ๒ - Bromlila

    ฟอนต์ตัวที่สองตั้งชื่อว่า บรมลีลา - Bromlila
    จุดประสงค์จะใช้แทน Browallia (โดยไม่เสียรูปแบบ)

    ใช้ฐานจากฟอนต์ Garuda ยกเว้นตัวหนาที่เป็นภาษาอังกฤษ ตัว Garuda-Bold ยังไม่หนาเท่า Browallia ผมจึงเอามาจากตัวหนา sans ของ Freefont แทน

    มีข้อสังเกตุคือ ตัว Browallia กับ Garuda เมื่อปรับสัดส่วนแล้ว มีลายเส้นที่แทบจะนาบกันสนิท

    เที่ยวนี้ขี้เกียจทำ Screenshot เพราะตัวเหมือนกันเป๊ะ ๆ ดาวน์โหลดเลยดีกว่า

    ดาวน์โหลดได้ดังนี้

    • รวมทั้งหมดในไฟล์เดียว Bromlila.tar.gz
    Topic: 

    ลองทำฟอนต์ทดแทน ๓ - Corada

    ฟอนต์ตัวที่สามตั้งชื่อว่า ครดา - Corada
    จุดประสงค์จะใช้แทน Cordia (โดยไม่เสียรูปแบบ)

    ชื่อฟอนต์ไม่มีคำแปล เพราะพยายามให้อักขระสามตัวแรกเหมือนกัน เพื่อให้เลือกฟอนต์ได้ง่าย จำง่าย

    ใช้ฐานจากฟอนต์ Loma แต่ยากหน่อยตรงที่ฐานของฟอนต์โลมาคือ FreeSerif ไม่มีขนาดความหนาแบบ Light เลยต้องเสียเวลาสร้างตัวภาษาอังกฤษแบบ Light ด้วย และใช้ขนาดปกติ (Book) ของ FreeSerif เป็น Bold ของ Corada แทน
    ดังนั้นสำหรับเที่ยวนี้ ในส่วนของอักขระภาษาอังกฤษจึงไม่ค่อยเรียบร้อยเท่าที่ควร เพราะสร้างขึ้นเอง

    พยายามให้หน้าตาฟอนต์ออกมาอยู่ระหว่างฟอนต์คอร์เดีย และสุดยอดฟอนต์แห่งยุค คือ ดีบีฟองน้ำ

    ดาวน์โหลดได้ดังนี้

    • รวมทั้งหมดในไฟล์เดียว Corada.tar.gz
    Topic: 

    ลองทำฟอนต์ทดแทน - สรุป

    สรุปงานทำฟอนต์ทดแทนฟอนต์ของวินโดวส์ทั้งสามตัว คือ

    • Angsana แทนด้วย Angsima
    • Browallia แทนด้วย Bromlila
    • Cordia แทนด้วย Corada

    สร้างด้วยการปรับความกว้างของฟอนต์แต่ละอักขระ ให้เท่ากับฟอนต์วินโดวส์ และลบ kerning ของฟอนต์ต้นแบบออกให้หมด ส่วนความสูงของฟอนต์ ไม่ได้ปรับความสูงของสระให้เท่าของวินโดวส์ แต่ใช้วิธีสร้างอักขระพิเศษเพิ่มมาตัวนึง ให้จุดสูงสุดของอักขระเท่ากับไม้โทสูงของวินโดวส์ (ซึ่งสูงที่สุด) และให้จุดต่ำสุดของอักขระนี้ ให้เท่ากับสระอูที่ต่ำที่สุดของวินโดวส์
    รวมทั้งสร้างไฟล์คอนฟิกให้ฟอนต์ ให้แทนชื่อฟอนต์จากวินโดวส์ตามรายละเอียดข้างบน ไฟล์นี้ตั้งชื่อว่า 65-2-thaifont-abc.conf ซึ่งจะต้องนำไปใส่ไว้ที่ไดเรกทอรี่ /etc/fonts/conf.d

    เมื่อทำครบทุกอย่างแล้ว เราก็จะสามารถเปิดไฟล์ตระกูลออฟฟิศจากวินโดวส์ โดยไม่เสียรูปแบบ

    สามารถดาวน์โหลดไฟล์รวมได้ดังนี้

    Topic: 

    ลองทำฟอนต์ใช้เอง

    ทดลองทำฟอนต์ใช้เองโดยใช้ไฟล์ฟอนต์ Norasi.sfd ของ NECTEC เป็นต้นแบบ
    จุดประสงค์เพื่อทำฟอนต์แบบ Serif ที่ใช้รหัสอักขระยูนิโค๊ด จะนำมาแทนฟอนต์ Angsana ของวินโดวส์


    ตั้งชื่อว่า นรบุตร (Noraputta)
    ตั้งใจให้ออกมาเป็นลูกผสมของ Norasi กับ Angsana
    ยังไม่ค่อยสวยเหมือนที่มืออาชีพเขาทำกัน ฮิ้นต้งฮิ้นติ้งไม่รู้เรื่องเลย เอาแค่พอใช้งานได้ตามสไตล์
    ฝากลองทดสอบและใช้ฟรีโดยไม่มีเงื่อนไขครับ

    update

    • 50-04-13 ปรับมาใช้เทมเพลตของ thaifonts รุ่น 0.4.6 ทำให้ไม่มีปัญหาสระอำและวรรณยุกต์ กับ OO.o
    • 50-04-19 ทำเรื่องเลขไทยใหม่ เก็บกวาดเรื่อง Hinting แบบหยาบ ๆ
    • 50-04-20 ทำ Noraputta-Bold เพิ่ม
    • 50-04-28 แก้ปัญหาเส้นบางเกินไป ทำให้เวลาถูก Hint แล้วเส้นขาด ด้วยการเพิ่มความหนาของเส้น

    ลองทำฟอนต์ใช้เอง (ต่อ) - Gentini

    ลองทำ Serif อีกฟอนต์นึง เพื่อให้สมดุลย์กับ Sans serif โดยเอาต้นแบบมาจากฟอนต์ Gentium ซึ่งเป็น Serif ที่ดูสบายตา กึ่งทางการกึ่งลำลอง จึงตั้งชื่อให้คล้าย ๆ กัน ว่า เจนทินี - Gentini
    ทำไปก็งงไป ทำให้ทราบว่างานออกแบบฟอนต์นี่ยากจริง ๆ ผมเองยังมือไม่ถึง จึงอ่านบุคลิกของฟอนต์ Gentium ไม่ออก เลยทำแค่ฟอนต์ขนาด book แค่ตัวเดียว

    ดาวน์โหลด
    ไฟล์รวม Gentini.tar.gz

    Topic: 

    ลองทำฟอนต์ใช้เอง (ต่อ) - Pantaka

    ไม่ใช่งานใหม่ แต่เป็นการเอา โลมาบุตร มาชำระล้าง ปรับปรุงเล็กน้อย แต่พอทำไป ๆ มันชักเพี้ยนมาทาง อัมพุช
    เลยเปลี่ยนชื่อเสียเลยดีกว่า เพื่อไม่ให้สับสน และไม่ให้ทับซ้อนกับโลมา
    ตั้งชื่อว่า ปัณถกะ - Pantaka แปลว่าชำนาญทาง
    ทำแล้วรู้สึกว่าอ่านง่ายกว่า วีรชาติ เลยบรรจุเข้าประจำการเป็นฟอนต์หน้าจอแทนวีรชาติ

    ดาวน์โหลดไฟล์รวมดังนี้

    update

    • 50-07-02 ได้ปรับปรุงวีรชาติ จนฟอนต์วีรชาติอ่านง่ายกว่าแล้ว จึงเอาฟอนต์วีรชาติกลับเข้ามาประจำการเป็นฟอนต์แบบ San-Serif แทนปัณถกะ
    Topic: 

    ลองทำฟอนต์ใช้เอง (ต่อ) - Umpush

    หลังจากทำฟอนต์ Corada เสร็จแล้ว มีความรู้สึกว่าฟอนต์ Corada ตัวหนา น่าจะมาทำฟอนต์บนจอได้ เลยเอา Corada เดิม มาแปลงเป็น Light เอา Bold ทำเป็น Book แล้วสร้าง Bold ใหม่ ตั้งชื่อว่า อัมพุช - Umpush

    สามารถทำเป็นฟอนต์สำหรับหน้าจอก็ได้ หรือจะออกเป็นงานพิมพ์ก็ได้
    หากต้องการให้ดูทางหน้าจอภาพได้ง่ายขึ้น เพียงแค่ลดขนาดสระบน-ล่าง และวรรณยุกต์ ลงไปเป็นสัก 90% ก็จะดูทางจอภาพได้ง่ายขี้นแล้วครับ

    ดาวน์โหลดได้ดังนี้

    อย่าลืมว่า ฟอนต์ทุกตัวที่สร้างไว้ ถูกออกแบบไว้ด้วยการ Hint ของระบบ ดังนั้น จะต้องคอนฟิกฟอนต์ทุกครั้ง ด้วย
    $ sudo vi /etc/fonts/conf.d/65-1-ttfonts.conf

    <?xml version="1.0"?>
    <!DOCTYPE fontconfig SYSTEM "fonts.dtd">
    <fontconfig>
        <alias>
            <family>serif</family>
            <accept>
                <family>Noraputta</family>
                <family>Angsima</family>
            </accept>
        </alias>
        <alias>
            <family>sans-serif</family>
            <accept>
                <family>Umpush</family>
                <family>Verachart</family>
                <family>Lomaputta</family>
                <family>Bromlila</family>
                <family>Corada</family>
            </accept>
        </alias>
        ...
        <match target="font">
            <test name="family"><string>Umpush</string></test>
            <edit name="autohint" mode="assign"><bool>true</bool></edit>
            <edit name="hinting" mode="assign"><bool>true</bool></edit>
        </match>
    </fontconfig>
    

    $ fc-cache -r

    ถ้าไม่ประสบเหตุอื่นอีก ฟอนต์นี้คงเป็นฟอนต์สุดท้ายแล้วครับ

    Topic: 

    ลองทำฟอนต์ใช้เอง - Verachart

    ทำฟอนต์หน้าจอเพิ่ม ตั้งชื่อว่า วีรชาติ เพราะเอามาจากฟอนต์ Vera ของ BitStream


    ตัวบางไปหน่อย line spacing แคบไปนิด Hinting ยังแย่อยู่
    ช่วยทดสอบและใช้ได้ฟรีเหมือนเดิมครับ

    ดาวน์โหลดซอร์ส

    (ไฟล์ ttf สามารถดาวน์โหลดที่ หน้ารวม Fonts)

    การทดลองที่ไม่สำเร็จ
    ทดลองทำ Truetype Instruction ด้วยเมนู AutoInstruction
    แก้ไขการที่โปรแกรม Fontforge ทำ Truetype Hint ไม่สมบูรณ์ ด้วยการปรับละเอียดที่ส่วนโค้งของตัวอักษรแทน
    ไม่สำเร็จเนื่องจาก คุณภาพพอดูได้แค่ 11 ปอยนต์ ที่เหลือนอกจากนี้ ดูไม่ได้เลย

    • ไฟล์ฟอนต์ Verachartti.ttf
    • ไฟล์ FontForge Verachartti.sfd
    • ไฟล์ชุดนี้ยังไม่สมบูรณ์ แต่ถ้าหากต้องการทดลองใช้งานดู ไม่จำเป็นต้องแก้ไขไฟล์ 65-ttfonts.conf เนื่องจากมีการ Hint อยู่ในฟอนต์เรียบร้อยแล้ว

    update

    • 50-04-22 ปรับลดความสูงของฟอนต์ให้สมดุลย์กับภาษาอังกฤษ ใช้วิธี Hint แบบ AutoInstruction
    • 50-04-24 กลับมาใช้ Hint แบบเดิม เปลี่ยนมาให้ระบบ Hint ได้ผลดีกว่า โดยเฉพาะฟอนต์ชุดนี้ ให้ปรับไฟล์ 65-1-ttfont.conf เป็นดังนี้
      <fontconfig>
              <alias>
                      ...
                      <family>Verachart</family>
                      <default><family>san-serif</family></default>
              </alias>
              ...
              <match target="font">
                      <test name="family"><string>Verachart</string></test>
                      <edit name="autohint" mode="assign"><bool>true</bool></edit>
                      <edit name="hinting" mode="assign"><bool>true</bool></edit>
                      <edit name="hintstyle" mode="assign"><int>3</int></edit>
              </match>
      </fontconfig>
      

      จะให้ผลที่ดูนุ่มสบายตากว่า แม้ในขนาดฟอนต์ที่เล็กมาก ๆ
      หรือถ้าหากเห็นว่าเบลอเกินไป ก็ตั้งค่า hintstyle เป็น 4 ก็จะดูคมแข็งขึ้นครับ
      (ดูรายละเอียดการปรับตั้งที่ ลองทำฟอนต์ใช้เอง - แถม)

    • 50-04-24 สร้างฟอนต์ชุด Verachart-Bold เพิ่ม
    • 50-04-24 ปรับละเอียด
    • 50-06-06 ปรับปรุง Verachart-Bold เสร็จ ทำ Verachart-Oblique เสร็จ
    • 50-07-02 ปรับละเอียด Verachart 90% และ Verachart-Bold 50%
    • 50-07-04 ปรับละเอียด Verachart และ Verachart-Bold ครั้งที่สอง ทำเรื่อง Hinting โดยปรับให้ความหนาของตัวอักษร ในแนวนอน มีความสม่ำเสมอ จะทำให้การ Hint ดูดีขึ้นมาก
    • 50-07-12 ปรับปรุงตัวหนา ช ฃ ช ซ โ พ ฟ เล็กน้อย

    ลองทำฟอนต์ใช้เอง - แถม

    update

    • การตั้งค่าตามเนื้อความในโพสต์นี้ จะมีผลทำให้ฟอนต์ที่ถูกระบุในการปรับตั้งครั้งนี้ ไม่อยู่ภายใต้การควบคุมของระบบ (กับ Gnome คือ System -> Preference -> Fonts) นั่นคือการแสดงผลของฟอนต์ชุดนี้จะไม่เปลี่ยนไปตามการตั้งค่า Smoothing และ Hinting ของระบบ

    โพสต์นี้ได้ความรู้มาจากคุณสมเจตน์ ท่านช่วยทดสอบให้ ได้ความว่า

    ฟอนต์ชุดนี้ หากจะนำไปใช้ให้ได้ผลดีมีความคมชัด ต้องกำหนด Hint ให้ฟอนต์ด้วย ดังนี้

    สร้างไฟล์ชื่อ 65-1-ttfonts.conf เอาไปใส่ไว้ในไดเรกทอรี่ /etc/fonts/conf.avail แล้วสร้างลิงก์ไปยังไดเรกทอรี่ /etc/fonts/conf.d
    $ sudo vi /etc/fonts/conf.avail/65-1-ttfonts.conf

    <?xml version="1.0"?>
    <!DOCTYPE fontconfig SYSTEM "fonts.dtd">
    <fontconfig>
            <alias>
                    <family>Lomaputta</family>
                    <family>Lomaputta2</family>
                    <family>Garudatas</family>
                    <default><family>san-serif</family></default>
            </alias>
            <alias>
                    <family>Noraputta</family>
                    <family>Norasitas</family>
                    <default><family>serif</family></default>
            </alias>
            <match target="font">
                    <test name="family"><string>Lomaputta</string></test>
                    <edit name="autohint" mode="assign"><bool>true</bool></edit>
                    <edit name="hinting" mode="assign"><bool>true</bool></edit>
                    <edit name="embeddedbitmap" mode="assign"><bool>false</bool></edit>
            </match>
            <match target="font">
                    <test name="family"><string>Lomaputta2</string></test>
                    <edit name="autohint" mode="assign"><bool>true</bool></edit>
                    <edit name="hinting" mode="assign"><bool>true</bool></edit>
                    <edit name="embeddedbitmap" mode="assign"><bool>false</bool></edit>
            </match>
            <match target="font">
                    <test name="family"><string>Garudatas</string></test>
                    <edit name="autohint" mode="assign"><bool>true</bool></edit>
                    <edit name="hinting" mode="assign"><bool>true</bool></edit>
                    <edit name="embeddedbitmap" mode="assign"><bool>false</bool></edit>
            </match>
            <match target="font">
                    <test name="family"><string>Noraputta</string></test>
                    <edit name="autohint" mode="assign"><bool>true</bool></edit>
                    <edit name="hinting" mode="assign"><bool>true</bool></edit>
                    <edit name="embeddedbitmap" mode="assign"><bool>false</bool></edit>
            </match>
            <match target="font">
                    <test name="family"><string>Norasitas</string></test>
                    <edit name="autohint" mode="assign"><bool>true</bool></edit>
                    <edit name="hinting" mode="assign"><bool>true</bool></edit>
                    <edit name="embeddedbitmap" mode="assign"><bool>false</bool></edit>
            </match>
    </fontconfig>

    $ sudo ln -sf /etc/fonts/conf.avail/65-1-ttfonts.conf /etc/fonts/conf.d

    แล้วก็รีบูตเครื่องใหม่ หลังจากนั้นก็จะเห็นฟอนต์ชุดนี้มีความคมชัดเพิ่มขึ้นครับ

    ลิงก์รอศึกษา

    ลองทำฟอนต์ใช้เอง ๒

    ลองทำอีกชุดนึงสำหรับ sans-serif โดยเอาฟอนต์โลมามาเป็นต้นแบบ
    จุดประสงค์เพื่อจะนำมาทำเป็นฟอนต์สำหรับดูที่หน้าจอมอนิเตอร์ โดยต้องการให้อ่านง่าย จึงปรับให้หัวตัวอักษรกลมขึ้น แยกเส้นตัวอักษรให้เด็ดขาดขึ้น

    ตั้งชื่อว่าโลมาบุตร (Lomaputta)
    ช่วยทดสอบหรือเอาไปใช้ได้ฟรี (ฟอนต์โลมาต้นฉบับเป็น GPL)

    เพิ่มความหนานิดนึง ดูคล้าย ๆ Tahoma เสียดายอันเก่า เลยตั้งชื่อใหม่เป็นโลมาบุตร2

    update

    • 50-04-14 ปรับช่องไฟละเอียด, ปรับส่วนโค้งอักษรแบบละเอียด, ปรับมาใช้เทมเพลตของ thaifonts รุ่น 0.4.6 ทำให้สามารถใช้งาน OO.o ได้
    • 50-04-16 ปรับแต่ง Hinting ด้วยมือ ดูดีขึ้นมาก
    • 50-04-17 ปรับมาใช้เทคนิกการ Hint แบบเบลอภายในฟอนต์ด้วย AutoHint และคมภายนอกด้วย ManualHint
    • 50-04-17 สร้าง Lomaputta-Bold เพิ่ม
    • 50-04-17 เปลี่ยนกลับมาใช้ Hint ด้วยมือล้วน เนื่องจากแสดงผลในเดเบียนฟุ้ง(Blur)เกินไป (คงไม่เกี่ยวกับเดเบียน แต่อาจเป็นเพราะเครื่องเดเบียนของผมใช้จอภาพเป็น LCD ของเอเซอร์ ซึ่งการแสดงผลดูแล้วจะสู้ของแอลจีไม่ได้) แก้อาการหลอกตาด้วยการลดขนาดหัวตัวอักษรแทน
      รู้ปัญหาอาการฟุ้งบนเดเบียนแล้ว คือ เดเบียนไม่ทำ AutoHint เป็นค่าปริยาย จึงต้องทำเองด้วยมือ
      $ sudo ln -sf /etc/fonts/conf.avail/10-autohint.conf /etc/fonts/conf.d
      แล้วเข้าระบบใหม่ ผลที่ได้คือ ฟอนต์บนเดเบียนดูคมกว่าบนอูบุนตูอีก
    • 50-04-18 สร้าง Lomaputta-Oblique เพิ่ม
    • 50-04-19 แก้ไขตาราง Contextual ซ่อมเรื่องวรรณยุกต์กับสระอุ-สระอู ตามต้นฉบับ
    • 50-04-19 สร้าง Lomaputta-BoldOblique เพิ่ม
    • 50-04-27 ล้างลายเส้นเก่า สร้างลายเส้นใหม่ เลียนแบบของคุณเทพ

    ลองทำฟอนต์ใช้เอง ๓

    คราวก่อนทำฟอนต์โลมาบุตร ดูแล้วยังรู้สึกว่าอ่านยาก (ไม่รู้ว่าเป็นที่ hinting หรือเปล่า)
    คราวนี้ลองเอาอีกฟอนต์นึงคือฟอนต์ครุฑ (Garuda) มาปรับให้เหมาะกับการแสดงผลบนจอคอมพิวเตอร์
    โดยการลดขนาดสระและวรรณยุกต์ และปรับความกว้างของบรรทัดให้แคบเข้า
    เอาไว้เป็นตัวเผื่อเลือกสำหรับการแสดงผลของฟอนต์ sans-serif
    ตั้งชื่อว่าฟอนต์ ครุฑทัศน์ (Garudatas)

    ดาวน์โหลด

    update
    ทำเพิ่มเติมสำหรับ serif ด้วย คือฟอนต์นรสีห์ เป็น นรสีห์ทัศน์
    ดาวน์โหลด

    หมายเหตุ
    ไม่เหมาะสำหรับงานเอกสารที่ต้องพิมพ์ออกมา สำหรับงานพิมพ์ใช้ฟอนต์ Garuda และ Norasi เดิมสวยอยู่แล้ว

    เกร็ดเกี่ยวกับโปรแกรม FontForge

    โปรแกรม FontForge เป็นโปรแกรมที่ใช้ออกแบบฟอนต์ของลินุกซ์ที่ได้รับความนิยม มีความสามารถสูง แต่มีข้อเสียคือ ทำ AutoHint ได้แย่มาก เพราะโปรแกรมจะกันเหนียวด้วยการกำหนดแถบการ Hint ไว้กว้างเกินไป

    การกำหนดแถบการ Hint ไว้กว้าง ทำให้เวลาแสดงฟอนต์ทางจอภาพ อักษร ก ไก่ จะดูเตี้ยกว่าอักษร ข ไข่ ซึ่งไม่ถูก AutoHint ไว้กว้างแบบนั้น

    ถ้าจะทำให้ได้ผลการ Hint ที่ดี แบบที่เรา ๆ ท่าน ๆ สามารถทำได้เอง โดยไม่ต้องใช้ฝีมือระดับเทพ ก็คือการ Hint เองด้วยมือ
    ซึ่งทำได้โดยการกำหนดสองจุดคู่ที่จะทำการ Hint แล้วสั่ง Add HHint หรือ Add VHint ตามลักษณะของส่วนโค้งตัวอักษรนั้น ๆ

    วิธีนี้ทำให้ได้ตัวอักษรที่ดูสูงเท่ากัน แต่ปัญหาคือโปรแกรม FontForge ไม่ทำปุ่มลัดสำหรับคำสั่ง Add HHint และ Add VHint ไว้ด้วย
    งานที่จะต้องมานั่งเลือกจุดคู่แล้วไล่คลิกเมนูสั่งงาน นับว่าเปลืองเวลาเกินไป
    แต่ยังโชคดีที่โปรแกรมถูกออกแบบให้สามารถกำหนดปุ่มลัดได้เอง เพียงแต่ต้องออกแรงหน่อยนึงด้วยการคอมไพล์แพกเกจเอง
    เราจะกำหนดปุ่มลัดเอง ทำให้การทำงานเร็วขึ้นมาก

    การทำปุ่มลัดสำหรับ FontForge

    เริ่มด้วยการติดตั้งแพกเกจที่จำเป็นในการคอมไพล์ก่อน
    $ sudo aptitude install libfreetype6-dev
    (แพกเกจอื่น ๆ ไม่แน่ใจครับ อาจตรวจดูจากข้อผิดพลาดตอนสั่ง ./configure ก็ได้)

    ไปเอาซอร์สมาก่อนคือไฟล์ fontforge_full-20070312.tar.bz2

    เมื่อได้ไฟล์มาแล้วก็แตกไฟล์ออกก่อน
    $ tar xfj fontforge_full-20070312.tar.bz2

    คอมไพล์และติดตั้ง
    $ cd fontforge-20070312
    $ ./configure
    $ make
    $ sudo make install

    ต่อไปเป็นการสร้างไฟล์สำหรับกำหนดปุ่มลัด
    ทำตามคู่มือ ในการนำเอาไฟล์ FontForge-MenuShortCuts.pot ออกมา
    $ cd fontforge-20070312/fontforge
    $ make -f Makefile.in FontForge-MenuShortCuts.pot

    เราจะได้ไฟล์ FontForge-MenuShortCuts.pot
    เราจะแก้ไขในไฟล์นี้โดยกำหนดให้ Add HHint ใช้ปุ่มลัดเป็น Alt+Ctl+1
    และ Add VHint ใช้ปุ่มลัดเป็น Alt+Ctl+2
    $ vi FontForge-MenuShortCuts.pot

    ...
    #: charview.c:8105
    msgid "Add HHint|No Shortcut"
    msgstr "Alt+Ctl+1" 
    
    #: charview.c:8106
    msgid "Add VHint|No Shortcut"
    msgstr "Alt+Ctl+2"
    ...
    

    คอมไพล์ไฟล์ pot
    $ msgfmt -o FontForge-MenuShortCuts.mo FontForge-MenuShortCuts.pot

    ย้ายไฟล์นี้ไปไว้ที่ไดเรกทอรี่ที่เก็บ locale ของเครื่อง
    ถ้าตั้ง locale เป็น en_US.UTF8 คำสั่งจะเป็น
    $ sudo mkdir -p /usr/local/share/locale/en_US/LC_MESSAGES
    $ sudo mv FontForge-MenuShortCuts.mo /usr/local/share/locale/en_US/LC_MESSAGES

    เสร็จเรียบร้อยแล้ว สั่งรันโปรแกรมด้วยคำสั่ง
    $ /usr/local/bin/fontforge -dontopenxdevices [ชื่อไฟล์ฟอนต์]

    ผลที่ได้จากการทำ Hint ด้วยมือ ดูดีขึ้นกว่าทำ AutoHint มากครับ

    จากความรู้ที่ได้นี้ สามารถสรุปการ Hint ได้คือ

    • ส่วนในของฟอนต์เลือกใช้ AutoHint เนื่องจากต้องการให้เกิดการเบลอภายในให้มากที่สุด
    • ส่วนนอกของฟอนต์ คือ จุดสูงสุดและต่ำสุด ต้อง Hint เองด้วยมือ เพราะต้องการให้ส่วนสูงมีความคงที่
    • เพิ่มเติม

    • อ่านมาจาก http://osdir.com/ml/fonts.fontforge.user/2006-08/msg00030.html
      บอกว่า ปกติ FontForge ไม่ทำ Hint ของทรูไทป์โดยตรง แต่เป็นของ Type1
      ถ้าจะพยายามทำ Hint ให้ทรูไทป์ วิธีทำคือให้เปลี่ยนส่วนโค้งเป็นแบบ Quadratic
      Element -> Font Info ... -> เลือก Quadratic Splines

      หลังจากนั้นจึงทำ AutoHint และ AutoInstruction แล้วจึงสั่งผลิตฟอนต์ทรูไทป์
      เลือกช่วงฟอนต์ที่ต้องการ -> Hints -> AutoHint
      Hints -> AutoInstr
      Files -> Generates Fonts

      ทดลองแล้วได้ผลดีพอควร

    • 50-05-05 ลองทดสอบเรื่อง Truetype Hint ได้ความว่า
      ถึงแม้ว่า Fontforge จะทำ Truetype Hint ได้แย่มากก็ตาม แต่เราก็อาจบังคับทำได้ โดยได้ผลดีพอควร โดยมีข้อแม้ว่า :-
      1. จุดต่าง ๆ ที่กำกับส่วนโค้ง ต้องเลือกใช้จุดให้ตรงจริง ๆ ทั้งสามชนิดคือ จุดส่วนโค้ง จุดหัวมุม และจุดแทนเจนต์ ห้ามใช้จุดมั่วเด็ดขาด
      2. ขนาดความหนาของส่วนตัวอักษร และจุดกำกับส่วนโค้งต่าง ๆ ควรอยู่ในตำแหน่งทางเรขาคณิตแบบง่าย ๆ
      3. ส่วนโค้งที่ยาวมาก ต้องมีจุดแบ่งส่วนกำกับเสมอ
      4. ถ่าหากจุดเริ่มต้นส่วนโค้ง ไม่อยู่ในตำแหน่งทางเรขาคณิตอย่างง่าย ควรใช้จุดแทนเจนต์กำกับอยู่ใกล้ ๆ (เช่น ปลายหางของตัว จ.จาน เป็นต้น)
      5. เมื่อทดสอบแล้วพบว่ามีบางอักขระที่มีอาการฟุ้ง ให้ลองปรับลดหรือเพิ่มความกว้างของอักขระนั้นที่ละ 1 พิกเซล (ส่วนใหญ่ลองที่ขนาดฟอนต์ประมาณ 11 ปอยนต์)

      ถ้าผ่านข้อกำหนดดังกล่าว การ Hint จะได้ผลดีที่สุด

    • การทำงานกับส่วนโค้งที่เป็น Quadratic ไม่ยากจนเกินไปนัก หัดสักพักก็จะชิน เมื่อชินแล้วจะพบว่าการบังคับส่วนโค้ง ง่ายกว่าแบบ Cubic เสียอีก เพราะโดนบังคับด้วยจุดขนาบ
    • อนาคตของ Truetype Hint น่าจะเสื่อมความนิยมลงไปเรื่อย ๆ ผกผันกับขนาดความละเอียดของจอภาพที่จะละเอียดขึ้นไปเรื่อย ๆ
    • การทำให้การ Hint แบบ Adobe ได้ผลดี ควรปรับความหนาของตัวอักษรในแนวนอนให้มีความสม่ำเสมอ จึงจะได้ความสูงของตัวอักษรที่เท่า ๆ กัน ที่ขนาดตัวอักษรต่าง ๆ กัน

    ลองทำฟอนต์ใช้เอง - จบ

    ค้นไปค้นมา ไปพบฟอนต์ที่เป็นฟรีแวร์และ gpl สรุปได้ดังนี้

    • ฟอนต์แห่งชาติ นอกเหนือจากฟอนต์โลมา ครุฑ และนรสีห์แล้ว ยังมีฟอนต์กินรีที่สวยอยู่แล้ว ใช้แทนฟอนต์ Angsana ในวินโดวส์ได้เลย - ดาวน์โหลด national-fonts.zip
    • ฟอนต์ของบริษัท Tep Club เป็นฟรีแวร์ มีฟอนต์สวยมาก ๆ คือ CmPrasanmit - ดาวน์โหลด tep-clubfonts.zip
    • ฟอนต์ที่ SIPA พัฒนา ไม่ค่อยสวยเท่าไหร่ - ดาวน์โหลด dip-sipa-font.zip
    • ฟอนต์ตระกูล JS ของคุณหมอภาณุฑัต ที่แนบมากับลินุกซ์ทะเล 7 สามารถนำออกจากแผ่น TLE-7 ได้เลย หรือสามารถดาวน์โหลดไฟล์ rpm แล้วนำมาแตกเองด้วยโปรแกรม Archeive Manager - ดาวน์โหลด thai-ttf-js.0.0.2-1.src.rpm
    • มีฟอนต์สวย ๆ มากจริง ๆ

    ทำฟอนต์เอง มาตายตรง hinting มือไม่ถึง :P เวลาไม่เอื้อให้ศึกษา
    แต่ก็ยังชอบใจ โลมาบุตรอยู่ดี ;D

    Topic: 

    debian: ติดตั้งฟอนต์ Tahoma

    ฟอนต์ Tahoma ถูกใช้เป็นฟอนต์ปริยายในการแสดงผลของเว็บไซต์เป็นจำนวนมาก ลองค้นหาดูพบว่ามันอยู่ในแพคเกจของ cinelerra-data ในคลังของ debian-multimedia

    วิธีการคือเพิ่มคลังของ debian-multimedia และติดตั้งแพคเกจ cinelerra-data

    $ sudo vi /etc/apt/sources.list
    ...
    deb http://www.debian-multimedia.org sid main non-free
    ...
    $ sudo aptitude update
    $ sudo aptitude install cinelerra-data

    อาจเปลี่ยนรุ่นจาก sid เป็น lenny หรือรุ่นที่ใช้งานจริงได้

    เสร็จแล้วครับ
    จะได้ฟอนต์ Tahoma ที่มีภาษาไทยครบถ้วน อีกทั้งฟอนต์ของไมโครซอฟท์อีกหลายตัว ซึ่งฟอนต์ทั้งหมดจะถูกติดตั้งไว้ที่ /usr/lib/cinelerra/fonts/

    Topic: 

    fonts: TrueType Hinting Instruction

    ศึกษาการทำ TrueType Hinting Instruction

    ลิงก์

    การทำ Truetype Hinting Instructions

    ตัวอย่างไฟล์

    ไฟล์ DejaVuSansThai.tar.gz

    Topic: 

    fonts: บันทึก DroidSans+Thai+Lao

    ฟอนต์รุ่นนี้เป็นรุ่นลัดคิว

    1. งานคือเอาฟอนต์ DroidSansThai ของกูเกิล รุ่นที่เป็นแอนดรอยด์ 2.2 ลงไป (อาจจะเป็นชื่อ DroidSansThai.ttf หรือ DroidThai-Regular.ttf) มาทำตัวหนาเพิ่มแบบหยาบ ๆ โดยมีการดัดแปลงสคริปต์ 'ccmp' Glyph Composition/Decomposition in Thai lookup 2" เล็กน้อย เพื่อให้แสดงระดับวรรณยุกต์ได้ถูกต้อง เราจะให้อยู่ในชื่อ DroidSansThai
      รุ่นนี้ เนื่องจากมีเแต่ภาษาไทย ดังนั้นถ้านำมาใช้ในลินุกซ์จะต้องสร้างไฟล์ fontconfig ประมาณนี้ (ยังไม่ได้ทดสอบ)

      ...
        <match target="scan">
          <test name="family">
            <string>Droid Sans Thai</string>
          </test>
          <edit name="family">
            <string>Droid Sans</string>
          </edit>
          <edit name="fullname">
            <string>Droid Sans</string>
          </edit>
        </match>
      ...
         <alias binding="same">
          <family>Droid Sans Thai</family>
          <accept>
            <family>Droid Sans</family>
          </accept>
        </alias>
      ...
    2. อีกงานนึงคือเอาอักขระไทยจาก DroidSansThai สอดเข้าไปในฟอนต์ DroidSans เพื่อให้โทรศัพท์แอนดรอยด์ใช้งานฟอนต์ตัวนี้ได้ อันนี้จะอยู่ในชื่อ DroidSans (เสียดายที่แอนดรอยด์ไม่รองรับตาราง OpenType การแสดงวรรณยุกต์จึงยังลอยอยู่)

    ดาวน์โหลดไฟล์ฟอนต์ (ล่าสุดคือ 20100812)

    1. DroidSansThai-ttf.tar.gz
    2. DroidSans-ttf.tar.gz (สำหรับใช้กับโทรศัพท์แอนดรอยด์)
    ข้อความด้านล่างเป็นการแสดงผลจากหน้าเว็บด้วยฟอนต์นี้ (จากความสามารถของ css3)

    ดาวน์โหลดไฟล์ซอร์ส

    ทดสอบภาษาลาว

    • ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝ
    • ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝ

    ภาพตัวอย่าง
    ภาพจากบราวเซอร์ epiphany
    ตัวธรรมดา

    ตัวหนา

    Topic: 

    fonts: บันทึก DroidSansMono+Thai+Lao

    ลัดคิว #3
    ทำฟอนต์ DroidSansMono เพิ่ม โดยทำทั้งภาษาไทยและลาว เสียดายที่ต้นฉบับไม่มีตัวหนา เลยทำแค่ตัวธรรมดาอย่างเดียว
    ทำเป็นฟอนต์แบบ Monospace แท้ ๆ โดยใช้ต้นแบบตาราง Lookup จากฟอนต์ TlwgTypo

    ดาวน์โหลดไฟล์ฟอนต์ (ล่าสุดคือ 20100917)

    ข้อความด้านล่างเป็นการแสดงผลจากหน้าเว็บด้วยฟอนต์นี้ (จากความสามารถของ css3)

    ดาวน์โหลดไฟล์ซอร์ส

    ทดสอบภาษาลาว

    • ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝ

    ภาพตัวอย่าง
    ภาพจากบราวเซอร์ epiphany
    ตัวธรรมดา

    fonts: บันทึก DroidSerif+Thai+Lao

    ลัดคิว #2
    ทำฟอนต์ DroidSerif เพิ่ม ถึงจะมีที่ใช้น้อย แต่ก็ทำไว้เพื่อให้แสดงผลได้สมบูรณ์ ทำทั้งภาษาไทยและลาว

    update

    • 561227: Google เปลี่ยนชื่อฟอนต์ Droid Serif เป็น Noto Serif ไฟล์ต้นฉบับเป็นภาษาอังกฤษ+ละติน และแยกไฟล์ออกมาอีกหลายภาษา (รวมทั้งไทยและลาว) ดาวน์โหลดได้ที่ code.google.com:noto
    • 561228: เปลี่ยน Droid Serif เป็น Droid Serif Web ป้องกันการสับสน มี อังกฤษ ละติน ไทย ลาว และปรับ Glyph ใหม่หมด
    • 570219:
      • เอาฐานฟอนต์ Droid Serif ของกูเกิลรุ่นล่าสุด คือ 1.0.3 มาทำ Droid Serif Web
      • เอาฐานฟอนต์ Noto Sans Thai มาทำ Droid Serif ThaiLao โดยให้ชื่อ font family เป็น Droid Serif ThaiLao และ font family preferred เป็น Droid Serif ดังนั้น ถ้าเราติดตั้งฟอนต์ fonts-droid จะสามารถใช้ภาษาไทยและลาวจากฟอนต์ Droid Serif ThaiLao ได้ภายใต้ชื่อ Droid Serif (ยกเว้น Inkscape ต้องใช้ Droid Serif Web แทน)

    Droid Serif (ต้นฉบับ+ไทย+ลาว) - เลิกทำแล้ว (จริง ๆ คือเปลี่ยนชื่อเป็น Droid Serif Web แทน ป้องกันสับสน)

    ดาวน์โหลดไฟล์ฟอนต์ (ล่าสุดคือ 20100914)
    DroidSerif-ttf.tar.gz
    ดาวน์โหลดไฟล์ซอร์ส
  • รุ่นร่าง ยังไม่ได้ทำ hint : DroidSerif-src-20100823.tar.gz
  • เสร็จแบบยังไม่มี hint ลดความกว้างลงเล็กน้อย : DroidSerif-src-20100914.tar.gz
  • ตัวอย่าง

    24!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` Aabcdefghijklmnopqrstuvwxyz{|}~ mrnrtodocode ṃāñūṭḍṇṅ
    aกัขิฃีคึฅืฆุงูจฺฉ็ช่ซ้ฌ๊ญ๋ญุฎ์ฏํฐ๎ฐูฑั่ฒิ้ณี๊ดื๋ติ์ถะทาธำน่ำเบี่แปิํโผใฝ่ไพฟ้ภมยรฤๅลฦวศษสหฬอฮฯๆ ฿๏๐๑๒๓๔๕ ๖๗๘๙๚๛ ก่ป่ฝ้ฟ๊ฬ๋ คฅศ ดตฒ ญฐญานํ ญฐญานํ โสตฺถิํ
    ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝໞໟ

    24!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` Aabcdefghijklmnopqrstuvwxyz{|}~ mrnrtodocode ṃāñūṭḍṇṅ
    aกัขิฃีคึฅืฆุงูจฺฉ็ช่ซ้ฌ๊ญ๋ญุฎ์ฏํฐ๎ฐูฑั่ฒิ้ณี๊ดื๋ติ์ถะทาธำน่ำเบี่แปิํโผใฝ่ไพฟ้ภมยรฤๅลฦวศษสหฬอฮฯๆ ฿๏๐๑๒๓๔๕ ๖๗๘๙๚๛ ก่ป่ฝ้ฟ๊ฬ๋ คฅศ ดตฒ ญฐญานํ ญฐญานํ โสตฺถิํ
    ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝໞໟ


    Droid Serif ThaiLao (มีเฉพาะภาษาไทย+ลาว)

    ดาวน์โหลดไฟล์ฟอนต์ (ล่าสุดคือ 20140219)
    DroidSerifThaiLao-ttf.tar.gz
    ดาวน์โหลดไฟล์ซอร์ส
  • ปรับ glyph ใหม่หมดให้ดูสง่าขึ้น ลดช่องไฟตัวหนาให้ดูกระชับ เพิ่ม glyph ภาษาลาว (ขมุ-ก และ ขมุ-ญ) รุ่นนี้มีการเปลี่ยนความกว้างฟอนต์หลายตัว จึงไม่ compat กับของเก่าเลย : DroidSerifThaiLao-src-20131227.tar.gz
  • แต่งตัวเลขไทย : DroidSerifThaiLao-src-20140104.tar.gz
  • ปรับฐานใหม่ ให้ใช้งานภายใต้ชื่อ Droid Serif ได้ : DroidSerifThaiLao-src-20140219.tar.gz
  • ตัวอย่าง

    24!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` Aabcdefghijklmnopqrstuvwxyz{|}~ mrnrtodocode ṃāñūṭḍṇṅ
    aกัขิฃีคึฅืฆุงูจฺฉ็ช่ซ้ฌ๊ญ๋ญุฎ์ฏํฐ๎ฐูฑั่ฒิ้ณี๊ดื๋ติ์ถะทาธำน่ำเบี่แปิํโผใฝ่ไพฟ้ภมยรฤๅลฦวศษสหฬอฮฯๆ ฿๏๐๑๒๓๔๕ ๖๗๘๙๚๛ ก่ป่ฝ้ฟ๊ฬ๋ คฅศ ดตฒ ญฐญานํ ญฐญานํ โสตฺถิํ
    ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝໞໟ

    24!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` Aabcdefghijklmnopqrstuvwxyz{|}~ mrnrtodocode ṃāñūṭḍṇṅ
    aกัขิฃีคึฅืฆุงูจฺฉ็ช่ซ้ฌ๊ญ๋ญุฎ์ฏํฐ๎ฐูฑั่ฒิ้ณี๊ดื๋ติ์ถะทาธำน่ำเบี่แปิํโผใฝ่ไพฟ้ภมยรฤๅลฦวศษสหฬอฮฯๆ ฿๏๐๑๒๓๔๕ ๖๗๘๙๚๛ ก่ป่ฝ้ฟ๊ฬ๋ คฅศ ดตฒ ญฐญานํ ญฐญานํ โสตฺถิํ
    ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝໞໟ


    Droid Serif Web (อังกฤษ+ละติน+ไทย+ลาว)

    ดาวน์โหลดไฟล์ฟอนต์ (ล่าสุดคือ 20140219)
    DroidSerifWeb-ttf.tar.gz
    ดาวน์โหลดไฟล์ซอร์ส
  • DroidSerifWeb-src-20131227.tar.gz
  • แต่งตัวเลขไทย : DroidSerifWeb-src-20140104.tar.gz
  • ปรับฐานเป็นรุ่นล่าสุด : DroidSerifWeb-src-20140219.tar.gz
  • ตัวอย่าง

    24!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` Aabcdefghijklmnopqrstuvwxyz{|}~ mrnrtodocode ṃāñūṭḍṇṅ
    aกัขิฃีคึฅืฆุงูจฺฉ็ช่ซ้ฌ๊ญ๋ญุฎ์ฏํฐ๎ฐูฑั่ฒิ้ณี๊ดื๋ติ์ถะทาธำน่ำเบี่แปิํโผใฝ่ไพฟ้ภมยรฤๅลฦวศษสหฬอฮฯๆ ฿๏๐๑๒๓๔๕ ๖๗๘๙๚๛ ก่ป่ฝ้ฟ๊ฬ๋ คฅศ ดตฒ ญฐญานํ ญฐญานํ โสตฺถิํ
    ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝໞໟ

    24!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` Aabcdefghijklmnopqrstuvwxyz{|}~ mrnrtodocode ṃāñūṭḍṇṅ
    aกัขิฃีคึฅืฆุงูจฺฉ็ช่ซ้ฌ๊ญ๋ญุฎ์ฏํฐ๎ฐูฑั่ฒิ้ณี๊ดื๋ติ์ถะทาธำน่ำเบี่แปิํโผใฝ่ไพฟ้ภมยรฤๅลฦวศษสหฬอฮฯๆ ฿๏๐๑๒๓๔๕ ๖๗๘๙๚๛ ก่ป่ฝ้ฟ๊ฬ๋ คฅศ ดตฒ ญฐญานํ ญฐญานํ โสตฺถิํ
    ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝໞໟ

    Topic: 

    fonts: บันทึก Lomaputta

    เอา Lomaputta - โลมาบุตร ซึ่งเอามาจากฟอนต์โลมาของ ltn: ThaiFonts-Scalable มาทำเรื่อง hinting

    ตอนทำ hinting จริง ๆ ต้องปรับลายเส้นจากเดิมเยอะเหมือนกัน

    ดาวน์โหลดไฟล์ฟอนต์(20100602)

    ดาวน์โหลดไฟล์ซอร์ส

    • รุ่นเริ่มต้น ยังไม่มีตัวหนา ฟอนต์ไทย hint ด้วยมือ ส่วนฟอนต์อังกฤษ ใช้ Auto-Instruction แบบช่วยปรับแต่งเล็กน้อย (การปรับแต่งยังไม่ดีนัก เพราะโค๊ด dfont.py ยังไม่เข้าที่ รอรุ่นหน้าต่อไป :) Lomaputta-src-520501.tar.gz
    • ตัวหนาเกือบเสร็จ เปลี่ยนการเดินจุดให้อัตโนมัติมากขึ้น ด้วยคำสั่ง SROUND Lomaputta-src-20090506.tar.gz
    • ตัวหนาเสร็จแล้ว Lomaputta-src-20090511.tar.gz
    • แก้บั๊กสระ 'แ' ใน openoffice.org-3.0.1 พิมพ์ไม่ออก Lomaputta-src-20090518.tar.gz - แก้โดยการเติมจุดเปล่าที่ช่อง uni0E00 (ข้างหน้า 'ก') แล้ว copy reference มาผสมลงในช่องสระแอ (วิธีพิสดารหน่อย อนาคตอาจเอาออก) เป็นบั๊กทางโปรแกรมมิ่งของผมเอง แก้ไขเรียบร้อยแล้วครับ
    • ปรับปรุงสระและวรรณยุกต์เหนืออักษรมีหางบน (ป ฝ ฟ ฬ) ให้แยกจากตัวอักษรมากขึ้น Lomaputta-src-20100119.tar.gz
    • ทำ hinting ภาษาอังกฤษเพิ่ม Lomaputta-src-20100531.tar.gz
    • ปรับ hint ให้เส้นนอนนุ่มนวลขึ้น แก้ปาก ก.ไก่ ให้หนาขึ้น แก้เส้นหลัง ร.เรือ ให้คมขึ้น Lomaputta-src-20100602.tar.gz

    ภาพตัวอย่าง
    จากบราวเซอร์ epiphany
    ตัวธรรมดา

    ตัวหนา

    Topic: 

    fonts: บันทึก Norasiputta

    เอาฟอนต์นรสีห์จาก ltn: ThaiFonts-Scalable มาทำเรื่อง hinting

    แทบไม่เปลี่ยนลายเส้นเลย คงรูปเดิมให้มากที่สุด แปลงแต่จุด เพื่อให้เหมาะกับการทำ hinting

    ดาวน์โหลดไฟล์ฟอนต์ (20100625)

    ข้อความด้านล่างเป็นการแสดงผลจากหน้าเว็บด้วยฟอนต์นี้ (จากความสามารถของ css3)

    ดาวน์โหลดไฟล์ซอร์ส

    • รุ่นเริ่มต้น ยังไม่มีตัวหนา ฟอนต์ไทย hint ด้วยมือ ส่วนฟอนต์อังกฤษ ใช้ Auto-Instruction แบบช่วยปรับแต่งเล็กน้อย Norasiputta-src-520702.tar.gz
    • ตัวหนาเสร็จแบบยังไม่ได้เกลา Norasiputta-src-520707.tar.gz
    • รื้อมาทำใหม่ จุดประสงค์คือต้องการทำเป็นฟอนต์สำหรับดูหน้าจอภาพ ด้วยการเพิ่มความหนา stem ไทย เปลี่ยน glyph ภาษาอังกฤษ โดยเอาฐานมาจากฟอนต์ Dustismo Roman และ Droid Serif เพื่อให้ดูกลมกลืนกับ glyph ไทย รุ่นนี้จึงถือเป็นรุ่นร่าง ยังไม่มี hint - Norasiputta-src-20100610.tar.gz
    • ตัวธรรมดา hint หยาบเสร็จ - Norasiputta-src-20100618.tar.gz
    • ตัวหนาเสร็จ ตรวจสอบการแสดงผลไปเรื่อย ๆ - Norasiputta-src-20100625.tar.gz

    ภาพตัวอย่าง
    จาก Epiphany Browser
    ตัวธรรมดา

    ตัวหนา

    Topic: 

    fonts: บันทึก Roboto

    เอาฟอนต์ Roboto มาใส่ภาษาไทย โดยเอาโครงฟอนต์ Roboto (20%) + Droid Sans (30%) + Garuda (50%)

    จุดประสงค์คือจะนำไปใช้ทดสอบ Android ICS

    Update

    • 20140220
      • เลิกทำภายใต้ชื่อ Roboto เฉย ๆ แต่เปลี่ยนเป็น Roboto Web แทน ซึ่งจะมีภาษาอังกฤษ, ละติน, ไทย และลาว ใช้งานภายใต้ชื่อ Roboto Web
      • ทำรุ่นที่มีเฉพาะไทยกับลาวภายใต้ชื่อ Roboto ThaiLao โดยตึ้งค่า perferred family เป็น Roboto ใช้งานภายใต้ชื่อ Roboto แต่ต้องมีการลงแพ็กเกจหรือปรับตั้งอื่น ดังนี้
        • สำหรับเดสก์ทอป ลงแพ็กเกจชื่อ fonts-roboto แล้วสามารถใช้งานผ่านชื่อฟอนต์ Roboto ได้เลย (ยกเว้น Inkscape ให้ใช้ Roboto Web แทน)
        • สำหรับโทรศัพท์แอนดรอยด์ ให้นำ RobotoThaiLao-*.ttf ใส่ใน /system/fonts แล้วแก้ไขไฟล์ /system/etc/fallback_fonts.xml เพิ่มบรรทัดดังนี้
          ...
              <family>
                  <fileset>
                      <file>RobotoThaiLao-Regular.ttf</file>
                      <file>RobotoThaiLao-Bold.ttf</file>
                  </fileset>
              </family>
          ...
          
          ยกเว้น RobotoThaiLao-Light และ RobotoThaiLao-Thin ต้องแก้ /system/etc/system_fonts.xml โดยตรง ดังนี้
          ...
              <family>
                  <nameset>
                      <name>sans-serif-light</name>
                  </nameset>
                  <fileset>
                      <file>Roboto-Light.ttf</file>
                      <file>Roboto-LightItalic.ttf</file>
                      <file>RobotoThaiLao-Light.ttf</file>
                  </fileset>
              </family>
          
              <family>
                  <nameset>
                      <name>sans-serif-thin</name>
                  </nameset>
                  <fileset>
                      <file>Roboto-Thin.ttf</file>
                      <file>Roboto-ThinItalic.ttf</file>
                      <file>RobotoThaiLao-Thin.ttf</file>
                  </fileset>
              </family>
          ...
          

    Roboto (ต้นฉบับ+ไทย+ลาว) - เลิกทำแล้ว (จริง ๆ คือเปลี่ยนชื่อเป็น Roboto Web แทน ป้องกันสับสน)

    ดาวน์โหลดไฟล์ฟอนต์ (ล่าสุดคือ 20121003)
    Roboto-ttf.tar.gz
    ดาวน์โหลดไฟล์ซอร์ส
  • รุ่นร่างเริ่มต้น ยังไม่ได้ทำ hint ยังไม่ได้ทำภาษาลาว (ใช้ของเดิมที่เป็นของ Droid Sans ที่ทำไว้ก่อนแล้ว) เพิ่มการรองรับภาษาบาลี (lang="pi"): Roboto-src-20121003.tar.gz
  • ตัวอย่าง

    24!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` Aabcdefghijklmnopqrstuvwxyz{|}~ mrnrtodocode ṃāñūṭḍṇṅ
    aกัขิฃีคึฅืฆุงูจฺฉ็ช่ซ้ฌ๊ญ๋ญุฎ์ฏํฐ๎ฐูฑั่ฒิ้ณี๊ดื๋ติ์ถะทาธำน่ำเบี่แปิํโผใฝ่ไพฟ้ภมยรฤๅลฦวศษสหฬอฮฯๆ ฿๏๐๑๒๓๔๕ ๖๗๘๙๚๛ ก่ป่ฝ้ฟ๊ฬ๋ คฅศ ดตฒ ญฐญานํ ญฐญานํ โสตฺถิํ
    ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝໞໟ

    24!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` Aabcdefghijklmnopqrstuvwxyz{|}~ mrnrtodocode ṃāñūṭḍṇṅ
    aกัขิฃีคึฅืฆุงูจฺฉ็ช่ซ้ฌ๊ญ๋ญุฎ์ฏํฐ๎ฐูฑั่ฒิ้ณี๊ดื๋ติ์ถะทาธำน่ำเบี่แปิํโผใฝ่ไพฟ้ภมยรฤๅลฦวศษสหฬอฮฯๆ ฿๏๐๑๒๓๔๕ ๖๗๘๙๚๛ ก่ป่ฝ้ฟ๊ฬ๋ คฅศ ดตฒ ญฐญานํ ญฐญานํ โสตฺถิํ
    ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝໞໟ


    Roboto ThaiLao (มีเฉพาะภาษาไทย+ลาว)

    ดาวน์โหลดไฟล์ฟอนต์ (ล่าสุดคือ 20140225)
    RobotoThaiLao-ttf.tar.gz
    ดาวน์โหลดไฟล์ซอร์ส
  • ใช้ฐานฟอนต์ของ Noto Sans Thai และ Roboto ต้นฉบับ เกลาภาษาไทยเล็กน้อย ทำ Glyph ภาษาลาวใหม่ให้สอดคล้องกับรูปแบบของ Roboto (ภาษาลาวมีการเปลี่ยนความกว้าง ไม่คอมแพตกับของเดิม) : RobotoThaiLao-src-20140221.tar.gz
  • เพิ่ม Light : RobotoThaiLao-src-20140225.tar.gz
  • ตัวอย่าง

    24!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` Aabcdefghijklmnopqrstuvwxyz{|}~ mrnrtodocode ṃāñūṭḍṇṅ
    aกัขิฃีคึฅืฆุงูจฺฉ็ช่ซ้ฌ๊ญ๋ญุฎ์ฏํฐ๎ฐูฑั่ฒิ้ณี๊ดื๋ติ์ถะทาธำน่ำเบี่แปิํโผใฝ่ไพฟ้ภมยรฤๅลฦวศษสหฬอฮฯๆ ฿๏๐๑๒๓๔๕ ๖๗๘๙๚๛ ก่ป่ฝ้ฟ๊ฬ๋ คฅศ ดตฒ ญฐญานํ ญฐญานํ โสตฺถิํ
    ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝໞໟ

    24!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` Aabcdefghijklmnopqrstuvwxyz{|}~ mrnrtodocode ṃāñūṭḍṇṅ
    aกัขิฃีคึฅืฆุงูจฺฉ็ช่ซ้ฌ๊ญ๋ญุฎ์ฏํฐ๎ฐูฑั่ฒิ้ณี๊ดื๋ติ์ถะทาธำน่ำเบี่แปิํโผใฝ่ไพฟ้ภมยรฤๅลฦวศษสหฬอฮฯๆ ฿๏๐๑๒๓๔๕ ๖๗๘๙๚๛ ก่ป่ฝ้ฟ๊ฬ๋ คฅศ ดตฒ ญฐญานํ ญฐญานํ โสตฺถิํ
    ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝໞໟ

    24!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` Aabcdefghijklmnopqrstuvwxyz{|}~ mrnrtodocode ṃāñūṭḍṇṅ
    aกัขิฃีคึฅืฆุงูจฺฉ็ช่ซ้ฌ๊ญ๋ญุฎ์ฏํฐ๎ฐูฑั่ฒิ้ณี๊ดื๋ติ์ถะทาธำน่ำเบี่แปิํโผใฝ่ไพฟ้ภมยรฤๅลฦวศษสหฬอฮฯๆ ฿๏๐๑๒๓๔๕ ๖๗๘๙๚๛ ก่ป่ฝ้ฟ๊ฬ๋ คฅศ ดตฒ ญฐญานํ ญฐญานํ โสตฺถิํ
    ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝໞໟ


    Roboto Web (อังกฤษ+ละติน+ไทย+ลาว)

    ดาวน์โหลดไฟล์ฟอนต์ (ล่าสุดคือ 20140225)
    RobotoWeb-ttf.tar.gz
    ดาวน์โหลดไฟล์ซอร์ส
  • รุ่นแรก ใส่ตัวละตินยังไม่ครบ : RobotoWeb-src-20140221.tar.gz
  • เพิ่ม Light : RobotoWeb-src-20140225.tar.gz
  • ตัวอย่าง

    24!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` Aabcdefghijklmnopqrstuvwxyz{|}~ mrnrtodocode ṃāñūṭḍṇṅ
    aกัขิฃีคึฅืฆุงูจฺฉ็ช่ซ้ฌ๊ญ๋ญุฎ์ฏํฐ๎ฐูฑั่ฒิ้ณี๊ดื๋ติ์ถะทาธำน่ำเบี่แปิํโผใฝ่ไพฟ้ภมยรฤๅลฦวศษสหฬอฮฯๆ ฿๏๐๑๒๓๔๕ ๖๗๘๙๚๛ ก่ป่ฝ้ฟ๊ฬ๋ คฅศ ดตฒ ญฐญานํ ญฐญานํ โสตฺถิํ
    ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝໞໟ

    24!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` Aabcdefghijklmnopqrstuvwxyz{|}~ mrnrtodocode ṃāñūṭḍṇṅ
    aกัขิฃีคึฅืฆุงูจฺฉ็ช่ซ้ฌ๊ญ๋ญุฎ์ฏํฐ๎ฐูฑั่ฒิ้ณี๊ดื๋ติ์ถะทาธำน่ำเบี่แปิํโผใฝ่ไพฟ้ภมยรฤๅลฦวศษสหฬอฮฯๆ ฿๏๐๑๒๓๔๕ ๖๗๘๙๚๛ ก่ป่ฝ้ฟ๊ฬ๋ คฅศ ดตฒ ญฐญานํ ญฐญานํ โสตฺถิํ
    ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝໞໟ

    24!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` Aabcdefghijklmnopqrstuvwxyz{|}~ mrnrtodocode ṃāñūṭḍṇṅ
    aกัขิฃีคึฅืฆุงูจฺฉ็ช่ซ้ฌ๊ญ๋ญุฎ์ฏํฐ๎ฐูฑั่ฒิ้ณี๊ดื๋ติ์ถะทาธำน่ำเบี่แปิํโผใฝ่ไพฟ้ภมยรฤๅลฦวศษสหฬอฮฯๆ ฿๏๐๑๒๓๔๕ ๖๗๘๙๚๛ ก่ป่ฝ้ฟ๊ฬ๋ คฅศ ดตฒ ญฐญานํ ญฐญานํ โสตฺถิํ
    ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝໞໟ

    Topic: 

    fonts: บันทึก Taeyhom

    ทำฟอนต์เพื่อทดแทน Tahoma ตั้งชื่อว่า "เตยหอม" (Taeyhom)

    พยายามทำให้คอมแพตกับ Tahoma 100% ยกเว้นตัวเลขไทย ของเดิมความกว้างไม่เท่ากัน แต่ของเราทำให้เท่ากันตามมาตรฐาน

    ดาวน์โหลดไฟล์ฟอนต์ (ล่าสุดคือ 20100531)

    ดาวน์โหลดไฟล์ซอร์ส

    • รุ่นร่างเริ่มต้น ยังไม่ได้ทำ hint ยังไม่ได้เกลาละเอียด Taeyhom-src-20100305.tar.gz
    • ทำ hint ตัวธรรมดาเสร็จ Taeyhom-src-20100327.tar.gz บันทึก - ลองเพิ่มจุดอ้างอิงเพื่อมัดติดกับจุดสมอ แต่พบว่าจุดสมอไม่เลื่อนไปตามจุดอ้างอิงที่ถูก hint เราต้องเผื่อเอาเอง
    • รุ่นพักเหนื่อย - ทำ hint ตัวหนาเสร็จ และกลับมาเกลาตัวธรรมดาจนเกือบเสร็จ Taeyhom-src-20100410.tar.gz
      บันทึก - ทดลองใช้ฟังก์ชั่นใหม่ ๆ หลายตัว (MD, MPPEM, SDPVTL, MUL, DIV, IF, EIF) ยังงง ๆ อยู่
    • รุ่นพักยก - เปลี่ยนการวางอักขระยึดตาม tlwg เพื่อให้เข้ากันได้กับเอกสารทั่วไป ตัวธรรมดาเกลาจนดีแล้ว แต่พบปัญหาว่าตัวบางเกินไป จึงเก็บโค๊ดไว้ก่อน รุ่นหน้าจะทำตามมาตรฐานที่ควรเป็นเสียที Taeyhom-src-20100413.tar.gz
      บันทึก
      • ปรับโค๊ด dfont.py หลายจุด ตอนนี้สามารถถอดโค๊ดฟอนต์ทั่วไปได้แล้ว
      • การ hint ที่ผ่านมา เดินเส้น stem แบบไม่ปัดให้เต็ม จุดประสงค์คือให้ดูนุ่มนวล แต่พบปัญหาคือ เราไม่สามารถเติมเส้นให้เต็มในขนาด ppem วิกฤต (14,15,16ppem) คือไม่ขาดนิดนึงก็เกินนิดนึง ถ้าขาด ฟอนต์จะดูบาง ถ้าเกิน ฟอนต์จะดูฟุ้ง รุ่นต่อไปจะปัดให้เส้นเต็มจนถึง 32 ppem แล้วจึงปล่อย น่าจะทำให้ดูดีขึ้น
    • รุ่นพักยก2 - ตัวธรรมดาเปลี่ยนเยอะมาก แต่ตัวหนายังไม่ได้เปลี่ยน รอดูผลสักพัก Taeyhom-src-20100417.tar.gz
      บันทึก
      • เริ่มใช้ function call
      • เปลี่ยนการ hint มาเป็นแบบเต็มเส้นจนถึง 42ppem แล้วจึงปล่อย
      • เริ่มใช้ตาราง prep โดยส่วนใหญ่จะใช้ในการแทนค่า cvt เพื่อให้ขนาดเส้นดูสม่ำเสมอ จนถึง 42ppem (DELTAC)
    • รุ่นอีกนิดเดึยว - ออกเพื่อพักเหนื่อย เหลือเกลาตัวหนา และปรับให้กลไกมาเหมือนกับตัวธรรมดา Taeyhom-src-20100421.tar.gz
      บันทึก
      • สงสัยว่าทำไม่ใช้กับวินโดวส์ไม่สวยเลย
    • เสร็จแล้วครับ - แต่คงยังมีบั๊กอีกเยอะ Taeyhom-src-20100423.tar.gz
    • แก้บั๊กหลายจุด และปรับปรุงความฟุ้ง Taeyhom-src-20100428.tar.gz
    • รุ่นทดลอง - สร้างฟังก์ชั่นหาจุดลงตัวของ stem หน้าหลัง และฟังก์ชั่นปรับเปลี่ยนค่า SROUND ไปตามขนาด ppem ต่าง ๆ ทำให้ไม่จำเป็นต้องกำหนดค่า cvt ของกั้นหน้ากั้นหลังและความกว้างตัวอักษร (ถ้าใช้ได้ผลจะได้เอาไปใช้ในการสร้างฟอนต์ตัวต่อ ๆ ไป งานจะลดลงมาก) Taeyhom-src-20100503.tar.gz
    • รุ่นทดลองที่เริ่มลงตัว - ทำกับตัวหนาอย่างเดียว Taeyhom-src-20100511.tar.gz
    • เสร็จ - รอตรวจบั๊กไปเรื่อย ๆ Taeyhom-src-20100512.tar.gz
    • เปลี่ยนเทคนิกลดความฟุ้งที่หัวอักษร ย้ายการลดความฟุ้งจากเส้นตั้งเป็นเส้นนอน ทำให้ได้ความกลมและแยกแยะอักขระได้ดีขึ้น ความเปรียบต่างสูงขึ้น Taeyhom-src-20100516.tar.gz
    • เก็บรายละเอียด 9-16 ppem และเก็บรายละเอียดอื่น ๆ Taeyhom-src-20100518.tar.gz
    • แก้ไขตัว พ ฟ ให้ชัดขึ้นที่ 11,12,13 ppem Taeyhom-src-20100524.tar.gz
    • แก้ไขปากตัว ก.ไก่ และตัวอื่น ๆ ให้โค้งเล็กน้อยเพื่อให้รับกับตัว ร.เรือ (ทำให้เริ่มไม่เหมือน Tahoma แล้ว) Taeyhom-src-20100531.tar.gz

    ภาพตัวอย่าง
    ภาพจากบราวเซอร์ epiphany และ oo.o
    ตัวธรรมดาที่ hint แล้ว

    ตัวธรรมดา

    ตัวหนาที่ hint แล้ว

    ตัวหนา

    Topic: 

    fonts: บันทึก TlwgTypott

    เอา TlwgTypo จาก ltn: ThaiFonts-Scalable มาทำเรื่อง hinting
    พอจะเริ่ม hint จริง ๆ พบว่าลายเส้นของไทยไม่เข้ากับของฝรั่ง ซึ่งจะทำให้การ hint ยุ่งยาก จึงตัดสินใจสร้างลายเส้นไทยขึ้นมาใหม่ และตั้งชื่อใหม่ว่า TlwgTypott

    ดาวน์โหลดไฟล์ฟอนต์(520421)

    ดาวน์โหลดไฟล์ซอร์ส

    • รุ่นเริ่มต้น ยังไม่มีตัวหนา ยังไม่ได้ปรับละเอียด ฟอนต์ไทย hint ด้วยมือ ส่วนฟอนต์อังกฤษ ใช้ Auto-Instruction TlwgTypott-src-520408.tar.gz (พบว่า Auto-Instruction ของ Fontforge มีประสิทธิภาพดีขึ้นมาก ฟอนต์อังกฤษสวยงามมาก แต่กับฟอนต์ไทย ผลยังแย่อยู่จึง hint เองด้วยมือ)
    • ทำตัวหนา ตัวเอียง และตัวหนาเอียง แต่ใช้ Auto-Instruction ทั้งหมด TlwgTypott-src-520415.tar.gz (รุ่นนี้เอาไฟล์ฟอนต์ต้นฉบับของ Freefont มาใช้ ทำให้ได้รหัสอักขระเพิ่มขึ้น แต่พบบั๊กใน Abiword แสดงผลเพี้ยน ๆ แต่กับ gedit และ Epiphany แสดงปกติ)
    • hint ตัวหนาเสร็จ (เฉพาะตัวอักษรหลัก สระและวรรณวุกต์ไม่ได้ทำ) ใช้วิธี hint แบบไม่ลงจุด เพื่อให้เข้ากันได้กับอักขระโรมันที่ hint ด้วย Auto-Instruction TlwgTypott-src-520421.tar.gz (รุ่นนี้แก้บั๊กของรุ่นก่อนเรื่องการแสดงผลเพี้ยน โดยเอาซอร์สของ TlwgTypo กลับมาทำแทน บั๊กรุ่นก่อนเกิดจากต้นฉบับของ GNU ทำเรื่อง OpenType ไว้ยังไม่สมบูรณ์)
    • แก้บั๊ก konsole แสดงวรรณยุกต์เพี้ยน และบั๊กการ hint อื่นเล็กน้อย TlwgTypott-src-520423.tar.gz

    ภาพตัวอย่าง
    จาก abiword (openoffice แสดงผลเพี้ยน)
    ตัวธรรมดา

    ตัวหนา

    ความรู้ที่ได้

    • Auto-Instruction ใช้ได้ดีกับฟอนต์ที่มีเส้นบาง ๆ แต่ก็ต้องเพิ่ม/ลด Hhint Vhint ช่วยด้วย จึงจะได้ผลดี ลำพังใช้ AutoHint เฉย ๆ ไม่ไหว ประกอบกับการสร้างจุด ต้องแม่นจริง ๆ จึงจะทำให้งานออกมาดูกลมกลืน ซึ่งหลาย ๆ อย่างรวมกันแล้วอาจทำให้เสียเวลามากกว่าการเขียนโปรแกรม hint ด้วยซ้ำไป
    Topic: 

    fonts: บันทึก Waree Sans

    เอาฟอนต์ Waree - วารี จาก ltn: ThaiFonts-Scalable มาทำเรื่อง hinting

    ต้องขออภัยที่ต้องปรับความกว้างฟอนต์จากเดิม เพื่อให้เหมาะกับการทำ hinting ดังนั้นจึงไม่สามารถใช้แทนกันได้อย่างสนิท

    ดาวน์โหลดไฟล์ฟอนต์(รุ่น 20090603)

    ดาวน์โหลดไฟล์ซอร์ส

    • รุ่นเริ่มต้น ยังไม่มีตัวหนา ฟอนต์ไทย hint ด้วยมือ ส่วนฟอนต์อังกฤษ ใช้ของเดิมคือฟอนต์ Bitstream Vera Sans ซึ่ง hint stem ด้วยการทดลงจุด (ของเขาดูนุ่ม แต่ของเราดูแข็งหน่อย) : WareeSans-src-20090517.tar.gz
    • เกลาตัวธรรมดาเสร็จ พยัญชนะตัวหนาเสร็จ freeze เพื่อดูผล : WareeSans-src-20090520.tar.gz
    • ปรับลายเส้นให้ดูนุ่มนวลขึ้น เกลาตัวหนาเสร็จ : WareeSans-src-20090523.tar.gz
    • เกลาส่วนฟุ้ง ปรับช่องไฟให้หลวมขึ้น : WareeSans-src-20090527.tar.gz
    • เกลาละเอียด WareeSans-src-20090603.tar.gz

    ภาพตัวอย่าง
    จาก openoffice.org รุ่น 3.0.1
    ตัวธรรมดา

    ตัวหนา

    Topic: 

    fonts: บันทึก Waree Sans Mono

    เอาลายเส้นจาก Waree Sans มาทำเป็น Monospace แต่ทำเป็นแบบไม่ใช่ความกว้างคงที่แท้ ๆ คือสระและวรรณยุกต์ทำเป็นแบบความกว้างเป็นศูนย์ เพื่อให้ใช้งานกับ Openoffice.org ได้

    ทำแล้วดูแล้วยังไม่ค่อยสวย เพราะความกว้างฟอนต์อังกฤษเดิมแคบไป จึงทำให้สัดส่วนฟอนต์ไทยดูสูงชลูดไปหน่อย

    ดาวน์โหลดไฟล์ฟอนต์(รุ่น 20090613)

    ดาวน์โหลดไฟล์ซอร์ส

    • รุ่นเริ่มต้น ยังไม่มีตัวหนา เอา hint เดิมจาก Waree Sans มาใช้ทั้งหมด ดูหยาบสักหน่อย เพราะเริ่มเหนื่อยแล้ว ;D : WareeSansMono-src-20090609.tar.gz
    • ตัวหนาเสร็จแล้ว แต่เสร็จแบบไม่ดีเลย เนื่องจากความกว้างของภาษาอังกฤษแคบมาก ทำให้ hint ยากมาก WareeSansMono-src-20090613.tar.gz

    ภาพตัวอย่าง
    จาก openoffice.org รุ่น 3.0.1
    ตัวธรรมดา

    ตัวหนา

    Topic: 

    fonts: บันทึก Waree Serif

    เอาภาษาไทยจากฟอนต์ DejaVu Serif Thai และภาษาอังกฤษจาก Bitstream Vera Serif มาทำใหม่ ให้ความสูงฟอนต์ไทยเท่ากับ Waree Sans

    ภาษาไทยดั้งเดิม เอาแบบมาจาก JS-Saksit (คล้าย Angsana New) จึงพยายามปรับให้หน้าตาออกมาระหว่าง JS-Saksit กับ Bitstream Vera Serif

    เนื่องจากเห็นเลขไทยของเก่าสวยมากอยู่แล้ว จึงต้องการคงลักษณะเดิมไว้ แต่มีปัญหาว่าลายเส้นมีความซับซ้อนและมีหลายความหนา hint ออกมาแล้วไม่สวย จึงแก้ปัญหาด้วยการ hint แบบไม่ลงจุด ดังนั้นฟอนต์ชุดนี้จะมี hinting แปลกแยกตรงเลขไทยจะดูนุ่มหน่อยครับ

    ดาวน์โหลดไฟล์ฟอนต์(รุ่น 20091124)

    ดาวน์โหลดไฟล์ซอร์ส

    ภาพตัวอย่าง
    จาก openoffice.org รุ่น 3.0.1
    ตัวธรรมดา

    ตัวหนา

    Topic: 

    fonts: บันทึกการทดลองทำ DejaVuSansMonoThai

    เพิ่งเริ่มทำนะครับ

    ขั้นตอน

    • เอาซอร์สของ DejaVu รุ่น 2.28
    • เอาลายเส้นจาก DejaVuSansThai มาปรับ
    • ทำด้วย fontforge รุ่น 0.0.20080429-1 20081224

    งาน
    งานของฟอนต์ตัวนี้คือ เริ่มศึกษาการทำ ตาราง Lookups - GPOS โดยใช้ภาษาลาวเป็นต้นแบบ คือ

    • การวางสระบนอักษร ป ฟ ฬ จะไม่ได้ใช้ตัวหลบแล้ว
    • ความกว้างสระ ใช้แบบความกว้างคงที่ แต่ใช้ตาราง Lookups - GSUB ดันกลับให้มีความกว้างเป็นศูนย์

    download ttf

    download src

    • DejaVuSansMonoThai-src-520127.tar.gz
      • รุ่นแรก ยังไม่ได้ทำ Instruction ยังไม่มีตัวหนา
      • ลบสระเยื้องซ้ายออก
    • DejaVuSansMonoThai-src-520207.tar.gz
      • ลบสระหลบออกทั้งหมด กลับมาใช้ตาราง GPOS อย่างเดียว (คงเหลือแค่ "ฐ" กับ "ญ" ไม่มีเชิง ที่ยังอยู่ในช่วง private area #F700)
      • ทำ Instruction แล้ว รวมทั้งอักขระลาวตัวที่ยังไม่ได้ทำในไฟล์ต้นฉบับ (แต่สำหรับอักขระลาว เนื่องจากไม่ต้องการดัดแปลง spline ต้นฉบับที่ยังวางจุดไม่สมบูรณ์ จึงยังมีข้อจำกัดในการทำ Instruction เล็กน้อย) การทำ Instruction ในรุ่นนี้ ใช้วิธีคล้ายของ DejaVu แต่จะเขียนโค๊ดลงจุดให้น้อยที่สุดเท่าที่จำเป็นเท่านั้น เพื่อให้พัฒนาได้เร็ว และรูปร่างอักขระเพี้ยนน้อย จึงอาจเห็นการฟุ้งอยู่บ้าง
      • ดัดแปลงตัวอักขระ "บ" "ป" "อ" และ "ฮ" ให้มีเชิงเล็กน้อย เพื่อให้ดูเต็มช่องกับขนาดความกว้างอักขระคงที่
      • ช่วงบ่าย ปรับช่องไฟละเอียดแล้ว (ฝากดาวน์โหลดใหม่ด้วย)

    screenshot
    OpenOffice.org-2.4 แสดงผลที่ ppem ต่าง ๆ
    DejaVuSansMonoThai in OpenOffice.org

    รุ่นล่าสุด 520207
    DejaVuSansMonoThai latest screenshot

    รุ่นแรก
    DejaVuSansMonoThai before instruct

    Topic: 

    fonts: บันทึกการทดลองทำ DejaVuSansThai รุ่นแรก

    บันทึกการแปลงฟอนต์ Waree เป็น DejaVuSansThai รุ่นแรก

    • ใช้หลักการ instruct โดยพยายามยึดตามแนวของ DejaVu เท่าที่พอแกะออก
    • ยังขาดการทำ delta hint เพราะยังทำไม่เป็น ดังนั้นการออกแบบฟอนต์และการ instruct จึงพยายามปรับ เพื่อเลี่ยงการทำ delta hint ซึ่งต้องรอศึกษาต่อไป
      ทำ delta hint ได้แล้ว แต่เสียเวลาและสายตามากเกินไป จึงพยายามออกแบบโค๊ดให้ลดการทำ delta hint ให้มากที่สุด
      ล่าสุดเปลี่ยนแนวคิดการออกแบบเป็น กำหนดจุดให้น้อยที่สุดเพื่อให้ฟอนต์เพี้ยนน้อยที่สุด จึงจำเป็นต้องพึ่งการใช้ delta hint อย่างมาก
    • ลดความสูงของฟอนต์ไทย ให้เท่ากับอังกฤษตัวเล็ก แล้วพยายามย่นความสูงของสระและพยัญชนะลงมา แต่กระนั้นก็ยังล้นระยะห่างระหว่างบรรทัดของ DejaVu อยู่ดี
    • ค่า cvt ของ DejaVu Sans เต็ม 256 ค่าแล้ว แต่มีความจำเป็นต้องเพิ่มค่าของเราเข้าไป ทำให้ต้องอ้างค่าเป็น word แทน byte โค๊ดจึงอาจดูยากขึ้นเล็กน้อย
    • เขียนสคริปต์ไพธอน เล็ก ๆ ชื่อ dfont.py เอาไว้คลี่และเรียงสแต็ก ใช้ได้ผลดีพอควร แต่สคริปต์ยังขาดการตรวจสอบความถูกต้องของ instructing code ซึ่งถ้าใช้ด้วยพารามิเตอร์ --all อาจทำให้ fontforge หยุดการทำงานได้ - รอปรับปรุงต่อไป
    • ยังเหลือบั๊กอีกหลายจุด ตัว ค.ควาย จ.จาน ย.ยักษ์ ยังออกแบบไม่ดี ตัว ร.เรือ ธ.ธง ยัง instruct ได้ไม่ดี และยังไม่ได้ทำตัวหนา ตัวเอียง และตัวหนาเอียง แต่มีความจำเป็นต้องเว้นวรรคนาน จึงบันทึกไว้เพื่อให้จำได้

    ความรู้ที่ได้

    • การทำ TrueType Hinting Instruction ตัวอักษรจะเพี้ยนเสมอ ทั้งนี้เนื่องมาจากการบังคับให้ลงจุดในจอมอนิเตอร์ ดังนั้น การ instruct ก็คือการบอกว่าจะให้เพี้ยนยังไง จึงจะทำให้ดูคมชัด
    • การเคลื่อนจุดด้วยวิธี indirect เช่นคำสั่ง MIRP (ซึ่งต้องอ้างค่าจาก cvt - Control Value Table) มีความแม่นยำแน่นอนกว่าการเคลื่อนค่าแบบ direct (เช่นคำสั่ง MDRP)
    • คำสั่ง ip (Interpolate) จะทำให้ฟอนต์ดูฟุ้ง แต่ระยะที่ได้ แน่นอนกว่าการเคลื่อนจุดแบบ direct (เว้นเสียแต่ถ้าไม่มีการทดลงจุด คืออาร์กิวเมนต์ rnd ควรใช้ MDRP เสมอ ไม่งั้นบางทีอาจเพี้ยน)
    • ถ้ามีความจำเป็นต้องใช้การ Interpolate อาจทำแค่แกนเดียว ส่วนอีกแกนนึงให้ใช้การเคลื่อนแบบ direct แทน
    • พยายามยึดแนวแกนซ้ายขวาและความสูงเฉลี่ยของตัวอักษรไว้ ดังนั้นจึงควรบรรจุค่าความสูงและความกว้างของตัวอักษรในตาราง cvt เสมอ
    • ควรออกแบบความกว้างของตัวอักษรให้ดูสม่ำเสมอ แล้วเขียนโค๊ดโดยดูจากตาราง cvt เป็นสำคัญ แต่จะมีข้อยกเว้นเป็นบางตัวอักษรที่มีหัวอักษรอยู่ตรงกลางฟอนต์ เช่น ค.ควาย หรือ ด.เด็ก อาจต้องยอมทิ้งค่าความกว้างจาก cvt โดยต้องไล่จุดไปตามแนวที่ผ่านหัวอักษรไปเรื่อย ๆ ไม่งั้นเวลาแสดงผลที่ขนาดปอยต์ต่าง ๆ หัวอักษรอาจเยื้องไปทางซ้ายบ้างขวาบ้าง บางครั้งอาจดูลีบติดไปทางแกนอักษรข้างใดข้างหนึ่งบ้าง - อาจแก้ได้ด้วย delta hint
    • การทำ delta hint หรือ grid fitting โดยกำหนดให้เป็น version 1 จะได้ฟอนต์ที่ดูนุ่มนวลดีกว่า version 0
    • ถ้าไม่ทดลงจุดด้วยอาร์กิวเมนต์ rnd ห้ามใช้คำสั่ง SHPIX ที่จุดนั้นเด็ดขาด จะมีปัญหาเลอะตอนพิมพ์ โดยเฉพาะในแนวแกน Y

    ผลการทดลอง - บนลินุกซ์ ความละเอียดจอภาพ 85 dpi

    • ดูดีที่ 12 และ 13 ปอยต์
    • ตั้งแต่ 7 ปอยต์ลงไป อ่านไม่ได้
    • ตั้งแต่ 18 ปอยต์ขึ้นไป ไม่มีปัญหาเรื่องการ hint
    • แย่สุดที่ 14 ปอยต์ ที่เหลือนอกจากนี้ พอดูได้
    • รุ่นล่าสุด (510519) ปรับด้วย delta shift hint พยายามทำให้ดูดีในทุก ๆ ppem แต่ปรับละเอียดที่ 14,15 และ 16 ppem
    • ความกระชับของโค๊ด ขึ้นกับแนวคิดในการไล่เส้นทางเดินของฟอนต์
    • ความสวยของฟอนต์ขึ้นกับความเพียรในการทำ delta hint

    ดาวน์โหลดไฟล์ฟอนต์ ttf ล่าสุด (รุ่น 520401)

    ดาวน์โหลดไฟล์ซอร์ส

    • DejaVuSansThai-src-510331.tar.gz
    • ปรับปรุงช่องไฟ (ยังไม่ดี) ปรับปรุงเรื่องหัวเล็กน้อย (ดีขึ้น) และปรับหลัก instruction บางส่วน (ดีขึ้น)
      DejaVuSansThai-src-510408.tar.gz
    • รุ่นสุดท้ายก่อนทำ delta hint DejaVuSansThai-src-510415.tar.gz
    • เริ่มทำ delta hint (gridfit) ของตัว ค.ควาย ด.เด็ก และปรับปรุงตัว ร.เรือ DejaVuSansThai-src-510416.tar.gz
    • ทำตัวหนาเพิ่ม DejaVuSansThai-src-510420.tar.gz
    • ปรับวิธี hint ใหม่หมด เลียนแบบจาก Serif ซึ่งพยายามเลียนจาก Tahoma อีกที โดยปรับละเอียดที่ 16 ppem และปรับหัวให้ดูนุ่มขึ้น ที่ 14,15 และ 16 ppem
      DejaVuSansThai-src-510519.tar.gz
    • ทำตัวหนาเสร็จ ปรับวิธี hint อีกเล็กน้อย โดยใช้หลัก hint เท่าที่จำเป็น
      รุ่นนี้คิดว่าสมบูรณ์พอจะเอาไปใช้งานได้แล้ว DejaVuSansThai-src-510523.tar.gz
    • ทำรุ่นใหม่ โดยใช้ฟังก์ชั่น SHPIX บีบหัวให้ฟุ้งน้อยลง จึงทำให้ดูเหมือนกับคมขึ้น ตามไปช่วย hint ให้ภาษาลาวเล็กน้อย แต่ยังไม่เสร็จ DejaVuSansThai-src-510612.tar.gz
    • hint ภาษาลาวเสร็จ ปรับแก้เรื่องเส้นขีดฆ่า ตามคำแนะนำของคุณเทพ (แต่ตัวหนายังไม่ได้แก้ คิดว่าจะแก้ใหญ่ในภายหลังครับ) DejaVuSansThai-src-510618.tar.gz
    • เพิ่มตาราง open type (แก้ปัญหา OpenOffice-2.4 "สระอำ" เพี้ยน) และตรวจแก้ข้อมูลตาราง lookup gsub ขาดไป : DejaVuSansThai-src-510823.tar.gz
    • เริ่มการใช้ตาราง GPOS ลดสระหลบทั้งหมด ย้าย ฐ และ ญ ไม่มีฐานขึ้นข้างบน ดัดแปลงลายเส้นเล็กน้อย hint แบบให้กลมกลึง (คมชัดน้อยลง) : DejaVuSansThai-src-520218.tar.gz
    • hint ตัวหนา(เกือบ)เสร็จ (พักไปงานอื่นก่อน) รุ่นนี้พยายามทดลองเขียนโค๊ดไพธอนแบบนำมาใช้ใหม่ แต่เวลากระชั้นมาก โค๊ดข้างในจึงเลอะเทอะมาก (ตัวหนา) : DejaVuSansThai-src-520303.tar.gz
    • เกลา hint ตัวธรรมดาใหม่ โค๊ดเป็นฟังก์ชั่นเพื่อให้การ hint ไปในแนวเดียวกันทุก ๆ อักขระ แก้ปัญหาหัวบางที่ 9-12 ppem ทำให้อ่านง่ายขึ้น ลบการฟุ้งมากไปหน่อยจนทำให้ฟอนต์ดูแห้ง พยายามทำให้ขนาดเส้นตั้งกับเส้นนอนไม่ต่างกันมากนัก ที่ 17-19 ppem ยังไม่ได้แยกวรรณยุกต์เป็น 2 ระดับ (โค๊ดที่เป็นฟังก์ชั่นยังเลอะเทอะอยู่) : DejaVuSansThai-src-520322.tar.gz
    • ทำวรรณยุกต์ระดับสอง ปรับช่องไฟและความกว้างฟอนต์ขนาดเล็ก : DejaVuSansThai-src-520401.tar.gz

    งานที่เหลือ และที่ตั้งใจจะทำ

    • เกลาช่องไฟละเอียด
    • ดูเส้นขาดฟอนต์ขาวพื้นหลังดำ
    • ทำตัวหนาให้มาแนวเดียวกัน

    ภาพตัวอย่างของรุ่นล่าสุด

    ตัวหนา

    ภาพจาก OpenOffice.org รุ่นล่าสุด

    oo ตัวหนา

    ภาพตัวอย่าง รุ่นแรก (จากจอภาพขนาด 85 dpi)








    Topic: 

    fonts: โค๊ดไพธอนที่ใช้ช่วยทำงาน

    สรุปรวมจาก python: เขียนโค๊ดคลี่แสต็กฟอนต์ และ python: โค๊ดฟอนต์ย้อนกลับ
    รวมเป็นไฟล์เดียว ตั้งชื่อว่า dfont.py การทำงานแค่คลี่และเรียงแสต็กใหม่
    เวลาใช้งาน จะต้องเขียนสคริปต์ไพธอนเพิ่มสำหรับฟอนต์แต่ละตัว เพื่อมาเรียกใช้ dfont เป็นมอดูล ปรับปรุง
    • 51-05-06 เพิ่มฟังก์ชั่นการทำ grid fitting ทำให้การเขียนโค๊ดง่ายขึ้น
      เช่นต้องการขยับจุด 20 ไป +8 ที่ฟอนต์ขนาด 9, 10 และ 11 ppem
      เดิมเขียนโค๊ดเป็น
      deltap1 3 20 15 20 31 20 47 เปลี่ยนเป็น
      f_deltap 20 9+8 20 10+8 20 11+8
    โค๊ดมีดังนี้
    $ vi dfont.py
    #!/usr/bin/env python
    """
    This file is only stack render engine.
    Usage:
    1. Decode from instucted code
        ./dfont.py -d INST_CODE.txt > PSEUDO_CODE.txt
    2. Encode from pseudo_code
        ./dfont.py -e PSEUDO_CODE.txt > INST_CODE.txt
    
    
    Implement:
    1 Create FONTNAME.py contain code as followed:
        1.1 import dfont, sys, os
        1.2 cvt_dict = {"NAME": VALUE, ... }
        1.3 pseudo_code_dict = {"CHARACTER_NAME": "PSEUDO CODE TRUETYPE INSTRUCTION", ...}
        1.4 if __name__ == "__main__":
                if sys.argv[1] == "--all":
                    #$0 --all = ENCODE ALL CHARS
                    sfd_file = os.path.basename(sys.argv[0]).split('.',1)[0] + '.sfd'
                    print "Encoding all character in %s" % (sfd_file)
                    dfont.inst_encode_all( sfd_file, pseudo_code_dict, cvt_dict )
                else:
                    #$0 uni0E01 > x.txt = PRINT INSTRUCTION CODE OF uni0E01 TO x.txt
                    print '\n'.join(dfont.inst_encode( pseudo_code_dict[sys.argv[1]], cvt_dict ))
    
    2 Encode:
        2.1 Process all character, this script will modify FONTNAME.sfd
            Usage: ./FONTNAME.py --all
        2.2 Encode each character, for example KO_KAI="uni0E01"
            Usage: ./FONTNAME.py uni0E01 > INSTRUCTED.TXT
    """
    
    import sys
    import os
    
    # put cvt_dict and pseudo_code_dict varirable in FONTNAME.py
    # cvt value example:
    #cvt_dict = {
    #    "base":             10,     #0
    #    "hstem":            8,      #184
    #    "vstem":            96,     #154 
    #    "vstem_small":      27,     #135 
    #    "headstem_small":   11,     #113    =kho
    #    "headdia_small":    180,    #377    =kho
    #    "headhole_small":   254,    #150    =kho
    #    "headneck_kho":     39,     #180    =kho
    #    "hwidth_ko":        164,    #987    =ko,tho 
    #    "hwidth_kho":       14,     #690    =ko,tho 
    #    "hwidth_sho":       108,    #772    =sho
    #    "vheight":          49,     #1208 
    #    "vheight_hi":       54,     #1208   =ko 
    #    "vheight_hi_kho":   54,     #1229   =kho 
    #    "vheight_lo":       88,     #20 
    #    "vheight_lo_sho":   256,    #6  *** NEWVALUE
    #    "head_diff":        131,    #254    =head of character: bo,po
    #    "beak_diff":        9,      #102    =beak of ko,tho
    #    "front_space_ko":   65,     #201    =front spacing of ko,tho
    #    "front_space_kho":  38,     #340    =front spacing of kho
    #}
    
    # pseudo_code example:
    #pseudo_code_dict = {
    #    #ko_kai
    #    "uni0E01": """
    #srp0    26
    #mirp[rp0,min,rnd,grey] front_kai 14
    #mirp[min,rnd,grey]  hstem  12
    #mirp[rp0,rnd,grey]  hwidth_14 25
    #mirp[min,rnd,grey]  hstem 1
    #mdrp[min,rnd,grey]  27
    #srp0   14
    #mdrp[rp0,rnd,grey]  18
    #mdrp[min,rnd,grey]  8
    #mdrp[rp0,rnd,grey]  17
    #mdrp[min,rnd,grey]  10
    #iup[x]
    #svtca[y-axis]
    #mdap[rnd]  1
    #ALIGNRP    13
    #mirp[rp0,rnd,grey]  vheight_shoot    22
    #mirp[min,rnd,grey]  vstem_curve  5
    #srp1    5
    #srp2    13
    #sloop   10
    #ip  19 8 18 9 17 10 2 25 15 12
    #iup[y]
    #""",
    #}
    
    
    #BEGIN
    # inst_dict = { "COMMAND" : ("Description",diff,pops,push), ... }
    # diff: 0=NOOP, 1=1BYTE, 2=2BYTE, ...
    #       -1=FIRST BYTE IS ONE BYTE COUNTER,
    #       -2=FIRST BYTE IS TWO BYTE COUNTER, 
    #       -3=CLEAR STACK
    #       -4=REQUIRE SOME PROCESSING
    inst_dict = {
        "AA" :       ("Adjust Angle", 1, 1, 0),
        "ABS" :      ("ABSolute value", 0, 1, 1),
        "ADD" :      ("ADD", 1, 2, 1),
        "ALIGNPTS" : ("ALIGN Points", 2, 2, 0),
        "ALIGNRP" :  ("ALIGN to Reference Point", 1, 1, 0),
        "AND" :      ("logical AND", 1, 2, 1),
        "CALL" :     ("CALL function", 1, 1, 0),
        "CEILING" :  ("CEILING", 0, 1, 1),
        "CINDEX" :   ("Copy the INDEXed element to the top of the stack", 1, 1, -4),
        "CLEAR" :    ("CLEAR the stack", -3, 0, 0),
        "DEBUG" :    ("DEBUG call", 1, 1, 0),
        "DELTAC1" :  ("DELTA exception C1", -2, 0, 0),
        "DELTAC2" :  ("DELTA exception C2", -2, 0, 0),
        "DELTAC3" :  ("DELTA exception C3", -2, 0, 0),
        "DELTAP1" :  ("DELTA exception P1", -2, 0, 0),
        "DELTAP2" :  ("DELTA exception P2", -2, 0, 0),
        "DELTAP3" :  ("DELTA exception P3", -2, 0, 0),
        "DEPTH" :    ("DEPTH of the stack", 0, 0, 1),
        "DIV" :      ("DIVide", 1, 2, 1),
        "DUP" :      ("DUPlicate top stack element", 0, 1, 1),
        "EIF" :      ("End IF", 0, 0, 0),
        "ELSE" :     ("ELSE clause", 0, 0, 0),
        "ENDF" :     ("END Function definition", 0, 0, 0),
        "EQ" :       ("EQual", 1, 2, 1),
        "EVEN" :     ("EVEN", 0, 1, 1),
        "FDEF" :     ("Function DEFinition", 1, 1, 0),
        "FLIPOFF" :  ("set the auto FLIP Boolean to OFF", 0, 0, 0),
        "FLIPON" :   ("set the auto FLIP Boolean to ON", 0, 0, 0),
        "FLIPPT" :   ("FLIP PoinT", 1, 1, 0),
        "FLIPRGOFF" :    ("FLIP RanGe OFF", 2, 2, 0),
        "FLIPRGON" : ("FLIP RanGe ON", 2, 2, 0),
        "FLOOR" :    ("FLOOR", 2, 2, 0),
        "GC" :       ("Get Coordinate projected onto the projection vector", 0, 1, 1),
        "GETINFO" :  ("GET INFOrmation", 0, 1, 1),
        "GFV" :      ("Get Freedom Vector", 0, 0, 2),
        "GPV" :      ("Get Projection Vector", 0, 0, 2),
        "GT" :       ("Greater Than", 1, 2, 1),
        "GTEQ" :     ("Greater Than or EQual", 1, 2, 1),
        "IDEF" :     ("Instruction DEFinition", 1, 1, 0),
        "IF" :       ("IF test", 1, 1, 0),
        "INSTCTRL" : ("INSTRuction execution ConTRoL", 2, 2, 0),
        "IP" :       ("Interpolate Point", 1, 1, 0),
        "ISECT" :    ("moves point p to the InterSECTion of two lines", 5, 5, 0),
        "IUP" :      ("Interpolate Untouched Points through the outline", 0, 0, 0),
        "JMPR" :     ("JuMP Relative", 1, 1, 0),
        "JROF" :     ("Jump Relative On False", 1, 1, 0),
        "JROT" :     ("Jump Relative On True", 3, 3, 0),
        "LOOPCALL" : ("LOOP and CALL function", 2, 2, 0),
        "LT" :       ("Less Than", 1, 2, 1),
        "LTEQ" :     ("Less Than or Equal", 1, 2, 1),
        "MAX" :      ("MAXimum of top two stack elements", 1, 2, 1),
        "MD" :       ("Measure Distance", 1, 2, 1),
        "MDAP" :     ("Move Direct Absolute Point", 1, 1, 0),
        "MDRP" :     ("Move Direct Relative Point", 1, 1, 0),
        "MIAP" :     ("Move Indirect Absolute Point", 2, 2, 0),
        "MIN" :      ("MINimum of top two stack elements", 1, 2, 1),
        "MINDEX" :   ("Move the INDEXed element to the top of the stack", 1, 1, 3),
        "MIRP" :     ("Move Indirect Relative Point", 2, 2, 0),
        "MPPEM" :    ("Measure Pixels Per EM", 0, 0, 1),
        "MPS" :      ("Measure Point Size", 0, 0, 1),
        "MSIRP" :    ("Move Stack Indirect Relative Point", 1, 1, 0),
        "MUL" :      ("MULtiply", 1, 2, 1),
        "NEG" :      ("NEGate", 0, 1, 1),
        "NEQ" :      ("Not EQual", 1, 2, 1),
        "NOT" :      ("logical NOT", 0, 1, 1),
        "NPUSHB" :   ("PUSH N Bytes", -1, 0, 0),
        "NPUSHW" :   ("PUSH N Words", -1, 0, 0),
        "NROUND" :   ("No ROUNDing of value", 0, 1, 1),
        "ODD" :      ("ODD", 0, 1, 1),
        "OR" :       ("logical OR", 1, 2, 1),
        "POP" :      ("POP top stack element", 1, 1, 0),
        "PUSHB" :    ("PUSH Bytes", -4, 0, 0),
        "PUSHW" :    ("PUSH Words", -4, 0, 0),
        "RCVT" :     ("Read Control Value Table entry", 0, 1, 1),
        "RDTG" :     ("Round Down To Grid", 0, 0, 0),
        "ROFF" :     ("Round OFF", 0, 0, 0),
        "ROLL" :     ("ROLL the top three stack elements", 0, 3, 3),
        "ROUND" :    ("ROUND value", 0, 1, 1),
        "RS" :       ("Read Store", 0, 1, 1),
        "RTDG" :     ("Round To Double Grid", 0, 0, 0),
        "RTG" :      ("Round To Grid", 0, 0, 0),
        "RTHG" :     ("Round To Half Grid", 0, 0, 0),
        "RUTG" :     ("Round Up To Grid", 0, 0, 0),
        "S45ROUND" : ("Super ROUND 45 degrees", 1, 1, 0),
        "SANGW" :    ("Set Angle Weight", 1, 1, 0),
        "SCANCTRL" : ("SCAN conversion ConTRoL", 1, 1, 0),
        "SCANTYPE" : ("SCANTYPE", 1, 1, 0),
        "SCFS" : ("Sets Coordinate From the Stack using projection vector and freedom vector", 2, 2, 0),
        "SCVTCI" :   ("Set Control Value Table Cut-In", 1, 1, 0),
        "SDB" :      ("Set Delta Base in the graphics state", 1, 1, 0),
        "SDPVTL" :   ("Set Dual Projection Vector To Line", 2, 2, 0),
        "SDS" :      ("Set Delta Shift in the graphics state", 1, 1, 0),
        "SFVFS" :    ("Set Freedom Vector From Stack", 2, 2, 0),
        "SFVTCA" :   ("Set Freedom Vector To Coordinate Axis", 0, 0, 0),
        "SFVTL" :    ("Set Freedom Vector To Line", 2, 2, 0),
        "SFVTP" :    ("Set Freedom Vector To Projection Vector", 0, 0, 0),
        "SHC" :      ("SHift Contour using reference point", 1, 1, 0),
        "SHP" :      ("SHift Point using reference point", 1, 1, 0),
        "SHPIX" :    ("SHift point by a PIXel amount", 2, 2, 0),
        "SHZ" :      ("SHift Zone using reference point", 1, 1, 0),
        "SLOOP" :    ("Set LOOP variable", 1, 1, 0),
        "SMD" :      ("Set Minimum Distance", 1, 1, 0),
        "SPVFS" :    ("Set Projection Vector From Stack", 2, 2, 0),
        "SPVTCA" :   ("Set Projection Vector To Coordinate Axis", 0, 0, 0),
        "SPVTL" :    ("Set Projection Vector To Line", 2, 2, 0),
        "SROUND" :   ("Super ROUND", 1, 1, 0),
        "SRP0" :     ("Set Reference Point 0", 1, 1, 0),
        "SRP1" :     ("Set Reference Point 1", 1, 1, 0),
        "SRP2" :     ("Set Reference Point 2", 1, 1, 0),
        "SSW" :      ("Set Single Width", 1, 1, 0),
        "SSWCI" :    ("Set Single Width Cut-In", 1, 1, 0),
        "SUB" :      ("SUBtract", 1, 2, 1),
        "SVTCA" :    ("Set freedom and projection Vectors To Coordinate Axis", 0, 0, 0),
        "SWAP" :     ("SWAP the top two elements on the stack", 0, 2, 2),
        "SZP0" :     ("Set Zone Pointer 0", 1, 1, 0),
        "SZP1" :     ("Set Zone Pointer 1", 1, 1, 0),
        "SZP2" :     ("Set Zone Pointer 2", 1, 1, 0),
        "SZPS" :     ("Set Zone PointerS", 1, 1, 0),
        "UTP" :      ("UnTouch Point", 1, 1, 0),
        "WCVTF" :    ("Write Control Value Table in Funits", 1, 1, 0),
        "WCVTP" :    ("Write Control Value Table in Pixel units", 2, 2, 0),
        "WS" :       ("Write Store", 2, 2, 0),
    }
    
    stack1_command = ("NPUSHB", "NPUSHW")
    stack2_command = ("PUSHB", "PUSHW")
    
    arg_1_command = ("MDAP", "MDRP")
    arg_2_command = ("MIAP", "MIRP")
    
    delta_command = ("F_DELTA",)
    #step_list USE IN SPECIAL PSUEDO FUNCTION f_delta
    step_list = [-8, -7, -6, -5, -4, -3, -2, -1, 1, 2, 3, 4, 5, 6, 7, 8]
    
    normal_command = []
    for i in range(6):
        normal_command.append( [ j for j in inst_dict.keys() if inst_dict[j][1]==i ] )
    
    #           -1=FIRST BYTE IS ONE BYTE COUNTER,
    #           -2=FIRST BYTE IS TWO BYTE COUNTER, 
    #           -3=CLEAR STACK
    #           -4=REQUIRE PROCESS
    pop_command = []
    pop_command.append([])
    for i in range(-1, -4, -1):
        pop_command.append( [ j for j in inst_dict.keys() if inst_dict[j][1]==i ] )
    
    
    def usage(prog_name):
        print """\
    Usage: %s [-d CODE | [-e] PSUEDO_CODE]
    """ % (prog_name)
        return
    
    def line_format(cmd,stack,desc):
        #STRING, LIST, STRING
        return "%-24s %-10s ;%10s" % (cmd, "  ".join(stack), desc,)
    
    def f_delta(first_cmd, l):
        #PSUEDO COMMAND TO PROCESS DELTA FUNCTION
        #
        #first_cmd = PSUEDO COMMAND, ex: f_deltap1 = deltap1
        #l = LIST OF ARGUMENT (INCLUDE SELF UN-UPPERCASE COMMAND IN FIRST ARGUMENT)
        #
        #usage: 
        #   f_deltap 0 16+8     #deltap1 MOVE POINT 0 AT 16 PPEM +8
        #real code will be:
        #   DELTAP1  1 0 127
        #
        d1_list = []
        d2_list = []
        d3_list = []
        first_cmd = first_cmd[2:]   #TRIM F_ OUT
        l.pop(0)
        while len(l) > 0:
            point = l.pop(0)
            pstep = l.pop(0)
            if '+' in pstep or '-' in pstep:
                if '+' in pstep:
                    ppem, no_of_step = pstep.split('+')
                    ppem = int(ppem)
                    no_of_step = int(no_of_step)
                else:
                    ppem, no_of_step = pstep.split('-')
                    ppem = int(ppem)
                    no_of_step = -int(no_of_step)
                if ppem < 9:
                    raise ValueError('ppem must greater than 9, %s: %s %s' % (first_cmd, point, pstep,))
                if abs(no_of_step) > 8:
                    raise ValueError('no_of_step must be between +8 and -8, %s: %s %s' % (first_cmd, point, pstep,))
                if no_of_step == 0:
                    raise ValueError('no_of_step must not be 0, %s: %s %s' % (first_cmd, point, pstep,))
                num = (ppem-9)*16 + step_list.index(no_of_step)
                if num < 256:
                    d1_list.extend([point,str(num)])
                elif num < 512:
                    d2_list.extend([point,str(num)])
                elif num < 1024:
                    d3_list.extend([point,str(num)])
                else:
                    raise ValueError('Number of delta point exceed 1024, %s' % (num,))
            else:
                raise SyntaxError('Please use + or - in f_delta second argument, %s %s' % (point, pstep,))
        new_l = []
        if d1_list:
            new_l.append(first_cmd+'1')
            new_l.append(str(len(d1_list)/2))
            new_l.extend(d1_list)
        if d2_list:
            new_l.append(first_cmd+'2')
            new_l.append(str(len(d2_list)/2))
            new_l.extend(d2_list)
        if d3_list:
            new_l.append(first_cmd+'3')
            new_l.append(str(len(d3_list)/2))
            new_l.extend(d3_list)
        return  new_l[0], new_l
    
    def inst_decode(txt):
        """Decode TrueType Instruction code into simpler code"""
        txt_list = txt.split("\n")
        new_list = []
        commentlist = []
        stack_list = []
        sloop = 0
        i = 0
        while i < len(txt_list):
            if "[" in txt_list[i]:
                c1,c2 = txt_list[i].strip().split("[",1)
            else:
                c1,c2 = txt_list[i].strip(), ""
            #SKIP EMPTY LINE
            if c1 == "":
                i += 1
                continue
            #STACK: NPUSHB, NPUSHW
            if c1 in stack1_command:
                i += 1
                n = int(txt_list[i].strip())
                i += 1
                while n > 0:
                    stack_list.append(txt_list[i].strip())
                    i += 1
                    n -= 1
                continue
            #STACK2: PUSHB, PUSHW
            if c1[:5] in stack2_command:
                n = int(txt_list[i].strip()[6:])
                i += 1
                while n > 0:
                    stack_list.append(txt_list[i].strip())
                    i += 1
                    n -= 1
                continue
            temp_list = []
            #POP ONE
            if c1 in pop_command[1]:
                idx = stack_list.pop()
                temp_list = [idx]
                for j in range(int(idx)):
                    temp_list.append(stack_list.pop()) 
                new_list.append(line_format(txt_list[i],temp_list,inst_dict[c1][0]))
                i += 1
                continue
            #POP PAIR
            elif c1 in pop_command[2]:
                idx = stack_list.pop()
                temp_list = [idx]
                for j in range(int(idx)):
                    temp_list.append(stack_list.pop()) 
                    temp_list.append(stack_list.pop()) 
                new_list.append(line_format(txt_list[i],temp_list,inst_dict[c1][0]))
                i += 1
                continue
            #POP ALL (CLEAR STACK)
            elif c1 in pop_command[3]:
                stack_list = []
                new_list.append(line_format(txt_list[i],temp_list,inst_dict[c1][0]))
                i += 1
                continue
    
            #NORMAL COMMAND
            if c1 in normal_command[0]:
                count = 0
            elif c1 in normal_command[1]:
                count = 1 
            elif c1 in normal_command[2]:
                count = 2 
            elif c1 in normal_command[3]:
                count = 3 
            elif c1 in normal_command[4]:
                count = 4 
            elif c1 in normal_command[5]:
                count = 5 
            else:
                count = -1
                #print 'count-1:',c1
                new_list.append('count-1:%s' % (c1,))
            if count > 0:
                if sloop > 0:
                    count += sloop-1
                    sloop = 0
            while count > 0:
                if stack_list == []:
                    #print temp_list
                    new_list.extend(temp_list)
                    break
                cnum = stack_list.pop()
                temp_list.append(cnum)
                if c1 == 'SLOOP':
                    sloop = int(cnum)
                count -= 1
            new_list.append(line_format(txt_list[i],temp_list,inst_dict[c1][0]))
            i += 1
        return new_list
        
    def stack_format(stack_list):
    
        def flush(new_list, cmd_list, ind, cur_ind):
            #if len(cmd_list)==0: return [], [], cur_ind
            if ind == 0:
                temp = ['PUSHB_','NPUSHB']
            else:
                temp = ['PUSHW_','NPUSHW']
            if len(cmd_list) < 8:
                new_list.append('%s%s' % (temp[0],len(cmd_list),))
            else:
                new_list.append(temp[1])
                new_list.append(' %s' % (len(cmd_list),))
            new_list.extend(cmd_list)
            return new_list, [], cur_ind
    
        if len(stack_list)==0: return []
        n = 0
        new_list = []
        cmd_list = []
        stack_list.reverse()
        if int(stack_list[n]) < 256:
            ind = 0     #BYTE
        else:
            ind = 1     #WORD
        while n < len(stack_list):
            if int(stack_list[n]) < 256:
                cur_ind = 0     #BYTE
            else:
                cur_ind = 1     #WORD
            if ind == cur_ind:
                cmd_list.append(' %s' % (stack_list[n],))
            else:
                new_list, cmd_list, ind = flush(new_list, cmd_list, ind, cur_ind)    #FLUSH
                cmd_list.append(' %s' % (stack_list[n],))
            n += 1
        new_list, cmd_list, ind = flush(new_list, cmd_list, ind, cur_ind)    #FLUSH
        return new_list 
    
    def inst_encode(txt,cvt_dict={}):
        """Encode simple code into TrueType Instruction code"""
        if cvt_dict == {}:
            print "WARNING: cvt_dict is empty, please supply cvt_dict argument"
        comment_list = ['#',';']    #COMMENT CHARACTER
        flush_list = ['SVTCA']      #FLUSH STACK
        stack_list = []
        new_list = []
        cmd_list = []
        txt_list = txt.split('\n')
        for line in txt_list:
            line = line.replace("\t"," ")
            if " " in line:
                l = line.split(" ")
            else:
                l = [line] 
            l = [ j for j in l if j != "" ]
            if l == []:
                continue
            if l[0][0] in comment_list: #BYPASS COMMENT
                continue
            for f in flush_list:    #?FLUSH STACK
                if f == l[0][:len(f)]:
                    new_list.extend(stack_format(stack_list))
                    stack_list = []
                    new_list.extend(cmd_list)
                    cmd_list = []
                    break
            if '[' in l[0]:         #TO UPPERCASE
                ltemp = l[0].split('[',1)
                first_cmd = ltemp[0].upper()
                first_word = first_cmd+'['+ltemp[1]
            else:
                first_word = l[0].upper()
                first_cmd = first_word
            #CHECK SPECIAL COMMAND ---------------------------------------
            # f_delta -> f_deltap1 = deltap1, ...
            for temp in delta_command:
                if temp in first_word:
                    first_word, l = f_delta(first_word, l)
        
            #END CHECK SPECIAL COMMAND -----------------------------------
            cmd_list.append(first_word)     #KEEP COMMAND
            l.pop(0)                        #PROCESS REST STACK NUM
    #
            temp_arg_list = []
            for element in l:
                if element[0] in comment_list:
                    break 
                else:
                    temp_list = element.split('[',1)
                    if element in cvt_dict.keys():                  #CHECK CVT VALUE
                        stack_list.append(cvt_dict[element])
                        temp_arg_list.append(element)
                    elif temp_list[0].upper() in inst_dict.keys():  #TRAP DELTA COMMAND
                        temp_list[0] = temp_list[0].upper()
                        element = '['.join(temp_list)
                        cmd_list.append(element)
                    else:
                        stack_list.append(element)
                        temp_arg_list.append(element)
            #TEST NUMBER OF PARAMETER
            if first_cmd in arg_1_command:
                if len(temp_arg_list) != 1:
                    raise ValueError('%s must take 1 argument, %s' % (first_word, temp_arg_list,))
            elif first_cmd in arg_2_command:
                if len(temp_arg_list) != 2:
                    raise ValueError('%s must take 2 arguments, %s' % (first_word, temp_arg_list,))
            #
        if stack_list != []:
            new_list.extend(stack_format(stack_list))
        new_list.extend(cmd_list)
        return new_list
    
    
    def inst_encode_all(sfd_file, pseudo_code_dict={}, cvt_dict={}):
        """Encode all characters in pseudo_code_dict, modify FONTNAME.sfd."""
        if os.path.isfile(sfd_file):
            sfd = open(sfd_file).read().split('\n')
            sfd_bak = sfd[:]
        else:
            print "File %s.sfd is not existed, script aborted." % (sfd_file,)
            sys.exit[1]
        for chr,txt in pseudo_code_dict.iteritems():
            search_line = 'StartChar: %s' % (chr,)
            if search_line in sfd:
                line = sfd.index(search_line)
                while line < len(sfd):
                    if sfd[line] == "TtInstrs:":
                        temp_sfd = sfd[:line+1]
                        #print temp_sfd[-2:]
                        temp_sfd += inst_encode(txt,cvt_dict)
                        line += 1
                        while sfd[line] != "EndTTInstrs":
                            line += 1
                        temp_sfd += sfd[line:]
                        sfd = temp_sfd[:]
                        break
                    elif sfd[line] in ["Back","Fore"]:
                        temp_sfd = sfd[:line] \
                                   + ["TtInstrs:"] \
                                   + inst_encode(txt,cvt_dict) \
                                   + ["EndTTInstrs"]+sfd[line:]
                        sfd = temp_sfd[:]
                        break
                    elif sfd[line] == "EndChar":
                        print "sfd file format error at %s" % (chr,)
                        break
                    else:
                        line += 1
            else:
                print "Character %s not found, script aborted." % (chr,)
                sys.exit(1)
        if sfd != sfd_bak:
            os.rename(sfd_file, "%s.bak" % (sfd_file,))
            f = open(sfd_file,"w")
            f.write("\n".join(sfd))
            f.close()
            print "%s modified." % (sfd_file,)
        else:
            print "No modified."
    
    
    if __name__ == "__main__":
        if sys.argv[1] == "-d":
            #DECODE
            #$0 -d x.txt > d.txt = PRINT PSEUDO_CODE FROM x.txt TO d.txt
            f = open(sys.argv[2])
            txt = f.read()
            f.close()
            print '\n'.join(inst_decode(txt))
        elif sys.argv[1] == "-e":
            #ENCODE
            #$0 -e d.txt > x.txt = PRINT INSTRUCTED CODE FROM PSEUDO_CODE d.txt TO x.txt
            f = open(sys.argv[2])
            txt = f.read()
            f.close()
            print '\n'.join(inst_encode(txt))
        else:
            #DEFAULT IS ENCODING
            #$0 -e d.txt > x.txt = PRINT INSTRUCTED CODE FROM PSEUDO_CODE d.txt TO x.txt
            f = open(sys.argv[1])
            txt = f.read()
            f.close()
            print '\n'.join(inst_encode(txt))
    
    Topic: 

    บันทึกการ instruct ฟอนต์

    เที่ยวนี้ไม่มีอะไร บันทึกตัวอย่างการ instruct เอาไว้ดูเพื่ออ้างอิงเฉย ๆ

    ตัวอย่าง DejaVuSans อักขระ n

    โค๊ด

    NPUSHB
     25
     3
     9
     0
     3
     14
     1
     6
     135
     14
     17
     184
     12
     188
     10
     1
     2
     8
     0
     78
     13
     9
     8
     11
     70
     20
    SRP0
    MIRP[rp0,min,rnd,grey]
    MIRP[min,rnd,grey]
    SHP[rp2]
    MIRP[rp0,rnd,grey]
    MIRP[min,rnd,grey]
    IUP[x]
    SVTCA[y-axis]
    MDAP[rnd]
    ALIGNRP
    MIRP[rnd,grey]
    MIRP[rp0,rnd,grey]
    MDRP[rnd,grey]
    MIRP[min,rnd,grey]
    SRP1
    SRP2
    SLOOP
    IP
    IUP[y]
    PUSHB_5
     96
     21
     207
     21
     2
    SVTCA[x-axis]
    DELTAP1
    

    outline

    x-direction instruction

    y-direction instruction

    คลี่สแต็กให้พออ่านง่าย

    CODE                   RP0     STACK      DESCRIPTION
                                               (x-axis is default direction)
    SRP0                           20         Set Reference Point 0
    MIRP[rp0,min,rnd,grey] (20)    70 11      Move Indirect Relative Point
    MIRP[min,rnd,grey]     (11)    8 9
    SHP[rp2]               (11)    13         SHift Point using reference point
    MIRP[rp0,rnd,grey]     (11)    78 0
    MIRP[min,rnd,grey]     (0)     8 2
    IUP[x]                                    Interpolate Untouched Points through the outline
    
    SVTCA[y-axis]                             Set freedom and projection Vectors To Coordinate Axis
    MDAP[rnd]                      1          Move Direct Absolute Point
    ALIGNRP                (1)     10         ALIGN to Reference Point
    MIRP[rnd,grey]         (1)     188 12
    MIRP[rp0,rnd,grey]     (1)     184 17
    MDRP[rnd,grey]         (17)    14
    MIRP[min,rnd,grey]     (17)    135 6
    SRP1                           1          Set Reference Point 1
    SRP2                           14         Set Reference Point 2
    SLOOP                          3          Set LOOP variable
    IP                             0 9 3      Interpolate Point
    IUP[y]                                    Interpolate Untouched Points through the outline
    
    SVTCA[x-axis]
    DELTAP1                       2 21 207 21 96    DELTA exception P1
    


    อธิบาย deltap

    The 8 bit arg component of the DELTA instructions decomposes into two parts. 
    The first 4 bits represent the relative number of pixels per em at which the exception is applied. 
    The second 4 bits represent the magnitude of the change to be made. The structure of the arg is shown in FIGURE 26.
    ppem = pointSize * dpi / 72 
    
    207 = 1100 1111
    1100=12 (9+12=21ppem)
    1111=15 = 8step = 8/64 of pixel    (0=-8, 1=-7, ... 14=+7, 15=+8)
    
    96 = 0110 0000
    0110=6 (9+6=15ppem)
    0000=0 = -8step = -8/64 of pixel
    

    แปลว่า
    1.เลื่อนจุด 21 ไป 8step ที่ขนาดฟอนต์ 21 ppem (จอ Mac75dpi=21pt Windows96dpi~16pt Linux(จอผม85dpi)~18pt)
    2. เลื่อนจุด 21 ไป -8step ที่ขนาดฟอนต์ 15 ppem (จอ Mac75dpi=15pt Windows96dpi~11pt Linux(จอผม85dpi)~13pt)

    ตาราง cvt

    ITEM            VALUE           DESCRIPTION
    8               184             stem width
    70              186             left spacing
    78              938             outer width
    135             156             top stem thick
    184             1147            straight vertical height
    188             1120            outer height
    
    Topic: 

    fonts: ตัวอย่างการ hint ก.ไก่

    มีค่า cvt ของฟอนต์ DejaVu Sans ที่เกี่ยวข้อง ทำเป็นตัวแปรแบบดิกชันนารีในไพธอน คือ
    cvt_dict = {
        ...
        "front_kai":      11,     #113    =front spacing of ko_kai 
        "hstem":          8,      #184    =horizontal stem width
        "w_881":          163,    #881    =width of ko kai
        "vheight_shoot":  184,    #1147   =overshoot height
        "vstem_curve":    185,    #156    =curve vertical stem width
        ...
    }
    
    ค่า cvt ของฟอนต์ ดูได้จากเมนูของ FontForge คือ Hints -> Edit 'cvt' ... โดยจะเรียงตั้งแต่ลำดับที่ 0 เป็นต้นไป
    ค่า cvt ของ ก.ไก่ข้างต้น คือ กำหนดให้ลำดับที่ 11 (ซึ่งมีค่า 113) เป็นระยะช่องไฟด้านหน้า เป็นต้น โครง ก.ไก่ ตัวอย่างจะเริ่มด้วยการ hint ในแนวแกน X ก่อน (เป็นค่าปริยาย) จะแสดงเป็นโค๊ด instruction แบบจำลอง เพื่อให้ดูง่าย เวลาใช้งานจริง ก็นำไปเขียนเป็นโค๊ดในไพธอน โปรแกรม dfont.py จะคลี่แสต็กและเรียงออกมาเป็นโค๊ดจริง ๆ อีกที แนวแกน X
    เส้นทาง hint ในแนวแกน X จุดเริ่มต้นคือจุดที่ 26 (จุดสุดท้ายคือ 25 + 1)
    srp0                26
    
    จากจุดเริ่มต้น จะเคลื่อนจุดอ้างอิง rp0 ไปยังจุดที่ใกล้ขอบซ้ายที่สุด คือจุด 18 เพื่อกั้นเป็นระยะช่องไฟด้านหน้า ด้วยค่า cvt คือ front_kai
    การเคลื่อนด้วยการอ้างอิงค่า คำสั่งคือ MIRP
    การเคลื่อนจุดอ้างอิงไปด้วย ใช้อาร์กิวเมนต์ rp0
    การปัดเศษให้ลงจุด (round) ใช้อาร์กิวเมนต์ rnd
    การแรเงาพื้นที่ ใช้อาร์กิวเมนต์ grey (ปกติควรเป็น white แต่ DejaVu ใฃ้ grey เสมอ จึงใช้ตาม เพื่อกันสับสน)
    ค่า cvt ที่ใช้ คือ front_kai
    จุดที่จะเคลื่อนไป คือ 18
    mirp[rp0,min,rnd,grey]  front_kai 18
    
    จุดที่จะไปต่อคือ จุด 8 แต่เนื่องจากเมื่อเคลื่อนไปแล้ว ไม่มีจุดที่จะไปต่อ เราจึงไม่ต้องเคลื่อนจุด rp0 ไปด้วย จึงไม่ต้องใส่อาร์กิวเมนต์ rp0
    ระยะของปาก ก.ไก่ ไม่จำเป็นต้องเป็นค่าที่แน่นอนนัก เราจึงไม่ต้องอ้างค่า cvt จึงใช้คำสั่ง MDRP
    ปัดเศษด้วย ใช้ rnd
    แรเงา ใช้ grey
    จุดที่เคลื่อนไปคือ 8
    mdrp[min,rnd,grey]  8
    
    ตอนนี้ rp0 ยังอยู่ที่เดิม คือ จุด 18 เราต้องเคลื่อนไปต่อที่จุด 17 และ 10 ตามลำดับ แต่หากเราเคลื่อนไปจุด 17 ก่อน แล้วต่อไปที่ 10 จะทำให้ระยะที่ถูกทด (round) แล้ว มีค่ามากเกินไป ทำให้ปาก ก.ไก่ ไม่สวยงาม เราจึงใช้การเคลื่อนไปที่จุด 10 ก่อน แล้วจึงย้อนมาที่ 17 อีกครั้งหนึ่ง ทำให้ได้ภาพที่สวยงามกว่า
    mdrp[rp0,rnd,grey]  10
    mdrp[min,rnd,grey]  17
    
    จุดที่จะไปต่อคือจุด 14 แต่ตอนนี้จุดอ้างอิง rp0 มาอยู่ที่จุด 10 แล้ว หากเราเคลื่อนจากจุดนี้ไปเลย จะทำให้ระยะทดไม่แน่นอน จึงควรย้อนกลับไปที่จุดแรกคือ 18 จะดีกว่า
    srp0                18
    mdrp[rp0,rnd,grey]  14
    
    ต่อไปเป็นการกำหนดความหนาของเส้นตั้ง (hstem) ต้องใช้ค่า cvt เสมอ
    ต้องอ้างอิงจาก cvt คำสั่งคือ MIRP
    ไม่ต้องย้าย rp0 ไปด้วย เพราะไม่มีจุดที่จะไปต่อ จึงไม่ต้องใช้อาร์กิวเมนต์ rp0
    ถึงแม้ขนาดเส้นจะบางอย่างไร การแสดงผลต้องกำหนดค่าให้อย่างน้อย 1 จุดเสมอ ใช้อาร์กิวเมนต์ min
    แรเงาใช้ grey
    mirp[min,rnd,grey]  hstem  12
    
    ต่อไปเป็นการกำหนดความกว้างของตัวอักษร ต้องใช้ cvt เสมอ โดยต้องย้ายจุด rp0 ไปด้วย เพื่อไปทำงานต่อ โดยจะกำหนดขนาดให้คลุมความกว้างรวมก่อน แล้วจึงย้อนมากำหนดความหนาของเส้นตั้งตัวหลังอีกครั้งหนึ่ง
    mirp[rp0,rnd,grey]  w_881 25
    mirp[min,rnd,grey]  hstem  1
    
    กั้นเป็นฃ่องไฟด้านหลัง โดยไม่ต้องกำหนดระยะ min และเผื่อการแรเงาเป็น white เพื่อให้มีช่องว่างอย่างน้อย 1 จุดคั่นกับอักษรตัวถัดไป มีประโยชน์สำหรับฟอนต์ที่มีการทดลงจุดในแนวแกน X มาก ๆ ซึ่งจะทำให้ล้นความกว้างที่มีอยู่ (คำสั่งนี้คิดเอง เพื่อให้ไม่ต้องทำ delta hint ตามแบบของ DejaVu)
    mdrp[rnd,white]     27
    
    เกลี่ยจุดที่เรายังไม่ได้อ้างอิงในแนวแกน X ซึ่งจะใช้คำสั่งสี้ปิดท้ายเสมอ (IUP คือ Interpolate Untouched Point)
    IUP[x]
    
    แนวแกน Y
    เส้นทาง hint ในแนวแกน Y เริ่มย้ายมาแกน Y
    SVTCA[y-axis]
    
    จะเริ่มต้นที่จุด 1 ในแนวแกน Y นี้ เรายังไม่ได้ทำอะไรเลย จึงควรปัดให้ลงจุดเสียก่อน
    mdap[rnd]           1
    
    บอกว่าจุด 13 อยู่ในระดับเดียวกับจุด 1
    alignrp             13
    
    กำหนดความสูงของฟอนต์
    mirp[rp0,rnd,grey]  vheight_shoot    22
    
    กำหนดความหนาของเส้นในแนวนอน
    mirp[min,rnd,grey]  vstem_curve  5
    
    กำหนดให้ rp1 เป็นจุด 5 และ rp2 เป็นจุด 13 เพื่อจะเกลี่ยจุดที่สำคัญอื่น ๆ โดยใช้ rp1 และ rp2 เป็นจุดอ้างอิงในการเฉลี่ยค่า
    srp1                5
    srp2                13
    sloop               10
    ip      19 8 18 9 17 10 2 25 15 12
    
    เกลี่ยจุดที่เหลือ ในแนวแกน Y
    IUP[y]
    
    เมื่อนำโค๊ดที่เขียนมาถอดด้วยสคริปต์ dfont.py จะได้โค๊ด instruction ดังนี้
    NPUSHB
     15
     27
     1
     8
     25
     163
     12
     8
     14
     18
     17
     10
     8
     18
     11
     26
    SRP0
    MIRP[rp0,min,rnd,grey]
    MDRP[min,rnd,grey]
    MDRP[rp0,rnd,grey]
    MDRP[min,rnd,grey]
    SRP0
    MDRP[rp0,rnd,grey]
    MIRP[min,rnd,grey]
    MIRP[rp0,rnd,grey]
    MIRP[min,rnd,grey]
    MDRP[rnd,white]
    IUP[x]
    NPUSHB
     19
     12
     15
     25
     2
     10
     17
     9
     18
     8
     19
     10
     13
     5
     5
     185
     22
     184
     13
     1
    SVTCA[y-axis]
    MDAP[rnd]
    ALIGNRP
    MIRP[rp0,rnd,grey]
    MIRP[min,rnd,grey]
    SRP1
    SRP2
    SLOOP
    IP
    IUP[y]
    จบแล้วครับ
    Topic: 

    fonts: ตัวอย่างการ hint ข.ไข่

    ค่า cvt ที่เกี่ยวข้องคือ
    cvt_dict = {
        ...
        "w_690":            14,     #690    =width of kho_khai
        "hstem":            8,      #184    =horizontal stem
        "vstem":            96,     #154    =vertical stem
        "headstem":         258,    #116    =head stem
        "headstem_plus_hole":   259, #268   =head stem + hole width
        "headdia":          257,    #384    =head diameter
        "vheight":          188,    #1120   =normal height 
        "vheight_shoot":    184,    #1147   =overshoot height
        "front_khai":       32,     #51     =front spacing of kho_khai
        ...
    }
    ภาพลายเส้น
    โครง ข.ไข่ แนวแกน X
    เส้นทาง hint ในแนวแกน X ตัวอย่างนี้เริ่มซับซ้อน เนื่องจากช่วงหัวของ ข.ไข่ มีทางเดินที่ต้องการทดลงจุดมาก ทำให้ระยะที่ได้มีค่าไม่แน่นอนตามขนาดฟอนต์ที่เปลี่ยนไป ผลที่ได้คือ
    ถ้าเราทำให้ฟอนต์มีขนาดคงที่ จะทำให้บางครั้งหัวดูลีบหรือใหญ่เกินไป
    ถ้าเราทำให้หัวดูสวยงาม บางครั้งฟอนต์จะดูกว้างหรือลีบเกินไป
    ทางแก้คือเราจะ hint ให้ช่วงหัวให้ดูสวยงามก่อน แล้วโยงไปเส้น stem ด้านหลัง แล้วจึงโยงกลับมาที่ stem ด้านหน้าอีกครั้ง โดยใช้ตรงโค้งช่วงคอของอักษรเป็นช่วงที่รับระยะการเปลี่ยนแปลง วิธีนี้ทำให้เกิดผลข้างเคียงน้อยที่สุด (แต่ก็ยังมีอยู่ดี ต้องแก้ต่อไปด้วย delta hint สำหรับขนาดฟอนต์ที่ดูไม่งาม) เริ่มต้นที่จุด 53
    srp0                53
    
    เคลื่อนไปจุดใกล้ทีสุดด้วยระยะ front_khai
    mirp[rp0,min,rnd,grey]  front_khai 21
    
    จัดการหัวก่อน ด้วยการกำหนดขนาดเส้นหัว เคลือนไปอีกด้านหนึ่ง แล้วกำหนดขนาดย้อนกลับอีกครั้ง
    mirp[min,rnd,grey]  headstem 50
    mirp[rp0,rnd,grey]  headdia 15
    mirp[min,rnd,grey]  headstem 44
    
    กำหนดจุดคอดที่จุด 12
    mdrp[rnd,grey]      12
    
    เคลื่อนไปที่จุด 7 ด้วยการแรเงาแบบ white เพื่อแยกหัวออกจากคออักษรให้ชัดเจน
    mdrp[rp0,rnd,white] 7
    
    เคลื่อนไปต่อ เพื่อกำหนดความกว้างของคอ ให้เท่ากับระยะ vstem (ยืมค่า vstem ซึ่งน้อยกว่า hstem มาใช้สำหรับคออักษร)
    mirp[rp0,rnd,grey]  vstem 27
    
    เคลื่อนไปต้อ ด้วยการแรเงาแบบ white เพื่อแยกเส้นหน้าและเส้นหลังจากกัน
    mdrp[rp0,rnd,white] 36
    
    เคลื่อนต่อ กำหนดขนาดของเส้นหลัง
    mirp[rp0,min,rnd,grey] hstem 38
    
    กำหนดระยะกั้นหลัง
    mdrp[rnd,white]     54
    
    เคลื่อนย้อนกลับมาที่จุด 1 เพื่อกำหนดความกว้างหลักของอักษร ให้เท่ากับระยะ w_690
    mirp[rp0,rnd,grey]  w_690 1
    
    กำหนดความกว้างของเส้นหน้า
    mirp[min,rnd,grey]  hstem 32
    
    เกลี่ยจุดที่เหลือ จบการทำงานในแกน X
    IUP[x]
    
    แนวแกน Y
    เส้นทาง hint ในแนวแกน Y ทำงานในแกน Y
    SVTCA[y-axis]
    
    ปัดเศษลงจุด 1
    mdap[rnd]           1
    
    กำหนดความสูงปกติของเส้นหลัง
    mirp[rnd,grey]      vheight 38
    
    กำหนดความหนาของเส้นแนวนอนให้เท่ากับระยะ vstem
    mirp[min,rnd,grey]  vstem 33
    
    เคลื่อนไปเพื่อกำหนดความสูงหลอกตา (overshoot) ของหัว
    mirp[rp0,rnd,grey]  vheight_shoot 24
    
    เคลื่อนจุด กำหนดความหนาของคอแนวนอน โดยกำหนดให้เท่ากับความหนาของหัว คือ headstem
    mirp[rp0,rnd,grey]  headstem 10
    
    ย้ายมากำหนดส่วนคอด
    mdrp[rp0,rnd,white] 12
    
    ตรงนี้ เราจะเคลื่อนลงไปใต้สุดของหัวเลย เพื่ออาศัยพื้นที่ส่วนบนของหัว เป็นระยะรองรับการทดจุด (มีพื้นที่ดำมากกว่าส่วนอื่น) แล้วจึงกำหนดจุดของความหนาหัวและรูของหัวอักษรจากด้านล่าง
    mdrp[rp0,rnd,grey]  18
    mirp[min,rnd,grey]  headstem 41
    mirp[rnd,grey]      headstem_plus_hole 47
    
    เกลี่ยจุดเป็นคำสั่งสุดท้าย
    IUP[y]
    
    เสร็จแล้ว
    ถอดด้วย dfont.py จะได้โค๊ด instruction ดังนี้
    NPUSHB
     12
     32
     8
     1
     14
     54
     38
     8
     36
     27
     96
     7
     44
    PUSHW_1
     258
    PUSHB_2
     12
     15
    PUSHW_1
     257
    PUSHB_1
     50
    PUSHW_1
     258
    PUSHB_3
     21
     32
     53
    SRP0
    MIRP[rp0,min,rnd,grey]
    MIRP[min,rnd,grey]
    MIRP[rp0,rnd,grey]
    MDRP[rnd,grey]
    MIRP[min,rnd,grey]
    MDRP[rp0,rnd,white]
    MIRP[rp0,rnd,grey]
    MDRP[rp0,rnd,white]
    MIRP[rp0,min,rnd,grey]
    MDRP[rnd,white]
    MIRP[rp0,rnd,grey]
    MIRP[min,rnd,grey]
    IUP[x]
    PUSHB_1
     47
    PUSHW_1
     259
    PUSHB_1
     41
    PUSHW_1
     258
    PUSHB_3
     18
     12
     10
    PUSHW_1
     258
    PUSHB_7
     24
     184
     33
     96
     38
     188
     1
    SVTCA[y-axis]
    MDAP[rnd]
    MIRP[rnd,grey]
    MIRP[min,rnd,grey]
    MIRP[rp0,rnd,grey]
    MIRP[rp0,rnd,grey]
    MDRP[rp0,rnd,white]
    MDRP[rp0,rnd,grey]
    MIRP[min,rnd,grey]
    MIRP[rnd,grey]
    IUP[y]
    
    Topic: 

    fonts: ตัวอย่างการ hint ค.ควาย

    ค่า cvt ที่เกี่ยวข้องคือ
    cvt_dict = {
        ...
        "w_1001":           71,     #1001   =width of kho_kwai
        "w_690":            14,     #690    =
        "front_kai":        11,     #113    =front spacing of ko_kai
        "hstem":            8,      #184    =horizontal stem thick
        "headstem":         258,    #116    =head stem thick
        "headstem_plus_hole":   259, #268   =head stem thick + head hole width
        "vheight_shoot":    184,    #1147   =overshoot height
        "vstem_curve":      185,    #156    =curve range vertical stem
        ...
    }
    ภาพลายเส้น
    โครง ค.ควาย แนวแกน X
    เส้นทาง hint ในแนวแกน X เริ่มที่จุด 52
    srp0                52
    
    เคลื่อนไปที่จุดใกล้สุด 33 ด้วยระยะ front_kai
    mirp[rp0,min,rnd,grey] front_kai 33
    
    กำหนดความหนาของเส้นหน้า ที่จุด 8
    mirp[min,rnd,grey]  hstem 8
    
    เคลื่อนไปกำหนดความกว้างของตัวอักษรที่จุดขวาสุด 39 ด้วยความกว้าง w_1001
    mirp[rp0,rnd,grey]  w_1001  39
    
    กำหนดช่องไฟหลัง
    mdrp[rnd,white]     53
    
    กำหนดความหนาของเส้นหลัง ที่จุด 1
    mirp[min,rnd,grey]  hstem 1
    
    มาเริ่มกันใหม่ที่จุด 8
    srp0                8
    
    เคลื่อนลงข้างล่าง สู่จุด 11 (เพื่อจะนำไปสู่ฐานของเส้นหน้า) ให้การแรเงาเป็น white เพื่อแยกเส้นหน้ากับคอของหัวอักษร
    mdrp[rp0,rnd,white] 11
    
    เนื่องจากเส้นตรงนี้บางมาก จึงกำหนดจุดเพื่อคงระยะอย่างน้อย ที่จุด 27 กำหนดเป็น min
    mdrp[min,rnd,grey]  27
    
    จากจุด 11 เคลื่อนไปลงจุด 30
    mdrp[rp0,rnd,grey]  30
    
    กำหนดความหนาของฐาน ที่จุด 29
    mirp[min,rnd,grey]  hstem 29
    
    กลับไปที่จุด 11
    srp0                11
    
    เคลื่อนไปที่จุด 14 ด้วยการแรเงา white อีกครั้ง เพื่อแยกเส้นให้เด็ดขาด
    mdrp[rp0,rnd,white] 14
    
    คงความหนาของส่วนคอดไว้
    mdrp[min,rnd,grey]  25
    
    ย้อนกลับไปตั้งต้นที่จุด 33 อีกครั้งหนึ่ง เพื่อจะสร้างหัวอักษร โดยให้ระยะ จาก 14-49 เป็นตัวรองรับการทดจุด
    srp0                33
    
    เพื่อความแน่นอนแม่นยำ เราจะเคลื่อนจุดไปหาจุดขวาสุดของหัวอักษร โดยกำหนดค่าเป็น w_690
    (จำเป็นต้องให้แม่นยำ เนื่องจากช่องว่างตรงหัวอักษรมีจำกัดมาก) แล้วจึงกำหนดขนาดความหนาหัวอักษรและรูย้อนกลับอีกที
    mirp[rp0,rnd,grey]  w_690   20
    mirp[min,rnd,grey]  headstem 43
    mirp[rnd,grey]      headstem_plus_hole 49
    
    เกลี่ยจุดเป็นคำสั่งสุดท้าย
    IUP[x]
    
    แนวแกน Y
    เส้นทาง hint ในแนวแกน Y ทำงานในแกน Y
    SVTCA[y-axis]
    
    เริ่มที่จุด 0
    MDAP[rnd]           0
    
    บอกว่าจุด 29 อยู่ในระดับเดียวกัน
    ALIGNRP             29
    
    เคลื่อนไปกำหนดจุดสูงสุดด้วยค่า vheight_shoot
    mirp[rp0,rnd,grey]  vheight_shoot  36
    
    กำหนดความหนาตรงส่วนนี้ด้วยค่า vstem_curve
    mirp[min,rnd,grey]  vstem_curve  5
    
    จากจุด 36 เดิม เคลื่อนไปส่วนบนของหัวอักษรที่จุด 17 เนื่องจากไม่กังวลระยะมากนัก จึงใช้การเคลื่อนแบบไม่อ้างค่า cvt คือคำสั่ง MDRP
    (เหตุที่ใช้จุด 36 แทนที่จะเป็นจุด 1 หรือ จุด 0 ในการอ้างอิงสำหรับหัวอักษร ค.ควาย เนื่องจากความสวยงามในการวาดหัวอักษร จะขึ้นกับโค้งด้านบนมากว่าฐานด้านล่าง)
    mdrp[rp0,rnd,grey]  17
    
    กำหนดขนาดหัวโดยใช้เทคนิกเหมือนเดิม คือกำหนดความหนาด้านบน เคลื่อนไปกำหนดขนาดรวม และกำหนดความหนาด้านล่าง
    mirp[min,rnd,grey]  headstem  46
    mirp[rp0,rnd,grey]  headdia  23
    mirp[min,rnd,grey]  headstem  40
    
    ย้ายมาที่จุด 29 เพื่อมากำหนดความหนาตรงจุดนั้น
    srp0                29
    mdrp[min,rnd,grey]  11
    
    เกลี่ยจุดสำคัญ โดยให้ท้องตัวอักษรเป็นจุดเริ่มต้น คือจุด 5 และความหนาของฐานเป็นจุดสิ้นสุด คือจุด 11
    srp1                5
    srp2                11
    sloop               4
    ip                  33 8 2 39
    
    เกลี่ยจุดที่เหลือ
    IUP[y]
    
    เสร็จแล้ว
    แต่ถึงแม้จะป้องกันอย่างไร รูปร่างฟอนต์แบบตัว ค.ควาย จะยังมีปัญหาในตอนทดจุดอยู่ดี
    คือที่ขนาด 17 ppem หัวอักษรจะชิดติดกับแกนขวาของอักษร
    (สรุปเป็นปอยต์ตามความละเอียดของจอภาพคือ 72dpi=17pt, 85dpi=14.5pt, 96dpi=13pt)
    ดูจากเมนู View -> Grid Fit -> Show Grid Fit -> 17pt 72dpi ได้ภาพดังนี้
    17ppem gridfit แก้ด้วยการขยับจุดจำนวน 8 จุด ในแนวแกน X คือ
    จุด 2 ขยับไปทางขวา 8px คือ +8px ที่ 17ppem สูตรคือ
    +8px ค่าในตาราง delta hint คือ 15
    No.of step -8 -7 -6 -5 -4 -3 -2 -1 +1 +2 +3 +4 +5 +6 +7 +8
    Selector 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
    17ppem นำมาลบด้วย 9 (ลบด้วย 9 เสมอ) คือ 6
    ค่า 6 จะเป็น 4 บิตบน และค่า 15 คือ 4 บิตล่าง รวมกันคือ 6*16+15=143
    จะได้คู่ของการทำ delta hint คือ จุด 2 และค่าผลรวม 143 เขียนสรุปย่อดังนี้
    ที่ 17 ppem
    จุด 2 ขยับ +8 = 2 143
    จุด 39 ขยับ +8 = 39 143
    จุด 0 ขยับ +8 = 0 143
    จุด 1 ขยับ +8 = 1 143
    จุด 3 ขยับ +6 = 1 141
    จุด 38 ขยับ +6 = 38 141
    จุด 37 ขยับ +4 = 37 139
    จุด 4 ขยับ +4 = 4 139
    นับรวมได้ 8 คู่ จะได้โค๊ดจำลองดังนี้ กำหนดการทำงานในแกน X
    SVTCA[x-axis]
    
    ใส่ delta hint โดยใส่จำนวนคู่ไว้เป็นค่าแรก
    deltap1             8 2 143 39 143 0 143 1 143 3 141 38 141 37 139 4 139
    
    ภาพหลังการขยับแล้วจะป็นดังนี้
    17ppem after gridfit เสร็จแล้ว
    เมื่อนำมาถอดด้วย dfont.py จะได้โค๊ด instruction ดังนี้
    PUSHB_1
     49
    PUSHW_1
     259
    PUSHB_1
     43
    PUSHW_1
     258
    NPUSHB
     22
     20
     14
     33
     25
     14
     11
     29
     8
     30
     27
     11
     8
     1
     8
     53
     39
     71
     8
     8
     33
     11
     52
    SRP0
    MIRP[rp0,min,rnd,grey]
    MIRP[min,rnd,grey]
    MIRP[rp0,rnd,grey]
    MDRP[rnd,white]
    MIRP[min,rnd,grey]
    SRP0
    MDRP[rp0,rnd,white]
    MDRP[min,rnd,grey]
    MDRP[rp0,rnd,grey]
    MIRP[min,rnd,grey]
    SRP0
    MDRP[rp0,rnd,white]
    MDRP[min,rnd,grey]
    SRP0
    MIRP[rp0,rnd,grey]
    MIRP[min,rnd,grey]
    MIRP[rnd,grey]
    IUP[x]
    NPUSHB
     10
     39
     2
     8
     33
     4
     11
     5
     11
     29
     40
    PUSHW_1
     258
    PUSHB_1
     23
    PUSHW_1
     257
    PUSHB_1
     46
    PUSHW_1
     258
    PUSHB_7
     17
     5
     185
     36
     184
     29
     0
    SVTCA[y-axis]
    MDAP[rnd]
    ALIGNRP
    MIRP[rp0,rnd,grey]
    MIRP[min,rnd,grey]
    MDRP[rp0,rnd,grey]
    MIRP[min,rnd,grey]
    MIRP[rp0,rnd,grey]
    MIRP[min,rnd,grey]
    SRP0
    MDRP[min,rnd,grey]
    SRP1
    SRP2
    SLOOP
    IP
    IUP[y]
    NPUSHB
     17
     139
     4
     139
     37
     141
     38
     141
     3
     143
     1
     143
     0
     143
     39
     143
     2
     8
    SVTCA[x-axis]
    DELTAP1
    
    Topic: 

    fonts: บันทึกการทดลองทำ DejaVuSerifThai อีกรุ่น

    บันทึกการสร้างฟอนต์ DejaVu Serif Thai

    • ตัวนี้ทดลองทำ hinting เลียนแบบวิธีของ Tahoma คือ
      คงระยะคงที่ช่องไฟหน้าและหลังไว้ และให้ความกว้างของตัวอักษรเป็นตัวรองรับระยะการทดจุดที่เปลี่ยนไปมา ซึ่งบังคับว่าต้องทำ grid fitting (delta hint) เพื่อกำหนดความกว้างของฟอนต์ก่อน แล้วจึงเริ่มเดินจุด
      การทำ delta hint ก่อน จำเป็นมากสำหรับฟอนต์ขนาดเล็ก ซึ่งมีอัตราการเพี้ยนของความกว้างของอักษรมาก ไหน ๆ ก็ต้องทำ delta hint อยู่แล้ว เที่ยวนี้จึงพยายามลงลึกไปทำถึงขนาดหัวอักษรด้วย ผลที่ได้คืออ่านง่ายขึ้น โดยเฉพาะกับฟอนต์ขนาดเล็ก ๆ แต่ก็ต้องแลกมาด้วยการเสียเวลาและสายตาเป็นอย่างมาก
      (การทำงานต้องปรับขนาดจอภาพให้มีความละเอียด 72 dpi เพื่อให้รองรับขนาดฟอนต์ได้ทุก ๆ ppem บวกกับการเพ่งกำหนดจุดที่เปลี่ยน จึงเปลืองสายตามาก)
    • รูปแบบฟอนต์ของ DejaVu Serif ดูไม่เป็น serif จัดนัก จึงนำเอาฟอนต์ Angsima มาแปลงใส่เข้าไป
      เนื่องจากเห็นว่า ภาษาไทยทำ serif แท้ ๆ ไม่สวย จึงพยายามทำเท่าที่ทำได้ คือ hint เฉพาะพยัญชนะ ส่วนสระบนและล่างไม่ hint และไม่แปลงรูปแบบเลย

    ผลการทดลอง

    • เนื่องจากมีการทำ grid fitting (เกือบ)เต็มที่ จึงดูดีที่ฟอนต์ขนาดเล็ก ๆ ด้วย (หรือเปล่า?)
    • สระบนล่าง ทำ hint แล้วไม่สวย จึงตัดสินใจไม่ hint เพียงแค่กำหนดระยะในแกน Y เล็กน้อย ผลที่ได้คือแนวเส้นบรรทัดที่เป็นพญัญชนะจะดูคมชัดกว่าแนวสระบนล่าง - ไม่รู้ว่าดีหรือเปล่า รอดูผลการใช้งานต่อไป
    • แบบอักษรดูคล้าย sans ไปหน่อย โดยเฉพาะกับฟอนต์ขนาดเล็ก ยกเว้นสระบนล่างที่เป็นแบบของ Angima ชัดเจน ซึ่งอาจทำให้ดูไม่กลมกลืน

    ปรับปรุง
    (เนื่องจากเป็นการทำงานไปด้วย ศึกษาไปด้วย การทำ hinting จึงไม่เป็นอันหนึ่งอันเดียวกันในทุก ๆ ฟอนต์ที่ทำ ต้องขออภัยด้วย)

    • 51-05-06 ทำตัวหนาเพิ่มเสร็จแล้ว ตัวหนาที่ทำ ใช้เทคนิก hint เท่าที่จำเป็น จึงอาจดูไม่คมชัดนัก แต่ฟอนต์น่าจะอ่านง่ายขึ้นและผิดรูปน้อยลง
    • เขียนฟังก์ชั่นให้ทำ grid fitting ง่ายขึ้น งานของตัวหนาจึงเพิ่มเรื่อง grid fitting มากขึ้นมาก
    • 51-05-31 ปรับละเอียด เริ่มใช้ฟังก์ชั่น SHPIX ในการปรับหัวไม่ให้คมแข็ง พยายามปรับฟอนต์ให้ดูนิ่มนวลขึ้น ทำให้ดูดีขึ้นสำหรับการแสดงผลพื้นขาวตัวดำ แต่ยังมีปัญหากับพื้นหลังที่เข้มไม่มาก แต่ตัวหนังสือสีขาว (เช่นเว็บ pantip.com) ยังดูยากหน่อย พยายามปรับระดับความสูงวรรณยุกต์ระดับ 2 ไม่ให้เหลื่อม (ยังไม่ได้ทำตัวหนา เพราะยังไม่แน่ใจผล)

    ดาวน์โหลดไฟล์ฟอนต์ ttf

    ดาวน์โหลดซอร์ส

    • รุ่นแรกยังไม่มีตัวหนา DejaVuSerifThai-src-510502.tar.gz
    • รุ่นสองเพิ่มตัวหนาแล้ว DejaVuSerifThai-src-510506.tar.gz
    • ทำเลขไทยเสร็จแล้ว hint สระแล้ว DejaVuSerifThai-src-510508.tar.gz
    • รุ่นใหม่ ปรับให้ดูนุ่มนวล DejaVuSerifThai-src-510531.tar.gz
    • ทำตัวหนาเสร็จ แต่ตัวหนาไม่ได้ปรับหัว เพราะความจำเป็นน้อย สิ่งที่ปรับปรุงคือปรับการ hint โดยใช้แนวคิดว่าไม่จำเป็นต้องปัดเศษให้ลงจุดในทุกจุด ซึ่งจะทำให้ดูนุ่มนวลขึ้น เว้นเสียแต่ว่าระบบไม่มีการทำ Anti-Alias เช่นวินโดวส์รุ่นเก่า อาจทำให้ฟอนต์ดูเพี้ยน DejaVuSerifThai-src-510606.tar.gz
    • แก้บั๊กตาราง Lookups/GSUB ให้เรียบร้อย ทำตาราง OpenType เพื่อแก้ปัญหา "สระอำ" ใน OpenOffice : DejaVuSerifThai-src-510824.tar.gz

    ภาพตัวอย่าง (จากขนาดจอภาพ 72 dpi จึงกำหนดระยะเป็น ppem แทนเพื่อป้องกันสับสน)
    DejaVu Serif Thai

    Topic: 

    fonts: บันทึกฟอนต์อุโฆษ (Ukhosa)

    ต้องการทำฟอนต์ที่ใช้ในงานโฆษณา แต่ไม่แปลงรูปฟอนต์มากนัก ให้มีหัวบาง ๆ อยู่ทุกตัว ตั้งชื่อว่า อุโฆษ (Ukhosa) สร้างโดยเอาโครงฟอนต์โลมาบุตรมาแปลง

    ดาวน์โหลดไฟล์ฟอนต์ (20100707)

    ข้อความด้านล่างเป็นการแสดงผลจากหน้าเว็บด้วยฟอนต์นี้ (จากความสามารถของ css3)

    ดาวน์โหลดไฟล์ซอร์ส

    • รุ่นร่าง ยังไม่มีตัวหนา ยังไม่มี hint (รุ่นนี้อาจไม่ทำ hinting) Ukhosa-src-20100626.tar.gz
    • ยังไม่เสร็จ แต่จะเปลี่ยนลายเส้นภาษาอังกฤษเป็นแบบโลโกอูบุนตู - Ukhosa-src-20100629.tar.gz
    • อาจเว้นยาวหลายวัน โพสต์แปะไว้ก่อน - Ukhosa-src-20100630.tar.gz
    • ร่างตัวหนาเสร็จ - Ukhosa-src-20100707.tar.gz

    ภาพตัวอย่าง
    จาก Epiphany Browser
    ตัวธรรมดา

    ตัวหนา

    Topic: 

    python: เขียนโค๊ดคลี่แสต็กฟอนต์

    เหตุมาจากต้องการดูการ instruct ของฟอนต์ DejaVu Sans
    แต่โค๊ดอ่านยากเหลือเกิน เพราะเขียนข้อมูลเป็นสแต็กไว้ก่อน แล้วจึงเขียนโค๊ดตามหลัง ทำให้ดูยาก จึงเขียนสคริปต์แบบหยาบ ๆ มาคลี่ข้อมูลเรียงต่อท้ายคำสั่ง เพื่อให้ดูง่ายขึ้น ตั้งชื่อชั่วคราวว่า dfont.py
    $ touch dfont.py; chmod 755 dfont.py; vi dfont.py
    #!/usr/bin/env python
    
    import sys
    
    # ins_dict = { "COMMAND" : ("Description",pops,push), ... }
    # pops,push: 0=NOOP, 1=1BYTE, 2=2BYTE, ...
    #           -1=FIRST BYTE IS ONE BYTE COUNTER,
    #           -2=FIRST BYTE IS TWO BYTE COUNTER, 
    #           -3=CLEAR STACK
    #           -4=REQUIRE SOME PROCESSING
    
    ins_dict = {
        "AA" :       ("Adjust Angle", 1, 0),
        "ABS" :      ("ABSolute value", 1, 1),
        "ADD" :      ("ADD", 2, 1),
        "ALIGNPTS" : ("ALIGN Points", 2, 0),
        "ALIGNRP" :  ("ALIGN to Reference Point", 1, 0),
        "AND" :      ("logical AND", 2, 1),
        "CALL" :     ("CALL function", 1, 0),
        "CEILING" :  ("CEILING", 1, 1),
        "CINDEX" :   ("Copy the INDEXed element to the top of the stack", 1, -1),
        "CLEAR" :    ("CLEAR the stack", -3, 0),
        "DEBUG" :    ("DEBUG call", 1, 0),
        "DELTAC1" :  ("DELTA exception C1", -2, 0),
        "DELTAC2" :  ("DELTA exception C2", -2, 0),
        "DELTAC3" :  ("DELTA exception C3", -2, 0),
        "DELTAP1" :  ("DELTA exception P1", -2, 0),
        "DELTAP2" :  ("DELTA exception P2", -2, 0),
        "DELTAP3" :  ("DELTA exception P3", -2, 0),
        "DEPTH" :    ("DEPTH of the stack", 0, 1),
        "DIV" :      ("DIVide", 2, 1),
        "DUP" :      ("DUPlicate top stack element", 1, 1),
        "EIF" :      ("End IF", 0, 0),
        "ELSE" :     ("ELSE clause", 0, 0),
        "ENDF" :     ("END Function definition", 0, 0),
        "EQ" :       ("EQual", 2, 1),
        "EVEN" :     ("EVEN", 1, 1),
        "FDEF" :     ("Function DEFinition", 1, 0),
        "FLIPOFF" :  ("set the auto FLIP Boolean to OFF", 0, 0),
        "FLIPON" :   ("set the auto FLIP Boolean to ON", 0, 0),
        "FLIPPT" :   ("FLIP PoinT", 1, 0),
        "FLIPRGOFF" :    ("FLIP RanGe OFF", 2, 0),
        "FLIPRGON" : ("FLIP RanGe ON", 2, 0),
        "FLOOR" :    ("FLOOR", 2, 0),
        "GC" :       ("Get Coordinate projected onto the projection vector", 1, 1),
        "GETINFO" :  ("GET INFOrmation", 1, 1),
        "GFV" :      ("Get Freedom Vector", 0, 2),
        "GPV" :      ("Get Projection Vector", 0, 2),
        "GT" :       ("Greater Than", 2, 1),
        "GTEQ" :     ("Greater Than or EQual", 2, 1),
        "IDEF" :     ("Instruction DEFinition", 1, 0),
        "IF" :       ("IF test", 1, 0),
        "INSTCTRL" : ("INSTRuction execution ConTRoL", 2, 0),
        "IP" :       ("Interpolate Point", 1, 0),
        "ISECT" :    ("moves point p to the InterSECTion of two lines", 5, 0),
        "IUP" :      ("Interpolate Untouched Points through the outline", 0, 0),
        "JMPR" :     ("JuMP Relative", 1, 0),
        "JROF" :     ("Jump Relative On False", 1, 0),
        "JROT" :     ("Jump Relative On True", 3, 0),
        "LOOPCALL" : ("LOOP and CALL function", 2, 0),
        "LT" :       ("Less Than", 2, 1),
        "LTEQ" :     ("Less Than or Equal", 2, 1),
        "MAX" :      ("MAXimum of top two stack elements", 2, 1),
        "MD" :       ("Measure Distance", 2, 1),
        "MDAP" :     ("Move Direct Absolute Point", 1, 0),
        "MDRP" :     ("Move Direct Relative Point", 1, 0),
        "MIAP" :     ("Move Indirect Absolute Point", 2, 0),
        "MIN" :      ("MINimum of top two stack elements", 2, 1),
        "MINDEX" :   ("Move the INDEXed element to the top of the stack", 1, 3),
        "MIRP" :     ("Move Indirect Relative Point", 2, 0),
        "MPPEM" :    ("Measure Pixels Per EM", 0, 1),
        "MPS" :      ("Measure Point Size", 0, 1),
        "MSIRP" :    ("Move Stack Indirect Relative Point", 1, 0),
        "MUL" :      ("MULtiply", 2, 1),
        "NEG" :      ("NEGate", 1, 1),
        "NEQ" :      ("Not EQual", 2, 1),
        "NOT" :      ("logical NOT", 1, 1),
        "NPUSHB" :   ("PUSH N Bytes", -1, 0),
        "NPUSHW" :   ("PUSH N Words", -1, 0),
        "NROUND" :   ("No ROUNDing of value", 1, 1),
        "ODD" :      ("ODD", 1, 1),
        "OR" :       ("logical OR", 2, 1),
        "POP" :      ("POP top stack element", 1, 0),
        "PUSHB" :    ("PUSH Bytes", -4, 0),
        "PUSHW" :    ("PUSH Words", -4, 0),
        "RCVT" :     ("Read Control Value Table entry", 1, 1),
        "RDTG" :     ("Round Down To Grid", 0, 0),
        "ROFF" :     ("Round OFF", 0, 0),
        "ROLL" :     ("ROLL the top three stack elements", 3, 3),
        "ROUND" :    ("ROUND value", 1, 1),
        "RS" :       ("Read Store", 1, 1),
        "RTDG" :     ("Round To Double Grid", 0, 0),
        "RTG" :      ("Round To Grid", 0, 0),
        "RTHG" :     ("Round To Half Grid", 0, 0),
        "RUTG" :     ("Round Up To Grid", 0, 0),
        "S45ROUND" : ("Super ROUND 45 degrees", 1, 0),
        "SANGW" :    ("Set Angle Weight", 1, 0),
        "SCANCTRL" : ("SCAN conversion ConTRoL", 1, 0),
        "SCANTYPE" : ("SCANTYPE", 1, 0),
        "SCFS" : ("Sets Coordinate From the Stack using projection vector and freedom vector", 2, 0),
        "SCVTCI" :   ("Set Control Value Table Cut-In", 1, 0),
        "SDB" :      ("Set Delta Base in the graphics state", 1, 0),
        "SDPVTL" :   ("Set Dual Projection Vector To Line", 2, 0),
        "SDS" :      ("Set Delta Shift in the graphics state", 1, 0),
        "SFVFS" :    ("Set Freedom Vector From Stack", 2, 0),
        "SFVTCA" :   ("Set Freedom Vector To Coordinate Axis", 0, 0),
        "SFVTL" :    ("Set Freedom Vector To Line", 2, 0),
        "SFVTP" :    ("Set Freedom Vector To Projection Vector", 0, 0),
        "SHC" :      ("SHift Contour using reference point", 1, 0),
        "SHP" :      ("SHift Point using reference point", 1, 0),
        "SHPIX" :    ("SHift point by a PIXel amount", 2, 0),
        "SHZ" :      ("SHift Zone using reference point", 1, 0),
        "SLOOP" :    ("Set LOOP variable", 1, 0),
        "SMD" :      ("Set Minimum Distance", 1, 0),
        "SPVFS" :    ("Set Projection Vector From Stack", 2, 0),
        "SPVTCA" :   ("Set Projection Vector To Coordinate Axis", 0, 0),
        "SPVTL" :    ("Set Projection Vector To Line", 2, 0),
        "SROUND" :   ("Super ROUND", 1, 0),
        "SRP0" :     ("Set Reference Point 0", 1, 0),
        "SRP1" :     ("Set Reference Point 1", 1, 0),
        "SRP2" :     ("Set Reference Point 2", 1, 0),
        "SSW" :      ("Set Single Width", 1, 0),
        "SSWCI" :    ("Set Single Width Cut-In", 1, 0),
        "SUB" :      ("SUBtract", 2, 1),
        "SVTCA" :    ("Set freedom and projection Vectors To Coordinate Axis", 0, 0),
        "SWAP" :     ("SWAP the top two elements on the stack", 2, 2),
        "SZP0" :     ("Set Zone Pointer 0", 1, 0),
        "SZP1" :     ("Set Zone Pointer 1", 1, 0),
        "SZP2" :     ("Set Zone Pointer 2", 1, 0),
        "SZPS" :     ("Set Zone PointerS", 1, 0),
        "UTP" :      ("UnTouch Point", 1, 0),
        "WCVTF" :    ("Write Control Value Table in Funits", 1, 0),
        "WCVTP" :    ("Write Control Value Table in Pixel units", 2, 0),
        "WS" :       ("Write Store", 2, 0),
    }
    
    stack1_command = ("NPUSHB", "NPUSHW")
    stack2_command = ("PUSHB", "PUSHW")
    
    normal_command = []
    for i in range(6):
        normal_command.append( [ j for j in ins_dict.keys() if ins_dict[j][1]==i ] )
    
    #           -1=FIRST BYTE IS ONE BYTE COUNTER,
    #           -2=FIRST BYTE IS TWO BYTE COUNTER, 
    #           -3=CLEAR STACK
    #           -4=REQUIRE PROCESS
    pop_command = []
    pop_command.append([])
    for i in range(-1, -4, -1):
        pop_command.append( [ j for j in ins_dict.keys() if ins_dict[j][1]==i ] )
    
    
    def line_format(cmd,stack,desc):
        #STRING, LIST, STRING
        return "%-24s %-10s ;%10s" % (cmd, "  ".join(stack), desc,)
    
    def ins_decode(txt):
        txtlist = txt.split("\n")
        newlist = []
        commentlist = []
        stacklist = []
        sloop = 0
        i = 0
        while i < len(txtlist):
            if "[" in txtlist[i]:
                c1,c2 = txtlist[i].strip().split("[",1)
            else:
                c1,c2 = txtlist[i].strip(), ""
            #SKIP EMPTY LINE
            if c1 == "":
                i += 1
                continue
            #STACK: NPUSHB, NPUSHW
            if c1 in stack1_command:
                i += 1
                n = int(txtlist[i].strip())
                i += 1
                while n > 0:
                    stacklist.append(txtlist[i].strip())
                    i += 1
                    n -= 1
                continue
            #STACK2: PUSHB, PUSHW
            if c1[:5] in stack2_command:
    
                n = int(txtlist[i].strip()[6:])
                i += 1
                while n > 0:
                    stacklist.append(txtlist[i].strip())
                    i += 1
                    n -= 1
                continue
            temp_list = []
            #POP ONE
            if c1 in pop_command[1]:
                idx = stacklist.pop()
                temp_list = [idx]
                for j in range(int(idx)):
                    temp_list.append(stacklist.pop())
                newlist.append(line_format(txtlist[i],temp_list,ins_dict[c1][0]))
                i += 1
                continue
            #POP PAIR
            elif c1 in pop_command[2]:
                idx = stacklist.pop()
                temp_list = [idx]
                for j in range(int(idx)):
                    temp_list.append(stacklist.pop())
                    temp_list.append(stacklist.pop())
                newlist.append(line_format(txtlist[i],temp_list,ins_dict[c1][0]))
                i += 1
                continue
            #POP ALL (CLEAR STACK)
            elif c1 in pop_command[3]:
                stacklist = []
                newlist.append(line_format(txtlist[i],temp_list,ins_dict[c1][0]))
                i += 1
                continue
    
            #NORMAL COMMAND
            if c1 in normal_command[0]:
                count = 0
            elif c1 in normal_command[1]:
                count = 1
            elif c1 in normal_command[2]:
                count = 2
            elif c1 in normal_command[3]:
                count = 3
            elif c1 in normal_command[4]:
                count = 4
            elif c1 in normal_command[5]:
                count = 5
            else:
                count = -1
                print 'count-1:',c1
            if count > 0:
                if sloop > 0:
                    count += sloop-1
                    sloop = 0
            while count > 0:
                cnum = stacklist.pop()
                temp_list.append(cnum)
                if c1 == 'SLOOP':
                    sloop = int(cnum)
                count -= 1
            newlist.append(line_format(txtlist[i],temp_list,ins_dict[c1][0]))
            i += 1
        print '--------------------------------------'
        print '\n'.join(newlist)
    
    if __name__ == "__main__":
        txt = sys.argv[1]
        ins_decode(txt)
    
    เนื่องจากทำแบบหยาบ ๆ ใช้ลำบากหน่อย
    เรียกใช้ด้วยคำสั่ง
    $ ./dfont.py "
    แปะด้วยโค๊ดที่คัดลอกมาจากฟอนต์ อักขระ n
    "
    ได้ผลเป็น
    SRP0                     20         ;Set Reference Point 0
    MIRP[rp0,min,rnd,grey]   70  11     ;Move Indirect Relative Point
    MIRP[min,rnd,grey]       8  9       ;Move Indirect Relative Point
    SHP[rp2]                 13         ;SHift Point using reference point
    MIRP[rp0,rnd,grey]       78  0      ;Move Indirect Relative Point
    MIRP[min,rnd,grey]       8  2       ;Move Indirect Relative Point
    IUP[x]                              ;Interpolate Untouched Points through the outline
    SVTCA[y-axis]                       ;Set freedom and projection Vectors To Coordinate Axis
    MDAP[rnd]                1          ;Move Direct Absolute Point
    ALIGNRP                  10         ;ALIGN to Reference Point
    MIRP[rnd,grey]           188  12    ;Move Indirect Relative Point
    MIRP[rp0,rnd,grey]       184  17    ;Move Indirect Relative Point
    MDRP[rnd,grey]           14         ;Move Direct Relative Point
    MIRP[min,rnd,grey]       135  6     ;Move Indirect Relative Point
    SRP1                     1          ;Set Reference Point 1
    SRP2                     14         ;Set Reference Point 2
    SLOOP                    3          ;Set LOOP variable
    IP                       0  9  3    ;Interpolate Point
    IUP[y]                              ;Interpolate Untouched Points through the outline
    SVTCA[x-axis]                       ;Set freedom and projection Vectors To Coordinate Axis
    DELTAP1                  2  21  207  21  96 ;DELTA exception P1
    
    ทดสอบอีกอันนึง เป็นอักขระ a
    SRP0                     38         ;Set Reference Point 0
    MIRP[rp0,min,rnd,grey]   69  20     ;Move Indirect Relative Point
    MIRP[min,rnd,grey]       8  3       ;Move Indirect Relative Point
    MDRP[min,rnd,grey]       31         ;Move Direct Relative Point
    MDRP[rp0,rnd,grey]       11         ;Move Direct Relative Point
    MIRP[min,rnd,grey]       8  9       ;Move Indirect Relative Point
    SHP[rp2]                 13         ;SHift Point using reference point
    SHP[rp2]                 24         ;SHift Point using reference point
    SRP1                     3          ;Set Reference Point 1
    IP                       23         ;Interpolate Point
    IP                       0          ;Interpolate Point
    IUP[x]                              ;Interpolate Untouched Points through the outline
    SVTCA[y-axis]                       ;Set freedom and projection Vectors To Coordinate Axis
    MDAP[rnd]                12         ;Move Direct Absolute Point
    MDRP[rnd,grey]           23         ;Move Direct Relative Point
    MIRP[rnd,grey]           140  17    ;Move Indirect Relative Point
    MIRP[rp0,rnd,grey]       184  35    ;Move Indirect Relative Point
    MIRP[rp0,min,rnd,grey]   185  28    ;Move Indirect Relative Point
    MIRP[rp0,rnd,grey]       186  31    ;Move Indirect Relative Point
    MIRP[min,rnd,grey]       134  32    ;Move Indirect Relative Point
    SRP0                     17         ;Set Reference Point 0
    MDRP[rnd,white]          14         ;Move Direct Relative Point
    MIRP[min,rnd,white]      185  6     ;Move Indirect Relative Point
    SRP0                     23         ;Set Reference Point 0
    MIRP[min,rnd,white]      169  0     ;Move Indirect Relative Point
    SRP1                     14         ;Set Reference Point 1
    IP                       9          ;Interpolate Point
    SRP1                     23         ;Set Reference Point 1
    IP                       11         ;Interpolate Point
    SRP2                     31         ;Set Reference Point 2
    IP                       25         ;Interpolate Point
    IUP[y]                              ;Interpolate Untouched Points through the outline
    DELTAP1                  24  33  128  32  128  31  128  30  128  33  112  32  112  31  112  30  112  33  96  32  96  31  96  30  96  33  80  32  80  31  80  30  80  33  64  32  64  31  64  30  64  33  48  32  48  31  48  30  48 ;DELTA exception P1
    SVTCA[x-axis]                       ;Set freedom and projection Vectors To Coordinate Axis
    DELTAP1                  30  39  240  39  160  39  144  34  133  33  135  32  135  31  135  30  135  29  133  39  112  39  80  34  80  33  80  32  80  31  80  30  80  29  80  34  64  33  64  32  64  31  64  30  64  29  64  39  63  34  48  33  48  32  48  31  48  30  48  29  48 ;DELTA exception P1
    
    Topic: 

    python: โค๊ดฟอนต์ย้อนกลับ

    เพื่อให้ครบกระบวน ต่อด้วยโค๊ดย้อนกลับอีกที
    ต่อจาก python: เขียนโค๊ดคลี่แสต็กฟอนต์ ที่ผ่านมานะครับ $ vi dfont.py
    ...
    def stack_format(stacklist):
    
        def flush(newlist, templist, ind, cur_ind):
            if ind == 0:
                newlist.append('NPUSHB')
            else:
                newlist.append('NPUSHW')
            newlist.append(' %s' % len(templist))
            newlist.extend(templist)
            return newlist, [], cur_ind
    
        if len(stacklist)==0: return []
        n = 0
        newlist = []
        templist = []
        if int(stacklist[0]) < 256:
            ind = 0
        else:
            ind = 1
        while n < len(stacklist):
            if int(stacklist[n]) < 256:
                cur_ind = 0
            else:
                cur_ind = 1
            if ind == cur_ind:
                templist.insert(0,' '+stacklist[n])
            else:
                newlist, templist, ind = flush(newlist, templist, ind, cur_ind) #FLUSH
            n += 1
        newlist, templist, ind = flush(newlist, templist, ind, cur_ind) #FLUSH
        return newlist
    
    def ins_encode(txt):
        """Encode simple code into TrueType Instruction code"""
        comment_list = ['#',';']    #COMMENT CHARACTER
        flush_list = ['SVTCA']      #FLUSH STACK
        stacklist = []
        newlist = []
        templist = []
        txtlist = txt.split('\n')
        for line in txtlist:
            line = line.replace("\t"," ")
            if " " in line:
                l = line.split(" ")
            else:
                l = [line]
            l = [ j for j in l if j != "" ]
            if l == []:
                continue
            if l[0][0] in comment_list: #BYPASS COMMENT
                continue
            for f in flush_list:    #?FLUSH STACK
                if f == l[0][:len(f)]:
                    newlist.extend(stack_format(stacklist))
                    stacklist = []
                    newlist.extend(templist)
                    templist = []
                    break
            if '[' in l[0]:         #TO UPPERCASE
                ltemp = l[0].split('[',1)
                temp = ltemp[0].upper()+'['+ltemp[1]
            else:
                temp = l[0].upper()
            templist.append(temp)   #KEEP COMMAND
            l.pop(0)                #PROCESS REST STACK NUM
            for element in l:
                if element[0] in comment_list:
                    break
                else:
                    stacklist.append(element)
        if stacklist != []:
            newlist.extend(stack_format(stacklist))
        newlist.extend(templist)
        print '===Encode==============================='
        print '\n'.join(newlist)
    
    
    if __name__ == "__main__":
        txt = sys.argv[1]
        #ins_decode(txt)
        ins_encode(txt)
    
    
    ทดสอบด้วยตัวอย่าง n เมื่อกี้นี้
    $ dfont.py "
    แปะด้วยโค๊ดเทียมที่ถูกคลี่แล้ว จากตัวอย่าง n
    "
    ===Encode===============================
    NPUSHB
     10
     2
     8
     0
     78
     13
     9
     8
     11
     70
     20
    SRP0
    MIRP[rp0,min,rnd,grey]
    MIRP[min,rnd,grey]
    SHP[rp2]
    MIRP[rp0,rnd,grey]
    MIRP[min,rnd,grey]
    IUP[x]
    NPUSHB
     15
     3
     9
     0
     3
     14
     1
     6
     135
     14
     17
     184
     12
     188
     10
     1
    SVTCA[y-axis]
    MDAP[rnd]
    ALIGNRP
    MIRP[rnd,grey]
    MIRP[rp0,rnd,grey]
    MDRP[rnd,grey]
    MIRP[min,rnd,grey]
    SRP1
    SRP2
    SLOOP
    IP
    IUP[y]
    NPUSHB
     5
     96
     21
     207
     21
     2
    SVTCA[x-axis]
    DELTAP1
    
    ไม่เหมือนเป๊ะ แต่น่าจะทำงานได้เหมือนกัน
    Topic: