Theppitak's blog

My personal blog.

14 สิงหาคม 2558

Patani Malay Support in Fonts-TLWG with Teochew Experiment

โครงการ fonts-tlwg กำลังอยู่ระหว่างพัฒนาเพิ่มเติมให้รองรับภาษาชาติพันธุ์ที่เขียนด้วยอักษรไทยได้สมบูรณ์ยิ่งขึ้น โดยรอบนี้เจาะไปที่ภาษามลายูปาตานีที่นอกจากจะต้องผ่อนคลายกฎการซ้อนอักขระต่าง ๆ แล้ว ยังต้องการอักขระเพิ่มเติมจากบล็อคยูนิโค้ดภาษาไทยอีก 4 ตัว เพื่อเป็นเครื่องหมายกำกับเสียงอ่าน กล่าวคือ:

  • U+0303 COMBINING TILDE คือสัญลักษณ์ตัวหนอนที่เขียนกำกับเหนือพยัญชนะเพื่อให้ออกเสียงขึ้นจมูก (เสียงนาสิก) คงได้แนวคิดจากตัว ñ ในภาษาสเปน
  • U+0331 COMBINING MACRON BELOW คือสัญลักษณ์ขีดเส้นใต้พยัญชนะเพื่อตัดเสียงนาสิกออกจากพยัญชนะนาสิกของไทย 4 ตัว คือ ง ญ น ม
  • U+02BC MODIFIER LETTER APOSTROPHE ใช้ในการลดรูปคำให้เหลือจำนวนพยางค์น้อยลง
  • U+02D7 MODIFIER LETTER MINUS ใช้ในการกล้ำสองพยางค์ให้ต่อเนื่องเป็นพยางค์เดียว

สองตัวหลังดูไม่มีอะไรมาก แค่เพิ่ม glyph ให้ก็ดูจะเพียงพอ แต่สองคัวแรกซึ่งเป็นอักขระประกอบ (combining character) ก็เลยมีปฏิสัมพันธ์กับสระบน-ล่าง วรรณยุกต์ และเครื่องหมายกำกับเสียงของไทย ทำให้ต้องมาจัดระเบียบใหม่ ซึ่งปรากฏว่าต้องทั้งขยับอักษรไทย ทั้งเปลี่ยนลำดับ normalization ของยูนิโค้ดด้วย

ตัวหนอนบอกเสียงนาสิกดูจะไม่มีประเด็นอะไรสำหรับภาษามลายูปาตานี เนื่องจากคำที่มีเครื่องหมายนี้จะไม่มีสระบนและวรรณยุกต์กำกับอยู่แล้ว ส่วนตัวขีดเส้นใต้ก็ควรขีดเส้นใต้พยัญชนะที่ความกว้างไม่เท่ากันให้สวยงามทั้งสี่ตัวด้วย (กล่าวคือ ไม่ใช่ใช้อักขระเดียวขีดเส้นใต้อักขระทุกตัว แต่ความยาวของขีดควรปรับตามความกว้างของพยัญชนะด้วย) รวมทั้งต้องตัดเชิง ญ เมื่อขีดเส้นใต้ด้วย

ก็ดูไม่ยุ่งยากอะไร ตัวหนอนก็แค่ทำประหนึ่งมันเป็นสระอิอีอึอือเสียก็จบ ส่วนตัวขีดเส้นใต้ก็สร้าง ligature glyph สำหรับ ง ญ น ม ขีดเส้นใต้สำเร็จรูปเท่านั้นเอง ผลออกมาก็งามน่าแล

Patani Malay text using Garuda

