summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJungshik Shin <jungshik@google.com>2016-01-15 16:18:25 -0800
committerThe Android Automerger <android-build@google.com>2016-02-24 13:20:13 -0800
commitf720f0dbcf012d6c984dbbefa0875ef9840458c6 (patch)
treebdb1068e64623c623100071dc586117aba4a2417
parentec62c527eb34ee4481a0153ceb42dfd35d7e1d26 (diff)
downloadandroid_external_freetype-f720f0dbcf012d6c984dbbefa0875ef9840458c6.tar.gz
android_external_freetype-f720f0dbcf012d6c984dbbefa0875ef9840458c6.tar.bz2
android_external_freetype-f720f0dbcf012d6c984dbbefa0875ef9840458c6.zip
[DO NOT MERGE] Update FreeType to 2.6.2 + update from 2.6.0
1. Update to a512b0fe7a (several patches past 2.6.2). Major changes include - stem-darkening is OFF for CFF fonts by default - general code tightening - header file location is back to include/freetype (used be include/) 2. A bit more details are added to README.android for the reference. This CL requires a pdfium change (the way it includes FT header files : https://googleplex-android-review.git.corp.google.com/#/c/846889 An AOSP master CL (https://android-review.googlesource.com/#/c/196504/) is ported to mnc-dev. Bug: 24296662 Change-Id: Iec6784838d89098f332e6d1ed79663efd91a8441 Signed-off-by: Jungshik Shin <jungshik@google.com>
-rw-r--r--README.android18
-rw-r--r--include/freetype/config/ftconfig.h (renamed from include/config/ftconfig.h)4
-rw-r--r--include/freetype/config/ftheader.h (renamed from include/config/ftheader.h)116
-rw-r--r--include/freetype/config/ftmodule.h (renamed from include/config/ftmodule.h)0
-rw-r--r--include/freetype/config/ftoption.h (renamed from include/config/ftoption.h)28
-rw-r--r--include/freetype/config/ftstdlib.h (renamed from include/config/ftstdlib.h)1
-rw-r--r--include/freetype/freetype.h (renamed from include/freetype.h)309
-rw-r--r--include/freetype/ftadvanc.h (renamed from include/ftadvanc.h)0
-rw-r--r--include/freetype/ftautoh.h (renamed from include/ftautoh.h)57
-rw-r--r--include/freetype/ftbbox.h (renamed from include/ftbbox.h)0
-rw-r--r--include/freetype/ftbdf.h (renamed from include/ftbdf.h)0
-rw-r--r--include/freetype/ftbitmap.h (renamed from include/ftbitmap.h)0
-rw-r--r--include/freetype/ftbzip2.h (renamed from include/ftbzip2.h)0
-rw-r--r--include/freetype/ftcache.h (renamed from include/ftcache.h)0
-rw-r--r--include/freetype/ftcffdrv.h (renamed from include/ftcffdrv.h)8
-rw-r--r--include/freetype/ftchapters.h (renamed from include/ftchapters.h)14
-rw-r--r--include/freetype/ftcid.h (renamed from include/ftcid.h)0
-rw-r--r--include/freetype/fterrdef.h (renamed from include/fterrdef.h)49
-rw-r--r--include/freetype/fterrors.h (renamed from include/fterrors.h)102
-rw-r--r--include/freetype/ftfntfmt.h (renamed from include/ftfntfmt.h)0
-rw-r--r--include/freetype/ftgasp.h (renamed from include/ftgasp.h)0
-rw-r--r--include/freetype/ftglyph.h (renamed from include/ftglyph.h)0
-rw-r--r--include/freetype/ftgxval.h (renamed from include/ftgxval.h)0
-rw-r--r--include/freetype/ftgzip.h (renamed from include/ftgzip.h)0
-rw-r--r--include/freetype/ftimage.h (renamed from include/ftimage.h)0
-rw-r--r--include/freetype/ftincrem.h (renamed from include/ftincrem.h)0
-rw-r--r--include/freetype/ftlcdfil.h (renamed from include/ftlcdfil.h)139
-rw-r--r--include/freetype/ftlist.h (renamed from include/ftlist.h)0
-rw-r--r--include/freetype/ftlzw.h (renamed from include/ftlzw.h)0
-rw-r--r--include/freetype/ftmac.h (renamed from include/ftmac.h)0
-rw-r--r--include/freetype/ftmm.h (renamed from include/ftmm.h)7
-rw-r--r--include/freetype/ftmodapi.h (renamed from include/ftmodapi.h)17
-rw-r--r--include/freetype/ftmoderr.h (renamed from include/ftmoderr.h)0
-rw-r--r--include/freetype/ftotval.h (renamed from include/ftotval.h)0
-rw-r--r--include/freetype/ftoutln.h (renamed from include/ftoutln.h)4
-rw-r--r--include/freetype/ftpfr.h (renamed from include/ftpfr.h)0
-rw-r--r--include/freetype/ftrender.h (renamed from include/ftrender.h)0
-rw-r--r--include/freetype/ftsizes.h (renamed from include/ftsizes.h)0
-rw-r--r--include/freetype/ftsnames.h (renamed from include/ftsnames.h)0
-rw-r--r--include/freetype/ftstroke.h (renamed from include/ftstroke.h)0
-rw-r--r--include/freetype/ftsynth.h (renamed from include/ftsynth.h)0
-rw-r--r--include/freetype/ftsystem.h (renamed from include/ftsystem.h)0
-rw-r--r--include/freetype/fttrigon.h (renamed from include/fttrigon.h)4
-rw-r--r--include/freetype/ftttdrv.h (renamed from include/ftttdrv.h)77
-rw-r--r--include/freetype/fttypes.h (renamed from include/fttypes.h)0
-rw-r--r--include/freetype/ftwinfnt.h (renamed from include/ftwinfnt.h)0
-rw-r--r--include/freetype/internal/autohint.h (renamed from include/internal/autohint.h)0
-rw-r--r--include/freetype/internal/ftcalc.h (renamed from include/internal/ftcalc.h)20
-rw-r--r--include/freetype/internal/ftdebug.h (renamed from include/internal/ftdebug.h)0
-rw-r--r--include/freetype/internal/ftdriver.h (renamed from include/internal/ftdriver.h)0
-rw-r--r--include/freetype/internal/ftgloadr.h (renamed from include/internal/ftgloadr.h)0
-rw-r--r--include/freetype/internal/ftmemory.h (renamed from include/internal/ftmemory.h)0
-rw-r--r--include/freetype/internal/ftobjs.h (renamed from include/internal/ftobjs.h)9
-rw-r--r--include/freetype/internal/ftpic.h (renamed from include/internal/ftpic.h)0
-rw-r--r--include/freetype/internal/ftrfork.h (renamed from include/internal/ftrfork.h)0
-rw-r--r--include/freetype/internal/ftserv.h (renamed from include/internal/ftserv.h)36
-rw-r--r--include/freetype/internal/ftstream.h (renamed from include/internal/ftstream.h)0
-rw-r--r--include/freetype/internal/fttrace.h (renamed from include/internal/fttrace.h)2
-rw-r--r--include/freetype/internal/ftvalid.h (renamed from include/internal/ftvalid.h)0
-rw-r--r--include/freetype/internal/internal.h (renamed from include/internal/internal.h)44
-rw-r--r--include/freetype/internal/psaux.h (renamed from include/internal/psaux.h)0
-rw-r--r--include/freetype/internal/pshints.h (renamed from include/internal/pshints.h)0
-rw-r--r--include/freetype/internal/services/svbdf.h (renamed from include/internal/services/svbdf.h)0
-rw-r--r--include/freetype/internal/services/svcid.h (renamed from include/internal/services/svcid.h)0
-rw-r--r--include/freetype/internal/services/svfntfmt.h (renamed from include/internal/services/svfntfmt.h)0
-rw-r--r--include/freetype/internal/services/svgldict.h (renamed from include/internal/services/svgldict.h)0
-rw-r--r--include/freetype/internal/services/svgxval.h (renamed from include/internal/services/svgxval.h)0
-rw-r--r--include/freetype/internal/services/svkern.h (renamed from include/internal/services/svkern.h)0
-rw-r--r--include/freetype/internal/services/svmm.h (renamed from include/internal/services/svmm.h)0
-rw-r--r--include/freetype/internal/services/svotval.h (renamed from include/internal/services/svotval.h)0
-rw-r--r--include/freetype/internal/services/svpfr.h (renamed from include/internal/services/svpfr.h)0
-rw-r--r--include/freetype/internal/services/svpostnm.h (renamed from include/internal/services/svpostnm.h)0
-rw-r--r--include/freetype/internal/services/svprop.h (renamed from include/internal/services/svprop.h)0
-rw-r--r--include/freetype/internal/services/svpscmap.h (renamed from include/internal/services/svpscmap.h)0
-rw-r--r--include/freetype/internal/services/svpsinfo.h (renamed from include/internal/services/svpsinfo.h)0
-rw-r--r--include/freetype/internal/services/svsfnt.h (renamed from include/internal/services/svsfnt.h)0
-rw-r--r--include/freetype/internal/services/svttcmap.h (renamed from include/internal/services/svttcmap.h)5
-rw-r--r--include/freetype/internal/services/svtteng.h (renamed from include/internal/services/svtteng.h)0
-rw-r--r--include/freetype/internal/services/svttglyf.h (renamed from include/internal/services/svttglyf.h)0
-rw-r--r--include/freetype/internal/services/svwinfnt.h (renamed from include/internal/services/svwinfnt.h)0
-rw-r--r--include/freetype/internal/sfnt.h (renamed from include/internal/sfnt.h)45
-rw-r--r--include/freetype/internal/t1types.h (renamed from include/internal/t1types.h)0
-rw-r--r--include/freetype/internal/tttypes.h (renamed from include/internal/tttypes.h)19
-rw-r--r--include/freetype/t1tables.h (renamed from include/t1tables.h)0
-rw-r--r--include/freetype/ttnameid.h (renamed from include/ttnameid.h)0
-rw-r--r--include/freetype/tttables.h (renamed from include/tttables.h)0
-rw-r--r--include/freetype/tttags.h (renamed from include/tttags.h)0
-rw-r--r--include/freetype/ttunpat.h (renamed from include/ttunpat.h)0
-rw-r--r--include/ft2build.h2
-rw-r--r--module_option.diff57
-rw-r--r--src/autofit/afblue.c233
-rw-r--r--src/autofit/afblue.dat295
-rw-r--r--src/autofit/afblue.h183
-rw-r--r--src/autofit/afblue.hin62
-rw-r--r--src/autofit/afcjk.c193
-rw-r--r--src/autofit/afcjk.h3
-rw-r--r--src/autofit/afdummy.c6
-rw-r--r--src/autofit/afglobal.c107
-rw-r--r--src/autofit/afglobal.h37
-rw-r--r--src/autofit/afhints.c144
-rw-r--r--src/autofit/afindic.c23
-rw-r--r--src/autofit/aflatin.c1038
-rw-r--r--src/autofit/aflatin.h10
-rw-r--r--src/autofit/aflatin2.c22
-rw-r--r--src/autofit/afloader.c271
-rw-r--r--src/autofit/afloader.h5
-rw-r--r--src/autofit/afmodule.c95
-rw-r--r--src/autofit/afmodule.h2
-rw-r--r--src/autofit/afpic.c2
-rw-r--r--src/autofit/afpic.h8
-rw-r--r--src/autofit/afranges.c440
-rw-r--r--src/autofit/afranges.h8
-rw-r--r--src/autofit/afscript.h80
-rw-r--r--src/autofit/afshaper.c676
-rw-r--r--src/autofit/afshaper.h71
-rw-r--r--src/autofit/afstyles.h55
-rw-r--r--src/autofit/aftypes.h71
-rw-r--r--src/autofit/afwarp.c2
-rw-r--r--src/autofit/afwarp.h2
-rw-r--r--src/autofit/autofit.c2
-rw-r--r--src/base/basepic.h9
-rw-r--r--src/base/ftbase.h5
-rw-r--r--src/base/ftbdf.c91
-rw-r--r--src/base/ftcalc.c201
-rw-r--r--src/base/ftcid.c118
-rw-r--r--src/base/ftdbgmem.c2
-rw-r--r--src/base/ftdebug.c4
-rw-r--r--src/base/ftglyph.c14
-rw-r--r--src/base/ftgxval.c142
-rw-r--r--src/base/ftinit.c4
-rw-r--r--src/base/ftlcdfil.c7
-rw-r--r--src/base/ftmac.c1080
-rw-r--r--src/base/ftobjs.c180
-rw-r--r--src/base/ftotval.c91
-rw-r--r--src/base/ftoutln.c150
-rw-r--r--src/base/ftpfr.c153
-rw-r--r--src/base/ftrfork.c37
-rw-r--r--src/base/ftstroke.c19
-rw-r--r--src/cache/ftcache.c31
-rw-r--r--src/cache/ftccache.c2
-rw-r--r--src/cache/ftcerror.h41
-rw-r--r--src/cache/ftcimage.c164
-rw-r--r--src/cache/ftcimage.h107
-rw-r--r--src/cache/ftcmanag.c703
-rw-r--r--src/cache/ftcmru.h246
-rw-r--r--src/cff/cf2arrst.c2
-rw-r--r--src/cff/cf2ft.c14
-rw-r--r--src/cff/cf2ft.h4
-rw-r--r--src/cff/cf2hints.c5
-rw-r--r--src/cff/cf2intrp.c20
-rw-r--r--src/cff/cffdrivr.c74
-rw-r--r--src/cff/cffgload.c38
-rw-r--r--src/cff/cffload.c4
-rw-r--r--src/cff/cffobjs.c16
-rw-r--r--src/cff/cffpic.h8
-rw-r--r--src/gzip/ftgzip.c34
-rw-r--r--src/pfr/pfrload.c941
-rw-r--r--src/psaux/psobjs.c9
-rw-r--r--src/psaux/t1decode.c4
-rw-r--r--src/pshinter/pshalgo.c94
-rw-r--r--src/pshinter/pshglob.c2
-rw-r--r--src/pshinter/pshpic.h8
-rw-r--r--src/psnames/psmodule.c32
-rw-r--r--src/psnames/pspic.h10
-rw-r--r--src/raster/ftmisc.h4
-rw-r--r--src/raster/ftraster.c24
-rw-r--r--src/raster/ftrend1.h6
-rw-r--r--src/raster/rastpic.c20
-rw-r--r--src/raster/rastpic.h10
-rw-r--r--src/sfnt/sfdriver.c22
-rw-r--r--src/sfnt/sfntpic.h12
-rw-r--r--src/sfnt/sfobjs.c148
-rw-r--r--src/sfnt/sfobjs.h9
-rw-r--r--src/sfnt/ttcmap.c358
-rw-r--r--src/sfnt/ttload.c117
-rw-r--r--src/sfnt/ttsbit.c169
-rw-r--r--src/smooth/ftgrays.c196
-rw-r--r--src/smooth/ftspic.h5
-rw-r--r--src/truetype/ttdriver.c51
-rw-r--r--src/truetype/ttgload.c216
-rw-r--r--src/truetype/ttgxvar.c147
-rw-r--r--src/truetype/ttgxvar.h2
-rw-r--r--src/truetype/ttinterp.c55
-rw-r--r--src/truetype/ttobjs.c69
-rw-r--r--src/truetype/ttobjs.h11
-rw-r--r--src/truetype/ttpic.h10
-rw-r--r--src/truetype/ttpload.c26
-rw-r--r--src/truetype/ttsubpix.c2
188 files changed, 8870 insertions, 3078 deletions
diff --git a/README.android b/README.android
index ed61907..c3139d5 100644
--- a/README.android
+++ b/README.android
@@ -1,4 +1,16 @@
-Freetype
+Name: FreeType
+Version: 2.6.2 + update
+Revision: a512b0fe7a8d9db0e5aa9c0a4db1e92cb861722d
-Not all modules in include/config/ftmodule.h are enabled.
-Some options in include/config/ftoption.h are enabled/disabled.
+Local modifications:
+
+1. Drop unused build files (Jamfiles, {module,rules}.mk)
+2. Drop src directories for unused modules:
+ bdf, cid, pcf, pfr, type1, type42, winfonts
+3. Drop src/{bzip2,tools,lzw,otvalid,gxvalid}
+4. Customize include/freetype/config/{ftmodule,ftoption}.h by applying
+ module_option.diff
+
+To faciliate an easier update, all the files in src/{base,autofit} are kept
+even if some of them are for dropped modules/options. Android.mk can be used
+to control exactly what's built.
diff --git a/include/config/ftconfig.h b/include/freetype/config/ftconfig.h
index 086db76..d4d7993 100644
--- a/include/config/ftconfig.h
+++ b/include/freetype/config/ftconfig.h
@@ -335,9 +335,9 @@ FT_BEGIN_HEADER
#if ( __GNUC__ >= 2 || \
defined( __IBM__TYPEOF__ ) || \
( __SUNPRO_C >= 0x5110 && !__STDC__ ) )
-#define TYPEOF( type ) (__typeof__ (type))
+#define FT_TYPEOF( type ) (__typeof__ (type))
#else
-#define TYPEOF( type ) /* empty */
+#define FT_TYPEOF( type ) /* empty */
#endif
diff --git a/include/config/ftheader.h b/include/freetype/config/ftheader.h
index 4906bc1..55f833d 100644
--- a/include/config/ftheader.h
+++ b/include/freetype/config/ftheader.h
@@ -107,7 +107,7 @@
*
*/
#ifndef FT_CONFIG_CONFIG_H
-#define FT_CONFIG_CONFIG_H <config/ftconfig.h>
+#define FT_CONFIG_CONFIG_H <freetype/config/ftconfig.h>
#endif
@@ -122,7 +122,7 @@
*
*/
#ifndef FT_CONFIG_STANDARD_LIBRARY_H
-#define FT_CONFIG_STANDARD_LIBRARY_H <config/ftstdlib.h>
+#define FT_CONFIG_STANDARD_LIBRARY_H <freetype/config/ftstdlib.h>
#endif
@@ -137,7 +137,7 @@
*
*/
#ifndef FT_CONFIG_OPTIONS_H
-#define FT_CONFIG_OPTIONS_H <config/ftoption.h>
+#define FT_CONFIG_OPTIONS_H <freetype/config/ftoption.h>
#endif
@@ -153,7 +153,7 @@
*
*/
#ifndef FT_CONFIG_MODULES_H
-#define FT_CONFIG_MODULES_H <config/ftmodule.h>
+#define FT_CONFIG_MODULES_H <freetype/config/ftmodule.h>
#endif
/* */
@@ -170,7 +170,7 @@
* base FreeType~2 API.
*
*/
-#define FT_FREETYPE_H <freetype.h>
+#define FT_FREETYPE_H <freetype/freetype.h>
/*************************************************************************
@@ -185,7 +185,7 @@
* It is included by @FT_FREETYPE_H.
*
*/
-#define FT_ERRORS_H <fterrors.h>
+#define FT_ERRORS_H <freetype/fterrors.h>
/*************************************************************************
@@ -198,7 +198,7 @@
* list of FreeType~2 module error offsets (and messages).
*
*/
-#define FT_MODULE_ERRORS_H <ftmoderr.h>
+#define FT_MODULE_ERRORS_H <freetype/ftmoderr.h>
/*************************************************************************
@@ -214,7 +214,7 @@
* It is included by @FT_FREETYPE_H.
*
*/
-#define FT_SYSTEM_H <ftsystem.h>
+#define FT_SYSTEM_H <freetype/ftsystem.h>
/*************************************************************************
@@ -230,7 +230,7 @@
* It is included by @FT_FREETYPE_H.
*
*/
-#define FT_IMAGE_H <ftimage.h>
+#define FT_IMAGE_H <freetype/ftimage.h>
/*************************************************************************
@@ -245,7 +245,7 @@
* It is included by @FT_FREETYPE_H.
*
*/
-#define FT_TYPES_H <fttypes.h>
+#define FT_TYPES_H <freetype/fttypes.h>
/*************************************************************************
@@ -260,7 +260,7 @@
* (Most applications will never need to include this file.)
*
*/
-#define FT_LIST_H <ftlist.h>
+#define FT_LIST_H <freetype/ftlist.h>
/*************************************************************************
@@ -273,7 +273,7 @@
* scalable outline management API of FreeType~2.
*
*/
-#define FT_OUTLINE_H <ftoutln.h>
+#define FT_OUTLINE_H <freetype/ftoutln.h>
/*************************************************************************
@@ -286,7 +286,7 @@
* API which manages multiple @FT_Size objects per face.
*
*/
-#define FT_SIZES_H <ftsizes.h>
+#define FT_SIZES_H <freetype/ftsizes.h>
/*************************************************************************
@@ -299,7 +299,7 @@
* module management API of FreeType~2.
*
*/
-#define FT_MODULE_H <ftmodapi.h>
+#define FT_MODULE_H <freetype/ftmodapi.h>
/*************************************************************************
@@ -312,7 +312,7 @@
* renderer module management API of FreeType~2.
*
*/
-#define FT_RENDER_H <ftrender.h>
+#define FT_RENDER_H <freetype/ftrender.h>
/*************************************************************************
@@ -325,7 +325,7 @@
* structures and macros related to the auto-hinting module.
*
*/
-#define FT_AUTOHINTER_H <ftautoh.h>
+#define FT_AUTOHINTER_H <freetype/ftautoh.h>
/*************************************************************************
@@ -338,7 +338,7 @@
* structures and macros related to the CFF driver module.
*
*/
-#define FT_CFF_DRIVER_H <ftcffdrv.h>
+#define FT_CFF_DRIVER_H <freetype/ftcffdrv.h>
/*************************************************************************
@@ -351,7 +351,7 @@
* structures and macros related to the TrueType driver module.
*
*/
-#define FT_TRUETYPE_DRIVER_H <ftttdrv.h>
+#define FT_TRUETYPE_DRIVER_H <freetype/ftttdrv.h>
/*************************************************************************
@@ -364,7 +364,7 @@
* types and API specific to the Type~1 format.
*
*/
-#define FT_TYPE1_TABLES_H <t1tables.h>
+#define FT_TYPE1_TABLES_H <freetype/t1tables.h>
/*************************************************************************
@@ -379,7 +379,7 @@
* definitions, taken from the TrueType and OpenType specifications.
*
*/
-#define FT_TRUETYPE_IDS_H <ttnameid.h>
+#define FT_TRUETYPE_IDS_H <freetype/ttnameid.h>
/*************************************************************************
@@ -392,7 +392,7 @@
* types and API specific to the TrueType (as well as OpenType) format.
*
*/
-#define FT_TRUETYPE_TABLES_H <tttables.h>
+#define FT_TRUETYPE_TABLES_H <freetype/tttables.h>
/*************************************************************************
@@ -406,7 +406,7 @@
* SFNT-based font formats (i.e., TrueType and OpenType).
*
*/
-#define FT_TRUETYPE_TAGS_H <tttags.h>
+#define FT_TRUETYPE_TAGS_H <freetype/tttags.h>
/*************************************************************************
@@ -420,7 +420,7 @@
* face.
*
*/
-#define FT_BDF_H <ftbdf.h>
+#define FT_BDF_H <freetype/ftbdf.h>
/*************************************************************************
@@ -434,7 +434,7 @@
* face.
*
*/
-#define FT_CID_H <ftcid.h>
+#define FT_CID_H <freetype/ftcid.h>
/*************************************************************************
@@ -447,7 +447,7 @@
* definitions of an API which supports gzip-compressed files.
*
*/
-#define FT_GZIP_H <ftgzip.h>
+#define FT_GZIP_H <freetype/ftgzip.h>
/*************************************************************************
@@ -460,7 +460,7 @@
* definitions of an API which supports LZW-compressed files.
*
*/
-#define FT_LZW_H <ftlzw.h>
+#define FT_LZW_H <freetype/ftlzw.h>
/*************************************************************************
@@ -473,7 +473,7 @@
* definitions of an API which supports bzip2-compressed files.
*
*/
-#define FT_BZIP2_H <ftbzip2.h>
+#define FT_BZIP2_H <freetype/ftbzip2.h>
/*************************************************************************
@@ -486,7 +486,7 @@
* definitions of an API which supports Windows FNT files.
*
*/
-#define FT_WINFONTS_H <ftwinfnt.h>
+#define FT_WINFONTS_H <freetype/ftwinfnt.h>
/*************************************************************************
@@ -499,7 +499,7 @@
* API of the optional glyph management component.
*
*/
-#define FT_GLYPH_H <ftglyph.h>
+#define FT_GLYPH_H <freetype/ftglyph.h>
/*************************************************************************
@@ -512,7 +512,7 @@
* API of the optional bitmap conversion component.
*
*/
-#define FT_BITMAP_H <ftbitmap.h>
+#define FT_BITMAP_H <freetype/ftbitmap.h>
/*************************************************************************
@@ -525,7 +525,7 @@
* API of the optional exact bounding box computation routines.
*
*/
-#define FT_BBOX_H <ftbbox.h>
+#define FT_BBOX_H <freetype/ftbbox.h>
/*************************************************************************
@@ -538,7 +538,7 @@
* API of the optional FreeType~2 cache sub-system.
*
*/
-#define FT_CACHE_H <ftcache.h>
+#define FT_CACHE_H <freetype/ftcache.h>
/*************************************************************************
@@ -612,7 +612,7 @@
* compiled on the Mac (note that the base API still works though).
*
*/
-#define FT_MAC_H <ftmac.h>
+#define FT_MAC_H <freetype/ftmac.h>
/*************************************************************************
@@ -625,7 +625,7 @@
* optional multiple-masters management API of FreeType~2.
*
*/
-#define FT_MULTIPLE_MASTERS_H <ftmm.h>
+#define FT_MULTIPLE_MASTERS_H <freetype/ftmm.h>
/*************************************************************************
@@ -639,7 +639,7 @@
* SFNT-based font formats (i.e., TrueType and OpenType).
*
*/
-#define FT_SFNT_NAMES_H <ftsnames.h>
+#define FT_SFNT_NAMES_H <freetype/ftsnames.h>
/*************************************************************************
@@ -653,7 +653,7 @@
* GPOS, GSUB, JSTF).
*
*/
-#define FT_OPENTYPE_VALIDATE_H <ftotval.h>
+#define FT_OPENTYPE_VALIDATE_H <freetype/ftotval.h>
/*************************************************************************
@@ -667,7 +667,7 @@
* mort, morx, bsln, just, kern, opbd, trak, prop).
*
*/
-#define FT_GX_VALIDATE_H <ftgxval.h>
+#define FT_GX_VALIDATE_H <freetype/ftgxval.h>
/*************************************************************************
@@ -680,7 +680,7 @@
* FreeType~2 API which accesses PFR-specific data.
*
*/
-#define FT_PFR_H <ftpfr.h>
+#define FT_PFR_H <freetype/ftpfr.h>
/*************************************************************************
@@ -692,7 +692,7 @@
* A macro used in #include statements to name the file containing the
* FreeType~2 API which provides functions to stroke outline paths.
*/
-#define FT_STROKER_H <ftstroke.h>
+#define FT_STROKER_H <freetype/ftstroke.h>
/*************************************************************************
@@ -704,7 +704,7 @@
* A macro used in #include statements to name the file containing the
* FreeType~2 API which performs artificial obliquing and emboldening.
*/
-#define FT_SYNTHESIS_H <ftsynth.h>
+#define FT_SYNTHESIS_H <freetype/ftsynth.h>
/*************************************************************************
@@ -716,7 +716,7 @@
* A macro used in #include statements to name the file containing the
* FreeType~2 API which provides functions specific to font formats.
*/
-#define FT_FONT_FORMATS_H <ftfntfmt.h>
+#define FT_FONT_FORMATS_H <freetype/ftfntfmt.h>
/* deprecated */
#define FT_XFREE86_H FT_FONT_FORMATS_H
@@ -732,7 +732,7 @@
* FreeType~2 API which performs trigonometric computations (e.g.,
* cosines and arc tangents).
*/
-#define FT_TRIGONOMETRY_H <fttrigon.h>
+#define FT_TRIGONOMETRY_H <freetype/fttrigon.h>
/*************************************************************************
@@ -744,7 +744,7 @@
* A macro used in #include statements to name the file containing the
* FreeType~2 API which performs color filtering for subpixel rendering.
*/
-#define FT_LCD_FILTER_H <ftlcdfil.h>
+#define FT_LCD_FILTER_H <freetype/ftlcdfil.h>
/*************************************************************************
@@ -756,7 +756,7 @@
* A macro used in #include statements to name the file containing the
* FreeType~2 API which performs color filtering for subpixel rendering.
*/
-#define FT_UNPATENTED_HINTING_H <ttunpat.h>
+#define FT_UNPATENTED_HINTING_H <freetype/ttunpat.h>
/*************************************************************************
@@ -768,7 +768,7 @@
* A macro used in #include statements to name the file containing the
* FreeType~2 API which performs color filtering for subpixel rendering.
*/
-#define FT_INCREMENTAL_H <ftincrem.h>
+#define FT_INCREMENTAL_H <freetype/ftincrem.h>
/*************************************************************************
@@ -780,7 +780,7 @@
* A macro used in #include statements to name the file containing the
* FreeType~2 API which returns entries from the TrueType GASP table.
*/
-#define FT_GASP_H <ftgasp.h>
+#define FT_GASP_H <freetype/ftgasp.h>
/*************************************************************************
@@ -792,30 +792,30 @@
* A macro used in #include statements to name the file containing the
* FreeType~2 API which returns individual and ranged glyph advances.
*/
-#define FT_ADVANCES_H <ftadvanc.h>
+#define FT_ADVANCES_H <freetype/ftadvanc.h>
/* */
-#define FT_ERROR_DEFINITIONS_H <fterrdef.h>
+#define FT_ERROR_DEFINITIONS_H <freetype/fterrdef.h>
/* The internals of the cache sub-system are no longer exposed. We */
/* default to FT_CACHE_H at the moment just in case, but we know of */
/* no rogue client that uses them. */
/* */
-#define FT_CACHE_MANAGER_H <ftcache.h>
-#define FT_CACHE_INTERNAL_MRU_H <ftcache.h>
-#define FT_CACHE_INTERNAL_MANAGER_H <ftcache.h>
-#define FT_CACHE_INTERNAL_CACHE_H <ftcache.h>
-#define FT_CACHE_INTERNAL_GLYPH_H <ftcache.h>
-#define FT_CACHE_INTERNAL_IMAGE_H <ftcache.h>
-#define FT_CACHE_INTERNAL_SBITS_H <ftcache.h>
+#define FT_CACHE_MANAGER_H <freetype/ftcache.h>
+#define FT_CACHE_INTERNAL_MRU_H <freetype/ftcache.h>
+#define FT_CACHE_INTERNAL_MANAGER_H <freetype/ftcache.h>
+#define FT_CACHE_INTERNAL_CACHE_H <freetype/ftcache.h>
+#define FT_CACHE_INTERNAL_GLYPH_H <freetype/ftcache.h>
+#define FT_CACHE_INTERNAL_IMAGE_H <freetype/ftcache.h>
+#define FT_CACHE_INTERNAL_SBITS_H <freetype/ftcache.h>
-#define FT_INCREMENTAL_H <ftincrem.h>
+#define FT_INCREMENTAL_H <freetype/ftincrem.h>
-#define FT_TRUETYPE_UNPATENTED_H <ttunpat.h>
+#define FT_TRUETYPE_UNPATENTED_H <freetype/ttunpat.h>
/*
@@ -823,7 +823,7 @@
* only when building the library.
*/
#ifdef FT2_BUILD_LIBRARY
-#define FT_INTERNAL_INTERNAL_H <internal/internal.h>
+#define FT_INTERNAL_INTERNAL_H <freetype/internal/internal.h>
#include FT_INTERNAL_INTERNAL_H
#endif /* FT2_BUILD_LIBRARY */
diff --git a/include/config/ftmodule.h b/include/freetype/config/ftmodule.h
index e145790..e145790 100644
--- a/include/config/ftmodule.h
+++ b/include/freetype/config/ftmodule.h
diff --git a/include/config/ftoption.h b/include/freetype/config/ftoption.h
index 6e8a528..3819586 100644
--- a/include/config/ftoption.h
+++ b/include/freetype/config/ftoption.h
@@ -38,9 +38,9 @@ FT_BEGIN_HEADER
/* library from a single source directory. */
/* */
/* - You can put a copy of this file in your build directory, more */
- /* precisely in `$BUILD/config/ftoption.h', where `$BUILD' is the */
- /* name of a directory that is included _before_ the FreeType include */
- /* path during compilation. */
+ /* precisely in `$BUILD/freetype/config/ftoption.h', where `$BUILD' */
+ /* is the name of a directory that is included _before_ the FreeType */
+ /* include path during compilation. */
/* */
/* The default FreeType Makefiles and Jamfiles use the build */
/* directory `builds/<system>' by default, but you can easily change */
@@ -51,7 +51,7 @@ FT_BEGIN_HEADER
/* locate this file during the build. For example, */
/* */
/* #define FT_CONFIG_OPTIONS_H <myftoptions.h> */
- /* #include <config/ftheader.h> */
+ /* #include <freetype/config/ftheader.h> */
/* */
/* will use `$BUILD/myftoptions.h' instead of this file for macro */
/* definitions. */
@@ -59,7 +59,7 @@ FT_BEGIN_HEADER
/* Note also that you can similarly pre-define the macro */
/* FT_CONFIG_MODULES_H used to locate the file listing of the modules */
/* that are statically linked to the library at compile time. By */
- /* default, this file is <config/ftmodule.h>. */
+ /* default, this file is <freetype/config/ftmodule.h>. */
/* */
/* We highly recommend using the third method whenever possible. */
/* */
@@ -693,6 +693,24 @@ FT_BEGIN_HEADER
/*************************************************************************/
+ /* */
+ /* Option TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES controls the maximum */
+ /* number of bytecode instructions executed for a single run of the */
+ /* bytecode interpreter, needed to prevent infinite loops. You don't */
+ /* want to change this except for very special situations (e.g., making */
+ /* a library fuzzer spend less time to handle broken fonts). */
+ /* */
+ /* It is not expected that this value is ever modified by a configuring */
+ /* script; instead, it gets surrounded with #ifndef ... #endif so that */
+ /* the value can be set as a preprocessor option on the compiler's */
+ /* command line. */
+ /* */
+#ifndef TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES
+#define TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES 1000000L
+#endif
+
+
+ /*************************************************************************/
/*************************************************************************/
/**** ****/
/**** T Y P E 1 D R I V E R C O N F I G U R A T I O N ****/
diff --git a/include/config/ftstdlib.h b/include/freetype/config/ftstdlib.h
index 8ef43c0..4b471d4 100644
--- a/include/config/ftstdlib.h
+++ b/include/freetype/config/ftstdlib.h
@@ -64,6 +64,7 @@
#define FT_INT_MAX INT_MAX
#define FT_INT_MIN INT_MIN
#define FT_UINT_MAX UINT_MAX
+#define FT_LONG_MAX LONG_MAX
#define FT_ULONG_MAX ULONG_MAX
diff --git a/include/freetype.h b/include/freetype/freetype.h
index bca93e5..f68718d 100644
--- a/include/freetype.h
+++ b/include/freetype/freetype.h
@@ -876,17 +876,36 @@ FT_BEGIN_HEADER
/* font formats can have multiple faces in */
/* a font file. */
/* */
- /* face_index :: The index of the face in the font file. It */
- /* is set to~0 if there is only one face in */
+ /* face_index :: This field holds two different values. */
+ /* Bits 0-15 are the index of the face in the */
+ /* font file (starting with value~0). They */
+ /* are set to~0 if there is only one face in */
/* the font file. */
/* */
+ /* Bits 16-30 are relevant to GX variation */
+ /* fonts only, holding the named instance */
+ /* index for the current face index (starting */
+ /* with value~1; value~0 indicates font access */
+ /* without GX variation data). For non-GX */
+ /* fonts, bits 16-30 are ignored. If we have */
+ /* the third named instance of face~4, say, */
+ /* `face_index' is set to 0x00030004. */
+ /* */
+ /* Bit 31 is always zero (this is, */
+ /* `face_index' is always a positive value). */
+ /* */
/* face_flags :: A set of bit flags that give important */
/* information about the face; see */
/* @FT_FACE_FLAG_XXX for the details. */
/* */
- /* style_flags :: A set of bit flags indicating the style of */
- /* the face; see @FT_STYLE_FLAG_XXX for the */
- /* details. */
+ /* style_flags :: The lower 16~bits contain a set of bit */
+ /* flags indicating the style of the face; see */
+ /* @FT_STYLE_FLAG_XXX for the details. Bits */
+ /* 16-30 hold the number of named instances */
+ /* available for the current face if we have a */
+ /* GX variation (sub)font. Bit 31 is always */
+ /* zero (this is, `style_flags' is always a */
+ /* positive value). */
/* */
/* num_glyphs :: The number of glyphs in the face. If the */
/* face is scalable and has sbits (see */
@@ -1392,7 +1411,7 @@ FT_BEGIN_HEADER
/* FT_STYLE_FLAG_XXX */
/* */
/* <Description> */
- /* A list of bit-flags used to indicate the style of a given face. */
+ /* A list of bit flags used to indicate the style of a given face. */
/* These are used in the `style_flags' field of @FT_FaceRec. */
/* */
/* <Values> */
@@ -1824,7 +1843,7 @@ FT_BEGIN_HEADER
/* FT_OPEN_XXX */
/* */
/* <Description> */
- /* A list of bit-field constants used within the `flags' field of the */
+ /* A list of bit field constants used within the `flags' field of the */
/* @FT_Open_Args structure. */
/* */
/* <Values> */
@@ -1971,13 +1990,12 @@ FT_BEGIN_HEADER
/* <Input> */
/* pathname :: A path to the font file. */
/* */
- /* face_index :: The index of the face within the font. The first */
- /* face has index~0. */
+ /* face_index :: See @FT_Open_Face for a detailed description of this */
+ /* parameter. */
/* */
/* <Output> */
/* aface :: A handle to a new face object. If `face_index' is */
/* greater than or equal to zero, it must be non-NULL. */
- /* See @FT_Open_Face for more details. */
/* */
/* <Return> */
/* FreeType error code. 0~means success. */
@@ -2010,13 +2028,12 @@ FT_BEGIN_HEADER
/* */
/* file_size :: The size of the memory chunk used by the font data. */
/* */
- /* face_index :: The index of the face within the font. The first */
- /* face has index~0. */
+ /* face_index :: See @FT_Open_Face for a detailed description of this */
+ /* parameter. */
/* */
/* <Output> */
/* aface :: A handle to a new face object. If `face_index' is */
/* greater than or equal to zero, it must be non-NULL. */
- /* See @FT_Open_Face for more details. */
/* */
/* <Return> */
/* FreeType error code. 0~means success. */
@@ -2048,13 +2065,43 @@ FT_BEGIN_HEADER
/* args :: A pointer to an `FT_Open_Args' structure that must */
/* be filled by the caller. */
/* */
- /* face_index :: The index of the face within the font. The first */
- /* face has index~0. */
+ /* face_index :: This field holds two different values. Bits 0-15 */
+ /* are the index of the face in the font file (starting */
+ /* with value~0). Set it to~0 if there is only one */
+ /* face in the font file. */
+ /* */
+ /* Bits 16-30 are relevant to GX variation fonts only, */
+ /* specifying the named instance index for the current */
+ /* face index (starting with value~1; value~0 makes */
+ /* FreeType ignore named instances). For non-GX fonts, */
+ /* bits 16-30 are ignored. Assuming that you want to */
+ /* access the third named instance in face~4, */
+ /* `face_index' should be set to 0x00030004. If you */
+ /* want to access face~4 without GX variation handling, */
+ /* simply set `face_index' to value~4. */
+ /* */
+ /* FT_Open_Face and its siblings can be used to quickly */
+ /* check whether the font format of a given font */
+ /* resource is supported by FreeType. In general, if */
+ /* the `face_index' argument is negative, the */
+ /* function's return value is~0 if the font format is */
+ /* recognized, or non-zero otherwise. The function */
+ /* allocates a more or less empty face handle in */
+ /* `*aface' (if `aface' isn't NULL); the only two */
+ /* useful fields in this special case are */
+ /* `face->num_faces' and `face->style_flags'. For any */
+ /* negative value of `face_index', `face->num_faces' */
+ /* gives the number of faces within the font file. For */
+ /* the negative value `-(N+1)' (with `N' a 16-bit */
+ /* value), bits 16-30 in `face->style_flags' give the */
+ /* number of named instances in face `N' if we have a */
+ /* GX variation font (or zero otherwise). After */
+ /* examination, the returned @FT_Face structure should */
+ /* be deallocated with a call to @FT_Done_Face. */
/* */
/* <Output> */
/* aface :: A handle to a new face object. If `face_index' is */
/* greater than or equal to zero, it must be non-NULL. */
- /* See note below. */
/* */
/* <Return> */
/* FreeType error code. 0~means success. */
@@ -2064,16 +2111,6 @@ FT_BEGIN_HEADER
/* slot for the face object that can be accessed directly through */
/* `face->glyph'. */
/* */
- /* FT_Open_Face can be used to quickly check whether the font */
- /* format of a given font resource is supported by FreeType. If the */
- /* `face_index' field is negative, the function's return value is~0 */
- /* if the font format is recognized, or non-zero otherwise; */
- /* the function returns a more or less empty face handle in `*aface' */
- /* (if `aface' isn't NULL). The only useful field in this special */
- /* case is `face->num_faces' that gives the number of faces within */
- /* the font file. After examination, the returned @FT_Face structure */
- /* should be deallocated with a call to @FT_Done_Face. */
- /* */
/* Each new face object created with this function also owns a */
/* default @FT_Size object, accessible as `face->size'. */
/* */
@@ -2084,6 +2121,74 @@ FT_BEGIN_HEADER
/* See the discussion of reference counters in the description of */
/* @FT_Reference_Face. */
/* */
+ /* To loop over all faces, use code similar to the following snippet */
+ /* (omitting the error handling). */
+ /* */
+ /* { */
+ /* ... */
+ /* FT_Face face; */
+ /* FT_Long i, num_faces; */
+ /* */
+ /* */
+ /* error = FT_Open_Face( library, args, -1, &face ); */
+ /* if ( error ) { ... } */
+ /* */
+ /* num_faces = face->num_faces; */
+ /* FT_Done_Face( face ); */
+ /* */
+ /* for ( i = 0; i < num_faces; i++ ) */
+ /* { */
+ /* ... */
+ /* error = FT_Open_Face( library, args, i, &face ); */
+ /* ... */
+ /* FT_Done_Face( face ); */
+ /* ... */
+ /* } */
+ /* } */
+ /* */
+ /* To loop over all valid values for `face_index', use something */
+ /* similar to the following snippet, again without error handling. */
+ /* The code accesses all faces immediately (thus only a single call */
+ /* of `FT_Open_Face' within the do-loop), with and without named */
+ /* instances. */
+ /* */
+ /* { */
+ /* ... */
+ /* FT_Face face; */
+ /* */
+ /* FT_Long num_faces = 0; */
+ /* FT_Long num_instances = 0; */
+ /* */
+ /* FT_Long face_idx = 0; */
+ /* FT_Long instance_idx = 0; */
+ /* */
+ /* */
+ /* do */
+ /* { */
+ /* FT_Long id = ( instance_idx << 16 ) + face_idx; */
+ /* */
+ /* */
+ /* error = FT_Open_Face( library, args, id, &face ); */
+ /* if ( error ) { ... } */
+ /* */
+ /* num_faces = face->num_faces; */
+ /* num_instances = face->style_flags >> 16; */
+ /* */
+ /* ... */
+ /* */
+ /* FT_Done_Face( face ); */
+ /* */
+ /* if ( instance_idx < num_instances ) */
+ /* instance_idx++; */
+ /* else */
+ /* { */
+ /* face_idx++; */
+ /* instance_idx = 0; */
+ /* } */
+ /* */
+ /* } while ( face_idx < num_faces ) */
+ /* } */
+ /* */
FT_EXPORT( FT_Error )
FT_Open_Face( FT_Library library,
const FT_Open_Args* args,
@@ -2521,7 +2626,7 @@ FT_BEGIN_HEADER
* FT_LOAD_XXX
*
* @description:
- * A list of bit-field constants used with @FT_Load_Glyph to indicate
+ * A list of bit field constants used with @FT_Load_Glyph to indicate
* what kind of operations to perform during glyph loading.
*
* @values:
@@ -2638,6 +2743,16 @@ FT_BEGIN_HEADER
* bitmaps transparently. Those bitmaps will be in the
* @FT_PIXEL_MODE_GRAY format.
*
+ * FT_LOAD_COMPUTE_METRICS ::
+ * This flag sets computing glyph metrics without the use of bundled
+ * metrics tables (for example, the `hdmx' table in TrueType fonts).
+ * Well-behaving fonts have optimized bundled metrics and these should
+ * be used. This flag is mainly used by font validating or font
+ * editing applications, which need to ignore, verify, or edit those
+ * tables.
+ *
+ * Currently, this flag is only implemented for TrueType fonts.
+ *
* FT_LOAD_CROP_BITMAP ::
* Ignored. Deprecated.
*
@@ -2683,6 +2798,7 @@ FT_BEGIN_HEADER
#define FT_LOAD_NO_AUTOHINT ( 1L << 15 )
/* Bits 16..19 are used by `FT_LOAD_TARGET_' */
#define FT_LOAD_COLOR ( 1L << 20 )
+#define FT_LOAD_COMPUTE_METRICS ( 1L << 21 )
/* */
@@ -2705,9 +2821,6 @@ FT_BEGIN_HEADER
* have specified (e.g., the TrueType bytecode interpreter). You can set
* @FT_LOAD_FORCE_AUTOHINT to ensure that the auto-hinter is used.
*
- * Also note that @FT_LOAD_TARGET_LIGHT is an exception, in that it
- * always implies @FT_LOAD_FORCE_AUTOHINT.
- *
* @values:
* FT_LOAD_TARGET_NORMAL ::
* This corresponds to the default hinting algorithm, optimized for
@@ -2715,11 +2828,14 @@ FT_BEGIN_HEADER
* @FT_LOAD_TARGET_MONO instead.
*
* FT_LOAD_TARGET_LIGHT ::
- * A lighter hinting algorithm for non-monochrome modes. Many
- * generated glyphs are more fuzzy but better resemble its original
- * shape. A bit like rendering on Mac OS~X.
- *
- * As a special exception, this target implies @FT_LOAD_FORCE_AUTOHINT.
+ * A lighter hinting algorithm for gray-level modes. Many generated
+ * glyphs are fuzzier but better resemble their original shape. This
+ * is achieved by snapping glyphs to the pixel grid only vertically
+ * (Y-axis), as is done by Microsoft's ClearType and Adobe's
+ * proprietary font renderer. This preserves inter-glyph spacing in
+ * horizontal text. The snapping is done either by the native font
+ * driver if the driver itself and the font support it or by the
+ * auto-hinter.
*
* FT_LOAD_TARGET_MONO ::
* Strong hinting algorithm that should only be used for monochrome
@@ -2826,7 +2942,10 @@ FT_BEGIN_HEADER
/* field in the @FT_GlyphSlotRec structure gives the format of the */
/* returned bitmap. */
/* */
- /* All modes except @FT_RENDER_MODE_MONO use 256 levels of opacity. */
+ /* All modes except @FT_RENDER_MODE_MONO use 256 levels of opacity, */
+ /* indicating pixel coverage. Use linear alpha blending and gamma */
+ /* correction to correctly render non-monochrome glyph bitmaps onto a */
+ /* surface; see @FT_Render_Glyph. */
/* */
/* <Values> */
/* FT_RENDER_MODE_NORMAL :: */
@@ -2912,6 +3031,83 @@ FT_BEGIN_HEADER
/* To get meaningful results, font scaling values must be set with */
/* functions like @FT_Set_Char_Size before calling FT_Render_Glyph. */
/* */
+ /* When FreeType outputs a bitmap of a glyph, it really outputs an */
+ /* alpha coverage map. If a pixel is completely covered by a */
+ /* filled-in outline, the bitmap contains 0xFF at that pixel, meaning */
+ /* that 0xFF/0xFF fraction of that pixel is covered, meaning the */
+ /* pixel is 100% black (or 0% bright). If a pixel is only 50% */
+ /* covered (value 0x80), the pixel is made 50% black (50% bright or a */
+ /* middle shade of grey). 0% covered means 0% black (100% bright or */
+ /* white). */
+ /* */
+ /* On high-DPI screens like on smartphones and tablets, the pixels */
+ /* are so small that their chance of being completely covered and */
+ /* therefore completely black are fairly good. On the low-DPI */
+ /* screens, however, the situation is different. The pixels are too */
+ /* large for most of the details of a glyph and shades of gray are */
+ /* the norm rather than the exception. */
+ /* */
+ /* This is relevant because all our screens have a second problem: */
+ /* they are not linear. 1~+~1 is not~2. Twice the value does not */
+ /* result in twice the brightness. When a pixel is only 50% covered, */
+ /* the coverage map says 50% black, and this translates to a pixel */
+ /* value of 128 when you use 8~bits per channel (0-255). However, */
+ /* this does not translate to 50% brightness for that pixel on our */
+ /* sRGB and gamma~2.2 screens. Due to their non-linearity, they */
+ /* dwell longer in the darks and only a pixel value of about 186 */
+ /* results in 50% brightness – 128 ends up too dark on both bright */
+ /* and dark backgrounds. The net result is that dark text looks */
+ /* burnt-out, pixely and blotchy on bright background, bright text */
+ /* too frail on dark backgrounds, and colored text on colored */
+ /* background (for example, red on green) seems to have dark halos or */
+ /* `dirt' around it. The situation is especially ugly for diagonal */
+ /* stems like in `w' glyph shapes where the quality of FreeType's */
+ /* anti-aliasing depends on the correct display of grays. On */
+ /* high-DPI screens where smaller, fully black pixels reign supreme, */
+ /* this doesn't matter, but on our low-DPI screens with all the gray */
+ /* shades, it does. 0% and 100% brightness are the same things in */
+ /* linear and non-linear space, just all the shades in-between */
+ /* aren't. */
+ /* */
+ /* The blending function for placing text over a background is */
+ /* */
+ /* { */
+ /* dst = alpha * src + (1 - alpha) * dst , */
+ /* } */
+ /* */
+ /* which is known as the OVER operator. */
+ /* */
+ /* To correctly composite an antialiased pixel of a glyph onto a */
+ /* surface, */
+ /* */
+ /* 1. take the foreground and background colors (e.g., in sRGB space) */
+ /* and apply gamma to get them in a linear space, */
+ /* */
+ /* 2. use OVER to blend the two linear colors using the glyph pixel */
+ /* as the alpha value (remember, the glyph bitmap is an alpha */
+ /* coverage bitmap), and */
+ /* */
+ /* 3. apply inverse gamma to the blended pixel and write it back to */
+ /* the image. */
+ /* */
+ /* Internal testing at Adobe found that a target inverse gamma of~1.8 */
+ /* for step~3 gives good results across a wide range of displays with */
+ /* an sRGB gamma curve or a similar one. */
+ /* */
+ /* This process can cost performance. There is an approximation that */
+ /* does not need to know about the background color; see */
+ /* https://bel.fi/alankila/lcd/ and */
+ /* https://bel.fi/alankila/lcd/alpcor.html for details. */
+ /* */
+ /* *ATTENTION*: Linear blending is even more important when dealing */
+ /* with subpixel-rendered glyphs to prevent color-fringing! A */
+ /* subpixel-rendered glyph must first be filtered with a filter that */
+ /* gives equal weight to the three color primaries and does not */
+ /* exceed a sum of 0x100, see section @lcd_filtering. Then the */
+ /* only difference to gray linear blending is that subpixel-rendered */
+ /* linear blending is done 3~times per pixel: red foreground subpixel */
+ /* to red background subpixel and so on for green and blue. */
+ /* */
FT_EXPORT( FT_Error )
FT_Render_Glyph( FT_GlyphSlot slot,
FT_Render_Mode render_mode );
@@ -2927,15 +3123,22 @@ FT_BEGIN_HEADER
/* @FT_Get_Kerning. */
/* */
/* <Values> */
- /* FT_KERNING_DEFAULT :: Return scaled and grid-fitted kerning */
- /* distances (value is~0). */
+ /* FT_KERNING_DEFAULT :: Return grid-fitted kerning distances in */
+ /* pixels (value is~0). Whether they are */
+ /* scaled depends on @FT_LOAD_NO_SCALE. */
/* */
- /* FT_KERNING_UNFITTED :: Return scaled but un-grid-fitted kerning */
- /* distances. */
+ /* FT_KERNING_UNFITTED :: Return un-grid-fitted kerning distances in */
+ /* 26.6 fractional pixels. Whether they are */
+ /* scaled depends on @FT_LOAD_NO_SCALE. */
/* */
/* FT_KERNING_UNSCALED :: Return the kerning vector in original font */
/* units. */
/* */
+ /* <Note> */
+ /* FT_KERNING_DEFAULT returns full pixel values; it also makes */
+ /* FreeType heuristically scale down kerning distances at small ppem */
+ /* values so that they don't become too big. */
+ /* */
typedef enum FT_Kerning_Mode_
{
FT_KERNING_DEFAULT = 0,
@@ -2972,9 +3175,10 @@ FT_BEGIN_HEADER
/* kerning vector. */
/* */
/* <Output> */
- /* akerning :: The kerning vector. This is either in font units */
- /* or in pixels (26.6 format) for scalable formats, */
- /* and in pixels for fixed-sizes formats. */
+ /* akerning :: The kerning vector. This is either in font units, */
+ /* fractional pixels (26.6 format), or pixels for */
+ /* scalable formats, and in pixels for fixed-sizes */
+ /* formats. */
/* */
/* <Return> */
/* FreeType error code. 0~means success. */
@@ -3259,6 +3463,13 @@ FT_BEGIN_HEADER
/* } */
/* } */
/* */
+ /* Be aware that character codes can have values up to 0xFFFFFFFF; */
+ /* this might happen for non-Unicode or malformed cmaps. However, */
+ /* even with regular Unicode encoding, so-called `last resort fonts' */
+ /* (using SFNT cmap format 13, see function @FT_Get_CMap_Format) */
+ /* normally have entries for all Unicode characters up to 0x1FFFFF, */
+ /* which can cause *a lot* of iterations. */
+ /* */
/* Note that `*agindex' is set to~0 if the charmap is empty. The */
/* result itself can be~0 in two cases: if the charmap is empty or */
/* if the value~0 is the first valid character code. */
@@ -3454,6 +3665,9 @@ FT_BEGIN_HEADER
/* bitmaps available in the font, then the font is unembeddable. */
/* */
/* <Note> */
+ /* The flags are ORed together, thus more than a single value can be */
+ /* returned. */
+ /* */
/* While the fsType flags can indicate that a font may be embedded, a */
/* license with the font vendor may be separately required to use the */
/* font in this way. */
@@ -3839,7 +4053,8 @@ FT_BEGIN_HEADER
/* a :: The number to be rounded. */
/* */
/* <Return> */
- /* The result of `(a + 0x8000) & -0x10000'. */
+ /* `a' rounded to nearest 16.16 fixed integer, halfway cases away */
+ /* from zero. */
/* */
FT_EXPORT( FT_Fixed )
FT_RoundFix( FT_Fixed a );
@@ -3858,7 +4073,7 @@ FT_BEGIN_HEADER
/* a :: The number for which the ceiling function is to be computed. */
/* */
/* <Return> */
- /* The result of `(a + 0x10000 - 1) & -0x10000'. */
+ /* `a' rounded towards plus infinity. */
/* */
FT_EXPORT( FT_Fixed )
FT_CeilFix( FT_Fixed a );
@@ -3877,7 +4092,7 @@ FT_BEGIN_HEADER
/* a :: The number for which the floor function is to be computed. */
/* */
/* <Return> */
- /* The result of `a & -0x10000'. */
+ /* `a' rounded towards minus infinity. */
/* */
FT_EXPORT( FT_Fixed )
FT_FloorFix( FT_Fixed a );
@@ -3958,7 +4173,7 @@ FT_BEGIN_HEADER
*/
#define FREETYPE_MAJOR 2
#define FREETYPE_MINOR 6
-#define FREETYPE_PATCH 0
+#define FREETYPE_PATCH 2
/*************************************************************************/
diff --git a/include/ftadvanc.h b/include/freetype/ftadvanc.h
index b4d2aed..b4d2aed 100644
--- a/include/ftadvanc.h
+++ b/include/freetype/ftadvanc.h
diff --git a/include/ftautoh.h b/include/freetype/ftautoh.h
index cf7b76f..d0f6445 100644
--- a/include/ftautoh.h
+++ b/include/freetype/ftautoh.h
@@ -247,8 +247,8 @@ FT_BEGIN_HEADER
*/
typedef struct FT_Prop_GlyphToScriptMap_
{
- FT_Face face;
- FT_Byte* map;
+ FT_Face face;
+ FT_UShort* map;
} FT_Prop_GlyphToScriptMap;
@@ -439,6 +439,59 @@ FT_BEGIN_HEADER
*/
+ /**************************************************************************
+ *
+ * @property:
+ * no-stem-darkening[autofit]
+ *
+ * @description:
+ * *Experimental* *only,* *requires* *linear* *alpha* *blending* *and*
+ * *gamma* *correction*
+ *
+ * Stem darkening emboldens glyphs at smaller sizes to make them more
+ * readable on common low-DPI screens when using linear alpha blending
+ * and gamma correction, see @FT_Render_Glyph. When not using linear
+ * alpha blending and gamma correction, glyphs will appear heavy and
+ * fuzzy!
+ *
+ * Gamma correction essentially lightens fonts since shades of grey are
+ * shifted to higher pixel values (=~higher brightness) to match the
+ * original intention to the reality of our screens. The side-effect is
+ * that glyphs `thin out'. Mac OS~X and Adobe's proprietary font
+ * rendering library implement a counter-measure: stem darkening at
+ * smaller sizes where shades of gray dominate. By emboldening a glyph
+ * slightly in relation to its pixel size, individual pixels get higher
+ * coverage of filled-in outlines and are therefore `blacker'. This
+ * counteracts the `thinning out' of glyphs, making text remain readable
+ * at smaller sizes. All glyphs that pass through the auto-hinter will
+ * be emboldened unless this property is set to TRUE.
+ *
+ * See the description of the CFF driver for algorithmic details. Total
+ * consistency with the CFF driver is currently not achieved because the
+ * emboldening method differs and glyphs must be scaled down on the
+ * Y-axis to keep outline points inside their precomputed blue zones.
+ * The smaller the size (especially 9ppem and down), the higher the loss
+ * of emboldening versus the CFF driver.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @property:
+ * darkening-parameters[autofit]
+ *
+ * @description:
+ * *Experimental* *only*
+ *
+ * See the description of the CFF driver for details. This
+ * implementation appropriates the
+ * CFF_CONFIG_OPTION_DARKENING_PARAMETER_* #defines for consistency.
+ * Note the differences described in @no-stem-darkening[autofit].
+ *
+ */
+
+
/* */
diff --git a/include/ftbbox.h b/include/freetype/ftbbox.h
index 9d9d040..9d9d040 100644
--- a/include/ftbbox.h
+++ b/include/freetype/ftbbox.h
diff --git a/include/ftbdf.h b/include/freetype/ftbdf.h
index 0bdabf4..0bdabf4 100644
--- a/include/ftbdf.h
+++ b/include/freetype/ftbdf.h
diff --git a/include/ftbitmap.h b/include/freetype/ftbitmap.h
index 46cc47b..46cc47b 100644
--- a/include/ftbitmap.h
+++ b/include/freetype/ftbitmap.h
diff --git a/include/ftbzip2.h b/include/freetype/ftbzip2.h
index c25f946..c25f946 100644
--- a/include/ftbzip2.h
+++ b/include/freetype/ftbzip2.h
diff --git a/include/ftcache.h b/include/freetype/ftcache.h
index 68525bb..68525bb 100644
--- a/include/ftcache.h
+++ b/include/freetype/ftcache.h
diff --git a/include/ftcffdrv.h b/include/freetype/ftcffdrv.h
index 6c8e416..8500346 100644
--- a/include/ftcffdrv.h
+++ b/include/freetype/ftcffdrv.h
@@ -111,8 +111,8 @@ FT_BEGIN_HEADER
*
* @order:
* hinting-engine
- * no-stem-darkening
- * darkening-parameters
+ * no-stem-darkening[cff]
+ * darkening-parameters[cff]
*
*/
@@ -175,7 +175,7 @@ FT_BEGIN_HEADER
/**************************************************************************
*
* @property:
- * no-stem-darkening
+ * no-stem-darkening[cff]
*
* @description:
* By default, the Adobe CFF engine darkens stems at smaller sizes,
@@ -205,7 +205,7 @@ FT_BEGIN_HEADER
/**************************************************************************
*
* @property:
- * darkening-parameters
+ * darkening-parameters[cff]
*
* @description:
* By default, the Adobe CFF engine darkens stems as follows (if the
diff --git a/include/ftchapters.h b/include/freetype/ftchapters.h
index d333761..ab43895 100644
--- a/include/ftchapters.h
+++ b/include/freetype/ftchapters.h
@@ -119,3 +119,17 @@
/* lcd_filtering */
/* */
/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* <Chapter> */
+/* error_codes */
+/* */
+/* <Title> */
+/* Error Codes */
+/* */
+/* <Sections> */
+/* error_enumerations */
+/* error_code_values */
+/* */
+/***************************************************************************/
diff --git a/include/ftcid.h b/include/freetype/ftcid.h
index 05741c8..05741c8 100644
--- a/include/ftcid.h
+++ b/include/freetype/ftcid.h
diff --git a/include/fterrdef.h b/include/freetype/fterrdef.h
index 1bf0751..3bf4e63 100644
--- a/include/fterrdef.h
+++ b/include/freetype/fterrdef.h
@@ -16,18 +16,43 @@
/***************************************************************************/
- /*******************************************************************/
- /*******************************************************************/
- /***** *****/
- /***** LIST OF ERROR CODES/MESSAGES *****/
- /***** *****/
- /*******************************************************************/
- /*******************************************************************/
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* error_code_values */
+ /* */
+ /* <Title> */
+ /* Error Code Values */
+ /* */
+ /* <Abstract> */
+ /* All possible error codes returned by FreeType functions. */
+ /* */
+ /* <Description> */
+ /* The list below is taken verbatim from the file `fterrdef.h' */
+ /* (loaded automatically by including `FT_FREETYPE_H'). The first */
+ /* argument of the `FT_ERROR_DEF_' macro is the error label; by */
+ /* default, the prefix `FT_Err_' gets added so that you get error */
+ /* names like `FT_Err_Cannot_Open_Resource'. The second argument is */
+ /* the error code, and the last argument an error string, which is not */
+ /* used by FreeType. */
+ /* */
+ /* Within your application you should *only* use error names and */
+ /* *never* its numeric values! The latter might (and actually do) */
+ /* change in forthcoming FreeType versions. */
+ /* */
+ /* Macro `FT_NOERRORDEF_' defines `FT_Err_Ok', which is always zero. */
+ /* See the `Error Enumerations' subsection how to automatically */
+ /* generate a list of error strings. */
+ /* */
+ /*************************************************************************/
- /* You need to define both FT_ERRORDEF_ and FT_NOERRORDEF_ before */
- /* including this file. */
-
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* FT_Err_XXX */
+ /* */
+ /*************************************************************************/
/* generic errors */
@@ -218,7 +243,7 @@
FT_ERRORDEF_( No_Unicode_Glyph_Name, 0xA3,
"no Unicode glyph name found" )
FT_ERRORDEF_( Glyph_Too_Big, 0xA4,
- "glyph to big for hinting" )
+ "glyph too big for hinting" )
/* BDF errors */
@@ -245,5 +270,7 @@
FT_ERRORDEF_( Corrupted_Font_Glyphs, 0xBA,
"Font glyphs corrupted or missing fields" )
+ /* */
+
/* END */
diff --git a/include/fterrors.h b/include/freetype/fterrors.h
index 376bee6..0507b9a 100644
--- a/include/fterrors.h
+++ b/include/freetype/fterrors.h
@@ -18,68 +18,86 @@
/*************************************************************************/
/* */
- /* This special header file is used to define the handling of FT2 */
- /* enumeration constants. It can also be used to generate error message */
- /* strings with a small macro trick explained below. */
+ /* <Section> */
+ /* error_enumerations */
/* */
- /* I - Error Formats */
- /* ----------------- */
+ /* <Title> */
+ /* Error Enumerations */
+ /* */
+ /* <Abstract> */
+ /* How to handle errors and error strings. */
+ /* */
+ /* <Description> */
+ /* The header file `fterrors.h' (which is automatically included by */
+ /* `freetype.h' defines the handling of FreeType's enumeration */
+ /* constants. It can also be used to generate error message strings */
+ /* with a small macro trick explained below. */
+ /* */
+ /* *Error* *Formats* */
/* */
/* The configuration macro FT_CONFIG_OPTION_USE_MODULE_ERRORS can be */
- /* defined in ftoption.h in order to make the higher byte indicate */
+ /* defined in `ftoption.h' in order to make the higher byte indicate */
/* the module where the error has happened (this is not compatible */
- /* with standard builds of FreeType 2). See the file `ftmoderr.h' for */
- /* more details. */
+ /* with standard builds of FreeType&nbsp;2, however). See the file */
+ /* `ftmoderr.h' for more details. */
/* */
+ /* *Error* *Message* *Strings* */
/* */
- /* II - Error Message strings */
- /* -------------------------- */
- /* */
- /* The error definitions below are made through special macros that */
- /* allow client applications to build a table of error message strings */
- /* if they need it. The strings are not included in a normal build of */
- /* FreeType 2 to save space (most client applications do not use */
- /* them). */
+ /* Error definitions are set up with special macros that allow client */
+ /* applications to build a table of error message strings. The */
+ /* strings are not included in a normal build of FreeType&nbsp;2 to */
+ /* save space (most client applications do not use them). */
/* */
/* To do so, you have to define the following macros before including */
- /* this file: */
+ /* this file. */
/* */
- /* FT_ERROR_START_LIST :: */
- /* This macro is called before anything else to define the start of */
- /* the error list. It is followed by several FT_ERROR_DEF calls */
- /* (see below). */
+ /* { */
+ /* FT_ERROR_START_LIST */
+ /* } */
/* */
- /* FT_ERROR_DEF( e, v, s ) :: */
- /* This macro is called to define one single error. */
- /* `e' is the error code identifier (e.g. FT_Err_Invalid_Argument). */
- /* `v' is the error numerical value. */
- /* `s' is the corresponding error string. */
+ /* This macro is called before anything else to define the start of */
+ /* the error list. It is followed by several FT_ERROR_DEF calls. */
/* */
- /* FT_ERROR_END_LIST :: */
- /* This macro ends the list. */
+ /* { */
+ /* FT_ERROR_DEF( e, v, s ) */
+ /* } */
/* */
- /* Additionally, you have to undefine __FTERRORS_H__ before #including */
- /* this file. */
+ /* This macro is called to define one single error. `e' is the error */
+ /* code identifier (e.g., `Invalid_Argument'), `v' is the error's */
+ /* numerical value, and `s' is the corresponding error string. */
+ /* */
+ /* { */
+ /* FT_ERROR_END_LIST */
+ /* } */
+ /* */
+ /* This macro ends the list. */
+ /* */
+ /* Additionally, you have to undefine `__FTERRORS_H__' before */
+ /* #including this file. */
+ /* */
+ /* Here is a simple example. */
/* */
- /* Here is a simple example: */
+ /* { */
+ /* #undef __FTERRORS_H__ */
+ /* #define FT_ERRORDEF( e, v, s ) { e, s }, */
+ /* #define FT_ERROR_START_LIST { */
+ /* #define FT_ERROR_END_LIST { 0, NULL } }; */
/* */
+ /* const struct */
/* { */
- /* #undef __FTERRORS_H__ */
- /* #define FT_ERRORDEF( e, v, s ) { e, s }, */
- /* #define FT_ERROR_START_LIST { */
- /* #define FT_ERROR_END_LIST { 0, 0 } }; */
+ /* int err_code; */
+ /* const char* err_msg; */
+ /* } ft_errors[] = */
/* */
- /* const struct */
- /* { */
- /* int err_code; */
- /* const char* err_msg; */
- /* } ft_errors[] = */
+ /* #include FT_ERRORS_H */
+ /* } */
/* */
- /* #include FT_ERRORS_H */
- /* } */
+ /* Note that `FT_Err_Ok' is _not_ defined with `FT_ERRORDEF' but with */
+ /* `FT_NOERRORDEF'; it is always zero. */
/* */
/*************************************************************************/
+ /* */
#ifndef __FTERRORS_H__
#define __FTERRORS_H__
diff --git a/include/ftfntfmt.h b/include/freetype/ftfntfmt.h
index 1f8ff28..1f8ff28 100644
--- a/include/ftfntfmt.h
+++ b/include/freetype/ftfntfmt.h
diff --git a/include/ftgasp.h b/include/freetype/ftgasp.h
index 9a9b632..9a9b632 100644
--- a/include/ftgasp.h
+++ b/include/freetype/ftgasp.h
diff --git a/include/ftglyph.h b/include/freetype/ftglyph.h
index 803ad39..803ad39 100644
--- a/include/ftglyph.h
+++ b/include/freetype/ftglyph.h
diff --git a/include/ftgxval.h b/include/freetype/ftgxval.h
index 0e9ac1d..0e9ac1d 100644
--- a/include/ftgxval.h
+++ b/include/freetype/ftgxval.h
diff --git a/include/ftgzip.h b/include/freetype/ftgzip.h
index b3a532d..b3a532d 100644
--- a/include/ftgzip.h
+++ b/include/freetype/ftgzip.h
diff --git a/include/ftimage.h b/include/freetype/ftimage.h
index 82f284c..82f284c 100644
--- a/include/ftimage.h
+++ b/include/freetype/ftimage.h
diff --git a/include/ftincrem.h b/include/freetype/ftincrem.h
index 840af25..840af25 100644
--- a/include/ftincrem.h
+++ b/include/freetype/ftincrem.h
diff --git a/include/ftlcdfil.h b/include/freetype/ftlcdfil.h
index 4cd999a..a9dd3ea 100644
--- a/include/ftlcdfil.h
+++ b/include/freetype/ftlcdfil.h
@@ -41,56 +41,78 @@ FT_BEGIN_HEADER
* LCD Filtering
*
* @abstract:
- * Reduce color fringes of LCD-optimized bitmaps.
+ * Reduce color fringes of subpixel-rendered bitmaps.
*
* @description:
- * The @FT_Library_SetLcdFilter API can be used to specify a low-pass
- * filter, which is then applied to LCD-optimized bitmaps generated
- * through @FT_Render_Glyph. This is useful to reduce color fringes
- * that would occur with unfiltered rendering.
+ * Subpixel rendering exploits the color-striped structure of LCD
+ * pixels, increasing the available resolution in the direction of the
+ * stripe (usually horizontal RGB) by a factor of~3. Since these
+ * subpixels are color pixels, using them unfiltered creates severe
+ * color fringes. Use the @FT_Library_SetLcdFilter API to specify a
+ * low-pass filter, which is then applied to subpixel-rendered bitmaps
+ * generated through @FT_Render_Glyph. The filter sacrifices some of
+ * the higher resolution to reduce color fringes, making the glyph image
+ * slightly blurrier. Positional improvements will remain.
*
* Note that no filter is active by default, and that this function is
* *not* implemented in default builds of the library. You need to
* #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING in your `ftoption.h' file
* in order to activate it.
*
- * FreeType generates alpha coverage maps, which are linear by nature.
- * For instance, the value 0x80 in bitmap representation means that
- * (within numerical precision) 0x80/0xFF fraction of that pixel is
- * covered by the glyph's outline. The blending function for placing
- * text over a background is
- *
- * {
- * dst = alpha * src + (1 - alpha) * dst ,
- * }
- *
- * which is known as OVER. However, when calculating the output of the
- * OVER operator, the source colors should first be transformed to a
- * linear color space, then alpha blended in that space, and transformed
- * back to the output color space.
- *
- * When linear light blending is used, the default FIR5 filtering
- * weights (as given by FT_LCD_FILTER_DEFAULT) are no longer optimal, as
- * they have been designed for black on white rendering while lacking
- * gamma correction. To preserve color neutrality, weights for a FIR5
- * filter should be chosen according to two free parameters `a' and `c',
- * and the FIR weights should be
- *
- * {
- * [a - c, a + c, 2 * a, a + c, a - c] .
- * }
- *
- * This formula generates equal weights for all the color primaries
- * across the filter kernel, which makes it colorless. One suggested
- * set of weights is
- *
- * {
- * [0x10, 0x50, 0x60, 0x50, 0x10] ,
- * }
- *
- * where `a' has value 0x30 and `b' value 0x20. The weights in filter
- * may have a sum larger than 0x100, which increases coloration slightly
- * but also improves contrast.
+ * A filter should have two properties:
+ *
+ * 1) It should be normalized, meaning the sum of the 5~components
+ * should be 256 (0x100). It is possible to go above or under this
+ * target sum, however: going under means tossing out contrast, going
+ * over means invoking clamping and thereby non-linearities that
+ * increase contrast somewhat at the expense of greater distortion
+ * and color-fringing. Contrast is better enhanced through stem
+ * darkening.
+ *
+ * 2) It should be color-balanced, meaning a filter `{~a, b, c, b, a~}'
+ * where a~+ b~=~c. It distributes the computed coverage for one
+ * subpixel to all subpixels equally, sacrificing some won resolution
+ * but drastically reducing color-fringing. Positioning improvements
+ * remain! Note that color-fringing can only really be minimized
+ * when using a color-balanced filter and alpha-blending the glyph
+ * onto a surface in linear space; see @FT_Render_Glyph.
+ *
+ * Regarding the form, a filter can be a `boxy' filter or a `beveled'
+ * filter. Boxy filters are sharper but are less forgiving of non-ideal
+ * gamma curves of a screen (viewing angles!), beveled filters are
+ * fuzzier but more tolerant.
+ *
+ * Examples:
+ *
+ * - [0x10 0x40 0x70 0x40 0x10] is beveled and neither balanced nor
+ * normalized.
+ *
+ * - [0x1A 0x33 0x4D 0x33 0x1A] is beveled and balanced but not
+ * normalized.
+ *
+ * - [0x19 0x33 0x66 0x4c 0x19] is beveled and normalized but not
+ * balanced.
+ *
+ * - [0x00 0x4c 0x66 0x4c 0x00] is boxily beveled and normalized but not
+ * balanced.
+ *
+ * - [0x00 0x55 0x56 0x55 0x00] is boxy, normalized, and almost
+ * balanced.
+ *
+ * - [0x08 0x4D 0x56 0x4D 0x08] is beveled, normalized and, almost
+ * balanced.
+ *
+ * It is important to understand that linear alpha blending and gamma
+ * correction is critical for correctly rendering glyphs onto surfaces
+ * without artifacts and even more critical when subpixel rendering is
+ * involved.
+ *
+ * Each of the 3~alpha values (subpixels) is independently used to blend
+ * one color channel. That is, red alpha blends the red channel of the
+ * text color with the red channel of the background pixel. The
+ * distribution of density values by the color-balanced filter assumes
+ * alpha blending is done in linear space; only then color artifacts
+ * cancel out.
*/
@@ -111,10 +133,21 @@ FT_BEGIN_HEADER
* The default filter reduces color fringes considerably, at the cost
* of a slight blurriness in the output.
*
+ * It is a beveled, normalized, and color-balanced five-tap filter
+ * that is more forgiving to screens with non-ideal gamma curves and
+ * viewing angles. Note that while color-fringing is reduced, it can
+ * only be minimized by using linear alpha blending and gamma
+ * correction to render glyphs onto surfaces.
+ *
* FT_LCD_FILTER_LIGHT ::
- * The light filter is a variant that produces less blurriness at the
- * cost of slightly more color fringes than the default one. It might
- * be better, depending on taste, your monitor, or your personal vision.
+ * The light filter is a variant that is sharper at the cost of
+ * slightly more color fringes than the default one.
+ *
+ * It is a boxy, normalized, and color-balanced three-tap filter that
+ * is less forgiving to screens with non-ideal gamma curves and
+ * viewing angles. This filter works best when the rendering system
+ * uses linear alpha blending and gamma correction to render glyphs
+ * onto surfaces.
*
* FT_LCD_FILTER_LEGACY ::
* This filter corresponds to the original libXft color filter. It
@@ -126,14 +159,23 @@ FT_BEGIN_HEADER
* This filter is only provided for comparison purposes, and might be
* disabled or stay unsupported in the future.
*
+ * FT_LCD_FILTER_LEGACY1 ::
+ * For historical reasons, the FontConfig library returns a different
+ * enumeration value for legacy LCD filtering. To make code work that
+ * (incorrectly) forwards FontConfig's enumeration value to
+ * @FT_Library_SetLcdFilter without proper mapping, it is thus easiest
+ * to have another enumeration value, which is completely equal to
+ * `FT_LCD_FILTER_LEGACY'.
+ *
* @since:
- * 2.3.0
+ * 2.3.0 (`FT_LCD_FILTER_LEGACY1' since 2.6.2)
*/
typedef enum FT_LcdFilter_
{
FT_LCD_FILTER_NONE = 0,
FT_LCD_FILTER_DEFAULT = 1,
FT_LCD_FILTER_LIGHT = 2,
+ FT_LCD_FILTER_LEGACY1 = 3,
FT_LCD_FILTER_LEGACY = 16,
FT_LCD_FILTER_MAX /* do not remove */
@@ -208,9 +250,8 @@ FT_BEGIN_HEADER
* @description:
* Use this function to override the filter weights selected by
* @FT_Library_SetLcdFilter. By default, FreeType uses the quintuple
- * (0x00, 0x55, 0x56, 0x55, 0x00) for FT_LCD_FILTER_LIGHT, and (0x10,
- * 0x40, 0x70, 0x40, 0x10) for FT_LCD_FILTER_DEFAULT and
- * FT_LCD_FILTER_LEGACY.
+ * (0x00, 0x55, 0x56, 0x55, 0x00) for FT_LCD_FILTER_LIGHT, and (0x08,
+ * 0x4D, 0x56, 0x4D, 0x08) for FT_LCD_FILTER_DEFAULT.
*
* @input:
* library ::
diff --git a/include/ftlist.h b/include/freetype/ftlist.h
index 12b48c7..12b48c7 100644
--- a/include/ftlist.h
+++ b/include/freetype/ftlist.h
diff --git a/include/ftlzw.h b/include/freetype/ftlzw.h
index d3ec28e..d3ec28e 100644
--- a/include/ftlzw.h
+++ b/include/freetype/ftlzw.h
diff --git a/include/ftmac.h b/include/freetype/ftmac.h
index 14c55cf..14c55cf 100644
--- a/include/ftmac.h
+++ b/include/freetype/ftmac.h
diff --git a/include/ftmm.h b/include/freetype/ftmm.h
index 6ef4798..96dd66e 100644
--- a/include/ftmm.h
+++ b/include/freetype/ftmm.h
@@ -203,9 +203,13 @@ FT_BEGIN_HEADER
/* */
/* axis :: An axis descriptor table. */
/* GX fonts contain slightly more data than MM. */
+ /* Memory management of this pointer is done */
+ /* internally by FreeType. */
/* */
/* namedstyle :: A named style table. */
/* Only meaningful with GX. */
+ /* Memory management of this pointer is done */
+ /* internally by FreeType. */
/* */
typedef struct FT_MM_Var_
{
@@ -255,7 +259,8 @@ FT_BEGIN_HEADER
/* */
/* <Output> */
/* amaster :: The Multiple Masters/GX var descriptor. */
- /* Allocates a data structure, which the user must free. */
+ /* Allocates a data structure, which the user must */
+ /* deallocate with `free' after use. */
/* */
/* <Return> */
/* FreeType error code. 0~means success. */
diff --git a/include/ftmodapi.h b/include/freetype/ftmodapi.h
index 2ef3f46..89d9347 100644
--- a/include/ftmodapi.h
+++ b/include/freetype/ftmodapi.h
@@ -63,7 +63,7 @@ FT_BEGIN_HEADER
/* psaux */
/* pshinter */
/* psnames */
- /* raster1, raster5 */
+ /* raster1 */
/* sfnt */
/* smooth, smooth-lcd, smooth-lcdv */
/* truetype */
@@ -111,12 +111,14 @@ FT_BEGIN_HEADER
#define FT_MODULE_HINTER 4 /* this module is a glyph hinter */
#define FT_MODULE_STYLER 8 /* this module is a styler */
-#define FT_MODULE_DRIVER_SCALABLE 0x100 /* the driver supports */
+#define FT_MODULE_DRIVER_SCALABLE 0x100 /* the driver supports */
/* scalable fonts */
-#define FT_MODULE_DRIVER_NO_OUTLINES 0x200 /* the driver does not */
+#define FT_MODULE_DRIVER_NO_OUTLINES 0x200 /* the driver does not */
/* support vector outlines */
-#define FT_MODULE_DRIVER_HAS_HINTER 0x400 /* the driver provides its */
+#define FT_MODULE_DRIVER_HAS_HINTER 0x400 /* the driver provides its */
/* own hinter */
+#define FT_MODULE_DRIVER_HINTS_LIGHTLY 0x800 /* the driver's hinter */
+ /* produces LIGHT hints */
/* deprecated values */
@@ -125,9 +127,10 @@ FT_BEGIN_HEADER
#define ft_module_hinter FT_MODULE_HINTER
#define ft_module_styler FT_MODULE_STYLER
-#define ft_module_driver_scalable FT_MODULE_DRIVER_SCALABLE
-#define ft_module_driver_no_outlines FT_MODULE_DRIVER_NO_OUTLINES
-#define ft_module_driver_has_hinter FT_MODULE_DRIVER_HAS_HINTER
+#define ft_module_driver_scalable FT_MODULE_DRIVER_SCALABLE
+#define ft_module_driver_no_outlines FT_MODULE_DRIVER_NO_OUTLINES
+#define ft_module_driver_has_hinter FT_MODULE_DRIVER_HAS_HINTER
+#define ft_module_driver_hints_lightly FT_MODULE_DRIVER_HINTS_LIGHTLY
typedef FT_Pointer FT_Module_Interface;
diff --git a/include/ftmoderr.h b/include/freetype/ftmoderr.h
index 9d7f981..9d7f981 100644
--- a/include/ftmoderr.h
+++ b/include/freetype/ftmoderr.h
diff --git a/include/ftotval.h b/include/freetype/ftotval.h
index e744b71..e744b71 100644
--- a/include/ftotval.h
+++ b/include/freetype/ftotval.h
diff --git a/include/ftoutln.h b/include/freetype/ftoutln.h
index 106cfde..b6ec70d 100644
--- a/include/ftoutln.h
+++ b/include/freetype/ftoutln.h
@@ -354,8 +354,8 @@ FT_BEGIN_HEADER
/* */
/* { */
/* FT_Load_Glyph( face, index, FT_LOAD_DEFAULT ); */
- /* if ( face->slot->format == FT_GLYPH_FORMAT_OUTLINE ) */
- /* FT_Outline_Embolden( &face->slot->outline, strength ); */
+ /* if ( face->glyph->format == FT_GLYPH_FORMAT_OUTLINE ) */
+ /* FT_Outline_Embolden( &face->glyph->outline, strength ); */
/* } */
/* */
/* To get meaningful results, font scaling values must be set with */
diff --git a/include/ftpfr.h b/include/freetype/ftpfr.h
index a1c02a2..a1c02a2 100644
--- a/include/ftpfr.h
+++ b/include/freetype/ftpfr.h
diff --git a/include/ftrender.h b/include/freetype/ftrender.h
index ec8da70..ec8da70 100644
--- a/include/ftrender.h
+++ b/include/freetype/ftrender.h
diff --git a/include/ftsizes.h b/include/freetype/ftsizes.h
index bef8424..bef8424 100644
--- a/include/ftsizes.h
+++ b/include/freetype/ftsizes.h
diff --git a/include/ftsnames.h b/include/freetype/ftsnames.h
index 0f7fbe1..0f7fbe1 100644
--- a/include/ftsnames.h
+++ b/include/freetype/ftsnames.h
diff --git a/include/ftstroke.h b/include/freetype/ftstroke.h
index 7ebb1e7..7ebb1e7 100644
--- a/include/ftstroke.h
+++ b/include/freetype/ftstroke.h
diff --git a/include/ftsynth.h b/include/freetype/ftsynth.h
index fbcbad8..fbcbad8 100644
--- a/include/ftsynth.h
+++ b/include/freetype/ftsynth.h
diff --git a/include/ftsystem.h b/include/freetype/ftsystem.h
index 2bc9999..2bc9999 100644
--- a/include/ftsystem.h
+++ b/include/freetype/ftsystem.h
diff --git a/include/fttrigon.h b/include/freetype/fttrigon.h
index 3d821ba..485ec51 100644
--- a/include/fttrigon.h
+++ b/include/freetype/fttrigon.h
@@ -225,8 +225,8 @@ FT_BEGIN_HEADER
*
* @description:
* Return the unit vector corresponding to a given angle. After the
- * call, the value of `vec.x' will be `sin(angle)', and the value of
- * `vec.y' will be `cos(angle)'.
+ * call, the value of `vec.x' will be `cos(angle)', and the value of
+ * `vec.y' will be `sin(angle)'.
*
* This function is useful to retrieve both the sinus and cosinus of a
* given angle quickly.
diff --git a/include/ftttdrv.h b/include/freetype/ftttdrv.h
index f56040b..dc0081a 100644
--- a/include/ftttdrv.h
+++ b/include/freetype/ftttdrv.h
@@ -52,6 +52,83 @@ FT_BEGIN_HEADER
*
* The TrueType driver's module name is `truetype'.
*
+ * We start with a list of definitions, kindly provided by Greg
+ * Hitchcock.
+ *
+ * _Bi-Level_ _Rendering_
+ *
+ * Monochromatic rendering, exclusively used in the early days of
+ * TrueType by both Apple and Microsoft. Microsoft's GDI interface
+ * supported hinting of the right-side bearing point, such that the
+ * advance width could be non-linear. Most often this was done to
+ * achieve some level of glyph symmetry. To enable reasonable
+ * performance (e.g., not having to run hinting on all glyphs just to
+ * get the widths) there was a bit in the head table indicating if the
+ * side bearing was hinted, and additional tables, `hdmx' and `LTSH', to
+ * cache hinting widths across multiple sizes and device aspect ratios.
+ *
+ * _Font_ _Smoothing_
+ *
+ * Microsoft's GDI implementation of anti-aliasing. Not traditional
+ * anti-aliasing as the outlines were hinted before the sampling. The
+ * widths matched the bi-level rendering.
+ *
+ * _ClearType_ _Rendering_
+ *
+ * Technique that uses physical subpixels to improve rendering on LCD
+ * (and other) displays. Because of the higher resolution, many methods
+ * of improving symmetry in glyphs through hinting the right-side
+ * bearing were no longer necessary. This lead to what GDI calls
+ * `natural widths' ClearType, see
+ * http://www.beatstamm.com/typography/RTRCh4.htm#Sec21. Since hinting
+ * has extra resolution, most non-linearity went away, but it is still
+ * possible for hints to change the advance widths in this mode.
+ *
+ * _ClearType_ _Compatible_ _Widths_
+ *
+ * One of the earliest challenges with ClearType was allowing the
+ * implementation in GDI to be selected without requiring all UI and
+ * documents to reflow. To address this, a compatible method of
+ * rendering ClearType was added where the font hints are executed once
+ * to determine the width in bi-level rendering, and then re-run in
+ * ClearType, with the difference in widths being absorbed in the font
+ * hints for ClearType (mostly in the white space of hints); see
+ * http://www.beatstamm.com/typography/RTRCh4.htm#Sec20. Somewhat by
+ * definition, compatible width ClearType allows for non-linear widths,
+ * but only when the bi-level version has non-linear widths.
+ *
+ * _ClearType_ _Subpixel_ _Positioning_
+ *
+ * One of the nice benefits of ClearType is the ability to more crisply
+ * display fractional widths; unfortunately, the GDI model of integer
+ * bitmaps did not support this. However, the WPF and Direct Write
+ * frameworks do support fractional widths. DWrite calls this `natural
+ * mode', not to be confused with GDI's `natural widths'. Subpixel
+ * positioning, in the current implementation of Direct Write,
+ * unfortunately does not support hinted advance widths, see
+ * http://www.beatstamm.com/typography/RTRCh4.htm#Sec22. Note that the
+ * TrueType interpreter fully allows the advance width to be adjusted in
+ * this mode, just the DWrite client will ignore those changes.
+ *
+ * _ClearType_ _Backwards_ _Compatibility_
+ *
+ * This is a set of exceptions made in the TrueType interpreter to
+ * minimize hinting techniques that were problematic with the extra
+ * resolution of ClearType; see
+ * http://www.beatstamm.com/typography/RTRCh4.htm#Sec1 and
+ * http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx.
+ * This technique is not to be confused with ClearType compatible
+ * widths. ClearType backwards compatibility has no direct impact on
+ * changing advance widths, but there might be an indirect impact on
+ * disabling some deltas. This could be worked around in backwards
+ * compatibility mode.
+ *
+ * _Native_ _ClearType_ _Mode_
+ *
+ * (Not to be confused with `natural widths'.) This mode removes all
+ * the exceptions in the TrueType interpreter when running with
+ * ClearType. Any issues on widths would still apply, though.
+ *
*/
diff --git a/include/fttypes.h b/include/freetype/fttypes.h
index 706a1be..706a1be 100644
--- a/include/fttypes.h
+++ b/include/freetype/fttypes.h
diff --git a/include/ftwinfnt.h b/include/freetype/ftwinfnt.h
index caedaa1..caedaa1 100644
--- a/include/ftwinfnt.h
+++ b/include/freetype/ftwinfnt.h
diff --git a/include/internal/autohint.h b/include/freetype/internal/autohint.h
index 8d5a977..8d5a977 100644
--- a/include/internal/autohint.h
+++ b/include/freetype/internal/autohint.h
diff --git a/include/internal/ftcalc.h b/include/freetype/internal/ftcalc.h
index 75752c3..a76682b 100644
--- a/include/internal/ftcalc.h
+++ b/include/freetype/internal/ftcalc.h
@@ -47,7 +47,7 @@ FT_BEGIN_HEADER
FT_MulFix_arm( FT_Int32 a,
FT_Int32 b )
{
- register FT_Int32 t, t2;
+ FT_Int32 t, t2;
__asm
@@ -80,7 +80,7 @@ FT_BEGIN_HEADER
FT_MulFix_arm( FT_Int32 a,
FT_Int32 b )
{
- register FT_Int32 t, t2;
+ FT_Int32 t, t2;
__asm__ __volatile__ (
@@ -116,7 +116,7 @@ FT_BEGIN_HEADER
FT_MulFix_i386( FT_Int32 a,
FT_Int32 b )
{
- register FT_Int32 result;
+ FT_Int32 result;
__asm__ __volatile__ (
@@ -152,7 +152,7 @@ FT_BEGIN_HEADER
FT_MulFix_i386( FT_Int32 a,
FT_Int32 b )
{
- register FT_Int32 result;
+ FT_Int32 result;
__asm
{
@@ -300,6 +300,18 @@ FT_BEGIN_HEADER
/*
+ * This function normalizes a vector and returns its original length.
+ * The normalized vector is a 16.16 fixed-point unit vector with length
+ * close to 0x10000. The accuracy of the returned length is limited to
+ * 16 bits also. The function utilizes quick inverse square root
+ * approximation without divisions and square roots relying on Newton's
+ * iterations instead.
+ */
+ FT_BASE( FT_UInt32 )
+ FT_Vector_NormLen( FT_Vector* vector );
+
+
+ /*
* Return -1, 0, or +1, depending on the orientation of a given corner.
* We use the Cartesian coordinate system, with positive vertical values
* going upwards. The function returns +1 if the corner turns to the
diff --git a/include/internal/ftdebug.h b/include/freetype/internal/ftdebug.h
index 216c730..216c730 100644
--- a/include/internal/ftdebug.h
+++ b/include/freetype/internal/ftdebug.h
diff --git a/include/internal/ftdriver.h b/include/freetype/internal/ftdriver.h
index 16856d3..16856d3 100644
--- a/include/internal/ftdriver.h
+++ b/include/freetype/internal/ftdriver.h
diff --git a/include/internal/ftgloadr.h b/include/freetype/internal/ftgloadr.h
index 970dd70..970dd70 100644
--- a/include/internal/ftgloadr.h
+++ b/include/freetype/internal/ftgloadr.h
diff --git a/include/internal/ftmemory.h b/include/freetype/internal/ftmemory.h
index c0c553b..c0c553b 100644
--- a/include/internal/ftmemory.h
+++ b/include/freetype/internal/ftmemory.h
diff --git a/include/internal/ftobjs.h b/include/freetype/internal/ftobjs.h
index 37317a4..9a333fc 100644
--- a/include/internal/ftobjs.h
+++ b/include/freetype/internal/ftobjs.h
@@ -83,12 +83,12 @@ FT_BEGIN_HEADER
x > y ? x + ( 3 * y >> 3 ) \
: y + ( 3 * x >> 3 ) )
- /* we use the TYPEOF macro to suppress signedness compilation warnings */
-#define FT_PAD_FLOOR( x, n ) ( (x) & ~TYPEOF( x )( (n)-1 ) )
+ /* we use FT_TYPEOF to suppress signedness compilation warnings */
+#define FT_PAD_FLOOR( x, n ) ( (x) & ~FT_TYPEOF( x )( (n)-1 ) )
#define FT_PAD_ROUND( x, n ) FT_PAD_FLOOR( (x) + ((n)/2), n )
#define FT_PAD_CEIL( x, n ) FT_PAD_FLOOR( (x) + ((n)-1), n )
-#define FT_PIX_FLOOR( x ) ( (x) & ~TYPEOF( x )63 )
+#define FT_PIX_FLOOR( x ) ( (x) & ~FT_TYPEOF( x )63 )
#define FT_PIX_ROUND( x ) FT_PIX_FLOOR( (x) + 32 )
#define FT_PIX_CEIL( x ) FT_PIX_FLOOR( (x) + 63 )
@@ -506,6 +506,9 @@ FT_BEGIN_HEADER
#define FT_DRIVER_HAS_HINTER( x ) ( FT_MODULE_CLASS( x )->module_flags & \
FT_MODULE_DRIVER_HAS_HINTER )
+#define FT_DRIVER_HINTS_LIGHTLY( x ) ( FT_MODULE_CLASS( x )->module_flags & \
+ FT_MODULE_DRIVER_HINTS_LIGHTLY )
+
/*************************************************************************/
/* */
diff --git a/include/internal/ftpic.h b/include/freetype/internal/ftpic.h
index 7f9154f..7f9154f 100644
--- a/include/internal/ftpic.h
+++ b/include/freetype/internal/ftpic.h
diff --git a/include/internal/ftrfork.h b/include/freetype/internal/ftrfork.h
index da61ca7..da61ca7 100644
--- a/include/internal/ftrfork.h
+++ b/include/freetype/internal/ftrfork.h
diff --git a/include/internal/ftserv.h b/include/freetype/internal/ftserv.h
index 8f837e4..11a0c7f 100644
--- a/include/internal/ftserv.h
+++ b/include/freetype/internal/ftserv.h
@@ -734,24 +734,24 @@ FT_BEGIN_HEADER
* The header files containing the services.
*/
-#define FT_SERVICE_BDF_H <internal/services/svbdf.h>
-#define FT_SERVICE_CID_H <internal/services/svcid.h>
-#define FT_SERVICE_GLYPH_DICT_H <internal/services/svgldict.h>
-#define FT_SERVICE_GX_VALIDATE_H <internal/services/svgxval.h>
-#define FT_SERVICE_KERNING_H <internal/services/svkern.h>
-#define FT_SERVICE_MULTIPLE_MASTERS_H <internal/services/svmm.h>
-#define FT_SERVICE_OPENTYPE_VALIDATE_H <internal/services/svotval.h>
-#define FT_SERVICE_PFR_H <internal/services/svpfr.h>
-#define FT_SERVICE_POSTSCRIPT_CMAPS_H <internal/services/svpscmap.h>
-#define FT_SERVICE_POSTSCRIPT_INFO_H <internal/services/svpsinfo.h>
-#define FT_SERVICE_POSTSCRIPT_NAME_H <internal/services/svpostnm.h>
-#define FT_SERVICE_PROPERTIES_H <internal/services/svprop.h>
-#define FT_SERVICE_SFNT_H <internal/services/svsfnt.h>
-#define FT_SERVICE_TRUETYPE_ENGINE_H <internal/services/svtteng.h>
-#define FT_SERVICE_TT_CMAP_H <internal/services/svttcmap.h>
-#define FT_SERVICE_WINFNT_H <internal/services/svwinfnt.h>
-#define FT_SERVICE_FONT_FORMAT_H <internal/services/svfntfmt.h>
-#define FT_SERVICE_TRUETYPE_GLYF_H <internal/services/svttglyf.h>
+#define FT_SERVICE_BDF_H <freetype/internal/services/svbdf.h>
+#define FT_SERVICE_CID_H <freetype/internal/services/svcid.h>
+#define FT_SERVICE_GLYPH_DICT_H <freetype/internal/services/svgldict.h>
+#define FT_SERVICE_GX_VALIDATE_H <freetype/internal/services/svgxval.h>
+#define FT_SERVICE_KERNING_H <freetype/internal/services/svkern.h>
+#define FT_SERVICE_MULTIPLE_MASTERS_H <freetype/internal/services/svmm.h>
+#define FT_SERVICE_OPENTYPE_VALIDATE_H <freetype/internal/services/svotval.h>
+#define FT_SERVICE_PFR_H <freetype/internal/services/svpfr.h>
+#define FT_SERVICE_POSTSCRIPT_CMAPS_H <freetype/internal/services/svpscmap.h>
+#define FT_SERVICE_POSTSCRIPT_INFO_H <freetype/internal/services/svpsinfo.h>
+#define FT_SERVICE_POSTSCRIPT_NAME_H <freetype/internal/services/svpostnm.h>
+#define FT_SERVICE_PROPERTIES_H <freetype/internal/services/svprop.h>
+#define FT_SERVICE_SFNT_H <freetype/internal/services/svsfnt.h>
+#define FT_SERVICE_TRUETYPE_ENGINE_H <freetype/internal/services/svtteng.h>
+#define FT_SERVICE_TT_CMAP_H <freetype/internal/services/svttcmap.h>
+#define FT_SERVICE_WINFNT_H <freetype/internal/services/svwinfnt.h>
+#define FT_SERVICE_FONT_FORMAT_H <freetype/internal/services/svfntfmt.h>
+#define FT_SERVICE_TRUETYPE_GLYF_H <freetype/internal/services/svttglyf.h>
/* */
diff --git a/include/internal/ftstream.h b/include/freetype/internal/ftstream.h
index 384e5df..384e5df 100644
--- a/include/internal/ftstream.h
+++ b/include/freetype/internal/ftstream.h
diff --git a/include/internal/fttrace.h b/include/freetype/internal/fttrace.h
index 9d28d21..2b0bf9d 100644
--- a/include/internal/fttrace.h
+++ b/include/freetype/internal/fttrace.h
@@ -148,7 +148,7 @@ FT_TRACE_DEF( afcjk )
FT_TRACE_DEF( aflatin )
FT_TRACE_DEF( aflatin2 )
FT_TRACE_DEF( afwarp )
-FT_TRACE_DEF( afharfbuzz )
+FT_TRACE_DEF( afshaper )
FT_TRACE_DEF( afglobal )
/* END */
diff --git a/include/internal/ftvalid.h b/include/freetype/internal/ftvalid.h
index 9cda6ee..9cda6ee 100644
--- a/include/internal/ftvalid.h
+++ b/include/freetype/internal/ftvalid.h
diff --git a/include/internal/internal.h b/include/freetype/internal/internal.h
index 1c1fd0e..809ce59 100644
--- a/include/internal/internal.h
+++ b/include/freetype/internal/internal.h
@@ -24,28 +24,28 @@
/*************************************************************************/
-#define FT_INTERNAL_OBJECTS_H <internal/ftobjs.h>
-#define FT_INTERNAL_PIC_H <internal/ftpic.h>
-#define FT_INTERNAL_STREAM_H <internal/ftstream.h>
-#define FT_INTERNAL_MEMORY_H <internal/ftmemory.h>
-#define FT_INTERNAL_DEBUG_H <internal/ftdebug.h>
-#define FT_INTERNAL_CALC_H <internal/ftcalc.h>
-#define FT_INTERNAL_DRIVER_H <internal/ftdriver.h>
-#define FT_INTERNAL_TRACE_H <internal/fttrace.h>
-#define FT_INTERNAL_GLYPH_LOADER_H <internal/ftgloadr.h>
-#define FT_INTERNAL_SFNT_H <internal/sfnt.h>
-#define FT_INTERNAL_SERVICE_H <internal/ftserv.h>
-#define FT_INTERNAL_RFORK_H <internal/ftrfork.h>
-#define FT_INTERNAL_VALIDATE_H <internal/ftvalid.h>
-
-#define FT_INTERNAL_TRUETYPE_TYPES_H <internal/tttypes.h>
-#define FT_INTERNAL_TYPE1_TYPES_H <internal/t1types.h>
-
-#define FT_INTERNAL_POSTSCRIPT_AUX_H <internal/psaux.h>
-#define FT_INTERNAL_POSTSCRIPT_HINTS_H <internal/pshints.h>
-#define FT_INTERNAL_POSTSCRIPT_GLOBALS_H <internal/psglobal.h>
-
-#define FT_INTERNAL_AUTOHINT_H <internal/autohint.h>
+#define FT_INTERNAL_OBJECTS_H <freetype/internal/ftobjs.h>
+#define FT_INTERNAL_PIC_H <freetype/internal/ftpic.h>
+#define FT_INTERNAL_STREAM_H <freetype/internal/ftstream.h>
+#define FT_INTERNAL_MEMORY_H <freetype/internal/ftmemory.h>
+#define FT_INTERNAL_DEBUG_H <freetype/internal/ftdebug.h>
+#define FT_INTERNAL_CALC_H <freetype/internal/ftcalc.h>
+#define FT_INTERNAL_DRIVER_H <freetype/internal/ftdriver.h>
+#define FT_INTERNAL_TRACE_H <freetype/internal/fttrace.h>
+#define FT_INTERNAL_GLYPH_LOADER_H <freetype/internal/ftgloadr.h>
+#define FT_INTERNAL_SFNT_H <freetype/internal/sfnt.h>
+#define FT_INTERNAL_SERVICE_H <freetype/internal/ftserv.h>
+#define FT_INTERNAL_RFORK_H <freetype/internal/ftrfork.h>
+#define FT_INTERNAL_VALIDATE_H <freetype/internal/ftvalid.h>
+
+#define FT_INTERNAL_TRUETYPE_TYPES_H <freetype/internal/tttypes.h>
+#define FT_INTERNAL_TYPE1_TYPES_H <freetype/internal/t1types.h>
+
+#define FT_INTERNAL_POSTSCRIPT_AUX_H <freetype/internal/psaux.h>
+#define FT_INTERNAL_POSTSCRIPT_HINTS_H <freetype/internal/pshints.h>
+#define FT_INTERNAL_POSTSCRIPT_GLOBALS_H <freetype/internal/psglobal.h>
+
+#define FT_INTERNAL_AUTOHINT_H <freetype/internal/autohint.h>
#if defined( _MSC_VER ) /* Visual C++ (and Intel C++) */
diff --git a/include/internal/psaux.h b/include/freetype/internal/psaux.h
index 1c5f784..1c5f784 100644
--- a/include/internal/psaux.h
+++ b/include/freetype/internal/psaux.h
diff --git a/include/internal/pshints.h b/include/freetype/internal/pshints.h
index 12aaaba..12aaaba 100644
--- a/include/internal/pshints.h
+++ b/include/freetype/internal/pshints.h
diff --git a/include/internal/services/svbdf.h b/include/freetype/internal/services/svbdf.h
index 865b536..865b536 100644
--- a/include/internal/services/svbdf.h
+++ b/include/freetype/internal/services/svbdf.h
diff --git a/include/internal/services/svcid.h b/include/freetype/internal/services/svcid.h
index 4a535a6..4a535a6 100644
--- a/include/internal/services/svcid.h
+++ b/include/freetype/internal/services/svcid.h
diff --git a/include/internal/services/svfntfmt.h b/include/freetype/internal/services/svfntfmt.h
index f8b3617..f8b3617 100644
--- a/include/internal/services/svfntfmt.h
+++ b/include/freetype/internal/services/svfntfmt.h
diff --git a/include/internal/services/svgldict.h b/include/freetype/internal/services/svgldict.h
index f78bca5..f78bca5 100644
--- a/include/internal/services/svgldict.h
+++ b/include/freetype/internal/services/svgldict.h
diff --git a/include/internal/services/svgxval.h b/include/freetype/internal/services/svgxval.h
index 59cc3b7..59cc3b7 100644
--- a/include/internal/services/svgxval.h
+++ b/include/freetype/internal/services/svgxval.h
diff --git a/include/internal/services/svkern.h b/include/freetype/internal/services/svkern.h
index bc26f15..bc26f15 100644
--- a/include/internal/services/svkern.h
+++ b/include/freetype/internal/services/svkern.h
diff --git a/include/internal/services/svmm.h b/include/freetype/internal/services/svmm.h
index f2cecfb..f2cecfb 100644
--- a/include/internal/services/svmm.h
+++ b/include/freetype/internal/services/svmm.h
diff --git a/include/internal/services/svotval.h b/include/freetype/internal/services/svotval.h
index a82a642..a82a642 100644
--- a/include/internal/services/svotval.h
+++ b/include/freetype/internal/services/svotval.h
diff --git a/include/internal/services/svpfr.h b/include/freetype/internal/services/svpfr.h
index d4eb169..d4eb169 100644
--- a/include/internal/services/svpfr.h
+++ b/include/freetype/internal/services/svpfr.h
diff --git a/include/internal/services/svpostnm.h b/include/freetype/internal/services/svpostnm.h
index a89f79e..a89f79e 100644
--- a/include/internal/services/svpostnm.h
+++ b/include/freetype/internal/services/svpostnm.h
diff --git a/include/internal/services/svprop.h b/include/freetype/internal/services/svprop.h
index c9f07ce..c9f07ce 100644
--- a/include/internal/services/svprop.h
+++ b/include/freetype/internal/services/svprop.h
diff --git a/include/internal/services/svpscmap.h b/include/freetype/internal/services/svpscmap.h
index 66da6e1..66da6e1 100644
--- a/include/internal/services/svpscmap.h
+++ b/include/freetype/internal/services/svpscmap.h
diff --git a/include/internal/services/svpsinfo.h b/include/freetype/internal/services/svpsinfo.h
index 752a266..752a266 100644
--- a/include/internal/services/svpsinfo.h
+++ b/include/freetype/internal/services/svpsinfo.h
diff --git a/include/internal/services/svsfnt.h b/include/freetype/internal/services/svsfnt.h
index 252ae1c..252ae1c 100644
--- a/include/internal/services/svsfnt.h
+++ b/include/freetype/internal/services/svsfnt.h
diff --git a/include/internal/services/svttcmap.h b/include/freetype/internal/services/svttcmap.h
index 4351a9a..cd95b9a 100644
--- a/include/internal/services/svttcmap.h
+++ b/include/freetype/internal/services/svttcmap.h
@@ -48,11 +48,12 @@ FT_BEGIN_HEADER
/* `ttnameid.h'. */
/* */
/* format :: */
- /* The cmap format. OpenType 1.5 defines the formats 0 (byte */
+ /* The cmap format. OpenType 1.6 defines the formats 0 (byte */
/* encoding table), 2~(high-byte mapping through table), 4~(segment */
/* mapping to delta values), 6~(trimmed table mapping), 8~(mixed */
/* 16-bit and 32-bit coverage), 10~(trimmed array), 12~(segmented */
- /* coverage), and 14 (Unicode Variation Sequences). */
+ /* coverage), 13~(last resort font), and 14 (Unicode Variation */
+ /* Sequences). */
/* */
typedef struct TT_CMapInfo_
{
diff --git a/include/internal/services/svtteng.h b/include/freetype/internal/services/svtteng.h
index 272ee8c..272ee8c 100644
--- a/include/internal/services/svtteng.h
+++ b/include/freetype/internal/services/svtteng.h
diff --git a/include/internal/services/svttglyf.h b/include/freetype/internal/services/svttglyf.h
index f5cb76a..f5cb76a 100644
--- a/include/internal/services/svttglyf.h
+++ b/include/freetype/internal/services/svttglyf.h
diff --git a/include/internal/services/svwinfnt.h b/include/freetype/internal/services/svwinfnt.h
index 0036929..0036929 100644
--- a/include/internal/services/svwinfnt.h
+++ b/include/freetype/internal/services/svwinfnt.h
diff --git a/include/internal/sfnt.h b/include/freetype/internal/sfnt.h
index 97ce390..30f53bf 100644
--- a/include/internal/sfnt.h
+++ b/include/freetype/internal/sfnt.h
@@ -44,7 +44,9 @@ FT_BEGIN_HEADER
/* face :: A handle to the target face object. */
/* */
/* face_index :: The index of the TrueType font, if we are opening a */
- /* collection. */
+ /* collection, in bits 0-15. The numbered instance */
+ /* index~+~1 of a GX (sub)font, if applicable, in bits */
+ /* 16-30. */
/* */
/* num_params :: The number of additional parameters. */
/* */
@@ -87,7 +89,9 @@ FT_BEGIN_HEADER
/* face :: A handle to the target face object. */
/* */
/* face_index :: The index of the TrueType font, if we are opening a */
- /* collection. */
+ /* collection, in bits 0-15. The numbered instance */
+ /* index~+~1 of a GX (sub)font, if applicable, in bits */
+ /* 16-30. */
/* */
/* num_params :: The number of additional parameters. */
/* */
@@ -427,6 +431,33 @@ FT_BEGIN_HEADER
/*************************************************************************/
/* */
/* <FuncType> */
+ /* TT_Get_Name_Func */
+ /* */
+ /* <Description> */
+ /* From the `name' table, return a given ENGLISH name record in */
+ /* ASCII. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* nameid :: The name id of the name record to return. */
+ /* */
+ /* <InOut> */
+ /* name :: The address of an allocated string pointer. NULL if */
+ /* no name is present. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ typedef FT_Error
+ (*TT_Get_Name_Func)( TT_Face face,
+ FT_UShort nameid,
+ FT_String** name );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
/* TT_Load_Table_Func */
/* */
/* <Description> */
@@ -556,6 +587,8 @@ FT_BEGIN_HEADER
TT_Get_Metrics_Func get_metrics;
+ TT_Get_Name_Func get_name;
+
} SFNT_Interface;
@@ -594,7 +627,8 @@ FT_BEGIN_HEADER
free_eblc_, \
set_sbit_strike_, \
load_strike_metrics_, \
- get_metrics_ ) \
+ get_metrics_, \
+ get_name_ ) \
static const SFNT_Interface class_ = \
{ \
goto_table_, \
@@ -626,6 +660,7 @@ FT_BEGIN_HEADER
set_sbit_strike_, \
load_strike_metrics_, \
get_metrics_, \
+ get_name_, \
};
#else /* FT_CONFIG_OPTION_PIC */
@@ -663,7 +698,8 @@ FT_BEGIN_HEADER
free_eblc_, \
set_sbit_strike_, \
load_strike_metrics_, \
- get_metrics_ ) \
+ get_metrics_, \
+ get_name_ ) \
void \
FT_Init_Class_ ## class_( FT_Library library, \
SFNT_Interface* clazz ) \
@@ -699,6 +735,7 @@ FT_BEGIN_HEADER
clazz->set_sbit_strike = set_sbit_strike_; \
clazz->load_strike_metrics = load_strike_metrics_; \
clazz->get_metrics = get_metrics_; \
+ clazz->get_name = get_name_; \
}
#endif /* FT_CONFIG_OPTION_PIC */
diff --git a/include/internal/t1types.h b/include/freetype/internal/t1types.h
index 029acc4..029acc4 100644
--- a/include/internal/t1types.h
+++ b/include/freetype/internal/t1types.h
diff --git a/include/internal/tttypes.h b/include/freetype/internal/tttypes.h
index 31dd0aa..000c5a8 100644
--- a/include/internal/tttypes.h
+++ b/include/freetype/internal/tttypes.h
@@ -1457,11 +1457,23 @@ FT_BEGIN_HEADER
/* handle to execution context */
typedef struct TT_ExecContextRec_* TT_ExecContext;
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* TT_Size */
+ /* */
+ /* <Description> */
+ /* A handle to a TrueType size object. */
+ /* */
+ typedef struct TT_SizeRec_* TT_Size;
+
+
/* glyph loader structure */
typedef struct TT_LoaderRec_
{
- FT_Face face;
- FT_Size size;
+ TT_Face face;
+ TT_Size size;
FT_GlyphSlot glyph;
FT_GlyphLoader gloader;
@@ -1503,6 +1515,9 @@ FT_BEGIN_HEADER
FT_Byte* cursor;
FT_Byte* limit;
+ /* since version 2.6.2 */
+ FT_ListRec composites;
+
} TT_LoaderRec;
diff --git a/include/t1tables.h b/include/freetype/t1tables.h
index a6ea415..a6ea415 100644
--- a/include/t1tables.h
+++ b/include/freetype/t1tables.h
diff --git a/include/ttnameid.h b/include/freetype/ttnameid.h
index c9585f2..c9585f2 100644
--- a/include/ttnameid.h
+++ b/include/freetype/ttnameid.h
diff --git a/include/tttables.h b/include/freetype/tttables.h
index 1568f40..1568f40 100644
--- a/include/tttables.h
+++ b/include/freetype/tttables.h
diff --git a/include/tttags.h b/include/freetype/tttags.h
index 3836c7b..3836c7b 100644
--- a/include/tttags.h
+++ b/include/freetype/tttags.h
diff --git a/include/ttunpat.h b/include/freetype/ttunpat.h
index 8ea5568..8ea5568 100644
--- a/include/ttunpat.h
+++ b/include/freetype/ttunpat.h
diff --git a/include/ft2build.h b/include/ft2build.h
index 09c19d4..419b80a 100644
--- a/include/ft2build.h
+++ b/include/ft2build.h
@@ -34,7 +34,7 @@
#ifndef __FT2BUILD_H__
#define __FT2BUILD_H__
-#include <config/ftheader.h>
+#include <freetype/config/ftheader.h>
#endif /* __FT2BUILD_H__ */
diff --git a/module_option.diff b/module_option.diff
new file mode 100644
index 0000000..75079ce
--- /dev/null
+++ b/module_option.diff
@@ -0,0 +1,57 @@
+diff --git a/include/freetype/config/ftmodule.h b/include/freetype/config/ftmodule.h
+index 76d271a..e145790 100644
+--- a/include/freetype/config/ftmodule.h
++++ b/include/freetype/config/ftmodule.h
+@@ -12,14 +12,7 @@
+
+ FT_USE_MODULE( FT_Module_Class, autofit_module_class )
+ FT_USE_MODULE( FT_Driver_ClassRec, tt_driver_class )
+-FT_USE_MODULE( FT_Driver_ClassRec, t1_driver_class )
+ FT_USE_MODULE( FT_Driver_ClassRec, cff_driver_class )
+-FT_USE_MODULE( FT_Driver_ClassRec, t1cid_driver_class )
+-FT_USE_MODULE( FT_Driver_ClassRec, pfr_driver_class )
+-FT_USE_MODULE( FT_Driver_ClassRec, t42_driver_class )
+-FT_USE_MODULE( FT_Driver_ClassRec, winfnt_driver_class )
+-FT_USE_MODULE( FT_Driver_ClassRec, pcf_driver_class )
+-FT_USE_MODULE( FT_Module_Class, psaux_module_class )
+ FT_USE_MODULE( FT_Module_Class, psnames_module_class )
+ FT_USE_MODULE( FT_Module_Class, pshinter_module_class )
+ FT_USE_MODULE( FT_Renderer_Class, ft_raster1_renderer_class )
+@@ -27,6 +20,5 @@ FT_USE_MODULE( FT_Module_Class, sfnt_module_class )
+ FT_USE_MODULE( FT_Renderer_Class, ft_smooth_renderer_class )
+ FT_USE_MODULE( FT_Renderer_Class, ft_smooth_lcd_renderer_class )
+ FT_USE_MODULE( FT_Renderer_Class, ft_smooth_lcdv_renderer_class )
+-FT_USE_MODULE( FT_Driver_ClassRec, bdf_driver_class )
+
+ /* EOF */
+diff --git a/include/freetype/config/ftoption.h b/include/freetype/config/ftoption.h
+index b481f8f..3819586 100644
+--- a/include/freetype/config/ftoption.h
++++ b/include/freetype/config/ftoption.h
+@@ -225,7 +225,7 @@ FT_BEGIN_HEADER
+ /* */
+ /* Define this macro if you want to enable this `feature'. */
+ /* */
+-/* #define FT_CONFIG_OPTION_USE_PNG */
++#define FT_CONFIG_OPTION_USE_PNG
+
+
+ /*************************************************************************/
+@@ -370,7 +370,7 @@ FT_BEGIN_HEADER
+ /* supply font data incrementally as the document is parsed, such */
+ /* as the Ghostscript interpreter for the PostScript language. */
+ /* */
+-#define FT_CONFIG_OPTION_INCREMENTAL
++/* #define FT_CONFIG_OPTION_INCREMENTAL */
+
+
+ /*************************************************************************/
+@@ -843,7 +843,7 @@ FT_BEGIN_HEADER
+ /* `warping' property of the auto-hinter (see file `ftautoh.h' for more */
+ /* information; by default it is switched off). */
+ /* */
+-#define AF_CONFIG_OPTION_USE_WARPER
++/* #define AF_CONFIG_OPTION_USE_WARPER */
+
+ /* */
+
diff --git a/src/autofit/afblue.c b/src/autofit/afblue.c
index e2b2451..104ee17 100644
--- a/src/autofit/afblue.c
+++ b/src/autofit/afblue.c
@@ -26,107 +26,161 @@
af_blue_strings[] =
{
/* */
- '\xD8', '\xA7', '\xD8', '\xA5', '\xD9', '\x84', '\xD9', '\x83', '\xD8', '\xB7', '\xD8', '\xB8', /* ا إ ل ك ط ظ */
+ '\xD8', '\xA7', ' ', '\xD8', '\xA5', ' ', '\xD9', '\x84', ' ', '\xD9', '\x83', ' ', '\xD8', '\xB7', ' ', '\xD8', '\xB8', /* ا إ ل ك ط ظ */
'\0',
- '\xD8', '\xAA', '\xD8', '\xAB', '\xD8', '\xB7', '\xD8', '\xB8', '\xD9', '\x83', /* ت ث ط ظ ك */
+ '\xD8', '\xAA', ' ', '\xD8', '\xAB', ' ', '\xD8', '\xB7', ' ', '\xD8', '\xB8', ' ', '\xD9', '\x83', /* ت ث ط ظ ك */
'\0',
- '\xD0', '\x91', '\xD0', '\x92', '\xD0', '\x95', '\xD0', '\x9F', '\xD0', '\x97', '\xD0', '\x9E', '\xD0', '\xA1', '\xD0', '\xAD', /* БВЕПЗОСЭ */
+ '\xD9', '\x80', /* ـ */
'\0',
- '\xD0', '\x91', '\xD0', '\x92', '\xD0', '\x95', '\xD0', '\xA8', '\xD0', '\x97', '\xD0', '\x9E', '\xD0', '\xA1', '\xD0', '\xAD', /* БВЕШЗОСЭ */
+ '\xD0', '\x91', ' ', '\xD0', '\x92', ' ', '\xD0', '\x95', ' ', '\xD0', '\x9F', ' ', '\xD0', '\x97', ' ', '\xD0', '\x9E', ' ', '\xD0', '\xA1', ' ', '\xD0', '\xAD', /* Б В Е П З О С Э */
'\0',
- '\xD1', '\x85', '\xD0', '\xBF', '\xD0', '\xBD', '\xD1', '\x88', '\xD0', '\xB5', '\xD0', '\xB7', '\xD0', '\xBE', '\xD1', '\x81', /* хпншезос */
+ '\xD0', '\x91', ' ', '\xD0', '\x92', ' ', '\xD0', '\x95', ' ', '\xD0', '\xA8', ' ', '\xD0', '\x97', ' ', '\xD0', '\x9E', ' ', '\xD0', '\xA1', ' ', '\xD0', '\xAD', /* Б В Е Ш З О С Э */
'\0',
- '\xD1', '\x80', '\xD1', '\x83', '\xD1', '\x84', /* руф */
+ '\xD1', '\x85', ' ', '\xD0', '\xBF', ' ', '\xD0', '\xBD', ' ', '\xD1', '\x88', ' ', '\xD0', '\xB5', ' ', '\xD0', '\xB7', ' ', '\xD0', '\xBE', ' ', '\xD1', '\x81', /* х п н ш е з о с */
'\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', /* क म अ आ थ ध भ श */
+ '\xD1', '\x80', ' ', '\xD1', '\x83', ' ', '\xD1', '\x84', /* р у ф */
'\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', /* ई ऐ ओ औ ि ी ो ौ */
+ '\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', '\x95', '\xE0', '\xA4', '\xAE', '\xE0', '\xA4', '\x85', '\xE0', '\xA4', '\x86', '\xE0', '\xA4', '\xA5', '\xE0', '\xA4', '\xA7', '\xE0', '\xA4', '\xAD', '\xE0', '\xA4', '\xB6', /* क म अ आ थ ध भ श */
+ '\xE0', '\xA4', '\x88', ' ', '\xE0', '\xA4', '\x90', ' ', '\xE0', '\xA4', '\x93', ' ', '\xE0', '\xA4', '\x94', ' ', '\xE0', '\xA4', '\xBF', ' ', '\xE0', '\xA5', '\x80', ' ', '\xE0', '\xA5', '\x8B', ' ', '\xE0', '\xA5', '\x8C', /* ई ऐ ओ औ ि ी ो ौ */
'\0',
- '\xE0', '\xA5', '\x81', '\xE0', '\xA5', '\x83', /* ु ृ */
+ '\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',
- '\xCE', '\x93', '\xCE', '\x92', '\xCE', '\x95', '\xCE', '\x96', '\xCE', '\x98', '\xCE', '\x9F', '\xCE', '\xA9', /* ΓΒΕΖΘΟΩ */
+ '\xE0', '\xA5', '\x81', ' ', '\xE0', '\xA5', '\x83', /* ु ृ */
'\0',
- '\xCE', '\x92', '\xCE', '\x94', '\xCE', '\x96', '\xCE', '\x9E', '\xCE', '\x98', '\xCE', '\x9F', /* ΒΔΖΞΘΟ */
+ '\xCE', '\x93', ' ', '\xCE', '\x92', ' ', '\xCE', '\x95', ' ', '\xCE', '\x96', ' ', '\xCE', '\x98', ' ', '\xCE', '\x9F', ' ', '\xCE', '\xA9', /* Γ Β Ε Ζ Θ Ο Ω */
'\0',
- '\xCE', '\xB2', '\xCE', '\xB8', '\xCE', '\xB4', '\xCE', '\xB6', '\xCE', '\xBB', '\xCE', '\xBE', /* βθδζλξ */
+ '\xCE', '\x92', ' ', '\xCE', '\x94', ' ', '\xCE', '\x96', ' ', '\xCE', '\x9E', ' ', '\xCE', '\x98', ' ', '\xCE', '\x9F', /* Β Δ Ζ Ξ Θ Ο */
'\0',
- '\xCE', '\xB1', '\xCE', '\xB5', '\xCE', '\xB9', '\xCE', '\xBF', '\xCF', '\x80', '\xCF', '\x83', '\xCF', '\x84', '\xCF', '\x89', /* αειοπστω */
+ '\xCE', '\xB2', ' ', '\xCE', '\xB8', ' ', '\xCE', '\xB4', ' ', '\xCE', '\xB6', ' ', '\xCE', '\xBB', ' ', '\xCE', '\xBE', /* β θ δ ζ λ ξ */
'\0',
- '\xCE', '\xB2', '\xCE', '\xB3', '\xCE', '\xB7', '\xCE', '\xBC', '\xCF', '\x81', '\xCF', '\x86', '\xCF', '\x87', '\xCF', '\x88', /* βγημρφχψ */
+ '\xCE', '\xB1', ' ', '\xCE', '\xB5', ' ', '\xCE', '\xB9', ' ', '\xCE', '\xBF', ' ', '\xCF', '\x80', ' ', '\xCF', '\x83', ' ', '\xCF', '\x84', ' ', '\xCF', '\x89', /* α ε ι ο π σ τ ω */
'\0',
- '\xD7', '\x91', '\xD7', '\x93', '\xD7', '\x94', '\xD7', '\x97', '\xD7', '\x9A', '\xD7', '\x9B', '\xD7', '\x9D', '\xD7', '\xA1', /* בדהחךכםס */
+ '\xCE', '\xB2', ' ', '\xCE', '\xB3', ' ', '\xCE', '\xB7', ' ', '\xCE', '\xBC', ' ', '\xCF', '\x81', ' ', '\xCF', '\x86', ' ', '\xCF', '\x87', ' ', '\xCF', '\x88', /* β γ η μ ρ φ χ ψ */
'\0',
- '\xD7', '\x91', '\xD7', '\x98', '\xD7', '\x9B', '\xD7', '\x9D', '\xD7', '\xA1', '\xD7', '\xA6', /* בטכםסצ */
+ '\xD7', '\x91', ' ', '\xD7', '\x93', ' ', '\xD7', '\x94', ' ', '\xD7', '\x97', ' ', '\xD7', '\x9A', ' ', '\xD7', '\x9B', ' ', '\xD7', '\x9D', ' ', '\xD7', '\xA1', /* ב ד ה ח ך כ ם ס */
'\0',
- '\xD7', '\xA7', '\xD7', '\x9A', '\xD7', '\x9F', '\xD7', '\xA3', '\xD7', '\xA5', /* קךןףץ */
+ '\xD7', '\x91', ' ', '\xD7', '\x98', ' ', '\xD7', '\x9B', ' ', '\xD7', '\x9D', ' ', '\xD7', '\xA1', ' ', '\xD7', '\xA6', /* ב ט כ ם ס צ */
'\0',
- 'T', 'H', 'E', 'Z', 'O', 'C', 'Q', 'S', /* THEZOCQS */
+ '\xD7', '\xA7', ' ', '\xD7', '\x9A', ' ', '\xD7', '\x9F', ' ', '\xD7', '\xA3', ' ', '\xD7', '\xA5', /* ק ך ן ף ץ */
'\0',
- 'H', 'E', 'Z', 'L', 'O', 'C', 'U', 'S', /* HEZLOCUS */
+ '\xE1', '\x9E', '\x81', ' ', '\xE1', '\x9E', '\x91', ' ', '\xE1', '\x9E', '\x93', ' ', '\xE1', '\x9E', '\xA7', ' ', '\xE1', '\x9E', '\xA9', ' ', '\xE1', '\x9E', '\xB6', /* ខ ទ ន ឧ ឩ ា */
'\0',
- 'f', 'i', 'j', 'k', 'd', 'b', 'h', /* fijkdbh */
+ '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x80', ' ', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x81', ' ', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x82', ' ', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x90', /* ក្ក ក្ខ ក្គ ក្ថ */
'\0',
- 'x', 'z', 'r', 'o', 'e', 's', 'c', /* xzroesc */
+ '\xE1', '\x9E', '\x81', ' ', '\xE1', '\x9E', '\x83', ' ', '\xE1', '\x9E', '\x85', ' ', '\xE1', '\x9E', '\x8B', ' ', '\xE1', '\x9E', '\x94', ' ', '\xE1', '\x9E', '\x98', ' ', '\xE1', '\x9E', '\x99', ' ', '\xE1', '\x9E', '\xB2', /* ខ ឃ ច ឋ ប ម យ ឲ */
'\0',
- 'p', 'q', 'g', 'j', 'y', /* pqgjy */
+ '\xE1', '\x9E', '\x8F', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x9A', ' ', '\xE1', '\x9E', '\x9A', '\xE1', '\x9F', '\x80', ' ', '\xE1', '\x9E', '\xB2', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x99', ' ', '\xE1', '\x9E', '\xA2', '\xE1', '\x9E', '\xBF', /* ត្រ រៀ ឲ្យ អឿ */
'\0',
- '\xE0', '\xB0', '\x87', '\xE0', '\xB0', '\x8C', '\xE0', '\xB0', '\x99', '\xE0', '\xB0', '\x9E', '\xE0', '\xB0', '\xA3', '\xE0', '\xB0', '\xB1', '\xE0', '\xB1', '\xAF', /* ఇ ఌ ఙ ఞ ణ ఱ ౯ */
+ '\xE1', '\x9E', '\x93', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x8F', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x9A', '\xE1', '\x9F', '\x83', ' ', '\xE1', '\x9E', '\x84', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x81', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x99', ' ', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x94', '\xE1', '\x9F', '\x80', ' ', '\xE1', '\x9E', '\x85', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x9A', '\xE1', '\x9F', '\x80', ' ', '\xE1', '\x9E', '\x93', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x8F', '\xE1', '\x9E', '\xBF', ' ', '\xE1', '\x9E', '\x9B', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x94', '\xE1', '\x9E', '\xBF', /* ន្ត្រៃ ង្ខ្យ ក្បៀ ច្រៀ ន្តឿ ល្បឿ */
'\0',
- '\xE0', '\xB0', '\x85', '\xE0', '\xB0', '\x95', '\xE0', '\xB0', '\x9A', '\xE0', '\xB0', '\xB0', '\xE0', '\xB0', '\xBD', '\xE0', '\xB1', '\xA8', '\xE0', '\xB1', '\xAC', /* అ క చ ర ఽ ౨ ౬ */
+ '\xE1', '\xA7', '\xA0', ' ', '\xE1', '\xA7', '\xA1', /* ᧠ ᧡ */
'\0',
- '\xE0', '\xB8', '\x9A', '\xE0', '\xB9', '\x80', '\xE0', '\xB9', '\x81', '\xE0', '\xB8', '\xAD', '\xE0', '\xB8', '\x81', '\xE0', '\xB8', '\xB2', /* บ เ แ อ ก า */
+ '\xE1', '\xA7', '\xB6', ' ', '\xE1', '\xA7', '\xB9', /* ᧶ ᧹ */
'\0',
- '\xE0', '\xB8', '\x9A', '\xE0', '\xB8', '\x9B', '\xE0', '\xB8', '\xA9', '\xE0', '\xB8', '\xAF', '\xE0', '\xB8', '\xAD', '\xE0', '\xB8', '\xA2', '\xE0', '\xB8', '\xAE', /* บ ป ษ ฯ อ ย ฮ */
+ '\xE0', '\xBA', '\xB2', ' ', '\xE0', '\xBA', '\x94', ' ', '\xE0', '\xBA', '\xAD', ' ', '\xE0', '\xBA', '\xA1', ' ', '\xE0', '\xBA', '\xA5', ' ', '\xE0', '\xBA', '\xA7', ' ', '\xE0', '\xBA', '\xA3', ' ', '\xE0', '\xBA', '\x87', /* າ ດ ອ ມ ລ ວ ຣ ງ */
'\0',
- '\xE0', '\xB8', '\x9B', '\xE0', '\xB8', '\x9D', '\xE0', '\xB8', '\x9F', /* ป ฝ ฟ */
+ '\xE0', '\xBA', '\xB2', ' ', '\xE0', '\xBA', '\xAD', ' ', '\xE0', '\xBA', '\x9A', ' ', '\xE0', '\xBA', '\x8D', ' ', '\xE0', '\xBA', '\xA3', ' ', '\xE0', '\xBA', '\xAE', ' ', '\xE0', '\xBA', '\xA7', ' ', '\xE0', '\xBA', '\xA2', /* າ ອ ບ ຍ ຣ ຮ ວ ຢ */
'\0',
- '\xE0', '\xB9', '\x82', '\xE0', '\xB9', '\x83', '\xE0', '\xB9', '\x84', /* โ ใ ไ */
+ '\xE0', '\xBA', '\x9B', ' ', '\xE0', '\xBA', '\xA2', ' ', '\xE0', '\xBA', '\x9F', ' ', '\xE0', '\xBA', '\x9D', /* ປ ຢ ຟ ຝ */
'\0',
- '\xE0', '\xB8', '\x8E', '\xE0', '\xB8', '\x8F', '\xE0', '\xB8', '\xA4', '\xE0', '\xB8', '\xA6', /* ฎ ฏ ฤ ฦ */
+ '\xE0', '\xBB', '\x82', ' ', '\xE0', '\xBB', '\x84', ' ', '\xE0', '\xBB', '\x83', /* ໂ ໄ ໃ */
'\0',
- '\xE0', '\xB8', '\x8D', '\xE0', '\xB8', '\x90', /* ญ ฐ */
+ '\xE0', '\xBA', '\x87', ' ', '\xE0', '\xBA', '\x8A', ' ', '\xE0', '\xBA', '\x96', ' ', '\xE0', '\xBA', '\xBD', ' ', '\xE0', '\xBB', '\x86', ' ', '\xE0', '\xBA', '\xAF', /* ງ ຊ ຖ ຽ ໆ ຯ */
'\0',
- '\xE0', '\xB9', '\x90', '\xE0', '\xB9', '\x91', '\xE0', '\xB9', '\x93', /* ๐ ๑ ๓ */
+ 'T', ' ', 'H', ' ', 'E', ' ', 'Z', ' ', 'O', ' ', 'C', ' ', 'Q', ' ', 'S', /* T H E Z O C Q S */
+ '\0',
+ 'H', ' ', 'E', ' ', 'Z', ' ', 'L', ' ', 'O', ' ', 'C', ' ', 'U', ' ', 'S', /* H E Z L O C U S */
+ '\0',
+ 'f', ' ', 'i', ' ', 'j', ' ', 'k', ' ', 'd', ' ', 'b', ' ', 'h', /* f i j k d b h */
+ '\0',
+ 'x', ' ', 'z', ' ', 'r', ' ', 'o', ' ', 'e', ' ', 's', ' ', 'c', /* x z r o e s c */
+ '\0',
+ 'p', ' ', 'q', ' ', 'g', ' ', 'j', ' ', 'y', /* p q g j y */
+ '\0',
+ '\xE2', '\x82', '\x80', ' ', '\xE2', '\x82', '\x83', ' ', '\xE2', '\x82', '\x85', ' ', '\xE2', '\x82', '\x87', ' ', '\xE2', '\x82', '\x88', /* ₀ ₃ ₅ ₇ ₈ */
+ '\0',
+ '\xE2', '\x82', '\x80', ' ', '\xE2', '\x82', '\x81', ' ', '\xE2', '\x82', '\x82', ' ', '\xE2', '\x82', '\x83', ' ', '\xE2', '\x82', '\x88', /* ₀ ₁ ₂ ₃ ₈ */
+ '\0',
+ '\xE1', '\xB5', '\xA2', ' ', '\xE2', '\xB1', '\xBC', ' ', '\xE2', '\x82', '\x95', ' ', '\xE2', '\x82', '\x96', ' ', '\xE2', '\x82', '\x97', /* ᵢ ⱼ ₕ ₖ ₗ */
+ '\0',
+ '\xE2', '\x82', '\x90', ' ', '\xE2', '\x82', '\x91', ' ', '\xE2', '\x82', '\x92', ' ', '\xE2', '\x82', '\x93', ' ', '\xE2', '\x82', '\x99', ' ', '\xE2', '\x82', '\x9B', ' ', '\xE1', '\xB5', '\xA5', ' ', '\xE1', '\xB5', '\xA4', ' ', '\xE1', '\xB5', '\xA3', /* ₐ ₑ ₒ ₓ ₙ ₛ ᵥ ᵤ ᵣ */
+ '\0',
+ '\xE1', '\xB5', '\xA6', ' ', '\xE1', '\xB5', '\xA7', ' ', '\xE1', '\xB5', '\xA8', ' ', '\xE1', '\xB5', '\xA9', ' ', '\xE2', '\x82', '\x9A', /* ᵦ ᵧ ᵨ ᵩ ₚ */
+ '\0',
+ '\xE2', '\x81', '\xB0', ' ', '\xC2', '\xB3', ' ', '\xE2', '\x81', '\xB5', ' ', '\xE2', '\x81', '\xB7', ' ', '\xE1', '\xB5', '\x80', ' ', '\xE1', '\xB4', '\xB4', ' ', '\xE1', '\xB4', '\xB1', ' ', '\xE1', '\xB4', '\xBC', /* ⁰ ³ ⁵ ⁷ ᵀ ᴴ ᴱ ᴼ */
+ '\0',
+ '\xE2', '\x81', '\xB0', ' ', '\xC2', '\xB9', ' ', '\xC2', '\xB2', ' ', '\xC2', '\xB3', ' ', '\xE1', '\xB4', '\xB1', ' ', '\xE1', '\xB4', '\xB8', ' ', '\xE1', '\xB4', '\xBC', ' ', '\xE1', '\xB5', '\x81', /* ⁰ ¹ ² ³ ᴱ ᴸ ᴼ ᵁ */
+ '\0',
+ '\xE1', '\xB5', '\x87', ' ', '\xE1', '\xB5', '\x88', ' ', '\xE1', '\xB5', '\x8F', ' ', '\xCA', '\xB0', ' ', '\xCA', '\xB2', ' ', '\xE1', '\xB6', '\xA0', ' ', '\xE2', '\x81', '\xB1', /* ᵇ ᵈ ᵏ ʰ ʲ ᶠ ⁱ */
+ '\0',
+ '\xE1', '\xB5', '\x89', ' ', '\xE1', '\xB5', '\x92', ' ', '\xCA', '\xB3', ' ', '\xCB', '\xA2', ' ', '\xCB', '\xA3', ' ', '\xE1', '\xB6', '\x9C', ' ', '\xE1', '\xB6', '\xBB', /* ᵉ ᵒ ʳ ˢ ˣ ᶜ ᶻ */
+ '\0',
+ '\xE1', '\xB5', '\x96', ' ', '\xCA', '\xB8', ' ', '\xE1', '\xB5', '\x8D', /* ᵖ ʸ ᵍ */
+ '\0',
+ '\xE1', '\x80', '\x81', ' ', '\xE1', '\x80', '\x82', ' ', '\xE1', '\x80', '\x84', ' ', '\xE1', '\x80', '\x92', ' ', '\xE1', '\x80', '\x9D', ' ', '\xE1', '\x81', '\xA5', ' ', '\xE1', '\x81', '\x8A', ' ', '\xE1', '\x81', '\x8B', /* ခ ဂ င ဒ ဝ ၥ ၊ ။ */
+ '\0',
+ '\xE1', '\x80', '\x84', ' ', '\xE1', '\x80', '\x8E', ' ', '\xE1', '\x80', '\x92', ' ', '\xE1', '\x80', '\x95', ' ', '\xE1', '\x80', '\x97', ' ', '\xE1', '\x80', '\x9D', ' ', '\xE1', '\x81', '\x8A', ' ', '\xE1', '\x81', '\x8B', /* င ဎ ဒ ပ ဗ ဝ ၊ ။ */
+ '\0',
+ '\xE1', '\x80', '\xA9', ' ', '\xE1', '\x80', '\xBC', ' ', '\xE1', '\x81', '\x8D', ' ', '\xE1', '\x81', '\x8F', ' ', '\xE1', '\x81', '\x86', ' ', '\xE1', '\x80', '\xAB', ' ', '\xE1', '\x80', '\xAD', /* ဩ ြ ၍ ၏ ၆ ါ ိ */
+ '\0',
+ '\xE1', '\x80', '\x89', ' ', '\xE1', '\x80', '\x8A', ' ', '\xE1', '\x80', '\xA5', ' ', '\xE1', '\x80', '\xA9', ' ', '\xE1', '\x80', '\xA8', ' ', '\xE1', '\x81', '\x82', ' ', '\xE1', '\x81', '\x85', ' ', '\xE1', '\x81', '\x89', /* ဉ ည ဥ ဩ ဨ ၂ ၅ ၉ */
+ '\0',
+ '\xE0', '\xB0', '\x87', ' ', '\xE0', '\xB0', '\x8C', ' ', '\xE0', '\xB0', '\x99', ' ', '\xE0', '\xB0', '\x9E', ' ', '\xE0', '\xB0', '\xA3', ' ', '\xE0', '\xB0', '\xB1', ' ', '\xE0', '\xB1', '\xAF', /* ఇ ఌ ఙ ఞ ణ ఱ ౯ */
+ '\0',
+ '\xE0', '\xB0', '\x85', ' ', '\xE0', '\xB0', '\x95', ' ', '\xE0', '\xB0', '\x9A', ' ', '\xE0', '\xB0', '\xB0', ' ', '\xE0', '\xB0', '\xBD', ' ', '\xE0', '\xB1', '\xA8', ' ', '\xE0', '\xB1', '\xAC', /* అ క చ ర ఽ ౨ ౬ */
+ '\0',
+ '\xE0', '\xB8', '\x9A', ' ', '\xE0', '\xB9', '\x80', ' ', '\xE0', '\xB9', '\x81', ' ', '\xE0', '\xB8', '\xAD', ' ', '\xE0', '\xB8', '\x81', ' ', '\xE0', '\xB8', '\xB2', /* บ เ แ อ ก า */
+ '\0',
+ '\xE0', '\xB8', '\x9A', ' ', '\xE0', '\xB8', '\x9B', ' ', '\xE0', '\xB8', '\xA9', ' ', '\xE0', '\xB8', '\xAF', ' ', '\xE0', '\xB8', '\xAD', ' ', '\xE0', '\xB8', '\xA2', ' ', '\xE0', '\xB8', '\xAE', /* บ ป ษ ฯ อ ย ฮ */
+ '\0',
+ '\xE0', '\xB8', '\x9B', ' ', '\xE0', '\xB8', '\x9D', ' ', '\xE0', '\xB8', '\x9F', /* ป ฝ ฟ */
+ '\0',
+ '\xE0', '\xB9', '\x82', ' ', '\xE0', '\xB9', '\x83', ' ', '\xE0', '\xB9', '\x84', /* โ ใ ไ */
+ '\0',
+ '\xE0', '\xB8', '\x8E', ' ', '\xE0', '\xB8', '\x8F', ' ', '\xE0', '\xB8', '\xA4', ' ', '\xE0', '\xB8', '\xA6', /* ฎ ฏ ฤ ฦ */
+ '\0',
+ '\xE0', '\xB8', '\x8D', ' ', '\xE0', '\xB8', '\x90', /* ญ ฐ */
+ '\0',
+ '\xE0', '\xB9', '\x90', ' ', '\xE0', '\xB9', '\x91', ' ', '\xE0', '\xB9', '\x93', /* ๐ ๑ ๓ */
#ifdef AF_CONFIG_OPTION_CJK
'\0',
- '\xE4', '\xBB', '\x96', '\xE4', '\xBB', '\xAC', '\xE4', '\xBD', '\xA0', '\xE4', '\xBE', '\x86', '\xE5', '\x80', '\x91', '\xE5', '\x88', '\xB0', '\xE5', '\x92', '\x8C', '\xE5', '\x9C', '\xB0', /* 他们你來們到和地 */
- '\xE5', '\xAF', '\xB9', '\xE5', '\xB0', '\x8D', '\xE5', '\xB0', '\xB1', '\xE5', '\xB8', '\xAD', '\xE6', '\x88', '\x91', '\xE6', '\x97', '\xB6', '\xE6', '\x99', '\x82', '\xE6', '\x9C', '\x83', /* 对對就席我时時會 */
- '\xE6', '\x9D', '\xA5', '\xE7', '\x82', '\xBA', '\xE8', '\x83', '\xBD', '\xE8', '\x88', '\xB0', '\xE8', '\xAA', '\xAA', '\xE8', '\xAF', '\xB4', '\xE8', '\xBF', '\x99', '\xE9', '\x80', '\x99', /* 来為能舰說说这這 */
- '\xE9', '\xBD', '\x8A', '|', /* 齊 | */
- '\xE5', '\x86', '\x9B', '\xE5', '\x90', '\x8C', '\xE5', '\xB7', '\xB2', '\xE6', '\x84', '\xBF', '\xE6', '\x97', '\xA2', '\xE6', '\x98', '\x9F', '\xE6', '\x98', '\xAF', '\xE6', '\x99', '\xAF', /* 军同已愿既星是景 */
- '\xE6', '\xB0', '\x91', '\xE7', '\x85', '\xA7', '\xE7', '\x8E', '\xB0', '\xE7', '\x8F', '\xBE', '\xE7', '\x90', '\x86', '\xE7', '\x94', '\xA8', '\xE7', '\xBD', '\xAE', '\xE8', '\xA6', '\x81', /* 民照现現理用置要 */
- '\xE8', '\xBB', '\x8D', '\xE9', '\x82', '\xA3', '\xE9', '\x85', '\x8D', '\xE9', '\x87', '\x8C', '\xE9', '\x96', '\x8B', '\xE9', '\x9B', '\xB7', '\xE9', '\x9C', '\xB2', '\xE9', '\x9D', '\xA2', /* 軍那配里開雷露面 */
- '\xE9', '\xA1', '\xBE', /* 顾 */
- '\0',
- '\xE4', '\xB8', '\xAA', '\xE4', '\xB8', '\xBA', '\xE4', '\xBA', '\xBA', '\xE4', '\xBB', '\x96', '\xE4', '\xBB', '\xA5', '\xE4', '\xBB', '\xAC', '\xE4', '\xBD', '\xA0', '\xE4', '\xBE', '\x86', /* 个为人他以们你來 */
- '\xE5', '\x80', '\x8B', '\xE5', '\x80', '\x91', '\xE5', '\x88', '\xB0', '\xE5', '\x92', '\x8C', '\xE5', '\xA4', '\xA7', '\xE5', '\xAF', '\xB9', '\xE5', '\xB0', '\x8D', '\xE5', '\xB0', '\xB1', /* 個們到和大对對就 */
- '\xE6', '\x88', '\x91', '\xE6', '\x97', '\xB6', '\xE6', '\x99', '\x82', '\xE6', '\x9C', '\x89', '\xE6', '\x9D', '\xA5', '\xE7', '\x82', '\xBA', '\xE8', '\xA6', '\x81', '\xE8', '\xAA', '\xAA', /* 我时時有来為要說 */
- '\xE8', '\xAF', '\xB4', '|', /* 说 | */
- '\xE4', '\xB8', '\xBB', '\xE4', '\xBA', '\x9B', '\xE5', '\x9B', '\xA0', '\xE5', '\xAE', '\x83', '\xE6', '\x83', '\xB3', '\xE6', '\x84', '\x8F', '\xE7', '\x90', '\x86', '\xE7', '\x94', '\x9F', /* 主些因它想意理生 */
- '\xE7', '\x95', '\xB6', '\xE7', '\x9C', '\x8B', '\xE7', '\x9D', '\x80', '\xE7', '\xBD', '\xAE', '\xE8', '\x80', '\x85', '\xE8', '\x87', '\xAA', '\xE8', '\x91', '\x97', '\xE8', '\xA3', '\xA1', /* 當看着置者自著裡 */
- '\xE8', '\xBF', '\x87', '\xE8', '\xBF', '\x98', '\xE8', '\xBF', '\x9B', '\xE9', '\x80', '\xB2', '\xE9', '\x81', '\x8E', '\xE9', '\x81', '\x93', '\xE9', '\x82', '\x84', '\xE9', '\x87', '\x8C', /* 过还进進過道還里 */
- '\xE9', '\x9D', '\xA2', /* 面 */
+ '\xE4', '\xBB', '\x96', ' ', '\xE4', '\xBB', '\xAC', ' ', '\xE4', '\xBD', '\xA0', ' ', '\xE4', '\xBE', '\x86', ' ', '\xE5', '\x80', '\x91', ' ', '\xE5', '\x88', '\xB0', ' ', '\xE5', '\x92', '\x8C', ' ', '\xE5', '\x9C', '\xB0', /* 他 们 你 來 們 到 和 地 */
+ ' ', '\xE5', '\xAF', '\xB9', ' ', '\xE5', '\xB0', '\x8D', ' ', '\xE5', '\xB0', '\xB1', ' ', '\xE5', '\xB8', '\xAD', ' ', '\xE6', '\x88', '\x91', ' ', '\xE6', '\x97', '\xB6', ' ', '\xE6', '\x99', '\x82', ' ', '\xE6', '\x9C', '\x83', /* 对 對 就 席 我 时 時 會 */
+ ' ', '\xE6', '\x9D', '\xA5', ' ', '\xE7', '\x82', '\xBA', ' ', '\xE8', '\x83', '\xBD', ' ', '\xE8', '\x88', '\xB0', ' ', '\xE8', '\xAA', '\xAA', ' ', '\xE8', '\xAF', '\xB4', ' ', '\xE8', '\xBF', '\x99', ' ', '\xE9', '\x80', '\x99', /* 来 為 能 舰 說 说 这 這 */
+ ' ', '\xE9', '\xBD', '\x8A', ' ', '|', /* 齊 | */
+ ' ', '\xE5', '\x86', '\x9B', ' ', '\xE5', '\x90', '\x8C', ' ', '\xE5', '\xB7', '\xB2', ' ', '\xE6', '\x84', '\xBF', ' ', '\xE6', '\x97', '\xA2', ' ', '\xE6', '\x98', '\x9F', ' ', '\xE6', '\x98', '\xAF', ' ', '\xE6', '\x99', '\xAF', /* 军 同 已 愿 既 星 是 景 */
+ ' ', '\xE6', '\xB0', '\x91', ' ', '\xE7', '\x85', '\xA7', ' ', '\xE7', '\x8E', '\xB0', ' ', '\xE7', '\x8F', '\xBE', ' ', '\xE7', '\x90', '\x86', ' ', '\xE7', '\x94', '\xA8', ' ', '\xE7', '\xBD', '\xAE', ' ', '\xE8', '\xA6', '\x81', /* 民 照 现 現 理 用 置 要 */
+ ' ', '\xE8', '\xBB', '\x8D', ' ', '\xE9', '\x82', '\xA3', ' ', '\xE9', '\x85', '\x8D', ' ', '\xE9', '\x87', '\x8C', ' ', '\xE9', '\x96', '\x8B', ' ', '\xE9', '\x9B', '\xB7', ' ', '\xE9', '\x9C', '\xB2', ' ', '\xE9', '\x9D', '\xA2', /* 軍 那 配 里 開 雷 露 面 */
+ ' ', '\xE9', '\xA1', '\xBE', /* 顾 */
+ '\0',
+ '\xE4', '\xB8', '\xAA', ' ', '\xE4', '\xB8', '\xBA', ' ', '\xE4', '\xBA', '\xBA', ' ', '\xE4', '\xBB', '\x96', ' ', '\xE4', '\xBB', '\xA5', ' ', '\xE4', '\xBB', '\xAC', ' ', '\xE4', '\xBD', '\xA0', ' ', '\xE4', '\xBE', '\x86', /* 个 为 人 他 以 们 你 來 */
+ ' ', '\xE5', '\x80', '\x8B', ' ', '\xE5', '\x80', '\x91', ' ', '\xE5', '\x88', '\xB0', ' ', '\xE5', '\x92', '\x8C', ' ', '\xE5', '\xA4', '\xA7', ' ', '\xE5', '\xAF', '\xB9', ' ', '\xE5', '\xB0', '\x8D', ' ', '\xE5', '\xB0', '\xB1', /* 個 們 到 和 大 对 對 就 */
+ ' ', '\xE6', '\x88', '\x91', ' ', '\xE6', '\x97', '\xB6', ' ', '\xE6', '\x99', '\x82', ' ', '\xE6', '\x9C', '\x89', ' ', '\xE6', '\x9D', '\xA5', ' ', '\xE7', '\x82', '\xBA', ' ', '\xE8', '\xA6', '\x81', ' ', '\xE8', '\xAA', '\xAA', /* 我 时 時 有 来 為 要 說 */
+ ' ', '\xE8', '\xAF', '\xB4', ' ', '|', /* 说 | */
+ ' ', '\xE4', '\xB8', '\xBB', ' ', '\xE4', '\xBA', '\x9B', ' ', '\xE5', '\x9B', '\xA0', ' ', '\xE5', '\xAE', '\x83', ' ', '\xE6', '\x83', '\xB3', ' ', '\xE6', '\x84', '\x8F', ' ', '\xE7', '\x90', '\x86', ' ', '\xE7', '\x94', '\x9F', /* 主 些 因 它 想 意 理 生 */
+ ' ', '\xE7', '\x95', '\xB6', ' ', '\xE7', '\x9C', '\x8B', ' ', '\xE7', '\x9D', '\x80', ' ', '\xE7', '\xBD', '\xAE', ' ', '\xE8', '\x80', '\x85', ' ', '\xE8', '\x87', '\xAA', ' ', '\xE8', '\x91', '\x97', ' ', '\xE8', '\xA3', '\xA1', /* 當 看 着 置 者 自 著 裡 */
+ ' ', '\xE8', '\xBF', '\x87', ' ', '\xE8', '\xBF', '\x98', ' ', '\xE8', '\xBF', '\x9B', ' ', '\xE9', '\x80', '\xB2', ' ', '\xE9', '\x81', '\x8E', ' ', '\xE9', '\x81', '\x93', ' ', '\xE9', '\x82', '\x84', ' ', '\xE9', '\x87', '\x8C', /* 过 还 进 進 過 道 還 里 */
+ ' ', '\xE9', '\x9D', '\xA2', /* 面 */
#ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
'\0',
- '\xE4', '\xBA', '\x9B', '\xE4', '\xBB', '\xAC', '\xE4', '\xBD', '\xA0', '\xE4', '\xBE', '\x86', '\xE5', '\x80', '\x91', '\xE5', '\x88', '\xB0', '\xE5', '\x92', '\x8C', '\xE5', '\x9C', '\xB0', /* 些们你來們到和地 */
- '\xE5', '\xA5', '\xB9', '\xE5', '\xB0', '\x86', '\xE5', '\xB0', '\x87', '\xE5', '\xB0', '\xB1', '\xE5', '\xB9', '\xB4', '\xE5', '\xBE', '\x97', '\xE6', '\x83', '\x85', '\xE6', '\x9C', '\x80', /* 她将將就年得情最 */
- '\xE6', '\xA0', '\xB7', '\xE6', '\xA8', '\xA3', '\xE7', '\x90', '\x86', '\xE8', '\x83', '\xBD', '\xE8', '\xAA', '\xAA', '\xE8', '\xAF', '\xB4', '\xE8', '\xBF', '\x99', '\xE9', '\x80', '\x99', /* 样樣理能說说这這 */
- '\xE9', '\x80', '\x9A', '|', /* 通 | */
- '\xE5', '\x8D', '\xB3', '\xE5', '\x90', '\x97', '\xE5', '\x90', '\xA7', '\xE5', '\x90', '\xAC', '\xE5', '\x91', '\xA2', '\xE5', '\x93', '\x81', '\xE5', '\x93', '\x8D', '\xE5', '\x97', '\x8E', /* 即吗吧听呢品响嗎 */
- '\xE5', '\xB8', '\x88', '\xE5', '\xB8', '\xAB', '\xE6', '\x94', '\xB6', '\xE6', '\x96', '\xAD', '\xE6', '\x96', '\xB7', '\xE6', '\x98', '\x8E', '\xE7', '\x9C', '\xBC', '\xE9', '\x96', '\x93', /* 师師收断斷明眼間 */
- '\xE9', '\x97', '\xB4', '\xE9', '\x99', '\x85', '\xE9', '\x99', '\x88', '\xE9', '\x99', '\x90', '\xE9', '\x99', '\xA4', '\xE9', '\x99', '\xB3', '\xE9', '\x9A', '\x8F', '\xE9', '\x9A', '\x9B', /* 间际陈限除陳随際 */
- '\xE9', '\x9A', '\xA8', /* 隨 */
- '\0',
- '\xE4', '\xBA', '\x8B', '\xE5', '\x89', '\x8D', '\xE5', '\xAD', '\xB8', '\xE5', '\xB0', '\x86', '\xE5', '\xB0', '\x87', '\xE6', '\x83', '\x85', '\xE6', '\x83', '\xB3', '\xE6', '\x88', '\x96', /* 事前學将將情想或 */
- '\xE6', '\x94', '\xBF', '\xE6', '\x96', '\xAF', '\xE6', '\x96', '\xB0', '\xE6', '\xA0', '\xB7', '\xE6', '\xA8', '\xA3', '\xE6', '\xB0', '\x91', '\xE6', '\xB2', '\x92', '\xE6', '\xB2', '\xA1', /* 政斯新样樣民沒没 */
- '\xE7', '\x84', '\xB6', '\xE7', '\x89', '\xB9', '\xE7', '\x8E', '\xB0', '\xE7', '\x8F', '\xBE', '\xE7', '\x90', '\x83', '\xE7', '\xAC', '\xAC', '\xE7', '\xB6', '\x93', '\xE8', '\xB0', '\x81', /* 然特现現球第經谁 */
- '\xE8', '\xB5', '\xB7', '|', /* 起 | */
- '\xE4', '\xBE', '\x8B', '\xE5', '\x88', '\xA5', '\xE5', '\x88', '\xAB', '\xE5', '\x88', '\xB6', '\xE5', '\x8A', '\xA8', '\xE5', '\x8B', '\x95', '\xE5', '\x90', '\x97', '\xE5', '\x97', '\x8E', /* 例別别制动動吗嗎 */
- '\xE5', '\xA2', '\x9E', '\xE6', '\x8C', '\x87', '\xE6', '\x98', '\x8E', '\xE6', '\x9C', '\x9D', '\xE6', '\x9C', '\x9F', '\xE6', '\x9E', '\x84', '\xE7', '\x89', '\xA9', '\xE7', '\xA1', '\xAE', /* 增指明朝期构物确 */
- '\xE7', '\xA7', '\x8D', '\xE8', '\xAA', '\xBF', '\xE8', '\xB0', '\x83', '\xE8', '\xB2', '\xBB', '\xE8', '\xB4', '\xB9', '\xE9', '\x82', '\xA3', '\xE9', '\x83', '\xBD', '\xE9', '\x96', '\x93', /* 种調调費费那都間 */
- '\xE9', '\x97', '\xB4', /* 间 */
+ ' ', '\xE4', '\xBA', '\x9B', ' ', '\xE4', '\xBB', '\xAC', ' ', '\xE4', '\xBD', '\xA0', ' ', '\xE4', '\xBE', '\x86', ' ', '\xE5', '\x80', '\x91', ' ', '\xE5', '\x88', '\xB0', ' ', '\xE5', '\x92', '\x8C', ' ', '\xE5', '\x9C', '\xB0', /* 些 们 你 來 們 到 和 地 */
+ ' ', '\xE5', '\xA5', '\xB9', ' ', '\xE5', '\xB0', '\x86', ' ', '\xE5', '\xB0', '\x87', ' ', '\xE5', '\xB0', '\xB1', ' ', '\xE5', '\xB9', '\xB4', ' ', '\xE5', '\xBE', '\x97', ' ', '\xE6', '\x83', '\x85', ' ', '\xE6', '\x9C', '\x80', /* 她 将 將 就 年 得 情 最 */
+ ' ', '\xE6', '\xA0', '\xB7', ' ', '\xE6', '\xA8', '\xA3', ' ', '\xE7', '\x90', '\x86', ' ', '\xE8', '\x83', '\xBD', ' ', '\xE8', '\xAA', '\xAA', ' ', '\xE8', '\xAF', '\xB4', ' ', '\xE8', '\xBF', '\x99', ' ', '\xE9', '\x80', '\x99', /* 样 樣 理 能 說 说 这 這 */
+ ' ', '\xE9', '\x80', '\x9A', ' ', '|', /* 通 | */
+ ' ', '\xE5', '\x8D', '\xB3', ' ', '\xE5', '\x90', '\x97', ' ', '\xE5', '\x90', '\xA7', ' ', '\xE5', '\x90', '\xAC', ' ', '\xE5', '\x91', '\xA2', ' ', '\xE5', '\x93', '\x81', ' ', '\xE5', '\x93', '\x8D', ' ', '\xE5', '\x97', '\x8E', /* 即 吗 吧 听 呢 品 响 嗎 */
+ ' ', '\xE5', '\xB8', '\x88', ' ', '\xE5', '\xB8', '\xAB', ' ', '\xE6', '\x94', '\xB6', ' ', '\xE6', '\x96', '\xAD', ' ', '\xE6', '\x96', '\xB7', ' ', '\xE6', '\x98', '\x8E', ' ', '\xE7', '\x9C', '\xBC', ' ', '\xE9', '\x96', '\x93', /* 师 師 收 断 斷 明 眼 間 */
+ ' ', '\xE9', '\x97', '\xB4', ' ', '\xE9', '\x99', '\x85', ' ', '\xE9', '\x99', '\x88', ' ', '\xE9', '\x99', '\x90', ' ', '\xE9', '\x99', '\xA4', ' ', '\xE9', '\x99', '\xB3', ' ', '\xE9', '\x9A', '\x8F', ' ', '\xE9', '\x9A', '\x9B', /* 间 际 陈 限 除 陳 随 際 */
+ ' ', '\xE9', '\x9A', '\xA8', /* 隨 */
+ '\0',
+ '\xE4', '\xBA', '\x8B', ' ', '\xE5', '\x89', '\x8D', ' ', '\xE5', '\xAD', '\xB8', ' ', '\xE5', '\xB0', '\x86', ' ', '\xE5', '\xB0', '\x87', ' ', '\xE6', '\x83', '\x85', ' ', '\xE6', '\x83', '\xB3', ' ', '\xE6', '\x88', '\x96', /* 事 前 學 将 將 情 想 或 */
+ ' ', '\xE6', '\x94', '\xBF', ' ', '\xE6', '\x96', '\xAF', ' ', '\xE6', '\x96', '\xB0', ' ', '\xE6', '\xA0', '\xB7', ' ', '\xE6', '\xA8', '\xA3', ' ', '\xE6', '\xB0', '\x91', ' ', '\xE6', '\xB2', '\x92', ' ', '\xE6', '\xB2', '\xA1', /* 政 斯 新 样 樣 民 沒 没 */
+ ' ', '\xE7', '\x84', '\xB6', ' ', '\xE7', '\x89', '\xB9', ' ', '\xE7', '\x8E', '\xB0', ' ', '\xE7', '\x8F', '\xBE', ' ', '\xE7', '\x90', '\x83', ' ', '\xE7', '\xAC', '\xAC', ' ', '\xE7', '\xB6', '\x93', ' ', '\xE8', '\xB0', '\x81', /* 然 特 现 現 球 第 經 谁 */
+ ' ', '\xE8', '\xB5', '\xB7', ' ', '|', /* 起 | */
+ ' ', '\xE4', '\xBE', '\x8B', ' ', '\xE5', '\x88', '\xA5', ' ', '\xE5', '\x88', '\xAB', ' ', '\xE5', '\x88', '\xB6', ' ', '\xE5', '\x8A', '\xA8', ' ', '\xE5', '\x8B', '\x95', ' ', '\xE5', '\x90', '\x97', ' ', '\xE5', '\x97', '\x8E', /* 例 別 别 制 动 動 吗 嗎 */
+ ' ', '\xE5', '\xA2', '\x9E', ' ', '\xE6', '\x8C', '\x87', ' ', '\xE6', '\x98', '\x8E', ' ', '\xE6', '\x9C', '\x9D', ' ', '\xE6', '\x9C', '\x9F', ' ', '\xE6', '\x9E', '\x84', ' ', '\xE7', '\x89', '\xA9', ' ', '\xE7', '\xA1', '\xAE', /* 增 指 明 朝 期 构 物 确 */
+ ' ', '\xE7', '\xA7', '\x8D', ' ', '\xE8', '\xAA', '\xBF', ' ', '\xE8', '\xB0', '\x83', ' ', '\xE8', '\xB2', '\xBB', ' ', '\xE8', '\xB4', '\xB9', ' ', '\xE9', '\x82', '\xA3', ' ', '\xE9', '\x83', '\xBD', ' ', '\xE9', '\x96', '\x93', /* 种 調 调 費 费 那 都 間 */
+ ' ', '\xE9', '\x97', '\xB4', /* 间 */
#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
#endif /* AF_CONFIG_OPTION_CJK */
'\0',
@@ -139,9 +193,10 @@
af_blue_stringsets[] =
{
/* */
- { AF_BLUE_STRING_ARABIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
- { AF_BLUE_STRING_ARABIC_JOIN, 0 },
- { AF_BLUE_STRING_MAX, 0 },
+ { AF_BLUE_STRING_ARABIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_ARABIC_BOTTOM, 0 },
+ { AF_BLUE_STRING_ARABIC_JOIN, AF_BLUE_PROPERTY_LATIN_NEUTRAL },
+ { AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_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 |
@@ -170,6 +225,24 @@
{ AF_BLUE_STRING_HEBREW_BOTTOM, 0 },
{ AF_BLUE_STRING_HEBREW_DESCENDER, 0 },
{ AF_BLUE_STRING_MAX, 0 },
+ { AF_BLUE_STRING_KHMER_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
+ { AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP, AF_BLUE_PROPERTY_LATIN_SUB_TOP },
+ { AF_BLUE_STRING_KHMER_BOTTOM, 0 },
+ { AF_BLUE_STRING_KHMER_DESCENDER, 0 },
+ { AF_BLUE_STRING_KHMER_LARGE_DESCENDER, 0 },
+ { AF_BLUE_STRING_MAX, 0 },
+ { AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
+ { AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM, 0 },
+ { AF_BLUE_STRING_MAX, 0 },
+ { AF_BLUE_STRING_LAO_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
+ { AF_BLUE_STRING_LAO_BOTTOM, 0 },
+ { AF_BLUE_STRING_LAO_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_LAO_LARGE_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_LAO_DESCENDER, 0 },
+ { AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_LATIN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM, 0 },
{ AF_BLUE_STRING_LATIN_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
@@ -178,6 +251,28 @@
{ AF_BLUE_STRING_LATIN_SMALL, 0 },
{ AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0 },
{ AF_BLUE_STRING_MAX, 0 },
+ { AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM, 0 },
+ { AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_LATIN_SUBS_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
+ { AF_BLUE_STRING_LATIN_SUBS_SMALL, 0 },
+ { AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER, 0 },
+ { AF_BLUE_STRING_MAX, 0 },
+ { AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM, 0 },
+ { AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_LATIN_SUPS_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
+ { AF_BLUE_STRING_LATIN_SUPS_SMALL, 0 },
+ { AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER, 0 },
+ { AF_BLUE_STRING_MAX, 0 },
+ { AF_BLUE_STRING_MYANMAR_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
+ { AF_BLUE_STRING_MYANMAR_BOTTOM, 0 },
+ { AF_BLUE_STRING_MYANMAR_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_MYANMAR_DESCENDER, 0 },
+ { AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_TELUGU_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_TELUGU_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
diff --git a/src/autofit/afblue.dat b/src/autofit/afblue.dat
index fd5684e..5ffb852 100644
--- a/src/autofit/afblue.dat
+++ b/src/autofit/afblue.dat
@@ -20,9 +20,8 @@
// labels separated by whitespace and followed by a colon (everything in a
// single line); the first label gives the name of the enumeration template,
// the second the name of the array template, and the third the name of the
-// `maximum' template, holding the size of the largest array element. The
-// script then fills the corresponding templates (indicated by `@'
-// characters around the name).
+// `maximum' template. The script then fills the corresponding templates
+// (indicated by `@' characters around the name).
//
// A section contains one or more data records. Each data record consists
// of two or more lines. The first line holds the enumeration name, and the
@@ -30,15 +29,20 @@
//
// There are two possible representations for array data.
//
-// - A string of characters in UTF-8 encoding enclosed in double quotes,
-// using C syntax. There can be only one string per line, thus the
-// starting and ending double quote must be the first and last character
-// in the line, respectively, ignoring whitespace before and after the
-// string. Space characters within the string are ignored too. If there
-// are multiple strings (in multiple lines), they are concatenated to a
-// single string. In the output, a string gets represented as a series of
-// singles bytes, followed by a zero byte. The enumeration values simply
-// hold byte offsets to the start of the corresponding strings.
+// - A string of characters or character clusters (for example, representing
+// Aksharas, Devanagari syllables) in UTF-8 encoding enclosed in double
+// quotes, using C syntax, where the elements are separated by spaces.
+// There can be only one string per line, thus the starting and ending
+// double quote must be the first and last character in the line,
+// respectively, ignoring whitespace before and after the string. If
+// there are multiple strings (in multiple lines), they are concatenated
+// to a single string. In the output, a string gets represented as a
+// series of singles bytes, followed by a zero byte. The enumeration
+// values simply hold byte offsets to the start of the corresponding
+// strings.
+//
+// For strings, the `maximum' template holds the maximum number of
+// non-space characters in all strings.
//
// - Data blocks enclosed in balanced braces, which get copied verbatim and
// which can span multiple lines. The opening brace of a block must be
@@ -47,6 +51,9 @@
// character after each block and counts the number of blocks to set the
// enumeration values.
//
+// For data blocks, the `maximum' template holds the maximum number of
+// array elements.
+//
// A section can contain either strings only or data blocks only.
//
// A comment line starts with `//'; it gets removed. A preprocessor
@@ -69,20 +76,25 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN:
AF_BLUE_STRING_ARABIC_TOP
"ا إ ل ك ط ظ"
- AF_BLUE_STRING_ARABIC_JOIN
+ AF_BLUE_STRING_ARABIC_BOTTOM
"ت ث ط ظ ك"
+ // We don't necessarily have access to medial forms via Unicode in case
+ // Arabic presentational forms are missing. The only character that is
+ // guaranteed to have the same vertical position with joining (this is,
+ // non-isolated) forms is U+0640, ARABIC TATWEEL, which must join both
+ // round and flat curves.
+ AF_BLUE_STRING_ARABIC_JOIN
+ "ـ"
AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP
- "БВЕПЗОСЭ"
+ "Б В Е П З О С Э"
AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM
- "БВЕШЗОСЭ"
+ "Б В Е Ш З О С Э"
AF_BLUE_STRING_CYRILLIC_SMALL
- "хпншезос"
+ "х п н ш е з о с"
AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER
- "руф"
+ "р у ф"
- // we separate the letters with spaces to avoid ligatures;
- // this is just for convenience to simplify reading
AF_BLUE_STRING_DEVANAGARI_BASE
"क म अ आ थ ध भ श"
AF_BLUE_STRING_DEVANAGARI_TOP
@@ -96,36 +108,95 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN:
"ु ृ"
AF_BLUE_STRING_GREEK_CAPITAL_TOP
- "ΓΒΕΖΘΟΩ"
+ "Γ Β Ε Ζ Θ Ο Ω"
AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM
- "ΒΔΖΞΘΟ"
+ "Β Δ Ζ Ξ Θ Ο"
AF_BLUE_STRING_GREEK_SMALL_BETA_TOP
- "βθδζλξ"
+ "β θ δ ζ λ ξ"
AF_BLUE_STRING_GREEK_SMALL
- "αειοπστω"
+ "α ε ι ο π σ τ ω"
AF_BLUE_STRING_GREEK_SMALL_DESCENDER
- "βγημρφχψ"
+ "β γ η μ ρ φ χ ψ"
AF_BLUE_STRING_HEBREW_TOP
- "בדהחךכםס"
+ "ב ד ה ח ך כ ם ס"
AF_BLUE_STRING_HEBREW_BOTTOM
- "בטכםסצ"
+ "ב ט כ ם ס צ"
AF_BLUE_STRING_HEBREW_DESCENDER
- "קךןףץ"
+ "ק ך ן ף ץ"
+
+ AF_BLUE_STRING_KHMER_TOP
+ "ខ ទ ន ឧ ឩ ា"
+ AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP
+ "ក្ក ក្ខ ក្គ ក្ថ"
+ AF_BLUE_STRING_KHMER_BOTTOM
+ "ខ ឃ ច ឋ ប ម យ ឲ"
+ AF_BLUE_STRING_KHMER_DESCENDER
+ "ត្រ រៀ ឲ្យ អឿ"
+ AF_BLUE_STRING_KHMER_LARGE_DESCENDER
+ "ន្ត្រៃ ង្ខ្យ ក្បៀ ច្រៀ ន្តឿ ល្បឿ"
+
+ AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP
+ "᧠ ᧡"
+ AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM
+ "᧶ ᧹"
+
+ AF_BLUE_STRING_LAO_TOP
+ "າ ດ ອ ມ ລ ວ ຣ ງ"
+ AF_BLUE_STRING_LAO_BOTTOM
+ "າ ອ ບ ຍ ຣ ຮ ວ ຢ"
+ AF_BLUE_STRING_LAO_ASCENDER
+ "ປ ຢ ຟ ຝ"
+ AF_BLUE_STRING_LAO_LARGE_ASCENDER
+ "ໂ ໄ ໃ"
+ AF_BLUE_STRING_LAO_DESCENDER
+ "ງ ຊ ຖ ຽ ໆ ຯ"
AF_BLUE_STRING_LATIN_CAPITAL_TOP
- "THEZOCQS"
+ "T H E Z O C Q S"
AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM
- "HEZLOCUS"
+ "H E Z L O C U S"
AF_BLUE_STRING_LATIN_SMALL_F_TOP
- "fijkdbh"
+ "f i j k d b h"
AF_BLUE_STRING_LATIN_SMALL
- "xzroesc"
+ "x z r o e s c"
AF_BLUE_STRING_LATIN_SMALL_DESCENDER
- "pqgjy"
+ "p q g j y"
+
+ // we assume that both the subscript and superscript ranges
+ // don't contain oldstyle digits (actually, most fonts probably
+ // have digits only in those ranges)
+ AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP
+ "₀ ₃ ₅ ₇ ₈"
+ AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM
+ "₀ ₁ ₂ ₃ ₈"
+ AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP
+ "ᵢ ⱼ ₕ ₖ ₗ"
+ AF_BLUE_STRING_LATIN_SUBS_SMALL
+ "ₐ ₑ ₒ ₓ ₙ ₛ ᵥ ᵤ ᵣ"
+ AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER
+ "ᵦ ᵧ ᵨ ᵩ ₚ"
+
+ AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP
+ "⁰ ³ ⁵ ⁷ ᵀ ᴴ ᴱ ᴼ"
+ AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM
+ "⁰ ¹ ² ³ ᴱ ᴸ ᴼ ᵁ"
+ AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP
+ "ᵇ ᵈ ᵏ ʰ ʲ ᶠ ⁱ"
+ AF_BLUE_STRING_LATIN_SUPS_SMALL
+ "ᵉ ᵒ ʳ ˢ ˣ ᶜ ᶻ"
+ AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER
+ "ᵖ ʸ ᵍ"
+
+ AF_BLUE_STRING_MYANMAR_TOP
+ "ခ ဂ င ဒ ဝ ၥ ၊ ။"
+ AF_BLUE_STRING_MYANMAR_BOTTOM
+ "င ဎ ဒ ပ ဗ ဝ ၊ ။"
+ AF_BLUE_STRING_MYANMAR_ASCENDER
+ "ဩ ြ ၍ ၏ ၆ ါ ိ"
+ AF_BLUE_STRING_MYANMAR_DESCENDER
+ "ဉ ည ဥ ဩ ဨ ၂ ၅ ၉"
- // we separate the letters with spaces to avoid ligatures;
- // this is just for convenience to simplify reading
AF_BLUE_STRING_TELUGU_TOP
"ఇ ఌ ఙ ఞ ణ ఱ ౯"
AF_BLUE_STRING_TELUGU_BOTTOM
@@ -150,44 +221,44 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN:
#ifdef AF_CONFIG_OPTION_CJK
AF_BLUE_STRING_CJK_TOP
- "他们你來們到和地"
- "对對就席我时時會"
- "来為能舰說说这這"
- "齊 |"
- "军同已愿既星是景"
- "民照现現理用置要"
- "軍那配里開雷露面"
- "顾"
+ "他 们 你 來 們 到 和 地"
+ " 对 對 就 席 我 时 時 會"
+ " 来 為 能 舰 說 说 这 這"
+ " 齊 |"
+ " 军 同 已 愿 既 星 是 景"
+ " 民 照 现 現 理 用 置 要"
+ " 軍 那 配 里 開 雷 露 面"
+ " 顾"
AF_BLUE_STRING_CJK_BOTTOM
- "个为人他以们你來"
- "個們到和大对對就"
- "我时時有来為要說"
- "说 |"
- "主些因它想意理生"
- "當看着置者自著裡"
- "过还进進過道還里"
- "面"
+ "个 为 人 他 以 们 你 來"
+ " 個 們 到 和 大 对 對 就"
+ " 我 时 時 有 来 為 要 說"
+ " 说 |"
+ " 主 些 因 它 想 意 理 生"
+ " 當 看 着 置 者 自 著 裡"
+ " 过 还 进 進 過 道 還 里"
+ " 面"
#ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
AF_BLUE_STRING_CJK_LEFT
- "些们你來們到和地"
- "她将將就年得情最"
- "样樣理能說说这這"
- "通 |"
- "即吗吧听呢品响嗎"
- "师師收断斷明眼間"
- "间际陈限除陳随際"
- "隨"
+ " 些 们 你 來 們 到 和 地"
+ " 她 将 將 就 年 得 情 最"
+ " 样 樣 理 能 說 说 这 這"
+ " 通 |"
+ " 即 吗 吧 听 呢 品 响 嗎"
+ " 师 師 收 断 斷 明 眼 間"
+ " 间 际 陈 限 除 陳 随 際"
+ " 隨"
AF_BLUE_STRING_CJK_RIGHT
- "事前學将將情想或"
- "政斯新样樣民沒没"
- "然特现現球第經谁"
- "起 |"
- "例別别制动動吗嗎"
- "增指明朝期构物确"
- "种調调費费那都間"
- "间"
+ "事 前 學 将 將 情 想 或"
+ " 政 斯 新 样 樣 民 沒 没"
+ " 然 特 现 現 球 第 經 谁"
+ " 起 |"
+ " 例 別 别 制 动 動 吗 嗎"
+ " 增 指 明 朝 期 构 物 确"
+ " 种 調 调 費 费 那 都 間"
+ " 间"
#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
@@ -219,6 +290,14 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN:
// respectively. Only horizontal blue zones (i.e., adjusting vertical
// coordinate values) are supported.
//
+// Some scripts like Khmer need character composition to get all necessary
+// blue zones, since Unicode only provides an abstract data model that
+// doesn't represent all possible glyph shapes. For such character
+// clusters, the HarfBuzz library is used to convert them into the
+// corresponding glyphs. The largest glyph element (where `largest' can be
+// either `largest ascender' or `largest descender') then defines the
+// corresponding flat or round extremum.
+//
// For the latin auto-hinter, the overshoot should be larger than the
// reference for top zones, and vice versa for bottom zones.
//
@@ -229,6 +308,21 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN:
//
// If not set, take the minimum values.
//
+// Mutually exclusive with `LATIN_SUB_TOP'.
+//
+// LATIN_SUB_TOP
+// For all glyphs of a character cluster, compute the maximum flat
+// and round coordinate values of each component, then take the
+// smallest of the maximum values. The idea is to get the top of
+// subscript glyphs, as used in Khmer, for example. Note that
+// this mechanism doesn't work for ordinary ligatures.
+//
+// This flags indicates a secondary blue zone: It gets removed if
+// there is a non-LATIN_SUB_TOP blue zone at the same coordinate
+// value (after scaling).
+//
+// Mutually exclusive with `LATIN_TOP'.
+//
// LATIN_NEUTRAL
// Ignore round extrema and define the blue zone with flat values only.
// Both top and bottom of contours can match. This is useful for
@@ -264,11 +358,11 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN:
//
// Characters in a blue string are *not* automatically classified. Instead,
// first come the characters used for the overshoot value, then the
-// character `|', then the characters used for the reference value. The
-// blue zone is then set up by the mean values of all reference values and
-// all overshoot values, respectively. Both horizontal and vertical blue
-// zones (i.e., adjusting vertical and horizontal coordinate values,
-// respectively) are supported.
+// character `|', then the characters used for the reference value
+// (everything separated by space characters). The blue zone is then set up
+// by the mean values of all reference values and all overshoot values,
+// respectively. Both horizontal and vertical blue zones (i.e., adjusting
+// vertical and horizontal coordinate values, respectively) are supported.
//
// For the cjk auto-hinter, the overshoot should be smaller than the
// reference for top zones, and vice versa for bottom zones.
@@ -289,9 +383,10 @@ 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_ARAB
- { AF_BLUE_STRING_ARABIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_ARABIC_JOIN, 0 }
- { AF_BLUE_STRING_MAX, 0 }
+ { AF_BLUE_STRING_ARABIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_ARABIC_BOTTOM, 0 }
+ { AF_BLUE_STRING_ARABIC_JOIN, AF_BLUE_PROPERTY_LATIN_NEUTRAL }
+ { AF_BLUE_STRING_MAX, 0 }
AF_BLUE_STRINGSET_CYRL
{ AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
@@ -329,6 +424,30 @@ 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_KHMR
+ { AF_BLUE_STRING_KHMER_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
+ { AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP, AF_BLUE_PROPERTY_LATIN_SUB_TOP }
+ { AF_BLUE_STRING_KHMER_BOTTOM, 0 }
+ { AF_BLUE_STRING_KHMER_DESCENDER, 0 }
+ { AF_BLUE_STRING_KHMER_LARGE_DESCENDER, 0 }
+ { AF_BLUE_STRING_MAX, 0 }
+
+ AF_BLUE_STRINGSET_KHMS
+ { AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
+ { AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM, 0 }
+ { AF_BLUE_STRING_MAX, 0 }
+
+ AF_BLUE_STRINGSET_LAO
+ { AF_BLUE_STRING_LAO_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
+ { AF_BLUE_STRING_LAO_BOTTOM, 0 }
+ { AF_BLUE_STRING_LAO_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_LAO_LARGE_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_LAO_DESCENDER, 0 }
+ { AF_BLUE_STRING_MAX, 0 }
+
AF_BLUE_STRINGSET_LATN
{ AF_BLUE_STRING_LATIN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
{ AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM, 0 }
@@ -339,6 +458,34 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN:
{ AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0 }
{ AF_BLUE_STRING_MAX, 0 }
+ AF_BLUE_STRINGSET_LATB
+ { AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM, 0 }
+ { AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_LATIN_SUBS_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
+ { AF_BLUE_STRING_LATIN_SUBS_SMALL, 0 }
+ { AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER, 0 }
+ { AF_BLUE_STRING_MAX, 0 }
+
+ AF_BLUE_STRINGSET_LATP
+ { AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM, 0 }
+ { AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_LATIN_SUPS_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
+ { AF_BLUE_STRING_LATIN_SUPS_SMALL, 0 }
+ { AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER, 0 }
+ { AF_BLUE_STRING_MAX, 0 }
+
+ AF_BLUE_STRINGSET_MYMR
+ { AF_BLUE_STRING_MYANMAR_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
+ { AF_BLUE_STRING_MYANMAR_BOTTOM, 0 }
+ { AF_BLUE_STRING_MYANMAR_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_MYANMAR_DESCENDER, 0 }
+ { AF_BLUE_STRING_MAX, 0 }
+
AF_BLUE_STRINGSET_TELU
{ AF_BLUE_STRING_TELUGU_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
{ AF_BLUE_STRING_TELUGU_BOTTOM, 0 }
diff --git a/src/autofit/afblue.h b/src/autofit/afblue.h
index 94e33a9..34f90e9 100644
--- a/src/autofit/afblue.h
+++ b/src/autofit/afblue.h
@@ -28,32 +28,35 @@ FT_BEGIN_HEADER
/* an auxiliary macro to decode a UTF-8 character -- since we only use */
/* hard-coded, self-converted data, no error checking is performed */
-#define GET_UTF8_CHAR( ch, p ) \
- ch = (unsigned char)*p++; \
- if ( ch >= 0x80 ) \
- { \
- FT_UInt len; \
- \
- \
- if ( ch < 0xE0 ) \
- { \
- len = 1; \
- ch &= 0x1F; \
- } \
- else if ( ch < 0xF0 ) \
- { \
- len = 2; \
- ch &= 0x0F; \
- } \
- else \
- { \
- len = 3; \
- ch &= 0x07; \
- } \
- \
- for ( ; len > 0; len-- ) \
- ch = ( ch << 6 ) | ( *p++ & 0x3F ); \
- }
+#define GET_UTF8_CHAR( ch, p ) \
+ do \
+ { \
+ ch = (unsigned char)*p++; \
+ if ( ch >= 0x80 ) \
+ { \
+ FT_UInt len_; \
+ \
+ \
+ if ( ch < 0xE0 ) \
+ { \
+ len_ = 1; \
+ ch &= 0x1F; \
+ } \
+ else if ( ch < 0xF0 ) \
+ { \
+ len_ = 2; \
+ ch &= 0x0F; \
+ } \
+ else \
+ { \
+ len_ = 3; \
+ ch &= 0x07; \
+ } \
+ \
+ for ( ; len_ > 0; len_-- ) \
+ ch = ( ch << 6 ) | ( *p++ & 0x3F ); \
+ } \
+ } while ( 0 )
/*************************************************************************/
@@ -75,46 +78,73 @@ FT_BEGIN_HEADER
typedef enum AF_Blue_String_
{
AF_BLUE_STRING_ARABIC_TOP = 0,
- AF_BLUE_STRING_ARABIC_JOIN = 13,
- AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP = 24,
- AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM = 41,
- AF_BLUE_STRING_CYRILLIC_SMALL = 58,
- AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER = 75,
- AF_BLUE_STRING_DEVANAGARI_BASE = 82,
- AF_BLUE_STRING_DEVANAGARI_TOP = 107,
- AF_BLUE_STRING_DEVANAGARI_HEAD = 132,
- AF_BLUE_STRING_DEVANAGARI_BOTTOM = 157,
- AF_BLUE_STRING_GREEK_CAPITAL_TOP = 164,
- AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM = 179,
- AF_BLUE_STRING_GREEK_SMALL_BETA_TOP = 192,
- AF_BLUE_STRING_GREEK_SMALL = 205,
- AF_BLUE_STRING_GREEK_SMALL_DESCENDER = 222,
- AF_BLUE_STRING_HEBREW_TOP = 239,
- AF_BLUE_STRING_HEBREW_BOTTOM = 256,
- AF_BLUE_STRING_HEBREW_DESCENDER = 269,
- AF_BLUE_STRING_LATIN_CAPITAL_TOP = 280,
- AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM = 289,
- AF_BLUE_STRING_LATIN_SMALL_F_TOP = 298,
- AF_BLUE_STRING_LATIN_SMALL = 306,
- AF_BLUE_STRING_LATIN_SMALL_DESCENDER = 314,
- AF_BLUE_STRING_TELUGU_TOP = 320,
- AF_BLUE_STRING_TELUGU_BOTTOM = 342,
- AF_BLUE_STRING_THAI_TOP = 364,
- AF_BLUE_STRING_THAI_BOTTOM = 383,
- AF_BLUE_STRING_THAI_ASCENDER = 405,
- AF_BLUE_STRING_THAI_LARGE_ASCENDER = 415,
- AF_BLUE_STRING_THAI_DESCENDER = 425,
- AF_BLUE_STRING_THAI_LARGE_DESCENDER = 438,
- AF_BLUE_STRING_THAI_DIGIT_TOP = 445,
- af_blue_1_1 = 454,
+ AF_BLUE_STRING_ARABIC_BOTTOM = 18,
+ AF_BLUE_STRING_ARABIC_JOIN = 33,
+ AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP = 36,
+ AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM = 60,
+ AF_BLUE_STRING_CYRILLIC_SMALL = 84,
+ AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER = 108,
+ AF_BLUE_STRING_DEVANAGARI_BASE = 117,
+ AF_BLUE_STRING_DEVANAGARI_TOP = 149,
+ AF_BLUE_STRING_DEVANAGARI_HEAD = 181,
+ AF_BLUE_STRING_DEVANAGARI_BOTTOM = 213,
+ AF_BLUE_STRING_GREEK_CAPITAL_TOP = 221,
+ AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM = 242,
+ AF_BLUE_STRING_GREEK_SMALL_BETA_TOP = 260,
+ AF_BLUE_STRING_GREEK_SMALL = 278,
+ AF_BLUE_STRING_GREEK_SMALL_DESCENDER = 302,
+ AF_BLUE_STRING_HEBREW_TOP = 326,
+ AF_BLUE_STRING_HEBREW_BOTTOM = 350,
+ AF_BLUE_STRING_HEBREW_DESCENDER = 368,
+ AF_BLUE_STRING_KHMER_TOP = 383,
+ AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP = 407,
+ AF_BLUE_STRING_KHMER_BOTTOM = 447,
+ AF_BLUE_STRING_KHMER_DESCENDER = 479,
+ AF_BLUE_STRING_KHMER_LARGE_DESCENDER = 513,
+ AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP = 600,
+ AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM = 608,
+ AF_BLUE_STRING_LAO_TOP = 616,
+ AF_BLUE_STRING_LAO_BOTTOM = 648,
+ AF_BLUE_STRING_LAO_ASCENDER = 680,
+ AF_BLUE_STRING_LAO_LARGE_ASCENDER = 696,
+ AF_BLUE_STRING_LAO_DESCENDER = 708,
+ AF_BLUE_STRING_LATIN_CAPITAL_TOP = 732,
+ AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM = 748,
+ AF_BLUE_STRING_LATIN_SMALL_F_TOP = 764,
+ AF_BLUE_STRING_LATIN_SMALL = 778,
+ AF_BLUE_STRING_LATIN_SMALL_DESCENDER = 792,
+ AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP = 802,
+ AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM = 822,
+ AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP = 842,
+ AF_BLUE_STRING_LATIN_SUBS_SMALL = 862,
+ AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER = 898,
+ AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP = 918,
+ AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM = 949,
+ AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP = 978,
+ AF_BLUE_STRING_LATIN_SUPS_SMALL = 1004,
+ AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER = 1029,
+ AF_BLUE_STRING_MYANMAR_TOP = 1040,
+ AF_BLUE_STRING_MYANMAR_BOTTOM = 1072,
+ AF_BLUE_STRING_MYANMAR_ASCENDER = 1104,
+ AF_BLUE_STRING_MYANMAR_DESCENDER = 1132,
+ AF_BLUE_STRING_TELUGU_TOP = 1164,
+ AF_BLUE_STRING_TELUGU_BOTTOM = 1192,
+ AF_BLUE_STRING_THAI_TOP = 1220,
+ AF_BLUE_STRING_THAI_BOTTOM = 1244,
+ AF_BLUE_STRING_THAI_ASCENDER = 1272,
+ AF_BLUE_STRING_THAI_LARGE_ASCENDER = 1284,
+ AF_BLUE_STRING_THAI_DESCENDER = 1296,
+ AF_BLUE_STRING_THAI_LARGE_DESCENDER = 1312,
+ AF_BLUE_STRING_THAI_DIGIT_TOP = 1320,
+ af_blue_1_1 = 1331,
#ifdef AF_CONFIG_OPTION_CJK
AF_BLUE_STRING_CJK_TOP = af_blue_1_1 + 1,
- AF_BLUE_STRING_CJK_BOTTOM = af_blue_1_1 + 153,
- af_blue_1_1_1 = af_blue_1_1 + 304,
+ AF_BLUE_STRING_CJK_BOTTOM = af_blue_1_1 + 203,
+ af_blue_1_1_1 = af_blue_1_1 + 404,
#ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
AF_BLUE_STRING_CJK_LEFT = af_blue_1_1_1 + 1,
- AF_BLUE_STRING_CJK_RIGHT = af_blue_1_1_1 + 153,
- af_blue_1_1_2 = af_blue_1_1_1 + 304,
+ AF_BLUE_STRING_CJK_RIGHT = af_blue_1_1_1 + 204,
+ af_blue_1_1_2 = af_blue_1_1_1 + 405,
#else
af_blue_1_1_2 = af_blue_1_1_1 + 0,
#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
@@ -148,9 +178,10 @@ FT_BEGIN_HEADER
/* blue string can't be used in more than a single writing system, which */
/* is a safe bet. */
#define AF_BLUE_PROPERTY_LATIN_TOP ( 1U << 0 ) /* must have value 1 */
-#define AF_BLUE_PROPERTY_LATIN_NEUTRAL ( 1U << 1 )
-#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1U << 2 )
-#define AF_BLUE_PROPERTY_LATIN_LONG ( 1U << 3 )
+#define AF_BLUE_PROPERTY_LATIN_SUB_TOP ( 1U << 1 )
+#define AF_BLUE_PROPERTY_LATIN_NEUTRAL ( 1U << 2 )
+#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1U << 3 )
+#define AF_BLUE_PROPERTY_LATIN_LONG ( 1U << 4 )
#define AF_BLUE_PROPERTY_CJK_TOP ( 1U << 0 ) /* must have value 1 */
#define AF_BLUE_PROPERTY_CJK_HORIZ ( 1U << 1 ) /* must have value 2 */
@@ -165,14 +196,20 @@ FT_BEGIN_HEADER
typedef enum AF_Blue_Stringset_
{
AF_BLUE_STRINGSET_ARAB = 0,
- AF_BLUE_STRINGSET_CYRL = 3,
- AF_BLUE_STRINGSET_DEVA = 9,
- AF_BLUE_STRINGSET_GREK = 15,
- AF_BLUE_STRINGSET_HEBR = 22,
- AF_BLUE_STRINGSET_LATN = 26,
- AF_BLUE_STRINGSET_TELU = 33,
- AF_BLUE_STRINGSET_THAI = 36,
- af_blue_2_1 = 44,
+ AF_BLUE_STRINGSET_CYRL = 4,
+ AF_BLUE_STRINGSET_DEVA = 10,
+ AF_BLUE_STRINGSET_GREK = 16,
+ AF_BLUE_STRINGSET_HEBR = 23,
+ AF_BLUE_STRINGSET_KHMR = 27,
+ AF_BLUE_STRINGSET_KHMS = 33,
+ AF_BLUE_STRINGSET_LAO = 36,
+ AF_BLUE_STRINGSET_LATN = 42,
+ AF_BLUE_STRINGSET_LATB = 49,
+ AF_BLUE_STRINGSET_LATP = 56,
+ AF_BLUE_STRINGSET_MYMR = 63,
+ AF_BLUE_STRINGSET_TELU = 68,
+ AF_BLUE_STRINGSET_THAI = 71,
+ af_blue_2_1 = 79,
#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/src/autofit/afblue.hin b/src/autofit/afblue.hin
index ad43fe6..1eb9172 100644
--- a/src/autofit/afblue.hin
+++ b/src/autofit/afblue.hin
@@ -25,32 +25,35 @@ FT_BEGIN_HEADER
/* an auxiliary macro to decode a UTF-8 character -- since we only use */
/* hard-coded, self-converted data, no error checking is performed */
-#define GET_UTF8_CHAR( ch, p ) \
- ch = (unsigned char)*p++; \
- if ( ch >= 0x80 ) \
- { \
- FT_UInt len; \
- \
- \
- if ( ch < 0xE0 ) \
- { \
- len = 1; \
- ch &= 0x1F; \
- } \
- else if ( ch < 0xF0 ) \
- { \
- len = 2; \
- ch &= 0x0F; \
- } \
- else \
- { \
- len = 3; \
- ch &= 0x07; \
- } \
- \
- for ( ; len > 0; len-- ) \
- ch = ( ch << 6 ) | ( *p++ & 0x3F ); \
- }
+#define GET_UTF8_CHAR( ch, p ) \
+ do \
+ { \
+ ch = (unsigned char)*p++; \
+ if ( ch >= 0x80 ) \
+ { \
+ FT_UInt len_; \
+ \
+ \
+ if ( ch < 0xE0 ) \
+ { \
+ len_ = 1; \
+ ch &= 0x1F; \
+ } \
+ else if ( ch < 0xF0 ) \
+ { \
+ len_ = 2; \
+ ch &= 0x0F; \
+ } \
+ else \
+ { \
+ len_ = 3; \
+ ch &= 0x07; \
+ } \
+ \
+ for ( ; len_ > 0; len_-- ) \
+ ch = ( ch << 6 ) | ( *p++ & 0x3F ); \
+ } \
+ } while ( 0 )
/*************************************************************************/
@@ -97,9 +100,10 @@ FT_BEGIN_HEADER
/* blue string can't be used in more than a single writing system, which */
/* is a safe bet. */
#define AF_BLUE_PROPERTY_LATIN_TOP ( 1U << 0 ) /* must have value 1 */
-#define AF_BLUE_PROPERTY_LATIN_NEUTRAL ( 1U << 1 )
-#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1U << 2 )
-#define AF_BLUE_PROPERTY_LATIN_LONG ( 1U << 3 )
+#define AF_BLUE_PROPERTY_LATIN_SUB_TOP ( 1U << 1 )
+#define AF_BLUE_PROPERTY_LATIN_NEUTRAL ( 1U << 2 )
+#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1U << 3 )
+#define AF_BLUE_PROPERTY_LATIN_LONG ( 1U << 4 )
#define AF_BLUE_PROPERTY_CJK_TOP ( 1U << 0 ) /* must have value 1 */
#define AF_BLUE_PROPERTY_CJK_HORIZ ( 1U << 1 ) /* must have value 2 */
diff --git a/src/autofit/afcjk.c b/src/autofit/afcjk.c
index 905408b..73d75ae 100644
--- a/src/autofit/afcjk.c
+++ b/src/autofit/afcjk.c
@@ -88,7 +88,6 @@
{
FT_Error error;
FT_ULong glyph_index;
- FT_Long y_offset;
int dim;
AF_CJKMetricsRec dummy[1];
AF_Scaler scaler = &dummy->root.scaler;
@@ -101,45 +100,61 @@
AF_ScriptClass script_class = AF_SCRIPT_CLASSES_GET
[style_class->script];
- FT_UInt32 standard_char;
+ void* shaper_buf;
+ const char* p;
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_ULong ch;
+#endif
- standard_char = script_class->standard_char1;
- af_get_char_index( &metrics->root,
- standard_char,
- &glyph_index,
- &y_offset );
- if ( !glyph_index )
+ p = script_class->standard_charstring;
+ shaper_buf = af_shaper_buf_create( face );
+
+ /* We check a list of standard characters. The first match wins. */
+
+ glyph_index = 0;
+ while ( *p )
{
- if ( script_class->standard_char2 )
- {
- standard_char = script_class->standard_char2;
- af_get_char_index( &metrics->root,
- standard_char,
- &glyph_index,
- &y_offset );
- if ( !glyph_index )
- {
- if ( script_class->standard_char3 )
- {
- standard_char = script_class->standard_char3;
- af_get_char_index( &metrics->root,
- standard_char,
- &glyph_index,
- &y_offset );
- if ( !glyph_index )
- goto Exit;
- }
- else
- goto Exit;
- }
- }
- else
- goto Exit;
+ unsigned int num_idx;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ const char* p_old;
+#endif
+
+
+ while ( *p == ' ' )
+ p++;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ p_old = p;
+ GET_UTF8_CHAR( ch, p_old );
+#endif
+
+ /* reject input that maps to more than a single glyph */
+ p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
+ if ( num_idx > 1 )
+ continue;
+
+ /* otherwise exit loop if we have a result */
+ glyph_index = af_shaper_get_elem( &metrics->root,
+ shaper_buf,
+ 0,
+ NULL,
+ NULL );
+ if ( glyph_index )
+ break;
}
+ af_shaper_buf_destroy( face, shaper_buf );
+
+ if ( !glyph_index )
+ goto Exit;
+
+ if ( !glyph_index )
+ goto Exit;
+
FT_TRACE5(( "standard character: U+%04lX (glyph index %d)\n",
- standard_char, glyph_index ));
+ ch, glyph_index ));
error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
if ( error || face->glyph->outline.n_points <= 0 )
@@ -177,6 +192,12 @@
if ( error )
goto Exit;
+ /*
+ * We assume that the glyphs selected for the stem width
+ * computation are `featureless' enough so that the linking
+ * algorithm works fine without adjustments of its scoring
+ * function.
+ */
af_latin_hints_link_segments( hints,
0,
NULL,
@@ -275,6 +296,8 @@
AF_Blue_Stringset bss = sc->blue_stringset;
const AF_Blue_StringRec* bs = &af_blue_stringsets[bss];
+ void* shaper_buf;
+
/* we walk over the blue character strings as specified in the */
/* style's entry in the `af_blue_stringset' array, computing its */
@@ -284,6 +307,8 @@
"==========================\n"
"\n" ));
+ shaper_buf = af_shaper_buf_create( face );
+
for ( ; bs->string != AF_BLUE_STRING_MAX; bs++ )
{
const char* p = &af_blue_strings[bs->string];
@@ -322,26 +347,47 @@
while ( *p )
{
- FT_ULong ch;
FT_ULong glyph_index;
- FT_Long y_offset;
FT_Pos best_pos; /* same as points.y or points.x, resp. */
FT_Int best_point;
FT_Vector* points;
+ unsigned int num_idx;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ const char* p_old;
+ FT_ULong ch;
+#endif
+
- GET_UTF8_CHAR( ch, p );
+ while ( *p == ' ' )
+ p++;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ p_old = p;
+ GET_UTF8_CHAR( ch, p_old );
+#endif
/* switch to characters that define flat values */
- if ( ch == '|' )
+ if ( *p == '|' )
{
fill = 0;
FT_TRACE5(( " [reference values]\n" ));
+ p++;
continue;
}
+ /* reject input that maps to more than a single glyph */
+ p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
+ if ( num_idx > 1 )
+ continue;
+
/* load the character in the face -- skip unknown or empty ones */
- af_get_char_index( &metrics->root, ch, &glyph_index, &y_offset );
+ glyph_index = af_shaper_get_elem( &metrics->root,
+ shaper_buf,
+ 0,
+ NULL,
+ NULL );
if ( glyph_index == 0 )
{
FT_TRACE5(( " U+%04lX unavailable\n", ch ));
@@ -350,9 +396,9 @@
error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
outline = face->glyph->outline;
- if ( error || outline.n_points <= 0 )
+ if ( error || outline.n_points <= 2 )
{
- FT_TRACE5(( " U+%04lX contains no outlines\n", ch ));
+ FT_TRACE5(( " U+%04lX contains no (usable) outlines\n", ch ));
continue;
}
@@ -431,7 +477,8 @@
fills[num_fills++] = best_pos;
else
flats[num_flats++] = best_pos;
- }
+
+ } /* end while loop */
if ( num_flats == 0 && num_fills == 0 )
{
@@ -498,7 +545,10 @@
FT_TRACE5(( " -> reference = %ld\n"
" overshoot = %ld\n",
*blue_ref, *blue_shoot ));
- }
+
+ } /* end for loop */
+
+ af_shaper_buf_destroy( face, shaper_buf );
FT_TRACE5(( "\n" ));
@@ -512,27 +562,36 @@
af_cjk_metrics_check_digits( AF_CJKMetrics metrics,
FT_Face face )
{
- FT_UInt i;
FT_Bool started = 0, same_width = 1;
FT_Fixed advance, old_advance = 0;
+ void* shaper_buf;
- /* digit `0' is 0x30 in all supported charmaps */
- for ( i = 0x30; i <= 0x39; i++ )
+ /* in all supported charmaps, digits have character codes 0x30-0x39 */
+ const char digits[] = "0 1 2 3 4 5 6 7 8 9";
+ const char* p;
+
+
+ p = digits;
+ shaper_buf = af_shaper_buf_create( face );
+
+ while ( *p )
{
- FT_ULong glyph_index;
- FT_Long y_offset;
+ FT_ULong glyph_index;
+ unsigned int num_idx;
- af_get_char_index( &metrics->root, i, &glyph_index, &y_offset );
- if ( glyph_index == 0 )
+ /* reject input that maps to more than a single glyph */
+ p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
+ if ( num_idx > 1 )
continue;
- if ( FT_Get_Advance( face, glyph_index,
- FT_LOAD_NO_SCALE |
- FT_LOAD_NO_HINTING |
- FT_LOAD_IGNORE_TRANSFORM,
- &advance ) )
+ glyph_index = af_shaper_get_elem( &metrics->root,
+ shaper_buf,
+ 0,
+ &advance,
+ NULL );
+ if ( !glyph_index )
continue;
if ( started )
@@ -550,6 +609,8 @@
}
}
+ af_shaper_buf_destroy( face, shaper_buf );
+
metrics->root.digits_have_same_width = same_width;
}
@@ -688,6 +749,22 @@
}
+ /* Extract standard_width from writing system/script specific */
+ /* metrics class. */
+
+ FT_LOCAL_DEF( void )
+ af_cjk_get_standard_widths( AF_CJKMetrics metrics,
+ FT_Pos* stdHW,
+ FT_Pos* stdVW )
+ {
+ if ( stdHW )
+ *stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width;
+
+ if ( stdVW )
+ *stdVW = metrics->axis[AF_DIMENSION_HORZ].standard_width;
+ }
+
+
/*************************************************************************/
/*************************************************************************/
/***** *****/
@@ -2181,7 +2258,8 @@
/* Apply the complete hinting algorithm to a CJK glyph. */
FT_LOCAL_DEF( FT_Error )
- af_cjk_hints_apply( AF_GlyphHints hints,
+ af_cjk_hints_apply( FT_UInt glyph_index,
+ AF_GlyphHints hints,
FT_Outline* outline,
AF_CJKMetrics metrics )
{
@@ -2189,6 +2267,7 @@
int dim;
FT_UNUSED( metrics );
+ FT_UNUSED( glyph_index );
error = af_glyph_hints_reload( hints, outline );
@@ -2278,6 +2357,7 @@
(AF_WritingSystem_InitMetricsFunc) af_cjk_metrics_init,
(AF_WritingSystem_ScaleMetricsFunc)af_cjk_metrics_scale,
(AF_WritingSystem_DoneMetricsFunc) NULL,
+ (AF_WritingSystem_GetStdWidthsFunc)af_cjk_get_standard_widths,
(AF_WritingSystem_InitHintsFunc) af_cjk_hints_init,
(AF_WritingSystem_ApplyHintsFunc) af_cjk_hints_apply
@@ -2297,6 +2377,7 @@
(AF_WritingSystem_InitMetricsFunc) NULL,
(AF_WritingSystem_ScaleMetricsFunc)NULL,
(AF_WritingSystem_DoneMetricsFunc) NULL,
+ (AF_WritingSystem_GetStdWidthsFunc)NULL,
(AF_WritingSystem_InitHintsFunc) NULL,
(AF_WritingSystem_ApplyHintsFunc) NULL
diff --git a/src/autofit/afcjk.h b/src/autofit/afcjk.h
index bfd11f2..e395e74 100644
--- a/src/autofit/afcjk.h
+++ b/src/autofit/afcjk.h
@@ -115,7 +115,8 @@ FT_BEGIN_HEADER
AF_CJKMetrics metrics );
FT_LOCAL( FT_Error )
- af_cjk_hints_apply( AF_GlyphHints hints,
+ af_cjk_hints_apply( FT_UInt glyph_index,
+ AF_GlyphHints hints,
FT_Outline* outline,
AF_CJKMetrics metrics );
diff --git a/src/autofit/afdummy.c b/src/autofit/afdummy.c
index 03ca25f..9142c78 100644
--- a/src/autofit/afdummy.c
+++ b/src/autofit/afdummy.c
@@ -38,11 +38,14 @@
static FT_Error
- af_dummy_hints_apply( AF_GlyphHints hints,
+ af_dummy_hints_apply( FT_UInt glyph_index,
+ AF_GlyphHints hints,
FT_Outline* outline )
{
FT_Error error;
+ FT_UNUSED( glyph_index );
+
error = af_glyph_hints_reload( hints, outline );
if ( !error )
@@ -62,6 +65,7 @@
(AF_WritingSystem_InitMetricsFunc) NULL,
(AF_WritingSystem_ScaleMetricsFunc)NULL,
(AF_WritingSystem_DoneMetricsFunc) NULL,
+ (AF_WritingSystem_GetStdWidthsFunc)NULL,
(AF_WritingSystem_InitHintsFunc) af_dummy_hints_init,
(AF_WritingSystem_ApplyHintsFunc) af_dummy_hints_apply
diff --git a/src/autofit/afglobal.c b/src/autofit/afglobal.c
index 64b9293..3223358 100644
--- a/src/autofit/afglobal.c
+++ b/src/autofit/afglobal.c
@@ -18,7 +18,7 @@
#include "afglobal.h"
#include "afranges.h"
-#include "hbshim.h"
+#include "afshaper.h"
#include FT_INTERNAL_DEBUG_H
@@ -42,12 +42,13 @@
#undef SCRIPT
-#define SCRIPT( s, S, d, h, sc1, sc2, sc3 ) \
+#define SCRIPT( s, S, d, h, ss ) \
AF_DEFINE_SCRIPT_CLASS( \
af_ ## s ## _script_class, \
AF_SCRIPT_ ## S, \
af_ ## s ## _uniranges, \
- sc1, sc2, sc3 )
+ af_ ## s ## _nonbase_uniranges, \
+ ss )
#include "afscript.h"
@@ -82,7 +83,7 @@
#undef SCRIPT
-#define SCRIPT( s, S, d, h, sc1, sc2, sc3 ) \
+#define SCRIPT( s, S, d, h, ss ) \
&af_ ## s ## _script_class,
FT_LOCAL_ARRAY_DEF( AF_ScriptClass )
@@ -135,16 +136,15 @@
FT_Error error;
FT_Face face = globals->face;
FT_CharMap old_charmap = face->charmap;
- FT_Byte* gstyles = globals->glyph_styles;
+ FT_UShort* gstyles = globals->glyph_styles;
FT_UInt ss;
FT_UInt i;
FT_UInt dflt = ~0U; /* a non-valid value */
/* the value AF_STYLE_UNASSIGNED means `uncovered glyph' */
- FT_MEM_SET( globals->glyph_styles,
- AF_STYLE_UNASSIGNED,
- globals->glyph_count );
+ for ( i = 0; i < (FT_UInt)globals->glyph_count; i++ )
+ gstyles[i] = AF_STYLE_UNASSIGNED;
error = FT_Select_Charmap( face, FT_ENCODING_UNICODE );
if ( error )
@@ -190,10 +190,10 @@
gindex = FT_Get_Char_Index( face, charcode );
- if ( gindex != 0 &&
- gindex < (FT_ULong)globals->glyph_count &&
- gstyles[gindex] == AF_STYLE_UNASSIGNED )
- gstyles[gindex] = (FT_Byte)ss;
+ if ( gindex != 0 &&
+ gindex < (FT_ULong)globals->glyph_count &&
+ ( gstyles[gindex] & AF_STYLE_MASK ) == AF_STYLE_UNASSIGNED )
+ gstyles[gindex] = (FT_UShort)ss;
for (;;)
{
@@ -202,21 +202,50 @@
if ( gindex == 0 || charcode > range->last )
break;
- if ( gindex < (FT_ULong)globals->glyph_count &&
- gstyles[gindex] == AF_STYLE_UNASSIGNED )
- gstyles[gindex] = (FT_Byte)ss;
+ if ( gindex < (FT_ULong)globals->glyph_count &&
+ ( gstyles[gindex] & AF_STYLE_MASK ) == AF_STYLE_UNASSIGNED )
+ gstyles[gindex] = (FT_UShort)ss;
+ }
+ }
+
+ /* do the same for the script's non-base characters */
+ for ( range = script_class->script_uni_nonbase_ranges;
+ range->first != 0;
+ range++ )
+ {
+ FT_ULong charcode = range->first;
+ FT_UInt gindex;
+
+
+ gindex = FT_Get_Char_Index( face, charcode );
+
+ if ( gindex != 0 &&
+ gindex < (FT_ULong)globals->glyph_count &&
+ ( gstyles[gindex] & AF_STYLE_MASK ) == (FT_UShort)ss )
+ gstyles[gindex] |= AF_NONBASE;
+
+ for (;;)
+ {
+ charcode = FT_Get_Next_Char( face, charcode, &gindex );
+
+ if ( gindex == 0 || charcode > range->last )
+ break;
+
+ if ( gindex < (FT_ULong)globals->glyph_count &&
+ ( gstyles[gindex] & AF_STYLE_MASK ) == (FT_UShort)ss )
+ gstyles[gindex] |= AF_NONBASE;
}
}
}
else
{
/* get glyphs not directly addressable by cmap */
- af_get_coverage( globals, style_class, gstyles );
+ af_shaper_get_coverage( globals, style_class, gstyles );
}
}
/* handle the default OpenType features of the default script ... */
- af_get_coverage( globals, AF_STYLE_CLASSES_GET[dflt], gstyles );
+ af_shaper_get_coverage( globals, AF_STYLE_CLASSES_GET[dflt], gstyles );
/* ... and the remaining default OpenType features */
for ( ss = 0; AF_STYLE_CLASSES_GET[ss]; ss++ )
@@ -225,7 +254,7 @@
if ( ss != dflt && style_class->coverage == AF_COVERAGE_DEFAULT )
- af_get_coverage( globals, style_class, gstyles );
+ af_shaper_get_coverage( globals, style_class, gstyles );
}
/* mark ASCII digits */
@@ -250,9 +279,9 @@
for ( nn = 0; nn < globals->glyph_count; nn++ )
{
- if ( ( gstyles[nn] & ~AF_DIGIT ) == AF_STYLE_UNASSIGNED )
+ if ( ( gstyles[nn] & AF_STYLE_MASK ) == AF_STYLE_UNASSIGNED )
{
- gstyles[nn] &= ~AF_STYLE_UNASSIGNED;
+ gstyles[nn] &= ~AF_STYLE_MASK;
gstyles[nn] |= globals->module->fallback_style;
}
}
@@ -276,7 +305,7 @@
for ( idx = 0; idx < globals->glyph_count; idx++ )
{
- if ( ( gstyles[idx] & ~AF_DIGIT ) == style_class->style )
+ if ( ( gstyles[idx] & AF_STYLE_MASK ) == style_class->style )
{
if ( !( count % 10 ) )
FT_TRACE4(( " " ));
@@ -314,18 +343,28 @@
memory = face->memory;
+ /* we allocate an AF_FaceGlobals structure together */
+ /* with the glyph_styles array */
if ( FT_ALLOC( globals,
sizeof ( *globals ) +
- (FT_ULong)face->num_glyphs * sizeof ( FT_Byte ) ) )
+ (FT_ULong)face->num_glyphs * sizeof ( FT_UShort ) ) )
goto Exit;
- globals->face = face;
- globals->glyph_count = face->num_glyphs;
- globals->glyph_styles = (FT_Byte*)( globals + 1 );
- globals->module = module;
+ globals->face = face;
+ globals->glyph_count = face->num_glyphs;
+ /* right after the globals structure come the glyph styles */
+ globals->glyph_styles = (FT_UShort*)( globals + 1 );
+ globals->module = module;
+ globals->stem_darkening_for_ppem = 0;
+ globals->darken_x = 0;
+ globals->darken_y = 0;
+ globals->standard_vertical_width = 0;
+ globals->standard_horizontal_width = 0;
+ globals->scale_down_factor = 0;
#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
globals->hb_font = hb_ft_font_create( face, NULL );
+ globals->hb_buf = hb_buffer_create();
#endif
error = af_face_globals_compute_style_coverage( globals );
@@ -372,11 +411,21 @@
#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
- globals->glyph_count = 0;
- globals->glyph_styles = NULL; /* no need to free this one! */
- globals->face = NULL;
+ globals->glyph_count = 0;
+ globals->stem_darkening_for_ppem = 0;
+ globals->darken_x = 0;
+ globals->darken_y = 0;
+ globals->standard_vertical_width = 0;
+ globals->standard_horizontal_width = 0;
+ globals->scale_down_factor = 0;
+ /* no need to free this one! */
+ globals->glyph_styles = NULL;
+ globals->face = NULL;
FT_FREE( globals );
}
diff --git a/src/autofit/afglobal.h b/src/autofit/afglobal.h
index 9bbb687..5b4e439 100644
--- a/src/autofit/afglobal.h
+++ b/src/autofit/afglobal.h
@@ -23,7 +23,7 @@
#include "aftypes.h"
#include "afmodule.h"
-#include "hbshim.h"
+#include "afshaper.h"
FT_BEGIN_HEADER
@@ -34,7 +34,7 @@ FT_BEGIN_HEADER
#undef SCRIPT
-#define SCRIPT( s, S, d, h, sc1, sc2, sc3 ) \
+#define SCRIPT( s, S, d, h, ss ) \
AF_DECLARE_SCRIPT_CLASS( af_ ## s ## _script_class )
#include "afscript.h"
@@ -72,10 +72,16 @@ FT_BEGIN_HEADER
#endif
/* default script for OpenType; ignored if HarfBuzz isn't used */
#define AF_SCRIPT_DEFAULT AF_SCRIPT_LATN
- /* a bit mask indicating an uncovered glyph */
-#define AF_STYLE_UNASSIGNED 0x7F
- /* if this flag is set, we have an ASCII digit */
-#define AF_DIGIT 0x80
+
+ /* a bit mask for AF_DIGIT and AF_NONBASE */
+#define AF_STYLE_MASK 0x3FFF
+ /* an uncovered glyph */
+#define AF_STYLE_UNASSIGNED AF_STYLE_MASK
+
+ /* if this flag is set, we have an ASCII digit */
+#define AF_DIGIT 0x8000U
+ /* if this flag is set, we have a non-base character */
+#define AF_NONBASE 0x4000U
/* `increase-x-height' property */
#define AF_PROP_INCREASE_X_HEIGHT_MIN 6
@@ -100,10 +106,11 @@ FT_BEGIN_HEADER
{
FT_Face face;
FT_Long glyph_count; /* same as face->num_glyphs */
- FT_Byte* glyph_styles;
+ FT_UShort* glyph_styles;
#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
hb_font_t* hb_font;
+ hb_buffer_t* hb_buf; /* for feature comparison */
#endif
/* per-face auto-hinter properties */
@@ -111,6 +118,22 @@ FT_BEGIN_HEADER
AF_StyleMetrics metrics[AF_STYLE_MAX];
+ /* Compute darkening amount once per size. Use this to check whether */
+ /* darken_{x,y} needs to be recomputed. */
+ FT_UShort stem_darkening_for_ppem;
+ /* Copy from e.g. AF_LatinMetrics.axis[AF_DIMENSION_HORZ] */
+ /* to compute the darkening amount. */
+ FT_Pos standard_vertical_width;
+ /* Copy from e.g. AF_LatinMetrics.axis[AF_DIMENSION_VERT] */
+ /* to compute the darkening amount. */
+ FT_Pos standard_horizontal_width;
+ /* The actual amount to darken a glyph along the X axis. */
+ FT_Pos darken_x;
+ /* The actual amount to darken a glyph along the Y axis. */
+ FT_Pos darken_y;
+ /* Amount to scale down by to keep emboldened points */
+ /* on the Y-axis in pre-computed blue zones. */
+ FT_Fixed scale_down_factor;
AF_Module module; /* to access global properties */
} AF_FaceGlobalsRec;
diff --git a/src/autofit/afhints.c b/src/autofit/afhints.c
index 37482eb..56c8220 100644
--- a/src/autofit/afhints.c
+++ b/src/autofit/afhints.c
@@ -219,6 +219,82 @@
#define AF_INDEX_NUM( ptr, base ) (int)( (ptr) ? ( (ptr) - (base) ) : -1 )
+ static char*
+ af_print_idx( char* p,
+ int idx )
+ {
+ if ( idx == -1 )
+ {
+ p[0] = '-';
+ p[1] = '-';
+ p[2] = '\0';
+ }
+ else
+ ft_sprintf( p, "%d", idx );
+
+ return p;
+ }
+
+
+ static int
+ af_get_segment_index( AF_GlyphHints hints,
+ int point_idx,
+ int dimension )
+ {
+ AF_AxisHints axis = &hints->axis[dimension];
+ AF_Point point = hints->points + point_idx;
+ AF_Segment segments = axis->segments;
+ AF_Segment limit = segments + axis->num_segments;
+ AF_Segment segment;
+
+
+ for ( segment = segments; segment < limit; segment++ )
+ {
+ if ( segment->first <= segment->last )
+ {
+ if ( point >= segment->first && point <= segment->last )
+ break;
+ }
+ else
+ {
+ AF_Point p = segment->first;
+
+
+ for (;;)
+ {
+ if ( point == p )
+ goto Exit;
+
+ if ( p == segment->last )
+ break;
+
+ p = p->next;
+ }
+ }
+ }
+
+ Exit:
+ if ( segment == limit )
+ return -1;
+
+ return (int)( segment - segments );
+ }
+
+
+ static int
+ af_get_edge_index( AF_GlyphHints hints,
+ int segment_idx,
+ int dimension )
+ {
+ AF_AxisHints axis = &hints->axis[dimension];
+ AF_Edge edges = axis->edges;
+ AF_Segment segment = axis->segments + segment_idx;
+
+
+ return segment_idx == -1 ? -1 : AF_INDEX_NUM( segment->edge, edges );
+ }
+
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -234,22 +310,39 @@
AF_DUMP(( "Table of points:\n" ));
if ( hints->num_points )
- AF_DUMP(( " [ index | xorg | yorg | xscale | yscale"
- " | xfit | yfit | flags ]\n" ));
+ AF_DUMP(( " index hedge hseg vedge vseg flags"
+ " xorg yorg xscale yscale xfit yfit\n" ));
else
AF_DUMP(( " (none)\n" ));
for ( point = points; point < limit; point++ )
- AF_DUMP(( " [ %5d | %5d | %5d | %6.2f | %6.2f"
- " | %5.2f | %5.2f | %c ]\n",
- AF_INDEX_NUM( point, points ),
+ {
+ int point_idx = AF_INDEX_NUM( point, points );
+ int segment_idx_0 = af_get_segment_index( hints, point_idx, 0 );
+ int segment_idx_1 = af_get_segment_index( hints, point_idx, 1 );
+
+ char buf1[16], buf2[16], buf3[16], buf4[16];
+
+
+ AF_DUMP(( " %5d %5s %5s %5s %5s %s "
+ " %5d %5d %7.2f %7.2f %7.2f %7.2f\n",
+ point_idx,
+ af_print_idx( buf1,
+ af_get_edge_index( hints, segment_idx_1, 1 ) ),
+ af_print_idx( buf2, segment_idx_1 ),
+ af_print_idx( buf3,
+ af_get_edge_index( hints, segment_idx_0, 0 ) ),
+ af_print_idx( buf4, segment_idx_0 ),
+ ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) ? "weak"
+ : " -- ",
+
point->fx,
point->fy,
point->ox / 64.0,
point->oy / 64.0,
point->x / 64.0,
- point->y / 64.0,
- ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) ? 'w' : ' '));
+ point->y / 64.0 ));
+ }
AF_DUMP(( "\n" ));
}
#ifdef __cplusplus
@@ -306,21 +399,23 @@
AF_Segment limit = segments + axis->num_segments;
AF_Segment seg;
+ char buf1[16], buf2[16], buf3[16];
+
AF_DUMP(( "Table of %s segments:\n",
dimension == AF_DIMENSION_HORZ ? "vertical"
: "horizontal" ));
if ( axis->num_segments )
- AF_DUMP(( " [ index | pos | dir | from"
- " | to | link | serif | edge"
- " | height | extra | flags ]\n" ));
+ AF_DUMP(( " index pos dir from to"
+ " link serif edge"
+ " height extra flags\n" ));
else
AF_DUMP(( " (none)\n" ));
for ( seg = segments; seg < limit; seg++ )
- AF_DUMP(( " [ %5d | %5.2g | %5s | %4d"
- " | %4d | %4d | %5d | %4d"
- " | %6d | %5d | %11s ]\n",
+ AF_DUMP(( " %5d %5.2g %5s %4d %4d"
+ " %4s %5s %4s"
+ " %6d %5d %11s\n",
AF_INDEX_NUM( seg, segments ),
dimension == AF_DIMENSION_HORZ
? (int)seg->first->ox / 64.0
@@ -328,9 +423,11 @@
af_dir_str( (AF_Direction)seg->dir ),
AF_INDEX_NUM( seg->first, points ),
AF_INDEX_NUM( seg->last, points ),
- AF_INDEX_NUM( seg->link, segments ),
- AF_INDEX_NUM( seg->serif, segments ),
- AF_INDEX_NUM( seg->edge, edges ),
+
+ af_print_idx( buf1, AF_INDEX_NUM( seg->link, segments ) ),
+ af_print_idx( buf2, AF_INDEX_NUM( seg->serif, segments ) ),
+ af_print_idx( buf3, AF_INDEX_NUM( seg->edge, edges ) ),
+
seg->height,
seg->height - ( seg->max_coord - seg->min_coord ),
af_edge_flags_to_string( seg->flags ) ));
@@ -435,6 +532,8 @@
AF_Edge limit = edges + axis->num_edges;
AF_Edge edge;
+ char buf1[16], buf2[16];
+
/*
* note: AF_DIMENSION_HORZ corresponds to _vertical_ edges
@@ -444,19 +543,20 @@
dimension == AF_DIMENSION_HORZ ? "vertical"
: "horizontal" ));
if ( axis->num_edges )
- AF_DUMP(( " [ index | pos | dir | link"
- " | serif | blue | opos | pos | flags ]\n" ));
+ AF_DUMP(( " index pos dir link serif"
+ " blue opos pos flags\n" ));
else
AF_DUMP(( " (none)\n" ));
for ( edge = edges; edge < limit; edge++ )
- AF_DUMP(( " [ %5d | %5.2g | %5s | %4d"
- " | %5d | %c | %5.2f | %5.2f | %11s ]\n",
+ AF_DUMP(( " %5d %5.2g %5s %4s %5s"
+ " %c %5.2f %5.2f %11s\n",
AF_INDEX_NUM( edge, edges ),
(int)edge->opos / 64.0,
af_dir_str( (AF_Direction)edge->dir ),
- AF_INDEX_NUM( edge->link, edges ),
- AF_INDEX_NUM( edge->serif, edges ),
+ af_print_idx( buf1, AF_INDEX_NUM( edge->link, edges ) ),
+ af_print_idx( buf2, AF_INDEX_NUM( edge->serif, edges ) ),
+
edge->blue_edge ? 'y' : 'n',
edge->opos / 64.0,
edge->pos / 64.0,
diff --git a/src/autofit/afindic.c b/src/autofit/afindic.c
index 7412cd1..59b14d7 100644
--- a/src/autofit/afindic.c
+++ b/src/autofit/afindic.c
@@ -79,12 +79,29 @@
static FT_Error
- af_indic_hints_apply( AF_GlyphHints hints,
+ af_indic_hints_apply( FT_UInt glyph_index,
+ AF_GlyphHints hints,
FT_Outline* outline,
AF_CJKMetrics metrics )
{
/* use CJK routines */
- return af_cjk_hints_apply( hints, outline, metrics );
+ return af_cjk_hints_apply( glyph_index, hints, outline, metrics );
+ }
+
+
+ /* Extract standard_width from writing system/script specific */
+ /* metrics class. */
+
+ static void
+ af_indic_get_standard_widths( AF_CJKMetrics metrics,
+ FT_Pos* stdHW,
+ FT_Pos* stdVW )
+ {
+ if ( stdHW )
+ *stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width;
+
+ if ( stdVW )
+ *stdVW = metrics->axis[AF_DIMENSION_HORZ].standard_width;
}
@@ -107,6 +124,7 @@
(AF_WritingSystem_InitMetricsFunc) af_indic_metrics_init,
(AF_WritingSystem_ScaleMetricsFunc)af_indic_metrics_scale,
(AF_WritingSystem_DoneMetricsFunc) NULL,
+ (AF_WritingSystem_GetStdWidthsFunc)af_indic_get_standard_widths,
(AF_WritingSystem_InitHintsFunc) af_indic_hints_init,
(AF_WritingSystem_ApplyHintsFunc) af_indic_hints_apply
@@ -126,6 +144,7 @@
(AF_WritingSystem_InitMetricsFunc) NULL,
(AF_WritingSystem_ScaleMetricsFunc)NULL,
(AF_WritingSystem_DoneMetricsFunc) NULL,
+ (AF_WritingSystem_GetStdWidthsFunc)NULL,
(AF_WritingSystem_InitHintsFunc) NULL,
(AF_WritingSystem_ApplyHintsFunc) NULL
diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c
index 893e986..9c9f370 100644
--- a/src/autofit/aflatin.c
+++ b/src/autofit/aflatin.c
@@ -41,6 +41,10 @@
#define FT_COMPONENT trace_aflatin
+ /* needed for computation of round vs. flat segments */
+#define FLAT_THRESHOLD( x ) ( x / 14 )
+
+
/*************************************************************************/
/*************************************************************************/
/***** *****/
@@ -75,7 +79,6 @@
{
FT_Error error;
FT_ULong glyph_index;
- FT_Long y_offset;
int dim;
AF_LatinMetricsRec dummy[1];
AF_Scaler scaler = &dummy->root.scaler;
@@ -88,52 +91,63 @@
AF_ScriptClass script_class = AF_SCRIPT_CLASSES_GET
[style_class->script];
- FT_UInt32 standard_char;
+ void* shaper_buf;
+ const char* p;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_ULong ch;
+#endif
+ p = script_class->standard_charstring;
+ shaper_buf = af_shaper_buf_create( face );
/*
- * We check more than a single standard character to catch features
- * like `c2sc' (small caps from caps) that don't contain lowercase
- * letters by definition, or other features that mainly operate on
- * numerals.
+ * We check a list of standard characters to catch features like
+ * `c2sc' (small caps from caps) that don't contain lowercase letters
+ * by definition, or other features that mainly operate on numerals.
+ * The first match wins.
*/
- standard_char = script_class->standard_char1;
- af_get_char_index( &metrics->root,
- standard_char,
- &glyph_index,
- &y_offset );
- if ( !glyph_index )
+ glyph_index = 0;
+ while ( *p )
{
- if ( script_class->standard_char2 )
- {
- standard_char = script_class->standard_char2;
- af_get_char_index( &metrics->root,
- standard_char,
- &glyph_index,
- &y_offset );
- if ( !glyph_index )
- {
- if ( script_class->standard_char3 )
- {
- standard_char = script_class->standard_char3;
- af_get_char_index( &metrics->root,
- standard_char,
- &glyph_index,
- &y_offset );
- if ( !glyph_index )
- goto Exit;
- }
- else
- goto Exit;
- }
- }
- else
- goto Exit;
+ unsigned int num_idx;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ const char* p_old;
+#endif
+
+
+ while ( *p == ' ' )
+ p++;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ p_old = p;
+ GET_UTF8_CHAR( ch, p_old );
+#endif
+
+ /* reject input that maps to more than a single glyph */
+ p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
+ if ( num_idx > 1 )
+ continue;
+
+ /* otherwise exit loop if we have a result */
+ glyph_index = af_shaper_get_elem( &metrics->root,
+ shaper_buf,
+ 0,
+ NULL,
+ NULL );
+ if ( glyph_index )
+ break;
}
+ af_shaper_buf_destroy( face, shaper_buf );
+
+ if ( !glyph_index )
+ goto Exit;
+
FT_TRACE5(( "standard character: U+%04lX (glyph index %d)\n",
- standard_char, glyph_index ));
+ ch, glyph_index ));
error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
if ( error || face->glyph->outline.n_points <= 0 )
@@ -274,6 +288,10 @@
AF_Blue_Stringset bss = sc->blue_stringset;
const AF_Blue_StringRec* bs = &af_blue_stringsets[bss];
+ FT_Pos flat_threshold = FLAT_THRESHOLD( metrics->units_per_em );
+
+ void* shaper_buf;
+
/* we walk over the blue character strings as specified in the */
/* style's entry in the `af_blue_stringset' array */
@@ -282,11 +300,15 @@
"============================\n"
"\n" ));
+ shaper_buf = af_shaper_buf_create( face );
+
for ( ; bs->string != AF_BLUE_STRING_MAX; bs++ )
{
const char* p = &af_blue_strings[bs->string];
FT_Pos* blue_ref;
FT_Pos* blue_shoot;
+ FT_Pos ascender;
+ FT_Pos descender;
#ifdef FT_DEBUG_LEVEL_TRACE
@@ -305,6 +327,11 @@
FT_TRACE5(( "top" ));
have_flag = 1;
}
+ else if ( AF_LATIN_IS_SUB_TOP_BLUE( bs ) )
+ {
+ FT_TRACE5(( "sub top" ));
+ have_flag = 1;
+ }
if ( AF_LATIN_IS_NEUTRAL_BLUE( bs ) )
{
@@ -338,394 +365,482 @@
num_flats = 0;
num_rounds = 0;
+ ascender = 0;
+ descender = 0;
while ( *p )
{
- FT_ULong ch;
FT_ULong glyph_index;
FT_Long y_offset;
- FT_Pos best_y; /* same as points.y */
FT_Int best_point, best_contour_first, best_contour_last;
FT_Vector* points;
- FT_Bool round = 0;
+ FT_Pos best_y_extremum; /* same as points.y */
+ FT_Bool best_round = 0;
- GET_UTF8_CHAR( ch, p );
+ unsigned int i, num_idx;
- /* load the character in the face -- skip unknown or empty ones */
- af_get_char_index( &metrics->root, ch, &glyph_index, &y_offset );
- if ( glyph_index == 0 )
- {
- FT_TRACE5(( " U+%04lX unavailable\n", ch ));
- continue;
- }
+#ifdef FT_DEBUG_LEVEL_TRACE
+ const char* p_old;
+ FT_ULong ch;
+#endif
+
+
+ while ( *p == ' ' )
+ p++;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ p_old = p;
+ GET_UTF8_CHAR( ch, p_old );
+#endif
- error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
- outline = face->glyph->outline;
- /* reject glyphs that don't produce any rendering */
- if ( error || outline.n_points <= 2 )
+ p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
+
+ if ( !num_idx )
{
- FT_TRACE5(( " U+%04lX contains no (usable) outlines\n", ch ));
+ FT_TRACE5(( " U+%04lX unavailable\n", ch ));
continue;
}
- /* now compute min or max point indices and coordinates */
- points = outline.points;
- best_point = -1;
- best_y = 0; /* make compiler happy */
- best_contour_first = 0; /* ditto */
- best_contour_last = 0; /* ditto */
+ if ( AF_LATIN_IS_TOP_BLUE( bs ) )
+ best_y_extremum = FT_INT_MIN;
+ else
+ best_y_extremum = FT_INT_MAX;
+ /* iterate over all glyph elements of the character cluster */
+ /* and get the data of the `biggest' one */
+ for ( i = 0; i < num_idx; i++ )
{
- FT_Int nn;
- FT_Int first = 0;
- FT_Int last = -1;
+ FT_Pos best_y;
+ FT_Bool round = 0;
- for ( nn = 0; nn < outline.n_contours; first = last + 1, nn++ )
+ /* load the character in the face -- skip unknown or empty ones */
+ glyph_index = af_shaper_get_elem( &metrics->root,
+ shaper_buf,
+ i,
+ NULL,
+ &y_offset );
+ if ( glyph_index == 0 )
{
- FT_Int old_best_point = best_point;
- FT_Int pp;
+ FT_TRACE5(( " U+%04lX unavailable\n", ch ));
+ continue;
+ }
+ error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
+ outline = face->glyph->outline;
+ /* reject glyphs that don't produce any rendering */
+ if ( error || outline.n_points <= 2 )
+ {
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( num_idx == 1 )
+ FT_TRACE5(( " U+%04lX contains no (usable) outlines\n", ch ));
+ else
+ FT_TRACE5(( " component %d of cluster starting with U+%04lX"
+ " contains no (usable) outlines\n", i, ch ));
+#endif
+ continue;
+ }
- last = outline.contours[nn];
+ /* now compute min or max point indices and coordinates */
+ points = outline.points;
+ best_point = -1;
+ best_y = 0; /* make compiler happy */
+ best_contour_first = 0; /* ditto */
+ best_contour_last = 0; /* ditto */
- /* Avoid single-point contours since they are never rasterized. */
- /* In some fonts, they correspond to mark attachment points */
- /* that are way outside of the glyph's real outline. */
- if ( last <= first )
- continue;
+ {
+ FT_Int nn;
+ FT_Int first = 0;
+ FT_Int last = -1;
- if ( AF_LATIN_IS_TOP_BLUE( bs ) )
+
+ for ( nn = 0; nn < outline.n_contours; first = last + 1, nn++ )
{
- for ( pp = first; pp <= last; pp++ )
- if ( best_point < 0 || points[pp].y > best_y )
+ FT_Int old_best_point = best_point;
+ FT_Int pp;
+
+
+ last = outline.contours[nn];
+
+ /* Avoid single-point contours since they are never */
+ /* rasterized. In some fonts, they correspond to mark */
+ /* attachment points that are way outside of the glyph's */
+ /* real outline. */
+ if ( last <= first )
+ continue;
+
+ if ( AF_LATIN_IS_TOP_BLUE( bs ) ||
+ AF_LATIN_IS_SUB_TOP_BLUE( bs ) )
+ {
+ for ( pp = first; pp <= last; pp++ )
{
- best_point = pp;
- best_y = points[pp].y;
+ if ( best_point < 0 || points[pp].y > best_y )
+ {
+ best_point = pp;
+ best_y = points[pp].y;
+ ascender = FT_MAX( ascender, best_y + y_offset );
+ }
+ else
+ descender = FT_MIN( descender, points[pp].y + y_offset );
}
- }
- else
- {
- for ( pp = first; pp <= last; pp++ )
- if ( best_point < 0 || points[pp].y < best_y )
+ }
+ else
+ {
+ for ( pp = first; pp <= last; pp++ )
{
- best_point = pp;
- best_y = points[pp].y;
+ if ( best_point < 0 || points[pp].y < best_y )
+ {
+ best_point = pp;
+ best_y = points[pp].y;
+ descender = FT_MIN( descender, best_y + y_offset );
+ }
+ else
+ ascender = FT_MAX( ascender, points[pp].y + y_offset );
}
- }
+ }
- if ( best_point != old_best_point )
- {
- best_contour_first = first;
- best_contour_last = last;
+ if ( best_point != old_best_point )
+ {
+ best_contour_first = first;
+ best_contour_last = last;
+ }
}
}
- }
-
- /* now check whether the point belongs to a straight or round */
- /* segment; we first need to find in which contour the extremum */
- /* lies, then inspect its previous and next points */
- if ( best_point >= 0 )
- {
- FT_Pos best_x = points[best_point].x;
- FT_Int prev, next;
- FT_Int best_segment_first, best_segment_last;
- FT_Int best_on_point_first, best_on_point_last;
- FT_Pos dist;
-
- best_segment_first = best_point;
- best_segment_last = best_point;
-
- if ( FT_CURVE_TAG( outline.tags[best_point] ) == FT_CURVE_TAG_ON )
+ /* now check whether the point belongs to a straight or round */
+ /* segment; we first need to find in which contour the extremum */
+ /* lies, then inspect its previous and next points */
+ if ( best_point >= 0 )
{
- best_on_point_first = best_point;
- best_on_point_last = best_point;
- }
- else
- {
- best_on_point_first = -1;
- best_on_point_last = -1;
- }
+ FT_Pos best_x = points[best_point].x;
+ FT_Int prev, next;
+ FT_Int best_segment_first, best_segment_last;
+ FT_Int best_on_point_first, best_on_point_last;
+ FT_Pos dist;
- /* look for the previous and next points on the contour */
- /* that are not on the same Y coordinate, then threshold */
- /* the `closeness'... */
- prev = best_point;
- next = prev;
- do
- {
- if ( prev > best_contour_first )
- prev--;
- else
- prev = best_contour_last;
+ best_segment_first = best_point;
+ best_segment_last = best_point;
- dist = FT_ABS( points[prev].y - best_y );
- /* accept a small distance or a small angle (both values are */
- /* heuristic; value 20 corresponds to approx. 2.9 degrees) */
- if ( dist > 5 )
- if ( FT_ABS( points[prev].x - best_x ) <= 20 * dist )
- break;
+ if ( FT_CURVE_TAG( outline.tags[best_point] ) == FT_CURVE_TAG_ON )
+ {
+ best_on_point_first = best_point;
+ best_on_point_last = best_point;
+ }
+ else
+ {
+ best_on_point_first = -1;
+ best_on_point_last = -1;
+ }
- best_segment_first = prev;
+ /* look for the previous and next points on the contour */
+ /* that are not on the same Y coordinate, then threshold */
+ /* the `closeness'... */
+ prev = best_point;
+ next = prev;
- if ( FT_CURVE_TAG( outline.tags[prev] ) == FT_CURVE_TAG_ON )
+ do
{
- best_on_point_first = prev;
- if ( best_on_point_last < 0 )
- best_on_point_last = prev;
- }
+ if ( prev > best_contour_first )
+ prev--;
+ else
+ prev = best_contour_last;
- } while ( prev != best_point );
+ dist = FT_ABS( points[prev].y - best_y );
+ /* accept a small distance or a small angle (both values are */
+ /* heuristic; value 20 corresponds to approx. 2.9 degrees) */
+ if ( dist > 5 )
+ if ( FT_ABS( points[prev].x - best_x ) <= 20 * dist )
+ break;
- do
- {
- if ( next < best_contour_last )
- next++;
- else
- next = best_contour_first;
+ best_segment_first = prev;
- dist = FT_ABS( points[next].y - best_y );
- if ( dist > 5 )
- if ( FT_ABS( points[next].x - best_x ) <= 20 * dist )
- break;
+ if ( FT_CURVE_TAG( outline.tags[prev] ) == FT_CURVE_TAG_ON )
+ {
+ best_on_point_first = prev;
+ if ( best_on_point_last < 0 )
+ best_on_point_last = prev;
+ }
- best_segment_last = next;
+ } while ( prev != best_point );
- if ( FT_CURVE_TAG( outline.tags[next] ) == FT_CURVE_TAG_ON )
+ do
{
- best_on_point_last = next;
- if ( best_on_point_first < 0 )
- best_on_point_first = next;
- }
+ if ( next < best_contour_last )
+ next++;
+ else
+ next = best_contour_first;
- } while ( next != best_point );
+ dist = FT_ABS( points[next].y - best_y );
+ if ( dist > 5 )
+ if ( FT_ABS( points[next].x - best_x ) <= 20 * dist )
+ break;
- if ( AF_LATIN_IS_LONG_BLUE( bs ) )
- {
- /* If this flag is set, we have an additional constraint to */
- /* get the blue zone distance: Find a segment of the topmost */
- /* (or bottommost) contour that is longer than a heuristic */
- /* threshold. This ensures that small bumps in the outline */
- /* are ignored (for example, the `vertical serifs' found in */
- /* many Hebrew glyph designs). */
-
- /* If this segment is long enough, we are done. Otherwise, */
- /* search the segment next to the extremum that is long */
- /* enough, has the same direction, and a not too large */
- /* vertical distance from the extremum. Note that the */
- /* algorithm doesn't check whether the found segment is */
- /* actually the one (vertically) nearest to the extremum. */
-
- /* heuristic threshold value */
- FT_Pos length_threshold = metrics->units_per_em / 25;
-
-
- dist = FT_ABS( points[best_segment_last].x -
- points[best_segment_first].x );
-
- if ( dist < length_threshold &&
- best_segment_last - best_segment_first + 2 <=
- best_contour_last - best_contour_first )
+ best_segment_last = next;
+
+ if ( FT_CURVE_TAG( outline.tags[next] ) == FT_CURVE_TAG_ON )
+ {
+ best_on_point_last = next;
+ if ( best_on_point_first < 0 )
+ best_on_point_first = next;
+ }
+
+ } while ( next != best_point );
+
+ if ( AF_LATIN_IS_LONG_BLUE( bs ) )
{
+ /* If this flag is set, we have an additional constraint to */
+ /* get the blue zone distance: Find a segment of the topmost */
+ /* (or bottommost) contour that is longer than a heuristic */
+ /* threshold. This ensures that small bumps in the outline */
+ /* are ignored (for example, the `vertical serifs' found in */
+ /* many Hebrew glyph designs). */
+
+ /* If this segment is long enough, we are done. Otherwise, */
+ /* search the segment next to the extremum that is long */
+ /* enough, has the same direction, and a not too large */
+ /* vertical distance from the extremum. Note that the */
+ /* algorithm doesn't check whether the found segment is */
+ /* actually the one (vertically) nearest to the extremum. */
+
/* heuristic threshold value */
- FT_Pos height_threshold = metrics->units_per_em / 4;
+ FT_Pos length_threshold = metrics->units_per_em / 25;
- FT_Int first;
- FT_Int last;
- FT_Bool hit;
- /* we intentionally declare these two variables */
- /* outside of the loop since various compilers emit */
- /* incorrect warning messages otherwise, talking about */
- /* `possibly uninitialized variables' */
- FT_Int p_first = 0; /* make compiler happy */
- FT_Int p_last = 0;
+ dist = FT_ABS( points[best_segment_last].x -
+ points[best_segment_first].x );
- FT_Bool left2right;
+ if ( dist < length_threshold &&
+ best_segment_last - best_segment_first + 2 <=
+ best_contour_last - best_contour_first )
+ {
+ /* heuristic threshold value */
+ FT_Pos height_threshold = metrics->units_per_em / 4;
+ FT_Int first;
+ FT_Int last;
+ FT_Bool hit;
- /* compute direction */
- prev = best_point;
+ /* we intentionally declare these two variables */
+ /* outside of the loop since various compilers emit */
+ /* incorrect warning messages otherwise, talking about */
+ /* `possibly uninitialized variables' */
+ FT_Int p_first = 0; /* make compiler happy */
+ FT_Int p_last = 0;
- do
- {
- if ( prev > best_contour_first )
- prev--;
- else
- prev = best_contour_last;
+ FT_Bool left2right;
- if ( points[prev].x != best_x )
- break;
- } while ( prev != best_point );
+ /* compute direction */
+ prev = best_point;
- /* skip glyph for the degenerate case */
- if ( prev == best_point )
- continue;
+ do
+ {
+ if ( prev > best_contour_first )
+ prev--;
+ else
+ prev = best_contour_last;
- left2right = FT_BOOL( points[prev].x < points[best_point].x );
+ if ( points[prev].x != best_x )
+ break;
- first = best_segment_last;
- last = first;
- hit = 0;
+ } while ( prev != best_point );
- do
- {
- FT_Bool l2r;
- FT_Pos d;
+ /* skip glyph for the degenerate case */
+ if ( prev == best_point )
+ continue;
+ left2right = FT_BOOL( points[prev].x < points[best_point].x );
- if ( !hit )
+ first = best_segment_last;
+ last = first;
+ hit = 0;
+
+ do
{
- /* no hit; adjust first point */
- first = last;
+ FT_Bool l2r;
+ FT_Pos d;
- /* also adjust first and last on point */
- if ( FT_CURVE_TAG( outline.tags[first] ) ==
- FT_CURVE_TAG_ON )
- {
- p_first = first;
- p_last = first;
- }
- else
+
+ if ( !hit )
{
- p_first = -1;
- p_last = -1;
- }
+ /* no hit; adjust first point */
+ first = last;
- hit = 1;
- }
+ /* also adjust first and last on point */
+ if ( FT_CURVE_TAG( outline.tags[first] ) ==
+ FT_CURVE_TAG_ON )
+ {
+ p_first = first;
+ p_last = first;
+ }
+ else
+ {
+ p_first = -1;
+ p_last = -1;
+ }
- if ( last < best_contour_last )
- last++;
- else
- last = best_contour_first;
+ hit = 1;
+ }
- if ( FT_ABS( best_y - points[first].y ) > height_threshold )
- {
- /* vertical distance too large */
- hit = 0;
- continue;
- }
+ if ( last < best_contour_last )
+ last++;
+ else
+ last = best_contour_first;
- /* same test as above */
- dist = FT_ABS( points[last].y - points[first].y );
- if ( dist > 5 )
- if ( FT_ABS( points[last].x - points[first].x ) <=
- 20 * dist )
+ if ( FT_ABS( best_y - points[first].y ) > height_threshold )
{
+ /* vertical distance too large */
hit = 0;
continue;
}
- if ( FT_CURVE_TAG( outline.tags[last] ) == FT_CURVE_TAG_ON )
- {
- p_last = last;
- if ( p_first < 0 )
- p_first = last;
- }
+ /* same test as above */
+ dist = FT_ABS( points[last].y - points[first].y );
+ if ( dist > 5 )
+ if ( FT_ABS( points[last].x - points[first].x ) <=
+ 20 * dist )
+ {
+ hit = 0;
+ continue;
+ }
- l2r = FT_BOOL( points[first].x < points[last].x );
- d = FT_ABS( points[last].x - points[first].x );
+ if ( FT_CURVE_TAG( outline.tags[last] ) == FT_CURVE_TAG_ON )
+ {
+ p_last = last;
+ if ( p_first < 0 )
+ p_first = last;
+ }
- if ( l2r == left2right &&
- d >= length_threshold )
- {
- /* all constraints are met; update segment after finding */
- /* its end */
- do
+ l2r = FT_BOOL( points[first].x < points[last].x );
+ d = FT_ABS( points[last].x - points[first].x );
+
+ if ( l2r == left2right &&
+ d >= length_threshold )
{
- if ( last < best_contour_last )
- last++;
- else
- last = best_contour_first;
+ /* all constraints are met; update segment after */
+ /* finding its end */
+ do
+ {
+ if ( last < best_contour_last )
+ last++;
+ else
+ last = best_contour_first;
+
+ d = FT_ABS( points[last].y - points[first].y );
+ if ( d > 5 )
+ if ( FT_ABS( points[next].x - points[first].x ) <=
+ 20 * dist )
+ {
+ if ( last > best_contour_first )
+ last--;
+ else
+ last = best_contour_last;
+ break;
+ }
- d = FT_ABS( points[last].y - points[first].y );
- if ( d > 5 )
- if ( FT_ABS( points[next].x - points[first].x ) <=
- 20 * dist )
+ p_last = last;
+
+ if ( FT_CURVE_TAG( outline.tags[last] ) ==
+ FT_CURVE_TAG_ON )
{
- if ( last > best_contour_first )
- last--;
- else
- last = best_contour_last;
- break;
+ p_last = last;
+ if ( p_first < 0 )
+ p_first = last;
}
- p_last = last;
+ } while ( last != best_segment_first );
- if ( FT_CURVE_TAG( outline.tags[last] ) ==
- FT_CURVE_TAG_ON )
- {
- p_last = last;
- if ( p_first < 0 )
- p_first = last;
- }
+ best_y = points[first].y;
+
+ best_segment_first = first;
+ best_segment_last = last;
+
+ best_on_point_first = p_first;
+ best_on_point_last = p_last;
- } while ( last != best_segment_first );
+ break;
+ }
- best_y = points[first].y;
+ } while ( last != best_segment_first );
+ }
+ }
- best_segment_first = first;
- best_segment_last = last;
+ /* for computing blue zones, we add the y offset as returned */
+ /* by the currently used OpenType feature -- for example, */
+ /* superscript glyphs might be identical to subscript glyphs */
+ /* with a vertical shift */
+ best_y += y_offset;
- best_on_point_first = p_first;
- best_on_point_last = p_last;
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( num_idx == 1 )
+ FT_TRACE5(( " U+%04lX: best_y = %5ld", ch, best_y ));
+ else
+ FT_TRACE5(( " component %d of cluster starting with U+%04lX:"
+ " best_y = %5ld", i, ch, best_y ));
+#endif
- break;
- }
+ /* now set the `round' flag depending on the segment's kind: */
+ /* */
+ /* - if the horizontal distance between the first and last */
+ /* `on' point is larger than a heuristic threshold */
+ /* we have a flat segment */
+ /* - if either the first or the last point of the segment is */
+ /* an `off' point, the segment is round, otherwise it is */
+ /* flat */
+ if ( best_on_point_first >= 0 &&
+ best_on_point_last >= 0 &&
+ ( FT_ABS( points[best_on_point_last].x -
+ points[best_on_point_first].x ) ) >
+ flat_threshold )
+ round = 0;
+ else
+ round = FT_BOOL(
+ FT_CURVE_TAG( outline.tags[best_segment_first] ) !=
+ FT_CURVE_TAG_ON ||
+ FT_CURVE_TAG( outline.tags[best_segment_last] ) !=
+ FT_CURVE_TAG_ON );
- } while ( last != best_segment_first );
+ if ( round && AF_LATIN_IS_NEUTRAL_BLUE( bs ) )
+ {
+ /* only use flat segments for a neutral blue zone */
+ FT_TRACE5(( " (round, skipped)\n" ));
+ continue;
}
+
+ FT_TRACE5(( " (%s)\n", round ? "round" : "flat" ));
}
- /* for computing blue zones, we add the y offset as returned */
- /* by the currently used OpenType feature -- for example, */
- /* superscript glyphs might be identical to subscript glyphs */
- /* with a vertical shift */
- best_y += y_offset;
-
- FT_TRACE5(( " U+%04lX: best_y = %5ld", ch, best_y ));
-
- /* now set the `round' flag depending on the segment's kind: */
- /* */
- /* - if the horizontal distance between the first and last */
- /* `on' point is larger than upem/8 (value 8 is heuristic) */
- /* we have a flat segment */
- /* - if either the first or the last point of the segment is */
- /* an `off' point, the segment is round, otherwise it is */
- /* flat */
- if ( best_on_point_first >= 0 &&
- best_on_point_last >= 0 &&
- (FT_UInt)( FT_ABS( points[best_on_point_last].x -
- points[best_on_point_first].x ) ) >
- metrics->units_per_em / 8 )
- round = 0;
+ if ( AF_LATIN_IS_TOP_BLUE( bs ) )
+ {
+ if ( best_y > best_y_extremum )
+ {
+ best_y_extremum = best_y;
+ best_round = round;
+ }
+ }
else
- round = FT_BOOL(
- FT_CURVE_TAG( outline.tags[best_segment_first] ) !=
- FT_CURVE_TAG_ON ||
- FT_CURVE_TAG( outline.tags[best_segment_last] ) !=
- FT_CURVE_TAG_ON );
-
- if ( round && AF_LATIN_IS_NEUTRAL_BLUE( bs ) )
{
- /* only use flat segments for a neutral blue zone */
- FT_TRACE5(( " (round, skipped)\n" ));
- continue;
+ if ( best_y < best_y_extremum )
+ {
+ best_y_extremum = best_y;
+ best_round = round;
+ }
}
- FT_TRACE5(( " (%s)\n", round ? "round" : "flat" ));
+ } /* end for loop */
+
+ if ( !( best_y_extremum == FT_INT_MIN ||
+ best_y_extremum == FT_INT_MAX ) )
+ {
+ if ( best_round )
+ rounds[num_rounds++] = best_y_extremum;
+ else
+ flats[num_flats++] = best_y_extremum;
}
- if ( round )
- rounds[num_rounds++] = best_y;
- else
- flats[num_flats++] = best_y;
- }
+ } /* end while loop */
if ( num_flats == 0 && num_rounds == 0 )
{
@@ -775,7 +890,8 @@
FT_Bool over_ref = FT_BOOL( shoot > ref );
- if ( AF_LATIN_IS_TOP_BLUE( bs ) ^ over_ref )
+ if ( ( AF_LATIN_IS_TOP_BLUE( bs ) ||
+ AF_LATIN_IS_SUB_TOP_BLUE( bs) ) ^ over_ref )
{
*blue_ref =
*blue_shoot = ( shoot + ref ) / 2;
@@ -785,9 +901,14 @@
}
}
+ blue->ascender = ascender;
+ blue->descender = descender;
+
blue->flags = 0;
if ( AF_LATIN_IS_TOP_BLUE( bs ) )
blue->flags |= AF_LATIN_BLUE_TOP;
+ if ( AF_LATIN_IS_SUB_TOP_BLUE( bs ) )
+ blue->flags |= AF_LATIN_BLUE_SUB_TOP;
if ( AF_LATIN_IS_NEUTRAL_BLUE( bs ) )
blue->flags |= AF_LATIN_BLUE_NEUTRAL;
@@ -802,7 +923,10 @@
FT_TRACE5(( " -> reference = %ld\n"
" overshoot = %ld\n",
*blue_ref, *blue_shoot ));
- }
+
+ } /* end for loop */
+
+ af_shaper_buf_destroy( face, shaper_buf );
FT_TRACE5(( "\n" ));
@@ -816,27 +940,36 @@
af_latin_metrics_check_digits( AF_LatinMetrics metrics,
FT_Face face )
{
- FT_UInt i;
FT_Bool started = 0, same_width = 1;
FT_Fixed advance, old_advance = 0;
+ void* shaper_buf;
- /* digit `0' is 0x30 in all supported charmaps */
- for ( i = 0x30; i <= 0x39; i++ )
+ /* in all supported charmaps, digits have character codes 0x30-0x39 */
+ const char digits[] = "0 1 2 3 4 5 6 7 8 9";
+ const char* p;
+
+
+ p = digits;
+ shaper_buf = af_shaper_buf_create( face );
+
+ while ( *p )
{
- FT_ULong glyph_index;
- FT_Long y_offset;
+ FT_ULong glyph_index;
+ unsigned int num_idx;
- af_get_char_index( &metrics->root, i, &glyph_index, &y_offset );
- if ( glyph_index == 0 )
+ /* reject input that maps to more than a single glyph */
+ p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
+ if ( num_idx > 1 )
continue;
- if ( FT_Get_Advance( face, glyph_index,
- FT_LOAD_NO_SCALE |
- FT_LOAD_NO_HINTING |
- FT_LOAD_IGNORE_TRANSFORM,
- &advance ) )
+ glyph_index = af_shaper_get_elem( &metrics->root,
+ shaper_buf,
+ 0,
+ &advance,
+ NULL );
+ if ( !glyph_index )
continue;
if ( started )
@@ -854,6 +987,8 @@
}
}
+ af_shaper_buf_destroy( face, shaper_buf );
+
metrics->root.digits_have_same_width = same_width;
}
@@ -967,18 +1102,52 @@
#endif
if ( dim == AF_DIMENSION_VERT )
{
- scale = FT_MulDiv( scale, fitted, scaled );
-
- FT_TRACE5((
- "af_latin_metrics_scale_dim:"
- " x height alignment (style `%s'):\n"
- " "
- " vertical scaling changed from %.4f to %.4f (by %d%%)\n"
- "\n",
- af_style_names[metrics->root.style_class->style],
- axis->org_scale / 65536.0,
- scale / 65536.0,
- ( fitted - scaled ) * 100 / scaled ));
+ FT_Pos max_height;
+ FT_Pos dist;
+ FT_Fixed new_scale;
+
+
+ new_scale = FT_MulDiv( scale, fitted, scaled );
+
+ /* the scaling should not change the result by more than two pixels */
+ max_height = metrics->units_per_em;
+
+ for ( nn = 0; nn < Axis->blue_count; nn++ )
+ {
+ max_height = FT_MAX( max_height, Axis->blues[nn].ascender );
+ max_height = FT_MAX( max_height, -Axis->blues[nn].descender );
+ }
+
+ dist = FT_ABS( FT_MulFix( max_height, new_scale - scale ) );
+ dist &= ~127;
+
+ if ( dist == 0 )
+ {
+ scale = new_scale;
+
+ FT_TRACE5((
+ "af_latin_metrics_scale_dim:"
+ " x height alignment (style `%s'):\n"
+ " "
+ " vertical scaling changed from %.4f to %.4f (by %d%%)\n"
+ "\n",
+ af_style_names[metrics->root.style_class->style],
+ axis->org_scale / 65536.0,
+ scale / 65536.0,
+ ( fitted - scaled ) * 100 / scaled ));
+ }
+#ifdef FT_DEBUG_LEVEL_TRACE
+ else
+ {
+ FT_TRACE5((
+ "af_latin_metrics_scale_dim:"
+ " x height alignment (style `%s'):\n"
+ " "
+ " excessive vertical scaling abandoned\n"
+ "\n",
+ af_style_names[metrics->root.style_class->style] ));
+ }
+#endif
}
}
}
@@ -1032,8 +1201,11 @@
if ( dim == AF_DIMENSION_VERT )
{
- FT_TRACE5(( "blue zones (style `%s')\n",
- af_style_names[metrics->root.style_class->style] ));
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( axis->blue_count )
+ FT_TRACE5(( "blue zones (style `%s')\n",
+ af_style_names[metrics->root.style_class->style] ));
+#endif
/* scale the blue zones */
for ( nn = 0; nn < axis->blue_count; nn++ )
@@ -1106,21 +1278,63 @@
#endif
blue->flags |= AF_LATIN_BLUE_ACTIVE;
+ }
+ }
+
+ /* use sub-top blue zone only if it doesn't overlap with */
+ /* another (non-sup-top) blue zone; otherwise, the */
+ /* effect would be similar to a neutral blue zone, which */
+ /* is not desired here */
+ for ( nn = 0; nn < axis->blue_count; nn++ )
+ {
+ AF_LatinBlue blue = &axis->blues[nn];
+ FT_UInt i;
+
+
+ if ( !( blue->flags & AF_LATIN_BLUE_SUB_TOP ) )
+ continue;
+ if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) )
+ continue;
- FT_TRACE5(( " reference %d: %d scaled to %.2f%s\n"
- " overshoot %d: %d scaled to %.2f%s\n",
- nn,
- blue->ref.org,
- blue->ref.fit / 64.0,
- blue->flags & AF_LATIN_BLUE_ACTIVE ? ""
- : " (inactive)",
- nn,
- blue->shoot.org,
- blue->shoot.fit / 64.0,
- blue->flags & AF_LATIN_BLUE_ACTIVE ? ""
- : " (inactive)" ));
+ for ( i = 0; i < axis->blue_count; i++ )
+ {
+ AF_LatinBlue b = &axis->blues[i];
+
+
+ if ( b->flags & AF_LATIN_BLUE_SUB_TOP )
+ continue;
+ if ( !( b->flags & AF_LATIN_BLUE_ACTIVE ) )
+ continue;
+
+ if ( b->ref.fit <= blue->shoot.fit &&
+ b->shoot.fit >= blue->ref.fit )
+ {
+ blue->flags &= ~AF_LATIN_BLUE_ACTIVE;
+ break;
+ }
}
}
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ for ( nn = 0; nn < axis->blue_count; nn++ )
+ {
+ AF_LatinBlue blue = &axis->blues[nn];
+
+
+ FT_TRACE5(( " reference %d: %d scaled to %.2f%s\n"
+ " overshoot %d: %d scaled to %.2f%s\n",
+ nn,
+ blue->ref.org,
+ blue->ref.fit / 64.0,
+ blue->flags & AF_LATIN_BLUE_ACTIVE ? ""
+ : " (inactive)",
+ nn,
+ blue->shoot.org,
+ blue->shoot.fit / 64.0,
+ blue->flags & AF_LATIN_BLUE_ACTIVE ? ""
+ : " (inactive)" ));
+ }
+#endif
}
}
@@ -1140,6 +1354,22 @@
}
+ /* Extract standard_width from writing system/script specific */
+ /* metrics class. */
+
+ FT_LOCAL_DEF( void )
+ af_latin_get_standard_widths( AF_LatinMetrics metrics,
+ FT_Pos* stdHW,
+ FT_Pos* stdVW )
+ {
+ if ( stdHW )
+ *stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width;
+
+ if ( stdVW )
+ *stdVW = metrics->axis[AF_DIMENSION_HORZ].standard_width;
+ }
+
+
/*************************************************************************/
/*************************************************************************/
/***** *****/
@@ -1155,14 +1385,17 @@
af_latin_hints_compute_segments( AF_GlyphHints hints,
AF_Dimension dim )
{
- AF_AxisHints axis = &hints->axis[dim];
- FT_Memory memory = hints->memory;
- FT_Error error = FT_Err_Ok;
- AF_Segment segment = NULL;
- AF_SegmentRec seg0;
- AF_Point* contour = hints->contours;
- AF_Point* contour_limit = contour + hints->num_contours;
- AF_Direction major_dir, segment_dir;
+ AF_LatinMetrics metrics = (AF_LatinMetrics)hints->metrics;
+ AF_AxisHints axis = &hints->axis[dim];
+ FT_Memory memory = hints->memory;
+ FT_Error error = FT_Err_Ok;
+ AF_Segment segment = NULL;
+ AF_SegmentRec seg0;
+ AF_Point* contour = hints->contours;
+ AF_Point* contour_limit = contour + hints->num_contours;
+ AF_Direction major_dir, segment_dir;
+
+ FT_Pos flat_threshold = FLAT_THRESHOLD( metrics->units_per_em );
FT_ZERO( &seg0 );
@@ -1203,11 +1436,13 @@
/* do each contour separately */
for ( ; contour < contour_limit; contour++ )
{
- AF_Point point = contour[0];
- AF_Point last = point->prev;
- int on_edge = 0;
- FT_Pos min_pos = 32000; /* minimum segment pos != min_coord */
- FT_Pos max_pos = -32000; /* maximum segment pos != max_coord */
+ AF_Point point = contour[0];
+ AF_Point last = point->prev;
+ int on_edge = 0;
+ FT_Pos min_pos = 32000; /* minimum segment pos != min_coord */
+ FT_Pos max_pos = -32000; /* maximum segment pos != max_coord */
+ FT_Pos min_on_pos = 32000;
+ FT_Pos max_on_pos = -32000;
FT_Bool passed;
@@ -1249,6 +1484,16 @@
if ( u > max_pos )
max_pos = u;
+ /* get minimum and maximum coordinate of on points */
+ if ( !( point->flags & AF_FLAG_CONTROL ) )
+ {
+ v = point->v;
+ if ( v < min_on_pos )
+ min_on_pos = v;
+ if ( v > max_on_pos )
+ max_on_pos = v;
+ }
+
if ( point->out_dir != segment_dir || point == last )
{
/* we are just leaving an edge; record a new segment! */
@@ -1256,9 +1501,10 @@
segment->pos = (FT_Short)( ( min_pos + max_pos ) >> 1 );
/* a segment is round if either its first or last point */
- /* is a control point */
- if ( ( segment->first->flags | point->flags ) &
- AF_FLAG_CONTROL )
+ /* is a control point, and the length of the on points */
+ /* inbetween doesn't exceed a heuristic limit */
+ if ( ( segment->first->flags | point->flags ) & AF_FLAG_CONTROL &&
+ ( max_on_pos - min_on_pos ) < flat_threshold )
segment->flags |= AF_EDGE_ROUND;
/* compute segment size */
@@ -1301,10 +1547,19 @@
/* clear all segment fields */
segment[0] = seg0;
- segment->dir = (FT_Char)segment_dir;
+ segment->dir = (FT_Char)segment_dir;
+ segment->first = point;
+ segment->last = point;
+
min_pos = max_pos = point->u;
- segment->first = point;
- segment->last = point;
+
+ if ( point->flags & AF_FLAG_CONTROL )
+ {
+ min_on_pos = 32000;
+ max_on_pos = -32000;
+ }
+ else
+ min_on_pos = max_on_pos = point->v;
on_edge = 1;
}
@@ -1872,7 +2127,8 @@
/* the major direction) -- this assumes the TrueType convention */
/* for the orientation of contours */
is_top_blue =
- (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 );
+ (FT_Byte)( ( blue->flags & ( AF_LATIN_BLUE_TOP |
+ AF_LATIN_BLUE_SUB_TOP ) ) != 0 );
is_neutral_blue =
(FT_Byte)( ( blue->flags & AF_LATIN_BLUE_NEUTRAL ) != 0);
is_major_dir =
@@ -2805,7 +3061,8 @@
/* Apply the complete hinting algorithm to a latin glyph. */
static FT_Error
- af_latin_hints_apply( AF_GlyphHints hints,
+ af_latin_hints_apply( FT_UInt glyph_index,
+ AF_GlyphHints hints,
FT_Outline* outline,
AF_LatinMetrics metrics )
{
@@ -2847,7 +3104,9 @@
if ( error )
goto Exit;
- af_latin_hints_compute_blue_edges( hints, metrics );
+ /* apply blue zones to base characters only */
+ if ( !( metrics->root.globals->glyph_styles[glyph_index] & AF_NONBASE ) )
+ af_latin_hints_compute_blue_edges( hints, metrics );
}
/* grid-fit the outline */
@@ -2907,6 +3166,7 @@
(AF_WritingSystem_InitMetricsFunc) af_latin_metrics_init,
(AF_WritingSystem_ScaleMetricsFunc)af_latin_metrics_scale,
(AF_WritingSystem_DoneMetricsFunc) NULL,
+ (AF_WritingSystem_GetStdWidthsFunc)af_latin_get_standard_widths,
(AF_WritingSystem_InitHintsFunc) af_latin_hints_init,
(AF_WritingSystem_ApplyHintsFunc) af_latin_hints_apply
diff --git a/src/autofit/aflatin.h b/src/autofit/aflatin.h
index 6855492..414060f 100644
--- a/src/autofit/aflatin.h
+++ b/src/autofit/aflatin.h
@@ -53,6 +53,8 @@ FT_BEGIN_HEADER
#define AF_LATIN_IS_TOP_BLUE( b ) \
( (b)->properties & AF_BLUE_PROPERTY_LATIN_TOP )
+#define AF_LATIN_IS_SUB_TOP_BLUE( b ) \
+ ( (b)->properties & AF_BLUE_PROPERTY_LATIN_SUB_TOP )
#define AF_LATIN_IS_NEUTRAL_BLUE( b ) \
( (b)->properties & AF_BLUE_PROPERTY_LATIN_NEUTRAL )
#define AF_LATIN_IS_X_HEIGHT_BLUE( b ) \
@@ -65,8 +67,10 @@ FT_BEGIN_HEADER
#define AF_LATIN_BLUE_ACTIVE ( 1U << 0 ) /* zone height is <= 3/4px */
#define AF_LATIN_BLUE_TOP ( 1U << 1 ) /* we have a top blue zone */
-#define AF_LATIN_BLUE_NEUTRAL ( 1U << 2 ) /* we have neutral blue zone */
-#define AF_LATIN_BLUE_ADJUSTMENT ( 1U << 3 ) /* used for scale adjustment */
+#define AF_LATIN_BLUE_SUB_TOP ( 1U << 2 ) /* we have a subscript top */
+ /* blue zone */
+#define AF_LATIN_BLUE_NEUTRAL ( 1U << 3 ) /* we have neutral blue zone */
+#define AF_LATIN_BLUE_ADJUSTMENT ( 1U << 4 ) /* used for scale adjustment */
/* optimization */
@@ -74,6 +78,8 @@ FT_BEGIN_HEADER
{
AF_WidthRec ref;
AF_WidthRec shoot;
+ FT_Pos ascender;
+ FT_Pos descender;
FT_UInt flags;
} AF_LatinBlueRec, *AF_LatinBlue;
diff --git a/src/autofit/aflatin2.c b/src/autofit/aflatin2.c
index ac9f933..2fb7d1d 100644
--- a/src/autofit/aflatin2.c
+++ b/src/autofit/aflatin2.c
@@ -693,6 +693,22 @@
}
+ /* Extract standard_width from writing system/script specific */
+ /* metrics class. */
+
+ FT_LOCAL_DEF( void )
+ af_latin2_get_standard_widths( AF_LatinMetrics metrics,
+ FT_Pos* stdHW,
+ FT_Pos* stdVW )
+ {
+ if ( stdHW )
+ *stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width;
+
+ if ( stdVW )
+ *stdVW = metrics->axis[AF_DIMENSION_HORZ].standard_width;
+ }
+
+
/*************************************************************************/
/*************************************************************************/
/***** *****/
@@ -2300,13 +2316,16 @@
static FT_Error
- af_latin2_hints_apply( AF_GlyphHints hints,
+ af_latin2_hints_apply( FT_UInt glyph_index,
+ AF_GlyphHints hints,
FT_Outline* outline,
AF_LatinMetrics metrics )
{
FT_Error error;
int dim;
+ FT_UNUSED( glyph_index );
+
error = af_glyph_hints_reload( hints, outline );
if ( error )
@@ -2389,6 +2408,7 @@
(AF_WritingSystem_InitMetricsFunc) af_latin2_metrics_init,
(AF_WritingSystem_ScaleMetricsFunc)af_latin2_metrics_scale,
(AF_WritingSystem_DoneMetricsFunc) NULL,
+ (AF_WritingSystem_GetStdWidthsFunc)af_latin2_get_standard_widths,
(AF_WritingSystem_InitHintsFunc) af_latin2_hints_init,
(AF_WritingSystem_ApplyHintsFunc) af_latin2_hints_apply
diff --git a/src/autofit/afloader.c b/src/autofit/afloader.c
index 7c2fa7c..aa5b8fd 100644
--- a/src/autofit/afloader.c
+++ b/src/autofit/afloader.c
@@ -23,6 +23,8 @@
#include "afmodule.h"
#include "afpic.h"
+#include FT_INTERNAL_CALC_H
+
/* Initialize glyph loader. */
@@ -76,6 +78,14 @@
}
+#define af_intToFixed( i ) \
+ ( (FT_Fixed)( (FT_UInt32)(i) << 16 ) )
+#define af_fixedToInt( x ) \
+ ( (FT_Short)( ( (FT_UInt32)(x) + 0x8000U ) >> 16 ) )
+#define af_floatToFixed( f ) \
+ ( (FT_Fixed)( (f) * 65536.0 + 0.5 ) )
+
+
/* Do the main work of `af_loader_load_glyph'. Note that we never */
/* have to deal with composite glyphs as those get loaded into */
/* FT_GLYPH_FORMAT_OUTLINE by the recursed `FT_Load_Glyph' function. */
@@ -88,6 +98,8 @@
FT_UInt glyph_index,
FT_Int32 load_flags )
{
+ AF_Module module = loader->globals->module;
+
FT_Error error;
FT_Face face = loader->face;
AF_StyleMetrics metrics = loader->metrics;
@@ -103,6 +115,132 @@
if ( error )
goto Exit;
+ /*
+ * Apply stem darkening (emboldening) here before hints are applied to
+ * the outline. Glyphs are scaled down proportionally to the
+ * emboldening so that curve points don't fall outside their precomputed
+ * blue zones.
+ *
+ * Any emboldening done by the font driver (e.g., the CFF driver)
+ * doesn't reach here because the autohinter loads the unprocessed
+ * glyphs in font units for analysis (functions `af_*_metrics_init_*')
+ * and then above to prepare it for the rasterizers by itself,
+ * independently of the font driver. So emboldening must be done here,
+ * within the autohinter.
+ *
+ * All glyphs to be autohinted pass through here one by one. The
+ * standard widths can therefore change from one glyph to the next,
+ * depending on what script a glyph is assigned to (each script has its
+ * own set of standard widths and other metrics). The darkening amount
+ * must therefore be recomputed for each size and
+ * `standard_{vertical,horizontal}_width' change.
+ */
+ if ( !module->no_stem_darkening )
+ {
+ AF_FaceGlobals globals = loader->globals;
+ AF_WritingSystemClass writing_system_class;
+
+ FT_Pos stdVW = 0;
+ FT_Pos stdHW = 0;
+
+ FT_Bool size_changed = face->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 );
+
+ FT_Matrix scale_down_matrix = { 0x10000L, 0, 0, 0x10000L };
+
+
+ /* Skip stem darkening for broken fonts. */
+ if ( !face->units_per_EM )
+ goto After_Emboldening;
+
+ /*
+ * We depend on the writing system (script analyzers) to supply
+ * standard widths for the script of the glyph we are looking at. If
+ * it can't deliver, stem darkening is effectively disabled.
+ */
+ writing_system_class =
+ AF_WRITING_SYSTEM_CLASSES_GET[metrics->style_class->writing_system];
+
+ if ( writing_system_class->style_metrics_getstdw )
+ writing_system_class->style_metrics_getstdw( metrics,
+ &stdHW,
+ &stdVW );
+ else
+ goto After_Emboldening;
+
+
+ if ( size_changed ||
+ ( stdVW > 0 && stdVW != globals->standard_vertical_width ) )
+ {
+ FT_Fixed darken_by_font_units_x, darken_x;
+
+
+ darken_by_font_units_x =
+ af_intToFixed( af_loader_compute_darkening( loader,
+ face,
+ stdVW ) );
+ darken_x = FT_DivFix( FT_MulFix( darken_by_font_units_x,
+ face->size->metrics.x_scale ),
+ em_ratio );
+
+ globals->standard_vertical_width = stdVW;
+ globals->stem_darkening_for_ppem = face->size->metrics.x_ppem;
+ globals->darken_x = af_fixedToInt( darken_x );
+ }
+
+ if ( size_changed ||
+ ( stdHW > 0 && stdHW != globals->standard_horizontal_width ) )
+ {
+ FT_Fixed darken_by_font_units_y, darken_y;
+
+
+ darken_by_font_units_y =
+ af_intToFixed( af_loader_compute_darkening( loader,
+ face,
+ stdHW ) );
+ darken_y = FT_DivFix( FT_MulFix( darken_by_font_units_y,
+ face->size->metrics.y_scale ),
+ em_ratio );
+
+ globals->standard_horizontal_width = stdHW;
+ globals->stem_darkening_for_ppem = face->size->metrics.x_ppem;
+ globals->darken_y = af_fixedToInt( darken_y );
+
+ /*
+ * Scale outlines down on the Y-axis to keep them inside their blue
+ * zones. The stronger the emboldening, the stronger the
+ * downscaling (plus heuristical padding to prevent outlines still
+ * falling out their zones due to rounding).
+ *
+ * Reason: `FT_Outline_Embolden' works by shifting the rightmost
+ * points of stems farther to the right, and topmost points farther
+ * up. This positions points on the Y-axis outside their
+ * pre-computed blue zones and leads to distortion when applying the
+ * hints in the code further below. Code outside this emboldening
+ * block doesn't know we are presenting it with modified outlines
+ * the analyzer didn't see!
+ *
+ * An unfortunate side effect of downscaling is that the emboldening
+ * effect is slightly decreased. The loss becomes more pronounced
+ * versus the CFF driver at smaller sizes, e.g., at 9ppem and below.
+ */
+ globals->scale_down_factor =
+ FT_DivFix( em_size - ( darken_by_font_units_y + af_intToFixed( 8 ) ),
+ em_size );
+ }
+
+ FT_Outline_EmboldenXY( &slot->outline,
+ globals->darken_x,
+ globals->darken_y );
+
+ scale_down_matrix.yy = globals->scale_down_factor;
+ FT_Outline_Transform( &slot->outline, &scale_down_matrix );
+ }
+
+ After_Emboldening:
loader->transformed = internal->glyph_transformed;
if ( loader->transformed )
{
@@ -150,7 +288,8 @@
if ( writing_system_class->style_hints_apply )
- writing_system_class->style_hints_apply( hints,
+ writing_system_class->style_hints_apply( glyph_index,
+ hints,
&gloader->base.outline,
metrics );
}
@@ -404,4 +543,134 @@
}
+ /*
+ * Compute amount of font units the face should be emboldened by, in
+ * analogy to the CFF driver's `cf2_computeDarkening' function. See there
+ * for details of the algorithm.
+ *
+ * XXX: Currently a crude adaption of the original algorithm. Do better?
+ */
+ FT_LOCAL_DEF( FT_Int32 )
+ af_loader_compute_darkening( AF_Loader loader,
+ FT_Face face,
+ FT_Pos standard_width )
+ {
+ AF_Module module = loader->globals->module;
+
+ FT_UShort units_per_EM;
+ FT_Fixed ppem, em_ratio;
+ FT_Fixed stem_width, stem_width_per_1000, scaled_stem, darken_amount;
+ FT_Int log_base_2;
+ FT_Int x1, y1, x2, y2, x3, y3, x4, y4;
+
+
+ ppem = FT_MAX( af_intToFixed( 4 ),
+ af_intToFixed( face->size->metrics.x_ppem ) );
+ units_per_EM = face->units_per_EM;
+
+ em_ratio = FT_DivFix( af_intToFixed( 1000 ),
+ af_intToFixed ( units_per_EM ) );
+ if ( em_ratio < af_floatToFixed( .01 ) )
+ {
+ /* If something goes wrong, don't embolden. */
+ return 0;
+ }
+
+ x1 = module->darken_params[0];
+ y1 = module->darken_params[1];
+ x2 = module->darken_params[2];
+ y2 = module->darken_params[3];
+ x3 = module->darken_params[4];
+ y3 = module->darken_params[5];
+ x4 = module->darken_params[6];
+ y4 = module->darken_params[7];
+
+ if ( standard_width <= 0 )
+ {
+ stem_width = af_intToFixed( 75 ); /* taken from cf2font.c */
+ stem_width_per_1000 = stem_width;
+ }
+ else
+ {
+ stem_width = af_intToFixed( standard_width );
+ stem_width_per_1000 = FT_MulFix( stem_width, em_ratio );
+ }
+
+ log_base_2 = FT_MSB( (FT_UInt32)stem_width_per_1000 ) +
+ FT_MSB( (FT_UInt32)ppem );
+
+ if ( log_base_2 >= 46 )
+ {
+ /* possible overflow */
+ scaled_stem = af_intToFixed( x4 );
+ }
+ else
+ scaled_stem = FT_MulFix( stem_width_per_1000, ppem );
+
+ /* now apply the darkening parameters */
+ if ( scaled_stem < af_intToFixed( x1 ) )
+ darken_amount = FT_DivFix( af_intToFixed( y1 ), ppem );
+
+ else if ( scaled_stem < af_intToFixed( x2 ) )
+ {
+ FT_Int xdelta = x2 - x1;
+ FT_Int ydelta = y2 - y1;
+ FT_Int x = stem_width_per_1000 -
+ FT_DivFix( af_intToFixed( x1 ), ppem );
+
+
+ if ( !xdelta )
+ goto Try_x3;
+
+ darken_amount = FT_MulDiv( x, ydelta, xdelta ) +
+ FT_DivFix( af_intToFixed( y1 ), ppem );
+ }
+
+ else if ( scaled_stem < af_intToFixed( x3 ) )
+ {
+ Try_x3:
+ {
+ FT_Int xdelta = x3 - x2;
+ FT_Int ydelta = y3 - y2;
+ FT_Int x = stem_width_per_1000 -
+ FT_DivFix( af_intToFixed( x2 ), ppem );
+
+
+ if ( !xdelta )
+ goto Try_x4;
+
+ darken_amount = FT_MulDiv( x, ydelta, xdelta ) +
+ FT_DivFix( af_intToFixed( y2 ), ppem );
+ }
+ }
+
+ else if ( scaled_stem < af_intToFixed( x4 ) )
+ {
+ Try_x4:
+ {
+ FT_Int xdelta = x4 - x3;
+ FT_Int ydelta = y4 - y3;
+ FT_Int x = stem_width_per_1000 -
+ FT_DivFix( af_intToFixed( x3 ), ppem );
+
+
+ if ( !xdelta )
+ goto Use_y4;
+
+ darken_amount = FT_MulDiv( x, ydelta, xdelta ) +
+ FT_DivFix( af_intToFixed( y3 ), ppem );
+ }
+ }
+
+ else
+ {
+ Use_y4:
+ darken_amount = FT_DivFix( af_intToFixed( y4 ), ppem );
+ }
+
+ /* Convert darken_amount from per 1000 em to true character space. */
+ return af_fixedToInt( FT_DivFix( darken_amount, em_ratio ) );
+ }
+
+
/* END */
diff --git a/src/autofit/afloader.h b/src/autofit/afloader.h
index 37cfd14..4c4affc 100644
--- a/src/autofit/afloader.h
+++ b/src/autofit/afloader.h
@@ -75,6 +75,11 @@ FT_BEGIN_HEADER
FT_UInt gindex,
FT_Int32 load_flags );
+ FT_LOCAL_DEF( FT_Int32 )
+ af_loader_compute_darkening( AF_Loader loader,
+ FT_Face face,
+ FT_Pos standard_width );
+
/* */
diff --git a/src/autofit/afmodule.c b/src/autofit/afmodule.c
index 8ae425c..45fd360 100644
--- a/src/autofit/afmodule.c
+++ b/src/autofit/afmodule.c
@@ -25,6 +25,10 @@
#ifdef FT_DEBUG_AUTOFIT
#ifndef FT_MAKE_OPTION_SINGLE_OBJECT
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
extern void
af_glyph_hints_dump_segments( AF_GlyphHints hints,
FT_Bool to_stdout );
@@ -34,6 +38,10 @@
extern void
af_glyph_hints_dump_edges( AF_GlyphHints hints,
FT_Bool to_stdout );
+#ifdef __cplusplus
+ }
+#endif
+
#endif
int _af_debug_disable_horz_hints;
@@ -169,6 +177,46 @@
return error;
}
#endif /* AF_CONFIG_OPTION_USE_WARPER */
+ else if ( !ft_strcmp( property_name, "darkening-parameters" ) )
+ {
+ FT_Int* darken_params = (FT_Int*)value;
+
+ FT_Int x1 = darken_params[0];
+ FT_Int y1 = darken_params[1];
+ FT_Int x2 = darken_params[2];
+ FT_Int y2 = darken_params[3];
+ FT_Int x3 = darken_params[4];
+ FT_Int y3 = darken_params[5];
+ FT_Int x4 = darken_params[6];
+ FT_Int y4 = darken_params[7];
+
+
+ if ( x1 < 0 || x2 < 0 || x3 < 0 || x4 < 0 ||
+ y1 < 0 || y2 < 0 || y3 < 0 || y4 < 0 ||
+ x1 > x2 || x2 > x3 || x3 > x4 ||
+ y1 > 500 || y2 > 500 || y3 > 500 || y4 > 500 )
+ return FT_THROW( Invalid_Argument );
+
+ module->darken_params[0] = x1;
+ module->darken_params[1] = y1;
+ module->darken_params[2] = x2;
+ module->darken_params[3] = y2;
+ module->darken_params[4] = x3;
+ module->darken_params[5] = y3;
+ module->darken_params[6] = x4;
+ module->darken_params[7] = y4;
+
+ return error;
+ }
+ else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
+ {
+ FT_Bool* no_stem_darkening = (FT_Bool*)value;
+
+
+ module->no_stem_darkening = *no_stem_darkening;
+
+ return error;
+ }
FT_TRACE0(( "af_property_set: missing property `%s'\n",
property_name ));
@@ -245,6 +293,33 @@
return error;
}
#endif /* AF_CONFIG_OPTION_USE_WARPER */
+ else if ( !ft_strcmp( property_name, "darkening-parameters" ) )
+ {
+ FT_Int* darken_params = module->darken_params;
+ FT_Int* val = (FT_Int*)value;
+
+
+ val[0] = darken_params[0];
+ val[1] = darken_params[1];
+ val[2] = darken_params[2];
+ val[3] = darken_params[3];
+ val[4] = darken_params[4];
+ val[5] = darken_params[5];
+ val[6] = darken_params[6];
+ val[7] = darken_params[7];
+
+ return error;
+ }
+ else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
+ {
+ FT_Bool no_stem_darkening = module->no_stem_darkening;
+ FT_Bool* val = (FT_Bool*)value;
+
+
+ *val = no_stem_darkening;
+
+ return error;
+ }
FT_TRACE0(( "af_property_get: missing property `%s'\n",
property_name ));
@@ -254,8 +329,8 @@
FT_DEFINE_SERVICE_PROPERTIESREC(
af_service_properties,
- (FT_Properties_SetFunc)af_property_set,
- (FT_Properties_GetFunc)af_property_get )
+ (FT_Properties_SetFunc)af_property_set, /* set_property */
+ (FT_Properties_GetFunc)af_property_get ) /* get_property */
FT_DEFINE_SERVICEDESCREC1(
@@ -291,11 +366,21 @@
AF_Module module = (AF_Module)ft_module;
- module->fallback_style = AF_STYLE_FALLBACK;
- module->default_script = AF_SCRIPT_DEFAULT;
+ module->fallback_style = AF_STYLE_FALLBACK;
+ module->default_script = AF_SCRIPT_DEFAULT;
#ifdef AF_CONFIG_OPTION_USE_WARPER
- module->warping = 0;
+ module->warping = 0;
#endif
+ module->no_stem_darkening = TRUE;
+
+ module->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1;
+ module->darken_params[1] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1;
+ module->darken_params[2] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2;
+ module->darken_params[3] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2;
+ module->darken_params[4] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3;
+ module->darken_params[5] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3;
+ module->darken_params[6] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4;
+ module->darken_params[7] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4;
return FT_Err_Ok;
}
diff --git a/src/autofit/afmodule.h b/src/autofit/afmodule.h
index b9c2fd8..3c61d89 100644
--- a/src/autofit/afmodule.h
+++ b/src/autofit/afmodule.h
@@ -41,6 +41,8 @@ FT_BEGIN_HEADER
#ifdef AF_CONFIG_OPTION_USE_WARPER
FT_Bool warping;
#endif
+ FT_Bool no_stem_darkening;
+ FT_Int darken_params[8];
} AF_ModuleRec, *AF_Module;
diff --git a/src/autofit/afpic.c b/src/autofit/afpic.c
index 5589e61..37254a2 100644
--- a/src/autofit/afpic.c
+++ b/src/autofit/afpic.c
@@ -122,7 +122,7 @@
#include "afwrtsys.h"
#undef SCRIPT
-#define SCRIPT( s, S, d, h, sc1, sc2, sc3 ) \
+#define SCRIPT( s, S, d, h, sss ) \
FT_Init_Class_af_ ## s ## _script_class( \
&container->af_script_classes_rec[ss++] );
diff --git a/src/autofit/afpic.h b/src/autofit/afpic.h
index 25071e3..9b45069 100644
--- a/src/autofit/afpic.h
+++ b/src/autofit/afpic.h
@@ -20,8 +20,6 @@
#define __AFPIC_H__
-FT_BEGIN_HEADER
-
#include FT_INTERNAL_PIC_H
@@ -43,6 +41,8 @@ FT_BEGIN_HEADER
#include "aftypes.h"
+FT_BEGIN_HEADER
+
typedef struct AFModulePIC_
{
FT_ServiceDescRec* af_services;
@@ -93,12 +93,12 @@ FT_BEGIN_HEADER
FT_Error
autofit_module_class_pic_init( FT_Library library );
+FT_END_HEADER
+
#endif /* FT_CONFIG_OPTION_PIC */
/* */
-FT_END_HEADER
-
#endif /* __AFPIC_H__ */
diff --git a/src/autofit/afranges.c b/src/autofit/afranges.c
index c1e0afb..cf8bb7c 100644
--- a/src/autofit/afranges.c
+++ b/src/autofit/afranges.c
@@ -18,6 +18,43 @@
#include "afranges.h"
+ /*
+ * The algorithm for assigning properties and styles to the `glyph_styles'
+ * array is as follows (cf. the implementation in
+ * `af_face_globals_compute_style_coverage').
+ *
+ * Walk over all scripts (as listed in `afscript.h').
+ *
+ * For a given script, walk over all styles (as listed in `afstyles.h').
+ * The order of styles is important and should be as follows.
+ *
+ * - First come styles based on OpenType features (small caps, for
+ * example). Since features rely on glyph indices, thus completely
+ * bypassing character codes, no properties are assigned.
+ *
+ * - Next comes the default style, using the character ranges as defined
+ * below. This also assigns properties.
+ *
+ * Note that there also exist fallback scripts, mainly covering
+ * superscript and subscript glyphs of a script that are not present as
+ * OpenType features. Fallback scripts are defined below, also
+ * assigning properties; they are applied after the corresponding
+ * script.
+ *
+ */
+
+
+ /* XXX Check base character ranges again: */
+ /* Right now, they are quickly derived by visual inspection. */
+ /* I can imagine that fine-tuning is necessary. */
+
+ /* for the auto-hinter, a `non-base character' is something that should */
+ /* 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 */
+
const AF_Script_UniRangeRec af_arab_uniranges[] =
{
@@ -30,6 +67,30 @@
AF_UNIRANGE_REC( 0UL, 0UL )
};
+ const AF_Script_UniRangeRec af_arab_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0600UL, 0x0605UL ),
+ AF_UNIRANGE_REC( 0x0610UL, 0x061AUL ),
+ AF_UNIRANGE_REC( 0x064BUL, 0x065FUL ),
+ AF_UNIRANGE_REC( 0x0670UL, 0x0670UL ),
+ AF_UNIRANGE_REC( 0x06D6UL, 0x06DCUL ),
+ AF_UNIRANGE_REC( 0x06DFUL, 0x06E4UL ),
+ AF_UNIRANGE_REC( 0x06E7UL, 0x06E8UL ),
+ AF_UNIRANGE_REC( 0x06EAUL, 0x06EDUL ),
+ AF_UNIRANGE_REC( 0x08E3UL, 0x08FFUL ),
+ AF_UNIRANGE_REC( 0xFBB2UL, 0xFBC1UL ),
+ AF_UNIRANGE_REC( 0xFE70UL, 0xFE70UL ),
+ AF_UNIRANGE_REC( 0xFE72UL, 0xFE72UL ),
+ AF_UNIRANGE_REC( 0xFE74UL, 0xFE74UL ),
+ AF_UNIRANGE_REC( 0xFE76UL, 0xFE76UL ),
+ AF_UNIRANGE_REC( 0xFE78UL, 0xFE78UL ),
+ AF_UNIRANGE_REC( 0xFE7AUL, 0xFE7AUL ),
+ AF_UNIRANGE_REC( 0xFE7CUL, 0xFE7CUL ),
+ AF_UNIRANGE_REC( 0xFE7EUL, 0xFE7EUL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
const AF_Script_UniRangeRec af_cyrl_uniranges[] =
{
AF_UNIRANGE_REC( 0x0400UL, 0x04FFUL ), /* Cyrillic */
@@ -39,23 +100,47 @@
AF_UNIRANGE_REC( 0UL, 0UL )
};
- /* there are some characters in the Devanagari Unicode block that are */
+ const AF_Script_UniRangeRec af_cyrl_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0483UL, 0x0489UL ),
+ AF_UNIRANGE_REC( 0x2DE0UL, 0x2DFFUL ),
+ AF_UNIRANGE_REC( 0xA66FUL, 0xA67FUL ),
+ AF_UNIRANGE_REC( 0xA69EUL, 0xA69FUL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ /* There are some characters in the Devanagari Unicode block that are */
/* generic to Indic scripts; we omit them so that their presence doesn't */
- /* trigger Devanagari */
+ /* trigger Devanagari. */
const AF_Script_UniRangeRec af_deva_uniranges[] =
{
- AF_UNIRANGE_REC( 0x0900UL, 0x093BUL ), /* Devanagari */
+ AF_UNIRANGE_REC( 0x0900UL, 0x093BUL ), /* Devanagari */
/* omitting U+093C nukta */
- AF_UNIRANGE_REC( 0x093DUL, 0x0950UL ),
+ AF_UNIRANGE_REC( 0x093DUL, 0x0950UL ), /* ... continued */
/* omitting U+0951 udatta, U+0952 anudatta */
- AF_UNIRANGE_REC( 0x0953UL, 0x0963UL ),
+ AF_UNIRANGE_REC( 0x0953UL, 0x0963UL ), /* ... continued */
/* omitting U+0964 danda, U+0965 double danda */
- AF_UNIRANGE_REC( 0x0966UL, 0x097FUL ),
- AF_UNIRANGE_REC( 0x20B9UL, 0x20B9UL ), /* (new) Rupee sign */
+ AF_UNIRANGE_REC( 0x0966UL, 0x097FUL ), /* ... continued */
+ AF_UNIRANGE_REC( 0x20B9UL, 0x20B9UL ), /* (new) Rupee sign */
+ AF_UNIRANGE_REC( 0xA8E0UL, 0xA8FFUL ), /* Devanagari Extended */
AF_UNIRANGE_REC( 0UL, 0UL )
};
+ const AF_Script_UniRangeRec af_deva_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0900UL, 0x0902UL ),
+ AF_UNIRANGE_REC( 0x093AUL, 0x093AUL ),
+ AF_UNIRANGE_REC( 0x0941UL, 0x0948UL ),
+ AF_UNIRANGE_REC( 0x094DUL, 0x094DUL ),
+ AF_UNIRANGE_REC( 0x0953UL, 0x0957UL ),
+ AF_UNIRANGE_REC( 0x0962UL, 0x0963UL ),
+ AF_UNIRANGE_REC( 0xA8E0UL, 0xA8F1UL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
const AF_Script_UniRangeRec af_grek_uniranges[] =
{
AF_UNIRANGE_REC( 0x0370UL, 0x03FFUL ), /* Greek and Coptic */
@@ -63,6 +148,19 @@
AF_UNIRANGE_REC( 0UL, 0UL )
};
+ const AF_Script_UniRangeRec af_grek_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x037AUL, 0x037AUL ),
+ AF_UNIRANGE_REC( 0x0384UL, 0x0385UL ),
+ AF_UNIRANGE_REC( 0x1FBDUL, 0x1FC1UL ),
+ AF_UNIRANGE_REC( 0x1FCDUL, 0x1FCFUL ),
+ AF_UNIRANGE_REC( 0x1FDDUL, 0x1FDFUL ),
+ AF_UNIRANGE_REC( 0x1FEDUL, 0x1FEFUL ),
+ AF_UNIRANGE_REC( 0x1FFDUL, 0x1FFEUL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
const AF_Script_UniRangeRec af_hebr_uniranges[] =
{
AF_UNIRANGE_REC( 0x0590UL, 0x05FFUL ), /* Hebrew */
@@ -70,51 +168,225 @@
AF_UNIRANGE_REC( 0UL, 0UL )
};
+ const AF_Script_UniRangeRec af_hebr_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0591UL, 0x05BFUL ),
+ AF_UNIRANGE_REC( 0x05C1UL, 0x05C2UL ),
+ AF_UNIRANGE_REC( 0x05C4UL, 0x05C5UL ),
+ AF_UNIRANGE_REC( 0x05C7UL, 0x05C7UL ),
+ AF_UNIRANGE_REC( 0xFB1EUL, 0xFB1EUL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_khmr_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x1780UL, 0x17FFUL ), /* Khmer */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_khmr_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x17B7UL, 0x17BDUL ),
+ AF_UNIRANGE_REC( 0x17C6UL, 0x17C6UL ),
+ AF_UNIRANGE_REC( 0x17C9UL, 0x17D3UL ),
+ AF_UNIRANGE_REC( 0x17DDUL, 0x17DDUL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_khms_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x19E0UL, 0x19FFUL ), /* Khmer Symbols */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_khms_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_lao_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0E80UL, 0x0EFFUL ), /* Lao */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_lao_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0EB1UL, 0x0EB1UL ),
+ AF_UNIRANGE_REC( 0x0EB4UL, 0x0EBCUL ),
+ AF_UNIRANGE_REC( 0x0EC8UL, 0x0ECDUL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
const AF_Script_UniRangeRec af_latn_uniranges[] =
{
AF_UNIRANGE_REC( 0x0020UL, 0x007FUL ), /* Basic Latin (no control chars) */
- AF_UNIRANGE_REC( 0x00A0UL, 0x00FFUL ), /* Latin-1 Supplement (no control chars) */
+ AF_UNIRANGE_REC( 0x00A0UL, 0x00A9UL ), /* Latin-1 Supplement (no control chars) */
+ AF_UNIRANGE_REC( 0x00ABUL, 0x00B1UL ), /* ... continued */
+ AF_UNIRANGE_REC( 0x00B4UL, 0x00B8UL ), /* ... continued */
+ AF_UNIRANGE_REC( 0x00BBUL, 0x00FFUL ), /* ... continued */
AF_UNIRANGE_REC( 0x0100UL, 0x017FUL ), /* Latin Extended-A */
AF_UNIRANGE_REC( 0x0180UL, 0x024FUL ), /* Latin Extended-B */
AF_UNIRANGE_REC( 0x0250UL, 0x02AFUL ), /* IPA Extensions */
- AF_UNIRANGE_REC( 0x02B0UL, 0x02FFUL ), /* Spacing Modifier Letters */
+ AF_UNIRANGE_REC( 0x02B9UL, 0x02DFUL ), /* Spacing Modifier Letters */
+ AF_UNIRANGE_REC( 0x02E5UL, 0x02FFUL ), /* ... continued */
AF_UNIRANGE_REC( 0x0300UL, 0x036FUL ), /* Combining Diacritical Marks */
- AF_UNIRANGE_REC( 0x1D00UL, 0x1D7FUL ), /* Phonetic Extensions */
- AF_UNIRANGE_REC( 0x1D80UL, 0x1DBFUL ), /* Phonetic Extensions Supplement */
+ AF_UNIRANGE_REC( 0x1AB0UL, 0x1ABEUL ), /* Combining Diacritical Marks Extended */
+ AF_UNIRANGE_REC( 0x1D00UL, 0x1D2BUL ), /* Phonetic Extensions */
+ AF_UNIRANGE_REC( 0x1D6BUL, 0x1D77UL ), /* ... continued */
+ AF_UNIRANGE_REC( 0x1D79UL, 0x1D7FUL ), /* ... continued */
+ AF_UNIRANGE_REC( 0x1D80UL, 0x1D9AUL ), /* Phonetic Extensions Supplement */
AF_UNIRANGE_REC( 0x1DC0UL, 0x1DFFUL ), /* Combining Diacritical Marks Supplement */
AF_UNIRANGE_REC( 0x1E00UL, 0x1EFFUL ), /* Latin Extended Additional */
AF_UNIRANGE_REC( 0x2000UL, 0x206FUL ), /* General Punctuation */
- AF_UNIRANGE_REC( 0x2070UL, 0x209FUL ), /* Superscripts and Subscripts */
AF_UNIRANGE_REC( 0x20A0UL, 0x20B8UL ), /* Currency Symbols ... */
AF_UNIRANGE_REC( 0x20BAUL, 0x20CFUL ), /* ... except new Rupee sign */
AF_UNIRANGE_REC( 0x2150UL, 0x218FUL ), /* Number Forms */
- AF_UNIRANGE_REC( 0x2460UL, 0x24FFUL ), /* Enclosed Alphanumerics */
- AF_UNIRANGE_REC( 0x2C60UL, 0x2C7FUL ), /* Latin Extended-C */
+ AF_UNIRANGE_REC( 0x2C60UL, 0x2C7BUL ), /* Latin Extended-C */
+ AF_UNIRANGE_REC( 0x2C7EUL, 0x2C7FUL ), /* ... continued */
AF_UNIRANGE_REC( 0x2E00UL, 0x2E7FUL ), /* Supplemental Punctuation */
- AF_UNIRANGE_REC( 0xA720UL, 0xA7FFUL ), /* Latin Extended-D */
+ AF_UNIRANGE_REC( 0xA720UL, 0xA76FUL ), /* Latin Extended-D */
+ AF_UNIRANGE_REC( 0xA771UL, 0xA7F7UL ), /* ... continued */
+ AF_UNIRANGE_REC( 0xA7FAUL, 0xA7FFUL ), /* ... continued */
+ AF_UNIRANGE_REC( 0xAB30UL, 0xAB5BUL ), /* Latin Extended-E */
+ AF_UNIRANGE_REC( 0xAB60UL, 0xAB6FUL ), /* ... continued */
AF_UNIRANGE_REC( 0xFB00UL, 0xFB06UL ), /* Alphab. Present. Forms (Latin Ligs) */
AF_UNIRANGE_REC( 0x1D400UL, 0x1D7FFUL ), /* Mathematical Alphanumeric Symbols */
- AF_UNIRANGE_REC( 0x1F100UL, 0x1F1FFUL ), /* Enclosed Alphanumeric Supplement */
AF_UNIRANGE_REC( 0UL, 0UL )
};
+ const AF_Script_UniRangeRec af_latn_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x005EUL, 0x0060UL ),
+ AF_UNIRANGE_REC( 0x007EUL, 0x007EUL ),
+ AF_UNIRANGE_REC( 0x00A8UL, 0x00A9UL ),
+ AF_UNIRANGE_REC( 0x00AEUL, 0x00B0UL ),
+ AF_UNIRANGE_REC( 0x00B4UL, 0x00B4UL ),
+ AF_UNIRANGE_REC( 0x00B8UL, 0x00B8UL ),
+ AF_UNIRANGE_REC( 0x00BCUL, 0x00BEUL ),
+ AF_UNIRANGE_REC( 0x02B9UL, 0x02DFUL ),
+ AF_UNIRANGE_REC( 0x02E5UL, 0x02FFUL ),
+ AF_UNIRANGE_REC( 0x0300UL, 0x036FUL ),
+ AF_UNIRANGE_REC( 0x1AB0UL, 0x1ABEUL ),
+ AF_UNIRANGE_REC( 0x1DC0UL, 0x1DFFUL ),
+ AF_UNIRANGE_REC( 0x2017UL, 0x2017UL ),
+ AF_UNIRANGE_REC( 0x203EUL, 0x203EUL ),
+ AF_UNIRANGE_REC( 0xA788UL, 0xA788UL ),
+ AF_UNIRANGE_REC( 0xA7F8UL, 0xA7FAUL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_latb_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x1D62UL, 0x1D6AUL ), /* some small subscript letters */
+ AF_UNIRANGE_REC( 0x2080UL, 0x209CUL ), /* subscript digits and letters */
+ AF_UNIRANGE_REC( 0x2C7CUL, 0x2C7CUL ), /* latin subscript small letter j */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_latb_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_latp_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x00AAUL, 0x00AAUL ), /* feminine ordinal indicator */
+ AF_UNIRANGE_REC( 0x00B2UL, 0x00B3UL ), /* superscript two and three */
+ AF_UNIRANGE_REC( 0x00B9UL, 0x00BAUL ), /* superscript one, masc. ord. indic. */
+ AF_UNIRANGE_REC( 0x02B0UL, 0x02B8UL ), /* some latin superscript mod. letters */
+ AF_UNIRANGE_REC( 0x02E0UL, 0x02E4UL ), /* some IPA modifier letters */
+ AF_UNIRANGE_REC( 0x1D2CUL, 0x1D61UL ), /* latin superscript modifier letters */
+ AF_UNIRANGE_REC( 0x1D78UL, 0x1D78UL ), /* modifier letter cyrillic en */
+ AF_UNIRANGE_REC( 0x1D9BUL, 0x1DBFUL ), /* more modifier letters */
+ AF_UNIRANGE_REC( 0x2070UL, 0x207FUL ), /* superscript digits and letters */
+ AF_UNIRANGE_REC( 0x2C7DUL, 0x2C7DUL ), /* modifier letter capital v */
+ AF_UNIRANGE_REC( 0xA770UL, 0xA770UL ), /* modifier letter us */
+ AF_UNIRANGE_REC( 0xA7F8UL, 0xA7F9UL ), /* more modifier letters */
+ AF_UNIRANGE_REC( 0xAB5CUL, 0xAB5FUL ), /* more modifier letters */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_latp_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_mymr_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x1000UL, 0x109FUL ), /* Myanmar */
+ AF_UNIRANGE_REC( 0xA9E0UL, 0xA9FFUL ), /* Myanmar Extended-B */
+ AF_UNIRANGE_REC( 0xAA60UL, 0xAA7FUL ), /* Myanmar Extended-A */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_mymr_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x102DUL, 0x1030UL ),
+ AF_UNIRANGE_REC( 0x1032UL, 0x1037UL ),
+ AF_UNIRANGE_REC( 0x103AUL, 0x103AUL ),
+ AF_UNIRANGE_REC( 0x103DUL, 0x103EUL ),
+ AF_UNIRANGE_REC( 0x1058UL, 0x1059UL ),
+ AF_UNIRANGE_REC( 0x105EUL, 0x1060UL ),
+ AF_UNIRANGE_REC( 0x1071UL, 0x1074UL ),
+ AF_UNIRANGE_REC( 0x1082UL, 0x1082UL ),
+ AF_UNIRANGE_REC( 0x1085UL, 0x1086UL ),
+ AF_UNIRANGE_REC( 0x108DUL, 0x108DUL ),
+ AF_UNIRANGE_REC( 0xA9E5UL, 0xA9E5UL ),
+ AF_UNIRANGE_REC( 0xAA7CUL, 0xAA7CUL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
const AF_Script_UniRangeRec af_none_uniranges[] =
{
AF_UNIRANGE_REC( 0UL, 0UL )
};
+ const AF_Script_UniRangeRec af_none_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
const AF_Script_UniRangeRec af_telu_uniranges[] =
{
AF_UNIRANGE_REC( 0x0C00UL, 0x0C7FUL ), /* Telugu */
AF_UNIRANGE_REC( 0UL, 0UL )
};
+ const AF_Script_UniRangeRec af_telu_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0C00UL, 0x0C00UL ),
+ AF_UNIRANGE_REC( 0x0C3EUL, 0x0C40UL ),
+ AF_UNIRANGE_REC( 0x0C46UL, 0x0C56UL ),
+ AF_UNIRANGE_REC( 0x0C62UL, 0x0C63UL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
const AF_Script_UniRangeRec af_thai_uniranges[] =
{
AF_UNIRANGE_REC( 0x0E00UL, 0x0E7FUL ), /* Thai */
AF_UNIRANGE_REC( 0UL, 0UL )
};
+ const AF_Script_UniRangeRec af_thai_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0E31UL, 0x0E31UL ),
+ AF_UNIRANGE_REC( 0x0E34UL, 0x0E3AUL ),
+ AF_UNIRANGE_REC( 0x0E47UL, 0x0E4EUL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
#ifdef AF_CONFIG_OPTION_INDIC
const AF_Script_UniRangeRec af_beng_uniranges[] =
@@ -123,72 +395,197 @@
AF_UNIRANGE_REC( 0UL, 0UL )
};
+ const AF_Script_UniRangeRec af_beng_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0981UL, 0x0981UL ),
+ AF_UNIRANGE_REC( 0x09BCUL, 0x09BCUL ),
+ AF_UNIRANGE_REC( 0x09C1UL, 0x09C4UL ),
+ AF_UNIRANGE_REC( 0x09CDUL, 0x09CDUL ),
+ AF_UNIRANGE_REC( 0x09E2UL, 0x09E3UL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
const AF_Script_UniRangeRec af_gujr_uniranges[] =
{
AF_UNIRANGE_REC( 0x0A80UL, 0x0AFFUL ), /* Gujarati */
AF_UNIRANGE_REC( 0UL, 0UL )
};
+ const AF_Script_UniRangeRec af_gujr_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0A81UL, 0x0A82UL ),
+ AF_UNIRANGE_REC( 0x0ABCUL, 0x0ABCUL ),
+ AF_UNIRANGE_REC( 0x0AC1UL, 0x0AC8UL ),
+ AF_UNIRANGE_REC( 0x0ACDUL, 0x0ACDUL ),
+ AF_UNIRANGE_REC( 0x0AE2UL, 0x0AE3UL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
const AF_Script_UniRangeRec af_guru_uniranges[] =
{
AF_UNIRANGE_REC( 0x0A00UL, 0x0A7FUL ), /* Gurmukhi */
AF_UNIRANGE_REC( 0UL, 0UL )
};
+ const AF_Script_UniRangeRec af_guru_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0A01UL, 0x0A02UL ),
+ AF_UNIRANGE_REC( 0x0A3CUL, 0x0A3EUL ),
+ AF_UNIRANGE_REC( 0x0A41UL, 0x0A51UL ),
+ AF_UNIRANGE_REC( 0x0A70UL, 0x0A71UL ),
+ AF_UNIRANGE_REC( 0x0A75UL, 0x0A75UL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
const AF_Script_UniRangeRec af_knda_uniranges[] =
{
AF_UNIRANGE_REC( 0x0C80UL, 0x0CFFUL ), /* Kannada */
AF_UNIRANGE_REC( 0UL, 0UL )
};
+ const AF_Script_UniRangeRec af_knda_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0C81UL, 0x0C81UL ),
+ AF_UNIRANGE_REC( 0x0CBCUL, 0x0CBCUL ),
+ AF_UNIRANGE_REC( 0x0CBFUL, 0x0CBFUL ),
+ AF_UNIRANGE_REC( 0x0CC6UL, 0x0CC6UL ),
+ AF_UNIRANGE_REC( 0x0CCCUL, 0x0CCDUL ),
+ AF_UNIRANGE_REC( 0x0CE2UL, 0x0CE3UL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
const AF_Script_UniRangeRec af_limb_uniranges[] =
{
AF_UNIRANGE_REC( 0x1900UL, 0x194FUL ), /* Limbu */
AF_UNIRANGE_REC( 0UL, 0UL )
};
+ const AF_Script_UniRangeRec af_limb_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x1920UL, 0x1922UL ),
+ AF_UNIRANGE_REC( 0x1927UL, 0x1934UL ),
+ AF_UNIRANGE_REC( 0x1937UL, 0x193BUL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
const AF_Script_UniRangeRec af_mlym_uniranges[] =
{
AF_UNIRANGE_REC( 0x0D00UL, 0x0D7FUL ), /* Malayalam */
AF_UNIRANGE_REC( 0UL, 0UL )
};
+ const AF_Script_UniRangeRec af_mlym_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0D01UL, 0x0D01UL ),
+ AF_UNIRANGE_REC( 0x0D4DUL, 0x0D4EUL ),
+ AF_UNIRANGE_REC( 0x0D62UL, 0x0D63UL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
const AF_Script_UniRangeRec af_orya_uniranges[] =
{
AF_UNIRANGE_REC( 0x0B00UL, 0x0B7FUL ), /* Oriya */
AF_UNIRANGE_REC( 0UL, 0UL )
};
+ const AF_Script_UniRangeRec af_orya_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0B01UL, 0x0B02UL ),
+ AF_UNIRANGE_REC( 0x0B3CUL, 0x0B3CUL ),
+ AF_UNIRANGE_REC( 0x0B3FUL, 0x0B3FUL ),
+ AF_UNIRANGE_REC( 0x0B41UL, 0x0B44UL ),
+ AF_UNIRANGE_REC( 0x0B4DUL, 0x0B56UL ),
+ AF_UNIRANGE_REC( 0x0B62UL, 0x0B63UL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
const AF_Script_UniRangeRec af_sinh_uniranges[] =
{
AF_UNIRANGE_REC( 0x0D80UL, 0x0DFFUL ), /* Sinhala */
AF_UNIRANGE_REC( 0UL, 0UL )
};
+ const AF_Script_UniRangeRec af_sinh_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0DCAUL, 0x0DCAUL ),
+ AF_UNIRANGE_REC( 0x0DD2UL, 0x0DD6UL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
const AF_Script_UniRangeRec af_sund_uniranges[] =
{
- AF_UNIRANGE_REC( 0x1B80UL, 0x1BBFUL ), /* Sundanese */
+ AF_UNIRANGE_REC( 0x1B80UL, 0x1BBFUL ), /* Sundanese */
+ AF_UNIRANGE_REC( 0x1CC0UL, 0x1CCFUL ), /* Sundanese Supplement */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_sund_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x1B80UL, 0x1B82UL ),
+ AF_UNIRANGE_REC( 0x1BA1UL, 0x1BADUL ),
AF_UNIRANGE_REC( 0UL, 0UL )
};
+
const AF_Script_UniRangeRec af_sylo_uniranges[] =
{
AF_UNIRANGE_REC( 0xA800UL, 0xA82FUL ), /* Syloti Nagri */
AF_UNIRANGE_REC( 0UL, 0UL )
};
+ const AF_Script_UniRangeRec af_sylo_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0xA802UL, 0xA802UL ),
+ AF_UNIRANGE_REC( 0xA806UL, 0xA806UL ),
+ AF_UNIRANGE_REC( 0xA80BUL, 0xA80BUL ),
+ AF_UNIRANGE_REC( 0xA825UL, 0xA826UL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
const AF_Script_UniRangeRec af_taml_uniranges[] =
{
AF_UNIRANGE_REC( 0x0B80UL, 0x0BFFUL ), /* Tamil */
AF_UNIRANGE_REC( 0UL, 0UL )
};
+ const AF_Script_UniRangeRec af_taml_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0B82UL, 0x0B82UL ),
+ AF_UNIRANGE_REC( 0x0BC0UL, 0x0BC2UL ),
+ AF_UNIRANGE_REC( 0x0BCDUL, 0x0BCDUL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
const AF_Script_UniRangeRec af_tibt_uniranges[] =
{
AF_UNIRANGE_REC( 0x0F00UL, 0x0FFFUL ), /* Tibetan */
AF_UNIRANGE_REC( 0UL, 0UL )
};
+ const AF_Script_UniRangeRec af_tibt_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0F18UL, 0x0F19UL ),
+ AF_UNIRANGE_REC( 0x0F35UL, 0x0F35UL ),
+ AF_UNIRANGE_REC( 0x0F37UL, 0x0F37UL ),
+ AF_UNIRANGE_REC( 0x0F39UL, 0x0F39UL ),
+ AF_UNIRANGE_REC( 0x0F3EUL, 0x0F3FUL ),
+ AF_UNIRANGE_REC( 0x0F71UL, 0x0F7EUL ),
+ AF_UNIRANGE_REC( 0x0F80UL, 0x0F84UL ),
+ AF_UNIRANGE_REC( 0x0F86UL, 0x0F87UL ),
+ AF_UNIRANGE_REC( 0x0F8DUL, 0x0FBCUL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
#endif /* !AF_CONFIG_OPTION_INDIC */
#ifdef AF_CONFIG_OPTION_CJK
@@ -210,7 +607,6 @@
AF_UNIRANGE_REC( 0x31A0UL, 0x31BFUL ), /* Bopomofo Extended */
AF_UNIRANGE_REC( 0x31C0UL, 0x31EFUL ), /* CJK Strokes */
AF_UNIRANGE_REC( 0x31F0UL, 0x31FFUL ), /* Katakana Phonetic Extensions */
- AF_UNIRANGE_REC( 0x3200UL, 0x32FFUL ), /* Enclosed CJK Letters and Months */
AF_UNIRANGE_REC( 0x3300UL, 0x33FFUL ), /* CJK Compatibility */
AF_UNIRANGE_REC( 0x3400UL, 0x4DBFUL ), /* CJK Unified Ideographs Extension A */
AF_UNIRANGE_REC( 0x4DC0UL, 0x4DFFUL ), /* Yijing Hexagram Symbols */
@@ -224,7 +620,6 @@
AF_UNIRANGE_REC( 0xFF00UL, 0xFFEFUL ), /* Halfwidth and Fullwidth Forms */
AF_UNIRANGE_REC( 0x1B000UL, 0x1B0FFUL ), /* Kana Supplement */
AF_UNIRANGE_REC( 0x1D300UL, 0x1D35FUL ), /* Tai Xuan Hing Symbols */
- AF_UNIRANGE_REC( 0x1F200UL, 0x1F2FFUL ), /* Enclosed Ideographic Supplement */
AF_UNIRANGE_REC( 0x20000UL, 0x2A6DFUL ), /* CJK Unified Ideographs Extension B */
AF_UNIRANGE_REC( 0x2A700UL, 0x2B73FUL ), /* CJK Unified Ideographs Extension C */
AF_UNIRANGE_REC( 0x2B740UL, 0x2B81FUL ), /* CJK Unified Ideographs Extension D */
@@ -232,6 +627,13 @@
AF_UNIRANGE_REC( 0UL, 0UL )
};
+ const AF_Script_UniRangeRec af_hani_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x302AUL, 0x302FUL ),
+ AF_UNIRANGE_REC( 0x3190UL, 0x319FUL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
#endif /* !AF_CONFIG_OPTION_CJK */
/* END */
diff --git a/src/autofit/afranges.h b/src/autofit/afranges.h
index 7c78ab0..bca5084 100644
--- a/src/autofit/afranges.h
+++ b/src/autofit/afranges.h
@@ -26,11 +26,17 @@
FT_BEGIN_HEADER
#undef SCRIPT
-#define SCRIPT( s, S, d, h, sc1, sc2, sc3 ) \
+#define SCRIPT( s, S, d, h, ss ) \
extern const AF_Script_UniRangeRec af_ ## s ## _uniranges[];
#include "afscript.h"
+#undef SCRIPT
+#define SCRIPT( s, S, d, h, ss ) \
+ extern const AF_Script_UniRangeRec af_ ## s ## _nonbase_uniranges[];
+
+#include "afscript.h"
+
/* */
FT_END_HEADER
diff --git a/src/autofit/afscript.h b/src/autofit/afscript.h
index dfcc830..39ec652 100644
--- a/src/autofit/afscript.h
+++ b/src/autofit/afscript.h
@@ -25,114 +25,150 @@
/* by a description string. Then comes the corresponding HarfBuzz */
/* script name tag, followed by a string of standard characters (to */
/* derive the standard width and height of stems). */
+ /* */
+ /* Note that fallback scripts only have a default style, thus we */
+ /* use `HB_SCRIPT_INVALID' as the HarfBuzz script name tag for */
+ /* them. */
SCRIPT( arab, ARAB,
"Arabic",
HB_SCRIPT_ARABIC,
- 0x644, 0x62D, 0x640 ) /* ل ح ـ */
+ "\xD9\x84 \xD8\xAD \xD9\x80" ) /* ل ح ـ */
SCRIPT( cyrl, CYRL,
"Cyrillic",
HB_SCRIPT_CYRILLIC,
- 0x43E, 0x41E, 0x0 ) /* оО */
+ "\xD0\xBE \xD0\x9E" ) /* о О */
SCRIPT( deva, DEVA,
"Devanagari",
HB_SCRIPT_DEVANAGARI,
- 0x920, 0x935, 0x91F ) /* ठ व ट */
+ "\xE0\xA4\xA0 \xE0\xA4\xB5 \xE0\xA4\x9F" ) /* ठ व ट */
SCRIPT( grek, GREK,
"Greek",
HB_SCRIPT_GREEK,
- 0x3BF, 0x39F, 0x0 ) /* οΟ */
+ "\xCE\xBF \xCE\x9F" ) /* ο Ο */
SCRIPT( hebr, HEBR,
"Hebrew",
HB_SCRIPT_HEBREW,
- 0x5DD, 0x0, 0x0 ) /* ם */
+ "\xD7\x9D" ) /* ם */
+
+ /* only digit zero has a simple shape in the Khmer script */
+ SCRIPT( khmr, KHMR,
+ "Khmer",
+ HB_SCRIPT_KHMER,
+ "\xE1\x9F\xA0" ) /* ០ */
+
+ SCRIPT( khms, KHMS,
+ "Khmer Symbols",
+ HB_SCRIPT_INVALID,
+ "\xE1\xA7\xA1 \xE1\xA7\xAA" ) /* ᧡ ᧪ */
+
+ /* only digit zero has a simple shape in the Lao script */
+ SCRIPT( lao, LAO,
+ "Lao",
+ HB_SCRIPT_LAO,
+ "\xE0\xBB\x90" ) /* ໐ */
SCRIPT( latn, LATN,
"Latin",
HB_SCRIPT_LATIN,
- 'o', 'O', '0' )
+ "o O 0" )
+
+ SCRIPT( latb, LATB,
+ "Latin Subscript Fallback",
+ HB_SCRIPT_INVALID,
+ "\xE2\x82\x92 \xE2\x82\x80" ) /* ₒ ₀ */
+
+ SCRIPT( latp, LATP,
+ "Latin Superscript Fallback",
+ HB_SCRIPT_INVALID,
+ "\xE1\xB5\x92 \xE1\xB4\xBC \xE2\x81\xB0" ) /* ᵒ ᴼ ⁰ */
+
+ SCRIPT( mymr, MYMR,
+ "Myanmar",
+ HB_SCRIPT_MYANMAR,
+ "\xE1\x80\x9D \xE1\x80\x84 \xE1\x80\x82" ) /* ဝ င ဂ */
SCRIPT( none, NONE,
"no script",
HB_SCRIPT_INVALID,
- 0x0, 0x0, 0x0 )
+ "" )
/* there are no simple forms for letters; we thus use two digit shapes */
SCRIPT( telu, TELU,
"Telugu",
HB_SCRIPT_TELUGU,
- 0xC66, 0xC67, 0x0 ) /* ౦ ౧ */
+ "\xE0\xB1\xA6 \xE0\xB1\xA7" ) /* ౦ ౧ */
SCRIPT( thai, THAI,
"Thai",
HB_SCRIPT_THAI,
- 0xE32, 0xE45, 0xE50 ) /* า ๅ ๐ */
+ "\xE0\xB8\xB2 \xE0\xB9\x85 \xE0\xB9\x90" ) /* า ๅ ๐ */
#ifdef AF_CONFIG_OPTION_INDIC
SCRIPT( beng, BENG,
"Bengali",
HB_SCRIPT_BENGALI,
- 'o', 0x0, 0x0 ) /* XXX */
+ "o" ) /* XXX */
SCRIPT( gujr, GUJR,
"Gujarati",
HB_SCRIPT_GUJARATI,
- 'o', 0x0, 0x0 ) /* XXX */
+ "o" ) /* XXX */
SCRIPT( guru, GURU,
"Gurmukhi",
HB_SCRIPT_GURMUKHI,
- 'o', 0x0, 0x0 ) /* XXX */
+ "o" ) /* XXX */
SCRIPT( knda, KNDA,
"Kannada",
HB_SCRIPT_KANNADA,
- 'o', 0x0, 0x0 ) /* XXX */
+ "o" ) /* XXX */
SCRIPT( limb, LIMB,
"Limbu",
HB_SCRIPT_LIMBU,
- 'o', 0x0, 0x0 ) /* XXX */
+ "o" ) /* XXX */
SCRIPT( mlym, MLYM,
"Malayalam",
HB_SCRIPT_MALAYALAM,
- 'o', 0x0, 0x0 ) /* XXX */
+ "o" ) /* XXX */
SCRIPT( orya, ORYA,
"Oriya",
HB_SCRIPT_ORIYA,
- 'o', 0x0, 0x0 ) /* XXX */
+ "o" ) /* XXX */
SCRIPT( sinh, SINH,
"Sinhala",
HB_SCRIPT_SINHALA,
- 'o', 0x0, 0x0 ) /* XXX */
+ "o" ) /* XXX */
SCRIPT( sund, SUND,
"Sundanese",
HB_SCRIPT_SUNDANESE,
- 'o', 0x0, 0x0 ) /* XXX */
+ "o" ) /* XXX */
SCRIPT( sylo, SYLO,
"Syloti Nagri",
HB_SCRIPT_SYLOTI_NAGRI,
- 'o', 0x0, 0x0 ) /* XXX */
+ "o" ) /* XXX */
SCRIPT( taml, TAML,
"Tamil",
HB_SCRIPT_TAMIL,
- 'o', 0x0, 0x0 ) /* XXX */
+ "o" ) /* XXX */
SCRIPT( tibt, TIBT,
"Tibetan",
HB_SCRIPT_TIBETAN,
- 'o', 0x0, 0x0 ) /* XXX */
+ "o" ) /* XXX */
#endif /* AF_CONFIG_OPTION_INDIC */
@@ -141,7 +177,7 @@
SCRIPT( hani, HANI,
"CJKV ideographs",
HB_SCRIPT_HAN,
- 0x7530, 0x56D7, 0x0 ) /* 田囗 */
+ "\xE7\x94\xB0 \xE5\x9B\x97" ) /* 田 囗 */
#endif /* AF_CONFIG_OPTION_CJK */
diff --git a/src/autofit/afshaper.c b/src/autofit/afshaper.c
new file mode 100644
index 0000000..6ba9190
--- /dev/null
+++ b/src/autofit/afshaper.c
@@ -0,0 +1,676 @@
+/***************************************************************************/
+/* */
+/* afshaper.c */
+/* */
+/* HarfBuzz interface for accessing OpenType features (body). */
+/* */
+/* Copyright 2013-2015 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include "afglobal.h"
+#include "aftypes.h"
+#include "afshaper.h"
+
+#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_afshaper
+
+
+ /*
+ * We use `sets' (in the HarfBuzz sense, which comes quite near to the
+ * usual mathematical meaning) to manage both lookups and glyph indices.
+ *
+ * 1. For each coverage, collect lookup IDs in a set. Note that an
+ * auto-hinter `coverage' is represented by one `feature', and a
+ * feature consists of an arbitrary number of (font specific) `lookup's
+ * that actually do the mapping job. Please check the OpenType
+ * specification for more details on features and lookups.
+ *
+ * 2. Create glyph ID sets from the corresponding lookup sets.
+ *
+ * 3. The glyph set corresponding to AF_COVERAGE_DEFAULT is computed
+ * with all lookups specific to the OpenType script activated. It
+ * relies on the order of AF_DEFINE_STYLE_CLASS entries so that
+ * special coverages (like `oldstyle figures') don't get overwritten.
+ *
+ */
+
+
+ /* load coverage tags */
+#undef COVERAGE
+#define COVERAGE( name, NAME, description, \
+ tag1, tag2, tag3, tag4 ) \
+ static const hb_tag_t name ## _coverage[] = \
+ { \
+ HB_TAG( tag1, tag2, tag3, tag4 ), \
+ HB_TAG_NONE \
+ };
+
+
+#include "afcover.h"
+
+
+ /* define mapping between coverage tags and AF_Coverage */
+#undef COVERAGE
+#define COVERAGE( name, NAME, description, \
+ tag1, tag2, tag3, tag4 ) \
+ name ## _coverage,
+
+
+ static const hb_tag_t* coverages[] =
+ {
+#include "afcover.h"
+
+ NULL /* AF_COVERAGE_DEFAULT */
+ };
+
+
+ /* load HarfBuzz script tags */
+#undef SCRIPT
+#define SCRIPT( s, S, d, h, ss ) h,
+
+
+ static const hb_script_t scripts[] =
+ {
+#include "afscript.h"
+ };
+
+
+ FT_Error
+ af_shaper_get_coverage( AF_FaceGlobals globals,
+ AF_StyleClass style_class,
+ FT_UShort* gstyles )
+ {
+ hb_face_t* face;
+
+ hb_set_t* gsub_lookups; /* GSUB lookups for a given script */
+ hb_set_t* gsub_glyphs; /* glyphs covered by GSUB lookups */
+ hb_set_t* gpos_lookups; /* GPOS lookups for a given script */
+ hb_set_t* gpos_glyphs; /* glyphs covered by GPOS lookups */
+
+ hb_script_t script;
+ const hb_tag_t* coverage_tags;
+ hb_tag_t script_tags[] = { HB_TAG_NONE,
+ HB_TAG_NONE,
+ HB_TAG_NONE,
+ HB_TAG_NONE };
+
+ hb_codepoint_t idx;
+#ifdef FT_DEBUG_LEVEL_TRACE
+ int count;
+#endif
+
+
+ if ( !globals || !style_class || !gstyles )
+ return FT_THROW( Invalid_Argument );
+
+ face = hb_font_get_face( globals->hb_font );
+
+ gsub_lookups = hb_set_create();
+ gsub_glyphs = hb_set_create();
+ gpos_lookups = hb_set_create();
+ gpos_glyphs = hb_set_create();
+
+ coverage_tags = coverages[style_class->coverage];
+ script = scripts[style_class->script];
+
+ /* Convert a HarfBuzz script tag into the corresponding OpenType */
+ /* tag or tags -- some Indic scripts like Devanagari have an old */
+ /* and a new set of features. */
+ hb_ot_tags_from_script( script,
+ &script_tags[0],
+ &script_tags[1] );
+
+ /* `hb_ot_tags_from_script' usually returns HB_OT_TAG_DEFAULT_SCRIPT */
+ /* as the second tag. We change that to HB_TAG_NONE except for the */
+ /* default script. */
+ if ( style_class->script == globals->module->default_script &&
+ style_class->coverage == AF_COVERAGE_DEFAULT )
+ {
+ if ( script_tags[0] == HB_TAG_NONE )
+ script_tags[0] = HB_OT_TAG_DEFAULT_SCRIPT;
+ else
+ {
+ if ( script_tags[1] == HB_TAG_NONE )
+ script_tags[1] = HB_OT_TAG_DEFAULT_SCRIPT;
+ else if ( script_tags[1] != HB_OT_TAG_DEFAULT_SCRIPT )
+ script_tags[2] = HB_OT_TAG_DEFAULT_SCRIPT;
+ }
+ }
+ else
+ {
+ if ( script_tags[1] == HB_OT_TAG_DEFAULT_SCRIPT )
+ script_tags[1] = HB_TAG_NONE;
+ }
+
+ hb_ot_layout_collect_lookups( face,
+ HB_OT_TAG_GSUB,
+ script_tags,
+ NULL,
+ coverage_tags,
+ gsub_lookups );
+
+ if ( hb_set_is_empty( gsub_lookups ) )
+ goto Exit; /* nothing to do */
+
+ hb_ot_layout_collect_lookups( face,
+ HB_OT_TAG_GPOS,
+ script_tags,
+ NULL,
+ coverage_tags,
+ gpos_lookups );
+
+ FT_TRACE4(( "GSUB lookups (style `%s'):\n"
+ " ",
+ af_style_names[style_class->style] ));
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ count = 0;
+#endif
+
+ for ( idx = HB_SET_VALUE_INVALID; hb_set_next( gsub_lookups, &idx ); )
+ {
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_TRACE4(( " %d", idx ));
+ count++;
+#endif
+
+ /* get output coverage of GSUB feature */
+ hb_ot_layout_lookup_collect_glyphs( face,
+ HB_OT_TAG_GSUB,
+ idx,
+ NULL,
+ NULL,
+ NULL,
+ gsub_glyphs );
+ }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( !count )
+ FT_TRACE4(( " (none)" ));
+ FT_TRACE4(( "\n\n" ));
+#endif
+
+ FT_TRACE4(( "GPOS lookups (style `%s'):\n"
+ " ",
+ af_style_names[style_class->style] ));
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ count = 0;
+#endif
+
+ for ( idx = HB_SET_VALUE_INVALID; hb_set_next( gpos_lookups, &idx ); )
+ {
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_TRACE4(( " %d", idx ));
+ count++;
+#endif
+
+ /* get input coverage of GPOS feature */
+ hb_ot_layout_lookup_collect_glyphs( face,
+ HB_OT_TAG_GPOS,
+ idx,
+ NULL,
+ gpos_glyphs,
+ NULL,
+ NULL );
+ }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( !count )
+ FT_TRACE4(( " (none)" ));
+ FT_TRACE4(( "\n\n" ));
+#endif
+
+ /*
+ * We now check whether we can construct blue zones, using glyphs
+ * covered by the feature only. In case there is not a single zone
+ * (this is, not a single character is covered), we skip this coverage.
+ *
+ */
+ if ( style_class->coverage != AF_COVERAGE_DEFAULT )
+ {
+ AF_Blue_Stringset bss = style_class->blue_stringset;
+ const AF_Blue_StringRec* bs = &af_blue_stringsets[bss];
+
+ FT_Bool found = 0;
+
+
+ for ( ; bs->string != AF_BLUE_STRING_MAX; bs++ )
+ {
+ const char* p = &af_blue_strings[bs->string];
+
+
+ while ( *p )
+ {
+ hb_codepoint_t ch;
+
+
+ GET_UTF8_CHAR( ch, p );
+
+ for ( idx = HB_SET_VALUE_INVALID; hb_set_next( gsub_lookups,
+ &idx ); )
+ {
+ hb_codepoint_t gidx = FT_Get_Char_Index( globals->face, ch );
+
+
+ if ( hb_ot_layout_lookup_would_substitute( face, idx,
+ &gidx, 1, 1 ) )
+ {
+ found = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ if ( !found )
+ {
+ FT_TRACE4(( " no blue characters found; style skipped\n" ));
+ goto Exit;
+ }
+ }
+
+ /*
+ * Various OpenType features might use the same glyphs at different
+ * vertical positions; for example, superscript and subscript glyphs
+ * could be the same. However, the auto-hinter is completely
+ * agnostic of OpenType features after the feature analysis has been
+ * completed: The engine then simply receives a glyph index and returns a
+ * hinted and usually rendered glyph.
+ *
+ * Consider the superscript feature of font `pala.ttf': Some of the
+ * glyphs are `real', this is, they have a zero vertical offset, but
+ * most of them are small caps glyphs shifted up to the superscript
+ * position (this is, the `sups' feature is present in both the GSUB and
+ * GPOS tables). The code for blue zones computation actually uses a
+ * feature's y offset so that the `real' glyphs get correct hints. But
+ * later on it is impossible to decide whether a glyph index belongs to,
+ * say, the small caps or superscript feature.
+ *
+ * For this reason, we don't assign a style to a glyph if the current
+ * feature covers the glyph in both the GSUB and the GPOS tables. This
+ * is quite a broad condition, assuming that
+ *
+ * (a) glyphs that get used in multiple features are present in a
+ * feature without vertical shift,
+ *
+ * and
+ *
+ * (b) a feature's GPOS data really moves the glyph vertically.
+ *
+ * Not fulfilling condition (a) makes a font larger; it would also
+ * reduce the number of glyphs that could be addressed directly without
+ * using OpenType features, so this assumption is rather strong.
+ *
+ * Condition (b) is much weaker, and there might be glyphs which get
+ * missed. However, the OpenType features we are going to handle are
+ * primarily located in GSUB, and HarfBuzz doesn't provide an API to
+ * directly get the necessary information from the GPOS table. A
+ * possible solution might be to directly parse the GPOS table to find
+ * out whether a glyph gets shifted vertically, but this is something I
+ * would like to avoid if not really necessary.
+ *
+ * Note that we don't follow this logic for the default coverage.
+ * Complex scripts like Devanagari have mandatory GPOS features to
+ * position many glyph elements, using mark-to-base or mark-to-ligature
+ * tables; the number of glyphs missed due to condition (b) would be far
+ * too large.
+ *
+ */
+ if ( style_class->coverage != AF_COVERAGE_DEFAULT )
+ hb_set_subtract( gsub_glyphs, gpos_glyphs );
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_TRACE4(( " glyphs without GPOS data (`*' means already assigned)" ));
+ count = 0;
+#endif
+
+ for ( idx = HB_SET_VALUE_INVALID; hb_set_next( gsub_glyphs, &idx ); )
+ {
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( !( count % 10 ) )
+ FT_TRACE4(( "\n"
+ " " ));
+
+ FT_TRACE4(( " %d", idx ));
+ count++;
+#endif
+
+ /* glyph indices returned by `hb_ot_layout_lookup_collect_glyphs' */
+ /* can be arbitrary: some fonts use fake indices for processing */
+ /* internal to GSUB or GPOS, which is fully valid */
+ if ( idx >= (hb_codepoint_t)globals->glyph_count )
+ continue;
+
+ if ( gstyles[idx] == AF_STYLE_UNASSIGNED )
+ gstyles[idx] = (FT_UShort)style_class->style;
+#ifdef FT_DEBUG_LEVEL_TRACE
+ else
+ FT_TRACE4(( "*" ));
+#endif
+ }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( !count )
+ FT_TRACE4(( "\n"
+ " (none)" ));
+ FT_TRACE4(( "\n\n" ));
+#endif
+
+ Exit:
+ hb_set_destroy( gsub_lookups );
+ hb_set_destroy( gsub_glyphs );
+ hb_set_destroy( gpos_lookups );
+ hb_set_destroy( gpos_glyphs );
+
+ return FT_Err_Ok;
+ }
+
+
+ /* construct HarfBuzz features */
+#undef COVERAGE
+#define COVERAGE( name, NAME, description, \
+ tag1, tag2, tag3, tag4 ) \
+ static const hb_feature_t name ## _feature[] = \
+ { \
+ { \
+ HB_TAG( tag1, tag2, tag3, tag4 ), \
+ 1, 0, (unsigned int)-1 \
+ } \
+ };
+
+
+#include "afcover.h"
+
+
+ /* define mapping between HarfBuzz features and AF_Coverage */
+#undef COVERAGE
+#define COVERAGE( name, NAME, description, \
+ tag1, tag2, tag3, tag4 ) \
+ name ## _feature,
+
+
+ static const hb_feature_t* features[] =
+ {
+#include "afcover.h"
+
+ NULL /* AF_COVERAGE_DEFAULT */
+ };
+
+
+ void*
+ af_shaper_buf_create( FT_Face face )
+ {
+ FT_UNUSED( face );
+
+ return (void*)hb_buffer_create();
+ }
+
+
+ void
+ af_shaper_buf_destroy( FT_Face face,
+ void* buf )
+ {
+ FT_UNUSED( face );
+
+ hb_buffer_destroy( (hb_buffer_t*)buf );
+ }
+
+
+ const char*
+ af_shaper_get_cluster( const char* p,
+ AF_StyleMetrics metrics,
+ void* buf_,
+ unsigned int* count )
+ {
+ AF_StyleClass style_class;
+ const hb_feature_t* feature;
+ FT_Int upem;
+ const char* q;
+ int len;
+
+ hb_buffer_t* buf = (hb_buffer_t*)buf_;
+ hb_font_t* font;
+ hb_codepoint_t dummy;
+
+
+ upem = (FT_Int)metrics->globals->face->units_per_EM;
+ style_class = metrics->style_class;
+ feature = features[style_class->coverage];
+
+ font = metrics->globals->hb_font;
+
+ /* we shape at a size of units per EM; this means font units */
+ hb_font_set_scale( font, upem, upem );
+
+ while ( *p == ' ' )
+ p++;
+
+ /* count bytes up to next space (or end of buffer) */
+ q = p;
+ while ( !( *q == ' ' || *q == '\0' ) )
+ GET_UTF8_CHAR( dummy, q );
+ len = (int)( q - p );
+
+ /* feed character(s) to the HarfBuzz buffer */
+ hb_buffer_clear_contents( buf );
+ hb_buffer_add_utf8( buf, p, len, 0, len );
+
+ /* we let HarfBuzz guess the script and writing direction */
+ hb_buffer_guess_segment_properties( buf );
+
+ /* shape buffer, which means conversion from character codes to */
+ /* glyph indices, possibly applying a feature */
+ hb_shape( font, buf, feature, feature ? 1 : 0 );
+
+ if ( feature )
+ {
+ hb_buffer_t* hb_buf = metrics->globals->hb_buf;
+
+ unsigned int gcount;
+ hb_glyph_info_t* ginfo;
+
+ unsigned int hb_gcount;
+ hb_glyph_info_t* hb_ginfo;
+
+
+ /* we have to check whether applying a feature does actually change */
+ /* glyph indices; otherwise the affected glyph or glyphs aren't */
+ /* available at all in the feature */
+
+ hb_buffer_clear_contents( hb_buf );
+ hb_buffer_add_utf8( hb_buf, p, len, 0, len );
+ hb_buffer_guess_segment_properties( hb_buf );
+ hb_shape( font, hb_buf, NULL, 0 );
+
+ ginfo = hb_buffer_get_glyph_infos( buf, &gcount );
+ hb_ginfo = hb_buffer_get_glyph_infos( hb_buf, &hb_gcount );
+
+ if ( gcount == hb_gcount )
+ {
+ unsigned int i;
+
+
+ for (i = 0; i < gcount; i++ )
+ if ( ginfo[i].codepoint != hb_ginfo[i].codepoint )
+ break;
+
+ if ( i == gcount )
+ {
+ /* both buffers have identical glyph indices */
+ hb_buffer_clear_contents( buf );
+ }
+ }
+ }
+
+ *count = hb_buffer_get_length( buf );
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( feature && *count > 1 )
+ FT_TRACE1(( "af_shaper_get_cluster:"
+ " input character mapped to multiple glyphs\n" ));
+#endif
+
+ return q;
+ }
+
+
+ FT_ULong
+ af_shaper_get_elem( AF_StyleMetrics metrics,
+ void* buf_,
+ unsigned int idx,
+ FT_Long* advance,
+ FT_Long* y_offset )
+ {
+ hb_buffer_t* buf = (hb_buffer_t*)buf_;
+ hb_glyph_info_t* ginfo;
+ hb_glyph_position_t* gpos;
+ unsigned int gcount;
+
+ FT_UNUSED( metrics );
+
+
+ ginfo = hb_buffer_get_glyph_infos( buf, &gcount );
+ gpos = hb_buffer_get_glyph_positions( buf, &gcount );
+
+ if ( idx >= gcount )
+ return 0;
+
+ if ( advance )
+ *advance = gpos[idx].x_advance;
+ if ( y_offset )
+ *y_offset = gpos[idx].y_offset;
+
+ return ginfo[idx].codepoint;
+ }
+
+
+#else /* !FT_CONFIG_OPTION_USE_HARFBUZZ */
+
+
+ FT_Error
+ af_shaper_get_coverage( AF_FaceGlobals globals,
+ AF_StyleClass style_class,
+ FT_UShort* gstyles )
+ {
+ FT_UNUSED( globals );
+ FT_UNUSED( style_class );
+ FT_UNUSED( gstyles );
+
+ return FT_Err_Ok;
+ }
+
+
+ void*
+ af_shaper_buf_create( FT_Face face )
+ {
+ FT_Error error;
+ FT_Memory memory = face->memory;
+ FT_ULong* buf;
+
+
+ FT_MEM_ALLOC( buf, sizeof ( FT_ULong ) );
+
+ return (void*)buf;
+ }
+
+
+ void
+ af_shaper_buf_destroy( FT_Face face,
+ void* buf )
+ {
+ FT_Memory memory = face->memory;
+
+
+ FT_FREE( buf );
+ }
+
+
+ const char*
+ af_shaper_get_cluster( const char* p,
+ AF_StyleMetrics metrics,
+ void* buf_,
+ unsigned int* count )
+ {
+ FT_Face face = metrics->globals->face;
+ FT_ULong ch, dummy = 0;
+ FT_ULong* buf = (FT_ULong*)buf_;
+
+
+ while ( *p == ' ' )
+ p++;
+
+ GET_UTF8_CHAR( ch, p );
+
+ /* since we don't have an engine to handle clusters, */
+ /* we scan the characters but return zero */
+ while ( !( *p == ' ' || *p == '\0' ) )
+ GET_UTF8_CHAR( dummy, p );
+
+ if ( dummy )
+ {
+ *buf = 0;
+ *count = 0;
+ }
+ else
+ {
+ *buf = FT_Get_Char_Index( face, ch );
+ *count = 1;
+ }
+
+ return p;
+ }
+
+
+ FT_ULong
+ af_shaper_get_elem( AF_StyleMetrics metrics,
+ void* buf_,
+ unsigned int idx,
+ FT_Long* advance,
+ FT_Long* y_offset )
+ {
+ FT_Face face = metrics->globals->face;
+ FT_ULong glyph_index = *(FT_ULong*)buf_;
+
+ FT_UNUSED( idx );
+
+
+ if ( advance )
+ FT_Get_Advance( face,
+ glyph_index,
+ FT_LOAD_NO_SCALE |
+ FT_LOAD_NO_HINTING |
+ FT_LOAD_IGNORE_TRANSFORM,
+ advance );
+
+ if ( y_offset )
+ *y_offset = 0;
+
+ return glyph_index;
+ }
+
+
+#endif /* !FT_CONFIG_OPTION_USE_HARFBUZZ */
+
+
+/* END */
diff --git a/src/autofit/afshaper.h b/src/autofit/afshaper.h
new file mode 100644
index 0000000..db1b4e0
--- /dev/null
+++ b/src/autofit/afshaper.h
@@ -0,0 +1,71 @@
+/***************************************************************************/
+/* */
+/* afshaper.h */
+/* */
+/* HarfBuzz interface for accessing OpenType features (specification). */
+/* */
+/* Copyright 2013-2015 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef __AFSHAPER_H__
+#define __AFSHAPER_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
+
+#include <hb.h>
+#include <hb-ot.h>
+#include <hb-ft.h>
+
+#endif
+
+
+FT_BEGIN_HEADER
+
+ FT_Error
+ af_shaper_get_coverage( AF_FaceGlobals globals,
+ AF_StyleClass style_class,
+ FT_UShort* gstyles );
+
+
+ void*
+ af_shaper_buf_create( FT_Face face );
+
+ void
+ af_shaper_buf_destroy( FT_Face face,
+ void* buf );
+
+ const char*
+ af_shaper_get_cluster( const char* p,
+ AF_StyleMetrics metrics,
+ void* buf_,
+ unsigned int* count );
+
+ FT_ULong
+ af_shaper_get_elem( AF_StyleMetrics metrics,
+ void* buf_,
+ unsigned int idx,
+ FT_Long* x_advance,
+ FT_Long* y_offset );
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __AFSHAPER_H__ */
+
+
+/* END */
diff --git a/src/autofit/afstyles.h b/src/autofit/afstyles.h
index bfd5bb9..e214442 100644
--- a/src/autofit/afstyles.h
+++ b/src/autofit/afstyles.h
@@ -27,7 +27,9 @@
/* coverage. */
/* */
/* Note that styles using `AF_COVERAGE_DEFAULT' should always */
- /* come after styles with other coverages. */
+ /* come after styles with other coverages. Also note that */
+ /* fallback scripts only use `AF_COVERAGE_DEFAULT' for its */
+ /* style. */
/* */
/* Example: */
/* */
@@ -90,6 +92,13 @@
META_STYLE_LATIN( cyrl, CYRL, "Cyrillic" )
+ STYLE( deva_dflt, DEVA_DFLT,
+ "Devanagari default style",
+ AF_WRITING_SYSTEM_LATIN,
+ AF_SCRIPT_DEVA,
+ AF_BLUE_STRINGSET_DEVA,
+ AF_COVERAGE_DEFAULT )
+
META_STYLE_LATIN( grek, GREK, "Greek" )
STYLE( hebr_dflt, HEBR_DFLT,
@@ -98,13 +107,42 @@
AF_SCRIPT_HEBR,
AF_BLUE_STRINGSET_HEBR,
AF_COVERAGE_DEFAULT )
+
+ STYLE( khmr_dflt, KHMR_DFLT,
+ "Khmer default style",
+ AF_WRITING_SYSTEM_LATIN,
+ AF_SCRIPT_KHMR,
+ AF_BLUE_STRINGSET_KHMR,
+ AF_COVERAGE_DEFAULT )
+
+ STYLE( khms_dflt, KHMS_DFLT,
+ "Khmer Symbols default style",
+ AF_WRITING_SYSTEM_LATIN,
+ AF_SCRIPT_KHMS,
+ AF_BLUE_STRINGSET_KHMS,
+ AF_COVERAGE_DEFAULT )
+
+ STYLE( lao_dflt, LAO_DFLT,
+ "Lao default style",
+ AF_WRITING_SYSTEM_LATIN,
+ AF_SCRIPT_LAO,
+ AF_BLUE_STRINGSET_LAO,
+ AF_COVERAGE_DEFAULT )
+
META_STYLE_LATIN( latn, LATN, "Latin" )
- STYLE( deva_dflt, DEVA_DFLT,
- "Devanagari default style",
+ STYLE( latb_dflt, LATB_DFLT,
+ "Latin subscript fallback default style",
AF_WRITING_SYSTEM_LATIN,
- AF_SCRIPT_DEVA,
- AF_BLUE_STRINGSET_DEVA,
+ AF_SCRIPT_LATB,
+ AF_BLUE_STRINGSET_LATB,
+ AF_COVERAGE_DEFAULT )
+
+ STYLE( latp_dflt, LATP_DFLT,
+ "Latin superscript fallback default style",
+ AF_WRITING_SYSTEM_LATIN,
+ AF_SCRIPT_LATP,
+ AF_BLUE_STRINGSET_LATP,
AF_COVERAGE_DEFAULT )
#ifdef FT_OPTION_AUTOFIT2
@@ -116,6 +154,13 @@
AF_COVERAGE_DEFAULT )
#endif
+ STYLE( mymr_dflt, MYMR_DFLT,
+ "Myanmar default style",
+ AF_WRITING_SYSTEM_LATIN,
+ AF_SCRIPT_MYMR,
+ AF_BLUE_STRINGSET_MYMR,
+ AF_COVERAGE_DEFAULT )
+
STYLE( none_dflt, NONE_DFLT,
"no style",
AF_WRITING_SYSTEM_DUMMY,
diff --git a/src/autofit/aftypes.h b/src/autofit/aftypes.h
index 78e3fd7..b483619 100644
--- a/src/autofit/aftypes.h
+++ b/src/autofit/aftypes.h
@@ -41,6 +41,10 @@
#include "afblue.h"
+#ifdef FT_DEBUG_AUTOFIT
+#include FT_CONFIG_STANDARD_LIBRARY_H
+#endif
+
FT_BEGIN_HEADER
@@ -54,8 +58,6 @@ FT_BEGIN_HEADER
#ifdef FT_DEBUG_AUTOFIT
-#include FT_CONFIG_STANDARD_LIBRARY_H
-
extern int _af_debug_disable_horz_hints;
extern int _af_debug_disable_vert_hints;
extern int _af_debug_disable_blue_hints;
@@ -209,13 +211,19 @@ extern void* _af_debug_hints;
typedef void
(*AF_WritingSystem_DoneMetricsFunc)( AF_StyleMetrics metrics );
+ typedef void
+ (*AF_WritingSystem_GetStdWidthsFunc)( AF_StyleMetrics metrics,
+ FT_Pos* stdHW,
+ FT_Pos* stdVW );
+
typedef FT_Error
(*AF_WritingSystem_InitHintsFunc)( AF_GlyphHints hints,
AF_StyleMetrics metrics );
typedef void
- (*AF_WritingSystem_ApplyHintsFunc)( AF_GlyphHints hints,
+ (*AF_WritingSystem_ApplyHintsFunc)( FT_UInt glyph_index,
+ AF_GlyphHints hints,
FT_Outline* outline,
AF_StyleMetrics metrics );
@@ -273,6 +281,7 @@ extern void* _af_debug_hints;
AF_WritingSystem_InitMetricsFunc style_metrics_init;
AF_WritingSystem_ScaleMetricsFunc style_metrics_scale;
AF_WritingSystem_DoneMetricsFunc style_metrics_done;
+ AF_WritingSystem_GetStdWidthsFunc style_metrics_getstdw;
AF_WritingSystem_InitHintsFunc style_hints_init;
AF_WritingSystem_ApplyHintsFunc style_hints_apply;
@@ -291,15 +300,16 @@ extern void* _af_debug_hints;
/*************************************************************************/
/*
- * Each script is associated with a set of Unicode ranges that gets used
- * to test whether the font face supports the script.
+ * Each script is associated with two sets of Unicode ranges to test
+ * whether the font face supports the script, and which non-base
+ * characters the script contains.
*
* We use four-letter script tags from the OpenType specification,
* extended by `NONE', which indicates `no script'.
*/
#undef SCRIPT
-#define SCRIPT( s, S, d, h, sc1, sc2, sc3 ) \
+#define SCRIPT( s, S, d, h, ss ) \
AF_SCRIPT_ ## S,
/* The list of known scripts. */
@@ -329,11 +339,11 @@ extern void* _af_debug_hints;
{
AF_Script script;
- AF_Script_UniRange script_uni_ranges; /* last must be { 0, 0 } */
+ /* last element in the ranges must be { 0, 0 } */
+ AF_Script_UniRange script_uni_ranges;
+ AF_Script_UniRange script_uni_nonbase_ranges;
- FT_UInt32 standard_char1; /* for default width and height */
- FT_UInt32 standard_char2; /* ditto */
- FT_UInt32 standard_char3; /* ditto */
+ const char* standard_charstring; /* for default width and height */
} AF_ScriptClassRec;
@@ -483,6 +493,7 @@ extern void* _af_debug_hints;
m_init, \
m_scale, \
m_done, \
+ m_stdw, \
h_init, \
h_apply ) \
FT_CALLBACK_TABLE_DEF \
@@ -495,6 +506,7 @@ extern void* _af_debug_hints;
m_init, \
m_scale, \
m_done, \
+ m_stdw, \
\
h_init, \
h_apply \
@@ -509,17 +521,15 @@ extern void* _af_debug_hints;
script_class, \
script, \
ranges, \
- std_char1, \
- std_char2, \
- std_char3 ) \
+ nonbase_ranges, \
+ std_charstring ) \
FT_CALLBACK_TABLE_DEF \
const AF_ScriptClassRec script_class = \
{ \
script, \
ranges, \
- std_char1, \
- std_char2, \
- std_char3 \
+ nonbase_ranges, \
+ std_charstring, \
};
@@ -562,16 +572,17 @@ extern void* _af_debug_hints;
FT_LOCAL_DEF( void ) \
FT_Init_Class_ ## writing_system_class( AF_WritingSystemClassRec* ac ) \
{ \
- ac->writing_system = system; \
+ ac->writing_system = system; \
\
- ac->style_metrics_size = m_size; \
+ ac->style_metrics_size = m_size; \
\
- ac->style_metrics_init = m_init; \
- ac->style_metrics_scale = m_scale; \
- ac->style_metrics_done = m_done; \
+ ac->style_metrics_init = m_init; \
+ ac->style_metrics_scale = m_scale; \
+ ac->style_metrics_done = m_done; \
+ ac->style_metrics_getstdw = m_stdw; \
\
- ac->style_hints_init = h_init; \
- ac->style_hints_apply = h_apply; \
+ ac->style_hints_init = h_init; \
+ ac->style_hints_apply = h_apply; \
}
@@ -583,17 +594,15 @@ extern void* _af_debug_hints;
script_class, \
script_, \
ranges, \
- std_char1, \
- std_char2, \
- std_char3 ) \
+ nonbase_ranges, \
+ std_charstring ) \
FT_LOCAL_DEF( void ) \
FT_Init_Class_ ## script_class( AF_ScriptClassRec* ac ) \
{ \
- ac->script = script_; \
- ac->script_uni_ranges = ranges; \
- ac->standard_char1 = std_char1; \
- ac->standard_char2 = std_char2; \
- ac->standard_char3 = std_char3; \
+ ac->script = script_; \
+ ac->script_uni_ranges = ranges; \
+ ac->script_uni_nonbase_ranges = nonbase_ranges; \
+ ac->standard_charstring = std_charstring; \
}
diff --git a/src/autofit/afwarp.c b/src/autofit/afwarp.c
index 59af4f0..ae92db1 100644
--- a/src/autofit/afwarp.c
+++ b/src/autofit/afwarp.c
@@ -193,7 +193,7 @@
warper->best_scale = org_scale;
warper->best_delta = org_delta;
- warper->best_score = INT_MIN;
+ warper->best_score = FT_INT_MIN;
warper->best_distort = 0;
axis = &hints->axis[dim];
diff --git a/src/autofit/afwarp.h b/src/autofit/afwarp.h
index 5a6208a..6069b6b 100644
--- a/src/autofit/afwarp.h
+++ b/src/autofit/afwarp.h
@@ -25,7 +25,7 @@ FT_BEGIN_HEADER
#define AF_WARPER_SCALE
-#define AF_WARPER_FLOOR( x ) ( (x) & ~TYPEOF( x )63 )
+#define AF_WARPER_FLOOR( x ) ( (x) & ~FT_TYPEOF( x )63 )
#define AF_WARPER_CEIL( x ) AF_WARPER_FLOOR( (x) + 63 )
diff --git a/src/autofit/autofit.c b/src/autofit/autofit.c
index b6ed4a0..a971a24 100644
--- a/src/autofit/autofit.c
+++ b/src/autofit/autofit.c
@@ -34,7 +34,7 @@
#include "afcjk.c"
#include "afindic.c"
-#include "hbshim.c"
+#include "afshaper.c"
#include "afloader.c"
#include "afmodule.c"
diff --git a/src/base/basepic.h b/src/base/basepic.h
index 51ecf9e..c5d7cbf 100644
--- a/src/base/basepic.h
+++ b/src/base/basepic.h
@@ -20,10 +20,9 @@
#define __BASEPIC_H__
-FT_BEGIN_HEADER
-
#include FT_INTERNAL_PIC_H
+
#ifndef FT_CONFIG_OPTION_PIC
#define FT_OUTLINE_GLYPH_CLASS_GET &ft_outline_glyph_class
@@ -43,6 +42,8 @@ FT_BEGIN_HEADER
#endif
+FT_BEGIN_HEADER
+
typedef struct BasePIC_
{
FT_Module_Class** default_module_classes;
@@ -78,12 +79,12 @@ FT_BEGIN_HEADER
FT_Error
ft_base_pic_init( FT_Library library );
+FT_END_HEADER
+
#endif /* FT_CONFIG_OPTION_PIC */
/* */
-FT_END_HEADER
-
#endif /* __BASEPIC_H__ */
diff --git a/src/base/ftbase.h b/src/base/ftbase.h
index cb57f96..e37fefa 100644
--- a/src/base/ftbase.h
+++ b/src/base/ftbase.h
@@ -27,6 +27,11 @@
FT_BEGIN_HEADER
+ /* MacOS resource fork cannot exceed 16MB at least for Carbon code; */
+ /* see https://support.microsoft.com/en-us/kb/130437 */
+#define FT_MAC_RFORK_MAX_LEN 0x00FFFFFFUL
+
+
/* Assume the stream is sfnt-wrapped PS Type1 or sfnt-wrapped CID-keyed */
/* font, and try to load a face specified by the face_index. */
FT_LOCAL( FT_Error )
diff --git a/src/base/ftbdf.c b/src/base/ftbdf.c
new file mode 100644
index 0000000..aa72ddc
--- /dev/null
+++ b/src/base/ftbdf.c
@@ -0,0 +1,91 @@
+/***************************************************************************/
+/* */
+/* ftbdf.c */
+/* */
+/* FreeType API for accessing BDF-specific strings (body). */
+/* */
+/* Copyright 2002-2015 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_INTERNAL_DEBUG_H
+
+#include FT_INTERNAL_OBJECTS_H
+#include FT_SERVICE_BDF_H
+
+
+ /* documentation is in ftbdf.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_BDF_Charset_ID( FT_Face face,
+ const char* *acharset_encoding,
+ const char* *acharset_registry )
+ {
+ FT_Error error;
+ const char* encoding = NULL;
+ const char* registry = NULL;
+
+ FT_Service_BDF service;
+
+
+ if ( !face )
+ return FT_THROW( Invalid_Face_Handle );
+
+ FT_FACE_FIND_SERVICE( face, service, BDF );
+
+ if ( service && service->get_charset_id )
+ error = service->get_charset_id( face, &encoding, &registry );
+ else
+ error = FT_THROW( Invalid_Argument );
+
+ if ( acharset_encoding )
+ *acharset_encoding = encoding;
+
+ if ( acharset_registry )
+ *acharset_registry = registry;
+
+ return error;
+ }
+
+
+ /* documentation is in ftbdf.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_BDF_Property( FT_Face face,
+ const char* prop_name,
+ BDF_PropertyRec *aproperty )
+ {
+ FT_Error error;
+
+ FT_Service_BDF service;
+
+
+ if ( !face )
+ return FT_THROW( Invalid_Face_Handle );
+
+ if ( !aproperty )
+ return FT_THROW( Invalid_Argument );
+
+ aproperty->type = BDF_PROPERTY_TYPE_NONE;
+
+ FT_FACE_FIND_SERVICE( face, service, BDF );
+
+ if ( service && service->get_property )
+ error = service->get_property( face, prop_name, aproperty );
+ else
+ error = FT_THROW( Invalid_Argument );
+
+ return error;
+ }
+
+
+/* END */
diff --git a/src/base/ftcalc.c b/src/base/ftcalc.c
index dca0e1d..619a08b 100644
--- a/src/base/ftcalc.c
+++ b/src/base/ftcalc.c
@@ -86,8 +86,7 @@
FT_EXPORT_DEF( FT_Fixed )
FT_RoundFix( FT_Fixed a )
{
- return a >= 0 ? ( a + 0x8000L ) & ~0xFFFFL
- : -((-a + 0x8000L ) & ~0xFFFFL );
+ return ( a + 0x8000L - ( a < 0 ) ) & ~0xFFFFL;
}
@@ -96,8 +95,7 @@
FT_EXPORT_DEF( FT_Fixed )
FT_CeilFix( FT_Fixed a )
{
- return a >= 0 ? ( a + 0xFFFFL ) & ~0xFFFFL
- : -((-a + 0xFFFFL ) & ~0xFFFFL );
+ return ( a + 0xFFFFL ) & ~0xFFFFL;
}
@@ -106,8 +104,7 @@
FT_EXPORT_DEF( FT_Fixed )
FT_FloorFix( FT_Fixed a )
{
- return a >= 0 ? a & ~0xFFFFL
- : -((-a) & ~0xFFFFL );
+ return a & ~0xFFFFL;
}
#ifndef FT_MSB
@@ -240,22 +237,10 @@
#else
- FT_Int s = 1;
- FT_UInt64 a, b, c;
- FT_Long c_;
-
+ FT_Int64 ab = (FT_Int64)a_ * (FT_Int64)b_;
- FT_MOVE_SIGN( a_, s );
- FT_MOVE_SIGN( b_, s );
-
- a = (FT_UInt64)a_;
- b = (FT_UInt64)b_;
-
- c = ( a * b + 0x8000UL ) >> 16;
-
- c_ = (FT_Long)c;
-
- return s < 0 ? -c_ : c_;
+ /* this requires arithmetic right shift of signed numbers */
+ return (FT_Long)( ( ab + 0x8000L - ( ab < 0 ) ) >> 16 );
#endif /* FT_MULFIX_ASSEMBLER */
}
@@ -437,9 +422,6 @@
/* XXX: this function does not allow 64-bit arguments */
- if ( a_ == 0 || b_ == c_ )
- return a_;
-
FT_MOVE_SIGN( a_, s );
FT_MOVE_SIGN( b_, s );
FT_MOVE_SIGN( c_, s );
@@ -488,9 +470,6 @@
/* XXX: this function does not allow 64-bit arguments */
- if ( a_ == 0 || b_ == c_ )
- return a_;
-
FT_MOVE_SIGN( a_, s );
FT_MOVE_SIGN( b_, s );
FT_MOVE_SIGN( c_, s );
@@ -546,9 +525,6 @@
FT_UInt32 a, b;
- if ( a_ == 0 || b_ == 0x10000L )
- return a_;
-
/*
* This is a clever way of converting a signed number `a' into its
* absolute value (stored back into `a') and its sign. The sign is
@@ -599,9 +575,6 @@
/* XXX: this function does not allow 64-bit arguments */
- if ( a_ == 0 || b_ == 0x10000L )
- return a_;
-
FT_MOVE_SIGN( a_, s );
FT_MOVE_SIGN( b_, s );
@@ -785,6 +758,102 @@
}
+ /* documentation is in ftcalc.h */
+
+ FT_BASE_DEF( FT_UInt32 )
+ FT_Vector_NormLen( FT_Vector* vector )
+ {
+ FT_Int32 x_ = vector->x;
+ FT_Int32 y_ = vector->y;
+ FT_Int32 b, z;
+ FT_UInt32 x, y, u, v, l;
+ 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_;
+
+ /* trivial cases */
+ if ( x == 0 )
+ {
+ if ( y > 0 )
+ vector->y = sy * 0x10000;
+ return y;
+ }
+ else if ( y == 0 )
+ {
+ if ( x > 0 )
+ vector->x = sx * 0x10000;
+ return x;
+ }
+
+ /* Estimate length and prenormalize by shifting so that */
+ /* the new approximate length is between 2/3 and 4/3. */
+ /* The magic constant 0xAAAAAAAAUL (2/3 of 2^32) helps */
+ /* achieve this in 16.16 fixed-point representation. */
+ l = x > y ? x + ( y >> 1 )
+ : y + ( x >> 1 );
+
+ shift = 31 - FT_MSB( l );
+ shift -= 15 + ( l >= ( 0xAAAAAAAAUL >> shift ) );
+
+ if ( shift > 0 )
+ {
+ x <<= shift;
+ y <<= shift;
+
+ /* re-estimate length for tiny vectors */
+ l = x > y ? x + ( y >> 1 )
+ : y + ( x >> 1 );
+ }
+ else
+ {
+ x >>= -shift;
+ y >>= -shift;
+ l >>= -shift;
+ }
+
+ /* lower linear approximation for reciprocal length minus one */
+ b = 0x10000 - (FT_Int32)l;
+
+ x_ = (FT_Int32)x;
+ y_ = (FT_Int32)y;
+
+ /* Newton's iterations */
+ do
+ {
+ u = (FT_UInt32)( x_ + ( x_ * b >> 16 ) );
+ v = (FT_UInt32)( y_ + ( y_ * b >> 16 ) );
+
+ /* Normalized squared length in the parentheses approaches 2^32. */
+ /* On two's complement systems, converting to signed gives the */
+ /* difference with 2^32 even if the expression wraps around. */
+ z = -(FT_Int32)( u * u + v * v ) / 0x200;
+ z = z * ( ( 0x10000 + b ) >> 8 ) / 0x10000;
+
+ b += z;
+
+ } while ( z > 0 );
+
+ vector->x = sx < 0 ? -(FT_Pos)u : (FT_Pos)u;
+ vector->y = sy < 0 ? -(FT_Pos)v : (FT_Pos)v;
+
+ /* Conversion to signed helps to recover from likely wrap around */
+ /* in calculating the prenormalized length, because it gives the */
+ /* correct difference with 2^32 on two's complement systems. */
+ l = (FT_UInt32)( 0x10000 + (FT_Int32)( u * x + v * y ) / 0x10000 );
+ if ( shift > 0 )
+ l = ( l + ( 1 << ( shift - 1 ) ) ) >> shift;
+ else
+ l <<= -shift;
+
+ return l;
+ }
+
+
#if 0
/* documentation is in ftcalc.h */
@@ -832,52 +901,34 @@
FT_Pos out_x,
FT_Pos out_y )
{
- FT_Long result; /* avoid overflow on 16-bit system */
-
-
- /* deal with the trivial cases quickly */
- if ( in_y == 0 )
- {
- if ( in_x >= 0 )
- result = out_y;
- else
- result = -out_y;
- }
- else if ( in_x == 0 )
- {
- if ( in_y >= 0 )
- result = -out_x;
- else
- result = out_x;
- }
- else if ( out_y == 0 )
- {
- if ( out_x >= 0 )
- result = in_y;
- else
- result = -in_y;
- }
- else if ( out_x == 0 )
- {
- if ( out_y >= 0 )
- result = -in_x;
- else
- result = in_x;
- }
- else /* general case */
- {
#ifdef FT_LONG64
- FT_Int64 delta = (FT_Int64)in_x * out_y - (FT_Int64)in_y * out_x;
+ FT_Int64 delta = (FT_Int64)in_x * out_y - (FT_Int64)in_y * out_x;
- if ( delta == 0 )
- result = 0;
- else
- result = 1 - 2 * ( delta < 0 );
+ return ( delta > 0 ) - ( delta < 0 );
#else
+ 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 )
+ {
+ FT_Long z1 = in_x * out_y;
+ FT_Long z2 = in_y * out_x;
+
+
+ if ( z1 > z2 )
+ result = +1;
+ else if ( z1 < z2 )
+ result = -1;
+ else
+ result = 0;
+ }
+ else /* products might overflow 32 bits */
+ {
FT_Int64 z1, z2;
@@ -895,12 +946,12 @@
result = -1;
else
result = 0;
-
-#endif
}
/* XXX: only the sign of return value, +1/0/-1 must be used */
- return (FT_Int)result;
+ return result;
+
+#endif
}
diff --git a/src/base/ftcid.c b/src/base/ftcid.c
new file mode 100644
index 0000000..0734881
--- /dev/null
+++ b/src/base/ftcid.c
@@ -0,0 +1,118 @@
+/***************************************************************************/
+/* */
+/* ftcid.c */
+/* */
+/* FreeType API for accessing CID font information. */
+/* */
+/* Copyright 2007-2015 by */
+/* Derek Clegg and Michael Toftdal. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_CID_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_SERVICE_CID_H
+
+
+ /* documentation is in ftcid.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_CID_Registry_Ordering_Supplement( FT_Face face,
+ const char* *registry,
+ const char* *ordering,
+ FT_Int *supplement)
+ {
+ FT_Error error;
+ const char* r = NULL;
+ const char* o = NULL;
+ FT_Int s = 0;
+
+
+ error = FT_ERR( Invalid_Argument );
+
+ if ( face )
+ {
+ FT_Service_CID service;
+
+
+ FT_FACE_FIND_SERVICE( face, service, CID );
+
+ if ( service && service->get_ros )
+ error = service->get_ros( face, &r, &o, &s );
+ }
+
+ if ( registry )
+ *registry = r;
+
+ if ( ordering )
+ *ordering = o;
+
+ if ( supplement )
+ *supplement = s;
+
+ return error;
+ }
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_CID_Is_Internally_CID_Keyed( FT_Face face,
+ FT_Bool *is_cid )
+ {
+ FT_Error error = FT_ERR( Invalid_Argument );
+ FT_Bool ic = 0;
+
+
+ if ( face )
+ {
+ FT_Service_CID service;
+
+
+ FT_FACE_FIND_SERVICE( face, service, CID );
+
+ if ( service && service->get_is_cid )
+ error = service->get_is_cid( face, &ic);
+ }
+
+ if ( is_cid )
+ *is_cid = ic;
+
+ return error;
+ }
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_CID_From_Glyph_Index( FT_Face face,
+ FT_UInt glyph_index,
+ FT_UInt *cid )
+ {
+ FT_Error error = FT_ERR( Invalid_Argument );
+ FT_UInt c = 0;
+
+
+ if ( face )
+ {
+ FT_Service_CID service;
+
+
+ FT_FACE_FIND_SERVICE( face, service, CID );
+
+ if ( service && service->get_cid_from_glyph_index )
+ error = service->get_cid_from_glyph_index( face, glyph_index, &c);
+ }
+
+ if ( cid )
+ *cid = c;
+
+ return error;
+ }
+
+
+/* END */
diff --git a/src/base/ftdbgmem.c b/src/base/ftdbgmem.c
index 6f20313..02eeb01 100644
--- a/src/base/ftdbgmem.c
+++ b/src/base/ftdbgmem.c
@@ -462,7 +462,7 @@
(FT_UInt32)( 5 * _ft_debug_lineno );
pnode = &table->sources[hash % FT_MEM_SOURCE_BUCKETS];
- for ( ;; )
+ for (;;)
{
node = *pnode;
if ( node == NULL )
diff --git a/src/base/ftdebug.c b/src/base/ftdebug.c
index 2cdb7c2..03e18a8 100644
--- a/src/base/ftdebug.c
+++ b/src/base/ftdebug.c
@@ -152,8 +152,8 @@
/* the memory and stream components which are set to 7 and 5, */
/* respectively. */
/* */
- /* See the file <include/internal/fttrace.h> for details of the */
- /* available toggle names. */
+ /* See the file `include/freetype/internal/fttrace.h' for details of */
+ /* the available toggle names. */
/* */
/* The level must be between 0 and 7; 0 means quiet (except for serious */
/* runtime errors), and 7 means _very_ verbose. */
diff --git a/src/base/ftglyph.c b/src/base/ftglyph.c
index cb7fc37..2778743 100644
--- a/src/base/ftglyph.c
+++ b/src/base/ftglyph.c
@@ -125,10 +125,10 @@
FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph;
- cbox->xMin = glyph->left << 6;
- cbox->xMax = cbox->xMin + (FT_Pos)( glyph->bitmap.width << 6 );
- cbox->yMax = glyph->top << 6;
- cbox->yMin = cbox->yMax - (FT_Pos)( glyph->bitmap.rows << 6 );
+ cbox->xMin = glyph->left * 64;
+ cbox->xMax = cbox->xMin + (FT_Pos)( glyph->bitmap.width * 64 );
+ cbox->yMax = glyph->top * 64;
+ cbox->yMin = cbox->yMax - (FT_Pos)( glyph->bitmap.rows * 64 );
}
@@ -403,9 +403,9 @@
if ( error )
goto Exit;
- /* copy advance while converting it to 16.16 format */
- glyph->advance.x = slot->advance.x << 10;
- glyph->advance.y = slot->advance.y << 10;
+ /* copy advance while converting 26.6 to 16.16 format */
+ 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 );
diff --git a/src/base/ftgxval.c b/src/base/ftgxval.c
new file mode 100644
index 0000000..58868f2
--- /dev/null
+++ b/src/base/ftgxval.c
@@ -0,0 +1,142 @@
+/***************************************************************************/
+/* */
+/* ftgxval.c */
+/* */
+/* FreeType API for validating TrueTyepGX/AAT tables (body). */
+/* */
+/* Copyright 2004-2015 by */
+/* Masatake YAMATO, Redhat K.K, */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+
+#include FT_INTERNAL_OBJECTS_H
+#include FT_SERVICE_GX_VALIDATE_H
+
+
+ /* documentation is in ftgxval.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_TrueTypeGX_Validate( FT_Face face,
+ FT_UInt validation_flags,
+ FT_Bytes tables[FT_VALIDATE_GX_LENGTH],
+ FT_UInt table_length )
+ {
+ FT_Service_GXvalidate service;
+ FT_Error error;
+
+
+ if ( !face )
+ {
+ error = FT_THROW( Invalid_Face_Handle );
+ goto Exit;
+ }
+
+ if ( !tables )
+ {
+ error = FT_THROW( Invalid_Argument );
+ goto Exit;
+ }
+
+ FT_FACE_FIND_GLOBAL_SERVICE( face, service, GX_VALIDATE );
+
+ if ( service )
+ error = service->validate( face,
+ validation_flags,
+ tables,
+ table_length );
+ else
+ error = FT_THROW( Unimplemented_Feature );
+
+ Exit:
+ return error;
+ }
+
+
+ FT_EXPORT_DEF( void )
+ FT_TrueTypeGX_Free( FT_Face face,
+ FT_Bytes table )
+ {
+ FT_Memory memory;
+
+
+ if ( !face )
+ return;
+
+ memory = FT_FACE_MEMORY( face );
+
+ FT_FREE( table );
+ }
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_ClassicKern_Validate( FT_Face face,
+ FT_UInt validation_flags,
+ FT_Bytes *ckern_table )
+ {
+ FT_Service_CKERNvalidate service;
+ FT_Error error;
+
+
+ if ( !face )
+ {
+ error = FT_THROW( Invalid_Face_Handle );
+ goto Exit;
+ }
+
+ if ( !ckern_table )
+ {
+ error = FT_THROW( Invalid_Argument );
+ goto Exit;
+ }
+
+ FT_FACE_FIND_GLOBAL_SERVICE( face, service, CLASSICKERN_VALIDATE );
+
+ if ( service )
+ error = service->validate( face,
+ validation_flags,
+ ckern_table );
+ else
+ error = FT_THROW( Unimplemented_Feature );
+
+ Exit:
+ return error;
+ }
+
+
+ FT_EXPORT_DEF( void )
+ FT_ClassicKern_Free( FT_Face face,
+ FT_Bytes table )
+ {
+ FT_Memory memory;
+
+
+ if ( !face )
+ return;
+
+ memory = FT_FACE_MEMORY( face );
+
+
+ FT_FREE( table );
+ }
+
+
+/* END */
diff --git a/src/base/ftinit.c b/src/base/ftinit.c
index cc95e6a..b65a91d 100644
--- a/src/base/ftinit.c
+++ b/src/base/ftinit.c
@@ -23,8 +23,8 @@
/* FT_Add_Default_Modules(): */
/* This function is used to add the set of default modules to a */
/* fresh new library object. The set is taken from the header file */
- /* `config/ftmodule.h'. See the document `FreeType 2.0 Build */
- /* System' for more information. */
+ /* `freetype/config/ftmodule.h'. See the document `FreeType 2.0 */
+ /* Build System' for more information. */
/* */
/* FT_Init_FreeType(): */
/* This function creates a system object for the current platform, */
diff --git a/src/base/ftlcdfil.c b/src/base/ftlcdfil.c
index ff6f7e9..5ee7e0a 100644
--- a/src/base/ftlcdfil.c
+++ b/src/base/ftlcdfil.c
@@ -305,12 +305,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 };
- /* the values here sum up to a value larger than 256, */
- /* providing a cheap gamma correction */
- static const FT_Byte default_filter[5] =
- { 0x10, 0x40, 0x70, 0x40, 0x10 };
if ( !library )
@@ -354,6 +352,7 @@
#ifdef USE_LEGACY
case FT_LCD_FILTER_LEGACY:
+ case FT_LCD_FILTER_LEGACY1:
library->lcd_filter_func = _ft_lcd_filter_legacy;
library->lcd_extra = 0;
break;
diff --git a/src/base/ftmac.c b/src/base/ftmac.c
new file mode 100644
index 0000000..114bbb6
--- /dev/null
+++ b/src/base/ftmac.c
@@ -0,0 +1,1080 @@
+/***************************************************************************/
+/* */
+/* ftmac.c */
+/* */
+/* Mac FOND support. Written by just@letterror.com. */
+/* Heavily modified by mpsuzuki, George Williams, and Sean McBride. */
+/* */
+/* This file is for Mac OS X only; see builds/mac/ftoldmac.c for */
+/* classic platforms built by MPW. */
+/* */
+/* Copyright 1996-2015 by */
+/* Just van Rossum, 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. */
+/* */
+/***************************************************************************/
+
+
+ /*
+ Notes
+
+ Mac suitcase files can (and often do!) contain multiple fonts. To
+ support this I use the face_index argument of FT_(Open|New)_Face()
+ functions, and pretend the suitcase file is a collection.
+
+ Warning: fbit and NFNT bitmap resources are not supported yet. In old
+ sfnt fonts, bitmap glyph data for each size is stored in each `NFNT'
+ resources instead of the `bdat' table in the sfnt resource. Therefore,
+ face->num_fixed_sizes is set to 0, because bitmap data in `NFNT'
+ resource is unavailable at present.
+
+ The Mac FOND support works roughly like this:
+
+ - Check whether the offered stream points to a Mac suitcase file. This
+ is done by checking the file type: it has to be 'FFIL' or 'tfil'. The
+ stream that gets passed to our init_face() routine is a stdio stream,
+ which isn't usable for us, since the FOND resources live in the
+ resource fork. So we just grab the stream->pathname field.
+
+ - Read the FOND resource into memory, then check whether there is a
+ TrueType font and/or(!) a Type 1 font available.
+
+ - If there is a Type 1 font available (as a separate `LWFN' file), read
+ its data into memory, massage it slightly so it becomes PFB data, wrap
+ it into a memory stream, load the Type 1 driver and delegate the rest
+ of the work to it by calling FT_Open_Face(). (XXX TODO: after this
+ has been done, the kerning data from the FOND resource should be
+ appended to the face: On the Mac there are usually no AFM files
+ available. However, this is tricky since we need to map Mac char
+ codes to ps glyph names to glyph ID's...)
+
+ - If there is a TrueType font (an `sfnt' resource), read it into memory,
+ wrap it into a memory stream, load the TrueType driver and delegate
+ the rest of the work to it, by calling FT_Open_Face().
+
+ - Some suitcase fonts (notably Onyx) might point the `LWFN' file to
+ itself, even though it doesn't contains `POST' resources. To handle
+ this special case without opening the file an extra time, we just
+ ignore errors from the `LWFN' and fallback to the `sfnt' if both are
+ available.
+ */
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_TRUETYPE_TAGS_H
+#include FT_INTERNAL_STREAM_H
+#include "ftbase.h"
+
+ /* This is for Mac OS X. Without redefinition, OS_INLINE */
+ /* expands to `static inline' which doesn't survive the */
+ /* -ansi compilation flag of GCC. */
+#if !HAVE_ANSI_OS_INLINE
+#undef OS_INLINE
+#define OS_INLINE static __inline__
+#endif
+
+ /* `configure' checks the availability of `ResourceIndex' strictly */
+ /* and sets HAVE_TYPE_RESOURCE_INDEX 1 or 0 always. If it is */
+ /* not set (e.g., a build without `configure'), the availability */
+ /* is guessed from the SDK version. */
+#ifndef HAVE_TYPE_RESOURCE_INDEX
+#if !defined( MAC_OS_X_VERSION_10_5 ) || \
+ ( MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 )
+#define HAVE_TYPE_RESOURCE_INDEX 0
+#else
+#define HAVE_TYPE_RESOURCE_INDEX 1
+#endif
+#endif /* !HAVE_TYPE_RESOURCE_INDEX */
+
+#if ( HAVE_TYPE_RESOURCE_INDEX == 0 )
+ typedef short ResourceIndex;
+#endif
+
+#include <CoreServices/CoreServices.h>
+#include <ApplicationServices/ApplicationServices.h>
+#include <sys/syslimits.h> /* PATH_MAX */
+
+ /* Don't want warnings about our own use of deprecated functions. */
+#define FT_DEPRECATED_ATTRIBUTE
+
+#include FT_MAC_H
+
+#ifndef kATSOptionFlagsUnRestrictedScope /* since Mac OS X 10.1 */
+#define kATSOptionFlagsUnRestrictedScope kATSOptionFlagsDefault
+#endif
+
+
+ /* Set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over
+ TrueType in case *both* are available (this is not common,
+ but it *is* possible). */
+#ifndef PREFER_LWFN
+#define PREFER_LWFN 1
+#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,
+ FSSpec* pathSpec,
+ FT_Long* face_index )
+ {
+ FT_UNUSED( fontName );
+ FT_UNUSED( pathSpec );
+ FT_UNUSED( face_index );
+
+ return FT_THROW( Unimplemented_Feature );
+ }
+
+
+ /* Private function. */
+ /* The FSSpec type has been discouraged for a long time, */
+ /* unfortunately an FSRef replacement API for */
+ /* ATSFontGetFileSpecification() is only available in */
+ /* Mac OS X 10.5 and later. */
+ static OSStatus
+ FT_ATSFontGetFileReference( ATSFontRef ats_font_id,
+ FSRef* ats_font_ref )
+ {
+#if defined( MAC_OS_X_VERSION_10_5 ) && \
+ ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
+
+ OSStatus err;
+
+ err = ATSFontGetFileReference( ats_font_id, ats_font_ref );
+
+ return err;
+#elif __LP64__ /* No 64bit Carbon API on legacy platforms */
+ FT_UNUSED( ats_font_id );
+ FT_UNUSED( ats_font_ref );
+
+
+ return fnfErr;
+#else /* 32bit Carbon API on legacy platforms */
+ OSStatus err;
+ FSSpec spec;
+
+
+ err = ATSFontGetFileSpecification( ats_font_id, &spec );
+ if ( noErr == err )
+ err = FSpMakeFSRef( &spec, ats_font_ref );
+
+ return err;
+#endif
+ }
+
+
+ static FT_Error
+ FT_GetFileRef_From_Mac_ATS_Name( const char* fontName,
+ FSRef* ats_font_ref,
+ FT_Long* face_index )
+ {
+ CFStringRef cf_fontName;
+ ATSFontRef ats_font_id;
+
+
+ *face_index = 0;
+
+ cf_fontName = CFStringCreateWithCString( NULL, fontName,
+ kCFStringEncodingMacRoman );
+ ats_font_id = ATSFontFindFromName( cf_fontName,
+ kATSOptionFlagsUnRestrictedScope );
+ CFRelease( cf_fontName );
+
+ if ( ats_font_id == 0 || ats_font_id == 0xFFFFFFFFUL )
+ return FT_THROW( Unknown_File_Format );
+
+ if ( noErr != FT_ATSFontGetFileReference( ats_font_id, ats_font_ref ) )
+ return FT_THROW( Unknown_File_Format );
+
+ /* face_index calculation by searching preceding fontIDs */
+ /* with same FSRef */
+ {
+ ATSFontRef id2 = ats_font_id - 1;
+ FSRef ref2;
+
+
+ while ( id2 > 0 )
+ {
+ if ( noErr != FT_ATSFontGetFileReference( id2, &ref2 ) )
+ break;
+ if ( noErr != FSCompareFSRefs( ats_font_ref, &ref2 ) )
+ break;
+
+ id2 --;
+ }
+ *face_index = ats_font_id - ( id2 + 1 );
+ }
+
+ return FT_Err_Ok;
+ }
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_GetFilePath_From_Mac_ATS_Name( const char* fontName,
+ UInt8* path,
+ UInt32 maxPathSize,
+ FT_Long* face_index )
+ {
+ FSRef ref;
+ FT_Error err;
+
+
+ if ( !fontName || !face_index )
+ return FT_THROW( Invalid_Argument) ;
+
+ err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
+ if ( err )
+ return err;
+
+ if ( noErr != FSRefMakePath( &ref, path, maxPathSize ) )
+ return FT_THROW( Unknown_File_Format );
+
+ return FT_Err_Ok;
+ }
+
+
+ /* This function is deprecated because FSSpec is deprecated in Mac OS X */
+ FT_EXPORT_DEF( FT_Error )
+ FT_GetFile_From_Mac_ATS_Name( const char* fontName,
+ FSSpec* pathSpec,
+ FT_Long* face_index )
+ {
+#if ( __LP64__ ) || ( defined( MAC_OS_X_VERSION_10_5 ) && \
+ ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) )
+ FT_UNUSED( fontName );
+ FT_UNUSED( pathSpec );
+ FT_UNUSED( face_index );
+
+ return FT_THROW( Unimplemented_Feature );
+#else
+ FSRef ref;
+ FT_Error err;
+
+
+ if ( !fontName || !face_index )
+ return FT_THROW( Invalid_Argument );
+
+ err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
+ if ( err )
+ return err;
+
+ if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone, NULL, NULL,
+ pathSpec, NULL ) )
+ return FT_THROW( Unknown_File_Format );
+
+ return FT_Err_Ok;
+#endif
+ }
+
+
+ static OSErr
+ FT_FSPathMakeRes( const UInt8* pathname,
+ ResFileRefNum* res )
+ {
+ OSErr err;
+ FSRef ref;
+
+
+ if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
+ return FT_THROW( Cannot_Open_Resource );
+
+ /* at present, no support for dfont format */
+ err = FSOpenResourceFile( &ref, 0, NULL, fsRdPerm, res );
+ if ( noErr == err )
+ return err;
+
+ /* fallback to original resource-fork font */
+ *res = FSOpenResFile( &ref, fsRdPerm );
+ err = ResError();
+
+ return err;
+ }
+
+
+ /* Return the file type for given pathname */
+ static OSType
+ get_file_type_from_path( const UInt8* pathname )
+ {
+ FSRef ref;
+ FSCatalogInfo info;
+
+
+ if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
+ return ( OSType ) 0;
+
+ if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoFinderInfo, &info,
+ NULL, NULL, NULL ) )
+ return ( OSType ) 0;
+
+ return ((FInfo *)(info.finderInfo))->fdType;
+ }
+
+
+ /* Given a PostScript font name, create the Macintosh LWFN file name. */
+ static void
+ create_lwfn_name( char* ps_name,
+ Str255 lwfn_file_name )
+ {
+ int max = 5, count = 0;
+ FT_Byte* p = lwfn_file_name;
+ FT_Byte* q = (FT_Byte*)ps_name;
+
+
+ lwfn_file_name[0] = 0;
+
+ while ( *q )
+ {
+ if ( ft_isupper( *q ) )
+ {
+ if ( count )
+ max = 3;
+ count = 0;
+ }
+ if ( count < max && ( ft_isalnum( *q ) || *q == '_' ) )
+ {
+ *++p = *q;
+ lwfn_file_name[0]++;
+ count++;
+ }
+ q++;
+ }
+ }
+
+
+ static short
+ count_faces_sfnt( char* fond_data )
+ {
+ /* The count is 1 greater than the value in the FOND. */
+ /* Isn't that cute? :-) */
+
+ return EndianS16_BtoN( *( (short*)( fond_data +
+ sizeof ( FamRec ) ) ) ) + 1;
+ }
+
+
+ static short
+ count_faces_scalable( char* fond_data )
+ {
+ AsscEntry* assoc;
+ short i, face, face_all;
+
+
+ face_all = EndianS16_BtoN( *( (short *)( fond_data +
+ sizeof ( FamRec ) ) ) ) + 1;
+ assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
+ face = 0;
+
+ for ( i = 0; i < face_all; i++ )
+ {
+ if ( 0 == EndianS16_BtoN( assoc[i].fontSize ) )
+ face++;
+ }
+ return face;
+ }
+
+
+ /* Look inside the FOND data, answer whether there should be an SFNT
+ resource, and answer the name of a possible LWFN Type 1 file.
+
+ Thanks to Paul Miller (paulm@profoundeffects.com) for the fix
+ to load a face OTHER than the first one in the FOND!
+ */
+
+
+ static void
+ parse_fond( char* fond_data,
+ short* have_sfnt,
+ ResID* sfnt_id,
+ Str255 lwfn_file_name,
+ short face_index )
+ {
+ AsscEntry* assoc;
+ AsscEntry* base_assoc;
+ FamRec* fond;
+
+
+ *sfnt_id = 0;
+ *have_sfnt = 0;
+ lwfn_file_name[0] = 0;
+
+ fond = (FamRec*)fond_data;
+ assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
+ base_assoc = assoc;
+
+ /* the maximum faces in a FOND is 48, size of StyleTable.indexes[] */
+ if ( 47 < face_index )
+ return;
+
+ /* Let's do a little range checking before we get too excited here */
+ if ( face_index < count_faces_sfnt( fond_data ) )
+ {
+ assoc += face_index; /* add on the face_index! */
+
+ /* if the face at this index is not scalable,
+ fall back to the first one (old behavior) */
+ if ( EndianS16_BtoN( assoc->fontSize ) == 0 )
+ {
+ *have_sfnt = 1;
+ *sfnt_id = EndianS16_BtoN( assoc->fontID );
+ }
+ else if ( base_assoc->fontSize == 0 )
+ {
+ *have_sfnt = 1;
+ *sfnt_id = EndianS16_BtoN( base_assoc->fontID );
+ }
+ }
+
+ if ( EndianS32_BtoN( fond->ffStylOff ) )
+ {
+ unsigned char* p = (unsigned char*)fond_data;
+ StyleTable* style;
+ unsigned short string_count;
+ char ps_name[256];
+ unsigned char* names[64];
+ int i;
+
+
+ p += EndianS32_BtoN( fond->ffStylOff );
+ style = (StyleTable*)p;
+ p += sizeof ( StyleTable );
+ string_count = EndianS16_BtoN( *(short*)(p) );
+ string_count = FT_MIN( 64, string_count );
+ p += sizeof ( short );
+
+ for ( i = 0; i < string_count; i++ )
+ {
+ names[i] = p;
+ p += names[i][0];
+ p++;
+ }
+
+ {
+ size_t ps_name_len = (size_t)names[0][0];
+
+
+ if ( ps_name_len != 0 )
+ {
+ ft_memcpy(ps_name, names[0] + 1, ps_name_len);
+ ps_name[ps_name_len] = 0;
+ }
+ if ( style->indexes[face_index] > 1 &&
+ style->indexes[face_index] <= string_count )
+ {
+ unsigned char* suffixes = names[style->indexes[face_index] - 1];
+
+
+ for ( i = 1; i <= suffixes[0]; i++ )
+ {
+ unsigned char* s;
+ size_t j = suffixes[i] - 1;
+
+
+ if ( j < string_count && ( s = names[j] ) != NULL )
+ {
+ size_t s_len = (size_t)s[0];
+
+
+ if ( s_len != 0 && ps_name_len + s_len < sizeof ( ps_name ) )
+ {
+ ft_memcpy( ps_name + ps_name_len, s + 1, s_len );
+ ps_name_len += s_len;
+ ps_name[ps_name_len] = 0;
+ }
+ }
+ }
+ }
+ }
+
+ create_lwfn_name( ps_name, lwfn_file_name );
+ }
+ }
+
+
+ static FT_Error
+ lookup_lwfn_by_fond( const UInt8* path_fond,
+ ConstStr255Param base_lwfn,
+ UInt8* path_lwfn,
+ size_t path_size )
+ {
+ FSRef ref, par_ref;
+ size_t dirname_len;
+
+
+ /* Pathname for FSRef can be in various formats: HFS, HFS+, and POSIX. */
+ /* We should not extract parent directory by string manipulation. */
+
+ if ( noErr != FSPathMakeRef( path_fond, &ref, FALSE ) )
+ return FT_THROW( Invalid_Argument );
+
+ if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
+ NULL, NULL, NULL, &par_ref ) )
+ return FT_THROW( Invalid_Argument );
+
+ if ( noErr != FSRefMakePath( &par_ref, path_lwfn, path_size ) )
+ return FT_THROW( Invalid_Argument );
+
+ if ( ft_strlen( (char *)path_lwfn ) + 1 + base_lwfn[0] > path_size )
+ return FT_THROW( Invalid_Argument );
+
+ /* now we have absolute dirname in path_lwfn */
+ ft_strcat( (char *)path_lwfn, "/" );
+ dirname_len = ft_strlen( (char *)path_lwfn );
+ ft_strcat( (char *)path_lwfn, (char *)base_lwfn + 1 );
+ path_lwfn[dirname_len + base_lwfn[0]] = '\0';
+
+ if ( noErr != FSPathMakeRef( path_lwfn, &ref, FALSE ) )
+ return FT_THROW( Cannot_Open_Resource );
+
+ if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
+ NULL, NULL, NULL, NULL ) )
+ return FT_THROW( Cannot_Open_Resource );
+
+ return FT_Err_Ok;
+ }
+
+
+ static short
+ count_faces( Handle fond,
+ const UInt8* pathname )
+ {
+ ResID sfnt_id;
+ short have_sfnt, have_lwfn;
+ Str255 lwfn_file_name;
+ UInt8 buff[PATH_MAX];
+ FT_Error err;
+ short num_faces;
+
+
+ have_sfnt = have_lwfn = 0;
+
+ parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, 0 );
+
+ if ( lwfn_file_name[0] )
+ {
+ err = lookup_lwfn_by_fond( pathname, lwfn_file_name,
+ buff, sizeof ( buff ) );
+ if ( !err )
+ have_lwfn = 1;
+ }
+
+ if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
+ num_faces = 1;
+ else
+ num_faces = count_faces_scalable( *fond );
+
+ return num_faces;
+ }
+
+
+ /* Read Type 1 data from the POST resources inside the LWFN file,
+ return a PFB buffer. This is somewhat convoluted because the FT2
+ PFB parser wants the ASCII header as one chunk, and the LWFN
+ chunks are often not organized that way, so we glue chunks
+ of the same type together. */
+ static FT_Error
+ read_lwfn( FT_Memory memory,
+ ResFileRefNum res,
+ FT_Byte** pfb_data,
+ FT_ULong* size )
+ {
+ FT_Error error = FT_Err_Ok;
+ ResID res_id;
+ unsigned char *buffer, *p, *size_p = NULL;
+ FT_ULong total_size = 0;
+ FT_ULong old_total_size = 0;
+ FT_ULong post_size, pfb_chunk_size;
+ Handle post_data;
+ char code, last_code;
+
+
+ UseResFile( res );
+
+ /* First pass: load all POST resources, and determine the size of */
+ /* the output buffer. */
+ res_id = 501;
+ last_code = -1;
+
+ for (;;)
+ {
+ post_data = Get1Resource( TTAG_POST, res_id++ );
+ if ( post_data == NULL )
+ break; /* we are done */
+
+ code = (*post_data)[0];
+
+ if ( code != last_code )
+ {
+ if ( code == 5 )
+ total_size += 2; /* just the end code */
+ else
+ total_size += 6; /* code + 4 bytes chunk length */
+ }
+
+ total_size += (FT_ULong)GetHandleSize( post_data ) - 2;
+ last_code = code;
+
+ /* detect resource fork overflow */
+ if ( FT_MAC_RFORK_MAX_LEN < total_size )
+ {
+ error = FT_THROW( Array_Too_Large );
+ goto Error;
+ }
+
+ old_total_size = total_size;
+ }
+
+ if ( FT_ALLOC( buffer, (FT_Long)total_size ) )
+ goto Error;
+
+ /* Second pass: append all POST data to the buffer, add PFB fields. */
+ /* Glue all consecutive chunks of the same type together. */
+ p = buffer;
+ res_id = 501;
+ last_code = -1;
+ pfb_chunk_size = 0;
+
+ for (;;)
+ {
+ post_data = Get1Resource( TTAG_POST, res_id++ );
+ if ( post_data == NULL )
+ break; /* we are done */
+
+ post_size = (FT_ULong)GetHandleSize( post_data ) - 2;
+ code = (*post_data)[0];
+
+ if ( code != last_code )
+ {
+ if ( last_code != -1 )
+ {
+ /* we are done adding a chunk, fill in the size field */
+ if ( size_p != NULL )
+ {
+ *size_p++ = (FT_Byte)( pfb_chunk_size & 0xFF );
+ *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 8 ) & 0xFF );
+ *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 16 ) & 0xFF );
+ *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 24 ) & 0xFF );
+ }
+ pfb_chunk_size = 0;
+ }
+
+ *p++ = 0x80;
+ if ( code == 5 )
+ *p++ = 0x03; /* the end */
+ else if ( code == 2 )
+ *p++ = 0x02; /* binary segment */
+ else
+ *p++ = 0x01; /* ASCII segment */
+
+ if ( code != 5 )
+ {
+ size_p = p; /* save for later */
+ p += 4; /* make space for size field */
+ }
+ }
+
+ ft_memcpy( p, *post_data + 2, post_size );
+ pfb_chunk_size += post_size;
+ p += post_size;
+ last_code = code;
+ }
+
+ *pfb_data = buffer;
+ *size = total_size;
+
+ Error:
+ CloseResFile( res );
+ return error;
+ }
+
+
+ /* Create a new FT_Face from a file path to an LWFN file. */
+ static FT_Error
+ FT_New_Face_From_LWFN( FT_Library library,
+ const UInt8* pathname,
+ FT_Long face_index,
+ FT_Face* aface )
+ {
+ FT_Byte* pfb_data;
+ FT_ULong pfb_size;
+ FT_Error error;
+ ResFileRefNum res;
+
+
+ if ( noErr != FT_FSPathMakeRes( pathname, &res ) )
+ return FT_THROW( Cannot_Open_Resource );
+
+ pfb_data = NULL;
+ pfb_size = 0;
+ error = read_lwfn( library->memory, res, &pfb_data, &pfb_size );
+ CloseResFile( res ); /* PFB is already loaded, useless anymore */
+ if ( error )
+ return error;
+
+ return open_face_from_buffer( library,
+ pfb_data,
+ pfb_size,
+ face_index,
+ "type1",
+ aface );
+ }
+
+
+ /* Create a new FT_Face from an SFNT resource, specified by res ID. */
+ static FT_Error
+ FT_New_Face_From_SFNT( FT_Library library,
+ ResID sfnt_id,
+ FT_Long face_index,
+ FT_Face* aface )
+ {
+ Handle sfnt = NULL;
+ FT_Byte* sfnt_data;
+ size_t sfnt_size;
+ FT_Error error = FT_Err_Ok;
+ FT_Memory memory = library->memory;
+ int is_cff, is_sfnt_ps;
+
+
+ sfnt = GetResource( TTAG_sfnt, sfnt_id );
+ if ( sfnt == NULL )
+ return FT_THROW( Invalid_Handle );
+
+ sfnt_size = (FT_ULong)GetHandleSize( sfnt );
+
+ /* detect resource fork overflow */
+ if ( FT_MAC_RFORK_MAX_LEN < sfnt_size )
+ return FT_THROW( Array_Too_Large );
+
+ if ( FT_ALLOC( sfnt_data, (FT_Long)sfnt_size ) )
+ {
+ ReleaseResource( sfnt );
+ return error;
+ }
+
+ ft_memcpy( sfnt_data, *sfnt, sfnt_size );
+ ReleaseResource( sfnt );
+
+ is_cff = sfnt_size > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
+ is_sfnt_ps = sfnt_size > 4 && !ft_memcmp( sfnt_data, "typ1", 4 );
+
+ if ( is_sfnt_ps )
+ {
+ FT_Stream stream;
+
+
+ if ( FT_NEW( stream ) )
+ goto Try_OpenType;
+
+ FT_Stream_OpenMemory( stream, sfnt_data, sfnt_size );
+ if ( !open_face_PS_from_sfnt_stream( library,
+ stream,
+ face_index,
+ 0, NULL,
+ aface ) )
+ {
+ FT_Stream_Close( stream );
+ FT_FREE( stream );
+ FT_FREE( sfnt_data );
+ goto Exit;
+ }
+
+ FT_FREE( stream );
+ }
+ Try_OpenType:
+ error = open_face_from_buffer( library,
+ sfnt_data,
+ sfnt_size,
+ face_index,
+ is_cff ? "cff" : "truetype",
+ aface );
+ Exit:
+ return error;
+ }
+
+
+ /* Create a new FT_Face from a file path to a suitcase file. */
+ static FT_Error
+ FT_New_Face_From_Suitcase( FT_Library library,
+ const UInt8* pathname,
+ FT_Long face_index,
+ FT_Face* aface )
+ {
+ FT_Error error = FT_ERR( Cannot_Open_Resource );
+ ResFileRefNum res_ref;
+ ResourceIndex res_index;
+ Handle fond;
+ short num_faces_in_res;
+
+
+ if ( noErr != FT_FSPathMakeRes( pathname, &res_ref ) )
+ return FT_THROW( Cannot_Open_Resource );
+
+ UseResFile( res_ref );
+ if ( ResError() )
+ return FT_THROW( Cannot_Open_Resource );
+
+ num_faces_in_res = 0;
+ for ( res_index = 1; ; ++res_index )
+ {
+ short num_faces_in_fond;
+
+
+ fond = Get1IndResource( TTAG_FOND, res_index );
+ if ( ResError() )
+ break;
+
+ num_faces_in_fond = count_faces( fond, pathname );
+ num_faces_in_res += num_faces_in_fond;
+
+ if ( 0 <= face_index && face_index < num_faces_in_fond && error )
+ error = FT_New_Face_From_FOND( library, fond, face_index, aface );
+
+ face_index -= num_faces_in_fond;
+ }
+
+ CloseResFile( res_ref );
+ if ( !error && aface && *aface )
+ (*aface)->num_faces = num_faces_in_res;
+ return error;
+ }
+
+
+ /* documentation is in ftmac.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_New_Face_From_FOND( FT_Library library,
+ Handle fond,
+ FT_Long face_index,
+ FT_Face* aface )
+ {
+ short have_sfnt, have_lwfn = 0;
+ ResID sfnt_id, fond_id;
+ OSType fond_type;
+ Str255 fond_name;
+ Str255 lwfn_file_name;
+ UInt8 path_lwfn[PATH_MAX];
+ OSErr err;
+ FT_Error error = FT_Err_Ok;
+
+
+ /* check of `library' and `aface' delayed to `FT_New_Face_From_XXX' */
+
+ GetResInfo( fond, &fond_id, &fond_type, fond_name );
+ if ( ResError() != noErr || fond_type != TTAG_FOND )
+ return FT_THROW( Invalid_File_Format );
+
+ parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, face_index );
+
+ if ( lwfn_file_name[0] )
+ {
+ ResFileRefNum res;
+
+
+ res = HomeResFile( fond );
+ if ( noErr != ResError() )
+ goto found_no_lwfn_file;
+
+ {
+ UInt8 path_fond[PATH_MAX];
+ FSRef ref;
+
+
+ err = FSGetForkCBInfo( res, kFSInvalidVolumeRefNum,
+ NULL, NULL, NULL, &ref, NULL );
+ if ( noErr != err )
+ goto found_no_lwfn_file;
+
+ err = FSRefMakePath( &ref, path_fond, sizeof ( path_fond ) );
+ if ( noErr != err )
+ goto found_no_lwfn_file;
+
+ error = lookup_lwfn_by_fond( path_fond, lwfn_file_name,
+ path_lwfn, sizeof ( path_lwfn ) );
+ if ( !error )
+ have_lwfn = 1;
+ }
+ }
+
+ if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
+ error = FT_New_Face_From_LWFN( library,
+ path_lwfn,
+ face_index,
+ aface );
+ else
+ error = FT_THROW( Unknown_File_Format );
+
+ found_no_lwfn_file:
+ if ( have_sfnt && error )
+ error = FT_New_Face_From_SFNT( library,
+ sfnt_id,
+ face_index,
+ aface );
+
+ return error;
+ }
+
+
+ /* Common function to load a new FT_Face from a resource file. */
+ static FT_Error
+ FT_New_Face_From_Resource( FT_Library library,
+ const UInt8* pathname,
+ FT_Long face_index,
+ FT_Face* aface )
+ {
+ OSType file_type;
+ FT_Error error;
+
+
+ /* LWFN is a (very) specific file format, check for it explicitly */
+ file_type = get_file_type_from_path( pathname );
+ if ( file_type == TTAG_LWFN )
+ return FT_New_Face_From_LWFN( library, pathname, face_index, aface );
+
+ /* Otherwise the file type doesn't matter (there are more than */
+ /* `FFIL' and `tfil'). Just try opening it as a font suitcase; */
+ /* if it works, fine. */
+
+ error = FT_New_Face_From_Suitcase( library, pathname, face_index, aface );
+ if ( error == 0 )
+ return error;
+
+ /* let it fall through to normal loader (.ttf, .otf, etc.); */
+ /* we signal this by returning no error and no FT_Face */
+ *aface = NULL;
+ return 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_Face */
+ /* */
+ /* <Description> */
+ /* This is the Mac-specific implementation of FT_New_Face. In */
+ /* addition to the standard FT_New_Face() functionality, it also */
+ /* accepts pathnames to Mac suitcase files. For further */
+ /* documentation see the original FT_New_Face() in freetype.h. */
+ /* */
+ FT_EXPORT_DEF( FT_Error )
+ FT_New_Face( FT_Library library,
+ const char* pathname,
+ FT_Long face_index,
+ FT_Face* aface )
+ {
+ FT_Open_Args args;
+ FT_Error error;
+
+
+ /* test for valid `library' and `aface' delayed to FT_Open_Face() */
+ if ( !pathname )
+ return FT_THROW( Invalid_Argument );
+
+ *aface = NULL;
+
+ /* try resourcefork based font: LWFN, FFIL */
+ error = FT_New_Face_From_Resource( library, (UInt8 *)pathname,
+ face_index, aface );
+ if ( error != 0 || *aface != NULL )
+ return error;
+
+ /* let it fall through to normal loader (.ttf, .otf, etc.) */
+ args.flags = FT_OPEN_PATHNAME;
+ args.pathname = (char*)pathname;
+ return FT_Open_Face( library, &args, face_index, aface );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_Face_From_FSRef */
+ /* */
+ /* <Description> */
+ /* FT_New_Face_From_FSRef is identical to FT_New_Face except it */
+ /* 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. */
+ FT_EXPORT_DEF( FT_Error )
+ FT_New_Face_From_FSRef( FT_Library library,
+ const FSRef* ref,
+ FT_Long face_index,
+ FT_Face* aface )
+ {
+ FT_Error error;
+ FT_Open_Args args;
+
+ OSErr err;
+ UInt8 pathname[PATH_MAX];
+
+
+ /* check of `library' and `aface' delayed to */
+ /* `FT_New_Face_From_Resource' */
+
+ if ( !ref )
+ return FT_THROW( Invalid_Argument );
+
+ err = FSRefMakePath( ref, pathname, sizeof ( pathname ) );
+ if ( err )
+ error = FT_THROW( Cannot_Open_Resource );
+
+ error = FT_New_Face_From_Resource( library, pathname, face_index, aface );
+ if ( error != 0 || *aface != NULL )
+ return error;
+
+ /* fallback to datafork font */
+ args.flags = FT_OPEN_PATHNAME;
+ args.pathname = (char*)pathname;
+ return FT_Open_Face( library, &args, face_index, aface );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_Face_From_FSSpec */
+ /* */
+ /* <Description> */
+ /* FT_New_Face_From_FSSpec is identical to FT_New_Face except it */
+ /* accepts an FSSpec instead of a path. */
+ /* */
+ /* This function is deprecated because FSSpec is deprecated in Mac OS X */
+ FT_EXPORT_DEF( FT_Error )
+ FT_New_Face_From_FSSpec( FT_Library library,
+ const FSSpec* spec,
+ FT_Long face_index,
+ FT_Face* aface )
+ {
+#if ( __LP64__ ) || ( defined( MAC_OS_X_VERSION_10_5 ) && \
+ ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) )
+ FT_UNUSED( library );
+ FT_UNUSED( spec );
+ FT_UNUSED( face_index );
+ FT_UNUSED( aface );
+
+ return FT_THROW( Unimplemented_Feature );
+#else
+ FSRef ref;
+
+
+ /* check of `library' and `aface' delayed to `FT_New_Face_From_FSRef' */
+
+ if ( !spec || FSpMakeFSRef( spec, &ref ) != noErr )
+ return FT_THROW( Invalid_Argument );
+ else
+ return FT_New_Face_From_FSRef( library, &ref, face_index, aface );
+#endif
+ }
+
+#endif /* FT_MACINTOSH */
+
+
+/* END */
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index 9c3332c..96572bd 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -55,7 +55,18 @@
#pragma warning( disable : 4244 )
#endif /* _MSC_VER */
- /* it's easiest to include `md5.c' directly */
+ /* It's easiest to include `md5.c' directly. However, since OpenSSL */
+ /* also provides the same functions, there might be conflicts if */
+ /* both FreeType and OpenSSL are built as static libraries. For */
+ /* this reason, we put the MD5 stuff into the `FT_' namespace. */
+#define MD5_u32plus FT_MD5_u32plus
+#define MD5_CTX FT_MD5_CTX
+#define MD5_Init FT_MD5_Init
+#define MD5_Update FT_MD5_Update
+#define MD5_Final FT_MD5_Final
+
+#undef HAVE_OPENSSL
+
#include "md5.c"
#if defined( _MSC_VER )
@@ -675,7 +686,8 @@
/* 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 ||
+ if ( ( mode == FT_RENDER_MODE_LIGHT &&
+ !FT_DRIVER_HINTS_LIGHTLY( driver ) ) ||
face->internal->ignore_unpatented_hinter ||
( FT_IS_SFNT( face ) &&
ttface->num_locations &&
@@ -1375,13 +1387,13 @@
}
#ifdef FT_MACINTOSH
- /* At this point, face_index has served its purpose; */
+ /* At this point, the face index has served its purpose; */
/* whoever calls this function has already used it to */
/* locate the correct font data. We should not propagate */
/* this index to FT_Open_Face() (unless it is negative). */
if ( face_index > 0 )
- face_index = 0;
+ face_index &= 0x7FFF0000L; /* retain GX data */
#endif
error = FT_Open_Face( library, &args, face_index, aface );
@@ -1495,6 +1507,10 @@
FT_UNUSED( params );
+ /* ignore GX stuff */
+ if ( face_index > 0 )
+ face_index &= 0xFFFFL;
+
pos = FT_STREAM_POS();
error = ft_lookup_PS_in_sfnt_stream( stream,
@@ -1505,15 +1521,18 @@
if ( error )
goto Exit;
- if ( FT_Stream_Seek( stream, pos + offset ) )
+ error = FT_Stream_Seek( stream, pos + offset );
+ if ( error )
goto Exit;
if ( FT_ALLOC( sfnt_ps, (FT_Long)length ) )
goto Exit;
error = FT_Stream_Read( stream, (FT_Byte *)sfnt_ps, length );
- if ( error )
+ if ( error ) {
+ FT_FREE( sfnt_ps );
goto Exit;
+ }
error = open_face_from_buffer( library,
sfnt_ps,
@@ -1582,12 +1601,14 @@
/* FT2 allocator takes signed long buffer length,
* too large value causing overflow should be checked
*/
- FT_TRACE4(( " POST fragment #%d: length=0x%08x\n",
- i, temp));
- if ( 0x7FFFFFFFUL < temp || pfb_len + temp + 6 < pfb_len )
+ FT_TRACE4(( " POST fragment #%d: length=0x%08x"
+ " total pfb_len=0x%08x\n",
+ i, temp, pfb_len + temp + 6));
+ if ( FT_MAC_RFORK_MAX_LEN < temp ||
+ FT_MAC_RFORK_MAX_LEN - temp < pfb_len + 6 )
{
- FT_TRACE2(( " too long fragment length makes"
- " pfb_len confused: temp=0x%08x\n", temp ));
+ FT_TRACE2(( " MacOS resource length cannot exceed"
+ " 0x%08x\n", FT_MAC_RFORK_MAX_LEN ));
error = FT_THROW( Invalid_Offset );
goto Exit;
}
@@ -1660,7 +1681,7 @@
else
{
FT_TRACE3(( " Write POST fragment #%d header (4-byte) to buffer"
- " 0x%p + 0x%08x\n", i, pfb_data, pfb_lenpos ));
+ " %p + 0x%08x\n", i, pfb_data, pfb_lenpos ));
if ( pfb_lenpos + 3 > pfb_len + 2 )
goto Exit2;
pfb_data[pfb_lenpos ] = (FT_Byte)( len );
@@ -1672,7 +1693,7 @@
break;
FT_TRACE3(( " Write POST fragment #%d header (6-byte) to buffer"
- " 0x%p + 0x%08x\n", i, pfb_data, pfb_pos ));
+ " %p + 0x%08x\n", i, pfb_data, pfb_pos ));
if ( pfb_pos + 6 > pfb_len + 2 )
goto Exit2;
pfb_data[pfb_pos++] = 0x80;
@@ -1692,7 +1713,7 @@
goto Exit2;
FT_TRACE3(( " Load POST fragment #%d (%d byte) to buffer"
- " 0x%p + 0x%08x\n", i, rlen, pfb_data, pfb_pos ));
+ " %p + 0x%08x\n", i, rlen, pfb_data, pfb_pos ));
error = FT_Stream_Read( stream, (FT_Byte *)pfb_data + pfb_pos, rlen );
if ( error )
goto Exit2;
@@ -1737,7 +1758,7 @@
/* The resource header says we've got resource_cnt `sfnt' */
/* (TrueType/OpenType) resources in this file. Look through */
/* them for the one indicated by face_index, load it into mem, */
- /* pass it on the the truetype driver and return it. */
+ /* pass it on to the truetype driver, and return it. */
/* */
static FT_Error
Mac_Read_sfnt_Resource( FT_Library library,
@@ -1770,6 +1791,8 @@
goto Exit;
if ( rlen == -1 )
return FT_THROW( Cannot_Open_Resource );
+ if ( (FT_ULong)rlen > FT_MAC_RFORK_MAX_LEN )
+ return FT_THROW( Invalid_Offset );
error = open_face_PS_from_sfnt_stream( library,
stream,
@@ -1780,14 +1803,17 @@
goto Exit;
/* rewind sfnt stream before open_face_PS_from_sfnt_stream() */
- if ( FT_Stream_Seek( stream, flag_offset + 4 ) )
+ error = FT_Stream_Seek( stream, flag_offset + 4 );
+ if ( error )
goto Exit;
if ( FT_ALLOC( sfnt_data, rlen ) )
return error;
error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, (FT_ULong)rlen );
- if ( error )
+ if ( error ) {
+ FT_FREE( sfnt_data );
goto Exit;
+ }
is_cff = rlen > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
error = open_face_from_buffer( library,
@@ -1889,13 +1915,14 @@
if ( error )
goto Exit;
- if ( header[ 0] != 0 ||
- header[74] != 0 ||
- header[82] != 0 ||
- header[ 1] == 0 ||
- header[ 1] > 33 ||
- header[63] != 0 ||
- header[2 + header[1]] != 0 )
+ if ( header[ 0] != 0 ||
+ header[74] != 0 ||
+ header[82] != 0 ||
+ header[ 1] == 0 ||
+ header[ 1] > 33 ||
+ header[63] != 0 ||
+ header[2 + header[1]] != 0 ||
+ header[0x53] > 0x7F )
return FT_THROW( Unknown_File_Format );
dlen = ( header[0x53] << 24 ) |
@@ -2032,7 +2059,11 @@
#undef FT_COMPONENT
#define FT_COMPONENT trace_raccess
- FT_TRACE3(( "Try as dfont: %s ...", args->pathname ));
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_TRACE3(( "Try as dfont: " ));
+ if ( !( args->flags & FT_OPEN_MEMORY ) )
+ FT_TRACE3(( "%s ...", args->pathname ));
+#endif
error = IsMacResource( library, stream, 0, face_index, aface );
@@ -2154,7 +2185,8 @@
FT_ERR_EQ( error, Table_Missing ) )
{
/* TrueType but essential tables are missing */
- if ( FT_Stream_Seek( stream, 0 ) )
+ error = FT_Stream_Seek( stream, 0 );
+ if ( error )
break;
error = open_face_PS_from_sfnt_stream( library,
@@ -3068,18 +3100,37 @@
if ( kern_mode != FT_KERNING_UNFITTED )
{
+ FT_Pos orig_x = akerning->x;
+ FT_Pos orig_y = akerning->y;
+
+
/* we scale down kerning values for small ppem values */
/* to avoid that rounding makes them too big. */
/* `25' has been determined heuristically. */
if ( face->size->metrics.x_ppem < 25 )
- akerning->x = FT_MulDiv( akerning->x,
+ akerning->x = FT_MulDiv( orig_x,
face->size->metrics.x_ppem, 25 );
if ( face->size->metrics.y_ppem < 25 )
- akerning->y = FT_MulDiv( akerning->y,
+ akerning->y = FT_MulDiv( orig_y,
face->size->metrics.y_ppem, 25 );
akerning->x = FT_PIX_ROUND( akerning->x );
akerning->y = FT_PIX_ROUND( akerning->y );
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ {
+ FT_Pos orig_x_rounded = FT_PIX_ROUND( orig_x );
+ FT_Pos orig_y_rounded = FT_PIX_ROUND( orig_y );
+
+
+ if ( akerning->x != orig_x_rounded ||
+ akerning->y != orig_y_rounded )
+ FT_TRACE5(( "FT_Get_Kerning: horizontal kerning"
+ " (%d, %d) scaled down to (%d, %d) pixels\n",
+ orig_x_rounded / 64, orig_y_rounded / 64,
+ akerning->x / 64, akerning->y / 64 ));
+ }
+#endif
}
}
}
@@ -3350,8 +3401,12 @@
FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));
FT_TRACE1(( " 0x%x is truncated\n", charcode ));
}
+
result = cmap->clazz->char_index( cmap, (FT_UInt32)charcode );
+ if ( result >= (FT_UInt)face->num_glyphs )
+ result = 0;
}
+
return result;
}
@@ -3370,7 +3425,7 @@
if ( face && face->charmap && face->num_glyphs )
{
gindex = FT_Get_Char_Index( face, 0 );
- if ( gindex == 0 || gindex >= (FT_UInt)face->num_glyphs )
+ if ( gindex == 0 )
result = FT_Get_Next_Char( face, 0, &gindex );
}
@@ -4116,39 +4171,50 @@
#undef FT_COMPONENT
#define FT_COMPONENT trace_bitmap
- /* we convert to a single bitmap format for computing the checksum */
- if ( !error )
+ /*
+ * Computing the MD5 checksum is expensive, unnecessarily distorting a
+ * possible profiling of FreeType if compiled with tracing support. For
+ * this reason, we execute the following code only if explicitly
+ * requested.
+ */
+
+ /* we use FT_TRACE3 in this block */
+ if ( ft_trace_levels[trace_bitmap] >= 3 )
{
- FT_Bitmap bitmap;
- FT_Error err;
+ /* we convert to a single bitmap format for computing the checksum */
+ if ( !error )
+ {
+ FT_Bitmap bitmap;
+ FT_Error err;
- FT_Bitmap_Init( &bitmap );
+ FT_Bitmap_Init( &bitmap );
- /* this also converts the bitmap flow to `down' (i.e., pitch > 0) */
- err = FT_Bitmap_Convert( library, &slot->bitmap, &bitmap, 1 );
- if ( !err )
- {
- MD5_CTX ctx;
- unsigned char md5[16];
- int i;
- unsigned int rows = bitmap.rows;
- unsigned int pitch = (unsigned int)bitmap.pitch;
-
-
- MD5_Init( &ctx );
- 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" ));
- }
+ /* this also converts the bitmap flow to `down' (i.e., pitch > 0) */
+ err = FT_Bitmap_Convert( library, &slot->bitmap, &bitmap, 1 );
+ if ( !err )
+ {
+ MD5_CTX ctx;
+ unsigned char md5[16];
+ int i;
+ unsigned int rows = bitmap.rows;
+ unsigned int pitch = (unsigned int)bitmap.pitch;
+
+
+ MD5_Init( &ctx );
+ 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" ));
+ }
- FT_Bitmap_Done( library, &bitmap );
+ FT_Bitmap_Done( library, &bitmap );
+ }
}
#undef FT_COMPONENT
diff --git a/src/base/ftotval.c b/src/base/ftotval.c
new file mode 100644
index 0000000..786457b
--- /dev/null
+++ b/src/base/ftotval.c
@@ -0,0 +1,91 @@
+/***************************************************************************/
+/* */
+/* ftotval.c */
+/* */
+/* FreeType API for validating OpenType tables (body). */
+/* */
+/* Copyright 2004-2015 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_INTERNAL_DEBUG_H
+
+#include FT_INTERNAL_OBJECTS_H
+#include FT_SERVICE_OPENTYPE_VALIDATE_H
+#include FT_OPENTYPE_VALIDATE_H
+
+
+ /* documentation is in ftotval.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_OpenType_Validate( FT_Face face,
+ FT_UInt validation_flags,
+ FT_Bytes *BASE_table,
+ FT_Bytes *GDEF_table,
+ FT_Bytes *GPOS_table,
+ FT_Bytes *GSUB_table,
+ FT_Bytes *JSTF_table )
+ {
+ FT_Service_OTvalidate service;
+ FT_Error error;
+
+
+ if ( !face )
+ {
+ error = FT_THROW( Invalid_Face_Handle );
+ goto Exit;
+ }
+
+ if ( !( BASE_table &&
+ GDEF_table &&
+ GPOS_table &&
+ GSUB_table &&
+ JSTF_table ) )
+ {
+ error = FT_THROW( Invalid_Argument );
+ goto Exit;
+ }
+
+ FT_FACE_FIND_GLOBAL_SERVICE( face, service, OPENTYPE_VALIDATE );
+
+ if ( service )
+ error = service->validate( face,
+ validation_flags,
+ BASE_table,
+ GDEF_table,
+ GPOS_table,
+ GSUB_table,
+ JSTF_table );
+ else
+ error = FT_THROW( Unimplemented_Feature );
+
+ Exit:
+ return error;
+ }
+
+
+ FT_EXPORT_DEF( void )
+ FT_OpenType_Free( FT_Face face,
+ FT_Bytes table )
+ {
+ FT_Memory memory;
+
+
+ if ( !face )
+ return;
+
+ memory = FT_FACE_MEMORY( face );
+
+ FT_FREE( table );
+ }
+
+
+/* END */
diff --git a/src/base/ftoutln.c b/src/base/ftoutln.c
index d821c49..201ceab 100644
--- a/src/base/ftoutln.c
+++ b/src/base/ftoutln.c
@@ -52,8 +52,9 @@
const FT_Outline_Funcs* func_interface,
void* user )
{
-#undef SCALED
-#define SCALED( x ) ( ( (x) << shift ) - delta )
+#undef SCALED
+#define SCALED( x ) ( ( (x) < 0 ? -( -(x) << shift ) \
+ : ( (x) << shift ) ) - delta )
FT_Vector v_last;
FT_Vector v_control;
@@ -907,8 +908,7 @@
FT_Pos ystrength )
{
FT_Vector* points;
- FT_Vector v_prev, v_first, v_next, v_cur;
- FT_Int c, n, first;
+ FT_Int c, first, last;
FT_Int orientation;
@@ -934,87 +934,98 @@
first = 0;
for ( c = 0; c < outline->n_contours; c++ )
{
- FT_Vector in, out, shift;
- FT_Fixed l_in, l_out, l, q, d;
- int last = outline->contours[c];
+ FT_Vector in, out, anchor, shift;
+ FT_Fixed l_in, l_out, l_anchor = 0, l, q, d;
+ FT_Int i, j, k;
- v_first = points[first];
- v_prev = points[last];
- v_cur = v_first;
+ l_in = 0;
+ last = outline->contours[c];
- /* compute incoming normalized vector */
- in.x = v_cur.x - v_prev.x;
- in.y = v_cur.y - v_prev.y;
- l_in = FT_Vector_Length( &in );
- if ( l_in )
- {
- in.x = FT_DivFix( in.x, l_in );
- in.y = FT_DivFix( in.y, l_in );
- }
+ /* pacify compiler */
+ in.x = in.y = anchor.x = anchor.y = 0;
- for ( n = first; n <= last; n++ )
+ /* Counter j cycles though the points; counter i advances only */
+ /* when points are moved; anchor k marks the first moved point. */
+ for ( i = last, j = first, k = -1;
+ j != i && i != k;
+ j = j < last ? j + 1 : first )
{
- if ( n < last )
- v_next = points[n + 1];
- else
- v_next = v_first;
+ if ( j != k )
+ {
+ out.x = points[j].x - points[i].x;
+ out.y = points[j].y - points[i].y;
+ l_out = (FT_Fixed)FT_Vector_NormLen( &out );
- /* compute outgoing normalized vector */
- out.x = v_next.x - v_cur.x;
- out.y = v_next.y - v_cur.y;
- l_out = FT_Vector_Length( &out );
- if ( l_out )
+ if ( l_out == 0 )
+ continue;
+ }
+ else
{
- out.x = FT_DivFix( out.x, l_out );
- out.y = FT_DivFix( out.y, l_out );
+ out = anchor;
+ l_out = l_anchor;
}
- d = FT_MulFix( in.x, out.x ) + FT_MulFix( in.y, out.y );
-
- /* shift only if turn is less than ~160 degrees */
- if ( d > -0xF000L )
+ if ( l_in != 0 )
{
- d = d + 0x10000L;
+ if ( k < 0 )
+ {
+ k = i;
+ anchor = in;
+ l_anchor = l_in;
+ }
- /* shift components are aligned along lateral bisector */
- /* and directed according to the outline orientation. */
- shift.x = in.y + out.y;
- shift.y = in.x + out.x;
+ d = FT_MulFix( in.x, out.x ) + FT_MulFix( in.y, out.y );
- if ( orientation == FT_ORIENTATION_TRUETYPE )
- shift.x = -shift.x;
- else
- shift.y = -shift.y;
+ /* shift only if turn is less than ~160 degrees */
+ if ( d > -0xF000L )
+ {
+ d = d + 0x10000L;
- /* restrict shift magnitude to better handle collapsing segments */
- q = FT_MulFix( out.x, in.y ) - FT_MulFix( out.y, in.x );
- if ( orientation == FT_ORIENTATION_TRUETYPE )
- q = -q;
+ /* shift components along lateral bisector in proper orientation */
+ shift.x = in.y + out.y;
+ shift.y = in.x + out.x;
- l = FT_MIN( l_in, l_out );
+ if ( orientation == FT_ORIENTATION_TRUETYPE )
+ shift.x = -shift.x;
+ else
+ shift.y = -shift.y;
- /* non-strict inequalities avoid divide-by-zero when q == l == 0 */
- if ( FT_MulFix( xstrength, q ) <= FT_MulFix( l, d ) )
- shift.x = FT_MulDiv( shift.x, xstrength, d );
- else
- shift.x = FT_MulDiv( shift.x, l, q );
+ /* restrict shift magnitude to better handle collapsing segments */
+ q = FT_MulFix( out.x, in.y ) - FT_MulFix( out.y, in.x );
+ if ( orientation == FT_ORIENTATION_TRUETYPE )
+ q = -q;
+ l = FT_MIN( l_in, l_out );
- if ( FT_MulFix( ystrength, q ) <= FT_MulFix( l, d ) )
- shift.y = FT_MulDiv( shift.y, ystrength, d );
+ /* non-strict inequalities avoid divide-by-zero when q == l == 0 */
+ if ( FT_MulFix( xstrength, q ) <= FT_MulFix( l, d ) )
+ shift.x = FT_MulDiv( shift.x, xstrength, d );
+ else
+ shift.x = FT_MulDiv( shift.x, l, q );
+
+
+ if ( FT_MulFix( ystrength, q ) <= FT_MulFix( l, d ) )
+ shift.y = FT_MulDiv( shift.y, ystrength, d );
+ else
+ shift.y = FT_MulDiv( shift.y, l, q );
+ }
else
- shift.y = FT_MulDiv( shift.y, l, q );
+ shift.x = shift.y = 0;
+
+ for ( ;
+ i != j;
+ i = i < last ? i + 1 : first )
+ {
+ points[i].x += xstrength + shift.x;
+ points[i].y += ystrength + shift.y;
+ }
}
else
- shift.x = shift.y = 0;
+ i = j;
- outline->points[n].x = v_cur.x + xstrength + shift.x;
- outline->points[n].y = v_cur.y + ystrength + shift.y;
-
- in = out;
- l_in = l_out;
- v_cur = v_next;
+ in = out;
+ l_in = l_out;
}
first = last + 1;
@@ -1066,13 +1077,16 @@
FT_Int last = outline->contours[c];
- v_prev = points[last];
+ v_prev.x = points[last].x >> xshift;
+ v_prev.y = points[last].y >> yshift;
for ( n = first; n <= last; n++ )
{
- v_cur = points[n];
- area += ( ( v_cur.y - v_prev.y ) >> yshift ) *
- ( ( v_cur.x + v_prev.x ) >> xshift );
+ 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 );
+
v_prev = v_cur;
}
diff --git a/src/base/ftpfr.c b/src/base/ftpfr.c
new file mode 100644
index 0000000..39f089e
--- /dev/null
+++ b/src/base/ftpfr.c
@@ -0,0 +1,153 @@
+/***************************************************************************/
+/* */
+/* ftpfr.c */
+/* */
+/* FreeType API for accessing PFR-specific data (body). */
+/* */
+/* Copyright 2002-2015 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_INTERNAL_DEBUG_H
+
+#include FT_INTERNAL_OBJECTS_H
+#include FT_SERVICE_PFR_H
+
+
+ /* check the format */
+ static FT_Service_PfrMetrics
+ ft_pfr_check( FT_Face face )
+ {
+ FT_Service_PfrMetrics service = NULL;
+
+
+ if ( face )
+ FT_FACE_LOOKUP_SERVICE( face, service, PFR_METRICS );
+
+ return service;
+ }
+
+
+ /* documentation is in ftpfr.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_PFR_Metrics( FT_Face face,
+ FT_UInt *aoutline_resolution,
+ FT_UInt *ametrics_resolution,
+ FT_Fixed *ametrics_x_scale,
+ FT_Fixed *ametrics_y_scale )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_Service_PfrMetrics service;
+
+
+ if ( !face )
+ return FT_THROW( Invalid_Face_Handle );
+
+ service = ft_pfr_check( face );
+ if ( service )
+ {
+ error = service->get_metrics( face,
+ aoutline_resolution,
+ ametrics_resolution,
+ ametrics_x_scale,
+ ametrics_y_scale );
+ }
+ else
+ {
+ FT_Fixed x_scale, y_scale;
+
+
+ /* this is not a PFR font */
+ if ( aoutline_resolution )
+ *aoutline_resolution = face->units_per_EM;
+
+ if ( ametrics_resolution )
+ *ametrics_resolution = face->units_per_EM;
+
+ x_scale = y_scale = 0x10000L;
+ if ( face->size )
+ {
+ x_scale = face->size->metrics.x_scale;
+ y_scale = face->size->metrics.y_scale;
+ }
+
+ if ( ametrics_x_scale )
+ *ametrics_x_scale = x_scale;
+
+ if ( ametrics_y_scale )
+ *ametrics_y_scale = y_scale;
+
+ error = FT_THROW( Unknown_File_Format );
+ }
+
+ return error;
+ }
+
+
+ /* documentation is in ftpfr.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_PFR_Kerning( FT_Face face,
+ FT_UInt left,
+ FT_UInt right,
+ FT_Vector *avector )
+ {
+ FT_Error error;
+ FT_Service_PfrMetrics service;
+
+
+ if ( !face )
+ return FT_THROW( Invalid_Face_Handle );
+
+ if ( !avector )
+ return FT_THROW( Invalid_Argument );
+
+ service = ft_pfr_check( face );
+ if ( service )
+ error = service->get_kerning( face, left, right, avector );
+ else
+ error = FT_Get_Kerning( face, left, right,
+ FT_KERNING_UNSCALED, avector );
+
+ return error;
+ }
+
+
+ /* documentation is in ftpfr.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_PFR_Advance( FT_Face face,
+ FT_UInt gindex,
+ FT_Pos *aadvance )
+ {
+ FT_Error error;
+ FT_Service_PfrMetrics service;
+
+
+ if ( !face )
+ return FT_THROW( Invalid_Face_Handle );
+
+ if ( !aadvance )
+ return FT_THROW( Invalid_Argument );
+
+ service = ft_pfr_check( face );
+ if ( service )
+ error = service->get_advance( face, gindex, aadvance );
+ else
+ /* XXX: TODO: PROVIDE ADVANCE-LOADING METHOD TO ALL FONT DRIVERS */
+ error = FT_THROW( Invalid_Argument );
+
+ return error;
+ }
+
+
+/* END */
diff --git a/src/base/ftrfork.c b/src/base/ftrfork.c
index 82d54f8..c30c766 100644
--- a/src/base/ftrfork.c
+++ b/src/base/ftrfork.c
@@ -71,24 +71,35 @@
if ( error )
return error;
- *rdata_pos = rfork_offset + ( ( head[0] << 24 ) |
- ( head[1] << 16 ) |
- ( head[2] << 8 ) |
- head[3] );
- map_pos = rfork_offset + ( ( head[4] << 24 ) |
- ( head[5] << 16 ) |
- ( head[6] << 8 ) |
- head[7] );
- rdata_len = ( head[ 8] << 24 ) |
- ( head[ 9] << 16 ) |
- ( head[10] << 8 ) |
- head[11];
+ /* ensure positive values */
+ if ( head[0] >= 0x80 || head[4] >= 0x80 || head[8] >= 0x80 )
+ return FT_THROW( Unknown_File_Format );
+
+ *rdata_pos = ( head[ 0] << 24 ) |
+ ( head[ 1] << 16 ) |
+ ( head[ 2] << 8 ) |
+ head[ 3];
+ map_pos = ( head[ 4] << 24 ) |
+ ( head[ 5] << 16 ) |
+ ( head[ 6] << 8 ) |
+ head[ 7];
+ rdata_len = ( head[ 8] << 24 ) |
+ ( head[ 9] << 16 ) |
+ ( head[10] << 8 ) |
+ head[11];
/* map_len = head[12] .. head[15] */
- if ( *rdata_pos + rdata_len != map_pos || map_pos == rfork_offset )
+ if ( *rdata_pos != map_pos - rdata_len || map_pos == 0 )
return FT_THROW( Unknown_File_Format );
+ if ( FT_LONG_MAX - rfork_offset < *rdata_pos ||
+ FT_LONG_MAX - rfork_offset < map_pos )
+ return FT_THROW( Unknown_File_Format );
+
+ *rdata_pos += rfork_offset;
+ map_pos += rfork_offset;
+
error = FT_Stream_Seek( stream, (FT_ULong)map_pos );
if ( error )
return error;
diff --git a/src/base/ftstroke.c b/src/base/ftstroke.c
index 842ee30..fecb3cc 100644
--- a/src/base/ftstroke.c
+++ b/src/base/ftstroke.c
@@ -24,6 +24,16 @@
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_OBJECTS_H
+#include "basepic.h"
+
+
+ /* declare an extern to access `ft_outline_glyph_class' globally */
+ /* allocated in `ftglyph.c', and use the FT_OUTLINE_GLYPH_CLASS_GET */
+ /* macro to access it when FT_CONFIG_OPTION_PIC is defined */
+#ifndef FT_CONFIG_OPTION_PIC
+ FT_CALLBACK_TABLE const FT_Glyph_Class ft_outline_glyph_class;
+#endif
+
/* documentation is in ftstroke.h */
@@ -2285,15 +2295,6 @@
}
- /* declare an extern to access `ft_outline_glyph_class' globally */
- /* allocated in `ftglyph.c', and use the FT_OUTLINE_GLYPH_CLASS_GET */
- /* macro to access it when FT_CONFIG_OPTION_PIC is defined */
-#ifndef FT_CONFIG_OPTION_PIC
- extern const FT_Glyph_Class ft_outline_glyph_class;
-#endif
-#include "basepic.h"
-
-
/* documentation is in ftstroke.h */
FT_EXPORT_DEF( FT_Error )
diff --git a/src/cache/ftcache.c b/src/cache/ftcache.c
new file mode 100644
index 0000000..8de527a
--- /dev/null
+++ b/src/cache/ftcache.c
@@ -0,0 +1,31 @@
+/***************************************************************************/
+/* */
+/* ftcache.c */
+/* */
+/* The FreeType Caching sub-system (body only). */
+/* */
+/* Copyright 2000-2015 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+#include "ftcmru.c"
+#include "ftcmanag.c"
+#include "ftccache.c"
+#include "ftccmap.c"
+#include "ftcglyph.c"
+#include "ftcimage.c"
+#include "ftcsbits.c"
+#include "ftcbasic.c"
+
+/* END */
diff --git a/src/cache/ftccache.c b/src/cache/ftccache.c
index d8c5b99..b82a789 100644
--- a/src/cache/ftccache.c
+++ b/src/cache/ftccache.c
@@ -576,7 +576,7 @@
FTC_Node* pnode = bucket;
- for ( ;; )
+ for (;;)
{
FTC_Node node = *pnode;
FT_Bool list_changed = FALSE;
diff --git a/src/cache/ftcerror.h b/src/cache/ftcerror.h
new file mode 100644
index 0000000..15adec5
--- /dev/null
+++ b/src/cache/ftcerror.h
@@ -0,0 +1,41 @@
+/***************************************************************************/
+/* */
+/* ftcerror.h */
+/* */
+/* Caching sub-system error codes (specification only). */
+/* */
+/* Copyright 2001-2015 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file is used to define the caching sub-system error enumeration */
+ /* constants. */
+ /* */
+ /*************************************************************************/
+
+#ifndef __FTCERROR_H__
+#define __FTCERROR_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#undef FT_ERR_PREFIX
+#define FT_ERR_PREFIX FTC_Err_
+#define FT_ERR_BASE FT_Mod_Err_Cache
+
+#include FT_ERRORS_H
+
+#endif /* __FTCERROR_H__ */
+
+/* END */
diff --git a/src/cache/ftcimage.c b/src/cache/ftcimage.c
new file mode 100644
index 0000000..f519a61
--- /dev/null
+++ b/src/cache/ftcimage.c
@@ -0,0 +1,164 @@
+/***************************************************************************/
+/* */
+/* ftcimage.c */
+/* */
+/* FreeType Image cache (body). */
+/* */
+/* Copyright 2000-2015 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_CACHE_H
+#include "ftcimage.h"
+#include FT_INTERNAL_MEMORY_H
+#include FT_INTERNAL_OBJECTS_H
+
+#include "ftccback.h"
+#include "ftcerror.h"
+
+
+ /* finalize a given glyph image node */
+ FT_LOCAL_DEF( void )
+ ftc_inode_free( FTC_Node ftcinode,
+ FTC_Cache cache )
+ {
+ FTC_INode inode = (FTC_INode)ftcinode;
+ FT_Memory memory = cache->memory;
+
+
+ if ( inode->glyph )
+ {
+ FT_Done_Glyph( inode->glyph );
+ inode->glyph = NULL;
+ }
+
+ FTC_GNode_Done( FTC_GNODE( inode ), cache );
+ FT_FREE( inode );
+ }
+
+
+ FT_LOCAL_DEF( void )
+ FTC_INode_Free( FTC_INode inode,
+ FTC_Cache cache )
+ {
+ ftc_inode_free( FTC_NODE( inode ), cache );
+ }
+
+
+ /* initialize a new glyph image node */
+ FT_LOCAL_DEF( FT_Error )
+ FTC_INode_New( FTC_INode *pinode,
+ FTC_GQuery gquery,
+ FTC_Cache cache )
+ {
+ FT_Memory memory = cache->memory;
+ FT_Error error;
+ FTC_INode inode = NULL;
+
+
+ if ( !FT_NEW( inode ) )
+ {
+ FTC_GNode gnode = FTC_GNODE( inode );
+ FTC_Family family = gquery->family;
+ FT_UInt gindex = gquery->gindex;
+ FTC_IFamilyClass clazz = FTC_CACHE__IFAMILY_CLASS( cache );
+
+
+ /* initialize its inner fields */
+ FTC_GNode_Init( gnode, gindex, family );
+
+ /* we will now load the glyph image */
+ error = clazz->family_load_glyph( family, gindex, cache,
+ &inode->glyph );
+ if ( error )
+ {
+ FTC_INode_Free( inode, cache );
+ inode = NULL;
+ }
+ }
+
+ *pinode = inode;
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ ftc_inode_new( FTC_Node *ftcpinode,
+ FT_Pointer ftcgquery,
+ FTC_Cache cache )
+ {
+ FTC_INode *pinode = (FTC_INode*)ftcpinode;
+ FTC_GQuery gquery = (FTC_GQuery)ftcgquery;
+
+
+ return FTC_INode_New( pinode, gquery, cache );
+ }
+
+
+ FT_LOCAL_DEF( FT_Offset )
+ ftc_inode_weight( FTC_Node ftcinode,
+ FTC_Cache ftccache )
+ {
+ FTC_INode inode = (FTC_INode)ftcinode;
+ FT_Offset size = 0;
+ FT_Glyph glyph = inode->glyph;
+
+ FT_UNUSED( ftccache );
+
+
+ switch ( glyph->format )
+ {
+ case FT_GLYPH_FORMAT_BITMAP:
+ {
+ FT_BitmapGlyph bitg;
+
+
+ bitg = (FT_BitmapGlyph)glyph;
+ size = bitg->bitmap.rows * (FT_Offset)FT_ABS( bitg->bitmap.pitch ) +
+ sizeof ( *bitg );
+ }
+ break;
+
+ case FT_GLYPH_FORMAT_OUTLINE:
+ {
+ FT_OutlineGlyph outg;
+
+
+ outg = (FT_OutlineGlyph)glyph;
+ size = (FT_Offset)outg->outline.n_points *
+ ( sizeof ( FT_Vector ) + sizeof ( FT_Byte ) ) +
+ (FT_Offset)outg->outline.n_contours * sizeof ( FT_Short ) +
+ sizeof ( *outg );
+ }
+ break;
+
+ default:
+ ;
+ }
+
+ size += sizeof ( *inode );
+ return size;
+ }
+
+
+#if 0
+
+ FT_LOCAL_DEF( FT_Offset )
+ FTC_INode_Weight( FTC_INode inode )
+ {
+ return ftc_inode_weight( FTC_NODE( inode ), NULL );
+ }
+
+#endif /* 0 */
+
+
+/* END */
diff --git a/src/cache/ftcimage.h b/src/cache/ftcimage.h
new file mode 100644
index 0000000..b312eaa
--- /dev/null
+++ b/src/cache/ftcimage.h
@@ -0,0 +1,107 @@
+/***************************************************************************/
+/* */
+/* ftcimage.h */
+/* */
+/* FreeType Generic Image cache (specification) */
+/* */
+/* Copyright 2000-2015 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*
+ * FTC_ICache is an _abstract_ cache used to store a single FT_Glyph
+ * image per cache node.
+ *
+ * FTC_ICache extends FTC_GCache. For an implementation example,
+ * see FTC_ImageCache in `src/cache/ftbasic.c'.
+ */
+
+
+ /*************************************************************************/
+ /* */
+ /* Each image cache really manages FT_Glyph objects. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef __FTCIMAGE_H__
+#define __FTCIMAGE_H__
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include "ftcglyph.h"
+
+FT_BEGIN_HEADER
+
+
+ /* the FT_Glyph image node type - we store only 1 glyph per node */
+ typedef struct FTC_INodeRec_
+ {
+ FTC_GNodeRec gnode;
+ FT_Glyph glyph;
+
+ } FTC_INodeRec, *FTC_INode;
+
+#define FTC_INODE( x ) ( (FTC_INode)( x ) )
+#define FTC_INODE_GINDEX( x ) FTC_GNODE(x)->gindex
+#define FTC_INODE_FAMILY( x ) FTC_GNODE(x)->family
+
+ typedef FT_Error
+ (*FTC_IFamily_LoadGlyphFunc)( FTC_Family family,
+ FT_UInt gindex,
+ FTC_Cache cache,
+ FT_Glyph *aglyph );
+
+ typedef struct FTC_IFamilyClassRec_
+ {
+ FTC_MruListClassRec clazz;
+ FTC_IFamily_LoadGlyphFunc family_load_glyph;
+
+ } FTC_IFamilyClassRec;
+
+ typedef const FTC_IFamilyClassRec* FTC_IFamilyClass;
+
+#define FTC_IFAMILY_CLASS( x ) ((FTC_IFamilyClass)(x))
+
+#define FTC_CACHE__IFAMILY_CLASS( x ) \
+ FTC_IFAMILY_CLASS( FTC_CACHE__GCACHE_CLASS(x)->family_class )
+
+
+ /* can be used as a @FTC_Node_FreeFunc */
+ FT_LOCAL( void )
+ FTC_INode_Free( FTC_INode inode,
+ FTC_Cache cache );
+
+ /* Can be used as @FTC_Node_NewFunc. `gquery.index' and `gquery.family'
+ * must be set correctly. This function will call the `family_load_glyph'
+ * method to load the FT_Glyph into the cache node.
+ */
+ FT_LOCAL( FT_Error )
+ FTC_INode_New( FTC_INode *pinode,
+ FTC_GQuery gquery,
+ FTC_Cache cache );
+
+#if 0
+ /* can be used as @FTC_Node_WeightFunc */
+ FT_LOCAL( FT_ULong )
+ FTC_INode_Weight( FTC_INode inode );
+#endif
+
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __FTCIMAGE_H__ */
+
+
+/* END */
diff --git a/src/cache/ftcmanag.c b/src/cache/ftcmanag.c
new file mode 100644
index 0000000..658614c
--- /dev/null
+++ b/src/cache/ftcmanag.c
@@ -0,0 +1,703 @@
+/***************************************************************************/
+/* */
+/* ftcmanag.c */
+/* */
+/* FreeType Cache Manager (body). */
+/* */
+/* Copyright 2000-2015 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_CACHE_H
+#include "ftcmanag.h"
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_SIZES_H
+
+#include "ftccback.h"
+#include "ftcerror.h"
+
+#ifdef FT_CONFIG_OPTION_PIC
+#error "cache system does not support PIC yet"
+#endif
+
+
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_cache
+
+
+ static FT_Error
+ ftc_scaler_lookup_size( FTC_Manager manager,
+ FTC_Scaler scaler,
+ FT_Size *asize )
+ {
+ FT_Face face;
+ FT_Size size = NULL;
+ FT_Error error;
+
+
+ error = FTC_Manager_LookupFace( manager, scaler->face_id, &face );
+ if ( error )
+ goto Exit;
+
+ error = FT_New_Size( face, &size );
+ if ( error )
+ goto Exit;
+
+ FT_Activate_Size( size );
+
+ if ( scaler->pixel )
+ error = FT_Set_Pixel_Sizes( face, scaler->width, scaler->height );
+ else
+ error = FT_Set_Char_Size( face,
+ (FT_F26Dot6)scaler->width,
+ (FT_F26Dot6)scaler->height,
+ scaler->x_res,
+ scaler->y_res );
+ if ( error )
+ {
+ FT_Done_Size( size );
+ size = NULL;
+ }
+
+ Exit:
+ *asize = size;
+ return error;
+ }
+
+
+ typedef struct FTC_SizeNodeRec_
+ {
+ FTC_MruNodeRec node;
+ FT_Size size;
+ FTC_ScalerRec scaler;
+
+ } FTC_SizeNodeRec, *FTC_SizeNode;
+
+#define FTC_SIZE_NODE( x ) ( (FTC_SizeNode)( x ) )
+
+
+ FT_CALLBACK_DEF( void )
+ ftc_size_node_done( FTC_MruNode ftcnode,
+ FT_Pointer data )
+ {
+ FTC_SizeNode node = (FTC_SizeNode)ftcnode;
+ FT_Size size = node->size;
+ FT_UNUSED( data );
+
+
+ if ( size )
+ FT_Done_Size( size );
+ }
+
+
+ FT_CALLBACK_DEF( FT_Bool )
+ ftc_size_node_compare( FTC_MruNode ftcnode,
+ FT_Pointer ftcscaler )
+ {
+ FTC_SizeNode node = (FTC_SizeNode)ftcnode;
+ FTC_Scaler scaler = (FTC_Scaler)ftcscaler;
+ FTC_Scaler scaler0 = &node->scaler;
+
+
+ if ( FTC_SCALER_COMPARE( scaler0, scaler ) )
+ {
+ FT_Activate_Size( node->size );
+ return 1;
+ }
+ return 0;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ ftc_size_node_init( FTC_MruNode ftcnode,
+ FT_Pointer ftcscaler,
+ FT_Pointer ftcmanager )
+ {
+ FTC_SizeNode node = (FTC_SizeNode)ftcnode;
+ FTC_Scaler scaler = (FTC_Scaler)ftcscaler;
+ FTC_Manager manager = (FTC_Manager)ftcmanager;
+
+
+ node->scaler = scaler[0];
+
+ return ftc_scaler_lookup_size( manager, scaler, &node->size );
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ ftc_size_node_reset( FTC_MruNode ftcnode,
+ FT_Pointer ftcscaler,
+ FT_Pointer ftcmanager )
+ {
+ FTC_SizeNode node = (FTC_SizeNode)ftcnode;
+ FTC_Scaler scaler = (FTC_Scaler)ftcscaler;
+ FTC_Manager manager = (FTC_Manager)ftcmanager;
+
+
+ FT_Done_Size( node->size );
+
+ node->scaler = scaler[0];
+
+ return ftc_scaler_lookup_size( manager, scaler, &node->size );
+ }
+
+
+ static
+ const FTC_MruListClassRec ftc_size_list_class =
+ {
+ sizeof ( FTC_SizeNodeRec ),
+ ftc_size_node_compare,
+ ftc_size_node_init,
+ ftc_size_node_reset,
+ ftc_size_node_done
+ };
+
+
+ /* helper function used by ftc_face_node_done */
+ static FT_Bool
+ ftc_size_node_compare_faceid( FTC_MruNode ftcnode,
+ FT_Pointer ftcface_id )
+ {
+ FTC_SizeNode node = (FTC_SizeNode)ftcnode;
+ FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
+
+
+ return FT_BOOL( node->scaler.face_id == face_id );
+ }
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FTC_Manager_LookupSize( FTC_Manager manager,
+ FTC_Scaler scaler,
+ FT_Size *asize )
+ {
+ FT_Error error;
+ FTC_MruNode mrunode;
+
+
+ if ( !asize || !scaler )
+ return FT_THROW( Invalid_Argument );
+
+ *asize = NULL;
+
+ if ( !manager )
+ return FT_THROW( Invalid_Cache_Handle );
+
+#ifdef FTC_INLINE
+
+ FTC_MRULIST_LOOKUP_CMP( &manager->sizes, scaler, ftc_size_node_compare,
+ mrunode, error );
+
+#else
+ error = FTC_MruList_Lookup( &manager->sizes, scaler, &mrunode );
+#endif
+
+ if ( !error )
+ *asize = FTC_SIZE_NODE( mrunode )->size;
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** FACE MRU IMPLEMENTATION *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ typedef struct FTC_FaceNodeRec_
+ {
+ FTC_MruNodeRec node;
+ FTC_FaceID face_id;
+ FT_Face face;
+
+ } FTC_FaceNodeRec, *FTC_FaceNode;
+
+#define FTC_FACE_NODE( x ) ( ( FTC_FaceNode )( x ) )
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ ftc_face_node_init( FTC_MruNode ftcnode,
+ FT_Pointer ftcface_id,
+ FT_Pointer ftcmanager )
+ {
+ FTC_FaceNode node = (FTC_FaceNode)ftcnode;
+ FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
+ FTC_Manager manager = (FTC_Manager)ftcmanager;
+ FT_Error error;
+
+
+ node->face_id = face_id;
+
+ error = manager->request_face( face_id,
+ manager->library,
+ manager->request_data,
+ &node->face );
+ if ( !error )
+ {
+ /* destroy initial size object; it will be re-created later */
+ if ( node->face->size )
+ FT_Done_Size( node->face->size );
+ }
+
+ return error;
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ ftc_face_node_done( FTC_MruNode ftcnode,
+ FT_Pointer ftcmanager )
+ {
+ FTC_FaceNode node = (FTC_FaceNode)ftcnode;
+ FTC_Manager manager = (FTC_Manager)ftcmanager;
+
+
+ /* we must begin by removing all scalers for the target face */
+ /* from the manager's list */
+ FTC_MruList_RemoveSelection( &manager->sizes,
+ ftc_size_node_compare_faceid,
+ node->face_id );
+
+ /* all right, we can discard the face now */
+ FT_Done_Face( node->face );
+ node->face = NULL;
+ node->face_id = NULL;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Bool )
+ ftc_face_node_compare( FTC_MruNode ftcnode,
+ FT_Pointer ftcface_id )
+ {
+ FTC_FaceNode node = (FTC_FaceNode)ftcnode;
+ FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
+
+
+ return FT_BOOL( node->face_id == face_id );
+ }
+
+
+ static
+ const FTC_MruListClassRec ftc_face_list_class =
+ {
+ sizeof ( FTC_FaceNodeRec),
+
+ ftc_face_node_compare,
+ ftc_face_node_init,
+ 0, /* FTC_MruNode_ResetFunc */
+ ftc_face_node_done
+ };
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FTC_Manager_LookupFace( FTC_Manager manager,
+ FTC_FaceID face_id,
+ FT_Face *aface )
+ {
+ FT_Error error;
+ FTC_MruNode mrunode;
+
+
+ if ( !aface || !face_id )
+ return FT_THROW( Invalid_Argument );
+
+ *aface = NULL;
+
+ if ( !manager )
+ return FT_THROW( Invalid_Cache_Handle );
+
+ /* we break encapsulation for the sake of speed */
+#ifdef FTC_INLINE
+
+ FTC_MRULIST_LOOKUP_CMP( &manager->faces, face_id, ftc_face_node_compare,
+ mrunode, error );
+
+#else
+ error = FTC_MruList_Lookup( &manager->faces, face_id, &mrunode );
+#endif
+
+ if ( !error )
+ *aface = FTC_FACE_NODE( mrunode )->face;
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** CACHE MANAGER ROUTINES *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FTC_Manager_New( FT_Library library,
+ FT_UInt max_faces,
+ FT_UInt max_sizes,
+ FT_ULong max_bytes,
+ FTC_Face_Requester requester,
+ FT_Pointer req_data,
+ FTC_Manager *amanager )
+ {
+ FT_Error error;
+ FT_Memory memory;
+ FTC_Manager manager = 0;
+
+
+ if ( !library )
+ return FT_THROW( Invalid_Library_Handle );
+
+ if ( !amanager || !requester )
+ return FT_THROW( Invalid_Argument );
+
+ memory = library->memory;
+
+ if ( FT_NEW( manager ) )
+ goto Exit;
+
+ if ( max_faces == 0 )
+ max_faces = FTC_MAX_FACES_DEFAULT;
+
+ if ( max_sizes == 0 )
+ max_sizes = FTC_MAX_SIZES_DEFAULT;
+
+ if ( max_bytes == 0 )
+ max_bytes = FTC_MAX_BYTES_DEFAULT;
+
+ manager->library = library;
+ manager->memory = memory;
+ manager->max_weight = max_bytes;
+
+ manager->request_face = requester;
+ manager->request_data = req_data;
+
+ FTC_MruList_Init( &manager->faces,
+ &ftc_face_list_class,
+ max_faces,
+ manager,
+ memory );
+
+ FTC_MruList_Init( &manager->sizes,
+ &ftc_size_list_class,
+ max_sizes,
+ manager,
+ memory );
+
+ *amanager = manager;
+
+ Exit:
+ return error;
+ }
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( void )
+ FTC_Manager_Done( FTC_Manager manager )
+ {
+ FT_Memory memory;
+ FT_UInt idx;
+
+
+ if ( !manager || !manager->library )
+ return;
+
+ memory = manager->memory;
+
+ /* now discard all caches */
+ for (idx = manager->num_caches; idx-- > 0; )
+ {
+ FTC_Cache cache = manager->caches[idx];
+
+
+ if ( cache )
+ {
+ cache->clazz.cache_done( cache );
+ FT_FREE( cache );
+ manager->caches[idx] = NULL;
+ }
+ }
+ manager->num_caches = 0;
+
+ /* discard faces and sizes */
+ FTC_MruList_Done( &manager->sizes );
+ FTC_MruList_Done( &manager->faces );
+
+ manager->library = NULL;
+ manager->memory = NULL;
+
+ FT_FREE( manager );
+ }
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( void )
+ FTC_Manager_Reset( FTC_Manager manager )
+ {
+ if ( !manager )
+ return;
+
+ FTC_MruList_Reset( &manager->sizes );
+ FTC_MruList_Reset( &manager->faces );
+
+ FTC_Manager_FlushN( manager, manager->num_nodes );
+ }
+
+
+#ifdef FT_DEBUG_ERROR
+
+ static void
+ FTC_Manager_Check( FTC_Manager manager )
+ {
+ FTC_Node node, first;
+
+
+ first = manager->nodes_list;
+
+ /* check node weights */
+ if ( first )
+ {
+ FT_Offset weight = 0;
+
+
+ node = first;
+
+ do
+ {
+ FTC_Cache cache = manager->caches[node->cache_index];
+
+
+ if ( (FT_UInt)node->cache_index >= manager->num_caches )
+ FT_TRACE0(( "FTC_Manager_Check: invalid node (cache index = %ld\n",
+ node->cache_index ));
+ else
+ weight += cache->clazz.node_weight( node, cache );
+
+ node = FTC_NODE__NEXT( node );
+
+ } while ( node != first );
+
+ if ( weight != manager->cur_weight )
+ FT_TRACE0(( "FTC_Manager_Check: invalid weight %ld instead of %ld\n",
+ manager->cur_weight, weight ));
+ }
+
+ /* check circular list */
+ if ( first )
+ {
+ FT_UFast count = 0;
+
+
+ node = first;
+ do
+ {
+ count++;
+ node = FTC_NODE__NEXT( node );
+
+ } while ( node != first );
+
+ if ( count != manager->num_nodes )
+ FT_TRACE0(( "FTC_Manager_Check:"
+ " invalid cache node count %d instead of %d\n",
+ manager->num_nodes, count ));
+ }
+ }
+
+#endif /* FT_DEBUG_ERROR */
+
+
+ /* `Compress' the manager's data, i.e., get rid of old cache nodes */
+ /* that are not referenced anymore in order to limit the total */
+ /* memory used by the cache. */
+
+ /* documentation is in ftcmanag.h */
+
+ FT_LOCAL_DEF( void )
+ FTC_Manager_Compress( FTC_Manager manager )
+ {
+ FTC_Node node, first;
+
+
+ if ( !manager )
+ return;
+
+ first = manager->nodes_list;
+
+#ifdef FT_DEBUG_ERROR
+ FTC_Manager_Check( manager );
+
+ FT_TRACE0(( "compressing, weight = %ld, max = %ld, nodes = %d\n",
+ manager->cur_weight, manager->max_weight,
+ manager->num_nodes ));
+#endif
+
+ if ( manager->cur_weight < manager->max_weight || first == NULL )
+ return;
+
+ /* go to last node -- it's a circular list */
+ node = FTC_NODE__PREV( first );
+ do
+ {
+ FTC_Node prev;
+
+
+ prev = ( node == first ) ? NULL : FTC_NODE__PREV( node );
+
+ if ( node->ref_count <= 0 )
+ ftc_node_destroy( node, manager );
+
+ node = prev;
+
+ } while ( node && manager->cur_weight > manager->max_weight );
+ }
+
+
+ /* documentation is in ftcmanag.h */
+
+ FT_LOCAL_DEF( FT_Error )
+ FTC_Manager_RegisterCache( FTC_Manager manager,
+ FTC_CacheClass clazz,
+ FTC_Cache *acache )
+ {
+ FT_Error error = FT_ERR( Invalid_Argument );
+ FTC_Cache cache = NULL;
+
+
+ if ( manager && clazz && acache )
+ {
+ FT_Memory memory = manager->memory;
+
+
+ if ( manager->num_caches >= FTC_MAX_CACHES )
+ {
+ error = FT_THROW( Too_Many_Caches );
+ FT_ERROR(( "FTC_Manager_RegisterCache:"
+ " too many registered caches\n" ));
+ goto Exit;
+ }
+
+ if ( !FT_ALLOC( cache, clazz->cache_size ) )
+ {
+ cache->manager = manager;
+ cache->memory = memory;
+ cache->clazz = clazz[0];
+ cache->org_class = clazz;
+
+ /* THIS IS VERY IMPORTANT! IT WILL WRETCH THE MANAGER */
+ /* IF IT IS NOT SET CORRECTLY */
+ cache->index = manager->num_caches;
+
+ error = clazz->cache_init( cache );
+ if ( error )
+ {
+ clazz->cache_done( cache );
+ FT_FREE( cache );
+ goto Exit;
+ }
+
+ manager->caches[manager->num_caches++] = cache;
+ }
+ }
+
+ Exit:
+ if ( acache )
+ *acache = cache;
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_UInt )
+ FTC_Manager_FlushN( FTC_Manager manager,
+ FT_UInt count )
+ {
+ FTC_Node first = manager->nodes_list;
+ FTC_Node node;
+ FT_UInt result;
+
+
+ /* try to remove `count' nodes from the list */
+ if ( first == NULL ) /* empty list! */
+ return 0;
+
+ /* go to last node - it's a circular list */
+ node = FTC_NODE__PREV(first);
+ for ( result = 0; result < count; )
+ {
+ FTC_Node prev = FTC_NODE__PREV( node );
+
+
+ /* don't touch locked nodes */
+ if ( node->ref_count <= 0 )
+ {
+ ftc_node_destroy( node, manager );
+ result++;
+ }
+
+ if ( node == first )
+ break;
+
+ node = prev;
+ }
+ return result;
+ }
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( void )
+ FTC_Manager_RemoveFaceID( FTC_Manager manager,
+ FTC_FaceID face_id )
+ {
+ FT_UInt nn;
+
+
+ if ( !manager || !face_id )
+ return;
+
+ /* this will remove all FTC_SizeNode that correspond to
+ * the face_id as well
+ */
+ FTC_MruList_RemoveSelection( &manager->faces,
+ ftc_face_node_compare,
+ face_id );
+
+ for ( nn = 0; nn < manager->num_caches; nn++ )
+ FTC_Cache_RemoveFaceID( manager->caches[nn], face_id );
+ }
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( void )
+ FTC_Node_Unref( FTC_Node node,
+ FTC_Manager manager )
+ {
+ if ( node &&
+ manager &&
+ (FT_UInt)node->cache_index < manager->num_caches )
+ node->ref_count--;
+ }
+
+
+/* END */
diff --git a/src/cache/ftcmru.h b/src/cache/ftcmru.h
new file mode 100644
index 0000000..c0c35f9
--- /dev/null
+++ b/src/cache/ftcmru.h
@@ -0,0 +1,246 @@
+/***************************************************************************/
+/* */
+/* ftcmru.h */
+/* */
+/* Simple MRU list-cache (specification). */
+/* */
+/* Copyright 2000-2015 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* An MRU is a list that cannot hold more than a certain number of */
+ /* elements (`max_elements'). All elements in the list are sorted in */
+ /* least-recently-used order, i.e., the `oldest' element is at the tail */
+ /* of the list. */
+ /* */
+ /* When doing a lookup (either through `Lookup()' or `Lookup_Node()'), */
+ /* the list is searched for an element with the corresponding key. If */
+ /* it is found, the element is moved to the head of the list and is */
+ /* returned. */
+ /* */
+ /* If no corresponding element is found, the lookup routine will try to */
+ /* obtain a new element with the relevant key. If the list is already */
+ /* full, the oldest element from the list is discarded and replaced by a */
+ /* new one; a new element is added to the list otherwise. */
+ /* */
+ /* Note that it is possible to pre-allocate the element list nodes. */
+ /* This is handy if `max_elements' is sufficiently small, as it saves */
+ /* allocations/releases during the lookup process. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef __FTCMRU_H__
+#define __FTCMRU_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+#define xxFT_DEBUG_ERROR
+#define FTC_INLINE
+
+FT_BEGIN_HEADER
+
+ typedef struct FTC_MruNodeRec_* FTC_MruNode;
+
+ typedef struct FTC_MruNodeRec_
+ {
+ FTC_MruNode next;
+ FTC_MruNode prev;
+
+ } FTC_MruNodeRec;
+
+
+ FT_LOCAL( void )
+ FTC_MruNode_Prepend( FTC_MruNode *plist,
+ FTC_MruNode node );
+
+ FT_LOCAL( void )
+ FTC_MruNode_Up( FTC_MruNode *plist,
+ FTC_MruNode node );
+
+ FT_LOCAL( void )
+ FTC_MruNode_Remove( FTC_MruNode *plist,
+ FTC_MruNode node );
+
+
+ typedef struct FTC_MruListRec_* FTC_MruList;
+
+ typedef struct FTC_MruListClassRec_ const * FTC_MruListClass;
+
+
+ typedef FT_Bool
+ (*FTC_MruNode_CompareFunc)( FTC_MruNode node,
+ FT_Pointer key );
+
+ typedef FT_Error
+ (*FTC_MruNode_InitFunc)( FTC_MruNode node,
+ FT_Pointer key,
+ FT_Pointer data );
+
+ typedef FT_Error
+ (*FTC_MruNode_ResetFunc)( FTC_MruNode node,
+ FT_Pointer key,
+ FT_Pointer data );
+
+ typedef void
+ (*FTC_MruNode_DoneFunc)( FTC_MruNode node,
+ FT_Pointer data );
+
+
+ typedef struct FTC_MruListClassRec_
+ {
+ FT_Offset node_size;
+ FTC_MruNode_CompareFunc node_compare;
+ FTC_MruNode_InitFunc node_init;
+ FTC_MruNode_ResetFunc node_reset;
+ FTC_MruNode_DoneFunc node_done;
+
+ } FTC_MruListClassRec;
+
+ typedef struct FTC_MruListRec_
+ {
+ FT_UInt num_nodes;
+ FT_UInt max_nodes;
+ FTC_MruNode nodes;
+ FT_Pointer data;
+ FTC_MruListClassRec clazz;
+ FT_Memory memory;
+
+ } FTC_MruListRec;
+
+
+ FT_LOCAL( void )
+ FTC_MruList_Init( FTC_MruList list,
+ FTC_MruListClass clazz,
+ FT_UInt max_nodes,
+ FT_Pointer data,
+ FT_Memory memory );
+
+ FT_LOCAL( void )
+ FTC_MruList_Reset( FTC_MruList list );
+
+
+ FT_LOCAL( void )
+ FTC_MruList_Done( FTC_MruList list );
+
+
+ FT_LOCAL( FT_Error )
+ FTC_MruList_New( FTC_MruList list,
+ FT_Pointer key,
+ FTC_MruNode *anode );
+
+ FT_LOCAL( void )
+ FTC_MruList_Remove( FTC_MruList list,
+ FTC_MruNode node );
+
+ FT_LOCAL( void )
+ FTC_MruList_RemoveSelection( FTC_MruList list,
+ FTC_MruNode_CompareFunc selection,
+ FT_Pointer key );
+
+
+#ifdef FTC_INLINE
+
+#define FTC_MRULIST_LOOKUP_CMP( list, key, compare, node, error ) \
+ FT_BEGIN_STMNT \
+ FTC_MruNode* _pfirst = &(list)->nodes; \
+ FTC_MruNode_CompareFunc _compare = (FTC_MruNode_CompareFunc)(compare); \
+ FTC_MruNode _first, _node; \
+ \
+ \
+ error = FT_Err_Ok; \
+ _first = *(_pfirst); \
+ _node = NULL; \
+ \
+ if ( _first ) \
+ { \
+ _node = _first; \
+ do \
+ { \
+ if ( _compare( _node, (key) ) ) \
+ { \
+ if ( _node != _first ) \
+ FTC_MruNode_Up( _pfirst, _node ); \
+ \
+ node = _node; \
+ goto _MruOk; \
+ } \
+ _node = _node->next; \
+ \
+ } while ( _node != _first) ; \
+ } \
+ \
+ error = FTC_MruList_New( (list), (key), (FTC_MruNode*)(void*)&(node) ); \
+ _MruOk: \
+ ; \
+ FT_END_STMNT
+
+#define FTC_MRULIST_LOOKUP( list, key, node, error ) \
+ FTC_MRULIST_LOOKUP_CMP( list, key, (list)->clazz.node_compare, node, error )
+
+#else /* !FTC_INLINE */
+
+ FT_LOCAL( FTC_MruNode )
+ FTC_MruList_Find( FTC_MruList list,
+ FT_Pointer key );
+
+ FT_LOCAL( FT_Error )
+ FTC_MruList_Lookup( FTC_MruList list,
+ FT_Pointer key,
+ FTC_MruNode *pnode );
+
+#define FTC_MRULIST_LOOKUP( list, key, node, error ) \
+ error = FTC_MruList_Lookup( (list), (key), (FTC_MruNode*)&(node) )
+
+#endif /* !FTC_INLINE */
+
+
+#define FTC_MRULIST_LOOP( list, node ) \
+ FT_BEGIN_STMNT \
+ FTC_MruNode _first = (list)->nodes; \
+ \
+ \
+ if ( _first ) \
+ { \
+ FTC_MruNode _node = _first; \
+ \
+ \
+ do \
+ { \
+ *(FTC_MruNode*)&(node) = _node;
+
+
+#define FTC_MRULIST_LOOP_END() \
+ _node = _node->next; \
+ \
+ } while ( _node != _first ); \
+ } \
+ FT_END_STMNT
+
+ /* */
+
+FT_END_HEADER
+
+
+#endif /* __FTCMRU_H__ */
+
+
+/* END */
diff --git a/src/cff/cf2arrst.c b/src/cff/cf2arrst.c
index 528b1fa..89f3e9f 100644
--- a/src/cff/cf2arrst.c
+++ b/src/cff/cf2arrst.c
@@ -104,7 +104,7 @@
size_t newSize = numElements * arrstack->sizeItem;
- if ( numElements > LONG_MAX / arrstack->sizeItem )
+ if ( numElements > FT_LONG_MAX / arrstack->sizeItem )
goto exit;
diff --git a/src/cff/cf2ft.c b/src/cff/cf2ft.c
index d2544a2..55f3206 100644
--- a/src/cff/cf2ft.c
+++ b/src/cff/cf2ft.c
@@ -544,14 +544,17 @@
/* return 0 on success */
FT_LOCAL_DEF( CF2_Int )
cf2_initGlobalRegionBuffer( CFF_Decoder* decoder,
- CF2_UInt idx,
+ CF2_Int subrNum,
CF2_Buffer buf )
{
+ CF2_UInt idx;
+
+
FT_ASSERT( decoder );
FT_ZERO( buf );
- idx += (CF2_UInt)decoder->globals_bias;
+ idx = (CF2_UInt)( subrNum + decoder->globals_bias );
if ( idx >= decoder->num_globals )
return TRUE; /* error */
@@ -628,14 +631,17 @@
FT_LOCAL_DEF( CF2_Int )
cf2_initLocalRegionBuffer( CFF_Decoder* decoder,
- CF2_UInt idx,
+ CF2_Int subrNum,
CF2_Buffer buf )
{
+ CF2_UInt idx;
+
+
FT_ASSERT( decoder );
FT_ZERO( buf );
- idx += (CF2_UInt)decoder->locals_bias;
+ idx = (CF2_UInt)( subrNum + decoder->locals_bias );
if ( idx >= decoder->num_locals )
return TRUE; /* error */
diff --git a/src/cff/cf2ft.h b/src/cff/cf2ft.h
index 3073df3..9810511 100644
--- a/src/cff/cf2ft.h
+++ b/src/cff/cf2ft.h
@@ -99,7 +99,7 @@ FT_BEGIN_HEADER
FT_LOCAL( CF2_Int )
cf2_initGlobalRegionBuffer( CFF_Decoder* decoder,
- CF2_UInt idx,
+ CF2_Int subrNum,
CF2_Buffer buf );
FT_LOCAL( FT_Error )
cf2_getSeacComponent( CFF_Decoder* decoder,
@@ -110,7 +110,7 @@ FT_BEGIN_HEADER
CF2_Buffer buf );
FT_LOCAL( CF2_Int )
cf2_initLocalRegionBuffer( CFF_Decoder* decoder,
- CF2_UInt idx,
+ CF2_Int subrNum,
CF2_Buffer buf );
FT_LOCAL( CF2_Fixed )
diff --git a/src/cff/cf2hints.c b/src/cff/cf2hints.c
index 0e27000..bbbe8e3 100644
--- a/src/cff/cf2hints.c
+++ b/src/cff/cf2hints.c
@@ -587,8 +587,9 @@
}
/* paired edges must be in proper order */
- FT_ASSERT( !isPair ||
- topHintEdge->csCoord >= bottomHintEdge->csCoord );
+ if ( isPair &&
+ topHintEdge->csCoord < bottomHintEdge->csCoord )
+ return;
/* linear search to find index value of insertion point */
indexInsert = 0;
diff --git a/src/cff/cf2intrp.c b/src/cff/cf2intrp.c
index 537e060..1910f1b 100644
--- a/src/cff/cf2intrp.c
+++ b/src/cff/cf2intrp.c
@@ -184,7 +184,7 @@
return;
FT_ASSERT( hintmask->byteCount > 0 );
- FT_ASSERT( hintmask->byteCount <
+ FT_ASSERT( hintmask->byteCount <=
sizeof ( hintmask->mask ) / sizeof ( hintmask->mask[0] ) );
/* set mask to all ones */
@@ -746,7 +746,7 @@
case cf2_cmdCALLGSUBR:
case cf2_cmdCALLSUBR:
{
- CF2_UInt subrIndex;
+ CF2_Int subrNum;
FT_TRACE4(( op1 == cf2_cmdCALLGSUBR ? " callgsubr"
@@ -766,17 +766,17 @@
(size_t)charstringIndex + 1 );
/* set up the new CFF region and pointer */
- subrIndex = (CF2_UInt)cf2_stack_popInt( opStack );
+ subrNum = cf2_stack_popInt( opStack );
switch ( op1 )
{
case cf2_cmdCALLGSUBR:
FT_TRACE4(( " (idx %d, entering level %d)\n",
- subrIndex + (CF2_UInt)decoder->globals_bias,
+ subrNum + decoder->globals_bias,
charstringIndex + 1 ));
if ( cf2_initGlobalRegionBuffer( decoder,
- subrIndex,
+ subrNum,
charstring ) )
{
lastError = FT_THROW( Invalid_Glyph_Format );
@@ -787,11 +787,11 @@
default:
/* cf2_cmdCALLSUBR */
FT_TRACE4(( " (idx %d, entering level %d)\n",
- subrIndex + (CF2_UInt)decoder->locals_bias,
+ subrNum + decoder->locals_bias,
charstringIndex + 1 ));
if ( cf2_initLocalRegionBuffer( decoder,
- subrIndex,
+ subrNum,
charstring ) )
{
lastError = FT_THROW( Invalid_Glyph_Format );
@@ -1305,7 +1305,7 @@
/* 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 & ~2;
+ count = count1 & ~2U;
index += count1 - count;
FT_TRACE4(( " vvcurveto\n" ));
@@ -1350,7 +1350,7 @@
/* 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 & ~2;
+ count = count1 & ~2U;
index += count1 - count;
FT_TRACE4(( " hhcurveto\n" ));
@@ -1399,7 +1399,7 @@
/* 8n+4, or 8n+5, we enforce it by clearing the */
/* second bit */
/* (and sorting the stack indexing to suit) */
- count = count1 & ~2;
+ count = count1 & ~2U;
index += count1 - count;
FT_TRACE4(( alternate ? " hvcurveto\n" : " vhcurveto\n" ));
diff --git a/src/cff/cffdrivr.c b/src/cff/cffdrivr.c
index a718b7a..9a06b7c 100644
--- a/src/cff/cffdrivr.c
+++ b/src/cff/cffdrivr.c
@@ -358,8 +358,8 @@
FT_DEFINE_SERVICE_GLYPHDICTREC(
cff_service_glyph_dict,
- (FT_GlyphDict_GetNameFunc) cff_get_glyph_name,
- (FT_GlyphDict_NameIndexFunc)cff_get_name_index
+ (FT_GlyphDict_GetNameFunc) cff_get_glyph_name, /* get_name */
+ (FT_GlyphDict_NameIndexFunc)cff_get_name_index /* name_index */
)
@@ -421,11 +421,13 @@
FT_DEFINE_SERVICE_PSINFOREC(
cff_service_ps_info,
- (PS_GetFontInfoFunc) cff_ps_get_font_info,
- (PS_GetFontExtraFunc) NULL,
- (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names,
- (PS_GetFontPrivateFunc)NULL, /* unsupported with CFF fonts */
- (PS_GetFontValueFunc) NULL /* not implemented */
+ (PS_GetFontInfoFunc) cff_ps_get_font_info, /* ps_get_font_info */
+ (PS_GetFontExtraFunc) NULL, /* 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 */
+ /* not implemented */
+ (PS_GetFontValueFunc) NULL /* ps_get_font_value */
)
@@ -444,7 +446,7 @@
/* following the OpenType specification 1.7, we return the name stored */
/* in the `name' table for a CFF wrapped into an SFNT container */
- if ( sfnt )
+ if ( FT_IS_SFNT( FT_FACE( face ) ) && sfnt )
{
FT_Library library = FT_FACE_LIBRARY( face );
FT_Module sfnt_module = FT_Get_Module( library, "sfnt" );
@@ -464,7 +466,7 @@
FT_DEFINE_SERVICE_PSFONTNAMEREC(
cff_service_ps_name,
- (FT_PsName_GetFunc)cff_get_ps_name
+ (FT_PsName_GetFunc)cff_get_ps_name /* get_ps_font_name */
)
@@ -511,7 +513,7 @@
FT_DEFINE_SERVICE_TTCMAPSREC(
cff_service_get_cmap_info,
- (TT_CMap_Info_GetFunc)cff_get_cmap_info
+ (TT_CMap_Info_GetFunc)cff_get_cmap_info /* get_cmap_info */
)
@@ -641,9 +643,12 @@
FT_DEFINE_SERVICE_CIDREC(
cff_service_cid_info,
- (FT_CID_GetRegistryOrderingSupplementFunc)cff_get_ros,
- (FT_CID_GetIsInternallyCIDKeyedFunc) cff_get_is_cid,
- (FT_CID_GetCIDFromGlyphIndexFunc) cff_get_cid_from_glyph_index
+ (FT_CID_GetRegistryOrderingSupplementFunc)
+ cff_get_ros, /* get_ros */
+ (FT_CID_GetIsInternallyCIDKeyedFunc)
+ cff_get_is_cid, /* get_is_cid */
+ (FT_CID_GetCIDFromGlyphIndexFunc)
+ cff_get_cid_from_glyph_index /* get_cid_from_glyph_index */
)
@@ -776,8 +781,8 @@
FT_DEFINE_SERVICE_PROPERTIESREC(
cff_service_properties,
- (FT_Properties_SetFunc)cff_property_set,
- (FT_Properties_GetFunc)cff_property_get )
+ (FT_Properties_SetFunc)cff_property_set, /* set_property */
+ (FT_Properties_GetFunc)cff_property_get ) /* get_property */
/*************************************************************************/
@@ -865,9 +870,10 @@
FT_DEFINE_DRIVER(
cff_driver_class,
- FT_MODULE_FONT_DRIVER |
- FT_MODULE_DRIVER_SCALABLE |
- FT_MODULE_DRIVER_HAS_HINTER,
+ FT_MODULE_FONT_DRIVER |
+ FT_MODULE_DRIVER_SCALABLE |
+ FT_MODULE_DRIVER_HAS_HINTER |
+ FT_MODULE_DRIVER_HINTS_LIGHTLY,
sizeof ( CFF_DriverRec ),
"cff",
@@ -876,31 +882,29 @@
0, /* module-specific interface */
- cff_driver_init,
- cff_driver_done,
- cff_get_interface,
+ cff_driver_init, /* FT_Module_Constructor module_init */
+ cff_driver_done, /* FT_Module_Destructor module_done */
+ cff_get_interface, /* FT_Module_Requester get_interface */
- /* now the specific driver fields */
sizeof ( TT_FaceRec ),
sizeof ( CFF_SizeRec ),
sizeof ( CFF_GlyphSlotRec ),
- cff_face_init,
- cff_face_done,
- cff_size_init,
- cff_size_done,
- cff_slot_init,
- cff_slot_done,
-
- cff_glyph_load,
+ cff_face_init, /* FT_Face_InitFunc init_face */
+ cff_face_done, /* FT_Face_DoneFunc done_face */
+ cff_size_init, /* FT_Size_InitFunc init_size */
+ cff_size_done, /* FT_Size_DoneFunc done_size */
+ cff_slot_init, /* FT_Slot_InitFunc init_slot */
+ cff_slot_done, /* FT_Slot_DoneFunc done_slot */
- cff_get_kerning,
- 0, /* FT_Face_AttachFunc */
- cff_get_advances,
+ cff_glyph_load, /* FT_Slot_LoadFunc load_glyph */
- cff_size_request,
+ cff_get_kerning, /* FT_Face_GetKerningFunc get_kerning */
+ 0, /* FT_Face_AttachFunc attach_file */
+ cff_get_advances, /* FT_Face_GetAdvancesFunc get_advances */
- CFF_SIZE_SELECT
+ cff_size_request, /* FT_Size_RequestFunc request_size */
+ CFF_SIZE_SELECT /* FT_Size_SelectFunc select_size */
)
diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c
index 43054f8..5f57403 100644
--- a/src/cff/cffgload.c
+++ b/src/cff/cffgload.c
@@ -2949,7 +2949,6 @@
{
FT_BBox cbox;
FT_Glyph_Metrics* metrics = &glyph->root.metrics;
- FT_Vector advance;
FT_Bool has_vertical_info;
@@ -3014,26 +3013,27 @@
glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL;
- if ( !( font_matrix.xx == 0x10000L &&
- font_matrix.yy == 0x10000L &&
- font_matrix.xy == 0 &&
- font_matrix.yx == 0 ) )
+ /* apply the font matrix, if any */
+ if ( font_matrix.xx != 0x10000L || font_matrix.yy != 0x10000L ||
+ font_matrix.xy != 0 || font_matrix.yx != 0 )
+ {
FT_Outline_Transform( &glyph->root.outline, &font_matrix );
- if ( !( font_offset.x == 0 &&
- font_offset.y == 0 ) )
- FT_Outline_Translate( &glyph->root.outline,
- font_offset.x, font_offset.y );
+ metrics->horiAdvance = FT_MulFix( metrics->horiAdvance,
+ font_matrix.xx );
+ metrics->vertAdvance = FT_MulFix( metrics->vertAdvance,
+ font_matrix.yy );
+ }
- advance.x = metrics->horiAdvance;
- advance.y = 0;
- FT_Vector_Transform( &advance, &font_matrix );
- metrics->horiAdvance = advance.x + font_offset.x;
+ if ( font_offset.x || font_offset.y )
+ {
+ FT_Outline_Translate( &glyph->root.outline,
+ font_offset.x,
+ font_offset.y );
- advance.x = 0;
- advance.y = metrics->vertAdvance;
- FT_Vector_Transform( &advance, &font_matrix );
- metrics->vertAdvance = advance.y + font_offset.y;
+ metrics->horiAdvance += font_offset.x;
+ metrics->vertAdvance += font_offset.y;
+ }
if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || force_scaling )
{
@@ -3064,9 +3064,7 @@
metrics->width = cbox.xMax - cbox.xMin;
metrics->height = cbox.yMax - cbox.yMin;
- if ( !face->horizontal.number_Of_HMetrics )
- metrics->horiBearingX = cbox.xMin;
-
+ metrics->horiBearingX = cbox.xMin;
metrics->horiBearingY = cbox.yMax;
if ( has_vertical_info )
diff --git a/src/cff/cffload.c b/src/cff/cffload.c
index fcb7348..c61222d 100644
--- a/src/cff/cffload.c
+++ b/src/cff/cffload.c
@@ -1495,9 +1495,9 @@
if ( pure_cff )
{
/* well, we don't really forget the `disabled' fonts... */
- subfont_index = (FT_UInt)face_index;
+ subfont_index = (FT_UInt)( face_index & 0xFFFF );
- if ( subfont_index >= font->name_index.count )
+ if ( face_index > 0 && subfont_index >= font->name_index.count )
{
FT_ERROR(( "cff_font_load:"
" invalid subfont index for pure CFF font (%d)\n",
diff --git a/src/cff/cffobjs.c b/src/cff/cffobjs.c
index 4a1ef11..d628b68 100644
--- a/src/cff/cffobjs.c
+++ b/src/cff/cffobjs.c
@@ -583,10 +583,15 @@
if ( error )
goto Exit;
+ /* if we are performing a simple font format check, exit immediately */
+ /* (this is here for pure CFF) */
+ if ( face_index < 0 )
+ return FT_Err_Ok;
+
cff->pshinter = pshinter;
cff->psnames = psnames;
- cffface->face_index = face_index;
+ cffface->face_index = face_index & 0xFFFF;
/* Complement the root flags with some interesting information. */
/* Note that this is only necessary for pure CFF and CEF fonts; */
@@ -629,7 +634,7 @@
if ( !dict->has_font_matrix )
dict->units_per_em = pure_cff ? 1000 : face->root.units_per_EM;
- /* Normalize the font matrix so that `matrix->xx' is 1; the */
+ /* Normalize the font matrix so that `matrix->yy' is 1; the */
/* scaling is done with `units_per_em' then (at this point, */
/* it already contains the scaling factor, but without */
/* normalization of the matrix). */
@@ -765,8 +770,9 @@
(FT_Short)( dict->underline_thickness >> 16 );
/* retrieve font family & style name */
- cffface->family_name = cff_index_get_name( cff,
- (FT_UInt)face_index );
+ cffface->family_name = cff_index_get_name(
+ cff,
+ (FT_UInt)( face_index & 0xFFFF ) );
if ( cffface->family_name )
{
char* full = cff_index_get_sid_string( cff,
@@ -1046,7 +1052,7 @@
driver->hinting_engine = FT_CFF_HINTING_ADOBE;
#endif
- driver->no_stem_darkening = FALSE;
+ 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;
diff --git a/src/cff/cffpic.h b/src/cff/cffpic.h
index a29620e..9a221a7 100644
--- a/src/cff/cffpic.h
+++ b/src/cff/cffpic.h
@@ -20,8 +20,6 @@
#define __CFFPIC_H__
-FT_BEGIN_HEADER
-
#include FT_INTERNAL_PIC_H
@@ -49,6 +47,8 @@ FT_BEGIN_HEADER
#include FT_SERVICE_PROPERTIES_H
+FT_BEGIN_HEADER
+
typedef struct CffModulePIC_
{
FT_ServiceDescRec* cff_services;
@@ -96,12 +96,12 @@ FT_BEGIN_HEADER
FT_Error
cff_driver_class_pic_init( FT_Library library );
+FT_END_HEADER
+
#endif /* FT_CONFIG_OPTION_PIC */
/* */
-FT_END_HEADER
-
#endif /* __CFFPIC_H__ */
diff --git a/src/gzip/ftgzip.c b/src/gzip/ftgzip.c
index 879eb88..27c6254 100644
--- a/src/gzip/ftgzip.c
+++ b/src/gzip/ftgzip.c
@@ -377,7 +377,10 @@
size = stream->read( stream, stream->pos, zip->input,
FT_GZIP_BUFFER_SIZE );
if ( size == 0 )
+ {
+ zip->limit = zip->cursor;
return FT_THROW( Invalid_Stream_Operation );
+ }
}
else
{
@@ -386,7 +389,10 @@
size = FT_GZIP_BUFFER_SIZE;
if ( size == 0 )
+ {
+ zip->limit = zip->cursor;
return FT_THROW( Invalid_Stream_Operation );
+ }
FT_MEM_COPY( zip->input, stream->base + stream->pos, size );
}
@@ -433,7 +439,8 @@
}
else if ( err != Z_OK )
{
- error = FT_THROW( Invalid_Stream_Operation );
+ zip->limit = zip->cursor;
+ error = FT_THROW( Invalid_Stream_Operation );
break;
}
}
@@ -557,19 +564,22 @@
stream->descriptor.pointer = NULL;
}
+
+ if ( !stream->read )
+ FT_FREE( stream->base );
}
- static FT_ULong
- ft_gzip_stream_io( FT_Stream stream,
- FT_ULong pos,
- FT_Byte* buffer,
- FT_ULong count )
+ static unsigned long
+ ft_gzip_stream_io( FT_Stream stream,
+ unsigned long offset,
+ unsigned char* buffer,
+ unsigned long count )
{
FT_GZipFile zip = (FT_GZipFile)stream->descriptor.pointer;
- return ft_gzip_file_io( zip, pos, buffer, count );
+ return ft_gzip_file_io( zip, offset, buffer, count );
}
@@ -584,7 +594,7 @@
old_pos = stream->pos;
if ( !FT_Stream_Seek( stream, stream->size - 4 ) )
{
- result = FT_Stream_ReadULong( stream, &error );
+ result = FT_Stream_ReadULongLE( stream, &error );
if ( error )
result = 0;
@@ -681,11 +691,15 @@
}
error = FT_Err_Ok;
}
+
+ if ( zip_size )
+ stream->size = zip_size;
+ else
+ stream->size = 0x7FFFFFFFL; /* don't know the real size! */
}
- stream->size = 0x7FFFFFFFL; /* don't know the real size! */
stream->pos = 0;
- stream->base = 0;
+ stream->base = NULL;
stream->read = ft_gzip_stream_io;
stream->close = ft_gzip_stream_close;
diff --git a/src/pfr/pfrload.c b/src/pfr/pfrload.c
deleted file mode 100644
index ec7311d..0000000
--- a/src/pfr/pfrload.c
+++ /dev/null
@@ -1,941 +0,0 @@
-/***************************************************************************/
-/* */
-/* pfrload.c */
-/* */
-/* FreeType PFR loader (body). */
-/* */
-/* Copyright 2002-2015 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 "pfrload.h"
-#include FT_INTERNAL_DEBUG_H
-#include FT_INTERNAL_STREAM_H
-
-#include "pfrerror.h"
-
-#undef FT_COMPONENT
-#define FT_COMPONENT trace_pfr
-
-
- /*************************************************************************/
- /*************************************************************************/
- /***** *****/
- /***** EXTRA ITEMS *****/
- /***** *****/
- /*************************************************************************/
- /*************************************************************************/
-
-
- FT_LOCAL_DEF( FT_Error )
- pfr_extra_items_skip( FT_Byte* *pp,
- FT_Byte* limit )
- {
- return pfr_extra_items_parse( pp, limit, NULL, NULL );
- }
-
-
- FT_LOCAL_DEF( FT_Error )
- pfr_extra_items_parse( FT_Byte* *pp,
- FT_Byte* limit,
- PFR_ExtraItem item_list,
- FT_Pointer item_data )
- {
- FT_Error error = FT_Err_Ok;
- FT_Byte* p = *pp;
- FT_UInt num_items, item_type, item_size;
-
-
- PFR_CHECK( 1 );
- num_items = PFR_NEXT_BYTE( p );
-
- for ( ; num_items > 0; num_items-- )
- {
- PFR_CHECK( 2 );
- item_size = PFR_NEXT_BYTE( p );
- item_type = PFR_NEXT_BYTE( p );
-
- PFR_CHECK( item_size );
-
- if ( item_list )
- {
- PFR_ExtraItem extra = item_list;
-
-
- for ( extra = item_list; extra->parser != NULL; extra++ )
- {
- if ( extra->type == item_type )
- {
- error = extra->parser( p, p + item_size, item_data );
- if ( error ) goto Exit;
-
- break;
- }
- }
- }
-
- p += item_size;
- }
-
- Exit:
- *pp = p;
- return error;
-
- Too_Short:
- FT_ERROR(( "pfr_extra_items_parse: invalid extra items table\n" ));
- error = FT_THROW( Invalid_Table );
- goto Exit;
- }
-
-
- /*************************************************************************/
- /*************************************************************************/
- /***** *****/
- /***** PFR HEADER *****/
- /***** *****/
- /*************************************************************************/
- /*************************************************************************/
-
- static const FT_Frame_Field pfr_header_fields[] =
- {
-#undef FT_STRUCTURE
-#define FT_STRUCTURE PFR_HeaderRec
-
- FT_FRAME_START( 58 ),
- FT_FRAME_ULONG ( signature ),
- FT_FRAME_USHORT( version ),
- FT_FRAME_USHORT( signature2 ),
- FT_FRAME_USHORT( header_size ),
-
- FT_FRAME_USHORT( log_dir_size ),
- FT_FRAME_USHORT( log_dir_offset ),
-
- FT_FRAME_USHORT( log_font_max_size ),
- FT_FRAME_UOFF3 ( log_font_section_size ),
- FT_FRAME_UOFF3 ( log_font_section_offset ),
-
- FT_FRAME_USHORT( phy_font_max_size ),
- FT_FRAME_UOFF3 ( phy_font_section_size ),
- FT_FRAME_UOFF3 ( phy_font_section_offset ),
-
- FT_FRAME_USHORT( gps_max_size ),
- FT_FRAME_UOFF3 ( gps_section_size ),
- FT_FRAME_UOFF3 ( gps_section_offset ),
-
- FT_FRAME_BYTE ( max_blue_values ),
- FT_FRAME_BYTE ( max_x_orus ),
- FT_FRAME_BYTE ( max_y_orus ),
-
- FT_FRAME_BYTE ( phy_font_max_size_high ),
- FT_FRAME_BYTE ( color_flags ),
-
- FT_FRAME_UOFF3 ( bct_max_size ),
- FT_FRAME_UOFF3 ( bct_set_max_size ),
- FT_FRAME_UOFF3 ( phy_bct_set_max_size ),
-
- FT_FRAME_USHORT( num_phy_fonts ),
- FT_FRAME_BYTE ( max_vert_stem_snap ),
- FT_FRAME_BYTE ( max_horz_stem_snap ),
- FT_FRAME_USHORT( max_chars ),
- FT_FRAME_END
- };
-
-
- FT_LOCAL_DEF( FT_Error )
- pfr_header_load( PFR_Header header,
- FT_Stream stream )
- {
- FT_Error error;
-
-
- /* read header directly */
- if ( !FT_STREAM_SEEK( 0 ) &&
- !FT_STREAM_READ_FIELDS( pfr_header_fields, header ) )
- {
- /* make a few adjustments to the header */
- header->phy_font_max_size +=
- (FT_UInt32)header->phy_font_max_size_high << 16;
- }
-
- return error;
- }
-
-
- FT_LOCAL_DEF( FT_Bool )
- pfr_header_check( PFR_Header header )
- {
- FT_Bool result = 1;
-
-
- /* check signature and header size */
- if ( header->signature != 0x50465230L || /* "PFR0" */
- header->version > 4 ||
- header->header_size < 58 ||
- header->signature2 != 0x0D0A ) /* CR/LF */
- {
- result = 0;
- }
- return result;
- }
-
-
- /***********************************************************************/
- /***********************************************************************/
- /***** *****/
- /***** PFR LOGICAL FONTS *****/
- /***** *****/
- /***********************************************************************/
- /***********************************************************************/
-
-
- FT_LOCAL_DEF( FT_Error )
- pfr_log_font_count( FT_Stream stream,
- FT_UInt32 section_offset,
- FT_Long *acount )
- {
- FT_Error error;
- FT_UInt count;
- FT_UInt result = 0;
-
-
- if ( FT_STREAM_SEEK( section_offset ) || FT_READ_USHORT( count ) )
- goto Exit;
-
- result = count;
-
- Exit:
- *acount = (FT_Long)result;
- return error;
- }
-
-
- FT_LOCAL_DEF( FT_Error )
- pfr_log_font_load( PFR_LogFont log_font,
- FT_Stream stream,
- FT_UInt idx,
- FT_UInt32 section_offset,
- FT_Bool size_increment )
- {
- FT_UInt num_log_fonts;
- FT_UInt flags;
- FT_UInt32 offset;
- FT_UInt32 size;
- FT_Error error;
-
-
- if ( FT_STREAM_SEEK( section_offset ) ||
- FT_READ_USHORT( num_log_fonts ) )
- goto Exit;
-
- if ( idx >= num_log_fonts )
- return FT_THROW( Invalid_Argument );
-
- if ( FT_STREAM_SKIP( idx * 5 ) ||
- FT_READ_USHORT( size ) ||
- FT_READ_UOFF3 ( offset ) )
- goto Exit;
-
- /* save logical font size and offset */
- log_font->size = size;
- log_font->offset = offset;
-
- /* now, check the rest of the table before loading it */
- {
- FT_Byte* p;
- FT_Byte* limit;
- FT_UInt local;
-
-
- if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( size ) )
- goto Exit;
-
- p = stream->cursor;
- limit = p + size;
-
- PFR_CHECK(13);
-
- log_font->matrix[0] = PFR_NEXT_LONG( p );
- log_font->matrix[1] = PFR_NEXT_LONG( p );
- log_font->matrix[2] = PFR_NEXT_LONG( p );
- log_font->matrix[3] = PFR_NEXT_LONG( p );
-
- flags = PFR_NEXT_BYTE( p );
-
- local = 0;
- if ( flags & PFR_LOG_STROKE )
- {
- local++;
- if ( flags & PFR_LOG_2BYTE_STROKE )
- local++;
-
- if ( (flags & PFR_LINE_JOIN_MASK) == PFR_LINE_JOIN_MITER )
- local += 3;
- }
- if ( flags & PFR_LOG_BOLD )
- {
- local++;
- if ( flags & PFR_LOG_2BYTE_BOLD )
- local++;
- }
-
- PFR_CHECK( local );
-
- if ( flags & PFR_LOG_STROKE )
- {
- log_font->stroke_thickness = ( flags & PFR_LOG_2BYTE_STROKE )
- ? PFR_NEXT_SHORT( p )
- : PFR_NEXT_BYTE( p );
-
- if ( ( flags & PFR_LINE_JOIN_MASK ) == PFR_LINE_JOIN_MITER )
- log_font->miter_limit = PFR_NEXT_LONG( p );
- }
-
- if ( flags & PFR_LOG_BOLD )
- {
- log_font->bold_thickness = ( flags & PFR_LOG_2BYTE_BOLD )
- ? PFR_NEXT_SHORT( p )
- : PFR_NEXT_BYTE( p );
- }
-
- if ( flags & PFR_LOG_EXTRA_ITEMS )
- {
- error = pfr_extra_items_skip( &p, limit );
- if (error) goto Fail;
- }
-
- PFR_CHECK(5);
- log_font->phys_size = PFR_NEXT_USHORT( p );
- log_font->phys_offset = PFR_NEXT_ULONG( p );
- if ( size_increment )
- {
- PFR_CHECK( 1 );
- log_font->phys_size += (FT_UInt32)PFR_NEXT_BYTE( p ) << 16;
- }
- }
-
- Fail:
- FT_FRAME_EXIT();
-
- Exit:
- return error;
-
- Too_Short:
- FT_ERROR(( "pfr_log_font_load: invalid logical font table\n" ));
- error = FT_THROW( Invalid_Table );
- goto Fail;
- }
-
-
- /***********************************************************************/
- /***********************************************************************/
- /***** *****/
- /***** PFR PHYSICAL FONTS *****/
- /***** *****/
- /***********************************************************************/
- /***********************************************************************/
-
-
- /* load bitmap strikes lists */
- FT_CALLBACK_DEF( FT_Error )
- pfr_extra_item_load_bitmap_info( FT_Byte* p,
- FT_Byte* limit,
- PFR_PhyFont phy_font )
- {
- FT_Memory memory = phy_font->memory;
- PFR_Strike strike;
- FT_UInt flags0;
- FT_UInt n, count, size1;
- FT_Error error = FT_Err_Ok;
-
-
- PFR_CHECK( 5 );
-
- p += 3; /* skip bctSize */
- flags0 = PFR_NEXT_BYTE( p );
- count = PFR_NEXT_BYTE( p );
-
- /* re-allocate when needed */
- if ( phy_font->num_strikes + count > phy_font->max_strikes )
- {
- FT_UInt new_max = FT_PAD_CEIL( phy_font->num_strikes + count, 4 );
-
-
- if ( FT_RENEW_ARRAY( phy_font->strikes,
- phy_font->num_strikes,
- new_max ) )
- goto Exit;
-
- phy_font->max_strikes = new_max;
- }
-
- size1 = 1 + 1 + 1 + 2 + 2 + 1;
- if ( flags0 & PFR_STRIKE_2BYTE_XPPM )
- size1++;
-
- if ( flags0 & PFR_STRIKE_2BYTE_YPPM )
- size1++;
-
- if ( flags0 & PFR_STRIKE_3BYTE_SIZE )
- size1++;
-
- if ( flags0 & PFR_STRIKE_3BYTE_OFFSET )
- size1++;
-
- if ( flags0 & PFR_STRIKE_2BYTE_COUNT )
- size1++;
-
- strike = phy_font->strikes + phy_font->num_strikes;
-
- PFR_CHECK( count * size1 );
-
- for ( n = 0; n < count; n++, strike++ )
- {
- strike->x_ppm = ( flags0 & PFR_STRIKE_2BYTE_XPPM )
- ? PFR_NEXT_USHORT( p )
- : PFR_NEXT_BYTE( p );
-
- strike->y_ppm = ( flags0 & PFR_STRIKE_2BYTE_YPPM )
- ? PFR_NEXT_USHORT( p )
- : PFR_NEXT_BYTE( p );
-
- strike->flags = PFR_NEXT_BYTE( p );
-
- strike->bct_size = ( flags0 & PFR_STRIKE_3BYTE_SIZE )
- ? PFR_NEXT_ULONG( p )
- : PFR_NEXT_USHORT( p );
-
- strike->bct_offset = ( flags0 & PFR_STRIKE_3BYTE_OFFSET )
- ? PFR_NEXT_ULONG( p )
- : PFR_NEXT_USHORT( p );
-
- strike->num_bitmaps = ( flags0 & PFR_STRIKE_2BYTE_COUNT )
- ? PFR_NEXT_USHORT( p )
- : PFR_NEXT_BYTE( p );
- }
-
- phy_font->num_strikes += count;
-
- Exit:
- return error;
-
- Too_Short:
- error = FT_THROW( Invalid_Table );
- FT_ERROR(( "pfr_extra_item_load_bitmap_info:"
- " invalid bitmap info table\n" ));
- goto Exit;
- }
-
-
- /* Load font ID. This is a so-called "unique" name that is rather
- * long and descriptive (like "Tiresias ScreenFont v7.51").
- *
- * Note that a PFR font's family name is contained in an *undocumented*
- * string of the "auxiliary data" portion of a physical font record. This
- * may also contain the "real" style name!
- *
- * If no family name is present, the font ID is used instead for the
- * family.
- */
- FT_CALLBACK_DEF( FT_Error )
- pfr_extra_item_load_font_id( FT_Byte* p,
- FT_Byte* limit,
- PFR_PhyFont phy_font )
- {
- FT_Error error = FT_Err_Ok;
- FT_Memory memory = phy_font->memory;
- FT_UInt len = (FT_UInt)( limit - p );
-
-
- if ( phy_font->font_id != NULL )
- goto Exit;
-
- if ( FT_ALLOC( phy_font->font_id, len + 1 ) )
- goto Exit;
-
- /* copy font ID name, and terminate it for safety */
- FT_MEM_COPY( phy_font->font_id, p, len );
- phy_font->font_id[len] = 0;
-
- Exit:
- return error;
- }
-
-
- /* load stem snap tables */
- FT_CALLBACK_DEF( FT_Error )
- pfr_extra_item_load_stem_snaps( FT_Byte* p,
- FT_Byte* limit,
- PFR_PhyFont phy_font )
- {
- FT_UInt count, num_vert, num_horz;
- FT_Int* snaps = NULL;
- FT_Error error = FT_Err_Ok;
- FT_Memory memory = phy_font->memory;
-
-
- if ( phy_font->vertical.stem_snaps != NULL )
- goto Exit;
-
- PFR_CHECK( 1 );
- count = PFR_NEXT_BYTE( p );
-
- num_vert = count & 15;
- num_horz = count >> 4;
- count = num_vert + num_horz;
-
- PFR_CHECK( count * 2 );
-
- if ( FT_NEW_ARRAY( snaps, count ) )
- goto Exit;
-
- phy_font->vertical.stem_snaps = snaps;
- phy_font->horizontal.stem_snaps = snaps + num_vert;
-
- for ( ; count > 0; count--, snaps++ )
- *snaps = FT_NEXT_SHORT( p );
-
- Exit:
- return error;
-
- Too_Short:
- error = FT_THROW( Invalid_Table );
- FT_ERROR(( "pfr_exta_item_load_stem_snaps:"
- " invalid stem snaps table\n" ));
- goto Exit;
- }
-
-
-
- /* load kerning pair data */
- FT_CALLBACK_DEF( FT_Error )
- pfr_extra_item_load_kerning_pairs( FT_Byte* p,
- FT_Byte* limit,
- PFR_PhyFont phy_font )
- {
- PFR_KernItem item = NULL;
- FT_Error error = FT_Err_Ok;
- FT_Memory memory = phy_font->memory;
-
-
- FT_TRACE2(( "pfr_extra_item_load_kerning_pairs()\n" ));
-
- if ( FT_NEW( item ) )
- goto Exit;
-
- PFR_CHECK( 4 );
-
- item->pair_count = PFR_NEXT_BYTE( p );
- item->base_adj = PFR_NEXT_SHORT( p );
- item->flags = PFR_NEXT_BYTE( p );
- item->offset = phy_font->offset +
- (FT_Offset)( p - phy_font->cursor );
-
-#ifndef PFR_CONFIG_NO_CHECKS
- item->pair_size = 3;
-
- if ( item->flags & PFR_KERN_2BYTE_CHAR )
- item->pair_size += 2;
-
- if ( item->flags & PFR_KERN_2BYTE_ADJ )
- item->pair_size += 1;
-
- PFR_CHECK( item->pair_count * item->pair_size );
-#endif
-
- /* load first and last pairs into the item to speed up */
- /* lookup later... */
- if ( item->pair_count > 0 )
- {
- FT_UInt char1, char2;
- FT_Byte* q;
-
-
- if ( item->flags & PFR_KERN_2BYTE_CHAR )
- {
- q = p;
- char1 = PFR_NEXT_USHORT( q );
- char2 = PFR_NEXT_USHORT( q );
-
- item->pair1 = PFR_KERN_INDEX( char1, char2 );
-
- q = p + item->pair_size * ( item->pair_count - 1 );
- char1 = PFR_NEXT_USHORT( q );
- char2 = PFR_NEXT_USHORT( q );
-
- item->pair2 = PFR_KERN_INDEX( char1, char2 );
- }
- else
- {
- q = p;
- char1 = PFR_NEXT_BYTE( q );
- char2 = PFR_NEXT_BYTE( q );
-
- item->pair1 = PFR_KERN_INDEX( char1, char2 );
-
- q = p + item->pair_size * ( item->pair_count - 1 );
- char1 = PFR_NEXT_BYTE( q );
- char2 = PFR_NEXT_BYTE( q );
-
- item->pair2 = PFR_KERN_INDEX( char1, char2 );
- }
-
- /* add new item to the current list */
- item->next = NULL;
- *phy_font->kern_items_tail = item;
- phy_font->kern_items_tail = &item->next;
- phy_font->num_kern_pairs += item->pair_count;
- }
- else
- {
- /* empty item! */
- FT_FREE( item );
- }
-
- Exit:
- return error;
-
- Too_Short:
- FT_FREE( item );
-
- error = FT_THROW( Invalid_Table );
- FT_ERROR(( "pfr_extra_item_load_kerning_pairs:"
- " invalid kerning pairs table\n" ));
- goto Exit;
- }
-
-
-
- static const PFR_ExtraItemRec pfr_phy_font_extra_items[] =
- {
- { 1, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_bitmap_info },
- { 2, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_font_id },
- { 3, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_stem_snaps },
- { 4, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_kerning_pairs },
- { 0, NULL }
- };
-
-
- /* Loads a name from the auxiliary data. Since this extracts undocumented
- * strings from the font file, we need to be careful here.
- */
- static FT_Error
- pfr_aux_name_load( FT_Byte* p,
- FT_UInt len,
- FT_Memory memory,
- FT_String* *astring )
- {
- FT_Error error = FT_Err_Ok;
- FT_String* result = NULL;
- FT_UInt n, ok;
-
-
- if ( len > 0 && p[len - 1] == 0 )
- len--;
-
- /* check that each character is ASCII for making sure not to
- load garbage
- */
- ok = ( len > 0 );
- for ( n = 0; n < len; n++ )
- if ( p[n] < 32 || p[n] > 127 )
- {
- ok = 0;
- break;
- }
-
- if ( ok )
- {
- if ( FT_ALLOC( result, len + 1 ) )
- goto Exit;
-
- FT_MEM_COPY( result, p, len );
- result[len] = 0;
- }
- Exit:
- *astring = result;
- return error;
- }
-
-
- FT_LOCAL_DEF( void )
- pfr_phy_font_done( PFR_PhyFont phy_font,
- FT_Memory memory )
- {
- FT_FREE( phy_font->font_id );
- FT_FREE( phy_font->family_name );
- FT_FREE( phy_font->style_name );
-
- FT_FREE( phy_font->vertical.stem_snaps );
- phy_font->vertical.num_stem_snaps = 0;
-
- phy_font->horizontal.stem_snaps = NULL;
- phy_font->horizontal.num_stem_snaps = 0;
-
- FT_FREE( phy_font->strikes );
- phy_font->num_strikes = 0;
- phy_font->max_strikes = 0;
-
- FT_FREE( phy_font->chars );
- phy_font->num_chars = 0;
- phy_font->chars_offset = 0;
-
- FT_FREE( phy_font->blue_values );
- phy_font->num_blue_values = 0;
-
- {
- PFR_KernItem item, next;
-
-
- item = phy_font->kern_items;
- while ( item )
- {
- next = item->next;
- FT_FREE( item );
- item = next;
- }
- phy_font->kern_items = NULL;
- phy_font->kern_items_tail = NULL;
- }
-
- phy_font->num_kern_pairs = 0;
- }
-
-
- FT_LOCAL_DEF( FT_Error )
- pfr_phy_font_load( PFR_PhyFont phy_font,
- FT_Stream stream,
- FT_UInt32 offset,
- FT_UInt32 size )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
- FT_UInt flags;
- FT_ULong num_aux;
- FT_Byte* p;
- FT_Byte* limit;
-
-
- phy_font->memory = memory;
- phy_font->offset = offset;
-
- phy_font->kern_items = NULL;
- phy_font->kern_items_tail = &phy_font->kern_items;
-
- if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( size ) )
- goto Exit;
-
- phy_font->cursor = stream->cursor;
-
- p = stream->cursor;
- limit = p + size;
-
- PFR_CHECK( 15 );
- phy_font->font_ref_number = PFR_NEXT_USHORT( p );
- phy_font->outline_resolution = PFR_NEXT_USHORT( p );
- phy_font->metrics_resolution = PFR_NEXT_USHORT( p );
- phy_font->bbox.xMin = PFR_NEXT_SHORT( p );
- phy_font->bbox.yMin = PFR_NEXT_SHORT( p );
- phy_font->bbox.xMax = PFR_NEXT_SHORT( p );
- phy_font->bbox.yMax = PFR_NEXT_SHORT( p );
- phy_font->flags = flags = PFR_NEXT_BYTE( p );
-
- /* get the standard advance for non-proportional fonts */
- if ( !(flags & PFR_PHY_PROPORTIONAL) )
- {
- PFR_CHECK( 2 );
- phy_font->standard_advance = PFR_NEXT_SHORT( p );
- }
-
- /* load the extra items when present */
- if ( flags & PFR_PHY_EXTRA_ITEMS )
- {
- error = pfr_extra_items_parse( &p, limit,
- pfr_phy_font_extra_items, phy_font );
-
- if ( error )
- goto Fail;
- }
-
- /* In certain fonts, the auxiliary bytes contain interesting */
- /* information. These are not in the specification but can be */
- /* guessed by looking at the content of a few PFR0 fonts. */
- PFR_CHECK( 3 );
- num_aux = PFR_NEXT_ULONG( p );
-
- if ( num_aux > 0 )
- {
- FT_Byte* q = p;
- FT_Byte* q2;
-
-
- PFR_CHECK( num_aux );
- p += num_aux;
-
- while ( num_aux > 0 )
- {
- FT_UInt length, type;
-
-
- if ( q + 4 > p )
- break;
-
- length = PFR_NEXT_USHORT( q );
- if ( length < 4 || length > num_aux )
- break;
-
- q2 = q + length - 2;
- type = PFR_NEXT_USHORT( q );
-
- switch ( type )
- {
- case 1:
- /* this seems to correspond to the font's family name,
- * padded to 16-bits with one zero when necessary
- */
- error = pfr_aux_name_load( q, length - 4U, memory,
- &phy_font->family_name );
- if ( error )
- goto Exit;
- break;
-
- case 2:
- if ( q + 32 > q2 )
- break;
-
- q += 10;
- phy_font->ascent = PFR_NEXT_SHORT( q );
- phy_font->descent = PFR_NEXT_SHORT( q );
- phy_font->leading = PFR_NEXT_SHORT( q );
- break;
-
- case 3:
- /* this seems to correspond to the font's style name,
- * padded to 16-bits with one zero when necessary
- */
- error = pfr_aux_name_load( q, length - 4U, memory,
- &phy_font->style_name );
- if ( error )
- goto Exit;
- break;
-
- default:
- ;
- }
-
- q = q2;
- num_aux -= length;
- }
- }
-
- /* read the blue values */
- {
- FT_UInt n, count;
-
-
- PFR_CHECK( 1 );
- phy_font->num_blue_values = count = PFR_NEXT_BYTE( p );
-
- PFR_CHECK( count * 2 );
-
- if ( FT_NEW_ARRAY( phy_font->blue_values, count ) )
- goto Fail;
-
- for ( n = 0; n < count; n++ )
- phy_font->blue_values[n] = PFR_NEXT_SHORT( p );
- }
-
- PFR_CHECK( 8 );
- phy_font->blue_fuzz = PFR_NEXT_BYTE( p );
- phy_font->blue_scale = PFR_NEXT_BYTE( p );
-
- phy_font->vertical.standard = PFR_NEXT_USHORT( p );
- phy_font->horizontal.standard = PFR_NEXT_USHORT( p );
-
- /* read the character descriptors */
- {
- FT_UInt n, count, Size;
-
-
- phy_font->num_chars = count = PFR_NEXT_USHORT( p );
- phy_font->chars_offset = offset + (FT_Offset)( p - stream->cursor );
-
- if ( FT_NEW_ARRAY( phy_font->chars, count ) )
- goto Fail;
-
- Size = 1 + 1 + 2;
- if ( flags & PFR_PHY_2BYTE_CHARCODE )
- Size += 1;
-
- if ( flags & PFR_PHY_PROPORTIONAL )
- Size += 2;
-
- if ( flags & PFR_PHY_ASCII_CODE )
- Size += 1;
-
- if ( flags & PFR_PHY_2BYTE_GPS_SIZE )
- Size += 1;
-
- if ( flags & PFR_PHY_3BYTE_GPS_OFFSET )
- Size += 1;
-
- PFR_CHECK( count * Size );
-
- for ( n = 0; n < count; n++ )
- {
- PFR_Char cur = &phy_font->chars[n];
-
-
- cur->char_code = ( flags & PFR_PHY_2BYTE_CHARCODE )
- ? PFR_NEXT_USHORT( p )
- : PFR_NEXT_BYTE( p );
-
- cur->advance = ( flags & PFR_PHY_PROPORTIONAL )
- ? PFR_NEXT_SHORT( p )
- : phy_font->standard_advance;
-
-#if 0
- cur->ascii = ( flags & PFR_PHY_ASCII_CODE )
- ? PFR_NEXT_BYTE( p )
- : 0;
-#else
- if ( flags & PFR_PHY_ASCII_CODE )
- p += 1;
-#endif
- cur->gps_size = ( flags & PFR_PHY_2BYTE_GPS_SIZE )
- ? PFR_NEXT_USHORT( p )
- : PFR_NEXT_BYTE( p );
-
- cur->gps_offset = ( flags & PFR_PHY_3BYTE_GPS_OFFSET )
- ? PFR_NEXT_ULONG( p )
- : PFR_NEXT_USHORT( p );
- }
- }
-
- /* that's it! */
-
- Fail:
- FT_FRAME_EXIT();
-
- /* save position of bitmap info */
- phy_font->bct_offset = FT_STREAM_POS();
- phy_font->cursor = NULL;
-
- Exit:
- return error;
-
- Too_Short:
- error = FT_THROW( Invalid_Table );
- FT_ERROR(( "pfr_phy_font_load: invalid physical font table\n" ));
- goto Fail;
- }
-
-
-/* END */
diff --git a/src/psaux/psobjs.c b/src/psaux/psobjs.c
index c7cbc67..1d3c7e6 100644
--- a/src/psaux/psobjs.c
+++ b/src/psaux/psobjs.c
@@ -594,6 +594,9 @@
error = FT_THROW( Invalid_File_Format );
}
+ if ( cur > limit )
+ cur = limit;
+
parser->error = error;
parser->cursor = cur;
}
@@ -1229,15 +1232,17 @@
if ( result < 0 || (FT_UInt)result < max_objects )
{
FT_ERROR(( "ps_parser_load_field:"
- " expected %d integers in the %s subarray\n"
+ " expected %d integer%s in the %s subarray\n"
" "
" of /FontBBox in the /Blend dictionary\n",
- max_objects,
+ max_objects, max_objects > 1 ? "s" : "",
i == 0 ? "first"
: ( i == 1 ? "second"
: ( i == 2 ? "third"
: "fourth" ) ) ));
error = FT_THROW( Invalid_File_Format );
+
+ FT_FREE( temp );
goto Exit;
}
diff --git a/src/psaux/t1decode.c b/src/psaux/t1decode.c
index 2e19928..5811fcb 100644
--- a/src/psaux/t1decode.c
+++ b/src/psaux/t1decode.c
@@ -512,7 +512,7 @@
break;
case 12:
- if ( ip > limit )
+ if ( ip >= limit )
{
FT_ERROR(( "t1_decoder_parse_charstrings:"
" invalid escape (12+EOF)\n" ));
@@ -669,7 +669,7 @@
if ( large_int )
FT_TRACE4(( " %ld", value ));
else
- FT_TRACE4(( " %ld", Fix2Int( value ) ));
+ FT_TRACE4(( " %ld", value / 65536 ));
#endif
*top++ = value;
diff --git a/src/pshinter/pshalgo.c b/src/pshinter/pshalgo.c
index bfdb3ed..6e654cb 100644
--- a/src/pshinter/pshalgo.c
+++ b/src/pshinter/pshalgo.c
@@ -916,103 +916,9 @@
/*************************************************************************/
/*************************************************************************/
-#if 1
-
#define psh_corner_is_flat ft_corner_is_flat
#define psh_corner_orientation ft_corner_orientation
-#else
-
- FT_LOCAL_DEF( FT_Int )
- psh_corner_is_flat( FT_Pos x_in,
- FT_Pos y_in,
- FT_Pos x_out,
- FT_Pos y_out )
- {
- FT_Pos ax = x_in;
- FT_Pos ay = y_in;
-
- FT_Pos d_in, d_out, d_corner;
-
-
- if ( ax < 0 )
- ax = -ax;
- if ( ay < 0 )
- ay = -ay;
- d_in = ax + ay;
-
- ax = x_out;
- if ( ax < 0 )
- ax = -ax;
- ay = y_out;
- if ( ay < 0 )
- ay = -ay;
- d_out = ax + ay;
-
- ax = x_out + x_in;
- if ( ax < 0 )
- ax = -ax;
- ay = y_out + y_in;
- if ( ay < 0 )
- ay = -ay;
- d_corner = ax + ay;
-
- return ( d_in + d_out - d_corner ) < ( d_corner >> 4 );
- }
-
- static FT_Int
- psh_corner_orientation( FT_Pos in_x,
- FT_Pos in_y,
- FT_Pos out_x,
- FT_Pos out_y )
- {
- FT_Int result;
-
-
- /* deal with the trivial cases quickly */
- if ( in_y == 0 )
- {
- if ( in_x >= 0 )
- result = out_y;
- else
- result = -out_y;
- }
- else if ( in_x == 0 )
- {
- if ( in_y >= 0 )
- result = -out_x;
- else
- result = out_x;
- }
- else if ( out_y == 0 )
- {
- if ( out_x >= 0 )
- result = in_y;
- else
- result = -in_y;
- }
- else if ( out_x == 0 )
- {
- if ( out_y >= 0 )
- result = -in_x;
- else
- result = in_x;
- }
- else /* general case */
- {
- long long delta = (long long)in_x * out_y - (long long)in_y * out_x;
-
- if ( delta == 0 )
- result = 0;
- else
- result = 1 - 2 * ( delta < 0 );
- }
-
- return result;
- }
-
-#endif /* !1 */
-
#ifdef COMPUTE_INFLEXS
diff --git a/src/pshinter/pshglob.c b/src/pshinter/pshglob.c
index 6723b71..4616bdc 100644
--- a/src/pshinter/pshglob.c
+++ b/src/pshinter/pshglob.c
@@ -339,7 +339,7 @@
bot = zone[1].org_bottom;
delta = bot - top;
- if ( delta < 2 * fuzz )
+ if ( delta / 2 < fuzz )
zone[0].org_top = zone[1].org_bottom = top + delta / 2;
else
{
diff --git a/src/pshinter/pshpic.h b/src/pshinter/pshpic.h
index 62de457..ca35cd6 100644
--- a/src/pshinter/pshpic.h
+++ b/src/pshinter/pshpic.h
@@ -20,8 +20,6 @@
#define __PSHPIC_H__
-FT_BEGIN_HEADER
-
#include FT_INTERNAL_PIC_H
@@ -33,6 +31,8 @@ FT_BEGIN_HEADER
#include FT_INTERNAL_POSTSCRIPT_HINTS_H
+FT_BEGIN_HEADER
+
typedef struct PSHinterPIC_
{
PSHinter_Interface pshinter_interface;
@@ -51,12 +51,12 @@ FT_BEGIN_HEADER
FT_Error
pshinter_module_class_pic_init( FT_Library library );
+FT_END_HEADER
+
#endif /* FT_CONFIG_OPTION_PIC */
/* */
-FT_END_HEADER
-
#endif /* __PSHPIC_H__ */
diff --git a/src/psnames/psmodule.c b/src/psnames/psmodule.c
index 0f04c2f..5406098 100644
--- a/src/psnames/psmodule.c
+++ b/src/psnames/psmodule.c
@@ -525,31 +525,31 @@
FT_DEFINE_SERVICE_PSCMAPSREC(
pscmaps_interface,
- (PS_Unicode_ValueFunc) ps_unicode_value,
- (PS_Unicodes_InitFunc) ps_unicodes_init,
- (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index,
- (PS_Unicodes_CharNextFunc) ps_unicodes_char_next,
+ (PS_Unicode_ValueFunc) ps_unicode_value, /* unicode_value */
+ (PS_Unicodes_InitFunc) ps_unicodes_init, /* unicodes_init */
+ (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index, /* unicodes_char_index */
+ (PS_Unicodes_CharNextFunc) ps_unicodes_char_next, /* unicodes_char_next */
- (PS_Macintosh_NameFunc) ps_get_macintosh_name,
- (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
+ (PS_Macintosh_NameFunc) ps_get_macintosh_name, /* macintosh_name */
+ (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, /* adobe_std_strings */
- t1_standard_encoding,
- t1_expert_encoding )
+ t1_standard_encoding, /* adobe_std_encoding */
+ t1_expert_encoding ) /* adobe_expert_encoding */
#else
FT_DEFINE_SERVICE_PSCMAPSREC(
pscmaps_interface,
- NULL,
- NULL,
- NULL,
- NULL,
+ NULL, /* unicode_value */
+ NULL, /* unicodes_init */
+ NULL, /* unicodes_char_index */
+ NULL, /* unicodes_char_next */
- (PS_Macintosh_NameFunc) ps_get_macintosh_name,
- (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
+ (PS_Macintosh_NameFunc) ps_get_macintosh_name, /* macintosh_name */
+ (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, /* adobe_std_strings */
- t1_standard_encoding,
- t1_expert_encoding )
+ t1_standard_encoding, /* adobe_std_encoding */
+ t1_expert_encoding ) /* adobe_expert_encoding */
#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
diff --git a/src/psnames/pspic.h b/src/psnames/pspic.h
index 88ccda3..443225a 100644
--- a/src/psnames/pspic.h
+++ b/src/psnames/pspic.h
@@ -20,10 +20,9 @@
#define __PSPIC_H__
-FT_BEGIN_HEADER
-
#include FT_INTERNAL_PIC_H
+
#ifndef FT_CONFIG_OPTION_PIC
#define PSCMAPS_SERVICES_GET pscmaps_services
@@ -33,6 +32,9 @@ FT_BEGIN_HEADER
#include FT_SERVICE_POSTSCRIPT_CMAPS_H
+
+FT_BEGIN_HEADER
+
typedef struct PSModulePIC_
{
FT_ServiceDescRec* pscmaps_services;
@@ -54,12 +56,12 @@ FT_BEGIN_HEADER
FT_Error
psnames_module_class_pic_init( FT_Library library );
+FT_END_HEADER
+
#endif /* FT_CONFIG_OPTION_PIC */
/* */
-FT_END_HEADER
-
#endif /* __PSPIC_H__ */
diff --git a/src/raster/ftmisc.h b/src/raster/ftmisc.h
index 19be4ca..b87e0b6 100644
--- a/src/raster/ftmisc.h
+++ b/src/raster/ftmisc.h
@@ -37,7 +37,7 @@
#define FT_LOCAL_DEF( x ) static x
- /* from include/freetype2/fttypes.h */
+ /* from include/freetype/fttypes.h */
typedef unsigned char FT_Byte;
typedef signed int FT_Int;
@@ -54,7 +54,7 @@
(FT_ULong)_x4 )
- /* from include/freetype2/ftsystem.h */
+ /* from include/freetype/ftsystem.h */
typedef struct FT_MemoryRec_* FT_Memory;
diff --git a/src/raster/ftraster.c b/src/raster/ftraster.c
index eeab143..e4bab98 100644
--- a/src/raster/ftraster.c
+++ b/src/raster/ftraster.c
@@ -24,8 +24,8 @@
/* */
/* - copy `src/raster/ftraster.c' (this file) to your current directory */
/* */
- /* - copy `include/ftimage.h' and `src/raster/ftmisc.h' to your current */
- /* directory */
+ /* - copy `include/freetype/ftimage.h' and `src/raster/ftmisc.h' to your */
+ /* current directory */
/* */
/* - compile `ftraster' with the _STANDALONE_ macro defined, as in */
/* */
@@ -450,7 +450,9 @@
#define CEILING( x ) ( ( (x) + ras.precision - 1 ) & -ras.precision )
#define TRUNC( x ) ( (Long)(x) >> ras.precision_bits )
#define FRAC( x ) ( (x) & ( ras.precision - 1 ) )
-#define SCALED( x ) ( ( (Long)(x) << ras.scale_shift ) - ras.precision_half )
+#define SCALED( x ) ( ( (x) < 0 ? -( -(x) << ras.scale_shift ) \
+ : ( (x) << ras.scale_shift ) ) \
+ - ras.precision_half )
#define IS_BOTTOM_OVERSHOOT( x ) \
(Bool)( CEILING( x ) - x >= ras.precision_half )
@@ -799,15 +801,14 @@
/* if it is <, simply insert it, ignore if == */
if ( n >= 0 && y > y_turns[n] )
- while ( n >= 0 )
+ do
{
Int y2 = (Int)y_turns[n];
y_turns[n] = y;
y = y2;
- n--;
- }
+ } while ( --n >= 0 );
if ( n < 0 )
{
@@ -848,7 +849,7 @@
if ( n > 1 && p )
{
- while ( n > 0 )
+ do
{
Int bottom, top;
@@ -876,8 +877,7 @@
return FAILURE;
p = p->link;
- n--;
- }
+ } while ( --n );
}
else
ras.fProfile = NULL;
@@ -1248,7 +1248,7 @@
start_arc = arc;
- while ( arc >= start_arc && e <= e2 )
+ do
{
ras.joint = FALSE;
@@ -1281,7 +1281,7 @@
}
arc -= degree;
}
- }
+ } while ( arc >= start_arc && e <= e2 );
Fin:
ras.top = top;
@@ -2114,7 +2114,7 @@
while ( current )
{
current->X = *current->offset;
- current->offset += current->flags & Flow_Up ? 1 : -1;
+ current->offset += ( current->flags & Flow_Up ) ? 1 : -1;
current->height--;
current = current->link;
}
diff --git a/src/raster/ftrend1.h b/src/raster/ftrend1.h
index c367260..edc5d13 100644
--- a/src/raster/ftrend1.h
+++ b/src/raster/ftrend1.h
@@ -29,12 +29,6 @@ FT_BEGIN_HEADER
FT_DECLARE_RENDERER( ft_raster1_renderer_class )
- /* this renderer is _NOT_ part of the default modules, you'll need */
- /* to register it by hand in your application. It should only be */
- /* used for backwards-compatibility with FT 1.x anyway. */
- /* */
- FT_DECLARE_RENDERER( ft_raster5_renderer_class )
-
FT_END_HEADER
diff --git a/src/raster/rastpic.c b/src/raster/rastpic.c
index fe58c99..77e7ec3 100644
--- a/src/raster/rastpic.c
+++ b/src/raster/rastpic.c
@@ -59,8 +59,9 @@
FT_Memory memory = library->memory;
- /* since this function also serves raster5 renderer, */
- /* it implements reference counting */
+ /* XXX: since this function also served the no longer available */
+ /* raster5 renderer it uses reference counting, which could */
+ /* be removed now */
if ( pic_container->raster )
{
((RasterPIC*)pic_container->raster)->ref_count++;
@@ -82,21 +83,6 @@
return error;
}
-
- /* re-route these init and free functions to the above functions */
- FT_Error
- ft_raster5_renderer_class_pic_init( FT_Library library )
- {
- return ft_raster1_renderer_class_pic_init( library );
- }
-
-
- void
- ft_raster5_renderer_class_pic_free( FT_Library library )
- {
- ft_raster1_renderer_class_pic_free( library );
- }
-
#endif /* FT_CONFIG_OPTION_PIC */
diff --git a/src/raster/rastpic.h b/src/raster/rastpic.h
index a875884..408996a 100644
--- a/src/raster/rastpic.h
+++ b/src/raster/rastpic.h
@@ -20,11 +20,11 @@
#define __RASTPIC_H__
-FT_BEGIN_HEADER
-
#include FT_INTERNAL_PIC_H
+FT_BEGIN_HEADER
+
#ifndef FT_CONFIG_OPTION_PIC
#define FT_STANDARD_RASTER_GET ft_standard_raster
@@ -48,15 +48,9 @@ FT_BEGIN_HEADER
void
ft_raster1_renderer_class_pic_free( FT_Library library );
- void
- ft_raster5_renderer_class_pic_free( FT_Library library );
-
FT_Error
ft_raster1_renderer_class_pic_init( FT_Library library );
- FT_Error
- ft_raster5_renderer_class_pic_init( FT_Library library );
-
#endif /* FT_CONFIG_OPTION_PIC */
/* */
diff --git a/src/sfnt/sfdriver.c b/src/sfnt/sfdriver.c
index 0948ad4..5dd8449 100644
--- a/src/sfnt/sfdriver.c
+++ b/src/sfnt/sfdriver.c
@@ -139,9 +139,9 @@
FT_DEFINE_SERVICE_SFNT_TABLEREC(
sfnt_service_sfnt_table,
- (FT_SFNT_TableLoadFunc)tt_face_load_any,
- (FT_SFNT_TableGetFunc) get_sfnt_table,
- (FT_SFNT_TableInfoFunc)sfnt_table_info )
+ (FT_SFNT_TableLoadFunc)tt_face_load_any, /* load_table */
+ (FT_SFNT_TableGetFunc) get_sfnt_table, /* get_table */
+ (FT_SFNT_TableInfoFunc)sfnt_table_info ) /* table_info */
#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
@@ -205,8 +205,8 @@
FT_DEFINE_SERVICE_GLYPHDICTREC(
sfnt_service_glyph_dict,
- (FT_GlyphDict_GetNameFunc) sfnt_get_glyph_name,
- (FT_GlyphDict_NameIndexFunc)sfnt_get_name_index )
+ (FT_GlyphDict_GetNameFunc) sfnt_get_glyph_name, /* get_name */
+ (FT_GlyphDict_NameIndexFunc)sfnt_get_name_index ) /* name_index */
#endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */
@@ -330,7 +330,7 @@
FT_DEFINE_SERVICE_PSFONTNAMEREC(
sfnt_service_ps_name,
- (FT_PsName_GetFunc)sfnt_get_ps_name )
+ (FT_PsName_GetFunc)sfnt_get_ps_name ) /* get_ps_font_name */
/*
@@ -338,7 +338,7 @@
*/
FT_DEFINE_SERVICE_TTCMAPSREC(
tt_service_get_cmap_info,
- (TT_CMap_Info_GetFunc)tt_get_cmap_info )
+ (TT_CMap_Info_GetFunc)tt_get_cmap_info ) /* get_cmap_info */
#ifdef TT_CONFIG_OPTION_BDF
@@ -381,8 +381,8 @@
FT_DEFINE_SERVICE_BDFRec(
sfnt_service_bdf,
- (FT_BDF_GetCharsetIdFunc)sfnt_get_charset_id,
- (FT_BDF_GetPropertyFunc) tt_face_find_bdf_prop )
+ (FT_BDF_GetCharsetIdFunc)sfnt_get_charset_id, /* get_charset_id */
+ (FT_BDF_GetPropertyFunc) tt_face_find_bdf_prop ) /* get_property */
#endif /* TT_CONFIG_OPTION_BDF */
@@ -505,7 +505,9 @@
PUT_EMBEDDED_BITMAPS( tt_face_set_sbit_strike ),
PUT_EMBEDDED_BITMAPS( tt_face_load_strike_metrics ),
- tt_face_get_metrics
+ tt_face_get_metrics,
+
+ tt_face_get_name
)
diff --git a/src/sfnt/sfntpic.h b/src/sfnt/sfntpic.h
index 563d634..d99be6a 100644
--- a/src/sfnt/sfntpic.h
+++ b/src/sfnt/sfntpic.h
@@ -20,8 +20,6 @@
#define __SFNTPIC_H__
-FT_BEGIN_HEADER
-
#include FT_INTERNAL_PIC_H
@@ -31,7 +29,6 @@ FT_BEGIN_HEADER
#define SFNT_SERVICE_GLYPH_DICT_GET sfnt_service_glyph_dict
#define SFNT_SERVICE_PS_NAME_GET sfnt_service_ps_name
#define TT_SERVICE_CMAP_INFO_GET tt_service_get_cmap_info
-#define SFNT_SERVICES_GET sfnt_services
#define TT_CMAP_CLASSES_GET tt_cmap_classes
#define SFNT_SERVICE_SFNT_TABLE_GET sfnt_service_sfnt_table
#define SFNT_SERVICE_BDF_GET sfnt_service_bdf
@@ -56,6 +53,8 @@ FT_BEGIN_HEADER
#include "ttcmap.h"
+FT_BEGIN_HEADER
+
typedef struct sfntModulePIC_
{
FT_ServiceDescRec* sfnt_services;
@@ -83,8 +82,6 @@ FT_BEGIN_HEADER
( GET_PIC( library )->sfnt_service_ps_name )
#define TT_SERVICE_CMAP_INFO_GET \
( GET_PIC( library )->tt_service_get_cmap_info )
-#define SFNT_SERVICES_GET \
- ( GET_PIC( library )->sfnt_services )
#define TT_CMAP_CLASSES_GET \
( GET_PIC( library )->tt_cmap_classes )
#define SFNT_SERVICE_SFNT_TABLE_GET \
@@ -102,12 +99,13 @@ FT_BEGIN_HEADER
FT_Error
sfnt_module_class_pic_init( FT_Library library );
+
+FT_END_HEADER
+
#endif /* FT_CONFIG_OPTION_PIC */
/* */
-FT_END_HEADER
-
#endif /* __SFNTPIC_H__ */
diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c
index 40c27fa..de030ea 100644
--- a/src/sfnt/sfobjs.c
+++ b/src/sfnt/sfobjs.c
@@ -120,27 +120,9 @@
FT_Memory memory );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_get_name */
- /* */
- /* <Description> */
- /* Returns a given ENGLISH name record in ASCII. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face object. */
- /* */
- /* nameid :: The name id of the name record to return. */
- /* */
- /* <InOut> */
- /* name :: The address of a string pointer. NULL if no name is */
- /* present. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- static FT_Error
+ /* documentation is in sfnt.h */
+
+ FT_LOCAL_DEF( FT_Error )
tt_face_get_name( TT_Face face,
FT_UShort nameid,
FT_String** name )
@@ -469,10 +451,14 @@
woff.metaOrigLength != 0 ) ) ||
( woff.metaLength != 0 && woff.metaOrigLength == 0 ) ||
( woff.privOffset == 0 && woff.privLength != 0 ) )
+ {
+ FT_ERROR(( "woff_font_open: invalid WOFF header\n" ));
return FT_THROW( Invalid_Table );
+ }
- if ( FT_ALLOC( sfnt, woff.totalSfntSize ) ||
- FT_NEW( sfnt_stream ) )
+ /* Don't trust `totalSfntSize' before thorough checks. */
+ if ( FT_ALLOC( sfnt, 12 + woff.num_tables * 16UL ) ||
+ FT_NEW( sfnt_stream ) )
goto Exit;
sfnt_header = sfnt;
@@ -539,6 +525,8 @@
if ( table->Tag <= old_tag )
{
FT_FRAME_EXIT();
+
+ FT_ERROR(( "woff_font_open: table tags are not sorted\n" ));
error = FT_THROW( Invalid_Table );
goto Exit;
}
@@ -573,6 +561,7 @@
sfnt_offset > woff.totalSfntSize - table->OrigLength ||
table->CompLength > table->OrigLength )
{
+ FT_ERROR(( "woff_font_open: invalid table offsets\n" ));
error = FT_THROW( Invalid_Table );
goto Exit;
}
@@ -598,6 +587,8 @@
if ( woff.metaOffset != woff_offset ||
woff.metaOffset + woff.metaLength > woff.length )
{
+ FT_ERROR(( "woff_font_open:"
+ " invalid `metadata' offset or length\n" ));
error = FT_THROW( Invalid_Table );
goto Exit;
}
@@ -614,6 +605,7 @@
if ( woff.privOffset != woff_offset ||
woff.privOffset + woff.privLength > woff.length )
{
+ FT_ERROR(( "woff_font_open: invalid `private' offset or length\n" ));
error = FT_THROW( Invalid_Table );
goto Exit;
}
@@ -625,10 +617,19 @@
if ( sfnt_offset != woff.totalSfntSize ||
woff_offset != woff.length )
{
+ FT_ERROR(( "woff_font_open: invalid `sfnt' table structure\n" ));
error = FT_THROW( Invalid_Table );
goto Exit;
}
+ /* Now use `totalSfntSize'. */
+ if ( FT_REALLOC( sfnt,
+ 12 + woff.num_tables * 16UL,
+ woff.totalSfntSize ) )
+ goto Exit;
+
+ sfnt_header = sfnt + 12;
+
/* Write the tables. */
for ( nn = 0; nn < woff.num_tables; nn++ )
@@ -669,6 +670,7 @@
goto Exit;
if ( output_len != table->OrigLength )
{
+ FT_ERROR(( "woff_font_open: compressed table length mismatch\n" ));
error = FT_THROW( Invalid_Table );
goto Exit;
}
@@ -839,13 +841,14 @@
FT_LOCAL_DEF( FT_Error )
sfnt_init_face( FT_Stream stream,
TT_Face face,
- FT_Int face_index,
+ FT_Int face_instance_index,
FT_Int num_params,
FT_Parameter* params )
{
- FT_Error error;
- FT_Library library = face->root.driver->root.library;
- SFNT_Service sfnt;
+ FT_Error error;
+ FT_Library library = face->root.driver->root.library;
+ SFNT_Service sfnt;
+ FT_Int face_index;
/* for now, parameters are unused */
@@ -878,22 +881,97 @@
/* Stream may have changed in sfnt_open_font. */
stream = face->root.stream;
- FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face, face_index ));
+ FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face, face_instance_index ));
- if ( face_index < 0 )
- face_index = 0;
+ face_index = FT_ABS( face_instance_index ) & 0xFFFF;
if ( face_index >= face->ttc_header.count )
- return FT_THROW( Invalid_Argument );
+ {
+ if ( face_instance_index >= 0 )
+ return FT_THROW( Invalid_Argument );
+ else
+ face_index = 0;
+ }
if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) )
return error;
- /* check that we have a valid TrueType file */
+ /* check whether we have a valid TrueType file */
error = sfnt->load_font_dir( face, stream );
if ( error )
return error;
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+ {
+ FT_ULong fvar_len;
+
+ FT_ULong version;
+ FT_ULong offset;
+
+ FT_UShort num_axes;
+ FT_UShort axis_size;
+ FT_UShort num_instances;
+ FT_UShort instance_size;
+
+ FT_Int instance_index;
+
+
+ instance_index = FT_ABS( face_instance_index ) >> 16;
+
+ /* test whether current face is a GX font with named instances */
+ if ( face->goto_table( face, TTAG_fvar, stream, &fvar_len ) ||
+ fvar_len < 20 ||
+ FT_READ_ULONG( version ) ||
+ FT_READ_USHORT( offset ) ||
+ FT_STREAM_SKIP( 2 ) ||
+ FT_READ_USHORT( num_axes ) ||
+ FT_READ_USHORT( axis_size ) ||
+ FT_READ_USHORT( num_instances ) ||
+ FT_READ_USHORT( instance_size ) )
+ {
+ version = 0;
+ offset = 0;
+ num_axes = 0;
+ axis_size = 0;
+ num_instances = 0;
+ instance_size = 0;
+ }
+
+ /* check that the data is bound by the table length; */
+ /* based on similar code in function `TT_Get_MM_Var' */
+ if ( version != 0x00010000UL ||
+ axis_size != 20 ||
+ num_axes > 0x3FFE ||
+ instance_size != 4 + 4 * num_axes ||
+ num_instances > 0x7EFF ||
+ offset +
+ axis_size * num_axes +
+ instance_size * num_instances > fvar_len )
+ num_instances = 0;
+
+ /* we support at most 2^15 - 1 instances */
+ if ( num_instances >= ( 1U << 15 ) - 1 )
+ {
+ if ( face_instance_index >= 0 )
+ return FT_THROW( Invalid_Argument );
+ else
+ num_instances = 0;
+ }
+
+ /* instance indices in `face_instance_index' start with index 1, */
+ /* thus `>' and not `>=' */
+ if ( instance_index > num_instances )
+ {
+ if ( face_instance_index >= 0 )
+ return FT_THROW( Invalid_Argument );
+ else
+ num_instances = 0;
+ }
+
+ face->root.style_flags = (FT_Long)num_instances << 16;
+ }
+#endif
+
face->root.num_faces = face->ttc_header.count;
face->root.face_index = face_index;
@@ -946,7 +1024,7 @@
FT_LOCAL_DEF( FT_Error )
sfnt_load_face( FT_Stream stream,
TT_Face face,
- FT_Int face_index,
+ FT_Int face_instance_index,
FT_Int num_params,
FT_Parameter* params )
{
@@ -962,7 +1040,7 @@
SFNT_Service sfnt = (SFNT_Service)face->sfnt;
- FT_UNUSED( face_index );
+ FT_UNUSED( face_instance_index );
/* Check parameters */
@@ -1284,7 +1362,7 @@
flags |= FT_STYLE_FLAG_ITALIC;
}
- root->style_flags = flags;
+ root->style_flags |= flags;
/*********************************************************************/
/* */
diff --git a/src/sfnt/sfobjs.h b/src/sfnt/sfobjs.h
index 77c7d92..455f867 100644
--- a/src/sfnt/sfobjs.h
+++ b/src/sfnt/sfobjs.h
@@ -31,20 +31,25 @@ FT_BEGIN_HEADER
FT_LOCAL( FT_Error )
sfnt_init_face( FT_Stream stream,
TT_Face face,
- FT_Int face_index,
+ FT_Int face_instance_index,
FT_Int num_params,
FT_Parameter* params );
FT_LOCAL( FT_Error )
sfnt_load_face( FT_Stream stream,
TT_Face face,
- FT_Int face_index,
+ FT_Int face_instance_index,
FT_Int num_params,
FT_Parameter* params );
FT_LOCAL( void )
sfnt_done_face( TT_Face face );
+ FT_LOCAL( FT_Error )
+ tt_face_get_name( TT_Face face,
+ FT_UShort nameid,
+ FT_String** name );
+
FT_END_HEADER
diff --git a/src/sfnt/ttcmap.c b/src/sfnt/ttcmap.c
index 815ee7c..2b1337f 100644
--- a/src/sfnt/ttcmap.c
+++ b/src/sfnt/ttcmap.c
@@ -51,6 +51,13 @@
#define TT_NEXT_ULONG FT_NEXT_ULONG
+ /* Too large glyph index return values are caught in `FT_Get_Char_Index' */
+ /* and `FT_Get_Next_Char' (the latter calls the internal `next' function */
+ /* again in this case). To mark character code return values as invalid */
+ /* it is sufficient to set the corresponding glyph index return value to */
+ /* zero. */
+
+
FT_CALLBACK_DEF( FT_Error )
tt_cmap_init( TT_CMap cmap,
FT_Byte* table )
@@ -199,7 +206,7 @@
/***** FORMAT 2 *****/
/***** *****/
/***** This is used for certain CJK encodings that encode text in a *****/
- /***** mixed 8/16 bits encoding along the following lines: *****/
+ /***** mixed 8/16 bits encoding along the following lines. *****/
/***** *****/
/***** * Certain byte values correspond to an 8-bit character code *****/
/***** (typically in the range 0..127 for ASCII compatibility). *****/
@@ -209,19 +216,19 @@
/***** second byte of a 2-byte character). *****/
/***** *****/
/***** The following charmap lookup and iteration functions all *****/
- /***** assume that the value "charcode" correspond to following: *****/
+ /***** 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 *****/
- /***** character code in big endian format. More exactly: *****/
+ /***** - For two byte characters, `charcode' is the 2-byte *****/
+ /***** character code in big endian format. More precisely: *****/
/***** *****/
/***** (charcode >> 8) is the first byte value *****/
/***** (charcode & 0xFF) is the second byte value *****/
/***** *****/
- /***** Note that not all values of "charcode" are valid according *****/
- /***** to these rules, and the function moderately check the *****/
+ /***** Note that not all values of `charcode' are valid according *****/
+ /***** to these rules, and the function moderately checks the *****/
/***** arguments. *****/
/***** *****/
/*************************************************************************/
@@ -249,7 +256,7 @@
/* table, i.e., it is the corresponding sub-header index multiplied */
/* by 8. */
/* */
- /* Each sub-header has the following format: */
+ /* Each sub-header has the following format. */
/* */
/* NAME OFFSET TYPE DESCRIPTION */
/* */
@@ -264,11 +271,11 @@
/* according to the specification. */
/* */
/* If a character code is contained within a given sub-header, then */
- /* mapping it to a glyph index is done as follows: */
+ /* mapping it to a glyph index is done as follows. */
/* */
/* * The value of `offset' is read. This is a _byte_ distance from the */
/* location of the `offset' field itself into a slice of the */
- /* `glyph_ids' table. Let's call it `slice' (it is a USHORT[] too). */
+ /* `glyph_ids' table. Let's call it `slice' (it is a USHORT[], too). */
/* */
/* * The value `slice[char.lo - first]' is read. If it is 0, there is */
/* no glyph for the charcode. Otherwise, the value of `delta' is */
@@ -326,7 +333,7 @@
FT_ASSERT( p == table + 518 );
subs = p;
- glyph_ids = subs + (max_subs + 1) * 8;
+ glyph_ids = subs + ( max_subs + 1 ) * 8;
if ( glyph_ids > valid->limit )
FT_INVALID_TOO_SHORT;
@@ -436,6 +443,7 @@
}
result = sub;
}
+
Exit:
return result;
}
@@ -475,6 +483,7 @@
result = (FT_UInt)( (FT_Int)idx + delta ) & 0xFFFFU;
}
}
+
return result;
}
@@ -765,7 +774,7 @@
if ( charcode < cmap->cur_start )
charcode = cmap->cur_start;
- for ( ;; )
+ for (;;)
{
FT_Byte* values = cmap->cur_values;
FT_UInt end = cmap->cur_end;
@@ -973,7 +982,7 @@
/* segment if it contains only a single character. */
/* */
/* We thus omit the test here, delaying it to the */
- /* routines which actually access the cmap. */
+ /* routines that actually access the cmap. */
else if ( n != num_segs - 1 ||
!( start == 0xFFFFU && end == 0xFFFFU ) )
{
@@ -1026,12 +1035,17 @@
FT_UInt32* pcharcode,
FT_Bool next )
{
+ TT_Face face = (TT_Face)cmap->cmap.charmap.face;
+ FT_Byte* limit = face->cmap_table + face->cmap_size;
+
+
FT_UInt num_segs2, start, end, offset;
FT_Int delta;
FT_UInt i, num_segs;
FT_UInt32 charcode = *pcharcode;
FT_UInt gindex = 0;
FT_Byte* p;
+ FT_Byte* q;
p = cmap->data + 6;
@@ -1045,65 +1059,106 @@
if ( next )
charcode++;
+ if ( charcode > 0xFFFFU )
+ return 0;
+
/* linear search */
- for ( ; charcode <= 0xFFFFU; charcode++ )
- {
- FT_Byte* q;
+ p = cmap->data + 14; /* ends table */
+ q = cmap->data + 16 + num_segs2; /* starts table */
+ for ( i = 0; i < num_segs; i++ )
+ {
+ end = TT_NEXT_USHORT( p );
+ start = TT_NEXT_USHORT( q );
- p = cmap->data + 14; /* ends table */
- q = cmap->data + 16 + num_segs2; /* starts table */
+ if ( charcode < start )
+ {
+ if ( next )
+ charcode = start;
+ else
+ break;
+ }
- for ( i = 0; i < num_segs; i++ )
+ Again:
+ if ( charcode <= end )
{
- end = TT_NEXT_USHORT( p );
- start = TT_NEXT_USHORT( q );
+ FT_Byte* r;
+
- if ( charcode >= start && charcode <= end )
+ r = q - 2 + num_segs2;
+ delta = TT_PEEK_SHORT( r );
+ r += num_segs2;
+ offset = TT_PEEK_USHORT( r );
+
+ /* some fonts have an incorrect last segment; */
+ /* we have to catch it */
+ if ( i >= num_segs - 1 &&
+ start == 0xFFFFU && end == 0xFFFFU )
{
- p = q - 2 + num_segs2;
- delta = TT_PEEK_SHORT( p );
- p += num_segs2;
- offset = TT_PEEK_USHORT( p );
-
- /* some fonts have an incorrect last segment; */
- /* we have to catch it */
- if ( i >= num_segs - 1 &&
- start == 0xFFFFU && end == 0xFFFFU )
+ if ( offset && r + offset + 2 > limit )
{
- TT_Face face = (TT_Face)cmap->cmap.charmap.face;
- FT_Byte* limit = face->cmap_table + face->cmap_size;
+ delta = 1;
+ offset = 0;
+ }
+ }
+ if ( offset == 0xFFFFU )
+ continue;
- if ( offset && p + offset + 2 > limit )
- {
- delta = 1;
- offset = 0;
- }
- }
+ if ( offset )
+ {
+ r += offset + ( charcode - start ) * 2;
- if ( offset == 0xFFFFU )
+ /* if r > limit, the whole segment is invalid */
+ if ( next && r > limit )
continue;
- if ( offset )
+ gindex = TT_PEEK_USHORT( r );
+ if ( gindex )
{
- p += offset + ( charcode - start ) * 2;
- gindex = TT_PEEK_USHORT( p );
- if ( gindex != 0 )
- gindex = (FT_UInt)( (FT_Int)gindex + delta ) & 0xFFFFU;
+ gindex = (FT_UInt)( (FT_Int)gindex + delta ) & 0xFFFFU;
+ if ( gindex >= (FT_UInt)face->root.num_glyphs )
+ gindex = 0;
}
- else
- gindex = (FT_UInt)( (FT_Int)charcode + delta ) & 0xFFFFU;
+ }
+ else
+ {
+ gindex = (FT_UInt)( (FT_Int)charcode + delta ) & 0xFFFFU;
- break;
+ if ( next && gindex >= (FT_UInt)face->root.num_glyphs )
+ {
+ /* we have an invalid glyph index; if there is an overflow, */
+ /* we can adjust `charcode', otherwise the whole segment is */
+ /* invalid */
+ gindex = 0;
+
+ if ( (FT_Int)charcode + delta < 0 &&
+ (FT_Int)end + delta >= 0 )
+ charcode = (FT_UInt)( -delta );
+
+ else if ( (FT_Int)charcode + delta < 0x10000L &&
+ (FT_Int)end + delta >= 0x10000L )
+ charcode = (FT_UInt)( 0x10000L - delta );
+
+ else
+ continue;
+ }
+ }
+
+ if ( next && !gindex )
+ {
+ if ( charcode >= 0xFFFFU )
+ break;
+
+ charcode++;
+ goto Again;
}
- }
- if ( !next || gindex )
break;
+ }
}
- if ( next && gindex )
+ if ( next )
*pcharcode = charcode;
return gindex;
@@ -1310,7 +1365,6 @@
/* if `charcode' is not in any segment, then `mid' is */
/* the segment nearest to `charcode' */
- /* */
if ( charcode > end )
{
@@ -1443,7 +1497,7 @@
/* */
/* NAME OFFSET TYPE DESCRIPTION */
/* */
- /* format 0 USHORT must be 4 */
+ /* format 0 USHORT must be 6 */
/* length 2 USHORT table length in bytes */
/* language 4 USHORT Mac language code */
/* */
@@ -1511,6 +1565,7 @@
p += 2 * idx;
result = TT_PEEK_USHORT( p );
}
+
return result;
}
@@ -1531,7 +1586,7 @@
if ( char_code >= 0x10000UL )
- goto Exit;
+ return 0;
if ( char_code < start )
char_code = start;
@@ -1547,10 +1602,13 @@
result = char_code;
break;
}
+
+ if ( char_code >= 0xFFFFU )
+ return 0;
+
char_code++;
}
- Exit:
*pchar_code = result;
return gindex;
}
@@ -1602,7 +1660,7 @@
/***** *****/
/***** The purpose of this format is to easily map UTF-16 text to *****/
/***** glyph indices. Basically, the `char_code' must be in one of *****/
- /***** the following formats: *****/
+ /***** the following formats. *****/
/***** *****/
/***** - A 16-bit value that isn't part of the Unicode Surrogates *****/
/***** Area (i.e. U+D800-U+DFFF). *****/
@@ -1615,7 +1673,7 @@
/***** The `is32' table embedded in the charmap indicates whether a *****/
/***** given 16-bit value is in the surrogates area or not. *****/
/***** *****/
- /***** So, for any given `char_code', we can assert the following: *****/
+ /***** So, for any given `char_code', we can assert the following. *****/
/***** *****/
/***** If `char_hi == 0' then we must have `is32[char_lo] == 0'. *****/
/***** *****/
@@ -1770,7 +1828,10 @@
if ( char_code <= end )
{
- result = (FT_UInt)( start_id + char_code - start );
+ if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) )
+ return 0;
+
+ result = (FT_UInt)( start_id + ( char_code - start ) );
break;
}
}
@@ -1782,8 +1843,9 @@
tt_cmap8_char_next( TT_CMap cmap,
FT_UInt32 *pchar_code )
{
+ FT_Face face = cmap->cmap.charmap.face;
FT_UInt32 result = 0;
- FT_UInt32 char_code = *pchar_code + 1;
+ FT_UInt32 char_code;
FT_UInt gindex = 0;
FT_Byte* table = cmap->data;
FT_Byte* p = table + 8204;
@@ -1791,6 +1853,11 @@
FT_UInt32 start, end, start_id;
+ if ( *pchar_code >= 0xFFFFFFFFUL )
+ return 0;
+
+ char_code = *pchar_code + 1;
+
p = table + 8208;
for ( ; num_groups > 0; num_groups-- )
@@ -1802,18 +1869,38 @@
if ( char_code < start )
char_code = start;
+ Again:
if ( char_code <= end )
{
- gindex = (FT_UInt)( char_code - start + start_id );
- if ( gindex != 0 )
+ /* ignore invalid group */
+ if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) )
+ continue;
+
+ gindex = (FT_UInt)( start_id + ( char_code - start ) );
+
+ /* does first element of group point to `.notdef' glyph? */
+ if ( gindex == 0 )
{
- result = char_code;
- goto Exit;
+ if ( char_code >= 0xFFFFFFFFUL )
+ break;
+
+ char_code++;
+ goto Again;
}
+
+ /* if `gindex' is invalid, the remaining values */
+ /* in this group are invalid, too */
+ if ( gindex >= (FT_UInt)face->num_glyphs )
+ {
+ gindex = 0;
+ continue;
+ }
+
+ result = char_code;
+ break;
}
}
- Exit:
*pchar_code = result;
return gindex;
}
@@ -1930,14 +2017,20 @@
FT_Byte* p = table + 12;
FT_UInt32 start = TT_NEXT_ULONG( p );
FT_UInt32 count = TT_NEXT_ULONG( p );
- FT_UInt32 idx = (FT_ULong)( char_code - start );
+ FT_UInt32 idx;
+
+ if ( char_code < start )
+ return 0;
+
+ idx = char_code - start;
if ( idx < count )
{
p += 2 * idx;
result = TT_PEEK_USHORT( p );
}
+
return result;
}
@@ -1947,7 +2040,7 @@
FT_UInt32 *pchar_code )
{
FT_Byte* table = cmap->data;
- FT_UInt32 char_code = *pchar_code + 1;
+ FT_UInt32 char_code;
FT_UInt gindex = 0;
FT_Byte* p = table + 12;
FT_UInt32 start = TT_NEXT_ULONG( p );
@@ -1955,10 +2048,15 @@
FT_UInt32 idx;
+ if ( *pchar_code >= 0xFFFFFFFFUL )
+ return 0;
+
+ char_code = *pchar_code + 1;
+
if ( char_code < start )
char_code = start;
- idx = (FT_UInt32)( char_code - start );
+ idx = char_code - start;
p += 2 * idx;
for ( ; idx < count; idx++ )
@@ -1966,6 +2064,10 @@
gindex = TT_NEXT_USHORT( p );
if ( gindex != 0 )
break;
+
+ if ( char_code >= 0xFFFFFFFFUL )
+ return 0;
+
char_code++;
}
@@ -2134,6 +2236,7 @@
static void
tt_cmap12_next( TT_CMap12 cmap )
{
+ FT_Face face = cmap->cmap.cmap.charmap.face;
FT_Byte* p;
FT_ULong start, end, start_id, char_code;
FT_ULong n;
@@ -2155,18 +2258,38 @@
if ( char_code < start )
char_code = start;
- for ( ; char_code <= end; char_code++ )
+ Again:
+ if ( char_code <= end )
{
- gindex = (FT_UInt)( start_id + char_code - start );
+ /* ignore invalid group */
+ if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) )
+ continue;
- if ( gindex )
+ gindex = (FT_UInt)( start_id + ( char_code - start ) );
+
+ /* does first element of group point to `.notdef' glyph? */
+ if ( gindex == 0 )
{
- cmap->cur_charcode = char_code;;
- cmap->cur_gindex = gindex;
- cmap->cur_group = n;
+ if ( char_code >= 0xFFFFFFFFUL )
+ goto Fail;
- return;
+ char_code++;
+ goto Again;
+ }
+
+ /* if `gindex' is invalid, the remaining values */
+ /* in this group are invalid, too */
+ if ( gindex >= (FT_UInt)face->num_glyphs )
+ {
+ gindex = 0;
+ continue;
}
+
+ cmap->cur_charcode = char_code;
+ cmap->cur_gindex = gindex;
+ cmap->cur_group = n;
+
+ return;
}
}
@@ -2196,7 +2319,12 @@
end = 0xFFFFFFFFUL;
if ( next )
+ {
+ if ( char_code >= 0xFFFFFFFFUL )
+ return 0;
+
char_code++;
+ }
min = 0;
max = num_groups;
@@ -2217,20 +2345,24 @@
else
{
start_id = TT_PEEK_ULONG( p );
- gindex = (FT_UInt)( start_id + char_code - start );
+ /* reject invalid glyph index */
+ if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) )
+ gindex = 0;
+ else
+ gindex = (FT_UInt)( start_id + ( char_code - start ) );
break;
}
}
if ( next )
{
+ FT_Face face = cmap->cmap.charmap.face;
TT_CMap12 cmap12 = (TT_CMap12)cmap;
/* if `char_code' is not in any group, then `mid' is */
/* the group nearest to `char_code' */
- /* */
if ( char_code > end )
{
@@ -2243,6 +2375,9 @@
cmap12->cur_charcode = char_code;
cmap12->cur_group = mid;
+ if ( gindex >= (FT_UInt)face->num_glyphs )
+ gindex = 0;
+
if ( !gindex )
{
tt_cmap12_next( cmap12 );
@@ -2253,8 +2388,7 @@
else
cmap12->cur_gindex = gindex;
- if ( gindex )
- *pchar_code = cmap12->cur_charcode;
+ *pchar_code = cmap12->cur_charcode;
}
return gindex;
@@ -2274,11 +2408,8 @@
FT_UInt32 *pchar_code )
{
TT_CMap12 cmap12 = (TT_CMap12)cmap;
- FT_ULong gindex;
-
+ FT_UInt gindex;
- if ( cmap12->cur_charcode >= 0xFFFFFFFFUL )
- return 0;
/* no need to search */
if ( cmap12->valid && cmap12->cur_charcode == *pchar_code )
@@ -2286,11 +2417,8 @@
tt_cmap12_next( cmap12 );
if ( cmap12->valid )
{
- gindex = cmap12->cur_gindex;
-
- /* XXX: check cur_charcode overflow is expected */
- if ( gindex )
- *pchar_code = (FT_UInt32)cmap12->cur_charcode;
+ gindex = cmap12->cur_gindex;
+ *pchar_code = (FT_UInt32)cmap12->cur_charcode;
}
else
gindex = 0;
@@ -2298,8 +2426,7 @@
else
gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 );
- /* XXX: check gindex overflow is expected */
- return (FT_UInt32)gindex;
+ return gindex;
}
@@ -2458,6 +2585,7 @@
static void
tt_cmap13_next( TT_CMap13 cmap )
{
+ FT_Face face = cmap->cmap.cmap.charmap.face;
FT_Byte* p;
FT_ULong start, end, glyph_id, char_code;
FT_ULong n;
@@ -2483,9 +2611,9 @@
{
gindex = (FT_UInt)glyph_id;
- if ( gindex )
+ if ( gindex && gindex < (FT_UInt)face->num_glyphs )
{
- cmap->cur_charcode = char_code;;
+ cmap->cur_charcode = char_code;
cmap->cur_gindex = gindex;
cmap->cur_group = n;
@@ -2520,7 +2648,12 @@
end = 0xFFFFFFFFUL;
if ( next )
+ {
+ if ( char_code >= 0xFFFFFFFFUL )
+ return 0;
+
char_code++;
+ }
min = 0;
max = num_groups;
@@ -2548,6 +2681,7 @@
if ( next )
{
+ FT_Face face = cmap->cmap.charmap.face;
TT_CMap13 cmap13 = (TT_CMap13)cmap;
@@ -2565,6 +2699,9 @@
cmap13->cur_charcode = char_code;
cmap13->cur_group = mid;
+ if ( gindex >= (FT_UInt)face->num_glyphs )
+ gindex = 0;
+
if ( !gindex )
{
tt_cmap13_next( cmap13 );
@@ -2575,8 +2712,7 @@
else
cmap13->cur_gindex = gindex;
- if ( gindex )
- *pchar_code = cmap13->cur_charcode;
+ *pchar_code = cmap13->cur_charcode;
}
return gindex;
@@ -2599,18 +2735,14 @@
FT_UInt gindex;
- if ( cmap13->cur_charcode >= 0xFFFFFFFFUL )
- return 0;
-
/* no need to search */
if ( cmap13->valid && cmap13->cur_charcode == *pchar_code )
{
tt_cmap13_next( cmap13 );
if ( cmap13->valid )
{
- gindex = cmap13->cur_gindex;
- if ( gindex )
- *pchar_code = cmap13->cur_charcode;
+ gindex = cmap13->cur_gindex;
+ *pchar_code = cmap13->cur_charcode;
}
else
gindex = 0;
@@ -2836,11 +2968,16 @@
/* through the normal Unicode cmap, no GIDs, just check order) */
if ( defOff != 0 )
{
- FT_Byte* defp = table + defOff;
- FT_ULong numRanges = TT_NEXT_ULONG( defp );
+ FT_Byte* defp = table + defOff;
+ FT_ULong numRanges;
FT_ULong i;
- FT_ULong lastBase = 0;
+ FT_ULong lastBase = 0;
+
+
+ if ( defp + 4 > valid->limit )
+ FT_INVALID_TOO_SHORT;
+ numRanges = TT_NEXT_ULONG( defp );
/* defp + numRanges * 4 > valid->limit ? */
if ( numRanges > (FT_ULong)( valid->limit - defp ) / 4 )
@@ -2865,13 +3002,18 @@
/* and the non-default table (these glyphs are specified here) */
if ( nondefOff != 0 )
{
- FT_Byte* ndp = table + nondefOff;
- FT_ULong numMappings = TT_NEXT_ULONG( ndp );
- FT_ULong i, lastUni = 0;
+ FT_Byte* ndp = table + nondefOff;
+ FT_ULong numMappings;
+ FT_ULong i, lastUni = 0;
+
+
+ if ( ndp + 4 > valid->limit )
+ FT_INVALID_TOO_SHORT;
+ numMappings = TT_NEXT_ULONG( ndp );
- /* numMappings * 4 > (FT_ULong)( valid->limit - ndp ) ? */
- if ( numMappings > ( (FT_ULong)( valid->limit - ndp ) ) / 4 )
+ /* numMappings * 5 > (FT_ULong)( valid->limit - ndp ) ? */
+ if ( numMappings > ( (FT_ULong)( valid->limit - ndp ) ) / 5 )
FT_INVALID_TOO_SHORT;
for ( i = 0; i < numMappings; ++i )
@@ -3316,7 +3458,7 @@
ni = 1;
i = 0;
- for ( ;; )
+ for (;;)
{
if ( nuni > duni + dcnt )
{
diff --git a/src/sfnt/ttload.c b/src/sfnt/ttload.c
index ad2975d..c1bd7f0 100644
--- a/src/sfnt/ttload.c
+++ b/src/sfnt/ttload.c
@@ -151,7 +151,8 @@
/* Here, we */
/* */
- /* - check that `num_tables' is valid (and adjust it if necessary) */
+ /* - check that `num_tables' is valid (and adjust it if necessary); */
+ /* also return the number of valid table entries */
/* */
/* - look for a `head' table, check its size, and parse it to check */
/* whether its `magic' field is correctly set */
@@ -167,7 +168,8 @@
/* */
static FT_Error
check_table_dir( SFNT_Header sfnt,
- FT_Stream stream )
+ FT_Stream stream,
+ FT_UShort* valid )
{
FT_Error error;
FT_UShort nn, valid_entries = 0;
@@ -209,7 +211,10 @@
/* we ignore invalid tables */
if ( table.Offset > stream->size )
+ {
+ FT_TRACE2(( "check_table_dir: table entry %d invalid\n", nn ));
continue;
+ }
else if ( table.Length > stream->size - table.Offset )
{
/* Some tables have such a simple structure that clipping its */
@@ -273,11 +278,11 @@
has_meta = 1;
}
- sfnt->num_tables = valid_entries;
+ *valid = valid_entries;
- if ( sfnt->num_tables == 0 )
+ if ( !valid_entries )
{
- FT_TRACE2(( "check_table_dir: no tables found\n" ));
+ FT_TRACE2(( "check_table_dir: no valid tables found\n" ));
error = FT_THROW( Unknown_File_Format );
goto Exit;
}
@@ -333,8 +338,7 @@
SFNT_HeaderRec sfnt;
FT_Error error;
FT_Memory memory = stream->memory;
- TT_TableRec* entry;
- FT_Int nn;
+ FT_UShort nn, valid_entries;
static const FT_Frame_Field offset_table_fields[] =
{
@@ -375,85 +379,114 @@
if ( sfnt.format_tag != TTAG_OTTO )
{
/* check first */
- error = check_table_dir( &sfnt, stream );
+ error = check_table_dir( &sfnt, stream, &valid_entries );
if ( error )
{
FT_TRACE2(( "tt_face_load_font_dir:"
" invalid table directory for TrueType\n" ));
-
goto Exit;
}
}
+ else
+ valid_entries = sfnt.num_tables;
- face->num_tables = sfnt.num_tables;
+ face->num_tables = valid_entries;
face->format_tag = sfnt.format_tag;
if ( FT_QNEW_ARRAY( face->dir_tables, face->num_tables ) )
goto Exit;
- if ( FT_STREAM_SEEK( sfnt.offset + 12 ) ||
- FT_FRAME_ENTER( face->num_tables * 16L ) )
+ if ( FT_STREAM_SEEK( sfnt.offset + 12 ) ||
+ FT_FRAME_ENTER( sfnt.num_tables * 16L ) )
goto Exit;
- entry = face->dir_tables;
-
FT_TRACE2(( "\n"
" tag offset length checksum\n"
" ----------------------------------\n" ));
+ valid_entries = 0;
for ( nn = 0; nn < sfnt.num_tables; nn++ )
{
- entry->Tag = FT_GET_TAG4();
- entry->CheckSum = FT_GET_ULONG();
- entry->Offset = FT_GET_ULONG();
- entry->Length = FT_GET_ULONG();
+ TT_TableRec entry;
+ FT_UShort i;
+ FT_Bool duplicate;
+
+
+ entry.Tag = FT_GET_TAG4();
+ entry.CheckSum = FT_GET_ULONG();
+ entry.Offset = FT_GET_ULONG();
+ entry.Length = FT_GET_ULONG();
/* ignore invalid tables that can't be sanitized */
- if ( entry->Offset > stream->size )
+ if ( entry.Offset > stream->size )
continue;
- else if ( entry->Length > stream->size - entry->Offset )
+ else if ( entry.Length > stream->size - entry.Offset )
{
- if ( entry->Tag == TTAG_hmtx ||
- entry->Tag == TTAG_vmtx )
+ if ( entry.Tag == TTAG_hmtx ||
+ entry.Tag == TTAG_vmtx )
{
#ifdef FT_DEBUG_LEVEL_TRACE
- FT_ULong old_length = entry->Length;
+ FT_ULong old_length = entry.Length;
#endif
/* make metrics table length a multiple of 4 */
- entry->Length = ( stream->size - entry->Offset ) & ~3U;
+ entry.Length = ( stream->size - entry.Offset ) & ~3U;
FT_TRACE2(( " %c%c%c%c %08lx %08lx %08lx"
- " (sanitized; original length %08lx)\n",
- (FT_Char)( entry->Tag >> 24 ),
- (FT_Char)( entry->Tag >> 16 ),
- (FT_Char)( entry->Tag >> 8 ),
- (FT_Char)( entry->Tag ),
- entry->Offset,
- entry->Length,
- entry->CheckSum,
+ " (sanitized; original length %08lx)",
+ (FT_Char)( entry.Tag >> 24 ),
+ (FT_Char)( entry.Tag >> 16 ),
+ (FT_Char)( entry.Tag >> 8 ),
+ (FT_Char)( entry.Tag ),
+ entry.Offset,
+ entry.Length,
+ entry.CheckSum,
old_length ));
- entry++;
}
else
continue;
}
+#ifdef FT_DEBUG_LEVEL_TRACE
+ else
+ FT_TRACE2(( " %c%c%c%c %08lx %08lx %08lx",
+ (FT_Char)( entry.Tag >> 24 ),
+ (FT_Char)( entry.Tag >> 16 ),
+ (FT_Char)( entry.Tag >> 8 ),
+ (FT_Char)( entry.Tag ),
+ entry.Offset,
+ entry.Length,
+ entry.CheckSum ));
+#endif
+
+ /* ignore duplicate tables – the first one wins */
+ duplicate = 0;
+ for ( i = 0; i < valid_entries; i++ )
+ {
+ if ( face->dir_tables[i].Tag == entry.Tag )
+ {
+ duplicate = 1;
+ break;
+ }
+ }
+ if ( duplicate )
+ {
+ FT_TRACE2(( " (duplicate, ignored)\n" ));
+ continue;
+ }
else
{
- FT_TRACE2(( " %c%c%c%c %08lx %08lx %08lx\n",
- (FT_Char)( entry->Tag >> 24 ),
- (FT_Char)( entry->Tag >> 16 ),
- (FT_Char)( entry->Tag >> 8 ),
- (FT_Char)( entry->Tag ),
- entry->Offset,
- entry->Length,
- entry->CheckSum ));
- entry++;
+ FT_TRACE2(( "\n" ));
+
+ /* we finally have a valid entry */
+ face->dir_tables[valid_entries++] = entry;
}
}
+ /* final adjustment to number of tables */
+ face->num_tables = valid_entries;
+
FT_FRAME_EXIT();
FT_TRACE2(( "table directory loaded\n\n" ));
diff --git a/src/sfnt/ttsbit.c b/src/sfnt/ttsbit.c
index 143f276..09260b8 100644
--- a/src/sfnt/ttsbit.c
+++ b/src/sfnt/ttsbit.c
@@ -104,7 +104,8 @@
version = FT_NEXT_LONG( p );
num_strikes = FT_NEXT_ULONG( p );
- if ( ( (FT_ULong)version & 0xFFFF0000UL ) != 0x00020000UL )
+ if ( ( (FT_ULong)version & 0xFFFF0000UL ) != 0x00020000UL &&
+ ( (FT_ULong)version & 0xFFFF0000UL ) != 0x00030000UL )
{
error = FT_THROW( Unknown_File_Format );
goto Exit;
@@ -247,6 +248,8 @@
case TT_SBIT_TABLE_TYPE_CBLC:
{
FT_Byte* strike;
+ FT_Char max_before_bl;
+ FT_Char min_after_bl;
strike = face->sbit_table + 8 + strike_index * 48;
@@ -254,26 +257,83 @@
metrics->x_ppem = (FT_UShort)strike[44];
metrics->y_ppem = (FT_UShort)strike[45];
- metrics->ascender = (FT_Char)strike[16] << 6; /* hori.ascender */
- metrics->descender = (FT_Char)strike[17] << 6; /* hori.descender */
- metrics->height = metrics->ascender - metrics->descender;
+ metrics->ascender = (FT_Char)strike[16] * 64; /* hori.ascender */
+ metrics->descender = (FT_Char)strike[17] * 64; /* hori.descender */
+
+ /* Due to fuzzy wording in the EBLC documentation, we find both */
+ /* positive and negative values for `descender'. Additionally, */
+ /* many fonts have both `ascender' and `descender' set to zero */
+ /* (which is definitely wrong). MS Windows simply ignores all */
+ /* those values... For these reasons we apply some heuristics */
+ /* to get a reasonable, non-zero value for the height. */
+
+ max_before_bl = (FT_Char)strike[24];
+ min_after_bl = (FT_Char)strike[25];
+
+ if ( metrics->descender > 0 )
+ {
+ /* compare sign of descender with `min_after_bl' */
+ if ( min_after_bl < 0 )
+ metrics->descender = -metrics->descender;
+ }
+
+ else if ( metrics->descender == 0 )
+ {
+ if ( metrics->ascender == 0 )
+ {
+ FT_TRACE2(( "tt_face_load_strike_metrics:"
+ " sanitizing invalid ascender and descender\n"
+ " "
+ " values for strike (%d, %d)\n",
+ metrics->x_ppem, metrics->y_ppem ));
+
+ /* sanitize buggy ascender and descender values */
+ if ( max_before_bl || min_after_bl )
+ {
+ metrics->ascender = max_before_bl * 64;
+ metrics->descender = min_after_bl * 64;
+ }
+ else
+ {
+ metrics->ascender = metrics->y_ppem * 64;
+ metrics->descender = 0;
+ }
+ }
+ }
+
+#if 0
+ else
+ ; /* if we have a negative descender, simply use it */
+#endif
+
+ metrics->height = metrics->ascender - metrics->descender;
+ if ( metrics->height == 0 )
+ {
+ FT_TRACE2(( "tt_face_load_strike_metrics:"
+ " sanitizing invalid height value\n"
+ " "
+ " for strike (%d, %d)\n",
+ metrics->x_ppem, metrics->y_ppem ));
+ metrics->height = metrics->y_ppem * 64;
+ metrics->descender = metrics->ascender - metrics->height;
+ }
/* Is this correct? */
metrics->max_advance = ( (FT_Char)strike[22] + /* min_origin_SB */
strike[18] + /* max_width */
(FT_Char)strike[23] /* min_advance_SB */
- ) << 6;
+ ) * 64;
return FT_Err_Ok;
}
case TT_SBIT_TABLE_TYPE_SBIX:
{
FT_Stream stream = face->root.stream;
- FT_UInt offset, upem;
- FT_UShort ppem, resolution;
+ FT_UInt offset;
+ FT_UShort upem, ppem, resolution;
TT_HoriHeader *hori;
FT_ULong table_size;
- FT_Pos ppem_, upem_; /* to reduce casts */
+ FT_Pos ppem_; /* to reduce casts */
FT_Error error;
FT_Byte* p;
@@ -307,14 +367,16 @@
metrics->y_ppem = ppem;
ppem_ = (FT_Pos)ppem;
- upem_ = (FT_Pos)upem;
- metrics->ascender = ppem_ * hori->Ascender * 64 / upem_;
- metrics->descender = ppem_ * hori->Descender * 64 / upem_;
- metrics->height = ppem_ * ( hori->Ascender -
- hori->Descender +
- hori->Line_Gap ) * 64 / upem_;
- metrics->max_advance = ppem_ * hori->advance_Width_Max * 64 / upem_;
+ metrics->ascender =
+ FT_MulDiv( hori->Ascender, ppem_ * 64, upem );
+ metrics->descender =
+ FT_MulDiv( hori->Descender, ppem_ * 64, upem );
+ metrics->height =
+ FT_MulDiv( hori->Ascender - hori->Descender + hori->Line_Gap,
+ ppem_ * 64, upem );
+ metrics->max_advance =
+ FT_MulDiv( hori->advance_Width_Max, ppem_ * 64, upem );
return error;
}
@@ -547,13 +609,16 @@
tt_sbit_decoder_load_image( TT_SBitDecoder decoder,
FT_UInt glyph_index,
FT_Int x_pos,
- FT_Int y_pos );
+ FT_Int y_pos,
+ FT_UInt recurse_count );
- typedef FT_Error (*TT_SBitDecoder_LoadFunc)( TT_SBitDecoder decoder,
- FT_Byte* p,
- FT_Byte* plimit,
- FT_Int x_pos,
- FT_Int y_pos );
+ typedef FT_Error (*TT_SBitDecoder_LoadFunc)(
+ TT_SBitDecoder decoder,
+ FT_Byte* p,
+ FT_Byte* plimit,
+ FT_Int x_pos,
+ FT_Int y_pos,
+ FT_UInt recurse_count );
static FT_Error
@@ -561,7 +626,8 @@
FT_Byte* p,
FT_Byte* limit,
FT_Int x_pos,
- FT_Int y_pos )
+ FT_Int y_pos,
+ FT_UInt recurse_count )
{
FT_Error error = FT_Err_Ok;
FT_Byte* line;
@@ -569,6 +635,8 @@
FT_UInt bit_height, bit_width;
FT_Bitmap* bitmap;
+ FT_UNUSED( recurse_count );
+
/* check that we can write the glyph into the bitmap */
bitmap = decoder->bitmap;
@@ -700,7 +768,8 @@
FT_Byte* p,
FT_Byte* limit,
FT_Int x_pos,
- FT_Int y_pos )
+ FT_Int y_pos,
+ FT_UInt recurse_count )
{
FT_Error error = FT_Err_Ok;
FT_Byte* line;
@@ -709,6 +778,8 @@
FT_Bitmap* bitmap;
FT_UShort rval;
+ FT_UNUSED( recurse_count );
+
/* check that we can write the glyph into the bitmap */
bitmap = decoder->bitmap;
@@ -738,6 +809,12 @@
goto Exit;
}
+ if ( !line_bits || !height )
+ {
+ /* nothing to do */
+ goto Exit;
+ }
+
/* now do the blit */
/* adjust `line' to point to the first byte of the bitmap */
@@ -824,7 +901,8 @@
FT_Byte* p,
FT_Byte* limit,
FT_Int x_pos,
- FT_Int y_pos )
+ FT_Int y_pos,
+ FT_UInt recurse_count )
{
FT_Error error = FT_Err_Ok;
FT_UInt num_components, nn;
@@ -858,8 +936,11 @@
/* NB: a recursive call */
- error = tt_sbit_decoder_load_image( decoder, gindex,
- x_pos + dx, y_pos + dy );
+ error = tt_sbit_decoder_load_image( decoder,
+ gindex,
+ x_pos + dx,
+ y_pos + dy,
+ recurse_count + 1 );
if ( error )
break;
}
@@ -891,11 +972,14 @@
FT_Byte* p,
FT_Byte* limit,
FT_Int x_pos,
- FT_Int y_pos )
+ FT_Int y_pos,
+ FT_UInt recurse_count )
{
FT_Error error = FT_Err_Ok;
FT_ULong png_len;
+ FT_UNUSED( recurse_count );
+
if ( limit - p < 4 )
{
@@ -937,7 +1021,8 @@
FT_ULong glyph_start,
FT_ULong glyph_size,
FT_Int x_pos,
- FT_Int y_pos )
+ FT_Int y_pos,
+ FT_UInt recurse_count )
{
FT_Error error;
FT_Stream stream = decoder->stream;
@@ -947,7 +1032,8 @@
/* seek into the EBDT table now */
- if ( glyph_start + glyph_size > decoder->ebdt_size )
+ if ( !glyph_size ||
+ glyph_start + glyph_size > decoder->ebdt_size )
{
error = FT_THROW( Invalid_Argument );
goto Exit;
@@ -1063,7 +1149,7 @@
goto Fail;
}
- error = loader( decoder, p, p_limit, x_pos, y_pos );
+ error = loader( decoder, p, p_limit, x_pos, y_pos, recurse_count );
}
Fail:
@@ -1078,13 +1164,9 @@
tt_sbit_decoder_load_image( TT_SBitDecoder decoder,
FT_UInt glyph_index,
FT_Int x_pos,
- FT_Int y_pos )
+ FT_Int y_pos,
+ FT_UInt recurse_count )
{
- /*
- * First, we find the correct strike range that applies to this
- * glyph index.
- */
-
FT_Byte* p = decoder->eblc_base + decoder->strike_index_array;
FT_Byte* p_limit = decoder->eblc_limit;
FT_ULong num_ranges = decoder->strike_index_count;
@@ -1092,6 +1174,17 @@
FT_ULong image_start = 0, image_end = 0, image_offset;
+ /* arbitrary recursion limit */
+ if ( recurse_count > 100 )
+ {
+ FT_TRACE4(( "tt_sbit_decoder_load_image:"
+ " recursion depth exceeded\n" ));
+ goto Failure;
+ }
+
+
+ /* First, we find the correct strike range that applies to this */
+ /* glyph index. */
for ( ; num_ranges > 0; num_ranges-- )
{
start = FT_NEXT_USHORT( p );
@@ -1256,7 +1349,8 @@
image_start,
image_end,
x_pos,
- y_pos );
+ y_pos,
+ recurse_count );
Failure:
return FT_THROW( Invalid_Table );
@@ -1419,6 +1513,7 @@
error = tt_sbit_decoder_load_image( decoder,
glyph_index,
0,
+ 0,
0 );
tt_sbit_decoder_done( decoder );
}
diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c
index 77b58f2..9a43c07 100644
--- a/src/smooth/ftgrays.c
+++ b/src/smooth/ftgrays.c
@@ -24,8 +24,8 @@
/* */
/* - copy `src/smooth/ftgrays.c' (this file) to your current directory */
/* */
- /* - copy `include/ftimage.h' and `src/smooth/ftgrays.h' to the same */
- /* directory */
+ /* - copy `include/freetype/ftimage.h' and `src/smooth/ftgrays.h' to the */
+ /* same directory */
/* */
/* - compile `ftgrays' with the _STANDALONE_ macro defined, as in */
/* */
@@ -135,8 +135,10 @@
#include <string.h>
#include <setjmp.h>
#include <limits.h>
-#define FT_UINT_MAX UINT_MAX
-#define FT_INT_MAX INT_MAX
+#define FT_CHAR_BIT CHAR_BIT
+#define FT_UINT_MAX UINT_MAX
+#define FT_INT_MAX INT_MAX
+#define FT_ULONG_MAX ULONG_MAX
#define ft_memset memset
@@ -317,7 +319,6 @@ typedef ptrdiff_t FT_PtrDist;
#undef SCALED
#define ONE_PIXEL ( 1L << PIXEL_BITS )
-#define PIXEL_MASK ( -1L << PIXEL_BITS )
#define TRUNC( x ) ( (TCoord)( (x) >> PIXEL_BITS ) )
#define SUBPIXELS( x ) ( (TPos)(x) << PIXEL_BITS )
#define FLOOR( x ) ( (x) & -ONE_PIXEL )
@@ -367,6 +368,15 @@ typedef ptrdiff_t FT_PtrDist;
#endif /* __arm__ */
+ /* These macros speed up repetitive divisions by replacing them */
+ /* with multiplications and right shifts. */
+#define FT_UDIVPREP( b ) \
+ long b ## _r = (long)( FT_ULONG_MAX >> PIXEL_BITS ) / ( b )
+#define FT_UDIV( a, b ) \
+ ( ( (unsigned long)( a ) * (unsigned long)( b ## _r ) ) >> \
+ ( sizeof( long ) * FT_CHAR_BIT - PIXEL_BITS ) )
+
+
/*************************************************************************/
/* */
/* TYPE DEFINITIONS */
@@ -440,11 +450,8 @@ typedef ptrdiff_t FT_PtrDist;
FT_PtrDist max_cells;
FT_PtrDist num_cells;
- TCoord cx, cy;
TPos x, y;
- TPos last_ey;
-
FT_Vector bez_stack[32 * 3 + 1];
int lev_stack[32];
@@ -677,12 +684,12 @@ typedef ptrdiff_t FT_PtrDist;
ras.cover = 0;
ras.ex = ex - ras.min_ex;
ras.ey = ey - ras.min_ey;
- ras.last_ey = SUBPIXELS( ey );
ras.invalid = 0;
gray_set_cell( RAS_VAR_ ex, ey );
}
+#if 0
/*************************************************************************/
/* */
@@ -758,7 +765,7 @@ typedef ptrdiff_t FT_PtrDist;
mod -= (int)dx;
- while ( ex1 != ex2 )
+ do
{
delta = lift;
mod += rem;
@@ -773,7 +780,7 @@ typedef ptrdiff_t FT_PtrDist;
y1 += delta;
ex1 += incr;
gray_set_cell( RAS_VAR_ ex1, ey );
- }
+ } while ( ex1 != ex2 );
}
delta = y2 - y1;
@@ -796,29 +803,18 @@ typedef ptrdiff_t FT_PtrDist;
int delta, rem, lift, incr;
- ey1 = TRUNC( ras.last_ey );
+ ey1 = TRUNC( ras.y );
ey2 = TRUNC( to_y ); /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */
- fy1 = (TCoord)( ras.y - ras.last_ey );
+ fy1 = (TCoord)( ras.y - SUBPIXELS( ey1 ) );
fy2 = (TCoord)( to_y - SUBPIXELS( ey2 ) );
dx = to_x - ras.x;
dy = to_y - ras.y;
/* perform vertical clipping */
- {
- TCoord min, max;
-
-
- min = ey1;
- max = ey2;
- if ( ey1 > ey2 )
- {
- min = ey2;
- max = ey1;
- }
- if ( min >= ras.max_ey || max < ras.min_ey )
- goto End;
- }
+ if ( ( ey1 >= ras.max_ey && ey2 >= ras.max_ey ) ||
+ ( ey1 < ras.min_ey && ey2 < ras.min_ey ) )
+ goto End;
/* everything is on a single scanline */
if ( ey1 == ey2 )
@@ -896,7 +892,7 @@ typedef ptrdiff_t FT_PtrDist;
FT_DIV_MOD( int, p, dy, lift, rem );
mod -= (int)dy;
- while ( ey1 != ey2 )
+ do
{
delta = lift;
mod += rem;
@@ -914,7 +910,7 @@ typedef ptrdiff_t FT_PtrDist;
ey1 += incr;
gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );
- }
+ } while ( ey1 != ey2 );
}
gray_render_scanline( RAS_VAR_ ey1, x,
@@ -924,9 +920,145 @@ typedef ptrdiff_t FT_PtrDist;
End:
ras.x = to_x;
ras.y = to_y;
- ras.last_ey = SUBPIXELS( ey2 );
}
+#else
+
+ /*************************************************************************/
+ /* */
+ /* Render a straight line across multiple cells in any direction. */
+ /* */
+ static void
+ gray_render_line( RAS_ARG_ TPos to_x,
+ TPos to_y )
+ {
+ TPos dx, dy, fx1, fy1, fx2, fy2;
+ TCoord ex1, ex2, ey1, ey2;
+
+
+ ex1 = TRUNC( ras.x );
+ ex2 = TRUNC( to_x );
+ ey1 = TRUNC( ras.y );
+ ey2 = TRUNC( to_y );
+
+ /* perform vertical clipping */
+ if ( ( ey1 >= ras.max_ey && ey2 >= ras.max_ey ) ||
+ ( ey1 < ras.min_ey && ey2 < ras.min_ey ) )
+ goto End;
+
+ dx = to_x - ras.x;
+ dy = to_y - ras.y;
+
+ fx1 = ras.x - SUBPIXELS( ex1 );
+ fy1 = ras.y - SUBPIXELS( ey1 );
+
+ if ( ex1 == ex2 && ey1 == ey2 ) /* inside one cell */
+ ;
+ else if ( dy == 0 ) /* ex1 != ex2 */ /* any horizontal line */
+ {
+ ex1 = ex2;
+ gray_set_cell( RAS_VAR_ ex1, ey1 );
+ }
+ else if ( dx == 0 )
+ {
+ if ( dy > 0 ) /* vertical line up */
+ do
+ {
+ fy2 = ONE_PIXEL;
+ ras.cover += ( fy2 - fy1 );
+ ras.area += ( fy2 - fy1 ) * fx1 * 2;
+ fy1 = 0;
+ ey1++;
+ gray_set_cell( RAS_VAR_ ex1, ey1 );
+ } while ( ey1 != ey2 );
+ else /* vertical line down */
+ do
+ {
+ fy2 = 0;
+ ras.cover += ( fy2 - fy1 );
+ ras.area += ( fy2 - fy1 ) * fx1 * 2;
+ fy1 = ONE_PIXEL;
+ ey1--;
+ gray_set_cell( RAS_VAR_ ex1, ey1 );
+ } while ( ey1 != ey2 );
+ }
+ else /* any other line */
+ {
+ TArea prod = dx * fy1 - dy * fx1;
+ FT_UDIVPREP( dx );
+ FT_UDIVPREP( dy );
+
+
+ /* The fundamental value `prod' determines which side and the */
+ /* exact coordinate where the line exits current cell. It is */
+ /* also easily updated when moving from one cell to the next. */
+ do
+ {
+ if ( prod <= 0 &&
+ prod - dx * ONE_PIXEL > 0 ) /* left */
+ {
+ fx2 = 0;
+ fy2 = (TPos)FT_UDIV( -prod, -dx );
+ prod -= dy * ONE_PIXEL;
+ ras.cover += ( fy2 - fy1 );
+ ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
+ fx1 = ONE_PIXEL;
+ fy1 = fy2;
+ ex1--;
+ }
+ else if ( prod - dx * ONE_PIXEL <= 0 &&
+ prod - dx * ONE_PIXEL + dy * ONE_PIXEL > 0 ) /* up */
+ {
+ prod -= dx * ONE_PIXEL;
+ fx2 = (TPos)FT_UDIV( -prod, dy );
+ fy2 = ONE_PIXEL;
+ ras.cover += ( fy2 - fy1 );
+ ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
+ fx1 = fx2;
+ fy1 = 0;
+ ey1++;
+ }
+ else if ( prod - dx * ONE_PIXEL + dy * ONE_PIXEL <= 0 &&
+ prod + dy * ONE_PIXEL >= 0 ) /* right */
+ {
+ prod += dy * ONE_PIXEL;
+ fx2 = ONE_PIXEL;
+ fy2 = (TPos)FT_UDIV( prod, dx );
+ ras.cover += ( fy2 - fy1 );
+ ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
+ fx1 = 0;
+ fy1 = fy2;
+ ex1++;
+ }
+ else /* ( prod + dy * ONE_PIXEL < 0 &&
+ prod > 0 ) down */
+ {
+ fx2 = (TPos)FT_UDIV( prod, -dy );
+ fy2 = 0;
+ prod += dx * ONE_PIXEL;
+ ras.cover += ( fy2 - fy1 );
+ ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
+ fx1 = fx2;
+ fy1 = ONE_PIXEL;
+ ey1--;
+ }
+
+ gray_set_cell( RAS_VAR_ ex1, ey1 );
+ } while ( ex1 != ex2 || ey1 != ey2 );
+ }
+
+ fx2 = to_x - SUBPIXELS( ex2 );
+ fy2 = to_y - SUBPIXELS( ey2 );
+
+ ras.cover += ( fy2 - fy1 );
+ ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
+
+ End:
+ ras.x = to_x;
+ ras.y = to_y;
+ }
+
+#endif
static void
gray_split_conic( FT_Vector* base )
@@ -1847,7 +1979,7 @@ typedef ptrdiff_t FT_PtrDist;
bands[0].max = max;
band = bands;
- while ( band >= bands )
+ do
{
TPos bottom, top, middle;
int error;
@@ -1923,7 +2055,7 @@ typedef ptrdiff_t FT_PtrDist;
band[0].min = middle;
band[0].max = top;
band++;
- }
+ } while ( band >= bands );
}
if ( ras.band_shoot > 8 && ras.band_size > 16 )
diff --git a/src/smooth/ftspic.h b/src/smooth/ftspic.h
index 99b9f0e..071afcf 100644
--- a/src/smooth/ftspic.h
+++ b/src/smooth/ftspic.h
@@ -20,10 +20,11 @@
#define __FTSPIC_H__
-FT_BEGIN_HEADER
-
#include FT_INTERNAL_PIC_H
+
+FT_BEGIN_HEADER
+
#ifndef FT_CONFIG_OPTION_PIC
#define FT_GRAYS_RASTER_GET ft_grays_raster
diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c
index 08b30c9..1ba71f0 100644
--- a/src/truetype/ttdriver.c
+++ b/src/truetype/ttdriver.c
@@ -117,8 +117,8 @@
FT_DEFINE_SERVICE_PROPERTIESREC(
tt_service_properties,
- (FT_Properties_SetFunc)tt_property_set,
- (FT_Properties_GetFunc)tt_property_get )
+ (FT_Properties_SetFunc)tt_property_set, /* set_property */
+ (FT_Properties_GetFunc)tt_property_get ) /* get_property */
/*************************************************************************/
@@ -417,13 +417,14 @@
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
FT_DEFINE_SERVICE_MULTIMASTERSREC(
tt_service_gx_multi_masters,
- (FT_Get_MM_Func) NULL,
- (FT_Set_MM_Design_Func) NULL,
- (FT_Set_MM_Blend_Func) TT_Set_MM_Blend,
- (FT_Get_MM_Var_Func) TT_Get_MM_Var,
- (FT_Set_Var_Design_Func)TT_Set_Var_Design )
+ (FT_Get_MM_Func) NULL, /* get_mm */
+ (FT_Set_MM_Design_Func) NULL, /* set_mm_design */
+ (FT_Set_MM_Blend_Func) TT_Set_MM_Blend, /* set_mm_blend */
+ (FT_Get_MM_Var_Func) TT_Get_MM_Var, /* get_mm_var */
+ (FT_Set_Var_Design_Func)TT_Set_Var_Design ) /* set_var_design */
#endif
+
static const FT_Service_TrueTypeEngineRec tt_service_truetype_engine =
{
#ifdef TT_USE_BYTECODE_INTERPRETER
@@ -441,9 +442,11 @@
#endif /* TT_USE_BYTECODE_INTERPRETER */
};
+
FT_DEFINE_SERVICE_TTGLYFREC(
tt_service_truetype_glyf,
- (TT_Glyf_GetLocationFunc)tt_face_get_location )
+ (TT_Glyf_GetLocationFunc)tt_face_get_location ) /* get_location */
+
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
FT_DEFINE_SERVICEDESCREC5(
@@ -534,31 +537,31 @@
0x10000L, /* driver version == 1.0 */
0x20000L, /* driver requires FreeType 2.0 or above */
- (void*)0, /* driver specific interface */
+ 0, /* module-specific interface */
- tt_driver_init,
- tt_driver_done,
- tt_get_interface,
+ tt_driver_init, /* FT_Module_Constructor module_init */
+ tt_driver_done, /* FT_Module_Destructor module_done */
+ tt_get_interface, /* FT_Module_Requester get_interface */
sizeof ( TT_FaceRec ),
sizeof ( TT_SizeRec ),
sizeof ( FT_GlyphSlotRec ),
- tt_face_init,
- tt_face_done,
- tt_size_init,
- tt_size_done,
- tt_slot_init,
- 0, /* FT_Slot_DoneFunc */
+ tt_face_init, /* FT_Face_InitFunc init_face */
+ tt_face_done, /* FT_Face_DoneFunc done_face */
+ tt_size_init, /* FT_Size_InitFunc init_size */
+ tt_size_done, /* FT_Size_DoneFunc done_size */
+ tt_slot_init, /* FT_Slot_InitFunc init_slot */
+ 0, /* FT_Slot_DoneFunc done_slot */
- tt_glyph_load,
+ tt_glyph_load, /* FT_Slot_LoadFunc load_glyph */
- tt_get_kerning,
- 0, /* FT_Face_AttachFunc */
- tt_get_advances,
+ tt_get_kerning, /* FT_Face_GetKerningFunc get_kerning */
+ 0, /* FT_Face_AttachFunc attach_file */
+ tt_get_advances, /* FT_Face_GetAdvancesFunc get_advances */
- tt_size_request,
- TT_SIZE_SELECT
+ tt_size_request, /* FT_Size_RequestFunc request_size */
+ TT_SIZE_SELECT /* FT_Size_SelectFunc select_size */
)
diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c
index e1acd69..d94fc92 100644
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -24,6 +24,7 @@
#include FT_TRUETYPE_TAGS_H
#include FT_OUTLINE_H
#include FT_TRUETYPE_DRIVER_H
+#include FT_LIST_H
#include "ttgload.h"
#include "ttpload.h"
@@ -120,7 +121,7 @@
tt_get_metrics( TT_Loader loader,
FT_UInt glyph_index )
{
- TT_Face face = (TT_Face)loader->face;
+ TT_Face face = loader->face;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
#endif
@@ -182,7 +183,7 @@
tt_get_metrics_incr_overrides( TT_Loader loader,
FT_UInt glyph_index )
{
- TT_Face face = (TT_Face)loader->face;
+ TT_Face face = loader->face;
FT_Short left_bearing = 0, top_bearing = 0;
FT_UShort advance_width = 0, advance_height = 0;
@@ -250,29 +251,6 @@
/*************************************************************************/
/* */
- /* Translates an array of coordinates. */
- /* */
- static void
- translate_array( FT_UInt n,
- FT_Vector* coords,
- FT_Pos delta_x,
- FT_Pos delta_y )
- {
- FT_UInt k;
-
-
- if ( delta_x )
- for ( k = 0; k < n; k++ )
- coords[k].x += delta_x;
-
- if ( delta_y )
- for ( k = 0; k < n; k++ )
- coords[k].y += delta_y;
- }
-
-
- /*************************************************************************/
- /* */
/* The following functions are used by default with TrueType fonts. */
/* However, they can be replaced by alternatives if we need to support */
/* TrueType-compressed formats (like MicroType) in the future. */
@@ -656,20 +634,20 @@
if ( subglyph->flags & WE_HAVE_A_SCALE )
{
- xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
+ xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
yy = xx;
}
else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
{
- xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
- yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
+ xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
+ yy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
}
else if ( subglyph->flags & WE_HAVE_A_2X2 )
{
- xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
- yx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
- xy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
- yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
+ xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
+ yx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
+ xy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
+ yy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
}
subglyph->transform.xx = xx;
@@ -682,6 +660,7 @@
} while ( subglyph->flags & MORE_COMPONENTS );
gloader->current.num_subglyphs = num_subglyphs;
+ FT_TRACE5(( " %d components\n", num_subglyphs ));
#ifdef TT_USE_BYTECODE_INTERPRETER
@@ -754,7 +733,7 @@
FT_Bool is_composite )
{
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- TT_Face face = (TT_Face)loader->face;
+ TT_Face face = loader->face;
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
#endif
@@ -781,7 +760,7 @@
FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points );
/* Reset graphics state. */
- loader->exec->GS = ((TT_Size)loader->size)->GS;
+ loader->exec->GS = loader->size->GS;
/* XXX: UNDOCUMENTED! Hinting instructions of a composite glyph */
/* completely refer to the (already) hinted subglyphs. */
@@ -794,10 +773,8 @@
}
else
{
- loader->exec->metrics.x_scale =
- ((TT_Size)loader->size)->metrics.x_scale;
- loader->exec->metrics.y_scale =
- ((TT_Size)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
@@ -897,13 +874,13 @@
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- if ( ((TT_Face)loader->face)->doblend )
+ if ( loader->face->doblend )
{
/* Deltas apply to the unscaled data. */
- error = TT_Vary_Apply_Glyph_Deltas( (TT_Face)(loader->face),
- loader->glyph_index,
- outline,
- (FT_UInt)n_points );
+ error = TT_Vary_Apply_Glyph_Deltas( loader->face,
+ loader->glyph_index,
+ outline,
+ (FT_UInt)n_points );
if ( error )
return error;
}
@@ -920,7 +897,7 @@
{
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- TT_Face face = (TT_Face)loader->face;
+ TT_Face face = loader->face;
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
FT_String* family = face->root.family_name;
@@ -953,9 +930,9 @@
if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ||
x_scale_factor != 1000 )
{
- x_scale = FT_MulDiv( ((TT_Size)loader->size)->metrics.x_scale,
+ x_scale = FT_MulDiv( loader->size->metrics.x_scale,
(FT_Long)x_scale_factor, 1000 );
- y_scale = ((TT_Size)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 */
@@ -975,8 +952,8 @@
/* scale the glyph */
if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
{
- x_scale = ((TT_Size)loader->size)->metrics.x_scale;
- y_scale = ((TT_Size)loader->size)->metrics.y_scale;
+ x_scale = loader->size->metrics.x_scale;
+ y_scale = loader->size->metrics.y_scale;
do_scale = TRUE;
}
@@ -1023,30 +1000,29 @@
FT_UInt start_point,
FT_UInt num_base_points )
{
- FT_GlyphLoader gloader = loader->gloader;
- FT_Vector* base_vec = gloader->base.outline.points;
- FT_UInt num_points = (FT_UInt)gloader->base.outline.n_points;
+ FT_GlyphLoader gloader = loader->gloader;
+ FT_Outline current;
FT_Bool have_scale;
FT_Pos x, y;
+ current.points = gloader->base.outline.points +
+ num_base_points;
+ current.n_points = gloader->base.outline.n_points -
+ (short)num_base_points;
+
have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE |
WE_HAVE_AN_XY_SCALE |
WE_HAVE_A_2X2 ) );
/* perform the transform required for this subglyph */
if ( have_scale )
- {
- FT_UInt i;
-
-
- for ( i = num_base_points; i < num_points; i++ )
- FT_Vector_Transform( base_vec + i, &subglyph->transform );
- }
+ FT_Outline_Transform( &current, &subglyph->transform );
/* get offset */
if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
{
+ FT_UInt num_points = (FT_UInt)gloader->base.outline.n_points;
FT_UInt k = (FT_UInt)subglyph->arg1;
FT_UInt l = (FT_UInt)subglyph->arg2;
FT_Vector* p1;
@@ -1135,8 +1111,8 @@
if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
{
- FT_Fixed x_scale = ((TT_Size)loader->size)->metrics.x_scale;
- FT_Fixed y_scale = ((TT_Size)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 );
@@ -1151,9 +1127,7 @@
}
if ( x || y )
- translate_array( num_points - num_base_points,
- base_vec + num_base_points,
- x, y );
+ FT_Outline_Translate( &current, x, y );
return FT_Err_Ok;
}
@@ -1215,7 +1189,7 @@
FT_TRACE5(( " Instructions size = %d\n", n_ins ));
/* check it */
- max_ins = ((TT_Face)loader->face)->max_profile.maxSizeOfInstructions;
+ max_ins = loader->face->max_profile.maxSizeOfInstructions;
if ( n_ins > max_ins )
{
/* don't trust `maxSizeOfInstructions'; */
@@ -1412,7 +1386,7 @@
FT_Error error = FT_Err_Ok;
FT_Fixed x_scale, y_scale;
FT_ULong offset;
- TT_Face face = (TT_Face)loader->face;
+ TT_Face face = loader->face;
FT_GlyphLoader gloader = loader->gloader;
FT_Bool opened_frame = 0;
@@ -1423,6 +1397,11 @@
#endif
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( recurse_count )
+ FT_TRACE5(( " nesting level: %d\n", recurse_count ));
+#endif
+
/* some fonts have an incorrect value of `maxComponentDepth', */
/* thus we allow depth 1 to catch the majority of them */
if ( recurse_count > 1 &&
@@ -1445,8 +1424,8 @@
if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
{
- x_scale = ((TT_Size)loader->size)->metrics.x_scale;
- y_scale = ((TT_Size)loader->size)->metrics.y_scale;
+ x_scale = loader->size->metrics.x_scale;
+ y_scale = loader->size->metrics.y_scale;
}
else
{
@@ -1552,7 +1531,7 @@
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- if ( ((TT_Face)(loader->face))->doblend )
+ if ( loader->face->doblend )
{
/* a small outline structure with four elements for */
/* communication with `TT_Vary_Apply_Glyph_Deltas' */
@@ -1579,10 +1558,10 @@
outline.contours = contours;
/* this must be done before scaling */
- error = TT_Vary_Apply_Glyph_Deltas( (TT_Face)(loader->face),
- glyph_index,
- &outline,
- outline.n_points );
+ error = TT_Vary_Apply_Glyph_Deltas( loader->face,
+ glyph_index,
+ &outline,
+ (FT_UInt)outline.n_points );
if ( error )
goto Exit;
@@ -1655,11 +1634,40 @@
/* otherwise, load a composite! */
else if ( loader->n_contours == -1 )
{
+ FT_Memory memory = face->root.memory;
+
FT_UInt start_point;
FT_UInt start_contour;
FT_ULong ins_pos; /* position of composite instructions, if any */
+ /*
+ * We store the glyph index directly in the `node->data' pointer,
+ * following the glib solution (cf. macro `GUINT_TO_POINTER') with a
+ * double cast to make this portable. Note, however, that this needs
+ * pointers with a width of at least 32 bits.
+ */
+
+ /* check whether we already have a composite glyph with this index */
+ if ( FT_List_Find( &loader->composites,
+ (void*)(unsigned long)glyph_index ) )
+ {
+ FT_TRACE1(( "TT_Load_Composite_Glyph:"
+ " infinite recursion detected\n" ));
+ error = FT_THROW( Invalid_Composite );
+ goto Exit;
+ }
+ else
+ {
+ FT_ListNode node = NULL;
+
+
+ if ( FT_NEW( node ) )
+ goto Exit;
+ node->data = (void*)(unsigned long)glyph_index;
+ FT_List_Add( &loader->composites, node );
+ }
+
start_point = (FT_UInt)gloader->base.outline.n_points;
start_contour = (FT_UInt)gloader->base.outline.n_contours;
@@ -1679,7 +1687,7 @@
if ( face->doblend )
{
- FT_UInt i, limit;
+ short i, limit;
FT_SubGlyph subglyph;
FT_Outline outline;
@@ -1687,14 +1695,12 @@
char* tags = NULL;
short* contours = NULL;
- FT_Memory memory = face->root.memory;
-
- limit = gloader->current.num_subglyphs;
+ limit = (short)gloader->current.num_subglyphs;
/* construct an outline structure for */
/* communication with `TT_Vary_Apply_Glyph_Deltas' */
- outline.n_points = gloader->current.num_subglyphs + 4;
+ outline.n_points = (short)( gloader->current.num_subglyphs + 4 );
outline.n_contours = outline.n_points;
if ( FT_NEW_ARRAY( points, outline.n_points ) ||
@@ -1702,7 +1708,7 @@
FT_NEW_ARRAY( contours, outline.n_points ) )
goto Exit1;
- subglyph = gloader->current.subglyphs + gloader->base.num_subglyphs;
+ subglyph = gloader->current.subglyphs;
for ( i = 0; i < limit; i++, subglyph++ )
{
@@ -1748,10 +1754,10 @@
face,
glyph_index,
&outline,
- outline.n_points ) ) != 0 )
+ (FT_UInt)outline.n_points ) ) != 0 )
goto Exit1;
- subglyph = gloader->current.subglyphs + gloader->base.num_subglyphs;
+ subglyph = gloader->current.subglyphs;
for ( i = 0; i < limit; i++, subglyph++ )
{
@@ -1935,7 +1941,7 @@
compute_glyph_metrics( TT_Loader loader,
FT_UInt glyph_index )
{
- TT_Face face = (TT_Face)loader->face;
+ TT_Face face = loader->face;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
#endif
@@ -1943,7 +1949,7 @@
FT_BBox bbox;
FT_Fixed y_scale;
TT_GlyphSlot glyph = loader->glyph;
- TT_Size size = (TT_Size)loader->size;
+ TT_Size size = loader->size;
y_scale = 0x10000L;
@@ -1964,8 +1970,10 @@
glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
/* adjust advance width to the value contained in the hdmx table */
- if ( !face->postscript.isFixedPitch &&
- IS_HINTED( loader->load_flags ) )
+ /* unless FT_LOAD_COMPUTE_METRICS is set */
+ if ( !face->postscript.isFixedPitch &&
+ IS_HINTED( loader->load_flags ) &&
+ !( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) )
{
FT_Byte* widthp;
@@ -1988,7 +1996,7 @@
( ( ignore_x_mode && loader->exec->compatible_widths ) ||
!ignore_x_mode ||
SPH_OPTION_BITMAP_WIDTHS ) )
- glyph->metrics.horiAdvance = *widthp << 6;
+ glyph->metrics.horiAdvance = *widthp * 64;
}
else
@@ -1996,7 +2004,7 @@
{
if ( widthp )
- glyph->metrics.horiAdvance = *widthp << 6;
+ glyph->metrics.horiAdvance = *widthp * 64;
}
}
@@ -2136,16 +2144,16 @@
glyph->outline.n_points = 0;
glyph->outline.n_contours = 0;
- glyph->metrics.width = (FT_Pos)metrics.width << 6;
- glyph->metrics.height = (FT_Pos)metrics.height << 6;
+ glyph->metrics.width = (FT_Pos)metrics.width * 64;
+ glyph->metrics.height = (FT_Pos)metrics.height * 64;
- glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
- glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
- glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6;
+ 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.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
- glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
- glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6;
+ 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->format = FT_GLYPH_FORMAT_BITMAP;
@@ -2414,15 +2422,28 @@
loader->load_flags = (FT_ULong)load_flags;
- loader->face = (FT_Face)face;
- loader->size = (FT_Size)size;
+ loader->face = face;
+ loader->size = size;
loader->glyph = (FT_GlyphSlot)glyph;
loader->stream = stream;
+ loader->composites.head = NULL;
+ loader->composites.tail = NULL;
+
return FT_Err_Ok;
}
+ static void
+ tt_loader_done( TT_Loader loader )
+ {
+ FT_List_Finalize( &loader->composites,
+ NULL,
+ loader->face->root.memory,
+ NULL );
+ }
+
+
/*************************************************************************/
/* */
/* <Function> */
@@ -2479,6 +2500,7 @@
/* for the bbox we need the header only */
(void)tt_loader_init( &loader, size, glyph, load_flags, TRUE );
(void)load_truetype_glyph( &loader, glyph_index, 0, TRUE );
+ tt_loader_done( &loader );
glyph->linearHoriAdvance = loader.linear;
glyph->linearVertAdvance = loader.vadvance;
@@ -2574,6 +2596,8 @@
error = compute_glyph_metrics( &loader, glyph_index );
}
+ tt_loader_done( &loader );
+
/* Set the `high precision' bit flag. */
/* This is _critical_ to get correct output for monochrome */
/* TrueType glyphs at all sizes using the bytecode interpreter. */
diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c
index 2b12483..5d4384e 100644
--- a/src/truetype/ttgxvar.c
+++ b/src/truetype/ttgxvar.c
@@ -112,6 +112,8 @@
/* <Input> */
/* stream :: The data stream. */
/* */
+ /* size :: The size of the table holding the data. */
+ /* */
/* <Output> */
/* point_cnt :: The number of points read. A zero value means that */
/* all points in the glyph will be affected, without */
@@ -123,6 +125,7 @@
/* */
static FT_UShort*
ft_var_readpackedpoints( FT_Stream stream,
+ FT_ULong size,
FT_UInt *point_cnt )
{
FT_UShort *points = NULL;
@@ -149,6 +152,12 @@
n |= FT_GET_BYTE();
}
+ if ( n > size )
+ {
+ FT_TRACE1(( "ft_var_readpackedpoints: number of points too large\n" ));
+ return NULL;
+ }
+
if ( FT_NEW_ARRAY( points, n ) )
return NULL;
@@ -212,6 +221,8 @@
/* <Input> */
/* stream :: The data stream. */
/* */
+ /* size :: The size of the table holding the data. */
+ /* */
/* delta_cnt :: The number of deltas to be read. */
/* */
/* <Return> */
@@ -222,6 +233,7 @@
/* */
static FT_Short*
ft_var_readpackeddeltas( FT_Stream stream,
+ FT_ULong size,
FT_UInt delta_cnt )
{
FT_Short *deltas = NULL;
@@ -233,6 +245,12 @@
FT_UNUSED( error );
+ if ( delta_cnt > size )
+ {
+ FT_TRACE1(( "ft_var_readpackeddeltas: number of points too large\n" ));
+ return NULL;
+ }
+
if ( FT_NEW_ARRAY( deltas, delta_cnt ) )
return NULL;
@@ -341,7 +359,8 @@
FT_TRACE5(( " axis %d:\n", i ));
segment->pairCount = FT_GET_USHORT();
- if ( FT_NEW_ARRAY( segment->correspondence, segment->pairCount ) )
+ if ( (FT_ULong)segment->pairCount * 4 > table_len ||
+ FT_NEW_ARRAY( segment->correspondence, segment->pairCount ) )
{
/* Failure. Free everything we have done so far. We must do */
/* it right now since loading the `avar' table is optional. */
@@ -357,8 +376,8 @@
for ( j = 0; j < segment->pairCount; j++ )
{
/* convert to Fixed */
- segment->correspondence[j].fromCoord = FT_GET_SHORT() << 2;
- segment->correspondence[j].toCoord = FT_GET_SHORT() << 2;
+ segment->correspondence[j].fromCoord = FT_GET_SHORT() * 4;
+ segment->correspondence[j].toCoord = FT_GET_SHORT() * 4;
FT_TRACE5(( " mapping %.4f to %.4f\n",
segment->correspondence[j].fromCoord / 65536.0,
@@ -447,10 +466,6 @@
if ( FT_STREAM_READ_FIELDS( gvar_fields, &gvar_head ) )
goto Exit;
- blend->tuplecount = gvar_head.globalCoordCount;
- blend->gv_glyphcnt = gvar_head.glyphCount;
- offsetToData = gvar_start + gvar_head.offsetToData;
-
if ( gvar_head.version != 0x00010000L )
{
FT_TRACE1(( "bad table version\n" ));
@@ -458,8 +473,6 @@
goto Exit;
}
- FT_TRACE2(( "loaded\n" ));
-
if ( gvar_head.axisCount != (FT_UShort)blend->mmvar->num_axis )
{
FT_TRACE1(( "ft_var_load_gvar: number of axes in `gvar' and `cvar'\n"
@@ -468,6 +481,33 @@
goto Exit;
}
+ /* rough sanity check, ignoring offsets */
+ if ( (FT_ULong)gvar_head.globalCoordCount * gvar_head.axisCount >
+ table_len / 2 )
+ {
+ FT_TRACE1(( "ft_var_load_gvar:"
+ " invalid number of global coordinates\n" ));
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+
+ /* rough sanity check: offsets can be either 2 or 4 bytes, */
+ /* and a single variation needs at least 4 bytes per glyph */
+ if ( (FT_ULong)gvar_head.glyphCount *
+ ( ( gvar_head.flags & 1 ) ? 8 : 6 ) > table_len )
+ {
+ FT_TRACE1(( "ft_var_load_gvar: invalid number of glyphs\n" ));
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+
+ FT_TRACE2(( "loaded\n" ));
+
+ blend->gvar_size = table_len;
+ blend->tuplecount = gvar_head.globalCoordCount;
+ blend->gv_glyphcnt = gvar_head.glyphCount;
+ offsetToData = gvar_start + gvar_head.offsetToData;
+
FT_TRACE5(( "gvar: there are %d shared coordinates:\n",
blend->tuplecount ));
@@ -514,7 +554,7 @@
for ( j = 0 ; j < (FT_UInt)gvar_head.axisCount; j++ )
{
blend->tuplecoords[i * gvar_head.axisCount + j] =
- FT_GET_SHORT() << 2; /* convert to FT_Fixed */
+ FT_GET_SHORT() * 4; /* convert to FT_Fixed */
FT_TRACE5(( "%.4f ",
blend->tuplecoords[i * gvar_head.axisCount + j] / 65536.0 ));
}
@@ -698,7 +738,8 @@
/* TT_Get_MM_Var initializes the blend structure. */
/* */
/* <Output> */
- /* master :: The `fvar' data (must be freed by caller). */
+ /* master :: The `fvar' data (must be freed by caller). Can be NULL, */
+ /* which makes this function simply load MM support. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
@@ -1352,13 +1393,25 @@
goto FExit;
tupleCount = FT_GET_USHORT();
- offsetToData = table_start + FT_GET_USHORT();
+ offsetToData = FT_GET_USHORT();
+
+ /* rough sanity test */
+ if ( offsetToData + tupleCount * 4 > table_len )
+ {
+ FT_TRACE2(( "tt_face_vary_cvt:"
+ " invalid CVT variation array header\n" ));
+
+ error = FT_THROW( Invalid_Table );
+ goto FExit;
+ }
- /* The documentation implies there are flags packed into the */
- /* tuplecount, but John Jenkins says that shared points don't apply */
- /* to `cvar', and no other flags are defined. */
+ offsetToData += table_start;
- FT_TRACE5(( "cvar: there are %d tuples:\n", tupleCount ));
+ /* 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. */
+
+ FT_TRACE5(( "cvar: there are %d tuples:\n", tupleCount & 0xFFF ));
for ( i = 0; i < ( tupleCount & 0xFFF ); i++ )
{
@@ -1378,7 +1431,7 @@
if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
{
for ( j = 0; j < blend->num_axis; j++ )
- tuple_coords[j] = FT_GET_SHORT() << 2; /* convert from */
+ tuple_coords[j] = FT_GET_SHORT() * 4; /* convert from */
/* short frac to fixed */
}
else
@@ -1396,9 +1449,9 @@
if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
{
for ( j = 0; j < blend->num_axis; j++ )
- im_start_coords[j] = FT_GET_SHORT() << 2;
+ im_start_coords[j] = FT_GET_SHORT() * 4;
for ( j = 0; j < blend->num_axis; j++ )
- im_end_coords[j] = FT_GET_SHORT() << 2;
+ im_end_coords[j] = FT_GET_SHORT() * 4;
}
apply = ft_var_apply_tuple( blend,
@@ -1420,8 +1473,11 @@
FT_Stream_SeekSet( stream, offsetToData );
- localpoints = ft_var_readpackedpoints( stream, &point_count );
+ 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 == NULL || deltas == NULL )
@@ -1649,13 +1705,13 @@
{
FT_Vector* out_points;
- FT_UInt first_point;
- FT_UInt end_point;
+ FT_Int first_point;
+ FT_Int end_point;
- FT_UInt first_delta;
- FT_UInt cur_delta;
+ FT_Int first_delta;
+ FT_Int cur_delta;
- FT_UInt point;
+ FT_Int point;
FT_Short contour;
@@ -1818,7 +1874,19 @@
goto Fail2;
tupleCount = FT_GET_USHORT();
- offsetToData = glyph_start + FT_GET_USHORT();
+ offsetToData = FT_GET_USHORT();
+
+ /* rough sanity test */
+ if ( offsetToData + tupleCount * 4 > blend->gvar_size )
+ {
+ FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:"
+ " invalid glyph variation array header\n" ));
+
+ error = FT_THROW( Invalid_Table );
+ goto Fail2;
+ }
+
+ offsetToData += glyph_start;
if ( tupleCount & GX_TC_TUPLES_SHARE_POINT_NUMBERS )
{
@@ -1826,13 +1894,16 @@
FT_Stream_SeekSet( stream, offsetToData );
- sharedpoints = ft_var_readpackedpoints( stream, &spoint_count );
+ sharedpoints = ft_var_readpackedpoints( stream,
+ blend->gvar_size,
+ &spoint_count );
offsetToData = FT_Stream_FTell( stream );
FT_Stream_SeekSet( stream, here );
}
- FT_TRACE5(( "gvar: there are %d tuples:\n", tupleCount ));
+ FT_TRACE5(( "gvar: there are %d tuples:\n",
+ tupleCount & GX_TC_TUPLE_COUNT_MASK ));
for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); i++ )
{
@@ -1849,11 +1920,14 @@
if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
{
for ( j = 0; j < blend->num_axis; j++ )
- tuple_coords[j] = FT_GET_SHORT() << 2; /* convert from */
+ tuple_coords[j] = FT_GET_SHORT() * 4; /* convert from */
/* short frac to fixed */
}
else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount )
{
+ FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:"
+ " invalid tuple index\n" ));
+
error = FT_THROW( Invalid_Table );
goto Fail2;
}
@@ -1866,9 +1940,9 @@
if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
{
for ( j = 0; j < blend->num_axis; j++ )
- im_start_coords[j] = FT_GET_SHORT() << 2;
+ im_start_coords[j] = FT_GET_SHORT() * 4;
for ( j = 0; j < blend->num_axis; j++ )
- im_end_coords[j] = FT_GET_SHORT() << 2;
+ im_end_coords[j] = FT_GET_SHORT() * 4;
}
apply = ft_var_apply_tuple( blend,
@@ -1889,7 +1963,9 @@
{
FT_Stream_SeekSet( stream, offsetToData );
- localpoints = ft_var_readpackedpoints( stream, &point_count );
+ localpoints = ft_var_readpackedpoints( stream,
+ blend->gvar_size,
+ &point_count );
points = localpoints;
}
else
@@ -1899,9 +1975,11 @@
}
deltas_x = ft_var_readpackeddeltas( stream,
+ blend->gvar_size,
point_count == 0 ? n_points
: point_count );
deltas_y = ft_var_readpackeddeltas( stream,
+ blend->gvar_size,
point_count == 0 ? n_points
: point_count );
@@ -1949,6 +2027,9 @@
#endif
}
+ else if ( localpoints == NULL )
+ ; /* failure, ignore it */
+
else
{
#ifdef FT_DEBUG_LEVEL_TRACE
@@ -2020,6 +2101,8 @@
FT_TRACE5(( "\n" ));
Fail2:
+ if ( sharedpoints != ALL_POINTS )
+ FT_FREE( sharedpoints );
FT_FREE( tuple_coords );
FT_FREE( im_start_coords );
FT_FREE( im_end_coords );
diff --git a/src/truetype/ttgxvar.h b/src/truetype/ttgxvar.h
index 060d4d6..dd1411f 100644
--- a/src/truetype/ttgxvar.h
+++ b/src/truetype/ttgxvar.h
@@ -95,6 +95,8 @@ FT_BEGIN_HEADER
FT_UInt gv_glyphcnt;
FT_ULong* glyphoffsets;
+ FT_ULong gvar_size;
+
} GX_BlendRec;
diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index 089f604..1c1d7de 100644
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -45,15 +45,6 @@
#define FT_COMPONENT trace_ttinterp
- /*************************************************************************/
- /* */
- /* In order to detect infinite loops in the code, we set up a counter */
- /* within the run loop. A single stroke of interpretation is now */
- /* limited to a maximum number of opcodes defined below. */
- /* */
-#define MAX_RUNNABLE_OPCODES 1000000L
-
-
#define SUBPIXEL_HINTING \
( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \
TT_INTERPRETER_VERSION_38 )
@@ -88,13 +79,6 @@
#define BOUNDSL( x, n ) ( (FT_ULong)(x) >= (FT_ULong)(n) )
- /*************************************************************************/
- /* */
- /* This macro computes (a*2^14)/b and complements TT_MulFix14. */
- /* */
-#define TT_DivFix14( a, b ) FT_DivFix( a, (b) << 2 )
-
-
#undef SUCCESS
#define SUCCESS 0
@@ -2580,26 +2564,23 @@
FT_F26Dot6 Vy,
FT_UnitVector* R )
{
- FT_F26Dot6 W;
+ FT_Vector V;
- if ( FT_ABS( Vx ) < 0x4000L && FT_ABS( Vy ) < 0x4000L )
+ if ( Vx == 0 && Vy == 0 )
{
- if ( Vx == 0 && Vy == 0 )
- {
- /* XXX: UNDOCUMENTED! It seems that it is possible to try */
- /* to normalize the vector (0,0). Return immediately. */
- return SUCCESS;
- }
-
- Vx *= 0x4000;
- Vy *= 0x4000;
+ /* XXX: UNDOCUMENTED! It seems that it is possible to try */
+ /* to normalize the vector (0,0). Return immediately. */
+ return SUCCESS;
}
- W = FT_Hypot( Vx, Vy );
+ V.x = Vx;
+ V.y = Vy;
- R->x = (FT_F2Dot14)TT_DivFix14( Vx, W );
- R->y = (FT_F2Dot14)TT_DivFix14( Vy, W );
+ FT_Vector_NormLen( &V );
+
+ R->x = (FT_F2Dot14)( V.x / 4 );
+ R->y = (FT_F2Dot14)( V.y / 4 );
return SUCCESS;
}
@@ -5157,11 +5138,11 @@
Ins_INSTCTRL( TT_ExecContext exc,
FT_Long* args )
{
- FT_Long K, L, Kf;
+ FT_ULong K, L, Kf;
- K = args[1];
- L = args[0];
+ K = (FT_ULong)args[1];
+ L = (FT_ULong)args[0];
/* selector values cannot be `OR'ed; */
/* they are indices starting with index 1, not flags */
@@ -6505,8 +6486,6 @@
dx = exc->zp0.cur[b0].x - exc->zp1.cur[a0].x;
dy = exc->zp0.cur[b0].y - exc->zp1.cur[a0].y;
- exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH;
-
discriminant = FT_MulDiv( dax, -dby, 0x40 ) +
FT_MulDiv( day, dbx, 0x40 );
dotproduct = FT_MulDiv( dax, dbx, 0x40 ) +
@@ -6543,6 +6522,8 @@
exc->zp0.cur[b0].y +
exc->zp0.cur[b1].y ) / 4;
}
+
+ exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH;
}
@@ -7575,7 +7556,7 @@
? 2
: 12 - ( *opcode_name[exc->opcode] - '0' ),
"#" ));
- for ( n = 0; n < cnt; n++ )
+ for ( n = 1; n <= cnt; n++ )
FT_TRACE7(( " %d", exc->stack[exc->top - n] ));
FT_TRACE6(( "\n" ));
}
@@ -8240,7 +8221,7 @@
/* increment instruction counter and check if we didn't */
/* run this program for too long (e.g. infinite loops). */
- if ( ++ins_counter > MAX_RUNNABLE_OPCODES )
+ if ( ++ins_counter > TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES )
return FT_THROW( Execution_Too_Long );
LSuiteLabel_:
diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c
index 202aa04..b0d9f28 100644
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -191,7 +191,7 @@
{
FT_Error error;
FT_UInt32 checksum = 0;
- int i;
+ FT_UInt i;
if ( FT_FRAME_ENTER( length ) )
@@ -200,8 +200,8 @@
for ( ; length > 3; length -= 4 )
checksum += (FT_UInt32)FT_GET_ULONG();
- for ( i = 3; length > 0; length --, i-- )
- checksum += (FT_UInt32)( FT_GET_BYTE() << ( i * 8 ) );
+ for ( i = 3; length > 0; length--, i-- )
+ checksum += (FT_UInt32)FT_GET_BYTE() << ( i * 8 );
FT_FRAME_EXIT();
@@ -490,7 +490,10 @@
/* <Input> */
/* stream :: The source font stream. */
/* */
- /* face_index :: The index of the font face in the resource. */
+ /* face_index :: The index of the TrueType font, if we are opening a */
+ /* collection, in bits 0-15. The numbered instance */
+ /* index~+~1 of a GX (sub)font, if applicable, in bits */
+ /* 16-30. */
/* */
/* num_params :: Number of additional generic parameters. Ignored. */
/* */
@@ -599,7 +602,7 @@
ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE;
}
-#else
+#else /* !FT_CONFIG_OPTION_INCREMENTAL */
if ( !error )
error = tt_face_load_loca( face, stream );
@@ -623,10 +626,56 @@
ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE;
}
-#endif
+#endif /* !FT_CONFIG_OPTION_INCREMENTAL */
}
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+
+ {
+ FT_Int instance_index = face_index >> 16;
+
+
+ if ( FT_HAS_MULTIPLE_MASTERS( ttface ) &&
+ instance_index > 0 )
+ {
+ error = TT_Get_MM_Var( face, NULL );
+ 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;
+ }
+ }
+ }
+
+#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
+
#if defined( TT_CONFIG_OPTION_UNPATENTED_HINTING ) && \
!defined( TT_CONFIG_OPTION_BYTECODE_INTERPRETER )
@@ -1029,7 +1078,15 @@
}
/* Fine, now run the font program! */
+
+ /* In case of an error while executing `fpgm', we intentionally don't */
+ /* clean up immediately – bugs in the `fpgm' are so fundamental that */
+ /* all following hinting calls should fail. Additionally, `fpgm' is */
+ /* to be executed just once; calling it again is completely useless */
+ /* and might even lead to extremely slow behaviour if it is malformed */
+ /* (containing an infinite loop, for example). */
error = tt_size_run_fpgm( size, pedantic );
+ return error;
Exit:
if ( error )
diff --git a/src/truetype/ttobjs.h b/src/truetype/ttobjs.h
index 7ac4123..9396089 100644
--- a/src/truetype/ttobjs.h
+++ b/src/truetype/ttobjs.h
@@ -42,17 +42,6 @@ FT_BEGIN_HEADER
/*************************************************************************/
/* */
/* <Type> */
- /* TT_Instance */
- /* */
- /* <Description> */
- /* A handle to a TrueType size object. */
- /* */
- typedef struct TT_SizeRec_* TT_Size;
-
-
- /*************************************************************************/
- /* */
- /* <Type> */
/* TT_GlyphSlot */
/* */
/* <Description> */
diff --git a/src/truetype/ttpic.h b/src/truetype/ttpic.h
index 48ba4aa..076ae56 100644
--- a/src/truetype/ttpic.h
+++ b/src/truetype/ttpic.h
@@ -20,7 +20,8 @@
#define __TTPIC_H__
-FT_BEGIN_HEADER
+#include FT_INTERNAL_PIC_H
+
#ifndef FT_CONFIG_OPTION_PIC
@@ -37,6 +38,8 @@ FT_BEGIN_HEADER
#include FT_SERVICE_PROPERTIES_H
+FT_BEGIN_HEADER
+
typedef struct TTModulePIC_
{
FT_ServiceDescRec* tt_services;
@@ -68,13 +71,12 @@ FT_BEGIN_HEADER
FT_Error
tt_driver_class_pic_init( FT_Library library );
+FT_END_HEADER
+
#endif /* FT_CONFIG_OPTION_PIC */
/* */
-
-FT_END_HEADER
-
#endif /* __TTPIC_H__ */
diff --git a/src/truetype/ttpload.c b/src/truetype/ttpload.c
index fb338bd..9bf67f9 100644
--- a/src/truetype/ttpload.c
+++ b/src/truetype/ttpload.c
@@ -124,8 +124,9 @@
TT_Table entry = face->dir_tables;
TT_Table limit = entry + face->num_tables;
- FT_Long pos = (FT_Long)FT_STREAM_POS();
- FT_Long dist = 0x7FFFFFFFL;
+ FT_Long pos = (FT_Long)FT_STREAM_POS();
+ FT_Long dist = 0x7FFFFFFFL;
+ FT_Bool found = 0;
/* compute the distance to next table in font file */
@@ -135,10 +136,13 @@
if ( diff > 0 && diff < dist )
- dist = diff;
+ {
+ dist = diff;
+ found = 1;
+ }
}
- if ( entry == limit )
+ if ( !found )
{
/* `loca' is the last table */
dist = (FT_Long)stream->size - pos;
@@ -152,6 +156,14 @@
FT_TRACE2(( "adjusting num_locations to %d\n",
face->num_locations ));
}
+ else
+ {
+ face->root.num_glyphs = face->num_locations
+ ? (FT_Long)face->num_locations - 1 : 0;
+
+ FT_TRACE2(( "adjusting num_glyphs to %d\n",
+ face->root.num_glyphs ));
+ }
}
}
@@ -214,7 +226,8 @@
if ( pos1 > face->glyf_len )
{
FT_TRACE1(( "tt_face_get_location:"
- " too large offset=0x%08lx found for gid=0x%04lx,"
+ " too large offset=0x%08lx found for gid=0x%04lx,\n"
+ " "
" exceeding the end of glyf table (0x%08lx)\n",
pos1, gindex, face->glyf_len ));
*asize = 0;
@@ -224,7 +237,8 @@
if ( pos2 > face->glyf_len )
{
FT_TRACE1(( "tt_face_get_location:"
- " too large offset=0x%08lx found for gid=0x%04lx,"
+ " too large offset=0x%08lx found for gid=0x%04lx,\n"
+ " "
" truncate at the end of glyf table (0x%08lx)\n",
pos2, gindex + 1, face->glyf_len ));
pos2 = face->glyf_len;
diff --git a/src/truetype/ttsubpix.c b/src/truetype/ttsubpix.c
index dbda4d9..0d391e9 100644
--- a/src/truetype/ttsubpix.c
+++ b/src/truetype/ttsubpix.c
@@ -903,7 +903,7 @@
sph_set_tweaks( TT_Loader loader,
FT_UInt glyph_index )
{
- TT_Face face = (TT_Face)loader->face;
+ TT_Face face = loader->face;
FT_String* family = face->root.family_name;
FT_UInt ppem = loader->size->metrics.x_ppem;
FT_String* style = face->root.style_name;