Theppitak's blog

My personal blog.

23 มกราคม 2551

"ปู่" Bug Fixed for ThaiLaTeX

ตามธรรมเนียมแต่กาลก่อนนั้น หลังจากที่ thaifonts-scalable ออกรุ่นใหม่ ก็จะมี thailatex ออกตามมาไม่ห่างกันนัก โดยปรับรุ่นฟอนต์ใหม่มาใช้ใน thailatex แต่ด้วยเหตุปัจจัยหลาย ๆ อย่าง ทำให้มี thaifonts-scalable ออกมาโดยไร้เงาของ thailatex ถึง 3 รุ่น (0.4.6 - 0.4.8) โดย thailatex รุ่นล่าสุด ออก เมื่อปลายปี 2549

อย่ากระนั้นเลย ควรเราจะออก thailatex รุ่นใหม่ตาม thaifonts-scalable 0.4.9 ที่ เพิ่งออก เสียหน่อย

ผมสร้างฟอนต์จาก thaifonts-scalable 0.4.9 สำหรับ thailatex ไว้แล้วใน CVS โดยเพิ่มฟอนต์ใหม่ทั้ง 4 ฟอนต์ คือ กินรี, สวัสดี, วารี และอัมพุชด้วย

แต่นอกเหนือจากนั้น ก็มีการ กระทุ้ง จากคุณอานนท์ เกี่ยวกับบั๊กเรื่อง "ปู่" ที่ค้างคามานาน คือ thailatex จะจัดพิมพ์คำนี้โดยวางไม้เอกผิดตำแหน่ง อันเนื่องมาจากข้อจำกัดของ LIGKERN ใน virtual font ของ TeX ที่อ้างถึง context ได้ทีละสองอักขระ แต่จะจัดการไม้เอกของ "ปู่" ได้ จะต้องใช้ context ถึงสามอักขระ ทำให้เขียนกฎที่ซับซ้อนเพียงพอไม่ได้ (ยินข่าวว่า Omega ได้แก้ข้อจำกัดนี้แล้ว.. จะว่าไป ถึงยุคนี้แล้วก็น่าจะ ลอง Omega บ้างเหมือนกัน หรือจะเป็น XeTeX ที่คุณ fat dog father เคย ชวน ไว้ ก็น่าสนใจ)

ปัญหา LIGKERN ของ TeX กับภาษาไทยนี้ คุณ Werner Lemberg ได้เคยเสนอวิธีแก้ไว้ในบทความ "Thai Fonts" ใน TUGboat Volume 21, Number 2, June 2000 โดยใช้ trick กับ afm2tfm ที่ใช้ encoding vector สองชุดในการสร้าง virtual font ถ้า hack กระบวนการสร้างฟอนต์ดี ๆ จะทำให้ใช้รหัส glyph สองชุดที่อ้างถึง glyph เดียวกันได้ ทำให้สามารถเขียนกฎจัดการกรณี "ปู่" ภายใต้กรอบของ LIGKERN ของ TeX ได้

หลักการของเขาก็คือ afm2tfm ใช้ encoding vector สองชุด ชุดหนึ่งสำหรับ TeX (คือไฟล์ *.enc) ซึ่งจะ map หมายเลข glyph ใน TeX ไปเป็นชื่อ glyph และอีกชุดหนึ่งสำหรับ Postscript (คือไฟล์ *.afm) ซึ่งจะ map ชื่อ glyph ไปเป็นหมายเลข glyph ซึ่งเมื่อใช้ร่วมกันก็จะทำให้อ้าง glyph ต่าง ๆ ในฟอนต์ Postscript จากใน TeX ได้ โดยใช้ encoding ที่กำหนดโดย TeX เอง โดยเมื่อ afm2tfm สร้าง virtual font ก็จะ map จากหมายเลขถึงหมายเลข (ผ่านชื่อ) แล้วดึงข้อมูล metrics ของ glyph จาก AFM มาเติมใน VPL ที่สร้างให้เลย หรือถ้ามีการอ้างถึง glyph เดียวกันจากมากกว่าหนึ่งค่าใน encoding vector ก็จะระบุ map จากหมายเลขถึงหมายเลขที่ resolve ชื่อเรียบร้อยแล้วลงในแฟ้ม VPL เลย

ในการเรียก afm2tfm โดยทั่วไปสำหรับภาษาไทย เราจะ reencode font ทั้งฝั่ง TeX และ Postscript ด้วย vector เดียวกัน (โดยใช้ตัวเลือก -T) เพราะหลังจากที่เราใช้ยูนิโค้ดกันแล้ว จำนวน glyph ในฟอนต์มักจะเกินขนาด glyph index 8 บิต ทำให้บาง glyph ในฟอนต์ Postscript ไม่สามารถอ้างด้วย index ได้ ก็เลยบังคับให้ใช้ index ของ TeX เสีย จากนั้น ก็ไปเพิ่มค่าตั้งใน dvips เพื่อให้ตอน render (ด้วย xdvi หรือ dvips) มีการ reencode ฟอนต์กลับผ่านแฟ้ม *.enc ของ TeX เพื่อให้ได้ชื่อ glyph สำหรับแต่ละ index ที่อ้าง เพื่อนำไปดึง glyph จากฟอนต์ Postscript มาวาดต่อไป