แต่ช้าก่อน ฟีเจอร์ของภาษามลายูปาตานีฟังดูน่าสนใจไม่น้อยสำหรับคนพูดภาษาแต้จิ๋วอย่างผม

  • เสียงนาสิกเป็นตัวแยกความหมายของคำในภาษาแต้จิ๋ว ภาษาไทยมีเสียงนาสิกแค่ไม่กี่เสียง คือ ง ญ ณ น ม ถ้าพยัญชนะต้นไม่ใช่เสียงพวกนี้ก็จะไม่ออกเสียงขึ้นจมูก (ญ ไม่มีเสียงนาสิกในไทยกลาง แต่ยังมีในไทยอีสาน [ดู blog เก่าประกอบ] และอาจจะมี ห ฮ ที่ยังขึ้นจมูกบ้างไม่ขึ้นบ้างแล้วแต่สำเนียง) แต่ภาษาแต้จิ๋วสามารถขึ้นจมูกได้ทุกพยางค์ และยังเป็นตัวแยกความหมายอีกด้วย เช่น คำว่า 碗 ที่แปลว่า ชาม จะออกเสียงเป็น อั้ว พร้อมเสียงขึ้นจมูก ซึ่งจะแตกต่างจากคำว่า 我 ที่เป็นสรรพนามบุรุษที่หนึ่งเอกพจน์ ซึ่งออกเสียงเป็น อั้ว เหมือนกันแต่ไม่ขึ้นจมูก ในเมื่อเสียงนาสิกมีความสำคัญถึงขนาดแยกความหมายของคำในภาษาแต้จิ๋วเช่นนี้ ตัวหนอนกำกับเสียงนาสิกของมลายูปาตานีจึงน่าจะนำมาใช้กับแต้จิ๋วได้
  • พยัญชนะที่ตัดเสียงนาสิกในภาษาแต้จิ๋วก็มี เช่นในคำว่า 牛 ที่แปลว่า วัว จะออกเสียงเป็น ก๎งู๊ คือเป็น ง ที่กล้ำกับเสียง ก ที่คอและไม่ขึ้นจมูก เสียงพยัญชนะนี้ไม่มีในภาษาไทย และมีความยากลำบากในการเขียนด้วยอักษรไทยมาก ตัวขีดเส้นใต้ตัดเสียงนาสิกของมลายูปาตานีก็น่าจะนำมาใช้ได้เช่นกัน

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

ในการทำฟอนต์นั้น ไม่ใช่ว่าเราจะรองรับเฉพาะอักขรวิธีที่กำหนดไว้เท่านั้น แต่ยังควรเตรียม fallback สำหรับรองรับการแสดงผลรูปแบบที่อยู่นอกเหนือจากที่กำหนดด้วยตามสมควร ถึงแม้ไม่มีโจทย์ภาษาแต้จิ๋ว ก็ต้องคิดเผื่ออยู่แล้วว่าจะจัดการกับกรณีทั่วไปที่อยู่นอกเหนือข้อกำหนดของภาษามลายูปาตานีอย่างไร การมีโจทย์สมมุติของภาษาแต้จิ๋วเช่นนี้ก็เท่ากับทำให้เห็นแนวทางชัดเจนยิ่งขึ้น

