summaryrefslogtreecommitdiffstats
path: root/src/autofit
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@google.com>2014-08-08 17:55:11 -0400
committerBehdad Esfahbod <behdad@google.com>2014-08-08 17:59:36 -0400
commit9c745321260bb728ab1cd1c8fd5f075854b2ad49 (patch)
tree86c9ee0214cac2870a94905e4240732413ed768b /src/autofit
parentec0bab5697bb31ba980810145f62e3799946ec60 (diff)
downloadandroid_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')
-rw-r--r--src/autofit/afblue.c104
-rw-r--r--src/autofit/afblue.cin2
-rw-r--r--src/autofit/afblue.dat244
-rw-r--r--src/autofit/afblue.h101
-rw-r--r--src/autofit/afblue.hin16
-rw-r--r--src/autofit/afcjk.c251
-rw-r--r--src/autofit/afcjk.h17
-rw-r--r--src/autofit/afcover.h105
-rw-r--r--src/autofit/afdummy.c28
-rw-r--r--src/autofit/afdummy.h6
-rw-r--r--src/autofit/afglobal.c299
-rw-r--r--src/autofit/afglobal.h66
-rw-r--r--src/autofit/afhints.c269
-rw-r--r--src/autofit/afhints.h58
-rw-r--r--src/autofit/afindic.c55
-rw-r--r--src/autofit/afindic.h8
-rw-r--r--src/autofit/aflatin.c439
-rw-r--r--src/autofit/aflatin.h43
-rw-r--r--src/autofit/aflatin2.c67
-rw-r--r--src/autofit/aflatin2.h14
-rw-r--r--src/autofit/afloader.c47
-rw-r--r--src/autofit/afloader.h4
-rw-r--r--src/autofit/afmodule.c71
-rw-r--r--src/autofit/afmodule.h5
-rw-r--r--src/autofit/afpic.c28
-rw-r--r--src/autofit/afpic.h16
-rw-r--r--src/autofit/afranges.c210
-rw-r--r--src/autofit/afranges.h41
-rw-r--r--src/autofit/afscript.h125
-rw-r--r--src/autofit/afstyles.h158
-rw-r--r--src/autofit/aftypes.h310
-rw-r--r--src/autofit/afwrtsys.h3
-rw-r--r--src/autofit/autofit.c4
-rw-r--r--src/autofit/hbshim.c545
-rw-r--r--src/autofit/hbshim.h56
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 */