diff options
author | Behdad Esfahbod <behdad@google.com> | 2014-08-08 17:55:11 -0400 |
---|---|---|
committer | Behdad Esfahbod <behdad@google.com> | 2014-08-08 17:59:36 -0400 |
commit | 9c745321260bb728ab1cd1c8fd5f075854b2ad49 (patch) | |
tree | 86c9ee0214cac2870a94905e4240732413ed768b /src/autofit | |
parent | ec0bab5697bb31ba980810145f62e3799946ec60 (diff) | |
download | android_external_freetype-staging/cm-12.0-caf.tar.gz android_external_freetype-staging/cm-12.0-caf.tar.bz2 android_external_freetype-staging/cm-12.0-caf.zip |
Update freetype to e1394d56752cac3bd68ab2358a8e1384ce7b9aaastaging/cm-12.0-cafstaging/cm-12.0
Integrated patches from freetype2 git repository, up to hashval
e1394d56752cac3bd68ab2358a8e1384ce7b9aaa, which is post-2.5.3.
Most recent commit message from freetype git:
Minor documentation improvement.
Noteworthy patches included:
Fix Savannah bug #41697, part 2.
Fix Savannah bug #41697, part 1.
Bug: 16575323
Change-Id: I4f8f9375afd2540618b3ebf6152d77b743975dce
Diffstat (limited to 'src/autofit')
35 files changed, 2800 insertions, 1015 deletions
diff --git a/src/autofit/afblue.c b/src/autofit/afblue.c index 22ef6d5..f3526bf 100644 --- a/src/autofit/afblue.c +++ b/src/autofit/afblue.c @@ -26,15 +26,21 @@ af_blue_strings[] = { /* */ - 'T', 'H', 'E', 'Z', 'O', 'C', 'Q', 'S', /* THEZOCQS */ + '\xD0', '\x91', '\xD0', '\x92', '\xD0', '\x95', '\xD0', '\x9F', '\xD0', '\x97', '\xD0', '\x9E', '\xD0', '\xA1', '\xD0', '\xAD', /* БВЕПЗОСЭ */ '\0', - 'H', 'E', 'Z', 'L', 'O', 'C', 'U', 'S', /* HEZLOCUS */ + '\xD0', '\x91', '\xD0', '\x92', '\xD0', '\x95', '\xD0', '\xA8', '\xD0', '\x97', '\xD0', '\x9E', '\xD0', '\xA1', '\xD0', '\xAD', /* БВЕШЗОСЭ */ '\0', - 'f', 'i', 'j', 'k', 'd', 'b', 'h', /* fijkdbh */ + '\xD1', '\x85', '\xD0', '\xBF', '\xD0', '\xBD', '\xD1', '\x88', '\xD0', '\xB5', '\xD0', '\xB7', '\xD0', '\xBE', '\xD1', '\x81', /* хпншезос */ '\0', - 'x', 'z', 'r', 'o', 'e', 's', 'c', /* xzroesc */ + '\xD1', '\x80', '\xD1', '\x83', '\xD1', '\x84', /* руф */ '\0', - 'p', 'q', 'g', 'j', 'y', /* pqgjy */ + '\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', '\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', '\xCE', '\x93', '\xCE', '\x92', '\xCE', '\x95', '\xCE', '\x96', '\xCE', '\x98', '\xCE', '\x9F', '\xCE', '\xA9', /* ΓΒΕΖΘΟΩ */ '\0', @@ -46,26 +52,27 @@ '\0', '\xCE', '\xB2', '\xCE', '\xB3', '\xCE', '\xB7', '\xCE', '\xBC', '\xCF', '\x81', '\xCF', '\x86', '\xCF', '\x87', '\xCF', '\x88', /* βγημρφχψ */ '\0', - '\xD0', '\x91', '\xD0', '\x92', '\xD0', '\x95', '\xD0', '\x9F', '\xD0', '\x97', '\xD0', '\x9E', '\xD0', '\xA1', '\xD0', '\xAD', /* БВЕПЗОСЭ */ + '\xD7', '\x91', '\xD7', '\x93', '\xD7', '\x94', '\xD7', '\x97', '\xD7', '\x9A', '\xD7', '\x9B', '\xD7', '\x9D', '\xD7', '\xA1', /* בדהחךכםס */ '\0', - '\xD0', '\x91', '\xD0', '\x92', '\xD0', '\x95', '\xD0', '\xA8', '\xD0', '\x97', '\xD0', '\x9E', '\xD0', '\xA1', '\xD0', '\xAD', /* БВЕШЗОСЭ */ + '\xD7', '\x91', '\xD7', '\x98', '\xD7', '\x9B', '\xD7', '\x9D', '\xD7', '\xA1', '\xD7', '\xA6', /* בטכםסצ */ '\0', - '\xD1', '\x85', '\xD0', '\xBF', '\xD0', '\xBD', '\xD1', '\x88', '\xD0', '\xB5', '\xD0', '\xB7', '\xD0', '\xBE', '\xD1', '\x81', /* хпншезос */ + '\xD7', '\xA7', '\xD7', '\x9A', '\xD7', '\x9F', '\xD7', '\xA3', '\xD7', '\xA5', /* קךןףץ */ '\0', - '\xD1', '\x80', '\xD1', '\x83', '\xD1', '\x84', /* руф */ + 'T', 'H', 'E', 'Z', 'O', 'C', 'Q', 'S', /* THEZOCQS */ '\0', - '\xD7', '\x91', '\xD7', '\x93', '\xD7', '\x94', '\xD7', '\x97', '\xD7', '\x9A', '\xD7', '\x9B', '\xD7', '\x9D', '\xD7', '\xA1', /* בדהחךכםס */ + 'H', 'E', 'Z', 'L', 'O', 'C', 'U', 'S', /* HEZLOCUS */ '\0', - '\xD7', '\x91', '\xD7', '\x98', '\xD7', '\x9B', '\xD7', '\x9D', '\xD7', '\xA1', '\xD7', '\xA6', /* בטכםסצ */ + 'f', 'i', 'j', 'k', 'd', 'b', 'h', /* fijkdbh */ '\0', - '\xD7', '\xA7', '\xD7', '\x9A', '\xD7', '\x9F', '\xD7', '\xA3', '\xD7', '\xA5', /* קךןףץ */ + 'x', 'z', 'r', 'o', 'e', 's', 'c', /* xzroesc */ + '\0', + 'p', 'q', 'g', 'j', 'y', /* pqgjy */ #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', /* 齊 */ - '\0', + '\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', /* 軍那配里開雷露面 */ @@ -74,8 +81,7 @@ '\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', /* 说 */ - '\0', + '\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', /* 过还进進過道還里 */ @@ -85,8 +91,7 @@ '\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', /* 通 */ - '\0', + '\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', /* 间际陈限除陳随際 */ @@ -95,8 +100,7 @@ '\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', /* 起 */ - '\0', + '\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', /* 种調调費费那都間 */ @@ -108,19 +112,26 @@ }; - /* stringsets are specific to scripts */ + /* stringsets are specific to styles */ FT_LOCAL_ARRAY_DEF( AF_Blue_StringRec ) af_blue_stringsets[] = { /* */ - { 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, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, - { AF_BLUE_STRING_LATIN_SMALL, 0 }, - { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 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_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 }, @@ -129,35 +140,28 @@ { AF_BLUE_STRING_GREEK_SMALL, 0 }, { AF_BLUE_STRING_GREEK_SMALL_DESCENDER, 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_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_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, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_LATIN_SMALL, 0 }, + { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0 }, + { AF_BLUE_STRING_MAX, 0 }, #ifdef AF_CONFIG_OPTION_CJK - { AF_BLUE_STRING_CJK_TOP_FILL, AF_BLUE_PROPERTY_CJK_TOP | - AF_BLUE_PROPERTY_CJK_FILL }, - { AF_BLUE_STRING_CJK_TOP_UNFILL, AF_BLUE_PROPERTY_CJK_TOP }, - { AF_BLUE_STRING_CJK_BOTTOM_FILL, AF_BLUE_PROPERTY_CJK_FILL }, - { AF_BLUE_STRING_CJK_BOTTOM_UNFILL, 0 }, + { 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_FILL, AF_BLUE_PROPERTY_CJK_HORIZ | - AF_BLUE_PROPERTY_CJK_FILL }, - { AF_BLUE_STRING_CJK_LEFT_UNFILL, AF_BLUE_PROPERTY_CJK_HORIZ }, - { AF_BLUE_STRING_CJK_RIGHT_FILL, AF_BLUE_PROPERTY_CJK_HORIZ | - AF_BLUE_PROPERTY_CJK_RIGHT | - AF_BLUE_PROPERTY_CJK_FILL }, - { AF_BLUE_STRING_CJK_RIGHT_UNFILL, AF_BLUE_PROPERTY_CJK_HORIZ | - AF_BLUE_PROPERTY_CJK_RIGHT }, + { 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 }, + { AF_BLUE_STRING_MAX, 0 }, #endif /* AF_CONFIG_OPTION_CJK */ }; diff --git a/src/autofit/afblue.cin b/src/autofit/afblue.cin index c693d89..c6762be 100644 --- a/src/autofit/afblue.cin +++ b/src/autofit/afblue.cin @@ -27,7 +27,7 @@ }; - /* stringsets are specific to scripts */ + /* stringsets are specific to styles */ FT_LOCAL_ARRAY_DEF( AF_Blue_StringRec ) af_blue_stringsets[] = { diff --git a/src/autofit/afblue.dat b/src/autofit/afblue.dat index d488f3f..74a472d 100644 --- a/src/autofit/afblue.dat +++ b/src/autofit/afblue.dat @@ -2,7 +2,7 @@ // // Auto-fitter data for blue strings. // -// Copyright 2013 by +// Copyright 2013, 2014 by // David Turner, Robert Wilhelm, and Werner Lemberg. // // This file is part of the FreeType project, and may only be used, @@ -34,11 +34,11 @@ // using C syntax. There can be only one string per line, thus the // starting and ending double quote must be the first and last character // in the line, respectively, ignoring whitespace before and after the -// string. If there are multiple strings (in multiple lines), they are -// concatenated to a single string. In the output, a string gets -// represented as a series of singles bytes, followed by a zero byte. The -// enumeration values simply hold byte offsets to the start of the -// corresponding strings. +// string. Space characters within the string are ignored too. If there +// are multiple strings (in multiple lines), they are concatenated to a +// single string. In the output, a string gets represented as a series of +// singles bytes, followed by a zero byte. The enumeration values simply +// hold byte offsets to the start of the corresponding strings. // // - Data blocks enclosed in balanced braces, which get copied verbatim and // which can span multiple lines. The opening brace of a block must be @@ -63,18 +63,32 @@ // characters, not bytes. +// The blue zone string data, to be used in the blue stringsets below. + AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: - AF_BLUE_STRING_LATIN_CAPITAL_TOP - "THEZOCQS" - AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM - "HEZLOCUS" - AF_BLUE_STRING_LATIN_SMALL_F_TOP - "fijkdbh" - AF_BLUE_STRING_LATIN_SMALL - "xzroesc" - AF_BLUE_STRING_LATIN_SMALL_DESCENDER - "pqgjy" + AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP + "БВЕПЗОСЭ" + AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM + "БВЕШЗОСЭ" + AF_BLUE_STRING_CYRILLIC_SMALL + "хпншезос" + AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER + "руф" + + // we separate the letters with spaces to avoid ligatures; + // this is just for convenience to simplify reading + AF_BLUE_STRING_DEVANAGARI_BASE + "क म अ आ थ ध भ श" + AF_BLUE_STRING_DEVANAGARI_TOP + "ई ऐ ओ औ ि ी ो ौ" + // note that some fonts have extreme variation in the height of the + // round head elements; for this reason we also define the `base' + // blue zone, which must be always present + AF_BLUE_STRING_DEVANAGARI_HEAD + "क म अ आ थ ध भ श" + AF_BLUE_STRING_DEVANAGARI_BOTTOM + "ु ृ" AF_BLUE_STRING_GREEK_CAPITAL_TOP "ΓΒΕΖΘΟΩ" @@ -87,15 +101,6 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: AF_BLUE_STRING_GREEK_SMALL_DESCENDER "βγημρφχψ" - AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP - "БВЕПЗОСЭ" - AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM - "БВЕШЗОСЭ" - AF_BLUE_STRING_CYRILLIC_SMALL - "хпншезос" - AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER - "руф" - AF_BLUE_STRING_HEBREW_TOP "בדהחךכםס" AF_BLUE_STRING_HEBREW_BOTTOM @@ -103,24 +108,33 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: AF_BLUE_STRING_HEBREW_DESCENDER "קךןףץ" + AF_BLUE_STRING_LATIN_CAPITAL_TOP + "THEZOCQS" + AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM + "HEZLOCUS" + AF_BLUE_STRING_LATIN_SMALL_F_TOP + "fijkdbh" + AF_BLUE_STRING_LATIN_SMALL + "xzroesc" + AF_BLUE_STRING_LATIN_SMALL_DESCENDER + "pqgjy" + #ifdef AF_CONFIG_OPTION_CJK - AF_BLUE_STRING_CJK_TOP_FILL + AF_BLUE_STRING_CJK_TOP "他们你來們到和地" "对對就席我时時會" "来為能舰說说这這" - "齊" - AF_BLUE_STRING_CJK_TOP_UNFILL + "齊 |" "军同已愿既星是景" "民照现現理用置要" "軍那配里開雷露面" "顾" - AF_BLUE_STRING_CJK_BOTTOM_FILL + AF_BLUE_STRING_CJK_BOTTOM "个为人他以们你來" "個們到和大对對就" "我时時有来為要說" - "说" - AF_BLUE_STRING_CJK_BOTTOM_UNFILL + "说 |" "主些因它想意理生" "當看着置者自著裡" "过还进進過道還里" @@ -128,22 +142,20 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: #ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT - AF_BLUE_STRING_CJK_LEFT_FILL + AF_BLUE_STRING_CJK_LEFT "些们你來們到和地" "她将將就年得情最" "样樣理能說说这這" - "通" - AF_BLUE_STRING_CJK_LEFT_UNFILL + "通 |" "即吗吧听呢品响嗎" "师師收断斷明眼間" "间际陈限除陳随際" "隨" - AF_BLUE_STRING_CJK_RIGHT_FILL + AF_BLUE_STRING_CJK_RIGHT "事前學将將情想或" "政斯新样樣民沒没" "然特现現球第經谁" - "起" - AF_BLUE_STRING_CJK_RIGHT_UNFILL + "起 |" "例別别制动動吗嗎" "增指明朝期构物确" "种調调費费那都間" @@ -154,17 +166,118 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: #endif /* AF_CONFIG_OPTION_CJK */ +// The blue zone stringsets, as used in the script styles, cf. `afstyles.h'. +// +// The AF_BLUE_PROPERTY_XXX flags are defined in `afblue.h'; here some +// explanations. +// +// A blue zone in general is defined by a reference and an overshoot line. +// During the hinting process, all coordinate values between those two lines +// are set equal to the reference value, provided that the blue zone is not +// wider than 0.75 pixels (otherwise the blue zone gets ignored). All +// entries must have `AF_BLUE_STRING_MAX' as the final line. +// +// During the glyph analysis, edges are sorted from bottom to top, and then +// sequentially checked, edge by edge, against the blue zones in the order +// given below. +// +// +// latin auto-hinter +// ----------------- +// +// Characters in a blue string are automatically classified as having a flat +// (reference) or a round (overshoot) extremum. The blue zone is then set +// up by the mean values of all flat extrema and all round extrema, +// respectively. Only horizontal blue zones (i.e., adjusting vertical +// coordinate values) are supported. +// +// For the latin auto-hinter, the overshoot should be larger than the +// reference for top zones, and vice versa for bottom zones. +// +// LATIN_TOP +// Take the maximum flat and round coordinate values of the blue string +// characters for computing the blue zone's reference and overshoot +// values. +// +// If not set, take the minimum values. +// +// LATIN_NEUTRAL +// Ignore round extrema and define the blue zone with flat values only. +// Both top and bottom of contours can match. This is useful for +// scripts like Devanagari where vowel signs attach to the base +// character and are implemented as components of composite glyphs. +// +// If not set, both round and flat extrema are taken into account. +// Additionally, only the top or the bottom of a contour can match, +// depending on the LATIN_TOP flag. +// +// Neutral blue zones should always follow non-neutral blue zones. +// +// LATIN_X_HEIGHT +// Scale all glyphs vertically from the corresponding script to make the +// reference line of this blue zone align on the grid. The scaling +// takes place before all other blue zones get aligned to the grid. +// Only one blue character string of a script style can have this flag. +// +// LATIN_LONG +// Apply an additional constraint for blue zone values: Don't +// necessarily use the extremum as-is but a segment of the topmost (or +// bottommost) contour that is longer than a heuristic threshold, and +// which is not too far away vertically from the real extremum. This +// ensures that small bumps in the outline are ignored (for example, the +// `vertical serifs' found in many Hebrew glyph designs). +// +// The segment must be at least EM/25 font units long, and the distance +// to the extremum must be smaller than EM/4. +// +// +// cjk auto-hinter +// --------------- +// +// Characters in a blue string are *not* automatically classified. Instead, +// first come the characters used for the overshoot value, then the +// character `|', then the characters used for the reference value. The +// blue zone is then set up by the mean values of all reference values and +// all overshoot values, respectively. Both horizontal and vertical blue +// zones (i.e., adjusting vertical and horizontal coordinate values, +// respectively) are supported. +// +// For the cjk auto-hinter, the overshoot should be smaller than the +// reference for top zones, and vice versa for bottom zones. +// +// CJK_TOP +// Take the maximum flat and round coordinate values of the blue string +// characters. If not set, take the minimum values. +// +// CJK_RIGHT +// A synonym for CJK_TOP. If CJK_HORIZ is set, this flag indicates the +// right blue zone, taking horizontal maximum values. +// +// CJK_HORIZ +// Define a blue zone for horizontal hinting (i.e., vertical blue +// zones). If not set, this is a blue zone for vertical hinting. + + AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: - AF_BLUE_STRINGSET_LATN - { 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, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT } - { AF_BLUE_STRING_LATIN_SMALL, 0 } - { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0 } - { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_CYRL + { 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_STRINGSET_DEVA + { 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_STRINGSET_GREK { AF_BLUE_STRING_GREEK_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } @@ -176,15 +289,6 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_GREEK_SMALL_DESCENDER, 0 } { AF_BLUE_STRING_MAX, 0 } - AF_BLUE_STRINGSET_CYRL - { 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_STRINGSET_HEBR { AF_BLUE_STRING_HEBREW_TOP, AF_BLUE_PROPERTY_LATIN_TOP | AF_BLUE_PROPERTY_LATIN_LONG } @@ -192,25 +296,27 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_HEBREW_DESCENDER, 0 } { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_LATN + { 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, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_LATIN_SMALL, 0 } + { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0 } + { AF_BLUE_STRING_MAX, 0 } + #ifdef AF_CONFIG_OPTION_CJK AF_BLUE_STRINGSET_HANI - { AF_BLUE_STRING_CJK_TOP_FILL, AF_BLUE_PROPERTY_CJK_TOP | - AF_BLUE_PROPERTY_CJK_FILL } - { AF_BLUE_STRING_CJK_TOP_UNFILL, AF_BLUE_PROPERTY_CJK_TOP } - { AF_BLUE_STRING_CJK_BOTTOM_FILL, AF_BLUE_PROPERTY_CJK_FILL } - { AF_BLUE_STRING_CJK_BOTTOM_UNFILL, 0 } + { 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_FILL, AF_BLUE_PROPERTY_CJK_HORIZ | - AF_BLUE_PROPERTY_CJK_FILL } - { AF_BLUE_STRING_CJK_LEFT_UNFILL, AF_BLUE_PROPERTY_CJK_HORIZ } - { AF_BLUE_STRING_CJK_RIGHT_FILL, AF_BLUE_PROPERTY_CJK_HORIZ | - AF_BLUE_PROPERTY_CJK_RIGHT | - AF_BLUE_PROPERTY_CJK_FILL } - { AF_BLUE_STRING_CJK_RIGHT_UNFILL, AF_BLUE_PROPERTY_CJK_HORIZ | - AF_BLUE_PROPERTY_CJK_RIGHT } + { 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 } + { AF_BLUE_STRING_MAX, 0 } #endif /* AF_CONFIG_OPTION_CJK */ diff --git a/src/autofit/afblue.h b/src/autofit/afblue.h index 86a3649..d239e8e 100644 --- a/src/autofit/afblue.h +++ b/src/autofit/afblue.h @@ -7,7 +7,7 @@ /* */ /* Auto-fitter data for blue strings (specification). */ /* */ -/* Copyright 2013 by */ +/* Copyright 2013, 2014 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -67,49 +67,49 @@ FT_BEGIN_HEADER /* At the bottommost level, we define strings for finding blue zones. */ -#define AF_BLUE_STRING_MAX_LEN 25 +#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_LATIN_CAPITAL_TOP = 0, - AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM = 9, - AF_BLUE_STRING_LATIN_SMALL_F_TOP = 18, - AF_BLUE_STRING_LATIN_SMALL = 26, - AF_BLUE_STRING_LATIN_SMALL_DESCENDER = 34, - AF_BLUE_STRING_GREEK_CAPITAL_TOP = 40, - AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM = 55, - AF_BLUE_STRING_GREEK_SMALL_BETA_TOP = 68, - AF_BLUE_STRING_GREEK_SMALL = 81, - AF_BLUE_STRING_GREEK_SMALL_DESCENDER = 98, - AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP = 115, - AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM = 132, - AF_BLUE_STRING_CYRILLIC_SMALL = 149, - AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER = 166, - AF_BLUE_STRING_HEBREW_TOP = 173, - AF_BLUE_STRING_HEBREW_BOTTOM = 190, - AF_BLUE_STRING_HEBREW_DESCENDER = 203, - af_blue_1_1 = 213, + AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP = 0, + AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM = 17, + AF_BLUE_STRING_CYRILLIC_SMALL = 34, + AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER = 51, + AF_BLUE_STRING_DEVANAGARI_BASE = 58, + AF_BLUE_STRING_DEVANAGARI_TOP = 83, + AF_BLUE_STRING_DEVANAGARI_HEAD = 108, + AF_BLUE_STRING_DEVANAGARI_BOTTOM = 133, + AF_BLUE_STRING_GREEK_CAPITAL_TOP = 140, + AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM = 155, + AF_BLUE_STRING_GREEK_SMALL_BETA_TOP = 168, + AF_BLUE_STRING_GREEK_SMALL = 181, + AF_BLUE_STRING_GREEK_SMALL_DESCENDER = 198, + AF_BLUE_STRING_HEBREW_TOP = 215, + AF_BLUE_STRING_HEBREW_BOTTOM = 232, + AF_BLUE_STRING_HEBREW_DESCENDER = 245, + AF_BLUE_STRING_LATIN_CAPITAL_TOP = 256, + AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM = 265, + AF_BLUE_STRING_LATIN_SMALL_F_TOP = 274, + AF_BLUE_STRING_LATIN_SMALL = 282, + AF_BLUE_STRING_LATIN_SMALL_DESCENDER = 290, + af_blue_1_1 = 295, #ifdef AF_CONFIG_OPTION_CJK - AF_BLUE_STRING_CJK_TOP_FILL = af_blue_1_1 + 1, - AF_BLUE_STRING_CJK_TOP_UNFILL = af_blue_1_1 + 77, - AF_BLUE_STRING_CJK_BOTTOM_FILL = af_blue_1_1 + 153, - AF_BLUE_STRING_CJK_BOTTOM_UNFILL = af_blue_1_1 + 229, + AF_BLUE_STRING_CJK_TOP = af_blue_1_1 + 1, + AF_BLUE_STRING_CJK_BOTTOM = af_blue_1_1 + 153, af_blue_1_1_1 = af_blue_1_1 + 304, #ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT - AF_BLUE_STRING_CJK_LEFT_FILL = af_blue_1_1_1 + 1, - AF_BLUE_STRING_CJK_LEFT_UNFILL = af_blue_1_1_1 + 77, - AF_BLUE_STRING_CJK_RIGHT_FILL = af_blue_1_1_1 + 153, - AF_BLUE_STRING_CJK_RIGHT_UNFILL = af_blue_1_1_1 + 229, - af_blue_1_2_1 = af_blue_1_1_1 + 304, + AF_BLUE_STRING_CJK_LEFT = af_blue_1_1_1 + 1, + AF_BLUE_STRING_CJK_RIGHT = af_blue_1_1_1 + 153, + af_blue_1_1_2 = af_blue_1_1_1 + 304, #else - af_blue_1_2_1 = af_blue_1_1_1 + 0, + 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_2_1 + 0, + af_blue_1_2 = af_blue_1_1_2 + 0, #else - af_blue_1_2 = af_blue_1_2_1 + 0, + af_blue_1_2 = af_blue_1_1 + 0, #endif /* AF_CONFIG_OPTION_CJK */ @@ -130,45 +130,46 @@ FT_BEGIN_HEADER /*************************************************************************/ /*************************************************************************/ - /* The next level is to group blue strings into script-specific sets. */ + /* 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 ( 1 << 0 ) -#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1 << 1 ) -#define AF_BLUE_PROPERTY_LATIN_LONG ( 1 << 2 ) +#define AF_BLUE_PROPERTY_LATIN_TOP ( 1 << 0 ) /* must have value 1 */ +#define AF_BLUE_PROPERTY_LATIN_NEUTRAL ( 1 << 1 ) +#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1 << 2 ) +#define AF_BLUE_PROPERTY_LATIN_LONG ( 1 << 3 ) -#define AF_BLUE_PROPERTY_CJK_HORIZ ( 1 << 0 ) -#define AF_BLUE_PROPERTY_CJK_TOP ( 1 << 1 ) -#define AF_BLUE_PROPERTY_CJK_FILL ( 1 << 2 ) +#define AF_BLUE_PROPERTY_CJK_TOP ( 1 << 0 ) /* must have value 1 */ +#define AF_BLUE_PROPERTY_CJK_HORIZ ( 1 << 1 ) /* must have value 2 */ #define AF_BLUE_PROPERTY_CJK_RIGHT AF_BLUE_PROPERTY_CJK_TOP -#define AF_BLUE_STRINGSET_MAX_LEN 9 +#define AF_BLUE_STRINGSET_MAX_LEN 7 /* The AF_Blue_Stringset enumeration values are offsets into the */ /* `af_blue_stringsets' array. */ typedef enum AF_Blue_Stringset_ { - AF_BLUE_STRINGSET_LATN = 0, - AF_BLUE_STRINGSET_GREK = 7, - AF_BLUE_STRINGSET_CYRL = 14, - AF_BLUE_STRINGSET_HEBR = 20, - af_blue_2_1 = 24, + AF_BLUE_STRINGSET_CYRL = 0, + AF_BLUE_STRINGSET_DEVA = 6, + AF_BLUE_STRINGSET_GREK = 12, + AF_BLUE_STRINGSET_HEBR = 19, + AF_BLUE_STRINGSET_LATN = 23, + af_blue_2_1 = 30, #ifdef AF_CONFIG_OPTION_CJK AF_BLUE_STRINGSET_HANI = af_blue_2_1 + 0, - af_blue_2_1_1 = af_blue_2_1 + 4, + af_blue_2_1_1 = af_blue_2_1 + 2, #ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT - af_blue_2_2_1 = af_blue_2_1_1 + 4, + af_blue_2_1_2 = af_blue_2_1_1 + 2, #else - af_blue_2_2_1 = af_blue_2_1_1 + 0, + 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_2_1 + 1, + af_blue_2_2 = af_blue_2_1_2 + 1, #else - af_blue_2_2 = af_blue_2_2_1 + 0, + af_blue_2_2 = af_blue_2_1 + 0, #endif /* AF_CONFIG_OPTION_CJK */ diff --git a/src/autofit/afblue.hin b/src/autofit/afblue.hin index 00282c3..0b4b48d 100644 --- a/src/autofit/afblue.hin +++ b/src/autofit/afblue.hin @@ -4,7 +4,7 @@ /* */ /* Auto-fitter data for blue strings (specification). */ /* */ -/* Copyright 2013 by */ +/* Copyright 2013, 2014 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -90,19 +90,19 @@ FT_BEGIN_HEADER /*************************************************************************/ /*************************************************************************/ - /* The next level is to group blue strings into script-specific sets. */ + /* 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 ( 1 << 0 ) -#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1 << 1 ) -#define AF_BLUE_PROPERTY_LATIN_LONG ( 1 << 2 ) +#define AF_BLUE_PROPERTY_LATIN_TOP ( 1 << 0 ) /* must have value 1 */ +#define AF_BLUE_PROPERTY_LATIN_NEUTRAL ( 1 << 1 ) +#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1 << 2 ) +#define AF_BLUE_PROPERTY_LATIN_LONG ( 1 << 3 ) -#define AF_BLUE_PROPERTY_CJK_HORIZ ( 1 << 0 ) -#define AF_BLUE_PROPERTY_CJK_TOP ( 1 << 1 ) -#define AF_BLUE_PROPERTY_CJK_FILL ( 1 << 2 ) +#define AF_BLUE_PROPERTY_CJK_TOP ( 1 << 0 ) /* must have value 1 */ +#define AF_BLUE_PROPERTY_CJK_HORIZ ( 1 << 1 ) /* must have value 2 */ #define AF_BLUE_PROPERTY_CJK_RIGHT AF_BLUE_PROPERTY_CJK_TOP diff --git a/src/autofit/afcjk.c b/src/autofit/afcjk.c index 7a6f835..ca7acca 100644 --- a/src/autofit/afcjk.c +++ b/src/autofit/afcjk.c @@ -2,9 +2,9 @@ /* */ /* afcjk.c */ /* */ -/* Auto-fitter hinting routines for CJK script (body). */ +/* Auto-fitter hinting routines for CJK writing system (body). */ /* */ -/* Copyright 2006-2013 by */ +/* Copyright 2006-2014 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -27,6 +27,7 @@ #include FT_INTERNAL_DEBUG_H #include "afglobal.h" +#include "afpic.h" #include "aflatin.h" @@ -74,10 +75,10 @@ FT_TRACE5(( "\n" - "cjk standard widths computation (script `%s')\n" - "===============================================\n" + "cjk standard widths computation (style `%s')\n" + "===================================================\n" "\n", - af_script_names[metrics->root.script_class->script] )); + af_style_names[metrics->root.style_class->style] )); af_glyph_hints_init( hints, face->memory ); @@ -86,20 +87,59 @@ { FT_Error error; - FT_UInt glyph_index; + FT_ULong glyph_index; + FT_Long y_offset; int dim; AF_CJKMetricsRec dummy[1]; AF_Scaler scaler = &dummy->root.scaler; +#ifdef FT_CONFIG_OPTION_PIC + AF_FaceGlobals globals = metrics->root.globals; +#endif - glyph_index = FT_Get_Char_Index( - face, - metrics->root.script_class->standard_char ); - if ( glyph_index == 0 ) - goto Exit; + AF_StyleClass style_class = metrics->root.style_class; + AF_ScriptClass script_class = AF_SCRIPT_CLASSES_GET + [style_class->script]; + + FT_UInt32 standard_char; + + + standard_char = script_class->standard_char1; + af_get_char_index( &metrics->root, + standard_char, + &glyph_index, + &y_offset ); + if ( !glyph_index ) + { + if ( script_class->standard_char2 ) + { + standard_char = script_class->standard_char2; + af_get_char_index( &metrics->root, + standard_char, + &glyph_index, + &y_offset ); + if ( !glyph_index ) + { + if ( script_class->standard_char3 ) + { + standard_char = script_class->standard_char3; + af_get_char_index( &metrics->root, + standard_char, + &glyph_index, + &y_offset ); + if ( !glyph_index ) + goto Exit; + } + else + goto Exit; + } + } + else + goto Exit; + } FT_TRACE5(( "standard character: U+%04lX (glyph index %d)\n", - metrics->root.script_class->standard_char, glyph_index )); + standard_char, glyph_index )); error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE ); if ( error || face->glyph->outline.n_points <= 0 ) @@ -118,7 +158,7 @@ scaler->render_mode = FT_RENDER_MODE_NORMAL; scaler->flags = 0; - af_glyph_hints_rescale( hints, (AF_ScriptMetrics)dummy ); + af_glyph_hints_rescale( hints, (AF_StyleMetrics)dummy ); error = af_glyph_hints_reload( hints, &face->glyph->outline ); if ( error ) @@ -138,6 +178,8 @@ goto Exit; af_latin_hints_link_segments( hints, + 0, + NULL, (AF_Dimension)dim ); seg = axhints->segments; @@ -221,34 +263,22 @@ FT_Int num_fills; FT_Int num_flats; + FT_Bool fill; + AF_CJKBlue blue; FT_Error error; AF_CJKAxis axis; FT_Outline outline; - AF_Blue_Stringset bss = metrics->root.script_class->blue_stringset; - const AF_Blue_StringRec* bs = &af_blue_stringsets[bss]; + AF_StyleClass sc = metrics->root.style_class; -#ifdef FT_DEBUG_LEVEL_TRACE - FT_String* cjk_blue_name[4] = - { - (FT_String*)"bottom", /* -- , -- */ - (FT_String*)"top", /* -- , TOP */ - (FT_String*)"left", /* HORIZ, -- */ - (FT_String*)"right" /* HORIZ, TOP */ - }; - - FT_String* cjk_blue_type_name[2] = - { - (FT_String*)"unfilled", /* -- */ - (FT_String*)"filled" /* FILL */ - }; -#endif + AF_Blue_Stringset bss = sc->blue_stringset; + const AF_Blue_StringRec* bs = &af_blue_stringsets[bss]; - /* we walk over the blue character strings as specified in the */ - /* script's entry in the `af_blue_stringset' array, computing its */ - /* extremum points (depending on the string properties) */ + /* we walk over the blue character strings as specified in the */ + /* style's entry in the `af_blue_stringset' array, computing its */ + /* extremum points (depending on the string properties) */ FT_TRACE5(( "cjk blue zones computation\n" "==========================\n" @@ -266,20 +296,35 @@ else axis = &metrics->axis[AF_DIMENSION_VERT]; - FT_TRACE5(( "blue zone %d:\n", axis->blue_count )); +#ifdef FT_DEBUG_LEVEL_TRACE + { + FT_String* cjk_blue_name[4] = + { + (FT_String*)"bottom", /* -- , -- */ + (FT_String*)"top", /* -- , TOP */ + (FT_String*)"left", /* HORIZ, -- */ + (FT_String*)"right" /* HORIZ, TOP */ + }; + + + FT_TRACE5(( "blue zone %d (%s):\n", + axis->blue_count, + cjk_blue_name[AF_CJK_IS_HORIZ_BLUE( bs ) | + AF_CJK_IS_TOP_BLUE( bs ) ] )); + } +#endif /* FT_DEBUG_LEVEL_TRACE */ num_fills = 0; num_flats = 0; - FT_TRACE5(( " cjk blue %s/%s\n", - cjk_blue_name[AF_CJK_IS_HORIZ_BLUE( bs ) | - AF_CJK_IS_TOP_BLUE( bs ) ], - cjk_blue_type_name[!!AF_CJK_IS_FILLED_BLUE( bs )] )); + fill = 1; /* start with characters that define fill values */ + FT_TRACE5(( " [overshoot values]\n" )); while ( *p ) { FT_ULong ch; - FT_UInt glyph_index; + FT_ULong glyph_index; + FT_Long y_offset; FT_Pos best_pos; /* same as points.y or points.x, resp. */ FT_Int best_point; FT_Vector* points; @@ -287,8 +332,16 @@ GET_UTF8_CHAR( ch, p ); + /* switch to characters that define flat values */ + if ( ch == '|' ) + { + fill = 0; + FT_TRACE5(( " [reference values]\n" )); + continue; + } + /* load the character in the face -- skip unknown or empty ones */ - glyph_index = FT_Get_Char_Index( face, ch ); + af_get_char_index( &metrics->root, ch, &glyph_index, &y_offset ); if ( glyph_index == 0 ) { FT_TRACE5(( " U+%04lX unavailable\n", ch )); @@ -374,7 +427,7 @@ FT_TRACE5(( " U+%04lX: best_pos = %5ld\n", ch, best_pos )); } - if ( AF_CJK_IS_FILLED_BLUE( bs ) ) + if ( fill ) fills[num_fills++] = best_pos; else flats[num_flats++] = best_pos; @@ -386,15 +439,15 @@ * we couldn't find a single glyph to compute this blue zone, * we will simply ignore it then */ - FT_TRACE5(( " empty\n" )); + FT_TRACE5(( " empty\n" )); continue; } - /* we have computed the contents of the `fill' and `flats' tables, */ - /* now determine the reference position of the blue zone -- */ - /* we simply take the median value after a simple sort */ - af_sort_pos( num_flats, flats ); + /* we have computed the contents of the `fill' and `flats' tables, */ + /* now determine the reference and overshoot position of the blue -- */ + /* we simply take the median value after a simple sort */ af_sort_pos( num_fills, fills ); + af_sort_pos( num_flats, flats ); blue = &axis->blues[axis->blue_count]; blue_ref = &blue->ref.org; @@ -433,7 +486,7 @@ *blue_ref = *blue_shoot = ( shoot + ref ) / 2; - FT_TRACE5(( " [overshoot smaller than reference," + FT_TRACE5(( " [reference smaller than overshoot," " taking mean value]\n" )); } } @@ -467,10 +520,11 @@ /* digit `0' is 0x30 in all supported charmaps */ for ( i = 0x30; i <= 0x39; i++ ) { - FT_UInt glyph_index; + FT_ULong glyph_index; + FT_Long y_offset; - glyph_index = FT_Get_Char_Index( face, i ); + af_get_char_index( &metrics->root, i, &glyph_index, &y_offset ); if ( glyph_index == 0 ) continue; @@ -1186,8 +1240,10 @@ /* zone, check for left edges */ /* */ /* of course, that's for TrueType */ - is_top_right_blue = FT_BOOL( blue->flags & AF_CJK_BLUE_TOP ); - is_major_dir = FT_BOOL( edge->dir == axis->major_dir ); + is_top_right_blue = + (FT_Byte)( ( blue->flags & AF_CJK_BLUE_TOP ) != 0 ); + is_major_dir = + FT_BOOL( edge->dir == axis->major_dir ); /* if it is a top zone, the edge must be against the major */ /* direction; if it is a bottom zone, it must be in the major */ @@ -1234,7 +1290,7 @@ FT_UInt32 scaler_flags, other_flags; - af_glyph_hints_rescale( hints, (AF_ScriptMetrics)metrics ); + af_glyph_hints_rescale( hints, (AF_StyleMetrics)metrics ); /* * correct x_scale and y_scale when needed, since they may have @@ -1484,6 +1540,12 @@ stem_edge->pos = base_edge->pos + fitted_width; + + FT_TRACE5(( " CJKLINK: edge %d @%d (opos=%.2f) linked to %.2f," + " dist was %.2f, now %.2f\n", + stem_edge - hints->axis[dim].edges, stem_edge->fpos, + stem_edge->opos / 64.0, stem_edge->pos / 64.0, + dist / 64.0, fitted_width / 64.0 )); } @@ -1665,9 +1727,9 @@ #endif - FT_TRACE5(( "cjk %s edge hinting (script `%s')\n", + FT_TRACE5(( "cjk %s edge hinting (style `%s')\n", dim == AF_DIMENSION_VERT ? "horizontal" : "vertical", - af_script_names[hints->metrics->script_class->script] )); + af_style_names[hints->metrics->style_class->style] )); /* we begin by aligning all stems relative to the blue zone */ @@ -2210,60 +2272,18 @@ sizeof ( AF_CJKMetricsRec ), - (AF_Script_InitMetricsFunc) af_cjk_metrics_init, - (AF_Script_ScaleMetricsFunc)af_cjk_metrics_scale, - (AF_Script_DoneMetricsFunc) NULL, + (AF_WritingSystem_InitMetricsFunc) af_cjk_metrics_init, + (AF_WritingSystem_ScaleMetricsFunc)af_cjk_metrics_scale, + (AF_WritingSystem_DoneMetricsFunc) NULL, - (AF_Script_InitHintsFunc) af_cjk_hints_init, - (AF_Script_ApplyHintsFunc) af_cjk_hints_apply + (AF_WritingSystem_InitHintsFunc) af_cjk_hints_init, + (AF_WritingSystem_ApplyHintsFunc) af_cjk_hints_apply ) - /* this corresponds to Unicode 6.0 */ - - /* XXX: this should probably fine tuned to differentiate better between */ - /* scripts... */ - - static const AF_Script_UniRangeRec af_hani_uniranges[] = - { - AF_UNIRANGE_REC( 0x1100UL, 0x11FFUL ), /* Hangul Jamo */ - AF_UNIRANGE_REC( 0x2E80UL, 0x2EFFUL ), /* CJK Radicals Supplement */ - AF_UNIRANGE_REC( 0x2F00UL, 0x2FDFUL ), /* Kangxi Radicals */ - AF_UNIRANGE_REC( 0x2FF0UL, 0x2FFFUL ), /* Ideographic Description Characters */ - AF_UNIRANGE_REC( 0x3000UL, 0x303FUL ), /* CJK Symbols and Punctuation */ - AF_UNIRANGE_REC( 0x3040UL, 0x309FUL ), /* Hiragana */ - AF_UNIRANGE_REC( 0x30A0UL, 0x30FFUL ), /* Katakana */ - AF_UNIRANGE_REC( 0x3100UL, 0x312FUL ), /* Bopomofo */ - AF_UNIRANGE_REC( 0x3130UL, 0x318FUL ), /* Hangul Compatibility Jamo */ - AF_UNIRANGE_REC( 0x3190UL, 0x319FUL ), /* Kanbun */ - AF_UNIRANGE_REC( 0x31A0UL, 0x31BFUL ), /* Bopomofo Extended */ - AF_UNIRANGE_REC( 0x31C0UL, 0x31EFUL ), /* CJK Strokes */ - AF_UNIRANGE_REC( 0x31F0UL, 0x31FFUL ), /* Katakana Phonetic Extensions */ - AF_UNIRANGE_REC( 0x3200UL, 0x32FFUL ), /* Enclosed CJK Letters and Months */ - AF_UNIRANGE_REC( 0x3300UL, 0x33FFUL ), /* CJK Compatibility */ - AF_UNIRANGE_REC( 0x3400UL, 0x4DBFUL ), /* CJK Unified Ideographs Extension A */ - AF_UNIRANGE_REC( 0x4DC0UL, 0x4DFFUL ), /* Yijing Hexagram Symbols */ - AF_UNIRANGE_REC( 0x4E00UL, 0x9FFFUL ), /* CJK Unified Ideographs */ - AF_UNIRANGE_REC( 0xA960UL, 0xA97FUL ), /* Hangul Jamo Extended-A */ - AF_UNIRANGE_REC( 0xAC00UL, 0xD7AFUL ), /* Hangul Syllables */ - AF_UNIRANGE_REC( 0xD7B0UL, 0xD7FFUL ), /* Hangul Jamo Extended-B */ - AF_UNIRANGE_REC( 0xF900UL, 0xFAFFUL ), /* CJK Compatibility Ideographs */ - AF_UNIRANGE_REC( 0xFE10UL, 0xFE1FUL ), /* Vertical forms */ - AF_UNIRANGE_REC( 0xFE30UL, 0xFE4FUL ), /* CJK Compatibility Forms */ - AF_UNIRANGE_REC( 0xFF00UL, 0xFFEFUL ), /* Halfwidth and Fullwidth Forms */ - AF_UNIRANGE_REC( 0x1B000UL, 0x1B0FFUL ), /* Kana Supplement */ - AF_UNIRANGE_REC( 0x1D300UL, 0x1D35FUL ), /* Tai Xuan Hing Symbols */ - AF_UNIRANGE_REC( 0x1F200UL, 0x1F2FFUL ), /* Enclosed Ideographic Supplement */ - AF_UNIRANGE_REC( 0x20000UL, 0x2A6DFUL ), /* CJK Unified Ideographs Extension B */ - AF_UNIRANGE_REC( 0x2A700UL, 0x2B73FUL ), /* CJK Unified Ideographs Extension C */ - AF_UNIRANGE_REC( 0x2B740UL, 0x2B81FUL ), /* CJK Unified Ideographs Extension D */ - AF_UNIRANGE_REC( 0x2F800UL, 0x2FA1FUL ), /* CJK Compatibility Ideographs Supplement */ - AF_UNIRANGE_REC( 0UL, 0UL ) - }; - - #else /* !AF_CONFIG_OPTION_CJK */ + AF_DEFINE_WRITING_SYSTEM_CLASS( af_cjk_writing_system_class, @@ -2271,33 +2291,16 @@ sizeof ( AF_CJKMetricsRec ), - (AF_Script_InitMetricsFunc) NULL, - (AF_Script_ScaleMetricsFunc)NULL, - (AF_Script_DoneMetricsFunc) NULL, + (AF_WritingSystem_InitMetricsFunc) NULL, + (AF_WritingSystem_ScaleMetricsFunc)NULL, + (AF_WritingSystem_DoneMetricsFunc) NULL, - (AF_Script_InitHintsFunc) NULL, - (AF_Script_ApplyHintsFunc) NULL + (AF_WritingSystem_InitHintsFunc) NULL, + (AF_WritingSystem_ApplyHintsFunc) NULL ) - static const AF_Script_UniRangeRec af_hani_uniranges[] = - { - AF_UNIRANGE_REC( 0UL, 0UL ) - }; - #endif /* !AF_CONFIG_OPTION_CJK */ - AF_DEFINE_SCRIPT_CLASS( - af_hani_script_class, - - AF_SCRIPT_HANI, - AF_BLUE_STRINGSET_HANI, - AF_WRITING_SYSTEM_CJK, - - af_hani_uniranges, - 0x7530 /* 田 */ - ) - - /* END */ diff --git a/src/autofit/afcjk.h b/src/autofit/afcjk.h index 6f5bdc5..4dd4f39 100644 --- a/src/autofit/afcjk.h +++ b/src/autofit/afcjk.h @@ -2,9 +2,9 @@ /* */ /* afcjk.h */ /* */ -/* Auto-fitter hinting routines for CJK script (specification). */ +/* Auto-fitter hinting routines for CJK writing system (specification). */ /* */ -/* Copyright 2006, 2007, 2011-2013 by */ +/* Copyright 2006, 2007, 2011-2014 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -31,11 +31,6 @@ FT_BEGIN_HEADER AF_DECLARE_WRITING_SYSTEM_CLASS( af_cjk_writing_system_class ) - /* the CJK-specific script classes */ - - AF_DECLARE_SCRIPT_CLASS( af_hani_script_class ) - - /*************************************************************************/ /*************************************************************************/ /***** *****/ @@ -55,8 +50,6 @@ FT_BEGIN_HEADER ( (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_FILLED_BLUE( b ) \ - ( (b)->properties & AF_BLUE_PROPERTY_CJK_FILL ) #define AF_CJK_IS_RIGHT_BLUE AF_CJK_IS_TOP_BLUE #define AF_CJK_MAX_WIDTHS 16 @@ -105,9 +98,9 @@ FT_BEGIN_HEADER typedef struct AF_CJKMetricsRec_ { - AF_ScriptMetricsRec root; - FT_UInt units_per_em; - AF_CJKAxisRec axis[AF_DIMENSION_MAX]; + AF_StyleMetricsRec root; + FT_UInt units_per_em; + AF_CJKAxisRec axis[AF_DIMENSION_MAX]; } AF_CJKMetricsRec, *AF_CJKMetrics; diff --git a/src/autofit/afcover.h b/src/autofit/afcover.h new file mode 100644 index 0000000..d5ac969 --- /dev/null +++ b/src/autofit/afcover.h @@ -0,0 +1,105 @@ +/***************************************************************************/ +/* */ +/* afcover.h */ +/* */ +/* Auto-fitter coverages (specification only). */ +/* */ +/* Copyright 2013, 2014 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 */ diff --git a/src/autofit/afdummy.c b/src/autofit/afdummy.c index b2b3a20..f8702a1 100644 --- a/src/autofit/afdummy.c +++ b/src/autofit/afdummy.c @@ -23,8 +23,8 @@ static FT_Error - af_dummy_hints_init( AF_GlyphHints hints, - AF_ScriptMetrics metrics ) + af_dummy_hints_init( AF_GlyphHints hints, + AF_StyleMetrics metrics ) { af_glyph_hints_rescale( hints, metrics ); @@ -57,26 +57,14 @@ AF_WRITING_SYSTEM_DUMMY, - sizeof ( AF_ScriptMetricsRec ), + sizeof ( AF_StyleMetricsRec ), - (AF_Script_InitMetricsFunc) NULL, - (AF_Script_ScaleMetricsFunc)NULL, - (AF_Script_DoneMetricsFunc) NULL, + (AF_WritingSystem_InitMetricsFunc) NULL, + (AF_WritingSystem_ScaleMetricsFunc)NULL, + (AF_WritingSystem_DoneMetricsFunc) NULL, - (AF_Script_InitHintsFunc) af_dummy_hints_init, - (AF_Script_ApplyHintsFunc) af_dummy_hints_apply - ) - - - AF_DEFINE_SCRIPT_CLASS( - af_none_script_class, - - AF_SCRIPT_NONE, - (AF_Blue_Stringset)0, - AF_WRITING_SYSTEM_DUMMY, - - NULL, - '\0' + (AF_WritingSystem_InitHintsFunc) af_dummy_hints_init, + (AF_WritingSystem_ApplyHintsFunc) af_dummy_hints_apply ) diff --git a/src/autofit/afdummy.h b/src/autofit/afdummy.h index 9a4d3c2..ad1b0d3 100644 --- a/src/autofit/afdummy.h +++ b/src/autofit/afdummy.h @@ -25,14 +25,10 @@ FT_BEGIN_HEADER - /* A dummy writing system and script class used when no hinting should be - * performed. - */ + /* A dummy writing system used when no hinting should be performed. */ AF_DECLARE_WRITING_SYSTEM_CLASS( af_dummy_writing_system_class ) - AF_DECLARE_SCRIPT_CLASS( af_none_script_class ) - /* */ FT_END_HEADER diff --git a/src/autofit/afglobal.c b/src/autofit/afglobal.c index c2151af..a54c20c 100644 --- a/src/autofit/afglobal.c +++ b/src/autofit/afglobal.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter routines to compute global hinting values (body). */ /* */ -/* Copyright 2003-2013 by */ +/* Copyright 2003-2014 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,6 +17,20 @@ #include "afglobal.h" +#include "afranges.h" +#include "hbshim.h" +#include FT_INTERNAL_DEBUG_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 trace_afglobal + /* get writing system specific header files */ #undef WRITING_SYSTEM @@ -27,6 +41,30 @@ #include "afpic.h" +#undef SCRIPT +#define SCRIPT( s, S, d, h, sc1, sc2, sc3 ) \ + AF_DEFINE_SCRIPT_CLASS( \ + af_ ## s ## _script_class, \ + AF_SCRIPT_ ## S, \ + af_ ## s ## _uniranges, \ + sc1, sc2, sc3 ) + +#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" + + #ifndef FT_CONFIG_OPTION_PIC #undef WRITING_SYSTEM @@ -44,7 +82,7 @@ #undef SCRIPT -#define SCRIPT( s, S, d ) \ +#define SCRIPT( s, S, d, h, sc1, sc2, sc3 ) \ &af_ ## s ## _script_class, FT_LOCAL_ARRAY_DEF( AF_ScriptClass ) @@ -56,58 +94,76 @@ 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 */ + }; + #endif /* !FT_CONFIG_OPTION_PIC */ #ifdef FT_DEBUG_LEVEL_TRACE -#undef SCRIPT -#define SCRIPT( s, S, d ) #s, +#undef STYLE +#define STYLE( s, S, d, ws, sc, ss, c ) #s, FT_LOCAL_ARRAY_DEF( char* ) - af_script_names[] = + af_style_names[] = { -#include "afscript.h" +#include "afstyles.h" }; #endif /* FT_DEBUG_LEVEL_TRACE */ - /* Compute the script index of each glyph within a given face. */ + /* Compute the style index of each glyph within a given face. */ static FT_Error - af_face_globals_compute_script_coverage( AF_FaceGlobals globals ) + af_face_globals_compute_style_coverage( AF_FaceGlobals globals ) { FT_Error error; FT_Face face = globals->face; FT_CharMap old_charmap = face->charmap; - FT_Byte* gscripts = globals->glyph_scripts; + FT_Byte* gstyles = globals->glyph_styles; FT_UInt ss; FT_UInt i; + FT_UInt dflt = ~0U; /* a non-valid value */ - /* the value AF_SCRIPT_UNASSIGNED means `uncovered glyph' */ - FT_MEM_SET( globals->glyph_scripts, - AF_SCRIPT_UNASSIGNED, + /* the value AF_STYLE_UNASSIGNED means `uncovered glyph' */ + FT_MEM_SET( globals->glyph_styles, + AF_STYLE_UNASSIGNED, globals->glyph_count ); error = FT_Select_Charmap( face, FT_ENCODING_UNICODE ); if ( error ) { - /* - * Ignore this error; we simply use the fallback script. - * XXX: Shouldn't we rather disable hinting? - */ + /* + * Ignore this error; we simply use the fallback style. + * XXX: Shouldn't we rather disable hinting? + */ error = FT_Err_Ok; goto Exit; } - /* scan each script in a Unicode charmap */ - for ( ss = 0; AF_SCRIPT_CLASSES_GET[ss]; ss++ ) + /* scan each style in a Unicode charmap */ + for ( ss = 0; AF_STYLE_CLASSES_GET[ss]; ss++ ) { - AF_ScriptClass script_class = AF_SCRIPT_CLASSES_GET[ss]; + AF_StyleClass style_class = + AF_STYLE_CLASSES_GET[ss]; + AF_ScriptClass script_class = + AF_SCRIPT_CLASSES_GET[style_class->script]; AF_Script_UniRange range; @@ -116,35 +172,60 @@ /* * Scan all Unicode points in the range and set the corresponding - * glyph script index. + * glyph style index. */ - for ( range = script_class->script_uni_ranges; - range->first != 0; - range++ ) + if ( style_class->coverage == AF_COVERAGE_DEFAULT ) { - FT_ULong charcode = range->first; - FT_UInt gindex; + if ( (FT_UInt)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 < (FT_ULong)globals->glyph_count && - gscripts[gindex] == AF_SCRIPT_UNASSIGNED ) - gscripts[gindex] = (FT_Byte)ss; + gindex = FT_Get_Char_Index( face, charcode ); - for (;;) - { - charcode = FT_Get_Next_Char( face, charcode, &gindex ); + if ( gindex != 0 && + gindex < (FT_ULong)globals->glyph_count && + gstyles[gindex] == AF_STYLE_UNASSIGNED ) + gstyles[gindex] = (FT_Byte)ss; - if ( gindex == 0 || charcode > range->last ) - break; + for (;;) + { + charcode = FT_Get_Next_Char( face, charcode, &gindex ); - if ( gindex < (FT_ULong)globals->glyph_count && - gscripts[gindex] == AF_SCRIPT_UNASSIGNED ) - gscripts[gindex] = (FT_Byte)ss; + if ( gindex == 0 || charcode > range->last ) + break; + + if ( gindex < (FT_ULong)globals->glyph_count && + gstyles[gindex] == AF_STYLE_UNASSIGNED ) + gstyles[gindex] = (FT_Byte)ss; + } } } + else + { + /* get glyphs not directly addressable by cmap */ + af_get_coverage( globals, style_class, gstyles ); + } + } + + /* handle the default OpenType features of the default script ... */ + af_get_coverage( globals, AF_STYLE_CLASSES_GET[dflt], gstyles ); + + /* ... and the remaining default OpenType features */ + for ( ss = 0; AF_STYLE_CLASSES_GET[ss]; ss++ ) + { + AF_StyleClass style_class = AF_STYLE_CLASSES_GET[ss]; + + + if ( ss != dflt && style_class->coverage == AF_COVERAGE_DEFAULT ) + af_get_coverage( globals, style_class, gstyles ); } /* mark ASCII digits */ @@ -154,29 +235,68 @@ if ( gindex != 0 && gindex < (FT_ULong)globals->glyph_count ) - gscripts[gindex] |= AF_DIGIT; + gstyles[gindex] |= AF_DIGIT; } Exit: /* - * By default, all uncovered glyphs are set to the fallback script. + * 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_script != AF_SCRIPT_UNASSIGNED ) + if ( globals->module->fallback_style != AF_STYLE_UNASSIGNED ) { FT_Long nn; for ( nn = 0; nn < globals->glyph_count; nn++ ) { - if ( ( gscripts[nn] & ~AF_DIGIT ) == AF_SCRIPT_UNASSIGNED ) + if ( ( gstyles[nn] & ~AF_DIGIT ) == AF_STYLE_UNASSIGNED ) { - gscripts[nn] &= ~AF_SCRIPT_UNASSIGNED; - gscripts[nn] |= globals->module->fallback_script; + gstyles[nn] &= ~AF_STYLE_UNASSIGNED; + gstyles[nn] |= globals->module->fallback_style; } } } +#ifdef FT_DEBUG_LEVEL_TRACE + + FT_TRACE4(( "\n" + "style coverage\n" + "==============\n" + "\n" )); + + for ( ss = 0; AF_STYLE_CLASSES_GET[ss]; ss++ ) + { + AF_StyleClass style_class = AF_STYLE_CLASSES_GET[ss]; + FT_UInt count = 0; + FT_Long idx; + + + FT_TRACE4(( "%s:\n", af_style_names[style_class->style] )); + + for ( idx = 0; idx < globals->glyph_count; idx++ ) + { + if ( ( gstyles[idx] & ~AF_DIGIT ) == 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 */ + FT_Set_Charmap( face, old_charmap ); return error; } @@ -198,19 +318,23 @@ face->num_glyphs * sizeof ( FT_Byte ) ) ) goto Exit; - globals->face = face; - globals->glyph_count = face->num_glyphs; - globals->glyph_scripts = (FT_Byte*)( globals + 1 ); - globals->module = module; + globals->face = face; + globals->glyph_count = face->num_glyphs; + globals->glyph_styles = (FT_Byte*)( globals + 1 ); + globals->module = module; - error = af_face_globals_compute_script_coverage( globals ); +#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ + globals->hb_font = hb_ft_font_create( face, NULL ); +#endif + + error = af_face_globals_compute_style_coverage( globals ); if ( error ) { af_face_globals_free( globals ); globals = NULL; } - - globals->increase_x_height = AF_PROP_INCREASE_X_HEIGHT_MAX; + else + globals->increase_x_height = AF_PROP_INCREASE_X_HEIGHT_MAX; Exit: *aglobals = globals; @@ -227,26 +351,31 @@ FT_UInt nn; - for ( nn = 0; nn < AF_SCRIPT_MAX; nn++ ) + for ( nn = 0; nn < AF_STYLE_MAX; nn++ ) { if ( globals->metrics[nn] ) { - AF_ScriptClass script_class = - AF_SCRIPT_CLASSES_GET[nn]; + AF_StyleClass style_class = + AF_STYLE_CLASSES_GET[nn]; AF_WritingSystemClass writing_system_class = - AF_WRITING_SYSTEM_CLASSES_GET[script_class->writing_system]; + AF_WRITING_SYSTEM_CLASSES_GET[style_class->writing_system]; - if ( writing_system_class->script_metrics_done ) - writing_system_class->script_metrics_done( globals->metrics[nn] ); + if ( writing_system_class->style_metrics_done ) + writing_system_class->style_metrics_done( globals->metrics[nn] ); FT_FREE( globals->metrics[nn] ); } } - globals->glyph_count = 0; - globals->glyph_scripts = NULL; /* no need to free this one! */ - globals->face = NULL; +#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ + hb_font_destroy( globals->hb_font ); + globals->hb_font = NULL; +#endif + + globals->glyph_count = 0; + globals->glyph_styles = NULL; /* no need to free this one! */ + globals->face = NULL; FT_FREE( globals ); } @@ -254,16 +383,16 @@ FT_LOCAL_DEF( FT_Error ) - af_face_globals_get_metrics( AF_FaceGlobals globals, - FT_UInt gindex, - FT_UInt options, - AF_ScriptMetrics *ametrics ) + af_face_globals_get_metrics( AF_FaceGlobals globals, + FT_UInt gindex, + FT_UInt options, + AF_StyleMetrics *ametrics ) { - AF_ScriptMetrics metrics = NULL; + AF_StyleMetrics metrics = NULL; - AF_Script script = (AF_Script)( options & 15 ); + AF_Style style = (AF_Style)options; AF_WritingSystemClass writing_system_class; - AF_ScriptClass script_class; + AF_StyleClass style_class; FT_Error error = FT_Err_Ok; @@ -274,44 +403,44 @@ goto Exit; } - /* if we have a forced script (via `options'), use it, */ - /* otherwise look into `glyph_scripts' array */ - if ( script == AF_SCRIPT_NONE || script + 1 >= AF_SCRIPT_MAX ) - script = (AF_Script)( globals->glyph_scripts[gindex] & - AF_SCRIPT_UNASSIGNED ); + /* 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 ); - script_class = AF_SCRIPT_CLASSES_GET[script]; + style_class = AF_STYLE_CLASSES_GET[style]; writing_system_class = AF_WRITING_SYSTEM_CLASSES_GET - [script_class->writing_system]; + [style_class->writing_system]; - metrics = globals->metrics[script]; + metrics = globals->metrics[style]; if ( metrics == NULL ) { /* create the global metrics object if necessary */ FT_Memory memory = globals->face->memory; - if ( FT_ALLOC( metrics, writing_system_class->script_metrics_size ) ) + if ( FT_ALLOC( metrics, writing_system_class->style_metrics_size ) ) goto Exit; - metrics->script_class = script_class; - metrics->globals = globals; + metrics->style_class = style_class; + metrics->globals = globals; - if ( writing_system_class->script_metrics_init ) + if ( writing_system_class->style_metrics_init ) { - error = writing_system_class->script_metrics_init( metrics, - globals->face ); + error = writing_system_class->style_metrics_init( metrics, + globals->face ); if ( error ) { - if ( writing_system_class->script_metrics_done ) - writing_system_class->script_metrics_done( metrics ); + if ( writing_system_class->style_metrics_done ) + writing_system_class->style_metrics_done( metrics ); FT_FREE( metrics ); goto Exit; } } - globals->metrics[script] = metrics; + globals->metrics[style] = metrics; } Exit: @@ -326,7 +455,7 @@ FT_UInt gindex ) { if ( gindex < (FT_ULong)globals->glyph_count ) - return (FT_Bool)( globals->glyph_scripts[gindex] & AF_DIGIT ); + return (FT_Bool)( globals->glyph_styles[gindex] & AF_DIGIT ); return (FT_Bool)0; } diff --git a/src/autofit/afglobal.h b/src/autofit/afglobal.h index c01b474..38d8d69 100644 --- a/src/autofit/afglobal.h +++ b/src/autofit/afglobal.h @@ -5,7 +5,7 @@ /* Auto-fitter routines to compute global hinting values */ /* (specification). */ /* */ -/* Copyright 2003-2005, 2007, 2009, 2011-2013 by */ +/* Copyright 2003-2005, 2007, 2009, 2011-2014 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -23,6 +23,7 @@ #include "aftypes.h" #include "afmodule.h" +#include "hbshim.h" FT_BEGIN_HEADER @@ -31,29 +32,50 @@ FT_BEGIN_HEADER FT_LOCAL_ARRAY( AF_WritingSystemClass ) af_writing_system_classes[]; + +#undef SCRIPT +#define SCRIPT( s, S, d, h, sc1, sc2, sc3 ) \ + 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_script_names[]; + 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 script in `af_script_classes' */ + /* index of fallback style in `af_style_classes' */ #ifdef AF_CONFIG_OPTION_CJK -#define AF_SCRIPT_FALLBACK AF_SCRIPT_HANI +#define AF_STYLE_FALLBACK AF_STYLE_HANI_DFLT #else -#define AF_SCRIPT_FALLBACK AF_SCRIPT_NONE +#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 indicating an uncovered glyph */ -#define AF_SCRIPT_UNASSIGNED 0x7F +#define AF_STYLE_UNASSIGNED 0x7F /* if this flag is set, we have an ASCII digit */ -#define AF_DIGIT 0x80 +#define AF_DIGIT 0x80 /* `increase-x-height' property */ #define AF_PROP_INCREASE_X_HEIGHT_MIN 6 @@ -70,29 +92,33 @@ FT_BEGIN_HEADER /* - * Note that glyph_scripts[] maps each glyph to an index into the - * `af_script_classes' array. + * Note that glyph_styles[] maps each glyph to an index into the + * `af_style_classes' array. * */ typedef struct AF_FaceGlobalsRec_ { - FT_Face face; - FT_Long glyph_count; /* same as face->num_glyphs */ - FT_Byte* glyph_scripts; + FT_Face face; + FT_Long glyph_count; /* same as face->num_glyphs */ + FT_Byte* glyph_styles; + +#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ + hb_font_t* hb_font; +#endif /* per-face auto-hinter properties */ - FT_UInt increase_x_height; + FT_UInt increase_x_height; - AF_ScriptMetrics metrics[AF_SCRIPT_MAX]; + AF_StyleMetrics metrics[AF_STYLE_MAX]; - AF_Module module; /* to access global properties */ + AF_Module module; /* to access global properties */ } AF_FaceGlobalsRec; /* * model the global hints data for a given face, decomposed into - * script-specific items + * style-specific items */ FT_LOCAL( FT_Error ) @@ -101,10 +127,10 @@ FT_BEGIN_HEADER AF_Module module ); FT_LOCAL( FT_Error ) - af_face_globals_get_metrics( AF_FaceGlobals globals, - FT_UInt gindex, - FT_UInt options, - AF_ScriptMetrics *ametrics ); + af_face_globals_get_metrics( AF_FaceGlobals globals, + FT_UInt gindex, + FT_UInt options, + AF_StyleMetrics *ametrics ); FT_LOCAL( void ) af_face_globals_free( AF_FaceGlobals globals ); diff --git a/src/autofit/afhints.c b/src/autofit/afhints.c index ce504cc..88a97d4 100644 --- a/src/autofit/afhints.c +++ b/src/autofit/afhints.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter hinting routines (body). */ /* */ -/* Copyright 2003-2007, 2009-2013 by */ +/* Copyright 2003-2007, 2009-2014 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -345,7 +345,9 @@ af_glyph_hints_get_segment_offset( AF_GlyphHints hints, FT_Int dimension, FT_Int idx, - FT_Pos* offset ) + FT_Pos *offset, + FT_Bool *is_blue, + FT_Pos *blue_offset ) { AF_Dimension dim; AF_AxisHints axis; @@ -362,9 +364,18 @@ if ( idx < 0 || idx >= axis->num_segments ) return FT_THROW( Invalid_Argument ); - seg = &axis->segments[idx]; - *offset = ( dim == AF_DIMENSION_HORZ ) ? seg->first->ox - : seg->first->oy; + seg = &axis->segments[idx]; + *offset = ( dim == AF_DIMENSION_HORZ ) ? seg->first->ox + : seg->first->oy; + if ( seg->edge ) + *is_blue = (FT_Bool)( seg->edge->blue_edge != 0 ); + else + *is_blue = FALSE; + + if ( *is_blue ) + *blue_offset = seg->edge->blue_edge->cur; + else + *blue_offset = 0; return FT_Err_Ok; } @@ -533,8 +544,8 @@ /* Reset metrics. */ FT_LOCAL_DEF( void ) - af_glyph_hints_rescale( AF_GlyphHints hints, - AF_ScriptMetrics metrics ) + af_glyph_hints_rescale( AF_GlyphHints hints, + AF_StyleMetrics metrics ) { hints->metrics = metrics; hints->scaler_flags = metrics->scaler.flags; @@ -640,6 +651,9 @@ for ( point = points; point < point_limit; point++, vec++, tag++ ) { + point->in_dir = (FT_Char)AF_DIR_NONE; + point->out_dir = (FT_Char)AF_DIR_NONE; + point->fx = (FT_Short)vec->x; point->fy = (FT_Short)vec->y; point->ox = point->x = FT_MulFix( vec->x, x_scale ) + x_delta; @@ -687,91 +701,186 @@ } } - /* compute directions of in & out vectors */ { - AF_Point first = points; - AF_Point prev = NULL; - FT_Pos in_x = 0; - FT_Pos in_y = 0; - AF_Direction in_dir = AF_DIR_NONE; - - FT_Pos last_good_in_x = 0; - FT_Pos last_good_in_y = 0; - + /* + * Compute directions of `in' and `out' vectors. + * + * Note that distances between points that are very near to each + * other are accumulated. In other words, the auto-hinter + * prepends the small vectors between near points to the first + * non-near vector. All intermediate points are tagged as + * weak; the directions are adjusted also to be equal to the + * accumulated one. + */ + + /* value 20 in `near_limit' is heuristic */ FT_UInt units_per_em = hints->metrics->scaler.face->units_per_EM; FT_Int near_limit = 20 * units_per_em / 2048; + FT_Int near_limit2 = 2 * near_limit - 1; + AF_Point* contour; + AF_Point* contour_limit = hints->contours + hints->num_contours; - for ( point = points; point < point_limit; point++ ) + + for ( contour = hints->contours; contour < contour_limit; contour++ ) { - AF_Point next; - FT_Pos out_x, out_y; + AF_Point first = *contour; + AF_Point next, prev, curr; + + FT_Pos out_x, out_y; + + FT_Bool is_first; - if ( point == first ) + /* since the first point of a contour could be part of a */ + /* series of near points, go backwards to find the first */ + /* non-near point and adjust `first' */ + + point = first; + prev = first->prev; + + while ( prev != first ) { - prev = first->prev; + out_x = point->fx - prev->fx; + out_y = point->fy - prev->fy; + + /* + * We use Taxicab metrics to measure the vector length. + * + * Note that the accumulated distances so far could have the + * opposite direction of the distance measured here. For this + * reason we use `near_limit2' for the comparison to get a + * non-near point even in the worst case. + */ + if ( FT_ABS( out_x ) + FT_ABS( out_y ) >= near_limit2 ) + break; + + point = prev; + prev = prev->prev; + } - in_x = first->fx - prev->fx; - in_y = first->fy - prev->fy; + /* adjust first point */ + first = point; - last_good_in_x = in_x; - last_good_in_y = in_y; + /* now loop over all points of the contour to get */ + /* `in' and `out' vector directions */ - if ( FT_ABS( in_x ) + FT_ABS( in_y ) < near_limit ) - { - /* search first non-near point to get a good `in_dir' value */ + curr = first; - AF_Point point_ = prev; + /* + * We abuse the `u' and `v' fields to store index deltas to the + * next and previous non-near point, respectively. + * + * To avoid problems with not having non-near points, we point to + * `first' by default as the next non-near point. + * + */ + curr->u = (FT_Pos)( first - curr ); + first->v = -curr->u; + out_x = 0; + out_y = 0; - while ( point_ != first ) - { - AF_Point prev_ = point_->prev; + is_first = 1; - FT_Pos in_x_ = point_->fx - prev_->fx; - FT_Pos in_y_ = point_->fy - prev_->fy; + for ( point = first; + point != first || is_first; + point = point->next ) + { + AF_Direction out_dir; - if ( FT_ABS( in_x_ ) + FT_ABS( in_y_ ) >= near_limit ) - { - last_good_in_x = in_x_; - last_good_in_y = in_y_; + is_first = 0; - break; - } + next = point->next; - point_ = prev_; - } + out_x += next->fx - point->fx; + out_y += next->fy - point->fy; + + if ( FT_ABS( out_x ) + FT_ABS( out_y ) < near_limit ) + { + next->flags |= AF_FLAG_WEAK_INTERPOLATION; + continue; } - in_dir = af_direction_compute( in_x, in_y ); - first = prev + 1; + curr->u = (FT_Pos)( next - curr ); + next->v = -curr->u; + + out_dir = af_direction_compute( out_x, out_y ); + + /* adjust directions for all points inbetween; */ + /* the loop also updates position of `curr' */ + curr->out_dir = (FT_Char)out_dir; + for ( curr = curr->next; curr != next; curr = curr->next ) + { + curr->in_dir = (FT_Char)out_dir; + curr->out_dir = (FT_Char)out_dir; + } + next->in_dir = (FT_Char)out_dir; + + curr->u = (FT_Pos)( first - curr ); + first->v = -curr->u; + + out_x = 0; + out_y = 0; } + } - point->in_dir = (FT_Char)in_dir; + /* + * The next step is to `simplify' an outline's topology so that we + * can identify local extrema more reliably: A series of + * non-horizontal or non-vertical vectors pointing into the same + * quadrant are handled as a single, long vector. From a + * topological point of the view, the intermediate points are of no + * interest and thus tagged as weak. + */ - /* check whether the current point is near to the previous one */ - /* (value 20 in `near_limit' is heuristic; we use Taxicab */ - /* metrics for the test) */ + for ( point = points; point < point_limit; point++ ) + { + if ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) + continue; - if ( FT_ABS( in_x ) + FT_ABS( in_y ) < near_limit ) - point->flags |= AF_FLAG_NEAR; - else + if ( point->in_dir == AF_DIR_NONE && + point->out_dir == AF_DIR_NONE ) { - last_good_in_x = in_x; - last_good_in_y = in_y; - } + /* check whether both vectors point into the same quadrant */ + + FT_Pos in_x, in_y; + FT_Pos out_x, out_y; + + AF_Point next_u = point + point->u; + AF_Point prev_v = point + point->v; + - next = point->next; - out_x = next->fx - point->fx; - out_y = next->fy - point->fy; + in_x = point->fx - prev_v->fx; + in_y = point->fy - prev_v->fy; + + out_x = next_u->fx - point->fx; + out_y = next_u->fy - point->fy; + + if ( ( in_x ^ out_x ) >= 0 && ( in_y ^ out_y ) >= 0 ) + { + /* yes, so tag current point as weak */ + /* and update index deltas */ + + point->flags |= AF_FLAG_WEAK_INTERPOLATION; + + prev_v->u = (FT_Pos)( next_u - prev_v ); + next_u->v = -prev_v->u; + } + } + } - in_dir = af_direction_compute( out_x, out_y ); - point->out_dir = (FT_Char)in_dir; + /* + * Finally, check for remaining weak points. Everything else not + * collected in edges so far is then implicitly classified as strong + * points. + */ - /* Check for weak points. The remaining points not collected */ - /* in edges are then implicitly classified as strong points. */ + for ( point = points; point < point_limit; point++ ) + { + if ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) + continue; if ( point->flags & AF_FLAG_CONTROL ) { @@ -788,18 +897,25 @@ goto Is_Weak_Point; } - /* test whether `in' and `out' direction is approximately */ - /* the same (and use the last good `in' vector in case */ - /* the current point is near to the previous one) */ - if ( ft_corner_is_flat( - point->flags & AF_FLAG_NEAR ? last_good_in_x : in_x, - point->flags & AF_FLAG_NEAR ? last_good_in_y : in_y, - out_x, - out_y ) ) { - /* current point lies on a straight, diagonal line */ - /* (more or less) */ - goto Is_Weak_Point; + AF_Point next_u = point + point->u; + AF_Point prev_v = point + point->v; + + + if ( ft_corner_is_flat( point->fx - prev_v->fx, + point->fy - prev_v->fy, + next_u->fx - point->fx, + next_u->fy - point->fy ) ) + { + /* either the `in' or the `out' vector is much more */ + /* dominant than the other one, so tag current point */ + /* as weak and update index deltas */ + + prev_v->u = (FT_Pos)( next_u - prev_v ); + next_u->v = -prev_v->u; + + goto Is_Weak_Point; + } } } else if ( point->in_dir == -point->out_dir ) @@ -807,10 +923,6 @@ /* current point forms a spike */ goto Is_Weak_Point; } - - in_x = out_x; - in_y = out_y; - prev = point; } } } @@ -1224,8 +1336,6 @@ } } - point = points; - for ( ; contour < contour_limit; contour++ ) { AF_Point first_touched, last_touched; @@ -1248,7 +1358,6 @@ } first_touched = point; - last_touched = point; for (;;) { diff --git a/src/autofit/afhints.h b/src/autofit/afhints.h index ce52325..c0ebd0d 100644 --- a/src/autofit/afhints.h +++ b/src/autofit/afhints.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter hinting routines (specification). */ /* */ -/* Copyright 2003-2008, 2010-2012 by */ +/* Copyright 2003-2008, 2010-2012, 2014 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -27,7 +27,7 @@ FT_BEGIN_HEADER /* * The definition of outline glyph hints. These are shared by all - * script analysis routines (until now). + * writing system analysis routines (until now). */ typedef enum AF_Dimension_ @@ -236,10 +236,7 @@ FT_BEGIN_HEADER AF_FLAG_WEAK_INTERPOLATION = 1 << 8, /* all inflection points in the outline have this flag set */ - AF_FLAG_INFLECTION = 1 << 9, - - /* the current point is very near to another one */ - AF_FLAG_NEAR = 1 << 10 + AF_FLAG_INFLECTION = 1 << 9 } AF_Flags; @@ -247,10 +244,11 @@ FT_BEGIN_HEADER /* edge hint flags */ typedef enum AF_Edge_Flags_ { - AF_EDGE_NORMAL = 0, - AF_EDGE_ROUND = 1 << 0, - AF_EDGE_SERIF = 1 << 1, - AF_EDGE_DONE = 1 << 2 + AF_EDGE_NORMAL = 0, + AF_EDGE_ROUND = 1 << 0, + AF_EDGE_SERIF = 1 << 1, + AF_EDGE_DONE = 1 << 2, + AF_EDGE_NEUTRAL = 1 << 3 /* set if edge aligns to a neutral blue zone */ } AF_Edge_Flags; @@ -343,31 +341,31 @@ FT_BEGIN_HEADER typedef struct AF_GlyphHintsRec_ { - FT_Memory memory; + FT_Memory memory; - FT_Fixed x_scale; - FT_Pos x_delta; + FT_Fixed x_scale; + FT_Pos x_delta; - FT_Fixed y_scale; - FT_Pos y_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_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 */ + 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]; + AF_AxisHintsRec axis[AF_DIMENSION_MAX]; - FT_UInt32 scaler_flags; /* copy of scaler flags */ - FT_UInt32 other_flags; /* free for script-specific */ - /* implementations */ - AF_ScriptMetrics metrics; + FT_UInt32 scaler_flags; /* copy of scaler flags */ + FT_UInt32 other_flags; /* free for style-specific */ + /* implementations */ + AF_StyleMetrics metrics; - FT_Pos xmin_delta; /* used for warping */ - FT_Pos xmax_delta; + FT_Pos xmin_delta; /* used for warping */ + FT_Pos xmax_delta; } AF_GlyphHintsRec; @@ -429,8 +427,8 @@ FT_BEGIN_HEADER FT_Memory memory ); FT_LOCAL( void ) - af_glyph_hints_rescale( AF_GlyphHints hints, - AF_ScriptMetrics metrics ); + af_glyph_hints_rescale( AF_GlyphHints hints, + AF_StyleMetrics metrics ); FT_LOCAL( FT_Error ) af_glyph_hints_reload( AF_GlyphHints hints, diff --git a/src/autofit/afindic.c b/src/autofit/afindic.c index ef8299f..197881b 100644 --- a/src/autofit/afindic.c +++ b/src/autofit/afindic.c @@ -2,7 +2,7 @@ /* */ /* afindic.c */ /* */ -/* Auto-fitter hinting routines for Indic scripts (body). */ +/* Auto-fitter hinting routines for Indic writing system (body). */ /* */ /* Copyright 2007, 2011-2013 by */ /* Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>. */ @@ -104,32 +104,18 @@ sizeof ( AF_CJKMetricsRec ), - (AF_Script_InitMetricsFunc) af_indic_metrics_init, - (AF_Script_ScaleMetricsFunc)af_indic_metrics_scale, - (AF_Script_DoneMetricsFunc) NULL, + (AF_WritingSystem_InitMetricsFunc) af_indic_metrics_init, + (AF_WritingSystem_ScaleMetricsFunc)af_indic_metrics_scale, + (AF_WritingSystem_DoneMetricsFunc) NULL, - (AF_Script_InitHintsFunc) af_indic_hints_init, - (AF_Script_ApplyHintsFunc) af_indic_hints_apply + (AF_WritingSystem_InitHintsFunc) af_indic_hints_init, + (AF_WritingSystem_ApplyHintsFunc) af_indic_hints_apply ) - /* XXX: this should probably fine tuned to differentiate better between */ - /* scripts... */ - - static const AF_Script_UniRangeRec af_deva_uniranges[] = - { - AF_UNIRANGE_REC( 0x0900UL, 0x0DFFUL ), /* Indic Range */ - AF_UNIRANGE_REC( 0x0F00UL, 0x0FFFUL ), /* Tibetan */ - AF_UNIRANGE_REC( 0x1900UL, 0x194FUL ), /* Limbu */ - AF_UNIRANGE_REC( 0x1B80UL, 0x1BBFUL ), /* Sundanese */ - AF_UNIRANGE_REC( 0x1C80UL, 0x1CDFUL ), /* Meetei Mayak */ - AF_UNIRANGE_REC( 0xA800UL, 0xA82FUL ), /* Syloti Nagri */ - AF_UNIRANGE_REC( 0x11800UL, 0x118DFUL ), /* Sharada */ - AF_UNIRANGE_REC( 0UL, 0UL ) - }; - #else /* !AF_CONFIG_OPTION_INDIC */ + AF_DEFINE_WRITING_SYSTEM_CLASS( af_indic_writing_system_class, @@ -137,33 +123,16 @@ sizeof ( AF_CJKMetricsRec ), - (AF_Script_InitMetricsFunc) NULL, - (AF_Script_ScaleMetricsFunc)NULL, - (AF_Script_DoneMetricsFunc) NULL, + (AF_WritingSystem_InitMetricsFunc) NULL, + (AF_WritingSystem_ScaleMetricsFunc)NULL, + (AF_WritingSystem_DoneMetricsFunc) NULL, - (AF_Script_InitHintsFunc) NULL, - (AF_Script_ApplyHintsFunc) NULL + (AF_WritingSystem_InitHintsFunc) NULL, + (AF_WritingSystem_ApplyHintsFunc) NULL ) - static const AF_Script_UniRangeRec af_deva_uniranges[] = - { - AF_UNIRANGE_REC( 0UL, 0UL ) - }; - #endif /* !AF_CONFIG_OPTION_INDIC */ - AF_DEFINE_SCRIPT_CLASS( - af_deva_script_class, - - AF_SCRIPT_DEVA, - (AF_Blue_Stringset)0, /* XXX */ - AF_WRITING_SYSTEM_INDIC, - - af_deva_uniranges, - 'o' /* XXX */ - ) - - /* END */ diff --git a/src/autofit/afindic.h b/src/autofit/afindic.h index db38e96..9e13cf7 100644 --- a/src/autofit/afindic.h +++ b/src/autofit/afindic.h @@ -2,7 +2,8 @@ /* */ /* afindic.h */ /* */ -/* Auto-fitter hinting routines for Indic scripts (specification). */ +/* Auto-fitter hinting routines for Indic writing system */ +/* (specification). */ /* */ /* Copyright 2007, 2012, 2013 by */ /* Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>. */ @@ -30,11 +31,6 @@ FT_BEGIN_HEADER AF_DECLARE_WRITING_SYSTEM_CLASS( af_indic_writing_system_class ) - /* the indic-specific script classes */ - - AF_DECLARE_SCRIPT_CLASS( af_deva_script_class ) - - /* */ FT_END_HEADER diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c index 15a241e..a1f2b33 100644 --- a/src/autofit/aflatin.c +++ b/src/autofit/aflatin.c @@ -2,9 +2,9 @@ /* */ /* aflatin.c */ /* */ -/* Auto-fitter hinting routines for latin script (body). */ +/* Auto-fitter hinting routines for latin writing system (body). */ /* */ -/* Copyright 2003-2013 by */ +/* Copyright 2003-2014 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -21,6 +21,7 @@ #include FT_INTERNAL_DEBUG_H #include "afglobal.h" +#include "afpic.h" #include "aflatin.h" #include "aferrors.h" @@ -61,10 +62,10 @@ FT_TRACE5(( "\n" - "latin standard widths computation (script `%s')\n" - "=================================================\n" + "latin standard widths computation (style `%s')\n" + "=====================================================\n" "\n", - af_script_names[metrics->root.script_class->script] )); + af_style_names[metrics->root.style_class->style] )); af_glyph_hints_init( hints, face->memory ); @@ -73,20 +74,66 @@ { FT_Error error; - FT_UInt glyph_index; + FT_ULong glyph_index; + FT_Long y_offset; int dim; AF_LatinMetricsRec dummy[1]; AF_Scaler scaler = &dummy->root.scaler; +#ifdef FT_CONFIG_OPTION_PIC + AF_FaceGlobals globals = metrics->root.globals; +#endif - glyph_index = FT_Get_Char_Index( - face, - metrics->root.script_class->standard_char ); - if ( glyph_index == 0 ) - goto Exit; + AF_StyleClass style_class = metrics->root.style_class; + AF_ScriptClass script_class = AF_SCRIPT_CLASSES_GET + [style_class->script]; + + FT_UInt32 standard_char; + + + /* + * We check more than a single standard character to catch features + * like `c2sc' (small caps from caps) that don't contain lowercase + * letters by definition, or other features that mainly operate on + * numerals. + */ + + standard_char = script_class->standard_char1; + af_get_char_index( &metrics->root, + standard_char, + &glyph_index, + &y_offset ); + if ( !glyph_index ) + { + if ( script_class->standard_char2 ) + { + standard_char = script_class->standard_char2; + af_get_char_index( &metrics->root, + standard_char, + &glyph_index, + &y_offset ); + if ( !glyph_index ) + { + if ( script_class->standard_char3 ) + { + standard_char = script_class->standard_char3; + af_get_char_index( &metrics->root, + standard_char, + &glyph_index, + &y_offset ); + if ( !glyph_index ) + goto Exit; + } + else + goto Exit; + } + } + else + goto Exit; + } FT_TRACE5(( "standard character: U+%04lX (glyph index %d)\n", - metrics->root.script_class->standard_char, glyph_index )); + standard_char, glyph_index )); error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE ); if ( error || face->glyph->outline.n_points <= 0 ) @@ -105,7 +152,7 @@ scaler->render_mode = FT_RENDER_MODE_NORMAL; scaler->flags = 0; - af_glyph_hints_rescale( hints, (AF_ScriptMetrics)dummy ); + af_glyph_hints_rescale( hints, (AF_StyleMetrics)dummy ); error = af_glyph_hints_reload( hints, &face->glyph->outline ); if ( error ) @@ -124,7 +171,15 @@ if ( error ) goto Exit; + /* + * We assume that the glyphs selected for the stem width + * computation are `featureless' enough so that the linking + * algorithm works fine without adjustments of its scoring + * function. + */ af_latin_hints_link_segments( hints, + 0, + NULL, (AF_Dimension)dim ); seg = axhints->segments; @@ -214,12 +269,14 @@ AF_LatinAxis axis = &metrics->axis[AF_DIMENSION_VERT]; FT_Outline outline; - AF_Blue_Stringset bss = metrics->root.script_class->blue_stringset; + AF_StyleClass sc = metrics->root.style_class; + + AF_Blue_Stringset bss = sc->blue_stringset; const AF_Blue_StringRec* bs = &af_blue_stringsets[bss]; - /* we walk over the blue character strings as specified in the */ - /* script's entry in the `af_blue_stringset' array */ + /* we walk over the blue character strings as specified in the */ + /* style's entry in the `af_blue_stringset' array */ FT_TRACE5(( "latin blue zones computation\n" "============================\n" @@ -249,6 +306,14 @@ have_flag = 1; } + if ( AF_LATIN_IS_NEUTRAL_BLUE( bs ) ) + { + if ( have_flag ) + FT_TRACE5(( ", " )); + FT_TRACE5(( "neutral" )); + have_flag = 1; + } + if ( AF_LATIN_IS_X_HEIGHT_BLUE( bs ) ) { if ( have_flag ) @@ -277,7 +342,8 @@ while ( *p ) { FT_ULong ch; - FT_UInt glyph_index; + FT_ULong glyph_index; + FT_Long y_offset; FT_Pos best_y; /* same as points.y */ FT_Int best_point, best_contour_first, best_contour_last; FT_Vector* points; @@ -287,7 +353,7 @@ GET_UTF8_CHAR( ch, p ); /* load the character in the face -- skip unknown or empty ones */ - glyph_index = FT_Get_Char_Index( face, ch ); + af_get_char_index( &metrics->root, ch, &glyph_index, &y_offset ); if ( glyph_index == 0 ) { FT_TRACE5(( " U+%04lX unavailable\n", ch )); @@ -470,6 +536,13 @@ FT_Int last; FT_Bool hit; + /* we intentionally declare these two variables */ + /* outside of the loop since various compilers emit */ + /* incorrect warning messages otherwise, talking about */ + /* `possibly uninitialized variables' */ + FT_Int p_first = 0; /* make compiler happy */ + FT_Int p_last = 0; + FT_Bool left2right; @@ -502,7 +575,6 @@ { FT_Bool l2r; FT_Pos d; - FT_Int p_first, p_last; if ( !hit ) @@ -575,7 +647,10 @@ if ( FT_ABS( points[next].x - points[first].x ) <= 20 * dist ) { - last--; + if ( last > best_contour_first ) + last--; + else + last = best_contour_last; break; } @@ -606,6 +681,12 @@ } } + /* for computing blue zones, we add the y offset as returned */ + /* by the currently used OpenType feature -- for example, */ + /* superscript glyphs might be identical to subscript glyphs */ + /* with a vertical shift */ + best_y += y_offset; + FT_TRACE5(( " U+%04lX: best_y = %5ld", ch, best_y )); /* now set the `round' flag depending on the segment's kind: */ @@ -629,6 +710,13 @@ FT_CURVE_TAG( outline.tags[best_segment_last] ) != FT_CURVE_TAG_ON ); + if ( round && AF_LATIN_IS_NEUTRAL_BLUE( bs ) ) + { + /* only use flat segments for a neutral blue zone */ + FT_TRACE5(( " (round, skipped)\n" )); + continue; + } + FT_TRACE5(( " (%s)\n", round ? "round" : "flat" )); } @@ -699,6 +787,8 @@ blue->flags = 0; if ( AF_LATIN_IS_TOP_BLUE( bs ) ) blue->flags |= AF_LATIN_BLUE_TOP; + if ( AF_LATIN_IS_NEUTRAL_BLUE( bs ) ) + blue->flags |= AF_LATIN_BLUE_NEUTRAL; /* * The following flag is used later to adjust the y and x scales @@ -733,10 +823,11 @@ /* digit `0' is 0x30 in all supported charmaps */ for ( i = 0x30; i <= 0x39; i++ ) { - FT_UInt glyph_index; + FT_ULong glyph_index; + FT_Long y_offset; - glyph_index = FT_Get_Char_Index( face, i ); + af_get_char_index( &metrics->root, i, &glyph_index, &y_offset ); if ( glyph_index == 0 ) continue; @@ -879,11 +970,11 @@ FT_TRACE5(( "af_latin_metrics_scale_dim:" - " x height alignment (script `%s'):\n" + " x height alignment (style `%s'):\n" " " " vertical scaling changed from %.4f to %.4f (by %d%%)\n" "\n", - af_script_names[metrics->root.script_class->script], + af_style_names[metrics->root.style_class->style], axis->org_scale / 65536.0, scale / 65536.0, ( fitted - scaled ) * 100 / scaled )); @@ -906,9 +997,9 @@ metrics->root.scaler.y_delta = delta; } - FT_TRACE5(( "%s widths (script `%s')\n", + FT_TRACE5(( "%s widths (style `%s')\n", dim == AF_DIMENSION_HORZ ? "horizontal" : "vertical", - af_script_names[metrics->root.script_class->script] )); + af_style_names[metrics->root.style_class->style] )); /* scale the widths */ for ( nn = 0; nn < axis->width_count; nn++ ) @@ -933,15 +1024,15 @@ #ifdef FT_DEBUG_LEVEL_TRACE if ( axis->extra_light ) - FT_TRACE5(( "`%s' script is extra light (at current resolution)\n" + FT_TRACE5(( "`%s' style is extra light (at current resolution)\n" "\n", - af_script_names[metrics->root.script_class->script] )); + af_style_names[metrics->root.style_class->style] )); #endif if ( dim == AF_DIMENSION_VERT ) { - FT_TRACE5(( "blue zones (script `%s')\n", - af_script_names[metrics->root.script_class->script] )); + FT_TRACE5(( "blue zones (style `%s')\n", + af_style_names[metrics->root.style_class->style] )); /* scale the blue zones */ for ( nn = 0; nn < axis->blue_count; nn++ ) @@ -1277,25 +1368,40 @@ } - /* Link segments to form stems and serifs. */ + /* Link segments to form stems and serifs. If `width_count' and */ + /* `widths' are non-zero, use them to fine-tune the scoring function. */ FT_LOCAL_DEF( void ) af_latin_hints_link_segments( AF_GlyphHints hints, + FT_UInt width_count, + AF_WidthRec* widths, AF_Dimension dim ) { AF_AxisHints axis = &hints->axis[dim]; AF_Segment segments = axis->segments; AF_Segment segment_limit = segments + axis->num_segments; - FT_Pos len_threshold, len_score; + FT_Pos len_threshold, len_score, dist_score, max_width; AF_Segment seg1, seg2; + if ( width_count ) + max_width = widths[width_count - 1].org; + else + max_width = 0; + + /* a heuristic value to set up a minimum value for overlapping */ len_threshold = AF_LATIN_CONSTANT( hints->metrics, 8 ); if ( len_threshold == 0 ) len_threshold = 1; + /* a heuristic value to weight lengths */ len_score = AF_LATIN_CONSTANT( hints->metrics, 6000 ); + /* a heuristic value to weight distances (no call to */ + /* AF_LATIN_CONSTANT needed, since we work on multiples */ + /* of the stem width) */ + dist_score = 3000; + /* now compare each segment to the others */ for ( seg1 = segments; seg1 < segment_limit; seg1++ ) { @@ -1315,10 +1421,9 @@ if ( seg1->dir + seg2->dir == 0 && pos2 > pos1 ) { /* compute distance between the two segments */ - FT_Pos dist = pos2 - pos1; - FT_Pos min = seg1->min_coord; - FT_Pos max = seg1->max_coord; - FT_Pos len, score; + FT_Pos min = seg1->min_coord; + FT_Pos max = seg1->max_coord; + FT_Pos len; if ( min < seg2->min_coord ) @@ -1328,15 +1433,49 @@ max = seg2->max_coord; /* compute maximum coordinate difference of the two segments */ + /* (this is, how much they overlap) */ len = max - min; if ( len >= len_threshold ) { - /* small coordinate differences cause a higher score, and */ - /* segments with a greater distance cause a higher score also */ - score = dist + len_score / len; + /* + * The score is the sum of two demerits indicating the + * `badness' of a fit, measured along the segments' main axis + * and orthogonal to it, respectively. + * + * o The less overlapping along the main axis, the worse it + * is, causing a larger demerit. + * + * o The nearer the orthogonal distance to a stem width, the + * better it is, causing a smaller demerit. For simplicity, + * however, we only increase the demerit for values that + * exceed the largest stem width. + */ + + FT_Pos dist = pos2 - pos1; + + FT_Pos dist_demerit, score; + + + if ( max_width ) + { + /* distance demerits are based on multiples of `max_width'; */ + /* we scale by 1024 for getting more precision */ + FT_Pos delta = ( dist << 10 ) / max_width - ( 1 << 10 ); + + + if ( delta > 10000 ) + dist_demerit = 32000; + else if ( delta > 0 ) + dist_demerit = delta * delta / dist_score; + else + dist_demerit = 0; + } + else + dist_demerit = dist; /* default if no widths available */ + + score = dist_demerit + len_score / len; /* and we search for the smallest score */ - /* of the sum of the two values */ if ( score < seg1->score ) { seg1->score = score; @@ -1668,6 +1807,8 @@ FT_LOCAL_DEF( FT_Error ) af_latin_hints_detect_features( AF_GlyphHints hints, + FT_UInt width_count, + AF_WidthRec* widths, AF_Dimension dim ) { FT_Error error; @@ -1676,7 +1817,7 @@ error = af_latin_hints_compute_segments( hints, dim ); if ( !error ) { - af_latin_hints_link_segments( hints, dim ); + af_latin_hints_link_segments( hints, width_count, widths, dim ); error = af_latin_hints_compute_edges( hints, dim ); } @@ -1705,8 +1846,9 @@ for ( ; edge < edge_limit; edge++ ) { FT_UInt bb; - AF_Width best_blue = NULL; - FT_Pos best_dist; /* initial threshold */ + AF_Width best_blue = NULL; + FT_Bool best_blue_is_neutral = 0; + FT_Pos best_dist; /* initial threshold */ /* compute the initial threshold as a fraction of the EM size */ @@ -1720,24 +1862,26 @@ for ( bb = 0; bb < latin->blue_count; bb++ ) { AF_LatinBlue blue = latin->blues + bb; - FT_Bool is_top_blue, is_major_dir; + FT_Bool is_top_blue, is_neutral_blue, is_major_dir; /* skip inactive blue zones (i.e., those that are too large) */ if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) ) continue; - /* if it is a top zone, check for right edges -- if it is a bottom */ - /* zone, check for left edges */ - /* */ - /* of course, that's for TrueType */ - is_top_blue = (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 ); - is_major_dir = FT_BOOL( edge->dir == axis->major_dir ); - - /* if it is a top zone, the edge must be against the major */ - /* direction; if it is a bottom zone, it must be in the major */ - /* direction */ - if ( is_top_blue ^ is_major_dir ) + /* if it is a top zone, check for right edges (against the major */ + /* direction); if it is a bottom zone, check for left edges (in */ + /* the major direction) -- this assumes the TrueType convention */ + /* for the orientation of contours */ + is_top_blue = + (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 ); + is_neutral_blue = + (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_NEUTRAL ) != 0); + is_major_dir = + FT_BOOL( edge->dir == axis->major_dir ); + + /* neutral blue zones are handled for both directions */ + if ( is_top_blue ^ is_major_dir || is_neutral_blue ) { FT_Pos dist; @@ -1750,15 +1894,19 @@ dist = FT_MulFix( dist, scale ); if ( dist < best_dist ) { - best_dist = dist; - best_blue = &blue->ref; + best_dist = dist; + best_blue = &blue->ref; + best_blue_is_neutral = is_neutral_blue; } /* now compare it to the overshoot position and check whether */ /* the edge is rounded, and whether the edge is over the */ /* reference position of a top zone, or under the reference */ - /* position of a bottom zone */ - if ( edge->flags & AF_EDGE_ROUND && dist != 0 ) + /* position of a bottom zone (provided we don't have a */ + /* neutral blue zone) */ + if ( edge->flags & AF_EDGE_ROUND && + dist != 0 && + !is_neutral_blue ) { FT_Bool is_under_ref = FT_BOOL( edge->fpos < blue->ref.org ); @@ -1772,8 +1920,9 @@ dist = FT_MulFix( dist, scale ); if ( dist < best_dist ) { - best_dist = dist; - best_blue = &blue->shoot; + best_dist = dist; + best_blue = &blue->shoot; + best_blue_is_neutral = is_neutral_blue; } } } @@ -1781,7 +1930,11 @@ } if ( best_blue ) + { edge->blue_edge = best_blue; + if ( best_blue_is_neutral ) + edge->flags |= AF_EDGE_NEUTRAL; + } } } @@ -1797,7 +1950,7 @@ FT_Face face = metrics->root.scaler.face; - af_glyph_hints_rescale( hints, (AF_ScriptMetrics)metrics ); + af_glyph_hints_rescale( hints, (AF_StyleMetrics)metrics ); /* * correct x_scale and y_scale if needed, since they may have @@ -2099,7 +2252,7 @@ FT_TRACE5(( " LINK: edge %d (opos=%.2f) linked to %.2f," " dist was %.2f, now %.2f\n", - stem_edge-hints->axis[dim].edges, stem_edge->opos / 64.0, + stem_edge - hints->axis[dim].edges, stem_edge->opos / 64.0, stem_edge->pos / 64.0, dist / 64.0, fitted_width / 64.0 )); } @@ -2148,9 +2301,9 @@ #endif - FT_TRACE5(( "latin %s edge hinting (script `%s')\n", + FT_TRACE5(( "latin %s edge hinting (style `%s')\n", dim == AF_DIMENSION_VERT ? "horizontal" : "vertical", - af_script_names[hints->metrics->script_class->script] )); + af_style_names[hints->metrics->style_class->style] )); /* we begin by aligning all stems relative to the blue zone */ /* if needed -- that's only for horizontal edges */ @@ -2166,14 +2319,41 @@ if ( edge->flags & AF_EDGE_DONE ) continue; - blue = edge->blue_edge; edge1 = NULL; edge2 = edge->link; + /* + * If a stem contains both a neutral and a non-neutral blue zone, + * skip the neutral one. Otherwise, outlines with different + * directions might be incorrectly aligned at the same vertical + * position. + * + * If we have two neutral blue zones, skip one of them. + * + */ + if ( edge->blue_edge && edge2 && edge2->blue_edge ) + { + FT_Byte neutral = edge->flags & AF_EDGE_NEUTRAL; + FT_Byte neutral2 = edge2->flags & AF_EDGE_NEUTRAL; + + + if ( ( neutral && neutral2 ) || neutral2 ) + { + edge2->blue_edge = NULL; + edge2->flags &= ~AF_EDGE_NEUTRAL; + } + else if ( neutral ) + { + edge->blue_edge = NULL; + edge->flags &= ~AF_EDGE_NEUTRAL; + } + } + + blue = edge->blue_edge; if ( blue ) edge1 = edge; - /* flip edges if the other stem is aligned to a blue zone */ + /* flip edges if the other edge is aligned to a blue zone */ else if ( edge2 && edge2->blue_edge ) { blue = edge2->blue_edge; @@ -2240,7 +2420,7 @@ /* this should not happen, but it's better to be safe */ if ( edge2->blue_edge ) { - FT_TRACE5(( " ASSERTION FAILED for edge %d\n", edge2-edges )); + FT_TRACE5(( " ASSERTION FAILED for edge %d\n", edge2 - edges )); af_latin_align_linked_edge( hints, dim, edge2, edge ); edge->flags |= AF_EDGE_DONE; @@ -2629,6 +2809,8 @@ FT_Error error; int dim; + AF_LatinAxis axis; + error = af_glyph_hints_reload( hints, outline ); if ( error ) @@ -2642,14 +2824,22 @@ if ( AF_HINTS_DO_HORIZONTAL( hints ) ) #endif { - error = af_latin_hints_detect_features( hints, AF_DIMENSION_HORZ ); + axis = &metrics->axis[AF_DIMENSION_HORZ]; + error = af_latin_hints_detect_features( hints, + axis->width_count, + axis->widths, + AF_DIMENSION_HORZ ); if ( error ) goto Exit; } if ( AF_HINTS_DO_VERTICAL( hints ) ) { - error = af_latin_hints_detect_features( hints, AF_DIMENSION_VERT ); + axis = &metrics->axis[AF_DIMENSION_VERT]; + error = af_latin_hints_detect_features( hints, + axis->width_count, + axis->widths, + AF_DIMENSION_VERT ); if ( error ) goto Exit; @@ -2709,111 +2899,12 @@ sizeof ( AF_LatinMetricsRec ), - (AF_Script_InitMetricsFunc) af_latin_metrics_init, - (AF_Script_ScaleMetricsFunc)af_latin_metrics_scale, - (AF_Script_DoneMetricsFunc) NULL, - - (AF_Script_InitHintsFunc) af_latin_hints_init, - (AF_Script_ApplyHintsFunc) af_latin_hints_apply - ) - - - /* XXX: this should probably fine tuned to differentiate better between */ - /* scripts... */ - - static const AF_Script_UniRangeRec af_latn_uniranges[] = - { - AF_UNIRANGE_REC( 0x0020UL, 0x007FUL ), /* Basic Latin (no control chars) */ - AF_UNIRANGE_REC( 0x00A0UL, 0x00FFUL ), /* Latin-1 Supplement (no control chars) */ - AF_UNIRANGE_REC( 0x0100UL, 0x017FUL ), /* Latin Extended-A */ - AF_UNIRANGE_REC( 0x0180UL, 0x024FUL ), /* Latin Extended-B */ - AF_UNIRANGE_REC( 0x0250UL, 0x02AFUL ), /* IPA Extensions */ - AF_UNIRANGE_REC( 0x02B0UL, 0x02FFUL ), /* Spacing Modifier Letters */ - AF_UNIRANGE_REC( 0x0300UL, 0x036FUL ), /* Combining Diacritical Marks */ - AF_UNIRANGE_REC( 0x1D00UL, 0x1D7FUL ), /* Phonetic Extensions */ - AF_UNIRANGE_REC( 0x1D80UL, 0x1DBFUL ), /* Phonetic Extensions Supplement */ - AF_UNIRANGE_REC( 0x1DC0UL, 0x1DFFUL ), /* Combining Diacritical Marks Supplement */ - AF_UNIRANGE_REC( 0x1E00UL, 0x1EFFUL ), /* Latin Extended Additional */ - AF_UNIRANGE_REC( 0x2000UL, 0x206FUL ), /* General Punctuation */ - AF_UNIRANGE_REC( 0x2070UL, 0x209FUL ), /* Superscripts and Subscripts */ - AF_UNIRANGE_REC( 0x20A0UL, 0x20CFUL ), /* Currency Symbols */ - AF_UNIRANGE_REC( 0x2150UL, 0x218FUL ), /* Number Forms */ - AF_UNIRANGE_REC( 0x2460UL, 0x24FFUL ), /* Enclosed Alphanumerics */ - AF_UNIRANGE_REC( 0x2C60UL, 0x2C7FUL ), /* Latin Extended-C */ - AF_UNIRANGE_REC( 0x2E00UL, 0x2E7FUL ), /* Supplemental Punctuation */ - AF_UNIRANGE_REC( 0xA720UL, 0xA7FFUL ), /* Latin Extended-D */ - AF_UNIRANGE_REC( 0xFB00UL, 0xFB06UL ), /* Alphab. Present. Forms (Latin Ligs) */ - AF_UNIRANGE_REC( 0x1D400UL, 0x1D7FFUL ), /* Mathematical Alphanumeric Symbols */ - AF_UNIRANGE_REC( 0x1F100UL, 0x1F1FFUL ), /* Enclosed Alphanumeric Supplement */ - AF_UNIRANGE_REC( 0UL, 0UL ) - }; - - static const AF_Script_UniRangeRec af_grek_uniranges[] = - { - AF_UNIRANGE_REC( 0x0370UL, 0x03FFUL ), /* Greek and Coptic */ - AF_UNIRANGE_REC( 0x1F00UL, 0x1FFFUL ), /* Greek Extended */ - AF_UNIRANGE_REC( 0UL, 0UL ) - }; - - static const AF_Script_UniRangeRec af_cyrl_uniranges[] = - { - AF_UNIRANGE_REC( 0x0400UL, 0x04FFUL ), /* Cyrillic */ - AF_UNIRANGE_REC( 0x0500UL, 0x052FUL ), /* Cyrillic Supplement */ - AF_UNIRANGE_REC( 0x2DE0UL, 0x2DFFUL ), /* Cyrillic Extended-A */ - AF_UNIRANGE_REC( 0xA640UL, 0xA69FUL ), /* Cyrillic Extended-B */ - AF_UNIRANGE_REC( 0UL, 0UL ) - }; - - static const AF_Script_UniRangeRec af_hebr_uniranges[] = - { - AF_UNIRANGE_REC( 0x0590UL, 0x05FFUL ), /* Hebrew */ - AF_UNIRANGE_REC( 0xFB1DUL, 0xFB4FUL ), /* Alphab. Present. Forms (Hebrew) */ - AF_UNIRANGE_REC( 0UL, 0UL ) - }; - - - AF_DEFINE_SCRIPT_CLASS( - af_latn_script_class, - - AF_SCRIPT_LATN, - AF_BLUE_STRINGSET_LATN, - AF_WRITING_SYSTEM_LATIN, - - af_latn_uniranges, - 'o' - ) - - AF_DEFINE_SCRIPT_CLASS( - af_grek_script_class, - - AF_SCRIPT_GREK, - AF_BLUE_STRINGSET_GREK, - AF_WRITING_SYSTEM_LATIN, - - af_grek_uniranges, - 0x3BF /* ο */ - ) - - AF_DEFINE_SCRIPT_CLASS( - af_cyrl_script_class, - - AF_SCRIPT_CYRL, - AF_BLUE_STRINGSET_CYRL, - AF_WRITING_SYSTEM_LATIN, - - af_cyrl_uniranges, - 0x43E /* о */ - ) - - AF_DEFINE_SCRIPT_CLASS( - af_hebr_script_class, - - AF_SCRIPT_HEBR, - AF_BLUE_STRINGSET_HEBR, - AF_WRITING_SYSTEM_LATIN, + (AF_WritingSystem_InitMetricsFunc) af_latin_metrics_init, + (AF_WritingSystem_ScaleMetricsFunc)af_latin_metrics_scale, + (AF_WritingSystem_DoneMetricsFunc) NULL, - af_hebr_uniranges, - 0x5DD /* ם */ + (AF_WritingSystem_InitHintsFunc) af_latin_hints_init, + (AF_WritingSystem_ApplyHintsFunc) af_latin_hints_apply ) diff --git a/src/autofit/aflatin.h b/src/autofit/aflatin.h index c06cbd9..2c0bfca 100644 --- a/src/autofit/aflatin.h +++ b/src/autofit/aflatin.h @@ -2,9 +2,10 @@ /* */ /* aflatin.h */ /* */ -/* Auto-fitter hinting routines for latin script (specification). */ +/* Auto-fitter hinting routines for latin writing system */ +/* (specification). */ /* */ -/* Copyright 2003-2007, 2009, 2011-2013 by */ +/* Copyright 2003-2007, 2009, 2011-2014 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -29,17 +30,6 @@ FT_BEGIN_HEADER AF_DECLARE_WRITING_SYSTEM_CLASS( af_latin_writing_system_class ) - /* the latin-specific script classes */ - - AF_DECLARE_SCRIPT_CLASS( af_cyrl_script_class ) - AF_DECLARE_SCRIPT_CLASS( af_grek_script_class ) - AF_DECLARE_SCRIPT_CLASS( af_latn_script_class ) - AF_DECLARE_SCRIPT_CLASS( af_hebr_script_class ) -#if 0 - AF_DECLARE_SCRIPT_CLASS( af_armn_script_class ) -#endif - - /* 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 ) @@ -56,13 +46,15 @@ FT_BEGIN_HEADER /* * The following declarations could be embedded in the file `aflatin.c'; - * they have been made semi-public to allow alternate script hinters to - * re-use some of them. + * 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_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 ) \ @@ -73,10 +65,11 @@ FT_BEGIN_HEADER enum { - AF_LATIN_BLUE_ACTIVE = 1 << 0, /* set if zone height is <= 3/4px */ - AF_LATIN_BLUE_TOP = 1 << 1, /* result of AF_LATIN_IS_TOP_BLUE */ - AF_LATIN_BLUE_ADJUSTMENT = 1 << 2, /* used for scale adjustment */ - /* optimization */ + AF_LATIN_BLUE_ACTIVE = 1 << 0, /* set if zone height is <= 3/4px */ + AF_LATIN_BLUE_TOP = 1 << 1, /* set if we have a top blue zone */ + AF_LATIN_BLUE_NEUTRAL = 1 << 2, /* set if we have neutral blue zone */ + AF_LATIN_BLUE_ADJUSTMENT = 1 << 3, /* used for scale adjustment */ + /* optimization */ AF_LATIN_BLUE_FLAG_MAX }; @@ -113,9 +106,9 @@ FT_BEGIN_HEADER typedef struct AF_LatinMetricsRec_ { - AF_ScriptMetricsRec root; - FT_UInt units_per_em; - AF_LatinAxisRec axis[AF_DIMENSION_MAX]; + AF_StyleMetricsRec root; + FT_UInt units_per_em; + AF_LatinAxisRec axis[AF_DIMENSION_MAX]; } AF_LatinMetricsRec, *AF_LatinMetrics; @@ -171,7 +164,7 @@ FT_BEGIN_HEADER /* * The next functions shouldn't normally be exported. However, other - * scripts might like to use these functions as-is. + * writing systems might like to use these functions as-is. */ FT_LOCAL( FT_Error ) af_latin_hints_compute_segments( AF_GlyphHints hints, @@ -179,6 +172,8 @@ FT_BEGIN_HEADER 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 ) @@ -187,6 +182,8 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) af_latin_hints_detect_features( AF_GlyphHints hints, + FT_UInt width_count, + AF_WidthRec* widths, AF_Dimension dim ); /* */ diff --git a/src/autofit/aflatin2.c b/src/autofit/aflatin2.c index a6d564a..930fa98 100644 --- a/src/autofit/aflatin2.c +++ b/src/autofit/aflatin2.c @@ -2,7 +2,7 @@ /* */ /* aflatin2.c */ /* */ -/* Auto-fitter hinting routines for latin script (body). */ +/* Auto-fitter hinting routines for latin writing system (body). */ /* */ /* Copyright 2003-2013 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ @@ -78,7 +78,7 @@ glyph_index = FT_Get_Char_Index( face, - metrics->root.script_class->standard_char ); + metrics->root.style_class->standard_char ); if ( glyph_index == 0 ) goto Exit; @@ -95,7 +95,7 @@ scaler->render_mode = FT_RENDER_MODE_NORMAL; scaler->flags = 0; - af_glyph_hints_rescale( hints, (AF_ScriptMetrics)dummy ); + af_glyph_hints_rescale( hints, (AF_StyleMetrics)dummy ); error = af_glyph_hints_reload( hints, &face->glyph->outline ); if ( error ) @@ -1501,7 +1501,7 @@ FT_Face face = metrics->root.scaler.face; - af_glyph_hints_rescale( hints, (AF_ScriptMetrics)metrics ); + af_glyph_hints_rescale( hints, (AF_StyleMetrics)metrics ); /* * correct x_scale and y_scale if needed, since they may have @@ -2387,61 +2387,12 @@ sizeof ( AF_LatinMetricsRec ), - (AF_Script_InitMetricsFunc) af_latin2_metrics_init, - (AF_Script_ScaleMetricsFunc)af_latin2_metrics_scale, - (AF_Script_DoneMetricsFunc) NULL, + (AF_WritingSystem_InitMetricsFunc) af_latin2_metrics_init, + (AF_WritingSystem_ScaleMetricsFunc)af_latin2_metrics_scale, + (AF_WritingSystem_DoneMetricsFunc) NULL, - (AF_Script_InitHintsFunc) af_latin2_hints_init, - (AF_Script_ApplyHintsFunc) af_latin2_hints_apply - ) - - - /* XXX: this should probably fine tuned to differentiate better between */ - /* scripts... */ - - static const AF_Script_UniRangeRec af_ltn2_uniranges[] = - { - AF_UNIRANGE_REC( 0x0020UL, 0x007FUL ), /* Basic Latin (no control chars) */ - AF_UNIRANGE_REC( 0x00A0UL, 0x00FFUL ), /* Latin-1 Supplement (no control chars) */ - AF_UNIRANGE_REC( 0x0100UL, 0x017FUL ), /* Latin Extended-A */ - AF_UNIRANGE_REC( 0x0180UL, 0x024FUL ), /* Latin Extended-B */ - AF_UNIRANGE_REC( 0x0250UL, 0x02AFUL ), /* IPA Extensions */ - AF_UNIRANGE_REC( 0x02B0UL, 0x02FFUL ), /* Spacing Modifier Letters */ - AF_UNIRANGE_REC( 0x0300UL, 0x036FUL ), /* Combining Diacritical Marks */ - AF_UNIRANGE_REC( 0x0370UL, 0x03FFUL ), /* Greek and Coptic */ - AF_UNIRANGE_REC( 0x0400UL, 0x04FFUL ), /* Cyrillic */ - AF_UNIRANGE_REC( 0x0500UL, 0x052FUL ), /* Cyrillic Supplement */ - AF_UNIRANGE_REC( 0x1D00UL, 0x1D7FUL ), /* Phonetic Extensions */ - AF_UNIRANGE_REC( 0x1D80UL, 0x1DBFUL ), /* Phonetic Extensions Supplement */ - AF_UNIRANGE_REC( 0x1DC0UL, 0x1DFFUL ), /* Combining Diacritical Marks Supplement */ - AF_UNIRANGE_REC( 0x1E00UL, 0x1EFFUL ), /* Latin Extended Additional */ - AF_UNIRANGE_REC( 0x1F00UL, 0x1FFFUL ), /* Greek Extended */ - AF_UNIRANGE_REC( 0x2000UL, 0x206FUL ), /* General Punctuation */ - AF_UNIRANGE_REC( 0x2070UL, 0x209FUL ), /* Superscripts and Subscripts */ - AF_UNIRANGE_REC( 0x20A0UL, 0x20CFUL ), /* Currency Symbols */ - AF_UNIRANGE_REC( 0x2150UL, 0x218FUL ), /* Number Forms */ - AF_UNIRANGE_REC( 0x2460UL, 0x24FFUL ), /* Enclosed Alphanumerics */ - AF_UNIRANGE_REC( 0x2C60UL, 0x2C7FUL ), /* Latin Extended-C */ - AF_UNIRANGE_REC( 0x2DE0UL, 0x2DFFUL ), /* Cyrillic Extended-A */ - AF_UNIRANGE_REC( 0x2E00UL, 0x2E7FUL ), /* Supplemental Punctuation */ - AF_UNIRANGE_REC( 0xA640UL, 0xA69FUL ), /* Cyrillic Extended-B */ - AF_UNIRANGE_REC( 0xA720UL, 0xA7FFUL ), /* Latin Extended-D */ - AF_UNIRANGE_REC( 0xFB00UL, 0xFB06UL ), /* Alphab. Present. Forms (Latin Ligs) */ - AF_UNIRANGE_REC( 0x1D400UL, 0x1D7FFUL ), /* Mathematical Alphanumeric Symbols */ - AF_UNIRANGE_REC( 0x1F100UL, 0x1F1FFUL ), /* Enclosed Alphanumeric Supplement */ - AF_UNIRANGE_REC( 0UL, 0UL ) - }; - - - AF_DEFINE_SCRIPT_CLASS( - af_ltn2_script_class, - - AF_SCRIPT_LTN2, - AF_BLUE_STRINGSET_LATN, - AF_WRITING_SYSTEM_LATIN2, - - af_ltn2_uniranges, - 'o' + (AF_WritingSystem_InitHintsFunc) af_latin2_hints_init, + (AF_WritingSystem_ApplyHintsFunc) af_latin2_hints_apply ) diff --git a/src/autofit/aflatin2.h b/src/autofit/aflatin2.h index f7f6d8d..b5d252a 100644 --- a/src/autofit/aflatin2.h +++ b/src/autofit/aflatin2.h @@ -2,7 +2,8 @@ /* */ /* aflatin2.h */ /* */ -/* Auto-fitter hinting routines for latin script (specification). */ +/* Auto-fitter hinting routines for latin writing system */ +/* (specification). */ /* */ /* Copyright 2003-2007, 2012, 2013 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ @@ -30,17 +31,6 @@ FT_BEGIN_HEADER AF_DECLARE_WRITING_SYSTEM_CLASS( af_latin2_writing_system_class ) - /* the latin-specific script classes */ - - AF_DECLARE_SCRIPT_CLASS( af_ltn2_script_class ) /* XXX */ -#if 0 - AF_DECLARE_SCRIPT_CLASS( af_arm2_script_class ) - AF_DECLARE_SCRIPT_CLASS( af_cyr2_script_class ) - AF_DECLARE_SCRIPT_CLASS( af_grk2_script_class ) - AF_DECLARE_SCRIPT_CLASS( af_hbr2_script_class ) -#endif - - /* */ FT_END_HEADER diff --git a/src/autofit/afloader.c b/src/autofit/afloader.c index 400b01e..0fa3c12 100644 --- a/src/autofit/afloader.c +++ b/src/autofit/afloader.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter glyph loading routines (body). */ /* */ -/* Copyright 2003-2009, 2011-2013 by */ +/* Copyright 2003-2009, 2011-2014 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -109,7 +109,7 @@ FT_Error error; FT_Face face = loader->face; FT_GlyphLoader gloader = loader->gloader; - AF_ScriptMetrics metrics = loader->metrics; + AF_StyleMetrics metrics = loader->metrics; AF_GlyphHints hints = &loader->hints; FT_GlyphSlot slot = face->glyph; FT_Slot_Internal internal = slot->internal; @@ -183,17 +183,17 @@ /* automatic hinting process */ { #ifdef FT_CONFIG_OPTION_PIC - AF_FaceGlobals globals = loader->globals; + AF_FaceGlobals globals = loader->globals; #endif + AF_StyleClass style_class = metrics->style_class; AF_WritingSystemClass writing_system_class = - AF_WRITING_SYSTEM_CLASSES_GET - [metrics->script_class->writing_system]; + AF_WRITING_SYSTEM_CLASSES_GET[style_class->writing_system]; - if ( writing_system_class->script_hints_apply ) - writing_system_class->script_hints_apply( hints, - &gloader->current.outline, - metrics ); + if ( writing_system_class->style_hints_apply ) + writing_system_class->style_hints_apply( hints, + &gloader->current.outline, + metrics ); } /* we now need to adjust the metrics according to the change in */ @@ -318,12 +318,7 @@ /* recompute subglyph pointer */ subglyph = gloader->base.subglyphs + num_base_subgs + nn; - if ( subglyph->flags & FT_SUBGLYPH_FLAG_USE_MY_METRICS ) - { - pp1 = loader->pp1; - pp2 = loader->pp2; - } - else + if ( !( subglyph->flags & FT_SUBGLYPH_FLAG_USE_MY_METRICS ) ) { loader->pp1 = pp1; loader->pp2 = pp2; @@ -529,14 +524,14 @@ error = af_loader_reset( module, face ); if ( !error ) { - AF_ScriptMetrics metrics; - FT_UInt options = AF_SCRIPT_NONE; + AF_StyleMetrics metrics; + FT_UInt options = AF_STYLE_NONE_DFLT; #ifdef FT_OPTION_AUTOFIT2 /* XXX: undocumented hook to activate the latin2 writing system */ if ( load_flags & ( 1UL << 20 ) ) - options = AF_SCRIPT_LTN2; + options = AF_STYLE_LTN2_DFLT; #endif error = af_face_globals_get_metrics( loader->globals, gindex, @@ -544,27 +539,27 @@ if ( !error ) { #ifdef FT_CONFIG_OPTION_PIC - AF_FaceGlobals globals = loader->globals; + AF_FaceGlobals globals = loader->globals; #endif + AF_StyleClass style_class = metrics->style_class; AF_WritingSystemClass writing_system_class = - AF_WRITING_SYSTEM_CLASSES_GET - [metrics->script_class->writing_system]; + AF_WRITING_SYSTEM_CLASSES_GET[style_class->writing_system]; loader->metrics = metrics; - if ( writing_system_class->script_metrics_scale ) - writing_system_class->script_metrics_scale( metrics, &scaler ); + if ( writing_system_class->style_metrics_scale ) + writing_system_class->style_metrics_scale( metrics, &scaler ); else metrics->scaler = scaler; load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_TRANSFORM; load_flags &= ~FT_LOAD_RENDER; - if ( writing_system_class->script_hints_init ) + if ( writing_system_class->style_hints_init ) { - error = writing_system_class->script_hints_init( &loader->hints, - metrics ); + error = writing_system_class->style_hints_init( &loader->hints, + metrics ); if ( error ) goto Exit; } diff --git a/src/autofit/afloader.h b/src/autofit/afloader.h index 1f34d17..9601e24 100644 --- a/src/autofit/afloader.h +++ b/src/autofit/afloader.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter glyph loading routines (specification). */ /* */ -/* Copyright 2003-2005, 2011-2012 by */ +/* Copyright 2003-2005, 2011-2013 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -44,7 +44,7 @@ FT_BEGIN_HEADER /* current glyph data */ FT_GlyphLoader gloader; AF_GlyphHintsRec hints; - AF_ScriptMetrics metrics; + AF_StyleMetrics metrics; FT_Bool transformed; FT_Matrix trans_matrix; FT_Vector trans_delta; diff --git a/src/autofit/afmodule.c b/src/autofit/afmodule.c index b1bb5ee..181cf55 100644 --- a/src/autofit/afmodule.c +++ b/src/autofit/afmodule.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter module implementation (body). */ /* */ -/* Copyright 2003-2006, 2009, 2011-2013 by */ +/* Copyright 2003-2006, 2009, 2011-2014 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -45,7 +45,7 @@ #define FT_COMPONENT trace_afmodule - FT_Error + static FT_Error af_property_get_face_globals( FT_Face face, AF_FaceGlobals* aglobals, AF_Module module ) @@ -60,8 +60,8 @@ globals = (AF_FaceGlobals)face->autohint.data; if ( !globals ) { - /* trigger computation of the global script data */ - /* in case it hasn't been done yet */ + /* 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 ) { @@ -79,7 +79,7 @@ } - FT_Error + static FT_Error af_property_set( FT_Module ft_module, const char* property_name, const void* value ) @@ -92,8 +92,40 @@ { FT_UInt* fallback_script = (FT_UInt*)value; + FT_UInt ss; - module->fallback_script = *fallback_script; + + /* 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_GET[ss]; ss++ ) + { + AF_StyleClass style_class = AF_STYLE_CLASSES_GET[ss]; + + + if ( (FT_UInt)style_class->script == *fallback_script && + style_class->coverage == AF_COVERAGE_DEFAULT ) + { + module->fallback_style = ss; + break; + } + } + + if ( !AF_STYLE_CLASSES_GET[ss] ) + { + FT_TRACE0(( "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" ) ) + { + FT_UInt* default_script = (FT_UInt*)value; + + + module->default_script = *default_script; return error; } @@ -116,14 +148,15 @@ } - FT_Error + 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; - FT_UInt fallback_script = module->fallback_script; + FT_Error error = FT_Err_Ok; + AF_Module module = (AF_Module)ft_module; + FT_UInt fallback_style = module->fallback_style; + FT_UInt default_script = module->default_script; if ( !ft_strcmp( property_name, "glyph-to-script-map" ) ) @@ -134,7 +167,7 @@ error = af_property_get_face_globals( prop->face, &globals, module ); if ( !error ) - prop->map = globals->glyph_scripts; + prop->map = globals->glyph_styles; return error; } @@ -142,8 +175,19 @@ { FT_UInt* val = (FT_UInt*)value; + AF_StyleClass style_class = AF_STYLE_CLASSES_GET[fallback_style]; + + + *val = style_class->script; + + return error; + } + else if ( !ft_strcmp( property_name, "default-script" ) ) + { + FT_UInt* val = (FT_UInt*)value; + - *val = fallback_script; + *val = default_script; return error; } @@ -206,7 +250,8 @@ AF_Module module = (AF_Module)ft_module; - module->fallback_script = AF_SCRIPT_FALLBACK; + module->fallback_style = AF_STYLE_FALLBACK; + module->default_script = AF_SCRIPT_DEFAULT; return af_loader_init( module ); } diff --git a/src/autofit/afmodule.h b/src/autofit/afmodule.h index c4e8f8f..20b7b9f 100644 --- a/src/autofit/afmodule.h +++ b/src/autofit/afmodule.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter module implementation (specification). */ /* */ -/* Copyright 2003, 2004, 2005 by */ +/* Copyright 2003-2005, 2009, 2012, 2013 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -40,7 +40,8 @@ FT_BEGIN_HEADER { FT_ModuleRec root; - FT_UInt fallback_script; + FT_UInt fallback_style; + FT_UInt default_script; AF_LoaderRec loader[1]; diff --git a/src/autofit/afpic.c b/src/autofit/afpic.c index 92d696d..cb29fd7 100644 --- a/src/autofit/afpic.c +++ b/src/autofit/afpic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for autofit module. */ /* */ -/* Copyright 2009-2013 by */ +/* Copyright 2009-2014 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -20,6 +20,7 @@ #include FT_FREETYPE_H #include FT_INTERNAL_OBJECTS_H #include "afpic.h" +#include "afglobal.h" #include "aferrors.h" @@ -42,7 +43,7 @@ FT_AutoHinter_InterfaceRec* clazz ); - /* forward declaration of PIC init functions from script classes */ + /* forward declaration of PIC init functions from writing system classes */ #undef WRITING_SYSTEM #define WRITING_SYSTEM( ws, WS ) /* empty */ @@ -97,15 +98,20 @@ FT_Init_Class_af_service_properties( &container->af_service_properties ); - for ( ss = 0; ss < AF_WRITING_SYSTEM_MAX - 1; ss++ ) + for ( ss = 0; ss < AF_WRITING_SYSTEM_MAX; ss++ ) container->af_writing_system_classes[ss] = &container->af_writing_system_classes_rec[ss]; - container->af_writing_system_classes[AF_WRITING_SYSTEM_MAX - 1] = NULL; + container->af_writing_system_classes[AF_WRITING_SYSTEM_MAX] = NULL; - for ( ss = 0; ss < AF_SCRIPT_MAX - 1; ss++ ) + for ( ss = 0; ss < AF_SCRIPT_MAX; ss++ ) container->af_script_classes[ss] = &container->af_script_classes_rec[ss]; - container->af_script_classes[AF_SCRIPT_MAX - 1] = NULL; + container->af_script_classes[AF_SCRIPT_MAX] = NULL; + + for ( ss = 0; ss < AF_STYLE_MAX; ss++ ) + container->af_style_classes[ss] = + &container->af_style_classes_rec[ss]; + container->af_style_classes[AF_STYLE_MAX] = NULL; #undef WRITING_SYSTEM #define WRITING_SYSTEM( ws, WS ) \ @@ -116,13 +122,21 @@ #include "afwrtsys.h" #undef SCRIPT -#define SCRIPT( s, S, d ) \ +#define SCRIPT( s, S, d, h, sc1, sc2, sc3 ) \ FT_Init_Class_af_ ## s ## _script_class( \ &container->af_script_classes_rec[ss++] ); ss = 0; #include "afscript.h" +#undef STYLE +#define STYLE( s, S, d, ws, sc, bss, c ) \ + FT_Init_Class_af_ ## s ## _style_class( \ + &container->af_style_classes_rec[ss++] ); + + ss = 0; +#include "afstyles.h" + FT_Init_Class_af_autofitter_interface( library, &container->af_autofitter_interface ); diff --git a/src/autofit/afpic.h b/src/autofit/afpic.h index 09f8258..9a68b4a 100644 --- a/src/autofit/afpic.h +++ b/src/autofit/afpic.h @@ -32,6 +32,7 @@ FT_BEGIN_HEADER #define AF_WRITING_SYSTEM_CLASSES_GET af_writing_system_classes #define AF_SCRIPT_CLASSES_GET af_script_classes +#define AF_STYLE_CLASSES_GET af_style_classes #define AF_INTERFACE_GET af_autofitter_interface #else /* FT_CONFIG_OPTION_PIC */ @@ -48,14 +49,19 @@ FT_BEGIN_HEADER FT_Service_PropertiesRec af_service_properties; AF_WritingSystemClass af_writing_system_classes - [AF_WRITING_SYSTEM_MAX]; + [AF_WRITING_SYSTEM_MAX + 1]; AF_WritingSystemClassRec af_writing_system_classes_rec - [AF_WRITING_SYSTEM_MAX - 1]; + [AF_WRITING_SYSTEM_MAX]; AF_ScriptClass af_script_classes - [AF_SCRIPT_MAX]; + [AF_SCRIPT_MAX + 1]; AF_ScriptClassRec af_script_classes_rec - [AF_SCRIPT_MAX - 1]; + [AF_SCRIPT_MAX]; + + AF_StyleClass af_style_classes + [AF_STYLE_MAX + 1]; + AF_StyleClassRec af_style_classes_rec + [AF_STYLE_MAX]; FT_AutoHinter_InterfaceRec af_autofitter_interface; @@ -74,6 +80,8 @@ FT_BEGIN_HEADER ( GET_PIC( FT_FACE_LIBRARY( globals->face ) )->af_writing_system_classes ) #define AF_SCRIPT_CLASSES_GET \ ( GET_PIC( FT_FACE_LIBRARY( globals->face ) )->af_script_classes ) +#define AF_STYLE_CLASSES_GET \ + ( GET_PIC( FT_FACE_LIBRARY( globals->face ) )->af_style_classes ) #define AF_INTERFACE_GET \ ( GET_PIC( library )->af_autofitter_interface ) diff --git a/src/autofit/afranges.c b/src/autofit/afranges.c new file mode 100644 index 0000000..139a4c1 --- /dev/null +++ b/src/autofit/afranges.c @@ -0,0 +1,210 @@ +/***************************************************************************/ +/* */ +/* afranges.c */ +/* */ +/* Auto-fitter Unicode script ranges (body). */ +/* */ +/* Copyright 2013, 2014 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 "afranges.h" + + + const AF_Script_UniRangeRec af_cyrl_uniranges[] = + { + AF_UNIRANGE_REC( 0x0400UL, 0x04FFUL ), /* Cyrillic */ + AF_UNIRANGE_REC( 0x0500UL, 0x052FUL ), /* Cyrillic Supplement */ + AF_UNIRANGE_REC( 0x2DE0UL, 0x2DFFUL ), /* Cyrillic Extended-A */ + AF_UNIRANGE_REC( 0xA640UL, 0xA69FUL ), /* Cyrillic Extended-B */ + AF_UNIRANGE_REC( 0UL, 0UL ) + }; + + const AF_Script_UniRangeRec af_deva_uniranges[] = + { + AF_UNIRANGE_REC( 0x0900UL, 0x097FUL ), /* Devanagari */ + AF_UNIRANGE_REC( 0x20B9UL, 0x20B9UL ), /* (new) Rupee sign */ + AF_UNIRANGE_REC( 0UL, 0UL ) + }; + + const AF_Script_UniRangeRec af_grek_uniranges[] = + { + AF_UNIRANGE_REC( 0x0370UL, 0x03FFUL ), /* Greek and Coptic */ + AF_UNIRANGE_REC( 0x1F00UL, 0x1FFFUL ), /* Greek Extended */ + AF_UNIRANGE_REC( 0UL, 0UL ) + }; + + const AF_Script_UniRangeRec af_hebr_uniranges[] = + { + AF_UNIRANGE_REC( 0x0590UL, 0x05FFUL ), /* Hebrew */ + AF_UNIRANGE_REC( 0xFB1DUL, 0xFB4FUL ), /* Alphab. Present. Forms (Hebrew) */ + AF_UNIRANGE_REC( 0UL, 0UL ) + }; + + const AF_Script_UniRangeRec af_latn_uniranges[] = + { + AF_UNIRANGE_REC( 0x0020UL, 0x007FUL ), /* Basic Latin (no control chars) */ + AF_UNIRANGE_REC( 0x00A0UL, 0x00FFUL ), /* Latin-1 Supplement (no control chars) */ + AF_UNIRANGE_REC( 0x0100UL, 0x017FUL ), /* Latin Extended-A */ + AF_UNIRANGE_REC( 0x0180UL, 0x024FUL ), /* Latin Extended-B */ + AF_UNIRANGE_REC( 0x0250UL, 0x02AFUL ), /* IPA Extensions */ + AF_UNIRANGE_REC( 0x02B0UL, 0x02FFUL ), /* Spacing Modifier Letters */ + AF_UNIRANGE_REC( 0x0300UL, 0x036FUL ), /* Combining Diacritical Marks */ + AF_UNIRANGE_REC( 0x1D00UL, 0x1D7FUL ), /* Phonetic Extensions */ + AF_UNIRANGE_REC( 0x1D80UL, 0x1DBFUL ), /* Phonetic Extensions Supplement */ + AF_UNIRANGE_REC( 0x1DC0UL, 0x1DFFUL ), /* Combining Diacritical Marks Supplement */ + AF_UNIRANGE_REC( 0x1E00UL, 0x1EFFUL ), /* Latin Extended Additional */ + AF_UNIRANGE_REC( 0x2000UL, 0x206FUL ), /* General Punctuation */ + AF_UNIRANGE_REC( 0x2070UL, 0x209FUL ), /* Superscripts and Subscripts */ + AF_UNIRANGE_REC( 0x20A0UL, 0x20B8UL ), /* Currency Symbols ... */ + AF_UNIRANGE_REC( 0x20BAUL, 0x20CFUL ), /* ... except new Rupee sign */ + AF_UNIRANGE_REC( 0x2150UL, 0x218FUL ), /* Number Forms */ + AF_UNIRANGE_REC( 0x2460UL, 0x24FFUL ), /* Enclosed Alphanumerics */ + AF_UNIRANGE_REC( 0x2C60UL, 0x2C7FUL ), /* Latin Extended-C */ + AF_UNIRANGE_REC( 0x2E00UL, 0x2E7FUL ), /* Supplemental Punctuation */ + AF_UNIRANGE_REC( 0xA720UL, 0xA7FFUL ), /* Latin Extended-D */ + AF_UNIRANGE_REC( 0xFB00UL, 0xFB06UL ), /* Alphab. Present. Forms (Latin Ligs) */ + AF_UNIRANGE_REC( 0x1D400UL, 0x1D7FFUL ), /* Mathematical Alphanumeric Symbols */ + AF_UNIRANGE_REC( 0x1F100UL, 0x1F1FFUL ), /* Enclosed Alphanumeric Supplement */ + AF_UNIRANGE_REC( 0UL, 0UL ) + }; + + const AF_Script_UniRangeRec af_none_uniranges[] = + { + AF_UNIRANGE_REC( 0UL, 0UL ) + }; + +#ifdef AF_CONFIG_OPTION_INDIC + + const AF_Script_UniRangeRec af_beng_uniranges[] = + { + AF_UNIRANGE_REC( 0x0980UL, 0x09FFUL ), /* Bengali */ + AF_UNIRANGE_REC( 0UL, 0UL ) + }; + + const AF_Script_UniRangeRec af_gujr_uniranges[] = + { + AF_UNIRANGE_REC( 0x0A80UL, 0x0AFFUL ), /* Gujarati */ + AF_UNIRANGE_REC( 0UL, 0UL ) + }; + + const AF_Script_UniRangeRec af_guru_uniranges[] = + { + AF_UNIRANGE_REC( 0x0A00UL, 0x0A7FUL ), /* Gurmukhi */ + AF_UNIRANGE_REC( 0UL, 0UL ) + }; + + const AF_Script_UniRangeRec af_knda_uniranges[] = + { + AF_UNIRANGE_REC( 0x0C80UL, 0x0CFFUL ), /* Kannada */ + AF_UNIRANGE_REC( 0UL, 0UL ) + }; + + const AF_Script_UniRangeRec af_limb_uniranges[] = + { + AF_UNIRANGE_REC( 0x1900UL, 0x194FUL ), /* Limbu */ + AF_UNIRANGE_REC( 0UL, 0UL ) + }; + + const AF_Script_UniRangeRec af_mlym_uniranges[] = + { + AF_UNIRANGE_REC( 0x0D00UL, 0x0D7FUL ), /* Malayalam */ + AF_UNIRANGE_REC( 0UL, 0UL ) + }; + + const AF_Script_UniRangeRec af_orya_uniranges[] = + { + AF_UNIRANGE_REC( 0x0B00UL, 0x0B7FUL ), /* Oriya */ + AF_UNIRANGE_REC( 0UL, 0UL ) + }; + + const AF_Script_UniRangeRec af_sinh_uniranges[] = + { + AF_UNIRANGE_REC( 0x0D80UL, 0x0DFFUL ), /* Sinhala */ + AF_UNIRANGE_REC( 0UL, 0UL ) + }; + + const AF_Script_UniRangeRec af_sund_uniranges[] = + { + AF_UNIRANGE_REC( 0x1B80UL, 0x1BBFUL ), /* Sundanese */ + AF_UNIRANGE_REC( 0UL, 0UL ) + }; + + const AF_Script_UniRangeRec af_sylo_uniranges[] = + { + AF_UNIRANGE_REC( 0xA800UL, 0xA82FUL ), /* Syloti Nagri */ + AF_UNIRANGE_REC( 0UL, 0UL ) + }; + + const AF_Script_UniRangeRec af_taml_uniranges[] = + { + AF_UNIRANGE_REC( 0x0B80UL, 0x0BFFUL ), /* Tamil */ + AF_UNIRANGE_REC( 0UL, 0UL ) + }; + + const AF_Script_UniRangeRec af_telu_uniranges[] = + { + AF_UNIRANGE_REC( 0x0C00UL, 0x0C7FUL ), /* Telugu */ + AF_UNIRANGE_REC( 0UL, 0UL ) + }; + + const AF_Script_UniRangeRec af_tibt_uniranges[] = + { + AF_UNIRANGE_REC( 0x0F00UL, 0x0FFFUL ), /* Tibetan */ + AF_UNIRANGE_REC( 0UL, 0UL ) + }; + +#endif /* !AF_CONFIG_OPTION_INDIC */ + +#ifdef AF_CONFIG_OPTION_CJK + + /* this corresponds to Unicode 6.0 */ + + const AF_Script_UniRangeRec af_hani_uniranges[] = + { + AF_UNIRANGE_REC( 0x1100UL, 0x11FFUL ), /* Hangul Jamo */ + AF_UNIRANGE_REC( 0x2E80UL, 0x2EFFUL ), /* CJK Radicals Supplement */ + AF_UNIRANGE_REC( 0x2F00UL, 0x2FDFUL ), /* Kangxi Radicals */ + AF_UNIRANGE_REC( 0x2FF0UL, 0x2FFFUL ), /* Ideographic Description Characters */ + AF_UNIRANGE_REC( 0x3000UL, 0x303FUL ), /* CJK Symbols and Punctuation */ + AF_UNIRANGE_REC( 0x3040UL, 0x309FUL ), /* Hiragana */ + AF_UNIRANGE_REC( 0x30A0UL, 0x30FFUL ), /* Katakana */ + AF_UNIRANGE_REC( 0x3100UL, 0x312FUL ), /* Bopomofo */ + AF_UNIRANGE_REC( 0x3130UL, 0x318FUL ), /* Hangul Compatibility Jamo */ + AF_UNIRANGE_REC( 0x3190UL, 0x319FUL ), /* Kanbun */ + AF_UNIRANGE_REC( 0x31A0UL, 0x31BFUL ), /* Bopomofo Extended */ + AF_UNIRANGE_REC( 0x31C0UL, 0x31EFUL ), /* CJK Strokes */ + AF_UNIRANGE_REC( 0x31F0UL, 0x31FFUL ), /* Katakana Phonetic Extensions */ + AF_UNIRANGE_REC( 0x3200UL, 0x32FFUL ), /* Enclosed CJK Letters and Months */ + AF_UNIRANGE_REC( 0x3300UL, 0x33FFUL ), /* CJK Compatibility */ + AF_UNIRANGE_REC( 0x3400UL, 0x4DBFUL ), /* CJK Unified Ideographs Extension A */ + AF_UNIRANGE_REC( 0x4DC0UL, 0x4DFFUL ), /* Yijing Hexagram Symbols */ + AF_UNIRANGE_REC( 0x4E00UL, 0x9FFFUL ), /* CJK Unified Ideographs */ + AF_UNIRANGE_REC( 0xA960UL, 0xA97FUL ), /* Hangul Jamo Extended-A */ + AF_UNIRANGE_REC( 0xAC00UL, 0xD7AFUL ), /* Hangul Syllables */ + AF_UNIRANGE_REC( 0xD7B0UL, 0xD7FFUL ), /* Hangul Jamo Extended-B */ + AF_UNIRANGE_REC( 0xF900UL, 0xFAFFUL ), /* CJK Compatibility Ideographs */ + AF_UNIRANGE_REC( 0xFE10UL, 0xFE1FUL ), /* Vertical forms */ + AF_UNIRANGE_REC( 0xFE30UL, 0xFE4FUL ), /* CJK Compatibility Forms */ + AF_UNIRANGE_REC( 0xFF00UL, 0xFFEFUL ), /* Halfwidth and Fullwidth Forms */ + AF_UNIRANGE_REC( 0x1B000UL, 0x1B0FFUL ), /* Kana Supplement */ + AF_UNIRANGE_REC( 0x1D300UL, 0x1D35FUL ), /* Tai Xuan Hing Symbols */ + AF_UNIRANGE_REC( 0x1F200UL, 0x1F2FFUL ), /* Enclosed Ideographic Supplement */ + AF_UNIRANGE_REC( 0x20000UL, 0x2A6DFUL ), /* CJK Unified Ideographs Extension B */ + AF_UNIRANGE_REC( 0x2A700UL, 0x2B73FUL ), /* CJK Unified Ideographs Extension C */ + AF_UNIRANGE_REC( 0x2B740UL, 0x2B81FUL ), /* CJK Unified Ideographs Extension D */ + AF_UNIRANGE_REC( 0x2F800UL, 0x2FA1FUL ), /* CJK Compatibility Ideographs Supplement */ + AF_UNIRANGE_REC( 0UL, 0UL ) + }; + +#endif /* !AF_CONFIG_OPTION_CJK */ + +/* END */ diff --git a/src/autofit/afranges.h b/src/autofit/afranges.h new file mode 100644 index 0000000..fe5b2aa --- /dev/null +++ b/src/autofit/afranges.h @@ -0,0 +1,41 @@ +/***************************************************************************/ +/* */ +/* afranges.h */ +/* */ +/* Auto-fitter Unicode script ranges (specification). */ +/* */ +/* Copyright 2013, 2014 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, sc1, sc2, sc3 ) \ + extern const AF_Script_UniRangeRec af_ ## s ## _uniranges[]; + +#include "afscript.h" + + /* */ + +FT_END_HEADER + +#endif /* __AFRANGES_H__ */ + + +/* END */ diff --git a/src/autofit/afscript.h b/src/autofit/afscript.h index 32ec2ca..a418b05 100644 --- a/src/autofit/afscript.h +++ b/src/autofit/afscript.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter scripts (specification only). */ /* */ -/* Copyright 2013 by */ +/* Copyright 2013, 2014 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -20,18 +20,119 @@ /* Define `SCRIPT' as needed. */ - /* Add new scripts here. */ + /* 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). */ - SCRIPT( cyrl, CYRL, "Cyrillic" ) - SCRIPT( deva, DEVA, "Indic scripts" ) - SCRIPT( none, NONE, "no script" ) - SCRIPT( grek, GREK, "Greek" ) - SCRIPT( hani, HANI, "CJKV ideographs" ) - SCRIPT( hebr, HEBR, "Hebrew" ) - SCRIPT( latn, LATN, "Latin" ) -#ifdef FT_OPTION_AUTOFIT2 - SCRIPT( ltn2, LTN2, "Latin 2" ) -#endif + SCRIPT( cyrl, CYRL, + "Cyrillic", + HB_SCRIPT_CYRILLIC, + 0x43E, 0x41E, 0x0 ) /* оО */ + + SCRIPT( deva, DEVA, + "Devanagari", + HB_SCRIPT_DEVANAGARI, + 0x920, 0x935, 0x91F ) /* ठ व ट */ + + SCRIPT( grek, GREK, + "Greek", + HB_SCRIPT_GREEK, + 0x3BF, 0x39F, 0x0 ) /* οΟ */ + + SCRIPT( hebr, HEBR, + "Hebrew", + HB_SCRIPT_HEBREW, + 0x5DD, 0x0, 0x0 ) /* ם */ + + SCRIPT( latn, LATN, + "Latin", + HB_SCRIPT_LATIN, + 'o', 'O', '0' ) + + SCRIPT( none, NONE, + "no script", + HB_SCRIPT_INVALID, + 0x0, 0x0, 0x0 ) + +#ifdef AF_CONFIG_OPTION_INDIC + + SCRIPT( beng, BENG, + "Bengali", + HB_SCRIPT_BENGALI, + 'o', 0x0, 0x0 ) /* XXX */ + + SCRIPT( gujr, GUJR, + "Gujarati", + HB_SCRIPT_GUJARATI, + 'o', 0x0, 0x0 ) /* XXX */ + + SCRIPT( guru, GURU, + "Gurmukhi", + HB_SCRIPT_GURMUKHI, + 'o', 0x0, 0x0 ) /* XXX */ + + SCRIPT( knda, KNDA, + "Kannada", + HB_SCRIPT_KANNADA, + 'o', 0x0, 0x0 ) /* XXX */ + + SCRIPT( limb, LIMB, + "Limbu", + HB_SCRIPT_LIMBU, + 'o', 0x0, 0x0 ) /* XXX */ + + SCRIPT( mlym, MLYM, + "Malayalam", + HB_SCRIPT_MALAYALAM, + 'o', 0x0, 0x0 ) /* XXX */ + + SCRIPT( orya, ORYA, + "Oriya", + HB_SCRIPT_ORIYA, + 'o', 0x0, 0x0 ) /* XXX */ + + SCRIPT( sinh, SINH, + "Sinhala", + HB_SCRIPT_SINHALA, + 'o', 0x0, 0x0 ) /* XXX */ + + SCRIPT( sund, SUND, + "Sundanese", + HB_SCRIPT_SUNDANESE, + 'o', 0x0, 0x0 ) /* XXX */ + + SCRIPT( sylo, SYLO, + "Syloti Nagri", + HB_SCRIPT_SYLOTI_NAGRI, + 'o', 0x0, 0x0 ) /* XXX */ + + SCRIPT( taml, TAML, + "Tamil", + HB_SCRIPT_TAMIL, + 'o', 0x0, 0x0 ) /* XXX */ + + SCRIPT( telu, TELU, + "Telugu", + HB_SCRIPT_TELUGU, + 'o', 0x0, 0x0 ) /* XXX */ + + SCRIPT( tibt, TIBT, + "Tibetan", + HB_SCRIPT_TIBETAN, + 'o', 0x0, 0x0 ) /* XXX */ + +#endif /* AF_CONFIG_OPTION_INDIC */ + +#ifdef AF_CONFIG_OPTION_CJK + + SCRIPT( hani, HANI, + "CJKV ideographs", + HB_SCRIPT_HAN, + 0x7530, 0x56D7, 0x0 ) /* 田囗 */ + +#endif /* AF_CONFIG_OPTION_CJK */ /* END */ diff --git a/src/autofit/afstyles.h b/src/autofit/afstyles.h new file mode 100644 index 0000000..27fdd2e --- /dev/null +++ b/src/autofit/afstyles.h @@ -0,0 +1,158 @@ +/***************************************************************************/ +/* */ +/* afstyles.h */ +/* */ +/* Auto-fitter styles (specification only). */ +/* */ +/* Copyright 2013, 2014 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. */ + /* */ + /* 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 capticals from capitals", \ + PETITE_CAPITALS_FROM_CAPITALS ) \ + STYLE_LATIN( s, S, c2sc, C2SC, ds, \ + "small capticals 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 ) + + META_STYLE_LATIN( cyrl, CYRL, "Cyrillic" ) + + META_STYLE_LATIN( grek, GREK, "Greek" ) + + STYLE( hebr_dflt, HEBR_DFLT, + "Hebrew default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_HEBR, + AF_BLUE_STRINGSET_HEBR, + AF_COVERAGE_DEFAULT ) + META_STYLE_LATIN( latn, LATN, "Latin" ) + + STYLE( deva_dflt, DEVA_DFLT, + "Devanagari default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_DEVA, + AF_BLUE_STRINGSET_DEVA, + AF_COVERAGE_DEFAULT ) + +#ifdef FT_OPTION_AUTOFIT2 + STYLE( ltn2_dflt, LTN2_DFLT, + "Latin 2 default style", + AF_WRITING_SYSTEM_LATIN2, + AF_SCRIPT_LATN, + AF_BLUE_STRINGSET_LATN, + AF_COVERAGE_DEFAULT ) +#endif + + STYLE( none_dflt, NONE_DFLT, + "no style", + AF_WRITING_SYSTEM_DUMMY, + AF_SCRIPT_NONE, + (AF_Blue_Stringset)0, + 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( beng, BENG, "Bengali" ) + STYLE_DEFAULT_INDIC( gujr, GUJR, "Gujarati" ) + STYLE_DEFAULT_INDIC( guru, GURU, "Gurmukhi" ) + STYLE_DEFAULT_INDIC( knda, KNDA, "Kannada" ) + STYLE_DEFAULT_INDIC( limb, LIMB, "Limbu" ) + STYLE_DEFAULT_INDIC( mlym, MLYM, "Malayalam" ) + STYLE_DEFAULT_INDIC( orya, ORYA, "Oriya" ) + STYLE_DEFAULT_INDIC( sinh, SINH, "Sinhala" ) + STYLE_DEFAULT_INDIC( sund, SUND, "Sundanese" ) + STYLE_DEFAULT_INDIC( sylo, SYLO, "Syloti Nagri" ) + STYLE_DEFAULT_INDIC( taml, TAML, "Tamil" ) + STYLE_DEFAULT_INDIC( telu, TELU, "Telugu" ) + 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 */ diff --git a/src/autofit/aftypes.h b/src/autofit/aftypes.h index cda1f89..61badd1 100644 --- a/src/autofit/aftypes.h +++ b/src/autofit/aftypes.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter types (specification only). */ /* */ -/* Copyright 2003-2009, 2011-2013 by */ +/* Copyright 2003-2009, 2011-2014 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -20,7 +20,7 @@ * * The auto-fitter is a complete rewrite of the old auto-hinter. * Its main feature is the ability to differentiate between different - * writing systems in order to apply script-specific rules. + * writing systems and scripts in order to apply specific rules. * * The code has also been compartmentized into several entities that * should make algorithmic experimentation easier than with the old @@ -197,55 +197,31 @@ extern void* _af_debug_hints; (a)->y_delta == (b)->y_delta ) - /*************************************************************************/ - /*************************************************************************/ - /***** *****/ - /***** S C R I P T M E T R I C S *****/ - /***** *****/ - /*************************************************************************/ - /*************************************************************************/ - - /* This is the main structure which combines writing systems and script */ - /* data (for a given face object, see below). */ - - typedef struct AF_WritingSystemClassRec_ const* AF_WritingSystemClass; - typedef struct AF_ScriptClassRec_ const* AF_ScriptClass; - typedef struct AF_FaceGlobalsRec_* AF_FaceGlobals; - - typedef struct AF_ScriptMetricsRec_ - { - AF_ScriptClass script_class; - AF_ScalerRec scaler; - FT_Bool digits_have_same_width; - - AF_FaceGlobals globals; /* to access properties */ - - } AF_ScriptMetricsRec, *AF_ScriptMetrics; - + typedef struct AF_StyleMetricsRec_* AF_StyleMetrics; /* This function parses an FT_Face to compute global metrics for - * a specific script. + * a specific style. */ typedef FT_Error - (*AF_Script_InitMetricsFunc)( AF_ScriptMetrics metrics, - FT_Face face ); + (*AF_WritingSystem_InitMetricsFunc)( AF_StyleMetrics metrics, + FT_Face face ); typedef void - (*AF_Script_ScaleMetricsFunc)( AF_ScriptMetrics metrics, - AF_Scaler scaler ); + (*AF_WritingSystem_ScaleMetricsFunc)( AF_StyleMetrics metrics, + AF_Scaler scaler ); typedef void - (*AF_Script_DoneMetricsFunc)( AF_ScriptMetrics metrics ); + (*AF_WritingSystem_DoneMetricsFunc)( AF_StyleMetrics metrics ); typedef FT_Error - (*AF_Script_InitHintsFunc)( AF_GlyphHints hints, - AF_ScriptMetrics metrics ); + (*AF_WritingSystem_InitHintsFunc)( AF_GlyphHints hints, + AF_StyleMetrics metrics ); typedef void - (*AF_Script_ApplyHintsFunc)( AF_GlyphHints hints, - FT_Outline* outline, - AF_ScriptMetrics metrics ); + (*AF_WritingSystem_ApplyHintsFunc)( AF_GlyphHints hints, + FT_Outline* outline, + AF_StyleMetrics metrics ); /*************************************************************************/ @@ -257,14 +233,14 @@ extern void* _af_debug_hints; /*************************************************************************/ /* - * In FreeType, a writing system consists of multiple scripts which can - * be handled similarly *in a typographical way*; the relationship is not - * based on history. For example, both the Greek and the unrelated + * 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 which computes global metrics specific to + * - a specific global analyzer that computes global metrics specific to * the script (based on script-specific characters to identify ascender * height, x-height, etc.), * @@ -297,16 +273,18 @@ extern void* _af_debug_hints; { AF_WritingSystem writing_system; - FT_Offset script_metrics_size; - AF_Script_InitMetricsFunc script_metrics_init; - AF_Script_ScaleMetricsFunc script_metrics_scale; - AF_Script_DoneMetricsFunc script_metrics_done; + FT_Offset style_metrics_size; + AF_WritingSystem_InitMetricsFunc style_metrics_init; + AF_WritingSystem_ScaleMetricsFunc style_metrics_scale; + AF_WritingSystem_DoneMetricsFunc style_metrics_done; - AF_Script_InitHintsFunc script_hints_init; - AF_Script_ApplyHintsFunc script_hints_apply; + AF_WritingSystem_InitHintsFunc style_hints_init; + AF_WritingSystem_ApplyHintsFunc style_hints_apply; } AF_WritingSystemClassRec; + typedef const AF_WritingSystemClassRec* AF_WritingSystemClass; + /*************************************************************************/ /*************************************************************************/ @@ -317,15 +295,15 @@ extern void* _af_debug_hints; /*************************************************************************/ /* - * Each script is associated with a set of Unicode ranges which gets used - * to test whether the font face supports the script. It also references - * the writing system it belongs to. + * Each script is associated with a set of Unicode ranges that gets used + * to test whether the font face supports the script. * - * We use four-letter script tags from the OpenType specification. + * We use four-letter script tags from the OpenType specification, + * extended by `NONE', which indicates `no script'. */ #undef SCRIPT -#define SCRIPT( s, S, d ) \ +#define SCRIPT( s, S, d, h, sc1, sc2, sc3 ) \ AF_SCRIPT_ ## S, /* The list of known scripts. */ @@ -353,15 +331,147 @@ extern void* _af_debug_hints; typedef struct AF_ScriptClassRec_ { - AF_Script script; - AF_Blue_Stringset blue_stringset; - AF_WritingSystem writing_system; + AF_Script script; AF_Script_UniRange script_uni_ranges; /* last must be { 0, 0 } */ - FT_UInt32 standard_char; /* for default width and height */ + + FT_UInt32 standard_char1; /* for default width and height */ + FT_UInt32 standard_char2; /* ditto */ + FT_UInt32 standard_char3; /* ditto */ } 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; + /* Declare and define vtables for classes */ #ifndef FT_CONFIG_OPTION_PIC @@ -401,19 +511,41 @@ extern void* _af_debug_hints; #define AF_DEFINE_SCRIPT_CLASS( \ script_class, \ - script_, \ - blue_stringset_, \ - writing_system_, \ + script, \ ranges, \ - std_char ) \ + std_char1, \ + std_char2, \ + std_char3 ) \ FT_CALLBACK_TABLE_DEF \ const AF_ScriptClassRec script_class = \ { \ - script_, \ - blue_stringset_, \ - writing_system_, \ + script, \ ranges, \ - std_char \ + std_char1, \ + std_char2, \ + std_char3 \ + }; + + +#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 \ }; #else /* FT_CONFIG_OPTION_PIC */ @@ -434,16 +566,16 @@ extern void* _af_debug_hints; FT_LOCAL_DEF( void ) \ FT_Init_Class_ ## writing_system_class( AF_WritingSystemClassRec* ac ) \ { \ - ac->writing_system = system; \ + ac->writing_system = system; \ \ - ac->script_metrics_size = m_size; \ + ac->style_metrics_size = m_size; \ \ - ac->script_metrics_init = m_init; \ - ac->script_metrics_scale = m_scale; \ - ac->script_metrics_done = m_done; \ + ac->style_metrics_init = m_init; \ + ac->style_metrics_scale = m_scale; \ + ac->style_metrics_done = m_done; \ \ - ac->script_hints_init = h_init; \ - ac->script_hints_apply = h_apply; \ + ac->style_hints_init = h_init; \ + ac->style_hints_apply = h_apply; \ } @@ -454,18 +586,40 @@ extern void* _af_debug_hints; #define AF_DEFINE_SCRIPT_CLASS( \ script_class, \ script_, \ - blue_string_set_, \ - writing_system_, \ ranges, \ - std_char ) \ + std_char1, \ + std_char2, \ + std_char3 ) \ FT_LOCAL_DEF( void ) \ FT_Init_Class_ ## script_class( AF_ScriptClassRec* ac ) \ { \ ac->script = script_; \ - ac->blue_stringset = blue_stringset_; \ - ac->writing_system = writing_system_; \ ac->script_uni_ranges = ranges; \ - ac->standard_char = std_char; \ + ac->standard_char1 = std_char1; \ + ac->standard_char2 = std_char2; \ + ac->standard_char3 = std_char3; \ + } + + +#define AF_DECLARE_STYLE_CLASS( style_class ) \ + FT_LOCAL( void ) \ + FT_Init_Class_ ## style_class( AF_StyleClassRec* ac ); + +#define AF_DEFINE_STYLE_CLASS( \ + style_class, \ + style_, \ + writing_system_, \ + script_, \ + blue_stringset_, \ + coverage_ ) \ + FT_LOCAL_DEF( void ) \ + FT_Init_Class_ ## style_class( AF_StyleClassRec* ac ) \ + { \ + ac->style = style_; \ + ac->writing_system = writing_system_; \ + ac->script = script_; \ + ac->blue_stringset = blue_stringset_; \ + ac->coverage = coverage_; \ } #endif /* FT_CONFIG_OPTION_PIC */ diff --git a/src/autofit/afwrtsys.h b/src/autofit/afwrtsys.h index 602c558..8aa2ed9 100644 --- a/src/autofit/afwrtsys.h +++ b/src/autofit/afwrtsys.h @@ -37,7 +37,8 @@ /* Define `WRITING_SYSTEM' as needed. */ - /* Add new writing systems here. */ + /* 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 ) diff --git a/src/autofit/autofit.c b/src/autofit/autofit.c index b23374a..e2b9934 100644 --- a/src/autofit/autofit.c +++ b/src/autofit/autofit.c @@ -24,6 +24,8 @@ #include "afglobal.c" #include "afhints.c" +#include "afranges.c" + #include "afdummy.c" #include "aflatin.c" #ifdef FT_OPTION_AUTOFIT2 @@ -32,6 +34,8 @@ #include "afcjk.c" #include "afindic.c" +#include "hbshim.c" + #include "afloader.c" #include "afmodule.c" diff --git a/src/autofit/hbshim.c b/src/autofit/hbshim.c new file mode 100644 index 0000000..cc04815 --- /dev/null +++ b/src/autofit/hbshim.c @@ -0,0 +1,545 @@ +/***************************************************************************/ +/* */ +/* hbshim.c */ +/* */ +/* HarfBuzz interface for accessing OpenType features (body). */ +/* */ +/* Copyright 2013, 2014 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_FREETYPE_H +#include "afglobal.h" +#include "aftypes.h" +#include "hbshim.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 trace_afharfbuzz + + + /* + * 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, sc1, sc2, sc3 ) h, + + + static const hb_script_t scripts[] = + { +#include "afscript.h" + }; + + + FT_Error + af_get_coverage( AF_FaceGlobals globals, + AF_StyleClass style_class, + FT_Byte* gstyles ) + { + hb_face_t* face; + + hb_set_t* gsub_lookups; /* GSUB lookups for a given script */ + hb_set_t* gsub_glyphs; /* glyphs covered by GSUB lookups */ + hb_set_t* gpos_lookups; /* GPOS lookups for a given script */ + hb_set_t* gpos_glyphs; /* 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 ); + + gsub_lookups = hb_set_create(); + gsub_glyphs = hb_set_create(); + gpos_lookups = hb_set_create(); + gpos_glyphs = hb_set_create(); + + 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. */ + hb_ot_tags_from_script( script, + &script_tags[0], + &script_tags[1] ); + + /* `hb_ot_tags_from_script' usually returns HB_OT_TAG_DEFAULT_SCRIPT */ + /* as the second tag. We change that to HB_TAG_NONE except for the */ + /* default script. */ + if ( style_class->script == globals->module->default_script && + style_class->coverage == AF_COVERAGE_DEFAULT ) + { + 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 + { + if ( script_tags[1] == HB_OT_TAG_DEFAULT_SCRIPT ) + script_tags[1] = HB_TAG_NONE; + } + + 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 */ + + hb_ot_layout_collect_lookups( face, + HB_OT_TAG_GPOS, + script_tags, + NULL, + coverage_tags, + gpos_lookups ); + + FT_TRACE4(( "GSUB lookups (style `%s'):\n" + " ", + af_style_names[style_class->style] )); + +#ifdef FT_DEBUG_LEVEL_TRACE + count = 0; +#endif + + for ( idx = -1; 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\n" )); +#endif + + FT_TRACE4(( "GPOS lookups (style `%s'):\n" + " ", + af_style_names[style_class->style] )); + +#ifdef FT_DEBUG_LEVEL_TRACE + count = 0; +#endif + + for ( idx = -1; 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\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 + * (this 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 = -1; 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', this is, they have a zero vertical offset, but + * most of them are small caps glyphs shifted up to the superscript + * position (this 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 = -1; hb_set_next( gsub_glyphs, &idx ); ) + { +#ifdef FT_DEBUG_LEVEL_TRACE + if ( !( count % 10 ) ) + FT_TRACE4(( "\n" + " " )); + + 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_Byte)style_class->style; +#ifdef FT_DEBUG_LEVEL_TRACE + else + FT_TRACE4(( "*" )); +#endif + } + +#ifdef FT_DEBUG_LEVEL_TRACE + if ( !count ) + FT_TRACE4(( "\n" + " (none)" )); + FT_TRACE4(( "\n\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 */ + }; + + + FT_Error + af_get_char_index( AF_StyleMetrics metrics, + FT_ULong charcode, + FT_ULong *codepoint, + FT_Long *y_offset ) + { + AF_StyleClass style_class; + + const hb_feature_t* feature; + + FT_ULong in_idx, out_idx; + + + if ( !metrics ) + return FT_THROW( Invalid_Argument ); + + in_idx = FT_Get_Char_Index( metrics->globals->face, charcode ); + + style_class = metrics->style_class; + + feature = features[style_class->coverage]; + + if ( feature ) + { + FT_UInt upem = metrics->globals->face->units_per_EM; + + hb_font_t* font = metrics->globals->hb_font; + hb_buffer_t* buf = hb_buffer_create(); + + uint32_t c = (uint32_t)charcode; + + hb_glyph_info_t* ginfo; + hb_glyph_position_t* gpos; + unsigned int gcount; + + + /* we shape at a size of units per EM; this means font units */ + hb_font_set_scale( font, upem, upem ); + + /* XXX: is this sufficient for a single character of any script? */ + hb_buffer_set_direction( buf, HB_DIRECTION_LTR ); + hb_buffer_set_script( buf, scripts[style_class->script] ); + + /* we add one character to `buf' ... */ + hb_buffer_add_utf32( buf, &c, 1, 0, 1 ); + + /* ... and apply one feature */ + hb_shape( font, buf, feature, 1 ); + + ginfo = hb_buffer_get_glyph_infos( buf, &gcount ); + gpos = hb_buffer_get_glyph_positions( buf, &gcount ); + + out_idx = ginfo[0].codepoint; + + /* getting the same index indicates no substitution, */ + /* which means that the glyph isn't available in the feature */ + if ( in_idx == out_idx ) + { + *codepoint = 0; + *y_offset = 0; + } + else + { + *codepoint = out_idx; + *y_offset = gpos[0].y_offset; + } + + hb_buffer_destroy( buf ); + +#ifdef FT_DEBUG_LEVEL_TRACE + if ( gcount > 1 ) + FT_TRACE1(( "af_get_char_index:" + " input character mapped to multiple glyphs\n" )); +#endif + } + else + { + *codepoint = in_idx; + *y_offset = 0; + } + + return FT_Err_Ok; + } + + +#else /* !FT_CONFIG_OPTION_USE_HARFBUZZ */ + + + FT_Error + af_get_coverage( AF_FaceGlobals globals, + AF_StyleClass style_class, + FT_Byte* gstyles ) + { + FT_UNUSED( globals ); + FT_UNUSED( style_class ); + FT_UNUSED( gstyles ); + + return FT_Err_Ok; + } + + + FT_Error + af_get_char_index( AF_StyleMetrics metrics, + FT_ULong charcode, + FT_ULong *codepoint, + FT_Long *y_offset ) + { + FT_Face face; + + + if ( !metrics ) + return FT_THROW( Invalid_Argument ); + + face = metrics->globals->face; + + *codepoint = FT_Get_Char_Index( face, charcode ); + *y_offset = 0; + + return FT_Err_Ok; + } + + +#endif /* !FT_CONFIG_OPTION_USE_HARFBUZZ */ + + +/* END */ diff --git a/src/autofit/hbshim.h b/src/autofit/hbshim.h new file mode 100644 index 0000000..02f1513 --- /dev/null +++ b/src/autofit/hbshim.h @@ -0,0 +1,56 @@ +/***************************************************************************/ +/* */ +/* hbshim.h */ +/* */ +/* HarfBuzz interface for accessing OpenType features (specification). */ +/* */ +/* Copyright 2013 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 __HBSHIM_H__ +#define __HBSHIM_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + + +#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ + +#include <hb.h> +#include <hb-ot.h> +#include <hb-ft.h> + +#endif + + +FT_BEGIN_HEADER + + FT_Error + af_get_coverage( AF_FaceGlobals globals, + AF_StyleClass style_class, + FT_Byte* gstyles ); + + FT_Error + af_get_char_index( AF_StyleMetrics metrics, + FT_ULong charcode, + FT_ULong *codepoint, + FT_Long *y_offset ); + + /* */ + +FT_END_HEADER + +#endif /* __HBSHIM_H__ */ + + +/* END */ |