ประเด็นของโจทย์ก็คือ:

  • ตัวหนอนนาสิก ฐานข้อมูลอักขระยูนิโค้ดกำหนดให้มี combining class 220 ในขณะที่วรรณยุกต์ไทยเป็น class 107 ตามหลัก normalization ของยูนิโค้ด จะเรียงลำดับอักขระที่อยู่ระหว่างอักขระ class 0 (ได้แก่พยัญชนะบนบรรทัด) ตามลำดับ combining class จากน้อยไปหามาก (เรียกว่า canonical order) ผลคือ เมื่อตัวหนอนนาสิกผสมกับวรรณยุกต์ไทย rendering engine จะสลับมันไปอยู่หลังวรรณยุกต์ก่อนส่งให้ฟอนต์แสดงผลเสมอ แต่สิ่งที่เราต้องการคือวางตัวหนอนก่อนวรรณยุกต์ เพื่อให้อยู่ชิดพยัญชนะ แล้วจึงซ้อนวรรณยุกต์ทับทีหลัง ดังนั้น ฟอนต์จะต้องรู้จักกลับลำดับคืนด้วย แต่ถ้ามีสระบนมาคั่นกลางก็ไม่ต้องทำอะไร เพราะสระบน, ไม้ไต่คู้, ทัณฑฆาต, นิคหิต, ยามักการ ต่างถูกกำหนด combining class เป็น 0 เหมือนพยัญชนะบนเส้นบรรทัด จึงเป็นจุดกั้นแบ่งโซนการเรียงลำดับ combining character โดยปริยาย
  • ตัวขีดเส้นใต้ ฐานข้อมูลอักขระยูนิโค้ดกำหนดให้มี combining class 220 ในขณะที่สระอุ สระอู มี combining class เป็น 103 (แต่ Uniscribe และ Harfbuzz แก้เองให้เป็น 3 ด้วยเหตุผลใดไม่อาจทราบได้) และพินทุมี combining class เป็น 9 ทำให้ตัวขีดเส้นใต้จะถูก rendering engine normalize ให้ไปอยู่หลังสระล่างและพินทุเสมอ และถ้ามีวรรณยุกต์ก็จะเลื่อนไปอยู่หลังวรรณยุกต์ด้วย แต่สิ่งที่เราต้องการคือวางตัวขีดเส้นใต้ก่อนเพื่อน เพื่อให้อยู่ชิดพยัญชนะ ดังนั้น ฟอนต์จะต้องรู้จักกลับลำดับคืนด้วย
  • พินทุกับสระล่าง ตาม combining class ในฐานข้อมูลอักขระยูนิโค้ดแล้ว พินทุ (class 9) จะต้องมาก่อนสระล่าง (class 103) ใน canonical order ซึ่งเป็นสิ่งที่ต้องการอยู่แล้วสำหรับภาษามลายูปาตานี แต่ด้วยเหตุผลกลใดไม่ทราบได้ Uniscribe ของไมโครซอฟท์ได้แก้ทับคลาสของสระล่างจาก 103 เป็น 3 ทำให้สระล่างมาก่อนพินทุ และเพื่อความเข้ากันได้กับ Uniscribe ทำให้ Harfbuzz ก็ทำอย่างเดียวกันด้วย สิ่งที่ฟอนต์ต้องทำคือกลับลำดับนี้คืนอีกชั้นหนึ่ง

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

แต่ปัญหาของตัวขีดเส้นใต้ซับซ้อนกว่าที่คาดไว้มาก เพราะมีประเด็นอื่นที่ต้องพิจารณาร่วมด้วยอีก 2 ประเด็น คือ

  • การขีดเส้นใต้ ง ญ น ม ซึ่งความกว้างไม่เท่ากัน จัดการได้ด้วยการสร้าง precomposed glyph ที่ขีดเส้นใต้พยัญชนะดังกล่าวเสร็จสรรพ (ตัดเชิงสำหรับ ญ ไปในตัว) พร้อมกฎ ligature สำหรับเปลี่ยนคู่อักขระให้เป็นตัว precomposed กฎนี้ต้องทำงานในขณะที่พยัญชนะดังกล่าวกับตัวขีดเส้นใต้อยู่ติดกัน
  • กฎเดิมที่จัดการกรณีคำว่า ปู่ ซึ่งจะเปลี่ยนวรรณยุกต์ให้เป็นตัวต่ำพร้อมกับสลับสระล่างกับวรรณยุกต์ให้วรรณยุกต์มาก่อน เพื่อจะได้วางหลบหาง ป ฝ ฟ (และอาจจะ ฬ) ด้วย GPOS ได้ กฎนี้ต้องทำงานในขณะที่สระล่างตามหลังด้วยวรรณยุกต์ทันที

การเพิ่มกฎสำหรับกลับลำดับตัวขีดเส้นใต้จึงต้องระวังที่จะไม่ไปกีดขวางการทำงานของกฎดังกล่าวด้วย โดยถ้าทำก่อน ตัวขีดเส้นใต้ก็จะมาขวางกฎ ปู่ ให้ไม่ทำงาน และถ้าทำทีหลัง วรรณยุกต์จากกฎ ปู่ ก็จะมาขวางกฎสร้าง precomposed glyph ให้ไม่ทำงาน

หลังจากคิดและทดลองอยู่หลายตลบ ผมก็ได้ข้อสรุปเป็นลำดับกฎว่าดังนี้ :-

สตริงเริ่มแรก: C + Macron + BV + T
Uniscribe/Harfbuzz: C + BV + T + Macron
1: สลับ T กับ Macron C + BV + Macron + T
2: สลับ BV กับ Macron C + Macron + BV + T
3: ligature C-Macron-lig + BV + T || C + Macron + BV + T
3: สลับ Macron กับ BV C + BV + Macron + T
4: สลับ Macron กับ T C + BV + T + Macron
general composition C + T.low + BV + Macron
5: สลับ BV กับ Macron C + T.low + Macron + BV

