ระหว่างทำฟอนต์ Arundina รวมทั้งฟอนต์ Waree เองที่ผ่านไป เจอประเด็นหนึ่งให้ตัดสินใจ ระหว่างการใช้ cubic spline กับ quadratic spline เป็นรูปแบบสำหรับการ edit ฟอนต์ ว่าจะใช้รูปแบบไหนดี เนื่องจากต้นฉบับเขาใช้ quadratic แต่ผมคุ้นเคยกับ cubic
จากการทดลอง และคิดถึงหลักเหตุผลจากทฤษฎีเบื้องหลัง ก็ทำให้ตัดสินใจในที่สุดกับฟอนต์ดังกล่าว แต่ก่อนจะไปถึงคำตอบ ขอเท้าความสักนิด บันทึกความคิดเกี่ยวกับเรื่องนี้ก่อน
โมเดลของเส้นโค้งที่นิยมใช้กันมากที่สุดในแวดวงคอมพิวเตอร์กราฟิกส์ ก็คือ Bézier curve โดยแทนเส้นโค้งด้วยสมการ parametric เป็นพหุนาม ซึ่งสามารถเป็น linear, quadratic, cubic หรือดีกรีเท่าไรก็ได้ เส้นโค้งดีกรี n จะอาศัยจุดควบคุมทั้งหมด n + 1 จุด โดยเป็นจุดปลาย 2 จุด และจุดควบคุมเส้นโค้งอีก n - 1 จุด กล่าวคือ
ดีกรี 1 เป็นเส้นตรง สมการแทนเส้นตรงจากจุดปลาย P0 ไป P1 คือ
B(t) = (1 - t)P0 + tP1 ; 0 ≤ t ≤ 1
ดีกรี 2 (quadratic) สมการแทนเส้นโค้งจากจุดปลาย P0 ไป P2 โดยมีจุดควบคุมเส้นโค้ง P1 คือ
B(t) = (1 - t)2P0 + 2(1 - t)tP1 + t2P2 ; 0 ≤ t ≤ 1
ดีกรี 3 (cubic) สมการแทนเส้นโค้งจากจุดปลาย P0 ไป P3 โดยมีจุดควบคุมเส้นโค้ง P1 และ P2 คือ
B(t) = (1 - t)3P0 + 3(1 - t)2tP1 + 3(1 - t)t2P2 + t3P3 ; 0 ≤ t ≤ 1
ที่นิยมใช้มีแค่นี้ เนื่องจากดีกรีที่สูงกว่านี้จะจัดการยาก โดยที่นิยมใช้มากที่สุดคือ cubic Bézier curve เนื่องจากความอิสระของจุดควบคุมกำลังเหมาะกับการปรับแก้ด้วยมือ โปรแกรมกราฟิกส์ทั่วไปก็มักใช้ cubic Bézier นี้ จนกระทั่งเมื่อพูดถึง Bézier curve ลอย ๆ ก็จะหมายถึง cubic Bézier โดยปริยาย
Postscript ก็ใช้ cubic Bézier แทนเส้นโค้ง ฟอนต์ Postscript จึงแทนโค้งของตัวอักษรด้วย cubic Bézier ส่วนฟอนต์แบบ TrueType จะใช้ quadratic Bézier
แล้วข้อดีข้อเสียของเส้นโค้งทั้งสองแบบนี้เป็นยังไง?
การแปลงรูปแบบ
ถ้ายังไม่พูดถึงการแก้ไข การเก็บเส้นโค้งในรูป quadratic จะสามารถแปลงเป็น cubic ได้โดยไม่เสียความละเอียด เนื่องจากเส้นโค้งที่ดีกรีสูงกว่าสามารถลดรูปลงมาเป็นดีกรีที่ต่ำกว่าได้ ในขณะที่การแปลงจาก cubic เป็น quadratic จะไม่สามารถแทนเส้นโค้ง cubic ด้วย quadratic แบบแม่นยำได้ จะต้องมีการ interpolate จุดควบคุมระหว่างกลางเพิ่มเติม
เกี่ยวกับการลดรูปนี้ คุณสามารถพิสูจน์จากสมการ parametric ได้ว่า สำหรับเส้นโค้ง quadratic ที่มีจุดควบคุม P0, P1 และ P2 สามารถแทนได้ด้วยเส้นโค้ง cubic ที่สมมูลกันโดยมีจุดควบคุม P0, (P0/3 + 2P1/3), (2P1/3 + P2/3), และ P2
จำนวนจุดควบคุม
ความที่โค้ง quadratic มีจุดควบคุมโค้งเพียงจุดเดียว ความเป็นอิสระของโค้งจึงต่ำ การแทนโค้งใหญ่ ๆ จึงต้องอาศัยจำนวนโค้งย่อยมาต่อกันจำนวนมากกว่าโค้ง cubic ดังนั้น จุดต่อโค้งของโค้ง quadratic โดยทั่วไปจึงมากกว่าโค้ง cubic
![points in quadratric curve](https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_unqHbxZ4HsOnUajKBGGta1dzll4rBbaBW6hsUZ0OTDZ4-VlyAnv2v370xagP4ihAG7FPG9-x7-5Hc-mVpd2N6_VvWYmO-7bHyV_JdNR4axzs727fNsh7abvxl91Q=s0-d) |
![points in cubic curve](https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_vXr5cNnQ9LYg5O7VD5PpyV5A67-T6ltPl7KtRaLJgQdN2kvy3L5omr-VVqDO3J2gJCWuiSL6LrKJUV94lrKP0_xxuNZLBEntokkFTQSFTLpkV7Xknf1boL-JSdl6x6=s0-d) |
จำนวนจุดในโค้ง quadratic |
จำนวนจุดในโค้ง cubic |
การแก้ไข
เมื่อนำเส้นโค้งมาต่อกันเป็นโค้งใหญ่ แต่ละจุดเชื่อมต่อก็จะมีเวกเตอร์ควบคุมสองเส้น โดยชี้ไปยังจุดควบคุมของเส้นโค้งก่อนหน้าเส้นหนึ่ง กับชี้ไปยังเส้นโค้งส่วนถัดไปอีกเส้นหนึ่ง ซึ่งจุดเชื่อมต่อนี้ มีได้สามรูปแบบ คือ
- จุดหักมุม (corner point) เป็นจุดที่เส้นโค้งมีการหักมุม เวกเตอร์ควบคุมทั้งสองด้านจะเอียงทำมุมอย่างอิสระ ไม่ขึ้นต่อกัน
- จุดสัมผัสโค้ง (tangent point) เป็นจุดที่เปลี่ยนจากเส้นตรงเป็นเส้นโค้ง หรือเส้นโค้งเป็นเส้นตรง โดยมีความต่อเนื่องของเส้นต่อไป เวกเตอร์ควบคุมด้านที่ชี้ไปยังส่วนเส้นโค้งจะทำมุมเท่ากับมุมของส่วนเส้นตรง ส่วนเวกเตอร์ควบคุมที่ชี้ไปยังส่วนเส้นตรงนั้นไม่มี คือเป็นเวกเตอร์ศูนย์
- จุดต่อโค้ง (curve point) เป็นจุดเปลี่ยนจากโค้งหนึ่งเป็นอีกโค้งหนึ่ง โดยมีความต่อเนื่องของเส้น เวกเตอร์ควบคุมทั้งสองด้านจะทำมุมเท่ากัน แต่ชี้ในทิศตรงกันข้าม
จุดสองประเภทแรกนั้น ไม่ค่อยมีปัญหาเท่าไรกับการแก้ไข ไม่ว่าจะเป็น quadratic หรือ cubic แต่จุดต่อโค้งนั้น จะทำให้แก้ไขลำบากถ้าเป็น quadratic เนื่องจากเส้นโค้ง quadratic มีจุดควบคุมเพียงจุดเดียว ซึ่งจะมีผลกับเส้นโค้งทั้งสองปลาย แล้วเมื่อเวกเตอร์ควบคุมของส่วนของเส้นโค้งสองเส้นมาผูกติดกันด้วยมุมเอียง การปรับจุดควบคุมของโค้งหนึ่ง จึงกระทบถึงอีกโค้งหนึ่งทั้งโค้งอย่างเลี่ยงไม่ได้
![editing quadratic curve: before](https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_vs479IKNksB7wdXAWb55Dv3cjuClNhUwQ29V9je_dtghJcbgQRLyAWsf0O2YgZTmf_2p6su_8HZ4BJfqhy6p0Yuw5vNJyXlqy1WLYr9oBNPO7lmgmca-aw-chJs4CdXq8=s0-d) |
![editing quadratic curve: after](https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_v7yZVaIE7TfRPCq549XDDQqKszUJP0XryQBkdjGnzo-zpttNGCcROK_qcH_0jVu_Fz4AyM_zQkzyB2FZh96m3S7avhp6LEcsQvLS_uTjJ3WL2kH3qAZgkoekt_y9nnU8k=s0-d) |
การแก้ quadratic curve: ก่อน |
การแก้ quadratic curve: หลัง |
ในขณะที่โค้ง cubic จะเป็นอิสระกว่า เพราะมีจุดควบคุมสองจุด การปรับจุดควบคุมของโค้งหนึ่ง จึงมีผลต่อส่วนของเส้นโค้งที่แก้ไขอยู่เท่านั้น ไม่ใช่ไปกระทบต่อโค้งถัดไปด้วย
![editing cubic curve: before](https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_sS0qbC4lRd0-R2iuJOKpIHeQofAZHPOjnwxiDtDBc8niF6NePjzR_NqVAByXHwmQPBT-ZEhGOxL9zjabVRFaXO6ixR0u64sesAPeTS5xE2sSrBa1RFPN2XZvciDwZ_8Cw=s0-d) |
![editing cubic curve: after](https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_vKHnVZJWfhKJtpHyivdRSLkHlLH1U3Cyi1bYfxaG09vX-dNaZIBThgV2xuZjDaWavrtPwj5kBSSFg7uqUKnswFD6aPx09uNmNq4nAGYUWskLkawRt9kQX5D4mWcKAMdKE6=s0-d) |
การแก้ cubic curve: ก่อน |
การแก้ cubic curve: หลัง |
เมื่อประกอบเข้ากับเงื่อนไขที่ว่า โค้ง quadratic มีจำนวนจุดต่อมากกว่า ซึ่งหมายถึงจุดต่อโค้งอยู่ใกล้กันมาก ผลของความกระทบกระเทือนจึงมีอัตราสูงกว่าด้วย ทำให้การแก้ไขโค้ง quadratic ยิ่งยากขึ้นไปอีก
fontforge มีมาตรการคลายความอึดอัดตรงนี้บ้าง ด้วยการกำหนดให้จุดต่อโค้งบางจุดเป็น interpolated คือให้คำนวณตำแหน่งจากจุดข้างเคียง แทนที่จะให้แก้ไขโดยตรง การปรับจุดข้างเคียง ก็จะมีผลต่อตำแหน่งของจุดนี้ด้วย ทำให้ดูเสมือนไม่มีจุดต่อโค้งนี้อยู่ แต่สิ่งที่ได้คือ จุดควบคุมโค้งที่อยู่ถัดจากจุดนี้ไป จะเป็นอิสระจากการปรับโค้ง เสมือนหนึ่งกำลังปรับโค้งใหญ่ที่มีจุดควบคุมสองจุด นับเป็นวิธีที่ชาญฉลาดทีเดียว
![editing interpolated quadratic curve: before](https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_s5GVW8sXILWkHhjDnUouWpijyVxeVt0hVyRZlYDnVaRMVp_Rz9uzNymtrUHSQCSXbWfoOUhbrXMOkHE5AIGeqX4ZtIuFO8_fijDwFyx8js9RhMcaNTlDcSgJJyzb5gCO4ib7s=s0-d) |
![editing interpolated quadratic curve: after](https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_s_ZMfCvpG3AbxJpKTvSgevlzdXzytC1C3PBlV0snbPmMX6I_g1NpeJo2f4zbNsw2d92MBDTAvL_vuyHtFZVojJJcrAsRQcQhQ7HWnVQee_UOk45wXcPQEFoeNupjBpoMLollc=s0-d) |
การแก้ quadratic curve ที่มี interpolated point: ก่อน |
การแก้ quadratic curve ที่มี interpolated point: หลัง |
อย่างไรก็ดี จำนวนจุดต่อโค้งที่มากเกินไปของโค้ง quadratic ก็ยังทำให้การปรับเส้นโค้งเป็นไปอย่างทุลักทุเล โดยเฉพาะสำหรับ glyph ที่มีโค้งซับซ้อน เพราะต้องปรับโค้งย่อยทีละส่วน แทนที่จะปรับโค้งโดยรวมได้กว้างเหมือนโค้ง cubic
![editing interpolated quadratic curve: before](https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_t7Q0oYvLkM9Z-syUU-Vug_8ImOQRp0zOu4nbwdD20paJpZ76Nx7DOGfHL64IIfQV9giEeX9bJN8NS-EixG82Hhh9-hT-Pd6-CiH0gjj_glU9wDRC1TwERewadGO6NJbDY=s0-d) |
![editing interpolated quadratic curve: after](https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_uF7Tw-f41vOrff0OI1DRZGBY2tT1tejovhZgY8ReM1PNvBOtE3PeOssitkk0VrvJqvXbfWYjYhby0mnhCbzH1vHOLKbC9lmjNwM01h2AWhAp0GJmgF3FR4eh6anmv0JMxbHA=s0-d) |
ตัวอย่าง glyph ที่ซับซ้อนเมื่อเป็น quadratic |
ตัวอย่าง glyph ที่ซับซ้อนเมื่อเป็น cubic |
สรุป
- โดยปกติ การสร้างฟอนต์ในรูปโค้ง cubic แล้วให้โปรแกรมแปลงเป็น TrueType ที่เป็น quadratic จะทำให้ปรับแก้ฟอนต์ได้ง่ายกว่า แม้การแปลงเป็น quadratic จะต้องมีการ interpolate เพิ่ม แต่ก็ถือว่าโปรแกรมส่วนใหญ่ interpolate แบบอัตโนมัติได้ดี
- ถ้าต้องปรับแต่งฟอนต์ที่ต้นแบบเป็น TrueType ซึ่งใช้โค้ง quadratic ก็อาจจะขึ้นอยู่กับว่า ต้องปรับแก้ spline ของ glyph ต่าง ๆ หรือเปล่า ถ้าไม่ต้องปรับ การเก็บเป็น quadratic ก็ย่อมรักษาข้อมูลเดิมของฟอนต์ได้ครบถ้วน แต่ถ้าจำเป็นต้องปรับ การแปลงเป็น cubic โดย simplify spline เพื่อลดจำนวนจุดต่อโค้งด้วย จะทำให้ทำงานสะดวกกว่า ใช้เครื่องมือต่าง ๆ ได้ครบครันกว่า แม้จะเสียข้อมูลบางส่วนไป แต่การ interpolate ของโปรแกรมสร้างฟอนต์ก็ถือว่าไม่ทำให้เสียรูปเส้นโค้งเดิมไปเท่าไรนัก เทียบกับการปรับโค้งที่เป็นระเบียบกว่าแล้ว ถือว่าคุ้มค่า
ยาวหน่อยครับ blog นี้ ถือว่าเป็นการเรียบเรียงความคิดตัวเองไปในตัว
ป้ายกำกับ: typography