initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled

This commit is contained in:
2025-09-16 20:46:46 -04:00
commit 9d30169a8d
13378 changed files with 7050105 additions and 0 deletions

779
thirdparty/freetype/src/autofit/afblue.c vendored Normal file
View File

@@ -0,0 +1,779 @@
/* This file has been generated by the Perl script `afblue.pl', */
/* using data from file `afblue.dat'. */
/****************************************************************************
*
* afblue.c
*
* Auto-fitter data for blue strings (body).
*
* Copyright (C) 2013-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include "aftypes.h"
FT_LOCAL_ARRAY_DEF( char )
af_blue_strings[] =
{
/* */
'\xF0', '\x9E', '\xA4', '\x8C', ' ', '\xF0', '\x9E', '\xA4', '\x85', ' ', '\xF0', '\x9E', '\xA4', '\x88', ' ', '\xF0', '\x9E', '\xA4', '\x8F', ' ', '\xF0', '\x9E', '\xA4', '\x94', ' ', '\xF0', '\x9E', '\xA4', '\x9A', /* 𞤌 𞤅 𞤈 𞤏 𞤔 𞤚 */
'\0',
'\xF0', '\x9E', '\xA4', '\x82', ' ', '\xF0', '\x9E', '\xA4', '\x96', /* 𞤂 𞤖 */
'\0',
'\xF0', '\x9E', '\xA4', '\xAC', ' ', '\xF0', '\x9E', '\xA4', '\xAE', ' ', '\xF0', '\x9E', '\xA4', '\xBB', ' ', '\xF0', '\x9E', '\xA4', '\xBC', ' ', '\xF0', '\x9E', '\xA4', '\xBE', /* 𞤬 𞤮 𞤻 𞤼 𞤾 */
'\0',
'\xF0', '\x9E', '\xA4', '\xA4', ' ', '\xF0', '\x9E', '\xA4', '\xA8', ' ', '\xF0', '\x9E', '\xA4', '\xA9', ' ', '\xF0', '\x9E', '\xA4', '\xAD', ' ', '\xF0', '\x9E', '\xA4', '\xB4', ' ', '\xF0', '\x9E', '\xA4', '\xB8', ' ', '\xF0', '\x9E', '\xA4', '\xBA', ' ', '\xF0', '\x9E', '\xA5', '\x80', /* 𞤤 𞤨 𞤩 𞤭 𞤴 𞤸 𞤺 𞥀 */
'\0',
'\xD8', '\xA7', ' ', '\xD8', '\xA5', ' ', '\xD9', '\x84', ' ', '\xD9', '\x83', ' ', '\xD8', '\xB7', ' ', '\xD8', '\xB8', /* ا إ ل ك ط ظ */
'\0',
'\xD8', '\xAA', ' ', '\xD8', '\xAB', ' ', '\xD8', '\xB7', ' ', '\xD8', '\xB8', ' ', '\xD9', '\x83', /* ت ث ط ظ ك */
'\0',
'\xD9', '\x80', /* ـ */
'\0',
'\xD4', '\xB1', ' ', '\xD5', '\x84', ' ', '\xD5', '\x92', ' ', '\xD5', '\x8D', ' ', '\xD4', '\xB2', ' ', '\xD4', '\xB3', ' ', '\xD4', '\xB4', ' ', '\xD5', '\x95', /* Ա Մ Ւ Ս Բ Գ Դ Օ */
'\0',
'\xD5', '\x92', ' ', '\xD5', '\x88', ' ', '\xD4', '\xB4', ' ', '\xD5', '\x83', ' ', '\xD5', '\x87', ' ', '\xD5', '\x8D', ' ', '\xD5', '\x8F', ' ', '\xD5', '\x95', /* Ւ Ո Դ Ճ Շ Ս Տ Օ */
'\0',
'\xD5', '\xA5', ' ', '\xD5', '\xA7', ' ', '\xD5', '\xAB', ' ', '\xD5', '\xB4', ' ', '\xD5', '\xBE', ' ', '\xD6', '\x86', ' ', '\xD5', '\xB3', /* ե է ի մ վ ֆ ճ */
'\0',
'\xD5', '\xA1', ' ', '\xD5', '\xB5', ' ', '\xD6', '\x82', ' ', '\xD5', '\xBD', ' ', '\xD5', '\xA3', ' ', '\xD5', '\xB7', ' ', '\xD6', '\x80', ' ', '\xD6', '\x85', /* ա յ ւ ս գ շ ր օ */
'\0',
'\xD5', '\xB0', ' ', '\xD5', '\xB8', ' ', '\xD5', '\xB3', ' ', '\xD5', '\xA1', ' ', '\xD5', '\xA5', ' ', '\xD5', '\xAE', ' ', '\xD5', '\xBD', ' ', '\xD6', '\x85', /* հ ո ճ ա ե ծ ս օ */
'\0',
'\xD5', '\xA2', ' ', '\xD5', '\xA8', ' ', '\xD5', '\xAB', ' ', '\xD5', '\xAC', ' ', '\xD5', '\xB2', ' ', '\xD5', '\xBA', ' ', '\xD6', '\x83', ' ', '\xD6', '\x81', /* բ ը ի լ ղ պ փ ց */
'\0',
'\xF0', '\x90', '\xAC', '\x80', ' ', '\xF0', '\x90', '\xAC', '\x81', ' ', '\xF0', '\x90', '\xAC', '\x90', ' ', '\xF0', '\x90', '\xAC', '\x9B', /* 𐬀 𐬁 𐬐 𐬛 */
'\0',
'\xF0', '\x90', '\xAC', '\x80', ' ', '\xF0', '\x90', '\xAC', '\x81', /* 𐬀 𐬁 */
'\0',
'\xEA', '\x9A', '\xA7', ' ', '\xEA', '\x9A', '\xA8', ' ', '\xEA', '\x9B', '\x9B', ' ', '\xEA', '\x9B', '\x89', ' ', '\xEA', '\x9B', '\x81', ' ', '\xEA', '\x9B', '\x88', ' ', '\xEA', '\x9B', '\xAB', ' ', '\xEA', '\x9B', '\xAF', /* ꚧ ꚨ ꛛ ꛉ ꛁ ꛈ */
'\0',
'\xEA', '\x9A', '\xAD', ' ', '\xEA', '\x9A', '\xB3', ' ', '\xEA', '\x9A', '\xB6', ' ', '\xEA', '\x9B', '\xAC', ' ', '\xEA', '\x9A', '\xA2', ' ', '\xEA', '\x9A', '\xBD', ' ', '\xEA', '\x9B', '\xAF', ' ', '\xEA', '\x9B', '\xB2', /* ꚭ ꚳ ꚶ ꛬ ꚢ ꚽ ꛲ */
'\0',
'\xE0', '\xA6', '\x85', ' ', '\xE0', '\xA6', '\xA1', ' ', '\xE0', '\xA6', '\xA4', ' ', '\xE0', '\xA6', '\xA8', ' ', '\xE0', '\xA6', '\xAC', ' ', '\xE0', '\xA6', '\xAD', ' ', '\xE0', '\xA6', '\xB2', ' ', '\xE0', '\xA6', '\x95', /* অ ড ত ন ব ভ ল ক */
'\0',
'\xE0', '\xA6', '\x87', ' ', '\xE0', '\xA6', '\x9F', ' ', '\xE0', '\xA6', '\xA0', ' ', '\xE0', '\xA6', '\xBF', ' ', '\xE0', '\xA7', '\x80', ' ', '\xE0', '\xA7', '\x88', ' ', '\xE0', '\xA7', '\x97', /* ই ট ঠ ি ী ৈ ৗ */
'\0',
'\xE0', '\xA6', '\x93', ' ', '\xE0', '\xA6', '\x8F', ' ', '\xE0', '\xA6', '\xA1', ' ', '\xE0', '\xA6', '\xA4', ' ', '\xE0', '\xA6', '\xA8', ' ', '\xE0', '\xA6', '\xAC', ' ', '\xE0', '\xA6', '\xB2', ' ', '\xE0', '\xA6', '\x95', /* ও এ ড ত ন ব ল ক */
'\0',
'\xE1', '\x9D', '\x90', ' ', '\xE1', '\x9D', '\x88', /* ᝐ ᝈ */
'\0',
'\xE1', '\x9D', '\x85', ' ', '\xE1', '\x9D', '\x8A', ' ', '\xE1', '\x9D', '\x8E', /* ᝅ ᝊ ᝎ */
'\0',
'\xE1', '\x9D', '\x82', ' ', '\xE1', '\x9D', '\x83', ' ', '\xE1', '\x9D', '\x89', ' ', '\xE1', '\x9D', '\x8C', /* ᝂ ᝃ ᝉ ᝌ */
'\0',
'\xE1', '\x9D', '\x80', ' ', '\xE1', '\x9D', '\x83', ' ', '\xE1', '\x9D', '\x86', ' ', '\xE1', '\x9D', '\x89', ' ', '\xE1', '\x9D', '\x8B', ' ', '\xE1', '\x9D', '\x8F', ' ', '\xE1', '\x9D', '\x91', /* ᝀ ᝃ ᝆ ᝉ ᝋ ᝏ ᝑ */
'\0',
'\xE1', '\x97', '\x9C', ' ', '\xE1', '\x96', '\xB4', ' ', '\xE1', '\x90', '\x81', ' ', '\xE1', '\x92', '\xA3', ' ', '\xE1', '\x91', '\xAB', ' ', '\xE1', '\x91', '\x8E', ' ', '\xE1', '\x94', '\x91', ' ', '\xE1', '\x97', '\xB0', /* ᗜ ᐁ ᒣ ᑫ ᑎ ᔑ */
'\0',
'\xE1', '\x97', '\xB6', ' ', '\xE1', '\x96', '\xB5', ' ', '\xE1', '\x92', '\xA7', ' ', '\xE1', '\x90', '\x83', ' ', '\xE1', '\x91', '\x8C', ' ', '\xE1', '\x92', '\x8D', ' ', '\xE1', '\x94', '\x91', ' ', '\xE1', '\x97', '\xA2', /* ᗶ ᖵ ᒧ ᐃ ᔑ ᗢ */
'\0',
'\xE1', '\x93', '\x93', ' ', '\xE1', '\x93', '\x95', ' ', '\xE1', '\x93', '\x80', ' ', '\xE1', '\x93', '\x82', ' ', '\xE1', '\x93', '\x84', ' ', '\xE1', '\x95', '\x84', ' ', '\xE1', '\x95', '\x86', ' ', '\xE1', '\x98', '\xA3', /* ᓓ ᓕ ᓀ ᓂ ᓄ ᕄ ᕆ ᘣ */
'\0',
'\xE1', '\x95', '\x83', ' ', '\xE1', '\x93', '\x82', ' ', '\xE1', '\x93', '\x80', ' ', '\xE1', '\x95', '\x82', ' ', '\xE1', '\x93', '\x97', ' ', '\xE1', '\x93', '\x9A', ' ', '\xE1', '\x95', '\x86', ' ', '\xE1', '\x98', '\xA3', /* ᕃ ᓂ ᓀ ᕂ ᓗ ᓚ ᕆ ᘣ */
'\0',
'\xE1', '\x90', '\xAA', ' ', '\xE1', '\x99', '\x86', ' ', '\xE1', '\xA3', '\x98', ' ', '\xE1', '\x90', '\xA2', ' ', '\xE1', '\x92', '\xBE', ' ', '\xE1', '\xA3', '\x97', ' ', '\xE1', '\x94', '\x86', /* ᐪ ᙆ ᣘ ᐢ ᒾ ᣗ ᔆ */
'\0',
'\xE1', '\x99', '\x86', ' ', '\xE1', '\x97', '\xAE', ' ', '\xE1', '\x92', '\xBB', ' ', '\xE1', '\x90', '\x9E', ' ', '\xE1', '\x94', '\x86', ' ', '\xE1', '\x92', '\xA1', ' ', '\xE1', '\x92', '\xA2', ' ', '\xE1', '\x93', '\x91', /* ᙆ ᗮ ᒻ ᐞ ᔆ ᒡ ᒢ ᓑ */
'\0',
'\xF0', '\x90', '\x8A', '\xA7', ' ', '\xF0', '\x90', '\x8A', '\xAB', ' ', '\xF0', '\x90', '\x8A', '\xAC', ' ', '\xF0', '\x90', '\x8A', '\xAD', ' ', '\xF0', '\x90', '\x8A', '\xB1', ' ', '\xF0', '\x90', '\x8A', '\xBA', ' ', '\xF0', '\x90', '\x8A', '\xBC', ' ', '\xF0', '\x90', '\x8A', '\xBF', /* 𐊧 𐊫 𐊬 𐊭 𐊱 𐊺 𐊼 𐊿 */
'\0',
'\xF0', '\x90', '\x8A', '\xA3', ' ', '\xF0', '\x90', '\x8A', '\xA7', ' ', '\xF0', '\x90', '\x8A', '\xB7', ' ', '\xF0', '\x90', '\x8B', '\x80', ' ', '\xF0', '\x90', '\x8A', '\xAB', ' ', '\xF0', '\x90', '\x8A', '\xB8', ' ', '\xF0', '\x90', '\x8B', '\x89', /* 𐊣 𐊧 𐊷 𐋀 𐊫 𐊸 𐋉 */
'\0',
'\xF0', '\x91', '\x84', '\x83', ' ', '\xF0', '\x91', '\x84', '\x85', ' ', '\xF0', '\x91', '\x84', '\x89', ' ', '\xF0', '\x91', '\x84', '\x99', ' ', '\xF0', '\x91', '\x84', '\x97', /* 𑄃 𑄅 𑄉 𑄙 𑄗 */
'\0',
'\xF0', '\x91', '\x84', '\x85', ' ', '\xF0', '\x91', '\x84', '\x9B', ' ', '\xF0', '\x91', '\x84', '\x9D', ' ', '\xF0', '\x91', '\x84', '\x97', ' ', '\xF0', '\x91', '\x84', '\x93', /* 𑄅 𑄛 𑄝 𑄗 𑄓 */
'\0',
'\xF0', '\x91', '\x84', '\x96', '\xF0', '\x91', '\x84', '\xB3', '\xF0', '\x91', '\x84', '\xA2', ' ', '\xF0', '\x91', '\x84', '\x98', '\xF0', '\x91', '\x84', '\xB3', '\xF0', '\x91', '\x84', '\xA2', ' ', '\xF0', '\x91', '\x84', '\x99', '\xF0', '\x91', '\x84', '\xB3', '\xF0', '\x91', '\x84', '\xA2', ' ', '\xF0', '\x91', '\x84', '\xA4', '\xF0', '\x91', '\x84', '\xB3', '\xF0', '\x91', '\x84', '\xA2', ' ', '\xF0', '\x91', '\x84', '\xA5', '\xF0', '\x91', '\x84', '\xB3', '\xF0', '\x91', '\x84', '\xA2', /* 𑄖𑄳𑄢 𑄘𑄳𑄢 𑄙𑄳𑄢 𑄤𑄳𑄢 𑄥𑄳𑄢 */
'\0',
'\xE1', '\x8F', '\x86', ' ', '\xE1', '\x8E', '\xBB', ' ', '\xE1', '\x8E', '\xAC', ' ', '\xE1', '\x8F', '\x83', ' ', '\xE1', '\x8E', '\xA4', ' ', '\xE1', '\x8F', '\xA3', ' ', '\xE1', '\x8E', '\xA6', ' ', '\xE1', '\x8F', '\x95', /* Ꮖ Ꭴ Ꮳ Ꭶ */
'\0',
'\xEA', '\xAE', '\x92', ' ', '\xEA', '\xAE', '\xA4', ' ', '\xEA', '\xAE', '\xB6', ' ', '\xEA', '\xAD', '\xB4', ' ', '\xEA', '\xAD', '\xBE', ' ', '\xEA', '\xAE', '\x97', ' ', '\xEA', '\xAE', '\x9D', ' ', '\xEA', '\xAE', '\xBF', /* ꮒ ꮤ ꮶ ꭴ ꭾ ꮗ ꮝ ꮿ */
'\0',
'\xEA', '\xAE', '\x96', ' ', '\xEA', '\xAD', '\xBC', ' ', '\xEA', '\xAE', '\x93', ' ', '\xEA', '\xAE', '\xA0', ' ', '\xEA', '\xAE', '\xB3', ' ', '\xEA', '\xAD', '\xB6', ' ', '\xEA', '\xAE', '\xA5', ' ', '\xEA', '\xAE', '\xBB', /* ꮖ ꭼ ꮠ ꮳ ꭶ ꮥ ꮻ */
'\0',
'\xE1', '\x8F', '\xB8', ' ', '\xEA', '\xAE', '\x90', ' ', '\xEA', '\xAD', '\xB9', ' ', '\xEA', '\xAD', '\xBB', /* ᏸ ꮐ ꭹ ꭻ */
'\0',
'\xE2', '\xB2', '\x8C', ' ', '\xE2', '\xB2', '\x8E', ' ', '\xE2', '\xB2', '\xA0', ' ', '\xE2', '\xB3', '\x9E', ' ', '\xE2', '\xB2', '\x9E', ' ', '\xE2', '\xB2', '\x90', ' ', '\xE2', '\xB2', '\xA4', ' ', '\xE2', '\xB3', '\x8A', /* Ⲍ Ⲡ Ⳟ */
'\0',
'\xE2', '\xB3', '\x90', ' ', '\xE2', '\xB3', '\x98', ' ', '\xE2', '\xB3', '\x9E', ' ', '\xE2', '\xB2', '\x8E', ' ', '\xE2', '\xB2', '\x9E', ' ', '\xE2', '\xB2', '\x90', ' ', '\xE2', '\xB3', '\x9C', ' ', '\xE2', '\xB2', '\xB0', /* Ⳙ Ⳟ Ⲑ Ⳝ Ⲱ */
'\0',
'\xE2', '\xB2', '\x8D', ' ', '\xE2', '\xB2', '\x8F', ' ', '\xE2', '\xB2', '\xA1', ' ', '\xE2', '\xB3', '\x9F', ' ', '\xE2', '\xB2', '\x9F', ' ', '\xE2', '\xB2', '\x91', ' ', '\xE2', '\xB2', '\xA5', ' ', '\xE2', '\xB3', '\x8B', /* ⲍ ⲏ ⲡ ⳟ ⳋ */
'\0',
'\xE2', '\xB3', '\x91', ' ', '\xE2', '\xB3', '\x99', ' ', '\xE2', '\xB3', '\x9F', ' ', '\xE2', '\xB2', '\x8F', ' ', '\xE2', '\xB2', '\x9F', ' ', '\xE2', '\xB2', '\x91', ' ', '\xE2', '\xB3', '\x9D', ' ', '\xE2', '\xB3', '\x92', /* ⳑ ⳙ ⳟ ⲏ ⲑ ⳝ */
'\0',
'\xF0', '\x90', '\xA0', '\x8D', ' ', '\xF0', '\x90', '\xA0', '\x99', ' ', '\xF0', '\x90', '\xA0', '\xB3', ' ', '\xF0', '\x90', '\xA0', '\xB1', ' ', '\xF0', '\x90', '\xA0', '\x85', ' ', '\xF0', '\x90', '\xA0', '\x93', ' ', '\xF0', '\x90', '\xA0', '\xA3', ' ', '\xF0', '\x90', '\xA0', '\xA6', /* 𐠍 𐠙 𐠳 𐠱 𐠅 𐠓 𐠣 𐠦 */
'\0',
'\xF0', '\x90', '\xA0', '\x83', ' ', '\xF0', '\x90', '\xA0', '\x8A', ' ', '\xF0', '\x90', '\xA0', '\x9B', ' ', '\xF0', '\x90', '\xA0', '\xA3', ' ', '\xF0', '\x90', '\xA0', '\xB3', ' ', '\xF0', '\x90', '\xA0', '\xB5', ' ', '\xF0', '\x90', '\xA0', '\x90', /* 𐠃 𐠊 𐠛 𐠣 𐠳 𐠵 𐠐 */
'\0',
'\xF0', '\x90', '\xA0', '\x88', ' ', '\xF0', '\x90', '\xA0', '\x8F', ' ', '\xF0', '\x90', '\xA0', '\x96', /* 𐠈 𐠏 𐠖 */
'\0',
'\xD0', '\x91', ' ', '\xD0', '\x92', ' ', '\xD0', '\x95', ' ', '\xD0', '\x9F', ' ', '\xD0', '\x97', ' ', '\xD0', '\x9E', ' ', '\xD0', '\xA1', ' ', '\xD0', '\xAD', /* Б В Е П З О С Э */
'\0',
'\xD0', '\x91', ' ', '\xD0', '\x92', ' ', '\xD0', '\x95', ' ', '\xD0', '\xA8', ' ', '\xD0', '\x97', ' ', '\xD0', '\x9E', ' ', '\xD0', '\xA1', ' ', '\xD0', '\xAD', /* Б В Е Ш З О С Э */
'\0',
'\xD1', '\x85', ' ', '\xD0', '\xBF', ' ', '\xD0', '\xBD', ' ', '\xD1', '\x88', ' ', '\xD0', '\xB5', ' ', '\xD0', '\xB7', ' ', '\xD0', '\xBE', ' ', '\xD1', '\x81', /* х п н ш е з о с */
'\0',
'\xD1', '\x80', ' ', '\xD1', '\x83', ' ', '\xD1', '\x84', /* р у ф */
'\0',
'\xF0', '\x90', '\x90', '\x82', ' ', '\xF0', '\x90', '\x90', '\x84', ' ', '\xF0', '\x90', '\x90', '\x8B', ' ', '\xF0', '\x90', '\x90', '\x97', ' ', '\xF0', '\x90', '\x90', '\x91', /* 𐐂 𐐄 𐐋 𐐗 𐐑 */
'\0',
'\xF0', '\x90', '\x90', '\x80', ' ', '\xF0', '\x90', '\x90', '\x82', ' ', '\xF0', '\x90', '\x90', '\x84', ' ', '\xF0', '\x90', '\x90', '\x97', ' ', '\xF0', '\x90', '\x90', '\x9B', /* 𐐀 𐐂 𐐄 𐐗 𐐛 */
'\0',
'\xF0', '\x90', '\x90', '\xAA', ' ', '\xF0', '\x90', '\x90', '\xAC', ' ', '\xF0', '\x90', '\x90', '\xB3', ' ', '\xF0', '\x90', '\x90', '\xBF', ' ', '\xF0', '\x90', '\x90', '\xB9', /* 𐐪 𐐬 𐐳 𐐿 𐐹 */
'\0',
'\xF0', '\x90', '\x90', '\xA8', ' ', '\xF0', '\x90', '\x90', '\xAA', ' ', '\xF0', '\x90', '\x90', '\xAC', ' ', '\xF0', '\x90', '\x90', '\xBF', ' ', '\xF0', '\x90', '\x91', '\x83', /* 𐐨 𐐪 𐐬 𐐿 𐑃 */
'\0',
'\xE0', '\xA4', '\x95', ' ', '\xE0', '\xA4', '\xA8', ' ', '\xE0', '\xA4', '\xAE', ' ', '\xE0', '\xA4', '\x89', ' ', '\xE0', '\xA4', '\x9B', ' ', '\xE0', '\xA4', '\x9F', ' ', '\xE0', '\xA4', '\xA0', ' ', '\xE0', '\xA4', '\xA1', /* क न म उ छ ट ठ ड */
'\0',
'\xE0', '\xA4', '\x88', ' ', '\xE0', '\xA4', '\x90', ' ', '\xE0', '\xA4', '\x93', ' ', '\xE0', '\xA4', '\x94', ' ', '\xE0', '\xA4', '\xBF', ' ', '\xE0', '\xA5', '\x80', ' ', '\xE0', '\xA5', '\x8B', ' ', '\xE0', '\xA5', '\x8C', /* ई ऐ ओ औ ि ी ो ौ */
'\0',
'\xE0', '\xA4', '\x95', ' ', '\xE0', '\xA4', '\xAE', ' ', '\xE0', '\xA4', '\x85', ' ', '\xE0', '\xA4', '\x86', ' ', '\xE0', '\xA4', '\xA5', ' ', '\xE0', '\xA4', '\xA7', ' ', '\xE0', '\xA4', '\xAD', ' ', '\xE0', '\xA4', '\xB6', /* क म अ आ थ ध भ श */
'\0',
'\xE0', '\xA5', '\x81', ' ', '\xE0', '\xA5', '\x83', /* ु ृ */
'\0',
'\xE1', '\x88', '\x80', ' ', '\xE1', '\x88', '\x83', ' ', '\xE1', '\x8B', '\x98', ' ', '\xE1', '\x8D', '\x90', ' ', '\xE1', '\x88', '\x9B', ' ', '\xE1', '\x89', '\xA0', ' ', '\xE1', '\x8B', '\x8B', ' ', '\xE1', '\x8B', '\x90', /* ሃ ዘ ፐ ማ በ ዋ */
'\0',
'\xE1', '\x88', '\x88', ' ', '\xE1', '\x88', '\x90', ' ', '\xE1', '\x89', '\xA0', ' ', '\xE1', '\x8B', '\x98', ' ', '\xE1', '\x88', '\x80', ' ', '\xE1', '\x88', '\xAA', ' ', '\xE1', '\x8B', '\x90', ' ', '\xE1', '\x8C', '\xA8', /* ለ ሐ በ ዘ ጨ */
'\0',
'\xE1', '\x83', '\x92', ' ', '\xE1', '\x83', '\x93', ' ', '\xE1', '\x83', '\x94', ' ', '\xE1', '\x83', '\x95', ' ', '\xE1', '\x83', '\x97', ' ', '\xE1', '\x83', '\x98', ' ', '\xE1', '\x83', '\x9D', ' ', '\xE1', '\x83', '\xA6', /* გ დ ე ვ თ ი ო ღ */
'\0',
'\xE1', '\x83', '\x90', ' ', '\xE1', '\x83', '\x96', ' ', '\xE1', '\x83', '\x9B', ' ', '\xE1', '\x83', '\xA1', ' ', '\xE1', '\x83', '\xA8', ' ', '\xE1', '\x83', '\xAB', ' ', '\xE1', '\x83', '\xAE', ' ', '\xE1', '\x83', '\x9E', /* ა ზ მ ს შ ძ ხ პ */
'\0',
'\xE1', '\x83', '\xA1', ' ', '\xE1', '\x83', '\xAE', ' ', '\xE1', '\x83', '\xA5', ' ', '\xE1', '\x83', '\x96', ' ', '\xE1', '\x83', '\x9B', ' ', '\xE1', '\x83', '\xA8', ' ', '\xE1', '\x83', '\xA9', ' ', '\xE1', '\x83', '\xAC', /* ს ხ ქ ზ მ შ ჩ წ */
'\0',
'\xE1', '\x83', '\x94', ' ', '\xE1', '\x83', '\x95', ' ', '\xE1', '\x83', '\x9F', ' ', '\xE1', '\x83', '\xA2', ' ', '\xE1', '\x83', '\xA3', ' ', '\xE1', '\x83', '\xA4', ' ', '\xE1', '\x83', '\xA5', ' ', '\xE1', '\x83', '\xA7', /* ე ვ ჟ ტ უ ფ ქ */
'\0',
'\xE1', '\x82', '\xB1', ' ', '\xE1', '\x82', '\xA7', ' ', '\xE1', '\x82', '\xB9', ' ', '\xE1', '\x82', '\xBC', ' ', '\xE1', '\x82', '\xA4', ' ', '\xE1', '\x82', '\xA5', ' ', '\xE1', '\x82', '\xB3', ' ', '\xE1', '\x82', '\xBA', /* Ⴑ Ⴇ Ⴙ Ⴜ Ⴄ Ⴅ Ⴓ Ⴚ */
'\0',
'\xE1', '\x82', '\xA4', ' ', '\xE1', '\x82', '\xA5', ' ', '\xE1', '\x82', '\xA7', ' ', '\xE1', '\x82', '\xA8', ' ', '\xE1', '\x82', '\xA6', ' ', '\xE1', '\x82', '\xB1', ' ', '\xE1', '\x82', '\xAA', ' ', '\xE1', '\x82', '\xAB', /* Ⴄ Ⴅ Ⴇ Ⴈ Ⴆ Ⴑ Ⴊ Ⴋ */
'\0',
'\xE2', '\xB4', '\x81', ' ', '\xE2', '\xB4', '\x97', ' ', '\xE2', '\xB4', '\x82', ' ', '\xE2', '\xB4', '\x84', ' ', '\xE2', '\xB4', '\x85', ' ', '\xE2', '\xB4', '\x87', ' ', '\xE2', '\xB4', '\x94', ' ', '\xE2', '\xB4', '\x96', /* ⴁ ⴗ ⴂ ⴄ ⴅ ⴇ ⴔ ⴖ */
'\0',
'\xE2', '\xB4', '\x88', ' ', '\xE2', '\xB4', '\x8C', ' ', '\xE2', '\xB4', '\x96', ' ', '\xE2', '\xB4', '\x8E', ' ', '\xE2', '\xB4', '\x83', ' ', '\xE2', '\xB4', '\x86', ' ', '\xE2', '\xB4', '\x8B', ' ', '\xE2', '\xB4', '\xA2', /* ⴈ ⴌ ⴖ ⴎ ⴃ ⴆ ⴋ ⴢ */
'\0',
'\xE2', '\xB4', '\x90', ' ', '\xE2', '\xB4', '\x91', ' ', '\xE2', '\xB4', '\x93', ' ', '\xE2', '\xB4', '\x95', ' ', '\xE2', '\xB4', '\x99', ' ', '\xE2', '\xB4', '\x9B', ' ', '\xE2', '\xB4', '\xA1', ' ', '\xE2', '\xB4', '\xA3', /* ⴐ ⴑ ⴓ ⴕ ⴙ ⴛ ⴡ ⴣ */
'\0',
'\xE2', '\xB4', '\x84', ' ', '\xE2', '\xB4', '\x85', ' ', '\xE2', '\xB4', '\x94', ' ', '\xE2', '\xB4', '\x95', ' ', '\xE2', '\xB4', '\x81', ' ', '\xE2', '\xB4', '\x82', ' ', '\xE2', '\xB4', '\x98', ' ', '\xE2', '\xB4', '\x9D', /* ⴄ ⴅ ⴔ ⴕ ⴁ ⴂ ⴘ ⴝ */
'\0',
'\xE1', '\xB2', '\x9C', ' ', '\xE1', '\xB2', '\x9F', ' ', '\xE1', '\xB2', '\xB3', ' ', '\xE1', '\xB2', '\xB8', ' ', '\xE1', '\xB2', '\x92', ' ', '\xE1', '\xB2', '\x94', ' ', '\xE1', '\xB2', '\x9D', ' ', '\xE1', '\xB2', '\xB4', /* Ნ Ჟ Ჳ Ჸ Გ Ე Ო Ჴ */
'\0',
'\xE1', '\xB2', '\x98', ' ', '\xE1', '\xB2', '\xB2', ' ', '\xE1', '\xB2', '\x9D', ' ', '\xE1', '\xB2', '\xA9', ' ', '\xE1', '\xB2', '\x9B', ' ', '\xE1', '\xB2', '\xA8', ' ', '\xE1', '\xB2', '\xAF', ' ', '\xE1', '\xB2', '\xBD', /* Ი Ჲ Ო Ჩ Მ Შ Ჯ Ჽ */
'\0',
'\xE2', '\xB0', '\x85', ' ', '\xE2', '\xB0', '\x94', ' ', '\xE2', '\xB0', '\xAA', ' ', '\xE2', '\xB0', '\x84', ' ', '\xE2', '\xB0', '\x82', ' ', '\xE2', '\xB0', '\x8A', ' ', '\xE2', '\xB0', '\xAB', ' ', '\xE2', '\xB0', '\x8B', /* Ⰵ Ⱄ Ⱚ Ⰴ Ⰲ Ⰺ Ⱛ Ⰻ */
'\0',
'\xE2', '\xB0', '\x85', ' ', '\xE2', '\xB0', '\x84', ' ', '\xE2', '\xB0', '\x82', ' ', '\xE2', '\xB0', '\xAA', ' ', '\xE2', '\xB0', '\x9E', ' ', '\xE2', '\xB0', '\xA1', ' ', '\xE2', '\xB0', '\x8A', ' ', '\xE2', '\xB0', '\x94', /* Ⰵ Ⰴ Ⰲ Ⱚ Ⱎ Ⱑ Ⰺ Ⱄ */
'\0',
'\xE2', '\xB0', '\xB5', ' ', '\xE2', '\xB1', '\x84', ' ', '\xE2', '\xB1', '\x9A', ' ', '\xE2', '\xB0', '\xB4', ' ', '\xE2', '\xB0', '\xB2', ' ', '\xE2', '\xB0', '\xBA', ' ', '\xE2', '\xB1', '\x9B', ' ', '\xE2', '\xB0', '\xBB', /* ⰵ ⱄ ⱚ ⰴ ⰲ ⰺ ⱛ ⰻ */
'\0',
'\xE2', '\xB0', '\xB5', ' ', '\xE2', '\xB0', '\xB4', ' ', '\xE2', '\xB0', '\xB2', ' ', '\xE2', '\xB1', '\x9A', ' ', '\xE2', '\xB1', '\x8E', ' ', '\xE2', '\xB1', '\x91', ' ', '\xE2', '\xB0', '\xBA', ' ', '\xE2', '\xB1', '\x84', /* ⰵ ⰴ ⰲ ⱚ ⱎ ⱑ ⰺ ⱄ */
'\0',
'\xF0', '\x90', '\x8C', '\xB2', ' ', '\xF0', '\x90', '\x8C', '\xB6', ' ', '\xF0', '\x90', '\x8D', '\x80', ' ', '\xF0', '\x90', '\x8D', '\x84', ' ', '\xF0', '\x90', '\x8C', '\xB4', ' ', '\xF0', '\x90', '\x8D', '\x83', ' ', '\xF0', '\x90', '\x8D', '\x88', ' ', '\xF0', '\x90', '\x8C', '\xBE', /* 𐌲 𐌶 𐍀 𐍄 𐌴 𐍃 𐍈 𐌾 */
'\0',
'\xF0', '\x90', '\x8C', '\xB6', ' ', '\xF0', '\x90', '\x8C', '\xB4', ' ', '\xF0', '\x90', '\x8D', '\x83', ' ', '\xF0', '\x90', '\x8D', '\x88', /* 𐌶 𐌴 𐍃 𐍈 */
'\0',
'\xCE', '\x93', ' ', '\xCE', '\x92', ' ', '\xCE', '\x95', ' ', '\xCE', '\x96', ' ', '\xCE', '\x98', ' ', '\xCE', '\x9F', ' ', '\xCE', '\xA9', /* Γ Β Ε Ζ Θ Ο Ω */
'\0',
'\xCE', '\x92', ' ', '\xCE', '\x94', ' ', '\xCE', '\x96', ' ', '\xCE', '\x9E', ' ', '\xCE', '\x98', ' ', '\xCE', '\x9F', /* Β Δ Ζ Ξ Θ Ο */
'\0',
'\xCE', '\xB2', ' ', '\xCE', '\xB8', ' ', '\xCE', '\xB4', ' ', '\xCE', '\xB6', ' ', '\xCE', '\xBB', ' ', '\xCE', '\xBE', /* β θ δ ζ λ ξ */
'\0',
'\xCE', '\xB1', ' ', '\xCE', '\xB5', ' ', '\xCE', '\xB9', ' ', '\xCE', '\xBF', ' ', '\xCF', '\x80', ' ', '\xCF', '\x83', ' ', '\xCF', '\x84', ' ', '\xCF', '\x89', /* α ε ι ο π σ τ ω */
'\0',
'\xCE', '\xB2', ' ', '\xCE', '\xB3', ' ', '\xCE', '\xB7', ' ', '\xCE', '\xBC', ' ', '\xCF', '\x81', ' ', '\xCF', '\x86', ' ', '\xCF', '\x87', ' ', '\xCF', '\x88', /* β γ η μ ρ φ χ ψ */
'\0',
'\xE0', '\xAA', '\xA4', ' ', '\xE0', '\xAA', '\xA8', ' ', '\xE0', '\xAA', '\x8B', ' ', '\xE0', '\xAA', '\x8C', ' ', '\xE0', '\xAA', '\x9B', ' ', '\xE0', '\xAA', '\x9F', ' ', '\xE0', '\xAA', '\xB0', ' ', '\xE0', '\xAB', '\xA6', /* ત ન ઋ ઌ છ ટ ર */
'\0',
'\xE0', '\xAA', '\x96', ' ', '\xE0', '\xAA', '\x97', ' ', '\xE0', '\xAA', '\x98', ' ', '\xE0', '\xAA', '\x9E', ' ', '\xE0', '\xAA', '\x87', ' ', '\xE0', '\xAA', '\x88', ' ', '\xE0', '\xAA', '\xA0', ' ', '\xE0', '\xAA', '\x9C', /* ખ ગ ઘ ઞ ઇ ઈ ઠ જ */
'\0',
'\xE0', '\xAA', '\x88', ' ', '\xE0', '\xAA', '\x8A', ' ', '\xE0', '\xAA', '\xBF', ' ', '\xE0', '\xAB', '\x80', ' ', '\xE0', '\xAA', '\xB2', '\xE0', '\xAB', '\x80', ' ', '\xE0', '\xAA', '\xB6', '\xE0', '\xAB', '\x8D', '\xE0', '\xAA', '\x9A', '\xE0', '\xAA', '\xBF', ' ', '\xE0', '\xAA', '\x9C', '\xE0', '\xAA', '\xBF', ' ', '\xE0', '\xAA', '\xB8', '\xE0', '\xAB', '\x80', /* ઈ ઊ િ ી લી શ્ચિ જિ સી */
'\0',
'\xE0', '\xAB', '\x81', ' ', '\xE0', '\xAB', '\x83', ' ', '\xE0', '\xAB', '\x84', ' ', '\xE0', '\xAA', '\x96', '\xE0', '\xAB', '\x81', ' ', '\xE0', '\xAA', '\x9B', '\xE0', '\xAB', '\x83', ' ', '\xE0', '\xAA', '\x9B', '\xE0', '\xAB', '\x84', /* ુ ૃ ૄ ખુ છૃ છૄ */
'\0',
'\xE0', '\xAB', '\xA6', ' ', '\xE0', '\xAB', '\xA7', ' ', '\xE0', '\xAB', '\xA8', ' ', '\xE0', '\xAB', '\xA9', ' ', '\xE0', '\xAB', '\xAD', /* ૧ ૨ ૩ ૭ */
'\0',
'\xE0', '\xA8', '\x95', ' ', '\xE0', '\xA8', '\x97', ' ', '\xE0', '\xA8', '\x99', ' ', '\xE0', '\xA8', '\x9A', ' ', '\xE0', '\xA8', '\x9C', ' ', '\xE0', '\xA8', '\xA4', ' ', '\xE0', '\xA8', '\xA7', ' ', '\xE0', '\xA8', '\xB8', /* ਕ ਗ ਙ ਚ ਜ ਤ ਧ ਸ */
'\0',
'\xE0', '\xA8', '\x95', ' ', '\xE0', '\xA8', '\x97', ' ', '\xE0', '\xA8', '\x99', ' ', '\xE0', '\xA8', '\x9A', ' ', '\xE0', '\xA8', '\x9C', ' ', '\xE0', '\xA8', '\xA4', ' ', '\xE0', '\xA8', '\xA7', ' ', '\xE0', '\xA8', '\xB8', /* ਕ ਗ ਙ ਚ ਜ ਤ ਧ ਸ */
'\0',
'\xE0', '\xA8', '\x87', ' ', '\xE0', '\xA8', '\x88', ' ', '\xE0', '\xA8', '\x89', ' ', '\xE0', '\xA8', '\x8F', ' ', '\xE0', '\xA8', '\x93', ' ', '\xE0', '\xA9', '\xB3', ' ', '\xE0', '\xA8', '\xBF', ' ', '\xE0', '\xA9', '\x80', /* ਇ ਈ ਉ ਏ ਓ ੳ ਿ ੀ */
'\0',
'\xE0', '\xA8', '\x85', ' ', '\xE0', '\xA8', '\x8F', ' ', '\xE0', '\xA8', '\x93', ' ', '\xE0', '\xA8', '\x97', ' ', '\xE0', '\xA8', '\x9C', ' ', '\xE0', '\xA8', '\xA0', ' ', '\xE0', '\xA8', '\xB0', ' ', '\xE0', '\xA8', '\xB8', /* ਅ ਏ ਓ ਗ ਜ ਠ ਰ ਸ */
'\0',
'\xE0', '\xA9', '\xA6', ' ', '\xE0', '\xA9', '\xA7', ' ', '\xE0', '\xA9', '\xA8', ' ', '\xE0', '\xA9', '\xA9', ' ', '\xE0', '\xA9', '\xAD', /* ੨ ੩ ੭ */
'\0',
'\xD7', '\x91', ' ', '\xD7', '\x93', ' ', '\xD7', '\x94', ' ', '\xD7', '\x97', ' ', '\xD7', '\x9A', ' ', '\xD7', '\x9B', ' ', '\xD7', '\x9D', ' ', '\xD7', '\xA1', /* ב ד ה ח ך כ ם ס */
'\0',
'\xD7', '\x91', ' ', '\xD7', '\x98', ' ', '\xD7', '\x9B', ' ', '\xD7', '\x9D', ' ', '\xD7', '\xA1', ' ', '\xD7', '\xA6', /* ב ט כ ם ס צ */
'\0',
'\xD7', '\xA7', ' ', '\xD7', '\x9A', ' ', '\xD7', '\x9F', ' ', '\xD7', '\xA3', ' ', '\xD7', '\xA5', /* ק ך ן ף ץ */
'\0',
'\xE0', '\xB2', '\x87', ' ', '\xE0', '\xB2', '\x8A', ' ', '\xE0', '\xB2', '\x90', ' ', '\xE0', '\xB2', '\xA3', ' ', '\xE0', '\xB2', '\xB8', '\xE0', '\xB2', '\xBE', ' ', '\xE0', '\xB2', '\xA8', '\xE0', '\xB2', '\xBE', ' ', '\xE0', '\xB2', '\xA6', '\xE0', '\xB2', '\xBE', ' ', '\xE0', '\xB2', '\xB0', '\xE0', '\xB2', '\xBE', /* ಇ ಊ ಐ ಣ ಸಾ ನಾ ದಾ ರಾ */
'\0',
'\xE0', '\xB2', '\x85', ' ', '\xE0', '\xB2', '\x89', ' ', '\xE0', '\xB2', '\x8E', ' ', '\xE0', '\xB2', '\xB2', ' ', '\xE0', '\xB3', '\xA6', ' ', '\xE0', '\xB3', '\xA8', ' ', '\xE0', '\xB3', '\xAC', ' ', '\xE0', '\xB3', '\xAD', /* ಅ ಉ ಎ ಲ ೨ ೬ ೭ */
'\0',
'\xEA', '\xA4', '\x85', ' ', '\xEA', '\xA4', '\x8F', ' ', '\xEA', '\xA4', '\x81', ' ', '\xEA', '\xA4', '\x8B', ' ', '\xEA', '\xA4', '\x80', ' ', '\xEA', '\xA4', '\x8D', /* ꤅ ꤏ ꤁ ꤋ ꤀ ꤍ */
'\0',
'\xEA', '\xA4', '\x88', ' ', '\xEA', '\xA4', '\x98', ' ', '\xEA', '\xA4', '\x80', ' ', '\xEA', '\xA4', '\x8D', ' ', '\xEA', '\xA4', '\xA2', /* ꤈ ꤘ ꤀ ꤍ ꤢ */
'\0',
'\xEA', '\xA4', '\x96', ' ', '\xEA', '\xA4', '\xA1', /* ꤖ ꤡ */
'\0',
'\xEA', '\xA4', '\x91', ' ', '\xEA', '\xA4', '\x9C', ' ', '\xEA', '\xA4', '\x9E', /* ꤑ ꤜ ꤞ */
'\0',
'\xEA', '\xA4', '\x91', '\xEA', '\xA4', '\xAC', ' ', '\xEA', '\xA4', '\x9C', '\xEA', '\xA4', '\xAD', ' ', '\xEA', '\xA4', '\x94', '\xEA', '\xA4', '\xAC', /* ꤑ꤬ ꤜ꤭ ꤔ꤬ */
'\0',
'\xE1', '\x9E', '\x81', ' ', '\xE1', '\x9E', '\x91', ' ', '\xE1', '\x9E', '\x93', ' ', '\xE1', '\x9E', '\xA7', ' ', '\xE1', '\x9E', '\xA9', ' ', '\xE1', '\x9E', '\xB6', /* ខ ទ ន ឧ ឩ ា */
'\0',
'\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x80', ' ', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x81', ' ', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x82', ' ', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x90', /* ក្ក ក្ខ ក្គ ក្ថ */
'\0',
'\xE1', '\x9E', '\x81', ' ', '\xE1', '\x9E', '\x83', ' ', '\xE1', '\x9E', '\x85', ' ', '\xE1', '\x9E', '\x8B', ' ', '\xE1', '\x9E', '\x94', ' ', '\xE1', '\x9E', '\x98', ' ', '\xE1', '\x9E', '\x99', ' ', '\xE1', '\x9E', '\xB2', /* ខ ឃ ច ឋ ប ម យ ឲ */
'\0',
'\xE1', '\x9E', '\x8F', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x9A', ' ', '\xE1', '\x9E', '\x9A', '\xE1', '\x9F', '\x80', ' ', '\xE1', '\x9E', '\xB2', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x99', ' ', '\xE1', '\x9E', '\xA2', '\xE1', '\x9E', '\xBF', /* ត្រ រៀ ឲ្យ អឿ */
'\0',
'\xE1', '\x9E', '\x93', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x8F', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x9A', '\xE1', '\x9F', '\x83', ' ', '\xE1', '\x9E', '\x84', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x81', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x99', ' ', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x94', '\xE1', '\x9F', '\x80', ' ', '\xE1', '\x9E', '\x85', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x9A', '\xE1', '\x9F', '\x80', ' ', '\xE1', '\x9E', '\x93', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x8F', '\xE1', '\x9E', '\xBF', ' ', '\xE1', '\x9E', '\x9B', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x94', '\xE1', '\x9E', '\xBF', /* ន្ត្រៃ ង្ខ្យ ក្បៀ ច្រៀ ន្តឿ ល្បឿ */
'\0',
'\xE1', '\xA7', '\xA0', ' ', '\xE1', '\xA7', '\xA1', /* ᧠ ᧡ */
'\0',
'\xE1', '\xA7', '\xB6', ' ', '\xE1', '\xA7', '\xB9', /* ᧶ ᧹ */
'\0',
'\xE0', '\xBA', '\xB2', ' ', '\xE0', '\xBA', '\x94', ' ', '\xE0', '\xBA', '\xAD', ' ', '\xE0', '\xBA', '\xA1', ' ', '\xE0', '\xBA', '\xA5', ' ', '\xE0', '\xBA', '\xA7', ' ', '\xE0', '\xBA', '\xA3', ' ', '\xE0', '\xBA', '\x87', /* າ ດ ອ ມ ລ ວ ຣ ງ */
'\0',
'\xE0', '\xBA', '\xB2', ' ', '\xE0', '\xBA', '\xAD', ' ', '\xE0', '\xBA', '\x9A', ' ', '\xE0', '\xBA', '\x8D', ' ', '\xE0', '\xBA', '\xA3', ' ', '\xE0', '\xBA', '\xAE', ' ', '\xE0', '\xBA', '\xA7', ' ', '\xE0', '\xBA', '\xA2', /* າ ອ ບ ຍ ຣ ຮ ວ ຢ */
'\0',
'\xE0', '\xBA', '\x9B', ' ', '\xE0', '\xBA', '\xA2', ' ', '\xE0', '\xBA', '\x9F', ' ', '\xE0', '\xBA', '\x9D', /* ປ ຢ ຟ ຝ */
'\0',
'\xE0', '\xBB', '\x82', ' ', '\xE0', '\xBB', '\x84', ' ', '\xE0', '\xBB', '\x83', /* ໂ ໄ ໃ */
'\0',
'\xE0', '\xBA', '\x87', ' ', '\xE0', '\xBA', '\x8A', ' ', '\xE0', '\xBA', '\x96', ' ', '\xE0', '\xBA', '\xBD', ' ', '\xE0', '\xBB', '\x86', ' ', '\xE0', '\xBA', '\xAF', /* ງ ຊ ຖ ຽ ໆ ຯ */
'\0',
'T', ' ', 'H', ' ', 'E', ' ', 'Z', ' ', 'O', ' ', 'C', ' ', 'Q', ' ', 'S', /* T H E Z O C Q S */
'\0',
'H', ' ', 'E', ' ', 'Z', ' ', 'L', ' ', 'O', ' ', 'C', ' ', 'U', ' ', 'S', /* H E Z L O C U S */
'\0',
'f', ' ', 'i', ' ', 'j', ' ', 'k', ' ', 'd', ' ', 'b', ' ', 'h', /* f i j k d b h */
'\0',
'u', ' ', 'v', ' ', 'x', ' ', 'z', ' ', 'o', ' ', 'e', ' ', 's', ' ', 'c', /* u v x z o e s c */
'\0',
'n', ' ', 'r', ' ', 'x', ' ', 'z', ' ', 'o', ' ', 'e', ' ', 's', ' ', 'c', /* n r x z o e s c */
'\0',
'p', ' ', 'q', ' ', 'g', ' ', 'j', ' ', 'y', /* p q g j y */
'\0',
'\xE2', '\x82', '\x80', ' ', '\xE2', '\x82', '\x83', ' ', '\xE2', '\x82', '\x85', ' ', '\xE2', '\x82', '\x87', ' ', '\xE2', '\x82', '\x88', /* ₀ ₃ ₅ ₇ ₈ */
'\0',
'\xE2', '\x82', '\x80', ' ', '\xE2', '\x82', '\x81', ' ', '\xE2', '\x82', '\x82', ' ', '\xE2', '\x82', '\x83', ' ', '\xE2', '\x82', '\x88', /* ₀ ₁ ₂ ₃ ₈ */
'\0',
'\xE1', '\xB5', '\xA2', ' ', '\xE2', '\xB1', '\xBC', ' ', '\xE2', '\x82', '\x95', ' ', '\xE2', '\x82', '\x96', ' ', '\xE2', '\x82', '\x97', /* ᵢ ⱼ ₕ ₖ ₗ */
'\0',
'\xE2', '\x82', '\x90', ' ', '\xE2', '\x82', '\x91', ' ', '\xE2', '\x82', '\x92', ' ', '\xE2', '\x82', '\x93', ' ', '\xE2', '\x82', '\x99', ' ', '\xE2', '\x82', '\x9B', ' ', '\xE1', '\xB5', '\xA5', ' ', '\xE1', '\xB5', '\xA4', ' ', '\xE1', '\xB5', '\xA3', /* ₐ ₑ ₒ ₓ ₙ ₛ ᵥ ᵤ ᵣ */
'\0',
'\xE1', '\xB5', '\xA6', ' ', '\xE1', '\xB5', '\xA7', ' ', '\xE1', '\xB5', '\xA8', ' ', '\xE1', '\xB5', '\xA9', ' ', '\xE2', '\x82', '\x9A', /* ᵦ ᵧ ᵨ ᵩ ₚ */
'\0',
'\xE2', '\x81', '\xB0', ' ', '\xC2', '\xB3', ' ', '\xE2', '\x81', '\xB5', ' ', '\xE2', '\x81', '\xB7', ' ', '\xE1', '\xB5', '\x80', ' ', '\xE1', '\xB4', '\xB4', ' ', '\xE1', '\xB4', '\xB1', ' ', '\xE1', '\xB4', '\xBC', /* ⁰ ³ ⁵ ⁷ ᵀ ᴴ ᴱ ᴼ */
'\0',
'\xE2', '\x81', '\xB0', ' ', '\xC2', '\xB9', ' ', '\xC2', '\xB2', ' ', '\xC2', '\xB3', ' ', '\xE1', '\xB4', '\xB1', ' ', '\xE1', '\xB4', '\xB8', ' ', '\xE1', '\xB4', '\xBC', ' ', '\xE1', '\xB5', '\x81', /* ⁰ ¹ ² ³ ᴱ ᴸ ᴼ ᵁ */
'\0',
'\xE1', '\xB5', '\x87', ' ', '\xE1', '\xB5', '\x88', ' ', '\xE1', '\xB5', '\x8F', ' ', '\xCA', '\xB0', ' ', '\xCA', '\xB2', ' ', '\xE1', '\xB6', '\xA0', ' ', '\xE2', '\x81', '\xB1', /* ᵇ ᵈ ᵏ ʰ ʲ ᶠ ⁱ */
'\0',
'\xE1', '\xB5', '\x89', ' ', '\xE1', '\xB5', '\x92', ' ', '\xCA', '\xB3', ' ', '\xCB', '\xA2', ' ', '\xCB', '\xA3', ' ', '\xE1', '\xB6', '\x9C', ' ', '\xE1', '\xB6', '\xBB', /* ᵉ ᵒ ʳ ˢ ˣ ᶜ ᶻ */
'\0',
'\xE1', '\xB5', '\x96', ' ', '\xCA', '\xB8', ' ', '\xE1', '\xB5', '\x8D', /* ᵖ ʸ ᵍ */
'\0',
'\xEA', '\x93', '\xA1', ' ', '\xEA', '\x93', '\xA7', ' ', '\xEA', '\x93', '\xB1', ' ', '\xEA', '\x93', '\xB6', ' ', '\xEA', '\x93', '\xA9', ' ', '\xEA', '\x93', '\x9A', ' ', '\xEA', '\x93', '\xB5', ' ', '\xEA', '\x93', '\xB3', /* ꓱ ꓶ ꓩ */
'\0',
'\xEA', '\x93', '\x95', ' ', '\xEA', '\x93', '\x9C', ' ', '\xEA', '\x93', '\x9E', ' ', '\xEA', '\x93', '\xA1', ' ', '\xEA', '\x93', '\x9B', ' ', '\xEA', '\x93', '\xA2', ' ', '\xEA', '\x93', '\xB3', ' ', '\xEA', '\x93', '\xB4', /* ꓕ */
'\0',
'\xE0', '\xB4', '\x92', ' ', '\xE0', '\xB4', '\x9F', ' ', '\xE0', '\xB4', '\xA0', ' ', '\xE0', '\xB4', '\xB1', ' ', '\xE0', '\xB4', '\x9A', ' ', '\xE0', '\xB4', '\xAA', ' ', '\xE0', '\xB4', '\x9A', '\xE0', '\xB5', '\x8D', '\xE0', '\xB4', '\x9A', ' ', '\xE0', '\xB4', '\xAA', '\xE0', '\xB5', '\x8D', '\xE0', '\xB4', '\xAA', /* ഒ ട റ ച പ ച്ച പ്പ */
'\0',
'\xE0', '\xB4', '\x9F', ' ', '\xE0', '\xB4', '\xA0', ' ', '\xE0', '\xB4', '\xA7', ' ', '\xE0', '\xB4', '\xB6', ' ', '\xE0', '\xB4', '\x98', ' ', '\xE0', '\xB4', '\x9A', ' ', '\xE0', '\xB4', '\xA5', ' ', '\xE0', '\xB4', '\xB2', /* ട ധ ശ ഘ ച ഥ ല */
'\0',
'\xF0', '\x96', '\xB9', '\x80', ' ', '\xF0', '\x96', '\xB9', '\x81', ' ', '\xF0', '\x96', '\xB9', '\x82', ' ', '\xF0', '\x96', '\xB9', '\x83', ' ', '\xF0', '\x96', '\xB9', '\x8F', ' ', '\xF0', '\x96', '\xB9', '\x9A', ' ', '\xF0', '\x96', '\xB9', '\x9F', /* 𖹀 𖹁 𖹂 𖹃 𖹏 𖹚 𖹟 */
'\0',
'\xF0', '\x96', '\xB9', '\x80', ' ', '\xF0', '\x96', '\xB9', '\x81', ' ', '\xF0', '\x96', '\xB9', '\x82', ' ', '\xF0', '\x96', '\xB9', '\x83', ' ', '\xF0', '\x96', '\xB9', '\x8F', ' ', '\xF0', '\x96', '\xB9', '\x9A', ' ', '\xF0', '\x96', '\xB9', '\x92', ' ', '\xF0', '\x96', '\xB9', '\x93', /* 𖹀 𖹁 𖹂 𖹃 𖹏 𖹚 𖹒 𖹓 */
'\0',
'\xF0', '\x96', '\xB9', '\xA4', ' ', '\xF0', '\x96', '\xB9', '\xAC', ' ', '\xF0', '\x96', '\xB9', '\xA7', ' ', '\xF0', '\x96', '\xB9', '\xB4', ' ', '\xF0', '\x96', '\xB9', '\xB6', ' ', '\xF0', '\x96', '\xB9', '\xBE', /* 𖹤 𖹬 𖹧 𖹴 𖹶 𖹾 */
'\0',
'\xF0', '\x96', '\xB9', '\xA0', ' ', '\xF0', '\x96', '\xB9', '\xA1', ' ', '\xF0', '\x96', '\xB9', '\xA2', ' ', '\xF0', '\x96', '\xB9', '\xB9', ' ', '\xF0', '\x96', '\xB9', '\xB3', ' ', '\xF0', '\x96', '\xB9', '\xAE', /* 𖹠 𖹡 𖹢 𖹹 𖹳 𖹮 */
'\0',
'\xF0', '\x96', '\xB9', '\xA0', ' ', '\xF0', '\x96', '\xB9', '\xA1', ' ', '\xF0', '\x96', '\xB9', '\xA2', ' ', '\xF0', '\x96', '\xB9', '\xB3', ' ', '\xF0', '\x96', '\xB9', '\xAD', ' ', '\xF0', '\x96', '\xB9', '\xBD', /* 𖹠 𖹡 𖹢 𖹳 𖹭 𖹽 */
'\0',
'\xF0', '\x96', '\xB9', '\xA5', ' ', '\xF0', '\x96', '\xB9', '\xA8', ' ', '\xF0', '\x96', '\xB9', '\xA9', /* 𖹥 𖹨 𖹩 */
'\0',
'\xF0', '\x96', '\xBA', '\x80', ' ', '\xF0', '\x96', '\xBA', '\x85', ' ', '\xF0', '\x96', '\xBA', '\x88', ' ', '\xF0', '\x96', '\xBA', '\x84', ' ', '\xF0', '\x96', '\xBA', '\x8D', /* 𖺀 𖺅 𖺈 𖺄 𖺍 */
'\0',
'\xE1', '\xA0', '\xB3', ' ', '\xE1', '\xA0', '\xB4', ' ', '\xE1', '\xA0', '\xB6', ' ', '\xE1', '\xA0', '\xBD', ' ', '\xE1', '\xA1', '\x82', ' ', '\xE1', '\xA1', '\x8A', ' ', '\xE2', '\x80', '\x8D', '\xE1', '\xA1', '\xA1', '\xE2', '\x80', '\x8D', ' ', '\xE2', '\x80', '\x8D', '\xE1', '\xA1', '\xB3', '\xE2', '\x80', '\x8D', /* ᠳ ᠴ ᠶ ᠽ ᡂ ᡊ ‍ᡡ‍ ‍ᡳ‍ */
'\0',
'\xE1', '\xA1', '\x83', /* ᡃ */
'\0',
'\xE1', '\x80', '\x81', ' ', '\xE1', '\x80', '\x82', ' ', '\xE1', '\x80', '\x84', ' ', '\xE1', '\x80', '\x92', ' ', '\xE1', '\x80', '\x9D', ' ', '\xE1', '\x81', '\xA5', ' ', '\xE1', '\x81', '\x8A', ' ', '\xE1', '\x81', '\x8B', /* ခ ဂ င ဒ ၥ ၊ ။ */
'\0',
'\xE1', '\x80', '\x84', ' ', '\xE1', '\x80', '\x8E', ' ', '\xE1', '\x80', '\x92', ' ', '\xE1', '\x80', '\x95', ' ', '\xE1', '\x80', '\x97', ' ', '\xE1', '\x80', '\x9D', ' ', '\xE1', '\x81', '\x8A', ' ', '\xE1', '\x81', '\x8B', /* င ဎ ဒ ပ ဗ ၊ ။ */
'\0',
'\xE1', '\x80', '\xA9', ' ', '\xE1', '\x80', '\xBC', ' ', '\xE1', '\x81', '\x8D', ' ', '\xE1', '\x81', '\x8F', ' ', '\xE1', '\x81', '\x86', ' ', '\xE1', '\x80', '\xAB', ' ', '\xE1', '\x80', '\xAD', /* ဩ ြ ၍ ၏ ၆ ါ ိ */
'\0',
'\xE1', '\x80', '\x89', ' ', '\xE1', '\x80', '\x8A', ' ', '\xE1', '\x80', '\xA5', ' ', '\xE1', '\x80', '\xA9', ' ', '\xE1', '\x80', '\xA8', ' ', '\xE1', '\x81', '\x82', ' ', '\xE1', '\x81', '\x85', ' ', '\xE1', '\x81', '\x89', /* ဉ ည ဥ ဩ ဨ ၂ ၅ ၉ */
'\0',
'\xDF', '\x90', ' ', '\xDF', '\x89', ' ', '\xDF', '\x92', ' ', '\xDF', '\x9F', ' ', '\xDF', '\x96', ' ', '\xDF', '\x9C', ' ', '\xDF', '\xA0', ' ', '\xDF', '\xA5', /* ߐ ߉ ߒ ߟ ߖ ߜ ߠ ߥ */
'\0',
'\xDF', '\x80', ' ', '\xDF', '\x98', ' ', '\xDF', '\xA1', ' ', '\xDF', '\xA0', ' ', '\xDF', '\xA5', /* ߀ ߘ ߡ ߠ ߥ */
'\0',
'\xDF', '\x8F', ' ', '\xDF', '\x9B', ' ', '\xDF', '\x8B', /* ߏ ߛ ߋ */
'\0',
'\xDF', '\x8E', ' ', '\xDF', '\x8F', ' ', '\xDF', '\x9B', ' ', '\xDF', '\x8B', /* ߎ ߏ ߛ ߋ */
'\0',
'\xE1', '\xB1', '\x9B', ' ', '\xE1', '\xB1', '\x9C', ' ', '\xE1', '\xB1', '\x9D', ' ', '\xE1', '\xB1', '\xA1', ' ', '\xE1', '\xB1', '\xA2', ' ', '\xE1', '\xB1', '\xA5', /* ᱛ ᱜ ᱝ ᱡ ᱢ ᱥ */
'\0',
'\xF0', '\x90', '\xB0', '\x97', ' ', '\xF0', '\x90', '\xB0', '\x98', ' ', '\xF0', '\x90', '\xB0', '\xA7', /* 𐰗 𐰘 𐰧 */
'\0',
'\xF0', '\x90', '\xB0', '\x89', ' ', '\xF0', '\x90', '\xB0', '\x97', ' ', '\xF0', '\x90', '\xB0', '\xA6', ' ', '\xF0', '\x90', '\xB0', '\xA7', /* 𐰉 𐰗 𐰦 𐰧 */
'\0',
'\xF0', '\x90', '\x92', '\xBE', ' ', '\xF0', '\x90', '\x93', '\x8D', ' ', '\xF0', '\x90', '\x93', '\x92', ' ', '\xF0', '\x90', '\x93', '\x93', ' ', '\xF0', '\x90', '\x92', '\xBB', ' ', '\xF0', '\x90', '\x93', '\x82', ' ', '\xF0', '\x90', '\x92', '\xB5', ' ', '\xF0', '\x90', '\x93', '\x86', /* 𐒾 𐓍 𐓒 𐓓 𐒻 𐓂 𐒵 𐓆 */
'\0',
'\xF0', '\x90', '\x92', '\xB0', ' ', '\xF0', '\x90', '\x93', '\x8D', ' ', '\xF0', '\x90', '\x93', '\x82', ' ', '\xF0', '\x90', '\x92', '\xBF', ' ', '\xF0', '\x90', '\x93', '\x8E', ' ', '\xF0', '\x90', '\x92', '\xB9', /* 𐒰 𐓍 𐓂 𐒿 𐓎 𐒹 */
'\0',
'\xF0', '\x90', '\x92', '\xBC', ' ', '\xF0', '\x90', '\x92', '\xBD', ' ', '\xF0', '\x90', '\x92', '\xBE', /* 𐒼 𐒽 𐒾 */
'\0',
'\xF0', '\x90', '\x93', '\xB5', ' ', '\xF0', '\x90', '\x93', '\xB6', ' ', '\xF0', '\x90', '\x93', '\xBA', ' ', '\xF0', '\x90', '\x93', '\xBB', ' ', '\xF0', '\x90', '\x93', '\x9D', ' ', '\xF0', '\x90', '\x93', '\xA3', ' ', '\xF0', '\x90', '\x93', '\xAA', ' ', '\xF0', '\x90', '\x93', '\xAE', /* 𐓵 𐓶 𐓺 𐓻 𐓝 𐓣 𐓪 𐓮 */
'\0',
'\xF0', '\x90', '\x93', '\x98', ' ', '\xF0', '\x90', '\x93', '\x9A', ' ', '\xF0', '\x90', '\x93', '\xA3', ' ', '\xF0', '\x90', '\x93', '\xB5', ' ', '\xF0', '\x90', '\x93', '\xA1', ' ', '\xF0', '\x90', '\x93', '\xA7', ' ', '\xF0', '\x90', '\x93', '\xAA', ' ', '\xF0', '\x90', '\x93', '\xB6', /* 𐓘 𐓚 𐓣 𐓵 𐓡 𐓧 𐓪 𐓶 */
'\0',
'\xF0', '\x90', '\x93', '\xA4', ' ', '\xF0', '\x90', '\x93', '\xA6', ' ', '\xF0', '\x90', '\x93', '\xB8', ' ', '\xF0', '\x90', '\x93', '\xB9', ' ', '\xF0', '\x90', '\x93', '\x9B', /* 𐓤 𐓦 𐓸 𐓹 𐓛 */
'\0',
'\xF0', '\x90', '\x93', '\xA4', ' ', '\xF0', '\x90', '\x93', '\xA5', ' ', '\xF0', '\x90', '\x93', '\xA6', /* 𐓤 𐓥 𐓦 */
'\0',
'\xF0', '\x90', '\x92', '\x86', ' ', '\xF0', '\x90', '\x92', '\x89', ' ', '\xF0', '\x90', '\x92', '\x90', ' ', '\xF0', '\x90', '\x92', '\x92', ' ', '\xF0', '\x90', '\x92', '\x98', ' ', '\xF0', '\x90', '\x92', '\x9B', ' ', '\xF0', '\x90', '\x92', '\xA0', ' ', '\xF0', '\x90', '\x92', '\xA3', /* 𐒆 𐒉 𐒐 𐒒 𐒘 𐒛 𐒠 𐒣 */
'\0',
'\xF0', '\x90', '\x92', '\x80', ' ', '\xF0', '\x90', '\x92', '\x82', ' ', '\xF0', '\x90', '\x92', '\x86', ' ', '\xF0', '\x90', '\x92', '\x88', ' ', '\xF0', '\x90', '\x92', '\x8A', ' ', '\xF0', '\x90', '\x92', '\x92', ' ', '\xF0', '\x90', '\x92', '\xA0', ' ', '\xF0', '\x90', '\x92', '\xA9', /* 𐒀 𐒂 𐒆 𐒈 𐒊 𐒒 𐒠 𐒩 */
'\0',
'\xF0', '\x90', '\xB4', '\x83', ' ', '\xF0', '\x90', '\xB4', '\x80', ' ', '\xF0', '\x90', '\xB4', '\x86', ' ', '\xF0', '\x90', '\xB4', '\x96', ' ', '\xF0', '\x90', '\xB4', '\x95', /* 𐴃 𐴀 𐴆 𐴖 𐴕 */
'\0',
'\xF0', '\x90', '\xB4', '\x94', ' ', '\xF0', '\x90', '\xB4', '\x96', ' ', '\xF0', '\x90', '\xB4', '\x95', ' ', '\xF0', '\x90', '\xB4', '\x91', ' ', '\xF0', '\x90', '\xB4', '\x90', /* 𐴔 𐴖 𐴕 𐴑 𐴐 */
'\0',
'\xD9', '\x80', /* ـ */
'\0',
'\xEA', '\xA2', '\x9C', ' ', '\xEA', '\xA2', '\x9E', ' ', '\xEA', '\xA2', '\xB3', ' ', '\xEA', '\xA2', '\x82', ' ', '\xEA', '\xA2', '\x96', ' ', '\xEA', '\xA2', '\x92', ' ', '\xEA', '\xA2', '\x9D', ' ', '\xEA', '\xA2', '\x9B', /* ꢜ ꢞ ꢳ ꢂ ꢖ ꢒ ꢝ ꢛ */
'\0',
'\xEA', '\xA2', '\x82', ' ', '\xEA', '\xA2', '\xA8', ' ', '\xEA', '\xA2', '\xBA', ' ', '\xEA', '\xA2', '\xA4', ' ', '\xEA', '\xA2', '\x8E', /* ꢂ ꢨ ꢺ ꢤ ꢎ */
'\0',
'\xF0', '\x90', '\x91', '\x95', ' ', '\xF0', '\x90', '\x91', '\x99', /* 𐑕 𐑙 */
'\0',
'\xF0', '\x90', '\x91', '\x94', ' ', '\xF0', '\x90', '\x91', '\x96', ' ', '\xF0', '\x90', '\x91', '\x97', ' ', '\xF0', '\x90', '\x91', '\xB9', ' ', '\xF0', '\x90', '\x91', '\xBB', /* 𐑔 𐑖 𐑗 𐑹 𐑻 */
'\0',
'\xF0', '\x90', '\x91', '\x9F', ' ', '\xF0', '\x90', '\x91', '\xA3', /* 𐑟 𐑣 */
'\0',
'\xF0', '\x90', '\x91', '\xB1', ' ', '\xF0', '\x90', '\x91', '\xB2', ' ', '\xF0', '\x90', '\x91', '\xB3', ' ', '\xF0', '\x90', '\x91', '\xB4', ' ', '\xF0', '\x90', '\x91', '\xB8', ' ', '\xF0', '\x90', '\x91', '\xBA', ' ', '\xF0', '\x90', '\x91', '\xBC', /* 𐑱 𐑲 𐑳 𐑴 𐑸 𐑺 𐑼 */
'\0',
'\xF0', '\x90', '\x91', '\xB4', ' ', '\xF0', '\x90', '\x91', '\xBB', ' ', '\xF0', '\x90', '\x91', '\xB9', /* 𐑴 𐑻 𐑹 */
'\0',
'\xE0', '\xB6', '\x89', ' ', '\xE0', '\xB6', '\x9A', ' ', '\xE0', '\xB6', '\x9D', ' ', '\xE0', '\xB6', '\xB3', ' ', '\xE0', '\xB6', '\xB4', ' ', '\xE0', '\xB6', '\xBA', ' ', '\xE0', '\xB6', '\xBD', ' ', '\xE0', '\xB7', '\x86', /* ඉ ක ඝ ඳ ප ය ල ෆ */
'\0',
'\xE0', '\xB6', '\x91', ' ', '\xE0', '\xB6', '\x94', ' ', '\xE0', '\xB6', '\x9D', ' ', '\xE0', '\xB6', '\xA2', ' ', '\xE0', '\xB6', '\xA7', ' ', '\xE0', '\xB6', '\xAE', ' ', '\xE0', '\xB6', '\xB0', ' ', '\xE0', '\xB6', '\xBB', /* එ ඔ ඝ ජ ට ථ ධ ර */
'\0',
'\xE0', '\xB6', '\xAF', ' ', '\xE0', '\xB6', '\xB3', ' ', '\xE0', '\xB6', '\x8B', ' ', '\xE0', '\xB6', '\xBD', ' ', '\xE0', '\xB6', '\xAD', '\xE0', '\xB7', '\x96', ' ', '\xE0', '\xB6', '\xAD', '\xE0', '\xB7', '\x94', ' ', '\xE0', '\xB6', '\xB6', '\xE0', '\xB7', '\x94', ' ', '\xE0', '\xB6', '\xAF', '\xE0', '\xB7', '\x94', /* ද ඳ උ ල තූ තු බු දු */
'\0',
'\xE1', '\xAE', '\x8B', ' ', '\xE1', '\xAE', '\x9E', ' ', '\xE1', '\xAE', '\xAE', ' ', '\xE1', '\xAE', '\xBD', ' ', '\xE1', '\xAE', '\xB0', ' ', '\xE1', '\xAE', '\x88', /* ᮋ ᮞ ᮮ ᮽ ᮰ ᮈ */
'\0',
'\xE1', '\xAE', '\x84', ' ', '\xE1', '\xAE', '\x94', ' ', '\xE1', '\xAE', '\x95', ' ', '\xE1', '\xAE', '\x97', ' ', '\xE1', '\xAE', '\xB0', ' ', '\xE1', '\xAE', '\x86', ' ', '\xE1', '\xAE', '\x88', ' ', '\xE1', '\xAE', '\x89', /* ᮄ ᮔ ᮕ ᮗ ᮰ ᮆ ᮈ ᮉ */
'\0',
'\xE1', '\xAE', '\xBC', ' ', '\xE1', '\xB3', '\x84', /* ᮼ ᳄ */
'\0',
'\xEA', '\xAA', '\x86', ' ', '\xEA', '\xAA', '\x94', ' ', '\xEA', '\xAA', '\x92', ' ', '\xEA', '\xAA', '\x96', ' ', '\xEA', '\xAA', '\xAB', /* ꪆ ꪔ ꪒ ꪖ ꪫ */
'\0',
'\xEA', '\xAA', '\x89', ' ', '\xEA', '\xAA', '\xAB', ' ', '\xEA', '\xAA', '\xAE', /* ꪉ ꪫ ꪮ */
'\0',
'\xE0', '\xAE', '\x89', ' ', '\xE0', '\xAE', '\x92', ' ', '\xE0', '\xAE', '\x93', ' ', '\xE0', '\xAE', '\xB1', ' ', '\xE0', '\xAE', '\x88', ' ', '\xE0', '\xAE', '\x95', ' ', '\xE0', '\xAE', '\x99', ' ', '\xE0', '\xAE', '\x9A', /* உ ஒ ஓ ற ஈ க ங ச */
'\0',
'\xE0', '\xAE', '\x95', ' ', '\xE0', '\xAE', '\x9A', ' ', '\xE0', '\xAE', '\xB2', ' ', '\xE0', '\xAE', '\xB6', ' ', '\xE0', '\xAE', '\x89', ' ', '\xE0', '\xAE', '\x99', ' ', '\xE0', '\xAE', '\x9F', ' ', '\xE0', '\xAE', '\xAA', /* க ச ல ஶ உ ங ட ப */
'\0',
'\xE0', '\xB0', '\x87', ' ', '\xE0', '\xB0', '\x8C', ' ', '\xE0', '\xB0', '\x99', ' ', '\xE0', '\xB0', '\x9E', ' ', '\xE0', '\xB0', '\xA3', ' ', '\xE0', '\xB0', '\xB1', ' ', '\xE0', '\xB1', '\xAF', /* ఇ ఌ ఙ ఞ ణ ఱ ౯ */
'\0',
'\xE0', '\xB0', '\x85', ' ', '\xE0', '\xB0', '\x95', ' ', '\xE0', '\xB0', '\x9A', ' ', '\xE0', '\xB0', '\xB0', ' ', '\xE0', '\xB0', '\xBD', ' ', '\xE0', '\xB1', '\xA8', ' ', '\xE0', '\xB1', '\xAC', /* అ క చ ర ఽ ౨ ౬ */
'\0',
'\xE0', '\xB8', '\x9A', ' ', '\xE0', '\xB9', '\x80', ' ', '\xE0', '\xB9', '\x81', ' ', '\xE0', '\xB8', '\xAD', ' ', '\xE0', '\xB8', '\x81', ' ', '\xE0', '\xB8', '\xB2', /* บ เ แ อ ก า */
'\0',
'\xE0', '\xB8', '\x9A', ' ', '\xE0', '\xB8', '\x9B', ' ', '\xE0', '\xB8', '\xA9', ' ', '\xE0', '\xB8', '\xAF', ' ', '\xE0', '\xB8', '\xAD', ' ', '\xE0', '\xB8', '\xA2', ' ', '\xE0', '\xB8', '\xAE', /* บ ป ษ ฯ อ ย ฮ */
'\0',
'\xE0', '\xB8', '\x9B', ' ', '\xE0', '\xB8', '\x9D', ' ', '\xE0', '\xB8', '\x9F', /* ป ฝ ฟ */
'\0',
'\xE0', '\xB9', '\x82', ' ', '\xE0', '\xB9', '\x83', ' ', '\xE0', '\xB9', '\x84', /* โ ใ ไ */
'\0',
'\xE0', '\xB8', '\x8E', ' ', '\xE0', '\xB8', '\x8F', ' ', '\xE0', '\xB8', '\xA4', ' ', '\xE0', '\xB8', '\xA6', /* ฎ ฏ ฤ ฦ */
'\0',
'\xE0', '\xB8', '\x8D', ' ', '\xE0', '\xB8', '\x90', /* ญ ฐ */
'\0',
'\xE0', '\xB9', '\x90', ' ', '\xE0', '\xB9', '\x91', ' ', '\xE0', '\xB9', '\x93', /* ๑ ๓ */
'\0',
'\xE2', '\xB5', '\x94', ' ', '\xE2', '\xB5', '\x99', ' ', '\xE2', '\xB5', '\x9B', ' ', '\xE2', '\xB5', '\x9E', ' ', '\xE2', '\xB4', '\xB5', ' ', '\xE2', '\xB4', '\xBC', ' ', '\xE2', '\xB4', '\xB9', ' ', '\xE2', '\xB5', '\x8E', /* ⵙ ⵛ ⵞ ⴵ ⴼ ⵎ */
'\0',
'\xEA', '\x97', '\x8D', ' ', '\xEA', '\x98', '\x96', ' ', '\xEA', '\x98', '\x99', ' ', '\xEA', '\x98', '\x9C', ' ', '\xEA', '\x96', '\x9C', ' ', '\xEA', '\x96', '\x9D', ' ', '\xEA', '\x94', '\x85', ' ', '\xEA', '\x95', '\xA2', /* ꗍ ꘖ ꘙ ꘜ ꖜ ꖝ ꔅ ꕢ */
'\0',
'\xEA', '\x97', '\x8D', ' ', '\xEA', '\x98', '\x96', ' ', '\xEA', '\x98', '\x99', ' ', '\xEA', '\x97', '\x9E', ' ', '\xEA', '\x94', '\x85', ' ', '\xEA', '\x95', '\xA2', ' ', '\xEA', '\x96', '\x9C', ' ', '\xEA', '\x94', '\x86', /* ꗍ ꘖ ꘙ ꗞ ꔅ ꕢ ꖜ ꔆ */
#ifdef AF_CONFIG_OPTION_CJK
'\0',
'\xE4', '\xBB', '\x96', ' ', '\xE4', '\xBB', '\xAC', ' ', '\xE4', '\xBD', '\xA0', ' ', '\xE4', '\xBE', '\x86', ' ', '\xE5', '\x80', '\x91', ' ', '\xE5', '\x88', '\xB0', ' ', '\xE5', '\x92', '\x8C', ' ', '\xE5', '\x9C', '\xB0', /* 他 们 你 來 們 到 和 地 */
' ', '\xE5', '\xAF', '\xB9', ' ', '\xE5', '\xB0', '\x8D', ' ', '\xE5', '\xB0', '\xB1', ' ', '\xE5', '\xB8', '\xAD', ' ', '\xE6', '\x88', '\x91', ' ', '\xE6', '\x97', '\xB6', ' ', '\xE6', '\x99', '\x82', ' ', '\xE6', '\x9C', '\x83', /* 对 對 就 席 我 时 時 會 */
' ', '\xE6', '\x9D', '\xA5', ' ', '\xE7', '\x82', '\xBA', ' ', '\xE8', '\x83', '\xBD', ' ', '\xE8', '\x88', '\xB0', ' ', '\xE8', '\xAA', '\xAA', ' ', '\xE8', '\xAF', '\xB4', ' ', '\xE8', '\xBF', '\x99', ' ', '\xE9', '\x80', '\x99', /* 来 為 能 舰 說 说 这 這 */
' ', '\xE9', '\xBD', '\x8A', ' ', '|', /* 齊 | */
' ', '\xE5', '\x86', '\x9B', ' ', '\xE5', '\x90', '\x8C', ' ', '\xE5', '\xB7', '\xB2', ' ', '\xE6', '\x84', '\xBF', ' ', '\xE6', '\x97', '\xA2', ' ', '\xE6', '\x98', '\x9F', ' ', '\xE6', '\x98', '\xAF', ' ', '\xE6', '\x99', '\xAF', /* 军 同 已 愿 既 星 是 景 */
' ', '\xE6', '\xB0', '\x91', ' ', '\xE7', '\x85', '\xA7', ' ', '\xE7', '\x8E', '\xB0', ' ', '\xE7', '\x8F', '\xBE', ' ', '\xE7', '\x90', '\x86', ' ', '\xE7', '\x94', '\xA8', ' ', '\xE7', '\xBD', '\xAE', ' ', '\xE8', '\xA6', '\x81', /* 民 照 现 現 理 用 置 要 */
' ', '\xE8', '\xBB', '\x8D', ' ', '\xE9', '\x82', '\xA3', ' ', '\xE9', '\x85', '\x8D', ' ', '\xE9', '\x87', '\x8C', ' ', '\xE9', '\x96', '\x8B', ' ', '\xE9', '\x9B', '\xB7', ' ', '\xE9', '\x9C', '\xB2', ' ', '\xE9', '\x9D', '\xA2', /* 軍 那 配 里 開 雷 露 面 */
' ', '\xE9', '\xA1', '\xBE', /* 顾 */
'\0',
'\xE4', '\xB8', '\xAA', ' ', '\xE4', '\xB8', '\xBA', ' ', '\xE4', '\xBA', '\xBA', ' ', '\xE4', '\xBB', '\x96', ' ', '\xE4', '\xBB', '\xA5', ' ', '\xE4', '\xBB', '\xAC', ' ', '\xE4', '\xBD', '\xA0', ' ', '\xE4', '\xBE', '\x86', /* 个 为 人 他 以 们 你 來 */
' ', '\xE5', '\x80', '\x8B', ' ', '\xE5', '\x80', '\x91', ' ', '\xE5', '\x88', '\xB0', ' ', '\xE5', '\x92', '\x8C', ' ', '\xE5', '\xA4', '\xA7', ' ', '\xE5', '\xAF', '\xB9', ' ', '\xE5', '\xB0', '\x8D', ' ', '\xE5', '\xB0', '\xB1', /* 個 們 到 和 大 对 對 就 */
' ', '\xE6', '\x88', '\x91', ' ', '\xE6', '\x97', '\xB6', ' ', '\xE6', '\x99', '\x82', ' ', '\xE6', '\x9C', '\x89', ' ', '\xE6', '\x9D', '\xA5', ' ', '\xE7', '\x82', '\xBA', ' ', '\xE8', '\xA6', '\x81', ' ', '\xE8', '\xAA', '\xAA', /* 我 时 時 有 来 為 要 說 */
' ', '\xE8', '\xAF', '\xB4', ' ', '|', /* 说 | */
' ', '\xE4', '\xB8', '\xBB', ' ', '\xE4', '\xBA', '\x9B', ' ', '\xE5', '\x9B', '\xA0', ' ', '\xE5', '\xAE', '\x83', ' ', '\xE6', '\x83', '\xB3', ' ', '\xE6', '\x84', '\x8F', ' ', '\xE7', '\x90', '\x86', ' ', '\xE7', '\x94', '\x9F', /* 主 些 因 它 想 意 理 生 */
' ', '\xE7', '\x95', '\xB6', ' ', '\xE7', '\x9C', '\x8B', ' ', '\xE7', '\x9D', '\x80', ' ', '\xE7', '\xBD', '\xAE', ' ', '\xE8', '\x80', '\x85', ' ', '\xE8', '\x87', '\xAA', ' ', '\xE8', '\x91', '\x97', ' ', '\xE8', '\xA3', '\xA1', /* 當 看 着 置 者 自 著 裡 */
' ', '\xE8', '\xBF', '\x87', ' ', '\xE8', '\xBF', '\x98', ' ', '\xE8', '\xBF', '\x9B', ' ', '\xE9', '\x80', '\xB2', ' ', '\xE9', '\x81', '\x8E', ' ', '\xE9', '\x81', '\x93', ' ', '\xE9', '\x82', '\x84', ' ', '\xE9', '\x87', '\x8C', /* 过 还 进 進 過 道 還 里 */
' ', '\xE9', '\x9D', '\xA2', /* 面 */
#ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
'\0',
' ', '\xE4', '\xBA', '\x9B', ' ', '\xE4', '\xBB', '\xAC', ' ', '\xE4', '\xBD', '\xA0', ' ', '\xE4', '\xBE', '\x86', ' ', '\xE5', '\x80', '\x91', ' ', '\xE5', '\x88', '\xB0', ' ', '\xE5', '\x92', '\x8C', ' ', '\xE5', '\x9C', '\xB0', /* 些 们 你 來 們 到 和 地 */
' ', '\xE5', '\xA5', '\xB9', ' ', '\xE5', '\xB0', '\x86', ' ', '\xE5', '\xB0', '\x87', ' ', '\xE5', '\xB0', '\xB1', ' ', '\xE5', '\xB9', '\xB4', ' ', '\xE5', '\xBE', '\x97', ' ', '\xE6', '\x83', '\x85', ' ', '\xE6', '\x9C', '\x80', /* 她 将 將 就 年 得 情 最 */
' ', '\xE6', '\xA0', '\xB7', ' ', '\xE6', '\xA8', '\xA3', ' ', '\xE7', '\x90', '\x86', ' ', '\xE8', '\x83', '\xBD', ' ', '\xE8', '\xAA', '\xAA', ' ', '\xE8', '\xAF', '\xB4', ' ', '\xE8', '\xBF', '\x99', ' ', '\xE9', '\x80', '\x99', /* 样 樣 理 能 說 说 这 這 */
' ', '\xE9', '\x80', '\x9A', ' ', '|', /* 通 | */
' ', '\xE5', '\x8D', '\xB3', ' ', '\xE5', '\x90', '\x97', ' ', '\xE5', '\x90', '\xA7', ' ', '\xE5', '\x90', '\xAC', ' ', '\xE5', '\x91', '\xA2', ' ', '\xE5', '\x93', '\x81', ' ', '\xE5', '\x93', '\x8D', ' ', '\xE5', '\x97', '\x8E', /* 即 吗 吧 听 呢 品 响 嗎 */
' ', '\xE5', '\xB8', '\x88', ' ', '\xE5', '\xB8', '\xAB', ' ', '\xE6', '\x94', '\xB6', ' ', '\xE6', '\x96', '\xAD', ' ', '\xE6', '\x96', '\xB7', ' ', '\xE6', '\x98', '\x8E', ' ', '\xE7', '\x9C', '\xBC', ' ', '\xE9', '\x96', '\x93', /* 师 師 收 断 斷 明 眼 間 */
' ', '\xE9', '\x97', '\xB4', ' ', '\xE9', '\x99', '\x85', ' ', '\xE9', '\x99', '\x88', ' ', '\xE9', '\x99', '\x90', ' ', '\xE9', '\x99', '\xA4', ' ', '\xE9', '\x99', '\xB3', ' ', '\xE9', '\x9A', '\x8F', ' ', '\xE9', '\x9A', '\x9B', /* 间 际 陈 限 除 陳 随 際 */
' ', '\xE9', '\x9A', '\xA8', /* 隨 */
'\0',
'\xE4', '\xBA', '\x8B', ' ', '\xE5', '\x89', '\x8D', ' ', '\xE5', '\xAD', '\xB8', ' ', '\xE5', '\xB0', '\x86', ' ', '\xE5', '\xB0', '\x87', ' ', '\xE6', '\x83', '\x85', ' ', '\xE6', '\x83', '\xB3', ' ', '\xE6', '\x88', '\x96', /* 事 前 學 将 將 情 想 或 */
' ', '\xE6', '\x94', '\xBF', ' ', '\xE6', '\x96', '\xAF', ' ', '\xE6', '\x96', '\xB0', ' ', '\xE6', '\xA0', '\xB7', ' ', '\xE6', '\xA8', '\xA3', ' ', '\xE6', '\xB0', '\x91', ' ', '\xE6', '\xB2', '\x92', ' ', '\xE6', '\xB2', '\xA1', /* 政 斯 新 样 樣 民 沒 没 */
' ', '\xE7', '\x84', '\xB6', ' ', '\xE7', '\x89', '\xB9', ' ', '\xE7', '\x8E', '\xB0', ' ', '\xE7', '\x8F', '\xBE', ' ', '\xE7', '\x90', '\x83', ' ', '\xE7', '\xAC', '\xAC', ' ', '\xE7', '\xB6', '\x93', ' ', '\xE8', '\xB0', '\x81', /* 然 特 现 現 球 第 經 谁 */
' ', '\xE8', '\xB5', '\xB7', ' ', '|', /* 起 | */
' ', '\xE4', '\xBE', '\x8B', ' ', '\xE5', '\x88', '\xA5', ' ', '\xE5', '\x88', '\xAB', ' ', '\xE5', '\x88', '\xB6', ' ', '\xE5', '\x8A', '\xA8', ' ', '\xE5', '\x8B', '\x95', ' ', '\xE5', '\x90', '\x97', ' ', '\xE5', '\x97', '\x8E', /* 例 別 别 制 动 動 吗 嗎 */
' ', '\xE5', '\xA2', '\x9E', ' ', '\xE6', '\x8C', '\x87', ' ', '\xE6', '\x98', '\x8E', ' ', '\xE6', '\x9C', '\x9D', ' ', '\xE6', '\x9C', '\x9F', ' ', '\xE6', '\x9E', '\x84', ' ', '\xE7', '\x89', '\xA9', ' ', '\xE7', '\xA1', '\xAE', /* 增 指 明 朝 期 构 物 确 */
' ', '\xE7', '\xA7', '\x8D', ' ', '\xE8', '\xAA', '\xBF', ' ', '\xE8', '\xB0', '\x83', ' ', '\xE8', '\xB2', '\xBB', ' ', '\xE8', '\xB4', '\xB9', ' ', '\xE9', '\x82', '\xA3', ' ', '\xE9', '\x83', '\xBD', ' ', '\xE9', '\x96', '\x93', /* 种 調 调 費 费 那 都 間 */
' ', '\xE9', '\x97', '\xB4', /* 间 */
#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
#endif /* AF_CONFIG_OPTION_CJK */
'\0',
};
/* stringsets are specific to styles */
FT_LOCAL_ARRAY_DEF( AF_Blue_StringRec )
af_blue_stringsets[] =
{
/* */
{ AF_BLUE_STRING_ADLAM_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_ADLAM_CAPITAL_BOTTOM, 0 },
{ AF_BLUE_STRING_ADLAM_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_ADLAM_SMALL_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_ARABIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_ARABIC_BOTTOM, 0 },
{ AF_BLUE_STRING_ARABIC_JOIN, AF_BLUE_PROPERTY_LATIN_NEUTRAL },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_ARMENIAN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_ARMENIAN_CAPITAL_BOTTOM, 0 },
{ AF_BLUE_STRING_ARMENIAN_SMALL_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_ARMENIAN_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_ARMENIAN_SMALL_BOTTOM, 0 },
{ AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_AVESTAN_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_AVESTAN_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_BAMUM_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_BAMUM_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_BENGALI_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_BENGALI_HEAD, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_BENGALI_BASE, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_NEUTRAL |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_BENGALI_BASE, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_BUHID_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_BUHID_LARGE, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_BUHID_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_BUHID_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_CHAKMA_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_CHAKMA_BOTTOM, 0 },
{ AF_BLUE_STRING_CHAKMA_DESCENDER, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_CANADIAN_SYLLABICS_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_CANADIAN_SYLLABICS_BOTTOM, 0 },
{ AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_BOTTOM, 0 },
{ AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_CARIAN_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_CARIAN_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_CHEROKEE_CAPITAL, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_CHEROKEE_CAPITAL, 0 },
{ AF_BLUE_STRING_CHEROKEE_SMALL_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_CHEROKEE_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_CHEROKEE_SMALL, 0 },
{ AF_BLUE_STRING_CHEROKEE_SMALL_DESCENDER, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_COPTIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_COPTIC_CAPITAL_BOTTOM, 0 },
{ AF_BLUE_STRING_COPTIC_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_COPTIC_SMALL_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_CYPRIOT_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_CYPRIOT_BOTTOM, 0 },
{ AF_BLUE_STRING_CYPRIOT_SMALL, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_CYPRIOT_SMALL, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM, 0 },
{ AF_BLUE_STRING_CYRILLIC_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_CYRILLIC_SMALL, 0 },
{ AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_DEVANAGARI_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_DEVANAGARI_HEAD, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_DEVANAGARI_BASE, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_NEUTRAL |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_DEVANAGARI_BASE, 0 },
{ AF_BLUE_STRING_DEVANAGARI_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_DESERET_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_DESERET_CAPITAL_BOTTOM, 0 },
{ AF_BLUE_STRING_DESERET_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_DESERET_SMALL_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_ETHIOPIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_ETHIOPIC_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_GEORGIAN_MKHEDRULI_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_GEORGIAN_MKHEDRULI_BOTTOM, 0 },
{ AF_BLUE_STRING_GEORGIAN_MKHEDRULI_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_GEORGIAN_MKHEDRULI_DESCENDER, 0 },
{ AF_BLUE_STRING_GEORGIAN_MTAVRULI_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_GEORGIAN_MTAVRULI_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_BOTTOM, 0 },
{ AF_BLUE_STRING_GEORGIAN_NUSKHURI_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_GEORGIAN_NUSKHURI_BOTTOM, 0 },
{ AF_BLUE_STRING_GEORGIAN_NUSKHURI_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_GEORGIAN_NUSKHURI_DESCENDER, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_GLAGOLITIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_GLAGOLITIC_CAPITAL_BOTTOM, 0 },
{ AF_BLUE_STRING_GLAGOLITIC_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_GLAGOLITIC_SMALL_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_GOTHIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_GOTHIC_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_GREEK_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM, 0 },
{ AF_BLUE_STRING_GREEK_SMALL_BETA_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_GREEK_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_GREEK_SMALL, 0 },
{ AF_BLUE_STRING_GREEK_SMALL_DESCENDER, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_GUJARATI_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_GUJARATI_BOTTOM, 0 },
{ AF_BLUE_STRING_GUJARATI_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_GUJARATI_DESCENDER, 0 },
{ AF_BLUE_STRING_GUJARATI_DIGIT_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_GURMUKHI_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_GURMUKHI_HEAD, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_GURMUKHI_BASE, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_NEUTRAL |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_GURMUKHI_BOTTOM, 0 },
{ AF_BLUE_STRING_GURMUKHI_DIGIT_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_HEBREW_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_LONG },
{ AF_BLUE_STRING_HEBREW_BOTTOM, 0 },
{ AF_BLUE_STRING_HEBREW_DESCENDER, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_KANNADA_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_KANNADA_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_KAYAH_LI_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_KAYAH_LI_BOTTOM, 0 },
{ AF_BLUE_STRING_KAYAH_LI_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_KAYAH_LI_DESCENDER, 0 },
{ AF_BLUE_STRING_KAYAH_LI_LARGE_DESCENDER, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_KHMER_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP, AF_BLUE_PROPERTY_LATIN_SUB_TOP },
{ AF_BLUE_STRING_KHMER_BOTTOM, 0 },
{ AF_BLUE_STRING_KHMER_DESCENDER, 0 },
{ AF_BLUE_STRING_KHMER_LARGE_DESCENDER, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_LAO_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_LAO_BOTTOM, 0 },
{ AF_BLUE_STRING_LAO_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_LAO_LARGE_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_LAO_DESCENDER, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_LATIN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM, 0 },
{ AF_BLUE_STRING_LATIN_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_LATIN_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_LATIN_SMALL_BOTTOM, 0 },
{ AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM, 0 },
{ AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_LATIN_SUBS_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_LATIN_SUBS_SMALL, 0 },
{ AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM, 0 },
{ AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_LATIN_SUPS_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_LATIN_SUPS_SMALL, 0 },
{ AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_LISU_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_LISU_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_MALAYALAM_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_MALAYALAM_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_MEDEFAIDRIN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_MEDEFAIDRIN_CAPITAL_BOTTOM, 0 },
{ AF_BLUE_STRING_MEDEFAIDRIN_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_MEDEFAIDRIN_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_MEDEFAIDRIN_SMALL_BOTTOM, 0 },
{ AF_BLUE_STRING_MEDEFAIDRIN_SMALL_DESCENDER, 0 },
{ AF_BLUE_STRING_MEDEFAIDRIN_DIGIT_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_MONGOLIAN_TOP_BASE, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_MONGOLIAN_BOTTOM_BASE, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_MYANMAR_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_MYANMAR_BOTTOM, 0 },
{ AF_BLUE_STRING_MYANMAR_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_MYANMAR_DESCENDER, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_NKO_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_NKO_BOTTOM, 0 },
{ AF_BLUE_STRING_NKO_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_NKO_SMALL_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_OL_CHIKI, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_OL_CHIKI, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_OLD_TURKIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_OLD_TURKIC_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_OSAGE_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_OSAGE_CAPITAL_BOTTOM, 0 },
{ AF_BLUE_STRING_OSAGE_CAPITAL_DESCENDER, 0 },
{ AF_BLUE_STRING_OSAGE_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_OSAGE_SMALL_BOTTOM, 0 },
{ AF_BLUE_STRING_OSAGE_SMALL_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_OSAGE_SMALL_DESCENDER, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_OSMANYA_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_OSMANYA_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_ROHINGYA_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_ROHINGYA_BOTTOM, 0 },
{ AF_BLUE_STRING_ROHINGYA_JOIN, AF_BLUE_PROPERTY_LATIN_NEUTRAL },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_SAURASHTRA_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_SAURASHTRA_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_SHAVIAN_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_SHAVIAN_BOTTOM, 0 },
{ AF_BLUE_STRING_SHAVIAN_DESCENDER, 0 },
{ AF_BLUE_STRING_SHAVIAN_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_SHAVIAN_SMALL_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_SINHALA_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_SINHALA_BOTTOM, 0 },
{ AF_BLUE_STRING_SINHALA_DESCENDER, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_SUNDANESE_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_SUNDANESE_BOTTOM, 0 },
{ AF_BLUE_STRING_SUNDANESE_DESCENDER, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_TAMIL_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_TAMIL_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_TAI_VIET_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_TAI_VIET_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_TELUGU_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_TELUGU_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_THAI_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
{ AF_BLUE_STRING_THAI_BOTTOM, 0 },
{ AF_BLUE_STRING_THAI_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_THAI_LARGE_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_THAI_DESCENDER, 0 },
{ AF_BLUE_STRING_THAI_LARGE_DESCENDER, 0 },
{ AF_BLUE_STRING_THAI_DIGIT_TOP, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_TIFINAGH, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_TIFINAGH, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_VAI_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_VAI_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
#ifdef AF_CONFIG_OPTION_CJK
{ AF_BLUE_STRING_CJK_TOP, AF_BLUE_PROPERTY_CJK_TOP },
{ AF_BLUE_STRING_CJK_BOTTOM, 0 },
#ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
{ AF_BLUE_STRING_CJK_LEFT, AF_BLUE_PROPERTY_CJK_HORIZ },
{ AF_BLUE_STRING_CJK_RIGHT, AF_BLUE_PROPERTY_CJK_HORIZ |
AF_BLUE_PROPERTY_CJK_RIGHT },
#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
{ AF_BLUE_STRING_MAX, 0 },
#endif /* AF_CONFIG_OPTION_CJK */
};
/* END */

View File

@@ -0,0 +1,39 @@
/****************************************************************************
*
* afblue.c
*
* Auto-fitter data for blue strings (body).
*
* Copyright (C) 2013-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include "aftypes.h"
FT_LOCAL_ARRAY_DEF( char )
af_blue_strings[] =
{
/* */
@AF_BLUE_STRINGS_ARRAY@
};
/* stringsets are specific to styles */
FT_LOCAL_ARRAY_DEF( AF_Blue_StringRec )
af_blue_stringsets[] =
{
/* */
@AF_BLUE_STRINGSETS_ARRAY@
};
/* END */

429
thirdparty/freetype/src/autofit/afblue.h vendored Normal file
View File

@@ -0,0 +1,429 @@
/* This file has been generated by the Perl script `afblue.pl', */
/* using data from file `afblue.dat'. */
/****************************************************************************
*
* afblue.h
*
* Auto-fitter data for blue strings (specification).
*
* Copyright (C) 2013-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#ifndef AFBLUE_H_
#define AFBLUE_H_
FT_BEGIN_HEADER
/* an auxiliary macro to decode a UTF-8 character -- since we only use */
/* hard-coded, self-converted data, no error checking is performed */
#define GET_UTF8_CHAR( ch, p ) \
do \
{ \
ch = (unsigned char)*p++; \
if ( ch >= 0x80 ) \
{ \
FT_UInt len_; \
\
\
if ( ch < 0xE0 ) \
{ \
len_ = 1; \
ch &= 0x1F; \
} \
else if ( ch < 0xF0 ) \
{ \
len_ = 2; \
ch &= 0x0F; \
} \
else \
{ \
len_ = 3; \
ch &= 0x07; \
} \
\
for ( ; len_ > 0; len_-- ) \
ch = ( ch << 6 ) | ( *p++ & 0x3F ); \
} \
} while ( 0 )
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** B L U E S T R I N G S *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* At the bottommost level, we define strings for finding blue zones. */
#define AF_BLUE_STRING_MAX_LEN 51
/* The AF_Blue_String enumeration values are offsets into the */
/* `af_blue_strings' array. */
typedef enum AF_Blue_String_
{
AF_BLUE_STRING_ADLAM_CAPITAL_TOP = 0,
AF_BLUE_STRING_ADLAM_CAPITAL_BOTTOM = 30,
AF_BLUE_STRING_ADLAM_SMALL_TOP = 40,
AF_BLUE_STRING_ADLAM_SMALL_BOTTOM = 65,
AF_BLUE_STRING_ARABIC_TOP = 105,
AF_BLUE_STRING_ARABIC_BOTTOM = 123,
AF_BLUE_STRING_ARABIC_JOIN = 138,
AF_BLUE_STRING_ARMENIAN_CAPITAL_TOP = 141,
AF_BLUE_STRING_ARMENIAN_CAPITAL_BOTTOM = 165,
AF_BLUE_STRING_ARMENIAN_SMALL_ASCENDER = 189,
AF_BLUE_STRING_ARMENIAN_SMALL_TOP = 210,
AF_BLUE_STRING_ARMENIAN_SMALL_BOTTOM = 234,
AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER = 258,
AF_BLUE_STRING_AVESTAN_TOP = 282,
AF_BLUE_STRING_AVESTAN_BOTTOM = 302,
AF_BLUE_STRING_BAMUM_TOP = 312,
AF_BLUE_STRING_BAMUM_BOTTOM = 344,
AF_BLUE_STRING_BENGALI_BASE = 376,
AF_BLUE_STRING_BENGALI_TOP = 408,
AF_BLUE_STRING_BENGALI_HEAD = 436,
AF_BLUE_STRING_BUHID_TOP = 468,
AF_BLUE_STRING_BUHID_LARGE = 476,
AF_BLUE_STRING_BUHID_SMALL = 488,
AF_BLUE_STRING_BUHID_BOTTOM = 504,
AF_BLUE_STRING_CANADIAN_SYLLABICS_TOP = 532,
AF_BLUE_STRING_CANADIAN_SYLLABICS_BOTTOM = 564,
AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_TOP = 596,
AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_BOTTOM = 628,
AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_TOP = 660,
AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_BOTTOM = 688,
AF_BLUE_STRING_CARIAN_TOP = 720,
AF_BLUE_STRING_CARIAN_BOTTOM = 760,
AF_BLUE_STRING_CHAKMA_TOP = 795,
AF_BLUE_STRING_CHAKMA_BOTTOM = 820,
AF_BLUE_STRING_CHAKMA_DESCENDER = 845,
AF_BLUE_STRING_CHEROKEE_CAPITAL = 910,
AF_BLUE_STRING_CHEROKEE_SMALL_ASCENDER = 942,
AF_BLUE_STRING_CHEROKEE_SMALL = 974,
AF_BLUE_STRING_CHEROKEE_SMALL_DESCENDER = 1006,
AF_BLUE_STRING_COPTIC_CAPITAL_TOP = 1022,
AF_BLUE_STRING_COPTIC_CAPITAL_BOTTOM = 1054,
AF_BLUE_STRING_COPTIC_SMALL_TOP = 1086,
AF_BLUE_STRING_COPTIC_SMALL_BOTTOM = 1118,
AF_BLUE_STRING_CYPRIOT_TOP = 1150,
AF_BLUE_STRING_CYPRIOT_BOTTOM = 1190,
AF_BLUE_STRING_CYPRIOT_SMALL = 1225,
AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP = 1240,
AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM = 1264,
AF_BLUE_STRING_CYRILLIC_SMALL = 1288,
AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER = 1312,
AF_BLUE_STRING_DESERET_CAPITAL_TOP = 1321,
AF_BLUE_STRING_DESERET_CAPITAL_BOTTOM = 1346,
AF_BLUE_STRING_DESERET_SMALL_TOP = 1371,
AF_BLUE_STRING_DESERET_SMALL_BOTTOM = 1396,
AF_BLUE_STRING_DEVANAGARI_BASE = 1421,
AF_BLUE_STRING_DEVANAGARI_TOP = 1453,
AF_BLUE_STRING_DEVANAGARI_HEAD = 1485,
AF_BLUE_STRING_DEVANAGARI_BOTTOM = 1517,
AF_BLUE_STRING_ETHIOPIC_TOP = 1525,
AF_BLUE_STRING_ETHIOPIC_BOTTOM = 1557,
AF_BLUE_STRING_GEORGIAN_MKHEDRULI_TOP = 1589,
AF_BLUE_STRING_GEORGIAN_MKHEDRULI_BOTTOM = 1621,
AF_BLUE_STRING_GEORGIAN_MKHEDRULI_ASCENDER = 1653,
AF_BLUE_STRING_GEORGIAN_MKHEDRULI_DESCENDER = 1685,
AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_TOP = 1717,
AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_BOTTOM = 1749,
AF_BLUE_STRING_GEORGIAN_NUSKHURI_TOP = 1781,
AF_BLUE_STRING_GEORGIAN_NUSKHURI_BOTTOM = 1813,
AF_BLUE_STRING_GEORGIAN_NUSKHURI_ASCENDER = 1845,
AF_BLUE_STRING_GEORGIAN_NUSKHURI_DESCENDER = 1877,
AF_BLUE_STRING_GEORGIAN_MTAVRULI_TOP = 1909,
AF_BLUE_STRING_GEORGIAN_MTAVRULI_BOTTOM = 1941,
AF_BLUE_STRING_GLAGOLITIC_CAPITAL_TOP = 1973,
AF_BLUE_STRING_GLAGOLITIC_CAPITAL_BOTTOM = 2005,
AF_BLUE_STRING_GLAGOLITIC_SMALL_TOP = 2037,
AF_BLUE_STRING_GLAGOLITIC_SMALL_BOTTOM = 2069,
AF_BLUE_STRING_GOTHIC_TOP = 2101,
AF_BLUE_STRING_GOTHIC_BOTTOM = 2141,
AF_BLUE_STRING_GREEK_CAPITAL_TOP = 2161,
AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM = 2182,
AF_BLUE_STRING_GREEK_SMALL_BETA_TOP = 2200,
AF_BLUE_STRING_GREEK_SMALL = 2218,
AF_BLUE_STRING_GREEK_SMALL_DESCENDER = 2242,
AF_BLUE_STRING_GUJARATI_TOP = 2266,
AF_BLUE_STRING_GUJARATI_BOTTOM = 2298,
AF_BLUE_STRING_GUJARATI_ASCENDER = 2330,
AF_BLUE_STRING_GUJARATI_DESCENDER = 2380,
AF_BLUE_STRING_GUJARATI_DIGIT_TOP = 2413,
AF_BLUE_STRING_GURMUKHI_BASE = 2433,
AF_BLUE_STRING_GURMUKHI_HEAD = 2465,
AF_BLUE_STRING_GURMUKHI_TOP = 2497,
AF_BLUE_STRING_GURMUKHI_BOTTOM = 2529,
AF_BLUE_STRING_GURMUKHI_DIGIT_TOP = 2561,
AF_BLUE_STRING_HEBREW_TOP = 2581,
AF_BLUE_STRING_HEBREW_BOTTOM = 2605,
AF_BLUE_STRING_HEBREW_DESCENDER = 2623,
AF_BLUE_STRING_KANNADA_TOP = 2638,
AF_BLUE_STRING_KANNADA_BOTTOM = 2682,
AF_BLUE_STRING_KAYAH_LI_TOP = 2714,
AF_BLUE_STRING_KAYAH_LI_BOTTOM = 2738,
AF_BLUE_STRING_KAYAH_LI_ASCENDER = 2758,
AF_BLUE_STRING_KAYAH_LI_DESCENDER = 2766,
AF_BLUE_STRING_KAYAH_LI_LARGE_DESCENDER = 2778,
AF_BLUE_STRING_KHMER_TOP = 2799,
AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP = 2823,
AF_BLUE_STRING_KHMER_BOTTOM = 2863,
AF_BLUE_STRING_KHMER_DESCENDER = 2895,
AF_BLUE_STRING_KHMER_LARGE_DESCENDER = 2929,
AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP = 3016,
AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM = 3024,
AF_BLUE_STRING_LAO_TOP = 3032,
AF_BLUE_STRING_LAO_BOTTOM = 3064,
AF_BLUE_STRING_LAO_ASCENDER = 3096,
AF_BLUE_STRING_LAO_LARGE_ASCENDER = 3112,
AF_BLUE_STRING_LAO_DESCENDER = 3124,
AF_BLUE_STRING_LATIN_CAPITAL_TOP = 3148,
AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM = 3164,
AF_BLUE_STRING_LATIN_SMALL_F_TOP = 3180,
AF_BLUE_STRING_LATIN_SMALL_TOP = 3194,
AF_BLUE_STRING_LATIN_SMALL_BOTTOM = 3210,
AF_BLUE_STRING_LATIN_SMALL_DESCENDER = 3226,
AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP = 3236,
AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM = 3256,
AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP = 3276,
AF_BLUE_STRING_LATIN_SUBS_SMALL = 3296,
AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER = 3332,
AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP = 3352,
AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM = 3383,
AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP = 3412,
AF_BLUE_STRING_LATIN_SUPS_SMALL = 3438,
AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER = 3463,
AF_BLUE_STRING_LISU_TOP = 3474,
AF_BLUE_STRING_LISU_BOTTOM = 3506,
AF_BLUE_STRING_MALAYALAM_TOP = 3538,
AF_BLUE_STRING_MALAYALAM_BOTTOM = 3582,
AF_BLUE_STRING_MEDEFAIDRIN_CAPITAL_TOP = 3614,
AF_BLUE_STRING_MEDEFAIDRIN_CAPITAL_BOTTOM = 3649,
AF_BLUE_STRING_MEDEFAIDRIN_SMALL_F_TOP = 3689,
AF_BLUE_STRING_MEDEFAIDRIN_SMALL_TOP = 3719,
AF_BLUE_STRING_MEDEFAIDRIN_SMALL_BOTTOM = 3749,
AF_BLUE_STRING_MEDEFAIDRIN_SMALL_DESCENDER = 3779,
AF_BLUE_STRING_MEDEFAIDRIN_DIGIT_TOP = 3794,
AF_BLUE_STRING_MONGOLIAN_TOP_BASE = 3819,
AF_BLUE_STRING_MONGOLIAN_BOTTOM_BASE = 3863,
AF_BLUE_STRING_MYANMAR_TOP = 3867,
AF_BLUE_STRING_MYANMAR_BOTTOM = 3899,
AF_BLUE_STRING_MYANMAR_ASCENDER = 3931,
AF_BLUE_STRING_MYANMAR_DESCENDER = 3959,
AF_BLUE_STRING_NKO_TOP = 3991,
AF_BLUE_STRING_NKO_BOTTOM = 4015,
AF_BLUE_STRING_NKO_SMALL_TOP = 4030,
AF_BLUE_STRING_NKO_SMALL_BOTTOM = 4039,
AF_BLUE_STRING_OL_CHIKI = 4051,
AF_BLUE_STRING_OLD_TURKIC_TOP = 4075,
AF_BLUE_STRING_OLD_TURKIC_BOTTOM = 4090,
AF_BLUE_STRING_OSAGE_CAPITAL_TOP = 4110,
AF_BLUE_STRING_OSAGE_CAPITAL_BOTTOM = 4150,
AF_BLUE_STRING_OSAGE_CAPITAL_DESCENDER = 4180,
AF_BLUE_STRING_OSAGE_SMALL_TOP = 4195,
AF_BLUE_STRING_OSAGE_SMALL_BOTTOM = 4235,
AF_BLUE_STRING_OSAGE_SMALL_ASCENDER = 4275,
AF_BLUE_STRING_OSAGE_SMALL_DESCENDER = 4300,
AF_BLUE_STRING_OSMANYA_TOP = 4315,
AF_BLUE_STRING_OSMANYA_BOTTOM = 4355,
AF_BLUE_STRING_ROHINGYA_TOP = 4395,
AF_BLUE_STRING_ROHINGYA_BOTTOM = 4420,
AF_BLUE_STRING_ROHINGYA_JOIN = 4445,
AF_BLUE_STRING_SAURASHTRA_TOP = 4448,
AF_BLUE_STRING_SAURASHTRA_BOTTOM = 4480,
AF_BLUE_STRING_SHAVIAN_TOP = 4500,
AF_BLUE_STRING_SHAVIAN_BOTTOM = 4510,
AF_BLUE_STRING_SHAVIAN_DESCENDER = 4535,
AF_BLUE_STRING_SHAVIAN_SMALL_TOP = 4545,
AF_BLUE_STRING_SHAVIAN_SMALL_BOTTOM = 4580,
AF_BLUE_STRING_SINHALA_TOP = 4595,
AF_BLUE_STRING_SINHALA_BOTTOM = 4627,
AF_BLUE_STRING_SINHALA_DESCENDER = 4659,
AF_BLUE_STRING_SUNDANESE_TOP = 4703,
AF_BLUE_STRING_SUNDANESE_BOTTOM = 4727,
AF_BLUE_STRING_SUNDANESE_DESCENDER = 4759,
AF_BLUE_STRING_TAI_VIET_TOP = 4767,
AF_BLUE_STRING_TAI_VIET_BOTTOM = 4787,
AF_BLUE_STRING_TAMIL_TOP = 4799,
AF_BLUE_STRING_TAMIL_BOTTOM = 4831,
AF_BLUE_STRING_TELUGU_TOP = 4863,
AF_BLUE_STRING_TELUGU_BOTTOM = 4891,
AF_BLUE_STRING_THAI_TOP = 4919,
AF_BLUE_STRING_THAI_BOTTOM = 4943,
AF_BLUE_STRING_THAI_ASCENDER = 4971,
AF_BLUE_STRING_THAI_LARGE_ASCENDER = 4983,
AF_BLUE_STRING_THAI_DESCENDER = 4995,
AF_BLUE_STRING_THAI_LARGE_DESCENDER = 5011,
AF_BLUE_STRING_THAI_DIGIT_TOP = 5019,
AF_BLUE_STRING_TIFINAGH = 5031,
AF_BLUE_STRING_VAI_TOP = 5063,
AF_BLUE_STRING_VAI_BOTTOM = 5095,
af_blue_1_1 = 5126,
#ifdef AF_CONFIG_OPTION_CJK
AF_BLUE_STRING_CJK_TOP = af_blue_1_1 + 1,
AF_BLUE_STRING_CJK_BOTTOM = af_blue_1_1 + 203,
af_blue_1_1_1 = af_blue_1_1 + 404,
#ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
AF_BLUE_STRING_CJK_LEFT = af_blue_1_1_1 + 1,
AF_BLUE_STRING_CJK_RIGHT = af_blue_1_1_1 + 204,
af_blue_1_1_2 = af_blue_1_1_1 + 405,
#else
af_blue_1_1_2 = af_blue_1_1_1 + 0,
#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
af_blue_1_2 = af_blue_1_1_2 + 0,
#else
af_blue_1_2 = af_blue_1_1 + 0,
#endif /* AF_CONFIG_OPTION_CJK */
AF_BLUE_STRING_MAX /* do not remove */
} AF_Blue_String;
FT_LOCAL_ARRAY( char )
af_blue_strings[];
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** B L U E S T R I N G S E T S *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* The next level is to group blue strings into style-specific sets. */
/* Properties are specific to a writing system. We assume that a given */
/* blue string can't be used in more than a single writing system, which */
/* is a safe bet. */
#define AF_BLUE_PROPERTY_LATIN_TOP ( 1U << 0 ) /* must have value 1 */
#define AF_BLUE_PROPERTY_LATIN_SUB_TOP ( 1U << 1 )
#define AF_BLUE_PROPERTY_LATIN_NEUTRAL ( 1U << 2 )
#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1U << 3 )
#define AF_BLUE_PROPERTY_LATIN_LONG ( 1U << 4 )
#define AF_BLUE_PROPERTY_CJK_TOP ( 1U << 0 ) /* must have value 1 */
#define AF_BLUE_PROPERTY_CJK_HORIZ ( 1U << 1 ) /* must have value 2 */
#define AF_BLUE_PROPERTY_CJK_RIGHT AF_BLUE_PROPERTY_CJK_TOP
#define AF_BLUE_STRINGSET_MAX_LEN 8
/* The AF_Blue_Stringset enumeration values are offsets into the */
/* `af_blue_stringsets' array. */
typedef enum AF_Blue_Stringset_
{
AF_BLUE_STRINGSET_ADLM = 0,
AF_BLUE_STRINGSET_ARAB = 5,
AF_BLUE_STRINGSET_ARMN = 9,
AF_BLUE_STRINGSET_AVST = 16,
AF_BLUE_STRINGSET_BAMU = 19,
AF_BLUE_STRINGSET_BENG = 22,
AF_BLUE_STRINGSET_BUHD = 27,
AF_BLUE_STRINGSET_CAKM = 32,
AF_BLUE_STRINGSET_CANS = 36,
AF_BLUE_STRINGSET_CARI = 43,
AF_BLUE_STRINGSET_CHER = 46,
AF_BLUE_STRINGSET_COPT = 53,
AF_BLUE_STRINGSET_CPRT = 58,
AF_BLUE_STRINGSET_CYRL = 63,
AF_BLUE_STRINGSET_DEVA = 69,
AF_BLUE_STRINGSET_DSRT = 75,
AF_BLUE_STRINGSET_ETHI = 80,
AF_BLUE_STRINGSET_GEOR = 83,
AF_BLUE_STRINGSET_GEOK = 90,
AF_BLUE_STRINGSET_GLAG = 97,
AF_BLUE_STRINGSET_GOTH = 102,
AF_BLUE_STRINGSET_GREK = 105,
AF_BLUE_STRINGSET_GUJR = 112,
AF_BLUE_STRINGSET_GURU = 118,
AF_BLUE_STRINGSET_HEBR = 124,
AF_BLUE_STRINGSET_KNDA = 128,
AF_BLUE_STRINGSET_KALI = 131,
AF_BLUE_STRINGSET_KHMR = 137,
AF_BLUE_STRINGSET_KHMS = 143,
AF_BLUE_STRINGSET_LAO = 146,
AF_BLUE_STRINGSET_LATN = 152,
AF_BLUE_STRINGSET_LATB = 159,
AF_BLUE_STRINGSET_LATP = 166,
AF_BLUE_STRINGSET_LISU = 173,
AF_BLUE_STRINGSET_MLYM = 176,
AF_BLUE_STRINGSET_MEDF = 179,
AF_BLUE_STRINGSET_MONG = 187,
AF_BLUE_STRINGSET_MYMR = 190,
AF_BLUE_STRINGSET_NKOO = 195,
AF_BLUE_STRINGSET_NONE = 200,
AF_BLUE_STRINGSET_OLCK = 201,
AF_BLUE_STRINGSET_ORKH = 204,
AF_BLUE_STRINGSET_OSGE = 207,
AF_BLUE_STRINGSET_OSMA = 215,
AF_BLUE_STRINGSET_ROHG = 218,
AF_BLUE_STRINGSET_SAUR = 222,
AF_BLUE_STRINGSET_SHAW = 225,
AF_BLUE_STRINGSET_SINH = 231,
AF_BLUE_STRINGSET_SUND = 235,
AF_BLUE_STRINGSET_TAML = 239,
AF_BLUE_STRINGSET_TAVT = 242,
AF_BLUE_STRINGSET_TELU = 245,
AF_BLUE_STRINGSET_THAI = 248,
AF_BLUE_STRINGSET_TFNG = 256,
AF_BLUE_STRINGSET_VAII = 259,
af_blue_2_1 = 262,
#ifdef AF_CONFIG_OPTION_CJK
AF_BLUE_STRINGSET_HANI = af_blue_2_1 + 0,
af_blue_2_1_1 = af_blue_2_1 + 2,
#ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
af_blue_2_1_2 = af_blue_2_1_1 + 2,
#else
af_blue_2_1_2 = af_blue_2_1_1 + 0,
#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
af_blue_2_2 = af_blue_2_1_2 + 1,
#else
af_blue_2_2 = af_blue_2_1 + 0,
#endif /* AF_CONFIG_OPTION_CJK */
AF_BLUE_STRINGSET_MAX /* do not remove */
} AF_Blue_Stringset;
typedef struct AF_Blue_StringRec_
{
AF_Blue_String string;
FT_UShort properties;
} AF_Blue_StringRec;
FT_LOCAL_ARRAY( AF_Blue_StringRec )
af_blue_stringsets[];
/* */
FT_END_HEADER
#endif /* AFBLUE_H_ */
/* END */

View File

@@ -0,0 +1,146 @@
/****************************************************************************
*
* afblue.h
*
* Auto-fitter data for blue strings (specification).
*
* Copyright (C) 2013-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#ifndef AFBLUE_H_
#define AFBLUE_H_
FT_BEGIN_HEADER
/* an auxiliary macro to decode a UTF-8 character -- since we only use */
/* hard-coded, self-converted data, no error checking is performed */
#define GET_UTF8_CHAR( ch, p ) \
do \
{ \
ch = (unsigned char)*p++; \
if ( ch >= 0x80 ) \
{ \
FT_UInt len_; \
\
\
if ( ch < 0xE0 ) \
{ \
len_ = 1; \
ch &= 0x1F; \
} \
else if ( ch < 0xF0 ) \
{ \
len_ = 2; \
ch &= 0x0F; \
} \
else \
{ \
len_ = 3; \
ch &= 0x07; \
} \
\
for ( ; len_ > 0; len_-- ) \
ch = ( ch << 6 ) | ( *p++ & 0x3F ); \
} \
} while ( 0 )
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** B L U E S T R I N G S *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* At the bottommost level, we define strings for finding blue zones. */
#define AF_BLUE_STRING_MAX_LEN @AF_BLUE_STRING_MAX_LEN@
/* The AF_Blue_String enumeration values are offsets into the */
/* `af_blue_strings' array. */
typedef enum AF_Blue_String_
{
@AF_BLUE_STRING_ENUM@
AF_BLUE_STRING_MAX /* do not remove */
} AF_Blue_String;
FT_LOCAL_ARRAY( char )
af_blue_strings[];
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** B L U E S T R I N G S E T S *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* The next level is to group blue strings into style-specific sets. */
/* Properties are specific to a writing system. We assume that a given */
/* blue string can't be used in more than a single writing system, which */
/* is a safe bet. */
#define AF_BLUE_PROPERTY_LATIN_TOP ( 1U << 0 ) /* must have value 1 */
#define AF_BLUE_PROPERTY_LATIN_SUB_TOP ( 1U << 1 )
#define AF_BLUE_PROPERTY_LATIN_NEUTRAL ( 1U << 2 )
#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1U << 3 )
#define AF_BLUE_PROPERTY_LATIN_LONG ( 1U << 4 )
#define AF_BLUE_PROPERTY_CJK_TOP ( 1U << 0 ) /* must have value 1 */
#define AF_BLUE_PROPERTY_CJK_HORIZ ( 1U << 1 ) /* must have value 2 */
#define AF_BLUE_PROPERTY_CJK_RIGHT AF_BLUE_PROPERTY_CJK_TOP
#define AF_BLUE_STRINGSET_MAX_LEN @AF_BLUE_STRINGSET_MAX_LEN@
/* The AF_Blue_Stringset enumeration values are offsets into the */
/* `af_blue_stringsets' array. */
typedef enum AF_Blue_Stringset_
{
@AF_BLUE_STRINGSET_ENUM@
AF_BLUE_STRINGSET_MAX /* do not remove */
} AF_Blue_Stringset;
typedef struct AF_Blue_StringRec_
{
AF_Blue_String string;
FT_UShort properties;
} AF_Blue_StringRec;
FT_LOCAL_ARRAY( AF_Blue_StringRec )
af_blue_stringsets[];
/* */
FT_END_HEADER
#endif /* AFBLUE_H_ */
/* END */

2383
thirdparty/freetype/src/autofit/afcjk.c vendored Normal file

File diff suppressed because it is too large Load Diff

141
thirdparty/freetype/src/autofit/afcjk.h vendored Normal file
View File

@@ -0,0 +1,141 @@
/****************************************************************************
*
* afcjk.h
*
* Auto-fitter hinting routines for CJK writing system (specification).
*
* Copyright (C) 2006-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#ifndef AFCJK_H_
#define AFCJK_H_
#include "afhints.h"
#include "aflatin.h"
FT_BEGIN_HEADER
/* the CJK-specific writing system */
AF_DECLARE_WRITING_SYSTEM_CLASS( af_cjk_writing_system_class )
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** C J K G L O B A L M E T R I C S *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*
* CJK glyphs tend to fill the square. So we have both vertical and
* horizontal blue zones. But some glyphs have flat bounding strokes that
* leave some space between neighbour glyphs.
*/
#define AF_CJK_IS_TOP_BLUE( b ) \
( (b)->properties & AF_BLUE_PROPERTY_CJK_TOP )
#define AF_CJK_IS_HORIZ_BLUE( b ) \
( (b)->properties & AF_BLUE_PROPERTY_CJK_HORIZ )
#define AF_CJK_IS_RIGHT_BLUE AF_CJK_IS_TOP_BLUE
#define AF_CJK_MAX_WIDTHS 16
#define AF_CJK_BLUE_ACTIVE ( 1U << 0 ) /* zone height is <= 3/4px */
#define AF_CJK_BLUE_TOP ( 1U << 1 ) /* result of AF_CJK_IS_TOP_BLUE */
#define AF_CJK_BLUE_ADJUSTMENT ( 1U << 2 ) /* used for scale adjustment */
/* optimization */
typedef struct AF_CJKBlueRec_
{
AF_WidthRec ref;
AF_WidthRec shoot; /* undershoot */
FT_UInt flags;
} AF_CJKBlueRec, *AF_CJKBlue;
typedef struct AF_CJKAxisRec_
{
FT_Fixed scale;
FT_Pos delta;
FT_UInt width_count; /* number of used widths */
AF_WidthRec widths[AF_CJK_MAX_WIDTHS]; /* widths array */
FT_Pos edge_distance_threshold; /* used for creating edges */
FT_Pos standard_width; /* the default stem thickness */
FT_Bool extra_light; /* is standard width very light? */
/* used for horizontal metrics too for CJK */
FT_Bool control_overshoot;
FT_UInt blue_count;
AF_CJKBlueRec blues[AF_BLUE_STRINGSET_MAX_LEN];
FT_Fixed org_scale;
FT_Pos org_delta;
} AF_CJKAxisRec, *AF_CJKAxis;
typedef struct AF_CJKMetricsRec_
{
AF_StyleMetricsRec root;
FT_UInt units_per_em;
AF_CJKAxisRec axis[AF_DIMENSION_MAX];
} AF_CJKMetricsRec, *AF_CJKMetrics;
#ifdef AF_CONFIG_OPTION_CJK
FT_LOCAL( FT_Error )
af_cjk_metrics_init( AF_StyleMetrics metrics,
FT_Face face );
FT_LOCAL( void )
af_cjk_metrics_scale( AF_StyleMetrics metrics,
AF_Scaler scaler );
FT_LOCAL( FT_Error )
af_cjk_hints_init( AF_GlyphHints hints,
AF_StyleMetrics metrics );
FT_LOCAL( FT_Error )
af_cjk_hints_apply( FT_UInt glyph_index,
AF_GlyphHints hints,
FT_Outline* outline,
AF_StyleMetrics metrics );
/* shared; called from afindic.c */
FT_LOCAL( void )
af_cjk_metrics_check_digits( AF_CJKMetrics metrics,
FT_Face face );
FT_LOCAL( void )
af_cjk_metrics_init_widths( AF_CJKMetrics metrics,
FT_Face face );
#endif /* AF_CONFIG_OPTION_CJK */
/* */
FT_END_HEADER
#endif /* AFCJK_H_ */
/* END */

View File

@@ -0,0 +1,105 @@
/****************************************************************************
*
* afcover.h
*
* Auto-fitter coverages (specification only).
*
* Copyright (C) 2013-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
/* This header file can be included multiple times. */
/* Define `COVERAGE' as needed. */
/* Add new coverages here. The first and second arguments are the */
/* coverage name in lowercase and uppercase, respectively, followed */
/* by a description string. The last four arguments are the four */
/* characters defining the corresponding OpenType feature. */
#if 0
/* XXX: It's not possible to define blue zone characters in advance. */
COVERAGE( alternative_fractions, ALTERNATIVE_FRACTIONS,
"alternative fractions",
'a', 'f', 'r', 'c' )
#endif
COVERAGE( petite_capitals_from_capitals, PETITE_CAPITALS_FROM_CAPITALS,
"petite capitals from capitals",
'c', '2', 'c', 'p' )
COVERAGE( small_capitals_from_capitals, SMALL_CAPITALS_FROM_CAPITALS,
"small capitals from capitals",
'c', '2', 's', 'c' )
#if 0
/* XXX: Only digits are in this coverage, however, both normal style */
/* and oldstyle representation forms are possible. */
COVERAGE( denominators, DENOMINATORS,
"denominators",
'd', 'n', 'o', 'm' )
#endif
#if 0
/* XXX: It's not possible to define blue zone characters in advance. */
COVERAGE( fractions, FRACTIONS,
"fractions",
'f', 'r', 'a', 'c' )
#endif
#if 0
/* XXX: Only digits are in this coverage, however, both normal style */
/* and oldstyle representation forms are possible. */
COVERAGE( numerators, NUMERATORS,
"numerators",
'n', 'u', 'm', 'r' )
#endif
COVERAGE( ordinals, ORDINALS,
"ordinals",
'o', 'r', 'd', 'n' )
COVERAGE( petite_capitals, PETITE_CAPITALS,
"petite capitals",
'p', 'c', 'a', 'p' )
COVERAGE( ruby, RUBY,
"ruby",
'r', 'u', 'b', 'y' )
COVERAGE( scientific_inferiors, SCIENTIFIC_INFERIORS,
"scientific inferiors",
's', 'i', 'n', 'f' )
COVERAGE( small_capitals, SMALL_CAPITALS,
"small capitals",
's', 'm', 'c', 'p' )
COVERAGE( subscript, SUBSCRIPT,
"subscript",
's', 'u', 'b', 's' )
COVERAGE( superscript, SUPERSCRIPT,
"superscript",
's', 'u', 'p', 's' )
COVERAGE( titling, TITLING,
"titling",
't', 'i', 't', 'l' )
#if 0
/* to be always excluded */
COVERAGE(nalt, 'n', 'a', 'l', 't'); /* Alternate Annotation Forms (?) */
COVERAGE(ornm, 'o', 'r', 'n', 'm'); /* Ornaments (?) */
#endif
/* END */

View File

@@ -0,0 +1,77 @@
/****************************************************************************
*
* afdummy.c
*
* Auto-fitter dummy routines to be used if no hinting should be
* performed (body).
*
* Copyright (C) 2003-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include "afdummy.h"
#include "afhints.h"
#include "aferrors.h"
static FT_Error
af_dummy_hints_init( AF_GlyphHints hints,
AF_StyleMetrics metrics )
{
af_glyph_hints_rescale( hints, metrics );
hints->x_scale = metrics->scaler.x_scale;
hints->y_scale = metrics->scaler.y_scale;
hints->x_delta = metrics->scaler.x_delta;
hints->y_delta = metrics->scaler.y_delta;
return FT_Err_Ok;
}
static FT_Error
af_dummy_hints_apply( FT_UInt glyph_index,
AF_GlyphHints hints,
FT_Outline* outline,
AF_StyleMetrics metrics )
{
FT_Error error;
FT_UNUSED( glyph_index );
FT_UNUSED( metrics );
error = af_glyph_hints_reload( hints, outline );
if ( !error )
af_glyph_hints_save( hints, outline );
return error;
}
AF_DEFINE_WRITING_SYSTEM_CLASS(
af_dummy_writing_system_class,
AF_WRITING_SYSTEM_DUMMY,
sizeof ( AF_StyleMetricsRec ),
(AF_WritingSystem_InitMetricsFunc) NULL, /* style_metrics_init */
(AF_WritingSystem_ScaleMetricsFunc)NULL, /* style_metrics_scale */
(AF_WritingSystem_DoneMetricsFunc) NULL, /* style_metrics_done */
(AF_WritingSystem_GetStdWidthsFunc)NULL, /* style_metrics_getstdw */
(AF_WritingSystem_InitHintsFunc) af_dummy_hints_init, /* style_hints_init */
(AF_WritingSystem_ApplyHintsFunc) af_dummy_hints_apply /* style_hints_apply */
)
/* END */

View File

@@ -0,0 +1,40 @@
/****************************************************************************
*
* afdummy.h
*
* Auto-fitter dummy routines to be used if no hinting should be
* performed (specification).
*
* Copyright (C) 2003-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#ifndef AFDUMMY_H_
#define AFDUMMY_H_
#include "aftypes.h"
FT_BEGIN_HEADER
/* A dummy writing system used when no hinting should be performed. */
AF_DECLARE_WRITING_SYSTEM_CLASS( af_dummy_writing_system_class )
/* */
FT_END_HEADER
#endif /* AFDUMMY_H_ */
/* END */

View File

@@ -0,0 +1,42 @@
/****************************************************************************
*
* aferrors.h
*
* Autofitter error codes (specification only).
*
* Copyright (C) 2005-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
/**************************************************************************
*
* This file is used to define the Autofitter error enumeration
* constants.
*
*/
#ifndef AFERRORS_H_
#define AFERRORS_H_
#include <freetype/ftmoderr.h>
#undef FTERRORS_H_
#undef FT_ERR_PREFIX
#define FT_ERR_PREFIX AF_Err_
#define FT_ERR_BASE FT_Mod_Err_Autofit
#include <freetype/fterrors.h>
#endif /* AFERRORS_H_ */
/* END */

View File

@@ -0,0 +1,513 @@
/****************************************************************************
*
* afglobal.c
*
* Auto-fitter routines to compute global hinting values (body).
*
* Copyright (C) 2003-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include "afglobal.h"
#include "afranges.h"
#include "afshaper.h"
#include "afws-decl.h"
#include <freetype/internal/ftdebug.h>
/**************************************************************************
*
* The macro FT_COMPONENT is used in trace mode. It is an implicit
* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
* messages during execution.
*/
#undef FT_COMPONENT
#define FT_COMPONENT afglobal
#include "aferrors.h"
#undef SCRIPT
#define SCRIPT( s, S, d, h, H, ss ) \
AF_DEFINE_SCRIPT_CLASS( \
af_ ## s ## _script_class, \
AF_SCRIPT_ ## S, \
af_ ## s ## _uniranges, \
af_ ## s ## _nonbase_uniranges, \
AF_ ## H, \
ss )
#include "afscript.h"
#undef STYLE
#define STYLE( s, S, d, ws, sc, ss, c ) \
AF_DEFINE_STYLE_CLASS( \
af_ ## s ## _style_class, \
AF_STYLE_ ## S, \
ws, \
sc, \
ss, \
c )
#include "afstyles.h"
#undef WRITING_SYSTEM
#define WRITING_SYSTEM( ws, WS ) \
&af_ ## ws ## _writing_system_class,
FT_LOCAL_ARRAY_DEF( AF_WritingSystemClass )
af_writing_system_classes[] =
{
#include "afws-iter.h"
NULL /* do not remove */
};
#undef SCRIPT
#define SCRIPT( s, S, d, h, H, ss ) \
&af_ ## s ## _script_class,
FT_LOCAL_ARRAY_DEF( AF_ScriptClass )
af_script_classes[] =
{
#include "afscript.h"
NULL /* do not remove */
};
#undef STYLE
#define STYLE( s, S, d, ws, sc, ss, c ) \
&af_ ## s ## _style_class,
FT_LOCAL_ARRAY_DEF( AF_StyleClass )
af_style_classes[] =
{
#include "afstyles.h"
NULL /* do not remove */
};
#ifdef FT_DEBUG_LEVEL_TRACE
#undef STYLE
#define STYLE( s, S, d, ws, sc, ss, c ) #s,
FT_LOCAL_ARRAY_DEF( char* )
af_style_names[] =
{
#include "afstyles.h"
};
#endif /* FT_DEBUG_LEVEL_TRACE */
/* Compute the style index of each glyph within a given face. */
static FT_Error
af_face_globals_compute_style_coverage( AF_FaceGlobals globals )
{
FT_Error error;
FT_Face face = globals->face;
FT_CharMap old_charmap = face->charmap;
FT_UShort* gstyles = globals->glyph_styles;
FT_UShort ss;
FT_UShort dflt = 0xFFFFU; /* a non-valid value */
FT_UInt i;
/* the value AF_STYLE_UNASSIGNED means `uncovered glyph' */
for ( i = 0; i < globals->glyph_count; i++ )
gstyles[i] = AF_STYLE_UNASSIGNED;
error = FT_Select_Charmap( face, FT_ENCODING_UNICODE );
if ( error )
{
/*
* Ignore this error; we simply use the fallback style.
* XXX: Shouldn't we rather disable hinting?
*/
error = FT_Err_Ok;
goto Exit;
}
/* scan each style in a Unicode charmap */
for ( ss = 0; af_style_classes[ss]; ss++ )
{
AF_StyleClass style_class =
af_style_classes[ss];
AF_ScriptClass script_class =
af_script_classes[style_class->script];
AF_Script_UniRange range;
if ( !script_class->script_uni_ranges )
continue;
/*
* Scan all Unicode points in the range and set the corresponding
* glyph style index.
*/
if ( style_class->coverage == AF_COVERAGE_DEFAULT )
{
if ( style_class->script == globals->module->default_script )
dflt = ss;
for ( range = script_class->script_uni_ranges;
range->first != 0;
range++ )
{
FT_ULong charcode = range->first;
FT_UInt gindex;
gindex = FT_Get_Char_Index( face, charcode );
if ( gindex != 0 &&
gindex < globals->glyph_count &&
( gstyles[gindex] & AF_STYLE_MASK ) == AF_STYLE_UNASSIGNED )
gstyles[gindex] = ss;
for (;;)
{
charcode = FT_Get_Next_Char( face, charcode, &gindex );
if ( gindex == 0 || charcode > range->last )
break;
if ( gindex < globals->glyph_count &&
( gstyles[gindex] & AF_STYLE_MASK ) == AF_STYLE_UNASSIGNED )
gstyles[gindex] = ss;
}
}
/* do the same for the script's non-base characters */
for ( range = script_class->script_uni_nonbase_ranges;
range->first != 0;
range++ )
{
FT_ULong charcode = range->first;
FT_UInt gindex;
gindex = FT_Get_Char_Index( face, charcode );
if ( gindex != 0 &&
gindex < globals->glyph_count &&
( gstyles[gindex] & AF_STYLE_MASK ) == ss )
gstyles[gindex] |= AF_NONBASE;
for (;;)
{
charcode = FT_Get_Next_Char( face, charcode, &gindex );
if ( gindex == 0 || charcode > range->last )
break;
if ( gindex < globals->glyph_count &&
( gstyles[gindex] & AF_STYLE_MASK ) == ss )
gstyles[gindex] |= AF_NONBASE;
}
}
}
else
{
/* get glyphs not directly addressable by cmap */
af_shaper_get_coverage( globals, style_class, gstyles, 0 );
}
}
/* handle the remaining default OpenType features ... */
for ( ss = 0; af_style_classes[ss]; ss++ )
{
AF_StyleClass style_class = af_style_classes[ss];
if ( style_class->coverage == AF_COVERAGE_DEFAULT )
af_shaper_get_coverage( globals, style_class, gstyles, 0 );
}
/* ... and finally the default OpenType features of the default script */
af_shaper_get_coverage( globals, af_style_classes[dflt], gstyles, 1 );
/* mark ASCII digits */
for ( i = 0x30; i <= 0x39; i++ )
{
FT_UInt gindex = FT_Get_Char_Index( face, i );
if ( gindex != 0 && gindex < globals->glyph_count )
gstyles[gindex] |= AF_DIGIT;
}
Exit:
/*
* By default, all uncovered glyphs are set to the fallback style.
* XXX: Shouldn't we disable hinting or do something similar?
*/
if ( globals->module->fallback_style != AF_STYLE_UNASSIGNED )
{
FT_UInt nn;
for ( nn = 0; nn < globals->glyph_count; nn++ )
{
if ( ( gstyles[nn] & AF_STYLE_MASK ) == AF_STYLE_UNASSIGNED )
{
gstyles[nn] &= ~AF_STYLE_MASK;
gstyles[nn] |= globals->module->fallback_style;
}
}
}
#ifdef FT_DEBUG_LEVEL_TRACE
FT_TRACE4(( "\n" ));
FT_TRACE4(( "style coverage\n" ));
FT_TRACE4(( "==============\n" ));
FT_TRACE4(( "\n" ));
for ( ss = 0; af_style_classes[ss]; ss++ )
{
AF_StyleClass style_class = af_style_classes[ss];
FT_UInt count = 0;
FT_UInt idx;
FT_TRACE4(( "%s:\n", af_style_names[style_class->style] ));
for ( idx = 0; idx < globals->glyph_count; idx++ )
{
if ( ( gstyles[idx] & AF_STYLE_MASK ) == style_class->style )
{
if ( !( count % 10 ) )
FT_TRACE4(( " " ));
FT_TRACE4(( " %d", idx ));
count++;
if ( !( count % 10 ) )
FT_TRACE4(( "\n" ));
}
}
if ( !count )
FT_TRACE4(( " (none)\n" ));
if ( count % 10 )
FT_TRACE4(( "\n" ));
}
#endif /* FT_DEBUG_LEVEL_TRACE */
face->charmap = old_charmap;
return error;
}
FT_LOCAL_DEF( FT_Error )
af_face_globals_new( FT_Face face,
AF_FaceGlobals *aglobals,
AF_Module module )
{
FT_Error error;
FT_Memory memory;
AF_FaceGlobals globals = NULL;
memory = face->memory;
/* we allocate an AF_FaceGlobals structure together */
/* with the glyph_styles array */
if ( FT_QALLOC( globals,
sizeof ( *globals ) +
(FT_ULong)face->num_glyphs * sizeof ( FT_UShort ) ) )
goto Exit;
FT_ZERO( &globals->metrics );
globals->face = face;
globals->glyph_count = (FT_UInt)face->num_glyphs;
/* right after the globals structure come the glyph styles */
globals->glyph_styles = (FT_UShort*)( globals + 1 );
globals->module = module;
globals->stem_darkening_for_ppem = 0;
globals->darken_x = 0;
globals->darken_y = 0;
globals->standard_vertical_width = 0;
globals->standard_horizontal_width = 0;
globals->scale_down_factor = 0;
#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
globals->hb_font = hb_ft_font_create_( face, NULL );
globals->hb_buf = hb_buffer_create();
#endif
error = af_face_globals_compute_style_coverage( globals );
if ( error )
{
af_face_globals_free( globals );
globals = NULL;
}
else
globals->increase_x_height = AF_PROP_INCREASE_X_HEIGHT_MAX;
Exit:
*aglobals = globals;
return error;
}
FT_LOCAL_DEF( void )
af_face_globals_free( void* globals_ )
{
AF_FaceGlobals globals = (AF_FaceGlobals)globals_;
if ( globals )
{
FT_Memory memory = globals->face->memory;
FT_UInt nn;
for ( nn = 0; nn < AF_STYLE_MAX; nn++ )
{
if ( globals->metrics[nn] )
{
AF_StyleClass style_class =
af_style_classes[nn];
AF_WritingSystemClass writing_system_class =
af_writing_system_classes[style_class->writing_system];
if ( writing_system_class->style_metrics_done )
writing_system_class->style_metrics_done( globals->metrics[nn] );
FT_FREE( globals->metrics[nn] );
}
}
#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
hb_font_destroy( globals->hb_font );
hb_buffer_destroy( globals->hb_buf );
#endif
/* no need to free `globals->glyph_styles'; */
/* it is part of the `globals' array */
FT_FREE( globals );
}
}
FT_LOCAL_DEF( FT_Error )
af_face_globals_get_metrics( AF_FaceGlobals globals,
FT_UInt gindex,
FT_UInt options,
AF_StyleMetrics *ametrics )
{
AF_StyleMetrics metrics = NULL;
AF_Style style = (AF_Style)options;
AF_WritingSystemClass writing_system_class;
AF_StyleClass style_class;
FT_Error error = FT_Err_Ok;
if ( gindex >= globals->glyph_count )
{
error = FT_THROW( Invalid_Argument );
goto Exit;
}
/* if we have a forced style (via `options'), use it, */
/* otherwise look into `glyph_styles' array */
if ( style == AF_STYLE_NONE_DFLT || style + 1 >= AF_STYLE_MAX )
style = (AF_Style)( globals->glyph_styles[gindex] &
AF_STYLE_UNASSIGNED );
Again:
style_class = af_style_classes[style];
writing_system_class = af_writing_system_classes
[style_class->writing_system];
metrics = globals->metrics[style];
if ( !metrics )
{
/* create the global metrics object if necessary */
FT_Memory memory = globals->face->memory;
if ( FT_ALLOC( metrics, writing_system_class->style_metrics_size ) )
goto Exit;
metrics->style_class = style_class;
metrics->globals = globals;
if ( writing_system_class->style_metrics_init )
{
error = writing_system_class->style_metrics_init( metrics,
globals->face );
if ( error )
{
if ( writing_system_class->style_metrics_done )
writing_system_class->style_metrics_done( metrics );
FT_FREE( metrics );
/* internal error code -1 indicates */
/* that no blue zones have been found */
if ( error == -1 )
{
style = (AF_Style)( globals->glyph_styles[gindex] &
AF_STYLE_UNASSIGNED );
/* IMPORTANT: Clear the error code, see
* https://gitlab.freedesktop.org/freetype/freetype/-/issues/1063
*/
error = FT_Err_Ok;
goto Again;
}
goto Exit;
}
}
globals->metrics[style] = metrics;
}
Exit:
*ametrics = metrics;
return error;
}
FT_LOCAL_DEF( FT_Bool )
af_face_globals_is_digit( AF_FaceGlobals globals,
FT_UInt gindex )
{
if ( gindex < globals->glyph_count )
return FT_BOOL( globals->glyph_styles[gindex] & AF_DIGIT );
return FT_BOOL( 0 );
}
/* END */

View File

@@ -0,0 +1,173 @@
/****************************************************************************
*
* afglobal.h
*
* Auto-fitter routines to compute global hinting values
* (specification).
*
* Copyright (C) 2003-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#ifndef AFGLOBAL_H_
#define AFGLOBAL_H_
#include "aftypes.h"
#include "afmodule.h"
#include "afshaper.h"
FT_BEGIN_HEADER
FT_LOCAL_ARRAY( AF_WritingSystemClass )
af_writing_system_classes[];
#undef SCRIPT
#define SCRIPT( s, S, d, h, H, ss ) \
AF_DECLARE_SCRIPT_CLASS( af_ ## s ## _script_class )
#include "afscript.h"
FT_LOCAL_ARRAY( AF_ScriptClass )
af_script_classes[];
#undef STYLE
#define STYLE( s, S, d, ws, sc, ss, c ) \
AF_DECLARE_STYLE_CLASS( af_ ## s ## _style_class )
#include "afstyles.h"
FT_LOCAL_ARRAY( AF_StyleClass )
af_style_classes[];
#ifdef FT_DEBUG_LEVEL_TRACE
FT_LOCAL_ARRAY( char* )
af_style_names[];
#endif
/*
* Default values and flags for both autofitter globals (found in
* AF_ModuleRec) and face globals (in AF_FaceGlobalsRec).
*/
/* index of fallback style in `af_style_classes' */
#ifdef AF_CONFIG_OPTION_CJK
#define AF_STYLE_FALLBACK AF_STYLE_HANI_DFLT
#else
#define AF_STYLE_FALLBACK AF_STYLE_NONE_DFLT
#endif
/* default script for OpenType; ignored if HarfBuzz isn't used */
#define AF_SCRIPT_DEFAULT AF_SCRIPT_LATN
/* a bit mask for AF_DIGIT and AF_NONBASE */
#define AF_STYLE_MASK 0x3FFF
/* an uncovered glyph */
#define AF_STYLE_UNASSIGNED AF_STYLE_MASK
/* if this flag is set, we have an ASCII digit */
#define AF_DIGIT 0x8000U
/* if this flag is set, we have a non-base character */
#define AF_NONBASE 0x4000U
/* `increase-x-height' property */
#define AF_PROP_INCREASE_X_HEIGHT_MIN 6
#define AF_PROP_INCREASE_X_HEIGHT_MAX 0
/************************************************************************/
/************************************************************************/
/***** *****/
/***** F A C E G L O B A L S *****/
/***** *****/
/************************************************************************/
/************************************************************************/
/*
* Note that glyph_styles[] maps each glyph to an index into the
* `af_style_classes' array.
*
*/
typedef struct AF_FaceGlobalsRec_
{
FT_Face face;
FT_UInt glyph_count; /* unsigned face->num_glyphs */
FT_UShort* glyph_styles;
#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
hb_font_t* hb_font;
hb_buffer_t* hb_buf; /* for feature comparison */
#endif
/* per-face auto-hinter properties */
FT_UInt increase_x_height;
AF_StyleMetrics metrics[AF_STYLE_MAX];
/* Compute darkening amount once per size. Use this to check whether */
/* darken_{x,y} needs to be recomputed. */
FT_UShort stem_darkening_for_ppem;
/* Copy from e.g. AF_LatinMetrics.axis[AF_DIMENSION_HORZ] */
/* to compute the darkening amount. */
FT_Pos standard_vertical_width;
/* Copy from e.g. AF_LatinMetrics.axis[AF_DIMENSION_VERT] */
/* to compute the darkening amount. */
FT_Pos standard_horizontal_width;
/* The actual amount to darken a glyph along the X axis. */
FT_Pos darken_x;
/* The actual amount to darken a glyph along the Y axis. */
FT_Pos darken_y;
/* Amount to scale down by to keep emboldened points */
/* on the Y-axis in pre-computed blue zones. */
FT_Fixed scale_down_factor;
AF_Module module; /* to access global properties */
} AF_FaceGlobalsRec;
/*
* model the global hints data for a given face, decomposed into
* style-specific items
*/
FT_LOCAL( FT_Error )
af_face_globals_new( FT_Face face,
AF_FaceGlobals *aglobals,
AF_Module module );
FT_LOCAL( FT_Error )
af_face_globals_get_metrics( AF_FaceGlobals globals,
FT_UInt gindex,
FT_UInt options,
AF_StyleMetrics *ametrics );
FT_LOCAL( void )
af_face_globals_free( void* globals );
FT_LOCAL( FT_Bool )
af_face_globals_is_digit( AF_FaceGlobals globals,
FT_UInt gindex );
/* */
FT_END_HEADER
#endif /* AFGLOBAL_H_ */
/* END */

1796
thirdparty/freetype/src/autofit/afhints.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,467 @@
/****************************************************************************
*
* afhints.h
*
* Auto-fitter hinting routines (specification).
*
* Copyright (C) 2003-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#ifndef AFHINTS_H_
#define AFHINTS_H_
#include "aftypes.h"
FT_BEGIN_HEADER
/*
* The definition of outline glyph hints. These are shared by all
* writing system analysis routines (until now).
*/
typedef enum AF_Dimension_
{
AF_DIMENSION_HORZ = 0, /* x coordinates, */
/* i.e., vertical segments & edges */
AF_DIMENSION_VERT = 1, /* y coordinates, */
/* i.e., horizontal segments & edges */
AF_DIMENSION_MAX /* do not remove */
} AF_Dimension;
/* hint directions -- the values are computed so that two vectors are */
/* in opposite directions iff `dir1 + dir2 == 0' */
typedef enum AF_Direction_
{
AF_DIR_NONE = 4,
AF_DIR_RIGHT = 1,
AF_DIR_LEFT = -1,
AF_DIR_UP = 2,
AF_DIR_DOWN = -2
} AF_Direction;
/*
* The following explanations are mostly taken from the article
*
* Real-Time Grid Fitting of Typographic Outlines
*
* by David Turner and Werner Lemberg
*
* https://www.tug.org/TUGboat/Articles/tb24-3/lemberg.pdf
*
* with appropriate updates.
*
*
* Segments
*
* `af_{cjk,latin,...}_hints_compute_segments' are the functions to
* find segments in an outline.
*
* A segment is a series of at least two consecutive points that are
* approximately aligned along a coordinate axis. The analysis to do
* so is specific to a writing system.
*
*
* Edges
*
* `af_{cjk,latin,...}_hints_compute_edges' are the functions to find
* edges.
*
* As soon as segments are defined, the auto-hinter groups them into
* edges. An edge corresponds to a single position on the main
* dimension that collects one or more segments (allowing for a small
* threshold).
*
* As an example, the `latin' writing system first tries to grid-fit
* edges, then to align segments on the edges unless it detects that
* they form a serif.
*
*
* A H
* | |
* | |
* | |
* | |
* C | | F
* +------<-----+ +-----<------+
* | B G |
* | |
* | |
* +--------------->------------------+
* D E
*
*
* Stems
*
* Stems are detected by `af_{cjk,latin,...}_hint_edges'.
*
* Segments need to be `linked' to other ones in order to detect stems.
* A stem is made of two segments that face each other in opposite
* directions and that are sufficiently close to each other. Using
* vocabulary from the TrueType specification, stem segments form a
* `black distance'.
*
* In the above ASCII drawing, the horizontal segments are BC, DE, and
* FG; the vertical segments are AB, CD, EF, and GH.
*
* Each segment has at most one `best' candidate to form a black
* distance, or no candidate at all. Notice that two distinct segments
* can have the same candidate, which frequently means a serif.
*
* A stem is recognized by the following condition:
*
* best segment_1 = segment_2 && best segment_2 = segment_1
*
* The best candidate is stored in field `link' in structure
* `AF_Segment'.
*
* In the above ASCII drawing, the best candidate for both AB and CD is
* GH, while the best candidate for GH is AB. Similarly, the best
* candidate for EF and GH is AB, while the best candidate for AB is
* GH.
*
* The detection and handling of stems is dependent on the writing
* system.
*
*
* Serifs
*
* Serifs are detected by `af_{cjk,latin,...}_hint_edges'.
*
* In comparison to a stem, a serif (as handled by the auto-hinter
* module that takes care of the `latin' writing system) has
*
* best segment_1 = segment_2 && best segment_2 != segment_1
*
* where segment_1 corresponds to the serif segment (CD and EF in the
* above ASCII drawing).
*
* The best candidate is stored in field `serif' in structure
* `AF_Segment' (and `link' is set to NULL).
*
*
* Touched points
*
* A point is called `touched' if it has been processed somehow by the
* auto-hinter. It basically means that it shouldn't be moved again
* (or moved only under certain constraints to preserve the already
* applied processing).
*
*
* Flat and round segments
*
* Segments are `round' or `flat', depending on the series of points
* that define them. A segment is round if the next and previous point
* of an extremum (which can be either a single point or sequence of
* points) are both conic or cubic control points. Otherwise, a
* segment with an extremum is flat.
*
*
* Strong Points
*
* Experience has shown that points not part of an edge need to be
* interpolated linearly between their two closest edges, even if these
* are not part of the contour of those particular points. Typical
* candidates for this are
*
* - angle points (i.e., points where the `in' and `out' direction
* differ greatly)
*
* - inflection points (i.e., where the `in' and `out' angles are the
* same, but the curvature changes sign) [currently, such points
* aren't handled specially in the auto-hinter]
*
* `af_glyph_hints_align_strong_points' is the function that takes
* care of such situations; it is equivalent to the TrueType `IP'
* hinting instruction.
*
*
* Weak Points
*
* Other points in the outline must be interpolated using the
* coordinates of their previous and next unfitted contour neighbours.
* These are called `weak points' and are touched by the function
* `af_glyph_hints_align_weak_points', equivalent to the TrueType `IUP'
* hinting instruction. Typical candidates are control points and
* points on the contour without a major direction.
*
* The major effect is to reduce possible distortion caused by
* alignment of edges and strong points, thus weak points are processed
* after strong points.
*/
/* point hint flags */
#define AF_FLAG_NONE 0
/* point type flags */
#define AF_FLAG_CONIC ( 1U << 0 )
#define AF_FLAG_CUBIC ( 1U << 1 )
#define AF_FLAG_CONTROL ( AF_FLAG_CONIC | AF_FLAG_CUBIC )
/* point touch flags */
#define AF_FLAG_TOUCH_X ( 1U << 2 )
#define AF_FLAG_TOUCH_Y ( 1U << 3 )
/* candidates for weak interpolation have this flag set */
#define AF_FLAG_WEAK_INTERPOLATION ( 1U << 4 )
/* the distance to the next point is very small */
#define AF_FLAG_NEAR ( 1U << 5 )
/* edge hint flags */
#define AF_EDGE_NORMAL 0
#define AF_EDGE_ROUND ( 1U << 0 )
#define AF_EDGE_SERIF ( 1U << 1 )
#define AF_EDGE_DONE ( 1U << 2 )
#define AF_EDGE_NEUTRAL ( 1U << 3 ) /* edge aligns to a neutral blue zone */
typedef struct AF_PointRec_* AF_Point;
typedef struct AF_SegmentRec_* AF_Segment;
typedef struct AF_EdgeRec_* AF_Edge;
typedef struct AF_PointRec_
{
FT_UShort flags; /* point flags used by hinter */
FT_Char in_dir; /* direction of inwards vector */
FT_Char out_dir; /* direction of outwards vector */
FT_Pos ox, oy; /* original, scaled position */
FT_Short fx, fy; /* original, unscaled position (in font units) */
FT_Pos x, y; /* current position */
FT_Pos u, v; /* current (x,y) or (y,x) depending on context */
AF_Point next; /* next point in contour */
AF_Point prev; /* previous point in contour */
#ifdef FT_DEBUG_AUTOFIT
/* track `before' and `after' edges for strong points */
AF_Edge before[2];
AF_Edge after[2];
#endif
} AF_PointRec;
typedef struct AF_SegmentRec_
{
FT_Byte flags; /* edge/segment flags for this segment */
FT_Char dir; /* segment direction */
FT_Short pos; /* position of segment */
FT_Short delta; /* deviation from segment position */
FT_Short min_coord; /* minimum coordinate of segment */
FT_Short max_coord; /* maximum coordinate of segment */
FT_Short height; /* the hinted segment height */
AF_Edge edge; /* the segment's parent edge */
AF_Segment edge_next; /* link to next segment in parent edge */
AF_Segment link; /* (stem) link segment */
AF_Segment serif; /* primary segment for serifs */
FT_Pos score; /* used during stem matching */
FT_Pos len; /* used during stem matching */
AF_Point first; /* first point in edge segment */
AF_Point last; /* last point in edge segment */
} AF_SegmentRec;
typedef struct AF_EdgeRec_
{
FT_Short fpos; /* original, unscaled position (in font units) */
FT_Pos opos; /* original, scaled position */
FT_Pos pos; /* current position */
FT_Byte flags; /* edge flags */
FT_Char dir; /* edge direction */
FT_Fixed scale; /* used to speed up interpolation between edges */
AF_Width blue_edge; /* non-NULL if this is a blue edge */
AF_Edge link; /* link edge */
AF_Edge serif; /* primary edge for serifs */
FT_Int score; /* used during stem matching */
AF_Segment first; /* first segment in edge */
AF_Segment last; /* last segment in edge */
} AF_EdgeRec;
#define AF_SEGMENTS_EMBEDDED 18 /* number of embedded segments */
#define AF_EDGES_EMBEDDED 12 /* number of embedded edges */
typedef struct AF_AxisHintsRec_
{
FT_UInt num_segments; /* number of used segments */
FT_UInt max_segments; /* number of allocated segments */
AF_Segment segments; /* segments array */
FT_UInt num_edges; /* number of used edges */
FT_UInt max_edges; /* number of allocated edges */
AF_Edge edges; /* edges array */
AF_Direction major_dir; /* either vertical or horizontal */
/* two arrays to avoid allocation penalty */
struct
{
AF_SegmentRec segments[AF_SEGMENTS_EMBEDDED];
AF_EdgeRec edges[AF_EDGES_EMBEDDED];
} embedded;
} AF_AxisHintsRec, *AF_AxisHints;
#define AF_POINTS_EMBEDDED 96 /* number of embedded points */
#define AF_CONTOURS_EMBEDDED 8 /* number of embedded contours */
typedef struct AF_GlyphHintsRec_
{
FT_Memory memory;
FT_Fixed x_scale;
FT_Pos x_delta;
FT_Fixed y_scale;
FT_Pos y_delta;
FT_Int max_points; /* number of allocated points */
FT_Int num_points; /* number of used points */
AF_Point points; /* points array */
FT_Int max_contours; /* number of allocated contours */
FT_Int num_contours; /* number of used contours */
AF_Point* contours; /* contours array */
AF_AxisHintsRec axis[AF_DIMENSION_MAX];
FT_UInt32 scaler_flags; /* copy of scaler flags */
FT_UInt32 other_flags; /* free for style-specific */
/* implementations */
AF_StyleMetrics metrics;
/* Two arrays to avoid allocation penalty. */
/* The `embedded' structure must be the last element! */
struct
{
AF_Point contours[AF_CONTOURS_EMBEDDED];
AF_PointRec points[AF_POINTS_EMBEDDED];
} embedded;
} AF_GlyphHintsRec;
#define AF_HINTS_TEST_SCALER( h, f ) ( (h)->scaler_flags & (f) )
#define AF_HINTS_TEST_OTHER( h, f ) ( (h)->other_flags & (f) )
#ifdef FT_DEBUG_AUTOFIT
#define AF_HINTS_DO_HORIZONTAL( h ) \
( !af_debug_disable_horz_hints_ && \
!AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_HORIZONTAL ) )
#define AF_HINTS_DO_VERTICAL( h ) \
( !af_debug_disable_vert_hints_ && \
!AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_VERTICAL ) )
#define AF_HINTS_DO_BLUES( h ) ( !af_debug_disable_blue_hints_ )
#else /* !FT_DEBUG_AUTOFIT */
#define AF_HINTS_DO_HORIZONTAL( h ) \
!AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_HORIZONTAL )
#define AF_HINTS_DO_VERTICAL( h ) \
!AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_VERTICAL )
#define AF_HINTS_DO_BLUES( h ) 1
#endif /* !FT_DEBUG_AUTOFIT */
#define AF_HINTS_DO_ADVANCE( h ) \
!AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_ADVANCE )
FT_LOCAL( AF_Direction )
af_direction_compute( FT_Pos dx,
FT_Pos dy );
FT_LOCAL( FT_Error )
af_axis_hints_new_segment( AF_AxisHints axis,
FT_Memory memory,
AF_Segment *asegment );
FT_LOCAL( FT_Error)
af_axis_hints_new_edge( AF_AxisHints axis,
FT_Int fpos,
AF_Direction dir,
FT_Bool top_to_bottom_hinting,
FT_Memory memory,
AF_Edge *edge );
FT_LOCAL( void )
af_glyph_hints_init( AF_GlyphHints hints,
FT_Memory memory );
FT_LOCAL( void )
af_glyph_hints_rescale( AF_GlyphHints hints,
AF_StyleMetrics metrics );
FT_LOCAL( FT_Error )
af_glyph_hints_reload( AF_GlyphHints hints,
FT_Outline* outline );
FT_LOCAL( void )
af_glyph_hints_save( AF_GlyphHints hints,
FT_Outline* outline );
FT_LOCAL( void )
af_glyph_hints_align_edge_points( AF_GlyphHints hints,
AF_Dimension dim );
FT_LOCAL( void )
af_glyph_hints_align_strong_points( AF_GlyphHints hints,
AF_Dimension dim );
FT_LOCAL( void )
af_glyph_hints_align_weak_points( AF_GlyphHints hints,
AF_Dimension dim );
FT_LOCAL( void )
af_glyph_hints_done( AF_GlyphHints hints );
/* */
#define AF_SEGMENT_LEN( seg ) ( (seg)->max_coord - (seg)->min_coord )
#define AF_SEGMENT_DIST( seg1, seg2 ) ( ( (seg1)->pos > (seg2)->pos ) \
? (seg1)->pos - (seg2)->pos \
: (seg2)->pos - (seg1)->pos )
FT_END_HEADER
#endif /* AFHINTS_H_ */
/* END */

View File

@@ -0,0 +1,157 @@
/****************************************************************************
*
* afindic.c
*
* Auto-fitter hinting routines for Indic writing system (body).
*
* Copyright (C) 2007-2024 by
* Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include "aftypes.h"
#include "aflatin.h"
#include "afcjk.h"
#ifdef AF_CONFIG_OPTION_INDIC
#include "afindic.h"
#include "aferrors.h"
static FT_Error
af_indic_metrics_init( AF_StyleMetrics metrics_, /* AF_CJKMetrics */
FT_Face face )
{
AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_;
/* skip blue zone init in CJK routines */
FT_CharMap oldmap = face->charmap;
metrics->units_per_em = face->units_per_EM;
if ( FT_Select_Charmap( face, FT_ENCODING_UNICODE ) )
face->charmap = NULL;
else
{
af_cjk_metrics_init_widths( metrics, face );
#if 0
/* either need indic specific blue_chars[] or just skip blue zones */
af_cjk_metrics_init_blues( metrics, face, af_cjk_blue_chars );
#endif
af_cjk_metrics_check_digits( metrics, face );
}
face->charmap = oldmap;
return FT_Err_Ok;
}
static void
af_indic_metrics_scale( AF_StyleMetrics metrics,
AF_Scaler scaler )
{
/* use CJK routines */
af_cjk_metrics_scale( metrics, scaler );
}
static FT_Error
af_indic_hints_init( AF_GlyphHints hints,
AF_StyleMetrics metrics )
{
/* use CJK routines */
return af_cjk_hints_init( hints, metrics );
}
static FT_Error
af_indic_hints_apply( FT_UInt glyph_index,
AF_GlyphHints hints,
FT_Outline* outline,
AF_StyleMetrics metrics )
{
/* use CJK routines */
return af_cjk_hints_apply( glyph_index, hints, outline, metrics );
}
/* Extract standard_width from writing system/script specific */
/* metrics class. */
static void
af_indic_get_standard_widths( AF_StyleMetrics metrics_, /* AF_CJKMetrics */
FT_Pos* stdHW,
FT_Pos* stdVW )
{
AF_CJKMetrics metrics = (AF_CJKMetrics)metrics_;
if ( stdHW )
*stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width;
if ( stdVW )
*stdVW = metrics->axis[AF_DIMENSION_HORZ].standard_width;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** I N D I C S C R I P T C L A S S *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
AF_DEFINE_WRITING_SYSTEM_CLASS(
af_indic_writing_system_class,
AF_WRITING_SYSTEM_INDIC,
sizeof ( AF_CJKMetricsRec ),
(AF_WritingSystem_InitMetricsFunc) af_indic_metrics_init, /* style_metrics_init */
(AF_WritingSystem_ScaleMetricsFunc)af_indic_metrics_scale, /* style_metrics_scale */
(AF_WritingSystem_DoneMetricsFunc) NULL, /* style_metrics_done */
(AF_WritingSystem_GetStdWidthsFunc)af_indic_get_standard_widths, /* style_metrics_getstdw */
(AF_WritingSystem_InitHintsFunc) af_indic_hints_init, /* style_hints_init */
(AF_WritingSystem_ApplyHintsFunc) af_indic_hints_apply /* style_hints_apply */
)
#else /* !AF_CONFIG_OPTION_INDIC */
AF_DEFINE_WRITING_SYSTEM_CLASS(
af_indic_writing_system_class,
AF_WRITING_SYSTEM_INDIC,
sizeof ( AF_CJKMetricsRec ),
(AF_WritingSystem_InitMetricsFunc) NULL, /* style_metrics_init */
(AF_WritingSystem_ScaleMetricsFunc)NULL, /* style_metrics_scale */
(AF_WritingSystem_DoneMetricsFunc) NULL, /* style_metrics_done */
(AF_WritingSystem_GetStdWidthsFunc)NULL, /* style_metrics_getstdw */
(AF_WritingSystem_InitHintsFunc) NULL, /* style_hints_init */
(AF_WritingSystem_ApplyHintsFunc) NULL /* style_hints_apply */
)
#endif /* !AF_CONFIG_OPTION_INDIC */
/* END */

View File

@@ -0,0 +1,41 @@
/****************************************************************************
*
* afindic.h
*
* Auto-fitter hinting routines for Indic writing system
* (specification).
*
* Copyright (C) 2007-2024 by
* Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#ifndef AFINDIC_H_
#define AFINDIC_H_
#include "afhints.h"
FT_BEGIN_HEADER
/* the `indic' writing system */
AF_DECLARE_WRITING_SYSTEM_CLASS( af_indic_writing_system_class )
/* */
FT_END_HEADER
#endif /* AFINDIC_H_ */
/* END */

3643
thirdparty/freetype/src/autofit/aflatin.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,194 @@
/****************************************************************************
*
* aflatin.h
*
* Auto-fitter hinting routines for latin writing system
* (specification).
*
* Copyright (C) 2003-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#ifndef AFLATIN_H_
#define AFLATIN_H_
#include "afhints.h"
FT_BEGIN_HEADER
/* the `latin' writing system */
AF_DECLARE_WRITING_SYSTEM_CLASS( af_latin_writing_system_class )
/* constants are given with units_per_em == 2048 in mind */
#define AF_LATIN_CONSTANT( metrics, c ) \
( ( (c) * (FT_Long)( (AF_LatinMetrics)(metrics) )->units_per_em ) / 2048 )
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** L A T I N G L O B A L M E T R I C S *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*
* The following declarations could be embedded in the file `aflatin.c';
* they have been made semi-public to allow alternate writing system
* hinters to re-use some of them.
*/
#define AF_LATIN_IS_TOP_BLUE( b ) \
( (b)->properties & AF_BLUE_PROPERTY_LATIN_TOP )
#define AF_LATIN_IS_SUB_TOP_BLUE( b ) \
( (b)->properties & AF_BLUE_PROPERTY_LATIN_SUB_TOP )
#define AF_LATIN_IS_NEUTRAL_BLUE( b ) \
( (b)->properties & AF_BLUE_PROPERTY_LATIN_NEUTRAL )
#define AF_LATIN_IS_X_HEIGHT_BLUE( b ) \
( (b)->properties & AF_BLUE_PROPERTY_LATIN_X_HEIGHT )
#define AF_LATIN_IS_LONG_BLUE( b ) \
( (b)->properties & AF_BLUE_PROPERTY_LATIN_LONG )
#define AF_LATIN_MAX_WIDTHS 16
#define AF_LATIN_BLUE_ACTIVE ( 1U << 0 ) /* zone height is <= 3/4px */
#define AF_LATIN_BLUE_TOP ( 1U << 1 ) /* we have a top blue zone */
#define AF_LATIN_BLUE_SUB_TOP ( 1U << 2 ) /* we have a subscript top */
/* blue zone */
#define AF_LATIN_BLUE_NEUTRAL ( 1U << 3 ) /* we have neutral blue zone */
#define AF_LATIN_BLUE_ADJUSTMENT ( 1U << 4 ) /* used for scale adjustment */
/* optimization */
typedef struct AF_LatinBlueRec_
{
AF_WidthRec ref;
AF_WidthRec shoot;
FT_Pos ascender;
FT_Pos descender;
FT_UInt flags;
} AF_LatinBlueRec, *AF_LatinBlue;
typedef struct AF_LatinAxisRec_
{
FT_Fixed scale;
FT_Pos delta;
FT_UInt width_count; /* number of used widths */
AF_WidthRec widths[AF_LATIN_MAX_WIDTHS]; /* widths array */
FT_Pos edge_distance_threshold; /* used for creating edges */
FT_Pos standard_width; /* the default stem thickness */
FT_Bool extra_light; /* is standard width very light? */
/* ignored for horizontal metrics */
FT_UInt blue_count;
AF_LatinBlueRec blues[AF_BLUE_STRINGSET_MAX_LEN];
FT_Fixed org_scale;
FT_Pos org_delta;
} AF_LatinAxisRec, *AF_LatinAxis;
typedef struct AF_LatinMetricsRec_
{
AF_StyleMetricsRec root;
FT_UInt units_per_em;
AF_LatinAxisRec axis[AF_DIMENSION_MAX];
} AF_LatinMetricsRec, *AF_LatinMetrics;
FT_LOCAL( FT_Error )
af_latin_metrics_init( AF_StyleMetrics metrics,
FT_Face face );
FT_LOCAL( void )
af_latin_metrics_scale( AF_StyleMetrics metrics,
AF_Scaler scaler );
FT_LOCAL( void )
af_latin_metrics_init_widths( AF_LatinMetrics metrics,
FT_Face face );
FT_LOCAL( void )
af_latin_metrics_check_digits( AF_LatinMetrics metrics,
FT_Face face );
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** L A T I N G L Y P H A N A L Y S I S *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
#define AF_LATIN_HINTS_HORZ_SNAP ( 1U << 0 ) /* stem width snapping */
#define AF_LATIN_HINTS_VERT_SNAP ( 1U << 1 ) /* stem height snapping */
#define AF_LATIN_HINTS_STEM_ADJUST ( 1U << 2 ) /* stem width/height */
/* adjustment */
#define AF_LATIN_HINTS_MONO ( 1U << 3 ) /* monochrome rendering */
#define AF_LATIN_HINTS_DO_HORZ_SNAP( h ) \
AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_HORZ_SNAP )
#define AF_LATIN_HINTS_DO_VERT_SNAP( h ) \
AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_VERT_SNAP )
#define AF_LATIN_HINTS_DO_STEM_ADJUST( h ) \
AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_STEM_ADJUST )
#define AF_LATIN_HINTS_DO_MONO( h ) \
AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_MONO )
/*
* The next functions shouldn't normally be exported. However, other
* writing systems might like to use these functions as-is.
*/
FT_LOCAL( FT_Error )
af_latin_hints_compute_segments( AF_GlyphHints hints,
AF_Dimension dim );
FT_LOCAL( void )
af_latin_hints_link_segments( AF_GlyphHints hints,
FT_UInt width_count,
AF_WidthRec* widths,
AF_Dimension dim );
FT_LOCAL( FT_Error )
af_latin_hints_compute_edges( AF_GlyphHints hints,
AF_Dimension dim );
FT_LOCAL( FT_Error )
af_latin_hints_detect_features( AF_GlyphHints hints,
FT_UInt width_count,
AF_WidthRec* widths,
AF_Dimension dim );
/* */
FT_END_HEADER
#endif /* AFLATIN_H_ */
/* END */

View File

@@ -0,0 +1,706 @@
/****************************************************************************
*
* afloader.c
*
* Auto-fitter glyph loading routines (body).
*
* Copyright (C) 2003-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include "afglobal.h"
#include "afloader.h"
#include "afhints.h"
#include "aferrors.h"
#include "afmodule.h"
#include <freetype/internal/ftcalc.h>
/* Initialize glyph loader. */
FT_LOCAL_DEF( void )
af_loader_init( AF_Loader loader,
AF_GlyphHints hints )
{
FT_ZERO( loader );
loader->hints = hints;
}
/* Reset glyph loader and compute globals if necessary. */
FT_LOCAL_DEF( FT_Error )
af_loader_reset( AF_Loader loader,
AF_Module module,
FT_Face face )
{
FT_Error error = FT_Err_Ok;
loader->face = face;
loader->globals = (AF_FaceGlobals)face->autohint.data;
if ( !loader->globals )
{
error = af_face_globals_new( face, &loader->globals, module );
if ( !error )
{
face->autohint.data = (FT_Pointer)loader->globals;
face->autohint.finalizer = af_face_globals_free;
}
}
return error;
}
/* Finalize glyph loader. */
FT_LOCAL_DEF( void )
af_loader_done( AF_Loader loader )
{
loader->face = NULL;
loader->globals = NULL;
loader->hints = NULL;
}
#define af_intToFixed( i ) \
( (FT_Fixed)( (FT_UInt32)(i) << 16 ) )
#define af_fixedToInt( x ) \
( (FT_Short)( ( (FT_UInt32)(x) + 0x8000U ) >> 16 ) )
#define af_floatToFixed( f ) \
( (FT_Fixed)( (f) * 65536.0 + 0.5 ) )
static FT_Error
af_loader_embolden_glyph_in_slot( AF_Loader loader,
FT_Face face,
AF_StyleMetrics style_metrics )
{
FT_Error error = FT_Err_Ok;
FT_GlyphSlot slot = face->glyph;
AF_FaceGlobals globals = loader->globals;
AF_WritingSystemClass writing_system_class;
FT_Size_Metrics* size_metrics = &face->size->internal->autohint_metrics;
FT_Pos stdVW = 0;
FT_Pos stdHW = 0;
FT_Bool size_changed = size_metrics->x_ppem !=
globals->stem_darkening_for_ppem;
FT_Fixed em_size = af_intToFixed( face->units_per_EM );
FT_Matrix scale_down_matrix = { 0x10000L, 0, 0, 0x10000L };
/* Skip stem darkening for broken fonts. */
if ( !face->units_per_EM )
{
error = FT_ERR( Corrupted_Font_Header );
goto Exit;
}
/*
* We depend on the writing system (script analyzers) to supply
* standard widths for the script of the glyph we are looking at. If
* it can't deliver, stem darkening is disabled.
*/
writing_system_class =
af_writing_system_classes[style_metrics->style_class->writing_system];
if ( writing_system_class->style_metrics_getstdw )
writing_system_class->style_metrics_getstdw( style_metrics,
&stdHW,
&stdVW );
else
{
error = FT_ERR( Unimplemented_Feature );
goto Exit;
}
if ( size_changed ||
( stdVW > 0 && stdVW != globals->standard_vertical_width ) )
{
FT_Fixed darken_by_font_units_x, darken_x;
darken_by_font_units_x =
af_loader_compute_darkening( loader,
face,
stdVW ) ;
darken_x = FT_MulFix( darken_by_font_units_x,
size_metrics->x_scale );
globals->standard_vertical_width = stdVW;
globals->stem_darkening_for_ppem = size_metrics->x_ppem;
globals->darken_x = af_fixedToInt( darken_x );
}
if ( size_changed ||
( stdHW > 0 && stdHW != globals->standard_horizontal_width ) )
{
FT_Fixed darken_by_font_units_y, darken_y;
darken_by_font_units_y =
af_loader_compute_darkening( loader,
face,
stdHW ) ;
darken_y = FT_MulFix( darken_by_font_units_y,
size_metrics->y_scale );
globals->standard_horizontal_width = stdHW;
globals->stem_darkening_for_ppem = size_metrics->x_ppem;
globals->darken_y = af_fixedToInt( darken_y );
/*
* Scale outlines down on the Y-axis to keep them inside their blue
* zones. The stronger the emboldening, the stronger the downscaling
* (plus heuristical padding to prevent outlines still falling out
* their zones due to rounding).
*
* Reason: `FT_Outline_Embolden' works by shifting the rightmost
* points of stems farther to the right, and topmost points farther
* up. This positions points on the Y-axis outside their
* pre-computed blue zones and leads to distortion when applying the
* hints in the code further below. Code outside this emboldening
* block doesn't know we are presenting it with modified outlines the
* analyzer didn't see!
*
* An unfortunate side effect of downscaling is that the emboldening
* effect is slightly decreased. The loss becomes more pronounced
* versus the CFF driver at smaller sizes, e.g., at 9ppem and below.
*/
globals->scale_down_factor =
FT_DivFix( em_size - ( darken_by_font_units_y + af_intToFixed( 8 ) ),
em_size );
}
FT_Outline_EmboldenXY( &slot->outline,
globals->darken_x,
globals->darken_y );
scale_down_matrix.yy = globals->scale_down_factor;
FT_Outline_Transform( &slot->outline, &scale_down_matrix );
Exit:
return error;
}
/* Load the glyph at index into the current slot of a face and hint it. */
FT_LOCAL_DEF( FT_Error )
af_loader_load_glyph( AF_Loader loader,
AF_Module module,
FT_Face face,
FT_UInt glyph_index,
FT_Int32 load_flags )
{
FT_Error error;
FT_Size size = face->size;
FT_Size_Internal size_internal = size->internal;
FT_GlyphSlot slot = face->glyph;
FT_Slot_Internal slot_internal = slot->internal;
FT_GlyphLoader gloader = slot_internal->loader;
AF_GlyphHints hints = loader->hints;
AF_ScalerRec scaler;
AF_StyleMetrics style_metrics;
FT_UInt style_options = AF_STYLE_NONE_DFLT;
AF_StyleClass style_class;
AF_WritingSystemClass writing_system_class;
FT_ZERO( &scaler );
if ( !size_internal->autohint_metrics.x_scale ||
size_internal->autohint_mode != FT_LOAD_TARGET_MODE( load_flags ) )
{
/* switching between hinting modes usually means different scaling */
/* values; this later on enforces recomputation of everything */
/* related to the current size */
size_internal->autohint_mode = FT_LOAD_TARGET_MODE( load_flags );
size_internal->autohint_metrics = size->metrics;
#ifdef AF_CONFIG_OPTION_TT_SIZE_METRICS
{
FT_Size_Metrics* size_metrics = &size_internal->autohint_metrics;
/* set metrics to integer values and adjust scaling accordingly; */
/* this is the same setup as with TrueType fonts, cf. function */
/* `tt_size_reset' in file `ttobjs.c' */
size_metrics->ascender = FT_PIX_ROUND(
FT_MulFix( face->ascender,
size_metrics->y_scale ) );
size_metrics->descender = FT_PIX_ROUND(
FT_MulFix( face->descender,
size_metrics->y_scale ) );
size_metrics->height = FT_PIX_ROUND(
FT_MulFix( face->height,
size_metrics->y_scale ) );
size_metrics->x_scale = FT_DivFix( size_metrics->x_ppem << 6,
face->units_per_EM );
size_metrics->y_scale = FT_DivFix( size_metrics->y_ppem << 6,
face->units_per_EM );
size_metrics->max_advance = FT_PIX_ROUND(
FT_MulFix( face->max_advance_width,
size_metrics->x_scale ) );
}
#endif /* AF_CONFIG_OPTION_TT_SIZE_METRICS */
}
/*
* TODO: This code currently doesn't support fractional advance widths,
* i.e., placing hinted glyphs at anything other than integer
* x-positions. This is only relevant for the warper code, which
* scales and shifts glyphs to optimize blackness of stems (hinting on
* the x-axis by nature places things on pixel integers, hinting on the
* y-axis only, i.e., LIGHT mode, doesn't touch the x-axis). The delta
* values of the scaler would need to be adjusted.
*/
scaler.face = face;
scaler.x_scale = size_internal->autohint_metrics.x_scale;
scaler.x_delta = 0;
scaler.y_scale = size_internal->autohint_metrics.y_scale;
scaler.y_delta = 0;
scaler.render_mode = FT_LOAD_TARGET_MODE( load_flags );
scaler.flags = 0;
/* note that the fallback style can't be changed anymore */
/* after the first call of `af_loader_load_glyph' */
error = af_loader_reset( loader, module, face );
if ( error )
goto Exit;
/*
* Glyphs (really code points) are assigned to scripts. Script
* analysis is done lazily: For each glyph that passes through here,
* the corresponding script analyzer is called, but returns immediately
* if it has been run already.
*/
error = af_face_globals_get_metrics( loader->globals, glyph_index,
style_options, &style_metrics );
if ( error )
goto Exit;
style_class = style_metrics->style_class;
writing_system_class =
af_writing_system_classes[style_class->writing_system];
loader->metrics = style_metrics;
if ( writing_system_class->style_metrics_scale )
writing_system_class->style_metrics_scale( style_metrics, &scaler );
else
style_metrics->scaler = scaler;
if ( writing_system_class->style_hints_init )
{
error = writing_system_class->style_hints_init( hints,
style_metrics );
if ( error )
goto Exit;
}
/*
* Do the main work of `af_loader_load_glyph'. Note that we never have
* to deal with composite glyphs as those get loaded into
* FT_GLYPH_FORMAT_OUTLINE by the recursed `FT_Load_Glyph' function.
* In the rare cases where FT_LOAD_NO_RECURSE is set, it implies
* FT_LOAD_NO_SCALE and as such the auto-hinter is never called.
*/
load_flags |= FT_LOAD_NO_SCALE |
FT_LOAD_IGNORE_TRANSFORM |
FT_LOAD_LINEAR_DESIGN;
load_flags &= ~FT_LOAD_RENDER;
error = FT_Load_Glyph( face, glyph_index, load_flags );
if ( error )
goto Exit;
/*
* Apply stem darkening (emboldening) here before hints are applied to
* the outline. Glyphs are scaled down proportionally to the
* emboldening so that curve points don't fall outside their
* precomputed blue zones.
*
* Any emboldening done by the font driver (e.g., the CFF driver)
* doesn't reach here because the autohinter loads the unprocessed
* glyphs in font units for analysis (functions `af_*_metrics_init_*')
* and then above to prepare it for the rasterizers by itself,
* independently of the font driver. So emboldening must be done here,
* within the autohinter.
*
* All glyphs to be autohinted pass through here one by one. The
* standard widths can therefore change from one glyph to the next,
* depending on what script a glyph is assigned to (each script has its
* own set of standard widths and other metrics). The darkening amount
* must therefore be recomputed for each size and
* `standard_{vertical,horizontal}_width' change.
*
* Ignore errors and carry on without emboldening.
*
*/
/* stem darkening only works well in `light' mode */
if ( scaler.render_mode == FT_RENDER_MODE_LIGHT &&
( !face->internal->no_stem_darkening ||
( face->internal->no_stem_darkening < 0 &&
!module->no_stem_darkening ) ) )
af_loader_embolden_glyph_in_slot( loader, face, style_metrics );
loader->transformed = slot_internal->glyph_transformed;
if ( loader->transformed )
{
FT_Matrix inverse;
loader->trans_matrix = slot_internal->glyph_matrix;
loader->trans_delta = slot_internal->glyph_delta;
inverse = loader->trans_matrix;
if ( !FT_Matrix_Invert( &inverse ) )
FT_Vector_Transform( &loader->trans_delta, &inverse );
}
switch ( slot->format )
{
case FT_GLYPH_FORMAT_OUTLINE:
/* translate the loaded glyph when an internal transform is needed */
if ( loader->transformed )
FT_Outline_Translate( &slot->outline,
loader->trans_delta.x,
loader->trans_delta.y );
/* compute original horizontal phantom points */
/* (and ignore vertical ones) */
loader->pp1.x = hints->x_delta;
loader->pp1.y = hints->y_delta;
loader->pp2.x = FT_MulFix( slot->metrics.horiAdvance,
hints->x_scale ) + hints->x_delta;
loader->pp2.y = hints->y_delta;
/* be sure to check for spacing glyphs */
if ( slot->outline.n_points == 0 )
goto Hint_Metrics;
/* now load the slot image into the auto-outline */
/* and run the automatic hinting process */
if ( writing_system_class->style_hints_apply )
{
error = writing_system_class->style_hints_apply(
glyph_index,
hints,
&gloader->base.outline,
style_metrics );
if ( error )
goto Exit;
}
/* we now need to adjust the metrics according to the change in */
/* width/positioning that occurred during the hinting process */
if ( scaler.render_mode != FT_RENDER_MODE_LIGHT )
{
AF_AxisHints axis = &hints->axis[AF_DIMENSION_HORZ];
if ( axis->num_edges > 1 && AF_HINTS_DO_ADVANCE( hints ) )
{
AF_Edge edge1 = axis->edges; /* leftmost edge */
AF_Edge edge2 = edge1 +
axis->num_edges - 1; /* rightmost edge */
FT_Pos old_rsb = loader->pp2.x - edge2->opos;
/* loader->pp1.x is always zero at this point of time */
FT_Pos old_lsb = edge1->opos; /* - loader->pp1.x */
FT_Pos new_lsb = edge1->pos;
/* remember unhinted values to later account */
/* for rounding errors */
FT_Pos pp1x_uh = new_lsb - old_lsb;
FT_Pos pp2x_uh = edge2->pos + old_rsb;
/* prefer too much space over too little space */
/* for very small sizes */
if ( old_lsb < 24 )
pp1x_uh -= 8;
if ( old_rsb < 24 )
pp2x_uh += 8;
loader->pp1.x = FT_PIX_ROUND( pp1x_uh );
loader->pp2.x = FT_PIX_ROUND( pp2x_uh );
if ( loader->pp1.x >= new_lsb && old_lsb > 0 )
loader->pp1.x -= 64;
if ( loader->pp2.x <= edge2->pos && old_rsb > 0 )
loader->pp2.x += 64;
slot->lsb_delta = loader->pp1.x - pp1x_uh;
slot->rsb_delta = loader->pp2.x - pp2x_uh;
}
else
{
FT_Pos pp1x = loader->pp1.x;
FT_Pos pp2x = loader->pp2.x;
loader->pp1.x = FT_PIX_ROUND( pp1x );
loader->pp2.x = FT_PIX_ROUND( pp2x );
slot->lsb_delta = loader->pp1.x - pp1x;
slot->rsb_delta = loader->pp2.x - pp2x;
}
}
/* `light' mode uses integer advance widths */
/* but sets `lsb_delta' and `rsb_delta' */
else
{
FT_Pos pp1x = loader->pp1.x;
FT_Pos pp2x = loader->pp2.x;
loader->pp1.x = FT_PIX_ROUND( pp1x );
loader->pp2.x = FT_PIX_ROUND( pp2x );
slot->lsb_delta = loader->pp1.x - pp1x;
slot->rsb_delta = loader->pp2.x - pp2x;
}
break;
default:
/* we don't support other formats (yet?) */
error = FT_THROW( Unimplemented_Feature );
}
Hint_Metrics:
{
FT_BBox bbox;
FT_Vector vvector;
vvector.x = slot->metrics.vertBearingX - slot->metrics.horiBearingX;
vvector.y = slot->metrics.vertBearingY - slot->metrics.horiBearingY;
vvector.x = FT_MulFix( vvector.x, style_metrics->scaler.x_scale );
vvector.y = FT_MulFix( vvector.y, style_metrics->scaler.y_scale );
/* transform the hinted outline if needed */
if ( loader->transformed )
{
FT_Outline_Transform( &gloader->base.outline, &loader->trans_matrix );
FT_Vector_Transform( &vvector, &loader->trans_matrix );
}
/* we must translate our final outline by -pp1.x and compute */
/* the new metrics */
if ( loader->pp1.x )
FT_Outline_Translate( &gloader->base.outline, -loader->pp1.x, 0 );
FT_Outline_Get_CBox( &gloader->base.outline, &bbox );
bbox.xMin = FT_PIX_FLOOR( bbox.xMin );
bbox.yMin = FT_PIX_FLOOR( bbox.yMin );
bbox.xMax = FT_PIX_CEIL( bbox.xMax );
bbox.yMax = FT_PIX_CEIL( bbox.yMax );
slot->metrics.width = bbox.xMax - bbox.xMin;
slot->metrics.height = bbox.yMax - bbox.yMin;
slot->metrics.horiBearingX = bbox.xMin;
slot->metrics.horiBearingY = bbox.yMax;
slot->metrics.vertBearingX = FT_PIX_FLOOR( bbox.xMin + vvector.x );
slot->metrics.vertBearingY = FT_PIX_FLOOR( bbox.yMax + vvector.y );
/* for mono-width fonts (like Andale, Courier, etc.) we need */
/* to keep the original rounded advance width; ditto for */
/* digits if all have the same advance width */
if ( scaler.render_mode != FT_RENDER_MODE_LIGHT &&
( FT_IS_FIXED_WIDTH( slot->face ) ||
( af_face_globals_is_digit( loader->globals, glyph_index ) &&
style_metrics->digits_have_same_width ) ) )
{
slot->metrics.horiAdvance =
FT_MulFix( slot->metrics.horiAdvance,
style_metrics->scaler.x_scale );
/* Set delta values to 0. Otherwise code that uses them is */
/* going to ruin the fixed advance width. */
slot->lsb_delta = 0;
slot->rsb_delta = 0;
}
else
{
/* non-spacing glyphs must stay as-is */
if ( slot->metrics.horiAdvance )
slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
}
slot->metrics.vertAdvance = FT_MulFix( slot->metrics.vertAdvance,
style_metrics->scaler.y_scale );
slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance );
slot->metrics.vertAdvance = FT_PIX_ROUND( slot->metrics.vertAdvance );
slot->format = FT_GLYPH_FORMAT_OUTLINE;
}
Exit:
return error;
}
/*
* Compute amount of font units the face should be emboldened by, in
* analogy to the CFF driver's `cf2_computeDarkening' function. See there
* for details of the algorithm.
*
* XXX: Currently a crude adaption of the original algorithm. Do better?
*/
FT_LOCAL_DEF( FT_Fixed )
af_loader_compute_darkening( AF_Loader loader,
FT_Face face,
FT_Pos standard_width )
{
AF_Module module = loader->globals->module;
FT_UShort units_per_EM;
FT_Fixed ppem, em_ratio;
FT_Fixed stem_width, stem_width_per_1000, scaled_stem, darken_amount;
FT_Int log_base_2;
FT_Int x1, y1, x2, y2, x3, y3, x4, y4;
ppem = FT_MAX( af_intToFixed( 4 ),
af_intToFixed( face->size->metrics.x_ppem ) );
units_per_EM = face->units_per_EM;
em_ratio = FT_DivFix( af_intToFixed( 1000 ),
af_intToFixed ( units_per_EM ) );
if ( em_ratio < af_floatToFixed( .01 ) )
{
/* If something goes wrong, don't embolden. */
return 0;
}
x1 = module->darken_params[0];
y1 = module->darken_params[1];
x2 = module->darken_params[2];
y2 = module->darken_params[3];
x3 = module->darken_params[4];
y3 = module->darken_params[5];
x4 = module->darken_params[6];
y4 = module->darken_params[7];
if ( standard_width <= 0 )
{
stem_width = af_intToFixed( 75 ); /* taken from cf2font.c */
stem_width_per_1000 = stem_width;
}
else
{
stem_width = af_intToFixed( standard_width );
stem_width_per_1000 = FT_MulFix( stem_width, em_ratio );
}
log_base_2 = FT_MSB( (FT_UInt32)stem_width_per_1000 ) +
FT_MSB( (FT_UInt32)ppem );
if ( log_base_2 >= 46 )
{
/* possible overflow */
scaled_stem = af_intToFixed( x4 );
}
else
scaled_stem = FT_MulFix( stem_width_per_1000, ppem );
/* now apply the darkening parameters */
if ( scaled_stem < af_intToFixed( x1 ) )
darken_amount = FT_DivFix( af_intToFixed( y1 ), ppem );
else if ( scaled_stem < af_intToFixed( x2 ) )
{
FT_Int xdelta = x2 - x1;
FT_Int ydelta = y2 - y1;
FT_Int x = stem_width_per_1000 -
FT_DivFix( af_intToFixed( x1 ), ppem );
if ( !xdelta )
goto Try_x3;
darken_amount = FT_MulDiv( x, ydelta, xdelta ) +
FT_DivFix( af_intToFixed( y1 ), ppem );
}
else if ( scaled_stem < af_intToFixed( x3 ) )
{
Try_x3:
{
FT_Int xdelta = x3 - x2;
FT_Int ydelta = y3 - y2;
FT_Int x = stem_width_per_1000 -
FT_DivFix( af_intToFixed( x2 ), ppem );
if ( !xdelta )
goto Try_x4;
darken_amount = FT_MulDiv( x, ydelta, xdelta ) +
FT_DivFix( af_intToFixed( y2 ), ppem );
}
}
else if ( scaled_stem < af_intToFixed( x4 ) )
{
Try_x4:
{
FT_Int xdelta = x4 - x3;
FT_Int ydelta = y4 - y3;
FT_Int x = stem_width_per_1000 -
FT_DivFix( af_intToFixed( x3 ), ppem );
if ( !xdelta )
goto Use_y4;
darken_amount = FT_MulDiv( x, ydelta, xdelta ) +
FT_DivFix( af_intToFixed( y3 ), ppem );
}
}
else
{
Use_y4:
darken_amount = FT_DivFix( af_intToFixed( y4 ), ppem );
}
/* Convert darken_amount from per 1000 em to true character space. */
return FT_DivFix( darken_amount, em_ratio );
}
/* END */

View File

@@ -0,0 +1,91 @@
/****************************************************************************
*
* afloader.h
*
* Auto-fitter glyph loading routines (specification).
*
* Copyright (C) 2003-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#ifndef AFLOADER_H_
#define AFLOADER_H_
#include "afhints.h"
#include "afmodule.h"
#include "afglobal.h"
FT_BEGIN_HEADER
/*
* The autofitter module's (global) data structure to communicate with
* actual fonts. If necessary, `local' data like the current face, the
* current face's auto-hint data, or the current glyph's parameters
* relevant to auto-hinting are `swapped in'. Cf. functions like
* `af_loader_reset' and `af_loader_load_g'.
*/
typedef struct AF_LoaderRec_
{
/* current face data */
FT_Face face;
AF_FaceGlobals globals;
/* current glyph data */
AF_GlyphHints hints;
AF_StyleMetrics metrics;
FT_Bool transformed;
FT_Matrix trans_matrix;
FT_Vector trans_delta;
FT_Vector pp1;
FT_Vector pp2;
/* we don't handle vertical phantom points */
} AF_LoaderRec, *AF_Loader;
FT_LOCAL( void )
af_loader_init( AF_Loader loader,
AF_GlyphHints hints );
FT_LOCAL( FT_Error )
af_loader_reset( AF_Loader loader,
AF_Module module,
FT_Face face );
FT_LOCAL( void )
af_loader_done( AF_Loader loader );
FT_LOCAL( FT_Error )
af_loader_load_glyph( AF_Loader loader,
AF_Module module,
FT_Face face,
FT_UInt gindex,
FT_Int32 load_flags );
FT_LOCAL( FT_Fixed )
af_loader_compute_darkening( AF_Loader loader,
FT_Face face,
FT_Pos standard_width );
/* */
FT_END_HEADER
#endif /* AFLOADER_H_ */
/* END */

View File

@@ -0,0 +1,527 @@
/****************************************************************************
*
* afmodule.c
*
* Auto-fitter module implementation (body).
*
* Copyright (C) 2003-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include "afglobal.h"
#include "afmodule.h"
#include "afloader.h"
#include "aferrors.h"
#ifdef FT_DEBUG_AUTOFIT
#ifndef FT_MAKE_OPTION_SINGLE_OBJECT
#ifdef __cplusplus
extern "C" {
#endif
extern void
af_glyph_hints_dump_segments( AF_GlyphHints hints,
FT_Bool to_stdout );
extern void
af_glyph_hints_dump_points( AF_GlyphHints hints,
FT_Bool to_stdout );
extern void
af_glyph_hints_dump_edges( AF_GlyphHints hints,
FT_Bool to_stdout );
#ifdef __cplusplus
}
#endif
#endif
int af_debug_disable_horz_hints_;
int af_debug_disable_vert_hints_;
int af_debug_disable_blue_hints_;
/* we use a global object instead of a local one for debugging */
static AF_GlyphHintsRec af_debug_hints_rec_[1];
void* af_debug_hints_ = af_debug_hints_rec_;
#endif
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/ftdebug.h>
#include <freetype/ftdriver.h>
#include <freetype/internal/services/svprop.h>
/**************************************************************************
*
* The macro FT_COMPONENT is used in trace mode. It is an implicit
* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
* messages during execution.
*/
#undef FT_COMPONENT
#define FT_COMPONENT afmodule
static FT_Error
af_property_get_face_globals( FT_Face face,
AF_FaceGlobals* aglobals,
AF_Module module )
{
FT_Error error = FT_Err_Ok;
AF_FaceGlobals globals;
if ( !face )
return FT_THROW( Invalid_Face_Handle );
globals = (AF_FaceGlobals)face->autohint.data;
if ( !globals )
{
/* trigger computation of the global style data */
/* in case it hasn't been done yet */
error = af_face_globals_new( face, &globals, module );
if ( !error )
{
face->autohint.data = (FT_Pointer)globals;
face->autohint.finalizer = af_face_globals_free;
}
}
if ( !error )
*aglobals = globals;
return error;
}
static FT_Error
af_property_set( FT_Module ft_module,
const char* property_name,
const void* value,
FT_Bool value_is_string )
{
FT_Error error = FT_Err_Ok;
AF_Module module = (AF_Module)ft_module;
#ifndef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
FT_UNUSED( value_is_string );
#endif
if ( !ft_strcmp( property_name, "fallback-script" ) )
{
AF_Script* fallback_script;
FT_UInt ss;
#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
if ( value_is_string )
return FT_THROW( Invalid_Argument );
#endif
fallback_script = (AF_Script*)value;
/* We translate the fallback script to a fallback style that uses */
/* `fallback-script' as its script and `AF_COVERAGE_NONE' as its */
/* coverage value. */
for ( ss = 0; af_style_classes[ss]; ss++ )
{
AF_StyleClass style_class = af_style_classes[ss];
if ( style_class->script == *fallback_script &&
style_class->coverage == AF_COVERAGE_DEFAULT )
{
module->fallback_style = ss;
break;
}
}
if ( !af_style_classes[ss] )
{
FT_TRACE2(( "af_property_set: Invalid value %d for property `%s'\n",
*fallback_script, property_name ));
return FT_THROW( Invalid_Argument );
}
return error;
}
else if ( !ft_strcmp( property_name, "default-script" ) )
{
AF_Script* default_script;
#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
if ( value_is_string )
return FT_THROW( Invalid_Argument );
#endif
default_script = (AF_Script*)value;
module->default_script = *default_script;
return error;
}
else if ( !ft_strcmp( property_name, "increase-x-height" ) )
{
FT_Prop_IncreaseXHeight* prop;
AF_FaceGlobals globals;
#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
if ( value_is_string )
return FT_THROW( Invalid_Argument );
#endif
prop = (FT_Prop_IncreaseXHeight*)value;
error = af_property_get_face_globals( prop->face, &globals, module );
if ( !error )
globals->increase_x_height = prop->limit;
return error;
}
else if ( !ft_strcmp( property_name, "darkening-parameters" ) )
{
FT_Int* darken_params;
FT_Int x1, y1, x2, y2, x3, y3, x4, y4;
#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
FT_Int dp[8];
if ( value_is_string )
{
const char* s = (const char*)value;
char* ep;
int i;
/* eight comma-separated numbers */
for ( i = 0; i < 7; i++ )
{
dp[i] = (FT_Int)ft_strtol( s, &ep, 10 );
if ( *ep != ',' || s == ep )
return FT_THROW( Invalid_Argument );
s = ep + 1;
}
dp[7] = (FT_Int)ft_strtol( s, &ep, 10 );
if ( !( *ep == '\0' || *ep == ' ' ) || s == ep )
return FT_THROW( Invalid_Argument );
darken_params = dp;
}
else
#endif
darken_params = (FT_Int*)value;
x1 = darken_params[0];
y1 = darken_params[1];
x2 = darken_params[2];
y2 = darken_params[3];
x3 = darken_params[4];
y3 = darken_params[5];
x4 = darken_params[6];
y4 = darken_params[7];
if ( x1 < 0 || x2 < 0 || x3 < 0 || x4 < 0 ||
y1 < 0 || y2 < 0 || y3 < 0 || y4 < 0 ||
x1 > x2 || x2 > x3 || x3 > x4 ||
y1 > 500 || y2 > 500 || y3 > 500 || y4 > 500 )
return FT_THROW( Invalid_Argument );
module->darken_params[0] = x1;
module->darken_params[1] = y1;
module->darken_params[2] = x2;
module->darken_params[3] = y2;
module->darken_params[4] = x3;
module->darken_params[5] = y3;
module->darken_params[6] = x4;
module->darken_params[7] = y4;
return error;
}
else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
{
#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
if ( value_is_string )
{
const char* s = (const char*)value;
long nsd = ft_strtol( s, NULL, 10 );
if ( !nsd )
module->no_stem_darkening = FALSE;
else
module->no_stem_darkening = TRUE;
}
else
#endif
{
FT_Bool* no_stem_darkening = (FT_Bool*)value;
module->no_stem_darkening = *no_stem_darkening;
}
return error;
}
FT_TRACE2(( "af_property_set: missing property `%s'\n",
property_name ));
return FT_THROW( Missing_Property );
}
static FT_Error
af_property_get( FT_Module ft_module,
const char* property_name,
void* value )
{
FT_Error error = FT_Err_Ok;
AF_Module module = (AF_Module)ft_module;
if ( !ft_strcmp( property_name, "glyph-to-script-map" ) )
{
FT_Prop_GlyphToScriptMap* prop = (FT_Prop_GlyphToScriptMap*)value;
AF_FaceGlobals globals;
error = af_property_get_face_globals( prop->face, &globals, module );
if ( !error )
prop->map = globals->glyph_styles;
return error;
}
else if ( !ft_strcmp( property_name, "fallback-script" ) )
{
AF_Script* val = (AF_Script*)value;
AF_StyleClass style_class = af_style_classes[module->fallback_style];
*val = style_class->script;
return error;
}
else if ( !ft_strcmp( property_name, "default-script" ) )
{
AF_Script* val = (AF_Script*)value;
*val = module->default_script;
return error;
}
else if ( !ft_strcmp( property_name, "increase-x-height" ) )
{
FT_Prop_IncreaseXHeight* prop = (FT_Prop_IncreaseXHeight*)value;
AF_FaceGlobals globals;
error = af_property_get_face_globals( prop->face, &globals, module );
if ( !error )
prop->limit = globals->increase_x_height;
return error;
}
else if ( !ft_strcmp( property_name, "darkening-parameters" ) )
{
FT_Int* darken_params = module->darken_params;
FT_Int* val = (FT_Int*)value;
val[0] = darken_params[0];
val[1] = darken_params[1];
val[2] = darken_params[2];
val[3] = darken_params[3];
val[4] = darken_params[4];
val[5] = darken_params[5];
val[6] = darken_params[6];
val[7] = darken_params[7];
return error;
}
else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
{
FT_Bool no_stem_darkening = module->no_stem_darkening;
FT_Bool* val = (FT_Bool*)value;
*val = no_stem_darkening;
return error;
}
FT_TRACE2(( "af_property_get: missing property `%s'\n",
property_name ));
return FT_THROW( Missing_Property );
}
FT_DEFINE_SERVICE_PROPERTIESREC(
af_service_properties,
af_property_set, /* FT_Properties_SetFunc set_property */
af_property_get /* FT_Properties_GetFunc get_property */
)
FT_DEFINE_SERVICEDESCREC1(
af_services,
FT_SERVICE_ID_PROPERTIES, &af_service_properties )
FT_CALLBACK_DEF( FT_Module_Interface )
af_get_interface( FT_Module module,
const char* module_interface )
{
FT_UNUSED( module );
return ft_service_list_lookup( af_services, module_interface );
}
FT_CALLBACK_DEF( FT_Error )
af_autofitter_init( FT_Module ft_module ) /* AF_Module */
{
AF_Module module = (AF_Module)ft_module;
module->fallback_style = AF_STYLE_FALLBACK;
module->default_script = AF_SCRIPT_DEFAULT;
module->no_stem_darkening = TRUE;
module->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1;
module->darken_params[1] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1;
module->darken_params[2] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2;
module->darken_params[3] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2;
module->darken_params[4] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3;
module->darken_params[5] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3;
module->darken_params[6] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4;
module->darken_params[7] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4;
return FT_Err_Ok;
}
FT_CALLBACK_DEF( void )
af_autofitter_done( FT_Module ft_module ) /* AF_Module */
{
FT_UNUSED( ft_module );
#ifdef FT_DEBUG_AUTOFIT
if ( af_debug_hints_rec_->memory )
af_glyph_hints_done( af_debug_hints_rec_ );
#endif
}
FT_CALLBACK_DEF( FT_Error )
af_autofitter_load_glyph( FT_AutoHinter module_,
FT_GlyphSlot slot,
FT_Size size,
FT_UInt glyph_index,
FT_Int32 load_flags )
{
AF_Module module = (AF_Module)module_;
FT_Error error = FT_Err_Ok;
FT_Memory memory = module->root.memory;
#ifdef FT_DEBUG_AUTOFIT
/* in debug mode, we use a global object that survives this routine */
AF_GlyphHints hints = af_debug_hints_rec_;
AF_LoaderRec loader[1];
FT_UNUSED( size );
if ( hints->memory )
af_glyph_hints_done( hints );
af_glyph_hints_init( hints, memory );
af_loader_init( loader, hints );
error = af_loader_load_glyph( loader, module, slot->face,
glyph_index, load_flags );
#ifdef FT_DEBUG_LEVEL_TRACE
if ( ft_trace_levels[FT_TRACE_COMP( FT_COMPONENT )] )
{
#endif
af_glyph_hints_dump_points( hints, 0 );
af_glyph_hints_dump_segments( hints, 0 );
af_glyph_hints_dump_edges( hints, 0 );
#ifdef FT_DEBUG_LEVEL_TRACE
}
#endif
af_loader_done( loader );
return error;
#else /* !FT_DEBUG_AUTOFIT */
AF_GlyphHintsRec hints[1];
AF_LoaderRec loader[1];
FT_UNUSED( size );
af_glyph_hints_init( hints, memory );
af_loader_init( loader, hints );
error = af_loader_load_glyph( loader, module, slot->face,
glyph_index, load_flags );
af_loader_done( loader );
af_glyph_hints_done( hints );
return error;
#endif /* !FT_DEBUG_AUTOFIT */
}
FT_DEFINE_AUTOHINTER_INTERFACE(
af_autofitter_interface,
NULL, /* FT_AutoHinter_GlobalResetFunc reset_face */
NULL, /* FT_AutoHinter_GlobalGetFunc get_global_hints */
NULL, /* FT_AutoHinter_GlobalDoneFunc done_global_hints */
af_autofitter_load_glyph /* FT_AutoHinter_GlyphLoadFunc load_glyph */
)
FT_DEFINE_MODULE(
autofit_module_class,
FT_MODULE_HINTER,
sizeof ( AF_ModuleRec ),
"autofitter",
0x10000L, /* version 1.0 of the autofitter */
0x20000L, /* requires FreeType 2.0 or above */
(const void*)&af_autofitter_interface,
af_autofitter_init, /* FT_Module_Constructor module_init */
af_autofitter_done, /* FT_Module_Destructor module_done */
af_get_interface /* FT_Module_Requester get_interface */
)
/* END */

View File

@@ -0,0 +1,55 @@
/****************************************************************************
*
* afmodule.h
*
* Auto-fitter module implementation (specification).
*
* Copyright (C) 2003-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#ifndef AFMODULE_H_
#define AFMODULE_H_
#include <freetype/internal/ftobjs.h>
#include <freetype/ftmodapi.h>
FT_BEGIN_HEADER
/*
* This is the `extended' FT_Module structure that holds the
* autofitter's global data.
*/
typedef struct AF_ModuleRec_
{
FT_ModuleRec root;
FT_UInt fallback_style;
AF_Script default_script;
FT_Bool no_stem_darkening;
FT_Int darken_params[8];
} AF_ModuleRec, *AF_Module;
FT_DECLARE_AUTOHINTER_INTERFACE( af_autofitter_interface )
FT_DECLARE_MODULE( autofit_module_class )
FT_END_HEADER
#endif /* AFMODULE_H_ */
/* END */

1072
thirdparty/freetype/src/autofit/afranges.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,47 @@
/****************************************************************************
*
* afranges.h
*
* Auto-fitter Unicode script ranges (specification).
*
* Copyright (C) 2013-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#ifndef AFRANGES_H_
#define AFRANGES_H_
#include "aftypes.h"
FT_BEGIN_HEADER
#undef SCRIPT
#define SCRIPT( s, S, d, h, H, ss ) \
extern const AF_Script_UniRangeRec af_ ## s ## _uniranges[];
#include "afscript.h"
#undef SCRIPT
#define SCRIPT( s, S, d, h, H, ss ) \
extern const AF_Script_UniRangeRec af_ ## s ## _nonbase_uniranges[];
#include "afscript.h"
/* */
FT_END_HEADER
#endif /* AFRANGES_H_ */
/* END */

View File

@@ -0,0 +1,408 @@
/****************************************************************************
*
* afscript.h
*
* Auto-fitter scripts (specification only).
*
* Copyright (C) 2013-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
/* The following part can be included multiple times. */
/* Define `SCRIPT' as needed. */
/* Add new scripts here. The first and second arguments are the */
/* script name in lowercase and uppercase, respectively, followed */
/* by a description string. Then comes the corresponding HarfBuzz */
/* script name tag, followed by a string of standard characters (to */
/* derive the standard width and height of stems). */
/* */
/* Note that fallback scripts only have a default style, thus we */
/* use `HB_SCRIPT_INVALID' as the HarfBuzz script name tag for */
/* them. */
SCRIPT( adlm, ADLM,
"Adlam",
HB_SCRIPT_ADLAM,
HINTING_BOTTOM_TO_TOP,
"\xF0\x9E\xA4\x8C \xF0\x9E\xA4\xAE" ) /* 𞤌 𞤮 */
SCRIPT( arab, ARAB,
"Arabic",
HB_SCRIPT_ARABIC,
HINTING_BOTTOM_TO_TOP,
"\xD9\x84 \xD8\xAD \xD9\x80" ) /* ل ح ـ */
SCRIPT( armn, ARMN,
"Armenian",
HB_SCRIPT_ARMENIAN,
HINTING_BOTTOM_TO_TOP,
"\xD5\xBD \xD5\x8D" ) /* ս Ս */
SCRIPT( avst, AVST,
"Avestan",
HB_SCRIPT_AVESTAN,
HINTING_BOTTOM_TO_TOP,
"\xF0\x90\xAC\x9A" ) /* 𐬚 */
SCRIPT( bamu, BAMU,
"Bamum",
HB_SCRIPT_BAMUM,
HINTING_BOTTOM_TO_TOP,
"\xEA\x9B\x81 \xEA\x9B\xAF" ) /* ꛁ */
/* there are no simple forms for letters; we thus use two digit shapes */
SCRIPT( beng, BENG,
"Bengali",
HB_SCRIPT_BENGALI,
HINTING_TOP_TO_BOTTOM,
"\xE0\xA7\xA6 \xE0\xA7\xAA" ) /* */
SCRIPT( buhd, BUHD,
"Buhid",
HB_SCRIPT_BUHID,
HINTING_BOTTOM_TO_TOP,
"\xE1\x9D\x8B \xE1\x9D\x8F" ) /* ᝋ ᝏ */
SCRIPT( cakm, CAKM,
"Chakma",
HB_SCRIPT_CHAKMA,
HINTING_BOTTOM_TO_TOP,
"\xF0\x91\x84\xA4 \xF0\x91\x84\x89 \xF0\x91\x84\x9B" ) /* 𑄤 𑄉 𑄛 */
SCRIPT( cans, CANS,
"Canadian Syllabics",
HB_SCRIPT_CANADIAN_SYLLABICS,
HINTING_BOTTOM_TO_TOP,
"\xE1\x91\x8C \xE1\x93\x9A" ) /* ᓚ */
SCRIPT( cari, CARI,
"Carian",
HB_SCRIPT_CARIAN,
HINTING_BOTTOM_TO_TOP,
"\xF0\x90\x8A\xAB \xF0\x90\x8B\x89" ) /* 𐊫 𐋉 */
SCRIPT( cher, CHER,
"Cherokee",
HB_SCRIPT_CHEROKEE,
HINTING_BOTTOM_TO_TOP,
"\xE1\x8E\xA4 \xE1\x8F\x85 \xEA\xAE\x95" ) /* Ꭴ Ꮕ ꮕ */
SCRIPT( copt, COPT,
"Coptic",
HB_SCRIPT_COPTIC,
HINTING_BOTTOM_TO_TOP,
"\xE2\xB2\x9E \xE2\xB2\x9F" ) /* */
SCRIPT( cprt, CPRT,
"Cypriot",
HB_SCRIPT_CYPRIOT,
HINTING_BOTTOM_TO_TOP,
"\xF0\x90\xA0\x85 \xF0\x90\xA0\xA3" ) /* 𐠅 𐠣 */
SCRIPT( cyrl, CYRL,
"Cyrillic",
HB_SCRIPT_CYRILLIC,
HINTING_BOTTOM_TO_TOP,
"\xD0\xBE \xD0\x9E" ) /* о О */
SCRIPT( deva, DEVA,
"Devanagari",
HB_SCRIPT_DEVANAGARI,
HINTING_TOP_TO_BOTTOM,
"\xE0\xA4\xA0 \xE0\xA4\xB5 \xE0\xA4\x9F" ) /* ठ व ट */
SCRIPT( dsrt, DSRT,
"Deseret",
HB_SCRIPT_DESERET,
HINTING_BOTTOM_TO_TOP,
"\xF0\x90\x90\x84 \xF0\x90\x90\xAC" ) /* 𐐄 𐐬 */
SCRIPT( ethi, ETHI,
"Ethiopic",
HB_SCRIPT_ETHIOPIC,
HINTING_BOTTOM_TO_TOP,
"\xE1\x8B\x90" ) /* */
SCRIPT( geor, GEOR,
"Georgian (Mkhedruli)",
HB_SCRIPT_GEORGIAN,
HINTING_BOTTOM_TO_TOP,
"\xE1\x83\x98 \xE1\x83\x94 \xE1\x83\x90 \xE1\xB2\xBF" ) /* ი ე ა Ი */
SCRIPT( geok, GEOK,
"Georgian (Khutsuri)",
HB_SCRIPT_INVALID,
HINTING_BOTTOM_TO_TOP,
"\xE1\x82\xB6 \xE1\x82\xB1 \xE2\xB4\x99" ) /* Ⴖ Ⴑ ⴙ */
SCRIPT( glag, GLAG,
"Glagolitic",
HB_SCRIPT_GLAGOLITIC,
HINTING_BOTTOM_TO_TOP,
"\xE2\xB0\x95 \xE2\xB1\x85" ) /* Ⱅ ⱅ */
SCRIPT( goth, GOTH,
"Gothic",
HB_SCRIPT_GOTHIC,
HINTING_TOP_TO_BOTTOM,
"\xF0\x90\x8C\xB4 \xF0\x90\x8C\xBE \xF0\x90\x8D\x83" ) /* 𐌴 𐌾 𐍃 */
SCRIPT( grek, GREK,
"Greek",
HB_SCRIPT_GREEK,
HINTING_BOTTOM_TO_TOP,
"\xCE\xBF \xCE\x9F" ) /* ο Ο */
SCRIPT( gujr, GUJR,
"Gujarati",
HB_SCRIPT_GUJARATI,
HINTING_BOTTOM_TO_TOP,
"\xE0\xAA\x9F \xE0\xAB\xA6" ) /* ટ */
SCRIPT( guru, GURU,
"Gurmukhi",
HB_SCRIPT_GURMUKHI,
HINTING_TOP_TO_BOTTOM,
"\xE0\xA8\xA0 \xE0\xA8\xB0 \xE0\xA9\xA6" ) /* ਠ ਰ */
SCRIPT( hebr, HEBR,
"Hebrew",
HB_SCRIPT_HEBREW,
HINTING_BOTTOM_TO_TOP,
"\xD7\x9D" ) /* ם */
SCRIPT( kali, KALI,
"Kayah Li",
HB_SCRIPT_KAYAH_LI,
HINTING_BOTTOM_TO_TOP,
"\xEA\xA4\x8D \xEA\xA4\x80" ) /* ꤍ ꤀ */
/* only digit zero has a simple shape in the Khmer script */
SCRIPT( khmr, KHMR,
"Khmer",
HB_SCRIPT_KHMER,
HINTING_BOTTOM_TO_TOP,
"\xE1\x9F\xA0" ) /* ០ */
SCRIPT( khms, KHMS,
"Khmer Symbols",
HB_SCRIPT_INVALID,
HINTING_BOTTOM_TO_TOP,
"\xE1\xA7\xA1 \xE1\xA7\xAA" ) /* ᧡ ᧪ */
SCRIPT( knda, KNDA,
"Kannada",
HB_SCRIPT_KANNADA,
HINTING_BOTTOM_TO_TOP,
"\xE0\xB3\xA6 \xE0\xB2\xAC" ) /* ಬ */
/* only digit zero has a simple shape in the Lao script */
SCRIPT( lao, LAO,
"Lao",
HB_SCRIPT_LAO,
HINTING_BOTTOM_TO_TOP,
"\xE0\xBB\x90" ) /* */
SCRIPT( latn, LATN,
"Latin",
HB_SCRIPT_LATIN,
HINTING_BOTTOM_TO_TOP,
"o O 0" )
SCRIPT( latb, LATB,
"Latin Subscript Fallback",
HB_SCRIPT_INVALID,
HINTING_BOTTOM_TO_TOP,
"\xE2\x82\x92 \xE2\x82\x80" ) /* ₒ ₀ */
SCRIPT( latp, LATP,
"Latin Superscript Fallback",
HB_SCRIPT_INVALID,
HINTING_BOTTOM_TO_TOP,
"\xE1\xB5\x92 \xE1\xB4\xBC \xE2\x81\xB0" ) /* ᵒ ᴼ ⁰ */
SCRIPT( lisu, LISU,
"Lisu",
HB_SCRIPT_LISU,
HINTING_BOTTOM_TO_TOP,
"\xEA\x93\xB3" ) /* */
SCRIPT( mlym, MLYM,
"Malayalam",
HB_SCRIPT_MALAYALAM,
HINTING_BOTTOM_TO_TOP,
"\xE0\xB4\xA0 \xE0\xB4\xB1" ) /* റ */
SCRIPT( medf, MEDF,
"Medefaidrin",
HB_SCRIPT_MEDEFAIDRIN,
HINTING_BOTTOM_TO_TOP,
"\xF0\x96\xB9\xA1 \xF0\x96\xB9\x9B \xF0\x96\xB9\xAF" ) /* 𖹡 𖹛 𖹯 */
SCRIPT( mong, MONG,
"Mongolian",
HB_SCRIPT_MONGOLIAN,
HINTING_TOP_TO_BOTTOM,
"\xE1\xA1\x82 \xE1\xA0\xAA" ) /* ᡂ ᠪ */
SCRIPT( mymr, MYMR,
"Myanmar",
HB_SCRIPT_MYANMAR,
HINTING_BOTTOM_TO_TOP,
"\xE1\x80\x9D \xE1\x80\x84 \xE1\x80\x82" ) /* င ဂ */
SCRIPT( nkoo, NKOO,
"N'Ko",
HB_SCRIPT_NKO,
HINTING_BOTTOM_TO_TOP,
"\xDF\x8B \xDF\x80" ) /* ߋ ߀ */
SCRIPT( none, NONE,
"no script",
HB_SCRIPT_INVALID,
HINTING_BOTTOM_TO_TOP,
"" )
SCRIPT( olck, OLCK,
"Ol Chiki",
HB_SCRIPT_OL_CHIKI,
HINTING_BOTTOM_TO_TOP,
"\xE1\xB1\x9B" ) /* ᱛ */
SCRIPT( orkh, ORKH,
"Old Turkic",
HB_SCRIPT_OLD_TURKIC,
HINTING_BOTTOM_TO_TOP,
"\xF0\x90\xB0\x97" ) /* 𐰗 */
SCRIPT( osge, OSGE,
"Osage",
HB_SCRIPT_OSAGE,
HINTING_BOTTOM_TO_TOP,
"\xF0\x90\x93\x82 \xF0\x90\x93\xAA" ) /* 𐓂 𐓪 */
SCRIPT( osma, OSMA,
"Osmanya",
HB_SCRIPT_OSMANYA,
HINTING_BOTTOM_TO_TOP,
"\xF0\x90\x92\x86 \xF0\x90\x92\xA0" ) /* 𐒆 𐒠 */
SCRIPT( rohg, ROHG,
"Hanifi Rohingya",
HB_SCRIPT_HANIFI_ROHINGYA,
HINTING_BOTTOM_TO_TOP,
"\xF0\x90\xB4\xB0" ) /* 𐴰 */
SCRIPT( saur, SAUR,
"Saurashtra",
HB_SCRIPT_SAURASHTRA,
HINTING_BOTTOM_TO_TOP,
"\xEA\xA2\x9D \xEA\xA3\x90" ) /* ꢝ ꣐ */
SCRIPT( shaw, SHAW,
"Shavian",
HB_SCRIPT_SHAVIAN,
HINTING_BOTTOM_TO_TOP,
"\xF0\x90\x91\xB4" ) /* 𐑴 */
SCRIPT( sinh, SINH,
"Sinhala",
HB_SCRIPT_SINHALA,
HINTING_BOTTOM_TO_TOP,
"\xE0\xB6\xA7" ) /* ට */
/* only digit zero has a simple (round) shape in the Sundanese script */
SCRIPT( sund, SUND,
"Sundanese",
HB_SCRIPT_SUNDANESE,
HINTING_BOTTOM_TO_TOP,
"\xE1\xAE\xB0" ) /* ᮰ */
/* only digit zero has a simple (round) shape in the Tamil script */
SCRIPT( taml, TAML,
"Tamil",
HB_SCRIPT_TAMIL,
HINTING_BOTTOM_TO_TOP,
"\xE0\xAF\xA6" ) /* */
SCRIPT( tavt, TAVT,
"Tai Viet",
HB_SCRIPT_TAI_VIET,
HINTING_BOTTOM_TO_TOP,
"\xEA\xAA\x92 \xEA\xAA\xAB" ) /* ꪒ ꪫ */
/* there are no simple forms for letters; we thus use two digit shapes */
SCRIPT( telu, TELU,
"Telugu",
HB_SCRIPT_TELUGU,
HINTING_BOTTOM_TO_TOP,
"\xE0\xB1\xA6 \xE0\xB1\xA7" ) /* ౧ */
SCRIPT( tfng, TFNG,
"Tifinagh",
HB_SCRIPT_TIFINAGH,
HINTING_BOTTOM_TO_TOP,
"\xE2\xB5\x94" ) /* */
SCRIPT( thai, THAI,
"Thai",
HB_SCRIPT_THAI,
HINTING_BOTTOM_TO_TOP,
"\xE0\xB8\xB2 \xE0\xB9\x85 \xE0\xB9\x90" ) /* า ๅ */
SCRIPT( vaii, VAII,
"Vai",
HB_SCRIPT_VAI,
HINTING_BOTTOM_TO_TOP,
"\xEA\x98\x93 \xEA\x96\x9C \xEA\x96\xB4" ) /* ꘓ ꖜ ꖴ */
#ifdef AF_CONFIG_OPTION_INDIC
SCRIPT( limb, LIMB,
"Limbu",
HB_SCRIPT_LIMBU,
HINTING_BOTTOM_TO_TOP,
"o" ) /* XXX */
SCRIPT( orya, ORYA,
"Oriya",
HB_SCRIPT_ORIYA,
HINTING_BOTTOM_TO_TOP,
"o" ) /* XXX */
SCRIPT( sylo, SYLO,
"Syloti Nagri",
HB_SCRIPT_SYLOTI_NAGRI,
HINTING_BOTTOM_TO_TOP,
"o" ) /* XXX */
SCRIPT( tibt, TIBT,
"Tibetan",
HB_SCRIPT_TIBETAN,
HINTING_BOTTOM_TO_TOP,
"o" ) /* XXX */
#endif /* AF_CONFIG_OPTION_INDIC */
#ifdef AF_CONFIG_OPTION_CJK
SCRIPT( hani, HANI,
"CJKV ideographs",
HB_SCRIPT_HAN,
HINTING_BOTTOM_TO_TOP,
"\xE7\x94\xB0 \xE5\x9B\x97" ) /* 田 囗 */
#endif /* AF_CONFIG_OPTION_CJK */
/* END */

View File

@@ -0,0 +1,690 @@
/****************************************************************************
*
* afshaper.c
*
* HarfBuzz interface for accessing OpenType features (body).
*
* Copyright (C) 2013-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/freetype.h>
#include <freetype/ftadvanc.h>
#include "afglobal.h"
#include "aftypes.h"
#include "afshaper.h"
#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
/**************************************************************************
*
* The macro FT_COMPONENT is used in trace mode. It is an implicit
* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
* messages during execution.
*/
#undef FT_COMPONENT
#define FT_COMPONENT afshaper
/*
* We use `sets' (in the HarfBuzz sense, which comes quite near to the
* usual mathematical meaning) to manage both lookups and glyph indices.
*
* 1. For each coverage, collect lookup IDs in a set. Note that an
* auto-hinter `coverage' is represented by one `feature', and a
* feature consists of an arbitrary number of (font specific) `lookup's
* that actually do the mapping job. Please check the OpenType
* specification for more details on features and lookups.
*
* 2. Create glyph ID sets from the corresponding lookup sets.
*
* 3. The glyph set corresponding to AF_COVERAGE_DEFAULT is computed
* with all lookups specific to the OpenType script activated. It
* relies on the order of AF_DEFINE_STYLE_CLASS entries so that
* special coverages (like `oldstyle figures') don't get overwritten.
*
*/
/* load coverage tags */
#undef COVERAGE
#define COVERAGE( name, NAME, description, \
tag1, tag2, tag3, tag4 ) \
static const hb_tag_t name ## _coverage[] = \
{ \
HB_TAG( tag1, tag2, tag3, tag4 ), \
HB_TAG_NONE \
};
#include "afcover.h"
/* define mapping between coverage tags and AF_Coverage */
#undef COVERAGE
#define COVERAGE( name, NAME, description, \
tag1, tag2, tag3, tag4 ) \
name ## _coverage,
static const hb_tag_t* coverages[] =
{
#include "afcover.h"
NULL /* AF_COVERAGE_DEFAULT */
};
/* load HarfBuzz script tags */
#undef SCRIPT
#define SCRIPT( s, S, d, h, H, ss ) h,
static const hb_script_t scripts[] =
{
#include "afscript.h"
};
FT_Error
af_shaper_get_coverage( AF_FaceGlobals globals,
AF_StyleClass style_class,
FT_UShort* gstyles,
FT_Bool default_script )
{
hb_face_t* face;
hb_set_t* gsub_lookups = NULL; /* GSUB lookups for a given script */
hb_set_t* gsub_glyphs = NULL; /* glyphs covered by GSUB lookups */
hb_set_t* gpos_lookups = NULL; /* GPOS lookups for a given script */
hb_set_t* gpos_glyphs = NULL; /* glyphs covered by GPOS lookups */
hb_script_t script;
const hb_tag_t* coverage_tags;
hb_tag_t script_tags[] = { HB_TAG_NONE,
HB_TAG_NONE,
HB_TAG_NONE,
HB_TAG_NONE };
hb_codepoint_t idx;
#ifdef FT_DEBUG_LEVEL_TRACE
int count;
#endif
if ( !globals || !style_class || !gstyles )
return FT_THROW( Invalid_Argument );
face = hb_font_get_face( globals->hb_font );
coverage_tags = coverages[style_class->coverage];
script = scripts[style_class->script];
/* Convert a HarfBuzz script tag into the corresponding OpenType */
/* tag or tags -- some Indic scripts like Devanagari have an old */
/* and a new set of features. */
{
unsigned int tags_count = 3;
hb_tag_t tags[3];
hb_ot_tags_from_script_and_language( script,
HB_LANGUAGE_INVALID,
&tags_count,
tags,
NULL,
NULL );
script_tags[0] = tags_count > 0 ? tags[0] : HB_TAG_NONE;
script_tags[1] = tags_count > 1 ? tags[1] : HB_TAG_NONE;
script_tags[2] = tags_count > 2 ? tags[2] : HB_TAG_NONE;
}
/* If the second tag is HB_OT_TAG_DEFAULT_SCRIPT, change that to */
/* HB_TAG_NONE except for the default script. */
if ( default_script )
{
if ( script_tags[0] == HB_TAG_NONE )
script_tags[0] = HB_OT_TAG_DEFAULT_SCRIPT;
else
{
if ( script_tags[1] == HB_TAG_NONE )
script_tags[1] = HB_OT_TAG_DEFAULT_SCRIPT;
else if ( script_tags[1] != HB_OT_TAG_DEFAULT_SCRIPT )
script_tags[2] = HB_OT_TAG_DEFAULT_SCRIPT;
}
}
else
{
/* we use non-standard tags like `khms' for special purposes; */
/* HarfBuzz maps them to `DFLT', which we don't want to handle here */
if ( script_tags[0] == HB_OT_TAG_DEFAULT_SCRIPT )
goto Exit;
}
gsub_lookups = hb_set_create();
hb_ot_layout_collect_lookups( face,
HB_OT_TAG_GSUB,
script_tags,
NULL,
coverage_tags,
gsub_lookups );
if ( hb_set_is_empty( gsub_lookups ) )
goto Exit; /* nothing to do */
FT_TRACE4(( "GSUB lookups (style `%s'):\n",
af_style_names[style_class->style] ));
FT_TRACE4(( " " ));
#ifdef FT_DEBUG_LEVEL_TRACE
count = 0;
#endif
gsub_glyphs = hb_set_create();
for ( idx = HB_SET_VALUE_INVALID; hb_set_next( gsub_lookups, &idx ); )
{
#ifdef FT_DEBUG_LEVEL_TRACE
FT_TRACE4(( " %d", idx ));
count++;
#endif
/* get output coverage of GSUB feature */
hb_ot_layout_lookup_collect_glyphs( face,
HB_OT_TAG_GSUB,
idx,
NULL,
NULL,
NULL,
gsub_glyphs );
}
#ifdef FT_DEBUG_LEVEL_TRACE
if ( !count )
FT_TRACE4(( " (none)" ));
FT_TRACE4(( "\n" ));
FT_TRACE4(( "\n" ));
#endif
FT_TRACE4(( "GPOS lookups (style `%s'):\n",
af_style_names[style_class->style] ));
FT_TRACE4(( " " ));
gpos_lookups = hb_set_create();
hb_ot_layout_collect_lookups( face,
HB_OT_TAG_GPOS,
script_tags,
NULL,
coverage_tags,
gpos_lookups );
#ifdef FT_DEBUG_LEVEL_TRACE
count = 0;
#endif
gpos_glyphs = hb_set_create();
for ( idx = HB_SET_VALUE_INVALID; hb_set_next( gpos_lookups, &idx ); )
{
#ifdef FT_DEBUG_LEVEL_TRACE
FT_TRACE4(( " %d", idx ));
count++;
#endif
/* get input coverage of GPOS feature */
hb_ot_layout_lookup_collect_glyphs( face,
HB_OT_TAG_GPOS,
idx,
NULL,
gpos_glyphs,
NULL,
NULL );
}
#ifdef FT_DEBUG_LEVEL_TRACE
if ( !count )
FT_TRACE4(( " (none)" ));
FT_TRACE4(( "\n" ));
FT_TRACE4(( "\n" ));
#endif
/*
* We now check whether we can construct blue zones, using glyphs
* covered by the feature only. In case there is not a single zone
* (that is, not a single character is covered), we skip this coverage.
*
*/
if ( style_class->coverage != AF_COVERAGE_DEFAULT )
{
AF_Blue_Stringset bss = style_class->blue_stringset;
const AF_Blue_StringRec* bs = &af_blue_stringsets[bss];
FT_Bool found = 0;
for ( ; bs->string != AF_BLUE_STRING_MAX; bs++ )
{
const char* p = &af_blue_strings[bs->string];
while ( *p )
{
hb_codepoint_t ch;
GET_UTF8_CHAR( ch, p );
for ( idx = HB_SET_VALUE_INVALID; hb_set_next( gsub_lookups,
&idx ); )
{
hb_codepoint_t gidx = FT_Get_Char_Index( globals->face, ch );
if ( hb_ot_layout_lookup_would_substitute( face, idx,
&gidx, 1, 1 ) )
{
found = 1;
break;
}
}
}
}
if ( !found )
{
FT_TRACE4(( " no blue characters found; style skipped\n" ));
goto Exit;
}
}
/*
* Various OpenType features might use the same glyphs at different
* vertical positions; for example, superscript and subscript glyphs
* could be the same. However, the auto-hinter is completely
* agnostic of OpenType features after the feature analysis has been
* completed: The engine then simply receives a glyph index and returns a
* hinted and usually rendered glyph.
*
* Consider the superscript feature of font `pala.ttf': Some of the
* glyphs are `real', that is, they have a zero vertical offset, but
* most of them are small caps glyphs shifted up to the superscript
* position (that is, the `sups' feature is present in both the GSUB and
* GPOS tables). The code for blue zones computation actually uses a
* feature's y offset so that the `real' glyphs get correct hints. But
* later on it is impossible to decide whether a glyph index belongs to,
* say, the small caps or superscript feature.
*
* For this reason, we don't assign a style to a glyph if the current
* feature covers the glyph in both the GSUB and the GPOS tables. This
* is quite a broad condition, assuming that
*
* (a) glyphs that get used in multiple features are present in a
* feature without vertical shift,
*
* and
*
* (b) a feature's GPOS data really moves the glyph vertically.
*
* Not fulfilling condition (a) makes a font larger; it would also
* reduce the number of glyphs that could be addressed directly without
* using OpenType features, so this assumption is rather strong.
*
* Condition (b) is much weaker, and there might be glyphs which get
* missed. However, the OpenType features we are going to handle are
* primarily located in GSUB, and HarfBuzz doesn't provide an API to
* directly get the necessary information from the GPOS table. A
* possible solution might be to directly parse the GPOS table to find
* out whether a glyph gets shifted vertically, but this is something I
* would like to avoid if not really necessary.
*
* Note that we don't follow this logic for the default coverage.
* Complex scripts like Devanagari have mandatory GPOS features to
* position many glyph elements, using mark-to-base or mark-to-ligature
* tables; the number of glyphs missed due to condition (b) would be far
* too large.
*
*/
if ( style_class->coverage != AF_COVERAGE_DEFAULT )
hb_set_subtract( gsub_glyphs, gpos_glyphs );
#ifdef FT_DEBUG_LEVEL_TRACE
FT_TRACE4(( " glyphs without GPOS data (`*' means already assigned)" ));
count = 0;
#endif
for ( idx = HB_SET_VALUE_INVALID; hb_set_next( gsub_glyphs, &idx ); )
{
#ifdef FT_DEBUG_LEVEL_TRACE
if ( !( count % 10 ) )
{
FT_TRACE4(( "\n" ));
FT_TRACE4(( " " ));
}
FT_TRACE4(( " %d", idx ));
count++;
#endif
/* glyph indices returned by `hb_ot_layout_lookup_collect_glyphs' */
/* can be arbitrary: some fonts use fake indices for processing */
/* internal to GSUB or GPOS, which is fully valid */
if ( idx >= (hb_codepoint_t)globals->glyph_count )
continue;
if ( gstyles[idx] == AF_STYLE_UNASSIGNED )
gstyles[idx] = (FT_UShort)style_class->style;
#ifdef FT_DEBUG_LEVEL_TRACE
else
FT_TRACE4(( "*" ));
#endif
}
#ifdef FT_DEBUG_LEVEL_TRACE
if ( !count )
{
FT_TRACE4(( "\n" ));
FT_TRACE4(( " (none)" ));
}
FT_TRACE4(( "\n" ));
FT_TRACE4(( "\n" ));
#endif
Exit:
hb_set_destroy( gsub_lookups );
hb_set_destroy( gsub_glyphs );
hb_set_destroy( gpos_lookups );
hb_set_destroy( gpos_glyphs );
return FT_Err_Ok;
}
/* construct HarfBuzz features */
#undef COVERAGE
#define COVERAGE( name, NAME, description, \
tag1, tag2, tag3, tag4 ) \
static const hb_feature_t name ## _feature[] = \
{ \
{ \
HB_TAG( tag1, tag2, tag3, tag4 ), \
1, 0, (unsigned int)-1 \
} \
};
#include "afcover.h"
/* define mapping between HarfBuzz features and AF_Coverage */
#undef COVERAGE
#define COVERAGE( name, NAME, description, \
tag1, tag2, tag3, tag4 ) \
name ## _feature,
static const hb_feature_t* features[] =
{
#include "afcover.h"
NULL /* AF_COVERAGE_DEFAULT */
};
void*
af_shaper_buf_create( FT_Face face )
{
FT_UNUSED( face );
return (void*)hb_buffer_create();
}
void
af_shaper_buf_destroy( FT_Face face,
void* buf )
{
FT_UNUSED( face );
hb_buffer_destroy( (hb_buffer_t*)buf );
}
const char*
af_shaper_get_cluster( const char* p,
AF_StyleMetrics metrics,
void* buf_,
unsigned int* count )
{
AF_StyleClass style_class;
const hb_feature_t* feature;
FT_Int upem;
const char* q;
int len;
hb_buffer_t* buf = (hb_buffer_t*)buf_;
hb_font_t* font;
hb_codepoint_t dummy;
upem = (FT_Int)metrics->globals->face->units_per_EM;
style_class = metrics->style_class;
feature = features[style_class->coverage];
font = metrics->globals->hb_font;
/* we shape at a size of units per EM; this means font units */
hb_font_set_scale( font, upem, upem );
while ( *p == ' ' )
p++;
/* count bytes up to next space (or end of buffer) */
q = p;
while ( !( *q == ' ' || *q == '\0' ) )
GET_UTF8_CHAR( dummy, q );
len = (int)( q - p );
/* feed character(s) to the HarfBuzz buffer */
hb_buffer_clear_contents( buf );
hb_buffer_add_utf8( buf, p, len, 0, len );
/* we let HarfBuzz guess the script and writing direction */
hb_buffer_guess_segment_properties( buf );
/* shape buffer, which means conversion from character codes to */
/* glyph indices, possibly applying a feature */
hb_shape( font, buf, feature, feature ? 1 : 0 );
if ( feature )
{
hb_buffer_t* hb_buf = metrics->globals->hb_buf;
unsigned int gcount;
hb_glyph_info_t* ginfo;
unsigned int hb_gcount;
hb_glyph_info_t* hb_ginfo;
/* we have to check whether applying a feature does actually change */
/* glyph indices; otherwise the affected glyph or glyphs aren't */
/* available at all in the feature */
hb_buffer_clear_contents( hb_buf );
hb_buffer_add_utf8( hb_buf, p, len, 0, len );
hb_buffer_guess_segment_properties( hb_buf );
hb_shape( font, hb_buf, NULL, 0 );
ginfo = hb_buffer_get_glyph_infos( buf, &gcount );
hb_ginfo = hb_buffer_get_glyph_infos( hb_buf, &hb_gcount );
if ( gcount == hb_gcount )
{
unsigned int i;
for (i = 0; i < gcount; i++ )
if ( ginfo[i].codepoint != hb_ginfo[i].codepoint )
break;
if ( i == gcount )
{
/* both buffers have identical glyph indices */
hb_buffer_clear_contents( buf );
}
}
}
*count = hb_buffer_get_length( buf );
#ifdef FT_DEBUG_LEVEL_TRACE
if ( feature && *count > 1 )
FT_TRACE1(( "af_shaper_get_cluster:"
" input character mapped to multiple glyphs\n" ));
#endif
return q;
}
FT_ULong
af_shaper_get_elem( AF_StyleMetrics metrics,
void* buf_,
unsigned int idx,
FT_Long* advance,
FT_Long* y_offset )
{
hb_buffer_t* buf = (hb_buffer_t*)buf_;
hb_glyph_info_t* ginfo;
hb_glyph_position_t* gpos;
unsigned int gcount;
FT_UNUSED( metrics );
ginfo = hb_buffer_get_glyph_infos( buf, &gcount );
gpos = hb_buffer_get_glyph_positions( buf, &gcount );
if ( idx >= gcount )
return 0;
if ( advance )
*advance = gpos[idx].x_advance;
if ( y_offset )
*y_offset = gpos[idx].y_offset;
return ginfo[idx].codepoint;
}
#else /* !FT_CONFIG_OPTION_USE_HARFBUZZ */
FT_Error
af_shaper_get_coverage( AF_FaceGlobals globals,
AF_StyleClass style_class,
FT_UShort* gstyles,
FT_Bool default_script )
{
FT_UNUSED( globals );
FT_UNUSED( style_class );
FT_UNUSED( gstyles );
FT_UNUSED( default_script );
return FT_Err_Ok;
}
void*
af_shaper_buf_create( FT_Face face )
{
FT_UNUSED( face );
return NULL;
}
void
af_shaper_buf_destroy( FT_Face face,
void* buf )
{
FT_UNUSED( face );
FT_UNUSED( buf );
}
const char*
af_shaper_get_cluster( const char* p,
AF_StyleMetrics metrics,
void* buf_,
unsigned int* count )
{
FT_Face face = metrics->globals->face;
FT_ULong ch, dummy = 0;
FT_ULong* buf = (FT_ULong*)buf_;
while ( *p == ' ' )
p++;
GET_UTF8_CHAR( ch, p );
/* since we don't have an engine to handle clusters, */
/* we scan the characters but return zero */
while ( !( *p == ' ' || *p == '\0' ) )
GET_UTF8_CHAR( dummy, p );
if ( dummy )
{
*buf = 0;
*count = 0;
}
else
{
*buf = FT_Get_Char_Index( face, ch );
*count = 1;
}
return p;
}
FT_ULong
af_shaper_get_elem( AF_StyleMetrics metrics,
void* buf_,
unsigned int idx,
FT_Long* advance,
FT_Long* y_offset )
{
FT_Face face = metrics->globals->face;
FT_ULong glyph_index = *(FT_ULong*)buf_;
FT_UNUSED( idx );
if ( advance )
FT_Get_Advance( face,
glyph_index,
FT_LOAD_NO_SCALE |
FT_LOAD_NO_HINTING |
FT_LOAD_IGNORE_TRANSFORM,
advance );
if ( y_offset )
*y_offset = 0;
return glyph_index;
}
#endif /* !FT_CONFIG_OPTION_USE_HARFBUZZ */
/* END */

View File

@@ -0,0 +1,71 @@
/****************************************************************************
*
* afshaper.h
*
* HarfBuzz interface for accessing OpenType features (specification).
*
* Copyright (C) 2013-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#ifndef AFSHAPER_H_
#define AFSHAPER_H_
#include <freetype/freetype.h>
#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
#include <hb.h>
#include <hb-ot.h>
#include "ft-hb.h"
#endif
FT_BEGIN_HEADER
FT_Error
af_shaper_get_coverage( AF_FaceGlobals globals,
AF_StyleClass style_class,
FT_UShort* gstyles,
FT_Bool default_script );
void*
af_shaper_buf_create( FT_Face face );
void
af_shaper_buf_destroy( FT_Face face,
void* buf );
const char*
af_shaper_get_cluster( const char* p,
AF_StyleMetrics metrics,
void* buf_,
unsigned int* count );
FT_ULong
af_shaper_get_elem( AF_StyleMetrics metrics,
void* buf_,
unsigned int idx,
FT_Long* x_advance,
FT_Long* y_offset );
/* */
FT_END_HEADER
#endif /* AFSHAPER_H_ */
/* END */

View File

@@ -0,0 +1,487 @@
/****************************************************************************
*
* afstyles.h
*
* Auto-fitter styles (specification only).
*
* Copyright (C) 2013-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
/* The following part can be included multiple times. */
/* Define `STYLE' as needed. */
/* Add new styles here. The first and second arguments are the */
/* style name in lowercase and uppercase, respectively, followed */
/* by a description string. The next arguments are the */
/* corresponding writing system, script, blue stringset, and */
/* coverage. */
/* */
/* Note that styles using `AF_COVERAGE_DEFAULT' should always */
/* come after styles with other coverages. Also note that */
/* fallback scripts only use `AF_COVERAGE_DEFAULT' for its */
/* style. */
/* */
/* Example: */
/* */
/* STYLE( cyrl_dflt, CYRL_DFLT, */
/* "Cyrillic default style", */
/* AF_WRITING_SYSTEM_LATIN, */
/* AF_SCRIPT_CYRL, */
/* AF_BLUE_STRINGSET_CYRL, */
/* AF_COVERAGE_DEFAULT ) */
#undef STYLE_LATIN
#define STYLE_LATIN( s, S, f, F, ds, df, C ) \
STYLE( s ## _ ## f, S ## _ ## F, \
ds " " df " style", \
AF_WRITING_SYSTEM_LATIN, \
AF_SCRIPT_ ## S, \
AF_BLUE_STRINGSET_ ## S, \
AF_COVERAGE_ ## C )
#undef META_STYLE_LATIN
#define META_STYLE_LATIN( s, S, ds ) \
STYLE_LATIN( s, S, c2cp, C2CP, ds, \
"petite capitals from capitals", \
PETITE_CAPITALS_FROM_CAPITALS ) \
STYLE_LATIN( s, S, c2sc, C2SC, ds, \
"small capitals from capitals", \
SMALL_CAPITALS_FROM_CAPITALS ) \
STYLE_LATIN( s, S, ordn, ORDN, ds, \
"ordinals", \
ORDINALS ) \
STYLE_LATIN( s, S, pcap, PCAP, ds, \
"petite capitals", \
PETITE_CAPITALS ) \
STYLE_LATIN( s, S, sinf, SINF, ds, \
"scientific inferiors", \
SCIENTIFIC_INFERIORS ) \
STYLE_LATIN( s, S, smcp, SMCP, ds, \
"small capitals", \
SMALL_CAPITALS ) \
STYLE_LATIN( s, S, subs, SUBS, ds, \
"subscript", \
SUBSCRIPT ) \
STYLE_LATIN( s, S, sups, SUPS, ds, \
"superscript", \
SUPERSCRIPT ) \
STYLE_LATIN( s, S, titl, TITL, ds, \
"titling", \
TITLING ) \
STYLE_LATIN( s, S, dflt, DFLT, ds, \
"default", \
DEFAULT )
STYLE( adlm_dflt, ADLM_DFLT,
"Adlam default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_ADLM,
AF_BLUE_STRINGSET_ADLM,
AF_COVERAGE_DEFAULT )
STYLE( arab_dflt, ARAB_DFLT,
"Arabic default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_ARAB,
AF_BLUE_STRINGSET_ARAB,
AF_COVERAGE_DEFAULT )
STYLE( armn_dflt, ARMN_DFLT,
"Armenian default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_ARMN,
AF_BLUE_STRINGSET_ARMN,
AF_COVERAGE_DEFAULT )
STYLE( avst_dflt, AVST_DFLT,
"Avestan default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_AVST,
AF_BLUE_STRINGSET_AVST,
AF_COVERAGE_DEFAULT )
STYLE( bamu_dflt, BAMU_DFLT,
"Bamum default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_BAMU,
AF_BLUE_STRINGSET_BAMU,
AF_COVERAGE_DEFAULT )
STYLE( beng_dflt, BENG_DFLT,
"Bengali default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_BENG,
AF_BLUE_STRINGSET_BENG,
AF_COVERAGE_DEFAULT )
STYLE( buhd_dflt, BUHD_DFLT,
"Buhid default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_BUHD,
AF_BLUE_STRINGSET_BUHD,
AF_COVERAGE_DEFAULT )
STYLE( cakm_dflt, CAKM_DFLT,
"Chakma default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_CAKM,
AF_BLUE_STRINGSET_CAKM,
AF_COVERAGE_DEFAULT )
STYLE( cans_dflt, CANS_DFLT,
"Canadian Syllabics default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_CANS,
AF_BLUE_STRINGSET_CANS,
AF_COVERAGE_DEFAULT )
STYLE( cari_dflt, CARI_DFLT,
"Carian default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_CARI,
AF_BLUE_STRINGSET_CARI,
AF_COVERAGE_DEFAULT )
STYLE( cher_dflt, CHER_DFLT,
"Cherokee default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_CHER,
AF_BLUE_STRINGSET_CHER,
AF_COVERAGE_DEFAULT )
STYLE( copt_dflt, COPT_DFLT,
"Coptic default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_COPT,
AF_BLUE_STRINGSET_COPT,
AF_COVERAGE_DEFAULT )
STYLE( cprt_dflt, CPRT_DFLT,
"Cypriot default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_CPRT,
AF_BLUE_STRINGSET_CPRT,
AF_COVERAGE_DEFAULT )
META_STYLE_LATIN( cyrl, CYRL, "Cyrillic" )
STYLE( deva_dflt, DEVA_DFLT,
"Devanagari default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_DEVA,
AF_BLUE_STRINGSET_DEVA,
AF_COVERAGE_DEFAULT )
STYLE( dsrt_dflt, DSRT_DFLT,
"Deseret default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_DSRT,
AF_BLUE_STRINGSET_DSRT,
AF_COVERAGE_DEFAULT )
STYLE( ethi_dflt, ETHI_DFLT,
"Ethiopic default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_ETHI,
AF_BLUE_STRINGSET_ETHI,
AF_COVERAGE_DEFAULT )
STYLE( geor_dflt, GEOR_DFLT,
"Georgian (Mkhedruli) default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_GEOR,
AF_BLUE_STRINGSET_GEOR,
AF_COVERAGE_DEFAULT )
STYLE( geok_dflt, GEOK_DFLT,
"Georgian (Khutsuri) default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_GEOK,
AF_BLUE_STRINGSET_GEOK,
AF_COVERAGE_DEFAULT )
STYLE( glag_dflt, GLAG_DFLT,
"Glagolitic default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_GLAG,
AF_BLUE_STRINGSET_GLAG,
AF_COVERAGE_DEFAULT )
STYLE( goth_dflt, GOTH_DFLT,
"Gothic default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_GOTH,
AF_BLUE_STRINGSET_GOTH,
AF_COVERAGE_DEFAULT )
META_STYLE_LATIN( grek, GREK, "Greek" )
STYLE( gujr_dflt, GUJR_DFLT,
"Gujarati default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_GUJR,
AF_BLUE_STRINGSET_GUJR,
AF_COVERAGE_DEFAULT )
STYLE( guru_dflt, GURU_DFLT,
"Gurmukhi default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_GURU,
AF_BLUE_STRINGSET_GURU,
AF_COVERAGE_DEFAULT )
STYLE( hebr_dflt, HEBR_DFLT,
"Hebrew default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_HEBR,
AF_BLUE_STRINGSET_HEBR,
AF_COVERAGE_DEFAULT )
STYLE( kali_dflt, KALI_DFLT,
"Kayah Li default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_KALI,
AF_BLUE_STRINGSET_KALI,
AF_COVERAGE_DEFAULT )
STYLE( khmr_dflt, KHMR_DFLT,
"Khmer default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_KHMR,
AF_BLUE_STRINGSET_KHMR,
AF_COVERAGE_DEFAULT )
STYLE( khms_dflt, KHMS_DFLT,
"Khmer Symbols default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_KHMS,
AF_BLUE_STRINGSET_KHMS,
AF_COVERAGE_DEFAULT )
STYLE( knda_dflt, KNDA_DFLT,
"Kannada default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_KNDA,
AF_BLUE_STRINGSET_KNDA,
AF_COVERAGE_DEFAULT )
STYLE( lao_dflt, LAO_DFLT,
"Lao default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_LAO,
AF_BLUE_STRINGSET_LAO,
AF_COVERAGE_DEFAULT )
META_STYLE_LATIN( latn, LATN, "Latin" )
STYLE( latb_dflt, LATB_DFLT,
"Latin subscript fallback default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_LATB,
AF_BLUE_STRINGSET_LATB,
AF_COVERAGE_DEFAULT )
STYLE( latp_dflt, LATP_DFLT,
"Latin superscript fallback default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_LATP,
AF_BLUE_STRINGSET_LATP,
AF_COVERAGE_DEFAULT )
STYLE( lisu_dflt, LISU_DFLT,
"Lisu default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_LISU,
AF_BLUE_STRINGSET_LISU,
AF_COVERAGE_DEFAULT )
STYLE( mlym_dflt, MLYM_DFLT,
"Malayalam default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_MLYM,
AF_BLUE_STRINGSET_MLYM,
AF_COVERAGE_DEFAULT )
STYLE( medf_dflt, MEDF_DFLT,
"Medefaidrin default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_MEDF,
AF_BLUE_STRINGSET_MEDF,
AF_COVERAGE_DEFAULT )
STYLE( mong_dflt, MONG_DFLT,
"Mongolian default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_MONG,
AF_BLUE_STRINGSET_MONG,
AF_COVERAGE_DEFAULT )
STYLE( mymr_dflt, MYMR_DFLT,
"Myanmar default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_MYMR,
AF_BLUE_STRINGSET_MYMR,
AF_COVERAGE_DEFAULT )
STYLE( nkoo_dflt, NKOO_DFLT,
"N'Ko default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_NKOO,
AF_BLUE_STRINGSET_NKOO,
AF_COVERAGE_DEFAULT )
STYLE( none_dflt, NONE_DFLT,
"no style",
AF_WRITING_SYSTEM_DUMMY,
AF_SCRIPT_NONE,
AF_BLUE_STRINGSET_NONE,
AF_COVERAGE_DEFAULT )
STYLE( olck_dflt, OLCK_DFLT,
"Ol Chiki default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_OLCK,
AF_BLUE_STRINGSET_OLCK,
AF_COVERAGE_DEFAULT )
STYLE( orkh_dflt, ORKH_DFLT,
"Old Turkic default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_ORKH,
AF_BLUE_STRINGSET_ORKH,
AF_COVERAGE_DEFAULT )
STYLE( osge_dflt, OSGE_DFLT,
"Osage default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_OSGE,
AF_BLUE_STRINGSET_OSGE,
AF_COVERAGE_DEFAULT )
STYLE( osma_dflt, OSMA_DFLT,
"Osmanya default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_OSMA,
AF_BLUE_STRINGSET_OSMA,
AF_COVERAGE_DEFAULT )
STYLE( rohg_dflt, ROHG_DFLT,
"Hanifi Rohingya default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_ROHG,
AF_BLUE_STRINGSET_ROHG,
AF_COVERAGE_DEFAULT )
STYLE( saur_dflt, SAUR_DFLT,
"Saurashtra default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_SAUR,
AF_BLUE_STRINGSET_SAUR,
AF_COVERAGE_DEFAULT )
STYLE( shaw_dflt, SHAW_DFLT,
"Shavian default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_SHAW,
AF_BLUE_STRINGSET_SHAW,
AF_COVERAGE_DEFAULT )
STYLE( sinh_dflt, SINH_DFLT,
"Sinhala default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_SINH,
AF_BLUE_STRINGSET_SINH,
AF_COVERAGE_DEFAULT )
STYLE( sund_dflt, SUND_DFLT,
"Sundanese default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_SUND,
AF_BLUE_STRINGSET_SUND,
AF_COVERAGE_DEFAULT )
STYLE( taml_dflt, TAML_DFLT,
"Tamil default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_TAML,
AF_BLUE_STRINGSET_TAML,
AF_COVERAGE_DEFAULT )
STYLE( tavt_dflt, TAVT_DFLT,
"Tai Viet default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_TAVT,
AF_BLUE_STRINGSET_TAVT,
AF_COVERAGE_DEFAULT )
STYLE( telu_dflt, TELU_DFLT,
"Telugu default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_TELU,
AF_BLUE_STRINGSET_TELU,
AF_COVERAGE_DEFAULT )
STYLE( tfng_dflt, TFNG_DFLT,
"Tifinagh default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_TFNG,
AF_BLUE_STRINGSET_TFNG,
AF_COVERAGE_DEFAULT )
STYLE( thai_dflt, THAI_DFLT,
"Thai default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_THAI,
AF_BLUE_STRINGSET_THAI,
AF_COVERAGE_DEFAULT )
STYLE( vaii_dflt, VAII_DFLT,
"Vai default style",
AF_WRITING_SYSTEM_LATIN,
AF_SCRIPT_VAII,
AF_BLUE_STRINGSET_VAII,
AF_COVERAGE_DEFAULT )
#ifdef AF_CONFIG_OPTION_INDIC
/* no blue stringset support for the Indic writing system yet */
#undef STYLE_DEFAULT_INDIC
#define STYLE_DEFAULT_INDIC( s, S, d ) \
STYLE( s ## _dflt, S ## _DFLT, \
d " default style", \
AF_WRITING_SYSTEM_INDIC, \
AF_SCRIPT_ ## S, \
(AF_Blue_Stringset)0, \
AF_COVERAGE_DEFAULT )
STYLE_DEFAULT_INDIC( limb, LIMB, "Limbu" )
STYLE_DEFAULT_INDIC( orya, ORYA, "Oriya" )
STYLE_DEFAULT_INDIC( sylo, SYLO, "Syloti Nagri" )
STYLE_DEFAULT_INDIC( tibt, TIBT, "Tibetan" )
#endif /* AF_CONFIG_OPTION_INDIC */
#ifdef AF_CONFIG_OPTION_CJK
STYLE( hani_dflt, HANI_DFLT,
"CJKV ideographs default style",
AF_WRITING_SYSTEM_CJK,
AF_SCRIPT_HANI,
AF_BLUE_STRINGSET_HANI,
AF_COVERAGE_DEFAULT )
#endif /* AF_CONFIG_OPTION_CJK */
/* END */

View File

@@ -0,0 +1,511 @@
/****************************************************************************
*
* aftypes.h
*
* Auto-fitter types (specification only).
*
* Copyright (C) 2003-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
/*************************************************************************
*
* The auto-fitter is a complete rewrite of the old auto-hinter.
* Its main feature is the ability to differentiate between different
* writing systems and scripts in order to apply specific rules.
*
* The code has also been compartmentalized into several entities that
* should make algorithmic experimentation easier than with the old
* code.
*
*************************************************************************/
#ifndef AFTYPES_H_
#define AFTYPES_H_
#include <freetype/freetype.h>
#include <freetype/ftoutln.h>
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/ftdebug.h>
#include "afblue.h"
#ifdef FT_DEBUG_AUTOFIT
#include FT_CONFIG_STANDARD_LIBRARY_H
#endif
FT_BEGIN_HEADER
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** D E B U G G I N G *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
#ifdef FT_DEBUG_AUTOFIT
extern int af_debug_disable_horz_hints_;
extern int af_debug_disable_vert_hints_;
extern int af_debug_disable_blue_hints_;
extern void* af_debug_hints_;
#endif /* FT_DEBUG_AUTOFIT */
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** U T I L I T Y S T U F F *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
typedef struct AF_WidthRec_
{
FT_Pos org; /* original position/width in font units */
FT_Pos cur; /* current/scaled position/width in device subpixels */
FT_Pos fit; /* current/fitted position/width in device subpixels */
} AF_WidthRec, *AF_Width;
FT_LOCAL( void )
af_sort_pos( FT_UInt count,
FT_Pos* table );
FT_LOCAL( void )
af_sort_and_quantize_widths( FT_UInt* count,
AF_Width widths,
FT_Pos threshold );
/*
* opaque handle to glyph-specific hints -- see `afhints.h' for more
* details
*/
typedef struct AF_GlyphHintsRec_* AF_GlyphHints;
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** S C A L E R S *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*
* A scaler models the target pixel device that will receive the
* auto-hinted glyph image.
*/
#define AF_SCALER_FLAG_NO_HORIZONTAL 1U /* disable horizontal hinting */
#define AF_SCALER_FLAG_NO_VERTICAL 2U /* disable vertical hinting */
#define AF_SCALER_FLAG_NO_ADVANCE 4U /* disable advance hinting */
typedef struct AF_ScalerRec_
{
FT_Face face; /* source font face */
FT_Fixed x_scale; /* from font units to 1/64 device pixels */
FT_Fixed y_scale; /* from font units to 1/64 device pixels */
FT_Pos x_delta; /* in 1/64 device pixels */
FT_Pos y_delta; /* in 1/64 device pixels */
FT_Render_Mode render_mode; /* monochrome, anti-aliased, LCD, etc. */
FT_UInt32 flags; /* additional control flags, see above */
} AF_ScalerRec, *AF_Scaler;
#define AF_SCALER_EQUAL_SCALES( a, b ) \
( (a)->x_scale == (b)->x_scale && \
(a)->y_scale == (b)->y_scale && \
(a)->x_delta == (b)->x_delta && \
(a)->y_delta == (b)->y_delta )
typedef struct AF_StyleMetricsRec_* AF_StyleMetrics;
/*
* This function parses an FT_Face to compute global metrics for
* a specific style.
*/
typedef FT_Error
(*AF_WritingSystem_InitMetricsFunc)( AF_StyleMetrics metrics,
FT_Face face );
typedef void
(*AF_WritingSystem_ScaleMetricsFunc)( AF_StyleMetrics metrics,
AF_Scaler scaler );
typedef void
(*AF_WritingSystem_DoneMetricsFunc)( AF_StyleMetrics metrics );
typedef void
(*AF_WritingSystem_GetStdWidthsFunc)( AF_StyleMetrics metrics,
FT_Pos* stdHW,
FT_Pos* stdVW );
typedef FT_Error
(*AF_WritingSystem_InitHintsFunc)( AF_GlyphHints hints,
AF_StyleMetrics metrics );
typedef FT_Error
(*AF_WritingSystem_ApplyHintsFunc)( FT_UInt glyph_index,
AF_GlyphHints hints,
FT_Outline* outline,
AF_StyleMetrics metrics );
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** W R I T I N G S Y S T E M S *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*
* For the auto-hinter, a writing system consists of multiple scripts that
* can be handled similarly *in a typographical way*; the relationship is
* not based on history. For example, both the Greek and the unrelated
* Armenian scripts share the same features like ascender, descender,
* x-height, etc. Essentially, a writing system is covered by a
* submodule of the auto-fitter; it contains
*
* - a specific global analyzer that computes global metrics specific to
* the script (based on script-specific characters to identify ascender
* height, x-height, etc.),
*
* - a specific glyph analyzer that computes segments and edges for each
* glyph covered by the script,
*
* - a specific grid-fitting algorithm that distorts the scaled glyph
* outline according to the results of the glyph analyzer.
*/
#undef WRITING_SYSTEM
#define WRITING_SYSTEM( ws, WS ) \
AF_WRITING_SYSTEM_ ## WS,
/* The list of known writing systems. */
typedef enum AF_WritingSystem_
{
#include "afws-iter.h"
AF_WRITING_SYSTEM_MAX /* do not remove */
} AF_WritingSystem;
typedef struct AF_WritingSystemClassRec_
{
AF_WritingSystem writing_system;
FT_Offset style_metrics_size;
AF_WritingSystem_InitMetricsFunc style_metrics_init;
AF_WritingSystem_ScaleMetricsFunc style_metrics_scale;
AF_WritingSystem_DoneMetricsFunc style_metrics_done;
AF_WritingSystem_GetStdWidthsFunc style_metrics_getstdw;
AF_WritingSystem_InitHintsFunc style_hints_init;
AF_WritingSystem_ApplyHintsFunc style_hints_apply;
} AF_WritingSystemClassRec;
typedef const AF_WritingSystemClassRec* AF_WritingSystemClass;
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** S C R I P T S *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*
* Each script is associated with two sets of Unicode ranges to test
* whether the font face supports the script, and which non-base
* characters the script contains.
*
* We use four-letter script tags from the OpenType specification,
* extended by `NONE', which indicates `no script'.
*/
#undef SCRIPT
#define SCRIPT( s, S, d, h, H, ss ) \
AF_SCRIPT_ ## S,
/* The list of known scripts. */
typedef enum AF_Script_
{
#include "afscript.h"
AF_SCRIPT_MAX /* do not remove */
} AF_Script;
typedef struct AF_Script_UniRangeRec_
{
FT_UInt32 first;
FT_UInt32 last;
} AF_Script_UniRangeRec;
#define AF_UNIRANGE_REC( a, b ) { (FT_UInt32)(a), (FT_UInt32)(b) }
typedef const AF_Script_UniRangeRec* AF_Script_UniRange;
typedef struct AF_ScriptClassRec_
{
AF_Script script;
/* last element in the ranges must be { 0, 0 } */
AF_Script_UniRange script_uni_ranges;
AF_Script_UniRange script_uni_nonbase_ranges;
FT_Bool top_to_bottom_hinting;
const char* standard_charstring; /* for default width and height */
} AF_ScriptClassRec;
typedef const AF_ScriptClassRec* AF_ScriptClass;
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** C O V E R A G E S *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*
* Usually, a font contains more glyphs than can be addressed by its
* character map.
*
* In the PostScript font world, encoding vectors specific to a given
* task are used to select such glyphs, and these glyphs can be often
* recognized by having a suffix in its glyph names. For example, a
* superscript glyph `A' might be called `A.sup'. Unfortunately, this
* naming scheme is not standardized and thus unusable for us.
*
* In the OpenType world, a better solution was invented, namely
* `features', which cleanly separate a character's input encoding from
* the corresponding glyph's appearance, and which don't use glyph names
* at all. For our purposes, and slightly generalized, an OpenType
* feature is a name of a mapping that maps character codes to
* non-standard glyph indices (features get used for other things also).
* For example, the `sups' feature provides superscript glyphs, thus
* mapping character codes like `A' or `B' to superscript glyph
* representation forms. How this mapping happens is completely
* uninteresting to us.
*
* For the auto-hinter, a `coverage' represents all glyphs of an OpenType
* feature collected in a set (as listed below) that can be hinted
* together. To continue the above example, superscript glyphs must not
* be hinted together with normal glyphs because the blue zones
* completely differ.
*
* Note that FreeType itself doesn't compute coverages; it only provides
* the glyphs addressable by the default Unicode character map. Instead,
* we use the HarfBuzz library (if available), which has many functions
* exactly for this purpose.
*
* AF_COVERAGE_DEFAULT is special: It should cover everything that isn't
* listed separately (including the glyphs addressable by the character
* map). In case HarfBuzz isn't available, it exactly covers the glyphs
* addressable by the character map.
*
*/
#undef COVERAGE
#define COVERAGE( name, NAME, description, \
tag1, tag2, tag3, tag4 ) \
AF_COVERAGE_ ## NAME,
typedef enum AF_Coverage_
{
#include "afcover.h"
AF_COVERAGE_DEFAULT
} AF_Coverage;
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** S T Y L E S *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*
* The topmost structure for modelling the auto-hinter glyph input data
* is a `style class', grouping everything together.
*/
#undef STYLE
#define STYLE( s, S, d, ws, sc, ss, c ) \
AF_STYLE_ ## S,
/* The list of known styles. */
typedef enum AF_Style_
{
#include "afstyles.h"
AF_STYLE_MAX /* do not remove */
} AF_Style;
typedef struct AF_StyleClassRec_
{
AF_Style style;
AF_WritingSystem writing_system;
AF_Script script;
AF_Blue_Stringset blue_stringset;
AF_Coverage coverage;
} AF_StyleClassRec;
typedef const AF_StyleClassRec* AF_StyleClass;
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** S T Y L E M E T R I C S *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
typedef struct AF_FaceGlobalsRec_* AF_FaceGlobals;
/* This is the main structure that combines everything. Autofit modules */
/* specific to writing systems derive their structures from it, for */
/* example `AF_LatinMetrics'. */
typedef struct AF_StyleMetricsRec_
{
AF_StyleClass style_class;
AF_ScalerRec scaler;
FT_Bool digits_have_same_width;
AF_FaceGlobals globals; /* to access properties */
} AF_StyleMetricsRec;
#define AF_HINTING_BOTTOM_TO_TOP 0
#define AF_HINTING_TOP_TO_BOTTOM 1
/* Declare and define vtables for classes */
#define AF_DECLARE_WRITING_SYSTEM_CLASS( writing_system_class ) \
FT_CALLBACK_TABLE const AF_WritingSystemClassRec \
writing_system_class;
#define AF_DEFINE_WRITING_SYSTEM_CLASS( \
writing_system_class, \
system, \
m_size, \
m_init, \
m_scale, \
m_done, \
m_stdw, \
h_init, \
h_apply ) \
FT_CALLBACK_TABLE_DEF \
const AF_WritingSystemClassRec writing_system_class = \
{ \
system, \
\
m_size, \
\
m_init, \
m_scale, \
m_done, \
m_stdw, \
\
h_init, \
h_apply \
};
#define AF_DECLARE_SCRIPT_CLASS( script_class ) \
FT_CALLBACK_TABLE const AF_ScriptClassRec \
script_class;
#define AF_DEFINE_SCRIPT_CLASS( \
script_class, \
script, \
ranges, \
nonbase_ranges, \
top_to_bottom, \
std_charstring ) \
FT_CALLBACK_TABLE_DEF \
const AF_ScriptClassRec script_class = \
{ \
script, \
ranges, \
nonbase_ranges, \
top_to_bottom, \
std_charstring, \
};
#define AF_DECLARE_STYLE_CLASS( style_class ) \
FT_CALLBACK_TABLE const AF_StyleClassRec \
style_class;
#define AF_DEFINE_STYLE_CLASS( \
style_class, \
style, \
writing_system, \
script, \
blue_stringset, \
coverage ) \
FT_CALLBACK_TABLE_DEF \
const AF_StyleClassRec style_class = \
{ \
style, \
writing_system, \
script, \
blue_stringset, \
coverage \
};
/* */
FT_END_HEADER
#endif /* AFTYPES_H_ */
/* END */

View File

@@ -0,0 +1,33 @@
/****************************************************************************
*
* afws-decl.h
*
* Auto-fitter writing system declarations (specification only).
*
* Copyright (C) 2013-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#ifndef AFWS_DECL_H_
#define AFWS_DECL_H_
/* Since preprocessor directives can't create other preprocessor */
/* directives, we have to include the header files manually. */
#include "afdummy.h"
#include "aflatin.h"
#include "afcjk.h"
#include "afindic.h"
#endif /* AFWS_DECL_H_ */
/* END */

View File

@@ -0,0 +1,31 @@
/****************************************************************************
*
* afws-iter.h
*
* Auto-fitter writing systems iterator (specification only).
*
* Copyright (C) 2013-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
/* This header may be included multiple times. */
/* Define `WRITING_SYSTEM' as needed. */
/* Add new writing systems here. The arguments are the writing system */
/* name in lowercase and uppercase, respectively. */
WRITING_SYSTEM( dummy, DUMMY )
WRITING_SYSTEM( latin, LATIN )
WRITING_SYSTEM( cjk, CJK )
WRITING_SYSTEM( indic, INDIC )
/* END */

View File

@@ -0,0 +1,35 @@
/****************************************************************************
*
* autofit.c
*
* Auto-fitter module (body).
*
* Copyright (C) 2003-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#define FT_MAKE_OPTION_SINGLE_OBJECT
#include "ft-hb.c"
#include "afblue.c"
#include "afcjk.c"
#include "afdummy.c"
#include "afglobal.c"
#include "afhints.c"
#include "afindic.c"
#include "aflatin.c"
#include "afloader.c"
#include "afmodule.c"
#include "afranges.c"
#include "afshaper.c"
/* END */

115
thirdparty/freetype/src/autofit/ft-hb.c vendored Normal file
View File

@@ -0,0 +1,115 @@
/*
* Copyright © 2009, 2023 Red Hat, Inc.
* Copyright © 2015 Google, Inc.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Red Hat Author(s): Behdad Esfahbod, Matthias Clasen
* Google Author(s): Behdad Esfahbod
*/
#include <freetype/freetype.h>
#include <freetype/tttables.h>
#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
#include "ft-hb.h"
/* The following three functions are a more or less verbatim
* copy of corresponding HarfBuzz code from hb-ft.cc
*/
static hb_blob_t *
hb_ft_reference_table_ (hb_face_t *face, hb_tag_t tag, void *user_data)
{
FT_Face ft_face = (FT_Face) user_data;
FT_Byte *buffer;
FT_ULong length = 0;
FT_Error error;
FT_UNUSED (face);
/* Note: FreeType like HarfBuzz uses the NONE tag for fetching the entire blob */
error = FT_Load_Sfnt_Table (ft_face, tag, 0, NULL, &length);
if (error)
return NULL;
buffer = (FT_Byte *) ft_smalloc (length);
if (!buffer)
return NULL;
error = FT_Load_Sfnt_Table (ft_face, tag, 0, buffer, &length);
if (error)
{
free (buffer);
return NULL;
}
return hb_blob_create ((const char *) buffer, length,
HB_MEMORY_MODE_WRITABLE,
buffer, ft_sfree);
}
static hb_face_t *
hb_ft_face_create_ (FT_Face ft_face,
hb_destroy_func_t destroy)
{
hb_face_t *face;
if (!ft_face->stream->read) {
hb_blob_t *blob;
blob = hb_blob_create ((const char *) ft_face->stream->base,
(unsigned int) ft_face->stream->size,
HB_MEMORY_MODE_READONLY,
ft_face, destroy);
face = hb_face_create (blob, ft_face->face_index);
hb_blob_destroy (blob);
} else {
face = hb_face_create_for_tables (hb_ft_reference_table_, ft_face, destroy);
}
hb_face_set_index (face, ft_face->face_index);
hb_face_set_upem (face, ft_face->units_per_EM);
return face;
}
FT_LOCAL_DEF(hb_font_t *)
hb_ft_font_create_ (FT_Face ft_face,
hb_destroy_func_t destroy)
{
hb_font_t *font;
hb_face_t *face;
face = hb_ft_face_create_ (ft_face, destroy);
font = hb_font_create (face);
hb_face_destroy (face);
return font;
}
#else /* !FT_CONFIG_OPTION_USE_HARFBUZZ */
/* ANSI C doesn't like empty source files */
typedef int ft_hb_dummy_;
#endif /* !FT_CONFIG_OPTION_USE_HARFBUZZ */
/* END */

48
thirdparty/freetype/src/autofit/ft-hb.h vendored Normal file
View File

@@ -0,0 +1,48 @@
/*
* Copyright © 2009, 2023 Red Hat, Inc.
* Copyright © 2015 Google, Inc.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Red Hat Author(s): Behdad Esfahbod, Matthias Clasen
* Google Author(s): Behdad Esfahbod
*/
#ifndef FT_HB_H
#define FT_HB_H
#include <hb.h>
#include <freetype/internal/compiler-macros.h>
#include <freetype/freetype.h>
FT_BEGIN_HEADER
FT_LOCAL(hb_font_t *)
hb_ft_font_create_ (FT_Face ft_face,
hb_destroy_func_t destroy);
FT_END_HEADER
#endif /* FT_HB_H */
/* END */

174
thirdparty/freetype/src/base/ftadvanc.c vendored Normal file
View File

@@ -0,0 +1,174 @@
/****************************************************************************
*
* ftadvanc.c
*
* Quick computation of advance widths (body).
*
* Copyright (C) 2008-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/internal/ftdebug.h>
#include <freetype/ftadvanc.h>
#include <freetype/internal/ftobjs.h>
static FT_Error
ft_face_scale_advances_( FT_Face face,
FT_Fixed* advances,
FT_UInt count,
FT_Int32 flags )
{
FT_Fixed scale;
FT_UInt nn;
if ( flags & FT_LOAD_NO_SCALE )
return FT_Err_Ok;
if ( !face->size )
return FT_THROW( Invalid_Size_Handle );
if ( flags & FT_LOAD_VERTICAL_LAYOUT )
scale = face->size->metrics.y_scale;
else
scale = face->size->metrics.x_scale;
/* this must be the same scaling as to get linear{Hori,Vert}Advance */
/* (see `FT_Load_Glyph' implementation in src/base/ftobjs.c) */
for ( nn = 0; nn < count; nn++ )
advances[nn] = FT_MulDiv( advances[nn], scale, 64 );
return FT_Err_Ok;
}
/* at the moment, we can perform fast advance retrieval only in */
/* the following cases: */
/* */
/* - unscaled load */
/* - unhinted load */
/* - light-hinted load */
/* - if a variations font, it must have an `HVAR' or `VVAR' */
/* table (thus the old MM or GX fonts don't qualify; this */
/* gets checked by the driver-specific functions) */
#define LOAD_ADVANCE_FAST_CHECK( face, flags ) \
( flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) || \
FT_LOAD_TARGET_MODE( flags ) == FT_RENDER_MODE_LIGHT )
/* documentation is in ftadvanc.h */
FT_EXPORT_DEF( FT_Error )
FT_Get_Advance( FT_Face face,
FT_UInt gindex,
FT_Int32 flags,
FT_Fixed *padvance )
{
FT_Face_GetAdvancesFunc func;
if ( !face )
return FT_THROW( Invalid_Face_Handle );
if ( !padvance )
return FT_THROW( Invalid_Argument );
if ( gindex >= (FT_UInt)face->num_glyphs )
return FT_THROW( Invalid_Glyph_Index );
func = face->driver->clazz->get_advances;
if ( func && LOAD_ADVANCE_FAST_CHECK( face, flags ) )
{
FT_Error error;
error = func( face, gindex, 1, flags, padvance );
if ( !error )
return ft_face_scale_advances_( face, padvance, 1, flags );
if ( FT_ERR_NEQ( error, Unimplemented_Feature ) )
return error;
}
return FT_Get_Advances( face, gindex, 1, flags, padvance );
}
/* documentation is in ftadvanc.h */
FT_EXPORT_DEF( FT_Error )
FT_Get_Advances( FT_Face face,
FT_UInt start,
FT_UInt count,
FT_Int32 flags,
FT_Fixed *padvances )
{
FT_Error error = FT_Err_Ok;
FT_Face_GetAdvancesFunc func;
FT_UInt num, end, nn;
FT_Int factor;
if ( !face )
return FT_THROW( Invalid_Face_Handle );
if ( !padvances )
return FT_THROW( Invalid_Argument );
num = (FT_UInt)face->num_glyphs;
end = start + count;
if ( start >= num || end < start || end > num )
return FT_THROW( Invalid_Glyph_Index );
if ( count == 0 )
return FT_Err_Ok;
func = face->driver->clazz->get_advances;
if ( func && LOAD_ADVANCE_FAST_CHECK( face, flags ) )
{
error = func( face, start, count, flags, padvances );
if ( !error )
return ft_face_scale_advances_( face, padvances, count, flags );
if ( FT_ERR_NEQ( error, Unimplemented_Feature ) )
return error;
}
error = FT_Err_Ok;
if ( flags & FT_ADVANCE_FLAG_FAST_ONLY )
return FT_THROW( Unimplemented_Feature );
flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY;
factor = ( flags & FT_LOAD_NO_SCALE ) ? 1 : 1024;
for ( nn = 0; nn < count; nn++ )
{
error = FT_Load_Glyph( face, start + nn, flags );
if ( error )
break;
/* scale from 26.6 to 16.16, unless NO_SCALE was requested */
padvances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT )
? face->glyph->advance.y * factor
: face->glyph->advance.x * factor;
}
return error;
}
/* END */

41
thirdparty/freetype/src/base/ftbase.c vendored Normal file
View File

@@ -0,0 +1,41 @@
/****************************************************************************
*
* ftbase.c
*
* Single object library component (body only).
*
* Copyright (C) 1996-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#define FT_MAKE_OPTION_SINGLE_OBJECT
#include "ftadvanc.c"
#include "ftcalc.c"
#include "ftcolor.c"
#include "ftdbgmem.c"
#include "fterrors.c"
#include "ftfntfmt.c"
#include "ftgloadr.c"
#include "fthash.c"
#include "ftlcdfil.c"
#include "ftmac.c"
#include "ftobjs.c"
#include "ftoutln.c"
#include "ftpsprop.c"
#include "ftrfork.c"
#include "ftsnames.c"
#include "ftstream.c"
#include "fttrigon.c"
#include "ftutil.c"
/* END */

82
thirdparty/freetype/src/base/ftbase.h vendored Normal file
View File

@@ -0,0 +1,82 @@
/****************************************************************************
*
* ftbase.h
*
* Private functions used in the `base' module (specification).
*
* Copyright (C) 2008-2024 by
* David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#ifndef FTBASE_H_
#define FTBASE_H_
#include <freetype/internal/ftobjs.h>
FT_BEGIN_HEADER
FT_DECLARE_GLYPH( ft_bitmap_glyph_class )
FT_DECLARE_GLYPH( ft_outline_glyph_class )
FT_DECLARE_GLYPH( ft_svg_glyph_class )
#ifdef FT_CONFIG_OPTION_MAC_FONTS
/* MacOS resource fork cannot exceed 16MB at least for Carbon code; */
/* see https://support.microsoft.com/en-us/kb/130437 */
#define FT_MAC_RFORK_MAX_LEN 0x00FFFFFFUL
/* Assume the stream is sfnt-wrapped PS Type1 or sfnt-wrapped CID-keyed */
/* font, and try to load a face specified by the face_index. */
FT_LOCAL( FT_Error )
open_face_PS_from_sfnt_stream( FT_Library library,
FT_Stream stream,
FT_Long face_index,
FT_Int num_params,
FT_Parameter *params,
FT_Face *aface );
/* Create a new FT_Face given a buffer and a driver name. */
/* From ftmac.c. */
FT_LOCAL( FT_Error )
open_face_from_buffer( FT_Library library,
FT_Byte* base,
FT_ULong size,
FT_Long face_index,
const char* driver_name,
FT_Face *aface );
#if defined( FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK ) && \
!defined( FT_MACINTOSH )
/* Mac OS X/Darwin kernel often changes recommended method to access */
/* the resource fork and older methods makes the kernel issue the */
/* warning of deprecated method. To calm it down, the methods based */
/* on Darwin VFS should be grouped and skip the rest methods after */
/* the case the resource is opened but found to lack a font in it. */
FT_LOCAL( FT_Bool )
ft_raccess_rule_by_darwin_vfs( FT_Library library, FT_UInt rule_index );
#endif
#endif /* FT_CONFIG_OPTION_MAC_FONTS */
FT_END_HEADER
#endif /* FTBASE_H_ */
/* END */

542
thirdparty/freetype/src/base/ftbbox.c vendored Normal file
View File

@@ -0,0 +1,542 @@
/****************************************************************************
*
* ftbbox.c
*
* FreeType bbox computation (body).
*
* Copyright (C) 1996-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used
* modified and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
/**************************************************************************
*
* This component has a _single_ role: to compute exact outline bounding
* boxes.
*
*/
#include <freetype/internal/ftdebug.h>
#include <freetype/ftbbox.h>
#include <freetype/ftimage.h>
#include <freetype/ftoutln.h>
#include <freetype/internal/ftcalc.h>
#include <freetype/internal/ftobjs.h>
typedef struct TBBox_Rec_
{
FT_Vector last;
FT_BBox bbox;
} TBBox_Rec;
#define FT_UPDATE_BBOX( p, bbox ) \
FT_BEGIN_STMNT \
if ( p->x < bbox.xMin ) \
bbox.xMin = p->x; \
if ( p->x > bbox.xMax ) \
bbox.xMax = p->x; \
if ( p->y < bbox.yMin ) \
bbox.yMin = p->y; \
if ( p->y > bbox.yMax ) \
bbox.yMax = p->y; \
FT_END_STMNT
#define CHECK_X( p, bbox ) \
( p->x < bbox.xMin || p->x > bbox.xMax )
#define CHECK_Y( p, bbox ) \
( p->y < bbox.yMin || p->y > bbox.yMax )
/**************************************************************************
*
* @Function:
* BBox_Move_To
*
* @Description:
* This function is used as a `move_to' emitter during
* FT_Outline_Decompose(). It simply records the destination point
* in `user->last'. We also update bbox in case contour starts with
* an implicit `on' point.
*
* @Input:
* to ::
* A pointer to the destination vector.
*
* @InOut:
* user ::
* A pointer to the current walk context.
*
* @Return:
* Always 0. Needed for the interface only.
*/
FT_CALLBACK_DEF( int )
BBox_Move_To( const FT_Vector* to,
void* user_ )
{
TBBox_Rec* user = (TBBox_Rec*)user_;
FT_UPDATE_BBOX( to, user->bbox );
user->last = *to;
return 0;
}
/**************************************************************************
*
* @Function:
* BBox_Line_To
*
* @Description:
* This function is used as a `line_to' emitter during
* FT_Outline_Decompose(). It simply records the destination point
* in `user->last'; no further computations are necessary because
* bbox already contains both explicit ends of the line segment.
*
* @Input:
* to ::
* A pointer to the destination vector.
*
* @InOut:
* user ::
* A pointer to the current walk context.
*
* @Return:
* Always 0. Needed for the interface only.
*/
FT_CALLBACK_DEF( int )
BBox_Line_To( const FT_Vector* to,
void* user_ )
{
TBBox_Rec* user = (TBBox_Rec*)user_;
user->last = *to;
return 0;
}
/**************************************************************************
*
* @Function:
* BBox_Conic_Check
*
* @Description:
* Find the extrema of a 1-dimensional conic Bezier curve and update
* a bounding range. This version uses direct computation, as it
* doesn't need square roots.
*
* @Input:
* y1 ::
* The start coordinate.
*
* y2 ::
* The coordinate of the control point.
*
* y3 ::
* The end coordinate.
*
* @InOut:
* min ::
* The address of the current minimum.
*
* max ::
* The address of the current maximum.
*/
static void
BBox_Conic_Check( FT_Pos y1,
FT_Pos y2,
FT_Pos y3,
FT_Pos* min,
FT_Pos* max )
{
/* This function is only called when a control off-point is outside */
/* the bbox that contains all on-points. It finds a local extremum */
/* within the segment, equal to (y1*y3 - y2*y2)/(y1 - 2*y2 + y3). */
/* Or, offsetting from y2, we get */
y1 -= y2;
y3 -= y2;
y2 += FT_MulDiv( y1, y3, y1 + y3 );
if ( y2 < *min )
*min = y2;
if ( y2 > *max )
*max = y2;
}
/**************************************************************************
*
* @Function:
* BBox_Conic_To
*
* @Description:
* This function is used as a `conic_to' emitter during
* FT_Outline_Decompose(). It checks a conic Bezier curve with the
* current bounding box, and computes its extrema if necessary to
* update it.
*
* @Input:
* control ::
* A pointer to a control point.
*
* to ::
* A pointer to the destination vector.
*
* @InOut:
* user ::
* The address of the current walk context.
*
* @Return:
* Always 0. Needed for the interface only.
*
* @Note:
* In the case of a non-monotonous arc, we compute directly the
* extremum coordinates, as it is sufficiently fast.
*/
FT_CALLBACK_DEF( int )
BBox_Conic_To( const FT_Vector* control,
const FT_Vector* to,
void* user_ )
{
TBBox_Rec* user = (TBBox_Rec*)user_;
/* in case `to' is implicit and not included in bbox yet */
FT_UPDATE_BBOX( to, user->bbox );
if ( CHECK_X( control, user->bbox ) )
BBox_Conic_Check( user->last.x,
control->x,
to->x,
&user->bbox.xMin,
&user->bbox.xMax );
if ( CHECK_Y( control, user->bbox ) )
BBox_Conic_Check( user->last.y,
control->y,
to->y,
&user->bbox.yMin,
&user->bbox.yMax );
user->last = *to;
return 0;
}
/**************************************************************************
*
* @Function:
* BBox_Cubic_Check
*
* @Description:
* Find the extrema of a 1-dimensional cubic Bezier curve and
* update a bounding range. This version uses iterative splitting
* because it is faster than the exact solution with square roots.
*
* @Input:
* p1 ::
* The start coordinate.
*
* p2 ::
* The coordinate of the first control point.
*
* p3 ::
* The coordinate of the second control point.
*
* p4 ::
* The end coordinate.
*
* @InOut:
* min ::
* The address of the current minimum.
*
* max ::
* The address of the current maximum.
*/
static FT_Pos
cubic_peak( FT_Pos q1,
FT_Pos q2,
FT_Pos q3,
FT_Pos q4 )
{
FT_Pos peak = 0;
FT_Int shift;
/* This function finds a peak of a cubic segment if it is above 0 */
/* using iterative bisection of the segment, or returns 0. */
/* The fixed-point arithmetic of bisection is inherently stable */
/* but may loose accuracy in the two lowest bits. To compensate, */
/* we upscale the segment if there is room. Large values may need */
/* to be downscaled to avoid overflows during bisection. */
/* It is called with either q2 or q3 positive, which is necessary */
/* for the peak to exist and avoids undefined FT_MSB. */
shift = 27 - FT_MSB( (FT_UInt32)( FT_ABS( q1 ) |
FT_ABS( q2 ) |
FT_ABS( q3 ) |
FT_ABS( q4 ) ) );
if ( shift > 0 )
{
/* upscaling too much just wastes time */
if ( shift > 2 )
shift = 2;
q1 *= 1 << shift;
q2 *= 1 << shift;
q3 *= 1 << shift;
q4 *= 1 << shift;
}
else
{
q1 >>= -shift;
q2 >>= -shift;
q3 >>= -shift;
q4 >>= -shift;
}
/* for a peak to exist above 0, the cubic segment must have */
/* at least one of its control off-points above 0. */
while ( q2 > 0 || q3 > 0 )
{
/* determine which half contains the maximum and split */
if ( q1 + q2 > q3 + q4 ) /* first half */
{
q4 = q4 + q3;
q3 = q3 + q2;
q2 = q2 + q1;
q4 = q4 + q3;
q3 = q3 + q2;
q4 = ( q4 + q3 ) >> 3;
q3 = q3 >> 2;
q2 = q2 >> 1;
}
else /* second half */
{
q1 = q1 + q2;
q2 = q2 + q3;
q3 = q3 + q4;
q1 = q1 + q2;
q2 = q2 + q3;
q1 = ( q1 + q2 ) >> 3;
q2 = q2 >> 2;
q3 = q3 >> 1;
}
/* check whether either end reached the maximum */
if ( q1 == q2 && q1 >= q3 )
{
peak = q1;
break;
}
if ( q3 == q4 && q2 <= q4 )
{
peak = q4;
break;
}
}
if ( shift > 0 )
peak >>= shift;
else
peak <<= -shift;
return peak;
}
static void
BBox_Cubic_Check( FT_Pos p1,
FT_Pos p2,
FT_Pos p3,
FT_Pos p4,
FT_Pos* min,
FT_Pos* max )
{
/* This function is only called when a control off-point is outside */
/* the bbox that contains all on-points. So at least one of the */
/* conditions below holds and cubic_peak is called with at least one */
/* non-zero argument. */
if ( p2 > *max || p3 > *max )
*max += cubic_peak( p1 - *max, p2 - *max, p3 - *max, p4 - *max );
/* now flip the signs to update the minimum */
if ( p2 < *min || p3 < *min )
*min -= cubic_peak( *min - p1, *min - p2, *min - p3, *min - p4 );
}
/**************************************************************************
*
* @Function:
* BBox_Cubic_To
*
* @Description:
* This function is used as a `cubic_to' emitter during
* FT_Outline_Decompose(). It checks a cubic Bezier curve with the
* current bounding box, and computes its extrema if necessary to
* update it.
*
* @Input:
* control1 ::
* A pointer to the first control point.
*
* control2 ::
* A pointer to the second control point.
*
* to ::
* A pointer to the destination vector.
*
* @InOut:
* user ::
* The address of the current walk context.
*
* @Return:
* Always 0. Needed for the interface only.
*
* @Note:
* In the case of a non-monotonous arc, we don't compute directly
* extremum coordinates, we subdivide instead.
*/
FT_CALLBACK_DEF( int )
BBox_Cubic_To( const FT_Vector* control1,
const FT_Vector* control2,
const FT_Vector* to,
void* user_ )
{
TBBox_Rec* user = (TBBox_Rec*)user_;
/* We don't need to check `to' since it is always an on-point, */
/* thus within the bbox. Only segments with an off-point outside */
/* the bbox can possibly reach new extreme values. */
if ( CHECK_X( control1, user->bbox ) ||
CHECK_X( control2, user->bbox ) )
BBox_Cubic_Check( user->last.x,
control1->x,
control2->x,
to->x,
&user->bbox.xMin,
&user->bbox.xMax );
if ( CHECK_Y( control1, user->bbox ) ||
CHECK_Y( control2, user->bbox ) )
BBox_Cubic_Check( user->last.y,
control1->y,
control2->y,
to->y,
&user->bbox.yMin,
&user->bbox.yMax );
user->last = *to;
return 0;
}
FT_DEFINE_OUTLINE_FUNCS(
bbox_interface,
(FT_Outline_MoveTo_Func) BBox_Move_To, /* move_to */
(FT_Outline_LineTo_Func) BBox_Line_To, /* line_to */
(FT_Outline_ConicTo_Func)BBox_Conic_To, /* conic_to */
(FT_Outline_CubicTo_Func)BBox_Cubic_To, /* cubic_to */
0, /* shift */
0 /* delta */
)
/* documentation is in ftbbox.h */
FT_EXPORT_DEF( FT_Error )
FT_Outline_Get_BBox( FT_Outline* outline,
FT_BBox *abbox )
{
FT_BBox cbox = { 0x7FFFFFFFL, 0x7FFFFFFFL,
-0x7FFFFFFFL, -0x7FFFFFFFL };
FT_BBox bbox = { 0x7FFFFFFFL, 0x7FFFFFFFL,
-0x7FFFFFFFL, -0x7FFFFFFFL };
FT_Vector* vec;
FT_UShort n;
if ( !abbox )
return FT_THROW( Invalid_Argument );
if ( !outline )
return FT_THROW( Invalid_Outline );
/* if outline is empty, return (0,0,0,0) */
if ( outline->n_points == 0 || outline->n_contours == 0 )
{
abbox->xMin = abbox->xMax = 0;
abbox->yMin = abbox->yMax = 0;
return 0;
}
/* We compute the control box as well as the bounding box of */
/* all `on' points in the outline. Then, if the two boxes */
/* coincide, we exit immediately. */
vec = outline->points;
for ( n = 0; n < outline->n_points; n++ )
{
FT_UPDATE_BBOX( vec, cbox );
if ( FT_CURVE_TAG( outline->tags[n] ) == FT_CURVE_TAG_ON )
FT_UPDATE_BBOX( vec, bbox );
vec++;
}
/* test two boxes for equality */
if ( cbox.xMin < bbox.xMin || cbox.xMax > bbox.xMax ||
cbox.yMin < bbox.yMin || cbox.yMax > bbox.yMax )
{
/* the two boxes are different, now walk over the outline to */
/* get the Bezier arc extrema. */
FT_Error error;
TBBox_Rec user;
user.bbox = bbox;
error = FT_Outline_Decompose( outline, &bbox_interface, &user );
if ( error )
return error;
*abbox = user.bbox;
}
else
*abbox = bbox;
return FT_Err_Ok;
}
/* END */

90
thirdparty/freetype/src/base/ftbdf.c vendored Normal file
View File

@@ -0,0 +1,90 @@
/****************************************************************************
*
* ftbdf.c
*
* FreeType API for accessing BDF-specific strings (body).
*
* Copyright (C) 2002-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/internal/ftdebug.h>
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/services/svbdf.h>
/* documentation is in ftbdf.h */
FT_EXPORT_DEF( FT_Error )
FT_Get_BDF_Charset_ID( FT_Face face,
const char* *acharset_encoding,
const char* *acharset_registry )
{
FT_Error error;
const char* encoding = NULL;
const char* registry = NULL;
FT_Service_BDF service;
if ( !face )
return FT_THROW( Invalid_Face_Handle );
FT_FACE_FIND_SERVICE( face, service, BDF );
if ( service && service->get_charset_id )
error = service->get_charset_id( face, &encoding, &registry );
else
error = FT_THROW( Invalid_Argument );
if ( acharset_encoding )
*acharset_encoding = encoding;
if ( acharset_registry )
*acharset_registry = registry;
return error;
}
/* documentation is in ftbdf.h */
FT_EXPORT_DEF( FT_Error )
FT_Get_BDF_Property( FT_Face face,
const char* prop_name,
BDF_PropertyRec *aproperty )
{
FT_Error error;
FT_Service_BDF service;
if ( !face )
return FT_THROW( Invalid_Face_Handle );
if ( !aproperty )
return FT_THROW( Invalid_Argument );
aproperty->type = BDF_PROPERTY_TYPE_NONE;
FT_FACE_FIND_SERVICE( face, service, BDF );
if ( service && service->get_property )
error = service->get_property( face, prop_name, aproperty );
else
error = FT_THROW( Invalid_Argument );
return error;
}
/* END */

1144
thirdparty/freetype/src/base/ftbitmap.c vendored Normal file

File diff suppressed because it is too large Load Diff

1126
thirdparty/freetype/src/base/ftcalc.c vendored Normal file

File diff suppressed because it is too large Load Diff

117
thirdparty/freetype/src/base/ftcid.c vendored Normal file
View File

@@ -0,0 +1,117 @@
/****************************************************************************
*
* ftcid.c
*
* FreeType API for accessing CID font information.
*
* Copyright (C) 2007-2024 by
* Derek Clegg and Michael Toftdal.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/ftcid.h>
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/services/svcid.h>
/* documentation is in ftcid.h */
FT_EXPORT_DEF( FT_Error )
FT_Get_CID_Registry_Ordering_Supplement( FT_Face face,
const char* *registry,
const char* *ordering,
FT_Int *supplement)
{
FT_Error error;
const char* r = NULL;
const char* o = NULL;
FT_Int s = 0;
error = FT_ERR( Invalid_Argument );
if ( face )
{
FT_Service_CID service;
FT_FACE_FIND_SERVICE( face, service, CID );
if ( service && service->get_ros )
error = service->get_ros( face, &r, &o, &s );
}
if ( registry )
*registry = r;
if ( ordering )
*ordering = o;
if ( supplement )
*supplement = s;
return error;
}
FT_EXPORT_DEF( FT_Error )
FT_Get_CID_Is_Internally_CID_Keyed( FT_Face face,
FT_Bool *is_cid )
{
FT_Error error = FT_ERR( Invalid_Argument );
FT_Bool ic = 0;
if ( face )
{
FT_Service_CID service;
FT_FACE_FIND_SERVICE( face, service, CID );
if ( service && service->get_is_cid )
error = service->get_is_cid( face, &ic);
}
if ( is_cid )
*is_cid = ic;
return error;
}
FT_EXPORT_DEF( FT_Error )
FT_Get_CID_From_Glyph_Index( FT_Face face,
FT_UInt glyph_index,
FT_UInt *cid )
{
FT_Error error = FT_ERR( Invalid_Argument );
FT_UInt c = 0;
if ( face )
{
FT_Service_CID service;
FT_FACE_FIND_SERVICE( face, service, CID );
if ( service && service->get_cid_from_glyph_index )
error = service->get_cid_from_glyph_index( face, glyph_index, &c);
}
if ( cid )
*cid = c;
return error;
}
/* END */

156
thirdparty/freetype/src/base/ftcolor.c vendored Normal file
View File

@@ -0,0 +1,156 @@
/****************************************************************************
*
* ftcolor.c
*
* FreeType's glyph color management (body).
*
* Copyright (C) 2018-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/internal/ftdebug.h>
#include <freetype/internal/sfnt.h>
#include <freetype/internal/tttypes.h>
#include <freetype/ftcolor.h>
#ifdef TT_CONFIG_OPTION_COLOR_LAYERS
static
const FT_Palette_Data null_palette_data = { 0, NULL, NULL, 0, NULL };
/* documentation is in ftcolor.h */
FT_EXPORT_DEF( FT_Error )
FT_Palette_Data_Get( FT_Face face,
FT_Palette_Data *apalette_data )
{
if ( !face )
return FT_THROW( Invalid_Face_Handle );
if ( !apalette_data)
return FT_THROW( Invalid_Argument );
if ( FT_IS_SFNT( face ) )
*apalette_data = ( (TT_Face)face )->palette_data;
else
*apalette_data = null_palette_data;
return FT_Err_Ok;
}
/* documentation is in ftcolor.h */
FT_EXPORT_DEF( FT_Error )
FT_Palette_Select( FT_Face face,
FT_UShort palette_index,
FT_Color* *apalette )
{
FT_Error error;
TT_Face ttface;
SFNT_Service sfnt;
if ( !face )
return FT_THROW( Invalid_Face_Handle );
if ( !FT_IS_SFNT( face ) )
{
if ( apalette )
*apalette = NULL;
return FT_Err_Ok;
}
ttface = (TT_Face)face;
sfnt = (SFNT_Service)ttface->sfnt;
error = sfnt->set_palette( ttface, palette_index );
if ( error )
return error;
ttface->palette_index = palette_index;
if ( apalette )
*apalette = ttface->palette;
return FT_Err_Ok;
}
/* documentation is in ftcolor.h */
FT_EXPORT_DEF( FT_Error )
FT_Palette_Set_Foreground_Color( FT_Face face,
FT_Color foreground_color )
{
TT_Face ttface;
if ( !face )
return FT_THROW( Invalid_Face_Handle );
if ( !FT_IS_SFNT( face ) )
return FT_Err_Ok;
ttface = (TT_Face)face;
ttface->foreground_color = foreground_color;
ttface->have_foreground_color = 1;
return FT_Err_Ok;
}
#else /* !TT_CONFIG_OPTION_COLOR_LAYERS */
FT_EXPORT_DEF( FT_Error )
FT_Palette_Data_Get( FT_Face face,
FT_Palette_Data *apalette_data )
{
FT_UNUSED( face );
FT_UNUSED( apalette_data );
return FT_THROW( Unimplemented_Feature );
}
FT_EXPORT_DEF( FT_Error )
FT_Palette_Select( FT_Face face,
FT_UShort palette_index,
FT_Color* *apalette )
{
FT_UNUSED( face );
FT_UNUSED( palette_index );
FT_UNUSED( apalette );
return FT_THROW( Unimplemented_Feature );
}
FT_EXPORT_DEF( FT_Error )
FT_Palette_Set_Foreground_Color( FT_Face face,
FT_Color foreground_color )
{
FT_UNUSED( face );
FT_UNUSED( foreground_color );
return FT_THROW( Unimplemented_Feature );
}
#endif /* !TT_CONFIG_OPTION_COLOR_LAYERS */
/* END */

971
thirdparty/freetype/src/base/ftdbgmem.c vendored Normal file
View File

@@ -0,0 +1,971 @@
/****************************************************************************
*
* ftdbgmem.c
*
* Memory debugger (body).
*
* Copyright (C) 2001-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <ft2build.h>
#include FT_CONFIG_CONFIG_H
#include <freetype/internal/ftdebug.h>
#include <freetype/internal/ftmemory.h>
#include <freetype/ftsystem.h>
#include <freetype/fterrors.h>
#include <freetype/fttypes.h>
#ifdef FT_DEBUG_MEMORY
#define KEEPALIVE /* `Keep alive' means that freed blocks aren't released
* to the heap. This is useful to detect double-frees
* or weird heap corruption, but it uses large amounts of
* memory, however.
*/
#include FT_CONFIG_STANDARD_LIBRARY_H
FT_BASE_DEF( const char* ) ft_debug_file_ = NULL;
FT_BASE_DEF( long ) ft_debug_lineno_ = 0;
extern void
FT_DumpMemory( FT_Memory memory );
typedef struct FT_MemSourceRec_* FT_MemSource;
typedef struct FT_MemNodeRec_* FT_MemNode;
typedef struct FT_MemTableRec_* FT_MemTable;
#define FT_MEM_VAL( addr ) ( (FT_PtrDist)(FT_Pointer)( addr ) )
/*
* This structure holds statistics for a single allocation/release
* site. This is useful to know where memory operations happen the
* most.
*/
typedef struct FT_MemSourceRec_
{
const char* file_name;
long line_no;
FT_Long cur_blocks; /* current number of allocated blocks */
FT_Long max_blocks; /* max. number of allocated blocks */
FT_Long all_blocks; /* total number of blocks allocated */
FT_Long cur_size; /* current cumulative allocated size */
FT_Long max_size; /* maximum cumulative allocated size */
FT_Long all_size; /* total cumulative allocated size */
FT_Long cur_max; /* current maximum allocated size */
FT_UInt32 hash;
FT_MemSource link;
} FT_MemSourceRec;
/*
* We don't need a resizable array for the memory sources because
* their number is pretty limited within FreeType.
*/
#define FT_MEM_SOURCE_BUCKETS 128
/*
* This structure holds information related to a single allocated
* memory block. If KEEPALIVE is defined, blocks that are freed by
* FreeType are never released to the system. Instead, their `size'
* field is set to `-size'. This is mainly useful to detect double
* frees, at the price of a large memory footprint during execution.
*/
typedef struct FT_MemNodeRec_
{
FT_Byte* address;
FT_Long size; /* < 0 if the block was freed */
FT_MemSource source;
#ifdef KEEPALIVE
const char* free_file_name;
FT_Long free_line_no;
#endif
FT_MemNode link;
} FT_MemNodeRec;
/*
* The global structure, containing compound statistics and all hash
* tables.
*/
typedef struct FT_MemTableRec_
{
FT_Long size;
FT_Long nodes;
FT_MemNode* buckets;
FT_Long alloc_total;
FT_Long alloc_current;
FT_Long alloc_max;
FT_Long alloc_count;
FT_Bool bound_total;
FT_Long alloc_total_max;
FT_Bool bound_count;
FT_Long alloc_count_max;
FT_MemSource sources[FT_MEM_SOURCE_BUCKETS];
FT_Bool keep_alive;
FT_Memory memory;
FT_Pointer memory_user;
FT_Alloc_Func alloc;
FT_Free_Func free;
FT_Realloc_Func realloc;
} FT_MemTableRec;
#define FT_MEM_SIZE_MIN 7
#define FT_MEM_SIZE_MAX 13845163
#define FT_FILENAME( x ) ( (x) ? (x) : "unknown file" )
/*
* Prime numbers are ugly to handle. It would be better to implement
* L-Hashing, which is 10% faster and doesn't require divisions.
*/
static const FT_Int ft_mem_primes[] =
{
7,
11,
19,
37,
73,
109,
163,
251,
367,
557,
823,
1237,
1861,
2777,
4177,
6247,
9371,
14057,
21089,
31627,
47431,
71143,
106721,
160073,
240101,
360163,
540217,
810343,
1215497,
1823231,
2734867,
4102283,
6153409,
9230113,
13845163,
};
static FT_Long
ft_mem_closest_prime( FT_Long num )
{
size_t i;
for ( i = 0;
i < sizeof ( ft_mem_primes ) / sizeof ( ft_mem_primes[0] ); i++ )
if ( ft_mem_primes[i] > num )
return ft_mem_primes[i];
return FT_MEM_SIZE_MAX;
}
static void
ft_mem_debug_panic( const char* fmt,
... )
{
va_list ap;
printf( "FreeType.Debug: " );
va_start( ap, fmt );
vprintf( fmt, ap );
va_end( ap );
printf( "\n" );
exit( EXIT_FAILURE );
}
static FT_Pointer
ft_mem_table_alloc( FT_MemTable table,
FT_Long size )
{
FT_Memory memory = table->memory;
FT_Pointer block;
memory->user = table->memory_user;
block = table->alloc( memory, size );
memory->user = table;
return block;
}
static void
ft_mem_table_free( FT_MemTable table,
FT_Pointer block )
{
FT_Memory memory = table->memory;
memory->user = table->memory_user;
table->free( memory, block );
memory->user = table;
}
static void
ft_mem_table_resize( FT_MemTable table )
{
FT_Long new_size;
new_size = ft_mem_closest_prime( table->nodes );
if ( new_size != table->size )
{
FT_MemNode* new_buckets;
FT_Long i;
new_buckets = (FT_MemNode *)
ft_mem_table_alloc(
table,
new_size * (FT_Long)sizeof ( FT_MemNode ) );
if ( !new_buckets )
return;
FT_ARRAY_ZERO( new_buckets, new_size );
for ( i = 0; i < table->size; i++ )
{
FT_MemNode node, next, *pnode;
FT_PtrDist hash;
node = table->buckets[i];
while ( node )
{
next = node->link;
hash = FT_MEM_VAL( node->address ) % (FT_PtrDist)new_size;
pnode = new_buckets + hash;
node->link = pnode[0];
pnode[0] = node;
node = next;
}
}
if ( table->buckets )
ft_mem_table_free( table, table->buckets );
table->buckets = new_buckets;
table->size = new_size;
}
}
static void
ft_mem_table_destroy( FT_MemTable table )
{
FT_Long i;
FT_Long leak_count = 0;
FT_Long leaks = 0;
/* remove all blocks from the table, revealing leaked ones */
for ( i = 0; i < table->size; i++ )
{
FT_MemNode *pnode = table->buckets + i, next, node = *pnode;
while ( node )
{
next = node->link;
node->link = NULL;
if ( node->size > 0 )
{
printf(
"leaked memory block at address %p, size %8ld in (%s:%ld)\n",
(void*)node->address,
node->size,
FT_FILENAME( node->source->file_name ),
node->source->line_no );
leak_count++;
leaks += node->size;
ft_mem_table_free( table, node->address );
}
node->address = NULL;
node->size = 0;
ft_mem_table_free( table, node );
node = next;
}
table->buckets[i] = NULL;
}
ft_mem_table_free( table, table->buckets );
table->buckets = NULL;
table->size = 0;
table->nodes = 0;
/* remove all sources */
for ( i = 0; i < FT_MEM_SOURCE_BUCKETS; i++ )
{
FT_MemSource source, next;
for ( source = table->sources[i]; source != NULL; source = next )
{
next = source->link;
ft_mem_table_free( table, source );
}
table->sources[i] = NULL;
}
printf( "FreeType: total memory allocations = %ld\n",
table->alloc_total );
printf( "FreeType: maximum memory footprint = %ld\n",
table->alloc_max );
if ( leak_count > 0 )
ft_mem_debug_panic(
"FreeType: %ld bytes of memory leaked in %ld blocks\n",
leaks, leak_count );
printf( "FreeType: no memory leaks detected\n" );
}
static FT_MemNode*
ft_mem_table_get_nodep( FT_MemTable table,
FT_Byte* address )
{
FT_PtrDist hash;
FT_MemNode *pnode, node;
hash = FT_MEM_VAL( address );
pnode = table->buckets + ( hash % (FT_PtrDist)table->size );
for (;;)
{
node = pnode[0];
if ( !node )
break;
if ( node->address == address )
break;
pnode = &node->link;
}
return pnode;
}
static FT_MemSource
ft_mem_table_get_source( FT_MemTable table )
{
FT_UInt32 hash;
FT_MemSource node, *pnode;
/* cast to FT_PtrDist first since void* can be larger */
/* than FT_UInt32 and GCC 4.1.1 emits a warning */
hash = (FT_UInt32)(FT_PtrDist)(void*)ft_debug_file_ +
(FT_UInt32)( 5 * ft_debug_lineno_ );
pnode = &table->sources[hash % FT_MEM_SOURCE_BUCKETS];
for (;;)
{
node = *pnode;
if ( !node )
break;
if ( node->file_name == ft_debug_file_ &&
node->line_no == ft_debug_lineno_ )
goto Exit;
pnode = &node->link;
}
node = (FT_MemSource)ft_mem_table_alloc( table, sizeof ( *node ) );
if ( !node )
ft_mem_debug_panic(
"not enough memory to perform memory debugging\n" );
node->file_name = ft_debug_file_;
node->line_no = ft_debug_lineno_;
node->cur_blocks = 0;
node->max_blocks = 0;
node->all_blocks = 0;
node->cur_size = 0;
node->max_size = 0;
node->all_size = 0;
node->cur_max = 0;
node->link = NULL;
node->hash = hash;
*pnode = node;
Exit:
return node;
}
static void
ft_mem_table_set( FT_MemTable table,
FT_Byte* address,
FT_Long size,
FT_Long delta )
{
FT_MemNode *pnode, node;
if ( table )
{
FT_MemSource source;
pnode = ft_mem_table_get_nodep( table, address );
node = *pnode;
if ( node )
{
if ( node->size < 0 )
{
/* This block was already freed. Our memory is now completely */
/* corrupted! */
/* This can only happen in keep-alive mode. */
ft_mem_debug_panic(
"memory heap corrupted (allocating freed block)" );
}
else
{
/* This block was already allocated. This means that our memory */
/* is also corrupted! */
ft_mem_debug_panic(
"memory heap corrupted (re-allocating allocated block at"
" %p, of size %ld)\n"
"org=%s:%d new=%s:%d\n",
node->address, node->size,
FT_FILENAME( node->source->file_name ), node->source->line_no,
FT_FILENAME( ft_debug_file_ ), ft_debug_lineno_ );
}
}
/* we need to create a new node in this table */
node = (FT_MemNode)ft_mem_table_alloc( table, sizeof ( *node ) );
if ( !node )
ft_mem_debug_panic( "not enough memory to run memory tests" );
node->address = address;
node->size = size;
node->source = source = ft_mem_table_get_source( table );
if ( delta == 0 )
{
/* this is an allocation */
source->all_blocks++;
source->cur_blocks++;
if ( source->cur_blocks > source->max_blocks )
source->max_blocks = source->cur_blocks;
}
if ( size > source->cur_max )
source->cur_max = size;
if ( delta != 0 )
{
/* we are growing or shrinking a reallocated block */
source->cur_size += delta;
table->alloc_current += delta;
}
else
{
/* we are allocating a new block */
source->cur_size += size;
table->alloc_current += size;
}
source->all_size += size;
if ( source->cur_size > source->max_size )
source->max_size = source->cur_size;
node->free_file_name = NULL;
node->free_line_no = 0;
node->link = pnode[0];
pnode[0] = node;
table->nodes++;
table->alloc_total += size;
if ( table->alloc_current > table->alloc_max )
table->alloc_max = table->alloc_current;
if ( table->nodes * 3 < table->size ||
table->size * 3 < table->nodes )
ft_mem_table_resize( table );
}
}
static void
ft_mem_table_remove( FT_MemTable table,
FT_Byte* address,
FT_Long delta )
{
if ( table )
{
FT_MemNode *pnode, node;
pnode = ft_mem_table_get_nodep( table, address );
node = *pnode;
if ( node )
{
FT_MemSource source;
if ( node->size < 0 )
ft_mem_debug_panic(
"freeing memory block at %p more than once\n"
" at (%s:%ld)!\n"
" Block was allocated at (%s:%ld)\n"
" and released at (%s:%ld).",
address,
FT_FILENAME( ft_debug_file_ ), ft_debug_lineno_,
FT_FILENAME( node->source->file_name ), node->source->line_no,
FT_FILENAME( node->free_file_name ), node->free_line_no );
/* scramble the node's content for additional safety */
FT_MEM_SET( address, 0xF3, node->size );
if ( delta == 0 )
{
source = node->source;
source->cur_blocks--;
source->cur_size -= node->size;
table->alloc_current -= node->size;
}
if ( table->keep_alive )
{
/* we simply invert the node's size to indicate that the node */
/* was freed. */
node->size = -node->size;
node->free_file_name = ft_debug_file_;
node->free_line_no = ft_debug_lineno_;
}
else
{
table->nodes--;
*pnode = node->link;
node->size = 0;
node->source = NULL;
ft_mem_table_free( table, node );
if ( table->nodes * 3 < table->size ||
table->size * 3 < table->nodes )
ft_mem_table_resize( table );
}
}
else
ft_mem_debug_panic(
"trying to free unknown block at %p in (%s:%ld)\n",
address,
FT_FILENAME( ft_debug_file_ ), ft_debug_lineno_ );
}
}
static FT_Pointer
ft_mem_debug_alloc( FT_Memory memory,
FT_Long size )
{
FT_MemTable table = (FT_MemTable)memory->user;
FT_Byte* block;
if ( size <= 0 )
ft_mem_debug_panic( "negative block size allocation (%ld)", size );
/* return NULL if the maximum number of allocations was reached */
if ( table->bound_count &&
table->alloc_count >= table->alloc_count_max )
return NULL;
/* return NULL if this allocation would overflow the maximum heap size */
if ( table->bound_total &&
table->alloc_total_max - table->alloc_current > size )
return NULL;
block = (FT_Byte *)ft_mem_table_alloc( table, size );
if ( block )
{
ft_mem_table_set( table, block, size, 0 );
table->alloc_count++;
}
ft_debug_file_ = "<unknown>";
ft_debug_lineno_ = 0;
return (FT_Pointer)block;
}
static void
ft_mem_debug_free( FT_Memory memory,
FT_Pointer block )
{
FT_MemTable table = (FT_MemTable)memory->user;
if ( !block )
ft_mem_debug_panic( "trying to free NULL in (%s:%ld)",
FT_FILENAME( ft_debug_file_ ),
ft_debug_lineno_ );
ft_mem_table_remove( table, (FT_Byte*)block, 0 );
if ( !table->keep_alive )
ft_mem_table_free( table, block );
table->alloc_count--;
ft_debug_file_ = "<unknown>";
ft_debug_lineno_ = 0;
}
static FT_Pointer
ft_mem_debug_realloc( FT_Memory memory,
FT_Long cur_size,
FT_Long new_size,
FT_Pointer block )
{
FT_MemTable table = (FT_MemTable)memory->user;
FT_MemNode node, *pnode;
FT_Pointer new_block;
FT_Long delta;
const char* file_name = FT_FILENAME( ft_debug_file_ );
FT_Long line_no = ft_debug_lineno_;
/* unlikely, but possible */
if ( new_size == cur_size )
return block;
/* the following is valid according to ANSI C */
#if 0
if ( !block || !cur_size )
ft_mem_debug_panic( "trying to reallocate NULL in (%s:%ld)",
file_name, line_no );
#endif
/* while the following is allowed in ANSI C also, we abort since */
/* such case should be handled by FreeType. */
if ( new_size <= 0 )
ft_mem_debug_panic(
"trying to reallocate %p to size 0 (current is %ld) in (%s:%ld)",
block, cur_size, file_name, line_no );
/* check `cur_size' value */
pnode = ft_mem_table_get_nodep( table, (FT_Byte*)block );
node = *pnode;
if ( !node )
ft_mem_debug_panic(
"trying to reallocate unknown block at %p in (%s:%ld)",
block, file_name, line_no );
if ( node->size <= 0 )
ft_mem_debug_panic(
"trying to reallocate freed block at %p in (%s:%ld)",
block, file_name, line_no );
if ( node->size != cur_size )
ft_mem_debug_panic( "invalid ft_realloc request for %p. cur_size is "
"%ld instead of %ld in (%s:%ld)",
block, cur_size, node->size, file_name, line_no );
/* return NULL if the maximum number of allocations was reached */
if ( table->bound_count &&
table->alloc_count >= table->alloc_count_max )
return NULL;
delta = new_size - cur_size;
/* return NULL if this allocation would overflow the maximum heap size */
if ( delta > 0 &&
table->bound_total &&
table->alloc_current + delta > table->alloc_total_max )
return NULL;
new_block = (FT_Pointer)ft_mem_table_alloc( table, new_size );
if ( !new_block )
return NULL;
ft_mem_table_set( table, (FT_Byte*)new_block, new_size, delta );
ft_memcpy( new_block, block, cur_size < new_size ? (size_t)cur_size
: (size_t)new_size );
ft_mem_table_remove( table, (FT_Byte*)block, delta );
ft_debug_file_ = "<unknown>";
ft_debug_lineno_ = 0;
if ( !table->keep_alive )
ft_mem_table_free( table, block );
return new_block;
}
extern void
ft_mem_debug_init( FT_Memory memory )
{
FT_MemTable table;
if ( !ft_getenv( "FT2_DEBUG_MEMORY" ) )
return;
table = (FT_MemTable)memory->alloc( memory, sizeof ( *table ) );
if ( table )
{
FT_ZERO( table );
table->memory = memory;
table->memory_user = memory->user;
table->alloc = memory->alloc;
table->realloc = memory->realloc;
table->free = memory->free;
ft_mem_table_resize( table );
if ( table->size )
{
const char* p;
memory->user = table;
memory->alloc = ft_mem_debug_alloc;
memory->realloc = ft_mem_debug_realloc;
memory->free = ft_mem_debug_free;
p = ft_getenv( "FT2_ALLOC_TOTAL_MAX" );
if ( p )
{
FT_Long total_max = ft_strtol( p, NULL, 10 );
if ( total_max > 0 )
{
table->bound_total = 1;
table->alloc_total_max = total_max;
}
}
p = ft_getenv( "FT2_ALLOC_COUNT_MAX" );
if ( p )
{
FT_Long total_count = ft_strtol( p, NULL, 10 );
if ( total_count > 0 )
{
table->bound_count = 1;
table->alloc_count_max = total_count;
}
}
p = ft_getenv( "FT2_KEEP_ALIVE" );
if ( p )
{
FT_Long keep_alive = ft_strtol( p, NULL, 10 );
if ( keep_alive > 0 )
table->keep_alive = 1;
}
}
else
memory->free( memory, table );
}
}
extern void
ft_mem_debug_done( FT_Memory memory )
{
if ( memory->free == ft_mem_debug_free )
{
FT_MemTable table = (FT_MemTable)memory->user;
FT_DumpMemory( memory );
ft_mem_table_destroy( table );
memory->free = table->free;
memory->realloc = table->realloc;
memory->alloc = table->alloc;
memory->user = table->memory_user;
memory->free( memory, table );
}
}
FT_COMPARE_DEF( int )
ft_mem_source_compare( const void* p1,
const void* p2 )
{
FT_MemSource s1 = *(FT_MemSource*)p1;
FT_MemSource s2 = *(FT_MemSource*)p2;
if ( s2->max_size > s1->max_size )
return 1;
else if ( s2->max_size < s1->max_size )
return -1;
else
return 0;
}
extern void
FT_DumpMemory( FT_Memory memory )
{
if ( memory->free == ft_mem_debug_free )
{
FT_MemTable table = (FT_MemTable)memory->user;
FT_MemSource* bucket = table->sources;
FT_MemSource* limit = bucket + FT_MEM_SOURCE_BUCKETS;
FT_MemSource* sources;
FT_Int nn, count;
const char* fmt;
count = 0;
for ( ; bucket < limit; bucket++ )
{
FT_MemSource source = *bucket;
for ( ; source; source = source->link )
count++;
}
sources = (FT_MemSource*)
ft_mem_table_alloc(
table, count * (FT_Long)sizeof ( *sources ) );
count = 0;
for ( bucket = table->sources; bucket < limit; bucket++ )
{
FT_MemSource source = *bucket;
for ( ; source; source = source->link )
sources[count++] = source;
}
ft_qsort( sources,
(size_t)count,
sizeof ( *sources ),
ft_mem_source_compare );
printf( "FreeType Memory Dump: "
"current=%ld max=%ld total=%ld count=%ld\n",
table->alloc_current, table->alloc_max,
table->alloc_total, table->alloc_count );
printf( " block block sizes sizes sizes source\n" );
printf( " count high sum highsum max location\n" );
printf( "-------------------------------------------------\n" );
fmt = "%6ld %6ld %8ld %8ld %8ld %s:%d\n";
for ( nn = 0; nn < count; nn++ )
{
FT_MemSource source = sources[nn];
printf( fmt,
source->cur_blocks, source->max_blocks,
source->cur_size, source->max_size, source->cur_max,
FT_FILENAME( source->file_name ),
source->line_no );
}
printf( "------------------------------------------------\n" );
ft_mem_table_free( table, sources );
}
}
#else /* !FT_DEBUG_MEMORY */
/* ANSI C doesn't like empty source files */
typedef int debug_mem_dummy_;
#endif /* !FT_DEBUG_MEMORY */
/* END */

644
thirdparty/freetype/src/base/ftdebug.c vendored Normal file
View File

@@ -0,0 +1,644 @@
/****************************************************************************
*
* ftdebug.c
*
* Debugging and logging component (body).
*
* Copyright (C) 1996-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
/**************************************************************************
*
* This component contains various macros and functions used to ease the
* debugging of the FreeType engine. Its main purpose is in assertion
* checking, tracing, and error detection.
*
* There are now three debugging modes:
*
* - trace mode
*
* Error and trace messages are sent to the log file (which can be the
* standard error output).
*
* - error mode
*
* Only error messages are generated.
*
* - release mode:
*
* No error message is sent or generated. The code is free from any
* debugging parts.
*
*/
#include <freetype/freetype.h>
#include <freetype/ftlogging.h>
#include <freetype/internal/ftdebug.h>
#include <freetype/internal/ftobjs.h>
#ifdef FT_DEBUG_LOGGING
/**************************************************************************
*
* Variables used to control logging.
*
* 1. `ft_default_trace_level` stores the value of trace levels, which are
* provided to FreeType using the `FT2_DEBUG` environment variable.
*
* 2. `ft_fileptr` stores the `FILE*` handle.
*
* 3. `ft_component` is a string that holds the name of `FT_COMPONENT`.
*
* 4. The flag `ft_component_flag` prints the name of `FT_COMPONENT` along
* with the actual log message if set to true.
*
* 5. The flag `ft_timestamp_flag` prints time along with the actual log
* message if set to ture.
*
* 6. `ft_have_newline_char` is used to differentiate between a log
* message with and without a trailing newline character.
*
* 7. `ft_custom_trace_level` stores the custom trace level value, which
* is provided by the user at run-time.
*
* We use `static` to avoid 'unused variable' warnings.
*
*/
static const char* ft_default_trace_level = NULL;
static FILE* ft_fileptr = NULL;
static const char* ft_component = NULL;
static FT_Bool ft_component_flag = FALSE;
static FT_Bool ft_timestamp_flag = FALSE;
static FT_Bool ft_have_newline_char = TRUE;
static const char* ft_custom_trace_level = NULL;
/* declared in ftdebug.h */
dlg_handler ft_default_log_handler = NULL;
FT_Custom_Log_Handler custom_output_handler = NULL;
#endif /* FT_DEBUG_LOGGING */
#ifdef FT_DEBUG_LEVEL_ERROR
/* documentation is in ftdebug.h */
FT_BASE_DEF( void )
FT_Message( const char* fmt,
... )
{
va_list ap;
va_start( ap, fmt );
vfprintf( stderr, fmt, ap );
va_end( ap );
}
/* documentation is in ftdebug.h */
FT_BASE_DEF( void )
FT_Panic( const char* fmt,
... )
{
va_list ap;
va_start( ap, fmt );
vfprintf( stderr, fmt, ap );
va_end( ap );
exit( EXIT_FAILURE );
}
/* documentation is in ftdebug.h */
FT_BASE_DEF( int )
FT_Throw( FT_Error error,
int line,
const char* file )
{
#if 0
/* activating the code in this block makes FreeType very chatty */
fprintf( stderr,
"%s:%d: error 0x%02x: %s\n",
file,
line,
error,
FT_Error_String( error ) );
#else
FT_UNUSED( error );
FT_UNUSED( line );
FT_UNUSED( file );
#endif
return 0;
}
#endif /* FT_DEBUG_LEVEL_ERROR */
#ifdef FT_DEBUG_LEVEL_TRACE
/* array of trace levels, initialized to 0; */
/* this gets adjusted at run-time */
static int ft_trace_levels_enabled[trace_count];
/* array of trace levels, always initialized to 0 */
static int ft_trace_levels_disabled[trace_count];
/* a pointer to either `ft_trace_levels_enabled' */
/* or `ft_trace_levels_disabled' */
int* ft_trace_levels;
/* define array of trace toggle names */
#define FT_TRACE_DEF( x ) #x ,
static const char* ft_trace_toggles[trace_count + 1] =
{
#include <freetype/internal/fttrace.h>
NULL
};
#undef FT_TRACE_DEF
/* documentation is in ftdebug.h */
FT_BASE_DEF( FT_Int )
FT_Trace_Get_Count( void )
{
return trace_count;
}
/* documentation is in ftdebug.h */
FT_BASE_DEF( const char * )
FT_Trace_Get_Name( FT_Int idx )
{
int max = FT_Trace_Get_Count();
if ( idx < max )
return ft_trace_toggles[idx];
else
return NULL;
}
/* documentation is in ftdebug.h */
FT_BASE_DEF( void )
FT_Trace_Disable( void )
{
ft_trace_levels = ft_trace_levels_disabled;
}
/* documentation is in ftdebug.h */
FT_BASE_DEF( void )
FT_Trace_Enable( void )
{
ft_trace_levels = ft_trace_levels_enabled;
}
/**************************************************************************
*
* Initialize the tracing sub-system. This is done by retrieving the
* value of the `FT2_DEBUG' environment variable. It must be a list of
* toggles, separated by spaces, `;', or `,'. Example:
*
* export FT2_DEBUG="any:3 memory:7 stream:5"
*
* This requests that all levels be set to 3, except the trace level for
* the memory and stream components which are set to 7 and 5,
* respectively.
*
* See the file `include/freetype/internal/fttrace.h' for details of
* the available toggle names.
*
* The level must be between 0 and 7; 0 means quiet (except for serious
* runtime errors), and 7 means _very_ verbose.
*/
FT_BASE_DEF( void )
ft_debug_init( void )
{
const char* ft2_debug = NULL;
#ifdef FT_DEBUG_LOGGING
if ( ft_custom_trace_level != NULL )
ft2_debug = ft_custom_trace_level;
else
ft2_debug = ft_default_trace_level;
#else
ft2_debug = ft_getenv( "FT2_DEBUG" );
#endif
if ( ft2_debug )
{
const char* p = ft2_debug;
const char* q;
for ( ; *p; p++ )
{
/* skip leading whitespace and separators */
if ( *p == ' ' || *p == '\t' || *p == ',' || *p == ';' || *p == '=' )
continue;
#ifdef FT_DEBUG_LOGGING
/* check extra arguments for logging */
if ( *p == '-' )
{
const char* r = ++p;
if ( *r == 'v' )
{
const char* s = ++r;
ft_component_flag = TRUE;
if ( *s == 't' )
{
ft_timestamp_flag = TRUE;
p++;
}
p++;
}
else if ( *r == 't' )
{
const char* s = ++r;
ft_timestamp_flag = TRUE;
if ( *s == 'v' )
{
ft_component_flag = TRUE;
p++;
}
p++;
}
}
#endif /* FT_DEBUG_LOGGING */
/* read toggle name, followed by ':' */
q = p;
while ( *p && *p != ':' )
p++;
if ( !*p )
break;
if ( *p == ':' && p > q )
{
FT_Int n, i, len = (FT_Int)( p - q );
FT_Int level = -1, found = -1;
for ( n = 0; n < trace_count; n++ )
{
const char* toggle = ft_trace_toggles[n];
for ( i = 0; i < len; i++ )
{
if ( toggle[i] != q[i] )
break;
}
if ( i == len && toggle[i] == 0 )
{
found = n;
break;
}
}
/* read level */
p++;
if ( *p )
{
level = *p - '0';
if ( level < 0 || level > 7 )
level = -1;
}
if ( found >= 0 && level >= 0 )
{
if ( found == trace_any )
{
/* special case for `any' */
for ( n = 0; n < trace_count; n++ )
ft_trace_levels_enabled[n] = level;
}
else
ft_trace_levels_enabled[found] = level;
}
}
}
}
ft_trace_levels = ft_trace_levels_enabled;
}
#else /* !FT_DEBUG_LEVEL_TRACE */
FT_BASE_DEF( void )
ft_debug_init( void )
{
/* nothing */
}
FT_BASE_DEF( FT_Int )
FT_Trace_Get_Count( void )
{
return 0;
}
FT_BASE_DEF( const char * )
FT_Trace_Get_Name( FT_Int idx )
{
FT_UNUSED( idx );
return NULL;
}
FT_BASE_DEF( void )
FT_Trace_Disable( void )
{
/* nothing */
}
/* documentation is in ftdebug.h */
FT_BASE_DEF( void )
FT_Trace_Enable( void )
{
/* nothing */
}
#endif /* !FT_DEBUG_LEVEL_TRACE */
#ifdef FT_DEBUG_LOGGING
/**************************************************************************
*
* Initialize and de-initialize 'dlg' library.
*
*/
FT_BASE_DEF( void )
ft_logging_init( void )
{
ft_default_log_handler = ft_log_handler;
ft_default_trace_level = ft_getenv( "FT2_DEBUG" );
if ( ft_getenv( "FT_LOGGING_FILE" ) )
ft_fileptr = ft_fopen( ft_getenv( "FT_LOGGING_FILE" ), "w" );
else
ft_fileptr = stderr;
ft_debug_init();
/* Set the default output handler for 'dlg'. */
dlg_set_handler( ft_default_log_handler, NULL );
}
FT_BASE_DEF( void )
ft_logging_deinit( void )
{
if ( ft_fileptr != stderr )
ft_fclose( ft_fileptr );
}
/**************************************************************************
*
* An output log handler for FreeType.
*
*/
FT_BASE_DEF( void )
ft_log_handler( const struct dlg_origin* origin,
const char* string,
void* data )
{
char features_buf[128];
char* bufp = features_buf;
FT_UNUSED( data );
if ( ft_have_newline_char )
{
const char* features = NULL;
size_t features_length = 0;
#define FEATURES_TIMESTAMP "[%h:%m] "
#define FEATURES_COMPONENT "[%t] "
#define FEATURES_TIMESTAMP_COMPONENT "[%h:%m %t] "
if ( ft_timestamp_flag && ft_component_flag )
{
features = FEATURES_TIMESTAMP_COMPONENT;
features_length = sizeof ( FEATURES_TIMESTAMP_COMPONENT );
}
else if ( ft_timestamp_flag )
{
features = FEATURES_TIMESTAMP;
features_length = sizeof ( FEATURES_TIMESTAMP );
}
else if ( ft_component_flag )
{
features = FEATURES_COMPONENT;
features_length = sizeof ( FEATURES_COMPONENT );
}
if ( ft_component_flag || ft_timestamp_flag )
{
ft_strncpy( features_buf, features, features_length );
bufp += features_length - 1;
}
if ( ft_component_flag )
{
size_t tag_length = ft_strlen( *origin->tags );
size_t i;
/* To vertically align tracing messages we compensate the */
/* different FT_COMPONENT string lengths by inserting an */
/* appropriate amount of space characters. */
for ( i = 0;
i < FT_MAX_TRACE_LEVEL_LENGTH - tag_length;
i++ )
*bufp++ = ' ';
}
}
/* Finally add the format string for the tracing message. */
*bufp++ = '%';
*bufp++ = 'c';
*bufp = '\0';
dlg_generic_outputf_stream( ft_fileptr,
(const char*)features_buf,
origin,
string,
dlg_default_output_styles,
true );
if ( ft_strrchr( string, '\n' ) )
ft_have_newline_char = TRUE;
else
ft_have_newline_char = FALSE;
}
/* documentation is in ftdebug.h */
FT_BASE_DEF( void )
ft_add_tag( const char* tag )
{
ft_component = tag;
dlg_add_tag( tag, NULL );
}
/* documentation is in ftdebug.h */
FT_BASE_DEF( void )
ft_remove_tag( const char* tag )
{
dlg_remove_tag( tag, NULL );
}
/* documentation is in ftlogging.h */
FT_EXPORT_DEF( void )
FT_Trace_Set_Level( const char* level )
{
ft_component_flag = FALSE;
ft_timestamp_flag = FALSE;
ft_custom_trace_level = level;
ft_debug_init();
}
/* documentation is in ftlogging.h */
FT_EXPORT_DEF( void )
FT_Trace_Set_Default_Level( void )
{
ft_component_flag = FALSE;
ft_timestamp_flag = FALSE;
ft_custom_trace_level = NULL;
ft_debug_init();
}
/**************************************************************************
*
* Functions to handle a custom log handler.
*
*/
/* documentation is in ftlogging.h */
FT_EXPORT_DEF( void )
FT_Set_Log_Handler( FT_Custom_Log_Handler handler )
{
custom_output_handler = handler;
}
/* documentation is in ftlogging.h */
FT_EXPORT_DEF( void )
FT_Set_Default_Log_Handler( void )
{
custom_output_handler = NULL;
}
/* documentation is in ftdebug.h */
FT_BASE_DEF( void )
FT_Logging_Callback( const char* fmt,
... )
{
va_list ap;
va_start( ap, fmt );
custom_output_handler( ft_component, fmt, ap );
va_end( ap );
}
#else /* !FT_DEBUG_LOGGING */
FT_EXPORT_DEF( void )
FT_Trace_Set_Level( const char* level )
{
FT_UNUSED( level );
}
FT_EXPORT_DEF( void )
FT_Trace_Set_Default_Level( void )
{
/* nothing */
}
FT_EXPORT_DEF( void )
FT_Set_Log_Handler( FT_Custom_Log_Handler handler )
{
FT_UNUSED( handler );
}
FT_EXPORT_DEF( void )
FT_Set_Default_Log_Handler( void )
{
/* nothing */
}
#endif /* !FT_DEBUG_LOGGING */
/* END */

45
thirdparty/freetype/src/base/fterrors.c vendored Normal file
View File

@@ -0,0 +1,45 @@
/****************************************************************************
*
* fterrors.c
*
* FreeType API for error code handling.
*
* Copyright (C) 2018-2024 by
* Armin Hasitzka, David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/internal/ftdebug.h>
#include <freetype/fterrors.h>
/* documentation is in fterrors.h */
FT_EXPORT_DEF( const char* )
FT_Error_String( FT_Error error_code )
{
if ( error_code < 0 ||
error_code >= FT_ERR_CAT( FT_ERR_PREFIX, Max ) )
return NULL;
#if defined( FT_CONFIG_OPTION_ERROR_STRINGS ) || \
defined( FT_DEBUG_LEVEL_ERROR )
#undef FTERRORS_H_
#define FT_ERROR_START_LIST switch ( FT_ERROR_BASE( error_code ) ) {
#define FT_ERRORDEF( e, v, s ) case v: return s;
#define FT_ERROR_END_LIST }
#include <freetype/fterrors.h>
#endif /* defined( FT_CONFIG_OPTION_ERROR_STRINGS ) || ... */
return NULL;
}

54
thirdparty/freetype/src/base/ftfntfmt.c vendored Normal file
View File

@@ -0,0 +1,54 @@
/****************************************************************************
*
* ftfntfmt.c
*
* FreeType utility file for font formats (body).
*
* Copyright (C) 2002-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/ftfntfmt.h>
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/services/svfntfmt.h>
/* documentation is in ftfntfmt.h */
FT_EXPORT_DEF( const char* )
FT_Get_Font_Format( FT_Face face )
{
const char* result = NULL;
if ( face )
FT_FACE_FIND_SERVICE( face, result, FONT_FORMAT );
return result;
}
/* deprecated function name; retained for ABI compatibility */
FT_EXPORT_DEF( const char* )
FT_Get_X11_Font_Format( FT_Face face )
{
const char* result = NULL;
if ( face )
FT_FACE_FIND_SERVICE( face, result, FONT_FORMAT );
return result;
}
/* END */

61
thirdparty/freetype/src/base/ftfstype.c vendored Normal file
View File

@@ -0,0 +1,61 @@
/****************************************************************************
*
* ftfstype.c
*
* FreeType utility file to access FSType data (body).
*
* Copyright (C) 2008-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/t1tables.h>
#include <freetype/tttables.h>
#include <freetype/internal/ftserv.h>
#include <freetype/internal/services/svpsinfo.h>
/* documentation is in freetype.h */
FT_EXPORT_DEF( FT_UShort )
FT_Get_FSType_Flags( FT_Face face )
{
TT_OS2* os2;
/* first, try to get the fs_type directly from the font */
if ( face )
{
FT_Service_PsInfo service = NULL;
FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
if ( service && service->ps_get_font_extra )
{
PS_FontExtraRec extra;
if ( !service->ps_get_font_extra( face, &extra ) &&
extra.fs_type != 0 )
return extra.fs_type;
}
}
/* look at FSType before fsType for Type42 */
if ( ( os2 = (TT_OS2*)FT_Get_Sfnt_Table( face, FT_SFNT_OS2 ) ) != NULL &&
os2->version != 0xFFFFU )
return os2->fsType;
return 0;
}
/* END */

60
thirdparty/freetype/src/base/ftgasp.c vendored Normal file
View File

@@ -0,0 +1,60 @@
/****************************************************************************
*
* ftgasp.c
*
* Access of TrueType's `gasp' table (body).
*
* Copyright (C) 2007-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/ftgasp.h>
#include <freetype/internal/tttypes.h>
FT_EXPORT_DEF( FT_Int )
FT_Get_Gasp( FT_Face face,
FT_UInt ppem )
{
FT_Int result = FT_GASP_NO_TABLE;
if ( face && FT_IS_SFNT( face ) )
{
TT_Face ttface = (TT_Face)face;
if ( ttface->gasp.numRanges > 0 )
{
TT_GaspRange range = ttface->gasp.gaspRanges;
TT_GaspRange range_end = range + ttface->gasp.numRanges;
while ( ppem > range->maxPPEM )
{
range++;
if ( range >= range_end )
goto Exit;
}
result = range->gaspFlag;
/* ensure that we don't have spurious bits */
if ( ttface->gasp.version == 0 )
result &= 3;
}
}
Exit:
return result;
}
/* END */

383
thirdparty/freetype/src/base/ftgloadr.c vendored Normal file
View File

@@ -0,0 +1,383 @@
/****************************************************************************
*
* ftgloadr.c
*
* The FreeType glyph loader (body).
*
* Copyright (C) 2002-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/internal/ftdebug.h>
#include <freetype/internal/ftgloadr.h>
#include <freetype/internal/ftmemory.h>
#include <freetype/internal/ftobjs.h>
#undef FT_COMPONENT
#define FT_COMPONENT gloader
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** *****/
/***** G L Y P H L O A D E R *****/
/***** *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**************************************************************************
*
* The glyph loader is a simple object which is used to load a set of
* glyphs easily. It is critical for the correct loading of composites.
*
* Ideally, one can see it as a stack of abstract `glyph' objects.
*
* loader.base Is really the bottom of the stack. It describes a
* single glyph image made of the juxtaposition of
* several glyphs (those `in the stack').
*
* loader.current Describes the top of the stack, on which a new
* glyph can be loaded.
*
* Rewind Clears the stack.
* Prepare Set up `loader.current' for addition of a new glyph
* image.
* Add Add the `current' glyph image to the `base' one,
* and prepare for another one.
*
* The glyph loader is now a base object. Each driver used to
* re-implement it in one way or the other, which wasted code and
* energy.
*
*/
/* create a new glyph loader */
FT_BASE_DEF( FT_Error )
FT_GlyphLoader_New( FT_Memory memory,
FT_GlyphLoader *aloader )
{
FT_GlyphLoader loader = NULL;
FT_Error error;
if ( !FT_NEW( loader ) )
{
loader->memory = memory;
*aloader = loader;
}
return error;
}
/* rewind the glyph loader - reset counters to 0 */
FT_BASE_DEF( void )
FT_GlyphLoader_Rewind( FT_GlyphLoader loader )
{
FT_GlyphLoad base = &loader->base;
FT_GlyphLoad current = &loader->current;
base->outline.n_points = 0;
base->outline.n_contours = 0;
base->outline.flags = 0;
base->num_subglyphs = 0;
*current = *base;
}
/* reset glyph loader, free all allocated tables, */
/* and start from zero */
FT_BASE_DEF( void )
FT_GlyphLoader_Reset( FT_GlyphLoader loader )
{
FT_Memory memory = loader->memory;
FT_FREE( loader->base.outline.points );
FT_FREE( loader->base.outline.tags );
FT_FREE( loader->base.outline.contours );
FT_FREE( loader->base.extra_points );
FT_FREE( loader->base.subglyphs );
loader->base.extra_points2 = NULL;
loader->max_points = 0;
loader->max_contours = 0;
loader->max_subglyphs = 0;
FT_GlyphLoader_Rewind( loader );
}
/* delete a glyph loader */
FT_BASE_DEF( void )
FT_GlyphLoader_Done( FT_GlyphLoader loader )
{
if ( loader )
{
FT_Memory memory = loader->memory;
FT_GlyphLoader_Reset( loader );
FT_FREE( loader );
}
}
/* re-adjust the `current' outline fields */
static void
FT_GlyphLoader_Adjust_Points( FT_GlyphLoader loader )
{
FT_Outline* base = &loader->base.outline;
FT_Outline* current = &loader->current.outline;
current->points = FT_OFFSET( base->points, base->n_points );
current->tags = FT_OFFSET( base->tags, base->n_points );
current->contours = FT_OFFSET( base->contours, base->n_contours );
/* handle extra points table - if any */
if ( loader->use_extra )
{
loader->current.extra_points = loader->base.extra_points +
base->n_points;
loader->current.extra_points2 = loader->base.extra_points2 +
base->n_points;
}
}
FT_BASE_DEF( FT_Error )
FT_GlyphLoader_CreateExtra( FT_GlyphLoader loader )
{
FT_Error error;
FT_Memory memory = loader->memory;
if ( loader->max_points == 0 ||
loader->base.extra_points != NULL )
return FT_Err_Ok;
if ( !FT_NEW_ARRAY( loader->base.extra_points, 2 * loader->max_points ) )
{
loader->use_extra = 1;
loader->base.extra_points2 = loader->base.extra_points +
loader->max_points;
FT_GlyphLoader_Adjust_Points( loader );
}
return error;
}
/* re-adjust the `current' subglyphs field */
static void
FT_GlyphLoader_Adjust_Subglyphs( FT_GlyphLoader loader )
{
FT_GlyphLoad base = &loader->base;
FT_GlyphLoad current = &loader->current;
current->subglyphs = FT_OFFSET( base->subglyphs, base->num_subglyphs );
}
/* Ensure that we can add `n_points' and `n_contours' to our glyph. */
/* This function reallocates its outline tables if necessary. Note that */
/* it DOESN'T change the number of points within the loader! */
/* */
FT_BASE_DEF( FT_Error )
FT_GlyphLoader_CheckPoints( FT_GlyphLoader loader,
FT_UInt n_points,
FT_UInt n_contours )
{
FT_Memory memory = loader->memory;
FT_Error error = FT_Err_Ok;
FT_Outline* base = &loader->base.outline;
FT_Outline* current = &loader->current.outline;
FT_Bool adjust = 0;
FT_UInt new_max, old_max, min_new_max;
error = FT_GlyphLoader_CreateExtra( loader );
if ( error )
goto Exit;
/* check points & tags */
new_max = (FT_UInt)base->n_points + (FT_UInt)current->n_points +
n_points;
old_max = loader->max_points;
if ( new_max > old_max )
{
if ( new_max > FT_OUTLINE_POINTS_MAX )
{
error = FT_THROW( Array_Too_Large );
goto Exit;
}
min_new_max = old_max + ( old_max >> 1 );
if ( new_max < min_new_max )
new_max = min_new_max;
new_max = FT_PAD_CEIL( new_max, 8 );
if ( new_max > FT_OUTLINE_POINTS_MAX )
new_max = FT_OUTLINE_POINTS_MAX;
if ( FT_RENEW_ARRAY( base->points, old_max, new_max ) ||
FT_RENEW_ARRAY( base->tags, old_max, new_max ) )
goto Exit;
if ( loader->use_extra )
{
if ( FT_RENEW_ARRAY( loader->base.extra_points,
old_max * 2, new_max * 2 ) )
goto Exit;
FT_ARRAY_MOVE( loader->base.extra_points + new_max,
loader->base.extra_points + old_max,
old_max );
loader->base.extra_points2 = loader->base.extra_points + new_max;
}
adjust = 1;
loader->max_points = new_max;
}
error = FT_GlyphLoader_CreateExtra( loader );
if ( error )
goto Exit;
/* check contours */
old_max = loader->max_contours;
new_max = (FT_UInt)base->n_contours + (FT_UInt)current->n_contours +
n_contours;
if ( new_max > old_max )
{
if ( new_max > FT_OUTLINE_CONTOURS_MAX )
{
error = FT_THROW( Array_Too_Large );
goto Exit;
}
min_new_max = old_max + ( old_max >> 1 );
if ( new_max < min_new_max )
new_max = min_new_max;
new_max = FT_PAD_CEIL( new_max, 4 );
if ( new_max > FT_OUTLINE_CONTOURS_MAX )
new_max = FT_OUTLINE_CONTOURS_MAX;
if ( FT_RENEW_ARRAY( base->contours, old_max, new_max ) )
goto Exit;
adjust = 1;
loader->max_contours = new_max;
}
if ( adjust )
FT_GlyphLoader_Adjust_Points( loader );
Exit:
if ( error )
FT_GlyphLoader_Reset( loader );
return error;
}
/* Ensure that we can add `n_subglyphs' to our glyph. this function */
/* reallocates its subglyphs table if necessary. Note that it DOES */
/* NOT change the number of subglyphs within the loader! */
/* */
FT_BASE_DEF( FT_Error )
FT_GlyphLoader_CheckSubGlyphs( FT_GlyphLoader loader,
FT_UInt n_subs )
{
FT_Memory memory = loader->memory;
FT_Error error = FT_Err_Ok;
FT_UInt new_max, old_max;
FT_GlyphLoad base = &loader->base;
FT_GlyphLoad current = &loader->current;
new_max = base->num_subglyphs + current->num_subglyphs + n_subs;
old_max = loader->max_subglyphs;
if ( new_max > old_max )
{
new_max = FT_PAD_CEIL( new_max, 2 );
if ( FT_RENEW_ARRAY( base->subglyphs, old_max, new_max ) )
goto Exit;
loader->max_subglyphs = new_max;
FT_GlyphLoader_Adjust_Subglyphs( loader );
}
Exit:
return error;
}
/* prepare loader for the addition of a new glyph on top of the base one */
FT_BASE_DEF( void )
FT_GlyphLoader_Prepare( FT_GlyphLoader loader )
{
FT_GlyphLoad current = &loader->current;
current->outline.n_points = 0;
current->outline.n_contours = 0;
current->num_subglyphs = 0;
FT_GlyphLoader_Adjust_Points ( loader );
FT_GlyphLoader_Adjust_Subglyphs( loader );
}
/* add current glyph to the base image -- and prepare for another */
FT_BASE_DEF( void )
FT_GlyphLoader_Add( FT_GlyphLoader loader )
{
FT_Outline* base;
FT_Outline* current;
FT_Int n;
if ( !loader )
return;
base = &loader->base.outline;
current = &loader->current.outline;
/* adjust contours count in newest outline */
for ( n = 0; n < current->n_contours; n++ )
current->contours[n] += base->n_points;
base->n_points += current->n_points;
base->n_contours += current->n_contours;
loader->base.num_subglyphs += loader->current.num_subglyphs;
/* prepare for another new glyph image */
FT_GlyphLoader_Prepare( loader );
}
/* END */

911
thirdparty/freetype/src/base/ftglyph.c vendored Normal file
View File

@@ -0,0 +1,911 @@
/****************************************************************************
*
* ftglyph.c
*
* FreeType convenience functions to handle glyphs (body).
*
* Copyright (C) 1996-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
/**************************************************************************
*
* This file contains the definition of several convenience functions
* that can be used by client applications to easily retrieve glyph
* bitmaps and outlines from a given face.
*
* These functions should be optional if you are writing a font server
* or text layout engine on top of FreeType. However, they are pretty
* handy for many other simple uses of the library.
*
*/
#include <freetype/internal/ftdebug.h>
#include <freetype/ftglyph.h>
#include <freetype/ftoutln.h>
#include <freetype/ftbitmap.h>
#include <freetype/internal/ftobjs.h>
#include <freetype/otsvg.h>
#include "ftbase.h"
/**************************************************************************
*
* The macro FT_COMPONENT is used in trace mode. It is an implicit
* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
* messages during execution.
*/
#undef FT_COMPONENT
#define FT_COMPONENT glyph
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** FT_BitmapGlyph support ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
FT_CALLBACK_DEF( FT_Error )
ft_bitmap_glyph_init( FT_Glyph bitmap_glyph,
FT_GlyphSlot slot )
{
FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph;
FT_Error error = FT_Err_Ok;
FT_Library library = FT_GLYPH( glyph )->library;
if ( slot->format != FT_GLYPH_FORMAT_BITMAP )
{
error = FT_THROW( Invalid_Glyph_Format );
goto Exit;
}
glyph->left = slot->bitmap_left;
glyph->top = slot->bitmap_top;
/* do lazy copying whenever possible */
if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
{
glyph->bitmap = slot->bitmap;
slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
}
else
{
FT_Bitmap_Init( &glyph->bitmap );
error = FT_Bitmap_Copy( library, &slot->bitmap, &glyph->bitmap );
}
Exit:
return error;
}
FT_CALLBACK_DEF( FT_Error )
ft_bitmap_glyph_copy( FT_Glyph bitmap_source,
FT_Glyph bitmap_target )
{
FT_Library library = bitmap_source->library;
FT_BitmapGlyph source = (FT_BitmapGlyph)bitmap_source;
FT_BitmapGlyph target = (FT_BitmapGlyph)bitmap_target;
target->left = source->left;
target->top = source->top;
return FT_Bitmap_Copy( library, &source->bitmap, &target->bitmap );
}
FT_CALLBACK_DEF( void )
ft_bitmap_glyph_done( FT_Glyph bitmap_glyph )
{
FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph;
FT_Library library = FT_GLYPH( glyph )->library;
FT_Bitmap_Done( library, &glyph->bitmap );
}
FT_CALLBACK_DEF( void )
ft_bitmap_glyph_bbox( FT_Glyph bitmap_glyph,
FT_BBox* cbox )
{
FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph;
cbox->xMin = glyph->left * 64;
cbox->xMax = cbox->xMin + (FT_Pos)( glyph->bitmap.width * 64 );
cbox->yMax = glyph->top * 64;
cbox->yMin = cbox->yMax - (FT_Pos)( glyph->bitmap.rows * 64 );
}
FT_DEFINE_GLYPH(
ft_bitmap_glyph_class,
sizeof ( FT_BitmapGlyphRec ),
FT_GLYPH_FORMAT_BITMAP,
ft_bitmap_glyph_init, /* FT_Glyph_InitFunc glyph_init */
ft_bitmap_glyph_done, /* FT_Glyph_DoneFunc glyph_done */
ft_bitmap_glyph_copy, /* FT_Glyph_CopyFunc glyph_copy */
NULL, /* FT_Glyph_TransformFunc glyph_transform */
ft_bitmap_glyph_bbox, /* FT_Glyph_GetBBoxFunc glyph_bbox */
NULL /* FT_Glyph_PrepareFunc glyph_prepare */
)
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** FT_OutlineGlyph support ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
FT_CALLBACK_DEF( FT_Error )
ft_outline_glyph_init( FT_Glyph outline_glyph,
FT_GlyphSlot slot )
{
FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;
FT_Error error = FT_Err_Ok;
FT_Library library = FT_GLYPH( glyph )->library;
FT_Outline* source = &slot->outline;
FT_Outline* target = &glyph->outline;
/* check format in glyph slot */
if ( slot->format != FT_GLYPH_FORMAT_OUTLINE )
{
error = FT_THROW( Invalid_Glyph_Format );
goto Exit;
}
/* allocate new outline */
error = FT_Outline_New( library,
(FT_UInt)source->n_points,
source->n_contours,
&glyph->outline );
if ( error )
goto Exit;
FT_Outline_Copy( source, target );
Exit:
return error;
}
FT_CALLBACK_DEF( void )
ft_outline_glyph_done( FT_Glyph outline_glyph )
{
FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;
FT_Outline_Done( FT_GLYPH( glyph )->library, &glyph->outline );
}
FT_CALLBACK_DEF( FT_Error )
ft_outline_glyph_copy( FT_Glyph outline_source,
FT_Glyph outline_target )
{
FT_OutlineGlyph source = (FT_OutlineGlyph)outline_source;
FT_OutlineGlyph target = (FT_OutlineGlyph)outline_target;
FT_Error error;
FT_Library library = FT_GLYPH( source )->library;
error = FT_Outline_New( library,
(FT_UInt)source->outline.n_points,
source->outline.n_contours,
&target->outline );
if ( !error )
FT_Outline_Copy( &source->outline, &target->outline );
return error;
}
FT_CALLBACK_DEF( void )
ft_outline_glyph_transform( FT_Glyph outline_glyph,
const FT_Matrix* matrix,
const FT_Vector* delta )
{
FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;
if ( matrix )
FT_Outline_Transform( &glyph->outline, matrix );
if ( delta )
FT_Outline_Translate( &glyph->outline, delta->x, delta->y );
}
FT_CALLBACK_DEF( void )
ft_outline_glyph_bbox( FT_Glyph outline_glyph,
FT_BBox* bbox )
{
FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;
FT_Outline_Get_CBox( &glyph->outline, bbox );
}
FT_CALLBACK_DEF( FT_Error )
ft_outline_glyph_prepare( FT_Glyph outline_glyph,
FT_GlyphSlot slot )
{
FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;
slot->format = FT_GLYPH_FORMAT_OUTLINE;
slot->outline = glyph->outline;
slot->outline.flags &= ~FT_OUTLINE_OWNER;
return FT_Err_Ok;
}
FT_DEFINE_GLYPH(
ft_outline_glyph_class,
sizeof ( FT_OutlineGlyphRec ),
FT_GLYPH_FORMAT_OUTLINE,
ft_outline_glyph_init, /* FT_Glyph_InitFunc glyph_init */
ft_outline_glyph_done, /* FT_Glyph_DoneFunc glyph_done */
ft_outline_glyph_copy, /* FT_Glyph_CopyFunc glyph_copy */
ft_outline_glyph_transform, /* FT_Glyph_TransformFunc glyph_transform */
ft_outline_glyph_bbox, /* FT_Glyph_GetBBoxFunc glyph_bbox */
ft_outline_glyph_prepare /* FT_Glyph_PrepareFunc glyph_prepare */
)
#ifdef FT_CONFIG_OPTION_SVG
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** FT_SvgGlyph support ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
FT_CALLBACK_DEF( FT_Error )
ft_svg_glyph_init( FT_Glyph svg_glyph,
FT_GlyphSlot slot )
{
FT_ULong doc_length;
FT_SVG_Document document;
FT_SvgGlyph glyph = (FT_SvgGlyph)svg_glyph;
FT_Error error = FT_Err_Ok;
FT_Memory memory = FT_GLYPH( glyph )->library->memory;
if ( slot->format != FT_GLYPH_FORMAT_SVG )
{
error = FT_THROW( Invalid_Glyph_Format );
goto Exit;
}
if ( slot->other == NULL )
{
error = FT_THROW( Invalid_Slot_Handle );
goto Exit;
}
document = (FT_SVG_Document)slot->other;
if ( document->svg_document_length == 0 )
{
error = FT_THROW( Invalid_Slot_Handle );
goto Exit;
}
/* allocate a new document */
doc_length = document->svg_document_length;
if ( FT_QALLOC( glyph->svg_document, doc_length ) )
goto Exit;
glyph->svg_document_length = doc_length;
glyph->glyph_index = slot->glyph_index;
glyph->metrics = document->metrics;
glyph->units_per_EM = document->units_per_EM;
glyph->start_glyph_id = document->start_glyph_id;
glyph->end_glyph_id = document->end_glyph_id;
glyph->transform = document->transform;
glyph->delta = document->delta;
/* copy the document into glyph */
FT_MEM_COPY( glyph->svg_document, document->svg_document, doc_length );
Exit:
return error;
}
FT_CALLBACK_DEF( void )
ft_svg_glyph_done( FT_Glyph svg_glyph )
{
FT_SvgGlyph glyph = (FT_SvgGlyph)svg_glyph;
FT_Memory memory = svg_glyph->library->memory;
/* just free the memory */
FT_FREE( glyph->svg_document );
}
FT_CALLBACK_DEF( FT_Error )
ft_svg_glyph_copy( FT_Glyph svg_source,
FT_Glyph svg_target )
{
FT_SvgGlyph source = (FT_SvgGlyph)svg_source;
FT_SvgGlyph target = (FT_SvgGlyph)svg_target;
FT_Error error = FT_Err_Ok;
FT_Memory memory = FT_GLYPH( source )->library->memory;
if ( svg_source->format != FT_GLYPH_FORMAT_SVG )
{
error = FT_THROW( Invalid_Glyph_Format );
goto Exit;
}
if ( source->svg_document_length == 0 )
{
error = FT_THROW( Invalid_Slot_Handle );
goto Exit;
}
target->glyph_index = source->glyph_index;
target->svg_document_length = source->svg_document_length;
target->metrics = source->metrics;
target->units_per_EM = source->units_per_EM;
target->start_glyph_id = source->start_glyph_id;
target->end_glyph_id = source->end_glyph_id;
target->transform = source->transform;
target->delta = source->delta;
/* allocate space for the SVG document */
if ( FT_QALLOC( target->svg_document, target->svg_document_length ) )
goto Exit;
/* copy the document */
FT_MEM_COPY( target->svg_document,
source->svg_document,
target->svg_document_length );
Exit:
return error;
}
FT_CALLBACK_DEF( void )
ft_svg_glyph_transform( FT_Glyph svg_glyph,
const FT_Matrix* _matrix,
const FT_Vector* _delta )
{
FT_SvgGlyph glyph = (FT_SvgGlyph)svg_glyph;
FT_Matrix* matrix = (FT_Matrix*)_matrix;
FT_Vector* delta = (FT_Vector*)_delta;
FT_Matrix tmp_matrix;
FT_Vector tmp_delta;
FT_Matrix a, b;
FT_Pos x, y;
if ( !matrix )
{
tmp_matrix.xx = 0x10000;
tmp_matrix.xy = 0;
tmp_matrix.yx = 0;
tmp_matrix.yy = 0x10000;
matrix = &tmp_matrix;
}
if ( !delta )
{
tmp_delta.x = 0;
tmp_delta.y = 0;
delta = &tmp_delta;
}
a = glyph->transform;
b = *matrix;
FT_Matrix_Multiply( &b, &a );
x = ADD_LONG( ADD_LONG( FT_MulFix( matrix->xx, glyph->delta.x ),
FT_MulFix( matrix->xy, glyph->delta.y ) ),
delta->x );
y = ADD_LONG( ADD_LONG( FT_MulFix( matrix->yx, glyph->delta.x ),
FT_MulFix( matrix->yy, glyph->delta.y ) ),
delta->y );
glyph->delta.x = x;
glyph->delta.y = y;
glyph->transform = a;
}
FT_CALLBACK_DEF( FT_Error )
ft_svg_glyph_prepare( FT_Glyph svg_glyph,
FT_GlyphSlot slot )
{
FT_SvgGlyph glyph = (FT_SvgGlyph)svg_glyph;
FT_Error error = FT_Err_Ok;
FT_Memory memory = svg_glyph->library->memory;
FT_SVG_Document document = NULL;
if ( FT_NEW( document ) )
return error;
document->svg_document = glyph->svg_document;
document->svg_document_length = glyph->svg_document_length;
document->metrics = glyph->metrics;
document->units_per_EM = glyph->units_per_EM;
document->start_glyph_id = glyph->start_glyph_id;
document->end_glyph_id = glyph->end_glyph_id;
document->transform = glyph->transform;
document->delta = glyph->delta;
slot->format = FT_GLYPH_FORMAT_SVG;
slot->glyph_index = glyph->glyph_index;
slot->other = document;
return error;
}
FT_DEFINE_GLYPH(
ft_svg_glyph_class,
sizeof ( FT_SvgGlyphRec ),
FT_GLYPH_FORMAT_SVG,
ft_svg_glyph_init, /* FT_Glyph_InitFunc glyph_init */
ft_svg_glyph_done, /* FT_Glyph_DoneFunc glyph_done */
ft_svg_glyph_copy, /* FT_Glyph_CopyFunc glyph_copy */
ft_svg_glyph_transform, /* FT_Glyph_TransformFunc glyph_transform */
NULL, /* FT_Glyph_GetBBoxFunc glyph_bbox */
ft_svg_glyph_prepare /* FT_Glyph_PrepareFunc glyph_prepare */
)
#endif /* FT_CONFIG_OPTION_SVG */
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** FT_Glyph class and API ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
static FT_Error
ft_new_glyph( FT_Library library,
const FT_Glyph_Class* clazz,
FT_Glyph* aglyph )
{
FT_Memory memory = library->memory;
FT_Error error;
FT_Glyph glyph = NULL;
*aglyph = NULL;
if ( !FT_ALLOC( glyph, clazz->glyph_size ) )
{
glyph->library = library;
glyph->clazz = clazz;
glyph->format = clazz->glyph_format;
*aglyph = glyph;
}
return error;
}
/* documentation is in ftglyph.h */
FT_EXPORT_DEF( FT_Error )
FT_Glyph_Copy( FT_Glyph source,
FT_Glyph *target )
{
FT_Glyph copy;
FT_Error error;
const FT_Glyph_Class* clazz;
/* check arguments */
if ( !target || !source || !source->clazz )
{
error = FT_THROW( Invalid_Argument );
goto Exit;
}
*target = NULL;
if ( !source || !source->clazz )
{
error = FT_THROW( Invalid_Argument );
goto Exit;
}
clazz = source->clazz;
error = ft_new_glyph( source->library, clazz, &copy );
if ( error )
goto Exit;
copy->advance = source->advance;
copy->format = source->format;
if ( clazz->glyph_copy )
error = clazz->glyph_copy( source, copy );
if ( error )
FT_Done_Glyph( copy );
else
*target = copy;
Exit:
return error;
}
/* documentation is in ftglyph.h */
FT_EXPORT( FT_Error )
FT_New_Glyph( FT_Library library,
FT_Glyph_Format format,
FT_Glyph *aglyph )
{
const FT_Glyph_Class* clazz = NULL;
if ( !library || !aglyph )
return FT_THROW( Invalid_Argument );
/* if it is a bitmap, that's easy :-) */
if ( format == FT_GLYPH_FORMAT_BITMAP )
clazz = &ft_bitmap_glyph_class;
/* if it is an outline */
else if ( format == FT_GLYPH_FORMAT_OUTLINE )
clazz = &ft_outline_glyph_class;
#ifdef FT_CONFIG_OPTION_SVG
/* if it is an SVG glyph */
else if ( format == FT_GLYPH_FORMAT_SVG )
clazz = &ft_svg_glyph_class;
#endif
else
{
/* try to find a renderer that supports the glyph image format */
FT_Renderer render = FT_Lookup_Renderer( library, format, 0 );
if ( render )
clazz = &render->glyph_class;
}
if ( !clazz )
return FT_THROW( Invalid_Glyph_Format );
/* create FT_Glyph object */
return ft_new_glyph( library, clazz, aglyph );
}
/* documentation is in ftglyph.h */
FT_EXPORT_DEF( FT_Error )
FT_Get_Glyph( FT_GlyphSlot slot,
FT_Glyph *aglyph )
{
FT_Error error;
FT_Glyph glyph;
if ( !slot )
return FT_THROW( Invalid_Slot_Handle );
if ( !aglyph )
return FT_THROW( Invalid_Argument );
/* create FT_Glyph object */
error = FT_New_Glyph( slot->library, slot->format, &glyph );
if ( error )
goto Exit;
/* copy advance while converting 26.6 to 16.16 format */
if ( slot->advance.x >= 0x8000L * 64 ||
slot->advance.x <= -0x8000L * 64 )
{
FT_ERROR(( "FT_Get_Glyph: advance width too large\n" ));
error = FT_THROW( Invalid_Argument );
goto Exit2;
}
if ( slot->advance.y >= 0x8000L * 64 ||
slot->advance.y <= -0x8000L * 64 )
{
FT_ERROR(( "FT_Get_Glyph: advance height too large\n" ));
error = FT_THROW( Invalid_Argument );
goto Exit2;
}
glyph->advance.x = slot->advance.x * 1024;
glyph->advance.y = slot->advance.y * 1024;
/* now import the image from the glyph slot */
error = glyph->clazz->glyph_init( glyph, slot );
Exit2:
/* if an error occurred, destroy the glyph */
if ( error )
{
FT_Done_Glyph( glyph );
*aglyph = NULL;
}
else
*aglyph = glyph;
Exit:
return error;
}
/* documentation is in ftglyph.h */
FT_EXPORT_DEF( FT_Error )
FT_Glyph_Transform( FT_Glyph glyph,
const FT_Matrix* matrix,
const FT_Vector* delta )
{
FT_Error error = FT_Err_Ok;
if ( !glyph || !glyph->clazz )
error = FT_THROW( Invalid_Argument );
else
{
const FT_Glyph_Class* clazz = glyph->clazz;
if ( clazz->glyph_transform )
{
/* transform glyph image */
clazz->glyph_transform( glyph, matrix, delta );
/* transform advance vector */
if ( matrix )
FT_Vector_Transform( &glyph->advance, matrix );
}
else
error = FT_THROW( Invalid_Glyph_Format );
}
return error;
}
/* documentation is in ftglyph.h */
FT_EXPORT_DEF( void )
FT_Glyph_Get_CBox( FT_Glyph glyph,
FT_UInt bbox_mode,
FT_BBox *acbox )
{
const FT_Glyph_Class* clazz;
if ( !acbox )
return;
acbox->xMin = acbox->yMin = acbox->xMax = acbox->yMax = 0;
if ( !glyph || !glyph->clazz )
return;
clazz = glyph->clazz;
if ( !clazz->glyph_bbox )
return;
/* retrieve bbox in 26.6 coordinates */
clazz->glyph_bbox( glyph, acbox );
/* perform grid fitting if needed */
if ( bbox_mode == FT_GLYPH_BBOX_GRIDFIT ||
bbox_mode == FT_GLYPH_BBOX_PIXELS )
{
acbox->xMin = FT_PIX_FLOOR( acbox->xMin );
acbox->yMin = FT_PIX_FLOOR( acbox->yMin );
acbox->xMax = FT_PIX_CEIL_LONG( acbox->xMax );
acbox->yMax = FT_PIX_CEIL_LONG( acbox->yMax );
}
/* convert to integer pixels if needed */
if ( bbox_mode == FT_GLYPH_BBOX_TRUNCATE ||
bbox_mode == FT_GLYPH_BBOX_PIXELS )
{
acbox->xMin >>= 6;
acbox->yMin >>= 6;
acbox->xMax >>= 6;
acbox->yMax >>= 6;
}
}
/* documentation is in ftglyph.h */
FT_EXPORT_DEF( FT_Error )
FT_Glyph_To_Bitmap( FT_Glyph* the_glyph,
FT_Render_Mode render_mode,
const FT_Vector* origin,
FT_Bool destroy )
{
FT_GlyphSlotRec dummy;
FT_GlyphSlot_InternalRec dummy_internal;
FT_Error error = FT_Err_Ok;
FT_Glyph b, glyph;
FT_BitmapGlyph bitmap = NULL;
const FT_Glyph_Class* clazz;
FT_Library library;
/* check argument */
if ( !the_glyph )
goto Bad;
glyph = *the_glyph;
if ( !glyph )
goto Bad;
clazz = glyph->clazz;
library = glyph->library;
if ( !library || !clazz )
goto Bad;
/* when called with a bitmap glyph, do nothing and return successfully */
if ( clazz == &ft_bitmap_glyph_class )
goto Exit;
if ( !clazz->glyph_prepare )
goto Bad;
/* we render the glyph into a glyph bitmap using a `dummy' glyph slot */
/* then calling FT_Render_Glyph_Internal() */
FT_ZERO( &dummy );
FT_ZERO( &dummy_internal );
dummy.internal = &dummy_internal;
dummy.library = library;
dummy.format = clazz->glyph_format;
/* create result bitmap glyph */
error = ft_new_glyph( library, &ft_bitmap_glyph_class, &b );
if ( error )
goto Exit;
bitmap = (FT_BitmapGlyph)b;
#if 1
/* if `origin' is set, translate the glyph image */
if ( origin )
FT_Glyph_Transform( glyph, NULL, origin );
#else
FT_UNUSED( origin );
#endif
/* prepare dummy slot for rendering */
error = clazz->glyph_prepare( glyph, &dummy );
if ( !error )
error = FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode );
#ifdef FT_CONFIG_OPTION_SVG
if ( clazz == &ft_svg_glyph_class )
{
FT_Memory memory = library->memory;
FT_FREE( dummy.other );
}
#endif
#if 1
if ( !destroy && origin )
{
FT_Vector v;
v.x = -origin->x;
v.y = -origin->y;
FT_Glyph_Transform( glyph, NULL, &v );
}
#endif
if ( error )
goto Exit;
/* in case of success, copy the bitmap to the glyph bitmap */
error = ft_bitmap_glyph_init( (FT_Glyph)bitmap, &dummy );
if ( error )
goto Exit;
/* copy advance */
bitmap->root.advance = glyph->advance;
if ( destroy )
FT_Done_Glyph( glyph );
*the_glyph = FT_GLYPH( bitmap );
Exit:
if ( error && bitmap )
FT_Done_Glyph( FT_GLYPH( bitmap ) );
return error;
Bad:
error = FT_THROW( Invalid_Argument );
goto Exit;
}
/* documentation is in ftglyph.h */
FT_EXPORT_DEF( void )
FT_Done_Glyph( FT_Glyph glyph )
{
if ( glyph )
{
FT_Memory memory = glyph->library->memory;
const FT_Glyph_Class* clazz = glyph->clazz;
if ( clazz->glyph_done )
clazz->glyph_done( glyph );
FT_FREE( glyph );
}
}
/* END */

141
thirdparty/freetype/src/base/ftgxval.c vendored Normal file
View File

@@ -0,0 +1,141 @@
/****************************************************************************
*
* ftgxval.c
*
* FreeType API for validating TrueTypeGX/AAT tables (body).
*
* Copyright (C) 2004-2024 by
* Masatake YAMATO, Redhat K.K,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
/****************************************************************************
*
* gxvalid is derived from both gxlayout module and otvalid module.
* Development of gxlayout is supported by the Information-technology
* Promotion Agency(IPA), Japan.
*
*/
#include <freetype/internal/ftdebug.h>
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/services/svgxval.h>
/* documentation is in ftgxval.h */
FT_EXPORT_DEF( FT_Error )
FT_TrueTypeGX_Validate( FT_Face face,
FT_UInt validation_flags,
FT_Bytes tables[FT_VALIDATE_GX_LENGTH],
FT_UInt table_length )
{
FT_Service_GXvalidate service;
FT_Error error;
if ( !face )
{
error = FT_THROW( Invalid_Face_Handle );
goto Exit;
}
if ( !tables )
{
error = FT_THROW( Invalid_Argument );
goto Exit;
}
FT_FACE_FIND_GLOBAL_SERVICE( face, service, GX_VALIDATE );
if ( service )
error = service->validate( face,
validation_flags,
tables,
table_length );
else
error = FT_THROW( Unimplemented_Feature );
Exit:
return error;
}
FT_EXPORT_DEF( void )
FT_TrueTypeGX_Free( FT_Face face,
FT_Bytes table )
{
FT_Memory memory;
if ( !face )
return;
memory = FT_FACE_MEMORY( face );
FT_FREE( table );
}
FT_EXPORT_DEF( FT_Error )
FT_ClassicKern_Validate( FT_Face face,
FT_UInt validation_flags,
FT_Bytes *ckern_table )
{
FT_Service_CKERNvalidate service;
FT_Error error;
if ( !face )
{
error = FT_THROW( Invalid_Face_Handle );
goto Exit;
}
if ( !ckern_table )
{
error = FT_THROW( Invalid_Argument );
goto Exit;
}
FT_FACE_FIND_GLOBAL_SERVICE( face, service, CLASSICKERN_VALIDATE );
if ( service )
error = service->validate( face,
validation_flags,
ckern_table );
else
error = FT_THROW( Unimplemented_Feature );
Exit:
return error;
}
FT_EXPORT_DEF( void )
FT_ClassicKern_Free( FT_Face face,
FT_Bytes table )
{
FT_Memory memory;
if ( !face )
return;
memory = FT_FACE_MEMORY( face );
FT_FREE( table );
}
/* END */

338
thirdparty/freetype/src/base/fthash.c vendored Normal file
View File

@@ -0,0 +1,338 @@
/****************************************************************************
*
* fthash.c
*
* Hashing functions (body).
*
*/
/*
* Copyright 2000 Computing Research Labs, New Mexico State University
* Copyright 2001-2015
* Francesco Zappa Nardelli
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
* OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**************************************************************************
*
* This file is based on code from bdf.c,v 1.22 2000/03/16 20:08:50
*
* taken from Mark Leisher's xmbdfed package
*
*/
#include <freetype/internal/fthash.h>
#include <freetype/internal/ftmemory.h>
#define INITIAL_HT_SIZE 241
static FT_ULong
hash_str_lookup( FT_Hashkey* key )
{
const char* kp = key->str;
FT_ULong res = 0;
/* Mocklisp hash function. */
while ( *kp )
res = ( res << 5 ) - res + (FT_ULong)*kp++;
return res;
}
static FT_ULong
hash_num_lookup( FT_Hashkey* key )
{
FT_ULong num = (FT_ULong)key->num;
FT_ULong res;
/* Mocklisp hash function. */
res = num & 0xFF;
res = ( res << 5 ) - res + ( ( num >> 8 ) & 0xFF );
res = ( res << 5 ) - res + ( ( num >> 16 ) & 0xFF );
res = ( res << 5 ) - res + ( ( num >> 24 ) & 0xFF );
return res;
}
static FT_Bool
hash_str_compare( FT_Hashkey* a,
FT_Hashkey* b )
{
if ( a->str[0] == b->str[0] &&
ft_strcmp( a->str, b->str ) == 0 )
return 1;
return 0;
}
static FT_Bool
hash_num_compare( FT_Hashkey* a,
FT_Hashkey* b )
{
if ( a->num == b->num )
return 1;
return 0;
}
static FT_Hashnode*
hash_bucket( FT_Hashkey key,
FT_Hash hash )
{
FT_ULong res = 0;
FT_Hashnode* bp = hash->table;
FT_Hashnode* ndp;
res = (hash->lookup)( &key );
ndp = bp + ( res % hash->size );
while ( *ndp )
{
if ( (hash->compare)( &(*ndp)->key, &key ) )
break;
ndp--;
if ( ndp < bp )
ndp = bp + ( hash->size - 1 );
}
return ndp;
}
static FT_Error
hash_rehash( FT_Hash hash,
FT_Memory memory )
{
FT_Hashnode* obp = hash->table;
FT_Hashnode* bp;
FT_Hashnode* nbp;
FT_UInt i, sz = hash->size;
FT_Error error = FT_Err_Ok;
hash->size <<= 1;
hash->limit = hash->size / 3;
if ( FT_NEW_ARRAY( hash->table, hash->size ) )
goto Exit;
for ( i = 0, bp = obp; i < sz; i++, bp++ )
{
if ( *bp )
{
nbp = hash_bucket( (*bp)->key, hash );
*nbp = *bp;
}
}
FT_FREE( obp );
Exit:
return error;
}
static FT_Error
hash_init( FT_Hash hash,
FT_Bool is_num,
FT_Memory memory )
{
FT_UInt sz = INITIAL_HT_SIZE;
FT_Error error;
hash->size = sz;
hash->limit = sz / 3;
hash->used = 0;
if ( is_num )
{
hash->lookup = hash_num_lookup;
hash->compare = hash_num_compare;
}
else
{
hash->lookup = hash_str_lookup;
hash->compare = hash_str_compare;
}
FT_MEM_NEW_ARRAY( hash->table, sz );
return error;
}
FT_Error
ft_hash_str_init( FT_Hash hash,
FT_Memory memory )
{
return hash_init( hash, 0, memory );
}
FT_Error
ft_hash_num_init( FT_Hash hash,
FT_Memory memory )
{
return hash_init( hash, 1, memory );
}
void
ft_hash_str_free( FT_Hash hash,
FT_Memory memory )
{
if ( hash )
{
FT_UInt sz = hash->size;
FT_Hashnode* bp = hash->table;
FT_UInt i;
for ( i = 0; i < sz; i++, bp++ )
FT_FREE( *bp );
FT_FREE( hash->table );
}
}
/* `ft_hash_num_free' is the same as `ft_hash_str_free' */
static FT_Error
hash_insert( FT_Hashkey key,
size_t data,
FT_Hash hash,
FT_Memory memory )
{
FT_Hashnode nn;
FT_Hashnode* bp = hash_bucket( key, hash );
FT_Error error = FT_Err_Ok;
nn = *bp;
if ( !nn )
{
if ( FT_QNEW( nn ) )
goto Exit;
*bp = nn;
nn->key = key;
nn->data = data;
if ( hash->used >= hash->limit )
{
error = hash_rehash( hash, memory );
if ( error )
goto Exit;
}
hash->used++;
}
else
nn->data = data;
Exit:
return error;
}
FT_Error
ft_hash_str_insert( const char* key,
size_t data,
FT_Hash hash,
FT_Memory memory )
{
FT_Hashkey hk;
hk.str = key;
return hash_insert( hk, data, hash, memory );
}
FT_Error
ft_hash_num_insert( FT_Int num,
size_t data,
FT_Hash hash,
FT_Memory memory )
{
FT_Hashkey hk;
hk.num = num;
return hash_insert( hk, data, hash, memory );
}
static size_t*
hash_lookup( FT_Hashkey key,
FT_Hash hash )
{
FT_Hashnode* np = hash_bucket( key, hash );
return (*np) ? &(*np)->data
: NULL;
}
size_t*
ft_hash_str_lookup( const char* key,
FT_Hash hash )
{
FT_Hashkey hk;
hk.str = key;
return hash_lookup( hk, hash );
}
size_t*
ft_hash_num_lookup( FT_Int num,
FT_Hash hash )
{
FT_Hashkey hk;
hk.num = num;
return hash_lookup( hk, hash );
}
/* END */

263
thirdparty/freetype/src/base/ftinit.c vendored Normal file
View File

@@ -0,0 +1,263 @@
/****************************************************************************
*
* ftinit.c
*
* FreeType initialization layer (body).
*
* Copyright (C) 1996-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
/**************************************************************************
*
* The purpose of this file is to implement the following two
* functions:
*
* FT_Add_Default_Modules():
* This function is used to add the set of default modules to a
* fresh new library object. The set is taken from the header file
* `freetype/config/ftmodule.h'. See the document `FreeType 2.0
* Build System' for more information.
*
* FT_Init_FreeType():
* This function creates a system object for the current platform,
* builds a library out of it, then calls FT_Default_Drivers().
*
* Note that even if FT_Init_FreeType() uses the implementation of the
* system object defined at build time, client applications are still
* able to provide their own `ftsystem.c'.
*
*/
#include <ft2build.h>
#include FT_CONFIG_CONFIG_H
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/ftdebug.h>
#include <freetype/ftmodapi.h>
/**************************************************************************
*
* The macro FT_COMPONENT is used in trace mode. It is an implicit
* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
* messages during execution.
*/
#undef FT_COMPONENT
#define FT_COMPONENT init
#undef FT_USE_MODULE
#ifdef __cplusplus
#define FT_USE_MODULE( type, x ) extern "C" const type x;
#else
#define FT_USE_MODULE( type, x ) extern const type x;
#endif
#include FT_CONFIG_MODULES_H
#undef FT_USE_MODULE
#define FT_USE_MODULE( type, x ) (const FT_Module_Class*)&(x),
static
const FT_Module_Class* const ft_default_modules[] =
{
#include FT_CONFIG_MODULES_H
0
};
/* documentation is in ftmodapi.h */
FT_EXPORT_DEF( void )
FT_Add_Default_Modules( FT_Library library )
{
FT_Error error;
const FT_Module_Class* const* cur;
/* GCC 4.6 warns the type difference:
* FT_Module_Class** != const FT_Module_Class* const*
*/
cur = (const FT_Module_Class* const*)ft_default_modules;
/* test for valid `library' delayed to FT_Add_Module() */
while ( *cur )
{
error = FT_Add_Module( library, *cur );
/* notify errors, but don't stop */
if ( error )
FT_TRACE0(( "FT_Add_Default_Module:"
" Cannot install `%s', error = 0x%x\n",
(*cur)->module_name, error ));
cur++;
}
}
#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
#define MAX_LENGTH 128
/* documentation is in ftmodapi.h */
FT_EXPORT_DEF( void )
FT_Set_Default_Properties( FT_Library library )
{
const char* env;
const char* p;
const char* q;
char module_name[MAX_LENGTH + 1];
char property_name[MAX_LENGTH + 1];
char property_value[MAX_LENGTH + 1];
int i;
env = ft_getenv( "FREETYPE_PROPERTIES" );
if ( !env )
return;
for ( p = env; *p; p++ )
{
/* skip leading whitespace and separators */
if ( *p == ' ' || *p == '\t' )
continue;
/* read module name, followed by `:' */
q = p;
for ( i = 0; i < MAX_LENGTH; i++ )
{
if ( !*p || *p == ':' )
break;
module_name[i] = *p++;
}
module_name[i] = '\0';
if ( !*p || *p != ':' || p == q )
break;
/* read property name, followed by `=' */
q = ++p;
for ( i = 0; i < MAX_LENGTH; i++ )
{
if ( !*p || *p == '=' )
break;
property_name[i] = *p++;
}
property_name[i] = '\0';
if ( !*p || *p != '=' || p == q )
break;
/* read property value, followed by whitespace (if any) */
q = ++p;
for ( i = 0; i < MAX_LENGTH; i++ )
{
if ( !*p || *p == ' ' || *p == '\t' )
break;
property_value[i] = *p++;
}
property_value[i] = '\0';
if ( !( *p == '\0' || *p == ' ' || *p == '\t' ) || p == q )
break;
/* we completely ignore errors */
ft_property_string_set( library,
module_name,
property_name,
property_value );
if ( !*p )
break;
}
}
#else
FT_EXPORT_DEF( void )
FT_Set_Default_Properties( FT_Library library )
{
FT_UNUSED( library );
}
#endif
/* documentation is in freetype.h */
FT_EXPORT_DEF( FT_Error )
FT_Init_FreeType( FT_Library *alibrary )
{
FT_Error error;
FT_Memory memory;
#ifdef FT_DEBUG_LOGGING
ft_logging_init();
#endif
/* check of `alibrary' delayed to `FT_New_Library' */
/* First of all, allocate a new system object -- this function is part */
/* of the system-specific component, i.e. `ftsystem.c'. */
memory = FT_New_Memory();
if ( !memory )
{
FT_ERROR(( "FT_Init_FreeType: cannot find memory manager\n" ));
return FT_THROW( Unimplemented_Feature );
}
/* build a library out of it, then fill it with the set of */
/* default drivers. */
error = FT_New_Library( memory, alibrary );
if ( error )
FT_Done_Memory( memory );
else
FT_Add_Default_Modules( *alibrary );
FT_Set_Default_Properties( *alibrary );
return error;
}
/* documentation is in freetype.h */
FT_EXPORT_DEF( FT_Error )
FT_Done_FreeType( FT_Library library )
{
FT_Memory memory;
if ( !library )
return FT_THROW( Invalid_Library_Handle );
memory = library->memory;
/* Discard the library object */
FT_Done_Library( library );
/* discard memory manager */
FT_Done_Memory( memory );
#ifdef FT_DEBUG_LOGGING
ft_logging_deinit();
#endif
return FT_Err_Ok;
}
/* END */

437
thirdparty/freetype/src/base/ftlcdfil.c vendored Normal file
View File

@@ -0,0 +1,437 @@
/****************************************************************************
*
* ftlcdfil.c
*
* FreeType API for color filtering of subpixel bitmap glyphs (body).
*
* Copyright (C) 2006-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/internal/ftdebug.h>
#include <freetype/ftlcdfil.h>
#include <freetype/ftimage.h>
#include <freetype/internal/ftobjs.h>
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
/* define USE_LEGACY to implement the legacy filter */
#define USE_LEGACY
#define FT_SHIFTCLAMP( x ) ( x >>= 8, (FT_Byte)( x > 255 ? 255 : x ) )
/* add padding according to filter weights */
FT_BASE_DEF( void )
ft_lcd_padding( FT_BBox* cbox,
FT_GlyphSlot slot,
FT_Render_Mode mode )
{
FT_Byte* lcd_weights;
FT_Bitmap_LcdFilterFunc lcd_filter_func;
/* Per-face LCD filtering takes priority if set up. */
if ( slot->face && slot->face->internal->lcd_filter_func )
{
lcd_weights = slot->face->internal->lcd_weights;
lcd_filter_func = slot->face->internal->lcd_filter_func;
}
else
{
lcd_weights = slot->library->lcd_weights;
lcd_filter_func = slot->library->lcd_filter_func;
}
if ( lcd_filter_func == ft_lcd_filter_fir )
{
if ( mode == FT_RENDER_MODE_LCD )
{
cbox->xMin -= lcd_weights[0] ? 43 :
lcd_weights[1] ? 22 : 0;
cbox->xMax += lcd_weights[4] ? 43 :
lcd_weights[3] ? 22 : 0;
}
else if ( mode == FT_RENDER_MODE_LCD_V )
{
cbox->yMin -= lcd_weights[0] ? 43 :
lcd_weights[1] ? 22 : 0;
cbox->yMax += lcd_weights[4] ? 43 :
lcd_weights[3] ? 22 : 0;
}
}
}
/* FIR filter used by the default and light filters */
FT_BASE_DEF( void )
ft_lcd_filter_fir( FT_Bitmap* bitmap,
FT_LcdFiveTapFilter weights )
{
FT_UInt width = (FT_UInt)bitmap->width;
FT_UInt height = (FT_UInt)bitmap->rows;
FT_Int pitch = bitmap->pitch;
FT_Byte* origin = bitmap->buffer;
FT_Byte mode = bitmap->pixel_mode;
/* take care of bitmap flow */
if ( pitch > 0 && height > 0 )
origin += pitch * (FT_Int)( height - 1 );
/* horizontal in-place FIR filter */
if ( mode == FT_PIXEL_MODE_LCD && width >= 2 )
{
FT_Byte* line = origin;
/* `fir' must be at least 32 bit wide, since the sum of */
/* the values in `weights' can exceed 0xFF */
for ( ; height > 0; height--, line -= pitch )
{
FT_UInt fir[5];
FT_UInt val, xx;
val = line[0];
fir[2] = weights[2] * val;
fir[3] = weights[3] * val;
fir[4] = weights[4] * val;
val = line[1];
fir[1] = fir[2] + weights[1] * val;
fir[2] = fir[3] + weights[2] * val;
fir[3] = fir[4] + weights[3] * val;
fir[4] = weights[4] * val;
for ( xx = 2; xx < width; xx++ )
{
val = line[xx];
fir[0] = fir[1] + weights[0] * val;
fir[1] = fir[2] + weights[1] * val;
fir[2] = fir[3] + weights[2] * val;
fir[3] = fir[4] + weights[3] * val;
fir[4] = weights[4] * val;
line[xx - 2] = FT_SHIFTCLAMP( fir[0] );
}
line[xx - 2] = FT_SHIFTCLAMP( fir[1] );
line[xx - 1] = FT_SHIFTCLAMP( fir[2] );
}
}
/* vertical in-place FIR filter */
else if ( mode == FT_PIXEL_MODE_LCD_V && height >= 2 )
{
FT_Byte* column = origin;
for ( ; width > 0; width--, column++ )
{
FT_Byte* col = column;
FT_UInt fir[5];
FT_UInt val, yy;
val = col[0];
fir[2] = weights[2] * val;
fir[3] = weights[3] * val;
fir[4] = weights[4] * val;
col -= pitch;
val = col[0];
fir[1] = fir[2] + weights[1] * val;
fir[2] = fir[3] + weights[2] * val;
fir[3] = fir[4] + weights[3] * val;
fir[4] = weights[4] * val;
col -= pitch;
for ( yy = 2; yy < height; yy++, col -= pitch )
{
val = col[0];
fir[0] = fir[1] + weights[0] * val;
fir[1] = fir[2] + weights[1] * val;
fir[2] = fir[3] + weights[2] * val;
fir[3] = fir[4] + weights[3] * val;
fir[4] = weights[4] * val;
col[pitch * 2] = FT_SHIFTCLAMP( fir[0] );
}
col[pitch * 2] = FT_SHIFTCLAMP( fir[1] );
col[pitch] = FT_SHIFTCLAMP( fir[2] );
}
}
}
#ifdef USE_LEGACY
/* intra-pixel filter used by the legacy filter */
static void
_ft_lcd_filter_legacy( FT_Bitmap* bitmap,
FT_Byte* weights )
{
FT_UInt width = (FT_UInt)bitmap->width;
FT_UInt height = (FT_UInt)bitmap->rows;
FT_Int pitch = bitmap->pitch;
FT_Byte* origin = bitmap->buffer;
FT_Byte mode = bitmap->pixel_mode;
static const unsigned int filters[3][3] =
{
{ 65538 * 9/13, 65538 * 1/6, 65538 * 1/13 },
{ 65538 * 3/13, 65538 * 4/6, 65538 * 3/13 },
{ 65538 * 1/13, 65538 * 1/6, 65538 * 9/13 }
};
FT_UNUSED( weights );
/* take care of bitmap flow */
if ( pitch > 0 && height > 0 )
origin += pitch * (FT_Int)( height - 1 );
/* horizontal in-place intra-pixel filter */
if ( mode == FT_PIXEL_MODE_LCD && width >= 3 )
{
FT_Byte* line = origin;
for ( ; height > 0; height--, line -= pitch )
{
FT_UInt xx;
for ( xx = 0; xx < width; xx += 3 )
{
FT_UInt r, g, b;
FT_UInt p;
p = line[xx];
r = filters[0][0] * p;
g = filters[0][1] * p;
b = filters[0][2] * p;
p = line[xx + 1];
r += filters[1][0] * p;
g += filters[1][1] * p;
b += filters[1][2] * p;
p = line[xx + 2];
r += filters[2][0] * p;
g += filters[2][1] * p;
b += filters[2][2] * p;
line[xx] = (FT_Byte)( r / 65536 );
line[xx + 1] = (FT_Byte)( g / 65536 );
line[xx + 2] = (FT_Byte)( b / 65536 );
}
}
}
else if ( mode == FT_PIXEL_MODE_LCD_V && height >= 3 )
{
FT_Byte* column = origin;
for ( ; width > 0; width--, column++ )
{
FT_Byte* col = column - 2 * pitch;
for ( ; height > 0; height -= 3, col -= 3 * pitch )
{
FT_UInt r, g, b;
FT_UInt p;
p = col[0];
r = filters[0][0] * p;
g = filters[0][1] * p;
b = filters[0][2] * p;
p = col[pitch];
r += filters[1][0] * p;
g += filters[1][1] * p;
b += filters[1][2] * p;
p = col[pitch * 2];
r += filters[2][0] * p;
g += filters[2][1] * p;
b += filters[2][2] * p;
col[0] = (FT_Byte)( r / 65536 );
col[pitch] = (FT_Byte)( g / 65536 );
col[pitch * 2] = (FT_Byte)( b / 65536 );
}
}
}
}
#endif /* USE_LEGACY */
/* documentation in ftlcdfil.h */
FT_EXPORT_DEF( FT_Error )
FT_Library_SetLcdFilterWeights( FT_Library library,
unsigned char *weights )
{
if ( !library )
return FT_THROW( Invalid_Library_Handle );
if ( !weights )
return FT_THROW( Invalid_Argument );
ft_memcpy( library->lcd_weights, weights, FT_LCD_FILTER_FIVE_TAPS );
library->lcd_filter_func = ft_lcd_filter_fir;
return FT_Err_Ok;
}
/* documentation in ftlcdfil.h */
FT_EXPORT_DEF( FT_Error )
FT_Library_SetLcdFilter( FT_Library library,
FT_LcdFilter filter )
{
static const FT_LcdFiveTapFilter default_weights =
{ 0x08, 0x4d, 0x56, 0x4d, 0x08 };
static const FT_LcdFiveTapFilter light_weights =
{ 0x00, 0x55, 0x56, 0x55, 0x00 };
if ( !library )
return FT_THROW( Invalid_Library_Handle );
switch ( filter )
{
case FT_LCD_FILTER_NONE:
library->lcd_filter_func = NULL;
break;
case FT_LCD_FILTER_DEFAULT:
ft_memcpy( library->lcd_weights,
default_weights,
FT_LCD_FILTER_FIVE_TAPS );
library->lcd_filter_func = ft_lcd_filter_fir;
break;
case FT_LCD_FILTER_LIGHT:
ft_memcpy( library->lcd_weights,
light_weights,
FT_LCD_FILTER_FIVE_TAPS );
library->lcd_filter_func = ft_lcd_filter_fir;
break;
#ifdef USE_LEGACY
case FT_LCD_FILTER_LEGACY:
case FT_LCD_FILTER_LEGACY1:
library->lcd_filter_func = _ft_lcd_filter_legacy;
break;
#endif
default:
return FT_THROW( Invalid_Argument );
}
return FT_Err_Ok;
}
FT_EXPORT_DEF( FT_Error )
FT_Library_SetLcdGeometry( FT_Library library,
FT_Vector sub[3] )
{
FT_UNUSED( library );
FT_UNUSED( sub );
return FT_THROW( Unimplemented_Feature );
}
#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
/* add padding to accommodate outline shifts */
FT_BASE_DEF( void )
ft_lcd_padding( FT_BBox* cbox,
FT_GlyphSlot slot,
FT_Render_Mode mode )
{
FT_Vector* sub = slot->library->lcd_geometry;
if ( mode == FT_RENDER_MODE_LCD )
{
cbox->xMin -= FT_MAX( FT_MAX( sub[0].x, sub[1].x ), sub[2].x );
cbox->xMax -= FT_MIN( FT_MIN( sub[0].x, sub[1].x ), sub[2].x );
cbox->yMin -= FT_MAX( FT_MAX( sub[0].y, sub[1].y ), sub[2].y );
cbox->yMax -= FT_MIN( FT_MIN( sub[0].y, sub[1].y ), sub[2].y );
}
else if ( mode == FT_RENDER_MODE_LCD_V )
{
cbox->xMin -= FT_MAX( FT_MAX( sub[0].y, sub[1].y ), sub[2].y );
cbox->xMax -= FT_MIN( FT_MIN( sub[0].y, sub[1].y ), sub[2].y );
cbox->yMin += FT_MIN( FT_MIN( sub[0].x, sub[1].x ), sub[2].x );
cbox->yMax += FT_MAX( FT_MAX( sub[0].x, sub[1].x ), sub[2].x );
}
}
FT_EXPORT_DEF( FT_Error )
FT_Library_SetLcdFilterWeights( FT_Library library,
unsigned char *weights )
{
FT_UNUSED( library );
FT_UNUSED( weights );
return FT_THROW( Unimplemented_Feature );
}
FT_EXPORT_DEF( FT_Error )
FT_Library_SetLcdFilter( FT_Library library,
FT_LcdFilter filter )
{
FT_UNUSED( library );
FT_UNUSED( filter );
return FT_THROW( Unimplemented_Feature );
}
/* documentation in ftlcdfil.h */
FT_EXPORT_DEF( FT_Error )
FT_Library_SetLcdGeometry( FT_Library library,
FT_Vector sub[3] )
{
if ( !library )
return FT_THROW( Invalid_Library_Handle );
if ( !sub )
return FT_THROW( Invalid_Argument );
ft_memcpy( library->lcd_geometry, sub, 3 * sizeof( FT_Vector ) );
return FT_Err_Ok;
}
#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
/* END */

1099
thirdparty/freetype/src/base/ftmac.c vendored Normal file

File diff suppressed because it is too large Load Diff

704
thirdparty/freetype/src/base/ftmm.c vendored Normal file
View File

@@ -0,0 +1,704 @@
/****************************************************************************
*
* ftmm.c
*
* Multiple Master font support (body).
*
* Copyright (C) 1996-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/internal/ftdebug.h>
#include <freetype/ftmm.h>
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/services/svmm.h>
#include <freetype/internal/services/svmetric.h>
/**************************************************************************
*
* The macro FT_COMPONENT is used in trace mode. It is an implicit
* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
* messages during execution.
*/
#undef FT_COMPONENT
#define FT_COMPONENT mm
static FT_Error
ft_face_get_mm_service( FT_Face face,
FT_Service_MultiMasters *aservice )
{
FT_Error error;
*aservice = NULL;
if ( !face )
return FT_THROW( Invalid_Face_Handle );
error = FT_ERR( Invalid_Argument );
if ( FT_HAS_MULTIPLE_MASTERS( face ) )
{
FT_FACE_LOOKUP_SERVICE( face,
*aservice,
MULTI_MASTERS );
if ( *aservice )
error = FT_Err_Ok;
}
return error;
}
static FT_Error
ft_face_get_mvar_service( FT_Face face,
FT_Service_MetricsVariations *aservice )
{
FT_Error error;
*aservice = NULL;
if ( !face )
return FT_THROW( Invalid_Face_Handle );
error = FT_ERR( Invalid_Argument );
if ( FT_HAS_MULTIPLE_MASTERS( face ) )
{
FT_FACE_LOOKUP_SERVICE( face,
*aservice,
METRICS_VARIATIONS );
if ( *aservice )
error = FT_Err_Ok;
}
return error;
}
/* documentation is in ftmm.h */
FT_EXPORT_DEF( FT_Error )
FT_Get_Multi_Master( FT_Face face,
FT_Multi_Master *amaster )
{
FT_Error error;
FT_Service_MultiMasters service;
/* check of `face' delayed to `ft_face_get_mm_service' */
if ( !amaster )
return FT_THROW( Invalid_Argument );
error = ft_face_get_mm_service( face, &service );
if ( !error )
{
error = FT_ERR( Invalid_Argument );
if ( service->get_mm )
error = service->get_mm( face, amaster );
}
return error;
}
/* documentation is in ftmm.h */
FT_EXPORT_DEF( FT_Error )
FT_Get_MM_Var( FT_Face face,
FT_MM_Var* *amaster )
{
FT_Error error;
FT_Service_MultiMasters service;
/* check of `face' delayed to `ft_face_get_mm_service' */
if ( !amaster )
return FT_THROW( Invalid_Argument );
error = ft_face_get_mm_service( face, &service );
if ( !error )
{
error = FT_ERR( Invalid_Argument );
if ( service->get_mm_var )
error = service->get_mm_var( face, amaster );
}
return error;
}
/* documentation is in ftmm.h */
FT_EXPORT_DEF( FT_Error )
FT_Done_MM_Var( FT_Library library,
FT_MM_Var* amaster )
{
FT_Memory memory;
if ( !library )
return FT_THROW( Invalid_Library_Handle );
memory = library->memory;
FT_FREE( amaster );
return FT_Err_Ok;
}
/* documentation is in ftmm.h */
FT_EXPORT_DEF( FT_Error )
FT_Set_MM_Design_Coordinates( FT_Face face,
FT_UInt num_coords,
FT_Long* coords )
{
FT_Error error;
FT_Service_MultiMasters service;
/* check of `face' delayed to `ft_face_get_mm_service' */
if ( num_coords && !coords )
return FT_THROW( Invalid_Argument );
error = ft_face_get_mm_service( face, &service );
if ( !error )
{
error = FT_ERR( Invalid_Argument );
if ( service->set_mm_design )
error = service->set_mm_design( face, num_coords, coords );
if ( !error )
{
if ( num_coords )
face->face_flags |= FT_FACE_FLAG_VARIATION;
else
face->face_flags &= ~FT_FACE_FLAG_VARIATION;
}
}
/* enforce recomputation of auto-hinting data */
if ( !error && face->autohint.finalizer )
{
face->autohint.finalizer( face->autohint.data );
face->autohint.data = NULL;
}
return error;
}
/* documentation is in ftmm.h */
FT_EXPORT_DEF( FT_Error )
FT_Set_MM_WeightVector( FT_Face face,
FT_UInt len,
FT_Fixed* weightvector )
{
FT_Error error;
FT_Service_MultiMasters service;
/* check of `face' delayed to `ft_face_get_mm_service' */
if ( len && !weightvector )
return FT_THROW( Invalid_Argument );
error = ft_face_get_mm_service( face, &service );
if ( !error )
{
error = FT_ERR( Invalid_Argument );
if ( service->set_mm_weightvector )
error = service->set_mm_weightvector( face, len, weightvector );
if ( !error )
{
if ( len )
face->face_flags |= FT_FACE_FLAG_VARIATION;
else
face->face_flags &= ~FT_FACE_FLAG_VARIATION;
}
}
/* enforce recomputation of auto-hinting data */
if ( !error && face->autohint.finalizer )
{
face->autohint.finalizer( face->autohint.data );
face->autohint.data = NULL;
}
return error;
}
FT_EXPORT_DEF( FT_Error )
FT_Get_MM_WeightVector( FT_Face face,
FT_UInt* len,
FT_Fixed* weightvector )
{
FT_Error error;
FT_Service_MultiMasters service;
/* check of `face' delayed to `ft_face_get_mm_service' */
if ( len && !weightvector )
return FT_THROW( Invalid_Argument );
error = ft_face_get_mm_service( face, &service );
if ( !error )
{
error = FT_ERR( Invalid_Argument );
if ( service->get_mm_weightvector )
error = service->get_mm_weightvector( face, len, weightvector );
}
return error;
}
/* documentation is in ftmm.h */
FT_EXPORT_DEF( FT_Error )
FT_Set_Var_Design_Coordinates( FT_Face face,
FT_UInt num_coords,
FT_Fixed* coords )
{
FT_Error error;
FT_Service_MultiMasters service_mm = NULL;
FT_Service_MetricsVariations service_mvar = NULL;
/* check of `face' delayed to `ft_face_get_mm_service' */
if ( num_coords && !coords )
return FT_THROW( Invalid_Argument );
error = ft_face_get_mm_service( face, &service_mm );
if ( !error )
{
error = FT_ERR( Invalid_Argument );
if ( service_mm->set_var_design )
error = service_mm->set_var_design( face, num_coords, coords );
if ( !error || error == -1 )
{
FT_Bool is_variation_old = FT_IS_VARIATION( face );
if ( num_coords )
face->face_flags |= FT_FACE_FLAG_VARIATION;
else
face->face_flags &= ~FT_FACE_FLAG_VARIATION;
if ( service_mm->construct_ps_name )
{
if ( error == -1 )
{
/* The PS name of a named instance and a non-named instance */
/* usually differs, even if the axis values are identical. */
if ( is_variation_old != FT_IS_VARIATION( face ) )
service_mm->construct_ps_name( face );
}
else
service_mm->construct_ps_name( face );
}
}
/* internal error code -1 means `no change'; we can exit immediately */
if ( error == -1 )
return FT_Err_Ok;
}
if ( !error )
{
(void)ft_face_get_mvar_service( face, &service_mvar );
if ( service_mvar && service_mvar->metrics_adjust )
service_mvar->metrics_adjust( face );
}
/* enforce recomputation of auto-hinting data */
if ( !error && face->autohint.finalizer )
{
face->autohint.finalizer( face->autohint.data );
face->autohint.data = NULL;
}
return error;
}
/* documentation is in ftmm.h */
FT_EXPORT_DEF( FT_Error )
FT_Get_Var_Design_Coordinates( FT_Face face,
FT_UInt num_coords,
FT_Fixed* coords )
{
FT_Error error;
FT_Service_MultiMasters service;
/* check of `face' delayed to `ft_face_get_mm_service' */
if ( !coords )
return FT_THROW( Invalid_Argument );
error = ft_face_get_mm_service( face, &service );
if ( !error )
{
error = FT_ERR( Invalid_Argument );
if ( service->get_var_design )
error = service->get_var_design( face, num_coords, coords );
}
return error;
}
/* documentation is in ftmm.h */
FT_EXPORT_DEF( FT_Error )
FT_Set_MM_Blend_Coordinates( FT_Face face,
FT_UInt num_coords,
FT_Fixed* coords )
{
FT_Error error;
FT_Service_MultiMasters service_mm = NULL;
FT_Service_MetricsVariations service_mvar = NULL;
/* check of `face' delayed to `ft_face_get_mm_service' */
if ( num_coords && !coords )
return FT_THROW( Invalid_Argument );
error = ft_face_get_mm_service( face, &service_mm );
if ( !error )
{
error = FT_ERR( Invalid_Argument );
if ( service_mm->set_mm_blend )
error = service_mm->set_mm_blend( face, num_coords, coords );
if ( !error || error == -1 )
{
FT_Bool is_variation_old = FT_IS_VARIATION( face );
if ( num_coords )
face->face_flags |= FT_FACE_FLAG_VARIATION;
else
face->face_flags &= ~FT_FACE_FLAG_VARIATION;
if ( service_mm->construct_ps_name )
{
if ( error == -1 )
{
/* The PS name of a named instance and a non-named instance */
/* usually differs, even if the axis values are identical. */
if ( is_variation_old != FT_IS_VARIATION( face ) )
service_mm->construct_ps_name( face );
}
else
service_mm->construct_ps_name( face );
}
}
/* internal error code -1 means `no change'; we can exit immediately */
if ( error == -1 )
return FT_Err_Ok;
}
if ( !error )
{
(void)ft_face_get_mvar_service( face, &service_mvar );
if ( service_mvar && service_mvar->metrics_adjust )
service_mvar->metrics_adjust( face );
}
/* enforce recomputation of auto-hinting data */
if ( !error && face->autohint.finalizer )
{
face->autohint.finalizer( face->autohint.data );
face->autohint.data = NULL;
}
return error;
}
/* documentation is in ftmm.h */
/* This is exactly the same as the previous function. It exists for */
/* orthogonality. */
FT_EXPORT_DEF( FT_Error )
FT_Set_Var_Blend_Coordinates( FT_Face face,
FT_UInt num_coords,
FT_Fixed* coords )
{
FT_Error error;
FT_Service_MultiMasters service_mm = NULL;
FT_Service_MetricsVariations service_mvar = NULL;
/* check of `face' delayed to `ft_face_get_mm_service' */
if ( num_coords && !coords )
return FT_THROW( Invalid_Argument );
error = ft_face_get_mm_service( face, &service_mm );
if ( !error )
{
error = FT_ERR( Invalid_Argument );
if ( service_mm->set_mm_blend )
error = service_mm->set_mm_blend( face, num_coords, coords );
if ( !error || error == -1 )
{
FT_Bool is_variation_old = FT_IS_VARIATION( face );
if ( num_coords )
face->face_flags |= FT_FACE_FLAG_VARIATION;
else
face->face_flags &= ~FT_FACE_FLAG_VARIATION;
if ( service_mm->construct_ps_name )
{
if ( error == -1 )
{
/* The PS name of a named instance and a non-named instance */
/* usually differs, even if the axis values are identical. */
if ( is_variation_old != FT_IS_VARIATION( face ) )
service_mm->construct_ps_name( face );
}
else
service_mm->construct_ps_name( face );
}
}
/* internal error code -1 means `no change'; we can exit immediately */
if ( error == -1 )
return FT_Err_Ok;
}
if ( !error )
{
(void)ft_face_get_mvar_service( face, &service_mvar );
if ( service_mvar && service_mvar->metrics_adjust )
service_mvar->metrics_adjust( face );
}
/* enforce recomputation of auto-hinting data */
if ( !error && face->autohint.finalizer )
{
face->autohint.finalizer( face->autohint.data );
face->autohint.data = NULL;
}
return error;
}
/* documentation is in ftmm.h */
FT_EXPORT_DEF( FT_Error )
FT_Get_MM_Blend_Coordinates( FT_Face face,
FT_UInt num_coords,
FT_Fixed* coords )
{
FT_Error error;
FT_Service_MultiMasters service;
/* check of `face' delayed to `ft_face_get_mm_service' */
if ( !coords )
return FT_THROW( Invalid_Argument );
error = ft_face_get_mm_service( face, &service );
if ( !error )
{
error = FT_ERR( Invalid_Argument );
if ( service->get_mm_blend )
error = service->get_mm_blend( face, num_coords, coords );
}
return error;
}
/* documentation is in ftmm.h */
/* This is exactly the same as the previous function. It exists for */
/* orthogonality. */
FT_EXPORT_DEF( FT_Error )
FT_Get_Var_Blend_Coordinates( FT_Face face,
FT_UInt num_coords,
FT_Fixed* coords )
{
FT_Error error;
FT_Service_MultiMasters service;
/* check of `face' delayed to `ft_face_get_mm_service' */
if ( !coords )
return FT_THROW( Invalid_Argument );
error = ft_face_get_mm_service( face, &service );
if ( !error )
{
error = FT_ERR( Invalid_Argument );
if ( service->get_mm_blend )
error = service->get_mm_blend( face, num_coords, coords );
}
return error;
}
/* documentation is in ftmm.h */
FT_EXPORT_DEF( FT_Error )
FT_Get_Var_Axis_Flags( FT_MM_Var* master,
FT_UInt axis_index,
FT_UInt* flags )
{
FT_UShort* axis_flags;
if ( !master || !flags )
return FT_THROW( Invalid_Argument );
if ( axis_index >= master->num_axis )
return FT_THROW( Invalid_Argument );
/* the axis flags array immediately follows the data of `master' */
axis_flags = (FT_UShort*)&( master[1] );
*flags = axis_flags[axis_index];
return FT_Err_Ok;
}
/* documentation is in ftmm.h */
FT_EXPORT_DEF( FT_Error )
FT_Set_Named_Instance( FT_Face face,
FT_UInt instance_index )
{
FT_Error error;
FT_Service_MultiMasters service_mm = NULL;
FT_Service_MetricsVariations service_mvar = NULL;
/* check of `face' delayed to `ft_face_get_mm_service' */
error = ft_face_get_mm_service( face, &service_mm );
if ( !error )
{
error = FT_ERR( Invalid_Argument );
if ( service_mm->set_named_instance )
error = service_mm->set_named_instance( face, instance_index );
if ( !error || error == -1 )
{
FT_Bool is_variation_old = FT_IS_VARIATION( face );
face->face_flags &= ~FT_FACE_FLAG_VARIATION;
face->face_index = ( instance_index << 16 ) |
( face->face_index & 0xFFFFL );
if ( service_mm->construct_ps_name )
{
if ( error == -1 )
{
/* The PS name of a named instance and a non-named instance */
/* usually differs, even if the axis values are identical. */
if ( is_variation_old != FT_IS_VARIATION( face ) )
service_mm->construct_ps_name( face );
}
else
service_mm->construct_ps_name( face );
}
}
/* internal error code -1 means `no change'; we can exit immediately */
if ( error == -1 )
return FT_Err_Ok;
}
if ( !error )
{
(void)ft_face_get_mvar_service( face, &service_mvar );
if ( service_mvar && service_mvar->metrics_adjust )
service_mvar->metrics_adjust( face );
}
/* enforce recomputation of auto-hinting data */
if ( !error && face->autohint.finalizer )
{
face->autohint.finalizer( face->autohint.data );
face->autohint.data = NULL;
}
return error;
}
/* documentation is in ftmm.h */
FT_EXPORT_DEF( FT_Error )
FT_Get_Default_Named_Instance( FT_Face face,
FT_UInt *instance_index )
{
FT_Error error;
FT_Service_MultiMasters service_mm = NULL;
/* check of `face' delayed to `ft_face_get_mm_service' */
error = ft_face_get_mm_service( face, &service_mm );
if ( !error )
{
/* no error if `get_default_named_instance` is not available */
if ( service_mm->get_default_named_instance )
error = service_mm->get_default_named_instance( face,
instance_index );
else
error = FT_Err_Ok;
}
return error;
}
/* END */

5917
thirdparty/freetype/src/base/ftobjs.c vendored Normal file

File diff suppressed because it is too large Load Diff

90
thirdparty/freetype/src/base/ftotval.c vendored Normal file
View File

@@ -0,0 +1,90 @@
/****************************************************************************
*
* ftotval.c
*
* FreeType API for validating OpenType tables (body).
*
* Copyright (C) 2004-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/internal/ftdebug.h>
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/services/svotval.h>
#include <freetype/ftotval.h>
/* documentation is in ftotval.h */
FT_EXPORT_DEF( FT_Error )
FT_OpenType_Validate( FT_Face face,
FT_UInt validation_flags,
FT_Bytes *BASE_table,
FT_Bytes *GDEF_table,
FT_Bytes *GPOS_table,
FT_Bytes *GSUB_table,
FT_Bytes *JSTF_table )
{
FT_Service_OTvalidate service;
FT_Error error;
if ( !face )
{
error = FT_THROW( Invalid_Face_Handle );
goto Exit;
}
if ( !( BASE_table &&
GDEF_table &&
GPOS_table &&
GSUB_table &&
JSTF_table ) )
{
error = FT_THROW( Invalid_Argument );
goto Exit;
}
FT_FACE_FIND_GLOBAL_SERVICE( face, service, OPENTYPE_VALIDATE );
if ( service )
error = service->validate( face,
validation_flags,
BASE_table,
GDEF_table,
GPOS_table,
GSUB_table,
JSTF_table );
else
error = FT_THROW( Unimplemented_Feature );
Exit:
return error;
}
FT_EXPORT_DEF( void )
FT_OpenType_Free( FT_Face face,
FT_Bytes table )
{
FT_Memory memory;
if ( !face )
return;
memory = FT_FACE_MEMORY( face );
FT_FREE( table );
}
/* END */

1120
thirdparty/freetype/src/base/ftoutln.c vendored Normal file

File diff suppressed because it is too large Load Diff

50
thirdparty/freetype/src/base/ftpatent.c vendored Normal file
View File

@@ -0,0 +1,50 @@
/****************************************************************************
*
* ftpatent.c
*
* FreeType API for checking patented TrueType bytecode instructions
* (body). Obsolete, retained for backward compatibility.
*
* Copyright (C) 2007-2024 by
* David Turner.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/freetype.h>
#include <freetype/tttags.h>
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/ftstream.h>
#include <freetype/internal/services/svsfnt.h>
#include <freetype/internal/services/svttglyf.h>
/* documentation is in freetype.h */
FT_EXPORT_DEF( FT_Bool )
FT_Face_CheckTrueTypePatents( FT_Face face )
{
FT_UNUSED( face );
return FALSE;
}
/* documentation is in freetype.h */
FT_EXPORT_DEF( FT_Bool )
FT_Face_SetUnpatentedHinting( FT_Face face,
FT_Bool value )
{
FT_UNUSED( face );
FT_UNUSED( value );
return FALSE;
}
/* END */

152
thirdparty/freetype/src/base/ftpfr.c vendored Normal file
View File

@@ -0,0 +1,152 @@
/****************************************************************************
*
* ftpfr.c
*
* FreeType API for accessing PFR-specific data (body).
*
* Copyright (C) 2002-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/internal/ftdebug.h>
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/services/svpfr.h>
/* check the format */
static FT_Service_PfrMetrics
ft_pfr_check( FT_Face face )
{
FT_Service_PfrMetrics service = NULL;
if ( face )
FT_FACE_LOOKUP_SERVICE( face, service, PFR_METRICS );
return service;
}
/* documentation is in ftpfr.h */
FT_EXPORT_DEF( FT_Error )
FT_Get_PFR_Metrics( FT_Face face,
FT_UInt *aoutline_resolution,
FT_UInt *ametrics_resolution,
FT_Fixed *ametrics_x_scale,
FT_Fixed *ametrics_y_scale )
{
FT_Error error = FT_Err_Ok;
FT_Service_PfrMetrics service;
if ( !face )
return FT_THROW( Invalid_Face_Handle );
service = ft_pfr_check( face );
if ( service )
{
error = service->get_metrics( face,
aoutline_resolution,
ametrics_resolution,
ametrics_x_scale,
ametrics_y_scale );
}
else
{
FT_Fixed x_scale, y_scale;
/* this is not a PFR font */
if ( aoutline_resolution )
*aoutline_resolution = face->units_per_EM;
if ( ametrics_resolution )
*ametrics_resolution = face->units_per_EM;
x_scale = y_scale = 0x10000L;
if ( face->size )
{
x_scale = face->size->metrics.x_scale;
y_scale = face->size->metrics.y_scale;
}
if ( ametrics_x_scale )
*ametrics_x_scale = x_scale;
if ( ametrics_y_scale )
*ametrics_y_scale = y_scale;
error = FT_THROW( Unknown_File_Format );
}
return error;
}
/* documentation is in ftpfr.h */
FT_EXPORT_DEF( FT_Error )
FT_Get_PFR_Kerning( FT_Face face,
FT_UInt left,
FT_UInt right,
FT_Vector *avector )
{
FT_Error error;
FT_Service_PfrMetrics service;
if ( !face )
return FT_THROW( Invalid_Face_Handle );
if ( !avector )
return FT_THROW( Invalid_Argument );
service = ft_pfr_check( face );
if ( service )
error = service->get_kerning( face, left, right, avector );
else
error = FT_Get_Kerning( face, left, right,
FT_KERNING_UNSCALED, avector );
return error;
}
/* documentation is in ftpfr.h */
FT_EXPORT_DEF( FT_Error )
FT_Get_PFR_Advance( FT_Face face,
FT_UInt gindex,
FT_Pos *aadvance )
{
FT_Error error;
FT_Service_PfrMetrics service;
if ( !face )
return FT_THROW( Invalid_Face_Handle );
if ( !aadvance )
return FT_THROW( Invalid_Argument );
service = ft_pfr_check( face );
if ( service )
error = service->get_advance( face, gindex, aadvance );
else
/* XXX: TODO: PROVIDE ADVANCE-LOADING METHOD TO ALL FONT DRIVERS */
error = FT_THROW( Invalid_Argument );
return error;
}
/* END */

284
thirdparty/freetype/src/base/ftpsprop.c vendored Normal file
View File

@@ -0,0 +1,284 @@
/****************************************************************************
*
* ftpsprop.c
*
* Get and set properties of PostScript drivers (body).
* See `ftdriver.h' for available properties.
*
* Copyright (C) 2017-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/ftdriver.h>
#include <freetype/internal/ftdebug.h>
#include <freetype/internal/psaux.h>
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/ftpsprop.h>
/**************************************************************************
*
* The macro FT_COMPONENT is used in trace mode. It is an implicit
* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
* messages during execution.
*/
#undef FT_COMPONENT
#define FT_COMPONENT psprops
FT_BASE_CALLBACK_DEF( FT_Error )
ps_property_set( FT_Module module, /* PS_Driver */
const char* property_name,
const void* value,
FT_Bool value_is_string )
{
FT_Error error = FT_Err_Ok;
PS_Driver driver = (PS_Driver)module;
#ifndef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
FT_UNUSED( value_is_string );
#endif
if ( !ft_strcmp( property_name, "darkening-parameters" ) )
{
FT_Int* darken_params;
FT_Int x1, y1, x2, y2, x3, y3, x4, y4;
#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
FT_Int dp[8];
if ( value_is_string )
{
const char* s = (const char*)value;
char* ep;
int i;
/* eight comma-separated numbers */
for ( i = 0; i < 7; i++ )
{
dp[i] = (FT_Int)ft_strtol( s, &ep, 10 );
if ( *ep != ',' || s == ep )
return FT_THROW( Invalid_Argument );
s = ep + 1;
}
dp[7] = (FT_Int)ft_strtol( s, &ep, 10 );
if ( !( *ep == '\0' || *ep == ' ' ) || s == ep )
return FT_THROW( Invalid_Argument );
darken_params = dp;
}
else
#endif
darken_params = (FT_Int*)value;
x1 = darken_params[0];
y1 = darken_params[1];
x2 = darken_params[2];
y2 = darken_params[3];
x3 = darken_params[4];
y3 = darken_params[5];
x4 = darken_params[6];
y4 = darken_params[7];
if ( x1 < 0 || x2 < 0 || x3 < 0 || x4 < 0 ||
y1 < 0 || y2 < 0 || y3 < 0 || y4 < 0 ||
x1 > x2 || x2 > x3 || x3 > x4 ||
y1 > 500 || y2 > 500 || y3 > 500 || y4 > 500 )
return FT_THROW( Invalid_Argument );
driver->darken_params[0] = x1;
driver->darken_params[1] = y1;
driver->darken_params[2] = x2;
driver->darken_params[3] = y2;
driver->darken_params[4] = x3;
driver->darken_params[5] = y3;
driver->darken_params[6] = x4;
driver->darken_params[7] = y4;
return error;
}
else if ( !ft_strcmp( property_name, "hinting-engine" ) )
{
#if defined( CFF_CONFIG_OPTION_OLD_ENGINE ) || \
defined( T1_CONFIG_OPTION_OLD_ENGINE )
const char* module_name = module->clazz->module_name;
#endif
#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
if ( value_is_string )
{
const char* s = (const char*)value;
if ( !ft_strcmp( s, "adobe" ) )
driver->hinting_engine = FT_HINTING_ADOBE;
#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
else if ( !ft_strcmp( module_name, "cff" ) &&
!ft_strcmp( s, "freetype" ) )
driver->hinting_engine = FT_HINTING_FREETYPE;
#endif
#ifdef T1_CONFIG_OPTION_OLD_ENGINE
else if ( ( !ft_strcmp( module_name, "type1" ) ||
!ft_strcmp( module_name, "t1cid" ) ) &&
!ft_strcmp( s, "freetype" ) )
driver->hinting_engine = FT_HINTING_FREETYPE;
#endif
else
return FT_THROW( Invalid_Argument );
}
else
#endif /* FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES */
{
FT_UInt* hinting_engine = (FT_UInt*)value;
if ( *hinting_engine == FT_HINTING_ADOBE
#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
|| ( *hinting_engine == FT_HINTING_FREETYPE &&
!ft_strcmp( module_name, "cff" ) )
#endif
#ifdef T1_CONFIG_OPTION_OLD_ENGINE
|| ( *hinting_engine == FT_HINTING_FREETYPE &&
( !ft_strcmp( module_name, "type1" ) ||
!ft_strcmp( module_name, "t1cid" ) ) )
#endif
)
driver->hinting_engine = *hinting_engine;
else
error = FT_ERR( Unimplemented_Feature );
}
return error;
}
else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
{
#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
if ( value_is_string )
{
const char* s = (const char*)value;
long nsd = ft_strtol( s, NULL, 10 );
if ( !nsd )
driver->no_stem_darkening = FALSE;
else
driver->no_stem_darkening = TRUE;
}
else
#endif
{
FT_Bool* no_stem_darkening = (FT_Bool*)value;
driver->no_stem_darkening = *no_stem_darkening;
}
return error;
}
else if ( !ft_strcmp( property_name, "random-seed" ) )
{
FT_Int32 random_seed;
#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
if ( value_is_string )
{
const char* s = (const char*)value;
random_seed = (FT_Int32)ft_strtol( s, NULL, 10 );
}
else
#endif
random_seed = *(FT_Int32*)value;
if ( random_seed < 0 )
random_seed = 0;
driver->random_seed = random_seed;
return error;
}
FT_TRACE2(( "ps_property_set: missing property `%s'\n",
property_name ));
return FT_THROW( Missing_Property );
}
FT_BASE_CALLBACK_DEF( FT_Error )
ps_property_get( FT_Module module, /* PS_Driver */
const char* property_name,
void* value )
{
FT_Error error = FT_Err_Ok;
PS_Driver driver = (PS_Driver)module;
if ( !ft_strcmp( property_name, "darkening-parameters" ) )
{
FT_Int* darken_params = driver->darken_params;
FT_Int* val = (FT_Int*)value;
val[0] = darken_params[0];
val[1] = darken_params[1];
val[2] = darken_params[2];
val[3] = darken_params[3];
val[4] = darken_params[4];
val[5] = darken_params[5];
val[6] = darken_params[6];
val[7] = darken_params[7];
return error;
}
else if ( !ft_strcmp( property_name, "hinting-engine" ) )
{
FT_UInt hinting_engine = driver->hinting_engine;
FT_UInt* val = (FT_UInt*)value;
*val = hinting_engine;
return error;
}
else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
{
FT_Bool no_stem_darkening = driver->no_stem_darkening;
FT_Bool* val = (FT_Bool*)value;
*val = no_stem_darkening;
return error;
}
FT_TRACE2(( "ps_property_get: missing property `%s'\n",
property_name ));
return FT_THROW( Missing_Property );
}
/* END */

934
thirdparty/freetype/src/base/ftrfork.c vendored Normal file
View File

@@ -0,0 +1,934 @@
/****************************************************************************
*
* ftrfork.c
*
* Embedded resource forks accessor (body).
*
* Copyright (C) 2004-2024 by
* Masatake YAMATO and Redhat K.K.
*
* FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are
* derived from ftobjs.c.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
/****************************************************************************
* Development of the code in this file is support of
* Information-technology Promotion Agency, Japan.
*/
#include <freetype/internal/ftdebug.h>
#include <freetype/internal/ftstream.h>
#include <freetype/internal/ftrfork.h>
#include "ftbase.h"
#undef FT_COMPONENT
#define FT_COMPONENT raccess
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** ****/
/**** Resource fork directory access ****/
/**** ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
FT_BASE_DEF( FT_Error )
FT_Raccess_Get_HeaderInfo( FT_Library library,
FT_Stream stream,
FT_Long rfork_offset,
FT_Long *map_offset,
FT_Long *rdata_pos )
{
FT_Error error;
unsigned char head[16], head2[16];
FT_Long map_pos, map_len, rdata_len;
int allzeros, allmatch, i;
FT_Long type_list;
FT_UNUSED( library );
error = FT_Stream_Seek( stream, (FT_ULong)rfork_offset );
if ( error )
return error;
error = FT_Stream_Read( stream, (FT_Byte*)head, 16 );
if ( error )
return error;
/* ensure positive values */
if ( head[0] >= 0x80 ||
head[4] >= 0x80 ||
head[8] >= 0x80 ||
head[12] >= 0x80 )
return FT_THROW( Unknown_File_Format );
*rdata_pos = ( head[ 0] << 24 ) |
( head[ 1] << 16 ) |
( head[ 2] << 8 ) |
head[ 3];
map_pos = ( head[ 4] << 24 ) |
( head[ 5] << 16 ) |
( head[ 6] << 8 ) |
head[ 7];
rdata_len = ( head[ 8] << 24 ) |
( head[ 9] << 16 ) |
( head[10] << 8 ) |
head[11];
map_len = ( head[12] << 24 ) |
( head[13] << 16 ) |
( head[14] << 8 ) |
head[15];
/* the map must not be empty */
if ( !map_pos )
return FT_THROW( Unknown_File_Format );
/* check whether rdata and map overlap */
if ( *rdata_pos < map_pos )
{
if ( *rdata_pos > map_pos - rdata_len )
return FT_THROW( Unknown_File_Format );
}
else
{
if ( map_pos > *rdata_pos - map_len )
return FT_THROW( Unknown_File_Format );
}
/* check whether end of rdata or map exceeds stream size */
if ( FT_LONG_MAX - rdata_len < *rdata_pos ||
FT_LONG_MAX - map_len < map_pos ||
FT_LONG_MAX - ( *rdata_pos + rdata_len ) < rfork_offset ||
FT_LONG_MAX - ( map_pos + map_len ) < rfork_offset ||
(FT_ULong)( rfork_offset + *rdata_pos + rdata_len ) > stream->size ||
(FT_ULong)( rfork_offset + map_pos + map_len ) > stream->size )
return FT_THROW( Unknown_File_Format );
*rdata_pos += rfork_offset;
map_pos += rfork_offset;
error = FT_Stream_Seek( stream, (FT_ULong)map_pos );
if ( error )
return error;
head2[15] = (FT_Byte)( head[15] + 1 ); /* make it be different */
error = FT_Stream_Read( stream, (FT_Byte*)head2, 16 );
if ( error )
return error;
allzeros = 1;
allmatch = 1;
for ( i = 0; i < 16; i++ )
{
if ( head2[i] != 0 )
allzeros = 0;
if ( head2[i] != head[i] )
allmatch = 0;
}
if ( !allzeros && !allmatch )
return FT_THROW( Unknown_File_Format );
/* If we have reached this point then it is probably a mac resource */
/* file. Now, does it contain any interesting resources? */
(void)FT_STREAM_SKIP( 4 /* skip handle to next resource map */
+ 2 /* skip file resource number */
+ 2 ); /* skip attributes */
if ( FT_READ_SHORT( type_list ) )
return error;
if ( type_list < 0 )
return FT_THROW( Unknown_File_Format );
error = FT_Stream_Seek( stream, (FT_ULong)( map_pos + type_list ) );
if ( error )
return error;
*map_offset = map_pos + type_list;
return FT_Err_Ok;
}
FT_COMPARE_DEF( int )
ft_raccess_sort_ref_by_id( const void* a,
const void* b )
{
return ( (FT_RFork_Ref*)a )->res_id - ( (FT_RFork_Ref*)b )->res_id;
}
FT_BASE_DEF( FT_Error )
FT_Raccess_Get_DataOffsets( FT_Library library,
FT_Stream stream,
FT_Long map_offset,
FT_Long rdata_pos,
FT_Long tag,
FT_Bool sort_by_res_id,
FT_Long **offsets,
FT_Long *count )
{
FT_Error error;
int i, j, cnt, subcnt;
FT_Long tag_internal, rpos;
FT_Memory memory = library->memory;
FT_Long temp;
FT_Long *offsets_internal = NULL;
FT_RFork_Ref *ref = NULL;
FT_TRACE3(( "\n" ));
error = FT_Stream_Seek( stream, (FT_ULong)map_offset );
if ( error )
return error;
if ( FT_READ_SHORT( cnt ) )
return error;
cnt++;
/* `rpos' is a signed 16bit integer offset to resource records; the */
/* size of a resource record is 12 bytes. The map header is 28 bytes, */
/* and a type list needs 10 bytes or more. If we assume that the name */
/* list is empty and we have only a single entry in the type list, */
/* there can be at most */
/* */
/* (32768 - 28 - 10) / 12 = 2727 */
/* */
/* resources. */
/* */
/* A type list starts with a two-byte counter, followed by 10-byte */
/* type records. Assuming that there are no resources, the number of */
/* type records can be at most */
/* */
/* (32768 - 28 - 2) / 8 = 4079 */
/* */
if ( cnt > 4079 )
return FT_THROW( Invalid_Table );
for ( i = 0; i < cnt; i++ )
{
if ( FT_READ_LONG( tag_internal ) ||
FT_READ_SHORT( subcnt ) ||
FT_READ_SHORT( rpos ) )
return error;
FT_TRACE2(( "Resource tags: %c%c%c%c\n",
(char)( 0xFF & ( tag_internal >> 24 ) ),
(char)( 0xFF & ( tag_internal >> 16 ) ),
(char)( 0xFF & ( tag_internal >> 8 ) ),
(char)( 0xFF & ( tag_internal >> 0 ) ) ));
FT_TRACE3(( " : subcount=%d, suboffset=0x%04lx\n",
subcnt, rpos ));
if ( tag_internal == tag )
{
*count = subcnt + 1;
rpos += map_offset;
/* a zero count might be valid in the resource specification, */
/* however, it is completely useless to us */
if ( *count < 1 || *count > 2727 )
return FT_THROW( Invalid_Table );
error = FT_Stream_Seek( stream, (FT_ULong)rpos );
if ( error )
return error;
if ( FT_QNEW_ARRAY( ref, *count ) )
return error;
for ( j = 0; j < *count; j++ )
{
if ( FT_READ_SHORT( ref[j].res_id ) )
goto Exit;
if ( FT_STREAM_SKIP( 2 ) ) /* resource name offset */
goto Exit;
if ( FT_READ_LONG( temp ) ) /* attributes (8bit), offset (24bit) */
goto Exit;
if ( FT_STREAM_SKIP( 4 ) ) /* mbz */
goto Exit;
/*
* According to Inside Macintosh: More Macintosh Toolbox,
* "Resource IDs" (1-46), there are some reserved IDs.
* However, FreeType2 is not a font synthesizer, no need
* to check the acceptable resource ID.
*/
if ( temp < 0 )
{
error = FT_THROW( Invalid_Table );
goto Exit;
}
ref[j].offset = temp & 0xFFFFFFL;
FT_TRACE3(( " [%d]:"
" resource_id=0x%04x, offset=0x%08lx\n",
j, (FT_UShort)ref[j].res_id, ref[j].offset ));
}
if ( sort_by_res_id )
{
ft_qsort( ref,
(size_t)*count,
sizeof ( FT_RFork_Ref ),
ft_raccess_sort_ref_by_id );
FT_TRACE3(( " -- sort resources by their ids --\n" ));
for ( j = 0; j < *count; j++ )
FT_TRACE3(( " [%d]:"
" resource_id=0x%04x, offset=0x%08lx\n",
j, ref[j].res_id, ref[j].offset ));
}
if ( FT_QNEW_ARRAY( offsets_internal, *count ) )
goto Exit;
/* XXX: duplicated reference ID,
* gap between reference IDs are acceptable?
* further investigation on Apple implementation is needed.
*/
for ( j = 0; j < *count; j++ )
offsets_internal[j] = rdata_pos + ref[j].offset;
*offsets = offsets_internal;
error = FT_Err_Ok;
Exit:
FT_FREE( ref );
return error;
}
}
return FT_THROW( Cannot_Open_Resource );
}
#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** ****/
/**** Guessing functions ****/
/**** ****/
/**** When you add a new guessing function, ****/
/**** update FT_RACCESS_N_RULES in ftrfork.h. ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
static FT_Error
raccess_guess_apple_double( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_apple_single( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_darwin_ufs_export( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_darwin_newvfs( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_darwin_hfsplus( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_vfat( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_linux_cap( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_linux_double( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_linux_netatalk( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
CONST_FT_RFORK_RULE_ARRAY_BEGIN( ft_raccess_guess_table,
ft_raccess_guess_rec )
CONST_FT_RFORK_RULE_ARRAY_ENTRY( apple_double, apple_double )
CONST_FT_RFORK_RULE_ARRAY_ENTRY( apple_single, apple_single )
CONST_FT_RFORK_RULE_ARRAY_ENTRY( darwin_ufs_export, darwin_ufs_export )
CONST_FT_RFORK_RULE_ARRAY_ENTRY( darwin_newvfs, darwin_newvfs )
CONST_FT_RFORK_RULE_ARRAY_ENTRY( darwin_hfsplus, darwin_hfsplus )
CONST_FT_RFORK_RULE_ARRAY_ENTRY( vfat, vfat )
CONST_FT_RFORK_RULE_ARRAY_ENTRY( linux_cap, linux_cap )
CONST_FT_RFORK_RULE_ARRAY_ENTRY( linux_double, linux_double )
CONST_FT_RFORK_RULE_ARRAY_ENTRY( linux_netatalk, linux_netatalk )
CONST_FT_RFORK_RULE_ARRAY_END
/*************************************************************************/
/**** ****/
/**** Helper functions ****/
/**** ****/
/*************************************************************************/
static FT_Error
raccess_guess_apple_generic( FT_Library library,
FT_Stream stream,
char *base_file_name,
FT_Int32 magic,
FT_Long *result_offset );
static FT_Error
raccess_guess_linux_double_from_file_name( FT_Library library,
char* file_name,
FT_Long *result_offset );
static char *
raccess_make_file_name( FT_Memory memory,
const char *original_name,
const char *insertion );
FT_BASE_DEF( void )
FT_Raccess_Guess( FT_Library library,
FT_Stream stream,
char* base_name,
char **new_names,
FT_Long *offsets,
FT_Error *errors )
{
FT_Int i;
for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
{
new_names[i] = NULL;
if ( NULL != stream )
errors[i] = FT_Stream_Seek( stream, 0 );
else
errors[i] = FT_Err_Ok;
if ( errors[i] )
continue;
errors[i] = ft_raccess_guess_table[i].func( library,
stream, base_name,
&(new_names[i]),
&(offsets[i]) );
}
return;
}
#if defined( FT_CONFIG_OPTION_MAC_FONTS ) && !defined( FT_MACINTOSH )
static FT_RFork_Rule
raccess_get_rule_type_from_rule_index( FT_Library library,
FT_UInt rule_index )
{
FT_UNUSED( library );
if ( rule_index >= FT_RACCESS_N_RULES )
return FT_RFork_Rule_invalid;
return ft_raccess_guess_table[rule_index].type;
}
/*
* For this function, refer ftbase.h.
*/
FT_LOCAL_DEF( FT_Bool )
ft_raccess_rule_by_darwin_vfs( FT_Library library,
FT_UInt rule_index )
{
switch( raccess_get_rule_type_from_rule_index( library, rule_index ) )
{
case FT_RFork_Rule_darwin_newvfs:
case FT_RFork_Rule_darwin_hfsplus:
return TRUE;
default:
return FALSE;
}
}
#endif
static FT_Error
raccess_guess_apple_double( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
FT_Int32 magic = ( 0x00 << 24 ) |
( 0x05 << 16 ) |
( 0x16 << 8 ) |
0x07;
*result_file_name = NULL;
if ( NULL == stream )
return FT_THROW( Cannot_Open_Stream );
return raccess_guess_apple_generic( library, stream, base_file_name,
magic, result_offset );
}
static FT_Error
raccess_guess_apple_single( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
FT_Int32 magic = ( 0x00 << 24 ) |
( 0x05 << 16 ) |
( 0x16 << 8 ) |
0x00;
*result_file_name = NULL;
if ( NULL == stream )
return FT_THROW( Cannot_Open_Stream );
return raccess_guess_apple_generic( library, stream, base_file_name,
magic, result_offset );
}
static FT_Error
raccess_guess_darwin_ufs_export( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
char* newpath;
FT_Error error;
FT_Memory memory;
FT_UNUSED( stream );
memory = library->memory;
newpath = raccess_make_file_name( memory, base_file_name, "._" );
if ( !newpath )
return FT_THROW( Out_Of_Memory );
error = raccess_guess_linux_double_from_file_name( library, newpath,
result_offset );
if ( !error )
*result_file_name = newpath;
else
FT_FREE( newpath );
return error;
}
static FT_Error
raccess_guess_darwin_hfsplus( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
/*
Only meaningful on systems with hfs+ drivers (or Macs).
*/
FT_Error error;
char* newpath = NULL;
FT_Memory memory;
FT_Long base_file_len = (FT_Long)ft_strlen( base_file_name );
FT_UNUSED( stream );
memory = library->memory;
if ( base_file_len + 6 > FT_INT_MAX )
return FT_THROW( Array_Too_Large );
if ( FT_QALLOC( newpath, base_file_len + 6 ) )
return error;
FT_MEM_COPY( newpath, base_file_name, base_file_len );
FT_MEM_COPY( newpath + base_file_len, "/rsrc", 6 );
*result_file_name = newpath;
*result_offset = 0;
return FT_Err_Ok;
}
static FT_Error
raccess_guess_darwin_newvfs( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
/*
Only meaningful on systems with Mac OS X (> 10.1).
*/
FT_Error error;
char* newpath = NULL;
FT_Memory memory;
FT_Long base_file_len = (FT_Long)ft_strlen( base_file_name );
FT_UNUSED( stream );
memory = library->memory;
if ( base_file_len + 18 > FT_INT_MAX )
return FT_THROW( Array_Too_Large );
if ( FT_QALLOC( newpath, base_file_len + 18 ) )
return error;
FT_MEM_COPY( newpath, base_file_name, base_file_len );
FT_MEM_COPY( newpath + base_file_len, "/..namedfork/rsrc", 18 );
*result_file_name = newpath;
*result_offset = 0;
return FT_Err_Ok;
}
static FT_Error
raccess_guess_vfat( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
char* newpath;
FT_Memory memory;
FT_UNUSED( stream );
memory = library->memory;
newpath = raccess_make_file_name( memory, base_file_name,
"resource.frk/" );
if ( !newpath )
return FT_THROW( Out_Of_Memory );
*result_file_name = newpath;
*result_offset = 0;
return FT_Err_Ok;
}
static FT_Error
raccess_guess_linux_cap( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
char* newpath;
FT_Memory memory;
FT_UNUSED( stream );
memory = library->memory;
newpath = raccess_make_file_name( memory, base_file_name, ".resource/" );
if ( !newpath )
return FT_THROW( Out_Of_Memory );
*result_file_name = newpath;
*result_offset = 0;
return FT_Err_Ok;
}
static FT_Error
raccess_guess_linux_double( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
char* newpath;
FT_Error error;
FT_Memory memory;
FT_UNUSED( stream );
memory = library->memory;
newpath = raccess_make_file_name( memory, base_file_name, "%" );
if ( !newpath )
return FT_THROW( Out_Of_Memory );
error = raccess_guess_linux_double_from_file_name( library, newpath,
result_offset );
if ( !error )
*result_file_name = newpath;
else
FT_FREE( newpath );
return error;
}
static FT_Error
raccess_guess_linux_netatalk( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
char* newpath;
FT_Error error;
FT_Memory memory;
FT_UNUSED( stream );
memory = library->memory;
newpath = raccess_make_file_name( memory, base_file_name,
".AppleDouble/" );
if ( !newpath )
return FT_THROW( Out_Of_Memory );
error = raccess_guess_linux_double_from_file_name( library, newpath,
result_offset );
if ( !error )
*result_file_name = newpath;
else
FT_FREE( newpath );
return error;
}
static FT_Error
raccess_guess_apple_generic( FT_Library library,
FT_Stream stream,
char *base_file_name,
FT_Int32 magic,
FT_Long *result_offset )
{
FT_Int32 magic_from_stream;
FT_Error error;
FT_Int32 version_number = 0;
FT_UShort n_of_entries;
int i;
FT_Int32 entry_id, entry_offset, entry_length = 0;
const FT_Int32 resource_fork_entry_id = 0x2;
FT_UNUSED( library );
FT_UNUSED( base_file_name );
FT_UNUSED( version_number );
FT_UNUSED( entry_length );
if ( FT_READ_LONG( magic_from_stream ) )
return error;
if ( magic_from_stream != magic )
return FT_THROW( Unknown_File_Format );
if ( FT_READ_LONG( version_number ) )
return error;
/* filler */
error = FT_Stream_Skip( stream, 16 );
if ( error )
return error;
if ( FT_READ_USHORT( n_of_entries ) )
return error;
if ( n_of_entries == 0 )
return FT_THROW( Unknown_File_Format );
for ( i = 0; i < n_of_entries; i++ )
{
if ( FT_READ_LONG( entry_id ) )
return error;
if ( entry_id == resource_fork_entry_id )
{
if ( FT_READ_LONG( entry_offset ) ||
FT_READ_LONG( entry_length ) )
continue;
*result_offset = entry_offset;
return FT_Err_Ok;
}
else
{
error = FT_Stream_Skip( stream, 4 + 4 ); /* offset + length */
if ( error )
return error;
}
}
return FT_THROW( Unknown_File_Format );
}
static FT_Error
raccess_guess_linux_double_from_file_name( FT_Library library,
char *file_name,
FT_Long *result_offset )
{
FT_Open_Args args2;
FT_Stream stream2;
char* nouse = NULL;
FT_Error error;
args2.flags = FT_OPEN_PATHNAME;
args2.pathname = file_name;
error = FT_Stream_New( library, &args2, &stream2 );
if ( error )
return error;
error = raccess_guess_apple_double( library, stream2, file_name,
&nouse, result_offset );
FT_Stream_Free( stream2, 0 );
return error;
}
static char*
raccess_make_file_name( FT_Memory memory,
const char *original_name,
const char *insertion )
{
char* new_name = NULL;
const char* tmp;
const char* slash;
size_t new_length;
FT_Error error;
new_length = ft_strlen( original_name ) + ft_strlen( insertion );
if ( FT_QALLOC( new_name, new_length + 1 ) )
return NULL;
tmp = ft_strrchr( original_name, '/' );
if ( tmp )
{
ft_strncpy( new_name,
original_name,
(size_t)( tmp - original_name + 1 ) );
new_name[tmp - original_name + 1] = '\0';
slash = tmp + 1;
}
else
{
slash = original_name;
new_name[0] = '\0';
}
ft_strcat( new_name, insertion );
ft_strcat( new_name, slash );
return new_name;
}
#else /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
/**************************************************************************
* Dummy function; just sets errors
*/
FT_BASE_DEF( void )
FT_Raccess_Guess( FT_Library library,
FT_Stream stream,
char *base_name,
char **new_names,
FT_Long *offsets,
FT_Error *errors )
{
FT_Int i;
FT_UNUSED( library );
FT_UNUSED( stream );
FT_UNUSED( base_name );
for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
{
new_names[i] = NULL;
offsets[i] = 0;
errors[i] = FT_ERR( Unimplemented_Feature );
}
}
#endif /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
/* END */

185
thirdparty/freetype/src/base/ftsnames.c vendored Normal file
View File

@@ -0,0 +1,185 @@
/****************************************************************************
*
* ftsnames.c
*
* Simple interface to access SFNT name tables (which are used
* to hold font names, copyright info, notices, etc.) (body).
*
* This is _not_ used to retrieve glyph names!
*
* Copyright (C) 1996-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/internal/ftdebug.h>
#include <freetype/ftsnames.h>
#include <freetype/internal/tttypes.h>
#include <freetype/internal/ftstream.h>
#ifdef TT_CONFIG_OPTION_SFNT_NAMES
/* documentation is in ftsnames.h */
FT_EXPORT_DEF( FT_UInt )
FT_Get_Sfnt_Name_Count( FT_Face face )
{
return ( face && FT_IS_SFNT( face ) ) ? ((TT_Face)face)->num_names : 0;
}
/* documentation is in ftsnames.h */
FT_EXPORT_DEF( FT_Error )
FT_Get_Sfnt_Name( FT_Face face,
FT_UInt idx,
FT_SfntName *aname )
{
FT_Error error = FT_ERR( Invalid_Argument );
if ( aname && face && FT_IS_SFNT( face ) )
{
TT_Face ttface = (TT_Face)face;
if ( idx < (FT_UInt)ttface->num_names )
{
TT_Name entry = ttface->name_table.names + idx;
/* load name on demand */
if ( entry->stringLength > 0 && !entry->string )
{
FT_Memory memory = face->memory;
FT_Stream stream = face->stream;
if ( FT_QNEW_ARRAY ( entry->string, entry->stringLength ) ||
FT_STREAM_SEEK( entry->stringOffset ) ||
FT_STREAM_READ( entry->string, entry->stringLength ) )
{
FT_FREE( entry->string );
entry->stringLength = 0;
}
}
aname->platform_id = entry->platformID;
aname->encoding_id = entry->encodingID;
aname->language_id = entry->languageID;
aname->name_id = entry->nameID;
aname->string = (FT_Byte*)entry->string;
aname->string_len = entry->stringLength;
error = FT_Err_Ok;
}
}
return error;
}
/* documentation is in ftsnames.h */
FT_EXPORT_DEF( FT_Error )
FT_Get_Sfnt_LangTag( FT_Face face,
FT_UInt langID,
FT_SfntLangTag *alangTag )
{
FT_Error error = FT_ERR( Invalid_Argument );
if ( alangTag && face && FT_IS_SFNT( face ) )
{
TT_Face ttface = (TT_Face)face;
if ( ttface->name_table.format != 1 )
return FT_THROW( Invalid_Table );
if ( langID > 0x8000U &&
langID - 0x8000U < ttface->name_table.numLangTagRecords )
{
TT_LangTag entry = ttface->name_table.langTags +
( langID - 0x8000U );
/* load name on demand */
if ( entry->stringLength > 0 && !entry->string )
{
FT_Memory memory = face->memory;
FT_Stream stream = face->stream;
if ( FT_QNEW_ARRAY ( entry->string, entry->stringLength ) ||
FT_STREAM_SEEK( entry->stringOffset ) ||
FT_STREAM_READ( entry->string, entry->stringLength ) )
{
FT_FREE( entry->string );
entry->stringLength = 0;
}
}
alangTag->string = (FT_Byte*)entry->string;
alangTag->string_len = entry->stringLength;
error = FT_Err_Ok;
}
}
return error;
}
#else /* !TT_CONFIG_OPTION_SFNT_NAMES */
FT_EXPORT_DEF( FT_UInt )
FT_Get_Sfnt_Name_Count( FT_Face face )
{
FT_UNUSED( face );
return 0;
}
FT_EXPORT_DEF( FT_Error )
FT_Get_Sfnt_Name( FT_Face face,
FT_UInt idx,
FT_SfntName *aname )
{
FT_UNUSED( face );
FT_UNUSED( idx );
FT_UNUSED( aname );
return FT_THROW( Unimplemented_Feature );
}
FT_EXPORT_DEF( FT_Error )
FT_Get_Sfnt_LangTag( FT_Face face,
FT_UInt langID,
FT_SfntLangTag *alangTag )
{
FT_UNUSED( face );
FT_UNUSED( langID );
FT_UNUSED( alangTag );
return FT_THROW( Unimplemented_Feature );
}
#endif /* !TT_CONFIG_OPTION_SFNT_NAMES */
/* END */

872
thirdparty/freetype/src/base/ftstream.c vendored Normal file
View File

@@ -0,0 +1,872 @@
/****************************************************************************
*
* ftstream.c
*
* I/O stream support (body).
*
* Copyright (C) 2000-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/internal/ftstream.h>
#include <freetype/internal/ftdebug.h>
/**************************************************************************
*
* The macro FT_COMPONENT is used in trace mode. It is an implicit
* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
* messages during execution.
*/
#undef FT_COMPONENT
#define FT_COMPONENT stream
FT_BASE_DEF( void )
FT_Stream_OpenMemory( FT_Stream stream,
const FT_Byte* base,
FT_ULong size )
{
stream->base = (FT_Byte*) base;
stream->size = size;
stream->pos = 0;
stream->cursor = NULL;
stream->read = NULL;
stream->close = NULL;
}
FT_BASE_DEF( void )
FT_Stream_Close( FT_Stream stream )
{
if ( stream && stream->close )
stream->close( stream );
}
FT_BASE_DEF( FT_Error )
FT_Stream_Seek( FT_Stream stream,
FT_ULong pos )
{
FT_Error error = FT_Err_Ok;
if ( stream->read )
{
if ( stream->read( stream, pos, NULL, 0 ) )
{
FT_ERROR(( "FT_Stream_Seek:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
pos, stream->size ));
error = FT_THROW( Invalid_Stream_Operation );
}
}
/* note that seeking to the first position after the file is valid */
else if ( pos > stream->size )
{
FT_ERROR(( "FT_Stream_Seek:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
pos, stream->size ));
error = FT_THROW( Invalid_Stream_Operation );
}
if ( !error )
stream->pos = pos;
return error;
}
FT_BASE_DEF( FT_Error )
FT_Stream_Skip( FT_Stream stream,
FT_Long distance )
{
if ( distance < 0 )
return FT_THROW( Invalid_Stream_Operation );
return FT_Stream_Seek( stream, stream->pos + (FT_ULong)distance );
}
FT_BASE_DEF( FT_ULong )
FT_Stream_Pos( FT_Stream stream )
{
return stream->pos;
}
FT_BASE_DEF( FT_Error )
FT_Stream_Read( FT_Stream stream,
FT_Byte* buffer,
FT_ULong count )
{
return FT_Stream_ReadAt( stream, stream->pos, buffer, count );
}
FT_BASE_DEF( FT_Error )
FT_Stream_ReadAt( FT_Stream stream,
FT_ULong pos,
FT_Byte* buffer,
FT_ULong count )
{
FT_Error error = FT_Err_Ok;
FT_ULong read_bytes;
if ( pos >= stream->size )
{
FT_ERROR(( "FT_Stream_ReadAt:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
pos, stream->size ));
return FT_THROW( Invalid_Stream_Operation );
}
if ( stream->read )
read_bytes = stream->read( stream, pos, buffer, count );
else
{
read_bytes = stream->size - pos;
if ( read_bytes > count )
read_bytes = count;
/* Allow "reading" zero bytes without UB even if buffer is NULL */
if ( count )
FT_MEM_COPY( buffer, stream->base + pos, read_bytes );
}
stream->pos = pos + read_bytes;
if ( read_bytes < count )
{
FT_ERROR(( "FT_Stream_ReadAt:"
" invalid read; expected %lu bytes, got %lu\n",
count, read_bytes ));
error = FT_THROW( Invalid_Stream_Operation );
}
return error;
}
FT_BASE_DEF( FT_ULong )
FT_Stream_TryRead( FT_Stream stream,
FT_Byte* buffer,
FT_ULong count )
{
FT_ULong read_bytes = 0;
if ( stream->pos >= stream->size )
goto Exit;
if ( stream->read )
read_bytes = stream->read( stream, stream->pos, buffer, count );
else
{
read_bytes = stream->size - stream->pos;
if ( read_bytes > count )
read_bytes = count;
/* Allow "reading" zero bytes without UB even if buffer is NULL */
if ( count )
FT_MEM_COPY( buffer, stream->base + stream->pos, read_bytes );
}
stream->pos += read_bytes;
Exit:
return read_bytes;
}
FT_BASE_DEF( FT_Error )
FT_Stream_ExtractFrame( FT_Stream stream,
FT_ULong count,
FT_Byte** pbytes )
{
FT_Error error;
error = FT_Stream_EnterFrame( stream, count );
if ( !error )
{
*pbytes = (FT_Byte*)stream->cursor;
/* equivalent to FT_Stream_ExitFrame(), with no memory block release */
stream->cursor = NULL;
stream->limit = NULL;
}
return error;
}
FT_BASE_DEF( void )
FT_Stream_ReleaseFrame( FT_Stream stream,
FT_Byte** pbytes )
{
if ( stream && stream->read )
{
FT_Memory memory = stream->memory;
#ifdef FT_DEBUG_MEMORY
ft_mem_free( memory, *pbytes );
#else
FT_FREE( *pbytes );
#endif
}
*pbytes = NULL;
}
FT_BASE_DEF( FT_Error )
FT_Stream_EnterFrame( FT_Stream stream,
FT_ULong count )
{
FT_Error error = FT_Err_Ok;
FT_ULong read_bytes;
FT_TRACE7(( "FT_Stream_EnterFrame: %ld bytes\n", count ));
/* check for nested frame access */
FT_ASSERT( stream && stream->cursor == 0 );
if ( stream->read )
{
/* allocate the frame in memory */
FT_Memory memory = stream->memory;
/* simple sanity check */
if ( count > stream->size )
{
FT_ERROR(( "FT_Stream_EnterFrame:"
" frame size (%lu) larger than stream size (%lu)\n",
count, stream->size ));
error = FT_THROW( Invalid_Stream_Operation );
goto Exit;
}
#ifdef FT_DEBUG_MEMORY
/* assume `ft_debug_file_` and `ft_debug_lineno_` are already set */
stream->base = (unsigned char*)ft_mem_qalloc( memory,
(FT_Long)count,
&error );
if ( error )
goto Exit;
#else
if ( FT_QALLOC( stream->base, count ) )
goto Exit;
#endif
/* read it */
read_bytes = stream->read( stream, stream->pos,
stream->base, count );
if ( read_bytes < count )
{
FT_ERROR(( "FT_Stream_EnterFrame:"
" invalid read; expected %lu bytes, got %lu\n",
count, read_bytes ));
FT_FREE( stream->base );
error = FT_THROW( Invalid_Stream_Operation );
}
stream->cursor = stream->base;
stream->limit = FT_OFFSET( stream->cursor, count );
stream->pos += read_bytes;
}
else
{
/* check current and new position */
if ( stream->pos >= stream->size ||
stream->size - stream->pos < count )
{
FT_ERROR(( "FT_Stream_EnterFrame:"
" invalid i/o; pos = 0x%lx, count = %lu, size = 0x%lx\n",
stream->pos, count, stream->size ));
error = FT_THROW( Invalid_Stream_Operation );
goto Exit;
}
/* set cursor */
stream->cursor = stream->base + stream->pos;
stream->limit = stream->cursor + count;
stream->pos += count;
}
Exit:
return error;
}
FT_BASE_DEF( void )
FT_Stream_ExitFrame( FT_Stream stream )
{
/* IMPORTANT: The assertion stream->cursor != 0 was removed, given */
/* that it is possible to access a frame of length 0 in */
/* some weird fonts (usually, when accessing an array of */
/* 0 records, like in some strange kern tables). */
/* */
/* In this case, the loader code handles the 0-length table */
/* gracefully; however, stream.cursor is really set to 0 by the */
/* FT_Stream_EnterFrame() call, and this is not an error. */
FT_TRACE7(( "FT_Stream_ExitFrame\n" ));
FT_ASSERT( stream );
if ( stream->read )
{
FT_Memory memory = stream->memory;
#ifdef FT_DEBUG_MEMORY
ft_mem_free( memory, stream->base );
stream->base = NULL;
#else
FT_FREE( stream->base );
#endif
}
stream->cursor = NULL;
stream->limit = NULL;
}
FT_BASE_DEF( FT_Byte )
FT_Stream_GetByte( FT_Stream stream )
{
FT_Byte result;
FT_ASSERT( stream && stream->cursor );
result = 0;
if ( stream->cursor < stream->limit )
result = *stream->cursor++;
return result;
}
FT_BASE_DEF( FT_UInt16 )
FT_Stream_GetUShort( FT_Stream stream )
{
FT_Byte* p;
FT_UInt16 result;
FT_ASSERT( stream && stream->cursor );
result = 0;
p = stream->cursor;
if ( p + 1 < stream->limit )
result = FT_NEXT_USHORT( p );
stream->cursor = p;
return result;
}
FT_BASE_DEF( FT_UInt16 )
FT_Stream_GetUShortLE( FT_Stream stream )
{
FT_Byte* p;
FT_UInt16 result;
FT_ASSERT( stream && stream->cursor );
result = 0;
p = stream->cursor;
if ( p + 1 < stream->limit )
result = FT_NEXT_USHORT_LE( p );
stream->cursor = p;
return result;
}
FT_BASE_DEF( FT_UInt32 )
FT_Stream_GetUOffset( FT_Stream stream )
{
FT_Byte* p;
FT_UInt32 result;
FT_ASSERT( stream && stream->cursor );
result = 0;
p = stream->cursor;
if ( p + 2 < stream->limit )
result = FT_NEXT_UOFF3( p );
stream->cursor = p;
return result;
}
FT_BASE_DEF( FT_UInt32 )
FT_Stream_GetULong( FT_Stream stream )
{
FT_Byte* p;
FT_UInt32 result;
FT_ASSERT( stream && stream->cursor );
result = 0;
p = stream->cursor;
if ( p + 3 < stream->limit )
result = FT_NEXT_ULONG( p );
stream->cursor = p;
return result;
}
FT_BASE_DEF( FT_UInt32 )
FT_Stream_GetULongLE( FT_Stream stream )
{
FT_Byte* p;
FT_UInt32 result;
FT_ASSERT( stream && stream->cursor );
result = 0;
p = stream->cursor;
if ( p + 3 < stream->limit )
result = FT_NEXT_ULONG_LE( p );
stream->cursor = p;
return result;
}
FT_BASE_DEF( FT_Byte )
FT_Stream_ReadByte( FT_Stream stream,
FT_Error* error )
{
FT_Byte result = 0;
FT_ASSERT( stream );
if ( stream->pos < stream->size )
{
if ( stream->read )
{
if ( stream->read( stream, stream->pos, &result, 1L ) != 1L )
goto Fail;
}
else
result = stream->base[stream->pos];
}
else
goto Fail;
stream->pos++;
*error = FT_Err_Ok;
return result;
Fail:
*error = FT_THROW( Invalid_Stream_Operation );
FT_ERROR(( "FT_Stream_ReadByte:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
stream->pos, stream->size ));
return result;
}
FT_BASE_DEF( FT_UInt16 )
FT_Stream_ReadUShort( FT_Stream stream,
FT_Error* error )
{
FT_Byte reads[2];
FT_Byte* p;
FT_UInt16 result = 0;
FT_ASSERT( stream );
if ( stream->pos + 1 < stream->size )
{
if ( stream->read )
{
if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
goto Fail;
p = reads;
}
else
p = stream->base + stream->pos;
if ( p )
result = FT_NEXT_USHORT( p );
}
else
goto Fail;
stream->pos += 2;
*error = FT_Err_Ok;
return result;
Fail:
*error = FT_THROW( Invalid_Stream_Operation );
FT_ERROR(( "FT_Stream_ReadUShort:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
stream->pos, stream->size ));
return result;
}
FT_BASE_DEF( FT_UInt16 )
FT_Stream_ReadUShortLE( FT_Stream stream,
FT_Error* error )
{
FT_Byte reads[2];
FT_Byte* p;
FT_UInt16 result = 0;
FT_ASSERT( stream );
if ( stream->pos + 1 < stream->size )
{
if ( stream->read )
{
if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
goto Fail;
p = reads;
}
else
p = stream->base + stream->pos;
if ( p )
result = FT_NEXT_USHORT_LE( p );
}
else
goto Fail;
stream->pos += 2;
*error = FT_Err_Ok;
return result;
Fail:
*error = FT_THROW( Invalid_Stream_Operation );
FT_ERROR(( "FT_Stream_ReadUShortLE:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
stream->pos, stream->size ));
return result;
}
FT_BASE_DEF( FT_ULong )
FT_Stream_ReadUOffset( FT_Stream stream,
FT_Error* error )
{
FT_Byte reads[3];
FT_Byte* p;
FT_ULong result = 0;
FT_ASSERT( stream );
if ( stream->pos + 2 < stream->size )
{
if ( stream->read )
{
if (stream->read( stream, stream->pos, reads, 3L ) != 3L )
goto Fail;
p = reads;
}
else
p = stream->base + stream->pos;
if ( p )
result = FT_NEXT_UOFF3( p );
}
else
goto Fail;
stream->pos += 3;
*error = FT_Err_Ok;
return result;
Fail:
*error = FT_THROW( Invalid_Stream_Operation );
FT_ERROR(( "FT_Stream_ReadUOffset:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
stream->pos, stream->size ));
return result;
}
FT_BASE_DEF( FT_UInt32 )
FT_Stream_ReadULong( FT_Stream stream,
FT_Error* error )
{
FT_Byte reads[4];
FT_Byte* p;
FT_UInt32 result = 0;
FT_ASSERT( stream );
if ( stream->pos + 3 < stream->size )
{
if ( stream->read )
{
if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
goto Fail;
p = reads;
}
else
p = stream->base + stream->pos;
if ( p )
result = FT_NEXT_ULONG( p );
}
else
goto Fail;
stream->pos += 4;
*error = FT_Err_Ok;
return result;
Fail:
*error = FT_THROW( Invalid_Stream_Operation );
FT_ERROR(( "FT_Stream_ReadULong:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
stream->pos, stream->size ));
return result;
}
FT_BASE_DEF( FT_UInt32 )
FT_Stream_ReadULongLE( FT_Stream stream,
FT_Error* error )
{
FT_Byte reads[4];
FT_Byte* p;
FT_UInt32 result = 0;
FT_ASSERT( stream );
if ( stream->pos + 3 < stream->size )
{
if ( stream->read )
{
if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
goto Fail;
p = reads;
}
else
p = stream->base + stream->pos;
if ( p )
result = FT_NEXT_ULONG_LE( p );
}
else
goto Fail;
stream->pos += 4;
*error = FT_Err_Ok;
return result;
Fail:
*error = FT_THROW( Invalid_Stream_Operation );
FT_ERROR(( "FT_Stream_ReadULongLE:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
stream->pos, stream->size ));
return result;
}
FT_BASE_DEF( FT_Error )
FT_Stream_ReadFields( FT_Stream stream,
const FT_Frame_Field* fields,
void* structure )
{
FT_Error error;
FT_Bool frame_accessed = 0;
FT_Byte* cursor;
if ( !fields )
return FT_THROW( Invalid_Argument );
if ( !stream )
return FT_THROW( Invalid_Stream_Handle );
cursor = stream->cursor;
error = FT_Err_Ok;
do
{
FT_ULong value;
FT_Int sign_shift;
FT_Byte* p;
switch ( fields->value )
{
case ft_frame_start: /* access a new frame */
error = FT_Stream_EnterFrame( stream, fields->offset );
if ( error )
goto Exit;
frame_accessed = 1;
cursor = stream->cursor;
fields++;
continue; /* loop! */
case ft_frame_bytes: /* read a byte sequence */
case ft_frame_skip: /* skip some bytes */
{
FT_Offset len = fields->size;
if ( len > (FT_Offset)( stream->limit - cursor ) )
{
error = FT_THROW( Invalid_Stream_Operation );
goto Exit;
}
if ( fields->value == ft_frame_bytes )
{
p = (FT_Byte*)structure + fields->offset;
FT_MEM_COPY( p, cursor, len );
}
cursor += len;
fields++;
continue;
}
case ft_frame_byte:
case ft_frame_schar: /* read a single byte */
value = FT_NEXT_BYTE( cursor );
sign_shift = 24;
break;
case ft_frame_short_be:
case ft_frame_ushort_be: /* read a 2-byte big-endian short */
value = FT_NEXT_USHORT( cursor );
sign_shift = 16;
break;
case ft_frame_short_le:
case ft_frame_ushort_le: /* read a 2-byte little-endian short */
value = FT_NEXT_USHORT_LE( cursor );
sign_shift = 16;
break;
case ft_frame_long_be:
case ft_frame_ulong_be: /* read a 4-byte big-endian long */
value = FT_NEXT_ULONG( cursor );
sign_shift = 0;
break;
case ft_frame_long_le:
case ft_frame_ulong_le: /* read a 4-byte little-endian long */
value = FT_NEXT_ULONG_LE( cursor );
sign_shift = 0;
break;
case ft_frame_off3_be:
case ft_frame_uoff3_be: /* read a 3-byte big-endian long */
value = FT_NEXT_UOFF3( cursor );
sign_shift = 8;
break;
case ft_frame_off3_le:
case ft_frame_uoff3_le: /* read a 3-byte little-endian long */
value = FT_NEXT_UOFF3_LE( cursor );
sign_shift = 8;
break;
default:
/* otherwise, exit the loop */
stream->cursor = cursor;
goto Exit;
}
/* now, compute the signed value if necessary */
if ( fields->value & FT_FRAME_OP_SIGNED )
value = (FT_ULong)( (FT_Int32)( value << sign_shift ) >> sign_shift );
/* finally, store the value in the object */
p = (FT_Byte*)structure + fields->offset;
switch ( fields->size )
{
case ( 8 / FT_CHAR_BIT ):
*(FT_Byte*)p = (FT_Byte)value;
break;
case ( 16 / FT_CHAR_BIT ):
*(FT_UShort*)p = (FT_UShort)value;
break;
case ( 32 / FT_CHAR_BIT ):
*(FT_UInt32*)p = (FT_UInt32)value;
break;
default: /* for 64-bit systems */
*(FT_ULong*)p = (FT_ULong)value;
}
/* go to next field */
fields++;
}
while ( 1 );
Exit:
/* close the frame if it was opened by this read */
if ( frame_accessed )
FT_Stream_ExitFrame( stream );
return error;
}
/* END */

2403
thirdparty/freetype/src/base/ftstroke.c vendored Normal file

File diff suppressed because it is too large Load Diff

180
thirdparty/freetype/src/base/ftsynth.c vendored Normal file
View File

@@ -0,0 +1,180 @@
/****************************************************************************
*
* ftsynth.c
*
* FreeType synthesizing code for emboldening and slanting (body).
*
* Copyright (C) 2000-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/ftsynth.h>
#include <freetype/internal/ftdebug.h>
#include <freetype/internal/ftobjs.h>
#include <freetype/ftoutln.h>
#include <freetype/ftbitmap.h>
/**************************************************************************
*
* The macro FT_COMPONENT is used in trace mode. It is an implicit
* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
* messages during execution.
*/
#undef FT_COMPONENT
#define FT_COMPONENT synth
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** EXPERIMENTAL OBLIQUING SUPPORT ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/* documentation is in ftsynth.h */
FT_EXPORT_DEF( void )
FT_GlyphSlot_Oblique( FT_GlyphSlot slot )
{
/* Value '0x0366A' corresponds to a shear angle of about 12 degrees. */
FT_GlyphSlot_Slant( slot, 0x0366A, 0 );
}
/* documentation is in ftsynth.h */
FT_EXPORT_DEF( void )
FT_GlyphSlot_Slant( FT_GlyphSlot slot,
FT_Fixed xslant,
FT_Fixed yslant )
{
FT_Matrix transform;
FT_Outline* outline;
if ( !slot )
return;
outline = &slot->outline;
/* only oblique outline glyphs */
if ( slot->format != FT_GLYPH_FORMAT_OUTLINE )
return;
/* we don't touch the advance width */
/* For italic, simply apply a shear transform */
transform.xx = 0x10000L;
transform.yx = -yslant;
transform.xy = xslant;
transform.yy = 0x10000L;
FT_Outline_Transform( outline, &transform );
}
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** EXPERIMENTAL EMBOLDENING SUPPORT ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/* documentation is in ftsynth.h */
FT_EXPORT_DEF( void )
FT_GlyphSlot_Embolden( FT_GlyphSlot slot )
{
FT_GlyphSlot_AdjustWeight( slot, 0x0AAA, 0x0AAA );
}
FT_EXPORT_DEF( void )
FT_GlyphSlot_AdjustWeight( FT_GlyphSlot slot,
FT_Fixed xdelta,
FT_Fixed ydelta )
{
FT_Library library;
FT_Size size;
FT_Error error;
FT_Pos xstr, ystr;
if ( !slot )
return;
library = slot->library;
size = slot->face->size;
if ( slot->format != FT_GLYPH_FORMAT_OUTLINE &&
slot->format != FT_GLYPH_FORMAT_BITMAP )
return;
/* express deltas in pixels in 26.6 format */
xstr = (FT_Pos)size->metrics.x_ppem * xdelta / 1024;
ystr = (FT_Pos)size->metrics.y_ppem * ydelta / 1024;
if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
FT_Outline_EmboldenXY( &slot->outline, xstr, ystr );
else /* slot->format == FT_GLYPH_FORMAT_BITMAP */
{
/* round to full pixels */
xstr &= ~63;
if ( xstr == 0 )
xstr = 1 << 6;
ystr &= ~63;
/*
* XXX: overflow check for 16-bit system, for compatibility
* with FT_GlyphSlot_Embolden() since FreeType 2.1.10.
* unfortunately, this function return no informations
* about the cause of error.
*/
if ( ( ystr >> 6 ) > FT_INT_MAX || ( ystr >> 6 ) < FT_INT_MIN )
{
FT_TRACE1(( "FT_GlyphSlot_Embolden:" ));
FT_TRACE1(( "too strong emboldening parameter ystr=%ld\n", ystr ));
return;
}
error = FT_GlyphSlot_Own_Bitmap( slot );
if ( error )
return;
error = FT_Bitmap_Embolden( library, &slot->bitmap, xstr, ystr );
if ( error )
return;
}
if ( slot->advance.x )
slot->advance.x += xstr;
if ( slot->advance.y )
slot->advance.y += ystr;
slot->metrics.width += xstr;
slot->metrics.height += ystr;
slot->metrics.horiAdvance += xstr;
slot->metrics.vertAdvance += ystr;
slot->metrics.horiBearingY += ystr;
/* XXX: 16-bit overflow case must be excluded before here */
if ( slot->format == FT_GLYPH_FORMAT_BITMAP )
slot->bitmap_top += (FT_Int)( ystr >> 6 );
}
/* END */

338
thirdparty/freetype/src/base/ftsystem.c vendored Normal file
View File

@@ -0,0 +1,338 @@
/****************************************************************************
*
* ftsystem.c
*
* ANSI-specific FreeType low-level system interface (body).
*
* Copyright (C) 1996-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
/**************************************************************************
*
* This file contains the default interface used by FreeType to access
* low-level, i.e. memory management, i/o access as well as thread
* synchronisation. It can be replaced by user-specific routines if
* necessary.
*
*/
#include <ft2build.h>
#include FT_CONFIG_CONFIG_H
#include <freetype/internal/ftdebug.h>
#include <freetype/internal/ftstream.h>
#include <freetype/ftsystem.h>
#include <freetype/fterrors.h>
#include <freetype/fttypes.h>
/**************************************************************************
*
* MEMORY MANAGEMENT INTERFACE
*
*/
/**************************************************************************
*
* It is not necessary to do any error checking for the
* allocation-related functions. This will be done by the higher level
* routines like ft_mem_alloc() or ft_mem_realloc().
*
*/
/**************************************************************************
*
* @Function:
* ft_alloc
*
* @Description:
* The memory allocation function.
*
* @Input:
* memory ::
* A pointer to the memory object.
*
* size ::
* The requested size in bytes.
*
* @Return:
* The address of newly allocated block.
*/
FT_CALLBACK_DEF( void* )
ft_alloc( FT_Memory memory,
long size )
{
FT_UNUSED( memory );
return ft_smalloc( (size_t)size );
}
/**************************************************************************
*
* @Function:
* ft_realloc
*
* @Description:
* The memory reallocation function.
*
* @Input:
* memory ::
* A pointer to the memory object.
*
* cur_size ::
* The current size of the allocated memory block.
*
* new_size ::
* The newly requested size in bytes.
*
* block ::
* The current address of the block in memory.
*
* @Return:
* The address of the reallocated memory block.
*/
FT_CALLBACK_DEF( void* )
ft_realloc( FT_Memory memory,
long cur_size,
long new_size,
void* block )
{
FT_UNUSED( memory );
FT_UNUSED( cur_size );
return ft_srealloc( block, (size_t)new_size );
}
/**************************************************************************
*
* @Function:
* ft_free
*
* @Description:
* The memory release function.
*
* @Input:
* memory ::
* A pointer to the memory object.
*
* block ::
* The address of block in memory to be freed.
*/
FT_CALLBACK_DEF( void )
ft_free( FT_Memory memory,
void* block )
{
FT_UNUSED( memory );
ft_sfree( block );
}
/**************************************************************************
*
* RESOURCE MANAGEMENT INTERFACE
*
*/
#ifndef FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT
/**************************************************************************
*
* The macro FT_COMPONENT is used in trace mode. It is an implicit
* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
* messages during execution.
*/
#undef FT_COMPONENT
#define FT_COMPONENT io
/* We use the macro STREAM_FILE for convenience to extract the */
/* system-specific stream handle from a given FreeType stream object */
#define STREAM_FILE( stream ) ( (FT_FILE*)stream->descriptor.pointer )
/**************************************************************************
*
* @Function:
* ft_ansi_stream_close
*
* @Description:
* The function to close a stream.
*
* @Input:
* stream ::
* A pointer to the stream object.
*/
FT_CALLBACK_DEF( void )
ft_ansi_stream_close( FT_Stream stream )
{
ft_fclose( STREAM_FILE( stream ) );
stream->descriptor.pointer = NULL;
stream->size = 0;
stream->base = NULL;
}
/**************************************************************************
*
* @Function:
* ft_ansi_stream_io
*
* @Description:
* The function to open a stream.
*
* @Input:
* stream ::
* A pointer to the stream object.
*
* offset ::
* The position in the data stream to start reading.
*
* buffer ::
* The address of buffer to store the read data.
*
* count ::
* The number of bytes to read from the stream.
*
* @Return:
* The number of bytes actually read. If `count' is zero (that is,
* the function is used for seeking), a non-zero return value
* indicates an error.
*/
FT_CALLBACK_DEF( unsigned long )
ft_ansi_stream_io( FT_Stream stream,
unsigned long offset,
unsigned char* buffer,
unsigned long count )
{
FT_FILE* file;
if ( offset > stream->size && !count )
return 1;
file = STREAM_FILE( stream );
if ( stream->pos != offset )
ft_fseek( file, (long)offset, SEEK_SET );
/* Avoid calling `fread` with `buffer=NULL` and `count=0`, */
/* which is undefined behaviour. */
if ( !count )
return 0;
return (unsigned long)ft_fread( buffer, 1, count, file );
}
/* documentation is in ftstream.h */
FT_BASE_DEF( FT_Error )
FT_Stream_Open( FT_Stream stream,
const char* filepathname )
{
FT_FILE* file;
if ( !stream )
return FT_THROW( Invalid_Stream_Handle );
stream->descriptor.pointer = NULL;
stream->pathname.pointer = (char*)filepathname;
stream->base = NULL;
stream->pos = 0;
stream->read = NULL;
stream->close = NULL;
file = ft_fopen( filepathname, "rb" );
if ( !file )
{
FT_ERROR(( "FT_Stream_Open:"
" could not open `%s'\n", filepathname ));
return FT_THROW( Cannot_Open_Resource );
}
ft_fseek( file, 0, SEEK_END );
stream->size = (unsigned long)ft_ftell( file );
if ( !stream->size )
{
FT_ERROR(( "FT_Stream_Open:" ));
FT_ERROR(( " opened `%s' but zero-sized\n", filepathname ));
ft_fclose( file );
return FT_THROW( Cannot_Open_Stream );
}
ft_fseek( file, 0, SEEK_SET );
stream->descriptor.pointer = file;
stream->read = ft_ansi_stream_io;
stream->close = ft_ansi_stream_close;
FT_TRACE1(( "FT_Stream_Open:" ));
FT_TRACE1(( " opened `%s' (%ld bytes) successfully\n",
filepathname, stream->size ));
return FT_Err_Ok;
}
#endif /* !FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT */
#ifdef FT_DEBUG_MEMORY
extern FT_Int
ft_mem_debug_init( FT_Memory memory );
extern void
ft_mem_debug_done( FT_Memory memory );
#endif
/* documentation is in ftobjs.h */
FT_BASE_DEF( FT_Memory )
FT_New_Memory( void )
{
FT_Memory memory;
memory = (FT_Memory)ft_smalloc( sizeof ( *memory ) );
if ( memory )
{
memory->user = NULL;
memory->alloc = ft_alloc;
memory->realloc = ft_realloc;
memory->free = ft_free;
#ifdef FT_DEBUG_MEMORY
ft_mem_debug_init( memory );
#endif
}
return memory;
}
/* documentation is in ftobjs.h */
FT_BASE_DEF( void )
FT_Done_Memory( FT_Memory memory )
{
#ifdef FT_DEBUG_MEMORY
ft_mem_debug_done( memory );
#endif
ft_sfree( memory );
}
/* END */

517
thirdparty/freetype/src/base/fttrigon.c vendored Normal file
View File

@@ -0,0 +1,517 @@
/****************************************************************************
*
* fttrigon.c
*
* FreeType trigonometric functions (body).
*
* Copyright (C) 2001-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
/**************************************************************************
*
* This is a fixed-point CORDIC implementation of trigonometric
* functions as well as transformations between Cartesian and polar
* coordinates. The angles are represented as 16.16 fixed-point values
* in degrees, i.e., the angular resolution is 2^-16 degrees. Note that
* only vectors longer than 2^16*180/pi (or at least 22 bits) on a
* discrete Cartesian grid can have the same or better angular
* resolution. Therefore, to maintain this precision, some functions
* require an interim upscaling of the vectors, whereas others operate
* with 24-bit long vectors directly.
*
*/
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/ftcalc.h>
#include <freetype/fttrigon.h>
/* the Cordic shrink factor 0.858785336480436 * 2^32 */
#define FT_TRIG_SCALE 0xDBD95B16UL
/* the highest bit in overflow-safe vector components, */
/* MSB of 0.858785336480436 * sqrt(0.5) * 2^30 */
#define FT_TRIG_SAFE_MSB 29
/* this table was generated for FT_PI = 180L << 16, i.e. degrees */
#define FT_TRIG_MAX_ITERS 23
static const FT_Angle
ft_trig_arctan_table[] =
{
1740967L, 919879L, 466945L, 234379L, 117304L, 58666L, 29335L,
14668L, 7334L, 3667L, 1833L, 917L, 458L, 229L, 115L,
57L, 29L, 14L, 7L, 4L, 2L, 1L
};
#ifdef FT_INT64
/* multiply a given value by the CORDIC shrink factor */
static FT_Fixed
ft_trig_downscale( FT_Fixed val )
{
FT_Int s = 1;
if ( val < 0 )
{
val = -val;
s = -1;
}
/* 0x40000000 comes from regression analysis between true */
/* and CORDIC hypotenuse, so it minimizes the error */
val = (FT_Fixed)(
( (FT_UInt64)val * FT_TRIG_SCALE + 0x40000000UL ) >> 32 );
return s < 0 ? -val : val;
}
#else /* !FT_INT64 */
/* multiply a given value by the CORDIC shrink factor */
static FT_Fixed
ft_trig_downscale( FT_Fixed val )
{
FT_Int s = 1;
FT_UInt32 lo1, hi1, lo2, hi2, lo, hi, i1, i2;
if ( val < 0 )
{
val = -val;
s = -1;
}
lo1 = (FT_UInt32)val & 0x0000FFFFU;
hi1 = (FT_UInt32)val >> 16;
lo2 = FT_TRIG_SCALE & 0x0000FFFFU;
hi2 = FT_TRIG_SCALE >> 16;
lo = lo1 * lo2;
i1 = lo1 * hi2;
i2 = lo2 * hi1;
hi = hi1 * hi2;
/* Check carry overflow of i1 + i2 */
i1 += i2;
hi += (FT_UInt32)( i1 < i2 ) << 16;
hi += i1 >> 16;
i1 = i1 << 16;
/* Check carry overflow of i1 + lo */
lo += i1;
hi += ( lo < i1 );
/* 0x40000000 comes from regression analysis between true */
/* and CORDIC hypotenuse, so it minimizes the error */
/* Check carry overflow of lo + 0x40000000 */
lo += 0x40000000UL;
hi += ( lo < 0x40000000UL );
val = (FT_Fixed)hi;
return s < 0 ? -val : val;
}
#endif /* !FT_INT64 */
/* undefined and never called for zero vector */
static FT_Int
ft_trig_prenorm( FT_Vector* vec )
{
FT_Pos x, y;
FT_Int shift;
x = vec->x;
y = vec->y;
shift = FT_MSB( (FT_UInt32)( FT_ABS( x ) | FT_ABS( y ) ) );
if ( shift <= FT_TRIG_SAFE_MSB )
{
shift = FT_TRIG_SAFE_MSB - shift;
vec->x = (FT_Pos)( (FT_ULong)x << shift );
vec->y = (FT_Pos)( (FT_ULong)y << shift );
}
else
{
shift -= FT_TRIG_SAFE_MSB;
vec->x = x >> shift;
vec->y = y >> shift;
shift = -shift;
}
return shift;
}
static void
ft_trig_pseudo_rotate( FT_Vector* vec,
FT_Angle theta )
{
FT_Int i;
FT_Fixed x, y, xtemp, b;
const FT_Angle *arctanptr;
x = vec->x;
y = vec->y;
/* Rotate inside [-PI/4,PI/4] sector */
while ( theta < -FT_ANGLE_PI4 )
{
xtemp = y;
y = -x;
x = xtemp;
theta += FT_ANGLE_PI2;
}
while ( theta > FT_ANGLE_PI4 )
{
xtemp = -y;
y = x;
x = xtemp;
theta -= FT_ANGLE_PI2;
}
arctanptr = ft_trig_arctan_table;
/* Pseudorotations, with right shifts */
for ( i = 1, b = 1; i < FT_TRIG_MAX_ITERS; b <<= 1, i++ )
{
if ( theta < 0 )
{
xtemp = x + ( ( y + b ) >> i );
y = y - ( ( x + b ) >> i );
x = xtemp;
theta += *arctanptr++;
}
else
{
xtemp = x - ( ( y + b ) >> i );
y = y + ( ( x + b ) >> i );
x = xtemp;
theta -= *arctanptr++;
}
}
vec->x = x;
vec->y = y;
}
static void
ft_trig_pseudo_polarize( FT_Vector* vec )
{
FT_Angle theta;
FT_Int i;
FT_Fixed x, y, xtemp, b;
const FT_Angle *arctanptr;
x = vec->x;
y = vec->y;
/* Get the vector into [-PI/4,PI/4] sector */
if ( y > x )
{
if ( y > -x )
{
theta = FT_ANGLE_PI2;
xtemp = y;
y = -x;
x = xtemp;
}
else
{
theta = y > 0 ? FT_ANGLE_PI : -FT_ANGLE_PI;
x = -x;
y = -y;
}
}
else
{
if ( y < -x )
{
theta = -FT_ANGLE_PI2;
xtemp = -y;
y = x;
x = xtemp;
}
else
{
theta = 0;
}
}
arctanptr = ft_trig_arctan_table;
/* Pseudorotations, with right shifts */
for ( i = 1, b = 1; i < FT_TRIG_MAX_ITERS; b <<= 1, i++ )
{
if ( y > 0 )
{
xtemp = x + ( ( y + b ) >> i );
y = y - ( ( x + b ) >> i );
x = xtemp;
theta += *arctanptr++;
}
else
{
xtemp = x - ( ( y + b ) >> i );
y = y + ( ( x + b ) >> i );
x = xtemp;
theta -= *arctanptr++;
}
}
/* round theta to acknowledge its error that mostly comes */
/* from accumulated rounding errors in the arctan table */
if ( theta >= 0 )
theta = FT_PAD_ROUND( theta, 16 );
else
theta = -FT_PAD_ROUND( -theta, 16 );
vec->x = x;
vec->y = theta;
}
/* documentation is in fttrigon.h */
FT_EXPORT_DEF( FT_Fixed )
FT_Cos( FT_Angle angle )
{
FT_Vector v;
FT_Vector_Unit( &v, angle );
return v.x;
}
/* documentation is in fttrigon.h */
FT_EXPORT_DEF( FT_Fixed )
FT_Sin( FT_Angle angle )
{
FT_Vector v;
FT_Vector_Unit( &v, angle );
return v.y;
}
/* documentation is in fttrigon.h */
FT_EXPORT_DEF( FT_Fixed )
FT_Tan( FT_Angle angle )
{
FT_Vector v = { 1 << 24, 0 };
ft_trig_pseudo_rotate( &v, angle );
return FT_DivFix( v.y, v.x );
}
/* documentation is in fttrigon.h */
FT_EXPORT_DEF( FT_Angle )
FT_Atan2( FT_Fixed dx,
FT_Fixed dy )
{
FT_Vector v;
if ( dx == 0 && dy == 0 )
return 0;
v.x = dx;
v.y = dy;
ft_trig_prenorm( &v );
ft_trig_pseudo_polarize( &v );
return v.y;
}
/* documentation is in fttrigon.h */
FT_EXPORT_DEF( void )
FT_Vector_Unit( FT_Vector* vec,
FT_Angle angle )
{
if ( !vec )
return;
vec->x = FT_TRIG_SCALE >> 8;
vec->y = 0;
ft_trig_pseudo_rotate( vec, angle );
vec->x = ( vec->x + 0x80L ) >> 8;
vec->y = ( vec->y + 0x80L ) >> 8;
}
/* documentation is in fttrigon.h */
FT_EXPORT_DEF( void )
FT_Vector_Rotate( FT_Vector* vec,
FT_Angle angle )
{
FT_Int shift;
FT_Vector v;
if ( !vec || !angle )
return;
v = *vec;
if ( v.x == 0 && v.y == 0 )
return;
shift = ft_trig_prenorm( &v );
ft_trig_pseudo_rotate( &v, angle );
v.x = ft_trig_downscale( v.x );
v.y = ft_trig_downscale( v.y );
if ( shift > 0 )
{
FT_Int32 half = (FT_Int32)1L << ( shift - 1 );
vec->x = ( v.x + half - ( v.x < 0 ) ) >> shift;
vec->y = ( v.y + half - ( v.y < 0 ) ) >> shift;
}
else
{
shift = -shift;
vec->x = (FT_Pos)( (FT_ULong)v.x << shift );
vec->y = (FT_Pos)( (FT_ULong)v.y << shift );
}
}
/* documentation is in fttrigon.h */
FT_EXPORT_DEF( FT_Fixed )
FT_Vector_Length( FT_Vector* vec )
{
FT_Int shift;
FT_Vector v;
if ( !vec )
return 0;
v = *vec;
/* handle trivial cases */
if ( v.x == 0 )
{
return FT_ABS( v.y );
}
else if ( v.y == 0 )
{
return FT_ABS( v.x );
}
/* general case */
shift = ft_trig_prenorm( &v );
ft_trig_pseudo_polarize( &v );
v.x = ft_trig_downscale( v.x );
if ( shift > 0 )
return ( v.x + ( 1L << ( shift - 1 ) ) ) >> shift;
return (FT_Fixed)( (FT_UInt32)v.x << -shift );
}
/* documentation is in fttrigon.h */
FT_EXPORT_DEF( void )
FT_Vector_Polarize( FT_Vector* vec,
FT_Fixed *length,
FT_Angle *angle )
{
FT_Int shift;
FT_Vector v;
if ( !vec || !length || !angle )
return;
v = *vec;
if ( v.x == 0 && v.y == 0 )
return;
shift = ft_trig_prenorm( &v );
ft_trig_pseudo_polarize( &v );
v.x = ft_trig_downscale( v.x );
*length = shift >= 0 ? ( v.x >> shift )
: (FT_Fixed)( (FT_UInt32)v.x << -shift );
*angle = v.y;
}
/* documentation is in fttrigon.h */
FT_EXPORT_DEF( void )
FT_Vector_From_Polar( FT_Vector* vec,
FT_Fixed length,
FT_Angle angle )
{
if ( !vec )
return;
vec->x = length;
vec->y = 0;
FT_Vector_Rotate( vec, angle );
}
/* documentation is in fttrigon.h */
FT_EXPORT_DEF( FT_Angle )
FT_Angle_Diff( FT_Angle angle1,
FT_Angle angle2 )
{
FT_Angle delta = angle2 - angle1;
while ( delta <= -FT_ANGLE_PI )
delta += FT_ANGLE_2PI;
while ( delta > FT_ANGLE_PI )
delta -= FT_ANGLE_2PI;
return delta;
}
/* END */

126
thirdparty/freetype/src/base/fttype1.c vendored Normal file
View File

@@ -0,0 +1,126 @@
/****************************************************************************
*
* fttype1.c
*
* FreeType utility file for PS names support (body).
*
* Copyright (C) 2002-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/internal/ftdebug.h>
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/ftserv.h>
#include <freetype/internal/services/svpsinfo.h>
/* documentation is in t1tables.h */
FT_EXPORT_DEF( FT_Error )
FT_Get_PS_Font_Info( FT_Face face,
PS_FontInfoRec* afont_info )
{
FT_Error error;
FT_Service_PsInfo service;
if ( !face )
return FT_THROW( Invalid_Face_Handle );
if ( !afont_info )
return FT_THROW( Invalid_Argument );
FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
if ( service && service->ps_get_font_info )
error = service->ps_get_font_info( face, afont_info );
else
error = FT_THROW( Invalid_Argument );
return error;
}
/* documentation is in t1tables.h */
FT_EXPORT_DEF( FT_Int )
FT_Has_PS_Glyph_Names( FT_Face face )
{
FT_Int result = 0;
FT_Service_PsInfo service;
if ( face )
{
FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
if ( service && service->ps_has_glyph_names )
result = service->ps_has_glyph_names( face );
}
return result;
}
/* documentation is in t1tables.h */
FT_EXPORT_DEF( FT_Error )
FT_Get_PS_Font_Private( FT_Face face,
PS_PrivateRec* afont_private )
{
FT_Error error;
FT_Service_PsInfo service;
if ( !face )
return FT_THROW( Invalid_Face_Handle );
if ( !afont_private )
return FT_THROW( Invalid_Argument );
FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
if ( service && service->ps_get_font_private )
error = service->ps_get_font_private( face, afont_private );
else
error = FT_THROW( Invalid_Argument );
return error;
}
/* documentation is in t1tables.h */
FT_EXPORT_DEF( FT_Long )
FT_Get_PS_Font_Value( FT_Face face,
PS_Dict_Keys key,
FT_UInt idx,
void *value,
FT_Long value_len )
{
FT_Int result = 0;
FT_Service_PsInfo service = NULL;
if ( face )
{
FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
if ( service && service->ps_get_font_value )
result = service->ps_get_font_value( face, key, idx,
value, value_len );
}
return result;
}
/* END */

442
thirdparty/freetype/src/base/ftutil.c vendored Normal file
View File

@@ -0,0 +1,442 @@
/****************************************************************************
*
* ftutil.c
*
* FreeType utility file for memory and list management (body).
*
* Copyright (C) 2002-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/internal/ftdebug.h>
#include <freetype/internal/ftmemory.h>
#include <freetype/internal/ftobjs.h>
#include <freetype/ftlist.h>
/**************************************************************************
*
* The macro FT_COMPONENT is used in trace mode. It is an implicit
* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
* messages during execution.
*/
#undef FT_COMPONENT
#define FT_COMPONENT memory
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** *****/
/***** M E M O R Y M A N A G E M E N T *****/
/***** *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
FT_BASE_DEF( FT_Pointer )
ft_mem_alloc( FT_Memory memory,
FT_Long size,
FT_Error *p_error )
{
FT_Error error;
FT_Pointer block = ft_mem_qalloc( memory, size, &error );
if ( !error && block && size > 0 )
FT_MEM_ZERO( block, size );
*p_error = error;
return block;
}
FT_BASE_DEF( FT_Pointer )
ft_mem_qalloc( FT_Memory memory,
FT_Long size,
FT_Error *p_error )
{
FT_Error error = FT_Err_Ok;
FT_Pointer block = NULL;
if ( size > 0 )
{
block = memory->alloc( memory, size );
if ( !block )
error = FT_THROW( Out_Of_Memory );
}
else if ( size < 0 )
{
/* may help catch/prevent security issues */
error = FT_THROW( Invalid_Argument );
}
*p_error = error;
return block;
}
FT_BASE_DEF( FT_Pointer )
ft_mem_realloc( FT_Memory memory,
FT_Long item_size,
FT_Long cur_count,
FT_Long new_count,
void* block,
FT_Error *p_error )
{
FT_Error error = FT_Err_Ok;
block = ft_mem_qrealloc( memory, item_size,
cur_count, new_count, block, &error );
if ( !error && block && new_count > cur_count )
FT_MEM_ZERO( (char*)block + cur_count * item_size,
( new_count - cur_count ) * item_size );
*p_error = error;
return block;
}
FT_BASE_DEF( FT_Pointer )
ft_mem_qrealloc( FT_Memory memory,
FT_Long item_size,
FT_Long cur_count,
FT_Long new_count,
void* block,
FT_Error *p_error )
{
FT_Error error = FT_Err_Ok;
/* Note that we now accept `item_size == 0' as a valid parameter, in
* order to cover very weird cases where an ALLOC_MULT macro would be
* called.
*/
if ( cur_count < 0 || new_count < 0 || item_size < 0 )
{
/* may help catch/prevent nasty security issues */
error = FT_THROW( Invalid_Argument );
}
else if ( new_count == 0 || item_size == 0 )
{
ft_mem_free( memory, block );
block = NULL;
}
else if ( new_count > FT_INT_MAX / item_size )
{
error = FT_THROW( Array_Too_Large );
}
else if ( cur_count == 0 )
{
FT_ASSERT( !block );
block = memory->alloc( memory, new_count * item_size );
if ( block == NULL )
error = FT_THROW( Out_Of_Memory );
}
else
{
FT_Pointer block2;
FT_Long cur_size = cur_count * item_size;
FT_Long new_size = new_count * item_size;
block2 = memory->realloc( memory, cur_size, new_size, block );
if ( !block2 )
error = FT_THROW( Out_Of_Memory );
else
block = block2;
}
*p_error = error;
return block;
}
FT_BASE_DEF( void )
ft_mem_free( FT_Memory memory,
const void *P )
{
if ( P )
memory->free( memory, (void*)P );
}
FT_BASE_DEF( FT_Pointer )
ft_mem_dup( FT_Memory memory,
const void* address,
FT_ULong size,
FT_Error *p_error )
{
FT_Error error;
FT_Pointer p = ft_mem_qalloc( memory, (FT_Long)size, &error );
if ( !error && address && size > 0 )
ft_memcpy( p, address, size );
*p_error = error;
return p;
}
FT_BASE_DEF( FT_Pointer )
ft_mem_strdup( FT_Memory memory,
const char* str,
FT_Error *p_error )
{
FT_ULong len = str ? (FT_ULong)ft_strlen( str ) + 1
: 0;
return ft_mem_dup( memory, str, len, p_error );
}
FT_BASE_DEF( FT_Int )
ft_mem_strcpyn( char* dst,
const char* src,
FT_ULong size )
{
while ( size > 1 && *src != 0 )
{
*dst++ = *src++;
size--;
}
*dst = 0; /* always zero-terminate */
return *src != 0;
}
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** *****/
/***** D O U B L Y L I N K E D L I S T S *****/
/***** *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
#undef FT_COMPONENT
#define FT_COMPONENT list
/* documentation is in ftlist.h */
FT_EXPORT_DEF( FT_ListNode )
FT_List_Find( FT_List list,
void* data )
{
FT_ListNode cur;
if ( !list )
return NULL;
cur = list->head;
while ( cur )
{
if ( cur->data == data )
return cur;
cur = cur->next;
}
return NULL;
}
/* documentation is in ftlist.h */
FT_EXPORT_DEF( void )
FT_List_Add( FT_List list,
FT_ListNode node )
{
FT_ListNode before;
if ( !list || !node )
return;
before = list->tail;
node->next = NULL;
node->prev = before;
if ( before )
before->next = node;
else
list->head = node;
list->tail = node;
}
/* documentation is in ftlist.h */
FT_EXPORT_DEF( void )
FT_List_Insert( FT_List list,
FT_ListNode node )
{
FT_ListNode after;
if ( !list || !node )
return;
after = list->head;
node->next = after;
node->prev = NULL;
if ( !after )
list->tail = node;
else
after->prev = node;
list->head = node;
}
/* documentation is in ftlist.h */
FT_EXPORT_DEF( void )
FT_List_Remove( FT_List list,
FT_ListNode node )
{
FT_ListNode before, after;
if ( !list || !node )
return;
before = node->prev;
after = node->next;
if ( before )
before->next = after;
else
list->head = after;
if ( after )
after->prev = before;
else
list->tail = before;
}
/* documentation is in ftlist.h */
FT_EXPORT_DEF( void )
FT_List_Up( FT_List list,
FT_ListNode node )
{
FT_ListNode before, after;
if ( !list || !node )
return;
before = node->prev;
after = node->next;
/* check whether we are already on top of the list */
if ( !before )
return;
before->next = after;
if ( after )
after->prev = before;
else
list->tail = before;
node->prev = NULL;
node->next = list->head;
list->head->prev = node;
list->head = node;
}
/* documentation is in ftlist.h */
FT_EXPORT_DEF( FT_Error )
FT_List_Iterate( FT_List list,
FT_List_Iterator iterator,
void* user )
{
FT_ListNode cur;
FT_Error error = FT_Err_Ok;
if ( !list || !iterator )
return FT_THROW( Invalid_Argument );
cur = list->head;
while ( cur )
{
FT_ListNode next = cur->next;
error = iterator( cur, user );
if ( error )
break;
cur = next;
}
return error;
}
/* documentation is in ftlist.h */
FT_EXPORT_DEF( void )
FT_List_Finalize( FT_List list,
FT_List_Destructor destroy,
FT_Memory memory,
void* user )
{
FT_ListNode cur;
if ( !list || !memory )
return;
cur = list->head;
while ( cur )
{
FT_ListNode next = cur->next;
void* data = cur->data;
if ( destroy )
destroy( memory, data, user );
FT_FREE( cur );
cur = next;
}
list->head = NULL;
list->tail = NULL;
}
/* END */

52
thirdparty/freetype/src/base/ftwinfnt.c vendored Normal file
View File

@@ -0,0 +1,52 @@
/****************************************************************************
*
* ftwinfnt.c
*
* FreeType API for accessing Windows FNT specific info (body).
*
* Copyright (C) 2003-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/internal/ftdebug.h>
#include <freetype/ftwinfnt.h>
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/services/svwinfnt.h>
/* documentation is in ftwinfnt.h */
FT_EXPORT_DEF( FT_Error )
FT_Get_WinFNT_Header( FT_Face face,
FT_WinFNT_HeaderRec *header )
{
FT_Service_WinFnt service;
FT_Error error;
if ( !face )
return FT_THROW( Invalid_Face_Handle );
if ( !header )
return FT_THROW( Invalid_Argument );
FT_FACE_LOOKUP_SERVICE( face, service, WINFNT );
if ( service )
error = service->get_header( face, header );
else
error = FT_THROW( Invalid_Argument );
return error;
}
/* END */

291
thirdparty/freetype/src/base/md5.c vendored Normal file
View File

@@ -0,0 +1,291 @@
/*
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
* MD5 Message-Digest Algorithm (RFC 1321).
*
* Homepage:
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
*
* Author:
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
*
* This software was written by Alexander Peslyak in 2001. No copyright is
* claimed, and the software is hereby placed in the public domain.
* In case this attempt to disclaim copyright and place the software in the
* public domain is deemed null and void, then the software is
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
* general public under the following terms:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted.
*
* There's ABSOLUTELY NO WARRANTY, express or implied.
*
* (This is a heavily cut-down "BSD license".)
*
* This differs from Colin Plumb's older public domain implementation in that
* no exactly 32-bit integer data type is required (any 32-bit or wider
* unsigned integer data type will do), there's no compile-time endianness
* configuration, and the function prototypes match OpenSSL's. No code from
* Colin Plumb's implementation has been reused; this comment merely compares
* the properties of the two independent implementations.
*
* The primary goals of this implementation are portability and ease of use.
* It is meant to be fast, but not as fast as possible. Some known
* optimizations are not included to reduce source code size and avoid
* compile-time configuration.
*/
#ifndef HAVE_OPENSSL
#include <string.h>
#include "md5.h"
/*
* The basic MD5 functions.
*
* F and G are optimized compared to their RFC 1321 definitions for
* architectures that lack an AND-NOT instruction, just like in Colin Plumb's
* implementation.
*/
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
#define H(x, y, z) (((x) ^ (y)) ^ (z))
#define H2(x, y, z) ((x) ^ ((y) ^ (z)))
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
/*
* The MD5 transformation for all four rounds.
*/
#define STEP(f, a, b, c, d, x, t, s) \
(a) += f((b), (c), (d)) + (x) + (t); \
(a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
(a) += (b);
/*
* SET reads 4 input bytes in little-endian byte order and stores them in a
* properly aligned word in host byte order.
*
* The check for little-endian architectures that tolerate unaligned memory
* accesses is just an optimization. Nothing will break if it fails to detect
* a suitable architecture.
*
* Unfortunately, this optimization may be a C strict aliasing rules violation
* if the caller's data buffer has effective type that cannot be aliased by
* MD5_u32plus. In practice, this problem may occur if these MD5 routines are
* inlined into a calling function, or with future and dangerously advanced
* link-time optimizations. For the time being, keeping these MD5 routines in
* their own translation unit avoids the problem.
*/
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
#define SET(n) \
(*(MD5_u32plus *)&ptr[(n) * 4])
#define GET(n) \
SET(n)
#else
#define SET(n) \
(ctx->block[(n)] = \
(MD5_u32plus)ptr[(n) * 4] | \
((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
#define GET(n) \
(ctx->block[(n)])
#endif
/*
* This processes one or more 64-byte data blocks, but does NOT update the bit
* counters. There are no alignment requirements.
*/
static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
{
const unsigned char *ptr;
MD5_u32plus a, b, c, d;
MD5_u32plus saved_a, saved_b, saved_c, saved_d;
ptr = (const unsigned char *)data;
a = ctx->a;
b = ctx->b;
c = ctx->c;
d = ctx->d;
do {
saved_a = a;
saved_b = b;
saved_c = c;
saved_d = d;
/* Round 1 */
STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
/* Round 2 */
STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
/* Round 3 */
STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
/* Round 4 */
STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
a += saved_a;
b += saved_b;
c += saved_c;
d += saved_d;
ptr += 64;
} while (size -= 64);
ctx->a = a;
ctx->b = b;
ctx->c = c;
ctx->d = d;
return ptr;
}
void MD5_Init(MD5_CTX *ctx)
{
ctx->a = 0x67452301;
ctx->b = 0xefcdab89;
ctx->c = 0x98badcfe;
ctx->d = 0x10325476;
ctx->lo = 0;
ctx->hi = 0;
}
void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
{
MD5_u32plus saved_lo;
unsigned long used, available;
saved_lo = ctx->lo;
if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
ctx->hi++;
ctx->hi += size >> 29;
used = saved_lo & 0x3f;
if (used) {
available = 64 - used;
if (size < available) {
memcpy(&ctx->buffer[used], data, size);
return;
}
memcpy(&ctx->buffer[used], data, available);
data = (const unsigned char *)data + available;
size -= available;
body(ctx, ctx->buffer, 64);
}
if (size >= 64) {
data = body(ctx, data, size & ~(unsigned long)0x3f);
size &= 0x3f;
}
memcpy(ctx->buffer, data, size);
}
#define OUT(dst, src) \
(dst)[0] = (unsigned char)(src); \
(dst)[1] = (unsigned char)((src) >> 8); \
(dst)[2] = (unsigned char)((src) >> 16); \
(dst)[3] = (unsigned char)((src) >> 24);
void MD5_Final(unsigned char *result, MD5_CTX *ctx)
{
unsigned long used, available;
used = ctx->lo & 0x3f;
ctx->buffer[used++] = 0x80;
available = 64 - used;
if (available < 8) {
memset(&ctx->buffer[used], 0, available);
body(ctx, ctx->buffer, 64);
used = 0;
available = 64;
}
memset(&ctx->buffer[used], 0, available - 8);
ctx->lo <<= 3;
OUT(&ctx->buffer[56], ctx->lo)
OUT(&ctx->buffer[60], ctx->hi)
body(ctx, ctx->buffer, 64);
OUT(&result[0], ctx->a)
OUT(&result[4], ctx->b)
OUT(&result[8], ctx->c)
OUT(&result[12], ctx->d)
memset(ctx, 0, sizeof(*ctx));
}
#endif

45
thirdparty/freetype/src/base/md5.h vendored Normal file
View File

@@ -0,0 +1,45 @@
/*
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
* MD5 Message-Digest Algorithm (RFC 1321).
*
* Homepage:
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
*
* Author:
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
*
* This software was written by Alexander Peslyak in 2001. No copyright is
* claimed, and the software is hereby placed in the public domain.
* In case this attempt to disclaim copyright and place the software in the
* public domain is deemed null and void, then the software is
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
* general public under the following terms:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted.
*
* There's ABSOLUTELY NO WARRANTY, express or implied.
*
* See md5.c for more information.
*/
#ifdef HAVE_OPENSSL
#include <openssl/md5.h>
#elif !defined(_MD5_H)
#define _MD5_H
/* Any 32-bit or wider unsigned integer data type will do */
typedef unsigned int MD5_u32plus;
typedef struct {
MD5_u32plus lo, hi;
MD5_u32plus a, b, c, d;
unsigned char buffer[64];
MD5_u32plus block[16];
} MD5_CTX;
extern void MD5_Init(MD5_CTX *ctx);
extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size);
extern void MD5_Final(unsigned char *result, MD5_CTX *ctx);
#endif

34
thirdparty/freetype/src/bdf/bdf.c vendored Normal file
View File

@@ -0,0 +1,34 @@
/* bdf.c
FreeType font driver for bdf files
Copyright (C) 2001, 2002 by
Francesco Zappa Nardelli
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#define FT_MAKE_OPTION_SINGLE_OBJECT
#include "bdflib.c"
#include "bdfdrivr.c"
/* END */

253
thirdparty/freetype/src/bdf/bdf.h vendored Normal file
View File

@@ -0,0 +1,253 @@
/*
* Copyright 2000 Computing Research Labs, New Mexico State University
* Copyright 2001-2004, 2011 Francesco Zappa Nardelli
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
* OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef BDF_H_
#define BDF_H_
/*
* Based on bdf.h,v 1.16 2000/03/16 20:08:51 mleisher
*/
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/ftstream.h>
#include <freetype/internal/fthash.h>
FT_BEGIN_HEADER
/* Imported from bdfP.h */
#define _bdf_glyph_modified( map, e ) \
( (map)[(e) >> 5] & ( 1UL << ( (e) & 31 ) ) )
#define _bdf_set_glyph_modified( map, e ) \
( (map)[(e) >> 5] |= ( 1UL << ( (e) & 31 ) ) )
#define _bdf_clear_glyph_modified( map, e ) \
( (map)[(e) >> 5] &= ~( 1UL << ( (e) & 31 ) ) )
/* end of bdfP.h */
/**************************************************************************
*
* BDF font options macros and types.
*
*/
#define BDF_CORRECT_METRICS 0x01 /* Correct invalid metrics when loading. */
#define BDF_KEEP_COMMENTS 0x02 /* Preserve the font comments. */
#define BDF_KEEP_UNENCODED 0x04 /* Keep the unencoded glyphs. */
#define BDF_PROPORTIONAL 0x08 /* Font has proportional spacing. */
#define BDF_MONOWIDTH 0x10 /* Font has mono width. */
#define BDF_CHARCELL 0x20 /* Font has charcell spacing. */
#define BDF_ALL_SPACING ( BDF_PROPORTIONAL | \
BDF_MONOWIDTH | \
BDF_CHARCELL )
#define BDF_DEFAULT_LOAD_OPTIONS ( BDF_CORRECT_METRICS | \
BDF_KEEP_COMMENTS | \
BDF_KEEP_UNENCODED | \
BDF_PROPORTIONAL )
typedef struct bdf_options_t_
{
int correct_metrics;
int keep_unencoded;
int keep_comments;
int font_spacing;
} bdf_options_t;
/* Callback function type for unknown configuration options. */
typedef int
(*bdf_options_callback_t)( bdf_options_t* opts,
char** params,
unsigned long nparams,
void* client_data );
/**************************************************************************
*
* BDF font property macros and types.
*
*/
#define BDF_ATOM 1
#define BDF_INTEGER 2
#define BDF_CARDINAL 3
/* This structure represents a particular property of a font. */
/* There are a set of defaults and each font has their own. */
typedef struct bdf_property_t_
{
const char* name; /* Name of the property. */
int format; /* Format of the property. */
int builtin; /* A builtin property. */
union
{
char* atom;
long l;
unsigned long ul;
} value; /* Value of the property. */
} bdf_property_t;
/**************************************************************************
*
* BDF font metric and glyph types.
*
*/
typedef struct bdf_bbx_t_
{
unsigned short width;
unsigned short height;
short x_offset;
short y_offset;
short ascent;
short descent;
} bdf_bbx_t;
typedef struct bdf_glyph_t_
{
char* name; /* Glyph name. */
unsigned long encoding; /* Glyph encoding. */
unsigned short swidth; /* Scalable width. */
unsigned short dwidth; /* Device width. */
bdf_bbx_t bbx; /* Glyph bounding box. */
unsigned char* bitmap; /* Glyph bitmap. */
unsigned long bpr; /* Number of bytes used per row. */
unsigned short bytes; /* Number of bytes used for the bitmap. */
} bdf_glyph_t;
typedef struct bdf_font_t_
{
char* name; /* Name of the font. */
bdf_bbx_t bbx; /* Font bounding box. */
unsigned long point_size; /* Point size of the font. */
unsigned long resolution_x; /* Font horizontal resolution. */
unsigned long resolution_y; /* Font vertical resolution. */
int spacing; /* Font spacing value. */
unsigned short monowidth; /* Logical width for monowidth font. */
unsigned long default_char; /* Encoding of the default glyph. */
long font_ascent; /* Font ascent. */
long font_descent; /* Font descent. */
unsigned long glyphs_size; /* Glyph structures allocated. */
unsigned long glyphs_used; /* Glyph structures used. */
bdf_glyph_t* glyphs; /* Glyphs themselves. */
unsigned long unencoded_size; /* Unencoded glyph struct. allocated. */
unsigned long unencoded_used; /* Unencoded glyph struct. used. */
bdf_glyph_t* unencoded; /* Unencoded glyphs themselves. */
unsigned long props_size; /* Font properties allocated. */
unsigned long props_used; /* Font properties used. */
bdf_property_t* props; /* Font properties themselves. */
char* comments; /* Font comments. */
unsigned long comments_len; /* Length of comment string. */
void* internal; /* Internal data for the font. */
unsigned short bpp; /* Bits per pixel. */
FT_Memory memory;
bdf_property_t* user_props;
unsigned long nuser_props;
FT_HashRec proptbl;
} bdf_font_t;
/**************************************************************************
*
* Types for load/save callbacks.
*
*/
/* Error codes. */
#define BDF_MISSING_START -1
#define BDF_MISSING_FONTNAME -2
#define BDF_MISSING_SIZE -3
#define BDF_MISSING_CHARS -4
#define BDF_MISSING_STARTCHAR -5
#define BDF_MISSING_ENCODING -6
#define BDF_MISSING_BBX -7
#define BDF_OUT_OF_MEMORY -20
#define BDF_INVALID_LINE -100
/**************************************************************************
*
* BDF font API.
*
*/
FT_LOCAL( FT_Error )
bdf_load_font( FT_Stream stream,
FT_Memory memory,
bdf_options_t* opts,
bdf_font_t* *font );
FT_LOCAL( void )
bdf_free_font( bdf_font_t* font );
FT_LOCAL( bdf_property_t * )
bdf_get_font_property( bdf_font_t* font,
const char* name );
FT_END_HEADER
#endif /* BDF_H_ */
/* END */

1013
thirdparty/freetype/src/bdf/bdfdrivr.c vendored Normal file

File diff suppressed because it is too large Load Diff

72
thirdparty/freetype/src/bdf/bdfdrivr.h vendored Normal file
View File

@@ -0,0 +1,72 @@
/* bdfdrivr.h
FreeType font driver for bdf fonts
Copyright (C) 2001, 2002, 2003, 2004 by
Francesco Zappa Nardelli
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef BDFDRIVR_H_
#define BDFDRIVR_H_
#include <freetype/internal/ftdrv.h>
#include "bdf.h"
FT_BEGIN_HEADER
typedef struct BDF_encoding_el_
{
FT_ULong enc;
FT_UShort glyph;
} BDF_encoding_el;
typedef struct BDF_FaceRec_
{
FT_FaceRec root;
char* charset_encoding;
char* charset_registry;
bdf_font_t* bdffont;
BDF_encoding_el* en_table;
FT_UInt default_glyph;
} BDF_FaceRec, *BDF_Face;
FT_EXPORT_VAR( const FT_Driver_ClassRec ) bdf_driver_class;
FT_END_HEADER
#endif /* BDFDRIVR_H_ */
/* END */

45
thirdparty/freetype/src/bdf/bdferror.h vendored Normal file
View File

@@ -0,0 +1,45 @@
/*
* Copyright 2001, 2002, 2012 Francesco Zappa Nardelli
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
* OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**************************************************************************
*
* This file is used to define the BDF error enumeration constants.
*
*/
#ifndef BDFERROR_H_
#define BDFERROR_H_
#include <freetype/ftmoderr.h>
#undef FTERRORS_H_
#undef FT_ERR_PREFIX
#define FT_ERR_PREFIX BDF_Err_
#define FT_ERR_BASE FT_Mod_Err_BDF
#include <freetype/fterrors.h>
#endif /* BDFERROR_H_ */
/* END */

2378
thirdparty/freetype/src/bdf/bdflib.c vendored Normal file

File diff suppressed because it is too large Load Diff

535
thirdparty/freetype/src/bzip2/ftbzip2.c vendored Normal file
View File

@@ -0,0 +1,535 @@
/****************************************************************************
*
* ftbzip2.c
*
* FreeType support for .bz2 compressed files.
*
* This optional component relies on libbz2. It should mainly be used to
* parse compressed PCF fonts, as found with many X11 server
* distributions.
*
* Copyright (C) 2010-2024 by
* Joel Klinghed.
*
* based on `src/gzip/ftgzip.c'
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/internal/ftmemory.h>
#include <freetype/internal/ftstream.h>
#include <freetype/internal/ftdebug.h>
#include <freetype/ftbzip2.h>
#include FT_CONFIG_STANDARD_LIBRARY_H
#include <freetype/ftmoderr.h>
#undef FTERRORS_H_
#undef FT_ERR_PREFIX
#define FT_ERR_PREFIX Bzip2_Err_
#define FT_ERR_BASE FT_Mod_Err_Bzip2
#include <freetype/fterrors.h>
#ifdef FT_CONFIG_OPTION_USE_BZIP2
#define BZ_NO_STDIO /* Do not need FILE */
#include <bzlib.h>
/***************************************************************************/
/***************************************************************************/
/***** *****/
/***** B Z I P 2 M E M O R Y M A N A G E M E N T *****/
/***** *****/
/***************************************************************************/
/***************************************************************************/
/* it is better to use FreeType memory routines instead of raw
'malloc/free' */
typedef void* (*alloc_func)( void*, int, int );
typedef void (*free_func) ( void*, void* );
static void*
ft_bzip2_alloc( void* memory_, /* FT_Memory */
int items,
int size )
{
FT_Memory memory = (FT_Memory)memory_;
FT_ULong sz = (FT_ULong)size * (FT_ULong)items;
FT_Error error;
FT_Pointer p = NULL;
FT_MEM_QALLOC( p, sz );
return p;
}
static void
ft_bzip2_free( void* memory_, /* FT_Memory */
void* address )
{
FT_Memory memory = (FT_Memory)memory_;
FT_MEM_FREE( address );
}
/***************************************************************************/
/***************************************************************************/
/***** *****/
/***** B Z I P 2 F I L E D E S C R I P T O R *****/
/***** *****/
/***************************************************************************/
/***************************************************************************/
#define FT_BZIP2_BUFFER_SIZE 4096
typedef struct FT_BZip2FileRec_
{
FT_Stream source; /* parent/source stream */
FT_Stream stream; /* embedding stream */
FT_Memory memory; /* memory allocator */
bz_stream bzstream; /* bzlib input stream */
FT_Byte input[FT_BZIP2_BUFFER_SIZE]; /* input read buffer */
FT_Byte buffer[FT_BZIP2_BUFFER_SIZE]; /* output buffer */
FT_ULong pos; /* position in output */
FT_Byte* cursor;
FT_Byte* limit;
FT_Bool reset; /* reset before next read */
} FT_BZip2FileRec, *FT_BZip2File;
/* check and skip .bz2 header - we don't support `transparent' compression */
static FT_Error
ft_bzip2_check_header( FT_Stream stream )
{
FT_Error error = FT_Err_Ok;
FT_Byte head[4];
if ( FT_STREAM_SEEK( 0 ) ||
FT_STREAM_READ( head, 4 ) )
goto Exit;
/* head[0] && head[1] are the magic numbers; */
/* head[2] is the version, and head[3] the blocksize */
if ( head[0] != 0x42 ||
head[1] != 0x5A ||
head[2] != 0x68 ) /* only support bzip2 (huffman) */
{
error = FT_THROW( Invalid_File_Format );
goto Exit;
}
Exit:
return error;
}
static FT_Error
ft_bzip2_file_init( FT_BZip2File zip,
FT_Stream stream,
FT_Stream source )
{
bz_stream* bzstream = &zip->bzstream;
FT_Error error = FT_Err_Ok;
zip->stream = stream;
zip->source = source;
zip->memory = stream->memory;
zip->limit = zip->buffer + FT_BZIP2_BUFFER_SIZE;
zip->cursor = zip->limit;
zip->pos = 0;
zip->reset = 0;
/* check .bz2 header */
{
stream = source;
error = ft_bzip2_check_header( stream );
if ( error )
goto Exit;
if ( FT_STREAM_SEEK( 0 ) )
goto Exit;
}
/* initialize bzlib */
bzstream->bzalloc = ft_bzip2_alloc;
bzstream->bzfree = ft_bzip2_free;
bzstream->opaque = zip->memory;
bzstream->avail_in = 0;
bzstream->next_in = (char*)zip->buffer;
if ( BZ2_bzDecompressInit( bzstream, 0, 0 ) != BZ_OK ||
!bzstream->next_in )
error = FT_THROW( Invalid_File_Format );
Exit:
return error;
}
static void
ft_bzip2_file_done( FT_BZip2File zip )
{
bz_stream* bzstream = &zip->bzstream;
BZ2_bzDecompressEnd( bzstream );
/* clear the rest */
bzstream->bzalloc = NULL;
bzstream->bzfree = NULL;
bzstream->opaque = NULL;
bzstream->next_in = NULL;
bzstream->next_out = NULL;
bzstream->avail_in = 0;
bzstream->avail_out = 0;
zip->memory = NULL;
zip->source = NULL;
zip->stream = NULL;
}
static FT_Error
ft_bzip2_file_reset( FT_BZip2File zip )
{
FT_Stream stream = zip->source;
FT_Error error;
if ( !FT_STREAM_SEEK( 0 ) )
{
bz_stream* bzstream = &zip->bzstream;
BZ2_bzDecompressEnd( bzstream );
bzstream->avail_in = 0;
bzstream->next_in = (char*)zip->input;
bzstream->avail_out = 0;
bzstream->next_out = (char*)zip->buffer;
zip->limit = zip->buffer + FT_BZIP2_BUFFER_SIZE;
zip->cursor = zip->limit;
zip->pos = 0;
zip->reset = 0;
BZ2_bzDecompressInit( bzstream, 0, 0 );
}
return error;
}
static FT_Error
ft_bzip2_file_fill_input( FT_BZip2File zip )
{
bz_stream* bzstream = &zip->bzstream;
FT_Stream stream = zip->source;
FT_ULong size;
if ( stream->read )
{
size = stream->read( stream, stream->pos, zip->input,
FT_BZIP2_BUFFER_SIZE );
if ( size == 0 )
{
zip->limit = zip->cursor;
return FT_THROW( Invalid_Stream_Operation );
}
}
else
{
size = stream->size - stream->pos;
if ( size > FT_BZIP2_BUFFER_SIZE )
size = FT_BZIP2_BUFFER_SIZE;
if ( size == 0 )
{
zip->limit = zip->cursor;
return FT_THROW( Invalid_Stream_Operation );
}
FT_MEM_COPY( zip->input, stream->base + stream->pos, size );
}
stream->pos += size;
bzstream->next_in = (char*)zip->input;
bzstream->avail_in = size;
return FT_Err_Ok;
}
static FT_Error
ft_bzip2_file_fill_output( FT_BZip2File zip )
{
bz_stream* bzstream = &zip->bzstream;
FT_Error error = FT_Err_Ok;
zip->cursor = zip->buffer;
bzstream->next_out = (char*)zip->cursor;
bzstream->avail_out = FT_BZIP2_BUFFER_SIZE;
while ( bzstream->avail_out > 0 )
{
int err;
if ( bzstream->avail_in == 0 )
{
error = ft_bzip2_file_fill_input( zip );
if ( error )
break;
}
err = BZ2_bzDecompress( bzstream );
if ( err != BZ_OK )
{
zip->reset = 1;
if ( err == BZ_STREAM_END )
{
zip->limit = (FT_Byte*)bzstream->next_out;
if ( zip->limit == zip->cursor )
error = FT_THROW( Invalid_Stream_Operation );
break;
}
else
{
zip->limit = zip->cursor;
error = FT_THROW( Invalid_Stream_Operation );
break;
}
}
}
return error;
}
/* fill output buffer; `count' must be <= FT_BZIP2_BUFFER_SIZE */
static FT_Error
ft_bzip2_file_skip_output( FT_BZip2File zip,
FT_ULong count )
{
FT_Error error = FT_Err_Ok;
for (;;)
{
FT_ULong delta = (FT_ULong)( zip->limit - zip->cursor );
if ( delta >= count )
delta = count;
zip->cursor += delta;
zip->pos += delta;
count -= delta;
if ( count == 0 )
break;
error = ft_bzip2_file_fill_output( zip );
if ( error )
break;
}
return error;
}
static FT_ULong
ft_bzip2_file_io( FT_BZip2File zip,
FT_ULong pos,
FT_Byte* buffer,
FT_ULong count )
{
FT_ULong result = 0;
FT_Error error;
/* Reset inflate stream if seeking backwards or bzip reported an error. */
/* Yes, that is not too efficient, but it saves memory :-) */
if ( pos < zip->pos || zip->reset )
{
error = ft_bzip2_file_reset( zip );
if ( error )
goto Exit;
}
/* skip unwanted bytes */
if ( pos > zip->pos )
{
error = ft_bzip2_file_skip_output( zip, (FT_ULong)( pos - zip->pos ) );
if ( error )
goto Exit;
}
if ( count == 0 )
goto Exit;
/* now read the data */
for (;;)
{
FT_ULong delta;
delta = (FT_ULong)( zip->limit - zip->cursor );
if ( delta >= count )
delta = count;
FT_MEM_COPY( buffer, zip->cursor, delta );
buffer += delta;
result += delta;
zip->cursor += delta;
zip->pos += delta;
count -= delta;
if ( count == 0 )
break;
error = ft_bzip2_file_fill_output( zip );
if ( error )
break;
}
Exit:
return result;
}
/***************************************************************************/
/***************************************************************************/
/***** *****/
/***** B Z E M B E D D I N G S T R E A M *****/
/***** *****/
/***************************************************************************/
/***************************************************************************/
static void
ft_bzip2_stream_close( FT_Stream stream )
{
FT_BZip2File zip = (FT_BZip2File)stream->descriptor.pointer;
FT_Memory memory = stream->memory;
if ( zip )
{
/* finalize bzip file descriptor */
ft_bzip2_file_done( zip );
FT_FREE( zip );
stream->descriptor.pointer = NULL;
}
}
static unsigned long
ft_bzip2_stream_io( FT_Stream stream,
unsigned long offset,
unsigned char* buffer,
unsigned long count )
{
FT_BZip2File zip = (FT_BZip2File)stream->descriptor.pointer;
return ft_bzip2_file_io( zip, offset, buffer, count );
}
FT_EXPORT_DEF( FT_Error )
FT_Stream_OpenBzip2( FT_Stream stream,
FT_Stream source )
{
FT_Error error;
FT_Memory memory;
FT_BZip2File zip = NULL;
if ( !stream || !source )
{
error = FT_THROW( Invalid_Stream_Handle );
goto Exit;
}
memory = source->memory;
/*
* check the header right now; this prevents allocating unnecessary
* objects when we don't need them
*/
error = ft_bzip2_check_header( source );
if ( error )
goto Exit;
FT_ZERO( stream );
stream->memory = memory;
if ( !FT_QNEW( zip ) )
{
error = ft_bzip2_file_init( zip, stream, source );
if ( error )
{
FT_FREE( zip );
goto Exit;
}
stream->descriptor.pointer = zip;
}
stream->size = 0x7FFFFFFFL; /* don't know the real size! */
stream->pos = 0;
stream->base = NULL;
stream->read = ft_bzip2_stream_io;
stream->close = ft_bzip2_stream_close;
Exit:
return error;
}
#else /* !FT_CONFIG_OPTION_USE_BZIP2 */
FT_EXPORT_DEF( FT_Error )
FT_Stream_OpenBzip2( FT_Stream stream,
FT_Stream source )
{
FT_UNUSED( stream );
FT_UNUSED( source );
return FT_THROW( Unimplemented_Feature );
}
#endif /* !FT_CONFIG_OPTION_USE_BZIP2 */
/* END */

31
thirdparty/freetype/src/cache/ftcache.c vendored Normal file
View File

@@ -0,0 +1,31 @@
/****************************************************************************
*
* ftcache.c
*
* The FreeType Caching sub-system (body only).
*
* Copyright (C) 2000-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#define FT_MAKE_OPTION_SINGLE_OBJECT
#include "ftcbasic.c"
#include "ftccache.c"
#include "ftccmap.c"
#include "ftcglyph.c"
#include "ftcimage.c"
#include "ftcmanag.c"
#include "ftcmru.c"
#include "ftcsbits.c"
/* END */

598
thirdparty/freetype/src/cache/ftcbasic.c vendored Normal file
View File

@@ -0,0 +1,598 @@
/****************************************************************************
*
* ftcbasic.c
*
* The FreeType basic cache interface (body).
*
* Copyright (C) 2003-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/ftdebug.h>
#include <freetype/ftcache.h>
#include "ftcglyph.h"
#include "ftcimage.h"
#include "ftcsbits.h"
#include "ftccback.h"
#include "ftcerror.h"
#undef FT_COMPONENT
#define FT_COMPONENT cache
/*
* Basic Families
*
*/
typedef struct FTC_BasicAttrRec_
{
FTC_ScalerRec scaler;
FT_Int32 load_flags;
} FTC_BasicAttrRec, *FTC_BasicAttrs;
#define FTC_BASIC_ATTR_COMPARE( a, b ) \
FT_BOOL( FTC_SCALER_COMPARE( &(a)->scaler, &(b)->scaler ) && \
(a)->load_flags == (b)->load_flags )
#define FTC_BASIC_ATTR_HASH( a ) \
( FTC_SCALER_HASH( &(a)->scaler ) + \
(FT_Offset)( 31 * (a)->load_flags ) )
typedef struct FTC_BasicQueryRec_
{
FTC_GQueryRec gquery;
FTC_BasicAttrRec attrs;
} FTC_BasicQueryRec, *FTC_BasicQuery;
typedef struct FTC_BasicFamilyRec_
{
FTC_FamilyRec family;
FTC_BasicAttrRec attrs;
} FTC_BasicFamilyRec, *FTC_BasicFamily;
FT_CALLBACK_DEF( FT_Bool )
ftc_basic_family_compare( FTC_MruNode ftcfamily,
FT_Pointer ftcquery )
{
FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
FTC_BasicQuery query = (FTC_BasicQuery)ftcquery;
return FTC_BASIC_ATTR_COMPARE( &family->attrs, &query->attrs );
}
FT_CALLBACK_DEF( FT_Error )
ftc_basic_family_init( FTC_MruNode ftcfamily,
FT_Pointer ftcquery,
FT_Pointer ftccache )
{
FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
FTC_BasicQuery query = (FTC_BasicQuery)ftcquery;
FTC_Cache cache = (FTC_Cache)ftccache;
FTC_Family_Init( FTC_FAMILY( family ), cache );
family->attrs = query->attrs;
return 0;
}
FT_CALLBACK_DEF( FT_UInt )
ftc_basic_family_get_count( FTC_Family ftcfamily,
FTC_Manager manager )
{
FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
FT_Error error;
FT_Face face;
FT_UInt result = 0;
error = FTC_Manager_LookupFace( manager, family->attrs.scaler.face_id,
&face );
if ( error || !face )
return result;
#ifdef FT_DEBUG_LEVEL_TRACE
if ( (FT_ULong)face->num_glyphs > FT_UINT_MAX || 0 > face->num_glyphs )
{
FT_TRACE1(( "ftc_basic_family_get_count:"
" the number of glyphs in this face is %ld,\n",
face->num_glyphs ));
FT_TRACE1(( " "
" which is too much and thus truncated\n" ));
}
#endif
result = (FT_UInt)face->num_glyphs;
return result;
}
FT_CALLBACK_DEF( FT_Error )
ftc_basic_family_load_bitmap( FTC_Family ftcfamily,
FT_UInt gindex,
FTC_Manager manager,
FT_Face *aface )
{
FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
FT_Error error;
FT_Size size;
error = FTC_Manager_LookupSize( manager, &family->attrs.scaler, &size );
if ( !error )
{
FT_Face face = size->face;
error = FT_Load_Glyph( face,
gindex,
family->attrs.load_flags | FT_LOAD_RENDER );
if ( !error )
*aface = face;
}
return error;
}
FT_CALLBACK_DEF( FT_Error )
ftc_basic_family_load_glyph( FTC_Family ftcfamily,
FT_UInt gindex,
FTC_Cache cache,
FT_Glyph *aglyph )
{
FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;
FT_Error error;
FTC_Scaler scaler = &family->attrs.scaler;
FT_Face face;
FT_Size size;
/* we will now load the glyph image */
error = FTC_Manager_LookupSize( cache->manager,
scaler,
&size );
if ( !error )
{
face = size->face;
error = FT_Load_Glyph( face, gindex, family->attrs.load_flags );
if ( !error )
{
if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP ||
face->glyph->format == FT_GLYPH_FORMAT_OUTLINE ||
face->glyph->format == FT_GLYPH_FORMAT_SVG )
{
/* ok, copy it */
FT_Glyph glyph;
error = FT_Get_Glyph( face->glyph, &glyph );
if ( !error )
{
*aglyph = glyph;
goto Exit;
}
}
else
error = FT_THROW( Invalid_Argument );
}
}
Exit:
return error;
}
FT_CALLBACK_DEF( FT_Bool )
ftc_basic_gnode_compare_faceid( FTC_Node ftcgnode,
FT_Pointer ftcface_id,
FTC_Cache cache,
FT_Bool* list_changed )
{
FTC_GNode gnode = (FTC_GNode)ftcgnode;
FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
FTC_BasicFamily family = (FTC_BasicFamily)gnode->family;
FT_Bool result;
if ( list_changed )
*list_changed = FALSE;
result = FT_BOOL( family->attrs.scaler.face_id == face_id );
if ( result )
{
/* we must call this function to avoid this node from appearing
* in later lookups with the same face_id!
*/
FTC_GNode_UnselectFamily( gnode, cache );
}
return result;
}
/*
*
* basic image cache
*
*/
static
const FTC_IFamilyClassRec ftc_basic_image_family_class =
{
{
sizeof ( FTC_BasicFamilyRec ),
ftc_basic_family_compare, /* FTC_MruNode_CompareFunc node_compare */
ftc_basic_family_init, /* FTC_MruNode_InitFunc node_init */
NULL /* FTC_MruNode_DoneFunc node_done */
},
ftc_basic_family_load_glyph /* FTC_IFamily_LoadGlyphFunc family_load_glyph */
};
static
const FTC_GCacheClassRec ftc_basic_image_cache_class =
{
{
ftc_inode_new, /* FTC_Node_NewFunc node_new */
ftc_inode_weight, /* FTC_Node_WeightFunc node_weight */
ftc_gnode_compare, /* FTC_Node_CompareFunc node_compare */
ftc_basic_gnode_compare_faceid, /* FTC_Node_CompareFunc node_remove_faceid */
ftc_inode_free, /* FTC_Node_FreeFunc node_free */
sizeof ( FTC_GCacheRec ),
ftc_gcache_init, /* FTC_Cache_InitFunc cache_init */
ftc_gcache_done /* FTC_Cache_DoneFunc cache_done */
},
(FTC_MruListClass)&ftc_basic_image_family_class
};
/* documentation is in ftcache.h */
FT_EXPORT_DEF( FT_Error )
FTC_ImageCache_New( FTC_Manager manager,
FTC_ImageCache *acache )
{
return FTC_GCache_New( manager, &ftc_basic_image_cache_class,
(FTC_GCache*)acache );
}
/* documentation is in ftcache.h */
FT_EXPORT_DEF( FT_Error )
FTC_ImageCache_Lookup( FTC_ImageCache cache,
FTC_ImageType type,
FT_UInt gindex,
FT_Glyph *aglyph,
FTC_Node *anode )
{
FT_Error error;
FTC_BasicQueryRec query;
FTC_Node node = NULL; /* make compiler happy */
FT_Offset hash;
/* other argument checks delayed to `FTC_Cache_Lookup' */
if ( !aglyph )
return FT_THROW( Invalid_Argument );
*aglyph = NULL;
if ( anode )
*anode = NULL;
query.attrs.scaler.face_id = type->face_id;
query.attrs.scaler.width = type->width;
query.attrs.scaler.height = type->height;
query.attrs.load_flags = type->flags;
query.attrs.scaler.pixel = 1;
query.attrs.scaler.x_res = 0; /* make compilers happy */
query.attrs.scaler.y_res = 0;
hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;
#ifdef FTC_INLINE /* inlining is about 50% faster! */
FTC_GCACHE_LOOKUP_CMP( cache,
ftc_basic_family_compare,
ftc_gnode_compare,
hash, gindex,
&query,
node,
error );
#else
error = FTC_GCache_Lookup( FTC_GCACHE( cache ),
hash, gindex,
FTC_GQUERY( &query ),
&node );
#endif
if ( !error )
{
*aglyph = FTC_INODE( node )->glyph;
if ( anode )
{
*anode = node;
node->ref_count++;
}
}
return error;
}
/* documentation is in ftcache.h */
FT_EXPORT_DEF( FT_Error )
FTC_ImageCache_LookupScaler( FTC_ImageCache cache,
FTC_Scaler scaler,
FT_ULong load_flags,
FT_UInt gindex,
FT_Glyph *aglyph,
FTC_Node *anode )
{
FT_Error error;
FTC_BasicQueryRec query;
FTC_Node node = NULL; /* make compiler happy */
FT_Offset hash;
/* other argument checks delayed to `FTC_Cache_Lookup' */
if ( !aglyph || !scaler )
return FT_THROW( Invalid_Argument );
*aglyph = NULL;
if ( anode )
*anode = NULL;
/*
* Internal `FTC_BasicAttr->load_flags' is of type `FT_Int32',
* but public `FT_Face->face_flags' is of type `FT_Long'.
*
* On long > int systems, higher bits of load_flags cannot be handled.
*/
#if FT_ULONG_MAX > 0xFFFFFFFFUL
if ( load_flags > 0xFFFFFFFFUL )
FT_TRACE1(( "FTC_ImageCache_LookupScaler:"
" higher bits in load_flags 0x%lx are dropped\n",
load_flags & ~0xFFFFFFFFUL ));
#endif
query.attrs.scaler = scaler[0];
query.attrs.load_flags = (FT_Int32)load_flags;
hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;
FTC_GCACHE_LOOKUP_CMP( cache,
ftc_basic_family_compare,
ftc_gnode_compare,
hash, gindex,
&query,
node,
error );
if ( !error )
{
*aglyph = FTC_INODE( node )->glyph;
if ( anode )
{
*anode = node;
node->ref_count++;
}
}
return error;
}
/*
*
* basic small bitmap cache
*
*/
static
const FTC_SFamilyClassRec ftc_basic_sbit_family_class =
{
{
sizeof ( FTC_BasicFamilyRec ),
ftc_basic_family_compare, /* FTC_MruNode_CompareFunc node_compare */
ftc_basic_family_init, /* FTC_MruNode_InitFunc node_init */
NULL /* FTC_MruNode_DoneFunc node_done */
},
ftc_basic_family_get_count,
ftc_basic_family_load_bitmap
};
static
const FTC_GCacheClassRec ftc_basic_sbit_cache_class =
{
{
ftc_snode_new, /* FTC_Node_NewFunc node_new */
ftc_snode_weight, /* FTC_Node_WeightFunc node_weight */
ftc_snode_compare, /* FTC_Node_CompareFunc node_compare */
ftc_basic_gnode_compare_faceid, /* FTC_Node_CompareFunc node_remove_faceid */
ftc_snode_free, /* FTC_Node_FreeFunc node_free */
sizeof ( FTC_GCacheRec ),
ftc_gcache_init, /* FTC_Cache_InitFunc cache_init */
ftc_gcache_done /* FTC_Cache_DoneFunc cache_done */
},
(FTC_MruListClass)&ftc_basic_sbit_family_class
};
/* documentation is in ftcache.h */
FT_EXPORT_DEF( FT_Error )
FTC_SBitCache_New( FTC_Manager manager,
FTC_SBitCache *acache )
{
return FTC_GCache_New( manager, &ftc_basic_sbit_cache_class,
(FTC_GCache*)acache );
}
/* documentation is in ftcache.h */
FT_EXPORT_DEF( FT_Error )
FTC_SBitCache_Lookup( FTC_SBitCache cache,
FTC_ImageType type,
FT_UInt gindex,
FTC_SBit *ansbit,
FTC_Node *anode )
{
FT_Error error;
FTC_BasicQueryRec query;
FTC_Node node = NULL; /* make compiler happy */
FT_Offset hash;
/* other argument checks delayed to `FTC_Cache_Lookup' */
if ( !ansbit )
return FT_THROW( Invalid_Argument );
*ansbit = NULL;
if ( anode )
*anode = NULL;
query.attrs.scaler.face_id = type->face_id;
query.attrs.scaler.width = type->width;
query.attrs.scaler.height = type->height;
query.attrs.load_flags = type->flags;
query.attrs.scaler.pixel = 1;
query.attrs.scaler.x_res = 0; /* make compilers happy */
query.attrs.scaler.y_res = 0;
/* beware, the hash must be the same for all glyph ranges! */
hash = FTC_BASIC_ATTR_HASH( &query.attrs ) +
gindex / FTC_SBIT_ITEMS_PER_NODE;
#ifdef FTC_INLINE /* inlining is about 50% faster! */
FTC_GCACHE_LOOKUP_CMP( cache,
ftc_basic_family_compare,
ftc_snode_compare,
hash, gindex,
&query,
node,
error );
#else
error = FTC_GCache_Lookup( FTC_GCACHE( cache ),
hash,
gindex,
FTC_GQUERY( &query ),
&node );
#endif
if ( error )
goto Exit;
*ansbit = FTC_SNODE( node )->sbits +
( gindex - FTC_GNODE( node )->gindex );
if ( anode )
{
*anode = node;
node->ref_count++;
}
Exit:
return error;
}
/* documentation is in ftcache.h */
FT_EXPORT_DEF( FT_Error )
FTC_SBitCache_LookupScaler( FTC_SBitCache cache,
FTC_Scaler scaler,
FT_ULong load_flags,
FT_UInt gindex,
FTC_SBit *ansbit,
FTC_Node *anode )
{
FT_Error error;
FTC_BasicQueryRec query;
FTC_Node node = NULL; /* make compiler happy */
FT_Offset hash;
/* other argument checks delayed to `FTC_Cache_Lookup' */
if ( !ansbit || !scaler )
return FT_THROW( Invalid_Argument );
*ansbit = NULL;
if ( anode )
*anode = NULL;
/*
* Internal `FTC_BasicAttr->load_flags' is of type `FT_Int32',
* but public `FT_Face->face_flags' is of type `FT_Long'.
*
* On long > int systems, higher bits of load_flags cannot be handled.
*/
#if FT_ULONG_MAX > 0xFFFFFFFFUL
if ( load_flags > 0xFFFFFFFFUL )
FT_TRACE1(( "FTC_ImageCache_LookupScaler:"
" higher bits in load_flags 0x%lx are dropped\n",
load_flags & ~0xFFFFFFFFUL ));
#endif
query.attrs.scaler = scaler[0];
query.attrs.load_flags = (FT_Int32)load_flags;
/* beware, the hash must be the same for all glyph ranges! */
hash = FTC_BASIC_ATTR_HASH( &query.attrs ) +
gindex / FTC_SBIT_ITEMS_PER_NODE;
FTC_GCACHE_LOOKUP_CMP( cache,
ftc_basic_family_compare,
ftc_snode_compare,
hash, gindex,
&query,
node,
error );
if ( error )
goto Exit;
*ansbit = FTC_SNODE( node )->sbits +
( gindex - FTC_GNODE( node )->gindex );
if ( anode )
{
*anode = node;
node->ref_count++;
}
Exit:
return error;
}
/* END */

584
thirdparty/freetype/src/cache/ftccache.c vendored Normal file
View File

@@ -0,0 +1,584 @@
/****************************************************************************
*
* ftccache.c
*
* The FreeType internal cache interface (body).
*
* Copyright (C) 2000-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include "ftcmanag.h"
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/ftdebug.h>
#include "ftccback.h"
#include "ftcerror.h"
#undef FT_COMPONENT
#define FT_COMPONENT cache
#define FTC_HASH_MAX_LOAD 2
#define FTC_HASH_MIN_LOAD 1
#define FTC_HASH_SUB_LOAD ( FTC_HASH_MAX_LOAD - FTC_HASH_MIN_LOAD )
/* this one _must_ be a power of 2! */
#define FTC_HASH_INITIAL_SIZE 8
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** CACHE NODE DEFINITIONS *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* add a new node to the head of the manager's circular MRU list */
static void
ftc_node_mru_link( FTC_Node node,
FTC_Manager manager )
{
void *nl = &manager->nodes_list;
FTC_MruNode_Prepend( (FTC_MruNode*)nl,
(FTC_MruNode)node );
manager->num_nodes++;
}
/* remove a node from the manager's MRU list */
static void
ftc_node_mru_unlink( FTC_Node node,
FTC_Manager manager )
{
void *nl = &manager->nodes_list;
FTC_MruNode_Remove( (FTC_MruNode*)nl,
(FTC_MruNode)node );
manager->num_nodes--;
}
#ifndef FTC_INLINE
/* move a node to the head of the manager's MRU list */
static void
ftc_node_mru_up( FTC_Node node,
FTC_Manager manager )
{
FTC_MruNode_Up( (FTC_MruNode*)&manager->nodes_list,
(FTC_MruNode)node );
}
/* get a top bucket for specified hash from cache,
* body for FTC_NODE_TOP_FOR_HASH( cache, hash )
*/
FT_LOCAL_DEF( FTC_Node* )
ftc_get_top_node_for_hash( FTC_Cache cache,
FT_Offset hash )
{
FT_Offset idx;
idx = hash & cache->mask;
if ( idx >= cache->p )
idx = hash & ( cache->mask >> 1 );
return cache->buckets + idx;
}
#endif /* !FTC_INLINE */
/* Note that this function cannot fail. If we cannot re-size the
* buckets array appropriately, we simply degrade the hash table's
* performance!
*/
static void
ftc_cache_resize( FTC_Cache cache )
{
for (;;)
{
FTC_Node node, *pnode;
FT_UFast p = cache->p;
FT_UFast size = cache->mask + 1; /* available size */
FT_UFast half = size >> 1;
/* do we need to expand the buckets array? */
if ( cache->slack < 0 )
{
FTC_Node new_list = NULL;
/* try to expand the buckets array _before_ splitting
* the bucket lists
*/
if ( p == size )
{
FT_Memory memory = cache->memory;
FT_Error error;
/* if we can't expand the array, leave immediately */
if ( FT_QRENEW_ARRAY( cache->buckets, size, size * 2 ) )
break;
cache->mask = 2 * size - 1;
half = size;
}
/* the bucket to split */
pnode = cache->buckets + p - half;
for (;;)
{
node = *pnode;
if ( !node )
break;
if ( node->hash & half )
{
*pnode = node->link;
node->link = new_list;
new_list = node;
}
else
pnode = &node->link;
}
cache->buckets[p] = new_list;
cache->slack += FTC_HASH_MAX_LOAD;
cache->p = p + 1;
FT_TRACE2(( "ftc_cache_resize: cache %u increased to %u hashes\n",
cache->index, cache->p ));
}
/* do we need to shrink the buckets array? */
else if ( cache->slack > (FT_Long)p * FTC_HASH_SUB_LOAD )
{
FTC_Node old_list = cache->buckets[--p];
if ( p < FTC_HASH_INITIAL_SIZE )
break;
if ( p == half )
{
FT_Memory memory = cache->memory;
FT_Error error;
/* if we can't shrink the array, leave immediately */
if ( FT_QRENEW_ARRAY( cache->buckets, size, half ) )
break;
cache->mask = half - 1;
}
/* the bucket to merge */
pnode = cache->buckets + p - half;
while ( *pnode )
pnode = &(*pnode)->link;
*pnode = old_list;
cache->slack -= FTC_HASH_MAX_LOAD;
cache->p = p;
FT_TRACE2(( "ftc_cache_resize: cache %u decreased to %u hashes\n",
cache->index, cache->p ));
}
/* otherwise, the hash table is balanced */
else
break;
}
}
/* remove a node from its cache's hash table */
static void
ftc_node_hash_unlink( FTC_Node node0,
FTC_Cache cache )
{
FTC_Node *pnode = FTC_NODE_TOP_FOR_HASH( cache, node0->hash );
for (;;)
{
FTC_Node node = *pnode;
if ( !node )
{
FT_TRACE0(( "ftc_node_hash_unlink: unknown node\n" ));
return;
}
if ( node == node0 )
break;
pnode = &node->link;
}
*pnode = node0->link;
node0->link = NULL;
cache->slack++;
ftc_cache_resize( cache );
}
/* add a node to the `top' of its cache's hash table */
static void
ftc_node_hash_link( FTC_Node node,
FTC_Cache cache )
{
FTC_Node *pnode = FTC_NODE_TOP_FOR_HASH( cache, node->hash );
node->link = *pnode;
*pnode = node;
cache->slack--;
ftc_cache_resize( cache );
}
/* remove a node from the cache manager */
FT_LOCAL_DEF( void )
ftc_node_destroy( FTC_Node node,
FTC_Manager manager )
{
FTC_Cache cache;
#ifdef FT_DEBUG_ERROR
/* find node's cache */
if ( node->cache_index >= manager->num_caches )
{
FT_TRACE0(( "ftc_node_destroy: invalid node handle\n" ));
return;
}
#endif
cache = manager->caches[node->cache_index];
#ifdef FT_DEBUG_ERROR
if ( !cache )
{
FT_TRACE0(( "ftc_node_destroy: invalid node handle\n" ));
return;
}
#endif
manager->cur_weight -= cache->clazz.node_weight( node, cache );
/* remove node from mru list */
ftc_node_mru_unlink( node, manager );
/* remove node from cache's hash table */
ftc_node_hash_unlink( node, cache );
/* now finalize it */
cache->clazz.node_free( node, cache );
#if 0
/* check, just in case of general corruption :-) */
if ( manager->num_nodes == 0 )
FT_TRACE0(( "ftc_node_destroy: invalid cache node count (%u)\n",
manager->num_nodes ));
#endif
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** ABSTRACT CACHE CLASS *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
FT_LOCAL_DEF( FT_Error )
ftc_cache_init( FTC_Cache cache )
{
FT_Memory memory = cache->memory;
FT_Error error;
cache->p = FTC_HASH_INITIAL_SIZE;
cache->mask = FTC_HASH_INITIAL_SIZE - 1;
cache->slack = FTC_HASH_INITIAL_SIZE * FTC_HASH_MAX_LOAD;
FT_MEM_NEW_ARRAY( cache->buckets, FTC_HASH_INITIAL_SIZE );
return error;
}
FT_LOCAL_DEF( FT_Error )
FTC_Cache_Init( FTC_Cache cache )
{
return ftc_cache_init( cache );
}
FT_LOCAL_DEF( void )
ftc_cache_done( FTC_Cache cache )
{
FT_Memory memory = cache->memory;
if ( cache->buckets )
{
FTC_Manager manager = cache->manager;
FT_UFast count = cache->p;
FT_UFast i;
for ( i = 0; i < count; i++ )
{
FTC_Node node = cache->buckets[i], next;
while ( node )
{
next = node->link;
node->link = NULL;
/* remove node from mru list */
ftc_node_mru_unlink( node, manager );
/* now finalize it */
manager->cur_weight -= cache->clazz.node_weight( node, cache );
cache->clazz.node_free( node, cache );
node = next;
}
}
}
FT_FREE( cache->buckets );
cache->p = 0;
cache->mask = 0;
cache->slack = 0;
}
FT_LOCAL_DEF( void )
FTC_Cache_Done( FTC_Cache cache )
{
ftc_cache_done( cache );
}
static void
ftc_cache_add( FTC_Cache cache,
FT_Offset hash,
FTC_Node node )
{
node->hash = hash;
node->cache_index = (FT_UShort)cache->index;
node->ref_count = 0;
ftc_node_hash_link( node, cache );
ftc_node_mru_link( node, cache->manager );
{
FTC_Manager manager = cache->manager;
manager->cur_weight += cache->clazz.node_weight( node, cache );
if ( manager->cur_weight >= manager->max_weight )
{
node->ref_count++;
FTC_Manager_Compress( manager );
node->ref_count--;
}
}
}
FT_LOCAL_DEF( FT_Error )
FTC_Cache_NewNode( FTC_Cache cache,
FT_Offset hash,
FT_Pointer query,
FTC_Node *anode )
{
FT_Error error;
FTC_Node node;
/*
* We use the FTC_CACHE_TRYLOOP macros to support out-of-memory
* errors (OOM) correctly, i.e., by flushing the cache progressively
* in order to make more room.
*/
FTC_CACHE_TRYLOOP( cache )
{
error = cache->clazz.node_new( &node, query, cache );
}
FTC_CACHE_TRYLOOP_END( NULL )
if ( error )
node = NULL;
else
{
/* don't assume that the cache has the same number of buckets, since
* our allocation request might have triggered global cache flushing
*/
ftc_cache_add( cache, hash, node );
}
*anode = node;
return error;
}
#ifndef FTC_INLINE
FT_LOCAL_DEF( FT_Error )
FTC_Cache_Lookup( FTC_Cache cache,
FT_Offset hash,
FT_Pointer query,
FTC_Node *anode )
{
FTC_Node* bucket;
FTC_Node* pnode;
FTC_Node node;
FT_Error error = FT_Err_Ok;
FT_Bool list_changed = FALSE;
FTC_Node_CompareFunc compare = cache->clazz.node_compare;
if ( !cache || !anode )
return FT_THROW( Invalid_Argument );
/* Go to the `top' node of the list sharing same masked hash */
bucket = pnode = FTC_NODE_TOP_FOR_HASH( cache, hash );
/* Lookup a node with exactly same hash and queried properties. */
/* NOTE: _nodcomp() may change the linked list to reduce memory. */
for (;;)
{
node = *pnode;
if ( !node )
goto NewNode;
if ( node->hash == hash &&
compare( node, query, cache, &list_changed ) )
break;
pnode = &node->link;
}
if ( list_changed )
{
/* Update bucket by modified linked list */
bucket = pnode = FTC_NODE_TOP_FOR_HASH( cache, hash );
/* Update pnode by modified linked list */
while ( *pnode != node )
{
if ( !*pnode )
{
FT_ERROR(( "FTC_Cache_Lookup: oops!!! node missing\n" ));
goto NewNode;
}
else
pnode = &(*pnode)->link;
}
}
/* Reorder the list to move the found node to the `top' */
if ( node != *bucket )
{
*pnode = node->link;
node->link = *bucket;
*bucket = node;
}
/* move to head of MRU list */
{
FTC_Manager manager = cache->manager;
if ( node != manager->nodes_list )
ftc_node_mru_up( node, manager );
}
*anode = node;
return error;
NewNode:
return FTC_Cache_NewNode( cache, hash, query, anode );
}
#endif /* !FTC_INLINE */
FT_LOCAL_DEF( void )
FTC_Cache_RemoveFaceID( FTC_Cache cache,
FTC_FaceID face_id )
{
FTC_Manager manager = cache->manager;
FT_UFast count = cache->p;
FT_UFast i;
for ( i = 0; i < count; i++ )
{
FTC_Node* pnode = cache->buckets + i;
for (;;)
{
FTC_Node node = *pnode;
if ( !node )
break;
if ( cache->clazz.node_remove_faceid( node, face_id, cache, NULL ) )
{
*pnode = node->link;
manager->cur_weight -= cache->clazz.node_weight( node, cache );
ftc_node_mru_unlink( node, manager );
cache->clazz.node_free( node, cache );
cache->slack++;
}
else
pnode = &node->link;
}
}
ftc_cache_resize( cache );
}
/* END */

359
thirdparty/freetype/src/cache/ftccache.h vendored Normal file
View File

@@ -0,0 +1,359 @@
/****************************************************************************
*
* ftccache.h
*
* FreeType internal cache interface (specification).
*
* Copyright (C) 2000-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#ifndef FTCCACHE_H_
#define FTCCACHE_H_
#include <freetype/internal/compiler-macros.h>
#include "ftcmru.h"
FT_BEGIN_HEADER
#define FTC_FACE_ID_HASH( i ) \
( ( (FT_Offset)(i) >> 3 ) ^ ( (FT_Offset)(i) << 7 ) )
/* handle to cache object */
typedef struct FTC_CacheRec_* FTC_Cache;
/* handle to cache class */
typedef const struct FTC_CacheClassRec_* FTC_CacheClass;
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** CACHE NODE DEFINITIONS *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/**************************************************************************
*
* Each cache controls one or more cache nodes. Each node is part of
* the global_lru list of the manager. Its `data' field however is used
* as a reference count for now.
*
* A node can be anything, depending on the type of information held by
* the cache. It can be an individual glyph image, a set of bitmaps
* glyphs for a given size, some metrics, etc.
*
*/
/* structure size should be 20 bytes on 32-bits machines */
typedef struct FTC_NodeRec_
{
FTC_MruNodeRec mru; /* circular mru list pointer */
FTC_Node link; /* used for hashing */
FT_Offset hash; /* used for hashing too */
FT_UShort cache_index; /* index of cache the node belongs to */
FT_Short ref_count; /* reference count for this node */
} FTC_NodeRec;
#define FTC_NODE( x ) ( (FTC_Node)(x) )
#define FTC_NODE_P( x ) ( (FTC_Node*)(x) )
#define FTC_NODE_NEXT( x ) FTC_NODE( (x)->mru.next )
#define FTC_NODE_PREV( x ) FTC_NODE( (x)->mru.prev )
/* address the hash table entries */
#ifdef FTC_INLINE
#define FTC_NODE_TOP_FOR_HASH( cache, hash ) \
( ( cache )->buckets + \
( ( ( ( hash ) & ( cache )->mask ) >= ( cache )->p ) \
? ( ( hash ) & ( ( cache )->mask >> 1 ) ) \
: ( ( hash ) & ( cache )->mask ) ) )
#else
FT_LOCAL( FTC_Node* )
ftc_get_top_node_for_hash( FTC_Cache cache,
FT_Offset hash );
#define FTC_NODE_TOP_FOR_HASH( cache, hash ) \
ftc_get_top_node_for_hash( ( cache ), ( hash ) )
#endif
FT_LOCAL( void )
ftc_node_destroy( FTC_Node node,
FTC_Manager manager );
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** CACHE DEFINITIONS *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* initialize a new cache node */
typedef FT_Error
(*FTC_Node_NewFunc)( FTC_Node *pnode,
FT_Pointer query,
FTC_Cache cache );
typedef FT_Offset
(*FTC_Node_WeightFunc)( FTC_Node node,
FTC_Cache cache );
/* compare a node to a given key pair */
typedef FT_Bool
(*FTC_Node_CompareFunc)( FTC_Node node,
FT_Pointer key,
FTC_Cache cache,
FT_Bool* list_changed );
typedef void
(*FTC_Node_FreeFunc)( FTC_Node node,
FTC_Cache cache );
typedef FT_Error
(*FTC_Cache_InitFunc)( FTC_Cache cache );
typedef void
(*FTC_Cache_DoneFunc)( FTC_Cache cache );
typedef struct FTC_CacheClassRec_
{
FTC_Node_NewFunc node_new;
FTC_Node_WeightFunc node_weight;
FTC_Node_CompareFunc node_compare;
FTC_Node_CompareFunc node_remove_faceid;
FTC_Node_FreeFunc node_free;
FT_Offset cache_size;
FTC_Cache_InitFunc cache_init;
FTC_Cache_DoneFunc cache_done;
} FTC_CacheClassRec;
/* each cache really implements a hash table to manage its nodes */
/* the number of the table entries (buckets) can change dynamically */
/* each bucket contains a linked lists of nodes for a given hash */
typedef struct FTC_CacheRec_
{
FT_UFast p; /* hash table counter */
FT_UFast mask; /* hash table index range */
FT_Long slack;
FTC_Node* buckets;
FTC_CacheClassRec clazz; /* local copy, for speed */
FTC_Manager manager;
FT_Memory memory;
FT_UInt index; /* in manager's table */
FTC_CacheClass org_class; /* original class pointer */
} FTC_CacheRec;
#define FTC_CACHE( x ) ( (FTC_Cache)(x) )
#define FTC_CACHE_P( x ) ( (FTC_Cache*)(x) )
/* default cache initialize */
FT_LOCAL( FT_Error )
FTC_Cache_Init( FTC_Cache cache );
/* default cache finalizer */
FT_LOCAL( void )
FTC_Cache_Done( FTC_Cache cache );
/* Call this function to look up the cache. If no corresponding
* node is found, a new one is automatically created. This function
* is capable of flushing the cache adequately to make room for the
* new cache object.
*/
#ifndef FTC_INLINE
FT_LOCAL( FT_Error )
FTC_Cache_Lookup( FTC_Cache cache,
FT_Offset hash,
FT_Pointer query,
FTC_Node *anode );
#endif
FT_LOCAL( FT_Error )
FTC_Cache_NewNode( FTC_Cache cache,
FT_Offset hash,
FT_Pointer query,
FTC_Node *anode );
/* Remove all nodes that relate to a given face_id. This is useful
* when un-installing fonts. Note that if a cache node relates to
* the face_id but is locked (i.e., has `ref_count > 0'), the node
* will _not_ be destroyed, but its internal face_id reference will
* be modified.
*
* The final result will be that the node will never come back
* in further lookup requests, and will be flushed on demand from
* the cache normally when its reference count reaches 0.
*/
FT_LOCAL( void )
FTC_Cache_RemoveFaceID( FTC_Cache cache,
FTC_FaceID face_id );
#ifdef FTC_INLINE
#define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \
FT_BEGIN_STMNT \
FTC_Node *_bucket, *_pnode, _node; \
FTC_Cache _cache = FTC_CACHE( cache ); \
FT_Offset _hash = (FT_Offset)(hash); \
FTC_Node_CompareFunc _nodcomp = (FTC_Node_CompareFunc)(nodecmp); \
FT_Bool _list_changed = FALSE; \
\
\
error = FT_Err_Ok; \
node = NULL; \
\
/* Go to the `top' node of the list sharing same masked hash */ \
_bucket = _pnode = FTC_NODE_TOP_FOR_HASH( _cache, _hash ); \
\
/* Look up a node with identical hash and queried properties. */ \
/* NOTE: _nodcomp() may change the linked list to reduce memory. */ \
for (;;) \
{ \
_node = *_pnode; \
if ( !_node ) \
goto NewNode_; \
\
if ( _node->hash == _hash && \
_nodcomp( _node, query, _cache, &_list_changed ) ) \
break; \
\
_pnode = &_node->link; \
} \
\
if ( _list_changed ) \
{ \
/* Update _bucket by possibly modified linked list */ \
_bucket = _pnode = FTC_NODE_TOP_FOR_HASH( _cache, _hash ); \
\
/* Update _pnode by possibly modified linked list */ \
while ( *_pnode != _node ) \
{ \
if ( !*_pnode ) \
{ \
FT_ERROR(( "FTC_CACHE_LOOKUP_CMP: oops!!! node missing\n" )); \
goto NewNode_; \
} \
else \
_pnode = &(*_pnode)->link; \
} \
} \
\
/* Reorder the list to move the found node to the `top' */ \
if ( _node != *_bucket ) \
{ \
*_pnode = _node->link; \
_node->link = *_bucket; \
*_bucket = _node; \
} \
\
/* Update MRU list */ \
{ \
FTC_Manager _manager = _cache->manager; \
void* _nl = &_manager->nodes_list; \
\
\
if ( _node != _manager->nodes_list ) \
FTC_MruNode_Up( (FTC_MruNode*)_nl, \
(FTC_MruNode)_node ); \
} \
goto Ok_; \
\
NewNode_: \
error = FTC_Cache_NewNode( _cache, _hash, query, &_node ); \
\
Ok_: \
node = _node; \
FT_END_STMNT
#else /* !FTC_INLINE */
#define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \
FT_BEGIN_STMNT \
error = FTC_Cache_Lookup( FTC_CACHE( cache ), hash, query, \
(FTC_Node*)&(node) ); \
FT_END_STMNT
#endif /* !FTC_INLINE */
/*
* This macro, together with FTC_CACHE_TRYLOOP_END, defines a retry
* loop to flush the cache repeatedly in case of memory overflows.
*
* It is used when creating a new cache node, or within a lookup
* that needs to allocate data (e.g. the sbit cache lookup).
*
* Example:
*
* {
* FTC_CACHE_TRYLOOP( cache )
* error = load_data( ... );
* FTC_CACHE_TRYLOOP_END()
* }
*
*/
#define FTC_CACHE_TRYLOOP( cache ) \
{ \
FTC_Manager _try_manager = FTC_CACHE( cache )->manager; \
FT_UInt _try_count = 4; \
\
\
for (;;) \
{ \
FT_UInt _try_done;
#define FTC_CACHE_TRYLOOP_END( list_changed ) \
if ( !error || FT_ERR_NEQ( error, Out_Of_Memory ) ) \
break; \
\
_try_done = FTC_Manager_FlushN( _try_manager, _try_count ); \
if ( _try_done > 0 && list_changed != NULL ) \
*(FT_Bool*)( list_changed ) = TRUE; \
\
if ( _try_done == 0 ) \
break; \
\
if ( _try_done == _try_count ) \
{ \
_try_count *= 2; \
if ( _try_count < _try_done || \
_try_count > _try_manager->num_nodes ) \
_try_count = _try_manager->num_nodes; \
} \
} \
}
/* */
FT_END_HEADER
#endif /* FTCCACHE_H_ */
/* END */

View File

@@ -0,0 +1,85 @@
/****************************************************************************
*
* ftccback.h
*
* Callback functions of the caching sub-system (specification only).
*
* Copyright (C) 2004-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#ifndef FTCCBACK_H_
#define FTCCBACK_H_
#include <freetype/ftcache.h>
#include "ftccache.h"
FT_BEGIN_HEADER
FT_LOCAL( void )
ftc_inode_free( FTC_Node inode,
FTC_Cache cache );
FT_LOCAL( FT_Error )
ftc_inode_new( FTC_Node *pinode,
FT_Pointer gquery,
FTC_Cache cache );
FT_LOCAL( FT_Offset )
ftc_inode_weight( FTC_Node inode,
FTC_Cache cache );
FT_LOCAL( void )
ftc_snode_free( FTC_Node snode,
FTC_Cache cache );
FT_LOCAL( FT_Error )
ftc_snode_new( FTC_Node *psnode,
FT_Pointer gquery,
FTC_Cache cache );
FT_LOCAL( FT_Offset )
ftc_snode_weight( FTC_Node snode,
FTC_Cache cache );
FT_LOCAL( FT_Bool )
ftc_snode_compare( FTC_Node snode,
FT_Pointer gquery,
FTC_Cache cache,
FT_Bool* list_changed );
FT_LOCAL( FT_Bool )
ftc_gnode_compare( FTC_Node gnode,
FT_Pointer gquery,
FTC_Cache cache,
FT_Bool* list_changed );
FT_LOCAL( FT_Error )
ftc_gcache_init( FTC_Cache cache );
FT_LOCAL( void )
ftc_gcache_done( FTC_Cache cache );
FT_LOCAL( FT_Error )
ftc_cache_init( FTC_Cache cache );
FT_LOCAL( void )
ftc_cache_done( FTC_Cache cache );
FT_END_HEADER
#endif /* FTCCBACK_H_ */
/* END */

323
thirdparty/freetype/src/cache/ftccmap.c vendored Normal file
View File

@@ -0,0 +1,323 @@
/****************************************************************************
*
* ftccmap.c
*
* FreeType CharMap cache (body)
*
* Copyright (C) 2000-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/freetype.h>
#include <freetype/ftcache.h>
#include "ftcmanag.h"
#include <freetype/internal/ftmemory.h>
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/ftdebug.h>
#include "ftccback.h"
#include "ftcerror.h"
#undef FT_COMPONENT
#define FT_COMPONENT cache
/**************************************************************************
*
* Each FTC_CMapNode contains a simple array to map a range of character
* codes to equivalent glyph indices.
*
* For now, the implementation is very basic: Each node maps a range of
* 128 consecutive character codes to their corresponding glyph indices.
*
* We could do more complex things, but I don't think it is really very
* useful.
*
*/
/* number of glyph indices / character code per node */
#define FTC_CMAP_INDICES_MAX 128
/* compute a query/node hash */
#define FTC_CMAP_HASH( faceid, index, charcode ) \
( FTC_FACE_ID_HASH( faceid ) + 211 * (index) + \
( (charcode) / FTC_CMAP_INDICES_MAX ) )
/* the charmap query */
typedef struct FTC_CMapQueryRec_
{
FTC_FaceID face_id;
FT_UInt cmap_index;
FT_UInt32 char_code;
} FTC_CMapQueryRec, *FTC_CMapQuery;
#define FTC_CMAP_QUERY( x ) ((FTC_CMapQuery)(x))
/* the cmap cache node */
typedef struct FTC_CMapNodeRec_
{
FTC_NodeRec node;
FTC_FaceID face_id;
FT_UInt cmap_index;
FT_UInt32 first; /* first character in node */
FT_UInt16 indices[FTC_CMAP_INDICES_MAX]; /* array of glyph indices */
} FTC_CMapNodeRec, *FTC_CMapNode;
#define FTC_CMAP_NODE( x ) ( (FTC_CMapNode)( x ) )
/* if (indices[n] == FTC_CMAP_UNKNOWN), we assume that the corresponding */
/* glyph indices haven't been queried through FT_Get_Glyph_Index() yet */
#define FTC_CMAP_UNKNOWN (FT_UInt16)~0
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** CHARMAP NODES *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
FT_CALLBACK_DEF( void )
ftc_cmap_node_free( FTC_Node ftcnode,
FTC_Cache cache )
{
FTC_CMapNode node = (FTC_CMapNode)ftcnode;
FT_Memory memory = cache->memory;
FT_FREE( node );
}
/* initialize a new cmap node */
FT_CALLBACK_DEF( FT_Error )
ftc_cmap_node_new( FTC_Node *ftcanode,
FT_Pointer ftcquery,
FTC_Cache cache )
{
FTC_CMapNode *anode = (FTC_CMapNode*)ftcanode;
FTC_CMapQuery query = (FTC_CMapQuery)ftcquery;
FT_Error error;
FT_Memory memory = cache->memory;
FTC_CMapNode node = NULL;
FT_UInt nn;
if ( !FT_QNEW( node ) )
{
node->face_id = query->face_id;
node->cmap_index = query->cmap_index;
node->first = (query->char_code / FTC_CMAP_INDICES_MAX) *
FTC_CMAP_INDICES_MAX;
for ( nn = 0; nn < FTC_CMAP_INDICES_MAX; nn++ )
node->indices[nn] = FTC_CMAP_UNKNOWN;
}
*anode = node;
return error;
}
/* compute the weight of a given cmap node */
FT_CALLBACK_DEF( FT_Offset )
ftc_cmap_node_weight( FTC_Node cnode,
FTC_Cache cache )
{
FT_UNUSED( cnode );
FT_UNUSED( cache );
return sizeof ( *cnode );
}
/* compare a cmap node to a given query */
FT_CALLBACK_DEF( FT_Bool )
ftc_cmap_node_compare( FTC_Node ftcnode,
FT_Pointer ftcquery,
FTC_Cache cache,
FT_Bool* list_changed )
{
FTC_CMapNode node = (FTC_CMapNode)ftcnode;
FTC_CMapQuery query = (FTC_CMapQuery)ftcquery;
FT_UNUSED( cache );
if ( list_changed )
*list_changed = FALSE;
if ( node->face_id == query->face_id &&
node->cmap_index == query->cmap_index )
{
FT_UInt32 offset = (FT_UInt32)( query->char_code - node->first );
return FT_BOOL( offset < FTC_CMAP_INDICES_MAX );
}
return 0;
}
FT_CALLBACK_DEF( FT_Bool )
ftc_cmap_node_remove_faceid( FTC_Node ftcnode,
FT_Pointer ftcface_id,
FTC_Cache cache,
FT_Bool* list_changed )
{
FTC_CMapNode node = (FTC_CMapNode)ftcnode;
FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
FT_UNUSED( cache );
if ( list_changed )
*list_changed = FALSE;
return FT_BOOL( node->face_id == face_id );
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** GLYPH IMAGE CACHE *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
static
const FTC_CacheClassRec ftc_cmap_cache_class =
{
ftc_cmap_node_new, /* FTC_Node_NewFunc node_new */
ftc_cmap_node_weight, /* FTC_Node_WeightFunc node_weight */
ftc_cmap_node_compare, /* FTC_Node_CompareFunc node_compare */
ftc_cmap_node_remove_faceid, /* FTC_Node_CompareFunc node_remove_faceid */
ftc_cmap_node_free, /* FTC_Node_FreeFunc node_free */
sizeof ( FTC_CacheRec ),
ftc_cache_init, /* FTC_Cache_InitFunc cache_init */
ftc_cache_done, /* FTC_Cache_DoneFunc cache_done */
};
/* documentation is in ftcache.h */
FT_EXPORT_DEF( FT_Error )
FTC_CMapCache_New( FTC_Manager manager,
FTC_CMapCache *acache )
{
return FTC_Manager_RegisterCache( manager,
&ftc_cmap_cache_class,
FTC_CACHE_P( acache ) );
}
/* documentation is in ftcache.h */
FT_EXPORT_DEF( FT_UInt )
FTC_CMapCache_Lookup( FTC_CMapCache cmap_cache,
FTC_FaceID face_id,
FT_Int cmap_index,
FT_UInt32 char_code )
{
FTC_Cache cache = FTC_CACHE( cmap_cache );
FTC_CMapQueryRec query;
FTC_Node node;
FT_Error error;
FT_UInt gindex = 0;
FT_Offset hash;
FT_Int no_cmap_change = 0;
if ( cmap_index < 0 )
{
/* Treat a negative cmap index as a special value, meaning that you */
/* don't want to change the FT_Face's character map through this */
/* call. This can be useful if the face requester callback already */
/* sets the face's charmap to the appropriate value. */
no_cmap_change = 1;
cmap_index = 0;
}
if ( !cache )
{
FT_TRACE0(( "FTC_CMapCache_Lookup: bad arguments, returning 0\n" ));
return 0;
}
query.face_id = face_id;
query.cmap_index = (FT_UInt)cmap_index;
query.char_code = char_code;
hash = FTC_CMAP_HASH( face_id, (FT_UInt)cmap_index, char_code );
#ifdef FTC_INLINE
FTC_CACHE_LOOKUP_CMP( cache, ftc_cmap_node_compare, hash, &query,
node, error );
#else
error = FTC_Cache_Lookup( cache, hash, &query, &node );
#endif
if ( error )
goto Exit;
FT_ASSERT( char_code - FTC_CMAP_NODE( node )->first <
FTC_CMAP_INDICES_MAX );
/* something rotten can happen with rogue clients */
if ( char_code - FTC_CMAP_NODE( node )->first >= FTC_CMAP_INDICES_MAX )
return 0; /* XXX: should return appropriate error */
gindex = FTC_CMAP_NODE( node )->indices[char_code -
FTC_CMAP_NODE( node )->first];
if ( gindex == FTC_CMAP_UNKNOWN )
{
FT_Face face;
gindex = 0;
error = FTC_Manager_LookupFace( cache->manager,
FTC_CMAP_NODE( node )->face_id,
&face );
if ( error )
goto Exit;
if ( cmap_index < face->num_charmaps )
{
FT_CharMap old = face->charmap;
FT_CharMap cmap = face->charmaps[cmap_index];
if ( !no_cmap_change )
face->charmap = cmap;
gindex = FT_Get_Char_Index( face, char_code );
if ( !no_cmap_change )
face->charmap = old;
}
FTC_CMAP_NODE( node )->indices[char_code -
FTC_CMAP_NODE( node )->first]
= (FT_UShort)gindex;
}
Exit:
return gindex;
}
/* END */

View File

@@ -0,0 +1,42 @@
/****************************************************************************
*
* ftcerror.h
*
* Caching sub-system error codes (specification only).
*
* Copyright (C) 2001-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
/**************************************************************************
*
* This file is used to define the caching sub-system error enumeration
* constants.
*
*/
#ifndef FTCERROR_H_
#define FTCERROR_H_
#include <freetype/ftmoderr.h>
#undef FTERRORS_H_
#undef FT_ERR_PREFIX
#define FT_ERR_PREFIX FTC_Err_
#define FT_ERR_BASE FT_Mod_Err_Cache
#include <freetype/fterrors.h>
#endif /* FTCERROR_H_ */
/* END */

204
thirdparty/freetype/src/cache/ftcglyph.c vendored Normal file
View File

@@ -0,0 +1,204 @@
/****************************************************************************
*
* ftcglyph.c
*
* FreeType Glyph Image (FT_Glyph) cache (body).
*
* Copyright (C) 2000-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/internal/ftobjs.h>
#include <freetype/ftcache.h>
#include "ftcglyph.h"
#include <freetype/fterrors.h>
#include "ftccback.h"
#include "ftcerror.h"
/* create a new chunk node, setting its cache index and ref count */
FT_LOCAL_DEF( void )
FTC_GNode_Init( FTC_GNode gnode,
FT_UInt gindex,
FTC_Family family )
{
gnode->family = family;
gnode->gindex = gindex;
family->num_nodes++;
}
FT_LOCAL_DEF( void )
FTC_GNode_UnselectFamily( FTC_GNode gnode,
FTC_Cache cache )
{
FTC_Family family = gnode->family;
gnode->family = NULL;
if ( family && --family->num_nodes == 0 )
FTC_FAMILY_FREE( family, cache );
}
FT_LOCAL_DEF( void )
FTC_GNode_Done( FTC_GNode gnode,
FTC_Cache cache )
{
/* finalize the node */
gnode->gindex = 0;
FTC_GNode_UnselectFamily( gnode, cache );
}
FT_LOCAL_DEF( FT_Bool )
ftc_gnode_compare( FTC_Node ftcgnode,
FT_Pointer ftcgquery,
FTC_Cache cache,
FT_Bool* list_changed )
{
FTC_GNode gnode = (FTC_GNode)ftcgnode;
FTC_GQuery gquery = (FTC_GQuery)ftcgquery;
FT_UNUSED( cache );
if ( list_changed )
*list_changed = FALSE;
return FT_BOOL( gnode->family == gquery->family &&
gnode->gindex == gquery->gindex );
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** CHUNK SETS *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
FT_LOCAL_DEF( void )
FTC_Family_Init( FTC_Family family,
FTC_Cache cache )
{
FTC_GCacheClass clazz = FTC_CACHE_GCACHE_CLASS( cache );
family->clazz = clazz->family_class;
family->num_nodes = 0;
family->cache = cache;
}
FT_LOCAL_DEF( FT_Error )
ftc_gcache_init( FTC_Cache cache )
{
FTC_GCache gcache = (FTC_GCache)cache;
FT_Error error;
error = FTC_Cache_Init( cache );
if ( !error )
{
FTC_GCacheClass clazz = (FTC_GCacheClass)cache->org_class;
FTC_MruList_Init( &gcache->families,
clazz->family_class,
0, /* no maximum here! */
cache,
cache->memory );
}
return error;
}
#if 0
FT_LOCAL_DEF( FT_Error )
FTC_GCache_Init( FTC_GCache gcache )
{
return ftc_gcache_init( FTC_CACHE( gcache ) );
}
#endif /* 0 */
FT_LOCAL_DEF( void )
ftc_gcache_done( FTC_Cache cache )
{
FTC_GCache gcache = (FTC_GCache)cache;
FTC_Cache_Done( cache );
FTC_MruList_Done( &gcache->families );
}
#if 0
FT_LOCAL_DEF( void )
FTC_GCache_Done( FTC_GCache gcache )
{
ftc_gcache_done( FTC_CACHE( gcache ) );
}
#endif /* 0 */
FT_LOCAL_DEF( FT_Error )
FTC_GCache_New( FTC_Manager manager,
FTC_GCacheClass clazz,
FTC_GCache *acache )
{
return FTC_Manager_RegisterCache( manager, (FTC_CacheClass)clazz,
(FTC_Cache*)acache );
}
#ifndef FTC_INLINE
FT_LOCAL_DEF( FT_Error )
FTC_GCache_Lookup( FTC_GCache gcache,
FT_Offset hash,
FT_UInt gindex,
FTC_GQuery query,
FTC_Node *anode )
{
FT_Error error;
query->gindex = gindex;
FTC_MRULIST_LOOKUP( &gcache->families, query, query->family, error );
if ( !error )
{
FTC_Family family = query->family;
/* prevent the family from being destroyed too early when an */
/* out-of-memory condition occurs during glyph node initialization. */
family->num_nodes++;
error = FTC_Cache_Lookup( FTC_CACHE( gcache ), hash, query, anode );
if ( --family->num_nodes == 0 )
FTC_FAMILY_FREE( family, FTC_CACHE( gcache ) );
}
return error;
}
#endif /* !FTC_INLINE */
/* END */

314
thirdparty/freetype/src/cache/ftcglyph.h vendored Normal file
View File

@@ -0,0 +1,314 @@
/****************************************************************************
*
* ftcglyph.h
*
* FreeType abstract glyph cache (specification).
*
* Copyright (C) 2000-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
/*
*
* FTC_GCache is an _abstract_ cache object optimized to store glyph
* data. It works as follows:
*
* - It manages FTC_GNode objects. Each one of them can hold one or more
* glyph `items'. Item types are not specified in the FTC_GCache but
* in classes that extend it.
*
* - Glyph attributes, like face ID, character size, render mode, etc.,
* can be grouped into abstract `glyph families'. This avoids storing
* the attributes within the FTC_GCache, since it is likely that many
* FTC_GNodes will belong to the same family in typical uses.
*
* - Each FTC_GNode is thus an FTC_Node with two additional fields:
*
* * gindex: A glyph index, or the first index in a glyph range.
* * family: A pointer to a glyph `family'.
*
* - Family types are not fully specific in the FTC_Family type, but
* by classes that extend it.
*
* Note that both FTC_ImageCache and FTC_SBitCache extend FTC_GCache.
* They share an FTC_Family sub-class called FTC_BasicFamily which is
* used to store the following data: face ID, pixel/point sizes, load
* flags. For more details see the file `src/cache/ftcbasic.c'.
*
* Client applications can extend FTC_GNode with their own FTC_GNode
* and FTC_Family sub-classes to implement more complex caches (e.g.,
* handling automatic synthesis, like obliquing & emboldening, colored
* glyphs, etc.).
*
* See also the FTC_ICache & FTC_SCache classes in `ftcimage.h' and
* `ftcsbits.h', which both extend FTC_GCache with additional
* optimizations.
*
* A typical FTC_GCache implementation must provide at least the
* following:
*
* - FTC_GNode sub-class, e.g. MyNode, with relevant methods:
* my_node_new (must call FTC_GNode_Init)
* my_node_free (must call FTC_GNode_Done)
* my_node_compare (must call ftc_gnode_compare)
* my_node_remove_faceid (must call ftc_gnode_unselect in case
* of match)
*
* - FTC_Family sub-class, e.g. MyFamily, with relevant methods:
* my_family_compare
* my_family_init
* my_family_done
*
* - FTC_GQuery sub-class, e.g. MyQuery, to hold cache-specific query
* data.
*
* - Constant structures for a FTC_GNodeClass.
*
* - MyCacheNew() can be implemented easily as a call to the convenience
* function FTC_GCache_New.
*
* - MyCacheLookup with a call to FTC_GCache_Lookup. This function will
* automatically:
*
* - Search for the corresponding family in the cache, or create
* a new one if necessary. Put it in FTC_GQUERY(myquery).family
*
* - Call FTC_Cache_Lookup.
*
* If it returns NULL, you should create a new node, then call
* ftc_cache_add as usual.
*/
/**************************************************************************
*
* Important: The functions defined in this file are only used to
* implement an abstract glyph cache class. You need to
* provide additional logic to implement a complete cache.
*
*/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/********* *********/
/********* WARNING, THIS IS BETA CODE. *********/
/********* *********/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
#ifndef FTCGLYPH_H_
#define FTCGLYPH_H_
#include "ftcmanag.h"
FT_BEGIN_HEADER
/*
* We can group glyphs into `families'. Each family correspond to a
* given face ID, character size, transform, etc.
*
* Families are implemented as MRU list nodes. They are
* reference-counted.
*/
typedef struct FTC_FamilyRec_
{
FTC_MruNodeRec mrunode;
FT_UInt num_nodes; /* current number of nodes in this family */
FTC_Cache cache;
FTC_MruListClass clazz;
} FTC_FamilyRec, *FTC_Family;
#define FTC_FAMILY( x ) ( (FTC_Family)(x) )
#define FTC_FAMILY_P( x ) ( (FTC_Family*)(x) )
typedef struct FTC_GNodeRec_
{
FTC_NodeRec node;
FTC_Family family;
FT_UInt gindex;
} FTC_GNodeRec, *FTC_GNode;
#define FTC_GNODE( x ) ( (FTC_GNode)(x) )
#define FTC_GNODE_P( x ) ( (FTC_GNode*)(x) )
typedef struct FTC_GQueryRec_
{
FT_UInt gindex;
FTC_Family family;
} FTC_GQueryRec, *FTC_GQuery;
#define FTC_GQUERY( x ) ( (FTC_GQuery)(x) )
/**************************************************************************
*
* These functions are exported so that they can be called from
* user-provided cache classes; otherwise, they are really part of the
* cache sub-system internals.
*/
/* must be called by derived FTC_Node_InitFunc routines */
FT_LOCAL( void )
FTC_GNode_Init( FTC_GNode node,
FT_UInt gindex, /* glyph index for node */
FTC_Family family );
/* call this function to clear a node's family -- this is necessary */
/* to implement the `node_remove_faceid' cache method correctly */
FT_LOCAL( void )
FTC_GNode_UnselectFamily( FTC_GNode gnode,
FTC_Cache cache );
/* must be called by derived FTC_Node_DoneFunc routines */
FT_LOCAL( void )
FTC_GNode_Done( FTC_GNode node,
FTC_Cache cache );
FT_LOCAL( void )
FTC_Family_Init( FTC_Family family,
FTC_Cache cache );
typedef struct FTC_GCacheRec_
{
FTC_CacheRec cache;
FTC_MruListRec families;
} FTC_GCacheRec, *FTC_GCache;
#define FTC_GCACHE( x ) ((FTC_GCache)(x))
#if 0
/* can be used as @FTC_Cache_InitFunc */
FT_LOCAL( FT_Error )
FTC_GCache_Init( FTC_GCache cache );
#endif
#if 0
/* can be used as @FTC_Cache_DoneFunc */
FT_LOCAL( void )
FTC_GCache_Done( FTC_GCache cache );
#endif
/* the glyph cache class adds fields for the family implementation */
typedef struct FTC_GCacheClassRec_
{
FTC_CacheClassRec clazz;
FTC_MruListClass family_class;
} FTC_GCacheClassRec;
typedef const FTC_GCacheClassRec* FTC_GCacheClass;
#define FTC_GCACHE_CLASS( x ) ((FTC_GCacheClass)(x))
#define FTC_CACHE_GCACHE_CLASS( x ) \
FTC_GCACHE_CLASS( FTC_CACHE( x )->org_class )
#define FTC_CACHE_FAMILY_CLASS( x ) \
( (FTC_MruListClass)FTC_CACHE_GCACHE_CLASS( x )->family_class )
/* convenience function; use it instead of FTC_Manager_Register_Cache */
FT_LOCAL( FT_Error )
FTC_GCache_New( FTC_Manager manager,
FTC_GCacheClass clazz,
FTC_GCache *acache );
#ifndef FTC_INLINE
FT_LOCAL( FT_Error )
FTC_GCache_Lookup( FTC_GCache cache,
FT_Offset hash,
FT_UInt gindex,
FTC_GQuery query,
FTC_Node *anode );
#endif
/* */
#define FTC_FAMILY_FREE( family, cache ) \
FTC_MruList_Remove( &FTC_GCACHE((cache))->families, \
(FTC_MruNode)(family) )
#ifdef FTC_INLINE
#define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash, \
gindex, query, node, error ) \
FT_BEGIN_STMNT \
FTC_GCache _gcache = FTC_GCACHE( cache ); \
FTC_GQuery _gquery = (FTC_GQuery)( query ); \
FTC_MruNode_CompareFunc _fcompare = (FTC_MruNode_CompareFunc)(famcmp); \
FTC_MruNode _mrunode; \
\
\
_gquery->gindex = (gindex); \
\
FTC_MRULIST_LOOKUP_CMP( &_gcache->families, _gquery, _fcompare, \
_mrunode, error ); \
_gquery->family = FTC_FAMILY( _mrunode ); \
if ( !error ) \
{ \
FTC_Family _gqfamily = _gquery->family; \
\
\
_gqfamily->num_nodes++; \
\
FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ); \
\
if ( --_gqfamily->num_nodes == 0 ) \
FTC_FAMILY_FREE( _gqfamily, _gcache ); \
} \
FT_END_STMNT
/* */
#else /* !FTC_INLINE */
#define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash, \
gindex, query, node, error ) \
FT_BEGIN_STMNT \
\
error = FTC_GCache_Lookup( FTC_GCACHE( cache ), hash, gindex, \
FTC_GQUERY( query ), &node ); \
\
FT_END_STMNT
#endif /* !FTC_INLINE */
FT_END_HEADER
#endif /* FTCGLYPH_H_ */
/* END */

158
thirdparty/freetype/src/cache/ftcimage.c vendored Normal file
View File

@@ -0,0 +1,158 @@
/****************************************************************************
*
* ftcimage.c
*
* FreeType Image cache (body).
*
* Copyright (C) 2000-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/ftcache.h>
#include "ftcimage.h"
#include <freetype/internal/ftmemory.h>
#include <freetype/internal/ftobjs.h>
#include "ftccback.h"
#include "ftcerror.h"
/* finalize a given glyph image node */
FT_LOCAL_DEF( void )
ftc_inode_free( FTC_Node ftcinode,
FTC_Cache cache )
{
FTC_INode inode = (FTC_INode)ftcinode;
FT_Memory memory = cache->memory;
FT_Done_Glyph( inode->glyph );
FTC_GNode_Done( FTC_GNODE( inode ), cache );
FT_FREE( inode );
}
FT_LOCAL_DEF( void )
FTC_INode_Free( FTC_INode inode,
FTC_Cache cache )
{
ftc_inode_free( FTC_NODE( inode ), cache );
}
/* initialize a new glyph image node */
FT_LOCAL_DEF( FT_Error )
FTC_INode_New( FTC_INode *pinode,
FTC_GQuery gquery,
FTC_Cache cache )
{
FT_Memory memory = cache->memory;
FT_Error error;
FTC_INode inode = NULL;
if ( !FT_QNEW( inode ) )
{
FTC_GNode gnode = FTC_GNODE( inode );
FTC_Family family = gquery->family;
FT_UInt gindex = gquery->gindex;
FTC_IFamilyClass clazz = FTC_CACHE_IFAMILY_CLASS( cache );
/* initialize its inner fields */
FTC_GNode_Init( gnode, gindex, family );
inode->glyph = NULL;
/* we will now load the glyph image */
error = clazz->family_load_glyph( family, gindex, cache,
&inode->glyph );
if ( error )
{
FTC_INode_Free( inode, cache );
inode = NULL;
}
}
*pinode = inode;
return error;
}
FT_LOCAL_DEF( FT_Error )
ftc_inode_new( FTC_Node *ftcpinode,
FT_Pointer ftcgquery,
FTC_Cache cache )
{
FTC_INode *pinode = (FTC_INode*)ftcpinode;
FTC_GQuery gquery = (FTC_GQuery)ftcgquery;
return FTC_INode_New( pinode, gquery, cache );
}
FT_LOCAL_DEF( FT_Offset )
ftc_inode_weight( FTC_Node ftcinode,
FTC_Cache ftccache )
{
FTC_INode inode = (FTC_INode)ftcinode;
FT_Offset size = 0;
FT_Glyph glyph = inode->glyph;
FT_UNUSED( ftccache );
switch ( glyph->format )
{
case FT_GLYPH_FORMAT_BITMAP:
{
FT_BitmapGlyph bitg = (FT_BitmapGlyph)glyph;
size = bitg->bitmap.rows * (FT_Offset)FT_ABS( bitg->bitmap.pitch ) +
sizeof ( *bitg );
}
break;
case FT_GLYPH_FORMAT_OUTLINE:
{
FT_OutlineGlyph outg = (FT_OutlineGlyph)glyph;
size = (FT_Offset)outg->outline.n_points *
( sizeof ( FT_Vector ) + sizeof ( FT_Byte ) ) +
(FT_Offset)outg->outline.n_contours * sizeof ( FT_Short ) +
sizeof ( *outg );
}
break;
default:
;
}
size += sizeof ( *inode );
return size;
}
#if 0
FT_LOCAL_DEF( FT_Offset )
FTC_INode_Weight( FTC_INode inode )
{
return ftc_inode_weight( FTC_NODE( inode ), NULL );
}
#endif /* 0 */
/* END */

106
thirdparty/freetype/src/cache/ftcimage.h vendored Normal file
View File

@@ -0,0 +1,106 @@
/****************************************************************************
*
* ftcimage.h
*
* FreeType Generic Image cache (specification)
*
* Copyright (C) 2000-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
/*
* FTC_ICache is an _abstract_ cache used to store a single FT_Glyph
* image per cache node.
*
* FTC_ICache extends FTC_GCache. For an implementation example,
* see FTC_ImageCache in `src/cache/ftbasic.c'.
*/
/**************************************************************************
*
* Each image cache really manages FT_Glyph objects.
*
*/
#ifndef FTCIMAGE_H_
#define FTCIMAGE_H_
#include <freetype/ftcache.h>
#include "ftcglyph.h"
FT_BEGIN_HEADER
/* the FT_Glyph image node type - we store only 1 glyph per node */
typedef struct FTC_INodeRec_
{
FTC_GNodeRec gnode;
FT_Glyph glyph;
} FTC_INodeRec, *FTC_INode;
#define FTC_INODE( x ) ( (FTC_INode)( x ) )
#define FTC_INODE_GINDEX( x ) FTC_GNODE( x )->gindex
#define FTC_INODE_FAMILY( x ) FTC_GNODE( x )->family
typedef FT_Error
(*FTC_IFamily_LoadGlyphFunc)( FTC_Family family,
FT_UInt gindex,
FTC_Cache cache,
FT_Glyph *aglyph );
typedef struct FTC_IFamilyClassRec_
{
FTC_MruListClassRec clazz;
FTC_IFamily_LoadGlyphFunc family_load_glyph;
} FTC_IFamilyClassRec;
typedef const FTC_IFamilyClassRec* FTC_IFamilyClass;
#define FTC_IFAMILY_CLASS( x ) ((FTC_IFamilyClass)(x))
#define FTC_CACHE_IFAMILY_CLASS( x ) \
FTC_IFAMILY_CLASS( FTC_CACHE_GCACHE_CLASS( x )->family_class )
/* can be used as a @FTC_Node_FreeFunc */
FT_LOCAL( void )
FTC_INode_Free( FTC_INode inode,
FTC_Cache cache );
/* Can be used as @FTC_Node_NewFunc. `gquery.index' and `gquery.family'
* must be set correctly. This function will call the `family_load_glyph'
* method to load the FT_Glyph into the cache node.
*/
FT_LOCAL( FT_Error )
FTC_INode_New( FTC_INode *pinode,
FTC_GQuery gquery,
FTC_Cache cache );
#if 0
/* can be used as @FTC_Node_WeightFunc */
FT_LOCAL( FT_ULong )
FTC_INode_Weight( FTC_INode inode );
#endif
/* */
FT_END_HEADER
#endif /* FTCIMAGE_H_ */
/* END */

677
thirdparty/freetype/src/cache/ftcmanag.c vendored Normal file
View File

@@ -0,0 +1,677 @@
/****************************************************************************
*
* ftcmanag.c
*
* FreeType Cache Manager (body).
*
* Copyright (C) 2000-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/ftcache.h>
#include "ftcmanag.h"
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/ftdebug.h>
#include <freetype/ftsizes.h>
#include "ftcerror.h"
#undef FT_COMPONENT
#define FT_COMPONENT cache
static FT_Error
ftc_scaler_lookup_size( FTC_Manager manager,
FTC_Scaler scaler,
FT_Size *asize )
{
FT_Face face;
FT_Size size = NULL;
FT_Error error;
error = FTC_Manager_LookupFace( manager, scaler->face_id, &face );
if ( error )
goto Exit;
error = FT_New_Size( face, &size );
if ( error )
goto Exit;
FT_Activate_Size( size );
if ( scaler->pixel )
error = FT_Set_Pixel_Sizes( face, scaler->width, scaler->height );
else
error = FT_Set_Char_Size( face,
(FT_F26Dot6)scaler->width,
(FT_F26Dot6)scaler->height,
scaler->x_res,
scaler->y_res );
if ( error )
{
FT_Done_Size( size );
size = NULL;
}
Exit:
*asize = size;
return error;
}
typedef struct FTC_SizeNodeRec_
{
FTC_MruNodeRec node;
FT_Size size;
FTC_ScalerRec scaler;
} FTC_SizeNodeRec, *FTC_SizeNode;
#define FTC_SIZE_NODE( x ) ( (FTC_SizeNode)( x ) )
FT_CALLBACK_DEF( void )
ftc_size_node_done( FTC_MruNode ftcnode,
FT_Pointer data )
{
FTC_SizeNode node = (FTC_SizeNode)ftcnode;
FT_UNUSED( data );
FT_Done_Size( node->size );
}
FT_CALLBACK_DEF( FT_Bool )
ftc_size_node_compare( FTC_MruNode ftcnode,
FT_Pointer ftcscaler )
{
FTC_SizeNode node = (FTC_SizeNode)ftcnode;
FTC_Scaler scaler = (FTC_Scaler)ftcscaler;
FTC_Scaler scaler0 = &node->scaler;
if ( FTC_SCALER_COMPARE( scaler0, scaler ) )
{
FT_Activate_Size( node->size );
return 1;
}
return 0;
}
FT_CALLBACK_DEF( FT_Error )
ftc_size_node_init( FTC_MruNode ftcnode,
FT_Pointer ftcscaler,
FT_Pointer ftcmanager )
{
FT_Error error;
FT_Size size;
FTC_SizeNode node = (FTC_SizeNode)ftcnode;
FTC_Scaler scaler = (FTC_Scaler)ftcscaler;
FTC_Manager manager = (FTC_Manager)ftcmanager;
error = ftc_scaler_lookup_size( manager, scaler, &size );
if ( !error )
{
node->size = size;
node->scaler = scaler[0];
}
return error;
}
static
const FTC_MruListClassRec ftc_size_list_class =
{
sizeof ( FTC_SizeNodeRec ),
ftc_size_node_compare, /* FTC_MruNode_CompareFunc node_compare */
ftc_size_node_init, /* FTC_MruNode_InitFunc node_init */
ftc_size_node_done /* FTC_MruNode_DoneFunc node_done */
};
/* helper function used by ftc_face_node_done */
static FT_Bool
ftc_size_node_compare_faceid( FTC_MruNode ftcnode,
FT_Pointer ftcface_id )
{
FTC_SizeNode node = (FTC_SizeNode)ftcnode;
FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
return FT_BOOL( node->scaler.face_id == face_id );
}
/* documentation is in ftcache.h */
FT_EXPORT_DEF( FT_Error )
FTC_Manager_LookupSize( FTC_Manager manager,
FTC_Scaler scaler,
FT_Size *asize )
{
FT_Error error;
FTC_MruNode mrunode;
if ( !asize || !scaler )
return FT_THROW( Invalid_Argument );
*asize = NULL;
if ( !manager )
return FT_THROW( Invalid_Cache_Handle );
#ifdef FTC_INLINE
FTC_MRULIST_LOOKUP_CMP( &manager->sizes, scaler, ftc_size_node_compare,
mrunode, error );
#else
error = FTC_MruList_Lookup( &manager->sizes, scaler, &mrunode );
#endif
if ( !error )
*asize = FTC_SIZE_NODE( mrunode )->size;
return error;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** FACE MRU IMPLEMENTATION *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
typedef struct FTC_FaceNodeRec_
{
FTC_MruNodeRec node;
FTC_FaceID face_id;
FT_Face face;
} FTC_FaceNodeRec, *FTC_FaceNode;
#define FTC_FACE_NODE( x ) ( ( FTC_FaceNode )( x ) )
FT_CALLBACK_DEF( FT_Error )
ftc_face_node_init( FTC_MruNode ftcnode,
FT_Pointer ftcface_id,
FT_Pointer ftcmanager )
{
FT_Error error;
FT_Face face;
FTC_FaceNode node = (FTC_FaceNode)ftcnode;
FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
FTC_Manager manager = (FTC_Manager)ftcmanager;
error = manager->request_face( face_id,
manager->library,
manager->request_data,
&face );
if ( !error )
{
/* destroy initial size object; it will be re-created later */
if ( face->size )
FT_Done_Size( face->size );
node->face = face;
node->face_id = face_id;
}
return error;
}
FT_CALLBACK_DEF( void )
ftc_face_node_done( FTC_MruNode ftcnode,
FT_Pointer ftcmanager )
{
FTC_FaceNode node = (FTC_FaceNode)ftcnode;
FTC_Manager manager = (FTC_Manager)ftcmanager;
/* we must begin by removing all scalers for the target face */
/* from the manager's list */
FTC_MruList_RemoveSelection( &manager->sizes,
ftc_size_node_compare_faceid,
node->face_id );
/* all right, we can discard the face now */
FT_Done_Face( node->face );
node->face = NULL;
node->face_id = NULL;
}
FT_CALLBACK_DEF( FT_Bool )
ftc_face_node_compare( FTC_MruNode ftcnode,
FT_Pointer ftcface_id )
{
FTC_FaceNode node = (FTC_FaceNode)ftcnode;
FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
return FT_BOOL( node->face_id == face_id );
}
static
const FTC_MruListClassRec ftc_face_list_class =
{
sizeof ( FTC_FaceNodeRec),
ftc_face_node_compare, /* FTC_MruNode_CompareFunc node_compare */
ftc_face_node_init, /* FTC_MruNode_InitFunc node_init */
ftc_face_node_done /* FTC_MruNode_DoneFunc node_done */
};
/* documentation is in ftcache.h */
FT_EXPORT_DEF( FT_Error )
FTC_Manager_LookupFace( FTC_Manager manager,
FTC_FaceID face_id,
FT_Face *aface )
{
FT_Error error;
FTC_MruNode mrunode;
if ( !aface )
return FT_THROW( Invalid_Argument );
*aface = NULL;
if ( !manager )
return FT_THROW( Invalid_Cache_Handle );
/* we break encapsulation for the sake of speed */
#ifdef FTC_INLINE
FTC_MRULIST_LOOKUP_CMP( &manager->faces, face_id, ftc_face_node_compare,
mrunode, error );
#else
error = FTC_MruList_Lookup( &manager->faces, face_id, &mrunode );
#endif
if ( !error )
*aface = FTC_FACE_NODE( mrunode )->face;
return error;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** CACHE MANAGER ROUTINES *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* documentation is in ftcache.h */
FT_EXPORT_DEF( FT_Error )
FTC_Manager_New( FT_Library library,
FT_UInt max_faces,
FT_UInt max_sizes,
FT_ULong max_bytes,
FTC_Face_Requester requester,
FT_Pointer req_data,
FTC_Manager *amanager )
{
FT_Error error;
FT_Memory memory;
FTC_Manager manager = NULL;
if ( !library )
return FT_THROW( Invalid_Library_Handle );
if ( !amanager || !requester )
return FT_THROW( Invalid_Argument );
memory = library->memory;
if ( FT_QNEW( manager ) )
goto Exit;
if ( max_faces == 0 )
max_faces = FTC_MAX_FACES_DEFAULT;
if ( max_sizes == 0 )
max_sizes = FTC_MAX_SIZES_DEFAULT;
if ( max_bytes == 0 )
max_bytes = FTC_MAX_BYTES_DEFAULT;
manager->library = library;
manager->memory = memory;
manager->max_weight = max_bytes;
manager->cur_weight = 0;
manager->request_face = requester;
manager->request_data = req_data;
FTC_MruList_Init( &manager->faces,
&ftc_face_list_class,
max_faces,
manager,
memory );
FTC_MruList_Init( &manager->sizes,
&ftc_size_list_class,
max_sizes,
manager,
memory );
manager->nodes_list = NULL;
manager->num_nodes = 0;
manager->num_caches = 0;
*amanager = manager;
Exit:
return error;
}
/* documentation is in ftcache.h */
FT_EXPORT_DEF( void )
FTC_Manager_Done( FTC_Manager manager )
{
FT_Memory memory;
FT_UInt idx;
if ( !manager || !manager->library )
return;
memory = manager->memory;
/* now discard all caches */
for ( idx = manager->num_caches; idx-- > 0; )
{
FTC_Cache cache = manager->caches[idx];
if ( cache )
{
cache->clazz.cache_done( cache );
FT_FREE( cache );
}
}
/* discard faces and sizes */
FTC_MruList_Done( &manager->sizes );
FTC_MruList_Done( &manager->faces );
FT_FREE( manager );
}
/* documentation is in ftcache.h */
FT_EXPORT_DEF( void )
FTC_Manager_Reset( FTC_Manager manager )
{
if ( !manager )
return;
FTC_MruList_Reset( &manager->sizes );
FTC_MruList_Reset( &manager->faces );
FTC_Manager_FlushN( manager, manager->num_nodes );
}
#ifdef FT_DEBUG_ERROR
static void
FTC_Manager_Check( FTC_Manager manager )
{
FTC_Node node, first;
first = manager->nodes_list;
/* check node weights */
if ( first )
{
FT_Offset weight = 0;
node = first;
do
{
FTC_Cache cache = manager->caches[node->cache_index];
if ( node->cache_index >= manager->num_caches )
FT_TRACE0(( "FTC_Manager_Check: invalid node (cache index = %hu\n",
node->cache_index ));
else
weight += cache->clazz.node_weight( node, cache );
node = FTC_NODE_NEXT( node );
} while ( node != first );
if ( weight != manager->cur_weight )
FT_TRACE0(( "FTC_Manager_Check: invalid weight %ld instead of %ld\n",
manager->cur_weight, weight ));
}
/* check circular list */
if ( first )
{
FT_UFast count = 0;
node = first;
do
{
count++;
node = FTC_NODE_NEXT( node );
} while ( node != first );
if ( count != manager->num_nodes )
FT_TRACE0(( "FTC_Manager_Check:"
" invalid cache node count %u instead of %u\n",
manager->num_nodes, count ));
}
}
#endif /* FT_DEBUG_ERROR */
/* `Compress' the manager's data, i.e., get rid of old cache nodes */
/* that are not referenced anymore in order to limit the total */
/* memory used by the cache. */
/* documentation is in ftcmanag.h */
FT_LOCAL_DEF( void )
FTC_Manager_Compress( FTC_Manager manager )
{
FTC_Node node, prev, first;
if ( !manager )
return;
first = manager->nodes_list;
#ifdef FT_DEBUG_ERROR
FTC_Manager_Check( manager );
FT_TRACE0(( "compressing, weight = %ld, max = %ld, nodes = %u\n",
manager->cur_weight, manager->max_weight,
manager->num_nodes ));
#endif
if ( manager->cur_weight < manager->max_weight || !first )
return;
/* go to last node -- it's a circular list */
prev = FTC_NODE_PREV( first );
do
{
node = prev;
prev = FTC_NODE_PREV( node );
if ( node->ref_count <= 0 )
ftc_node_destroy( node, manager );
} while ( node != first && manager->cur_weight > manager->max_weight );
}
/* documentation is in ftcmanag.h */
FT_LOCAL_DEF( FT_Error )
FTC_Manager_RegisterCache( FTC_Manager manager,
FTC_CacheClass clazz,
FTC_Cache *acache )
{
FT_Error error = FT_ERR( Invalid_Argument );
FTC_Cache cache = NULL;
if ( manager && clazz && acache )
{
FT_Memory memory = manager->memory;
if ( manager->num_caches >= FTC_MAX_CACHES )
{
error = FT_THROW( Too_Many_Caches );
FT_ERROR(( "FTC_Manager_RegisterCache:"
" too many registered caches\n" ));
goto Exit;
}
if ( !FT_QALLOC( cache, clazz->cache_size ) )
{
cache->manager = manager;
cache->memory = memory;
cache->clazz = clazz[0];
cache->org_class = clazz;
/* THIS IS VERY IMPORTANT! IT WILL WRETCH THE MANAGER */
/* IF IT IS NOT SET CORRECTLY */
cache->index = manager->num_caches;
error = clazz->cache_init( cache );
if ( error )
{
clazz->cache_done( cache );
FT_FREE( cache );
goto Exit;
}
manager->caches[manager->num_caches++] = cache;
}
}
Exit:
if ( acache )
*acache = cache;
return error;
}
FT_LOCAL_DEF( FT_UInt )
FTC_Manager_FlushN( FTC_Manager manager,
FT_UInt count )
{
FTC_Node first = manager->nodes_list;
FTC_Node prev, node;
FT_UInt result = 0;
/* try to remove `count' nodes from the list */
if ( !first || !count )
return result;
/* go to last node -- it's a circular list */
prev = FTC_NODE_PREV( first );
do
{
node = prev;
prev = FTC_NODE_PREV( node );
/* don't touch locked nodes */
if ( node->ref_count <= 0 )
{
ftc_node_destroy( node, manager );
result++;
}
} while ( node != first && result < count );
return result;
}
/* documentation is in ftcache.h */
FT_EXPORT_DEF( void )
FTC_Manager_RemoveFaceID( FTC_Manager manager,
FTC_FaceID face_id )
{
FT_UInt nn;
if ( !manager )
return;
/* this will remove all FTC_SizeNode that correspond to
* the face_id as well
*/
FTC_MruList_RemoveSelection( &manager->faces,
ftc_face_node_compare,
face_id );
for ( nn = 0; nn < manager->num_caches; nn++ )
FTC_Cache_RemoveFaceID( manager->caches[nn], face_id );
}
/* documentation is in ftcache.h */
FT_EXPORT_DEF( void )
FTC_Node_Unref( FTC_Node node,
FTC_Manager manager )
{
if ( node &&
manager &&
node->cache_index < manager->num_caches )
node->ref_count--;
}
/* END */

175
thirdparty/freetype/src/cache/ftcmanag.h vendored Normal file
View File

@@ -0,0 +1,175 @@
/****************************************************************************
*
* ftcmanag.h
*
* FreeType Cache Manager (specification).
*
* Copyright (C) 2000-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
/**************************************************************************
*
* A cache manager is in charge of the following:
*
* - Maintain a mapping between generic FTC_FaceIDs and live FT_Face
* objects. The mapping itself is performed through a user-provided
* callback. However, the manager maintains a small cache of FT_Face
* and FT_Size objects in order to speed up things considerably.
*
* - Manage one or more cache objects. Each cache is in charge of
* holding a varying number of `cache nodes'. Each cache node
* represents a minimal amount of individually accessible cached
* data. For example, a cache node can be an FT_Glyph image
* containing a vector outline, or some glyph metrics, or anything
* else.
*
* Each cache node has a certain size in bytes that is added to the
* total amount of `cache memory' within the manager.
*
* All cache nodes are located in a global LRU list, where the oldest
* node is at the tail of the list.
*
* Each node belongs to a single cache, and includes a reference
* count to avoid destroying it (due to caching).
*
*/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/********* *********/
/********* WARNING, THIS IS BETA CODE. *********/
/********* *********/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
#ifndef FTCMANAG_H_
#define FTCMANAG_H_
#include <freetype/ftcache.h>
#include "ftcmru.h"
#include "ftccache.h"
FT_BEGIN_HEADER
/**************************************************************************
*
* @Section:
* cache_subsystem
*
*/
#define FTC_MAX_FACES_DEFAULT 2
#define FTC_MAX_SIZES_DEFAULT 4
#define FTC_MAX_BYTES_DEFAULT 200000L /* ~200kByte by default */
/* maximum number of caches registered in a single manager */
#define FTC_MAX_CACHES 16
typedef struct FTC_ManagerRec_
{
FT_Library library;
FT_Memory memory;
FTC_Node nodes_list;
FT_Offset max_weight;
FT_Offset cur_weight;
FT_UInt num_nodes;
FTC_Cache caches[FTC_MAX_CACHES];
FT_UInt num_caches;
FTC_MruListRec faces;
FTC_MruListRec sizes;
FT_Pointer request_data;
FTC_Face_Requester request_face;
} FTC_ManagerRec;
/**************************************************************************
*
* @Function:
* FTC_Manager_Compress
*
* @Description:
* This function is used to check the state of the cache manager if
* its `num_bytes' field is greater than its `max_bytes' field. It
* will flush as many old cache nodes as possible (ignoring cache
* nodes with a non-zero reference count).
*
* @InOut:
* manager ::
* A handle to the cache manager.
*
* @Note:
* Client applications should not call this function directly. It is
* normally invoked by specific cache implementations.
*
* The reason this function is exported is to allow client-specific
* cache classes.
*/
FT_LOCAL( void )
FTC_Manager_Compress( FTC_Manager manager );
/* try to flush `count' old nodes from the cache; return the number
* of really flushed nodes
*/
FT_LOCAL( FT_UInt )
FTC_Manager_FlushN( FTC_Manager manager,
FT_UInt count );
/* this must be used internally for the moment */
FT_LOCAL( FT_Error )
FTC_Manager_RegisterCache( FTC_Manager manager,
FTC_CacheClass clazz,
FTC_Cache *acache );
/* */
#define FTC_SCALER_COMPARE( a, b ) \
( (a)->face_id == (b)->face_id && \
(a)->width == (b)->width && \
(a)->height == (b)->height && \
((a)->pixel != 0) == ((b)->pixel != 0) && \
( (a)->pixel || \
( (a)->x_res == (b)->x_res && \
(a)->y_res == (b)->y_res ) ) )
#define FTC_SCALER_HASH( q ) \
( FTC_FACE_ID_HASH( (q)->face_id ) + \
(q)->width + (q)->height*7 + \
( (q)->pixel ? 0 : ( (q)->x_res*33 ^ (q)->y_res*61 ) ) )
/* */
FT_END_HEADER
#endif /* FTCMANAG_H_ */
/* END */

341
thirdparty/freetype/src/cache/ftcmru.c vendored Normal file
View File

@@ -0,0 +1,341 @@
/****************************************************************************
*
* ftcmru.c
*
* FreeType MRU support (body).
*
* Copyright (C) 2003-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/ftcache.h>
#include "ftcmru.h"
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/ftdebug.h>
#include "ftcerror.h"
FT_LOCAL_DEF( void )
FTC_MruNode_Prepend( FTC_MruNode *plist,
FTC_MruNode node )
{
FTC_MruNode first = *plist;
if ( first )
{
FTC_MruNode last = first->prev;
#ifdef FT_DEBUG_ERROR
{
FTC_MruNode cnode = first;
do
{
if ( cnode == node )
{
fprintf( stderr, "FTC_MruNode_Prepend: invalid action\n" );
exit( 2 );
}
cnode = cnode->next;
} while ( cnode != first );
}
#endif
first->prev = node;
last->next = node;
node->next = first;
node->prev = last;
}
else
{
node->next = node;
node->prev = node;
}
*plist = node;
}
FT_LOCAL_DEF( void )
FTC_MruNode_Up( FTC_MruNode *plist,
FTC_MruNode node )
{
FTC_MruNode first = *plist;
FT_ASSERT( first );
if ( first != node )
{
FTC_MruNode prev, next, last;
#ifdef FT_DEBUG_ERROR
{
FTC_MruNode cnode = first;
do
{
if ( cnode == node )
goto Ok;
cnode = cnode->next;
} while ( cnode != first );
fprintf( stderr, "FTC_MruNode_Up: invalid action\n" );
exit( 2 );
Ok:
}
#endif
prev = node->prev;
next = node->next;
prev->next = next;
next->prev = prev;
last = first->prev;
last->next = node;
first->prev = node;
node->next = first;
node->prev = last;
*plist = node;
}
}
FT_LOCAL_DEF( void )
FTC_MruNode_Remove( FTC_MruNode *plist,
FTC_MruNode node )
{
FTC_MruNode first = *plist;
FTC_MruNode prev, next;
FT_ASSERT( first );
#ifdef FT_DEBUG_ERROR
{
FTC_MruNode cnode = first;
do
{
if ( cnode == node )
goto Ok;
cnode = cnode->next;
} while ( cnode != first );
fprintf( stderr, "FTC_MruNode_Remove: invalid action\n" );
exit( 2 );
Ok:
}
#endif
prev = node->prev;
next = node->next;
prev->next = next;
next->prev = prev;
if ( node == next )
{
FT_ASSERT( first == node );
FT_ASSERT( prev == node );
*plist = NULL;
}
else if ( node == first )
*plist = next;
}
FT_LOCAL_DEF( void )
FTC_MruList_Init( FTC_MruList list,
FTC_MruListClass clazz,
FT_UInt max_nodes,
FT_Pointer data,
FT_Memory memory )
{
list->num_nodes = 0;
list->max_nodes = max_nodes;
list->nodes = NULL;
list->clazz = *clazz;
list->data = data;
list->memory = memory;
}
FT_LOCAL_DEF( void )
FTC_MruList_Reset( FTC_MruList list )
{
while ( list->nodes )
FTC_MruList_Remove( list, list->nodes );
FT_ASSERT( list->num_nodes == 0 );
}
FT_LOCAL_DEF( void )
FTC_MruList_Done( FTC_MruList list )
{
FTC_MruList_Reset( list );
}
#ifndef FTC_INLINE
FT_LOCAL_DEF( FTC_MruNode )
FTC_MruList_Find( FTC_MruList list,
FT_Pointer key )
{
FTC_MruNode_CompareFunc compare = list->clazz.node_compare;
FTC_MruNode first, node;
first = list->nodes;
node = NULL;
if ( first )
{
node = first;
do
{
if ( compare( node, key ) )
{
if ( node != first )
FTC_MruNode_Up( &list->nodes, node );
return node;
}
node = node->next;
} while ( node != first);
}
return NULL;
}
#endif
FT_LOCAL_DEF( FT_Error )
FTC_MruList_New( FTC_MruList list,
FT_Pointer key,
FTC_MruNode *anode )
{
FT_Error error;
FTC_MruNode node = NULL;
FTC_MruNode prev = NULL;
FT_Memory memory = list->memory;
/* zero new node in case of node_init failure */
if ( FT_ALLOC( node, list->clazz.node_size ) )
goto Exit;
error = list->clazz.node_init( node, key, list->data );
if ( error )
{
prev = node;
node = NULL;
goto Clean;
}
else if ( list->max_nodes > 0 && list->num_nodes >= list->max_nodes )
prev = list->nodes->prev;
FTC_MruNode_Prepend( &list->nodes, node );
list->num_nodes++;
if ( !prev )
goto Exit;
FTC_MruNode_Remove( &list->nodes, prev );
list->num_nodes--;
Clean:
if ( list->clazz.node_done )
list->clazz.node_done( prev, list->data );
FT_FREE( prev );
Exit:
*anode = node;
return error;
}
#ifndef FTC_INLINE
FT_LOCAL_DEF( FT_Error )
FTC_MruList_Lookup( FTC_MruList list,
FT_Pointer key,
FTC_MruNode *anode )
{
FTC_MruNode node;
node = FTC_MruList_Find( list, key );
if ( !node )
return FTC_MruList_New( list, key, anode );
*anode = node;
return 0;
}
#endif /* FTC_INLINE */
FT_LOCAL_DEF( void )
FTC_MruList_Remove( FTC_MruList list,
FTC_MruNode node )
{
FT_Memory memory = list->memory;
FTC_MruNode_Remove( &list->nodes, node );
list->num_nodes--;
if ( list->clazz.node_done )
list->clazz.node_done( node, list->data );
FT_FREE( node );
}
FT_LOCAL_DEF( void )
FTC_MruList_RemoveSelection( FTC_MruList list,
FTC_MruNode_CompareFunc selection,
FT_Pointer key )
{
FTC_MruNode first = list->nodes;
FTC_MruNode prev, node;
if ( !first || !selection )
return;
prev = first->prev;
do
{
node = prev;
prev = node->prev;
if ( selection( node, key ) )
FTC_MruList_Remove( list, node );
} while ( node != first );
}
/* END */

242
thirdparty/freetype/src/cache/ftcmru.h vendored Normal file
View File

@@ -0,0 +1,242 @@
/****************************************************************************
*
* ftcmru.h
*
* Simple MRU list-cache (specification).
*
* Copyright (C) 2000-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
/**************************************************************************
*
* An MRU is a list that cannot hold more than a certain number of
* elements (`max_elements'). All elements in the list are sorted in
* least-recently-used order, i.e., the `oldest' element is at the tail
* of the list.
*
* When doing a lookup (either through `Lookup()' or `Lookup_Node()'),
* the list is searched for an element with the corresponding key. If
* it is found, the element is moved to the head of the list and is
* returned.
*
* If no corresponding element is found, the lookup routine will try to
* obtain a new element with the relevant key. If the list is already
* full, the oldest element from the list is discarded and replaced by a
* new one; a new element is added to the list otherwise.
*
* Note that it is possible to pre-allocate the element list nodes.
* This is handy if `max_elements' is sufficiently small, as it saves
* allocations/releases during the lookup process.
*
*/
#ifndef FTCMRU_H_
#define FTCMRU_H_
#include <freetype/freetype.h>
#include <freetype/internal/compiler-macros.h>
#ifdef FREETYPE_H
#error "freetype.h of FreeType 1 has been loaded!"
#error "Please fix the directory search order for header files"
#error "so that freetype.h of FreeType 2 is found first."
#endif
#define xxFT_DEBUG_ERROR
#define FTC_INLINE
FT_BEGIN_HEADER
typedef struct FTC_MruNodeRec_* FTC_MruNode;
typedef struct FTC_MruNodeRec_
{
FTC_MruNode next;
FTC_MruNode prev;
} FTC_MruNodeRec;
FT_LOCAL( void )
FTC_MruNode_Prepend( FTC_MruNode *plist,
FTC_MruNode node );
FT_LOCAL( void )
FTC_MruNode_Up( FTC_MruNode *plist,
FTC_MruNode node );
FT_LOCAL( void )
FTC_MruNode_Remove( FTC_MruNode *plist,
FTC_MruNode node );
typedef struct FTC_MruListRec_* FTC_MruList;
typedef struct FTC_MruListClassRec_ const * FTC_MruListClass;
typedef FT_Bool
(*FTC_MruNode_CompareFunc)( FTC_MruNode node,
FT_Pointer key );
typedef FT_Error
(*FTC_MruNode_InitFunc)( FTC_MruNode node,
FT_Pointer key,
FT_Pointer data );
typedef void
(*FTC_MruNode_DoneFunc)( FTC_MruNode node,
FT_Pointer data );
typedef struct FTC_MruListClassRec_
{
FT_Offset node_size;
FTC_MruNode_CompareFunc node_compare;
FTC_MruNode_InitFunc node_init;
FTC_MruNode_DoneFunc node_done;
} FTC_MruListClassRec;
typedef struct FTC_MruListRec_
{
FT_UInt num_nodes;
FT_UInt max_nodes;
FTC_MruNode nodes;
FT_Pointer data;
FTC_MruListClassRec clazz;
FT_Memory memory;
} FTC_MruListRec;
FT_LOCAL( void )
FTC_MruList_Init( FTC_MruList list,
FTC_MruListClass clazz,
FT_UInt max_nodes,
FT_Pointer data,
FT_Memory memory );
FT_LOCAL( void )
FTC_MruList_Reset( FTC_MruList list );
FT_LOCAL( void )
FTC_MruList_Done( FTC_MruList list );
FT_LOCAL( FT_Error )
FTC_MruList_New( FTC_MruList list,
FT_Pointer key,
FTC_MruNode *anode );
FT_LOCAL( void )
FTC_MruList_Remove( FTC_MruList list,
FTC_MruNode node );
FT_LOCAL( void )
FTC_MruList_RemoveSelection( FTC_MruList list,
FTC_MruNode_CompareFunc selection,
FT_Pointer key );
#ifdef FTC_INLINE
#define FTC_MRULIST_LOOKUP_CMP( list, key, compare, node, error ) \
FT_BEGIN_STMNT \
FTC_MruNode* _pfirst = &(list)->nodes; \
FTC_MruNode_CompareFunc _compare = (FTC_MruNode_CompareFunc)(compare); \
FTC_MruNode _first, _node; \
\
\
error = FT_Err_Ok; \
_first = *(_pfirst); \
_node = NULL; \
\
if ( _first ) \
{ \
_node = _first; \
do \
{ \
if ( _compare( _node, (key) ) ) \
{ \
if ( _node != _first ) \
FTC_MruNode_Up( _pfirst, _node ); \
\
node = _node; \
goto MruOk_; \
} \
_node = _node->next; \
\
} while ( _node != _first); \
} \
\
error = FTC_MruList_New( (list), (key), (FTC_MruNode*)(void*)&(node) ); \
MruOk_: \
; \
FT_END_STMNT
#define FTC_MRULIST_LOOKUP( list, key, node, error ) \
FTC_MRULIST_LOOKUP_CMP( list, key, (list)->clazz.node_compare, node, error )
#else /* !FTC_INLINE */
FT_LOCAL( FTC_MruNode )
FTC_MruList_Find( FTC_MruList list,
FT_Pointer key );
FT_LOCAL( FT_Error )
FTC_MruList_Lookup( FTC_MruList list,
FT_Pointer key,
FTC_MruNode *pnode );
#define FTC_MRULIST_LOOKUP( list, key, node, error ) \
error = FTC_MruList_Lookup( (list), (key), (FTC_MruNode*)&(node) )
#endif /* !FTC_INLINE */
#define FTC_MRULIST_LOOP( list, node ) \
FT_BEGIN_STMNT \
FTC_MruNode _first = (list)->nodes; \
\
\
if ( _first ) \
{ \
FTC_MruNode _node = _first; \
\
\
do \
{ \
*(FTC_MruNode*)&(node) = _node;
#define FTC_MRULIST_LOOP_END() \
_node = _node->next; \
\
} while ( _node != _first ); \
} \
FT_END_STMNT
/* */
FT_END_HEADER
#endif /* FTCMRU_H_ */
/* END */

413
thirdparty/freetype/src/cache/ftcsbits.c vendored Normal file
View File

@@ -0,0 +1,413 @@
/****************************************************************************
*
* ftcsbits.c
*
* FreeType sbits manager (body).
*
* Copyright (C) 2000-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include <freetype/ftcache.h>
#include "ftcsbits.h"
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/ftdebug.h>
#include <freetype/fterrors.h>
#include "ftccback.h"
#include "ftcerror.h"
#undef FT_COMPONENT
#define FT_COMPONENT cache
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** SBIT CACHE NODES *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
static FT_Error
ftc_sbit_copy_bitmap( FTC_SBit sbit,
FT_Bitmap* bitmap,
FT_Memory memory )
{
FT_Error error;
FT_Int pitch = bitmap->pitch;
FT_ULong size;
if ( pitch < 0 )
pitch = -pitch;
size = (FT_ULong)pitch * bitmap->rows;
FT_MEM_DUP( sbit->buffer, bitmap->buffer, size );
return error;
}
FT_LOCAL_DEF( void )
ftc_snode_free( FTC_Node ftcsnode,
FTC_Cache cache )
{
FTC_SNode snode = (FTC_SNode)ftcsnode;
FTC_SBit sbit = snode->sbits;
FT_UInt count = snode->count;
FT_Memory memory = cache->memory;
for ( ; count > 0; sbit++, count-- )
FT_FREE( sbit->buffer );
FTC_GNode_Done( FTC_GNODE( snode ), cache );
FT_FREE( snode );
}
FT_LOCAL_DEF( void )
FTC_SNode_Free( FTC_SNode snode,
FTC_Cache cache )
{
ftc_snode_free( FTC_NODE( snode ), cache );
}
/*
* This function tries to load a small bitmap within a given FTC_SNode.
* Note that it returns a non-zero error code _only_ in the case of
* out-of-memory condition. For all other errors (e.g., corresponding
* to a bad font file), this function will mark the sbit as `unavailable'
* and return a value of 0.
*
* You should also read the comment within the @ftc_snode_compare
* function below to see how out-of-memory is handled during a lookup.
*/
static FT_Error
ftc_snode_load( FTC_SNode snode,
FTC_Manager manager,
FT_UInt gindex,
FT_ULong *asize )
{
FT_Error error;
FTC_GNode gnode = FTC_GNODE( snode );
FTC_Family family = gnode->family;
FT_Face face;
FTC_SBit sbit;
FTC_SFamilyClass clazz;
if ( gindex - gnode->gindex >= snode->count )
{
FT_ERROR(( "ftc_snode_load: invalid glyph index" ));
return FT_THROW( Invalid_Argument );
}
sbit = snode->sbits + ( gindex - gnode->gindex );
clazz = (FTC_SFamilyClass)family->clazz;
error = clazz->family_load_glyph( family, gindex, manager, &face );
if ( error )
goto BadGlyph;
{
FT_Int temp;
FT_GlyphSlot slot = face->glyph;
FT_Bitmap* bitmap = &slot->bitmap;
FT_Pos xadvance, yadvance; /* FT_GlyphSlot->advance.{x|y} */
if ( slot->format != FT_GLYPH_FORMAT_BITMAP )
{
FT_TRACE0(( "ftc_snode_load:"
" glyph loaded didn't return a bitmap\n" ));
goto BadGlyph;
}
/* Check whether our values fit into 8/16-bit containers! */
/* If this is not the case, our bitmap is too large */
/* and we will leave it as `missing' with sbit.buffer = 0 */
#define CHECK_CHAR( d ) ( temp = (FT_Char)d, (FT_Int) temp == (FT_Int) d )
#define CHECK_BYTE( d ) ( temp = (FT_Byte)d, (FT_UInt)temp == (FT_UInt)d )
#define CHECK_SHRT( d ) ( temp = (FT_Short)d, (FT_Int)temp == (FT_Int) d )
/* horizontal advance in pixels */
xadvance = ( slot->advance.x + 32 ) >> 6;
yadvance = ( slot->advance.y + 32 ) >> 6;
if ( !CHECK_BYTE( bitmap->rows ) ||
!CHECK_BYTE( bitmap->width ) ||
!CHECK_SHRT( bitmap->pitch ) ||
!CHECK_CHAR( slot->bitmap_left ) ||
!CHECK_CHAR( slot->bitmap_top ) ||
!CHECK_CHAR( xadvance ) ||
!CHECK_CHAR( yadvance ) )
{
FT_TRACE2(( "ftc_snode_load:"
" glyph too large for small bitmap cache\n"));
goto BadGlyph;
}
sbit->width = (FT_Byte)bitmap->width;
sbit->height = (FT_Byte)bitmap->rows;
sbit->pitch = (FT_Short)bitmap->pitch;
sbit->left = (FT_Char)slot->bitmap_left;
sbit->top = (FT_Char)slot->bitmap_top;
sbit->xadvance = (FT_Char)xadvance;
sbit->yadvance = (FT_Char)yadvance;
sbit->format = (FT_Byte)bitmap->pixel_mode;
sbit->max_grays = (FT_Byte)( bitmap->num_grays - 1 );
if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
{
/* take the bitmap ownership */
sbit->buffer = bitmap->buffer;
slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
}
else
{
/* copy the bitmap into a new buffer -- ignore error */
error = ftc_sbit_copy_bitmap( sbit, bitmap, manager->memory );
}
/* now, compute size */
if ( asize )
*asize = (FT_ULong)FT_ABS( sbit->pitch ) * sbit->height;
} /* glyph loading successful */
/* ignore the errors that might have occurred -- */
/* we mark unloaded glyphs with `sbit.buffer == 0' */
/* and `width == 255', `height == 0' */
/* */
if ( error && FT_ERR_NEQ( error, Out_Of_Memory ) )
{
BadGlyph:
sbit->width = 255;
sbit->height = 0;
sbit->buffer = NULL;
error = FT_Err_Ok;
if ( asize )
*asize = 0;
}
return error;
}
FT_LOCAL_DEF( FT_Error )
FTC_SNode_New( FTC_SNode *psnode,
FTC_GQuery gquery,
FTC_Cache cache )
{
FT_Memory memory = cache->memory;
FT_Error error;
FTC_SNode snode = NULL;
FT_UInt gindex = gquery->gindex;
FTC_Family family = gquery->family;
FTC_SFamilyClass clazz = FTC_CACHE_SFAMILY_CLASS( cache );
FT_UInt total;
FT_UInt node_count;
total = clazz->family_get_count( family, cache->manager );
if ( total == 0 || gindex >= total )
{
error = FT_THROW( Invalid_Argument );
goto Exit;
}
if ( !FT_QNEW( snode ) )
{
FT_UInt count, start;
start = gindex - ( gindex % FTC_SBIT_ITEMS_PER_NODE );
count = total - start;
if ( count > FTC_SBIT_ITEMS_PER_NODE )
count = FTC_SBIT_ITEMS_PER_NODE;
FTC_GNode_Init( FTC_GNODE( snode ), start, family );
snode->count = count;
for ( node_count = 0; node_count < count; node_count++ )
{
snode->sbits[node_count].width = 255;
snode->sbits[node_count].height = 0;
snode->sbits[node_count].buffer = NULL;
}
error = ftc_snode_load( snode,
cache->manager,
gindex,
NULL );
if ( error )
{
FTC_SNode_Free( snode, cache );
snode = NULL;
}
}
Exit:
*psnode = snode;
return error;
}
FT_LOCAL_DEF( FT_Error )
ftc_snode_new( FTC_Node *ftcpsnode,
FT_Pointer ftcgquery,
FTC_Cache cache )
{
FTC_SNode *psnode = (FTC_SNode*)ftcpsnode;
FTC_GQuery gquery = (FTC_GQuery)ftcgquery;
return FTC_SNode_New( psnode, gquery, cache );
}
FT_LOCAL_DEF( FT_Offset )
ftc_snode_weight( FTC_Node ftcsnode,
FTC_Cache cache )
{
FTC_SNode snode = (FTC_SNode)ftcsnode;
FT_UInt count = snode->count;
FTC_SBit sbit = snode->sbits;
FT_Int pitch;
FT_Offset size;
FT_UNUSED( cache );
FT_ASSERT( snode->count <= FTC_SBIT_ITEMS_PER_NODE );
/* the node itself */
size = sizeof ( *snode );
for ( ; count > 0; count--, sbit++ )
{
if ( sbit->buffer )
{
pitch = sbit->pitch;
if ( pitch < 0 )
pitch = -pitch;
/* add the size of a given glyph image */
size += (FT_Offset)pitch * sbit->height;
}
}
return size;
}
#if 0
FT_LOCAL_DEF( FT_Offset )
FTC_SNode_Weight( FTC_SNode snode )
{
return ftc_snode_weight( FTC_NODE( snode ), NULL );
}
#endif /* 0 */
FT_LOCAL_DEF( FT_Bool )
ftc_snode_compare( FTC_Node ftcsnode,
FT_Pointer ftcgquery,
FTC_Cache cache,
FT_Bool* list_changed )
{
FTC_SNode snode = (FTC_SNode)ftcsnode;
FTC_GQuery gquery = (FTC_GQuery)ftcgquery;
FTC_GNode gnode = FTC_GNODE( snode );
FT_UInt gindex = gquery->gindex;
FT_Bool result;
if ( list_changed )
*list_changed = FALSE;
result = FT_BOOL( gnode->family == gquery->family &&
gindex - gnode->gindex < snode->count );
if ( result )
{
/* check if we need to load the glyph bitmap now */
FTC_SBit sbit = snode->sbits + ( gindex - gnode->gindex );
/*
* The following code illustrates what to do when you want to
* perform operations that may fail within a lookup function.
*
* Here, we want to load a small bitmap on-demand; we thus
* need to call the `ftc_snode_load' function which may return
* a non-zero error code only when we are out of memory (OOM).
*
* The correct thing to do is to use @FTC_CACHE_TRYLOOP and
* @FTC_CACHE_TRYLOOP_END in order to implement a retry loop
* that is capable of flushing the cache incrementally when
* an OOM errors occur.
*
* However, we need to `lock' the node before this operation to
* prevent it from being flushed within the loop.
*
* When we exit the loop, we unlock the node, then check the `error'
* variable. If it is non-zero, this means that the cache was
* completely flushed and that no usable memory was found to load
* the bitmap.
*
* We then prefer to return a value of 0 (i.e., NO MATCH). This
* ensures that the caller will try to allocate a new node.
* This operation consequently _fail_ and the lookup function
* returns the appropriate OOM error code.
*
* Note that `buffer == NULL && width == 255' is a hack used to
* tag `unavailable' bitmaps in the array. We should never try
* to load these.
*
*/
if ( !sbit->buffer && sbit->width == 255 )
{
FT_ULong size;
FT_Error error;
ftcsnode->ref_count++; /* lock node to prevent flushing */
/* in retry loop */
FTC_CACHE_TRYLOOP( cache )
{
error = ftc_snode_load( snode, cache->manager, gindex, &size );
}
FTC_CACHE_TRYLOOP_END( list_changed )
ftcsnode->ref_count--; /* unlock the node */
if ( error )
result = 0;
else
cache->manager->cur_weight += size;
}
}
return result;
}
/* END */

View File

@@ -0,0 +1,91 @@
/****************************************************************************
*
* ftcsbits.h
*
* A small-bitmap cache (specification).
*
* Copyright (C) 2000-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#ifndef FTCSBITS_H_
#define FTCSBITS_H_
#include <freetype/ftcache.h>
#include "ftcglyph.h"
FT_BEGIN_HEADER
#define FTC_SBIT_ITEMS_PER_NODE 16
typedef struct FTC_SNodeRec_
{
FTC_GNodeRec gnode;
FT_UInt count;
FTC_SBitRec sbits[FTC_SBIT_ITEMS_PER_NODE];
} FTC_SNodeRec, *FTC_SNode;
#define FTC_SNODE( x ) ( (FTC_SNode)( x ) )
#define FTC_SNODE_GINDEX( x ) FTC_GNODE( x )->gindex
#define FTC_SNODE_FAMILY( x ) FTC_GNODE( x )->family
typedef FT_UInt
(*FTC_SFamily_GetCountFunc)( FTC_Family family,
FTC_Manager manager );
typedef FT_Error
(*FTC_SFamily_LoadGlyphFunc)( FTC_Family family,
FT_UInt gindex,
FTC_Manager manager,
FT_Face *aface );
typedef struct FTC_SFamilyClassRec_
{
FTC_MruListClassRec clazz;
FTC_SFamily_GetCountFunc family_get_count;
FTC_SFamily_LoadGlyphFunc family_load_glyph;
} FTC_SFamilyClassRec;
typedef const FTC_SFamilyClassRec* FTC_SFamilyClass;
#define FTC_SFAMILY_CLASS( x ) ( (FTC_SFamilyClass)(x) )
#define FTC_CACHE_SFAMILY_CLASS( x ) \
FTC_SFAMILY_CLASS( FTC_CACHE_GCACHE_CLASS( x )->family_class )
FT_LOCAL( void )
FTC_SNode_Free( FTC_SNode snode,
FTC_Cache cache );
FT_LOCAL( FT_Error )
FTC_SNode_New( FTC_SNode *psnode,
FTC_GQuery gquery,
FTC_Cache cache );
#if 0
FT_LOCAL( FT_ULong )
FTC_SNode_Weight( FTC_SNode inode );
#endif
/* */
FT_END_HEADER
#endif /* FTCSBITS_H_ */
/* END */

28
thirdparty/freetype/src/cff/cff.c vendored Normal file
View File

@@ -0,0 +1,28 @@
/****************************************************************************
*
* cff.c
*
* FreeType OpenType driver component (body only).
*
* Copyright (C) 1996-2024 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#define FT_MAKE_OPTION_SINGLE_OBJECT
#include "cffcmap.c"
#include "cffdrivr.c"
#include "cffgload.c"
#include "cffparse.c"
#include "cffload.c"
#include "cffobjs.c"
/* END */

Some files were not shown because too many files have changed in this diff Show More