จากการที่ afm2tfm ใช้ map สอง map ดังกล่าว ก็เปิดช่องให้เราสามารถสร้าง glyph เทียมของสระล่างขึ้นมาอีกชุด เพื่อไว้อ้างใน LIGKERN rules สำหรับกรณี "ปู่" ให้ต่างจากกรณีอย่าง "บู่" ได้ โดยสร้าง TeX map แบบนี้:

  [ ..., foo, ..., bar, ... ]

และ Postscript map อย่างนี้:

  [ ..., bar, ..., bar, ... ]

ผลคือ ใน Postscript map จะมีการสร้าง map ในช่อง bar ทั้งสอง ให้ map ไปยัง glyph เดียวกัน แต่ใน TeX map จะสามารถอ้างด้วยชื่อ foo กับ bar แยกกันได้

แต่โชคไม่ดี ที่ afm2tfm สามารถสร้างข้อมูลสำหรับ glyph ที่มีใน AFM ได้เท่านั้น เราจึงเสก foo ขึ้นมาใช้เป็นสระล่างชุดใหม่ไม่ได้ในทันที (ในเมื่อฟอนต์ปกติไม่มี glyph สระอุซ้าย เป็นต้น) จำเป็นต้องมีการ hack เล็กน้อย และ hack นี้แหละ ที่เป็นส่วนที่ tricky ที่สุดใน paper นี้

โดยสร้าง dummy AFM ขึ้นมา ให้มี glyph foo ที่ต้องการเสีย แล้วก็ใช้ generate VPL ที่มีข้อมูล ligature เตรียมไว้

จากนั้น ก็แยก *.enc ออกมาอีกแฟ้มหนึ่ง เปลี่ยน encoding vector ให้เป็นแบบหลังที่มีแต่ bar ไม่มี foo เพื่อใช้ generate VPL จาก AFM ของฟอนต์จริง

จากนั้นก็ merge VPL กัน โดยเอาข้อมูล LIGTABLE จาก VPL ที่มี ligature มาใส่แทน LIGTABLE ใน VPL ที่สร้างจากฟอนต์จริง

ผลคือ จะได้ VPL ที่มี glyph ของสระล่างสองชุด ที่อ้างไปยัง glyph ชุดเดียว พร้อม LIGTABLE ที่จัดวางสระล่างของ "ปู่" กับ "บู่" ด้วยคนละ glyph เดียวกัน

Q.E.D.!!!

ปล. commit แล้วครับ เฮือก!

ป้ายกำกับ: ,

2 ความเห็น:

  • 18 กันยายน 2552 08:55 , Blogger yut แถลง…

    หวัดดีครับ
    ผมสนใจเรื่องพัฒนาซอฟต์แวร์ภาษาไทยมานานแล้ว แต่กรณีการ display ฟอนต์บน linux นี้ไม่คุ้นเคยนัก

    ฟังเรื่อง บู่ หรือ ปู่ แล้วเกิดสงสัยว่าทำไมไม่ใช้เทคนิดเดียวกับที่เค้าทำใน windows หรือ ใน mac ล่ะครับ คือ ใช้ glyph ของ ไม้เอกมากกว่า 1 glyph ในการแก้ปัญหาเรื่องตำแหน่ง โดยแต่ละ glyph วางตำแหน่งไว้ไม่เหมือนกัน แล้วในกลไกการ display ก็เพียงแค่สลับ glyph ให้ถูกเท่านั้น

    อาจเป็นคำถามเชยๆ เพราะไม่คุ้นเคยกับระบบครับ ต้องขออภัยล่วงหน้า
    ศรายุทธ

     
  • 18 กันยายน 2552 11:14 , Blogger Thep แถลง…

    ตามที่ได้กล่าวไว้แล้วข้างบนนะครับ ว่า

    "อันเนื่องมาจากข้อจำกัดของ LIGKERN ใน virtual font ของ TeX ที่อ้างถึง context ได้ทีละสองอักขระ แต่จะจัดการไม้เอกของ "ปู่" ได้ จะต้องใช้ context ถึงสามอักขระ ทำให้เขียนกฎที่ซับซ้อนเพียงพอไม่ได้"

    ต้องเข้าใจว่า โครงสร้างของ TeX ยังไม่ได้มี hook ให้เกี่ยวออกมาทำเรื่องนี้ด้วยโค้ดได้ แต่มีช่องทางของ virtual font ที่ปกติใช้จัดการ ligature ของอักขระ ที่ทำให้เอามาจัดตำแหน่งวรรณยุกต์ภาษาไทยได้ แต่ช่องทางนี้ก็มีข้อจำกัดอย่างที่ว่าครับ

     

แสดงความเห็น (มีการกลั่นกรองสำหรับ blog ที่เก่ากว่า 14 วัน)

<< กลับหน้าแรก

hacker emblem