รวมหมวดฟอนต์
เอาไฟล์มาสรุปให้ดาวน์โหลดได้ง่ายขึ้นครับ
$ sudo ln -sf 65-z-ttfonts.conf /etc/fonts/conf.d $ fc-cache -fv
$ 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
***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 อีกทีนึงAngsima; Angsana New
ทั้งในหมวด Western text font และ CTL font
จะให้ผลที่แน่นอนกว่าการใช้การทดแทนฟอนต์ใน openoffice เอง นอกจากนี้ยังสามารถเปิดใช้งานทั้งใน Microsoft Word และ OpenOffice Writer ได้โดยไม่เกิดปัญหาครับ
Attachment | Size |
---|---|
rtv.zip | 45.32 KB |
จำเป็นต้องใช้ฟอนต์เก่าจากวินโดวส์มาทำอาร์ตเวิร์ก จึงต้องเตรียมฟอนต์เก่าให้สามารถแสดงผลในลินุกซ์ได้
ขั้นตอนคร่าว ๆ มีดังนี้
$ sudo aptitude install fontforge
$ cp ./thaifonts-scalable-0.4.5/nectec template.sfd
$ fontforge template.sfd
Element -> Merge Font...
จะได้ชุดอักษรจากฟอนต์เก่ามาทับบนเทมเพลตElement -> Font Info...
Encoding -> Reencode -> ISO 16041-1 (UNICODE, BMP)
คลิกขวา -> Add anchor
File -> Generate Fonts...
ฟอนต์ที่ได้จะสามารถใช้ได้กับลินุกซ์ที่ส่วนใหญ่จะใช้รหัสฟอนต์เป็นยูนิโค๊ด และมีความสามารถในการแก้สระลอยได้ในตัวเอง
หมายเหตุ
ช่วงนี้กำลังทดลองเอา 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
ฟอนต์ตัวที่สองตั้งชื่อว่า บรมลีลา - Bromlila
จุดประสงค์จะใช้แทน Browallia (โดยไม่เสียรูปแบบ)
ใช้ฐานจากฟอนต์ Garuda ยกเว้นตัวหนาที่เป็นภาษาอังกฤษ ตัว Garuda-Bold ยังไม่หนาเท่า Browallia ผมจึงเอามาจากตัวหนา sans ของ Freefont แทน
มีข้อสังเกตุคือ ตัว Browallia กับ Garuda เมื่อปรับสัดส่วนแล้ว มีลายเส้นที่แทบจะนาบกันสนิท
เที่ยวนี้ขี้เกียจทำ Screenshot เพราะตัวเหมือนกันเป๊ะ ๆ ดาวน์โหลดเลยดีกว่า
ดาวน์โหลดได้ดังนี้
ฟอนต์ตัวที่สามตั้งชื่อว่า ครดา - Corada
จุดประสงค์จะใช้แทน Cordia (โดยไม่เสียรูปแบบ)
ชื่อฟอนต์ไม่มีคำแปล เพราะพยายามให้อักขระสามตัวแรกเหมือนกัน เพื่อให้เลือกฟอนต์ได้ง่าย จำง่าย
ใช้ฐานจากฟอนต์ Loma แต่ยากหน่อยตรงที่ฐานของฟอนต์โลมาคือ FreeSerif ไม่มีขนาดความหนาแบบ Light เลยต้องเสียเวลาสร้างตัวภาษาอังกฤษแบบ Light ด้วย และใช้ขนาดปกติ (Book) ของ FreeSerif เป็น Bold ของ Corada แทน
ดังนั้นสำหรับเที่ยวนี้ ในส่วนของอักขระภาษาอังกฤษจึงไม่ค่อยเรียบร้อยเท่าที่ควร เพราะสร้างขึ้นเอง
พยายามให้หน้าตาฟอนต์ออกมาอยู่ระหว่างฟอนต์คอร์เดีย และสุดยอดฟอนต์แห่งยุค คือ ดีบีฟองน้ำ
ดาวน์โหลดได้ดังนี้
สรุปงานทำฟอนต์ทดแทนฟอนต์ของวินโดวส์ทั้งสามตัว คือ
สร้างด้วยการปรับความกว้างของฟอนต์แต่ละอักขระ ให้เท่ากับฟอนต์วินโดวส์ และลบ kerning ของฟอนต์ต้นแบบออกให้หมด ส่วนความสูงของฟอนต์ ไม่ได้ปรับความสูงของสระให้เท่าของวินโดวส์ แต่ใช้วิธีสร้างอักขระพิเศษเพิ่มมาตัวนึง ให้จุดสูงสุดของอักขระเท่ากับไม้โทสูงของวินโดวส์ (ซึ่งสูงที่สุด) และให้จุดต่ำสุดของอักขระนี้ ให้เท่ากับสระอูที่ต่ำที่สุดของวินโดวส์
รวมทั้งสร้างไฟล์คอนฟิกให้ฟอนต์ ให้แทนชื่อฟอนต์จากวินโดวส์ตามรายละเอียดข้างบน ไฟล์นี้ตั้งชื่อว่า 65-2-thaifont-abc.conf ซึ่งจะต้องนำไปใส่ไว้ที่ไดเรกทอรี่ /etc/fonts/conf.d
เมื่อทำครบทุกอย่างแล้ว เราก็จะสามารถเปิดไฟล์ตระกูลออฟฟิศจากวินโดวส์ โดยไม่เสียรูปแบบ
สามารถดาวน์โหลดไฟล์รวมได้ดังนี้
ทดลองทำฟอนต์ใช้เองโดยใช้ไฟล์ฟอนต์ Norasi.sfd ของ NECTEC เป็นต้นแบบ
จุดประสงค์เพื่อทำฟอนต์แบบ Serif ที่ใช้รหัสอักขระยูนิโค๊ด จะนำมาแทนฟอนต์ Angsana ของวินโดวส์
ตั้งชื่อว่า นรบุตร (Noraputta)
ตั้งใจให้ออกมาเป็นลูกผสมของ Norasi กับ Angsana
ยังไม่ค่อยสวยเหมือนที่มืออาชีพเขาทำกัน ฮิ้นต้งฮิ้นติ้งไม่รู้เรื่องเลย เอาแค่พอใช้งานได้ตามสไตล์
ฝากลองทดสอบและใช้ฟรีโดยไม่มีเงื่อนไขครับ
update
ลองทำ Serif อีกฟอนต์นึง เพื่อให้สมดุลย์กับ Sans serif โดยเอาต้นแบบมาจากฟอนต์ Gentium ซึ่งเป็น Serif ที่ดูสบายตา กึ่งทางการกึ่งลำลอง จึงตั้งชื่อให้คล้าย ๆ กัน ว่า เจนทินี - Gentini
ทำไปก็งงไป ทำให้ทราบว่างานออกแบบฟอนต์นี่ยากจริง ๆ ผมเองยังมือไม่ถึง จึงอ่านบุคลิกของฟอนต์ Gentium ไม่ออก เลยทำแค่ฟอนต์ขนาด book แค่ตัวเดียว
ดาวน์โหลด
ไฟล์รวม Gentini.tar.gz
ไม่ใช่งานใหม่ แต่เป็นการเอา โลมาบุตร มาชำระล้าง ปรับปรุงเล็กน้อย แต่พอทำไป ๆ มันชักเพี้ยนมาทาง อัมพุช
เลยเปลี่ยนชื่อเสียเลยดีกว่า เพื่อไม่ให้สับสน และไม่ให้ทับซ้อนกับโลมา
ตั้งชื่อว่า ปัณถกะ - Pantaka แปลว่าชำนาญทาง
ทำแล้วรู้สึกว่าอ่านง่ายกว่า วีรชาติ เลยบรรจุเข้าประจำการเป็นฟอนต์หน้าจอแทนวีรชาติ
ดาวน์โหลดไฟล์รวมดังนี้
update
หลังจากทำฟอนต์ 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
ถ้าไม่ประสบเหตุอื่นอีก ฟอนต์นี้คงเป็นฟอนต์สุดท้ายแล้วครับ
ทำฟอนต์หน้าจอเพิ่ม ตั้งชื่อว่า วีรชาติ เพราะเอามาจากฟอนต์ Vera ของ BitStream
ตัวบางไปหน่อย line spacing แคบไปนิด Hinting ยังแย่อยู่
ช่วยทดสอบและใช้ได้ฟรีเหมือนเดิมครับ
ดาวน์โหลดซอร์ส
(ไฟล์ ttf สามารถดาวน์โหลดที่ หน้ารวม Fonts)
การทดลองที่ไม่สำเร็จ
ทดลองทำ Truetype Instruction ด้วยเมนู AutoInstruction
แก้ไขการที่โปรแกรม Fontforge ทำ Truetype Hint ไม่สมบูรณ์ ด้วยการปรับละเอียดที่ส่วนโค้งของตัวอักษรแทน
ไม่สำเร็จเนื่องจาก คุณภาพพอดูได้แค่ 11 ปอยนต์ ที่เหลือนอกจากนี้ ดูไม่ได้เลย
ไฟล์ชุดนี้ยังไม่สมบูรณ์ แต่ถ้าหากต้องการทดลองใช้งานดู ไม่จำเป็นต้องแก้ไขไฟล์ 65-ttfonts.conf เนื่องจากมีการ Hint อยู่ในฟอนต์เรียบร้อยแล้ว
update
<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 ก็จะดูคมแข็งขึ้นครับ
(ดูรายละเอียดการปรับตั้งที่ ลองทำฟอนต์ใช้เอง - แถม)
update
โพสต์นี้ได้ความรู้มาจากคุณสมเจตน์ ท่านช่วยทดสอบให้ ได้ความว่า
ฟอนต์ชุดนี้ หากจะนำไปใช้ให้ได้ผลดีมีความคมชัด ต้องกำหนด 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
$ sudo ln -sf /etc/fonts/conf.avail/10-autohint.conf /etc/fonts/conf.d
คราวก่อนทำฟอนต์โลมาบุตร ดูแล้วยังรู้สึกว่าอ่านยาก (ไม่รู้ว่าเป็นที่ hinting หรือเปล่า)
คราวนี้ลองเอาอีกฟอนต์นึงคือฟอนต์ครุฑ (Garuda) มาปรับให้เหมาะกับการแสดงผลบนจอคอมพิวเตอร์
โดยการลดขนาดสระและวรรณยุกต์ และปรับความกว้างของบรรทัดให้แคบเข้า
เอาไว้เป็นตัวเผื่อเลือกสำหรับการแสดงผลของฟอนต์ sans-serif
ตั้งชื่อว่าฟอนต์ ครุฑทัศน์ (Garudatas)
ดาวน์โหลด
update
ทำเพิ่มเติมสำหรับ serif ด้วย คือฟอนต์นรสีห์ เป็น นรสีห์ทัศน์
ดาวน์โหลด
หมายเหตุ
ไม่เหมาะสำหรับงานเอกสารที่ต้องพิมพ์ออกมา สำหรับงานพิมพ์ใช้ฟอนต์ Garuda และ Norasi เดิมสวยอยู่แล้ว
โปรแกรม FontForge เป็นโปรแกรมที่ใช้ออกแบบฟอนต์ของลินุกซ์ที่ได้รับความนิยม มีความสามารถสูง แต่มีข้อเสียคือ ทำ AutoHint ได้แย่มาก เพราะโปรแกรมจะกันเหนียวด้วยการกำหนดแถบการ Hint ไว้กว้างเกินไป
การกำหนดแถบการ Hint ไว้กว้าง ทำให้เวลาแสดงฟอนต์ทางจอภาพ อักษร ก ไก่ จะดูเตี้ยกว่าอักษร ข ไข่ ซึ่งไม่ถูก AutoHint ไว้กว้างแบบนั้น
ถ้าจะทำให้ได้ผลการ Hint ที่ดี แบบที่เรา ๆ ท่าน ๆ สามารถทำได้เอง โดยไม่ต้องใช้ฝีมือระดับเทพ ก็คือการ Hint เองด้วยมือ
ซึ่งทำได้โดยการกำหนดสองจุดคู่ที่จะทำการ Hint แล้วสั่ง Add HHint หรือ Add VHint ตามลักษณะของส่วนโค้งตัวอักษรนั้น ๆ
วิธีนี้ทำให้ได้ตัวอักษรที่ดูสูงเท่ากัน แต่ปัญหาคือโปรแกรม FontForge ไม่ทำปุ่มลัดสำหรับคำสั่ง Add HHint และ Add VHint ไว้ด้วย
งานที่จะต้องมานั่งเลือกจุดคู่แล้วไล่คลิกเมนูสั่งงาน นับว่าเปลืองเวลาเกินไป
แต่ยังโชคดีที่โปรแกรมถูกออกแบบให้สามารถกำหนดปุ่มลัดได้เอง เพียงแต่ต้องออกแรงหน่อยนึงด้วยการคอมไพล์แพกเกจเอง
เราจะกำหนดปุ่มลัดเอง ทำให้การทำงานเร็วขึ้นมาก
เริ่มด้วยการติดตั้งแพกเกจที่จำเป็นในการคอมไพล์ก่อน
$ 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 ได้คือ
เพิ่มเติม
Element -> Font Info ... -> เลือก Quadratic Splines
หลังจากนั้นจึงทำ AutoHint และ AutoInstruction แล้วจึงสั่งผลิตฟอนต์ทรูไทป์
เลือกช่วงฟอนต์ที่ต้องการ -> Hints -> AutoHint
Hints -> AutoInstr
Files -> Generates Fonts
ทดลองแล้วได้ผลดีพอควร
ถ้าผ่านข้อกำหนดดังกล่าว การ Hint จะได้ผลดีที่สุด
ค้นไปค้นมา ไปพบฟอนต์ที่เป็นฟรีแวร์และ gpl สรุปได้ดังนี้
มีฟอนต์สวย ๆ มากจริง ๆ
ทำฟอนต์เอง มาตายตรง hinting มือไม่ถึง :P เวลาไม่เอื้อให้ศึกษา
แต่ก็ยังชอบใจ โลมาบุตรอยู่ดี ;D
ฟอนต์ 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/
ศึกษาการทำ TrueType Hinting Instruction
การทำ Truetype Hinting Instructions
$ ttx FONT.ttf
ฟอนต์รุ่นนี้เป็นรุ่นลัดคิว
'ccmp' Glyph Composition/Decomposition in Thai lookup 2"
เล็กน้อย เพื่อให้แสดงระดับวรรณยุกต์ได้ถูกต้อง เราจะให้อยู่ในชื่อ DroidSansThai... <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> ...
ดาวน์โหลดไฟล์ฟอนต์ (ล่าสุดคือ 20100812)
ดาวน์โหลดไฟล์ซอร์ส
ทดสอบภาษาลาว
ภาพตัวอย่าง
ภาพจากบราวเซอร์ epiphany
ตัวธรรมดา
ตัวหนา
ลัดคิว #3
ทำฟอนต์ DroidSansMono เพิ่ม โดยทำทั้งภาษาไทยและลาว เสียดายที่ต้นฉบับไม่มีตัวหนา เลยทำแค่ตัวธรรมดาอย่างเดียว
ทำเป็นฟอนต์แบบ Monospace แท้ ๆ โดยใช้ต้นแบบตาราง Lookup จากฟอนต์ TlwgTypo
ดาวน์โหลดไฟล์ฟอนต์ (ล่าสุดคือ 20100917)
ดาวน์โหลดไฟล์ซอร์ส
ทดสอบภาษาลาว
ภาพตัวอย่าง
ภาพจากบราวเซอร์ epiphany
ตัวธรรมดา
ลัดคิว #2
ทำฟอนต์ DroidSerif เพิ่ม ถึงจะมีที่ใช้น้อย แต่ก็ทำไว้เพื่อให้แสดงผลได้สมบูรณ์ ทำทั้งภาษาไทยและลาว
Droid Serif ThaiLao
และ font family preferred เป็น Droid Serif
ดังนั้น ถ้าเราติดตั้งฟอนต์ fonts-droid จะสามารถใช้ภาษาไทยและลาวจากฟอนต์ Droid Serif ThaiLao ได้ภายใต้ชื่อ Droid Serif (ยกเว้น Inkscape ต้องใช้ Droid Serif Web แทน)24!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` Aabcdefghijklmnopqrstuvwxyz{|}~ mrnrtodocode ṃāñūṭḍṇṅ
aกัขิฃีคึฅืฆุงูจฺฉ็ช่ซ้ฌ๊ญ๋ญุฎ์ฏํฐ๎ฐูฑั่ฒิ้ณี๊ดื๋ติ์ถะทาธำน่ำเบี่แปิํโผใฝ่ไพฟ้ภมยรฤๅลฦวศษสหฬอฮฯๆ ฿๏๐๑๒๓๔๕ ๖๗๘๙๚๛ ก่ป่ฝ้ฟ๊ฬ๋ คฅศ ดตฒ ญฐญานํ ญฐญานํ โสตฺถิํ
ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝໞໟ
24!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` Aabcdefghijklmnopqrstuvwxyz{|}~ mrnrtodocode ṃāñūṭḍṇṅ
aกัขิฃีคึฅืฆุงูจฺฉ็ช่ซ้ฌ๊ญ๋ญุฎ์ฏํฐ๎ฐูฑั่ฒิ้ณี๊ดื๋ติ์ถะทาธำน่ำเบี่แปิํโผใฝ่ไพฟ้ภมยรฤๅลฦวศษสหฬอฮฯๆ ฿๏๐๑๒๓๔๕ ๖๗๘๙๚๛ ก่ป่ฝ้ฟ๊ฬ๋ คฅศ ดตฒ ญฐญานํ ญฐญานํ โสตฺถิํ
ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝໞໟ
24!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` Aabcdefghijklmnopqrstuvwxyz{|}~ mrnrtodocode ṃāñūṭḍṇṅ
aกัขิฃีคึฅืฆุงูจฺฉ็ช่ซ้ฌ๊ญ๋ญุฎ์ฏํฐ๎ฐูฑั่ฒิ้ณี๊ดื๋ติ์ถะทาธำน่ำเบี่แปิํโผใฝ่ไพฟ้ภมยรฤๅลฦวศษสหฬอฮฯๆ ฿๏๐๑๒๓๔๕ ๖๗๘๙๚๛ ก่ป่ฝ้ฟ๊ฬ๋ คฅศ ดตฒ ญฐญานํ ญฐญานํ โสตฺถิํ
ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝໞໟ
24!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` Aabcdefghijklmnopqrstuvwxyz{|}~ mrnrtodocode ṃāñūṭḍṇṅ
aกัขิฃีคึฅืฆุงูจฺฉ็ช่ซ้ฌ๊ญ๋ญุฎ์ฏํฐ๎ฐูฑั่ฒิ้ณี๊ดื๋ติ์ถะทาธำน่ำเบี่แปิํโผใฝ่ไพฟ้ภมยรฤๅลฦวศษสหฬอฮฯๆ ฿๏๐๑๒๓๔๕ ๖๗๘๙๚๛ ก่ป่ฝ้ฟ๊ฬ๋ คฅศ ดตฒ ญฐญานํ ญฐญานํ โสตฺถิํ
ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝໞໟ
24!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` Aabcdefghijklmnopqrstuvwxyz{|}~ mrnrtodocode ṃāñūṭḍṇṅ
aกัขิฃีคึฅืฆุงูจฺฉ็ช่ซ้ฌ๊ญ๋ญุฎ์ฏํฐ๎ฐูฑั่ฒิ้ณี๊ดื๋ติ์ถะทาธำน่ำเบี่แปิํโผใฝ่ไพฟ้ภมยรฤๅลฦวศษสหฬอฮฯๆ ฿๏๐๑๒๓๔๕ ๖๗๘๙๚๛ ก่ป่ฝ้ฟ๊ฬ๋ คฅศ ดตฒ ญฐญานํ ญฐญานํ โสตฺถิํ
ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝໞໟ
24!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` Aabcdefghijklmnopqrstuvwxyz{|}~ mrnrtodocode ṃāñūṭḍṇṅ
aกัขิฃีคึฅืฆุงูจฺฉ็ช่ซ้ฌ๊ญ๋ญุฎ์ฏํฐ๎ฐูฑั่ฒิ้ณี๊ดื๋ติ์ถะทาธำน่ำเบี่แปิํโผใฝ่ไพฟ้ภมยรฤๅลฦวศษสหฬอฮฯๆ ฿๏๐๑๒๓๔๕ ๖๗๘๙๚๛ ก่ป่ฝ้ฟ๊ฬ๋ คฅศ ดตฒ ญฐญานํ ญฐญานํ โสตฺถิํ
ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝໞໟ
เอา Lomaputta - โลมาบุตร ซึ่งเอามาจากฟอนต์โลมาของ ltn: ThaiFonts-Scalable มาทำเรื่อง hinting
ตอนทำ hinting จริง ๆ ต้องปรับลายเส้นจากเดิมเยอะเหมือนกัน
ดาวน์โหลดไฟล์ฟอนต์(20100602)
ดาวน์โหลดไฟล์ซอร์ส
SROUND
Lomaputta-src-20090506.tar.gzภาพตัวอย่าง
จากบราวเซอร์ epiphany
ตัวธรรมดา
ตัวหนา
เอาฟอนต์นรสีห์จาก ltn: ThaiFonts-Scalable มาทำเรื่อง hinting
แทบไม่เปลี่ยนลายเส้นเลย คงรูปเดิมให้มากที่สุด แปลงแต่จุด เพื่อให้เหมาะกับการทำ hinting
ดาวน์โหลดไฟล์ฟอนต์ (20100625)
ดาวน์โหลดไฟล์ซอร์ส
ภาพตัวอย่าง
จาก Epiphany Browser
ตัวธรรมดา
ตัวหนา
เอาฟอนต์ Roboto มาใส่ภาษาไทย โดยเอาโครงฟอนต์ Roboto (20%) + Droid Sans (30%) + Garuda (50%)
จุดประสงค์คือจะนำไปใช้ทดสอบ Android ICS
Roboto
ใช้งานภายใต้ชื่อ Roboto แต่ต้องมีการลงแพ็กเกจหรือปรับตั้งอื่น ดังนี้fonts-roboto
แล้วสามารถใช้งานผ่านชื่อฟอนต์ Roboto ได้เลย (ยกเว้น Inkscape ให้ใช้ Roboto Web แทน)/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> ...
24!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` Aabcdefghijklmnopqrstuvwxyz{|}~ mrnrtodocode ṃāñūṭḍṇṅ
aกัขิฃีคึฅืฆุงูจฺฉ็ช่ซ้ฌ๊ญ๋ญุฎ์ฏํฐ๎ฐูฑั่ฒิ้ณี๊ดื๋ติ์ถะทาธำน่ำเบี่แปิํโผใฝ่ไพฟ้ภมยรฤๅลฦวศษสหฬอฮฯๆ ฿๏๐๑๒๓๔๕ ๖๗๘๙๚๛ ก่ป่ฝ้ฟ๊ฬ๋ คฅศ ดตฒ ญฐญานํ ญฐญานํ โสตฺถิํ
ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝໞໟ
24!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` Aabcdefghijklmnopqrstuvwxyz{|}~ mrnrtodocode ṃāñūṭḍṇṅ
aกัขิฃีคึฅืฆุงูจฺฉ็ช่ซ้ฌ๊ญ๋ญุฎ์ฏํฐ๎ฐูฑั่ฒิ้ณี๊ดื๋ติ์ถะทาธำน่ำเบี่แปิํโผใฝ่ไพฟ้ภมยรฤๅลฦวศษสหฬอฮฯๆ ฿๏๐๑๒๓๔๕ ๖๗๘๙๚๛ ก่ป่ฝ้ฟ๊ฬ๋ คฅศ ดตฒ ญฐญานํ ญฐญานํ โสตฺถิํ
ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝໞໟ
24!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` Aabcdefghijklmnopqrstuvwxyz{|}~ mrnrtodocode ṃāñūṭḍṇṅ
aกัขิฃีคึฅืฆุงูจฺฉ็ช่ซ้ฌ๊ญ๋ญุฎ์ฏํฐ๎ฐูฑั่ฒิ้ณี๊ดื๋ติ์ถะทาธำน่ำเบี่แปิํโผใฝ่ไพฟ้ภมยรฤๅลฦวศษสหฬอฮฯๆ ฿๏๐๑๒๓๔๕ ๖๗๘๙๚๛ ก่ป่ฝ้ฟ๊ฬ๋ คฅศ ดตฒ ญฐญานํ ญฐญานํ โสตฺถิํ
ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝໞໟ
24!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` Aabcdefghijklmnopqrstuvwxyz{|}~ mrnrtodocode ṃāñūṭḍṇṅ
aกัขิฃีคึฅืฆุงูจฺฉ็ช่ซ้ฌ๊ญ๋ญุฎ์ฏํฐ๎ฐูฑั่ฒิ้ณี๊ดื๋ติ์ถะทาธำน่ำเบี่แปิํโผใฝ่ไพฟ้ภมยรฤๅลฦวศษสหฬอฮฯๆ ฿๏๐๑๒๓๔๕ ๖๗๘๙๚๛ ก่ป่ฝ้ฟ๊ฬ๋ คฅศ ดตฒ ญฐญานํ ญฐญานํ โสตฺถิํ
ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝໞໟ
24!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` Aabcdefghijklmnopqrstuvwxyz{|}~ mrnrtodocode ṃāñūṭḍṇṅ
aกัขิฃีคึฅืฆุงูจฺฉ็ช่ซ้ฌ๊ญ๋ญุฎ์ฏํฐ๎ฐูฑั่ฒิ้ณี๊ดื๋ติ์ถะทาธำน่ำเบี่แปิํโผใฝ่ไพฟ้ภมยรฤๅลฦวศษสหฬอฮฯๆ ฿๏๐๑๒๓๔๕ ๖๗๘๙๚๛ ก่ป่ฝ้ฟ๊ฬ๋ คฅศ ดตฒ ญฐญานํ ญฐญานํ โสตฺถิํ
ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝໞໟ
24!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` Aabcdefghijklmnopqrstuvwxyz{|}~ mrnrtodocode ṃāñūṭḍṇṅ
aกัขิฃีคึฅืฆุงูจฺฉ็ช่ซ้ฌ๊ญ๋ญุฎ์ฏํฐ๎ฐูฑั่ฒิ้ณี๊ดื๋ติ์ถะทาธำน่ำเบี่แปิํโผใฝ่ไพฟ้ภมยรฤๅลฦวศษสหฬอฮฯๆ ฿๏๐๑๒๓๔๕ ๖๗๘๙๚๛ ก่ป่ฝ้ฟ๊ฬ๋ คฅศ ดตฒ ญฐญานํ ญฐญานํ โสตฺถิํ
ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝໞໟ
24!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` Aabcdefghijklmnopqrstuvwxyz{|}~ mrnrtodocode ṃāñūṭḍṇṅ
aกัขิฃีคึฅืฆุงูจฺฉ็ช่ซ้ฌ๊ญ๋ญุฎ์ฏํฐ๎ฐูฑั่ฒิ้ณี๊ดื๋ติ์ถะทาธำน่ำเบี่แปิํโผใฝ่ไพฟ้ภมยรฤๅลฦวศษสหฬอฮฯๆ ฿๏๐๑๒๓๔๕ ๖๗๘๙๚๛ ก่ป่ฝ้ฟ๊ฬ๋ คฅศ ดตฒ ญฐญานํ ญฐญานํ โสตฺถิํ
ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝໞໟ
24!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` Aabcdefghijklmnopqrstuvwxyz{|}~ mrnrtodocode ṃāñūṭḍṇṅ
aกัขิฃีคึฅืฆุงูจฺฉ็ช่ซ้ฌ๊ญ๋ญุฎ์ฏํฐ๎ฐูฑั่ฒิ้ณี๊ดื๋ติ์ถะทาธำน่ำเบี่แปิํโผใฝ่ไพฟ้ภมยรฤๅลฦวศษสหฬอฮฯๆ ฿๏๐๑๒๓๔๕ ๖๗๘๙๚๛ ก่ป่ฝ้ฟ๊ฬ๋ คฅศ ดตฒ ญฐญานํ ญฐญานํ โสตฺถิํ
ກະຂັຄາງ່ຳຈິ່ຊີ້ຍຶ໊ດື໋ຕຸ່ຖູ້ທົ໊ນຼ໋ເບແປໂຜໃຝໄພຟ່ມ້ຢ໊ຣ໋ລ໌ວໍສຫອຮຯຽໆ ໐໑໒໓໔໕໖໗໘໙ ໜໝໞໟ
ทำฟอนต์เพื่อทดแทน Tahoma ตั้งชื่อว่า "เตยหอม" (Taeyhom)
พยายามทำให้คอมแพตกับ Tahoma 100% ยกเว้นตัวเลขไทย ของเดิมความกว้างไม่เท่ากัน แต่ของเราทำให้เท่ากันตามมาตรฐาน
ดาวน์โหลดไฟล์ฟอนต์ (ล่าสุดคือ 20100531)
ดาวน์โหลดไฟล์ซอร์ส
MD, MPPEM, SDPVTL, MUL, DIV, IF, EIF
) ยังงง ๆ อยู่DELTAC
)SROUND
ไปตามขนาด ppem ต่าง ๆ ทำให้ไม่จำเป็นต้องกำหนดค่า cvt ของกั้นหน้ากั้นหลังและความกว้างตัวอักษร (ถ้าใช้ได้ผลจะได้เอาไปใช้ในการสร้างฟอนต์ตัวต่อ ๆ ไป งานจะลดลงมาก) Taeyhom-src-20100503.tar.gzภาพตัวอย่าง
ภาพจากบราวเซอร์ epiphany และ oo.o
ตัวธรรมดาที่ hint แล้ว
ตัวธรรมดา
ตัวหนาที่ hint แล้ว
ตัวหนา
เอา TlwgTypo จาก ltn: ThaiFonts-Scalable มาทำเรื่อง hinting
พอจะเริ่ม hint จริง ๆ พบว่าลายเส้นของไทยไม่เข้ากับของฝรั่ง ซึ่งจะทำให้การ hint ยุ่งยาก จึงตัดสินใจสร้างลายเส้นไทยขึ้นมาใหม่ และตั้งชื่อใหม่ว่า TlwgTypott
ดาวน์โหลดไฟล์ฟอนต์(520421)
ดาวน์โหลดไฟล์ซอร์ส
ภาพตัวอย่าง
จาก abiword (openoffice แสดงผลเพี้ยน)
ตัวธรรมดา
ตัวหนา
ความรู้ที่ได้
เอาฟอนต์ Waree - วารี จาก ltn: ThaiFonts-Scalable มาทำเรื่อง hinting
ต้องขออภัยที่ต้องปรับความกว้างฟอนต์จากเดิม เพื่อให้เหมาะกับการทำ hinting ดังนั้นจึงไม่สามารถใช้แทนกันได้อย่างสนิท
ดาวน์โหลดไฟล์ฟอนต์(รุ่น 20090603)
ดาวน์โหลดไฟล์ซอร์ส
ภาพตัวอย่าง
จาก openoffice.org รุ่น 3.0.1
ตัวธรรมดา
ตัวหนา
เอาลายเส้นจาก Waree Sans มาทำเป็น Monospace แต่ทำเป็นแบบไม่ใช่ความกว้างคงที่แท้ ๆ คือสระและวรรณยุกต์ทำเป็นแบบความกว้างเป็นศูนย์ เพื่อให้ใช้งานกับ Openoffice.org ได้
ทำแล้วดูแล้วยังไม่ค่อยสวย เพราะความกว้างฟอนต์อังกฤษเดิมแคบไป จึงทำให้สัดส่วนฟอนต์ไทยดูสูงชลูดไปหน่อย
ดาวน์โหลดไฟล์ฟอนต์(รุ่น 20090613)
ดาวน์โหลดไฟล์ซอร์ส
ภาพตัวอย่าง
จาก openoffice.org รุ่น 3.0.1
ตัวธรรมดา
ตัวหนา
เอาภาษาไทยจากฟอนต์ 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
ตัวธรรมดา
ตัวหนา
เพิ่งเริ่มทำนะครับ
ขั้นตอน
งาน
งานของฟอนต์ตัวนี้คือ เริ่มศึกษาการทำ ตาราง Lookups - GPOS โดยใช้ภาษาลาวเป็นต้นแบบ คือ
download ttf
download src
screenshot
OpenOffice.org-2.4 แสดงผลที่ ppem ต่าง ๆ
รุ่นล่าสุด 520207
รุ่นแรก
บันทึกการแปลงฟอนต์ Waree เป็น DejaVuSansThai รุ่นแรก
dfont.py
เอาไว้คลี่และเรียงสแต็ก ใช้ได้ผลดีพอควร แต่สคริปต์ยังขาดการตรวจสอบความถูกต้องของ instructing code ซึ่งถ้าใช้ด้วยพารามิเตอร์ --all
อาจทำให้ fontforge หยุดการทำงานได้ - รอปรับปรุงต่อไปความรู้ที่ได้
MIRP
(ซึ่งต้องอ้างค่าจาก cvt - Control Value Table) มีความแม่นยำแน่นอนกว่าการเคลื่อนค่าแบบ direct (เช่นคำสั่ง MDRP
)ip
(Interpolate) จะทำให้ฟอนต์ดูฟุ้ง แต่ระยะที่ได้ แน่นอนกว่าการเคลื่อนจุดแบบ direct (เว้นเสียแต่ถ้าไม่มีการทดลงจุด คืออาร์กิวเมนต์ rnd
ควรใช้ MDRP
เสมอ ไม่งั้นบางทีอาจเพี้ยน)rnd
ห้ามใช้คำสั่ง SHPIX
ที่จุดนั้นเด็ดขาด จะมีปัญหาเลอะตอนพิมพ์ โดยเฉพาะในแนวแกน Yผลการทดลอง - บนลินุกซ์ ความละเอียดจอภาพ 85 dpi
ดาวน์โหลดไฟล์ฟอนต์ ttf ล่าสุด (รุ่น 520401)
ดาวน์โหลดไฟล์ซอร์ส
งานที่เหลือ และที่ตั้งใจจะทำ
ภาพตัวอย่างของรุ่นล่าสุด
ตัวหนา
ภาพจาก OpenOffice.org รุ่นล่าสุด
oo ตัวหนา
ภาพตัวอย่าง รุ่นแรก (จากจอภาพขนาด 85 dpi)
dfont.py
การทำงานแค่คลี่และเรียงแสต็กใหม่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))
เที่ยวนี้ไม่มีอะไร บันทึกตัวอย่างการ 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
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 เป็นต้นไปsrp0 26จากจุดเริ่มต้น จะเคลื่อนจุดอ้างอิง rp0 ไปยังจุดที่ใกล้ขอบซ้ายที่สุด คือจุด 18 เพื่อกั้นเป็นระยะช่องไฟด้านหน้า ด้วยค่า cvt คือ front_kai
mirp[rp0,min,rnd,grey] front_kai 18จุดที่จะไปต่อคือ จุด 8 แต่เนื่องจากเมื่อเคลื่อนไปแล้ว ไม่มีจุดที่จะไปต่อ เราจึงไม่ต้องเคลื่อนจุด rp0 ไปด้วย จึงไม่ต้องใส่อาร์กิวเมนต์ rp0
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 เสมอ
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
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]จบแล้วครับ
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
...
}
ภาพลายเส้น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
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]เสร็จแล้ว
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]
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
...
}
ภาพลายเส้น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
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
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]เสร็จแล้ว
View -> Grid Fit -> Show Grid Fit -> 17pt 72dpi
ได้ภาพดังนี้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 |
SVTCA[x-axis]ใส่ delta hint โดยใส่จำนวนคู่ไว้เป็นค่าแรก
deltap1 8 2 143 39 143 0 143 1 143 3 141 38 141 37 139 4 139ภาพหลังการขยับแล้วจะป็นดังนี้
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
บันทึกการสร้างฟอนต์ DejaVu Serif Thai
ผลการทดลอง
ปรับปรุง
(เนื่องจากเป็นการทำงานไปด้วย ศึกษาไปด้วย การทำ hinting จึงไม่เป็นอันหนึ่งอันเดียวกันในทุก ๆ ฟอนต์ที่ทำ ต้องขออภัยด้วย)
ดาวน์โหลดไฟล์ฟอนต์ ttf
ดาวน์โหลดซอร์ส
ภาพตัวอย่าง (จากขนาดจอภาพ 72 dpi จึงกำหนดระยะเป็น ppem แทนเพื่อป้องกันสับสน)
ต้องการทำฟอนต์ที่ใช้ในงานโฆษณา แต่ไม่แปลงรูปฟอนต์มากนัก ให้มีหัวบาง ๆ อยู่ทุกตัว ตั้งชื่อว่า อุโฆษ (Ukhosa) สร้างโดยเอาโครงฟอนต์โลมาบุตรมาแปลง
ดาวน์โหลดไฟล์ฟอนต์ (20100707)
ดาวน์โหลดไฟล์ซอร์ส
ภาพตัวอย่าง
จาก Epiphany Browser
ตัวธรรมดา
ตัวหนา
$ 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
$ 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ไม่เหมือนเป๊ะ แต่น่าจะทำงานได้เหมือนกัน