บทเรียน typography · intermediate · 20 นาที
สระลอย สระจม — สาเหตุจริงและวิธีแก้ทุกโปรแกรม
อ่านหน้านี้ยังไง
สระลอยไม่ใช่ปัญหาเดียว แต่เป็นอาการเดียวของสาเหตุที่ต่างกันสี่แบบ และวิธีแก้ของแต่ละแบบไม่เหมือนกันเลย บทความส่วนใหญ่บนหน้าแรกของ Google บอกวิธีติ๊กช่องหนึ่งช่องในโปรแกรมหนึ่งโปรแกรม ซึ่งได้ผลก็ต่อเมื่อคุณบังเอิญเจอสาเหตุที่ตรงกับบทความนั้น หน้านี้เริ่มจากการวินิจฉัยก่อน แล้วค่อยแก้
หน้านี้เขียนให้ผู้อ่านสองกลุ่ม แยกกันชัดเจน กลุ่มแรกคือ นักออกแบบที่เจอปัญหาในโปรแกรม — ข้ามไปที่หัวข้อวินิจฉัยแล้วต่อด้วยหัวข้อของโปรแกรมที่คุณใช้ กลุ่มที่สองคือ คนทำฟอนต์ที่ฟอนต์ของตัวเองเป็นต้นเหตุ — ข้ามไปที่หัวข้อ “สำหรับคนทำฟอนต์” ท้ายหน้า ซึ่งลงลึกถึงตารางที่ต้องมีในไฟล์ฟอนต์
นิยามให้ตรงกันก่อน: สระลอย กับ สระจม
สระลอยคือเครื่องหมายที่ไม่ยึดกับพยัญชนะฐาน มันลอยไปวางที่ตำแหน่งเริ่มต้นของตัวมันเอง ส่วนสระจมคือเครื่องหมายที่ยึดถูกตัวแต่ไม่ยกชั้น จึงไปทับสระหรือวรรณยุกต์อีกตัวที่อยู่ก่อนหน้า ทั้งสองอาการมาจากตารางเดียวกันในไฟล์ฟอนต์ คนละส่วนกัน — สระลอยมาจากการไม่มีข้อมูล mark-to-base ส่วนสระจมมาจากการไม่มีข้อมูล mark-to-mark
Microsoft นิยามชั้นการวางเครื่องหมายของไทยไว้ 7 คลาส: ABOVE1 (U+0E31, U+0E34–U+0E37) คือสระบนชั้นที่ติดพยัญชนะที่สุด, ABOVE2 (U+0E47, U+0E4D), ABOVE3 (U+0E48–U+0E4B ซึ่งคือวรรณยุกต์ทั้งสี่), ABOVE4 (U+0E4C, U+0E4E), BELOW1 (U+0E38, U+0E39), BELOW2 (U+0E3A) และ AM (U+0E33) ภาษาไทยซ้อนเครื่องหมายได้ถึงสี่ชั้นเหนือพยัญชนะ นี่คือเหตุผลว่าทำไม mkmk จึงเป็นของจำเป็น ไม่ใช่ของขัดเกลา คำว่า น้ำ ต้องวาง ้ (ABOVE3) เหนือส่วนบนของ ำ ที่ถูกแตกออกมา — ถ้าฟอนต์ไม่มีข้อมูลชั้น มันก็ทับกันเป็นก้อน
วินิจฉัยใน 4 ขั้น — ขั้นตอนที่ไม่มีใครเขียน
ก่อนแก้อะไร ให้แยกก่อนว่าความผิดอยู่ที่ไฟล์ฟอนต์หรืออยู่ที่โปรแกรม วิธีแยกคือเอาข้อความชุดเดียวกันไปเปิดในเบราว์เซอร์ด้วยฟอนต์ตัวเดียวกัน เบราว์เซอร์สมัยใหม่รัน shaping engine เต็มรูปแบบเป็นค่าเริ่มต้น จึงใช้เป็นตัวควบคุมได้ดี ขั้นตอนต่อไปนี้เป็นวิธีทำงานของกองบรรณาธิการ ThaiGraph ไม่ใช่ขั้นตอนที่ผู้ผลิตซอฟต์แวร์รายใดประกาศ
ขั้นที่ 1 — ใช้ชุดข้อความทดสอบมาตรฐาน พิมพ์บรรทัดนี้: ญุ ฐู ป้ำ ที่ น้ำ ก็ อ์ ห้าคำแรกกวาดครบทุกกรณีที่ฟอนต์มักพัง — สระใต้ใต้พยัญชนะที่มีเชิง (ญุ ฐู), สระอำกับวรรณยุกต์ (ป้ำ น้ำ), วรรณยุกต์เหนือสระบน (ที่) และเครื่องหมายชั้นสองกับชั้นสี่ (ก็ อ์)
ขั้นที่ 2 — เปิดชุดเดียวกันในเบราว์เซอร์ ถ้าเบราว์เซอร์ก็แสดงผิดเหมือนกัน แปลว่าไฟล์ฟอนต์เป็นต้นเหตุ ไปที่สาเหตุ A หรือ C ถ้าเบราว์เซอร์แสดงถูกแต่โปรแกรมของคุณแสดงผิด แปลว่าโปรแกรมไม่ได้เปิด shaping ไปที่สาเหตุ B
ขั้นที่ 3 — แยกสาเหตุ A ออกจาก C พิมพ์วรรณยุกต์เดี่ยว ๆ โดยไม่มีพยัญชนะนำ เช่น ้ ตัวเดียว ฟอนต์ที่สร้างตามสเปกจะแสดงเป็นวงกลมประ (U+25CC) ล้อมเครื่องหมายไว้ ถ้าได้กล่องขาวหรือช่องว่าง แปลว่าฟอนต์ไม่มี glyph วงกลมประ ซึ่งเป็นสัญญาณชัดว่าฟอนต์นี้ไม่ได้ทำตามสเปกฟอนต์ไทย — คาดได้เลยว่าไม่มี mark/mkmk ด้วย (สาเหตุ A) แต่ถ้าฟอนต์เป็นไฟล์เก่ายุค TIS-620 ที่คุณได้มาจากแผ่นซีดีหรือไดรฟ์เก่าของออฟฟิศ และพิมพ์ตัวอักษรบางตัวแล้วได้อักขระคนละตัวไปเลย นั่นคือสาเหตุ C
ขั้นที่ 4 — เช็กว่าใช่สระลอยจริงไหม ซูมเข้าไป 400% ถ้าเครื่องหมายเกาะพยัญชนะถูกต้องทุกตัวแต่ยอดวรรณยุกต์ถูกตัดหายที่ขอบบนของกล่องข้อความหรือชนบรรทัดบน นั่นไม่ใช่สระลอย นั่นคือ line-height หรือกรอบข้อความแคบเกิน (สาเหตุ D) และแก้ที่เลย์เอาต์ ไม่ใช่ที่ฟอนต์ ค่ามาตรฐานที่เราใช้อยู่ใน คู่มือไทโปกราฟีสองภาษา
สาเหตุ A — ฟอนต์ไม่มีตาราง mark และ mkmk
เอกสารพัฒนาฟอนต์ไทยของ Microsoft ทำเครื่องหมายว่า “จำเป็น” ไว้กับฟีเจอร์เพียงสองตัวคือ mark (mark-to-base) และ mkmk (mark-to-mark) ทั้งคู่อยู่ในตาราง GPOS ส่วน ccmp และ kern อยู่ในเอกสารแต่ไม่ได้ถูกทำเครื่องหมายว่าจำเป็น ฟอนต์ที่ส่งออกมาโดยไม่มีข้อมูล anchor ของสองตัวนี้ ไม่มีคำสั่งใดบอกเอนจินว่าสระหรือวรรณยุกต์ควรไปอยู่ตรงไหน เครื่องหมายจึงตกลงที่จุดกำเนิดของ advance ตัวเอง — และนั่นคือสิ่งที่ผู้ใช้เห็นเป็นสระลอย
นี่คือสาเหตุที่พบบ่อยที่สุดในฟอนต์ฟรีที่คนทำเองแล้วปล่อยออกมา รวมถึงฟอนต์ลายมือที่ทำผ่านเว็บแปลงลายมือเป็นฟอนต์ ผู้ตั้งกระทู้ Pantip 39922367 เขียนไว้ว่า “สระที่จะต้องอยู่บน-ล่างพยัญชนะมันกลับไม่อยู่ค่ะ” และระบุว่าฟอนต์ตัวเดียวกันแสดงผลปกติบน Facebook แต่ผิดพลาดในแอป GoodNotes — ซึ่งเป็นเหตุผลที่ขั้นวินิจฉัยด้านบนให้ทดสอบข้อความชุดเดียวกันมากกว่าหนึ่งที่เสมอ
วิธีแก้ในฐานะผู้ใช้มีทางเดียว: เปลี่ยนฟอนต์ ไม่มีการตั้งค่าใดในโปรแกรมใดที่เติมข้อมูลที่ไม่มีอยู่ในไฟล์ให้ได้ ถ้าคุณต้องการฟอนต์ลายมือที่วางสระถูก เริ่มจาก หมวดฟอนต์ลายมือของ ThaiGraph ซึ่งทุกรายการผ่านการเปิดไฟล์ตรวจแล้ว และถ้าตั้งใจจะทำฟอนต์ของตัวเองให้ถูกตั้งแต่แรก อ่าน คู่มือทำฟอนต์ ก่อนลงมือ
สาเหตุ B — โปรแกรมไม่ได้เปิด shaping ของสคริปต์ซับซ้อน
ฟอนต์อาจสมบูรณ์แบบ แต่ถ้าโปรแกรมจัดข้อความไทยเหมือนสคริปต์ธรรมดาที่เรียงซ้ายไปขวา มันจะไม่เรียกตาราง GPOS เลย Illustrator เป็นตัวอย่างที่ชัดที่สุด — Adobe ระบุไว้เองว่าไทยอยู่ในกลุ่ม South East Asian ที่ต้องใช้ Middle Eastern and South Asian composer จนกว่าจะเลือก composer นั้น Illustrator จะวางไทยเป็นสคริปต์ธรรมดาและไม่ขยับเครื่องหมายเลย นี่คือสาเหตุที่แก้ได้ในสิบวินาที และเป็นสาเหตุที่บทความหน้าแรกส่วนใหญ่พูดถึง
สาเหตุ C — ฟอนต์เก่าก่อนยุค Unicode
ฟอนต์ไทยยุค TIS-620 / Windows-874 ไม่ได้ใช้ OpenType positioning เลย มันเก็บ glyph สำเร็จรูปไว้ที่ตำแหน่งรหัสตายตัว แล้วให้ไดรเวอร์คีย์บอร์ดหรือโปรแกรม DTP เป็นตัวสลับให้ เอกสารของเทพพิทักษ์ การุญบุญญานันท์ ระบุชื่อรูปเหล่านี้ไว้ตรง ๆ: “Low MAI EK” (ไม้เอกลดระดับ), “Low-left MAI THO”, “Left SARA I”, “Desc-less YO YING” เอกสาร shaping สมัยใหม่ยังคงเก็บโมเดล PUA เก่านี้ไว้ พร้อมคำสั่งเชิงบริบทสี่แบบ — SHIFT_DOWN, SHIFT_LEFT, SHIFT_DOWN_AND_LEFT และ REMOVE_DESCENDER ที่แก้ผ่าน state machine ไปยัง glyph ใน Private Use Area
เปิดฟอนต์แบบนี้ในโปรแกรม Unicode สมัยใหม่ กลไกทั้งหมดนั้นไม่ทำงาน เครื่องหมายจึงตกที่ตำแหน่งเริ่มต้น วิธีแก้คือหาฟอนต์รุ่น Unicode ที่เทียบเท่า ข้อควรระวังหนึ่งเรื่อง: อย่าใช้ TH Sarabun PSK เป็นตัวอย่างของฟอนต์ที่วางสระผิด เพราะผู้ออกแบบ ศุภกิจ เฉลิมลาภ ระบุกับ Beartai ว่าความต่างระหว่าง PSK กับ TH Sarabun New อยู่ที่ความคมชัดในขนาดเล็กบนจอความละเอียดต่ำเป็นหลัก และ “โดยทางกายภาพของฟอนต์แล้ว ไม่ว่าจะเป็นหน้าตา ช่องไฟ ระยะบรรทัดฯ ทุกอย่างเหมือนกัน”
สาเหตุ D — ไม่ใช่สระลอย แต่เป็นการตัดขอบ
อาการที่ถูกเข้าใจผิดบ่อยที่สุด: เครื่องหมายเกาะถูกตำแหน่งทุกอย่าง แต่ยอดวรรณยุกต์ถูกตัดหายที่ขอบบนของกล่อง หรือส่วนหางถูกตัดที่ขอบล่าง ไทยกินพื้นที่แนวตั้งสี่ชั้น ในขณะที่ลาตินกินสองชั้น ตั้ง line-height แบบลาตินกับข้อความไทยแล้ววรรณยุกต์จะหายไปครึ่งตัว บนเว็บ อาการนี้มาจาก overflow: hidden บนภาชนะที่สูงตายตัว หรือ line-height ต่ำกว่า 1.5 ในโปรแกรมออกแบบ มาจากกรอบ text frame ที่สูงไม่พอ
แก้ใน Adobe Illustrator
เปิด Edit > Preferences > Type แล้วติ๊ก “South East Asian Options” จากนั้นเปิดเมนู flyout ของแผง Paragraph แล้วเลือก “Middle Eastern & South Asian Every-line Composer” Adobe ระบุว่าใน Preferences > Type เลือกได้ทีละหนึ่งเท่านั้นระหว่างตัวเลือกอินดิกกับตัวเลือกเอเชียตะวันออก/ตะวันออกเฉียงใต้ จากนั้นตั้ง Language ที่แผง Character เป็น Thai — ค่าที่เลือกได้ในกลุ่มนี้คือ Thai, Burmese, Lao, Sinhalese และ Khmer
จุดที่ต้องแก้ความเข้าใจ: บทความไทยเกือบทุกบทความ รวมถึงบทความที่ติดอันดับสูงสุด สั่งให้ติ๊ก “Show Indic Options” ไทยเป็นสคริปต์เอเชียตะวันออกเฉียงใต้ ไม่ใช่สคริปต์อินดิก และเอกสาร Adobe ฉบับปัจจุบันแยก “South East Asian Options” ออกเป็นช่องต่างหากที่เปิดพร้อมกับช่องอินดิกไม่ได้ คำแนะนำเดิมมาจากบทความปี 2018 (ปรับปรุง 2022) ซึ่งเก่ากว่าการแยกช่องนี้ ถ้าคุณติ๊กช่องอินดิกแล้วยังไม่หาย นี่คือเหตุผล
หลังเปลี่ยน composer ข้อความที่พิมพ์ไว้ก่อนหน้าอาจต้องเลือกใหม่แล้วสั่งใช้ composer อีกครั้ง เพราะ composer ผูกกับย่อหน้า ไม่ใช่กับเอกสาร
แก้ใน Adobe Photoshop
ถ้าคุณใช้ Photoshop 23.0 (ตุลาคม 2021) ขึ้นไป คุณไม่ต้องทำอะไร — Unified Text Engine ที่สร้างบน HarfBuzz รองรับ shaping ของไทยเป็นค่าเริ่มต้นบน text layer ใหม่ทุกอัน และ Adobe ถอด UI สำหรับสลับ composer ใต้ Preferences > Type ออกไปแล้ว บทเรียนไทยทุกบทที่บอกให้เลือก “Middle Eastern and South Asian Layout” จากเมนู flyout ของแผง Paragraph กำลังอธิบาย Photoshop รุ่นก่อน 23.0 หรือกำลังอธิบาย text layer แบบ legacy
ถ้ายังเจอปัญหาใน Photoshop รุ่นใหม่ ให้ไล่สองอย่างนี้ หนึ่ง — เลเยอร์นั้นเป็น legacy text layer ที่มาจากไฟล์เก่า สร้างเลเยอร์ใหม่แล้ววางข้อความซ้ำ สอง — ตั้งภาษาผิด Adobe แนะนำให้ตั้งภาษาที่แผง Character และถ้าเลือกภาษาไทยให้ใช้ฟอนต์ไทย เช่น Adobe Thai หรือ Noto Sans Thai
แก้ใน Microsoft Word
Word จัด shaping ไทยให้เองอยู่แล้ว ไม่มี composer ให้สลับ ปัญหาจริงของ Word คือฟอนต์แยกร่าง — กล่องโต้ตอบ Font มีช่องเลือกฟอนต์สองช่องคือ “Latin text” และ “Complex scripts” และมีเพียงช่อง Complex scripts เท่านั้นที่ควบคุมข้อความไทย ตั้งเฉพาะช่องลาตินแล้วไทยจะยังอยู่บนฟอนต์ default ของ complex scripts ซึ่งมักเป็น Angsana New ช่องฟอนต์จะแสดงชื่อว่า “Latin text” ก็ต่อเมื่อเปิดการรองรับ Asian text หรือ Complex scripts ในระบบแล้วเท่านั้น และผู้ใช้ Word 2016 ภาษาไทยรายงานไว้ที่ Microsoft Q&A ว่าหลังบันทึกแล้วเปิดไฟล์ใหม่ อักขระอย่าง ( ) % - . ที่ตั้งเป็น Calibri ถูกสลับกลับไปเป็น Angsana New เอง ซึ่งเป็นอาการที่ไม่เกิดใน Word 2010 และ 2013
อาการที่สองของ Word ไม่ใช่สระลอย แต่เป็น Word ไม่ยอมให้พิมพ์ และมันมีชื่อเรียกอย่างเป็นทางการว่า Sequence Checking Microsoft อธิบายไว้ในบทความของ Sirirat Reinikka และ Wirote Petchdenlarp ว่านี่คือกฎการพิมพ์สำหรับไทย ฮินดี และเวียดนาม ที่บังคับให้พิมพ์ได้เฉพาะลำดับอักขระที่ถูกต้อง คู่กับกฎ Type and Replace ที่ลบอักขระตัวก่อนแล้วแทนที่ด้วยตัวใหม่ในกลุ่มเดียวกัน แอป Office ส่วนใหญ่เปิดกฎนี้ให้อัตโนมัติเมื่อตั้งภาษาเริ่มต้นเป็นไทย
ผลข้างเคียงคือคนที่พิมพ์คำอ่านหรือข้อความบาลีจะเจอลำดับที่ Word ไม่ยอมรับ คู่มือพิมพ์คำอ่านของ slice-of-thai.com ระบุว่า Word 2007 และ 2010 ไม่ยอมให้พิมพ์ชุดสระผสมวรรณยุกต์บางชุด และวิธีแก้คือเข้า File > Options > Advanced แล้วเอาเครื่องหมายถูกออกจากช่อง “Use sequence checking” (ช่อง “Type and replace” อยู่ตรงเดียวกัน) ปิดแล้วคุณจะพิมพ์ลำดับที่ต้องการได้ แต่ต้องยอมรับว่าจะไม่มีตัวช่วยกันลำดับผิดอีกต่อไป
แก้ใน Canva
Canva ไม่มีการตั้งค่า composer และไม่มีอะไรเทียบเท่ากับของ Adobe — ในทางปฏิบัติ การแก้สระลอยใน Canva คือการเลือกฟอนต์ใหม่ ไม่ใช่การไปแก้ค่าใด ๆ ศูนย์ช่วยเหลือของ Canva เสนอเพียงสองทางคือเปลี่ยนภาษาของบัญชี หรือเปลี่ยนฟอนต์ และเตือนไว้เองว่าฟอนต์ที่อัปโหลดขึ้นสำเร็จอาจยังแสดงผลผิดพลาดตอนนำไปใช้ พร้อมแนะให้อัปโหลดฟอนต์อื่นที่รองรับเต็มรูปแบบแทน Canva รับเฉพาะ .OTF, .TTF หรือ .WOFF ไม่รับ .ZIP, .EOT, .SVG หรือ .WOFF2
ข้อสังเกตที่มีประโยชน์กับคนทำฟอนต์: นักออกแบบไทยบางรายปล่อยไฟล์ “เวอร์ชันสำหรับ Canva” แยกจากไฟล์ปกติ เพราะพฤติกรรมการวางเครื่องหมายบนแพลตฟอร์มนี้ไม่เหมือนที่อื่น ถ้าฟอนต์ที่คุณซื้อหรือดาวน์โหลดมามีไฟล์แยกแบบนั้น ให้ใช้ไฟล์นั้นใน Canva
แก้ใน Figma
Figma แสดงผลไทยใน text layer ได้ถูกต้อง บั๊กที่ยืนยันแล้วและยังเปิดอยู่ถูกจำกัดอยู่ที่ป้ายชื่อเฟรมที่วาดบนแคนวาสเท่านั้น ผู้รายงานสรุปไว้ว่าเอนจินวาดภาพบนแคนวาสดูเหมือนไม่ได้ใช้กฎในตาราง GPOS ตอนวาดป้ายชื่อเฟรม ในขณะที่ text layer และช่องกรอกข้อความแสดงผลถูกต้อง รายงานเมื่อ 26 กุมภาพันธ์ 2026 และยังไม่มีคำตอบจากทีมงาน ณ วันที่เราเข้าถึง
แปลว่า: ถ้าสระลอยเฉพาะที่ชื่อเฟรมในแผงเลเยอร์หรือบนแคนวาส งานออกแบบของคุณไม่ได้พัง และ export ออกมาจะถูกต้อง ไม่ต้องเสียเวลาไล่แก้ฟอนต์ แต่ถ้าสระลอยใน text layer จริง ๆ ให้กลับไปที่ขั้นวินิจฉัย — สาเหตุอยู่ที่ไฟล์ฟอนต์
แก้บนเว็บและ CSS
กับดักที่ใหญ่ที่สุดบนเว็บคือ letter-spacing สเปก CSS Text Module Level 3 ของ W3C ใช้ภาษาไทยเป็นตัวอย่างของสคริปต์ที่ letter-spacing ใช้กับ grapheme cluster ตรง ๆ ไม่ได้ สเปกยกคำว่า คำ (U+0E04 + U+0E33) ซึ่งต้องแตก U+0E33 เป็น U+0E4D + U+0E32 ก่อนจึงจะเว้นระยะได้ถูก และยกคำว่า น้ำ (U+0E19 + U+0E49 + U+0E33) เป็นกรณีที่ซับซ้อนขึ้น พร้อมระบุว่าหน่วยที่เกี่ยวข้องกับ letter-spacing นั้นเล็กกว่า grapheme cluster ของ Unicode ผลในทางปฏิบัติคือ การใส่ letter-spacing กับข้อความไทยในเบราว์เซอร์ที่ implement ไม่ครบ จะแทรกช่องว่างระหว่างพยัญชนะกับสระของตัวมันเอง หน้าตาเหมือนสระลอยทุกประการ แต่ต้นเหตุคือ CSS ไม่ใช่ฟอนต์
/* ผิด — letter-spacing แทรกช่องว่างเข้าไปในพยางค์ */
.heading-th { letter-spacing: 0.05em; }
/* ถูก — เนื้อความไทยตั้ง letter-spacing เป็น 0 เสมอ
และเผื่อพื้นที่แนวตั้งให้เครื่องหมายสี่ชั้น */
.heading-th { letter-spacing: 0; line-height: 1.5; }
.body-th { letter-spacing: 0; line-height: 1.625; }
รายการตรวจอีกสองข้อสำหรับเว็บ หนึ่ง — ถ้าคุณ subset ไฟล์ webfont เอง อย่าลืมใส่ U+25CC และ U+200B ไว้ใน unicode-range ด้วย ไม่งั้นกลไก fallback หายไปทั้งชุด สอง — overflow: hidden บนภาชนะที่ล็อกความสูงไว้จะตัดยอดวรรณยุกต์ ซึ่งเป็นสาเหตุ D ไม่ใช่ปัญหาฟอนต์
สำหรับคนทำฟอนต์: ป้องกันตั้งแต่ต้นทาง
ถ้าฟอนต์ของคุณทำให้คนอื่นเจอสระลอย สิ่งที่ขาดคือข้อมูล anchor ใน GPOS ไม่ใช่รูปร่างตัวอักษร รายการต่อไปนี้คือสิ่งที่ต้องมีครบก่อนปล่อยฟอนต์ไทยออกไป ทุกข้ออ้างอิงเอกสารพัฒนาฟอนต์ไทยของ Microsoft และสเปกฟอนต์ไทยของเทพพิทักษ์ การุญบุญญานันท์
- mark (mark-to-base) — glyph เครื่องหมายทุกตัวต้องมี anchor และ mark class ส่วน glyph ฐานทุกตัวต้องนิยาม anchor แยกตามคลาสของเครื่องหมายที่มันรับได้ นี่คือตัวที่ทำให้สระ “เกาะ” พยัญชนะ ขาดตัวนี้ = สระลอย
- mkmk (mark-to-mark) — บอกว่าวรรณยุกต์ต้องยกขึ้นไปเหนือสระบนที่มีอยู่แล้ว ไทยซ้อนได้ถึงสี่ชั้น ขาดตัวนี้ = สระจม
- ccmp แตกสระอำ — U+0E33 ต้องถูกแตกเป็น U+0E4D (นิคหิต) + U+0E32 (สระอา) เพื่อให้ส่วนที่เป็นเครื่องหมายถูกวางตำแหน่งได้ และเอนจินต้องจำว่าทั้งสองมาจากสระอำเดิม
- ccmp สลับรูปตัดเชิง — เมื่อ ญ หรือ ฐ ตามด้วยสระใต้อย่างสระอุหรือสระอู ต้องสลับเป็นรูปไม่มีเชิงก่อน แล้วจึงให้ mark วางสระ ไม่งั้นสระชนหางพยัญชนะ
- glyph ทางเลือกตามตำแหน่ง — สเปกของเทพพิทักษ์ระบุชื่อไว้ชัด:
uni0E0D.descless,uni0E10.descless,uni0E48.lowถึงuni0E4C.low,uni0E4D.highและตัวเลือกเสริมuni0E47.highรวมประมาณ 8–9 glyph ที่มีอยู่เพื่อให้การวางตำแหน่งทำงานได้เท่านั้น - U+25CC และ U+200B — Microsoft ระบุว่าฟอนต์ไทยควรมี glyph วงกลมประ ไม่งั้นเครื่องหมายที่ไม่ถูกต้องจะแสดงเป็นกล่องขาว และควรมี ZWSP เพราะไทยไม่เว้นวรรคระหว่างคำ ZWSP คือช่องที่ขยายตอนจัดข้อความแบบ justify
ลำดับที่เอนจินเรียกใช้คือ GSUB locl แล้ว ccmp จากนั้น GPOS kern, mark, mkmk ตามเอกสาร shaping ของ n8willis และสำคัญมาก: ตารางฟีเจอร์ของ Microsoft ระบุ ccmp เป็นฟีเจอร์ GSUB ตัวเดียวในรายการ ส่วน locl ทำแค่สลับ glyph ตามภาษาของ text run เท่านั้น กฎการแทนที่ตามบริบทของไทยทั้งหมดจึงต้องลงทะเบียนใต้ ccmp
ทำไมเครื่องมือลายมือยอดนิยมทำไม่ได้
Calligraphr รุ่นฟรีจำกัดที่ 75 ตัวอักษรต่อฟอนต์ รุ่น Pro ที่ 600 ตัวอักษร โดยหน้าราคาแสดงให้ผู้เข้าชมจากไทยเป็น ฿300 สำหรับหนึ่งเดือน หรือ ฿200 ต่อเดือนเมื่ออัปเกรดแบบ 6 เดือน — แต่โควตาตัวอักษรไม่ใช่ข้อจำกัดที่แท้จริงสำหรับภาษาไทย เอกสารของ Calligraphr ระบุผลลัพธ์ OpenType ไว้เพียง Contextual Alternates และ ligatures ไม่ปรากฏการกล่าวถึง mark-to-base, mark-to-mark, anchor หรือการวางเครื่องหมายผสมเลย ซึ่งเป็นตารางที่ไทยต้องใช้ เราจึงประเมินว่าการอัปเกรดเป็น Pro เพื่อแก้สระลอยน่าจะเป็นการจ่ายเงินผิดปัญหา — ข้อสรุปนี้เป็นการอนุมานของ ThaiGraph จากฟีเจอร์ที่ Calligraphr ระบุไว้เทียบกับตารางฟีเจอร์จำเป็นของ Microsoft ไม่ใช่คำแถลงของผู้ผลิต
ข้อจำกัดนี้และทางออกทีละขั้นอยู่ใน คู่มือทำฟอนต์ลายมือตัวเองฟรี ส่วนทางที่ไม่เสียเงินและทำได้จริงคือ FontForge ซึ่งเป็นซอฟต์แวร์เสรีโอเพนซอร์ส ใช้ได้บน Windows, macOS และ GNU+Linux รุ่นเสถียรล่าสุดคือ 20251009 เส้นทางคือ Element > Font Info > Lookups > GPOS แล้วสร้าง lookup, สร้าง subtable และสร้าง anchor class ในนั้น โดยติดแท็กเป็น mark (mark-to-base) หรือ mkmk (mark-to-mark) นี่คือคำตอบที่ซื่อสัตย์ที่สุดสำหรับคนที่อยากได้ฟอนต์ลายมือไทยที่ถูกต้องโดยไม่มีงบ
สายการผลิตของ ThaiGraph ตรวจอะไรบ้าง
เราไม่ได้เขียนเรื่องนี้จากเอกสารอย่างเดียว — ThaiGraph ผลิตฟอนต์ของตัวเองชื่อ ThaiGraph Condensed 4 น้ำหนัก ต่อยอดจาก Anuphan ของ Cadson Demak ภายใต้ OFL 1.1 ด้วยสายการผลิตอัตโนมัติ และมีชุดตรวจ shaping ด้วย HarfBuzz รันกับไฟล์ที่ build เสร็จทุกน้ำหนัก ชุดตรวจนั้นตรวจสิ่งเดียวกับที่บทความนี้บอกให้คุณตรวจ: ไม่มี .notdef ในตัวอย่างข้อความไทยผสมลาติน, mark positioning ให้ค่า offset ไม่เป็นศูนย์, การซ้อนชั้นแบบ mkmk มีระยะแยกตรงกับต้นฉบับ, ccmp สลับ ญ เป็นรูปไม่มีเชิงเมื่อเจอสระอุ และสระอำถูกแตกเป็นนิคหิตกับสระอาจริง ถ้าข้อใดข้อหนึ่งไม่ผ่าน build นั้นถือว่าไม่ผ่าน
นี่คือเหตุผลที่รายการหกข้อด้านบนไม่ใช่ทฤษฎี มันคือสิ่งที่ทำให้ build ของเราพังเมื่อทำผิด
อ่านต่อ
ถ้าจะอ่านต่อเรื่องเดียว ให้อ่านเรื่องสัญญาอนุญาต — เพราะฟอนต์ที่แก้สระลอยให้คุณได้ อาจเป็นฟอนต์ที่คุณไม่มีสิทธิ์ใช้ในงานลูกค้า พิลลาร์ ไทโปกราฟีไทยฉบับสมบูรณ์ ครอบคลุมระบบการเขียนและโครงสร้างพยางค์ที่เป็นที่มาของทุกอย่างในหน้านี้ การปฏิวัติฟอนต์ไม่มีหัว อธิบายว่าทำไมฟอนต์ไม่มีหัวถึงจัดการชั้นเครื่องหมายต่างจากฟอนต์มีหัว ถ้ากำลังเลือกฟอนต์ใหม่แทนตัวที่พัง เริ่มที่ ฟอนต์ลายมือ หรือ ฟอนต์ไทยฟรี และก่อนใช้งานจริง อ่าน สัญญาอนุญาตฟอนต์ไทย ให้จบ — ฟอนต์ฟรีจำนวนมากฟรีเฉพาะการใช้ส่วนตัว ดู ทำเนียบฟอนต์ไทยทั้งหมด ได้ที่นี่
ตรวจสอบข้อมูลเมื่อ August 2026
แหล่งอ้างอิง
- ฟีเจอร์ OpenType ที่ 'จำเป็น' (Required) สำหรับฟอนต์ไทยมีเพียงสองตัวคือ mark (mark-to-base) และ mkmk (mark-to-mark) ทั้งคู่อยู่ในตาราง GPOS ส่วน ccmp และ kern อยู่ในเอกสารแต่ไม่ได้ถูกทำเครื่องหมายว่าจำเป็น—Microsoft Learn — 'Developing OpenType Fonts for Thai Script' (ตารางฟีเจอร์: mark GPOS required, mkmk GPOS required) (accessed Aug 11, 2026)
- Microsoft นิยามชั้นการวางเครื่องหมายของไทยไว้ 7 คลาส: ABOVE1 (U+0E31, U+0E34–U+0E37), ABOVE2 (U+0E47, U+0E4D), ABOVE3 (U+0E48–U+0E4B), ABOVE4 (U+0E4C, U+0E4E), BELOW1 (U+0E38, U+0E39), BELOW2 (U+0E3A) และ AM (U+0E33) เอนจินจะตรวจว่าไม่มีเครื่องหมายคลาสเดียวกันสองตัวบนพยัญชนะตัวเดียว—Microsoft Learn — 'Developing OpenType Fonts for Thai Script', หัวข้อ Invalid Combining Marks (accessed Aug 11, 2026)
- ฟอนต์ไทยควรมี glyph ของ U+25CC DOTTED CIRCLE ไม่เช่นนั้นเครื่องหมายที่ไม่ถูกต้องจะถูกแสดงเป็นกล่องขาว (.notdef) แทนกลไก fallback มาตรฐาน และ Microsoft แนะนำให้ใส่ U+200B ZWSP ด้วยเพราะภาษาไทยไม่เว้นวรรคระหว่างคำและ ZWSP คือช่องที่ขยายตอนจัดข้อความแบบ justify—Microsoft Learn — 'Developing OpenType Fonts for Thai Script', หัวข้อ Invalid Combining Marks (accessed Aug 11, 2026)
- Microsoft ระบุงานของ ccmp สำหรับไทยไว้สองอย่าง: แตก สระอำ (U+0E33) เพื่อให้วางส่วนที่เป็นเครื่องหมายได้ถูกตำแหน่ง และแทน ญ ด้วยรูปไม่มีเชิงเมื่อตามด้วยสระใต้ เช่น สระอุ/สระอู เพื่อไม่ให้สระชนหางพยัญชนะ—Microsoft Learn — 'Developing OpenType Fonts for Thai Script' (accessed Aug 11, 2026)
- สเปกฟอนต์ไทยของเทพพิทักษ์ การุญบุญญานันท์ ระบุ glyph ทางเลือกตามตำแหน่งที่ฟอนต์ไทยต้องมีเพิ่มจากคลัง Unicode: uni0E0D.descless (ญ), uni0E10.descless (ฐ), uni0E48.low ถึง uni0E4C.low, uni0E4D.high และตัวเลือกเสริม uni0E47.high—Theppitak Karoonboonyanan — 'Spec for Thai OpenType Font Creation', Linux Thai (สร้าง 2004-07-29, ปรับปรุง 2012-02-22) (accessed Aug 11, 2026)
- ฟอนต์ไทยยุคก่อน Unicode ไม่ได้ใช้ OpenType positioning เลย แต่เก็บ glyph สำเร็จรูปไว้ที่ตำแหน่งรหัสตายตัว (วรรณยุกต์ลดระดับ, เครื่องหมายเลื่อนซ้าย, พยัญชนะตัดเชิง) แล้วอาศัยไดรเวอร์คีย์บอร์ดหรือโปรแกรม DTP เป็นตัวสลับให้ เอกสารระบุชื่อรูปเหล่านี้ไว้ เช่น 'Low MAI EK', 'Low-left MAI THO', 'Left SARA I', 'Desc-less YO YING'—Theppitak Karoonboonyanan — 'Thai Script Shaping', Linux Thai (accessed Aug 11, 2026)
- การแตกสระอำในขั้นตอน shaping คือ U+0E33 → U+0E4D (นิคหิต) + U+0E32 (สระอา) และเอนจินต้องจำว่าทั้งสองส่วนมาจากสระอำเดิม ลำดับการทำงานของไทยคือ GSUB 'locl' แล้ว 'ccmp' ตามด้วย GPOS 'kern', 'mark', 'mkmk'—n8willis — opentype-shaping-documents, opentype-shaping-thai-lao.md (accessed Aug 11, 2026)
- Adobe Illustrator ไม่จัด shaping ภาษาไทยด้วย composer เริ่มต้น ไทยถูกจัดอยู่ในกลุ่ม South East Asian ที่ใช้ Middle Eastern and South Asian composer เปิดได้ที่ Edit > Preferences > Type แล้วเลือก 'South East Asian Options' จากนั้นเลือก composer จากเมนู flyout ของแผง Paragraph โดยเลือกได้ทีละหนึ่งระหว่าง South East Asian Options กับ Show Indic Options—Adobe Help — 'Composers for Asian scripts | Illustrator' (accessed Aug 11, 2026)
- คำแนะนำภาษาไทยที่แพร่หลายให้ติ๊ก 'Show Indic Options' ใน Illustrator มาจากบทความปี 2018 (ปรับปรุง 2022) ซึ่งเก่ากว่าการแยกตัวเลือก South East Asian ออกมาในเอกสารปัจจุบันของ Adobe—Grappik — 'วิธีแก้สระจม/ลอย บน Adobe Photoshop และ Illustrator แบบทีเดียวจบ' โดย อินทนนท์ ปัญญาโสภา เผยแพร่ 26/05/2018 ปรับปรุง 06/09/2022 เทียบกับเอกสาร Adobe Help ฉบับปัจจุบัน (accessed Aug 11, 2026)
- Photoshop 23.0 (ตุลาคม 2021) เปิดตัว Unified Text Engine ที่สร้างบน HarfBuzz ทำให้ text layer ใหม่รองรับ shaping ของสคริปต์ซับซ้อนรวมถึงไทยเป็นค่าเริ่มต้น และ UI สำหรับสลับ composer ใต้ Preferences > Type ถูกถอดออกแล้ว—Adobe Help — 'Unified Text Engine overview in Photoshop' (accessed Aug 11, 2026)
- ใน Photoshop ควรตั้งภาษาที่แผง Character และถ้าเลือกภาษาไทยควรใช้ฟอนต์ไทย เช่น Adobe Thai หรือ Noto Sans Thai—Adobe Help — 'Create documents using international languages, scripts, and text' (Photoshop) (accessed Aug 11, 2026)
- กล่องโต้ตอบ Font ของ Microsoft Office มีช่องเลือกฟอนต์แยกกันสองช่อง ช่องฟอนต์จะแสดงเป็น 'Latin text' ก็ต่อเมื่อเปิดการรองรับ Asian text หรือ Complex scripts (หรือทั้งคู่) ในระบบแล้ว และช่อง Complex scripts จะไม่มีผลกับเอกสารเลยตราบใดที่ไม่ได้พิมพ์ข้อความอาหรับ ฮีบรู ไทย หรือฮินดี—Microsoft Office Help — 'Text dialog box (Font tab)' และกระทู้ microsoft.public.word.international.features 'Complex scripts options in Font dialog box' (accessed Aug 11, 2026)
- ผู้ใช้ Word 2016 ภาษาไทยรายงานว่าเมื่อบันทึกแล้วเปิดไฟล์ใหม่ อักขระบางตัวเช่น ( ) % - . ที่ตั้งเป็นฟอนต์ลาตินอย่าง Calibri ถูกสลับไปเป็นฟอนต์ complex script ค่าเริ่มต้นคือ Angsana New เอง อาการนี้ไม่เกิดใน Word 2010 และ 2013—Microsoft Q&A — 'Bug in Word 2016 in Thai language (complex script)' (accessed Aug 11, 2026)
- กฎการพิมพ์ของ Microsoft Office สำหรับไทย ฮินดี และเวียดนาม เรียกว่า Sequence Checking ทำหน้าที่บังคับให้พิมพ์ลำดับอักขระที่ถูกต้องเท่านั้น คู่กับกฎ Type and Replace ที่ลบอักขระก่อนหน้าแล้วแทนที่ด้วยตัวใหม่ในกลุ่มเดียวกัน แอปพลิเคชัน Office ส่วนใหญ่เปิดกฎนี้อัตโนมัติเมื่อตั้งภาษาเริ่มต้นเป็นไทย ส่วน Word, Publisher และ Outlook เปิด-ปิดได้ที่ File > Options > Advanced ช่อง 'Use sequence checking' และ 'Type and replace'—Microsoft Learn (archive) — Sirirat Reinikka และ Wirote Petchdenlarp, 'How to Enable Sequence Checking and Type and Replace for Thai, Hindi and Vietnamese', 26 พฤษภาคม 2010 (accessed Aug 11, 2026)
- คู่มือพิมพ์คำอ่านภาษาไทยของ slice-of-thai.com ระบุว่า Word 2007 และ 2010 ไม่ยอมให้พิมพ์ชุดสระผสมวรรณยุกต์บางชุด และวิธีแก้คือเข้า Word Options > Advanced แล้วเอาเครื่องหมายถูกออกจากช่อง 'use sequence checking'—slice-of-thai.com — 'How to Type Pronunciation Guides' (accessed Aug 11, 2026)
- Canva ไม่มีการตั้งค่า composer สำหรับสคริปต์ซับซ้อน ศูนย์ช่วยเหลือเสนอเพียงการเปลี่ยนภาษาของบัญชีหรือเปลี่ยนฟอนต์ และเตือนว่าฟอนต์ที่อัปโหลดสำเร็จอาจยังแสดงผลผิดพลาดเมื่อนำไปใช้ Canva รับเฉพาะไฟล์ .OTF, .TTF หรือ .WOFF ไม่รับ .ZIP, .EOT, .SVG หรือ .WOFF2—Canva Help Center — 'Text doesn't display properly', 'Font upload error', 'Check file upload formats and requirements for Canva' (accessed Aug 11, 2026)
- Figma แสดงผลภาษาไทยใน text layer ได้ถูกต้อง แต่มีรายงานบั๊กที่ยังเปิดอยู่ว่าเอนจินวาดภาพบนแคนวาสไม่ได้ใช้กฎในตาราง GPOS ตอนวาดป้ายชื่อเฟรม ทำให้สระและวรรณยุกต์หลุดจากพยัญชนะเฉพาะที่ชื่อเฟรม รายงานเมื่อ 26 กุมภาพันธ์ 2026 และยังไม่มีคำตอบจากทีมงาน ณ วันที่เข้าถึง—Figma Forum — 'Thai script rendering broken on frame names: vowels and tone marks detached from consonants' (#51323) (accessed Aug 11, 2026)
- CSS Text Module Level 3 ใช้ภาษาไทยเป็นตัวอย่างว่าทำไม letter-spacing ถึงใช้กับ grapheme cluster ตรง ๆ ไม่ได้ โดยยกคำว่า คำ (U+0E04 + U+0E33) ซึ่งต้องแตก U+0E33 เป็น U+0E4D + U+0E32 ก่อน และคำว่า น้ำ (U+0E19 + U+0E49 + U+0E33) เป็นกรณีที่ซับซ้อนขึ้น สเปกระบุว่าหน่วยที่เกี่ยวข้องกับ letter-spacing เล็กกว่า grapheme cluster ของ Unicode—W3C CSS Text Module Level 3 (Editor's Draft) — หัวข้อ typographic character unit / letter-spacing (accessed Aug 11, 2026)
- TH Sarabun New ต่างจาก TH Sarabun PSK ที่ความคมชัดของการแสดงผลในขนาดเล็กบนจอความละเอียดต่ำเป็นหลัก ผู้ออกแบบ ศุภกิจ เฉลิมลาภ ระบุว่า 'โดยทางกายภาพของฟอนต์แล้ว ไม่ว่าจะเป็นหน้าตา ช่องไฟ ระยะบรรทัดฯ ทุกอย่างเหมือนกัน' จึงไม่ควรใช้ TH Sarabun PSK เป็นตัวอย่างของฟอนต์ที่วางสระผิด—Beartai — 'ทำไมถึงควรใช้ฟอนต์ TH Sarabun New แทน TH Sarabun PSK' (อ้างคำผู้ออกแบบ ศุภกิจ เฉลิมลาภ) (accessed Aug 11, 2026)
- FontForge เป็นซอฟต์แวร์เสรีโอเพนซอร์ส ไม่มีค่าใช้จ่าย ใช้ได้บน Windows, macOS และ GNU+Linux รุ่นเสถียรล่าสุดคือ 20251009 และรองรับการสร้าง anchor class แบบ mark-to-base และ mark-to-mark ผ่าน Element > Font Info > Lookups > GPOS—FontForge — เว็บไซต์ทางการและเอกสาร 'Advanced Typography Tables' (accessed Aug 11, 2026)
- Calligraphr รุ่นฟรีจำกัดที่ 75 ตัวอักษรต่อฟอนต์ รุ่น Pro จำกัดที่ 600 ตัวอักษร และแสดงราคาให้ผู้เข้าชมจากประเทศไทยเป็น ฿300 ต่อเดือน หรือ ฿200 ต่อเดือนเมื่ออัปเกรดแบบ 6 เดือน—Calligraphr — หน้าราคาอย่างเป็นทางการ (ระบุ '฿ 300 thb for one month' และ '฿ 200 thb per month for a 6 months upgrade') (accessed Aug 11, 2026)
- เอกสารของ Calligraphr ระบุผลลัพธ์ OpenType เพียง Contextual Alternates และ ligatures เท่านั้น ไม่มีการกล่าวถึง mark-to-base, mark-to-mark, anchor หรือการวางเครื่องหมายผสม ซึ่งเป็นตารางที่ภาษาไทยต้องใช้—Calligraphr — FAQ อย่างเป็นทางการ (ไม่ปรากฏเอกสารเรื่องการวางเครื่องหมายใด ๆ) (accessed Aug 11, 2026)
- ผู้ใช้ชาวไทยรายงานว่าฟอนต์ไทยที่ทำจาก Calligraphr แสดงสระหลุดจากพยัญชนะ ผู้ตั้งกระทู้เขียนว่า 'สระที่จะต้องอยู่บน-ล่างพยัญชนะมันกลับไม่อยู่ค่ะ' โดยระบุว่าฟอนต์แสดงผลปกติเมื่อใช้บน Facebook แต่ผิดพลาดในแอป GoodNotes—Pantip กระทู้ 39922367 — 'ทำฟ้อนต์ใช้เองด้วยเว็บ calligraphr' (accessed Aug 11, 2026)
- สายการผลิตฟอนต์ ThaiGraph Condensed (4 น้ำหนัก ต่อยอดจาก Anuphan ของ Cadson Demak ภายใต้ OFL 1.1) รันชุดตรวจ shaping ด้วย HarfBuzz กับไฟล์ที่ build เสร็จทุกน้ำหนัก โดยตรวจว่าไม่มี .notdef ในตัวอย่างข้อความไทยผสมลาติน, mark positioning ให้ค่า offset ไม่เป็นศูนย์, การซ้อนชั้นแบบ mkmk ตรงกับต้นฉบับ, ccmp สลับ ญ เป็นรูปไม่มีเชิงเมื่อเจอสระอุ และสระอำถูกแตกเป็นนิคหิตกับสระอา—ThaiGraph editorial — สคริปต์ QA ของสายการผลิตฟอนต์ภายใน (font-factory/scripts/qa.py) และไฟล์ config ของ ThaiGraph Condensed (accessed Aug 11, 2026)
- ค่า line-height ที่แนะนำสำหรับข้อความไทย (หัวเรื่อง 1.5 เนื้อความ 1.625) และการตั้ง letter-spacing เป็น 0 กับเนื้อความไทย เป็นค่าที่กองบรรณาธิการ ThaiGraph ใช้เอง ไม่ใช่ค่าที่ประกาศโดยสเปกหรือผู้ผลิตรายใด—ThaiGraph editorial — ค่ามาตรฐานการจัดข้อความไทยของกองบรรณาธิการ (accessed Aug 11, 2026)
- ลำดับการวินิจฉัยแบบข้ามโปรแกรม (ทดสอบข้อความชุดเดียวกันในเบราว์เซอร์ก่อนเพื่อแยกว่าปัญหาอยู่ที่ฟอนต์หรืออยู่ที่โปรแกรม) เป็นวิธีทำงานของกองบรรณาธิการ ThaiGraph ไม่ใช่ขั้นตอนที่ประกาศโดยผู้ผลิตซอฟต์แวร์รายใด—ThaiGraph editorial — ขั้นตอนวินิจฉัยของกองบรรณาธิการ (accessed Aug 11, 2026)