diff options
author | wolfbeast <mcwerewolf@gmail.com> | 2018-05-15 20:21:34 +0200 |
---|---|---|
committer | wolfbeast <mcwerewolf@gmail.com> | 2018-05-15 20:21:34 +0200 |
commit | 9c075dc4cdaeef79bc570ed2219bb757cb325c47 (patch) | |
tree | cda2be4b94e235a7c742b0598ee4b13478c1c7b8 /modules/freetype2/src | |
parent | 7bd7473702918934b4f5751a583c3f459bb06c7b (diff) | |
download | UXP-9c075dc4cdaeef79bc570ed2219bb757cb325c47.tar UXP-9c075dc4cdaeef79bc570ed2219bb757cb325c47.tar.gz UXP-9c075dc4cdaeef79bc570ed2219bb757cb325c47.tar.lz UXP-9c075dc4cdaeef79bc570ed2219bb757cb325c47.tar.xz UXP-9c075dc4cdaeef79bc570ed2219bb757cb325c47.zip |
Update in-tree freetype2 lib (unused) to 2.9.1
Diffstat (limited to 'modules/freetype2/src')
424 files changed, 17998 insertions, 9588 deletions
diff --git a/modules/freetype2/src/Jamfile b/modules/freetype2/src/Jamfile index ebc036983..562480c94 100644 --- a/modules/freetype2/src/Jamfile +++ b/modules/freetype2/src/Jamfile @@ -1,6 +1,6 @@ # FreeType 2 src Jamfile # -# Copyright 2001-2016 by +# Copyright 2001-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/autofit/Jamfile b/modules/freetype2/src/autofit/Jamfile index 638b22972..01b866ec6 100644 --- a/modules/freetype2/src/autofit/Jamfile +++ b/modules/freetype2/src/autofit/Jamfile @@ -1,6 +1,6 @@ # FreeType 2 src/autofit Jamfile # -# Copyright 2003-2016 by +# Copyright 2003-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/autofit/afangles.c b/modules/freetype2/src/autofit/afangles.c index b856e57a8..c65a3ae23 100644 --- a/modules/freetype2/src/autofit/afangles.c +++ b/modules/freetype2/src/autofit/afangles.c @@ -5,7 +5,7 @@ /* Routines used to compute vector angles with limited accuracy */ /* and very high speed. It also contains sorting routines (body). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/autofit/afblue.c b/modules/freetype2/src/autofit/afblue.c index 7719c02ca..e4078fd04 100644 --- a/modules/freetype2/src/autofit/afblue.c +++ b/modules/freetype2/src/autofit/afblue.c @@ -7,7 +7,7 @@ /* */ /* Auto-fitter data for blue strings (body). */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -26,6 +26,14 @@ af_blue_strings[] = { /* */ + '\xF0', '\x9E', '\xA4', '\x8C', ' ', '\xF0', '\x9E', '\xA4', '\x85', ' ', '\xF0', '\x9E', '\xA4', '\x88', ' ', '\xF0', '\x9E', '\xA4', '\x8F', ' ', '\xF0', '\x9E', '\xA4', '\x94', ' ', '\xF0', '\x9E', '\xA4', '\x9A', /* 𞤌 𞤅 𞤈 𞤏 𞤔 𞤚 */ + '\0', + '\xF0', '\x9E', '\xA4', '\x82', ' ', '\xF0', '\x9E', '\xA4', '\x96', /* 𞤂 𞤖 */ + '\0', + '\xF0', '\x9E', '\xA4', '\xAC', ' ', '\xF0', '\x9E', '\xA4', '\xAE', ' ', '\xF0', '\x9E', '\xA4', '\xBB', ' ', '\xF0', '\x9E', '\xA4', '\xBC', ' ', '\xF0', '\x9E', '\xA4', '\xBE', /* 𞤬 𞤮 𞤻 𞤼 𞤾 */ + '\0', + '\xF0', '\x9E', '\xA4', '\xA4', ' ', '\xF0', '\x9E', '\xA4', '\xA8', ' ', '\xF0', '\x9E', '\xA4', '\xA9', ' ', '\xF0', '\x9E', '\xA4', '\xAD', ' ', '\xF0', '\x9E', '\xA4', '\xB4', ' ', '\xF0', '\x9E', '\xA4', '\xB8', ' ', '\xF0', '\x9E', '\xA4', '\xBA', ' ', '\xF0', '\x9E', '\xA5', '\x80', /* 𞤤 𞤨 𞤩 𞤭 𞤴 𞤸 𞤺 𞥀 */ + '\0', '\xD8', '\xA7', ' ', '\xD8', '\xA5', ' ', '\xD9', '\x84', ' ', '\xD9', '\x83', ' ', '\xD8', '\xB7', ' ', '\xD8', '\xB8', /* ا إ ل ك ط ظ */ '\0', '\xD8', '\xAA', ' ', '\xD8', '\xAB', ' ', '\xD8', '\xB7', ' ', '\xD8', '\xB8', ' ', '\xD9', '\x83', /* ت ث ط ظ ك */ @@ -44,12 +52,50 @@ '\0', '\xD5', '\xA2', ' ', '\xD5', '\xA8', ' ', '\xD5', '\xAB', ' ', '\xD5', '\xAC', ' ', '\xD5', '\xB2', ' ', '\xD5', '\xBA', ' ', '\xD6', '\x83', ' ', '\xD6', '\x81', /* բ ը ի լ ղ պ փ ց */ '\0', + '\xF0', '\x90', '\xAC', '\x80', ' ', '\xF0', '\x90', '\xAC', '\x81', ' ', '\xF0', '\x90', '\xAC', '\x90', ' ', '\xF0', '\x90', '\xAC', '\x9B', /* 𐬀 𐬁 𐬐 𐬛 */ + '\0', + '\xF0', '\x90', '\xAC', '\x80', ' ', '\xF0', '\x90', '\xAC', '\x81', /* 𐬀 𐬁 */ + '\0', + '\xEA', '\x9A', '\xA7', ' ', '\xEA', '\x9A', '\xA8', ' ', '\xEA', '\x9B', '\x9B', ' ', '\xEA', '\x9B', '\x89', ' ', '\xEA', '\x9B', '\x81', ' ', '\xEA', '\x9B', '\x88', ' ', '\xEA', '\x9B', '\xAB', ' ', '\xEA', '\x9B', '\xAF', /* ꚧ ꚨ ꛛ ꛉ ꛁ ꛈ ꛫ ꛯ */ + '\0', + '\xEA', '\x9A', '\xAD', ' ', '\xEA', '\x9A', '\xB3', ' ', '\xEA', '\x9A', '\xB6', ' ', '\xEA', '\x9B', '\xAC', ' ', '\xEA', '\x9A', '\xA2', ' ', '\xEA', '\x9A', '\xBD', ' ', '\xEA', '\x9B', '\xAF', ' ', '\xEA', '\x9B', '\xB2', /* ꚭ ꚳ ꚶ ꛬ ꚢ ꚽ ꛯ ꛲ */ + '\0', '\xE0', '\xA6', '\x85', ' ', '\xE0', '\xA6', '\xA1', ' ', '\xE0', '\xA6', '\xA4', ' ', '\xE0', '\xA6', '\xA8', ' ', '\xE0', '\xA6', '\xAC', ' ', '\xE0', '\xA6', '\xAD', ' ', '\xE0', '\xA6', '\xB2', ' ', '\xE0', '\xA6', '\x95', /* অ ড ত ন ব ভ ল ক */ '\0', '\xE0', '\xA6', '\x87', ' ', '\xE0', '\xA6', '\x9F', ' ', '\xE0', '\xA6', '\xA0', ' ', '\xE0', '\xA6', '\xBF', ' ', '\xE0', '\xA7', '\x80', ' ', '\xE0', '\xA7', '\x88', ' ', '\xE0', '\xA7', '\x97', /* ই ট ঠ ি ী ৈ ৗ */ '\0', '\xE0', '\xA6', '\x93', ' ', '\xE0', '\xA6', '\x8F', ' ', '\xE0', '\xA6', '\xA1', ' ', '\xE0', '\xA6', '\xA4', ' ', '\xE0', '\xA6', '\xA8', ' ', '\xE0', '\xA6', '\xAC', ' ', '\xE0', '\xA6', '\xB2', ' ', '\xE0', '\xA6', '\x95', /* ও এ ড ত ন ব ল ক */ '\0', + '\xE1', '\x9D', '\x90', ' ', '\xE1', '\x9D', '\x88', /* ᝐ ᝈ */ + '\0', + '\xE1', '\x9D', '\x85', ' ', '\xE1', '\x9D', '\x8A', ' ', '\xE1', '\x9D', '\x8E', /* ᝅ ᝊ ᝎ */ + '\0', + '\xE1', '\x9D', '\x82', ' ', '\xE1', '\x9D', '\x83', ' ', '\xE1', '\x9D', '\x89', ' ', '\xE1', '\x9D', '\x8C', /* ᝂ ᝃ ᝉ ᝌ */ + '\0', + '\xE1', '\x9D', '\x80', ' ', '\xE1', '\x9D', '\x83', ' ', '\xE1', '\x9D', '\x86', ' ', '\xE1', '\x9D', '\x89', ' ', '\xE1', '\x9D', '\x8B', ' ', '\xE1', '\x9D', '\x8F', ' ', '\xE1', '\x9D', '\x91', /* ᝀ ᝃ ᝆ ᝉ ᝋ ᝏ ᝑ */ + '\0', + '\xE1', '\x97', '\x9C', ' ', '\xE1', '\x96', '\xB4', ' ', '\xE1', '\x90', '\x81', ' ', '\xE1', '\x92', '\xA3', ' ', '\xE1', '\x91', '\xAB', ' ', '\xE1', '\x91', '\x8E', ' ', '\xE1', '\x94', '\x91', ' ', '\xE1', '\x97', '\xB0', /* ᗜ ᖴ ᐁ ᒣ ᑫ ᑎ ᔑ ᗰ */ + '\0', + '\xE1', '\x97', '\xB6', ' ', '\xE1', '\x96', '\xB5', ' ', '\xE1', '\x92', '\xA7', ' ', '\xE1', '\x90', '\x83', ' ', '\xE1', '\x91', '\x8C', ' ', '\xE1', '\x92', '\x8D', ' ', '\xE1', '\x94', '\x91', ' ', '\xE1', '\x97', '\xA2', /* ᗶ ᖵ ᒧ ᐃ ᑌ ᒍ ᔑ ᗢ */ + '\0', + '\xE1', '\x93', '\x93', ' ', '\xE1', '\x93', '\x95', ' ', '\xE1', '\x93', '\x80', ' ', '\xE1', '\x93', '\x82', ' ', '\xE1', '\x93', '\x84', ' ', '\xE1', '\x95', '\x84', ' ', '\xE1', '\x95', '\x86', ' ', '\xE1', '\x98', '\xA3', /* ᓓ ᓕ ᓀ ᓂ ᓄ ᕄ ᕆ ᘣ */ + '\0', + '\xE1', '\x95', '\x83', ' ', '\xE1', '\x93', '\x82', ' ', '\xE1', '\x93', '\x80', ' ', '\xE1', '\x95', '\x82', ' ', '\xE1', '\x93', '\x97', ' ', '\xE1', '\x93', '\x9A', ' ', '\xE1', '\x95', '\x86', ' ', '\xE1', '\x98', '\xA3', /* ᕃ ᓂ ᓀ ᕂ ᓗ ᓚ ᕆ ᘣ */ + '\0', + '\xE1', '\x90', '\xAA', ' ', '\xE1', '\x99', '\x86', ' ', '\xE1', '\xA3', '\x98', ' ', '\xE1', '\x90', '\xA2', ' ', '\xE1', '\x92', '\xBE', ' ', '\xE1', '\xA3', '\x97', ' ', '\xE1', '\x94', '\x86', /* ᐪ ᙆ ᣘ ᐢ ᒾ ᣗ ᔆ */ + '\0', + '\xE1', '\x99', '\x86', ' ', '\xE1', '\x97', '\xAE', ' ', '\xE1', '\x92', '\xBB', ' ', '\xE1', '\x90', '\x9E', ' ', '\xE1', '\x94', '\x86', ' ', '\xE1', '\x92', '\xA1', ' ', '\xE1', '\x92', '\xA2', ' ', '\xE1', '\x93', '\x91', /* ᙆ ᗮ ᒻ ᐞ ᔆ ᒡ ᒢ ᓑ */ + '\0', + '\xF0', '\x90', '\x8A', '\xA7', ' ', '\xF0', '\x90', '\x8A', '\xAB', ' ', '\xF0', '\x90', '\x8A', '\xAC', ' ', '\xF0', '\x90', '\x8A', '\xAD', ' ', '\xF0', '\x90', '\x8A', '\xB1', ' ', '\xF0', '\x90', '\x8A', '\xBA', ' ', '\xF0', '\x90', '\x8A', '\xBC', ' ', '\xF0', '\x90', '\x8A', '\xBF', /* 𐊧 𐊫 𐊬 𐊭 𐊱 𐊺 𐊼 𐊿 */ + '\0', + '\xF0', '\x90', '\x8A', '\xA3', ' ', '\xF0', '\x90', '\x8A', '\xA7', ' ', '\xF0', '\x90', '\x8A', '\xB7', ' ', '\xF0', '\x90', '\x8B', '\x80', ' ', '\xF0', '\x90', '\x8A', '\xAB', ' ', '\xF0', '\x90', '\x8A', '\xB8', ' ', '\xF0', '\x90', '\x8B', '\x89', /* 𐊣 𐊧 𐊷 𐋀 𐊫 𐊸 𐋉 */ + '\0', + '\xF0', '\x91', '\x84', '\x83', ' ', '\xF0', '\x91', '\x84', '\x85', ' ', '\xF0', '\x91', '\x84', '\x89', ' ', '\xF0', '\x91', '\x84', '\x99', ' ', '\xF0', '\x91', '\x84', '\x97', /* 𑄃 𑄅 𑄉 𑄙 𑄗 */ + '\0', + '\xF0', '\x91', '\x84', '\x85', ' ', '\xF0', '\x91', '\x84', '\x9B', ' ', '\xF0', '\x91', '\x84', '\x9D', ' ', '\xF0', '\x91', '\x84', '\x97', ' ', '\xF0', '\x91', '\x84', '\x93', /* 𑄅 𑄛 𑄝 𑄗 𑄓 */ + '\0', + '\xF0', '\x91', '\x84', '\x96', '\xF0', '\x91', '\x84', '\xB3', '\xF0', '\x91', '\x84', '\xA2', ' ', '\xF0', '\x91', '\x84', '\x98', '\xF0', '\x91', '\x84', '\xB3', '\xF0', '\x91', '\x84', '\xA2', ' ', '\xF0', '\x91', '\x84', '\x99', '\xF0', '\x91', '\x84', '\xB3', '\xF0', '\x91', '\x84', '\xA2', ' ', '\xF0', '\x91', '\x84', '\xA4', '\xF0', '\x91', '\x84', '\xB3', '\xF0', '\x91', '\x84', '\xA2', ' ', '\xF0', '\x91', '\x84', '\xA5', '\xF0', '\x91', '\x84', '\xB3', '\xF0', '\x91', '\x84', '\xA2', /* 𑄖𑄳𑄢 𑄘𑄳𑄢 𑄙𑄳𑄢 𑄤𑄳𑄢 𑄥𑄳𑄢 */ + '\0', '\xE1', '\x8F', '\x86', ' ', '\xE1', '\x8E', '\xBB', ' ', '\xE1', '\x8E', '\xAC', ' ', '\xE1', '\x8F', '\x83', ' ', '\xE1', '\x8E', '\xA4', ' ', '\xE1', '\x8F', '\xA3', ' ', '\xE1', '\x8E', '\xA6', ' ', '\xE1', '\x8F', '\x95', /* Ꮖ Ꮋ Ꭼ Ꮓ Ꭴ Ꮳ Ꭶ Ꮥ */ '\0', '\xEA', '\xAE', '\x92', ' ', '\xEA', '\xAE', '\xA4', ' ', '\xEA', '\xAE', '\xB6', ' ', '\xEA', '\xAD', '\xB4', ' ', '\xEA', '\xAD', '\xBE', ' ', '\xEA', '\xAE', '\x97', ' ', '\xEA', '\xAE', '\x9D', ' ', '\xEA', '\xAE', '\xBF', /* ꮒ ꮤ ꮶ ꭴ ꭾ ꮗ ꮝ ꮿ */ @@ -58,6 +104,20 @@ '\0', '\xE1', '\x8F', '\xB8', ' ', '\xEA', '\xAE', '\x90', ' ', '\xEA', '\xAD', '\xB9', ' ', '\xEA', '\xAD', '\xBB', /* ᏸ ꮐ ꭹ ꭻ */ '\0', + '\xE2', '\xB2', '\x8C', ' ', '\xE2', '\xB2', '\x8E', ' ', '\xE2', '\xB2', '\xA0', ' ', '\xE2', '\xB3', '\x9E', ' ', '\xE2', '\xB2', '\x9E', ' ', '\xE2', '\xB2', '\x90', ' ', '\xE2', '\xB2', '\xA4', ' ', '\xE2', '\xB3', '\x8A', /* Ⲍ Ⲏ Ⲡ Ⳟ Ⲟ Ⲑ Ⲥ Ⳋ */ + '\0', + '\xE2', '\xB3', '\x90', ' ', '\xE2', '\xB3', '\x98', ' ', '\xE2', '\xB3', '\x9E', ' ', '\xE2', '\xB2', '\x8E', ' ', '\xE2', '\xB2', '\x9E', ' ', '\xE2', '\xB2', '\x90', ' ', '\xE2', '\xB3', '\x9C', ' ', '\xE2', '\xB2', '\xB0', /* Ⳑ Ⳙ Ⳟ Ⲏ Ⲟ Ⲑ Ⳝ Ⲱ */ + '\0', + '\xE2', '\xB2', '\x8D', ' ', '\xE2', '\xB2', '\x8F', ' ', '\xE2', '\xB2', '\xA1', ' ', '\xE2', '\xB3', '\x9F', ' ', '\xE2', '\xB2', '\x9F', ' ', '\xE2', '\xB2', '\x91', ' ', '\xE2', '\xB2', '\xA5', ' ', '\xE2', '\xB3', '\x8B', /* ⲍ ⲏ ⲡ ⳟ ⲟ ⲑ ⲥ ⳋ */ + '\0', + '\xE2', '\xB3', '\x91', ' ', '\xE2', '\xB3', '\x99', ' ', '\xE2', '\xB3', '\x9F', ' ', '\xE2', '\xB2', '\x8F', ' ', '\xE2', '\xB2', '\x9F', ' ', '\xE2', '\xB2', '\x91', ' ', '\xE2', '\xB3', '\x9D', ' ', '\xE2', '\xB3', '\x92', /* ⳑ ⳙ ⳟ ⲏ ⲟ ⲑ ⳝ Ⳓ */ + '\0', + '\xF0', '\x90', '\xA0', '\x8D', ' ', '\xF0', '\x90', '\xA0', '\x99', ' ', '\xF0', '\x90', '\xA0', '\xB3', ' ', '\xF0', '\x90', '\xA0', '\xB1', ' ', '\xF0', '\x90', '\xA0', '\x85', ' ', '\xF0', '\x90', '\xA0', '\x93', ' ', '\xF0', '\x90', '\xA0', '\xA3', ' ', '\xF0', '\x90', '\xA0', '\xA6', /* 𐠍 𐠙 𐠳 𐠱 𐠅 𐠓 𐠣 𐠦 */ + '\0', + '\xF0', '\x90', '\xA0', '\x83', ' ', '\xF0', '\x90', '\xA0', '\x8A', ' ', '\xF0', '\x90', '\xA0', '\x9B', ' ', '\xF0', '\x90', '\xA0', '\xA3', ' ', '\xF0', '\x90', '\xA0', '\xB3', ' ', '\xF0', '\x90', '\xA0', '\xB5', ' ', '\xF0', '\x90', '\xA0', '\x90', /* 𐠃 𐠊 𐠛 𐠣 𐠳 𐠵 𐠐 */ + '\0', + '\xF0', '\x90', '\xA0', '\x88', ' ', '\xF0', '\x90', '\xA0', '\x8F', ' ', '\xF0', '\x90', '\xA0', '\x96', /* 𐠈 𐠏 𐠖 */ + '\0', '\xD0', '\x91', ' ', '\xD0', '\x92', ' ', '\xD0', '\x95', ' ', '\xD0', '\x9F', ' ', '\xD0', '\x97', ' ', '\xD0', '\x9E', ' ', '\xD0', '\xA1', ' ', '\xD0', '\xAD', /* Б В Е П З О С Э */ '\0', '\xD0', '\x91', ' ', '\xD0', '\x92', ' ', '\xD0', '\x95', ' ', '\xD0', '\xA8', ' ', '\xD0', '\x97', ' ', '\xD0', '\x9E', ' ', '\xD0', '\xA1', ' ', '\xD0', '\xAD', /* Б В Е Ш З О С Э */ @@ -66,6 +126,14 @@ '\0', '\xD1', '\x80', ' ', '\xD1', '\x83', ' ', '\xD1', '\x84', /* р у ф */ '\0', + '\xF0', '\x90', '\x90', '\x82', ' ', '\xF0', '\x90', '\x90', '\x84', ' ', '\xF0', '\x90', '\x90', '\x8B', ' ', '\xF0', '\x90', '\x90', '\x97', ' ', '\xF0', '\x90', '\x90', '\x91', /* 𐐂 𐐄 𐐋 𐐗 𐐑 */ + '\0', + '\xF0', '\x90', '\x90', '\x80', ' ', '\xF0', '\x90', '\x90', '\x82', ' ', '\xF0', '\x90', '\x90', '\x84', ' ', '\xF0', '\x90', '\x90', '\x97', ' ', '\xF0', '\x90', '\x90', '\x9B', /* 𐐀 𐐂 𐐄 𐐗 𐐛 */ + '\0', + '\xF0', '\x90', '\x90', '\xAA', ' ', '\xF0', '\x90', '\x90', '\xAC', ' ', '\xF0', '\x90', '\x90', '\xB3', ' ', '\xF0', '\x90', '\x90', '\xBF', ' ', '\xF0', '\x90', '\x90', '\xB9', /* 𐐪 𐐬 𐐳 𐐿 𐐹 */ + '\0', + '\xF0', '\x90', '\x90', '\xA8', ' ', '\xF0', '\x90', '\x90', '\xAA', ' ', '\xF0', '\x90', '\x90', '\xAC', ' ', '\xF0', '\x90', '\x90', '\xBF', ' ', '\xF0', '\x90', '\x91', '\x83', /* 𐐨 𐐪 𐐬 𐐿 𐑃 */ + '\0', '\xE0', '\xA4', '\x95', ' ', '\xE0', '\xA4', '\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', /* ई ऐ ओ औ ि ी ो ौ */ @@ -98,6 +166,22 @@ '\0', '\xE2', '\xB4', '\x84', ' ', '\xE2', '\xB4', '\x85', ' ', '\xE2', '\xB4', '\x94', ' ', '\xE2', '\xB4', '\x95', ' ', '\xE2', '\xB4', '\x81', ' ', '\xE2', '\xB4', '\x82', ' ', '\xE2', '\xB4', '\x98', ' ', '\xE2', '\xB4', '\x9D', /* ⴄ ⴅ ⴔ ⴕ ⴁ ⴂ ⴘ ⴝ */ '\0', + '\xE1', '\xB2', '\x9C', ' ', '\xE1', '\xB2', '\x9F', ' ', '\xE1', '\xB2', '\xB3', ' ', '\xE1', '\xB2', '\xB8', ' ', '\xE1', '\xB2', '\x92', ' ', '\xE1', '\xB2', '\x94', ' ', '\xE1', '\xB2', '\x9D', ' ', '\xE1', '\xB2', '\xB4', /* Ნ Ჟ Ჳ Ჸ Გ Ე Ო Ჴ */ + '\0', + '\xE1', '\xB2', '\x98', ' ', '\xE1', '\xB2', '\xB2', ' ', '\xE1', '\xB2', '\x9D', ' ', '\xE1', '\xB2', '\xA9', ' ', '\xE1', '\xB2', '\x9B', ' ', '\xE1', '\xB2', '\xA8', ' ', '\xE1', '\xB2', '\xAF', ' ', '\xE1', '\xB2', '\xBD', /* Ი Ჲ Ო Ჩ Მ Შ Ჯ Ჽ */ + '\0', + '\xE2', '\xB0', '\x85', ' ', '\xE2', '\xB0', '\x94', ' ', '\xE2', '\xB0', '\xAA', ' ', '\xE2', '\xB0', '\x84', ' ', '\xE2', '\xB0', '\x82', ' ', '\xE2', '\xB0', '\x8A', ' ', '\xE2', '\xB0', '\xAB', ' ', '\xE2', '\xB0', '\x8B', /* Ⰵ Ⱄ Ⱚ Ⰴ Ⰲ Ⰺ Ⱛ Ⰻ */ + '\0', + '\xE2', '\xB0', '\x85', ' ', '\xE2', '\xB0', '\x84', ' ', '\xE2', '\xB0', '\x82', ' ', '\xE2', '\xB0', '\xAA', ' ', '\xE2', '\xB0', '\x9E', ' ', '\xE2', '\xB0', '\xA1', ' ', '\xE2', '\xB0', '\x8A', ' ', '\xE2', '\xB0', '\x94', /* Ⰵ Ⰴ Ⰲ Ⱚ Ⱎ Ⱑ Ⰺ Ⱄ */ + '\0', + '\xE2', '\xB0', '\xB5', ' ', '\xE2', '\xB1', '\x84', ' ', '\xE2', '\xB1', '\x9A', ' ', '\xE2', '\xB0', '\xB4', ' ', '\xE2', '\xB0', '\xB2', ' ', '\xE2', '\xB0', '\xBA', ' ', '\xE2', '\xB1', '\x9B', ' ', '\xE2', '\xB0', '\xBB', /* ⰵ ⱄ ⱚ ⰴ ⰲ ⰺ ⱛ ⰻ */ + '\0', + '\xE2', '\xB0', '\xB5', ' ', '\xE2', '\xB0', '\xB4', ' ', '\xE2', '\xB0', '\xB2', ' ', '\xE2', '\xB1', '\x9A', ' ', '\xE2', '\xB1', '\x8E', ' ', '\xE2', '\xB1', '\x91', ' ', '\xE2', '\xB0', '\xBA', ' ', '\xE2', '\xB1', '\x84', /* ⰵ ⰴ ⰲ ⱚ ⱎ ⱑ ⰺ ⱄ */ + '\0', + '\xF0', '\x90', '\x8C', '\xB2', ' ', '\xF0', '\x90', '\x8C', '\xB6', ' ', '\xF0', '\x90', '\x8D', '\x80', ' ', '\xF0', '\x90', '\x8D', '\x84', ' ', '\xF0', '\x90', '\x8C', '\xB4', ' ', '\xF0', '\x90', '\x8D', '\x83', ' ', '\xF0', '\x90', '\x8D', '\x88', ' ', '\xF0', '\x90', '\x8C', '\xBE', /* 𐌲 𐌶 𐍀 𐍄 𐌴 𐍃 𐍈 𐌾 */ + '\0', + '\xF0', '\x90', '\x8C', '\xB6', ' ', '\xF0', '\x90', '\x8C', '\xB4', ' ', '\xF0', '\x90', '\x8D', '\x83', ' ', '\xF0', '\x90', '\x8D', '\x88', /* 𐌶 𐌴 𐍃 𐍈 */ + '\0', '\xCE', '\x93', ' ', '\xCE', '\x92', ' ', '\xCE', '\x95', ' ', '\xCE', '\x96', ' ', '\xCE', '\x98', ' ', '\xCE', '\x9F', ' ', '\xCE', '\xA9', /* Γ Β Ε Ζ Θ Ο Ω */ '\0', '\xCE', '\x92', ' ', '\xCE', '\x94', ' ', '\xCE', '\x96', ' ', '\xCE', '\x9E', ' ', '\xCE', '\x98', ' ', '\xCE', '\x9F', /* Β Δ Ζ Ξ Θ Ο */ @@ -138,6 +222,16 @@ '\0', '\xE0', '\xB2', '\x85', ' ', '\xE0', '\xB2', '\x89', ' ', '\xE0', '\xB2', '\x8E', ' ', '\xE0', '\xB2', '\xB2', ' ', '\xE0', '\xB3', '\xA6', ' ', '\xE0', '\xB3', '\xA8', ' ', '\xE0', '\xB3', '\xAC', ' ', '\xE0', '\xB3', '\xAD', /* ಅ ಉ ಎ ಲ ೦ ೨ ೬ ೭ */ '\0', + '\xEA', '\xA4', '\x85', ' ', '\xEA', '\xA4', '\x8F', ' ', '\xEA', '\xA4', '\x81', ' ', '\xEA', '\xA4', '\x8B', ' ', '\xEA', '\xA4', '\x80', ' ', '\xEA', '\xA4', '\x8D', /* ꤅ ꤏ ꤁ ꤋ ꤀ ꤍ */ + '\0', + '\xEA', '\xA4', '\x88', ' ', '\xEA', '\xA4', '\x98', ' ', '\xEA', '\xA4', '\x80', ' ', '\xEA', '\xA4', '\x8D', ' ', '\xEA', '\xA4', '\xA2', /* ꤈ ꤘ ꤀ ꤍ ꤢ */ + '\0', + '\xEA', '\xA4', '\x96', ' ', '\xEA', '\xA4', '\xA1', /* ꤖ ꤡ */ + '\0', + '\xEA', '\xA4', '\x91', ' ', '\xEA', '\xA4', '\x9C', ' ', '\xEA', '\xA4', '\x9E', /* ꤑ ꤜ ꤞ */ + '\0', + '\xEA', '\xA4', '\x91', '\xEA', '\xA4', '\xAC', ' ', '\xEA', '\xA4', '\x9C', '\xEA', '\xA4', '\xAD', ' ', '\xEA', '\xA4', '\x94', '\xEA', '\xA4', '\xAC', /* ꤑ꤬ ꤜ꤭ ꤔ꤬ */ + '\0', '\xE1', '\x9E', '\x81', ' ', '\xE1', '\x9E', '\x91', ' ', '\xE1', '\x9E', '\x93', ' ', '\xE1', '\x9E', '\xA7', ' ', '\xE1', '\x9E', '\xA9', ' ', '\xE1', '\x9E', '\xB6', /* ខ ទ ន ឧ ឩ ា */ '\0', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x80', ' ', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x81', ' ', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x82', ' ', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x90', /* ក្ក ក្ខ ក្គ ក្ថ */ @@ -168,7 +262,9 @@ '\0', 'f', ' ', 'i', ' ', 'j', ' ', 'k', ' ', 'd', ' ', 'b', ' ', 'h', /* f i j k d b h */ '\0', - 'x', ' ', 'z', ' ', 'r', ' ', 'o', ' ', 'e', ' ', 's', ' ', 'c', /* x z r o e s c */ + 'u', ' ', 'v', ' ', 'x', ' ', 'z', ' ', 'o', ' ', 'e', ' ', 's', ' ', 'c', /* u v x z o e s c */ + '\0', + 'n', ' ', 'r', ' ', 'x', ' ', 'z', ' ', 'o', ' ', 'e', ' ', 's', ' ', 'c', /* n r x z o e s c */ '\0', 'p', ' ', 'q', ' ', 'g', ' ', 'j', ' ', 'y', /* p q g j y */ '\0', @@ -192,6 +288,10 @@ '\0', '\xE1', '\xB5', '\x96', ' ', '\xCA', '\xB8', ' ', '\xE1', '\xB5', '\x8D', /* ᵖ ʸ ᵍ */ '\0', + '\xEA', '\x93', '\xA1', ' ', '\xEA', '\x93', '\xA7', ' ', '\xEA', '\x93', '\xB1', ' ', '\xEA', '\x93', '\xB6', ' ', '\xEA', '\x93', '\xA9', ' ', '\xEA', '\x93', '\x9A', ' ', '\xEA', '\x93', '\xB5', ' ', '\xEA', '\x93', '\xB3', /* ꓡ ꓧ ꓱ ꓶ ꓩ ꓚ ꓵ ꓳ */ + '\0', + '\xEA', '\x93', '\x95', ' ', '\xEA', '\x93', '\x9C', ' ', '\xEA', '\x93', '\x9E', ' ', '\xEA', '\x93', '\xA1', ' ', '\xEA', '\x93', '\x9B', ' ', '\xEA', '\x93', '\xA2', ' ', '\xEA', '\x93', '\xB3', ' ', '\xEA', '\x93', '\xB4', /* ꓕ ꓜ ꓞ ꓡ ꓛ ꓢ ꓳ ꓴ */ + '\0', '\xE0', '\xB4', '\x92', ' ', '\xE0', '\xB4', '\x9F', ' ', '\xE0', '\xB4', '\xA0', ' ', '\xE0', '\xB4', '\xB1', ' ', '\xE0', '\xB4', '\x9A', ' ', '\xE0', '\xB4', '\xAA', ' ', '\xE0', '\xB4', '\x9A', '\xE0', '\xB5', '\x8D', '\xE0', '\xB4', '\x9A', ' ', '\xE0', '\xB4', '\xAA', '\xE0', '\xB5', '\x8D', '\xE0', '\xB4', '\xAA', /* ഒ ട ഠ റ ച പ ച്ച പ്പ */ '\0', '\xE0', '\xB4', '\x9F', ' ', '\xE0', '\xB4', '\xA0', ' ', '\xE0', '\xB4', '\xA7', ' ', '\xE0', '\xB4', '\xB6', ' ', '\xE0', '\xB4', '\x98', ' ', '\xE0', '\xB4', '\x9A', ' ', '\xE0', '\xB4', '\xA5', ' ', '\xE0', '\xB4', '\xB2', /* ട ഠ ധ ശ ഘ ച ഥ ല */ @@ -204,12 +304,68 @@ '\0', '\xE1', '\x80', '\x89', ' ', '\xE1', '\x80', '\x8A', ' ', '\xE1', '\x80', '\xA5', ' ', '\xE1', '\x80', '\xA9', ' ', '\xE1', '\x80', '\xA8', ' ', '\xE1', '\x81', '\x82', ' ', '\xE1', '\x81', '\x85', ' ', '\xE1', '\x81', '\x89', /* ဉ ည ဥ ဩ ဨ ၂ ၅ ၉ */ '\0', + '\xDF', '\x90', ' ', '\xDF', '\x89', ' ', '\xDF', '\x92', ' ', '\xDF', '\x9F', ' ', '\xDF', '\x96', ' ', '\xDF', '\x9C', ' ', '\xDF', '\xA0', ' ', '\xDF', '\xA5', /* ߐ ߉ ߒ ߟ ߖ ߜ ߠ ߥ */ + '\0', + '\xDF', '\x80', ' ', '\xDF', '\x98', ' ', '\xDF', '\xA1', ' ', '\xDF', '\xA0', ' ', '\xDF', '\xA5', /* ߀ ߘ ߡ ߠ ߥ */ + '\0', + '\xDF', '\x8F', ' ', '\xDF', '\x9B', ' ', '\xDF', '\x8B', /* ߏ ߛ ߋ */ + '\0', + '\xDF', '\x8E', ' ', '\xDF', '\x8F', ' ', '\xDF', '\x9B', ' ', '\xDF', '\x8B', /* ߎ ߏ ߛ ߋ */ + '\0', + '\xE1', '\xB1', '\x9B', ' ', '\xE1', '\xB1', '\x9C', ' ', '\xE1', '\xB1', '\x9D', ' ', '\xE1', '\xB1', '\xA1', ' ', '\xE1', '\xB1', '\xA2', ' ', '\xE1', '\xB1', '\xA5', /* ᱛ ᱜ ᱝ ᱡ ᱢ ᱥ */ + '\0', + '\xF0', '\x90', '\xB0', '\x97', ' ', '\xF0', '\x90', '\xB0', '\x98', ' ', '\xF0', '\x90', '\xB0', '\xA7', /* 𐰗 𐰘 𐰧 */ + '\0', + '\xF0', '\x90', '\xB0', '\x89', ' ', '\xF0', '\x90', '\xB0', '\x97', ' ', '\xF0', '\x90', '\xB0', '\xA6', ' ', '\xF0', '\x90', '\xB0', '\xA7', /* 𐰉 𐰗 𐰦 𐰧 */ + '\0', + '\xF0', '\x90', '\x92', '\xBE', ' ', '\xF0', '\x90', '\x93', '\x8D', ' ', '\xF0', '\x90', '\x93', '\x92', ' ', '\xF0', '\x90', '\x93', '\x93', ' ', '\xF0', '\x90', '\x92', '\xBB', ' ', '\xF0', '\x90', '\x93', '\x82', ' ', '\xF0', '\x90', '\x92', '\xB5', ' ', '\xF0', '\x90', '\x93', '\x86', /* 𐒾 𐓍 𐓒 𐓓 𐒻 𐓂 𐒵 𐓆 */ + '\0', + '\xF0', '\x90', '\x92', '\xB0', ' ', '\xF0', '\x90', '\x93', '\x8D', ' ', '\xF0', '\x90', '\x93', '\x82', ' ', '\xF0', '\x90', '\x92', '\xBF', ' ', '\xF0', '\x90', '\x93', '\x8E', ' ', '\xF0', '\x90', '\x92', '\xB9', /* 𐒰 𐓍 𐓂 𐒿 𐓎 𐒹 */ + '\0', + '\xF0', '\x90', '\x92', '\xBC', ' ', '\xF0', '\x90', '\x92', '\xBD', ' ', '\xF0', '\x90', '\x92', '\xBE', /* 𐒼 𐒽 𐒾 */ + '\0', + '\xF0', '\x90', '\x93', '\xB5', ' ', '\xF0', '\x90', '\x93', '\xB6', ' ', '\xF0', '\x90', '\x93', '\xBA', ' ', '\xF0', '\x90', '\x93', '\xBB', ' ', '\xF0', '\x90', '\x93', '\x9D', ' ', '\xF0', '\x90', '\x93', '\xA3', ' ', '\xF0', '\x90', '\x93', '\xAA', ' ', '\xF0', '\x90', '\x93', '\xAE', /* 𐓵 𐓶 𐓺 𐓻 𐓝 𐓣 𐓪 𐓮 */ + '\0', + '\xF0', '\x90', '\x93', '\x98', ' ', '\xF0', '\x90', '\x93', '\x9A', ' ', '\xF0', '\x90', '\x93', '\xA3', ' ', '\xF0', '\x90', '\x93', '\xB5', ' ', '\xF0', '\x90', '\x93', '\xA1', ' ', '\xF0', '\x90', '\x93', '\xA7', ' ', '\xF0', '\x90', '\x93', '\xAA', ' ', '\xF0', '\x90', '\x93', '\xB6', /* 𐓘 𐓚 𐓣 𐓵 𐓡 𐓧 𐓪 𐓶 */ + '\0', + '\xF0', '\x90', '\x93', '\xA4', ' ', '\xF0', '\x90', '\x93', '\xA6', ' ', '\xF0', '\x90', '\x93', '\xB8', ' ', '\xF0', '\x90', '\x93', '\xB9', ' ', '\xF0', '\x90', '\x93', '\x9B', /* 𐓤 𐓦 𐓸 𐓹 𐓛 */ + '\0', + '\xF0', '\x90', '\x93', '\xA4', ' ', '\xF0', '\x90', '\x93', '\xA5', ' ', '\xF0', '\x90', '\x93', '\xA6', /* 𐓤 𐓥 𐓦 */ + '\0', + '\xF0', '\x90', '\x92', '\x86', ' ', '\xF0', '\x90', '\x92', '\x89', ' ', '\xF0', '\x90', '\x92', '\x90', ' ', '\xF0', '\x90', '\x92', '\x92', ' ', '\xF0', '\x90', '\x92', '\x98', ' ', '\xF0', '\x90', '\x92', '\x9B', ' ', '\xF0', '\x90', '\x92', '\xA0', ' ', '\xF0', '\x90', '\x92', '\xA3', /* 𐒆 𐒉 𐒐 𐒒 𐒘 𐒛 𐒠 𐒣 */ + '\0', + '\xF0', '\x90', '\x92', '\x80', ' ', '\xF0', '\x90', '\x92', '\x82', ' ', '\xF0', '\x90', '\x92', '\x86', ' ', '\xF0', '\x90', '\x92', '\x88', ' ', '\xF0', '\x90', '\x92', '\x8A', ' ', '\xF0', '\x90', '\x92', '\x92', ' ', '\xF0', '\x90', '\x92', '\xA0', ' ', '\xF0', '\x90', '\x92', '\xA9', /* 𐒀 𐒂 𐒆 𐒈 𐒊 𐒒 𐒠 𐒩 */ + '\0', + '\xEA', '\xA2', '\x9C', ' ', '\xEA', '\xA2', '\x9E', ' ', '\xEA', '\xA2', '\xB3', ' ', '\xEA', '\xA2', '\x82', ' ', '\xEA', '\xA2', '\x96', ' ', '\xEA', '\xA2', '\x92', ' ', '\xEA', '\xA2', '\x9D', ' ', '\xEA', '\xA2', '\x9B', /* ꢜ ꢞ ꢳ ꢂ ꢖ ꢒ ꢝ ꢛ */ + '\0', + '\xEA', '\xA2', '\x82', ' ', '\xEA', '\xA2', '\xA8', ' ', '\xEA', '\xA2', '\xBA', ' ', '\xEA', '\xA2', '\xA4', ' ', '\xEA', '\xA2', '\x8E', /* ꢂ ꢨ ꢺ ꢤ ꢎ */ + '\0', + '\xF0', '\x90', '\x91', '\x95', ' ', '\xF0', '\x90', '\x91', '\x99', /* 𐑕 𐑙 */ + '\0', + '\xF0', '\x90', '\x91', '\x94', ' ', '\xF0', '\x90', '\x91', '\x96', ' ', '\xF0', '\x90', '\x91', '\x97', ' ', '\xF0', '\x90', '\x91', '\xB9', ' ', '\xF0', '\x90', '\x91', '\xBB', /* 𐑔 𐑖 𐑗 𐑹 𐑻 */ + '\0', + '\xF0', '\x90', '\x91', '\x9F', ' ', '\xF0', '\x90', '\x91', '\xA3', /* 𐑟 𐑣 */ + '\0', + '\xF0', '\x90', '\x91', '\xB1', ' ', '\xF0', '\x90', '\x91', '\xB2', ' ', '\xF0', '\x90', '\x91', '\xB3', ' ', '\xF0', '\x90', '\x91', '\xB4', ' ', '\xF0', '\x90', '\x91', '\xB8', ' ', '\xF0', '\x90', '\x91', '\xBA', ' ', '\xF0', '\x90', '\x91', '\xBC', /* 𐑱 𐑲 𐑳 𐑴 𐑸 𐑺 𐑼 */ + '\0', + '\xF0', '\x90', '\x91', '\xB4', ' ', '\xF0', '\x90', '\x91', '\xBB', ' ', '\xF0', '\x90', '\x91', '\xB9', /* 𐑴 𐑻 𐑹 */ + '\0', '\xE0', '\xB6', '\x89', ' ', '\xE0', '\xB6', '\x9A', ' ', '\xE0', '\xB6', '\x9D', ' ', '\xE0', '\xB6', '\xB3', ' ', '\xE0', '\xB6', '\xB4', ' ', '\xE0', '\xB6', '\xBA', ' ', '\xE0', '\xB6', '\xBD', ' ', '\xE0', '\xB7', '\x86', /* ඉ ක ඝ ඳ ප ය ල ෆ */ '\0', '\xE0', '\xB6', '\x91', ' ', '\xE0', '\xB6', '\x94', ' ', '\xE0', '\xB6', '\x9D', ' ', '\xE0', '\xB6', '\xA2', ' ', '\xE0', '\xB6', '\xA7', ' ', '\xE0', '\xB6', '\xAE', ' ', '\xE0', '\xB6', '\xB0', ' ', '\xE0', '\xB6', '\xBB', /* එ ඔ ඝ ජ ට ථ ධ ර */ '\0', '\xE0', '\xB6', '\xAF', ' ', '\xE0', '\xB6', '\xB3', ' ', '\xE0', '\xB6', '\x8B', ' ', '\xE0', '\xB6', '\xBD', ' ', '\xE0', '\xB6', '\xAD', '\xE0', '\xB7', '\x96', ' ', '\xE0', '\xB6', '\xAD', '\xE0', '\xB7', '\x94', ' ', '\xE0', '\xB6', '\xB6', '\xE0', '\xB7', '\x94', ' ', '\xE0', '\xB6', '\xAF', '\xE0', '\xB7', '\x94', /* ද ඳ උ ල තූ තු බු දු */ '\0', + '\xE1', '\xAE', '\x8B', ' ', '\xE1', '\xAE', '\x9E', ' ', '\xE1', '\xAE', '\xAE', ' ', '\xE1', '\xAE', '\xBD', ' ', '\xE1', '\xAE', '\xB0', ' ', '\xE1', '\xAE', '\x88', /* ᮋ ᮞ ᮮ ᮽ ᮰ ᮈ */ + '\0', + '\xE1', '\xAE', '\x84', ' ', '\xE1', '\xAE', '\x94', ' ', '\xE1', '\xAE', '\x95', ' ', '\xE1', '\xAE', '\x97', ' ', '\xE1', '\xAE', '\xB0', ' ', '\xE1', '\xAE', '\x86', ' ', '\xE1', '\xAE', '\x88', ' ', '\xE1', '\xAE', '\x89', /* ᮄ ᮔ ᮕ ᮗ ᮰ ᮆ ᮈ ᮉ */ + '\0', + '\xE1', '\xAE', '\xBC', ' ', '\xE1', '\xB3', '\x84', /* ᮼ ᳄ */ + '\0', + '\xEA', '\xAA', '\x86', ' ', '\xEA', '\xAA', '\x94', ' ', '\xEA', '\xAA', '\x92', ' ', '\xEA', '\xAA', '\x96', ' ', '\xEA', '\xAA', '\xAB', /* ꪆ ꪔ ꪒ ꪖ ꪫ */ + '\0', + '\xEA', '\xAA', '\x89', ' ', '\xEA', '\xAA', '\xAB', ' ', '\xEA', '\xAA', '\xAE', /* ꪉ ꪫ ꪮ */ + '\0', '\xE0', '\xAE', '\x89', ' ', '\xE0', '\xAE', '\x92', ' ', '\xE0', '\xAE', '\x93', ' ', '\xE0', '\xAE', '\xB1', ' ', '\xE0', '\xAE', '\x88', ' ', '\xE0', '\xAE', '\x95', ' ', '\xE0', '\xAE', '\x99', ' ', '\xE0', '\xAE', '\x9A', /* உ ஒ ஓ ற ஈ க ங ச */ '\0', '\xE0', '\xAE', '\x95', ' ', '\xE0', '\xAE', '\x9A', ' ', '\xE0', '\xAE', '\xB2', ' ', '\xE0', '\xAE', '\xB6', ' ', '\xE0', '\xAE', '\x89', ' ', '\xE0', '\xAE', '\x99', ' ', '\xE0', '\xAE', '\x9F', ' ', '\xE0', '\xAE', '\xAA', /* க ச ல ஶ உ ங ட ப */ @@ -231,6 +387,12 @@ '\xE0', '\xB8', '\x8D', ' ', '\xE0', '\xB8', '\x90', /* ญ ฐ */ '\0', '\xE0', '\xB9', '\x90', ' ', '\xE0', '\xB9', '\x91', ' ', '\xE0', '\xB9', '\x93', /* ๐ ๑ ๓ */ + '\0', + '\xE2', '\xB5', '\x94', ' ', '\xE2', '\xB5', '\x99', ' ', '\xE2', '\xB5', '\x9B', ' ', '\xE2', '\xB5', '\x9E', ' ', '\xE2', '\xB4', '\xB5', ' ', '\xE2', '\xB4', '\xBC', ' ', '\xE2', '\xB4', '\xB9', ' ', '\xE2', '\xB5', '\x8E', /* ⵔ ⵙ ⵛ ⵞ ⴵ ⴼ ⴹ ⵎ */ + '\0', + '\xEA', '\x97', '\x8D', ' ', '\xEA', '\x98', '\x96', ' ', '\xEA', '\x98', '\x99', ' ', '\xEA', '\x98', '\x9C', ' ', '\xEA', '\x96', '\x9C', ' ', '\xEA', '\x96', '\x9D', ' ', '\xEA', '\x94', '\x85', ' ', '\xEA', '\x95', '\xA2', /* ꗍ ꘖ ꘙ ꘜ ꖜ ꖝ ꔅ ꕢ */ + '\0', + '\xEA', '\x97', '\x8D', ' ', '\xEA', '\x98', '\x96', ' ', '\xEA', '\x98', '\x99', ' ', '\xEA', '\x97', '\x9E', ' ', '\xEA', '\x94', '\x85', ' ', '\xEA', '\x95', '\xA2', ' ', '\xEA', '\x96', '\x9C', ' ', '\xEA', '\x94', '\x86', /* ꗍ ꘖ ꘙ ꗞ ꔅ ꕢ ꖜ ꔆ */ #ifdef AF_CONFIG_OPTION_CJK '\0', '\xE4', '\xBB', '\x96', ' ', '\xE4', '\xBB', '\xAC', ' ', '\xE4', '\xBD', '\xA0', ' ', '\xE4', '\xBE', '\x86', ' ', '\xE5', '\x80', '\x91', ' ', '\xE5', '\x88', '\xB0', ' ', '\xE5', '\x92', '\x8C', ' ', '\xE5', '\x9C', '\xB0', /* 他 们 你 來 們 到 和 地 */ @@ -281,6 +443,12 @@ af_blue_stringsets[] = { /* */ + { AF_BLUE_STRING_ADLAM_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_ADLAM_CAPITAL_BOTTOM, 0 }, + { AF_BLUE_STRING_ADLAM_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_ADLAM_SMALL_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_ARABIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_ARABIC_BOTTOM, 0 }, { AF_BLUE_STRING_ARABIC_JOIN, AF_BLUE_PROPERTY_LATIN_NEUTRAL }, @@ -293,6 +461,12 @@ { AF_BLUE_STRING_ARMENIAN_SMALL_BOTTOM, 0 }, { AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER, 0 }, { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_AVESTAN_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_AVESTAN_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_BAMUM_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_BAMUM_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_BENGALI_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_BENGALI_HEAD, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_BENGALI_BASE, AF_BLUE_PROPERTY_LATIN_TOP | @@ -300,6 +474,27 @@ AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, { AF_BLUE_STRING_BENGALI_BASE, 0 }, { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_BUHID_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_BUHID_LARGE, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_BUHID_SMALL, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_BUHID_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_CHAKMA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_CHAKMA_BOTTOM, 0 }, + { AF_BLUE_STRING_CHAKMA_DESCENDER, 0 }, + { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_CANADIAN_SYLLABICS_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_CANADIAN_SYLLABICS_BOTTOM, 0 }, + { AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_BOTTOM, 0 }, + { AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_CARIAN_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_CARIAN_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_CHEROKEE_CAPITAL, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_CHEROKEE_CAPITAL, 0 }, { AF_BLUE_STRING_CHEROKEE_SMALL_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }, @@ -308,6 +503,17 @@ { AF_BLUE_STRING_CHEROKEE_SMALL, 0 }, { AF_BLUE_STRING_CHEROKEE_SMALL_DESCENDER, 0 }, { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_COPTIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_COPTIC_CAPITAL_BOTTOM, 0 }, + { AF_BLUE_STRING_COPTIC_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_COPTIC_SMALL_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_CYPRIOT_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_CYPRIOT_BOTTOM, 0 }, + { AF_BLUE_STRING_CYPRIOT_SMALL, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_CYPRIOT_SMALL, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM, 0 }, { AF_BLUE_STRING_CYRILLIC_SMALL, AF_BLUE_PROPERTY_LATIN_TOP | @@ -323,6 +529,12 @@ { AF_BLUE_STRING_DEVANAGARI_BASE, 0 }, { AF_BLUE_STRING_DEVANAGARI_BOTTOM, 0 }, { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_DESERET_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_DESERET_CAPITAL_BOTTOM, 0 }, + { AF_BLUE_STRING_DESERET_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_DESERET_SMALL_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_ETHIOPIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_ETHIOPIC_BOTTOM, 0 }, { AF_BLUE_STRING_MAX, 0 }, @@ -331,6 +543,8 @@ { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_BOTTOM, 0 }, { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_DESCENDER, 0 }, + { AF_BLUE_STRING_GEORGIAN_MTAVRULI_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_GEORGIAN_MTAVRULI_BOTTOM, 0 }, { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_BOTTOM, 0 }, @@ -340,6 +554,15 @@ { AF_BLUE_STRING_GEORGIAN_NUSKHURI_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_GEORGIAN_NUSKHURI_DESCENDER, 0 }, { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_GLAGOLITIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_GLAGOLITIC_CAPITAL_BOTTOM, 0 }, + { AF_BLUE_STRING_GLAGOLITIC_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_GLAGOLITIC_SMALL_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_GOTHIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_GOTHIC_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_GREEK_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM, 0 }, { AF_BLUE_STRING_GREEK_SMALL_BETA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, @@ -368,9 +591,13 @@ { AF_BLUE_STRING_HEBREW_BOTTOM, 0 }, { AF_BLUE_STRING_HEBREW_DESCENDER, 0 }, { AF_BLUE_STRING_MAX, 0 }, - { AF_BLUE_STRING_KANNADA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, - { AF_BLUE_STRING_KANNADA_BOTTOM, 0 }, - { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_KAYAH_LI_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_KAYAH_LI_BOTTOM, 0 }, + { AF_BLUE_STRING_KAYAH_LI_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_KAYAH_LI_DESCENDER, 0 }, + { AF_BLUE_STRING_KAYAH_LI_LARGE_DESCENDER, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_KHMER_TOP, AF_BLUE_PROPERTY_LATIN_TOP | AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, { AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP, AF_BLUE_PROPERTY_LATIN_SUB_TOP }, @@ -382,6 +609,9 @@ AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, { AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM, 0 }, { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_KANNADA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_KANNADA_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_LAO_TOP, AF_BLUE_PROPERTY_LATIN_TOP | AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, { AF_BLUE_STRING_LAO_BOTTOM, 0 }, @@ -392,9 +622,9 @@ { 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_STRING_LATIN_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, - { AF_BLUE_STRING_LATIN_SMALL, 0 }, + { AF_BLUE_STRING_LATIN_SMALL_BOTTOM, 0 }, { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0 }, { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, @@ -413,6 +643,9 @@ { AF_BLUE_STRING_LATIN_SUPS_SMALL, 0 }, { AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER, 0 }, { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_LISU_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_LISU_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_MALAYALAM_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_MALAYALAM_BOTTOM, 0 }, { AF_BLUE_STRING_MAX, 0 }, @@ -422,17 +655,61 @@ { AF_BLUE_STRING_MYANMAR_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_MYANMAR_DESCENDER, 0 }, { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_NKO_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_NKO_BOTTOM, 0 }, + { AF_BLUE_STRING_NKO_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_NKO_SMALL_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_OL_CHIKI, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_OL_CHIKI, 0 }, + { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_OLD_TURKIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_OLD_TURKIC_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_OSAGE_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_OSAGE_CAPITAL_BOTTOM, 0 }, + { AF_BLUE_STRING_OSAGE_CAPITAL_DESCENDER, 0 }, + { AF_BLUE_STRING_OSAGE_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_OSAGE_SMALL_BOTTOM, 0 }, + { AF_BLUE_STRING_OSAGE_SMALL_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_OSAGE_SMALL_DESCENDER, 0 }, + { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_OSMANYA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_OSMANYA_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_SAURASHTRA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_SAURASHTRA_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_SHAVIAN_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_SHAVIAN_BOTTOM, 0 }, + { AF_BLUE_STRING_SHAVIAN_DESCENDER, 0 }, + { AF_BLUE_STRING_SHAVIAN_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_SHAVIAN_SMALL_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_SINHALA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_SINHALA_BOTTOM, 0 }, { AF_BLUE_STRING_SINHALA_DESCENDER, 0 }, { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_SUNDANESE_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_SUNDANESE_BOTTOM, 0 }, + { AF_BLUE_STRING_SUNDANESE_DESCENDER, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_TAMIL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_TAMIL_BOTTOM, 0 }, { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_TAI_VIET_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_TAI_VIET_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_TELUGU_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_TELUGU_BOTTOM, 0 }, { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_TIFINAGH, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_TIFINAGH, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_THAI_TOP, AF_BLUE_PROPERTY_LATIN_TOP | AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, { AF_BLUE_STRING_THAI_BOTTOM, 0 }, @@ -442,6 +719,9 @@ { AF_BLUE_STRING_THAI_LARGE_DESCENDER, 0 }, { AF_BLUE_STRING_THAI_DIGIT_TOP, 0 }, { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_VAI_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_VAI_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, #ifdef AF_CONFIG_OPTION_CJK { AF_BLUE_STRING_CJK_TOP, AF_BLUE_PROPERTY_CJK_TOP }, { AF_BLUE_STRING_CJK_BOTTOM, 0 }, diff --git a/modules/freetype2/src/autofit/afblue.cin b/modules/freetype2/src/autofit/afblue.cin index 0c3cae818..4913e2eb6 100644 --- a/modules/freetype2/src/autofit/afblue.cin +++ b/modules/freetype2/src/autofit/afblue.cin @@ -4,7 +4,7 @@ /* */ /* Auto-fitter data for blue strings (body). */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/autofit/afblue.dat b/modules/freetype2/src/autofit/afblue.dat index f5f04f289..bc2f0d275 100644 --- a/modules/freetype2/src/autofit/afblue.dat +++ b/modules/freetype2/src/autofit/afblue.dat @@ -2,7 +2,7 @@ // // Auto-fitter data for blue strings. // -// Copyright 2013-2016 by +// Copyright 2013-2018 by // David Turner, Robert Wilhelm, and Werner Lemberg. // // This file is part of the FreeType project, and may only be used, @@ -74,6 +74,15 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: + AF_BLUE_STRING_ADLAM_CAPITAL_TOP + "𞤌 𞤅 𞤈 𞤏 𞤔 𞤚" + AF_BLUE_STRING_ADLAM_CAPITAL_BOTTOM + "𞤂 𞤖" + AF_BLUE_STRING_ADLAM_SMALL_TOP + "𞤬 𞤮 𞤻 𞤼 𞤾" + AF_BLUE_STRING_ADLAM_SMALL_BOTTOM + "𞤤 𞤨 𞤩 𞤭 𞤴 𞤸 𞤺 𞥀" + AF_BLUE_STRING_ARABIC_TOP "ا إ ل ك ط ظ" AF_BLUE_STRING_ARABIC_BOTTOM @@ -99,6 +108,16 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER "բ ը ի լ ղ պ փ ց" + AF_BLUE_STRING_AVESTAN_TOP + "𐬀 𐬁 𐬐 𐬛" + AF_BLUE_STRING_AVESTAN_BOTTOM + "𐬀 𐬁" + + AF_BLUE_STRING_BAMUM_TOP + "ꚧ ꚨ ꛛ ꛉ ꛁ ꛈ ꛫ ꛯ" + AF_BLUE_STRING_BAMUM_BOTTOM + "ꚭ ꚳ ꚶ ꛬ ꚢ ꚽ ꛯ ꛲" + AF_BLUE_STRING_BENGALI_BASE "অ ড ত ন ব ভ ল ক" AF_BLUE_STRING_BENGALI_TOP @@ -106,6 +125,40 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: AF_BLUE_STRING_BENGALI_HEAD "ও এ ড ত ন ব ল ক" + AF_BLUE_STRING_BUHID_TOP + "ᝐ ᝈ" + AF_BLUE_STRING_BUHID_LARGE + "ᝅ ᝊ ᝎ" + AF_BLUE_STRING_BUHID_SMALL + "ᝂ ᝃ ᝉ ᝌ" + AF_BLUE_STRING_BUHID_BOTTOM + "ᝀ ᝃ ᝆ ᝉ ᝋ ᝏ ᝑ" + + AF_BLUE_STRING_CANADIAN_SYLLABICS_TOP + "ᗜ ᖴ ᐁ ᒣ ᑫ ᑎ ᔑ ᗰ" + AF_BLUE_STRING_CANADIAN_SYLLABICS_BOTTOM + "ᗶ ᖵ ᒧ ᐃ ᑌ ᒍ ᔑ ᗢ" + AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_TOP + "ᓓ ᓕ ᓀ ᓂ ᓄ ᕄ ᕆ ᘣ" + AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_BOTTOM + "ᕃ ᓂ ᓀ ᕂ ᓗ ᓚ ᕆ ᘣ" + AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_TOP + "ᐪ ᙆ ᣘ ᐢ ᒾ ᣗ ᔆ" + AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_BOTTOM + "ᙆ ᗮ ᒻ ᐞ ᔆ ᒡ ᒢ ᓑ" + + AF_BLUE_STRING_CARIAN_TOP + "𐊧 𐊫 𐊬 𐊭 𐊱 𐊺 𐊼 𐊿" + AF_BLUE_STRING_CARIAN_BOTTOM + "𐊣 𐊧 𐊷 𐋀 𐊫 𐊸 𐋉" + + AF_BLUE_STRING_CHAKMA_TOP + "𑄃 𑄅 𑄉 𑄙 𑄗" + AF_BLUE_STRING_CHAKMA_BOTTOM + "𑄅 𑄛 𑄝 𑄗 𑄓" + AF_BLUE_STRING_CHAKMA_DESCENDER + "𑄖𑄳𑄢 𑄘𑄳𑄢 𑄙𑄳𑄢 𑄤𑄳𑄢 𑄥𑄳𑄢" + AF_BLUE_STRING_CHEROKEE_CAPITAL "Ꮖ Ꮋ Ꭼ Ꮓ Ꭴ Ꮳ Ꭶ Ꮥ" AF_BLUE_STRING_CHEROKEE_SMALL_ASCENDER @@ -115,6 +168,22 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: AF_BLUE_STRING_CHEROKEE_SMALL_DESCENDER "ᏸ ꮐ ꭹ ꭻ" + AF_BLUE_STRING_COPTIC_CAPITAL_TOP + "Ⲍ Ⲏ Ⲡ Ⳟ Ⲟ Ⲑ Ⲥ Ⳋ" + AF_BLUE_STRING_COPTIC_CAPITAL_BOTTOM + "Ⳑ Ⳙ Ⳟ Ⲏ Ⲟ Ⲑ Ⳝ Ⲱ" + AF_BLUE_STRING_COPTIC_SMALL_TOP + "ⲍ ⲏ ⲡ ⳟ ⲟ ⲑ ⲥ ⳋ" + AF_BLUE_STRING_COPTIC_SMALL_BOTTOM + "ⳑ ⳙ ⳟ ⲏ ⲟ ⲑ ⳝ Ⳓ" + + AF_BLUE_STRING_CYPRIOT_TOP + "𐠍 𐠙 𐠳 𐠱 𐠅 𐠓 𐠣 𐠦" + AF_BLUE_STRING_CYPRIOT_BOTTOM + "𐠃 𐠊 𐠛 𐠣 𐠳 𐠵 𐠐" + AF_BLUE_STRING_CYPRIOT_SMALL + "𐠈 𐠏 𐠖" + AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP "Б В Е П З О С Э" AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM @@ -124,6 +193,15 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER "р у ф" + AF_BLUE_STRING_DESERET_CAPITAL_TOP + "𐐂 𐐄 𐐋 𐐗 𐐑" + AF_BLUE_STRING_DESERET_CAPITAL_BOTTOM + "𐐀 𐐂 𐐄 𐐗 𐐛" + AF_BLUE_STRING_DESERET_SMALL_TOP + "𐐪 𐐬 𐐳 𐐿 𐐹" + AF_BLUE_STRING_DESERET_SMALL_BOTTOM + "𐐨 𐐪 𐐬 𐐿 𐑃" + AF_BLUE_STRING_DEVANAGARI_BASE "क म अ आ थ ध भ श" AF_BLUE_STRING_DEVANAGARI_TOP @@ -164,6 +242,25 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: AF_BLUE_STRING_GEORGIAN_NUSKHURI_DESCENDER "ⴄ ⴅ ⴔ ⴕ ⴁ ⴂ ⴘ ⴝ" + AF_BLUE_STRING_GEORGIAN_MTAVRULI_TOP + "Ნ Ჟ Ჳ Ჸ Გ Ე Ო Ჴ" + AF_BLUE_STRING_GEORGIAN_MTAVRULI_BOTTOM + "Ი Ჲ Ო Ჩ Მ Შ Ჯ Ჽ" + + AF_BLUE_STRING_GLAGOLITIC_CAPITAL_TOP + "Ⰵ Ⱄ Ⱚ Ⰴ Ⰲ Ⰺ Ⱛ Ⰻ" + AF_BLUE_STRING_GLAGOLITIC_CAPITAL_BOTTOM + "Ⰵ Ⰴ Ⰲ Ⱚ Ⱎ Ⱑ Ⰺ Ⱄ" + AF_BLUE_STRING_GLAGOLITIC_SMALL_TOP + "ⰵ ⱄ ⱚ ⰴ ⰲ ⰺ ⱛ ⰻ" + AF_BLUE_STRING_GLAGOLITIC_SMALL_BOTTOM + "ⰵ ⰴ ⰲ ⱚ ⱎ ⱑ ⰺ ⱄ" + + AF_BLUE_STRING_GOTHIC_TOP + "𐌲 𐌶 𐍀 𐍄 𐌴 𐍃 𐍈 𐌾" + AF_BLUE_STRING_GOTHIC_BOTTOM + "𐌶 𐌴 𐍃 𐍈" + AF_BLUE_STRING_GREEK_CAPITAL_TOP "Γ Β Ε Ζ Θ Ο Ω" AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM @@ -209,6 +306,17 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: AF_BLUE_STRING_KANNADA_BOTTOM "ಅ ಉ ಎ ಲ ೦ ೨ ೬ ೭" + AF_BLUE_STRING_KAYAH_LI_TOP + "꤅ ꤏ ꤁ ꤋ ꤀ ꤍ" + AF_BLUE_STRING_KAYAH_LI_BOTTOM + "꤈ ꤘ ꤀ ꤍ ꤢ" + AF_BLUE_STRING_KAYAH_LI_ASCENDER + "ꤖ ꤡ" + AF_BLUE_STRING_KAYAH_LI_DESCENDER + "ꤑ ꤜ ꤞ" + AF_BLUE_STRING_KAYAH_LI_LARGE_DESCENDER + "ꤑ꤬ ꤜ꤭ ꤔ꤬" + AF_BLUE_STRING_KHMER_TOP "ខ ទ ន ឧ ឩ ា" AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP @@ -242,8 +350,10 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: "H E Z L O C U S" AF_BLUE_STRING_LATIN_SMALL_F_TOP "f i j k d b h" - AF_BLUE_STRING_LATIN_SMALL - "x z r o e s c" + AF_BLUE_STRING_LATIN_SMALL_TOP + "u v x z o e s c" + AF_BLUE_STRING_LATIN_SMALL_BOTTOM + "n r x z o e s c" AF_BLUE_STRING_LATIN_SMALL_DESCENDER "p q g j y" @@ -272,6 +382,11 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER "ᵖ ʸ ᵍ" + AF_BLUE_STRING_LISU_TOP + "ꓡ ꓧ ꓱ ꓶ ꓩ ꓚ ꓵ ꓳ" + AF_BLUE_STRING_LISU_BOTTOM + "ꓕ ꓜ ꓞ ꓡ ꓛ ꓢ ꓳ ꓴ" + AF_BLUE_STRING_MALAYALAM_TOP "ഒ ട ഠ റ ച പ ച്ച പ്പ" AF_BLUE_STRING_MALAYALAM_BOTTOM @@ -286,6 +401,59 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: AF_BLUE_STRING_MYANMAR_DESCENDER "ဉ ည ဥ ဩ ဨ ၂ ၅ ၉" + AF_BLUE_STRING_NKO_TOP + "ߐ ߉ ߒ ߟ ߖ ߜ ߠ ߥ" + AF_BLUE_STRING_NKO_BOTTOM + "߀ ߘ ߡ ߠ ߥ" + AF_BLUE_STRING_NKO_SMALL_TOP + "ߏ ߛ ߋ" + AF_BLUE_STRING_NKO_SMALL_BOTTOM + "ߎ ߏ ߛ ߋ" + + AF_BLUE_STRING_OL_CHIKI + "ᱛ ᱜ ᱝ ᱡ ᱢ ᱥ" + + AF_BLUE_STRING_OLD_TURKIC_TOP + "𐰗 𐰘 𐰧" + AF_BLUE_STRING_OLD_TURKIC_BOTTOM + "𐰉 𐰗 𐰦 𐰧" + + AF_BLUE_STRING_OSAGE_CAPITAL_TOP + "𐒾 𐓍 𐓒 𐓓 𐒻 𐓂 𐒵 𐓆" + AF_BLUE_STRING_OSAGE_CAPITAL_BOTTOM + "𐒰 𐓍 𐓂 𐒿 𐓎 𐒹" + AF_BLUE_STRING_OSAGE_CAPITAL_DESCENDER + "𐒼 𐒽 𐒾" + AF_BLUE_STRING_OSAGE_SMALL_TOP + "𐓵 𐓶 𐓺 𐓻 𐓝 𐓣 𐓪 𐓮" + AF_BLUE_STRING_OSAGE_SMALL_BOTTOM + "𐓘 𐓚 𐓣 𐓵 𐓡 𐓧 𐓪 𐓶" + AF_BLUE_STRING_OSAGE_SMALL_ASCENDER + "𐓤 𐓦 𐓸 𐓹 𐓛" + AF_BLUE_STRING_OSAGE_SMALL_DESCENDER + "𐓤 𐓥 𐓦" + + AF_BLUE_STRING_OSMANYA_TOP + "𐒆 𐒉 𐒐 𐒒 𐒘 𐒛 𐒠 𐒣" + AF_BLUE_STRING_OSMANYA_BOTTOM + "𐒀 𐒂 𐒆 𐒈 𐒊 𐒒 𐒠 𐒩" + + AF_BLUE_STRING_SAURASHTRA_TOP + "ꢜ ꢞ ꢳ ꢂ ꢖ ꢒ ꢝ ꢛ" + AF_BLUE_STRING_SAURASHTRA_BOTTOM + "ꢂ ꢨ ꢺ ꢤ ꢎ" + + AF_BLUE_STRING_SHAVIAN_TOP + "𐑕 𐑙" + AF_BLUE_STRING_SHAVIAN_BOTTOM + "𐑔 𐑖 𐑗 𐑹 𐑻" + AF_BLUE_STRING_SHAVIAN_DESCENDER + "𐑟 𐑣" + AF_BLUE_STRING_SHAVIAN_SMALL_TOP + "𐑱 𐑲 𐑳 𐑴 𐑸 𐑺 𐑼" + AF_BLUE_STRING_SHAVIAN_SMALL_BOTTOM + "𐑴 𐑻 𐑹" + AF_BLUE_STRING_SINHALA_TOP "ඉ ක ඝ ඳ ප ය ල ෆ" AF_BLUE_STRING_SINHALA_BOTTOM @@ -293,6 +461,18 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: AF_BLUE_STRING_SINHALA_DESCENDER "ද ඳ උ ල තූ තු බු දු" + AF_BLUE_STRING_SUNDANESE_TOP + "ᮋ ᮞ ᮮ ᮽ ᮰ ᮈ" + AF_BLUE_STRING_SUNDANESE_BOTTOM + "ᮄ ᮔ ᮕ ᮗ ᮰ ᮆ ᮈ ᮉ" + AF_BLUE_STRING_SUNDANESE_DESCENDER + "ᮼ ᳄" + + AF_BLUE_STRING_TAI_VIET_TOP + "ꪆ ꪔ ꪒ ꪖ ꪫ" + AF_BLUE_STRING_TAI_VIET_BOTTOM + "ꪉ ꪫ ꪮ" + AF_BLUE_STRING_TAMIL_TOP "உ ஒ ஓ ற ஈ க ங ச" AF_BLUE_STRING_TAMIL_BOTTOM @@ -318,6 +498,14 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: AF_BLUE_STRING_THAI_DIGIT_TOP "๐ ๑ ๓" + AF_BLUE_STRING_TIFINAGH + "ⵔ ⵙ ⵛ ⵞ ⴵ ⴼ ⴹ ⵎ" + + AF_BLUE_STRING_VAI_TOP + "ꗍ ꘖ ꘙ ꘜ ꖜ ꖝ ꔅ ꕢ" + AF_BLUE_STRING_VAI_BOTTOM + "ꗍ ꘖ ꘙ ꗞ ꔅ ꕢ ꖜ ꔆ" + #ifdef AF_CONFIG_OPTION_CJK @@ -483,6 +671,14 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: + AF_BLUE_STRINGSET_ADLM + { AF_BLUE_STRING_ADLAM_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_ADLAM_CAPITAL_BOTTOM, 0 } + { AF_BLUE_STRING_ADLAM_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_ADLAM_SMALL_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_ARAB { AF_BLUE_STRING_ARABIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_ARABIC_BOTTOM, 0 } @@ -499,6 +695,16 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER, 0 } { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_AVST + { AF_BLUE_STRING_AVESTAN_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_AVESTAN_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + + AF_BLUE_STRINGSET_BAMU + { AF_BLUE_STRING_BAMUM_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_BAMUM_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_BENG { AF_BLUE_STRING_BENGALI_TOP, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_BENGALI_HEAD, AF_BLUE_PROPERTY_LATIN_TOP } @@ -508,6 +714,35 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_BENGALI_BASE, 0 } { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_BUHD + { AF_BLUE_STRING_BUHID_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_BUHID_LARGE, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_BUHID_SMALL, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_BUHID_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + + AF_BLUE_STRINGSET_CAKM + { AF_BLUE_STRING_CHAKMA_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_CHAKMA_BOTTOM, 0 } + { AF_BLUE_STRING_CHAKMA_DESCENDER, 0 } + { AF_BLUE_STRING_MAX, 0 } + + AF_BLUE_STRINGSET_CANS + { AF_BLUE_STRING_CANADIAN_SYLLABICS_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_CANADIAN_SYLLABICS_BOTTOM, 0 } + { AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_BOTTOM, 0 } + { AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + + AF_BLUE_STRINGSET_CARI + { AF_BLUE_STRING_CARIAN_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_CARIAN_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_CHER { AF_BLUE_STRING_CHEROKEE_CAPITAL, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_CHEROKEE_CAPITAL, 0 } @@ -518,6 +753,21 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_CHEROKEE_SMALL_DESCENDER, 0 } { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_COPT + { AF_BLUE_STRING_COPTIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_COPTIC_CAPITAL_BOTTOM, 0 } + { AF_BLUE_STRING_COPTIC_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_COPTIC_SMALL_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + + AF_BLUE_STRINGSET_CPRT + { AF_BLUE_STRING_CYPRIOT_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_CYPRIOT_BOTTOM, 0 } + { AF_BLUE_STRING_CYPRIOT_SMALL, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_CYPRIOT_SMALL, 0 } + { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_CYRL { AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM, 0 } @@ -537,18 +787,27 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_DEVANAGARI_BOTTOM, 0 } { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_DSRT + { AF_BLUE_STRING_DESERET_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_DESERET_CAPITAL_BOTTOM, 0 } + { AF_BLUE_STRING_DESERET_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_DESERET_SMALL_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_ETHI { AF_BLUE_STRING_ETHIOPIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_ETHIOPIC_BOTTOM, 0 } { AF_BLUE_STRING_MAX, 0 } - // blue zones for Mtavruli are missing (not yet defined in Unicode) AF_BLUE_STRINGSET_GEOR { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_TOP, AF_BLUE_PROPERTY_LATIN_TOP | AF_BLUE_PROPERTY_LATIN_X_HEIGHT } { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_BOTTOM, 0 } { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_DESCENDER, 0 } + { AF_BLUE_STRING_GEORGIAN_MTAVRULI_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_GEORGIAN_MTAVRULI_BOTTOM, 0 } { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_GEOK @@ -561,6 +820,19 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_GEORGIAN_NUSKHURI_DESCENDER, 0 } { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_GLAG + { AF_BLUE_STRING_GLAGOLITIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_GLAGOLITIC_CAPITAL_BOTTOM, 0 } + { AF_BLUE_STRING_GLAGOLITIC_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_GLAGOLITIC_SMALL_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + + AF_BLUE_STRINGSET_GOTH + { AF_BLUE_STRING_GOTHIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_GOTHIC_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_GREK { AF_BLUE_STRING_GREEK_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM, 0 } @@ -597,10 +869,14 @@ 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_KNDA - { AF_BLUE_STRING_KANNADA_TOP, AF_BLUE_PROPERTY_LATIN_TOP } - { AF_BLUE_STRING_KANNADA_BOTTOM, 0 } - { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_KALI + { AF_BLUE_STRING_KAYAH_LI_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_KAYAH_LI_BOTTOM, 0 } + { AF_BLUE_STRING_KAYAH_LI_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_KAYAH_LI_DESCENDER, 0 } + { AF_BLUE_STRING_KAYAH_LI_LARGE_DESCENDER, 0 } + { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_KHMR { AF_BLUE_STRING_KHMER_TOP, AF_BLUE_PROPERTY_LATIN_TOP | @@ -617,6 +893,11 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM, 0 } { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_KNDA + { AF_BLUE_STRING_KANNADA_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_KANNADA_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_LAO { AF_BLUE_STRING_LAO_TOP, AF_BLUE_PROPERTY_LATIN_TOP | AF_BLUE_PROPERTY_LATIN_X_HEIGHT } @@ -630,9 +911,9 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { 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_STRING_LATIN_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | AF_BLUE_PROPERTY_LATIN_X_HEIGHT } - { AF_BLUE_STRING_LATIN_SMALL, 0 } + { AF_BLUE_STRING_LATIN_SMALL_BOTTOM, 0 } { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0 } { AF_BLUE_STRING_MAX, 0 } @@ -656,6 +937,11 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER, 0 } { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_LISU + { AF_BLUE_STRING_LISU_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_LISU_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_MLYM { AF_BLUE_STRING_MALAYALAM_TOP, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_MALAYALAM_BOTTOM, 0 } @@ -669,25 +955,89 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_MYANMAR_DESCENDER, 0 } { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_NKOO + { AF_BLUE_STRING_NKO_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_NKO_BOTTOM, 0 } + { AF_BLUE_STRING_NKO_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_NKO_SMALL_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_NONE { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_OLCK + { AF_BLUE_STRING_OL_CHIKI, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_OL_CHIKI, 0 } + { AF_BLUE_STRING_MAX, 0 } + + AF_BLUE_STRINGSET_ORKH + { AF_BLUE_STRING_OLD_TURKIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_OLD_TURKIC_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + + AF_BLUE_STRINGSET_OSGE + { AF_BLUE_STRING_OSAGE_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_OSAGE_CAPITAL_BOTTOM, 0 } + { AF_BLUE_STRING_OSAGE_CAPITAL_DESCENDER, 0 } + { AF_BLUE_STRING_OSAGE_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_OSAGE_SMALL_BOTTOM, 0 } + { AF_BLUE_STRING_OSAGE_SMALL_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_OSAGE_SMALL_DESCENDER, 0 } + { AF_BLUE_STRING_MAX, 0 } + + AF_BLUE_STRINGSET_OSMA + { AF_BLUE_STRING_OSMANYA_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_OSMANYA_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + + AF_BLUE_STRINGSET_SAUR + { AF_BLUE_STRING_SAURASHTRA_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_SAURASHTRA_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + + AF_BLUE_STRINGSET_SHAW + { AF_BLUE_STRING_SHAVIAN_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_SHAVIAN_BOTTOM, 0 } + { AF_BLUE_STRING_SHAVIAN_DESCENDER, 0 } + { AF_BLUE_STRING_SHAVIAN_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_SHAVIAN_SMALL_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_SINH { AF_BLUE_STRING_SINHALA_TOP, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_SINHALA_BOTTOM, 0 } { AF_BLUE_STRING_SINHALA_DESCENDER, 0 } { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_SUND + { AF_BLUE_STRING_SUNDANESE_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_SUNDANESE_BOTTOM, 0 } + { AF_BLUE_STRING_SUNDANESE_DESCENDER, 0 } + { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_TAML { AF_BLUE_STRING_TAMIL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_TAMIL_BOTTOM, 0 } { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_TAVT + { AF_BLUE_STRING_TAI_VIET_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_TAI_VIET_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_TELU { AF_BLUE_STRING_TELUGU_TOP, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_TELUGU_BOTTOM, 0 } { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_TFNG + { AF_BLUE_STRING_TIFINAGH, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_TIFINAGH, 0 } + { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_THAI { AF_BLUE_STRING_THAI_TOP, AF_BLUE_PROPERTY_LATIN_TOP | AF_BLUE_PROPERTY_LATIN_X_HEIGHT } @@ -699,6 +1049,10 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_THAI_DIGIT_TOP, 0 } { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_STRINGSET_VAII + { AF_BLUE_STRING_VAI_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_VAI_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } #ifdef AF_CONFIG_OPTION_CJK diff --git a/modules/freetype2/src/autofit/afblue.h b/modules/freetype2/src/autofit/afblue.h index 75c3ab508..de31e259c 100644 --- a/modules/freetype2/src/autofit/afblue.h +++ b/modules/freetype2/src/autofit/afblue.h @@ -7,7 +7,7 @@ /* */ /* Auto-fitter data for blue strings (specification). */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -77,110 +77,191 @@ FT_BEGIN_HEADER typedef enum AF_Blue_String_ { - AF_BLUE_STRING_ARABIC_TOP = 0, - AF_BLUE_STRING_ARABIC_BOTTOM = 18, - AF_BLUE_STRING_ARABIC_JOIN = 33, - AF_BLUE_STRING_ARMENIAN_CAPITAL_TOP = 36, - AF_BLUE_STRING_ARMENIAN_CAPITAL_BOTTOM = 60, - AF_BLUE_STRING_ARMENIAN_SMALL_ASCENDER = 84, - AF_BLUE_STRING_ARMENIAN_SMALL_TOP = 105, - AF_BLUE_STRING_ARMENIAN_SMALL_BOTTOM = 129, - AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER = 153, - AF_BLUE_STRING_BENGALI_BASE = 177, - AF_BLUE_STRING_BENGALI_TOP = 209, - AF_BLUE_STRING_BENGALI_HEAD = 237, - AF_BLUE_STRING_CHEROKEE_CAPITAL = 269, - AF_BLUE_STRING_CHEROKEE_SMALL_ASCENDER = 301, - AF_BLUE_STRING_CHEROKEE_SMALL = 333, - AF_BLUE_STRING_CHEROKEE_SMALL_DESCENDER = 365, - AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP = 381, - AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM = 405, - AF_BLUE_STRING_CYRILLIC_SMALL = 429, - AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER = 453, - AF_BLUE_STRING_DEVANAGARI_BASE = 462, - AF_BLUE_STRING_DEVANAGARI_TOP = 494, - AF_BLUE_STRING_DEVANAGARI_HEAD = 526, - AF_BLUE_STRING_DEVANAGARI_BOTTOM = 558, - AF_BLUE_STRING_ETHIOPIC_TOP = 566, - AF_BLUE_STRING_ETHIOPIC_BOTTOM = 598, - AF_BLUE_STRING_GEORGIAN_MKHEDRULI_TOP = 630, - AF_BLUE_STRING_GEORGIAN_MKHEDRULI_BOTTOM = 662, - AF_BLUE_STRING_GEORGIAN_MKHEDRULI_ASCENDER = 694, - AF_BLUE_STRING_GEORGIAN_MKHEDRULI_DESCENDER = 726, - AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_TOP = 758, - AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_BOTTOM = 790, - AF_BLUE_STRING_GEORGIAN_NUSKHURI_TOP = 822, - AF_BLUE_STRING_GEORGIAN_NUSKHURI_BOTTOM = 854, - AF_BLUE_STRING_GEORGIAN_NUSKHURI_ASCENDER = 886, - AF_BLUE_STRING_GEORGIAN_NUSKHURI_DESCENDER = 918, - AF_BLUE_STRING_GREEK_CAPITAL_TOP = 950, - AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM = 971, - AF_BLUE_STRING_GREEK_SMALL_BETA_TOP = 989, - AF_BLUE_STRING_GREEK_SMALL = 1007, - AF_BLUE_STRING_GREEK_SMALL_DESCENDER = 1031, - AF_BLUE_STRING_GUJARATI_TOP = 1055, - AF_BLUE_STRING_GUJARATI_BOTTOM = 1087, - AF_BLUE_STRING_GUJARATI_ASCENDER = 1119, - AF_BLUE_STRING_GUJARATI_DESCENDER = 1169, - AF_BLUE_STRING_GUJARATI_DIGIT_TOP = 1202, - AF_BLUE_STRING_GURMUKHI_BASE = 1222, - AF_BLUE_STRING_GURMUKHI_HEAD = 1254, - AF_BLUE_STRING_GURMUKHI_TOP = 1286, - AF_BLUE_STRING_GURMUKHI_BOTTOM = 1318, - AF_BLUE_STRING_GURMUKHI_DIGIT_TOP = 1350, - AF_BLUE_STRING_HEBREW_TOP = 1370, - AF_BLUE_STRING_HEBREW_BOTTOM = 1394, - AF_BLUE_STRING_HEBREW_DESCENDER = 1412, - AF_BLUE_STRING_KANNADA_TOP = 1427, - AF_BLUE_STRING_KANNADA_BOTTOM = 1471, - AF_BLUE_STRING_KHMER_TOP = 1503, - AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP = 1527, - AF_BLUE_STRING_KHMER_BOTTOM = 1567, - AF_BLUE_STRING_KHMER_DESCENDER = 1599, - AF_BLUE_STRING_KHMER_LARGE_DESCENDER = 1633, - AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP = 1720, - AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM = 1728, - AF_BLUE_STRING_LAO_TOP = 1736, - AF_BLUE_STRING_LAO_BOTTOM = 1768, - AF_BLUE_STRING_LAO_ASCENDER = 1800, - AF_BLUE_STRING_LAO_LARGE_ASCENDER = 1816, - AF_BLUE_STRING_LAO_DESCENDER = 1828, - AF_BLUE_STRING_LATIN_CAPITAL_TOP = 1852, - AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM = 1868, - AF_BLUE_STRING_LATIN_SMALL_F_TOP = 1884, - AF_BLUE_STRING_LATIN_SMALL = 1898, - AF_BLUE_STRING_LATIN_SMALL_DESCENDER = 1912, - AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP = 1922, - AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM = 1942, - AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP = 1962, - AF_BLUE_STRING_LATIN_SUBS_SMALL = 1982, - AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER = 2018, - AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP = 2038, - AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM = 2069, - AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP = 2098, - AF_BLUE_STRING_LATIN_SUPS_SMALL = 2124, - AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER = 2149, - AF_BLUE_STRING_MALAYALAM_TOP = 2160, - AF_BLUE_STRING_MALAYALAM_BOTTOM = 2204, - AF_BLUE_STRING_MYANMAR_TOP = 2236, - AF_BLUE_STRING_MYANMAR_BOTTOM = 2268, - AF_BLUE_STRING_MYANMAR_ASCENDER = 2300, - AF_BLUE_STRING_MYANMAR_DESCENDER = 2328, - AF_BLUE_STRING_SINHALA_TOP = 2360, - AF_BLUE_STRING_SINHALA_BOTTOM = 2392, - AF_BLUE_STRING_SINHALA_DESCENDER = 2424, - AF_BLUE_STRING_TAMIL_TOP = 2468, - AF_BLUE_STRING_TAMIL_BOTTOM = 2500, - AF_BLUE_STRING_TELUGU_TOP = 2532, - AF_BLUE_STRING_TELUGU_BOTTOM = 2560, - AF_BLUE_STRING_THAI_TOP = 2588, - AF_BLUE_STRING_THAI_BOTTOM = 2612, - AF_BLUE_STRING_THAI_ASCENDER = 2640, - AF_BLUE_STRING_THAI_LARGE_ASCENDER = 2652, - AF_BLUE_STRING_THAI_DESCENDER = 2664, - AF_BLUE_STRING_THAI_LARGE_DESCENDER = 2680, - AF_BLUE_STRING_THAI_DIGIT_TOP = 2688, - af_blue_1_1 = 2699, + AF_BLUE_STRING_ADLAM_CAPITAL_TOP = 0, + AF_BLUE_STRING_ADLAM_CAPITAL_BOTTOM = 30, + AF_BLUE_STRING_ADLAM_SMALL_TOP = 40, + AF_BLUE_STRING_ADLAM_SMALL_BOTTOM = 65, + AF_BLUE_STRING_ARABIC_TOP = 105, + AF_BLUE_STRING_ARABIC_BOTTOM = 123, + AF_BLUE_STRING_ARABIC_JOIN = 138, + AF_BLUE_STRING_ARMENIAN_CAPITAL_TOP = 141, + AF_BLUE_STRING_ARMENIAN_CAPITAL_BOTTOM = 165, + AF_BLUE_STRING_ARMENIAN_SMALL_ASCENDER = 189, + AF_BLUE_STRING_ARMENIAN_SMALL_TOP = 210, + AF_BLUE_STRING_ARMENIAN_SMALL_BOTTOM = 234, + AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER = 258, + AF_BLUE_STRING_AVESTAN_TOP = 282, + AF_BLUE_STRING_AVESTAN_BOTTOM = 302, + AF_BLUE_STRING_BAMUM_TOP = 312, + AF_BLUE_STRING_BAMUM_BOTTOM = 344, + AF_BLUE_STRING_BENGALI_BASE = 376, + AF_BLUE_STRING_BENGALI_TOP = 408, + AF_BLUE_STRING_BENGALI_HEAD = 436, + AF_BLUE_STRING_BUHID_TOP = 468, + AF_BLUE_STRING_BUHID_LARGE = 476, + AF_BLUE_STRING_BUHID_SMALL = 488, + AF_BLUE_STRING_BUHID_BOTTOM = 504, + AF_BLUE_STRING_CANADIAN_SYLLABICS_TOP = 532, + AF_BLUE_STRING_CANADIAN_SYLLABICS_BOTTOM = 564, + AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_TOP = 596, + AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_BOTTOM = 628, + AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_TOP = 660, + AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_BOTTOM = 688, + AF_BLUE_STRING_CARIAN_TOP = 720, + AF_BLUE_STRING_CARIAN_BOTTOM = 760, + AF_BLUE_STRING_CHAKMA_TOP = 795, + AF_BLUE_STRING_CHAKMA_BOTTOM = 820, + AF_BLUE_STRING_CHAKMA_DESCENDER = 845, + AF_BLUE_STRING_CHEROKEE_CAPITAL = 910, + AF_BLUE_STRING_CHEROKEE_SMALL_ASCENDER = 942, + AF_BLUE_STRING_CHEROKEE_SMALL = 974, + AF_BLUE_STRING_CHEROKEE_SMALL_DESCENDER = 1006, + AF_BLUE_STRING_COPTIC_CAPITAL_TOP = 1022, + AF_BLUE_STRING_COPTIC_CAPITAL_BOTTOM = 1054, + AF_BLUE_STRING_COPTIC_SMALL_TOP = 1086, + AF_BLUE_STRING_COPTIC_SMALL_BOTTOM = 1118, + AF_BLUE_STRING_CYPRIOT_TOP = 1150, + AF_BLUE_STRING_CYPRIOT_BOTTOM = 1190, + AF_BLUE_STRING_CYPRIOT_SMALL = 1225, + AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP = 1240, + AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM = 1264, + AF_BLUE_STRING_CYRILLIC_SMALL = 1288, + AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER = 1312, + AF_BLUE_STRING_DESERET_CAPITAL_TOP = 1321, + AF_BLUE_STRING_DESERET_CAPITAL_BOTTOM = 1346, + AF_BLUE_STRING_DESERET_SMALL_TOP = 1371, + AF_BLUE_STRING_DESERET_SMALL_BOTTOM = 1396, + AF_BLUE_STRING_DEVANAGARI_BASE = 1421, + AF_BLUE_STRING_DEVANAGARI_TOP = 1453, + AF_BLUE_STRING_DEVANAGARI_HEAD = 1485, + AF_BLUE_STRING_DEVANAGARI_BOTTOM = 1517, + AF_BLUE_STRING_ETHIOPIC_TOP = 1525, + AF_BLUE_STRING_ETHIOPIC_BOTTOM = 1557, + AF_BLUE_STRING_GEORGIAN_MKHEDRULI_TOP = 1589, + AF_BLUE_STRING_GEORGIAN_MKHEDRULI_BOTTOM = 1621, + AF_BLUE_STRING_GEORGIAN_MKHEDRULI_ASCENDER = 1653, + AF_BLUE_STRING_GEORGIAN_MKHEDRULI_DESCENDER = 1685, + AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_TOP = 1717, + AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_BOTTOM = 1749, + AF_BLUE_STRING_GEORGIAN_NUSKHURI_TOP = 1781, + AF_BLUE_STRING_GEORGIAN_NUSKHURI_BOTTOM = 1813, + AF_BLUE_STRING_GEORGIAN_NUSKHURI_ASCENDER = 1845, + AF_BLUE_STRING_GEORGIAN_NUSKHURI_DESCENDER = 1877, + AF_BLUE_STRING_GEORGIAN_MTAVRULI_TOP = 1909, + AF_BLUE_STRING_GEORGIAN_MTAVRULI_BOTTOM = 1941, + AF_BLUE_STRING_GLAGOLITIC_CAPITAL_TOP = 1973, + AF_BLUE_STRING_GLAGOLITIC_CAPITAL_BOTTOM = 2005, + AF_BLUE_STRING_GLAGOLITIC_SMALL_TOP = 2037, + AF_BLUE_STRING_GLAGOLITIC_SMALL_BOTTOM = 2069, + AF_BLUE_STRING_GOTHIC_TOP = 2101, + AF_BLUE_STRING_GOTHIC_BOTTOM = 2141, + AF_BLUE_STRING_GREEK_CAPITAL_TOP = 2161, + AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM = 2182, + AF_BLUE_STRING_GREEK_SMALL_BETA_TOP = 2200, + AF_BLUE_STRING_GREEK_SMALL = 2218, + AF_BLUE_STRING_GREEK_SMALL_DESCENDER = 2242, + AF_BLUE_STRING_GUJARATI_TOP = 2266, + AF_BLUE_STRING_GUJARATI_BOTTOM = 2298, + AF_BLUE_STRING_GUJARATI_ASCENDER = 2330, + AF_BLUE_STRING_GUJARATI_DESCENDER = 2380, + AF_BLUE_STRING_GUJARATI_DIGIT_TOP = 2413, + AF_BLUE_STRING_GURMUKHI_BASE = 2433, + AF_BLUE_STRING_GURMUKHI_HEAD = 2465, + AF_BLUE_STRING_GURMUKHI_TOP = 2497, + AF_BLUE_STRING_GURMUKHI_BOTTOM = 2529, + AF_BLUE_STRING_GURMUKHI_DIGIT_TOP = 2561, + AF_BLUE_STRING_HEBREW_TOP = 2581, + AF_BLUE_STRING_HEBREW_BOTTOM = 2605, + AF_BLUE_STRING_HEBREW_DESCENDER = 2623, + AF_BLUE_STRING_KANNADA_TOP = 2638, + AF_BLUE_STRING_KANNADA_BOTTOM = 2682, + AF_BLUE_STRING_KAYAH_LI_TOP = 2714, + AF_BLUE_STRING_KAYAH_LI_BOTTOM = 2738, + AF_BLUE_STRING_KAYAH_LI_ASCENDER = 2758, + AF_BLUE_STRING_KAYAH_LI_DESCENDER = 2766, + AF_BLUE_STRING_KAYAH_LI_LARGE_DESCENDER = 2778, + AF_BLUE_STRING_KHMER_TOP = 2799, + AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP = 2823, + AF_BLUE_STRING_KHMER_BOTTOM = 2863, + AF_BLUE_STRING_KHMER_DESCENDER = 2895, + AF_BLUE_STRING_KHMER_LARGE_DESCENDER = 2929, + AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP = 3016, + AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM = 3024, + AF_BLUE_STRING_LAO_TOP = 3032, + AF_BLUE_STRING_LAO_BOTTOM = 3064, + AF_BLUE_STRING_LAO_ASCENDER = 3096, + AF_BLUE_STRING_LAO_LARGE_ASCENDER = 3112, + AF_BLUE_STRING_LAO_DESCENDER = 3124, + AF_BLUE_STRING_LATIN_CAPITAL_TOP = 3148, + AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM = 3164, + AF_BLUE_STRING_LATIN_SMALL_F_TOP = 3180, + AF_BLUE_STRING_LATIN_SMALL_TOP = 3194, + AF_BLUE_STRING_LATIN_SMALL_BOTTOM = 3210, + AF_BLUE_STRING_LATIN_SMALL_DESCENDER = 3226, + AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP = 3236, + AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM = 3256, + AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP = 3276, + AF_BLUE_STRING_LATIN_SUBS_SMALL = 3296, + AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER = 3332, + AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP = 3352, + AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM = 3383, + AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP = 3412, + AF_BLUE_STRING_LATIN_SUPS_SMALL = 3438, + AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER = 3463, + AF_BLUE_STRING_LISU_TOP = 3474, + AF_BLUE_STRING_LISU_BOTTOM = 3506, + AF_BLUE_STRING_MALAYALAM_TOP = 3538, + AF_BLUE_STRING_MALAYALAM_BOTTOM = 3582, + AF_BLUE_STRING_MYANMAR_TOP = 3614, + AF_BLUE_STRING_MYANMAR_BOTTOM = 3646, + AF_BLUE_STRING_MYANMAR_ASCENDER = 3678, + AF_BLUE_STRING_MYANMAR_DESCENDER = 3706, + AF_BLUE_STRING_NKO_TOP = 3738, + AF_BLUE_STRING_NKO_BOTTOM = 3762, + AF_BLUE_STRING_NKO_SMALL_TOP = 3777, + AF_BLUE_STRING_NKO_SMALL_BOTTOM = 3786, + AF_BLUE_STRING_OL_CHIKI = 3798, + AF_BLUE_STRING_OLD_TURKIC_TOP = 3822, + AF_BLUE_STRING_OLD_TURKIC_BOTTOM = 3837, + AF_BLUE_STRING_OSAGE_CAPITAL_TOP = 3857, + AF_BLUE_STRING_OSAGE_CAPITAL_BOTTOM = 3897, + AF_BLUE_STRING_OSAGE_CAPITAL_DESCENDER = 3927, + AF_BLUE_STRING_OSAGE_SMALL_TOP = 3942, + AF_BLUE_STRING_OSAGE_SMALL_BOTTOM = 3982, + AF_BLUE_STRING_OSAGE_SMALL_ASCENDER = 4022, + AF_BLUE_STRING_OSAGE_SMALL_DESCENDER = 4047, + AF_BLUE_STRING_OSMANYA_TOP = 4062, + AF_BLUE_STRING_OSMANYA_BOTTOM = 4102, + AF_BLUE_STRING_SAURASHTRA_TOP = 4142, + AF_BLUE_STRING_SAURASHTRA_BOTTOM = 4174, + AF_BLUE_STRING_SHAVIAN_TOP = 4194, + AF_BLUE_STRING_SHAVIAN_BOTTOM = 4204, + AF_BLUE_STRING_SHAVIAN_DESCENDER = 4229, + AF_BLUE_STRING_SHAVIAN_SMALL_TOP = 4239, + AF_BLUE_STRING_SHAVIAN_SMALL_BOTTOM = 4274, + AF_BLUE_STRING_SINHALA_TOP = 4289, + AF_BLUE_STRING_SINHALA_BOTTOM = 4321, + AF_BLUE_STRING_SINHALA_DESCENDER = 4353, + AF_BLUE_STRING_SUNDANESE_TOP = 4397, + AF_BLUE_STRING_SUNDANESE_BOTTOM = 4421, + AF_BLUE_STRING_SUNDANESE_DESCENDER = 4453, + AF_BLUE_STRING_TAI_VIET_TOP = 4461, + AF_BLUE_STRING_TAI_VIET_BOTTOM = 4481, + AF_BLUE_STRING_TAMIL_TOP = 4493, + AF_BLUE_STRING_TAMIL_BOTTOM = 4525, + AF_BLUE_STRING_TELUGU_TOP = 4557, + AF_BLUE_STRING_TELUGU_BOTTOM = 4585, + AF_BLUE_STRING_THAI_TOP = 4613, + AF_BLUE_STRING_THAI_BOTTOM = 4637, + AF_BLUE_STRING_THAI_ASCENDER = 4665, + AF_BLUE_STRING_THAI_LARGE_ASCENDER = 4677, + AF_BLUE_STRING_THAI_DESCENDER = 4689, + AF_BLUE_STRING_THAI_LARGE_DESCENDER = 4705, + AF_BLUE_STRING_THAI_DIGIT_TOP = 4713, + AF_BLUE_STRING_TIFINAGH = 4725, + AF_BLUE_STRING_VAI_TOP = 4757, + AF_BLUE_STRING_VAI_BOTTOM = 4789, + af_blue_1_1 = 4820, #ifdef AF_CONFIG_OPTION_CJK AF_BLUE_STRING_CJK_TOP = af_blue_1_1 + 1, AF_BLUE_STRING_CJK_BOTTOM = af_blue_1_1 + 203, @@ -239,34 +320,59 @@ FT_BEGIN_HEADER typedef enum AF_Blue_Stringset_ { - AF_BLUE_STRINGSET_ARAB = 0, - AF_BLUE_STRINGSET_ARMN = 4, - AF_BLUE_STRINGSET_BENG = 11, - AF_BLUE_STRINGSET_CHER = 16, - AF_BLUE_STRINGSET_CYRL = 23, - AF_BLUE_STRINGSET_DEVA = 29, - AF_BLUE_STRINGSET_ETHI = 35, - AF_BLUE_STRINGSET_GEOR = 38, - AF_BLUE_STRINGSET_GEOK = 43, - AF_BLUE_STRINGSET_GREK = 50, - AF_BLUE_STRINGSET_GUJR = 57, - AF_BLUE_STRINGSET_GURU = 63, - AF_BLUE_STRINGSET_HEBR = 69, - AF_BLUE_STRINGSET_KNDA = 73, - AF_BLUE_STRINGSET_KHMR = 76, - AF_BLUE_STRINGSET_KHMS = 82, - AF_BLUE_STRINGSET_LAO = 85, - AF_BLUE_STRINGSET_LATN = 91, - AF_BLUE_STRINGSET_LATB = 98, - AF_BLUE_STRINGSET_LATP = 105, - AF_BLUE_STRINGSET_MLYM = 112, - AF_BLUE_STRINGSET_MYMR = 115, - AF_BLUE_STRINGSET_NONE = 120, - AF_BLUE_STRINGSET_SINH = 121, - AF_BLUE_STRINGSET_TAML = 125, - AF_BLUE_STRINGSET_TELU = 128, - AF_BLUE_STRINGSET_THAI = 131, - af_blue_2_1 = 139, + AF_BLUE_STRINGSET_ADLM = 0, + AF_BLUE_STRINGSET_ARAB = 5, + AF_BLUE_STRINGSET_ARMN = 9, + AF_BLUE_STRINGSET_AVST = 16, + AF_BLUE_STRINGSET_BAMU = 19, + AF_BLUE_STRINGSET_BENG = 22, + AF_BLUE_STRINGSET_BUHD = 27, + AF_BLUE_STRINGSET_CAKM = 32, + AF_BLUE_STRINGSET_CANS = 36, + AF_BLUE_STRINGSET_CARI = 43, + AF_BLUE_STRINGSET_CHER = 46, + AF_BLUE_STRINGSET_COPT = 53, + AF_BLUE_STRINGSET_CPRT = 58, + AF_BLUE_STRINGSET_CYRL = 63, + AF_BLUE_STRINGSET_DEVA = 69, + AF_BLUE_STRINGSET_DSRT = 75, + AF_BLUE_STRINGSET_ETHI = 80, + AF_BLUE_STRINGSET_GEOR = 83, + AF_BLUE_STRINGSET_GEOK = 90, + AF_BLUE_STRINGSET_GLAG = 97, + AF_BLUE_STRINGSET_GOTH = 102, + AF_BLUE_STRINGSET_GREK = 105, + AF_BLUE_STRINGSET_GUJR = 112, + AF_BLUE_STRINGSET_GURU = 118, + AF_BLUE_STRINGSET_HEBR = 124, + AF_BLUE_STRINGSET_KALI = 128, + AF_BLUE_STRINGSET_KHMR = 134, + AF_BLUE_STRINGSET_KHMS = 140, + AF_BLUE_STRINGSET_KNDA = 143, + AF_BLUE_STRINGSET_LAO = 146, + AF_BLUE_STRINGSET_LATN = 152, + AF_BLUE_STRINGSET_LATB = 159, + AF_BLUE_STRINGSET_LATP = 166, + AF_BLUE_STRINGSET_LISU = 173, + AF_BLUE_STRINGSET_MLYM = 176, + AF_BLUE_STRINGSET_MYMR = 179, + AF_BLUE_STRINGSET_NKOO = 184, + AF_BLUE_STRINGSET_NONE = 189, + AF_BLUE_STRINGSET_OLCK = 190, + AF_BLUE_STRINGSET_ORKH = 193, + AF_BLUE_STRINGSET_OSGE = 196, + AF_BLUE_STRINGSET_OSMA = 204, + AF_BLUE_STRINGSET_SAUR = 207, + AF_BLUE_STRINGSET_SHAW = 210, + AF_BLUE_STRINGSET_SINH = 216, + AF_BLUE_STRINGSET_SUND = 220, + AF_BLUE_STRINGSET_TAML = 224, + AF_BLUE_STRINGSET_TAVT = 227, + AF_BLUE_STRINGSET_TELU = 230, + AF_BLUE_STRINGSET_TFNG = 233, + AF_BLUE_STRINGSET_THAI = 236, + AF_BLUE_STRINGSET_VAII = 244, + af_blue_2_1 = 247, #ifdef AF_CONFIG_OPTION_CJK AF_BLUE_STRINGSET_HANI = af_blue_2_1 + 0, af_blue_2_1_1 = af_blue_2_1 + 2, diff --git a/modules/freetype2/src/autofit/afblue.hin b/modules/freetype2/src/autofit/afblue.hin index dd44e7725..682147cb3 100644 --- a/modules/freetype2/src/autofit/afblue.hin +++ b/modules/freetype2/src/autofit/afblue.hin @@ -4,7 +4,7 @@ /* */ /* Auto-fitter data for blue strings (specification). */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/autofit/afcjk.c b/modules/freetype2/src/autofit/afcjk.c index 412663315..21b6bffa3 100644 --- a/modules/freetype2/src/autofit/afcjk.c +++ b/modules/freetype2/src/autofit/afcjk.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter hinting routines for CJK writing system (body). */ /* */ -/* Copyright 2006-2016 by */ +/* Copyright 2006-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -16,9 +16,9 @@ /***************************************************************************/ /* - * The algorithm is based on akito's autohint patch, available here: + * The algorithm is based on akito's autohint patch, archived at * - * http://www.kde.gr.jp/~akito/patch/freetype2/ + * https://web.archive.org/web/20051219160454/http://www.kde.gr.jp:80/~akito/patch/freetype2/2.1.7/ * */ @@ -29,13 +29,13 @@ #include "afglobal.h" #include "afpic.h" #include "aflatin.h" +#include "afcjk.h" #ifdef AF_CONFIG_OPTION_CJK #undef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT -#include "afcjk.h" #include "aferrors.h" @@ -563,7 +563,7 @@ FT_Face face ) { FT_Bool started = 0, same_width = 1; - FT_Fixed advance, old_advance = 0; + FT_Fixed advance = 0, old_advance = 0; void* shaper_buf; @@ -1398,9 +1398,9 @@ other_flags |= AF_LATIN_HINTS_VERT_SNAP; /* - * We adjust stems to full pixels only if we don't use the `light' mode. + * We adjust stems to full pixels unless in `light' or `lcd' mode. */ - if ( mode != FT_RENDER_MODE_LIGHT ) + if ( mode != FT_RENDER_MODE_LIGHT && mode != FT_RENDER_MODE_LCD ) other_flags |= AF_LATIN_HINTS_STEM_ADJUST; if ( mode == FT_RENDER_MODE_MONO ) @@ -2272,13 +2272,7 @@ goto Exit; /* analyze glyph outline */ -#ifdef AF_CONFIG_OPTION_USE_WARPER - if ( ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT && - AF_HINTS_DO_WARP( hints ) ) || - AF_HINTS_DO_HORIZONTAL( hints ) ) -#else if ( AF_HINTS_DO_HORIZONTAL( hints ) ) -#endif { error = af_cjk_hints_detect_features( hints, AF_DIMENSION_HORZ ); if ( error ) @@ -2304,9 +2298,9 @@ { #ifdef AF_CONFIG_OPTION_USE_WARPER - if ( dim == AF_DIMENSION_HORZ && - metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT && - AF_HINTS_DO_WARP( hints ) ) + if ( dim == AF_DIMENSION_HORZ && + metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL && + AF_HINTS_DO_WARP( hints ) ) { AF_WarperRec warper; FT_Fixed scale; diff --git a/modules/freetype2/src/autofit/afcjk.h b/modules/freetype2/src/autofit/afcjk.h index 40d118438..d229c0c9c 100644 --- a/modules/freetype2/src/autofit/afcjk.h +++ b/modules/freetype2/src/autofit/afcjk.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter hinting routines for CJK writing system (specification). */ /* */ -/* Copyright 2006-2016 by */ +/* Copyright 2006-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/autofit/afcover.h b/modules/freetype2/src/autofit/afcover.h index 1c39a707e..6eeb8fc9f 100644 --- a/modules/freetype2/src/autofit/afcover.h +++ b/modules/freetype2/src/autofit/afcover.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter coverages (specification only). */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/autofit/afdummy.c b/modules/freetype2/src/autofit/afdummy.c index ff47dcb0c..f30c517cb 100644 --- a/modules/freetype2/src/autofit/afdummy.c +++ b/modules/freetype2/src/autofit/afdummy.c @@ -5,7 +5,7 @@ /* Auto-fitter dummy routines to be used if no hinting should be */ /* performed (body). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/autofit/afdummy.h b/modules/freetype2/src/autofit/afdummy.h index 7e58d1a9a..b382acd92 100644 --- a/modules/freetype2/src/autofit/afdummy.h +++ b/modules/freetype2/src/autofit/afdummy.h @@ -5,7 +5,7 @@ /* Auto-fitter dummy routines to be used if no hinting should be */ /* performed (specification). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/autofit/aferrors.h b/modules/freetype2/src/autofit/aferrors.h index 53c01f64d..e5de54360 100644 --- a/modules/freetype2/src/autofit/aferrors.h +++ b/modules/freetype2/src/autofit/aferrors.h @@ -4,7 +4,7 @@ /* */ /* Autofitter error codes (specification only). */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/autofit/afglobal.c b/modules/freetype2/src/autofit/afglobal.c index 11ed0dff9..3d09c53e8 100644 --- a/modules/freetype2/src/autofit/afglobal.c +++ b/modules/freetype2/src/autofit/afglobal.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter routines to compute global hinting values (body). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -411,10 +411,7 @@ #ifdef FT_CONFIG_OPTION_USE_HARFBUZZ hb_font_destroy( globals->hb_font ); - globals->hb_font = NULL; - hb_buffer_destroy( globals->hb_buf ); - globals->hb_buf = NULL; #endif /* no need to free `globals->glyph_styles'; */ diff --git a/modules/freetype2/src/autofit/afglobal.h b/modules/freetype2/src/autofit/afglobal.h index ce6b9e8f2..489ed46d9 100644 --- a/modules/freetype2/src/autofit/afglobal.h +++ b/modules/freetype2/src/autofit/afglobal.h @@ -5,7 +5,7 @@ /* Auto-fitter routines to compute global hinting values */ /* (specification). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/autofit/afhints.c b/modules/freetype2/src/autofit/afhints.c index 8ad3e1c97..0666dbc8e 100644 --- a/modules/freetype2/src/autofit/afhints.c +++ b/modules/freetype2/src/autofit/afhints.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter hinting routines (body). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -314,8 +314,12 @@ AF_DUMP(( "Table of points:\n" )); if ( hints->num_points ) + { AF_DUMP(( " index hedge hseg vedge vseg flags " + /* " XXXXX XXXXX XXXXX XXXXX XXXXX XXXXXX" */ " xorg yorg xscale yscale xfit yfit" )); + /* " XXXXX XXXXX XXXX.XX XXXX.XX XXXX.XX XXXX.XX" */ + } else AF_DUMP(( " (none)\n" )); @@ -420,9 +424,14 @@ dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" )); if ( axis->num_segments ) + { AF_DUMP(( " index pos delta dir from to " + /* " XXXXX XXXXX XXXXX XXXXX XXXX XXXX" */ " link serif edge" + /* " XXXX XXXXX XXXX" */ " height extra flags\n" )); + /* " XXXXXX XXXXX XXXXXXXXXXX" */ + } else AF_DUMP(( " (none)\n" )); @@ -507,15 +516,15 @@ return FT_THROW( Invalid_Argument ); seg = &axis->segments[idx]; - *offset = ( dim == AF_DIMENSION_HORZ ) ? seg->first->ox - : seg->first->oy; + *offset = ( dim == AF_DIMENSION_HORZ ) ? seg->first->fx + : seg->first->fy; 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; + *blue_offset = seg->edge->blue_edge->org; else *blue_offset = 0; @@ -564,8 +573,12 @@ 10.0 * hints->y_scale / 65536.0 / 64.0 )); if ( axis->num_edges ) + { AF_DUMP(( " index pos dir link serif" + /* " XXXXX XXXX.XX XXXXX XXXX XXXXX" */ " blue opos pos flags\n" )); + /* " X XXXX.XX XXXX.XX XXXXXXXXXXX" */ + } else AF_DUMP(( " (none)\n" )); diff --git a/modules/freetype2/src/autofit/afhints.h b/modules/freetype2/src/autofit/afhints.h index 4fdf732d4..3326ebc44 100644 --- a/modules/freetype2/src/autofit/afhints.h +++ b/modules/freetype2/src/autofit/afhints.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter hinting routines (specification). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -62,7 +62,7 @@ FT_BEGIN_HEADER * * by David Turner and Werner Lemberg * - * http://www.tug.org/TUGboat/Articles/tb24-3/lemberg.pdf + * https://www.tug.org/TUGboat/Articles/tb24-3/lemberg.pdf * * with appropriate updates. * diff --git a/modules/freetype2/src/autofit/afindic.c b/modules/freetype2/src/autofit/afindic.c index cfaf7196d..dfbea5f34 100644 --- a/modules/freetype2/src/autofit/afindic.c +++ b/modules/freetype2/src/autofit/afindic.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter hinting routines for Indic writing system (body). */ /* */ -/* Copyright 2007-2016 by */ +/* Copyright 2007-2018 by */ /* Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -18,13 +18,13 @@ #include "aftypes.h" #include "aflatin.h" +#include "afcjk.h" #ifdef AF_CONFIG_OPTION_INDIC #include "afindic.h" #include "aferrors.h" -#include "afcjk.h" #ifdef AF_CONFIG_OPTION_USE_WARPER diff --git a/modules/freetype2/src/autofit/afindic.h b/modules/freetype2/src/autofit/afindic.h index 0772e07a2..5688738e6 100644 --- a/modules/freetype2/src/autofit/afindic.h +++ b/modules/freetype2/src/autofit/afindic.h @@ -5,7 +5,7 @@ /* Auto-fitter hinting routines for Indic writing system */ /* (specification). */ /* */ -/* Copyright 2007-2016 by */ +/* Copyright 2007-2018 by */ /* Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/autofit/aflatin.c b/modules/freetype2/src/autofit/aflatin.c index f4d29e7b8..9f1b54056 100644 --- a/modules/freetype2/src/autofit/aflatin.c +++ b/modules/freetype2/src/autofit/aflatin.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter hinting routines for latin writing system (body). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -265,6 +265,45 @@ } + static void + af_latin_sort_blue( FT_UInt count, + AF_LatinBlue* table ) + { + FT_UInt i, j; + AF_LatinBlue swap; + + + /* we sort from bottom to top */ + for ( i = 1; i < count; i++ ) + { + for ( j = i; j > 0; j-- ) + { + FT_Pos a, b; + + + if ( table[j - 1]->flags & ( AF_LATIN_BLUE_TOP | + AF_LATIN_BLUE_SUB_TOP ) ) + a = table[j - 1]->ref.org; + else + a = table[j - 1]->shoot.org; + + if ( table[j]->flags & ( AF_LATIN_BLUE_TOP | + AF_LATIN_BLUE_SUB_TOP ) ) + b = table[j]->ref.org; + else + b = table[j]->shoot.org; + + if ( b >= a ) + break; + + swap = table[j]; + table[j] = table[j - 1]; + table[j - 1] = swap; + } + } + } + + /* Find all blue zones. Flat segments give the reference points, */ /* round segments the overshoot positions. */ @@ -928,6 +967,60 @@ af_shaper_buf_destroy( face, shaper_buf ); + /* we finally check whether blue zones are ordered; */ + /* `ref' and `shoot' values of two blue zones must not overlap */ + if ( axis->blue_count ) + { + FT_UInt i; + AF_LatinBlue blue_sorted[AF_BLUE_STRINGSET_MAX_LEN + 2]; + + + for ( i = 0; i < axis->blue_count; i++ ) + blue_sorted[i] = &axis->blues[i]; + + /* sort bottoms of blue zones... */ + af_latin_sort_blue( axis->blue_count, blue_sorted ); + + /* ...and adjust top values if necessary */ + for ( i = 0; i < axis->blue_count - 1; i++ ) + { + FT_Pos* a; + FT_Pos* b; + +#ifdef FT_DEBUG_LEVEL_TRACE + FT_Bool a_is_top = 0; +#endif + + + if ( blue_sorted[i]->flags & ( AF_LATIN_BLUE_TOP | + AF_LATIN_BLUE_SUB_TOP ) ) + { + a = &blue_sorted[i]->shoot.org; +#ifdef FT_DEBUG_LEVEL_TRACE + a_is_top = 1; +#endif + } + else + a = &blue_sorted[i]->ref.org; + + if ( blue_sorted[i + 1]->flags & ( AF_LATIN_BLUE_TOP | + AF_LATIN_BLUE_SUB_TOP ) ) + b = &blue_sorted[i + 1]->shoot.org; + else + b = &blue_sorted[i + 1]->ref.org; + + if ( *a > *b ) + { + *a = *b; + FT_TRACE5(( "blue zone overlap:" + " adjusting %s %d to %ld\n", + a_is_top ? "overshoot" : "reference", + blue_sorted[i] - axis->blues, + *a )); + } + } + } + FT_TRACE5(( "\n" )); return; @@ -941,7 +1034,7 @@ FT_Face face ) { FT_Bool started = 0, same_width = 1; - FT_Fixed advance, old_advance = 0; + FT_Fixed advance = 0, old_advance = 0; void* shaper_buf; @@ -1597,9 +1690,11 @@ if ( prev_max_on_coord > max_on_coord ) max_on_coord = prev_max_on_coord; - prev_segment->last = point; - prev_segment->pos = (FT_Short)( ( min_pos + - max_pos ) >> 1 ); + prev_segment->last = point; + prev_segment->pos = (FT_Short)( ( min_pos + + max_pos ) >> 1 ); + prev_segment->delta = (FT_Short)( ( max_pos - + min_pos ) >> 1 ); if ( ( min_flags | max_flags ) & AF_FLAG_CONTROL && ( max_on_coord - min_on_coord ) < flat_threshold ) @@ -1627,9 +1722,11 @@ if ( max_pos > prev_max_pos ) prev_max_pos = max_pos; - prev_segment->last = point; - prev_segment->pos = (FT_Short)( ( prev_min_pos + - prev_max_pos ) >> 1 ); + prev_segment->last = point; + prev_segment->pos = (FT_Short)( ( prev_min_pos + + prev_max_pos ) >> 1 ); + prev_segment->delta = (FT_Short)( ( prev_max_pos - + prev_min_pos ) >> 1 ); } else { @@ -1640,8 +1737,9 @@ if ( prev_max_pos > max_pos ) max_pos = prev_max_pos; - segment->last = point; - segment->pos = (FT_Short)( ( min_pos + max_pos ) >> 1 ); + segment->last = point; + segment->pos = (FT_Short)( ( min_pos + max_pos ) >> 1 ); + segment->delta = (FT_Short)( ( max_pos - min_pos ) >> 1 ); if ( ( min_flags | max_flags ) & AF_FLAG_CONTROL && ( max_on_coord - min_on_coord ) < flat_threshold ) @@ -1951,6 +2049,10 @@ FT_Memory memory = hints->memory; AF_LatinAxis laxis = &((AF_LatinMetrics)hints->metrics)->axis[dim]; +#ifdef FT_CONFIG_OPTION_PIC + AF_FaceGlobals globals = hints->metrics->globals; +#endif + AF_StyleClass style_class = hints->metrics->style_class; AF_ScriptClass script_class = AF_SCRIPT_CLASSES_GET [style_class->script]; @@ -2478,23 +2580,23 @@ other_flags |= AF_LATIN_HINTS_VERT_SNAP; /* - * We adjust stems to full pixels only if we don't use the `light' mode. + * We adjust stems to full pixels unless in `light' or `lcd' mode. */ - if ( mode != FT_RENDER_MODE_LIGHT ) + if ( mode != FT_RENDER_MODE_LIGHT && mode != FT_RENDER_MODE_LCD ) other_flags |= AF_LATIN_HINTS_STEM_ADJUST; if ( mode == FT_RENDER_MODE_MONO ) other_flags |= AF_LATIN_HINTS_MONO; /* - * In `light' hinting mode we disable horizontal hinting completely. + * In `light' or `lcd' mode we disable horizontal hinting completely. * We also do it if the face is italic. * * However, if warping is enabled (which only works in `light' hinting * mode), advance widths get adjusted, too. */ - if ( mode == FT_RENDER_MODE_LIGHT || - ( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0 ) + if ( mode == FT_RENDER_MODE_LIGHT || mode == FT_RENDER_MODE_LCD || + ( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0 ) scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL; #ifdef AF_CONFIG_OPTION_USE_WARPER @@ -2834,6 +2936,10 @@ AF_Edge anchor = NULL; FT_Int has_serifs = 0; +#ifdef FT_CONFIG_OPTION_PIC + AF_FaceGlobals globals = hints->metrics->globals; +#endif + AF_StyleClass style_class = hints->metrics->style_class; AF_ScriptClass script_class = AF_SCRIPT_CLASSES_GET [style_class->script]; @@ -3391,13 +3497,7 @@ goto Exit; /* analyze glyph outline */ -#ifdef AF_CONFIG_OPTION_USE_WARPER - if ( ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT && - AF_HINTS_DO_WARP( hints ) ) || - AF_HINTS_DO_HORIZONTAL( hints ) ) -#else if ( AF_HINTS_DO_HORIZONTAL( hints ) ) -#endif { axis = &metrics->axis[AF_DIMENSION_HORZ]; error = af_latin_hints_detect_features( hints, @@ -3427,9 +3527,9 @@ for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ ) { #ifdef AF_CONFIG_OPTION_USE_WARPER - if ( dim == AF_DIMENSION_HORZ && - metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT && - AF_HINTS_DO_WARP( hints ) ) + if ( dim == AF_DIMENSION_HORZ && + metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL && + AF_HINTS_DO_WARP( hints ) ) { AF_WarperRec warper; FT_Fixed scale; diff --git a/modules/freetype2/src/autofit/aflatin.h b/modules/freetype2/src/autofit/aflatin.h index fe6bbd801..432cccce4 100644 --- a/modules/freetype2/src/autofit/aflatin.h +++ b/modules/freetype2/src/autofit/aflatin.h @@ -5,7 +5,7 @@ /* Auto-fitter hinting routines for latin writing system */ /* (specification). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/autofit/aflatin2.c b/modules/freetype2/src/autofit/aflatin2.c index e1cc1f56d..5c7137811 100644 --- a/modules/freetype2/src/autofit/aflatin2.c +++ b/modules/freetype2/src/autofit/aflatin2.c @@ -9,7 +9,7 @@ /* */ /* Auto-fitter hinting routines for latin writing system (body). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -23,6 +23,9 @@ #include FT_ADVANCES_H + +#ifdef FT_OPTION_AUTOFIT2 + #include "afglobal.h" #include "aflatin.h" #include "aflatin2.h" @@ -1555,20 +1558,20 @@ other_flags |= AF_LATIN_HINTS_VERT_SNAP; /* - * We adjust stems to full pixels only if we don't use the `light' mode. + * We adjust stems to full pixels unless in `light' or `lcd' mode. */ - if ( mode != FT_RENDER_MODE_LIGHT ) + if ( mode != FT_RENDER_MODE_LIGHT && mode != FT_RENDER_MODE_LCD ) other_flags |= AF_LATIN_HINTS_STEM_ADJUST; if ( mode == FT_RENDER_MODE_MONO ) other_flags |= AF_LATIN_HINTS_MONO; /* - * In `light' hinting mode we disable horizontal hinting completely. + * In `light' or `lcd' mode we disable horizontal hinting completely. * We also do it if the face is italic. */ - if ( mode == FT_RENDER_MODE_LIGHT || - ( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0 ) + if ( mode == FT_RENDER_MODE_LIGHT || mode == FT_RENDER_MODE_LCD || + ( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0 ) scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL; #ifdef AF_CONFIG_OPTION_USE_WARPER @@ -2337,13 +2340,7 @@ goto Exit; /* analyze glyph outline */ -#ifdef AF_CONFIG_OPTION_USE_WARPER - if ( ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT && - AF_HINTS_DO_WARP( hints ) ) || - AF_HINTS_DO_HORIZONTAL( hints ) ) -#else if ( AF_HINTS_DO_HORIZONTAL( hints ) ) -#endif { error = af_latin2_hints_detect_features( hints, AF_DIMENSION_HORZ ); if ( error ) @@ -2363,9 +2360,9 @@ for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ ) { #ifdef AF_CONFIG_OPTION_USE_WARPER - if ( dim == AF_DIMENSION_HORZ && - metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT && - AF_HINTS_DO_WARP( hints ) ) + if ( dim == AF_DIMENSION_HORZ && + metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL && + AF_HINTS_DO_WARP( hints ) ) { AF_WarperRec warper; FT_Fixed scale; @@ -2419,5 +2416,12 @@ (AF_WritingSystem_ApplyHintsFunc) af_latin2_hints_apply /* style_hints_apply */ ) +#else /* !FT_OPTION_AUTOFIT2 */ + + /* ANSI C doesn't like empty source files */ + typedef int _af_latin2_dummy; + +#endif /* !FT_OPTION_AUTOFIT2 */ + /* END */ diff --git a/modules/freetype2/src/autofit/aflatin2.h b/modules/freetype2/src/autofit/aflatin2.h index f83f70428..0129dc707 100644 --- a/modules/freetype2/src/autofit/aflatin2.h +++ b/modules/freetype2/src/autofit/aflatin2.h @@ -10,7 +10,7 @@ /* Auto-fitter hinting routines for latin writing system */ /* (specification). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/autofit/afloader.c b/modules/freetype2/src/autofit/afloader.c index 7f75fc349..a55550b33 100644 --- a/modules/freetype2/src/autofit/afloader.c +++ b/modules/freetype2/src/autofit/afloader.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter glyph loading routines (body). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -97,11 +97,13 @@ AF_FaceGlobals globals = loader->globals; AF_WritingSystemClass writing_system_class; + FT_Size_Metrics* size_metrics = &face->size->internal->autohint_metrics; + FT_Pos stdVW = 0; FT_Pos stdHW = 0; - FT_Bool size_changed = face->size->metrics.x_ppem - != globals->stem_darkening_for_ppem; + FT_Bool size_changed = size_metrics->x_ppem != + globals->stem_darkening_for_ppem; FT_Fixed em_size = af_intToFixed( face->units_per_EM ); FT_Fixed em_ratio = FT_DivFix( af_intToFixed( 1000 ), em_size ); @@ -112,7 +114,7 @@ /* Skip stem darkening for broken fonts. */ if ( !face->units_per_EM ) { - error = FT_Err_Corrupted_Font_Header; + error = FT_ERR( Corrupted_Font_Header ); goto Exit; } @@ -130,7 +132,7 @@ &stdVW ); else { - error = FT_Err_Unimplemented_Feature; + error = FT_ERR( Unimplemented_Feature ); goto Exit; } @@ -145,11 +147,11 @@ face, stdVW ) ); darken_x = FT_DivFix( FT_MulFix( darken_by_font_units_x, - face->size->metrics.x_scale ), + size_metrics->x_scale ), em_ratio ); globals->standard_vertical_width = stdVW; - globals->stem_darkening_for_ppem = face->size->metrics.x_ppem; + globals->stem_darkening_for_ppem = size_metrics->x_ppem; globals->darken_x = af_fixedToInt( darken_x ); } @@ -164,11 +166,11 @@ face, stdHW ) ); darken_y = FT_DivFix( FT_MulFix( darken_by_font_units_y, - face->size->metrics.y_scale ), + size_metrics->y_scale ), em_ratio ); globals->standard_horizontal_width = stdHW; - globals->stem_darkening_for_ppem = face->size->metrics.x_ppem; + globals->stem_darkening_for_ppem = size_metrics->x_ppem; globals->darken_y = af_fixedToInt( darken_y ); /* @@ -217,15 +219,16 @@ { FT_Error error; - FT_Size size = face->size; - FT_GlyphSlot slot = face->glyph; - FT_Slot_Internal internal = slot->internal; - FT_GlyphLoader gloader = internal->loader; + FT_Size size = face->size; + FT_Size_Internal size_internal = size->internal; + FT_GlyphSlot slot = face->glyph; + FT_Slot_Internal slot_internal = slot->internal; + FT_GlyphLoader gloader = slot_internal->loader; - AF_GlyphHints hints = loader->hints; + AF_GlyphHints hints = loader->hints; AF_ScalerRec scaler; AF_StyleMetrics style_metrics; - FT_UInt style_options = AF_STYLE_NONE_DFLT; + FT_UInt style_options = AF_STYLE_NONE_DFLT; AF_StyleClass style_class; AF_WritingSystemClass writing_system_class; @@ -239,24 +242,65 @@ FT_ZERO( &scaler ); + if ( !size_internal->autohint_metrics.x_scale || + size_internal->autohint_mode != FT_LOAD_TARGET_MODE( load_flags ) ) + { + /* switching between hinting modes usually means different scaling */ + /* values; this later on enforces recomputation of everything */ + /* related to the current size */ + + size_internal->autohint_mode = FT_LOAD_TARGET_MODE( load_flags ); + size_internal->autohint_metrics = size->metrics; + +#ifdef AF_CONFIG_OPTION_TT_SIZE_METRICS + { + FT_Size_Metrics* size_metrics = &size_internal->autohint_metrics; + + + /* set metrics to integer values and adjust scaling accordingly; */ + /* this is the same setup as with TrueType fonts, cf. function */ + /* `tt_size_reset' in file `ttobjs.c' */ + size_metrics->ascender = FT_PIX_ROUND( + FT_MulFix( face->ascender, + size_metrics->y_scale ) ); + size_metrics->descender = FT_PIX_ROUND( + FT_MulFix( face->descender, + size_metrics->y_scale ) ); + size_metrics->height = FT_PIX_ROUND( + FT_MulFix( face->height, + size_metrics->y_scale ) ); + + size_metrics->x_scale = FT_DivFix( size_metrics->x_ppem << 6, + face->units_per_EM ); + size_metrics->y_scale = FT_DivFix( size_metrics->y_ppem << 6, + face->units_per_EM ); + size_metrics->max_advance = FT_PIX_ROUND( + FT_MulFix( face->max_advance_width, + size_metrics->x_scale ) ); + } +#endif /* AF_CONFIG_OPTION_TT_SIZE_METRICS */ + } + /* * TODO: This code currently doesn't support fractional advance widths, - * i.e. placing hinted glyphs at anything other than integer + * i.e., placing hinted glyphs at anything other than integer * x-positions. This is only relevant for the warper code, which * scales and shifts glyphs to optimize blackness of stems (hinting on * the x-axis by nature places things on pixel integers, hinting on the - * y-axis only, i.e. LIGHT mode, doesn't touch the x-axis). The delta + * y-axis only, i.e., LIGHT mode, doesn't touch the x-axis). The delta * values of the scaler would need to be adjusted. */ scaler.face = face; - scaler.x_scale = size->metrics.x_scale; + scaler.x_scale = size_internal->autohint_metrics.x_scale; scaler.x_delta = 0; - scaler.y_scale = size->metrics.y_scale; + scaler.y_scale = size_internal->autohint_metrics.y_scale; scaler.y_delta = 0; scaler.render_mode = FT_LOAD_TARGET_MODE( load_flags ); scaler.flags = 0; + /* note that the fallback style can't be changed anymore */ + /* after the first call of `af_loader_load_glyph' */ error = af_loader_reset( loader, module, face ); if ( error ) goto Exit; @@ -334,18 +378,24 @@ * `standard_{vertical,horizontal}_width' change. * * Ignore errors and carry on without emboldening. + * */ - if ( !module->no_stem_darkening ) + + /* stem darkening only works well in `light' mode */ + if ( scaler.render_mode == FT_RENDER_MODE_LIGHT && + ( !face->internal->no_stem_darkening || + ( face->internal->no_stem_darkening < 0 && + !module->no_stem_darkening ) ) ) af_loader_embolden_glyph_in_slot( loader, face, style_metrics ); - loader->transformed = internal->glyph_transformed; + loader->transformed = slot_internal->glyph_transformed; if ( loader->transformed ) { FT_Matrix inverse; - loader->trans_matrix = internal->glyph_matrix; - loader->trans_delta = internal->glyph_delta; + loader->trans_matrix = slot_internal->glyph_matrix; + loader->trans_delta = slot_internal->glyph_delta; inverse = loader->trans_matrix; if ( !FT_Matrix_Invert( &inverse ) ) @@ -375,18 +425,11 @@ /* now load the slot image into the auto-outline */ /* and run the automatic hinting process */ - { -#ifdef FT_CONFIG_OPTION_PIC - AF_FaceGlobals globals = loader->globals; -#endif - - - if ( writing_system_class->style_hints_apply ) - writing_system_class->style_hints_apply( glyph_index, - hints, - &gloader->base.outline, - style_metrics ); - } + if ( writing_system_class->style_hints_apply ) + writing_system_class->style_hints_apply( glyph_index, + hints, + &gloader->base.outline, + style_metrics ); /* we now need to adjust the metrics according to the change in */ /* width/positioning that occurred during the hinting process */ @@ -408,6 +451,8 @@ old_lsb = edge1->opos /* - loader->pp1.x */; new_lsb = edge1->pos; + /* remember unhinted values to later account */ + /* for rounding errors */ pp1x_uh = new_lsb - old_lsb; pp2x_uh = edge2->pos + old_rsb; @@ -438,21 +483,23 @@ FT_Pos pp2x = loader->pp2.x; - loader->pp1.x = FT_PIX_ROUND( pp1x ); - loader->pp2.x = FT_PIX_ROUND( pp2x ); + loader->pp1.x = FT_PIX_ROUND( pp1x + hints->xmin_delta ); + loader->pp2.x = FT_PIX_ROUND( pp2x + hints->xmax_delta ); slot->lsb_delta = loader->pp1.x - pp1x; slot->rsb_delta = loader->pp2.x - pp2x; } } + /* `light' mode uses integer advance widths */ + /* but sets `lsb_delta' and `rsb_delta' */ else { FT_Pos pp1x = loader->pp1.x; FT_Pos pp2x = loader->pp2.x; - loader->pp1.x = FT_PIX_ROUND( pp1x + hints->xmin_delta ); - loader->pp2.x = FT_PIX_ROUND( pp2x + hints->xmax_delta ); + loader->pp1.x = FT_PIX_ROUND( pp1x ); + loader->pp2.x = FT_PIX_ROUND( pp2x ); slot->lsb_delta = loader->pp1.x - pp1x; slot->rsb_delta = loader->pp2.x - pp2x; diff --git a/modules/freetype2/src/autofit/afloader.h b/modules/freetype2/src/autofit/afloader.h index 0062eb9b0..d4d72d158 100644 --- a/modules/freetype2/src/autofit/afloader.h +++ b/modules/freetype2/src/autofit/afloader.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter glyph loading routines (specification). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/autofit/afmodule.c b/modules/freetype2/src/autofit/afmodule.c index f325ebf45..dcaa17a27 100644 --- a/modules/freetype2/src/autofit/afmodule.c +++ b/modules/freetype2/src/autofit/afmodule.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter module implementation (body). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -56,7 +56,7 @@ #include FT_INTERNAL_OBJECTS_H #include FT_INTERNAL_DEBUG_H -#include FT_AUTOHINTER_H +#include FT_DRIVER_H #include FT_SERVICE_PROPERTIES_H @@ -104,6 +104,19 @@ } +#ifdef FT_CONFIG_OPTION_PIC + +#undef AF_SCRIPT_CLASSES_GET +#define AF_SCRIPT_CLASSES_GET \ + ( GET_PIC( ft_module->library )->af_script_classes ) + +#undef AF_STYLE_CLASSES_GET +#define AF_STYLE_CLASSES_GET \ + ( GET_PIC( ft_module->library )->af_style_classes ) + +#endif + + static FT_Error af_property_set( FT_Module ft_module, const char* property_name, @@ -291,12 +304,10 @@ long nsd = ft_strtol( s, NULL, 10 ); - if ( nsd == 0 ) - module->no_stem_darkening = 0; - else if ( nsd == 1 ) - module->no_stem_darkening = 1; + if ( !nsd ) + module->no_stem_darkening = FALSE; else - return FT_THROW( Invalid_Argument ); + module->no_stem_darkening = TRUE; } else #endif diff --git a/modules/freetype2/src/autofit/afmodule.h b/modules/freetype2/src/autofit/afmodule.h index e65db5f5c..56f64eaf2 100644 --- a/modules/freetype2/src/autofit/afmodule.h +++ b/modules/freetype2/src/autofit/afmodule.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter module implementation (specification). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/autofit/afpic.c b/modules/freetype2/src/autofit/afpic.c index 3cbd9168e..d48d016a0 100644 --- a/modules/freetype2/src/autofit/afpic.c +++ b/modules/freetype2/src/autofit/afpic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for autofit module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2018 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/autofit/afpic.h b/modules/freetype2/src/autofit/afpic.h index 98a45a26b..0c7345678 100644 --- a/modules/freetype2/src/autofit/afpic.h +++ b/modules/freetype2/src/autofit/afpic.h @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for autofit module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2018 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -69,7 +69,7 @@ FT_BEGIN_HEADER #define GET_PIC( lib ) \ - ( (AFModulePIC*)((lib)->pic_container.autofit) ) + ( (AFModulePIC*)( (lib)->pic_container.autofit ) ) #define AF_SERVICES_GET \ ( GET_PIC( library )->af_services ) diff --git a/modules/freetype2/src/autofit/afranges.c b/modules/freetype2/src/autofit/afranges.c index 732f3d162..cf67fafb1 100644 --- a/modules/freetype2/src/autofit/afranges.c +++ b/modules/freetype2/src/autofit/afranges.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter Unicode script ranges (body). */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -52,8 +52,21 @@ /* not be affected by blue zones, regardless of whether this is a */ /* spacing or no-spacing glyph */ - /* the `ta_xxxx_nonbase_uniranges' ranges must be strict subsets */ - /* of the corresponding `ta_xxxx_uniranges' ranges */ + /* the `af_xxxx_nonbase_uniranges' ranges must be strict subsets */ + /* of the corresponding `af_xxxx_uniranges' ranges */ + + + const AF_Script_UniRangeRec af_adlm_uniranges[] = + { + AF_UNIRANGE_REC( 0x1E900, 0x1E95F ), /* Adlam */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_adlm_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0x1D944, 0x1E94A ), + AF_UNIRANGE_REC( 0, 0 ) + }; const AF_Script_UniRangeRec af_arab_uniranges[] = @@ -78,7 +91,7 @@ AF_UNIRANGE_REC( 0x06E7, 0x06E8 ), AF_UNIRANGE_REC( 0x06EA, 0x06ED ), AF_UNIRANGE_REC( 0x08D4, 0x08E1 ), - AF_UNIRANGE_REC( 0x08E3, 0x08FF ), + AF_UNIRANGE_REC( 0x08D3, 0x08FF ), AF_UNIRANGE_REC( 0xFBB2, 0xFBC1 ), AF_UNIRANGE_REC( 0xFE70, 0xFE70 ), AF_UNIRANGE_REC( 0xFE72, 0xFE72 ), @@ -106,6 +119,37 @@ }; + const AF_Script_UniRangeRec af_avst_uniranges[] = + { + AF_UNIRANGE_REC( 0x10B00, 0x10B3F ), /* Avestan */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_avst_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0x10B39, 0x10B3F ), + AF_UNIRANGE_REC( 0, 0 ) + }; + + + const AF_Script_UniRangeRec af_bamu_uniranges[] = + { + AF_UNIRANGE_REC( 0xA6A0, 0xA6FF ), /* Bamum */ +#if 0 + /* The characters in the Bamum supplement are pictograms, */ + /* not (directly) related to the syllabic Bamum script */ + AF_UNIRANGE_REC( 0x16800, 0x16A3F ), /* Bamum Supplement */ +#endif + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_bamu_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0xA6F0, 0xA6F1 ), + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_beng_uniranges[] = { AF_UNIRANGE_REC( 0x0980, 0x09FF ), /* Bengali */ @@ -119,10 +163,64 @@ AF_UNIRANGE_REC( 0x09C1, 0x09C4 ), AF_UNIRANGE_REC( 0x09CD, 0x09CD ), AF_UNIRANGE_REC( 0x09E2, 0x09E3 ), + AF_UNIRANGE_REC( 0x09FE, 0x09FE ), + AF_UNIRANGE_REC( 0, 0 ) + }; + + + const AF_Script_UniRangeRec af_buhd_uniranges[] = + { + AF_UNIRANGE_REC( 0x1740, 0x175F ), /* Buhid */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_buhd_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0x1752, 0x1753 ), + AF_UNIRANGE_REC( 0, 0 ) + }; + + + const AF_Script_UniRangeRec af_cakm_uniranges[] = + { + AF_UNIRANGE_REC( 0x11100, 0x1114F ), /* Chakma */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_cakm_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0x11100, 0x11102 ), + AF_UNIRANGE_REC( 0x11127, 0x11134 ), + AF_UNIRANGE_REC( 0x11146, 0x11146 ), AF_UNIRANGE_REC( 0, 0 ) }; + const AF_Script_UniRangeRec af_cans_uniranges[] = + { + AF_UNIRANGE_REC( 0x1400, 0x167F ), /* Unified Canadian Aboriginal Syllabics */ + AF_UNIRANGE_REC( 0x18B0, 0x18FF ), /* Unified Canadian Aboriginal Syllabics Extended */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_cans_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0, 0 ) + }; + + + const AF_Script_UniRangeRec af_cari_uniranges[] = + { + AF_UNIRANGE_REC( 0x102A0, 0x102DF ), /* Carian */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_cari_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_cher_uniranges[] = { AF_UNIRANGE_REC( 0x13A0, 0x13FF ), /* Cherokee */ @@ -136,6 +234,31 @@ }; + const AF_Script_UniRangeRec af_copt_uniranges[] = + { + AF_UNIRANGE_REC( 0x2C80, 0x2CFF ), /* Coptic */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_copt_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0x2CEF, 0x2CF1 ), + AF_UNIRANGE_REC( 0, 0 ) + }; + + + const AF_Script_UniRangeRec af_cprt_uniranges[] = + { + AF_UNIRANGE_REC( 0x10800, 0x1083F ), /* Cypriot */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_cprt_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_cyrl_uniranges[] = { AF_UNIRANGE_REC( 0x0400, 0x04FF ), /* Cyrillic */ @@ -183,10 +306,23 @@ AF_UNIRANGE_REC( 0x0953, 0x0957 ), AF_UNIRANGE_REC( 0x0962, 0x0963 ), AF_UNIRANGE_REC( 0xA8E0, 0xA8F1 ), + AF_UNIRANGE_REC( 0xA8FF, 0xA8FF ), AF_UNIRANGE_REC( 0, 0 ) }; + const AF_Script_UniRangeRec af_dsrt_uniranges[] = + { + AF_UNIRANGE_REC( 0x10400, 0x1044F ), /* Deseret */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_dsrt_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_ethi_uniranges[] = { AF_UNIRANGE_REC( 0x1200, 0x137F ), /* Ethiopic */ @@ -205,11 +341,8 @@ const AF_Script_UniRangeRec af_geor_uniranges[] = { - AF_UNIRANGE_REC( 0x10D0, 0x10FF ), /* Georgian (Mkhedruli) */ -#if 0 - /* the following range is proposed for inclusion in Unicode */ - AF_UNIRANGE_REC( 0x1C90, 0x1CBF ), /* Georgian (Mtavruli) */ -#endif + AF_UNIRANGE_REC( 0x10D0, 0x10FF ), /* Georgian (Mkhedruli) */ + AF_UNIRANGE_REC( 0x1C90, 0x1CBF ), /* Georgian Extended (Mtavruli) */ AF_UNIRANGE_REC( 0, 0 ) }; @@ -222,8 +355,8 @@ const AF_Script_UniRangeRec af_geok_uniranges[] = { /* Khutsuri */ - AF_UNIRANGE_REC( 0x10A0, 0x10CD ), /* Georgian (Asomtavruli) */ - AF_UNIRANGE_REC( 0x2D00, 0x2D2D ), /* Georgian (Nuskhuri) */ + AF_UNIRANGE_REC( 0x10A0, 0x10CD ), /* Georgian (Asomtavruli) */ + AF_UNIRANGE_REC( 0x2D00, 0x2D2D ), /* Georgian Supplement (Nuskhuri) */ AF_UNIRANGE_REC( 0, 0 ) }; @@ -233,6 +366,32 @@ }; + const AF_Script_UniRangeRec af_glag_uniranges[] = + { + AF_UNIRANGE_REC( 0x2C00, 0x2C5F ), /* Glagolitic */ + AF_UNIRANGE_REC( 0x1E000, 0x1E02F ), /* Glagolitic Supplement */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_glag_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0x1E000, 0x1E02F ), + AF_UNIRANGE_REC( 0, 0 ) + }; + + + const AF_Script_UniRangeRec af_goth_uniranges[] = + { + AF_UNIRANGE_REC( 0x10330, 0x1034F ), /* Gothic */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_goth_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_grek_uniranges[] = { AF_UNIRANGE_REC( 0x0370, 0x03FF ), /* Greek and Coptic */ @@ -266,6 +425,7 @@ AF_UNIRANGE_REC( 0x0AC1, 0x0AC8 ), AF_UNIRANGE_REC( 0x0ACD, 0x0ACD ), AF_UNIRANGE_REC( 0x0AE2, 0x0AE3 ), + AF_UNIRANGE_REC( 0x0AFA, 0x0AFF ), AF_UNIRANGE_REC( 0, 0 ) }; @@ -305,6 +465,19 @@ }; + const AF_Script_UniRangeRec af_kali_uniranges[] = + { + AF_UNIRANGE_REC( 0xA900, 0xA92F ), /* Kayah Li */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_kali_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0xA926, 0xA92D ), + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_knda_uniranges[] = { AF_UNIRANGE_REC( 0x0C80, 0x0CFF ), /* Kannada */ @@ -463,6 +636,18 @@ }; + const AF_Script_UniRangeRec af_lisu_uniranges[] = + { + AF_UNIRANGE_REC( 0xA4D0, 0xA4FF ), /* Lisu */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_lisu_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_mlym_uniranges[] = { AF_UNIRANGE_REC( 0x0D00, 0x0D7F ), /* Malayalam */ @@ -471,7 +656,8 @@ const AF_Script_UniRangeRec af_mlym_nonbase_uniranges[] = { - AF_UNIRANGE_REC( 0x0D01, 0x0D01 ), + AF_UNIRANGE_REC( 0x0D00, 0x0D01 ), + AF_UNIRANGE_REC( 0x0D3B, 0x0D3C ), AF_UNIRANGE_REC( 0x0D4D, 0x0D4E ), AF_UNIRANGE_REC( 0x0D62, 0x0D63 ), AF_UNIRANGE_REC( 0, 0 ) @@ -480,27 +666,41 @@ const AF_Script_UniRangeRec af_mymr_uniranges[] = { - AF_UNIRANGE_REC( 0x1000, 0x109F ), /* Myanmar */ - AF_UNIRANGE_REC( 0xA9E0, 0xA9FF ), /* Myanmar Extended-B */ - AF_UNIRANGE_REC( 0xAA60, 0xAA7F ), /* Myanmar Extended-A */ - AF_UNIRANGE_REC( 0, 0 ) + AF_UNIRANGE_REC( 0x1000, 0x109F ), /* Myanmar */ + AF_UNIRANGE_REC( 0xA9E0, 0xA9FF ), /* Myanmar Extended-B */ + AF_UNIRANGE_REC( 0xAA60, 0xAA7F ), /* Myanmar Extended-A */ + AF_UNIRANGE_REC( 0, 0 ) }; const AF_Script_UniRangeRec af_mymr_nonbase_uniranges[] = { - AF_UNIRANGE_REC( 0x102D, 0x1030 ), - AF_UNIRANGE_REC( 0x1032, 0x1037 ), - AF_UNIRANGE_REC( 0x103A, 0x103A ), - AF_UNIRANGE_REC( 0x103D, 0x103E ), - AF_UNIRANGE_REC( 0x1058, 0x1059 ), - AF_UNIRANGE_REC( 0x105E, 0x1060 ), - AF_UNIRANGE_REC( 0x1071, 0x1074 ), - AF_UNIRANGE_REC( 0x1082, 0x1082 ), - AF_UNIRANGE_REC( 0x1085, 0x1086 ), - AF_UNIRANGE_REC( 0x108D, 0x108D ), - AF_UNIRANGE_REC( 0xA9E5, 0xA9E5 ), - AF_UNIRANGE_REC( 0xAA7C, 0xAA7C ), - AF_UNIRANGE_REC( 0, 0 ) + AF_UNIRANGE_REC( 0x102D, 0x1030 ), + AF_UNIRANGE_REC( 0x1032, 0x1037 ), + AF_UNIRANGE_REC( 0x103A, 0x103A ), + AF_UNIRANGE_REC( 0x103D, 0x103E ), + AF_UNIRANGE_REC( 0x1058, 0x1059 ), + AF_UNIRANGE_REC( 0x105E, 0x1060 ), + AF_UNIRANGE_REC( 0x1071, 0x1074 ), + AF_UNIRANGE_REC( 0x1082, 0x1082 ), + AF_UNIRANGE_REC( 0x1085, 0x1086 ), + AF_UNIRANGE_REC( 0x108D, 0x108D ), + AF_UNIRANGE_REC( 0xA9E5, 0xA9E5 ), + AF_UNIRANGE_REC( 0xAA7C, 0xAA7C ), + AF_UNIRANGE_REC( 0, 0 ) + }; + + + const AF_Script_UniRangeRec af_nkoo_uniranges[] = + { + AF_UNIRANGE_REC( 0x07C0, 0x07FF ), /* N'Ko */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_nkoo_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0x07EB, 0x07F5 ), + AF_UNIRANGE_REC( 0x07FD, 0x07FD ), + AF_UNIRANGE_REC( 0, 0 ) }; @@ -515,6 +715,80 @@ }; + const AF_Script_UniRangeRec af_olck_uniranges[] = + { + AF_UNIRANGE_REC( 0x1C50, 0x1C7F ), /* Ol Chiki */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_olck_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0, 0 ) + }; + + + const AF_Script_UniRangeRec af_orkh_uniranges[] = + { + AF_UNIRANGE_REC( 0x10C00, 0x10C4F ), /* Old Turkic */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_orkh_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0, 0 ) + }; + + + const AF_Script_UniRangeRec af_osge_uniranges[] = + { + AF_UNIRANGE_REC( 0x104B0, 0x104FF ), /* Osage */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_osge_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0, 0 ) + }; + + + const AF_Script_UniRangeRec af_osma_uniranges[] = + { + AF_UNIRANGE_REC( 0x10480, 0x104AF ), /* Osmanya */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_osma_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0, 0 ) + }; + + + const AF_Script_UniRangeRec af_saur_uniranges[] = + { + AF_UNIRANGE_REC( 0xA880, 0xA8DF ), /* Saurashtra */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_saur_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0xA880, 0xA881 ), + AF_UNIRANGE_REC( 0xA8B4, 0xA8C5 ), + AF_UNIRANGE_REC( 0, 0 ) + }; + + + const AF_Script_UniRangeRec af_shaw_uniranges[] = + { + AF_UNIRANGE_REC( 0x10450, 0x1047F ), /* Shavian */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_shaw_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_sinh_uniranges[] = { AF_UNIRANGE_REC( 0x0D80, 0x0DFF ), /* Sinhala */ @@ -529,6 +803,21 @@ }; + const AF_Script_UniRangeRec af_sund_uniranges[] = + { + AF_UNIRANGE_REC( 0x1B80, 0x1BBF ), /* Sundanese */ + AF_UNIRANGE_REC( 0x1CC0, 0x1CCF ), /* Sundanese Supplement */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_sund_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0x1B80, 0x1B82 ), + AF_UNIRANGE_REC( 0x1BA1, 0x1BAD ), + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_taml_uniranges[] = { AF_UNIRANGE_REC( 0x0B80, 0x0BFF ), /* Tamil */ @@ -544,6 +833,23 @@ }; + const AF_Script_UniRangeRec af_tavt_uniranges[] = + { + AF_UNIRANGE_REC( 0xAA80, 0xAADF ), /* Tai Viet */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_tavt_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0xAAB0, 0xAAB0 ), + AF_UNIRANGE_REC( 0xAAB2, 0xAAB4 ), + AF_UNIRANGE_REC( 0xAAB7, 0xAAB8 ), + AF_UNIRANGE_REC( 0xAABE, 0xAABF ), + AF_UNIRANGE_REC( 0xAAC1, 0xAAC1 ), + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_telu_uniranges[] = { AF_UNIRANGE_REC( 0x0C00, 0x0C7F ), /* Telugu */ @@ -553,6 +859,7 @@ const AF_Script_UniRangeRec af_telu_nonbase_uniranges[] = { AF_UNIRANGE_REC( 0x0C00, 0x0C00 ), + AF_UNIRANGE_REC( 0x0C04, 0x0C04 ), AF_UNIRANGE_REC( 0x0C3E, 0x0C40 ), AF_UNIRANGE_REC( 0x0C46, 0x0C56 ), AF_UNIRANGE_REC( 0x0C62, 0x0C63 ), @@ -575,6 +882,30 @@ }; + const AF_Script_UniRangeRec af_tfng_uniranges[] = + { + AF_UNIRANGE_REC( 0x2D30, 0x2D7F ), /* Tifinagh */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_tfng_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0, 0 ) + }; + + + const AF_Script_UniRangeRec af_vaii_uniranges[] = + { + AF_UNIRANGE_REC( 0xA500, 0xA63F ), /* Vai */ + AF_UNIRANGE_REC( 0, 0 ) + }; + + const AF_Script_UniRangeRec af_vaii_nonbase_uniranges[] = + { + AF_UNIRANGE_REC( 0, 0 ) + }; + + #ifdef AF_CONFIG_OPTION_INDIC const AF_Script_UniRangeRec af_limb_uniranges[] = @@ -610,21 +941,6 @@ }; - const AF_Script_UniRangeRec af_sund_uniranges[] = - { - AF_UNIRANGE_REC( 0x1B80, 0x1BBF ), /* Sundanese */ - AF_UNIRANGE_REC( 0x1CC0, 0x1CCF ), /* Sundanese Supplement */ - AF_UNIRANGE_REC( 0, 0 ) - }; - - const AF_Script_UniRangeRec af_sund_nonbase_uniranges[] = - { - AF_UNIRANGE_REC( 0x1B80, 0x1B82 ), - AF_UNIRANGE_REC( 0x1BA1, 0x1BAD ), - AF_UNIRANGE_REC( 0, 0 ) - }; - - const AF_Script_UniRangeRec af_sylo_uniranges[] = { AF_UNIRANGE_REC( 0xA800, 0xA82F ), /* Syloti Nagri */ @@ -694,10 +1010,13 @@ AF_UNIRANGE_REC( 0xFE30, 0xFE4F ), /* CJK Compatibility Forms */ AF_UNIRANGE_REC( 0xFF00, 0xFFEF ), /* Halfwidth and Fullwidth Forms */ AF_UNIRANGE_REC( 0x1B000, 0x1B0FF ), /* Kana Supplement */ + AF_UNIRANGE_REC( 0x1B100, 0x1B12F ), /* Kana Extended-A */ AF_UNIRANGE_REC( 0x1D300, 0x1D35F ), /* Tai Xuan Hing Symbols */ AF_UNIRANGE_REC( 0x20000, 0x2A6DF ), /* CJK Unified Ideographs Extension B */ AF_UNIRANGE_REC( 0x2A700, 0x2B73F ), /* CJK Unified Ideographs Extension C */ AF_UNIRANGE_REC( 0x2B740, 0x2B81F ), /* CJK Unified Ideographs Extension D */ + AF_UNIRANGE_REC( 0x2B820, 0x2CEAF ), /* CJK Unified Ideographs Extension E */ + AF_UNIRANGE_REC( 0x2CEB0, 0x2EBEF ), /* CJK Unified Ideographs Extension F */ AF_UNIRANGE_REC( 0x2F800, 0x2FA1F ), /* CJK Compatibility Ideographs Supplement */ AF_UNIRANGE_REC( 0, 0 ) }; diff --git a/modules/freetype2/src/autofit/afranges.h b/modules/freetype2/src/autofit/afranges.h index 1a0e4b153..ba3b5e7cc 100644 --- a/modules/freetype2/src/autofit/afranges.h +++ b/modules/freetype2/src/autofit/afranges.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter Unicode script ranges (specification). */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/autofit/afscript.h b/modules/freetype2/src/autofit/afscript.h index cffe59105..623a1734a 100644 --- a/modules/freetype2/src/autofit/afscript.h +++ b/modules/freetype2/src/autofit/afscript.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter scripts (specification only). */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -30,6 +30,12 @@ /* use `HB_SCRIPT_INVALID' as the HarfBuzz script name tag for */ /* them. */ + SCRIPT( adlm, ADLM, + "Adlam", + HB_SCRIPT_ADLAM, + HINTING_BOTTOM_TO_TOP, + "\xF0\x9E\xA4\x8C \xF0\x9E\xA4\xAE" ) /* 𞤌 𞤮 */ + SCRIPT( arab, ARAB, "Arabic", HB_SCRIPT_ARABIC, @@ -42,6 +48,18 @@ HINTING_BOTTOM_TO_TOP, "\xD5\xBD \xD5\x8D" ) /* ս Ս */ + SCRIPT( avst, AVST, + "Avestan", + HB_SCRIPT_AVESTAN, + HINTING_BOTTOM_TO_TOP, + "\xF0\x90\xAC\x9A" ) /* 𐬚 */ + + SCRIPT( bamu, BAMU, + "Bamum", + HB_SCRIPT_BAMUM, + HINTING_BOTTOM_TO_TOP, + "\xEA\x9B\x81 \xEA\x9B\xAF" ) /* ꛁ ꛯ */ + /* there are no simple forms for letters; we thus use two digit shapes */ SCRIPT( beng, BENG, "Bengali", @@ -49,12 +67,48 @@ HINTING_TOP_TO_BOTTOM, "\xE0\xA7\xA6 \xE0\xA7\xAA" ) /* ০ ৪ */ + SCRIPT( buhd, BUHD, + "Buhid", + HB_SCRIPT_BUHID, + HINTING_BOTTOM_TO_TOP, + "\xE1\x9D\x8B \xE1\x9D\x8F" ) /* ᝋ ᝏ */ + + SCRIPT( cakm, CAKM, + "Chakma", + HB_SCRIPT_CHAKMA, + HINTING_BOTTOM_TO_TOP, + "\xF0\x91\x84\xA4 \xF0\x91\x84\x89 \xF0\x91\x84\x9B" ) /* 𑄤 𑄉 𑄛 */ + + SCRIPT( cans, CANS, + "Canadian Syllabics", + HB_SCRIPT_CANADIAN_SYLLABICS, + HINTING_BOTTOM_TO_TOP, + "\xE1\x91\x8C \xE1\x93\x9A" ) /* ᑌ ᓚ */ + + SCRIPT( cari, CARI, + "Carian", + HB_SCRIPT_CARIAN, + HINTING_BOTTOM_TO_TOP, + "\xF0\x90\x8A\xAB \xF0\x90\x8B\x89" ) /* 𐊫 𐋉 */ + SCRIPT( cher, CHER, "Cherokee", HB_SCRIPT_CHEROKEE, HINTING_BOTTOM_TO_TOP, "\xE1\x8E\xA4 \xE1\x8F\x85 \xEA\xAE\x95" ) /* Ꭴ Ꮕ ꮕ */ + SCRIPT( copt, COPT, + "Coptic", + HB_SCRIPT_COPTIC, + HINTING_BOTTOM_TO_TOP, + "\xE2\xB2\x9E \xE2\xB2\x9F" ) /* Ⲟ ⲟ */ + + SCRIPT( cprt, CPRT, + "Cypriot", + HB_SCRIPT_CYPRIOT, + HINTING_BOTTOM_TO_TOP, + "\xF0\x90\xA0\x85 \xF0\x90\xA0\xA3" ) /* 𐠅 𐠣 */ + SCRIPT( cyrl, CYRL, "Cyrillic", HB_SCRIPT_CYRILLIC, @@ -67,6 +121,12 @@ HINTING_TOP_TO_BOTTOM, "\xE0\xA4\xA0 \xE0\xA4\xB5 \xE0\xA4\x9F" ) /* ठ व ट */ + SCRIPT( dsrt, DSRT, + "Deseret", + HB_SCRIPT_DESERET, + HINTING_BOTTOM_TO_TOP, + "\xF0\x90\x90\x84 \xF0\x90\x90\xAC" ) /* 𐐄 𐐬 */ + SCRIPT( ethi, ETHI, "Ethiopic", HB_SCRIPT_ETHIOPIC, @@ -77,7 +137,7 @@ "Georgian (Mkhedruli)", HB_SCRIPT_GEORGIAN, HINTING_BOTTOM_TO_TOP, - "\xE1\x83\x98 \xE1\x83\x94 \xE1\x83\x90" ) /* ი ე ა */ + "\xE1\x83\x98 \xE1\x83\x94 \xE1\x83\x90 \xE1\xB2\xBF" ) /* ი ე ა Ი */ SCRIPT( geok, GEOK, "Georgian (Khutsuri)", @@ -85,6 +145,18 @@ HINTING_BOTTOM_TO_TOP, "\xE1\x82\xB6 \xE1\x82\xB1 \xE2\xB4\x99" ) /* Ⴖ Ⴑ ⴙ */ + SCRIPT( glag, GLAG, + "Glagolitic", + HB_SCRIPT_GLAGOLITIC, + HINTING_BOTTOM_TO_TOP, + "\xE2\xB0\x95 \xE2\xB1\x85" ) /* Ⱅ ⱅ */ + + SCRIPT( goth, GOTH, + "Gothic", + HB_SCRIPT_GOTHIC, + HINTING_TOP_TO_BOTTOM, + "\xF0\x90\x8C\xB4 \xF0\x90\x8C\xBE \xF0\x90\x8D\x83" ) /* 𐌴 𐌾 𐍃 */ + SCRIPT( grek, GREK, "Greek", HB_SCRIPT_GREEK, @@ -109,11 +181,11 @@ HINTING_BOTTOM_TO_TOP, "\xD7\x9D" ) /* ם */ - SCRIPT( knda, KNDA, - "Kannada", - HB_SCRIPT_KANNADA, + SCRIPT( kali, KALI, + "Kayah Li", + HB_SCRIPT_KAYAH_LI, HINTING_BOTTOM_TO_TOP, - "\xE0\xB3\xA6 \xE0\xB2\xAC" ) /* ೦ ಬ */ + "\xEA\xA4\x8D \xEA\xA4\x80" ) /* ꤍ ꤀ */ /* only digit zero has a simple shape in the Khmer script */ SCRIPT( khmr, KHMR, @@ -128,6 +200,12 @@ HINTING_BOTTOM_TO_TOP, "\xE1\xA7\xA1 \xE1\xA7\xAA" ) /* ᧡ ᧪ */ + SCRIPT( knda, KNDA, + "Kannada", + HB_SCRIPT_KANNADA, + HINTING_BOTTOM_TO_TOP, + "\xE0\xB3\xA6 \xE0\xB2\xAC" ) /* ೦ ಬ */ + /* only digit zero has a simple shape in the Lao script */ SCRIPT( lao, LAO, "Lao", @@ -153,6 +231,12 @@ HINTING_BOTTOM_TO_TOP, "\xE1\xB5\x92 \xE1\xB4\xBC \xE2\x81\xB0" ) /* ᵒ ᴼ ⁰ */ + SCRIPT( lisu, LISU, + "Lisu", + HB_SCRIPT_LISU, + HINTING_BOTTOM_TO_TOP, + "\xEA\x93\xB3" ) /* ꓳ */ + SCRIPT( mlym, MLYM, "Malayalam", HB_SCRIPT_MALAYALAM, @@ -165,18 +249,67 @@ HINTING_BOTTOM_TO_TOP, "\xE1\x80\x9D \xE1\x80\x84 \xE1\x80\x82" ) /* ဝ င ဂ */ + SCRIPT( nkoo, NKOO, + "N'Ko", + HB_SCRIPT_NKO, + HINTING_BOTTOM_TO_TOP, + "\xDF\x8B \xDF\x80" ) /* ߋ ߀ */ + SCRIPT( none, NONE, "no script", HB_SCRIPT_INVALID, HINTING_BOTTOM_TO_TOP, "" ) + SCRIPT( olck, OLCK, + "Ol Chiki", + HB_SCRIPT_OL_CHIKI, + HINTING_BOTTOM_TO_TOP, + "\xE1\xB1\x9B" ) /* ᱛ */ + + SCRIPT( orkh, ORKH, + "Old Turkic", + HB_SCRIPT_OLD_TURKIC, + HINTING_BOTTOM_TO_TOP, + "\xF0\x90\xB0\x97" ) /* 𐰗 */ + + SCRIPT( osge, OSGE, + "Osage", + HB_SCRIPT_OSAGE, + HINTING_BOTTOM_TO_TOP, + "\xF0\x90\x93\x82 \xF0\x90\x93\xAA" ) /* 𐓂 𐓪 */ + + SCRIPT( osma, OSMA, + "Osmanya", + HB_SCRIPT_OSMANYA, + HINTING_BOTTOM_TO_TOP, + "\xF0\x90\x92\x86 \xF0\x90\x92\xA0" ) /* 𐒆 𐒠 */ + + SCRIPT( saur, SAUR, + "Saurashtra", + HB_SCRIPT_SAURASHTRA, + HINTING_BOTTOM_TO_TOP, + "\xEA\xA2\x9D \xEA\xA3\x90" ) /* ꢝ ꣐ */ + + SCRIPT( shaw, SHAW, + "Shavian", + HB_SCRIPT_SHAVIAN, + HINTING_BOTTOM_TO_TOP, + "\xF0\x90\x91\xB4" ) /* 𐑴 */ + SCRIPT( sinh, SINH, "Sinhala", HB_SCRIPT_SINHALA, HINTING_BOTTOM_TO_TOP, "\xE0\xB6\xA7" ) /* ට */ + /* only digit zero has a simple (round) shape in the Sundanese script */ + SCRIPT( sund, SUND, + "Sundanese", + HB_SCRIPT_SUNDANESE, + HINTING_BOTTOM_TO_TOP, + "\xE1\xAE\xB0" ) /* ᮰ */ + /* only digit zero has a simple (round) shape in the Tamil script */ SCRIPT( taml, TAML, "Tamil", @@ -184,6 +317,12 @@ HINTING_BOTTOM_TO_TOP, "\xE0\xAF\xA6" ) /* ௦ */ + SCRIPT( tavt, TAVT, + "Tai Viet", + HB_SCRIPT_TAI_VIET, + HINTING_BOTTOM_TO_TOP, + "\xEA\xAA\x92 \xEA\xAA\xAB" ) /* ꪒ ꪫ */ + /* there are no simple forms for letters; we thus use two digit shapes */ SCRIPT( telu, TELU, "Telugu", @@ -191,12 +330,24 @@ HINTING_BOTTOM_TO_TOP, "\xE0\xB1\xA6 \xE0\xB1\xA7" ) /* ౦ ౧ */ + SCRIPT( tfng, TFNG, + "Tifinagh", + HB_SCRIPT_TIFINAGH, + HINTING_BOTTOM_TO_TOP, + "\xE2\xB5\x94" ) /* ⵔ */ + SCRIPT( thai, THAI, "Thai", HB_SCRIPT_THAI, HINTING_BOTTOM_TO_TOP, "\xE0\xB8\xB2 \xE0\xB9\x85 \xE0\xB9\x90" ) /* า ๅ ๐ */ + SCRIPT( vaii, VAII, + "Vai", + HB_SCRIPT_VAI, + HINTING_BOTTOM_TO_TOP, + "\xEA\x98\x93 \xEA\x96\x9C \xEA\x96\xB4" ) /* ꘓ ꖜ ꖴ */ + #ifdef AF_CONFIG_OPTION_INDIC SCRIPT( limb, LIMB, @@ -211,12 +362,6 @@ HINTING_BOTTOM_TO_TOP, "o" ) /* XXX */ - SCRIPT( sund, SUND, - "Sundanese", - HB_SCRIPT_SUNDANESE, - HINTING_BOTTOM_TO_TOP, - "o" ) /* XXX */ - SCRIPT( sylo, SYLO, "Syloti Nagri", HB_SCRIPT_SYLOTI_NAGRI, diff --git a/modules/freetype2/src/autofit/afshaper.c b/modules/freetype2/src/autofit/afshaper.c index 6d13b6585..f30828173 100644 --- a/modules/freetype2/src/autofit/afshaper.c +++ b/modules/freetype2/src/autofit/afshaper.c @@ -4,7 +4,7 @@ /* */ /* HarfBuzz interface for accessing OpenType features (body). */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -18,6 +18,7 @@ #include <ft2build.h> #include FT_FREETYPE_H +#include FT_ADVANCES_H #include "afglobal.h" #include "aftypes.h" #include "afshaper.h" @@ -103,10 +104,10 @@ { 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_set_t* gsub_lookups = NULL; /* GSUB lookups for a given script */ + hb_set_t* gsub_glyphs = NULL; /* glyphs covered by GSUB lookups */ + hb_set_t* gpos_lookups = NULL; /* GPOS lookups for a given script */ + hb_set_t* gpos_glyphs = NULL; /* glyphs covered by GPOS lookups */ hb_script_t script; const hb_tag_t* coverage_tags; @@ -126,11 +127,6 @@ 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]; @@ -167,6 +163,7 @@ script_tags[1] = HB_TAG_NONE; } + gsub_lookups = hb_set_create(); hb_ot_layout_collect_lookups( face, HB_OT_TAG_GSUB, script_tags, @@ -177,13 +174,6 @@ 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] )); @@ -192,6 +182,7 @@ count = 0; #endif + gsub_glyphs = hb_set_create(); for ( idx = HB_SET_VALUE_INVALID; hb_set_next( gsub_lookups, &idx ); ) { #ifdef FT_DEBUG_LEVEL_TRACE @@ -219,10 +210,19 @@ " ", af_style_names[style_class->style] )); + gpos_lookups = hb_set_create(); + hb_ot_layout_collect_lookups( face, + HB_OT_TAG_GPOS, + script_tags, + NULL, + coverage_tags, + gpos_lookups ); + #ifdef FT_DEBUG_LEVEL_TRACE count = 0; #endif + gpos_glyphs = hb_set_create(); for ( idx = HB_SET_VALUE_INVALID; hb_set_next( gpos_lookups, &idx ); ) { #ifdef FT_DEBUG_LEVEL_TRACE diff --git a/modules/freetype2/src/autofit/afshaper.h b/modules/freetype2/src/autofit/afshaper.h index 0d41f7876..7efd9f6a4 100644 --- a/modules/freetype2/src/autofit/afshaper.h +++ b/modules/freetype2/src/autofit/afshaper.h @@ -4,7 +4,7 @@ /* */ /* HarfBuzz interface for accessing OpenType features (specification). */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/autofit/afstyles.h b/modules/freetype2/src/autofit/afstyles.h index e83a95bb5..e2688b3fc 100644 --- a/modules/freetype2/src/autofit/afstyles.h +++ b/modules/freetype2/src/autofit/afstyles.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter styles (specification only). */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -83,6 +83,13 @@ DEFAULT ) + STYLE( adlm_dflt, ADLM_DFLT, + "Adlam default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_ADLM, + AF_BLUE_STRINGSET_ADLM, + AF_COVERAGE_DEFAULT ) + STYLE( arab_dflt, ARAB_DFLT, "Arabic default style", AF_WRITING_SYSTEM_LATIN, @@ -97,6 +104,20 @@ AF_BLUE_STRINGSET_ARMN, AF_COVERAGE_DEFAULT ) + STYLE( avst_dflt, AVST_DFLT, + "Avestan default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_AVST, + AF_BLUE_STRINGSET_AVST, + AF_COVERAGE_DEFAULT ) + + STYLE( bamu_dflt, BAMU_DFLT, + "Bamum default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_BAMU, + AF_BLUE_STRINGSET_BAMU, + AF_COVERAGE_DEFAULT ) + STYLE( beng_dflt, BENG_DFLT, "Bengali default style", AF_WRITING_SYSTEM_LATIN, @@ -104,6 +125,34 @@ AF_BLUE_STRINGSET_BENG, AF_COVERAGE_DEFAULT ) + STYLE( buhd_dflt, BUHD_DFLT, + "Buhid default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_BUHD, + AF_BLUE_STRINGSET_BUHD, + AF_COVERAGE_DEFAULT ) + + STYLE( cakm_dflt, CAKM_DFLT, + "Chakma default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_CAKM, + AF_BLUE_STRINGSET_CAKM, + AF_COVERAGE_DEFAULT ) + + STYLE( cans_dflt, CANS_DFLT, + "Canadian Syllabics default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_CANS, + AF_BLUE_STRINGSET_CANS, + AF_COVERAGE_DEFAULT ) + + STYLE( cari_dflt, CARI_DFLT, + "Carian default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_CARI, + AF_BLUE_STRINGSET_CARI, + AF_COVERAGE_DEFAULT ) + STYLE( cher_dflt, CHER_DFLT, "Cherokee default style", AF_WRITING_SYSTEM_LATIN, @@ -111,6 +160,20 @@ AF_BLUE_STRINGSET_CHER, AF_COVERAGE_DEFAULT ) + STYLE( copt_dflt, COPT_DFLT, + "Coptic default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_COPT, + AF_BLUE_STRINGSET_COPT, + AF_COVERAGE_DEFAULT ) + + STYLE( cprt_dflt, CPRT_DFLT, + "Cypriot default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_CPRT, + AF_BLUE_STRINGSET_CPRT, + AF_COVERAGE_DEFAULT ) + META_STYLE_LATIN( cyrl, CYRL, "Cyrillic" ) STYLE( deva_dflt, DEVA_DFLT, @@ -120,6 +183,13 @@ AF_BLUE_STRINGSET_DEVA, AF_COVERAGE_DEFAULT ) + STYLE( dsrt_dflt, DSRT_DFLT, + "Deseret default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_DSRT, + AF_BLUE_STRINGSET_DSRT, + AF_COVERAGE_DEFAULT ) + STYLE( ethi_dflt, ETHI_DFLT, "Ethiopic default style", AF_WRITING_SYSTEM_LATIN, @@ -141,6 +211,20 @@ AF_BLUE_STRINGSET_GEOK, AF_COVERAGE_DEFAULT ) + STYLE( glag_dflt, GLAG_DFLT, + "Glagolitic default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_GLAG, + AF_BLUE_STRINGSET_GLAG, + AF_COVERAGE_DEFAULT ) + + STYLE( goth_dflt, GOTH_DFLT, + "Gothic default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_GOTH, + AF_BLUE_STRINGSET_GOTH, + AF_COVERAGE_DEFAULT ) + META_STYLE_LATIN( grek, GREK, "Greek" ) STYLE( gujr_dflt, GUJR_DFLT, @@ -164,11 +248,11 @@ AF_BLUE_STRINGSET_HEBR, AF_COVERAGE_DEFAULT ) - STYLE( knda_dflt, KNDA_DFLT, - "Kannada default style", + STYLE( kali_dflt, KALI_DFLT, + "Kayah Li default style", AF_WRITING_SYSTEM_LATIN, - AF_SCRIPT_KNDA, - AF_BLUE_STRINGSET_KNDA, + AF_SCRIPT_KALI, + AF_BLUE_STRINGSET_KALI, AF_COVERAGE_DEFAULT ) STYLE( khmr_dflt, KHMR_DFLT, @@ -185,6 +269,13 @@ AF_BLUE_STRINGSET_KHMS, AF_COVERAGE_DEFAULT ) + STYLE( knda_dflt, KNDA_DFLT, + "Kannada default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_KNDA, + AF_BLUE_STRINGSET_KNDA, + AF_COVERAGE_DEFAULT ) + STYLE( lao_dflt, LAO_DFLT, "Lao default style", AF_WRITING_SYSTEM_LATIN, @@ -217,6 +308,13 @@ AF_COVERAGE_DEFAULT ) #endif + STYLE( lisu_dflt, LISU_DFLT, + "Lisu default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_LISU, + AF_BLUE_STRINGSET_LISU, + AF_COVERAGE_DEFAULT ) + STYLE( mlym_dflt, MLYM_DFLT, "Malayalam default style", AF_WRITING_SYSTEM_LATIN, @@ -231,6 +329,13 @@ AF_BLUE_STRINGSET_MYMR, AF_COVERAGE_DEFAULT ) + STYLE( nkoo_dflt, NKOO_DFLT, + "N'Ko default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_NKOO, + AF_BLUE_STRINGSET_NKOO, + AF_COVERAGE_DEFAULT ) + STYLE( none_dflt, NONE_DFLT, "no style", AF_WRITING_SYSTEM_DUMMY, @@ -238,6 +343,48 @@ AF_BLUE_STRINGSET_NONE, AF_COVERAGE_DEFAULT ) + STYLE( olck_dflt, OLCK_DFLT, + "Ol Chiki default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_OLCK, + AF_BLUE_STRINGSET_OLCK, + AF_COVERAGE_DEFAULT ) + + STYLE( orkh_dflt, ORKH_DFLT, + "Old Turkic default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_ORKH, + AF_BLUE_STRINGSET_ORKH, + AF_COVERAGE_DEFAULT ) + + STYLE( osge_dflt, OSGE_DFLT, + "Osage default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_OSGE, + AF_BLUE_STRINGSET_OSGE, + AF_COVERAGE_DEFAULT ) + + STYLE( osma_dflt, OSMA_DFLT, + "Osmanya default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_OSMA, + AF_BLUE_STRINGSET_OSMA, + AF_COVERAGE_DEFAULT ) + + STYLE( saur_dflt, SAUR_DFLT, + "Saurashtra default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_SAUR, + AF_BLUE_STRINGSET_SAUR, + AF_COVERAGE_DEFAULT ) + + STYLE( shaw_dflt, SHAW_DFLT, + "Shavian default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_SHAW, + AF_BLUE_STRINGSET_SHAW, + AF_COVERAGE_DEFAULT ) + STYLE( sinh_dflt, SINH_DFLT, "Sinhala default style", AF_WRITING_SYSTEM_LATIN, @@ -245,6 +392,13 @@ AF_BLUE_STRINGSET_SINH, AF_COVERAGE_DEFAULT ) + STYLE( sund_dflt, SUND_DFLT, + "Sundanese default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_SUND, + AF_BLUE_STRINGSET_SUND, + AF_COVERAGE_DEFAULT ) + STYLE( taml_dflt, TAML_DFLT, "Tamil default style", AF_WRITING_SYSTEM_LATIN, @@ -252,6 +406,13 @@ AF_BLUE_STRINGSET_TAML, AF_COVERAGE_DEFAULT ) + STYLE( tavt_dflt, TAVT_DFLT, + "Tai Viet default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_TAVT, + AF_BLUE_STRINGSET_TAVT, + AF_COVERAGE_DEFAULT ) + STYLE( telu_dflt, TELU_DFLT, "Telugu default style", AF_WRITING_SYSTEM_LATIN, @@ -259,6 +420,13 @@ AF_BLUE_STRINGSET_TELU, AF_COVERAGE_DEFAULT ) + STYLE( tfng_dflt, TFNG_DFLT, + "Tifinagh default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_TFNG, + AF_BLUE_STRINGSET_TFNG, + AF_COVERAGE_DEFAULT ) + STYLE( thai_dflt, THAI_DFLT, "Thai default style", AF_WRITING_SYSTEM_LATIN, @@ -266,6 +434,13 @@ AF_BLUE_STRINGSET_THAI, AF_COVERAGE_DEFAULT ) + STYLE( vaii_dflt, VAII_DFLT, + "Vai default style", + AF_WRITING_SYSTEM_LATIN, + AF_SCRIPT_VAII, + AF_BLUE_STRINGSET_VAII, + AF_COVERAGE_DEFAULT ) + #ifdef AF_CONFIG_OPTION_INDIC /* no blue stringset support for the Indic writing system yet */ @@ -280,7 +455,6 @@ STYLE_DEFAULT_INDIC( limb, LIMB, "Limbu" ) STYLE_DEFAULT_INDIC( orya, ORYA, "Oriya" ) - STYLE_DEFAULT_INDIC( sund, SUND, "Sundanese" ) STYLE_DEFAULT_INDIC( sylo, SYLO, "Syloti Nagri" ) STYLE_DEFAULT_INDIC( tibt, TIBT, "Tibetan" ) diff --git a/modules/freetype2/src/autofit/aftypes.h b/modules/freetype2/src/autofit/aftypes.h index 61b6b12bb..6bd8c895b 100644 --- a/modules/freetype2/src/autofit/aftypes.h +++ b/modules/freetype2/src/autofit/aftypes.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter types (specification only). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -76,9 +76,9 @@ extern void* _af_debug_hints; typedef struct AF_WidthRec_ { - FT_Pos org; /* original position/width in font units */ - FT_Pos cur; /* current/scaled position/width in device sub-pixels */ - FT_Pos fit; /* current/fitted position/width in device sub-pixels */ + FT_Pos org; /* original position/width in font units */ + FT_Pos cur; /* current/scaled position/width in device subpixels */ + FT_Pos fit; /* current/fitted position/width in device subpixels */ } AF_WidthRec, *AF_Width; @@ -575,6 +575,7 @@ extern void* _af_debug_hints; m_init, \ m_scale, \ m_done, \ + m_stdw, \ h_init, \ h_apply ) \ FT_LOCAL_DEF( void ) \ diff --git a/modules/freetype2/src/autofit/afwarp.c b/modules/freetype2/src/autofit/afwarp.c index ce1806c9d..2a75ea7b3 100644 --- a/modules/freetype2/src/autofit/afwarp.c +++ b/modules/freetype2/src/autofit/afwarp.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter warping algorithm (body). */ /* */ -/* Copyright 2006-2016 by */ +/* Copyright 2006-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -98,7 +98,6 @@ if ( xx1min + w < warper->x2min ) xx1min = warper->x2min - w; - xx1max = warper->x1max; if ( xx1max + w > warper->x2max ) xx1max = warper->x2max - w; diff --git a/modules/freetype2/src/autofit/afwarp.h b/modules/freetype2/src/autofit/afwarp.h index 6d96f86d7..520b1be90 100644 --- a/modules/freetype2/src/autofit/afwarp.h +++ b/modules/freetype2/src/autofit/afwarp.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter warping algorithm (specification). */ /* */ -/* Copyright 2006-2016 by */ +/* Copyright 2006-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/autofit/afwrtsys.h b/modules/freetype2/src/autofit/afwrtsys.h index 842f4921a..4675f3242 100644 --- a/modules/freetype2/src/autofit/afwrtsys.h +++ b/modules/freetype2/src/autofit/afwrtsys.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter writing systems (specification only). */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/autofit/autofit.c b/modules/freetype2/src/autofit/autofit.c index dda9aeb6d..c1605160a 100644 --- a/modules/freetype2/src/autofit/autofit.c +++ b/modules/freetype2/src/autofit/autofit.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter module (body). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -18,29 +18,22 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT #include <ft2build.h> -#include "afpic.c" + #include "afangles.c" #include "afblue.c" +#include "afcjk.c" +#include "afdummy.c" #include "afglobal.c" #include "afhints.c" - -#include "afranges.c" - -#include "afdummy.c" +#include "afindic.c" #include "aflatin.c" -#ifdef FT_OPTION_AUTOFIT2 #include "aflatin2.c" -#endif -#include "afcjk.c" -#include "afindic.c" - -#include "afshaper.c" - #include "afloader.c" #include "afmodule.c" - -#ifdef AF_CONFIG_OPTION_USE_WARPER +#include "afpic.c" +#include "afranges.c" +#include "afshaper.c" #include "afwarp.c" -#endif + /* END */ diff --git a/modules/freetype2/src/autofit/module.mk b/modules/freetype2/src/autofit/module.mk index 98f0612b9..ff05f83e7 100644 --- a/modules/freetype2/src/autofit/module.mk +++ b/modules/freetype2/src/autofit/module.mk @@ -3,7 +3,7 @@ # -# Copyright 2003-2016 by +# Copyright 2003-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/autofit/rules.mk b/modules/freetype2/src/autofit/rules.mk index 1ef470464..75171b412 100644 --- a/modules/freetype2/src/autofit/rules.mk +++ b/modules/freetype2/src/autofit/rules.mk @@ -3,7 +3,7 @@ # -# Copyright 2003-2016 by +# Copyright 2003-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/base/Jamfile b/modules/freetype2/src/base/Jamfile index cfc69657f..4994c1b4c 100644 --- a/modules/freetype2/src/base/Jamfile +++ b/modules/freetype2/src/base/Jamfile @@ -1,6 +1,6 @@ # FreeType 2 src/base Jamfile # -# Copyright 2001-2016 by +# Copyright 2001-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, @@ -21,11 +21,14 @@ SubDir FT2_TOP $(FT2_SRC_DIR) base ; ftadvanc ftcalc ftdbgmem + ftfntfmt ftgloadr fthash + ftlcdfil ftobjs ftoutln ftpic + ftpsprop ftrfork ftsnames ftstream @@ -50,13 +53,11 @@ SubDir FT2_TOP $(FT2_SRC_DIR) base ; ftbitmap ftcid ftdebug - ftfntfmt ftfstype ftgasp ftglyph ftgxval ftinit - ftlcdfil ftmm ftotval ftpatent diff --git a/modules/freetype2/src/base/basepic.c b/modules/freetype2/src/base/basepic.c index f2cea90d7..bc8040644 100644 --- a/modules/freetype2/src/base/basepic.c +++ b/modules/freetype2/src/base/basepic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for base. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2018 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/base/basepic.h b/modules/freetype2/src/base/basepic.h index a1a75a0ba..492d1ede5 100644 --- a/modules/freetype2/src/base/basepic.h +++ b/modules/freetype2/src/base/basepic.h @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for base. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2018 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/base/ftadvanc.c b/modules/freetype2/src/base/ftadvanc.c index 59c74502c..230c84d6a 100644 --- a/modules/freetype2/src/base/ftadvanc.c +++ b/modules/freetype2/src/base/ftadvanc.c @@ -4,7 +4,7 @@ /* */ /* Quick computation of advance widths (body). */ /* */ -/* Copyright 2008-2016 by */ +/* Copyright 2008-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -116,9 +116,12 @@ FT_Int32 flags, FT_Fixed *padvances ) { + FT_Error error = FT_Err_Ok; + FT_Face_GetAdvancesFunc func; - FT_UInt num, end, nn; - FT_Error error = FT_Err_Ok; + + FT_UInt num, end, nn; + FT_Int factor; if ( !face ) @@ -152,16 +155,17 @@ return FT_THROW( Unimplemented_Feature ); flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY; + factor = ( flags & FT_LOAD_NO_SCALE ) ? 1 : 1024; for ( nn = 0; nn < count; nn++ ) { error = FT_Load_Glyph( face, start + nn, flags ); if ( error ) break; - /* scale from 26.6 to 16.16 */ + /* scale from 26.6 to 16.16, unless NO_SCALE was requested */ padvances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT ) - ? face->glyph->advance.y * 1024 - : face->glyph->advance.x * 1024; + ? face->glyph->advance.y * factor + : face->glyph->advance.x * factor; } return error; diff --git a/modules/freetype2/src/base/ftapi.c b/modules/freetype2/src/base/ftapi.c index b94c3eb9f..32d6e95d1 100644 --- a/modules/freetype2/src/base/ftapi.c +++ b/modules/freetype2/src/base/ftapi.c @@ -4,7 +4,7 @@ /* */ /* The FreeType compatibility functions (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -38,7 +38,7 @@ /*************************************************************************/ /*************************************************************************/ - /* backwards compatibility API */ + /* backward compatibility API */ FT_BASE_DEF( void ) FT_New_Memory_Stream( FT_Library library, diff --git a/modules/freetype2/src/base/ftbase.c b/modules/freetype2/src/base/ftbase.c index ab1af6f9f..f914b9b24 100644 --- a/modules/freetype2/src/base/ftbase.c +++ b/modules/freetype2/src/base/ftbase.c @@ -4,7 +4,7 @@ /* */ /* Single object library component (body only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,26 +17,26 @@ #include <ft2build.h> - #define FT_MAKE_OPTION_SINGLE_OBJECT -#include "ftpic.c" #include "basepic.c" #include "ftadvanc.c" #include "ftcalc.c" #include "ftdbgmem.c" +#include "ftfntfmt.c" #include "ftgloadr.c" #include "fthash.c" +#include "ftlcdfil.c" +#include "ftmac.c" #include "ftobjs.c" #include "ftoutln.c" +#include "ftpic.c" +#include "ftpsprop.c" #include "ftrfork.c" #include "ftsnames.c" #include "ftstream.c" #include "fttrigon.c" #include "ftutil.c" -#ifdef FT_MACINTOSH -#include "ftmac.c" -#endif /* END */ diff --git a/modules/freetype2/src/base/ftbase.h b/modules/freetype2/src/base/ftbase.h index 717fdaae2..7e8cfad95 100644 --- a/modules/freetype2/src/base/ftbase.h +++ b/modules/freetype2/src/base/ftbase.h @@ -2,9 +2,9 @@ /* */ /* ftbase.h */ /* */ -/* The FreeType private functions used in base module (specification). */ +/* Private functions used in the `base' module (specification). */ /* */ -/* Copyright 2008-2016 by */ +/* Copyright 2008-2018 by */ /* David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -27,6 +27,8 @@ FT_BEGIN_HEADER +#ifdef FT_CONFIG_OPTION_MAC_FONTS + /* MacOS resource fork cannot exceed 16MB at least for Carbon code; */ /* see https://support.microsoft.com/en-us/kb/130437 */ #define FT_MAC_RFORK_MAX_LEN 0x00FFFFFFUL @@ -65,6 +67,8 @@ FT_BEGIN_HEADER ft_raccess_rule_by_darwin_vfs( FT_Library library, FT_UInt rule_index ); #endif +#endif /* FT_CONFIG_OPTION_MAC_FONTS */ + FT_END_HEADER diff --git a/modules/freetype2/src/base/ftbbox.c b/modules/freetype2/src/base/ftbbox.c index 804dc9058..151e85c97 100644 --- a/modules/freetype2/src/base/ftbbox.c +++ b/modules/freetype2/src/base/ftbbox.c @@ -4,7 +4,7 @@ /* */ /* FreeType bbox computation (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used */ diff --git a/modules/freetype2/src/base/ftbdf.c b/modules/freetype2/src/base/ftbdf.c index 4aafc2b98..c4ea502fb 100644 --- a/modules/freetype2/src/base/ftbdf.c +++ b/modules/freetype2/src/base/ftbdf.c @@ -4,7 +4,7 @@ /* */ /* FreeType API for accessing BDF-specific strings (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/base/ftbitmap.c b/modules/freetype2/src/base/ftbitmap.c index 533e57a70..a9746663f 100644 --- a/modules/freetype2/src/base/ftbitmap.c +++ b/modules/freetype2/src/base/ftbitmap.c @@ -4,7 +4,7 @@ /* */ /* FreeType utility functions for bitmaps (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -153,38 +153,36 @@ FT_UInt ypixels ) { FT_Error error; - int pitch; - int new_pitch; + unsigned int pitch; + unsigned int new_pitch; FT_UInt bpp; - FT_UInt i, width, height; + FT_UInt width, height; unsigned char* buffer = NULL; width = bitmap->width; height = bitmap->rows; - pitch = bitmap->pitch; - if ( pitch < 0 ) - pitch = -pitch; + pitch = (unsigned int)FT_ABS( bitmap->pitch ); switch ( bitmap->pixel_mode ) { case FT_PIXEL_MODE_MONO: bpp = 1; - new_pitch = (int)( ( width + xpixels + 7 ) >> 3 ); + new_pitch = ( width + xpixels + 7 ) >> 3; break; case FT_PIXEL_MODE_GRAY2: bpp = 2; - new_pitch = (int)( ( width + xpixels + 3 ) >> 2 ); + new_pitch = ( width + xpixels + 3 ) >> 2; break; case FT_PIXEL_MODE_GRAY4: bpp = 4; - new_pitch = (int)( ( width + xpixels + 1 ) >> 1 ); + new_pitch = ( width + xpixels + 1 ) >> 1; break; case FT_PIXEL_MODE_GRAY: case FT_PIXEL_MODE_LCD: case FT_PIXEL_MODE_LCD_V: bpp = 8; - new_pitch = (int)( width + xpixels ); + new_pitch = width + xpixels; break; default: return FT_THROW( Invalid_Glyph_Format ); @@ -194,7 +192,7 @@ if ( ypixels == 0 && new_pitch <= pitch ) { /* zero the padding */ - FT_UInt bit_width = (FT_UInt)pitch * 8; + FT_UInt bit_width = pitch * 8; FT_UInt bit_last = ( width + xpixels ) * bpp; @@ -226,7 +224,7 @@ } /* otherwise allocate new buffer */ - if ( FT_QALLOC_MULT( buffer, new_pitch, bitmap->rows + ypixels ) ) + if ( FT_QALLOC_MULT( buffer, bitmap->rows + ypixels, new_pitch ) ) return error; /* new rows get added at the top of the bitmap, */ @@ -235,31 +233,60 @@ { FT_UInt len = ( width * bpp + 7 ) >> 3; + unsigned char* in = bitmap->buffer; + unsigned char* out = buffer; + + unsigned char* limit = bitmap->buffer + pitch * bitmap->rows; + unsigned int delta = new_pitch - len; + + + FT_MEM_ZERO( out, new_pitch * ypixels ); + out += new_pitch * ypixels; - for ( i = 0; i < bitmap->rows; i++ ) - FT_MEM_COPY( buffer + (FT_UInt)new_pitch * ( ypixels + i ), - bitmap->buffer + (FT_UInt)pitch * i, - len ); + while ( in < limit ) + { + FT_MEM_COPY( out, in, len ); + in += pitch; + out += len; + + /* we use FT_QALLOC_MULT, which doesn't zero out the buffer; */ + /* consequently, we have to manually zero out the remaining bytes */ + FT_MEM_ZERO( out, delta ); + out += delta; + } } else { FT_UInt len = ( width * bpp + 7 ) >> 3; + unsigned char* in = bitmap->buffer; + unsigned char* out = buffer; + + unsigned char* limit = bitmap->buffer + pitch * bitmap->rows; + unsigned int delta = new_pitch - len; + - for ( i = 0; i < bitmap->rows; i++ ) - FT_MEM_COPY( buffer + (FT_UInt)new_pitch * i, - bitmap->buffer + (FT_UInt)pitch * i, - len ); + while ( in < limit ) + { + FT_MEM_COPY( out, in, len ); + in += pitch; + out += len; + + FT_MEM_ZERO( out, delta ); + out += delta; + } + + FT_MEM_ZERO( out, new_pitch * ypixels ); } FT_FREE( bitmap->buffer ); bitmap->buffer = buffer; - if ( bitmap->pitch < 0 ) - new_pitch = -new_pitch; - /* set pitch only, width and height are left untouched */ - bitmap->pitch = new_pitch; + if ( bitmap->pitch < 0 ) + bitmap->pitch = -(int)new_pitch; + else + bitmap->pitch = (int)new_pitch; return FT_Err_Ok; } @@ -444,7 +471,7 @@ * A gamma of 2.2 is fair to assume. And then, we need to * undo the premultiplication too. * - * http://accessibility.kde.org/hsl-adjusted.php + * https://accessibility.kde.org/hsl-adjusted.php * * We do the computation with integers only, applying a gamma of 2.0. * We guarantee 32-bit arithmetic to avoid overflow but the resulting @@ -534,8 +561,7 @@ (FT_ULong)target->rows > FT_ULONG_MAX / (FT_ULong)target_pitch ) return FT_THROW( Invalid_Argument ); - if ( target->rows * (FT_ULong)target_pitch > old_size && - FT_QREALLOC( target->buffer, + if ( FT_QREALLOC( target->buffer, old_size, target->rows * (FT_UInt)target_pitch ) ) return error; diff --git a/modules/freetype2/src/base/ftcalc.c b/modules/freetype2/src/base/ftcalc.c index 1c2392222..f4ff45f8e 100644 --- a/modules/freetype2/src/base/ftcalc.c +++ b/modules/freetype2/src/base/ftcalc.c @@ -4,7 +4,7 @@ /* */ /* Arithmetic computations (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -68,14 +68,15 @@ #define FT_COMPONENT trace_calc - /* transfer sign leaving a positive number */ -#define FT_MOVE_SIGN( x, s ) \ - FT_BEGIN_STMNT \ - if ( x < 0 ) \ - { \ - x = -x; \ - s = -s; \ - } \ + /* transfer sign, leaving a positive number; */ + /* we need an unsigned value to safely negate INT_MIN (or LONG_MIN) */ +#define FT_MOVE_SIGN( x, x_unsigned, s ) \ + FT_BEGIN_STMNT \ + if ( x < 0 ) \ + { \ + x_unsigned = 0U - (x_unsigned); \ + s = -s; \ + } \ FT_END_STMNT /* The following three functions are available regardless of whether */ @@ -86,7 +87,7 @@ FT_EXPORT_DEF( FT_Fixed ) FT_RoundFix( FT_Fixed a ) { - return ( a + 0x8000L - ( a < 0 ) ) & ~0xFFFFL; + return ( ADD_LONG( a, 0x8000L - ( a < 0 ) ) ) & ~0xFFFFL; } @@ -95,7 +96,7 @@ FT_EXPORT_DEF( FT_Fixed ) FT_CeilFix( FT_Fixed a ) { - return ( a + 0xFFFFL ) & ~0xFFFFL; + return ( ADD_LONG( a, 0xFFFFL ) ) & ~0xFFFFL; } @@ -179,20 +180,20 @@ FT_Long d_; - FT_MOVE_SIGN( a_, s ); - FT_MOVE_SIGN( b_, s ); - FT_MOVE_SIGN( c_, s ); - a = (FT_UInt64)a_; b = (FT_UInt64)b_; c = (FT_UInt64)c_; + FT_MOVE_SIGN( a_, a, s ); + FT_MOVE_SIGN( b_, b, s ); + FT_MOVE_SIGN( c_, c, s ); + d = c > 0 ? ( a * b + ( c >> 1 ) ) / c : 0x7FFFFFFFUL; d_ = (FT_Long)d; - return s < 0 ? -d_ : d_; + return s < 0 ? NEG_LONG( d_ ) : d_; } @@ -208,20 +209,20 @@ FT_Long d_; - FT_MOVE_SIGN( a_, s ); - FT_MOVE_SIGN( b_, s ); - FT_MOVE_SIGN( c_, s ); - a = (FT_UInt64)a_; b = (FT_UInt64)b_; c = (FT_UInt64)c_; + FT_MOVE_SIGN( a_, a, s ); + FT_MOVE_SIGN( b_, b, s ); + FT_MOVE_SIGN( c_, c, s ); + d = c > 0 ? a * b / c : 0x7FFFFFFFUL; d_ = (FT_Long)d; - return s < 0 ? -d_ : d_; + return s < 0 ? NEG_LONG( d_ ) : d_; } @@ -257,18 +258,18 @@ FT_Long q_; - FT_MOVE_SIGN( a_, s ); - FT_MOVE_SIGN( b_, s ); - a = (FT_UInt64)a_; b = (FT_UInt64)b_; + FT_MOVE_SIGN( a_, a, s ); + FT_MOVE_SIGN( b_, b, s ); + q = b > 0 ? ( ( a << 16 ) + ( b >> 1 ) ) / b : 0x7FFFFFFFUL; q_ = (FT_Long)q; - return s < 0 ? -q_ : q_; + return s < 0 ? NEG_LONG( q_ ) : q_; } @@ -422,14 +423,14 @@ /* XXX: this function does not allow 64-bit arguments */ - FT_MOVE_SIGN( a_, s ); - FT_MOVE_SIGN( b_, s ); - FT_MOVE_SIGN( c_, s ); - a = (FT_UInt32)a_; b = (FT_UInt32)b_; c = (FT_UInt32)c_; + FT_MOVE_SIGN( a_, a, s ); + FT_MOVE_SIGN( b_, b, s ); + FT_MOVE_SIGN( c_, c, s ); + if ( c == 0 ) a = 0x7FFFFFFFUL; @@ -455,7 +456,7 @@ a_ = (FT_Long)a; - return s < 0 ? -a_ : a_; + return s < 0 ? NEG_LONG( a_ ) : a_; } @@ -470,14 +471,14 @@ /* XXX: this function does not allow 64-bit arguments */ - FT_MOVE_SIGN( a_, s ); - FT_MOVE_SIGN( b_, s ); - FT_MOVE_SIGN( c_, s ); - a = (FT_UInt32)a_; b = (FT_UInt32)b_; c = (FT_UInt32)c_; + FT_MOVE_SIGN( a_, a, s ); + FT_MOVE_SIGN( b_, b, s ); + FT_MOVE_SIGN( c_, c, s ); + if ( c == 0 ) a = 0x7FFFFFFFUL; @@ -498,7 +499,7 @@ a_ = (FT_Long)a; - return s < 0 ? -a_ : a_; + return s < 0 ? NEG_LONG( a_ ) : a_; } @@ -575,12 +576,12 @@ /* XXX: this function does not allow 64-bit arguments */ - FT_MOVE_SIGN( a_, s ); - FT_MOVE_SIGN( b_, s ); - a = (FT_UInt32)a_; b = (FT_UInt32)b_; + FT_MOVE_SIGN( a_, a, s ); + FT_MOVE_SIGN( b_, b, s ); + if ( a + ( b >> 8 ) <= 8190UL ) a = ( a * b + 0x8000UL ) >> 16; else @@ -594,7 +595,7 @@ a_ = (FT_Long)a; - return s < 0 ? -a_ : a_; + return s < 0 ? NEG_LONG( a_ ) : a_; #endif /* 0 */ @@ -614,12 +615,12 @@ /* XXX: this function does not allow 64-bit arguments */ - FT_MOVE_SIGN( a_, s ); - FT_MOVE_SIGN( b_, s ); - a = (FT_UInt32)a_; b = (FT_UInt32)b_; + FT_MOVE_SIGN( a_, a, s ); + FT_MOVE_SIGN( b_, b, s ); + if ( b == 0 ) { /* check for division by 0 */ @@ -647,7 +648,7 @@ q_ = (FT_Long)q; - return s < 0 ? -q_ : q_; + return s < 0 ? NEG_LONG( q_ ) : q_; } @@ -666,13 +667,19 @@ if ( !a || !b ) return; - xx = FT_MulFix( a->xx, b->xx ) + FT_MulFix( a->xy, b->yx ); - xy = FT_MulFix( a->xx, b->xy ) + FT_MulFix( a->xy, b->yy ); - yx = FT_MulFix( a->yx, b->xx ) + FT_MulFix( a->yy, b->yx ); - yy = FT_MulFix( a->yx, b->xy ) + FT_MulFix( a->yy, b->yy ); - - b->xx = xx; b->xy = xy; - b->yx = yx; b->yy = yy; + xx = ADD_LONG( FT_MulFix( a->xx, b->xx ), + FT_MulFix( a->xy, b->yx ) ); + xy = ADD_LONG( FT_MulFix( a->xx, b->xy ), + FT_MulFix( a->xy, b->yy ) ); + yx = ADD_LONG( FT_MulFix( a->yx, b->xx ), + FT_MulFix( a->yy, b->yx ) ); + yy = ADD_LONG( FT_MulFix( a->yx, b->xy ), + FT_MulFix( a->yy, b->yy ) ); + + b->xx = xx; + b->xy = xy; + b->yx = yx; + b->yy = yy; } @@ -722,13 +729,19 @@ if ( !a || !b ) return; - xx = FT_MulDiv( a->xx, b->xx, val ) + FT_MulDiv( a->xy, b->yx, val ); - xy = FT_MulDiv( a->xx, b->xy, val ) + FT_MulDiv( a->xy, b->yy, val ); - yx = FT_MulDiv( a->yx, b->xx, val ) + FT_MulDiv( a->yy, b->yx, val ); - yy = FT_MulDiv( a->yx, b->xy, val ) + FT_MulDiv( a->yy, b->yy, val ); - - b->xx = xx; b->xy = xy; - b->yx = yx; b->yy = yy; + xx = ADD_LONG( FT_MulDiv( a->xx, b->xx, val ), + FT_MulDiv( a->xy, b->yx, val ) ); + xy = ADD_LONG( FT_MulDiv( a->xx, b->xy, val ), + FT_MulDiv( a->xy, b->yy, val ) ); + yx = ADD_LONG( FT_MulDiv( a->yx, b->xx, val ), + FT_MulDiv( a->yy, b->yx, val ) ); + yy = ADD_LONG( FT_MulDiv( a->yx, b->xy, val ), + FT_MulDiv( a->yy, b->yy, val ) ); + + b->xx = xx; + b->xy = xy; + b->yx = yx; + b->yy = yy; } @@ -747,11 +760,10 @@ if ( !vector || !matrix ) return; - xz = FT_MulDiv( vector->x, matrix->xx, val ) + - FT_MulDiv( vector->y, matrix->xy, val ); - - yz = FT_MulDiv( vector->x, matrix->yx, val ) + - FT_MulDiv( vector->y, matrix->yy, val ); + xz = ADD_LONG( FT_MulDiv( vector->x, matrix->xx, val ), + FT_MulDiv( vector->y, matrix->xy, val ) ); + yz = ADD_LONG( FT_MulDiv( vector->x, matrix->yx, val ), + FT_MulDiv( vector->y, matrix->yy, val ) ); vector->x = xz; vector->y = yz; @@ -770,12 +782,12 @@ FT_Int sx = 1, sy = 1, shift; - FT_MOVE_SIGN( x_, sx ); - FT_MOVE_SIGN( y_, sy ); - x = (FT_UInt32)x_; y = (FT_UInt32)y_; + FT_MOVE_SIGN( x_, x, sx ); + FT_MOVE_SIGN( y_, y, sy ); + /* trivial cases */ if ( x == 0 ) { @@ -913,11 +925,13 @@ FT_Int result; - if ( (FT_ULong)FT_ABS( in_x ) + (FT_ULong)FT_ABS( out_y ) <= 131071UL && - (FT_ULong)FT_ABS( in_y ) + (FT_ULong)FT_ABS( out_x ) <= 131071UL ) + /* we silently ignore overflow errors, since such large values */ + /* lead to even more (harmless) rendering errors later on */ + if ( ADD_LONG( FT_ABS( in_x ), FT_ABS( out_y ) ) <= 131071L && + ADD_LONG( FT_ABS( in_y ), FT_ABS( out_x ) ) <= 131071L ) { - FT_Long z1 = in_x * out_y; - FT_Long z2 = in_y * out_x; + FT_Long z1 = MUL_LONG( in_x, out_y ); + FT_Long z2 = MUL_LONG( in_y, out_x ); if ( z1 > z2 ) diff --git a/modules/freetype2/src/base/ftcid.c b/modules/freetype2/src/base/ftcid.c index 251bbd009..f5184649b 100644 --- a/modules/freetype2/src/base/ftcid.c +++ b/modules/freetype2/src/base/ftcid.c @@ -4,7 +4,7 @@ /* */ /* FreeType API for accessing CID font information. */ /* */ -/* Copyright 2007-2016 by */ +/* Copyright 2007-2018 by */ /* Derek Clegg and Michael Toftdal. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/base/ftdbgmem.c b/modules/freetype2/src/base/ftdbgmem.c index fcdceefd6..c33d8acb4 100644 --- a/modules/freetype2/src/base/ftdbgmem.c +++ b/modules/freetype2/src/base/ftdbgmem.c @@ -4,7 +4,7 @@ /* */ /* Memory debugger (body). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -826,7 +826,7 @@ FT_Int result = 0; - if ( getenv( "FT2_DEBUG_MEMORY" ) ) + if ( ft_getenv( "FT2_DEBUG_MEMORY" ) ) { table = ft_mem_table_new( memory ); if ( table ) @@ -839,7 +839,7 @@ memory->realloc = ft_mem_debug_realloc; memory->free = ft_mem_debug_free; - p = getenv( "FT2_ALLOC_TOTAL_MAX" ); + p = ft_getenv( "FT2_ALLOC_TOTAL_MAX" ); if ( p ) { FT_Long total_max = ft_strtol( p, NULL, 10 ); @@ -852,7 +852,7 @@ } } - p = getenv( "FT2_ALLOC_COUNT_MAX" ); + p = ft_getenv( "FT2_ALLOC_COUNT_MAX" ); if ( p ) { FT_Long total_count = ft_strtol( p, NULL, 10 ); @@ -865,7 +865,7 @@ } } - p = getenv( "FT2_KEEP_ALIVE" ); + p = ft_getenv( "FT2_KEEP_ALIVE" ); if ( p ) { FT_Long keep_alive = ft_strtol( p, NULL, 10 ); diff --git a/modules/freetype2/src/base/ftdebug.c b/modules/freetype2/src/base/ftdebug.c index 40925d14a..fe2630910 100644 --- a/modules/freetype2/src/base/ftdebug.c +++ b/modules/freetype2/src/base/ftdebug.c @@ -4,7 +4,7 @@ /* */ /* Debugging and logging component (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -161,7 +161,7 @@ FT_BASE_DEF( void ) ft_debug_init( void ) { - const char* ft2_debug = getenv( "FT2_DEBUG" ); + const char* ft2_debug = ft_getenv( "FT2_DEBUG" ); if ( ft2_debug ) diff --git a/modules/freetype2/src/base/ftfntfmt.c b/modules/freetype2/src/base/ftfntfmt.c index c6eb3190c..a2900ceb0 100644 --- a/modules/freetype2/src/base/ftfntfmt.c +++ b/modules/freetype2/src/base/ftfntfmt.c @@ -4,7 +4,7 @@ /* */ /* FreeType utility file for font formats (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/base/ftfstype.c b/modules/freetype2/src/base/ftfstype.c index ae56c8fc8..e6cdf6e2e 100644 --- a/modules/freetype2/src/base/ftfstype.c +++ b/modules/freetype2/src/base/ftfstype.c @@ -4,7 +4,7 @@ /* */ /* FreeType utility file to access FSType data (body). */ /* */ -/* Copyright 2008-2016 by */ +/* Copyright 2008-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/base/ftgasp.c b/modules/freetype2/src/base/ftgasp.c index e38e55b6c..4f80bba63 100644 --- a/modules/freetype2/src/base/ftgasp.c +++ b/modules/freetype2/src/base/ftgasp.c @@ -4,7 +4,7 @@ /* */ /* Access of TrueType's `gasp' table (body). */ /* */ -/* Copyright 2007-2016 by */ +/* Copyright 2007-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/base/ftgloadr.c b/modules/freetype2/src/base/ftgloadr.c index c4f0ff70f..47202496b 100644 --- a/modules/freetype2/src/base/ftgloadr.c +++ b/modules/freetype2/src/base/ftgloadr.c @@ -4,7 +4,7 @@ /* */ /* The FreeType glyph loader (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/base/ftglyph.c b/modules/freetype2/src/base/ftglyph.c index d336b1c12..6759aa25d 100644 --- a/modules/freetype2/src/base/ftglyph.c +++ b/modules/freetype2/src/base/ftglyph.c @@ -4,7 +4,7 @@ /* */ /* FreeType convenience functions to handle glyphs (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -408,12 +408,28 @@ goto Exit; /* copy advance while converting 26.6 to 16.16 format */ + if ( slot->advance.x >= 0x8000L * 64 || + slot->advance.x <= -0x8000L * 64 ) + { + FT_ERROR(( "FT_Get_Glyph: advance width too large\n" )); + error = FT_THROW( Invalid_Argument ); + goto Exit2; + } + if ( slot->advance.y >= 0x8000L * 64 || + slot->advance.y <= -0x8000L * 64 ) + { + FT_ERROR(( "FT_Get_Glyph: advance height too large\n" )); + error = FT_THROW( Invalid_Argument ); + goto Exit2; + } + glyph->advance.x = slot->advance.x * 1024; glyph->advance.y = slot->advance.y * 1024; /* now import the image from the glyph slot */ error = clazz->glyph_init( glyph, slot ); + Exit2: /* if an error occurred, destroy the glyph */ if ( error ) FT_Done_Glyph( glyph ); diff --git a/modules/freetype2/src/base/ftgxval.c b/modules/freetype2/src/base/ftgxval.c index 6667b371a..19e2d6acb 100644 --- a/modules/freetype2/src/base/ftgxval.c +++ b/modules/freetype2/src/base/ftgxval.c @@ -2,9 +2,9 @@ /* */ /* ftgxval.c */ /* */ -/* FreeType API for validating TrueTyepGX/AAT tables (body). */ +/* FreeType API for validating TrueTypeGX/AAT tables (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* Masatake YAMATO, Redhat K.K, */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/base/ftinit.c b/modules/freetype2/src/base/ftinit.c index 02ef938d5..1fa472109 100644 --- a/modules/freetype2/src/base/ftinit.c +++ b/modules/freetype2/src/base/ftinit.c @@ -4,7 +4,7 @@ /* */ /* FreeType initialization layer (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -230,31 +230,10 @@ #define MAX_LENGTH 128 - /* - * Set default properties derived from the `FREETYPE_PROPERTIES' - * environment variable. - * - * `FREETYPE_PROPERTIES' has the following syntax form (broken here into - * multiple lines for better readability) - * - * <optional whitespace> - * <module-name1> ':' - * <property-name1> '=' <property-value1> - * <whitespace> - * <module-name2> ':' - * <property-name2> '=' <property-value2> - * ... - * - * Example: - * - * FREETYPE_PROPERTIES=truetype:interpreter-version=35 \ - * cff:no-stem-darkening=1 \ - * autofitter:warping=1 - * - */ - - static void - ft_set_default_properties( FT_Library library ) + /* documentation is in ftmodapi.h */ + + FT_EXPORT_DEF( void ) + FT_Set_Default_Properties( FT_Library library ) { const char* env; const char* p; @@ -326,8 +305,8 @@ #else - static void - ft_set_default_properties( FT_Library library ) + FT_EXPORT_DEF( void ) + FT_Set_Default_Properties( FT_Library library ) { FT_UNUSED( library ); } @@ -365,7 +344,7 @@ else FT_Add_Default_Modules( *alibrary ); - ft_set_default_properties( *alibrary ); + FT_Set_Default_Properties( *alibrary ); return error; } diff --git a/modules/freetype2/src/base/ftlcdfil.c b/modules/freetype2/src/base/ftlcdfil.c index 8bcbed7aa..8d314df08 100644 --- a/modules/freetype2/src/base/ftlcdfil.c +++ b/modules/freetype2/src/base/ftlcdfil.c @@ -4,7 +4,7 @@ /* */ /* FreeType API for color filtering of subpixel bitmap glyphs (body). */ /* */ -/* Copyright 2006-2016 by */ +/* Copyright 2006-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -29,142 +29,140 @@ /* define USE_LEGACY to implement the legacy filter */ #define USE_LEGACY - /* FIR filter used by the default and light filters */ - static void - _ft_lcd_filter_fir( FT_Bitmap* bitmap, - FT_Render_Mode mode, - FT_Library library ) +#define FT_SHIFTCLAMP( x ) ( x >>= 8, (FT_Byte)( x > 255 ? 255 : x ) ) + + + /* add padding according to filter weights */ + FT_BASE_DEF (void) + ft_lcd_padding( FT_Pos* Min, + FT_Pos* Max, + FT_GlyphSlot slot ) { - FT_Byte* weights = library->lcd_weights; - FT_UInt width = (FT_UInt)bitmap->width; - FT_UInt height = (FT_UInt)bitmap->rows; + FT_Byte* lcd_weights; + FT_Bitmap_LcdFilterFunc lcd_filter_func; - /* horizontal in-place FIR filter */ - if ( mode == FT_RENDER_MODE_LCD && width >= 4 ) + /* Per-face LCD filtering takes priority if set up. */ + if ( slot->face && slot->face->internal->lcd_filter_func ) + { + lcd_weights = slot->face->internal->lcd_weights; + lcd_filter_func = slot->face->internal->lcd_filter_func; + } + else { - FT_Byte* line = bitmap->buffer; + lcd_weights = slot->library->lcd_weights; + lcd_filter_func = slot->library->lcd_filter_func; + } + if ( lcd_filter_func == ft_lcd_filter_fir ) + { + *Min -= lcd_weights[0] ? 43 : + lcd_weights[1] ? 22 : 0; + *Max += lcd_weights[4] ? 43 : + lcd_weights[3] ? 22 : 0; + } + } - /* take care of bitmap flow */ - if ( bitmap->pitch < 0 ) - line -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 ); - /* `fir' and `pix' must be at least 32 bit wide, since the sum of */ - /* the values in `weights' can exceed 0xFF */ + /* FIR filter used by the default and light filters */ + FT_BASE_DEF( void ) + ft_lcd_filter_fir( FT_Bitmap* bitmap, + FT_Render_Mode mode, + FT_LcdFiveTapFilter weights ) + { + FT_UInt width = (FT_UInt)bitmap->width; + FT_UInt height = (FT_UInt)bitmap->rows; + FT_Int pitch = bitmap->pitch; + FT_Byte* origin = bitmap->buffer; - for ( ; height > 0; height--, line += bitmap->pitch ) - { - FT_UInt fir[4]; /* below, `pix' is used as the 5th element */ - FT_UInt val1, xx; + /* take care of bitmap flow */ + if ( pitch > 0 && height > 0 ) + origin += pitch * (FT_Int)( height - 1 ); - val1 = line[0]; - fir[0] = weights[2] * val1; - fir[1] = weights[3] * val1; - fir[2] = weights[4] * val1; - fir[3] = 0; + /* horizontal in-place FIR filter */ + if ( mode == FT_RENDER_MODE_LCD && width >= 2 ) + { + FT_Byte* line = origin; - val1 = line[1]; - fir[0] += weights[1] * val1; - fir[1] += weights[2] * val1; - fir[2] += weights[3] * val1; - fir[3] += weights[4] * val1; - for ( xx = 2; xx < width; xx++ ) - { - FT_UInt val, pix; + /* `fir' must be at least 32 bit wide, since the sum of */ + /* the values in `weights' can exceed 0xFF */ + for ( ; height > 0; height--, line -= pitch ) + { + FT_UInt fir[5]; + FT_UInt val, xx; - val = line[xx]; - pix = fir[0] + weights[0] * val; - fir[0] = fir[1] + weights[1] * val; - fir[1] = fir[2] + weights[2] * val; - fir[2] = fir[3] + weights[3] * val; - fir[3] = weights[4] * val; - - pix >>= 8; - pix |= (FT_UInt)-(FT_Int)( pix >> 8 ); - line[xx - 2] = (FT_Byte)pix; - } - { - FT_UInt pix; + val = line[0]; + fir[2] = weights[2] * val; + fir[3] = weights[3] * val; + fir[4] = weights[4] * val; + val = line[1]; + fir[1] = fir[2] + weights[1] * val; + fir[2] = fir[3] + weights[2] * val; + fir[3] = fir[4] + weights[3] * val; + fir[4] = weights[4] * val; - pix = fir[0] >> 8; - pix |= (FT_UInt)-(FT_Int)( pix >> 8 ); - line[xx - 2] = (FT_Byte)pix; + for ( xx = 2; xx < width; xx++ ) + { + val = line[xx]; + fir[0] = fir[1] + weights[0] * val; + fir[1] = fir[2] + weights[1] * val; + fir[2] = fir[3] + weights[2] * val; + fir[3] = fir[4] + weights[3] * val; + fir[4] = weights[4] * val; - pix = fir[1] >> 8; - pix |= (FT_UInt)-(FT_Int)( pix >> 8 ); - line[xx - 1] = (FT_Byte)pix; + line[xx - 2] = FT_SHIFTCLAMP( fir[0] ); } + + line[xx - 2] = FT_SHIFTCLAMP( fir[1] ); + line[xx - 1] = FT_SHIFTCLAMP( fir[2] ); } } /* vertical in-place FIR filter */ - else if ( mode == FT_RENDER_MODE_LCD_V && height >= 4 ) + else if ( mode == FT_RENDER_MODE_LCD_V && height >= 2 ) { - FT_Byte* column = bitmap->buffer; - FT_Int pitch = bitmap->pitch; + FT_Byte* column = origin; - /* take care of bitmap flow */ - if ( bitmap->pitch < 0 ) - column -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 ); - for ( ; width > 0; width--, column++ ) { FT_Byte* col = column; - FT_UInt fir[4]; /* below, `pix' is used as the 5th element */ - FT_UInt val1, yy; + FT_UInt fir[5]; + FT_UInt val, yy; - val1 = col[0]; - fir[0] = weights[2] * val1; - fir[1] = weights[3] * val1; - fir[2] = weights[4] * val1; - fir[3] = 0; - col += pitch; + val = col[0]; + fir[2] = weights[2] * val; + fir[3] = weights[3] * val; + fir[4] = weights[4] * val; + col -= pitch; - val1 = col[0]; - fir[0] += weights[1] * val1; - fir[1] += weights[2] * val1; - fir[2] += weights[3] * val1; - fir[3] += weights[4] * val1; - col += pitch; + val = col[0]; + fir[1] = fir[2] + weights[1] * val; + fir[2] = fir[3] + weights[2] * val; + fir[3] = fir[4] + weights[3] * val; + fir[4] = weights[4] * val; + col -= pitch; - for ( yy = 2; yy < height; yy++ ) + for ( yy = 2; yy < height; yy++, col -= pitch ) { - FT_UInt val, pix; - - val = col[0]; - pix = fir[0] + weights[0] * val; - fir[0] = fir[1] + weights[1] * val; - fir[1] = fir[2] + weights[2] * val; - fir[2] = fir[3] + weights[3] * val; - fir[3] = weights[4] * val; - - pix >>= 8; - pix |= (FT_UInt)-(FT_Int)( pix >> 8 ); - col[-2 * pitch] = (FT_Byte)pix; - col += pitch; - } - - { - FT_UInt pix; + fir[0] = fir[1] + weights[0] * val; + fir[1] = fir[2] + weights[1] * val; + fir[2] = fir[3] + weights[2] * val; + fir[3] = fir[4] + weights[3] * val; + fir[4] = weights[4] * val; - - pix = fir[0] >> 8; - pix |= (FT_UInt)-(FT_Int)( pix >> 8 ); - col[-2 * pitch] = (FT_Byte)pix; - - pix = fir[1] >> 8; - pix |= (FT_UInt)-(FT_Int)( pix >> 8 ); - col[-pitch] = (FT_Byte)pix; + col[pitch * 2] = FT_SHIFTCLAMP( fir[0] ); } + + col[pitch * 2] = FT_SHIFTCLAMP( fir[1] ); + col[pitch] = FT_SHIFTCLAMP( fir[2] ); } } } @@ -176,11 +174,12 @@ static void _ft_lcd_filter_legacy( FT_Bitmap* bitmap, FT_Render_Mode mode, - FT_Library library ) + FT_Byte* weights ) { - FT_UInt width = (FT_UInt)bitmap->width; - FT_UInt height = (FT_UInt)bitmap->rows; - FT_Int pitch = bitmap->pitch; + FT_UInt width = (FT_UInt)bitmap->width; + FT_UInt height = (FT_UInt)bitmap->rows; + FT_Int pitch = bitmap->pitch; + FT_Byte* origin = bitmap->buffer; static const unsigned int filters[3][3] = { @@ -189,36 +188,34 @@ { 65538 * 1/13, 65538 * 1/6, 65538 * 9/13 } }; - FT_UNUSED( library ); + FT_UNUSED( weights ); + + /* take care of bitmap flow */ + if ( pitch > 0 && height > 0 ) + origin += pitch * (FT_Int)( height - 1 ); /* horizontal in-place intra-pixel filter */ if ( mode == FT_RENDER_MODE_LCD && width >= 3 ) { - FT_Byte* line = bitmap->buffer; + FT_Byte* line = origin; - /* take care of bitmap flow */ - if ( bitmap->pitch < 0 ) - line -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 ); - - for ( ; height > 0; height--, line += pitch ) + for ( ; height > 0; height--, line -= pitch ) { FT_UInt xx; for ( xx = 0; xx < width; xx += 3 ) { - FT_UInt r = 0; - FT_UInt g = 0; - FT_UInt b = 0; + FT_UInt r, g, b; FT_UInt p; p = line[xx]; - r += filters[0][0] * p; - g += filters[0][1] * p; - b += filters[0][2] * p; + r = filters[0][0] * p; + g = filters[0][1] * p; + b = filters[0][2] * p; p = line[xx + 1]; r += filters[1][0] * p; @@ -238,31 +235,24 @@ } else if ( mode == FT_RENDER_MODE_LCD_V && height >= 3 ) { - FT_Byte* column = bitmap->buffer; - + FT_Byte* column = origin; - /* take care of bitmap flow */ - if ( bitmap->pitch < 0 ) - column -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 ); for ( ; width > 0; width--, column++ ) { - FT_Byte* col = column; - FT_Byte* col_end = col + (FT_Int)height * pitch; + FT_Byte* col = column - 2 * pitch; - for ( ; col < col_end; col += 3 * pitch ) + for ( ; height > 0; height -= 3, col -= 3 * pitch ) { - FT_UInt r = 0; - FT_UInt g = 0; - FT_UInt b = 0; + FT_UInt r, g, b; FT_UInt p; p = col[0]; - r += filters[0][0] * p; - g += filters[0][1] * p; - b += filters[0][2] * p; + r = filters[0][0] * p; + g = filters[0][1] * p; + b = filters[0][2] * p; p = col[pitch]; r += filters[1][0] * p; @@ -276,7 +266,7 @@ col[0] = (FT_Byte)( r / 65536 ); col[pitch] = (FT_Byte)( g / 65536 ); - col[2 * pitch] = (FT_Byte)( b / 65536 ); + col[pitch * 2] = (FT_Byte)( b / 65536 ); } } } @@ -295,9 +285,8 @@ if ( !weights ) return FT_THROW( Invalid_Argument ); - ft_memcpy( library->lcd_weights, weights, 5 ); - library->lcd_filter_func = _ft_lcd_filter_fir; - library->lcd_extra = 2; + ft_memcpy( library->lcd_weights, weights, FT_LCD_FILTER_FIVE_TAPS ); + library->lcd_filter_func = ft_lcd_filter_fir; return FT_Err_Ok; } @@ -307,10 +296,10 @@ FT_Library_SetLcdFilter( FT_Library library, FT_LcdFilter filter ) { - static const FT_Byte default_filter[5] = - { 0x08, 0x4d, 0x56, 0x4d, 0x08 }; - static const FT_Byte light_filter[5] = - { 0x00, 0x55, 0x56, 0x55, 0x00 }; + static const FT_LcdFiveTapFilter default_weights = + { 0x08, 0x4d, 0x56, 0x4d, 0x08 }; + static const FT_LcdFiveTapFilter light_weights = + { 0x00, 0x55, 0x56, 0x55, 0x00 }; if ( !library ) @@ -320,19 +309,20 @@ { case FT_LCD_FILTER_NONE: library->lcd_filter_func = NULL; - library->lcd_extra = 0; break; case FT_LCD_FILTER_DEFAULT: - ft_memcpy( library->lcd_weights, default_filter, 5 ); - library->lcd_filter_func = _ft_lcd_filter_fir; - library->lcd_extra = 2; + ft_memcpy( library->lcd_weights, + default_weights, + FT_LCD_FILTER_FIVE_TAPS ); + library->lcd_filter_func = ft_lcd_filter_fir; break; case FT_LCD_FILTER_LIGHT: - ft_memcpy( library->lcd_weights, light_filter, 5 ); - library->lcd_filter_func = _ft_lcd_filter_fir; - library->lcd_extra = 2; + ft_memcpy( library->lcd_weights, + light_weights, + FT_LCD_FILTER_FIVE_TAPS ); + library->lcd_filter_func = ft_lcd_filter_fir; break; #ifdef USE_LEGACY @@ -340,7 +330,6 @@ case FT_LCD_FILTER_LEGACY: case FT_LCD_FILTER_LEGACY1: library->lcd_filter_func = _ft_lcd_filter_legacy; - library->lcd_extra = 0; break; #endif @@ -349,13 +338,24 @@ return FT_THROW( Invalid_Argument ); } - library->lcd_filter = filter; - return FT_Err_Ok; } #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ + /* add padding according to accommodate outline shifts */ + FT_BASE_DEF (void) + ft_lcd_padding( FT_Pos* Min, + FT_Pos* Max, + FT_GlyphSlot slot ) + { + FT_UNUSED( slot ); + + *Min -= 21; + *Max += 21; + } + + FT_EXPORT_DEF( FT_Error ) FT_Library_SetLcdFilterWeights( FT_Library library, unsigned char *weights ) diff --git a/modules/freetype2/src/base/ftmac.c b/modules/freetype2/src/base/ftmac.c index f0edc94ea..fd4c0cc27 100644 --- a/modules/freetype2/src/base/ftmac.c +++ b/modules/freetype2/src/base/ftmac.c @@ -8,7 +8,7 @@ /* This file is for Mac OS X only; see builds/mac/ftoldmac.c for */ /* classic platforms built by MPW. */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -71,6 +71,9 @@ #include FT_INTERNAL_STREAM_H #include "ftbase.h" + +#ifdef FT_MACINTOSH + /* This is for Mac OS X. Without redefinition, OS_INLINE */ /* expands to `static inline' which doesn't survive the */ /* -ansi compilation flag of GCC. */ @@ -118,8 +121,6 @@ #endif -#ifdef FT_MACINTOSH - /* This function is deprecated because FSSpec is deprecated in Mac OS X */ FT_EXPORT_DEF( FT_Error ) FT_GetFile_From_Mac_Name( const char* fontName, @@ -1004,7 +1005,7 @@ /* accepts an FSRef instead of a path. */ /* */ /* This function is deprecated because Carbon data types (FSRef) */ - /* are not cross-platform, and thus not suitable for the freetype API. */ + /* are not cross-platform, and thus not suitable for the FreeType API. */ FT_EXPORT_DEF( FT_Error ) FT_New_Face_From_FSRef( FT_Library library, const FSRef* ref, @@ -1076,7 +1077,12 @@ #endif } -#endif /* FT_MACINTOSH */ +#else /* !FT_MACINTOSH */ + + /* ANSI C doesn't like empty source files */ + typedef int _ft_mac_dummy; + +#endif /* !FT_MACINTOSH */ /* END */ diff --git a/modules/freetype2/src/base/ftmm.c b/modules/freetype2/src/base/ftmm.c index 1b724ace6..800441bca 100644 --- a/modules/freetype2/src/base/ftmm.c +++ b/modules/freetype2/src/base/ftmm.c @@ -4,7 +4,7 @@ /* */ /* Multiple Master font support (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -22,6 +22,7 @@ #include FT_MULTIPLE_MASTERS_H #include FT_INTERNAL_OBJECTS_H #include FT_SERVICE_MULTIPLE_MASTERS_H +#include FT_SERVICE_METRICS_VARIATIONS_H /*************************************************************************/ @@ -62,6 +63,34 @@ } + static FT_Error + ft_face_get_mvar_service( FT_Face face, + FT_Service_MetricsVariations *aservice ) + { + FT_Error error; + + + *aservice = NULL; + + if ( !face ) + return FT_THROW( Invalid_Face_Handle ); + + error = FT_ERR( Invalid_Argument ); + + if ( FT_HAS_MULTIPLE_MASTERS( face ) ) + { + FT_FACE_LOOKUP_SERVICE( face, + *aservice, + METRICS_VARIATIONS ); + + if ( *aservice ) + error = FT_Err_Ok; + } + + return error; + } + + /* documentation is in ftmm.h */ FT_EXPORT_DEF( FT_Error ) @@ -119,6 +148,25 @@ /* documentation is in ftmm.h */ FT_EXPORT_DEF( FT_Error ) + FT_Done_MM_Var( FT_Library library, + FT_MM_Var* amaster ) + { + FT_Memory memory; + + + if ( !library ) + return FT_THROW( Invalid_Library_Handle ); + + memory = library->memory; + FT_FREE( amaster ); + + return FT_Err_Ok; + } + + + /* documentation is in ftmm.h */ + + FT_EXPORT_DEF( FT_Error ) FT_Set_MM_Design_Coordinates( FT_Face face, FT_UInt num_coords, FT_Long* coords ) @@ -129,7 +177,7 @@ /* check of `face' delayed to `ft_face_get_mm_service' */ - if ( !coords ) + if ( num_coords && !coords ) return FT_THROW( Invalid_Argument ); error = ft_face_get_mm_service( face, &service ); @@ -158,21 +206,34 @@ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Error error; - FT_Service_MultiMasters service; + FT_Error error; + FT_Service_MultiMasters service_mm = NULL; + FT_Service_MetricsVariations service_mvar = NULL; /* check of `face' delayed to `ft_face_get_mm_service' */ - if ( !coords ) + if ( num_coords && !coords ) return FT_THROW( Invalid_Argument ); - error = ft_face_get_mm_service( face, &service ); + error = ft_face_get_mm_service( face, &service_mm ); if ( !error ) { error = FT_ERR( Invalid_Argument ); - if ( service->set_var_design ) - error = service->set_var_design( face, num_coords, coords ); + if ( service_mm->set_var_design ) + error = service_mm->set_var_design( face, num_coords, coords ); + + /* internal error code -1 means `no change'; we can exit immediately */ + if ( error == -1 ) + return FT_Err_Ok; + } + + if ( !error ) + { + (void)ft_face_get_mvar_service( face, &service_mvar ); + + if ( service_mvar && service_mvar->metrics_adjust ) + service_mvar->metrics_adjust( face ); } /* enforce recomputation of auto-hinting data */ @@ -221,21 +282,34 @@ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Error error; - FT_Service_MultiMasters service; + FT_Error error; + FT_Service_MultiMasters service_mm = NULL; + FT_Service_MetricsVariations service_mvar = NULL; /* check of `face' delayed to `ft_face_get_mm_service' */ - if ( !coords ) + if ( num_coords && !coords ) return FT_THROW( Invalid_Argument ); - error = ft_face_get_mm_service( face, &service ); + error = ft_face_get_mm_service( face, &service_mm ); if ( !error ) { error = FT_ERR( Invalid_Argument ); - if ( service->set_mm_blend ) - error = service->set_mm_blend( face, num_coords, coords ); + if ( service_mm->set_mm_blend ) + error = service_mm->set_mm_blend( face, num_coords, coords ); + + /* internal error code -1 means `no change'; we can exit immediately */ + if ( error == -1 ) + return FT_Err_Ok; + } + + if ( !error ) + { + (void)ft_face_get_mvar_service( face, &service_mvar ); + + if ( service_mvar && service_mvar->metrics_adjust ) + service_mvar->metrics_adjust( face ); } /* enforce recomputation of auto-hinting data */ @@ -259,21 +333,34 @@ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Error error; - FT_Service_MultiMasters service; + FT_Error error; + FT_Service_MultiMasters service_mm = NULL; + FT_Service_MetricsVariations service_mvar = NULL; /* check of `face' delayed to `ft_face_get_mm_service' */ - if ( !coords ) + if ( num_coords && !coords ) return FT_THROW( Invalid_Argument ); - error = ft_face_get_mm_service( face, &service ); + error = ft_face_get_mm_service( face, &service_mm ); if ( !error ) { error = FT_ERR( Invalid_Argument ); - if ( service->set_mm_blend ) - error = service->set_mm_blend( face, num_coords, coords ); + if ( service_mm->set_mm_blend ) + error = service_mm->set_mm_blend( face, num_coords, coords ); + + /* internal error code -1 means `no change'; we can exit immediately */ + if ( error == -1 ) + return FT_Err_Ok; + } + + if ( !error ) + { + (void)ft_face_get_mvar_service( face, &service_mvar ); + + if ( service_mvar && service_mvar->metrics_adjust ) + service_mvar->metrics_adjust( face ); } /* enforce recomputation of auto-hinting data */ @@ -346,4 +433,76 @@ } + /* documentation is in ftmm.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Get_Var_Axis_Flags( FT_MM_Var* master, + FT_UInt axis_index, + FT_UInt* flags ) + { + FT_UShort* axis_flags; + + + if ( !master || !flags ) + return FT_THROW( Invalid_Argument ); + + if ( axis_index >= master->num_axis ) + return FT_THROW( Invalid_Argument ); + + /* the axis flags array immediately follows the data of `master' */ + axis_flags = (FT_UShort*)&( master[1] ); + *flags = axis_flags[axis_index]; + + return FT_Err_Ok; + } + + + /* documentation is in ftmm.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Set_Named_Instance( FT_Face face, + FT_UInt instance_index ) + { + FT_Error error; + + FT_Service_MultiMasters service_mm = NULL; + FT_Service_MetricsVariations service_mvar = NULL; + + + /* check of `face' delayed to `ft_face_get_mm_service' */ + + error = ft_face_get_mm_service( face, &service_mm ); + if ( !error ) + { + error = FT_ERR( Invalid_Argument ); + if ( service_mm->set_instance ) + error = service_mm->set_instance( face, instance_index ); + } + + if ( !error ) + { + (void)ft_face_get_mvar_service( face, &service_mvar ); + + if ( service_mvar && service_mvar->metrics_adjust ) + service_mvar->metrics_adjust( face ); + } + + /* enforce recomputation of auto-hinting data */ + if ( !error && face->autohint.finalizer ) + { + face->autohint.finalizer( face->autohint.data ); + face->autohint.data = NULL; + } + + if ( !error ) + { + face->face_index = ( instance_index << 16 ) | + ( face->face_index & 0xFFFFL ); + face->face_flags &= ~FT_FACE_FLAG_VARIATION; + } + + return error; + } + + /* END */ diff --git a/modules/freetype2/src/base/ftobjs.c b/modules/freetype2/src/base/ftobjs.c index 4f2a9ecdb..8d07e35ae 100644 --- a/modules/freetype2/src/base/ftobjs.c +++ b/modules/freetype2/src/base/ftobjs.c @@ -4,7 +4,7 @@ /* */ /* The FreeType private base classes (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -19,12 +19,16 @@ #include <ft2build.h> #include FT_LIST_H #include FT_OUTLINE_H +#include FT_FONT_FORMATS_H + #include FT_INTERNAL_VALIDATE_H #include FT_INTERNAL_OBJECTS_H #include FT_INTERNAL_DEBUG_H #include FT_INTERNAL_RFORK_H #include FT_INTERNAL_STREAM_H -#include FT_INTERNAL_SFNT_H /* for SFNT_Load_Table_Func */ +#include FT_INTERNAL_SFNT_H /* for SFNT_Load_Table_Func */ +#include FT_INTERNAL_POSTSCRIPT_AUX_H /* for PS_Driver */ + #include FT_TRUETYPE_TABLES_H #include FT_TRUETYPE_TAGS_H #include FT_TRUETYPE_IDS_H @@ -37,6 +41,8 @@ #include FT_SERVICE_KERNING_H #include FT_SERVICE_TRUETYPE_ENGINE_H +#include FT_DRIVER_H + #ifdef FT_CONFIG_OPTION_MAC_FONTS #include "ftbase.h" #endif @@ -325,6 +331,138 @@ FT_BASE_DEF( void ) + ft_glyphslot_preset_bitmap( FT_GlyphSlot slot, + FT_Render_Mode mode, + const FT_Vector* origin ) + { + FT_Outline* outline = &slot->outline; + FT_Bitmap* bitmap = &slot->bitmap; + + FT_Pixel_Mode pixel_mode; + + FT_BBox cbox; + FT_Pos x_shift = 0; + FT_Pos y_shift = 0; + FT_Pos x_left, y_top; + FT_Pos width, height, pitch; + + + if ( slot->internal && ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) ) + return; + + if ( origin ) + { + x_shift = origin->x; + y_shift = origin->y; + } + + /* compute the control box, and grid-fit it, */ + /* taking into account the origin shift */ + FT_Outline_Get_CBox( outline, &cbox ); + + cbox.xMin += x_shift; + cbox.yMin += y_shift; + cbox.xMax += x_shift; + cbox.yMax += y_shift; + + switch ( mode ) + { + case FT_RENDER_MODE_MONO: + pixel_mode = FT_PIXEL_MODE_MONO; +#if 1 + /* undocumented but confirmed: bbox values get rounded */ + /* unless the rounded box can collapse for a narrow glyph */ + if ( cbox.xMax - cbox.xMin < 64 ) + { + cbox.xMin = FT_PIX_FLOOR( cbox.xMin ); + cbox.xMax = FT_PIX_CEIL_LONG( cbox.xMax ); + } + else + { + cbox.xMin = FT_PIX_ROUND_LONG( cbox.xMin ); + cbox.xMax = FT_PIX_ROUND_LONG( cbox.xMax ); + } + + if ( cbox.yMax - cbox.yMin < 64 ) + { + cbox.yMin = FT_PIX_FLOOR( cbox.yMin ); + cbox.yMax = FT_PIX_CEIL_LONG( cbox.yMax ); + } + else + { + cbox.yMin = FT_PIX_ROUND_LONG( cbox.yMin ); + cbox.yMax = FT_PIX_ROUND_LONG( cbox.yMax ); + } +#else + cbox.xMin = FT_PIX_FLOOR( cbox.xMin ); + cbox.yMin = FT_PIX_FLOOR( cbox.yMin ); + cbox.xMax = FT_PIX_CEIL_LONG( cbox.xMax ); + cbox.yMax = FT_PIX_CEIL_LONG( cbox.yMax ); +#endif + break; + + case FT_RENDER_MODE_LCD: + pixel_mode = FT_PIXEL_MODE_LCD; + ft_lcd_padding( &cbox.xMin, &cbox.xMax, slot ); + goto Round; + + case FT_RENDER_MODE_LCD_V: + pixel_mode = FT_PIXEL_MODE_LCD_V; + ft_lcd_padding( &cbox.yMin, &cbox.yMax, slot ); + goto Round; + + case FT_RENDER_MODE_NORMAL: + case FT_RENDER_MODE_LIGHT: + default: + pixel_mode = FT_PIXEL_MODE_GRAY; + Round: + cbox.xMin = FT_PIX_FLOOR( cbox.xMin ); + cbox.yMin = FT_PIX_FLOOR( cbox.yMin ); + cbox.xMax = FT_PIX_CEIL_LONG( cbox.xMax ); + cbox.yMax = FT_PIX_CEIL_LONG( cbox.yMax ); + } + + x_shift = SUB_LONG( x_shift, cbox.xMin ); + y_shift = SUB_LONG( y_shift, cbox.yMin ); + + x_left = cbox.xMin >> 6; + y_top = cbox.yMax >> 6; + + width = ( (FT_ULong)cbox.xMax - (FT_ULong)cbox.xMin ) >> 6; + height = ( (FT_ULong)cbox.yMax - (FT_ULong)cbox.yMin ) >> 6; + + switch ( pixel_mode ) + { + case FT_PIXEL_MODE_MONO: + pitch = ( ( width + 15 ) >> 4 ) << 1; + break; + + case FT_PIXEL_MODE_LCD: + width *= 3; + pitch = FT_PAD_CEIL( width, 4 ); + break; + + case FT_PIXEL_MODE_LCD_V: + height *= 3; + /* fall through */ + + case FT_PIXEL_MODE_GRAY: + default: + pitch = width; + } + + slot->bitmap_left = (FT_Int)x_left; + slot->bitmap_top = (FT_Int)y_top; + + bitmap->pixel_mode = (unsigned char)pixel_mode; + bitmap->num_grays = 256; + bitmap->width = (unsigned int)width; + bitmap->rows = (unsigned int)height; + bitmap->pitch = pitch; + } + + + FT_BASE_DEF( void ) ft_glyphslot_set_bitmap( FT_GlyphSlot slot, FT_Byte* buffer ) { @@ -462,7 +600,8 @@ Exit: - FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error )); + FT_TRACE4(( "FT_New_GlyphSlot: Return 0x%x\n", error )); + return error; } @@ -575,34 +714,42 @@ if ( vertical ) { metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX ); - metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY ); + metrics->horiBearingY = FT_PIX_CEIL_LONG( metrics->horiBearingY ); - right = FT_PIX_CEIL( metrics->vertBearingX + metrics->width ); - bottom = FT_PIX_CEIL( metrics->vertBearingY + metrics->height ); + right = FT_PIX_CEIL_LONG( ADD_LONG( metrics->vertBearingX, + metrics->width ) ); + bottom = FT_PIX_CEIL_LONG( ADD_LONG( metrics->vertBearingY, + metrics->height ) ); metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX ); metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY ); - metrics->width = right - metrics->vertBearingX; - metrics->height = bottom - metrics->vertBearingY; + metrics->width = SUB_LONG( right, + metrics->vertBearingX ); + metrics->height = SUB_LONG( bottom, + metrics->vertBearingY ); } else { metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX ); metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY ); - right = FT_PIX_CEIL ( metrics->horiBearingX + metrics->width ); - bottom = FT_PIX_FLOOR( metrics->horiBearingY - metrics->height ); + right = FT_PIX_CEIL_LONG( ADD_LONG( metrics->horiBearingX, + metrics->width ) ); + bottom = FT_PIX_FLOOR( SUB_LONG( metrics->horiBearingY, + metrics->height ) ); metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX ); - metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY ); + metrics->horiBearingY = FT_PIX_CEIL_LONG( metrics->horiBearingY ); - metrics->width = right - metrics->horiBearingX; - metrics->height = metrics->horiBearingY - bottom; + metrics->width = SUB_LONG( right, + metrics->horiBearingX ); + metrics->height = SUB_LONG( metrics->horiBearingY, + bottom ); } - metrics->horiAdvance = FT_PIX_ROUND( metrics->horiAdvance ); - metrics->vertAdvance = FT_PIX_ROUND( metrics->vertAdvance ); + metrics->horiAdvance = FT_PIX_ROUND_LONG( metrics->horiAdvance ); + metrics->vertAdvance = FT_PIX_ROUND_LONG( metrics->vertAdvance ); } #endif /* GRID_FIT_METRICS */ @@ -657,9 +804,13 @@ * Determine whether we need to auto-hint or not. * The general rules are: * - * - Do only auto-hinting if we have a hinter module, a scalable font - * format dealing with outlines, and no transforms except simple - * slants and/or rotations by integer multiples of 90 degrees. + * - Do only auto-hinting if we have + * + * - a hinter module, + * - a scalable font format dealing with outlines, + * - not a tricky font, and + * - no transforms except simple slants and/or rotations by + * integer multiples of 90 degrees. * * - Then, auto-hint if FT_LOAD_FORCE_AUTOHINT is set or if we don't * have a native font hinter. @@ -689,7 +840,14 @@ else { FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags ); + FT_Bool is_light_type1; + + /* only the new Adobe engine (for both CFF and Type 1) is `light'; */ + /* we use `strstr' to catch both `Type 1' and `CID Type 1' */ + is_light_type1 = + ft_strstr( FT_Get_Font_Format( face ), "Type 1" ) != NULL && + ((PS_Driver)driver)->hinting_engine == FT_HINTING_ADOBE; /* the check for `num_locations' assures that we actually */ /* test for instructions in a TTF and not in a CFF-based OTF */ @@ -698,8 +856,9 @@ /* check the size of the `fpgm' and `prep' tables, too -- */ /* the assumption is that there don't exist real TTFs where */ /* both `fpgm' and `prep' tables are missing */ - if ( ( mode == FT_RENDER_MODE_LIGHT && - !FT_DRIVER_HINTS_LIGHTLY( driver ) ) || + if ( ( mode == FT_RENDER_MODE_LIGHT && + ( !FT_DRIVER_HINTS_LIGHTLY( driver ) && + !is_light_type1 ) ) || ( FT_IS_SFNT( face ) && ttface->num_locations && ttface->max_profile.maxSizeOfInstructions == 0 && @@ -719,8 +878,8 @@ /* XXX: This is really a temporary hack that should disappear */ /* promptly with FreeType 2.1! */ /* */ - if ( FT_HAS_FIXED_SIZES( face ) && - ( load_flags & FT_LOAD_NO_BITMAP ) == 0 ) + if ( FT_HAS_FIXED_SIZES( face ) && + ( load_flags & FT_LOAD_NO_BITMAP ) == 0 ) { error = driver->clazz->load_glyph( slot, face->size, glyph_index, @@ -788,7 +947,7 @@ /* compute the linear advance in 16.16 pixels */ if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 && - ( FT_IS_SCALABLE( face ) ) ) + FT_IS_SCALABLE( face ) ) { FT_Size_Metrics* metrics = &face->size->metrics; @@ -836,28 +995,37 @@ } } - FT_TRACE5(( " x advance: %d\n" , slot->advance.x )); - FT_TRACE5(( " y advance: %d\n" , slot->advance.y )); - - FT_TRACE5(( " linear x advance: %d\n" , slot->linearHoriAdvance )); - FT_TRACE5(( " linear y advance: %d\n" , slot->linearVertAdvance )); - - /* do we need to render the image now? */ + /* do we need to render the image or preset the bitmap now? */ if ( !error && + ( load_flags & FT_LOAD_NO_SCALE ) == 0 && slot->format != FT_GLYPH_FORMAT_BITMAP && - slot->format != FT_GLYPH_FORMAT_COMPOSITE && - load_flags & FT_LOAD_RENDER ) + slot->format != FT_GLYPH_FORMAT_COMPOSITE ) { FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags ); - if ( mode == FT_RENDER_MODE_NORMAL && - (load_flags & FT_LOAD_MONOCHROME ) ) + if ( mode == FT_RENDER_MODE_NORMAL && + load_flags & FT_LOAD_MONOCHROME ) mode = FT_RENDER_MODE_MONO; - error = FT_Render_Glyph( slot, mode ); + if ( load_flags & FT_LOAD_RENDER ) + error = FT_Render_Glyph( slot, mode ); + else + ft_glyphslot_preset_bitmap( slot, mode, NULL ); } + FT_TRACE5(( "FT_Load_Glyph: index %d, flags %x\n", + glyph_index, load_flags )); + FT_TRACE5(( " x advance: %f\n", slot->advance.x / 64.0 )); + FT_TRACE5(( " y advance: %f\n", slot->advance.y / 64.0 )); + FT_TRACE5(( " linear x advance: %f\n", + slot->linearHoriAdvance / 65536.0 )); + FT_TRACE5(( " linear y advance: %f\n", + slot->linearVertAdvance / 65536.0 )); + FT_TRACE5(( " bitmap %dx%d, mode %d\n", + slot->bitmap.width, slot->bitmap.rows, + slot->bitmap.pixel_mode )); + Exit: return error; } @@ -1185,6 +1353,8 @@ } #endif + face->internal->random_seed = -1; + if ( clazz->init_face ) error = clazz->init_face( *astream, face, @@ -2031,13 +2201,15 @@ { FT_TRACE3(( "Skip rule %d: darwin vfs resource fork" " is already checked and" - " no font is found\n", i )); + " no font is found\n", + i )); continue; } if ( errors[i] ) { - FT_TRACE3(( "Error[%d] has occurred in rule %d\n", errors[i], i )); + FT_TRACE3(( "Error 0x%x has occurred in rule %d\n", + errors[i], i )); continue; } @@ -2396,7 +2568,7 @@ if ( bsize->height < 0 || bsize->x_ppem < 0 || bsize->y_ppem < 0 ) { FT_TRACE0(( "FT_Open_Face:" - " Invalid bitmap dimensions for stroke %d," + " Invalid bitmap dimensions for strike %d," " now disabled\n", i )); bsize->width = 0; bsize->height = 0; @@ -2421,6 +2593,13 @@ internal->transform_delta.y = 0; internal->refcount = 1; + + internal->no_stem_darkening = -1; + +#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING + /* Per-face filtering can only be set up by FT_Face_Properties */ + internal->lcd_filter_func = NULL; +#endif } if ( aface ) @@ -2440,15 +2619,17 @@ #ifdef FT_DEBUG_LEVEL_TRACE if ( !error && face_index < 0 ) { - FT_TRACE3(( "FT_Open_Face: The font has %ld faces\n" - " and %ld named instances for face %ld\n", + FT_TRACE3(( "FT_Open_Face: The font has %ld face%s\n" + " and %ld named instance%s for face %ld\n", face->num_faces, + face->num_faces == 1 ? "" : "s", face->style_flags >> 16, + ( face->style_flags >> 16 ) == 1 ? "" : "s", -face_index - 1 )); } #endif - FT_TRACE4(( "FT_Open_Face: Return %d\n", error )); + FT_TRACE4(( "FT_Open_Face: Return 0x%x\n", error )); return error; } @@ -2589,6 +2770,8 @@ FT_Size size = NULL; FT_ListNode node = NULL; + FT_Size_Internal internal = NULL; + if ( !face ) return FT_THROW( Invalid_Face_Handle ); @@ -2611,8 +2794,10 @@ size->face = face; - /* for now, do not use any internal fields in size objects */ - size->internal = NULL; + if ( FT_NEW( internal ) ) + goto Exit; + + size->internal = internal; if ( clazz->init_size ) error = clazz->init_size( size ); @@ -2836,18 +3021,6 @@ metrics->height = bsize->height << 6; metrics->max_advance = bsize->x_ppem; } - - FT_TRACE5(( "FT_Select_Metrics:\n" )); - FT_TRACE5(( " x scale: %d (%f)\n", - metrics->x_scale, metrics->x_scale / 65536.0 )); - FT_TRACE5(( " y scale: %d (%f)\n", - metrics->y_scale, metrics->y_scale / 65536.0 )); - FT_TRACE5(( " ascender: %f\n", metrics->ascender / 64.0 )); - FT_TRACE5(( " descender: %f\n", metrics->descender / 64.0 )); - FT_TRACE5(( " height: %f\n", metrics->height / 64.0 )); - FT_TRACE5(( " max advance: %f\n", metrics->max_advance / 64.0 )); - FT_TRACE5(( " x ppem: %d\n", metrics->x_ppem )); - FT_TRACE5(( " y ppem: %d\n", metrics->y_ppem )); } @@ -2956,18 +3129,6 @@ metrics->x_scale = 1L << 16; metrics->y_scale = 1L << 16; } - - FT_TRACE5(( "FT_Request_Metrics:\n" )); - FT_TRACE5(( " x scale: %d (%f)\n", - metrics->x_scale, metrics->x_scale / 65536.0 )); - FT_TRACE5(( " y scale: %d (%f)\n", - metrics->y_scale, metrics->y_scale / 65536.0 )); - FT_TRACE5(( " ascender: %f\n", metrics->ascender / 64.0 )); - FT_TRACE5(( " descender: %f\n", metrics->descender / 64.0 )); - FT_TRACE5(( " height: %f\n", metrics->height / 64.0 )); - FT_TRACE5(( " max advance: %f\n", metrics->max_advance / 64.0 )); - FT_TRACE5(( " x ppem: %d\n", metrics->x_ppem )); - FT_TRACE5(( " y ppem: %d\n", metrics->y_ppem )); } @@ -2977,6 +3138,7 @@ FT_Select_Size( FT_Face face, FT_Int strike_index ) { + FT_Error error = FT_Err_Ok; FT_Driver_Class clazz; @@ -2990,36 +3152,37 @@ if ( clazz->select_size ) { - FT_Error error; + error = clazz->select_size( face->size, (FT_ULong)strike_index ); + FT_TRACE5(( "FT_Select_Size (%s driver):\n", + face->driver->root.clazz->module_name )); + } + else + { + FT_Select_Metrics( face, (FT_ULong)strike_index ); - error = clazz->select_size( face->size, (FT_ULong)strike_index ); + FT_TRACE5(( "FT_Select_Size:\n" )); + } #ifdef FT_DEBUG_LEVEL_TRACE - { - FT_Size_Metrics* metrics = &face->size->metrics; - - - FT_TRACE5(( "FT_Select_Size (font driver's `select_size'):\n" )); - FT_TRACE5(( " x scale: %d (%f)\n", - metrics->x_scale, metrics->x_scale / 65536.0 )); - FT_TRACE5(( " y scale: %d (%f)\n", - metrics->y_scale, metrics->y_scale / 65536.0 )); - FT_TRACE5(( " ascender: %f\n", metrics->ascender / 64.0 )); - FT_TRACE5(( " descender: %f\n", metrics->descender / 64.0 )); - FT_TRACE5(( " height: %f\n", metrics->height / 64.0 )); - FT_TRACE5(( " max advance: %f\n", metrics->max_advance / 64.0 )); - FT_TRACE5(( " x ppem: %d\n", metrics->x_ppem )); - FT_TRACE5(( " y ppem: %d\n", metrics->y_ppem )); - } -#endif + { + FT_Size_Metrics* metrics = &face->size->metrics; - return error; - } - FT_Select_Metrics( face, (FT_ULong)strike_index ); + FT_TRACE5(( " x scale: %d (%f)\n", + metrics->x_scale, metrics->x_scale / 65536.0 )); + FT_TRACE5(( " y scale: %d (%f)\n", + metrics->y_scale, metrics->y_scale / 65536.0 )); + FT_TRACE5(( " ascender: %f\n", metrics->ascender / 64.0 )); + FT_TRACE5(( " descender: %f\n", metrics->descender / 64.0 )); + FT_TRACE5(( " height: %f\n", metrics->height / 64.0 )); + FT_TRACE5(( " max advance: %f\n", metrics->max_advance / 64.0 )); + FT_TRACE5(( " x ppem: %d\n", metrics->x_ppem )); + FT_TRACE5(( " y ppem: %d\n", metrics->y_ppem )); + } +#endif - return FT_Err_Ok; + return error; } @@ -3029,6 +3192,7 @@ FT_Request_Size( FT_Face face, FT_Size_Request req ) { + FT_Error error = FT_Err_Ok; FT_Driver_Class clazz; FT_ULong strike_index; @@ -3040,59 +3204,60 @@ req->type >= FT_SIZE_REQUEST_TYPE_MAX ) return FT_THROW( Invalid_Argument ); + /* signal the auto-hinter to recompute its size metrics */ + /* (if requested) */ + face->size->internal->autohint_metrics.x_scale = 0; + clazz = face->driver->clazz; if ( clazz->request_size ) { - FT_Error error; - - error = clazz->request_size( face->size, req ); -#ifdef FT_DEBUG_LEVEL_TRACE - { - FT_Size_Metrics* metrics = &face->size->metrics; - - - FT_TRACE5(( "FT_Request_Size (font driver's `request_size'):\n" )); - FT_TRACE5(( " x scale: %d (%f)\n", - metrics->x_scale, metrics->x_scale / 65536.0 )); - FT_TRACE5(( " y scale: %d (%f)\n", - metrics->y_scale, metrics->y_scale / 65536.0 )); - FT_TRACE5(( " ascender: %f\n", metrics->ascender / 64.0 )); - FT_TRACE5(( " descender: %f\n", metrics->descender / 64.0 )); - FT_TRACE5(( " height: %f\n", metrics->height / 64.0 )); - FT_TRACE5(( " max advance: %f\n", metrics->max_advance / 64.0 )); - FT_TRACE5(( " x ppem: %d\n", metrics->x_ppem )); - FT_TRACE5(( " y ppem: %d\n", metrics->y_ppem )); - } -#endif - - return error; + FT_TRACE5(( "FT_Request_Size (%s driver):\n", + face->driver->root.clazz->module_name )); } - - /* - * The reason that a driver doesn't have `request_size' defined is - * either that the scaling here suffices or that the supported formats - * are bitmap-only and size matching is not implemented. - * - * In the latter case, a simple size matching is done. - */ - if ( !FT_IS_SCALABLE( face ) && FT_HAS_FIXED_SIZES( face ) ) + else if ( !FT_IS_SCALABLE( face ) && FT_HAS_FIXED_SIZES( face ) ) { - FT_Error error; - - + /* + * The reason that a driver doesn't have `request_size' defined is + * either that the scaling here suffices or that the supported formats + * are bitmap-only and size matching is not implemented. + * + * In the latter case, a simple size matching is done. + */ error = FT_Match_Size( face, req, 0, &strike_index ); if ( error ) return error; return FT_Select_Size( face, (FT_Int)strike_index ); } + else + { + FT_Request_Metrics( face, req ); + + FT_TRACE5(( "FT_Request_Size:\n" )); + } + +#ifdef FT_DEBUG_LEVEL_TRACE + { + FT_Size_Metrics* metrics = &face->size->metrics; - FT_Request_Metrics( face, req ); - return FT_Err_Ok; + FT_TRACE5(( " x scale: %d (%f)\n", + metrics->x_scale, metrics->x_scale / 65536.0 )); + FT_TRACE5(( " y scale: %d (%f)\n", + metrics->y_scale, metrics->y_scale / 65536.0 )); + FT_TRACE5(( " ascender: %f\n", metrics->ascender / 64.0 )); + FT_TRACE5(( " descender: %f\n", metrics->descender / 64.0 )); + FT_TRACE5(( " height: %f\n", metrics->height / 64.0 )); + FT_TRACE5(( " max advance: %f\n", metrics->max_advance / 64.0 )); + FT_TRACE5(( " x ppem: %d\n", metrics->x_ppem )); + FT_TRACE5(( " y ppem: %d\n", metrics->y_ppem )); + } +#endif + + return error; } @@ -3586,6 +3751,85 @@ /* documentation is in freetype.h */ + FT_EXPORT_DEF( FT_Error ) + FT_Face_Properties( FT_Face face, + FT_UInt num_properties, + FT_Parameter* properties ) + { + FT_Error error = FT_Err_Ok; + + + if ( num_properties > 0 && !properties ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + for ( ; num_properties > 0; num_properties-- ) + { + if ( properties->tag == FT_PARAM_TAG_STEM_DARKENING ) + { + if ( properties->data ) + { + if ( *( (FT_Bool*)properties->data ) == TRUE ) + face->internal->no_stem_darkening = FALSE; + else + face->internal->no_stem_darkening = TRUE; + } + else + { + /* use module default */ + face->internal->no_stem_darkening = -1; + } + } + else if ( properties->tag == FT_PARAM_TAG_LCD_FILTER_WEIGHTS ) + { +#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING + if ( properties->data ) + { + ft_memcpy( face->internal->lcd_weights, + properties->data, + FT_LCD_FILTER_FIVE_TAPS ); + face->internal->lcd_filter_func = ft_lcd_filter_fir; + } +#else + error = FT_THROW( Unimplemented_Feature ); + goto Exit; +#endif + } + else if ( properties->tag == FT_PARAM_TAG_RANDOM_SEED ) + { + if ( properties->data ) + { + face->internal->random_seed = *( (FT_Int32*)properties->data ); + if ( face->internal->random_seed < 0 ) + face->internal->random_seed = 0; + } + else + { + /* use module default */ + face->internal->random_seed = -1; + } + } + else + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + if ( error ) + break; + + properties++; + } + + Exit: + return error; + } + + + /* documentation is in freetype.h */ + FT_EXPORT_DEF( FT_UInt ) FT_Face_GetCharVariantIndex( FT_Face face, FT_ULong charcode, @@ -3609,12 +3853,14 @@ if ( charcode > 0xFFFFFFFFUL ) { - FT_TRACE1(( "FT_Get_Char_Index: too large charcode" )); + FT_TRACE1(( "FT_Face_GetCharVariantIndex:" + " too large charcode" )); FT_TRACE1(( " 0x%x is truncated\n", charcode )); } if ( variantSelector > 0xFFFFFFFFUL ) { - FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" )); + FT_TRACE1(( "FT_Face_GetCharVariantIndex:" + " too large variantSelector" )); FT_TRACE1(( " 0x%x is truncated\n", variantSelector )); } @@ -3650,12 +3896,14 @@ if ( charcode > 0xFFFFFFFFUL ) { - FT_TRACE1(( "FT_Get_Char_Index: too large charcode" )); + FT_TRACE1(( "FT_Face_GetCharVariantIsDefault:" + " too large charcode" )); FT_TRACE1(( " 0x%x is truncated\n", charcode )); } if ( variantSelector > 0xFFFFFFFFUL ) { - FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" )); + FT_TRACE1(( "FT_Face_GetCharVariantIsDefault:" + " too large variantSelector" )); FT_TRACE1(( " 0x%x is truncated\n", variantSelector )); } @@ -3718,7 +3966,7 @@ if ( charcode > 0xFFFFFFFFUL ) { - FT_TRACE1(( "FT_Get_Char_Index: too large charcode" )); + FT_TRACE1(( "FT_Face_GetVariantsOfChar: too large charcode" )); FT_TRACE1(( " 0x%x is truncated\n", charcode )); } @@ -4294,43 +4542,97 @@ */ /* we use FT_TRACE3 in this block */ - if ( ft_trace_levels[trace_bitmap] >= 3 ) + if ( !error && + ft_trace_levels[trace_bitmap] >= 3 && + slot->bitmap.buffer ) { + FT_Bitmap bitmap; + FT_Error err; + + + FT_Bitmap_Init( &bitmap ); + /* we convert to a single bitmap format for computing the checksum */ - if ( !error && slot->bitmap.buffer ) + /* this also converts the bitmap flow to `down' (i.e., pitch > 0) */ + err = FT_Bitmap_Convert( library, &slot->bitmap, &bitmap, 1 ); + if ( !err ) { - FT_Bitmap bitmap; - FT_Error err; + MD5_CTX ctx; + unsigned char md5[16]; + unsigned long coverage = 0; + int i, j; + int rows = (int)bitmap.rows; + int pitch = bitmap.pitch; + + + FT_TRACE3(( "FT_Render_Glyph: bitmap %dx%d, mode %d\n", + rows, pitch, slot->bitmap.pixel_mode )); + + for ( i = 0; i < rows; i++ ) + for ( j = 0; j < pitch; j++ ) + coverage += bitmap.buffer[i * pitch + j]; + + FT_TRACE3(( " Total coverage: %lu\n", coverage )); + + MD5_Init( &ctx ); + if ( bitmap.buffer ) + MD5_Update( &ctx, bitmap.buffer, + (unsigned long)rows * (unsigned long)pitch ); + MD5_Final( md5, &ctx ); + + FT_TRACE3(( " MD5 checksum: " )); + for ( i = 0; i < 16; i++ ) + FT_TRACE3(( "%02X", md5[i] )); + FT_TRACE3(( "\n" )); + } + + FT_Bitmap_Done( library, &bitmap ); + } + + /* + * Dump bitmap in Netpbm format (PBM or PGM). + */ + /* we use FT_TRACE7 in this block */ + if ( !error && + ft_trace_levels[trace_bitmap] >= 7 && + slot->bitmap.rows < 128U && + slot->bitmap.width < 128U && + slot->bitmap.buffer ) + { + int rows = (int)slot->bitmap.rows; + int width = (int)slot->bitmap.width; + int pitch = slot->bitmap.pitch; + int i, j, m; + unsigned char* topleft = slot->bitmap.buffer; - FT_Bitmap_Init( &bitmap ); + if ( pitch < 0 ) + topleft -= pitch * ( rows - 1 ); - /* this also converts the bitmap flow to `down' (i.e., pitch > 0) */ - err = FT_Bitmap_Convert( library, &slot->bitmap, &bitmap, 1 ); - if ( !err ) + FT_TRACE7(( "Netpbm image: start\n" )); + switch ( slot->bitmap.pixel_mode ) + { + case FT_PIXEL_MODE_MONO: + FT_TRACE7(( "P1 %d %d\n", width, rows )); + for ( i = 0; i < rows; i++ ) { - MD5_CTX ctx; - unsigned char md5[16]; - int i; - unsigned int rows = bitmap.rows; - unsigned int pitch = (unsigned int)bitmap.pitch; - - - MD5_Init( &ctx ); - if ( bitmap.buffer ) - MD5_Update( &ctx, bitmap.buffer, rows * pitch ); - MD5_Final( md5, &ctx ); - - FT_TRACE3(( "MD5 checksum for %dx%d bitmap:\n" - " ", - rows, pitch )); - for ( i = 0; i < 16; i++ ) - FT_TRACE3(( "%02X", md5[i] )); - FT_TRACE3(( "\n" )); + for ( j = 0; j < width; ) + for ( m = 128; m > 0 && j < width; m >>= 1, j++ ) + FT_TRACE7(( " %d", ( topleft[i * pitch + j / 8] & m ) != 0 )); + FT_TRACE7(( "\n" )); } + break; - FT_Bitmap_Done( library, &bitmap ); + default: + FT_TRACE7(( "P2 %d %d 255\n", width, rows )); + for ( i = 0; i < rows; i++ ) + { + for ( j = 0; j < width; j += 1 ) + FT_TRACE7(( " %3u", topleft[i * pitch + j] )); + FT_TRACE7(( "\n" )); + } } + FT_TRACE7(( "Netpbm image: end\n" )); } #undef FT_COMPONENT @@ -4437,7 +4739,7 @@ if ( !clazz ) return FT_THROW( Invalid_Argument ); - /* check freetype version */ + /* check FreeType version */ if ( clazz->module_requires > FREETYPE_VER_FIXED ) return FT_THROW( Invalid_Version ); @@ -4861,10 +5163,6 @@ goto Fail; #endif - /* we don't use raster_pool anymore. */ - library->raster_pool_size = 0; - library->raster_pool = NULL; - library->version_major = FREETYPE_MAJOR; library->version_minor = FREETYPE_MINOR; library->version_patch = FREETYPE_PATCH; @@ -4879,9 +5177,9 @@ #ifdef FT_CONFIG_OPTION_PIC Fail: ft_pic_container_destroy( library ); -#endif FT_FREE( library ); return error; +#endif } diff --git a/modules/freetype2/src/base/ftotval.c b/modules/freetype2/src/base/ftotval.c index fe54e0228..a2944a795 100644 --- a/modules/freetype2/src/base/ftotval.c +++ b/modules/freetype2/src/base/ftotval.c @@ -4,7 +4,7 @@ /* */ /* FreeType API for validating OpenType tables (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/base/ftoutln.c b/modules/freetype2/src/base/ftoutln.c index fc28225c6..cb91321de 100644 --- a/modules/freetype2/src/base/ftoutln.c +++ b/modules/freetype2/src/base/ftoutln.c @@ -4,7 +4,7 @@ /* */ /* FreeType outline management (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -286,12 +286,13 @@ FT_TRACE5(( "FT_Outline_Decompose: Done\n", n )); return FT_Err_Ok; + Invalid_Outline: + error = FT_THROW( Invalid_Outline ); + /* fall through */ + Exit: - FT_TRACE5(( "FT_Outline_Decompose: Error %d\n", error )); + FT_TRACE5(( "FT_Outline_Decompose: Error 0x%x\n", error )); return error; - - Invalid_Outline: - return FT_THROW( Invalid_Outline ); } @@ -540,8 +541,8 @@ for ( n = 0; n < outline->n_points; n++ ) { - vec->x += xOffset; - vec->y += yOffset; + vec->x = ADD_LONG( vec->x, xOffset ); + vec->y = ADD_LONG( vec->y, yOffset ); vec++; } } @@ -1088,7 +1089,8 @@ v_cur.x = points[n].x >> xshift; v_cur.y = points[n].y >> yshift; - area += ( v_cur.y - v_prev.y ) * ( v_cur.x + v_prev.x ); + area = ADD_LONG( area, + ( v_cur.y - v_prev.y ) * ( v_cur.x + v_prev.x ) ); v_prev = v_cur; } diff --git a/modules/freetype2/src/base/ftpatent.c b/modules/freetype2/src/base/ftpatent.c index 4861be130..e23ee2e3f 100644 --- a/modules/freetype2/src/base/ftpatent.c +++ b/modules/freetype2/src/base/ftpatent.c @@ -3,9 +3,9 @@ /* ftpatent.c */ /* */ /* FreeType API for checking patented TrueType bytecode instructions */ -/* (body). Obsolete, retained for backwards compatibility. */ +/* (body). Obsolete, retained for backward compatibility. */ /* */ -/* Copyright 2007-2016 by */ +/* Copyright 2007-2018 by */ /* David Turner. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/base/ftpfr.c b/modules/freetype2/src/base/ftpfr.c index 81faa529c..bfe13520e 100644 --- a/modules/freetype2/src/base/ftpfr.c +++ b/modules/freetype2/src/base/ftpfr.c @@ -4,7 +4,7 @@ /* */ /* FreeType API for accessing PFR-specific data (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/base/ftpic.c b/modules/freetype2/src/base/ftpic.c index 03769dba2..1492e1809 100644 --- a/modules/freetype2/src/base/ftpic.c +++ b/modules/freetype2/src/base/ftpic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services (body). */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2018 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/base/ftpsprop.c b/modules/freetype2/src/base/ftpsprop.c new file mode 100644 index 000000000..459b5e605 --- /dev/null +++ b/modules/freetype2/src/base/ftpsprop.c @@ -0,0 +1,285 @@ +/***************************************************************************/ +/* */ +/* ftpsprop.c */ +/* */ +/* Get and set properties of PostScript drivers (body). */ +/* See `ftdriver.h' for available properties. */ +/* */ +/* Copyright 2017-2018 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_DRIVER_H +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_POSTSCRIPT_AUX_H +#include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_POSTSCRIPT_PROPS_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_psprops + + + FT_BASE_CALLBACK_DEF( FT_Error ) + ps_property_set( FT_Module module, /* PS_Driver */ + const char* property_name, + const void* value, + FT_Bool value_is_string ) + { + FT_Error error = FT_Err_Ok; + PS_Driver driver = (PS_Driver)module; + +#ifndef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES + FT_UNUSED( value_is_string ); +#endif + + + if ( !ft_strcmp( property_name, "darkening-parameters" ) ) + { + FT_Int* darken_params; + FT_Int x1, y1, x2, y2, x3, y3, x4, y4; + +#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES + FT_Int dp[8]; + + + if ( value_is_string ) + { + const char* s = (const char*)value; + char* ep; + int i; + + + /* eight comma-separated numbers */ + for ( i = 0; i < 7; i++ ) + { + dp[i] = (FT_Int)ft_strtol( s, &ep, 10 ); + if ( *ep != ',' || s == ep ) + return FT_THROW( Invalid_Argument ); + + s = ep + 1; + } + + dp[7] = (FT_Int)ft_strtol( s, &ep, 10 ); + if ( !( *ep == '\0' || *ep == ' ' ) || s == ep ) + return FT_THROW( Invalid_Argument ); + + darken_params = dp; + } + else +#endif + darken_params = (FT_Int*)value; + + x1 = darken_params[0]; + y1 = darken_params[1]; + x2 = darken_params[2]; + y2 = darken_params[3]; + x3 = darken_params[4]; + y3 = darken_params[5]; + x4 = darken_params[6]; + y4 = darken_params[7]; + + if ( x1 < 0 || x2 < 0 || x3 < 0 || x4 < 0 || + y1 < 0 || y2 < 0 || y3 < 0 || y4 < 0 || + x1 > x2 || x2 > x3 || x3 > x4 || + y1 > 500 || y2 > 500 || y3 > 500 || y4 > 500 ) + return FT_THROW( Invalid_Argument ); + + driver->darken_params[0] = x1; + driver->darken_params[1] = y1; + driver->darken_params[2] = x2; + driver->darken_params[3] = y2; + driver->darken_params[4] = x3; + driver->darken_params[5] = y3; + driver->darken_params[6] = x4; + driver->darken_params[7] = y4; + + return error; + } + + else if ( !ft_strcmp( property_name, "hinting-engine" ) ) + { +#if defined( CFF_CONFIG_OPTION_OLD_ENGINE ) || \ + defined( T1_CONFIG_OPTION_OLD_ENGINE ) + const char* module_name = module->clazz->module_name; +#endif + + +#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES + if ( value_is_string ) + { + const char* s = (const char*)value; + + + if ( !ft_strcmp( s, "adobe" ) ) + driver->hinting_engine = FT_HINTING_ADOBE; + +#ifdef CFF_CONFIG_OPTION_OLD_ENGINE + else if ( !ft_strcmp( module_name, "cff" ) && + !ft_strcmp( s, "freetype" ) ) + driver->hinting_engine = FT_HINTING_FREETYPE; +#endif + +#ifdef T1_CONFIG_OPTION_OLD_ENGINE + else if ( ( !ft_strcmp( module_name, "type1" ) || + !ft_strcmp( module_name, "t1cid" ) ) && + !ft_strcmp( s, "freetype" ) ) + driver->hinting_engine = FT_HINTING_FREETYPE; +#endif + + else + return FT_THROW( Invalid_Argument ); + } + else +#endif /* FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES */ + { + FT_UInt* hinting_engine = (FT_UInt*)value; + + + if ( *hinting_engine == FT_HINTING_ADOBE +#ifdef CFF_CONFIG_OPTION_OLD_ENGINE + || ( *hinting_engine == FT_HINTING_FREETYPE && + !ft_strcmp( module_name, "cff" ) ) +#endif +#ifdef T1_CONFIG_OPTION_OLD_ENGINE + || ( *hinting_engine == FT_HINTING_FREETYPE && + ( !ft_strcmp( module_name, "type1" ) || + !ft_strcmp( module_name, "t1cid" ) ) ) +#endif + ) + driver->hinting_engine = *hinting_engine; + else + error = FT_ERR( Unimplemented_Feature ); + + return error; + } + } + + else if ( !ft_strcmp( property_name, "no-stem-darkening" ) ) + { +#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES + if ( value_is_string ) + { + const char* s = (const char*)value; + long nsd = ft_strtol( s, NULL, 10 ); + + + if ( !nsd ) + driver->no_stem_darkening = FALSE; + else + driver->no_stem_darkening = TRUE; + } + else +#endif + { + FT_Bool* no_stem_darkening = (FT_Bool*)value; + + + driver->no_stem_darkening = *no_stem_darkening; + } + + return error; + } + + else if ( !ft_strcmp( property_name, "random-seed" ) ) + { + FT_Int32 random_seed; + + +#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES + if ( value_is_string ) + { + const char* s = (const char*)value; + + + random_seed = (FT_Int32)ft_strtol( s, NULL, 10 ); + } + else +#endif + random_seed = *(FT_Int32*)value; + + if ( random_seed < 0 ) + random_seed = 0; + + driver->random_seed = random_seed; + + return error; + } + + FT_TRACE0(( "ps_property_set: missing property `%s'\n", + property_name )); + return FT_THROW( Missing_Property ); + } + + + FT_BASE_CALLBACK_DEF( FT_Error ) + ps_property_get( FT_Module module, /* PS_Driver */ + const char* property_name, + void* value ) + { + FT_Error error = FT_Err_Ok; + PS_Driver driver = (PS_Driver)module; + + + if ( !ft_strcmp( property_name, "darkening-parameters" ) ) + { + FT_Int* darken_params = driver->darken_params; + FT_Int* val = (FT_Int*)value; + + + val[0] = darken_params[0]; + val[1] = darken_params[1]; + val[2] = darken_params[2]; + val[3] = darken_params[3]; + val[4] = darken_params[4]; + val[5] = darken_params[5]; + val[6] = darken_params[6]; + val[7] = darken_params[7]; + + return error; + } + + else if ( !ft_strcmp( property_name, "hinting-engine" ) ) + { + FT_UInt hinting_engine = driver->hinting_engine; + FT_UInt* val = (FT_UInt*)value; + + + *val = hinting_engine; + + return error; + } + + else if ( !ft_strcmp( property_name, "no-stem-darkening" ) ) + { + FT_Bool no_stem_darkening = driver->no_stem_darkening; + FT_Bool* val = (FT_Bool*)value; + + + *val = no_stem_darkening; + + return error; + } + + FT_TRACE0(( "ps_property_get: missing property `%s'\n", + property_name )); + return FT_THROW( Missing_Property ); + } + + +/* END */ diff --git a/modules/freetype2/src/base/ftrfork.c b/modules/freetype2/src/base/ftrfork.c index eac2ddba9..c3a2b9151 100644 --- a/modules/freetype2/src/base/ftrfork.c +++ b/modules/freetype2/src/base/ftrfork.c @@ -4,7 +4,7 @@ /* */ /* Embedded resource forks accessor (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* Masatake YAMATO and Redhat K.K. */ /* */ /* FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are */ @@ -271,7 +271,13 @@ if ( FT_STREAM_SKIP( 4 ) ) /* mbz */ goto Exit; - if ( ref[j].res_id < 0 || temp < 0 ) + /* + * According to Inside Macintosh: More Macintosh Toolbox, + * "Resource IDs" (1-46), there are some reserved IDs. + * However, FreeType2 is not a font synthesizer, no need + * to check the acceptable resource ID. + */ + if ( temp < 0 ) { error = FT_THROW( Invalid_Table ); goto Exit; @@ -281,7 +287,7 @@ FT_TRACE3(( " [%d]:" " resource_id=0x%04x, offset=0x%08x\n", - j, ref[j].res_id, ref[j].offset )); + j, (FT_UShort)ref[j].res_id, ref[j].offset )); } if ( sort_by_res_id ) @@ -472,7 +478,7 @@ } -#ifndef FT_MACINTOSH +#if defined( FT_CONFIG_OPTION_MAC_FONTS ) && !defined( FT_MACINTOSH ) static FT_RFork_Rule raccess_get_rule_type_from_rule_index( FT_Library library, FT_UInt rule_index ) diff --git a/modules/freetype2/src/base/ftsnames.c b/modules/freetype2/src/base/ftsnames.c index e0d5f824d..90ea1e2be 100644 --- a/modules/freetype2/src/base/ftsnames.c +++ b/modules/freetype2/src/base/ftsnames.c @@ -7,7 +7,7 @@ /* */ /* This is _not_ used to retrieve glyph names! */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -20,6 +20,8 @@ #include <ft2build.h> +#include FT_INTERNAL_DEBUG_H + #include FT_SFNT_NAMES_H #include FT_INTERNAL_TRUETYPE_TYPES_H #include FT_INTERNAL_STREAM_H @@ -54,7 +56,7 @@ if ( idx < (FT_UInt)ttface->num_names ) { - TT_NameEntryRec* entry = ttface->name_table.names + idx; + TT_Name entry = ttface->name_table.names + idx; /* load name on demand */ @@ -88,6 +90,58 @@ } + /* documentation is in ftsnames.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Get_Sfnt_LangTag( FT_Face face, + FT_UInt langID, + FT_SfntLangTag *alangTag ) + { + FT_Error error = FT_ERR( Invalid_Argument ); + + + if ( alangTag && face && FT_IS_SFNT( face ) ) + { + TT_Face ttface = (TT_Face)face; + + + if ( ttface->name_table.format != 1 ) + return FT_THROW( Invalid_Table ); + + if ( langID > 0x8000U && + langID - 0x8000U < ttface->name_table.numLangTagRecords ) + { + TT_LangTag entry = ttface->name_table.langTags + + ( langID - 0x8000U ); + + + /* load name on demand */ + if ( entry->stringLength > 0 && !entry->string ) + { + FT_Memory memory = face->memory; + FT_Stream stream = face->stream; + + + if ( FT_NEW_ARRAY ( entry->string, entry->stringLength ) || + FT_STREAM_SEEK( entry->stringOffset ) || + FT_STREAM_READ( entry->string, entry->stringLength ) ) + { + FT_FREE( entry->string ); + entry->stringLength = 0; + } + } + + alangTag->string = (FT_Byte*)entry->string; + alangTag->string_len = entry->stringLength; + + error = FT_Err_Ok; + } + } + + return error; + } + + #endif /* TT_CONFIG_OPTION_SFNT_NAMES */ diff --git a/modules/freetype2/src/base/ftstream.c b/modules/freetype2/src/base/ftstream.c index bb512a7cc..18df7dcfe 100644 --- a/modules/freetype2/src/base/ftstream.c +++ b/modules/freetype2/src/base/ftstream.c @@ -4,7 +4,7 @@ /* */ /* I/O stream support (body). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/base/ftstroke.c b/modules/freetype2/src/base/ftstroke.c index 4f3c4937b..6ae181906 100644 --- a/modules/freetype2/src/base/ftstroke.c +++ b/modules/freetype2/src/base/ftstroke.c @@ -4,7 +4,7 @@ /* */ /* FreeType path stroker (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/base/ftsynth.c b/modules/freetype2/src/base/ftsynth.c index 4b66a33c3..c28346707 100644 --- a/modules/freetype2/src/base/ftsynth.c +++ b/modules/freetype2/src/base/ftsynth.c @@ -4,7 +4,7 @@ /* */ /* FreeType synthesizing code for emboldening and slanting (body). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -123,14 +123,14 @@ /* * XXX: overflow check for 16-bit system, for compatibility - * with FT_GlyphSlot_Embolden() since freetype-2.1.10. + * with FT_GlyphSlot_Embolden() since FreeType 2.1.10. * unfortunately, this function return no informations * about the cause of error. */ if ( ( ystr >> 6 ) > FT_INT_MAX || ( ystr >> 6 ) < FT_INT_MIN ) { FT_TRACE1(( "FT_GlyphSlot_Embolden:" )); - FT_TRACE1(( "too strong embolding parameter ystr=%d\n", ystr )); + FT_TRACE1(( "too strong emboldening parameter ystr=%d\n", ystr )); return; } error = FT_GlyphSlot_Own_Bitmap( slot ); diff --git a/modules/freetype2/src/base/ftsystem.c b/modules/freetype2/src/base/ftsystem.c index ac1f01c8b..6adebdb93 100644 --- a/modules/freetype2/src/base/ftsystem.c +++ b/modules/freetype2/src/base/ftsystem.c @@ -4,7 +4,7 @@ /* */ /* ANSI-specific FreeType low-level system interface (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/base/fttrigon.c b/modules/freetype2/src/base/fttrigon.c index 7b582c8a3..d6dd098c4 100644 --- a/modules/freetype2/src/base/fttrigon.c +++ b/modules/freetype2/src/base/fttrigon.c @@ -4,7 +4,7 @@ /* */ /* FreeType trigonometric functions (body). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/base/fttype1.c b/modules/freetype2/src/base/fttype1.c index 5c0fce868..aa8f8ccbb 100644 --- a/modules/freetype2/src/base/fttype1.c +++ b/modules/freetype2/src/base/fttype1.c @@ -4,7 +4,7 @@ /* */ /* FreeType utility file for PS names support (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/base/ftutil.c b/modules/freetype2/src/base/ftutil.c index 36d2dd721..4de5f2c14 100644 --- a/modules/freetype2/src/base/ftutil.c +++ b/modules/freetype2/src/base/ftutil.c @@ -4,7 +4,7 @@ /* */ /* FreeType utility file for memory and list management (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -135,7 +135,7 @@ ft_mem_free( memory, block ); block = NULL; } - else if ( new_count > FT_INT_MAX/item_size ) + else if ( new_count > FT_INT_MAX / item_size ) { error = FT_THROW( Array_Too_Large ); } @@ -143,13 +143,15 @@ { FT_ASSERT( !block ); - block = ft_mem_alloc( memory, new_count*item_size, &error ); + block = memory->alloc( memory, new_count * item_size ); + if ( block == NULL ) + error = FT_THROW( Out_Of_Memory ); } else { FT_Pointer block2; - FT_Long cur_size = cur_count*item_size; - FT_Long new_size = new_count*item_size; + FT_Long cur_size = cur_count * item_size; + FT_Long new_size = new_count * item_size; block2 = memory->realloc( memory, cur_size, new_size, block ); diff --git a/modules/freetype2/src/base/ftver.rc b/modules/freetype2/src/base/ftver.rc new file mode 100644 index 000000000..a2903d588 --- /dev/null +++ b/modules/freetype2/src/base/ftver.rc @@ -0,0 +1,61 @@ +/***************************************************************************/ +/* */ +/* ftver.rc */ +/* */ +/* FreeType VERSIONINFO resource for Windows DLLs. */ +/* */ +/* Copyright 2018 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<windows.h> + +#define FT_VERSION 2,9,1,0 +#define FT_VERSION_STR "2.9.1" + +VS_VERSION_INFO VERSIONINFO +FILEVERSION FT_VERSION +PRODUCTVERSION FT_VERSION +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG +FILEFLAGS VS_FF_DEBUG +#endif +#ifdef _DLL +FILETYPE VFT_DLL +#define FT_FILENAME "freetype.dll" +#else +FILETYPE VFT_STATIC_LIB +#define FT_FILENAME "freetype.lib" +#endif +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "CompanyName", "The FreeType Project" + VALUE "FileDescription", "Font Rendering Library" + VALUE "FileVersion", FT_VERSION_STR + VALUE "ProductName", "FreeType" + VALUE "ProductVersion", FT_VERSION_STR + VALUE "LegalCopyright", "\251 2018 The FreeType Project www.freetype.org. All rights reserved." + VALUE "InternalName", "freetype" + VALUE "OriginalFilename", FT_FILENAME + END + END + + BLOCK "VarFileInfo" + BEGIN + /* The following line should only be modified for localized versions. */ + /* It consists of any number of WORD,WORD pairs, with each pair */ + /* describing a "language,codepage" combination supported by the file. */ + VALUE "Translation", 0x409, 1252 + END +END diff --git a/modules/freetype2/src/base/ftwinfnt.c b/modules/freetype2/src/base/ftwinfnt.c index 89e915509..11bd28afb 100644 --- a/modules/freetype2/src/base/ftwinfnt.c +++ b/modules/freetype2/src/base/ftwinfnt.c @@ -4,7 +4,7 @@ /* */ /* FreeType API for accessing Windows FNT specific info (body). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/base/rules.mk b/modules/freetype2/src/base/rules.mk index aa424c546..e9805bd06 100644 --- a/modules/freetype2/src/base/rules.mk +++ b/modules/freetype2/src/base/rules.mk @@ -3,7 +3,7 @@ # -# Copyright 1996-2016 by +# Copyright 1996-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, @@ -40,11 +40,14 @@ BASE_SRC := $(BASE_DIR)/basepic.c \ $(BASE_DIR)/ftadvanc.c \ $(BASE_DIR)/ftcalc.c \ $(BASE_DIR)/ftdbgmem.c \ + $(BASE_DIR)/ftfntfmt.c \ $(BASE_DIR)/ftgloadr.c \ $(BASE_DIR)/fthash.c \ + $(BASE_DIR)/ftlcdfil.c \ $(BASE_DIR)/ftobjs.c \ $(BASE_DIR)/ftoutln.c \ $(BASE_DIR)/ftpic.c \ + $(BASE_DIR)/ftpsprop.c \ $(BASE_DIR)/ftrfork.c \ $(BASE_DIR)/ftsnames.c \ $(BASE_DIR)/ftstream.c \ diff --git a/modules/freetype2/src/bdf/Jamfile b/modules/freetype2/src/bdf/Jamfile index 2f0147bbb..d9e441c18 100644 --- a/modules/freetype2/src/bdf/Jamfile +++ b/modules/freetype2/src/bdf/Jamfile @@ -1,6 +1,6 @@ # FreeType 2 src/bdf Jamfile # -# Copyright 2002-2016 by +# Copyright 2002-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/bdf/README b/modules/freetype2/src/bdf/README index b761aba2b..996ac2d2a 100644 --- a/modules/freetype2/src/bdf/README +++ b/modules/freetype2/src/bdf/README @@ -13,7 +13,7 @@ This code implements a BDF driver for the FreeType library, following the Adobe Specification V 2.2. The specification of the BDF font format is available from Adobe's web site: - http://partners.adobe.com/public/developer/en/font/5005.BDF_Spec.pdf + https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5005.BDF_Spec.pdf Many good bitmap fonts in bdf format come with XFree86 (www.XFree86.org). They do not define vertical metrics, because the X Consortium BDF diff --git a/modules/freetype2/src/bdf/bdf.c b/modules/freetype2/src/bdf/bdf.c index f95fb7622..e54df6649 100644 --- a/modules/freetype2/src/bdf/bdf.c +++ b/modules/freetype2/src/bdf/bdf.c @@ -24,9 +24,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#define FT_MAKE_OPTION_SINGLE_OBJECT +#define FT_MAKE_OPTION_SINGLE_OBJECT #include <ft2build.h> + #include "bdflib.c" #include "bdfdrivr.c" diff --git a/modules/freetype2/src/bdf/bdfdrivr.c b/modules/freetype2/src/bdf/bdfdrivr.c index a2242be01..ca937f89c 100644 --- a/modules/freetype2/src/bdf/bdfdrivr.c +++ b/modules/freetype2/src/bdf/bdfdrivr.c @@ -373,7 +373,7 @@ THE SOFTWARE. /* we have a bdf font: let's construct the face object */ face->bdffont = font; - /* BDF could not have multiple face in single font file. + /* BDF cannot have multiple faces in a single font file. * XXX: non-zero face_index is already invalid argument, but * Type1, Type42 driver has a convention to return * an invalid argument error when the font could be @@ -437,46 +437,156 @@ THE SOFTWARE. { FT_Bitmap_Size* bsize = bdfface->available_sizes; FT_Short resolution_x = 0, resolution_y = 0; + long value; FT_ZERO( bsize ); + /* sanity checks */ + if ( font->font_ascent > 0x7FFF || font->font_ascent < -0x7FFF ) + { + font->font_ascent = font->font_ascent < 0 ? -0x7FFF : 0x7FFF; + FT_TRACE0(( "BDF_Face_Init: clamping font ascent to value %d\n", + font->font_ascent )); + } + if ( font->font_descent > 0x7FFF || font->font_descent < -0x7FFF ) + { + font->font_descent = font->font_descent < 0 ? -0x7FFF : 0x7FFF; + FT_TRACE0(( "BDF_Face_Init: clamping font descent to value %d\n", + font->font_descent )); + } + bsize->height = (FT_Short)( font->font_ascent + font->font_descent ); prop = bdf_get_font_property( font, "AVERAGE_WIDTH" ); if ( prop ) - bsize->width = (FT_Short)( ( prop->value.l + 5 ) / 10 ); + { +#ifdef FT_DEBUG_LEVEL_TRACE + if ( prop->value.l < 0 ) + FT_TRACE0(( "BDF_Face_Init: negative average width\n" )); +#endif + if ( prop->value.l > 0x7FFFL * 10 - 5 || + prop->value.l < -( 0x7FFFL * 10 - 5 ) ) + { + bsize->width = 0x7FFF; + FT_TRACE0(( "BDF_Face_Init: clamping average width to value %d\n", + bsize->width )); + } + else + bsize->width = FT_ABS( (FT_Short)( ( prop->value.l + 5 ) / 10 ) ); + } else - bsize->width = (FT_Short)( bsize->height * 2/3 ); + { + /* this is a heuristical value */ + bsize->width = (FT_Short)FT_MulDiv( bsize->height, 2, 3 ); + } prop = bdf_get_font_property( font, "POINT_SIZE" ); if ( prop ) + { +#ifdef FT_DEBUG_LEVEL_TRACE + if ( prop->value.l < 0 ) + FT_TRACE0(( "BDF_Face_Init: negative point size\n" )); +#endif /* convert from 722.7 decipoints to 72 points per inch */ - bsize->size = - (FT_Pos)( ( prop->value.l * 64 * 7200 + 36135L ) / 72270L ); + if ( prop->value.l > 0x504C2L || /* 0x7FFF * 72270/7200 */ + prop->value.l < -0x504C2L ) + { + bsize->size = 0x7FFF; + FT_TRACE0(( "BDF_Face_Init: clamping point size to value %d\n", + bsize->size )); + } + else + bsize->size = FT_MulDiv( FT_ABS( prop->value.l ), + 64 * 7200, + 72270L ); + } + else if ( font->point_size ) + { + if ( font->point_size > 0x7FFF ) + { + bsize->size = 0x7FFF; + FT_TRACE0(( "BDF_Face_Init: clamping point size to value %d\n", + bsize->size )); + } + else + bsize->size = (FT_Pos)font->point_size << 6; + } else - bsize->size = bsize->width << 6; + { + /* this is a heuristical value */ + bsize->size = bsize->width * 64; + } prop = bdf_get_font_property( font, "PIXEL_SIZE" ); if ( prop ) - bsize->y_ppem = (FT_Short)prop->value.l << 6; + { +#ifdef FT_DEBUG_LEVEL_TRACE + if ( prop->value.l < 0 ) + FT_TRACE0(( "BDF_Face_Init: negative pixel size\n" )); +#endif + if ( prop->value.l > 0x7FFF || prop->value.l < -0x7FFF ) + { + bsize->y_ppem = 0x7FFF << 6; + FT_TRACE0(( "BDF_Face_Init: clamping pixel size to value %d\n", + bsize->y_ppem )); + } + else + bsize->y_ppem = FT_ABS( (FT_Short)prop->value.l ) << 6; + } prop = bdf_get_font_property( font, "RESOLUTION_X" ); if ( prop ) - resolution_x = (FT_Short)prop->value.l; + value = prop->value.l; + else + value = (long)font->resolution_x; + if ( value ) + { +#ifdef FT_DEBUG_LEVEL_TRACE + if ( value < 0 ) + FT_TRACE0(( "BDF_Face_Init: negative X resolution\n" )); +#endif + if ( value > 0x7FFF || value < -0x7FFF ) + { + resolution_x = 0x7FFF; + FT_TRACE0(( "BDF_Face_Init: clamping X resolution to value %d\n", + resolution_x )); + } + else + resolution_x = FT_ABS( (FT_Short)value ); + } prop = bdf_get_font_property( font, "RESOLUTION_Y" ); if ( prop ) - resolution_y = (FT_Short)prop->value.l; + value = prop->value.l; + else + value = (long)font->resolution_y; + if ( value ) + { +#ifdef FT_DEBUG_LEVEL_TRACE + if ( value < 0 ) + FT_TRACE0(( "BDF_Face_Init: negative Y resolution\n" )); +#endif + if ( value > 0x7FFF || value < -0x7FFF ) + { + resolution_y = 0x7FFF; + FT_TRACE0(( "BDF_Face_Init: clamping Y resolution to value %d\n", + resolution_y )); + } + else + resolution_y = FT_ABS( (FT_Short)value ); + } if ( bsize->y_ppem == 0 ) { bsize->y_ppem = bsize->size; if ( resolution_y ) - bsize->y_ppem = bsize->y_ppem * resolution_y / 72; + bsize->y_ppem = FT_MulDiv( bsize->y_ppem, resolution_y, 72 ); } if ( resolution_x && resolution_y ) - bsize->x_ppem = bsize->y_ppem * resolution_x / resolution_y; + bsize->x_ppem = FT_MulDiv( bsize->y_ppem, + resolution_x, + resolution_y ); else bsize->x_ppem = bsize->y_ppem; } @@ -545,7 +655,11 @@ THE SOFTWARE. if ( !ft_strcmp( s, "10646" ) || ( !ft_strcmp( s, "8859" ) && !ft_strcmp( face->charset_encoding, "1" ) ) ) - unicode_charmap = 1; + unicode_charmap = 1; + /* another name for ASCII */ + else if ( !ft_strcmp( s, "646.1991" ) && + !ft_strcmp( face->charset_encoding, "IRV" ) ) + unicode_charmap = 1; } { @@ -566,12 +680,6 @@ THE SOFTWARE. } error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL ); - -#if 0 - /* Select default charmap */ - if ( bdfface->num_charmaps ) - bdfface->charmap = bdfface->charmaps[0]; -#endif } goto Exit; @@ -705,7 +813,7 @@ THE SOFTWARE. bitmap->rows = glyph.bbx.height; bitmap->width = glyph.bbx.width; - if ( glyph.bpr > INT_MAX ) + if ( glyph.bpr > FT_INT_MAX ) FT_TRACE1(( "BDF_Glyph_Load: too large pitch %d is truncated\n", glyph.bpr )); bitmap->pitch = (int)glyph.bpr; /* same as FT_Bitmap.pitch */ diff --git a/modules/freetype2/src/bdf/bdflib.c b/modules/freetype2/src/bdf/bdflib.c index 7fd95a738..2f5c99d54 100644 --- a/modules/freetype2/src/bdf/bdflib.c +++ b/modules/freetype2/src/bdf/bdflib.c @@ -704,7 +704,15 @@ return 0; for ( v = 0; sbitset( ddigits, *s ); s++ ) - v = v * 10 + a2i[(int)*s]; + { + if ( v < ( FT_ULONG_MAX - 9 ) / 10 ) + v = v * 10 + a2i[(int)*s]; + else + { + v = FT_ULONG_MAX; + break; + } + } return v; } @@ -729,7 +737,15 @@ } for ( v = 0; sbitset( ddigits, *s ); s++ ) - v = v * 10 + a2i[(int)*s]; + { + if ( v < ( FT_LONG_MAX - 9 ) / 10 ) + v = v * 10 + a2i[(int)*s]; + else + { + v = FT_LONG_MAX; + break; + } + } return ( !neg ) ? v : -v; } @@ -746,7 +762,15 @@ return 0; for ( v = 0; sbitset( ddigits, *s ); s++ ) - v = (unsigned short)( v * 10 + a2i[(int)*s] ); + { + if ( v < ( FT_USHORT_MAX - 9 ) / 10 ) + v = (unsigned short)( v * 10 + a2i[(int)*s] ); + else + { + v = FT_USHORT_MAX; + break; + } + } return v; } @@ -771,7 +795,15 @@ } for ( v = 0; sbitset( ddigits, *s ); s++ ) - v = (short)( v * 10 + a2i[(int)*s] ); + { + if ( v < ( SHRT_MAX - 9 ) / 10 ) + v = (short)( v * 10 + a2i[(int)*s] ); + else + { + v = SHRT_MAX; + break; + } + } return (short)( ( !neg ) ? v : -v ); } diff --git a/modules/freetype2/src/bzip2/Jamfile b/modules/freetype2/src/bzip2/Jamfile index 5c28f7e53..3548eab59 100644 --- a/modules/freetype2/src/bzip2/Jamfile +++ b/modules/freetype2/src/bzip2/Jamfile @@ -1,6 +1,6 @@ # FreeType 2 src/bzip2 Jamfile # -# Copyright 2010-2016 by +# Copyright 2010-2018 by # Joel Klinghed # # based on `src/lzw/Jamfile' diff --git a/modules/freetype2/src/bzip2/ftbzip2.c b/modules/freetype2/src/bzip2/ftbzip2.c index 4d0b388d6..16019485a 100644 --- a/modules/freetype2/src/bzip2/ftbzip2.c +++ b/modules/freetype2/src/bzip2/ftbzip2.c @@ -8,7 +8,7 @@ /* parse compressed PCF fonts, as found with many X11 server */ /* distributions. */ /* */ -/* Copyright 2010-2016 by */ +/* Copyright 2010-2018 by */ /* Joel Klinghed. */ /* */ /* based on `src/gzip/ftgzip.c' */ diff --git a/modules/freetype2/src/bzip2/rules.mk b/modules/freetype2/src/bzip2/rules.mk index 68b17633d..95954d752 100644 --- a/modules/freetype2/src/bzip2/rules.mk +++ b/modules/freetype2/src/bzip2/rules.mk @@ -2,7 +2,7 @@ # FreeType 2 BZIP2 support configuration rules # -# Copyright 2010-2016 by +# Copyright 2010-2018 by # Joel Klinghed. # # based on `src/lzw/rules.mk' diff --git a/modules/freetype2/src/cache/Jamfile b/modules/freetype2/src/cache/Jamfile index da6551015..53f4c7b60 100644 --- a/modules/freetype2/src/cache/Jamfile +++ b/modules/freetype2/src/cache/Jamfile @@ -1,6 +1,6 @@ # FreeType 2 src/cache Jamfile # -# Copyright 2001-2016 by +# Copyright 2001-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/cache/ftcache.c b/modules/freetype2/src/cache/ftcache.c index 50941df4c..1b425af91 100644 --- a/modules/freetype2/src/cache/ftcache.c +++ b/modules/freetype2/src/cache/ftcache.c @@ -4,7 +4,7 @@ /* */ /* The FreeType Caching sub-system (body only). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,15 +17,16 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT - #include <ft2build.h> -#include "ftcmru.c" -#include "ftcmanag.c" + +#include "ftcbasic.c" #include "ftccache.c" #include "ftccmap.c" #include "ftcglyph.c" #include "ftcimage.c" +#include "ftcmanag.c" +#include "ftcmru.c" #include "ftcsbits.c" -#include "ftcbasic.c" + /* END */ diff --git a/modules/freetype2/src/cache/ftcbasic.c b/modules/freetype2/src/cache/ftcbasic.c index fc8905c95..994aa1228 100644 --- a/modules/freetype2/src/cache/ftcbasic.c +++ b/modules/freetype2/src/cache/ftcbasic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType basic cache interface (body). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -304,10 +304,18 @@ if ( anode ) *anode = NULL; - if ( (FT_ULong)( type->flags - FT_INT_MIN ) > FT_UINT_MAX ) + /* + * Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt', + * but public `FT_ImageType->flags' is of type `FT_Int32'. + * + * On 16bit systems, higher bits of type->flags cannot be handled. + */ +#if 0xFFFFFFFFUL > FT_UINT_MAX + if ( (type->flags & (FT_ULong)FT_UINT_MAX) ) FT_TRACE1(( "FTC_ImageCache_Lookup:" " higher bits in load_flags 0x%x are dropped\n", (FT_ULong)type->flags & ~((FT_ULong)FT_UINT_MAX) )); +#endif query.attrs.scaler.face_id = type->face_id; query.attrs.scaler.width = type->width; @@ -377,11 +385,18 @@ if ( anode ) *anode = NULL; - /* `FT_Load_Glyph' and `FT_Load_Char' take FT_UInt flags */ + /* + * Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt', + * but public `FT_Face->face_flags' is of type `FT_Long'. + * + * On long > int systems, higher bits of load_flags cannot be handled. + */ +#if FT_ULONG_MAX > FT_UINT_MAX if ( load_flags > FT_UINT_MAX ) FT_TRACE1(( "FTC_ImageCache_LookupScaler:" " higher bits in load_flags 0x%x are dropped\n", load_flags & ~((FT_ULong)FT_UINT_MAX) )); +#endif query.attrs.scaler = scaler[0]; query.attrs.load_flags = (FT_UInt)load_flags; @@ -487,10 +502,18 @@ *ansbit = NULL; - if ( (FT_ULong)( type->flags - FT_INT_MIN ) > FT_UINT_MAX ) + /* + * Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt', + * but public `FT_ImageType->flags' is of type `FT_Int32'. + * + * On 16bit systems, higher bits of type->flags cannot be handled. + */ +#if 0xFFFFFFFFUL > FT_UINT_MAX + if ( (type->flags & (FT_ULong)FT_UINT_MAX) ) FT_TRACE1(( "FTC_ImageCache_Lookup:" " higher bits in load_flags 0x%x are dropped\n", (FT_ULong)type->flags & ~((FT_ULong)FT_UINT_MAX) )); +#endif query.attrs.scaler.face_id = type->face_id; query.attrs.scaler.width = type->width; @@ -562,11 +585,18 @@ *ansbit = NULL; - /* `FT_Load_Glyph' and `FT_Load_Char' take FT_UInt flags */ + /* + * Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt', + * but public `FT_Face->face_flags' is of type `FT_Long'. + * + * On long > int systems, higher bits of load_flags cannot be handled. + */ +#if FT_ULONG_MAX > FT_UINT_MAX if ( load_flags > FT_UINT_MAX ) FT_TRACE1(( "FTC_ImageCache_LookupScaler:" " higher bits in load_flags 0x%x are dropped\n", load_flags & ~((FT_ULong)FT_UINT_MAX) )); +#endif query.attrs.scaler = scaler[0]; query.attrs.load_flags = (FT_UInt)load_flags; diff --git a/modules/freetype2/src/cache/ftccache.c b/modules/freetype2/src/cache/ftccache.c index de2025533..12ec585a2 100644 --- a/modules/freetype2/src/cache/ftccache.c +++ b/modules/freetype2/src/cache/ftccache.c @@ -4,7 +4,7 @@ /* */ /* The FreeType internal cache interface (body). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cache/ftccache.h b/modules/freetype2/src/cache/ftccache.h index ab4ea5124..859c547e4 100644 --- a/modules/freetype2/src/cache/ftccache.h +++ b/modules/freetype2/src/cache/ftccache.h @@ -4,7 +4,7 @@ /* */ /* FreeType internal cache interface (specification). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cache/ftccback.h b/modules/freetype2/src/cache/ftccback.h index 279e94d92..e51d8d6e5 100644 --- a/modules/freetype2/src/cache/ftccback.h +++ b/modules/freetype2/src/cache/ftccback.h @@ -4,7 +4,7 @@ /* */ /* Callback functions of the caching sub-system (specification only). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cache/ftccmap.c b/modules/freetype2/src/cache/ftccmap.c index f0a85f9c5..d20b0f48f 100644 --- a/modules/freetype2/src/cache/ftccmap.c +++ b/modules/freetype2/src/cache/ftccmap.c @@ -4,7 +4,7 @@ /* */ /* FreeType CharMap cache (body) */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cache/ftcerror.h b/modules/freetype2/src/cache/ftcerror.h index 1fd7357a8..a26cd5935 100644 --- a/modules/freetype2/src/cache/ftcerror.h +++ b/modules/freetype2/src/cache/ftcerror.h @@ -4,7 +4,7 @@ /* */ /* Caching sub-system error codes (specification only). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cache/ftcglyph.c b/modules/freetype2/src/cache/ftcglyph.c index c4046812d..782cc0ed0 100644 --- a/modules/freetype2/src/cache/ftcglyph.c +++ b/modules/freetype2/src/cache/ftcglyph.c @@ -4,7 +4,7 @@ /* */ /* FreeType Glyph Image (FT_Glyph) cache (body). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cache/ftcglyph.h b/modules/freetype2/src/cache/ftcglyph.h index dc7be06f0..23c24d223 100644 --- a/modules/freetype2/src/cache/ftcglyph.h +++ b/modules/freetype2/src/cache/ftcglyph.h @@ -4,7 +4,7 @@ /* */ /* FreeType abstract glyph cache (specification). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cache/ftcimage.c b/modules/freetype2/src/cache/ftcimage.c index 74040aa74..77a100153 100644 --- a/modules/freetype2/src/cache/ftcimage.c +++ b/modules/freetype2/src/cache/ftcimage.c @@ -4,7 +4,7 @@ /* */ /* FreeType Image cache (body). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cache/ftcimage.h b/modules/freetype2/src/cache/ftcimage.h index 25aa43b97..24a221053 100644 --- a/modules/freetype2/src/cache/ftcimage.h +++ b/modules/freetype2/src/cache/ftcimage.h @@ -4,7 +4,7 @@ /* */ /* FreeType Generic Image cache (specification) */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cache/ftcmanag.c b/modules/freetype2/src/cache/ftcmanag.c index 9a25b9772..2bcd9df50 100644 --- a/modules/freetype2/src/cache/ftcmanag.c +++ b/modules/freetype2/src/cache/ftcmanag.c @@ -4,7 +4,7 @@ /* */ /* FreeType Cache Manager (body). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cache/ftcmanag.h b/modules/freetype2/src/cache/ftcmanag.h index f2c434a13..b4b475535 100644 --- a/modules/freetype2/src/cache/ftcmanag.h +++ b/modules/freetype2/src/cache/ftcmanag.h @@ -4,7 +4,7 @@ /* */ /* FreeType Cache Manager (specification). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cache/ftcmru.c b/modules/freetype2/src/cache/ftcmru.c index 7c460b928..1087be4d8 100644 --- a/modules/freetype2/src/cache/ftcmru.c +++ b/modules/freetype2/src/cache/ftcmru.c @@ -4,7 +4,7 @@ /* */ /* FreeType MRU support (body). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cache/ftcmru.h b/modules/freetype2/src/cache/ftcmru.h index 27ad55aa0..82396b917 100644 --- a/modules/freetype2/src/cache/ftcmru.h +++ b/modules/freetype2/src/cache/ftcmru.h @@ -4,7 +4,7 @@ /* */ /* Simple MRU list-cache (specification). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cache/ftcsbits.c b/modules/freetype2/src/cache/ftcsbits.c index 78cd8de82..018f1ecdb 100644 --- a/modules/freetype2/src/cache/ftcsbits.c +++ b/modules/freetype2/src/cache/ftcsbits.c @@ -4,7 +4,7 @@ /* */ /* FreeType sbits manager (body). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cache/ftcsbits.h b/modules/freetype2/src/cache/ftcsbits.h index a0600ede0..206a1bb3f 100644 --- a/modules/freetype2/src/cache/ftcsbits.h +++ b/modules/freetype2/src/cache/ftcsbits.h @@ -4,7 +4,7 @@ /* */ /* A small-bitmap cache (specification). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cache/rules.mk b/modules/freetype2/src/cache/rules.mk index 827e259f9..558935976 100644 --- a/modules/freetype2/src/cache/rules.mk +++ b/modules/freetype2/src/cache/rules.mk @@ -3,7 +3,7 @@ # -# Copyright 2000-2016 by +# Copyright 2000-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/cff/Jamfile b/modules/freetype2/src/cff/Jamfile index 8067e6b29..53c904fcf 100644 --- a/modules/freetype2/src/cff/Jamfile +++ b/modules/freetype2/src/cff/Jamfile @@ -1,6 +1,6 @@ # FreeType 2 src/cff Jamfile # -# Copyright 2001-2016 by +# Copyright 2001-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, @@ -23,15 +23,6 @@ SubDir FT2_TOP $(FT2_SRC_DIR) cff ; cffobjs cffparse cffpic - cf2arrst - cf2blues - cf2error - cf2font - cf2ft - cf2hints - cf2intrp - cf2read - cf2stack ; } else diff --git a/modules/freetype2/src/cff/cf2intrp.c b/modules/freetype2/src/cff/cf2intrp.c deleted file mode 100644 index 6bf298a4d..000000000 --- a/modules/freetype2/src/cff/cf2intrp.c +++ /dev/null @@ -1,1913 +0,0 @@ -/***************************************************************************/ -/* */ -/* cf2intrp.c */ -/* */ -/* Adobe's CFF Interpreter (body). */ -/* */ -/* Copyright 2007-2014 Adobe Systems Incorporated. */ -/* */ -/* This software, and all works of authorship, whether in source or */ -/* object code form as indicated by the copyright notice(s) included */ -/* herein (collectively, the "Work") is made available, and may only be */ -/* used, modified, and distributed under the FreeType Project License, */ -/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */ -/* FreeType Project License, each contributor to the Work hereby grants */ -/* to any individual or legal entity exercising permissions granted by */ -/* the FreeType Project License and this section (hereafter, "You" or */ -/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */ -/* royalty-free, irrevocable (except as stated in this section) patent */ -/* license to make, have made, use, offer to sell, sell, import, and */ -/* otherwise transfer the Work, where such license applies only to those */ -/* patent claims licensable by such contributor that are necessarily */ -/* infringed by their contribution(s) alone or by combination of their */ -/* contribution(s) with the Work to which such contribution(s) was */ -/* submitted. If You institute patent litigation against any entity */ -/* (including a cross-claim or counterclaim in a lawsuit) alleging that */ -/* the Work or a contribution incorporated within the Work constitutes */ -/* direct or contributory patent infringement, then any patent licenses */ -/* granted to You under this License for that Work shall terminate as of */ -/* the date such litigation is filed. */ -/* */ -/* By using, modifying, or distributing the Work you indicate that you */ -/* have read and understood the terms and conditions of the */ -/* FreeType Project License as well as those provided in this section, */ -/* and you accept them fully. */ -/* */ -/***************************************************************************/ - - -#include "cf2ft.h" -#include FT_INTERNAL_DEBUG_H - -#include "cf2glue.h" -#include "cf2font.h" -#include "cf2stack.h" -#include "cf2hints.h" -#include "cf2intrp.h" - -#include "cf2error.h" - -#include "cffload.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_cf2interp - - - /* some operators are not implemented yet */ -#define CF2_FIXME FT_TRACE4(( "cf2_interpT2CharString:" \ - " operator not implemented yet\n" )) - - - - FT_LOCAL_DEF( void ) - cf2_hintmask_init( CF2_HintMask hintmask, - FT_Error* error ) - { - FT_ZERO( hintmask ); - - hintmask->error = error; - } - - - FT_LOCAL_DEF( FT_Bool ) - cf2_hintmask_isValid( const CF2_HintMask hintmask ) - { - return hintmask->isValid; - } - - - FT_LOCAL_DEF( FT_Bool ) - cf2_hintmask_isNew( const CF2_HintMask hintmask ) - { - return hintmask->isNew; - } - - - FT_LOCAL_DEF( void ) - cf2_hintmask_setNew( CF2_HintMask hintmask, - FT_Bool val ) - { - hintmask->isNew = val; - } - - - /* clients call `getMaskPtr' in order to iterate */ - /* through hint mask */ - - FT_LOCAL_DEF( FT_Byte* ) - cf2_hintmask_getMaskPtr( CF2_HintMask hintmask ) - { - return hintmask->mask; - } - - - static size_t - cf2_hintmask_setCounts( CF2_HintMask hintmask, - size_t bitCount ) - { - if ( bitCount > CF2_MAX_HINTS ) - { - /* total of h and v stems must be <= 96 */ - CF2_SET_ERROR( hintmask->error, Invalid_Glyph_Format ); - return 0; - } - - hintmask->bitCount = bitCount; - hintmask->byteCount = ( hintmask->bitCount + 7 ) / 8; - - hintmask->isValid = TRUE; - hintmask->isNew = TRUE; - - return bitCount; - } - - - /* consume the hintmask bytes from the charstring, advancing the src */ - /* pointer */ - static void - cf2_hintmask_read( CF2_HintMask hintmask, - CF2_Buffer charstring, - size_t bitCount ) - { - size_t i; - -#ifndef CF2_NDEBUG - /* these are the bits in the final mask byte that should be zero */ - /* Note: this variable is only used in an assert expression below */ - /* and then only if CF2_NDEBUG is not defined */ - CF2_UInt mask = ( 1 << ( -(CF2_Int)bitCount & 7 ) ) - 1; -#endif - - - /* initialize counts and isValid */ - if ( cf2_hintmask_setCounts( hintmask, bitCount ) == 0 ) - return; - - FT_ASSERT( hintmask->byteCount > 0 ); - - FT_TRACE4(( " (maskbytes:" )); - - /* set mask and advance interpreter's charstring pointer */ - for ( i = 0; i < hintmask->byteCount; i++ ) - { - hintmask->mask[i] = (FT_Byte)cf2_buf_readByte( charstring ); - FT_TRACE4(( " 0x%02X", hintmask->mask[i] )); - } - - FT_TRACE4(( ")\n" )); - - /* assert any unused bits in last byte are zero unless there's a prior */ - /* error */ - /* bitCount -> mask, 0 -> 0, 1 -> 7f, 2 -> 3f, ... 6 -> 3, 7 -> 1 */ -#ifndef CF2_NDEBUG - FT_ASSERT( ( hintmask->mask[hintmask->byteCount - 1] & mask ) == 0 || - *hintmask->error ); -#endif - } - - - FT_LOCAL_DEF( void ) - cf2_hintmask_setAll( CF2_HintMask hintmask, - size_t bitCount ) - { - size_t i; - CF2_UInt mask = ( 1 << ( -(CF2_Int)bitCount & 7 ) ) - 1; - - - /* initialize counts and isValid */ - if ( cf2_hintmask_setCounts( hintmask, bitCount ) == 0 ) - return; - - FT_ASSERT( hintmask->byteCount > 0 ); - FT_ASSERT( hintmask->byteCount <= - sizeof ( hintmask->mask ) / sizeof ( hintmask->mask[0] ) ); - - /* set mask to all ones */ - for ( i = 0; i < hintmask->byteCount; i++ ) - hintmask->mask[i] = 0xFF; - - /* clear unused bits */ - /* bitCount -> mask, 0 -> 0, 1 -> 7f, 2 -> 3f, ... 6 -> 3, 7 -> 1 */ - hintmask->mask[hintmask->byteCount - 1] &= ~mask; - } - - - /* Type2 charstring opcodes */ - enum - { - cf2_cmdRESERVED_0, /* 0 */ - cf2_cmdHSTEM, /* 1 */ - cf2_cmdRESERVED_2, /* 2 */ - cf2_cmdVSTEM, /* 3 */ - cf2_cmdVMOVETO, /* 4 */ - cf2_cmdRLINETO, /* 5 */ - cf2_cmdHLINETO, /* 6 */ - cf2_cmdVLINETO, /* 7 */ - cf2_cmdRRCURVETO, /* 8 */ - cf2_cmdRESERVED_9, /* 9 */ - cf2_cmdCALLSUBR, /* 10 */ - cf2_cmdRETURN, /* 11 */ - cf2_cmdESC, /* 12 */ - cf2_cmdRESERVED_13, /* 13 */ - cf2_cmdENDCHAR, /* 14 */ - cf2_cmdVSINDEX, /* 15 */ - cf2_cmdBLEND, /* 16 */ - cf2_cmdRESERVED_17, /* 17 */ - cf2_cmdHSTEMHM, /* 18 */ - cf2_cmdHINTMASK, /* 19 */ - cf2_cmdCNTRMASK, /* 20 */ - cf2_cmdRMOVETO, /* 21 */ - cf2_cmdHMOVETO, /* 22 */ - cf2_cmdVSTEMHM, /* 23 */ - cf2_cmdRCURVELINE, /* 24 */ - cf2_cmdRLINECURVE, /* 25 */ - cf2_cmdVVCURVETO, /* 26 */ - cf2_cmdHHCURVETO, /* 27 */ - cf2_cmdEXTENDEDNMBR, /* 28 */ - cf2_cmdCALLGSUBR, /* 29 */ - cf2_cmdVHCURVETO, /* 30 */ - cf2_cmdHVCURVETO /* 31 */ - }; - - enum - { - cf2_escDOTSECTION, /* 0 */ - cf2_escRESERVED_1, /* 1 */ - cf2_escRESERVED_2, /* 2 */ - cf2_escAND, /* 3 */ - cf2_escOR, /* 4 */ - cf2_escNOT, /* 5 */ - cf2_escRESERVED_6, /* 6 */ - cf2_escRESERVED_7, /* 7 */ - cf2_escRESERVED_8, /* 8 */ - cf2_escABS, /* 9 */ - cf2_escADD, /* 10 like otherADD */ - cf2_escSUB, /* 11 like otherSUB */ - cf2_escDIV, /* 12 */ - cf2_escRESERVED_13, /* 13 */ - cf2_escNEG, /* 14 */ - cf2_escEQ, /* 15 */ - cf2_escRESERVED_16, /* 16 */ - cf2_escRESERVED_17, /* 17 */ - cf2_escDROP, /* 18 */ - cf2_escRESERVED_19, /* 19 */ - cf2_escPUT, /* 20 like otherPUT */ - cf2_escGET, /* 21 like otherGET */ - cf2_escIFELSE, /* 22 like otherIFELSE */ - cf2_escRANDOM, /* 23 like otherRANDOM */ - cf2_escMUL, /* 24 like otherMUL */ - cf2_escRESERVED_25, /* 25 */ - cf2_escSQRT, /* 26 */ - cf2_escDUP, /* 27 like otherDUP */ - cf2_escEXCH, /* 28 like otherEXCH */ - cf2_escINDEX, /* 29 */ - cf2_escROLL, /* 30 */ - cf2_escRESERVED_31, /* 31 */ - cf2_escRESERVED_32, /* 32 */ - cf2_escRESERVED_33, /* 33 */ - cf2_escHFLEX, /* 34 */ - cf2_escFLEX, /* 35 */ - cf2_escHFLEX1, /* 36 */ - cf2_escFLEX1, /* 37 */ - cf2_escRESERVED_38 /* 38 & all higher */ - }; - - - /* `stemHintArray' does not change once we start drawing the outline. */ - static void - cf2_doStems( const CF2_Font font, - CF2_Stack opStack, - CF2_ArrStack stemHintArray, - CF2_Fixed* width, - FT_Bool* haveWidth, - CF2_Fixed hintOffset ) - { - CF2_UInt i; - CF2_UInt count = cf2_stack_count( opStack ); - FT_Bool hasWidthArg = (FT_Bool)( count & 1 ); - - /* variable accumulates delta values from operand stack */ - CF2_Fixed position = hintOffset; - - - if ( hasWidthArg && !*haveWidth ) - *width = cf2_stack_getReal( opStack, 0 ) + - cf2_getNominalWidthX( font->decoder ); - - if ( font->decoder->width_only ) - goto exit; - - for ( i = hasWidthArg ? 1 : 0; i < count; i += 2 ) - { - /* construct a CF2_StemHint and push it onto the list */ - CF2_StemHintRec stemhint; - - - stemhint.min = - position += cf2_stack_getReal( opStack, i ); - stemhint.max = - position += cf2_stack_getReal( opStack, i + 1 ); - - stemhint.used = FALSE; - stemhint.maxDS = - stemhint.minDS = 0; - - cf2_arrstack_push( stemHintArray, &stemhint ); /* defer error check */ - } - - cf2_stack_clear( opStack ); - - exit: - /* cf2_doStems must define a width (may be default) */ - *haveWidth = TRUE; - } - - - static void - cf2_doFlex( CF2_Stack opStack, - CF2_Fixed* curX, - CF2_Fixed* curY, - CF2_GlyphPath glyphPath, - const FT_Bool* readFromStack, - FT_Bool doConditionalLastRead ) - { - CF2_Fixed vals[14]; - CF2_UInt index; - FT_Bool isHFlex; - CF2_Int top, i, j; - - - vals[0] = *curX; - vals[1] = *curY; - index = 0; - isHFlex = FT_BOOL( readFromStack[9] == FALSE ); - top = isHFlex ? 9 : 10; - - for ( i = 0; i < top; i++ ) - { - vals[i + 2] = vals[i]; - if ( readFromStack[i] ) - vals[i + 2] += cf2_stack_getReal( opStack, index++ ); - } - - if ( isHFlex ) - vals[9 + 2] = *curY; - - if ( doConditionalLastRead ) - { - FT_Bool lastIsX = (FT_Bool)( cf2_fixedAbs( vals[10] - *curX ) > - cf2_fixedAbs( vals[11] - *curY ) ); - CF2_Fixed lastVal = cf2_stack_getReal( opStack, index ); - - - if ( lastIsX ) - { - vals[12] = vals[10] + lastVal; - vals[13] = *curY; - } - else - { - vals[12] = *curX; - vals[13] = vals[11] + lastVal; - } - } - else - { - if ( readFromStack[10] ) - vals[12] = vals[10] + cf2_stack_getReal( opStack, index++ ); - else - vals[12] = *curX; - - if ( readFromStack[11] ) - vals[13] = vals[11] + cf2_stack_getReal( opStack, index ); - else - vals[13] = *curY; - } - - for ( j = 0; j < 2; j++ ) - cf2_glyphpath_curveTo( glyphPath, vals[j * 6 + 2], - vals[j * 6 + 3], - vals[j * 6 + 4], - vals[j * 6 + 5], - vals[j * 6 + 6], - vals[j * 6 + 7] ); - - cf2_stack_clear( opStack ); - - *curX = vals[12]; - *curY = vals[13]; - } - - - /* Blend numOperands on the stack, */ - /* store results into the first numBlends values, */ - /* then pop remaining arguments. */ - static void - cf2_doBlend( const CFF_Blend blend, - CF2_Stack opStack, - CF2_UInt numBlends ) - { - CF2_UInt delta; - CF2_UInt base; - CF2_UInt i, j; - CF2_UInt numOperands = (CF2_UInt)( numBlends * blend->lenBV ); - - - base = cf2_stack_count( opStack ) - numOperands; - delta = base + numBlends; - - for ( i = 0; i < numBlends; i++ ) - { - const CF2_Fixed* weight = &blend->BV[1]; - - /* start with first term */ - CF2_Fixed sum = cf2_stack_getReal( opStack, i + base ); - - - for ( j = 1; j < blend->lenBV; j++ ) - sum += FT_MulFix( *weight++, cf2_stack_getReal( opStack, delta++ ) ); - - /* store blended result */ - cf2_stack_setReal( opStack, i + base, sum ); - } - - /* leave only `numBlends' results on stack */ - cf2_stack_pop( opStack, numOperands - numBlends ); - } - - - /* - * `error' is a shared error code used by many objects in this - * routine. Before the code continues from an error, it must check and - * record the error in `*error'. The idea is that this shared - * error code will record the first error encountered. If testing - * for an error anyway, the cost of `goto exit' is small, so we do it, - * even if continuing would be safe. In this case, `lastError' is - * set, so the testing and storing can be done in one place, at `exit'. - * - * Continuing after an error is intended for objects which do their own - * testing of `*error', e.g., array stack functions. This allows us to - * avoid an extra test after the call. - * - * Unimplemented opcodes are ignored. - * - */ - FT_LOCAL_DEF( void ) - cf2_interpT2CharString( CF2_Font font, - CF2_Buffer buf, - CF2_OutlineCallbacks callbacks, - const FT_Vector* translation, - FT_Bool doingSeac, - CF2_Fixed curX, - CF2_Fixed curY, - CF2_Fixed* width ) - { - /* lastError is used for errors that are immediately tested */ - FT_Error lastError = FT_Err_Ok; - - /* pointer to parsed font object */ - CFF_Decoder* decoder = font->decoder; - - FT_Error* error = &font->error; - FT_Memory memory = font->memory; - - CF2_Fixed scaleY = font->innerTransform.d; - CF2_Fixed nominalWidthX = cf2_getNominalWidthX( decoder ); - - /* save this for hinting seac accents */ - CF2_Fixed hintOriginY = curY; - - CF2_Stack opStack = NULL; - FT_UInt stackSize; - FT_Byte op1; /* first opcode byte */ - - CF2_F16Dot16 storage[CF2_STORAGE_SIZE]; /* for `put' and `get' */ - - /* instruction limit; 20,000,000 matches Avalon */ - FT_UInt32 instructionLimit = 20000000UL; - - CF2_ArrStackRec subrStack; - - FT_Bool haveWidth; - CF2_Buffer charstring = NULL; - - CF2_Int charstringIndex = -1; /* initialize to empty */ - - /* TODO: placeholders for hint structures */ - - /* objects used for hinting */ - CF2_ArrStackRec hStemHintArray; - CF2_ArrStackRec vStemHintArray; - - CF2_HintMaskRec hintMask; - CF2_GlyphPathRec glyphPath; - - - FT_ZERO( &storage ); - - /* initialize the remaining objects */ - cf2_arrstack_init( &subrStack, - memory, - error, - sizeof ( CF2_BufferRec ) ); - cf2_arrstack_init( &hStemHintArray, - memory, - error, - sizeof ( CF2_StemHintRec ) ); - cf2_arrstack_init( &vStemHintArray, - memory, - error, - sizeof ( CF2_StemHintRec ) ); - - /* initialize CF2_StemHint arrays */ - cf2_hintmask_init( &hintMask, error ); - - /* initialize path map to manage drawing operations */ - - /* Note: last 4 params are used to handle `MoveToPermissive', which */ - /* may need to call `hintMap.Build' */ - /* TODO: MoveToPermissive is gone; are these still needed? */ - cf2_glyphpath_init( &glyphPath, - font, - callbacks, - scaleY, - /* hShift, */ - &hStemHintArray, - &vStemHintArray, - &hintMask, - hintOriginY, - &font->blues, - translation ); - - /* - * Initialize state for width parsing. From the CFF Spec: - * - * The first stack-clearing operator, which must be one of hstem, - * hstemhm, vstem, vstemhm, cntrmask, hintmask, hmoveto, vmoveto, - * rmoveto, or endchar, takes an additional argument - the width (as - * described earlier), which may be expressed as zero or one numeric - * argument. - * - * What we implement here uses the first validly specified width, but - * does not detect errors for specifying more than one width. - * - * If one of the above operators occurs without explicitly specifying - * a width, we assume the default width. - * - * CFF2 charstrings always return the default width (0). - * - */ - haveWidth = font->isCFF2 ? TRUE : FALSE; - *width = cf2_getDefaultWidthX( decoder ); - - /* - * Note: At this point, all pointers to resources must be NULL - * and all local objects must be initialized. - * There must be no branches to `exit:' above this point. - * - */ - - /* allocate an operand stack */ - stackSize = font->isCFF2 ? cf2_getMaxstack( decoder ) - : CF2_OPERAND_STACK_SIZE; - opStack = cf2_stack_init( memory, error, stackSize ); - - if ( !opStack ) - { - lastError = FT_THROW( Out_Of_Memory ); - goto exit; - } - - /* initialize subroutine stack by placing top level charstring as */ - /* first element (max depth plus one for the charstring) */ - /* Note: Caller owns and must finalize the first charstring. */ - /* Our copy of it does not change that requirement. */ - cf2_arrstack_setCount( &subrStack, CF2_MAX_SUBR + 1 ); - - charstring = (CF2_Buffer)cf2_arrstack_getBuffer( &subrStack ); - *charstring = *buf; /* structure copy */ - - charstringIndex = 0; /* entry is valid now */ - - /* catch errors so far */ - if ( *error ) - goto exit; - - /* main interpreter loop */ - while ( 1 ) - { - if ( cf2_buf_isEnd( charstring ) ) - { - /* If we've reached the end of the charstring, simulate a */ - /* cf2_cmdRETURN or cf2_cmdENDCHAR. */ - /* We do this for both CFF and CFF2. */ - if ( charstringIndex ) - op1 = cf2_cmdRETURN; /* end of buffer for subroutine */ - else - op1 = cf2_cmdENDCHAR; /* end of buffer for top level charstring */ - } - else - { - op1 = (FT_Byte)cf2_buf_readByte( charstring ); - - /* Explicit RETURN and ENDCHAR in CFF2 should be ignored. */ - /* Note: Trace message will report 0 instead of 11 or 14. */ - if ( ( op1 == cf2_cmdRETURN || op1 == cf2_cmdENDCHAR ) && - font->isCFF2 ) - op1 = cf2_cmdRESERVED_0; - } - - /* check for errors once per loop */ - if ( *error ) - goto exit; - - instructionLimit--; - if ( instructionLimit == 0 ) - { - lastError = FT_THROW( Invalid_Glyph_Format ); - goto exit; - } - - switch( op1 ) - { - case cf2_cmdRESERVED_0: - case cf2_cmdRESERVED_2: - case cf2_cmdRESERVED_9: - case cf2_cmdRESERVED_13: - case cf2_cmdRESERVED_17: - /* we may get here if we have a prior error */ - FT_TRACE4(( " unknown op (%d)\n", op1 )); - break; - - case cf2_cmdVSINDEX: - FT_TRACE4(( " vsindex\n" )); - - if ( !font->isCFF2 ) - break; /* clear stack & ignore */ - - if ( font->blend.usedBV ) - { - /* vsindex not allowed after blend */ - lastError = FT_THROW( Invalid_Glyph_Format ); - goto exit; - } - - { - FT_Int temp = cf2_stack_popInt( opStack ); - - - if ( temp >= 0 ) - font->vsindex = (FT_UInt)temp; - } - break; - - case cf2_cmdBLEND: - { - FT_UInt numBlends; - - - FT_TRACE4(( " blend\n" )); - - if ( !font->isCFF2 ) - break; /* clear stack & ignore */ - - /* do we have a `blend' op in a non-variant font? */ - if ( !font->blend.font ) - { - lastError = FT_THROW( Invalid_Glyph_Format ); - goto exit; - } - - /* check cached blend vector */ - if ( cff_blend_check_vector( &font->blend, - font->vsindex, - font->lenNDV, - font->NDV ) ) - { - lastError = cff_blend_build_vector( &font->blend, - font->vsindex, - font->lenNDV, - font->NDV ); - if ( lastError ) - goto exit; - } - - /* do the blend */ - numBlends = (FT_UInt)cf2_stack_popInt( opStack ); - if ( numBlends > stackSize ) - { - lastError = FT_THROW( Invalid_Glyph_Format ); - goto exit; - } - - cf2_doBlend( &font->blend, opStack, numBlends ); - - font->blend.usedBV = TRUE; - } - continue; /* do not clear the stack */ - - case cf2_cmdHSTEMHM: - case cf2_cmdHSTEM: - FT_TRACE4(( op1 == cf2_cmdHSTEMHM ? " hstemhm\n" : " hstem\n" )); - - /* never add hints after the mask is computed */ - if ( cf2_hintmask_isValid( &hintMask ) ) - { - FT_TRACE4(( "cf2_interpT2CharString:" - " invalid horizontal hint mask\n" )); - break; - } - - cf2_doStems( font, - opStack, - &hStemHintArray, - width, - &haveWidth, - 0 ); - - if ( font->decoder->width_only ) - goto exit; - - break; - - case cf2_cmdVSTEMHM: - case cf2_cmdVSTEM: - FT_TRACE4(( op1 == cf2_cmdVSTEMHM ? " vstemhm\n" : " vstem\n" )); - - /* never add hints after the mask is computed */ - if ( cf2_hintmask_isValid( &hintMask ) ) - { - FT_TRACE4(( "cf2_interpT2CharString:" - " invalid vertical hint mask\n" )); - break; - } - - cf2_doStems( font, - opStack, - &vStemHintArray, - width, - &haveWidth, - 0 ); - - if ( font->decoder->width_only ) - goto exit; - - break; - - case cf2_cmdVMOVETO: - FT_TRACE4(( " vmoveto\n" )); - - if ( cf2_stack_count( opStack ) > 1 && !haveWidth ) - *width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX; - - /* width is defined or default after this */ - haveWidth = TRUE; - - if ( font->decoder->width_only ) - goto exit; - - curY += cf2_stack_popFixed( opStack ); - - cf2_glyphpath_moveTo( &glyphPath, curX, curY ); - - break; - - case cf2_cmdRLINETO: - { - CF2_UInt index; - CF2_UInt count = cf2_stack_count( opStack ); - - - FT_TRACE4(( " rlineto\n" )); - - for ( index = 0; index < count; index += 2 ) - { - curX += cf2_stack_getReal( opStack, index + 0 ); - curY += cf2_stack_getReal( opStack, index + 1 ); - - cf2_glyphpath_lineTo( &glyphPath, curX, curY ); - } - - cf2_stack_clear( opStack ); - } - continue; /* no need to clear stack again */ - - case cf2_cmdHLINETO: - case cf2_cmdVLINETO: - { - CF2_UInt index; - CF2_UInt count = cf2_stack_count( opStack ); - - FT_Bool isX = FT_BOOL( op1 == cf2_cmdHLINETO ); - - - FT_TRACE4(( isX ? " hlineto\n" : " vlineto\n" )); - - for ( index = 0; index < count; index++ ) - { - CF2_Fixed v = cf2_stack_getReal( opStack, index ); - - - if ( isX ) - curX += v; - else - curY += v; - - isX = !isX; - - cf2_glyphpath_lineTo( &glyphPath, curX, curY ); - } - - cf2_stack_clear( opStack ); - } - continue; - - case cf2_cmdRCURVELINE: - case cf2_cmdRRCURVETO: - { - CF2_UInt count = cf2_stack_count( opStack ); - CF2_UInt index = 0; - - - FT_TRACE4(( op1 == cf2_cmdRCURVELINE ? " rcurveline\n" - : " rrcurveto\n" )); - - while ( index + 6 <= count ) - { - CF2_Fixed x1 = cf2_stack_getReal( opStack, index + 0 ) + curX; - CF2_Fixed y1 = cf2_stack_getReal( opStack, index + 1 ) + curY; - CF2_Fixed x2 = cf2_stack_getReal( opStack, index + 2 ) + x1; - CF2_Fixed y2 = cf2_stack_getReal( opStack, index + 3 ) + y1; - CF2_Fixed x3 = cf2_stack_getReal( opStack, index + 4 ) + x2; - CF2_Fixed y3 = cf2_stack_getReal( opStack, index + 5 ) + y2; - - - cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); - - curX = x3; - curY = y3; - index += 6; - } - - if ( op1 == cf2_cmdRCURVELINE ) - { - curX += cf2_stack_getReal( opStack, index + 0 ); - curY += cf2_stack_getReal( opStack, index + 1 ); - - cf2_glyphpath_lineTo( &glyphPath, curX, curY ); - } - - cf2_stack_clear( opStack ); - } - continue; /* no need to clear stack again */ - - case cf2_cmdCALLGSUBR: - case cf2_cmdCALLSUBR: - { - CF2_Int subrNum; - - - FT_TRACE4(( op1 == cf2_cmdCALLGSUBR ? " callgsubr" - : " callsubr" )); - - if ( charstringIndex > CF2_MAX_SUBR ) - { - /* max subr plus one for charstring */ - lastError = FT_THROW( Invalid_Glyph_Format ); - goto exit; /* overflow of stack */ - } - - /* push our current CFF charstring region on subrStack */ - charstring = (CF2_Buffer) - cf2_arrstack_getPointer( - &subrStack, - (size_t)charstringIndex + 1 ); - - /* set up the new CFF region and pointer */ - subrNum = cf2_stack_popInt( opStack ); - - switch ( op1 ) - { - case cf2_cmdCALLGSUBR: - FT_TRACE4(( " (idx %d, entering level %d)\n", - subrNum + decoder->globals_bias, - charstringIndex + 1 )); - - if ( cf2_initGlobalRegionBuffer( decoder, - subrNum, - charstring ) ) - { - lastError = FT_THROW( Invalid_Glyph_Format ); - goto exit; /* subroutine lookup or stream error */ - } - break; - - default: - /* cf2_cmdCALLSUBR */ - FT_TRACE4(( " (idx %d, entering level %d)\n", - subrNum + decoder->locals_bias, - charstringIndex + 1 )); - - if ( cf2_initLocalRegionBuffer( decoder, - subrNum, - charstring ) ) - { - lastError = FT_THROW( Invalid_Glyph_Format ); - goto exit; /* subroutine lookup or stream error */ - } - } - - charstringIndex += 1; /* entry is valid now */ - } - continue; /* do not clear the stack */ - - case cf2_cmdRETURN: - FT_TRACE4(( " return (leaving level %d)\n", charstringIndex )); - - if ( charstringIndex < 1 ) - { - /* Note: cannot return from top charstring */ - lastError = FT_THROW( Invalid_Glyph_Format ); - goto exit; /* underflow of stack */ - } - - /* restore position in previous charstring */ - charstring = (CF2_Buffer) - cf2_arrstack_getPointer( - &subrStack, - (CF2_UInt)--charstringIndex ); - continue; /* do not clear the stack */ - - case cf2_cmdESC: - { - FT_Byte op2 = (FT_Byte)cf2_buf_readByte( charstring ); - - - /* first switch for 2-byte operators handles CFF2 */ - /* and opcodes that are reserved for both CFF and CFF2 */ - switch ( op2 ) - { - case cf2_escHFLEX: - { - static const FT_Bool readFromStack[12] = - { - TRUE /* dx1 */, FALSE /* dy1 */, - TRUE /* dx2 */, TRUE /* dy2 */, - TRUE /* dx3 */, FALSE /* dy3 */, - TRUE /* dx4 */, FALSE /* dy4 */, - TRUE /* dx5 */, FALSE /* dy5 */, - TRUE /* dx6 */, FALSE /* dy6 */ - }; - - - FT_TRACE4(( " hflex\n" )); - - cf2_doFlex( opStack, - &curX, - &curY, - &glyphPath, - readFromStack, - FALSE /* doConditionalLastRead */ ); - } - continue; - - case cf2_escFLEX: - { - static const FT_Bool readFromStack[12] = - { - TRUE /* dx1 */, TRUE /* dy1 */, - TRUE /* dx2 */, TRUE /* dy2 */, - TRUE /* dx3 */, TRUE /* dy3 */, - TRUE /* dx4 */, TRUE /* dy4 */, - TRUE /* dx5 */, TRUE /* dy5 */, - TRUE /* dx6 */, TRUE /* dy6 */ - }; - - - FT_TRACE4(( " flex\n" )); - - cf2_doFlex( opStack, - &curX, - &curY, - &glyphPath, - readFromStack, - FALSE /* doConditionalLastRead */ ); - } - break; /* TODO: why is this not a continue? */ - - case cf2_escHFLEX1: - { - static const FT_Bool readFromStack[12] = - { - TRUE /* dx1 */, TRUE /* dy1 */, - TRUE /* dx2 */, TRUE /* dy2 */, - TRUE /* dx3 */, FALSE /* dy3 */, - TRUE /* dx4 */, FALSE /* dy4 */, - TRUE /* dx5 */, TRUE /* dy5 */, - TRUE /* dx6 */, FALSE /* dy6 */ - }; - - - FT_TRACE4(( " hflex1\n" )); - - cf2_doFlex( opStack, - &curX, - &curY, - &glyphPath, - readFromStack, - FALSE /* doConditionalLastRead */ ); - } - continue; - - case cf2_escFLEX1: - { - static const FT_Bool readFromStack[12] = - { - TRUE /* dx1 */, TRUE /* dy1 */, - TRUE /* dx2 */, TRUE /* dy2 */, - TRUE /* dx3 */, TRUE /* dy3 */, - TRUE /* dx4 */, TRUE /* dy4 */, - TRUE /* dx5 */, TRUE /* dy5 */, - FALSE /* dx6 */, FALSE /* dy6 */ - }; - - - FT_TRACE4(( " flex1\n" )); - - cf2_doFlex( opStack, - &curX, - &curY, - &glyphPath, - readFromStack, - TRUE /* doConditionalLastRead */ ); - } - continue; - - /* these opcodes are reserved in both CFF & CFF2 */ - case cf2_escRESERVED_1: - case cf2_escRESERVED_2: - case cf2_escRESERVED_6: - case cf2_escRESERVED_7: - case cf2_escRESERVED_8: - case cf2_escRESERVED_13: - case cf2_escRESERVED_16: - case cf2_escRESERVED_17: - case cf2_escRESERVED_19: - case cf2_escRESERVED_25: - case cf2_escRESERVED_31: - case cf2_escRESERVED_32: - case cf2_escRESERVED_33: - FT_TRACE4(( " unknown op (12, %d)\n", op2 )); - break; - - default: - { - if ( font->isCFF2 || op2 >= cf2_escRESERVED_38 ) - FT_TRACE4(( " unknown op (12, %d)\n", op2 )); - else - { - /* second switch for 2-byte operators handles just CFF */ - switch ( op2 ) - { - - case cf2_escDOTSECTION: - /* something about `flip type of locking' -- ignore it */ - FT_TRACE4(( " dotsection\n" )); - - break; - - case cf2_escAND: - { - CF2_F16Dot16 arg1; - CF2_F16Dot16 arg2; - - - FT_TRACE4(( " and\n" )); - - arg2 = cf2_stack_popFixed( opStack ); - arg1 = cf2_stack_popFixed( opStack ); - - cf2_stack_pushInt( opStack, arg1 && arg2 ); - } - continue; /* do not clear the stack */ - - case cf2_escOR: - { - CF2_F16Dot16 arg1; - CF2_F16Dot16 arg2; - - - FT_TRACE4(( " or\n" )); - - arg2 = cf2_stack_popFixed( opStack ); - arg1 = cf2_stack_popFixed( opStack ); - - cf2_stack_pushInt( opStack, arg1 || arg2 ); - } - continue; /* do not clear the stack */ - - case cf2_escNOT: - { - CF2_F16Dot16 arg; - - - FT_TRACE4(( " not\n" )); - - arg = cf2_stack_popFixed( opStack ); - - cf2_stack_pushInt( opStack, !arg ); - } - continue; /* do not clear the stack */ - - case cf2_escABS: - { - CF2_F16Dot16 arg; - - - FT_TRACE4(( " abs\n" )); - - arg = cf2_stack_popFixed( opStack ); - - cf2_stack_pushFixed( opStack, FT_ABS( arg ) ); - } - continue; /* do not clear the stack */ - - case cf2_escADD: - { - CF2_F16Dot16 summand1; - CF2_F16Dot16 summand2; - - - FT_TRACE4(( " add\n" )); - - summand2 = cf2_stack_popFixed( opStack ); - summand1 = cf2_stack_popFixed( opStack ); - - cf2_stack_pushFixed( opStack, summand1 + summand2 ); - } - continue; /* do not clear the stack */ - - case cf2_escSUB: - { - CF2_F16Dot16 minuend; - CF2_F16Dot16 subtrahend; - - - FT_TRACE4(( " sub\n" )); - - subtrahend = cf2_stack_popFixed( opStack ); - minuend = cf2_stack_popFixed( opStack ); - - cf2_stack_pushFixed( opStack, minuend - subtrahend ); - } - continue; /* do not clear the stack */ - - case cf2_escDIV: - { - CF2_F16Dot16 dividend; - CF2_F16Dot16 divisor; - - - FT_TRACE4(( " div\n" )); - - divisor = cf2_stack_popFixed( opStack ); - dividend = cf2_stack_popFixed( opStack ); - - cf2_stack_pushFixed( opStack, FT_DivFix( dividend, divisor ) ); - } - continue; /* do not clear the stack */ - - case cf2_escNEG: - { - CF2_F16Dot16 arg; - - - FT_TRACE4(( " neg\n" )); - - arg = cf2_stack_popFixed( opStack ); - - cf2_stack_pushFixed( opStack, -arg ); - } - continue; /* do not clear the stack */ - - case cf2_escEQ: - { - CF2_F16Dot16 arg1; - CF2_F16Dot16 arg2; - - - FT_TRACE4(( " eq\n" )); - - arg2 = cf2_stack_popFixed( opStack ); - arg1 = cf2_stack_popFixed( opStack ); - - cf2_stack_pushInt( opStack, arg1 == arg2 ); - } - continue; /* do not clear the stack */ - - case cf2_escDROP: - FT_TRACE4(( " drop\n" )); - - (void)cf2_stack_popFixed( opStack ); - continue; /* do not clear the stack */ - - case cf2_escPUT: - { - CF2_F16Dot16 val; - CF2_Int idx; - - - FT_TRACE4(( " put\n" )); - - idx = cf2_stack_popInt( opStack ); - val = cf2_stack_popFixed( opStack ); - - if ( idx >= 0 && idx < CF2_STORAGE_SIZE ) - storage[idx] = val; - } - continue; /* do not clear the stack */ - - case cf2_escGET: - { - CF2_Int idx; - - - FT_TRACE4(( " get\n" )); - - idx = cf2_stack_popInt( opStack ); - - if ( idx >= 0 && idx < CF2_STORAGE_SIZE ) - cf2_stack_pushFixed( opStack, storage[idx] ); - } - continue; /* do not clear the stack */ - - case cf2_escIFELSE: - { - CF2_F16Dot16 arg1; - CF2_F16Dot16 arg2; - CF2_F16Dot16 cond1; - CF2_F16Dot16 cond2; - - - FT_TRACE4(( " ifelse\n" )); - - cond2 = cf2_stack_popFixed( opStack ); - cond1 = cf2_stack_popFixed( opStack ); - arg2 = cf2_stack_popFixed( opStack ); - arg1 = cf2_stack_popFixed( opStack ); - - cf2_stack_pushFixed( opStack, cond1 <= cond2 ? arg1 : arg2 ); - } - continue; /* do not clear the stack */ - - case cf2_escRANDOM: /* in spec */ - FT_TRACE4(( " random\n" )); - - CF2_FIXME; - break; - - case cf2_escMUL: - { - CF2_F16Dot16 factor1; - CF2_F16Dot16 factor2; - - - FT_TRACE4(( " mul\n" )); - - factor2 = cf2_stack_popFixed( opStack ); - factor1 = cf2_stack_popFixed( opStack ); - - cf2_stack_pushFixed( opStack, FT_MulFix( factor1, factor2 ) ); - } - continue; /* do not clear the stack */ - - case cf2_escSQRT: - { - CF2_F16Dot16 arg; - - - FT_TRACE4(( " sqrt\n" )); - - arg = cf2_stack_popFixed( opStack ); - if ( arg > 0 ) - { - FT_Fixed root = arg; - FT_Fixed new_root; - - - /* Babylonian method */ - for (;;) - { - new_root = ( root + FT_DivFix( arg, root ) + 1 ) >> 1; - if ( new_root == root ) - break; - root = new_root; - } - arg = new_root; - } - else - arg = 0; - - cf2_stack_pushFixed( opStack, arg ); - } - continue; /* do not clear the stack */ - - case cf2_escDUP: - { - CF2_F16Dot16 arg; - - - FT_TRACE4(( " dup\n" )); - - arg = cf2_stack_popFixed( opStack ); - - cf2_stack_pushFixed( opStack, arg ); - cf2_stack_pushFixed( opStack, arg ); - } - continue; /* do not clear the stack */ - - case cf2_escEXCH: - { - CF2_F16Dot16 arg1; - CF2_F16Dot16 arg2; - - - FT_TRACE4(( " exch\n" )); - - arg2 = cf2_stack_popFixed( opStack ); - arg1 = cf2_stack_popFixed( opStack ); - - cf2_stack_pushFixed( opStack, arg2 ); - cf2_stack_pushFixed( opStack, arg1 ); - } - continue; /* do not clear the stack */ - - case cf2_escINDEX: - { - CF2_Int idx; - CF2_UInt size; - - - FT_TRACE4(( " index\n" )); - - idx = cf2_stack_popInt( opStack ); - size = cf2_stack_count( opStack ); - - if ( size > 0 ) - { - /* for `cf2_stack_getReal', index 0 is bottom of stack */ - CF2_UInt gr_idx; - - - if ( idx < 0 ) - gr_idx = size - 1; - else if ( (CF2_UInt)idx >= size ) - gr_idx = 0; - else - gr_idx = size - 1 - (CF2_UInt)idx; - - cf2_stack_pushFixed( opStack, - cf2_stack_getReal( opStack, gr_idx ) ); - } - } - continue; /* do not clear the stack */ - - case cf2_escROLL: - { - CF2_Int idx; - CF2_Int count; - - - FT_TRACE4(( " roll\n" )); - - idx = cf2_stack_popInt( opStack ); - count = cf2_stack_popInt( opStack ); - - cf2_stack_roll( opStack, count, idx ); - } - continue; /* do not clear the stack */ - - } /* end of 2nd switch checking op2 */ - } - } - } /* end of 1st switch checking op2 */ - } /* case cf2_cmdESC */ - - break; - - case cf2_cmdENDCHAR: - FT_TRACE4(( " endchar\n" )); - - if ( cf2_stack_count( opStack ) == 1 || - cf2_stack_count( opStack ) == 5 ) - { - if ( !haveWidth ) - *width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX; - } - - /* width is defined or default after this */ - haveWidth = TRUE; - - if ( font->decoder->width_only ) - goto exit; - - /* close path if still open */ - cf2_glyphpath_closeOpenPath( &glyphPath ); - - /* disable seac for CFF2 (charstring ending with args on stack) */ - if ( !font->isCFF2 && cf2_stack_count( opStack ) > 1 ) - { - /* must be either 4 or 5 -- */ - /* this is a (deprecated) implied `seac' operator */ - - CF2_Int achar; - CF2_Int bchar; - CF2_BufferRec component; - CF2_Fixed dummyWidth; /* ignore component width */ - FT_Error error2; - - - if ( doingSeac ) - { - lastError = FT_THROW( Invalid_Glyph_Format ); - goto exit; /* nested seac */ - } - - achar = cf2_stack_popInt( opStack ); - bchar = cf2_stack_popInt( opStack ); - - curY = cf2_stack_popFixed( opStack ); - curX = cf2_stack_popFixed( opStack ); - - error2 = cf2_getSeacComponent( decoder, achar, &component ); - if ( error2 ) - { - lastError = error2; /* pass FreeType error through */ - goto exit; - } - cf2_interpT2CharString( font, - &component, - callbacks, - translation, - TRUE, - curX, - curY, - &dummyWidth ); - cf2_freeSeacComponent( decoder, &component ); - - error2 = cf2_getSeacComponent( decoder, bchar, &component ); - if ( error2 ) - { - lastError = error2; /* pass FreeType error through */ - goto exit; - } - cf2_interpT2CharString( font, - &component, - callbacks, - translation, - TRUE, - 0, - 0, - &dummyWidth ); - cf2_freeSeacComponent( decoder, &component ); - } - goto exit; - - case cf2_cmdCNTRMASK: - case cf2_cmdHINTMASK: - /* the final \n in the tracing message gets added in */ - /* `cf2_hintmask_read' (which also traces the mask bytes) */ - FT_TRACE4(( op1 == cf2_cmdCNTRMASK ? " cntrmask" : " hintmask" )); - - /* never add hints after the mask is computed */ - if ( cf2_stack_count( opStack ) > 1 && - cf2_hintmask_isValid( &hintMask ) ) - { - FT_TRACE4(( "cf2_interpT2CharString: invalid hint mask\n" )); - break; - } - - /* if there are arguments on the stack, there this is an */ - /* implied cf2_cmdVSTEMHM */ - cf2_doStems( font, - opStack, - &vStemHintArray, - width, - &haveWidth, - 0 ); - - if ( font->decoder->width_only ) - goto exit; - - if ( op1 == cf2_cmdHINTMASK ) - { - /* consume the hint mask bytes which follow the operator */ - cf2_hintmask_read( &hintMask, - charstring, - cf2_arrstack_size( &hStemHintArray ) + - cf2_arrstack_size( &vStemHintArray ) ); - } - else - { - /* - * Consume the counter mask bytes which follow the operator: - * Build a temporary hint map, just to place and lock those - * stems participating in the counter mask. These are most - * likely the dominant hstems, and are grouped together in a - * few counter groups, not necessarily in correspondence - * with the hint groups. This reduces the chances of - * conflicts between hstems that are initially placed in - * separate hint groups and then brought together. The - * positions are copied back to `hStemHintArray', so we can - * discard `counterMask' and `counterHintMap'. - * - */ - CF2_HintMapRec counterHintMap; - CF2_HintMaskRec counterMask; - - - cf2_hintmap_init( &counterHintMap, - font, - &glyphPath.initialHintMap, - &glyphPath.hintMoves, - scaleY ); - cf2_hintmask_init( &counterMask, error ); - - cf2_hintmask_read( &counterMask, - charstring, - cf2_arrstack_size( &hStemHintArray ) + - cf2_arrstack_size( &vStemHintArray ) ); - cf2_hintmap_build( &counterHintMap, - &hStemHintArray, - &vStemHintArray, - &counterMask, - 0, - FALSE ); - } - break; - - case cf2_cmdRMOVETO: - FT_TRACE4(( " rmoveto\n" )); - - if ( cf2_stack_count( opStack ) > 2 && !haveWidth ) - *width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX; - - /* width is defined or default after this */ - haveWidth = TRUE; - - if ( font->decoder->width_only ) - goto exit; - - curY += cf2_stack_popFixed( opStack ); - curX += cf2_stack_popFixed( opStack ); - - cf2_glyphpath_moveTo( &glyphPath, curX, curY ); - - break; - - case cf2_cmdHMOVETO: - FT_TRACE4(( " hmoveto\n" )); - - if ( cf2_stack_count( opStack ) > 1 && !haveWidth ) - *width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX; - - /* width is defined or default after this */ - haveWidth = TRUE; - - if ( font->decoder->width_only ) - goto exit; - - curX += cf2_stack_popFixed( opStack ); - - cf2_glyphpath_moveTo( &glyphPath, curX, curY ); - - break; - - case cf2_cmdRLINECURVE: - { - CF2_UInt count = cf2_stack_count( opStack ); - CF2_UInt index = 0; - - - FT_TRACE4(( " rlinecurve\n" )); - - while ( index + 6 < count ) - { - curX += cf2_stack_getReal( opStack, index + 0 ); - curY += cf2_stack_getReal( opStack, index + 1 ); - - cf2_glyphpath_lineTo( &glyphPath, curX, curY ); - index += 2; - } - - while ( index < count ) - { - CF2_Fixed x1 = cf2_stack_getReal( opStack, index + 0 ) + curX; - CF2_Fixed y1 = cf2_stack_getReal( opStack, index + 1 ) + curY; - CF2_Fixed x2 = cf2_stack_getReal( opStack, index + 2 ) + x1; - CF2_Fixed y2 = cf2_stack_getReal( opStack, index + 3 ) + y1; - CF2_Fixed x3 = cf2_stack_getReal( opStack, index + 4 ) + x2; - CF2_Fixed y3 = cf2_stack_getReal( opStack, index + 5 ) + y2; - - - cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); - - curX = x3; - curY = y3; - index += 6; - } - - cf2_stack_clear( opStack ); - } - continue; /* no need to clear stack again */ - - case cf2_cmdVVCURVETO: - { - CF2_UInt count, count1 = cf2_stack_count( opStack ); - CF2_UInt index = 0; - - - /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */ - /* we enforce it by clearing the second bit */ - /* (and sorting the stack indexing to suit) */ - count = count1 & ~2U; - index += count1 - count; - - FT_TRACE4(( " vvcurveto\n" )); - - while ( index < count ) - { - CF2_Fixed x1, y1, x2, y2, x3, y3; - - - if ( ( count - index ) & 1 ) - { - x1 = cf2_stack_getReal( opStack, index ) + curX; - - index++; - } - else - x1 = curX; - - y1 = cf2_stack_getReal( opStack, index + 0 ) + curY; - x2 = cf2_stack_getReal( opStack, index + 1 ) + x1; - y2 = cf2_stack_getReal( opStack, index + 2 ) + y1; - x3 = x2; - y3 = cf2_stack_getReal( opStack, index + 3 ) + y2; - - cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); - - curX = x3; - curY = y3; - index += 4; - } - - cf2_stack_clear( opStack ); - } - continue; /* no need to clear stack again */ - - case cf2_cmdHHCURVETO: - { - CF2_UInt count, count1 = cf2_stack_count( opStack ); - CF2_UInt index = 0; - - - /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */ - /* we enforce it by clearing the second bit */ - /* (and sorting the stack indexing to suit) */ - count = count1 & ~2U; - index += count1 - count; - - FT_TRACE4(( " hhcurveto\n" )); - - while ( index < count ) - { - CF2_Fixed x1, y1, x2, y2, x3, y3; - - - if ( ( count - index ) & 1 ) - { - y1 = cf2_stack_getReal( opStack, index ) + curY; - - index++; - } - else - y1 = curY; - - x1 = cf2_stack_getReal( opStack, index + 0 ) + curX; - x2 = cf2_stack_getReal( opStack, index + 1 ) + x1; - y2 = cf2_stack_getReal( opStack, index + 2 ) + y1; - x3 = cf2_stack_getReal( opStack, index + 3 ) + x2; - y3 = y2; - - cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); - - curX = x3; - curY = y3; - index += 4; - } - - cf2_stack_clear( opStack ); - } - continue; /* no need to clear stack again */ - - case cf2_cmdVHCURVETO: - case cf2_cmdHVCURVETO: - { - CF2_UInt count, count1 = cf2_stack_count( opStack ); - CF2_UInt index = 0; - - FT_Bool alternate = FT_BOOL( op1 == cf2_cmdHVCURVETO ); - - - /* if `cf2_stack_count' isn't of the form 8n, 8n+1, */ - /* 8n+4, or 8n+5, we enforce it by clearing the */ - /* second bit */ - /* (and sorting the stack indexing to suit) */ - count = count1 & ~2U; - index += count1 - count; - - FT_TRACE4(( alternate ? " hvcurveto\n" : " vhcurveto\n" )); - - while ( index < count ) - { - CF2_Fixed x1, x2, x3, y1, y2, y3; - - - if ( alternate ) - { - x1 = cf2_stack_getReal( opStack, index + 0 ) + curX; - y1 = curY; - x2 = cf2_stack_getReal( opStack, index + 1 ) + x1; - y2 = cf2_stack_getReal( opStack, index + 2 ) + y1; - y3 = cf2_stack_getReal( opStack, index + 3 ) + y2; - - if ( count - index == 5 ) - { - x3 = cf2_stack_getReal( opStack, index + 4 ) + x2; - - index++; - } - else - x3 = x2; - - alternate = FALSE; - } - else - { - x1 = curX; - y1 = cf2_stack_getReal( opStack, index + 0 ) + curY; - x2 = cf2_stack_getReal( opStack, index + 1 ) + x1; - y2 = cf2_stack_getReal( opStack, index + 2 ) + y1; - x3 = cf2_stack_getReal( opStack, index + 3 ) + x2; - - if ( count - index == 5 ) - { - y3 = cf2_stack_getReal( opStack, index + 4 ) + y2; - - index++; - } - else - y3 = y2; - - alternate = TRUE; - } - - cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); - - curX = x3; - curY = y3; - index += 4; - } - - cf2_stack_clear( opStack ); - } - continue; /* no need to clear stack again */ - - case cf2_cmdEXTENDEDNMBR: - { - CF2_Int v; - - CF2_Int byte1 = cf2_buf_readByte( charstring ); - CF2_Int byte2 = cf2_buf_readByte( charstring ); - - - v = (FT_Short)( ( byte1 << 8 ) | - byte2 ); - - FT_TRACE4(( " %d", v )); - - cf2_stack_pushInt( opStack, v ); - } - continue; - - default: - /* numbers */ - { - if ( /* op1 >= 32 && */ op1 <= 246 ) - { - CF2_Int v; - - - v = op1 - 139; - - FT_TRACE4(( " %d", v )); - - /* -107 .. 107 */ - cf2_stack_pushInt( opStack, v ); - } - - else if ( /* op1 >= 247 && */ op1 <= 250 ) - { - CF2_Int v; - - - v = op1; - v -= 247; - v *= 256; - v += cf2_buf_readByte( charstring ); - v += 108; - - FT_TRACE4(( " %d", v )); - - /* 108 .. 1131 */ - cf2_stack_pushInt( opStack, v ); - } - - else if ( /* op1 >= 251 && */ op1 <= 254 ) - { - CF2_Int v; - - - v = op1; - v -= 251; - v *= 256; - v += cf2_buf_readByte( charstring ); - v = -v - 108; - - FT_TRACE4(( " %d", v )); - - /* -1131 .. -108 */ - cf2_stack_pushInt( opStack, v ); - } - - else /* op1 == 255 */ - { - CF2_Fixed v; - - FT_UInt32 byte1 = (FT_UInt32)cf2_buf_readByte( charstring ); - FT_UInt32 byte2 = (FT_UInt32)cf2_buf_readByte( charstring ); - FT_UInt32 byte3 = (FT_UInt32)cf2_buf_readByte( charstring ); - FT_UInt32 byte4 = (FT_UInt32)cf2_buf_readByte( charstring ); - - - v = (CF2_Fixed)( ( byte1 << 24 ) | - ( byte2 << 16 ) | - ( byte3 << 8 ) | - byte4 ); - - FT_TRACE4(( " %.5f", v / 65536.0 )); - - cf2_stack_pushFixed( opStack, v ); - } - } - continue; /* don't clear stack */ - - } /* end of switch statement checking `op1' */ - - cf2_stack_clear( opStack ); - - } /* end of main interpreter loop */ - - /* we get here if the charstring ends without cf2_cmdENDCHAR */ - FT_TRACE4(( "cf2_interpT2CharString:" - " charstring ends without ENDCHAR\n" )); - - exit: - /* check whether last error seen is also the first one */ - cf2_setError( error, lastError ); - - if ( *error ) - FT_TRACE4(( "charstring error %d\n", *error )); - - /* free resources from objects we've used */ - cf2_glyphpath_finalize( &glyphPath ); - cf2_arrstack_finalize( &vStemHintArray ); - cf2_arrstack_finalize( &hStemHintArray ); - cf2_arrstack_finalize( &subrStack ); - cf2_stack_free( opStack ); - - FT_TRACE4(( "\n" )); - - return; - } - - -/* END */ diff --git a/modules/freetype2/src/cff/cff.c b/modules/freetype2/src/cff/cff.c index 86ca1be04..1a755d5da 100644 --- a/modules/freetype2/src/cff/cff.c +++ b/modules/freetype2/src/cff/cff.c @@ -4,7 +4,7 @@ /* */ /* FreeType OpenType driver component (body only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,25 +17,14 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT - #include <ft2build.h> -#include "cffpic.c" +#include "cffcmap.c" #include "cffdrivr.c" +#include "cffgload.c" #include "cffparse.c" +#include "cffpic.c" #include "cffload.c" #include "cffobjs.c" -#include "cffgload.c" -#include "cffcmap.c" - -#include "cf2arrst.c" -#include "cf2blues.c" -#include "cf2error.c" -#include "cf2font.c" -#include "cf2ft.c" -#include "cf2hints.c" -#include "cf2intrp.c" -#include "cf2read.c" -#include "cf2stack.c" /* END */ diff --git a/modules/freetype2/src/cff/cffcmap.c b/modules/freetype2/src/cff/cffcmap.c index 695ba69d9..e45ae1127 100644 --- a/modules/freetype2/src/cff/cffcmap.c +++ b/modules/freetype2/src/cff/cffcmap.c @@ -4,7 +4,7 @@ /* */ /* CFF character mapping table (cmap) support (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cff/cffcmap.h b/modules/freetype2/src/cff/cffcmap.h index 23795d509..856a43dd1 100644 --- a/modules/freetype2/src/cff/cffcmap.h +++ b/modules/freetype2/src/cff/cffcmap.h @@ -4,7 +4,7 @@ /* */ /* CFF character mapping table (cmap) support (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -19,7 +19,7 @@ #ifndef CFFCMAP_H_ #define CFFCMAP_H_ -#include "cffobjs.h" +#include FT_INTERNAL_CFF_OBJECTS_TYPES_H FT_BEGIN_HEADER diff --git a/modules/freetype2/src/cff/cffdrivr.c b/modules/freetype2/src/cff/cffdrivr.c index 31825286e..df896848d 100644 --- a/modules/freetype2/src/cff/cffdrivr.c +++ b/modules/freetype2/src/cff/cffdrivr.c @@ -4,7 +4,7 @@ /* */ /* OpenType font driver implementation (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -21,19 +21,24 @@ #include FT_INTERNAL_DEBUG_H #include FT_INTERNAL_STREAM_H #include FT_INTERNAL_SFNT_H +#include FT_INTERNAL_POSTSCRIPT_AUX_H +#include FT_INTERNAL_POSTSCRIPT_PROPS_H #include FT_SERVICE_CID_H #include FT_SERVICE_POSTSCRIPT_INFO_H #include FT_SERVICE_POSTSCRIPT_NAME_H #include FT_SERVICE_TT_CMAP_H +#include FT_SERVICE_CFF_TABLE_LOAD_H #include "cffdrivr.h" #include "cffgload.h" #include "cffload.h" #include "cffcmap.h" #include "cffparse.h" +#include "cffobjs.h" #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT #include FT_SERVICE_MULTIPLE_MASTERS_H +#include FT_SERVICE_METRICS_VARIATIONS_H #endif #include "cfferrs.h" @@ -42,7 +47,7 @@ #include FT_SERVICE_FONT_FORMAT_H #include FT_SERVICE_GLYPH_DICT_H #include FT_SERVICE_PROPERTIES_H -#include FT_CFF_DRIVER_H +#include FT_DRIVER_H /*************************************************************************/ @@ -213,8 +218,8 @@ { #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT /* no fast retrieval for blended MM fonts without VVAR table */ - if ( !ttface->is_default_instance && - !( ttface->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ) + if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) && + !( ttface->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ) return FT_THROW( Unimplemented_Feature ); #endif @@ -236,8 +241,10 @@ &dummy, &ah ); - FT_TRACE5(( " idx %d: advance height %d font units\n", - start + nn, ah )); + FT_TRACE5(( " idx %d: advance height %d font unit%s\n", + start + nn, + ah, + ah == 1 ? "" : "s" )); advances[nn] = ah; } } @@ -245,8 +252,8 @@ { #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT /* no fast retrieval for blended MM fonts without HVAR table */ - if ( !ttface->is_default_instance && - !( ttface->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ) + if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) && + !( ttface->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ) return FT_THROW( Unimplemented_Feature ); #endif @@ -265,8 +272,10 @@ &dummy, &aw ); - FT_TRACE5(( " idx %d: advance width %d font units\n", - start + nn, aw )); + FT_TRACE5(( " idx %d: advance width %d font unit%s\n", + start + nn, + aw, + aw == 1 ? "" : "s" )); advances[nn] = aw; } } @@ -492,11 +501,89 @@ } + static FT_Error + cff_ps_get_font_extra( CFF_Face face, + PS_FontExtraRec* afont_extra ) + { + CFF_Font cff = (CFF_Font)face->extra.data; + FT_Error error = FT_Err_Ok; + + + if ( cff && cff->font_extra == NULL ) + { + CFF_FontRecDict dict = &cff->top_font.font_dict; + PS_FontExtraRec* font_extra = NULL; + FT_Memory memory = face->root.memory; + FT_String* embedded_postscript; + + + if ( FT_ALLOC( font_extra, sizeof ( *font_extra ) ) ) + goto Fail; + + font_extra->fs_type = 0U; + + embedded_postscript = cff_index_get_sid_string( + cff, + dict->embedded_postscript ); + if ( embedded_postscript ) + { + FT_String* start_fstype; + FT_String* start_def; + + + /* Identify the XYZ integer in `/FSType XYZ def' substring. */ + if ( ( start_fstype = ft_strstr( embedded_postscript, + "/FSType" ) ) != NULL && + ( start_def = ft_strstr( start_fstype + + sizeof ( "/FSType" ) - 1, + "def" ) ) != NULL ) + { + FT_String* s; + + + for ( s = start_fstype + sizeof ( "/FSType" ) - 1; + s != start_def; + s++ ) + { + if ( *s >= '0' && *s <= '9' ) + { + if ( font_extra->fs_type >= ( FT_USHORT_MAX - 9 ) / 10 ) + { + /* Overflow - ignore the FSType value. */ + font_extra->fs_type = 0U; + break; + } + + font_extra->fs_type *= 10; + font_extra->fs_type += (FT_UShort)( *s - '0' ); + } + else if ( *s != ' ' && *s != '\n' && *s != '\r' ) + { + /* Non-whitespace character between `/FSType' and next `def' */ + /* - ignore the FSType value. */ + font_extra->fs_type = 0U; + break; + } + } + } + } + + cff->font_extra = font_extra; + } + + if ( cff ) + *afont_extra = *cff->font_extra; + + Fail: + return error; + } + + FT_DEFINE_SERVICE_PSINFOREC( cff_service_ps_info, (PS_GetFontInfoFunc) cff_ps_get_font_info, /* ps_get_font_info */ - (PS_GetFontExtraFunc) NULL, /* ps_get_font_extra */ + (PS_GetFontExtraFunc) cff_ps_get_font_extra, /* ps_get_font_extra */ (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names, /* ps_has_glyph_names */ /* unsupported with CFF fonts */ (PS_GetFontPrivateFunc)NULL, /* ps_get_font_private */ @@ -734,208 +821,12 @@ * PROPERTY SERVICE * */ - static FT_Error - cff_property_set( FT_Module module, /* CFF_Driver */ - const char* property_name, - const void* value, - FT_Bool value_is_string ) - { - FT_Error error = FT_Err_Ok; - CFF_Driver driver = (CFF_Driver)module; - -#ifndef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES - FT_UNUSED( value_is_string ); -#endif - - - if ( !ft_strcmp( property_name, "darkening-parameters" ) ) - { - FT_Int* darken_params; - FT_Int x1, y1, x2, y2, x3, y3, x4, y4; - -#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES - FT_Int dp[8]; - - - if ( value_is_string ) - { - const char* s = (const char*)value; - char* ep; - int i; - - - /* eight comma-separated numbers */ - for ( i = 0; i < 7; i++ ) - { - dp[i] = (FT_Int)ft_strtol( s, &ep, 10 ); - if ( *ep != ',' || s == ep ) - return FT_THROW( Invalid_Argument ); - - s = ep + 1; - } - - dp[7] = (FT_Int)ft_strtol( s, &ep, 10 ); - if ( !( *ep == '\0' || *ep == ' ' ) || s == ep ) - return FT_THROW( Invalid_Argument ); - - darken_params = dp; - } - else -#endif - darken_params = (FT_Int*)value; - - x1 = darken_params[0]; - y1 = darken_params[1]; - x2 = darken_params[2]; - y2 = darken_params[3]; - x3 = darken_params[4]; - y3 = darken_params[5]; - x4 = darken_params[6]; - y4 = darken_params[7]; - - if ( x1 < 0 || x2 < 0 || x3 < 0 || x4 < 0 || - y1 < 0 || y2 < 0 || y3 < 0 || y4 < 0 || - x1 > x2 || x2 > x3 || x3 > x4 || - y1 > 500 || y2 > 500 || y3 > 500 || y4 > 500 ) - return FT_THROW( Invalid_Argument ); - - driver->darken_params[0] = x1; - driver->darken_params[1] = y1; - driver->darken_params[2] = x2; - driver->darken_params[3] = y2; - driver->darken_params[4] = x3; - driver->darken_params[5] = y3; - driver->darken_params[6] = x4; - driver->darken_params[7] = y4; - - return error; - } - else if ( !ft_strcmp( property_name, "hinting-engine" ) ) - { -#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES - if ( value_is_string ) - { - const char* s = (const char*)value; - - - if ( !ft_strcmp( s, "adobe" ) ) - driver->hinting_engine = FT_CFF_HINTING_ADOBE; -#ifdef CFF_CONFIG_OPTION_OLD_ENGINE - else if ( !ft_strcmp( s, "freetype" ) ) - driver->hinting_engine = FT_CFF_HINTING_FREETYPE; -#endif - else - return FT_THROW( Invalid_Argument ); - } - else -#endif - { - FT_UInt* hinting_engine = (FT_UInt*)value; - - if ( *hinting_engine == FT_CFF_HINTING_ADOBE -#ifdef CFF_CONFIG_OPTION_OLD_ENGINE - || *hinting_engine == FT_CFF_HINTING_FREETYPE -#endif - ) - driver->hinting_engine = *hinting_engine; - else - error = FT_ERR( Unimplemented_Feature ); - - return error; - } - } - else if ( !ft_strcmp( property_name, "no-stem-darkening" ) ) - { -#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES - if ( value_is_string ) - { - const char* s = (const char*)value; - long nsd = ft_strtol( s, NULL, 10 ); - - - if ( nsd == 0 ) - driver->no_stem_darkening = 0; - else if ( nsd == 1 ) - driver->no_stem_darkening = 1; - else - return FT_THROW( Invalid_Argument ); - } - else -#endif - { - FT_Bool* no_stem_darkening = (FT_Bool*)value; - - - driver->no_stem_darkening = *no_stem_darkening; - } - - return error; - } - - FT_TRACE0(( "cff_property_set: missing property `%s'\n", - property_name )); - return FT_THROW( Missing_Property ); - } - - - static FT_Error - cff_property_get( FT_Module module, /* CFF_Driver */ - const char* property_name, - const void* value ) - { - FT_Error error = FT_Err_Ok; - CFF_Driver driver = (CFF_Driver)module; - - - if ( !ft_strcmp( property_name, "darkening-parameters" ) ) - { - FT_Int* darken_params = driver->darken_params; - FT_Int* val = (FT_Int*)value; - - - val[0] = darken_params[0]; - val[1] = darken_params[1]; - val[2] = darken_params[2]; - val[3] = darken_params[3]; - val[4] = darken_params[4]; - val[5] = darken_params[5]; - val[6] = darken_params[6]; - val[7] = darken_params[7]; - - return error; - } - else if ( !ft_strcmp( property_name, "hinting-engine" ) ) - { - FT_UInt hinting_engine = driver->hinting_engine; - FT_UInt* val = (FT_UInt*)value; - - - *val = hinting_engine; - - return error; - } - else if ( !ft_strcmp( property_name, "no-stem-darkening" ) ) - { - FT_Bool no_stem_darkening = driver->no_stem_darkening; - FT_Bool* val = (FT_Bool*)value; - - - *val = no_stem_darkening; - - return error; - } - - FT_TRACE0(( "cff_property_get: missing property `%s'\n", - property_name )); - return FT_THROW( Missing_Property ); - } - FT_DEFINE_SERVICE_PROPERTIESREC( cff_service_properties, - (FT_Properties_SetFunc)cff_property_set, /* set_property */ - (FT_Properties_GetFunc)cff_property_get ) /* get_property */ + (FT_Properties_SetFunc)ps_property_set, /* set_property */ + (FT_Properties_GetFunc)ps_property_get ) /* get_property */ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT @@ -1004,6 +895,17 @@ } + static FT_Error + cff_set_instance( CFF_Face face, + FT_UInt instance_index ) + { + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + + + return mm->set_instance( FT_FACE( face ), instance_index ); + } + + FT_DEFINE_SERVICE_MULTIMASTERSREC( cff_service_multi_masters, @@ -1014,13 +916,73 @@ (FT_Get_MM_Var_Func) cff_get_mm_var, /* get_mm_var */ (FT_Set_Var_Design_Func)cff_set_var_design, /* set_var_design */ (FT_Get_Var_Design_Func)cff_get_var_design, /* get_var_design */ + (FT_Set_Instance_Func) cff_set_instance, /* set_instance */ (FT_Get_Var_Blend_Func) cff_get_var_blend, /* get_var_blend */ (FT_Done_Blend_Func) cff_done_blend /* done_blend */ ) + + + /* + * METRICS VARIATIONS SERVICE + * + */ + + static FT_Error + cff_hadvance_adjust( CFF_Face face, + FT_UInt gindex, + FT_Int *avalue ) + { + FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var; + + + return var->hadvance_adjust( FT_FACE( face ), gindex, avalue ); + } + + + static void + cff_metrics_adjust( CFF_Face face ) + { + FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var; + + + var->metrics_adjust( FT_FACE( face ) ); + } + + + FT_DEFINE_SERVICE_METRICSVARIATIONSREC( + cff_service_metrics_variations, + + (FT_HAdvance_Adjust_Func)cff_hadvance_adjust, /* hadvance_adjust */ + (FT_LSB_Adjust_Func) NULL, /* lsb_adjust */ + (FT_RSB_Adjust_Func) NULL, /* rsb_adjust */ + + (FT_VAdvance_Adjust_Func)NULL, /* vadvance_adjust */ + (FT_TSB_Adjust_Func) NULL, /* tsb_adjust */ + (FT_BSB_Adjust_Func) NULL, /* bsb_adjust */ + (FT_VOrg_Adjust_Func) NULL, /* vorg_adjust */ + + (FT_Metrics_Adjust_Func) cff_metrics_adjust /* metrics_adjust */ + ) #endif + /* + * CFFLOAD SERVICE + * + */ + + FT_DEFINE_SERVICE_CFFLOADREC( + cff_service_cff_load, + + (FT_Get_Standard_Encoding_Func)cff_get_standard_encoding, + (FT_Load_Private_Dict_Func) cff_load_private_dict, + (FT_FD_Select_Get_Func) cff_fd_select_get, + (FT_Blend_Check_Vector_Func) cff_blend_check_vector, + (FT_Blend_Build_Vector_Func) cff_blend_build_vector + ) + + /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ @@ -1035,20 +997,22 @@ #if !defined FT_CONFIG_OPTION_NO_GLYPH_NAMES && \ defined TT_CONFIG_OPTION_GX_VAR_SUPPORT - FT_DEFINE_SERVICEDESCREC8( + FT_DEFINE_SERVICEDESCREC10( cff_services, FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF, FT_SERVICE_ID_MULTI_MASTERS, &CFF_SERVICE_MULTI_MASTERS_GET, + FT_SERVICE_ID_METRICS_VARIATIONS, &CFF_SERVICE_METRICS_VAR_GET, FT_SERVICE_ID_POSTSCRIPT_INFO, &CFF_SERVICE_PS_INFO_GET, FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET, FT_SERVICE_ID_GLYPH_DICT, &CFF_SERVICE_GLYPH_DICT_GET, FT_SERVICE_ID_TT_CMAP, &CFF_SERVICE_GET_CMAP_INFO_GET, FT_SERVICE_ID_CID, &CFF_SERVICE_CID_INFO_GET, - FT_SERVICE_ID_PROPERTIES, &CFF_SERVICE_PROPERTIES_GET + FT_SERVICE_ID_PROPERTIES, &CFF_SERVICE_PROPERTIES_GET, + FT_SERVICE_ID_CFF_LOAD, &CFF_SERVICE_CFF_LOAD_GET ) #elif !defined FT_CONFIG_OPTION_NO_GLYPH_NAMES - FT_DEFINE_SERVICEDESCREC7( + FT_DEFINE_SERVICEDESCREC8( cff_services, FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF, @@ -1057,22 +1021,25 @@ FT_SERVICE_ID_GLYPH_DICT, &CFF_SERVICE_GLYPH_DICT_GET, FT_SERVICE_ID_TT_CMAP, &CFF_SERVICE_GET_CMAP_INFO_GET, FT_SERVICE_ID_CID, &CFF_SERVICE_CID_INFO_GET, - FT_SERVICE_ID_PROPERTIES, &CFF_SERVICE_PROPERTIES_GET + FT_SERVICE_ID_PROPERTIES, &CFF_SERVICE_PROPERTIES_GET, + FT_SERVICE_ID_CFF_LOAD, &CFF_SERVICE_CFF_LOAD_GET ) #elif defined TT_CONFIG_OPTION_GX_VAR_SUPPORT - FT_DEFINE_SERVICEDESCREC7( + FT_DEFINE_SERVICEDESCREC9( cff_services, FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF, FT_SERVICE_ID_MULTI_MASTERS, &CFF_SERVICE_MULTI_MASTERS_GET, + FT_SERVICE_ID_METRICS_VARIATIONS, &CFF_SERVICE_METRICS_VAR_GET, FT_SERVICE_ID_POSTSCRIPT_INFO, &CFF_SERVICE_PS_INFO_GET, FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET, FT_SERVICE_ID_TT_CMAP, &CFF_SERVICE_GET_CMAP_INFO_GET, FT_SERVICE_ID_CID, &CFF_SERVICE_CID_INFO_GET, - FT_SERVICE_ID_PROPERTIES, &CFF_SERVICE_PROPERTIES_GET + FT_SERVICE_ID_PROPERTIES, &CFF_SERVICE_PROPERTIES_GET, + FT_SERVICE_ID_CFF_LOAD, &CFF_SERVICE_CFF_LOAD_GET ) #else - FT_DEFINE_SERVICEDESCREC6( + FT_DEFINE_SERVICEDESCREC7( cff_services, FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF, @@ -1080,7 +1047,8 @@ FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET, FT_SERVICE_ID_TT_CMAP, &CFF_SERVICE_GET_CMAP_INFO_GET, FT_SERVICE_ID_CID, &CFF_SERVICE_CID_INFO_GET, - FT_SERVICE_ID_PROPERTIES, &CFF_SERVICE_PROPERTIES_GET + FT_SERVICE_ID_PROPERTIES, &CFF_SERVICE_PROPERTIES_GET, + FT_SERVICE_ID_CFF_LOAD, &CFF_SERVICE_CFF_LOAD_GET ) #endif @@ -1139,7 +1107,7 @@ FT_MODULE_DRIVER_HAS_HINTER | FT_MODULE_DRIVER_HINTS_LIGHTLY, - sizeof ( CFF_DriverRec ), + sizeof ( PS_DriverRec ), "cff", 0x10000L, 0x20000L, diff --git a/modules/freetype2/src/cff/cffdrivr.h b/modules/freetype2/src/cff/cffdrivr.h index d7b059837..ad7c3ad70 100644 --- a/modules/freetype2/src/cff/cffdrivr.h +++ b/modules/freetype2/src/cff/cffdrivr.h @@ -4,7 +4,7 @@ /* */ /* High-level OpenType driver interface (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cff/cfferrs.h b/modules/freetype2/src/cff/cfferrs.h index e7fc6eb71..b2e1bfaf9 100644 --- a/modules/freetype2/src/cff/cfferrs.h +++ b/modules/freetype2/src/cff/cfferrs.h @@ -4,7 +4,7 @@ /* */ /* CFF error codes (specification only). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cff/cffgload.c b/modules/freetype2/src/cff/cffgload.c index d8084f865..c58471ce8 100644 --- a/modules/freetype2/src/cff/cffgload.c +++ b/modules/freetype2/src/cff/cffgload.c @@ -4,7 +4,7 @@ /* */ /* OpenType Glyph Loader (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -20,13 +20,13 @@ #include FT_INTERNAL_DEBUG_H #include FT_INTERNAL_STREAM_H #include FT_INTERNAL_SFNT_H +#include FT_INTERNAL_CALC_H +#include FT_INTERNAL_POSTSCRIPT_AUX_H #include FT_OUTLINE_H -#include FT_CFF_DRIVER_H +#include FT_DRIVER_H -#include "cffobjs.h" #include "cffload.h" #include "cffgload.h" -#include "cf2ft.h" /* for cf2_decoder_parse_charstrings */ #include "cfferrs.h" @@ -41,618 +41,6 @@ #define FT_COMPONENT trace_cffgload -#ifdef CFF_CONFIG_OPTION_OLD_ENGINE - - typedef enum CFF_Operator_ - { - cff_op_unknown = 0, - - cff_op_rmoveto, - cff_op_hmoveto, - cff_op_vmoveto, - - cff_op_rlineto, - cff_op_hlineto, - cff_op_vlineto, - - cff_op_rrcurveto, - cff_op_hhcurveto, - cff_op_hvcurveto, - cff_op_rcurveline, - cff_op_rlinecurve, - cff_op_vhcurveto, - cff_op_vvcurveto, - - cff_op_flex, - cff_op_hflex, - cff_op_hflex1, - cff_op_flex1, - - cff_op_endchar, - - cff_op_hstem, - cff_op_vstem, - cff_op_hstemhm, - cff_op_vstemhm, - - cff_op_hintmask, - cff_op_cntrmask, - cff_op_dotsection, /* deprecated, acts as no-op */ - - cff_op_abs, - cff_op_add, - cff_op_sub, - cff_op_div, - cff_op_neg, - cff_op_random, - cff_op_mul, - cff_op_sqrt, - - cff_op_blend, - - cff_op_drop, - cff_op_exch, - cff_op_index, - cff_op_roll, - cff_op_dup, - - cff_op_put, - cff_op_get, - cff_op_store, - cff_op_load, - - cff_op_and, - cff_op_or, - cff_op_not, - cff_op_eq, - cff_op_ifelse, - - cff_op_callsubr, - cff_op_callgsubr, - cff_op_return, - - /* Type 1 opcodes: invalid but seen in real life */ - cff_op_hsbw, - cff_op_closepath, - cff_op_callothersubr, - cff_op_pop, - cff_op_seac, - cff_op_sbw, - cff_op_setcurrentpoint, - - /* do not remove */ - cff_op_max - - } CFF_Operator; - - -#define CFF_COUNT_CHECK_WIDTH 0x80 -#define CFF_COUNT_EXACT 0x40 -#define CFF_COUNT_CLEAR_STACK 0x20 - - /* count values which have the `CFF_COUNT_CHECK_WIDTH' flag set are */ - /* used for checking the width and requested numbers of arguments */ - /* only; they are set to zero afterwards */ - - /* the other two flags are informative only and unused currently */ - - static const FT_Byte cff_argument_counts[] = - { - 0, /* unknown */ - - 2 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, /* rmoveto */ - 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, - 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, - - 0 | CFF_COUNT_CLEAR_STACK, /* rlineto */ - 0 | CFF_COUNT_CLEAR_STACK, - 0 | CFF_COUNT_CLEAR_STACK, - - 0 | CFF_COUNT_CLEAR_STACK, /* rrcurveto */ - 0 | CFF_COUNT_CLEAR_STACK, - 0 | CFF_COUNT_CLEAR_STACK, - 0 | CFF_COUNT_CLEAR_STACK, - 0 | CFF_COUNT_CLEAR_STACK, - 0 | CFF_COUNT_CLEAR_STACK, - 0 | CFF_COUNT_CLEAR_STACK, - - 13, /* flex */ - 7, - 9, - 11, - - 0 | CFF_COUNT_CHECK_WIDTH, /* endchar */ - - 2 | CFF_COUNT_CHECK_WIDTH, /* hstem */ - 2 | CFF_COUNT_CHECK_WIDTH, - 2 | CFF_COUNT_CHECK_WIDTH, - 2 | CFF_COUNT_CHECK_WIDTH, - - 0 | CFF_COUNT_CHECK_WIDTH, /* hintmask */ - 0 | CFF_COUNT_CHECK_WIDTH, /* cntrmask */ - 0, /* dotsection */ - - 1, /* abs */ - 2, - 2, - 2, - 1, - 0, - 2, - 1, - - 1, /* blend */ - - 1, /* drop */ - 2, - 1, - 2, - 1, - - 2, /* put */ - 1, - 4, - 3, - - 2, /* and */ - 2, - 1, - 2, - 4, - - 1, /* callsubr */ - 1, - 0, - - 2, /* hsbw */ - 0, - 0, - 0, - 5, /* seac */ - 4, /* sbw */ - 2 /* setcurrentpoint */ - }; - -#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */ - - - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /********** *********/ - /********** *********/ - /********** GENERIC CHARSTRING PARSING *********/ - /********** *********/ - /********** *********/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* cff_builder_init */ - /* */ - /* <Description> */ - /* Initializes a given glyph builder. */ - /* */ - /* <InOut> */ - /* builder :: A pointer to the glyph builder to initialize. */ - /* */ - /* <Input> */ - /* face :: The current face object. */ - /* */ - /* size :: The current size object. */ - /* */ - /* glyph :: The current glyph object. */ - /* */ - /* hinting :: Whether hinting is active. */ - /* */ - static void - cff_builder_init( CFF_Builder* builder, - TT_Face face, - CFF_Size size, - CFF_GlyphSlot glyph, - FT_Bool hinting ) - { - builder->path_begun = 0; - builder->load_points = 1; - - builder->face = face; - builder->glyph = glyph; - builder->memory = face->root.memory; - - if ( glyph ) - { - FT_GlyphLoader loader = glyph->root.internal->loader; - - - builder->loader = loader; - builder->base = &loader->base.outline; - builder->current = &loader->current.outline; - FT_GlyphLoader_Rewind( loader ); - - builder->hints_globals = NULL; - builder->hints_funcs = NULL; - - if ( hinting && size ) - { - CFF_Internal internal = (CFF_Internal)size->root.internal; - - - builder->hints_globals = (void *)internal->topfont; - builder->hints_funcs = glyph->root.internal->glyph_hints; - } - } - - builder->pos_x = 0; - builder->pos_y = 0; - - builder->left_bearing.x = 0; - builder->left_bearing.y = 0; - builder->advance.x = 0; - builder->advance.y = 0; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* cff_builder_done */ - /* */ - /* <Description> */ - /* Finalizes a given glyph builder. Its contents can still be used */ - /* after the call, but the function saves important information */ - /* within the corresponding glyph slot. */ - /* */ - /* <Input> */ - /* builder :: A pointer to the glyph builder to finalize. */ - /* */ - static void - cff_builder_done( CFF_Builder* builder ) - { - CFF_GlyphSlot glyph = builder->glyph; - - - if ( glyph ) - glyph->root.outline = *builder->base; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* cff_compute_bias */ - /* */ - /* <Description> */ - /* Computes the bias value in dependence of the number of glyph */ - /* subroutines. */ - /* */ - /* <Input> */ - /* in_charstring_type :: The `CharstringType' value of the top DICT */ - /* dictionary. */ - /* */ - /* num_subrs :: The number of glyph subroutines. */ - /* */ - /* <Return> */ - /* The bias value. */ - static FT_Int - cff_compute_bias( FT_Int in_charstring_type, - FT_UInt num_subrs ) - { - FT_Int result; - - - if ( in_charstring_type == 1 ) - result = 0; - else if ( num_subrs < 1240 ) - result = 107; - else if ( num_subrs < 33900U ) - result = 1131; - else - result = 32768U; - - return result; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* cff_decoder_init */ - /* */ - /* <Description> */ - /* Initializes a given glyph decoder. */ - /* */ - /* <InOut> */ - /* decoder :: A pointer to the glyph builder to initialize. */ - /* */ - /* <Input> */ - /* face :: The current face object. */ - /* */ - /* size :: The current size object. */ - /* */ - /* slot :: The current glyph object. */ - /* */ - /* hinting :: Whether hinting is active. */ - /* */ - /* hint_mode :: The hinting mode. */ - /* */ - FT_LOCAL_DEF( void ) - cff_decoder_init( CFF_Decoder* decoder, - TT_Face face, - CFF_Size size, - CFF_GlyphSlot slot, - FT_Bool hinting, - FT_Render_Mode hint_mode ) - { - CFF_Font cff = (CFF_Font)face->extra.data; - - - /* clear everything */ - FT_ZERO( decoder ); - - /* initialize builder */ - cff_builder_init( &decoder->builder, face, size, slot, hinting ); - - /* initialize Type2 decoder */ - decoder->cff = cff; - decoder->num_globals = cff->global_subrs_index.count; - decoder->globals = cff->global_subrs; - decoder->globals_bias = cff_compute_bias( - cff->top_font.font_dict.charstring_type, - decoder->num_globals ); - - decoder->hint_mode = hint_mode; - } - - - /* this function is used to select the subfont */ - /* and the locals subrs array */ - FT_LOCAL_DEF( FT_Error ) - cff_decoder_prepare( CFF_Decoder* decoder, - CFF_Size size, - FT_UInt glyph_index ) - { - CFF_Builder *builder = &decoder->builder; - CFF_Font cff = (CFF_Font)builder->face->extra.data; - CFF_SubFont sub = &cff->top_font; - FT_Error error = FT_Err_Ok; - - - /* manage CID fonts */ - if ( cff->num_subfonts ) - { - FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, glyph_index ); - - - if ( fd_index >= cff->num_subfonts ) - { - FT_TRACE4(( "cff_decoder_prepare: invalid CID subfont index\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - FT_TRACE3(( " in subfont %d:\n", fd_index )); - - sub = cff->subfonts[fd_index]; - - if ( builder->hints_funcs && size ) - { - CFF_Internal internal = (CFF_Internal)size->root.internal; - - - /* for CFFs without subfonts, this value has already been set */ - builder->hints_globals = (void *)internal->subfonts[fd_index]; - } - } - - decoder->num_locals = sub->local_subrs_index.count; - decoder->locals = sub->local_subrs; - decoder->locals_bias = cff_compute_bias( - decoder->cff->top_font.font_dict.charstring_type, - decoder->num_locals ); - - decoder->glyph_width = sub->private_dict.default_width; - decoder->nominal_width = sub->private_dict.nominal_width; - - decoder->current_subfont = sub; /* for Adobe's CFF handler */ - - Exit: - return error; - } - - - /* check that there is enough space for `count' more points */ - FT_LOCAL_DEF( FT_Error ) - cff_check_points( CFF_Builder* builder, - FT_Int count ) - { - return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 ); - } - - - /* add a new point, do not check space */ - FT_LOCAL_DEF( void ) - cff_builder_add_point( CFF_Builder* builder, - FT_Pos x, - FT_Pos y, - FT_Byte flag ) - { - FT_Outline* outline = builder->current; - - - if ( builder->load_points ) - { - FT_Vector* point = outline->points + outline->n_points; - FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; - -#ifdef CFF_CONFIG_OPTION_OLD_ENGINE - CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( builder->face ); - - - if ( driver->hinting_engine == FT_CFF_HINTING_FREETYPE ) - { - point->x = x >> 16; - point->y = y >> 16; - } - else -#endif - { - /* cf2_decoder_parse_charstrings uses 16.16 coordinates */ - point->x = x >> 10; - point->y = y >> 10; - } - *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC ); - } - - outline->n_points++; - } - - - /* check space for a new on-curve point, then add it */ - FT_LOCAL_DEF( FT_Error ) - cff_builder_add_point1( CFF_Builder* builder, - FT_Pos x, - FT_Pos y ) - { - FT_Error error; - - - error = cff_check_points( builder, 1 ); - if ( !error ) - cff_builder_add_point( builder, x, y, 1 ); - - return error; - } - - - /* check space for a new contour, then add it */ - static FT_Error - cff_builder_add_contour( CFF_Builder* builder ) - { - FT_Outline* outline = builder->current; - FT_Error error; - - - if ( !builder->load_points ) - { - outline->n_contours++; - return FT_Err_Ok; - } - - error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 ); - if ( !error ) - { - if ( outline->n_contours > 0 ) - outline->contours[outline->n_contours - 1] = - (short)( outline->n_points - 1 ); - - outline->n_contours++; - } - - return error; - } - - - /* if a path was begun, add its first on-curve point */ - FT_LOCAL_DEF( FT_Error ) - cff_builder_start_point( CFF_Builder* builder, - FT_Pos x, - FT_Pos y ) - { - FT_Error error = FT_Err_Ok; - - - /* test whether we are building a new contour */ - if ( !builder->path_begun ) - { - builder->path_begun = 1; - error = cff_builder_add_contour( builder ); - if ( !error ) - error = cff_builder_add_point1( builder, x, y ); - } - - return error; - } - - - /* close the current contour */ - FT_LOCAL_DEF( void ) - cff_builder_close_contour( CFF_Builder* builder ) - { - FT_Outline* outline = builder->current; - FT_Int first; - - - if ( !outline ) - return; - - first = outline->n_contours <= 1 - ? 0 : outline->contours[outline->n_contours - 2] + 1; - - /* We must not include the last point in the path if it */ - /* is located on the first point. */ - if ( outline->n_points > 1 ) - { - FT_Vector* p1 = outline->points + first; - FT_Vector* p2 = outline->points + outline->n_points - 1; - FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1; - - - /* `delete' last point only if it coincides with the first */ - /* point and if it is not a control point (which can happen). */ - if ( p1->x == p2->x && p1->y == p2->y ) - if ( *control == FT_CURVE_TAG_ON ) - outline->n_points--; - } - - if ( outline->n_contours > 0 ) - { - /* Don't add contours only consisting of one point, i.e., */ - /* check whether begin point and last point are the same. */ - if ( first == outline->n_points - 1 ) - { - outline->n_contours--; - outline->n_points--; - } - else - outline->contours[outline->n_contours - 1] = - (short)( outline->n_points - 1 ); - } - } - - - FT_LOCAL_DEF( FT_Int ) - cff_lookup_glyph_by_stdcharcode( CFF_Font cff, - FT_Int charcode ) - { - FT_UInt n; - FT_UShort glyph_sid; - - - /* CID-keyed fonts don't have glyph names */ - if ( !cff->charset.sids ) - return -1; - - /* check range of standard char code */ - if ( charcode < 0 || charcode > 255 ) - return -1; - - /* Get code to SID mapping from `cff_standard_encoding'. */ - glyph_sid = cff_get_standard_encoding( (FT_UInt)charcode ); - - for ( n = 0; n < cff->num_glyphs; n++ ) - { - if ( cff->charset.sids[n] == glyph_sid ) - return (FT_Int)n; - } - - return -1; - } - - FT_LOCAL_DEF( FT_Error ) cff_get_glyph_data( TT_Face face, FT_UInt glyph_index, @@ -724,1936 +112,6 @@ } -#ifdef CFF_CONFIG_OPTION_OLD_ENGINE - - static FT_Error - cff_operator_seac( CFF_Decoder* decoder, - FT_Pos asb, - FT_Pos adx, - FT_Pos ady, - FT_Int bchar, - FT_Int achar ) - { - FT_Error error; - CFF_Builder* builder = &decoder->builder; - FT_Int bchar_index, achar_index; - TT_Face face = decoder->builder.face; - FT_Vector left_bearing, advance; - FT_Byte* charstring; - FT_ULong charstring_len; - FT_Pos glyph_width; - - - if ( decoder->seac ) - { - FT_ERROR(( "cff_operator_seac: invalid nested seac\n" )); - return FT_THROW( Syntax_Error ); - } - - adx += decoder->builder.left_bearing.x; - ady += decoder->builder.left_bearing.y; - -#ifdef FT_CONFIG_OPTION_INCREMENTAL - /* Incremental fonts don't necessarily have valid charsets. */ - /* They use the character code, not the glyph index, in this case. */ - if ( face->root.internal->incremental_interface ) - { - bchar_index = bchar; - achar_index = achar; - } - else -#endif /* FT_CONFIG_OPTION_INCREMENTAL */ - { - CFF_Font cff = (CFF_Font)(face->extra.data); - - - bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar ); - achar_index = cff_lookup_glyph_by_stdcharcode( cff, achar ); - } - - if ( bchar_index < 0 || achar_index < 0 ) - { - FT_ERROR(( "cff_operator_seac:" - " invalid seac character code arguments\n" )); - return FT_THROW( Syntax_Error ); - } - - /* If we are trying to load a composite glyph, do not load the */ - /* accent character and return the array of subglyphs. */ - if ( builder->no_recurse ) - { - FT_GlyphSlot glyph = (FT_GlyphSlot)builder->glyph; - FT_GlyphLoader loader = glyph->internal->loader; - FT_SubGlyph subg; - - - /* reallocate subglyph array if necessary */ - error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 ); - if ( error ) - goto Exit; - - subg = loader->current.subglyphs; - - /* subglyph 0 = base character */ - subg->index = bchar_index; - subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES | - FT_SUBGLYPH_FLAG_USE_MY_METRICS; - subg->arg1 = 0; - subg->arg2 = 0; - subg++; - - /* subglyph 1 = accent character */ - subg->index = achar_index; - subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES; - subg->arg1 = (FT_Int)( adx >> 16 ); - subg->arg2 = (FT_Int)( ady >> 16 ); - - /* set up remaining glyph fields */ - glyph->num_subglyphs = 2; - glyph->subglyphs = loader->base.subglyphs; - glyph->format = FT_GLYPH_FORMAT_COMPOSITE; - - loader->current.num_subglyphs = 2; - } - - FT_GlyphLoader_Prepare( builder->loader ); - - /* First load `bchar' in builder */ - error = cff_get_glyph_data( face, (FT_UInt)bchar_index, - &charstring, &charstring_len ); - if ( !error ) - { - /* the seac operator must not be nested */ - decoder->seac = TRUE; - error = cff_decoder_parse_charstrings( decoder, charstring, - charstring_len, 0 ); - decoder->seac = FALSE; - - cff_free_glyph_data( face, &charstring, charstring_len ); - - if ( error ) - goto Exit; - } - - /* Save the left bearing, advance and glyph width of the base */ - /* character as they will be erased by the next load. */ - - left_bearing = builder->left_bearing; - advance = builder->advance; - glyph_width = decoder->glyph_width; - - builder->left_bearing.x = 0; - builder->left_bearing.y = 0; - - builder->pos_x = adx - asb; - builder->pos_y = ady; - - /* Now load `achar' on top of the base outline. */ - error = cff_get_glyph_data( face, (FT_UInt)achar_index, - &charstring, &charstring_len ); - if ( !error ) - { - /* the seac operator must not be nested */ - decoder->seac = TRUE; - error = cff_decoder_parse_charstrings( decoder, charstring, - charstring_len, 0 ); - decoder->seac = FALSE; - - cff_free_glyph_data( face, &charstring, charstring_len ); - - if ( error ) - goto Exit; - } - - /* Restore the left side bearing, advance and glyph width */ - /* of the base character. */ - builder->left_bearing = left_bearing; - builder->advance = advance; - decoder->glyph_width = glyph_width; - - builder->pos_x = 0; - builder->pos_y = 0; - - Exit: - return error; - } - - - /*************************************************************************/ - /* */ - /* <Function> */ - /* cff_decoder_parse_charstrings */ - /* */ - /* <Description> */ - /* Parses a given Type 2 charstrings program. */ - /* */ - /* <InOut> */ - /* decoder :: The current Type 1 decoder. */ - /* */ - /* <Input> */ - /* charstring_base :: The base of the charstring stream. */ - /* */ - /* charstring_len :: The length in bytes of the charstring stream. */ - /* */ - /* in_dict :: Set to 1 if function is called from top or */ - /* private DICT (needed for Multiple Master CFFs). */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - cff_decoder_parse_charstrings( CFF_Decoder* decoder, - FT_Byte* charstring_base, - FT_ULong charstring_len, - FT_Bool in_dict ) - { - FT_Error error; - CFF_Decoder_Zone* zone; - FT_Byte* ip; - FT_Byte* limit; - CFF_Builder* builder = &decoder->builder; - FT_Pos x, y; - FT_Fixed seed; - FT_Fixed* stack; - FT_Int charstring_type = - decoder->cff->top_font.font_dict.charstring_type; - FT_UShort num_designs = - decoder->cff->top_font.font_dict.num_designs; - FT_UShort num_axes = - decoder->cff->top_font.font_dict.num_axes; - - T2_Hints_Funcs hinter; - - - /* set default width */ - decoder->num_hints = 0; - decoder->read_width = 1; - - /* compute random seed from stack address of parameter */ - seed = (FT_Fixed)( ( (FT_Offset)(char*)&seed ^ - (FT_Offset)(char*)&decoder ^ - (FT_Offset)(char*)&charstring_base ) & - FT_ULONG_MAX ); - seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL; - if ( seed == 0 ) - seed = 0x7384; - - /* initialize the decoder */ - decoder->top = decoder->stack; - decoder->zone = decoder->zones; - zone = decoder->zones; - stack = decoder->top; - - hinter = (T2_Hints_Funcs)builder->hints_funcs; - - builder->path_begun = 0; - - zone->base = charstring_base; - limit = zone->limit = charstring_base + charstring_len; - ip = zone->cursor = zone->base; - - error = FT_Err_Ok; - - x = builder->pos_x; - y = builder->pos_y; - - /* begin hints recording session, if any */ - if ( hinter ) - hinter->open( hinter->hints ); - - /* now execute loop */ - while ( ip < limit ) - { - CFF_Operator op; - FT_Byte v; - - - /********************************************************************/ - /* */ - /* Decode operator or operand */ - /* */ - v = *ip++; - if ( v >= 32 || v == 28 ) - { - FT_Int shift = 16; - FT_Int32 val; - - - /* this is an operand, push it on the stack */ - - /* if we use shifts, all computations are done with unsigned */ - /* values; the conversion to a signed value is the last step */ - if ( v == 28 ) - { - if ( ip + 1 >= limit ) - goto Syntax_Error; - val = (FT_Short)( ( (FT_UShort)ip[0] << 8 ) | ip[1] ); - ip += 2; - } - else if ( v < 247 ) - val = (FT_Int32)v - 139; - else if ( v < 251 ) - { - if ( ip >= limit ) - goto Syntax_Error; - val = ( (FT_Int32)v - 247 ) * 256 + *ip++ + 108; - } - else if ( v < 255 ) - { - if ( ip >= limit ) - goto Syntax_Error; - val = -( (FT_Int32)v - 251 ) * 256 - *ip++ - 108; - } - else - { - if ( ip + 3 >= limit ) - goto Syntax_Error; - val = (FT_Int32)( ( (FT_UInt32)ip[0] << 24 ) | - ( (FT_UInt32)ip[1] << 16 ) | - ( (FT_UInt32)ip[2] << 8 ) | - (FT_UInt32)ip[3] ); - ip += 4; - if ( charstring_type == 2 ) - shift = 0; - } - if ( decoder->top - stack >= CFF_MAX_OPERANDS ) - goto Stack_Overflow; - - val = (FT_Int32)( (FT_UInt32)val << shift ); - *decoder->top++ = val; - -#ifdef FT_DEBUG_LEVEL_TRACE - if ( !( val & 0xFFFFL ) ) - FT_TRACE4(( " %hd", (FT_Short)( (FT_UInt32)val >> 16 ) )); - else - FT_TRACE4(( " %.5f", val / 65536.0 )); -#endif - - } - else - { - /* The specification says that normally arguments are to be taken */ - /* from the bottom of the stack. However, this seems not to be */ - /* correct, at least for Acroread 7.0.8 on GNU/Linux: It pops the */ - /* arguments similar to a PS interpreter. */ - - FT_Fixed* args = decoder->top; - FT_Int num_args = (FT_Int)( args - decoder->stack ); - FT_Int req_args; - - - /* find operator */ - op = cff_op_unknown; - - switch ( v ) - { - case 1: - op = cff_op_hstem; - break; - case 3: - op = cff_op_vstem; - break; - case 4: - op = cff_op_vmoveto; - break; - case 5: - op = cff_op_rlineto; - break; - case 6: - op = cff_op_hlineto; - break; - case 7: - op = cff_op_vlineto; - break; - case 8: - op = cff_op_rrcurveto; - break; - case 9: - op = cff_op_closepath; - break; - case 10: - op = cff_op_callsubr; - break; - case 11: - op = cff_op_return; - break; - case 12: - { - if ( ip >= limit ) - goto Syntax_Error; - v = *ip++; - - switch ( v ) - { - case 0: - op = cff_op_dotsection; - break; - case 1: /* this is actually the Type1 vstem3 operator */ - op = cff_op_vstem; - break; - case 2: /* this is actually the Type1 hstem3 operator */ - op = cff_op_hstem; - break; - case 3: - op = cff_op_and; - break; - case 4: - op = cff_op_or; - break; - case 5: - op = cff_op_not; - break; - case 6: - op = cff_op_seac; - break; - case 7: - op = cff_op_sbw; - break; - case 8: - op = cff_op_store; - break; - case 9: - op = cff_op_abs; - break; - case 10: - op = cff_op_add; - break; - case 11: - op = cff_op_sub; - break; - case 12: - op = cff_op_div; - break; - case 13: - op = cff_op_load; - break; - case 14: - op = cff_op_neg; - break; - case 15: - op = cff_op_eq; - break; - case 16: - op = cff_op_callothersubr; - break; - case 17: - op = cff_op_pop; - break; - case 18: - op = cff_op_drop; - break; - case 20: - op = cff_op_put; - break; - case 21: - op = cff_op_get; - break; - case 22: - op = cff_op_ifelse; - break; - case 23: - op = cff_op_random; - break; - case 24: - op = cff_op_mul; - break; - case 26: - op = cff_op_sqrt; - break; - case 27: - op = cff_op_dup; - break; - case 28: - op = cff_op_exch; - break; - case 29: - op = cff_op_index; - break; - case 30: - op = cff_op_roll; - break; - case 33: - op = cff_op_setcurrentpoint; - break; - case 34: - op = cff_op_hflex; - break; - case 35: - op = cff_op_flex; - break; - case 36: - op = cff_op_hflex1; - break; - case 37: - op = cff_op_flex1; - break; - default: - FT_TRACE4(( " unknown op (12, %d)\n", v )); - break; - } - } - break; - case 13: - op = cff_op_hsbw; - break; - case 14: - op = cff_op_endchar; - break; - case 16: - op = cff_op_blend; - break; - case 18: - op = cff_op_hstemhm; - break; - case 19: - op = cff_op_hintmask; - break; - case 20: - op = cff_op_cntrmask; - break; - case 21: - op = cff_op_rmoveto; - break; - case 22: - op = cff_op_hmoveto; - break; - case 23: - op = cff_op_vstemhm; - break; - case 24: - op = cff_op_rcurveline; - break; - case 25: - op = cff_op_rlinecurve; - break; - case 26: - op = cff_op_vvcurveto; - break; - case 27: - op = cff_op_hhcurveto; - break; - case 29: - op = cff_op_callgsubr; - break; - case 30: - op = cff_op_vhcurveto; - break; - case 31: - op = cff_op_hvcurveto; - break; - default: - FT_TRACE4(( " unknown op (%d)\n", v )); - break; - } - - if ( op == cff_op_unknown ) - continue; - - /* in Multiple Master CFFs, T2 charstrings can appear in */ - /* dictionaries, but some operators are prohibited */ - if ( in_dict ) - { - switch ( op ) - { - case cff_op_hstem: - case cff_op_vstem: - case cff_op_vmoveto: - case cff_op_rlineto: - case cff_op_hlineto: - case cff_op_vlineto: - case cff_op_rrcurveto: - case cff_op_hstemhm: - case cff_op_hintmask: - case cff_op_cntrmask: - case cff_op_rmoveto: - case cff_op_hmoveto: - case cff_op_vstemhm: - case cff_op_rcurveline: - case cff_op_rlinecurve: - case cff_op_vvcurveto: - case cff_op_hhcurveto: - case cff_op_vhcurveto: - case cff_op_hvcurveto: - case cff_op_hflex: - case cff_op_flex: - case cff_op_hflex1: - case cff_op_flex1: - case cff_op_callsubr: - case cff_op_callgsubr: - goto MM_Error; - - default: - break; - } - } - - /* check arguments */ - req_args = cff_argument_counts[op]; - if ( req_args & CFF_COUNT_CHECK_WIDTH ) - { - if ( num_args > 0 && decoder->read_width ) - { - /* If `nominal_width' is non-zero, the number is really a */ - /* difference against `nominal_width'. Else, the number here */ - /* is truly a width, not a difference against `nominal_width'. */ - /* If the font does not set `nominal_width', then */ - /* `nominal_width' defaults to zero, and so we can set */ - /* `glyph_width' to `nominal_width' plus number on the stack */ - /* -- for either case. */ - - FT_Int set_width_ok; - - - switch ( op ) - { - case cff_op_hmoveto: - case cff_op_vmoveto: - set_width_ok = num_args & 2; - break; - - case cff_op_hstem: - case cff_op_vstem: - case cff_op_hstemhm: - case cff_op_vstemhm: - case cff_op_rmoveto: - case cff_op_hintmask: - case cff_op_cntrmask: - set_width_ok = num_args & 1; - break; - - case cff_op_endchar: - /* If there is a width specified for endchar, we either have */ - /* 1 argument or 5 arguments. We like to argue. */ - set_width_ok = in_dict - ? 0 - : ( ( num_args == 5 ) || ( num_args == 1 ) ); - break; - - default: - set_width_ok = 0; - break; - } - - if ( set_width_ok ) - { - decoder->glyph_width = decoder->nominal_width + - ( stack[0] >> 16 ); - - if ( decoder->width_only ) - { - /* we only want the advance width; stop here */ - break; - } - - /* Consumed an argument. */ - num_args--; - } - } - - decoder->read_width = 0; - req_args = 0; - } - - req_args &= 0x000F; - if ( num_args < req_args ) - goto Stack_Underflow; - args -= req_args; - num_args -= req_args; - - /* At this point, `args' points to the first argument of the */ - /* operand in case `req_args' isn't zero. Otherwise, we have */ - /* to adjust `args' manually. */ - - /* Note that we only pop arguments from the stack which we */ - /* really need and can digest so that we can continue in case */ - /* of superfluous stack elements. */ - - switch ( op ) - { - case cff_op_hstem: - case cff_op_vstem: - case cff_op_hstemhm: - case cff_op_vstemhm: - /* the number of arguments is always even here */ - FT_TRACE4(( - op == cff_op_hstem ? " hstem\n" : - ( op == cff_op_vstem ? " vstem\n" : - ( op == cff_op_hstemhm ? " hstemhm\n" : " vstemhm\n" ) ) )); - - if ( hinter ) - hinter->stems( hinter->hints, - ( op == cff_op_hstem || op == cff_op_hstemhm ), - num_args / 2, - args - ( num_args & ~1 ) ); - - decoder->num_hints += num_args / 2; - args = stack; - break; - - case cff_op_hintmask: - case cff_op_cntrmask: - FT_TRACE4(( op == cff_op_hintmask ? " hintmask" : " cntrmask" )); - - /* implement vstem when needed -- */ - /* the specification doesn't say it, but this also works */ - /* with the 'cntrmask' operator */ - /* */ - if ( num_args > 0 ) - { - if ( hinter ) - hinter->stems( hinter->hints, - 0, - num_args / 2, - args - ( num_args & ~1 ) ); - - decoder->num_hints += num_args / 2; - } - - /* In a valid charstring there must be at least one byte */ - /* after `hintmask' or `cntrmask' (e.g., for a `return' */ - /* instruction). Additionally, there must be space for */ - /* `num_hints' bits. */ - - if ( ( ip + ( ( decoder->num_hints + 7 ) >> 3 ) ) >= limit ) - goto Syntax_Error; - - if ( hinter ) - { - if ( op == cff_op_hintmask ) - hinter->hintmask( hinter->hints, - (FT_UInt)builder->current->n_points, - (FT_UInt)decoder->num_hints, - ip ); - else - hinter->counter( hinter->hints, - (FT_UInt)decoder->num_hints, - ip ); - } - -#ifdef FT_DEBUG_LEVEL_TRACE - { - FT_UInt maskbyte; - - - FT_TRACE4(( " (maskbytes:" )); - - for ( maskbyte = 0; - maskbyte < (FT_UInt)( ( decoder->num_hints + 7 ) >> 3 ); - maskbyte++, ip++ ) - FT_TRACE4(( " 0x%02X", *ip )); - - FT_TRACE4(( ")\n" )); - } -#else - ip += ( decoder->num_hints + 7 ) >> 3; -#endif - args = stack; - break; - - case cff_op_rmoveto: - FT_TRACE4(( " rmoveto\n" )); - - cff_builder_close_contour( builder ); - builder->path_begun = 0; - x += args[-2]; - y += args[-1]; - args = stack; - break; - - case cff_op_vmoveto: - FT_TRACE4(( " vmoveto\n" )); - - cff_builder_close_contour( builder ); - builder->path_begun = 0; - y += args[-1]; - args = stack; - break; - - case cff_op_hmoveto: - FT_TRACE4(( " hmoveto\n" )); - - cff_builder_close_contour( builder ); - builder->path_begun = 0; - x += args[-1]; - args = stack; - break; - - case cff_op_rlineto: - FT_TRACE4(( " rlineto\n" )); - - if ( cff_builder_start_point( builder, x, y ) || - cff_check_points( builder, num_args / 2 ) ) - goto Fail; - - if ( num_args < 2 ) - goto Stack_Underflow; - - args -= num_args & ~1; - while ( args < decoder->top ) - { - x += args[0]; - y += args[1]; - cff_builder_add_point( builder, x, y, 1 ); - args += 2; - } - args = stack; - break; - - case cff_op_hlineto: - case cff_op_vlineto: - { - FT_Int phase = ( op == cff_op_hlineto ); - - - FT_TRACE4(( op == cff_op_hlineto ? " hlineto\n" - : " vlineto\n" )); - - if ( num_args < 0 ) - goto Stack_Underflow; - - /* there exist subsetted fonts (found in PDFs) */ - /* which call `hlineto' without arguments */ - if ( num_args == 0 ) - break; - - if ( cff_builder_start_point( builder, x, y ) || - cff_check_points( builder, num_args ) ) - goto Fail; - - args = stack; - while ( args < decoder->top ) - { - if ( phase ) - x += args[0]; - else - y += args[0]; - - if ( cff_builder_add_point1( builder, x, y ) ) - goto Fail; - - args++; - phase ^= 1; - } - args = stack; - } - break; - - case cff_op_rrcurveto: - { - FT_Int nargs; - - - FT_TRACE4(( " rrcurveto\n" )); - - if ( num_args < 6 ) - goto Stack_Underflow; - - nargs = num_args - num_args % 6; - - if ( cff_builder_start_point( builder, x, y ) || - cff_check_points( builder, nargs / 2 ) ) - goto Fail; - - args -= nargs; - while ( args < decoder->top ) - { - x += args[0]; - y += args[1]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[2]; - y += args[3]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[4]; - y += args[5]; - cff_builder_add_point( builder, x, y, 1 ); - args += 6; - } - args = stack; - } - break; - - case cff_op_vvcurveto: - { - FT_Int nargs; - - - FT_TRACE4(( " vvcurveto\n" )); - - if ( num_args < 4 ) - goto Stack_Underflow; - - /* if num_args isn't of the form 4n or 4n+1, */ - /* we enforce it by clearing the second bit */ - - nargs = num_args & ~2; - - if ( cff_builder_start_point( builder, x, y ) ) - goto Fail; - - args -= nargs; - - if ( nargs & 1 ) - { - x += args[0]; - args++; - nargs--; - } - - if ( cff_check_points( builder, 3 * ( nargs / 4 ) ) ) - goto Fail; - - while ( args < decoder->top ) - { - y += args[0]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[1]; - y += args[2]; - cff_builder_add_point( builder, x, y, 0 ); - y += args[3]; - cff_builder_add_point( builder, x, y, 1 ); - args += 4; - } - args = stack; - } - break; - - case cff_op_hhcurveto: - { - FT_Int nargs; - - - FT_TRACE4(( " hhcurveto\n" )); - - if ( num_args < 4 ) - goto Stack_Underflow; - - /* if num_args isn't of the form 4n or 4n+1, */ - /* we enforce it by clearing the second bit */ - - nargs = num_args & ~2; - - if ( cff_builder_start_point( builder, x, y ) ) - goto Fail; - - args -= nargs; - if ( nargs & 1 ) - { - y += args[0]; - args++; - nargs--; - } - - if ( cff_check_points( builder, 3 * ( nargs / 4 ) ) ) - goto Fail; - - while ( args < decoder->top ) - { - x += args[0]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[1]; - y += args[2]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[3]; - cff_builder_add_point( builder, x, y, 1 ); - args += 4; - } - args = stack; - } - break; - - case cff_op_vhcurveto: - case cff_op_hvcurveto: - { - FT_Int phase; - FT_Int nargs; - - - FT_TRACE4(( op == cff_op_vhcurveto ? " vhcurveto\n" - : " hvcurveto\n" )); - - if ( cff_builder_start_point( builder, x, y ) ) - goto Fail; - - if ( num_args < 4 ) - goto Stack_Underflow; - - /* if num_args isn't of the form 8n, 8n+1, 8n+4, or 8n+5, */ - /* we enforce it by clearing the second bit */ - - nargs = num_args & ~2; - - args -= nargs; - if ( cff_check_points( builder, ( nargs / 4 ) * 3 ) ) - goto Stack_Underflow; - - phase = ( op == cff_op_hvcurveto ); - - while ( nargs >= 4 ) - { - nargs -= 4; - if ( phase ) - { - x += args[0]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[1]; - y += args[2]; - cff_builder_add_point( builder, x, y, 0 ); - y += args[3]; - if ( nargs == 1 ) - x += args[4]; - cff_builder_add_point( builder, x, y, 1 ); - } - else - { - y += args[0]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[1]; - y += args[2]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[3]; - if ( nargs == 1 ) - y += args[4]; - cff_builder_add_point( builder, x, y, 1 ); - } - args += 4; - phase ^= 1; - } - args = stack; - } - break; - - case cff_op_rlinecurve: - { - FT_Int num_lines; - FT_Int nargs; - - - FT_TRACE4(( " rlinecurve\n" )); - - if ( num_args < 8 ) - goto Stack_Underflow; - - nargs = num_args & ~1; - num_lines = ( nargs - 6 ) / 2; - - if ( cff_builder_start_point( builder, x, y ) || - cff_check_points( builder, num_lines + 3 ) ) - goto Fail; - - args -= nargs; - - /* first, add the line segments */ - while ( num_lines > 0 ) - { - x += args[0]; - y += args[1]; - cff_builder_add_point( builder, x, y, 1 ); - args += 2; - num_lines--; - } - - /* then the curve */ - x += args[0]; - y += args[1]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[2]; - y += args[3]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[4]; - y += args[5]; - cff_builder_add_point( builder, x, y, 1 ); - args = stack; - } - break; - - case cff_op_rcurveline: - { - FT_Int num_curves; - FT_Int nargs; - - - FT_TRACE4(( " rcurveline\n" )); - - if ( num_args < 8 ) - goto Stack_Underflow; - - nargs = num_args - 2; - nargs = nargs - nargs % 6 + 2; - num_curves = ( nargs - 2 ) / 6; - - if ( cff_builder_start_point( builder, x, y ) || - cff_check_points( builder, num_curves * 3 + 2 ) ) - goto Fail; - - args -= nargs; - - /* first, add the curves */ - while ( num_curves > 0 ) - { - x += args[0]; - y += args[1]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[2]; - y += args[3]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[4]; - y += args[5]; - cff_builder_add_point( builder, x, y, 1 ); - args += 6; - num_curves--; - } - - /* then the final line */ - x += args[0]; - y += args[1]; - cff_builder_add_point( builder, x, y, 1 ); - args = stack; - } - break; - - case cff_op_hflex1: - { - FT_Pos start_y; - - - FT_TRACE4(( " hflex1\n" )); - - /* adding five more points: 4 control points, 1 on-curve point */ - /* -- make sure we have enough space for the start point if it */ - /* needs to be added */ - if ( cff_builder_start_point( builder, x, y ) || - cff_check_points( builder, 6 ) ) - goto Fail; - - /* record the starting point's y position for later use */ - start_y = y; - - /* first control point */ - x += args[0]; - y += args[1]; - cff_builder_add_point( builder, x, y, 0 ); - - /* second control point */ - x += args[2]; - y += args[3]; - cff_builder_add_point( builder, x, y, 0 ); - - /* join point; on curve, with y-value the same as the last */ - /* control point's y-value */ - x += args[4]; - cff_builder_add_point( builder, x, y, 1 ); - - /* third control point, with y-value the same as the join */ - /* point's y-value */ - x += args[5]; - cff_builder_add_point( builder, x, y, 0 ); - - /* fourth control point */ - x += args[6]; - y += args[7]; - cff_builder_add_point( builder, x, y, 0 ); - - /* ending point, with y-value the same as the start */ - x += args[8]; - y = start_y; - cff_builder_add_point( builder, x, y, 1 ); - - args = stack; - break; - } - - case cff_op_hflex: - { - FT_Pos start_y; - - - FT_TRACE4(( " hflex\n" )); - - /* adding six more points; 4 control points, 2 on-curve points */ - if ( cff_builder_start_point( builder, x, y ) || - cff_check_points( builder, 6 ) ) - goto Fail; - - /* record the starting point's y-position for later use */ - start_y = y; - - /* first control point */ - x += args[0]; - cff_builder_add_point( builder, x, y, 0 ); - - /* second control point */ - x += args[1]; - y += args[2]; - cff_builder_add_point( builder, x, y, 0 ); - - /* join point; on curve, with y-value the same as the last */ - /* control point's y-value */ - x += args[3]; - cff_builder_add_point( builder, x, y, 1 ); - - /* third control point, with y-value the same as the join */ - /* point's y-value */ - x += args[4]; - cff_builder_add_point( builder, x, y, 0 ); - - /* fourth control point */ - x += args[5]; - y = start_y; - cff_builder_add_point( builder, x, y, 0 ); - - /* ending point, with y-value the same as the start point's */ - /* y-value -- we don't add this point, though */ - x += args[6]; - cff_builder_add_point( builder, x, y, 1 ); - - args = stack; - break; - } - - case cff_op_flex1: - { - FT_Pos start_x, start_y; /* record start x, y values for */ - /* alter use */ - FT_Fixed dx = 0, dy = 0; /* used in horizontal/vertical */ - /* algorithm below */ - FT_Int horizontal, count; - FT_Fixed* temp; - - - FT_TRACE4(( " flex1\n" )); - - /* adding six more points; 4 control points, 2 on-curve points */ - if ( cff_builder_start_point( builder, x, y ) || - cff_check_points( builder, 6 ) ) - goto Fail; - - /* record the starting point's x, y position for later use */ - start_x = x; - start_y = y; - - /* XXX: figure out whether this is supposed to be a horizontal */ - /* or vertical flex; the Type 2 specification is vague... */ - - temp = args; - - /* grab up to the last argument */ - for ( count = 5; count > 0; count-- ) - { - dx += temp[0]; - dy += temp[1]; - temp += 2; - } - - if ( dx < 0 ) - dx = -dx; - if ( dy < 0 ) - dy = -dy; - - /* strange test, but here it is... */ - horizontal = ( dx > dy ); - - for ( count = 5; count > 0; count-- ) - { - x += args[0]; - y += args[1]; - cff_builder_add_point( builder, x, y, - (FT_Bool)( count == 3 ) ); - args += 2; - } - - /* is last operand an x- or y-delta? */ - if ( horizontal ) - { - x += args[0]; - y = start_y; - } - else - { - x = start_x; - y += args[0]; - } - - cff_builder_add_point( builder, x, y, 1 ); - - args = stack; - break; - } - - case cff_op_flex: - { - FT_UInt count; - - - FT_TRACE4(( " flex\n" )); - - if ( cff_builder_start_point( builder, x, y ) || - cff_check_points( builder, 6 ) ) - goto Fail; - - for ( count = 6; count > 0; count-- ) - { - x += args[0]; - y += args[1]; - cff_builder_add_point( builder, x, y, - (FT_Bool)( count == 4 || count == 1 ) ); - args += 2; - } - - args = stack; - } - break; - - case cff_op_seac: - FT_TRACE4(( " seac\n" )); - - error = cff_operator_seac( decoder, - args[0], args[1], args[2], - (FT_Int)( args[3] >> 16 ), - (FT_Int)( args[4] >> 16 ) ); - - /* add current outline to the glyph slot */ - FT_GlyphLoader_Add( builder->loader ); - - /* return now! */ - FT_TRACE4(( "\n" )); - return error; - - case cff_op_endchar: - /* in dictionaries, `endchar' simply indicates end of data */ - if ( in_dict ) - return error; - - FT_TRACE4(( " endchar\n" )); - - /* We are going to emulate the seac operator. */ - if ( num_args >= 4 ) - { - /* Save glyph width so that the subglyphs don't overwrite it. */ - FT_Pos glyph_width = decoder->glyph_width; - - - error = cff_operator_seac( decoder, - 0L, args[-4], args[-3], - (FT_Int)( args[-2] >> 16 ), - (FT_Int)( args[-1] >> 16 ) ); - - decoder->glyph_width = glyph_width; - } - else - { - cff_builder_close_contour( builder ); - - /* close hints recording session */ - if ( hinter ) - { - if ( hinter->close( hinter->hints, - (FT_UInt)builder->current->n_points ) ) - goto Syntax_Error; - - /* apply hints to the loaded glyph outline now */ - error = hinter->apply( hinter->hints, - builder->current, - (PSH_Globals)builder->hints_globals, - decoder->hint_mode ); - if ( error ) - goto Fail; - } - - /* add current outline to the glyph slot */ - FT_GlyphLoader_Add( builder->loader ); - } - - /* return now! */ - FT_TRACE4(( "\n" )); - return error; - - case cff_op_abs: - FT_TRACE4(( " abs\n" )); - - if ( args[0] < 0 ) - args[0] = -args[0]; - args++; - break; - - case cff_op_add: - FT_TRACE4(( " add\n" )); - - args[0] += args[1]; - args++; - break; - - case cff_op_sub: - FT_TRACE4(( " sub\n" )); - - args[0] -= args[1]; - args++; - break; - - case cff_op_div: - FT_TRACE4(( " div\n" )); - - args[0] = FT_DivFix( args[0], args[1] ); - args++; - break; - - case cff_op_neg: - FT_TRACE4(( " neg\n" )); - - args[0] = -args[0]; - args++; - break; - - case cff_op_random: - { - FT_Fixed Rand; - - - FT_TRACE4(( " rand\n" )); - - Rand = seed; - if ( Rand >= 0x8000L ) - Rand++; - - args[0] = Rand; - seed = FT_MulFix( seed, 0x10000L - seed ); - if ( seed == 0 ) - seed += 0x2873; - args++; - } - break; - - case cff_op_mul: - FT_TRACE4(( " mul\n" )); - - args[0] = FT_MulFix( args[0], args[1] ); - args++; - break; - - case cff_op_sqrt: - FT_TRACE4(( " sqrt\n" )); - - if ( args[0] > 0 ) - { - FT_Fixed root = args[0]; - FT_Fixed new_root; - - - for (;;) - { - new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1; - if ( new_root == root ) - break; - root = new_root; - } - args[0] = new_root; - } - else - args[0] = 0; - args++; - break; - - case cff_op_drop: - /* nothing */ - FT_TRACE4(( " drop\n" )); - - break; - - case cff_op_exch: - { - FT_Fixed tmp; - - - FT_TRACE4(( " exch\n" )); - - tmp = args[0]; - args[0] = args[1]; - args[1] = tmp; - args += 2; - } - break; - - case cff_op_index: - { - FT_Int idx = (FT_Int)( args[0] >> 16 ); - - - FT_TRACE4(( " index\n" )); - - if ( idx < 0 ) - idx = 0; - else if ( idx > num_args - 2 ) - idx = num_args - 2; - args[0] = args[-( idx + 1 )]; - args++; - } - break; - - case cff_op_roll: - { - FT_Int count = (FT_Int)( args[0] >> 16 ); - FT_Int idx = (FT_Int)( args[1] >> 16 ); - - - FT_TRACE4(( " roll\n" )); - - if ( count <= 0 ) - count = 1; - - args -= count; - if ( args < stack ) - goto Stack_Underflow; - - if ( idx >= 0 ) - { - while ( idx > 0 ) - { - FT_Fixed tmp = args[count - 1]; - FT_Int i; - - - for ( i = count - 2; i >= 0; i-- ) - args[i + 1] = args[i]; - args[0] = tmp; - idx--; - } - } - else - { - while ( idx < 0 ) - { - FT_Fixed tmp = args[0]; - FT_Int i; - - - for ( i = 0; i < count - 1; i++ ) - args[i] = args[i + 1]; - args[count - 1] = tmp; - idx++; - } - } - args += count; - } - break; - - case cff_op_dup: - FT_TRACE4(( " dup\n" )); - - args[1] = args[0]; - args += 2; - break; - - case cff_op_put: - { - FT_Fixed val = args[0]; - FT_Int idx = (FT_Int)( args[1] >> 16 ); - - - FT_TRACE4(( " put\n" )); - - /* the Type2 specification before version 16-March-2000 */ - /* didn't give a hard-coded size limit of the temporary */ - /* storage array; instead, an argument of the */ - /* `MultipleMaster' operator set the size */ - if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS ) - decoder->buildchar[idx] = val; - } - break; - - case cff_op_get: - { - FT_Int idx = (FT_Int)( args[0] >> 16 ); - FT_Fixed val = 0; - - - FT_TRACE4(( " get\n" )); - - if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS ) - val = decoder->buildchar[idx]; - - args[0] = val; - args++; - } - break; - - case cff_op_store: - /* this operator was removed from the Type2 specification */ - /* in version 16-March-2000 */ - - /* since we currently don't handle interpolation of multiple */ - /* master fonts, this is a no-op */ - FT_TRACE4(( " store\n")); - break; - - case cff_op_load: - /* this operator was removed from the Type2 specification */ - /* in version 16-March-2000 */ - { - FT_Int reg_idx = (FT_Int)args[0]; - FT_Int idx = (FT_Int)args[1]; - FT_Int count = (FT_Int)args[2]; - - - FT_TRACE4(( " load\n" )); - - /* since we currently don't handle interpolation of multiple */ - /* master fonts, we store a vector [1 0 0 ...] in the */ - /* temporary storage array regardless of the Registry index */ - if ( reg_idx >= 0 && reg_idx <= 2 && - idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS && - count >= 0 && count <= num_axes ) - { - FT_Int end, i; - - - end = FT_MIN( idx + count, CFF_MAX_TRANS_ELEMENTS ); - - if ( idx < end ) - decoder->buildchar[idx] = 1 << 16; - - for ( i = idx + 1; i < end; i++ ) - decoder->buildchar[i] = 0; - } - } - break; - - case cff_op_blend: - /* this operator was removed from the Type2 specification */ - /* in version 16-March-2000 */ - { - FT_Int num_results = (FT_Int)( args[0] >> 16 ); - - - FT_TRACE4(( " blend\n" )); - - if ( num_results < 0 ) - goto Syntax_Error; - - if ( num_results * (FT_Int)num_designs > num_args ) - goto Stack_Underflow; - - /* since we currently don't handle interpolation of multiple */ - /* master fonts, return the `num_results' values of the */ - /* first master */ - args -= num_results * ( num_designs - 1 ); - num_args -= num_results * ( num_designs - 1 ); - } - break; - - case cff_op_dotsection: - /* this operator is deprecated and ignored by the parser */ - FT_TRACE4(( " dotsection\n" )); - break; - - case cff_op_closepath: - /* this is an invalid Type 2 operator; however, there */ - /* exist fonts which are incorrectly converted from probably */ - /* Type 1 to CFF, and some parsers seem to accept it */ - - FT_TRACE4(( " closepath (invalid op)\n" )); - - args = stack; - break; - - case cff_op_hsbw: - /* this is an invalid Type 2 operator; however, there */ - /* exist fonts which are incorrectly converted from probably */ - /* Type 1 to CFF, and some parsers seem to accept it */ - - FT_TRACE4(( " hsbw (invalid op)\n" )); - - decoder->glyph_width = decoder->nominal_width + ( args[1] >> 16 ); - - decoder->builder.left_bearing.x = args[0]; - decoder->builder.left_bearing.y = 0; - - x = decoder->builder.pos_x + args[0]; - y = decoder->builder.pos_y; - args = stack; - break; - - case cff_op_sbw: - /* this is an invalid Type 2 operator; however, there */ - /* exist fonts which are incorrectly converted from probably */ - /* Type 1 to CFF, and some parsers seem to accept it */ - - FT_TRACE4(( " sbw (invalid op)\n" )); - - decoder->glyph_width = decoder->nominal_width + ( args[2] >> 16 ); - - decoder->builder.left_bearing.x = args[0]; - decoder->builder.left_bearing.y = args[1]; - - x = decoder->builder.pos_x + args[0]; - y = decoder->builder.pos_y + args[1]; - args = stack; - break; - - case cff_op_setcurrentpoint: - /* this is an invalid Type 2 operator; however, there */ - /* exist fonts which are incorrectly converted from probably */ - /* Type 1 to CFF, and some parsers seem to accept it */ - - FT_TRACE4(( " setcurrentpoint (invalid op)\n" )); - - x = decoder->builder.pos_x + args[0]; - y = decoder->builder.pos_y + args[1]; - args = stack; - break; - - case cff_op_callothersubr: - /* this is an invalid Type 2 operator; however, there */ - /* exist fonts which are incorrectly converted from probably */ - /* Type 1 to CFF, and some parsers seem to accept it */ - - FT_TRACE4(( " callothersubr (invalid op)\n" )); - - /* subsequent `pop' operands should add the arguments, */ - /* this is the implementation described for `unknown' other */ - /* subroutines in the Type1 spec. */ - /* */ - /* XXX Fix return arguments (see discussion below). */ - args -= 2 + ( args[-2] >> 16 ); - if ( args < stack ) - goto Stack_Underflow; - break; - - case cff_op_pop: - /* this is an invalid Type 2 operator; however, there */ - /* exist fonts which are incorrectly converted from probably */ - /* Type 1 to CFF, and some parsers seem to accept it */ - - FT_TRACE4(( " pop (invalid op)\n" )); - - /* XXX Increasing `args' is wrong: After a certain number of */ - /* `pop's we get a stack overflow. Reason for doing it is */ - /* code like this (actually found in a CFF font): */ - /* */ - /* 17 1 3 callothersubr */ - /* pop */ - /* callsubr */ - /* */ - /* Since we handle `callothersubr' as a no-op, and */ - /* `callsubr' needs at least one argument, `pop' can't be a */ - /* no-op too as it basically should be. */ - /* */ - /* The right solution would be to provide real support for */ - /* `callothersubr' as done in `t1decode.c', however, given */ - /* the fact that CFF fonts with `pop' are invalid, it is */ - /* questionable whether it is worth the time. */ - args++; - break; - - case cff_op_and: - { - FT_Fixed cond = ( args[0] && args[1] ); - - - FT_TRACE4(( " and\n" )); - - args[0] = cond ? 0x10000L : 0; - args++; - } - break; - - case cff_op_or: - { - FT_Fixed cond = ( args[0] || args[1] ); - - - FT_TRACE4(( " or\n" )); - - args[0] = cond ? 0x10000L : 0; - args++; - } - break; - - case cff_op_not: - { - FT_Fixed cond = !args[0]; - - - FT_TRACE4(( " not\n" )); - - args[0] = cond ? 0x10000L : 0; - args++; - } - break; - - case cff_op_eq: - { - FT_Fixed cond = ( args[0] == args[1] ); - - - FT_TRACE4(( " eq\n" )); - - args[0] = cond ? 0x10000L : 0; - args++; - } - break; - - case cff_op_ifelse: - { - FT_Fixed cond = ( args[2] <= args[3] ); - - - FT_TRACE4(( " ifelse\n" )); - - if ( !cond ) - args[0] = args[1]; - args++; - } - break; - - case cff_op_callsubr: - { - FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) + - decoder->locals_bias ); - - - FT_TRACE4(( " callsubr (idx %d, entering level %d)\n", - idx, - zone - decoder->zones + 1 )); - - if ( idx >= decoder->num_locals ) - { - FT_ERROR(( "cff_decoder_parse_charstrings:" - " invalid local subr index\n" )); - goto Syntax_Error; - } - - if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS ) - { - FT_ERROR(( "cff_decoder_parse_charstrings:" - " too many nested subrs\n" )); - goto Syntax_Error; - } - - zone->cursor = ip; /* save current instruction pointer */ - - zone++; - zone->base = decoder->locals[idx]; - zone->limit = decoder->locals[idx + 1]; - zone->cursor = zone->base; - - if ( !zone->base || zone->limit == zone->base ) - { - FT_ERROR(( "cff_decoder_parse_charstrings:" - " invoking empty subrs\n" )); - goto Syntax_Error; - } - - decoder->zone = zone; - ip = zone->base; - limit = zone->limit; - } - break; - - case cff_op_callgsubr: - { - FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) + - decoder->globals_bias ); - - - FT_TRACE4(( " callgsubr (idx %d, entering level %d)\n", - idx, - zone - decoder->zones + 1 )); - - if ( idx >= decoder->num_globals ) - { - FT_ERROR(( "cff_decoder_parse_charstrings:" - " invalid global subr index\n" )); - goto Syntax_Error; - } - - if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS ) - { - FT_ERROR(( "cff_decoder_parse_charstrings:" - " too many nested subrs\n" )); - goto Syntax_Error; - } - - zone->cursor = ip; /* save current instruction pointer */ - - zone++; - zone->base = decoder->globals[idx]; - zone->limit = decoder->globals[idx + 1]; - zone->cursor = zone->base; - - if ( !zone->base || zone->limit == zone->base ) - { - FT_ERROR(( "cff_decoder_parse_charstrings:" - " invoking empty subrs\n" )); - goto Syntax_Error; - } - - decoder->zone = zone; - ip = zone->base; - limit = zone->limit; - } - break; - - case cff_op_return: - FT_TRACE4(( " return (leaving level %d)\n", - decoder->zone - decoder->zones )); - - if ( decoder->zone <= decoder->zones ) - { - FT_ERROR(( "cff_decoder_parse_charstrings:" - " unexpected return\n" )); - goto Syntax_Error; - } - - decoder->zone--; - zone = decoder->zone; - ip = zone->cursor; - limit = zone->limit; - break; - - default: - FT_ERROR(( "Unimplemented opcode: %d", ip[-1] )); - - if ( ip[-1] == 12 ) - FT_ERROR(( " %d", ip[0] )); - FT_ERROR(( "\n" )); - - return FT_THROW( Unimplemented_Feature ); - } - - decoder->top = args; - - if ( decoder->top - stack >= CFF_MAX_OPERANDS ) - goto Stack_Overflow; - - } /* general operator processing */ - - } /* while ip < limit */ - - FT_TRACE4(( "..end..\n\n" )); - - Fail: - return error; - - MM_Error: - FT_TRACE4(( "cff_decoder_parse_charstrings:" - " invalid opcode found in top DICT charstring\n")); - return FT_THROW( Invalid_File_Format ); - - Syntax_Error: - FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error\n" )); - return FT_THROW( Invalid_File_Format ); - - Stack_Underflow: - FT_TRACE4(( "cff_decoder_parse_charstrings: stack underflow\n" )); - return FT_THROW( Too_Few_Arguments ); - - Stack_Overflow: - FT_TRACE4(( "cff_decoder_parse_charstrings: stack overflow\n" )); - return FT_THROW( Stack_Overflow ); - } - -#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */ - - /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ @@ -2684,11 +142,14 @@ FT_Int glyph_index; CFF_Font cff = (CFF_Font)face->other; + PSAux_Service psaux = (PSAux_Service)face->psaux; + const CFF_Decoder_Funcs decoder_funcs = psaux->cff_decoder_funcs; + *max_advance = 0; /* Initialize load decoder */ - cff_decoder_init( &decoder, face, 0, 0, 0, 0 ); + decoder_funcs->init( &decoder, face, 0, 0, 0, 0, 0, 0 ); decoder.builder.metrics_only = 1; decoder.builder.load_points = 0; @@ -2707,12 +168,12 @@ &charstring, &charstring_len ); if ( !error ) { - error = cff_decoder_prepare( &decoder, size, glyph_index ); + error = decoder_funcs->prepare( &decoder, size, glyph_index ); if ( !error ) - error = cff_decoder_parse_charstrings( &decoder, - charstring, - charstring_len, - 0 ); + error = decoder_funcs->parse_charstrings_old( &decoder, + charstring, + charstring_len, + 0 ); cff_free_glyph_data( face, &charstring, &charstring_len ); } @@ -2738,10 +199,14 @@ { FT_Error error; CFF_Decoder decoder; + PS_Decoder psdecoder; TT_Face face = (TT_Face)glyph->root.face; FT_Bool hinting, scaled, force_scaling; CFF_Font cff = (CFF_Font)face->extra.data; + PSAux_Service psaux = (PSAux_Service)face->psaux; + const CFF_Decoder_Funcs decoder_funcs = psaux->cff_decoder_funcs; + FT_Matrix font_matrix; FT_Vector font_offset; @@ -2931,7 +396,7 @@ { #ifdef CFF_CONFIG_OPTION_OLD_ENGINE - CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( face ); + PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( face ); #endif @@ -2939,8 +404,10 @@ FT_ULong charstring_len; - cff_decoder_init( &decoder, face, size, glyph, hinting, - FT_LOAD_TARGET_MODE( load_flags ) ); + decoder_funcs->init( &decoder, face, size, glyph, hinting, + FT_LOAD_TARGET_MODE( load_flags ), + cff_get_glyph_data, + cff_free_glyph_data ); /* this is for pure CFFs */ if ( load_flags & FT_LOAD_ADVANCE_ONLY ) @@ -2955,23 +422,25 @@ if ( error ) goto Glyph_Build_Finished; - error = cff_decoder_prepare( &decoder, size, glyph_index ); + error = decoder_funcs->prepare( &decoder, size, glyph_index ); if ( error ) goto Glyph_Build_Finished; #ifdef CFF_CONFIG_OPTION_OLD_ENGINE /* choose which CFF renderer to use */ - if ( driver->hinting_engine == FT_CFF_HINTING_FREETYPE ) - error = cff_decoder_parse_charstrings( &decoder, - charstring, - charstring_len, - 0 ); + if ( driver->hinting_engine == FT_HINTING_FREETYPE ) + error = decoder_funcs->parse_charstrings_old( &decoder, + charstring, + charstring_len, + 0 ); else #endif { - error = cf2_decoder_parse_charstrings( &decoder, - charstring, - charstring_len ); + psaux->ps_decoder_init( &psdecoder, &decoder, FALSE ); + + error = decoder_funcs->parse_charstrings( &psdecoder, + charstring, + charstring_len ); /* Adobe's engine uses 16.16 numbers everywhere; */ /* as a consequence, glyphs larger than 2000ppem get rejected */ @@ -2984,9 +453,9 @@ force_scaling = TRUE; glyph->hint = hinting; - error = cf2_decoder_parse_charstrings( &decoder, - charstring, - charstring_len ); + error = decoder_funcs->parse_charstrings( &psdecoder, + charstring, + charstring_len ); } } @@ -3024,7 +493,7 @@ Glyph_Build_Finished: /* save new glyph tables, if no error */ if ( !error ) - cff_builder_done( &decoder.builder ); + decoder.builder.funcs.done( &decoder.builder ); /* XXX: anything to do for broken glyph entry? */ } diff --git a/modules/freetype2/src/cff/cffgload.h b/modules/freetype2/src/cff/cffgload.h index b875fbed9..803f3974f 100644 --- a/modules/freetype2/src/cff/cffgload.h +++ b/modules/freetype2/src/cff/cffgload.h @@ -4,7 +4,7 @@ /* */ /* OpenType Glyph Loader (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -22,119 +22,11 @@ #include <ft2build.h> #include FT_FREETYPE_H -#include "cffobjs.h" +#include FT_INTERNAL_CFF_OBJECTS_TYPES_H FT_BEGIN_HEADER - -#define CFF_MAX_OPERANDS 48 -#define CFF_MAX_SUBRS_CALLS 16 /* maximum subroutine nesting; */ - /* only 10 are allowed but there exist */ - /* fonts like `HiraKakuProN-W3.ttf' */ - /* (Hiragino Kaku Gothic ProN W3; */ - /* 8.2d6e1; 2014-12-19) that exceed */ - /* this limit */ -#define CFF_MAX_TRANS_ELEMENTS 32 - - - /*************************************************************************/ - /* */ - /* <Structure> */ - /* CFF_Builder */ - /* */ - /* <Description> */ - /* A structure used during glyph loading to store its outline. */ - /* */ - /* <Fields> */ - /* memory :: The current memory object. */ - /* */ - /* face :: The current face object. */ - /* */ - /* glyph :: The current glyph slot. */ - /* */ - /* loader :: The current glyph loader. */ - /* */ - /* base :: The base glyph outline. */ - /* */ - /* current :: The current glyph outline. */ - /* */ - /* pos_x :: The horizontal translation (if composite glyph). */ - /* */ - /* pos_y :: The vertical translation (if composite glyph). */ - /* */ - /* left_bearing :: The left side bearing point. */ - /* */ - /* advance :: The horizontal advance vector. */ - /* */ - /* bbox :: Unused. */ - /* */ - /* path_begun :: A flag which indicates that a new path has begun. */ - /* */ - /* load_points :: If this flag is not set, no points are loaded. */ - /* */ - /* no_recurse :: Set but not used. */ - /* */ - /* metrics_only :: A boolean indicating that we only want to compute */ - /* the metrics of a given glyph, not load all of its */ - /* points. */ - /* */ - /* hints_funcs :: Auxiliary pointer for hinting. */ - /* */ - /* hints_globals :: Auxiliary pointer for hinting. */ - /* */ - typedef struct CFF_Builder_ - { - FT_Memory memory; - TT_Face face; - CFF_GlyphSlot glyph; - FT_GlyphLoader loader; - FT_Outline* base; - FT_Outline* current; - - FT_Pos pos_x; - FT_Pos pos_y; - - FT_Vector left_bearing; - FT_Vector advance; - - FT_BBox bbox; /* bounding box */ - FT_Bool path_begun; - FT_Bool load_points; - FT_Bool no_recurse; - - FT_Bool metrics_only; - - void* hints_funcs; /* hinter-specific */ - void* hints_globals; /* hinter-specific */ - - } CFF_Builder; - - - FT_LOCAL( FT_Error ) - cff_check_points( CFF_Builder* builder, - FT_Int count ); - - FT_LOCAL( void ) - cff_builder_add_point( CFF_Builder* builder, - FT_Pos x, - FT_Pos y, - FT_Byte flag ); - FT_LOCAL( FT_Error ) - cff_builder_add_point1( CFF_Builder* builder, - FT_Pos x, - FT_Pos y ); - FT_LOCAL( FT_Error ) - cff_builder_start_point( CFF_Builder* builder, - FT_Pos x, - FT_Pos y ); - FT_LOCAL( void ) - cff_builder_close_contour( CFF_Builder* builder ); - - - FT_LOCAL( FT_Int ) - cff_lookup_glyph_by_stdcharcode( CFF_Font cff, - FT_Int charcode ); FT_LOCAL( FT_Error ) cff_get_glyph_data( TT_Face face, FT_UInt glyph_index, @@ -146,74 +38,6 @@ FT_BEGIN_HEADER FT_ULong length ); - /* execution context charstring zone */ - - typedef struct CFF_Decoder_Zone_ - { - FT_Byte* base; - FT_Byte* limit; - FT_Byte* cursor; - - } CFF_Decoder_Zone; - - - typedef struct CFF_Decoder_ - { - CFF_Builder builder; - CFF_Font cff; - - FT_Fixed stack[CFF_MAX_OPERANDS + 1]; - FT_Fixed* top; - - CFF_Decoder_Zone zones[CFF_MAX_SUBRS_CALLS + 1]; - CFF_Decoder_Zone* zone; - - FT_Int flex_state; - FT_Int num_flex_vectors; - FT_Vector flex_vectors[7]; - - FT_Pos glyph_width; - FT_Pos nominal_width; - - FT_Bool read_width; - FT_Bool width_only; - FT_Int num_hints; - FT_Fixed buildchar[CFF_MAX_TRANS_ELEMENTS]; - - FT_UInt num_locals; - FT_UInt num_globals; - - FT_Int locals_bias; - FT_Int globals_bias; - - FT_Byte** locals; - FT_Byte** globals; - - FT_Byte** glyph_names; /* for pure CFF fonts only */ - FT_UInt num_glyphs; /* number of glyphs in font */ - - FT_Render_Mode hint_mode; - - FT_Bool seac; - - CFF_SubFont current_subfont; /* for current glyph_index */ - - } CFF_Decoder; - - - FT_LOCAL( void ) - cff_decoder_init( CFF_Decoder* decoder, - TT_Face face, - CFF_Size size, - CFF_GlyphSlot slot, - FT_Bool hinting, - FT_Render_Mode hint_mode ); - - FT_LOCAL( FT_Error ) - cff_decoder_prepare( CFF_Decoder* decoder, - CFF_Size size, - FT_UInt glyph_index ); - #if 0 /* unused until we support pure CFF fonts */ /* Compute the maximum advance width of a font through quick parsing */ @@ -223,13 +47,6 @@ FT_BEGIN_HEADER #endif /* 0 */ -#ifdef CFF_CONFIG_OPTION_OLD_ENGINE - FT_LOCAL( FT_Error ) - cff_decoder_parse_charstrings( CFF_Decoder* decoder, - FT_Byte* charstring_base, - FT_ULong charstring_len, - FT_Bool in_dict ); -#endif FT_LOCAL( FT_Error ) cff_slot_load( CFF_GlyphSlot glyph, diff --git a/modules/freetype2/src/cff/cffload.c b/modules/freetype2/src/cff/cffload.c index c1e6b14db..1c6fe5156 100644 --- a/modules/freetype2/src/cff/cffload.c +++ b/modules/freetype2/src/cff/cffload.c @@ -4,7 +4,7 @@ /* */ /* OpenType and CFF data/program tables loader (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -22,6 +22,7 @@ #include FT_INTERNAL_STREAM_H #include FT_TRUETYPE_TAGS_H #include FT_TYPE1_TABLES_H +#include FT_INTERNAL_POSTSCRIPT_AUX_H #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT #include FT_MULTIPLE_MASTERS_H @@ -1113,7 +1114,7 @@ /* convert 2.14 to Fixed */ - #define FT_fdot14ToFixed( x ) ( ( (FT_Fixed)( (FT_Int16)(x) ) ) << 2 ) + #define FT_fdot14ToFixed( x ) ( (FT_Fixed)( (FT_ULong)(x) << 2 ) ) static FT_Error @@ -1297,7 +1298,9 @@ if ( numOperands > count ) { - FT_TRACE4(( " cff_blend_doBlend: Stack underflow %d args\n", count )); + FT_TRACE4(( " cff_blend_doBlend: Stack underflow %d argument%s\n", + count, + count == 1 ? "" : "s" )); error = FT_THROW( Stack_Underflow ); goto Exit; @@ -1307,6 +1310,10 @@ size = 5 * numBlends; /* add 5 bytes per entry */ if ( subFont->blend_used + size > subFont->blend_alloc ) { + FT_Byte* blend_stack_old = subFont->blend_stack; + FT_Byte* blend_top_old = subFont->blend_top; + + /* increase or allocate `blend_stack' and reset `blend_top'; */ /* prepare to append `numBlends' values to the buffer */ if ( FT_REALLOC( subFont->blend_stack, @@ -1316,6 +1323,22 @@ subFont->blend_top = subFont->blend_stack + subFont->blend_used; subFont->blend_alloc += size; + + /* iterate over the parser stack and adjust pointers */ + /* if the reallocated buffer has a different address */ + if ( blend_stack_old && + subFont->blend_stack != blend_stack_old ) + { + FT_PtrDist offset = subFont->blend_stack - blend_stack_old; + FT_Byte** p; + + + for ( p = parser->stack; p < parser->top; p++ ) + { + if ( *p >= blend_stack_old && *p < blend_top_old ) + *p += offset; + } + } } subFont->blend_used += size; @@ -1325,28 +1348,27 @@ for ( i = 0; i < numBlends; i++ ) { const FT_Int32* weight = &blend->BV[1]; - FT_Int32 sum; + FT_UInt32 sum; /* convert inputs to 16.16 fixed point */ - sum = cff_parse_num( parser, &parser->stack[i + base] ) << 16; + sum = cff_parse_num( parser, &parser->stack[i + base] ) * 0x10000; for ( j = 1; j < blend->lenBV; j++ ) - sum += FT_MulFix( *weight++, - cff_parse_num( parser, - &parser->stack[delta++] ) << 16 ); + sum += cff_parse_num( parser, &parser->stack[delta++] ) * *weight++; /* point parser stack to new value on blend_stack */ parser->stack[i + base] = subFont->blend_top; - /* Push blended result as Type 2 5-byte fixed point number (except */ - /* that host byte order is used). This will not conflict with */ - /* actual DICTs because 255 is a reserved opcode in both CFF and */ - /* CFF2 DICTs. See `cff_parse_num' for decode of this, which rounds */ - /* to an integer. */ - *subFont->blend_top++ = 255; - *((FT_UInt32*)subFont->blend_top) = (FT_UInt32)sum; /* write 4 bytes */ - subFont->blend_top += 4; + /* Push blended result as Type 2 5-byte fixed point number. This */ + /* will not conflict with actual DICTs because 255 is a reserved */ + /* opcode in both CFF and CFF2 DICTs. See `cff_parse_num' for */ + /* decode of this, which rounds to an integer. */ + *subFont->blend_top++ = 255; + *subFont->blend_top++ = (FT_Byte)( sum >> 24 ); + *subFont->blend_top++ = (FT_Byte)( sum >> 16 ); + *subFont->blend_top++ = (FT_Byte)( sum >> 8 ); + *subFont->blend_top++ = (FT_Byte)sum; } /* leave only numBlends results on parser stack */ @@ -1442,10 +1464,15 @@ /* Note: `lenNDV' could be zero. */ /* In that case, build default blend vector (1,0,0...). */ - /* In the normal case, initialize each component to 1 */ - /* before inner loop. */ - if ( lenNDV != 0 ) - blend->BV[master] = FT_FIXED_ONE; /* default */ + if ( !lenNDV ) + { + blend->BV[master] = 0; + continue; + } + + /* In the normal case, initialize each component to 1 */ + /* before inner loop. */ + blend->BV[master] = FT_FIXED_ONE; /* default */ /* inner loop steps through axes in this region */ for ( j = 0; j < lenNDV; j++ ) @@ -1508,12 +1535,12 @@ lenNDV * sizeof ( *NDV ) ) ) goto Exit; - blend->lenNDV = lenNDV; FT_MEM_COPY( blend->lastNDV, NDV, lenNDV * sizeof ( *NDV ) ); } + blend->lenNDV = lenNDV; blend->builtBV = TRUE; Exit: @@ -1529,13 +1556,13 @@ FT_UInt lenNDV, FT_Fixed* NDV ) { - if ( !blend->builtBV || - blend->lastVsindex != vsindex || - blend->lenNDV != lenNDV || - ( lenNDV && - memcmp( NDV, - blend->lastNDV, - lenNDV * sizeof ( *NDV ) ) != 0 ) ) + if ( !blend->builtBV || + blend->lastVsindex != vsindex || + blend->lenNDV != lenNDV || + ( lenNDV && + ft_memcmp( NDV, + blend->lastNDV, + lenNDV * sizeof ( *NDV ) ) != 0 ) ) { /* need to build blend vector */ return TRUE; @@ -1551,12 +1578,17 @@ cff_get_var_blend( CFF_Face face, FT_UInt *num_coords, FT_Fixed* *coords, + FT_Fixed* *normalizedcoords, FT_MM_Var* *mm_var ) { FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; - return mm->get_var_blend( FT_FACE( face ), num_coords, coords, mm_var ); + return mm->get_var_blend( FT_FACE( face ), + num_coords, + coords, + normalizedcoords, + mm_var ); } @@ -1566,7 +1598,8 @@ FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; - mm->done_blend( FT_FACE( face ) ); + if (mm) + mm->done_blend( FT_FACE( face ) ); } #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ @@ -1864,7 +1897,8 @@ subfont->lenNDV = lenNDV; subfont->NDV = NDV; - stackSize = font->cff2 ? font->top_font.font_dict.maxstack + /* add 1 for the operator */ + stackSize = font->cff2 ? font->top_font.font_dict.maxstack + 1 : CFF_MAX_STACK_DEPTH + 1; if ( cff_parser_init( &parser, @@ -1892,6 +1926,31 @@ /* ensure that `num_blue_values' is even */ priv->num_blue_values &= ~1; + /* sanitize `initialRandomSeed' to be a positive value, if necessary; */ + /* this is not mandated by the specification but by our implementation */ + if ( priv->initial_random_seed < 0 ) + priv->initial_random_seed = -priv->initial_random_seed; + else if ( priv->initial_random_seed == 0 ) + priv->initial_random_seed = 987654321; + + /* some sanitizing to avoid overflows later on; */ + /* the upper limits are ad-hoc values */ + if ( priv->blue_shift > 1000 || priv->blue_shift < 0 ) + { + FT_TRACE2(( "cff_load_private_dict:" + " setting unlikely BlueShift value %d to default (7)\n", + priv->blue_shift )); + priv->blue_shift = 7; + } + + if ( priv->blue_fuzz > 1000 || priv->blue_fuzz < 0 ) + { + FT_TRACE2(( "cff_load_private_dict:" + " setting unlikely BlueFuzz value %d to default (1)\n", + priv->blue_fuzz )); + priv->blue_fuzz = 1; + } + Exit: /* clean up */ cff_blend_clear( subfont ); /* clear blend stack */ @@ -1916,7 +1975,8 @@ FT_Stream stream, FT_ULong base_offset, FT_UInt code, - CFF_Font font ) + CFF_Font font, + CFF_Face face ) { FT_Error error; CFF_ParserRec parser; @@ -1925,6 +1985,8 @@ CFF_FontRecDict top = &subfont->font_dict; CFF_Private priv = &subfont->private_dict; + PSAux_Service psaux = (PSAux_Service)face->psaux; + FT_Bool cff2 = FT_BOOL( code == CFF2_CODE_TOPDICT || code == CFF2_CODE_FONTDICT ); FT_UInt stackSize = cff2 ? CFF2_DEFAULT_STACK @@ -2013,6 +2075,56 @@ if ( error ) goto Exit; + if ( !cff2 ) + { + /* + * Initialize the random number generator. + * + * . If we have a face-specific seed, use it. + * If non-zero, update it to a positive value. + * + * . Otherwise, use the seed from the CFF driver. + * If non-zero, update it to a positive value. + * + * . If the random value is zero, use the seed given by the subfont's + * `initialRandomSeed' value. + * + */ + if ( face->root.internal->random_seed == -1 ) + { + PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( face ); + + + subfont->random = (FT_UInt32)driver->random_seed; + if ( driver->random_seed ) + { + do + { + driver->random_seed = + (FT_Int32)psaux->cff_random( (FT_UInt32)driver->random_seed ); + + } while ( driver->random_seed < 0 ); + } + } + else + { + subfont->random = (FT_UInt32)face->root.internal->random_seed; + if ( face->root.internal->random_seed ) + { + do + { + face->root.internal->random_seed = + (FT_Int32)psaux->cff_random( + (FT_UInt32)face->root.internal->random_seed ); + + } while ( face->root.internal->random_seed < 0 ); + } + } + + if ( !subfont->random ) + subfont->random = (FT_UInt32)priv->initial_random_seed; + } + /* read the local subrs, if any */ if ( priv->local_subrs_offset ) { @@ -2058,6 +2170,7 @@ FT_Stream stream, FT_Int face_index, CFF_Font font, + CFF_Face face, FT_Bool pure_cff, FT_Bool cff2 ) { @@ -2178,6 +2291,18 @@ goto Exit; } + /* if we have an empty font name, */ + /* it must be the only font in the CFF */ + if ( font->name_index.count > 1 && + font->name_index.data_size < font->name_index.count ) + { + /* for pure CFFs, we still haven't checked enough bytes */ + /* to be sure that it is a CFF at all */ + error = pure_cff ? FT_THROW( Unknown_File_Format ) + : FT_THROW( Invalid_File_Format ); + goto Exit; + } + if ( FT_SET_ERROR( cff_index_init( &font->font_dict_index, stream, 0, cff2 ) ) || FT_SET_ERROR( cff_index_init( &string_index, @@ -2189,6 +2314,15 @@ &font->string_pool, &font->string_pool_size ) ) ) goto Exit; + + /* there must be a Top DICT index entry for each name index entry */ + if ( font->name_index.count > font->font_dict_index.count ) + { + FT_ERROR(( "cff_font_load:" + " not enough entries in Top DICT index\n" )); + error = FT_THROW( Invalid_File_Format ); + goto Exit; + } } font->num_strings = string_index.count; @@ -2236,7 +2370,8 @@ stream, base_offset, cff2 ? CFF2_CODE_TOPDICT : CFF_CODE_TOPDICT, - font ); + font, + face ); if ( error ) goto Exit; @@ -2303,7 +2438,8 @@ base_offset, cff2 ? CFF2_CODE_FONTDICT : CFF_CODE_TOPDICT, - font ); + font, + face ); if ( error ) goto Fail_CID; } @@ -2420,6 +2556,8 @@ font->cf2_instance.finalizer( font->cf2_instance.data ); FT_FREE( font->cf2_instance.data ); } + + FT_FREE( font->font_extra ); } diff --git a/modules/freetype2/src/cff/cffload.h b/modules/freetype2/src/cff/cffload.h index dc3a2c523..14d14e211 100644 --- a/modules/freetype2/src/cff/cffload.h +++ b/modules/freetype2/src/cff/cffload.h @@ -4,7 +4,7 @@ /* */ /* OpenType & CFF data/program tables loader (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -21,9 +21,9 @@ #include <ft2build.h> -#include "cfftypes.h" +#include FT_INTERNAL_CFF_TYPES_H #include "cffparse.h" -#include "cffobjs.h" /* for CFF_Face */ +#include FT_INTERNAL_CFF_OBJECTS_TYPES_H /* for CFF_Face */ FT_BEGIN_HEADER @@ -66,6 +66,7 @@ FT_BEGIN_HEADER FT_Stream stream, FT_Int face_index, CFF_Font font, + CFF_Face face, FT_Bool pure_cff, FT_Bool cff2 ); @@ -108,6 +109,7 @@ FT_BEGIN_HEADER cff_get_var_blend( CFF_Face face, FT_UInt *num_coords, FT_Fixed* *coords, + FT_Fixed* *normalizedcoords, FT_MM_Var* *mm_var ); FT_LOCAL( void ) diff --git a/modules/freetype2/src/cff/cffobjs.c b/modules/freetype2/src/cff/cffobjs.c index 926effc52..a2d7aec65 100644 --- a/modules/freetype2/src/cff/cffobjs.c +++ b/modules/freetype2/src/cff/cffobjs.c @@ -4,7 +4,7 @@ /* */ /* OpenType objects manager (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -25,8 +25,15 @@ #include FT_TRUETYPE_IDS_H #include FT_TRUETYPE_TAGS_H #include FT_INTERNAL_SFNT_H -#include FT_CFF_DRIVER_H +#include FT_DRIVER_H +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT +#include FT_MULTIPLE_MASTERS_H +#include FT_SERVICE_MULTIPLE_MASTERS_H +#include FT_SERVICE_METRICS_VARIATIONS_H +#endif + +#include FT_INTERNAL_CFF_OBJECTS_TYPES_H #include "cffobjs.h" #include "cffload.h" #include "cffcmap.h" @@ -34,6 +41,9 @@ #include "cfferrs.h" +#include FT_INTERNAL_POSTSCRIPT_AUX_H +#include FT_SERVICE_CFF_TABLE_LOAD_H + /*************************************************************************/ /* */ @@ -49,9 +59,6 @@ /* */ /* SIZE FUNCTIONS */ /* */ - /* Note that we store the global hints in the size's `internal' root */ - /* field. */ - /* */ /*************************************************************************/ @@ -75,10 +82,11 @@ FT_LOCAL_DEF( void ) cff_size_done( FT_Size cffsize ) /* CFF_Size */ { + FT_Memory memory = cffsize->face->memory; CFF_Size size = (CFF_Size)cffsize; CFF_Face face = (CFF_Face)size->root.face; CFF_Font font = (CFF_Font)face->extra.data; - CFF_Internal internal = (CFF_Internal)cffsize->internal; + CFF_Internal internal = (CFF_Internal)cffsize->internal->module_data; if ( internal ) @@ -98,7 +106,7 @@ funcs->destroy( internal->subfonts[i - 1] ); } - /* `internal' is freed by destroy_size (in ftobjs.c) */ + FT_FREE( internal ); } } @@ -194,7 +202,7 @@ goto Exit; } - cffsize->internal = (FT_Size_Internal)(void*)internal; + cffsize->internal->module_data = internal; } size->strike_index = 0xFFFFFFFFUL; @@ -224,7 +232,7 @@ { CFF_Face face = (CFF_Face)size->face; CFF_Font font = (CFF_Font)face->extra.data; - CFF_Internal internal = (CFF_Internal)size->internal; + CFF_Internal internal = (CFF_Internal)size->internal->module_data; FT_Long top_upm = (FT_Long)font->top_font.font_dict.units_per_em; FT_UInt i; @@ -296,7 +304,7 @@ { CFF_Face cffface = (CFF_Face)size->face; CFF_Font font = (CFF_Font)cffface->extra.data; - CFF_Internal internal = (CFF_Internal)size->internal; + CFF_Internal internal = (CFF_Internal)size->internal->module_data; FT_Long top_upm = (FT_Long)font->top_font.font_dict.units_per_em; FT_UInt i; @@ -405,7 +413,7 @@ remove_subset_prefix( FT_String* name ) { FT_Int32 idx = 0; - FT_Int32 length = (FT_Int32)strlen( name ) + 1; + FT_Int32 length = (FT_Int32)ft_strlen( name ) + 1; FT_Bool continue_search = 1; @@ -442,8 +450,8 @@ FT_Int32 family_name_length, style_name_length; - family_name_length = (FT_Int32)strlen( family_name ); - style_name_length = (FT_Int32)strlen( style_name ); + family_name_length = (FT_Int32)ft_strlen( family_name ); + style_name_length = (FT_Int32)ft_strlen( style_name ); if ( family_name_length > style_name_length ) { @@ -490,14 +498,16 @@ SFNT_Service sfnt; FT_Service_PsCMaps psnames; PSHinter_Service pshinter; + PSAux_Service psaux; + FT_Service_CFFLoad cffload; FT_Bool pure_cff = 1; FT_Bool cff2 = 0; FT_Bool sfnt_format = 0; FT_Library library = cffface->driver->root.library; - sfnt = (SFNT_Service)FT_Get_Module_Interface( - library, "sfnt" ); + sfnt = (SFNT_Service)FT_Get_Module_Interface( library, + "sfnt" ); if ( !sfnt ) { FT_ERROR(( "cff_face_init: cannot access `sfnt' module\n" )); @@ -507,8 +517,20 @@ FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); - pshinter = (PSHinter_Service)FT_Get_Module_Interface( - library, "pshinter" ); + pshinter = (PSHinter_Service)FT_Get_Module_Interface( library, + "pshinter" ); + + psaux = (PSAux_Service)FT_Get_Module_Interface( library, + "psaux" ); + if ( !psaux ) + { + FT_ERROR(( "cff_face_init: cannot access `psaux' module\n" )); + error = FT_THROW( Missing_Module ); + goto Exit; + } + face->psaux = psaux; + + FT_FACE_FIND_GLOBAL_SERVICE( face, cffload, CFF_LOAD ); FT_TRACE2(( "CFF driver\n" )); @@ -517,6 +539,7 @@ goto Exit; /* check whether we have a valid OpenType file */ + FT_TRACE2(( " " )); error = sfnt->init_face( stream, face, face_index, num_params, params ); if ( !error ) { @@ -559,8 +582,8 @@ error = face->goto_table( face, TTAG_CFF2, stream, 0 ); if ( !error ) { - cff2 = 1; - face->isCFF2 = cff2; + cff2 = 1; + face->is_cff2 = cff2; } if ( FT_ERR_EQ( error, Table_Missing ) ) @@ -594,6 +617,7 @@ stream, face_index, cff, + face, pure_cff, cff2 ); if ( error ) @@ -609,6 +633,7 @@ cff->pshinter = pshinter; cff->psnames = psnames; + cff->cffload = cffload; cffface->face_index = face_index & 0xFFFF; @@ -683,62 +708,28 @@ } #endif /* FT_DEBUG_LEVEL_TRACE */ - - #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - - { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; - - FT_Int instance_index = face_index >> 16; - - - if ( FT_HAS_MULTIPLE_MASTERS( cffface ) && - mm && - instance_index > 0 ) { - FT_MM_Var* mm_var; + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var; + FT_UInt instance_index = (FT_UInt)face_index >> 16; - error = mm->get_mm_var( cffface, NULL ); - if ( error ) - goto Exit; - - mm->get_var_blend( cffface, NULL, NULL, &mm_var ); - if ( mm_var->namedstyle ) + if ( FT_HAS_MULTIPLE_MASTERS( cffface ) && + mm && + instance_index > 0 ) { - FT_Var_Named_Style* named_style; - FT_String* style_name; - - - /* in `face_index', the instance index starts with value 1 */ - named_style = mm_var->namedstyle + instance_index - 1; - error = sfnt->get_name( face, - (FT_UShort)named_style->strid, - &style_name ); + error = mm->set_instance( cffface, instance_index ); if ( error ) goto Exit; - /* set style name; if already set, replace it */ - if ( face->root.style_name ) - FT_FREE( face->root.style_name ); - face->root.style_name = style_name; - - /* finally, select the named instance */ - error = mm->set_var_design( cffface, - mm_var->num_axis, - named_style->coords ); - if ( error ) - goto Exit; + if ( var ) + var->metrics_adjust( cffface ); } } - } - #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ - - if ( !dict->has_font_matrix ) dict->units_per_em = pure_cff ? 1000 : face->root.units_per_EM; @@ -877,7 +868,8 @@ cffface->height = (FT_Short)( ( cffface->units_per_EM * 12 ) / 10 ); if ( cffface->height < cffface->ascender - cffface->descender ) - cffface->height = (FT_Short)( cffface->ascender - cffface->descender ); + cffface->height = (FT_Short)( cffface->ascender - + cffface->descender ); cffface->underline_position = (FT_Short)( dict->underline_position >> 16 ); @@ -885,28 +877,33 @@ (FT_Short)( dict->underline_thickness >> 16 ); /* retrieve font family & style name */ - cffface->family_name = cff_index_get_name( - cff, - (FT_UInt)( face_index & 0xFFFF ) ); + if ( dict->family_name ) + { + char* family_name; + + + family_name = cff_index_get_sid_string( cff, dict->family_name ); + if ( family_name ) + cffface->family_name = cff_strcpy( memory, family_name ); + } + + if ( !cffface->family_name ) + { + cffface->family_name = cff_index_get_name( + cff, + (FT_UInt)( face_index & 0xFFFF ) ); + if ( cffface->family_name ) + remove_subset_prefix( cffface->family_name ); + } + if ( cffface->family_name ) { char* full = cff_index_get_sid_string( cff, dict->full_name ); char* fullp = full; char* family = cffface->family_name; - char* family_name = NULL; - remove_subset_prefix( cffface->family_name ); - - if ( dict->family_name ) - { - family_name = cff_index_get_sid_string( cff, - dict->family_name ); - if ( family_name ) - family = family_name; - } - /* We try to extract the style name from the full name. */ /* We need to ignore spaces and dashes during the search. */ if ( full && family ) @@ -1021,7 +1018,6 @@ cffface->style_flags = flags; } - #ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES /* CID-keyed CFF fonts don't have glyph names -- the SFNT loader */ /* has unset this flag because of the 3.0 `post' table. */ @@ -1032,7 +1028,6 @@ if ( dict->cid_registry != 0xFFFFU && pure_cff ) cffface->face_flags |= FT_FACE_FLAG_CID_KEYED; - /*******************************************************************/ /* */ /* Compute char maps. */ @@ -1162,14 +1157,16 @@ FT_LOCAL_DEF( FT_Error ) cff_driver_init( FT_Module module ) /* CFF_Driver */ { - CFF_Driver driver = (CFF_Driver)module; + PS_Driver driver = (PS_Driver)module; + + FT_UInt32 seed; /* set default property values, cf. `ftcffdrv.h' */ #ifdef CFF_CONFIG_OPTION_OLD_ENGINE - driver->hinting_engine = FT_CFF_HINTING_FREETYPE; + driver->hinting_engine = FT_HINTING_FREETYPE; #else - driver->hinting_engine = FT_CFF_HINTING_ADOBE; + driver->hinting_engine = FT_HINTING_ADOBE; #endif driver->no_stem_darkening = TRUE; @@ -1183,6 +1180,18 @@ driver->darken_params[6] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4; driver->darken_params[7] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4; + /* compute random seed from some memory addresses */ + seed = (FT_UInt32)( (FT_Offset)(char*)&seed ^ + (FT_Offset)(char*)&module ^ + (FT_Offset)(char*)module->memory ); + seed = seed ^ ( seed >> 10 ) ^ ( seed >> 20 ); + + driver->random_seed = (FT_Int32)seed; + if ( driver->random_seed < 0 ) + driver->random_seed = -driver->random_seed; + else if ( driver->random_seed == 0 ) + driver->random_seed = 123456789; + return FT_Err_Ok; } diff --git a/modules/freetype2/src/cff/cffobjs.h b/modules/freetype2/src/cff/cffobjs.h index 9dc77536b..616a25b3b 100644 --- a/modules/freetype2/src/cff/cffobjs.h +++ b/modules/freetype2/src/cff/cffobjs.h @@ -4,7 +4,7 @@ /* */ /* OpenType objects manager (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -21,111 +21,11 @@ #include <ft2build.h> -#include FT_INTERNAL_OBJECTS_H -#include "cfftypes.h" -#include FT_INTERNAL_TRUETYPE_TYPES_H -#include FT_SERVICE_POSTSCRIPT_CMAPS_H -#include FT_INTERNAL_POSTSCRIPT_HINTS_H FT_BEGIN_HEADER - /*************************************************************************/ - /* */ - /* <Type> */ - /* CFF_Driver */ - /* */ - /* <Description> */ - /* A handle to an OpenType driver object. */ - /* */ - typedef struct CFF_DriverRec_* CFF_Driver; - - typedef TT_Face CFF_Face; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* CFF_Size */ - /* */ - /* <Description> */ - /* A handle to an OpenType size object. */ - /* */ - typedef struct CFF_SizeRec_ - { - FT_SizeRec root; - FT_ULong strike_index; /* 0xFFFFFFFF to indicate invalid */ - - } CFF_SizeRec, *CFF_Size; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* CFF_GlyphSlot */ - /* */ - /* <Description> */ - /* A handle to an OpenType glyph slot object. */ - /* */ - typedef struct CFF_GlyphSlotRec_ - { - FT_GlyphSlotRec root; - - FT_Bool hint; - FT_Bool scaled; - - FT_Fixed x_scale; - FT_Fixed y_scale; - - } CFF_GlyphSlotRec, *CFF_GlyphSlot; - - - /*************************************************************************/ - /* */ - /* <Type> */ - /* CFF_Internal */ - /* */ - /* <Description> */ - /* The interface to the `internal' field of `FT_Size'. */ - /* */ - typedef struct CFF_InternalRec_ - { - PSH_Globals topfont; - PSH_Globals subfonts[CFF_MAX_CID_FONTS]; - - } CFF_InternalRec, *CFF_Internal; - - - /*************************************************************************/ - /* */ - /* Subglyph transformation record. */ - /* */ - typedef struct CFF_Transform_ - { - FT_Fixed xx, xy; /* transformation matrix coefficients */ - FT_Fixed yx, yy; - FT_F26Dot6 ox, oy; /* offsets */ - - } CFF_Transform; - - - /***********************************************************************/ - /* */ - /* CFF driver class. */ - /* */ - typedef struct CFF_DriverRec_ - { - FT_DriverRec root; - - FT_UInt hinting_engine; - FT_Bool no_stem_darkening; - - FT_Int darken_params[8]; - - } CFF_DriverRec; - - FT_LOCAL( FT_Error ) cff_size_init( FT_Size size ); /* CFF_Size */ @@ -171,10 +71,10 @@ FT_BEGIN_HEADER /* Driver functions */ /* */ FT_LOCAL( FT_Error ) - cff_driver_init( FT_Module module ); /* CFF_Driver */ + cff_driver_init( FT_Module module ); /* PS_Driver */ FT_LOCAL( void ) - cff_driver_done( FT_Module module ); /* CFF_Driver */ + cff_driver_done( FT_Module module ); /* PS_Driver */ FT_END_HEADER diff --git a/modules/freetype2/src/cff/cffparse.c b/modules/freetype2/src/cff/cffparse.c index ee538c360..b9611cf54 100644 --- a/modules/freetype2/src/cff/cffparse.c +++ b/modules/freetype2/src/cff/cffparse.c @@ -4,7 +4,7 @@ /* */ /* CFF token stream parser (body) */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -20,10 +20,11 @@ #include "cffparse.h" #include FT_INTERNAL_STREAM_H #include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_CALC_H +#include FT_INTERNAL_POSTSCRIPT_AUX_H #include "cfferrs.h" #include "cffpic.h" -#include "cffgload.h" #include "cffload.h" @@ -156,6 +157,22 @@ 1000000000L }; + /* maximum values allowed for multiplying */ + /* with the corresponding `power_tens' element */ + static const FT_Long power_ten_limits[] = + { + FT_LONG_MAX / 1L, + FT_LONG_MAX / 10L, + FT_LONG_MAX / 100L, + FT_LONG_MAX / 1000L, + FT_LONG_MAX / 10000L, + FT_LONG_MAX / 100000L, + FT_LONG_MAX / 1000000L, + FT_LONG_MAX / 10000000L, + FT_LONG_MAX / 100000000L, + FT_LONG_MAX / 1000000000L, + }; + /* read a real */ static FT_Fixed @@ -448,9 +465,21 @@ /* 16.16 fixed point is used internally for CFF2 blend results. */ /* Since these are trusted values, a limit check is not needed. */ - /* After the 255, 4 bytes are in host order. */ - /* Blend result is rounded to integer. */ - return (FT_Long)( *( (FT_UInt32 *) ( d[0] + 1 ) ) + 0x8000U ) >> 16; + /* After the 255, 4 bytes give the number. */ + /* The blend value is converted to integer, with rounding; */ + /* due to the right-shift we don't need the lowest byte. */ +#if 0 + return (FT_Short)( + ( ( ( (FT_UInt32)*( d[0] + 1 ) << 24 ) | + ( (FT_UInt32)*( d[0] + 2 ) << 16 ) | + ( (FT_UInt32)*( d[0] + 3 ) << 8 ) | + (FT_UInt32)*( d[0] + 4 ) ) + 0x8000U ) >> 16 ); +#else + return (FT_Short)( + ( ( ( (FT_UInt32)*( d[0] + 1 ) << 16 ) | + ( (FT_UInt32)*( d[0] + 2 ) << 8 ) | + (FT_UInt32)*( d[0] + 3 ) ) + 0x80U ) >> 8 ); +#endif } else @@ -472,7 +501,15 @@ if ( scaling ) + { + if ( FT_ABS( val ) > power_ten_limits[scaling] ) + { + val = val > 0 ? 0x7FFFFFFFL : -0x7FFFFFFFL; + goto Overflow; + } + val *= power_tens[scaling]; + } if ( val > 0x7FFF ) { @@ -882,8 +919,6 @@ FT_Error error; - error = FT_ERR( Stack_Underflow ); - if ( !priv || !priv->subfont ) { error = FT_THROW( Invalid_File_Format ); @@ -914,7 +949,9 @@ goto Exit; } - FT_TRACE4(( " %d values blended\n", numBlends )); + FT_TRACE4(( " %d value%s blended\n", + numBlends, + numBlends == 1 ? "" : "s" )); error = cff_blend_doBlend( subFont, parser, numBlends ); @@ -1113,6 +1150,8 @@ #define CFF_FIELD_DELTA( code, name, max, id ) i++; #undef CFF_FIELD_CALLBACK #define CFF_FIELD_CALLBACK( code, name, id ) i++; +#undef CFF_FIELD_BLEND +#define CFF_FIELD_BLEND( code, id ) i++; #include "cfftoken.h" @@ -1160,6 +1199,17 @@ clazz[i].count_offset = FT_FIELD_OFFSET( num_ ## name_ ); \ i++; +#undef CFF_FIELD_BLEND +#define CFF_FIELD_BLEND( code_, id_ ) \ + clazz[i].kind = cff_kind_blend; \ + clazz[i].code = code_ | CFFCODE; \ + clazz[i].offset = 0; \ + clazz[i].size = 0; \ + clazz[i].reader = cff_parse_blend; \ + clazz[i].array_max = 0; \ + clazz[i].count_offset = 0; \ + i++; + #include "cfftoken.h" clazz[i].kind = 0; @@ -1210,6 +1260,18 @@ clazz[i].id = id_; \ i++; +#undef CFF_FIELD_BLEND +#define CFF_FIELD_BLEND( code_, id_ ) \ + clazz[i].kind = cff_kind_blend; \ + clazz[i].code = code_ | CFFCODE; \ + clazz[i].offset = 0; \ + clazz[i].size = 0; \ + clazz[i].reader = cff_parse_blend; \ + clazz[i].array_max = 0; \ + clazz[i].count_offset = 0; \ + clazz[i].id = id_; \ + i++; + #include "cfftoken.h" clazz[i].kind = 0; @@ -1239,9 +1301,14 @@ FT_Byte* start, FT_Byte* limit ) { +#ifdef CFF_CONFIG_OPTION_OLD_ENGINE + PSAux_Service psaux; +#endif + FT_Byte* p = start; FT_Error error = FT_Err_Ok; FT_Library library = parser->library; + FT_UNUSED( library ); @@ -1328,10 +1395,16 @@ cff_rec.top_font.font_dict.num_axes = parser->num_axes; decoder.cff = &cff_rec; - error = cff_decoder_parse_charstrings( &decoder, - charstring_base, - charstring_len, - 1 ); + psaux = (PSAux_Service)FT_Get_Module_Interface( library, "psaux" ); + if ( !psaux ) + { + FT_ERROR(( "cff_parser_run: cannot access `psaux' module\n" )); + error = FT_THROW( Missing_Module ); + goto Exit; + } + + error = psaux->cff_decoder_funcs->parse_charstrings_old( + &decoder, charstring_base, charstring_len, 1 ); /* Now copy the stack data in the temporary decoder object, */ /* converting it back to charstring number representations */ @@ -1550,7 +1623,7 @@ val = 0; while ( num_args > 0 ) { - val += cff_parse_num( parser, data++ ); + val = ADD_LONG( val, cff_parse_num( parser, data++ ) ); switch ( field->size ) { case (8 / FT_CHAR_BIT): diff --git a/modules/freetype2/src/cff/cffparse.h b/modules/freetype2/src/cff/cffparse.h index 6088fec21..8a8caeca4 100644 --- a/modules/freetype2/src/cff/cffparse.h +++ b/modules/freetype2/src/cff/cffparse.h @@ -4,7 +4,7 @@ /* */ /* CFF token stream parser (specification) */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -21,7 +21,7 @@ #include <ft2build.h> -#include "cfftypes.h" +#include FT_INTERNAL_CFF_TYPES_H #include FT_INTERNAL_OBJECTS_H @@ -31,8 +31,16 @@ FT_BEGIN_HEADER /* CFF uses constant parser stack size; */ /* CFF2 can increase from default 193 */ #define CFF_MAX_STACK_DEPTH 96 + + /* + * There are plans to remove the `maxstack' operator in a forthcoming + * revision of the CFF2 specification, increasing the (then static) stack + * size to 513. By making the default stack size equal to the maximum + * stack size, the operator is essentially disabled, which has the + * desired effect in FreeType. + */ #define CFF2_MAX_STACK 513 -#define CFF2_DEFAULT_STACK 193 +#define CFF2_DEFAULT_STACK 513 #define CFF_CODE_TOPDICT 0x1000 #define CFF_CODE_PRIVATE 0x2000 diff --git a/modules/freetype2/src/cff/cffpic.c b/modules/freetype2/src/cff/cffpic.c index a0bc34fd5..08b74c7cf 100644 --- a/modules/freetype2/src/cff/cffpic.c +++ b/modules/freetype2/src/cff/cffpic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for cff module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2018 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cff/cffpic.h b/modules/freetype2/src/cff/cffpic.h index 4737b9e38..8ba4203a8 100644 --- a/modules/freetype2/src/cff/cffpic.h +++ b/modules/freetype2/src/cff/cffpic.h @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for cff module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2018 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -22,7 +22,6 @@ #include FT_INTERNAL_PIC_H - #ifndef FT_CONFIG_OPTION_PIC #define CFF_SERVICE_PS_INFO_GET cff_service_ps_info @@ -33,6 +32,8 @@ #define CFF_SERVICE_PROPERTIES_GET cff_service_properties #define CFF_SERVICES_GET cff_services #define CFF_SERVICE_MULTI_MASTERS_GET cff_service_multi_masters +#define CFF_SERVICE_METRICS_VAR_GET cff_service_metrics_variations +#define CFF_SERVICE_CFF_LOAD_GET cff_service_cff_load #define CFF_CMAP_ENCODING_CLASS_REC_GET cff_cmap_encoding_class_rec #define CFF_CMAP_UNICODE_CLASS_REC_GET cff_cmap_unicode_class_rec #define CFF_FIELD_HANDLERS_GET cff_field_handlers @@ -46,22 +47,27 @@ #include FT_SERVICE_TT_CMAP_H #include FT_SERVICE_CID_H #include FT_SERVICE_PROPERTIES_H +#include FT_SERVICE_MULTIPLE_MASTERS_H +#include FT_SERVICE_METRICS_VARIATIONS_H FT_BEGIN_HEADER typedef struct CffModulePIC_ { - FT_ServiceDescRec* cff_services; - CFF_Field_Handler* cff_field_handlers; - FT_Service_PsInfoRec cff_service_ps_info; - FT_Service_GlyphDictRec cff_service_glyph_dict; - FT_Service_PsFontNameRec cff_service_ps_name; - FT_Service_TTCMapsRec cff_service_get_cmap_info; - FT_Service_CIDRec cff_service_cid_info; - FT_Service_PropertiesRec cff_service_properties; - FT_CMap_ClassRec cff_cmap_encoding_class_rec; - FT_CMap_ClassRec cff_cmap_unicode_class_rec; + FT_ServiceDescRec* cff_services; + CFF_Field_Handler* cff_field_handlers; + FT_Service_PsInfoRec cff_service_ps_info; + FT_Service_GlyphDictRec cff_service_glyph_dict; + FT_Service_PsFontNameRec cff_service_ps_name; + FT_Service_TTCMapsRec cff_service_get_cmap_info; + FT_Service_CIDRec cff_service_cid_info; + FT_Service_PropertiesRec cff_service_properties; + FT_Service_MultiMastersRec cff_service_multi_masters; + FT_Service_MetricsVariationsRec cff_service_metrics_variations; + FT_Service_CFFLoadRec cff_service_cff_load; + FT_CMap_ClassRec cff_cmap_encoding_class_rec; + FT_CMap_ClassRec cff_cmap_unicode_class_rec; } CffModulePIC; @@ -83,6 +89,12 @@ FT_BEGIN_HEADER ( GET_PIC( library )->cff_service_properties ) #define CFF_SERVICES_GET \ ( GET_PIC( library )->cff_services ) +#define CFF_SERVICE_MULTI_MASTERS_GET \ + ( GET_PIC( library )->cff_service_multi_masters ) +#define CFF_SERVICE_METRICS_VAR_GET \ + ( GET_PIC( library )->cff_service_metrics_variations ) +#define CFF_SERVICE_CFF_LOAD_GET \ + ( GET_PIC( library )->cff_service_cff_load ) #define CFF_CMAP_ENCODING_CLASS_REC_GET \ ( GET_PIC( library )->cff_cmap_encoding_class_rec ) #define CFF_CMAP_UNICODE_CLASS_REC_GET \ diff --git a/modules/freetype2/src/cff/cfftoken.h b/modules/freetype2/src/cff/cfftoken.h index fd41c6c71..fec1ca20b 100644 --- a/modules/freetype2/src/cff/cfftoken.h +++ b/modules/freetype2/src/cff/cfftoken.h @@ -4,7 +4,7 @@ /* */ /* CFF token definitions (specification only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cff/cfftypes.h b/modules/freetype2/src/cff/cfftypes.h deleted file mode 100644 index 4dae0f281..000000000 --- a/modules/freetype2/src/cff/cfftypes.h +++ /dev/null @@ -1,402 +0,0 @@ -/***************************************************************************/ -/* */ -/* cfftypes.h */ -/* */ -/* Basic OpenType/CFF type definitions and interface (specification */ -/* only). */ -/* */ -/* Copyright 1996-2016 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 CFFTYPES_H_ -#define CFFTYPES_H_ - - -#include <ft2build.h> -#include FT_FREETYPE_H -#include FT_TYPE1_TABLES_H -#include FT_INTERNAL_SERVICE_H -#include FT_SERVICE_POSTSCRIPT_CMAPS_H -#include FT_INTERNAL_POSTSCRIPT_HINTS_H - - -FT_BEGIN_HEADER - - - /*************************************************************************/ - /* */ - /* <Struct> */ - /* CFF_IndexRec */ - /* */ - /* <Description> */ - /* A structure used to model a CFF Index table. */ - /* */ - /* <Fields> */ - /* stream :: The source input stream. */ - /* */ - /* start :: The position of the first index byte in the */ - /* input stream. */ - /* */ - /* count :: The number of elements in the index. */ - /* */ - /* off_size :: The size in bytes of object offsets in index. */ - /* */ - /* data_offset :: The position of first data byte in the index's */ - /* bytes. */ - /* */ - /* data_size :: The size of the data table in this index. */ - /* */ - /* offsets :: A table of element offsets in the index. Must be */ - /* loaded explicitly. */ - /* */ - /* bytes :: If the index is loaded in memory, its bytes. */ - /* */ - typedef struct CFF_IndexRec_ - { - FT_Stream stream; - FT_ULong start; - FT_UInt hdr_size; - FT_UInt count; - FT_Byte off_size; - FT_ULong data_offset; - FT_ULong data_size; - - FT_ULong* offsets; - FT_Byte* bytes; - - } CFF_IndexRec, *CFF_Index; - - - typedef struct CFF_EncodingRec_ - { - FT_UInt format; - FT_ULong offset; - - FT_UInt count; - FT_UShort sids [256]; /* avoid dynamic allocations */ - FT_UShort codes[256]; - - } CFF_EncodingRec, *CFF_Encoding; - - - typedef struct CFF_CharsetRec_ - { - - FT_UInt format; - FT_ULong offset; - - FT_UShort* sids; - FT_UShort* cids; /* the inverse mapping of `sids'; only needed */ - /* for CID-keyed fonts */ - FT_UInt max_cid; - FT_UInt num_glyphs; - - } CFF_CharsetRec, *CFF_Charset; - - - /* cf. similar fields in file `ttgxvar.h' from the `truetype' module */ - - typedef struct CFF_VarData_ - { -#if 0 - FT_UInt itemCount; /* not used; always zero */ - FT_UInt shortDeltaCount; /* not used; always zero */ -#endif - - FT_UInt regionIdxCount; /* number of regions in this var data */ - FT_UInt* regionIndices; /* array of `regionCount' indices; */ - /* these index `varRegionList' */ - } CFF_VarData; - - - /* contribution of one axis to a region */ - typedef struct CFF_AxisCoords_ - { - FT_Fixed startCoord; - FT_Fixed peakCoord; /* zero peak means no effect (factor = 1) */ - FT_Fixed endCoord; - - } CFF_AxisCoords; - - - typedef struct CFF_VarRegion_ - { - CFF_AxisCoords* axisList; /* array of axisCount records */ - - } CFF_VarRegion; - - - typedef struct CFF_VStoreRec_ - { - FT_UInt dataCount; - CFF_VarData* varData; /* array of dataCount records */ - /* vsindex indexes this array */ - FT_UShort axisCount; - FT_UInt regionCount; /* total number of regions defined */ - CFF_VarRegion* varRegionList; - - } CFF_VStoreRec, *CFF_VStore; - - - /* forward reference */ - typedef struct CFF_FontRec_* CFF_Font; - - - /* This object manages one cached blend vector. */ - /* */ - /* There is a BlendRec for Private DICT parsing in each subfont */ - /* and a BlendRec for charstrings in CF2_Font instance data. */ - /* A cached BV may be used across DICTs or Charstrings if inputs */ - /* have not changed. */ - /* */ - /* `usedBV' is reset at the start of each parse or charstring. */ - /* vsindex cannot be changed after a BV is used. */ - /* */ - /* Note: NDV is long (32/64 bit), while BV is 16.16 (FT_Int32). */ - typedef struct CFF_BlendRec_ - { - FT_Bool builtBV; /* blendV has been built */ - FT_Bool usedBV; /* blendV has been used */ - CFF_Font font; /* top level font struct */ - FT_UInt lastVsindex; /* last vsindex used */ - FT_UInt lenNDV; /* normDV length (aka numAxes) */ - FT_Fixed* lastNDV; /* last NDV used */ - FT_UInt lenBV; /* BlendV length (aka numMasters) */ - FT_Int32* BV; /* current blendV (per DICT/glyph) */ - - } CFF_BlendRec, *CFF_Blend; - - - typedef struct CFF_FontRecDictRec_ - { - FT_UInt version; - FT_UInt notice; - FT_UInt copyright; - FT_UInt full_name; - FT_UInt family_name; - FT_UInt weight; - FT_Bool is_fixed_pitch; - FT_Fixed italic_angle; - FT_Fixed underline_position; - FT_Fixed underline_thickness; - FT_Int paint_type; - FT_Int charstring_type; - FT_Matrix font_matrix; - FT_Bool has_font_matrix; - FT_ULong units_per_em; /* temporarily used as scaling value also */ - FT_Vector font_offset; - FT_ULong unique_id; - FT_BBox font_bbox; - FT_Pos stroke_width; - FT_ULong charset_offset; - FT_ULong encoding_offset; - FT_ULong charstrings_offset; - FT_ULong private_offset; - FT_ULong private_size; - FT_Long synthetic_base; - FT_UInt embedded_postscript; - - /* these should only be used for the top-level font dictionary */ - FT_UInt cid_registry; - FT_UInt cid_ordering; - FT_Long cid_supplement; - - FT_Long cid_font_version; - FT_Long cid_font_revision; - FT_Long cid_font_type; - FT_ULong cid_count; - FT_ULong cid_uid_base; - FT_ULong cid_fd_array_offset; - FT_ULong cid_fd_select_offset; - FT_UInt cid_font_name; - - /* the next fields come from the data of the deprecated */ - /* `MultipleMaster' operator; they are needed to parse the (also */ - /* deprecated) `blend' operator in Type 2 charstrings */ - FT_UShort num_designs; - FT_UShort num_axes; - - /* fields for CFF2 */ - FT_ULong vstore_offset; - FT_UInt maxstack; - - } CFF_FontRecDictRec, *CFF_FontRecDict; - - - /* forward reference */ - typedef struct CFF_SubFontRec_* CFF_SubFont; - - - typedef struct CFF_PrivateRec_ - { - FT_Byte num_blue_values; - FT_Byte num_other_blues; - FT_Byte num_family_blues; - FT_Byte num_family_other_blues; - - FT_Pos blue_values[14]; - FT_Pos other_blues[10]; - FT_Pos family_blues[14]; - FT_Pos family_other_blues[10]; - - FT_Fixed blue_scale; - FT_Pos blue_shift; - FT_Pos blue_fuzz; - FT_Pos standard_width; - FT_Pos standard_height; - - FT_Byte num_snap_widths; - FT_Byte num_snap_heights; - FT_Pos snap_widths[13]; - FT_Pos snap_heights[13]; - FT_Bool force_bold; - FT_Fixed force_bold_threshold; - FT_Int lenIV; - FT_Int language_group; - FT_Fixed expansion_factor; - FT_Long initial_random_seed; - FT_ULong local_subrs_offset; - FT_Pos default_width; - FT_Pos nominal_width; - - /* fields for CFF2 */ - FT_UInt vsindex; - CFF_SubFont subfont; - - } CFF_PrivateRec, *CFF_Private; - - - typedef struct CFF_FDSelectRec_ - { - FT_Byte format; - FT_UInt range_count; - - /* that's the table, taken from the file `as is' */ - FT_Byte* data; - FT_UInt data_size; - - /* small cache for format 3 only */ - FT_UInt cache_first; - FT_UInt cache_count; - FT_Byte cache_fd; - - } CFF_FDSelectRec, *CFF_FDSelect; - - - /* A SubFont packs a font dict and a private dict together. They are */ - /* needed to support CID-keyed CFF fonts. */ - typedef struct CFF_SubFontRec_ - { - CFF_FontRecDictRec font_dict; - CFF_PrivateRec private_dict; - - /* fields for CFF2 */ - CFF_BlendRec blend; /* current blend vector */ - FT_UInt lenNDV; /* current length NDV or zero */ - FT_Fixed* NDV; /* ptr to current NDV or NULL */ - - /* `blend_stack' is a writable buffer to hold blend results. */ - /* This buffer is to the side of the normal cff parser stack; */ - /* `cff_parse_blend' and `cff_blend_doBlend' push blend results here. */ - /* The normal stack then points to these values instead of the DICT */ - /* because all other operators in Private DICT clear the stack. */ - /* `blend_stack' could be cleared at each operator other than blend. */ - /* Blended values are stored as 5-byte fixed point values. */ - - FT_Byte* blend_stack; /* base of stack allocation */ - FT_Byte* blend_top; /* first empty slot */ - FT_UInt blend_used; /* number of bytes in use */ - FT_UInt blend_alloc; /* number of bytes allocated */ - - CFF_IndexRec local_subrs_index; - FT_Byte** local_subrs; /* array of pointers */ - /* into Local Subrs INDEX data */ - - } CFF_SubFontRec; - - -#define CFF_MAX_CID_FONTS 256 - - - typedef struct CFF_FontRec_ - { - FT_Library library; - FT_Stream stream; - FT_Memory memory; /* TODO: take this from stream->memory? */ - FT_ULong base_offset; /* offset to start of CFF */ - FT_UInt num_faces; - FT_UInt num_glyphs; - - FT_Byte version_major; - FT_Byte version_minor; - FT_Byte header_size; - - FT_UInt top_dict_length; /* cff2 only */ - - FT_Bool cff2; - - CFF_IndexRec name_index; - CFF_IndexRec top_dict_index; - CFF_IndexRec global_subrs_index; - - CFF_EncodingRec encoding; - CFF_CharsetRec charset; - - CFF_IndexRec charstrings_index; - CFF_IndexRec font_dict_index; - CFF_IndexRec private_index; - CFF_IndexRec local_subrs_index; - - FT_String* font_name; - - /* array of pointers into Global Subrs INDEX data */ - FT_Byte** global_subrs; - - /* array of pointers into String INDEX data stored at string_pool */ - FT_UInt num_strings; - FT_Byte** strings; - FT_Byte* string_pool; - FT_ULong string_pool_size; - - CFF_SubFontRec top_font; - FT_UInt num_subfonts; - CFF_SubFont subfonts[CFF_MAX_CID_FONTS]; - - CFF_FDSelectRec fd_select; - - /* interface to PostScript hinter */ - PSHinter_Service pshinter; - - /* interface to Postscript Names service */ - FT_Service_PsCMaps psnames; - - /* since version 2.3.0 */ - PS_FontInfoRec* font_info; /* font info dictionary */ - - /* since version 2.3.6 */ - FT_String* registry; - FT_String* ordering; - - /* since version 2.4.12 */ - FT_Generic cf2_instance; - - CFF_VStoreRec vstore; /* parsed vstore structure */ - - } CFF_FontRec; - - -FT_END_HEADER - -#endif /* CFFTYPES_H_ */ - - -/* END */ diff --git a/modules/freetype2/src/cff/module.mk b/modules/freetype2/src/cff/module.mk index 1b4781afe..8013d5dca 100644 --- a/modules/freetype2/src/cff/module.mk +++ b/modules/freetype2/src/cff/module.mk @@ -3,7 +3,7 @@ # -# Copyright 1996-2016 by +# Copyright 1996-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/cff/rules.mk b/modules/freetype2/src/cff/rules.mk index 92f68b1ed..bce672927 100644 --- a/modules/freetype2/src/cff/rules.mk +++ b/modules/freetype2/src/cff/rules.mk @@ -3,7 +3,7 @@ # -# Copyright 1996-2016 by +# Copyright 1996-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, @@ -32,27 +32,14 @@ CFF_DRV_SRC := $(CFF_DIR)/cffcmap.c \ $(CFF_DIR)/cffload.c \ $(CFF_DIR)/cffobjs.c \ $(CFF_DIR)/cffparse.c \ - $(CFF_DIR)/cffpic.c \ - $(CFF_DIR)/cf2arrst.c \ - $(CFF_DIR)/cf2blues.c \ - $(CFF_DIR)/cf2error.c \ - $(CFF_DIR)/cf2font.c \ - $(CFF_DIR)/cf2ft.c \ - $(CFF_DIR)/cf2hints.c \ - $(CFF_DIR)/cf2intrp.c \ - $(CFF_DIR)/cf2read.c \ - $(CFF_DIR)/cf2stack.c + $(CFF_DIR)/cffpic.c # CFF driver headers # CFF_DRV_H := $(CFF_DRV_SRC:%.c=%.h) \ $(CFF_DIR)/cfferrs.h \ - $(CFF_DIR)/cfftoken.h \ - $(CFF_DIR)/cfftypes.h \ - $(CFF_DIR)/cf2fixed.h \ - $(CFF_DIR)/cf2glue.h \ - $(CFF_DIR)/cf2types.h + $(CFF_DIR)/cfftoken.h # CFF driver object(s) diff --git a/modules/freetype2/src/cid/Jamfile b/modules/freetype2/src/cid/Jamfile index 4b4eea17d..1c232fda3 100644 --- a/modules/freetype2/src/cid/Jamfile +++ b/modules/freetype2/src/cid/Jamfile @@ -1,6 +1,6 @@ # FreeType 2 src/cid Jamfile # -# Copyright 2001-2016 by +# Copyright 2001-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/cid/ciderrs.h b/modules/freetype2/src/cid/ciderrs.h index 1dc98c7cd..a5a86e3fc 100644 --- a/modules/freetype2/src/cid/ciderrs.h +++ b/modules/freetype2/src/cid/ciderrs.h @@ -4,7 +4,7 @@ /* */ /* CID error codes (specification only). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cid/cidgload.c b/modules/freetype2/src/cid/cidgload.c index c7b95593e..d14f9a2cc 100644 --- a/modules/freetype2/src/cid/cidgload.c +++ b/modules/freetype2/src/cid/cidgload.c @@ -4,7 +4,7 @@ /* */ /* CID-keyed Type1 Glyph Loader (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -24,6 +24,10 @@ #include FT_OUTLINE_H #include FT_INTERNAL_CALC_H +#include FT_INTERNAL_POSTSCRIPT_AUX_H +#include FT_INTERNAL_CFF_TYPES_H +#include FT_DRIVER_H + #include "ciderrs.h" @@ -52,9 +56,11 @@ FT_ULong glyph_length = 0; PSAux_Service psaux = (PSAux_Service)face->psaux; + FT_Bool force_scaling = FALSE; + #ifdef FT_CONFIG_OPTION_INCREMENTAL - FT_Incremental_InterfaceRec *inc = - face->root.internal->incremental_interface; + FT_Incremental_InterfaceRec *inc = + face->root.internal->incremental_interface; #endif @@ -169,9 +175,57 @@ if ( decoder->lenIV >= 0 ) psaux->t1_decrypt( charstring, glyph_length, 4330 ); - error = decoder->funcs.parse_charstrings( - decoder, charstring + cs_offset, - glyph_length - cs_offset ); + /* choose which renderer to use */ +#ifdef T1_CONFIG_OPTION_OLD_ENGINE + if ( ( (PS_Driver)FT_FACE_DRIVER( face ) )->hinting_engine == + FT_HINTING_FREETYPE || + decoder->builder.metrics_only ) + error = psaux->t1_decoder_funcs->parse_charstrings_old( + decoder, + charstring + cs_offset, + glyph_length - cs_offset ); +#else + if ( decoder->builder.metrics_only ) + error = psaux->t1_decoder_funcs->parse_metrics( + decoder, + charstring + cs_offset, + glyph_length - cs_offset ); +#endif + else + { + PS_Decoder psdecoder; + CFF_SubFontRec subfont; + + + psaux->ps_decoder_init( &psdecoder, decoder, TRUE ); + + psaux->t1_make_subfont( FT_FACE( face ), + &dict->private_dict, + &subfont ); + psdecoder.current_subfont = &subfont; + + error = psaux->t1_decoder_funcs->parse_charstrings( + &psdecoder, + charstring + cs_offset, + glyph_length - cs_offset ); + + /* Adobe's engine uses 16.16 numbers everywhere; */ + /* as a consequence, glyphs larger than 2000ppem get rejected */ + if ( FT_ERR_EQ( error, Glyph_Too_Big ) ) + { + /* this time, we retry unhinted and scale up the glyph later on */ + /* (the engine uses and sets the hardcoded value 0x10000 / 64 = */ + /* 0x400 for both `x_scale' and `y_scale' in this case) */ + ((CID_GlyphSlot)decoder->builder.glyph)->hint = FALSE; + + force_scaling = TRUE; + + error = psaux->t1_decoder_funcs->parse_charstrings( + &psdecoder, + charstring + cs_offset, + glyph_length - cs_offset ); + } + } } #ifdef FT_CONFIG_OPTION_INCREMENTAL @@ -200,6 +254,8 @@ Exit: FT_FREE( charstring ); + ((CID_GlyphSlot)decoder->builder.glyph)->scaled = force_scaling; + return error; } @@ -288,10 +344,12 @@ T1_DecoderRec decoder; CID_Face face = (CID_Face)cidglyph->face; FT_Bool hinting; + FT_Bool scaled; PSAux_Service psaux = (PSAux_Service)face->psaux; FT_Matrix font_matrix; FT_Vector font_offset; + FT_Bool must_finish_decoder = FALSE; if ( glyph_index >= (FT_UInt)face->root.num_glyphs ) @@ -311,7 +369,10 @@ hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 && ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); + scaled = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ); + glyph->hint = hinting; + glyph->scaled = scaled; cidglyph->format = FT_GLYPH_FORMAT_OUTLINE; error = psaux->t1_decoder_funcs->init( &decoder, @@ -329,6 +390,8 @@ /* TODO: initialize decoder.len_buildchar and decoder.buildchar */ /* if we ever support CID-keyed multiple master fonts */ + must_finish_decoder = TRUE; + /* set up the decoder */ decoder.builder.no_recurse = FT_BOOL( ( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 ) ); @@ -337,12 +400,18 @@ if ( error ) goto Exit; + /* copy flags back for forced scaling */ + hinting = glyph->hint; + scaled = glyph->scaled; + font_matrix = decoder.font_matrix; font_offset = decoder.font_offset; /* save new glyph tables */ psaux->t1_decoder_funcs->done( &decoder ); + must_finish_decoder = FALSE; + /* now set the metrics -- this is rather simple, as */ /* the left side bearing is the xMin, and the top side */ /* bearing the yMax */ @@ -410,7 +479,7 @@ metrics->vertAdvance += font_offset.y; } - if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ) + if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || scaled ) { /* scale the outline and the metrics */ FT_Int n; @@ -451,6 +520,10 @@ } Exit: + + if ( must_finish_decoder ) + psaux->t1_decoder_funcs->done( &decoder ); + return error; } diff --git a/modules/freetype2/src/cid/cidgload.h b/modules/freetype2/src/cid/cidgload.h index 62d664b3a..4811852ae 100644 --- a/modules/freetype2/src/cid/cidgload.h +++ b/modules/freetype2/src/cid/cidgload.h @@ -4,7 +4,7 @@ /* */ /* OpenType Glyph Loader (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cid/cidload.c b/modules/freetype2/src/cid/cidload.c index fc2a3cfe7..27cd09b3c 100644 --- a/modules/freetype2/src/cid/cidload.c +++ b/modules/freetype2/src/cid/cidload.c @@ -4,7 +4,7 @@ /* */ /* CID-keyed Type1 font loader (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -461,6 +461,9 @@ FT_Byte* p; + if ( !num_subrs ) + continue; + /* reallocate offsets array if needed */ if ( num_subrs + 1 > max_offsets ) { diff --git a/modules/freetype2/src/cid/cidload.h b/modules/freetype2/src/cid/cidload.h index 680f0d8fc..3f8bd0862 100644 --- a/modules/freetype2/src/cid/cidload.h +++ b/modules/freetype2/src/cid/cidload.h @@ -4,7 +4,7 @@ /* */ /* CID-keyed Type1 font loader (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cid/cidobjs.c b/modules/freetype2/src/cid/cidobjs.c index 2d2600fd4..77afe1c87 100644 --- a/modules/freetype2/src/cid/cidobjs.c +++ b/modules/freetype2/src/cid/cidobjs.c @@ -4,7 +4,7 @@ /* */ /* CID objects manager (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -26,6 +26,7 @@ #include FT_SERVICE_POSTSCRIPT_CMAPS_H #include FT_INTERNAL_POSTSCRIPT_AUX_H #include FT_INTERNAL_POSTSCRIPT_HINTS_H +#include FT_DRIVER_H #include "ciderrs.h" @@ -113,16 +114,16 @@ CID_Size size = (CID_Size)cidsize; - if ( cidsize->internal ) + if ( cidsize->internal->module_data ) { PSH_Globals_Funcs funcs; funcs = cid_size_get_globals_funcs( size ); if ( funcs ) - funcs->destroy( (PSH_Globals)cidsize->internal ); + funcs->destroy( (PSH_Globals)cidsize->internal->module_data ); - cidsize->internal = NULL; + cidsize->internal->module_data = NULL; } } @@ -145,7 +146,7 @@ error = funcs->create( cidsize->face->memory, priv, &globals ); if ( !error ) - cidsize->internal = (FT_Size_Internal)(void*)globals; + cidsize->internal->module_data = globals; } return error; @@ -164,7 +165,7 @@ funcs = cid_size_get_globals_funcs( (CID_Size)size ); if ( funcs ) - funcs->set_scale( (PSH_Globals)size->internal, + funcs->set_scale( (PSH_Globals)size->internal->module_data, size->metrics.x_scale, size->metrics.y_scale, 0, 0 ); @@ -463,9 +464,42 @@ /* FreeType error code. 0 means success. */ /* */ FT_LOCAL_DEF( FT_Error ) - cid_driver_init( FT_Module driver ) + cid_driver_init( FT_Module module ) { - FT_UNUSED( driver ); + PS_Driver driver = (PS_Driver)module; + + FT_UInt32 seed; + + + /* set default property values, cf. `ftt1drv.h' */ +#ifdef T1_CONFIG_OPTION_OLD_ENGINE + driver->hinting_engine = FT_HINTING_FREETYPE; +#else + driver->hinting_engine = FT_HINTING_ADOBE; +#endif + + driver->no_stem_darkening = TRUE; + + driver->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1; + driver->darken_params[1] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1; + driver->darken_params[2] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2; + driver->darken_params[3] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2; + driver->darken_params[4] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3; + driver->darken_params[5] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3; + driver->darken_params[6] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4; + driver->darken_params[7] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4; + + /* compute random seed from some memory addresses */ + seed = (FT_UInt32)( (FT_Offset)(char*)&seed ^ + (FT_Offset)(char*)&module ^ + (FT_Offset)(char*)module->memory ); + seed = seed ^ ( seed >> 10 ) ^ ( seed >> 20 ); + + driver->random_seed = (FT_Int32)seed; + if ( driver->random_seed < 0 ) + driver->random_seed = -driver->random_seed; + else if ( driver->random_seed == 0 ) + driver->random_seed = 123456789; return FT_Err_Ok; } diff --git a/modules/freetype2/src/cid/cidobjs.h b/modules/freetype2/src/cid/cidobjs.h index 5dd377a9f..0221f017d 100644 --- a/modules/freetype2/src/cid/cidobjs.h +++ b/modules/freetype2/src/cid/cidobjs.h @@ -4,7 +4,7 @@ /* */ /* CID objects manager (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cid/cidparse.c b/modules/freetype2/src/cid/cidparse.c index 1b27b2e95..b1c7f3cb2 100644 --- a/modules/freetype2/src/cid/cidparse.c +++ b/modules/freetype2/src/cid/cidparse.c @@ -4,7 +4,7 @@ /* */ /* CID-keyed Type1 parser (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cid/cidparse.h b/modules/freetype2/src/cid/cidparse.h index 7268dc6ae..61602f767 100644 --- a/modules/freetype2/src/cid/cidparse.h +++ b/modules/freetype2/src/cid/cidparse.h @@ -4,7 +4,7 @@ /* */ /* CID-keyed Type1 parser (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cid/cidriver.c b/modules/freetype2/src/cid/cidriver.c index 257365681..d9faf353e 100644 --- a/modules/freetype2/src/cid/cidriver.c +++ b/modules/freetype2/src/cid/cidriver.c @@ -4,7 +4,7 @@ /* */ /* CID driver interface (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -20,6 +20,7 @@ #include "cidriver.h" #include "cidgload.h" #include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_POSTSCRIPT_PROPS_H #include "ciderrs.h" @@ -27,6 +28,10 @@ #include FT_SERVICE_FONT_FORMAT_H #include FT_SERVICE_POSTSCRIPT_INFO_H #include FT_SERVICE_CID_H +#include FT_SERVICE_PROPERTIES_H +#include FT_DRIVER_H + +#include FT_INTERNAL_POSTSCRIPT_AUX_H /*************************************************************************/ @@ -168,6 +173,18 @@ /* + * PROPERTY SERVICE + * + */ + + FT_DEFINE_SERVICE_PROPERTIESREC( + cid_service_properties, + + (FT_Properties_SetFunc)ps_property_set, /* set_property */ + (FT_Properties_GetFunc)ps_property_get ) /* get_property */ + + + /* * SERVICE LIST * */ @@ -178,6 +195,7 @@ { FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cid_service_ps_name }, { FT_SERVICE_ID_POSTSCRIPT_INFO, &cid_service_ps_info }, { FT_SERVICE_ID_CID, &cid_service_cid_info }, + { FT_SERVICE_ID_PROPERTIES, &cid_service_properties }, { NULL, NULL } }; @@ -200,7 +218,7 @@ FT_MODULE_FONT_DRIVER | FT_MODULE_DRIVER_SCALABLE | FT_MODULE_DRIVER_HAS_HINTER, - sizeof ( FT_DriverRec ), + sizeof ( PS_DriverRec ), "t1cid", /* module name */ 0x10000L, /* version 1.0 of driver */ diff --git a/modules/freetype2/src/cid/cidriver.h b/modules/freetype2/src/cid/cidriver.h index a359a7890..59d9ded90 100644 --- a/modules/freetype2/src/cid/cidriver.h +++ b/modules/freetype2/src/cid/cidriver.h @@ -4,7 +4,7 @@ /* */ /* High-level CID driver interface (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cid/cidtoken.h b/modules/freetype2/src/cid/cidtoken.h index 9c773fd09..b0e2dac6a 100644 --- a/modules/freetype2/src/cid/cidtoken.h +++ b/modules/freetype2/src/cid/cidtoken.h @@ -4,7 +4,7 @@ /* */ /* CID token definitions (specification only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cid/module.mk b/modules/freetype2/src/cid/module.mk index d9585d781..9010e339a 100644 --- a/modules/freetype2/src/cid/module.mk +++ b/modules/freetype2/src/cid/module.mk @@ -3,7 +3,7 @@ # -# Copyright 1996-2016 by +# Copyright 1996-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/cid/rules.mk b/modules/freetype2/src/cid/rules.mk index f33aab00d..94333bda0 100644 --- a/modules/freetype2/src/cid/rules.mk +++ b/modules/freetype2/src/cid/rules.mk @@ -3,7 +3,7 @@ # -# Copyright 1996-2016 by +# Copyright 1996-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/cid/type1cid.c b/modules/freetype2/src/cid/type1cid.c index de3bdf770..61770e3f1 100644 --- a/modules/freetype2/src/cid/type1cid.c +++ b/modules/freetype2/src/cid/type1cid.c @@ -4,7 +4,7 @@ /* */ /* FreeType OpenType driver component (body only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,13 +17,13 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT - #include <ft2build.h> -#include "cidparse.c" + +#include "cidgload.c" #include "cidload.c" #include "cidobjs.c" +#include "cidparse.c" #include "cidriver.c" -#include "cidgload.c" /* END */ diff --git a/modules/freetype2/src/gxvalid/Jamfile b/modules/freetype2/src/gxvalid/Jamfile index 9738677e0..74f3c51ff 100644 --- a/modules/freetype2/src/gxvalid/Jamfile +++ b/modules/freetype2/src/gxvalid/Jamfile @@ -1,6 +1,6 @@ # FreeType 2 src/gxvalid Jamfile # -# Copyright 2005-2016 by +# Copyright 2005-2018 by # suzuki toshiya, Masatake YAMATO and Red Hat K.K. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/gxvalid/README b/modules/freetype2/src/gxvalid/README index d3ac49c3e..af8128e0e 100644 --- a/modules/freetype2/src/gxvalid/README +++ b/modules/freetype2/src/gxvalid/README @@ -9,7 +9,7 @@ gxvalid: TrueType GX validator additional tables in TrueType font which are used by `QuickDraw GX Text', Apple Advanced Typography (AAT). In addition, gxvalid can validates `kern' tables which have been extended for AAT. Like the - otvalid module, gxvalid uses Freetype 2's validator framework + otvalid module, gxvalid uses FreeType 2's validator framework (ftvalid). You can link gxvalid with your program; before running your own layout @@ -287,11 +287,11 @@ gxvalid: TrueType GX validator 4-5. invalid feature number (117/183) ------------------------------------- - The GX/AAT extension can include 255 different layout features, but - popular layout features are predefined (see - http://developer.apple.com/fonts/Registry/index.html). Some fonts - include feature numbers which are incompatible with the predefined - feature registry. + The GX/AAT extension can include 255 different layout features, + but popular layout features are predefined (see + https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html). + Some fonts include feature numbers which are incompatible with the + predefined feature registry. In our survey, there are 140 fonts including `feat' table. @@ -413,7 +413,7 @@ gxvalid: TrueType GX validator format assured for Windows and OS/2 support is only subtable format 0. The Microsoft TrueType specification also describes subtable format 2, but does not mention which platforms support - it. Aubtable formats 1, 3, and higher are documented as reserved + it. Subtable formats 1, 3, and higher are documented as reserved for future use. Therefore, the classic version can store subtable formats 0 and 2, at least. `ttfdump.exe', a font tool provided by Microsoft, ignores the subtable format written in the subtable @@ -518,7 +518,7 @@ gxvalid: TrueType GX validator ------------------------------------------------------------------------ -Copyright 2004-2016 by +Copyright 2004-2018 by suzuki toshiya, Masatake YAMATO, Red hat K.K., David Turner, Robert Wilhelm, and Werner Lemberg. diff --git a/modules/freetype2/src/gxvalid/gxvalid.c b/modules/freetype2/src/gxvalid/gxvalid.c index 7fb868cad..d0577a247 100644 --- a/modules/freetype2/src/gxvalid/gxvalid.c +++ b/modules/freetype2/src/gxvalid/gxvalid.c @@ -4,7 +4,7 @@ /* */ /* FreeType validator for TrueTypeGX/AAT tables (body only). */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ @@ -16,15 +16,17 @@ /* */ /***************************************************************************/ -#define FT_MAKE_OPTION_SINGLE_OBJECT +#define FT_MAKE_OPTION_SINGLE_OBJECT #include <ft2build.h> -#include "gxvfeat.c" -#include "gxvcommn.c" #include "gxvbsln.c" -#include "gxvtrak.c" +#include "gxvcommn.c" +#include "gxvfeat.c" #include "gxvjust.c" +#include "gxvkern.c" +#include "gxvlcar.c" +#include "gxvmod.c" #include "gxvmort.c" #include "gxvmort0.c" #include "gxvmort1.c" @@ -37,11 +39,9 @@ #include "gxvmorx2.c" #include "gxvmorx4.c" #include "gxvmorx5.c" -#include "gxvkern.c" #include "gxvopbd.c" #include "gxvprop.c" -#include "gxvlcar.c" -#include "gxvmod.c" +#include "gxvtrak.c" /* END */ diff --git a/modules/freetype2/src/gxvalid/gxvalid.h b/modules/freetype2/src/gxvalid/gxvalid.h index 7a3ab795e..19f037998 100644 --- a/modules/freetype2/src/gxvalid/gxvalid.h +++ b/modules/freetype2/src/gxvalid/gxvalid.h @@ -2,9 +2,9 @@ /* */ /* gxvalid.h */ /* */ -/* TrueTyeeGX/AAT table validation (specification only). */ +/* TrueTypeGX/AAT table validation (specification only). */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/gxvalid/gxvbsln.c b/modules/freetype2/src/gxvalid/gxvbsln.c index 493b20c31..c367d3848 100644 --- a/modules/freetype2/src/gxvalid/gxvbsln.c +++ b/modules/freetype2/src/gxvalid/gxvbsln.c @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT bsln table validation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/gxvalid/gxvcommn.c b/modules/freetype2/src/gxvalid/gxvcommn.c index b324bc602..b96601108 100644 --- a/modules/freetype2/src/gxvalid/gxvcommn.c +++ b/modules/freetype2/src/gxvalid/gxvcommn.c @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT common tables validation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ @@ -454,7 +454,7 @@ } - /* ================= Segment Single Format 2 Loolup Table ============== */ + /* ================= Segment Single Format 2 Lookup Table ============== */ /* * Apple spec says: * diff --git a/modules/freetype2/src/gxvalid/gxvcommn.h b/modules/freetype2/src/gxvalid/gxvcommn.h index 9470c8412..8e4ff9caf 100644 --- a/modules/freetype2/src/gxvalid/gxvcommn.h +++ b/modules/freetype2/src/gxvalid/gxvcommn.h @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT common tables validation (specification). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/gxvalid/gxverror.h b/modules/freetype2/src/gxvalid/gxverror.h index 2e53355ce..d1151258a 100644 --- a/modules/freetype2/src/gxvalid/gxverror.h +++ b/modules/freetype2/src/gxvalid/gxverror.h @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT validation module error codes (specification only). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/gxvalid/gxvfeat.c b/modules/freetype2/src/gxvalid/gxvfeat.c index 5bff7c261..2c805d1d1 100644 --- a/modules/freetype2/src/gxvalid/gxvfeat.c +++ b/modules/freetype2/src/gxvalid/gxvfeat.c @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT feat table validation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/gxvalid/gxvfeat.h b/modules/freetype2/src/gxvalid/gxvfeat.h index 284bada89..2d943806c 100644 --- a/modules/freetype2/src/gxvalid/gxvfeat.h +++ b/modules/freetype2/src/gxvalid/gxvfeat.h @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT feat table validation (specification). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/gxvalid/gxvfgen.c b/modules/freetype2/src/gxvalid/gxvfgen.c index 667dac3cd..840c0f352 100644 --- a/modules/freetype2/src/gxvalid/gxvfgen.c +++ b/modules/freetype2/src/gxvalid/gxvfgen.c @@ -5,7 +5,7 @@ /* Generate feature registry data for gxv `feat' validator. */ /* This program is derived from gxfeatreg.c in gxlayout. */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* Masatake YAMATO and Redhat K.K. */ /* */ /* This file may only be used, */ @@ -21,7 +21,7 @@ /* gxfeatreg.c */ /* */ /* Database of font features pre-defined by Apple Computer, Inc. */ -/* http://developer.apple.com/fonts/Registry/ */ +/* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html */ /* (body). */ /* */ /* Copyright 2003 by */ diff --git a/modules/freetype2/src/gxvalid/gxvjust.c b/modules/freetype2/src/gxvalid/gxvjust.c index 20d29bfbc..00c429319 100644 --- a/modules/freetype2/src/gxvalid/gxvjust.c +++ b/modules/freetype2/src/gxvalid/gxvjust.c @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT just table validation (body). */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/gxvalid/gxvkern.c b/modules/freetype2/src/gxvalid/gxvkern.c index ee1ab36f7..9c0efd7a4 100644 --- a/modules/freetype2/src/gxvalid/gxvkern.c +++ b/modules/freetype2/src/gxvalid/gxvkern.c @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT kern table validation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/gxvalid/gxvlcar.c b/modules/freetype2/src/gxvalid/gxvlcar.c index d31b6410b..0f261a9ac 100644 --- a/modules/freetype2/src/gxvalid/gxvlcar.c +++ b/modules/freetype2/src/gxvalid/gxvlcar.c @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT lcar table validation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/gxvalid/gxvmod.c b/modules/freetype2/src/gxvalid/gxvmod.c index 32fd84e14..1a3c86292 100644 --- a/modules/freetype2/src/gxvalid/gxvmod.c +++ b/modules/freetype2/src/gxvalid/gxvmod.c @@ -4,7 +4,7 @@ /* */ /* FreeType's TrueTypeGX/AAT validation module implementation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/gxvalid/gxvmod.h b/modules/freetype2/src/gxvalid/gxvmod.h index 8b82e9107..745c62e10 100644 --- a/modules/freetype2/src/gxvalid/gxvmod.h +++ b/modules/freetype2/src/gxvalid/gxvmod.h @@ -5,7 +5,7 @@ /* FreeType's TrueTypeGX/AAT validation module implementation */ /* (specification). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/gxvalid/gxvmort.c b/modules/freetype2/src/gxvalid/gxvmort.c index 120939204..b361cb2b9 100644 --- a/modules/freetype2/src/gxvalid/gxvmort.c +++ b/modules/freetype2/src/gxvalid/gxvmort.c @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT mort table validation (body). */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/gxvalid/gxvmort.h b/modules/freetype2/src/gxvalid/gxvmort.h index 5fd228212..d8030645e 100644 --- a/modules/freetype2/src/gxvalid/gxvmort.h +++ b/modules/freetype2/src/gxvalid/gxvmort.h @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT common definition for mort table (specification). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/gxvalid/gxvmort0.c b/modules/freetype2/src/gxvalid/gxvmort0.c index e11f5ddc4..95cf53d5e 100644 --- a/modules/freetype2/src/gxvalid/gxvmort0.c +++ b/modules/freetype2/src/gxvalid/gxvmort0.c @@ -5,7 +5,7 @@ /* TrueTypeGX/AAT mort table validation */ /* body for type0 (Indic Script Rearrangement) subtable. */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/gxvalid/gxvmort1.c b/modules/freetype2/src/gxvalid/gxvmort1.c index fd761d069..a7683a17b 100644 --- a/modules/freetype2/src/gxvalid/gxvmort1.c +++ b/modules/freetype2/src/gxvalid/gxvmort1.c @@ -5,7 +5,7 @@ /* TrueTypeGX/AAT mort table validation */ /* body for type1 (Contextual Substitution) subtable. */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/gxvalid/gxvmort2.c b/modules/freetype2/src/gxvalid/gxvmort2.c index 08455dec6..c23c2775a 100644 --- a/modules/freetype2/src/gxvalid/gxvmort2.c +++ b/modules/freetype2/src/gxvalid/gxvmort2.c @@ -5,7 +5,7 @@ /* TrueTypeGX/AAT mort table validation */ /* body for type2 (Ligature Substitution) subtable. */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/gxvalid/gxvmort4.c b/modules/freetype2/src/gxvalid/gxvmort4.c index 6f7bbb871..9d21a5fc2 100644 --- a/modules/freetype2/src/gxvalid/gxvmort4.c +++ b/modules/freetype2/src/gxvalid/gxvmort4.c @@ -5,7 +5,7 @@ /* TrueTypeGX/AAT mort table validation */ /* body for type4 (Non-Contextual Glyph Substitution) subtable. */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/gxvalid/gxvmort5.c b/modules/freetype2/src/gxvalid/gxvmort5.c index 54ddbe2b1..42cb428aa 100644 --- a/modules/freetype2/src/gxvalid/gxvmort5.c +++ b/modules/freetype2/src/gxvalid/gxvmort5.c @@ -5,7 +5,7 @@ /* TrueTypeGX/AAT mort table validation */ /* body for type5 (Contextual Glyph Insertion) subtable. */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/gxvalid/gxvmorx.c b/modules/freetype2/src/gxvalid/gxvmorx.c index b626993f2..9fd6e6b97 100644 --- a/modules/freetype2/src/gxvalid/gxvmorx.c +++ b/modules/freetype2/src/gxvalid/gxvmorx.c @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT morx table validation (body). */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/gxvalid/gxvmorx.h b/modules/freetype2/src/gxvalid/gxvmorx.h index 9ba25c14a..6d9925e92 100644 --- a/modules/freetype2/src/gxvalid/gxvmorx.h +++ b/modules/freetype2/src/gxvalid/gxvmorx.h @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT common definition for morx table (specification). */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/gxvalid/gxvmorx0.c b/modules/freetype2/src/gxvalid/gxvmorx0.c index 4abb7368f..302261b7f 100644 --- a/modules/freetype2/src/gxvalid/gxvmorx0.c +++ b/modules/freetype2/src/gxvalid/gxvmorx0.c @@ -5,7 +5,7 @@ /* TrueTypeGX/AAT morx table validation */ /* body for type0 (Indic Script Rearrangement) subtable. */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/gxvalid/gxvmorx1.c b/modules/freetype2/src/gxvalid/gxvmorx1.c index e581848c2..890ca74b1 100644 --- a/modules/freetype2/src/gxvalid/gxvmorx1.c +++ b/modules/freetype2/src/gxvalid/gxvmorx1.c @@ -5,7 +5,7 @@ /* TrueTypeGX/AAT morx table validation */ /* body for type1 (Contextual Substitution) subtable. */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/gxvalid/gxvmorx2.c b/modules/freetype2/src/gxvalid/gxvmorx2.c index 9495cca48..3135031d4 100644 --- a/modules/freetype2/src/gxvalid/gxvmorx2.c +++ b/modules/freetype2/src/gxvalid/gxvmorx2.c @@ -5,7 +5,7 @@ /* TrueTypeGX/AAT morx table validation */ /* body for type2 (Ligature Substitution) subtable. */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/gxvalid/gxvmorx4.c b/modules/freetype2/src/gxvalid/gxvmorx4.c index 3b7731bbc..1e2397b0c 100644 --- a/modules/freetype2/src/gxvalid/gxvmorx4.c +++ b/modules/freetype2/src/gxvalid/gxvmorx4.c @@ -5,7 +5,7 @@ /* TrueTypeGX/AAT morx table validation */ /* body for "morx" type4 (Non-Contextual Glyph Substitution) subtable. */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/gxvalid/gxvmorx5.c b/modules/freetype2/src/gxvalid/gxvmorx5.c index 0e96166c0..db4f9290c 100644 --- a/modules/freetype2/src/gxvalid/gxvmorx5.c +++ b/modules/freetype2/src/gxvalid/gxvmorx5.c @@ -5,7 +5,7 @@ /* TrueTypeGX/AAT morx table validation */ /* body for type5 (Contextual Glyph Insertion) subtable. */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/gxvalid/gxvopbd.c b/modules/freetype2/src/gxvalid/gxvopbd.c index e3ba082e1..e2c167ea5 100644 --- a/modules/freetype2/src/gxvalid/gxvopbd.c +++ b/modules/freetype2/src/gxvalid/gxvopbd.c @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT opbd table validation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/gxvalid/gxvprop.c b/modules/freetype2/src/gxvalid/gxvprop.c index 61b3aeee3..a67b6bdd0 100644 --- a/modules/freetype2/src/gxvalid/gxvprop.c +++ b/modules/freetype2/src/gxvalid/gxvprop.c @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT prop table validation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/gxvalid/gxvtrak.c b/modules/freetype2/src/gxvalid/gxvtrak.c index 0f07c04e2..d501b5014 100644 --- a/modules/freetype2/src/gxvalid/gxvtrak.c +++ b/modules/freetype2/src/gxvalid/gxvtrak.c @@ -4,7 +4,7 @@ /* */ /* TrueTypeGX/AAT trak table validation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ diff --git a/modules/freetype2/src/gxvalid/module.mk b/modules/freetype2/src/gxvalid/module.mk index b431384a5..b64879dce 100644 --- a/modules/freetype2/src/gxvalid/module.mk +++ b/modules/freetype2/src/gxvalid/module.mk @@ -2,7 +2,7 @@ # FreeType 2 gxvalid module definition # -# Copyright 2004-2016 by +# Copyright 2004-2018 by # suzuki toshiya, Masatake YAMATO, Red Hat K.K., # David Turner, Robert Wilhelm, and Werner Lemberg. # diff --git a/modules/freetype2/src/gxvalid/rules.mk b/modules/freetype2/src/gxvalid/rules.mk index 424f2a637..3a17c030a 100644 --- a/modules/freetype2/src/gxvalid/rules.mk +++ b/modules/freetype2/src/gxvalid/rules.mk @@ -3,7 +3,7 @@ # -# Copyright 2004-2016 by +# Copyright 2004-2018 by # suzuki toshiya, Masatake YAMATO, Red Hat K.K., # David Turner, Robert Wilhelm, and Werner Lemberg. # diff --git a/modules/freetype2/src/gzip/Jamfile b/modules/freetype2/src/gzip/Jamfile index ca994c3e1..a7b4c8c95 100644 --- a/modules/freetype2/src/gzip/Jamfile +++ b/modules/freetype2/src/gzip/Jamfile @@ -1,6 +1,6 @@ # FreeType 2 src/gzip Jamfile # -# Copyright 2001-2016 by +# Copyright 2001-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/gzip/ftgzip.c b/modules/freetype2/src/gzip/ftgzip.c index 74b467faa..f8011c2dd 100644 --- a/modules/freetype2/src/gzip/ftgzip.c +++ b/modules/freetype2/src/gzip/ftgzip.c @@ -8,7 +8,7 @@ /* parse compressed PCF fonts, as found with many X11 server */ /* distributions. */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/gzip/rules.mk b/modules/freetype2/src/gzip/rules.mk index 16af8c02d..1a2e48beb 100644 --- a/modules/freetype2/src/gzip/rules.mk +++ b/modules/freetype2/src/gzip/rules.mk @@ -3,7 +3,7 @@ # -# Copyright 2002-2016 by +# Copyright 2002-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, @@ -34,8 +34,8 @@ endif # gzip support sources # -# All source and header files get loaded by `ftgzip.c' only if SYTEM_ZLIB is -# not defined (regardless whether we have a `single' or a `multi' build). +# All source and header files get loaded by `ftgzip.c' only if SYSTEM_ZLIB +# is not defined (regardless whether we have a `single' or a `multi' build). # However, it doesn't harm if we add everything as a dependency # unconditionally. # diff --git a/modules/freetype2/src/lzw/Jamfile b/modules/freetype2/src/lzw/Jamfile index b7ec3b17e..cb83aa4a5 100644 --- a/modules/freetype2/src/lzw/Jamfile +++ b/modules/freetype2/src/lzw/Jamfile @@ -1,6 +1,6 @@ # FreeType 2 src/lzw Jamfile # -# Copyright 2004-2016 by +# Copyright 2004-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/lzw/ftlzw.c b/modules/freetype2/src/lzw/ftlzw.c index 6f5f89708..cb46f93c6 100644 --- a/modules/freetype2/src/lzw/ftlzw.c +++ b/modules/freetype2/src/lzw/ftlzw.c @@ -8,7 +8,7 @@ /* be used to parse compressed PCF fonts, as found with many X11 server */ /* distributions. */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* Albert Chin-A-Young. */ /* */ /* based on code in `src/gzip/ftgzip.c' */ diff --git a/modules/freetype2/src/lzw/ftzopen.c b/modules/freetype2/src/lzw/ftzopen.c index a2cc453d6..2b868ba9f 100644 --- a/modules/freetype2/src/lzw/ftzopen.c +++ b/modules/freetype2/src/lzw/ftzopen.c @@ -8,7 +8,7 @@ /* be used to parse compressed PCF fonts, as found with many X11 server */ /* distributions. */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2018 by */ /* David Turner. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/lzw/ftzopen.h b/modules/freetype2/src/lzw/ftzopen.h index 1c38f1ab3..4fd267eb9 100644 --- a/modules/freetype2/src/lzw/ftzopen.h +++ b/modules/freetype2/src/lzw/ftzopen.h @@ -8,7 +8,7 @@ /* be used to parse compressed PCF fonts, as found with many X11 server */ /* distributions. */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2018 by */ /* David Turner. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/lzw/rules.mk b/modules/freetype2/src/lzw/rules.mk index 13e41b976..18933c41c 100644 --- a/modules/freetype2/src/lzw/rules.mk +++ b/modules/freetype2/src/lzw/rules.mk @@ -3,7 +3,7 @@ # -# Copyright 2004-2016 by +# Copyright 2004-2018 by # Albert Chin-A-Young. # # based on `src/lzw/rules.mk' diff --git a/modules/freetype2/src/otvalid/Jamfile b/modules/freetype2/src/otvalid/Jamfile index eded89ab9..21b8e0cb0 100644 --- a/modules/freetype2/src/otvalid/Jamfile +++ b/modules/freetype2/src/otvalid/Jamfile @@ -1,6 +1,6 @@ # FreeType 2 src/otvalid Jamfile # -# Copyright 2004-2016 by +# Copyright 2004-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/otvalid/module.mk b/modules/freetype2/src/otvalid/module.mk index b929cdbab..34f3dab32 100644 --- a/modules/freetype2/src/otvalid/module.mk +++ b/modules/freetype2/src/otvalid/module.mk @@ -3,7 +3,7 @@ # -# Copyright 2004-2016 by +# Copyright 2004-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/otvalid/otvalid.c b/modules/freetype2/src/otvalid/otvalid.c index 932a974a3..4423ca101 100644 --- a/modules/freetype2/src/otvalid/otvalid.c +++ b/modules/freetype2/src/otvalid/otvalid.c @@ -4,7 +4,7 @@ /* */ /* FreeType validator for OpenType tables (body only). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -15,8 +15,8 @@ /* */ /***************************************************************************/ -#define FT_MAKE_OPTION_SINGLE_OBJECT +#define FT_MAKE_OPTION_SINGLE_OBJECT #include <ft2build.h> #include "otvbase.c" @@ -28,4 +28,5 @@ #include "otvmath.c" #include "otvmod.c" + /* END */ diff --git a/modules/freetype2/src/otvalid/otvalid.h b/modules/freetype2/src/otvalid/otvalid.h index 93438a063..d7801abae 100644 --- a/modules/freetype2/src/otvalid/otvalid.h +++ b/modules/freetype2/src/otvalid/otvalid.h @@ -4,7 +4,7 @@ /* */ /* OpenType table validation (specification only). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/otvalid/otvbase.c b/modules/freetype2/src/otvalid/otvbase.c index e86e8bb2f..a01d45c70 100644 --- a/modules/freetype2/src/otvalid/otvbase.c +++ b/modules/freetype2/src/otvalid/otvbase.c @@ -4,7 +4,7 @@ /* */ /* OpenType BASE table validation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -284,22 +284,41 @@ OTV_Validator otvalid = &otvalidrec; FT_Bytes p = table; FT_UInt table_size; + FT_UShort version; OTV_OPTIONAL_TABLE( HorizAxis ); OTV_OPTIONAL_TABLE( VertAxis ); + OTV_OPTIONAL_TABLE32( itemVarStore ); + otvalid->root = ftvalid; FT_TRACE3(( "validating BASE table\n" )); OTV_INIT; - OTV_LIMIT_CHECK( 6 ); + OTV_LIMIT_CHECK( 4 ); - if ( FT_NEXT_ULONG( p ) != 0x10000UL ) /* Version */ + if ( FT_NEXT_USHORT( p ) != 1 ) /* majorVersion */ FT_INVALID_FORMAT; - table_size = 6; + version = FT_NEXT_USHORT( p ); /* minorVersion */ + + table_size = 8; + switch ( version ) + { + case 0: + OTV_LIMIT_CHECK( 4 ); + break; + + case 1: + OTV_LIMIT_CHECK( 8 ); + table_size += 4; + break; + + default: + FT_INVALID_FORMAT; + } OTV_OPTIONAL_OFFSET( HorizAxis ); OTV_SIZE_CHECK( HorizAxis ); @@ -311,6 +330,14 @@ if ( VertAxis ) otv_Axis_validate( table + VertAxis, otvalid ); + if ( version > 0 ) + { + OTV_OPTIONAL_OFFSET32( itemVarStore ); + OTV_SIZE_CHECK32( itemVarStore ); + if ( itemVarStore ) + OTV_TRACE(( " [omitting itemVarStore validation]\n" )); /* XXX */ + } + FT_TRACE4(( "\n" )); } diff --git a/modules/freetype2/src/otvalid/otvcommn.c b/modules/freetype2/src/otvalid/otvcommn.c index 6a684441d..0ccfb03c0 100644 --- a/modules/freetype2/src/otvalid/otvcommn.c +++ b/modules/freetype2/src/otvalid/otvcommn.c @@ -4,7 +4,7 @@ /* */ /* OpenType common tables validation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -313,19 +313,26 @@ OTV_NAME_ENTER( "Device" ); - OTV_LIMIT_CHECK( 8 ); + OTV_LIMIT_CHECK( 6 ); StartSize = FT_NEXT_USHORT( p ); EndSize = FT_NEXT_USHORT( p ); DeltaFormat = FT_NEXT_USHORT( p ); - if ( DeltaFormat < 1 || DeltaFormat > 3 ) - FT_INVALID_FORMAT; + if ( DeltaFormat == 0x8000U ) + { + /* VariationIndex, nothing to do */ + } + else + { + if ( DeltaFormat < 1 || DeltaFormat > 3 ) + FT_INVALID_FORMAT; - if ( EndSize < StartSize ) - FT_INVALID_DATA; + if ( EndSize < StartSize ) + FT_INVALID_DATA; - count = EndSize - StartSize + 1; - OTV_LIMIT_CHECK( ( 1 << DeltaFormat ) * count / 8 ); /* DeltaValue */ + count = EndSize - StartSize + 1; + OTV_LIMIT_CHECK( ( 1 << DeltaFormat ) * count / 8 ); /* DeltaValue */ + } OTV_EXIT; } @@ -347,7 +354,7 @@ OTV_Validator otvalid ) { FT_Bytes p = table; - FT_UInt LookupType, SubTableCount; + FT_UInt LookupType, LookupFlag, SubTableCount; OTV_Validate_Func validate; @@ -355,7 +362,7 @@ OTV_LIMIT_CHECK( 6 ); LookupType = FT_NEXT_USHORT( p ); - p += 2; /* skip LookupFlag */ + LookupFlag = FT_NEXT_USHORT( p ); SubTableCount = FT_NEXT_USHORT( p ); OTV_TRACE(( " (type %d)\n", LookupType )); @@ -373,6 +380,9 @@ for ( ; SubTableCount > 0; SubTableCount-- ) validate( table + FT_NEXT_USHORT( p ), otvalid ); + if ( LookupFlag & 0x10 ) + OTV_LIMIT_CHECK( 2 ); /* MarkFilteringSet */ + OTV_EXIT; } diff --git a/modules/freetype2/src/otvalid/otvcommn.h b/modules/freetype2/src/otvalid/otvcommn.h index 44e0c6379..a392784cf 100644 --- a/modules/freetype2/src/otvalid/otvcommn.h +++ b/modules/freetype2/src/otvalid/otvcommn.h @@ -4,7 +4,7 @@ /* */ /* OpenType common tables validation (specification). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -67,29 +67,38 @@ FT_BEGIN_HEADER #undef FT_INVALID_ -#define FT_INVALID_( _error ) \ +#define FT_INVALID_( _error ) \ ft_validator_error( otvalid->root, FT_THROW( _error ) ) #define OTV_OPTIONAL_TABLE( _table ) FT_UShort _table; \ FT_Bytes _table ## _p +#define OTV_OPTIONAL_TABLE32( _table ) FT_ULong _table; \ + FT_Bytes _table ## _p + #define OTV_OPTIONAL_OFFSET( _offset ) \ FT_BEGIN_STMNT \ _offset ## _p = p; \ _offset = FT_NEXT_USHORT( p ); \ FT_END_STMNT -#define OTV_LIMIT_CHECK( _count ) \ - FT_BEGIN_STMNT \ +#define OTV_OPTIONAL_OFFSET32( _offset ) \ + FT_BEGIN_STMNT \ + _offset ## _p = p; \ + _offset = FT_NEXT_ULONG( p ); \ + FT_END_STMNT + +#define OTV_LIMIT_CHECK( _count ) \ + FT_BEGIN_STMNT \ if ( p + (_count) > otvalid->root->limit ) \ - FT_INVALID_TOO_SHORT; \ + FT_INVALID_TOO_SHORT; \ FT_END_STMNT #define OTV_SIZE_CHECK( _size ) \ FT_BEGIN_STMNT \ if ( _size > 0 && _size < table_size ) \ { \ - if ( otvalid->root->level == FT_VALIDATE_PARANOID ) \ + if ( otvalid->root->level == FT_VALIDATE_PARANOID ) \ FT_INVALID_OFFSET; \ else \ { \ @@ -102,12 +111,33 @@ FT_BEGIN_HEADER " set to zero.\n" \ "\n", #_size )); \ \ - /* always assume 16bit entities */ \ _size = pp[0] = pp[1] = 0; \ } \ } \ FT_END_STMNT +#define OTV_SIZE_CHECK32( _size ) \ + FT_BEGIN_STMNT \ + if ( _size > 0 && _size < table_size ) \ + { \ + if ( otvalid->root->level == FT_VALIDATE_PARANOID ) \ + FT_INVALID_OFFSET; \ + else \ + { \ + /* strip off `const' */ \ + FT_Byte* pp = (FT_Byte*)_size ## _p; \ + \ + \ + FT_TRACE3(( "\n" \ + "Invalid offset to optional table `%s'" \ + " set to zero.\n" \ + "\n", #_size )); \ + \ + _size = pp[0] = pp[1] = pp[2] = pp[3] = 0; \ + } \ + } \ + FT_END_STMNT + #define OTV_NAME_(x) #x #define OTV_NAME(x) OTV_NAME_(x) @@ -146,11 +176,11 @@ FT_BEGIN_HEADER #define OTV_INIT otvalid->debug_indent = 0 -#define OTV_ENTER \ - FT_BEGIN_STMNT \ - otvalid->debug_indent += 2; \ - FT_TRACE4(( "%*.s", otvalid->debug_indent, 0 )); \ - FT_TRACE4(( "%s table\n", \ +#define OTV_ENTER \ + FT_BEGIN_STMNT \ + otvalid->debug_indent += 2; \ + FT_TRACE4(( "%*.s", otvalid->debug_indent, 0 )); \ + FT_TRACE4(( "%s table\n", \ otvalid->debug_function_name[otvalid->nesting_level] )); \ FT_END_STMNT diff --git a/modules/freetype2/src/otvalid/otverror.h b/modules/freetype2/src/otvalid/otverror.h index e7c8db0d5..2fcf42e38 100644 --- a/modules/freetype2/src/otvalid/otverror.h +++ b/modules/freetype2/src/otvalid/otverror.h @@ -4,7 +4,7 @@ /* */ /* OpenType validation module error codes (specification only). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/otvalid/otvgdef.c b/modules/freetype2/src/otvalid/otvgdef.c index f19e300e5..08f317154 100644 --- a/modules/freetype2/src/otvalid/otvgdef.c +++ b/modules/freetype2/src/otvalid/otvgdef.c @@ -4,7 +4,7 @@ /* */ /* OpenType GDEF table validation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -68,7 +68,7 @@ OTV_LIMIT_CHECK( GlyphCount * 2 ); otvalid->nesting_level++; - func = otvalid->func[otvalid->nesting_level]; + func = otvalid->func[otvalid->nesting_level]; otvalid->extra1 = 0; for ( ; GlyphCount > 0; GlyphCount-- ) @@ -136,6 +136,40 @@ /*************************************************************************/ /*************************************************************************/ /***** *****/ + /***** MARK GLYPH SETS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + static void + otv_MarkGlyphSets_validate( FT_Bytes table, + OTV_Validator otvalid ) + { + FT_Bytes p = table; + FT_UInt MarkGlyphSetCount; + + + OTV_NAME_ENTER( "MarkGlyphSets" ); + + p += 2; /* skip Format */ + + OTV_LIMIT_CHECK( 2 ); + MarkGlyphSetCount = FT_NEXT_USHORT( p ); + + OTV_TRACE(( " (MarkGlyphSetCount = %d)\n", MarkGlyphSetCount )); + + OTV_LIMIT_CHECK( MarkGlyphSetCount * 4 ); /* CoverageOffsets */ + + for ( ; MarkGlyphSetCount > 0; MarkGlyphSetCount-- ) + otv_Coverage_validate( table + FT_NEXT_ULONG( p ), otvalid, -1 ); + + OTV_EXIT; + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ /***** GDEF TABLE *****/ /***** *****/ /*************************************************************************/ @@ -152,14 +186,18 @@ { OTV_ValidatorRec otvalidrec; OTV_Validator otvalid = &otvalidrec; - FT_Bytes p = table; + FT_Bytes p = table; FT_UInt table_size; - FT_Bool need_MarkAttachClassDef; + FT_UShort version; + FT_Bool need_MarkAttachClassDef = 1; OTV_OPTIONAL_TABLE( GlyphClassDef ); OTV_OPTIONAL_TABLE( AttachListOffset ); OTV_OPTIONAL_TABLE( LigCaretListOffset ); OTV_OPTIONAL_TABLE( MarkAttachClassDef ); + OTV_OPTIONAL_TABLE( MarkGlyphSetsDef ); + + OTV_OPTIONAL_TABLE32( itemVarStore ); otvalid->root = ftvalid; @@ -167,24 +205,49 @@ FT_TRACE3(( "validating GDEF table\n" )); OTV_INIT; - OTV_LIMIT_CHECK( 12 ); + OTV_LIMIT_CHECK( 4 ); - if ( FT_NEXT_ULONG( p ) != 0x10000UL ) /* Version */ + if ( FT_NEXT_USHORT( p ) != 1 ) /* majorVersion */ FT_INVALID_FORMAT; - /* MarkAttachClassDef has been added to the OpenType */ - /* specification without increasing GDEF's version, */ - /* so we use this ugly hack to find out whether the */ - /* table is needed actually. */ + version = FT_NEXT_USHORT( p ); /* minorVersion */ - need_MarkAttachClassDef = FT_BOOL( - otv_GSUBGPOS_have_MarkAttachmentType_flag( gsub ) || - otv_GSUBGPOS_have_MarkAttachmentType_flag( gpos ) ); + table_size = 10; + switch ( version ) + { + case 0: + /* MarkAttachClassDef has been added to the OpenType */ + /* specification without increasing GDEF's version, */ + /* so we use this ugly hack to find out whether the */ + /* table is needed actually. */ + + need_MarkAttachClassDef = FT_BOOL( + otv_GSUBGPOS_have_MarkAttachmentType_flag( gsub ) || + otv_GSUBGPOS_have_MarkAttachmentType_flag( gpos ) ); + + if ( need_MarkAttachClassDef ) + { + OTV_LIMIT_CHECK( 8 ); + table_size += 2; + } + else + OTV_LIMIT_CHECK( 6 ); /* OpenType < 1.2 */ - if ( need_MarkAttachClassDef ) - table_size = 12; /* OpenType >= 1.2 */ - else - table_size = 10; /* OpenType < 1.2 */ + break; + + case 2: + OTV_LIMIT_CHECK( 10 ); + table_size += 4; + break; + + case 3: + OTV_LIMIT_CHECK( 14 ); + table_size += 8; + break; + + default: + FT_INVALID_FORMAT; + } otvalid->glyph_count = glyph_count; @@ -217,6 +280,22 @@ otv_ClassDef_validate( table + MarkAttachClassDef, otvalid ); } + if ( version > 0 ) + { + OTV_OPTIONAL_OFFSET( MarkGlyphSetsDef ); + OTV_SIZE_CHECK( MarkGlyphSetsDef ); + if ( MarkGlyphSetsDef ) + otv_MarkGlyphSets_validate( table + MarkGlyphSetsDef, otvalid ); + } + + if ( version > 2 ) + { + OTV_OPTIONAL_OFFSET32( itemVarStore ); + OTV_SIZE_CHECK32( itemVarStore ); + if ( itemVarStore ) + OTV_TRACE(( " [omitting itemVarStore validation]\n" )); /* XXX */ + } + FT_TRACE4(( "\n" )); } diff --git a/modules/freetype2/src/otvalid/otvgpos.c b/modules/freetype2/src/otvalid/otvgpos.c index e904ea5d6..696b35cae 100644 --- a/modules/freetype2/src/otvalid/otvgpos.c +++ b/modules/freetype2/src/otvalid/otvgpos.c @@ -4,7 +4,7 @@ /* */ /* OpenType GPOS table validation (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -130,7 +130,7 @@ otv_MarkArray_validate( table + Array1, otvalid ); otvalid->nesting_level++; - func = otvalid->func[otvalid->nesting_level]; + func = otvalid->func[otvalid->nesting_level]; otvalid->extra1 = ClassCount; func( table + Array2, otvalid ); @@ -218,10 +218,6 @@ OTV_LIMIT_CHECK( 2 ); OTV_OPTIONAL_OFFSET( device ); - /* XXX: this value is usually too small, especially if the current */ - /* ValueRecord is part of an array -- getting the correct table */ - /* size is probably not worth the trouble */ - table_size = p - otvalid->extra3; OTV_SIZE_CHECK( device ); @@ -271,7 +267,7 @@ case 3: { - FT_UInt table_size; + FT_UInt table_size; OTV_OPTIONAL_TABLE( XDeviceTable ); OTV_OPTIONAL_TABLE( YDeviceTable ); @@ -426,6 +422,8 @@ /*************************************************************************/ /*************************************************************************/ + /* sets otvalid->extra3 (pointer to base table) */ + static void otv_PairSet_validate( FT_Bytes table, FT_UInt format1, @@ -438,6 +436,8 @@ OTV_NAME_ENTER( "PairSet" ); + otvalid->extra3 = table; + OTV_LIMIT_CHECK( 2 ); PairValueCount = FT_NEXT_USHORT( p ); @@ -483,8 +483,6 @@ OTV_TRACE(( " (format %d)\n", PosFormat )); - otvalid->extra3 = table; - switch ( PosFormat ) { case 1: /* PairPosFormat1 */ @@ -537,7 +535,9 @@ otv_ClassDef_validate( table + ClassDef2, otvalid ); OTV_LIMIT_CHECK( ClassCount1 * ClassCount2 * - ( len_value1 + len_value2 ) ); + ( len_value1 + len_value2 ) ); + + otvalid->extra3 = table; /* Class1Record */ for ( ; ClassCount1 > 0; ClassCount1-- ) @@ -985,20 +985,42 @@ { OTV_ValidatorRec validrec; OTV_Validator otvalid = &validrec; - FT_Bytes p = table; + FT_Bytes p = table; + FT_UInt table_size; + FT_UShort version; FT_UInt ScriptList, FeatureList, LookupList; + OTV_OPTIONAL_TABLE32( featureVariations ); + otvalid->root = ftvalid; FT_TRACE3(( "validating GPOS table\n" )); OTV_INIT; - OTV_LIMIT_CHECK( 10 ); + OTV_LIMIT_CHECK( 4 ); - if ( FT_NEXT_ULONG( p ) != 0x10000UL ) /* Version */ + if ( FT_NEXT_USHORT( p ) != 1 ) /* majorVersion */ FT_INVALID_FORMAT; + version = FT_NEXT_USHORT( p ); /* minorVersion */ + + table_size = 10; + switch ( version ) + { + case 0: + OTV_LIMIT_CHECK( 6 ); + break; + + case 1: + OTV_LIMIT_CHECK( 10 ); + table_size += 4; + break; + + default: + FT_INVALID_FORMAT; + } + ScriptList = FT_NEXT_USHORT( p ); FeatureList = FT_NEXT_USHORT( p ); LookupList = FT_NEXT_USHORT( p ); @@ -1014,6 +1036,14 @@ otv_ScriptList_validate( table + ScriptList, table + FeatureList, otvalid ); + if ( version > 0 ) + { + OTV_OPTIONAL_OFFSET32( featureVariations ); + OTV_SIZE_CHECK32( featureVariations ); + if ( featureVariations ) + OTV_TRACE(( " [omitting featureVariations validation]\n" )); /* XXX */ + } + FT_TRACE4(( "\n" )); } diff --git a/modules/freetype2/src/otvalid/otvgpos.h b/modules/freetype2/src/otvalid/otvgpos.h index 2c09e64f9..95f9ac3ee 100644 --- a/modules/freetype2/src/otvalid/otvgpos.h +++ b/modules/freetype2/src/otvalid/otvgpos.h @@ -4,7 +4,7 @@ /* */ /* OpenType GPOS table validator (specification). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/otvalid/otvgsub.c b/modules/freetype2/src/otvalid/otvgsub.c index c2b28569f..d35ea67f3 100644 --- a/modules/freetype2/src/otvalid/otvgsub.c +++ b/modules/freetype2/src/otvalid/otvgsub.c @@ -4,7 +4,7 @@ /* */ /* OpenType GSUB table validation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -552,18 +552,40 @@ OTV_ValidatorRec otvalidrec; OTV_Validator otvalid = &otvalidrec; FT_Bytes p = table; + FT_UInt table_size; + FT_UShort version; FT_UInt ScriptList, FeatureList, LookupList; + OTV_OPTIONAL_TABLE32( featureVariations ); + otvalid->root = ftvalid; FT_TRACE3(( "validating GSUB table\n" )); OTV_INIT; - OTV_LIMIT_CHECK( 10 ); + OTV_LIMIT_CHECK( 4 ); + + if ( FT_NEXT_USHORT( p ) != 1 ) /* majorVersion */ + FT_INVALID_FORMAT; + + version = FT_NEXT_USHORT( p ); /* minorVersion */ + + table_size = 10; + switch ( version ) + { + case 0: + OTV_LIMIT_CHECK( 6 ); + break; + + case 1: + OTV_LIMIT_CHECK( 10 ); + table_size += 4; + break; - if ( FT_NEXT_ULONG( p ) != 0x10000UL ) /* Version */ + default: FT_INVALID_FORMAT; + } ScriptList = FT_NEXT_USHORT( p ); FeatureList = FT_NEXT_USHORT( p ); @@ -580,6 +602,14 @@ otv_ScriptList_validate( table + ScriptList, table + FeatureList, otvalid ); + if ( version > 0 ) + { + OTV_OPTIONAL_OFFSET32( featureVariations ); + OTV_SIZE_CHECK32( featureVariations ); + if ( featureVariations ) + OTV_TRACE(( " [omitting featureVariations validation]\n" )); /* XXX */ + } + FT_TRACE4(( "\n" )); } diff --git a/modules/freetype2/src/otvalid/otvjstf.c b/modules/freetype2/src/otvalid/otvjstf.c index e19c1c121..94d4af90f 100644 --- a/modules/freetype2/src/otvalid/otvjstf.c +++ b/modules/freetype2/src/otvalid/otvjstf.c @@ -4,7 +4,7 @@ /* */ /* OpenType JSTF table validation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/otvalid/otvmath.c b/modules/freetype2/src/otvalid/otvmath.c index 47e2f87c1..b9800f60a 100644 --- a/modules/freetype2/src/otvalid/otvmath.c +++ b/modules/freetype2/src/otvalid/otvmath.c @@ -4,7 +4,7 @@ /* */ /* OpenType MATH table validation (body). */ /* */ -/* Copyright 2007-2016 by */ +/* Copyright 2007-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* Written by George Williams. */ diff --git a/modules/freetype2/src/otvalid/otvmod.c b/modules/freetype2/src/otvalid/otvmod.c index aed5e9c6f..89ee449d1 100644 --- a/modules/freetype2/src/otvalid/otvmod.c +++ b/modules/freetype2/src/otvalid/otvmod.c @@ -4,7 +4,7 @@ /* */ /* FreeType's OpenType validation module implementation (body). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/otvalid/otvmod.h b/modules/freetype2/src/otvalid/otvmod.h index e464030ab..6917bccee 100644 --- a/modules/freetype2/src/otvalid/otvmod.h +++ b/modules/freetype2/src/otvalid/otvmod.h @@ -5,7 +5,7 @@ /* FreeType's OpenType validation module implementation */ /* (specification). */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/otvalid/rules.mk b/modules/freetype2/src/otvalid/rules.mk index 077447fcb..d4fc72374 100644 --- a/modules/freetype2/src/otvalid/rules.mk +++ b/modules/freetype2/src/otvalid/rules.mk @@ -3,7 +3,7 @@ # -# Copyright 2004-2016 by +# Copyright 2004-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/pcf/Jamfile b/modules/freetype2/src/pcf/Jamfile index 9ebe6a2cb..7b92b12dd 100644 --- a/modules/freetype2/src/pcf/Jamfile +++ b/modules/freetype2/src/pcf/Jamfile @@ -1,6 +1,6 @@ # FreeType 2 src/pcf Jamfile # -# Copyright 2001-2016 by +# Copyright 2001-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/pcf/README b/modules/freetype2/src/pcf/README index 10eff15fb..09ea970ed 100644 --- a/modules/freetype2/src/pcf/README +++ b/modules/freetype2/src/pcf/README @@ -41,8 +41,8 @@ value given as argument into the corresponding glyph number. Known problems ************** -- dealing explicitly with encodings breaks the uniformity of freetype2 - api. +- dealing explicitly with encodings breaks the uniformity of FreeType 2 + API. - except for encodings properties, client applications have no visibility of the PCF_Face object. This means that applications diff --git a/modules/freetype2/src/pcf/pcf.c b/modules/freetype2/src/pcf/pcf.c index 11d5b7b2a..8ffd6e280 100644 --- a/modules/freetype2/src/pcf/pcf.c +++ b/modules/freetype2/src/pcf/pcf.c @@ -26,11 +26,11 @@ THE SOFTWARE. #define FT_MAKE_OPTION_SINGLE_OBJECT - - #include <ft2build.h> -#include "pcfutil.c" -#include "pcfread.c" + #include "pcfdrivr.c" +#include "pcfread.c" +#include "pcfutil.c" + /* END */ diff --git a/modules/freetype2/src/pcf/pcf.h b/modules/freetype2/src/pcf/pcf.h index c726e5ec6..f0390cb1e 100644 --- a/modules/freetype2/src/pcf/pcf.h +++ b/modules/freetype2/src/pcf/pcf.h @@ -163,6 +163,15 @@ FT_BEGIN_HEADER } PCF_FaceRec, *PCF_Face; + typedef struct PCF_DriverRec_ + { + FT_DriverRec root; + + FT_Bool no_long_family_names; + + } PCF_DriverRec, *PCF_Driver; + + /* macros for pcf font format */ #define LSBFirst 0 diff --git a/modules/freetype2/src/pcf/pcfdrivr.c b/modules/freetype2/src/pcf/pcfdrivr.c index d60cc3ee5..0119d9485 100644 --- a/modules/freetype2/src/pcf/pcfdrivr.c +++ b/modules/freetype2/src/pcf/pcfdrivr.c @@ -49,6 +49,8 @@ THE SOFTWARE. #include FT_SERVICE_BDF_H #include FT_SERVICE_FONT_FORMAT_H +#include FT_SERVICE_PROPERTIES_H +#include FT_DRIVER_H /*************************************************************************/ @@ -286,6 +288,7 @@ THE SOFTWARE. /* this didn't work, try gzip support! */ + FT_TRACE2(( " ... try gzip stream\n" )); error2 = FT_Stream_OpenGzip( &face->comp_stream, stream ); if ( FT_ERR_EQ( error2, Unimplemented_Feature ) ) goto Fail; @@ -301,6 +304,7 @@ THE SOFTWARE. /* this didn't work, try LZW support! */ + FT_TRACE2(( " ... try LZW stream\n" )); error3 = FT_Stream_OpenLZW( &face->comp_stream, stream ); if ( FT_ERR_EQ( error3, Unimplemented_Feature ) ) goto Fail; @@ -316,6 +320,7 @@ THE SOFTWARE. /* this didn't work, try Bzip2 support! */ + FT_TRACE2(( " ... try Bzip2 stream\n" )); error4 = FT_Stream_OpenBzip2( &face->comp_stream, stream ); if ( FT_ERR_EQ( error4, Unimplemented_Feature ) ) goto Fail; @@ -382,7 +387,11 @@ THE SOFTWARE. if ( !ft_strcmp( s, "10646" ) || ( !ft_strcmp( s, "8859" ) && !ft_strcmp( face->charset_encoding, "1" ) ) ) - unicode_charmap = 1; + unicode_charmap = 1; + /* another name for ASCII */ + else if ( !ft_strcmp( s, "646.1991" ) && + !ft_strcmp( face->charset_encoding, "IRV" ) ) + unicode_charmap = 1; } } @@ -404,12 +413,6 @@ THE SOFTWARE. } error = FT_CMap_New( &pcf_cmap_class, NULL, &charmap, NULL ); - -#if 0 - /* Select default charmap */ - if ( pcfface->num_charmaps ) - pcfface->charmap = pcfface->charmaps[0]; -#endif } } @@ -521,11 +524,6 @@ THE SOFTWARE. bitmap->num_grays = 1; bitmap->pixel_mode = FT_PIXEL_MODE_MONO; - FT_TRACE6(( "BIT_ORDER %d ; BYTE_ORDER %d ; GLYPH_PAD %d\n", - PCF_BIT_ORDER( face->bitmapsFormat ), - PCF_BYTE_ORDER( face->bitmapsFormat ), - PCF_GLYPH_PAD( face->bitmapsFormat ) )); - switch ( PCF_GLYPH_PAD( face->bitmapsFormat ) ) { case 1: @@ -627,19 +625,23 @@ THE SOFTWARE. } else { - if ( prop->value.l > 0x7FFFFFFFL || prop->value.l < ( -1 - 0x7FFFFFFFL ) ) + if ( prop->value.l > 0x7FFFFFFFL || + prop->value.l < ( -1 - 0x7FFFFFFFL ) ) { - FT_TRACE1(( "pcf_get_bdf_property: " )); - FT_TRACE1(( "too large integer 0x%x is truncated\n" )); + FT_TRACE1(( "pcf_get_bdf_property:" )); + FT_TRACE1(( " too large integer 0x%x is truncated\n" )); } - /* Apparently, the PCF driver loads all properties as signed integers! - * This really doesn't seem to be a problem, because this is - * sufficient for any meaningful values. + + /* + * The PCF driver loads all properties as signed integers. + * This really doesn't seem to be a problem, because this is + * sufficient for any meaningful values. */ aproperty->type = BDF_PROPERTY_TYPE_INTEGER; aproperty->u.integer = (FT_Int32)prop->value.l; } - return 0; + + return FT_Err_Ok; } return FT_THROW( Invalid_Argument ); @@ -654,7 +656,7 @@ THE SOFTWARE. *acharset_encoding = face->charset_encoding; *acharset_registry = face->charset_registry; - return 0; + return FT_Err_Ok; } @@ -665,6 +667,116 @@ THE SOFTWARE. }; + /* + * PROPERTY SERVICE + * + */ + static FT_Error + pcf_property_set( FT_Module module, /* PCF_Driver */ + const char* property_name, + const void* value, + FT_Bool value_is_string ) + { +#ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES + + FT_Error error = FT_Err_Ok; + PCF_Driver driver = (PCF_Driver)module; + +#ifndef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES + FT_UNUSED( value_is_string ); +#endif + + + if ( !ft_strcmp( property_name, "no-long-family-names" ) ) + { +#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES + if ( value_is_string ) + { + const char* s = (const char*)value; + long lfn = ft_strtol( s, NULL, 10 ); + + + if ( lfn == 0 ) + driver->no_long_family_names = 0; + else if ( lfn == 1 ) + driver->no_long_family_names = 1; + else + return FT_THROW( Invalid_Argument ); + } + else +#endif + { + FT_Bool* no_long_family_names = (FT_Bool*)value; + + + driver->no_long_family_names = *no_long_family_names; + } + + return error; + } + +#else /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ + + FT_UNUSED( module ); + FT_UNUSED( value ); + FT_UNUSED( value_is_string ); +#ifndef FT_DEBUG_LEVEL_TRACE + FT_UNUSED( property_name ); +#endif + +#endif /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ + + FT_TRACE0(( "pcf_property_set: missing property `%s'\n", + property_name )); + return FT_THROW( Missing_Property ); + } + + + static FT_Error + pcf_property_get( FT_Module module, /* PCF_Driver */ + const char* property_name, + const void* value ) + { +#ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES + + FT_Error error = FT_Err_Ok; + PCF_Driver driver = (PCF_Driver)module; + + + if ( !ft_strcmp( property_name, "no-long-family-names" ) ) + { + FT_Bool no_long_family_names = driver->no_long_family_names; + FT_Bool* val = (FT_Bool*)value; + + + *val = no_long_family_names; + + return error; + } + +#else /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ + + FT_UNUSED( module ); + FT_UNUSED( value ); +#ifndef FT_DEBUG_LEVEL_TRACE + FT_UNUSED( property_name ); +#endif + +#endif /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ + + FT_TRACE0(( "pcf_property_get: missing property `%s'\n", + property_name )); + return FT_THROW( Missing_Property ); + } + + + FT_DEFINE_SERVICE_PROPERTIESREC( + pcf_service_properties, + + (FT_Properties_SetFunc)pcf_property_set, /* set_property */ + (FT_Properties_GetFunc)pcf_property_get ) /* get_property */ + + /* * * SERVICE LIST @@ -675,6 +787,7 @@ THE SOFTWARE. { { FT_SERVICE_ID_BDF, &pcf_service_bdf }, { FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_PCF }, + { FT_SERVICE_ID_PROPERTIES, &pcf_service_properties }, { NULL, NULL } }; @@ -689,22 +802,45 @@ THE SOFTWARE. } + FT_CALLBACK_DEF( FT_Error ) + pcf_driver_init( FT_Module module ) /* PCF_Driver */ + { +#ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES + PCF_Driver driver = (PCF_Driver)module; + + + driver->no_long_family_names = 0; +#else + FT_UNUSED( module ); +#endif + + return FT_Err_Ok; + } + + + FT_CALLBACK_DEF( void ) + pcf_driver_done( FT_Module module ) /* PCF_Driver */ + { + FT_UNUSED( module ); + } + + FT_CALLBACK_TABLE_DEF const FT_Driver_ClassRec pcf_driver_class = { { FT_MODULE_FONT_DRIVER | FT_MODULE_DRIVER_NO_OUTLINES, - sizeof ( FT_DriverRec ), + sizeof ( PCF_DriverRec ), "pcf", 0x10000L, 0x20000L, - NULL, /* module-specific interface */ + NULL, /* module-specific interface */ - NULL, /* FT_Module_Constructor module_init */ - NULL, /* FT_Module_Destructor module_done */ + pcf_driver_init, /* FT_Module_Constructor module_init */ + pcf_driver_done, /* FT_Module_Destructor module_done */ pcf_driver_requester /* FT_Module_Requester get_interface */ }, diff --git a/modules/freetype2/src/pcf/pcfread.c b/modules/freetype2/src/pcf/pcfread.c index 95ee57018..537da0dc7 100644 --- a/modules/freetype2/src/pcf/pcfread.c +++ b/modules/freetype2/src/pcf/pcfread.c @@ -50,8 +50,15 @@ THE SOFTWARE. #ifdef FT_DEBUG_LEVEL_TRACE static const char* const tableNames[] = { - "prop", "accl", "mtrcs", "bmps", "imtrcs", - "enc", "swidth", "names", "accel" + "properties", + "accelerators", + "metrics", + "bitmaps", + "ink metrics", + "encodings", + "swidths", + "glyph names", + "BDF accelerators" }; #endif @@ -109,22 +116,20 @@ THE SOFTWARE. if ( stream->size < 16 ) return FT_THROW( Invalid_File_Format ); - /* We need 16 bytes per TOC entry. Additionally, as a */ - /* heuristic protection against gzip bombs (i.e., very */ - /* small input files that expand to insanely large */ - /* files), we limit the number of TOC entries to 1024. */ - if ( toc->count > stream->size >> 4 || - toc->count > 1024 ) + /* we need 16 bytes per TOC entry, */ + /* and there can be most 9 tables */ + if ( toc->count > ( stream->size >> 4 ) || + toc->count > 9 ) { FT_TRACE0(( "pcf_read_TOC: adjusting number of tables" " (from %d to %d)\n", toc->count, - FT_MIN( stream->size >> 4, 1024 ) )); - toc->count = FT_MIN( stream->size >> 4, 1024 ); + FT_MIN( stream->size >> 4, 9 ) )); + toc->count = FT_MIN( stream->size >> 4, 9 ); } if ( FT_NEW_ARRAY( face->toc.tables, toc->count ) ) - return FT_THROW( Out_Of_Memory ); + return error; tables = face->toc.tables; for ( n = 0; n < toc->count; n++ ) @@ -237,8 +242,8 @@ THE SOFTWARE. if ( tables[i].type == (FT_UInt)( 1 << j ) ) name = tableNames[j]; - FT_TRACE4(( " %d: type=%s, format=0x%X, " - "size=%ld (0x%lX), offset=%ld (0x%lX)\n", + FT_TRACE4(( " %d: type=%s, format=0x%X," + " size=%ld (0x%lX), offset=%ld (0x%lX)\n", i, name, tables[i].format, tables[i].size, tables[i].size, @@ -348,6 +353,17 @@ THE SOFTWARE. metric->attributes = 0; } + FT_TRACE5(( " width=%d," + " lsb=%d, rsb=%d," + " ascent=%d, descent=%d," + " attributes=%d\n", + metric->characterWidth, + metric->leftSideBearing, + metric->rightSideBearing, + metric->ascent, + metric->descent, + metric->attributes )); + Exit: return error; } @@ -466,7 +482,7 @@ THE SOFTWARE. { PCF_ParseProperty props = NULL; PCF_Property properties = NULL; - FT_ULong nprops, i; + FT_ULong nprops, orig_nprops, i; FT_ULong format, size; FT_Error error; FT_Memory memory = FT_FACE( face )->memory; @@ -486,32 +502,43 @@ THE SOFTWARE. if ( FT_READ_ULONG_LE( format ) ) goto Bail; - FT_TRACE4(( "pcf_get_properties:\n" )); - - FT_TRACE4(( " format = %ld\n", format )); + FT_TRACE4(( "pcf_get_properties:\n" + " format: 0x%lX (%s)\n", + format, + PCF_BYTE_ORDER( format ) == MSBFirst ? "MSB" : "LSB" )); if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) goto Bail; if ( PCF_BYTE_ORDER( format ) == MSBFirst ) - (void)FT_READ_ULONG( nprops ); + (void)FT_READ_ULONG( orig_nprops ); else - (void)FT_READ_ULONG_LE( nprops ); + (void)FT_READ_ULONG_LE( orig_nprops ); if ( error ) goto Bail; - FT_TRACE4(( " nprop = %d (truncate %d props)\n", - (int)nprops, nprops - (FT_ULong)(int)nprops )); - - nprops = (FT_ULong)(int)nprops; + FT_TRACE4(( " number of properties: %ld\n", orig_nprops )); /* rough estimate */ - if ( nprops > size / PCF_PROPERTY_SIZE ) + if ( orig_nprops > size / PCF_PROPERTY_SIZE ) { error = FT_THROW( Invalid_Table ); goto Bail; } + /* as a heuristic limit to avoid excessive allocation in */ + /* gzip bombs (i.e., very small, invalid input data that */ + /* pretends to expand to an insanely large file) we only */ + /* load the first 256 properties */ + if ( orig_nprops > 256 ) + { + FT_TRACE0(( "pcf_get_properties:" + " only loading first 256 properties\n" )); + nprops = 256; + } + else + nprops = orig_nprops; + face->nprops = (int)nprops; if ( FT_NEW_ARRAY( props, nprops ) ) @@ -531,14 +558,23 @@ THE SOFTWARE. } } + /* this skip will only work if we really have an extremely large */ + /* number of properties; it will fail for fake data, avoiding an */ + /* unnecessarily large allocation later on */ + if ( FT_STREAM_SKIP( ( orig_nprops - nprops ) * PCF_PROPERTY_SIZE ) ) + { + error = FT_THROW( Invalid_Stream_Skip ); + goto Bail; + } + /* pad the property array */ /* */ /* clever here - nprops is the same as the number of odd-units read, */ /* as only isStringProp are odd length (Keith Packard) */ /* */ - if ( nprops & 3 ) + if ( orig_nprops & 3 ) { - i = 4 - ( nprops & 3 ); + i = 4 - ( orig_nprops & 3 ); if ( FT_STREAM_SKIP( i ) ) { error = FT_THROW( Invalid_Stream_Skip ); @@ -553,15 +589,24 @@ THE SOFTWARE. if ( error ) goto Bail; - FT_TRACE4(( " string_size = %ld\n", string_size )); + FT_TRACE4(( " string size: %ld\n", string_size )); /* rough estimate */ - if ( string_size > size - nprops * PCF_PROPERTY_SIZE ) + if ( string_size > size - orig_nprops * PCF_PROPERTY_SIZE ) { error = FT_THROW( Invalid_Table ); goto Bail; } + /* the strings in the `strings' array are PostScript strings, */ + /* which can have a maximum length of 65536 characters each */ + if ( string_size > 16777472 ) /* 256 * (65536 + 1) */ + { + FT_TRACE0(( "pcf_get_properties:" + " loading only 16777472 bytes of strings array\n" )); + string_size = 16777472; + } + /* allocate one more byte so that we have a final null byte */ if ( FT_NEW_ARRAY( strings, string_size + 1 ) ) goto Bail; @@ -575,6 +620,7 @@ THE SOFTWARE. face->properties = properties; + FT_TRACE4(( "\n" )); for ( i = 0; i < nprops; i++ ) { FT_Long name_offset = props[i].name; @@ -637,7 +683,7 @@ THE SOFTWARE. FT_Memory memory = FT_FACE( face )->memory; FT_ULong format, size; PCF_Metric metrics = NULL; - FT_ULong nmetrics, i; + FT_ULong nmetrics, orig_nmetrics, i; error = pcf_seek_to_table_type( stream, @@ -652,6 +698,13 @@ THE SOFTWARE. if ( FT_READ_ULONG_LE( format ) ) goto Bail; + FT_TRACE4(( "pcf_get_metrics:\n" + " format: 0x%lX (%s, %s)\n", + format, + PCF_BYTE_ORDER( format ) == MSBFirst ? "MSB" : "LSB", + PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) ? + "compressed" : "uncompressed" )); + if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) && !PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) ) return FT_THROW( Invalid_File_Format ); @@ -659,61 +712,70 @@ THE SOFTWARE. if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) { if ( PCF_BYTE_ORDER( format ) == MSBFirst ) - (void)FT_READ_ULONG( nmetrics ); + (void)FT_READ_ULONG( orig_nmetrics ); else - (void)FT_READ_ULONG_LE( nmetrics ); + (void)FT_READ_ULONG_LE( orig_nmetrics ); } else { if ( PCF_BYTE_ORDER( format ) == MSBFirst ) - (void)FT_READ_USHORT( nmetrics ); + (void)FT_READ_USHORT( orig_nmetrics ); else - (void)FT_READ_USHORT_LE( nmetrics ); + (void)FT_READ_USHORT_LE( orig_nmetrics ); } if ( error ) return FT_THROW( Invalid_File_Format ); - face->nmetrics = nmetrics; - - if ( !nmetrics ) - return FT_THROW( Invalid_Table ); - - FT_TRACE4(( "pcf_get_metrics:\n" )); - - FT_TRACE4(( " number of metrics: %d\n", nmetrics )); + FT_TRACE4(( " number of metrics: %ld\n", orig_nmetrics )); /* rough estimate */ if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) { - if ( nmetrics > size / PCF_METRIC_SIZE ) + if ( orig_nmetrics > size / PCF_METRIC_SIZE ) return FT_THROW( Invalid_Table ); } else { - if ( nmetrics > size / PCF_COMPRESSED_METRIC_SIZE ) + if ( orig_nmetrics > size / PCF_COMPRESSED_METRIC_SIZE ) return FT_THROW( Invalid_Table ); } + if ( !orig_nmetrics ) + return FT_THROW( Invalid_Table ); + + /* PCF is a format from ancient times; Unicode was in its */ + /* infancy, and widely used two-byte character sets for CJK */ + /* scripts (Big 5, GB 2312, JIS X 0208, etc.) did have at most */ + /* 15000 characters. Even the more exotic CNS 11643 and CCCII */ + /* standards, which were essentially three-byte character sets, */ + /* provided less then 65536 assigned characters. */ + /* */ + /* While technically possible to have a larger number of glyphs */ + /* in PCF files, we thus limit the number to 65536. */ + if ( orig_nmetrics > 65536 ) + { + FT_TRACE0(( "pcf_get_metrics:" + " only loading first 65536 metrics\n" )); + nmetrics = 65536; + } + else + nmetrics = orig_nmetrics; + + face->nmetrics = nmetrics; + if ( FT_NEW_ARRAY( face->metrics, nmetrics ) ) - return FT_THROW( Out_Of_Memory ); + return error; metrics = face->metrics; + + FT_TRACE4(( "\n" )); for ( i = 0; i < nmetrics; i++, metrics++ ) { + FT_TRACE5(( " idx %ld:", i )); error = pcf_get_metric( stream, format, metrics ); metrics->bits = 0; - FT_TRACE5(( " idx %d: width=%d, " - "lsb=%d, rsb=%d, ascent=%d, descent=%d, swidth=%d\n", - i, - metrics->characterWidth, - metrics->leftSideBearing, - metrics->rightSideBearing, - metrics->ascent, - metrics->descent, - metrics->attributes )); - if ( error ) break; @@ -721,7 +783,7 @@ THE SOFTWARE. /* compute a glyph's bitmap dimensions, thus setting them to zero in */ /* case of an error disables this particular glyph only */ if ( metrics->rightSideBearing < metrics->leftSideBearing || - metrics->ascent + metrics->descent < 0 ) + metrics->ascent < -metrics->descent ) { metrics->characterWidth = 0; metrics->leftSideBearing = 0; @@ -751,7 +813,7 @@ THE SOFTWARE. FT_Long* offsets = NULL; FT_Long bitmapSizes[GLYPHPADOPTIONS]; FT_ULong format, size; - FT_ULong nbitmaps, i, sizebitmaps = 0; + FT_ULong nbitmaps, orig_nbitmaps, i, sizebitmaps = 0; error = pcf_seek_to_table_type( stream, @@ -769,18 +831,42 @@ THE SOFTWARE. format = FT_GET_ULONG_LE(); if ( PCF_BYTE_ORDER( format ) == MSBFirst ) - nbitmaps = FT_GET_ULONG(); + orig_nbitmaps = FT_GET_ULONG(); else - nbitmaps = FT_GET_ULONG_LE(); + orig_nbitmaps = FT_GET_ULONG_LE(); FT_Stream_ExitFrame( stream ); + FT_TRACE4(( "pcf_get_bitmaps:\n" + " format: 0x%lX\n" + " (%s, %s,\n" + " padding=%d bit%s, scanning=%d bit%s)\n", + format, + PCF_BYTE_ORDER( format ) == MSBFirst + ? "most significant byte first" + : "least significant byte first", + PCF_BIT_ORDER( format ) == MSBFirst + ? "most significant bit first" + : "least significant bit first", + 8 << PCF_GLYPH_PAD_INDEX( format ), + ( 8 << PCF_GLYPH_PAD_INDEX( format ) ) == 1 ? "" : "s", + 8 << PCF_SCAN_UNIT_INDEX( format ), + ( 8 << PCF_SCAN_UNIT_INDEX( format ) ) == 1 ? "" : "s" )); + if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) return FT_THROW( Invalid_File_Format ); - FT_TRACE4(( "pcf_get_bitmaps:\n" )); + FT_TRACE4(( " number of bitmaps: %ld\n", orig_nbitmaps )); - FT_TRACE4(( " number of bitmaps: %d\n", nbitmaps )); + /* see comment in `pcf_get_metrics' */ + if ( orig_nbitmaps > 65536 ) + { + FT_TRACE0(( "pcf_get_bitmaps:" + " only loading first 65536 bitmaps\n" )); + nbitmaps = 65536; + } + else + nbitmaps = orig_nbitmaps; if ( nbitmaps != face->nmetrics ) return FT_THROW( Invalid_File_Format ); @@ -788,6 +874,7 @@ THE SOFTWARE. if ( FT_NEW_ARRAY( offsets, nbitmaps ) ) return error; + FT_TRACE5(( "\n" )); for ( i = 0; i < nbitmaps; i++ ) { if ( PCF_BYTE_ORDER( format ) == MSBFirst ) @@ -795,7 +882,7 @@ THE SOFTWARE. else (void)FT_READ_LONG_LE( offsets[i] ); - FT_TRACE5(( " bitmap %d: offset %ld (0x%lX)\n", + FT_TRACE5(( " bitmap %ld: offset %ld (0x%lX)\n", i, offsets[i], offsets[i] )); } if ( error ) @@ -812,17 +899,19 @@ THE SOFTWARE. sizebitmaps = (FT_ULong)bitmapSizes[PCF_GLYPH_PAD_INDEX( format )]; - FT_TRACE4(( " padding %d implies a size of %ld\n", - i, bitmapSizes[i] )); + FT_TRACE4(( " %ld-bit padding implies a size of %ld\n", + 8 << i, bitmapSizes[i] )); } - FT_TRACE4(( " %d bitmaps, padding index %ld\n", + FT_TRACE4(( " %ld bitmaps, using %ld-bit padding\n", nbitmaps, - PCF_GLYPH_PAD_INDEX( format ) )); - FT_TRACE4(( " bitmap size = %d\n", sizebitmaps )); + 8 << PCF_GLYPH_PAD_INDEX( format ) )); + FT_TRACE4(( " bitmap size: %ld\n", sizebitmaps )); FT_UNUSED( sizebitmaps ); /* only used for debugging */ + /* right now, we only check the bitmap offsets; */ + /* actual bitmaps are only loaded on demand */ for ( i = 0; i < nbitmaps; i++ ) { /* rough estimate */ @@ -830,7 +919,7 @@ THE SOFTWARE. ( (FT_ULong)offsets[i] > size ) ) { FT_TRACE0(( "pcf_get_bitmaps:" - " invalid offset to bitmap data of glyph %d\n", i )); + " invalid offset to bitmap data of glyph %ld\n", i )); } else face->metrics[i].bits = stream->pos + (FT_ULong)offsets[i]; @@ -894,10 +983,20 @@ THE SOFTWARE. FT_Stream_ExitFrame( stream ); + FT_TRACE4(( "pcf_get_encodings:\n" + " format: 0x%lX (%s)\n", + format, + PCF_BYTE_ORDER( format ) == MSBFirst ? "MSB" : "LSB" )); + if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) return FT_THROW( Invalid_File_Format ); - /* sanity checks */ + FT_TRACE4(( " firstCol 0x%X, lastCol 0x%X\n" + " firstRow 0x%X, lastRow 0x%X\n", + firstCol, lastCol, + firstRow, lastRow )); + + /* sanity checks; we limit numbers of rows and columns to 256 */ if ( firstCol < 0 || firstCol > lastCol || lastCol > 0xFF || @@ -906,21 +1005,18 @@ THE SOFTWARE. lastRow > 0xFF ) return FT_THROW( Invalid_Table ); - FT_TRACE4(( "pdf_get_encodings:\n" )); - - FT_TRACE4(( " firstCol %d, lastCol %d, firstRow %d, lastRow %d\n", - firstCol, lastCol, firstRow, lastRow )); - nencoding = (FT_ULong)( lastCol - firstCol + 1 ) * (FT_ULong)( lastRow - firstRow + 1 ); if ( FT_NEW_ARRAY( encoding, nencoding ) ) - return FT_THROW( Out_Of_Memory ); + return error; error = FT_Stream_EnterFrame( stream, 2 * nencoding ); if ( error ) goto Bail; + FT_TRACE5(( "\n" )); + k = 0; for ( i = firstRow; i <= lastRow; i++ ) { @@ -1029,6 +1125,15 @@ THE SOFTWARE. if ( FT_READ_ULONG_LE( format ) ) goto Bail; + FT_TRACE4(( "pcf_get_accel%s:\n" + " format: 0x%lX (%s, %s)\n", + type == PCF_BDF_ACCELERATORS ? " (getting BDF accelerators)" + : "", + format, + PCF_BYTE_ORDER( format ) == MSBFirst ? "MSB" : "LSB", + PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) ? + "accelerated" : "not accelerated" )); + if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) && !PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) ) goto Bail; @@ -1044,12 +1149,43 @@ THE SOFTWARE. goto Bail; } + FT_TRACE5(( " noOverlap=%s, constantMetrics=%s," + " terminalFont=%s, constantWidth=%s\n" + " inkInside=%s, inkMetrics=%s, drawDirection=%s\n" + " fontAscent=%ld, fontDescent=%ld, maxOverlap=%ld\n", + accel->noOverlap ? "yes" : "no", + accel->constantMetrics ? "yes" : "no", + accel->terminalFont ? "yes" : "no", + accel->constantWidth ? "yes" : "no", + accel->inkInside ? "yes" : "no", + accel->inkMetrics ? "yes" : "no", + accel->drawDirection ? "RTL" : "LTR", + accel->fontAscent, + accel->fontDescent, + accel->maxOverlap )); + + /* sanity checks */ + if ( FT_ABS( accel->fontAscent ) > 0x7FFF ) + { + accel->fontAscent = accel->fontAscent < 0 ? -0x7FFF : 0x7FFF; + FT_TRACE0(( "pfc_get_accel: clamping font ascent to value %d\n", + accel->fontAscent )); + } + if ( FT_ABS( accel->fontDescent ) > 0x7FFF ) + { + accel->fontDescent = accel->fontDescent < 0 ? -0x7FFF : 0x7FFF; + FT_TRACE0(( "pfc_get_accel: clamping font descent to value %d\n", + accel->fontDescent )); + } + + FT_TRACE5(( " minbounds:" )); error = pcf_get_metric( stream, format & ( ~PCF_FORMAT_MASK ), &(accel->minbounds) ); if ( error ) goto Bail; + FT_TRACE5(( " maxbounds:" )); error = pcf_get_metric( stream, format & ( ~PCF_FORMAT_MASK ), &(accel->maxbounds) ); @@ -1058,12 +1194,14 @@ THE SOFTWARE. if ( PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) ) { + FT_TRACE5(( " ink minbounds:" )); error = pcf_get_metric( stream, format & ( ~PCF_FORMAT_MASK ), &(accel->ink_minbounds) ); if ( error ) goto Bail; + FT_TRACE5(( " ink maxbounds:" )); error = pcf_get_metric( stream, format & ( ~PCF_FORMAT_MASK ), &(accel->ink_maxbounds) ); @@ -1072,7 +1210,7 @@ THE SOFTWARE. } else { - accel->ink_minbounds = accel->minbounds; /* I'm not sure about this */ + accel->ink_minbounds = accel->minbounds; accel->ink_maxbounds = accel->maxbounds; } @@ -1271,57 +1409,75 @@ THE SOFTWARE. prop = pcf_find_property( face, "FAMILY_NAME" ); if ( prop && prop->isString ) { - /* Prepend the foundry name plus a space to the family name. */ - /* There are many fonts just called `Fixed' which look completely */ - /* different, and which have nothing to do with each other. When */ - /* selecting `Fixed' in KDE or Gnome one gets results that appear */ - /* rather random, the style changes often if one changes the size */ - /* and one cannot select some fonts at all. */ - /* */ - /* We also check whether we have `wide' characters; all put */ - /* together, we get family names like `Sony Fixed' or `Misc Fixed */ - /* Wide'. */ - PCF_Property foundry_prop, point_size_prop, average_width_prop; - - int l = ft_strlen( prop->value.atom ) + 1; - int wide = 0; - - - foundry_prop = pcf_find_property( face, "FOUNDRY" ); - point_size_prop = pcf_find_property( face, "POINT_SIZE" ); - average_width_prop = pcf_find_property( face, "AVERAGE_WIDTH" ); - - if ( point_size_prop && average_width_prop ) + +#ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES + + PCF_Driver driver = (PCF_Driver)FT_FACE_DRIVER( face ); + + + if ( !driver->no_long_family_names ) { - if ( average_width_prop->value.l >= point_size_prop->value.l ) + /* Prepend the foundry name plus a space to the family name. */ + /* There are many fonts just called `Fixed' which look */ + /* completely different, and which have nothing to do with each */ + /* other. When selecting `Fixed' in KDE or Gnome one gets */ + /* results that appear rather random, the style changes often if */ + /* one changes the size and one cannot select some fonts at all. */ + /* */ + /* We also check whether we have `wide' characters; all put */ + /* together, we get family names like `Sony Fixed' or `Misc */ + /* Fixed Wide'. */ + + PCF_Property foundry_prop, point_size_prop, average_width_prop; + + int l = ft_strlen( prop->value.atom ) + 1; + int wide = 0; + + + foundry_prop = pcf_find_property( face, "FOUNDRY" ); + point_size_prop = pcf_find_property( face, "POINT_SIZE" ); + average_width_prop = pcf_find_property( face, "AVERAGE_WIDTH" ); + + if ( point_size_prop && average_width_prop ) { - /* This font is at least square shaped or even wider */ - wide = 1; - l += ft_strlen( " Wide" ); + if ( average_width_prop->value.l >= point_size_prop->value.l ) + { + /* This font is at least square shaped or even wider */ + wide = 1; + l += ft_strlen( " Wide" ); + } } - } - if ( foundry_prop && foundry_prop->isString ) - { - l += ft_strlen( foundry_prop->value.atom ) + 1; + if ( foundry_prop && foundry_prop->isString ) + { + l += ft_strlen( foundry_prop->value.atom ) + 1; - if ( FT_NEW_ARRAY( root->family_name, l ) ) - goto Exit; + if ( FT_NEW_ARRAY( root->family_name, l ) ) + goto Exit; + + ft_strcpy( root->family_name, foundry_prop->value.atom ); + ft_strcat( root->family_name, " " ); + ft_strcat( root->family_name, prop->value.atom ); + } + else + { + if ( FT_NEW_ARRAY( root->family_name, l ) ) + goto Exit; + + ft_strcpy( root->family_name, prop->value.atom ); + } - ft_strcpy( root->family_name, foundry_prop->value.atom ); - ft_strcat( root->family_name, " " ); - ft_strcat( root->family_name, prop->value.atom ); + if ( wide ) + ft_strcat( root->family_name, " Wide" ); } else + +#endif /* PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ + { - if ( FT_NEW_ARRAY( root->family_name, l ) ) + if ( FT_STRDUP( root->family_name, prop->value.atom ) ) goto Exit; - - ft_strcpy( root->family_name, prop->value.atom ); } - - if ( wide ) - ft_strcat( root->family_name, " Wide" ); } else root->family_name = NULL; @@ -1356,8 +1512,16 @@ THE SOFTWARE. if ( face->accel.fontAscent + face->accel.fontDescent < 0 ) FT_TRACE0(( "pcf_load_font: negative height\n" )); #endif - bsize->height = FT_ABS( (FT_Short)( face->accel.fontAscent + - face->accel.fontDescent ) ); + if ( FT_ABS( face->accel.fontAscent + + face->accel.fontDescent ) > 0x7FFF ) + { + bsize->height = 0x7FFF; + FT_TRACE0(( "pcf_load_font: clamping height to value %d\n", + bsize->height )); + } + else + bsize->height = FT_ABS( (FT_Short)( face->accel.fontAscent + + face->accel.fontDescent ) ); prop = pcf_find_property( face, "AVERAGE_WIDTH" ); if ( prop ) @@ -1366,10 +1530,20 @@ THE SOFTWARE. if ( prop->value.l < 0 ) FT_TRACE0(( "pcf_load_font: negative average width\n" )); #endif - bsize->width = FT_ABS( (FT_Short)( ( prop->value.l ) + 5 ) / 10 ); + if ( ( FT_ABS( prop->value.l ) > 0x7FFFL * 10 - 5 ) ) + { + bsize->width = 0x7FFF; + FT_TRACE0(( "pcf_load_font: clamping average width to value %d\n", + bsize->width )); + } + else + bsize->width = FT_ABS( (FT_Short)( ( prop->value.l + 5 ) / 10 ) ); } else + { + /* this is a heuristical value */ bsize->width = (FT_Short)FT_MulDiv( bsize->height, 2, 3 ); + } prop = pcf_find_property( face, "POINT_SIZE" ); if ( prop ) @@ -1379,9 +1553,16 @@ THE SOFTWARE. FT_TRACE0(( "pcf_load_font: negative point size\n" )); #endif /* convert from 722.7 decipoints to 72 points per inch */ - bsize->size = FT_MulDiv( FT_ABS( prop->value.l ), - 64 * 7200, - 72270L ); + if ( FT_ABS( prop->value.l ) > 0x504C2L ) /* 0x7FFF * 72270/7200 */ + { + bsize->size = 0x7FFF; + FT_TRACE0(( "pcf_load_font: clamping point size to value %d\n", + bsize->size )); + } + else + bsize->size = FT_MulDiv( FT_ABS( prop->value.l ), + 64 * 7200, + 72270L ); } prop = pcf_find_property( face, "PIXEL_SIZE" ); @@ -1391,7 +1572,14 @@ THE SOFTWARE. if ( prop->value.l < 0 ) FT_TRACE0(( "pcf_load_font: negative pixel size\n" )); #endif - bsize->y_ppem = FT_ABS( (FT_Short)prop->value.l ) << 6; + if ( FT_ABS( prop->value.l ) > 0x7FFF ) + { + bsize->y_ppem = 0x7FFF << 6; + FT_TRACE0(( "pcf_load_font: clamping pixel size to value %d\n", + bsize->y_ppem )); + } + else + bsize->y_ppem = FT_ABS( (FT_Short)prop->value.l ) << 6; } prop = pcf_find_property( face, "RESOLUTION_X" ); @@ -1401,7 +1589,14 @@ THE SOFTWARE. if ( prop->value.l < 0 ) FT_TRACE0(( "pcf_load_font: negative X resolution\n" )); #endif - resolution_x = FT_ABS( (FT_Short)prop->value.l ); + if ( FT_ABS( prop->value.l ) > 0x7FFF ) + { + resolution_x = 0x7FFF; + FT_TRACE0(( "pcf_load_font: clamping X resolution to value %d\n", + resolution_x )); + } + else + resolution_x = FT_ABS( (FT_Short)prop->value.l ); } prop = pcf_find_property( face, "RESOLUTION_Y" ); @@ -1411,7 +1606,14 @@ THE SOFTWARE. if ( prop->value.l < 0 ) FT_TRACE0(( "pcf_load_font: negative Y resolution\n" )); #endif - resolution_y = FT_ABS( (FT_Short)prop->value.l ); + if ( FT_ABS( prop->value.l ) > 0x7FFF ) + { + resolution_y = 0x7FFF; + FT_TRACE0(( "pcf_load_font: clamping Y resolution to value %d\n", + resolution_y )); + } + else + resolution_y = FT_ABS( (FT_Short)prop->value.l ); } if ( bsize->y_ppem == 0 ) diff --git a/modules/freetype2/src/pfr/Jamfile b/modules/freetype2/src/pfr/Jamfile index a5b294b79..cb55a7ee8 100644 --- a/modules/freetype2/src/pfr/Jamfile +++ b/modules/freetype2/src/pfr/Jamfile @@ -1,6 +1,6 @@ # FreeType 2 src/pfr Jamfile # -# Copyright 2002-2016 by +# Copyright 2002-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/pfr/module.mk b/modules/freetype2/src/pfr/module.mk index bf7808c72..27fec8e5f 100644 --- a/modules/freetype2/src/pfr/module.mk +++ b/modules/freetype2/src/pfr/module.mk @@ -3,7 +3,7 @@ # -# Copyright 2002-2016 by +# Copyright 2002-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/pfr/pfr.c b/modules/freetype2/src/pfr/pfr.c index 1a433960a..1760882fc 100644 --- a/modules/freetype2/src/pfr/pfr.c +++ b/modules/freetype2/src/pfr/pfr.c @@ -4,7 +4,7 @@ /* */ /* FreeType PFR driver component. */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -15,15 +15,16 @@ /* */ /***************************************************************************/ -#define FT_MAKE_OPTION_SINGLE_OBJECT +#define FT_MAKE_OPTION_SINGLE_OBJECT #include <ft2build.h> -#include "pfrload.c" -#include "pfrgload.c" #include "pfrcmap.c" -#include "pfrobjs.c" #include "pfrdrivr.c" +#include "pfrgload.c" +#include "pfrload.c" +#include "pfrobjs.c" #include "pfrsbit.c" + /* END */ diff --git a/modules/freetype2/src/pfr/pfrcmap.c b/modules/freetype2/src/pfr/pfrcmap.c index f1f9c53b9..60643780a 100644 --- a/modules/freetype2/src/pfr/pfrcmap.c +++ b/modules/freetype2/src/pfr/pfrcmap.c @@ -4,7 +4,7 @@ /* */ /* FreeType PFR cmap handling (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/pfr/pfrcmap.h b/modules/freetype2/src/pfr/pfrcmap.h index 4a8a4d0a6..c70a0c83c 100644 --- a/modules/freetype2/src/pfr/pfrcmap.h +++ b/modules/freetype2/src/pfr/pfrcmap.h @@ -4,7 +4,7 @@ /* */ /* FreeType PFR cmap handling (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/pfr/pfrdrivr.c b/modules/freetype2/src/pfr/pfrdrivr.c index 2316cd3e7..6c7e50128 100644 --- a/modules/freetype2/src/pfr/pfrdrivr.c +++ b/modules/freetype2/src/pfr/pfrdrivr.c @@ -4,7 +4,7 @@ /* */ /* FreeType PFR driver interface (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/pfr/pfrdrivr.h b/modules/freetype2/src/pfr/pfrdrivr.h index 32b2d9eab..cab852789 100644 --- a/modules/freetype2/src/pfr/pfrdrivr.h +++ b/modules/freetype2/src/pfr/pfrdrivr.h @@ -4,7 +4,7 @@ /* */ /* High-level Type PFR driver interface (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/pfr/pfrerror.h b/modules/freetype2/src/pfr/pfrerror.h index 9305f8fb5..7027c818e 100644 --- a/modules/freetype2/src/pfr/pfrerror.h +++ b/modules/freetype2/src/pfr/pfrerror.h @@ -4,7 +4,7 @@ /* */ /* PFR error codes (specification only). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/pfr/pfrgload.c b/modules/freetype2/src/pfr/pfrgload.c index f9cd1f63b..b7990196b 100644 --- a/modules/freetype2/src/pfr/pfrgload.c +++ b/modules/freetype2/src/pfr/pfrgload.c @@ -4,7 +4,7 @@ /* */ /* FreeType PFR glyph loader (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -756,8 +756,10 @@ count = glyph->num_subs - old_count; - FT_TRACE4(( "compound glyph with %d elements (offset %lu):\n", - count, offset )); + FT_TRACE4(( "compound glyph with %d element%s (offset %lu):\n", + count, + count == 1 ? "" : "s", + offset )); /* now, load each individual glyph */ for ( n = 0; n < count; n++ ) @@ -810,7 +812,9 @@ /* proceed to next sub-glyph */ } - FT_TRACE4(( "end compound glyph with %d elements\n", count )); + FT_TRACE4(( "end compound glyph with %d element%s\n", + count, + count == 1 ? "" : "s" )); } else { diff --git a/modules/freetype2/src/pfr/pfrgload.h b/modules/freetype2/src/pfr/pfrgload.h index 908d4378a..01f48d770 100644 --- a/modules/freetype2/src/pfr/pfrgload.h +++ b/modules/freetype2/src/pfr/pfrgload.h @@ -4,7 +4,7 @@ /* */ /* FreeType PFR glyph loader (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/pfr/pfrload.c b/modules/freetype2/src/pfr/pfrload.c index aad759af1..2776da462 100644 --- a/modules/freetype2/src/pfr/pfrload.c +++ b/modules/freetype2/src/pfr/pfrload.c @@ -4,7 +4,7 @@ /* */ /* FreeType PFR loader (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/pfr/pfrload.h b/modules/freetype2/src/pfr/pfrload.h index 0f7a2bb23..36e809a76 100644 --- a/modules/freetype2/src/pfr/pfrload.h +++ b/modules/freetype2/src/pfr/pfrload.h @@ -4,7 +4,7 @@ /* */ /* FreeType PFR loader (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/pfr/pfrobjs.c b/modules/freetype2/src/pfr/pfrobjs.c index 0491d13df..737b97b5f 100644 --- a/modules/freetype2/src/pfr/pfrobjs.c +++ b/modules/freetype2/src/pfr/pfrobjs.c @@ -4,7 +4,7 @@ /* */ /* FreeType PFR object methods (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -264,12 +264,6 @@ charmap.encoding = FT_ENCODING_UNICODE; error = FT_CMap_New( &pfr_cmap_class_rec, NULL, &charmap, NULL ); - -#if 0 - /* select default charmap */ - if ( pfrface->num_charmaps ) - pfrface->charmap = pfrface->charmaps[0]; -#endif } /* check whether we have loaded any kerning pairs */ diff --git a/modules/freetype2/src/pfr/pfrobjs.h b/modules/freetype2/src/pfr/pfrobjs.h index 335aca885..59c709f58 100644 --- a/modules/freetype2/src/pfr/pfrobjs.h +++ b/modules/freetype2/src/pfr/pfrobjs.h @@ -4,7 +4,7 @@ /* */ /* FreeType PFR object methods (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/pfr/pfrsbit.c b/modules/freetype2/src/pfr/pfrsbit.c index f9dbf734b..ba909ddca 100644 --- a/modules/freetype2/src/pfr/pfrsbit.c +++ b/modules/freetype2/src/pfr/pfrsbit.c @@ -4,7 +4,7 @@ /* */ /* FreeType PFR bitmap loader (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/pfr/pfrsbit.h b/modules/freetype2/src/pfr/pfrsbit.h index 676ad55a9..07b27bc06 100644 --- a/modules/freetype2/src/pfr/pfrsbit.h +++ b/modules/freetype2/src/pfr/pfrsbit.h @@ -4,7 +4,7 @@ /* */ /* FreeType PFR bitmap loader (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/pfr/pfrtypes.h b/modules/freetype2/src/pfr/pfrtypes.h index bd6c2cd30..058d6aadc 100644 --- a/modules/freetype2/src/pfr/pfrtypes.h +++ b/modules/freetype2/src/pfr/pfrtypes.h @@ -4,7 +4,7 @@ /* */ /* FreeType PFR data structures (specification only). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/pfr/rules.mk b/modules/freetype2/src/pfr/rules.mk index 39bb9e941..3acb79569 100644 --- a/modules/freetype2/src/pfr/rules.mk +++ b/modules/freetype2/src/pfr/rules.mk @@ -3,7 +3,7 @@ # -# Copyright 2002-2016 by +# Copyright 2002-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/psaux/Jamfile b/modules/freetype2/src/psaux/Jamfile index 9270eec68..a231d5974 100644 --- a/modules/freetype2/src/psaux/Jamfile +++ b/modules/freetype2/src/psaux/Jamfile @@ -1,6 +1,6 @@ # FreeType 2 src/psaux Jamfile # -# Copyright 2001-2016 by +# Copyright 2001-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, @@ -22,6 +22,16 @@ SubDir FT2_TOP $(FT2_SRC_DIR) psaux ; psobjs t1cmap t1decode + cffdecode + psarrst + psblues + pserror + psfont + psft + pshints + psintrp + psread + psstack ; } else diff --git a/modules/freetype2/src/psaux/afmparse.c b/modules/freetype2/src/psaux/afmparse.c index 9fb0ac0e2..0c33d5949 100644 --- a/modules/freetype2/src/psaux/afmparse.c +++ b/modules/freetype2/src/psaux/afmparse.c @@ -4,7 +4,7 @@ /* */ /* AFM parser (body). */ /* */ -/* Copyright 2006-2016 by */ +/* Copyright 2006-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -20,6 +20,8 @@ #include FT_INTERNAL_DEBUG_H #include FT_INTERNAL_POSTSCRIPT_AUX_H +#ifndef T1_CONFIG_OPTION_NO_AFM + #include "afmparse.h" #include "psconv.h" @@ -973,5 +975,12 @@ return error; } +#else /* T1_CONFIG_OPTION_NO_AFM */ + + /* ANSI C doesn't like empty source files */ + typedef int _afm_parse_dummy; + +#endif /* T1_CONFIG_OPTION_NO_AFM */ + /* END */ diff --git a/modules/freetype2/src/psaux/afmparse.h b/modules/freetype2/src/psaux/afmparse.h index 6d8b193ff..86f852a24 100644 --- a/modules/freetype2/src/psaux/afmparse.h +++ b/modules/freetype2/src/psaux/afmparse.h @@ -4,7 +4,7 @@ /* */ /* AFM parser (specification). */ /* */ -/* Copyright 2006-2016 by */ +/* Copyright 2006-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/psaux/cffdecode.c b/modules/freetype2/src/psaux/cffdecode.c new file mode 100644 index 000000000..80d622c0e --- /dev/null +++ b/modules/freetype2/src/psaux/cffdecode.c @@ -0,0 +1,2370 @@ +/***************************************************************************/ +/* */ +/* cffdecode.c */ +/* */ +/* PostScript CFF (Type 2) decoding routines (body). */ +/* */ +/* Copyright 2017-2018 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 FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_SERVICE_H +#include FT_SERVICE_CFF_TABLE_LOAD_H + +#include "cffdecode.h" +#include "psobjs.h" + +#include "psauxerr.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_cffdecode + + +#ifdef CFF_CONFIG_OPTION_OLD_ENGINE + + typedef enum CFF_Operator_ + { + cff_op_unknown = 0, + + cff_op_rmoveto, + cff_op_hmoveto, + cff_op_vmoveto, + + cff_op_rlineto, + cff_op_hlineto, + cff_op_vlineto, + + cff_op_rrcurveto, + cff_op_hhcurveto, + cff_op_hvcurveto, + cff_op_rcurveline, + cff_op_rlinecurve, + cff_op_vhcurveto, + cff_op_vvcurveto, + + cff_op_flex, + cff_op_hflex, + cff_op_hflex1, + cff_op_flex1, + + cff_op_endchar, + + cff_op_hstem, + cff_op_vstem, + cff_op_hstemhm, + cff_op_vstemhm, + + cff_op_hintmask, + cff_op_cntrmask, + cff_op_dotsection, /* deprecated, acts as no-op */ + + cff_op_abs, + cff_op_add, + cff_op_sub, + cff_op_div, + cff_op_neg, + cff_op_random, + cff_op_mul, + cff_op_sqrt, + + cff_op_blend, + + cff_op_drop, + cff_op_exch, + cff_op_index, + cff_op_roll, + cff_op_dup, + + cff_op_put, + cff_op_get, + cff_op_store, + cff_op_load, + + cff_op_and, + cff_op_or, + cff_op_not, + cff_op_eq, + cff_op_ifelse, + + cff_op_callsubr, + cff_op_callgsubr, + cff_op_return, + + /* Type 1 opcodes: invalid but seen in real life */ + cff_op_hsbw, + cff_op_closepath, + cff_op_callothersubr, + cff_op_pop, + cff_op_seac, + cff_op_sbw, + cff_op_setcurrentpoint, + + /* do not remove */ + cff_op_max + + } CFF_Operator; + + +#define CFF_COUNT_CHECK_WIDTH 0x80 +#define CFF_COUNT_EXACT 0x40 +#define CFF_COUNT_CLEAR_STACK 0x20 + + /* count values which have the `CFF_COUNT_CHECK_WIDTH' flag set are */ + /* used for checking the width and requested numbers of arguments */ + /* only; they are set to zero afterwards */ + + /* the other two flags are informative only and unused currently */ + + static const FT_Byte cff_argument_counts[] = + { + 0, /* unknown */ + + 2 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, /* rmoveto */ + 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, + 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, + + 0 | CFF_COUNT_CLEAR_STACK, /* rlineto */ + 0 | CFF_COUNT_CLEAR_STACK, + 0 | CFF_COUNT_CLEAR_STACK, + + 0 | CFF_COUNT_CLEAR_STACK, /* rrcurveto */ + 0 | CFF_COUNT_CLEAR_STACK, + 0 | CFF_COUNT_CLEAR_STACK, + 0 | CFF_COUNT_CLEAR_STACK, + 0 | CFF_COUNT_CLEAR_STACK, + 0 | CFF_COUNT_CLEAR_STACK, + 0 | CFF_COUNT_CLEAR_STACK, + + 13, /* flex */ + 7, + 9, + 11, + + 0 | CFF_COUNT_CHECK_WIDTH, /* endchar */ + + 2 | CFF_COUNT_CHECK_WIDTH, /* hstem */ + 2 | CFF_COUNT_CHECK_WIDTH, + 2 | CFF_COUNT_CHECK_WIDTH, + 2 | CFF_COUNT_CHECK_WIDTH, + + 0 | CFF_COUNT_CHECK_WIDTH, /* hintmask */ + 0 | CFF_COUNT_CHECK_WIDTH, /* cntrmask */ + 0, /* dotsection */ + + 1, /* abs */ + 2, + 2, + 2, + 1, + 0, + 2, + 1, + + 1, /* blend */ + + 1, /* drop */ + 2, + 1, + 2, + 1, + + 2, /* put */ + 1, + 4, + 3, + + 2, /* and */ + 2, + 1, + 2, + 4, + + 1, /* callsubr */ + 1, + 0, + + 2, /* hsbw */ + 0, + 0, + 0, + 5, /* seac */ + 4, /* sbw */ + 2 /* setcurrentpoint */ + }; + + + static FT_Error + cff_operator_seac( CFF_Decoder* decoder, + FT_Pos asb, + FT_Pos adx, + FT_Pos ady, + FT_Int bchar, + FT_Int achar ) + { + FT_Error error; + CFF_Builder* builder = &decoder->builder; + FT_Int bchar_index, achar_index; + TT_Face face = decoder->builder.face; + FT_Vector left_bearing, advance; + FT_Byte* charstring; + FT_ULong charstring_len; + FT_Pos glyph_width; + + + if ( decoder->seac ) + { + FT_ERROR(( "cff_operator_seac: invalid nested seac\n" )); + return FT_THROW( Syntax_Error ); + } + + adx += decoder->builder.left_bearing.x; + ady += decoder->builder.left_bearing.y; + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + /* Incremental fonts don't necessarily have valid charsets. */ + /* They use the character code, not the glyph index, in this case. */ + if ( face->root.internal->incremental_interface ) + { + bchar_index = bchar; + achar_index = achar; + } + else +#endif /* FT_CONFIG_OPTION_INCREMENTAL */ + { + CFF_Font cff = (CFF_Font)(face->extra.data); + + + bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar ); + achar_index = cff_lookup_glyph_by_stdcharcode( cff, achar ); + } + + if ( bchar_index < 0 || achar_index < 0 ) + { + FT_ERROR(( "cff_operator_seac:" + " invalid seac character code arguments\n" )); + return FT_THROW( Syntax_Error ); + } + + /* If we are trying to load a composite glyph, do not load the */ + /* accent character and return the array of subglyphs. */ + if ( builder->no_recurse ) + { + FT_GlyphSlot glyph = (FT_GlyphSlot)builder->glyph; + FT_GlyphLoader loader = glyph->internal->loader; + FT_SubGlyph subg; + + + /* reallocate subglyph array if necessary */ + error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 ); + if ( error ) + goto Exit; + + subg = loader->current.subglyphs; + + /* subglyph 0 = base character */ + subg->index = bchar_index; + subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES | + FT_SUBGLYPH_FLAG_USE_MY_METRICS; + subg->arg1 = 0; + subg->arg2 = 0; + subg++; + + /* subglyph 1 = accent character */ + subg->index = achar_index; + subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES; + subg->arg1 = (FT_Int)( adx >> 16 ); + subg->arg2 = (FT_Int)( ady >> 16 ); + + /* set up remaining glyph fields */ + glyph->num_subglyphs = 2; + glyph->subglyphs = loader->base.subglyphs; + glyph->format = FT_GLYPH_FORMAT_COMPOSITE; + + loader->current.num_subglyphs = 2; + } + + FT_GlyphLoader_Prepare( builder->loader ); + + /* First load `bchar' in builder */ + error = decoder->get_glyph_callback( face, (FT_UInt)bchar_index, + &charstring, &charstring_len ); + if ( !error ) + { + /* the seac operator must not be nested */ + decoder->seac = TRUE; + error = cff_decoder_parse_charstrings( decoder, charstring, + charstring_len, 0 ); + decoder->seac = FALSE; + + decoder->free_glyph_callback( face, &charstring, charstring_len ); + + if ( error ) + goto Exit; + } + + /* Save the left bearing, advance and glyph width of the base */ + /* character as they will be erased by the next load. */ + + left_bearing = builder->left_bearing; + advance = builder->advance; + glyph_width = decoder->glyph_width; + + builder->left_bearing.x = 0; + builder->left_bearing.y = 0; + + builder->pos_x = adx - asb; + builder->pos_y = ady; + + /* Now load `achar' on top of the base outline. */ + error = decoder->get_glyph_callback( face, (FT_UInt)achar_index, + &charstring, &charstring_len ); + if ( !error ) + { + /* the seac operator must not be nested */ + decoder->seac = TRUE; + error = cff_decoder_parse_charstrings( decoder, charstring, + charstring_len, 0 ); + decoder->seac = FALSE; + + decoder->free_glyph_callback( face, &charstring, charstring_len ); + + if ( error ) + goto Exit; + } + + /* Restore the left side bearing, advance and glyph width */ + /* of the base character. */ + builder->left_bearing = left_bearing; + builder->advance = advance; + decoder->glyph_width = glyph_width; + + builder->pos_x = 0; + builder->pos_y = 0; + + Exit: + return error; + } + +#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */ + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** *********/ + /********** GENERIC CHARSTRING PARSING *********/ + /********** *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* <Function> */ + /* cff_compute_bias */ + /* */ + /* <Description> */ + /* Computes the bias value in dependence of the number of glyph */ + /* subroutines. */ + /* */ + /* <Input> */ + /* in_charstring_type :: The `CharstringType' value of the top DICT */ + /* dictionary. */ + /* */ + /* num_subrs :: The number of glyph subroutines. */ + /* */ + /* <Return> */ + /* The bias value. */ + static FT_Int + cff_compute_bias( FT_Int in_charstring_type, + FT_UInt num_subrs ) + { + FT_Int result; + + + if ( in_charstring_type == 1 ) + result = 0; + else if ( num_subrs < 1240 ) + result = 107; + else if ( num_subrs < 33900U ) + result = 1131; + else + result = 32768U; + + return result; + } + + + FT_LOCAL_DEF( FT_Int ) + cff_lookup_glyph_by_stdcharcode( CFF_Font cff, + FT_Int charcode ) + { + FT_UInt n; + FT_UShort glyph_sid; + + FT_Service_CFFLoad cffload; + + + /* CID-keyed fonts don't have glyph names */ + if ( !cff->charset.sids ) + return -1; + + /* check range of standard char code */ + if ( charcode < 0 || charcode > 255 ) + return -1; + +#if 0 + /* retrieve cffload from list of current modules */ + FT_Service_CFFLoad cffload; + + + FT_FACE_FIND_GLOBAL_SERVICE( face, cffload, CFF_LOAD ); + if ( !cffload ) + { + FT_ERROR(( "cff_lookup_glyph_by_stdcharcode:" + " the `cffload' module is not available\n" )); + return FT_THROW( Unimplemented_Feature ); + } +#endif + + cffload = (FT_Service_CFFLoad)cff->cffload; + + /* Get code to SID mapping from `cff_standard_encoding'. */ + glyph_sid = cffload->get_standard_encoding( (FT_UInt)charcode ); + + for ( n = 0; n < cff->num_glyphs; n++ ) + { + if ( cff->charset.sids[n] == glyph_sid ) + return (FT_Int)n; + } + + return -1; + } + + +#ifdef CFF_CONFIG_OPTION_OLD_ENGINE + + /*************************************************************************/ + /* */ + /* <Function> */ + /* cff_decoder_parse_charstrings */ + /* */ + /* <Description> */ + /* Parses a given Type 2 charstrings program. */ + /* */ + /* <InOut> */ + /* decoder :: The current Type 1 decoder. */ + /* */ + /* <Input> */ + /* charstring_base :: The base of the charstring stream. */ + /* */ + /* charstring_len :: The length in bytes of the charstring stream. */ + /* */ + /* in_dict :: Set to 1 if function is called from top or */ + /* private DICT (needed for Multiple Master CFFs). */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + cff_decoder_parse_charstrings( CFF_Decoder* decoder, + FT_Byte* charstring_base, + FT_ULong charstring_len, + FT_Bool in_dict ) + { + FT_Error error; + CFF_Decoder_Zone* zone; + FT_Byte* ip; + FT_Byte* limit; + CFF_Builder* builder = &decoder->builder; + FT_Pos x, y; + FT_Fixed* stack; + FT_Int charstring_type = + decoder->cff->top_font.font_dict.charstring_type; + FT_UShort num_designs = + decoder->cff->top_font.font_dict.num_designs; + FT_UShort num_axes = + decoder->cff->top_font.font_dict.num_axes; + + T2_Hints_Funcs hinter; + + + /* set default width */ + decoder->num_hints = 0; + decoder->read_width = 1; + + /* initialize the decoder */ + decoder->top = decoder->stack; + decoder->zone = decoder->zones; + zone = decoder->zones; + stack = decoder->top; + + hinter = (T2_Hints_Funcs)builder->hints_funcs; + + builder->path_begun = 0; + + zone->base = charstring_base; + limit = zone->limit = charstring_base + charstring_len; + ip = zone->cursor = zone->base; + + error = FT_Err_Ok; + + x = builder->pos_x; + y = builder->pos_y; + + /* begin hints recording session, if any */ + if ( hinter ) + hinter->open( hinter->hints ); + + /* now execute loop */ + while ( ip < limit ) + { + CFF_Operator op; + FT_Byte v; + + + /********************************************************************/ + /* */ + /* Decode operator or operand */ + /* */ + v = *ip++; + if ( v >= 32 || v == 28 ) + { + FT_Int shift = 16; + FT_Int32 val; + + + /* this is an operand, push it on the stack */ + + /* if we use shifts, all computations are done with unsigned */ + /* values; the conversion to a signed value is the last step */ + if ( v == 28 ) + { + if ( ip + 1 >= limit ) + goto Syntax_Error; + val = (FT_Short)( ( (FT_UShort)ip[0] << 8 ) | ip[1] ); + ip += 2; + } + else if ( v < 247 ) + val = (FT_Int32)v - 139; + else if ( v < 251 ) + { + if ( ip >= limit ) + goto Syntax_Error; + val = ( (FT_Int32)v - 247 ) * 256 + *ip++ + 108; + } + else if ( v < 255 ) + { + if ( ip >= limit ) + goto Syntax_Error; + val = -( (FT_Int32)v - 251 ) * 256 - *ip++ - 108; + } + else + { + if ( ip + 3 >= limit ) + goto Syntax_Error; + val = (FT_Int32)( ( (FT_UInt32)ip[0] << 24 ) | + ( (FT_UInt32)ip[1] << 16 ) | + ( (FT_UInt32)ip[2] << 8 ) | + (FT_UInt32)ip[3] ); + ip += 4; + if ( charstring_type == 2 ) + shift = 0; + } + if ( decoder->top - stack >= CFF_MAX_OPERANDS ) + goto Stack_Overflow; + + val = (FT_Int32)( (FT_UInt32)val << shift ); + *decoder->top++ = val; + +#ifdef FT_DEBUG_LEVEL_TRACE + if ( !( val & 0xFFFFL ) ) + FT_TRACE4(( " %hd", (FT_Short)( (FT_UInt32)val >> 16 ) )); + else + FT_TRACE4(( " %.5f", val / 65536.0 )); +#endif + + } + else + { + /* The specification says that normally arguments are to be taken */ + /* from the bottom of the stack. However, this seems not to be */ + /* correct, at least for Acroread 7.0.8 on GNU/Linux: It pops the */ + /* arguments similar to a PS interpreter. */ + + FT_Fixed* args = decoder->top; + FT_Int num_args = (FT_Int)( args - decoder->stack ); + FT_Int req_args; + + + /* find operator */ + op = cff_op_unknown; + + switch ( v ) + { + case 1: + op = cff_op_hstem; + break; + case 3: + op = cff_op_vstem; + break; + case 4: + op = cff_op_vmoveto; + break; + case 5: + op = cff_op_rlineto; + break; + case 6: + op = cff_op_hlineto; + break; + case 7: + op = cff_op_vlineto; + break; + case 8: + op = cff_op_rrcurveto; + break; + case 9: + op = cff_op_closepath; + break; + case 10: + op = cff_op_callsubr; + break; + case 11: + op = cff_op_return; + break; + case 12: + if ( ip >= limit ) + goto Syntax_Error; + v = *ip++; + + switch ( v ) + { + case 0: + op = cff_op_dotsection; + break; + case 1: /* this is actually the Type1 vstem3 operator */ + op = cff_op_vstem; + break; + case 2: /* this is actually the Type1 hstem3 operator */ + op = cff_op_hstem; + break; + case 3: + op = cff_op_and; + break; + case 4: + op = cff_op_or; + break; + case 5: + op = cff_op_not; + break; + case 6: + op = cff_op_seac; + break; + case 7: + op = cff_op_sbw; + break; + case 8: + op = cff_op_store; + break; + case 9: + op = cff_op_abs; + break; + case 10: + op = cff_op_add; + break; + case 11: + op = cff_op_sub; + break; + case 12: + op = cff_op_div; + break; + case 13: + op = cff_op_load; + break; + case 14: + op = cff_op_neg; + break; + case 15: + op = cff_op_eq; + break; + case 16: + op = cff_op_callothersubr; + break; + case 17: + op = cff_op_pop; + break; + case 18: + op = cff_op_drop; + break; + case 20: + op = cff_op_put; + break; + case 21: + op = cff_op_get; + break; + case 22: + op = cff_op_ifelse; + break; + case 23: + op = cff_op_random; + break; + case 24: + op = cff_op_mul; + break; + case 26: + op = cff_op_sqrt; + break; + case 27: + op = cff_op_dup; + break; + case 28: + op = cff_op_exch; + break; + case 29: + op = cff_op_index; + break; + case 30: + op = cff_op_roll; + break; + case 33: + op = cff_op_setcurrentpoint; + break; + case 34: + op = cff_op_hflex; + break; + case 35: + op = cff_op_flex; + break; + case 36: + op = cff_op_hflex1; + break; + case 37: + op = cff_op_flex1; + break; + default: + FT_TRACE4(( " unknown op (12, %d)\n", v )); + break; + } + break; + case 13: + op = cff_op_hsbw; + break; + case 14: + op = cff_op_endchar; + break; + case 16: + op = cff_op_blend; + break; + case 18: + op = cff_op_hstemhm; + break; + case 19: + op = cff_op_hintmask; + break; + case 20: + op = cff_op_cntrmask; + break; + case 21: + op = cff_op_rmoveto; + break; + case 22: + op = cff_op_hmoveto; + break; + case 23: + op = cff_op_vstemhm; + break; + case 24: + op = cff_op_rcurveline; + break; + case 25: + op = cff_op_rlinecurve; + break; + case 26: + op = cff_op_vvcurveto; + break; + case 27: + op = cff_op_hhcurveto; + break; + case 29: + op = cff_op_callgsubr; + break; + case 30: + op = cff_op_vhcurveto; + break; + case 31: + op = cff_op_hvcurveto; + break; + default: + FT_TRACE4(( " unknown op (%d)\n", v )); + break; + } + + if ( op == cff_op_unknown ) + continue; + + /* in Multiple Master CFFs, T2 charstrings can appear in */ + /* dictionaries, but some operators are prohibited */ + if ( in_dict ) + { + switch ( op ) + { + case cff_op_hstem: + case cff_op_vstem: + case cff_op_vmoveto: + case cff_op_rlineto: + case cff_op_hlineto: + case cff_op_vlineto: + case cff_op_rrcurveto: + case cff_op_hstemhm: + case cff_op_hintmask: + case cff_op_cntrmask: + case cff_op_rmoveto: + case cff_op_hmoveto: + case cff_op_vstemhm: + case cff_op_rcurveline: + case cff_op_rlinecurve: + case cff_op_vvcurveto: + case cff_op_hhcurveto: + case cff_op_vhcurveto: + case cff_op_hvcurveto: + case cff_op_hflex: + case cff_op_flex: + case cff_op_hflex1: + case cff_op_flex1: + case cff_op_callsubr: + case cff_op_callgsubr: + goto MM_Error; + + default: + break; + } + } + + /* check arguments */ + req_args = cff_argument_counts[op]; + if ( req_args & CFF_COUNT_CHECK_WIDTH ) + { + if ( num_args > 0 && decoder->read_width ) + { + /* If `nominal_width' is non-zero, the number is really a */ + /* difference against `nominal_width'. Else, the number here */ + /* is truly a width, not a difference against `nominal_width'. */ + /* If the font does not set `nominal_width', then */ + /* `nominal_width' defaults to zero, and so we can set */ + /* `glyph_width' to `nominal_width' plus number on the stack */ + /* -- for either case. */ + + FT_Int set_width_ok; + + + switch ( op ) + { + case cff_op_hmoveto: + case cff_op_vmoveto: + set_width_ok = num_args & 2; + break; + + case cff_op_hstem: + case cff_op_vstem: + case cff_op_hstemhm: + case cff_op_vstemhm: + case cff_op_rmoveto: + case cff_op_hintmask: + case cff_op_cntrmask: + set_width_ok = num_args & 1; + break; + + case cff_op_endchar: + /* If there is a width specified for endchar, we either have */ + /* 1 argument or 5 arguments. We like to argue. */ + set_width_ok = in_dict + ? 0 + : ( ( num_args == 5 ) || ( num_args == 1 ) ); + break; + + default: + set_width_ok = 0; + break; + } + + if ( set_width_ok ) + { + decoder->glyph_width = decoder->nominal_width + + ( stack[0] >> 16 ); + + if ( decoder->width_only ) + { + /* we only want the advance width; stop here */ + break; + } + + /* Consumed an argument. */ + num_args--; + } + } + + decoder->read_width = 0; + req_args = 0; + } + + req_args &= 0x000F; + if ( num_args < req_args ) + goto Stack_Underflow; + args -= req_args; + num_args -= req_args; + + /* At this point, `args' points to the first argument of the */ + /* operand in case `req_args' isn't zero. Otherwise, we have */ + /* to adjust `args' manually. */ + + /* Note that we only pop arguments from the stack which we */ + /* really need and can digest so that we can continue in case */ + /* of superfluous stack elements. */ + + switch ( op ) + { + case cff_op_hstem: + case cff_op_vstem: + case cff_op_hstemhm: + case cff_op_vstemhm: + /* the number of arguments is always even here */ + FT_TRACE4(( + op == cff_op_hstem ? " hstem\n" : + ( op == cff_op_vstem ? " vstem\n" : + ( op == cff_op_hstemhm ? " hstemhm\n" : " vstemhm\n" ) ) )); + + if ( hinter ) + hinter->stems( hinter->hints, + ( op == cff_op_hstem || op == cff_op_hstemhm ), + num_args / 2, + args - ( num_args & ~1 ) ); + + decoder->num_hints += num_args / 2; + args = stack; + break; + + case cff_op_hintmask: + case cff_op_cntrmask: + FT_TRACE4(( op == cff_op_hintmask ? " hintmask" : " cntrmask" )); + + /* implement vstem when needed -- */ + /* the specification doesn't say it, but this also works */ + /* with the 'cntrmask' operator */ + /* */ + if ( num_args > 0 ) + { + if ( hinter ) + hinter->stems( hinter->hints, + 0, + num_args / 2, + args - ( num_args & ~1 ) ); + + decoder->num_hints += num_args / 2; + } + + /* In a valid charstring there must be at least one byte */ + /* after `hintmask' or `cntrmask' (e.g., for a `return' */ + /* instruction). Additionally, there must be space for */ + /* `num_hints' bits. */ + + if ( ( ip + ( ( decoder->num_hints + 7 ) >> 3 ) ) >= limit ) + goto Syntax_Error; + + if ( hinter ) + { + if ( op == cff_op_hintmask ) + hinter->hintmask( hinter->hints, + (FT_UInt)builder->current->n_points, + (FT_UInt)decoder->num_hints, + ip ); + else + hinter->counter( hinter->hints, + (FT_UInt)decoder->num_hints, + ip ); + } + +#ifdef FT_DEBUG_LEVEL_TRACE + { + FT_UInt maskbyte; + + + FT_TRACE4(( " (maskbytes:" )); + + for ( maskbyte = 0; + maskbyte < (FT_UInt)( ( decoder->num_hints + 7 ) >> 3 ); + maskbyte++, ip++ ) + FT_TRACE4(( " 0x%02X", *ip )); + + FT_TRACE4(( ")\n" )); + } +#else + ip += ( decoder->num_hints + 7 ) >> 3; +#endif + args = stack; + break; + + case cff_op_rmoveto: + FT_TRACE4(( " rmoveto\n" )); + + cff_builder_close_contour( builder ); + builder->path_begun = 0; + x = ADD_LONG( x, args[-2] ); + y = ADD_LONG( y, args[-1] ); + args = stack; + break; + + case cff_op_vmoveto: + FT_TRACE4(( " vmoveto\n" )); + + cff_builder_close_contour( builder ); + builder->path_begun = 0; + y = ADD_LONG( y, args[-1] ); + args = stack; + break; + + case cff_op_hmoveto: + FT_TRACE4(( " hmoveto\n" )); + + cff_builder_close_contour( builder ); + builder->path_begun = 0; + x = ADD_LONG( x, args[-1] ); + args = stack; + break; + + case cff_op_rlineto: + FT_TRACE4(( " rlineto\n" )); + + if ( cff_builder_start_point( builder, x, y ) || + cff_check_points( builder, num_args / 2 ) ) + goto Fail; + + if ( num_args < 2 ) + goto Stack_Underflow; + + args -= num_args & ~1; + while ( args < decoder->top ) + { + x = ADD_LONG( x, args[0] ); + y = ADD_LONG( y, args[1] ); + cff_builder_add_point( builder, x, y, 1 ); + args += 2; + } + args = stack; + break; + + case cff_op_hlineto: + case cff_op_vlineto: + { + FT_Int phase = ( op == cff_op_hlineto ); + + + FT_TRACE4(( op == cff_op_hlineto ? " hlineto\n" + : " vlineto\n" )); + + if ( num_args < 0 ) + goto Stack_Underflow; + + /* there exist subsetted fonts (found in PDFs) */ + /* which call `hlineto' without arguments */ + if ( num_args == 0 ) + break; + + if ( cff_builder_start_point( builder, x, y ) || + cff_check_points( builder, num_args ) ) + goto Fail; + + args = stack; + while ( args < decoder->top ) + { + if ( phase ) + x = ADD_LONG( x, args[0] ); + else + y = ADD_LONG( y, args[0] ); + + if ( cff_builder_add_point1( builder, x, y ) ) + goto Fail; + + args++; + phase ^= 1; + } + args = stack; + } + break; + + case cff_op_rrcurveto: + { + FT_Int nargs; + + + FT_TRACE4(( " rrcurveto\n" )); + + if ( num_args < 6 ) + goto Stack_Underflow; + + nargs = num_args - num_args % 6; + + if ( cff_builder_start_point( builder, x, y ) || + cff_check_points( builder, nargs / 2 ) ) + goto Fail; + + args -= nargs; + while ( args < decoder->top ) + { + x = ADD_LONG( x, args[0] ); + y = ADD_LONG( y, args[1] ); + cff_builder_add_point( builder, x, y, 0 ); + + x = ADD_LONG( x, args[2] ); + y = ADD_LONG( y, args[3] ); + cff_builder_add_point( builder, x, y, 0 ); + + x = ADD_LONG( x, args[4] ); + y = ADD_LONG( y, args[5] ); + cff_builder_add_point( builder, x, y, 1 ); + + args += 6; + } + args = stack; + } + break; + + case cff_op_vvcurveto: + { + FT_Int nargs; + + + FT_TRACE4(( " vvcurveto\n" )); + + if ( num_args < 4 ) + goto Stack_Underflow; + + /* if num_args isn't of the form 4n or 4n+1, */ + /* we enforce it by clearing the second bit */ + + nargs = num_args & ~2; + + if ( cff_builder_start_point( builder, x, y ) ) + goto Fail; + + args -= nargs; + + if ( nargs & 1 ) + { + x = ADD_LONG( x, args[0] ); + args++; + nargs--; + } + + if ( cff_check_points( builder, 3 * ( nargs / 4 ) ) ) + goto Fail; + + while ( args < decoder->top ) + { + y = ADD_LONG( y, args[0] ); + cff_builder_add_point( builder, x, y, 0 ); + + x = ADD_LONG( x, args[1] ); + y = ADD_LONG( y, args[2] ); + cff_builder_add_point( builder, x, y, 0 ); + + y = ADD_LONG( y, args[3] ); + cff_builder_add_point( builder, x, y, 1 ); + + args += 4; + } + args = stack; + } + break; + + case cff_op_hhcurveto: + { + FT_Int nargs; + + + FT_TRACE4(( " hhcurveto\n" )); + + if ( num_args < 4 ) + goto Stack_Underflow; + + /* if num_args isn't of the form 4n or 4n+1, */ + /* we enforce it by clearing the second bit */ + + nargs = num_args & ~2; + + if ( cff_builder_start_point( builder, x, y ) ) + goto Fail; + + args -= nargs; + if ( nargs & 1 ) + { + y = ADD_LONG( y, args[0] ); + args++; + nargs--; + } + + if ( cff_check_points( builder, 3 * ( nargs / 4 ) ) ) + goto Fail; + + while ( args < decoder->top ) + { + x = ADD_LONG( x, args[0] ); + cff_builder_add_point( builder, x, y, 0 ); + + x = ADD_LONG( x, args[1] ); + y = ADD_LONG( y, args[2] ); + cff_builder_add_point( builder, x, y, 0 ); + + x = ADD_LONG( x, args[3] ); + cff_builder_add_point( builder, x, y, 1 ); + + args += 4; + } + args = stack; + } + break; + + case cff_op_vhcurveto: + case cff_op_hvcurveto: + { + FT_Int phase; + FT_Int nargs; + + + FT_TRACE4(( op == cff_op_vhcurveto ? " vhcurveto\n" + : " hvcurveto\n" )); + + if ( cff_builder_start_point( builder, x, y ) ) + goto Fail; + + if ( num_args < 4 ) + goto Stack_Underflow; + + /* if num_args isn't of the form 8n, 8n+1, 8n+4, or 8n+5, */ + /* we enforce it by clearing the second bit */ + + nargs = num_args & ~2; + + args -= nargs; + if ( cff_check_points( builder, ( nargs / 4 ) * 3 ) ) + goto Stack_Underflow; + + phase = ( op == cff_op_hvcurveto ); + + while ( nargs >= 4 ) + { + nargs -= 4; + if ( phase ) + { + x = ADD_LONG( x, args[0] ); + cff_builder_add_point( builder, x, y, 0 ); + + x = ADD_LONG( x, args[1] ); + y = ADD_LONG( y, args[2] ); + cff_builder_add_point( builder, x, y, 0 ); + + y = ADD_LONG( y, args[3] ); + if ( nargs == 1 ) + x = ADD_LONG( x, args[4] ); + cff_builder_add_point( builder, x, y, 1 ); + } + else + { + y = ADD_LONG( y, args[0] ); + cff_builder_add_point( builder, x, y, 0 ); + + x = ADD_LONG( x, args[1] ); + y = ADD_LONG( y, args[2] ); + cff_builder_add_point( builder, x, y, 0 ); + + x = ADD_LONG( x, args[3] ); + if ( nargs == 1 ) + y = ADD_LONG( y, args[4] ); + cff_builder_add_point( builder, x, y, 1 ); + } + args += 4; + phase ^= 1; + } + args = stack; + } + break; + + case cff_op_rlinecurve: + { + FT_Int num_lines; + FT_Int nargs; + + + FT_TRACE4(( " rlinecurve\n" )); + + if ( num_args < 8 ) + goto Stack_Underflow; + + nargs = num_args & ~1; + num_lines = ( nargs - 6 ) / 2; + + if ( cff_builder_start_point( builder, x, y ) || + cff_check_points( builder, num_lines + 3 ) ) + goto Fail; + + args -= nargs; + + /* first, add the line segments */ + while ( num_lines > 0 ) + { + x = ADD_LONG( x, args[0] ); + y = ADD_LONG( y, args[1] ); + cff_builder_add_point( builder, x, y, 1 ); + + args += 2; + num_lines--; + } + + /* then the curve */ + x = ADD_LONG( x, args[0] ); + y = ADD_LONG( y, args[1] ); + cff_builder_add_point( builder, x, y, 0 ); + + x = ADD_LONG( x, args[2] ); + y = ADD_LONG( y, args[3] ); + cff_builder_add_point( builder, x, y, 0 ); + + x = ADD_LONG( x, args[4] ); + y = ADD_LONG( y, args[5] ); + cff_builder_add_point( builder, x, y, 1 ); + + args = stack; + } + break; + + case cff_op_rcurveline: + { + FT_Int num_curves; + FT_Int nargs; + + + FT_TRACE4(( " rcurveline\n" )); + + if ( num_args < 8 ) + goto Stack_Underflow; + + nargs = num_args - 2; + nargs = nargs - nargs % 6 + 2; + num_curves = ( nargs - 2 ) / 6; + + if ( cff_builder_start_point( builder, x, y ) || + cff_check_points( builder, num_curves * 3 + 2 ) ) + goto Fail; + + args -= nargs; + + /* first, add the curves */ + while ( num_curves > 0 ) + { + x = ADD_LONG( x, args[0] ); + y = ADD_LONG( y, args[1] ); + cff_builder_add_point( builder, x, y, 0 ); + + x = ADD_LONG( x, args[2] ); + y = ADD_LONG( y, args[3] ); + cff_builder_add_point( builder, x, y, 0 ); + + x = ADD_LONG( x, args[4] ); + y = ADD_LONG( y, args[5] ); + cff_builder_add_point( builder, x, y, 1 ); + + args += 6; + num_curves--; + } + + /* then the final line */ + x = ADD_LONG( x, args[0] ); + y = ADD_LONG( y, args[1] ); + cff_builder_add_point( builder, x, y, 1 ); + + args = stack; + } + break; + + case cff_op_hflex1: + { + FT_Pos start_y; + + + FT_TRACE4(( " hflex1\n" )); + + /* adding five more points: 4 control points, 1 on-curve point */ + /* -- make sure we have enough space for the start point if it */ + /* needs to be added */ + if ( cff_builder_start_point( builder, x, y ) || + cff_check_points( builder, 6 ) ) + goto Fail; + + /* record the starting point's y position for later use */ + start_y = y; + + /* first control point */ + x = ADD_LONG( x, args[0] ); + y = ADD_LONG( y, args[1] ); + cff_builder_add_point( builder, x, y, 0 ); + + /* second control point */ + x = ADD_LONG( x, args[2] ); + y = ADD_LONG( y, args[3] ); + cff_builder_add_point( builder, x, y, 0 ); + + /* join point; on curve, with y-value the same as the last */ + /* control point's y-value */ + x = ADD_LONG( x, args[4] ); + cff_builder_add_point( builder, x, y, 1 ); + + /* third control point, with y-value the same as the join */ + /* point's y-value */ + x = ADD_LONG( x, args[5] ); + cff_builder_add_point( builder, x, y, 0 ); + + /* fourth control point */ + x = ADD_LONG( x, args[6] ); + y = ADD_LONG( y, args[7] ); + cff_builder_add_point( builder, x, y, 0 ); + + /* ending point, with y-value the same as the start */ + x = ADD_LONG( x, args[8] ); + y = start_y; + cff_builder_add_point( builder, x, y, 1 ); + + args = stack; + break; + } + + case cff_op_hflex: + { + FT_Pos start_y; + + + FT_TRACE4(( " hflex\n" )); + + /* adding six more points; 4 control points, 2 on-curve points */ + if ( cff_builder_start_point( builder, x, y ) || + cff_check_points( builder, 6 ) ) + goto Fail; + + /* record the starting point's y-position for later use */ + start_y = y; + + /* first control point */ + x = ADD_LONG( x, args[0] ); + cff_builder_add_point( builder, x, y, 0 ); + + /* second control point */ + x = ADD_LONG( x, args[1] ); + y = ADD_LONG( y, args[2] ); + cff_builder_add_point( builder, x, y, 0 ); + + /* join point; on curve, with y-value the same as the last */ + /* control point's y-value */ + x = ADD_LONG( x, args[3] ); + cff_builder_add_point( builder, x, y, 1 ); + + /* third control point, with y-value the same as the join */ + /* point's y-value */ + x = ADD_LONG( x, args[4] ); + cff_builder_add_point( builder, x, y, 0 ); + + /* fourth control point */ + x = ADD_LONG( x, args[5] ); + y = start_y; + cff_builder_add_point( builder, x, y, 0 ); + + /* ending point, with y-value the same as the start point's */ + /* y-value -- we don't add this point, though */ + x = ADD_LONG( x, args[6] ); + cff_builder_add_point( builder, x, y, 1 ); + + args = stack; + break; + } + + case cff_op_flex1: + { + FT_Pos start_x, start_y; /* record start x, y values for */ + /* alter use */ + FT_Fixed dx = 0, dy = 0; /* used in horizontal/vertical */ + /* algorithm below */ + FT_Int horizontal, count; + FT_Fixed* temp; + + + FT_TRACE4(( " flex1\n" )); + + /* adding six more points; 4 control points, 2 on-curve points */ + if ( cff_builder_start_point( builder, x, y ) || + cff_check_points( builder, 6 ) ) + goto Fail; + + /* record the starting point's x, y position for later use */ + start_x = x; + start_y = y; + + /* XXX: figure out whether this is supposed to be a horizontal */ + /* or vertical flex; the Type 2 specification is vague... */ + + temp = args; + + /* grab up to the last argument */ + for ( count = 5; count > 0; count-- ) + { + dx = ADD_LONG( dx, temp[0] ); + dy = ADD_LONG( dy, temp[1] ); + temp += 2; + } + + if ( dx < 0 ) + dx = -dx; + if ( dy < 0 ) + dy = -dy; + + /* strange test, but here it is... */ + horizontal = ( dx > dy ); + + for ( count = 5; count > 0; count-- ) + { + x = ADD_LONG( x, args[0] ); + y = ADD_LONG( y, args[1] ); + cff_builder_add_point( builder, x, y, + (FT_Bool)( count == 3 ) ); + args += 2; + } + + /* is last operand an x- or y-delta? */ + if ( horizontal ) + { + x = ADD_LONG( x, args[0] ); + y = start_y; + } + else + { + x = start_x; + y = ADD_LONG( y, args[0] ); + } + + cff_builder_add_point( builder, x, y, 1 ); + + args = stack; + break; + } + + case cff_op_flex: + { + FT_UInt count; + + + FT_TRACE4(( " flex\n" )); + + if ( cff_builder_start_point( builder, x, y ) || + cff_check_points( builder, 6 ) ) + goto Fail; + + for ( count = 6; count > 0; count-- ) + { + x = ADD_LONG( x, args[0] ); + y = ADD_LONG( y, args[1] ); + cff_builder_add_point( builder, x, y, + (FT_Bool)( count == 4 || count == 1 ) ); + args += 2; + } + + args = stack; + } + break; + + case cff_op_seac: + FT_TRACE4(( " seac\n" )); + + error = cff_operator_seac( decoder, + args[0], args[1], args[2], + (FT_Int)( args[3] >> 16 ), + (FT_Int)( args[4] >> 16 ) ); + + /* add current outline to the glyph slot */ + FT_GlyphLoader_Add( builder->loader ); + + /* return now! */ + FT_TRACE4(( "\n" )); + return error; + + case cff_op_endchar: + /* in dictionaries, `endchar' simply indicates end of data */ + if ( in_dict ) + return error; + + FT_TRACE4(( " endchar\n" )); + + /* We are going to emulate the seac operator. */ + if ( num_args >= 4 ) + { + /* Save glyph width so that the subglyphs don't overwrite it. */ + FT_Pos glyph_width = decoder->glyph_width; + + + error = cff_operator_seac( decoder, + 0L, args[-4], args[-3], + (FT_Int)( args[-2] >> 16 ), + (FT_Int)( args[-1] >> 16 ) ); + + decoder->glyph_width = glyph_width; + } + else + { + cff_builder_close_contour( builder ); + + /* close hints recording session */ + if ( hinter ) + { + if ( hinter->close( hinter->hints, + (FT_UInt)builder->current->n_points ) ) + goto Syntax_Error; + + /* apply hints to the loaded glyph outline now */ + error = hinter->apply( hinter->hints, + builder->current, + (PSH_Globals)builder->hints_globals, + decoder->hint_mode ); + if ( error ) + goto Fail; + } + + /* add current outline to the glyph slot */ + FT_GlyphLoader_Add( builder->loader ); + } + + /* return now! */ + FT_TRACE4(( "\n" )); + return error; + + case cff_op_abs: + FT_TRACE4(( " abs\n" )); + + if ( args[0] < 0 ) + { + if ( args[0] == FT_LONG_MIN ) + args[0] = FT_LONG_MAX; + else + args[0] = -args[0]; + } + args++; + break; + + case cff_op_add: + FT_TRACE4(( " add\n" )); + + args[0] = ADD_LONG( args[0], args[1] ); + args++; + break; + + case cff_op_sub: + FT_TRACE4(( " sub\n" )); + + args[0] = SUB_LONG( args[0], args[1] ); + args++; + break; + + case cff_op_div: + FT_TRACE4(( " div\n" )); + + args[0] = FT_DivFix( args[0], args[1] ); + args++; + break; + + case cff_op_neg: + FT_TRACE4(( " neg\n" )); + + if ( args[0] == FT_LONG_MIN ) + args[0] = FT_LONG_MAX; + args[0] = -args[0]; + args++; + break; + + case cff_op_random: + FT_TRACE4(( " random\n" )); + + /* only use the lower 16 bits of `random' */ + /* to generate a number in the range (0;1] */ + args[0] = (FT_Fixed) + ( ( decoder->current_subfont->random & 0xFFFF ) + 1 ); + args++; + + decoder->current_subfont->random = + cff_random( decoder->current_subfont->random ); + break; + + case cff_op_mul: + FT_TRACE4(( " mul\n" )); + + args[0] = FT_MulFix( args[0], args[1] ); + args++; + break; + + case cff_op_sqrt: + FT_TRACE4(( " sqrt\n" )); + + if ( args[0] > 0 ) + { + FT_Fixed root = args[0]; + FT_Fixed new_root; + + + for (;;) + { + new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1; + if ( new_root == root ) + break; + root = new_root; + } + args[0] = new_root; + } + else + args[0] = 0; + args++; + break; + + case cff_op_drop: + /* nothing */ + FT_TRACE4(( " drop\n" )); + + break; + + case cff_op_exch: + { + FT_Fixed tmp; + + + FT_TRACE4(( " exch\n" )); + + tmp = args[0]; + args[0] = args[1]; + args[1] = tmp; + args += 2; + } + break; + + case cff_op_index: + { + FT_Int idx = (FT_Int)( args[0] >> 16 ); + + + FT_TRACE4(( " index\n" )); + + if ( idx < 0 ) + idx = 0; + else if ( idx > num_args - 2 ) + idx = num_args - 2; + args[0] = args[-( idx + 1 )]; + args++; + } + break; + + case cff_op_roll: + { + FT_Int count = (FT_Int)( args[0] >> 16 ); + FT_Int idx = (FT_Int)( args[1] >> 16 ); + + + FT_TRACE4(( " roll\n" )); + + if ( count <= 0 ) + count = 1; + + args -= count; + if ( args < stack ) + goto Stack_Underflow; + + if ( idx >= 0 ) + { + while ( idx > 0 ) + { + FT_Fixed tmp = args[count - 1]; + FT_Int i; + + + for ( i = count - 2; i >= 0; i-- ) + args[i + 1] = args[i]; + args[0] = tmp; + idx--; + } + } + else + { + while ( idx < 0 ) + { + FT_Fixed tmp = args[0]; + FT_Int i; + + + for ( i = 0; i < count - 1; i++ ) + args[i] = args[i + 1]; + args[count - 1] = tmp; + idx++; + } + } + args += count; + } + break; + + case cff_op_dup: + FT_TRACE4(( " dup\n" )); + + args[1] = args[0]; + args += 2; + break; + + case cff_op_put: + { + FT_Fixed val = args[0]; + FT_Int idx = (FT_Int)( args[1] >> 16 ); + + + FT_TRACE4(( " put\n" )); + + /* the Type2 specification before version 16-March-2000 */ + /* didn't give a hard-coded size limit of the temporary */ + /* storage array; instead, an argument of the */ + /* `MultipleMaster' operator set the size */ + if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS ) + decoder->buildchar[idx] = val; + } + break; + + case cff_op_get: + { + FT_Int idx = (FT_Int)( args[0] >> 16 ); + FT_Fixed val = 0; + + + FT_TRACE4(( " get\n" )); + + if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS ) + val = decoder->buildchar[idx]; + + args[0] = val; + args++; + } + break; + + case cff_op_store: + /* this operator was removed from the Type2 specification */ + /* in version 16-March-2000 */ + + /* since we currently don't handle interpolation of multiple */ + /* master fonts, this is a no-op */ + FT_TRACE4(( " store\n" )); + break; + + case cff_op_load: + /* this operator was removed from the Type2 specification */ + /* in version 16-March-2000 */ + { + FT_Int reg_idx = (FT_Int)args[0]; + FT_Int idx = (FT_Int)args[1]; + FT_Int count = (FT_Int)args[2]; + + + FT_TRACE4(( " load\n" )); + + /* since we currently don't handle interpolation of multiple */ + /* master fonts, we store a vector [1 0 0 ...] in the */ + /* temporary storage array regardless of the Registry index */ + if ( reg_idx >= 0 && reg_idx <= 2 && + idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS && + count >= 0 && count <= num_axes ) + { + FT_Int end, i; + + + end = FT_MIN( idx + count, CFF_MAX_TRANS_ELEMENTS ); + + if ( idx < end ) + decoder->buildchar[idx] = 1 << 16; + + for ( i = idx + 1; i < end; i++ ) + decoder->buildchar[i] = 0; + } + } + break; + + case cff_op_blend: + /* this operator was removed from the Type2 specification */ + /* in version 16-March-2000 */ + { + FT_Int num_results = (FT_Int)( args[0] >> 16 ); + + + FT_TRACE4(( " blend\n" )); + + if ( num_results < 0 ) + goto Syntax_Error; + + if ( num_results * (FT_Int)num_designs > num_args ) + goto Stack_Underflow; + + /* since we currently don't handle interpolation of multiple */ + /* master fonts, return the `num_results' values of the */ + /* first master */ + args -= num_results * ( num_designs - 1 ); + num_args -= num_results * ( num_designs - 1 ); + } + break; + + case cff_op_dotsection: + /* this operator is deprecated and ignored by the parser */ + FT_TRACE4(( " dotsection\n" )); + break; + + case cff_op_closepath: + /* this is an invalid Type 2 operator; however, there */ + /* exist fonts which are incorrectly converted from probably */ + /* Type 1 to CFF, and some parsers seem to accept it */ + + FT_TRACE4(( " closepath (invalid op)\n" )); + + args = stack; + break; + + case cff_op_hsbw: + /* this is an invalid Type 2 operator; however, there */ + /* exist fonts which are incorrectly converted from probably */ + /* Type 1 to CFF, and some parsers seem to accept it */ + + FT_TRACE4(( " hsbw (invalid op)\n" )); + + decoder->glyph_width = + ADD_LONG( decoder->nominal_width, ( args[1] >> 16 ) ); + + decoder->builder.left_bearing.x = args[0]; + decoder->builder.left_bearing.y = 0; + + x = ADD_LONG( decoder->builder.pos_x, args[0] ); + y = decoder->builder.pos_y; + args = stack; + break; + + case cff_op_sbw: + /* this is an invalid Type 2 operator; however, there */ + /* exist fonts which are incorrectly converted from probably */ + /* Type 1 to CFF, and some parsers seem to accept it */ + + FT_TRACE4(( " sbw (invalid op)\n" )); + + decoder->glyph_width = + ADD_LONG( decoder->nominal_width, ( args[2] >> 16 ) ); + + decoder->builder.left_bearing.x = args[0]; + decoder->builder.left_bearing.y = args[1]; + + x = ADD_LONG( decoder->builder.pos_x, args[0] ); + y = ADD_LONG( decoder->builder.pos_y, args[1] ); + args = stack; + break; + + case cff_op_setcurrentpoint: + /* this is an invalid Type 2 operator; however, there */ + /* exist fonts which are incorrectly converted from probably */ + /* Type 1 to CFF, and some parsers seem to accept it */ + + FT_TRACE4(( " setcurrentpoint (invalid op)\n" )); + + x = ADD_LONG( decoder->builder.pos_x, args[0] ); + y = ADD_LONG( decoder->builder.pos_y, args[1] ); + args = stack; + break; + + case cff_op_callothersubr: + /* this is an invalid Type 2 operator; however, there */ + /* exist fonts which are incorrectly converted from probably */ + /* Type 1 to CFF, and some parsers seem to accept it */ + + FT_TRACE4(( " callothersubr (invalid op)\n" )); + + /* subsequent `pop' operands should add the arguments, */ + /* this is the implementation described for `unknown' other */ + /* subroutines in the Type1 spec. */ + /* */ + /* XXX Fix return arguments (see discussion below). */ + args -= 2 + ( args[-2] >> 16 ); + if ( args < stack ) + goto Stack_Underflow; + break; + + case cff_op_pop: + /* this is an invalid Type 2 operator; however, there */ + /* exist fonts which are incorrectly converted from probably */ + /* Type 1 to CFF, and some parsers seem to accept it */ + + FT_TRACE4(( " pop (invalid op)\n" )); + + /* XXX Increasing `args' is wrong: After a certain number of */ + /* `pop's we get a stack overflow. Reason for doing it is */ + /* code like this (actually found in a CFF font): */ + /* */ + /* 17 1 3 callothersubr */ + /* pop */ + /* callsubr */ + /* */ + /* Since we handle `callothersubr' as a no-op, and */ + /* `callsubr' needs at least one argument, `pop' can't be a */ + /* no-op too as it basically should be. */ + /* */ + /* The right solution would be to provide real support for */ + /* `callothersubr' as done in `t1decode.c', however, given */ + /* the fact that CFF fonts with `pop' are invalid, it is */ + /* questionable whether it is worth the time. */ + args++; + break; + + case cff_op_and: + { + FT_Fixed cond = ( args[0] && args[1] ); + + + FT_TRACE4(( " and\n" )); + + args[0] = cond ? 0x10000L : 0; + args++; + } + break; + + case cff_op_or: + { + FT_Fixed cond = ( args[0] || args[1] ); + + + FT_TRACE4(( " or\n" )); + + args[0] = cond ? 0x10000L : 0; + args++; + } + break; + + case cff_op_not: + { + FT_Fixed cond = !args[0]; + + + FT_TRACE4(( " not\n" )); + + args[0] = cond ? 0x10000L : 0; + args++; + } + break; + + case cff_op_eq: + { + FT_Fixed cond = ( args[0] == args[1] ); + + + FT_TRACE4(( " eq\n" )); + + args[0] = cond ? 0x10000L : 0; + args++; + } + break; + + case cff_op_ifelse: + { + FT_Fixed cond = ( args[2] <= args[3] ); + + + FT_TRACE4(( " ifelse\n" )); + + if ( !cond ) + args[0] = args[1]; + args++; + } + break; + + case cff_op_callsubr: + { + FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) + + decoder->locals_bias ); + + + FT_TRACE4(( " callsubr (idx %d, entering level %d)\n", + idx, + zone - decoder->zones + 1 )); + + if ( idx >= decoder->num_locals ) + { + FT_ERROR(( "cff_decoder_parse_charstrings:" + " invalid local subr index\n" )); + goto Syntax_Error; + } + + if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS ) + { + FT_ERROR(( "cff_decoder_parse_charstrings:" + " too many nested subrs\n" )); + goto Syntax_Error; + } + + zone->cursor = ip; /* save current instruction pointer */ + + zone++; + zone->base = decoder->locals[idx]; + zone->limit = decoder->locals[idx + 1]; + zone->cursor = zone->base; + + if ( !zone->base || zone->limit == zone->base ) + { + FT_ERROR(( "cff_decoder_parse_charstrings:" + " invoking empty subrs\n" )); + goto Syntax_Error; + } + + decoder->zone = zone; + ip = zone->base; + limit = zone->limit; + } + break; + + case cff_op_callgsubr: + { + FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) + + decoder->globals_bias ); + + + FT_TRACE4(( " callgsubr (idx %d, entering level %d)\n", + idx, + zone - decoder->zones + 1 )); + + if ( idx >= decoder->num_globals ) + { + FT_ERROR(( "cff_decoder_parse_charstrings:" + " invalid global subr index\n" )); + goto Syntax_Error; + } + + if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS ) + { + FT_ERROR(( "cff_decoder_parse_charstrings:" + " too many nested subrs\n" )); + goto Syntax_Error; + } + + zone->cursor = ip; /* save current instruction pointer */ + + zone++; + zone->base = decoder->globals[idx]; + zone->limit = decoder->globals[idx + 1]; + zone->cursor = zone->base; + + if ( !zone->base || zone->limit == zone->base ) + { + FT_ERROR(( "cff_decoder_parse_charstrings:" + " invoking empty subrs\n" )); + goto Syntax_Error; + } + + decoder->zone = zone; + ip = zone->base; + limit = zone->limit; + } + break; + + case cff_op_return: + FT_TRACE4(( " return (leaving level %d)\n", + decoder->zone - decoder->zones )); + + if ( decoder->zone <= decoder->zones ) + { + FT_ERROR(( "cff_decoder_parse_charstrings:" + " unexpected return\n" )); + goto Syntax_Error; + } + + decoder->zone--; + zone = decoder->zone; + ip = zone->cursor; + limit = zone->limit; + break; + + default: + FT_ERROR(( "Unimplemented opcode: %d", ip[-1] )); + + if ( ip[-1] == 12 ) + FT_ERROR(( " %d", ip[0] )); + FT_ERROR(( "\n" )); + + return FT_THROW( Unimplemented_Feature ); + } + + decoder->top = args; + + if ( decoder->top - stack >= CFF_MAX_OPERANDS ) + goto Stack_Overflow; + + } /* general operator processing */ + + } /* while ip < limit */ + + FT_TRACE4(( "..end..\n\n" )); + + Fail: + return error; + + MM_Error: + FT_TRACE4(( "cff_decoder_parse_charstrings:" + " invalid opcode found in top DICT charstring\n")); + return FT_THROW( Invalid_File_Format ); + + Syntax_Error: + FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error\n" )); + return FT_THROW( Invalid_File_Format ); + + Stack_Underflow: + FT_TRACE4(( "cff_decoder_parse_charstrings: stack underflow\n" )); + return FT_THROW( Too_Few_Arguments ); + + Stack_Overflow: + FT_TRACE4(( "cff_decoder_parse_charstrings: stack overflow\n" )); + return FT_THROW( Stack_Overflow ); + } + +#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* cff_decoder_init */ + /* */ + /* <Description> */ + /* Initializes a given glyph decoder. */ + /* */ + /* <InOut> */ + /* decoder :: A pointer to the glyph builder to initialize. */ + /* */ + /* <Input> */ + /* face :: The current face object. */ + /* */ + /* size :: The current size object. */ + /* */ + /* slot :: The current glyph object. */ + /* */ + /* hinting :: Whether hinting is active. */ + /* */ + /* hint_mode :: The hinting mode. */ + /* */ + FT_LOCAL_DEF( void ) + cff_decoder_init( CFF_Decoder* decoder, + TT_Face face, + CFF_Size size, + CFF_GlyphSlot slot, + FT_Bool hinting, + FT_Render_Mode hint_mode, + CFF_Decoder_Get_Glyph_Callback get_callback, + CFF_Decoder_Free_Glyph_Callback free_callback ) + { + CFF_Font cff = (CFF_Font)face->extra.data; + + + /* clear everything */ + FT_ZERO( decoder ); + + /* initialize builder */ + cff_builder_init( &decoder->builder, face, size, slot, hinting ); + + /* initialize Type2 decoder */ + decoder->cff = cff; + decoder->num_globals = cff->global_subrs_index.count; + decoder->globals = cff->global_subrs; + decoder->globals_bias = cff_compute_bias( + cff->top_font.font_dict.charstring_type, + decoder->num_globals ); + + decoder->hint_mode = hint_mode; + + decoder->get_glyph_callback = get_callback; + decoder->free_glyph_callback = free_callback; + } + + + /* this function is used to select the subfont */ + /* and the locals subrs array */ + FT_LOCAL_DEF( FT_Error ) + cff_decoder_prepare( CFF_Decoder* decoder, + CFF_Size size, + FT_UInt glyph_index ) + { + CFF_Builder *builder = &decoder->builder; + CFF_Font cff = (CFF_Font)builder->face->extra.data; + CFF_SubFont sub = &cff->top_font; + FT_Error error = FT_Err_Ok; + + FT_Service_CFFLoad cffload = (FT_Service_CFFLoad)cff->cffload; + + + /* manage CID fonts */ + if ( cff->num_subfonts ) + { + FT_Byte fd_index = cffload->fd_select_get( &cff->fd_select, + glyph_index ); + + + if ( fd_index >= cff->num_subfonts ) + { + FT_TRACE4(( "cff_decoder_prepare: invalid CID subfont index\n" )); + error = FT_THROW( Invalid_File_Format ); + goto Exit; + } + + FT_TRACE3(( " in subfont %d:\n", fd_index )); + + sub = cff->subfonts[fd_index]; + + if ( builder->hints_funcs && size ) + { + FT_Size ftsize = FT_SIZE( size ); + CFF_Internal internal = (CFF_Internal)ftsize->internal->module_data; + + + /* for CFFs without subfonts, this value has already been set */ + builder->hints_globals = (void *)internal->subfonts[fd_index]; + } + } + + decoder->num_locals = sub->local_subrs_index.count; + decoder->locals = sub->local_subrs; + decoder->locals_bias = cff_compute_bias( + decoder->cff->top_font.font_dict.charstring_type, + decoder->num_locals ); + + decoder->glyph_width = sub->private_dict.default_width; + decoder->nominal_width = sub->private_dict.nominal_width; + + decoder->current_subfont = sub; + + Exit: + return error; + } + + +/* END */ diff --git a/modules/freetype2/src/psaux/cffdecode.h b/modules/freetype2/src/psaux/cffdecode.h new file mode 100644 index 000000000..0d4f5fef6 --- /dev/null +++ b/modules/freetype2/src/psaux/cffdecode.h @@ -0,0 +1,64 @@ +/***************************************************************************/ +/* */ +/* cffdecode.h */ +/* */ +/* PostScript CFF (Type 2) decoding routines (specification). */ +/* */ +/* Copyright 2017-2018 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 CFFDECODE_H_ +#define CFFDECODE_H_ + + +#include <ft2build.h> +#include FT_INTERNAL_POSTSCRIPT_AUX_H + + +FT_BEGIN_HEADER + + FT_LOCAL( void ) + cff_decoder_init( CFF_Decoder* decoder, + TT_Face face, + CFF_Size size, + CFF_GlyphSlot slot, + FT_Bool hinting, + FT_Render_Mode hint_mode, + CFF_Decoder_Get_Glyph_Callback get_callback, + CFF_Decoder_Free_Glyph_Callback free_callback ); + + FT_LOCAL( FT_Error ) + cff_decoder_prepare( CFF_Decoder* decoder, + CFF_Size size, + FT_UInt glyph_index ); + + + FT_LOCAL( FT_Int ) + cff_lookup_glyph_by_stdcharcode( CFF_Font cff, + FT_Int charcode ); + + +#ifdef CFF_CONFIG_OPTION_OLD_ENGINE + FT_LOCAL( FT_Error ) + cff_decoder_parse_charstrings( CFF_Decoder* decoder, + FT_Byte* charstring_base, + FT_ULong charstring_len, + FT_Bool in_dict ); +#endif + + +FT_END_HEADER + +#endif + + +/* END */ diff --git a/modules/freetype2/src/psaux/module.mk b/modules/freetype2/src/psaux/module.mk index 630c4f39d..6584d075a 100644 --- a/modules/freetype2/src/psaux/module.mk +++ b/modules/freetype2/src/psaux/module.mk @@ -3,7 +3,7 @@ # -# Copyright 1996-2016 by +# Copyright 1996-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/cff/cf2arrst.c b/modules/freetype2/src/psaux/psarrst.c index 6796450fe..a8780947f 100644 --- a/modules/freetype2/src/cff/cf2arrst.c +++ b/modules/freetype2/src/psaux/psarrst.c @@ -1,6 +1,6 @@ /***************************************************************************/ /* */ -/* cf2arrst.c */ +/* psarrst.c */ /* */ /* Adobe's code for Array Stacks (body). */ /* */ @@ -36,13 +36,13 @@ /***************************************************************************/ -#include "cf2ft.h" +#include "psft.h" #include FT_INTERNAL_DEBUG_H -#include "cf2glue.h" -#include "cf2arrst.h" +#include "psglue.h" +#include "psarrst.h" -#include "cf2error.h" +#include "pserror.h" /* diff --git a/modules/freetype2/src/cff/cf2arrst.h b/modules/freetype2/src/psaux/psarrst.h index 3c21a3b67..b3568eb61 100644 --- a/modules/freetype2/src/cff/cf2arrst.h +++ b/modules/freetype2/src/psaux/psarrst.h @@ -1,6 +1,6 @@ /***************************************************************************/ /* */ -/* cf2arrst.h */ +/* psarrst.h */ /* */ /* Adobe's code for Array Stacks (specification). */ /* */ @@ -36,11 +36,11 @@ /***************************************************************************/ -#ifndef CF2ARRST_H_ -#define CF2ARRST_H_ +#ifndef PSARRST_H_ +#define PSARRST_H_ -#include "cf2error.h" +#include "pserror.h" FT_BEGIN_HEADER @@ -94,7 +94,7 @@ FT_BEGIN_HEADER FT_END_HEADER -#endif /* CF2ARRST_H_ */ +#endif /* PSARRST_H_ */ /* END */ diff --git a/modules/freetype2/src/psaux/psaux.c b/modules/freetype2/src/psaux/psaux.c index 33b462ef1..fb447fcdb 100644 --- a/modules/freetype2/src/psaux/psaux.c +++ b/modules/freetype2/src/psaux/psaux.c @@ -4,7 +4,7 @@ /* */ /* FreeType auxiliary PostScript driver component (body only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,18 +17,25 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT - #include <ft2build.h> -#include "psobjs.c" -#include "psauxmod.c" -#include "t1decode.c" -#include "t1cmap.c" -#ifndef T1_CONFIG_OPTION_NO_AFM #include "afmparse.c" -#endif - +#include "psauxmod.c" #include "psconv.c" +#include "psobjs.c" +#include "t1cmap.c" +#include "t1decode.c" +#include "cffdecode.c" + +#include "psarrst.c" +#include "psblues.c" +#include "pserror.c" +#include "psfont.c" +#include "psft.c" +#include "pshints.c" +#include "psintrp.c" +#include "psread.c" +#include "psstack.c" /* END */ diff --git a/modules/freetype2/src/psaux/psauxerr.h b/modules/freetype2/src/psaux/psauxerr.h index 9739157fc..cc33fd2ee 100644 --- a/modules/freetype2/src/psaux/psauxerr.h +++ b/modules/freetype2/src/psaux/psauxerr.h @@ -4,7 +4,7 @@ /* */ /* PS auxiliary module error codes (specification only). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/psaux/psauxmod.c b/modules/freetype2/src/psaux/psauxmod.c index b1b8b19c3..ee497085c 100644 --- a/modules/freetype2/src/psaux/psauxmod.c +++ b/modules/freetype2/src/psaux/psauxmod.c @@ -4,7 +4,7 @@ /* */ /* FreeType auxiliary PostScript module implementation (body). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -21,6 +21,8 @@ #include "psobjs.h" #include "t1decode.h" #include "t1cmap.h" +#include "psft.h" +#include "cffdecode.h" #ifndef T1_CONFIG_OPTION_NO_AFM #include "afmparse.h" @@ -60,6 +62,14 @@ FT_CALLBACK_TABLE_DEF + const PS_Builder_FuncsRec ps_builder_funcs = + { + ps_builder_init, /* init */ + ps_builder_done /* done */ + }; + + + FT_CALLBACK_TABLE_DEF const T1_Builder_FuncsRec t1_builder_funcs = { t1_builder_init, /* init */ @@ -77,9 +87,14 @@ FT_CALLBACK_TABLE_DEF const T1_Decoder_FuncsRec t1_decoder_funcs = { - t1_decoder_init, /* init */ - t1_decoder_done, /* done */ - t1_decoder_parse_charstrings /* parse_charstrings */ + t1_decoder_init, /* init */ + t1_decoder_done, /* done */ +#ifdef T1_CONFIG_OPTION_OLD_ENGINE + t1_decoder_parse_charstrings, /* parse_charstrings_old */ +#else + t1_decoder_parse_metrics, /* parse_metrics */ +#endif + cf2_decoder_parse_charstrings /* parse_charstrings */ }; @@ -104,6 +119,34 @@ }; + FT_CALLBACK_TABLE_DEF + const CFF_Builder_FuncsRec cff_builder_funcs = + { + cff_builder_init, /* init */ + cff_builder_done, /* done */ + + cff_check_points, /* check_points */ + cff_builder_add_point, /* add_point */ + cff_builder_add_point1, /* add_point1 */ + cff_builder_add_contour, /* add_contour */ + cff_builder_start_point, /* start_point */ + cff_builder_close_contour /* close_contour */ + }; + + + FT_CALLBACK_TABLE_DEF + const CFF_Decoder_FuncsRec cff_decoder_funcs = + { + cff_decoder_init, /* init */ + cff_decoder_prepare, /* prepare */ + +#ifdef CFF_CONFIG_OPTION_OLD_ENGINE + cff_decoder_parse_charstrings, /* parse_charstrings_old */ +#endif + cf2_decoder_parse_charstrings /* parse_charstrings */ + }; + + static const PSAux_Interface psaux_interface = { @@ -112,6 +155,9 @@ &t1_builder_funcs, &t1_decoder_funcs, t1_decrypt, + cff_random, + ps_decoder_init, + t1_make_subfont, (const T1_CMap_ClassesRec*) &t1_cmap_classes, @@ -120,6 +166,8 @@ #else 0, #endif + + &cff_decoder_funcs, }; diff --git a/modules/freetype2/src/psaux/psauxmod.h b/modules/freetype2/src/psaux/psauxmod.h index b1dbb0690..f30978f02 100644 --- a/modules/freetype2/src/psaux/psauxmod.h +++ b/modules/freetype2/src/psaux/psauxmod.h @@ -4,7 +4,7 @@ /* */ /* FreeType auxiliary PostScript module implementation (specification). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -23,6 +23,8 @@ #include <ft2build.h> #include FT_MODULE_H +#include FT_INTERNAL_POSTSCRIPT_AUX_H + FT_BEGIN_HEADER @@ -31,6 +33,13 @@ FT_BEGIN_HEADER #endif + FT_CALLBACK_TABLE + const CFF_Builder_FuncsRec cff_builder_funcs; + + FT_CALLBACK_TABLE + const PS_Builder_FuncsRec ps_builder_funcs; + + FT_EXPORT_VAR( const FT_Module_Class ) psaux_driver_class; diff --git a/modules/freetype2/src/cff/cf2blues.c b/modules/freetype2/src/psaux/psblues.c index 250f89e0d..ae39d03c7 100644 --- a/modules/freetype2/src/cff/cf2blues.c +++ b/modules/freetype2/src/psaux/psblues.c @@ -1,6 +1,6 @@ /***************************************************************************/ /* */ -/* cf2blues.c */ +/* psblues.c */ /* */ /* Adobe's code for handling Blue Zones (body). */ /* */ @@ -36,12 +36,12 @@ /***************************************************************************/ -#include "cf2ft.h" +#include "psft.h" #include FT_INTERNAL_DEBUG_H -#include "cf2blues.h" -#include "cf2hints.h" -#include "cf2font.h" +#include "psblues.h" +#include "pshints.h" +#include "psfont.h" /*************************************************************************/ @@ -67,7 +67,7 @@ CF2_Font font ) { /* pointer to parsed font object */ - CFF_Decoder* decoder = font->decoder; + PS_Decoder* decoder = font->decoder; CF2_Fixed zoneHeight; CF2_Fixed maxZoneHeight = 0; @@ -194,8 +194,8 @@ blues->zone[blues->count].csTopEdge = cf2_blueToFixed( blueValues[i + 1] ); - zoneHeight = blues->zone[blues->count].csTopEdge - - blues->zone[blues->count].csBottomEdge; + zoneHeight = SUB_INT32( blues->zone[blues->count].csTopEdge, + blues->zone[blues->count].csBottomEdge ); if ( zoneHeight < 0 ) { @@ -243,8 +243,8 @@ blues->zone[blues->count].csTopEdge = cf2_blueToFixed( otherBlues[i + 1] ); - zoneHeight = blues->zone[blues->count].csTopEdge - - blues->zone[blues->count].csBottomEdge; + zoneHeight = SUB_INT32( blues->zone[blues->count].csTopEdge, + blues->zone[blues->count].csBottomEdge ); if ( zoneHeight < 0 ) { @@ -301,7 +301,7 @@ /* top edge */ flatFamilyEdge = cf2_blueToFixed( familyOtherBlues[j + 1] ); - diff = cf2_fixedAbs( flatEdge - flatFamilyEdge ); + diff = cf2_fixedAbs( SUB_INT32( flatEdge, flatFamilyEdge ) ); if ( diff < minDiff && diff < csUnitsPerPixel ) { @@ -319,7 +319,7 @@ /* top edge */ flatFamilyEdge = cf2_blueToFixed( familyBlues[1] ); - diff = cf2_fixedAbs( flatEdge - flatFamilyEdge ); + diff = cf2_fixedAbs( SUB_INT32( flatEdge, flatFamilyEdge ) ); if ( diff < minDiff && diff < csUnitsPerPixel ) blues->zone[i].csFlatEdge = flatFamilyEdge; @@ -342,7 +342,7 @@ /* adjust edges of top zone upward by twice darkening amount */ flatFamilyEdge += 2 * font->darkenY; /* bottom edge */ - diff = cf2_fixedAbs( flatEdge - flatFamilyEdge ); + diff = cf2_fixedAbs( SUB_INT32( flatEdge, flatFamilyEdge ) ); if ( diff < minDiff && diff < csUnitsPerPixel ) { @@ -408,8 +408,8 @@ /* Note: constant changed from 0.5 to 0.6 to avoid a problem with */ /* 10ppem Arial */ - blues->boost = cf2_floatToFixed( .6 ) - - FT_MulDiv( cf2_floatToFixed ( .6 ), + blues->boost = cf2_doubleToFixed( .6 ) - + FT_MulDiv( cf2_doubleToFixed ( .6 ), blues->scale, blues->blueScale ); if ( blues->boost > 0x7FFF ) @@ -489,17 +489,18 @@ if ( blues->zone[i].bottomZone && cf2_hint_isBottom( bottomHintEdge ) ) { - if ( ( blues->zone[i].csBottomEdge - csFuzz ) <= - bottomHintEdge->csCoord && + if ( SUB_INT32( blues->zone[i].csBottomEdge, csFuzz ) <= + bottomHintEdge->csCoord && bottomHintEdge->csCoord <= - ( blues->zone[i].csTopEdge + csFuzz ) ) + ADD_INT32( blues->zone[i].csTopEdge, csFuzz ) ) { /* bottom edge captured by bottom zone */ if ( blues->suppressOvershoot ) dsNew = blues->zone[i].dsFlatEdge; - else if ( ( blues->zone[i].csTopEdge - bottomHintEdge->csCoord ) >= + else if ( SUB_INT32( blues->zone[i].csTopEdge, + bottomHintEdge->csCoord ) >= blues->blueShift ) { /* guarantee minimum of 1 pixel overshoot */ @@ -514,7 +515,7 @@ dsNew = cf2_fixedRound( bottomHintEdge->dsCoord ); } - dsMove = dsNew - bottomHintEdge->dsCoord; + dsMove = SUB_INT32( dsNew, bottomHintEdge->dsCoord ); captured = TRUE; break; @@ -523,17 +524,18 @@ if ( !blues->zone[i].bottomZone && cf2_hint_isTop( topHintEdge ) ) { - if ( ( blues->zone[i].csBottomEdge - csFuzz ) <= - topHintEdge->csCoord && + if ( SUB_INT32( blues->zone[i].csBottomEdge, csFuzz ) <= + topHintEdge->csCoord && topHintEdge->csCoord <= - ( blues->zone[i].csTopEdge + csFuzz ) ) + ADD_INT32( blues->zone[i].csTopEdge, csFuzz ) ) { /* top edge captured by top zone */ if ( blues->suppressOvershoot ) dsNew = blues->zone[i].dsFlatEdge; - else if ( ( topHintEdge->csCoord - blues->zone[i].csBottomEdge ) >= + else if ( SUB_INT32( topHintEdge->csCoord, + blues->zone[i].csBottomEdge ) >= blues->blueShift ) { /* guarantee minimum of 1 pixel overshoot */ @@ -548,7 +550,7 @@ dsNew = cf2_fixedRound( topHintEdge->dsCoord ); } - dsMove = dsNew - topHintEdge->dsCoord; + dsMove = SUB_INT32( dsNew, topHintEdge->dsCoord ); captured = TRUE; break; @@ -561,13 +563,14 @@ /* move both edges and flag them `locked' */ if ( cf2_hint_isValid( bottomHintEdge ) ) { - bottomHintEdge->dsCoord += dsMove; + bottomHintEdge->dsCoord = ADD_INT32( bottomHintEdge->dsCoord, + dsMove ); cf2_hint_lock( bottomHintEdge ); } if ( cf2_hint_isValid( topHintEdge ) ) { - topHintEdge->dsCoord += dsMove; + topHintEdge->dsCoord = ADD_INT32( topHintEdge->dsCoord, dsMove ); cf2_hint_lock( topHintEdge ); } } diff --git a/modules/freetype2/src/cff/cf2blues.h b/modules/freetype2/src/psaux/psblues.h index 96fb60f38..25ef6849c 100644 --- a/modules/freetype2/src/cff/cf2blues.h +++ b/modules/freetype2/src/psaux/psblues.h @@ -1,6 +1,6 @@ /***************************************************************************/ /* */ -/* cf2blues.h */ +/* psblues.h */ /* */ /* Adobe's code for handling Blue Zones (specification). */ /* */ @@ -65,11 +65,11 @@ */ -#ifndef CF2BLUES_H_ -#define CF2BLUES_H_ +#ifndef PSBLUES_H_ +#define PSBLUES_H_ -#include "cf2glue.h" +#include "psglue.h" FT_BEGIN_HEADER @@ -111,7 +111,7 @@ FT_BEGIN_HEADER * Constant used for hint adjustment and for synthetic em box hint * placement. */ -#define CF2_MIN_COUNTER cf2_floatToFixed( 0.5 ) +#define CF2_MIN_COUNTER cf2_doubleToFixed( 0.5 ) /* shared typedef is in cf2glue.h */ @@ -179,7 +179,7 @@ FT_BEGIN_HEADER FT_END_HEADER -#endif /* CF2BLUES_H_ */ +#endif /* PSBLUES_H_ */ /* END */ diff --git a/modules/freetype2/src/psaux/psconv.c b/modules/freetype2/src/psaux/psconv.c index fdaca7fb5..a03385000 100644 --- a/modules/freetype2/src/psaux/psconv.c +++ b/modules/freetype2/src/psaux/psconv.c @@ -4,7 +4,7 @@ /* */ /* Some convenience conversions (body). */ /* */ -/* Copyright 2006-2016 by */ +/* Copyright 2006-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -111,6 +111,10 @@ p++; if ( p == limit ) goto Bad; + + /* only a single sign is allowed */ + if ( *p == '-' || *p == '+' ) + return 0; } num_limit = 0x7FFFFFFFL / base; @@ -215,6 +219,10 @@ p++; if ( p == limit ) goto Bad; + + /* only a single sign is allowed */ + if ( *p == '-' || *p == '+' ) + return 0; } /* read the integer part */ diff --git a/modules/freetype2/src/psaux/psconv.h b/modules/freetype2/src/psaux/psconv.h index 062de3641..d643ffcfc 100644 --- a/modules/freetype2/src/psaux/psconv.h +++ b/modules/freetype2/src/psaux/psconv.h @@ -4,7 +4,7 @@ /* */ /* Some convenience conversions (specification). */ /* */ -/* Copyright 2006-2016 by */ +/* Copyright 2006-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/cff/cf2error.c b/modules/freetype2/src/psaux/pserror.c index e3dd69f50..9169e5222 100644 --- a/modules/freetype2/src/cff/cf2error.c +++ b/modules/freetype2/src/psaux/pserror.c @@ -1,6 +1,6 @@ /***************************************************************************/ /* */ -/* cf2error.c */ +/* pserror.c */ /* */ /* Adobe's code for error handling (body). */ /* */ @@ -36,8 +36,8 @@ /***************************************************************************/ -#include "cf2ft.h" -#include "cf2error.h" +#include "psft.h" +#include "pserror.h" FT_LOCAL_DEF( void ) diff --git a/modules/freetype2/src/cff/cf2error.h b/modules/freetype2/src/psaux/pserror.h index 512edd1d2..13d52062b 100644 --- a/modules/freetype2/src/cff/cf2error.h +++ b/modules/freetype2/src/psaux/pserror.h @@ -1,6 +1,6 @@ /***************************************************************************/ /* */ -/* cf2error.h */ +/* pserror.h */ /* */ /* Adobe's code for error handling (specification). */ /* */ @@ -36,8 +36,8 @@ /***************************************************************************/ -#ifndef CF2ERROR_H_ -#define CF2ERROR_H_ +#ifndef PSERROR_H_ +#define PSERROR_H_ #include FT_MODULE_ERRORS_H @@ -50,7 +50,7 @@ #include FT_ERRORS_H -#include "cf2ft.h" +#include "psft.h" FT_BEGIN_HEADER @@ -66,7 +66,7 @@ FT_BEGIN_HEADER * model our error mechanism on a Java-like exception mechanism. * When we assign an error code we are thus `throwing' an error. * - * The perservation of an error code is done by coding convention. + * The preservation of an error code is done by coding convention. * Upon a function call if the error code is anything other than * `FT_Err_Ok', which is guaranteed to be zero, we * will return without altering that error. This will allow the @@ -113,7 +113,7 @@ FT_BEGIN_HEADER FT_END_HEADER -#endif /* CF2ERROR_H_ */ +#endif /* PSERROR_H_ */ /* END */ diff --git a/modules/freetype2/src/cff/cf2fixed.h b/modules/freetype2/src/psaux/psfixed.h index 2e4b5032f..219589e7f 100644 --- a/modules/freetype2/src/cff/cf2fixed.h +++ b/modules/freetype2/src/psaux/psfixed.h @@ -1,6 +1,6 @@ /***************************************************************************/ /* */ -/* cf2fixed.h */ +/* psfixed.h */ /* */ /* Adobe's code for Fixed Point Mathematics (specification only). */ /* */ @@ -36,8 +36,8 @@ /***************************************************************************/ -#ifndef CF2FIXED_H_ -#define CF2FIXED_H_ +#ifndef PSFIXED_H_ +#define PSFIXED_H_ FT_BEGIN_HEADER @@ -63,10 +63,10 @@ FT_BEGIN_HEADER ( (FT_Short)( ( (FT_UInt32)(x) + 0x8000U ) >> 16 ) ) #define cf2_fixedRound( x ) \ ( (CF2_Fixed)( ( (FT_UInt32)(x) + 0x8000U ) & 0xFFFF0000UL ) ) -#define cf2_floatToFixed( f ) \ +#define cf2_doubleToFixed( f ) \ ( (CF2_Fixed)( (f) * 65536.0 + 0.5 ) ) #define cf2_fixedAbs( x ) \ - ( (x) < 0 ? -(x) : (x) ) + ( (x) < 0 ? NEG_INT32( x ) : (x) ) #define cf2_fixedFloor( x ) \ ( (CF2_Fixed)( (FT_UInt32)(x) & 0xFFFF0000UL ) ) #define cf2_fixedFraction( x ) \ @@ -89,7 +89,7 @@ FT_BEGIN_HEADER FT_END_HEADER -#endif /* CF2FIXED_H_ */ +#endif /* PSFIXED_H_ */ /* END */ diff --git a/modules/freetype2/src/cff/cf2font.c b/modules/freetype2/src/psaux/psfont.c index a86e3619b..dde67a739 100644 --- a/modules/freetype2/src/cff/cf2font.c +++ b/modules/freetype2/src/psaux/psfont.c @@ -1,6 +1,6 @@ /***************************************************************************/ /* */ -/* cf2font.c */ +/* psfont.c */ /* */ /* Adobe's code for font instances (body). */ /* */ @@ -39,12 +39,12 @@ #include <ft2build.h> #include FT_INTERNAL_CALC_H -#include "cf2ft.h" +#include "psft.h" -#include "cf2glue.h" -#include "cf2font.h" -#include "cf2error.h" -#include "cf2intrp.h" +#include "psglue.h" +#include "psfont.h" +#include "pserror.h" +#include "psintrp.h" /* Compute a stem darkening amount in character space. */ @@ -117,7 +117,7 @@ return; /* protect against range problems and divide by zero */ - if ( emRatio < cf2_floatToFixed( .01 ) ) + if ( emRatio < cf2_doubleToFixed( .01 ) ) return; if ( stemDarkened ) @@ -243,7 +243,7 @@ const CF2_Matrix* transform ) { /* pointer to parsed font object */ - CFF_Decoder* decoder = font->decoder; + PS_Decoder* decoder = font->decoder; FT_Bool needExtraSetup = FALSE; @@ -260,7 +260,6 @@ CF2_UInt lenNormalizedV = 0; FT_Fixed* normalizedV = NULL; - /* clear previous error */ font->error = FT_Err_Ok; @@ -273,46 +272,52 @@ needExtraSetup = TRUE; } - /* check for variation vectors */ - vstore = cf2_getVStore( decoder ); - hasVariations = ( vstore->dataCount != 0 ); - - if ( hasVariations ) + if ( !font->isT1 ) { -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - /* check whether Private DICT in this subfont needs to be reparsed */ - font->error = cf2_getNormalizedVector( decoder, - &lenNormalizedV, - &normalizedV ); - if ( font->error ) - return; + FT_Service_CFFLoad cffload = (FT_Service_CFFLoad)font->cffload; + + + /* check for variation vectors */ + vstore = cf2_getVStore( decoder ); + hasVariations = ( vstore->dataCount != 0 ); - if ( cff_blend_check_vector( &subFont->blend, - subFont->private_dict.vsindex, - lenNormalizedV, - normalizedV ) ) + if ( hasVariations ) { - /* blend has changed, reparse */ - cff_load_private_dict( decoder->cff, - subFont, - lenNormalizedV, - normalizedV ); - needExtraSetup = TRUE; - } +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + /* check whether Private DICT in this subfont needs to be reparsed */ + font->error = cf2_getNormalizedVector( decoder, + &lenNormalizedV, + &normalizedV ); + if ( font->error ) + return; + + if ( cffload->blend_check_vector( &subFont->blend, + subFont->private_dict.vsindex, + lenNormalizedV, + normalizedV ) ) + { + /* blend has changed, reparse */ + cffload->load_private_dict( decoder->cff, + subFont, + lenNormalizedV, + normalizedV ); + needExtraSetup = TRUE; + } #endif - /* copy from subfont */ - font->blend.font = subFont->blend.font; + /* copy from subfont */ + font->blend.font = subFont->blend.font; - /* clear state of charstring blend */ - font->blend.usedBV = FALSE; + /* clear state of charstring blend */ + font->blend.usedBV = FALSE; - /* initialize value for charstring */ - font->vsindex = subFont->private_dict.vsindex; + /* initialize value for charstring */ + font->vsindex = subFont->private_dict.vsindex; - /* store vector inputs for blends in charstring */ - font->lenNDV = lenNormalizedV; - font->NDV = normalizedV; + /* store vector inputs for blends in charstring */ + font->lenNDV = lenNormalizedV; + font->NDV = normalizedV; + } } /* if ppem has changed, we need to recompute some cached data */ @@ -447,7 +452,7 @@ /* choose a constant for StdHW that depends on font contrast */ stdHW = cf2_getStdHW( decoder ); - if ( stdHW > 0 && font->stdVW > 2 * stdHW ) + if ( stdHW > 0 && font->stdVW > MUL_INT32( 2, stdHW ) ) font->stdHW = FT_DivFix( cf2_intToFixed( 75 ), emRatio ); else { diff --git a/modules/freetype2/src/cff/cf2font.h b/modules/freetype2/src/psaux/psfont.h index 17ecd17bb..e611ac4bd 100644 --- a/modules/freetype2/src/cff/cf2font.h +++ b/modules/freetype2/src/psaux/psfont.h @@ -1,6 +1,6 @@ /***************************************************************************/ /* */ -/* cf2font.h */ +/* psfont.h */ /* */ /* Adobe's code for font instances (specification). */ /* */ @@ -36,13 +36,14 @@ /***************************************************************************/ -#ifndef CF2FONT_H_ -#define CF2FONT_H_ +#ifndef PSFONT_H_ +#define PSFONT_H_ -#include "cf2ft.h" -#include "cf2blues.h" -#include "cffload.h" +#include FT_SERVICE_CFF_TABLE_LOAD_H + +#include "psft.h" +#include "psblues.h" FT_BEGIN_HEADER @@ -64,6 +65,7 @@ FT_BEGIN_HEADER FT_Memory memory; FT_Error error; /* shared error for this instance */ + FT_Bool isT1; FT_Bool isCFF2; CF2_RenderingFlags renderingFlags; @@ -89,7 +91,7 @@ FT_BEGIN_HEADER /* FreeType related members */ CF2_OutlineRec outline; /* freetype glyph outline functions */ - CFF_Decoder* decoder; + PS_Decoder* decoder; CFF_SubFont lastSubfont; /* FreeType parsed data; */ /* top font or subfont */ @@ -111,6 +113,8 @@ FT_BEGIN_HEADER /* counterclockwise winding */ CF2_BluesRec blues; /* computed zone data */ + + FT_Service_CFFLoad cffload; /* pointer to cff functions */ }; @@ -124,7 +128,7 @@ FT_BEGIN_HEADER FT_END_HEADER -#endif /* CF2FONT_H_ */ +#endif /* PSFONT_H_ */ /* END */ diff --git a/modules/freetype2/src/cff/cf2ft.c b/modules/freetype2/src/psaux/psft.c index c0d067e94..1f750174a 100644 --- a/modules/freetype2/src/cff/cf2ft.c +++ b/modules/freetype2/src/psaux/psft.c @@ -1,6 +1,6 @@ /***************************************************************************/ /* */ -/* cf2ft.c */ +/* psft.c */ /* */ /* FreeType Glue Component to Adobe's Interpreter (body). */ /* */ @@ -36,11 +36,20 @@ /***************************************************************************/ -#include "cf2ft.h" +#include "psft.h" #include FT_INTERNAL_DEBUG_H -#include "cf2font.h" -#include "cf2error.h" +#include "psfont.h" +#include "pserror.h" +#include "psobjs.h" +#include "cffdecode.h" + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT +#include FT_MULTIPLE_MASTERS_H +#include FT_SERVICE_MULTIPLE_MASTERS_H +#endif + +#include FT_SERVICE_CFF_TABLE_LOAD_H #define CF2_MAX_SIZE cf2_intToFixed( 2000 ) /* max ppem */ @@ -83,12 +92,13 @@ cf2_setGlyphWidth( CF2_Outline outline, CF2_Fixed width ) { - CFF_Decoder* decoder = outline->decoder; + PS_Decoder* decoder = outline->decoder; FT_ASSERT( decoder ); - decoder->glyph_width = cf2_fixedToInt( width ); + if ( !decoder->builder.is_t1 ) + *decoder->glyph_width = cf2_fixedToInt( width ); } @@ -122,8 +132,8 @@ const CF2_CallbackParams params ) { /* downcast the object pointer */ - CF2_Outline outline = (CF2_Outline)callbacks; - CFF_Builder* builder; + CF2_Outline outline = (CF2_Outline)callbacks; + PS_Builder* builder; (void)params; /* only used in debug mode */ @@ -134,7 +144,7 @@ builder = &outline->decoder->builder; /* note: two successive moves simply close the contour twice */ - cff_builder_close_contour( builder ); + ps_builder_close_contour( builder ); builder->path_begun = 0; } @@ -146,8 +156,8 @@ FT_Error error; /* downcast the object pointer */ - CF2_Outline outline = (CF2_Outline)callbacks; - CFF_Builder* builder; + CF2_Outline outline = (CF2_Outline)callbacks; + PS_Builder* builder; FT_ASSERT( outline && outline->decoder ); @@ -159,9 +169,9 @@ { /* record the move before the line; also check points and set */ /* `path_begun' */ - error = cff_builder_start_point( builder, - params->pt0.x, - params->pt0.y ); + error = ps_builder_start_point( builder, + params->pt0.x, + params->pt0.y ); if ( error ) { if ( !*callbacks->error ) @@ -170,10 +180,10 @@ } } - /* `cff_builder_add_point1' includes a check_points call for one point */ - error = cff_builder_add_point1( builder, - params->pt1.x, - params->pt1.y ); + /* `ps_builder_add_point1' includes a check_points call for one point */ + error = ps_builder_add_point1( builder, + params->pt1.x, + params->pt1.y ); if ( error ) { if ( !*callbacks->error ) @@ -190,8 +200,8 @@ FT_Error error; /* downcast the object pointer */ - CF2_Outline outline = (CF2_Outline)callbacks; - CFF_Builder* builder; + CF2_Outline outline = (CF2_Outline)callbacks; + PS_Builder* builder; FT_ASSERT( outline && outline->decoder ); @@ -203,9 +213,9 @@ { /* record the move before the line; also check points and set */ /* `path_begun' */ - error = cff_builder_start_point( builder, - params->pt0.x, - params->pt0.y ); + error = ps_builder_start_point( builder, + params->pt0.x, + params->pt0.y ); if ( error ) { if ( !*callbacks->error ) @@ -215,7 +225,7 @@ } /* prepare room for 3 points: 2 off-curve, 1 on-curve */ - error = cff_check_points( builder, 3 ); + error = ps_builder_check_points( builder, 3 ); if ( error ) { if ( !*callbacks->error ) @@ -223,15 +233,15 @@ return; } - cff_builder_add_point( builder, - params->pt1.x, - params->pt1.y, 0 ); - cff_builder_add_point( builder, - params->pt2.x, - params->pt2.y, 0 ); - cff_builder_add_point( builder, - params->pt3.x, - params->pt3.y, 1 ); + ps_builder_add_point( builder, + params->pt1.x, + params->pt1.y, 0 ); + ps_builder_add_point( builder, + params->pt2.x, + params->pt2.y, 0 ); + ps_builder_add_point( builder, + params->pt3.x, + params->pt3.y, 1 ); } @@ -253,11 +263,11 @@ /* get scaling and hint flag from GlyphSlot */ static void - cf2_getScaleAndHintFlag( CFF_Decoder* decoder, - CF2_Fixed* x_scale, - CF2_Fixed* y_scale, - FT_Bool* hinted, - FT_Bool* scaled ) + cf2_getScaleAndHintFlag( PS_Decoder* decoder, + CF2_Fixed* x_scale, + CF2_Fixed* y_scale, + FT_Bool* hinted, + FT_Bool* scaled ) { FT_ASSERT( decoder && decoder->builder.glyph ); @@ -267,8 +277,8 @@ if ( *hinted ) { - *x_scale = ( decoder->builder.glyph->x_scale + 32 ) / 64; - *y_scale = ( decoder->builder.glyph->y_scale + 32 ) / 64; + *x_scale = ADD_INT32( decoder->builder.glyph->x_scale, 32 ) / 64; + *y_scale = ADD_INT32( decoder->builder.glyph->y_scale, 32 ) / 64; } else { @@ -284,47 +294,60 @@ /* get units per em from `FT_Face' */ /* TODO: should handle font matrix concatenation? */ static FT_UShort - cf2_getUnitsPerEm( CFF_Decoder* decoder ) + cf2_getUnitsPerEm( PS_Decoder* decoder ) { FT_ASSERT( decoder && decoder->builder.face ); - FT_ASSERT( decoder->builder.face->root.units_per_EM ); + FT_ASSERT( decoder->builder.face->units_per_EM ); - return decoder->builder.face->root.units_per_EM; + return decoder->builder.face->units_per_EM; } /* Main entry point: Render one glyph. */ FT_LOCAL_DEF( FT_Error ) - cf2_decoder_parse_charstrings( CFF_Decoder* decoder, - FT_Byte* charstring_base, - FT_ULong charstring_len ) + cf2_decoder_parse_charstrings( PS_Decoder* decoder, + FT_Byte* charstring_base, + FT_ULong charstring_len ) { FT_Memory memory; FT_Error error = FT_Err_Ok; CF2_Font font; + FT_Bool is_t1 = decoder->builder.is_t1; - FT_ASSERT( decoder && decoder->cff ); + + FT_ASSERT( decoder && + ( is_t1 || decoder->cff ) ); + + if ( is_t1 && !decoder->current_subfont ) + { + FT_ERROR(( "cf2_decoder_parse_charstrings (Type 1): " + "SubFont missing. Use `t1_make_subfont' first\n" )); + return FT_THROW( Invalid_Table ); + } memory = decoder->builder.memory; /* CF2 data is saved here across glyphs */ - font = (CF2_Font)decoder->cff->cf2_instance.data; + font = (CF2_Font)decoder->cf2_instance->data; /* on first glyph, allocate instance structure */ - if ( !decoder->cff->cf2_instance.data ) + if ( !decoder->cf2_instance->data ) { - decoder->cff->cf2_instance.finalizer = + decoder->cf2_instance->finalizer = (FT_Generic_Finalizer)cf2_free_instance; - if ( FT_ALLOC( decoder->cff->cf2_instance.data, + if ( FT_ALLOC( decoder->cf2_instance->data, sizeof ( CF2_FontRec ) ) ) return FT_THROW( Out_Of_Memory ); - font = (CF2_Font)decoder->cff->cf2_instance.data; + font = (CF2_Font)decoder->cf2_instance->data; font->memory = memory; + if ( !is_t1 ) + font->cffload = (FT_Service_CFFLoad)decoder->cff->cffload; + /* initialize a client outline, to be shared by each glyph rendered */ cf2_outline_init( &font->outline, font->memory, &font->error ); } @@ -337,8 +360,13 @@ { /* build parameters for Adobe engine */ - CFF_Builder* builder = &decoder->builder; - CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( builder->face ); + PS_Builder* builder = &decoder->builder; + PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( builder->face ); + + FT_Bool no_stem_darkening_driver = + driver->no_stem_darkening; + FT_Char no_stem_darkening_font = + builder->face->internal->no_stem_darkening; /* local error */ FT_Error error2 = FT_Err_Ok; @@ -367,13 +395,21 @@ &hinted, &scaled ); - /* copy isCFF2 boolean from TT_Face to CF2_Font */ - font->isCFF2 = builder->face->isCFF2; + if ( is_t1 ) + font->isCFF2 = FALSE; + else + { + /* copy isCFF2 boolean from TT_Face to CF2_Font */ + font->isCFF2 = ((TT_Face)builder->face)->is_cff2; + } + font->isT1 = is_t1; font->renderingFlags = 0; if ( hinted ) font->renderingFlags |= CF2_FlagsHinted; - if ( scaled && !driver->no_stem_darkening ) + if ( scaled && ( !no_stem_darkening_font || + ( no_stem_darkening_font < 0 && + !no_stem_darkening_driver ) ) ) font->renderingFlags |= CF2_FlagsDarkened; font->darkenParams[0] = driver->darken_params[0]; @@ -409,7 +445,7 @@ /* get pointer to current FreeType subfont (based on current glyphID) */ FT_LOCAL_DEF( CFF_SubFont ) - cf2_getSubfont( CFF_Decoder* decoder ) + cf2_getSubfont( PS_Decoder* decoder ) { FT_ASSERT( decoder && decoder->current_subfont ); @@ -419,7 +455,7 @@ /* get pointer to VStore structure */ FT_LOCAL_DEF( CFF_VStore ) - cf2_getVStore( CFF_Decoder* decoder ) + cf2_getVStore( PS_Decoder* decoder ) { FT_ASSERT( decoder && decoder->cff ); @@ -429,7 +465,7 @@ /* get maxstack value from CFF2 Top DICT */ FT_LOCAL_DEF( FT_UInt ) - cf2_getMaxstack( CFF_Decoder* decoder ) + cf2_getMaxstack( PS_Decoder* decoder ) { FT_ASSERT( decoder && decoder->cff ); @@ -443,25 +479,33 @@ /* */ /* Note: Uses FT_Fixed not CF2_Fixed for the vector. */ FT_LOCAL_DEF( FT_Error ) - cf2_getNormalizedVector( CFF_Decoder* decoder, + cf2_getNormalizedVector( PS_Decoder* decoder, CF2_UInt *len, FT_Fixed* *vec ) { + TT_Face face; + FT_Service_MultiMasters mm; + + FT_ASSERT( decoder && decoder->builder.face ); FT_ASSERT( vec && len ); + FT_ASSERT( !decoder->builder.is_t1 ); + + face = (TT_Face)decoder->builder.face; + mm = (FT_Service_MultiMasters)face->mm; - return cff_get_var_blend( decoder->builder.face, len, vec, NULL ); + return mm->get_var_blend( FT_FACE( face ), len, NULL, vec, NULL ); } #endif /* get `y_ppem' from `CFF_Size' */ FT_LOCAL_DEF( CF2_Fixed ) - cf2_getPpemY( CFF_Decoder* decoder ) + cf2_getPpemY( PS_Decoder* decoder ) { - FT_ASSERT( decoder && - decoder->builder.face && - decoder->builder.face->root.size ); + FT_ASSERT( decoder && + decoder->builder.face && + decoder->builder.face->size ); /* * Note that `y_ppem' can be zero if there wasn't a call to @@ -473,7 +517,7 @@ * */ return cf2_intToFixed( - decoder->builder.face->root.size->metrics.y_ppem ); + decoder->builder.face->size->metrics.y_ppem ); } @@ -481,7 +525,7 @@ /* FreeType stores these as integer font units */ /* (note: variable names seem swapped) */ FT_LOCAL_DEF( CF2_Fixed ) - cf2_getStdVW( CFF_Decoder* decoder ) + cf2_getStdVW( PS_Decoder* decoder ) { FT_ASSERT( decoder && decoder->current_subfont ); @@ -491,7 +535,7 @@ FT_LOCAL_DEF( CF2_Fixed ) - cf2_getStdHW( CFF_Decoder* decoder ) + cf2_getStdHW( PS_Decoder* decoder ) { FT_ASSERT( decoder && decoder->current_subfont ); @@ -502,10 +546,10 @@ /* note: FreeType stores 1000 times the actual value for `BlueScale' */ FT_LOCAL_DEF( void ) - cf2_getBlueMetrics( CFF_Decoder* decoder, - CF2_Fixed* blueScale, - CF2_Fixed* blueShift, - CF2_Fixed* blueFuzz ) + cf2_getBlueMetrics( PS_Decoder* decoder, + CF2_Fixed* blueScale, + CF2_Fixed* blueShift, + CF2_Fixed* blueFuzz ) { FT_ASSERT( decoder && decoder->current_subfont ); @@ -522,9 +566,9 @@ /* get blue values counts and arrays; the FreeType parser has validated */ /* the counts and verified that each is an even number */ FT_LOCAL_DEF( void ) - cf2_getBlueValues( CFF_Decoder* decoder, - size_t* count, - FT_Pos* *data ) + cf2_getBlueValues( PS_Decoder* decoder, + size_t* count, + FT_Pos* *data ) { FT_ASSERT( decoder && decoder->current_subfont ); @@ -535,9 +579,9 @@ FT_LOCAL_DEF( void ) - cf2_getOtherBlues( CFF_Decoder* decoder, - size_t* count, - FT_Pos* *data ) + cf2_getOtherBlues( PS_Decoder* decoder, + size_t* count, + FT_Pos* *data ) { FT_ASSERT( decoder && decoder->current_subfont ); @@ -548,9 +592,9 @@ FT_LOCAL_DEF( void ) - cf2_getFamilyBlues( CFF_Decoder* decoder, - size_t* count, - FT_Pos* *data ) + cf2_getFamilyBlues( PS_Decoder* decoder, + size_t* count, + FT_Pos* *data ) { FT_ASSERT( decoder && decoder->current_subfont ); @@ -561,9 +605,9 @@ FT_LOCAL_DEF( void ) - cf2_getFamilyOtherBlues( CFF_Decoder* decoder, - size_t* count, - FT_Pos* *data ) + cf2_getFamilyOtherBlues( PS_Decoder* decoder, + size_t* count, + FT_Pos* *data ) { FT_ASSERT( decoder && decoder->current_subfont ); @@ -574,7 +618,7 @@ FT_LOCAL_DEF( CF2_Int ) - cf2_getLanguageGroup( CFF_Decoder* decoder ) + cf2_getLanguageGroup( PS_Decoder* decoder ) { FT_ASSERT( decoder && decoder->current_subfont ); @@ -585,9 +629,9 @@ /* convert unbiased subroutine index to `CF2_Buffer' and */ /* return 0 on success */ FT_LOCAL_DEF( CF2_Int ) - cf2_initGlobalRegionBuffer( CFF_Decoder* decoder, - CF2_Int subrNum, - CF2_Buffer buf ) + cf2_initGlobalRegionBuffer( PS_Decoder* decoder, + CF2_Int subrNum, + CF2_Buffer buf ) { CF2_UInt idx; @@ -613,9 +657,9 @@ /* convert AdobeStandardEncoding code to CF2_Buffer; */ /* used for seac component */ FT_LOCAL_DEF( FT_Error ) - cf2_getSeacComponent( CFF_Decoder* decoder, - CF2_Int code, - CF2_Buffer buf ) + cf2_getSeacComponent( PS_Decoder* decoder, + CF2_Int code, + CF2_Buffer buf ) { CF2_Int gid; FT_Byte* charstring; @@ -624,13 +668,14 @@ FT_ASSERT( decoder ); + FT_ASSERT( !decoder->builder.is_t1 ); FT_ZERO( buf ); #ifdef FT_CONFIG_OPTION_INCREMENTAL /* Incremental fonts don't necessarily have valid charsets. */ /* They use the character code, not the glyph index, in this case. */ - if ( decoder->builder.face->root.internal->incremental_interface ) + if ( decoder->builder.face->internal->incremental_interface ) gid = code; else #endif /* FT_CONFIG_OPTION_INCREMENTAL */ @@ -640,10 +685,10 @@ return FT_THROW( Invalid_Glyph_Format ); } - error = cff_get_glyph_data( decoder->builder.face, - (CF2_UInt)gid, - &charstring, - &len ); + error = decoder->get_glyph_callback( (TT_Face)decoder->builder.face, + (CF2_UInt)gid, + &charstring, + &len ); /* TODO: for now, just pass the FreeType error through */ if ( error ) return error; @@ -660,21 +705,92 @@ FT_LOCAL_DEF( void ) - cf2_freeSeacComponent( CFF_Decoder* decoder, - CF2_Buffer buf ) + cf2_freeSeacComponent( PS_Decoder* decoder, + CF2_Buffer buf ) { FT_ASSERT( decoder ); + FT_ASSERT( !decoder->builder.is_t1 ); - cff_free_glyph_data( decoder->builder.face, - (FT_Byte**)&buf->start, - (FT_ULong)( buf->end - buf->start ) ); + decoder->free_glyph_callback( (TT_Face)decoder->builder.face, + (FT_Byte**)&buf->start, + (FT_ULong)( buf->end - buf->start ) ); + } + + + FT_LOCAL_DEF( FT_Error ) + cf2_getT1SeacComponent( PS_Decoder* decoder, + FT_UInt glyph_index, + CF2_Buffer buf ) + { + FT_Data glyph_data; + FT_Error error = FT_Err_Ok; + T1_Face face = (T1_Face)decoder->builder.face; + T1_Font type1 = &face->type1; + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + FT_Incremental_InterfaceRec *inc = + face->root.internal->incremental_interface; + + + /* For incremental fonts get the character data using the */ + /* callback function. */ + if ( inc ) + error = inc->funcs->get_glyph_data( inc->object, + glyph_index, &glyph_data ); + else +#endif + /* For ordinary fonts get the character data stored in the face record. */ + { + glyph_data.pointer = type1->charstrings[glyph_index]; + glyph_data.length = (FT_Int)type1->charstrings_len[glyph_index]; + } + + if ( !error ) + { + FT_Byte* charstring_base = (FT_Byte*)glyph_data.pointer; + FT_ULong charstring_len = (FT_ULong)glyph_data.length; + + + FT_ASSERT( charstring_base + charstring_len >= charstring_base ); + + FT_ZERO( buf ); + buf->start = + buf->ptr = charstring_base; + buf->end = charstring_base + charstring_len; + } + + return error; + } + + + FT_LOCAL_DEF( void ) + cf2_freeT1SeacComponent( PS_Decoder* decoder, + CF2_Buffer buf ) + { + T1_Face face; + FT_Data data; + + + FT_ASSERT( decoder ); + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + face = (T1_Face)decoder->builder.face; + + data.pointer = buf->start; + data.length = (FT_Int)( buf->end - buf->start ); + + if ( face->root.internal->incremental_interface ) + face->root.internal->incremental_interface->funcs->free_glyph_data( + face->root.internal->incremental_interface->object, + &data ); +#endif /* FT_CONFIG_OPTION_INCREMENTAL */ } FT_LOCAL_DEF( CF2_Int ) - cf2_initLocalRegionBuffer( CFF_Decoder* decoder, - CF2_Int subrNum, - CF2_Buffer buf ) + cf2_initLocalRegionBuffer( PS_Decoder* decoder, + CF2_Int subrNum, + CF2_Buffer buf ) { CF2_UInt idx; @@ -689,16 +805,42 @@ FT_ASSERT( decoder->locals ); - buf->start = - buf->ptr = decoder->locals[idx]; - buf->end = decoder->locals[idx + 1]; + buf->start = decoder->locals[idx]; + + if ( decoder->builder.is_t1 ) + { + /* The Type 1 driver stores subroutines without the seed bytes. */ + /* The CID driver stores subroutines with seed bytes. This */ + /* case is taken care of when decoder->subrs_len == 0. */ + if ( decoder->locals_len ) + buf->end = buf->start + decoder->locals_len[idx]; + else + { + /* We are using subroutines from a CID font. We must adjust */ + /* for the seed bytes. */ + buf->start += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 ); + buf->end = decoder->locals[idx + 1]; + } + + if ( !buf->start ) + { + FT_ERROR(( "cf2_initLocalRegionBuffer (Type 1 mode):" + " invoking empty subrs\n" )); + } + } + else + { + buf->end = decoder->locals[idx + 1]; + } + + buf->ptr = buf->start; return FALSE; /* success */ } FT_LOCAL_DEF( CF2_Fixed ) - cf2_getDefaultWidthX( CFF_Decoder* decoder ) + cf2_getDefaultWidthX( PS_Decoder* decoder ) { FT_ASSERT( decoder && decoder->current_subfont ); @@ -708,7 +850,7 @@ FT_LOCAL_DEF( CF2_Fixed ) - cf2_getNominalWidthX( CFF_Decoder* decoder ) + cf2_getNominalWidthX( PS_Decoder* decoder ) { FT_ASSERT( decoder && decoder->current_subfont ); @@ -720,7 +862,7 @@ FT_LOCAL_DEF( void ) cf2_outline_reset( CF2_Outline outline ) { - CFF_Decoder* decoder = outline->decoder; + PS_Decoder* decoder = outline->decoder; FT_ASSERT( decoder ); @@ -734,12 +876,12 @@ FT_LOCAL_DEF( void ) cf2_outline_close( CF2_Outline outline ) { - CFF_Decoder* decoder = outline->decoder; + PS_Decoder* decoder = outline->decoder; FT_ASSERT( decoder ); - cff_builder_close_contour( &decoder->builder ); + ps_builder_close_contour( &decoder->builder ); FT_GlyphLoader_Add( decoder->builder.loader ); } diff --git a/modules/freetype2/src/cff/cf2ft.h b/modules/freetype2/src/psaux/psft.h index b054a6e95..ab172110b 100644 --- a/modules/freetype2/src/cff/cf2ft.h +++ b/modules/freetype2/src/psaux/psft.h @@ -1,6 +1,6 @@ /***************************************************************************/ /* */ -/* cf2ft.h */ +/* psft.h */ /* */ /* FreeType Glue Component to Adobe's Interpreter (specification). */ /* */ @@ -36,11 +36,11 @@ /***************************************************************************/ -#ifndef CF2FT_H_ -#define CF2FT_H_ +#ifndef PSFT_H_ +#define PSFT_H_ -#include "cf2types.h" +#include "pstypes.h" /* TODO: disable asserts for now */ @@ -49,88 +49,96 @@ #include FT_SYSTEM_H -#include "cf2glue.h" -#include "cffgload.h" /* for CFF_Decoder */ +#include "psglue.h" +#include FT_INTERNAL_POSTSCRIPT_AUX_H /* for PS_Decoder */ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) - cf2_decoder_parse_charstrings( CFF_Decoder* decoder, - FT_Byte* charstring_base, - FT_ULong charstring_len ); + cf2_decoder_parse_charstrings( PS_Decoder* decoder, + FT_Byte* charstring_base, + FT_ULong charstring_len ); FT_LOCAL( CFF_SubFont ) - cf2_getSubfont( CFF_Decoder* decoder ); + cf2_getSubfont( PS_Decoder* decoder ); FT_LOCAL( CFF_VStore ) - cf2_getVStore( CFF_Decoder* decoder ); + cf2_getVStore( PS_Decoder* decoder ); FT_LOCAL( FT_UInt ) - cf2_getMaxstack( CFF_Decoder* decoder ); + cf2_getMaxstack( PS_Decoder* decoder ); #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT FT_LOCAL( FT_Error ) - cf2_getNormalizedVector( CFF_Decoder* decoder, - CF2_UInt *len, - FT_Fixed* *vec ); + cf2_getNormalizedVector( PS_Decoder* decoder, + CF2_UInt *len, + FT_Fixed* *vec ); #endif FT_LOCAL( CF2_Fixed ) - cf2_getPpemY( CFF_Decoder* decoder ); + cf2_getPpemY( PS_Decoder* decoder ); FT_LOCAL( CF2_Fixed ) - cf2_getStdVW( CFF_Decoder* decoder ); + cf2_getStdVW( PS_Decoder* decoder ); FT_LOCAL( CF2_Fixed ) - cf2_getStdHW( CFF_Decoder* decoder ); + cf2_getStdHW( PS_Decoder* decoder ); FT_LOCAL( void ) - cf2_getBlueMetrics( CFF_Decoder* decoder, - CF2_Fixed* blueScale, - CF2_Fixed* blueShift, - CF2_Fixed* blueFuzz ); + cf2_getBlueMetrics( PS_Decoder* decoder, + CF2_Fixed* blueScale, + CF2_Fixed* blueShift, + CF2_Fixed* blueFuzz ); FT_LOCAL( void ) - cf2_getBlueValues( CFF_Decoder* decoder, - size_t* count, - FT_Pos* *data ); + cf2_getBlueValues( PS_Decoder* decoder, + size_t* count, + FT_Pos* *data ); FT_LOCAL( void ) - cf2_getOtherBlues( CFF_Decoder* decoder, - size_t* count, - FT_Pos* *data ); + cf2_getOtherBlues( PS_Decoder* decoder, + size_t* count, + FT_Pos* *data ); FT_LOCAL( void ) - cf2_getFamilyBlues( CFF_Decoder* decoder, - size_t* count, - FT_Pos* *data ); + cf2_getFamilyBlues( PS_Decoder* decoder, + size_t* count, + FT_Pos* *data ); FT_LOCAL( void ) - cf2_getFamilyOtherBlues( CFF_Decoder* decoder, - size_t* count, - FT_Pos* *data ); + cf2_getFamilyOtherBlues( PS_Decoder* decoder, + size_t* count, + FT_Pos* *data ); FT_LOCAL( CF2_Int ) - cf2_getLanguageGroup( CFF_Decoder* decoder ); + cf2_getLanguageGroup( PS_Decoder* decoder ); FT_LOCAL( CF2_Int ) - cf2_initGlobalRegionBuffer( CFF_Decoder* decoder, - CF2_Int subrNum, - CF2_Buffer buf ); + cf2_initGlobalRegionBuffer( PS_Decoder* decoder, + CF2_Int subrNum, + CF2_Buffer buf ); FT_LOCAL( FT_Error ) - cf2_getSeacComponent( CFF_Decoder* decoder, - CF2_Int code, - CF2_Buffer buf ); + cf2_getSeacComponent( PS_Decoder* decoder, + CF2_Int code, + CF2_Buffer buf ); FT_LOCAL( void ) - cf2_freeSeacComponent( CFF_Decoder* decoder, - CF2_Buffer buf ); + cf2_freeSeacComponent( PS_Decoder* decoder, + CF2_Buffer buf ); FT_LOCAL( CF2_Int ) - cf2_initLocalRegionBuffer( CFF_Decoder* decoder, - CF2_Int subrNum, - CF2_Buffer buf ); + cf2_initLocalRegionBuffer( PS_Decoder* decoder, + CF2_Int subrNum, + CF2_Buffer buf ); FT_LOCAL( CF2_Fixed ) - cf2_getDefaultWidthX( CFF_Decoder* decoder ); + cf2_getDefaultWidthX( PS_Decoder* decoder ); FT_LOCAL( CF2_Fixed ) - cf2_getNominalWidthX( CFF_Decoder* decoder ); + cf2_getNominalWidthX( PS_Decoder* decoder ); + FT_LOCAL( FT_Error ) + cf2_getT1SeacComponent( PS_Decoder* decoder, + FT_UInt glyph_index, + CF2_Buffer buf ); + FT_LOCAL( void ) + cf2_freeT1SeacComponent( PS_Decoder* decoder, + CF2_Buffer buf ); + /* * FreeType client outline * @@ -139,7 +147,7 @@ FT_BEGIN_HEADER typedef struct CF2_OutlineRec_ { CF2_OutlineCallbacksRec root; /* base class must be first */ - CFF_Decoder* decoder; + PS_Decoder* decoder; } CF2_OutlineRec, *CF2_Outline; @@ -153,7 +161,7 @@ FT_BEGIN_HEADER FT_END_HEADER -#endif /* CF2FT_H_ */ +#endif /* PSFT_H_ */ /* END */ diff --git a/modules/freetype2/src/cff/cf2glue.h b/modules/freetype2/src/psaux/psglue.h index 56a7c248f..5545e12a5 100644 --- a/modules/freetype2/src/cff/cf2glue.h +++ b/modules/freetype2/src/psaux/psglue.h @@ -1,6 +1,6 @@ /***************************************************************************/ /* */ -/* cf2glue.h */ +/* psglue.h */ /* */ /* Adobe's code for shared stuff (specification only). */ /* */ @@ -36,15 +36,15 @@ /***************************************************************************/ -#ifndef CF2GLUE_H_ -#define CF2GLUE_H_ +#ifndef PSGLUE_H_ +#define PSGLUE_H_ /* common includes for other modules */ -#include "cf2error.h" -#include "cf2fixed.h" -#include "cf2arrst.h" -#include "cf2read.h" +#include "pserror.h" +#include "psfixed.h" +#include "psarrst.h" +#include "psread.h" FT_BEGIN_HEADER @@ -138,7 +138,7 @@ FT_BEGIN_HEADER FT_END_HEADER -#endif /* CF2GLUE_H_ */ +#endif /* PSGLUE_H_ */ /* END */ diff --git a/modules/freetype2/src/cff/cf2hints.c b/modules/freetype2/src/psaux/pshints.c index c8f7dfeba..361519642 100644 --- a/modules/freetype2/src/cff/cf2hints.c +++ b/modules/freetype2/src/psaux/pshints.c @@ -1,6 +1,6 @@ /***************************************************************************/ /* */ -/* cf2hints.c */ +/* pshints.c */ /* */ /* Adobe's code for handling CFF hints (body). */ /* */ @@ -36,13 +36,13 @@ /***************************************************************************/ -#include "cf2ft.h" +#include "psft.h" #include FT_INTERNAL_DEBUG_H -#include "cf2glue.h" -#include "cf2font.h" -#include "cf2hints.h" -#include "cf2intrp.h" +#include "psglue.h" +#include "psfont.h" +#include "pshints.h" +#include "psintrp.h" /*************************************************************************/ @@ -74,8 +74,8 @@ /* cross product of pt1 position from origin with pt2 position from */ /* pt1; we reduce the precision so that the result fits into 32 bits */ - return ( x1 >> 16 ) * ( ( y2 - y1 ) >> 16 ) - - ( y1 >> 16 ) * ( ( x2 - x1 ) >> 16 ); + return ( x1 >> 16 ) * ( SUB_INT32( y2, y1 ) >> 16 ) - + ( y1 >> 16 ) * ( SUB_INT32( x2, x1 ) >> 16 ); } @@ -105,7 +105,7 @@ stemHintArray, indexStemHint ); - width = stemHint->max - stemHint->min; + width = SUB_INT32( stemHint->max, stemHint->min ); if ( width == cf2_intToFixed( -21 ) ) { @@ -185,11 +185,11 @@ /* darkening. Bottoms are not changed; tops are incremented by twice */ /* `darkenY'. */ if ( cf2_hint_isTop( hint ) ) - hint->csCoord += 2 * font->darkenY; + hint->csCoord = ADD_INT32( hint->csCoord, 2 * font->darkenY ); - hint->csCoord += hintOrigin; - hint->scale = scale; - hint->index = indexStemHint; /* index in original stem hint array */ + hint->csCoord = ADD_INT32( hint->csCoord, hintOrigin ); + hint->scale = scale; + hint->index = indexStemHint; /* index in original stem hint array */ /* if original stem hint has been used, use the same position */ if ( hint->flags != 0 && stemHint->used ) @@ -299,6 +299,36 @@ } + static void + cf2_hintmap_dump( CF2_HintMap hintmap ) + { +#ifdef FT_DEBUG_LEVEL_TRACE + CF2_UInt i; + + + FT_TRACE6(( " index csCoord dsCoord scale flags\n" )); + + for ( i = 0; i < hintmap->count; i++ ) + { + CF2_Hint hint = &hintmap->edge[i]; + + + FT_TRACE6(( " %3d %7.2f %7.2f %5d %s%s%s%s\n", + hint->index, + hint->csCoord / 65536.0, + hint->dsCoord / ( hint->scale * 1.0 ), + hint->scale, + ( cf2_hint_isPair( hint ) ? "p" : "g" ), + ( cf2_hint_isTop( hint ) ? "t" : "b" ), + ( cf2_hint_isLocked( hint ) ? "L" : ""), + ( cf2_hint_isSynthetic( hint ) ? "S" : "" ) )); + } +#else + FT_UNUSED( hintmap ); +#endif + } + + /* transform character space coordinate to device space using hint map */ static CF2_Fixed cf2_hintmap_map( CF2_HintMap hintmap, @@ -314,6 +344,7 @@ /* start linear search from last hit */ CF2_UInt i = hintmap->lastIndex; + FT_ASSERT( hintmap->lastIndex < CF2_MAX_HINT_EDGES ); /* search up */ @@ -330,9 +361,10 @@ if ( i == 0 && csCoord < hintmap->edge[0].csCoord ) { /* special case for points below first edge: use uniform scale */ - return FT_MulFix( csCoord - hintmap->edge[0].csCoord, - hintmap->scale ) + - hintmap->edge[0].dsCoord; + return ADD_INT32( FT_MulFix( SUB_INT32( csCoord, + hintmap->edge[0].csCoord ), + hintmap->scale ), + hintmap->edge[0].dsCoord ); } else { @@ -340,9 +372,10 @@ * Note: entries with duplicate csCoord are allowed. * Use edge[i], the highest entry where csCoord >= entry[i].csCoord */ - return FT_MulFix( csCoord - hintmap->edge[i].csCoord, - hintmap->edge[i].scale ) + - hintmap->edge[i].dsCoord; + return ADD_INT32( FT_MulFix( SUB_INT32( csCoord, + hintmap->edge[i].csCoord ), + hintmap->edge[i].scale ), + hintmap->edge[i].dsCoord ); } } } @@ -437,14 +470,16 @@ /* is there room to move up? */ /* there is if we are at top of array or the next edge is at or */ /* beyond proposed move up? */ - if ( j >= hintmap->count - 1 || + if ( j >= hintmap->count - 1 || hintmap->edge[j + 1].dsCoord >= - hintmap->edge[j].dsCoord + moveUp + upMinCounter ) + ADD_INT32( hintmap->edge[j].dsCoord, + moveUp + upMinCounter ) ) { /* there is room to move up; is there also room to move down? */ - if ( i == 0 || + if ( i == 0 || hintmap->edge[i - 1].dsCoord <= - hintmap->edge[i].dsCoord + moveDown - downMinCounter ) + ADD_INT32( hintmap->edge[i].dsCoord, + moveDown - downMinCounter ) ) { /* move smaller absolute amount */ move = ( -moveDown < moveUp ) ? moveDown : moveUp; /* optimum */ @@ -455,9 +490,10 @@ else { /* is there room to move down? */ - if ( i == 0 || + if ( i == 0 || hintmap->edge[i - 1].dsCoord <= - hintmap->edge[i].dsCoord + moveDown - downMinCounter ) + ADD_INT32( hintmap->edge[i].dsCoord, + moveDown - downMinCounter ) ) { move = moveDown; /* true if non-optimum move */ @@ -491,9 +527,11 @@ } /* move the edge(s) */ - hintmap->edge[i].dsCoord += move; + hintmap->edge[i].dsCoord = ADD_INT32( hintmap->edge[i].dsCoord, + move ); if ( isPair ) - hintmap->edge[j].dsCoord += move; + hintmap->edge[j].dsCoord = ADD_INT32( hintmap->edge[j].dsCoord, + move ); } /* assert there are no overlaps in device space */ @@ -507,18 +545,20 @@ { if ( hintmap->edge[i].csCoord != hintmap->edge[i - 1].csCoord ) hintmap->edge[i - 1].scale = - FT_DivFix( - hintmap->edge[i].dsCoord - hintmap->edge[i - 1].dsCoord, - hintmap->edge[i].csCoord - hintmap->edge[i - 1].csCoord ); + FT_DivFix( SUB_INT32( hintmap->edge[i].dsCoord, + hintmap->edge[i - 1].dsCoord ), + SUB_INT32( hintmap->edge[i].csCoord, + hintmap->edge[i - 1].csCoord ) ); } if ( isPair ) { if ( hintmap->edge[j].csCoord != hintmap->edge[j - 1].csCoord ) hintmap->edge[j - 1].scale = - FT_DivFix( - hintmap->edge[j].dsCoord - hintmap->edge[j - 1].dsCoord, - hintmap->edge[j].csCoord - hintmap->edge[j - 1].csCoord ); + FT_DivFix( SUB_INT32( hintmap->edge[j].dsCoord, + hintmap->edge[j - 1].dsCoord ), + SUB_INT32( hintmap->edge[j].csCoord, + hintmap->edge[j - 1].csCoord ) ); i += 1; /* skip upper edge on next loop */ } @@ -539,15 +579,18 @@ /* is there room to move up? */ if ( hintmap->edge[j + 1].dsCoord >= - hintmap->edge[j].dsCoord + hintMove->moveUp + CF2_MIN_COUNTER ) + ADD_INT32( hintmap->edge[j].dsCoord, + hintMove->moveUp + CF2_MIN_COUNTER ) ) { /* there is more room now, move edge up */ - hintmap->edge[j].dsCoord += hintMove->moveUp; + hintmap->edge[j].dsCoord = ADD_INT32( hintmap->edge[j].dsCoord, + hintMove->moveUp ); if ( cf2_hint_isPair( &hintmap->edge[j] ) ) { FT_ASSERT( j > 0 ); - hintmap->edge[j - 1].dsCoord += hintMove->moveUp; + hintmap->edge[j - 1].dsCoord = + ADD_INT32( hintmap->edge[j - 1].dsCoord, hintMove->moveUp ); } } } @@ -599,6 +642,14 @@ break; } + FT_TRACE7(( " Got hint at %.2f (%.2f)\n", + firstHintEdge->csCoord / 65536.0, + firstHintEdge->dsCoord / 65536.0 )); + if ( isPair ) + FT_TRACE7(( " Got hint at %.2f (%.2f)\n", + secondHintEdge->csCoord / 65536.0, + secondHintEdge->dsCoord / 65536.0 )); + /* * Discard any hints that overlap in character space. Most often, this * is while building the initial map, where captured hints from all @@ -635,18 +686,19 @@ { /* Use hint map to position the center of stem, and nominal scale */ /* to position the two edges. This preserves the stem width. */ - CF2_Fixed midpoint = cf2_hintmap_map( - hintmap->initialHintMap, - ( secondHintEdge->csCoord + - firstHintEdge->csCoord ) / 2 ); - CF2_Fixed halfWidth = FT_MulFix( - ( secondHintEdge->csCoord - - firstHintEdge->csCoord ) / 2, - hintmap->scale ); - - - firstHintEdge->dsCoord = midpoint - halfWidth; - secondHintEdge->dsCoord = midpoint + halfWidth; + CF2_Fixed midpoint = + cf2_hintmap_map( + hintmap->initialHintMap, + ADD_INT32( secondHintEdge->csCoord, + firstHintEdge->csCoord ) / 2 ); + CF2_Fixed halfWidth = + FT_MulFix( SUB_INT32( secondHintEdge->csCoord, + firstHintEdge->csCoord ) / 2, + hintmap->scale ); + + + firstHintEdge->dsCoord = SUB_INT32( midpoint, halfWidth ); + secondHintEdge->dsCoord = ADD_INT32( midpoint, halfWidth ); } else firstHintEdge->dsCoord = cf2_hintmap_map( hintmap->initialHintMap, @@ -715,13 +767,22 @@ /* insert first edge */ hintmap->edge[indexInsert] = *firstHintEdge; /* copy struct */ - hintmap->count += 1; + hintmap->count += 1; + + FT_TRACE7(( " Inserting hint %.2f (%.2f)\n", + firstHintEdge->csCoord / 65536.0, + firstHintEdge->dsCoord / 65536.0 )); if ( isPair ) { /* insert second edge */ hintmap->edge[indexInsert + 1] = *secondHintEdge; /* copy struct */ hintmap->count += 1; + + FT_TRACE7(( " Inserting hint %.2f (%.2f)\n", + secondHintEdge->csCoord / 65536.0, + secondHintEdge->dsCoord / 65536.0 )); + } } @@ -781,7 +842,15 @@ cf2_arrstack_size( hStemHintArray ) + cf2_arrstack_size( vStemHintArray ) ); if ( !cf2_hintmask_isValid( hintMask ) ) - return; /* too many stem hints */ + { + if ( font->isT1 ) + { + /* no error, just continue unhinted */ + *hintMask->error = FT_Err_Ok; + hintmap->hinted = FALSE; + } + return; /* too many stem hints */ + } } /* begin by clearing the map */ @@ -797,7 +866,7 @@ /* Defense-in-depth. Should never return here. */ if ( bitCount > hintMask->bitCount ) - return; + return; /* synthetic embox hints get highest priority */ if ( font->blues.doEmBoxHints ) @@ -956,6 +1025,12 @@ } } + FT_TRACE6(( initialMap ? "flags: [p]air [g]host [t]op " + "[b]ottom [L]ocked [S]ynthetic\n" + "Initial hintmap\n" + : "Hints:\n" )); + cf2_hintmap_dump( hintmap ); + /* * Note: The following line is a convenient place to break when * debugging hinting. Examine `hintmap->edge' for the list of @@ -968,6 +1043,9 @@ /* adjust positions of hint edges that are not locked to blue zones */ cf2_hintmap_adjustHints( hintmap ); + FT_TRACE6(( "(adjusted)\n" )); + cf2_hintmap_dump( hintmap ); + /* save the position of all hints that were used in this hint map; */ /* if we use them again, we'll locate them in the same position */ if ( !initialMap ) @@ -1063,7 +1141,7 @@ cf2_fixedAbs( glyphpath->yOffset ) ); /* .1 character space unit */ - glyphpath->snapThreshold = cf2_floatToFixed( 0.1f ); + glyphpath->snapThreshold = cf2_doubleToFixed( 0.1 ); glyphpath->moveIsPending = TRUE; glyphpath->pathIsOpen = FALSE; @@ -1095,16 +1173,20 @@ FT_Vector pt; /* hinted point in upright DS */ - pt.x = FT_MulFix( glyphpath->scaleX, x ) + - FT_MulFix( glyphpath->scaleC, y ); + pt.x = ADD_INT32( FT_MulFix( glyphpath->scaleX, x ), + FT_MulFix( glyphpath->scaleC, y ) ); pt.y = cf2_hintmap_map( hintmap, y ); - ppt->x = FT_MulFix( glyphpath->font->outerTransform.a, pt.x ) + - FT_MulFix( glyphpath->font->outerTransform.c, pt.y ) + - glyphpath->fractionalTranslation.x; - ppt->y = FT_MulFix( glyphpath->font->outerTransform.b, pt.x ) + - FT_MulFix( glyphpath->font->outerTransform.d, pt.y ) + - glyphpath->fractionalTranslation.y; + ppt->x = ADD_INT32( + FT_MulFix( glyphpath->font->outerTransform.a, pt.x ), + ADD_INT32( + FT_MulFix( glyphpath->font->outerTransform.c, pt.y ), + glyphpath->fractionalTranslation.x ) ); + ppt->y = ADD_INT32( + FT_MulFix( glyphpath->font->outerTransform.b, pt.x ), + ADD_INT32( + FT_MulFix( glyphpath->font->outerTransform.d, pt.y ), + glyphpath->fractionalTranslation.y ) ); } @@ -1128,7 +1210,7 @@ * second segment. * Let `w 'be the zero-based vector from `u1' to `v1'. * `perp' is the `perpendicular dot product'; see - * http://mathworld.wolfram.com/PerpDotProduct.html. + * https://mathworld.wolfram.com/PerpDotProduct.html. * `s' is the parameter for the parametric line for the first segment * (`u'). * @@ -1154,12 +1236,12 @@ CF2_Fixed denominator, s; - u.x = CF2_CS_SCALE( u2->x - u1->x ); - u.y = CF2_CS_SCALE( u2->y - u1->y ); - v.x = CF2_CS_SCALE( v2->x - v1->x ); - v.y = CF2_CS_SCALE( v2->y - v1->y ); - w.x = CF2_CS_SCALE( v1->x - u1->x ); - w.y = CF2_CS_SCALE( v1->y - u1->y ); + u.x = CF2_CS_SCALE( SUB_INT32( u2->x, u1->x ) ); + u.y = CF2_CS_SCALE( SUB_INT32( u2->y, u1->y ) ); + v.x = CF2_CS_SCALE( SUB_INT32( v2->x, v1->x ) ); + v.y = CF2_CS_SCALE( SUB_INT32( v2->y, v1->y ) ); + w.x = CF2_CS_SCALE( SUB_INT32( v1->x, u1->x ) ); + w.y = CF2_CS_SCALE( SUB_INT32( v1->y, u1->y ) ); denominator = cf2_perp( u, v ); @@ -1168,8 +1250,11 @@ s = FT_DivFix( cf2_perp( w, v ), denominator ); - intersection->x = u1->x + FT_MulFix( s, u2->x - u1->x ); - intersection->y = u1->y + FT_MulFix( s, u2->y - u1->y ); + intersection->x = ADD_INT32( u1->x, + FT_MulFix( s, SUB_INT32( u2->x, u1->x ) ) ); + intersection->y = ADD_INT32( u1->y, + FT_MulFix( s, SUB_INT32( u2->y, u1->y ) ) ); + /* * Special case snapping for horizontal and vertical lines. @@ -1180,25 +1265,29 @@ * */ - if ( u1->x == u2->x && - cf2_fixedAbs( intersection->x - u1->x ) < glyphpath->snapThreshold ) + if ( u1->x == u2->x && + cf2_fixedAbs( SUB_INT32( intersection->x, + u1->x ) ) < glyphpath->snapThreshold ) intersection->x = u1->x; - if ( u1->y == u2->y && - cf2_fixedAbs( intersection->y - u1->y ) < glyphpath->snapThreshold ) + if ( u1->y == u2->y && + cf2_fixedAbs( SUB_INT32( intersection->y, + u1->y ) ) < glyphpath->snapThreshold ) intersection->y = u1->y; - if ( v1->x == v2->x && - cf2_fixedAbs( intersection->x - v1->x ) < glyphpath->snapThreshold ) + if ( v1->x == v2->x && + cf2_fixedAbs( SUB_INT32( intersection->x, + v1->x ) ) < glyphpath->snapThreshold ) intersection->x = v1->x; - if ( v1->y == v2->y && - cf2_fixedAbs( intersection->y - v1->y ) < glyphpath->snapThreshold ) + if ( v1->y == v2->y && + cf2_fixedAbs( SUB_INT32( intersection->y, + v1->y ) ) < glyphpath->snapThreshold ) intersection->y = v1->y; /* limit the intersection distance from midpoint of u2 and v1 */ - if ( cf2_fixedAbs( intersection->x - ( u2->x + v1->x ) / 2 ) > - glyphpath->miterLimit || - cf2_fixedAbs( intersection->y - ( u2->y + v1->y ) / 2 ) > - glyphpath->miterLimit ) + if ( cf2_fixedAbs( intersection->x - ADD_INT32( u2->x, v1->x ) / 2 ) > + glyphpath->miterLimit || + cf2_fixedAbs( intersection->y - ADD_INT32( u2->y, v1->y ) / 2 ) > + glyphpath->miterLimit ) return FALSE; return TRUE; @@ -1446,16 +1535,16 @@ CF2_Fixed* x, CF2_Fixed* y ) { - CF2_Fixed dx = x2 - x1; - CF2_Fixed dy = y2 - y1; + CF2_Fixed dx = SUB_INT32( x2, x1 ); + CF2_Fixed dy = SUB_INT32( y2, y1 ); /* note: negative offsets don't work here; negate deltas to change */ /* quadrants, below */ if ( glyphpath->font->reverseWinding ) { - dx = -dx; - dy = -dy; + dx = NEG_INT32( dx ); + dy = NEG_INT32( dy ); } *x = *y = 0; @@ -1464,8 +1553,9 @@ return; /* add momentum for this path element */ - glyphpath->callbacks->windingMomentum += - cf2_getWindingMomentum( x1, y1, x2, y2 ); + glyphpath->callbacks->windingMomentum = + ADD_INT32( glyphpath->callbacks->windingMomentum, + cf2_getWindingMomentum( x1, y1, x2, y2 ) ); /* note: allow mixed integer and fixed multiplication here */ if ( dx >= 0 ) @@ -1474,13 +1564,13 @@ { /* first quadrant, +x +y */ - if ( dx > 2 * dy ) + if ( dx > MUL_INT32( 2, dy ) ) { /* +x */ *x = 0; *y = 0; } - else if ( dy > 2 * dx ) + else if ( dy > MUL_INT32( 2, dx ) ) { /* +y */ *x = glyphpath->xOffset; @@ -1489,9 +1579,9 @@ else { /* +x +y */ - *x = FT_MulFix( cf2_floatToFixed( 0.7 ), + *x = FT_MulFix( cf2_doubleToFixed( 0.7 ), glyphpath->xOffset ); - *y = FT_MulFix( cf2_floatToFixed( 1.0 - 0.7 ), + *y = FT_MulFix( cf2_doubleToFixed( 1.0 - 0.7 ), glyphpath->yOffset ); } } @@ -1499,24 +1589,24 @@ { /* fourth quadrant, +x -y */ - if ( dx > -2 * dy ) + if ( dx > MUL_INT32( -2, dy ) ) { /* +x */ *x = 0; *y = 0; } - else if ( -dy > 2 * dx ) + else if ( NEG_INT32( dy ) > MUL_INT32( 2, dx ) ) { /* -y */ - *x = -glyphpath->xOffset; + *x = NEG_INT32( glyphpath->xOffset ); *y = glyphpath->yOffset; } else { /* +x -y */ - *x = FT_MulFix( cf2_floatToFixed( -0.7 ), + *x = FT_MulFix( cf2_doubleToFixed( -0.7 ), glyphpath->xOffset ); - *y = FT_MulFix( cf2_floatToFixed( 1.0 - 0.7 ), + *y = FT_MulFix( cf2_doubleToFixed( 1.0 - 0.7 ), glyphpath->yOffset ); } } @@ -1527,13 +1617,13 @@ { /* second quadrant, -x +y */ - if ( -dx > 2 * dy ) + if ( NEG_INT32( dx ) > MUL_INT32( 2, dy ) ) { /* -x */ *x = 0; - *y = 2 * glyphpath->yOffset; + *y = MUL_INT32( 2, glyphpath->yOffset ); } - else if ( dy > -2 * dx ) + else if ( dy > MUL_INT32( -2, dx ) ) { /* +y */ *x = glyphpath->xOffset; @@ -1542,9 +1632,9 @@ else { /* -x +y */ - *x = FT_MulFix( cf2_floatToFixed( 0.7 ), + *x = FT_MulFix( cf2_doubleToFixed( 0.7 ), glyphpath->xOffset ); - *y = FT_MulFix( cf2_floatToFixed( 1.0 + 0.7 ), + *y = FT_MulFix( cf2_doubleToFixed( 1.0 + 0.7 ), glyphpath->yOffset ); } } @@ -1552,24 +1642,24 @@ { /* third quadrant, -x -y */ - if ( -dx > -2 * dy ) + if ( NEG_INT32( dx ) > MUL_INT32( -2, dy ) ) { /* -x */ *x = 0; - *y = 2 * glyphpath->yOffset; + *y = MUL_INT32( 2, glyphpath->yOffset ); } - else if ( -dy > -2 * dx ) + else if ( NEG_INT32( dy ) > MUL_INT32( -2, dx ) ) { /* -y */ - *x = -glyphpath->xOffset; + *x = NEG_INT32( glyphpath->xOffset ); *y = glyphpath->yOffset; } else { /* -x -y */ - *x = FT_MulFix( cf2_floatToFixed( -0.7 ), + *x = FT_MulFix( cf2_doubleToFixed( -0.7 ), glyphpath->xOffset ); - *y = FT_MulFix( cf2_floatToFixed( 1.0 + 0.7 ), + *y = FT_MulFix( cf2_doubleToFixed( 1.0 + 0.7 ), glyphpath->yOffset ); } } @@ -1675,10 +1765,10 @@ &yOffset ); /* construct offset points */ - P0.x = glyphpath->currentCS.x + xOffset; - P0.y = glyphpath->currentCS.y + yOffset; - P1.x = x + xOffset; - P1.y = y + yOffset; + P0.x = ADD_INT32( glyphpath->currentCS.x, xOffset ); + P0.y = ADD_INT32( glyphpath->currentCS.y, yOffset ); + P1.x = ADD_INT32( x, xOffset ); + P1.y = ADD_INT32( y, yOffset ); if ( glyphpath->moveIsPending ) { @@ -1753,19 +1843,20 @@ &yOffset3 ); /* add momentum from the middle segment */ - glyphpath->callbacks->windingMomentum += - cf2_getWindingMomentum( x1, y1, x2, y2 ); + glyphpath->callbacks->windingMomentum = + ADD_INT32( glyphpath->callbacks->windingMomentum, + cf2_getWindingMomentum( x1, y1, x2, y2 ) ); /* construct offset points */ - P0.x = glyphpath->currentCS.x + xOffset1; - P0.y = glyphpath->currentCS.y + yOffset1; - P1.x = x1 + xOffset1; - P1.y = y1 + yOffset1; + P0.x = ADD_INT32( glyphpath->currentCS.x, xOffset1 ); + P0.y = ADD_INT32( glyphpath->currentCS.y, yOffset1 ); + P1.x = ADD_INT32( x1, xOffset1 ); + P1.y = ADD_INT32( y1, yOffset1 ); /* note: preserve angle of final segment by using offset3 at both ends */ - P2.x = x2 + xOffset3; - P2.y = y2 + yOffset3; - P3.x = x3 + xOffset3; - P3.y = y3 + yOffset3; + P2.x = ADD_INT32( x2, xOffset3 ); + P2.y = ADD_INT32( y2, yOffset3 ); + P3.x = ADD_INT32( x3, xOffset3 ); + P3.y = ADD_INT32( y3, yOffset3 ); if ( glyphpath->moveIsPending ) { diff --git a/modules/freetype2/src/cff/cf2hints.h b/modules/freetype2/src/psaux/pshints.h index a8984542a..92e37e98a 100644 --- a/modules/freetype2/src/cff/cf2hints.h +++ b/modules/freetype2/src/psaux/pshints.h @@ -1,6 +1,6 @@ /***************************************************************************/ /* */ -/* cf2hints.h */ +/* pshints.h */ /* */ /* Adobe's code for handling CFF hints (body). */ /* */ @@ -36,9 +36,8 @@ /***************************************************************************/ -#ifndef CF2HINTS_H_ -#define CF2HINTS_H_ - +#ifndef PSHINT_H_ +#define PSHINT_H_ FT_BEGIN_HEADER @@ -283,7 +282,7 @@ FT_BEGIN_HEADER FT_END_HEADER -#endif /* CF2HINTS_H_ */ +#endif /* PSHINT_H_ */ /* END */ diff --git a/modules/freetype2/src/psaux/psintrp.c b/modules/freetype2/src/psaux/psintrp.c new file mode 100644 index 000000000..da5a8dad1 --- /dev/null +++ b/modules/freetype2/src/psaux/psintrp.c @@ -0,0 +1,3040 @@ +/***************************************************************************/ +/* */ +/* psintrp.c */ +/* */ +/* Adobe's CFF Interpreter (body). */ +/* */ +/* Copyright 2007-2014 Adobe Systems Incorporated. */ +/* */ +/* This software, and all works of authorship, whether in source or */ +/* object code form as indicated by the copyright notice(s) included */ +/* herein (collectively, the "Work") is made available, and may only be */ +/* used, modified, and distributed under the FreeType Project License, */ +/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */ +/* FreeType Project License, each contributor to the Work hereby grants */ +/* to any individual or legal entity exercising permissions granted by */ +/* the FreeType Project License and this section (hereafter, "You" or */ +/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */ +/* royalty-free, irrevocable (except as stated in this section) patent */ +/* license to make, have made, use, offer to sell, sell, import, and */ +/* otherwise transfer the Work, where such license applies only to those */ +/* patent claims licensable by such contributor that are necessarily */ +/* infringed by their contribution(s) alone or by combination of their */ +/* contribution(s) with the Work to which such contribution(s) was */ +/* submitted. If You institute patent litigation against any entity */ +/* (including a cross-claim or counterclaim in a lawsuit) alleging that */ +/* the Work or a contribution incorporated within the Work constitutes */ +/* direct or contributory patent infringement, then any patent licenses */ +/* granted to You under this License for that Work shall terminate as of */ +/* the date such litigation is filed. */ +/* */ +/* By using, modifying, or distributing the Work you indicate that you */ +/* have read and understood the terms and conditions of the */ +/* FreeType Project License as well as those provided in this section, */ +/* and you accept them fully. */ +/* */ +/***************************************************************************/ + + +#include "psft.h" +#include FT_INTERNAL_DEBUG_H +#include FT_SERVICE_CFF_TABLE_LOAD_H + +#include "psglue.h" +#include "psfont.h" +#include "psstack.h" +#include "pshints.h" +#include "psintrp.h" + +#include "pserror.h" + +#include "psobjs.h" /* for cff_random */ +#include "t1decode.h" /* for t1 seac */ + + + /*************************************************************************/ + /* */ + /* 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_cf2interp + + + FT_LOCAL_DEF( void ) + cf2_hintmask_init( CF2_HintMask hintmask, + FT_Error* error ) + { + FT_ZERO( hintmask ); + + hintmask->error = error; + } + + + FT_LOCAL_DEF( FT_Bool ) + cf2_hintmask_isValid( const CF2_HintMask hintmask ) + { + return hintmask->isValid; + } + + + FT_LOCAL_DEF( FT_Bool ) + cf2_hintmask_isNew( const CF2_HintMask hintmask ) + { + return hintmask->isNew; + } + + + FT_LOCAL_DEF( void ) + cf2_hintmask_setNew( CF2_HintMask hintmask, + FT_Bool val ) + { + hintmask->isNew = val; + } + + + /* clients call `getMaskPtr' in order to iterate */ + /* through hint mask */ + + FT_LOCAL_DEF( FT_Byte* ) + cf2_hintmask_getMaskPtr( CF2_HintMask hintmask ) + { + return hintmask->mask; + } + + + static size_t + cf2_hintmask_setCounts( CF2_HintMask hintmask, + size_t bitCount ) + { + if ( bitCount > CF2_MAX_HINTS ) + { + /* total of h and v stems must be <= 96 */ + CF2_SET_ERROR( hintmask->error, Invalid_Glyph_Format ); + return 0; + } + + hintmask->bitCount = bitCount; + hintmask->byteCount = ( hintmask->bitCount + 7 ) / 8; + + hintmask->isValid = TRUE; + hintmask->isNew = TRUE; + + return bitCount; + } + + + /* consume the hintmask bytes from the charstring, advancing the src */ + /* pointer */ + static void + cf2_hintmask_read( CF2_HintMask hintmask, + CF2_Buffer charstring, + size_t bitCount ) + { + size_t i; + +#ifndef CF2_NDEBUG + /* these are the bits in the final mask byte that should be zero */ + /* Note: this variable is only used in an assert expression below */ + /* and then only if CF2_NDEBUG is not defined */ + CF2_UInt mask = ( 1 << ( -(CF2_Int)bitCount & 7 ) ) - 1; +#endif + + + /* initialize counts and isValid */ + if ( cf2_hintmask_setCounts( hintmask, bitCount ) == 0 ) + return; + + FT_ASSERT( hintmask->byteCount > 0 ); + + FT_TRACE4(( " (maskbytes:" )); + + /* set mask and advance interpreter's charstring pointer */ + for ( i = 0; i < hintmask->byteCount; i++ ) + { + hintmask->mask[i] = (FT_Byte)cf2_buf_readByte( charstring ); + FT_TRACE4(( " 0x%02X", hintmask->mask[i] )); + } + + FT_TRACE4(( ")\n" )); + + /* assert any unused bits in last byte are zero unless there's a prior */ + /* error */ + /* bitCount -> mask, 0 -> 0, 1 -> 7f, 2 -> 3f, ... 6 -> 3, 7 -> 1 */ +#ifndef CF2_NDEBUG + FT_ASSERT( ( hintmask->mask[hintmask->byteCount - 1] & mask ) == 0 || + *hintmask->error ); +#endif + } + + + FT_LOCAL_DEF( void ) + cf2_hintmask_setAll( CF2_HintMask hintmask, + size_t bitCount ) + { + size_t i; + CF2_UInt mask = ( 1 << ( -(CF2_Int)bitCount & 7 ) ) - 1; + + + /* initialize counts and isValid */ + if ( cf2_hintmask_setCounts( hintmask, bitCount ) == 0 ) + return; + + FT_ASSERT( hintmask->byteCount > 0 ); + FT_ASSERT( hintmask->byteCount <= + sizeof ( hintmask->mask ) / sizeof ( hintmask->mask[0] ) ); + + /* set mask to all ones */ + for ( i = 0; i < hintmask->byteCount; i++ ) + hintmask->mask[i] = 0xFF; + + /* clear unused bits */ + /* bitCount -> mask, 0 -> 0, 1 -> 7f, 2 -> 3f, ... 6 -> 3, 7 -> 1 */ + hintmask->mask[hintmask->byteCount - 1] &= ~mask; + } + + + /* Type2 charstring opcodes */ + enum + { + cf2_cmdRESERVED_0, /* 0 */ + cf2_cmdHSTEM, /* 1 */ + cf2_cmdRESERVED_2, /* 2 */ + cf2_cmdVSTEM, /* 3 */ + cf2_cmdVMOVETO, /* 4 */ + cf2_cmdRLINETO, /* 5 */ + cf2_cmdHLINETO, /* 6 */ + cf2_cmdVLINETO, /* 7 */ + cf2_cmdRRCURVETO, /* 8 */ + cf2_cmdCLOSEPATH, /* 9 T1 only */ + cf2_cmdCALLSUBR, /* 10 */ + cf2_cmdRETURN, /* 11 */ + cf2_cmdESC, /* 12 */ + cf2_cmdHSBW, /* 13 T1 only */ + cf2_cmdENDCHAR, /* 14 */ + cf2_cmdVSINDEX, /* 15 */ + cf2_cmdBLEND, /* 16 */ + cf2_cmdRESERVED_17, /* 17 */ + cf2_cmdHSTEMHM, /* 18 */ + cf2_cmdHINTMASK, /* 19 */ + cf2_cmdCNTRMASK, /* 20 */ + cf2_cmdRMOVETO, /* 21 */ + cf2_cmdHMOVETO, /* 22 */ + cf2_cmdVSTEMHM, /* 23 */ + cf2_cmdRCURVELINE, /* 24 */ + cf2_cmdRLINECURVE, /* 25 */ + cf2_cmdVVCURVETO, /* 26 */ + cf2_cmdHHCURVETO, /* 27 */ + cf2_cmdEXTENDEDNMBR, /* 28 */ + cf2_cmdCALLGSUBR, /* 29 */ + cf2_cmdVHCURVETO, /* 30 */ + cf2_cmdHVCURVETO /* 31 */ + }; + + enum + { + cf2_escDOTSECTION, /* 0 */ + cf2_escVSTEM3, /* 1 T1 only */ + cf2_escHSTEM3, /* 2 T1 only */ + cf2_escAND, /* 3 */ + cf2_escOR, /* 4 */ + cf2_escNOT, /* 5 */ + cf2_escSEAC, /* 6 T1 only */ + cf2_escSBW, /* 7 T1 only */ + cf2_escRESERVED_8, /* 8 */ + cf2_escABS, /* 9 */ + cf2_escADD, /* 10 like otherADD */ + cf2_escSUB, /* 11 like otherSUB */ + cf2_escDIV, /* 12 */ + cf2_escRESERVED_13, /* 13 */ + cf2_escNEG, /* 14 */ + cf2_escEQ, /* 15 */ + cf2_escCALLOTHERSUBR,/* 16 T1 only */ + cf2_escPOP, /* 17 T1 only */ + cf2_escDROP, /* 18 */ + cf2_escRESERVED_19, /* 19 */ + cf2_escPUT, /* 20 like otherPUT */ + cf2_escGET, /* 21 like otherGET */ + cf2_escIFELSE, /* 22 like otherIFELSE */ + cf2_escRANDOM, /* 23 like otherRANDOM */ + cf2_escMUL, /* 24 like otherMUL */ + cf2_escRESERVED_25, /* 25 */ + cf2_escSQRT, /* 26 */ + cf2_escDUP, /* 27 like otherDUP */ + cf2_escEXCH, /* 28 like otherEXCH */ + cf2_escINDEX, /* 29 */ + cf2_escROLL, /* 30 */ + cf2_escRESERVED_31, /* 31 */ + cf2_escRESERVED_32, /* 32 */ + cf2_escSETCURRENTPT, /* 33 T1 only */ + cf2_escHFLEX, /* 34 */ + cf2_escFLEX, /* 35 */ + cf2_escHFLEX1, /* 36 */ + cf2_escFLEX1, /* 37 */ + cf2_escRESERVED_38 /* 38 & all higher */ + }; + + + /* `stemHintArray' does not change once we start drawing the outline. */ + static void + cf2_doStems( const CF2_Font font, + CF2_Stack opStack, + CF2_ArrStack stemHintArray, + CF2_Fixed* width, + FT_Bool* haveWidth, + CF2_Fixed hintOffset ) + { + CF2_UInt i; + CF2_UInt count = cf2_stack_count( opStack ); + FT_Bool hasWidthArg = (FT_Bool)( count & 1 ); + + /* variable accumulates delta values from operand stack */ + CF2_Fixed position = hintOffset; + + if ( font->isT1 && !font->decoder->flex_state && !*haveWidth ) + FT_ERROR(( "cf2_doStems (Type 1 mode):" + " No width. Use hsbw/sbw as first op\n" )); + + if ( !font->isT1 && hasWidthArg && !*haveWidth ) + *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ), + cf2_getNominalWidthX( font->decoder ) ); + + if ( font->decoder->width_only ) + goto exit; + + for ( i = hasWidthArg ? 1 : 0; i < count; i += 2 ) + { + /* construct a CF2_StemHint and push it onto the list */ + CF2_StemHintRec stemhint; + + + stemhint.min = + position = ADD_INT32( position, + cf2_stack_getReal( opStack, i ) ); + stemhint.max = + position = ADD_INT32( position, + cf2_stack_getReal( opStack, i + 1 ) ); + + stemhint.used = FALSE; + stemhint.maxDS = + stemhint.minDS = 0; + + cf2_arrstack_push( stemHintArray, &stemhint ); /* defer error check */ + } + + cf2_stack_clear( opStack ); + + exit: + /* cf2_doStems must define a width (may be default) */ + *haveWidth = TRUE; + } + + + static void + cf2_doFlex( CF2_Stack opStack, + CF2_Fixed* curX, + CF2_Fixed* curY, + CF2_GlyphPath glyphPath, + const FT_Bool* readFromStack, + FT_Bool doConditionalLastRead ) + { + CF2_Fixed vals[14]; + CF2_UInt idx; + FT_Bool isHFlex; + CF2_Int top, i, j; + + + vals[0] = *curX; + vals[1] = *curY; + idx = 0; + isHFlex = FT_BOOL( readFromStack[9] == FALSE ); + top = isHFlex ? 9 : 10; + + for ( i = 0; i < top; i++ ) + { + vals[i + 2] = vals[i]; + if ( readFromStack[i] ) + vals[i + 2] = ADD_INT32( vals[i + 2], cf2_stack_getReal( opStack, + idx++ ) ); + } + + if ( isHFlex ) + vals[9 + 2] = *curY; + + if ( doConditionalLastRead ) + { + FT_Bool lastIsX = (FT_Bool)( + cf2_fixedAbs( SUB_INT32( vals[10], *curX ) ) > + cf2_fixedAbs( SUB_INT32( vals[11], *curY ) ) ); + CF2_Fixed lastVal = cf2_stack_getReal( opStack, idx ); + + + if ( lastIsX ) + { + vals[12] = ADD_INT32( vals[10], lastVal ); + vals[13] = *curY; + } + else + { + vals[12] = *curX; + vals[13] = ADD_INT32( vals[11], lastVal ); + } + } + else + { + if ( readFromStack[10] ) + vals[12] = ADD_INT32( vals[10], + cf2_stack_getReal( opStack, idx++ ) ); + else + vals[12] = *curX; + + if ( readFromStack[11] ) + vals[13] = ADD_INT32( vals[11], + cf2_stack_getReal( opStack, idx ) ); + else + vals[13] = *curY; + } + + for ( j = 0; j < 2; j++ ) + cf2_glyphpath_curveTo( glyphPath, vals[j * 6 + 2], + vals[j * 6 + 3], + vals[j * 6 + 4], + vals[j * 6 + 5], + vals[j * 6 + 6], + vals[j * 6 + 7] ); + + cf2_stack_clear( opStack ); + + *curX = vals[12]; + *curY = vals[13]; + } + + + /* Blend numOperands on the stack, */ + /* store results into the first numBlends values, */ + /* then pop remaining arguments. */ + static void + cf2_doBlend( const CFF_Blend blend, + CF2_Stack opStack, + CF2_UInt numBlends ) + { + CF2_UInt delta; + CF2_UInt base; + CF2_UInt i, j; + CF2_UInt numOperands = (CF2_UInt)( numBlends * blend->lenBV ); + + + base = cf2_stack_count( opStack ) - numOperands; + delta = base + numBlends; + + for ( i = 0; i < numBlends; i++ ) + { + const CF2_Fixed* weight = &blend->BV[1]; + + /* start with first term */ + CF2_Fixed sum = cf2_stack_getReal( opStack, i + base ); + + + for ( j = 1; j < blend->lenBV; j++ ) + sum = ADD_INT32( sum, + FT_MulFix( *weight++, + cf2_stack_getReal( opStack, + delta++ ) ) ); + + /* store blended result */ + cf2_stack_setReal( opStack, i + base, sum ); + } + + /* leave only `numBlends' results on stack */ + cf2_stack_pop( opStack, numOperands - numBlends ); + } + + + /* + * `error' is a shared error code used by many objects in this + * routine. Before the code continues from an error, it must check and + * record the error in `*error'. The idea is that this shared + * error code will record the first error encountered. If testing + * for an error anyway, the cost of `goto exit' is small, so we do it, + * even if continuing would be safe. In this case, `lastError' is + * set, so the testing and storing can be done in one place, at `exit'. + * + * Continuing after an error is intended for objects which do their own + * testing of `*error', e.g., array stack functions. This allows us to + * avoid an extra test after the call. + * + * Unimplemented opcodes are ignored. + * + */ + FT_LOCAL_DEF( void ) + cf2_interpT2CharString( CF2_Font font, + CF2_Buffer buf, + CF2_OutlineCallbacks callbacks, + const FT_Vector* translation, + FT_Bool doingSeac, + CF2_Fixed curX, + CF2_Fixed curY, + CF2_Fixed* width ) + { + /* lastError is used for errors that are immediately tested */ + FT_Error lastError = FT_Err_Ok; + + /* pointer to parsed font object */ + PS_Decoder* decoder = font->decoder; + + FT_Error* error = &font->error; + FT_Memory memory = font->memory; + + CF2_Fixed scaleY = font->innerTransform.d; + CF2_Fixed nominalWidthX = cf2_getNominalWidthX( decoder ); + + /* stuff for Type 1 */ + FT_Int known_othersubr_result_cnt = 0; + FT_Bool large_int = FALSE; + FT_Bool initial_map_ready = FALSE; + +#define PS_STORAGE_SIZE 3 + CF2_F16Dot16 results[PS_STORAGE_SIZE]; /* for othersubr results */ + FT_Int result_cnt = 0; + + /* save this for hinting seac accents */ + CF2_Fixed hintOriginY = curY; + + CF2_Stack opStack = NULL; + FT_UInt stackSize; + FT_Byte op1; /* first opcode byte */ + + CF2_F16Dot16 storage[CF2_STORAGE_SIZE]; /* for `put' and `get' */ + CF2_F16Dot16 flexStore[6]; /* for Type 1 flex */ + + /* instruction limit; 20,000,000 matches Avalon */ + FT_UInt32 instructionLimit = 20000000UL; + + CF2_ArrStackRec subrStack; + + FT_Bool haveWidth; + CF2_Buffer charstring = NULL; + + CF2_Int charstringIndex = -1; /* initialize to empty */ + + /* TODO: placeholders for hint structures */ + + /* objects used for hinting */ + CF2_ArrStackRec hStemHintArray; + CF2_ArrStackRec vStemHintArray; + + CF2_HintMaskRec hintMask; + CF2_GlyphPathRec glyphPath; + + + FT_ZERO( &storage ); + FT_ZERO( &results ); + FT_ZERO( &flexStore ); + + /* initialize the remaining objects */ + cf2_arrstack_init( &subrStack, + memory, + error, + sizeof ( CF2_BufferRec ) ); + cf2_arrstack_init( &hStemHintArray, + memory, + error, + sizeof ( CF2_StemHintRec ) ); + cf2_arrstack_init( &vStemHintArray, + memory, + error, + sizeof ( CF2_StemHintRec ) ); + + /* initialize CF2_StemHint arrays */ + cf2_hintmask_init( &hintMask, error ); + + /* initialize path map to manage drawing operations */ + + /* Note: last 4 params are used to handle `MoveToPermissive', which */ + /* may need to call `hintMap.Build' */ + /* TODO: MoveToPermissive is gone; are these still needed? */ + cf2_glyphpath_init( &glyphPath, + font, + callbacks, + scaleY, + /* hShift, */ + &hStemHintArray, + &vStemHintArray, + &hintMask, + hintOriginY, + &font->blues, + translation ); + + /* + * Initialize state for width parsing. From the CFF Spec: + * + * The first stack-clearing operator, which must be one of hstem, + * hstemhm, vstem, vstemhm, cntrmask, hintmask, hmoveto, vmoveto, + * rmoveto, or endchar, takes an additional argument - the width (as + * described earlier), which may be expressed as zero or one numeric + * argument. + * + * What we implement here uses the first validly specified width, but + * does not detect errors for specifying more than one width. + * + * If one of the above operators occurs without explicitly specifying + * a width, we assume the default width. + * + * CFF2 charstrings always return the default width (0). + * + */ + haveWidth = font->isCFF2 ? TRUE : FALSE; + *width = cf2_getDefaultWidthX( decoder ); + + /* + * Note: At this point, all pointers to resources must be NULL + * and all local objects must be initialized. + * There must be no branches to `exit:' above this point. + * + */ + + /* allocate an operand stack */ + stackSize = font->isCFF2 ? cf2_getMaxstack( decoder ) + : CF2_OPERAND_STACK_SIZE; + opStack = cf2_stack_init( memory, error, stackSize ); + + if ( !opStack ) + { + lastError = FT_THROW( Out_Of_Memory ); + goto exit; + } + + /* initialize subroutine stack by placing top level charstring as */ + /* first element (max depth plus one for the charstring) */ + /* Note: Caller owns and must finalize the first charstring. */ + /* Our copy of it does not change that requirement. */ + cf2_arrstack_setCount( &subrStack, CF2_MAX_SUBR + 1 ); + + charstring = (CF2_Buffer)cf2_arrstack_getBuffer( &subrStack ); + *charstring = *buf; /* structure copy */ + + charstringIndex = 0; /* entry is valid now */ + + /* catch errors so far */ + if ( *error ) + goto exit; + + /* main interpreter loop */ + while ( 1 ) + { + if ( font->isT1 ) + FT_ASSERT( known_othersubr_result_cnt == 0 || + result_cnt == 0 ); + + if ( cf2_buf_isEnd( charstring ) ) + { + /* If we've reached the end of the charstring, simulate a */ + /* cf2_cmdRETURN or cf2_cmdENDCHAR. */ + /* We do this for both CFF and CFF2. */ + if ( charstringIndex ) + op1 = cf2_cmdRETURN; /* end of buffer for subroutine */ + else + op1 = cf2_cmdENDCHAR; /* end of buffer for top level charstring */ + } + else + { + op1 = (FT_Byte)cf2_buf_readByte( charstring ); + + /* Explicit RETURN and ENDCHAR in CFF2 should be ignored. */ + /* Note: Trace message will report 0 instead of 11 or 14. */ + if ( ( op1 == cf2_cmdRETURN || op1 == cf2_cmdENDCHAR ) && + font->isCFF2 ) + op1 = cf2_cmdRESERVED_0; + } + + if ( font->isT1 ) + { + if ( !initial_map_ready && + !( op1 == cf2_cmdHSTEM || + op1 == cf2_cmdVSTEM || + op1 == cf2_cmdHSBW || + op1 == cf2_cmdCALLSUBR || + op1 == cf2_cmdRETURN || + op1 == cf2_cmdESC || + op1 == cf2_cmdENDCHAR || + op1 >= 32 /* Numbers */ ) ) + { + /* Skip outline commands first time round. */ + /* `endchar' will trigger initial hintmap build */ + /* and rewind the charstring. */ + cf2_stack_clear( opStack ); + continue; + } + + if ( result_cnt > 0 && + !( op1 == cf2_cmdCALLSUBR || + op1 == cf2_cmdRETURN || + op1 == cf2_cmdESC || + op1 >= 32 /* Numbers */ ) ) + { + /* all operands have been transferred by previous pops */ + result_cnt = 0; + } + + if ( large_int && !( op1 >= 32 || op1 == cf2_escDIV ) ) + { + FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):" + " no `div' after large integer\n" )); + + large_int = FALSE; + } + } + + /* check for errors once per loop */ + if ( *error ) + goto exit; + + instructionLimit--; + if ( instructionLimit == 0 ) + { + lastError = FT_THROW( Invalid_Glyph_Format ); + goto exit; + } + + switch( op1 ) + { + case cf2_cmdRESERVED_0: + case cf2_cmdRESERVED_2: + case cf2_cmdRESERVED_17: + /* we may get here if we have a prior error */ + FT_TRACE4(( " unknown op (%d)\n", op1 )); + break; + + case cf2_cmdVSINDEX: + FT_TRACE4(( " vsindex\n" )); + + if ( !font->isCFF2 ) + break; /* clear stack & ignore */ + + if ( font->blend.usedBV ) + { + /* vsindex not allowed after blend */ + lastError = FT_THROW( Invalid_Glyph_Format ); + goto exit; + } + + { + FT_Int temp = cf2_stack_popInt( opStack ); + + + if ( temp >= 0 ) + font->vsindex = (FT_UInt)temp; + } + break; + + case cf2_cmdBLEND: + { + FT_UInt numBlends; + + + FT_TRACE4(( " blend\n" )); + + if ( !font->isCFF2 ) + break; /* clear stack & ignore */ + + /* do we have a `blend' op in a non-variant font? */ + if ( !font->blend.font ) + { + lastError = FT_THROW( Invalid_Glyph_Format ); + goto exit; + } + + /* check cached blend vector */ + if ( font->cffload->blend_check_vector( &font->blend, + font->vsindex, + font->lenNDV, + font->NDV ) ) + { + lastError = font->cffload->blend_build_vector( &font->blend, + font->vsindex, + font->lenNDV, + font->NDV ); + if ( lastError ) + goto exit; + } + + /* do the blend */ + numBlends = (FT_UInt)cf2_stack_popInt( opStack ); + if ( numBlends > stackSize ) + { + lastError = FT_THROW( Invalid_Glyph_Format ); + goto exit; + } + + cf2_doBlend( &font->blend, opStack, numBlends ); + + font->blend.usedBV = TRUE; + } + continue; /* do not clear the stack */ + + case cf2_cmdHSTEMHM: + case cf2_cmdHSTEM: + FT_TRACE4(( op1 == cf2_cmdHSTEMHM ? " hstemhm\n" : " hstem\n" )); + + if ( !font->isT1 ) + { + /* never add hints after the mask is computed */ + /* except if in Type 1 mode (no hintmask op) */ + if ( cf2_hintmask_isValid( &hintMask ) ) + { + FT_TRACE4(( "cf2_interpT2CharString:" + " invalid horizontal hint mask\n" )); + break; + } + } + + /* add left-sidebearing correction in Type 1 mode */ + cf2_doStems( font, + opStack, + &hStemHintArray, + width, + &haveWidth, + font->isT1 ? decoder->builder.left_bearing->y + : 0 ); + + if ( decoder->width_only ) + goto exit; + + break; + + case cf2_cmdVSTEMHM: + case cf2_cmdVSTEM: + FT_TRACE4(( op1 == cf2_cmdVSTEMHM ? " vstemhm\n" : " vstem\n" )); + + if ( !font->isT1 ) + { + /* never add hints after the mask is computed */ + /* except if in Type 1 mode (no hintmask op) */ + if ( cf2_hintmask_isValid( &hintMask ) ) + { + FT_TRACE4(( "cf2_interpT2CharString:" + " invalid vertical hint mask\n" )); + break; + } + } + + /* add left-sidebearing correction in Type 1 mode */ + cf2_doStems( font, + opStack, + &vStemHintArray, + width, + &haveWidth, + font->isT1 ? decoder->builder.left_bearing->x + : 0 ); + + if ( decoder->width_only ) + goto exit; + + break; + + case cf2_cmdVMOVETO: + FT_TRACE4(( " vmoveto\n" )); + + if ( font->isT1 && !decoder->flex_state && !haveWidth ) + FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):" + " No width. Use hsbw/sbw as first op\n" )); + + if ( cf2_stack_count( opStack ) > 1 && !haveWidth ) + *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ), + nominalWidthX ); + + /* width is defined or default after this */ + haveWidth = TRUE; + + if ( decoder->width_only ) + goto exit; + + curY = ADD_INT32( curY, cf2_stack_popFixed( opStack ) ); + + if ( !decoder->flex_state ) + cf2_glyphpath_moveTo( &glyphPath, curX, curY ); + + break; + + case cf2_cmdRLINETO: + { + CF2_UInt idx; + CF2_UInt count = cf2_stack_count( opStack ); + + + FT_TRACE4(( " rlineto\n" )); + + for ( idx = 0; idx < count; idx += 2 ) + { + curX = ADD_INT32( curX, cf2_stack_getReal( opStack, + idx + 0 ) ); + curY = ADD_INT32( curY, cf2_stack_getReal( opStack, + idx + 1 ) ); + + cf2_glyphpath_lineTo( &glyphPath, curX, curY ); + } + + cf2_stack_clear( opStack ); + } + continue; /* no need to clear stack again */ + + case cf2_cmdHLINETO: + case cf2_cmdVLINETO: + { + CF2_UInt idx; + CF2_UInt count = cf2_stack_count( opStack ); + + FT_Bool isX = FT_BOOL( op1 == cf2_cmdHLINETO ); + + + FT_TRACE4(( isX ? " hlineto\n" : " vlineto\n" )); + + for ( idx = 0; idx < count; idx++ ) + { + CF2_Fixed v = cf2_stack_getReal( opStack, idx ); + + + if ( isX ) + curX = ADD_INT32( curX, v ); + else + curY = ADD_INT32( curY, v ); + + isX = !isX; + + cf2_glyphpath_lineTo( &glyphPath, curX, curY ); + } + + cf2_stack_clear( opStack ); + } + continue; + + case cf2_cmdRCURVELINE: + case cf2_cmdRRCURVETO: + { + CF2_UInt count = cf2_stack_count( opStack ); + CF2_UInt idx = 0; + + + FT_TRACE4(( op1 == cf2_cmdRCURVELINE ? " rcurveline\n" + : " rrcurveto\n" )); + + while ( idx + 6 <= count ) + { + CF2_Fixed x1, y1, x2, y2, x3, y3; + + + x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX ); + y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), curY ); + x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), x1 ); + y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y1 ); + x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 ); + y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 5 ), y2 ); + + cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); + + curX = x3; + curY = y3; + idx += 6; + } + + if ( op1 == cf2_cmdRCURVELINE ) + { + curX = ADD_INT32( curX, cf2_stack_getReal( opStack, + idx + 0 ) ); + curY = ADD_INT32( curY, cf2_stack_getReal( opStack, + idx + 1 ) ); + + cf2_glyphpath_lineTo( &glyphPath, curX, curY ); + } + + cf2_stack_clear( opStack ); + } + continue; /* no need to clear stack again */ + + case cf2_cmdCLOSEPATH: + if ( !font->isT1 ) + FT_TRACE4(( " unknown op (%d)\n", op1 )); + else + { + FT_TRACE4(( " closepath" )); + + /* if there is no path, `closepath' is a no-op */ + ps_builder_close_contour( &decoder->builder ); + + haveWidth = TRUE; + } + break; + + case cf2_cmdCALLGSUBR: + case cf2_cmdCALLSUBR: + { + CF2_Int subrNum; + + + FT_TRACE4(( op1 == cf2_cmdCALLGSUBR ? " callgsubr" + : " callsubr" )); + + if ( ( !font->isT1 && charstringIndex > CF2_MAX_SUBR ) || + ( font->isT1 && charstringIndex > T1_MAX_SUBRS_CALLS ) ) + { + /* max subr plus one for charstring */ + lastError = FT_THROW( Invalid_Glyph_Format ); + goto exit; /* overflow of stack */ + } + + /* push our current CFF charstring region on subrStack */ + charstring = (CF2_Buffer) + cf2_arrstack_getPointer( + &subrStack, + (size_t)charstringIndex + 1 ); + + /* set up the new CFF region and pointer */ + subrNum = cf2_stack_popInt( opStack ); + + if ( font->isT1 && decoder->locals_hash ) + { + size_t* val = ft_hash_num_lookup( subrNum, + decoder->locals_hash ); + + + if ( val ) + subrNum = *val; + else + subrNum = -1; + } + + switch ( op1 ) + { + case cf2_cmdCALLGSUBR: + FT_TRACE4(( " (idx %d, entering level %d)\n", + subrNum + decoder->globals_bias, + charstringIndex + 1 )); + + if ( cf2_initGlobalRegionBuffer( decoder, + subrNum, + charstring ) ) + { + lastError = FT_THROW( Invalid_Glyph_Format ); + goto exit; /* subroutine lookup or stream error */ + } + break; + + default: + /* cf2_cmdCALLSUBR */ + FT_TRACE4(( " (idx %d, entering level %d)\n", + subrNum + decoder->locals_bias, + charstringIndex + 1 )); + + if ( cf2_initLocalRegionBuffer( decoder, + subrNum, + charstring ) ) + { + lastError = FT_THROW( Invalid_Glyph_Format ); + goto exit; /* subroutine lookup or stream error */ + } + } + + charstringIndex += 1; /* entry is valid now */ + } + continue; /* do not clear the stack */ + + case cf2_cmdRETURN: + FT_TRACE4(( " return (leaving level %d)\n", charstringIndex )); + + if ( charstringIndex < 1 ) + { + /* Note: cannot return from top charstring */ + lastError = FT_THROW( Invalid_Glyph_Format ); + goto exit; /* underflow of stack */ + } + + /* restore position in previous charstring */ + charstring = (CF2_Buffer) + cf2_arrstack_getPointer( + &subrStack, + (CF2_UInt)--charstringIndex ); + continue; /* do not clear the stack */ + + case cf2_cmdESC: + { + FT_Byte op2 = (FT_Byte)cf2_buf_readByte( charstring ); + + + /* first switch for 2-byte operators handles CFF2 */ + /* and opcodes that are reserved for both CFF and CFF2 */ + switch ( op2 ) + { + case cf2_escHFLEX: + { + static const FT_Bool readFromStack[12] = + { + TRUE /* dx1 */, FALSE /* dy1 */, + TRUE /* dx2 */, TRUE /* dy2 */, + TRUE /* dx3 */, FALSE /* dy3 */, + TRUE /* dx4 */, FALSE /* dy4 */, + TRUE /* dx5 */, FALSE /* dy5 */, + TRUE /* dx6 */, FALSE /* dy6 */ + }; + + + FT_TRACE4(( " hflex\n" )); + + cf2_doFlex( opStack, + &curX, + &curY, + &glyphPath, + readFromStack, + FALSE /* doConditionalLastRead */ ); + } + continue; + + case cf2_escFLEX: + { + static const FT_Bool readFromStack[12] = + { + TRUE /* dx1 */, TRUE /* dy1 */, + TRUE /* dx2 */, TRUE /* dy2 */, + TRUE /* dx3 */, TRUE /* dy3 */, + TRUE /* dx4 */, TRUE /* dy4 */, + TRUE /* dx5 */, TRUE /* dy5 */, + TRUE /* dx6 */, TRUE /* dy6 */ + }; + + + FT_TRACE4(( " flex\n" )); + + cf2_doFlex( opStack, + &curX, + &curY, + &glyphPath, + readFromStack, + FALSE /* doConditionalLastRead */ ); + } + break; /* TODO: why is this not a continue? */ + + case cf2_escHFLEX1: + { + static const FT_Bool readFromStack[12] = + { + TRUE /* dx1 */, TRUE /* dy1 */, + TRUE /* dx2 */, TRUE /* dy2 */, + TRUE /* dx3 */, FALSE /* dy3 */, + TRUE /* dx4 */, FALSE /* dy4 */, + TRUE /* dx5 */, TRUE /* dy5 */, + TRUE /* dx6 */, FALSE /* dy6 */ + }; + + + FT_TRACE4(( " hflex1\n" )); + + cf2_doFlex( opStack, + &curX, + &curY, + &glyphPath, + readFromStack, + FALSE /* doConditionalLastRead */ ); + } + continue; + + case cf2_escFLEX1: + { + static const FT_Bool readFromStack[12] = + { + TRUE /* dx1 */, TRUE /* dy1 */, + TRUE /* dx2 */, TRUE /* dy2 */, + TRUE /* dx3 */, TRUE /* dy3 */, + TRUE /* dx4 */, TRUE /* dy4 */, + TRUE /* dx5 */, TRUE /* dy5 */, + FALSE /* dx6 */, FALSE /* dy6 */ + }; + + + FT_TRACE4(( " flex1\n" )); + + cf2_doFlex( opStack, + &curX, + &curY, + &glyphPath, + readFromStack, + TRUE /* doConditionalLastRead */ ); + } + continue; + + /* these opcodes are always reserved */ + case cf2_escRESERVED_8: + case cf2_escRESERVED_13: + case cf2_escRESERVED_19: + case cf2_escRESERVED_25: + case cf2_escRESERVED_31: + case cf2_escRESERVED_32: + FT_TRACE4(( " unknown op (12, %d)\n", op2 )); + break; + + default: + { + if ( font->isCFF2 || op2 >= cf2_escRESERVED_38 ) + FT_TRACE4(( " unknown op (12, %d)\n", op2 )); + else if ( font->isT1 && result_cnt > 0 && op2 != cf2_escPOP ) + { + /* all operands have been transferred by previous pops */ + result_cnt = 0; + } + else + { + /* second switch for 2-byte operators handles */ + /* CFF and Type 1 */ + switch ( op2 ) + { + + case cf2_escDOTSECTION: + /* something about `flip type of locking' -- ignore it */ + FT_TRACE4(( " dotsection\n" )); + + break; + + case cf2_escVSTEM3: + case cf2_escHSTEM3: + /* + * Type 1: Type 2: + * x0 dx0 x1 dx1 x2 dx2 vstem3 x dx {dxa dxb}* vstem + * y0 dy0 y1 dy1 y2 dy2 hstem3 y dy {dya dyb}* hstem + * relative to lsb point relative to zero + * + */ + { + if ( !font->isT1 ) + FT_TRACE4(( " unknown op (12, %d)\n", op2 )); + else + { + CF2_F16Dot16 v0, v1, v2; + + FT_Bool isV = FT_BOOL( op2 == cf2_escVSTEM3 ); + + + FT_TRACE4(( isV ? " vstem3\n" + : " hstem3\n" )); + + FT_ASSERT( cf2_stack_count( opStack ) == 6 ); + + v0 = cf2_stack_getReal( opStack, 0 ); + v1 = cf2_stack_getReal( opStack, 2 ); + v2 = cf2_stack_getReal( opStack, 4 ); + + cf2_stack_setReal( + opStack, 2, + SUB_INT32( SUB_INT32( v1, v0 ), + cf2_stack_getReal( opStack, 1 ) ) ); + cf2_stack_setReal( + opStack, 4, + SUB_INT32( SUB_INT32( v2, v1 ), + cf2_stack_getReal( opStack, 3 ) ) ); + + /* add left-sidebearing correction */ + cf2_doStems( font, + opStack, + isV ? &vStemHintArray : &hStemHintArray, + width, + &haveWidth, + isV ? decoder->builder.left_bearing->x + : decoder->builder.left_bearing->y ); + + if ( decoder->width_only ) + goto exit; + } + } + break; + + case cf2_escAND: + { + CF2_F16Dot16 arg1; + CF2_F16Dot16 arg2; + + + FT_TRACE4(( " and\n" )); + + arg2 = cf2_stack_popFixed( opStack ); + arg1 = cf2_stack_popFixed( opStack ); + + cf2_stack_pushInt( opStack, arg1 && arg2 ); + } + continue; /* do not clear the stack */ + + case cf2_escOR: + { + CF2_F16Dot16 arg1; + CF2_F16Dot16 arg2; + + + FT_TRACE4(( " or\n" )); + + arg2 = cf2_stack_popFixed( opStack ); + arg1 = cf2_stack_popFixed( opStack ); + + cf2_stack_pushInt( opStack, arg1 || arg2 ); + } + continue; /* do not clear the stack */ + + case cf2_escNOT: + { + CF2_F16Dot16 arg; + + + FT_TRACE4(( " not\n" )); + + arg = cf2_stack_popFixed( opStack ); + + cf2_stack_pushInt( opStack, !arg ); + } + continue; /* do not clear the stack */ + + case cf2_escSEAC: + if ( !font->isT1 ) + FT_TRACE4(( " unknown op (12, %d)\n", op2 )); + else + { + FT_Error error2; + CF2_Int bchar_index, achar_index; + FT_Vector left_bearing, advance; + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + T1_Face face = (T1_Face)decoder->builder.face; +#endif + CF2_BufferRec component; + CF2_Fixed dummyWidth; + + CF2_Int achar = cf2_stack_popInt( opStack ); + CF2_Int bchar = cf2_stack_popInt( opStack ); + + FT_Pos ady = cf2_stack_popFixed ( opStack ); + FT_Pos adx = cf2_stack_popFixed ( opStack ); + FT_Pos asb = cf2_stack_popFixed ( opStack ); + + + FT_TRACE4(( " seac\n" )); + + if ( doingSeac ) + { + FT_ERROR(( " nested seac\n" )); + lastError = FT_THROW( Invalid_Glyph_Format ); + goto exit; /* nested seac */ + } + + if ( decoder->builder.metrics_only ) + { + FT_ERROR(( " unexpected seac\n" )); + lastError = FT_THROW( Invalid_Glyph_Format ); + goto exit; /* unexpected seac */ + } + + /* `glyph_names' is set to 0 for CID fonts which do */ + /* not include an encoding. How can we deal with */ + /* these? */ +#ifdef FT_CONFIG_OPTION_INCREMENTAL + if ( decoder->glyph_names == 0 && + !face->root.internal->incremental_interface ) +#else + if ( decoder->glyph_names == 0 ) +#endif /* FT_CONFIG_OPTION_INCREMENTAL */ + { + FT_ERROR(( + "cf2_interpT2CharString: (Type 1 seac)" + " glyph names table not available in this font\n" )); + lastError = FT_THROW( Invalid_Glyph_Format ); + goto exit; + } + + /* seac weirdness */ + adx += decoder->builder.left_bearing->x; + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + if ( face->root.internal->incremental_interface ) + { + /* the caller must handle the font encoding also */ + bchar_index = bchar; + achar_index = achar; + } + else +#endif + { + bchar_index = t1_lookup_glyph_by_stdcharcode_ps( + decoder, bchar ); + achar_index = t1_lookup_glyph_by_stdcharcode_ps( + decoder, achar ); + } + + if ( bchar_index < 0 || achar_index < 0 ) + { + FT_ERROR(( + "cf2_interpT2CharString: (Type 1 seac)" + " invalid seac character code arguments\n" )); + lastError = FT_THROW( Invalid_Glyph_Format ); + goto exit; + } + + /* if we are trying to load a composite glyph, */ + /* do not load the accent character and return */ + /* the array of subglyphs. */ + if ( decoder->builder.no_recurse ) + { + FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph; + FT_GlyphLoader loader = glyph->internal->loader; + FT_SubGlyph subg; + + + /* reallocate subglyph array if necessary */ + error2 = FT_GlyphLoader_CheckSubGlyphs( loader, 2 ); + if ( error2 ) + { + lastError = error2; /* pass FreeType error through */ + goto exit; + } + + subg = loader->current.subglyphs; + + /* subglyph 0 = base character */ + subg->index = bchar_index; + subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES | + FT_SUBGLYPH_FLAG_USE_MY_METRICS; + subg->arg1 = 0; + subg->arg2 = 0; + subg++; + + /* subglyph 1 = accent character */ + subg->index = achar_index; + subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES; + subg->arg1 = (FT_Int)FIXED_TO_INT( adx - asb ); + subg->arg2 = (FT_Int)FIXED_TO_INT( ady ); + + /* set up remaining glyph fields */ + glyph->num_subglyphs = 2; + glyph->subglyphs = loader->base.subglyphs; + glyph->format = FT_GLYPH_FORMAT_COMPOSITE; + + loader->current.num_subglyphs = 2; + + goto exit; + } + + /* First load `bchar' in builder */ + /* now load the unscaled outline */ + + /* prepare loader */ + FT_GlyphLoader_Prepare( decoder->builder.loader ); + + error2 = cf2_getT1SeacComponent( decoder, + (FT_UInt)bchar_index, + &component ); + if ( error2 ) + { + lastError = error2; /* pass FreeType error through */ + goto exit; + } + cf2_interpT2CharString( font, + &component, + callbacks, + translation, + TRUE, + 0, + 0, + &dummyWidth ); + cf2_freeT1SeacComponent( decoder, &component ); + + /* save the left bearing and width of the base */ + /* character as they will be erased by the next load */ + + left_bearing = *decoder->builder.left_bearing; + advance = *decoder->builder.advance; + + decoder->builder.left_bearing->x = 0; + decoder->builder.left_bearing->y = 0; + + /* Now load `achar' on top of */ + /* the base outline */ + + error2 = cf2_getT1SeacComponent( decoder, + (FT_UInt)achar_index, + &component ); + if ( error2 ) + { + lastError = error2; /* pass FreeType error through */ + goto exit; + } + cf2_interpT2CharString( font, + &component, + callbacks, + translation, + TRUE, + adx - asb, + ady, + &dummyWidth ); + cf2_freeT1SeacComponent( decoder, &component ); + + /* restore the left side bearing and */ + /* advance width of the base character */ + + *decoder->builder.left_bearing = left_bearing; + *decoder->builder.advance = advance; + + goto exit; + } + break; + + case cf2_escSBW: + if ( !font->isT1 ) + FT_TRACE4(( " unknown op (12, %d)\n", op2 )); + else + { + CF2_Fixed lsb_x, lsb_y; + PS_Builder* builder; + + + FT_TRACE4(( " sbw" )); + + builder = &decoder->builder; + + builder->advance->y = cf2_stack_popFixed( opStack ); + builder->advance->x = cf2_stack_popFixed( opStack ); + + lsb_y = cf2_stack_popFixed( opStack ); + lsb_x = cf2_stack_popFixed( opStack ); + + builder->left_bearing->x = + ADD_INT32( builder->left_bearing->x, lsb_x ); + builder->left_bearing->y = + ADD_INT32( builder->left_bearing->y, lsb_y ); + + haveWidth = TRUE; + + /* the `metrics_only' indicates that we only want */ + /* to compute the glyph's metrics (lsb + advance */ + /* width), not load the rest of it; so exit */ + /* immediately */ + if ( builder->metrics_only ) + goto exit; + + if ( initial_map_ready ) + { + curX = ADD_INT32( curX, lsb_x ); + curY = ADD_INT32( curY, lsb_y ); + } + } + break; + + case cf2_escABS: + { + CF2_F16Dot16 arg; + + + FT_TRACE4(( " abs\n" )); + + arg = cf2_stack_popFixed( opStack ); + + if ( arg < -CF2_FIXED_MAX ) + cf2_stack_pushFixed( opStack, CF2_FIXED_MAX ); + else + cf2_stack_pushFixed( opStack, FT_ABS( arg ) ); + } + continue; /* do not clear the stack */ + + case cf2_escADD: + { + CF2_F16Dot16 summand1; + CF2_F16Dot16 summand2; + + + FT_TRACE4(( " add\n" )); + + summand2 = cf2_stack_popFixed( opStack ); + summand1 = cf2_stack_popFixed( opStack ); + + cf2_stack_pushFixed( opStack, + ADD_INT32( summand1, + summand2 ) ); + } + continue; /* do not clear the stack */ + + case cf2_escSUB: + { + CF2_F16Dot16 minuend; + CF2_F16Dot16 subtrahend; + + + FT_TRACE4(( " sub\n" )); + + subtrahend = cf2_stack_popFixed( opStack ); + minuend = cf2_stack_popFixed( opStack ); + + cf2_stack_pushFixed( opStack, + SUB_INT32( minuend, subtrahend ) ); + } + continue; /* do not clear the stack */ + + case cf2_escDIV: + { + CF2_F16Dot16 dividend; + CF2_F16Dot16 divisor; + + + FT_TRACE4(( " div\n" )); + + if ( font->isT1 && large_int ) + { + divisor = (CF2_F16Dot16)cf2_stack_popInt( opStack ); + dividend = (CF2_F16Dot16)cf2_stack_popInt( opStack ); + + large_int = FALSE; + } + else + { + divisor = cf2_stack_popFixed( opStack ); + dividend = cf2_stack_popFixed( opStack ); + } + + cf2_stack_pushFixed( opStack, + FT_DivFix( dividend, divisor ) ); + + } + continue; /* do not clear the stack */ + + case cf2_escNEG: + { + CF2_F16Dot16 arg; + + + FT_TRACE4(( " neg\n" )); + + arg = cf2_stack_popFixed( opStack ); + + if ( arg < -CF2_FIXED_MAX ) + cf2_stack_pushFixed( opStack, CF2_FIXED_MAX ); + else + cf2_stack_pushFixed( opStack, -arg ); + } + continue; /* do not clear the stack */ + + case cf2_escEQ: + { + CF2_F16Dot16 arg1; + CF2_F16Dot16 arg2; + + + FT_TRACE4(( " eq\n" )); + + arg2 = cf2_stack_popFixed( opStack ); + arg1 = cf2_stack_popFixed( opStack ); + + cf2_stack_pushInt( opStack, arg1 == arg2 ); + } + continue; /* do not clear the stack */ + + case cf2_escCALLOTHERSUBR: + if ( !font->isT1 ) + FT_TRACE4(( " unknown op (12, %d)\n", op2 )); + else + { + CF2_Int subr_no; + CF2_Int arg_cnt; + CF2_UInt count; + CF2_UInt opIdx = 0; + + + FT_TRACE4(( " callothersubr\n" )); + + subr_no = cf2_stack_popInt( opStack ); + arg_cnt = cf2_stack_popInt( opStack ); + + /*******************************************************/ + /* */ + /* remove all operands to callothersubr from the stack */ + /* */ + /* for handled othersubrs, where we know the number of */ + /* arguments, we increase the stack by the value of */ + /* known_othersubr_result_cnt */ + /* */ + /* for unhandled othersubrs the following pops adjust */ + /* the stack pointer as necessary */ + + count = cf2_stack_count( opStack ); + FT_ASSERT( (CF2_UInt)arg_cnt <= count ); + + opIdx += count - (CF2_UInt)arg_cnt; + + known_othersubr_result_cnt = 0; + result_cnt = 0; + + /* XXX TODO: The checks to `arg_count == <whatever>' */ + /* might not be correct; an othersubr expects a */ + /* certain number of operands on the PostScript stack */ + /* (as opposed to the T1 stack) but it doesn't have to */ + /* put them there by itself; previous othersubrs might */ + /* have left the operands there if they were not */ + /* followed by an appropriate number of pops */ + /* */ + /* On the other hand, Adobe Reader 7.0.8 for Linux */ + /* doesn't accept a font that contains charstrings */ + /* like */ + /* */ + /* 100 200 2 20 callothersubr */ + /* 300 1 20 callothersubr pop */ + /* */ + /* Perhaps this is the reason why BuildCharArray */ + /* exists. */ + + switch ( subr_no ) + { + case 0: /* end flex feature */ + if ( arg_cnt != 3 ) + goto Unexpected_OtherSubr; + + if ( initial_map_ready && + ( !decoder->flex_state || + decoder->num_flex_vectors != 7 ) ) + { + FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):" + " unexpected flex end\n" )); + lastError = FT_THROW( Invalid_Glyph_Format ); + goto exit; + } + + /* the two `results' are popped */ + /* by the following setcurrentpoint */ + cf2_stack_pushFixed( opStack, curX ); + cf2_stack_pushFixed( opStack, curY ); + known_othersubr_result_cnt = 2; + break; + + case 1: /* start flex feature */ + if ( arg_cnt != 0 ) + goto Unexpected_OtherSubr; + + if ( !initial_map_ready ) + break; + + if ( ps_builder_check_points( &decoder->builder, 6 ) ) + goto exit; + + decoder->flex_state = 1; + decoder->num_flex_vectors = 0; + break; + + case 2: /* add flex vectors */ + { + FT_Int idx; + FT_Int idx2; + + + if ( arg_cnt != 0 ) + goto Unexpected_OtherSubr; + + if ( !initial_map_ready ) + break; + + if ( !decoder->flex_state ) + { + FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):" + " missing flex start\n" )); + lastError = FT_THROW( Invalid_Glyph_Format ); + goto exit; + } + + /* note that we should not add a point for */ + /* index 0; this will move our current position */ + /* to the flex point without adding any point */ + /* to the outline */ + idx = decoder->num_flex_vectors++; + if ( idx > 0 && idx < 7 ) + { + /* in malformed fonts it is possible to have */ + /* other opcodes in the middle of a flex (which */ + /* don't increase `num_flex_vectors'); we thus */ + /* have to check whether we can add a point */ + + if ( ps_builder_check_points( &decoder->builder, + 1 ) ) + { + lastError = FT_THROW( Invalid_Glyph_Format ); + goto exit; + } + + /* map: 1->2 2->4 3->6 4->2 5->4 6->6 */ + idx2 = ( idx > 3 ? idx - 3 : idx ) * 2; + + flexStore[idx2 - 2] = curX; + flexStore[idx2 - 1] = curY; + + if ( idx == 3 || idx == 6 ) + cf2_glyphpath_curveTo( &glyphPath, + flexStore[0], + flexStore[1], + flexStore[2], + flexStore[3], + flexStore[4], + flexStore[5] ); + } + } + break; + + case 3: /* change hints */ + if ( arg_cnt != 1 ) + goto Unexpected_OtherSubr; + + if ( initial_map_ready ) + { + /* do not clear hints if initial hintmap */ + /* is not ready - we need to collate all */ + cf2_arrstack_clear( &vStemHintArray ); + cf2_arrstack_clear( &hStemHintArray ); + + cf2_hintmask_init( &hintMask, error ); + hintMask.isValid = FALSE; + hintMask.isNew = TRUE; + } + + known_othersubr_result_cnt = 1; + break; + + case 12: + case 13: + /* counter control hints, clear stack */ + cf2_stack_clear( opStack ); + break; + + case 14: + case 15: + case 16: + case 17: + case 18: /* multiple masters */ + { + PS_Blend blend = decoder->blend; + FT_UInt num_points, nn, mm; + CF2_UInt delta; + CF2_UInt values; + + + if ( !blend ) + { + FT_ERROR(( + "cf2_interpT2CharString:" + " unexpected multiple masters operator\n" )); + lastError = FT_THROW( Invalid_Glyph_Format ); + goto exit; + } + + num_points = (FT_UInt)subr_no - 13 + + ( subr_no == 18 ); + if ( arg_cnt != (FT_Int)( num_points * + blend->num_designs ) ) + { + FT_ERROR(( + "cf2_interpT2CharString:" + " incorrect number of multiple masters arguments\n" )); + lastError = FT_THROW( Invalid_Glyph_Format ); + goto exit; + } + + /* We want to compute */ + /* */ + /* a0*w0 + a1*w1 + ... + ak*wk */ + /* */ + /* but we only have a0, a1-a0, a2-a0, ..., ak-a0. */ + /* */ + /* However, given that w0 + w1 + ... + wk == 1, we */ + /* can rewrite it easily as */ + /* */ + /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + ... + (ak-a0)*wk */ + /* */ + /* where k == num_designs-1. */ + /* */ + /* I guess that's why it's written in this `compact' */ + /* form. */ + /* */ + delta = opIdx + num_points; + values = opIdx; + for ( nn = 0; nn < num_points; nn++ ) + { + CF2_Fixed tmp = cf2_stack_getReal( opStack, + values ); + + + for ( mm = 1; mm < blend->num_designs; mm++ ) + tmp = ADD_INT32( tmp, + FT_MulFix( + cf2_stack_getReal( opStack, + delta++ ), + blend->weight_vector[mm] ) ); + + cf2_stack_setReal( opStack, values++, tmp ); + } + cf2_stack_pop( opStack, + (CF2_UInt)arg_cnt - num_points ); + + known_othersubr_result_cnt = (FT_Int)num_points; + break; + } + + case 19: + /* <idx> 1 19 callothersubr */ + /* ==> replace elements starting from index */ + /* cvi( <idx> ) of BuildCharArray with */ + /* WeightVector */ + { + FT_Int idx; + PS_Blend blend = decoder->blend; + + + if ( arg_cnt != 1 || !blend ) + goto Unexpected_OtherSubr; + + idx = cf2_stack_popInt( opStack ); + + if ( idx < 0 || + (FT_UInt)idx + blend->num_designs > + decoder->len_buildchar ) + goto Unexpected_OtherSubr; + + ft_memcpy( &decoder->buildchar[idx], + blend->weight_vector, + blend->num_designs * + sizeof ( blend->weight_vector[0] ) ); + } + break; + + case 20: + /* <arg1> <arg2> 2 20 callothersubr pop */ + /* ==> push <arg1> + <arg2> onto T1 stack */ + { + CF2_F16Dot16 summand1; + CF2_F16Dot16 summand2; + + + if ( arg_cnt != 2 ) + goto Unexpected_OtherSubr; + + summand2 = cf2_stack_popFixed( opStack ); + summand1 = cf2_stack_popFixed( opStack ); + + cf2_stack_pushFixed( opStack, + ADD_INT32( summand1, + summand2 ) ); + known_othersubr_result_cnt = 1; + } + break; + + case 21: + /* <arg1> <arg2> 2 21 callothersubr pop */ + /* ==> push <arg1> - <arg2> onto T1 stack */ + { + CF2_F16Dot16 minuend; + CF2_F16Dot16 subtrahend; + + + if ( arg_cnt != 2 ) + goto Unexpected_OtherSubr; + + subtrahend = cf2_stack_popFixed( opStack ); + minuend = cf2_stack_popFixed( opStack ); + + cf2_stack_pushFixed( opStack, + SUB_INT32( minuend, + subtrahend ) ); + known_othersubr_result_cnt = 1; + } + break; + + case 22: + /* <arg1> <arg2> 2 22 callothersubr pop */ + /* ==> push <arg1> * <arg2> onto T1 stack */ + { + CF2_F16Dot16 factor1; + CF2_F16Dot16 factor2; + + + if ( arg_cnt != 2 ) + goto Unexpected_OtherSubr; + + factor2 = cf2_stack_popFixed( opStack ); + factor1 = cf2_stack_popFixed( opStack ); + + cf2_stack_pushFixed( opStack, + FT_MulFix( factor1, factor2 ) ); + known_othersubr_result_cnt = 1; + } + break; + + case 23: + /* <arg1> <arg2> 2 23 callothersubr pop */ + /* ==> push <arg1> / <arg2> onto T1 stack */ + { + CF2_F16Dot16 dividend; + CF2_F16Dot16 divisor; + + + if ( arg_cnt != 2 ) + goto Unexpected_OtherSubr; + + divisor = cf2_stack_popFixed( opStack ); + dividend = cf2_stack_popFixed( opStack ); + + if ( divisor == 0 ) + goto Unexpected_OtherSubr; + + cf2_stack_pushFixed( opStack, + FT_DivFix( dividend, + divisor ) ); + known_othersubr_result_cnt = 1; + } + break; + + case 24: + /* <val> <idx> 2 24 callothersubr */ + /* ==> set BuildCharArray[cvi( <idx> )] = <val> */ + { + CF2_Int idx; + PS_Blend blend = decoder->blend; + + + if ( arg_cnt != 2 || !blend ) + goto Unexpected_OtherSubr; + + idx = cf2_stack_popInt( opStack ); + + if ( idx < 0 || + (FT_UInt)idx >= decoder->len_buildchar ) + goto Unexpected_OtherSubr; + + decoder->buildchar[idx] = + cf2_stack_popFixed( opStack ); + } + break; + + case 25: + /* <idx> 1 25 callothersubr pop */ + /* ==> push BuildCharArray[cvi( idx )] */ + /* onto T1 stack */ + { + CF2_Int idx; + PS_Blend blend = decoder->blend; + + + if ( arg_cnt != 1 || !blend ) + goto Unexpected_OtherSubr; + + idx = cf2_stack_popInt( opStack ); + + if ( idx < 0 || + (FT_UInt)idx >= decoder->len_buildchar ) + goto Unexpected_OtherSubr; + + cf2_stack_pushFixed( opStack, + decoder->buildchar[idx] ); + known_othersubr_result_cnt = 1; + } + break; + +#if 0 + case 26: + /* <val> mark <idx> */ + /* ==> set BuildCharArray[cvi( <idx> )] = <val>, */ + /* leave mark on T1 stack */ + /* <val> <idx> */ + /* ==> set BuildCharArray[cvi( <idx> )] = <val> */ + XXX which routine has left its mark on the + XXX (PostScript) stack?; + break; +#endif + + case 27: + /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */ + /* ==> push <res1> onto T1 stack if <val1> <= <val2>, */ + /* otherwise push <res2> */ + { + CF2_F16Dot16 arg1; + CF2_F16Dot16 arg2; + CF2_F16Dot16 cond1; + CF2_F16Dot16 cond2; + + + if ( arg_cnt != 4 ) + goto Unexpected_OtherSubr; + + cond2 = cf2_stack_popFixed( opStack ); + cond1 = cf2_stack_popFixed( opStack ); + arg2 = cf2_stack_popFixed( opStack ); + arg1 = cf2_stack_popFixed( opStack ); + + cf2_stack_pushFixed( opStack, + cond1 <= cond2 ? arg1 : arg2 ); + known_othersubr_result_cnt = 1; + } + break; + + case 28: + /* 0 28 callothersubr pop */ + /* ==> push random value from interval [0, 1) */ + /* onto stack */ + { + CF2_F16Dot16 r; + + + if ( arg_cnt != 0 ) + goto Unexpected_OtherSubr; + + /* only use the lower 16 bits of `random' */ + /* to generate a number in the range (0;1] */ + r = (CF2_F16Dot16) + ( ( decoder->current_subfont->random & 0xFFFF ) + 1 ); + + decoder->current_subfont->random = + cff_random( decoder->current_subfont->random ); + + cf2_stack_pushFixed( opStack, r ); + known_othersubr_result_cnt = 1; + } + break; + + default: + if ( arg_cnt >= 0 && subr_no >= 0 ) + { + FT_Int i; + + + FT_ERROR(( + "cf2_interpT2CharString (Type 1 mode):" + " unknown othersubr [%d %d], wish me luck\n", + arg_cnt, subr_no )); + + /* store the unused args */ + /* for this unhandled OtherSubr */ + + if ( arg_cnt > PS_STORAGE_SIZE ) + arg_cnt = PS_STORAGE_SIZE; + result_cnt = arg_cnt; + + for ( i = 1; i <= arg_cnt; i++ ) + results[result_cnt - i] = + cf2_stack_popFixed( opStack ); + + break; + } + /* fall through */ + + Unexpected_OtherSubr: + FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):" + " invalid othersubr [%d %d]\n", + arg_cnt, subr_no )); + lastError = FT_THROW( Invalid_Glyph_Format ); + goto exit; + } + } + continue; /* do not clear the stack */ + + case cf2_escPOP: + if ( !font->isT1 ) + FT_TRACE4(( " unknown op (12, %d)\n", op2 )); + else + { + FT_TRACE4(( " pop" )); + + if ( known_othersubr_result_cnt > 0 ) + { + known_othersubr_result_cnt--; + /* ignore, we pushed the operands ourselves */ + continue; + } + + if ( result_cnt == 0 ) + { + FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):" + " no more operands for othersubr\n" )); + lastError = FT_THROW( Invalid_Glyph_Format ); + goto exit; + } + + result_cnt--; + cf2_stack_pushFixed( opStack, results[result_cnt] ); + } + continue; /* do not clear the stack */ + + case cf2_escDROP: + FT_TRACE4(( " drop\n" )); + + (void)cf2_stack_popFixed( opStack ); + continue; /* do not clear the stack */ + + case cf2_escPUT: + { + CF2_F16Dot16 val; + CF2_Int idx; + + + FT_TRACE4(( " put\n" )); + + idx = cf2_stack_popInt( opStack ); + val = cf2_stack_popFixed( opStack ); + + if ( idx >= 0 && idx < CF2_STORAGE_SIZE ) + storage[idx] = val; + } + continue; /* do not clear the stack */ + + case cf2_escGET: + { + CF2_Int idx; + + + FT_TRACE4(( " get\n" )); + + idx = cf2_stack_popInt( opStack ); + + if ( idx >= 0 && idx < CF2_STORAGE_SIZE ) + cf2_stack_pushFixed( opStack, storage[idx] ); + } + continue; /* do not clear the stack */ + + case cf2_escIFELSE: + { + CF2_F16Dot16 arg1; + CF2_F16Dot16 arg2; + CF2_F16Dot16 cond1; + CF2_F16Dot16 cond2; + + + FT_TRACE4(( " ifelse\n" )); + + cond2 = cf2_stack_popFixed( opStack ); + cond1 = cf2_stack_popFixed( opStack ); + arg2 = cf2_stack_popFixed( opStack ); + arg1 = cf2_stack_popFixed( opStack ); + + cf2_stack_pushFixed( opStack, + cond1 <= cond2 ? arg1 : arg2 ); + } + continue; /* do not clear the stack */ + + case cf2_escRANDOM: /* in spec */ + { + CF2_F16Dot16 r; + + + FT_TRACE4(( " random\n" )); + + /* only use the lower 16 bits of `random' */ + /* to generate a number in the range (0;1] */ + r = (CF2_F16Dot16) + ( ( decoder->current_subfont->random & 0xFFFF ) + 1 ); + + decoder->current_subfont->random = + cff_random( decoder->current_subfont->random ); + + cf2_stack_pushFixed( opStack, r ); + } + continue; /* do not clear the stack */ + + case cf2_escMUL: + { + CF2_F16Dot16 factor1; + CF2_F16Dot16 factor2; + + + FT_TRACE4(( " mul\n" )); + + factor2 = cf2_stack_popFixed( opStack ); + factor1 = cf2_stack_popFixed( opStack ); + + cf2_stack_pushFixed( opStack, + FT_MulFix( factor1, factor2 ) ); + } + continue; /* do not clear the stack */ + + case cf2_escSQRT: + { + CF2_F16Dot16 arg; + + + FT_TRACE4(( " sqrt\n" )); + + arg = cf2_stack_popFixed( opStack ); + if ( arg > 0 ) + { + /* use a start value that doesn't make */ + /* the algorithm's addition overflow */ + FT_Fixed root = arg < 10 ? arg : arg >> 1; + FT_Fixed new_root; + + + /* Babylonian method */ + for (;;) + { + new_root = ( root + FT_DivFix( arg, root ) + 1 ) >> 1; + if ( new_root == root ) + break; + root = new_root; + } + arg = new_root; + } + else + arg = 0; + + cf2_stack_pushFixed( opStack, arg ); + } + continue; /* do not clear the stack */ + + case cf2_escDUP: + { + CF2_F16Dot16 arg; + + + FT_TRACE4(( " dup\n" )); + + arg = cf2_stack_popFixed( opStack ); + + cf2_stack_pushFixed( opStack, arg ); + cf2_stack_pushFixed( opStack, arg ); + } + continue; /* do not clear the stack */ + + case cf2_escEXCH: + { + CF2_F16Dot16 arg1; + CF2_F16Dot16 arg2; + + + FT_TRACE4(( " exch\n" )); + + arg2 = cf2_stack_popFixed( opStack ); + arg1 = cf2_stack_popFixed( opStack ); + + cf2_stack_pushFixed( opStack, arg2 ); + cf2_stack_pushFixed( opStack, arg1 ); + } + continue; /* do not clear the stack */ + + case cf2_escINDEX: + { + CF2_Int idx; + CF2_UInt size; + + + FT_TRACE4(( " index\n" )); + + idx = cf2_stack_popInt( opStack ); + size = cf2_stack_count( opStack ); + + if ( size > 0 ) + { + /* for `cf2_stack_getReal', */ + /* index 0 is bottom of stack */ + CF2_UInt gr_idx; + + + if ( idx < 0 ) + gr_idx = size - 1; + else if ( (CF2_UInt)idx >= size ) + gr_idx = 0; + else + gr_idx = size - 1 - (CF2_UInt)idx; + + cf2_stack_pushFixed( opStack, + cf2_stack_getReal( opStack, + gr_idx ) ); + } + } + continue; /* do not clear the stack */ + + case cf2_escROLL: + { + CF2_Int idx; + CF2_Int count; + + + FT_TRACE4(( " roll\n" )); + + idx = cf2_stack_popInt( opStack ); + count = cf2_stack_popInt( opStack ); + + cf2_stack_roll( opStack, count, idx ); + } + continue; /* do not clear the stack */ + + case cf2_escSETCURRENTPT: + if ( !font->isT1 ) + FT_TRACE4(( " unknown op (12, %d)\n", op2 )); + else + { + FT_TRACE4(( " setcurrentpoint" )); + + if ( !initial_map_ready ) + break; + + /* From the T1 specification, section 6.4: */ + /* */ + /* The setcurrentpoint command is used only in */ + /* conjunction with results from OtherSubrs */ + /* procedures. */ + + /* known_othersubr_result_cnt != 0 is already handled */ + /* above. */ + + /* Note, however, that both Ghostscript and Adobe */ + /* Distiller handle this situation by silently */ + /* ignoring the inappropriate `setcurrentpoint' */ + /* instruction. So we do the same. */ +#if 0 + + if ( decoder->flex_state != 1 ) + { + FT_ERROR(( "cf2_interpT2CharString:" + " unexpected `setcurrentpoint'\n" )); + goto Syntax_Error; + } + else + ... +#endif + + curY = cf2_stack_popFixed( opStack ); + curX = cf2_stack_popFixed( opStack ); + + decoder->flex_state = 0; + } + break; + + } /* end of 2nd switch checking op2 */ + } + } + } /* end of 1st switch checking op2 */ + } /* case cf2_cmdESC */ + + break; + + case cf2_cmdHSBW: + if ( !font->isT1 ) + FT_TRACE4(( " unknown op (%d)\n", op1 )); + else + { + CF2_Fixed lsb_x; + PS_Builder* builder; + + + FT_TRACE4(( " hsbw" )); + + builder = &decoder->builder; + + builder->advance->x = cf2_stack_popFixed( opStack ); + builder->advance->y = 0; + + lsb_x = cf2_stack_popFixed( opStack ); + + builder->left_bearing->x = ADD_INT32( builder->left_bearing->x, + lsb_x ); + + haveWidth = TRUE; + + /* the `metrics_only' indicates that we only want to compute */ + /* the glyph's metrics (lsb + advance width), not load the */ + /* rest of it; so exit immediately */ + if ( builder->metrics_only ) + goto exit; + + if ( initial_map_ready ) + curX = ADD_INT32( curX, lsb_x ); + } + break; + + case cf2_cmdENDCHAR: + FT_TRACE4(( " endchar\n" )); + + if ( font->isT1 && !initial_map_ready ) + { + FT_TRACE5(( "cf2_interpT2CharString (Type 1 mode): " + "Build initial hintmap, rewinding...\n" )); + + /* trigger initial hintmap build */ + cf2_glyphpath_moveTo( &glyphPath, curX, curY ); + + initial_map_ready = TRUE; + + /* change hints routine - clear for rewind */ + cf2_arrstack_clear( &vStemHintArray ); + cf2_arrstack_clear( &hStemHintArray ); + + cf2_hintmask_init( &hintMask, error ); + hintMask.isValid = FALSE; + hintMask.isNew = TRUE; + + /* rewind charstring */ + /* some charstrings use endchar from a final subroutine call */ + /* without returning, detect these and exit to the top level */ + /* charstring */ + while ( charstringIndex > 0 ) + { + FT_TRACE4(( " return (leaving level %d)\n", charstringIndex )); + + /* restore position in previous charstring */ + charstring = (CF2_Buffer) + cf2_arrstack_getPointer( + &subrStack, + (CF2_UInt)--charstringIndex ); + } + charstring->ptr = charstring->start; + + break; + } + + if ( cf2_stack_count( opStack ) == 1 || + cf2_stack_count( opStack ) == 5 ) + { + if ( !haveWidth ) + *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ), + nominalWidthX ); + } + + /* width is defined or default after this */ + haveWidth = TRUE; + + if ( decoder->width_only ) + goto exit; + + /* close path if still open */ + cf2_glyphpath_closeOpenPath( &glyphPath ); + + /* disable seac for CFF2 and Type1 */ + /* (charstring ending with args on stack) */ + if ( !font->isCFF2 && !font->isT1 && cf2_stack_count( opStack ) > 1 ) + { + /* must be either 4 or 5 -- */ + /* this is a (deprecated) implied `seac' operator */ + + CF2_Int achar; + CF2_Int bchar; + CF2_BufferRec component; + CF2_Fixed dummyWidth; /* ignore component width */ + FT_Error error2; + + + if ( doingSeac ) + { + lastError = FT_THROW( Invalid_Glyph_Format ); + goto exit; /* nested seac */ + } + + achar = cf2_stack_popInt( opStack ); + bchar = cf2_stack_popInt( opStack ); + + curY = cf2_stack_popFixed( opStack ); + curX = cf2_stack_popFixed( opStack ); + + error2 = cf2_getSeacComponent( decoder, achar, &component ); + if ( error2 ) + { + lastError = error2; /* pass FreeType error through */ + goto exit; + } + cf2_interpT2CharString( font, + &component, + callbacks, + translation, + TRUE, + curX, + curY, + &dummyWidth ); + cf2_freeSeacComponent( decoder, &component ); + + error2 = cf2_getSeacComponent( decoder, bchar, &component ); + if ( error2 ) + { + lastError = error2; /* pass FreeType error through */ + goto exit; + } + cf2_interpT2CharString( font, + &component, + callbacks, + translation, + TRUE, + 0, + 0, + &dummyWidth ); + cf2_freeSeacComponent( decoder, &component ); + } + goto exit; + + case cf2_cmdCNTRMASK: + case cf2_cmdHINTMASK: + /* the final \n in the tracing message gets added in */ + /* `cf2_hintmask_read' (which also traces the mask bytes) */ + FT_TRACE4(( op1 == cf2_cmdCNTRMASK ? " cntrmask" : " hintmask" )); + + /* never add hints after the mask is computed */ + if ( cf2_stack_count( opStack ) > 1 && + cf2_hintmask_isValid( &hintMask ) ) + { + FT_TRACE4(( "cf2_interpT2CharString: invalid hint mask\n" )); + break; + } + + /* if there are arguments on the stack, there this is an */ + /* implied cf2_cmdVSTEMHM */ + cf2_doStems( font, + opStack, + &vStemHintArray, + width, + &haveWidth, + 0 ); + + if ( decoder->width_only ) + goto exit; + + if ( op1 == cf2_cmdHINTMASK ) + { + /* consume the hint mask bytes which follow the operator */ + cf2_hintmask_read( &hintMask, + charstring, + cf2_arrstack_size( &hStemHintArray ) + + cf2_arrstack_size( &vStemHintArray ) ); + } + else + { + /* + * Consume the counter mask bytes which follow the operator: + * Build a temporary hint map, just to place and lock those + * stems participating in the counter mask. These are most + * likely the dominant hstems, and are grouped together in a + * few counter groups, not necessarily in correspondence + * with the hint groups. This reduces the chances of + * conflicts between hstems that are initially placed in + * separate hint groups and then brought together. The + * positions are copied back to `hStemHintArray', so we can + * discard `counterMask' and `counterHintMap'. + * + */ + CF2_HintMapRec counterHintMap; + CF2_HintMaskRec counterMask; + + + cf2_hintmap_init( &counterHintMap, + font, + &glyphPath.initialHintMap, + &glyphPath.hintMoves, + scaleY ); + cf2_hintmask_init( &counterMask, error ); + + cf2_hintmask_read( &counterMask, + charstring, + cf2_arrstack_size( &hStemHintArray ) + + cf2_arrstack_size( &vStemHintArray ) ); + cf2_hintmap_build( &counterHintMap, + &hStemHintArray, + &vStemHintArray, + &counterMask, + 0, + FALSE ); + } + break; + + case cf2_cmdRMOVETO: + FT_TRACE4(( " rmoveto\n" )); + + if ( font->isT1 && !decoder->flex_state && !haveWidth ) + FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):" + " No width. Use hsbw/sbw as first op\n" )); + + if ( cf2_stack_count( opStack ) > 2 && !haveWidth ) + *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ), + nominalWidthX ); + + /* width is defined or default after this */ + haveWidth = TRUE; + + if ( decoder->width_only ) + goto exit; + + curY = ADD_INT32( curY, cf2_stack_popFixed( opStack ) ); + curX = ADD_INT32( curX, cf2_stack_popFixed( opStack ) ); + + if ( !decoder->flex_state ) + cf2_glyphpath_moveTo( &glyphPath, curX, curY ); + + break; + + case cf2_cmdHMOVETO: + FT_TRACE4(( " hmoveto\n" )); + + if ( font->isT1 && !decoder->flex_state && !haveWidth ) + FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):" + " No width. Use hsbw/sbw as first op\n" )); + + if ( cf2_stack_count( opStack ) > 1 && !haveWidth ) + *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ), + nominalWidthX ); + + /* width is defined or default after this */ + haveWidth = TRUE; + + if ( decoder->width_only ) + goto exit; + + curX = ADD_INT32( curX, cf2_stack_popFixed( opStack ) ); + + if ( !decoder->flex_state ) + cf2_glyphpath_moveTo( &glyphPath, curX, curY ); + + break; + + case cf2_cmdRLINECURVE: + { + CF2_UInt count = cf2_stack_count( opStack ); + CF2_UInt idx = 0; + + + FT_TRACE4(( " rlinecurve\n" )); + + while ( idx + 6 < count ) + { + curX = ADD_INT32( curX, cf2_stack_getReal( opStack, + idx + 0 ) ); + curY = ADD_INT32( curY, cf2_stack_getReal( opStack, + idx + 1 ) ); + + cf2_glyphpath_lineTo( &glyphPath, curX, curY ); + idx += 2; + } + + while ( idx < count ) + { + CF2_Fixed x1, y1, x2, y2, x3, y3; + + + x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX ); + y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), curY ); + x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), x1 ); + y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y1 ); + x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 ); + y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 5 ), y2 ); + + cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); + + curX = x3; + curY = y3; + idx += 6; + } + + cf2_stack_clear( opStack ); + } + continue; /* no need to clear stack again */ + + case cf2_cmdVVCURVETO: + { + CF2_UInt count, count1 = cf2_stack_count( opStack ); + CF2_UInt idx = 0; + + + /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */ + /* we enforce it by clearing the second bit */ + /* (and sorting the stack indexing to suit) */ + count = count1 & ~2U; + idx += count1 - count; + + FT_TRACE4(( " vvcurveto\n" )); + + while ( idx < count ) + { + CF2_Fixed x1, y1, x2, y2, x3, y3; + + + if ( ( count - idx ) & 1 ) + { + x1 = ADD_INT32( cf2_stack_getReal( opStack, idx ), curX ); + + idx++; + } + else + x1 = curX; + + y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curY ); + x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 ); + y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 ); + x3 = x2; + y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y2 ); + + cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); + + curX = x3; + curY = y3; + idx += 4; + } + + cf2_stack_clear( opStack ); + } + continue; /* no need to clear stack again */ + + case cf2_cmdHHCURVETO: + { + CF2_UInt count, count1 = cf2_stack_count( opStack ); + CF2_UInt idx = 0; + + + /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */ + /* we enforce it by clearing the second bit */ + /* (and sorting the stack indexing to suit) */ + count = count1 & ~2U; + idx += count1 - count; + + FT_TRACE4(( " hhcurveto\n" )); + + while ( idx < count ) + { + CF2_Fixed x1, y1, x2, y2, x3, y3; + + + if ( ( count - idx ) & 1 ) + { + y1 = ADD_INT32( cf2_stack_getReal( opStack, idx ), curY ); + + idx++; + } + else + y1 = curY; + + x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX ); + x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 ); + y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 ); + x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), x2 ); + y3 = y2; + + cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); + + curX = x3; + curY = y3; + idx += 4; + } + + cf2_stack_clear( opStack ); + } + continue; /* no need to clear stack again */ + + case cf2_cmdVHCURVETO: + case cf2_cmdHVCURVETO: + { + CF2_UInt count, count1 = cf2_stack_count( opStack ); + CF2_UInt idx = 0; + + FT_Bool alternate = FT_BOOL( op1 == cf2_cmdHVCURVETO ); + + + /* if `cf2_stack_count' isn't of the form 8n, 8n+1, */ + /* 8n+4, or 8n+5, we enforce it by clearing the */ + /* second bit */ + /* (and sorting the stack indexing to suit) */ + count = count1 & ~2U; + idx += count1 - count; + + FT_TRACE4(( alternate ? " hvcurveto\n" : " vhcurveto\n" )); + + while ( idx < count ) + { + CF2_Fixed x1, x2, x3, y1, y2, y3; + + + if ( alternate ) + { + x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX ); + y1 = curY; + x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 ); + y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 ); + y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y2 ); + + if ( count - idx == 5 ) + { + x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 ); + + idx++; + } + else + x3 = x2; + + alternate = FALSE; + } + else + { + x1 = curX; + y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curY ); + x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 ); + y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 ); + x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), x2 ); + + if ( count - idx == 5 ) + { + y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), y2 ); + + idx++; + } + else + y3 = y2; + + alternate = TRUE; + } + + cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); + + curX = x3; + curY = y3; + idx += 4; + } + + cf2_stack_clear( opStack ); + } + continue; /* no need to clear stack again */ + + case cf2_cmdEXTENDEDNMBR: + { + CF2_Int v; + + CF2_Int byte1 = cf2_buf_readByte( charstring ); + CF2_Int byte2 = cf2_buf_readByte( charstring ); + + + v = (FT_Short)( ( byte1 << 8 ) | + byte2 ); + + FT_TRACE4(( " %d", v )); + + cf2_stack_pushInt( opStack, v ); + } + continue; + + default: + /* numbers */ + { + if ( /* op1 >= 32 && */ op1 <= 246 ) + { + CF2_Int v; + + + v = op1 - 139; + + FT_TRACE4(( " %d", v )); + + /* -107 .. 107 */ + cf2_stack_pushInt( opStack, v ); + } + + else if ( /* op1 >= 247 && */ op1 <= 250 ) + { + CF2_Int v; + + + v = op1; + v -= 247; + v *= 256; + v += cf2_buf_readByte( charstring ); + v += 108; + + FT_TRACE4(( " %d", v )); + + /* 108 .. 1131 */ + cf2_stack_pushInt( opStack, v ); + } + + else if ( /* op1 >= 251 && */ op1 <= 254 ) + { + CF2_Int v; + + + v = op1; + v -= 251; + v *= 256; + v += cf2_buf_readByte( charstring ); + v = -v - 108; + + FT_TRACE4(( " %d", v )); + + /* -1131 .. -108 */ + cf2_stack_pushInt( opStack, v ); + } + + else /* op1 == 255 */ + { + CF2_Fixed v; + + FT_UInt32 byte1 = (FT_UInt32)cf2_buf_readByte( charstring ); + FT_UInt32 byte2 = (FT_UInt32)cf2_buf_readByte( charstring ); + FT_UInt32 byte3 = (FT_UInt32)cf2_buf_readByte( charstring ); + FT_UInt32 byte4 = (FT_UInt32)cf2_buf_readByte( charstring ); + + + v = (CF2_Fixed)( ( byte1 << 24 ) | + ( byte2 << 16 ) | + ( byte3 << 8 ) | + byte4 ); + + /* + * For Type 1: + * + * According to the specification, values > 32000 or < -32000 + * must be followed by a `div' operator to make the result be + * in the range [-32000;32000]. We expect that the second + * argument of `div' is not a large number. Additionally, we + * don't handle stuff like `<large1> <large2> <num> div <num> + * div' or <large1> <large2> <num> div div'. This is probably + * not allowed anyway. + * + * <large> <num> <num>+ div is not checked but should not be + * allowed as the large value remains untouched. + * + */ + if ( font->isT1 ) + { + if ( v > 32000 || v < -32000 ) + { + if ( large_int ) + FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):" + " no `div' after large integer\n" )); + else + large_int = TRUE; + } + + FT_TRACE4(( " %d", v )); + + cf2_stack_pushInt( opStack, (CF2_Int)v ); + } + else + { + FT_TRACE4(( " %.5fF", v / 65536.0 )); + + cf2_stack_pushFixed( opStack, v ); + } + } + } + continue; /* don't clear stack */ + + } /* end of switch statement checking `op1' */ + + cf2_stack_clear( opStack ); + + } /* end of main interpreter loop */ + + /* we get here if the charstring ends without cf2_cmdENDCHAR */ + FT_TRACE4(( "cf2_interpT2CharString:" + " charstring ends without ENDCHAR\n" )); + + exit: + /* check whether last error seen is also the first one */ + cf2_setError( error, lastError ); + + if ( *error ) + FT_TRACE4(( "charstring error %d\n", *error )); + + /* free resources from objects we've used */ + cf2_glyphpath_finalize( &glyphPath ); + cf2_arrstack_finalize( &vStemHintArray ); + cf2_arrstack_finalize( &hStemHintArray ); + cf2_arrstack_finalize( &subrStack ); + cf2_stack_free( opStack ); + + FT_TRACE4(( "\n" )); + + return; + } + + +/* END */ diff --git a/modules/freetype2/src/cff/cf2intrp.h b/modules/freetype2/src/psaux/psintrp.h index ec030e894..4790aaa30 100644 --- a/modules/freetype2/src/cff/cf2intrp.h +++ b/modules/freetype2/src/psaux/psintrp.h @@ -1,6 +1,6 @@ /***************************************************************************/ /* */ -/* cf2font.h */ +/* psintrp.h */ /* */ /* Adobe's CFF Interpreter (specification). */ /* */ @@ -36,12 +36,12 @@ /***************************************************************************/ -#ifndef CF2INTRP_H_ -#define CF2INTRP_H_ +#ifndef PSINTRP_H_ +#define PSINTRP_H_ -#include "cf2ft.h" -#include "cf2hints.h" +#include "psft.h" +#include "pshints.h" FT_BEGIN_HEADER @@ -77,7 +77,7 @@ FT_BEGIN_HEADER FT_END_HEADER -#endif /* CF2INTRP_H_ */ +#endif /* PSINTRP_H_ */ /* END */ diff --git a/modules/freetype2/src/psaux/psobjs.c b/modules/freetype2/src/psaux/psobjs.c index 6e528d407..f54bc7e41 100644 --- a/modules/freetype2/src/psaux/psobjs.c +++ b/modules/freetype2/src/psaux/psobjs.c @@ -4,7 +4,7 @@ /* */ /* Auxiliary functions for PostScript fonts (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -20,11 +20,13 @@ #include FT_INTERNAL_POSTSCRIPT_AUX_H #include FT_INTERNAL_DEBUG_H #include FT_INTERNAL_CALC_H +#include FT_DRIVER_H #include "psobjs.h" #include "psconv.h" #include "psauxerr.h" +#include "psauxmod.h" /*************************************************************************/ @@ -1551,7 +1553,7 @@ builder->current = &loader->current.outline; FT_GlyphLoader_Rewind( loader ); - builder->hints_globals = size->internal; + builder->hints_globals = size->internal->module_data; builder->hints_funcs = NULL; if ( hinting ) @@ -1718,6 +1720,581 @@ first = outline->n_contours <= 1 ? 0 : outline->contours[outline->n_contours - 2] + 1; + /* in malformed fonts it can happen that a contour was started */ + /* but no points were added */ + if ( outline->n_contours && first == outline->n_points ) + { + outline->n_contours--; + return; + } + + /* We must not include the last point in the path if it */ + /* is located on the first point. */ + if ( outline->n_points > 1 ) + { + FT_Vector* p1 = outline->points + first; + FT_Vector* p2 = outline->points + outline->n_points - 1; + FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1; + + + /* `delete' last point only if it coincides with the first */ + /* point and it is not a control point (which can happen). */ + if ( p1->x == p2->x && p1->y == p2->y ) + if ( *control == FT_CURVE_TAG_ON ) + outline->n_points--; + } + + if ( outline->n_contours > 0 ) + { + /* Don't add contours only consisting of one point, i.e., */ + /* check whether the first and the last point is the same. */ + if ( first == outline->n_points - 1 ) + { + outline->n_contours--; + outline->n_points--; + } + else + outline->contours[outline->n_contours - 1] = + (short)( outline->n_points - 1 ); + } + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** CFF BUILDER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* cff_builder_init */ + /* */ + /* <Description> */ + /* Initializes a given glyph builder. */ + /* */ + /* <InOut> */ + /* builder :: A pointer to the glyph builder to initialize. */ + /* */ + /* <Input> */ + /* face :: The current face object. */ + /* */ + /* size :: The current size object. */ + /* */ + /* glyph :: The current glyph object. */ + /* */ + /* hinting :: Whether hinting is active. */ + /* */ + FT_LOCAL_DEF( void ) + cff_builder_init( CFF_Builder* builder, + TT_Face face, + CFF_Size size, + CFF_GlyphSlot glyph, + FT_Bool hinting ) + { + builder->path_begun = 0; + builder->load_points = 1; + + builder->face = face; + builder->glyph = glyph; + builder->memory = face->root.memory; + + if ( glyph ) + { + FT_GlyphLoader loader = glyph->root.internal->loader; + + + builder->loader = loader; + builder->base = &loader->base.outline; + builder->current = &loader->current.outline; + FT_GlyphLoader_Rewind( loader ); + + builder->hints_globals = NULL; + builder->hints_funcs = NULL; + + if ( hinting && size ) + { + FT_Size ftsize = FT_SIZE( size ); + CFF_Internal internal = (CFF_Internal)ftsize->internal->module_data; + + if ( internal ) + { + builder->hints_globals = (void *)internal->topfont; + builder->hints_funcs = glyph->root.internal->glyph_hints; + } + } + } + + builder->pos_x = 0; + builder->pos_y = 0; + + builder->left_bearing.x = 0; + builder->left_bearing.y = 0; + builder->advance.x = 0; + builder->advance.y = 0; + + builder->funcs = cff_builder_funcs; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* cff_builder_done */ + /* */ + /* <Description> */ + /* Finalizes a given glyph builder. Its contents can still be used */ + /* after the call, but the function saves important information */ + /* within the corresponding glyph slot. */ + /* */ + /* <Input> */ + /* builder :: A pointer to the glyph builder to finalize. */ + /* */ + FT_LOCAL_DEF( void ) + cff_builder_done( CFF_Builder* builder ) + { + CFF_GlyphSlot glyph = builder->glyph; + + + if ( glyph ) + glyph->root.outline = *builder->base; + } + + + /* check that there is enough space for `count' more points */ + FT_LOCAL_DEF( FT_Error ) + cff_check_points( CFF_Builder* builder, + FT_Int count ) + { + return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 ); + } + + + /* add a new point, do not check space */ + FT_LOCAL_DEF( void ) + cff_builder_add_point( CFF_Builder* builder, + FT_Pos x, + FT_Pos y, + FT_Byte flag ) + { + FT_Outline* outline = builder->current; + + + if ( builder->load_points ) + { + FT_Vector* point = outline->points + outline->n_points; + FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; + +#ifdef CFF_CONFIG_OPTION_OLD_ENGINE + PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( builder->face ); + + + if ( driver->hinting_engine == FT_HINTING_FREETYPE ) + { + point->x = x >> 16; + point->y = y >> 16; + } + else +#endif + { + /* cf2_decoder_parse_charstrings uses 16.16 coordinates */ + point->x = x >> 10; + point->y = y >> 10; + } + *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC ); + } + + outline->n_points++; + } + + + /* check space for a new on-curve point, then add it */ + FT_LOCAL_DEF( FT_Error ) + cff_builder_add_point1( CFF_Builder* builder, + FT_Pos x, + FT_Pos y ) + { + FT_Error error; + + + error = cff_check_points( builder, 1 ); + if ( !error ) + cff_builder_add_point( builder, x, y, 1 ); + + return error; + } + + + /* check space for a new contour, then add it */ + FT_LOCAL_DEF( FT_Error ) + cff_builder_add_contour( CFF_Builder* builder ) + { + FT_Outline* outline = builder->current; + FT_Error error; + + + if ( !builder->load_points ) + { + outline->n_contours++; + return FT_Err_Ok; + } + + error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 ); + if ( !error ) + { + if ( outline->n_contours > 0 ) + outline->contours[outline->n_contours - 1] = + (short)( outline->n_points - 1 ); + + outline->n_contours++; + } + + return error; + } + + + /* if a path was begun, add its first on-curve point */ + FT_LOCAL_DEF( FT_Error ) + cff_builder_start_point( CFF_Builder* builder, + FT_Pos x, + FT_Pos y ) + { + FT_Error error = FT_Err_Ok; + + + /* test whether we are building a new contour */ + if ( !builder->path_begun ) + { + builder->path_begun = 1; + error = cff_builder_add_contour( builder ); + if ( !error ) + error = cff_builder_add_point1( builder, x, y ); + } + + return error; + } + + + /* close the current contour */ + FT_LOCAL_DEF( void ) + cff_builder_close_contour( CFF_Builder* builder ) + { + FT_Outline* outline = builder->current; + FT_Int first; + + + if ( !outline ) + return; + + first = outline->n_contours <= 1 + ? 0 : outline->contours[outline->n_contours - 2] + 1; + + /* We must not include the last point in the path if it */ + /* is located on the first point. */ + if ( outline->n_points > 1 ) + { + FT_Vector* p1 = outline->points + first; + FT_Vector* p2 = outline->points + outline->n_points - 1; + FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1; + + + /* `delete' last point only if it coincides with the first */ + /* point and if it is not a control point (which can happen). */ + if ( p1->x == p2->x && p1->y == p2->y ) + if ( *control == FT_CURVE_TAG_ON ) + outline->n_points--; + } + + if ( outline->n_contours > 0 ) + { + /* Don't add contours only consisting of one point, i.e., */ + /* check whether begin point and last point are the same. */ + if ( first == outline->n_points - 1 ) + { + outline->n_contours--; + outline->n_points--; + } + else + outline->contours[outline->n_contours - 1] = + (short)( outline->n_points - 1 ); + } + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** PS BUILDER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* <Function> */ + /* ps_builder_init */ + /* */ + /* <Description> */ + /* Initializes a given glyph builder. */ + /* */ + /* <InOut> */ + /* builder :: A pointer to the glyph builder to initialize. */ + /* */ + /* <Input> */ + /* face :: The current face object. */ + /* */ + /* size :: The current size object. */ + /* */ + /* glyph :: The current glyph object. */ + /* */ + /* hinting :: Whether hinting should be applied. */ + /* */ + FT_LOCAL_DEF( void ) + ps_builder_init( PS_Builder* ps_builder, + void* builder, + FT_Bool is_t1 ) + { + FT_ZERO( ps_builder ); + + if ( is_t1 ) + { + T1_Builder t1builder = (T1_Builder)builder; + + + ps_builder->memory = t1builder->memory; + ps_builder->face = (FT_Face)t1builder->face; + ps_builder->glyph = (CFF_GlyphSlot)t1builder->glyph; + ps_builder->loader = t1builder->loader; + ps_builder->base = t1builder->base; + ps_builder->current = t1builder->current; + + ps_builder->pos_x = &t1builder->pos_x; + ps_builder->pos_y = &t1builder->pos_y; + + ps_builder->left_bearing = &t1builder->left_bearing; + ps_builder->advance = &t1builder->advance; + + ps_builder->bbox = &t1builder->bbox; + ps_builder->path_begun = 0; + ps_builder->load_points = t1builder->load_points; + ps_builder->no_recurse = t1builder->no_recurse; + + ps_builder->metrics_only = t1builder->metrics_only; + } + else + { + CFF_Builder* cffbuilder = (CFF_Builder*)builder; + + + ps_builder->memory = cffbuilder->memory; + ps_builder->face = (FT_Face)cffbuilder->face; + ps_builder->glyph = cffbuilder->glyph; + ps_builder->loader = cffbuilder->loader; + ps_builder->base = cffbuilder->base; + ps_builder->current = cffbuilder->current; + + ps_builder->pos_x = &cffbuilder->pos_x; + ps_builder->pos_y = &cffbuilder->pos_y; + + ps_builder->left_bearing = &cffbuilder->left_bearing; + ps_builder->advance = &cffbuilder->advance; + + ps_builder->bbox = &cffbuilder->bbox; + ps_builder->path_begun = cffbuilder->path_begun; + ps_builder->load_points = cffbuilder->load_points; + ps_builder->no_recurse = cffbuilder->no_recurse; + + ps_builder->metrics_only = cffbuilder->metrics_only; + } + + ps_builder->is_t1 = is_t1; + ps_builder->funcs = ps_builder_funcs; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* ps_builder_done */ + /* */ + /* <Description> */ + /* Finalizes a given glyph builder. Its contents can still be used */ + /* after the call, but the function saves important information */ + /* within the corresponding glyph slot. */ + /* */ + /* <Input> */ + /* builder :: A pointer to the glyph builder to finalize. */ + /* */ + FT_LOCAL_DEF( void ) + ps_builder_done( PS_Builder* builder ) + { + CFF_GlyphSlot glyph = builder->glyph; + + + if ( glyph ) + glyph->root.outline = *builder->base; + } + + + /* check that there is enough space for `count' more points */ + FT_LOCAL_DEF( FT_Error ) + ps_builder_check_points( PS_Builder* builder, + FT_Int count ) + { + return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 ); + } + + + /* add a new point, do not check space */ + FT_LOCAL_DEF( void ) + ps_builder_add_point( PS_Builder* builder, + FT_Pos x, + FT_Pos y, + FT_Byte flag ) + { + FT_Outline* outline = builder->current; + + + if ( builder->load_points ) + { + FT_Vector* point = outline->points + outline->n_points; + FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; + +#ifdef CFF_CONFIG_OPTION_OLD_ENGINE + PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( builder->face ); + + + if ( !builder->is_t1 && + driver->hinting_engine == FT_HINTING_FREETYPE ) + { + point->x = x >> 16; + point->y = y >> 16; + } + else +#endif +#ifdef T1_CONFIG_OPTION_OLD_ENGINE +#ifndef CFF_CONFIG_OPTION_OLD_ENGINE + PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( builder->face ); +#endif + if ( builder->is_t1 && + driver->hinting_engine == FT_HINTING_FREETYPE ) + { + point->x = FIXED_TO_INT( x ); + point->y = FIXED_TO_INT( y ); + } + else +#endif + { + /* cf2_decoder_parse_charstrings uses 16.16 coordinates */ + point->x = x >> 10; + point->y = y >> 10; + } + *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC ); + } + outline->n_points++; + } + + + /* check space for a new on-curve point, then add it */ + FT_LOCAL_DEF( FT_Error ) + ps_builder_add_point1( PS_Builder* builder, + FT_Pos x, + FT_Pos y ) + { + FT_Error error; + + + error = ps_builder_check_points( builder, 1 ); + if ( !error ) + ps_builder_add_point( builder, x, y, 1 ); + + return error; + } + + + /* check space for a new contour, then add it */ + FT_LOCAL_DEF( FT_Error ) + ps_builder_add_contour( PS_Builder* builder ) + { + FT_Outline* outline = builder->current; + FT_Error error; + + + /* this might happen in invalid fonts */ + if ( !outline ) + { + FT_ERROR(( "ps_builder_add_contour: no outline to add points to\n" )); + return FT_THROW( Invalid_File_Format ); + } + + if ( !builder->load_points ) + { + outline->n_contours++; + return FT_Err_Ok; + } + + error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 ); + if ( !error ) + { + if ( outline->n_contours > 0 ) + outline->contours[outline->n_contours - 1] = + (short)( outline->n_points - 1 ); + + outline->n_contours++; + } + + return error; + } + + + /* if a path was begun, add its first on-curve point */ + FT_LOCAL_DEF( FT_Error ) + ps_builder_start_point( PS_Builder* builder, + FT_Pos x, + FT_Pos y ) + { + FT_Error error = FT_Err_Ok; + + + /* test whether we are building a new contour */ + if ( !builder->path_begun ) + { + builder->path_begun = 1; + error = ps_builder_add_contour( builder ); + if ( !error ) + error = ps_builder_add_point1( builder, x, y ); + } + + return error; + } + + + /* close the current contour */ + FT_LOCAL_DEF( void ) + ps_builder_close_contour( PS_Builder* builder ) + { + FT_Outline* outline = builder->current; + FT_Int first; + + + if ( !outline ) + return; + + first = outline->n_contours <= 1 + ? 0 : outline->contours[outline->n_contours - 2] + 1; + + /* in malformed fonts it can happen that a contour was started */ + /* but no points were added */ + if ( outline->n_contours && first == outline->n_points ) + { + outline->n_contours--; + return; + } + /* We must not include the last point in the path if it */ /* is located on the first point. */ if ( outline->n_points > 1 ) @@ -1758,6 +2335,176 @@ /*************************************************************************/ /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* <Function> */ + /* ps_decoder_init */ + /* */ + /* <Description> */ + /* Creates a wrapper decoder for use in the combined */ + /* Type 1 / CFF interpreter. */ + /* */ + /* <InOut> */ + /* ps_decoder :: A pointer to the decoder to initialize. */ + /* */ + /* <Input> */ + /* decoder :: A pointer to the original decoder. */ + /* */ + /* is_t1 :: Flag indicating Type 1 or CFF */ + /* */ + FT_LOCAL_DEF( void ) + ps_decoder_init( PS_Decoder* ps_decoder, + void* decoder, + FT_Bool is_t1 ) + { + FT_ZERO( ps_decoder ); + + if ( is_t1 ) + { + T1_Decoder t1_decoder = (T1_Decoder)decoder; + + + ps_builder_init( &ps_decoder->builder, + &t1_decoder->builder, + is_t1 ); + + ps_decoder->cf2_instance = &t1_decoder->cf2_instance; + ps_decoder->psnames = t1_decoder->psnames; + + ps_decoder->num_glyphs = t1_decoder->num_glyphs; + ps_decoder->glyph_names = t1_decoder->glyph_names; + ps_decoder->hint_mode = t1_decoder->hint_mode; + ps_decoder->blend = t1_decoder->blend; + + ps_decoder->num_locals = (FT_UInt)t1_decoder->num_subrs; + ps_decoder->locals = t1_decoder->subrs; + ps_decoder->locals_len = t1_decoder->subrs_len; + ps_decoder->locals_hash = t1_decoder->subrs_hash; + + ps_decoder->buildchar = t1_decoder->buildchar; + ps_decoder->len_buildchar = t1_decoder->len_buildchar; + + ps_decoder->lenIV = t1_decoder->lenIV; + } + else + { + CFF_Decoder* cff_decoder = (CFF_Decoder*)decoder; + + + ps_builder_init( &ps_decoder->builder, + &cff_decoder->builder, + is_t1 ); + + ps_decoder->cff = cff_decoder->cff; + ps_decoder->cf2_instance = &cff_decoder->cff->cf2_instance; + ps_decoder->current_subfont = cff_decoder->current_subfont; + + ps_decoder->num_globals = cff_decoder->num_globals; + ps_decoder->globals = cff_decoder->globals; + ps_decoder->globals_bias = cff_decoder->globals_bias; + ps_decoder->num_locals = cff_decoder->num_locals; + ps_decoder->locals = cff_decoder->locals; + ps_decoder->locals_bias = cff_decoder->locals_bias; + + ps_decoder->glyph_width = &cff_decoder->glyph_width; + ps_decoder->width_only = cff_decoder->width_only; + + ps_decoder->hint_mode = cff_decoder->hint_mode; + + ps_decoder->get_glyph_callback = cff_decoder->get_glyph_callback; + ps_decoder->free_glyph_callback = cff_decoder->free_glyph_callback; + } + } + + + /* Synthesize a SubFont object for Type 1 fonts, for use in the */ + /* new interpreter to access Private dict data. */ + FT_LOCAL_DEF( void ) + t1_make_subfont( FT_Face face, + PS_Private priv, + CFF_SubFont subfont ) + { + CFF_Private cpriv = &subfont->private_dict; + FT_UInt n, count; + + + FT_ZERO( subfont ); + FT_ZERO( cpriv ); + + count = cpriv->num_blue_values = priv->num_blue_values; + for ( n = 0; n < count; n++ ) + cpriv->blue_values[n] = (FT_Pos)priv->blue_values[n]; + + count = cpriv->num_other_blues = priv->num_other_blues; + for ( n = 0; n < count; n++ ) + cpriv->other_blues[n] = (FT_Pos)priv->other_blues[n]; + + count = cpriv->num_family_blues = priv->num_family_blues; + for ( n = 0; n < count; n++ ) + cpriv->family_blues[n] = (FT_Pos)priv->family_blues[n]; + + count = cpriv->num_family_other_blues = priv->num_family_other_blues; + for ( n = 0; n < count; n++ ) + cpriv->family_other_blues[n] = (FT_Pos)priv->family_other_blues[n]; + + cpriv->blue_scale = priv->blue_scale; + cpriv->blue_shift = (FT_Pos)priv->blue_shift; + cpriv->blue_fuzz = (FT_Pos)priv->blue_fuzz; + + cpriv->standard_width = (FT_Pos)priv->standard_width[0]; + cpriv->standard_height = (FT_Pos)priv->standard_height[0]; + + count = cpriv->num_snap_widths = priv->num_snap_widths; + for ( n = 0; n < count; n++ ) + cpriv->snap_widths[n] = (FT_Pos)priv->snap_widths[n]; + + count = cpriv->num_snap_heights = priv->num_snap_heights; + for ( n = 0; n < count; n++ ) + cpriv->snap_heights[n] = (FT_Pos)priv->snap_heights[n]; + + cpriv->force_bold = priv->force_bold; + cpriv->lenIV = priv->lenIV; + cpriv->language_group = priv->language_group; + cpriv->expansion_factor = priv->expansion_factor; + + cpriv->subfont = subfont; + + + /* Initialize the random number generator. */ + if ( face->internal->random_seed != -1 ) + { + /* If we have a face-specific seed, use it. */ + /* If non-zero, update it to a positive value. */ + subfont->random = (FT_UInt32)face->internal->random_seed; + if ( face->internal->random_seed ) + { + do + { + face->internal->random_seed = (FT_Int32)cff_random( + (FT_UInt32)face->internal->random_seed ); + + } while ( face->internal->random_seed < 0 ); + } + } + if ( !subfont->random ) + { + FT_UInt32 seed; + + + /* compute random seed from some memory addresses */ + seed = (FT_UInt32)( (FT_Offset)(char*)&seed ^ + (FT_Offset)(char*)&face ^ + (FT_Offset)(char*)&subfont ); + seed = seed ^ ( seed >> 10 ) ^ ( seed >> 20 ); + if ( seed == 0 ) + seed = 0x7384; + + subfont->random = seed; + } + } + + FT_LOCAL_DEF( void ) t1_decrypt( FT_Byte* buffer, FT_Offset length, @@ -1771,4 +2518,16 @@ } + FT_LOCAL_DEF( FT_UInt32 ) + cff_random( FT_UInt32 r ) + { + /* a 32bit version of the `xorshift' algorithm */ + r ^= r << 13; + r ^= r >> 17; + r ^= r << 5; + + return r; + } + + /* END */ diff --git a/modules/freetype2/src/psaux/psobjs.h b/modules/freetype2/src/psaux/psobjs.h index 4c7178e79..8e0fe5fa4 100644 --- a/modules/freetype2/src/psaux/psobjs.h +++ b/modules/freetype2/src/psaux/psobjs.h @@ -4,7 +4,7 @@ /* */ /* Auxiliary functions for PostScript fonts (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -22,6 +22,7 @@ #include <ft2build.h> #include FT_INTERNAL_POSTSCRIPT_AUX_H +#include FT_INTERNAL_CFF_OBJECTS_TYPES_H FT_BEGIN_HEADER @@ -193,17 +194,117 @@ FT_BEGIN_HEADER /*************************************************************************/ /*************************************************************************/ /***** *****/ + /***** CFF BUILDER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + FT_LOCAL( void ) + cff_builder_init( CFF_Builder* builder, + TT_Face face, + CFF_Size size, + CFF_GlyphSlot glyph, + FT_Bool hinting ); + + FT_LOCAL( void ) + cff_builder_done( CFF_Builder* builder ); + + FT_LOCAL( FT_Error ) + cff_check_points( CFF_Builder* builder, + FT_Int count ); + + FT_LOCAL( void ) + cff_builder_add_point( CFF_Builder* builder, + FT_Pos x, + FT_Pos y, + FT_Byte flag ); + FT_LOCAL( FT_Error ) + cff_builder_add_point1( CFF_Builder* builder, + FT_Pos x, + FT_Pos y ); + FT_LOCAL( FT_Error ) + cff_builder_start_point( CFF_Builder* builder, + FT_Pos x, + FT_Pos y ); + FT_LOCAL( void ) + cff_builder_close_contour( CFF_Builder* builder ); + + FT_LOCAL( FT_Error ) + cff_builder_add_contour( CFF_Builder* builder ); + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** PS BUILDER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + FT_LOCAL( void ) + ps_builder_init( PS_Builder* ps_builder, + void* builder, + FT_Bool is_t1 ); + + + FT_LOCAL( void ) + ps_builder_done( PS_Builder* builder ); + + FT_LOCAL( FT_Error ) + ps_builder_check_points( PS_Builder* builder, + FT_Int count ); + + FT_LOCAL( void ) + ps_builder_add_point( PS_Builder* builder, + FT_Pos x, + FT_Pos y, + FT_Byte flag ); + + FT_LOCAL( FT_Error ) + ps_builder_add_point1( PS_Builder* builder, + FT_Pos x, + FT_Pos y ); + + FT_LOCAL( FT_Error ) + ps_builder_add_contour( PS_Builder* builder ); + + FT_LOCAL( FT_Error ) + ps_builder_start_point( PS_Builder* builder, + FT_Pos x, + FT_Pos y ); + + FT_LOCAL( void ) + ps_builder_close_contour( PS_Builder* builder ); + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ /***** OTHER *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ FT_LOCAL( void ) + ps_decoder_init( PS_Decoder* ps_decoder, + void* decoder, + FT_Bool is_t1 ); + + FT_LOCAL( void ) + t1_make_subfont( FT_Face face, + PS_Private priv, + CFF_SubFont subfont ); + + FT_LOCAL( void ) t1_decrypt( FT_Byte* buffer, FT_Offset length, FT_UShort seed ); + FT_LOCAL( FT_UInt32 ) + cff_random( FT_UInt32 r ); + + FT_END_HEADER #endif /* PSOBJS_H_ */ diff --git a/modules/freetype2/src/cff/cf2read.c b/modules/freetype2/src/psaux/psread.c index 2b429e3ee..719863ce1 100644 --- a/modules/freetype2/src/cff/cf2read.c +++ b/modules/freetype2/src/psaux/psread.c @@ -1,6 +1,6 @@ /***************************************************************************/ /* */ -/* cf2read.c */ +/* psread.c */ /* */ /* Adobe's code for stream handling (body). */ /* */ @@ -36,12 +36,12 @@ /***************************************************************************/ -#include "cf2ft.h" +#include "psft.h" #include FT_INTERNAL_DEBUG_H -#include "cf2glue.h" +#include "psglue.h" -#include "cf2error.h" +#include "pserror.h" /* Define CF2_IO_FAIL as 1 to enable random errors and random */ diff --git a/modules/freetype2/src/cff/cf2read.h b/modules/freetype2/src/psaux/psread.h index b0b0db803..464b29ba7 100644 --- a/modules/freetype2/src/cff/cf2read.h +++ b/modules/freetype2/src/psaux/psread.h @@ -1,6 +1,6 @@ /***************************************************************************/ /* */ -/* cf2read.h */ +/* psread.h */ /* */ /* Adobe's code for stream handling (specification). */ /* */ @@ -36,8 +36,8 @@ /***************************************************************************/ -#ifndef CF2READ_H_ -#define CF2READ_H_ +#ifndef PSREAD_H_ +#define PSREAD_H_ FT_BEGIN_HEADER @@ -62,7 +62,7 @@ FT_BEGIN_HEADER FT_END_HEADER -#endif /* CF2READ_H_ */ +#endif /* PSREAD_H_ */ /* END */ diff --git a/modules/freetype2/src/cff/cf2stack.c b/modules/freetype2/src/psaux/psstack.c index 12a026d21..69d063349 100644 --- a/modules/freetype2/src/cff/cf2stack.c +++ b/modules/freetype2/src/psaux/psstack.c @@ -1,6 +1,6 @@ /***************************************************************************/ /* */ -/* cf2stack.c */ +/* psstack.c */ /* */ /* Adobe's code for emulating a CFF stack (body). */ /* */ @@ -36,14 +36,14 @@ /***************************************************************************/ -#include "cf2ft.h" +#include "psft.h" #include FT_INTERNAL_DEBUG_H -#include "cf2glue.h" -#include "cf2font.h" -#include "cf2stack.h" +#include "psglue.h" +#include "psfont.h" +#include "psstack.h" -#include "cf2error.h" +#include "pserror.h" /* Allocate and initialize an instance of CF2_Stack. */ diff --git a/modules/freetype2/src/cff/cf2stack.h b/modules/freetype2/src/psaux/psstack.h index ef08eefe4..38f7b41c6 100644 --- a/modules/freetype2/src/cff/cf2stack.h +++ b/modules/freetype2/src/psaux/psstack.h @@ -1,6 +1,6 @@ /***************************************************************************/ /* */ -/* cf2stack.h */ +/* psstack.h */ /* */ /* Adobe's code for emulating a CFF stack (specification). */ /* */ @@ -36,8 +36,8 @@ /***************************************************************************/ -#ifndef CF2STACK_H_ -#define CF2STACK_H_ +#ifndef PSSTACK_H_ +#define PSSTACK_H_ FT_BEGIN_HEADER @@ -115,7 +115,7 @@ FT_BEGIN_HEADER FT_END_HEADER -#endif /* CF2STACK_H_ */ +#endif /* PSSTACK_H_ */ /* END */ diff --git a/modules/freetype2/src/cff/cf2types.h b/modules/freetype2/src/psaux/pstypes.h index 5b7e1239a..dfbaa3d47 100644 --- a/modules/freetype2/src/cff/cf2types.h +++ b/modules/freetype2/src/psaux/pstypes.h @@ -1,6 +1,6 @@ /***************************************************************************/ /* */ -/* cf2types.h */ +/* pstypes.h */ /* */ /* Adobe's code for defining data types (specification only). */ /* */ @@ -36,8 +36,8 @@ /***************************************************************************/ -#ifndef CF2TYPES_H_ -#define CF2TYPES_H_ +#ifndef PSTYPES_H_ +#define PSTYPES_H_ #include <ft2build.h> #include FT_FREETYPE_H @@ -72,7 +72,7 @@ FT_BEGIN_HEADER FT_END_HEADER -#endif /* CF2TYPES_H_ */ +#endif /* PSTYPES_H_ */ /* END */ diff --git a/modules/freetype2/src/psaux/rules.mk b/modules/freetype2/src/psaux/rules.mk index 19787b5f8..a87bfe968 100644 --- a/modules/freetype2/src/psaux/rules.mk +++ b/modules/freetype2/src/psaux/rules.mk @@ -3,7 +3,7 @@ # -# Copyright 1996-2016 by +# Copyright 1996-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, @@ -33,12 +33,25 @@ PSAUX_DRV_SRC := $(PSAUX_DIR)/psobjs.c \ $(PSAUX_DIR)/t1cmap.c \ $(PSAUX_DIR)/afmparse.c \ $(PSAUX_DIR)/psconv.c \ - $(PSAUX_DIR)/psauxmod.c + $(PSAUX_DIR)/psauxmod.c \ + $(PSAUX_DIR)/psarrst.c \ + $(PSAUX_DIR)/psblues.c \ + $(PSAUX_DIR)/pserror.c \ + $(PSAUX_DIR)/psfont.c \ + $(PSAUX_DIR)/psft.c \ + $(PSAUX_DIR)/pshints.c \ + $(PSAUX_DIR)/psintrp.c \ + $(PSAUX_DIR)/psread.c \ + $(PSAUX_DIR)/psstack.c \ + $(PSAUX_DIR)/cffdecode.c # PSAUX driver headers # PSAUX_DRV_H := $(PSAUX_DRV_SRC:%c=%h) \ - $(PSAUX_DIR)/psauxerr.h + $(PSAUX_DIR)/psauxerr.h \ + $(PSAUX_DIR)/psfixed.h \ + $(PSAUX_DIR)/psglue.h \ + $(PSAUX_DIR)/pstypes.h # PSAUX driver object(s) diff --git a/modules/freetype2/src/psaux/t1cmap.c b/modules/freetype2/src/psaux/t1cmap.c index 7b289b7f5..112a7892b 100644 --- a/modules/freetype2/src/psaux/t1cmap.c +++ b/modules/freetype2/src/psaux/t1cmap.c @@ -4,7 +4,7 @@ /* */ /* Type 1 character map support (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/psaux/t1cmap.h b/modules/freetype2/src/psaux/t1cmap.h index 5e1277dc6..4308e31d2 100644 --- a/modules/freetype2/src/psaux/t1cmap.h +++ b/modules/freetype2/src/psaux/t1cmap.h @@ -4,7 +4,7 @@ /* */ /* Type 1 character map support (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/psaux/t1decode.c b/modules/freetype2/src/psaux/t1decode.c index 1cd9d730a..6ad145661 100644 --- a/modules/freetype2/src/psaux/t1decode.c +++ b/modules/freetype2/src/psaux/t1decode.c @@ -4,7 +4,7 @@ /* */ /* PostScript Type 1 decoding routines (body). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -112,6 +112,56 @@ /*************************************************************************/ /* */ /* <Function> */ + /* t1_lookup_glyph_by_stdcharcode_ps */ + /* */ + /* <Description> */ + /* Looks up a given glyph by its StandardEncoding charcode. Used to */ + /* implement the SEAC Type 1 operator in the Adobe engine */ + /* */ + /* <Input> */ + /* face :: The current face object. */ + /* */ + /* charcode :: The character code to look for. */ + /* */ + /* <Return> */ + /* A glyph index in the font face. Returns -1 if the corresponding */ + /* glyph wasn't found. */ + /* */ + FT_LOCAL_DEF( FT_Int ) + t1_lookup_glyph_by_stdcharcode_ps( PS_Decoder* decoder, + FT_Int charcode ) + { + FT_UInt n; + const FT_String* glyph_name; + FT_Service_PsCMaps psnames = decoder->psnames; + + + /* check range of standard char code */ + if ( charcode < 0 || charcode > 255 ) + return -1; + + glyph_name = psnames->adobe_std_strings( + psnames->adobe_std_encoding[charcode]); + + for ( n = 0; n < decoder->num_glyphs; n++ ) + { + FT_String* name = (FT_String*)decoder->glyph_names[n]; + + + if ( name && + name[0] == glyph_name[0] && + ft_strcmp( name, glyph_name ) == 0 ) + return (FT_Int)n; + } + + return -1; + } + + +#ifdef T1_CONFIG_OPTION_OLD_ENGINE + /*************************************************************************/ + /* */ + /* <Function> */ /* t1_lookup_glyph_by_stdcharcode */ /* */ /* <Description> */ @@ -158,6 +208,15 @@ } + /* parse a single Type 1 glyph */ + FT_LOCAL_DEF( FT_Error ) + t1_decoder_parse_glyph( T1_Decoder decoder, + FT_UInt glyph ) + { + return decoder->parse_callback( decoder, glyph ); + } + + /*************************************************************************/ /* */ /* <Function> */ @@ -666,9 +725,9 @@ #ifdef FT_DEBUG_LEVEL_TRACE if ( large_int ) - FT_TRACE4(( " %ld", value )); + FT_TRACE4(( " %d", value )); else - FT_TRACE4(( " %ld", value / 65536 )); + FT_TRACE4(( " %d", value / 65536 )); #endif *top++ = value; @@ -780,10 +839,19 @@ /* point without adding any point to the outline */ idx = decoder->num_flex_vectors++; if ( idx > 0 && idx < 7 ) + { + /* in malformed fonts it is possible to have other */ + /* opcodes in the middle of a flex (which don't */ + /* increase `num_flex_vectors'); we thus have to */ + /* check whether we can add a point */ + if ( FT_SET_ERROR( t1_builder_check_points( builder, 1 ) ) ) + goto Syntax_Error; + t1_builder_add_point( builder, x, y, (FT_Byte)( idx == 3 || idx == 6 ) ); + } } break; @@ -855,7 +923,9 @@ for ( mm = 1; mm < blend->num_designs; mm++ ) - tmp += FT_MulFix( *delta++, blend->weight_vector[mm] ); + tmp = ADD_LONG( tmp, + FT_MulFix( *delta++, + blend->weight_vector[mm] ) ); *values++ = tmp; } @@ -895,7 +965,7 @@ if ( arg_cnt != 2 ) goto Unexpected_OtherSubr; - top[0] += top[1]; /* XXX (over|under)flow */ + top[0] = ADD_LONG( top[0], top[1] ); known_othersubr_result_cnt = 1; break; @@ -906,7 +976,7 @@ if ( arg_cnt != 2 ) goto Unexpected_OtherSubr; - top[0] -= top[1]; /* XXX (over|under)flow */ + top[0] = SUB_LONG( top[0], top[1] ); known_othersubr_result_cnt = 1; break; @@ -1138,11 +1208,13 @@ builder->parse_state = T1_Parse_Have_Width; - builder->left_bearing.x += top[0]; - builder->advance.x = top[1]; - builder->advance.y = 0; + builder->left_bearing.x = ADD_LONG( builder->left_bearing.x, + top[0] ); + + builder->advance.x = top[1]; + builder->advance.y = 0; - orig_x = x = builder->pos_x + top[0]; + orig_x = x = ADD_LONG( builder->pos_x, top[0] ); orig_y = y = builder->pos_y; FT_UNUSED( orig_y ); @@ -1168,13 +1240,16 @@ builder->parse_state = T1_Parse_Have_Width; - builder->left_bearing.x += top[0]; - builder->left_bearing.y += top[1]; - builder->advance.x = top[2]; - builder->advance.y = top[3]; + builder->left_bearing.x = ADD_LONG( builder->left_bearing.x, + top[0] ); + builder->left_bearing.y = ADD_LONG( builder->left_bearing.y, + top[1] ); - x = builder->pos_x + top[0]; - y = builder->pos_y + top[1]; + builder->advance.x = top[2]; + builder->advance.y = top[3]; + + x = ADD_LONG( builder->pos_x, top[0] ); + y = ADD_LONG( builder->pos_y, top[1] ); /* the `metrics_only' indicates that we only want to compute */ /* the glyph's metrics (lsb + advance width), not load the */ @@ -1201,13 +1276,14 @@ if ( FT_SET_ERROR( t1_builder_start_point( builder, x, y ) ) ) goto Fail; - x += top[0]; + x = ADD_LONG( x, top[0] ); goto Add_Line; case op_hmoveto: FT_TRACE4(( " hmoveto" )); - x += top[0]; + x = ADD_LONG( x, top[0] ); + if ( !decoder->flex_state ) { if ( builder->parse_state == T1_Parse_Start ) @@ -1223,12 +1299,14 @@ FT_SET_ERROR( t1_builder_check_points( builder, 3 ) ) ) goto Fail; - x += top[0]; + x = ADD_LONG( x, top[0] ); t1_builder_add_point( builder, x, y, 0 ); - x += top[1]; - y += top[2]; + + x = ADD_LONG( x, top[1] ); + y = ADD_LONG( y, top[2] ); t1_builder_add_point( builder, x, y, 0 ); - y += top[3]; + + y = ADD_LONG( y, top[3] ); t1_builder_add_point( builder, x, y, 1 ); break; @@ -1238,8 +1316,8 @@ if ( FT_SET_ERROR( t1_builder_start_point( builder, x, y ) ) ) goto Fail; - x += top[0]; - y += top[1]; + x = ADD_LONG( x, top[0] ); + y = ADD_LONG( y, top[1] ); Add_Line: if ( FT_SET_ERROR( t1_builder_add_point1( builder, x, y ) ) ) @@ -1249,8 +1327,9 @@ case op_rmoveto: FT_TRACE4(( " rmoveto" )); - x += top[0]; - y += top[1]; + x = ADD_LONG( x, top[0] ); + y = ADD_LONG( y, top[1] ); + if ( !decoder->flex_state ) { if ( builder->parse_state == T1_Parse_Start ) @@ -1266,16 +1345,16 @@ FT_SET_ERROR( t1_builder_check_points( builder, 3 ) ) ) goto Fail; - x += top[0]; - y += top[1]; + x = ADD_LONG( x, top[0] ); + y = ADD_LONG( y, top[1] ); t1_builder_add_point( builder, x, y, 0 ); - x += top[2]; - y += top[3]; + x = ADD_LONG( x, top[2] ); + y = ADD_LONG( y, top[3] ); t1_builder_add_point( builder, x, y, 0 ); - x += top[4]; - y += top[5]; + x = ADD_LONG( x, top[4] ); + y = ADD_LONG( y, top[5] ); t1_builder_add_point( builder, x, y, 1 ); break; @@ -1286,12 +1365,14 @@ FT_SET_ERROR( t1_builder_check_points( builder, 3 ) ) ) goto Fail; - y += top[0]; + y = ADD_LONG( y, top[0] ); t1_builder_add_point( builder, x, y, 0 ); - x += top[1]; - y += top[2]; + + x = ADD_LONG( x, top[1] ); + y = ADD_LONG( y, top[2] ); t1_builder_add_point( builder, x, y, 0 ); - x += top[3]; + + x = ADD_LONG( x, top[3] ); t1_builder_add_point( builder, x, y, 1 ); break; @@ -1301,13 +1382,14 @@ if ( FT_SET_ERROR( t1_builder_start_point( builder, x, y ) ) ) goto Fail; - y += top[0]; + y = ADD_LONG( y, top[0] ); goto Add_Line; case op_vmoveto: FT_TRACE4(( " vmoveto" )); - y += top[0]; + y = ADD_LONG( y, top[0] ); + if ( !decoder->flex_state ) { if ( builder->parse_state == T1_Parse_Start ) @@ -1464,7 +1546,7 @@ /* record vertical hint */ if ( hinter ) { - top[0] += orig_x; + top[0] = ADD_LONG( top[0], orig_x ); hinter->stem( hinter->hints, 0, top ); } break; @@ -1478,9 +1560,9 @@ FT_Pos dx = orig_x; - top[0] += dx; - top[2] += dx; - top[4] += dx; + top[0] = ADD_LONG( top[0], dx ); + top[2] = ADD_LONG( top[2], dx ); + top[4] = ADD_LONG( top[4], dx ); hinter->stem3( hinter->hints, 0, top ); } break; @@ -1556,14 +1638,286 @@ return FT_THROW( Stack_Underflow ); } +#else /* T1_CONFIG_OPTION_OLD_ENGINE */ - /* parse a single Type 1 glyph */ + /*************************************************************************/ + /* */ + /* <Function> */ + /* t1_decoder_parse_metrics */ + /* */ + /* <Description> */ + /* Parses a given Type 1 charstrings program to extract width */ + /* */ + /* <Input> */ + /* decoder :: The current Type 1 decoder. */ + /* */ + /* charstring_base :: The base address of the charstring stream. */ + /* */ + /* charstring_len :: The length in bytes of the charstring stream. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ FT_LOCAL_DEF( FT_Error ) - t1_decoder_parse_glyph( T1_Decoder decoder, - FT_UInt glyph ) + t1_decoder_parse_metrics( T1_Decoder decoder, + FT_Byte* charstring_base, + FT_UInt charstring_len ) { - return decoder->parse_callback( decoder, glyph ); + T1_Decoder_Zone zone; + FT_Byte* ip; + FT_Byte* limit; + T1_Builder builder = &decoder->builder; + +#ifdef FT_DEBUG_LEVEL_TRACE + FT_Bool bol = TRUE; +#endif + + + /* First of all, initialize the decoder */ + decoder->top = decoder->stack; + decoder->zone = decoder->zones; + zone = decoder->zones; + + builder->parse_state = T1_Parse_Start; + + FT_TRACE4(( "\n" + "Start charstring: get width\n" )); + + zone->base = charstring_base; + limit = zone->limit = charstring_base + charstring_len; + ip = zone->cursor = zone->base; + + /* now, execute loop */ + while ( ip < limit ) + { + FT_Long* top = decoder->top; + T1_Operator op = op_none; + FT_Int32 value = 0; + + +#ifdef FT_DEBUG_LEVEL_TRACE + if ( bol ) + { + FT_TRACE5(( " (%d)", decoder->top - decoder->stack )); + bol = FALSE; + } +#endif + + /*********************************************************************/ + /* */ + /* Decode operator or operand */ + /* */ + /* */ + + /* first of all, decompress operator or value */ + switch ( *ip++ ) + { + case 1: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 14: + case 15: + case 21: + case 22: + case 30: + case 31: + goto No_Width; + + case 13: + op = op_hsbw; + break; + + case 12: + if ( ip >= limit ) + { + FT_ERROR(( "t1_decoder_parse_metrics:" + " invalid escape (12+EOF)\n" )); + goto Syntax_Error; + } + + switch ( *ip++ ) + { + case 7: + op = op_sbw; + break; + + default: + goto No_Width; + } + break; + + case 255: /* four bytes integer */ + if ( ip + 4 > limit ) + { + FT_ERROR(( "t1_decoder_parse_metrics:" + " unexpected EOF in integer\n" )); + goto Syntax_Error; + } + + value = (FT_Int32)( ( (FT_UInt32)ip[0] << 24 ) | + ( (FT_UInt32)ip[1] << 16 ) | + ( (FT_UInt32)ip[2] << 8 ) | + (FT_UInt32)ip[3] ); + ip += 4; + + /* According to the specification, values > 32000 or < -32000 must */ + /* be followed by a `div' operator to make the result be in the */ + /* range [-32000;32000]. We expect that the second argument of */ + /* `div' is not a large number. Additionally, we don't handle */ + /* stuff like `<large1> <large2> <num> div <num> div' or */ + /* <large1> <large2> <num> div div'. This is probably not allowed */ + /* anyway. */ + if ( value > 32000 || value < -32000 ) + { + FT_ERROR(( "t1_decoder_parse_metrics:" + " large integer found for width\n" )); + goto Syntax_Error; + } + else + { + value = (FT_Int32)( (FT_UInt32)value << 16 ); + } + + break; + + default: + if ( ip[-1] >= 32 ) + { + if ( ip[-1] < 247 ) + value = (FT_Int32)ip[-1] - 139; + else + { + if ( ++ip > limit ) + { + FT_ERROR(( "t1_decoder_parse_metrics:" + " unexpected EOF in integer\n" )); + goto Syntax_Error; + } + + if ( ip[-2] < 251 ) + value = ( ( ip[-2] - 247 ) * 256 ) + ip[-1] + 108; + else + value = -( ( ( ip[-2] - 251 ) * 256 ) + ip[-1] + 108 ); + } + + value = (FT_Int32)( (FT_UInt32)value << 16 ); + } + else + { + FT_ERROR(( "t1_decoder_parse_metrics:" + " invalid byte (%d)\n", ip[-1] )); + goto Syntax_Error; + } + } + + /*********************************************************************/ + /* */ + /* Push value on stack, or process operator */ + /* */ + /* */ + if ( op == op_none ) + { + if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS ) + { + FT_ERROR(( "t1_decoder_parse_metrics: stack overflow\n" )); + goto Syntax_Error; + } + +#ifdef FT_DEBUG_LEVEL_TRACE + FT_TRACE4(( " %d", value / 65536 )); +#endif + + *top++ = value; + decoder->top = top; + } + else /* general operator */ + { + FT_Int num_args = t1_args_count[op]; + + + FT_ASSERT( num_args >= 0 ); + + if ( top - decoder->stack < num_args ) + goto Stack_Underflow; + +#ifdef FT_DEBUG_LEVEL_TRACE + + if ( top - decoder->stack != num_args ) + FT_TRACE0(( "t1_decoder_parse_metrics:" + " too much operands on the stack" + " (seen %d, expected %d)\n", + top - decoder->stack, num_args )); + +#endif /* FT_DEBUG_LEVEL_TRACE */ + + top -= num_args; + + switch ( op ) + { + case op_hsbw: + FT_TRACE4(( " hsbw" )); + + builder->parse_state = T1_Parse_Have_Width; + + builder->left_bearing.x = ADD_LONG( builder->left_bearing.x, + top[0] ); + + builder->advance.x = top[1]; + builder->advance.y = 0; + + /* we only want to compute the glyph's metrics */ + /* (lsb + advance width), not load the rest of */ + /* it; so exit immediately */ + return FT_Err_Ok; + + case op_sbw: + FT_TRACE4(( " sbw" )); + + builder->parse_state = T1_Parse_Have_Width; + + builder->left_bearing.x = ADD_LONG( builder->left_bearing.x, + top[0] ); + builder->left_bearing.y = ADD_LONG( builder->left_bearing.y, + top[1] ); + + builder->advance.x = top[2]; + builder->advance.y = top[3]; + + /* we only want to compute the glyph's metrics */ + /* (lsb + advance width), not load the rest of */ + /* it; so exit immediately */ + return FT_Err_Ok; + + default: + FT_ERROR(( "t1_decoder_parse_metrics:" + " unhandled opcode %d\n", op )); + goto Syntax_Error; + } + + } /* general operator processing */ + + } /* while ip < limit */ + + FT_TRACE4(( "..end..\n\n" )); + + No_Width: + FT_ERROR(( "t1_decoder_parse_metrics:" + " no width, found op %d instead\n", + ip[-1] )); + Syntax_Error: + return FT_THROW( Syntax_Error ); + + Stack_Underflow: + return FT_THROW( Stack_Underflow ); } +#endif /* T1_CONFIG_OPTION_OLD_ENGINE */ /* initialize T1 decoder */ @@ -1618,7 +1972,16 @@ FT_LOCAL_DEF( void ) t1_decoder_done( T1_Decoder decoder ) { + FT_Memory memory = decoder->builder.memory; + + t1_builder_done( &decoder->builder ); + + if ( decoder->cf2_instance.finalizer ) + { + decoder->cf2_instance.finalizer( decoder->cf2_instance.data ); + FT_FREE( decoder->cf2_instance.data ); + } } diff --git a/modules/freetype2/src/psaux/t1decode.h b/modules/freetype2/src/psaux/t1decode.h index 0f5adfa15..1d9718d67 100644 --- a/modules/freetype2/src/psaux/t1decode.h +++ b/modules/freetype2/src/psaux/t1decode.h @@ -4,7 +4,7 @@ /* */ /* PostScript Type 1 decoding routines (specification). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -31,7 +31,11 @@ FT_BEGIN_HEADER FT_CALLBACK_TABLE const T1_Decoder_FuncsRec t1_decoder_funcs; + FT_LOCAL( FT_Int ) + t1_lookup_glyph_by_stdcharcode_ps( PS_Decoder* decoder, + FT_Int charcode ); +#ifdef T1_CONFIG_OPTION_OLD_ENGINE FT_LOCAL( FT_Error ) t1_decoder_parse_glyph( T1_Decoder decoder, FT_UInt glyph_index ); @@ -40,6 +44,12 @@ FT_BEGIN_HEADER t1_decoder_parse_charstrings( T1_Decoder decoder, FT_Byte* base, FT_UInt len ); +#else + FT_LOCAL( FT_Error ) + t1_decoder_parse_metrics( T1_Decoder decoder, + FT_Byte* charstring_base, + FT_UInt charstring_len ); +#endif FT_LOCAL( FT_Error ) t1_decoder_init( T1_Decoder decoder, diff --git a/modules/freetype2/src/pshinter/Jamfile b/modules/freetype2/src/pshinter/Jamfile index fcb225811..3f5f0ae40 100644 --- a/modules/freetype2/src/pshinter/Jamfile +++ b/modules/freetype2/src/pshinter/Jamfile @@ -1,6 +1,6 @@ # FreeType 2 src/pshinter Jamfile # -# Copyright 2001-2016 by +# Copyright 2001-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/pshinter/module.mk b/modules/freetype2/src/pshinter/module.mk index 63110c46a..06707be3b 100644 --- a/modules/freetype2/src/pshinter/module.mk +++ b/modules/freetype2/src/pshinter/module.mk @@ -3,7 +3,7 @@ # -# Copyright 1996-2016 by +# Copyright 1996-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/pshinter/pshalgo.c b/modules/freetype2/src/pshinter/pshalgo.c index 5a538e27d..b98077c62 100644 --- a/modules/freetype2/src/pshinter/pshalgo.c +++ b/modules/freetype2/src/pshinter/pshalgo.c @@ -4,7 +4,7 @@ /* */ /* PostScript hinting algorithm (body). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used */ @@ -26,7 +26,7 @@ #undef FT_COMPONENT -#define FT_COMPONENT trace_pshalgo2 +#define FT_COMPONENT trace_pshalgo #ifdef DEBUG_HINTER diff --git a/modules/freetype2/src/pshinter/pshalgo.h b/modules/freetype2/src/pshinter/pshalgo.h index f1bda6501..c50683fbe 100644 --- a/modules/freetype2/src/pshinter/pshalgo.h +++ b/modules/freetype2/src/pshinter/pshalgo.h @@ -4,7 +4,7 @@ /* */ /* PostScript hinting algorithm (specification). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/pshinter/pshglob.c b/modules/freetype2/src/pshinter/pshglob.c index 2ac5ef155..accc04921 100644 --- a/modules/freetype2/src/pshinter/pshglob.c +++ b/modules/freetype2/src/pshinter/pshglob.c @@ -5,7 +5,7 @@ /* PostScript hinter global hinting management (body). */ /* Inspired by the new auto-hinter module. */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used */ @@ -227,8 +227,8 @@ } - /* Re-read blue zones from the original fonts and store them into out */ - /* private structure. This function re-orders, sanitizes and */ + /* Re-read blue zones from the original fonts and store them into our */ + /* private structure. This function re-orders, sanitizes, and */ /* fuzz-expands the zones as well. */ static void psh_blues_set_zones( PSH_Blues target, diff --git a/modules/freetype2/src/pshinter/pshglob.h b/modules/freetype2/src/pshinter/pshglob.h index 45c957b6e..cf80bf40e 100644 --- a/modules/freetype2/src/pshinter/pshglob.h +++ b/modules/freetype2/src/pshinter/pshglob.h @@ -4,7 +4,7 @@ /* */ /* PostScript hinter global hinting management. */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/pshinter/pshinter.c b/modules/freetype2/src/pshinter/pshinter.c index 614e0bb3d..0eedac452 100644 --- a/modules/freetype2/src/pshinter/pshinter.c +++ b/modules/freetype2/src/pshinter/pshinter.c @@ -4,7 +4,7 @@ /* */ /* FreeType PostScript Hinting module */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,13 +17,13 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT - #include <ft2build.h> -#include "pshpic.c" -#include "pshrec.c" -#include "pshglob.c" + #include "pshalgo.c" +#include "pshglob.c" #include "pshmod.c" +#include "pshpic.c" +#include "pshrec.c" /* END */ diff --git a/modules/freetype2/src/pshinter/pshmod.c b/modules/freetype2/src/pshinter/pshmod.c index d5d53ab2d..0b8f6f99b 100644 --- a/modules/freetype2/src/pshinter/pshmod.c +++ b/modules/freetype2/src/pshinter/pshmod.c @@ -4,7 +4,7 @@ /* */ /* FreeType PostScript hinter module implementation (body). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/pshinter/pshmod.h b/modules/freetype2/src/pshinter/pshmod.h index 39112a956..556de2fbc 100644 --- a/modules/freetype2/src/pshinter/pshmod.h +++ b/modules/freetype2/src/pshinter/pshmod.h @@ -4,7 +4,7 @@ /* */ /* PostScript hinter module interface (specification). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/pshinter/pshnterr.h b/modules/freetype2/src/pshinter/pshnterr.h index 7a94588b8..b9d02d295 100644 --- a/modules/freetype2/src/pshinter/pshnterr.h +++ b/modules/freetype2/src/pshinter/pshnterr.h @@ -4,7 +4,7 @@ /* */ /* PS Hinter error codes (specification only). */ /* */ -/* Copyright 2003-2016 by */ +/* Copyright 2003-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/pshinter/pshpic.c b/modules/freetype2/src/pshinter/pshpic.c index d0a3d8ebc..465ad3188 100644 --- a/modules/freetype2/src/pshinter/pshpic.c +++ b/modules/freetype2/src/pshinter/pshpic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for pshinter module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2018 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/pshinter/pshpic.h b/modules/freetype2/src/pshinter/pshpic.h index 75ee57354..4469ba87c 100644 --- a/modules/freetype2/src/pshinter/pshpic.h +++ b/modules/freetype2/src/pshinter/pshpic.h @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for pshinter module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2018 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/pshinter/pshrec.c b/modules/freetype2/src/pshinter/pshrec.c index 3aeb2651f..6648d13d6 100644 --- a/modules/freetype2/src/pshinter/pshrec.c +++ b/modules/freetype2/src/pshinter/pshrec.c @@ -4,7 +4,7 @@ /* */ /* FreeType PostScript hints recorder (body). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/pshinter/pshrec.h b/modules/freetype2/src/pshinter/pshrec.h index 97e6f0ed5..7e3dfe0d5 100644 --- a/modules/freetype2/src/pshinter/pshrec.h +++ b/modules/freetype2/src/pshinter/pshrec.h @@ -4,7 +4,7 @@ /* */ /* Postscript (Type1/Type2) hints recorder (specification). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/pshinter/rules.mk b/modules/freetype2/src/pshinter/rules.mk index 67ecf7862..966690efc 100644 --- a/modules/freetype2/src/pshinter/rules.mk +++ b/modules/freetype2/src/pshinter/rules.mk @@ -3,7 +3,7 @@ # -# Copyright 2001-2016 by +# Copyright 2001-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/psnames/Jamfile b/modules/freetype2/src/psnames/Jamfile index 35b8a99c8..a0fd37397 100644 --- a/modules/freetype2/src/psnames/Jamfile +++ b/modules/freetype2/src/psnames/Jamfile @@ -1,6 +1,6 @@ # FreeType 2 src/psnames Jamfile # -# Copyright 2001-2016 by +# Copyright 2001-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/psnames/module.mk b/modules/freetype2/src/psnames/module.mk index ba29af813..410f48a19 100644 --- a/modules/freetype2/src/psnames/module.mk +++ b/modules/freetype2/src/psnames/module.mk @@ -3,7 +3,7 @@ # -# Copyright 1996-2016 by +# Copyright 1996-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/psnames/psmodule.c b/modules/freetype2/src/psnames/psmodule.c index 01b85c3c8..8929ebe75 100644 --- a/modules/freetype2/src/psnames/psmodule.c +++ b/modules/freetype2/src/psnames/psmodule.c @@ -4,7 +4,7 @@ /* */ /* PSNames module implementation (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -23,7 +23,21 @@ #include "psmodule.h" + /* + * The file `pstables.h' with its arrays and its function + * `ft_get_adobe_glyph_index' is useful for other projects also (for + * example, `pdfium' is using it). However, if used as a C++ header, + * including it in two different source files makes it necessary to use + * `extern const' for the declaration of its arrays, otherwise the data + * would be duplicated as mandated by the C++ standard. + * + * For this reason, we use `DEFINE_PS_TABLES' to guard the function + * definitions, and `DEFINE_PS_TABLES_DATA' to provide both proper array + * declarations and definitions. + */ +#include "pstables.h" #define DEFINE_PS_TABLES +#define DEFINE_PS_TABLES_DATA #include "pstables.h" #include "psnamerr.h" diff --git a/modules/freetype2/src/psnames/psmodule.h b/modules/freetype2/src/psnames/psmodule.h index ee3c6cb63..3e94f8b43 100644 --- a/modules/freetype2/src/psnames/psmodule.h +++ b/modules/freetype2/src/psnames/psmodule.h @@ -4,7 +4,7 @@ /* */ /* High-level PSNames module interface (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/psnames/psnamerr.h b/modules/freetype2/src/psnames/psnamerr.h index 3a9f65323..14eb76c99 100644 --- a/modules/freetype2/src/psnames/psnamerr.h +++ b/modules/freetype2/src/psnames/psnamerr.h @@ -4,7 +4,7 @@ /* */ /* PS names module error codes (specification only). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/psnames/psnames.c b/modules/freetype2/src/psnames/psnames.c index e7b2c0b5e..febb80d59 100644 --- a/modules/freetype2/src/psnames/psnames.c +++ b/modules/freetype2/src/psnames/psnames.c @@ -4,7 +4,7 @@ /* */ /* FreeType PSNames module component (body only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,10 +17,10 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT - #include <ft2build.h> -#include "pspic.c" + #include "psmodule.c" +#include "pspic.c" /* END */ diff --git a/modules/freetype2/src/psnames/pspic.c b/modules/freetype2/src/psnames/pspic.c index a78ec5aa8..85a06f360 100644 --- a/modules/freetype2/src/psnames/pspic.c +++ b/modules/freetype2/src/psnames/pspic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for psnames module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2018 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/psnames/pspic.h b/modules/freetype2/src/psnames/pspic.h index 48348765c..889780cc0 100644 --- a/modules/freetype2/src/psnames/pspic.h +++ b/modules/freetype2/src/psnames/pspic.h @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for psnames module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2018 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/psnames/pstables.h b/modules/freetype2/src/psnames/pstables.h index 309f16bd3..79545ee03 100644 --- a/modules/freetype2/src/psnames/pstables.h +++ b/modules/freetype2/src/psnames/pstables.h @@ -4,7 +4,7 @@ /* */ /* PostScript glyph names. */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -19,7 +19,7 @@ /* This file has been generated automatically -- do not edit! */ -#ifndef DEFINE_PS_TABLES +#ifndef DEFINE_PS_TABLES_DATA #ifdef __cplusplus extern "C" #else @@ -27,7 +27,7 @@ #endif #endif const char ft_standard_glyph_names[3696] -#ifdef DEFINE_PS_TABLES +#ifdef DEFINE_PS_TABLES_DATA = { '.','n','u','l','l', 0, @@ -451,7 +451,7 @@ 'R','o','m','a','n', 0, 'S','e','m','i','b','o','l','d', 0, } -#endif /* DEFINE_PS_TABLES */ +#endif /* DEFINE_PS_TABLES_DATA */ ; @@ -459,7 +459,7 @@ /* Values are offsets into the `ft_standard_glyph_names' table */ -#ifndef DEFINE_PS_TABLES +#ifndef DEFINE_PS_TABLES_DATA #ifdef __cplusplus extern "C" #else @@ -467,7 +467,7 @@ #endif #endif const short ft_mac_names[FT_NUM_MAC_NAMES] -#ifdef DEFINE_PS_TABLES +#ifdef DEFINE_PS_TABLES_DATA = { 253, 0, 6, 261, 267, 274, 283, 294, 301, 309, 758, 330, 340, 351, @@ -490,7 +490,7 @@ 1270,1313,1323,1171,1290,1332,1211,1235,1276, 169, 175, 182, 189, 200, 209, 218, 225, 232, 239, 246 } -#endif /* DEFINE_PS_TABLES */ +#endif /* DEFINE_PS_TABLES_DATA */ ; @@ -498,7 +498,7 @@ /* Values are offsets into the `ft_standard_glyph_names' table */ -#ifndef DEFINE_PS_TABLES +#ifndef DEFINE_PS_TABLES_DATA #ifdef __cplusplus extern "C" #else @@ -506,7 +506,7 @@ #endif #endif const short ft_sid_names[FT_NUM_SID_NAMES] -#ifdef DEFINE_PS_TABLES +#ifdef DEFINE_PS_TABLES_DATA = { 253, 261, 267, 274, 283, 294, 301, 309, 319, 330, 340, 351, 360, 365, @@ -538,12 +538,12 @@ 3418,3430,3442,3454,3471,3483,3498,3506,3518,3530,3542,3559,3574,3586, 3597,3612,3620,3628,3636,3644,3650,3655,3660,3666,3673,3681,3687 } -#endif /* DEFINE_PS_TABLES */ +#endif /* DEFINE_PS_TABLES_DATA */ ; /* the following are indices into the SID name table */ -#ifndef DEFINE_PS_TABLES +#ifndef DEFINE_PS_TABLES_DATA #ifdef __cplusplus extern "C" #else @@ -551,7 +551,7 @@ #endif #endif const unsigned short t1_standard_encoding[256] -#ifdef DEFINE_PS_TABLES +#ifdef DEFINE_PS_TABLES_DATA = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -571,12 +571,12 @@ 0,138, 0,139, 0, 0, 0, 0,140,141,142,143, 0, 0, 0, 0, 0,144, 0, 0, 0,145, 0, 0,146,147,148,149, 0, 0, 0, 0 } -#endif /* DEFINE_PS_TABLES */ +#endif /* DEFINE_PS_TABLES_DATA */ ; /* the following are indices into the SID name table */ -#ifndef DEFINE_PS_TABLES +#ifndef DEFINE_PS_TABLES_DATA #ifdef __cplusplus extern "C" #else @@ -584,7 +584,7 @@ #endif #endif const unsigned short t1_expert_encoding[256] -#ifdef DEFINE_PS_TABLES +#ifdef DEFINE_PS_TABLES_DATA = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -604,7 +604,7 @@ 347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362, 363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378 } -#endif /* DEFINE_PS_TABLES */ +#endif /* DEFINE_PS_TABLES_DATA */ ; @@ -619,7 +619,7 @@ #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST -#ifndef DEFINE_PS_TABLES +#ifndef DEFINE_PS_TABLES_DATA #ifdef __cplusplus extern "C" #else @@ -627,7 +627,7 @@ #endif #endif const unsigned char ft_adobe_glyph_list[55997L] -#ifdef DEFINE_PS_TABLES +#ifdef DEFINE_PS_TABLES_DATA = { 0, 52, 0,106, 2,167, 3, 63, 4,220, 6,125, 9,143, 10, 23, @@ -4131,10 +4131,11 @@ 182,117, 2,218,167,218,178,232,233,242,225,231,225,238, 97,128, 48, 90,235,225,244,225,235,225,238, 97,128, 48,186 } -#endif /* DEFINE_PS_TABLES */ +#endif /* DEFINE_PS_TABLES_DATA */ ; +#ifdef DEFINE_PS_TABLES /* * This function searches the compressed table efficiently. */ @@ -4229,6 +4230,7 @@ NotFound: return 0; } +#endif /* DEFINE_PS_TABLES */ #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ diff --git a/modules/freetype2/src/psnames/rules.mk b/modules/freetype2/src/psnames/rules.mk index 9849f4053..4d629d841 100644 --- a/modules/freetype2/src/psnames/rules.mk +++ b/modules/freetype2/src/psnames/rules.mk @@ -3,7 +3,7 @@ # -# Copyright 1996-2016 by +# Copyright 1996-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/raster/Jamfile b/modules/freetype2/src/raster/Jamfile index 2ec88f560..838e7ef57 100644 --- a/modules/freetype2/src/raster/Jamfile +++ b/modules/freetype2/src/raster/Jamfile @@ -1,6 +1,6 @@ # FreeType 2 src/raster Jamfile # -# Copyright 2001-2016 by +# Copyright 2001-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/raster/ftmisc.h b/modules/freetype2/src/raster/ftmisc.h index 981ce3227..7e4011907 100644 --- a/modules/freetype2/src/raster/ftmisc.h +++ b/modules/freetype2/src/raster/ftmisc.h @@ -5,7 +5,7 @@ /* Miscellaneous macros for stand-alone rasterizer (specification */ /* only). */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used */ diff --git a/modules/freetype2/src/raster/ftraster.c b/modules/freetype2/src/raster/ftraster.c index 429f0d250..4354730d5 100644 --- a/modules/freetype2/src/raster/ftraster.c +++ b/modules/freetype2/src/raster/ftraster.c @@ -4,7 +4,7 @@ /* */ /* The FreeType glyph rasterizer (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/raster/ftraster.h b/modules/freetype2/src/raster/ftraster.h index 65cd5f960..40b5d6d32 100644 --- a/modules/freetype2/src/raster/ftraster.h +++ b/modules/freetype2/src/raster/ftraster.h @@ -4,7 +4,7 @@ /* */ /* The FreeType glyph rasterizer (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used */ diff --git a/modules/freetype2/src/raster/ftrend1.c b/modules/freetype2/src/raster/ftrend1.c index 5bd4b30c8..a7ce9731d 100644 --- a/modules/freetype2/src/raster/ftrend1.c +++ b/modules/freetype2/src/raster/ftrend1.c @@ -4,7 +4,7 @@ /* */ /* The FreeType glyph rasterizer interface (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -31,12 +31,7 @@ static FT_Error ft_raster1_init( FT_Renderer render ) { - FT_Library library = FT_MODULE_LIBRARY( render ); - - - render->clazz->raster_class->raster_reset( render->raster, - library->raster_pool, - library->raster_pool_size ); + render->clazz->raster_class->raster_reset( render->raster, NULL, 0 ); return FT_Err_Ok; } @@ -102,12 +97,12 @@ FT_Render_Mode mode, const FT_Vector* origin ) { - FT_Error error; - FT_Outline* outline; - FT_BBox cbox, cbox0; - FT_UInt width, height, pitch; - FT_Bitmap* bitmap; - FT_Memory memory; + FT_Error error = FT_Err_Ok; + FT_Outline* outline = &slot->outline; + FT_Bitmap* bitmap = &slot->bitmap; + FT_Memory memory = render->root.memory; + FT_Pos x_shift = 0; + FT_Pos y_shift = 0; FT_Raster_Params params; @@ -126,60 +121,6 @@ return FT_THROW( Cannot_Render_Glyph ); } - outline = &slot->outline; - - /* translate the outline to the new origin if needed */ - if ( origin ) - FT_Outline_Translate( outline, origin->x, origin->y ); - - /* compute the control box, and grid fit it */ - FT_Outline_Get_CBox( outline, &cbox0 ); - - /* undocumented but confirmed: bbox values get rounded */ -#if 1 - cbox.xMin = FT_PIX_ROUND( cbox0.xMin ); - cbox.yMin = FT_PIX_ROUND( cbox0.yMin ); - cbox.xMax = FT_PIX_ROUND( cbox0.xMax ); - cbox.yMax = FT_PIX_ROUND( cbox0.yMax ); -#else - cbox.xMin = FT_PIX_FLOOR( cbox.xMin ); - cbox.yMin = FT_PIX_FLOOR( cbox.yMin ); - cbox.xMax = FT_PIX_CEIL( cbox.xMax ); - cbox.yMax = FT_PIX_CEIL( cbox.yMax ); -#endif - - /* If either `width' or `height' round to 0, try */ - /* explicitly rounding up/down. In the case of */ - /* glyphs containing only one very narrow feature, */ - /* this gives the drop-out compensation in the scan */ - /* conversion code a chance to do its stuff. */ - width = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 ); - if ( width == 0 ) - { - cbox.xMin = FT_PIX_FLOOR( cbox0.xMin ); - cbox.xMax = FT_PIX_CEIL( cbox0.xMax ); - - width = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 ); - } - - height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 ); - if ( height == 0 ) - { - cbox.yMin = FT_PIX_FLOOR( cbox0.yMin ); - cbox.yMax = FT_PIX_CEIL( cbox0.yMax ); - - height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 ); - } - - if ( width > FT_USHORT_MAX || height > FT_USHORT_MAX ) - { - error = FT_THROW( Invalid_Argument ); - goto Exit; - } - - bitmap = &slot->bitmap; - memory = render->root.memory; - /* release old bitmap buffer */ if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) { @@ -187,39 +128,48 @@ slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; } - pitch = ( ( width + 15 ) >> 4 ) << 1; - bitmap->pixel_mode = FT_PIXEL_MODE_MONO; + ft_glyphslot_preset_bitmap( slot, mode, origin ); - bitmap->width = width; - bitmap->rows = height; - bitmap->pitch = (int)pitch; - - if ( FT_ALLOC_MULT( bitmap->buffer, pitch, height ) ) + /* allocate new one */ + if ( FT_ALLOC_MULT( bitmap->buffer, bitmap->rows, bitmap->pitch ) ) goto Exit; slot->internal->flags |= FT_GLYPH_OWN_BITMAP; + x_shift = -slot->bitmap_left * 64; + y_shift = ( (FT_Int)bitmap->rows - slot->bitmap_top ) * 64; + + if ( origin ) + { + x_shift += origin->x; + y_shift += origin->y; + } + /* translate outline to render it into the bitmap */ - FT_Outline_Translate( outline, -cbox.xMin, -cbox.yMin ); + if ( x_shift || y_shift ) + FT_Outline_Translate( outline, x_shift, y_shift ); /* set up parameters */ params.target = bitmap; params.source = outline; - params.flags = 0; + params.flags = FT_RASTER_FLAG_DEFAULT; /* render outline into the bitmap */ error = render->raster_render( render->raster, ¶ms ); - FT_Outline_Translate( outline, cbox.xMin, cbox.yMin ); - - if ( error ) - goto Exit; + Exit: + if ( !error ) + /* everything is fine; the glyph is now officially a bitmap */ + slot->format = FT_GLYPH_FORMAT_BITMAP; + else if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) + { + FT_FREE( bitmap->buffer ); + slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; + } - slot->format = FT_GLYPH_FORMAT_BITMAP; - slot->bitmap_left = (FT_Int)( cbox.xMin >> 6 ); - slot->bitmap_top = (FT_Int)( cbox.yMax >> 6 ); + if ( x_shift || y_shift ) + FT_Outline_Translate( outline, -x_shift, -y_shift ); - Exit: return error; } diff --git a/modules/freetype2/src/raster/ftrend1.h b/modules/freetype2/src/raster/ftrend1.h index a431f185d..2abdf2d70 100644 --- a/modules/freetype2/src/raster/ftrend1.h +++ b/modules/freetype2/src/raster/ftrend1.h @@ -4,7 +4,7 @@ /* */ /* The FreeType glyph rasterizer interface (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/raster/module.mk b/modules/freetype2/src/raster/module.mk index f4a5f8e83..b115f416b 100644 --- a/modules/freetype2/src/raster/module.mk +++ b/modules/freetype2/src/raster/module.mk @@ -3,7 +3,7 @@ # -# Copyright 1996-2016 by +# Copyright 1996-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/raster/raster.c b/modules/freetype2/src/raster/raster.c index 5b21dcbc6..76edd21e1 100644 --- a/modules/freetype2/src/raster/raster.c +++ b/modules/freetype2/src/raster/raster.c @@ -4,7 +4,7 @@ /* */ /* FreeType monochrome rasterer module component (body only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,11 +17,11 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT - #include <ft2build.h> -#include "rastpic.c" + #include "ftraster.c" #include "ftrend1.c" +#include "rastpic.c" /* END */ diff --git a/modules/freetype2/src/raster/rasterrs.h b/modules/freetype2/src/raster/rasterrs.h index 44da7fca5..22a3e1534 100644 --- a/modules/freetype2/src/raster/rasterrs.h +++ b/modules/freetype2/src/raster/rasterrs.h @@ -4,7 +4,7 @@ /* */ /* monochrome renderer error codes (specification only). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/raster/rastpic.c b/modules/freetype2/src/raster/rastpic.c index dcfa92eef..1dc8981b8 100644 --- a/modules/freetype2/src/raster/rastpic.c +++ b/modules/freetype2/src/raster/rastpic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for raster module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2018 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/raster/rastpic.h b/modules/freetype2/src/raster/rastpic.h index 781587638..6d0877c42 100644 --- a/modules/freetype2/src/raster/rastpic.h +++ b/modules/freetype2/src/raster/rastpic.h @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for raster module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2018 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/raster/rules.mk b/modules/freetype2/src/raster/rules.mk index 929faa3a9..9aef1f0ba 100644 --- a/modules/freetype2/src/raster/rules.mk +++ b/modules/freetype2/src/raster/rules.mk @@ -3,7 +3,7 @@ # -# Copyright 1996-2016 by +# Copyright 1996-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/sfnt/Jamfile b/modules/freetype2/src/sfnt/Jamfile index 089cc269b..57977fc96 100644 --- a/modules/freetype2/src/sfnt/Jamfile +++ b/modules/freetype2/src/sfnt/Jamfile @@ -1,6 +1,6 @@ # FreeType 2 src/sfnt Jamfile # -# Copyright 2001-2016 by +# Copyright 2001-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/sfnt/module.mk b/modules/freetype2/src/sfnt/module.mk index ca19e096a..51ca67e78 100644 --- a/modules/freetype2/src/sfnt/module.mk +++ b/modules/freetype2/src/sfnt/module.mk @@ -3,7 +3,7 @@ # -# Copyright 1996-2016 by +# Copyright 1996-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/sfnt/pngshim.c b/modules/freetype2/src/sfnt/pngshim.c index ff6729273..16020266a 100644 --- a/modules/freetype2/src/sfnt/pngshim.c +++ b/modules/freetype2/src/sfnt/pngshim.c @@ -4,7 +4,7 @@ /* */ /* PNG Bitmap glyph support. */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2018 by */ /* Google, Inc. */ /* Written by Stuart Gill and Behdad Esfahbod. */ /* */ @@ -24,9 +24,10 @@ #include FT_CONFIG_STANDARD_LIBRARY_H -#ifdef FT_CONFIG_OPTION_USE_PNG +#if defined( TT_CONFIG_OPTION_EMBEDDED_BITMAPS ) && \ + defined( FT_CONFIG_OPTION_USE_PNG ) - /* We always include <stjmp.h>, so make libpng shut up! */ + /* We always include <setjmp.h>, so make libpng shut up! */ #define PNG_SKIP_SETJMP_CHECK 1 #include <png.h> #include "pngshim.h" @@ -48,18 +49,85 @@ } - /* Premultiplies data and converts RGBA bytes => native endian. */ + /* Premultiplies data and converts RGBA bytes => BGRA. */ static void premultiply_data( png_structp png, png_row_infop row_info, png_bytep data ) { - unsigned int i; + unsigned int i = 0, limit; + + /* The `vector_size' attribute was introduced in gcc 3.1, which */ + /* predates clang; the `__BYTE_ORDER__' preprocessor symbol was */ + /* introduced in gcc 4.6 and clang 3.2, respectively. */ + /* `__builtin_shuffle' for gcc was introduced in gcc 4.7.0. */ +#if ( ( defined( __GNUC__ ) && \ + ( ( __GNUC__ >= 5 ) || \ + ( ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ >= 7 ) ) ) ) || \ + ( defined( __clang__ ) && \ + ( ( __clang_major__ >= 4 ) || \ + ( ( __clang_major__ == 3 ) && ( __clang_minor__ >= 2 ) ) ) ) ) && \ + defined( __OPTIMIZE__ ) && \ + __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + +#ifdef __clang__ + /* the clang documentation doesn't cover the two-argument case of */ + /* `__builtin_shufflevector'; however, it is is implemented since */ + /* version 2.8 */ +#define vector_shuffle __builtin_shufflevector +#else +#define vector_shuffle __builtin_shuffle +#endif - FT_UNUSED( png ); + typedef unsigned short v82 __attribute__(( vector_size( 16 ) )); - for ( i = 0; i < row_info->rowbytes; i += 4 ) + if ( row_info->rowbytes > 15 ) + { + /* process blocks of 16 bytes in one rush, which gives a nice speed-up */ + limit = row_info->rowbytes - 16 + 1; + for ( ; i < limit; i += 16 ) + { + unsigned char* base = &data[i]; + + v82 s, s0, s1, a; + + /* clang <= 3.9 can't apply scalar values to vectors */ + /* (or rather, it needs a different syntax) */ + v82 n0x80 = { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }; + v82 n0xFF = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + v82 n8 = { 8, 8, 8, 8, 8, 8, 8, 8 }; + + v82 ma = { 1, 1, 3, 3, 5, 5, 7, 7 }; + v82 o1 = { 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF }; + v82 m0 = { 1, 0, 3, 2, 5, 4, 7, 6 }; + + + ft_memcpy( &s, base, 16 ); /* RGBA RGBA RGBA RGBA */ + s0 = s & n0xFF; /* R B R B R B R B */ + s1 = s >> n8; /* G A G A G A G A */ + + a = vector_shuffle( s1, ma ); /* A A A A A A A A */ + s1 |= o1; /* G 1 G 1 G 1 G 1 */ + s0 = vector_shuffle( s0, m0 ); /* B R B R B R B R */ + + s0 *= a; + s1 *= a; + s0 += n0x80; + s1 += n0x80; + s0 = ( s0 + ( s0 >> n8 ) ) >> n8; + s1 = ( s1 + ( s1 >> n8 ) ) >> n8; + + s = s0 | ( s1 << n8 ); + ft_memcpy( base, &s, 16 ); + } + } +#endif /* use `vector_size' */ + + FT_UNUSED( png ); + + limit = row_info->rowbytes; + for ( ; i < limit; i += 4 ) { unsigned char* base = &data[i]; unsigned int alpha = base[3]; @@ -169,7 +237,7 @@ return; } - memcpy( data, stream->cursor, length ); + ft_memcpy( data, stream->cursor, length ); FT_FRAME_EXIT(); } @@ -377,7 +445,12 @@ return error; } -#endif /* FT_CONFIG_OPTION_USE_PNG */ +#else /* !(TT_CONFIG_OPTION_EMBEDDED_BITMAPS && FT_CONFIG_OPTION_USE_PNG) */ + + /* ANSI C doesn't like empty source files */ + typedef int _pngshim_dummy; + +#endif /* !(TT_CONFIG_OPTION_EMBEDDED_BITMAPS && FT_CONFIG_OPTION_USE_PNG) */ /* END */ diff --git a/modules/freetype2/src/sfnt/pngshim.h b/modules/freetype2/src/sfnt/pngshim.h index 0af4bfc5b..194238c3a 100644 --- a/modules/freetype2/src/sfnt/pngshim.h +++ b/modules/freetype2/src/sfnt/pngshim.h @@ -4,7 +4,7 @@ /* */ /* PNG Bitmap glyph support. */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2018 by */ /* Google, Inc. */ /* Written by Stuart Gill and Behdad Esfahbod. */ /* */ diff --git a/modules/freetype2/src/sfnt/rules.mk b/modules/freetype2/src/sfnt/rules.mk index e9fc42156..83acc66a8 100644 --- a/modules/freetype2/src/sfnt/rules.mk +++ b/modules/freetype2/src/sfnt/rules.mk @@ -3,7 +3,7 @@ # -# Copyright 1996-2016 by +# Copyright 1996-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/sfnt/sfdriver.c b/modules/freetype2/src/sfnt/sfdriver.c index 1f15223cb..303e1ca9f 100644 --- a/modules/freetype2/src/sfnt/sfdriver.c +++ b/modules/freetype2/src/sfnt/sfdriver.c @@ -4,7 +4,7 @@ /* */ /* High-level SFNT driver interface (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -20,6 +20,7 @@ #include FT_INTERNAL_DEBUG_H #include FT_INTERNAL_SFNT_H #include FT_INTERNAL_OBJECTS_H +#include FT_TRUETYPE_IDS_H #include "sfdriver.h" #include "ttload.h" @@ -50,6 +51,11 @@ #include FT_SERVICE_SFNT_H #include FT_SERVICE_TT_CMAP_H +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT +#include FT_MULTIPLE_MASTERS_H +#include FT_SERVICE_MULTIPLE_MASTERS_H +#endif + /*************************************************************************/ /* */ @@ -220,113 +226,841 @@ * */ - static const char* - sfnt_get_ps_name( TT_Face face ) + /* an array representing allowed ASCII characters in a PS string */ + static const unsigned char sfnt_ps_map[16] = { - FT_Int n, found_win, found_apple; - const char* result = NULL; + /* 4 0 C 8 */ + 0x00, 0x00, /* 0x00: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 */ + 0x00, 0x00, /* 0x10: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 */ + 0xDE, 0x7C, /* 0x20: 1 1 0 1 1 1 1 0 0 1 1 1 1 1 0 0 */ + 0xFF, 0xAF, /* 0x30: 1 1 1 1 1 1 1 1 1 0 1 0 1 1 1 1 */ + 0xFF, 0xFF, /* 0x40: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 */ + 0xFF, 0xD7, /* 0x50: 1 1 1 1 1 1 1 1 1 1 0 1 0 1 1 1 */ + 0xFF, 0xFF, /* 0x60: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 */ + 0xFF, 0x57 /* 0x70: 1 1 1 1 1 1 1 1 0 1 0 1 0 1 1 1 */ + }; + + + static int + sfnt_is_postscript( int c ) + { + unsigned int cc; - /* shouldn't happen, but just in case to avoid memory leaks */ - if ( face->postscript_name ) - return face->postscript_name; + if ( c < 0 || c >= 0x80 ) + return 0; - /* scan the name table to see whether we have a Postscript name here, */ - /* either in Macintosh or Windows platform encodings */ - found_win = -1; - found_apple = -1; + cc = (unsigned int)c; + + return sfnt_ps_map[cc >> 3] & ( 1 << ( cc & 0x07 ) ); + } + + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + + /* Only ASCII letters and digits are taken for a variation font */ + /* instance's PostScript name. */ + /* */ + /* `ft_isalnum' is a macro, but we need a function here, thus */ + /* this definition. */ + static int + sfnt_is_alphanumeric( int c ) + { + return ft_isalnum( c ); + } + + + /* the implementation of MurmurHash3 is taken and adapted from */ + /* https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp */ + +#define ROTL32( x, r ) ( x << r ) | ( x >> ( 32 - r ) ) + + + static FT_UInt32 + fmix32( FT_UInt32 h ) + { + h ^= h >> 16; + h *= 0x85ebca6b; + h ^= h >> 13; + h *= 0xc2b2ae35; + h ^= h >> 16; + + return h; + } + + + static void + murmur_hash_3_128( const void* key, + const unsigned int len, + FT_UInt32 seed, + void* out ) + { + const FT_Byte* data = (const FT_Byte*)key; + const int nblocks = (int)len / 16; + + FT_UInt32 h1 = seed; + FT_UInt32 h2 = seed; + FT_UInt32 h3 = seed; + FT_UInt32 h4 = seed; + + const FT_UInt32 c1 = 0x239b961b; + const FT_UInt32 c2 = 0xab0e9789; + const FT_UInt32 c3 = 0x38b34ae5; + const FT_UInt32 c4 = 0xa1e38b93; + + const FT_UInt32* blocks = (const FT_UInt32*)( data + nblocks * 16 ); + + int i; + + + for( i = -nblocks; i; i++ ) + { + FT_UInt32 k1 = blocks[i * 4 + 0]; + FT_UInt32 k2 = blocks[i * 4 + 1]; + FT_UInt32 k3 = blocks[i * 4 + 2]; + FT_UInt32 k4 = blocks[i * 4 + 3]; + + + k1 *= c1; + k1 = ROTL32( k1, 15 ); + k1 *= c2; + h1 ^= k1; + + h1 = ROTL32( h1, 19 ); + h1 += h2; + h1 = h1 * 5 + 0x561ccd1b; + + k2 *= c2; + k2 = ROTL32( k2, 16 ); + k2 *= c3; + h2 ^= k2; + + h2 = ROTL32( h2, 17 ); + h2 += h3; + h2 = h2 * 5 + 0x0bcaa747; + + k3 *= c3; + k3 = ROTL32( k3, 17 ); + k3 *= c4; + h3 ^= k3; + + h3 = ROTL32( h3, 15 ); + h3 += h4; + h3 = h3 * 5 + 0x96cd1c35; + + k4 *= c4; + k4 = ROTL32( k4, 18 ); + k4 *= c1; + h4 ^= k4; + + h4 = ROTL32( h4, 13 ); + h4 += h1; + h4 = h4 * 5 + 0x32ac3b17; + } - for ( n = 0; n < face->num_names; n++ ) { - TT_NameEntryRec* name = face->name_table.names + n; + const FT_Byte* tail = (const FT_Byte*)( data + nblocks * 16 ); + FT_UInt32 k1 = 0; + FT_UInt32 k2 = 0; + FT_UInt32 k3 = 0; + FT_UInt32 k4 = 0; - if ( name->nameID == 6 && name->stringLength > 0 ) + + switch ( len & 15 ) { - if ( name->platformID == 3 && - name->encodingID == 1 && - name->languageID == 0x409 ) - found_win = n; - - if ( name->platformID == 1 && - name->encodingID == 0 && - name->languageID == 0 ) - found_apple = n; + case 15: + k4 ^= (FT_UInt32)tail[14] << 16; + case 14: + k4 ^= (FT_UInt32)tail[13] << 8; + case 13: + k4 ^= (FT_UInt32)tail[12]; + k4 *= c4; + k4 = ROTL32( k4, 18 ); + k4 *= c1; + h4 ^= k4; + + case 12: + k3 ^= (FT_UInt32)tail[11] << 24; + case 11: + k3 ^= (FT_UInt32)tail[10] << 16; + case 10: + k3 ^= (FT_UInt32)tail[9] << 8; + case 9: + k3 ^= (FT_UInt32)tail[8]; + k3 *= c3; + k3 = ROTL32( k3, 17 ); + k3 *= c4; + h3 ^= k3; + + case 8: + k2 ^= (FT_UInt32)tail[7] << 24; + case 7: + k2 ^= (FT_UInt32)tail[6] << 16; + case 6: + k2 ^= (FT_UInt32)tail[5] << 8; + case 5: + k2 ^= (FT_UInt32)tail[4]; + k2 *= c2; + k2 = ROTL32( k2, 16 ); + k2 *= c3; + h2 ^= k2; + + case 4: + k1 ^= (FT_UInt32)tail[3] << 24; + case 3: + k1 ^= (FT_UInt32)tail[2] << 16; + case 2: + k1 ^= (FT_UInt32)tail[1] << 8; + case 1: + k1 ^= (FT_UInt32)tail[0]; + k1 *= c1; + k1 = ROTL32( k1, 15 ); + k1 *= c2; + h1 ^= k1; } } - if ( found_win != -1 ) + h1 ^= len; + h2 ^= len; + h3 ^= len; + h4 ^= len; + + h1 += h2; + h1 += h3; + h1 += h4; + + h2 += h1; + h3 += h1; + h4 += h1; + + h1 = fmix32( h1 ); + h2 = fmix32( h2 ); + h3 = fmix32( h3 ); + h4 = fmix32( h4 ); + + h1 += h2; + h1 += h3; + h1 += h4; + + h2 += h1; + h3 += h1; + h4 += h1; + + ((FT_UInt32*)out)[0] = h1; + ((FT_UInt32*)out)[1] = h2; + ((FT_UInt32*)out)[2] = h3; + ((FT_UInt32*)out)[3] = h4; + } + + +#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ + + + typedef int (*char_type_func)( int c ); + + + /* handling of PID/EID 3/0 and 3/1 is the same */ +#define IS_WIN( n ) ( (n)->platformID == 3 && \ + ( (n)->encodingID == 1 || (n)->encodingID == 0 ) && \ + (n)->languageID == 0x409 ) + +#define IS_APPLE( n ) ( (n)->platformID == 1 && \ + (n)->encodingID == 0 && \ + (n)->languageID == 0 ) + + static char* + get_win_string( FT_Memory memory, + FT_Stream stream, + TT_Name entry, + char_type_func char_type, + FT_Bool report_invalid_characters ) + { + FT_Error error = FT_Err_Ok; + + char* result = NULL; + FT_String* r; + FT_Char* p; + FT_UInt len; + + FT_UNUSED( error ); + + + if ( FT_ALLOC( result, entry->stringLength / 2 + 1 ) ) + return NULL; + + if ( FT_STREAM_SEEK( entry->stringOffset ) || + FT_FRAME_ENTER( entry->stringLength ) ) { - FT_Memory memory = face->root.memory; - TT_NameEntryRec* name = face->name_table.names + found_win; - FT_UInt len = name->stringLength / 2; - FT_Error error = FT_Err_Ok; + FT_FREE( result ); + entry->stringLength = 0; + entry->stringOffset = 0; + FT_FREE( entry->string ); - FT_UNUSED( error ); + return NULL; + } + r = (FT_String*)result; + p = (FT_Char*)stream->cursor; - if ( !FT_ALLOC( result, name->stringLength + 1 ) ) + for ( len = entry->stringLength / 2; len > 0; len--, p += 2 ) + { + if ( p[0] == 0 ) { - FT_Stream stream = face->name_table.stream; - FT_String* r = (FT_String*)result; - FT_Char* p; + if ( char_type( p[1] ) ) + *r++ = p[1]; + else + { + if ( report_invalid_characters ) + { + FT_TRACE0(( "get_win_string:" + " Character `%c' (0x%X) invalid in PS name string\n", + p[1], p[1] )); + /* it's not the job of FreeType to correct PS names... */ + *r++ = p[1]; + } + } + } + } + *r = '\0'; + + FT_FRAME_EXIT(); + + return result; + } + + + static char* + get_apple_string( FT_Memory memory, + FT_Stream stream, + TT_Name entry, + char_type_func char_type, + FT_Bool report_invalid_characters ) + { + FT_Error error = FT_Err_Ok; + + char* result = NULL; + FT_String* r; + FT_Char* p; + FT_UInt len; + + FT_UNUSED( error ); + + if ( FT_ALLOC( result, entry->stringLength + 1 ) ) + return NULL; + + if ( FT_STREAM_SEEK( entry->stringOffset ) || + FT_FRAME_ENTER( entry->stringLength ) ) + { + FT_FREE( result ); + entry->stringOffset = 0; + entry->stringLength = 0; + FT_FREE( entry->string ); + + return NULL; + } - if ( FT_STREAM_SEEK( name->stringOffset ) || - FT_FRAME_ENTER( name->stringLength ) ) + r = (FT_String*)result; + p = (FT_Char*)stream->cursor; + + for ( len = entry->stringLength; len > 0; len--, p++ ) + { + if ( char_type( *p ) ) + *r++ = *p; + else + { + if ( report_invalid_characters ) { - FT_FREE( result ); - name->stringLength = 0; - name->stringOffset = 0; - FT_FREE( name->string ); + FT_TRACE0(( "get_apple_string:" + " Character `%c' (0x%X) invalid in PS name string\n", + *p, *p )); + /* it's not the job of FreeType to correct PS names... */ + *r++ = *p; + } + } + } + *r = '\0'; + + FT_FRAME_EXIT(); + + return result; + } - goto Exit; + + static FT_Bool + sfnt_get_name_id( TT_Face face, + FT_UShort id, + FT_Int *win, + FT_Int *apple ) + { + FT_Int n; + + + *win = -1; + *apple = -1; + + for ( n = 0; n < face->num_names; n++ ) + { + TT_Name name = face->name_table.names + n; + + + if ( name->nameID == id && name->stringLength > 0 ) + { + if ( IS_WIN( name ) ) + *win = n; + + if ( IS_APPLE( name ) ) + *apple = n; + } + } + + return ( *win >= 0 ) || ( *apple >= 0 ); + } + + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + + /* + The maximum length of an axis value descriptor. + + We need 65536 different values for the decimal fraction; this fits + nicely into five decimal places. Consequently, it consists of + + . the minus sign if the number is negative, + . up to five characters for the digits before the decimal point, + . the decimal point if there is a fractional part, and + . up to five characters for the digits after the decimal point. + + We also need one byte for the leading `_' character and up to four + bytes for the axis tag. + */ +#define MAX_VALUE_DESCRIPTOR_LEN ( 1 + 5 + 1 + 5 + 1 + 4 ) + + + /* the maximum length of PostScript font names */ +#define MAX_PS_NAME_LEN 127 + + + /* + * Find the shortest decimal representation of a 16.16 fixed point + * number. The function fills `buf' with the result, returning a pointer + * to the position after the representation's last byte. + */ + + static char* + fixed2float( FT_Int fixed, + char* buf ) + { + char* p; + char* q; + char tmp[5]; + + FT_Int int_part; + FT_Int frac_part; + + FT_Int i; + + + p = buf; + + if ( fixed == 0 ) + { + *p++ = '0'; + return p; + } + + if ( fixed < 0 ) + { + *p++ = '-'; + fixed = -fixed; + } + + int_part = ( fixed >> 16 ) & 0xFFFF; + frac_part = fixed & 0xFFFF; + + /* get digits of integer part (in reverse order) */ + q = tmp; + while ( int_part > 0 ) + { + *q++ = '0' + int_part % 10; + int_part /= 10; + } + + /* copy digits in correct order to buffer */ + while ( q > tmp ) + *p++ = *--q; + + if ( !frac_part ) + return p; + + /* save position of point */ + q = p; + *p++ = '.'; + + /* apply rounding */ + frac_part = frac_part * 10 + 5; + + /* get digits of fractional part */ + for ( i = 0; i < 5; i++ ) + { + *p++ = '0' + (char)( frac_part / 0x10000L ); + + frac_part %= 0x10000L; + if ( !frac_part ) + break; + + frac_part *= 10; + } + + /* + If the remainder stored in `frac_part' (after the last FOR loop) is + smaller than 34480*10, the resulting decimal value minus 0.00001 is + an equivalent representation of `fixed'. + + The above FOR loop always finds the larger of the two values; I + verified this by iterating over all possible fixed point numbers. + + If the remainder is 17232*10, both values are equally good, and we + take the next even number (following IEEE 754's `round to nearest, + ties to even' rounding rule). + + If the remainder is smaller than 17232*10, the lower of the two + numbers is nearer to the exact result (values 17232 and 34480 were + also found by testing all possible fixed point values). + + We use this to find a shorter decimal representation. If not ending + with digit zero, we take the representation with less error. + */ + p--; + if ( p - q == 5 ) /* five digits? */ + { + /* take the representation that has zero as the last digit */ + if ( frac_part < 34480 * 10 && + *p == '1' ) + *p = '0'; + + /* otherwise use the one with less error */ + else if ( frac_part == 17232 * 10 && + *p & 1 ) + *p -= 1; + + else if ( frac_part < 17232 * 10 && + *p != '0' ) + *p -= 1; + } + + /* remove trailing zeros */ + while ( *p == '0' ) + *p-- = '\0'; + + return p + 1; + } + + + static const char hexdigits[16] = + { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' + }; + + + static const char* + sfnt_get_var_ps_name( TT_Face face ) + { + FT_Error error; + FT_Memory memory = face->root.memory; + + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + + FT_UInt num_coords; + FT_Fixed* coords; + FT_MM_Var* mm_var; + + FT_Int found, win, apple; + FT_UInt i, j; + + char* result = NULL; + char* p; + + + if ( !face->var_postscript_prefix ) + { + FT_UInt len; + + + /* check whether we have a Variations PostScript Name Prefix */ + found = sfnt_get_name_id( face, + TT_NAME_ID_VARIATIONS_PREFIX, + &win, + &apple ); + if ( !found ) + { + /* otherwise use the typographic family name */ + found = sfnt_get_name_id( face, + TT_NAME_ID_TYPOGRAPHIC_FAMILY, + &win, + &apple ); + } + + if ( !found ) + { + /* as a last resort we try the family name; note that this is */ + /* not in the Adobe TechNote, but GX fonts (which predate the */ + /* TechNote) benefit from this behaviour */ + found = sfnt_get_name_id( face, + TT_NAME_ID_FONT_FAMILY, + &win, + &apple ); + } + + if ( !found ) + { + FT_TRACE0(( "sfnt_get_var_ps_name:" + " Can't construct PS name prefix for font instances\n" )); + return NULL; + } + + /* prefer Windows entries over Apple */ + if ( win != -1 ) + result = get_win_string( face->root.memory, + face->name_table.stream, + face->name_table.names + win, + sfnt_is_alphanumeric, + 0 ); + else + result = get_apple_string( face->root.memory, + face->name_table.stream, + face->name_table.names + apple, + sfnt_is_alphanumeric, + 0 ); + + len = ft_strlen( result ); + + /* sanitize if necessary; we reserve space for 36 bytes (a 128bit */ + /* checksum as a hex number, preceded by `-' and followed by three */ + /* ASCII dots, to be used if the constructed PS name would be too */ + /* long); this is also sufficient for a single instance */ + if ( len > MAX_PS_NAME_LEN - ( 1 + 32 + 3 ) ) + { + len = MAX_PS_NAME_LEN - ( 1 + 32 + 3 ); + result[len] = '\0'; + + FT_TRACE0(( "sfnt_get_var_ps_name:" + " Shortening variation PS name prefix\n" + " " + " to %d characters\n", len )); + } + + face->var_postscript_prefix = result; + face->var_postscript_prefix_len = len; + } + + mm->get_var_blend( FT_FACE( face ), + &num_coords, + &coords, + NULL, + &mm_var ); + + if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) && + !FT_IS_VARIATION( FT_FACE( face ) ) ) + { + SFNT_Service sfnt = (SFNT_Service)face->sfnt; + + FT_Long instance = ( ( face->root.face_index & 0x7FFF0000L ) >> 16 ) - 1; + FT_UInt psid = mm_var->namedstyle[instance].psid; + + char* ps_name = NULL; + + + /* try first to load the name string with index `postScriptNameID' */ + if ( psid == 6 || + ( psid > 255 && psid < 32768 ) ) + (void)sfnt->get_name( face, (FT_UShort)psid, &ps_name ); + + if ( ps_name ) + { + result = ps_name; + p = result + ft_strlen( result ) + 1; + + goto check_length; + } + else + { + /* otherwise construct a name using `subfamilyNameID' */ + FT_UInt strid = mm_var->namedstyle[instance].strid; + + char* subfamily_name; + char* s; + + + (void)sfnt->get_name( face, (FT_UShort)strid, &subfamily_name ); + + if ( !subfamily_name ) + { + FT_TRACE1(( "sfnt_get_var_ps_name:" + " can't construct named instance PS name;\n" + " " + " trying to construct normal instance PS name\n" )); + goto construct_instance_name; } - p = (FT_Char*)stream->cursor; + /* after the prefix we have character `-' followed by the */ + /* subfamily name (using only characters a-z, A-Z, and 0-9) */ + if ( FT_ALLOC( result, face->var_postscript_prefix_len + + 1 + ft_strlen( subfamily_name ) + 1 ) ) + return NULL; + + ft_strcpy( result, face->var_postscript_prefix ); + + p = result + face->var_postscript_prefix_len; + *p++ = '-'; - for ( ; len > 0; len--, p += 2 ) + s = subfamily_name; + while ( *s ) { - if ( p[0] == 0 && p[1] >= 32 ) - *r++ = p[1]; + if ( ft_isalnum( *s ) ) + *p++ = *s; + s++; } - *r = '\0'; + *p++ = '\0'; + + FT_FREE( subfamily_name ); + } + } + else + { + FT_Var_Axis* axis; + + + construct_instance_name: + axis = mm_var->axis; - FT_FRAME_EXIT(); + if ( FT_ALLOC( result, + face->var_postscript_prefix_len + + num_coords * MAX_VALUE_DESCRIPTOR_LEN + 1 ) ) + return NULL; + + p = result; + + ft_strcpy( p, face->var_postscript_prefix ); + p += face->var_postscript_prefix_len; + + for ( i = 0; i < num_coords; i++, coords++, axis++ ) + { + char t; + + + /* omit axis value descriptor if it is identical */ + /* to the default axis value */ + if ( *coords == axis->def ) + continue; + + *p++ = '_'; + p = fixed2float( *coords, p ); + + t = (char)( axis->tag >> 24 ); + if ( t != ' ' && ft_isalnum( t ) ) + *p++ = t; + t = (char)( axis->tag >> 16 ); + if ( t != ' ' && ft_isalnum( t ) ) + *p++ = t; + t = (char)( axis->tag >> 8 ); + if ( t != ' ' && ft_isalnum( t ) ) + *p++ = t; + t = (char)axis->tag; + if ( t != ' ' && ft_isalnum( t ) ) + *p++ = t; } - goto Exit; } - if ( found_apple != -1 ) + check_length: + if ( p - result > MAX_PS_NAME_LEN ) { - FT_Memory memory = face->root.memory; - TT_NameEntryRec* name = face->name_table.names + found_apple; - FT_UInt len = name->stringLength; - FT_Error error = FT_Err_Ok; + /* the PS name is too long; replace the part after the prefix with */ + /* a checksum; we use MurmurHash 3 with a hash length of 128 bit */ - FT_UNUSED( error ); + FT_UInt32 seed = 123456789; + FT_UInt32 hash[4]; + FT_UInt32* h; - if ( !FT_ALLOC( result, len + 1 ) ) + + murmur_hash_3_128( result, p - result, seed, hash ); + + p = result + face->var_postscript_prefix_len; + *p++ = '-'; + + /* we convert the hash value to hex digits from back to front */ + p += 32 + 3; + h = hash + 3; + + *p-- = '\0'; + *p-- = '.'; + *p-- = '.'; + *p-- = '.'; + + for ( i = 0; i < 4; i++, h-- ) { - FT_Stream stream = face->name_table.stream; + FT_UInt32 v = *h; - if ( FT_STREAM_SEEK( name->stringOffset ) || - FT_STREAM_READ( result, len ) ) + for ( j = 0; j < 8; j++ ) { - name->stringOffset = 0; - name->stringLength = 0; - FT_FREE( name->string ); - FT_FREE( result ); - goto Exit; + *p-- = hexdigits[v & 0xF]; + v >>= 4; } - ((char*)result)[len] = '\0'; } } - Exit: + return result; + } + +#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ + + + static const char* + sfnt_get_ps_name( TT_Face face ) + { + FT_Int found, win, apple; + const char* result = NULL; + + + if ( face->postscript_name ) + return face->postscript_name; + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( face->blend && + ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) || + FT_IS_VARIATION( FT_FACE( face ) ) ) ) + { + face->postscript_name = sfnt_get_var_ps_name( face ); + return face->postscript_name; + } +#endif + + /* scan the name table to see whether we have a Postscript name here, */ + /* either in Macintosh or Windows platform encodings */ + found = sfnt_get_name_id( face, TT_NAME_ID_PS_NAME, &win, &apple ); + if ( !found ) + return NULL; + + /* prefer Windows entries over Apple */ + if ( win != -1 ) + result = get_win_string( face->root.memory, + face->name_table.stream, + face->name_table.names + win, + sfnt_is_postscript, + 1 ); + else + result = get_apple_string( face->root.memory, + face->name_table.stream, + face->name_table.names + apple, + sfnt_is_postscript, + 1 ); + face->postscript_name = result; + return result; } @@ -528,7 +1262,8 @@ tt_face_get_metrics, /* TT_Get_Metrics_Func get_metrics */ - tt_face_get_name /* TT_Get_Name_Func get_name */ + tt_face_get_name, /* TT_Get_Name_Func get_name */ + sfnt_get_name_id /* TT_Get_Name_ID_Func get_name_id */ ) diff --git a/modules/freetype2/src/sfnt/sfdriver.h b/modules/freetype2/src/sfnt/sfdriver.h index 2694488e2..81c22d288 100644 --- a/modules/freetype2/src/sfnt/sfdriver.h +++ b/modules/freetype2/src/sfnt/sfdriver.h @@ -4,7 +4,7 @@ /* */ /* High-level SFNT driver interface (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/sfnt/sferrors.h b/modules/freetype2/src/sfnt/sferrors.h index c2f9fdfea..74003d4b3 100644 --- a/modules/freetype2/src/sfnt/sferrors.h +++ b/modules/freetype2/src/sfnt/sferrors.h @@ -4,7 +4,7 @@ /* */ /* SFNT error codes (specification only). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/sfnt/sfnt.c b/modules/freetype2/src/sfnt/sfnt.c index 952d6d425..8b9a6b345 100644 --- a/modules/freetype2/src/sfnt/sfnt.c +++ b/modules/freetype2/src/sfnt/sfnt.c @@ -4,7 +4,7 @@ /* */ /* Single object library component. */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,27 +17,19 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT - #include <ft2build.h> + +#include "pngshim.c" +#include "sfdriver.c" #include "sfntpic.c" -#include "ttload.c" -#include "ttmtx.c" +#include "sfobjs.c" +#include "ttbdf.c" #include "ttcmap.c" #include "ttkern.c" -#include "sfobjs.c" -#include "sfdriver.c" - -#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS -#include "pngshim.c" -#include "ttsbit.c" -#endif - -#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES +#include "ttload.c" +#include "ttmtx.c" #include "ttpost.c" -#endif +#include "ttsbit.c" -#ifdef TT_CONFIG_OPTION_BDF -#include "ttbdf.c" -#endif /* END */ diff --git a/modules/freetype2/src/sfnt/sfntpic.c b/modules/freetype2/src/sfnt/sfntpic.c index 1f596c093..db2d816ce 100644 --- a/modules/freetype2/src/sfnt/sfntpic.c +++ b/modules/freetype2/src/sfnt/sfntpic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for sfnt module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2018 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/sfnt/sfntpic.h b/modules/freetype2/src/sfnt/sfntpic.h index 5ce96d393..8f43122d8 100644 --- a/modules/freetype2/src/sfnt/sfntpic.h +++ b/modules/freetype2/src/sfnt/sfntpic.h @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for sfnt module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2018 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/sfnt/sfobjs.c b/modules/freetype2/src/sfnt/sfobjs.c index 818009ef5..6ba8509f5 100644 --- a/modules/freetype2/src/sfnt/sfobjs.c +++ b/modules/freetype2/src/sfnt/sfobjs.c @@ -4,7 +4,7 @@ /* */ /* SFNT object management (base). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -54,8 +54,8 @@ /* convert a UTF-16 name entry to ASCII */ static FT_String* - tt_name_entry_ascii_from_utf16( TT_NameEntry entry, - FT_Memory memory ) + tt_name_ascii_from_utf16( TT_Name entry, + FT_Memory memory ) { FT_String* string = NULL; FT_UInt len, code, n; @@ -89,8 +89,8 @@ /* convert an Apple Roman or symbol name entry to ASCII */ static FT_String* - tt_name_entry_ascii_from_other( TT_NameEntry entry, - FT_Memory memory ) + tt_name_ascii_from_other( TT_Name entry, + FT_Memory memory ) { FT_String* string = NULL; FT_UInt len, code, n; @@ -122,8 +122,8 @@ } - typedef FT_String* (*TT_NameEntry_ConvertFunc)( TT_NameEntry entry, - FT_Memory memory ); + typedef FT_String* (*TT_Name_ConvertFunc)( TT_Name entry, + FT_Memory memory ); /* documentation is in sfnt.h */ @@ -133,20 +133,21 @@ FT_UShort nameid, FT_String** name ) { - FT_Memory memory = face->root.memory; - FT_Error error = FT_Err_Ok; - FT_String* result = NULL; - FT_UShort n; - TT_NameEntryRec* rec; - FT_Int found_apple = -1; - FT_Int found_apple_roman = -1; - FT_Int found_apple_english = -1; - FT_Int found_win = -1; - FT_Int found_unicode = -1; + FT_Memory memory = face->root.memory; + FT_Error error = FT_Err_Ok; + FT_String* result = NULL; + FT_UShort n; + TT_Name rec; - FT_Bool is_english = 0; + FT_Int found_apple = -1; + FT_Int found_apple_roman = -1; + FT_Int found_apple_english = -1; + FT_Int found_win = -1; + FT_Int found_unicode = -1; - TT_NameEntry_ConvertFunc convert; + FT_Bool is_english = 0; + + TT_Name_ConvertFunc convert; FT_ASSERT( name ); @@ -231,7 +232,7 @@ /* all Unicode strings are encoded using UTF-16BE */ case TT_MS_ID_UNICODE_CS: case TT_MS_ID_SYMBOL_CS: - convert = tt_name_entry_ascii_from_utf16; + convert = tt_name_ascii_from_utf16; break; case TT_MS_ID_UCS_4: @@ -240,7 +241,7 @@ /* MsGothic font shipped with Windows Vista shows that this really */ /* means UTF-16 encoded names (UCS-4 values are only used within */ /* charmaps). */ - convert = tt_name_entry_ascii_from_utf16; + convert = tt_name_ascii_from_utf16; break; default: @@ -250,12 +251,12 @@ else if ( found_apple >= 0 ) { rec = face->name_table.names + found_apple; - convert = tt_name_entry_ascii_from_other; + convert = tt_name_ascii_from_other; } else if ( found_unicode >= 0 ) { rec = face->name_table.names + found_unicode; - convert = tt_name_entry_ascii_from_utf16; + convert = tt_name_ascii_from_utf16; } if ( rec && convert ) @@ -310,7 +311,7 @@ { TT_PLATFORM_MICROSOFT, TT_MS_ID_UCS_4, FT_ENCODING_UNICODE }, { TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, FT_ENCODING_UNICODE }, { TT_PLATFORM_MICROSOFT, TT_MS_ID_SJIS, FT_ENCODING_SJIS }, - { TT_PLATFORM_MICROSOFT, TT_MS_ID_GB2312, FT_ENCODING_GB2312 }, + { TT_PLATFORM_MICROSOFT, TT_MS_ID_PRC, FT_ENCODING_PRC }, { TT_PLATFORM_MICROSOFT, TT_MS_ID_BIG_5, FT_ENCODING_BIG5 }, { TT_PLATFORM_MICROSOFT, TT_MS_ID_WANSUNG, FT_ENCODING_WANSUNG }, { TT_PLATFORM_MICROSOFT, TT_MS_ID_JOHAB, FT_ENCODING_JOHAB } @@ -786,6 +787,8 @@ tag != TTAG_OTTO && tag != TTAG_true && tag != TTAG_typ1 && + tag != TTAG_0xA5kbd && + tag != TTAG_0xA5lst && tag != 0x00020000UL ) { FT_TRACE2(( " not a font using the SFNT container format\n" )); @@ -893,7 +896,17 @@ 0 ); } - FT_FACE_FIND_GLOBAL_SERVICE( face, face->var, METRICS_VARIATIONS ); + if ( !face->var ) + { + /* we want the metrics variations interface */ + /* from the `truetype' module only */ + FT_Module tt_module = FT_Get_Module( library, "truetype" ); + + + face->var = ft_module_get_service( tt_module, + FT_SERVICE_ID_METRICS_VARIATIONS, + 0 ); + } #endif FT_TRACE2(( "SFNT driver\n" )); @@ -909,6 +922,10 @@ face_index = FT_ABS( face_instance_index ) & 0xFFFF; + /* value -(N+1) requests information on index N */ + if ( face_instance_index < 0 ) + face_index--; + if ( face_index >= face->ttc_header.count ) { if ( face_instance_index >= 0 ) @@ -927,6 +944,8 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT { + FT_Memory memory = face->root.memory; + FT_ULong fvar_len; FT_ULong version; @@ -939,8 +958,9 @@ FT_Int instance_index; + FT_Byte* default_values = NULL; + FT_Byte* instance_values = NULL; - face->is_default_instance = 1; instance_index = FT_ABS( face_instance_index ) >> 16; @@ -949,7 +969,7 @@ fvar_len < 20 || FT_READ_ULONG( version ) || FT_READ_USHORT( offset ) || - FT_STREAM_SKIP( 2 ) /* count_size_pairs */ || + FT_STREAM_SKIP( 2 ) /* reserved */ || FT_READ_USHORT( num_axes ) || FT_READ_USHORT( axis_size ) || FT_READ_USHORT( num_instances ) || @@ -965,18 +985,13 @@ /* check that the data is bound by the table length */ if ( version != 0x00010000UL || -#if 0 - /* fonts like `JamRegular.ttf' have an incorrect value for */ - /* `count_size_pairs'; since value 2 is hard-coded in `fvar' */ - /* version 1.0, we simply ignore it */ - count_size_pairs != 2 || -#endif axis_size != 20 || num_axes == 0 || /* `num_axes' limit implied by 16-bit `instance_size' */ num_axes > 0x3FFE || !( instance_size == 4 + 4 * num_axes || instance_size == 6 + 4 * num_axes ) || + /* `num_instances' limit implied by limited range of name IDs */ num_instances > 0x7EFF || offset + axis_size * num_axes + @@ -985,19 +1000,73 @@ else face->variation_support |= TT_FACE_FLAG_VAR_FVAR; - /* we don't support Multiple Master CFFs yet */ - if ( !face->goto_table( face, TTAG_CFF, stream, 0 ) ) - num_instances = 0; + /* + * As documented in the OpenType specification, an entry for the + * default instance may be omitted in the named instance table. In + * particular this means that even if there is no named instance + * table in the font we actually do have a named instance, namely the + * default instance. + * + * For consistency, we always want the default instance in our list + * of named instances. If it is missing, we try to synthesize it + * later on. Here, we have to adjust `num_instances' accordingly. + */ - /* we support at most 2^15 - 1 instances */ - if ( num_instances >= ( 1U << 15 ) - 1 ) + if ( ( face->variation_support & TT_FACE_FLAG_VAR_FVAR ) && + !( FT_ALLOC( default_values, num_axes * 4 ) || + FT_ALLOC( instance_values, num_axes * 4 ) ) ) { - if ( face_instance_index >= 0 ) - return FT_THROW( Invalid_Argument ); - else - num_instances = 0; + /* the current stream position is 16 bytes after the table start */ + FT_ULong array_start = FT_STREAM_POS() - 16 + offset; + FT_ULong default_value_offset, instance_offset; + + FT_Byte* p; + FT_UInt i; + + + default_value_offset = array_start + 8; + p = default_values; + + for ( i = 0; i < num_axes; i++ ) + { + (void)FT_STREAM_READ_AT( default_value_offset, p, 4 ); + + default_value_offset += axis_size; + p += 4; + } + + instance_offset = array_start + axis_size * num_axes + 4; + + for ( i = 0; i < num_instances; i++ ) + { + (void)FT_STREAM_READ_AT( instance_offset, + instance_values, + num_axes * 4 ); + + if ( !ft_memcmp( default_values, instance_values, num_axes * 4 ) ) + break; + + instance_offset += instance_size; + } + + if ( i == num_instances ) + { + /* no default instance in named instance table; */ + /* we thus have to synthesize it */ + num_instances++; + } } + FT_FREE( default_values ); + FT_FREE( instance_values ); + + /* we don't support Multiple Master CFFs yet; */ + /* note that `glyf' or `CFF2' have precedence */ + if ( face->goto_table( face, TTAG_glyf, stream, 0 ) && + face->goto_table( face, TTAG_CFF2, stream, 0 ) && + !face->goto_table( face, TTAG_CFF, stream, 0 ) ) + num_instances = 0; + /* instance indices in `face_instance_index' start with index 1, */ /* thus `>' and not `>=' */ if ( instance_index > num_instances ) @@ -1075,8 +1144,10 @@ FT_Bool has_outline; FT_Bool is_apple_sbit; FT_Bool is_apple_sbix; - FT_Bool ignore_preferred_family = FALSE; - FT_Bool ignore_preferred_subfamily = FALSE; + FT_Bool has_CBLC; + FT_Bool has_CBDT; + FT_Bool ignore_typographic_family = FALSE; + FT_Bool ignore_typographic_subfamily = FALSE; SFNT_Service sfnt = (SFNT_Service)face->sfnt; @@ -1091,10 +1162,10 @@ for ( i = 0; i < num_params; i++ ) { - if ( params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY ) - ignore_preferred_family = TRUE; - else if ( params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY ) - ignore_preferred_subfamily = TRUE; + if ( params[i].tag == FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY ) + ignore_typographic_family = TRUE; + else if ( params[i].tag == FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY ) + ignore_typographic_subfamily = TRUE; } } @@ -1155,7 +1226,17 @@ goto Exit; } - if ( face->header.Units_Per_EM == 0 ) + has_CBLC = !face->goto_table( face, TTAG_CBLC, stream, 0 ); + has_CBDT = !face->goto_table( face, TTAG_CBDT, stream, 0 ); + + /* Ignore outlines for CBLC/CBDT fonts. */ + if ( has_CBLC || has_CBDT ) + has_outline = FALSE; + + /* OpenType 1.8.2 introduced limits to this value; */ + /* however, they make sense for older SFNT fonts also */ + if ( face->header.Units_Per_EM < 16 || + face->header.Units_Per_EM > 16384 ) { error = FT_THROW( Invalid_Table ); @@ -1258,30 +1339,10 @@ /* embedded bitmap support */ if ( sfnt->load_eblc ) - { LOAD_( eblc ); - if ( error ) - { - /* a font which contains neither bitmaps nor outlines is */ - /* still valid (although rather useless in most cases); */ - /* however, you can find such stripped fonts in PDFs */ - if ( FT_ERR_EQ( error, Table_Missing ) ) - error = FT_Err_Ok; - else - goto Exit; - } - } + /* consider the pclt, kerning, and gasp tables as optional */ LOAD_( pclt ); - if ( error ) - { - if ( FT_ERR_NEQ( error, Table_Missing ) ) - goto Exit; - - face->pclt.Version = 0; - } - - /* consider the kerning and gasp tables as optional */ LOAD_( gasp ); LOAD_( kern ); @@ -1297,27 +1358,27 @@ face->root.style_name = NULL; if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 256 ) { - if ( !ignore_preferred_family ) - GET_NAME( PREFERRED_FAMILY, &face->root.family_name ); + if ( !ignore_typographic_family ) + GET_NAME( TYPOGRAPHIC_FAMILY, &face->root.family_name ); if ( !face->root.family_name ) GET_NAME( FONT_FAMILY, &face->root.family_name ); - if ( !ignore_preferred_subfamily ) - GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name ); + if ( !ignore_typographic_subfamily ) + GET_NAME( TYPOGRAPHIC_SUBFAMILY, &face->root.style_name ); if ( !face->root.style_name ) GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); } else { GET_NAME( WWS_FAMILY, &face->root.family_name ); - if ( !face->root.family_name && !ignore_preferred_family ) - GET_NAME( PREFERRED_FAMILY, &face->root.family_name ); + if ( !face->root.family_name && !ignore_typographic_family ) + GET_NAME( TYPOGRAPHIC_FAMILY, &face->root.family_name ); if ( !face->root.family_name ) GET_NAME( FONT_FAMILY, &face->root.family_name ); GET_NAME( WWS_SUBFAMILY, &face->root.style_name ); - if ( !face->root.style_name && !ignore_preferred_subfamily ) - GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name ); + if ( !face->root.style_name && !ignore_typographic_subfamily ) + GET_NAME( TYPOGRAPHIC_SUBFAMILY, &face->root.style_name ); if ( !face->root.style_name ) GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); } @@ -1415,7 +1476,8 @@ /* Polish the charmaps. */ /* */ /* Try to set the charmap encoding according to the platform & */ - /* encoding ID of each charmap. */ + /* encoding ID of each charmap. Emulate Unicode charmap if one */ + /* is missing. */ /* */ tt_face_build_cmaps( face ); /* ignore errors */ @@ -1423,7 +1485,10 @@ /* set the encoding fields */ { - FT_Int m; + FT_Int m; +#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES + FT_Bool has_unicode = FALSE; +#endif for ( m = 0; m < root->num_charmaps; m++ ) @@ -1434,14 +1499,34 @@ charmap->encoding = sfnt_find_encoding( charmap->platform_id, charmap->encoding_id ); -#if 0 - if ( !root->charmap && - charmap->encoding == FT_ENCODING_UNICODE ) - { - /* set 'root->charmap' to the first Unicode encoding we find */ - root->charmap = charmap; - } -#endif +#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES + + if ( charmap->encoding == FT_ENCODING_UNICODE || + charmap->encoding == FT_ENCODING_MS_SYMBOL ) /* PUA */ + has_unicode = TRUE; + } + + /* synthesize Unicode charmap if one is missing */ + if ( !has_unicode ) + { + FT_CharMapRec cmaprec; + + + cmaprec.face = root; + cmaprec.platform_id = TT_PLATFORM_MICROSOFT; + cmaprec.encoding_id = TT_MS_ID_UNICODE_CS; + cmaprec.encoding = FT_ENCODING_UNICODE; + + + error = FT_CMap_New( (FT_CMap_Class)&tt_cmap_unicode_class_rec, + NULL, &cmaprec, NULL ); + if ( error && + FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) ) + goto Exit; + error = FT_Err_Ok; + +#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ + } } @@ -1608,9 +1693,9 @@ (FT_Short)( face->vertical_info ? face->vertical.advance_Height_Max : root->height ); - /* See http://www.microsoft.com/OpenType/OTSpec/post.htm -- */ - /* Adjust underline position from top edge to centre of */ - /* stroke to convert TrueType meaning to FreeType meaning. */ + /* See https://www.microsoft.com/typography/otspec/post.htm -- */ + /* Adjust underline position from top edge to centre of */ + /* stroke to convert TrueType meaning to FreeType meaning. */ root->underline_position = face->postscript.underlinePosition - face->postscript.underlineThickness / 2; root->underline_thickness = face->postscript.underlineThickness; @@ -1707,7 +1792,10 @@ FT_FREE( face->sbit_strike_map ); face->root.num_fixed_sizes = 0; +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT FT_FREE( face->postscript_name ); + FT_FREE( face->var_postscript_prefix ); +#endif face->sfnt = NULL; } diff --git a/modules/freetype2/src/sfnt/sfobjs.h b/modules/freetype2/src/sfnt/sfobjs.h index 60b5698ed..1b8d1be5b 100644 --- a/modules/freetype2/src/sfnt/sfobjs.h +++ b/modules/freetype2/src/sfnt/sfobjs.h @@ -4,7 +4,7 @@ /* */ /* SFNT object management (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/sfnt/ttbdf.c b/modules/freetype2/src/sfnt/ttbdf.c index 62acf090c..534201f22 100644 --- a/modules/freetype2/src/sfnt/ttbdf.c +++ b/modules/freetype2/src/sfnt/ttbdf.c @@ -4,7 +4,7 @@ /* */ /* TrueType and OpenType embedded BDF properties (body). */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -246,7 +246,12 @@ return error; } -#endif /* TT_CONFIG_OPTION_BDF */ +#else /* !TT_CONFIG_OPTION_BDF */ + + /* ANSI C doesn't like empty source files */ + typedef int _tt_bdf_dummy; + +#endif /* !TT_CONFIG_OPTION_BDF */ /* END */ diff --git a/modules/freetype2/src/sfnt/ttbdf.h b/modules/freetype2/src/sfnt/ttbdf.h index ae521c60b..809a66300 100644 --- a/modules/freetype2/src/sfnt/ttbdf.h +++ b/modules/freetype2/src/sfnt/ttbdf.h @@ -4,7 +4,7 @@ /* */ /* TrueType and OpenType embedded BDF properties (specification). */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -28,6 +28,8 @@ FT_BEGIN_HEADER +#ifdef TT_CONFIG_OPTION_BDF + FT_LOCAL( void ) tt_face_free_bdf_props( TT_Face face ); @@ -37,6 +39,8 @@ FT_BEGIN_HEADER const char* property_name, BDF_PropertyRec *aprop ); +#endif /* TT_CONFIG_OPTION_BDF */ + FT_END_HEADER diff --git a/modules/freetype2/src/sfnt/ttcmap.c b/modules/freetype2/src/sfnt/ttcmap.c index e48c15c65..996e66485 100644 --- a/modules/freetype2/src/sfnt/ttcmap.c +++ b/modules/freetype2/src/sfnt/ttcmap.c @@ -4,7 +4,7 @@ /* */ /* TrueType character mapping table (cmap) support (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -23,8 +23,10 @@ #include FT_INTERNAL_VALIDATE_H #include FT_INTERNAL_STREAM_H +#include FT_SERVICE_POSTSCRIPT_CMAPS_H #include "ttload.h" #include "ttcmap.h" +#include "ttpost.h" #include "sfntpic.h" @@ -220,10 +222,10 @@ /***** The following charmap lookup and iteration functions all *****/ /***** assume that the value `charcode' fulfills the following. *****/ /***** *****/ - /***** - For one byte characters, `charcode' is simply the *****/ + /***** - For one-byte characters, `charcode' is simply the *****/ /***** character code. *****/ /***** *****/ - /***** - For two byte characters, `charcode' is the 2-byte *****/ + /***** - For two-byte characters, `charcode' is the 2-byte *****/ /***** character code in big endian format. More precisely: *****/ /***** *****/ /***** (charcode >> 8) is the first byte value *****/ @@ -250,11 +252,11 @@ /* subs 518 SUBHEAD[NSUBS] sub-headers array */ /* glyph_ids 518+NSUB*8 USHORT[] glyph ID array */ /* */ - /* The `keys' table is used to map charcode high-bytes to sub-headers. */ + /* The `keys' table is used to map charcode high bytes to sub-headers. */ /* The value of `NSUBS' is the number of sub-headers defined in the */ /* table and is computed by finding the maximum of the `keys' table. */ /* */ - /* Note that for any n, `keys[n]' is a byte offset within the `subs' */ + /* Note that for any `n', `keys[n]' is a byte offset within the `subs' */ /* table, i.e., it is the corresponding sub-header index multiplied */ /* by 8. */ /* */ @@ -267,8 +269,8 @@ /* delta 4 SHORT see below */ /* offset 6 USHORT see below */ /* */ - /* A sub-header defines, for each high-byte, the range of valid */ - /* low-bytes within the charmap. Note that the range defined by `first' */ + /* A sub-header defines, for each high byte, the range of valid */ + /* low bytes within the charmap. Note that the range defined by `first' */ /* and `count' must be completely included in the interval [0..255] */ /* according to the specification. */ /* */ @@ -358,7 +360,7 @@ /* check range within 0..255 */ if ( valid->level >= FT_VALIDATE_PARANOID ) { - if ( first_code >= 256 || first_code + code_count > 256 ) + if ( first_code >= 256 || code_count > 256 - first_code ) FT_INVALID_DATA; } @@ -410,7 +412,7 @@ { FT_UInt char_lo = (FT_UInt)( char_code & 0xFF ); FT_UInt char_hi = (FT_UInt)( char_code >> 8 ); - FT_Byte* p = table + 6; /* keys table */ + FT_Byte* p = table + 6; /* keys table */ FT_Byte* subs = table + 518; /* subheaders table */ FT_Byte* sub; @@ -423,8 +425,8 @@ sub = subs; /* jump to first sub-header */ /* check that the sub-header for this byte is 0, which */ - /* indicates that it is really a valid one-byte value */ - /* Otherwise, return 0 */ + /* indicates that it is really a valid one-byte value; */ + /* otherwise, return 0 */ /* */ p += char_lo * 2; if ( TT_PEEK_USHORT( p ) != 0 ) @@ -443,6 +445,7 @@ if ( sub == subs ) goto Exit; } + result = sub; } @@ -515,8 +518,19 @@ FT_UInt pos, idx; + if ( char_lo >= start + count && charcode <= 0xFF ) + { + /* this happens only for a malformed cmap */ + charcode = 0x100; + continue; + } + if ( offset == 0 ) + { + if ( charcode == 0x100 ) + goto Exit; /* this happens only for a malformed cmap */ goto Next_SubHeader; + } if ( char_lo < start ) { @@ -543,11 +557,20 @@ } } } + + /* if unsuccessful, avoid `charcode' leaving */ + /* the current 256-character block */ + if ( count ) + charcode--; } - /* jump to next sub-header, i.e. higher byte value */ + /* If `charcode' is <= 0xFF, retry with `charcode + 1'. */ + /* Otherwise jump to the next 256-character block and retry. */ Next_SubHeader: - charcode = FT_PAD_FLOOR( charcode, 256 ) + 256; + if ( charcode <= 0xFF ) + charcode++; + else + charcode = FT_PAD_FLOOR( charcode, 0x100 ) + 0x100; } Exit: @@ -3622,6 +3645,110 @@ #endif /* TT_CONFIG_CMAP_FORMAT_14 */ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** SYNTHETIC UNICODE *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /* This charmap is generated using postscript glyph names. */ + +#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES + + FT_CALLBACK_DEF( const char * ) + tt_get_glyph_name( TT_Face face, + FT_UInt idx ) + { + FT_String* PSname; + + + tt_face_get_ps_name( face, idx, &PSname ); + + return PSname; + } + + + FT_CALLBACK_DEF( FT_Error ) + tt_cmap_unicode_init( PS_Unicodes unicodes, + FT_Pointer pointer ) + { + TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); + FT_Memory memory = FT_FACE_MEMORY( face ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + + FT_UNUSED( pointer ); + + + return psnames->unicodes_init( memory, + unicodes, + face->root.num_glyphs, + (PS_GetGlyphNameFunc)&tt_get_glyph_name, + (PS_FreeGlyphNameFunc)NULL, + (FT_Pointer)face ); + } + + + FT_CALLBACK_DEF( void ) + tt_cmap_unicode_done( PS_Unicodes unicodes ) + { + FT_Face face = FT_CMAP_FACE( unicodes ); + FT_Memory memory = FT_FACE_MEMORY( face ); + + + FT_FREE( unicodes->maps ); + unicodes->num_maps = 0; + } + + + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap_unicode_char_index( PS_Unicodes unicodes, + FT_UInt32 char_code ) + { + TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + + + return psnames->unicodes_char_index( unicodes, char_code ); + } + + + FT_CALLBACK_DEF( FT_UInt32 ) + tt_cmap_unicode_char_next( PS_Unicodes unicodes, + FT_UInt32 *pchar_code ) + { + TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + + + return psnames->unicodes_char_next( unicodes, pchar_code ); + } + + + FT_DEFINE_TT_CMAP( + tt_cmap_unicode_class_rec, + + sizeof ( PS_UnicodesRec ), + + (FT_CMap_InitFunc) tt_cmap_unicode_init, /* init */ + (FT_CMap_DoneFunc) tt_cmap_unicode_done, /* done */ + (FT_CMap_CharIndexFunc)tt_cmap_unicode_char_index, /* char_index */ + (FT_CMap_CharNextFunc) tt_cmap_unicode_char_next, /* char_next */ + + (FT_CMap_CharVarIndexFunc) NULL, /* char_var_index */ + (FT_CMap_CharVarIsDefaultFunc)NULL, /* char_var_default */ + (FT_CMap_VariantListFunc) NULL, /* variant_list */ + (FT_CMap_CharVariantListFunc) NULL, /* charvariant_list */ + (FT_CMap_VariantCharListFunc) NULL, /* variantchar_list */ + + ~0U, + (TT_CMap_ValidateFunc)NULL, /* validate */ + (TT_CMap_Info_GetFunc)NULL /* get_cmap_info */ + ) + +#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ + #ifndef FT_CONFIG_OPTION_PIC static const TT_CMap_Class tt_cmap_classes[] = @@ -3801,8 +3928,10 @@ FT_CMap cmap = (FT_CMap)charmap; TT_CMap_Class clazz = (TT_CMap_Class)cmap->clazz; - - return clazz->get_cmap_info( charmap, cmap_info ); + if ( clazz->get_cmap_info ) + return clazz->get_cmap_info( charmap, cmap_info ); + else + return FT_THROW( Invalid_CharMap_Format ); } diff --git a/modules/freetype2/src/sfnt/ttcmap.h b/modules/freetype2/src/sfnt/ttcmap.h index 2273cbd96..d264d99d2 100644 --- a/modules/freetype2/src/sfnt/ttcmap.h +++ b/modules/freetype2/src/sfnt/ttcmap.h @@ -4,7 +4,7 @@ /* */ /* TrueType character mapping table (cmap) support (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -141,6 +141,8 @@ FT_BEGIN_HEADER #define TT_VALID_GLYPH_COUNT( x ) TT_VALIDATOR( x )->num_glyphs + FT_CALLBACK_TABLE const TT_CMap_ClassRec tt_cmap_unicode_class_rec; + FT_LOCAL( FT_Error ) tt_face_build_cmaps( TT_Face face ); diff --git a/modules/freetype2/src/sfnt/ttcmapc.h b/modules/freetype2/src/sfnt/ttcmapc.h index 7c732fbd3..4980e9dd3 100644 --- a/modules/freetype2/src/sfnt/ttcmapc.h +++ b/modules/freetype2/src/sfnt/ttcmapc.h @@ -4,7 +4,7 @@ /* */ /* TT CMAP classes definitions (specification only). */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2018 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/sfnt/ttkern.c b/modules/freetype2/src/sfnt/ttkern.c index 6f9fa522d..68f15a201 100644 --- a/modules/freetype2/src/sfnt/ttkern.c +++ b/modules/freetype2/src/sfnt/ttkern.c @@ -5,7 +5,7 @@ /* Load the basic TrueType kerning table. This doesn't handle */ /* kerning data within the GPOS table at the moment. */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -85,7 +85,7 @@ for ( nn = 0; nn < num_tables; nn++ ) { - FT_UInt num_pairs, length, coverage; + FT_UInt num_pairs, length, coverage, format; FT_Byte* p_next; FT_UInt32 mask = (FT_UInt32)1UL << nn; @@ -107,9 +107,15 @@ if ( p_next > p_limit ) /* handle broken table */ p_next = p_limit; + format = coverage >> 8; + + /* we currently only support format 0 kerning tables */ + if ( format != 0 ) + goto NextTable; + /* only use horizontal kerning tables */ - if ( ( coverage & ~8U ) != 0x0001 || - p + 8 > p_limit ) + if ( ( coverage & 3U ) != 0x0001 || + p + 8 > p_next ) goto NextTable; num_pairs = FT_NEXT_USHORT( p ); @@ -214,8 +220,7 @@ if ( ( face->kern_avail_bits & mask ) == 0 ) goto NextTable; - if ( p + 8 > next ) - goto NextTable; + FT_ASSERT( p + 8 <= next ); /* tested in tt_face_load_kern */ num_pairs = FT_NEXT_USHORT( p ); p += 6; diff --git a/modules/freetype2/src/sfnt/ttkern.h b/modules/freetype2/src/sfnt/ttkern.h index 85dd5c31a..4e45d0964 100644 --- a/modules/freetype2/src/sfnt/ttkern.h +++ b/modules/freetype2/src/sfnt/ttkern.h @@ -5,7 +5,7 @@ /* Load the basic TrueType kerning table. This doesn't handle */ /* kerning data within the GPOS table at the moment. */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/sfnt/ttload.c b/modules/freetype2/src/sfnt/ttload.c index d615bba04..a86a546c3 100644 --- a/modules/freetype2/src/sfnt/ttload.c +++ b/modules/freetype2/src/sfnt/ttload.c @@ -5,7 +5,7 @@ /* Load the basic TrueType tables, i.e., tables that can be either in */ /* TTF or OTF fonts (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -338,7 +338,7 @@ SFNT_HeaderRec sfnt; FT_Error error; FT_Memory memory = stream->memory; - FT_UShort nn, valid_entries; + FT_UShort nn, valid_entries = 0; static const FT_Frame_Field offset_table_fields[] = { @@ -808,7 +808,6 @@ FT_Memory memory = stream->memory; FT_ULong table_pos, table_len; FT_ULong storage_start, storage_limit; - FT_UInt count; TT_NameTable table; static const FT_Frame_Field name_table_fields[] = @@ -826,7 +825,7 @@ static const FT_Frame_Field name_record_fields[] = { #undef FT_STRUCTURE -#define FT_STRUCTURE TT_NameEntryRec +#define FT_STRUCTURE TT_NameRec /* no FT_FRAME_START */ FT_FRAME_USHORT( platformID ), @@ -838,6 +837,17 @@ FT_FRAME_END }; + static const FT_Frame_Field langTag_record_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE TT_LangTagRec + + /* no FT_FRAME_START */ + FT_FRAME_USHORT( stringLength ), + FT_FRAME_USHORT( stringOffset ), + FT_FRAME_END + }; + table = &face->name_table; table->stream = stream; @@ -848,18 +858,17 @@ table_pos = FT_STREAM_POS(); - if ( FT_STREAM_READ_FIELDS( name_table_fields, table ) ) goto Exit; - /* Some popular Asian fonts have an invalid `storageOffset' value */ - /* (it should be at least "6 + 12*num_names"). However, the string */ - /* offsets, computed as "storageOffset + entry->stringOffset", are */ - /* valid pointers within the name table... */ - /* */ - /* We thus can't check `storageOffset' right now. */ - /* */ - storage_start = table_pos + 6 + 12*table->numNameRecords; + /* Some popular Asian fonts have an invalid `storageOffset' value (it */ + /* should be at least `6 + 12*numNameRecords'). However, the string */ + /* offsets, computed as `storageOffset + entry->stringOffset', are */ + /* valid pointers within the name table... */ + /* */ + /* We thus can't check `storageOffset' right now. */ + /* */ + storage_start = table_pos + 6 + 12 * table->numNameRecords; storage_limit = table_pos + table_len; if ( storage_start > storage_limit ) @@ -869,18 +878,56 @@ goto Exit; } - /* Allocate the array of name records. */ - count = table->numNameRecords; - table->numNameRecords = 0; + /* `name' format 1 contains additional language tag records, */ + /* which we load first */ + if ( table->format == 1 ) + { + if ( FT_STREAM_SEEK( storage_start ) || + FT_READ_USHORT( table->numLangTagRecords ) ) + goto Exit; + + storage_start += 2 + 4 * table->numLangTagRecords; + + /* allocate language tag records array */ + if ( FT_NEW_ARRAY( table->langTags, table->numLangTagRecords ) || + FT_FRAME_ENTER( table->numLangTagRecords * 4 ) ) + goto Exit; - if ( FT_NEW_ARRAY( table->names, count ) || - FT_FRAME_ENTER( count * 12 ) ) + /* load language tags */ + { + TT_LangTag entry = table->langTags; + TT_LangTag limit = entry + table->numLangTagRecords; + + + for ( ; entry < limit; entry++ ) + { + (void)FT_STREAM_READ_FIELDS( langTag_record_fields, entry ); + + /* check that the langTag string is within the table */ + entry->stringOffset += table_pos + table->storageOffset; + if ( entry->stringOffset < storage_start || + entry->stringOffset + entry->stringLength > storage_limit ) + { + /* invalid entry; ignore it */ + entry->stringLength = 0; + } + } + } + + FT_FRAME_EXIT(); + + (void)FT_STREAM_SEEK( table_pos + 6 ); + } + + /* allocate name records array */ + if ( FT_NEW_ARRAY( table->names, table->numNameRecords ) || + FT_FRAME_ENTER( table->numNameRecords * 12 ) ) goto Exit; - /* Load the name records and determine how much storage is needed */ - /* to hold the strings themselves. */ + /* load name records */ { - TT_NameEntryRec* entry = table->names; + TT_Name entry = table->names; + FT_UInt count = table->numNameRecords; for ( ; count > 0; count-- ) @@ -897,22 +944,37 @@ if ( entry->stringOffset < storage_start || entry->stringOffset + entry->stringLength > storage_limit ) { - /* invalid entry - ignore it */ - entry->stringOffset = 0; - entry->stringLength = 0; + /* invalid entry; ignore it */ continue; } + /* assure that we have a valid language tag ID, and */ + /* that the corresponding langTag entry is valid, too */ + if ( table->format == 1 && entry->languageID >= 0x8000U ) + { + if ( entry->languageID - 0x8000U >= table->numLangTagRecords || + !table->langTags[entry->languageID - 0x8000U].stringLength ) + { + /* invalid entry; ignore it */ + continue; + } + } + entry++; } - table->numNameRecords = (FT_UInt)( entry - table->names ); + /* reduce array size to the actually used elements */ + count = (FT_UInt)( entry - table->names ); + (void)FT_RENEW_ARRAY( table->names, + table->numNameRecords, + count ); + table->numNameRecords = count; } FT_FRAME_EXIT(); /* everything went well, update face->num_names */ - face->num_names = (FT_UShort) table->numNameRecords; + face->num_names = (FT_UShort)table->numNameRecords; Exit: return error; @@ -922,7 +984,7 @@ /*************************************************************************/ /* */ /* <Function> */ - /* tt_face_free_names */ + /* tt_face_free_name */ /* */ /* <Description> */ /* Frees the name records. */ @@ -935,25 +997,36 @@ { FT_Memory memory = face->root.driver->root.memory; TT_NameTable table = &face->name_table; - TT_NameEntry entry = table->names; - FT_UInt count = table->numNameRecords; if ( table->names ) { - for ( ; count > 0; count--, entry++ ) - { + TT_Name entry = table->names; + TT_Name limit = entry + table->numNameRecords; + + + for ( ; entry < limit; entry++ ) FT_FREE( entry->string ); - entry->stringLength = 0; - } - /* free strings table */ FT_FREE( table->names ); } - table->numNameRecords = 0; - table->format = 0; - table->storageOffset = 0; + if ( table->langTags ) + { + TT_LangTag entry = table->langTags; + TT_LangTag limit = entry + table->numLangTagRecords; + + + for ( ; entry < limit; entry++ ) + FT_FREE( entry->string ); + + FT_FREE( table->langTags ); + } + + table->numNameRecords = 0; + table->numLangTagRecords = 0; + table->format = 0; + table->storageOffset = 0; } diff --git a/modules/freetype2/src/sfnt/ttload.h b/modules/freetype2/src/sfnt/ttload.h index bec42b94b..f94be8b7b 100644 --- a/modules/freetype2/src/sfnt/ttload.h +++ b/modules/freetype2/src/sfnt/ttload.h @@ -5,7 +5,7 @@ /* Load the basic TrueType tables, i.e., tables that can be either in */ /* TTF or OTF fonts (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/sfnt/ttmtx.c b/modules/freetype2/src/sfnt/ttmtx.c index 8c5508e24..6ddda95b5 100644 --- a/modules/freetype2/src/sfnt/ttmtx.c +++ b/modules/freetype2/src/sfnt/ttmtx.c @@ -4,7 +4,7 @@ /* */ /* Load the metrics tables common to TTF and OTF fonts (body). */ /* */ -/* Copyright 2006-2016 by */ +/* Copyright 2006-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -30,6 +30,14 @@ #include "sferrors.h" + /* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should */ + /* be identical except for the names of their fields, */ + /* which are different. */ + /* */ + /* This ensures that `tt_face_load_hmtx' is able to read */ + /* both the horizontal and vertical headers. */ + + /*************************************************************************/ /* */ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ diff --git a/modules/freetype2/src/sfnt/ttmtx.h b/modules/freetype2/src/sfnt/ttmtx.h index 78395def3..ab00acd79 100644 --- a/modules/freetype2/src/sfnt/ttmtx.h +++ b/modules/freetype2/src/sfnt/ttmtx.h @@ -4,7 +4,7 @@ /* */ /* Load the metrics tables common to TTF and OTF fonts (specification). */ /* */ -/* Copyright 2006-2016 by */ +/* Copyright 2006-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/sfnt/ttpost.c b/modules/freetype2/src/sfnt/ttpost.c index ef81e63a3..6de99ef97 100644 --- a/modules/freetype2/src/sfnt/ttpost.c +++ b/modules/freetype2/src/sfnt/ttpost.c @@ -5,7 +5,7 @@ /* PostScript name table processing for TrueType and OpenType fonts */ /* (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -29,6 +29,10 @@ #include FT_INTERNAL_DEBUG_H #include FT_INTERNAL_STREAM_H #include FT_TRUETYPE_TAGS_H + + +#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES + #include "ttpost.h" #include "sferrors.h" @@ -321,7 +325,6 @@ FT_UNUSED( post_limit ); - /* UNDOCUMENTED! This value appears only in the Apple TT specs. */ if ( FT_READ_USHORT( num_glyphs ) ) goto Exit; @@ -404,7 +407,7 @@ /* now read postscript table */ if ( format == 0x00020000L ) error = load_format_20( face, stream, post_limit ); - else if ( format == 0x00028000L ) + else if ( format == 0x00025000L ) error = load_format_25( face, stream, post_limit ); else error = FT_THROW( Invalid_File_Format ); @@ -443,7 +446,7 @@ FT_FREE( table->glyph_names ); table->num_names = 0; } - else if ( format == 0x00028000L ) + else if ( format == 0x00025000L ) { TT_Post_25 table = &names->names.format_25; @@ -470,8 +473,8 @@ /* idx :: The glyph index. */ /* */ /* <InOut> */ - /* PSname :: The address of a string pointer. Will be NULL in case */ - /* of error, otherwise it is a pointer to the glyph name. */ + /* PSname :: The address of a string pointer. Undefined in case of */ + /* error, otherwise it is a pointer to the glyph name. */ /* */ /* You must not modify the returned string! */ /* */ @@ -539,7 +542,7 @@ *PSname = (FT_String*)table->glyph_names[name_index - 258]; } } - else if ( format == 0x00028000L ) + else if ( format == 0x00025000L ) { TT_Post_25 table = &names->names.format_25; @@ -561,5 +564,12 @@ return FT_Err_Ok; } +#else /* !TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ + + /* ANSI C doesn't like empty source files */ + typedef int _tt_post_dummy; + +#endif /* !TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ + /* END */ diff --git a/modules/freetype2/src/sfnt/ttpost.h b/modules/freetype2/src/sfnt/ttpost.h index ede45fd84..3bec07e44 100644 --- a/modules/freetype2/src/sfnt/ttpost.h +++ b/modules/freetype2/src/sfnt/ttpost.h @@ -5,7 +5,7 @@ /* PostScript name table processing for TrueType and OpenType fonts */ /* (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/sfnt/ttsbit.c b/modules/freetype2/src/sfnt/ttsbit.c index bf6ecca5a..33b8640bc 100644 --- a/modules/freetype2/src/sfnt/ttsbit.c +++ b/modules/freetype2/src/sfnt/ttsbit.c @@ -4,7 +4,7 @@ /* */ /* TrueType and OpenType embedded bitmap support (body). */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* Copyright 2013 by Google, Inc. */ @@ -24,6 +24,10 @@ #include FT_INTERNAL_STREAM_H #include FT_TRUETYPE_TAGS_H #include FT_BITMAP_H + + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + #include "ttsbit.h" #include "sferrors.h" @@ -444,6 +448,15 @@ metrics->max_advance = FT_MulDiv( hori->advance_Width_Max, ppem_ * 64, upem ); + /* set the scale values (in 16.16 units) so advances */ + /* from the hmtx and vmtx table are scaled correctly */ + metrics->x_scale = FT_MulDiv( metrics->x_ppem, + 64 * 0x10000, + face->header.Units_Per_EM ); + metrics->y_scale = FT_MulDiv( metrics->y_ppem, + 64 * 0x10000, + face->header.Units_Per_EM ); + return error; } @@ -994,8 +1007,9 @@ goto Fail; } - FT_TRACE3(( "tt_sbit_decoder_load_compound: loading %d components\n", - num_components )); + FT_TRACE3(( "tt_sbit_decoder_load_compound: loading %d component%s\n", + num_components, + num_components == 1 ? "" : "s" )); for ( nn = 0; nn < num_components; nn++ ) { @@ -1435,10 +1449,17 @@ return FT_THROW( Invalid_Table ); NoBitmap: + if ( recurse_count ) + { + FT_TRACE4(( "tt_sbit_decoder_load_image:" + " missing subglyph sbit with glyph index %d\n", + glyph_index )); + return FT_THROW( Invalid_Composite ); + } + FT_TRACE4(( "tt_sbit_decoder_load_image:" " no sbit found for glyph index %d\n", glyph_index )); - - return FT_THROW( Invalid_Argument ); + return FT_THROW( Missing_Bitmap ); } @@ -1460,6 +1481,9 @@ FT_Byte* p; FT_UNUSED( map ); +#ifndef FT_CONFIG_OPTION_USE_PNG + FT_UNUSED( metrics_only ); +#endif strike_index = face->sbit_strike_map[strike_index]; @@ -1490,7 +1514,7 @@ FT_FRAME_EXIT(); if ( glyph_start == glyph_end ) - return FT_THROW( Invalid_Argument ); + return FT_THROW( Missing_Bitmap ); if ( glyph_start > glyph_end || glyph_end - glyph_start < 8 || face->ebdt_size - strike_offset < glyph_end ) @@ -1647,5 +1671,12 @@ return error; } +#else /* !TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + /* ANSI C doesn't like empty source files */ + typedef int _tt_sbit_dummy; + +#endif /* !TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + -/* EOF */ +/* END */ diff --git a/modules/freetype2/src/sfnt/ttsbit.h b/modules/freetype2/src/sfnt/ttsbit.h index d8a816708..ce2af3c16 100644 --- a/modules/freetype2/src/sfnt/ttsbit.h +++ b/modules/freetype2/src/sfnt/ttsbit.h @@ -4,7 +4,7 @@ /* */ /* TrueType and OpenType embedded bitmap support (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/smooth/Jamfile b/modules/freetype2/src/smooth/Jamfile index a388c11d9..9957d5e91 100644 --- a/modules/freetype2/src/smooth/Jamfile +++ b/modules/freetype2/src/smooth/Jamfile @@ -1,6 +1,6 @@ # FreeType 2 src/smooth Jamfile # -# Copyright 2001-2016 by +# Copyright 2001-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/smooth/ftgrays.c b/modules/freetype2/src/smooth/ftgrays.c index ba42c9ca9..803a19e41 100644 --- a/modules/freetype2/src/smooth/ftgrays.c +++ b/modules/freetype2/src/smooth/ftgrays.c @@ -4,7 +4,7 @@ /* */ /* A new `perfect' anti-aliasing renderer (body). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -141,6 +141,16 @@ #define FT_INT_MAX INT_MAX #define FT_ULONG_MAX ULONG_MAX +#define ADD_LONG( a, b ) \ + (long)( (unsigned long)(a) + (unsigned long)(b) ) +#define SUB_LONG( a, b ) \ + (long)( (unsigned long)(a) - (unsigned long)(b) ) +#define MUL_LONG( a, b ) \ + (long)( (unsigned long)(a) * (unsigned long)(b) ) +#define NEG_LONG( a ) \ + (long)( -(unsigned long)(a) ) + + #define ft_memset memset #define ft_setjmp setjmp @@ -264,6 +274,7 @@ typedef ptrdiff_t FT_PtrDist; #include "ftgrays.h" #include FT_INTERNAL_OBJECTS_H #include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_CALC_H #include FT_OUTLINE_H #include "ftsmerrs.h" @@ -341,7 +352,8 @@ typedef ptrdiff_t FT_PtrDist; /* Compute `dividend / divisor' and return both its quotient and */ /* remainder, cast to a specific type. This macro also ensures that */ - /* the remainder is always positive. */ + /* the remainder is always positive. We use the remainder to keep */ + /* track of accumulating errors and compensate for them. */ #define FT_DIV_MOD( type, dividend, divisor, quotient, remainder ) \ FT_BEGIN_STMNT \ (quotient) = (type)( (dividend) / (divisor) ); \ @@ -358,7 +370,7 @@ typedef ptrdiff_t FT_PtrDist; /* optimize a division and modulo operation on the same parameters */ /* into a single call to `__aeabi_idivmod'. See */ /* */ - /* http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43721 */ + /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43721 */ #undef FT_DIV_MOD #define FT_DIV_MOD( type, dividend, divisor, quotient, remainder ) \ FT_BEGIN_STMNT \ @@ -392,7 +404,7 @@ typedef ptrdiff_t FT_PtrDist; /* need to define them to "float" or "double" when experimenting with */ /* new algorithms */ - typedef long TPos; /* sub-pixel coordinate */ + typedef long TPos; /* subpixel coordinate */ typedef int TCoord; /* integer scanline/pixel coordinate */ typedef int TArea; /* cell areas, coordinate products */ @@ -567,14 +579,11 @@ typedef ptrdiff_t FT_PtrDist; /* Note that if a cell is to the left of the clipping region, it is */ /* actually set to the (min_ex-1) horizontal position. */ - /* All cells that are on the left of the clipping region go to the */ - /* min_ex - 1 horizontal position. */ - if ( ex < ras.min_ex ) ex = ras.min_ex - 1; - /* record the current one if it is valid */ - if ( !ras.invalid ) + /* record the current one if it is valid and substantial */ + if ( !ras.invalid && ( ras.area || ras.cover ) ) gray_record_cell( RAS_VAR ); ras.area = 0; @@ -600,7 +609,7 @@ typedef ptrdiff_t FT_PtrDist; TPos x2, TCoord y2 ) { - TCoord ex1, ex2, fx1, fx2, first, delta, mod; + TCoord ex1, ex2, fx1, fx2, first, dy, delta, mod; TPos p, dx; int incr; @@ -617,31 +626,27 @@ typedef ptrdiff_t FT_PtrDist; fx1 = (TCoord)( x1 - SUBPIXELS( ex1 ) ); fx2 = (TCoord)( x2 - SUBPIXELS( ex2 ) ); - delta = y2 - y1; /* everything is located in a single cell. That is easy! */ /* */ if ( ex1 == ex2 ) - { - ras.area += (TArea)(( fx1 + fx2 ) * delta); - ras.cover += delta; - return; - } + goto End; /* ok, we'll have to render a run of adjacent cells on the same */ /* scanline... */ /* */ dx = x2 - x1; + dy = y2 - y1; if ( dx > 0 ) { - p = ( ONE_PIXEL - fx1 ) * delta; + p = ( ONE_PIXEL - fx1 ) * dy; first = ONE_PIXEL; incr = 1; } else { - p = fx1 * delta; + p = fx1 * dy; first = 0; incr = -1; dx = -dx; @@ -649,34 +654,31 @@ typedef ptrdiff_t FT_PtrDist; FT_DIV_MOD( TCoord, p, dx, delta, mod ); - ras.area += (TArea)(( fx1 + first ) * delta); + ras.area += (TArea)( ( fx1 + first ) * delta ); ras.cover += delta; - - ex1 += incr; + y1 += delta; + ex1 += incr; gray_set_cell( RAS_VAR_ ex1, ey ); - y1 += delta; if ( ex1 != ex2 ) { TCoord lift, rem; - p = ONE_PIXEL * ( y2 - y1 + delta ); + p = ONE_PIXEL * dy; FT_DIV_MOD( TCoord, p, dx, lift, rem ); - mod -= (int)dx; - do { delta = lift; mod += rem; - if ( mod >= 0 ) + if ( mod >= (TCoord)dx ) { mod -= (TCoord)dx; delta++; } - ras.area += (TArea)(ONE_PIXEL * delta); + ras.area += (TArea)( ONE_PIXEL * delta ); ras.cover += delta; y1 += delta; ex1 += incr; @@ -684,9 +686,13 @@ typedef ptrdiff_t FT_PtrDist; } while ( ex1 != ex2 ); } - delta = y2 - y1; - ras.area += (TArea)(( fx2 + ONE_PIXEL - first ) * delta); - ras.cover += delta; + fx1 = ONE_PIXEL - first; + + End: + dy = y2 - y1; + + ras.area += (TArea)( ( fx1 + fx2 ) * dy ); + ras.cover += dy; } @@ -798,13 +804,12 @@ typedef ptrdiff_t FT_PtrDist; p = ONE_PIXEL * dx; FT_DIV_MOD( TCoord, p, dy, lift, rem ); - mod -= (TCoord)dy; do { delta = lift; mod += rem; - if ( mod >= 0 ) + if ( mod >= (TCoord)dy ) { mod -= (TCoord)dy; delta++; @@ -1141,7 +1146,7 @@ typedef ptrdiff_t FT_PtrDist; /* s is L * the perpendicular distance from P1 to the line P0-P3. */ dx1 = arc[1].x - arc[0].x; dy1 = arc[1].y - arc[0].y; - s = FT_ABS( dy * dx1 - dx * dy1 ); + s = FT_ABS( SUB_LONG( MUL_LONG( dy, dx1 ), MUL_LONG( dx, dy1 ) ) ); if ( s > s_limit ) goto Split; @@ -1149,7 +1154,7 @@ typedef ptrdiff_t FT_PtrDist; /* s is L * the perpendicular distance from P2 to the line P0-P3. */ dx2 = arc[2].x - arc[0].x; dy2 = arc[2].y - arc[0].y; - s = FT_ABS( dy * dx2 - dx * dy2 ); + s = FT_ABS( SUB_LONG( MUL_LONG( dy, dx2 ), MUL_LONG( dx, dy2 ) ) ); if ( s > s_limit ) goto Split; @@ -1228,31 +1233,21 @@ typedef ptrdiff_t FT_PtrDist; static void gray_hline( RAS_ARG_ TCoord x, TCoord y, - TArea area, + TArea coverage, TCoord acount ) { - int coverage; - FT_Span span; - - - /* compute the coverage line's coverage, depending on the */ - /* outline fill rule */ - /* */ - /* the coverage percentage is area/(PIXEL_BITS*PIXEL_BITS*2) */ - /* */ - coverage = (int)( area >> ( PIXEL_BITS * 2 + 1 - 8 ) ); - /* use range 0..256 */ + /* scale the coverage from 0..(ONE_PIXEL*ONE_PIXEL*2) to 0..256 */ + coverage >>= PIXEL_BITS * 2 + 1 - 8; if ( coverage < 0 ) - coverage = -coverage; + coverage = -coverage - 1; + /* compute the line's coverage depending on the outline fill rule */ if ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) { coverage &= 511; - if ( coverage > 256 ) - coverage = 512 - coverage; - else if ( coverage == 256 ) - coverage = 255; + if ( coverage >= 256 ) + coverage = 511 - coverage; } else { @@ -1263,6 +1258,9 @@ typedef ptrdiff_t FT_PtrDist; if ( ras.render_span ) /* for FT_RASTER_FLAG_DIRECT only */ { + FT_Span span; + + span.x = (short)x; span.len = (unsigned short)acount; span.coverage = (unsigned char)coverage; @@ -1302,26 +1300,21 @@ typedef ptrdiff_t FT_PtrDist; int y; - FT_TRACE7(( "gray_sweep: start\n" )); - for ( y = ras.min_ey; y < ras.max_ey; y++ ) { PCell cell = ras.ycells[y - ras.min_ey]; - TCoord cover = 0; TCoord x = ras.min_ex; + TArea cover = 0; + TArea area; for ( ; cell != NULL; cell = cell->next ) { - TArea area; - - if ( cover != 0 && cell->x > x ) - gray_hline( RAS_VAR_ x, y, (TArea)cover * ( ONE_PIXEL * 2 ), - cell->x - x ); + gray_hline( RAS_VAR_ x, y, cover, cell->x - x ); - cover += cell->cover; - area = (TArea)cover * ( ONE_PIXEL * 2 ) - cell->area; + cover += (TArea)cell->cover * ( ONE_PIXEL * 2 ); + area = cover - cell->area; if ( area != 0 && cell->x >= ras.min_ex ) gray_hline( RAS_VAR_ cell->x, y, area, 1 ); @@ -1330,11 +1323,8 @@ typedef ptrdiff_t FT_PtrDist; } if ( cover != 0 ) - gray_hline( RAS_VAR_ x, y, (TArea)cover * ( ONE_PIXEL * 2 ), - ras.max_ex - x ); + gray_hline( RAS_VAR_ x, y, cover, ras.max_ex - x ); } - - FT_TRACE7(( "gray_sweep: end\n" )); } @@ -1613,7 +1603,7 @@ typedef ptrdiff_t FT_PtrDist; return 0; Exit: - FT_TRACE5(( "FT_Outline_Decompose: Error %d\n", error )); + FT_TRACE5(( "FT_Outline_Decompose: Error 0x%x\n", error )); return error; Invalid_Outline: @@ -1728,8 +1718,11 @@ typedef ptrdiff_t FT_PtrDist; if ( !ras.invalid ) gray_record_cell( RAS_VAR ); - FT_TRACE7(( "band [%d..%d]: %d cells\n", - ras.min_ey, ras.max_ey, ras.num_cells )); + FT_TRACE7(( "band [%d..%d]: %d cell%s\n", + ras.min_ey, + ras.max_ey, + ras.num_cells, + ras.num_cells == 1 ? "" : "s" )); } else { @@ -1746,35 +1739,43 @@ typedef ptrdiff_t FT_PtrDist; static int gray_convert_glyph( RAS_ARG ) { + const TCoord yMin = ras.min_ey; + const TCoord yMax = ras.max_ey; + const TCoord xMin = ras.min_ex; + const TCoord xMax = ras.max_ex; + TCell buffer[FT_MAX_GRAY_POOL]; - TCoord band_size = FT_MAX_GRAY_POOL / 8; - TCoord count = ras.max_ey - ras.min_ey; - int num_bands; - TCoord min, max, max_y; + size_t height = (size_t)( yMax - yMin ); + size_t n = FT_MAX_GRAY_POOL / 8; + TCoord y; TCoord bands[32]; /* enough to accommodate bisections */ TCoord* band; /* set up vertical bands */ - if ( count > band_size ) + if ( height > n ) { /* two divisions rounded up */ - num_bands = (int)( ( count + band_size - 1) / band_size ); - band_size = ( count + num_bands - 1 ) / num_bands; + n = ( height + n - 1 ) / n; + height = ( height + n - 1 ) / n; } - min = ras.min_ey; - max_y = ras.max_ey; + /* memory management */ + n = ( height * sizeof ( PCell ) + sizeof ( TCell ) - 1 ) / sizeof ( TCell ); + + ras.cells = buffer + n; + ras.max_cells = (FT_PtrDist)( FT_MAX_GRAY_POOL - n ); + ras.ycells = (PCell*)buffer; - for ( ; min < max_y; min = max ) + for ( y = yMin; y < yMax; ) { - max = min + band_size; - if ( max > max_y ) - max = max_y; + ras.min_ey = y; + y += height; + ras.max_ey = FT_MIN( y, yMax ); band = bands; - band[1] = min; - band[0] = max; + band[1] = xMin; + band[0] = xMax; do { @@ -1782,27 +1783,12 @@ typedef ptrdiff_t FT_PtrDist; int error; - /* memory management */ - { - size_t ycount = (size_t)width; - size_t cell_start; - - - cell_start = ( ycount * sizeof ( PCell ) + sizeof ( TCell ) - 1 ) / - sizeof ( TCell ); - - ras.cells = buffer + cell_start; - ras.max_cells = (FT_PtrDist)( FT_MAX_GRAY_POOL - cell_start ); - ras.num_cells = 0; - - ras.ycells = (PCell*)buffer; - while ( ycount ) - ras.ycells[--ycount] = NULL; - } + FT_MEM_ZERO( ras.ycells, height * sizeof ( PCell ) ); + ras.num_cells = 0; ras.invalid = 1; - ras.min_ey = band[1]; - ras.max_ey = band[0]; + ras.min_ex = band[1]; + ras.max_ex = band[0]; error = gray_convert_glyph_inner( RAS_VAR ); @@ -1818,8 +1804,7 @@ typedef ptrdiff_t FT_PtrDist; /* render pool overflow; we will reduce the render band by half */ width >>= 1; - /* This is too complex for a single scanline; there must */ - /* be some problems. */ + /* this should never happen even with tiny rendering pool */ if ( width == 0 ) { FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" )); diff --git a/modules/freetype2/src/smooth/ftgrays.h b/modules/freetype2/src/smooth/ftgrays.h index 21c2badca..9e11ca675 100644 --- a/modules/freetype2/src/smooth/ftgrays.h +++ b/modules/freetype2/src/smooth/ftgrays.h @@ -4,7 +4,7 @@ /* */ /* FreeType smooth renderer declaration */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/smooth/ftsmerrs.h b/modules/freetype2/src/smooth/ftsmerrs.h index a759b91c1..226dc1b00 100644 --- a/modules/freetype2/src/smooth/ftsmerrs.h +++ b/modules/freetype2/src/smooth/ftsmerrs.h @@ -4,7 +4,7 @@ /* */ /* smooth renderer error codes (specification only). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/smooth/ftsmooth.c b/modules/freetype2/src/smooth/ftsmooth.c index 5f6aa60ef..ef176bdf1 100644 --- a/modules/freetype2/src/smooth/ftsmooth.c +++ b/modules/freetype2/src/smooth/ftsmooth.c @@ -4,7 +4,7 @@ /* */ /* Anti-aliasing renderer interface (body). */ /* */ -/* Copyright 2000-2016 by */ +/* Copyright 2000-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -31,12 +31,7 @@ static FT_Error ft_smooth_init( FT_Renderer render ) { - FT_Library library = FT_MODULE_LIBRARY( render ); - - - render->clazz->raster_class->raster_reset( render->raster, - library->raster_pool, - library->raster_pool_size ); + render->clazz->raster_class->raster_reset( render->raster, NULL, 0 ); return 0; } @@ -102,26 +97,17 @@ const FT_Vector* origin, FT_Render_Mode required_mode ) { - FT_Error error; + FT_Error error = FT_Err_Ok; FT_Outline* outline = &slot->outline; FT_Bitmap* bitmap = &slot->bitmap; FT_Memory memory = render->root.memory; - FT_BBox cbox; FT_Pos x_shift = 0; FT_Pos y_shift = 0; - FT_Pos x_left, y_top; - FT_Pos width, height, pitch; -#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING - FT_Pos height_org, width_org; -#endif FT_Int hmul = ( mode == FT_RENDER_MODE_LCD ); FT_Int vmul = ( mode == FT_RENDER_MODE_LCD_V ); FT_Raster_Params params; - FT_Bool have_outline_shifted = FALSE; - FT_Bool have_buffer = FALSE; - /* check glyph image format */ if ( slot->format != render->glyph_format ) @@ -137,91 +123,6 @@ goto Exit; } - if ( origin ) - { - x_shift = origin->x; - y_shift = origin->y; - } - - /* compute the control box, and grid fit it */ - /* taking into account the origin shift */ - FT_Outline_Get_CBox( outline, &cbox ); - - cbox.xMin = FT_PIX_FLOOR( cbox.xMin + x_shift ); - cbox.yMin = FT_PIX_FLOOR( cbox.yMin + y_shift ); - cbox.xMax = FT_PIX_CEIL( cbox.xMax + x_shift ); - cbox.yMax = FT_PIX_CEIL( cbox.yMax + y_shift ); - - x_shift -= cbox.xMin; - y_shift -= cbox.yMin; - - x_left = cbox.xMin >> 6; - y_top = cbox.yMax >> 6; - - width = (FT_ULong)( cbox.xMax - cbox.xMin ) >> 6; - height = (FT_ULong)( cbox.yMax - cbox.yMin ) >> 6; - -#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING - width_org = width; - height_org = height; -#endif - - pitch = width; - if ( hmul ) - { - width *= 3; - pitch = FT_PAD_CEIL( width, 4 ); - } - - if ( vmul ) - height *= 3; - -#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING - - if ( slot->library->lcd_filter_func ) - { - FT_Int extra = slot->library->lcd_extra; - - - if ( hmul ) - { - x_shift += 64 * ( extra >> 1 ); - x_left -= extra >> 1; - width += 3 * extra; - pitch = FT_PAD_CEIL( width, 4 ); - } - - if ( vmul ) - { - y_shift += 64 * ( extra >> 1 ); - y_top += extra >> 1; - height += 3 * extra; - } - } - -#endif - - /* - * XXX: on 16bit system, we return an error for huge bitmap - * to prevent an overflow. - */ - if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX || - x_left < FT_INT_MIN || y_top < FT_INT_MIN ) - { - error = FT_THROW( Invalid_Pixel_Size ); - goto Exit; - } - - /* Required check is (pitch * height < FT_ULONG_MAX), */ - /* but we care realistic cases only. Always pitch <= width. */ - if ( width > 0x7FFF || height > 0x7FFF ) - { - FT_ERROR(( "ft_smooth_render_generic: glyph too large: %u x %u\n", - width, height )); - error = FT_THROW( Raster_Overflow ); - goto Exit; - } - /* release old bitmap buffer */ if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) { @@ -229,30 +130,30 @@ slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; } + ft_glyphslot_preset_bitmap( slot, mode, origin ); + /* allocate new one */ - if ( FT_ALLOC( bitmap->buffer, (FT_ULong)( pitch * height ) ) ) + if ( FT_ALLOC_MULT( bitmap->buffer, bitmap->rows, bitmap->pitch ) ) goto Exit; - else - have_buffer = TRUE; slot->internal->flags |= FT_GLYPH_OWN_BITMAP; - slot->format = FT_GLYPH_FORMAT_BITMAP; - slot->bitmap_left = (FT_Int)x_left; - slot->bitmap_top = (FT_Int)y_top; + x_shift = 64 * -slot->bitmap_left; + y_shift = 64 * -slot->bitmap_top; + if ( bitmap->pixel_mode == FT_PIXEL_MODE_LCD_V ) + y_shift += 64 * (FT_Int)bitmap->rows / 3; + else + y_shift += 64 * (FT_Int)bitmap->rows; - bitmap->pixel_mode = FT_PIXEL_MODE_GRAY; - bitmap->num_grays = 256; - bitmap->width = (unsigned int)width; - bitmap->rows = (unsigned int)height; - bitmap->pitch = pitch; + if ( origin ) + { + x_shift += origin->x; + y_shift += origin->y; + } /* translate outline to render it into the bitmap */ if ( x_shift || y_shift ) - { FT_Outline_Translate( outline, x_shift, y_shift ); - have_outline_shifted = TRUE; - } /* set up parameters */ params.target = bitmap; @@ -299,80 +200,143 @@ if ( error ) goto Exit; - if ( slot->library->lcd_filter_func ) - slot->library->lcd_filter_func( bitmap, mode, slot->library ); + /* finally apply filtering */ + if ( hmul || vmul ) + { + FT_Byte* lcd_weights; + FT_Bitmap_LcdFilterFunc lcd_filter_func; -#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ - /* render outline into bitmap */ - error = render->raster_render( render->raster, ¶ms ); - if ( error ) - goto Exit; + /* Per-face LCD filtering takes priority if set up. */ + if ( slot->face && slot->face->internal->lcd_filter_func ) + { + lcd_weights = slot->face->internal->lcd_weights; + lcd_filter_func = slot->face->internal->lcd_filter_func; + } + else + { + lcd_weights = slot->library->lcd_weights; + lcd_filter_func = slot->library->lcd_filter_func; + } - /* expand it horizontally */ - if ( hmul ) + if ( lcd_filter_func ) + lcd_filter_func( bitmap, mode, lcd_weights ); + } + +#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ + + if ( hmul ) /* lcd */ { - FT_Byte* line = bitmap->buffer; - FT_UInt hh; + FT_Byte* line; + FT_Byte* temp = NULL; + FT_UInt i, j; + unsigned int height = bitmap->rows; + unsigned int width = bitmap->width; + int pitch = bitmap->pitch; - for ( hh = height_org; hh > 0; hh--, line += pitch ) - { - FT_UInt xx; - FT_Byte* end = line + width; + /* Render 3 separate monochrome bitmaps, shifting the outline */ + /* by 1/3 pixel. */ + width /= 3; - for ( xx = width_org; xx > 0; xx-- ) - { - FT_UInt pixel = line[xx-1]; + bitmap->buffer += width; + error = render->raster_render( render->raster, ¶ms ); + if ( error ) + goto Exit; - end[-3] = (FT_Byte)pixel; - end[-2] = (FT_Byte)pixel; - end[-1] = (FT_Byte)pixel; - end -= 3; + FT_Outline_Translate( outline, -21, 0 ); + x_shift -= 21; + bitmap->buffer += width; + + error = render->raster_render( render->raster, ¶ms ); + if ( error ) + goto Exit; + + FT_Outline_Translate( outline, 42, 0 ); + x_shift += 42; + bitmap->buffer -= 2 * width; + + error = render->raster_render( render->raster, ¶ms ); + if ( error ) + goto Exit; + + /* XXX: Rearrange the bytes according to FT_PIXEL_MODE_LCD. */ + /* XXX: It is more efficient to render every third byte above. */ + + if ( FT_ALLOC( temp, (FT_ULong)pitch ) ) + goto Exit; + + for ( i = 0; i < height; i++ ) + { + line = bitmap->buffer + i * (FT_ULong)pitch; + for ( j = 0; j < width; j++ ) + { + temp[3 * j ] = line[j]; + temp[3 * j + 1] = line[j + width]; + temp[3 * j + 2] = line[j + width + width]; } + FT_MEM_COPY( line, temp, pitch ); } - } - /* expand it vertically */ - if ( vmul ) + FT_FREE( temp ); + } + else if ( vmul ) /* lcd_v */ { - FT_Byte* read = bitmap->buffer + ( height - height_org ) * pitch; - FT_Byte* write = bitmap->buffer; - FT_UInt hh; + int pitch = bitmap->pitch; - for ( hh = height_org; hh > 0; hh-- ) - { - ft_memcpy( write, read, pitch ); - write += pitch; + /* Render 3 separate monochrome bitmaps, shifting the outline */ + /* by 1/3 pixel. Triple the pitch to render on each third row. */ + bitmap->pitch *= 3; + bitmap->rows /= 3; - ft_memcpy( write, read, pitch ); - write += pitch; + bitmap->buffer += pitch; - ft_memcpy( write, read, pitch ); - write += pitch; - read += pitch; - } - } + error = render->raster_render( render->raster, ¶ms ); + if ( error ) + goto Exit; -#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ + FT_Outline_Translate( outline, 0, 21 ); + y_shift += 21; + bitmap->buffer += pitch; + + error = render->raster_render( render->raster, ¶ms ); + if ( error ) + goto Exit; - /* everything is fine; don't deallocate buffer */ - have_buffer = FALSE; + FT_Outline_Translate( outline, 0, -42 ); + y_shift -= 42; + bitmap->buffer -= 2 * pitch; + + error = render->raster_render( render->raster, ¶ms ); + if ( error ) + goto Exit; + + bitmap->pitch /= 3; + bitmap->rows *= 3; + } + else /* grayscale */ + error = render->raster_render( render->raster, ¶ms ); - error = FT_Err_Ok; +#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ Exit: - if ( have_outline_shifted ) - FT_Outline_Translate( outline, -x_shift, -y_shift ); - if ( have_buffer ) + if ( !error ) + { + /* everything is fine; the glyph is now officially a bitmap */ + slot->format = FT_GLYPH_FORMAT_BITMAP; + } + else if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) { FT_FREE( bitmap->buffer ); slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; } + if ( x_shift || y_shift ) + FT_Outline_Translate( outline, -x_shift, -y_shift ); + return error; } @@ -399,14 +363,8 @@ FT_Render_Mode mode, const FT_Vector* origin ) { - FT_Error error; - - error = ft_smooth_render_generic( render, slot, mode, origin, - FT_RENDER_MODE_LCD ); - if ( !error ) - slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD; - - return error; + return ft_smooth_render_generic( render, slot, mode, origin, + FT_RENDER_MODE_LCD ); } @@ -417,14 +375,8 @@ FT_Render_Mode mode, const FT_Vector* origin ) { - FT_Error error; - - error = ft_smooth_render_generic( render, slot, mode, origin, - FT_RENDER_MODE_LCD_V ); - if ( !error ) - slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD_V; - - return error; + return ft_smooth_render_generic( render, slot, mode, origin, + FT_RENDER_MODE_LCD_V ); } diff --git a/modules/freetype2/src/smooth/ftsmooth.h b/modules/freetype2/src/smooth/ftsmooth.h index c7c28c244..c76ffc503 100644 --- a/modules/freetype2/src/smooth/ftsmooth.h +++ b/modules/freetype2/src/smooth/ftsmooth.h @@ -4,7 +4,7 @@ /* */ /* Anti-aliasing renderer interface (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -27,18 +27,11 @@ FT_BEGIN_HEADER -#ifndef FT_CONFIG_OPTION_NO_STD_RASTER - FT_DECLARE_RENDERER( ft_std_renderer_class ) -#endif - -#ifndef FT_CONFIG_OPTION_NO_SMOOTH_RASTER FT_DECLARE_RENDERER( ft_smooth_renderer_class ) FT_DECLARE_RENDERER( ft_smooth_lcd_renderer_class ) - FT_DECLARE_RENDERER( ft_smooth_lcd_v_renderer_class ) -#endif - + FT_DECLARE_RENDERER( ft_smooth_lcdv_renderer_class ) FT_END_HEADER diff --git a/modules/freetype2/src/smooth/ftspic.c b/modules/freetype2/src/smooth/ftspic.c index 6c2b2329b..10f04cf4c 100644 --- a/modules/freetype2/src/smooth/ftspic.c +++ b/modules/freetype2/src/smooth/ftspic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for smooth module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2018 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/smooth/ftspic.h b/modules/freetype2/src/smooth/ftspic.h index fe7615277..80fb64cff 100644 --- a/modules/freetype2/src/smooth/ftspic.h +++ b/modules/freetype2/src/smooth/ftspic.h @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for smooth module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2018 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/smooth/module.mk b/modules/freetype2/src/smooth/module.mk index f3cb04403..5b8bc3be3 100644 --- a/modules/freetype2/src/smooth/module.mk +++ b/modules/freetype2/src/smooth/module.mk @@ -3,7 +3,7 @@ # -# Copyright 1996-2016 by +# Copyright 1996-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/smooth/rules.mk b/modules/freetype2/src/smooth/rules.mk index 5e94f7351..f30824a36 100644 --- a/modules/freetype2/src/smooth/rules.mk +++ b/modules/freetype2/src/smooth/rules.mk @@ -3,7 +3,7 @@ # -# Copyright 1996-2016 by +# Copyright 1996-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/smooth/smooth.c b/modules/freetype2/src/smooth/smooth.c index 97ca3e599..5249a8931 100644 --- a/modules/freetype2/src/smooth/smooth.c +++ b/modules/freetype2/src/smooth/smooth.c @@ -4,7 +4,7 @@ /* */ /* FreeType anti-aliasing rasterer module component (body only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,11 +17,11 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT - #include <ft2build.h> -#include "ftspic.c" + #include "ftgrays.c" #include "ftsmooth.c" +#include "ftspic.c" /* END */ diff --git a/modules/freetype2/src/tools/afblue.pl b/modules/freetype2/src/tools/afblue.pl index 39fe5c584..7c6f1a7df 100644 --- a/modules/freetype2/src/tools/afblue.pl +++ b/modules/freetype2/src/tools/afblue.pl @@ -5,7 +5,7 @@ # # Process a blue zone character data file. # -# Copyright 2013-2016 by +# Copyright 2013-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, diff --git a/modules/freetype2/src/tools/apinames.c b/modules/freetype2/src/tools/apinames.c index 73bc99de5..06c326043 100644 --- a/modules/freetype2/src/tools/apinames.c +++ b/modules/freetype2/src/tools/apinames.c @@ -22,7 +22,7 @@ #include <ctype.h> #define PROGRAM_NAME "apinames" -#define PROGRAM_VERSION "0.2" +#define PROGRAM_VERSION "0.3" #define LINEBUFF_SIZE 1024 @@ -32,7 +32,8 @@ typedef enum OutputFormat_ OUTPUT_WINDOWS_DEF, /* output a Windows .DEF file for Visual C++ or Mingw */ OUTPUT_BORLAND_DEF, /* output a Windows .DEF file for Borland C++ */ OUTPUT_WATCOM_LBC, /* output a Watcom Linker Command File */ - OUTPUT_NETWARE_IMP /* output a NetWare ImportFile */ + OUTPUT_NETWARE_IMP, /* output a NetWare ImportFile */ + OUTPUT_GNU_VERMAP /* output a version map for GNU or Solaris linker */ } OutputFormat; @@ -198,6 +199,15 @@ names_dump( FILE* out, } break; + case OUTPUT_GNU_VERMAP: + { + fprintf( out, "{\n\tglobal:\n" ); + for ( nn = 0; nn < num_names; nn++ ) + fprintf( out, "\t\t%s;\n", the_names[nn].name ); + fprintf( out, "\tlocal:\n\t\t*;\n};\n" ); + } + break; + default: /* LIST */ for ( nn = 0; nn < num_names; nn++ ) fprintf( out, "%s\n", the_names[nn].name ); @@ -323,6 +333,7 @@ usage( void ) " -wB : output .DEF file for Borland C++\n" " -wW : output Watcom Linker Response File\n" " -wN : output NetWare Import File\n" + " -wL : output version map for GNU or Solaris linker\n" "\n"; fprintf( stderr, @@ -410,6 +421,10 @@ int main( int argc, const char* const* argv ) format = OUTPUT_NETWARE_IMP; break; + case 'L': + format = OUTPUT_GNU_VERMAP; + break; + case 0: break; diff --git a/modules/freetype2/src/tools/docmaker/content.py b/modules/freetype2/src/tools/docmaker/content.py index 438345c41..198780aee 100644 --- a/modules/freetype2/src/tools/docmaker/content.py +++ b/modules/freetype2/src/tools/docmaker/content.py @@ -3,7 +3,7 @@ # # Parse comment blocks to build content blocks (library file). # -# Copyright 2002-2016 by +# Copyright 2002-2018 by # David Turner. # # This file is part of the FreeType project, and may only be used, @@ -109,7 +109,7 @@ class DocCode: def dump( self, prefix = "", width = 60 ): lines = self.dump_lines( 0, width ) for l in lines: - print prefix + l + print( prefix + l ) def dump_lines( self, margin = 0, width = 60 ): result = [] @@ -139,7 +139,7 @@ class DocPara: def dump( self, prefix = "", width = 60 ): lines = self.dump_lines( 0, width ) for l in lines: - print prefix + l + print( prefix + l ) def dump_lines( self, margin = 0, width = 60 ): cur = "" # current line @@ -243,13 +243,13 @@ class DocField: def dump( self, prefix = "" ): if self.field: - print prefix + self.field + " ::" + print( prefix + self.field + " ::" ) prefix = prefix + "----" first = 1 for p in self.items: if not first: - print "" + print( "" ) p.dump( prefix ) first = 0 @@ -330,10 +330,10 @@ class DocMarkup: return None def dump( self, margin ): - print " " * margin + "<" + self.tag + ">" + print( " " * margin + "<" + self.tag + ">" ) for f in self.fields: f.dump( " " ) - print " " * margin + "</" + self.tag + ">" + print( " " * margin + "</" + self.tag + ">" ) ################################################################ @@ -453,15 +453,32 @@ class ContentProcessor: markup_lines = [] first = 1 + margin = -1 + in_code = 0 + for line in content: - found = None - for t in re_markup_tags: - m = t.match( line ) + if in_code: + m = re_code_end.match( line ) + if m and len( m.group( 1 ) ) <= margin: + in_code = 0 + margin = -1 + else: + m = re_code_start.match( line ) if m: - found = string.lower( m.group( 1 ) ) - prefix = len( m.group( 0 ) ) - line = " " * prefix + line[prefix:] # remove markup from line - break + in_code = 1 + margin = len( m.group( 1 ) ) + + found = None + + if not in_code: + for t in re_markup_tags: + m = t.match( line ) + if m: + found = string.lower( m.group( 1 ) ) + prefix = len( m.group( 0 ) ) + # remove markup from line + line = " " * prefix + line[prefix:] + break # is it the start of a new markup section ? if found: diff --git a/modules/freetype2/src/tools/docmaker/docbeauty.py b/modules/freetype2/src/tools/docmaker/docbeauty.py index 3ddf4a94a..0b021fa6c 100644 --- a/modules/freetype2/src/tools/docmaker/docbeauty.py +++ b/modules/freetype2/src/tools/docmaker/docbeauty.py @@ -10,9 +10,7 @@ from sources import * from content import * from utils import * -import utils - -import sys, os, time, string, getopt +import sys, os, string, getopt content_processor = ContentProcessor() @@ -40,13 +38,13 @@ def beautify_block( block ): def usage(): - print "\nDocBeauty 0.1 Usage information\n" - print " docbeauty [options] file1 [file2 ...]\n" - print "using the following options:\n" - print " -h : print this page" - print " -b : backup original files with the 'orig' extension" - print "" - print " --backup : same as -b" + print( "\nDocBeauty 0.1 Usage information\n" ) + print( " docbeauty [options] file1 [file2 ...]\n" ) + print( "using the following options:\n" ) + print( " -h : print this page" ) + print( " -b : backup original files with the 'orig' extension" ) + print( "" ) + print( " --backup : same as -b" ) def main( argv ): diff --git a/modules/freetype2/src/tools/docmaker/docmaker.py b/modules/freetype2/src/tools/docmaker/docmaker.py index aa8899664..eb49afb0a 100644 --- a/modules/freetype2/src/tools/docmaker/docmaker.py +++ b/modules/freetype2/src/tools/docmaker/docmaker.py @@ -4,7 +4,7 @@ # # Convert source code markup to HTML documentation. # -# Copyright 2002-2016 by +# Copyright 2002-2018 by # David Turner. # # This file is part of the FreeType project, and may only be used, @@ -31,21 +31,21 @@ from tohtml import * import utils -import sys, os, time, string, glob, getopt +import sys, glob, getopt def usage(): - print "\nDocMaker Usage information\n" - print " docmaker [options] file1 [file2 ...]\n" - print "using the following options:\n" - print " -h : print this page" - print " -t : set project title, as in '-t \"My Project\"'" - print " -o : set output directory, as in '-o mydir'" - print " -p : set documentation prefix, as in '-p ft2'" - print "" - print " --title : same as -t, as in '--title=\"My Project\"'" - print " --output : same as -o, as in '--output=mydir'" - print " --prefix : same as -p, as in '--prefix=ft2'" + print( "\nDocMaker Usage information\n" ) + print( " docmaker [options] file1 [file2 ...]\n" ) + print( "using the following options:\n" ) + print( " -h : print this page" ) + print( " -t : set project title, as in '-t \"My Project\"'" ) + print( " -o : set output directory, as in '-o mydir'" ) + print( " -p : set documentation prefix, as in '-p ft2'" ) + print( "" ) + print( " --title : same as -t, as in '--title=\"My Project\"'" ) + print( " --output : same as -o, as in '--output=mydir'" ) + print( " --prefix : same as -p, as in '--prefix=ft2'" ) def main( argv ): diff --git a/modules/freetype2/src/tools/docmaker/formatter.py b/modules/freetype2/src/tools/docmaker/formatter.py index c47589048..2708fd40d 100644 --- a/modules/freetype2/src/tools/docmaker/formatter.py +++ b/modules/freetype2/src/tools/docmaker/formatter.py @@ -3,7 +3,7 @@ # # Convert parsed content blocks to a structured document (library file). # -# Copyright 2002-2016 by +# Copyright 2002-2018 by # David Turner. # # This file is part of the FreeType project, and may only be used, diff --git a/modules/freetype2/src/tools/docmaker/sources.py b/modules/freetype2/src/tools/docmaker/sources.py index 3d30c7277..e3b95e0fa 100644 --- a/modules/freetype2/src/tools/docmaker/sources.py +++ b/modules/freetype2/src/tools/docmaker/sources.py @@ -3,7 +3,7 @@ # # Convert source code comments to multi-line blocks (library file). # -# Copyright 2002-2016 by +# Copyright 2002-2018 by # David Turner. # # This file is part of the FreeType project, and may only be used, @@ -29,7 +29,7 @@ # -import fileinput, re, sys, os, string +import fileinput, re, string ################################################################ @@ -171,7 +171,7 @@ re_bold = re.compile( r"\*((?:\w|-)(?:\w|'|-)*)\*(.*)" ) # *bold* # # This regular expression code to identify an URL has been taken from # -# http://mail.python.org/pipermail/tutor/2002-September/017228.html +# https://mail.python.org/pipermail/tutor/2002-September/017228.html # # (with slight modifications). # @@ -296,10 +296,10 @@ class SourceBlock: # debugging only -- not used in normal operations def dump( self ): if self.content: - print "{{{content start---" + print( "{{{content start---" ) for l in self.content: - print l - print "---content end}}}" + print( l ) + print( "---content end}}}" ) return fmt = "" @@ -307,7 +307,7 @@ class SourceBlock: fmt = repr( self.format.id ) + " " for line in self.lines: - print line + print( line ) ################################################################ diff --git a/modules/freetype2/src/tools/docmaker/tohtml.py b/modules/freetype2/src/tools/docmaker/tohtml.py index 9b28780e9..9f318a2a4 100644 --- a/modules/freetype2/src/tools/docmaker/tohtml.py +++ b/modules/freetype2/src/tools/docmaker/tohtml.py @@ -3,7 +3,7 @@ # # A sub-class container of the `Formatter' class to produce HTML. # -# Copyright 2002-2016 by +# Copyright 2002-2018 by # David Turner. # # This file is part of the FreeType project, and may only be used, @@ -25,7 +25,7 @@ import time # The following strings define the HTML header used by all generated pages. html_header_1 = """\ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" -"http://www.w3.org/TR/html4/loose.dtd"> +"https://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> @@ -406,7 +406,7 @@ class HtmlFormatter( Formatter ): return string.join( lines, '\n' ) def print_html_items( self, items ): - print self.make_html_items( items ) + print( self.make_html_items( items ) ) def print_html_field( self, field ): if field.name: @@ -414,10 +414,10 @@ class HtmlFormatter( Formatter ): + field.name + "</b></td><td>" ) - print self.make_html_items( field.items ) + print( self.make_html_items( field.items ) ) if field.name: - print "</td></tr></table>" + print( "</td></tr></table>" ) def html_source_quote( self, line, block_name = None ): result = "" @@ -468,14 +468,14 @@ class HtmlFormatter( Formatter ): return result def print_html_field_list( self, fields ): - print '<table class="fields">' + print( '<table class="fields">' ) for field in fields: - print ( '<tr><td class="val" id="' + field.name + '">' - + field.name - + '</td><td class="desc">' ) + print( '<tr><td class="val" id="' + field.name + '">' + + field.name + + '</td><td class="desc">' ) self.print_html_items( field.items ) - print "</td></tr>" - print "</table>" + print( "</td></tr>" ) + print( "</table>" ) def print_html_markup( self, markup ): table_fields = [] @@ -499,7 +499,7 @@ class HtmlFormatter( Formatter ): # formatting the index # def index_enter( self ): - print self.html_index_header + print( self.html_index_header ) self.index_items = {} def index_name_enter( self, name ): @@ -512,7 +512,7 @@ class HtmlFormatter( Formatter ): count = len( self.block_index ) rows = ( count + self.columns - 1 ) // self.columns - print '<table class="index">' + print( '<table class="index">' ) for r in range( rows ): line = "<tr>" for c in range( self.columns ): @@ -531,15 +531,15 @@ class HtmlFormatter( Formatter ): else: line = line + '<td></td>' line = line + "</tr>" - print line + print( line ) - print "</table>" + print( "</table>" ) print( index_footer_start + self.file_prefix + "toc.html" + index_footer_end ) - print self.html_footer + print( self.html_footer ) self.index_items = {} @@ -553,25 +553,25 @@ class HtmlFormatter( Formatter ): # formatting the table of contents # def toc_enter( self ): - print self.html_toc_header - print "<h1>Table of Contents</h1>" + print( self.html_toc_header ) + print( "<h1>Table of Contents</h1>" ) def toc_chapter_enter( self, chapter ): - print chapter_header + string.join( chapter.title ) + chapter_inter - print '<table class="toc">' + print( chapter_header + string.join( chapter.title ) + chapter_inter ) + print( '<table class="toc">' ) def toc_section_enter( self, section ): - print ( '<tr><td class="link">' - + '<a href="' + self.make_section_url( section ) + '">' - + section.title + '</a></td><td class="desc">' ) - print self.make_html_para( section.abstract ) + print( '<tr><td class="link">' + + '<a href="' + self.make_section_url( section ) + '">' + + section.title + '</a></td><td class="desc">' ) + print( self.make_html_para( section.abstract ) ) def toc_section_exit( self, section ): - print "</td></tr>" + print( "</td></tr>" ) def toc_chapter_exit( self, chapter ): - print "</table>" - print chapter_footer + print( "</table>" ) + print( chapter_footer ) def toc_index( self, index_filename ): print( chapter_header @@ -583,7 +583,7 @@ class HtmlFormatter( Formatter ): + self.file_prefix + "index.html" + toc_footer_end ) - print self.html_footer + print( self.html_footer ) def toc_dump( self, toc_filename = None, index_filename = None ): if toc_filename == None: @@ -598,11 +598,11 @@ class HtmlFormatter( Formatter ): # formatting sections # def section_enter( self, section ): - print self.html_header + print( self.html_header ) - print ( section_title_header1 + section.name + section_title_header2 - + section.title - + section_title_footer ) + print( section_title_header1 + section.name + section_title_header2 + + section.title + + section_title_footer ) maxwidth = 0 for b in section.blocks.values(): @@ -612,8 +612,8 @@ class HtmlFormatter( Formatter ): width = 70 # XXX magic number if maxwidth > 0: # print section synopsis - print section_synopsis_header - print '<table class="synopsis">' + print( section_synopsis_header ) + print( '<table class="synopsis">' ) columns = width // maxwidth if columns < 1: @@ -650,17 +650,17 @@ class HtmlFormatter( Formatter ): line = line + '</td>' line = line + "</tr>" - print line + print( line ) - print "</table>" - print section_synopsis_footer + print( "</table>" ) + print( section_synopsis_footer ) - print description_header - print self.make_html_items( section.description ) - print description_footer + print( description_header ) + print( self.make_html_items( section.description ) ) + print( description_footer ) def block_enter( self, block ): - print block_header + print( block_header ) # place html anchor if needed if block.name: @@ -686,28 +686,28 @@ class HtmlFormatter( Formatter ): # + " '" + block.source.filename + "'.\n" ) if header: - print ( header_location_header - + 'Defined in ' + header + '.' - + header_location_footer ) + print( header_location_header + + 'Defined in ' + header + '.' + + header_location_footer ) - print source_header + print( source_header ) for l in block.code: - print self.html_source_quote( l, block.name ) - print source_footer + print( self.html_source_quote( l, block.name ) ) + print( source_footer ) def markup_enter( self, markup, block ): if markup.tag == "description": - print description_header + print( description_header ) else: - print marker_header + markup.tag + marker_inter + print( marker_header + markup.tag + marker_inter ) self.print_html_markup( markup ) def markup_exit( self, markup, block ): if markup.tag == "description": - print description_footer + print( description_footer ) else: - print marker_footer + print( marker_footer ) def block_exit( self, block ): print( block_footer_start + self.file_prefix + "index.html" @@ -715,7 +715,7 @@ class HtmlFormatter( Formatter ): + block_footer_end ) def section_exit( self, section ): - print html_footer + print( html_footer ) def section_dump_all( self ): for section in self.sections: diff --git a/modules/freetype2/src/tools/docmaker/utils.py b/modules/freetype2/src/tools/docmaker/utils.py index cbba9b874..f40f1674a 100644 --- a/modules/freetype2/src/tools/docmaker/utils.py +++ b/modules/freetype2/src/tools/docmaker/utils.py @@ -3,7 +3,7 @@ # # Auxiliary functions for the `docmaker' tool (library file). # -# Copyright 2002-2016 by +# Copyright 2002-2018 by # David Turner. # # This file is part of the FreeType project, and may only be used, diff --git a/modules/freetype2/src/tools/ftfuzzer/README b/modules/freetype2/src/tools/ftfuzzer/README index c16b7e94e..09d8e9f32 100644 --- a/modules/freetype2/src/tools/ftfuzzer/README +++ b/modules/freetype2/src/tools/ftfuzzer/README @@ -6,7 +6,7 @@ ftfuzzer.cc ----------- This file contains a target function for FreeType fuzzing. It can be -used with libFuzzer (http://llvm.org/docs/LibFuzzer.html) or +used with libFuzzer (https://llvm.org/docs/LibFuzzer.html) or potentially any other similar fuzzer. Usage: @@ -20,7 +20,7 @@ Usage: -fsanitize=address,signed-integer-overflow,shift You also need the header files from the `libarchive' library - (http://www.libarchive.org/) for handling tar files (see file + (https://www.libarchive.org/) for handling tar files (see file `ftmutator.cc' below for more). 2. Link with `libFuzzer' (it contains `main') and `libarchive'. @@ -29,10 +29,14 @@ Usage: The exact flags and commands may vary. + https://github.com/google/oss-fuzz/tree/master/projects/freetype2 There is a continuous fuzzing bot that runs ftfuzzer. - https://github.com/google/libfuzzer-bot/tree/master/freetype + https://oss-fuzz.com + +(You need an account to be able to see coverage reports and the like +on oss-fuzz.com.) Check the bot configuration for the most current settings. @@ -64,7 +68,7 @@ a convenience `main' function. Link it with `ftfuzzer.cc', ---------------------------------------------------------------------- -Copyright 2015-2016 by +Copyright 2015-2018 by David Turner, Robert Wilhelm, and Werner Lemberg. This file is part of the FreeType project, and may only be used, diff --git a/modules/freetype2/src/tools/ftfuzzer/ftfuzzer.cc b/modules/freetype2/src/tools/ftfuzzer/ftfuzzer.cc index 31834a5f9..acf2bc982 100644 --- a/modules/freetype2/src/tools/ftfuzzer/ftfuzzer.cc +++ b/modules/freetype2/src/tools/ftfuzzer/ftfuzzer.cc @@ -2,7 +2,7 @@ // // A fuzzing function to test FreeType with libFuzzer. // -// Copyright 2015-2016 by +// Copyright 2015-2018 by // David Turner, Robert Wilhelm, and Werner Lemberg. // // This file is part of the FreeType project, and may only be used, @@ -43,8 +43,7 @@ #include FT_OUTLINE_H #include FT_BBOX_H #include FT_MODULE_H -#include FT_CFF_DRIVER_H -#include FT_TRUETYPE_DRIVER_H +#include FT_DRIVER_H #include FT_MULTIPLE_MASTERS_H @@ -61,7 +60,7 @@ return; // try to activate Adobe's CFF engine; it might not be the default - unsigned int cff_hinting_engine = FT_CFF_HINTING_ADOBE; + unsigned int cff_hinting_engine = FT_HINTING_ADOBE; FT_Property_Set( library, "cff", "hinting-engine", &cff_hinting_engine ); @@ -76,7 +75,7 @@ FT_Global global_ft; - // We want to select n values at random (without repitition), + // We want to select n values at random (without repetition), // with 0 < n <= N. The algorithm is taken from TAoCP, Vol. 2 // (Algorithm S, selection sampling technique) struct Random @@ -270,11 +269,20 @@ long num_faces = face->num_faces; FT_Done_Face( face ); - // loop over all faces - for ( long face_index = 0; - face_index < num_faces; - face_index++ ) + // loop over up to 20 arbitrarily selected faces + // from index range [0;num-faces-1] + long max_face_cnt = num_faces < 20 + ? num_faces + : 20; + + Random faces_pool( (int)max_face_cnt, (int)num_faces ); + + for ( long face_cnt = 0; + face_cnt < max_face_cnt; + face_cnt++ ) { + long face_index = faces_pool.get() - 1; + // get number of instances if ( FT_New_Memory_Face( library, files[0].data(), @@ -285,17 +293,41 @@ long num_instances = face->style_flags >> 16; FT_Done_Face( face ); - // load face with and without instances - for ( long instance_index = 0; - instance_index < num_instances + 1; - instance_index++ ) + // loop over the face without instance (index 0) + // and up to 20 arbitrarily selected instances + // from index range [1;num_instances] + long max_instance_cnt = num_instances < 20 + ? num_instances + : 20; + + Random instances_pool( (int)max_instance_cnt, (int)num_instances ); + + for ( long instance_cnt = 0; + instance_cnt <= max_instance_cnt; + instance_cnt++ ) { - if ( FT_New_Memory_Face( library, - files[0].data(), - (FT_Long)files[0].size(), - ( instance_index << 16 ) + face_index, - &face ) ) - continue; + long instance_index = 0; + + if ( !instance_cnt ) + { + if ( FT_New_Memory_Face( library, + files[0].data(), + (FT_Long)files[0].size(), + face_index, + &face ) ) + continue; + } + else + { + instance_index = instances_pool.get(); + + if ( FT_New_Memory_Face( library, + files[0].data(), + (FT_Long)files[0].size(), + ( instance_index << 16 ) + face_index, + &face ) ) + continue; + } // if we have more than a single input file coming from an archive, // attach them (starting with the second file) using the order given @@ -314,19 +346,24 @@ FT_Attach_Stream( face, &open_args ); } - // loop over an arbitrary size for outlines (index 0) - // and up to ten arbitrarily selected bitmap stroke sizes (index 1-10) - int max_idx = face->num_fixed_sizes < 10 - ? face->num_fixed_sizes - : 10; + // loop over an arbitrary size for outlines + // and up to ten arbitrarily selected bitmap strike sizes + // from the range [0;num_fixed_sizes - 1] + int max_size_cnt = face->num_fixed_sizes < 10 + ? face->num_fixed_sizes + : 10; - Random pool( max_idx, face->num_fixed_sizes ); + Random sizes_pool( max_size_cnt, face->num_fixed_sizes ); - for ( int idx = 0; idx <= max_idx; idx++ ) + for ( int size_cnt = 0; + size_cnt <= max_size_cnt; + size_cnt++ ) { FT_Int32 flags = load_flags; - if ( !idx ) + int size_index = 0; + + if ( !size_cnt ) { // set up 20pt at 72dpi as an arbitrary size if ( FT_Set_Char_Size( face, 20 * 64, 20 * 64, 72, 72 ) ) @@ -335,17 +372,20 @@ } else { - // bitmap strokes are not active for glyph variations + // bitmap strikes are not active for font variations if ( instance_index ) continue; - if ( FT_Select_Size( face, pool.get() - 1 ) ) + size_index = sizes_pool.get() - 1; + + if ( FT_Select_Size( face, size_index ) ) continue; flags |= FT_LOAD_COLOR; } // test MM interface only for a face without a selected instance - if ( instance_index == 0 ) + // and without a selected bitmap strike + if ( !instance_index && !size_cnt ) setIntermediateAxis( face ); // loop over all glyphs diff --git a/modules/freetype2/src/tools/ftfuzzer/ftmutator.cc b/modules/freetype2/src/tools/ftfuzzer/ftmutator.cc index 4818450aa..ae4b14040 100644 --- a/modules/freetype2/src/tools/ftfuzzer/ftmutator.cc +++ b/modules/freetype2/src/tools/ftfuzzer/ftmutator.cc @@ -2,7 +2,7 @@ // // A custom fuzzer mutator to test for FreeType with libFuzzer. // -// Copyright 2015-2016 by +// Copyright 2015-2018 by // David Turner, Robert Wilhelm, and Werner Lemberg. // // This file is part of the FreeType project, and may only be used, diff --git a/modules/freetype2/src/tools/ftfuzzer/rasterfuzzer.cc b/modules/freetype2/src/tools/ftfuzzer/rasterfuzzer.cc index 05187b0be..c69b95ea0 100644 --- a/modules/freetype2/src/tools/ftfuzzer/rasterfuzzer.cc +++ b/modules/freetype2/src/tools/ftfuzzer/rasterfuzzer.cc @@ -2,7 +2,7 @@ // // A fuzzing function to test FreeType's rasterizers with libFuzzer. // -// Copyright 2016 by +// Copyright 2016-2018 by // David Turner, Robert Wilhelm, and Werner Lemberg. // // This file is part of the FreeType project, and may only be used, diff --git a/modules/freetype2/src/tools/ftfuzzer/runinput.cc b/modules/freetype2/src/tools/ftfuzzer/runinput.cc index d5f9f1587..2b02f5758 100644 --- a/modules/freetype2/src/tools/ftfuzzer/runinput.cc +++ b/modules/freetype2/src/tools/ftfuzzer/runinput.cc @@ -2,7 +2,7 @@ // // A `main' function for fuzzers like `ftfuzzer.cc'. // -// Copyright 2015-2016 by +// Copyright 2015-2018 by // David Turner, Robert Wilhelm, and Werner Lemberg. // // This file is part of the FreeType project, and may only be used, diff --git a/modules/freetype2/src/tools/glnames.py b/modules/freetype2/src/tools/glnames.py index 3569f06ee..b048d2936 100644 --- a/modules/freetype2/src/tools/glnames.py +++ b/modules/freetype2/src/tools/glnames.py @@ -6,7 +6,7 @@ # -# Copyright 1996-2016 by +# Copyright 1996-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, @@ -151,7 +151,7 @@ mac_standard_names = \ # The list of standard `SID' glyph names. For the official list, # see Annex A of document at # -# http://partners.adobe.com/public/developer/en/font/5176.CFF.pdf . +# https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5176.CFF.pdf . # sid_standard_names = \ [ @@ -4920,7 +4920,7 @@ class StringTable: def dump( self, file ): write = file.write - write( "#ifndef DEFINE_PS_TABLES\n" ) + write( "#ifndef DEFINE_PS_TABLES_DATA\n" ) write( "#ifdef __cplusplus\n" ) write( ' extern "C"\n' ) write( "#else\n" ) @@ -4929,7 +4929,7 @@ class StringTable: write( "#endif\n" ) write( " const char " + self.master_table + "[" + repr( self.total ) + "]\n" ) - write( "#ifdef DEFINE_PS_TABLES\n" ) + write( "#ifdef DEFINE_PS_TABLES_DATA\n" ) write( " =\n" ) write( " {\n" ) @@ -4941,7 +4941,7 @@ class StringTable: write( line ) write( " }\n" ) - write( "#endif /* DEFINE_PS_TABLES */\n" ) + write( "#endif /* DEFINE_PS_TABLES_DATA */\n" ) write( " ;\n\n\n" ) def dump_sublist( self, file, table_name, macro_name, sublist ): @@ -4950,7 +4950,7 @@ class StringTable: write( " /* Values are offsets into the `" + self.master_table + "' table */\n\n" ) - write( "#ifndef DEFINE_PS_TABLES\n" ) + write( "#ifndef DEFINE_PS_TABLES_DATA\n" ) write( "#ifdef __cplusplus\n" ) write( ' extern "C"\n' ) write( "#else\n" ) @@ -4959,7 +4959,7 @@ class StringTable: write( "#endif\n" ) write( " const short " + table_name + "[" + macro_name + "]\n" ) - write( "#ifdef DEFINE_PS_TABLES\n" ) + write( "#ifdef DEFINE_PS_TABLES_DATA\n" ) write( " =\n" ) write( " {\n" ) @@ -4979,7 +4979,7 @@ class StringTable: write( line ) write( "\n" ) write( " }\n" ) - write( "#endif /* DEFINE_PS_TABLES */\n" ) + write( "#endif /* DEFINE_PS_TABLES_DATA */\n" ) write( " ;\n\n\n" ) @@ -5213,7 +5213,7 @@ def dump_encoding( file, encoding_name, encoding_list ): write = file.write write( " /* the following are indices into the SID name table */\n" ) - write( "#ifndef DEFINE_PS_TABLES\n" ) + write( "#ifndef DEFINE_PS_TABLES_DATA\n" ) write( "#ifdef __cplusplus\n" ) write( ' extern "C"\n' ) write( "#else\n" ) @@ -5222,7 +5222,7 @@ def dump_encoding( file, encoding_name, encoding_list ): write( "#endif\n" ) write( " const unsigned short " + encoding_name + "[" + repr( len( encoding_list ) ) + "]\n" ) - write( "#ifdef DEFINE_PS_TABLES\n" ) + write( "#ifdef DEFINE_PS_TABLES_DATA\n" ) write( " =\n" ) write( " {\n" ) @@ -5241,14 +5241,14 @@ def dump_encoding( file, encoding_name, encoding_list ): write( line ) write( "\n" ) write( " }\n" ) - write( "#endif /* DEFINE_PS_TABLES */\n" ) + write( "#endif /* DEFINE_PS_TABLES_DATA */\n" ) write( " ;\n\n\n" ) def dump_array( the_array, write, array_name ): """dumps a given encoding""" - write( "#ifndef DEFINE_PS_TABLES\n" ) + write( "#ifndef DEFINE_PS_TABLES_DATA\n" ) write( "#ifdef __cplusplus\n" ) write( ' extern "C"\n' ) write( "#else\n" ) @@ -5257,7 +5257,7 @@ def dump_array( the_array, write, array_name ): write( "#endif\n" ) write( " const unsigned char " + array_name + "[" + repr( len( the_array ) ) + "L]\n" ) - write( "#ifdef DEFINE_PS_TABLES\n" ) + write( "#ifdef DEFINE_PS_TABLES_DATA\n" ) write( " =\n" ) write( " {\n" ) @@ -5282,7 +5282,7 @@ def dump_array( the_array, write, array_name ): write( line ) write( "\n" ) write( " }\n" ) - write( "#endif /* DEFINE_PS_TABLES */\n" ) + write( "#endif /* DEFINE_PS_TABLES_DATA */\n" ) write( " ;\n\n\n" ) @@ -5293,7 +5293,7 @@ def main(): print __doc__ % sys.argv[0] sys.exit( 1 ) - file = open( sys.argv[1], "w\n" ) + file = open( sys.argv[1], "wb" ) write = file.write count_sid = len( sid_standard_names ) @@ -5318,7 +5318,7 @@ def main(): write( "/* */\n" ) write( "/* PostScript glyph names. */\n" ) write( "/* */\n" ) - write( "/* Copyright 2005-2016 by */\n" ) + write( "/* Copyright 2005-2018 by */\n" ) write( "/* David Turner, Robert Wilhelm, and Werner Lemberg. */\n" ) write( "/* */\n" ) write( "/* This file is part of the FreeType project, and may only be used, */\n" ) @@ -5378,6 +5378,7 @@ def main(): # write the lookup routine now # write( """\ +#ifdef DEFINE_PS_TABLES /* * This function searches the compressed table efficiently. */ @@ -5472,6 +5473,7 @@ def main(): NotFound: return 0; } +#endif /* DEFINE_PS_TABLES */ #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ diff --git a/modules/freetype2/src/tools/update-copyright-year b/modules/freetype2/src/tools/update-copyright-year index f4a323b7c..934f11cf0 100755 --- a/modules/freetype2/src/tools/update-copyright-year +++ b/modules/freetype2/src/tools/update-copyright-year @@ -2,7 +2,7 @@ eval '(exit $?0)' && eval 'exec perl -wS -i "$0" ${1+"$@"}' & eval 'exec perl -wS -i "$0" $argv:q' if 0; -# Copyright 2015-2016 by +# Copyright 2015-2018 by # Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/truetype/Jamfile b/modules/freetype2/src/truetype/Jamfile index ecbb2dbdd..e321fba14 100644 --- a/modules/freetype2/src/truetype/Jamfile +++ b/modules/freetype2/src/truetype/Jamfile @@ -1,6 +1,6 @@ # FreeType 2 src/truetype Jamfile # -# Copyright 2001-2016 by +# Copyright 2001-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/truetype/module.mk b/modules/freetype2/src/truetype/module.mk index 80c9832b2..16bc9c8b2 100644 --- a/modules/freetype2/src/truetype/module.mk +++ b/modules/freetype2/src/truetype/module.mk @@ -3,7 +3,7 @@ # -# Copyright 1996-2016 by +# Copyright 1996-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/truetype/rules.mk b/modules/freetype2/src/truetype/rules.mk index 3bf7cf770..e16113f12 100644 --- a/modules/freetype2/src/truetype/rules.mk +++ b/modules/freetype2/src/truetype/rules.mk @@ -3,7 +3,7 @@ # -# Copyright 1996-2016 by +# Copyright 1996-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/truetype/truetype.c b/modules/freetype2/src/truetype/truetype.c index 23e2ea00a..484370975 100644 --- a/modules/freetype2/src/truetype/truetype.c +++ b/modules/freetype2/src/truetype/truetype.c @@ -4,7 +4,7 @@ /* */ /* FreeType TrueType driver component (body only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,22 +17,16 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT - #include <ft2build.h> -#include "ttpic.c" + #include "ttdriver.c" /* driver interface */ -#include "ttpload.c" /* tables loader */ #include "ttgload.c" /* glyph loader */ -#include "ttobjs.c" /* object manager */ - -#ifdef TT_USE_BYTECODE_INTERPRETER +#include "ttgxvar.c" /* gx distortable font */ #include "ttinterp.c" +#include "ttobjs.c" /* object manager */ +#include "ttpic.c" +#include "ttpload.c" /* tables loader */ #include "ttsubpix.c" -#endif - -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT -#include "ttgxvar.c" /* gx distortable font */ -#endif /* END */ diff --git a/modules/freetype2/src/truetype/ttdriver.c b/modules/freetype2/src/truetype/ttdriver.c index af8b205e3..820cafbb8 100644 --- a/modules/freetype2/src/truetype/ttdriver.c +++ b/modules/freetype2/src/truetype/ttdriver.c @@ -4,7 +4,7 @@ /* */ /* TrueType font driver implementation (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -31,7 +31,7 @@ #include FT_SERVICE_TRUETYPE_ENGINE_H #include FT_SERVICE_TRUETYPE_GLYF_H #include FT_SERVICE_PROPERTIES_H -#include FT_TRUETYPE_DRIVER_H +#include FT_DRIVER_H #include "ttdriver.h" #include "ttgload.h" @@ -233,8 +233,8 @@ { #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT /* no fast retrieval for blended MM fonts without VVAR table */ - if ( !face->is_default_instance && - !( face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ) + if ( ( FT_IS_NAMED_INSTANCE( ttface ) || FT_IS_VARIATION( ttface ) ) && + !( face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ) return FT_THROW( Unimplemented_Feature ); #endif @@ -253,8 +253,8 @@ { #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT /* no fast retrieval for blended MM fonts without HVAR table */ - if ( !face->is_default_instance && - !( face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ) + if ( ( FT_IS_NAMED_INSTANCE( ttface ) || FT_IS_VARIATION( ttface ) ) && + !( face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ) return FT_THROW( Unimplemented_Feature ); #endif @@ -304,15 +304,17 @@ /* use the scaled metrics, even when tt_size_reset fails */ FT_Select_Metrics( size->face, strike_index ); - tt_size_reset( ttsize ); /* ignore return value */ + tt_size_reset( ttsize, 0 ); /* ignore return value */ } else { - SFNT_Service sfnt = (SFNT_Service)ttface->sfnt; - FT_Size_Metrics* metrics = &size->metrics; + SFNT_Service sfnt = (SFNT_Service)ttface->sfnt; + FT_Size_Metrics* size_metrics = &size->metrics; - error = sfnt->load_strike_metrics( ttface, strike_index, metrics ); + error = sfnt->load_strike_metrics( ttface, + strike_index, + size_metrics ); if ( error ) ttsize->strike_index = 0xFFFFFFFFUL; } @@ -354,15 +356,16 @@ if ( FT_IS_SCALABLE( size->face ) ) { - error = tt_size_reset( ttsize ); - ttsize->root.metrics = ttsize->metrics; + error = tt_size_reset( ttsize, 0 ); #ifdef TT_USE_BYTECODE_INTERPRETER /* for the `MPS' bytecode instruction we need the point size */ + if ( !error ) { - FT_UInt resolution = ttsize->metrics.x_ppem > ttsize->metrics.y_ppem - ? req->horiResolution - : req->vertResolution; + FT_UInt resolution = + ttsize->metrics->x_ppem > ttsize->metrics->y_ppem + ? req->horiResolution + : req->vertResolution; /* if we don't have a resolution value, assume 72dpi */ @@ -456,6 +459,11 @@ load_flags |= FT_LOAD_NO_HINTING; } + /* use hinted metrics only if we load a glyph with hinting */ + size->metrics = ( load_flags & FT_LOAD_NO_HINTING ) + ? &ttsize->metrics + : &size->hinted_metrics; + /* now load the glyph outline if necessary */ error = TT_Load_Glyph( size, slot, glyph_index, load_flags ); @@ -490,6 +498,7 @@ (FT_Get_MM_Var_Func) TT_Get_MM_Var, /* get_mm_var */ (FT_Set_Var_Design_Func)TT_Set_Var_Design, /* set_var_design */ (FT_Get_Var_Design_Func)TT_Get_Var_Design, /* get_var_design */ + (FT_Set_Instance_Func) TT_Set_Named_Instance, /* set_instance */ (FT_Get_Var_Blend_Func) tt_get_var_blend, /* get_var_blend */ (FT_Done_Blend_Func) tt_done_blend /* done_blend */ @@ -502,12 +511,12 @@ (FT_LSB_Adjust_Func) NULL, /* lsb_adjust */ (FT_RSB_Adjust_Func) NULL, /* rsb_adjust */ - (FT_VAdvance_Adjust_Func)NULL, /* vadvance_adjust */ + (FT_VAdvance_Adjust_Func)tt_vadvance_adjust, /* vadvance_adjust */ (FT_TSB_Adjust_Func) NULL, /* tsb_adjust */ (FT_BSB_Adjust_Func) NULL, /* bsb_adjust */ (FT_VOrg_Adjust_Func) NULL, /* vorg_adjust */ - (FT_Metrics_Adjust_Func) NULL /* metrics_adjust */ + (FT_Metrics_Adjust_Func) tt_apply_mvar /* metrics_adjust */ ) #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ diff --git a/modules/freetype2/src/truetype/ttdriver.h b/modules/freetype2/src/truetype/ttdriver.h index 74392bbd0..707aa68ed 100644 --- a/modules/freetype2/src/truetype/ttdriver.h +++ b/modules/freetype2/src/truetype/ttdriver.h @@ -4,7 +4,7 @@ /* */ /* High-level TrueType driver interface (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/truetype/tterrors.h b/modules/freetype2/src/truetype/tterrors.h index 895989f5f..88bca3a04 100644 --- a/modules/freetype2/src/truetype/tterrors.h +++ b/modules/freetype2/src/truetype/tterrors.h @@ -4,7 +4,7 @@ /* */ /* TrueType error codes (specification only). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/truetype/ttgload.c b/modules/freetype2/src/truetype/ttgload.c index a0cdfc890..39d9c3f73 100644 --- a/modules/freetype2/src/truetype/ttgload.c +++ b/modules/freetype2/src/truetype/ttgload.c @@ -4,7 +4,7 @@ /* */ /* TrueType Glyph Loader (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -18,12 +18,13 @@ #include <ft2build.h> #include FT_INTERNAL_DEBUG_H +#include FT_CONFIG_CONFIG_H #include FT_INTERNAL_CALC_H #include FT_INTERNAL_STREAM_H #include FT_INTERNAL_SFNT_H #include FT_TRUETYPE_TAGS_H #include FT_OUTLINE_H -#include FT_TRUETYPE_DRIVER_H +#include FT_DRIVER_H #include FT_LIST_H #include "ttgload.h" @@ -86,7 +87,7 @@ /*************************************************************************/ /* */ /* Return the vertical metrics in font units for a given glyph. */ - /* See macro `TT_LOADER_SET_PP' below for explanations. */ + /* See function `tt_loader_set_pp' below for explanations. */ /* */ FT_LOCAL_DEF( void ) TT_Get_VMetrics( TT_Face face, @@ -162,7 +163,7 @@ /* This may not be the right place for this, but it works... */ /* Note that we have to unconditionally load the tweaks since */ /* it is possible that glyphs individually switch ClearType's */ - /* backwards compatibility mode on and off. */ + /* backward compatibility mode on and off. */ sph_set_tweaks( loader, glyph_index ); } #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ @@ -194,39 +195,39 @@ if ( face->root.internal->incremental_interface && face->root.internal->incremental_interface->funcs->get_glyph_metrics ) { - FT_Incremental_MetricsRec metrics; + FT_Incremental_MetricsRec incr_metrics; FT_Error error; - metrics.bearing_x = loader->left_bearing; - metrics.bearing_y = 0; - metrics.advance = loader->advance; - metrics.advance_v = 0; + incr_metrics.bearing_x = loader->left_bearing; + incr_metrics.bearing_y = 0; + incr_metrics.advance = loader->advance; + incr_metrics.advance_v = 0; error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( face->root.internal->incremental_interface->object, - glyph_index, FALSE, &metrics ); + glyph_index, FALSE, &incr_metrics ); if ( error ) goto Exit; - left_bearing = (FT_Short)metrics.bearing_x; - advance_width = (FT_UShort)metrics.advance; + left_bearing = (FT_Short)incr_metrics.bearing_x; + advance_width = (FT_UShort)incr_metrics.advance; #if 0 /* GWW: Do I do the same for vertical metrics? */ - metrics.bearing_x = 0; - metrics.bearing_y = loader->top_bearing; - metrics.advance = loader->vadvance; + incr_metrics.bearing_x = 0; + incr_metrics.bearing_y = loader->top_bearing; + incr_metrics.advance = loader->vadvance; error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( face->root.internal->incremental_interface->object, - glyph_index, TRUE, &metrics ); + glyph_index, TRUE, &incr_metrics ); if ( error ) goto Exit; - top_bearing = (FT_Short)metrics.bearing_y; - advance_height = (FT_UShort)metrics.advance; + top_bearing = (FT_Short)incr_metrics.bearing_y; + advance_height = (FT_UShort)incr_metrics.advance; #endif /* 0 */ @@ -332,7 +333,6 @@ FT_Outline* outline; FT_UShort n_ins; FT_Int n_points; - FT_ULong tmp; FT_Byte *flag, *flag_limit; FT_Byte c, count; @@ -398,18 +398,21 @@ FT_TRACE5(( " Instructions size: %u\n", n_ins )); - /* check it */ - if ( ( limit - p ) < n_ins ) - { - FT_TRACE0(( "TT_Load_Simple_Glyph: instruction count mismatch\n" )); - error = FT_THROW( Too_Many_Hints ); - goto Fail; - } - #ifdef TT_USE_BYTECODE_INTERPRETER if ( IS_HINTED( load->load_flags ) ) { + FT_ULong tmp; + + + /* check instructions size */ + if ( ( limit - p ) < n_ins ) + { + FT_TRACE1(( "TT_Load_Simple_Glyph: instruction count mismatch\n" )); + error = FT_THROW( Too_Many_Hints ); + goto Fail; + } + /* we don't trust `maxSizeOfInstructions' in the `maxp' table */ /* and thus update the bytecode array size by ourselves */ @@ -661,7 +664,52 @@ } while ( subglyph->flags & MORE_COMPONENTS ); gloader->current.num_subglyphs = num_subglyphs; - FT_TRACE5(( " %d components\n", num_subglyphs )); + FT_TRACE5(( " %d component%s\n", + num_subglyphs, + num_subglyphs > 1 ? "s" : "" )); + +#ifdef FT_DEBUG_LEVEL_TRACE + { + FT_UInt i; + + + subglyph = gloader->current.subglyphs; + + for ( i = 0; i < num_subglyphs; i++ ) + { + if ( num_subglyphs > 1 ) + FT_TRACE7(( " subglyph %d:\n", i )); + + FT_TRACE7(( " glyph index: %d\n", subglyph->index )); + + if ( subglyph->flags & ARGS_ARE_XY_VALUES ) + FT_TRACE7(( " offset: x=%d, y=%d\n", + subglyph->arg1, + subglyph->arg2 )); + else + FT_TRACE7(( " matching points: base=%d, component=%d\n", + subglyph->arg1, + subglyph->arg2 )); + + if ( subglyph->flags & WE_HAVE_A_SCALE ) + FT_TRACE7(( " scaling: %f\n", + subglyph->transform.xx / 65536.0 )); + else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE ) + FT_TRACE7(( " scaling: x=%f, y=%f\n", + subglyph->transform.xx / 65536.0, + subglyph->transform.yy / 65536.0 )); + else if ( subglyph->flags & WE_HAVE_A_2X2 ) + FT_TRACE7(( " scaling: xx=%f, yx=%f\n" + " xy=%f, yy=%f\n", + subglyph->transform.xx / 65536.0, + subglyph->transform.yx / 65536.0, + subglyph->transform.xy / 65536.0, + subglyph->transform.yy / 65536.0 )); + + subglyph++; + } + } +#endif /* FT_DEBUG_LEVEL_TRACE */ #ifdef TT_USE_BYTECODE_INTERPRETER @@ -753,7 +801,7 @@ { FT_TRACE1(( "TT_Hint_Glyph: too long instructions" )); FT_TRACE1(( " (0x%lx byte) is truncated\n", - loader->glyph->control_len )); + loader->glyph->control_len )); } n_ins = loader->glyph->control_len; @@ -775,8 +823,8 @@ } else { - loader->exec->metrics.x_scale = loader->size->metrics.x_scale; - loader->exec->metrics.y_scale = loader->size->metrics.y_scale; + loader->exec->metrics.x_scale = loader->size->metrics->x_scale; + loader->exec->metrics.y_scale = loader->size->metrics->y_scale; } #endif @@ -818,11 +866,11 @@ #endif #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - /* Save possibly modified glyph phantom points unless in v40 backwards */ + /* Save possibly modified glyph phantom points unless in v40 backward */ /* compatibility mode, where no movement on the x axis means no reason */ /* to change bearings or advance widths. */ if ( !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && - !loader->exec->backwards_compatibility ) ) + loader->exec->backward_compatibility ) ) { #endif loader->pp1 = zone->cur[zone->n_points - 4]; @@ -886,7 +934,8 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - if ( loader->face->doblend && !loader->face->is_default_instance ) + if ( FT_IS_NAMED_INSTANCE( FT_FACE( loader->face ) ) || + FT_IS_VARIATION( FT_FACE( loader->face ) ) ) { /* Deltas apply to the unscaled data. */ error = TT_Vary_Apply_Glyph_Deltas( loader->face, @@ -923,7 +972,7 @@ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face ); FT_String* family = face->root.family_name; - FT_UInt ppem = loader->size->metrics.x_ppem; + FT_UInt ppem = loader->size->metrics->x_ppem; FT_String* style = face->root.style_name; FT_UInt x_scale_factor = 1000; #endif @@ -952,9 +1001,9 @@ if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 || x_scale_factor != 1000 ) { - x_scale = FT_MulDiv( loader->size->metrics.x_scale, + x_scale = FT_MulDiv( loader->size->metrics->x_scale, (FT_Long)x_scale_factor, 1000 ); - y_scale = loader->size->metrics.y_scale; + y_scale = loader->size->metrics->y_scale; /* compensate for any scaling by de/emboldening; */ /* the amount was determined via experimentation */ @@ -974,8 +1023,8 @@ /* scale the glyph */ if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) { - x_scale = loader->size->metrics.x_scale; - y_scale = loader->size->metrics.y_scale; + x_scale = loader->size->metrics->x_scale; + y_scale = loader->size->metrics->y_scale; do_scale = TRUE; } @@ -988,9 +1037,24 @@ vec->x = FT_MulFix( vec->x, x_scale ); vec->y = FT_MulFix( vec->y, y_scale ); } + } +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + /* if we have a HVAR table, `pp1' and/or `pp2' are already adjusted */ + if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) || + !IS_HINTED( loader->load_flags ) ) +#endif + { loader->pp1 = outline->points[n_points - 4]; loader->pp2 = outline->points[n_points - 3]; + } + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + /* if we have a VVAR table, `pp3' and/or `pp4' are already adjusted */ + if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) || + !IS_HINTED( loader->load_flags ) ) +#endif + { loader->pp3 = outline->points[n_points - 2]; loader->pp4 = outline->points[n_points - 1]; } @@ -1133,8 +1197,8 @@ if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) ) { - FT_Fixed x_scale = loader->size->metrics.x_scale; - FT_Fixed y_scale = loader->size->metrics.y_scale; + FT_Fixed x_scale = loader->size->metrics->x_scale; + FT_Fixed y_scale = loader->size->metrics->y_scale; x = FT_MulFix( x, x_scale ); @@ -1142,8 +1206,28 @@ if ( subglyph->flags & ROUND_XY_TO_GRID ) { - x = FT_PIX_ROUND( x ); - y = FT_PIX_ROUND( y ); + TT_Face face = loader->face; + TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face ); + + + if ( IS_HINTED( loader->load_flags ) ) + { + /* + * We round the horizontal offset only if there is hinting along + * the x axis; this corresponds to integer advance width values. + * + * Theoretically, a glyph's bytecode can toggle ClearType's + * `backward compatibility' mode, which would allow modification + * of the advance width. In reality, however, applications + * neither allow nor expect modified advance widths if subpixel + * rendering is active. + * + */ + if ( driver->interpreter_version == TT_INTERPRETER_VERSION_35 ) + x = FT_PIX_ROUND( x ); + + y = FT_PIX_ROUND( y ); + } } } } @@ -1356,6 +1440,7 @@ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( loader->face ); #endif + #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) { @@ -1392,7 +1477,7 @@ /* a utility function to retrieve i-th node from given FT_List */ static FT_ListNode ft_list_get_node_at( FT_List list, - FT_UInt index ) + FT_UInt idx ) { FT_ListNode cur; @@ -1402,10 +1487,10 @@ for ( cur = list->head; cur; cur = cur->next ) { - if ( !index ) + if ( !idx ) return cur; - index--; + idx--; } return NULL; @@ -1467,8 +1552,8 @@ if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) { - x_scale = loader->size->metrics.x_scale; - y_scale = loader->size->metrics.y_scale; + x_scale = loader->size->metrics->x_scale; + y_scale = loader->size->metrics->y_scale; } else { @@ -1574,7 +1659,8 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - if ( loader->face->doblend && !loader->face->is_default_instance ) + if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) || + FT_IS_VARIATION( FT_FACE( face ) ) ) { /* a small outline structure with four elements for */ /* communication with `TT_Vary_Apply_Glyph_Deltas' */ @@ -1683,7 +1769,7 @@ /***********************************************************************/ /* otherwise, load a composite! */ - else if ( loader->n_contours == -1 ) + else if ( loader->n_contours < 0 ) { FT_Memory memory = face->root.memory; @@ -1694,6 +1780,9 @@ FT_ListNode node, node2; + /* normalize the `n_contours' value */ + loader->n_contours = -1; + /* * We store the glyph index directly in the `node->data' pointer, * following the glib solution (cf. macro `GUINT_TO_POINTER') with a @@ -1705,11 +1794,11 @@ /* clear the nodes filled by sibling chains */ node = ft_list_get_node_at( &loader->composites, recurse_count ); for ( node2 = node; node2; node2 = node2->next ) - node2->data = (void*)ULONG_MAX; + node2->data = (void*)FT_ULONG_MAX; /* check whether we already have a composite glyph with this index */ if ( FT_List_Find( &loader->composites, - (void*)(unsigned long)glyph_index ) ) + FT_UINT_TO_POINTER( glyph_index ) ) ) { FT_TRACE1(( "TT_Load_Composite_Glyph:" " infinite recursion detected\n" )); @@ -1718,13 +1807,13 @@ } else if ( node ) - node->data = (void*)(unsigned long)glyph_index; + node->data = FT_UINT_TO_POINTER( glyph_index ); else { if ( FT_NEW( node ) ) goto Exit; - node->data = (void*)(unsigned long)glyph_index; + node->data = FT_UINT_TO_POINTER( glyph_index ); FT_List_Add( &loader->composites, node ); } @@ -1745,7 +1834,8 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - if ( face->doblend && !face->is_default_instance ) + if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) || + FT_IS_VARIATION( FT_FACE( face ) ) ) { short i, limit; FT_SubGlyph subglyph; @@ -1988,12 +2078,6 @@ } } } - else - { - /* invalid composite count (negative but not -1) */ - error = FT_THROW( Invalid_Outline ); - goto Exit; - } /***********************************************************************/ /***********************************************************************/ @@ -2035,7 +2119,7 @@ y_scale = 0x10000L; if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) - y_scale = size->root.metrics.y_scale; + y_scale = size->metrics->y_scale; if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE ) FT_Outline_Get_CBox( &glyph->outline, &bbox ); @@ -2050,24 +2134,24 @@ glyph->metrics.horiBearingY = bbox.yMax; glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x; - /* Adjust advance width to the value contained in the hdmx table */ - /* unless FT_LOAD_COMPUTE_METRICS is set or backwards compatibility */ - /* mode of the v40 interpreter is active. See `ttinterp.h' for */ - /* details on backwards compatibility mode. */ + /* Adjust advance width to the value contained in the hdmx table */ + /* unless FT_LOAD_COMPUTE_METRICS is set or backward compatibility */ + /* mode of the v40 interpreter is active. See `ttinterp.h' for */ + /* details on backward compatibility mode. */ if ( #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && - ( loader->exec && loader->exec->backwards_compatibility ) ) && + !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && + ( loader->exec && loader->exec->backward_compatibility ) ) && #endif - !face->postscript.isFixedPitch && - IS_HINTED( loader->load_flags ) && - !( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) ) + !face->postscript.isFixedPitch && + IS_HINTED( loader->load_flags ) && + !( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) ) { FT_Byte* widthp; widthp = tt_face_get_device_metrics( face, - size->root.metrics.x_ppem, + size->metrics->x_ppem, glyph_index ); #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY @@ -2097,8 +2181,8 @@ } /* set glyph dimensions */ - glyph->metrics.width = bbox.xMax - bbox.xMin; - glyph->metrics.height = bbox.yMax - bbox.yMin; + glyph->metrics.width = SUB_LONG( bbox.xMax, bbox.xMin ); + glyph->metrics.height = SUB_LONG( bbox.yMax, bbox.yMin ); /* Now take care of vertical metrics. In the case where there is */ /* no vertical information within the font (relatively common), */ @@ -2134,7 +2218,8 @@ /* table in the font. Otherwise, we use the */ /* values defined in the horizontal header. */ - height = (FT_Short)FT_DivFix( bbox.yMax - bbox.yMin, + height = (FT_Short)FT_DivFix( SUB_LONG( bbox.yMax, + bbox.yMin ), y_scale ); if ( face->os2.version != 0xFFFFU ) advance = (FT_Pos)( face->os2.sTypoAscender - @@ -2149,7 +2234,7 @@ #ifdef FT_CONFIG_OPTION_INCREMENTAL { FT_Incremental_InterfaceRec* incr; - FT_Incremental_MetricsRec metrics; + FT_Incremental_MetricsRec incr_metrics; FT_Error error; @@ -2159,19 +2244,19 @@ /* overriding metrics for this glyph. */ if ( incr && incr->funcs->get_glyph_metrics ) { - metrics.bearing_x = 0; - metrics.bearing_y = top; - metrics.advance = advance; + incr_metrics.bearing_x = 0; + incr_metrics.bearing_y = top; + incr_metrics.advance = advance; error = incr->funcs->get_glyph_metrics( incr->object, glyph_index, TRUE, - &metrics ); + &incr_metrics ); if ( error ) return error; - top = metrics.bearing_y; - advance = metrics.advance; + top = incr_metrics.bearing_y; + advance = incr_metrics.advance; } } @@ -2213,7 +2298,7 @@ SFNT_Service sfnt; FT_Stream stream; FT_Error error; - TT_SBit_MetricsRec metrics; + TT_SBit_MetricsRec sbit_metrics; face = (TT_Face)glyph->face; @@ -2226,34 +2311,34 @@ (FT_UInt)load_flags, stream, &glyph->bitmap, - &metrics ); + &sbit_metrics ); if ( !error ) { glyph->outline.n_points = 0; glyph->outline.n_contours = 0; - glyph->metrics.width = (FT_Pos)metrics.width * 64; - glyph->metrics.height = (FT_Pos)metrics.height * 64; + glyph->metrics.width = (FT_Pos)sbit_metrics.width * 64; + glyph->metrics.height = (FT_Pos)sbit_metrics.height * 64; - glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX * 64; - glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY * 64; - glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance * 64; + glyph->metrics.horiBearingX = (FT_Pos)sbit_metrics.horiBearingX * 64; + glyph->metrics.horiBearingY = (FT_Pos)sbit_metrics.horiBearingY * 64; + glyph->metrics.horiAdvance = (FT_Pos)sbit_metrics.horiAdvance * 64; - glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX * 64; - glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY * 64; - glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance * 64; + glyph->metrics.vertBearingX = (FT_Pos)sbit_metrics.vertBearingX * 64; + glyph->metrics.vertBearingY = (FT_Pos)sbit_metrics.vertBearingY * 64; + glyph->metrics.vertAdvance = (FT_Pos)sbit_metrics.vertAdvance * 64; glyph->format = FT_GLYPH_FORMAT_BITMAP; if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) { - glyph->bitmap_left = metrics.vertBearingX; - glyph->bitmap_top = metrics.vertBearingY; + glyph->bitmap_left = sbit_metrics.vertBearingX; + glyph->bitmap_top = sbit_metrics.vertBearingY; } else { - glyph->bitmap_left = metrics.horiBearingX; - glyph->bitmap_top = metrics.horiBearingY; + glyph->bitmap_left = sbit_metrics.horiBearingX; + glyph->bitmap_top = sbit_metrics.horiBearingY; } } @@ -2270,17 +2355,17 @@ FT_Int32 load_flags, FT_Bool glyf_table_only ) { - FT_Error error; - TT_Face face; FT_Stream stream; + #ifdef TT_USE_BYTECODE_INTERPRETER + FT_Error error; FT_Bool pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC ); -#endif #if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \ defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( (TT_Face)glyph->face ); #endif +#endif face = (TT_Face)glyph->face; @@ -2336,13 +2421,19 @@ #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 ) { - subpixel_hinting_lean = TRUE; - grayscale_cleartype = !FT_BOOL( load_flags & - FT_LOAD_TARGET_LCD || - load_flags & - FT_LOAD_TARGET_LCD_V ); - exec->vertical_lcd_lean = FT_BOOL( load_flags & - FT_LOAD_TARGET_LCD_V ); + subpixel_hinting_lean = + FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != + FT_RENDER_MODE_MONO ); + grayscale_cleartype = + FT_BOOL( subpixel_hinting_lean && + !( ( load_flags & + FT_LOAD_TARGET_LCD ) || + ( load_flags & + FT_LOAD_TARGET_LCD_V ) ) ); + exec->vertical_lcd_lean = + FT_BOOL( subpixel_hinting_lean && + ( load_flags & + FT_LOAD_TARGET_LCD_V ) ); } else { @@ -2602,7 +2693,8 @@ TT_LoaderRec loader; #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT -#define IS_DEFAULT_INSTANCE ( ( (TT_Face)glyph->face )->is_default_instance ) +#define IS_DEFAULT_INSTANCE ( !( FT_IS_NAMED_INSTANCE( glyph->face ) || \ + FT_IS_VARIATION( glyph->face ) ) ) #else #define IS_DEFAULT_INSTANCE 1 #endif @@ -2617,8 +2709,73 @@ ( load_flags & FT_LOAD_NO_BITMAP ) == 0 && IS_DEFAULT_INSTANCE ) { + FT_Fixed x_scale = size->root.metrics.x_scale; + FT_Fixed y_scale = size->root.metrics.y_scale; + + error = load_sbit_image( size, glyph, glyph_index, load_flags ); - if ( !error ) + if ( FT_ERR_EQ( error, Missing_Bitmap ) ) + { + /* the bitmap strike is incomplete and misses the requested glyph; */ + /* if we have a bitmap-only font, return an empty glyph */ + if ( !FT_IS_SCALABLE( glyph->face ) ) + { + TT_Face face = (TT_Face)glyph->face; + + FT_Short left_bearing = 0; + FT_Short top_bearing = 0; + + FT_UShort advance_width = 0; + FT_UShort advance_height = 0; + + + /* to return an empty glyph, however, we need metrics data */ + /* from the `hmtx' (or `vmtx') table; the assumption is that */ + /* empty glyphs are missing intentionally, representing */ + /* whitespace - not having at least horizontal metrics is */ + /* thus considered an error */ + if ( !face->horz_metrics_size ) + return error; + + /* we now construct an empty bitmap glyph */ + TT_Get_HMetrics( face, glyph_index, + &left_bearing, + &advance_width ); + TT_Get_VMetrics( face, glyph_index, + 0, + &top_bearing, + &advance_height ); + + glyph->outline.n_points = 0; + glyph->outline.n_contours = 0; + + glyph->metrics.width = 0; + glyph->metrics.height = 0; + + glyph->metrics.horiBearingX = FT_MulFix( left_bearing, x_scale ); + glyph->metrics.horiBearingY = 0; + glyph->metrics.horiAdvance = FT_MulFix( advance_width, x_scale ); + + glyph->metrics.vertBearingX = 0; + glyph->metrics.vertBearingY = FT_MulFix( top_bearing, y_scale ); + glyph->metrics.vertAdvance = FT_MulFix( advance_height, y_scale ); + + glyph->format = FT_GLYPH_FORMAT_BITMAP; + glyph->bitmap.pixel_mode = FT_PIXEL_MODE_MONO; + + glyph->bitmap_left = 0; + glyph->bitmap_top = 0; + + return FT_Err_Ok; + } + } + else if ( error ) + { + /* return error if font is not scalable */ + if ( !FT_IS_SCALABLE( glyph->face ) ) + return error; + } + else { if ( FT_IS_SCALABLE( glyph->face ) ) { @@ -2632,13 +2789,11 @@ /* sanity checks: if `xxxAdvance' in the sbit metric */ /* structure isn't set, use `linearXXXAdvance' */ if ( !glyph->metrics.horiAdvance && glyph->linearHoriAdvance ) - glyph->metrics.horiAdvance = - FT_MulFix( glyph->linearHoriAdvance, - size->root.metrics.x_scale ); + glyph->metrics.horiAdvance = FT_MulFix( glyph->linearHoriAdvance, + x_scale ); if ( !glyph->metrics.vertAdvance && glyph->linearVertAdvance ) - glyph->metrics.vertAdvance = - FT_MulFix( glyph->linearVertAdvance, - size->root.metrics.y_scale ); + glyph->metrics.vertAdvance = FT_MulFix( glyph->linearVertAdvance, + y_scale ); } return FT_Err_Ok; @@ -2649,14 +2804,20 @@ /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */ if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid ) - return FT_THROW( Invalid_Size_Handle ); + { + error = FT_THROW( Invalid_Size_Handle ); + goto Exit; + } if ( load_flags & FT_LOAD_SBITS_ONLY ) - return FT_THROW( Invalid_Argument ); + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } error = tt_loader_init( &loader, size, glyph, load_flags, FALSE ); if ( error ) - return error; + goto Exit; glyph->format = FT_GLYPH_FORMAT_OUTLINE; glyph->num_subglyphs = 0; @@ -2728,9 +2889,16 @@ /* TrueType glyphs at all sizes using the bytecode interpreter. */ /* */ if ( !( load_flags & FT_LOAD_NO_SCALE ) && - size->root.metrics.y_ppem < 24 ) + size->metrics->y_ppem < 24 ) glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION; + Exit: +#ifdef FT_DEBUG_LEVEL_TRACE + if ( error ) + FT_TRACE1(( " failed (error code 0x%x)\n", + error )); +#endif + return error; } diff --git a/modules/freetype2/src/truetype/ttgload.h b/modules/freetype2/src/truetype/ttgload.h index bfa29e4ff..d237cfd28 100644 --- a/modules/freetype2/src/truetype/ttgload.h +++ b/modules/freetype2/src/truetype/ttgload.h @@ -4,7 +4,7 @@ /* */ /* TrueType Glyph Loader (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/truetype/ttgxvar.c b/modules/freetype2/src/truetype/ttgxvar.c index cf4f7b17a..29ab2a4ef 100644 --- a/modules/freetype2/src/truetype/ttgxvar.c +++ b/modules/freetype2/src/truetype/ttgxvar.c @@ -4,7 +4,7 @@ /* */ /* TrueType GX Font Variation loader */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -22,10 +22,6 @@ /* */ /* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6[fgca]var.html */ /* */ - /* The documentation for `fvar' is inconsistent. At one point it says */ - /* that `countSizePairs' should be 3, at another point 2. It should */ - /* be 2. */ - /* */ /* The documentation for `gvar' is not intelligible; `cvar' refers you */ /* to `gvar' and is thus also incomprehensible. */ /* */ @@ -49,7 +45,9 @@ #include FT_INTERNAL_STREAM_H #include FT_INTERNAL_SFNT_H #include FT_TRUETYPE_TAGS_H +#include FT_TRUETYPE_IDS_H #include FT_MULTIPLE_MASTERS_H +#include FT_LIST_H #include "ttpload.h" #include "ttgxvar.h" @@ -62,8 +60,11 @@ #define FT_Stream_FTell( stream ) \ (FT_ULong)( (stream)->cursor - (stream)->base ) -#define FT_Stream_SeekSet( stream, off ) \ - ( (stream)->cursor = (stream)->base + (off) ) +#define FT_Stream_SeekSet( stream, off ) \ + (stream)->cursor = \ + ( (off) < (FT_ULong)( (stream)->limit - (stream)->base ) ) \ + ? (stream)->base + (off) \ + : (stream)->limit /*************************************************************************/ @@ -322,7 +323,7 @@ FT_TRACE2(( "AVAR " )); - blend->avar_checked = TRUE; + blend->avar_loaded = TRUE; error = face->goto_table( face, TTAG_avar, stream, &table_len ); if ( error ) { @@ -346,7 +347,7 @@ if ( axisCount != (FT_Long)blend->mmvar->num_axis ) { - FT_TRACE2(( "ft_var_load_avar: number of axes in `avar' and `cvar'\n" + FT_TRACE2(( "ft_var_load_avar: number of axes in `avar' and `fvar'\n" " table are different\n" )); goto Exit; } @@ -394,361 +395,309 @@ /* some macros we need */ - #define FT_FIXED_ONE ( (FT_Fixed)0x10000 ) +#define FT_FIXED_ONE ( (FT_Fixed)0x10000 ) - #define FT_fdot14ToFixed( x ) \ - ( ( (FT_Fixed)( (FT_Int16)(x) ) ) << 2 ) - #define FT_intToFixed( i ) \ - ( (FT_Fixed)( (FT_UInt32)(i) << 16 ) ) - #define FT_fixedToInt( x ) \ - ( (FT_Short)( ( (FT_UInt32)(x) + 0x8000U ) >> 16 ) ) +#define FT_fdot14ToFixed( x ) \ + ( (FT_Fixed)( (FT_ULong)(x) << 2 ) ) +#define FT_intToFixed( i ) \ + ( (FT_Fixed)( (FT_ULong)(i) << 16 ) ) +#define FT_fixedToInt( x ) \ + ( (FT_Short)( ( (FT_UInt32)(x) + 0x8000U ) >> 16 ) ) - /*************************************************************************/ - /* */ - /* <Function> */ - /* ft_var_load_hvar */ - /* */ - /* <Description> */ - /* Parse the `HVAR' table and set `blend->hvar_loaded' to TRUE. */ - /* */ - /* On success, `blend->hvar_checked' is set to TRUE. */ - /* */ - /* Some memory may remain allocated on error; it is always freed in */ - /* `tt_done_blend', however. */ - /* */ - /* <InOut> */ - /* face :: The font face. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ static FT_Error - ft_var_load_hvar( TT_Face face ) + ft_var_load_item_variation_store( TT_Face face, + FT_ULong offset, + GX_ItemVarStore itemStore ) { FT_Stream stream = FT_FACE_STREAM( face ); FT_Memory memory = stream->memory; - GX_Blend blend = face->blend; - FT_Error error; - FT_UShort majorVersion; - FT_ULong table_len; - FT_ULong table_offset; - FT_ULong store_offset; + FT_UShort format; + FT_ULong region_offset; + FT_UInt i, j, k; + FT_UInt shortDeltaCount; - FT_ULong* dataOffsetArray = NULL; + GX_Blend blend = face->blend; + GX_ItemVarData varData; + FT_ULong* dataOffsetArray = NULL; - blend->hvar_loaded = TRUE; - FT_TRACE2(( "HVAR " )); + if ( FT_STREAM_SEEK( offset ) || + FT_READ_USHORT( format ) ) + goto Exit; - error = face->goto_table( face, TTAG_HVAR, stream, &table_len ); - if ( error ) + if ( format != 1 ) { - FT_TRACE2(( "is missing\n" )); + FT_TRACE2(( "ft_var_load_item_variation_store: bad store format %d\n", + format )); + error = FT_THROW( Invalid_Table ); goto Exit; } - table_offset = FT_STREAM_POS(); - - /* skip minor version */ - if ( FT_READ_USHORT( majorVersion ) || - FT_STREAM_SKIP( 2 ) ) + /* read top level fields */ + if ( FT_READ_ULONG( region_offset ) || + FT_READ_USHORT( itemStore->dataCount ) ) goto Exit; - if ( majorVersion != 1 ) + + /* we need at least one entry in `itemStore->varData' */ + if ( !itemStore->dataCount ) { - FT_TRACE2(( "bad table version %d\n", majorVersion )); + FT_TRACE2(( "ft_var_load_item_variation_store: missing varData\n" )); error = FT_THROW( Invalid_Table ); goto Exit; } - /* skip map offset */ - if ( FT_READ_ULONG( store_offset ) || - FT_STREAM_SKIP( 4 ) ) + /* make temporary copy of item variation data offsets; */ + /* we will parse region list first, then come back */ + if ( FT_NEW_ARRAY( dataOffsetArray, itemStore->dataCount ) ) goto Exit; - /* parse item variation store */ + for ( i = 0; i < itemStore->dataCount; i++ ) { - FT_UShort format; - FT_ULong region_offset; - FT_UInt i, j, k; - FT_UInt shortDeltaCount; - - GX_HVStore itemStore; - GX_HVarTable hvarTable; - GX_HVarData hvarData; - - - if ( FT_STREAM_SEEK( table_offset + store_offset ) || - FT_READ_USHORT( format ) ) - goto Exit; - if ( format != 1 ) - { - FT_TRACE2(( "bad store format %d\n", format )); - error = FT_THROW( Invalid_Table ); + if ( FT_READ_ULONG( dataOffsetArray[i] ) ) goto Exit; - } + } - if ( FT_NEW( blend->hvar_table ) ) /* allocate table at top level */ - goto Exit; + /* parse array of region records (region list) */ + if ( FT_STREAM_SEEK( offset + region_offset ) ) + goto Exit; - hvarTable = blend->hvar_table; - itemStore = &hvarTable->itemStore; + if ( FT_READ_USHORT( itemStore->axisCount ) || + FT_READ_USHORT( itemStore->regionCount ) ) + goto Exit; - /* read top level fields */ - if ( FT_READ_ULONG( region_offset ) || - FT_READ_USHORT( itemStore->dataCount ) ) - goto Exit; + if ( itemStore->axisCount != (FT_Long)blend->mmvar->num_axis ) + { + FT_TRACE2(( "ft_var_load_item_variation_store:" + " number of axes in item variation store\n" + " " + " and `fvar' table are different\n" )); + error = FT_THROW( Invalid_Table ); + goto Exit; + } - /* make temporary copy of item variation data offsets; */ - /* we will parse region list first, then come back */ - if ( FT_NEW_ARRAY( dataOffsetArray, itemStore->dataCount ) ) - goto Exit; + if ( FT_NEW_ARRAY( itemStore->varRegionList, itemStore->regionCount ) ) + goto Exit; - for ( i = 0; i < itemStore->dataCount; i++ ) - { - if ( FT_READ_ULONG( dataOffsetArray[i] ) ) - goto Exit; - } + for ( i = 0; i < itemStore->regionCount; i++ ) + { + GX_AxisCoords axisCoords; - /* parse array of region records (region list) */ - if ( FT_STREAM_SEEK( table_offset + store_offset + region_offset ) ) - goto Exit; - if ( FT_READ_USHORT( itemStore->axisCount ) || - FT_READ_USHORT( itemStore->regionCount ) ) + if ( FT_NEW_ARRAY( itemStore->varRegionList[i].axisList, + itemStore->axisCount ) ) goto Exit; - if ( FT_NEW_ARRAY( itemStore->varRegionList, itemStore->regionCount ) ) - goto Exit; + axisCoords = itemStore->varRegionList[i].axisList; - for ( i = 0; i < itemStore->regionCount; i++ ) + for ( j = 0; j < itemStore->axisCount; j++ ) { - GX_AxisCoords axisCoords; + FT_Short start, peak, end; - if ( FT_NEW_ARRAY( itemStore->varRegionList[i].axisList, - itemStore->axisCount ) ) + if ( FT_READ_SHORT( start ) || + FT_READ_SHORT( peak ) || + FT_READ_SHORT( end ) ) goto Exit; - axisCoords = itemStore->varRegionList[i].axisList; + axisCoords[j].startCoord = FT_fdot14ToFixed( start ); + axisCoords[j].peakCoord = FT_fdot14ToFixed( peak ); + axisCoords[j].endCoord = FT_fdot14ToFixed( end ); + } + } - for ( j = 0; j < itemStore->axisCount; j++ ) - { - FT_Short start, peak, end; + /* end of region list parse */ + /* use dataOffsetArray now to parse varData items */ + if ( FT_NEW_ARRAY( itemStore->varData, itemStore->dataCount ) ) + goto Exit; - if ( FT_READ_SHORT( start ) || - FT_READ_SHORT( peak ) || - FT_READ_SHORT( end ) ) - goto Exit; + for ( i = 0; i < itemStore->dataCount; i++ ) + { + varData = &itemStore->varData[i]; - axisCoords[j].startCoord = FT_fdot14ToFixed( start ); - axisCoords[j].peakCoord = FT_fdot14ToFixed( peak ); - axisCoords[j].endCoord = FT_fdot14ToFixed( end ); - } - } + if ( FT_STREAM_SEEK( offset + dataOffsetArray[i] ) ) + goto Exit; - /* end of region list parse */ + if ( FT_READ_USHORT( varData->itemCount ) || + FT_READ_USHORT( shortDeltaCount ) || + FT_READ_USHORT( varData->regionIdxCount ) ) + goto Exit; - /* use dataOffsetArray now to parse varData items */ - if ( FT_NEW_ARRAY( itemStore->varData, itemStore->dataCount ) ) + /* check some data consistency */ + if ( shortDeltaCount > varData->regionIdxCount ) + { + FT_TRACE2(( "bad short count %d or region count %d\n", + shortDeltaCount, + varData->regionIdxCount )); + error = FT_THROW( Invalid_Table ); goto Exit; + } - for ( i = 0; i < itemStore->dataCount; i++ ) + if ( varData->regionIdxCount > itemStore->regionCount ) { - hvarData = &itemStore->varData[i]; + FT_TRACE2(( "inconsistent regionCount %d in varData[%d]\n", + varData->regionIdxCount, + i )); + error = FT_THROW( Invalid_Table ); + goto Exit; + } - if ( FT_STREAM_SEEK( table_offset + - store_offset + - dataOffsetArray[i] ) ) - goto Exit; + /* parse region indices */ + if ( FT_NEW_ARRAY( varData->regionIndices, + varData->regionIdxCount ) ) + goto Exit; - if ( FT_READ_USHORT( hvarData->itemCount ) || - FT_READ_USHORT( shortDeltaCount ) || - FT_READ_USHORT( hvarData->regionIdxCount ) ) + for ( j = 0; j < varData->regionIdxCount; j++ ) + { + if ( FT_READ_USHORT( varData->regionIndices[j] ) ) goto Exit; - /* check some data consistency */ - if ( shortDeltaCount > hvarData->regionIdxCount ) + if ( varData->regionIndices[j] >= itemStore->regionCount ) { - FT_TRACE2(( "bad short count %d or region count %d\n", - shortDeltaCount, - hvarData->regionIdxCount )); + FT_TRACE2(( "bad region index %d\n", + varData->regionIndices[j] )); error = FT_THROW( Invalid_Table ); goto Exit; } + } + + /* Parse delta set. */ + /* */ + /* On input, deltas are (shortDeltaCount + regionIdxCount) bytes */ + /* each; on output, deltas are expanded to `regionIdxCount' shorts */ + /* each. */ + if ( FT_NEW_ARRAY( varData->deltaSet, + varData->regionIdxCount * varData->itemCount ) ) + goto Exit; - if ( hvarData->regionIdxCount > itemStore->regionCount ) + /* the delta set is stored as a 2-dimensional array of shorts; */ + /* sign-extend signed bytes to signed shorts */ + for ( j = 0; j < varData->itemCount * varData->regionIdxCount; ) + { + for ( k = 0; k < shortDeltaCount; k++, j++ ) { - FT_TRACE2(( "inconsistent regionCount %d in varData[%d]\n", - hvarData->regionIdxCount, - i )); - error = FT_THROW( Invalid_Table ); - goto Exit; - } + /* read the short deltas */ + FT_Short delta; - /* parse region indices */ - if ( FT_NEW_ARRAY( hvarData->regionIndices, - hvarData->regionIdxCount ) ) - goto Exit; - for ( j = 0; j < hvarData->regionIdxCount; j++ ) - { - if ( FT_READ_USHORT( hvarData->regionIndices[j] ) ) + if ( FT_READ_SHORT( delta ) ) goto Exit; - if ( hvarData->regionIndices[j] >= itemStore->regionCount ) - { - FT_TRACE2(( "bad region index %d\n", - hvarData->regionIndices[j] )); - error = FT_THROW( Invalid_Table ); - goto Exit; - } + varData->deltaSet[j] = delta; } - /* Parse delta set. */ - /* */ - /* On input, deltas are ( shortDeltaCount + regionIdxCount ) bytes */ - /* each; on output, deltas are expanded to `regionIdxCount' shorts */ - /* each. */ - if ( FT_NEW_ARRAY( hvarData->deltaSet, - hvarData->regionIdxCount * hvarData->itemCount ) ) - goto Exit; - - /* the delta set is stored as a 2-dimensional array of shorts; */ - /* sign-extend signed bytes to signed shorts */ - for ( j = 0; j < hvarData->itemCount * hvarData->regionIdxCount; ) + for ( ; k < varData->regionIdxCount; k++, j++ ) { - for ( k = 0; k < shortDeltaCount; k++, j++ ) - { - /* read the short deltas */ - FT_Short delta; + /* read the (signed) byte deltas */ + FT_Char delta; - if ( FT_READ_SHORT( delta ) ) - goto Exit; - - hvarData->deltaSet[j] = delta; - } - - for ( ; k < hvarData->regionIdxCount; k++, j++ ) - { - /* read the (signed) byte deltas */ - FT_Char delta; - - - if ( FT_READ_CHAR( delta ) ) - goto Exit; + if ( FT_READ_CHAR( delta ) ) + goto Exit; - hvarData->deltaSet[j] = delta; - } + varData->deltaSet[j] = delta; } } } - /* end parse item variation store */ + Exit: + FT_FREE( dataOffsetArray ); - /* parse width map */ - { - GX_WidthMap widthMap; + return error; + } - FT_UShort format; - FT_UInt entrySize; - FT_UInt innerBitCount; - FT_UInt innerIndexMask; - FT_UInt i, j; + static FT_Error + ft_var_load_delta_set_index_mapping( TT_Face face, + FT_ULong offset, + GX_DeltaSetIdxMap map, + GX_ItemVarStore itemStore ) + { + FT_Stream stream = FT_FACE_STREAM( face ); + FT_Memory memory = stream->memory; - widthMap = &blend->hvar_table->widthMap; + FT_Error error; - if ( FT_READ_USHORT( format ) || - FT_READ_USHORT( widthMap->mapCount ) ) - goto Exit; + FT_UShort format; + FT_UInt entrySize; + FT_UInt innerBitCount; + FT_UInt innerIndexMask; + FT_UInt i, j; - if ( format & 0xFFC0 ) - { - FT_TRACE2(( "bad map format %d\n", format )); - error = FT_THROW( Invalid_Table ); - goto Exit; - } - /* bytes per entry: 1, 2, 3, or 4 */ - entrySize = ( ( format & 0x0030 ) >> 4 ) + 1; - innerBitCount = ( format & 0x000F ) + 1; - innerIndexMask = ( 1 << innerBitCount ) - 1; + if ( FT_STREAM_SEEK( offset ) || + FT_READ_USHORT( format ) || + FT_READ_USHORT( map->mapCount ) ) + goto Exit; - if ( FT_NEW_ARRAY( widthMap->innerIndex, widthMap->mapCount ) ) - goto Exit; + if ( format & 0xFFC0 ) + { + FT_TRACE2(( "bad map format %d\n", format )); + error = FT_THROW( Invalid_Table ); + goto Exit; + } - if ( FT_NEW_ARRAY( widthMap->outerIndex, widthMap->mapCount ) ) - goto Exit; + /* bytes per entry: 1, 2, 3, or 4 */ + entrySize = ( ( format & 0x0030 ) >> 4 ) + 1; + innerBitCount = ( format & 0x000F ) + 1; + innerIndexMask = ( 1 << innerBitCount ) - 1; - for ( i = 0; i < widthMap->mapCount; i++ ) - { - FT_UInt mapData = 0; - FT_UInt outerIndex, innerIndex; + if ( FT_NEW_ARRAY( map->innerIndex, map->mapCount ) ) + goto Exit; + if ( FT_NEW_ARRAY( map->outerIndex, map->mapCount ) ) + goto Exit; - /* read map data one unsigned byte at a time, big endian */ - for ( j = 0; j < entrySize; j++ ) - { - FT_Byte data; + for ( i = 0; i < map->mapCount; i++ ) + { + FT_UInt mapData = 0; + FT_UInt outerIndex, innerIndex; - if ( FT_READ_BYTE( data ) ) - goto Exit; - - mapData = ( mapData << 8 ) | data; - } + /* read map data one unsigned byte at a time, big endian */ + for ( j = 0; j < entrySize; j++ ) + { + FT_Byte data; - outerIndex = mapData >> innerBitCount; - if ( outerIndex >= blend->hvar_table->itemStore.dataCount ) - { - FT_TRACE2(( "outerIndex[%d] == %d out of range\n", - i, - outerIndex )); - error = FT_THROW( Invalid_Table ); + if ( FT_READ_BYTE( data ) ) goto Exit; - } - widthMap->outerIndex[i] = outerIndex; + mapData = ( mapData << 8 ) | data; + } - innerIndex = mapData & innerIndexMask; + outerIndex = mapData >> innerBitCount; - if ( innerIndex >= - blend->hvar_table->itemStore.varData[outerIndex].itemCount ) - { - FT_TRACE2(( "innerIndex[%d] == %d out of range\n", - i, - innerIndex )); - error = FT_THROW( Invalid_Table ); - goto Exit; - } - - widthMap->innerIndex[i] = innerIndex; + if ( outerIndex >= itemStore->dataCount ) + { + FT_TRACE2(( "outerIndex[%d] == %d out of range\n", + i, + outerIndex )); + error = FT_THROW( Invalid_Table ); + goto Exit; } - } - /* end parse width map */ + map->outerIndex[i] = outerIndex; - FT_TRACE2(( "loaded\n" )); - error = FT_Err_Ok; + innerIndex = mapData & innerIndexMask; - Exit: - FT_FREE( dataOffsetArray ); - - if ( !error ) - { - blend->hvar_checked = TRUE; + if ( innerIndex >= itemStore->varData[outerIndex].itemCount ) + { + FT_TRACE2(( "innerIndex[%d] == %d out of range\n", + i, + innerIndex )); + error = FT_THROW( Invalid_Table ); + goto Exit; + } - /* TODO: implement other HVAR stuff */ - face->variation_support |= TT_FACE_FLAG_VAR_HADVANCE; + map->innerIndex[i] = innerIndex; } + Exit: return error; } @@ -756,86 +705,181 @@ /*************************************************************************/ /* */ /* <Function> */ - /* tt_hadvance_adjust */ + /* ft_var_load_hvvar */ /* */ /* <Description> */ - /* Apply HVAR advance width adjustment of a given glyph. */ + /* If `vertical' is zero, parse the `HVAR' table and set */ + /* `blend->hvar_loaded' to TRUE. On success, `blend->hvar_checked' */ + /* is set to TRUE. */ /* */ - /* <Input> */ - /* gindex :: The glyph index. */ + /* If `vertical' is not zero, parse the `VVAR' table and set */ + /* `blend->vvar_loaded' to TRUE. On success, `blend->vvar_checked' */ + /* is set to TRUE. */ + /* */ + /* Some memory may remain allocated on error; it is always freed in */ + /* `tt_done_blend', however. */ /* */ /* <InOut> */ - /* face :: The font face. */ + /* face :: The font face. */ /* */ - /* adelta :: Points to width value that gets modified. */ + /* <Return> */ + /* FreeType error code. 0 means success. */ /* */ - FT_LOCAL_DEF( FT_Error ) - tt_hadvance_adjust( TT_Face face, - FT_UInt gindex, - FT_Int *avalue ) + static FT_Error + ft_var_load_hvvar( TT_Face face, + FT_Bool vertical ) { - FT_Error error = FT_Err_Ok; + FT_Stream stream = FT_FACE_STREAM( face ); + FT_Memory memory = stream->memory; - GX_HVarData varData; + GX_Blend blend = face->blend; - FT_UInt innerIndex, outerIndex; - FT_UInt master, j; - FT_Fixed netAdjustment = 0; /* accumulated adjustment */ - FT_Fixed scaledDelta; - FT_Short* deltaSet; - FT_Fixed delta; + GX_HVVarTable table; + FT_Error error; + FT_UShort majorVersion; + FT_ULong table_len; + FT_ULong table_offset; + FT_ULong store_offset; + FT_ULong widthMap_offset; - if ( !face->doblend || !face->blend ) - goto Exit; - if ( !face->blend->hvar_loaded ) + if ( vertical ) + { + blend->vvar_loaded = TRUE; + + FT_TRACE2(( "VVAR " )); + + error = face->goto_table( face, TTAG_VVAR, stream, &table_len ); + } + else + { + blend->hvar_loaded = TRUE; + + FT_TRACE2(( "HVAR " )); + + error = face->goto_table( face, TTAG_HVAR, stream, &table_len ); + } + + if ( error ) { - /* initialize hvar table */ - face->blend->hvar_error = ft_var_load_hvar( face ); + FT_TRACE2(( "is missing\n" )); + goto Exit; } - if ( !face->blend->hvar_checked ) + table_offset = FT_STREAM_POS(); + + /* skip minor version */ + if ( FT_READ_USHORT( majorVersion ) || + FT_STREAM_SKIP( 2 ) ) + goto Exit; + + if ( majorVersion != 1 ) { - error = face->blend->hvar_error; + FT_TRACE2(( "bad table version %d\n", majorVersion )); + error = FT_THROW( Invalid_Table ); goto Exit; } - /* advance width adjustments are always present in an `HVAR' table, */ - /* so need to test for this capability */ + if ( FT_READ_ULONG( store_offset ) || + FT_READ_ULONG( widthMap_offset ) ) + goto Exit; - if ( gindex >= face->blend->hvar_table->widthMap.mapCount ) + if ( vertical ) + { + if ( FT_NEW( blend->vvar_table ) ) + goto Exit; + table = blend->vvar_table; + } + else { - FT_TRACE2(( "gindex %d out of range\n", gindex )); - error = FT_THROW( Invalid_Argument ); + if ( FT_NEW( blend->hvar_table ) ) + goto Exit; + table = blend->hvar_table; + } + + error = ft_var_load_item_variation_store( + face, + table_offset + store_offset, + &table->itemStore ); + if ( error ) goto Exit; + + if ( widthMap_offset ) + { + error = ft_var_load_delta_set_index_mapping( + face, + table_offset + widthMap_offset, + &table->widthMap, + &table->itemStore ); + if ( error ) + goto Exit; } - /* trust that HVAR parser has checked indices */ - outerIndex = face->blend->hvar_table->widthMap.outerIndex[gindex]; - innerIndex = face->blend->hvar_table->widthMap.innerIndex[gindex]; - varData = &face->blend->hvar_table->itemStore.varData[outerIndex]; - deltaSet = &varData->deltaSet[varData->regionIdxCount * innerIndex]; + FT_TRACE2(( "loaded\n" )); + error = FT_Err_Ok; + + Exit: + if ( !error ) + { + if ( vertical ) + { + blend->vvar_checked = TRUE; + + /* FreeType doesn't provide functions to quickly retrieve */ + /* TSB, BSB, or VORG values; we thus don't have to implement */ + /* support for those three item variation stores. */ + + face->variation_support |= TT_FACE_FLAG_VAR_VADVANCE; + } + else + { + blend->hvar_checked = TRUE; + + /* FreeType doesn't provide functions to quickly retrieve */ + /* LSB or RSB values; we thus don't have to implement */ + /* support for those two item variation stores. */ + + face->variation_support |= TT_FACE_FLAG_VAR_HADVANCE; + } + } + + return error; + } + + + static FT_Int + ft_var_get_item_delta( TT_Face face, + GX_ItemVarStore itemStore, + FT_UInt outerIndex, + FT_UInt innerIndex ) + { + GX_ItemVarData varData; + FT_Short* deltaSet; + + FT_UInt master, j; + FT_Fixed netAdjustment = 0; /* accumulated adjustment */ + FT_Fixed scaledDelta; + FT_Fixed delta; + /* See pseudo code from `Font Variations Overview' */ /* in the OpenType specification. */ + varData = &itemStore->varData[outerIndex]; + deltaSet = &varData->deltaSet[varData->regionIdxCount * innerIndex]; + /* outer loop steps through master designs to be blended */ for ( master = 0; master < varData->regionIdxCount; master++ ) { FT_Fixed scalar = FT_FIXED_ONE; FT_UInt regionIndex = varData->regionIndices[master]; - GX_AxisCoords axis = face->blend - ->hvar_table - ->itemStore.varRegionList[regionIndex] - .axisList; + GX_AxisCoords axis = itemStore->varRegionList[regionIndex].axisList; /* inner loop steps through axes in this region */ - for ( j = 0; - j < face->blend->hvar_table->itemStore.axisCount; - j++, axis++ ) + for ( j = 0; j < itemStore->axisCount; j++, axis++ ) { FT_Fixed axisScalar; @@ -889,18 +933,460 @@ } /* per-region loop */ - /* apply the accumulated adjustment to derive the interpolated value */ - FT_TRACE5(( "horizontal width %d adjusted by %d units (HVAR)\n", + return FT_fixedToInt( netAdjustment ); + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_hvadvance_adjust */ + /* */ + /* <Description> */ + /* Apply `HVAR' advance width or `VVAR' advance height adjustment of */ + /* a given glyph. */ + /* */ + /* <Input> */ + /* gindex :: The glyph index. */ + /* */ + /* vertical :: If set, handle `VVAR' table. */ + /* */ + /* <InOut> */ + /* face :: The font face. */ + /* */ + /* adelta :: Points to width or height value that gets modified. */ + /* */ + static FT_Error + tt_hvadvance_adjust( TT_Face face, + FT_UInt gindex, + FT_Int *avalue, + FT_Bool vertical ) + { + FT_Error error = FT_Err_Ok; + FT_UInt innerIndex, outerIndex; + FT_Int delta; + + GX_HVVarTable table; + + + if ( !face->doblend || !face->blend ) + goto Exit; + + if ( vertical ) + { + if ( !face->blend->vvar_loaded ) + { + /* initialize vvar table */ + face->blend->vvar_error = ft_var_load_hvvar( face, 1 ); + } + + if ( !face->blend->vvar_checked ) + { + error = face->blend->vvar_error; + goto Exit; + } + + table = face->blend->vvar_table; + } + else + { + if ( !face->blend->hvar_loaded ) + { + /* initialize hvar table */ + face->blend->hvar_error = ft_var_load_hvvar( face, 0 ); + } + + if ( !face->blend->hvar_checked ) + { + error = face->blend->hvar_error; + goto Exit; + } + + table = face->blend->hvar_table; + } + + /* advance width or height adjustments are always present in an */ + /* `HVAR' or `VVAR' table; no need to test for this capability */ + + if ( table->widthMap.innerIndex ) + { + FT_UInt idx = gindex; + + + if ( idx >= table->widthMap.mapCount ) + idx = table->widthMap.mapCount - 1; + + /* trust that HVAR parser has checked indices */ + outerIndex = table->widthMap.outerIndex[idx]; + innerIndex = table->widthMap.innerIndex[idx]; + } + else + { + GX_ItemVarData varData; + + + /* no widthMap data */ + outerIndex = 0; + innerIndex = gindex; + + varData = &table->itemStore.varData[outerIndex]; + if ( gindex >= varData->itemCount ) + { + FT_TRACE2(( "gindex %d out of range\n", gindex )); + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + } + + delta = ft_var_get_item_delta( face, + &table->itemStore, + outerIndex, + innerIndex ); + + FT_TRACE5(( "%s value %d adjusted by %d unit%s (%s)\n", + vertical ? "vertical height" : "horizontal width", *avalue, - FT_fixedToInt( netAdjustment ) )); + delta, + delta == 1 ? "" : "s", + vertical ? "VVAR" : "HVAR" )); - *avalue += FT_fixedToInt( netAdjustment ); + *avalue += delta; Exit: return error; } + FT_LOCAL_DEF( FT_Error ) + tt_hadvance_adjust( TT_Face face, + FT_UInt gindex, + FT_Int *avalue ) + { + return tt_hvadvance_adjust( face, gindex, avalue, 0 ); + } + + + FT_LOCAL_DEF( FT_Error ) + tt_vadvance_adjust( TT_Face face, + FT_UInt gindex, + FT_Int *avalue ) + { + return tt_hvadvance_adjust( face, gindex, avalue, 1 ); + } + + +#define GX_VALUE_SIZE 8 + + /* all values are FT_Short or FT_UShort entities; */ + /* we treat them consistently as FT_Short */ +#define GX_VALUE_CASE( tag, dflt ) \ + case MVAR_TAG_ ## tag : \ + p = (FT_Short*)&face->dflt; \ + break + +#define GX_GASP_CASE( idx ) \ + case MVAR_TAG_GASP_ ## idx : \ + if ( idx < face->gasp.numRanges - 1 ) \ + p = (FT_Short*)&face->gasp.gaspRanges[idx].maxPPEM; \ + else \ + p = NULL; \ + break + + + static FT_Short* + ft_var_get_value_pointer( TT_Face face, + FT_ULong mvar_tag ) + { + FT_Short* p; + + + switch ( mvar_tag ) + { + GX_GASP_CASE( 0 ); + GX_GASP_CASE( 1 ); + GX_GASP_CASE( 2 ); + GX_GASP_CASE( 3 ); + GX_GASP_CASE( 4 ); + GX_GASP_CASE( 5 ); + GX_GASP_CASE( 6 ); + GX_GASP_CASE( 7 ); + GX_GASP_CASE( 8 ); + GX_GASP_CASE( 9 ); + + GX_VALUE_CASE( CPHT, os2.sCapHeight ); + GX_VALUE_CASE( HASC, os2.sTypoAscender ); + GX_VALUE_CASE( HCLA, os2.usWinAscent ); + GX_VALUE_CASE( HCLD, os2.usWinDescent ); + GX_VALUE_CASE( HCOF, horizontal.caret_Offset ); + GX_VALUE_CASE( HCRN, horizontal.caret_Slope_Run ); + GX_VALUE_CASE( HCRS, horizontal.caret_Slope_Rise ); + GX_VALUE_CASE( HDSC, os2.sTypoDescender ); + GX_VALUE_CASE( HLGP, os2.sTypoLineGap ); + GX_VALUE_CASE( SBXO, os2.ySubscriptXOffset); + GX_VALUE_CASE( SBXS, os2.ySubscriptXSize ); + GX_VALUE_CASE( SBYO, os2.ySubscriptYOffset ); + GX_VALUE_CASE( SBYS, os2.ySubscriptYSize ); + GX_VALUE_CASE( SPXO, os2.ySuperscriptXOffset ); + GX_VALUE_CASE( SPXS, os2.ySuperscriptXSize ); + GX_VALUE_CASE( SPYO, os2.ySuperscriptYOffset ); + GX_VALUE_CASE( SPYS, os2.ySuperscriptYSize ); + GX_VALUE_CASE( STRO, os2.yStrikeoutPosition ); + GX_VALUE_CASE( STRS, os2.yStrikeoutSize ); + GX_VALUE_CASE( UNDO, postscript.underlinePosition ); + GX_VALUE_CASE( UNDS, postscript.underlineThickness ); + GX_VALUE_CASE( VASC, vertical.Ascender ); + GX_VALUE_CASE( VCOF, vertical.caret_Offset ); + GX_VALUE_CASE( VCRN, vertical.caret_Slope_Run ); + GX_VALUE_CASE( VCRS, vertical.caret_Slope_Rise ); + GX_VALUE_CASE( VDSC, vertical.Descender ); + GX_VALUE_CASE( VLGP, vertical.Line_Gap ); + GX_VALUE_CASE( XHGT, os2.sxHeight ); + + default: + /* ignore unknown tag */ + p = NULL; + } + + return p; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* ft_var_load_mvar */ + /* */ + /* <Description> */ + /* Parse the `MVAR' table. */ + /* */ + /* Some memory may remain allocated on error; it is always freed in */ + /* `tt_done_blend', however. */ + /* */ + /* <InOut> */ + /* face :: The font face. */ + /* */ + static void + ft_var_load_mvar( TT_Face face ) + { + FT_Stream stream = FT_FACE_STREAM( face ); + FT_Memory memory = stream->memory; + + GX_Blend blend = face->blend; + GX_ItemVarStore itemStore; + GX_Value value, limit; + + FT_Error error; + FT_UShort majorVersion; + FT_ULong table_len; + FT_ULong table_offset; + FT_UShort store_offset; + FT_ULong records_offset; + + + FT_TRACE2(( "MVAR " )); + + error = face->goto_table( face, TTAG_MVAR, stream, &table_len ); + if ( error ) + { + FT_TRACE2(( "is missing\n" )); + return; + } + + table_offset = FT_STREAM_POS(); + + /* skip minor version */ + if ( FT_READ_USHORT( majorVersion ) || + FT_STREAM_SKIP( 2 ) ) + return; + + if ( majorVersion != 1 ) + { + FT_TRACE2(( "bad table version %d\n", majorVersion )); + return; + } + + if ( FT_NEW( blend->mvar_table ) ) + return; + + /* skip reserved entry and value record size */ + if ( FT_STREAM_SKIP( 4 ) || + FT_READ_USHORT( blend->mvar_table->valueCount ) || + FT_READ_USHORT( store_offset ) ) + return; + + records_offset = FT_STREAM_POS(); + + error = ft_var_load_item_variation_store( + face, + table_offset + store_offset, + &blend->mvar_table->itemStore ); + if ( error ) + return; + + if ( FT_NEW_ARRAY( blend->mvar_table->values, + blend->mvar_table->valueCount ) ) + return; + + if ( FT_STREAM_SEEK( records_offset ) || + FT_FRAME_ENTER( blend->mvar_table->valueCount * GX_VALUE_SIZE ) ) + return; + + value = blend->mvar_table->values; + limit = value + blend->mvar_table->valueCount; + itemStore = &blend->mvar_table->itemStore; + + for ( ; value < limit; value++ ) + { + value->tag = FT_GET_ULONG(); + value->outerIndex = FT_GET_USHORT(); + value->innerIndex = FT_GET_USHORT(); + + if ( value->outerIndex >= itemStore->dataCount || + value->innerIndex >= itemStore->varData[value->outerIndex] + .itemCount ) + { + error = FT_THROW( Invalid_Table ); + break; + } + } + + FT_FRAME_EXIT(); + + if ( error ) + return; + + FT_TRACE2(( "loaded\n" )); + + value = blend->mvar_table->values; + limit = value + blend->mvar_table->valueCount; + + /* save original values of the data MVAR is going to modify */ + for ( ; value < limit; value++ ) + { + FT_Short* p = ft_var_get_value_pointer( face, value->tag ); + + + if ( p ) + value->unmodified = *p; +#ifdef FT_DEBUG_LEVEL_TRACE + else + FT_TRACE1(( "ft_var_load_mvar: Ignoring unknown tag `%c%c%c%c'\n", + (FT_Char)( value->tag >> 24 ), + (FT_Char)( value->tag >> 16 ), + (FT_Char)( value->tag >> 8 ), + (FT_Char)( value->tag ) )); +#endif + } + + face->variation_support |= TT_FACE_FLAG_VAR_MVAR; + } + + + static FT_Error + tt_size_reset_iterator( FT_ListNode node, + void* user ) + { + TT_Size size = (TT_Size)node->data; + + FT_UNUSED( user ); + + + tt_size_reset( size, 1 ); + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_apply_mvar */ + /* */ + /* <Description> */ + /* Apply `MVAR' table adjustments. */ + /* */ + /* <InOut> */ + /* face :: The font face. */ + /* */ + FT_LOCAL_DEF( void ) + tt_apply_mvar( TT_Face face ) + { + GX_Blend blend = face->blend; + GX_Value value, limit; + + + if ( !( face->variation_support & TT_FACE_FLAG_VAR_MVAR ) ) + return; + + value = blend->mvar_table->values; + limit = value + blend->mvar_table->valueCount; + + for ( ; value < limit; value++ ) + { + FT_Short* p = ft_var_get_value_pointer( face, value->tag ); + FT_Int delta; + + + delta = ft_var_get_item_delta( face, + &blend->mvar_table->itemStore, + value->outerIndex, + value->innerIndex ); + + if ( p ) + { + FT_TRACE5(( "value %c%c%c%c (%d unit%s) adjusted by %d unit%s (MVAR)\n", + (FT_Char)( value->tag >> 24 ), + (FT_Char)( value->tag >> 16 ), + (FT_Char)( value->tag >> 8 ), + (FT_Char)( value->tag ), + value->unmodified, + value->unmodified == 1 ? "" : "s", + delta, + delta == 1 ? "" : "s" )); + + /* since we handle both signed and unsigned values as FT_Short, */ + /* ensure proper overflow arithmetic */ + *p = (FT_Short)( value->unmodified + (FT_Short)delta ); + } + } + + /* adjust all derived values */ + { + FT_Face root = &face->root; + + + if ( face->os2.version != 0xFFFFU ) + { + if ( face->os2.sTypoAscender || face->os2.sTypoDescender ) + { + root->ascender = face->os2.sTypoAscender; + root->descender = face->os2.sTypoDescender; + + root->height = root->ascender - root->descender + + face->os2.sTypoLineGap; + } + else + { + root->ascender = (FT_Short)face->os2.usWinAscent; + root->descender = -(FT_Short)face->os2.usWinDescent; + + root->height = root->ascender - root->descender; + } + } + + root->underline_position = face->postscript.underlinePosition - + face->postscript.underlineThickness / 2; + root->underline_thickness = face->postscript.underlineThickness; + + /* iterate over all FT_Size objects and call `tt_size_reset' */ + /* to propagate the metrics changes */ + FT_List_Iterate( &root->sizes_list, + tt_size_reset_iterator, + NULL ); + } + } + + typedef struct GX_GVar_Head_ { FT_Long version; @@ -1000,10 +1486,9 @@ goto Exit; } - /* rough sanity check: offsets can be either 2 or 4 bytes, */ - /* and a single variation needs at least 4 bytes per glyph */ + /* rough sanity check: offsets can be either 2 or 4 bytes */ if ( (FT_ULong)gvar_head.glyphCount * - ( ( gvar_head.flags & 1 ) ? 8 : 6 ) > table_len ) + ( ( gvar_head.flags & 1 ) ? 4 : 2 ) > table_len ) { FT_TRACE1(( "ft_var_load_gvar: invalid number of glyphs\n" )); error = FT_THROW( Invalid_Table ); @@ -1017,8 +1502,10 @@ blend->gv_glyphcnt = gvar_head.glyphCount; offsetToData = gvar_start + gvar_head.offsetToData; - FT_TRACE5(( "gvar: there are %d shared coordinates:\n", - blend->tuplecount )); + FT_TRACE5(( "gvar: there %s %d shared coordinate%s:\n", + blend->tuplecount == 1 ? "is" : "are", + blend->tuplecount, + blend->tuplecount == 1 ? "" : "s" )); if ( FT_NEW_ARRAY( blend->glyphoffsets, blend->gv_glyphcnt + 1 ) ) goto Exit; @@ -1216,6 +1703,180 @@ } + /* convert from design coordinates to normalized coordinates */ + + static void + ft_var_to_normalized( TT_Face face, + FT_UInt num_coords, + FT_Fixed* coords, + FT_Fixed* normalized ) + { + GX_Blend blend; + FT_MM_Var* mmvar; + FT_UInt i, j; + FT_Var_Axis* a; + GX_AVarSegment av; + + + blend = face->blend; + mmvar = blend->mmvar; + + if ( num_coords > mmvar->num_axis ) + { + FT_TRACE2(( "ft_var_to_normalized:" + " only using first %d of %d coordinates\n", + mmvar->num_axis, num_coords )); + num_coords = mmvar->num_axis; + } + + /* Axis normalization is a two-stage process. First we normalize */ + /* based on the [min,def,max] values for the axis to be [-1,0,1]. */ + /* Then, if there's an `avar' table, we renormalize this range. */ + + a = mmvar->axis; + for ( i = 0; i < num_coords; i++, a++ ) + { + FT_Fixed coord = coords[i]; + + + FT_TRACE5(( " %d: %.5f\n", i, coord / 65536.0 )); + if ( coord > a->maximum || coord < a->minimum ) + { + FT_TRACE1(( + "ft_var_to_normalized: design coordinate %.5f\n" + " is out of range [%.5f;%.5f]; clamping\n", + coord / 65536.0, + a->minimum / 65536.0, + a->maximum / 65536.0 )); + + if ( coord > a->maximum ) + coord = a->maximum; + else + coord = a->minimum; + } + + if ( coord < a->def ) + normalized[i] = -FT_DivFix( coord - a->def, + a->minimum - a->def ); + else if ( coord > a->def ) + normalized[i] = FT_DivFix( coord - a->def, + a->maximum - a->def ); + else + normalized[i] = 0; + } + + FT_TRACE5(( "\n" )); + + for ( ; i < mmvar->num_axis; i++ ) + normalized[i] = 0; + + if ( blend->avar_segment ) + { + FT_TRACE5(( "normalized design coordinates" + " before applying `avar' data:\n" )); + + av = blend->avar_segment; + for ( i = 0; i < mmvar->num_axis; i++, av++ ) + { + for ( j = 1; j < (FT_UInt)av->pairCount; j++ ) + { + if ( normalized[i] < av->correspondence[j].fromCoord ) + { + FT_TRACE5(( " %.5f\n", normalized[i] / 65536.0 )); + + normalized[i] = + FT_MulDiv( normalized[i] - av->correspondence[j - 1].fromCoord, + av->correspondence[j].toCoord - + av->correspondence[j - 1].toCoord, + av->correspondence[j].fromCoord - + av->correspondence[j - 1].fromCoord ) + + av->correspondence[j - 1].toCoord; + break; + } + } + } + } + } + + + /* convert from normalized coordinates to design coordinates */ + + static void + ft_var_to_design( TT_Face face, + FT_UInt num_coords, + FT_Fixed* coords, + FT_Fixed* design ) + { + GX_Blend blend; + FT_MM_Var* mmvar; + FT_Var_Axis* a; + + FT_UInt i, j, nc; + + + blend = face->blend; + + nc = num_coords; + if ( num_coords > blend->num_axis ) + { + FT_TRACE2(( "ft_var_to_design:" + " only using first %d of %d coordinates\n", + blend->num_axis, num_coords )); + nc = blend->num_axis; + } + + for ( i = 0; i < nc; i++ ) + design[i] = coords[i]; + + for ( ; i < num_coords; i++ ) + design[i] = 0; + + if ( blend->avar_segment ) + { + GX_AVarSegment av = blend->avar_segment; + + + FT_TRACE5(( "design coordinates" + " after removing `avar' distortion:\n" )); + + for ( i = 0; i < nc; i++, av++ ) + { + for ( j = 1; j < (FT_UInt)av->pairCount; j++ ) + { + if ( design[i] < av->correspondence[j].toCoord ) + { + design[i] = + FT_MulDiv( design[i] - av->correspondence[j - 1].toCoord, + av->correspondence[j].fromCoord - + av->correspondence[j - 1].fromCoord, + av->correspondence[j].toCoord - + av->correspondence[j - 1].toCoord ) + + av->correspondence[j - 1].fromCoord; + + FT_TRACE5(( " %.5f\n", design[i] / 65536.0 )); + break; + } + } + } + } + + mmvar = blend->mmvar; + a = mmvar->axis; + + for ( i = 0; i < nc; i++, a++ ) + { + if ( design[i] < 0 ) + design[i] = a->def + FT_MulFix( design[i], + a->def - a->minimum ); + else if ( design[i] > 0 ) + design[i] = a->def + FT_MulFix( design[i], + a->maximum - a->def ); + else + design[i] = a->def; + } + } + + /*************************************************************************/ /*************************************************************************/ /***** *****/ @@ -1229,7 +1890,6 @@ { FT_Long version; FT_UShort offsetToData; - FT_UShort countSizePairs; FT_UShort axisCount; FT_UShort axisSize; FT_UShort instanceCount; @@ -1257,7 +1917,8 @@ /* */ /* <Description> */ /* Check that the font's `fvar' table is valid, parse it, and return */ - /* those data. */ + /* those data. It also loads (and parses) the `MVAR' table, if */ + /* possible. */ /* */ /* <InOut> */ /* face :: The font face. */ @@ -1274,19 +1935,33 @@ TT_Get_MM_Var( TT_Face face, FT_MM_Var* *master ) { - FT_Stream stream = face->root.stream; - FT_Memory memory = face->root.memory; + FT_Stream stream = face->root.stream; + FT_Memory memory = face->root.memory; FT_ULong table_len; - FT_Error error = FT_Err_Ok; - FT_ULong fvar_start; - FT_Int i, j; + FT_Error error = FT_Err_Ok; + FT_ULong fvar_start = 0; + FT_UInt i, j; FT_MM_Var* mmvar = NULL; FT_Fixed* next_coords; + FT_Fixed* nsc; FT_String* next_name; FT_Var_Axis* a; + FT_Fixed* c; FT_Var_Named_Style* ns; GX_FVar_Head fvar_head; - FT_Bool usePsName; + FT_Bool usePsName = 0; + FT_UInt num_instances; + FT_UInt num_axes; + FT_UShort* axis_flags; + + FT_Offset mmvar_size; + FT_Offset axis_flags_size; + FT_Offset axis_size; + FT_Offset namedstyle_size; + FT_Offset next_coords_size; + FT_Offset next_name_size; + + FT_Bool need_init; static const FT_Frame_Field fvar_fields[] = { @@ -1295,13 +1970,13 @@ #define FT_STRUCTURE GX_FVar_Head FT_FRAME_START( 16 ), - FT_FRAME_LONG ( version ), - FT_FRAME_USHORT( offsetToData ), - FT_FRAME_USHORT( countSizePairs ), - FT_FRAME_USHORT( axisCount ), - FT_FRAME_USHORT( axisSize ), - FT_FRAME_USHORT( instanceCount ), - FT_FRAME_USHORT( instanceSize ), + FT_FRAME_LONG ( version ), + FT_FRAME_USHORT ( offsetToData ), + FT_FRAME_SKIP_SHORT, + FT_FRAME_USHORT ( axisCount ), + FT_FRAME_USHORT ( axisSize ), + FT_FRAME_USHORT ( instanceCount ), + FT_FRAME_USHORT ( instanceSize ), FT_FRAME_END }; @@ -1325,7 +2000,9 @@ /* read the font data and set up the internal representation */ /* if not already done */ - if ( !face->blend ) + need_init = !face->blend; + + if ( need_init ) { FT_TRACE2(( "FVAR " )); @@ -1362,18 +2039,57 @@ FT_TRACE2(( "loaded\n" )); - FT_TRACE5(( "number of GX style axes: %d\n", fvar_head.axisCount )); + FT_TRACE5(( "%d variation ax%s\n", + fvar_head.axisCount, + fvar_head.axisCount == 1 ? "is" : "es" )); if ( FT_NEW( face->blend ) ) goto Exit; - /* cannot overflow 32-bit arithmetic because of limits above */ - face->blend->mmvar_len = - sizeof ( FT_MM_Var ) + - fvar_head.axisCount * sizeof ( FT_Var_Axis ) + - fvar_head.instanceCount * sizeof ( FT_Var_Named_Style ) + - fvar_head.instanceCount * fvar_head.axisCount * sizeof ( FT_Fixed ) + - 5 * fvar_head.axisCount; + num_axes = fvar_head.axisCount; + face->blend->num_axis = num_axes; + } + else + num_axes = face->blend->num_axis; + + /* `num_instances' holds the number of all named instances, */ + /* including the default instance which might be missing */ + /* in fvar's table of named instances */ + num_instances = (FT_UInt)face->root.style_flags >> 16; + + /* prepare storage area for MM data; this cannot overflow */ + /* 32-bit arithmetic because of the size limits used in the */ + /* `fvar' table validity check in `sfnt_init_face' */ + + /* the various `*_size' variables, which we also use as */ + /* offsets into the `mmlen' array, must be multiples of the */ + /* pointer size (except the last one); without such an */ + /* alignment there might be runtime errors due to */ + /* misaligned addresses */ +#undef ALIGN_SIZE +#define ALIGN_SIZE( n ) \ + ( ( (n) + sizeof (void*) - 1 ) & ~( sizeof (void*) - 1 ) ) + + mmvar_size = ALIGN_SIZE( sizeof ( FT_MM_Var ) ); + axis_flags_size = ALIGN_SIZE( num_axes * + sizeof ( FT_UShort ) ); + axis_size = ALIGN_SIZE( num_axes * + sizeof ( FT_Var_Axis ) ); + namedstyle_size = ALIGN_SIZE( num_instances * + sizeof ( FT_Var_Named_Style ) ); + next_coords_size = ALIGN_SIZE( num_instances * + num_axes * + sizeof ( FT_Fixed ) ); + next_name_size = num_axes * 5; + + if ( need_init ) + { + face->blend->mmvar_len = mmvar_size + + axis_flags_size + + axis_size + + namedstyle_size + + next_coords_size + + next_name_size; if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) ) goto Exit; @@ -1383,28 +2099,33 @@ /* the data gets filled in later on */ mmvar->num_axis = - fvar_head.axisCount; + num_axes; mmvar->num_designs = ~0U; /* meaningless in this context; each glyph */ /* may have a different number of designs */ /* (or tuples, as called by Apple) */ mmvar->num_namedstyles = - fvar_head.instanceCount; + num_instances; + + /* alas, no public field in `FT_Var_Axis' for axis flags */ + axis_flags = + (FT_UShort*)( (char*)mmvar + mmvar_size ); mmvar->axis = - (FT_Var_Axis*)&( mmvar[1] ); + (FT_Var_Axis*)( (char*)axis_flags + axis_flags_size ); mmvar->namedstyle = - (FT_Var_Named_Style*)&( mmvar->axis[fvar_head.axisCount] ); + (FT_Var_Named_Style*)( (char*)mmvar->axis + axis_size ); - next_coords = - (FT_Fixed*)&( mmvar->namedstyle[fvar_head.instanceCount] ); - for ( i = 0; i < fvar_head.instanceCount; i++ ) + next_coords = (FT_Fixed*)( (char*)mmvar->namedstyle + + namedstyle_size ); + for ( i = 0; i < num_instances; i++ ) { mmvar->namedstyle[i].coords = next_coords; - next_coords += fvar_head.axisCount; + next_coords += num_axes; } - next_name = (FT_String*)next_coords; - for ( i = 0; i < fvar_head.axisCount; i++ ) + next_name = (FT_String*)( (char*)mmvar->namedstyle + + namedstyle_size + next_coords_size ); + for ( i = 0; i < num_axes; i++ ) { mmvar->axis[i].name = next_name; next_name += 5; @@ -1416,10 +2137,14 @@ goto Exit; a = mmvar->axis; - for ( i = 0; i < fvar_head.axisCount; i++ ) + for ( i = 0; i < num_axes; i++ ) { GX_FVar_Axis axis_rec; +#ifdef FT_DEBUG_LEVEL_TRACE + int invalid = 0; +#endif + if ( FT_STREAM_READ_FIELDS( fvaraxis_fields, &axis_rec ) ) goto Exit; @@ -1435,47 +2160,189 @@ a->name[3] = (FT_String)( ( a->tag ) & 0xFF ); a->name[4] = '\0'; + *axis_flags = axis_rec.flags; + if ( a->minimum > a->def || a->def > a->maximum ) { - FT_TRACE2(( "TT_Get_MM_Var:" - " invalid \"%s\" axis record; disabling\n", - a->name )); - a->minimum = a->def; a->maximum = a->def; + +#ifdef FT_DEBUG_LEVEL_TRACE + invalid = 1; +#endif } - FT_TRACE5(( " \"%s\": minimum=%.5f, default=%.5f, maximum=%.5f\n", +#ifdef FT_DEBUG_LEVEL_TRACE + if ( i == 0 ) + FT_TRACE5(( " idx tag " + /* " XXX `XXXX'" */ + " minimum default maximum flags\n" )); + /* " XXXX.XXXXX XXXX.XXXXX XXXX.XXXXX 0xXXXX" */ + + FT_TRACE5(( " %3d `%s'" + " %10.5f %10.5f %10.5f 0x%04X%s\n", + i, a->name, a->minimum / 65536.0, a->def / 65536.0, - a->maximum / 65536.0 )); + a->maximum / 65536.0, + *axis_flags, + invalid ? " (invalid, disabled)" : "" )); +#endif a++; + axis_flags++; } FT_TRACE5(( "\n" )); - ns = mmvar->namedstyle; + /* named instance coordinates are stored as design coordinates; */ + /* we have to convert them to normalized coordinates also */ + if ( FT_NEW_ARRAY( face->blend->normalized_stylecoords, + num_axes * num_instances ) ) + goto Exit; + + if ( fvar_head.instanceCount && !face->blend->avar_loaded ) + { + FT_ULong offset = FT_STREAM_POS(); + + + ft_var_load_avar( face ); + + if ( FT_STREAM_SEEK( offset ) ) + goto Exit; + } + + FT_TRACE5(( "%d instance%s\n", + fvar_head.instanceCount, + fvar_head.instanceCount == 1 ? "" : "s" )); + + ns = mmvar->namedstyle; + nsc = face->blend->normalized_stylecoords; for ( i = 0; i < fvar_head.instanceCount; i++, ns++ ) { /* PostScript names add 2 bytes to the instance record size */ if ( FT_FRAME_ENTER( ( usePsName ? 6L : 4L ) + - 4L * fvar_head.axisCount ) ) + 4L * num_axes ) ) goto Exit; ns->strid = FT_GET_USHORT(); (void) /* flags = */ FT_GET_USHORT(); - for ( j = 0; j < fvar_head.axisCount; j++ ) - ns->coords[j] = FT_GET_LONG(); + c = ns->coords; + for ( j = 0; j < num_axes; j++, c++ ) + *c = FT_GET_LONG(); + /* valid psid values are 6, [256;32767], and 0xFFFF */ if ( usePsName ) ns->psid = FT_GET_USHORT(); + else + ns->psid = 0xFFFF; + +#ifdef FT_DEBUG_LEVEL_TRACE + { + SFNT_Service sfnt = (SFNT_Service)face->sfnt; + + FT_String* strname = NULL; + FT_String* psname = NULL; + + FT_ULong pos; + + + pos = FT_STREAM_POS(); + + if ( ns->strid != 0xFFFF ) + { + (void)sfnt->get_name( face, + (FT_UShort)ns->strid, + &strname ); + if ( strname && !ft_strcmp( strname, ".notdef" ) ) + strname = NULL; + } + + if ( ns->psid != 0xFFFF ) + { + (void)sfnt->get_name( face, + (FT_UShort)ns->psid, + &psname ); + if ( psname && !ft_strcmp( psname, ".notdef" ) ) + psname = NULL; + } + + (void)FT_STREAM_SEEK( pos ); + + FT_TRACE5(( " instance %d (%s%s%s, %s%s%s)\n", + i, + strname ? "name: `" : "", + strname ? strname : "unnamed", + strname ? "'" : "", + psname ? "PS name: `" : "", + psname ? psname : "no PS name", + psname ? "'" : "" )); + + FT_FREE( strname ); + FT_FREE( psname ); + } +#endif /* FT_DEBUG_LEVEL_TRACE */ + + ft_var_to_normalized( face, num_axes, ns->coords, nsc ); + nsc += num_axes; FT_FRAME_EXIT(); } + + if ( num_instances != fvar_head.instanceCount ) + { + SFNT_Service sfnt = (SFNT_Service)face->sfnt; + + FT_Int found, dummy1, dummy2; + FT_UInt strid = ~0U; + + + /* the default instance is missing in array the */ + /* of named instances; try to synthesize an entry */ + found = sfnt->get_name_id( face, + TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY, + &dummy1, + &dummy2 ); + if ( found ) + strid = TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY; + else + { + found = sfnt->get_name_id( face, + TT_NAME_ID_FONT_SUBFAMILY, + &dummy1, + &dummy2 ); + if ( found ) + strid = TT_NAME_ID_FONT_SUBFAMILY; + } + + if ( found ) + { + found = sfnt->get_name_id( face, + TT_NAME_ID_PS_NAME, + &dummy1, + &dummy2 ); + if ( found ) + { + FT_TRACE5(( "TT_Get_MM_Var:" + " Adding default instance to named instances\n" )); + + ns = &mmvar->namedstyle[fvar_head.instanceCount]; + + ns->strid = strid; + ns->psid = TT_NAME_ID_PS_NAME; + + a = mmvar->axis; + c = ns->coords; + for ( j = 0; j < num_axes; j++, a++, c++ ) + *c = a->def; + } + } + } + + ft_var_load_mvar( face ); } /* fill the output array if requested */ @@ -1489,22 +2356,25 @@ goto Exit; FT_MEM_COPY( mmvar, face->blend->mmvar, face->blend->mmvar_len ); + axis_flags = + (FT_UShort*)( (char*)mmvar + mmvar_size ); mmvar->axis = - (FT_Var_Axis*)&( mmvar[1] ); + (FT_Var_Axis*)( (char*)axis_flags + axis_flags_size ); mmvar->namedstyle = - (FT_Var_Named_Style*)&( mmvar->axis[mmvar->num_axis] ); - next_coords = - (FT_Fixed*)&( mmvar->namedstyle[mmvar->num_namedstyles] ); + (FT_Var_Named_Style*)( (char*)mmvar->axis+ axis_size ); + next_coords = (FT_Fixed*)( (char*)mmvar->namedstyle + + namedstyle_size ); for ( n = 0; n < mmvar->num_namedstyles; n++ ) { mmvar->namedstyle[n].coords = next_coords; - next_coords += mmvar->num_axis; + next_coords += num_axes; } a = mmvar->axis; - next_name = (FT_String*)next_coords; - for ( n = 0; n < mmvar->num_axis; n++ ) + next_name = (FT_String*)( (char*)mmvar->namedstyle + + namedstyle_size + next_coords_size ); + for ( n = 0; n < num_axes; n++ ) { a->name = next_name; @@ -1530,41 +2400,19 @@ } - /*************************************************************************/ - /* */ - /* <Function> */ - /* TT_Set_MM_Blend */ - /* */ - /* <Description> */ - /* Set the blend (normalized) coordinates for this instance of the */ - /* font. Check that the `gvar' table is reasonable and does some */ - /* initial preparation. */ - /* */ - /* <InOut> */ - /* face :: The font. */ - /* Initialize the blend structure with `gvar' data. */ - /* */ - /* <Input> */ - /* num_coords :: The number of available coordinates. If it is */ - /* larger than the number of axes, ignore the excess */ - /* values. If it is smaller than the number of axes, */ - /* use the default value (0) for the remaining axes. */ - /* */ - /* coords :: An array of `num_coords', each between [-1,1]. */ - /* */ - /* <Return> */ - /* FreeType error code. 0 means success. */ - /* */ - FT_LOCAL_DEF( FT_Error ) - TT_Set_MM_Blend( TT_Face face, + static FT_Error + tt_set_mm_blend( TT_Face face, FT_UInt num_coords, - FT_Fixed* coords ) + FT_Fixed* coords, + FT_Bool set_design_coords ) { FT_Error error = FT_Err_Ok; GX_Blend blend; FT_MM_Var* mmvar; FT_UInt i; - FT_Bool is_default_instance = 1; + + FT_Bool all_design_coords = FALSE; + FT_Memory memory = face->root.memory; enum @@ -1589,16 +2437,18 @@ if ( num_coords > mmvar->num_axis ) { - FT_TRACE2(( "TT_Set_MM_Blend: only using first %d of %d coordinates\n", + FT_TRACE2(( "TT_Set_MM_Blend:" + " only using first %d of %d coordinates\n", mmvar->num_axis, num_coords )); num_coords = mmvar->num_axis; } - FT_TRACE5(( "normalized design coordinates:\n" )); + FT_TRACE5(( "TT_Set_MM_Blend:\n" + " normalized design coordinates:\n" )); for ( i = 0; i < num_coords; i++ ) { - FT_TRACE5(( " %.5f\n", coords[i] / 65536.0 )); + FT_TRACE5(( " %.5f\n", coords[i] / 65536.0 )); if ( coords[i] < -0x00010000L || coords[i] > 0x00010000L ) { FT_TRACE1(( "TT_Set_MM_Blend: normalized design coordinate %.5f\n" @@ -1607,17 +2457,23 @@ error = FT_THROW( Invalid_Argument ); goto Exit; } - - if ( coords[i] != 0 ) - is_default_instance = 0; } FT_TRACE5(( "\n" )); - if ( !face->isCFF2 && !blend->glyphoffsets ) + if ( !face->is_cff2 && !blend->glyphoffsets ) if ( FT_SET_ERROR( ft_var_load_gvar( face ) ) ) goto Exit; + if ( !blend->coords ) + { + if ( FT_NEW_ARRAY( blend->coords, mmvar->num_axis ) ) + goto Exit; + + /* the first time we have to compute all design coordinates */ + all_design_coords = TRUE; + } + if ( !blend->normalizedcoords ) { if ( FT_NEW_ARRAY( blend->normalizedcoords, mmvar->num_axis ) ) @@ -1631,6 +2487,12 @@ } else { + FT_Bool have_diff = 0; + FT_UInt j; + FT_Fixed* c; + FT_Fixed* n; + + manageCvt = mcvt_retain; for ( i = 0; i < num_coords; i++ ) @@ -1638,10 +2500,34 @@ if ( blend->normalizedcoords[i] != coords[i] ) { manageCvt = mcvt_load; + have_diff = 1; break; } } + if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ) + { + FT_UInt idx = (FT_UInt)face->root.face_index >> 16; + + + c = blend->normalizedcoords + i; + n = blend->normalized_stylecoords + idx * mmvar->num_axis + i; + for ( j = i; j < mmvar->num_axis; j++, n++, c++ ) + if ( *c != *n ) + have_diff = 1; + } + else + { + c = blend->normalizedcoords + i; + for ( j = i; j < mmvar->num_axis; j++, c++ ) + if ( *c != 0 ) + have_diff = 1; + } + + /* return value -1 indicates `no change' */ + if ( !have_diff ) + return -1; + for ( ; i < mmvar->num_axis; i++ ) { if ( blend->normalizedcoords[i] != 0 ) @@ -1662,6 +2548,12 @@ coords, num_coords * sizeof ( FT_Fixed ) ); + if ( set_design_coords ) + ft_var_to_design( face, + all_design_coords ? blend->num_axis : num_coords, + blend->normalizedcoords, + blend->coords ); + face->doblend = TRUE; if ( face->cvt ) @@ -1689,7 +2581,9 @@ } } - face->is_default_instance = is_default_instance; + /* enforce recomputation of the PostScript name; */ + FT_FREE( face->postscript_name ); + face->postscript_name = NULL; Exit: return error; @@ -1699,6 +2593,52 @@ /*************************************************************************/ /* */ /* <Function> */ + /* TT_Set_MM_Blend */ + /* */ + /* <Description> */ + /* Set the blend (normalized) coordinates for this instance of the */ + /* font. Check that the `gvar' table is reasonable and does some */ + /* initial preparation. */ + /* */ + /* <InOut> */ + /* face :: The font. */ + /* Initialize the blend structure with `gvar' data. */ + /* */ + /* <Input> */ + /* num_coords :: The number of available coordinates. If it is */ + /* larger than the number of axes, ignore the excess */ + /* values. If it is smaller than the number of axes, */ + /* use the default value (0) for the remaining axes. */ + /* */ + /* coords :: An array of `num_coords', each between [-1,1]. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + TT_Set_MM_Blend( TT_Face face, + FT_UInt num_coords, + FT_Fixed* coords ) + { + FT_Error error; + + + error = tt_set_mm_blend( face, num_coords, coords, 1 ); + if ( error ) + return error; + + if ( num_coords ) + face->root.face_flags |= FT_FACE_FLAG_VARIATION; + else + face->root.face_flags &= ~FT_FACE_FLAG_VARIATION; + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ /* TT_Get_MM_Blend */ /* */ /* <Description> */ @@ -1737,10 +2677,19 @@ blend = face->blend; + if ( !blend->coords ) + { + /* select default instance coordinates */ + /* if no instance is selected yet */ + if ( FT_SET_ERROR( tt_set_mm_blend( face, 0, NULL, 1 ) ) ) + return error; + } + nc = num_coords; if ( num_coords > blend->num_axis ) { - FT_TRACE2(( "TT_Get_MM_Blend: only using first %d of %d coordinates\n", + FT_TRACE2(( "TT_Get_MM_Blend:" + " only using first %d of %d coordinates\n", blend->num_axis, num_coords )); nc = blend->num_axis; } @@ -1793,14 +2742,17 @@ FT_UInt num_coords, FT_Fixed* coords ) { - FT_Error error = FT_Err_Ok; - FT_Fixed* normalized = NULL; - GX_Blend blend; - FT_MM_Var* mmvar; - FT_UInt i, j; - FT_Var_Axis* a; - GX_AVarSegment av; - FT_Memory memory = face->root.memory; + FT_Error error = FT_Err_Ok; + GX_Blend blend; + FT_MM_Var* mmvar; + FT_UInt i; + FT_Memory memory = face->root.memory; + + FT_Fixed* c; + FT_Fixed* n; + FT_Fixed* normalized = NULL; + + FT_Bool have_diff = 0; if ( !face->blend ) @@ -1820,83 +2772,81 @@ num_coords = mmvar->num_axis; } - /* Axis normalization is a two-stage process. First we normalize */ - /* based on the [min,def,max] values for the axis to be [-1,0,1]. */ - /* Then, if there's an `avar' table, we renormalize this range. */ - - if ( FT_NEW_ARRAY( normalized, mmvar->num_axis ) ) - goto Exit; - - FT_TRACE5(( "design coordinates:\n" )); - - a = mmvar->axis; - for ( i = 0; i < num_coords; i++, a++ ) + if ( !blend->coords ) { - FT_Fixed coord = coords[i]; - + if ( FT_NEW_ARRAY( blend->coords, mmvar->num_axis ) ) + goto Exit; + } - FT_TRACE5(( " %.5f\n", coord / 65536.0 )); - if ( coord > a->maximum || coord < a->minimum ) + c = blend->coords; + n = coords; + for ( i = 0; i < num_coords; i++, n++, c++ ) + { + if ( *c != *n ) { - FT_TRACE1(( - "TT_Set_Var_Design: design coordinate %.5f\n" - " is out of range [%.5f;%.5f]; clamping\n", - coord / 65536.0, - a->minimum / 65536.0, - a->maximum / 65536.0 )); - - if ( coord > a->maximum) - coord = a->maximum; - else - coord = a->minimum; + *c = *n; + have_diff = 1; } - - if ( coord < a->def ) - normalized[i] = -FT_DivFix( coords[i] - a->def, - a->minimum - a->def ); - else if ( coord > a->def ) - normalized[i] = FT_DivFix( coords[i] - a->def, - a->maximum - a->def ); - else - normalized[i] = 0; } - FT_TRACE5(( "\n" )); + if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ) + { + FT_UInt instance_index; + FT_Var_Named_Style* named_style; - for ( ; i < mmvar->num_axis; i++ ) - normalized[i] = 0; - if ( !blend->avar_checked ) - ft_var_load_avar( face ); + instance_index = (FT_UInt)face->root.face_index >> 16; + named_style = mmvar->namedstyle + instance_index - 1; - if ( blend->avar_segment ) + n = named_style->coords + num_coords; + for ( ; i < mmvar->num_axis; i++, n++, c++ ) + { + if ( *c != *n ) + { + *c = *n; + have_diff = 1; + } + } + } + else { - FT_TRACE5(( "normalized design coordinates" - " before applying `avar' data:\n" )); + FT_Var_Axis* a; - av = blend->avar_segment; - for ( i = 0; i < mmvar->num_axis; i++, av++ ) + + a = mmvar->axis + num_coords; + for ( ; i < mmvar->num_axis; i++, a++, c++ ) { - for ( j = 1; j < (FT_UInt)av->pairCount; j++ ) + if ( *c != a->def ) { - if ( normalized[i] < av->correspondence[j].fromCoord ) - { - FT_TRACE5(( " %.5f\n", normalized[i] / 65536.0 )); - - normalized[i] = - FT_MulDiv( normalized[i] - av->correspondence[j - 1].fromCoord, - av->correspondence[j].toCoord - - av->correspondence[j - 1].toCoord, - av->correspondence[j].fromCoord - - av->correspondence[j - 1].fromCoord ) + - av->correspondence[j - 1].toCoord; - break; - } + *c = a->def; + have_diff = 1; } } } - error = TT_Set_MM_Blend( face, mmvar->num_axis, normalized ); + /* return value -1 indicates `no change'; */ + /* we can exit early if `normalizedcoords' is already computed */ + if ( blend->normalizedcoords && !have_diff ) + return -1; + + if ( FT_NEW_ARRAY( normalized, mmvar->num_axis ) ) + goto Exit; + + if ( !face->blend->avar_loaded ) + ft_var_load_avar( face ); + + FT_TRACE5(( "TT_Set_Var_Design:\n" + " normalized design coordinates:\n" )); + ft_var_to_normalized( face, num_coords, blend->coords, normalized ); + + error = tt_set_mm_blend( face, mmvar->num_axis, normalized, 0 ); + if ( error ) + goto Exit; + + if ( num_coords ) + face->root.face_flags |= FT_FACE_FLAG_VARIATION; + else + face->root.face_flags &= ~FT_FACE_FLAG_VARIATION; Exit: FT_FREE( normalized ); @@ -1932,12 +2882,8 @@ FT_Fixed* coords ) { FT_Error error = FT_Err_Ok; - - GX_Blend blend; - FT_MM_Var* mmvar; - FT_Var_Axis* a; - - FT_UInt i, j, nc; + GX_Blend blend; + FT_UInt i, nc; if ( !face->blend ) @@ -1948,10 +2894,19 @@ blend = face->blend; + if ( !blend->coords ) + { + /* select default instance coordinates */ + /* if no instance is selected yet */ + if ( FT_SET_ERROR( tt_set_mm_blend( face, 0, NULL, 1 ) ) ) + return error; + } + nc = num_coords; if ( num_coords > blend->num_axis ) { - FT_TRACE2(( "TT_Get_Var_Design: only using first %d of %d coordinates\n", + FT_TRACE2(( "TT_Get_Var_Design:" + " only using first %d of %d coordinates\n", blend->num_axis, num_coords )); nc = blend->num_axis; } @@ -1959,7 +2914,7 @@ if ( face->doblend ) { for ( i = 0; i < nc; i++ ) - coords[i] = blend->normalizedcoords[i]; + coords[i] = blend->coords[i]; } else { @@ -1970,54 +2925,91 @@ for ( ; i < num_coords; i++ ) coords[i] = 0; - if ( !blend->avar_checked ) - ft_var_load_avar( face ); + return FT_Err_Ok; + } - if ( blend->avar_segment ) - { - GX_AVarSegment av = blend->avar_segment; + /*************************************************************************/ + /* */ + /* <Function> */ + /* TT_Set_Named_Instance */ + /* */ + /* <Description> */ + /* Set the given named instance, also resetting any further */ + /* variation. */ + /* */ + /* <Input> */ + /* face :: A handle to the source face. */ + /* */ + /* instance_index :: The instance index, starting with value 1. */ + /* Value 0 indicates to not use an instance. */ + /* */ + /* <Return> */ + /* FreeType error code. 0~means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + TT_Set_Named_Instance( TT_Face face, + FT_UInt instance_index ) + { + FT_Error error = FT_ERR( Invalid_Argument ); + GX_Blend blend; + FT_MM_Var* mmvar; - FT_TRACE5(( "design coordinates" - " after removing `avar' distortion:\n" )); + FT_UInt num_instances; - for ( i = 0; i < nc; i++, av++ ) - { - for ( j = 1; j < (FT_UInt)av->pairCount; j++ ) - { - if ( coords[i] < av->correspondence[j].toCoord ) - { - coords[i] = - FT_MulDiv( coords[i] - av->correspondence[j - 1].toCoord, - av->correspondence[j].fromCoord - - av->correspondence[j - 1].fromCoord, - av->correspondence[j].toCoord - - av->correspondence[j - 1].toCoord ) + - av->correspondence[j - 1].fromCoord; - FT_TRACE5(( " %.5f\n", coords[i] / 65536.0 )); - break; - } - } - } + if ( !face->blend ) + { + if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) ) + goto Exit; } + blend = face->blend; mmvar = blend->mmvar; - a = mmvar->axis; - for ( i = 0; i < nc; i++, a++ ) + num_instances = (FT_UInt)face->root.style_flags >> 16; + + /* `instance_index' starts with value 1, thus `>' */ + if ( instance_index > num_instances ) + goto Exit; + + if ( instance_index > 0 && mmvar->namedstyle ) { - if ( coords[i] < 0 ) - coords[i] = a->def + FT_MulFix( coords[i], - a->def - a->minimum ); - else if ( coords[i] > 0 ) - coords[i] = a->def + FT_MulFix( coords[i], - a->maximum - a->def ); - else - coords[i] = a->def; + FT_Memory memory = face->root.memory; + SFNT_Service sfnt = (SFNT_Service)face->sfnt; + + FT_Var_Named_Style* named_style; + FT_String* style_name; + + + named_style = mmvar->namedstyle + instance_index - 1; + + error = sfnt->get_name( face, + (FT_UShort)named_style->strid, + &style_name ); + if ( error ) + goto Exit; + + /* set (or replace) style name */ + FT_FREE( face->root.style_name ); + face->root.style_name = style_name; + + /* finally, select the named instance */ + error = TT_Set_Var_Design( face, + mmvar->num_axis, + named_style->coords ); + if ( error ) + goto Exit; } + else + error = TT_Set_Var_Design( face, 0, NULL ); - return FT_Err_Ok; + face->root.face_index = ( instance_index << 16 ) | + ( face->root.face_index & 0xFFFFL ); + face->root.face_flags &= ~FT_FACE_FLAG_VARIATION; + + Exit: + return error; } @@ -2067,8 +3059,10 @@ FT_Fixed* im_start_coords = NULL; FT_Fixed* im_end_coords = NULL; GX_Blend blend = face->blend; - FT_UInt point_count; - FT_UShort* localpoints; + FT_UInt point_count, spoint_count = 0; + FT_UShort* sharedpoints = NULL; + FT_UShort* localpoints = NULL; + FT_UShort* points; FT_Short* deltas; @@ -2137,11 +3131,24 @@ offsetToData += table_start; - /* The documentation implies there are flags packed into */ - /* `tupleCount', but John Jenkins says that shared points don't apply */ - /* to `cvar', and no other flags are defined. */ + if ( tupleCount & GX_TC_TUPLES_SHARE_POINT_NUMBERS ) + { + here = FT_Stream_FTell( stream ); + + FT_Stream_SeekSet( stream, offsetToData ); + + sharedpoints = ft_var_readpackedpoints( stream, + table_len, + &spoint_count ); + offsetToData = FT_Stream_FTell( stream ); + + FT_Stream_SeekSet( stream, here ); + } - FT_TRACE5(( "cvar: there are %d tuples:\n", tupleCount & 0xFFF )); + FT_TRACE5(( "cvar: there %s %d tuple%s:\n", + ( tupleCount & 0xFFF ) == 1 ? "is" : "are", + tupleCount & 0xFFF, + ( tupleCount & 0xFFF ) == 1 ? "" : "s" )); for ( i = 0; i < ( tupleCount & 0xFFF ); i++ ) { @@ -2155,26 +3162,25 @@ tupleDataSize = FT_GET_USHORT(); tupleIndex = FT_GET_USHORT(); - /* There is no provision here for a global tuple coordinate section, */ - /* so John says. There are no tuple indices, just embedded tuples. */ - if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD ) { for ( j = 0; j < blend->num_axis; j++ ) tuple_coords[j] = FT_GET_SHORT() * 4; /* convert from */ /* short frac to fixed */ } - else + else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount ) { - /* skip this tuple; it makes no sense */ - - if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) - for ( j = 0; j < 2 * blend->num_axis; j++ ) - (void)FT_GET_SHORT(); + FT_TRACE2(( "tt_face_vary_cvt:" + " invalid tuple index\n" )); - offsetToData += tupleDataSize; - continue; + error = FT_THROW( Invalid_Table ); + goto Exit; } + else + FT_MEM_COPY( + tuple_coords, + &blend->tuplecoords[( tupleIndex & 0xFFF ) * blend->num_axis], + blend->num_axis * sizeof ( FT_Fixed ) ); if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) { @@ -2189,11 +3195,8 @@ tuple_coords, im_start_coords, im_end_coords ); - if ( /* tuple isn't active for our blend */ - apply == 0 || - /* global points not allowed, */ - /* if they aren't local, makes no sense */ - !( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS ) ) + + if ( apply == 0 ) /* tuple isn't active for our blend */ { offsetToData += tupleDataSize; continue; @@ -2203,14 +3206,27 @@ FT_Stream_SeekSet( stream, offsetToData ); - localpoints = ft_var_readpackedpoints( stream, - table_len, - &point_count ); - deltas = ft_var_readpackeddeltas( stream, - table_len, - point_count == 0 ? face->cvt_size - : point_count ); - if ( !localpoints || !deltas ) + if ( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS ) + { + localpoints = ft_var_readpackedpoints( stream, + table_len, + &point_count ); + points = localpoints; + } + else + { + points = sharedpoints; + point_count = spoint_count; + } + + deltas = ft_var_readpackeddeltas( stream, + table_len, + point_count == 0 ? face->cvt_size + : point_count ); + + if ( !points || + !deltas || + ( localpoints == ALL_POINTS && point_count != face->cvt_size ) ) ; /* failure, ignore it */ else if ( localpoints == ALL_POINTS ) @@ -2262,7 +3278,7 @@ FT_Long orig_cvt; - pindex = localpoints[j]; + pindex = points[j]; if ( (FT_ULong)pindex >= face->cvt_size ) continue; @@ -2301,6 +3317,8 @@ FT_FRAME_EXIT(); Exit: + if ( sharedpoints != ALL_POINTS ) + FT_FREE( sharedpoints ); FT_FREE( tuple_coords ); FT_FREE( im_start_coords ); FT_FREE( im_end_coords ); @@ -2389,25 +3407,12 @@ d1 = out1 - in1; d2 = out2 - in2; - if ( out1 == out2 || in1 == in2 ) + /* If the reference points have the same coordinate but different */ + /* delta, inferred delta is zero. Otherwise interpolate. */ + if ( in1 != in2 || out1 == out2 ) { - for ( p = p1; p <= p2; p++ ) - { - out = in_points[p].x; - - if ( out <= in1 ) - out += d1; - else if ( out >= in2 ) - out += d2; - else - out = out1; - - out_points[p].x = out; - } - } - else - { - FT_Fixed scale = FT_DivFix( out2 - out1, in2 - in1 ); + FT_Fixed scale = in1 != in2 ? FT_DivFix( out2 - out1, in2 - in1 ) + : 0; for ( p = p1; p <= p2; p++ ) @@ -2600,7 +3605,6 @@ glyph_start = FT_Stream_FTell( stream ); /* each set of glyph variation data is formatted similarly to `cvar' */ - /* (except we get shared points and global tuples) */ if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis ) || FT_NEW_ARRAY( im_start_coords, blend->num_axis ) || @@ -2637,8 +3641,10 @@ FT_Stream_SeekSet( stream, here ); } - FT_TRACE5(( "gvar: there are %d tuples:\n", - tupleCount & GX_TC_TUPLE_COUNT_MASK )); + FT_TRACE5(( "gvar: there %s %d tuple%s:\n", + ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) == 1 ? "is" : "are", + tupleCount & GX_TC_TUPLE_COUNT_MASK, + ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) == 1 ? "" : "s" )); for ( j = 0; j < n_points; j++ ) points_org[j] = outline->points[j]; @@ -2740,7 +3746,7 @@ FT_Pos delta_y = FT_MulFix( deltas_y[j], apply ); - if ( j < n_points - 3 ) + if ( j < n_points - 4 ) { outline->points[j].x += delta_x; outline->points[j].y += delta_y; @@ -2750,25 +3756,25 @@ /* To avoid double adjustment of advance width or height, */ /* adjust phantom points only if there is no HVAR or VVAR */ /* support, respectively. */ - if ( j == ( n_points - 3 ) && - !( face->variation_support & - TT_FACE_FLAG_VAR_HADVANCE ) ) + if ( j == ( n_points - 4 ) && + !( face->variation_support & + TT_FACE_FLAG_VAR_LSB ) ) + outline->points[j].x += delta_x; + + else if ( j == ( n_points - 3 ) && + !( face->variation_support & + TT_FACE_FLAG_VAR_HADVANCE ) ) outline->points[j].x += delta_x; else if ( j == ( n_points - 2 ) && !( face->variation_support & - TT_FACE_FLAG_VAR_LSB ) ) - outline->points[j].x += delta_x; + TT_FACE_FLAG_VAR_TSB ) ) + outline->points[j].y += delta_y; else if ( j == ( n_points - 1 ) && !( face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ) outline->points[j].y += delta_y; - - else if ( j == ( n_points - 0 ) && - !( face->variation_support & - TT_FACE_FLAG_VAR_TSB ) ) - outline->points[j].y += delta_y; } #ifdef FT_DEBUG_LEVEL_TRACE @@ -2835,8 +3841,36 @@ FT_Pos delta_y = points_out[j].y - points_org[j].y; - outline->points[j].x += delta_x; - outline->points[j].y += delta_y; + if ( j < n_points - 4 ) + { + outline->points[j].x += delta_x; + outline->points[j].y += delta_y; + } + else + { + /* To avoid double adjustment of advance width or height, */ + /* adjust phantom points only if there is no HVAR or VVAR */ + /* support, respectively. */ + if ( j == ( n_points - 4 ) && + !( face->variation_support & + TT_FACE_FLAG_VAR_LSB ) ) + outline->points[j].x += delta_x; + + else if ( j == ( n_points - 3 ) && + !( face->variation_support & + TT_FACE_FLAG_VAR_HADVANCE ) ) + outline->points[j].x += delta_x; + + else if ( j == ( n_points - 2 ) && + !( face->variation_support & + TT_FACE_FLAG_VAR_TSB ) ) + outline->points[j].y += delta_y; + + else if ( j == ( n_points - 1 ) && + !( face->variation_support & + TT_FACE_FLAG_VAR_VADVANCE ) ) + outline->points[j].y += delta_y; + } #ifdef FT_DEBUG_LEVEL_TRACE if ( delta_x || delta_y ) @@ -2902,16 +3936,19 @@ tt_get_var_blend( TT_Face face, FT_UInt *num_coords, FT_Fixed* *coords, + FT_Fixed* *normalizedcoords, FT_MM_Var* *mm_var ) { if ( face->blend ) { if ( num_coords ) - *num_coords = face->blend->num_axis; + *num_coords = face->blend->num_axis; if ( coords ) - *coords = face->blend->normalizedcoords; + *coords = face->blend->coords; + if ( normalizedcoords ) + *normalizedcoords = face->blend->normalizedcoords; if ( mm_var ) - *mm_var = face->blend->mmvar; + *mm_var = face->blend->mmvar; } else { @@ -2927,6 +3964,35 @@ } + static void + ft_var_done_item_variation_store( TT_Face face, + GX_ItemVarStore itemStore ) + { + FT_Memory memory = FT_FACE_MEMORY( face ); + FT_UInt i; + + + if ( itemStore->varData ) + { + for ( i = 0; i < itemStore->dataCount; i++ ) + { + FT_FREE( itemStore->varData[i].regionIndices ); + FT_FREE( itemStore->varData[i].deltaSet ); + } + + FT_FREE( itemStore->varData ); + } + + if ( itemStore->varRegionList ) + { + for ( i = 0; i < itemStore->regionCount; i++ ) + FT_FREE( itemStore->varRegionList[i].axisList ); + + FT_FREE( itemStore->varRegionList ); + } + } + + /*************************************************************************/ /* */ /* <Function> */ @@ -2950,7 +4016,9 @@ /* blend->num_axis might not be set up yet */ num_axes = blend->mmvar->num_axis; + FT_FREE( blend->coords ); FT_FREE( blend->normalizedcoords ); + FT_FREE( blend->normalized_stylecoords ); FT_FREE( blend->mmvar ); if ( blend->avar_segment ) @@ -2962,35 +4030,45 @@ if ( blend->hvar_table ) { - if ( blend->hvar_table->itemStore.varData ) - { - for ( i = 0; i < blend->hvar_table->itemStore.dataCount; i++ ) - { - FT_FREE( blend->hvar_table->itemStore.varData[i].regionIndices ); - FT_FREE( blend->hvar_table->itemStore.varData[i].deltaSet ); - } - FT_FREE( blend->hvar_table->itemStore.varData ); - } - - if ( blend->hvar_table->itemStore.varRegionList ) - { - for ( i = 0; i < blend->hvar_table->itemStore.regionCount; i++ ) - FT_FREE( blend->hvar_table->itemStore.varRegionList[i].axisList ); - FT_FREE( blend->hvar_table->itemStore.varRegionList ); - } + ft_var_done_item_variation_store( face, + &blend->hvar_table->itemStore ); FT_FREE( blend->hvar_table->widthMap.innerIndex ); FT_FREE( blend->hvar_table->widthMap.outerIndex ); FT_FREE( blend->hvar_table ); } + if ( blend->vvar_table ) + { + ft_var_done_item_variation_store( face, + &blend->vvar_table->itemStore ); + + FT_FREE( blend->vvar_table->widthMap.innerIndex ); + FT_FREE( blend->vvar_table->widthMap.outerIndex ); + FT_FREE( blend->vvar_table ); + } + + if ( blend->mvar_table ) + { + ft_var_done_item_variation_store( face, + &blend->mvar_table->itemStore ); + + FT_FREE( blend->mvar_table->values ); + FT_FREE( blend->mvar_table ); + } + FT_FREE( blend->tuplecoords ); FT_FREE( blend->glyphoffsets ); FT_FREE( blend ); } } -#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ +#else /* !TT_CONFIG_OPTION_GX_VAR_SUPPORT */ + + /* ANSI C doesn't like empty source files */ + typedef int _tt_gxvar_dummy; + +#endif /* !TT_CONFIG_OPTION_GX_VAR_SUPPORT */ /* END */ diff --git a/modules/freetype2/src/truetype/ttgxvar.h b/modules/freetype2/src/truetype/ttgxvar.h index 215e109cc..a37bb9026 100644 --- a/modules/freetype2/src/truetype/ttgxvar.h +++ b/modules/freetype2/src/truetype/ttgxvar.h @@ -4,7 +4,7 @@ /* */ /* TrueType GX Font Variation loader (specification) */ /* */ -/* Copyright 2004-2016 by */ +/* Copyright 2004-2018 by */ /* David Turner, Robert Wilhelm, Werner Lemberg and George Williams. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -27,6 +27,8 @@ FT_BEGIN_HEADER +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + /*************************************************************************/ /* */ /* <Struct> */ @@ -61,7 +63,7 @@ FT_BEGIN_HEADER } GX_AVarSegmentRec, *GX_AVarSegment; - typedef struct GX_HVarDataRec_ + typedef struct GX_ItemVarDataRec_ { FT_UInt itemCount; /* number of delta sets per item */ FT_UInt regionIdxCount; /* number of region indices in this data */ @@ -70,7 +72,7 @@ FT_BEGIN_HEADER FT_Short* deltaSet; /* array of `itemCount' deltas */ /* use `innerIndex' for this array */ - } GX_HVarDataRec, *GX_HVarData; + } GX_ItemVarDataRec, *GX_ItemVarData; /* contribution of one axis to a region */ @@ -83,53 +85,128 @@ FT_BEGIN_HEADER } GX_AxisCoordsRec, *GX_AxisCoords; - typedef struct GX_HVarRegionRec_ + typedef struct GX_VarRegionRec_ { GX_AxisCoords axisList; /* array of axisCount records */ - } GX_HVarRegionRec, *GX_HVarRegion; + } GX_VarRegionRec, *GX_VarRegion; - /* HVAR item variation store */ - typedef struct GX_HVStoreRec_ + /* item variation store */ + typedef struct GX_ItemVarStoreRec_ { - FT_UInt dataCount; - GX_HVarData varData; /* array of dataCount records; */ - /* use `outerIndex' for this array */ - FT_UShort axisCount; - FT_UInt regionCount; /* total number of regions defined */ - GX_HVarRegion varRegionList; + FT_UInt dataCount; + GX_ItemVarData varData; /* array of dataCount records; */ + /* use `outerIndex' for this array */ + FT_UShort axisCount; + FT_UInt regionCount; /* total number of regions defined */ + GX_VarRegion varRegionList; - } GX_HVStoreRec, *GX_HVStore; + } GX_ItemVarStoreRec, *GX_ItemVarStore; - typedef struct GX_WidthMapRec_ + typedef struct GX_DeltaSetIdxMapRec_ { FT_UInt mapCount; FT_UInt* outerIndex; /* indices to item var data */ FT_UInt* innerIndex; /* indices to delta set */ - } GX_WidthMapRec, *GX_WidthMap; + } GX_DeltaSetIdxMapRec, *GX_DeltaSetIdxMap; /*************************************************************************/ /* */ /* <Struct> */ - /* GX_HVarTableRec */ + /* GX_HVVarTableRec */ /* */ /* <Description> */ - /* Data from the `HVAR' table. */ + /* Data from either the `HVAR' or `VVAR' table. */ /* */ - typedef struct GX_HVarTableRec_ + typedef struct GX_HVVarTableRec_ { - GX_HVStoreRec itemStore; /* Item Variation Store */ - GX_WidthMapRec widthMap; /* Advance Width Mapping */ + GX_ItemVarStoreRec itemStore; /* Item Variation Store */ + GX_DeltaSetIdxMapRec widthMap; /* Advance Width Mapping */ + #if 0 - GX_LSBMap LsbMap; /* not implemented */ - GX_RSBMap RsbMap; /* not implemented */ + GX_DeltaSetIdxMapRec lsbMap; /* not implemented */ + GX_DeltaSetIdxMapRec rsbMap; /* not implemented */ + + GX_DeltaSetIdxMapRec tsbMap; /* not implemented */ + GX_DeltaSetIdxMapRec bsbMap; /* not implemented */ + GX_DeltaSetIdxMapRec vorgMap; /* not implemented */ #endif - } GX_HVarTableRec, *GX_HVarTable; + } GX_HVVarTableRec, *GX_HVVarTable; + + +#define MVAR_TAG_GASP_0 FT_MAKE_TAG( 'g', 's', 'p', '0' ) +#define MVAR_TAG_GASP_1 FT_MAKE_TAG( 'g', 's', 'p', '1' ) +#define MVAR_TAG_GASP_2 FT_MAKE_TAG( 'g', 's', 'p', '2' ) +#define MVAR_TAG_GASP_3 FT_MAKE_TAG( 'g', 's', 'p', '3' ) +#define MVAR_TAG_GASP_4 FT_MAKE_TAG( 'g', 's', 'p', '4' ) +#define MVAR_TAG_GASP_5 FT_MAKE_TAG( 'g', 's', 'p', '5' ) +#define MVAR_TAG_GASP_6 FT_MAKE_TAG( 'g', 's', 'p', '6' ) +#define MVAR_TAG_GASP_7 FT_MAKE_TAG( 'g', 's', 'p', '7' ) +#define MVAR_TAG_GASP_8 FT_MAKE_TAG( 'g', 's', 'p', '8' ) +#define MVAR_TAG_GASP_9 FT_MAKE_TAG( 'g', 's', 'p', '9' ) + +#define MVAR_TAG_CPHT FT_MAKE_TAG( 'c', 'p', 'h', 't' ) +#define MVAR_TAG_HASC FT_MAKE_TAG( 'h', 'a', 's', 'c' ) +#define MVAR_TAG_HCLA FT_MAKE_TAG( 'h', 'c', 'l', 'a' ) +#define MVAR_TAG_HCLD FT_MAKE_TAG( 'h', 'c', 'l', 'd' ) +#define MVAR_TAG_HCOF FT_MAKE_TAG( 'h', 'c', 'o', 'f' ) +#define MVAR_TAG_HCRN FT_MAKE_TAG( 'h', 'c', 'r', 'n' ) +#define MVAR_TAG_HCRS FT_MAKE_TAG( 'h', 'c', 'r', 's' ) +#define MVAR_TAG_HDSC FT_MAKE_TAG( 'h', 'd', 's', 'c' ) +#define MVAR_TAG_HLGP FT_MAKE_TAG( 'h', 'l', 'g', 'p' ) +#define MVAR_TAG_SBXO FT_MAKE_TAG( 's', 'b', 'x', 'o' ) +#define MVAR_TAG_SBXS FT_MAKE_TAG( 's', 'b', 'x', 's' ) +#define MVAR_TAG_SBYO FT_MAKE_TAG( 's', 'b', 'y', 'o' ) +#define MVAR_TAG_SBYS FT_MAKE_TAG( 's', 'b', 'y', 's' ) +#define MVAR_TAG_SPXO FT_MAKE_TAG( 's', 'p', 'x', 'o' ) +#define MVAR_TAG_SPXS FT_MAKE_TAG( 's', 'p', 'x', 's' ) +#define MVAR_TAG_SPYO FT_MAKE_TAG( 's', 'p', 'y', 'o' ) +#define MVAR_TAG_SPYS FT_MAKE_TAG( 's', 'p', 'y', 's' ) +#define MVAR_TAG_STRO FT_MAKE_TAG( 's', 't', 'r', 'o' ) +#define MVAR_TAG_STRS FT_MAKE_TAG( 's', 't', 'r', 's' ) +#define MVAR_TAG_UNDO FT_MAKE_TAG( 'u', 'n', 'd', 'o' ) +#define MVAR_TAG_UNDS FT_MAKE_TAG( 'u', 'n', 'd', 's' ) +#define MVAR_TAG_VASC FT_MAKE_TAG( 'v', 'a', 's', 'c' ) +#define MVAR_TAG_VCOF FT_MAKE_TAG( 'v', 'c', 'o', 'f' ) +#define MVAR_TAG_VCRN FT_MAKE_TAG( 'v', 'c', 'r', 'n' ) +#define MVAR_TAG_VCRS FT_MAKE_TAG( 'v', 'c', 'r', 's' ) +#define MVAR_TAG_VDSC FT_MAKE_TAG( 'v', 'd', 's', 'c' ) +#define MVAR_TAG_VLGP FT_MAKE_TAG( 'v', 'l', 'g', 'p' ) +#define MVAR_TAG_XHGT FT_MAKE_TAG( 'x', 'h', 'g', 't' ) + + + typedef struct GX_ValueRec_ + { + FT_ULong tag; + FT_UShort outerIndex; + FT_UShort innerIndex; + + FT_Short unmodified; /* values are either FT_Short or FT_UShort */ + + } GX_ValueRec, *GX_Value; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* GX_MVarTableRec */ + /* */ + /* <Description> */ + /* Data from the `MVAR' table. */ + /* */ + typedef struct GX_MVarTableRec_ + { + FT_UShort valueCount; + + GX_ItemVarStoreRec itemStore; /* Item Variation Store */ + GX_Value values; /* Value Records */ + + } GX_MVarTableRec, *GX_MVarTable; /*************************************************************************/ @@ -139,37 +216,120 @@ FT_BEGIN_HEADER /* */ /* <Description> */ /* Data for interpolating a font from a distortable font specified */ - /* by the GX *var tables ([fgca]var). */ + /* by the GX *var tables ([fgcahvm]var). */ /* */ /* <Fields> */ - /* num_axis :: The number of axes along which interpolation */ - /* may happen */ + /* num_axis :: */ + /* The number of axes along which interpolation may happen. */ + /* */ + /* coords :: */ + /* An array of design coordinates (in user space) indicating the */ + /* contribution along each axis to the final interpolated font. */ + /* `normalizedcoords' holds the same values. */ + /* */ + /* normalizedcoords :: */ + /* An array of normalized values (between [-1,1]) indicating the */ + /* contribution along each axis to the final interpolated font. */ + /* `coords' holds the same values. */ + /* */ + /* mmvar :: */ + /* Data from the `fvar' table. */ + /* */ + /* mmvar_len :: */ + /* The length of the `mmvar' structure. */ + /* */ + /* normalized_stylecoords :: */ + /* A two-dimensional array that holds the named instance data from */ + /* `mmvar' as normalized values. */ + /* */ + /* avar_loaded :: */ + /* A Boolean; if set, FreeType tried to load (and parse) the `avar' */ + /* table. */ + /* */ + /* avar_segment :: */ + /* Data from the `avar' table. */ + /* */ + /* hvar_loaded :: */ + /* A Boolean; if set, FreeType tried to load (and parse) the `hvar' */ + /* table. */ /* */ - /* normalizedcoords :: A normalized value (between [-1,1]) indicating */ - /* the contribution along each axis to the final */ - /* interpolated font. */ + /* hvar_checked :: */ + /* A Boolean; if set, FreeType successfully loaded and parsed the */ + /* `hvar' table. */ + /* */ + /* hvar_error :: */ + /* If loading and parsing of the `hvar' table failed, this field */ + /* holds the corresponding error code. */ + /* */ + /* hvar_table :: */ + /* Data from the `hvar' table. */ + /* */ + /* vvar_loaded :: */ + /* A Boolean; if set, FreeType tried to load (and parse) the `vvar' */ + /* table. */ + /* */ + /* vvar_checked :: */ + /* A Boolean; if set, FreeType successfully loaded and parsed the */ + /* `vvar' table. */ + /* */ + /* vvar_error :: */ + /* If loading and parsing of the `vvar' table failed, this field */ + /* holds the corresponding error code. */ + /* */ + /* vvar_table :: */ + /* Data from the `vvar' table. */ + /* */ + /* mvar_table :: */ + /* Data from the `mvar' table. */ + /* */ + /* tuplecount :: */ + /* The number of shared tuples in the `gvar' table. */ + /* */ + /* tuplecoords :: */ + /* A two-dimensional array that holds the shared tuple coordinates */ + /* in the `gvar' table. */ + /* */ + /* gv_glyphcnt :: */ + /* The number of glyphs handled in the `gvar' table. */ + /* */ + /* glyphoffsets :: */ + /* Offsets into the glyph variation data array. */ + /* */ + /* gvar_size :: */ + /* The size of the `gvar' table. */ /* */ typedef struct GX_BlendRec_ { FT_UInt num_axis; + FT_Fixed* coords; FT_Fixed* normalizedcoords; FT_MM_Var* mmvar; FT_Offset mmvar_len; - FT_Bool avar_checked; - GX_AVarSegment avar_segment; + FT_Fixed* normalized_stylecoords; + /* normalized_stylecoords[num_namedstyles][num_axis] */ + + FT_Bool avar_loaded; + GX_AVarSegment avar_segment; /* avar_segment[num_axis] */ FT_Bool hvar_loaded; FT_Bool hvar_checked; FT_Error hvar_error; - GX_HVarTable hvar_table; + GX_HVVarTable hvar_table; + + FT_Bool vvar_loaded; + FT_Bool vvar_checked; + FT_Error vvar_error; + GX_HVVarTable vvar_table; + + GX_MVarTable mvar_table; - FT_UInt tuplecount; /* shared tuples in `gvar' */ - FT_Fixed* tuplecoords; /* tuplecoords[tuplecount][num_axis] */ + FT_UInt tuplecount; + FT_Fixed* tuplecoords; /* tuplecoords[tuplecount][num_axis] */ FT_UInt gv_glyphcnt; - FT_ULong* glyphoffsets; + FT_ULong* glyphoffsets; /* glyphoffsets[gv_glyphcnt + 1] */ FT_ULong gvar_size; @@ -244,6 +404,10 @@ FT_BEGIN_HEADER FT_Fixed* coords ); FT_LOCAL( FT_Error ) + TT_Set_Named_Instance( TT_Face face, + FT_UInt instance_index ); + + FT_LOCAL( FT_Error ) tt_face_vary_cvt( TT_Face face, FT_Stream stream ); @@ -260,14 +424,25 @@ FT_BEGIN_HEADER FT_Int *adelta ); FT_LOCAL( FT_Error ) + tt_vadvance_adjust( TT_Face face, + FT_UInt gindex, + FT_Int *adelta ); + + FT_LOCAL( void ) + tt_apply_mvar( TT_Face face ); + + FT_LOCAL( FT_Error ) tt_get_var_blend( TT_Face face, FT_UInt *num_coords, FT_Fixed* *coords, + FT_Fixed* *normalizedcoords, FT_MM_Var* *mm_var ); FT_LOCAL( void ) tt_done_blend( TT_Face face ); +#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ + FT_END_HEADER diff --git a/modules/freetype2/src/truetype/ttinterp.c b/modules/freetype2/src/truetype/ttinterp.c index 4a506ee81..da9b595ab 100644 --- a/modules/freetype2/src/truetype/ttinterp.c +++ b/modules/freetype2/src/truetype/ttinterp.c @@ -4,7 +4,7 @@ /* */ /* TrueType bytecode interpreter (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -25,7 +25,7 @@ #include FT_INTERNAL_CALC_H #include FT_TRIGONOMETRY_H #include FT_SYSTEM_H -#include FT_TRUETYPE_DRIVER_H +#include FT_DRIVER_H #include FT_MULTIPLE_MASTERS_H #include "ttinterp.h" @@ -65,11 +65,15 @@ TT_INTERPRETER_VERSION_40 ) #endif -#define PROJECT( v1, v2 ) \ - exc->func_project( exc, (v1)->x - (v2)->x, (v1)->y - (v2)->y ) +#define PROJECT( v1, v2 ) \ + exc->func_project( exc, \ + SUB_LONG( (v1)->x, (v2)->x ), \ + SUB_LONG( (v1)->y, (v2)->y ) ) -#define DUALPROJ( v1, v2 ) \ - exc->func_dualproj( exc, (v1)->x - (v2)->x, (v1)->y - (v2)->y ) +#define DUALPROJ( v1, v2 ) \ + exc->func_dualproj( exc, \ + SUB_LONG( (v1)->x, (v2)->x ), \ + SUB_LONG( (v1)->y, (v2)->y ) ) #define FAST_PROJECT( v ) \ exc->func_project( exc, (v)->x, (v)->y ) @@ -402,7 +406,7 @@ exec->IDefs = size->instruction_defs; exec->pointSize = size->point_size; exec->tt_metrics = size->ttmetrics; - exec->metrics = size->metrics; + exec->metrics = *size->metrics; exec->maxFunc = size->max_func; exec->maxIns = size->max_ins; @@ -1656,7 +1660,7 @@ /* zone :: The affected glyph zone. */ /* */ /* <Note> */ - /* See `ttinterp.h' for details on backwards compatibility mode. */ + /* See `ttinterp.h' for details on backward compatibility mode. */ /* `Touches' the point. */ /* */ static void @@ -1676,7 +1680,10 @@ if ( SUBPIXEL_HINTING_INFINALITY && ( !exc->ignore_x_mode || ( exc->sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) ) - zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P ); + zone->cur[point].x = ADD_LONG( zone->cur[point].x, + FT_MulDiv( distance, + v, + exc->F_dot_P ) ); else #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ @@ -1684,13 +1691,19 @@ /* Exception to the post-IUP curfew: Allow the x component of */ /* diagonal moves, but only post-IUP. DejaVu tries to adjust */ /* diagonal stems like on `Z' and `z' post-IUP. */ - if ( SUBPIXEL_HINTING_MINIMAL && !exc->backwards_compatibility ) - zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P ); + if ( SUBPIXEL_HINTING_MINIMAL && !exc->backward_compatibility ) + zone->cur[point].x = ADD_LONG( zone->cur[point].x, + FT_MulDiv( distance, + v, + exc->F_dot_P ) ); else #endif if ( NO_SUBPIXEL_HINTING ) - zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P ); + zone->cur[point].x = ADD_LONG( zone->cur[point].x, + FT_MulDiv( distance, + v, + exc->F_dot_P ) ); zone->tags[point] |= FT_CURVE_TAG_TOUCH_X; } @@ -1700,12 +1713,15 @@ if ( v != 0 ) { #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - if ( !( SUBPIXEL_HINTING_MINIMAL && - exc->backwards_compatibility && - exc->iupx_called && - exc->iupy_called ) ) + if ( !( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility && + exc->iupx_called && + exc->iupy_called ) ) #endif - zone->cur[point].y += FT_MulDiv( distance, v, exc->F_dot_P ); + zone->cur[point].y = ADD_LONG( zone->cur[point].y, + FT_MulDiv( distance, + v, + exc->F_dot_P ) ); zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y; } @@ -1741,12 +1757,18 @@ v = exc->GS.freeVector.x; if ( v != 0 ) - zone->org[point].x += FT_MulDiv( distance, v, exc->F_dot_P ); + zone->org[point].x = ADD_LONG( zone->org[point].x, + FT_MulDiv( distance, + v, + exc->F_dot_P ) ); v = exc->GS.freeVector.y; if ( v != 0 ) - zone->org[point].y += FT_MulDiv( distance, v, exc->F_dot_P ); + zone->org[point].y = ADD_LONG( zone->org[point].y, + FT_MulDiv( distance, + v, + exc->F_dot_P ) ); } @@ -1756,7 +1778,7 @@ /* */ /* The following versions are used whenever both vectors are both */ /* along one of the coordinate unit vectors, i.e. in 90% of the cases. */ - /* See `ttinterp.h' for details on backwards compatibility mode. */ + /* See `ttinterp.h' for details on backward compatibility mode. */ /* */ /*************************************************************************/ @@ -1769,18 +1791,18 @@ { #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY if ( SUBPIXEL_HINTING_INFINALITY && !exc->ignore_x_mode ) - zone->cur[point].x += distance; + zone->cur[point].x = ADD_LONG( zone->cur[point].x, distance ); else #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - if ( SUBPIXEL_HINTING_MINIMAL && !exc->backwards_compatibility ) - zone->cur[point].x += distance; + if ( SUBPIXEL_HINTING_MINIMAL && !exc->backward_compatibility ) + zone->cur[point].x = ADD_LONG( zone->cur[point].x, distance ); else #endif if ( NO_SUBPIXEL_HINTING ) - zone->cur[point].x += distance; + zone->cur[point].x = ADD_LONG( zone->cur[point].x, distance ); zone->tags[point] |= FT_CURVE_TAG_TOUCH_X; } @@ -1796,10 +1818,10 @@ #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL if ( !( SUBPIXEL_HINTING_MINIMAL && - exc->backwards_compatibility && + exc->backward_compatibility && exc->iupx_called && exc->iupy_called ) ) #endif - zone->cur[point].y += distance; + zone->cur[point].y = ADD_LONG( zone->cur[point].y, distance ); zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y; } @@ -1823,7 +1845,7 @@ { FT_UNUSED( exc ); - zone->org[point].x += distance; + zone->org[point].x = ADD_LONG( zone->org[point].x, distance ); } @@ -1835,7 +1857,7 @@ { FT_UNUSED( exc ); - zone->org[point].y += distance; + zone->org[point].y = ADD_LONG( zone->org[point].y, distance ); } @@ -1873,13 +1895,13 @@ if ( distance >= 0 ) { - val = distance + compensation; + val = ADD_LONG( distance, compensation ); if ( val < 0 ) val = 0; } else { - val = distance - compensation; + val = SUB_LONG( distance, compensation ); if ( val > 0 ) val = 0; } @@ -1915,13 +1937,14 @@ if ( distance >= 0 ) { - val = FT_PIX_ROUND( distance + compensation ); + val = FT_PIX_ROUND_LONG( ADD_LONG( distance, compensation ) ); if ( val < 0 ) val = 0; } else { - val = -FT_PIX_ROUND( compensation - distance ); + val = NEG_LONG( FT_PIX_ROUND_LONG( SUB_LONG( compensation, + distance ) ) ); if ( val > 0 ) val = 0; } @@ -1958,13 +1981,16 @@ if ( distance >= 0 ) { - val = FT_PIX_FLOOR( distance + compensation ) + 32; + val = ADD_LONG( FT_PIX_FLOOR( ADD_LONG( distance, compensation ) ), + 32 ); if ( val < 0 ) val = 32; } else { - val = -( FT_PIX_FLOOR( compensation - distance ) + 32 ); + val = NEG_LONG( ADD_LONG( FT_PIX_FLOOR( SUB_LONG( compensation, + distance ) ), + 32 ) ); if ( val > 0 ) val = -32; } @@ -2001,13 +2027,13 @@ if ( distance >= 0 ) { - val = FT_PIX_FLOOR( distance + compensation ); + val = FT_PIX_FLOOR( ADD_LONG( distance, compensation ) ); if ( val < 0 ) val = 0; } else { - val = -FT_PIX_FLOOR( compensation - distance ); + val = NEG_LONG( FT_PIX_FLOOR( SUB_LONG( compensation, distance ) ) ); if ( val > 0 ) val = 0; } @@ -2044,13 +2070,14 @@ if ( distance >= 0 ) { - val = FT_PIX_CEIL( distance + compensation ); + val = FT_PIX_CEIL_LONG( ADD_LONG( distance, compensation ) ); if ( val < 0 ) val = 0; } else { - val = -FT_PIX_CEIL( compensation - distance ); + val = NEG_LONG( FT_PIX_CEIL_LONG( SUB_LONG( compensation, + distance ) ) ); if ( val > 0 ) val = 0; } @@ -2087,13 +2114,14 @@ if ( distance >= 0 ) { - val = FT_PAD_ROUND( distance + compensation, 32 ); + val = FT_PAD_ROUND_LONG( ADD_LONG( distance, compensation ), 32 ); if ( val < 0 ) val = 0; } else { - val = -FT_PAD_ROUND( compensation - distance, 32 ); + val = NEG_LONG( FT_PAD_ROUND_LONG( SUB_LONG( compensation, distance ), + 32 ) ); if ( val > 0 ) val = 0; } @@ -2134,17 +2162,19 @@ if ( distance >= 0 ) { - val = ( distance - exc->phase + exc->threshold + compensation ) & + val = ADD_LONG( distance, + exc->threshold - exc->phase + compensation ) & -exc->period; - val += exc->phase; + val = ADD_LONG( val, exc->phase ); if ( val < 0 ) val = exc->phase; } else { - val = -( ( exc->threshold - exc->phase - distance + compensation ) & - -exc->period ); - val -= exc->phase; + val = NEG_LONG( SUB_LONG( exc->threshold - exc->phase + compensation, + distance ) & + -exc->period ); + val = SUB_LONG( val, exc->phase ); if ( val > 0 ) val = -exc->phase; } @@ -2183,17 +2213,19 @@ if ( distance >= 0 ) { - val = ( ( distance - exc->phase + exc->threshold + compensation ) / + val = ( ADD_LONG( distance, + exc->threshold - exc->phase + compensation ) / exc->period ) * exc->period; - val += exc->phase; + val = ADD_LONG( val, exc->phase ); if ( val < 0 ) val = exc->phase; } else { - val = -( ( ( exc->threshold - exc->phase - distance + compensation ) / - exc->period ) * exc->period ); - val -= exc->phase; + val = NEG_LONG( ( SUB_LONG( exc->threshold - exc->phase + compensation, + distance ) / + exc->period ) * exc->period ); + val = SUB_LONG( val, exc->phase ); if ( val > 0 ) val = -exc->phase; } @@ -2826,7 +2858,7 @@ static void Ins_ADD( FT_Long* args ) { - args[0] += args[1]; + args[0] = ADD_LONG( args[0], args[1] ); } @@ -2839,7 +2871,7 @@ static void Ins_SUB( FT_Long* args ) { - args[0] -= args[1]; + args[0] = SUB_LONG( args[0], args[1] ); } @@ -2882,7 +2914,8 @@ static void Ins_ABS( FT_Long* args ) { - args[0] = FT_ABS( args[0] ); + if ( args[0] < 0 ) + args[0] = NEG_LONG( args[0] ); } @@ -2895,7 +2928,7 @@ static void Ins_NEG( FT_Long* args ) { - args[0] = -args[0]; + args[0] = NEG_LONG( args[0] ); } @@ -2921,7 +2954,7 @@ static void Ins_CEILING( FT_Long* args ) { - args[0] = FT_PIX_CEIL( args[0] ); + args[0] = FT_PIX_CEIL_LONG( args[0] ); } @@ -3256,7 +3289,10 @@ if ( args[0] < 0 ) exc->error = FT_THROW( Bad_Argument ); else - exc->GS.loop = args[0]; + { + /* we heuristically limit the number of loops to 16 bits */ + exc->GS.loop = args[0] > 0xFFFFL ? 0xFFFFL : args[0]; + } } @@ -3564,6 +3600,13 @@ #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ + /* FDEF is only allowed in `prep' or `fpgm' */ + if ( exc->curRange == tt_coderange_glyph ) + { + exc->error = FT_THROW( DEF_In_Glyf_Bytecode ); + return; + } + /* some font programs are broken enough to redefine functions! */ /* We will then parse the current table. */ @@ -3990,6 +4033,13 @@ TT_DefRecord* limit; + /* we enable IDEF only in `prep' or `fpgm' */ + if ( exc->curRange == tt_coderange_glyph ) + { + exc->error = FT_THROW( DEF_In_Glyf_Bytecode ); + return; + } + /* First of all, look for the same function in our table */ def = exc->IDefs; @@ -4197,8 +4247,8 @@ p1 = exc->zp1.cur + aIdx2; p2 = exc->zp2.cur + aIdx1; - A = p1->x - p2->x; - B = p1->y - p2->y; + A = SUB_LONG( p1->x, p2->x ); + B = SUB_LONG( p1->y, p2->y ); /* If p1 == p2, SPvTL and SFvTL behave the same as */ /* SPvTCA[X] and SFvTCA[X], respectively. */ @@ -4213,9 +4263,9 @@ if ( ( opcode & 1 ) != 0 ) { - C = B; /* counter clockwise rotation */ - B = A; - A = -C; + C = B; /* counter clockwise rotation */ + B = A; + A = NEG_LONG( C ); } Normalize( A, B, Vec ); @@ -4756,7 +4806,7 @@ K = FAST_PROJECT( &exc->zp2.cur[L] ); - exc->func_move( exc, &exc->zp2, L, args[1] - K ); + exc->func_move( exc, &exc->zp2, L, SUB_LONG( args[1], K ) ); /* UNDOCUMENTED! The MS rasterizer does that with */ /* twilight points (confirmed by Greg Hitchcock) */ @@ -4880,12 +4930,12 @@ } { - FT_Vector* v1 = exc->zp1.org + p2; - FT_Vector* v2 = exc->zp2.org + p1; + FT_Vector* v1 = exc->zp1.org + p2; + FT_Vector* v2 = exc->zp2.org + p1; - A = v1->x - v2->x; - B = v1->y - v2->y; + A = SUB_LONG( v1->x, v2->x ); + B = SUB_LONG( v1->y, v2->y ); /* If v1 == v2, SDPvTL behaves the same as */ /* SVTCA[X], respectively. */ @@ -4901,9 +4951,9 @@ if ( ( opcode & 1 ) != 0 ) { - C = B; /* counter clockwise rotation */ - B = A; - A = -C; + C = B; /* counter clockwise rotation */ + B = A; + A = NEG_LONG( C ); } Normalize( A, B, &exc->GS.dualVector ); @@ -4913,8 +4963,8 @@ FT_Vector* v2 = exc->zp2.cur + p1; - A = v1->x - v2->x; - B = v1->y - v2->y; + A = SUB_LONG( v1->x, v2->x ); + B = SUB_LONG( v1->y, v2->y ); if ( A == 0 && B == 0 ) { @@ -4925,9 +4975,9 @@ if ( ( opcode & 1 ) != 0 ) { - C = B; /* counter clockwise rotation */ - B = A; - A = -C; + C = B; /* counter clockwise rotation */ + B = A; + A = NEG_LONG( C ); } Normalize( A, B, &exc->GS.projVector ); @@ -5112,11 +5162,11 @@ #endif #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - /* Native ClearType fonts sign a waiver that turns off all backwards */ + /* Native ClearType fonts sign a waiver that turns off all backward */ /* compatibility hacks and lets them program points to the grid like */ /* it's 1996. They might sign a waiver for just one glyph, though. */ if ( SUBPIXEL_HINTING_MINIMAL ) - exc->backwards_compatibility = !FT_BOOL( L == 4 ); + exc->backward_compatibility = !FT_BOOL( L == 4 ); #endif } } @@ -5204,11 +5254,11 @@ #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - /* See `ttinterp.h' for details on backwards compatibility mode. */ - if ( SUBPIXEL_HINTING_MINIMAL && - exc->backwards_compatibility && - exc->iupx_called && - exc->iupy_called ) + /* See `ttinterp.h' for details on backward compatibility mode. */ + if ( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility && + exc->iupx_called && + exc->iupy_called ) goto Fail; #endif @@ -5259,11 +5309,11 @@ #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - /* See `ttinterp.h' for details on backwards compatibility mode. */ - if ( SUBPIXEL_HINTING_MINIMAL && - exc->backwards_compatibility && - exc->iupx_called && - exc->iupy_called ) + /* See `ttinterp.h' for details on backward compatibility mode. */ + if ( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility && + exc->iupx_called && + exc->iupy_called ) return; #endif @@ -5297,11 +5347,11 @@ #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - /* See `ttinterp.h' for details on backwards compatibility mode. */ - if ( SUBPIXEL_HINTING_MINIMAL && - exc->backwards_compatibility && - exc->iupx_called && - exc->iupy_called ) + /* See `ttinterp.h' for details on backward compatibility mode. */ + if ( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility && + exc->iupx_called && + exc->iupy_called ) return; #endif @@ -5364,7 +5414,7 @@ } - /* See `ttinterp.h' for details on backwards compatibility mode. */ + /* See `ttinterp.h' for details on backward compatibility mode. */ static void Move_Zp2_Point( TT_ExecContext exc, FT_UShort point, @@ -5375,10 +5425,10 @@ if ( exc->GS.freeVector.x != 0 ) { #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - if ( !( SUBPIXEL_HINTING_MINIMAL && - exc->backwards_compatibility ) ) + if ( !( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility ) ) #endif - exc->zp2.cur[point].x += dx; + exc->zp2.cur[point].x = ADD_LONG( exc->zp2.cur[point].x, dx ); if ( touch ) exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X; @@ -5387,12 +5437,12 @@ if ( exc->GS.freeVector.y != 0 ) { #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - if ( !( SUBPIXEL_HINTING_MINIMAL && - exc->backwards_compatibility && - exc->iupx_called && - exc->iupy_called ) ) + if ( !( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility && + exc->iupx_called && + exc->iupy_called ) ) #endif - exc->zp2.cur[point].y += dy; + exc->zp2.cur[point].y = ADD_LONG( exc->zp2.cur[point].y, dy ); if ( touch ) exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y; @@ -5643,7 +5693,11 @@ ( B1 & 63 ) != 0 && ( B2 & 63 ) != 0 && B1 != B2 ) - Move_Zp2_Point( exc, point, -dx, -dy, TRUE ); + Move_Zp2_Point( exc, + point, + NEG_LONG( dx ), + NEG_LONG( dy ), + TRUE ); } } else if ( exc->face->sph_compatibility_mode ) @@ -5675,7 +5729,7 @@ if ( ( B1 & 63 ) == 0 && ( B2 & 63 ) != 0 && B1 != B2 ) - Move_Zp2_Point( exc, point, 0, -dy, TRUE ); + Move_Zp2_Point( exc, point, 0, NEG_LONG( dy ), TRUE ); } } else if ( exc->sph_in_func_flags & SPH_FDEF_TYPEMAN_DIAGENDCTRL ) @@ -5687,14 +5741,14 @@ else #endif #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - if ( SUBPIXEL_HINTING_MINIMAL && - exc->backwards_compatibility ) + if ( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility ) { /* Special case: allow SHPIX to move points in the twilight zone. */ /* Otherwise, treat SHPIX the same as DELTAP. Unbreaks various */ /* fonts such as older versions of Rokkitt and DTL Argo T Light */ - /* that would glitch severly after calling ALIGNRP after a blocked */ - /* SHPIX. */ + /* that would glitch severely after calling ALIGNRP after a */ + /* blocked SHPIX. */ if ( in_twilight || ( !( exc->iupx_called && exc->iupy_called ) && ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) || @@ -5731,6 +5785,7 @@ FT_F26Dot6 distance; #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY FT_F26Dot6 control_value_cutin = 0; + FT_F26Dot6 delta; if ( SUBPIXEL_HINTING_INFINALITY ) @@ -5766,15 +5821,22 @@ distance = PROJECT( exc->zp1.cur + point, exc->zp0.cur + exc->GS.rp0 ); #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY + delta = SUB_LONG( distance, args[1] ); + if ( delta < 0 ) + delta = NEG_LONG( delta ); + /* subpixel hinting - make MSIRP respect CVT cut-in; */ - if ( SUBPIXEL_HINTING_INFINALITY && - exc->ignore_x_mode && - exc->GS.freeVector.x != 0 && - FT_ABS( distance - args[1] ) >= control_value_cutin ) + if ( SUBPIXEL_HINTING_INFINALITY && + exc->ignore_x_mode && + exc->GS.freeVector.x != 0 && + delta >= control_value_cutin ) distance = args[1]; #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - exc->func_move( exc, &exc->zp1, point, args[1] - distance ); + exc->func_move( exc, + &exc->zp1, + point, + SUB_LONG( args[1], distance ) ); exc->GS.rp1 = exc->GS.rp0; exc->GS.rp2 = point; @@ -5815,16 +5877,18 @@ if ( SUBPIXEL_HINTING_INFINALITY && exc->ignore_x_mode && exc->GS.freeVector.x != 0 ) - distance = Round_None( - exc, - cur_dist, - exc->tt_metrics.compensations[0] ) - cur_dist; + distance = SUB_LONG( + Round_None( exc, + cur_dist, + exc->tt_metrics.compensations[0] ), + cur_dist ); else #endif - distance = exc->func_round( - exc, - cur_dist, - exc->tt_metrics.compensations[0] ) - cur_dist; + distance = SUB_LONG( + exc->func_round( exc, + cur_dist, + exc->tt_metrics.compensations[0] ), + cur_dist ); } else distance = 0; @@ -5924,7 +5988,14 @@ if ( ( exc->opcode & 1 ) != 0 ) /* rounding and control cut-in flag */ { - if ( FT_ABS( distance - org_dist ) > control_value_cutin ) + FT_F26Dot6 delta; + + + delta = SUB_LONG( distance, org_dist ); + if ( delta < 0 ) + delta = NEG_LONG( delta ); + + if ( delta > control_value_cutin ) distance = org_dist; #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY @@ -5941,7 +6012,7 @@ exc->tt_metrics.compensations[0] ); } - exc->func_move( exc, &exc->zp0, point, distance - org_dist ); + exc->func_move( exc, &exc->zp0, point, SUB_LONG( distance, org_dist ) ); Fail: exc->GS.rp0 = point; @@ -6013,8 +6084,10 @@ FT_Vector vec; - vec.x = FT_MulFix( vec1->x - vec2->x, exc->metrics.x_scale ); - vec.y = FT_MulFix( vec1->y - vec2->y, exc->metrics.y_scale ); + vec.x = FT_MulFix( SUB_LONG( vec1->x, vec2->x ), + exc->metrics.x_scale ); + vec.y = FT_MulFix( SUB_LONG( vec1->y, vec2->y ), + exc->metrics.y_scale ); org_dist = FAST_DUALPROJ( &vec ); } @@ -6022,8 +6095,12 @@ /* single width cut-in test */ - if ( FT_ABS( org_dist - exc->GS.single_width_value ) < - exc->GS.single_width_cutin ) + /* |org_dist - single_width_value| < single_width_cutin */ + if ( exc->GS.single_width_cutin > 0 && + org_dist < exc->GS.single_width_value + + exc->GS.single_width_cutin && + org_dist > exc->GS.single_width_value - + exc->GS.single_width_cutin ) { if ( org_dist >= 0 ) org_dist = exc->GS.single_width_value; @@ -6067,8 +6144,8 @@ } else { - if ( distance > -minimum_distance ) - distance = -minimum_distance; + if ( distance > NEG_LONG( minimum_distance ) ) + distance = NEG_LONG( minimum_distance ); } } @@ -6076,7 +6153,7 @@ org_dist = PROJECT( exc->zp1.cur + point, exc->zp0.cur + exc->GS.rp0 ); - exc->func_move( exc, &exc->zp1, point, distance - org_dist ); + exc->func_move( exc, &exc->zp1, point, SUB_LONG( distance, org_dist ) ); Fail: exc->GS.rp1 = exc->GS.rp0; @@ -6116,7 +6193,7 @@ minimum_distance = exc->GS.minimum_distance; control_value_cutin = exc->GS.control_value_cutin; point = (FT_UShort)args[0]; - cvtEntry = (FT_ULong)( args[1] + 1 ); + cvtEntry = (FT_ULong)( ADD_LONG( args[1], 1 ) ); #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY if ( SUBPIXEL_HINTING_INFINALITY && @@ -6199,6 +6276,9 @@ if ( exc->GS.gep0 == exc->GS.gep1 ) { + FT_F26Dot6 delta; + + /* XXX: According to Greg Hitchcock, the following wording is */ /* the right one: */ /* */ @@ -6211,7 +6291,11 @@ /* `ttinst2.doc', version 1.66, is thus incorrect since */ /* it implies `>=' instead of `>'. */ - if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin ) + delta = SUB_LONG( cvt_dist, org_dist ); + if ( delta < 0 ) + delta = NEG_LONG( delta ); + + if ( delta > control_value_cutin ) cvt_dist = org_dist; } @@ -6229,7 +6313,14 @@ exc->ignore_x_mode && exc->GS.gep0 == exc->GS.gep1 ) { - if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin ) + FT_F26Dot6 delta; + + + delta = SUB_LONG( cvt_dist, org_dist ); + if ( delta < 0 ) + delta = NEG_LONG( delta ); + + if ( delta > control_value_cutin ) cvt_dist = org_dist; } #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ @@ -6251,8 +6342,8 @@ } else { - if ( distance > -minimum_distance ) - distance = -minimum_distance; + if ( distance > NEG_LONG( minimum_distance ) ) + distance = NEG_LONG( minimum_distance ); } } @@ -6276,7 +6367,10 @@ } #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - exc->func_move( exc, &exc->zp1, point, distance - cur_dist ); + exc->func_move( exc, + &exc->zp1, + point, + SUB_LONG( distance, cur_dist ) ); #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY if ( SUBPIXEL_HINTING_INFINALITY ) @@ -6300,7 +6394,10 @@ } if ( reverse_move ) - exc->func_move( exc, &exc->zp1, point, -( distance - cur_dist ) ); + exc->func_move( exc, + &exc->zp1, + point, + SUB_LONG( cur_dist, distance ) ); } #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ @@ -6366,7 +6463,7 @@ distance = PROJECT( exc->zp1.cur + point, exc->zp0.cur + exc->GS.rp0 ); - exc->func_move( exc, &exc->zp1, point, -distance ); + exc->func_move( exc, &exc->zp1, point, NEG_LONG( distance ) ); } exc->GS.loop--; @@ -6423,19 +6520,19 @@ /* Cramer's rule */ - dbx = exc->zp0.cur[b1].x - exc->zp0.cur[b0].x; - dby = exc->zp0.cur[b1].y - exc->zp0.cur[b0].y; + dbx = SUB_LONG( exc->zp0.cur[b1].x, exc->zp0.cur[b0].x ); + dby = SUB_LONG( exc->zp0.cur[b1].y, exc->zp0.cur[b0].y ); - dax = exc->zp1.cur[a1].x - exc->zp1.cur[a0].x; - day = exc->zp1.cur[a1].y - exc->zp1.cur[a0].y; + dax = SUB_LONG( exc->zp1.cur[a1].x, exc->zp1.cur[a0].x ); + day = SUB_LONG( exc->zp1.cur[a1].y, exc->zp1.cur[a0].y ); - dx = exc->zp0.cur[b0].x - exc->zp1.cur[a0].x; - dy = exc->zp0.cur[b0].y - exc->zp1.cur[a0].y; + dx = SUB_LONG( exc->zp0.cur[b0].x, exc->zp1.cur[a0].x ); + dy = SUB_LONG( exc->zp0.cur[b0].y, exc->zp1.cur[a0].y ); - discriminant = FT_MulDiv( dax, -dby, 0x40 ) + - FT_MulDiv( day, dbx, 0x40 ); - dotproduct = FT_MulDiv( dax, dbx, 0x40 ) + - FT_MulDiv( day, dby, 0x40 ); + discriminant = ADD_LONG( FT_MulDiv( dax, NEG_LONG( dby ), 0x40 ), + FT_MulDiv( day, dbx, 0x40 ) ); + dotproduct = ADD_LONG( FT_MulDiv( dax, dbx, 0x40 ), + FT_MulDiv( day, dby, 0x40 ) ); /* The discriminant above is actually a cross product of vectors */ /* da and db. Together with the dot product, they can be used as */ @@ -6445,30 +6542,29 @@ /* discriminant = |da||db|sin(angle) . */ /* We use these equations to reject grazing intersections by */ /* thresholding abs(tan(angle)) at 1/19, corresponding to 3 degrees. */ - if ( 19 * FT_ABS( discriminant ) > FT_ABS( dotproduct ) ) + if ( MUL_LONG( 19, FT_ABS( discriminant ) ) > FT_ABS( dotproduct ) ) { - val = FT_MulDiv( dx, -dby, 0x40 ) + FT_MulDiv( dy, dbx, 0x40 ); + val = ADD_LONG( FT_MulDiv( dx, NEG_LONG( dby ), 0x40 ), + FT_MulDiv( dy, dbx, 0x40 ) ); R.x = FT_MulDiv( val, dax, discriminant ); R.y = FT_MulDiv( val, day, discriminant ); - /* XXX: Block in backwards_compatibility and/or post-IUP? */ - exc->zp2.cur[point].x = exc->zp1.cur[a0].x + R.x; - exc->zp2.cur[point].y = exc->zp1.cur[a0].y + R.y; + /* XXX: Block in backward_compatibility and/or post-IUP? */ + exc->zp2.cur[point].x = ADD_LONG( exc->zp1.cur[a0].x, R.x ); + exc->zp2.cur[point].y = ADD_LONG( exc->zp1.cur[a0].y, R.y ); } else { /* else, take the middle of the middles of A and B */ - /* XXX: Block in backwards_compatibility and/or post-IUP? */ - exc->zp2.cur[point].x = ( exc->zp1.cur[a0].x + - exc->zp1.cur[a1].x + - exc->zp0.cur[b0].x + - exc->zp0.cur[b1].x ) / 4; - exc->zp2.cur[point].y = ( exc->zp1.cur[a0].y + - exc->zp1.cur[a1].y + - exc->zp0.cur[b0].y + - exc->zp0.cur[b1].y ) / 4; + /* XXX: Block in backward_compatibility and/or post-IUP? */ + exc->zp2.cur[point].x = + ADD_LONG( ADD_LONG( exc->zp1.cur[a0].x, exc->zp1.cur[a1].x ), + ADD_LONG( exc->zp0.cur[b0].x, exc->zp0.cur[b1].x ) ) / 4; + exc->zp2.cur[point].y = + ADD_LONG( ADD_LONG( exc->zp1.cur[a0].y, exc->zp1.cur[a1].y ), + ADD_LONG( exc->zp0.cur[b0].y, exc->zp0.cur[b1].y ) ) / 4; } exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH; @@ -6503,7 +6599,7 @@ distance = PROJECT( exc->zp0.cur + p2, exc->zp1.cur + p1 ) / 2; exc->func_move( exc, &exc->zp1, p1, distance ); - exc->func_move( exc, &exc->zp0, p2, -distance ); + exc->func_move( exc, &exc->zp0, p2, NEG_LONG( distance ) ); } @@ -6576,9 +6672,11 @@ FT_Vector vec; - vec.x = FT_MulFix( exc->zp1.orus[exc->GS.rp2].x - orus_base->x, + vec.x = FT_MulFix( SUB_LONG( exc->zp1.orus[exc->GS.rp2].x, + orus_base->x ), exc->metrics.x_scale ); - vec.y = FT_MulFix( exc->zp1.orus[exc->GS.rp2].y - orus_base->y, + vec.y = FT_MulFix( SUB_LONG( exc->zp1.orus[exc->GS.rp2].y, + orus_base->y ), exc->metrics.y_scale ); old_range = FAST_DUALPROJ( &vec ); @@ -6613,9 +6711,11 @@ FT_Vector vec; - vec.x = FT_MulFix( exc->zp2.orus[point].x - orus_base->x, + vec.x = FT_MulFix( SUB_LONG( exc->zp2.orus[point].x, + orus_base->x ), exc->metrics.x_scale ); - vec.y = FT_MulFix( exc->zp2.orus[point].y - orus_base->y, + vec.y = FT_MulFix( SUB_LONG( exc->zp2.orus[point].y, + orus_base->y ), exc->metrics.y_scale ); org_dist = FAST_DUALPROJ( &vec ); @@ -6654,7 +6754,7 @@ exc->func_move( exc, &exc->zp2, (FT_UShort)point, - new_dist - cur_dist ); + SUB_LONG( new_dist, cur_dist ) ); } Fail: @@ -6719,14 +6819,14 @@ FT_F26Dot6 dx; - dx = worker->curs[p].x - worker->orgs[p].x; + dx = SUB_LONG( worker->curs[p].x, worker->orgs[p].x ); if ( dx != 0 ) { for ( i = p1; i < p; i++ ) - worker->curs[i].x += dx; + worker->curs[i].x = ADD_LONG( worker->curs[i].x, dx ); for ( i = p + 1; i <= p2; i++ ) - worker->curs[i].x += dx; + worker->curs[i].x = ADD_LONG( worker->curs[i].x, dx ); } } @@ -6771,8 +6871,8 @@ org2 = worker->orgs[ref2].x; cur1 = worker->curs[ref1].x; cur2 = worker->curs[ref2].x; - delta1 = cur1 - org1; - delta2 = cur2 - org2; + delta1 = SUB_LONG( cur1, org1 ); + delta2 = SUB_LONG( cur2, org2 ); if ( cur1 == cur2 || orus1 == orus2 ) { @@ -6784,10 +6884,10 @@ if ( x <= org1 ) - x += delta1; + x = ADD_LONG( x, delta1 ); else if ( x >= org2 ) - x += delta2; + x = ADD_LONG( x, delta2 ); else x = cur1; @@ -6808,20 +6908,23 @@ if ( x <= org1 ) - x += delta1; + x = ADD_LONG( x, delta1 ); else if ( x >= org2 ) - x += delta2; + x = ADD_LONG( x, delta2 ); else { if ( !scale_valid ) { scale_valid = 1; - scale = FT_DivFix( cur2 - cur1, orus2 - orus1 ); + scale = FT_DivFix( SUB_LONG( cur2, cur1 ), + SUB_LONG( orus2, orus1 ) ); } - x = cur1 + FT_MulFix( worker->orus[i].x - orus1, scale ); + x = ADD_LONG( cur1, + FT_MulFix( SUB_LONG( worker->orus[i].x, orus1 ), + scale ) ); } worker->curs[i].x = x; } @@ -6852,11 +6955,11 @@ #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - /* See `ttinterp.h' for details on backwards compatibility mode. */ + /* See `ttinterp.h' for details on backward compatibility mode. */ /* Allow IUP until it has been called on both axes. Immediately */ /* return on subsequent ones. */ - if ( SUBPIXEL_HINTING_MINIMAL && - exc->backwards_compatibility ) + if ( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility ) { if ( exc->iupx_called && exc->iupy_called ) return; @@ -7089,7 +7192,7 @@ SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP ) && ( B1 & 63 ) != 0 && ( B2 & 63 ) != 0 ) ) ) - exc->func_move( exc, &exc->zp0, A, -B ); + exc->func_move( exc, &exc->zp0, A, NEG_LONG( B ) ); } } else @@ -7098,10 +7201,10 @@ { #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - /* See `ttinterp.h' for details on backwards compatibility */ - /* mode. */ - if ( SUBPIXEL_HINTING_MINIMAL && - exc->backwards_compatibility ) + /* See `ttinterp.h' for details on backward compatibility */ + /* mode. */ + if ( SUBPIXEL_HINTING_MINIMAL && + exc->backward_compatibility ) { if ( !( exc->iupx_called && exc->iupy_called ) && ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) || @@ -7245,7 +7348,7 @@ { if ( exc->ignore_x_mode ) { - /* if in ClearType backwards compatibility mode, */ + /* if in ClearType backward compatibility mode, */ /* we sometimes change the TrueType version dynamically */ K = exc->rasterizer_version; FT_TRACE6(( "Setting rasterizer version %d\n", @@ -7296,7 +7399,11 @@ K |= 1 << 12; #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - if ( SUBPIXEL_HINTING_MINIMAL ) + /* Toggle the following flags only outside of monochrome mode. */ + /* Otherwise, instructions may behave weirdly and rendering results */ + /* may differ between v35 and v40 mode, e.g., in `Times New Roman */ + /* Bold Italic'. */ + if ( SUBPIXEL_HINTING_MINIMAL && exc->subpixel_hinting_lean ) { /********************************/ /* HINTING FOR SUBPIXEL */ @@ -7331,7 +7438,7 @@ /* */ /* The only smoothing method FreeType supports unless someone sets */ /* FT_LOAD_TARGET_MONO. */ - if ( ( args[0] & 2048 ) != 0 ) + if ( ( args[0] & 2048 ) != 0 && exc->subpixel_hinting_lean ) K |= 1 << 18; /********************************/ @@ -7456,8 +7563,16 @@ return; } - for ( i = 0; i < num_axes; i++ ) - args[i] = coords[i] >> 2; /* convert 16.16 to 2.14 format */ + if ( coords ) + { + for ( i = 0; i < num_axes; i++ ) + args[i] = coords[i] >> 2; /* convert 16.16 to 2.14 format */ + } + else + { + for ( i = 0; i < num_axes; i++ ) + args[i] = 0; + } } @@ -7575,15 +7690,25 @@ #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - /* Toggle backwards compatibility according to what font says, except */ - /* when it's a `tricky' font that heavily relies on the interpreter to */ - /* render glyphs correctly, e.g. DFKai-SB. Backwards compatibility */ - /* hacks may break it. */ + /* + * Toggle backward compatibility according to what font wants, except + * when + * + * 1) we have a `tricky' font that heavily relies on the interpreter to + * render glyphs correctly, for example DFKai-SB, or + * 2) FT_RENDER_MODE_MONO (i.e, monochome rendering) is requested. + * + * In those cases, backward compatibility needs to be turned off to get + * correct rendering. The rendering is then completely up to the + * font's programming. + * + */ if ( SUBPIXEL_HINTING_MINIMAL && + exc->subpixel_hinting_lean && !FT_IS_TRICKY( &exc->face->root ) ) - exc->backwards_compatibility = !( exc->GS.instruct_control & 4 ); + exc->backward_compatibility = !( exc->GS.instruct_control & 4 ); else - exc->backwards_compatibility = FALSE; + exc->backward_compatibility = FALSE; exc->iupx_called = FALSE; exc->iupy_called = FALSE; @@ -7605,21 +7730,34 @@ exc->twilight.n_points = (FT_UShort)num_twilight_points; } - /* Set up loop detectors. We restrict the number of LOOPCALL loops */ - /* and the number of JMPR, JROT, and JROF calls with a negative */ - /* argument to values that depend on the size of the CVT table and */ - /* the number of points in the current glyph (if applicable). */ - /* */ - /* The idea is that in real-world bytecode you either iterate over */ - /* all CVT entries, or over all points (or contours) of a glyph, and */ - /* such iterations don't happen very often. */ + /* Set up loop detectors. We restrict the number of LOOPCALL loops */ + /* and the number of JMPR, JROT, and JROF calls with a negative */ + /* argument to values that depend on various parameters like the */ + /* size of the CVT table or the number of points in the current */ + /* glyph (if applicable). */ + /* */ + /* The idea is that in real-world bytecode you either iterate over */ + /* all CVT entries (in the `prep' table), or over all points (or */ + /* contours, in the `glyf' table) of a glyph, and such iterations */ + /* don't happen very often. */ exc->loopcall_counter = 0; exc->neg_jump_counter = 0; /* The maximum values are heuristic. */ - exc->loopcall_counter_max = FT_MAX( 100, - 10 * ( exc->pts.n_points + - exc->cvtSize ) ); + if ( exc->pts.n_points ) + exc->loopcall_counter_max = FT_MAX( 50, + 10 * exc->pts.n_points ) + + FT_MAX( 50, + exc->cvtSize / 10 ); + else + exc->loopcall_counter_max = 300 + 8 * exc->cvtSize; + + /* as a protection against an unreasonable number of CVT entries */ + /* we assume at most 100 control values per glyph for the counter */ + if ( exc->loopcall_counter_max > + 100 * (FT_ULong)exc->face->root.num_glyphs ) + exc->loopcall_counter_max = 100 * (FT_ULong)exc->face->root.num_glyphs; + FT_TRACE5(( "TT_RunIns: Limiting total number of loops in LOOPCALL" " to %d\n", exc->loopcall_counter_max )); @@ -8387,30 +8525,27 @@ } while ( !exc->instruction_trap ); LNo_Error_: - FT_TRACE4(( " %d instructions executed\n", ins_counter )); + FT_TRACE4(( " %d instruction%s executed\n", + ins_counter, + ins_counter == 1 ? "" : "s" )); return FT_Err_Ok; LErrorCodeOverflow_: exc->error = FT_THROW( Code_Overflow ); LErrorLabel_: - /* If any errors have occurred, function tables may be broken. */ - /* Force a re-execution of `prep' and `fpgm' tables if no */ - /* bytecode debugger is run. */ - if ( exc->error && - !exc->instruction_trap && - exc->curRange == tt_coderange_glyph ) - { + if ( exc->error && !exc->instruction_trap ) FT_TRACE1(( " The interpreter returned error 0x%x\n", exc->error )); - exc->size->bytecode_ready = -1; - exc->size->cvt_ready = -1; - } return exc->error; } +#else /* !TT_USE_BYTECODE_INTERPRETER */ + + /* ANSI C doesn't like empty source files */ + typedef int _tt_interp_dummy; -#endif /* TT_USE_BYTECODE_INTERPRETER */ +#endif /* !TT_USE_BYTECODE_INTERPRETER */ /* END */ diff --git a/modules/freetype2/src/truetype/ttinterp.h b/modules/freetype2/src/truetype/ttinterp.h index 33a9b122f..2966439ea 100644 --- a/modules/freetype2/src/truetype/ttinterp.h +++ b/modules/freetype2/src/truetype/ttinterp.h @@ -4,7 +4,7 @@ /* */ /* TrueType bytecode interpreter (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -253,23 +253,38 @@ FT_BEGIN_HEADER #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL /* - * Modern TrueType fonts are usually rendered through Microsoft's - * collection of rendering techniques called ClearType (e.g., subpixel - * rendering and subpixel hinting). When ClearType was introduced, most - * fonts were not ready. Microsoft decided to implement a backwards - * compatibility mode that employed several simple to complicated - * assumptions and tricks that modified the interpretation of the - * bytecode contained in these fonts to make them look ClearType-y - * somehow. Most (web)fonts that were released since then have come to - * rely on these hacks to render correctly, even some of Microsoft's - * flagship ClearType fonts (Calibri, Cambria, Segoe UI). + * FreeType supports ClearType-like hinting of TrueType fonts through + * the version 40 interpreter. This is achieved through several hacks + * in the base (v35) interpreter, as detailed below. * - * The minimal subpixel hinting code (interpreter version 40) employs a - * small list of font-agnostic hacks to bludgeon non-native-ClearType - * fonts (except tricky ones[1]) into submission. It will not try to - * toggle hacks for specific fonts for performance and complexity - * reasons. The focus is on modern (web)fonts rather than legacy fonts - * that were made for black-and-white rendering. + * ClearType is an umbrella term for several rendering techniques + * employed by Microsoft's various GUI and rendering toolkit + * implementations, most importantly: subpixel rendering for using the + * RGB subpixels of LCDs to approximately triple the perceived + * resolution on the x-axis and subpixel hinting for positioning stems + * on subpixel borders. TrueType programming is explicit, i.e., fonts + * must be programmed to take advantage of ClearType's possibilities. + * + * When ClearType was introduced, it seemed unlikely that all fonts + * would be reprogrammed, so Microsoft decided to implement a backward + * compatibility mode. It employs several simple to complicated + * assumptions and tricks, many of them font-dependent, that modify the + * interpretation of the bytecode contained in these fonts to retrofit + * them into a ClearType-y look. The quality of the results varies. + * Most (web)fonts that were released since then have come to rely on + * these hacks to render correctly, even some of Microsoft's flagship + * fonts (e.g., Calibri, Cambria, Segoe UI). + * + * FreeType's minimal subpixel hinting code (interpreter version 40) + * employs a small list of font-agnostic hacks loosely based on the + * public information available on Microsoft's compatibility mode[2]. + * The focus is on modern (web)fonts rather than legacy fonts that were + * made for monochrome rendering. It will not match ClearType rendering + * exactly. Unlike the `Infinality' code (interpreter version 38) that + * came before, it will not try to toggle hacks for specific fonts for + * performance and complexity reasons. It will fall back to version 35 + * behavior for tricky fonts[1] or when monochrome rendering is + * requested. * * Major hacks * @@ -316,12 +331,12 @@ FT_BEGIN_HEADER * very specific patterns (`superhinting') for pre-ClearType-displays, * the worse the results. * - * Microsoft defines a way to turn off backwards compatibility and + * Microsoft defines a way to turn off backward compatibility and * interpret instructions as before (called `native ClearType')[2][3]. * The font designer then regains full control and is responsible for * making the font work correctly with ClearType without any * hand-holding by the interpreter or rasterizer[4]. The v40 - * interpreter assumes backwards compatibility by default, which can be + * interpreter assumes backward compatibility by default, which can be * turned off the same way by executing the following in the control * program (cf. `Ins_INSTCTRL'). * @@ -331,7 +346,7 @@ FT_BEGIN_HEADER * [1] Tricky fonts as FreeType defines them rely on the bytecode * interpreter to display correctly. Hacks can interfere with them, * so they get treated like native ClearType fonts (v40 with - * backwards compatibility turned off). Cf. `TT_RunIns'. + * backward compatibility turned off). Cf. `TT_RunIns'. * * [2] Proposed by Microsoft's Greg Hitchcock in * https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx @@ -347,7 +362,8 @@ FT_BEGIN_HEADER * */ - /* Using v40 implies subpixel hinting. Used to detect interpreter */ + /* Using v40 implies subpixel hinting, unless FT_RENDER_MODE_MONO has been + * requested. Used to detect interpreter */ /* version switches. `_lean' to differentiate from the Infinality */ /* `subpixel_hinting', which is managed differently. */ FT_Bool subpixel_hinting_lean; @@ -357,10 +373,10 @@ FT_BEGIN_HEADER /* is managed differently. */ FT_Bool vertical_lcd_lean; - /* Default to backwards compatibility mode in v40 interpreter. If */ + /* Default to backward compatibility mode in v40 interpreter. If */ /* this is false, it implies the interpreter is in v35 or in native */ /* ClearType mode. */ - FT_Bool backwards_compatibility; + FT_Bool backward_compatibility; /* Useful for detecting and denying post-IUP trickery that is usually */ /* used to fix pixel patterns (`superhinting'). */ diff --git a/modules/freetype2/src/truetype/ttobjs.c b/modules/freetype2/src/truetype/ttobjs.c index 7e37113f9..6685dc819 100644 --- a/modules/freetype2/src/truetype/ttobjs.c +++ b/modules/freetype2/src/truetype/ttobjs.c @@ -4,7 +4,7 @@ /* */ /* Objects manager (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -21,7 +21,7 @@ #include FT_INTERNAL_STREAM_H #include FT_TRUETYPE_TAGS_H #include FT_INTERNAL_SFNT_H -#include FT_TRUETYPE_DRIVER_H +#include FT_DRIVER_H #include "ttgload.h" #include "ttpload.h" @@ -147,20 +147,51 @@ { #define TRICK_NAMES_MAX_CHARACTERS 19 -#define TRICK_NAMES_COUNT 9 +#define TRICK_NAMES_COUNT 26 static const char trick_names[TRICK_NAMES_COUNT] [TRICK_NAMES_MAX_CHARACTERS + 1] = { + /* + PostScript names are given in brackets if they differ from the + family name. The version numbers, together with the copyright or + release year data, are taken from fonts available to the + developers. + + Note that later versions of the fonts might be no longer tricky; + for example, `MingLiU' version 7.00 (file `mingliu.ttc' from + Windows 7) is an ordinary TTC with non-tricky subfonts. + */ + + "cpop", /* dftt-p7.ttf; version 1.00, 1992 [DLJGyShoMedium] */ + "DFGirl-W6-WIN-BF", /* dftt-h6.ttf; version 1.00, 1993 */ + "DFGothic-EB", /* DynaLab Inc. 1992-1995 */ + "DFGyoSho-Lt", /* DynaLab Inc. 1992-1995 */ + "DFHei-Md-HK-BF", /* maybe DynaLab Inc. */ + "DFHSGothic-W5", /* DynaLab Inc. 1992-1995 */ + "DFHSMincho-W3", /* DynaLab Inc. 1992-1995 */ + "DFHSMincho-W7", /* DynaLab Inc. 1992-1995 */ "DFKaiSho-SB", /* dfkaisb.ttf */ "DFKaiShu", - "DFKai-SB", /* kaiu.ttf */ + "DFKaiShu-Md-HK-BF", /* maybe DynaLab Inc. */ + "DFKai-SB", /* kaiu.ttf; version 3.00, 1998 [DFKaiShu-SB-Estd-BF] */ + "DFMing-Bd-HK-BF", /* maybe DynaLab Inc. */ + "DLC", /* dftt-m7.ttf; version 1.00, 1993 [DLCMingBold] */ + /* dftt-f5.ttf; version 1.00, 1993 [DLCFongSung] */ + "DLCHayMedium", /* dftt-b5.ttf; version 1.00, 1993 */ + "DLCHayBold", /* dftt-b7.ttf; version 1.00, 1993 */ + "DLCKaiMedium", /* dftt-k5.ttf; version 1.00, 1992 */ + "DLCLiShu", /* dftt-l5.ttf; version 1.00, 1992 */ + "DLCRoundBold", /* dftt-r7.ttf; version 1.00, 1993 */ "HuaTianKaiTi?", /* htkt2.ttf */ "HuaTianSongTi?", /* htst3.ttf */ - "Ming(for ISO10646)", /* hkscsiic.ttf & iicore.ttf */ - "MingLiU", /* mingliu.ttf & mingliu.ttc */ - "PMingLiU", /* mingliu.ttc */ - "MingLi43", /* mingli.ttf */ + "Ming(for ISO10646)", /* hkscsiic.ttf; version 0.12, 2007 [Ming] */ + /* iicore.ttf; version 0.07, 2007 [Ming] */ + "MingLiU", /* mingliu.ttf */ + /* mingliu.ttc; version 3.21, 2001 */ + "MingMedium", /* dftt-m5.ttf; version 1.00, 1993 [DLCMingMedium] */ + "PMingLiU", /* mingliu.ttc; version 3.21, 2001 */ + "MingLi43", /* mingli.ttf; version 1.00, 1992 */ }; int nn; @@ -242,7 +273,7 @@ tt_check_trickyness_sfnt_ids( TT_Face face ) { #define TRICK_SFNT_IDS_PER_FACE 3 -#define TRICK_SFNT_IDS_NUM_FACES 18 +#define TRICK_SFNT_IDS_NUM_FACES 29 static const tt_sfnt_id_rec sfnt_id[TRICK_SFNT_IDS_NUM_FACES] [TRICK_SFNT_IDS_PER_FACE] = { @@ -261,16 +292,66 @@ { 0x28233BF1UL, 0x000087C4UL }, /* fpgm */ { 0xA344A1EBUL, 0x000001E1UL } /* prep */ }, + { /* DFGothic-EB */ + { 0x12C3EBB2UL, 0x00000350UL }, /* cvt */ + { 0xB680EE64UL, 0x000087A7UL }, /* fpgm */ + { 0xCE939563UL, 0x00000758UL } /* prep */ + }, + { /* DFGyoSho-Lt */ + { 0x11E5EAD4UL, 0x00000350UL }, /* cvt */ + { 0xCE5956E9UL, 0x0000BC85UL }, /* fpgm */ + { 0x8272F416UL, 0x00000045UL } /* prep */ + }, + { /* DFHei-Md-HK-BF */ + { 0x1257EB46UL, 0x00000350UL }, /* cvt */ + { 0xF699D160UL, 0x0000715FUL }, /* fpgm */ + { 0xD222F568UL, 0x000003BCUL } /* prep */ + }, + { /* DFHSGothic-W5 */ + { 0x1262EB4EUL, 0x00000350UL }, /* cvt */ + { 0xE86A5D64UL, 0x00007940UL }, /* fpgm */ + { 0x7850F729UL, 0x000005FFUL } /* prep */ + }, + { /* DFHSMincho-W3 */ + { 0x122DEB0AUL, 0x00000350UL }, /* cvt */ + { 0x3D16328AUL, 0x0000859BUL }, /* fpgm */ + { 0xA93FC33BUL, 0x000002CBUL } /* prep */ + }, + { /* DFHSMincho-W7 */ + { 0x125FEB26UL, 0x00000350UL }, /* cvt */ + { 0xA5ACC982UL, 0x00007EE1UL }, /* fpgm */ + { 0x90999196UL, 0x0000041FUL } /* prep */ + }, { /* DFKaiShu */ { 0x11E5EAD4UL, 0x00000350UL }, /* cvt */ { 0x5A30CA3BUL, 0x00009063UL }, /* fpgm */ { 0x13A42602UL, 0x0000007EUL } /* prep */ }, - { /* DFKaiShu2 */ + { /* DFKaiShu, variant */ { 0x11E5EAD4UL, 0x00000350UL }, /* cvt */ { 0xA6E78C01UL, 0x00008998UL }, /* fpgm */ { 0x13A42602UL, 0x0000007EUL } /* prep */ }, + { /* DFKaiShu-Md-HK-BF */ + { 0x11E5EAD4UL, 0x00000360UL }, /* cvt */ + { 0x9DB282B2UL, 0x0000C06EUL }, /* fpgm */ + { 0x53E6D7CAUL, 0x00000082UL } /* prep */ + }, + { /* DFMing-Bd-HK-BF */ + { 0x1243EB18UL, 0x00000350UL }, /* cvt */ + { 0xBA0A8C30UL, 0x000074ADUL }, /* fpgm */ + { 0xF3D83409UL, 0x0000037BUL } /* prep */ + }, + { /* DLCLiShu */ + { 0x07DCF546UL, 0x00000308UL }, /* cvt */ + { 0x40FE7C90UL, 0x00008E2AUL }, /* fpgm */ + { 0x608174B5UL, 0x0000007AUL } /* prep */ + }, + { /* DLCHayBold */ + { 0xEB891238UL, 0x00000308UL }, /* cvt */ + { 0xD2E4DCD4UL, 0x0000676FUL }, /* fpgm */ + { 0x8EA5F293UL, 0x000003B8UL } /* prep */ + }, { /* HuaTianKaiTi */ { 0xFFFBFFFCUL, 0x00000008UL }, /* cvt */ { 0x9C9E48B8UL, 0x0000BEA2UL }, /* fpgm */ @@ -340,6 +421,11 @@ { 0x00000000UL, 0x00000000UL }, /* cvt */ { 0xF055FC48UL, 0x000001C2UL }, /* fpgm */ { 0x3900DED3UL, 0x00001E18UL } /* prep */ + }, + { /* MINGLI.TTF, 1992 */ + { 0x00170003UL, 0x00000060UL }, /* cvt */ + { 0xDBB4306EUL, 0x000058AAUL }, /* fpgm */ + { 0xD643482AUL, 0x00000035UL } /* prep */ } }; @@ -536,6 +622,7 @@ goto Exit; /* check that we have a valid TrueType file */ + FT_TRACE2(( " " )); error = sfnt->init_face( stream, face, face_index, num_params, params ); /* Stream may have changed. */ @@ -547,9 +634,11 @@ /* We must also be able to accept Mac/GX fonts, as well as OT ones. */ /* The 0x00020000 tag is completely undocumented; some fonts from */ /* Arphic made for Chinese Windows 3.1 have this. */ - if ( face->format_tag != 0x00010000L && /* MS fonts */ - face->format_tag != 0x00020000L && /* CJK fonts for Win 3.1 */ - face->format_tag != TTAG_true ) /* Mac fonts */ + if ( face->format_tag != 0x00010000L && /* MS fonts */ + face->format_tag != 0x00020000L && /* CJK fonts for Win 3.1 */ + face->format_tag != TTAG_true && /* Mac fonts */ + face->format_tag != TTAG_0xA5kbd && /* `Keyboard.dfont' (legacy Mac OS X) */ + face->format_tag != TTAG_0xA5lst ) /* `LastResort.dfont' (legacy Mac OS X) */ { FT_TRACE2(( " not a TTF font\n" )); goto Bad_Format; @@ -626,44 +715,17 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT { - FT_Int instance_index = face_index >> 16; + FT_UInt instance_index = (FT_UInt)face_index >> 16; if ( FT_HAS_MULTIPLE_MASTERS( ttface ) && instance_index > 0 ) { - error = TT_Get_MM_Var( face, NULL ); + error = TT_Set_Named_Instance( face, instance_index ); if ( error ) goto Exit; - if ( face->blend->mmvar->namedstyle ) - { - FT_Memory memory = ttface->memory; - - FT_Var_Named_Style* named_style; - FT_String* style_name; - - - /* in `face_index', the instance index starts with value 1 */ - named_style = face->blend->mmvar->namedstyle + instance_index - 1; - error = sfnt->get_name( face, - (FT_UShort)named_style->strid, - &style_name ); - if ( error ) - goto Exit; - - /* set style name; if already set, replace it */ - if ( face->root.style_name ) - FT_FREE( face->root.style_name ); - face->root.style_name = style_name; - - /* finally, select the named instance */ - error = TT_Set_Var_Design( face, - face->blend->mmvar->num_axis, - named_style->coords ); - if ( error ) - goto Exit; - } + tt_apply_mvar( face ); } } @@ -789,14 +851,14 @@ exec->pedantic_hinting = pedantic; { - FT_Size_Metrics* metrics = &exec->metrics; - TT_Size_Metrics* tt_metrics = &exec->tt_metrics; + FT_Size_Metrics* size_metrics = &exec->metrics; + TT_Size_Metrics* tt_metrics = &exec->tt_metrics; - metrics->x_ppem = 0; - metrics->y_ppem = 0; - metrics->x_scale = 0; - metrics->y_scale = 0; + size_metrics->x_ppem = 0; + size_metrics->y_ppem = 0; + size_metrics->x_scale = 0; + size_metrics->y_scale = 0; tt_metrics->ppem = 0; tt_metrics->scale = 0; @@ -819,6 +881,11 @@ FT_TRACE4(( "Executing `fpgm' table.\n" )); error = face->interpreter( exec ); +#ifdef FT_DEBUG_LEVEL_TRACE + if ( error ) + FT_TRACE4(( " interpretation failed with error code 0x%x\n", + error )); +#endif } else error = FT_Err_Ok; @@ -882,8 +949,12 @@ TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 ); FT_TRACE4(( "Executing `prep' table.\n" )); - error = face->interpreter( exec ); +#ifdef FT_DEBUG_LEVEL_TRACE + if ( error ) + FT_TRACE4(( " interpretation failed with error code 0x%x\n", + error )); +#endif } else error = FT_Err_Ok; @@ -1002,17 +1073,17 @@ /* Set default metrics */ { - TT_Size_Metrics* metrics = &size->ttmetrics; + TT_Size_Metrics* tt_metrics = &size->ttmetrics; - metrics->rotated = FALSE; - metrics->stretched = FALSE; + tt_metrics->rotated = FALSE; + tt_metrics->stretched = FALSE; /* set default engine compensation */ - metrics->compensations[0] = 0; /* gray */ - metrics->compensations[1] = 0; /* black */ - metrics->compensations[2] = 0; /* white */ - metrics->compensations[3] = 0; /* reserved */ + tt_metrics->compensations[0] = 0; /* gray */ + tt_metrics->compensations[1] = 0; /* black */ + tt_metrics->compensations[2] = 0; /* white */ + tt_metrics->compensations[3] = 0; /* reserved */ } /* allocate function defs, instruction defs, cvt, and storage area */ @@ -1075,8 +1146,10 @@ if ( size->bytecode_ready < 0 ) error = tt_size_init_bytecode( (FT_Size)size, pedantic ); + else + error = size->bytecode_ready; - if ( error || size->bytecode_ready ) + if ( error ) goto Exit; /* rescale CVT when needed */ @@ -1108,6 +1181,8 @@ error = tt_size_run_prep( size, pedantic ); } + else + error = size->cvt_ready; Exit: return error; @@ -1184,26 +1259,34 @@ /* have been changed. */ /* */ /* <Input> */ - /* size :: A handle to the target size object. */ + /* size :: A handle to the target size object. */ + /* */ + /* only_height :: Only recompute ascender, descender, and height; */ + /* this flag is used for variation fonts where */ + /* `tt_size_reset' is used as an iterator function. */ /* */ FT_LOCAL_DEF( FT_Error ) - tt_size_reset( TT_Size size ) + tt_size_reset( TT_Size size, + FT_Bool only_height ) { TT_Face face; - FT_Error error = FT_Err_Ok; - FT_Size_Metrics* metrics; - + FT_Size_Metrics* size_metrics; - size->ttmetrics.valid = FALSE; face = (TT_Face)size->root.face; - metrics = &size->metrics; + /* nothing to do for CFF2 */ + if ( face->is_cff2 ) + return FT_Err_Ok; + + size->ttmetrics.valid = FALSE; + + size_metrics = &size->hinted_metrics; /* copy the result from base layer */ - *metrics = size->root.metrics; + *size_metrics = size->root.metrics; - if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 ) + if ( size_metrics->x_ppem < 1 || size_metrics->y_ppem < 1 ) return FT_THROW( Invalid_PPem ); /* This bit flag, if set, indicates that the ppems must be */ @@ -1212,48 +1295,66 @@ /* */ if ( face->header.Flags & 8 ) { - metrics->x_scale = FT_DivFix( metrics->x_ppem << 6, - face->root.units_per_EM ); - metrics->y_scale = FT_DivFix( metrics->y_ppem << 6, - face->root.units_per_EM ); - - metrics->ascender = - FT_PIX_ROUND( FT_MulFix( face->root.ascender, metrics->y_scale ) ); - metrics->descender = - FT_PIX_ROUND( FT_MulFix( face->root.descender, metrics->y_scale ) ); - metrics->height = - FT_PIX_ROUND( FT_MulFix( face->root.height, metrics->y_scale ) ); - metrics->max_advance = - FT_PIX_ROUND( FT_MulFix( face->root.max_advance_width, - metrics->x_scale ) ); + /* the TT spec always asks for ROUND, not FLOOR or CEIL */ + size_metrics->ascender = FT_PIX_ROUND( + FT_MulFix( face->root.ascender, + size_metrics->y_scale ) ); + size_metrics->descender = FT_PIX_ROUND( + FT_MulFix( face->root.descender, + size_metrics->y_scale ) ); + size_metrics->height = FT_PIX_ROUND( + FT_MulFix( face->root.height, + size_metrics->y_scale ) ); + } + + size->ttmetrics.valid = TRUE; + + if ( only_height ) + { + /* we must not recompute the scaling values here since */ + /* `tt_size_reset' was already called (with only_height = 0) */ + return FT_Err_Ok; + } + + if ( face->header.Flags & 8 ) + { + /* base scaling values on integer ppem values, */ + /* as mandated by the TrueType specification */ + size_metrics->x_scale = FT_DivFix( size_metrics->x_ppem << 6, + face->root.units_per_EM ); + size_metrics->y_scale = FT_DivFix( size_metrics->y_ppem << 6, + face->root.units_per_EM ); + + size_metrics->max_advance = FT_PIX_ROUND( + FT_MulFix( face->root.max_advance_width, + size_metrics->x_scale ) ); } /* compute new transformation */ - if ( metrics->x_ppem >= metrics->y_ppem ) + if ( size_metrics->x_ppem >= size_metrics->y_ppem ) { - size->ttmetrics.scale = metrics->x_scale; - size->ttmetrics.ppem = metrics->x_ppem; + size->ttmetrics.scale = size_metrics->x_scale; + size->ttmetrics.ppem = size_metrics->x_ppem; size->ttmetrics.x_ratio = 0x10000L; - size->ttmetrics.y_ratio = FT_DivFix( metrics->y_ppem, - metrics->x_ppem ); + size->ttmetrics.y_ratio = FT_DivFix( size_metrics->y_ppem, + size_metrics->x_ppem ); } else { - size->ttmetrics.scale = metrics->y_scale; - size->ttmetrics.ppem = metrics->y_ppem; - size->ttmetrics.x_ratio = FT_DivFix( metrics->x_ppem, - metrics->y_ppem ); + size->ttmetrics.scale = size_metrics->y_scale; + size->ttmetrics.ppem = size_metrics->y_ppem; + size->ttmetrics.x_ratio = FT_DivFix( size_metrics->x_ppem, + size_metrics->y_ppem ); size->ttmetrics.y_ratio = 0x10000L; } + size->metrics = size_metrics; + #ifdef TT_USE_BYTECODE_INTERPRETER size->cvt_ready = -1; #endif /* TT_USE_BYTECODE_INTERPRETER */ - if ( !error ) - size->ttmetrics.valid = TRUE; - - return error; + return FT_Err_Ok; } diff --git a/modules/freetype2/src/truetype/ttobjs.h b/modules/freetype2/src/truetype/ttobjs.h index 98ad38373..38fa30e4e 100644 --- a/modules/freetype2/src/truetype/ttobjs.h +++ b/modules/freetype2/src/truetype/ttobjs.h @@ -4,7 +4,7 @@ /* */ /* Objects manager (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -278,7 +278,8 @@ FT_BEGIN_HEADER /* we have our own copy of metrics so that we can modify */ /* it without affecting auto-hinting (when used) */ - FT_Size_Metrics metrics; + FT_Size_Metrics* metrics; /* for the current rendering mode */ + FT_Size_Metrics hinted_metrics; /* for the hinted rendering mode */ TT_Size_Metrics ttmetrics; @@ -389,7 +390,8 @@ FT_BEGIN_HEADER #endif /* TT_USE_BYTECODE_INTERPRETER */ FT_LOCAL( FT_Error ) - tt_size_reset( TT_Size size ); + tt_size_reset( TT_Size size, + FT_Bool only_height ); /*************************************************************************/ diff --git a/modules/freetype2/src/truetype/ttpic.c b/modules/freetype2/src/truetype/ttpic.c index 54a5b8bed..cdbb80639 100644 --- a/modules/freetype2/src/truetype/ttpic.c +++ b/modules/freetype2/src/truetype/ttpic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for truetype module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2018 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/truetype/ttpic.h b/modules/freetype2/src/truetype/ttpic.h index a71d589df..df878ae6f 100644 --- a/modules/freetype2/src/truetype/ttpic.h +++ b/modules/freetype2/src/truetype/ttpic.h @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for truetype module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2018 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/truetype/ttpload.c b/modules/freetype2/src/truetype/ttpload.c index d756d3842..d9526ad08 100644 --- a/modules/freetype2/src/truetype/ttpload.c +++ b/modules/freetype2/src/truetype/ttpload.c @@ -4,7 +4,7 @@ /* */ /* TrueType-specific tables loader (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -247,13 +247,13 @@ if ( pos2 > face->glyf_len ) { /* We try to sanitize the last `loca' entry. */ - if ( gindex == face->num_locations - 1 ) + if ( gindex == face->num_locations - 2 ) { FT_TRACE1(( "tt_face_get_location:" - " too large offset (0x%08lx) found for glyph index %ld,\n" + " too large size (%ld bytes) found for glyph index %ld,\n" " " - " truncating at the end of `glyf' table (0x%08lx)\n", - pos2, gindex + 1, face->glyf_len )); + " truncating at the end of `glyf' table to %ld bytes\n", + pos2 - pos1, gindex, face->glyf_len - pos1 )); pos2 = face->glyf_len; } else diff --git a/modules/freetype2/src/truetype/ttpload.h b/modules/freetype2/src/truetype/ttpload.h index aa2e38e6e..fa1252724 100644 --- a/modules/freetype2/src/truetype/ttpload.h +++ b/modules/freetype2/src/truetype/ttpload.h @@ -4,7 +4,7 @@ /* */ /* TrueType-specific tables loader (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/truetype/ttsubpix.c b/modules/freetype2/src/truetype/ttsubpix.c index 03950960a..d94bcc8b5 100644 --- a/modules/freetype2/src/truetype/ttsubpix.c +++ b/modules/freetype2/src/truetype/ttsubpix.c @@ -4,7 +4,7 @@ /* */ /* TrueType Subpixel Hinting. */ /* */ -/* Copyright 2010-2016 by */ +/* Copyright 2010-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -22,12 +22,13 @@ #include FT_INTERNAL_SFNT_H #include FT_TRUETYPE_TAGS_H #include FT_OUTLINE_H -#include FT_TRUETYPE_DRIVER_H +#include FT_DRIVER_H #include "ttsubpix.h" -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY +#if defined( TT_USE_BYTECODE_INTERPRETER ) && \ + defined( TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY ) /*************************************************************************/ /* */ @@ -752,24 +753,24 @@ /* Does font name match rule family? */ - if ( strcmp( detected_font_name, rule_font_name ) == 0 ) + if ( ft_strcmp( detected_font_name, rule_font_name ) == 0 ) return TRUE; /* Is font name a wildcard ""? */ - if ( strcmp( rule_font_name, "" ) == 0 ) + if ( ft_strcmp( rule_font_name, "" ) == 0 ) return TRUE; /* Is font name contained in a class list? */ for ( i = 0; i < FAMILY_CLASS_RULES_SIZE; i++ ) { - if ( strcmp( FAMILY_CLASS_Rules[i].name, rule_font_name ) == 0 ) + if ( ft_strcmp( FAMILY_CLASS_Rules[i].name, rule_font_name ) == 0 ) { for ( j = 0; j < SPH_MAX_CLASS_MEMBERS; j++ ) { - if ( strcmp( FAMILY_CLASS_Rules[i].member[j], "" ) == 0 ) + if ( ft_strcmp( FAMILY_CLASS_Rules[i].member[j], "" ) == 0 ) continue; - if ( strcmp( FAMILY_CLASS_Rules[i].member[j], - detected_font_name ) == 0 ) + if ( ft_strcmp( FAMILY_CLASS_Rules[i].member[j], + detected_font_name ) == 0 ) return TRUE; } } @@ -787,24 +788,24 @@ /* Does font style match rule style? */ - if ( strcmp( detected_font_style, rule_font_style ) == 0 ) + if ( ft_strcmp( detected_font_style, rule_font_style ) == 0 ) return TRUE; /* Is font style a wildcard ""? */ - if ( strcmp( rule_font_style, "" ) == 0 ) + if ( ft_strcmp( rule_font_style, "" ) == 0 ) return TRUE; /* Is font style contained in a class list? */ for ( i = 0; i < STYLE_CLASS_RULES_SIZE; i++ ) { - if ( strcmp( STYLE_CLASS_Rules[i].name, rule_font_style ) == 0 ) + if ( ft_strcmp( STYLE_CLASS_Rules[i].name, rule_font_style ) == 0 ) { for ( j = 0; j < SPH_MAX_CLASS_MEMBERS; j++ ) { - if ( strcmp( STYLE_CLASS_Rules[i].member[j], "" ) == 0 ) + if ( ft_strcmp( STYLE_CLASS_Rules[i].member[j], "" ) == 0 ) continue; - if ( strcmp( STYLE_CLASS_Rules[i].member[j], - detected_font_style ) == 0 ) + if ( ft_strcmp( STYLE_CLASS_Rules[i].member[j], + detected_font_style ) == 0 ) return TRUE; } } @@ -905,7 +906,7 @@ { TT_Face face = loader->face; FT_String* family = face->root.family_name; - FT_UInt ppem = loader->size->metrics.x_ppem; + FT_UInt ppem = loader->size->metrics->x_ppem; FT_String* style = face->root.style_name; @@ -1000,12 +1001,14 @@ } } -#else /* !TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ +#else /* !(TT_USE_BYTECODE_INTERPRETER && */ + /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY) */ /* ANSI C doesn't like empty source files */ typedef int _tt_subpix_dummy; -#endif /* !TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ +#endif /* !(TT_USE_BYTECODE_INTERPRETER && */ + /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY) */ /* END */ diff --git a/modules/freetype2/src/truetype/ttsubpix.h b/modules/freetype2/src/truetype/ttsubpix.h index 86844da66..1070bb016 100644 --- a/modules/freetype2/src/truetype/ttsubpix.h +++ b/modules/freetype2/src/truetype/ttsubpix.h @@ -4,7 +4,7 @@ /* */ /* TrueType Subpixel Hinting. */ /* */ -/* Copyright 2010-2016 by */ +/* Copyright 2010-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/type1/Jamfile b/modules/freetype2/src/type1/Jamfile index 948b40854..b94b7d0aa 100644 --- a/modules/freetype2/src/type1/Jamfile +++ b/modules/freetype2/src/type1/Jamfile @@ -1,6 +1,6 @@ # FreeType 2 src/type1 Jamfile # -# Copyright 2001-2016 by +# Copyright 2001-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/type1/module.mk b/modules/freetype2/src/type1/module.mk index d7ab520c7..3fea5cc16 100644 --- a/modules/freetype2/src/type1/module.mk +++ b/modules/freetype2/src/type1/module.mk @@ -3,7 +3,7 @@ # -# Copyright 1996-2016 by +# Copyright 1996-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/type1/rules.mk b/modules/freetype2/src/type1/rules.mk index bdec29479..cb1a14286 100644 --- a/modules/freetype2/src/type1/rules.mk +++ b/modules/freetype2/src/type1/rules.mk @@ -3,7 +3,7 @@ # -# Copyright 1996-2016 by +# Copyright 1996-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/type1/t1afm.c b/modules/freetype2/src/type1/t1afm.c index 5c7f38968..61053d9a6 100644 --- a/modules/freetype2/src/type1/t1afm.c +++ b/modules/freetype2/src/type1/t1afm.c @@ -4,7 +4,7 @@ /* */ /* AFM support for Type 1 fonts (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -24,6 +24,8 @@ #include "t1errors.h" +#ifndef T1_CONFIG_OPTION_NO_AFM + /*************************************************************************/ /* */ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ @@ -402,5 +404,12 @@ return FT_Err_Ok; } +#else /* T1_CONFIG_OPTION_NO_AFM */ + + /* ANSI C doesn't like empty source files */ + typedef int _t1_afm_dummy; + +#endif /* T1_CONFIG_OPTION_NO_AFM */ + /* END */ diff --git a/modules/freetype2/src/type1/t1afm.h b/modules/freetype2/src/type1/t1afm.h index 3a864f237..cb8d302b4 100644 --- a/modules/freetype2/src/type1/t1afm.h +++ b/modules/freetype2/src/type1/t1afm.h @@ -4,7 +4,7 @@ /* */ /* AFM support for Type 1 fonts (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/type1/t1driver.c b/modules/freetype2/src/type1/t1driver.c index fd9e13e11..029b410b4 100644 --- a/modules/freetype2/src/type1/t1driver.c +++ b/modules/freetype2/src/type1/t1driver.c @@ -4,7 +4,7 @@ /* */ /* Type 1 driver interface (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -30,6 +30,8 @@ #include FT_INTERNAL_DEBUG_H #include FT_INTERNAL_STREAM_H #include FT_INTERNAL_HASH_H +#include FT_INTERNAL_POSTSCRIPT_PROPS_H +#include FT_DRIVER_H #include FT_SERVICE_MULTIPLE_MASTERS_H #include FT_SERVICE_GLYPH_DICT_H @@ -37,6 +39,7 @@ #include FT_SERVICE_POSTSCRIPT_NAME_H #include FT_SERVICE_POSTSCRIPT_CMAPS_H #include FT_SERVICE_POSTSCRIPT_INFO_H +#include FT_SERVICE_PROPERTIES_H #include FT_SERVICE_KERNING_H @@ -126,6 +129,7 @@ (FT_Get_MM_Var_Func) T1_Get_MM_Var, /* get_mm_var */ (FT_Set_Var_Design_Func)T1_Set_Var_Design, /* set_var_design */ (FT_Get_Var_Design_Func)T1_Get_Var_Design, /* get_var_design */ + (FT_Set_Instance_Func) T1_Reset_MM_Blend, /* set_instance */ (FT_Get_Var_Blend_Func) NULL, /* get_var_blend */ (FT_Done_Blend_Func) T1_Done_Blend /* done_blend */ @@ -614,6 +618,18 @@ /* + * PROPERTY SERVICE + * + */ + + FT_DEFINE_SERVICE_PROPERTIESREC( + t1_service_properties, + + (FT_Properties_SetFunc)ps_property_set, /* set_property */ + (FT_Properties_GetFunc)ps_property_get ) /* get_property */ + + + /* * SERVICE LIST * */ @@ -624,6 +640,7 @@ { FT_SERVICE_ID_GLYPH_DICT, &t1_service_glyph_dict }, { FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_TYPE_1 }, { FT_SERVICE_ID_POSTSCRIPT_INFO, &t1_service_ps_info }, + { FT_SERVICE_ID_PROPERTIES, &t1_service_properties }, #ifndef T1_CONFIG_OPTION_NO_AFM { FT_SERVICE_ID_KERNING, &t1_service_kerning }, @@ -713,7 +730,7 @@ FT_MODULE_DRIVER_SCALABLE | FT_MODULE_DRIVER_HAS_HINTER, - sizeof ( FT_DriverRec ), + sizeof ( PS_DriverRec ), "type1", 0x10000L, diff --git a/modules/freetype2/src/type1/t1driver.h b/modules/freetype2/src/type1/t1driver.h index 78d8e38aa..2b1507233 100644 --- a/modules/freetype2/src/type1/t1driver.h +++ b/modules/freetype2/src/type1/t1driver.h @@ -4,7 +4,7 @@ /* */ /* High-level Type 1 driver interface (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/type1/t1errors.h b/modules/freetype2/src/type1/t1errors.h index 9ba470ed6..9e0151b95 100644 --- a/modules/freetype2/src/type1/t1errors.h +++ b/modules/freetype2/src/type1/t1errors.h @@ -4,7 +4,7 @@ /* */ /* Type 1 error codes (specification only). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/type1/t1gload.c b/modules/freetype2/src/type1/t1gload.c index ea36f6414..87d40e756 100644 --- a/modules/freetype2/src/type1/t1gload.c +++ b/modules/freetype2/src/type1/t1gload.c @@ -4,7 +4,7 @@ /* */ /* Type 1 Glyph Loader (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -23,6 +23,8 @@ #include FT_INTERNAL_STREAM_H #include FT_OUTLINE_H #include FT_INTERNAL_POSTSCRIPT_AUX_H +#include FT_INTERNAL_CFF_TYPES_H +#include FT_DRIVER_H #include "t1errors.h" @@ -37,37 +39,28 @@ #define FT_COMPONENT trace_t1gload - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - /********** *********/ - /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/ - /********** *********/ - /********** The following code is in charge of computing *********/ - /********** the maximum advance width of the font. It *********/ - /********** quickly processes each glyph charstring to *********/ - /********** extract the value from either a `sbw' or `seac' *********/ - /********** operator. *********/ - /********** *********/ - /*************************************************************************/ - /*************************************************************************/ - /*************************************************************************/ - - static FT_Error T1_Parse_Glyph_And_Get_Char_String( T1_Decoder decoder, FT_UInt glyph_index, - FT_Data* char_string ) + FT_Data* char_string, + FT_Bool* force_scaling ) { T1_Face face = (T1_Face)decoder->builder.face; T1_Font type1 = &face->type1; FT_Error error = FT_Err_Ok; + PSAux_Service psaux = (PSAux_Service)face->psaux; + const T1_Decoder_Funcs decoder_funcs = psaux->t1_decoder_funcs; + PS_Decoder psdecoder; + #ifdef FT_CONFIG_OPTION_INCREMENTAL FT_Incremental_InterfaceRec *inc = face->root.internal->incremental_interface; #endif +#ifdef T1_CONFIG_OPTION_OLD_ENGINE + PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( face ); +#endif decoder->font_matrix = type1->font_matrix; decoder->font_offset = type1->font_offset; @@ -90,9 +83,56 @@ } if ( !error ) - error = decoder->funcs.parse_charstrings( - decoder, (FT_Byte*)char_string->pointer, - (FT_UInt)char_string->length ); + { + /* choose which renderer to use */ +#ifdef T1_CONFIG_OPTION_OLD_ENGINE + if ( driver->hinting_engine == FT_HINTING_FREETYPE || + decoder->builder.metrics_only ) + error = decoder_funcs->parse_charstrings_old( + decoder, + (FT_Byte*)char_string->pointer, + (FT_UInt)char_string->length ); +#else + if ( decoder->builder.metrics_only ) + error = decoder_funcs->parse_metrics( + decoder, + (FT_Byte*)char_string->pointer, + (FT_UInt)char_string->length ); +#endif + else + { + CFF_SubFontRec subfont; + + + psaux->ps_decoder_init( &psdecoder, decoder, TRUE ); + + psaux->t1_make_subfont( FT_FACE( face ), + &face->type1.private_dict, &subfont ); + psdecoder.current_subfont = &subfont; + + error = decoder_funcs->parse_charstrings( + &psdecoder, + (FT_Byte*)char_string->pointer, + (FT_ULong)char_string->length ); + + /* Adobe's engine uses 16.16 numbers everywhere; */ + /* as a consequence, glyphs larger than 2000ppem get rejected */ + if ( FT_ERR_EQ( error, Glyph_Too_Big ) ) + { + /* this time, we retry unhinted and scale up the glyph later on */ + /* (the engine uses and sets the hardcoded value 0x10000 / 64 = */ + /* 0x400 for both `x_scale' and `y_scale' in this case) */ + ((T1_GlyphSlot)decoder->builder.glyph)->hint = FALSE; + + *force_scaling = TRUE; + + error = decoder_funcs->parse_charstrings( + &psdecoder, + (FT_Byte*)char_string->pointer, + (FT_ULong)char_string->length ); + } + } + } #ifdef FT_CONFIG_OPTION_INCREMENTAL @@ -126,8 +166,10 @@ FT_UInt glyph_index ) { FT_Data glyph_data; - FT_Error error = T1_Parse_Glyph_And_Get_Char_String( - decoder, glyph_index, &glyph_data ); + FT_Bool force_scaling = FALSE; + FT_Error error = T1_Parse_Glyph_And_Get_Char_String( + decoder, glyph_index, &glyph_data, + &force_scaling ); #ifdef FT_CONFIG_OPTION_INCREMENTAL @@ -149,6 +191,23 @@ } + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/ + /********** *********/ + /********** The following code is in charge of computing *********/ + /********** the maximum advance width of the font. It *********/ + /********** quickly processes each glyph charstring to *********/ + /********** extract the value from either a `sbw' or `seac' *********/ + /********** operator. *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + FT_LOCAL_DEF( FT_Error ) T1_Compute_Max_Advance( T1_Face face, FT_Pos* max_advance ) @@ -278,6 +337,8 @@ T1_DecoderRec decoder; T1_Face face = (T1_Face)t1glyph->face; FT_Bool hinting; + FT_Bool scaled; + FT_Bool force_scaling = FALSE; T1_Font type1 = &face->type1; PSAux_Service psaux = (PSAux_Service)face->psaux; const T1_Decoder_Funcs decoder_funcs = psaux->t1_decoder_funcs; @@ -325,7 +386,10 @@ hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 && ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); + scaled = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ); + glyph->hint = hinting; + glyph->scaled = scaled; t1glyph->format = FT_GLYPH_FORMAT_OUTLINE; error = decoder_funcs->init( &decoder, @@ -355,13 +419,15 @@ /* now load the unscaled outline */ error = T1_Parse_Glyph_And_Get_Char_String( &decoder, glyph_index, - &glyph_data ); + &glyph_data, + &force_scaling ); if ( error ) goto Exit; #ifdef FT_CONFIG_OPTION_INCREMENTAL glyph_data_loaded = 1; #endif + hinting = glyph->hint; font_matrix = decoder.font_matrix; font_offset = decoder.font_offset; @@ -451,7 +517,7 @@ } #endif - if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ) + if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || force_scaling ) { /* scale the outline and the metrics */ FT_Int n; diff --git a/modules/freetype2/src/type1/t1gload.h b/modules/freetype2/src/type1/t1gload.h index 975f22785..72ef76f6a 100644 --- a/modules/freetype2/src/type1/t1gload.h +++ b/modules/freetype2/src/type1/t1gload.h @@ -4,7 +4,7 @@ /* */ /* Type 1 Glyph Loader (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/type1/t1load.c b/modules/freetype2/src/type1/t1load.c index f6b43dc2f..9dfa637a6 100644 --- a/modules/freetype2/src/type1/t1load.c +++ b/modules/freetype2/src/type1/t1load.c @@ -4,7 +4,7 @@ /* */ /* Type 1 font loader (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -329,8 +329,8 @@ for ( i = 0; i < mmaster.num_axis; i++ ) { mmvar->axis[i].name = mmaster.axis[i].name; - mmvar->axis[i].minimum = INT_TO_FIXED( mmaster.axis[i].minimum); - mmvar->axis[i].maximum = INT_TO_FIXED( mmaster.axis[i].maximum); + mmvar->axis[i].minimum = INT_TO_FIXED( mmaster.axis[i].minimum ); + mmvar->axis[i].maximum = INT_TO_FIXED( mmaster.axis[i].maximum ); mmvar->axis[i].def = ( mmvar->axis[i].minimum + mmvar->axis[i].maximum ) / 2; /* Does not apply. But this value is in range */ @@ -366,14 +366,16 @@ } - FT_LOCAL_DEF( FT_Error ) - T1_Set_MM_Blend( T1_Face face, + static FT_Error + t1_set_mm_blend( T1_Face face, FT_UInt num_coords, FT_Fixed* coords ) { PS_Blend blend = face->blend; FT_UInt n, m; + FT_Bool have_diff = 0; + if ( !blend ) return FT_THROW( Invalid_Argument ); @@ -405,9 +407,36 @@ result = FT_MulFix( result, factor ); } - blend->weight_vector[n] = result; + + if ( blend->weight_vector[n] != result ) + { + blend->weight_vector[n] = result; + have_diff = 1; + } } + /* return value -1 indicates `no change' */ + return have_diff ? FT_Err_Ok : -1; + } + + + FT_LOCAL_DEF( FT_Error ) + T1_Set_MM_Blend( T1_Face face, + FT_UInt num_coords, + FT_Fixed* coords ) + { + FT_Error error; + + + error = t1_set_mm_blend( face, num_coords, coords ); + if ( error ) + return error; + + if ( num_coords ) + face->root.face_flags |= FT_FACE_FLAG_VARIATION; + else + face->root.face_flags &= ~FT_FACE_FLAG_VARIATION; + return FT_Err_Ok; } @@ -452,6 +481,7 @@ FT_UInt num_coords, FT_Long* coords ) { + FT_Error error; PS_Blend blend = face->blend; FT_UInt n, p; FT_Fixed final_blends[T1_MAX_MM_DESIGNS]; @@ -518,7 +548,28 @@ final_blends[n] = the_blend; } - return T1_Set_MM_Blend( face, blend->num_axis, final_blends ); + error = t1_set_mm_blend( face, blend->num_axis, final_blends ); + if ( error ) + return error; + + if ( num_coords ) + face->root.face_flags |= FT_FACE_FLAG_VARIATION; + else + face->root.face_flags &= ~FT_FACE_FLAG_VARIATION; + + return FT_Err_Ok; + } + + + /* MM fonts don't have named instances, so only the design is reset */ + + FT_LOCAL_DEF( FT_Error ) + T1_Reset_MM_Blend( T1_Face face, + FT_UInt instance_index ) + { + FT_UNUSED( instance_index ); + + return T1_Set_MM_Blend( face, 0, NULL ); } @@ -1266,7 +1317,7 @@ if ( ft_isdigit( *cur ) || *cur == '[' ) { T1_Encoding encode = &face->type1.encoding; - FT_Int count, n; + FT_Int count, array_size, n; PS_Table char_table = &loader->encoding_table; FT_Memory memory = parser->root.memory; FT_Error error; @@ -1283,13 +1334,12 @@ else count = (FT_Int)T1_ToInt( parser ); - /* only composite fonts (which we don't support) */ - /* can have larger values */ + array_size = count; if ( count > 256 ) { - FT_ERROR(( "parse_encoding: invalid encoding array size\n" )); - parser->root.error = FT_THROW( Invalid_File_Format ); - return; + FT_TRACE2(( "parse_encoding:" + " only using first 256 encoding array entries\n" )); + array_size = 256; } T1_Skip_Spaces( parser ); @@ -1305,18 +1355,18 @@ } /* we use a T1_Table to store our charnames */ - loader->num_chars = encode->num_chars = count; - if ( FT_NEW_ARRAY( encode->char_index, count ) || - FT_NEW_ARRAY( encode->char_name, count ) || + loader->num_chars = encode->num_chars = array_size; + if ( FT_NEW_ARRAY( encode->char_index, array_size ) || + FT_NEW_ARRAY( encode->char_name, array_size ) || FT_SET_ERROR( psaux->ps_table_funcs->init( - char_table, count, memory ) ) ) + char_table, array_size, memory ) ) ) { parser->root.error = error; return; } /* We need to `zero' out encoding_table.elements */ - for ( n = 0; n < count; n++ ) + for ( n = 0; n < array_size; n++ ) { char* notdef = (char *)".notdef"; @@ -1409,11 +1459,14 @@ len = (FT_UInt)( parser->root.cursor - cur ); - parser->root.error = T1_Add_Table( char_table, charcode, - cur, len + 1 ); - if ( parser->root.error ) - return; - char_table->elements[charcode][len] = '\0'; + if ( n < array_size ) + { + parser->root.error = T1_Add_Table( char_table, charcode, + cur, len + 1 ); + if ( parser->root.error ) + return; + char_table->elements[charcode][len] = '\0'; + } n++; } @@ -2440,6 +2493,24 @@ type1->encoding.num_chars = loader.num_chars; } + /* some sanitizing to avoid overflows later on; */ + /* the upper limits are ad-hoc values */ + if ( priv->blue_shift > 1000 || priv->blue_shift < 0 ) + { + FT_TRACE2(( "T1_Open_Face:" + " setting unlikely BlueShift value %d to default (7)\n", + priv->blue_shift )); + priv->blue_shift = 7; + } + + if ( priv->blue_fuzz > 1000 || priv->blue_fuzz < 0 ) + { + FT_TRACE2(( "T1_Open_Face:" + " setting unlikely BlueFuzz value %d to default (1)\n", + priv->blue_fuzz )); + priv->blue_fuzz = 1; + } + Exit: t1_done_loader( &loader ); return error; diff --git a/modules/freetype2/src/type1/t1load.h b/modules/freetype2/src/type1/t1load.h index 72445c531..03be3f7f9 100644 --- a/modules/freetype2/src/type1/t1load.h +++ b/modules/freetype2/src/type1/t1load.h @@ -4,7 +4,7 @@ /* */ /* Type 1 font loader (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -90,6 +90,10 @@ FT_BEGIN_HEADER FT_Long* coords ); FT_LOCAL( FT_Error ) + T1_Reset_MM_Blend( T1_Face face, + FT_UInt instance_index ); + + FT_LOCAL( FT_Error ) T1_Get_Var_Design( T1_Face face, FT_UInt num_coords, FT_Fixed* coords ); diff --git a/modules/freetype2/src/type1/t1objs.c b/modules/freetype2/src/type1/t1objs.c index a00911713..7333c4c95 100644 --- a/modules/freetype2/src/type1/t1objs.c +++ b/modules/freetype2/src/type1/t1objs.c @@ -4,7 +4,7 @@ /* */ /* Type 1 objects manager (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 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 FT_INTERNAL_STREAM_H #include FT_TRUETYPE_IDS_H +#include FT_DRIVER_H #include "t1gload.h" #include "t1load.h" @@ -49,9 +50,6 @@ /* */ /* SIZE FUNCTIONS */ /* */ - /* note that we store the global hints in the size's "internal" root */ - /* field */ - /* */ /*************************************************************************/ @@ -77,16 +75,16 @@ T1_Size size = (T1_Size)t1size; - if ( size->root.internal ) + if ( t1size->internal->module_data ) { PSH_Globals_Funcs funcs; funcs = T1_Size_Get_Globals_Funcs( size ); if ( funcs ) - funcs->destroy( (PSH_Globals)size->root.internal ); + funcs->destroy( (PSH_Globals)t1size->internal->module_data ); - size->root.internal = NULL; + t1size->internal->module_data = NULL; } } @@ -108,7 +106,7 @@ error = funcs->create( size->root.face->memory, &face->type1.private_dict, &globals ); if ( !error ) - size->root.internal = (FT_Size_Internal)(void*)globals; + t1size->internal->module_data = globals; } return error; @@ -126,7 +124,7 @@ FT_Request_Metrics( size->root.face, req ); if ( funcs ) - funcs->set_scale( (PSH_Globals)size->root.internal, + funcs->set_scale( (PSH_Globals)t1size->internal->module_data, size->root.metrics.x_scale, size->root.metrics.y_scale, 0, 0 ); @@ -382,7 +380,7 @@ /* simplistic and might get some things wrong. For a full-featured */ /* algorithm you might have a look at the whitepaper given at */ /* */ - /* http://blogs.msdn.com/text/archive/2007/04/23/wpf-font-selection-model.aspx */ + /* https://blogs.msdn.com/text/archive/2007/04/23/wpf-font-selection-model.aspx */ /* get style name -- be careful, some broken fonts only */ /* have a `/FontName' dictionary entry! */ @@ -558,12 +556,6 @@ if ( clazz ) error = FT_CMap_New( clazz, NULL, &charmap, NULL ); - -#if 0 - /* Select default charmap */ - if (root->num_charmaps) - root->charmap = root->charmaps[0]; -#endif } } @@ -587,9 +579,42 @@ /* FreeType error code. 0 means success. */ /* */ FT_LOCAL_DEF( FT_Error ) - T1_Driver_Init( FT_Module driver ) + T1_Driver_Init( FT_Module module ) { - FT_UNUSED( driver ); + PS_Driver driver = (PS_Driver)module; + + FT_UInt32 seed; + + + /* set default property values, cf. `ftt1drv.h' */ +#ifdef T1_CONFIG_OPTION_OLD_ENGINE + driver->hinting_engine = FT_HINTING_FREETYPE; +#else + driver->hinting_engine = FT_HINTING_ADOBE; +#endif + + driver->no_stem_darkening = TRUE; + + driver->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1; + driver->darken_params[1] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1; + driver->darken_params[2] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2; + driver->darken_params[3] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2; + driver->darken_params[4] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3; + driver->darken_params[5] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3; + driver->darken_params[6] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4; + driver->darken_params[7] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4; + + /* compute random seed from some memory addresses */ + seed = (FT_UInt32)( (FT_Offset)(char*)&seed ^ + (FT_Offset)(char*)&module ^ + (FT_Offset)(char*)module->memory ); + seed = seed ^ ( seed >> 10 ) ^ ( seed >> 20 ); + + driver->random_seed = (FT_Int32)seed; + if ( driver->random_seed < 0 ) + driver->random_seed = -driver->random_seed; + else if ( driver->random_seed == 0 ) + driver->random_seed = 123456789; return FT_Err_Ok; } diff --git a/modules/freetype2/src/type1/t1objs.h b/modules/freetype2/src/type1/t1objs.h index 94fbdee9a..8298e036f 100644 --- a/modules/freetype2/src/type1/t1objs.h +++ b/modules/freetype2/src/type1/t1objs.h @@ -4,7 +4,7 @@ /* */ /* Type 1 objects manager (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -120,12 +120,12 @@ FT_BEGIN_HEADER FT_Bool hint; FT_Bool scaled; - FT_Int max_points; - FT_Int max_contours; - FT_Fixed x_scale; FT_Fixed y_scale; + FT_Int max_points; + FT_Int max_contours; + } T1_GlyphSlotRec; diff --git a/modules/freetype2/src/type1/t1parse.c b/modules/freetype2/src/type1/t1parse.c index 478c80bce..8e201e5ef 100644 --- a/modules/freetype2/src/type1/t1parse.c +++ b/modules/freetype2/src/type1/t1parse.c @@ -4,7 +4,7 @@ /* */ /* Type 1 parser (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/type1/t1parse.h b/modules/freetype2/src/type1/t1parse.h index affa818e6..4ac82ae91 100644 --- a/modules/freetype2/src/type1/t1parse.h +++ b/modules/freetype2/src/type1/t1parse.h @@ -4,7 +4,7 @@ /* */ /* Type 1 parser (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/type1/t1tokens.h b/modules/freetype2/src/type1/t1tokens.h index a84f291a6..43a65d88e 100644 --- a/modules/freetype2/src/type1/t1tokens.h +++ b/modules/freetype2/src/type1/t1tokens.h @@ -4,7 +4,7 @@ /* */ /* Type 1 tokenizer (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/type1/type1.c b/modules/freetype2/src/type1/type1.c index bb8aca97f..72eff59bf 100644 --- a/modules/freetype2/src/type1/type1.c +++ b/modules/freetype2/src/type1/type1.c @@ -4,7 +4,7 @@ /* */ /* FreeType Type 1 driver component (body only). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,17 +17,14 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT - #include <ft2build.h> -#include "t1parse.c" -#include "t1load.c" -#include "t1objs.c" -#include "t1driver.c" -#include "t1gload.c" -#ifndef T1_CONFIG_OPTION_NO_AFM #include "t1afm.c" -#endif +#include "t1driver.c" +#include "t1gload.c" +#include "t1load.c" +#include "t1objs.c" +#include "t1parse.c" /* END */ diff --git a/modules/freetype2/src/type42/Jamfile b/modules/freetype2/src/type42/Jamfile index a504ad17d..b98de05a7 100644 --- a/modules/freetype2/src/type42/Jamfile +++ b/modules/freetype2/src/type42/Jamfile @@ -1,6 +1,6 @@ # FreeType 2 src/type42 Jamfile # -# Copyright 2002-2016 by +# Copyright 2002-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/type42/module.mk b/modules/freetype2/src/type42/module.mk index a7e27b723..3d4732bb6 100644 --- a/modules/freetype2/src/type42/module.mk +++ b/modules/freetype2/src/type42/module.mk @@ -3,7 +3,7 @@ # -# Copyright 2002-2016 by +# Copyright 2002-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/type42/rules.mk b/modules/freetype2/src/type42/rules.mk index 80710eff6..9325d3898 100644 --- a/modules/freetype2/src/type42/rules.mk +++ b/modules/freetype2/src/type42/rules.mk @@ -3,7 +3,7 @@ # -# Copyright 2002-2016 by +# Copyright 2002-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/type42/t42drivr.c b/modules/freetype2/src/type42/t42drivr.c index dad35c2b1..f579b2708 100644 --- a/modules/freetype2/src/type42/t42drivr.c +++ b/modules/freetype2/src/type42/t42drivr.c @@ -4,7 +4,7 @@ /* */ /* High-level Type 42 driver interface (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* Roberto Alameda. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/type42/t42drivr.h b/modules/freetype2/src/type42/t42drivr.h index 6ddfb639d..3667f3e06 100644 --- a/modules/freetype2/src/type42/t42drivr.h +++ b/modules/freetype2/src/type42/t42drivr.h @@ -4,7 +4,7 @@ /* */ /* High-level Type 42 driver interface (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* Roberto Alameda. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/type42/t42error.h b/modules/freetype2/src/type42/t42error.h index e1097cc81..e3978a760 100644 --- a/modules/freetype2/src/type42/t42error.h +++ b/modules/freetype2/src/type42/t42error.h @@ -4,7 +4,7 @@ /* */ /* Type 42 error codes (specification only). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/type42/t42objs.c b/modules/freetype2/src/type42/t42objs.c index 1e4907b86..66e5c4038 100644 --- a/modules/freetype2/src/type42/t42objs.c +++ b/modules/freetype2/src/type42/t42objs.c @@ -4,7 +4,7 @@ /* */ /* Type 42 objects manager (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* Roberto Alameda. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -394,12 +394,6 @@ if ( clazz ) error = FT_CMap_New( clazz, NULL, &charmap, NULL ); - -#if 0 - /* Select default charmap */ - if ( root->num_charmaps ) - root->charmap = root->charmaps[0]; -#endif } } Exit: diff --git a/modules/freetype2/src/type42/t42objs.h b/modules/freetype2/src/type42/t42objs.h index 87a40452f..3bad5135e 100644 --- a/modules/freetype2/src/type42/t42objs.h +++ b/modules/freetype2/src/type42/t42objs.h @@ -4,7 +4,7 @@ /* */ /* Type 42 objects manager (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* Roberto Alameda. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/type42/t42parse.c b/modules/freetype2/src/type42/t42parse.c index ef36ffe3c..4813d1f3f 100644 --- a/modules/freetype2/src/type42/t42parse.c +++ b/modules/freetype2/src/type42/t42parse.c @@ -4,7 +4,7 @@ /* */ /* Type 42 font parser (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* Roberto Alameda. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/type42/t42parse.h b/modules/freetype2/src/type42/t42parse.h index ba9e85719..f35d23de6 100644 --- a/modules/freetype2/src/type42/t42parse.h +++ b/modules/freetype2/src/type42/t42parse.h @@ -4,7 +4,7 @@ /* */ /* Type 42 font parser (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* Roberto Alameda. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/type42/t42types.h b/modules/freetype2/src/type42/t42types.h index 850a156e4..d0aa2de57 100644 --- a/modules/freetype2/src/type42/t42types.h +++ b/modules/freetype2/src/type42/t42types.h @@ -4,7 +4,7 @@ /* */ /* Type 42 font data types (specification only). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* Roberto Alameda. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/type42/type42.c b/modules/freetype2/src/type42/type42.c index 0d17a9b1d..6a89cfbed 100644 --- a/modules/freetype2/src/type42/type42.c +++ b/modules/freetype2/src/type42/type42.c @@ -4,7 +4,7 @@ /* */ /* FreeType Type 42 driver component. */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -15,11 +15,13 @@ /* */ /***************************************************************************/ -#define FT_MAKE_OPTION_SINGLE_OBJECT +#define FT_MAKE_OPTION_SINGLE_OBJECT #include <ft2build.h> + +#include "t42drivr.c" #include "t42objs.c" #include "t42parse.c" -#include "t42drivr.c" + /* END */ diff --git a/modules/freetype2/src/winfonts/Jamfile b/modules/freetype2/src/winfonts/Jamfile index d81165e92..4385e3b39 100644 --- a/modules/freetype2/src/winfonts/Jamfile +++ b/modules/freetype2/src/winfonts/Jamfile @@ -1,6 +1,6 @@ # FreeType 2 src/winfonts Jamfile # -# Copyright 2001-2016 by +# Copyright 2001-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/winfonts/fnterrs.h b/modules/freetype2/src/winfonts/fnterrs.h index 6835d3e64..3a86af5aa 100644 --- a/modules/freetype2/src/winfonts/fnterrs.h +++ b/modules/freetype2/src/winfonts/fnterrs.h @@ -4,7 +4,7 @@ /* */ /* Win FNT/FON error codes (specification only). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/winfonts/module.mk b/modules/freetype2/src/winfonts/module.mk index 83da5732f..13f9077cf 100644 --- a/modules/freetype2/src/winfonts/module.mk +++ b/modules/freetype2/src/winfonts/module.mk @@ -3,7 +3,7 @@ # -# Copyright 1996-2016 by +# Copyright 1996-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/winfonts/rules.mk b/modules/freetype2/src/winfonts/rules.mk index 2fd7b822a..d694d1a77 100644 --- a/modules/freetype2/src/winfonts/rules.mk +++ b/modules/freetype2/src/winfonts/rules.mk @@ -3,7 +3,7 @@ # -# Copyright 1996-2016 by +# Copyright 1996-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/winfonts/winfnt.c b/modules/freetype2/src/winfonts/winfnt.c index 99cc96617..36bd3148d 100644 --- a/modules/freetype2/src/winfonts/winfnt.c +++ b/modules/freetype2/src/winfonts/winfnt.c @@ -4,7 +4,7 @@ /* */ /* FreeType font driver for Windows FNT/FON files */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* Copyright 2003 Huw D M Davies for Codeweavers */ /* Copyright 2007 Dmitry Timoshkov for Codeweavers */ @@ -561,7 +561,7 @@ error = fnt_font_load( face->font, stream ); if ( error ) { - FT_TRACE2(( "font #%lu load error %d\n", + FT_TRACE2(( "font #%lu load error 0x%x\n", dir_entry2.name, error )); goto Fail; } @@ -859,10 +859,6 @@ NULL ); if ( error ) goto Fail; - - /* Select default charmap */ - if ( root->num_charmaps ) - root->charmap = root->charmaps[0]; } /* set up remaining flags */ @@ -1095,7 +1091,7 @@ /* note: since glyphs are stored in columns and not in rows we */ /* can't use ft_glyphslot_set_bitmap */ - if ( FT_ALLOC_MULT( bitmap->buffer, pitch, bitmap->rows ) ) + if ( FT_ALLOC_MULT( bitmap->buffer, bitmap->rows, pitch ) ) goto Exit; column = (FT_Byte*)bitmap->buffer; diff --git a/modules/freetype2/src/winfonts/winfnt.h b/modules/freetype2/src/winfonts/winfnt.h index 9a4f32d5b..4885c9d74 100644 --- a/modules/freetype2/src/winfonts/winfnt.h +++ b/modules/freetype2/src/winfonts/winfnt.h @@ -4,7 +4,7 @@ /* */ /* FreeType font driver for Windows FNT/FON files */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* Copyright 2007 Dmitry Timoshkov for Codeweavers */ /* */ |