กล่าวคือ เริ่มจากเลื่อนตัวขีดเส้นใต้ไปชิดกับพยัญชนะก่อนเพื่อให้กฎ ligature ทำงาน และถ้าตัวขีดเส้นใต้ไม่ได้ทำให้เกิด ligature ก็เลื่อนกลับที่เดิมเพื่อให้กฎ ปู่ ใน general composition ทำงาน จากนั้นจึงสลับตัวขีดเส้นใต้ให้มาก่อนสระล่าง ก็เป็นอันได้ลำดับที่เราต้องการ

กรณีลำดับของพินทุกับสระล่างที่ Uniscribe/Harfbuzz แปลงสารมาก็ทำนองเดียวกัน มีความซับซ้อนเล็กน้อย แต่ก็แค่กับกฎ ปู่ เท่านั้น :-

สตริงเริ่มแรก: C + Ph + BV + T
Uniscribe/Harfbuzz: C + BV + Ph + T
1: สลับพินทุกับ BV C + Ph + BV + T
general composition: C + Ph + T.low + BV
2: สลับพินทุกับ T.low C + T.low + Ph + BV

กล่าวคือ สลับพินทุกับสระล่างกลับให้เป็นเหมือนเดิม แล้วปล่อยให้กฎ ปู่ ใน general composition ทำงาน เสร็จแล้วก็เลื่อนวรรณยุกต์ตัวต่ำให้เข้าไปชิดกับพยัญชนะ

ผลที่ได้ดูจะทำงานได้ดีเมื่อทำ stress test ด้วยภาษาแต้จิ๋ว:

Experimental Teochew text using Garuda

และเนื่องจาก requirement ในเรื่องตัวหนอนนาสิกและตัวขีดเส้นใต้ของภาษาแต้จิ๋ว เป็น superset ของมลายูปาตานี การผ่านการทดสอบด้วยภาษาแต้จิ๋วย่อมถือว่าครอบคลุมภาษามลายูปาตานีโดยปริยาย

สังเกตว่า ในขณะที่ทำภาษามลายูปาตานีในขั้นแรกนั้น ผมลืมกรณีที่พยัญชนะขีดเส้นใต้มีสระล่างไปเสียสนิทด้วยซ้ำ การเล่นกับภาษาแต้จิ๋วยังช่วยจับบั๊กนี้ให้ด้วย

เมื่อทดลองกับฟอนต์ Garuda เป็นที่พอใจแล้ว ก็มาสรุปขั้นตอนทุกอย่างอีกครั้งกับฟอนต์ Kinnari:

Experimental Teochew text using Kinnari

แล้วก็ใช้ฟอนต์ Kinnari เป็นแบบสำหรับฟอนต์อื่น ๆ ต่อไป โดยเริ่มจากฟอนต์ Norasi:

Experimental Teochew text using Norasi

ตอนนี้ทำถึงขั้นนี้เท่านั้นครับ ยังมีฟอนต์อื่น ๆ อีกสิบกว่าฟอนต์ในชุด fonts-tlwg ที่ผมจะค่อยทยอยทำต่อไปเมื่อมีเวลาว่าง คาดว่าคงใช้เวลาอีกหลายเดือน :-P

ผมสร้าง หน้าทดสอบ โดยใช้ web font ที่สร้างจากตัวล่าสุดที่อยู่ระหว่างพัฒนาไว้ด้วย คงจะอัปเดตไปเรื่อย ๆ ตามความคืบหน้าครับ

ในอีกด้านหนึ่ง ก็ได้ อภิปรายและเสนอแพตช์ สำหรับ Harfbuzz เพื่อขอตัดการ override combining class ของสระล่างของไทยเสียด้วย ดูจะได้รับความเห็นชอบ แต่ยังไม่ apply เสียที อาจจะเกรงความไม่เข้ากันกับ Uniscribe หรือเปล่าก็ไม่ทราบได้ แต่การแก้ในฟอนต์ที่ผมทำไปก็เท่ากับทำให้มันทำงานบนวินโดวส์ได้ด้วย

ป้ายกำกับ: ,

hacker emblem