freetype2 (empty) → 0.0.1
raw patch · 378 files changed
+153254/−0 lines, 378 filesdep +arraydep +basedep +freetype2setup-changed
Dependencies added: array, base, freetype2, missing-foreign
Files
- Graphics/Rendering/FreeType/Internal.hsc +60/−0
- Graphics/Rendering/FreeType/Internal/Bitmap.hsc +56/−0
- Graphics/Rendering/FreeType/Internal/Face.hsc +45/−0
- Graphics/Rendering/FreeType/Internal/Glyph.hsc +44/−0
- Graphics/Rendering/FreeType/Internal/GlyphSlot.hsc +50/−0
- Graphics/Rendering/FreeType/Internal/Library.hsc +26/−0
- Graphics/Rendering/FreeType/Internal/Matrix.hsc +35/−0
- Graphics/Rendering/FreeType/Internal/PrimitiveTypes.hsc +72/−0
- Graphics/Rendering/FreeType/Internal/Vector.hsc +28/−0
- LICENSE +30/−0
- Main.hs +115/−0
- Setup.hs +2/−0
- freetype2.cabal +251/−0
- include/freetype/config/ftconfig.h +528/−0
- include/freetype/config/ftheader.h +780/−0
- include/freetype/config/ftmodule.h +32/−0
- include/freetype/config/ftoption.h +733/−0
- include/freetype/config/ftstdlib.h +173/−0
- include/freetype/freetype.h +3919/−0
- include/freetype/ftadvanc.h +179/−0
- include/freetype/ftbbox.h +94/−0
- include/freetype/ftbdf.h +209/−0
- include/freetype/ftbitmap.h +227/−0
- include/freetype/ftcache.h +1140/−0
- include/freetype/ftchapters.h +103/−0
- include/freetype/ftcid.h +166/−0
- include/freetype/fterrdef.h +244/−0
- include/freetype/fterrors.h +206/−0
- include/freetype/ftgasp.h +120/−0
- include/freetype/ftglyph.h +613/−0
- include/freetype/ftgxval.h +358/−0
- include/freetype/ftgzip.h +102/−0
- include/freetype/ftimage.h +1313/−0
- include/freetype/ftincrem.h +353/−0
- include/freetype/ftlcdfil.h +213/−0
- include/freetype/ftlist.h +277/−0
- include/freetype/ftlzw.h +99/−0
- include/freetype/ftmac.h +274/−0
- include/freetype/ftmm.h +378/−0
- include/freetype/ftmodapi.h +483/−0
- include/freetype/ftmoderr.h +155/−0
- include/freetype/ftotval.h +203/−0
- include/freetype/ftoutln.h +537/−0
- include/freetype/ftpfr.h +172/−0
- include/freetype/ftrender.h +230/−0
- include/freetype/ftsizes.h +159/−0
- include/freetype/ftsnames.h +200/−0
- include/freetype/ftstroke.h +716/−0
- include/freetype/ftsynth.h +80/−0
- include/freetype/ftsystem.h +347/−0
- include/freetype/fttrigon.h +350/−0
- include/freetype/fttypes.h +588/−0
- include/freetype/ftwinfnt.h +274/−0
- include/freetype/ftxf86.h +83/−0
- include/freetype/internal/autohint.h +231/−0
- include/freetype/internal/ftcalc.h +179/−0
- include/freetype/internal/ftdebug.h +250/−0
- include/freetype/internal/ftdriver.h +422/−0
- include/freetype/internal/ftgloadr.h +168/−0
- include/freetype/internal/ftmemory.h +380/−0
- include/freetype/internal/ftobjs.h +1428/−0
- include/freetype/internal/ftpic.h +67/−0
- include/freetype/internal/ftrfork.h +196/−0
- include/freetype/internal/ftserv.h +620/−0
- include/freetype/internal/ftstream.h +539/−0
- include/freetype/internal/fttrace.h +139/−0
- include/freetype/internal/ftvalid.h +150/−0
- include/freetype/internal/internal.h +51/−0
- include/freetype/internal/pcftypes.h +56/−0
- include/freetype/internal/psaux.h +873/−0
- include/freetype/internal/pshints.h +712/−0
- include/freetype/internal/services/svbdf.h +77/−0
- include/freetype/internal/services/svcid.h +83/−0
- include/freetype/internal/services/svgldict.h +82/−0
- include/freetype/internal/services/svgxval.h +72/−0
- include/freetype/internal/services/svkern.h +51/−0
- include/freetype/internal/services/svmm.h +104/−0
- include/freetype/internal/services/svotval.h +55/−0
- include/freetype/internal/services/svpfr.h +66/−0
- include/freetype/internal/services/svpostnm.h +79/−0
- include/freetype/internal/services/svpscmap.h +164/−0
- include/freetype/internal/services/svpsinfo.h +92/−0
- include/freetype/internal/services/svsfnt.h +102/−0
- include/freetype/internal/services/svttcmap.h +106/−0
- include/freetype/internal/services/svtteng.h +53/−0
- include/freetype/internal/services/svttglyf.h +67/−0
- include/freetype/internal/services/svwinfnt.h +50/−0
- include/freetype/internal/services/svxf86nm.h +55/−0
- include/freetype/internal/sfnt.h +897/−0
- include/freetype/internal/t1types.h +270/−0
- include/freetype/internal/tttypes.h +1543/−0
- include/freetype/t1tables.h +504/−0
- include/freetype/ttnameid.h +1247/−0
- include/freetype/tttables.h +759/−0
- include/freetype/tttags.h +107/−0
- include/freetype/ttunpat.h +59/−0
- include/ft2build.h +39/−0
- objs/ftmodule.h +20/−0
- src/autofit/afangles.c +292/−0
- src/autofit/afangles.h +7/−0
- src/autofit/afcjk.c +1512/−0
- src/autofit/afcjk.h +57/−0
- src/autofit/afdummy.c +60/−0
- src/autofit/afdummy.h +42/−0
- src/autofit/aferrors.h +40/−0
- src/autofit/afglobal.c +323/−0
- src/autofit/afglobal.h +71/−0
- src/autofit/afhints.c +1142/−0
- src/autofit/afhints.h +332/−0
- src/autofit/afindic.c +130/−0
- src/autofit/afindic.h +40/−0
- src/autofit/aflatin.c +2224/−0
- src/autofit/aflatin.h +212/−0
- src/autofit/aflatin2.c +2345/−0
- src/autofit/aflatin2.h +39/−0
- src/autofit/afloader.c +539/−0
- src/autofit/afloader.h +73/−0
- src/autofit/afmodule.c +94/−0
- src/autofit/afmodule.h +37/−0
- src/autofit/afpic.c +94/−0
- src/autofit/afpic.h +64/−0
- src/autofit/aftypes.h +403/−0
- src/autofit/afwarp.c +338/−0
- src/autofit/afwarp.h +64/−0
- src/autofit/autofit.c +41/−0
- src/base/basepic.c +83/−0
- src/base/basepic.h +62/−0
- src/base/ftadvanc.c +163/−0
- src/base/ftapi.c +121/−0
- src/base/ftbase.c +41/−0
- src/base/ftbase.h +68/−0
- src/base/ftbbox.c +662/−0
- src/base/ftbdf.c +88/−0
- src/base/ftbitmap.c +663/−0
- src/base/ftcalc.c +957/−0
- src/base/ftcid.c +117/−0
- src/base/ftdbgmem.c +997/−0
- src/base/ftdebug.c +246/−0
- src/base/ftfstype.c +62/−0
- src/base/ftgasp.c +61/−0
- src/base/ftgloadr.c +401/−0
- src/base/ftglyph.c +627/−0
- src/base/ftgxval.c +140/−0
- src/base/ftinit.c +253/−0
- src/base/ftlcdfil.c +376/−0
- src/base/ftmac.c +1057/−0
- src/base/ftmm.c +202/−0
- src/base/ftobjs.c +4664/−0
- src/base/ftotval.c +89/−0
- src/base/ftoutln.c +1129/−0
- src/base/ftpatent.c +286/−0
- src/base/ftpfr.c +144/−0
- src/base/ftpic.c +54/−0
- src/base/ftrfork.c +871/−0
- src/base/ftsnames.c +94/−0
- src/base/ftstream.c +864/−0
- src/base/ftstroke.c +2039/−0
- src/base/ftsynth.c +160/−0
- src/base/ftsystem.c +318/−0
- src/base/fttrigon.c +546/−0
- src/base/fttype1.c +94/−0
- src/base/ftutil.c +501/−0
- src/base/ftwinfnt.c +51/−0
- src/base/ftxf86.c +40/−0
- src/bdf/bdf.c +34/−0
- src/bdf/bdf.h +295/−0
- src/bdf/bdfdrivr.c +881/−0
- src/bdf/bdfdrivr.h +80/−0
- src/bdf/bdferror.h +44/−0
- src/bdf/bdflib.c +2542/−0
- src/cache/ftcache.c +31/−0
- src/cache/ftcbasic.c +851/−0
- src/cache/ftccache.c +595/−0
- src/cache/ftccache.h +319/−0
- src/cache/ftccback.h +90/−0
- src/cache/ftccmap.c +430/−0
- src/cache/ftcerror.h +40/−0
- src/cache/ftcglyph.c +209/−0
- src/cache/ftcglyph.h +323/−0
- src/cache/ftcimage.c +163/−0
- src/cache/ftcimage.h +107/−0
- src/cache/ftcmanag.c +743/−0
- src/cache/ftcmanag.h +175/−0
- src/cache/ftcmru.c +357/−0
- src/cache/ftcmru.h +246/−0
- src/cache/ftcsbits.c +408/−0
- src/cache/ftcsbits.h +98/−0
- src/cff/cff.c +30/−0
- src/cff/cffcmap.c +208/−0
- src/cff/cffcmap.h +67/−0
- src/cff/cffdrivr.c +671/−0
- src/cff/cffdrivr.h +38/−0
- src/cff/cfferrs.h +41/−0
- src/cff/cffgload.c +2972/−0
- src/cff/cffgload.h +201/−0
- src/cff/cffload.c +1661/−0
- src/cff/cffload.h +83/−0
- src/cff/cffobjs.c +1008/−0
- src/cff/cffobjs.h +181/−0
- src/cff/cffparse.c +924/−0
- src/cff/cffparse.h +102/−0
- src/cff/cffpic.c +101/−0
- src/cff/cffpic.h +80/−0
- src/cff/cfftoken.h +97/−0
- src/cff/cfftypes.h +281/−0
- src/cid/ciderrs.h +40/−0
- src/cid/cidgload.c +442/−0
- src/cid/cidgload.h +51/−0
- src/cid/cidload.c +672/−0
- src/cid/cidload.h +53/−0
- src/cid/cidobjs.c +482/−0
- src/cid/cidobjs.h +154/−0
- src/cid/cidparse.c +225/−0
- src/cid/cidparse.h +123/−0
- src/cid/cidriver.c +240/−0
- src/cid/cidriver.h +43/−0
- src/cid/cidtoken.h +112/−0
- src/cid/type1cid.c +29/−0
- src/gzip/adler32.c +48/−0
- src/gzip/ftgzip.c +688/−0
- src/gzip/infblock.c +387/−0
- src/gzip/infblock.h +36/−0
- src/gzip/infcodes.c +250/−0
- src/gzip/infcodes.h +31/−0
- src/gzip/inffixed.h +151/−0
- src/gzip/inflate.c +273/−0
- src/gzip/inftrees.c +468/−0
- src/gzip/inftrees.h +63/−0
- src/gzip/infutil.c +86/−0
- src/gzip/infutil.h +98/−0
- src/gzip/zconf.h +284/−0
- src/gzip/zlib.h +830/−0
- src/gzip/zutil.c +181/−0
- src/gzip/zutil.h +215/−0
- src/lzw/ftlzw.c +412/−0
- src/lzw/ftzopen.c +401/−0
- src/lzw/ftzopen.h +171/−0
- src/pcf/pcf.c +36/−0
- src/pcf/pcf.h +237/−0
- src/pcf/pcfdrivr.c +698/−0
- src/pcf/pcfdrivr.h +48/−0
- src/pcf/pcferror.h +40/−0
- src/pcf/pcfread.c +1278/−0
- src/pcf/pcfread.h +45/−0
- src/pcf/pcfutil.c +104/−0
- src/pcf/pcfutil.h +55/−0
- src/pfr/pfr.c +29/−0
- src/pfr/pfrcmap.c +166/−0
- src/pfr/pfrcmap.h +46/−0
- src/pfr/pfrdrivr.c +214/−0
- src/pfr/pfrdrivr.h +43/−0
- src/pfr/pfrerror.h +40/−0
- src/pfr/pfrgload.c +844/−0
- src/pfr/pfrgload.h +49/−0
- src/pfr/pfrload.c +941/−0
- src/pfr/pfrload.h +118/−0
- src/pfr/pfrobjs.c +591/−0
- src/pfr/pfrobjs.h +96/−0
- src/pfr/pfrsbit.c +698/−0
- src/pfr/pfrsbit.h +36/−0
- src/pfr/pfrtypes.h +362/−0
- src/psaux/afmparse.c +964/−0
- src/psaux/afmparse.h +88/−0
- src/psaux/psaux.c +34/−0
- src/psaux/psauxerr.h +41/−0
- src/psaux/psauxmod.c +139/−0
- src/psaux/psauxmod.h +42/−0
- src/psaux/psconv.c +472/−0
- src/psaux/psconv.h +71/−0
- src/psaux/psobjs.c +1711/−0
- src/psaux/psobjs.h +212/−0
- src/psaux/t1cmap.c +341/−0
- src/psaux/t1cmap.h +105/−0
- src/psaux/t1decode.c +1601/−0
- src/psaux/t1decode.h +64/−0
- src/pshinter/pshalgo.c +2306/−0
- src/pshinter/pshalgo.h +255/−0
- src/pshinter/pshglob.c +750/−0
- src/pshinter/pshglob.h +196/−0
- src/pshinter/pshinter.c +29/−0
- src/pshinter/pshmod.c +118/−0
- src/pshinter/pshmod.h +39/−0
- src/pshinter/pshnterr.h +40/−0
- src/pshinter/pshpic.c +69/−0
- src/pshinter/pshpic.h +53/−0
- src/pshinter/pshrec.c +1224/−0
- src/pshinter/pshrec.h +176/−0
- src/psnames/psmodule.c +597/−0
- src/psnames/psmodule.h +38/−0
- src/psnames/psnamerr.h +41/−0
- src/psnames/psnames.c +26/−0
- src/psnames/pspic.c +79/−0
- src/psnames/pspic.h +54/−0
- src/psnames/pstables.h +4095/−0
- src/raster/ftmisc.h +121/−0
- src/raster/ftraster.c +3563/−0
- src/raster/ftraster.h +46/−0
- src/raster/ftrend1.c +291/−0
- src/raster/ftrend1.h +44/−0
- src/raster/raster.c +27/−0
- src/raster/rasterrs.h +41/−0
- src/raster/rastpic.c +90/−0
- src/raster/rastpic.h +50/−0
- src/sfnt/sfdriver.c +651/−0
- src/sfnt/sfdriver.h +38/−0
- src/sfnt/sferrors.h +41/−0
- src/sfnt/sfnt.c +42/−0
- src/sfnt/sfntpic.c +102/−0
- src/sfnt/sfntpic.h +88/−0
- src/sfnt/sfobjs.c +1147/−0
- src/sfnt/sfobjs.h +54/−0
- src/sfnt/ttbdf.c +250/−0
- src/sfnt/ttbdf.h +46/−0
- src/sfnt/ttcmap.c +3512/−0
- src/sfnt/ttcmap.h +125/−0
- src/sfnt/ttcmapc.h +55/−0
- src/sfnt/ttkern.c +306/−0
- src/sfnt/ttkern.h +52/−0
- src/sfnt/ttload.c +1267/−0
- src/sfnt/ttload.h +112/−0
- src/sfnt/ttmtx.c +468/−0
- src/sfnt/ttmtx.h +55/−0
- src/sfnt/ttpost.c +563/−0
- src/sfnt/ttpost.h +46/−0
- src/sfnt/ttsbit.c +1508/−0
- src/sfnt/ttsbit.h +79/−0
- src/sfnt/ttsbit0.c +1011/−0
- src/smooth/ftgrays.c +2062/−0
- src/smooth/ftgrays.h +58/−0
- src/smooth/ftsmerrs.h +41/−0
- src/smooth/ftsmooth.c +499/−0
- src/smooth/ftsmooth.h +49/−0
- src/smooth/ftspic.c +98/−0
- src/smooth/ftspic.h +50/−0
- src/smooth/smooth.c +27/−0
- src/truetype/truetype.c +37/−0
- src/truetype/ttdriver.c +487/−0
- src/truetype/ttdriver.h +38/−0
- src/truetype/tterrors.h +40/−0
- src/truetype/ttgload.c +2147/−0
- src/truetype/ttgload.h +63/−0
- src/truetype/ttgxvar.c +1548/−0
- src/truetype/ttgxvar.h +182/−0
- src/truetype/ttinterp.c +8160/−0
- src/truetype/ttinterp.h +319/−0
- src/truetype/ttobjs.c +1135/−0
- src/truetype/ttobjs.h +431/−0
- src/truetype/ttpic.c +81/−0
- src/truetype/ttpic.h +59/−0
- src/truetype/ttpload.c +598/−0
- src/truetype/ttpload.h +75/−0
- src/type1/t1afm.c +397/−0
- src/type1/t1afm.h +54/−0
- src/type1/t1driver.c +331/−0
- src/type1/t1driver.h +42/−0
- src/type1/t1errors.h +40/−0
- src/type1/t1gload.c +515/−0
- src/type1/t1gload.h +53/−0
- src/type1/t1load.c +2237/−0
- src/type1/t1load.h +102/−0
- src/type1/t1objs.c +597/−0
- src/type1/t1objs.h +171/−0
- src/type1/t1parse.c +486/−0
- src/type1/t1parse.h +135/−0
- src/type1/t1tokens.h +143/−0
- src/type1/type1.c +33/−0
- src/type42/t42drivr.c +246/−0
- src/type42/t42drivr.h +42/−0
- src/type42/t42error.h +40/−0
- src/type42/t42objs.c +652/−0
- src/type42/t42objs.h +124/−0
- src/type42/t42parse.c +1187/−0
- src/type42/t42parse.h +90/−0
- src/type42/t42types.h +56/−0
- src/type42/type42.c +25/−0
- src/winfonts/fnterrs.h +41/−0
- src/winfonts/winfnt.c +1145/−0
- src/winfonts/winfnt.h +171/−0
+ Graphics/Rendering/FreeType/Internal.hsc view
@@ -0,0 +1,60 @@+{-# LANGUAGE ForeignFunctionInterface #-}+module Graphics.Rendering.FreeType.Internal where++import Foreign+import Foreign.C.String++import Graphics.Rendering.FreeType.Internal.PrimitiveTypes+import Graphics.Rendering.FreeType.Internal.Library+import Graphics.Rendering.FreeType.Internal.Face+import Graphics.Rendering.FreeType.Internal.Matrix+import Graphics.Rendering.FreeType.Internal.Vector+import Graphics.Rendering.FreeType.Internal.Glyph+import Graphics.Rendering.FreeType.Internal.GlyphSlot++#include "ft2build.h"+#include FT_FREETYPE_H++foreign import ccall "FT_Init_FreeType"+ ft_Init_FreeType :: Ptr FT_Library -> IO FT_Error++foreign import ccall "FT_New_Face"+ ft_New_Face :: FT_Library -> CString -> FT_Long+ -> Ptr FT_Face -> IO FT_Error++foreign import ccall "FT_Set_Char_Size"+ ft_Set_Char_Size :: FT_Face -> FT_F26Dot6 -> FT_F26Dot6+ -> FT_UInt -> FT_UInt -> IO FT_Error++foreign import ccall "FT_Set_Pixel_Sizes"+ ft_Set_Pixel_Sizes :: FT_Face -> FT_UInt -> FT_UInt+ -> IO FT_Error++foreign import ccall "FT_Get_Char_Index"+ ft_Get_Char_Index :: FT_Face -> FT_ULong -> IO FT_UInt++foreign import ccall "FT_Set_Transform"+ ft_Set_Transform :: FT_Face -> Ptr FT_Matrix+ -> Ptr FT_Vector -> IO ()++foreign import ccall "FT_Load_Char"+ ft_Load_Char :: FT_Face -> FT_ULong -> FT_Int32 -> IO FT_Error++foreign import ccall "FT_Done_Face"+ ft_Done_Face :: FT_Face -> IO FT_Error++foreign import ccall "FT_Done_FreeType"+ ft_Done_FreeType :: FT_Library -> IO FT_Error++foreign import ccall "FT_Load_Glyph"+ ft_Load_Glyph :: FT_Face -> FT_UInt -> FT_Int32 -> IO FT_Error++foreign import ccall "FT_Get_Glyph"+ ft_Get_Glyph :: FT_GlyphSlot -> Ptr FT_Glyph -> IO FT_Error++foreign import ccall "FT_Done_Glyph"+ ft_Done_Glyph :: FT_Glyph -> IO ()++foreign import ccall "FT_Glyph_To_Bitmap"+ ft_Glyph_To_Bitmap :: Ptr FT_Glyph -> FT_Render_Mode+ -> Ptr FT_Vector -> FT_Bool -> IO FT_Error
+ Graphics/Rendering/FreeType/Internal/Bitmap.hsc view
@@ -0,0 +1,56 @@+{-# LANGUAGE ForeignFunctionInterface #-} +module Graphics.Rendering.FreeType.Internal.Bitmap +( FT_Bitmap(..) +) where + +import Foreign +import Foreign.C.Types +import Foreign.Storable + +#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__) + +#include "ft2build.h" +#include FT_FREETYPE_H + +data FT_Bitmap = FT_Bitmap + { rows :: CInt + , width :: CInt + , pitch :: CInt + , buffer :: Ptr CChar + , num_grays :: CShort + , pixel_mode :: CChar + , palette_mode :: CChar + , palette :: Ptr () + } + +instance Storable FT_Bitmap where + sizeOf _ = #size FT_Bitmap + alignment _ = #alignment FT_Bitmap + peek ptr = do + rows' <- (#peek FT_Bitmap, rows) ptr + width' <- (#peek FT_Bitmap, width) ptr + pitch' <- (#peek FT_Bitmap, pitch) ptr + buffer' <- (#peek FT_Bitmap, buffer) ptr + num_grays' <- (#peek FT_Bitmap, num_grays) ptr + pixel_mode' <- (#peek FT_Bitmap, pixel_mode) ptr + palette_mode' <- (#peek FT_Bitmap, palette_mode) ptr + palette' <- (#peek FT_Bitmap, palette) ptr + return $ FT_Bitmap + { rows = rows' + , width = width' + , pitch = pitch' + , buffer = buffer' + , num_grays = num_grays' + , pixel_mode = pixel_mode' + , palette_mode = palette_mode' + , palette = palette' + } + poke ptr val = do + (#poke FT_Bitmap, rows) ptr (rows val) + (#poke FT_Bitmap, width) ptr (width val) + (#poke FT_Bitmap, pitch) ptr (pitch val) + (#poke FT_Bitmap, buffer) ptr (buffer val) + (#poke FT_Bitmap, num_grays) ptr (num_grays val) + (#poke FT_Bitmap, pixel_mode) ptr (pixel_mode val) + (#poke FT_Bitmap, palette_mode) ptr (palette_mode val) + (#poke FT_Bitmap, palette) ptr (palette val)
+ Graphics/Rendering/FreeType/Internal/Face.hsc view
@@ -0,0 +1,45 @@+{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-}+module Graphics.Rendering.FreeType.Internal.Face+( FT_FaceRec_+, FT_Face+, num_faces+, num_glyphs+, glyph+, underline_thickness+) where++import Foreign+import Foreign.Storable++import Graphics.Rendering.FreeType.Internal.PrimitiveTypes+import qualified Graphics.Rendering.FreeType.Internal.GlyphSlot as GS++#include <stddef.h>+#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)++#include "ft2build.h"+#include FT_FREETYPE_H++#include "internal/ftobjs.h"++data FT_FaceRec_+type FT_Face = Ptr FT_FaceRec_++instance Storable FT_FaceRec_ where+ sizeOf _ = #size struct FT_FaceRec_+ alignment _ = #alignment struct FT_FaceRec_+ peek = error "peek not implemented for FT_FaceRec_"+ poke = error "poke not implemented for FT_FaceRec_"++num_faces :: FT_Face -> Ptr FT_Long+num_faces = #ptr struct FT_FaceRec_, num_faces++num_glyphs :: FT_Face -> Ptr FT_Long+num_glyphs = #ptr struct FT_FaceRec_, num_glyphs++glyph :: FT_Face -> Ptr GS.FT_GlyphSlot+glyph = #ptr struct FT_FaceRec_, glyph++underline_thickness :: FT_Face -> Ptr FT_Short+underline_thickness = #ptr struct FT_FaceRec_, underline_thickness+
+ Graphics/Rendering/FreeType/Internal/Glyph.hsc view
@@ -0,0 +1,44 @@+{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-} +module Graphics.Rendering.FreeType.Internal.Glyph +( FT_GlyphRec_ +, FT_Glyph +, library +, advance +) where + +import Foreign +import Foreign.Storable + +-- import Graphics.Rendering.FreeType.Internal.PrimitiveTypes +import qualified Graphics.Rendering.FreeType.Internal.Library as Lib +import qualified Graphics.Rendering.FreeType.Internal.Vector as V + +#include <stddef.h> +#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__) + +#include "ft2build.h" +#include FT_FREETYPE_H + +#include "freetype/ftglyph.h" + +data FT_GlyphRec_ +type FT_Glyph = Ptr FT_GlyphRec_ + +instance Storable FT_GlyphRec_ where + sizeOf _ = #size struct FT_GlyphRec_ + alignment _ = #alignment struct FT_GlyphRec_ + peek = error "peek not implemented for FT_GlyphRec_" + poke = error "peek not implemented for FT_GlyphRec_" + +library :: FT_Glyph -> Ptr Lib.FT_Library +library = #ptr struct FT_GlyphRec_, library + +{- TODO: implement FT_Glyph_Format +format :: FT_Glyph -> Ptr FT_Glyph_Format +format = #ptr struct FT_GlyphRec_, format +-} + +advance :: FT_Glyph -> Ptr V.FT_Vector +advance = #ptr struct FT_GlyphRec_, advance + +
+ Graphics/Rendering/FreeType/Internal/GlyphSlot.hsc view
@@ -0,0 +1,50 @@+{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-} +module Graphics.Rendering.FreeType.Internal.GlyphSlot +( FT_GlyphSlotRec_ +, FT_GlyphSlot +, library +, advance +, bitmap +, bitmap_top +, bitmap_left +) where + +import Foreign +import Foreign.Storable + +import Graphics.Rendering.FreeType.Internal.PrimitiveTypes +import qualified Graphics.Rendering.FreeType.Internal.Library as Lib +import qualified Graphics.Rendering.FreeType.Internal.Vector as V +import qualified Graphics.Rendering.FreeType.Internal.Bitmap as B + +#include <stddef.h> +#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__) + +#include "ft2build.h" +#include FT_FREETYPE_H + +#include "internal/ftobjs.h" + +data FT_GlyphSlotRec_ +type FT_GlyphSlot = Ptr FT_GlyphSlotRec_ + +instance Storable FT_GlyphSlotRec_ where + sizeOf _ = #size struct FT_GlyphSlotRec_ + alignment _ = #alignment struct FT_GlyphSlotRec_ + peek = error "peek not implemented for FT_GlyphSlotRec_" + poke = error "poke not implemented for FT_GlyphSlotRec_" + +library :: FT_GlyphSlot -> Lib.FT_Library +library = (#ptr struct FT_GlyphSlotRec_, library) + +advance :: FT_GlyphSlot -> Ptr V.FT_Vector +advance = (#ptr struct FT_GlyphSlotRec_, advance) + +bitmap :: FT_GlyphSlot -> Ptr B.FT_Bitmap +bitmap = (#ptr struct FT_GlyphSlotRec_, bitmap) + +bitmap_left :: FT_GlyphSlot -> Ptr FT_Int +bitmap_left = (#ptr struct FT_GlyphSlotRec_, bitmap_left) + +bitmap_top :: FT_GlyphSlot -> Ptr FT_Int +bitmap_top = (#ptr struct FT_GlyphSlotRec_, bitmap_top)
+ Graphics/Rendering/FreeType/Internal/Library.hsc view
@@ -0,0 +1,26 @@+{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-} +module Graphics.Rendering.FreeType.Internal.Library +( FT_LibraryRec_ +, FT_Library +) where + +import Foreign +import Foreign.Storable + +#include <stddef.h> +#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__) + +#include "ft2build.h" +#include FT_FREETYPE_H + +#include "internal/ftobjs.h" + +data FT_LibraryRec_ +type FT_Library = Ptr FT_LibraryRec_ + +instance Storable FT_LibraryRec_ where + sizeOf _ = #size struct FT_LibraryRec_ + alignment _ = #alignment struct FT_LibraryRec_ + peek = error "peek not implemented for FT_LibraryRec_" + poke = error "poke not implemented for FT_LibraryRec_" +
+ Graphics/Rendering/FreeType/Internal/Matrix.hsc view
@@ -0,0 +1,35 @@+{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-} +module Graphics.Rendering.FreeType.Internal.Matrix +( FT_Matrix(..) +) where + +import Foreign +import Foreign.Storable + +import Graphics.Rendering.FreeType.Internal.PrimitiveTypes + +#include "ft2build.h" +#include FT_FREETYPE_H + +#include "internal/ftobjs.h" + +data FT_Matrix = FT_Matrix + { xx, xy :: FT_Fixed + , yx, yy :: FT_Fixed + } + deriving (Read, Show, Eq) + +instance Storable FT_Matrix where + sizeOf _ = #size FT_Matrix + alignment _ = alignment (undefined :: FT_Fixed) + peek ptr = do + xx' <- (#peek FT_Matrix, xx) ptr + xy' <- (#peek FT_Matrix, xy) ptr + yx' <- (#peek FT_Matrix, yx) ptr + yy' <- (#peek FT_Matrix, yy) ptr + return $! FT_Matrix xx' xy' yx' yy' + poke ptr val = do + (#poke FT_Matrix, xx) ptr (xx val) + (#poke FT_Matrix, xy) ptr (xy val) + (#poke FT_Matrix, yx) ptr (yx val) + (#poke FT_Matrix, yy) ptr (yy val)
+ Graphics/Rendering/FreeType/Internal/PrimitiveTypes.hsc view
@@ -0,0 +1,72 @@+{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-}+module Graphics.Rendering.FreeType.Internal.PrimitiveTypes where++import Foreign+import Foreign.C.Types++#include <stddef.h>++#include "ft2build.h"+#include FT_FREETYPE_H++ft_LOAD_DEFAULT :: FT_Int32+ft_LOAD_DEFAULT = #const FT_LOAD_DEFAULT+ft_LOAD_NO_SCALE :: FT_Int32+ft_LOAD_NO_SCALE = #const FT_LOAD_NO_SCALE+ft_LOAD_NO_HINTING :: FT_Int32+ft_LOAD_NO_HINTING = #const FT_LOAD_NO_HINTING+ft_LOAD_RENDER :: FT_Int32+ft_LOAD_RENDER = #const FT_LOAD_RENDER+ft_LOAD_NO_BITMAP :: FT_Int32+ft_LOAD_NO_BITMAP = #const FT_LOAD_NO_BITMAP+ft_LOAD_VERTICAL_LAYOUT :: FT_Int32+ft_LOAD_VERTICAL_LAYOUT = #const FT_LOAD_VERTICAL_LAYOUT+ft_LOAD_FORCE_AUTOHINT :: FT_Int32+ft_LOAD_FORCE_AUTOHINT = #const FT_LOAD_FORCE_AUTOHINT+ft_LOAD_CROP_BITMAP :: FT_Int32+ft_LOAD_CROP_BITMAP = #const FT_LOAD_CROP_BITMAP+ft_LOAD_PEDANTIC :: FT_Int32+ft_LOAD_PEDANTIC = #const FT_LOAD_PEDANTIC+ft_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH :: FT_Int32+ft_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH+ = #const FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH+ft_LOAD_NO_RECURSE :: FT_Int32+ft_LOAD_NO_RECURSE = #const FT_LOAD_NO_RECURSE+ft_LOAD_IGNORE_TRANSFORM :: FT_Int32+ft_LOAD_IGNORE_TRANSFORM = #const FT_LOAD_IGNORE_TRANSFORM+ft_LOAD_MONOCHROME :: FT_Int32+ft_LOAD_MONOCHROME = #const FT_LOAD_MONOCHROME+ft_LOAD_LINEAR_DESIGN :: FT_Int32+ft_LOAD_LINEAR_DESIGN = #const FT_LOAD_LINEAR_DESIGN+ft_LOAD_NO_AUTOHINT :: FT_Int32+ft_LOAD_NO_AUTOHINT = #const FT_LOAD_NO_AUTOHINT++type FT_Byte = CUChar+type FT_Bytes = Ptr FT_Byte+type FT_Char = CChar+type FT_Int = CInt+type FT_UInt = CUInt+type FT_Int16 = CShort+type FT_UInt16 = CUShort+type FT_Int32 = Int32+type FT_UInt32 = Word32+type FT_Short = CShort+type FT_UShort = CUShort+type FT_Long = CLong+type FT_ULong = CULong+type FT_Bool = CUChar+type FT_Offset = #type size_t+type FT_Error = CInt+type FT_F26Dot6 = CLong+type FT_Fixed = CLong+type FT_Pos = CLong++newtype FT_Render_Mode = FT_Render_Mode CUInt++#{enum FT_Render_Mode, FT_Render_Mode,+ ft_RENDER_MODE_NORMAL = FT_RENDER_MODE_NORMAL,+ ft_RENDER_MODE_LIGHT = FT_RENDER_MODE_LIGHT,+ ft_RENDER_MODE_MONO = FT_RENDER_MODE_MONO,+ ft_RENDER_MODE_LCD = FT_RENDER_MODE_LCD,+ ft_RENDER_MODE_LCD_V = FT_RENDER_MODE_LCD_V+}
+ Graphics/Rendering/FreeType/Internal/Vector.hsc view
@@ -0,0 +1,28 @@+{-# LANGUAGE ForeignFunctionInterface #-} +module Graphics.Rendering.FreeType.Internal.Vector +( FT_Vector(..) +) where + +import Foreign.Storable + +import Graphics.Rendering.FreeType.Internal.PrimitiveTypes + +#include "ft2build.h" +#include FT_FREETYPE_H + +data FT_Vector = FT_Vector + { x :: FT_Pos + , y :: FT_Pos + } + deriving (Read, Show, Eq) + +instance Storable FT_Vector where + sizeOf _ = #size FT_Vector + alignment _ = alignment (undefined :: FT_Pos) + peek ptr = do + x' <- (#peek FT_Vector, x) ptr + y' <- (#peek FT_Vector, y) ptr + return $! FT_Vector x' y' + poke ptr val = do + (#poke FT_Vector, x) ptr (x val) + (#poke FT_Vector, y) ptr (y val)
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c)2011, Jason Dagit <dagitj@gmail.com> + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of Jason Dagit <dagitj@gmail.com> nor the names of other + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Main.hs view
@@ -0,0 +1,115 @@+module Main where + +import Control.Monad +import System.Environment +import Graphics.Rendering.FreeType.Internal as FT +import Graphics.Rendering.FreeType.Internal.Matrix as M +import Graphics.Rendering.FreeType.Internal.Vector as V +import Graphics.Rendering.FreeType.Internal.GlyphSlot as GS +import Graphics.Rendering.FreeType.Internal.PrimitiveTypes as PT +import Graphics.Rendering.FreeType.Internal.Face as F +import Graphics.Rendering.FreeType.Internal.Library as L +import Graphics.Rendering.FreeType.Internal.Bitmap as B + +import Foreign +import Foreign.Marshal +import Foreign.Marshal.MissingAlloc +import Foreign.C.String + +import System.Exit + +import Data.Array.IO as A + +main :: IO () +main = do + let width = 640 + height = 480 + angle = (25 / 360) * pi * 2 + matrix <- mallocForeignPtr + pen <- mallocForeignPtr + withForeignPtr matrix $ \p-> poke p (FT_Matrix + { xx = round $ cos angle * 0x10000 + , xy = round $ -(sin angle * 0x10000) + , yx = round $ sin angle * 0x10000 + , yy = round $ cos angle * 0x10000 + }) + withForeignPtr pen $ \p -> poke p (FT_Vector + { x = 300 * 64 + , y = (height - 200) * 64 + }) + (filename:text:_) <- getArgs + + libraryptr <- calloc + library <- do + print $ libraryptr == nullPtr + ft_Init_FreeType libraryptr >>= print + peek libraryptr + + faceptr <- calloc + print $ faceptr == nullPtr + face <- withCString filename $ \str -> do + print =<< ft_New_Face library str 0 faceptr + peek faceptr + + image <- A.newArray + ((0,0), (fromIntegral height - 1, fromIntegral width - 1)) 0 + :: IO (IOUArray (Int, Int) Int) + + print =<< ft_Set_Char_Size face (50*64) 0 100 0 + forM_ text $ \c -> do + withForeignPtr matrix $ \mp -> + withForeignPtr pen $ \pp -> do + ft_Set_Transform face mp pp + slot <- peek $ glyph face + print =<< ft_Load_Char face + (fromIntegral . fromEnum $ c) + ft_LOAD_RENDER + numFaces <- peek $ num_faces face + putStrLn $ "face->num_faces = " ++ show numFaces + v <- peek $ advance slot + putStrLn "advance: " + print v + numGlyphs <- peek $ num_glyphs face + putStrLn $ "numGlyphs = " ++ show numGlyphs + pen' <- peek pp + poke pp $ FT_Vector { x = x v + x pen' + , y = y v + y pen' } + b <- peek $ bitmap slot + left <- peek $ bitmap_left slot + top <- peek $ bitmap_top slot + drawBitmap b + image + left + (fromIntegral height - top) + showImage image + print =<< ft_Done_Face face + print =<< ft_Done_FreeType library + + +drawBitmap :: FT_Bitmap -> IOUArray (Int, Int) Int + -> FT_Int -> FT_Int -> IO () +drawBitmap bitmap image x y = do + let xMax = x + width bitmap + yMax = y + rows bitmap + forM_ (zip [ x .. xMax - 1] [0 .. ]) $ \(i,p) -> + forM_ (zip [ y .. yMax - 1] [0 .. ]) $ \(j,q) -> do + let index = q * width bitmap + p + v <- readArray image (fromIntegral j, fromIntegral i) :: IO Int + b <- peek $ (buffer bitmap) `plusPtr` fromIntegral index + writeArray image (fromIntegral j, fromIntegral i) $ v .|. b + +showImage :: IOUArray (Int, Int) Int -> IO () +showImage image = do + ((hmin,wmin), (hmax,wmax)) <- getBounds image + forM_ [ hmin .. hmax ] $ \i -> do + forM_ [ wmin .. wmax ] $ \j -> do + v <- readArray image (i,j) + putc v + putChar '\n' + where + putc :: Int -> IO () + putc c + | c == 0 = putChar '0' + | c < 128 = putChar '+' + | otherwise = putChar '*' +
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple +main = defaultMain
+ freetype2.cabal view
@@ -0,0 +1,251 @@+Name: freetype2+Version: 0.0.1+Synopsis: Haskell binding for FreeType 2 library+Description: Wrapper around FreeType 2 library. Relevant+ exerpts from the FreeType 2 website:+ .+ What is FreeType 2?+ .+ FreeType 2 is a software font engine that is+ designed to be small, efficient, highly+ customizable, and portable while capable of+ producing high-quality output (glyph images). It+ can be used in graphics libraries, display+ servers, font conversion tools, text image+ generation tools, and many other products as+ well.+ .+ The following is a non-exhaustive list of+ features provided by FreeType 2.+ .+ * FreeType 2 provides a simple and easy-to-use+ API to access font content in a uniform way,+ independently of the file format. Additionally,+ some format-specific APIs can be used to access+ special data in the font file.+ .+ * Unlike most comparable libraries, FreeType 2+ supports scalable font formats like TrueType or+ Type 1 natively and can return the outline data+ (and control instructions/hints) to client+ applications.+ .+ By default, FreeType 2 supports the following+ font formats.+ .+ * TrueType fonts (and collections)+ .+ * Type 1 fonts+ .+ * CID-keyed Type 1 fonts+ .+ * CFF fonts+ .+ * OpenType fonts (both TrueType and CFF variants)+ .+ * SFNT-based bitmap fonts+ .+ * X11 PCF fonts+ .+ * Windows FNT fonts+ .+ * BDF fonts (including anti-aliased ones)+ .+ * PFR fonts+ .+ * Type 42 fonts (limited support)+ .+ From a given glyph outline, FreeType 2 is capable+ of producing a high-quality monochrome bitmap, or+ anti-aliased pixmap, using 256 levels of+ 'gray'. This is much better than the 5 levels+ used by Windows 9x\/98\/NT\/2000 or FreeType 1.+ .+ FreeType 2 supports all the character mappings+ defined by the TrueType and OpenType+ specification. It is also capable of+ automatically synthetizing a Unicode charmap from+ Type 1 fonts, which puts an end to the painful+ 'encoding translation' headache common with this+ format (of course, original encodings are also+ available in the case where you need them).+ .+ The FreeType 2 core API provides simple functions+ to access advanced information like glyph names+ or kerning data.+ .+ FreeType 2 provides information that is often not+ available from other similar font engines, like+ kerning distances, glyph names, vertical metrics,+ etc.+ .+ FreeType 2 provides its own caching subsystem+ since release 2.0.1. It can be used to cache+ either face instances or glyph images+ efficiently.+License: BSD3+License-file: LICENSE+Author: Jason Dagit <dagitj@gmail.com>+Maintainer: Jason Dagit <dagitj@gmail.com>+Copyright: Copyright Jason Dagit 2011+Category: Graphics+Build-type: Simple+Extra-source-files: objs/ftmodule.h+ include/*.h+ include/freetype/*.h+ include/freetype/config/*.h+ include/freetype/internal/*.h+ include/freetype/internal/services/*.h+ src/base/*.h+ src/base/*.c+ src/truetype/*.h+ src/truetype/*.c+ src/type1/*.h+ src/type1/*.c+ src/cff/*.h+ src/cff/*.c+ src/cid/*.h+ src/cid/*.c+ src/pfr/*.h+ src/pfr/*.c+ src/type42/*.h+ src/type42/*.c+ src/winfonts/*.h+ src/winfonts/*.c+ src/pcf/*.h+ src/pcf/*.c+ src/bdf/*.h+ src/bdf/*.c+ src/sfnt/*.h+ src/sfnt/*.c+ src/autofit/*.h+ src/autofit/*.c+ src/pshinter/*.h+ src/pshinter/*.c+ src/raster/*.h+ src/raster/*.c+ src/smooth/*.h+ src/smooth/*.c+ src/cache/*.h+ src/cache/*.c+ src/gzip/*.h+ src/gzip/*.c+ src/lzw/*.h+ src/lzw/*.c+ src/psaux/*.h+ src/psaux/*.c+ src/psnames/*.h+ src/psnames/*.c++Cabal-version: >=1.8++Flag examples+ Description: Build example programs+ Default: False++Executable freetype-example1++ if flag(examples)+ Buildable: True+ Build-depends: base > 3 && < 5, freetype2, array,+ missing-foreign >= 0.1.1 && < 0.2.0+ else+ Buildable: False+ Main-is: Main.hs++Library+ -- Modules exported by the library.+ Exposed-modules: Graphics.Rendering.FreeType.Internal+ Graphics.Rendering.FreeType.Internal.Bitmap+ Graphics.Rendering.FreeType.Internal.Face+ Graphics.Rendering.FreeType.Internal.GlyphSlot+ Graphics.Rendering.FreeType.Internal.Library+ Graphics.Rendering.FreeType.Internal.Matrix+ Graphics.Rendering.FreeType.Internal.PrimitiveTypes+ Graphics.Rendering.FreeType.Internal.Vector+ Graphics.Rendering.FreeType.Internal.Glyph++ -- Packages needed in order to build this package.+ Build-depends: base > 3 && < 5++ -- Modules not exported by this package.+ -- Other-modules: ++ -- Extra tools (e.g. alex, hsc2hs, ...) needed to build the source.+ Build-tools: hsc2hs+ ghc-options: -Wall+ include-dirs: objs include include/freetype/config+ include/freetype+ src/base+ src/truetype+ src/type1+ src/cff+ src/cid+ src/pfr+ src/type42+ src/winfonts+ src/pcf+ src/bdf+ src/sfnt+ src/autofit+ src/pshinter+ src/raster+ src/smooth+ src/cache+ src/gzip+ src/lzw+ src/psaux+ src/psnames++ cc-options: -DFT_CONFIG_CONFIG_H=<ftconfig.h>+ -DFT2_BUILD_LIBRARY+ -DFT_CONFIG_MODULES_H=<ftmodule.h>+ -DDARWIN_NO_CARBON++ c-sources:+ src/base/ftsystem.c+ src/base/ftdebug.c+ src/base/ftinit.c+ src/base/ftbase.c+ src/base/ftbbox.c+ src/base/ftbdf.c+ src/base/ftbitmap.c+ src/base/ftcid.c+ src/base/ftfstype.c+ src/base/ftgasp.c+ src/base/ftglyph.c+ src/base/ftgxval.c+ src/base/ftlcdfil.c+ src/base/ftmm.c+ src/base/ftotval.c+ src/base/ftpatent.c+ src/base/ftpfr.c+ src/base/ftstroke.c+ src/base/ftsynth.c+ src/base/fttype1.c+ src/base/ftwinfnt.c+ src/base/ftxf86.c+ src/truetype/truetype.c+ src/type1/type1.c+ src/cff/cff.c+ src/cid/type1cid.c+ src/pfr/pfr.c+ src/type42/type42.c+ src/winfonts/winfnt.c+ src/pcf/pcf.c+ src/bdf/bdf.c+ src/sfnt/sfnt.c+ src/autofit/autofit.c+ src/pshinter/pshinter.c+ src/raster/raster.c+ src/smooth/smooth.c+ src/cache/ftcache.c+ src/gzip/ftgzip.c+ src/lzw/ftlzw.c+ src/psaux/psaux.c+ src/psnames/psmodule.c++source-repository head+ type: git+ location: git://github.com/dagit/freetype2.git+
+ include/freetype/config/ftconfig.h view
@@ -0,0 +1,528 @@+/***************************************************************************/+/* */+/* ftconfig.h */+/* */+/* ANSI-specific configuration file (specification only). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007, 2008, 2010 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++ /*************************************************************************/+ /* */+ /* This header file contains a number of macro definitions that are used */+ /* by the rest of the engine. Most of the macros here are automatically */+ /* determined at compile time, and you should not need to change it to */+ /* port FreeType, except to compile the library with a non-ANSI */+ /* compiler. */+ /* */+ /* Note however that if some specific modifications are needed, we */+ /* advise you to place a modified copy in your build directory. */+ /* */+ /* The build directory is usually `freetype/builds/<system>', and */+ /* contains system-specific files that are always included first when */+ /* building the library. */+ /* */+ /* This ANSI version should stay in `include/freetype/config'. */+ /* */+ /*************************************************************************/++#ifndef __FTCONFIG_H__+#define __FTCONFIG_H__++#include <ft2build.h>+#include FT_CONFIG_OPTIONS_H+#include FT_CONFIG_STANDARD_LIBRARY_H+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* PLATFORM-SPECIFIC CONFIGURATION MACROS */+ /* */+ /* These macros can be toggled to suit a specific system. The current */+ /* ones are defaults used to compile FreeType in an ANSI C environment */+ /* (16bit compilers are also supported). Copy this file to your own */+ /* `freetype/builds/<system>' directory, and edit it to port the engine. */+ /* */+ /*************************************************************************/+++ /* There are systems (like the Texas Instruments 'C54x) where a `char' */+ /* has 16 bits. ANSI C says that sizeof(char) is always 1. Since an */+ /* `int' has 16 bits also for this system, sizeof(int) gives 1 which */+ /* is probably unexpected. */+ /* */+ /* `CHAR_BIT' (defined in limits.h) gives the number of bits in a */+ /* `char' type. */++#ifndef FT_CHAR_BIT+#define FT_CHAR_BIT CHAR_BIT+#endif+++ /* The size of an `int' type. */+#if FT_UINT_MAX == 0xFFFFUL+#define FT_SIZEOF_INT (16 / FT_CHAR_BIT)+#elif FT_UINT_MAX == 0xFFFFFFFFUL+#define FT_SIZEOF_INT (32 / FT_CHAR_BIT)+#elif FT_UINT_MAX > 0xFFFFFFFFUL && FT_UINT_MAX == 0xFFFFFFFFFFFFFFFFUL+#define FT_SIZEOF_INT (64 / FT_CHAR_BIT)+#else+#error "Unsupported size of `int' type!"+#endif++ /* The size of a `long' type. A five-byte `long' (as used e.g. on the */+ /* DM642) is recognized but avoided. */+#if FT_ULONG_MAX == 0xFFFFFFFFUL+#define FT_SIZEOF_LONG (32 / FT_CHAR_BIT)+#elif FT_ULONG_MAX > 0xFFFFFFFFUL && FT_ULONG_MAX == 0xFFFFFFFFFFUL+#define FT_SIZEOF_LONG (32 / FT_CHAR_BIT)+#elif FT_ULONG_MAX > 0xFFFFFFFFUL && FT_ULONG_MAX == 0xFFFFFFFFFFFFFFFFUL+#define FT_SIZEOF_LONG (64 / FT_CHAR_BIT)+#else+#error "Unsupported size of `long' type!"+#endif+++ /* Preferred alignment of data */+#define FT_ALIGNMENT 8+++ /* FT_UNUSED is a macro used to indicate that a given parameter is not */+ /* used -- this is only used to get rid of unpleasant compiler warnings */+#ifndef FT_UNUSED+#define FT_UNUSED( arg ) ( (arg) = (arg) )+#endif+++ /*************************************************************************/+ /* */+ /* AUTOMATIC CONFIGURATION MACROS */+ /* */+ /* These macros are computed from the ones defined above. Don't touch */+ /* their definition, unless you know precisely what you are doing. No */+ /* porter should need to mess with them. */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* Mac support */+ /* */+ /* This is the only necessary change, so it is defined here instead */+ /* providing a new configuration file. */+ /* */+#if ( defined( __APPLE__ ) && !defined( DARWIN_NO_CARBON ) ) || \+ ( defined( __MWERKS__ ) && defined( macintosh ) )+ /* no Carbon frameworks for 64bit 10.4.x */+#include "AvailabilityMacros.h"+#if defined( __LP64__ ) && \+ ( MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 )+#define DARWIN_NO_CARBON 1+#else+#define FT_MACINTOSH 1+#endif++#elif defined( __SC__ ) || defined( __MRC__ )+ /* Classic MacOS compilers */+#include "ConditionalMacros.h"+#if TARGET_OS_MAC+#define FT_MACINTOSH 1+#endif++#endif+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* basic_types */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_Int16 */+ /* */+ /* <Description> */+ /* A typedef for a 16bit signed integer type. */+ /* */+ typedef signed short FT_Int16;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_UInt16 */+ /* */+ /* <Description> */+ /* A typedef for a 16bit unsigned integer type. */+ /* */+ typedef unsigned short FT_UInt16;++ /* */+++ /* this #if 0 ... #endif clause is for documentation purposes */+#if 0++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_Int32 */+ /* */+ /* <Description> */+ /* A typedef for a 32bit signed integer type. The size depends on */+ /* the configuration. */+ /* */+ typedef signed XXX FT_Int32;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_UInt32 */+ /* */+ /* A typedef for a 32bit unsigned integer type. The size depends on */+ /* the configuration. */+ /* */+ typedef unsigned XXX FT_UInt32;++ /* */++#endif++#if FT_SIZEOF_INT == (32 / FT_CHAR_BIT)++ typedef signed int FT_Int32;+ typedef unsigned int FT_UInt32;++#elif FT_SIZEOF_LONG == (32 / FT_CHAR_BIT)++ typedef signed long FT_Int32;+ typedef unsigned long FT_UInt32;++#else+#error "no 32bit type found -- please check your configuration files"+#endif+++ /* look up an integer type that is at least 32 bits */+#if FT_SIZEOF_INT >= (32 / FT_CHAR_BIT)++ typedef int FT_Fast;+ typedef unsigned int FT_UFast;++#elif FT_SIZEOF_LONG >= (32 / FT_CHAR_BIT)++ typedef long FT_Fast;+ typedef unsigned long FT_UFast;++#endif+++ /* determine whether we have a 64-bit int type for platforms without */+ /* Autoconf */+#if FT_SIZEOF_LONG == (64 / FT_CHAR_BIT)++ /* FT_LONG64 must be defined if a 64-bit type is available */+#define FT_LONG64+#define FT_INT64 long++#elif defined( _MSC_VER ) && _MSC_VER >= 900 /* Visual C++ (and Intel C++) */++ /* this compiler provides the __int64 type */+#define FT_LONG64+#define FT_INT64 __int64++#elif defined( __BORLANDC__ ) /* Borland C++ */++ /* XXXX: We should probably check the value of __BORLANDC__ in order */+ /* to test the compiler version. */++ /* this compiler provides the __int64 type */+#define FT_LONG64+#define FT_INT64 __int64++#elif defined( __WATCOMC__ ) /* Watcom C++ */++ /* Watcom doesn't provide 64-bit data types */++#elif defined( __MWERKS__ ) /* Metrowerks CodeWarrior */++#define FT_LONG64+#define FT_INT64 long long int++#elif defined( __GNUC__ )++ /* GCC provides the `long long' type */+#define FT_LONG64+#define FT_INT64 long long int++#endif /* FT_SIZEOF_LONG == (64 / FT_CHAR_BIT) */+++ /*************************************************************************/+ /* */+ /* A 64-bit data type will create compilation problems if you compile */+ /* in strict ANSI mode. To avoid them, we disable its use if __STDC__ */+ /* is defined. You can however ignore this rule by defining the */+ /* FT_CONFIG_OPTION_FORCE_INT64 configuration macro. */+ /* */+#if defined( FT_LONG64 ) && !defined( FT_CONFIG_OPTION_FORCE_INT64 )++#ifdef __STDC__++ /* undefine the 64-bit macros in strict ANSI compilation mode */+#undef FT_LONG64+#undef FT_INT64++#endif /* __STDC__ */++#endif /* FT_LONG64 && !FT_CONFIG_OPTION_FORCE_INT64 */+++#define FT_BEGIN_STMNT do {+#define FT_END_STMNT } while ( 0 )+#define FT_DUMMY_STMNT FT_BEGIN_STMNT FT_END_STMNT+++#ifndef FT_CONFIG_OPTION_NO_ASSEMBLER+ /* Provide assembler fragments for performance-critical functions. */+ /* These must be defined `static __inline__' with GCC. */++#if defined( __CC_ARM ) || defined( __ARMCC__ ) /* RVCT */+#define FT_MULFIX_ASSEMBLER FT_MulFix_arm++ /* documentation is in freetype.h */++ static __inline FT_Int32+ FT_MulFix_arm( FT_Int32 a,+ FT_Int32 b )+ {+ register FT_Int32 t, t2;+++ __asm+ {+ smull t2, t, b, a /* (lo=t2,hi=t) = a*b */+ mov a, t, asr #31 /* a = (hi >> 31) */+ add a, a, #0x8000 /* a += 0x8000 */+ adds t2, t2, a /* t2 += a */+ adc t, t, #0 /* t += carry */+ mov a, t2, lsr #16 /* a = t2 >> 16 */+ orr a, a, t, lsl #16 /* a |= t << 16 */+ }+ return a;+ }++#endif /* __CC_ARM || __ARMCC__ */+++#ifdef __GNUC__++#if defined( __arm__ ) && !defined( __thumb__ ) && \+ !( defined( __CC_ARM ) || defined( __ARMCC__ ) )+#define FT_MULFIX_ASSEMBLER FT_MulFix_arm++ /* documentation is in freetype.h */++ static __inline__ FT_Int32+ FT_MulFix_arm( FT_Int32 a,+ FT_Int32 b )+ {+ register FT_Int32 t, t2;+++ asm __volatile__ (+ "smull %1, %2, %4, %3\n\t" /* (lo=%1,hi=%2) = a*b */+ "mov %0, %2, asr #31\n\t" /* %0 = (hi >> 31) */+ "add %0, %0, #0x8000\n\t" /* %0 += 0x8000 */+ "adds %1, %1, %0\n\t" /* %1 += %0 */+ "adc %2, %2, #0\n\t" /* %2 += carry */+ "mov %0, %1, lsr #16\n\t" /* %0 = %1 >> 16 */+ "orr %0, %2, lsl #16\n\t" /* %0 |= %2 << 16 */+ : "=r"(a), "=&r"(t2), "=&r"(t)+ : "r"(a), "r"(b) );+ return a;+ }++#endif /* __arm__ && !__thumb__ && !( __CC_ARM || __ARMCC__ ) */++#if defined( __i386__ )+#define FT_MULFIX_ASSEMBLER FT_MulFix_i386++ /* documentation is in freetype.h */++ static __inline__ FT_Int32+ FT_MulFix_i386( FT_Int32 a,+ FT_Int32 b )+ {+ register FT_Int32 result;+++ __asm__ __volatile__ (+ "imul %%edx\n"+ "movl %%edx, %%ecx\n"+ "sarl $31, %%ecx\n"+ "addl $0x8000, %%ecx\n"+ "addl %%ecx, %%eax\n"+ "adcl $0, %%edx\n"+ "shrl $16, %%eax\n"+ "shll $16, %%edx\n"+ "addl %%edx, %%eax\n"+ : "=a"(result), "=d"(b)+ : "a"(a), "d"(b)+ : "%ecx", "cc" );+ return result;+ }++#endif /* i386 */++#endif /* __GNUC__ */++#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */+++#ifdef FT_CONFIG_OPTION_INLINE_MULFIX+#ifdef FT_MULFIX_ASSEMBLER+#define FT_MULFIX_INLINED FT_MULFIX_ASSEMBLER+#endif+#endif+++#ifdef FT_MAKE_OPTION_SINGLE_OBJECT++#define FT_LOCAL( x ) static x+#define FT_LOCAL_DEF( x ) static x++#else++#ifdef __cplusplus+#define FT_LOCAL( x ) extern "C" x+#define FT_LOCAL_DEF( x ) extern "C" x+#else+#define FT_LOCAL( x ) extern x+#define FT_LOCAL_DEF( x ) x+#endif++#endif /* FT_MAKE_OPTION_SINGLE_OBJECT */+++#ifndef FT_BASE++#ifdef __cplusplus+#define FT_BASE( x ) extern "C" x+#else+#define FT_BASE( x ) extern x+#endif++#endif /* !FT_BASE */+++#ifndef FT_BASE_DEF++#ifdef __cplusplus+#define FT_BASE_DEF( x ) x+#else+#define FT_BASE_DEF( x ) x+#endif++#endif /* !FT_BASE_DEF */+++#ifndef FT_EXPORT++#ifdef __cplusplus+#define FT_EXPORT( x ) extern "C" x+#else+#define FT_EXPORT( x ) extern x+#endif++#endif /* !FT_EXPORT */+++#ifndef FT_EXPORT_DEF++#ifdef __cplusplus+#define FT_EXPORT_DEF( x ) extern "C" x+#else+#define FT_EXPORT_DEF( x ) extern x+#endif++#endif /* !FT_EXPORT_DEF */+++#ifndef FT_EXPORT_VAR++#ifdef __cplusplus+#define FT_EXPORT_VAR( x ) extern "C" x+#else+#define FT_EXPORT_VAR( x ) extern x+#endif++#endif /* !FT_EXPORT_VAR */++ /* The following macros are needed to compile the library with a */+ /* C++ compiler and with 16bit compilers. */+ /* */++ /* This is special. Within C++, you must specify `extern "C"' for */+ /* functions which are used via function pointers, and you also */+ /* must do that for structures which contain function pointers to */+ /* assure C linkage -- it's not possible to have (local) anonymous */+ /* functions which are accessed by (global) function pointers. */+ /* */+ /* */+ /* FT_CALLBACK_DEF is used to _define_ a callback function. */+ /* */+ /* FT_CALLBACK_TABLE is used to _declare_ a constant variable that */+ /* contains pointers to callback functions. */+ /* */+ /* FT_CALLBACK_TABLE_DEF is used to _define_ a constant variable */+ /* that contains pointers to callback functions. */+ /* */+ /* */+ /* Some 16bit compilers have to redefine these macros to insert */+ /* the infamous `_cdecl' or `__fastcall' declarations. */+ /* */+#ifndef FT_CALLBACK_DEF+#ifdef __cplusplus+#define FT_CALLBACK_DEF( x ) extern "C" x+#else+#define FT_CALLBACK_DEF( x ) static x+#endif+#endif /* FT_CALLBACK_DEF */++#ifndef FT_CALLBACK_TABLE+#ifdef __cplusplus+#define FT_CALLBACK_TABLE extern "C"+#define FT_CALLBACK_TABLE_DEF extern "C"+#else+#define FT_CALLBACK_TABLE extern+#define FT_CALLBACK_TABLE_DEF /* nothing */+#endif+#endif /* FT_CALLBACK_TABLE */+++FT_END_HEADER+++#endif /* __FTCONFIG_H__ */+++/* END */
+ include/freetype/config/ftheader.h view
@@ -0,0 +1,780 @@+/***************************************************************************/+/* */+/* ftheader.h */+/* */+/* Build macros of the FreeType 2 library. */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 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 __FT_HEADER_H__+#define __FT_HEADER_H__+++ /*@***********************************************************************/+ /* */+ /* <Macro> */+ /* FT_BEGIN_HEADER */+ /* */+ /* <Description> */+ /* This macro is used in association with @FT_END_HEADER in header */+ /* files to ensure that the declarations within are properly */+ /* encapsulated in an `extern "C" { .. }' block when included from a */+ /* C++ compiler. */+ /* */+#ifdef __cplusplus+#define FT_BEGIN_HEADER extern "C" {+#else+#define FT_BEGIN_HEADER /* nothing */+#endif+++ /*@***********************************************************************/+ /* */+ /* <Macro> */+ /* FT_END_HEADER */+ /* */+ /* <Description> */+ /* This macro is used in association with @FT_BEGIN_HEADER in header */+ /* files to ensure that the declarations within are properly */+ /* encapsulated in an `extern "C" { .. }' block when included from a */+ /* C++ compiler. */+ /* */+#ifdef __cplusplus+#define FT_END_HEADER }+#else+#define FT_END_HEADER /* nothing */+#endif+++ /*************************************************************************/+ /* */+ /* Aliases for the FreeType 2 public and configuration files. */+ /* */+ /*************************************************************************/++ /*************************************************************************/+ /* */+ /* <Section> */+ /* header_file_macros */+ /* */+ /* <Title> */+ /* Header File Macros */+ /* */+ /* <Abstract> */+ /* Macro definitions used to #include specific header files. */+ /* */+ /* <Description> */+ /* The following macros are defined to the name of specific */+ /* FreeType~2 header files. They can be used directly in #include */+ /* statements as in: */+ /* */+ /* { */+ /* #include FT_FREETYPE_H */+ /* #include FT_MULTIPLE_MASTERS_H */+ /* #include FT_GLYPH_H */+ /* } */+ /* */+ /* There are several reasons why we are now using macros to name */+ /* public header files. The first one is that such macros are not */+ /* limited to the infamous 8.3~naming rule required by DOS (and */+ /* `FT_MULTIPLE_MASTERS_H' is a lot more meaningful than `ftmm.h'). */+ /* */+ /* The second reason is that it allows for more flexibility in the */+ /* way FreeType~2 is installed on a given system. */+ /* */+ /*************************************************************************/+++ /* configuration files */++ /*************************************************************************+ *+ * @macro:+ * FT_CONFIG_CONFIG_H+ *+ * @description:+ * A macro used in #include statements to name the file containing+ * FreeType~2 configuration data.+ *+ */+#ifndef FT_CONFIG_CONFIG_H+#define FT_CONFIG_CONFIG_H <freetype/config/ftconfig.h>+#endif+++ /*************************************************************************+ *+ * @macro:+ * FT_CONFIG_STANDARD_LIBRARY_H+ *+ * @description:+ * A macro used in #include statements to name the file containing+ * FreeType~2 interface to the standard C library functions.+ *+ */+#ifndef FT_CONFIG_STANDARD_LIBRARY_H+#define FT_CONFIG_STANDARD_LIBRARY_H <freetype/config/ftstdlib.h>+#endif+++ /*************************************************************************+ *+ * @macro:+ * FT_CONFIG_OPTIONS_H+ *+ * @description:+ * A macro used in #include statements to name the file containing+ * FreeType~2 project-specific configuration options.+ *+ */+#ifndef FT_CONFIG_OPTIONS_H+#define FT_CONFIG_OPTIONS_H <freetype/config/ftoption.h>+#endif+++ /*************************************************************************+ *+ * @macro:+ * FT_CONFIG_MODULES_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * list of FreeType~2 modules that are statically linked to new library+ * instances in @FT_Init_FreeType.+ *+ */+#ifndef FT_CONFIG_MODULES_H+#define FT_CONFIG_MODULES_H <freetype/config/ftmodule.h>+#endif++ /* */++ /* public headers */++ /*************************************************************************+ *+ * @macro:+ * FT_FREETYPE_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * base FreeType~2 API.+ *+ */+#define FT_FREETYPE_H <freetype/freetype.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_ERRORS_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * list of FreeType~2 error codes (and messages).+ *+ * It is included by @FT_FREETYPE_H.+ *+ */+#define FT_ERRORS_H <freetype/fterrors.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_MODULE_ERRORS_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * list of FreeType~2 module error offsets (and messages).+ *+ */+#define FT_MODULE_ERRORS_H <freetype/ftmoderr.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_SYSTEM_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * FreeType~2 interface to low-level operations (i.e., memory management+ * and stream i/o).+ *+ * It is included by @FT_FREETYPE_H.+ *+ */+#define FT_SYSTEM_H <freetype/ftsystem.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_IMAGE_H+ *+ * @description:+ * A macro used in #include statements to name the file containing type+ * definitions related to glyph images (i.e., bitmaps, outlines,+ * scan-converter parameters).+ *+ * It is included by @FT_FREETYPE_H.+ *+ */+#define FT_IMAGE_H <freetype/ftimage.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_TYPES_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * basic data types defined by FreeType~2.+ *+ * It is included by @FT_FREETYPE_H.+ *+ */+#define FT_TYPES_H <freetype/fttypes.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_LIST_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * list management API of FreeType~2.+ *+ * (Most applications will never need to include this file.)+ *+ */+#define FT_LIST_H <freetype/ftlist.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_OUTLINE_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * scalable outline management API of FreeType~2.+ *+ */+#define FT_OUTLINE_H <freetype/ftoutln.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_SIZES_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * API which manages multiple @FT_Size objects per face.+ *+ */+#define FT_SIZES_H <freetype/ftsizes.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_MODULE_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * module management API of FreeType~2.+ *+ */+#define FT_MODULE_H <freetype/ftmodapi.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_RENDER_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * renderer module management API of FreeType~2.+ *+ */+#define FT_RENDER_H <freetype/ftrender.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_TYPE1_TABLES_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * types and API specific to the Type~1 format.+ *+ */+#define FT_TYPE1_TABLES_H <freetype/t1tables.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_TRUETYPE_IDS_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * enumeration values which identify name strings, languages, encodings,+ * etc. This file really contains a _large_ set of constant macro+ * definitions, taken from the TrueType and OpenType specifications.+ *+ */+#define FT_TRUETYPE_IDS_H <freetype/ttnameid.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_TRUETYPE_TABLES_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * types and API specific to the TrueType (as well as OpenType) format.+ *+ */+#define FT_TRUETYPE_TABLES_H <freetype/tttables.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_TRUETYPE_TAGS_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * definitions of TrueType four-byte `tags' which identify blocks in+ * SFNT-based font formats (i.e., TrueType and OpenType).+ *+ */+#define FT_TRUETYPE_TAGS_H <freetype/tttags.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_BDF_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * definitions of an API which accesses BDF-specific strings from a+ * face.+ *+ */+#define FT_BDF_H <freetype/ftbdf.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_CID_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * definitions of an API which access CID font information from a+ * face.+ *+ */+#define FT_CID_H <freetype/ftcid.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_GZIP_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * definitions of an API which supports gzip-compressed files.+ *+ */+#define FT_GZIP_H <freetype/ftgzip.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_LZW_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * definitions of an API which supports LZW-compressed files.+ *+ */+#define FT_LZW_H <freetype/ftlzw.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_WINFONTS_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * definitions of an API which supports Windows FNT files.+ *+ */+#define FT_WINFONTS_H <freetype/ftwinfnt.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_GLYPH_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * API of the optional glyph management component.+ *+ */+#define FT_GLYPH_H <freetype/ftglyph.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_BITMAP_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * API of the optional bitmap conversion component.+ *+ */+#define FT_BITMAP_H <freetype/ftbitmap.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_BBOX_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * API of the optional exact bounding box computation routines.+ *+ */+#define FT_BBOX_H <freetype/ftbbox.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_CACHE_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * API of the optional FreeType~2 cache sub-system.+ *+ */+#define FT_CACHE_H <freetype/ftcache.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_CACHE_IMAGE_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * `glyph image' API of the FreeType~2 cache sub-system.+ *+ * It is used to define a cache for @FT_Glyph elements. You can also+ * use the API defined in @FT_CACHE_SMALL_BITMAPS_H if you only need to+ * store small glyph bitmaps, as it will use less memory.+ *+ * This macro is deprecated. Simply include @FT_CACHE_H to have all+ * glyph image-related cache declarations.+ *+ */+#define FT_CACHE_IMAGE_H FT_CACHE_H+++ /*************************************************************************+ *+ * @macro:+ * FT_CACHE_SMALL_BITMAPS_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * `small bitmaps' API of the FreeType~2 cache sub-system.+ *+ * It is used to define a cache for small glyph bitmaps in a relatively+ * memory-efficient way. You can also use the API defined in+ * @FT_CACHE_IMAGE_H if you want to cache arbitrary glyph images,+ * including scalable outlines.+ *+ * This macro is deprecated. Simply include @FT_CACHE_H to have all+ * small bitmaps-related cache declarations.+ *+ */+#define FT_CACHE_SMALL_BITMAPS_H FT_CACHE_H+++ /*************************************************************************+ *+ * @macro:+ * FT_CACHE_CHARMAP_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * `charmap' API of the FreeType~2 cache sub-system.+ *+ * This macro is deprecated. Simply include @FT_CACHE_H to have all+ * charmap-based cache declarations.+ *+ */+#define FT_CACHE_CHARMAP_H FT_CACHE_H+++ /*************************************************************************+ *+ * @macro:+ * FT_MAC_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * Macintosh-specific FreeType~2 API. The latter is used to access+ * fonts embedded in resource forks.+ *+ * This header file must be explicitly included by client applications+ * compiled on the Mac (note that the base API still works though).+ *+ */+#define FT_MAC_H <freetype/ftmac.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_MULTIPLE_MASTERS_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * optional multiple-masters management API of FreeType~2.+ *+ */+#define FT_MULTIPLE_MASTERS_H <freetype/ftmm.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_SFNT_NAMES_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * optional FreeType~2 API which accesses embedded `name' strings in+ * SFNT-based font formats (i.e., TrueType and OpenType).+ *+ */+#define FT_SFNT_NAMES_H <freetype/ftsnames.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_OPENTYPE_VALIDATE_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * optional FreeType~2 API which validates OpenType tables (BASE, GDEF,+ * GPOS, GSUB, JSTF).+ *+ */+#define FT_OPENTYPE_VALIDATE_H <freetype/ftotval.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_GX_VALIDATE_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * optional FreeType~2 API which validates TrueTypeGX/AAT tables (feat,+ * mort, morx, bsln, just, kern, opbd, trak, prop).+ *+ */+#define FT_GX_VALIDATE_H <freetype/ftgxval.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_PFR_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * FreeType~2 API which accesses PFR-specific data.+ *+ */+#define FT_PFR_H <freetype/ftpfr.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_STROKER_H+ *+ * @description:+ * 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 <freetype/ftstroke.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_SYNTHESIS_H+ *+ * @description:+ * 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 <freetype/ftsynth.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_XFREE86_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * FreeType~2 API which provides functions specific to the XFree86 and+ * X.Org X11 servers.+ */+#define FT_XFREE86_H <freetype/ftxf86.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_TRIGONOMETRY_H+ *+ * @description:+ * A macro used in #include statements to name the file containing the+ * FreeType~2 API which performs trigonometric computations (e.g.,+ * cosines and arc tangents).+ */+#define FT_TRIGONOMETRY_H <freetype/fttrigon.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_LCD_FILTER_H+ *+ * @description:+ * 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 <freetype/ftlcdfil.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_UNPATENTED_HINTING_H+ *+ * @description:+ * 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 <freetype/ttunpat.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_INCREMENTAL_H+ *+ * @description:+ * 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 <freetype/ftincrem.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_GASP_H+ *+ * @description:+ * 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 <freetype/ftgasp.h>+++ /*************************************************************************+ *+ * @macro:+ * FT_ADVANCES_H+ *+ * @description:+ * 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 <freetype/ftadvanc.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 <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 <freetype/ftincrem.h>++#define FT_TRUETYPE_UNPATENTED_H <freetype/ttunpat.h>+++ /*+ * Include internal headers definitions from <freetype/internal/...>+ * only when building the library.+ */+#ifdef FT2_BUILD_LIBRARY+#define FT_INTERNAL_INTERNAL_H <freetype/internal/internal.h>+#include FT_INTERNAL_INTERNAL_H+#endif /* FT2_BUILD_LIBRARY */+++#endif /* __FT2_BUILD_H__ */+++/* END */
+ include/freetype/config/ftmodule.h view
@@ -0,0 +1,32 @@+/*+ * This file registers the FreeType modules compiled into the library.+ *+ * If you use GNU make, this file IS NOT USED! Instead, it is created in+ * the objects directory (normally `<topdir>/objs/') based on information+ * from `<topdir>/modules.cfg'.+ *+ * Please read `docs/INSTALL.ANY' and `docs/CUSTOMIZE' how to compile+ * FreeType without GNU make.+ *+ */++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 )+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 */
+ include/freetype/config/ftoption.h view
@@ -0,0 +1,733 @@+/***************************************************************************/+/* */+/* ftoption.h */+/* */+/* User-selectable configuration macros (specification only). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */+/* 2010 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 __FTOPTION_H__+#define __FTOPTION_H__+++#include <ft2build.h>+++FT_BEGIN_HEADER++ /*************************************************************************/+ /* */+ /* USER-SELECTABLE CONFIGURATION MACROS */+ /* */+ /* This file contains the default configuration macro definitions for */+ /* a standard build of the FreeType library. There are three ways to */+ /* use this file to build project-specific versions of the library: */+ /* */+ /* - You can modify this file by hand, but this is not recommended in */+ /* cases where you would like to build several versions of the */+ /* library from a single source directory. */+ /* */+ /* - You can put a copy of this file in your build directory, more */+ /* 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 */+ /* that for your own projects. */+ /* */+ /* - Copy the file <ft2build.h> to `$BUILD/ft2build.h' and modify it */+ /* slightly to pre-define the macro FT_CONFIG_OPTIONS_H used to */+ /* locate this file during the build. For example, */+ /* */+ /* #define FT_CONFIG_OPTIONS_H <myftoptions.h> */+ /* #include <freetype/config/ftheader.h> */+ /* */+ /* will use `$BUILD/myftoptions.h' instead of this file for macro */+ /* definitions. */+ /* */+ /* 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 <freetype/config/ftmodule.h>. */+ /* */+ /* We highly recommend using the third method whenever possible. */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** G E N E R A L F R E E T Y P E 2 C O N F I G U R A T I O N ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* Uncomment the line below if you want to activate sub-pixel rendering */+ /* (a.k.a. LCD rendering, or ClearType) in this build of the library. */+ /* */+ /* Note that this feature is covered by several Microsoft patents */+ /* and should not be activated in any default build of the library. */+ /* */+ /* This macro has no impact on the FreeType API, only on its */+ /* _implementation_. For example, using FT_RENDER_MODE_LCD when calling */+ /* FT_Render_Glyph still generates a bitmap that is 3 times wider than */+ /* the original size in case this macro isn't defined; however, each */+ /* triplet of subpixels has R=G=B. */+ /* */+ /* This is done to allow FreeType clients to run unmodified, forcing */+ /* them to display normal gray-level anti-aliased glyphs. */+ /* */+/* #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING */+++ /*************************************************************************/+ /* */+ /* Many compilers provide a non-ANSI 64-bit data type that can be used */+ /* by FreeType to speed up some computations. However, this will create */+ /* some problems when compiling the library in strict ANSI mode. */+ /* */+ /* For this reason, the use of 64-bit integers is normally disabled when */+ /* the __STDC__ macro is defined. You can however disable this by */+ /* defining the macro FT_CONFIG_OPTION_FORCE_INT64 here. */+ /* */+ /* For most compilers, this will only create compilation warnings when */+ /* building the library. */+ /* */+ /* ObNote: The compiler-specific 64-bit integers are detected in the */+ /* file `ftconfig.h' either statically or through the */+ /* `configure' script on supported platforms. */+ /* */+#undef FT_CONFIG_OPTION_FORCE_INT64+++ /*************************************************************************/+ /* */+ /* If this macro is defined, do not try to use an assembler version of */+ /* performance-critical functions (e.g. FT_MulFix). You should only do */+ /* that to verify that the assembler function works properly, or to */+ /* execute benchmark tests of the various implementations. */+/* #define FT_CONFIG_OPTION_NO_ASSEMBLER */+++ /*************************************************************************/+ /* */+ /* If this macro is defined, try to use an inlined assembler version of */+ /* the `FT_MulFix' function, which is a `hotspot' when loading and */+ /* hinting glyphs, and which should be executed as fast as possible. */+ /* */+ /* Note that if your compiler or CPU is not supported, this will default */+ /* to the standard and portable implementation found in `ftcalc.c'. */+ /* */+#define FT_CONFIG_OPTION_INLINE_MULFIX+++ /*************************************************************************/+ /* */+ /* LZW-compressed file support. */+ /* */+ /* FreeType now handles font files that have been compressed with the */+ /* `compress' program. This is mostly used to parse many of the PCF */+ /* files that come with various X11 distributions. The implementation */+ /* uses NetBSD's `zopen' to partially uncompress the file on the fly */+ /* (see src/lzw/ftgzip.c). */+ /* */+ /* Define this macro if you want to enable this `feature'. */+ /* */+#define FT_CONFIG_OPTION_USE_LZW+++ /*************************************************************************/+ /* */+ /* Gzip-compressed file support. */+ /* */+ /* FreeType now handles font files that have been compressed with the */+ /* `gzip' program. This is mostly used to parse many of the PCF files */+ /* that come with XFree86. The implementation uses `zlib' to */+ /* partially uncompress the file on the fly (see src/gzip/ftgzip.c). */+ /* */+ /* Define this macro if you want to enable this `feature'. See also */+ /* the macro FT_CONFIG_OPTION_SYSTEM_ZLIB below. */+ /* */+#define FT_CONFIG_OPTION_USE_ZLIB+++ /*************************************************************************/+ /* */+ /* ZLib library selection */+ /* */+ /* This macro is only used when FT_CONFIG_OPTION_USE_ZLIB is defined. */+ /* It allows FreeType's `ftgzip' component to link to the system's */+ /* installation of the ZLib library. This is useful on systems like */+ /* Unix or VMS where it generally is already available. */+ /* */+ /* If you let it undefined, the component will use its own copy */+ /* of the zlib sources instead. These have been modified to be */+ /* included directly within the component and *not* export external */+ /* function names. This allows you to link any program with FreeType */+ /* _and_ ZLib without linking conflicts. */+ /* */+ /* Do not #undef this macro here since the build system might define */+ /* it for certain configurations only. */+ /* */+/* #define FT_CONFIG_OPTION_SYSTEM_ZLIB */+++ /*************************************************************************/+ /* */+ /* DLL export compilation */+ /* */+ /* When compiling FreeType as a DLL, some systems/compilers need a */+ /* special keyword in front OR after the return type of function */+ /* declarations. */+ /* */+ /* Two macros are used within the FreeType source code to define */+ /* exported library functions: FT_EXPORT and FT_EXPORT_DEF. */+ /* */+ /* FT_EXPORT( return_type ) */+ /* */+ /* is used in a function declaration, as in */+ /* */+ /* FT_EXPORT( FT_Error ) */+ /* FT_Init_FreeType( FT_Library* alibrary ); */+ /* */+ /* */+ /* FT_EXPORT_DEF( return_type ) */+ /* */+ /* is used in a function definition, as in */+ /* */+ /* FT_EXPORT_DEF( FT_Error ) */+ /* FT_Init_FreeType( FT_Library* alibrary ) */+ /* { */+ /* ... some code ... */+ /* return FT_Err_Ok; */+ /* } */+ /* */+ /* You can provide your own implementation of FT_EXPORT and */+ /* FT_EXPORT_DEF here if you want. If you leave them undefined, they */+ /* will be later automatically defined as `extern return_type' to */+ /* allow normal compilation. */+ /* */+ /* Do not #undef these macros here since the build system might define */+ /* them for certain configurations only. */+ /* */+/* #define FT_EXPORT(x) extern x */+/* #define FT_EXPORT_DEF(x) x */+++ /*************************************************************************/+ /* */+ /* Glyph Postscript Names handling */+ /* */+ /* By default, FreeType 2 is compiled with the `psnames' module. This */+ /* module is in charge of converting a glyph name string into a */+ /* Unicode value, or return a Macintosh standard glyph name for the */+ /* use with the TrueType `post' table. */+ /* */+ /* Undefine this macro if you do not want `psnames' compiled in your */+ /* build of FreeType. This has the following effects: */+ /* */+ /* - The TrueType driver will provide its own set of glyph names, */+ /* if you build it to support postscript names in the TrueType */+ /* `post' table. */+ /* */+ /* - The Type 1 driver will not be able to synthesize a Unicode */+ /* charmap out of the glyphs found in the fonts. */+ /* */+ /* You would normally undefine this configuration macro when building */+ /* a version of FreeType that doesn't contain a Type 1 or CFF driver. */+ /* */+#define FT_CONFIG_OPTION_POSTSCRIPT_NAMES+++ /*************************************************************************/+ /* */+ /* Postscript Names to Unicode Values support */+ /* */+ /* By default, FreeType 2 is built with the `PSNames' module compiled */+ /* in. Among other things, the module is used to convert a glyph name */+ /* into a Unicode value. This is especially useful in order to */+ /* synthesize on the fly a Unicode charmap from the CFF/Type 1 driver */+ /* through a big table named the `Adobe Glyph List' (AGL). */+ /* */+ /* Undefine this macro if you do not want the Adobe Glyph List */+ /* compiled in your `PSNames' module. The Type 1 driver will not be */+ /* able to synthesize a Unicode charmap out of the glyphs found in the */+ /* fonts. */+ /* */+#define FT_CONFIG_OPTION_ADOBE_GLYPH_LIST+++ /*************************************************************************/+ /* */+ /* Support for Mac fonts */+ /* */+ /* Define this macro if you want support for outline fonts in Mac */+ /* format (mac dfont, mac resource, macbinary containing a mac */+ /* resource) on non-Mac platforms. */+ /* */+ /* Note that the `FOND' resource isn't checked. */+ /* */+#define FT_CONFIG_OPTION_MAC_FONTS+++ /*************************************************************************/+ /* */+ /* Guessing methods to access embedded resource forks */+ /* */+ /* Enable extra Mac fonts support on non-Mac platforms (e.g. */+ /* GNU/Linux). */+ /* */+ /* Resource forks which include fonts data are stored sometimes in */+ /* locations which users or developers don't expected. In some cases, */+ /* resource forks start with some offset from the head of a file. In */+ /* other cases, the actual resource fork is stored in file different */+ /* from what the user specifies. If this option is activated, */+ /* FreeType tries to guess whether such offsets or different file */+ /* names must be used. */+ /* */+ /* Note that normal, direct access of resource forks is controlled via */+ /* the FT_CONFIG_OPTION_MAC_FONTS option. */+ /* */+#ifdef FT_CONFIG_OPTION_MAC_FONTS+#define FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK+#endif+++ /*************************************************************************/+ /* */+ /* Allow the use of FT_Incremental_Interface to load typefaces that */+ /* contain no glyph data, but supply it via a callback function. */+ /* This is required by clients supporting document formats which */+ /* supply font data incrementally as the document is parsed, such */+ /* as the Ghostscript interpreter for the PostScript language. */+ /* */+#define FT_CONFIG_OPTION_INCREMENTAL+++ /*************************************************************************/+ /* */+ /* The size in bytes of the render pool used by the scan-line converter */+ /* to do all of its work. */+ /* */+ /* This must be greater than 4KByte if you use FreeType to rasterize */+ /* glyphs; otherwise, you may set it to zero to avoid unnecessary */+ /* allocation of the render pool. */+ /* */+#define FT_RENDER_POOL_SIZE 16384L+++ /*************************************************************************/+ /* */+ /* FT_MAX_MODULES */+ /* */+ /* The maximum number of modules that can be registered in a single */+ /* FreeType library object. 32 is the default. */+ /* */+#define FT_MAX_MODULES 32+++ /*************************************************************************/+ /* */+ /* Debug level */+ /* */+ /* FreeType can be compiled in debug or trace mode. In debug mode, */+ /* errors are reported through the `ftdebug' component. In trace */+ /* mode, additional messages are sent to the standard output during */+ /* execution. */+ /* */+ /* Define FT_DEBUG_LEVEL_ERROR to build the library in debug mode. */+ /* Define FT_DEBUG_LEVEL_TRACE to build it in trace mode. */+ /* */+ /* Don't define any of these macros to compile in `release' mode! */+ /* */+ /* Do not #undef these macros here since the build system might define */+ /* them for certain configurations only. */+ /* */+/* #define FT_DEBUG_LEVEL_ERROR */+/* #define FT_DEBUG_LEVEL_TRACE */+++ /*************************************************************************/+ /* */+ /* Memory Debugging */+ /* */+ /* FreeType now comes with an integrated memory debugger that is */+ /* capable of detecting simple errors like memory leaks or double */+ /* deletes. To compile it within your build of the library, you */+ /* should define FT_DEBUG_MEMORY here. */+ /* */+ /* Note that the memory debugger is only activated at runtime when */+ /* when the _environment_ variable `FT2_DEBUG_MEMORY' is defined also! */+ /* */+ /* Do not #undef this macro here since the build system might define */+ /* it for certain configurations only. */+ /* */+/* #define FT_DEBUG_MEMORY */+++ /*************************************************************************/+ /* */+ /* Module errors */+ /* */+ /* If this macro is set (which is _not_ the default), the higher byte */+ /* of an error code gives the module in which the error has occurred, */+ /* while the lower byte is the real error code. */+ /* */+ /* Setting this macro makes sense for debugging purposes only, since */+ /* it would break source compatibility of certain programs that use */+ /* FreeType 2. */+ /* */+ /* More details can be found in the files ftmoderr.h and fterrors.h. */+ /* */+#undef FT_CONFIG_OPTION_USE_MODULE_ERRORS+++ /*************************************************************************/+ /* */+ /* Position Independent Code */+ /* */+ /* If this macro is set (which is _not_ the default), FreeType2 will */+ /* avoid creating constants that require address fixups. Instead the */+ /* constants will be moved into a struct and additional intialization */+ /* code will be used. */+ /* */+ /* Setting this macro is needed for systems that prohibit address */+ /* fixups, such as BREW. */+ /* */+/* #define FT_CONFIG_OPTION_PIC */+++ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** S F N T D R I V E R C O N F I G U R A T I O N ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* Define TT_CONFIG_OPTION_EMBEDDED_BITMAPS if you want to support */+ /* embedded bitmaps in all formats using the SFNT module (namely */+ /* TrueType & OpenType). */+ /* */+#define TT_CONFIG_OPTION_EMBEDDED_BITMAPS+++ /*************************************************************************/+ /* */+ /* Define TT_CONFIG_OPTION_POSTSCRIPT_NAMES if you want to be able to */+ /* load and enumerate the glyph Postscript names in a TrueType or */+ /* OpenType file. */+ /* */+ /* Note that when you do not compile the `PSNames' module by undefining */+ /* the above FT_CONFIG_OPTION_POSTSCRIPT_NAMES, the `sfnt' module will */+ /* contain additional code used to read the PS Names table from a font. */+ /* */+ /* (By default, the module uses `PSNames' to extract glyph names.) */+ /* */+#define TT_CONFIG_OPTION_POSTSCRIPT_NAMES+++ /*************************************************************************/+ /* */+ /* Define TT_CONFIG_OPTION_SFNT_NAMES if your applications need to */+ /* access the internal name table in a SFNT-based format like TrueType */+ /* or OpenType. The name table contains various strings used to */+ /* describe the font, like family name, copyright, version, etc. It */+ /* does not contain any glyph name though. */+ /* */+ /* Accessing SFNT names is done through the functions declared in */+ /* `freetype/ftsnames.h'. */+ /* */+#define TT_CONFIG_OPTION_SFNT_NAMES+++ /*************************************************************************/+ /* */+ /* TrueType CMap support */+ /* */+ /* Here you can fine-tune which TrueType CMap table format shall be */+ /* supported. */+#define TT_CONFIG_CMAP_FORMAT_0+#define TT_CONFIG_CMAP_FORMAT_2+#define TT_CONFIG_CMAP_FORMAT_4+#define TT_CONFIG_CMAP_FORMAT_6+#define TT_CONFIG_CMAP_FORMAT_8+#define TT_CONFIG_CMAP_FORMAT_10+#define TT_CONFIG_CMAP_FORMAT_12+#define TT_CONFIG_CMAP_FORMAT_13+#define TT_CONFIG_CMAP_FORMAT_14+++ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** T R U E T Y P E D R I V E R C O N F I G U R A T I O N ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/++ /*************************************************************************/+ /* */+ /* Define TT_CONFIG_OPTION_BYTECODE_INTERPRETER if you want to compile */+ /* a bytecode interpreter in the TrueType driver. */+ /* */+ /* By undefining this, you will only compile the code necessary to load */+ /* TrueType glyphs without hinting. */+ /* */+ /* Do not #undef this macro here, since the build system might */+ /* define it for certain configurations only. */+ /* */+#define TT_CONFIG_OPTION_BYTECODE_INTERPRETER+++ /*************************************************************************/+ /* */+ /* If you define TT_CONFIG_OPTION_UNPATENTED_HINTING, a special version */+ /* of the TrueType bytecode interpreter is used that doesn't implement */+ /* any of the patented opcodes and algorithms. The patents related to */+ /* TrueType hinting have expired worldwide since May 2010; this option */+ /* is now deprecated. */+ /* */+ /* Note that the TT_CONFIG_OPTION_UNPATENTED_HINTING macro is *ignored* */+ /* if you define TT_CONFIG_OPTION_BYTECODE_INTERPRETER; in other words, */+ /* either define TT_CONFIG_OPTION_BYTECODE_INTERPRETER or */+ /* TT_CONFIG_OPTION_UNPATENTED_HINTING but not both at the same time. */+ /* */+ /* This macro is only useful for a small number of font files (mostly */+ /* for Asian scripts) that require bytecode interpretation to properly */+ /* load glyphs. For all other fonts, this produces unpleasant results, */+ /* thus the unpatented interpreter is never used to load glyphs from */+ /* TrueType fonts unless one of the following two options is used. */+ /* */+ /* - The unpatented interpreter is explicitly activated by the user */+ /* through the FT_PARAM_TAG_UNPATENTED_HINTING parameter tag */+ /* when opening the FT_Face. */+ /* */+ /* - FreeType detects that the FT_Face corresponds to one of the */+ /* `trick' fonts (e.g., `Mingliu') it knows about. The font engine */+ /* contains a hard-coded list of font names and other matching */+ /* parameters (see function `tt_face_init' in file */+ /* `src/truetype/ttobjs.c'). */+ /* */+ /* Here a sample code snippet for using FT_PARAM_TAG_UNPATENTED_HINTING. */+ /* */+ /* { */+ /* FT_Parameter parameter; */+ /* FT_Open_Args open_args; */+ /* */+ /* */+ /* parameter.tag = FT_PARAM_TAG_UNPATENTED_HINTING; */+ /* */+ /* open_args.flags = FT_OPEN_PATHNAME | FT_OPEN_PARAMS; */+ /* open_args.pathname = my_font_pathname; */+ /* open_args.num_params = 1; */+ /* open_args.params = ¶meter; */+ /* */+ /* error = FT_Open_Face( library, &open_args, index, &face ); */+ /* ... */+ /* } */+ /* */+/* #define TT_CONFIG_OPTION_UNPATENTED_HINTING */+++ /*************************************************************************/+ /* */+ /* Define TT_CONFIG_OPTION_INTERPRETER_SWITCH to compile the TrueType */+ /* bytecode interpreter with a huge switch statement, rather than a call */+ /* table. This results in smaller and faster code for a number of */+ /* architectures. */+ /* */+ /* Note however that on some compiler/processor combinations, undefining */+ /* this macro will generate faster, though larger, code. */+ /* */+#define TT_CONFIG_OPTION_INTERPRETER_SWITCH+++ /*************************************************************************/+ /* */+ /* Define TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED to compile the */+ /* TrueType glyph loader to use Apple's definition of how to handle */+ /* component offsets in composite glyphs. */+ /* */+ /* Apple and MS disagree on the default behavior of component offsets */+ /* in composites. Apple says that they should be scaled by the scaling */+ /* factors in the transformation matrix (roughly, it's more complex) */+ /* while MS says they should not. OpenType defines two bits in the */+ /* composite flags array which can be used to disambiguate, but old */+ /* fonts will not have them. */+ /* */+ /* http://partners.adobe.com/asn/developer/opentype/glyf.html */+ /* http://fonts.apple.com/TTRefMan/RM06/Chap6glyf.html */+ /* */+#undef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED+++ /*************************************************************************/+ /* */+ /* Define TT_CONFIG_OPTION_GX_VAR_SUPPORT if you want to include */+ /* support for Apple's distortable font technology (fvar, gvar, cvar, */+ /* and avar tables). This has many similarities to Type 1 Multiple */+ /* Masters support. */+ /* */+#define TT_CONFIG_OPTION_GX_VAR_SUPPORT+++ /*************************************************************************/+ /* */+ /* Define TT_CONFIG_OPTION_BDF if you want to include support for */+ /* an embedded `BDF ' table within SFNT-based bitmap formats. */+ /* */+#define TT_CONFIG_OPTION_BDF+++ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** T Y P E 1 D R I V E R C O N F I G U R A T I O N ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* T1_MAX_DICT_DEPTH is the maximal depth of nest dictionaries and */+ /* arrays in the Type 1 stream (see t1load.c). A minimum of 4 is */+ /* required. */+ /* */+#define T1_MAX_DICT_DEPTH 5+++ /*************************************************************************/+ /* */+ /* T1_MAX_SUBRS_CALLS details the maximum number of nested sub-routine */+ /* calls during glyph loading. */+ /* */+#define T1_MAX_SUBRS_CALLS 16+++ /*************************************************************************/+ /* */+ /* T1_MAX_CHARSTRING_OPERANDS is the charstring stack's capacity. A */+ /* minimum of 16 is required. */+ /* */+ /* The Chinese font MingTiEG-Medium (CNS 11643 character set) needs 256. */+ /* */+#define T1_MAX_CHARSTRINGS_OPERANDS 256+++ /*************************************************************************/+ /* */+ /* Define this configuration macro if you want to prevent the */+ /* compilation of `t1afm', which is in charge of reading Type 1 AFM */+ /* files into an existing face. Note that if set, the T1 driver will be */+ /* unable to produce kerning distances. */+ /* */+#undef T1_CONFIG_OPTION_NO_AFM+++ /*************************************************************************/+ /* */+ /* Define this configuration macro if you want to prevent the */+ /* compilation of the Multiple Masters font support in the Type 1 */+ /* driver. */+ /* */+#undef T1_CONFIG_OPTION_NO_MM_SUPPORT+++ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** A U T O F I T M O D U L E C O N F I G U R A T I O N ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* Compile autofit module with CJK (Chinese, Japanese, Korean) script */+ /* support. */+ /* */+#define AF_CONFIG_OPTION_CJK++ /*************************************************************************/+ /* */+ /* Compile autofit module with Indic script support. */+ /* */+#define AF_CONFIG_OPTION_INDIC++ /* */+++ /*+ * Define this variable if you want to keep the layout of internal+ * structures that was used prior to FreeType 2.2. This also compiles in+ * a few obsolete functions to avoid linking problems on typical Unix+ * distributions.+ *+ * For embedded systems or building a new distribution from scratch, it+ * is recommended to disable the macro since it reduces the library's code+ * size and activates a few memory-saving optimizations as well.+ */+#define FT_CONFIG_OPTION_OLD_INTERNALS+++ /*+ * To detect legacy cache-lookup call from a rogue client (<= 2.1.7),+ * we restrict the number of charmaps in a font. The current API of+ * FTC_CMapCache_Lookup() takes cmap_index & charcode, but old API+ * takes charcode only. To determine the passed value is for cmap_index+ * or charcode, the possible cmap_index is restricted not to exceed+ * the minimum possible charcode by a rogue client. It is also very+ * unlikely that a rogue client is interested in Unicode values 0 to 15.+ *+ * NOTE: The original threshold was 4 deduced from popular number of+ * cmap subtables in UCS-4 TrueType fonts, but now it is not+ * irregular for OpenType fonts to have more than 4 subtables,+ * because variation selector subtables are available for Apple+ * and Microsoft platforms.+ */++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS+#define FT_MAX_CHARMAP_CACHEABLE 15+#endif+++ /*+ * This macro is defined if either unpatented or native TrueType+ * hinting is requested by the definitions above.+ */+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER+#define TT_USE_BYTECODE_INTERPRETER+#undef TT_CONFIG_OPTION_UNPATENTED_HINTING+#elif defined TT_CONFIG_OPTION_UNPATENTED_HINTING+#define TT_USE_BYTECODE_INTERPRETER+#endif++FT_END_HEADER+++#endif /* __FTOPTION_H__ */+++/* END */
+ include/freetype/config/ftstdlib.h view
@@ -0,0 +1,173 @@+/***************************************************************************/+/* */+/* ftstdlib.h */+/* */+/* ANSI-specific library and header configuration file (specification */+/* only). */+/* */+/* Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2009 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 group all #includes to the ANSI C library that */+ /* FreeType normally requires. It also defines macros to rename the */+ /* standard functions within the FreeType source code. */+ /* */+ /* Load a file which defines __FTSTDLIB_H__ before this one to override */+ /* it. */+ /* */+ /*************************************************************************/+++#ifndef __FTSTDLIB_H__+#define __FTSTDLIB_H__+++#include <stddef.h>++#define ft_ptrdiff_t ptrdiff_t+++ /**********************************************************************/+ /* */+ /* integer limits */+ /* */+ /* UINT_MAX and ULONG_MAX are used to automatically compute the size */+ /* of `int' and `long' in bytes at compile-time. So far, this works */+ /* for all platforms the library has been tested on. */+ /* */+ /* Note that on the extremely rare platforms that do not provide */+ /* integer types that are _exactly_ 16 and 32 bits wide (e.g. some */+ /* old Crays where `int' is 36 bits), we do not make any guarantee */+ /* about the correct behaviour of FT2 with all fonts. */+ /* */+ /* In these case, `ftconfig.h' will refuse to compile anyway with a */+ /* message like `couldn't find 32-bit type' or something similar. */+ /* */+ /**********************************************************************/+++#include <limits.h>++#define FT_CHAR_BIT CHAR_BIT+#define FT_INT_MAX INT_MAX+#define FT_INT_MIN INT_MIN+#define FT_UINT_MAX UINT_MAX+#define FT_ULONG_MAX ULONG_MAX+++ /**********************************************************************/+ /* */+ /* character and string processing */+ /* */+ /**********************************************************************/+++#include <string.h>++#define ft_memchr memchr+#define ft_memcmp memcmp+#define ft_memcpy memcpy+#define ft_memmove memmove+#define ft_memset memset+#define ft_strcat strcat+#define ft_strcmp strcmp+#define ft_strcpy strcpy+#define ft_strlen strlen+#define ft_strncmp strncmp+#define ft_strncpy strncpy+#define ft_strrchr strrchr+#define ft_strstr strstr+++ /**********************************************************************/+ /* */+ /* file handling */+ /* */+ /**********************************************************************/+++#include <stdio.h>++#define FT_FILE FILE+#define ft_fclose fclose+#define ft_fopen fopen+#define ft_fread fread+#define ft_fseek fseek+#define ft_ftell ftell+#define ft_sprintf sprintf+++ /**********************************************************************/+ /* */+ /* sorting */+ /* */+ /**********************************************************************/+++#include <stdlib.h>++#define ft_qsort qsort+++ /**********************************************************************/+ /* */+ /* memory allocation */+ /* */+ /**********************************************************************/+++#define ft_scalloc calloc+#define ft_sfree free+#define ft_smalloc malloc+#define ft_srealloc realloc+++ /**********************************************************************/+ /* */+ /* miscellaneous */+ /* */+ /**********************************************************************/+++#define ft_atol atol+#define ft_labs labs+++ /**********************************************************************/+ /* */+ /* execution control */+ /* */+ /**********************************************************************/+++#include <setjmp.h>++#define ft_jmp_buf jmp_buf /* note: this cannot be a typedef since */+ /* jmp_buf is defined as a macro */+ /* on certain platforms */++#define ft_longjmp longjmp+#define ft_setjmp( b ) setjmp( *(jmp_buf*) &(b) ) /* same thing here */+++ /* the following is only used for debugging purposes, i.e., if */+ /* FT_DEBUG_LEVEL_ERROR or FT_DEBUG_LEVEL_TRACE are defined */++#include <stdarg.h>+++#endif /* __FTSTDLIB_H__ */+++/* END */
+ include/freetype/freetype.h view
@@ -0,0 +1,3919 @@+/***************************************************************************/+/* */+/* freetype.h */+/* */+/* FreeType high-level API and common types (specification only). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */+/* 2010 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 FT_FREETYPE_H+#error "`ft2build.h' hasn't been included yet!"+#error "Please always use macros to include FreeType header files."+#error "Example:"+#error " #include <ft2build.h>"+#error " #include FT_FREETYPE_H"+#endif+++#ifndef __FREETYPE_H__+#define __FREETYPE_H__+++#include <ft2build.h>+#include FT_CONFIG_CONFIG_H+#include FT_ERRORS_H+#include FT_TYPES_H+++FT_BEGIN_HEADER++++ /*************************************************************************/+ /* */+ /* <Section> */+ /* user_allocation */+ /* */+ /* <Title> */+ /* User allocation */+ /* */+ /* <Abstract> */+ /* How client applications should allocate FreeType data structures. */+ /* */+ /* <Description> */+ /* FreeType assumes that structures allocated by the user and passed */+ /* as arguments are zeroed out except for the actual data. In other */+ /* words, it is recommended to use `calloc' (or variants of it) */+ /* instead of `malloc' for allocation. */+ /* */+ /*************************************************************************/++++ /*************************************************************************/+ /*************************************************************************/+ /* */+ /* B A S I C T Y P E S */+ /* */+ /*************************************************************************/+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* base_interface */+ /* */+ /* <Title> */+ /* Base Interface */+ /* */+ /* <Abstract> */+ /* The FreeType~2 base font interface. */+ /* */+ /* <Description> */+ /* This section describes the public high-level API of FreeType~2. */+ /* */+ /* <Order> */+ /* FT_Library */+ /* FT_Face */+ /* FT_Size */+ /* FT_GlyphSlot */+ /* FT_CharMap */+ /* FT_Encoding */+ /* */+ /* FT_FaceRec */+ /* */+ /* FT_FACE_FLAG_SCALABLE */+ /* FT_FACE_FLAG_FIXED_SIZES */+ /* FT_FACE_FLAG_FIXED_WIDTH */+ /* FT_FACE_FLAG_HORIZONTAL */+ /* FT_FACE_FLAG_VERTICAL */+ /* FT_FACE_FLAG_SFNT */+ /* FT_FACE_FLAG_KERNING */+ /* FT_FACE_FLAG_MULTIPLE_MASTERS */+ /* FT_FACE_FLAG_GLYPH_NAMES */+ /* FT_FACE_FLAG_EXTERNAL_STREAM */+ /* FT_FACE_FLAG_FAST_GLYPHS */+ /* FT_FACE_FLAG_HINTER */+ /* */+ /* FT_STYLE_FLAG_BOLD */+ /* FT_STYLE_FLAG_ITALIC */+ /* */+ /* FT_SizeRec */+ /* FT_Size_Metrics */+ /* */+ /* FT_GlyphSlotRec */+ /* FT_Glyph_Metrics */+ /* FT_SubGlyph */+ /* */+ /* FT_Bitmap_Size */+ /* */+ /* FT_Init_FreeType */+ /* FT_Done_FreeType */+ /* */+ /* FT_New_Face */+ /* FT_Done_Face */+ /* FT_New_Memory_Face */+ /* FT_Open_Face */+ /* FT_Open_Args */+ /* FT_Parameter */+ /* FT_Attach_File */+ /* FT_Attach_Stream */+ /* */+ /* FT_Set_Char_Size */+ /* FT_Set_Pixel_Sizes */+ /* FT_Request_Size */+ /* FT_Select_Size */+ /* FT_Size_Request_Type */+ /* FT_Size_Request */+ /* FT_Set_Transform */+ /* FT_Load_Glyph */+ /* FT_Get_Char_Index */+ /* FT_Get_Name_Index */+ /* FT_Load_Char */+ /* */+ /* FT_OPEN_MEMORY */+ /* FT_OPEN_STREAM */+ /* FT_OPEN_PATHNAME */+ /* FT_OPEN_DRIVER */+ /* FT_OPEN_PARAMS */+ /* */+ /* FT_LOAD_DEFAULT */+ /* FT_LOAD_RENDER */+ /* FT_LOAD_MONOCHROME */+ /* FT_LOAD_LINEAR_DESIGN */+ /* FT_LOAD_NO_SCALE */+ /* FT_LOAD_NO_HINTING */+ /* FT_LOAD_NO_BITMAP */+ /* FT_LOAD_CROP_BITMAP */+ /* */+ /* FT_LOAD_VERTICAL_LAYOUT */+ /* FT_LOAD_IGNORE_TRANSFORM */+ /* FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH */+ /* FT_LOAD_FORCE_AUTOHINT */+ /* FT_LOAD_NO_RECURSE */+ /* FT_LOAD_PEDANTIC */+ /* */+ /* FT_LOAD_TARGET_NORMAL */+ /* FT_LOAD_TARGET_LIGHT */+ /* FT_LOAD_TARGET_MONO */+ /* FT_LOAD_TARGET_LCD */+ /* FT_LOAD_TARGET_LCD_V */+ /* */+ /* FT_Render_Glyph */+ /* FT_Render_Mode */+ /* FT_Get_Kerning */+ /* FT_Kerning_Mode */+ /* FT_Get_Track_Kerning */+ /* FT_Get_Glyph_Name */+ /* FT_Get_Postscript_Name */+ /* */+ /* FT_CharMapRec */+ /* FT_Select_Charmap */+ /* FT_Set_Charmap */+ /* FT_Get_Charmap_Index */+ /* */+ /* FT_FSTYPE_INSTALLABLE_EMBEDDING */+ /* FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING */+ /* FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING */+ /* FT_FSTYPE_EDITABLE_EMBEDDING */+ /* FT_FSTYPE_NO_SUBSETTING */+ /* FT_FSTYPE_BITMAP_EMBEDDING_ONLY */+ /* */+ /* FT_Get_FSType_Flags */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_Glyph_Metrics */+ /* */+ /* <Description> */+ /* A structure used to model the metrics of a single glyph. The */+ /* values are expressed in 26.6 fractional pixel format; if the flag */+ /* @FT_LOAD_NO_SCALE has been used while loading the glyph, values */+ /* are expressed in font units instead. */+ /* */+ /* <Fields> */+ /* width :: */+ /* The glyph's width. */+ /* */+ /* height :: */+ /* The glyph's height. */+ /* */+ /* horiBearingX :: */+ /* Left side bearing for horizontal layout. */+ /* */+ /* horiBearingY :: */+ /* Top side bearing for horizontal layout. */+ /* */+ /* horiAdvance :: */+ /* Advance width for horizontal layout. */+ /* */+ /* vertBearingX :: */+ /* Left side bearing for vertical layout. */+ /* */+ /* vertBearingY :: */+ /* Top side bearing for vertical layout. */+ /* */+ /* vertAdvance :: */+ /* Advance height for vertical layout. */+ /* */+ /* <Note> */+ /* If not disabled with @FT_LOAD_NO_HINTING, the values represent */+ /* dimensions of the hinted glyph (in case hinting is applicable). */+ /* */+ typedef struct FT_Glyph_Metrics_+ {+ FT_Pos width;+ FT_Pos height;++ FT_Pos horiBearingX;+ FT_Pos horiBearingY;+ FT_Pos horiAdvance;++ FT_Pos vertBearingX;+ FT_Pos vertBearingY;+ FT_Pos vertAdvance;++ } FT_Glyph_Metrics;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_Bitmap_Size */+ /* */+ /* <Description> */+ /* This structure models the metrics of a bitmap strike (i.e., a set */+ /* of glyphs for a given point size and resolution) in a bitmap font. */+ /* It is used for the `available_sizes' field of @FT_Face. */+ /* */+ /* <Fields> */+ /* height :: The vertical distance, in pixels, between two */+ /* consecutive baselines. It is always positive. */+ /* */+ /* width :: The average width, in pixels, of all glyphs in the */+ /* strike. */+ /* */+ /* size :: The nominal size of the strike in 26.6 fractional */+ /* points. This field is not very useful. */+ /* */+ /* x_ppem :: The horizontal ppem (nominal width) in 26.6 fractional */+ /* pixels. */+ /* */+ /* y_ppem :: The vertical ppem (nominal height) in 26.6 fractional */+ /* pixels. */+ /* */+ /* <Note> */+ /* Windows FNT: */+ /* The nominal size given in a FNT font is not reliable. Thus when */+ /* the driver finds it incorrect, it sets `size' to some calculated */+ /* values and sets `x_ppem' and `y_ppem' to the pixel width and */+ /* height given in the font, respectively. */+ /* */+ /* TrueType embedded bitmaps: */+ /* `size', `width', and `height' values are not contained in the */+ /* bitmap strike itself. They are computed from the global font */+ /* parameters. */+ /* */+ typedef struct FT_Bitmap_Size_+ {+ FT_Short height;+ FT_Short width;++ FT_Pos size;++ FT_Pos x_ppem;+ FT_Pos y_ppem;++ } FT_Bitmap_Size;+++ /*************************************************************************/+ /*************************************************************************/+ /* */+ /* O B J E C T C L A S S E S */+ /* */+ /*************************************************************************/+ /*************************************************************************/++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_Library */+ /* */+ /* <Description> */+ /* A handle to a FreeType library instance. Each `library' is */+ /* completely independent from the others; it is the `root' of a set */+ /* of objects like fonts, faces, sizes, etc. */+ /* */+ /* It also embeds a memory manager (see @FT_Memory), as well as a */+ /* scan-line converter object (see @FT_Raster). */+ /* */+ /* For multi-threading applications each thread should have its own */+ /* FT_Library object. */+ /* */+ /* <Note> */+ /* Library objects are normally created by @FT_Init_FreeType, and */+ /* destroyed with @FT_Done_FreeType. */+ /* */+ typedef struct FT_LibraryRec_ *FT_Library;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_Module */+ /* */+ /* <Description> */+ /* A handle to a given FreeType module object. Each module can be a */+ /* font driver, a renderer, or anything else that provides services */+ /* to the formers. */+ /* */+ typedef struct FT_ModuleRec_* FT_Module;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_Driver */+ /* */+ /* <Description> */+ /* A handle to a given FreeType font driver object. Each font driver */+ /* is a special module capable of creating faces from font files. */+ /* */+ typedef struct FT_DriverRec_* FT_Driver;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_Renderer */+ /* */+ /* <Description> */+ /* A handle to a given FreeType renderer. A renderer is a special */+ /* module in charge of converting a glyph image to a bitmap, when */+ /* necessary. Each renderer supports a given glyph image format, and */+ /* one or more target surface depths. */+ /* */+ typedef struct FT_RendererRec_* FT_Renderer;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_Face */+ /* */+ /* <Description> */+ /* A handle to a given typographic face object. A face object models */+ /* a given typeface, in a given style. */+ /* */+ /* <Note> */+ /* Each face object also owns a single @FT_GlyphSlot object, as well */+ /* as one or more @FT_Size objects. */+ /* */+ /* Use @FT_New_Face or @FT_Open_Face to create a new face object from */+ /* a given filepathname or a custom input stream. */+ /* */+ /* Use @FT_Done_Face to destroy it (along with its slot and sizes). */+ /* */+ /* <Also> */+ /* See @FT_FaceRec for the publicly accessible fields of a given face */+ /* object. */+ /* */+ typedef struct FT_FaceRec_* FT_Face;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_Size */+ /* */+ /* <Description> */+ /* A handle to an object used to model a face scaled to a given */+ /* character size. */+ /* */+ /* <Note> */+ /* Each @FT_Face has an _active_ @FT_Size object that is used by */+ /* functions like @FT_Load_Glyph to determine the scaling */+ /* transformation which is used to load and hint glyphs and metrics. */+ /* */+ /* You can use @FT_Set_Char_Size, @FT_Set_Pixel_Sizes, */+ /* @FT_Request_Size or even @FT_Select_Size to change the content */+ /* (i.e., the scaling values) of the active @FT_Size. */+ /* */+ /* You can use @FT_New_Size to create additional size objects for a */+ /* given @FT_Face, but they won't be used by other functions until */+ /* you activate it through @FT_Activate_Size. Only one size can be */+ /* activated at any given time per face. */+ /* */+ /* <Also> */+ /* See @FT_SizeRec for the publicly accessible fields of a given size */+ /* object. */+ /* */+ typedef struct FT_SizeRec_* FT_Size;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_GlyphSlot */+ /* */+ /* <Description> */+ /* A handle to a given `glyph slot'. A slot is a container where it */+ /* is possible to load any of the glyphs contained in its parent */+ /* face. */+ /* */+ /* In other words, each time you call @FT_Load_Glyph or */+ /* @FT_Load_Char, the slot's content is erased by the new glyph data, */+ /* i.e., the glyph's metrics, its image (bitmap or outline), and */+ /* other control information. */+ /* */+ /* <Also> */+ /* See @FT_GlyphSlotRec for the publicly accessible glyph fields. */+ /* */+ typedef struct FT_GlyphSlotRec_* FT_GlyphSlot;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_CharMap */+ /* */+ /* <Description> */+ /* A handle to a given character map. A charmap is used to translate */+ /* character codes in a given encoding into glyph indexes for its */+ /* parent's face. Some font formats may provide several charmaps per */+ /* font. */+ /* */+ /* Each face object owns zero or more charmaps, but only one of them */+ /* can be `active' and used by @FT_Get_Char_Index or @FT_Load_Char. */+ /* */+ /* The list of available charmaps in a face is available through the */+ /* `face->num_charmaps' and `face->charmaps' fields of @FT_FaceRec. */+ /* */+ /* The currently active charmap is available as `face->charmap'. */+ /* You should call @FT_Set_Charmap to change it. */+ /* */+ /* <Note> */+ /* When a new face is created (either through @FT_New_Face or */+ /* @FT_Open_Face), the library looks for a Unicode charmap within */+ /* the list and automatically activates it. */+ /* */+ /* <Also> */+ /* See @FT_CharMapRec for the publicly accessible fields of a given */+ /* character map. */+ /* */+ typedef struct FT_CharMapRec_* FT_CharMap;+++ /*************************************************************************/+ /* */+ /* <Macro> */+ /* FT_ENC_TAG */+ /* */+ /* <Description> */+ /* This macro converts four-letter tags into an unsigned long. It is */+ /* used to define `encoding' identifiers (see @FT_Encoding). */+ /* */+ /* <Note> */+ /* Since many 16-bit compilers don't like 32-bit enumerations, you */+ /* should redefine this macro in case of problems to something like */+ /* this: */+ /* */+ /* { */+ /* #define FT_ENC_TAG( value, a, b, c, d ) value */+ /* } */+ /* */+ /* to get a simple enumeration without assigning special numbers. */+ /* */++#ifndef FT_ENC_TAG+#define FT_ENC_TAG( value, a, b, c, d ) \+ value = ( ( (FT_UInt32)(a) << 24 ) | \+ ( (FT_UInt32)(b) << 16 ) | \+ ( (FT_UInt32)(c) << 8 ) | \+ (FT_UInt32)(d) )++#endif /* FT_ENC_TAG */+++ /*************************************************************************/+ /* */+ /* <Enum> */+ /* FT_Encoding */+ /* */+ /* <Description> */+ /* An enumeration used to specify character sets supported by */+ /* charmaps. Used in the @FT_Select_Charmap API function. */+ /* */+ /* <Note> */+ /* Despite the name, this enumeration lists specific character */+ /* repertories (i.e., charsets), and not text encoding methods (e.g., */+ /* UTF-8, UTF-16, etc.). */+ /* */+ /* Other encodings might be defined in the future. */+ /* */+ /* <Values> */+ /* FT_ENCODING_NONE :: */+ /* The encoding value~0 is reserved. */+ /* */+ /* FT_ENCODING_UNICODE :: */+ /* Corresponds to the Unicode character set. This value covers */+ /* all versions of the Unicode repertoire, including ASCII and */+ /* Latin-1. Most fonts include a Unicode charmap, but not all */+ /* of them. */+ /* */+ /* For example, if you want to access Unicode value U+1F028 (and */+ /* the font contains it), use value 0x1F028 as the input value for */+ /* @FT_Get_Char_Index. */+ /* */+ /* FT_ENCODING_MS_SYMBOL :: */+ /* Corresponds to the Microsoft Symbol encoding, used to encode */+ /* mathematical symbols in the 32..255 character code range. For */+ /* more information, see `http://www.ceviz.net/symbol.htm'. */+ /* */+ /* FT_ENCODING_SJIS :: */+ /* Corresponds to Japanese SJIS encoding. More info at */+ /* at `http://langsupport.japanreference.com/encoding.shtml'. */+ /* See note on multi-byte encodings below. */+ /* */+ /* FT_ENCODING_GB2312 :: */+ /* Corresponds to an encoding system for Simplified Chinese as used */+ /* used in mainland China. */+ /* */+ /* FT_ENCODING_BIG5 :: */+ /* Corresponds to an encoding system for Traditional Chinese as */+ /* used in Taiwan and Hong Kong. */+ /* */+ /* FT_ENCODING_WANSUNG :: */+ /* Corresponds to the Korean encoding system known as Wansung. */+ /* For more information see */+ /* `http://www.microsoft.com/typography/unicode/949.txt'. */+ /* */+ /* FT_ENCODING_JOHAB :: */+ /* The Korean standard character set (KS~C 5601-1992), which */+ /* corresponds to MS Windows code page 1361. This character set */+ /* includes all possible Hangeul character combinations. */+ /* */+ /* FT_ENCODING_ADOBE_LATIN_1 :: */+ /* Corresponds to a Latin-1 encoding as defined in a Type~1 */+ /* PostScript font. It is limited to 256 character codes. */+ /* */+ /* FT_ENCODING_ADOBE_STANDARD :: */+ /* Corresponds to the Adobe Standard encoding, as found in Type~1, */+ /* CFF, and OpenType/CFF fonts. It is limited to 256 character */+ /* codes. */+ /* */+ /* FT_ENCODING_ADOBE_EXPERT :: */+ /* Corresponds to the Adobe Expert encoding, as found in Type~1, */+ /* CFF, and OpenType/CFF fonts. It is limited to 256 character */+ /* codes. */+ /* */+ /* FT_ENCODING_ADOBE_CUSTOM :: */+ /* Corresponds to a custom encoding, as found in Type~1, CFF, and */+ /* OpenType/CFF fonts. It is limited to 256 character codes. */+ /* */+ /* FT_ENCODING_APPLE_ROMAN :: */+ /* Corresponds to the 8-bit Apple roman encoding. Many TrueType */+ /* and OpenType fonts contain a charmap for this encoding, since */+ /* older versions of Mac OS are able to use it. */+ /* */+ /* FT_ENCODING_OLD_LATIN_2 :: */+ /* This value is deprecated and was never used nor reported by */+ /* FreeType. Don't use or test for it. */+ /* */+ /* FT_ENCODING_MS_SJIS :: */+ /* Same as FT_ENCODING_SJIS. Deprecated. */+ /* */+ /* FT_ENCODING_MS_GB2312 :: */+ /* Same as FT_ENCODING_GB2312. Deprecated. */+ /* */+ /* FT_ENCODING_MS_BIG5 :: */+ /* Same as FT_ENCODING_BIG5. Deprecated. */+ /* */+ /* FT_ENCODING_MS_WANSUNG :: */+ /* Same as FT_ENCODING_WANSUNG. Deprecated. */+ /* */+ /* FT_ENCODING_MS_JOHAB :: */+ /* Same as FT_ENCODING_JOHAB. Deprecated. */+ /* */+ /* <Note> */+ /* By default, FreeType automatically synthesizes a Unicode charmap */+ /* for PostScript fonts, using their glyph names dictionaries. */+ /* However, it also reports the encodings defined explicitly in the */+ /* font file, for the cases when they are needed, with the Adobe */+ /* values as well. */+ /* */+ /* FT_ENCODING_NONE is set by the BDF and PCF drivers if the charmap */+ /* is neither Unicode nor ISO-8859-1 (otherwise it is set to */+ /* FT_ENCODING_UNICODE). Use @FT_Get_BDF_Charset_ID to find out */+ /* which encoding is really present. If, for example, the */+ /* `cs_registry' field is `KOI8' and the `cs_encoding' field is `R', */+ /* the font is encoded in KOI8-R. */+ /* */+ /* FT_ENCODING_NONE is always set (with a single exception) by the */+ /* winfonts driver. Use @FT_Get_WinFNT_Header and examine the */+ /* `charset' field of the @FT_WinFNT_HeaderRec structure to find out */+ /* which encoding is really present. For example, */+ /* @FT_WinFNT_ID_CP1251 (204) means Windows code page 1251 (for */+ /* Russian). */+ /* */+ /* FT_ENCODING_NONE is set if `platform_id' is @TT_PLATFORM_MACINTOSH */+ /* and `encoding_id' is not @TT_MAC_ID_ROMAN (otherwise it is set to */+ /* FT_ENCODING_APPLE_ROMAN). */+ /* */+ /* If `platform_id' is @TT_PLATFORM_MACINTOSH, use the function */+ /* @FT_Get_CMap_Language_ID to query the Mac language ID which may */+ /* be needed to be able to distinguish Apple encoding variants. See */+ /* */+ /* http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/README.TXT */+ /* */+ /* to get an idea how to do that. Basically, if the language ID */+ /* is~0, don't use it, otherwise subtract 1 from the language ID. */+ /* Then examine `encoding_id'. If, for example, `encoding_id' is */+ /* @TT_MAC_ID_ROMAN and the language ID (minus~1) is */+ /* `TT_MAC_LANGID_GREEK', it is the Greek encoding, not Roman. */+ /* @TT_MAC_ID_ARABIC with `TT_MAC_LANGID_FARSI' means the Farsi */+ /* variant the Arabic encoding. */+ /* */+ typedef enum FT_Encoding_+ {+ FT_ENC_TAG( FT_ENCODING_NONE, 0, 0, 0, 0 ),++ FT_ENC_TAG( FT_ENCODING_MS_SYMBOL, 's', 'y', 'm', 'b' ),+ FT_ENC_TAG( FT_ENCODING_UNICODE, 'u', 'n', 'i', 'c' ),++ FT_ENC_TAG( FT_ENCODING_SJIS, 's', 'j', 'i', 's' ),+ FT_ENC_TAG( FT_ENCODING_GB2312, 'g', 'b', ' ', ' ' ),+ FT_ENC_TAG( FT_ENCODING_BIG5, 'b', 'i', 'g', '5' ),+ FT_ENC_TAG( FT_ENCODING_WANSUNG, 'w', 'a', 'n', 's' ),+ FT_ENC_TAG( FT_ENCODING_JOHAB, 'j', 'o', 'h', 'a' ),++ /* for backwards compatibility */+ FT_ENCODING_MS_SJIS = FT_ENCODING_SJIS,+ FT_ENCODING_MS_GB2312 = FT_ENCODING_GB2312,+ FT_ENCODING_MS_BIG5 = FT_ENCODING_BIG5,+ FT_ENCODING_MS_WANSUNG = FT_ENCODING_WANSUNG,+ FT_ENCODING_MS_JOHAB = FT_ENCODING_JOHAB,++ FT_ENC_TAG( FT_ENCODING_ADOBE_STANDARD, 'A', 'D', 'O', 'B' ),+ FT_ENC_TAG( FT_ENCODING_ADOBE_EXPERT, 'A', 'D', 'B', 'E' ),+ FT_ENC_TAG( FT_ENCODING_ADOBE_CUSTOM, 'A', 'D', 'B', 'C' ),+ FT_ENC_TAG( FT_ENCODING_ADOBE_LATIN_1, 'l', 'a', 't', '1' ),++ FT_ENC_TAG( FT_ENCODING_OLD_LATIN_2, 'l', 'a', 't', '2' ),++ FT_ENC_TAG( FT_ENCODING_APPLE_ROMAN, 'a', 'r', 'm', 'n' )++ } FT_Encoding;+++ /*************************************************************************/+ /* */+ /* <Enum> */+ /* ft_encoding_xxx */+ /* */+ /* <Description> */+ /* These constants are deprecated; use the corresponding @FT_Encoding */+ /* values instead. */+ /* */+#define ft_encoding_none FT_ENCODING_NONE+#define ft_encoding_unicode FT_ENCODING_UNICODE+#define ft_encoding_symbol FT_ENCODING_MS_SYMBOL+#define ft_encoding_latin_1 FT_ENCODING_ADOBE_LATIN_1+#define ft_encoding_latin_2 FT_ENCODING_OLD_LATIN_2+#define ft_encoding_sjis FT_ENCODING_SJIS+#define ft_encoding_gb2312 FT_ENCODING_GB2312+#define ft_encoding_big5 FT_ENCODING_BIG5+#define ft_encoding_wansung FT_ENCODING_WANSUNG+#define ft_encoding_johab FT_ENCODING_JOHAB++#define ft_encoding_adobe_standard FT_ENCODING_ADOBE_STANDARD+#define ft_encoding_adobe_expert FT_ENCODING_ADOBE_EXPERT+#define ft_encoding_adobe_custom FT_ENCODING_ADOBE_CUSTOM+#define ft_encoding_apple_roman FT_ENCODING_APPLE_ROMAN+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_CharMapRec */+ /* */+ /* <Description> */+ /* The base charmap structure. */+ /* */+ /* <Fields> */+ /* face :: A handle to the parent face object. */+ /* */+ /* encoding :: An @FT_Encoding tag identifying the charmap. Use */+ /* this with @FT_Select_Charmap. */+ /* */+ /* platform_id :: An ID number describing the platform for the */+ /* following encoding ID. This comes directly from */+ /* the TrueType specification and should be emulated */+ /* for other formats. */+ /* */+ /* encoding_id :: A platform specific encoding number. This also */+ /* comes from the TrueType specification and should be */+ /* emulated similarly. */+ /* */+ typedef struct FT_CharMapRec_+ {+ FT_Face face;+ FT_Encoding encoding;+ FT_UShort platform_id;+ FT_UShort encoding_id;++ } FT_CharMapRec;+++ /*************************************************************************/+ /*************************************************************************/+ /* */+ /* B A S E O B J E C T C L A S S E S */+ /* */+ /*************************************************************************/+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_Face_Internal */+ /* */+ /* <Description> */+ /* An opaque handle to an `FT_Face_InternalRec' structure, used to */+ /* model private data of a given @FT_Face object. */+ /* */+ /* This structure might change between releases of FreeType~2 and is */+ /* not generally available to client applications. */+ /* */+ typedef struct FT_Face_InternalRec_* FT_Face_Internal;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_FaceRec */+ /* */+ /* <Description> */+ /* FreeType root face class structure. A face object models a */+ /* typeface in a font file. */+ /* */+ /* <Fields> */+ /* num_faces :: The number of faces in the font file. Some */+ /* 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 */+ /* the font file. */+ /* */+ /* 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. */+ /* */+ /* num_glyphs :: The number of glyphs in the face. If the */+ /* face is scalable and has sbits (see */+ /* `num_fixed_sizes'), it is set to the number */+ /* of outline glyphs. */+ /* */+ /* For CID-keyed fonts, this value gives the */+ /* highest CID used in the font. */+ /* */+ /* family_name :: The face's family name. This is an ASCII */+ /* string, usually in English, which describes */+ /* the typeface's family (like `Times New */+ /* Roman', `Bodoni', `Garamond', etc). This */+ /* is a least common denominator used to list */+ /* fonts. Some formats (TrueType & OpenType) */+ /* provide localized and Unicode versions of */+ /* this string. Applications should use the */+ /* format specific interface to access them. */+ /* Can be NULL (e.g., in fonts embedded in a */+ /* PDF file). */+ /* */+ /* style_name :: The face's style name. This is an ASCII */+ /* string, usually in English, which describes */+ /* the typeface's style (like `Italic', */+ /* `Bold', `Condensed', etc). Not all font */+ /* formats provide a style name, so this field */+ /* is optional, and can be set to NULL. As */+ /* for `family_name', some formats provide */+ /* localized and Unicode versions of this */+ /* string. Applications should use the format */+ /* specific interface to access them. */+ /* */+ /* num_fixed_sizes :: The number of bitmap strikes in the face. */+ /* Even if the face is scalable, there might */+ /* still be bitmap strikes, which are called */+ /* `sbits' in that case. */+ /* */+ /* available_sizes :: An array of @FT_Bitmap_Size for all bitmap */+ /* strikes in the face. It is set to NULL if */+ /* there is no bitmap strike. */+ /* */+ /* num_charmaps :: The number of charmaps in the face. */+ /* */+ /* charmaps :: An array of the charmaps of the face. */+ /* */+ /* generic :: A field reserved for client uses. See the */+ /* @FT_Generic type description. */+ /* */+ /* bbox :: The font bounding box. Coordinates are */+ /* expressed in font units (see */+ /* `units_per_EM'). The box is large enough */+ /* to contain any glyph from the font. Thus, */+ /* `bbox.yMax' can be seen as the `maximal */+ /* ascender', and `bbox.yMin' as the `minimal */+ /* descender'. Only relevant for scalable */+ /* formats. */+ /* */+ /* Note that the bounding box might be off by */+ /* (at least) one pixel for hinted fonts. See */+ /* @FT_Size_Metrics for further discussion. */+ /* */+ /* units_per_EM :: The number of font units per EM square for */+ /* this face. This is typically 2048 for */+ /* TrueType fonts, and 1000 for Type~1 fonts. */+ /* Only relevant for scalable formats. */+ /* */+ /* ascender :: The typographic ascender of the face, */+ /* expressed in font units. For font formats */+ /* not having this information, it is set to */+ /* `bbox.yMax'. Only relevant for scalable */+ /* formats. */+ /* */+ /* descender :: The typographic descender of the face, */+ /* expressed in font units. For font formats */+ /* not having this information, it is set to */+ /* `bbox.yMin'. Note that this field is */+ /* usually negative. Only relevant for */+ /* scalable formats. */+ /* */+ /* height :: The height is the vertical distance */+ /* between two consecutive baselines, */+ /* expressed in font units. It is always */+ /* positive. Only relevant for scalable */+ /* formats. */+ /* */+ /* max_advance_width :: The maximal advance width, in font units, */+ /* for all glyphs in this face. This can be */+ /* used to make word wrapping computations */+ /* faster. Only relevant for scalable */+ /* formats. */+ /* */+ /* max_advance_height :: The maximal advance height, in font units, */+ /* for all glyphs in this face. This is only */+ /* relevant for vertical layouts, and is set */+ /* to `height' for fonts that do not provide */+ /* vertical metrics. Only relevant for */+ /* scalable formats. */+ /* */+ /* underline_position :: The position, in font units, of the */+ /* underline line for this face. It is the */+ /* center of the underlining stem. Only */+ /* relevant for scalable formats. */+ /* */+ /* underline_thickness :: The thickness, in font units, of the */+ /* underline for this face. Only relevant for */+ /* scalable formats. */+ /* */+ /* glyph :: The face's associated glyph slot(s). */+ /* */+ /* size :: The current active size for this face. */+ /* */+ /* charmap :: The current active charmap for this face. */+ /* */+ /* <Note> */+ /* Fields may be changed after a call to @FT_Attach_File or */+ /* @FT_Attach_Stream. */+ /* */+ typedef struct FT_FaceRec_+ {+ FT_Long num_faces;+ FT_Long face_index;++ FT_Long face_flags;+ FT_Long style_flags;++ FT_Long num_glyphs;++ FT_String* family_name;+ FT_String* style_name;++ FT_Int num_fixed_sizes;+ FT_Bitmap_Size* available_sizes;++ FT_Int num_charmaps;+ FT_CharMap* charmaps;++ FT_Generic generic;++ /*# The following member variables (down to `underline_thickness') */+ /*# are only relevant to scalable outlines; cf. @FT_Bitmap_Size */+ /*# for bitmap fonts. */+ FT_BBox bbox;++ FT_UShort units_per_EM;+ FT_Short ascender;+ FT_Short descender;+ FT_Short height;++ FT_Short max_advance_width;+ FT_Short max_advance_height;++ FT_Short underline_position;+ FT_Short underline_thickness;++ FT_GlyphSlot glyph;+ FT_Size size;+ FT_CharMap charmap;++ /*@private begin */++ FT_Driver driver;+ FT_Memory memory;+ FT_Stream stream;++ FT_ListRec sizes_list;++ FT_Generic autohint;+ void* extensions;++ FT_Face_Internal internal;++ /*@private end */++ } FT_FaceRec;+++ /*************************************************************************/+ /* */+ /* <Enum> */+ /* FT_FACE_FLAG_XXX */+ /* */+ /* <Description> */+ /* A list of bit flags used in the `face_flags' field of the */+ /* @FT_FaceRec structure. They inform client applications of */+ /* properties of the corresponding face. */+ /* */+ /* <Values> */+ /* FT_FACE_FLAG_SCALABLE :: */+ /* Indicates that the face contains outline glyphs. This doesn't */+ /* prevent bitmap strikes, i.e., a face can have both this and */+ /* and @FT_FACE_FLAG_FIXED_SIZES set. */+ /* */+ /* FT_FACE_FLAG_FIXED_SIZES :: */+ /* Indicates that the face contains bitmap strikes. See also the */+ /* `num_fixed_sizes' and `available_sizes' fields of @FT_FaceRec. */+ /* */+ /* FT_FACE_FLAG_FIXED_WIDTH :: */+ /* Indicates that the face contains fixed-width characters (like */+ /* Courier, Lucido, MonoType, etc.). */+ /* */+ /* FT_FACE_FLAG_SFNT :: */+ /* Indicates that the face uses the `sfnt' storage scheme. For */+ /* now, this means TrueType and OpenType. */+ /* */+ /* FT_FACE_FLAG_HORIZONTAL :: */+ /* Indicates that the face contains horizontal glyph metrics. This */+ /* should be set for all common formats. */+ /* */+ /* FT_FACE_FLAG_VERTICAL :: */+ /* Indicates that the face contains vertical glyph metrics. This */+ /* is only available in some formats, not all of them. */+ /* */+ /* FT_FACE_FLAG_KERNING :: */+ /* Indicates that the face contains kerning information. If set, */+ /* the kerning distance can be retrieved through the function */+ /* @FT_Get_Kerning. Otherwise the function always return the */+ /* vector (0,0). Note that FreeType doesn't handle kerning data */+ /* from the `GPOS' table (as present in some OpenType fonts). */+ /* */+ /* FT_FACE_FLAG_FAST_GLYPHS :: */+ /* THIS FLAG IS DEPRECATED. DO NOT USE OR TEST IT. */+ /* */+ /* FT_FACE_FLAG_MULTIPLE_MASTERS :: */+ /* Indicates that the font contains multiple masters and is capable */+ /* of interpolating between them. See the multiple-masters */+ /* specific API for details. */+ /* */+ /* FT_FACE_FLAG_GLYPH_NAMES :: */+ /* Indicates that the font contains glyph names that can be */+ /* retrieved through @FT_Get_Glyph_Name. Note that some TrueType */+ /* fonts contain broken glyph name tables. Use the function */+ /* @FT_Has_PS_Glyph_Names when needed. */+ /* */+ /* FT_FACE_FLAG_EXTERNAL_STREAM :: */+ /* Used internally by FreeType to indicate that a face's stream was */+ /* provided by the client application and should not be destroyed */+ /* when @FT_Done_Face is called. Don't read or test this flag. */+ /* */+ /* FT_FACE_FLAG_HINTER :: */+ /* Set if the font driver has a hinting machine of its own. For */+ /* example, with TrueType fonts, it makes sense to use data from */+ /* the SFNT `gasp' table only if the native TrueType hinting engine */+ /* (with the bytecode interpreter) is available and active. */+ /* */+ /* FT_FACE_FLAG_CID_KEYED :: */+ /* Set if the font is CID-keyed. In that case, the font is not */+ /* accessed by glyph indices but by CID values. For subsetted */+ /* CID-keyed fonts this has the consequence that not all index */+ /* values are a valid argument to FT_Load_Glyph. Only the CID */+ /* values for which corresponding glyphs in the subsetted font */+ /* exist make FT_Load_Glyph return successfully; in all other cases */+ /* you get an `FT_Err_Invalid_Argument' error. */+ /* */+ /* Note that CID-keyed fonts which are in an SFNT wrapper don't */+ /* have this flag set since the glyphs are accessed in the normal */+ /* way (using contiguous indices); the `CID-ness' isn't visible to */+ /* the application. */+ /* */+ /* FT_FACE_FLAG_TRICKY :: */+ /* Set if the font is `tricky', this is, it always needs the */+ /* font format's native hinting engine to get a reasonable result. */+ /* A typical example is the Chinese font `mingli.ttf' which uses */+ /* TrueType bytecode instructions to move and scale all of its */+ /* subglyphs. */+ /* */+ /* It is not possible to autohint such fonts using */+ /* @FT_LOAD_FORCE_AUTOHINT; it will also ignore */+ /* @FT_LOAD_NO_HINTING. You have to set both FT_LOAD_NO_HINTING */+ /* and @FT_LOAD_NO_AUTOHINT to really disable hinting; however, you */+ /* probably never want this except for demonstration purposes. */+ /* */+ /* Currently, there are six TrueType fonts in the list of tricky */+ /* fonts; they are hard-coded in file `ttobjs.c'. */+ /* */+#define FT_FACE_FLAG_SCALABLE ( 1L << 0 )+#define FT_FACE_FLAG_FIXED_SIZES ( 1L << 1 )+#define FT_FACE_FLAG_FIXED_WIDTH ( 1L << 2 )+#define FT_FACE_FLAG_SFNT ( 1L << 3 )+#define FT_FACE_FLAG_HORIZONTAL ( 1L << 4 )+#define FT_FACE_FLAG_VERTICAL ( 1L << 5 )+#define FT_FACE_FLAG_KERNING ( 1L << 6 )+#define FT_FACE_FLAG_FAST_GLYPHS ( 1L << 7 )+#define FT_FACE_FLAG_MULTIPLE_MASTERS ( 1L << 8 )+#define FT_FACE_FLAG_GLYPH_NAMES ( 1L << 9 )+#define FT_FACE_FLAG_EXTERNAL_STREAM ( 1L << 10 )+#define FT_FACE_FLAG_HINTER ( 1L << 11 )+#define FT_FACE_FLAG_CID_KEYED ( 1L << 12 )+#define FT_FACE_FLAG_TRICKY ( 1L << 13 )+++ /*************************************************************************+ *+ * @macro:+ * FT_HAS_HORIZONTAL( face )+ *+ * @description:+ * A macro that returns true whenever a face object contains+ * horizontal metrics (this is true for all font formats though).+ *+ * @also:+ * @FT_HAS_VERTICAL can be used to check for vertical metrics.+ *+ */+#define FT_HAS_HORIZONTAL( face ) \+ ( face->face_flags & FT_FACE_FLAG_HORIZONTAL )+++ /*************************************************************************+ *+ * @macro:+ * FT_HAS_VERTICAL( face )+ *+ * @description:+ * A macro that returns true whenever a face object contains vertical+ * metrics.+ *+ */+#define FT_HAS_VERTICAL( face ) \+ ( face->face_flags & FT_FACE_FLAG_VERTICAL )+++ /*************************************************************************+ *+ * @macro:+ * FT_HAS_KERNING( face )+ *+ * @description:+ * A macro that returns true whenever a face object contains kerning+ * data that can be accessed with @FT_Get_Kerning.+ *+ */+#define FT_HAS_KERNING( face ) \+ ( face->face_flags & FT_FACE_FLAG_KERNING )+++ /*************************************************************************+ *+ * @macro:+ * FT_IS_SCALABLE( face )+ *+ * @description:+ * A macro that returns true whenever a face object contains a scalable+ * font face (true for TrueType, Type~1, Type~42, CID, OpenType/CFF,+ * and PFR font formats.+ *+ */+#define FT_IS_SCALABLE( face ) \+ ( face->face_flags & FT_FACE_FLAG_SCALABLE )+++ /*************************************************************************+ *+ * @macro:+ * FT_IS_SFNT( face )+ *+ * @description:+ * A macro that returns true whenever a face object contains a font+ * whose format is based on the SFNT storage scheme. This usually+ * means: TrueType fonts, OpenType fonts, as well as SFNT-based embedded+ * bitmap fonts.+ *+ * If this macro is true, all functions defined in @FT_SFNT_NAMES_H and+ * @FT_TRUETYPE_TABLES_H are available.+ *+ */+#define FT_IS_SFNT( face ) \+ ( face->face_flags & FT_FACE_FLAG_SFNT )+++ /*************************************************************************+ *+ * @macro:+ * FT_IS_FIXED_WIDTH( face )+ *+ * @description:+ * A macro that returns true whenever a face object contains a font face+ * that contains fixed-width (or `monospace', `fixed-pitch', etc.)+ * glyphs.+ *+ */+#define FT_IS_FIXED_WIDTH( face ) \+ ( face->face_flags & FT_FACE_FLAG_FIXED_WIDTH )+++ /*************************************************************************+ *+ * @macro:+ * FT_HAS_FIXED_SIZES( face )+ *+ * @description:+ * A macro that returns true whenever a face object contains some+ * embedded bitmaps. See the `available_sizes' field of the+ * @FT_FaceRec structure.+ *+ */+#define FT_HAS_FIXED_SIZES( face ) \+ ( face->face_flags & FT_FACE_FLAG_FIXED_SIZES )+++ /*************************************************************************+ *+ * @macro:+ * FT_HAS_FAST_GLYPHS( face )+ *+ * @description:+ * Deprecated.+ *+ */+#define FT_HAS_FAST_GLYPHS( face ) 0+++ /*************************************************************************+ *+ * @macro:+ * FT_HAS_GLYPH_NAMES( face )+ *+ * @description:+ * A macro that returns true whenever a face object contains some glyph+ * names that can be accessed through @FT_Get_Glyph_Name.+ *+ */+#define FT_HAS_GLYPH_NAMES( face ) \+ ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES )+++ /*************************************************************************+ *+ * @macro:+ * FT_HAS_MULTIPLE_MASTERS( face )+ *+ * @description:+ * A macro that returns true whenever a face object contains some+ * multiple masters. The functions provided by @FT_MULTIPLE_MASTERS_H+ * are then available to choose the exact design you want.+ *+ */+#define FT_HAS_MULTIPLE_MASTERS( face ) \+ ( face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS )+++ /*************************************************************************+ *+ * @macro:+ * FT_IS_CID_KEYED( face )+ *+ * @description:+ * A macro that returns true whenever a face object contains a CID-keyed+ * font. See the discussion of @FT_FACE_FLAG_CID_KEYED for more+ * details.+ *+ * If this macro is true, all functions defined in @FT_CID_H are+ * available.+ *+ */+#define FT_IS_CID_KEYED( face ) \+ ( face->face_flags & FT_FACE_FLAG_CID_KEYED )+++ /*************************************************************************+ *+ * @macro:+ * FT_IS_TRICKY( face )+ *+ * @description:+ * A macro that returns true whenever a face represents a `tricky' font.+ * See the discussion of @FT_FACE_FLAG_TRICKY for more details.+ *+ */+#define FT_IS_TRICKY( face ) \+ ( face->face_flags & FT_FACE_FLAG_TRICKY )+++ /*************************************************************************/+ /* */+ /* <Const> */+ /* FT_STYLE_FLAG_XXX */+ /* */+ /* <Description> */+ /* 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> */+ /* FT_STYLE_FLAG_ITALIC :: */+ /* Indicates that a given face style is italic or oblique. */+ /* */+ /* FT_STYLE_FLAG_BOLD :: */+ /* Indicates that a given face is bold. */+ /* */+ /* <Note> */+ /* The style information as provided by FreeType is very basic. More */+ /* details are beyond the scope and should be done on a higher level */+ /* (for example, by analyzing various fields of the `OS/2' table in */+ /* SFNT based fonts). */+ /* */+#define FT_STYLE_FLAG_ITALIC ( 1 << 0 )+#define FT_STYLE_FLAG_BOLD ( 1 << 1 )+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_Size_Internal */+ /* */+ /* <Description> */+ /* An opaque handle to an `FT_Size_InternalRec' structure, used to */+ /* model private data of a given @FT_Size object. */+ /* */+ typedef struct FT_Size_InternalRec_* FT_Size_Internal;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_Size_Metrics */+ /* */+ /* <Description> */+ /* The size metrics structure gives the metrics of a size object. */+ /* */+ /* <Fields> */+ /* x_ppem :: The width of the scaled EM square in pixels, hence */+ /* the term `ppem' (pixels per EM). It is also */+ /* referred to as `nominal width'. */+ /* */+ /* y_ppem :: The height of the scaled EM square in pixels, */+ /* hence the term `ppem' (pixels per EM). It is also */+ /* referred to as `nominal height'. */+ /* */+ /* x_scale :: A 16.16 fractional scaling value used to convert */+ /* horizontal metrics from font units to 26.6 */+ /* fractional pixels. Only relevant for scalable */+ /* font formats. */+ /* */+ /* y_scale :: A 16.16 fractional scaling value used to convert */+ /* vertical metrics from font units to 26.6 */+ /* fractional pixels. Only relevant for scalable */+ /* font formats. */+ /* */+ /* ascender :: The ascender in 26.6 fractional pixels. See */+ /* @FT_FaceRec for the details. */+ /* */+ /* descender :: The descender in 26.6 fractional pixels. See */+ /* @FT_FaceRec for the details. */+ /* */+ /* height :: The height in 26.6 fractional pixels. See */+ /* @FT_FaceRec for the details. */+ /* */+ /* max_advance :: The maximal advance width in 26.6 fractional */+ /* pixels. See @FT_FaceRec for the details. */+ /* */+ /* <Note> */+ /* The scaling values, if relevant, are determined first during a */+ /* size changing operation. The remaining fields are then set by the */+ /* driver. For scalable formats, they are usually set to scaled */+ /* values of the corresponding fields in @FT_FaceRec. */+ /* */+ /* Note that due to glyph hinting, these values might not be exact */+ /* for certain fonts. Thus they must be treated as unreliable */+ /* with an error margin of at least one pixel! */+ /* */+ /* Indeed, the only way to get the exact metrics is to render _all_ */+ /* glyphs. As this would be a definite performance hit, it is up to */+ /* client applications to perform such computations. */+ /* */+ /* The FT_Size_Metrics structure is valid for bitmap fonts also. */+ /* */+ typedef struct FT_Size_Metrics_+ {+ FT_UShort x_ppem; /* horizontal pixels per EM */+ FT_UShort y_ppem; /* vertical pixels per EM */++ FT_Fixed x_scale; /* scaling values used to convert font */+ FT_Fixed y_scale; /* units to 26.6 fractional pixels */++ FT_Pos ascender; /* ascender in 26.6 frac. pixels */+ FT_Pos descender; /* descender in 26.6 frac. pixels */+ FT_Pos height; /* text height in 26.6 frac. pixels */+ FT_Pos max_advance; /* max horizontal advance, in 26.6 pixels */++ } FT_Size_Metrics;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_SizeRec */+ /* */+ /* <Description> */+ /* FreeType root size class structure. A size object models a face */+ /* object at a given size. */+ /* */+ /* <Fields> */+ /* face :: Handle to the parent face object. */+ /* */+ /* generic :: A typeless pointer, which is unused by the FreeType */+ /* library or any of its drivers. It can be used by */+ /* client applications to link their own data to each size */+ /* object. */+ /* */+ /* metrics :: Metrics for this size object. This field is read-only. */+ /* */+ typedef struct FT_SizeRec_+ {+ FT_Face face; /* parent face object */+ FT_Generic generic; /* generic pointer for client uses */+ FT_Size_Metrics metrics; /* size metrics */+ FT_Size_Internal internal;++ } FT_SizeRec;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_SubGlyph */+ /* */+ /* <Description> */+ /* The subglyph structure is an internal object used to describe */+ /* subglyphs (for example, in the case of composites). */+ /* */+ /* <Note> */+ /* The subglyph implementation is not part of the high-level API, */+ /* hence the forward structure declaration. */+ /* */+ /* You can however retrieve subglyph information with */+ /* @FT_Get_SubGlyph_Info. */+ /* */+ typedef struct FT_SubGlyphRec_* FT_SubGlyph;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_Slot_Internal */+ /* */+ /* <Description> */+ /* An opaque handle to an `FT_Slot_InternalRec' structure, used to */+ /* model private data of a given @FT_GlyphSlot object. */+ /* */+ typedef struct FT_Slot_InternalRec_* FT_Slot_Internal;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_GlyphSlotRec */+ /* */+ /* <Description> */+ /* FreeType root glyph slot class structure. A glyph slot is a */+ /* container where individual glyphs can be loaded, be they in */+ /* outline or bitmap format. */+ /* */+ /* <Fields> */+ /* library :: A handle to the FreeType library instance */+ /* this slot belongs to. */+ /* */+ /* face :: A handle to the parent face object. */+ /* */+ /* next :: In some cases (like some font tools), several */+ /* glyph slots per face object can be a good */+ /* thing. As this is rare, the glyph slots are */+ /* listed through a direct, single-linked list */+ /* using its `next' field. */+ /* */+ /* generic :: A typeless pointer which is unused by the */+ /* FreeType library or any of its drivers. It */+ /* can be used by client applications to link */+ /* their own data to each glyph slot object. */+ /* */+ /* metrics :: The metrics of the last loaded glyph in the */+ /* slot. The returned values depend on the last */+ /* load flags (see the @FT_Load_Glyph API */+ /* function) and can be expressed either in 26.6 */+ /* fractional pixels or font units. */+ /* */+ /* Note that even when the glyph image is */+ /* transformed, the metrics are not. */+ /* */+ /* linearHoriAdvance :: The advance width of the unhinted glyph. */+ /* Its value is expressed in 16.16 fractional */+ /* pixels, unless @FT_LOAD_LINEAR_DESIGN is set */+ /* when loading the glyph. This field can be */+ /* important to perform correct WYSIWYG layout. */+ /* Only relevant for outline glyphs. */+ /* */+ /* linearVertAdvance :: The advance height of the unhinted glyph. */+ /* Its value is expressed in 16.16 fractional */+ /* pixels, unless @FT_LOAD_LINEAR_DESIGN is set */+ /* when loading the glyph. This field can be */+ /* important to perform correct WYSIWYG layout. */+ /* Only relevant for outline glyphs. */+ /* */+ /* advance :: This shorthand is, depending on */+ /* @FT_LOAD_IGNORE_TRANSFORM, the transformed */+ /* advance width for the glyph (in 26.6 */+ /* fractional pixel format). As specified with */+ /* @FT_LOAD_VERTICAL_LAYOUT, it uses either the */+ /* `horiAdvance' or the `vertAdvance' value of */+ /* `metrics' field. */+ /* */+ /* format :: This field indicates the format of the image */+ /* contained in the glyph slot. Typically */+ /* @FT_GLYPH_FORMAT_BITMAP, */+ /* @FT_GLYPH_FORMAT_OUTLINE, or */+ /* @FT_GLYPH_FORMAT_COMPOSITE, but others are */+ /* possible. */+ /* */+ /* bitmap :: This field is used as a bitmap descriptor */+ /* when the slot format is */+ /* @FT_GLYPH_FORMAT_BITMAP. Note that the */+ /* address and content of the bitmap buffer can */+ /* change between calls of @FT_Load_Glyph and a */+ /* few other functions. */+ /* */+ /* bitmap_left :: This is the bitmap's left bearing expressed */+ /* in integer pixels. Of course, this is only */+ /* valid if the format is */+ /* @FT_GLYPH_FORMAT_BITMAP. */+ /* */+ /* bitmap_top :: This is the bitmap's top bearing expressed in */+ /* integer pixels. Remember that this is the */+ /* distance from the baseline to the top-most */+ /* glyph scanline, upwards y~coordinates being */+ /* *positive*. */+ /* */+ /* outline :: The outline descriptor for the current glyph */+ /* image if its format is */+ /* @FT_GLYPH_FORMAT_OUTLINE. Once a glyph is */+ /* loaded, `outline' can be transformed, */+ /* distorted, embolded, etc. However, it must */+ /* not be freed. */+ /* */+ /* num_subglyphs :: The number of subglyphs in a composite glyph. */+ /* This field is only valid for the composite */+ /* glyph format that should normally only be */+ /* loaded with the @FT_LOAD_NO_RECURSE flag. */+ /* For now this is internal to FreeType. */+ /* */+ /* subglyphs :: An array of subglyph descriptors for */+ /* composite glyphs. There are `num_subglyphs' */+ /* elements in there. Currently internal to */+ /* FreeType. */+ /* */+ /* control_data :: Certain font drivers can also return the */+ /* control data for a given glyph image (e.g. */+ /* TrueType bytecode, Type~1 charstrings, etc.). */+ /* This field is a pointer to such data. */+ /* */+ /* control_len :: This is the length in bytes of the control */+ /* data. */+ /* */+ /* other :: Really wicked formats can use this pointer to */+ /* present their own glyph image to client */+ /* applications. Note that the application */+ /* needs to know about the image format. */+ /* */+ /* lsb_delta :: The difference between hinted and unhinted */+ /* left side bearing while autohinting is */+ /* active. Zero otherwise. */+ /* */+ /* rsb_delta :: The difference between hinted and unhinted */+ /* right side bearing while autohinting is */+ /* active. Zero otherwise. */+ /* */+ /* <Note> */+ /* If @FT_Load_Glyph is called with default flags (see */+ /* @FT_LOAD_DEFAULT) the glyph image is loaded in the glyph slot in */+ /* its native format (e.g., an outline glyph for TrueType and Type~1 */+ /* formats). */+ /* */+ /* This image can later be converted into a bitmap by calling */+ /* @FT_Render_Glyph. This function finds the current renderer for */+ /* the native image's format, then invokes it. */+ /* */+ /* The renderer is in charge of transforming the native image through */+ /* the slot's face transformation fields, then converting it into a */+ /* bitmap that is returned in `slot->bitmap'. */+ /* */+ /* Note that `slot->bitmap_left' and `slot->bitmap_top' are also used */+ /* to specify the position of the bitmap relative to the current pen */+ /* position (e.g., coordinates (0,0) on the baseline). Of course, */+ /* `slot->format' is also changed to @FT_GLYPH_FORMAT_BITMAP. */+ /* */+ /* <Note> */+ /* Here a small pseudo code fragment which shows how to use */+ /* `lsb_delta' and `rsb_delta': */+ /* */+ /* { */+ /* FT_Pos origin_x = 0; */+ /* FT_Pos prev_rsb_delta = 0; */+ /* */+ /* */+ /* for all glyphs do */+ /* <compute kern between current and previous glyph and add it to */+ /* `origin_x'> */+ /* */+ /* <load glyph with `FT_Load_Glyph'> */+ /* */+ /* if ( prev_rsb_delta - face->glyph->lsb_delta >= 32 ) */+ /* origin_x -= 64; */+ /* else if ( prev_rsb_delta - face->glyph->lsb_delta < -32 ) */+ /* origin_x += 64; */+ /* */+ /* prev_rsb_delta = face->glyph->rsb_delta; */+ /* */+ /* <save glyph image, or render glyph, or ...> */+ /* */+ /* origin_x += face->glyph->advance.x; */+ /* endfor */+ /* } */+ /* */+ typedef struct FT_GlyphSlotRec_+ {+ FT_Library library;+ FT_Face face;+ FT_GlyphSlot next;+ FT_UInt reserved; /* retained for binary compatibility */+ FT_Generic generic;++ FT_Glyph_Metrics metrics;+ FT_Fixed linearHoriAdvance;+ FT_Fixed linearVertAdvance;+ FT_Vector advance;++ FT_Glyph_Format format;++ FT_Bitmap bitmap;+ FT_Int bitmap_left;+ FT_Int bitmap_top;++ FT_Outline outline;++ FT_UInt num_subglyphs;+ FT_SubGlyph subglyphs;++ void* control_data;+ long control_len;++ FT_Pos lsb_delta;+ FT_Pos rsb_delta;++ void* other;++ FT_Slot_Internal internal;++ } FT_GlyphSlotRec;+++ /*************************************************************************/+ /*************************************************************************/+ /* */+ /* F U N C T I O N S */+ /* */+ /*************************************************************************/+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Init_FreeType */+ /* */+ /* <Description> */+ /* Initialize a new FreeType library object. The set of modules */+ /* that are registered by this function is determined at build time. */+ /* */+ /* <Output> */+ /* alibrary :: A handle to a new library object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* In case you want to provide your own memory allocating routines, */+ /* use @FT_New_Library instead, followed by a call to */+ /* @FT_Add_Default_Modules (or a series of calls to @FT_Add_Module). */+ /* */+ FT_EXPORT( FT_Error )+ FT_Init_FreeType( FT_Library *alibrary );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Done_FreeType */+ /* */+ /* <Description> */+ /* Destroy a given FreeType library object and all of its children, */+ /* including resources, drivers, faces, sizes, etc. */+ /* */+ /* <Input> */+ /* library :: A handle to the target library object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Done_FreeType( FT_Library library );+++ /*************************************************************************/+ /* */+ /* <Enum> */+ /* FT_OPEN_XXX */+ /* */+ /* <Description> */+ /* A list of bit-field constants used within the `flags' field of the */+ /* @FT_Open_Args structure. */+ /* */+ /* <Values> */+ /* FT_OPEN_MEMORY :: This is a memory-based stream. */+ /* */+ /* FT_OPEN_STREAM :: Copy the stream from the `stream' field. */+ /* */+ /* FT_OPEN_PATHNAME :: Create a new input stream from a C~path */+ /* name. */+ /* */+ /* FT_OPEN_DRIVER :: Use the `driver' field. */+ /* */+ /* FT_OPEN_PARAMS :: Use the `num_params' and `params' fields. */+ /* */+ /* ft_open_memory :: Deprecated; use @FT_OPEN_MEMORY instead. */+ /* */+ /* ft_open_stream :: Deprecated; use @FT_OPEN_STREAM instead. */+ /* */+ /* ft_open_pathname :: Deprecated; use @FT_OPEN_PATHNAME instead. */+ /* */+ /* ft_open_driver :: Deprecated; use @FT_OPEN_DRIVER instead. */+ /* */+ /* ft_open_params :: Deprecated; use @FT_OPEN_PARAMS instead. */+ /* */+ /* <Note> */+ /* The `FT_OPEN_MEMORY', `FT_OPEN_STREAM', and `FT_OPEN_PATHNAME' */+ /* flags are mutually exclusive. */+ /* */+#define FT_OPEN_MEMORY 0x1+#define FT_OPEN_STREAM 0x2+#define FT_OPEN_PATHNAME 0x4+#define FT_OPEN_DRIVER 0x8+#define FT_OPEN_PARAMS 0x10++#define ft_open_memory FT_OPEN_MEMORY /* deprecated */+#define ft_open_stream FT_OPEN_STREAM /* deprecated */+#define ft_open_pathname FT_OPEN_PATHNAME /* deprecated */+#define ft_open_driver FT_OPEN_DRIVER /* deprecated */+#define ft_open_params FT_OPEN_PARAMS /* deprecated */+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_Parameter */+ /* */+ /* <Description> */+ /* A simple structure used to pass more or less generic parameters to */+ /* @FT_Open_Face. */+ /* */+ /* <Fields> */+ /* tag :: A four-byte identification tag. */+ /* */+ /* data :: A pointer to the parameter data. */+ /* */+ /* <Note> */+ /* The ID and function of parameters are driver-specific. See the */+ /* various FT_PARAM_TAG_XXX flags for more information. */+ /* */+ typedef struct FT_Parameter_+ {+ FT_ULong tag;+ FT_Pointer data;++ } FT_Parameter;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_Open_Args */+ /* */+ /* <Description> */+ /* A structure used to indicate how to open a new font file or */+ /* stream. A pointer to such a structure can be used as a parameter */+ /* for the functions @FT_Open_Face and @FT_Attach_Stream. */+ /* */+ /* <Fields> */+ /* flags :: A set of bit flags indicating how to use the */+ /* structure. */+ /* */+ /* memory_base :: The first byte of the file in memory. */+ /* */+ /* memory_size :: The size in bytes of the file in memory. */+ /* */+ /* pathname :: A pointer to an 8-bit file pathname. */+ /* */+ /* stream :: A handle to a source stream object. */+ /* */+ /* driver :: This field is exclusively used by @FT_Open_Face; */+ /* it simply specifies the font driver to use to open */+ /* the face. If set to~0, FreeType tries to load the */+ /* face with each one of the drivers in its list. */+ /* */+ /* num_params :: The number of extra parameters. */+ /* */+ /* params :: Extra parameters passed to the font driver when */+ /* opening a new face. */+ /* */+ /* <Note> */+ /* The stream type is determined by the contents of `flags' which */+ /* are tested in the following order by @FT_Open_Face: */+ /* */+ /* If the `FT_OPEN_MEMORY' bit is set, assume that this is a */+ /* memory file of `memory_size' bytes, located at `memory_address'. */+ /* The data are are not copied, and the client is responsible for */+ /* releasing and destroying them _after_ the corresponding call to */+ /* @FT_Done_Face. */+ /* */+ /* Otherwise, if the `FT_OPEN_STREAM' bit is set, assume that a */+ /* custom input stream `stream' is used. */+ /* */+ /* Otherwise, if the `FT_OPEN_PATHNAME' bit is set, assume that this */+ /* is a normal file and use `pathname' to open it. */+ /* */+ /* If the `FT_OPEN_DRIVER' bit is set, @FT_Open_Face only tries to */+ /* open the file with the driver whose handler is in `driver'. */+ /* */+ /* If the `FT_OPEN_PARAMS' bit is set, the parameters given by */+ /* `num_params' and `params' is used. They are ignored otherwise. */+ /* */+ /* Ideally, both the `pathname' and `params' fields should be tagged */+ /* as `const'; this is missing for API backwards compatibility. In */+ /* other words, applications should treat them as read-only. */+ /* */+ typedef struct FT_Open_Args_+ {+ FT_UInt flags;+ const FT_Byte* memory_base;+ FT_Long memory_size;+ FT_String* pathname;+ FT_Stream stream;+ FT_Module driver;+ FT_Int num_params;+ FT_Parameter* params;++ } FT_Open_Args;+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_New_Face */+ /* */+ /* <Description> */+ /* This function calls @FT_Open_Face to open a font by its pathname. */+ /* */+ /* <InOut> */+ /* library :: A handle to the library resource. */+ /* */+ /* <Input> */+ /* pathname :: A path to the font file. */+ /* */+ /* face_index :: The index of the face within the font. The first */+ /* face has index~0. */+ /* */+ /* <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. */+ /* */+ FT_EXPORT( FT_Error )+ FT_New_Face( FT_Library library,+ const char* filepathname,+ FT_Long face_index,+ FT_Face *aface );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_New_Memory_Face */+ /* */+ /* <Description> */+ /* This function calls @FT_Open_Face to open a font which has been */+ /* loaded into memory. */+ /* */+ /* <InOut> */+ /* library :: A handle to the library resource. */+ /* */+ /* <Input> */+ /* file_base :: A pointer to the beginning of the font data. */+ /* */+ /* 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. */+ /* */+ /* <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. */+ /* */+ /* <Note> */+ /* You must not deallocate the memory before calling @FT_Done_Face. */+ /* */+ FT_EXPORT( FT_Error )+ FT_New_Memory_Face( FT_Library library,+ const FT_Byte* file_base,+ FT_Long file_size,+ FT_Long face_index,+ FT_Face *aface );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Open_Face */+ /* */+ /* <Description> */+ /* Create a face object from a given resource described by */+ /* @FT_Open_Args. */+ /* */+ /* <InOut> */+ /* library :: A handle to the library resource. */+ /* */+ /* <Input> */+ /* args :: A pointer to an `FT_Open_Args' structure which must */+ /* be filled by the caller. */+ /* */+ /* face_index :: The index of the face within the font. The first */+ /* face has index~0. */+ /* */+ /* <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. */+ /* */+ /* <Note> */+ /* Unlike FreeType 1.x, this function automatically creates a glyph */+ /* slot for the face object which 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' which 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'. */+ /* */+ /* See the discussion of reference counters in the description of */+ /* @FT_Reference_Face. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Open_Face( FT_Library library,+ const FT_Open_Args* args,+ FT_Long face_index,+ FT_Face *aface );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Attach_File */+ /* */+ /* <Description> */+ /* This function calls @FT_Attach_Stream to attach a file. */+ /* */+ /* <InOut> */+ /* face :: The target face object. */+ /* */+ /* <Input> */+ /* filepathname :: The pathname. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Attach_File( FT_Face face,+ const char* filepathname );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Attach_Stream */+ /* */+ /* <Description> */+ /* `Attach' data to a face object. Normally, this is used to read */+ /* additional information for the face object. For example, you can */+ /* attach an AFM file that comes with a Type~1 font to get the */+ /* kerning values and other metrics. */+ /* */+ /* <InOut> */+ /* face :: The target face object. */+ /* */+ /* <Input> */+ /* parameters :: A pointer to @FT_Open_Args which must be filled by */+ /* the caller. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* The meaning of the `attach' (i.e., what really happens when the */+ /* new file is read) is not fixed by FreeType itself. It really */+ /* depends on the font format (and thus the font driver). */+ /* */+ /* Client applications are expected to know what they are doing */+ /* when invoking this function. Most drivers simply do not implement */+ /* file attachments. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Attach_Stream( FT_Face face,+ FT_Open_Args* parameters );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Reference_Face */+ /* */+ /* <Description> */+ /* A counter gets initialized to~1 at the time an @FT_Face structure */+ /* is created. This function increments the counter. @FT_Done_Face */+ /* then only destroys a face if the counter is~1, otherwise it simply */+ /* decrements the counter. */+ /* */+ /* This function helps in managing life-cycles of structures which */+ /* reference @FT_Face objects. */+ /* */+ /* <Input> */+ /* face :: A handle to a target face object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Since> */+ /* 2.4.2 */+ /* */+ FT_EXPORT( FT_Error )+ FT_Reference_Face( FT_Face face );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Done_Face */+ /* */+ /* <Description> */+ /* Discard a given face object, as well as all of its child slots and */+ /* sizes. */+ /* */+ /* <Input> */+ /* face :: A handle to a target face object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* See the discussion of reference counters in the description of */+ /* @FT_Reference_Face. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Done_Face( FT_Face face );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Select_Size */+ /* */+ /* <Description> */+ /* Select a bitmap strike. */+ /* */+ /* <InOut> */+ /* face :: A handle to a target face object. */+ /* */+ /* <Input> */+ /* strike_index :: The index of the bitmap strike in the */+ /* `available_sizes' field of @FT_FaceRec structure. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Select_Size( FT_Face face,+ FT_Int strike_index );+++ /*************************************************************************/+ /* */+ /* <Enum> */+ /* FT_Size_Request_Type */+ /* */+ /* <Description> */+ /* An enumeration type that lists the supported size request types. */+ /* */+ /* <Values> */+ /* FT_SIZE_REQUEST_TYPE_NOMINAL :: */+ /* The nominal size. The `units_per_EM' field of @FT_FaceRec is */+ /* used to determine both scaling values. */+ /* */+ /* FT_SIZE_REQUEST_TYPE_REAL_DIM :: */+ /* The real dimension. The sum of the the `Ascender' and (minus */+ /* of) the `Descender' fields of @FT_FaceRec are used to determine */+ /* both scaling values. */+ /* */+ /* FT_SIZE_REQUEST_TYPE_BBOX :: */+ /* The font bounding box. The width and height of the `bbox' field */+ /* of @FT_FaceRec are used to determine the horizontal and vertical */+ /* scaling value, respectively. */+ /* */+ /* FT_SIZE_REQUEST_TYPE_CELL :: */+ /* The `max_advance_width' field of @FT_FaceRec is used to */+ /* determine the horizontal scaling value; the vertical scaling */+ /* value is determined the same way as */+ /* @FT_SIZE_REQUEST_TYPE_REAL_DIM does. Finally, both scaling */+ /* values are set to the smaller one. This type is useful if you */+ /* want to specify the font size for, say, a window of a given */+ /* dimension and 80x24 cells. */+ /* */+ /* FT_SIZE_REQUEST_TYPE_SCALES :: */+ /* Specify the scaling values directly. */+ /* */+ /* <Note> */+ /* The above descriptions only apply to scalable formats. For bitmap */+ /* formats, the behaviour is up to the driver. */+ /* */+ /* See the note section of @FT_Size_Metrics if you wonder how size */+ /* requesting relates to scaling values. */+ /* */+ typedef enum FT_Size_Request_Type_+ {+ FT_SIZE_REQUEST_TYPE_NOMINAL,+ FT_SIZE_REQUEST_TYPE_REAL_DIM,+ FT_SIZE_REQUEST_TYPE_BBOX,+ FT_SIZE_REQUEST_TYPE_CELL,+ FT_SIZE_REQUEST_TYPE_SCALES,++ FT_SIZE_REQUEST_TYPE_MAX++ } FT_Size_Request_Type;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_Size_RequestRec */+ /* */+ /* <Description> */+ /* A structure used to model a size request. */+ /* */+ /* <Fields> */+ /* type :: See @FT_Size_Request_Type. */+ /* */+ /* width :: The desired width. */+ /* */+ /* height :: The desired height. */+ /* */+ /* horiResolution :: The horizontal resolution. If set to zero, */+ /* `width' is treated as a 26.6 fractional pixel */+ /* value. */+ /* */+ /* vertResolution :: The vertical resolution. If set to zero, */+ /* `height' is treated as a 26.6 fractional pixel */+ /* value. */+ /* */+ /* <Note> */+ /* If `width' is zero, then the horizontal scaling value is set equal */+ /* to the vertical scaling value, and vice versa. */+ /* */+ typedef struct FT_Size_RequestRec_+ {+ FT_Size_Request_Type type;+ FT_Long width;+ FT_Long height;+ FT_UInt horiResolution;+ FT_UInt vertResolution;++ } FT_Size_RequestRec;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_Size_Request */+ /* */+ /* <Description> */+ /* A handle to a size request structure. */+ /* */+ typedef struct FT_Size_RequestRec_ *FT_Size_Request;+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Request_Size */+ /* */+ /* <Description> */+ /* Resize the scale of the active @FT_Size object in a face. */+ /* */+ /* <InOut> */+ /* face :: A handle to a target face object. */+ /* */+ /* <Input> */+ /* req :: A pointer to a @FT_Size_RequestRec. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* Although drivers may select the bitmap strike matching the */+ /* request, you should not rely on this if you intend to select a */+ /* particular bitmap strike. Use @FT_Select_Size instead in that */+ /* case. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Request_Size( FT_Face face,+ FT_Size_Request req );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Set_Char_Size */+ /* */+ /* <Description> */+ /* This function calls @FT_Request_Size to request the nominal size */+ /* (in points). */+ /* */+ /* <InOut> */+ /* face :: A handle to a target face object. */+ /* */+ /* <Input> */+ /* char_width :: The nominal width, in 26.6 fractional points. */+ /* */+ /* char_height :: The nominal height, in 26.6 fractional points. */+ /* */+ /* horz_resolution :: The horizontal resolution in dpi. */+ /* */+ /* vert_resolution :: The vertical resolution in dpi. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* If either the character width or height is zero, it is set equal */+ /* to the other value. */+ /* */+ /* If either the horizontal or vertical resolution is zero, it is set */+ /* equal to the other value. */+ /* */+ /* A character width or height smaller than 1pt is set to 1pt; if */+ /* both resolution values are zero, they are set to 72dpi. */+ /* */+ /* Don't use this function if you are using the FreeType cache API. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Set_Char_Size( FT_Face face,+ FT_F26Dot6 char_width,+ FT_F26Dot6 char_height,+ FT_UInt horz_resolution,+ FT_UInt vert_resolution );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Set_Pixel_Sizes */+ /* */+ /* <Description> */+ /* This function calls @FT_Request_Size to request the nominal size */+ /* (in pixels). */+ /* */+ /* <InOut> */+ /* face :: A handle to the target face object. */+ /* */+ /* <Input> */+ /* pixel_width :: The nominal width, in pixels. */+ /* */+ /* pixel_height :: The nominal height, in pixels. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Set_Pixel_Sizes( FT_Face face,+ FT_UInt pixel_width,+ FT_UInt pixel_height );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Load_Glyph */+ /* */+ /* <Description> */+ /* A function used to load a single glyph into the glyph slot of a */+ /* face object. */+ /* */+ /* <InOut> */+ /* face :: A handle to the target face object where the glyph */+ /* is loaded. */+ /* */+ /* <Input> */+ /* glyph_index :: The index of the glyph in the font file. For */+ /* CID-keyed fonts (either in PS or in CFF format) */+ /* this argument specifies the CID value. */+ /* */+ /* load_flags :: A flag indicating what to load for this glyph. The */+ /* @FT_LOAD_XXX constants can be used to control the */+ /* glyph loading process (e.g., whether the outline */+ /* should be scaled, whether to load bitmaps or not, */+ /* whether to hint the outline, etc). */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* The loaded glyph may be transformed. See @FT_Set_Transform for */+ /* the details. */+ /* */+ /* For subsetted CID-keyed fonts, `FT_Err_Invalid_Argument' is */+ /* returned for invalid CID values (this is, for CID values which */+ /* don't have a corresponding glyph in the font). See the discussion */+ /* of the @FT_FACE_FLAG_CID_KEYED flag for more details. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Load_Glyph( FT_Face face,+ FT_UInt glyph_index,+ FT_Int32 load_flags );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Load_Char */+ /* */+ /* <Description> */+ /* A function used to load a single glyph into the glyph slot of a */+ /* face object, according to its character code. */+ /* */+ /* <InOut> */+ /* face :: A handle to a target face object where the glyph */+ /* is loaded. */+ /* */+ /* <Input> */+ /* char_code :: The glyph's character code, according to the */+ /* current charmap used in the face. */+ /* */+ /* load_flags :: A flag indicating what to load for this glyph. The */+ /* @FT_LOAD_XXX constants can be used to control the */+ /* glyph loading process (e.g., whether the outline */+ /* should be scaled, whether to load bitmaps or not, */+ /* whether to hint the outline, etc). */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* This function simply calls @FT_Get_Char_Index and @FT_Load_Glyph. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Load_Char( FT_Face face,+ FT_ULong char_code,+ FT_Int32 load_flags );+++ /*************************************************************************+ *+ * @enum:+ * FT_LOAD_XXX+ *+ * @description:+ * A list of bit-field constants used with @FT_Load_Glyph to indicate+ * what kind of operations to perform during glyph loading.+ *+ * @values:+ * FT_LOAD_DEFAULT ::+ * Corresponding to~0, this value is used as the default glyph load+ * operation. In this case, the following happens:+ *+ * 1. FreeType looks for a bitmap for the glyph corresponding to the+ * face's current size. If one is found, the function returns.+ * The bitmap data can be accessed from the glyph slot (see note+ * below).+ *+ * 2. If no embedded bitmap is searched or found, FreeType looks for a+ * scalable outline. If one is found, it is loaded from the font+ * file, scaled to device pixels, then `hinted' to the pixel grid+ * in order to optimize it. The outline data can be accessed from+ * the glyph slot (see note below).+ *+ * Note that by default, the glyph loader doesn't render outlines into+ * bitmaps. The following flags are used to modify this default+ * behaviour to more specific and useful cases.+ *+ * FT_LOAD_NO_SCALE ::+ * Don't scale the outline glyph loaded, but keep it in font units.+ *+ * This flag implies @FT_LOAD_NO_HINTING and @FT_LOAD_NO_BITMAP, and+ * unsets @FT_LOAD_RENDER.+ *+ * FT_LOAD_NO_HINTING ::+ * Disable hinting. This generally generates `blurrier' bitmap glyph+ * when the glyph is rendered in any of the anti-aliased modes. See+ * also the note below.+ *+ * This flag is implied by @FT_LOAD_NO_SCALE.+ *+ * FT_LOAD_RENDER ::+ * Call @FT_Render_Glyph after the glyph is loaded. By default, the+ * glyph is rendered in @FT_RENDER_MODE_NORMAL mode. This can be+ * overridden by @FT_LOAD_TARGET_XXX or @FT_LOAD_MONOCHROME.+ *+ * This flag is unset by @FT_LOAD_NO_SCALE.+ *+ * FT_LOAD_NO_BITMAP ::+ * Ignore bitmap strikes when loading. Bitmap-only fonts ignore this+ * flag.+ *+ * @FT_LOAD_NO_SCALE always sets this flag.+ *+ * FT_LOAD_VERTICAL_LAYOUT ::+ * Load the glyph for vertical text layout. _Don't_ use it as it is+ * problematic currently.+ *+ * FT_LOAD_FORCE_AUTOHINT ::+ * Indicates that the auto-hinter is preferred over the font's native+ * hinter. See also the note below.+ *+ * FT_LOAD_CROP_BITMAP ::+ * Indicates that the font driver should crop the loaded bitmap glyph+ * (i.e., remove all space around its black bits). Not all drivers+ * implement this.+ *+ * FT_LOAD_PEDANTIC ::+ * Indicates that the font driver should perform pedantic verifications+ * during glyph loading. This is mostly used to detect broken glyphs+ * in fonts. By default, FreeType tries to handle broken fonts also.+ *+ * FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ::+ * Indicates that the font driver should ignore the global advance+ * width defined in the font. By default, that value is used as the+ * advance width for all glyphs when the face has+ * @FT_FACE_FLAG_FIXED_WIDTH set.+ *+ * This flag exists for historical reasons (to support buggy CJK+ * fonts).+ *+ * FT_LOAD_NO_RECURSE ::+ * This flag is only used internally. It merely indicates that the+ * font driver should not load composite glyphs recursively. Instead,+ * it should set the `num_subglyph' and `subglyphs' values of the+ * glyph slot accordingly, and set `glyph->format' to+ * @FT_GLYPH_FORMAT_COMPOSITE.+ *+ * The description of sub-glyphs is not available to client+ * applications for now.+ *+ * This flag implies @FT_LOAD_NO_SCALE and @FT_LOAD_IGNORE_TRANSFORM.+ *+ * FT_LOAD_IGNORE_TRANSFORM ::+ * Indicates that the transform matrix set by @FT_Set_Transform should+ * be ignored.+ *+ * FT_LOAD_MONOCHROME ::+ * This flag is used with @FT_LOAD_RENDER to indicate that you want to+ * render an outline glyph to a 1-bit monochrome bitmap glyph, with+ * 8~pixels packed into each byte of the bitmap data.+ *+ * Note that this has no effect on the hinting algorithm used. You+ * should rather use @FT_LOAD_TARGET_MONO so that the+ * monochrome-optimized hinting algorithm is used.+ *+ * FT_LOAD_LINEAR_DESIGN ::+ * Indicates that the `linearHoriAdvance' and `linearVertAdvance'+ * fields of @FT_GlyphSlotRec should be kept in font units. See+ * @FT_GlyphSlotRec for details.+ *+ * FT_LOAD_NO_AUTOHINT ::+ * Disable auto-hinter. See also the note below.+ *+ * @note:+ * By default, hinting is enabled and the font's native hinter (see+ * @FT_FACE_FLAG_HINTER) is preferred over the auto-hinter. You can+ * disable hinting by setting @FT_LOAD_NO_HINTING or change the+ * precedence by setting @FT_LOAD_FORCE_AUTOHINT. You can also set+ * @FT_LOAD_NO_AUTOHINT in case you don't want the auto-hinter to be+ * used at all.+ *+ * See the description of @FT_FACE_FLAG_TRICKY for a special exception+ * (affecting only a handful of Asian fonts).+ *+ * Besides deciding which hinter to use, you can also decide which+ * hinting algorithm to use. See @FT_LOAD_TARGET_XXX for details.+ *+ */+#define FT_LOAD_DEFAULT 0x0+#define FT_LOAD_NO_SCALE 0x1+#define FT_LOAD_NO_HINTING 0x2+#define FT_LOAD_RENDER 0x4+#define FT_LOAD_NO_BITMAP 0x8+#define FT_LOAD_VERTICAL_LAYOUT 0x10+#define FT_LOAD_FORCE_AUTOHINT 0x20+#define FT_LOAD_CROP_BITMAP 0x40+#define FT_LOAD_PEDANTIC 0x80+#define FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH 0x200+#define FT_LOAD_NO_RECURSE 0x400+#define FT_LOAD_IGNORE_TRANSFORM 0x800+#define FT_LOAD_MONOCHROME 0x1000+#define FT_LOAD_LINEAR_DESIGN 0x2000+#define FT_LOAD_NO_AUTOHINT 0x8000U++ /* */++ /* used internally only by certain font drivers! */+#define FT_LOAD_ADVANCE_ONLY 0x100+#define FT_LOAD_SBITS_ONLY 0x4000+++ /**************************************************************************+ *+ * @enum:+ * FT_LOAD_TARGET_XXX+ *+ * @description:+ * A list of values that are used to select a specific hinting algorithm+ * to use by the hinter. You should OR one of these values to your+ * `load_flags' when calling @FT_Load_Glyph.+ *+ * Note that font's native hinters may ignore the hinting algorithm you+ * 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+ * standard gray-level rendering. For monochrome output, use+ * @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.+ *+ * FT_LOAD_TARGET_MONO ::+ * Strong hinting algorithm that should only be used for monochrome+ * output. The result is probably unpleasant if the glyph is rendered+ * in non-monochrome modes.+ *+ * FT_LOAD_TARGET_LCD ::+ * A variant of @FT_LOAD_TARGET_NORMAL optimized for horizontally+ * decimated LCD displays.+ *+ * FT_LOAD_TARGET_LCD_V ::+ * A variant of @FT_LOAD_TARGET_NORMAL optimized for vertically+ * decimated LCD displays.+ *+ * @note:+ * You should use only _one_ of the FT_LOAD_TARGET_XXX values in your+ * `load_flags'. They can't be ORed.+ *+ * If @FT_LOAD_RENDER is also set, the glyph is rendered in the+ * corresponding mode (i.e., the mode which matches the used algorithm+ * best) unless @FT_LOAD_MONOCHROME is set.+ *+ * You can use a hinting algorithm that doesn't correspond to the same+ * rendering mode. As an example, it is possible to use the `light'+ * hinting algorithm and have the results rendered in horizontal LCD+ * pixel mode, with code like+ *+ * {+ * FT_Load_Glyph( face, glyph_index,+ * load_flags | FT_LOAD_TARGET_LIGHT );+ *+ * FT_Render_Glyph( face->glyph, FT_RENDER_MODE_LCD );+ * }+ *+ */+#define FT_LOAD_TARGET_( x ) ( (FT_Int32)( (x) & 15 ) << 16 )++#define FT_LOAD_TARGET_NORMAL FT_LOAD_TARGET_( FT_RENDER_MODE_NORMAL )+#define FT_LOAD_TARGET_LIGHT FT_LOAD_TARGET_( FT_RENDER_MODE_LIGHT )+#define FT_LOAD_TARGET_MONO FT_LOAD_TARGET_( FT_RENDER_MODE_MONO )+#define FT_LOAD_TARGET_LCD FT_LOAD_TARGET_( FT_RENDER_MODE_LCD )+#define FT_LOAD_TARGET_LCD_V FT_LOAD_TARGET_( FT_RENDER_MODE_LCD_V )+++ /**************************************************************************+ *+ * @macro:+ * FT_LOAD_TARGET_MODE+ *+ * @description:+ * Return the @FT_Render_Mode corresponding to a given+ * @FT_LOAD_TARGET_XXX value.+ *+ */+#define FT_LOAD_TARGET_MODE( x ) ( (FT_Render_Mode)( ( (x) >> 16 ) & 15 ) )+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Set_Transform */+ /* */+ /* <Description> */+ /* A function used to set the transformation that is applied to glyph */+ /* images when they are loaded into a glyph slot through */+ /* @FT_Load_Glyph. */+ /* */+ /* <InOut> */+ /* face :: A handle to the source face object. */+ /* */+ /* <Input> */+ /* matrix :: A pointer to the transformation's 2x2 matrix. Use~0 for */+ /* the identity matrix. */+ /* delta :: A pointer to the translation vector. Use~0 for the null */+ /* vector. */+ /* */+ /* <Note> */+ /* The transformation is only applied to scalable image formats after */+ /* the glyph has been loaded. It means that hinting is unaltered by */+ /* the transformation and is performed on the character size given in */+ /* the last call to @FT_Set_Char_Size or @FT_Set_Pixel_Sizes. */+ /* */+ /* Note that this also transforms the `face.glyph.advance' field, but */+ /* *not* the values in `face.glyph.metrics'. */+ /* */+ FT_EXPORT( void )+ FT_Set_Transform( FT_Face face,+ FT_Matrix* matrix,+ FT_Vector* delta );+++ /*************************************************************************/+ /* */+ /* <Enum> */+ /* FT_Render_Mode */+ /* */+ /* <Description> */+ /* An enumeration type that lists the render modes supported by */+ /* FreeType~2. Each mode corresponds to a specific type of scanline */+ /* conversion performed on the outline. */+ /* */+ /* For bitmap fonts and embedded bitmaps the `bitmap->pixel_mode' */+ /* 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. */+ /* */+ /* <Values> */+ /* FT_RENDER_MODE_NORMAL :: */+ /* This is the default render mode; it corresponds to 8-bit */+ /* anti-aliased bitmaps. */+ /* */+ /* FT_RENDER_MODE_LIGHT :: */+ /* This is equivalent to @FT_RENDER_MODE_NORMAL. It is only */+ /* defined as a separate value because render modes are also used */+ /* indirectly to define hinting algorithm selectors. See */+ /* @FT_LOAD_TARGET_XXX for details. */+ /* */+ /* FT_RENDER_MODE_MONO :: */+ /* This mode corresponds to 1-bit bitmaps (with 2~levels of */+ /* opacity). */+ /* */+ /* FT_RENDER_MODE_LCD :: */+ /* This mode corresponds to horizontal RGB and BGR sub-pixel */+ /* displays like LCD screens. It produces 8-bit bitmaps that are */+ /* 3~times the width of the original glyph outline in pixels, and */+ /* which use the @FT_PIXEL_MODE_LCD mode. */+ /* */+ /* FT_RENDER_MODE_LCD_V :: */+ /* This mode corresponds to vertical RGB and BGR sub-pixel displays */+ /* (like PDA screens, rotated LCD displays, etc.). It produces */+ /* 8-bit bitmaps that are 3~times the height of the original */+ /* glyph outline in pixels and use the @FT_PIXEL_MODE_LCD_V mode. */+ /* */+ /* <Note> */+ /* The LCD-optimized glyph bitmaps produced by FT_Render_Glyph can be */+ /* filtered to reduce color-fringes by using @FT_Library_SetLcdFilter */+ /* (not active in the default builds). It is up to the caller to */+ /* either call @FT_Library_SetLcdFilter (if available) or do the */+ /* filtering itself. */+ /* */+ /* The selected render mode only affects vector glyphs of a font. */+ /* Embedded bitmaps often have a different pixel mode like */+ /* @FT_PIXEL_MODE_MONO. You can use @FT_Bitmap_Convert to transform */+ /* them into 8-bit pixmaps. */+ /* */+ typedef enum FT_Render_Mode_+ {+ FT_RENDER_MODE_NORMAL = 0,+ FT_RENDER_MODE_LIGHT,+ FT_RENDER_MODE_MONO,+ FT_RENDER_MODE_LCD,+ FT_RENDER_MODE_LCD_V,++ FT_RENDER_MODE_MAX++ } FT_Render_Mode;+++ /*************************************************************************/+ /* */+ /* <Enum> */+ /* ft_render_mode_xxx */+ /* */+ /* <Description> */+ /* These constants are deprecated. Use the corresponding */+ /* @FT_Render_Mode values instead. */+ /* */+ /* <Values> */+ /* ft_render_mode_normal :: see @FT_RENDER_MODE_NORMAL */+ /* ft_render_mode_mono :: see @FT_RENDER_MODE_MONO */+ /* */+#define ft_render_mode_normal FT_RENDER_MODE_NORMAL+#define ft_render_mode_mono FT_RENDER_MODE_MONO+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Render_Glyph */+ /* */+ /* <Description> */+ /* Convert a given glyph image to a bitmap. It does so by inspecting */+ /* the glyph image format, finding the relevant renderer, and */+ /* invoking it. */+ /* */+ /* <InOut> */+ /* slot :: A handle to the glyph slot containing the image to */+ /* convert. */+ /* */+ /* <Input> */+ /* render_mode :: This is the render mode used to render the glyph */+ /* image into a bitmap. See @FT_Render_Mode for a */+ /* list of possible values. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Render_Glyph( FT_GlyphSlot slot,+ FT_Render_Mode render_mode );+++ /*************************************************************************/+ /* */+ /* <Enum> */+ /* FT_Kerning_Mode */+ /* */+ /* <Description> */+ /* An enumeration used to specify which kerning values to return in */+ /* @FT_Get_Kerning. */+ /* */+ /* <Values> */+ /* FT_KERNING_DEFAULT :: Return scaled and grid-fitted kerning */+ /* distances (value is~0). */+ /* */+ /* FT_KERNING_UNFITTED :: Return scaled but un-grid-fitted kerning */+ /* distances. */+ /* */+ /* FT_KERNING_UNSCALED :: Return the kerning vector in original font */+ /* units. */+ /* */+ typedef enum FT_Kerning_Mode_+ {+ FT_KERNING_DEFAULT = 0,+ FT_KERNING_UNFITTED,+ FT_KERNING_UNSCALED++ } FT_Kerning_Mode;+++ /*************************************************************************/+ /* */+ /* <Const> */+ /* ft_kerning_default */+ /* */+ /* <Description> */+ /* This constant is deprecated. Please use @FT_KERNING_DEFAULT */+ /* instead. */+ /* */+#define ft_kerning_default FT_KERNING_DEFAULT+++ /*************************************************************************/+ /* */+ /* <Const> */+ /* ft_kerning_unfitted */+ /* */+ /* <Description> */+ /* This constant is deprecated. Please use @FT_KERNING_UNFITTED */+ /* instead. */+ /* */+#define ft_kerning_unfitted FT_KERNING_UNFITTED+++ /*************************************************************************/+ /* */+ /* <Const> */+ /* ft_kerning_unscaled */+ /* */+ /* <Description> */+ /* This constant is deprecated. Please use @FT_KERNING_UNSCALED */+ /* instead. */+ /* */+#define ft_kerning_unscaled FT_KERNING_UNSCALED+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Get_Kerning */+ /* */+ /* <Description> */+ /* Return the kerning vector between two glyphs of a same face. */+ /* */+ /* <Input> */+ /* face :: A handle to a source face object. */+ /* */+ /* left_glyph :: The index of the left glyph in the kern pair. */+ /* */+ /* right_glyph :: The index of the right glyph in the kern pair. */+ /* */+ /* kern_mode :: See @FT_Kerning_Mode for more information. */+ /* Determines the scale and dimension of the returned */+ /* 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. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* Only horizontal layouts (left-to-right & right-to-left) are */+ /* supported by this method. Other layouts, or more sophisticated */+ /* kernings, are out of the scope of this API function -- they can be */+ /* implemented through format-specific interfaces. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Get_Kerning( FT_Face face,+ FT_UInt left_glyph,+ FT_UInt right_glyph,+ FT_UInt kern_mode,+ FT_Vector *akerning );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Get_Track_Kerning */+ /* */+ /* <Description> */+ /* Return the track kerning for a given face object at a given size. */+ /* */+ /* <Input> */+ /* face :: A handle to a source face object. */+ /* */+ /* point_size :: The point size in 16.16 fractional points. */+ /* */+ /* degree :: The degree of tightness. */+ /* */+ /* <Output> */+ /* akerning :: The kerning in 16.16 fractional points. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Get_Track_Kerning( FT_Face face,+ FT_Fixed point_size,+ FT_Int degree,+ FT_Fixed* akerning );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Get_Glyph_Name */+ /* */+ /* <Description> */+ /* Retrieve the ASCII name of a given glyph in a face. This only */+ /* works for those faces where @FT_HAS_GLYPH_NAMES(face) returns~1. */+ /* */+ /* <Input> */+ /* face :: A handle to a source face object. */+ /* */+ /* glyph_index :: The glyph index. */+ /* */+ /* buffer_max :: The maximal number of bytes available in the */+ /* buffer. */+ /* */+ /* <Output> */+ /* buffer :: A pointer to a target buffer where the name is */+ /* copied to. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* An error is returned if the face doesn't provide glyph names or if */+ /* the glyph index is invalid. In all cases of failure, the first */+ /* byte of `buffer' is set to~0 to indicate an empty name. */+ /* */+ /* The glyph name is truncated to fit within the buffer if it is too */+ /* long. The returned string is always zero-terminated. */+ /* */+ /* This function is not compiled within the library if the config */+ /* macro `FT_CONFIG_OPTION_NO_GLYPH_NAMES' is defined in */+ /* `include/freetype/config/ftoptions.h'. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Get_Glyph_Name( FT_Face face,+ FT_UInt glyph_index,+ FT_Pointer buffer,+ FT_UInt buffer_max );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Get_Postscript_Name */+ /* */+ /* <Description> */+ /* Retrieve the ASCII PostScript name of a given face, if available. */+ /* This only works with PostScript and TrueType fonts. */+ /* */+ /* <Input> */+ /* face :: A handle to the source face object. */+ /* */+ /* <Return> */+ /* A pointer to the face's PostScript name. NULL if unavailable. */+ /* */+ /* <Note> */+ /* The returned pointer is owned by the face and is destroyed with */+ /* it. */+ /* */+ FT_EXPORT( const char* )+ FT_Get_Postscript_Name( FT_Face face );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Select_Charmap */+ /* */+ /* <Description> */+ /* Select a given charmap by its encoding tag (as listed in */+ /* `freetype.h'). */+ /* */+ /* <InOut> */+ /* face :: A handle to the source face object. */+ /* */+ /* <Input> */+ /* encoding :: A handle to the selected encoding. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* This function returns an error if no charmap in the face */+ /* corresponds to the encoding queried here. */+ /* */+ /* Because many fonts contain more than a single cmap for Unicode */+ /* encoding, this function has some special code to select the one */+ /* which covers Unicode best (`best' in the sense that a UCS-4 cmap */+ /* is preferred to a UCS-2 cmap). It is thus preferable to */+ /* @FT_Set_Charmap in this case. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Select_Charmap( FT_Face face,+ FT_Encoding encoding );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Set_Charmap */+ /* */+ /* <Description> */+ /* Select a given charmap for character code to glyph index mapping. */+ /* */+ /* <InOut> */+ /* face :: A handle to the source face object. */+ /* */+ /* <Input> */+ /* charmap :: A handle to the selected charmap. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* This function returns an error if the charmap is not part of */+ /* the face (i.e., if it is not listed in the `face->charmaps' */+ /* table). */+ /* */+ /* It also fails if a type~14 charmap is selected. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Set_Charmap( FT_Face face,+ FT_CharMap charmap );+++ /*************************************************************************+ *+ * @function:+ * FT_Get_Charmap_Index+ *+ * @description:+ * Retrieve index of a given charmap.+ *+ * @input:+ * charmap ::+ * A handle to a charmap.+ *+ * @return:+ * The index into the array of character maps within the face to which+ * `charmap' belongs. If an error occurs, -1 is returned.+ *+ */+ FT_EXPORT( FT_Int )+ FT_Get_Charmap_Index( FT_CharMap charmap );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Get_Char_Index */+ /* */+ /* <Description> */+ /* Return the glyph index of a given character code. This function */+ /* uses a charmap object to do the mapping. */+ /* */+ /* <Input> */+ /* face :: A handle to the source face object. */+ /* */+ /* charcode :: The character code. */+ /* */+ /* <Return> */+ /* The glyph index. 0~means `undefined character code'. */+ /* */+ /* <Note> */+ /* If you use FreeType to manipulate the contents of font files */+ /* directly, be aware that the glyph index returned by this function */+ /* doesn't always correspond to the internal indices used within */+ /* the file. This is done to ensure that value~0 always corresponds */+ /* to the `missing glyph'. */+ /* */+ FT_EXPORT( FT_UInt )+ FT_Get_Char_Index( FT_Face face,+ FT_ULong charcode );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Get_First_Char */+ /* */+ /* <Description> */+ /* This function is used to return the first character code in the */+ /* current charmap of a given face. It also returns the */+ /* corresponding glyph index. */+ /* */+ /* <Input> */+ /* face :: A handle to the source face object. */+ /* */+ /* <Output> */+ /* agindex :: Glyph index of first character code. 0~if charmap is */+ /* empty. */+ /* */+ /* <Return> */+ /* The charmap's first character code. */+ /* */+ /* <Note> */+ /* You should use this function with @FT_Get_Next_Char to be able to */+ /* parse all character codes available in a given charmap. The code */+ /* should look like this: */+ /* */+ /* { */+ /* FT_ULong charcode; */+ /* FT_UInt gindex; */+ /* */+ /* */+ /* charcode = FT_Get_First_Char( face, &gindex ); */+ /* while ( gindex != 0 ) */+ /* { */+ /* ... do something with (charcode,gindex) pair ... */+ /* */+ /* charcode = FT_Get_Next_Char( face, charcode, &gindex ); */+ /* } */+ /* } */+ /* */+ /* 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. */+ /* */+ FT_EXPORT( FT_ULong )+ FT_Get_First_Char( FT_Face face,+ FT_UInt *agindex );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Get_Next_Char */+ /* */+ /* <Description> */+ /* This function is used to return the next character code in the */+ /* current charmap of a given face following the value `char_code', */+ /* as well as the corresponding glyph index. */+ /* */+ /* <Input> */+ /* face :: A handle to the source face object. */+ /* char_code :: The starting character code. */+ /* */+ /* <Output> */+ /* agindex :: Glyph index of next character code. 0~if charmap */+ /* is empty. */+ /* */+ /* <Return> */+ /* The charmap's next character code. */+ /* */+ /* <Note> */+ /* You should use this function with @FT_Get_First_Char to walk */+ /* over all character codes available in a given charmap. See the */+ /* note for this function for a simple code example. */+ /* */+ /* Note that `*agindex' is set to~0 when there are no more codes in */+ /* the charmap. */+ /* */+ FT_EXPORT( FT_ULong )+ FT_Get_Next_Char( FT_Face face,+ FT_ULong char_code,+ FT_UInt *agindex );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Get_Name_Index */+ /* */+ /* <Description> */+ /* Return the glyph index of a given glyph name. This function uses */+ /* driver specific objects to do the translation. */+ /* */+ /* <Input> */+ /* face :: A handle to the source face object. */+ /* */+ /* glyph_name :: The glyph name. */+ /* */+ /* <Return> */+ /* The glyph index. 0~means `undefined character code'. */+ /* */+ FT_EXPORT( FT_UInt )+ FT_Get_Name_Index( FT_Face face,+ FT_String* glyph_name );+++ /*************************************************************************+ *+ * @macro:+ * FT_SUBGLYPH_FLAG_XXX+ *+ * @description:+ * A list of constants used to describe subglyphs. Please refer to the+ * TrueType specification for the meaning of the various flags.+ *+ * @values:+ * FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS ::+ * FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES ::+ * FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID ::+ * FT_SUBGLYPH_FLAG_SCALE ::+ * FT_SUBGLYPH_FLAG_XY_SCALE ::+ * FT_SUBGLYPH_FLAG_2X2 ::+ * FT_SUBGLYPH_FLAG_USE_MY_METRICS ::+ *+ */+#define FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS 1+#define FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES 2+#define FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID 4+#define FT_SUBGLYPH_FLAG_SCALE 8+#define FT_SUBGLYPH_FLAG_XY_SCALE 0x40+#define FT_SUBGLYPH_FLAG_2X2 0x80+#define FT_SUBGLYPH_FLAG_USE_MY_METRICS 0x200+++ /*************************************************************************+ *+ * @func:+ * FT_Get_SubGlyph_Info+ *+ * @description:+ * Retrieve a description of a given subglyph. Only use it if+ * `glyph->format' is @FT_GLYPH_FORMAT_COMPOSITE; an error is+ * returned otherwise.+ *+ * @input:+ * glyph ::+ * The source glyph slot.+ *+ * sub_index ::+ * The index of the subglyph. Must be less than+ * `glyph->num_subglyphs'.+ *+ * @output:+ * p_index ::+ * The glyph index of the subglyph.+ *+ * p_flags ::+ * The subglyph flags, see @FT_SUBGLYPH_FLAG_XXX.+ *+ * p_arg1 ::+ * The subglyph's first argument (if any).+ *+ * p_arg2 ::+ * The subglyph's second argument (if any).+ *+ * p_transform ::+ * The subglyph transformation (if any).+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * The values of `*p_arg1', `*p_arg2', and `*p_transform' must be+ * interpreted depending on the flags returned in `*p_flags'. See the+ * TrueType specification for details.+ *+ */+ FT_EXPORT( FT_Error )+ FT_Get_SubGlyph_Info( FT_GlyphSlot glyph,+ FT_UInt sub_index,+ FT_Int *p_index,+ FT_UInt *p_flags,+ FT_Int *p_arg1,+ FT_Int *p_arg2,+ FT_Matrix *p_transform );+++ /*************************************************************************/+ /* */+ /* <Enum> */+ /* FT_FSTYPE_XXX */+ /* */+ /* <Description> */+ /* A list of bit flags used in the `fsType' field of the OS/2 table */+ /* in a TrueType or OpenType font and the `FSType' entry in a */+ /* PostScript font. These bit flags are returned by */+ /* @FT_Get_FSType_Flags; they inform client applications of embedding */+ /* and subsetting restrictions associated with a font. */+ /* */+ /* See http://www.adobe.com/devnet/acrobat/pdfs/FontPolicies.pdf for */+ /* more details. */+ /* */+ /* <Values> */+ /* FT_FSTYPE_INSTALLABLE_EMBEDDING :: */+ /* Fonts with no fsType bit set may be embedded and permanently */+ /* installed on the remote system by an application. */+ /* */+ /* FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING :: */+ /* Fonts that have only this bit set must not be modified, embedded */+ /* or exchanged in any manner without first obtaining permission of */+ /* the font software copyright owner. */+ /* */+ /* FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING :: */+ /* If this bit is set, the font may be embedded and temporarily */+ /* loaded on the remote system. Documents containing Preview & */+ /* Print fonts must be opened `read-only'; no edits can be applied */+ /* to the document. */+ /* */+ /* FT_FSTYPE_EDITABLE_EMBEDDING :: */+ /* If this bit is set, the font may be embedded but must only be */+ /* installed temporarily on other systems. In contrast to Preview */+ /* & Print fonts, documents containing editable fonts may be opened */+ /* for reading, editing is permitted, and changes may be saved. */+ /* */+ /* FT_FSTYPE_NO_SUBSETTING :: */+ /* If this bit is set, the font may not be subsetted prior to */+ /* embedding. */+ /* */+ /* FT_FSTYPE_BITMAP_EMBEDDING_ONLY :: */+ /* If this bit is set, only bitmaps contained in the font may be */+ /* embedded; no outline data may be embedded. If there are no */+ /* bitmaps available in the font, then the font is unembeddable. */+ /* */+ /* <Note> */+ /* 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. */+ /* */+#define FT_FSTYPE_INSTALLABLE_EMBEDDING 0x0000+#define FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING 0x0002+#define FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING 0x0004+#define FT_FSTYPE_EDITABLE_EMBEDDING 0x0008+#define FT_FSTYPE_NO_SUBSETTING 0x0100+#define FT_FSTYPE_BITMAP_EMBEDDING_ONLY 0x0200+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Get_FSType_Flags */+ /* */+ /* <Description> */+ /* Return the fsType flags for a font. */+ /* */+ /* <Input> */+ /* face :: A handle to the source face object. */+ /* */+ /* <Return> */+ /* The fsType flags, @FT_FSTYPE_XXX. */+ /* */+ /* <Note> */+ /* Use this function rather than directly reading the `fs_type' field */+ /* in the @PS_FontInfoRec structure which is only guaranteed to */+ /* return the correct results for Type~1 fonts. */+ /* */+ FT_EXPORT( FT_UShort )+ FT_Get_FSType_Flags( FT_Face face );+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* glyph_variants */+ /* */+ /* <Title> */+ /* Glyph Variants */+ /* */+ /* <Abstract> */+ /* The FreeType~2 interface to Unicode Ideographic Variation */+ /* Sequences (IVS), using the SFNT cmap format~14. */+ /* */+ /* <Description> */+ /* Many CJK characters have variant forms. They are a sort of grey */+ /* area somewhere between being totally irrelevant and semantically */+ /* distinct; for this reason, the Unicode consortium decided to */+ /* introduce Ideographic Variation Sequences (IVS), consisting of a */+ /* Unicode base character and one of 240 variant selectors */+ /* (U+E0100-U+E01EF), instead of further extending the already huge */+ /* code range for CJK characters. */+ /* */+ /* An IVS is registered and unique; for further details please refer */+ /* to Unicode Technical Report #37, the Ideographic Variation */+ /* Database. To date (October 2007), the character with the most */+ /* variants is U+908A, having 8~such IVS. */+ /* */+ /* Adobe and MS decided to support IVS with a new cmap subtable */+ /* (format~14). It is an odd subtable because it is not a mapping of */+ /* input code points to glyphs, but contains lists of all variants */+ /* supported by the font. */+ /* */+ /* A variant may be either `default' or `non-default'. A default */+ /* variant is the one you will get for that code point if you look it */+ /* up in the standard Unicode cmap. A non-default variant is a */+ /* different glyph. */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Face_GetCharVariantIndex */+ /* */+ /* <Description> */+ /* Return the glyph index of a given character code as modified by */+ /* the variation selector. */+ /* */+ /* <Input> */+ /* face :: */+ /* A handle to the source face object. */+ /* */+ /* charcode :: */+ /* The character code point in Unicode. */+ /* */+ /* variantSelector :: */+ /* The Unicode code point of the variation selector. */+ /* */+ /* <Return> */+ /* The glyph index. 0~means either `undefined character code', or */+ /* `undefined selector code', or `no variation selector cmap */+ /* subtable', or `current CharMap is not Unicode'. */+ /* */+ /* <Note> */+ /* If you use FreeType to manipulate the contents of font files */+ /* directly, be aware that the glyph index returned by this function */+ /* doesn't always correspond to the internal indices used within */+ /* the file. This is done to ensure that value~0 always corresponds */+ /* to the `missing glyph'. */+ /* */+ /* This function is only meaningful if */+ /* a) the font has a variation selector cmap sub table, */+ /* and */+ /* b) the current charmap has a Unicode encoding. */+ /* */+ /* <Since> */+ /* 2.3.6 */+ /* */+ FT_EXPORT( FT_UInt )+ FT_Face_GetCharVariantIndex( FT_Face face,+ FT_ULong charcode,+ FT_ULong variantSelector );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Face_GetCharVariantIsDefault */+ /* */+ /* <Description> */+ /* Check whether this variant of this Unicode character is the one to */+ /* be found in the `cmap'. */+ /* */+ /* <Input> */+ /* face :: */+ /* A handle to the source face object. */+ /* */+ /* charcode :: */+ /* The character codepoint in Unicode. */+ /* */+ /* variantSelector :: */+ /* The Unicode codepoint of the variation selector. */+ /* */+ /* <Return> */+ /* 1~if found in the standard (Unicode) cmap, 0~if found in the */+ /* variation selector cmap, or -1 if it is not a variant. */+ /* */+ /* <Note> */+ /* This function is only meaningful if the font has a variation */+ /* selector cmap subtable. */+ /* */+ /* <Since> */+ /* 2.3.6 */+ /* */+ FT_EXPORT( FT_Int )+ FT_Face_GetCharVariantIsDefault( FT_Face face,+ FT_ULong charcode,+ FT_ULong variantSelector );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Face_GetVariantSelectors */+ /* */+ /* <Description> */+ /* Return a zero-terminated list of Unicode variant selectors found */+ /* in the font. */+ /* */+ /* <Input> */+ /* face :: */+ /* A handle to the source face object. */+ /* */+ /* <Return> */+ /* A pointer to an array of selector code points, or NULL if there is */+ /* no valid variant selector cmap subtable. */+ /* */+ /* <Note> */+ /* The last item in the array is~0; the array is owned by the */+ /* @FT_Face object but can be overwritten or released on the next */+ /* call to a FreeType function. */+ /* */+ /* <Since> */+ /* 2.3.6 */+ /* */+ FT_EXPORT( FT_UInt32* )+ FT_Face_GetVariantSelectors( FT_Face face );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Face_GetVariantsOfChar */+ /* */+ /* <Description> */+ /* Return a zero-terminated list of Unicode variant selectors found */+ /* for the specified character code. */+ /* */+ /* <Input> */+ /* face :: */+ /* A handle to the source face object. */+ /* */+ /* charcode :: */+ /* The character codepoint in Unicode. */+ /* */+ /* <Return> */+ /* A pointer to an array of variant selector code points which are */+ /* active for the given character, or NULL if the corresponding list */+ /* is empty. */+ /* */+ /* <Note> */+ /* The last item in the array is~0; the array is owned by the */+ /* @FT_Face object but can be overwritten or released on the next */+ /* call to a FreeType function. */+ /* */+ /* <Since> */+ /* 2.3.6 */+ /* */+ FT_EXPORT( FT_UInt32* )+ FT_Face_GetVariantsOfChar( FT_Face face,+ FT_ULong charcode );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Face_GetCharsOfVariant */+ /* */+ /* <Description> */+ /* Return a zero-terminated list of Unicode character codes found for */+ /* the specified variant selector. */+ /* */+ /* <Input> */+ /* face :: */+ /* A handle to the source face object. */+ /* */+ /* variantSelector :: */+ /* The variant selector code point in Unicode. */+ /* */+ /* <Return> */+ /* A list of all the code points which are specified by this selector */+ /* (both default and non-default codes are returned) or NULL if there */+ /* is no valid cmap or the variant selector is invalid. */+ /* */+ /* <Note> */+ /* The last item in the array is~0; the array is owned by the */+ /* @FT_Face object but can be overwritten or released on the next */+ /* call to a FreeType function. */+ /* */+ /* <Since> */+ /* 2.3.6 */+ /* */+ FT_EXPORT( FT_UInt32* )+ FT_Face_GetCharsOfVariant( FT_Face face,+ FT_ULong variantSelector );+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* computations */+ /* */+ /* <Title> */+ /* Computations */+ /* */+ /* <Abstract> */+ /* Crunching fixed numbers and vectors. */+ /* */+ /* <Description> */+ /* This section contains various functions used to perform */+ /* computations on 16.16 fixed-float numbers or 2d vectors. */+ /* */+ /* <Order> */+ /* FT_MulDiv */+ /* FT_MulFix */+ /* FT_DivFix */+ /* FT_RoundFix */+ /* FT_CeilFix */+ /* FT_FloorFix */+ /* FT_Vector_Transform */+ /* FT_Matrix_Multiply */+ /* FT_Matrix_Invert */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_MulDiv */+ /* */+ /* <Description> */+ /* A very simple function used to perform the computation `(a*b)/c' */+ /* with maximal accuracy (it uses a 64-bit intermediate integer */+ /* whenever necessary). */+ /* */+ /* This function isn't necessarily as fast as some processor specific */+ /* operations, but is at least completely portable. */+ /* */+ /* <Input> */+ /* a :: The first multiplier. */+ /* b :: The second multiplier. */+ /* c :: The divisor. */+ /* */+ /* <Return> */+ /* The result of `(a*b)/c'. This function never traps when trying to */+ /* divide by zero; it simply returns `MaxInt' or `MinInt' depending */+ /* on the signs of `a' and `b'. */+ /* */+ FT_EXPORT( FT_Long )+ FT_MulDiv( FT_Long a,+ FT_Long b,+ FT_Long c );+++ /* */++ /* The following #if 0 ... #endif is for the documentation formatter, */+ /* hiding the internal `FT_MULFIX_INLINED' macro. */++#if 0+ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_MulFix */+ /* */+ /* <Description> */+ /* A very simple function used to perform the computation */+ /* `(a*b)/0x10000' with maximal accuracy. Most of the time this is */+ /* used to multiply a given value by a 16.16 fixed float factor. */+ /* */+ /* <Input> */+ /* a :: The first multiplier. */+ /* b :: The second multiplier. Use a 16.16 factor here whenever */+ /* possible (see note below). */+ /* */+ /* <Return> */+ /* The result of `(a*b)/0x10000'. */+ /* */+ /* <Note> */+ /* This function has been optimized for the case where the absolute */+ /* value of `a' is less than 2048, and `b' is a 16.16 scaling factor. */+ /* As this happens mainly when scaling from notional units to */+ /* fractional pixels in FreeType, it resulted in noticeable speed */+ /* improvements between versions 2.x and 1.x. */+ /* */+ /* As a conclusion, always try to place a 16.16 factor as the */+ /* _second_ argument of this function; this can make a great */+ /* difference. */+ /* */+ FT_EXPORT( FT_Long )+ FT_MulFix( FT_Long a,+ FT_Long b );++ /* */+#endif++#ifdef FT_MULFIX_INLINED+#define FT_MulFix( a, b ) FT_MULFIX_INLINED( a, b )+#else+ FT_EXPORT( FT_Long )+ FT_MulFix( FT_Long a,+ FT_Long b );+#endif+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_DivFix */+ /* */+ /* <Description> */+ /* A very simple function used to perform the computation */+ /* `(a*0x10000)/b' with maximal accuracy. Most of the time, this is */+ /* used to divide a given value by a 16.16 fixed float factor. */+ /* */+ /* <Input> */+ /* a :: The first multiplier. */+ /* b :: The second multiplier. Use a 16.16 factor here whenever */+ /* possible (see note below). */+ /* */+ /* <Return> */+ /* The result of `(a*0x10000)/b'. */+ /* */+ /* <Note> */+ /* The optimization for FT_DivFix() is simple: If (a~<<~16) fits in */+ /* 32~bits, then the division is computed directly. Otherwise, we */+ /* use a specialized version of @FT_MulDiv. */+ /* */+ FT_EXPORT( FT_Long )+ FT_DivFix( FT_Long a,+ FT_Long b );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_RoundFix */+ /* */+ /* <Description> */+ /* A very simple function used to round a 16.16 fixed number. */+ /* */+ /* <Input> */+ /* a :: The number to be rounded. */+ /* */+ /* <Return> */+ /* The result of `(a + 0x8000) & -0x10000'. */+ /* */+ FT_EXPORT( FT_Fixed )+ FT_RoundFix( FT_Fixed a );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_CeilFix */+ /* */+ /* <Description> */+ /* A very simple function used to compute the ceiling function of a */+ /* 16.16 fixed number. */+ /* */+ /* <Input> */+ /* a :: The number for which the ceiling function is to be computed. */+ /* */+ /* <Return> */+ /* The result of `(a + 0x10000 - 1) & -0x10000'. */+ /* */+ FT_EXPORT( FT_Fixed )+ FT_CeilFix( FT_Fixed a );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_FloorFix */+ /* */+ /* <Description> */+ /* A very simple function used to compute the floor function of a */+ /* 16.16 fixed number. */+ /* */+ /* <Input> */+ /* a :: The number for which the floor function is to be computed. */+ /* */+ /* <Return> */+ /* The result of `a & -0x10000'. */+ /* */+ FT_EXPORT( FT_Fixed )+ FT_FloorFix( FT_Fixed a );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Vector_Transform */+ /* */+ /* <Description> */+ /* Transform a single vector through a 2x2 matrix. */+ /* */+ /* <InOut> */+ /* vector :: The target vector to transform. */+ /* */+ /* <Input> */+ /* matrix :: A pointer to the source 2x2 matrix. */+ /* */+ /* <Note> */+ /* The result is undefined if either `vector' or `matrix' is invalid. */+ /* */+ FT_EXPORT( void )+ FT_Vector_Transform( FT_Vector* vec,+ const FT_Matrix* matrix );+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* version */+ /* */+ /* <Title> */+ /* FreeType Version */+ /* */+ /* <Abstract> */+ /* Functions and macros related to FreeType versions. */+ /* */+ /* <Description> */+ /* Note that those functions and macros are of limited use because */+ /* even a new release of FreeType with only documentation changes */+ /* increases the version number. */+ /* */+ /*************************************************************************/+++ /*************************************************************************+ *+ * @enum:+ * FREETYPE_XXX+ *+ * @description:+ * These three macros identify the FreeType source code version.+ * Use @FT_Library_Version to access them at runtime.+ *+ * @values:+ * FREETYPE_MAJOR :: The major version number.+ * FREETYPE_MINOR :: The minor version number.+ * FREETYPE_PATCH :: The patch level.+ *+ * @note:+ * The version number of FreeType if built as a dynamic link library+ * with the `libtool' package is _not_ controlled by these three+ * macros.+ *+ */+#define FREETYPE_MAJOR 2+#define FREETYPE_MINOR 4+#define FREETYPE_PATCH 4+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Library_Version */+ /* */+ /* <Description> */+ /* Return the version of the FreeType library being used. This is */+ /* useful when dynamically linking to the library, since one cannot */+ /* use the macros @FREETYPE_MAJOR, @FREETYPE_MINOR, and */+ /* @FREETYPE_PATCH. */+ /* */+ /* <Input> */+ /* library :: A source library handle. */+ /* */+ /* <Output> */+ /* amajor :: The major version number. */+ /* */+ /* aminor :: The minor version number. */+ /* */+ /* apatch :: The patch version number. */+ /* */+ /* <Note> */+ /* The reason why this function takes a `library' argument is because */+ /* certain programs implement library initialization in a custom way */+ /* that doesn't use @FT_Init_FreeType. */+ /* */+ /* In such cases, the library version might not be available before */+ /* the library object has been created. */+ /* */+ FT_EXPORT( void )+ FT_Library_Version( FT_Library library,+ FT_Int *amajor,+ FT_Int *aminor,+ FT_Int *apatch );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Face_CheckTrueTypePatents */+ /* */+ /* <Description> */+ /* Parse all bytecode instructions of a TrueType font file to check */+ /* whether any of the patented opcodes are used. This is only useful */+ /* if you want to be able to use the unpatented hinter with */+ /* fonts that do *not* use these opcodes. */+ /* */+ /* Note that this function parses *all* glyph instructions in the */+ /* font file, which may be slow. */+ /* */+ /* <Input> */+ /* face :: A face handle. */+ /* */+ /* <Return> */+ /* 1~if this is a TrueType font that uses one of the patented */+ /* opcodes, 0~otherwise. */+ /* */+ /* <Note> */+ /* Since May 2010, TrueType hinting is no longer patented. */+ /* */+ /* <Since> */+ /* 2.3.5 */+ /* */+ FT_EXPORT( FT_Bool )+ FT_Face_CheckTrueTypePatents( FT_Face face );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Face_SetUnpatentedHinting */+ /* */+ /* <Description> */+ /* Enable or disable the unpatented hinter for a given face. */+ /* Only enable it if you have determined that the face doesn't */+ /* use any patented opcodes (see @FT_Face_CheckTrueTypePatents). */+ /* */+ /* <Input> */+ /* face :: A face handle. */+ /* */+ /* value :: New boolean setting. */+ /* */+ /* <Return> */+ /* The old setting value. This will always be false if this is not */+ /* an SFNT font, or if the unpatented hinter is not compiled in this */+ /* instance of the library. */+ /* */+ /* <Note> */+ /* Since May 2010, TrueType hinting is no longer patented. */+ /* */+ /* <Since> */+ /* 2.3.5 */+ /* */+ FT_EXPORT( FT_Bool )+ FT_Face_SetUnpatentedHinting( FT_Face face,+ FT_Bool value );++ /* */+++FT_END_HEADER++#endif /* __FREETYPE_H__ */+++/* END */
+ include/freetype/ftadvanc.h view
@@ -0,0 +1,179 @@+/***************************************************************************/+/* */+/* ftadvanc.h */+/* */+/* Quick computation of advance widths (specification only). */+/* */+/* Copyright 2008 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 __FTADVANC_H__+#define __FTADVANC_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+++FT_BEGIN_HEADER+++ /**************************************************************************+ *+ * @section:+ * quick_advance+ *+ * @title:+ * Quick retrieval of advance values+ *+ * @abstract:+ * Retrieve horizontal and vertical advance values without processing+ * glyph outlines, if possible.+ *+ * @description:+ * This section contains functions to quickly extract advance values+ * without handling glyph outlines, if possible.+ */+++ /*************************************************************************/+ /* */+ /* <Const> */+ /* FT_ADVANCE_FLAG_FAST_ONLY */+ /* */+ /* <Description> */+ /* A bit-flag to be OR-ed with the `flags' parameter of the */+ /* @FT_Get_Advance and @FT_Get_Advances functions. */+ /* */+ /* If set, it indicates that you want these functions to fail if the */+ /* corresponding hinting mode or font driver doesn't allow for very */+ /* quick advance computation. */+ /* */+ /* Typically, glyphs which are either unscaled, unhinted, bitmapped, */+ /* or light-hinted can have their advance width computed very */+ /* quickly. */+ /* */+ /* Normal and bytecode hinted modes, which require loading, scaling, */+ /* and hinting of the glyph outline, are extremely slow by */+ /* comparison. */+ /* */+#define FT_ADVANCE_FLAG_FAST_ONLY 0x20000000UL+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Get_Advance */+ /* */+ /* <Description> */+ /* Retrieve the advance value of a given glyph outline in an */+ /* @FT_Face. By default, the unhinted advance is returned in font */+ /* units. */+ /* */+ /* <Input> */+ /* face :: The source @FT_Face handle. */+ /* */+ /* gindex :: The glyph index. */+ /* */+ /* load_flags :: A set of bit flags similar to those used when */+ /* calling @FT_Load_Glyph, used to determine what kind */+ /* of advances you need. */+ /* <Output> */+ /* padvance :: The advance value, in either font units or 16.16 */+ /* format. */+ /* */+ /* If @FT_LOAD_VERTICAL_LAYOUT is set, this is the */+ /* vertical advance corresponding to a vertical layout. */+ /* Otherwise, it is the horizontal advance in a */+ /* horizontal layout. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ /* <Note> */+ /* This function may fail if you use @FT_ADVANCE_FLAG_FAST_ONLY and */+ /* if the corresponding font backend doesn't have a quick way to */+ /* retrieve the advances. */+ /* */+ /* A scaled advance is returned in 16.16 format but isn't transformed */+ /* by the affine transformation specified by @FT_Set_Transform. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Get_Advance( FT_Face face,+ FT_UInt gindex,+ FT_Int32 load_flags,+ FT_Fixed *padvance );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Get_Advances */+ /* */+ /* <Description> */+ /* Retrieve the advance values of several glyph outlines in an */+ /* @FT_Face. By default, the unhinted advances are returned in font */+ /* units. */+ /* */+ /* <Input> */+ /* face :: The source @FT_Face handle. */+ /* */+ /* start :: The first glyph index. */+ /* */+ /* count :: The number of advance values you want to retrieve. */+ /* */+ /* load_flags :: A set of bit flags similar to those used when */+ /* calling @FT_Load_Glyph. */+ /* */+ /* <Output> */+ /* padvance :: The advances, in either font units or 16.16 format. */+ /* This array must contain at least `count' elements. */+ /* */+ /* If @FT_LOAD_VERTICAL_LAYOUT is set, these are the */+ /* vertical advances corresponding to a vertical layout. */+ /* Otherwise, they are the horizontal advances in a */+ /* horizontal layout. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ /* <Note> */+ /* This function may fail if you use @FT_ADVANCE_FLAG_FAST_ONLY and */+ /* if the corresponding font backend doesn't have a quick way to */+ /* retrieve the advances. */+ /* */+ /* Scaled advances are returned in 16.16 format but aren't */+ /* transformed by the affine transformation specified by */+ /* @FT_Set_Transform. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Get_Advances( FT_Face face,+ FT_UInt start,+ FT_UInt count,+ FT_Int32 load_flags,+ FT_Fixed *padvances );++/* */+++FT_END_HEADER++#endif /* __FTADVANC_H__ */+++/* END */
+ include/freetype/ftbbox.h view
@@ -0,0 +1,94 @@+/***************************************************************************/+/* */+/* ftbbox.h */+/* */+/* FreeType exact bbox computation (specification). */+/* */+/* Copyright 1996-2001, 2003, 2007 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++ /*************************************************************************/+ /* */+ /* This component has a _single_ role: to compute exact outline bounding */+ /* boxes. */+ /* */+ /* It is separated from the rest of the engine for various technical */+ /* reasons. It may well be integrated in `ftoutln' later. */+ /* */+ /*************************************************************************/+++#ifndef __FTBBOX_H__+#define __FTBBOX_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+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* outline_processing */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Outline_Get_BBox */+ /* */+ /* <Description> */+ /* Compute the exact bounding box of an outline. This is slower */+ /* than computing the control box. However, it uses an advanced */+ /* algorithm which returns _very_ quickly when the two boxes */+ /* coincide. Otherwise, the outline Bézier arcs are traversed to */+ /* extract their extrema. */+ /* */+ /* <Input> */+ /* outline :: A pointer to the source outline. */+ /* */+ /* <Output> */+ /* abbox :: The outline's exact bounding box. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Outline_Get_BBox( FT_Outline* outline,+ FT_BBox *abbox );+++ /* */+++FT_END_HEADER++#endif /* __FTBBOX_H__ */+++/* END */+++/* Local Variables: */+/* coding: utf-8 */+/* End: */
+ include/freetype/ftbdf.h view
@@ -0,0 +1,209 @@+/***************************************************************************/+/* */+/* ftbdf.h */+/* */+/* FreeType API for accessing BDF-specific strings (specification). */+/* */+/* Copyright 2002, 2003, 2004, 2006, 2009 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 __FTBDF_H__+#define __FTBDF_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+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* bdf_fonts */+ /* */+ /* <Title> */+ /* BDF and PCF Files */+ /* */+ /* <Abstract> */+ /* BDF and PCF specific API. */+ /* */+ /* <Description> */+ /* This section contains the declaration of functions specific to BDF */+ /* and PCF fonts. */+ /* */+ /*************************************************************************/+++ /**********************************************************************+ *+ * @enum:+ * FT_PropertyType+ *+ * @description:+ * A list of BDF property types.+ *+ * @values:+ * BDF_PROPERTY_TYPE_NONE ::+ * Value~0 is used to indicate a missing property.+ *+ * BDF_PROPERTY_TYPE_ATOM ::+ * Property is a string atom.+ *+ * BDF_PROPERTY_TYPE_INTEGER ::+ * Property is a 32-bit signed integer.+ *+ * BDF_PROPERTY_TYPE_CARDINAL ::+ * Property is a 32-bit unsigned integer.+ */+ typedef enum BDF_PropertyType_+ {+ BDF_PROPERTY_TYPE_NONE = 0,+ BDF_PROPERTY_TYPE_ATOM = 1,+ BDF_PROPERTY_TYPE_INTEGER = 2,+ BDF_PROPERTY_TYPE_CARDINAL = 3++ } BDF_PropertyType;+++ /**********************************************************************+ *+ * @type:+ * BDF_Property+ *+ * @description:+ * A handle to a @BDF_PropertyRec structure to model a given+ * BDF/PCF property.+ */+ typedef struct BDF_PropertyRec_* BDF_Property;+++ /**********************************************************************+ *+ * @struct:+ * BDF_PropertyRec+ *+ * @description:+ * This structure models a given BDF/PCF property.+ *+ * @fields:+ * type ::+ * The property type.+ *+ * u.atom ::+ * The atom string, if type is @BDF_PROPERTY_TYPE_ATOM.+ *+ * u.integer ::+ * A signed integer, if type is @BDF_PROPERTY_TYPE_INTEGER.+ *+ * u.cardinal ::+ * An unsigned integer, if type is @BDF_PROPERTY_TYPE_CARDINAL.+ */+ typedef struct BDF_PropertyRec_+ {+ BDF_PropertyType type;+ union {+ const char* atom;+ FT_Int32 integer;+ FT_UInt32 cardinal;++ } u;++ } BDF_PropertyRec;+++ /**********************************************************************+ *+ * @function:+ * FT_Get_BDF_Charset_ID+ *+ * @description:+ * Retrieve a BDF font character set identity, according to+ * the BDF specification.+ *+ * @input:+ * face ::+ * A handle to the input face.+ *+ * @output:+ * acharset_encoding ::+ * Charset encoding, as a C~string, owned by the face.+ *+ * acharset_registry ::+ * Charset registry, as a C~string, owned by the face.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * This function only works with BDF faces, returning an error otherwise.+ */+ FT_EXPORT( FT_Error )+ FT_Get_BDF_Charset_ID( FT_Face face,+ const char* *acharset_encoding,+ const char* *acharset_registry );+++ /**********************************************************************+ *+ * @function:+ * FT_Get_BDF_Property+ *+ * @description:+ * Retrieve a BDF property from a BDF or PCF font file.+ *+ * @input:+ * face :: A handle to the input face.+ *+ * name :: The property name.+ *+ * @output:+ * aproperty :: The property.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * This function works with BDF _and_ PCF fonts. It returns an error+ * otherwise. It also returns an error if the property is not in the+ * font.+ *+ * A `property' is a either key-value pair within the STARTPROPERTIES+ * ... ENDPROPERTIES block of a BDF font or a key-value pair from the+ * `info->props' array within a `FontRec' structure of a PCF font.+ *+ * Integer properties are always stored as `signed' within PCF fonts;+ * consequently, @BDF_PROPERTY_TYPE_CARDINAL is a possible return value+ * for BDF fonts only.+ *+ * In case of error, `aproperty->type' is always set to+ * @BDF_PROPERTY_TYPE_NONE.+ */+ FT_EXPORT( FT_Error )+ FT_Get_BDF_Property( FT_Face face,+ const char* prop_name,+ BDF_PropertyRec *aproperty );++ /* */++FT_END_HEADER++#endif /* __FTBDF_H__ */+++/* END */
+ include/freetype/ftbitmap.h view
@@ -0,0 +1,227 @@+/***************************************************************************/+/* */+/* ftbitmap.h */+/* */+/* FreeType utility functions for bitmaps (specification). */+/* */+/* Copyright 2004, 2005, 2006, 2008 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 __FTBITMAP_H__+#define __FTBITMAP_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+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* bitmap_handling */+ /* */+ /* <Title> */+ /* Bitmap Handling */+ /* */+ /* <Abstract> */+ /* Handling FT_Bitmap objects. */+ /* */+ /* <Description> */+ /* This section contains functions for converting FT_Bitmap objects. */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Bitmap_New */+ /* */+ /* <Description> */+ /* Initialize a pointer to an @FT_Bitmap structure. */+ /* */+ /* <InOut> */+ /* abitmap :: A pointer to the bitmap structure. */+ /* */+ FT_EXPORT( void )+ FT_Bitmap_New( FT_Bitmap *abitmap );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Bitmap_Copy */+ /* */+ /* <Description> */+ /* Copy a bitmap into another one. */+ /* */+ /* <Input> */+ /* library :: A handle to a library object. */+ /* */+ /* source :: A handle to the source bitmap. */+ /* */+ /* <Output> */+ /* target :: A handle to the target bitmap. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Bitmap_Copy( FT_Library library,+ const FT_Bitmap *source,+ FT_Bitmap *target);+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Bitmap_Embolden */+ /* */+ /* <Description> */+ /* Embolden a bitmap. The new bitmap will be about `xStrength' */+ /* pixels wider and `yStrength' pixels higher. The left and bottom */+ /* borders are kept unchanged. */+ /* */+ /* <Input> */+ /* library :: A handle to a library object. */+ /* */+ /* xStrength :: How strong the glyph is emboldened horizontally. */+ /* Expressed in 26.6 pixel format. */+ /* */+ /* yStrength :: How strong the glyph is emboldened vertically. */+ /* Expressed in 26.6 pixel format. */+ /* */+ /* <InOut> */+ /* bitmap :: A handle to the target bitmap. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* The current implementation restricts `xStrength' to be less than */+ /* or equal to~8 if bitmap is of pixel_mode @FT_PIXEL_MODE_MONO. */+ /* */+ /* If you want to embolden the bitmap owned by a @FT_GlyphSlotRec, */+ /* you should call @FT_GlyphSlot_Own_Bitmap on the slot first. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Bitmap_Embolden( FT_Library library,+ FT_Bitmap* bitmap,+ FT_Pos xStrength,+ FT_Pos yStrength );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Bitmap_Convert */+ /* */+ /* <Description> */+ /* Convert a bitmap object with depth 1bpp, 2bpp, 4bpp, or 8bpp to a */+ /* bitmap object with depth 8bpp, making the number of used bytes per */+ /* line (a.k.a. the `pitch') a multiple of `alignment'. */+ /* */+ /* <Input> */+ /* library :: A handle to a library object. */+ /* */+ /* source :: The source bitmap. */+ /* */+ /* alignment :: The pitch of the bitmap is a multiple of this */+ /* parameter. Common values are 1, 2, or 4. */+ /* */+ /* <Output> */+ /* target :: The target bitmap. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* It is possible to call @FT_Bitmap_Convert multiple times without */+ /* calling @FT_Bitmap_Done (the memory is simply reallocated). */+ /* */+ /* Use @FT_Bitmap_Done to finally remove the bitmap object. */+ /* */+ /* The `library' argument is taken to have access to FreeType's */+ /* memory handling functions. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Bitmap_Convert( FT_Library library,+ const FT_Bitmap *source,+ FT_Bitmap *target,+ FT_Int alignment );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_GlyphSlot_Own_Bitmap */+ /* */+ /* <Description> */+ /* Make sure that a glyph slot owns `slot->bitmap'. */+ /* */+ /* <Input> */+ /* slot :: The glyph slot. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* This function is to be used in combination with */+ /* @FT_Bitmap_Embolden. */+ /* */+ FT_EXPORT( FT_Error )+ FT_GlyphSlot_Own_Bitmap( FT_GlyphSlot slot );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Bitmap_Done */+ /* */+ /* <Description> */+ /* Destroy a bitmap object created with @FT_Bitmap_New. */+ /* */+ /* <Input> */+ /* library :: A handle to a library object. */+ /* */+ /* bitmap :: The bitmap object to be freed. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* The `library' argument is taken to have access to FreeType's */+ /* memory handling functions. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Bitmap_Done( FT_Library library,+ FT_Bitmap *bitmap );+++ /* */+++FT_END_HEADER++#endif /* __FTBITMAP_H__ */+++/* END */
+ include/freetype/ftcache.h view
@@ -0,0 +1,1140 @@+/***************************************************************************/+/* */+/* ftcache.h */+/* */+/* FreeType Cache subsystem (specification). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 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 __FTCACHE_H__+#define __FTCACHE_H__+++#include <ft2build.h>+#include FT_GLYPH_H+++FT_BEGIN_HEADER+++ /*************************************************************************+ *+ * <Section>+ * cache_subsystem+ *+ * <Title>+ * Cache Sub-System+ *+ * <Abstract>+ * How to cache face, size, and glyph data with FreeType~2.+ *+ * <Description>+ * This section describes the FreeType~2 cache sub-system, which is used+ * to limit the number of concurrently opened @FT_Face and @FT_Size+ * objects, as well as caching information like character maps and glyph+ * images while limiting their maximum memory usage.+ *+ * Note that all types and functions begin with the `FTC_' prefix.+ *+ * The cache is highly portable and thus doesn't know anything about the+ * fonts installed on your system, or how to access them. This implies+ * the following scheme:+ *+ * First, available or installed font faces are uniquely identified by+ * @FTC_FaceID values, provided to the cache by the client. Note that+ * the cache only stores and compares these values, and doesn't try to+ * interpret them in any way.+ *+ * Second, the cache calls, only when needed, a client-provided function+ * to convert an @FTC_FaceID into a new @FT_Face object. The latter is+ * then completely managed by the cache, including its termination+ * through @FT_Done_Face. To monitor termination of face objects, the+ * finalizer callback in the `generic' field of the @FT_Face object can+ * be used, which might also be used to store the @FTC_FaceID of the+ * face.+ *+ * Clients are free to map face IDs to anything else. The most simple+ * usage is to associate them to a (pathname,face_index) pair that is+ * used to call @FT_New_Face. However, more complex schemes are also+ * possible.+ *+ * Note that for the cache to work correctly, the face ID values must be+ * *persistent*, which means that the contents they point to should not+ * change at runtime, or that their value should not become invalid.+ *+ * If this is unavoidable (e.g., when a font is uninstalled at runtime),+ * you should call @FTC_Manager_RemoveFaceID as soon as possible, to let+ * the cache get rid of any references to the old @FTC_FaceID it may+ * keep internally. Failure to do so will lead to incorrect behaviour+ * or even crashes.+ *+ * To use the cache, start with calling @FTC_Manager_New to create a new+ * @FTC_Manager object, which models a single cache instance. You can+ * then look up @FT_Face and @FT_Size objects with+ * @FTC_Manager_LookupFace and @FTC_Manager_LookupSize, respectively.+ *+ * If you want to use the charmap caching, call @FTC_CMapCache_New, then+ * later use @FTC_CMapCache_Lookup to perform the equivalent of+ * @FT_Get_Char_Index, only much faster.+ *+ * If you want to use the @FT_Glyph caching, call @FTC_ImageCache, then+ * later use @FTC_ImageCache_Lookup to retrieve the corresponding+ * @FT_Glyph objects from the cache.+ *+ * If you need lots of small bitmaps, it is much more memory efficient+ * to call @FTC_SBitCache_New followed by @FTC_SBitCache_Lookup. This+ * returns @FTC_SBitRec structures, which are used to store small+ * bitmaps directly. (A small bitmap is one whose metrics and+ * dimensions all fit into 8-bit integers).+ *+ * We hope to also provide a kerning cache in the near future.+ *+ *+ * <Order>+ * FTC_Manager+ * FTC_FaceID+ * FTC_Face_Requester+ *+ * FTC_Manager_New+ * FTC_Manager_Reset+ * FTC_Manager_Done+ * FTC_Manager_LookupFace+ * FTC_Manager_LookupSize+ * FTC_Manager_RemoveFaceID+ *+ * FTC_Node+ * FTC_Node_Unref+ *+ * FTC_ImageCache+ * FTC_ImageCache_New+ * FTC_ImageCache_Lookup+ *+ * FTC_SBit+ * FTC_SBitCache+ * FTC_SBitCache_New+ * FTC_SBitCache_Lookup+ *+ * FTC_CMapCache+ * FTC_CMapCache_New+ * FTC_CMapCache_Lookup+ *+ *************************************************************************/+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** BASIC TYPE DEFINITIONS *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ /*************************************************************************+ *+ * @type: FTC_FaceID+ *+ * @description:+ * An opaque pointer type that is used to identity face objects. The+ * contents of such objects is application-dependent.+ *+ * These pointers are typically used to point to a user-defined+ * structure containing a font file path, and face index.+ *+ * @note:+ * Never use NULL as a valid @FTC_FaceID.+ *+ * Face IDs are passed by the client to the cache manager, which calls,+ * when needed, the @FTC_Face_Requester to translate them into new+ * @FT_Face objects.+ *+ * If the content of a given face ID changes at runtime, or if the value+ * becomes invalid (e.g., when uninstalling a font), you should+ * immediately call @FTC_Manager_RemoveFaceID before any other cache+ * function.+ *+ * Failure to do so will result in incorrect behaviour or even+ * memory leaks and crashes.+ */+ typedef FT_Pointer FTC_FaceID;+++ /************************************************************************+ *+ * @functype:+ * FTC_Face_Requester+ *+ * @description:+ * A callback function provided by client applications. It is used by+ * the cache manager to translate a given @FTC_FaceID into a new valid+ * @FT_Face object, on demand.+ *+ * <Input>+ * face_id ::+ * The face ID to resolve.+ *+ * library ::+ * A handle to a FreeType library object.+ *+ * req_data ::+ * Application-provided request data (see note below).+ *+ * <Output>+ * aface ::+ * A new @FT_Face handle.+ *+ * <Return>+ * FreeType error code. 0~means success.+ *+ * <Note>+ * The third parameter `req_data' is the same as the one passed by the+ * client when @FTC_Manager_New is called.+ *+ * The face requester should not perform funny things on the returned+ * face object, like creating a new @FT_Size for it, or setting a+ * transformation through @FT_Set_Transform!+ */+ typedef FT_Error+ (*FTC_Face_Requester)( FTC_FaceID face_id,+ FT_Library library,+ FT_Pointer request_data,+ FT_Face* aface );++ /* */++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS++ /* these macros are incompatible with LLP64, should not be used */++#define FT_POINTER_TO_ULONG( p ) ( (FT_ULong)(FT_Pointer)(p) )++#define FTC_FACE_ID_HASH( i ) \+ ((FT_UInt32)(( FT_POINTER_TO_ULONG( i ) >> 3 ) ^ \+ ( FT_POINTER_TO_ULONG( i ) << 7 ) ) )++#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** CACHE MANAGER OBJECT *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FTC_Manager */+ /* */+ /* <Description> */+ /* This object corresponds to one instance of the cache-subsystem. */+ /* It is used to cache one or more @FT_Face objects, along with */+ /* corresponding @FT_Size objects. */+ /* */+ /* The manager intentionally limits the total number of opened */+ /* @FT_Face and @FT_Size objects to control memory usage. See the */+ /* `max_faces' and `max_sizes' parameters of @FTC_Manager_New. */+ /* */+ /* The manager is also used to cache `nodes' of various types while */+ /* limiting their total memory usage. */+ /* */+ /* All limitations are enforced by keeping lists of managed objects */+ /* in most-recently-used order, and flushing old nodes to make room */+ /* for new ones. */+ /* */+ typedef struct FTC_ManagerRec_* FTC_Manager;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FTC_Node */+ /* */+ /* <Description> */+ /* An opaque handle to a cache node object. Each cache node is */+ /* reference-counted. A node with a count of~0 might be flushed */+ /* out of a full cache whenever a lookup request is performed. */+ /* */+ /* If you look up nodes, you have the ability to `acquire' them, */+ /* i.e., to increment their reference count. This will prevent the */+ /* node from being flushed out of the cache until you explicitly */+ /* `release' it (see @FTC_Node_Unref). */+ /* */+ /* See also @FTC_SBitCache_Lookup and @FTC_ImageCache_Lookup. */+ /* */+ typedef struct FTC_NodeRec_* FTC_Node;+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FTC_Manager_New */+ /* */+ /* <Description> */+ /* Create a new cache manager. */+ /* */+ /* <Input> */+ /* library :: The parent FreeType library handle to use. */+ /* */+ /* max_faces :: Maximum number of opened @FT_Face objects managed by */+ /* this cache instance. Use~0 for defaults. */+ /* */+ /* max_sizes :: Maximum number of opened @FT_Size objects managed by */+ /* this cache instance. Use~0 for defaults. */+ /* */+ /* max_bytes :: Maximum number of bytes to use for cached data nodes. */+ /* Use~0 for defaults. Note that this value does not */+ /* account for managed @FT_Face and @FT_Size objects. */+ /* */+ /* requester :: An application-provided callback used to translate */+ /* face IDs into real @FT_Face objects. */+ /* */+ /* req_data :: A generic pointer that is passed to the requester */+ /* each time it is called (see @FTC_Face_Requester). */+ /* */+ /* <Output> */+ /* amanager :: A handle to a new manager object. 0~in case of */+ /* failure. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ FT_EXPORT( 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 );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FTC_Manager_Reset */+ /* */+ /* <Description> */+ /* Empty a given cache manager. This simply gets rid of all the */+ /* currently cached @FT_Face and @FT_Size objects within the manager. */+ /* */+ /* <InOut> */+ /* manager :: A handle to the manager. */+ /* */+ FT_EXPORT( void )+ FTC_Manager_Reset( FTC_Manager manager );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FTC_Manager_Done */+ /* */+ /* <Description> */+ /* Destroy a given manager after emptying it. */+ /* */+ /* <Input> */+ /* manager :: A handle to the target cache manager object. */+ /* */+ FT_EXPORT( void )+ FTC_Manager_Done( FTC_Manager manager );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FTC_Manager_LookupFace */+ /* */+ /* <Description> */+ /* Retrieve the @FT_Face object that corresponds to a given face ID */+ /* through a cache manager. */+ /* */+ /* <Input> */+ /* manager :: A handle to the cache manager. */+ /* */+ /* face_id :: The ID of the face object. */+ /* */+ /* <Output> */+ /* aface :: A handle to the face object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* The returned @FT_Face object is always owned by the manager. You */+ /* should never try to discard it yourself. */+ /* */+ /* The @FT_Face object doesn't necessarily have a current size object */+ /* (i.e., face->size can be 0). If you need a specific `font size', */+ /* use @FTC_Manager_LookupSize instead. */+ /* */+ /* Never change the face's transformation matrix (i.e., never call */+ /* the @FT_Set_Transform function) on a returned face! If you need */+ /* to transform glyphs, do it yourself after glyph loading. */+ /* */+ /* When you perform a lookup, out-of-memory errors are detected */+ /* _within_ the lookup and force incremental flushes of the cache */+ /* until enough memory is released for the lookup to succeed. */+ /* */+ /* If a lookup fails with `FT_Err_Out_Of_Memory' the cache has */+ /* already been completely flushed, and still no memory was available */+ /* for the operation. */+ /* */+ FT_EXPORT( FT_Error )+ FTC_Manager_LookupFace( FTC_Manager manager,+ FTC_FaceID face_id,+ FT_Face *aface );+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FTC_ScalerRec */+ /* */+ /* <Description> */+ /* A structure used to describe a given character size in either */+ /* pixels or points to the cache manager. See */+ /* @FTC_Manager_LookupSize. */+ /* */+ /* <Fields> */+ /* face_id :: The source face ID. */+ /* */+ /* width :: The character width. */+ /* */+ /* height :: The character height. */+ /* */+ /* pixel :: A Boolean. If 1, the `width' and `height' fields are */+ /* interpreted as integer pixel character sizes. */+ /* Otherwise, they are expressed as 1/64th of points. */+ /* */+ /* x_res :: Only used when `pixel' is value~0 to indicate the */+ /* horizontal resolution in dpi. */+ /* */+ /* y_res :: Only used when `pixel' is value~0 to indicate the */+ /* vertical resolution in dpi. */+ /* */+ /* <Note> */+ /* This type is mainly used to retrieve @FT_Size objects through the */+ /* cache manager. */+ /* */+ typedef struct FTC_ScalerRec_+ {+ FTC_FaceID face_id;+ FT_UInt width;+ FT_UInt height;+ FT_Int pixel;+ FT_UInt x_res;+ FT_UInt y_res;++ } FTC_ScalerRec;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FTC_Scaler */+ /* */+ /* <Description> */+ /* A handle to an @FTC_ScalerRec structure. */+ /* */+ typedef struct FTC_ScalerRec_* FTC_Scaler;+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FTC_Manager_LookupSize */+ /* */+ /* <Description> */+ /* Retrieve the @FT_Size object that corresponds to a given */+ /* @FTC_ScalerRec pointer through a cache manager. */+ /* */+ /* <Input> */+ /* manager :: A handle to the cache manager. */+ /* */+ /* scaler :: A scaler handle. */+ /* */+ /* <Output> */+ /* asize :: A handle to the size object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* The returned @FT_Size object is always owned by the manager. You */+ /* should never try to discard it by yourself. */+ /* */+ /* You can access the parent @FT_Face object simply as `size->face' */+ /* if you need it. Note that this object is also owned by the */+ /* manager. */+ /* */+ /* <Note> */+ /* When you perform a lookup, out-of-memory errors are detected */+ /* _within_ the lookup and force incremental flushes of the cache */+ /* until enough memory is released for the lookup to succeed. */+ /* */+ /* If a lookup fails with `FT_Err_Out_Of_Memory' the cache has */+ /* already been completely flushed, and still no memory is available */+ /* for the operation. */+ /* */+ FT_EXPORT( FT_Error )+ FTC_Manager_LookupSize( FTC_Manager manager,+ FTC_Scaler scaler,+ FT_Size *asize );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FTC_Node_Unref */+ /* */+ /* <Description> */+ /* Decrement a cache node's internal reference count. When the count */+ /* reaches 0, it is not destroyed but becomes eligible for subsequent */+ /* cache flushes. */+ /* */+ /* <Input> */+ /* node :: The cache node handle. */+ /* */+ /* manager :: The cache manager handle. */+ /* */+ FT_EXPORT( void )+ FTC_Node_Unref( FTC_Node node,+ FTC_Manager manager );+++ /*************************************************************************+ *+ * @function:+ * FTC_Manager_RemoveFaceID+ *+ * @description:+ * A special function used to indicate to the cache manager that+ * a given @FTC_FaceID is no longer valid, either because its+ * content changed, or because it was deallocated or uninstalled.+ *+ * @input:+ * manager ::+ * The cache manager handle.+ *+ * face_id ::+ * The @FTC_FaceID to be removed.+ *+ * @note:+ * This function flushes all nodes from the cache corresponding to this+ * `face_id', with the exception of nodes with a non-null reference+ * count.+ *+ * Such nodes are however modified internally so as to never appear+ * in later lookups with the same `face_id' value, and to be immediately+ * destroyed when released by all their users.+ *+ */+ FT_EXPORT( void )+ FTC_Manager_RemoveFaceID( FTC_Manager manager,+ FTC_FaceID face_id );+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* cache_subsystem */+ /* */+ /*************************************************************************/++ /*************************************************************************+ *+ * @type:+ * FTC_CMapCache+ *+ * @description:+ * An opaque handle used to model a charmap cache. This cache is to+ * hold character codes -> glyph indices mappings.+ *+ */+ typedef struct FTC_CMapCacheRec_* FTC_CMapCache;+++ /*************************************************************************+ *+ * @function:+ * FTC_CMapCache_New+ *+ * @description:+ * Create a new charmap cache.+ *+ * @input:+ * manager ::+ * A handle to the cache manager.+ *+ * @output:+ * acache ::+ * A new cache handle. NULL in case of error.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * Like all other caches, this one will be destroyed with the cache+ * manager.+ *+ */+ FT_EXPORT( FT_Error )+ FTC_CMapCache_New( FTC_Manager manager,+ FTC_CMapCache *acache );+++ /************************************************************************+ *+ * @function:+ * FTC_CMapCache_Lookup+ *+ * @description:+ * Translate a character code into a glyph index, using the charmap+ * cache.+ *+ * @input:+ * cache ::+ * A charmap cache handle.+ *+ * face_id ::+ * The source face ID.+ *+ * cmap_index ::+ * The index of the charmap in the source face. Any negative value+ * means to use the cache @FT_Face's default charmap.+ *+ * char_code ::+ * The character code (in the corresponding charmap).+ *+ * @return:+ * Glyph index. 0~means `no glyph'.+ *+ */+ FT_EXPORT( FT_UInt )+ FTC_CMapCache_Lookup( FTC_CMapCache cache,+ FTC_FaceID face_id,+ FT_Int cmap_index,+ FT_UInt32 char_code );+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* cache_subsystem */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** IMAGE CACHE OBJECT *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ /*************************************************************************+ *+ * @struct:+ * FTC_ImageTypeRec+ *+ * @description:+ * A structure used to model the type of images in a glyph cache.+ *+ * @fields:+ * face_id ::+ * The face ID.+ *+ * width ::+ * The width in pixels.+ *+ * height ::+ * The height in pixels.+ *+ * flags ::+ * The load flags, as in @FT_Load_Glyph.+ *+ */+ typedef struct FTC_ImageTypeRec_+ {+ FTC_FaceID face_id;+ FT_Int width;+ FT_Int height;+ FT_Int32 flags;++ } FTC_ImageTypeRec;+++ /*************************************************************************+ *+ * @type:+ * FTC_ImageType+ *+ * @description:+ * A handle to an @FTC_ImageTypeRec structure.+ *+ */+ typedef struct FTC_ImageTypeRec_* FTC_ImageType;+++ /* */+++#define FTC_IMAGE_TYPE_COMPARE( d1, d2 ) \+ ( (d1)->face_id == (d2)->face_id && \+ (d1)->width == (d2)->width && \+ (d1)->flags == (d2)->flags )++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS++ /* this macro is incompatible with LLP64, should not be used */++#define FTC_IMAGE_TYPE_HASH( d ) \+ (FT_UFast)( FTC_FACE_ID_HASH( (d)->face_id ) ^ \+ ( (d)->width << 8 ) ^ (d)->height ^ \+ ( (d)->flags << 4 ) )++#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FTC_ImageCache */+ /* */+ /* <Description> */+ /* A handle to an glyph image cache object. They are designed to */+ /* hold many distinct glyph images while not exceeding a certain */+ /* memory threshold. */+ /* */+ typedef struct FTC_ImageCacheRec_* FTC_ImageCache;+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FTC_ImageCache_New */+ /* */+ /* <Description> */+ /* Create a new glyph image cache. */+ /* */+ /* <Input> */+ /* manager :: The parent manager for the image cache. */+ /* */+ /* <Output> */+ /* acache :: A handle to the new glyph image cache object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ FT_EXPORT( FT_Error )+ FTC_ImageCache_New( FTC_Manager manager,+ FTC_ImageCache *acache );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FTC_ImageCache_Lookup */+ /* */+ /* <Description> */+ /* Retrieve a given glyph image from a glyph image cache. */+ /* */+ /* <Input> */+ /* cache :: A handle to the source glyph image cache. */+ /* */+ /* type :: A pointer to a glyph image type descriptor. */+ /* */+ /* gindex :: The glyph index to retrieve. */+ /* */+ /* <Output> */+ /* aglyph :: The corresponding @FT_Glyph object. 0~in case of */+ /* failure. */+ /* */+ /* anode :: Used to return the address of of the corresponding cache */+ /* node after incrementing its reference count (see note */+ /* below). */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* The returned glyph is owned and managed by the glyph image cache. */+ /* Never try to transform or discard it manually! You can however */+ /* create a copy with @FT_Glyph_Copy and modify the new one. */+ /* */+ /* If `anode' is _not_ NULL, it receives the address of the cache */+ /* node containing the glyph image, after increasing its reference */+ /* count. This ensures that the node (as well as the @FT_Glyph) will */+ /* always be kept in the cache until you call @FTC_Node_Unref to */+ /* `release' it. */+ /* */+ /* If `anode' is NULL, the cache node is left unchanged, which means */+ /* that the @FT_Glyph could be flushed out of the cache on the next */+ /* call to one of the caching sub-system APIs. Don't assume that it */+ /* is persistent! */+ /* */+ FT_EXPORT( FT_Error )+ FTC_ImageCache_Lookup( FTC_ImageCache cache,+ FTC_ImageType type,+ FT_UInt gindex,+ FT_Glyph *aglyph,+ FTC_Node *anode );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FTC_ImageCache_LookupScaler */+ /* */+ /* <Description> */+ /* A variant of @FTC_ImageCache_Lookup that uses an @FTC_ScalerRec */+ /* to specify the face ID and its size. */+ /* */+ /* <Input> */+ /* cache :: A handle to the source glyph image cache. */+ /* */+ /* scaler :: A pointer to a scaler descriptor. */+ /* */+ /* load_flags :: The corresponding load flags. */+ /* */+ /* gindex :: The glyph index to retrieve. */+ /* */+ /* <Output> */+ /* aglyph :: The corresponding @FT_Glyph object. 0~in case of */+ /* failure. */+ /* */+ /* anode :: Used to return the address of of the corresponding */+ /* cache node after incrementing its reference count */+ /* (see note below). */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* The returned glyph is owned and managed by the glyph image cache. */+ /* Never try to transform or discard it manually! You can however */+ /* create a copy with @FT_Glyph_Copy and modify the new one. */+ /* */+ /* If `anode' is _not_ NULL, it receives the address of the cache */+ /* node containing the glyph image, after increasing its reference */+ /* count. This ensures that the node (as well as the @FT_Glyph) will */+ /* always be kept in the cache until you call @FTC_Node_Unref to */+ /* `release' it. */+ /* */+ /* If `anode' is NULL, the cache node is left unchanged, which means */+ /* that the @FT_Glyph could be flushed out of the cache on the next */+ /* call to one of the caching sub-system APIs. Don't assume that it */+ /* is persistent! */+ /* */+ /* Calls to @FT_Set_Char_Size and friends have no effect on cached */+ /* glyphs; you should always use the FreeType cache API instead. */+ /* */+ FT_EXPORT( FT_Error )+ FTC_ImageCache_LookupScaler( FTC_ImageCache cache,+ FTC_Scaler scaler,+ FT_ULong load_flags,+ FT_UInt gindex,+ FT_Glyph *aglyph,+ FTC_Node *anode );+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FTC_SBit */+ /* */+ /* <Description> */+ /* A handle to a small bitmap descriptor. See the @FTC_SBitRec */+ /* structure for details. */+ /* */+ typedef struct FTC_SBitRec_* FTC_SBit;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FTC_SBitRec */+ /* */+ /* <Description> */+ /* A very compact structure used to describe a small glyph bitmap. */+ /* */+ /* <Fields> */+ /* width :: The bitmap width in pixels. */+ /* */+ /* height :: The bitmap height in pixels. */+ /* */+ /* left :: The horizontal distance from the pen position to the */+ /* left bitmap border (a.k.a. `left side bearing', or */+ /* `lsb'). */+ /* */+ /* top :: The vertical distance from the pen position (on the */+ /* baseline) to the upper bitmap border (a.k.a. `top */+ /* side bearing'). The distance is positive for upwards */+ /* y~coordinates. */+ /* */+ /* format :: The format of the glyph bitmap (monochrome or gray). */+ /* */+ /* max_grays :: Maximum gray level value (in the range 1 to~255). */+ /* */+ /* pitch :: The number of bytes per bitmap line. May be positive */+ /* or negative. */+ /* */+ /* xadvance :: The horizontal advance width in pixels. */+ /* */+ /* yadvance :: The vertical advance height in pixels. */+ /* */+ /* buffer :: A pointer to the bitmap pixels. */+ /* */+ typedef struct FTC_SBitRec_+ {+ FT_Byte width;+ FT_Byte height;+ FT_Char left;+ FT_Char top;++ FT_Byte format;+ FT_Byte max_grays;+ FT_Short pitch;+ FT_Char xadvance;+ FT_Char yadvance;++ FT_Byte* buffer;++ } FTC_SBitRec;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FTC_SBitCache */+ /* */+ /* <Description> */+ /* A handle to a small bitmap cache. These are special cache objects */+ /* used to store small glyph bitmaps (and anti-aliased pixmaps) in a */+ /* much more efficient way than the traditional glyph image cache */+ /* implemented by @FTC_ImageCache. */+ /* */+ typedef struct FTC_SBitCacheRec_* FTC_SBitCache;+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FTC_SBitCache_New */+ /* */+ /* <Description> */+ /* Create a new cache to store small glyph bitmaps. */+ /* */+ /* <Input> */+ /* manager :: A handle to the source cache manager. */+ /* */+ /* <Output> */+ /* acache :: A handle to the new sbit cache. NULL in case of error. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ FT_EXPORT( FT_Error )+ FTC_SBitCache_New( FTC_Manager manager,+ FTC_SBitCache *acache );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FTC_SBitCache_Lookup */+ /* */+ /* <Description> */+ /* Look up a given small glyph bitmap in a given sbit cache and */+ /* `lock' it to prevent its flushing from the cache until needed. */+ /* */+ /* <Input> */+ /* cache :: A handle to the source sbit cache. */+ /* */+ /* type :: A pointer to the glyph image type descriptor. */+ /* */+ /* gindex :: The glyph index. */+ /* */+ /* <Output> */+ /* sbit :: A handle to a small bitmap descriptor. */+ /* */+ /* anode :: Used to return the address of of the corresponding cache */+ /* node after incrementing its reference count (see note */+ /* below). */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* The small bitmap descriptor and its bit buffer are owned by the */+ /* cache and should never be freed by the application. They might */+ /* as well disappear from memory on the next cache lookup, so don't */+ /* treat them as persistent data. */+ /* */+ /* The descriptor's `buffer' field is set to~0 to indicate a missing */+ /* glyph bitmap. */+ /* */+ /* If `anode' is _not_ NULL, it receives the address of the cache */+ /* node containing the bitmap, after increasing its reference count. */+ /* This ensures that the node (as well as the image) will always be */+ /* kept in the cache until you call @FTC_Node_Unref to `release' it. */+ /* */+ /* If `anode' is NULL, the cache node is left unchanged, which means */+ /* that the bitmap could be flushed out of the cache on the next */+ /* call to one of the caching sub-system APIs. Don't assume that it */+ /* is persistent! */+ /* */+ FT_EXPORT( FT_Error )+ FTC_SBitCache_Lookup( FTC_SBitCache cache,+ FTC_ImageType type,+ FT_UInt gindex,+ FTC_SBit *sbit,+ FTC_Node *anode );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FTC_SBitCache_LookupScaler */+ /* */+ /* <Description> */+ /* A variant of @FTC_SBitCache_Lookup that uses an @FTC_ScalerRec */+ /* to specify the face ID and its size. */+ /* */+ /* <Input> */+ /* cache :: A handle to the source sbit cache. */+ /* */+ /* scaler :: A pointer to the scaler descriptor. */+ /* */+ /* load_flags :: The corresponding load flags. */+ /* */+ /* gindex :: The glyph index. */+ /* */+ /* <Output> */+ /* sbit :: A handle to a small bitmap descriptor. */+ /* */+ /* anode :: Used to return the address of of the corresponding */+ /* cache node after incrementing its reference count */+ /* (see note below). */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* The small bitmap descriptor and its bit buffer are owned by the */+ /* cache and should never be freed by the application. They might */+ /* as well disappear from memory on the next cache lookup, so don't */+ /* treat them as persistent data. */+ /* */+ /* The descriptor's `buffer' field is set to~0 to indicate a missing */+ /* glyph bitmap. */+ /* */+ /* If `anode' is _not_ NULL, it receives the address of the cache */+ /* node containing the bitmap, after increasing its reference count. */+ /* This ensures that the node (as well as the image) will always be */+ /* kept in the cache until you call @FTC_Node_Unref to `release' it. */+ /* */+ /* If `anode' is NULL, the cache node is left unchanged, which means */+ /* that the bitmap could be flushed out of the cache on the next */+ /* call to one of the caching sub-system APIs. Don't assume that it */+ /* is persistent! */+ /* */+ FT_EXPORT( FT_Error )+ FTC_SBitCache_LookupScaler( FTC_SBitCache cache,+ FTC_Scaler scaler,+ FT_ULong load_flags,+ FT_UInt gindex,+ FTC_SBit *sbit,+ FTC_Node *anode );+++ /* */++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS++ /*@***********************************************************************/+ /* */+ /* <Struct> */+ /* FTC_FontRec */+ /* */+ /* <Description> */+ /* A simple structure used to describe a given `font' to the cache */+ /* manager. Note that a `font' is the combination of a given face */+ /* with a given character size. */+ /* */+ /* <Fields> */+ /* face_id :: The ID of the face to use. */+ /* */+ /* pix_width :: The character width in integer pixels. */+ /* */+ /* pix_height :: The character height in integer pixels. */+ /* */+ typedef struct FTC_FontRec_+ {+ FTC_FaceID face_id;+ FT_UShort pix_width;+ FT_UShort pix_height;++ } FTC_FontRec;+++ /* */+++#define FTC_FONT_COMPARE( f1, f2 ) \+ ( (f1)->face_id == (f2)->face_id && \+ (f1)->pix_width == (f2)->pix_width && \+ (f1)->pix_height == (f2)->pix_height )++ /* this macro is incompatible with LLP64, should not be used */+#define FTC_FONT_HASH( f ) \+ (FT_UInt32)( FTC_FACE_ID_HASH((f)->face_id) ^ \+ ((f)->pix_width << 8) ^ \+ ((f)->pix_height) )++ typedef FTC_FontRec* FTC_Font;+++ FT_EXPORT( FT_Error )+ FTC_Manager_Lookup_Face( FTC_Manager manager,+ FTC_FaceID face_id,+ FT_Face *aface );++ FT_EXPORT( FT_Error )+ FTC_Manager_Lookup_Size( FTC_Manager manager,+ FTC_Font font,+ FT_Face *aface,+ FT_Size *asize );++#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */+++ /* */++FT_END_HEADER++#endif /* __FTCACHE_H__ */+++/* END */
+ include/freetype/ftchapters.h view
@@ -0,0 +1,103 @@+/***************************************************************************/+/* */+/* This file defines the structure of the FreeType reference. */+/* It is used by the python script which generates the HTML files. */+/* */+/***************************************************************************/+++/***************************************************************************/+/* */+/* <Chapter> */+/* general_remarks */+/* */+/* <Title> */+/* General Remarks */+/* */+/* <Sections> */+/* user_allocation */+/* */+/***************************************************************************/+++/***************************************************************************/+/* */+/* <Chapter> */+/* core_api */+/* */+/* <Title> */+/* Core API */+/* */+/* <Sections> */+/* version */+/* basic_types */+/* base_interface */+/* glyph_variants */+/* glyph_management */+/* mac_specific */+/* sizes_management */+/* header_file_macros */+/* */+/***************************************************************************/+++/***************************************************************************/+/* */+/* <Chapter> */+/* format_specific */+/* */+/* <Title> */+/* Format-Specific API */+/* */+/* <Sections> */+/* multiple_masters */+/* truetype_tables */+/* type1_tables */+/* sfnt_names */+/* bdf_fonts */+/* cid_fonts */+/* pfr_fonts */+/* winfnt_fonts */+/* font_formats */+/* gasp_table */+/* */+/***************************************************************************/+++/***************************************************************************/+/* */+/* <Chapter> */+/* cache_subsystem */+/* */+/* <Title> */+/* Cache Sub-System */+/* */+/* <Sections> */+/* cache_subsystem */+/* */+/***************************************************************************/+++/***************************************************************************/+/* */+/* <Chapter> */+/* support_api */+/* */+/* <Title> */+/* Support API */+/* */+/* <Sections> */+/* computations */+/* list_processing */+/* outline_processing */+/* quick_advance */+/* bitmap_handling */+/* raster */+/* glyph_stroker */+/* system_interface */+/* module_management */+/* gzip */+/* lzw */+/* lcd_filtering */+/* */+/***************************************************************************/
+ include/freetype/ftcid.h view
@@ -0,0 +1,166 @@+/***************************************************************************/+/* */+/* ftcid.h */+/* */+/* FreeType API for accessing CID font information (specification). */+/* */+/* Copyright 2007, 2009 by Dereg Clegg, 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. */+/* */+/***************************************************************************/+++#ifndef __FTCID_H__+#define __FTCID_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+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* cid_fonts */+ /* */+ /* <Title> */+ /* CID Fonts */+ /* */+ /* <Abstract> */+ /* CID-keyed font specific API. */+ /* */+ /* <Description> */+ /* This section contains the declaration of CID-keyed font specific */+ /* functions. */+ /* */+ /*************************************************************************/+++ /**********************************************************************+ *+ * @function:+ * FT_Get_CID_Registry_Ordering_Supplement+ *+ * @description:+ * Retrieve the Registry/Ordering/Supplement triple (also known as the+ * "R/O/S") from a CID-keyed font.+ *+ * @input:+ * face ::+ * A handle to the input face.+ *+ * @output:+ * registry ::+ * The registry, as a C~string, owned by the face.+ *+ * ordering ::+ * The ordering, as a C~string, owned by the face.+ *+ * supplement ::+ * The supplement.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * This function only works with CID faces, returning an error+ * otherwise.+ *+ * @since:+ * 2.3.6+ */+ FT_EXPORT( FT_Error )+ FT_Get_CID_Registry_Ordering_Supplement( FT_Face face,+ const char* *registry,+ const char* *ordering,+ FT_Int *supplement);+++ /**********************************************************************+ *+ * @function:+ * FT_Get_CID_Is_Internally_CID_Keyed+ *+ * @description:+ * Retrieve the type of the input face, CID keyed or not. In+ * constrast to the @FT_IS_CID_KEYED macro this function returns+ * successfully also for CID-keyed fonts in an SNFT wrapper.+ *+ * @input:+ * face ::+ * A handle to the input face.+ *+ * @output:+ * is_cid ::+ * The type of the face as an @FT_Bool.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * This function only works with CID faces and OpenType fonts,+ * returning an error otherwise.+ *+ * @since:+ * 2.3.9+ */+ FT_EXPORT( FT_Error )+ FT_Get_CID_Is_Internally_CID_Keyed( FT_Face face,+ FT_Bool *is_cid );+++ /**********************************************************************+ *+ * @function:+ * FT_Get_CID_From_Glyph_Index+ *+ * @description:+ * Retrieve the CID of the input glyph index.+ *+ * @input:+ * face ::+ * A handle to the input face.+ *+ * glyph_index ::+ * The input glyph index.+ *+ * @output:+ * cid ::+ * The CID as an @FT_UInt.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * This function only works with CID faces and OpenType fonts,+ * returning an error otherwise.+ *+ * @since:+ * 2.3.9+ */+ FT_EXPORT( FT_Error )+ FT_Get_CID_From_Glyph_Index( FT_Face face,+ FT_UInt glyph_index,+ FT_UInt *cid );++ /* */++FT_END_HEADER++#endif /* __FTCID_H__ */+++/* END */
+ include/freetype/fterrdef.h view
@@ -0,0 +1,244 @@+/***************************************************************************/+/* */+/* fterrdef.h */+/* */+/* FreeType error codes (specification). */+/* */+/* Copyright 2002, 2004, 2006, 2007, 2010 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. */+/* */+/***************************************************************************/+++ /*******************************************************************/+ /*******************************************************************/+ /***** *****/+ /***** LIST OF ERROR CODES/MESSAGES *****/+ /***** *****/+ /*******************************************************************/+ /*******************************************************************/+++ /* You need to define both FT_ERRORDEF_ and FT_NOERRORDEF_ before */+ /* including this file. */+++ /* generic errors */++ FT_NOERRORDEF_( Ok, 0x00, \+ "no error" )++ FT_ERRORDEF_( Cannot_Open_Resource, 0x01, \+ "cannot open resource" )+ FT_ERRORDEF_( Unknown_File_Format, 0x02, \+ "unknown file format" )+ FT_ERRORDEF_( Invalid_File_Format, 0x03, \+ "broken file" )+ FT_ERRORDEF_( Invalid_Version, 0x04, \+ "invalid FreeType version" )+ FT_ERRORDEF_( Lower_Module_Version, 0x05, \+ "module version is too low" )+ FT_ERRORDEF_( Invalid_Argument, 0x06, \+ "invalid argument" )+ FT_ERRORDEF_( Unimplemented_Feature, 0x07, \+ "unimplemented feature" )+ FT_ERRORDEF_( Invalid_Table, 0x08, \+ "broken table" )+ FT_ERRORDEF_( Invalid_Offset, 0x09, \+ "broken offset within table" )+ FT_ERRORDEF_( Array_Too_Large, 0x0A, \+ "array allocation size too large" )++ /* glyph/character errors */++ FT_ERRORDEF_( Invalid_Glyph_Index, 0x10, \+ "invalid glyph index" )+ FT_ERRORDEF_( Invalid_Character_Code, 0x11, \+ "invalid character code" )+ FT_ERRORDEF_( Invalid_Glyph_Format, 0x12, \+ "unsupported glyph image format" )+ FT_ERRORDEF_( Cannot_Render_Glyph, 0x13, \+ "cannot render this glyph format" )+ FT_ERRORDEF_( Invalid_Outline, 0x14, \+ "invalid outline" )+ FT_ERRORDEF_( Invalid_Composite, 0x15, \+ "invalid composite glyph" )+ FT_ERRORDEF_( Too_Many_Hints, 0x16, \+ "too many hints" )+ FT_ERRORDEF_( Invalid_Pixel_Size, 0x17, \+ "invalid pixel size" )++ /* handle errors */++ FT_ERRORDEF_( Invalid_Handle, 0x20, \+ "invalid object handle" )+ FT_ERRORDEF_( Invalid_Library_Handle, 0x21, \+ "invalid library handle" )+ FT_ERRORDEF_( Invalid_Driver_Handle, 0x22, \+ "invalid module handle" )+ FT_ERRORDEF_( Invalid_Face_Handle, 0x23, \+ "invalid face handle" )+ FT_ERRORDEF_( Invalid_Size_Handle, 0x24, \+ "invalid size handle" )+ FT_ERRORDEF_( Invalid_Slot_Handle, 0x25, \+ "invalid glyph slot handle" )+ FT_ERRORDEF_( Invalid_CharMap_Handle, 0x26, \+ "invalid charmap handle" )+ FT_ERRORDEF_( Invalid_Cache_Handle, 0x27, \+ "invalid cache manager handle" )+ FT_ERRORDEF_( Invalid_Stream_Handle, 0x28, \+ "invalid stream handle" )++ /* driver errors */++ FT_ERRORDEF_( Too_Many_Drivers, 0x30, \+ "too many modules" )+ FT_ERRORDEF_( Too_Many_Extensions, 0x31, \+ "too many extensions" )++ /* memory errors */++ FT_ERRORDEF_( Out_Of_Memory, 0x40, \+ "out of memory" )+ FT_ERRORDEF_( Unlisted_Object, 0x41, \+ "unlisted object" )++ /* stream errors */++ FT_ERRORDEF_( Cannot_Open_Stream, 0x51, \+ "cannot open stream" )+ FT_ERRORDEF_( Invalid_Stream_Seek, 0x52, \+ "invalid stream seek" )+ FT_ERRORDEF_( Invalid_Stream_Skip, 0x53, \+ "invalid stream skip" )+ FT_ERRORDEF_( Invalid_Stream_Read, 0x54, \+ "invalid stream read" )+ FT_ERRORDEF_( Invalid_Stream_Operation, 0x55, \+ "invalid stream operation" )+ FT_ERRORDEF_( Invalid_Frame_Operation, 0x56, \+ "invalid frame operation" )+ FT_ERRORDEF_( Nested_Frame_Access, 0x57, \+ "nested frame access" )+ FT_ERRORDEF_( Invalid_Frame_Read, 0x58, \+ "invalid frame read" )++ /* raster errors */++ FT_ERRORDEF_( Raster_Uninitialized, 0x60, \+ "raster uninitialized" )+ FT_ERRORDEF_( Raster_Corrupted, 0x61, \+ "raster corrupted" )+ FT_ERRORDEF_( Raster_Overflow, 0x62, \+ "raster overflow" )+ FT_ERRORDEF_( Raster_Negative_Height, 0x63, \+ "negative height while rastering" )++ /* cache errors */++ FT_ERRORDEF_( Too_Many_Caches, 0x70, \+ "too many registered caches" )++ /* TrueType and SFNT errors */++ FT_ERRORDEF_( Invalid_Opcode, 0x80, \+ "invalid opcode" )+ FT_ERRORDEF_( Too_Few_Arguments, 0x81, \+ "too few arguments" )+ FT_ERRORDEF_( Stack_Overflow, 0x82, \+ "stack overflow" )+ FT_ERRORDEF_( Code_Overflow, 0x83, \+ "code overflow" )+ FT_ERRORDEF_( Bad_Argument, 0x84, \+ "bad argument" )+ FT_ERRORDEF_( Divide_By_Zero, 0x85, \+ "division by zero" )+ FT_ERRORDEF_( Invalid_Reference, 0x86, \+ "invalid reference" )+ FT_ERRORDEF_( Debug_OpCode, 0x87, \+ "found debug opcode" )+ FT_ERRORDEF_( ENDF_In_Exec_Stream, 0x88, \+ "found ENDF opcode in execution stream" )+ FT_ERRORDEF_( Nested_DEFS, 0x89, \+ "nested DEFS" )+ FT_ERRORDEF_( Invalid_CodeRange, 0x8A, \+ "invalid code range" )+ FT_ERRORDEF_( Execution_Too_Long, 0x8B, \+ "execution context too long" )+ FT_ERRORDEF_( Too_Many_Function_Defs, 0x8C, \+ "too many function definitions" )+ FT_ERRORDEF_( Too_Many_Instruction_Defs, 0x8D, \+ "too many instruction definitions" )+ FT_ERRORDEF_( Table_Missing, 0x8E, \+ "SFNT font table missing" )+ FT_ERRORDEF_( Horiz_Header_Missing, 0x8F, \+ "horizontal header (hhea) table missing" )+ FT_ERRORDEF_( Locations_Missing, 0x90, \+ "locations (loca) table missing" )+ FT_ERRORDEF_( Name_Table_Missing, 0x91, \+ "name table missing" )+ FT_ERRORDEF_( CMap_Table_Missing, 0x92, \+ "character map (cmap) table missing" )+ FT_ERRORDEF_( Hmtx_Table_Missing, 0x93, \+ "horizontal metrics (hmtx) table missing" )+ FT_ERRORDEF_( Post_Table_Missing, 0x94, \+ "PostScript (post) table missing" )+ FT_ERRORDEF_( Invalid_Horiz_Metrics, 0x95, \+ "invalid horizontal metrics" )+ FT_ERRORDEF_( Invalid_CharMap_Format, 0x96, \+ "invalid character map (cmap) format" )+ FT_ERRORDEF_( Invalid_PPem, 0x97, \+ "invalid ppem value" )+ FT_ERRORDEF_( Invalid_Vert_Metrics, 0x98, \+ "invalid vertical metrics" )+ FT_ERRORDEF_( Could_Not_Find_Context, 0x99, \+ "could not find context" )+ FT_ERRORDEF_( Invalid_Post_Table_Format, 0x9A, \+ "invalid PostScript (post) table format" )+ FT_ERRORDEF_( Invalid_Post_Table, 0x9B, \+ "invalid PostScript (post) table" )++ /* CFF, CID, and Type 1 errors */++ FT_ERRORDEF_( Syntax_Error, 0xA0, \+ "opcode syntax error" )+ FT_ERRORDEF_( Stack_Underflow, 0xA1, \+ "argument stack underflow" )+ FT_ERRORDEF_( Ignore, 0xA2, \+ "ignore" )+ FT_ERRORDEF_( No_Unicode_Glyph_Name, 0xA3, \+ "no Unicode glyph name found" )+++ /* BDF errors */++ FT_ERRORDEF_( Missing_Startfont_Field, 0xB0, \+ "`STARTFONT' field missing" )+ FT_ERRORDEF_( Missing_Font_Field, 0xB1, \+ "`FONT' field missing" )+ FT_ERRORDEF_( Missing_Size_Field, 0xB2, \+ "`SIZE' field missing" )+ FT_ERRORDEF_( Missing_Fontboundingbox_Field, 0xB3, \+ "`FONTBOUNDINGBOX' field missing" )+ FT_ERRORDEF_( Missing_Chars_Field, 0xB4, \+ "`CHARS' field missing" )+ FT_ERRORDEF_( Missing_Startchar_Field, 0xB5, \+ "`STARTCHAR' field missing" )+ FT_ERRORDEF_( Missing_Encoding_Field, 0xB6, \+ "`ENCODING' field missing" )+ FT_ERRORDEF_( Missing_Bbx_Field, 0xB7, \+ "`BBX' field missing" )+ FT_ERRORDEF_( Bbx_Too_Big, 0xB8, \+ "`BBX' too big" )+ FT_ERRORDEF_( Corrupted_Font_Header, 0xB9, \+ "Font header corrupted or missing fields" )+ FT_ERRORDEF_( Corrupted_Font_Glyphs, 0xBA, \+ "Font glyphs corrupted or missing fields" )+++/* END */
+ include/freetype/fterrors.h view
@@ -0,0 +1,206 @@+/***************************************************************************/+/* */+/* fterrors.h */+/* */+/* FreeType error code handling (specification). */+/* */+/* Copyright 1996-2001, 2002, 2004, 2007 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 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. */+ /* */+ /* I - 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 */+ /* the module where the error has happened (this is not compatible */+ /* with standard builds of FreeType 2). You can then use the macro */+ /* FT_ERROR_BASE macro to extract the generic error code from an */+ /* FT_Error value. */+ /* */+ /* */+ /* 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). */+ /* */+ /* To do so, you have to define the following macros before including */+ /* 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_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. */+ /* */+ /* 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: */+ /* */+ /* { */+ /* #undef __FTERRORS_H__ */+ /* #define FT_ERRORDEF( e, v, s ) { e, s }, */+ /* #define FT_ERROR_START_LIST { */+ /* #define FT_ERROR_END_LIST { 0, 0 } }; */+ /* */+ /* const struct */+ /* { */+ /* int err_code; */+ /* const char* err_msg; */+ /* } ft_errors[] = */+ /* */+ /* #include FT_ERRORS_H */+ /* } */+ /* */+ /*************************************************************************/+++#ifndef __FTERRORS_H__+#define __FTERRORS_H__+++ /* include module base error codes */+#include FT_MODULE_ERRORS_H+++ /*******************************************************************/+ /*******************************************************************/+ /***** *****/+ /***** SETUP MACROS *****/+ /***** *****/+ /*******************************************************************/+ /*******************************************************************/+++#undef FT_NEED_EXTERN_C++#undef FT_ERR_XCAT+#undef FT_ERR_CAT++#define FT_ERR_XCAT( x, y ) x ## y+#define FT_ERR_CAT( x, y ) FT_ERR_XCAT( x, y )+++ /* FT_ERR_PREFIX is used as a prefix for error identifiers. */+ /* By default, we use `FT_Err_'. */+ /* */+#ifndef FT_ERR_PREFIX+#define FT_ERR_PREFIX FT_Err_+#endif+++ /* FT_ERR_BASE is used as the base for module-specific errors. */+ /* */+#ifdef FT_CONFIG_OPTION_USE_MODULE_ERRORS++#ifndef FT_ERR_BASE+#define FT_ERR_BASE FT_Mod_Err_Base+#endif++#else++#undef FT_ERR_BASE+#define FT_ERR_BASE 0++#endif /* FT_CONFIG_OPTION_USE_MODULE_ERRORS */+++ /* If FT_ERRORDEF is not defined, we need to define a simple */+ /* enumeration type. */+ /* */+#ifndef FT_ERRORDEF++#define FT_ERRORDEF( e, v, s ) e = v,+#define FT_ERROR_START_LIST enum {+#define FT_ERROR_END_LIST FT_ERR_CAT( FT_ERR_PREFIX, Max ) };++#ifdef __cplusplus+#define FT_NEED_EXTERN_C+ extern "C" {+#endif++#endif /* !FT_ERRORDEF */+++ /* this macro is used to define an error */+#define FT_ERRORDEF_( e, v, s ) \+ FT_ERRORDEF( FT_ERR_CAT( FT_ERR_PREFIX, e ), v + FT_ERR_BASE, s )++ /* this is only used for <module>_Err_Ok, which must be 0! */+#define FT_NOERRORDEF_( e, v, s ) \+ FT_ERRORDEF( FT_ERR_CAT( FT_ERR_PREFIX, e ), v, s )+++#ifdef FT_ERROR_START_LIST+ FT_ERROR_START_LIST+#endif+++ /* now include the error codes */+#include FT_ERROR_DEFINITIONS_H+++#ifdef FT_ERROR_END_LIST+ FT_ERROR_END_LIST+#endif+++ /*******************************************************************/+ /*******************************************************************/+ /***** *****/+ /***** SIMPLE CLEANUP *****/+ /***** *****/+ /*******************************************************************/+ /*******************************************************************/++#ifdef FT_NEED_EXTERN_C+ }+#endif++#undef FT_ERROR_START_LIST+#undef FT_ERROR_END_LIST++#undef FT_ERRORDEF+#undef FT_ERRORDEF_+#undef FT_NOERRORDEF_++#undef FT_NEED_EXTERN_C+#undef FT_ERR_CONCAT+#undef FT_ERR_BASE++ /* FT_KEEP_ERR_PREFIX is needed for ftvalid.h */+#ifndef FT_KEEP_ERR_PREFIX+#undef FT_ERR_PREFIX+#endif++#endif /* __FTERRORS_H__ */+++/* END */
+ include/freetype/ftgasp.h view
@@ -0,0 +1,120 @@+/***************************************************************************/+/* */+/* ftgasp.h */+/* */+/* Access of TrueType's `gasp' table (specification). */+/* */+/* Copyright 2007, 2008 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 _FT_GASP_H_+#define _FT_GASP_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+++ /***************************************************************************+ *+ * @section:+ * gasp_table+ *+ * @title:+ * Gasp Table+ *+ * @abstract:+ * Retrieving TrueType `gasp' table entries.+ *+ * @description:+ * The function @FT_Get_Gasp can be used to query a TrueType or OpenType+ * font for specific entries in its `gasp' table, if any. This is+ * mainly useful when implementing native TrueType hinting with the+ * bytecode interpreter to duplicate the Windows text rendering results.+ */++ /*************************************************************************+ *+ * @enum:+ * FT_GASP_XXX+ *+ * @description:+ * A list of values and/or bit-flags returned by the @FT_Get_Gasp+ * function.+ *+ * @values:+ * FT_GASP_NO_TABLE ::+ * This special value means that there is no GASP table in this face.+ * It is up to the client to decide what to do.+ *+ * FT_GASP_DO_GRIDFIT ::+ * Grid-fitting and hinting should be performed at the specified ppem.+ * This *really* means TrueType bytecode interpretation.+ *+ * FT_GASP_DO_GRAY ::+ * Anti-aliased rendering should be performed at the specified ppem.+ *+ * FT_GASP_SYMMETRIC_SMOOTHING ::+ * Smoothing along multiple axes must be used with ClearType.+ *+ * FT_GASP_SYMMETRIC_GRIDFIT ::+ * Grid-fitting must be used with ClearType's symmetric smoothing.+ *+ * @note:+ * `ClearType' is Microsoft's implementation of LCD rendering, partly+ * protected by patents.+ *+ * @since:+ * 2.3.0+ */+#define FT_GASP_NO_TABLE -1+#define FT_GASP_DO_GRIDFIT 0x01+#define FT_GASP_DO_GRAY 0x02+#define FT_GASP_SYMMETRIC_SMOOTHING 0x08+#define FT_GASP_SYMMETRIC_GRIDFIT 0x10+++ /*************************************************************************+ *+ * @func:+ * FT_Get_Gasp+ *+ * @description:+ * Read the `gasp' table from a TrueType or OpenType font file and+ * return the entry corresponding to a given character pixel size.+ *+ * @input:+ * face :: The source face handle.+ * ppem :: The vertical character pixel size.+ *+ * @return:+ * Bit flags (see @FT_GASP_XXX), or @FT_GASP_NO_TABLE if there is no+ * `gasp' table in the face.+ *+ * @since:+ * 2.3.0+ */+ FT_EXPORT( FT_Int )+ FT_Get_Gasp( FT_Face face,+ FT_UInt ppem );++/* */++#endif /* _FT_GASP_H_ */+++/* END */
+ include/freetype/ftglyph.h view
@@ -0,0 +1,613 @@+/***************************************************************************/+/* */+/* ftglyph.h */+/* */+/* FreeType convenience functions to handle glyphs (specification). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2006, 2008, 2009 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++ /*************************************************************************/+ /* */+ /* This file contains the definition of several convenience functions */+ /* that can be used by client applications to easily retrieve glyph */+ /* bitmaps and outlines from a given face. */+ /* */+ /* These functions should be optional if you are writing a font server */+ /* or text layout engine on top of FreeType. However, they are pretty */+ /* handy for many other simple uses of the library. */+ /* */+ /*************************************************************************/+++#ifndef __FTGLYPH_H__+#define __FTGLYPH_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+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* glyph_management */+ /* */+ /* <Title> */+ /* Glyph Management */+ /* */+ /* <Abstract> */+ /* Generic interface to manage individual glyph data. */+ /* */+ /* <Description> */+ /* This section contains definitions used to manage glyph data */+ /* through generic FT_Glyph objects. Each of them can contain a */+ /* bitmap, a vector outline, or even images in other formats. */+ /* */+ /*************************************************************************/+++ /* forward declaration to a private type */+ typedef struct FT_Glyph_Class_ FT_Glyph_Class;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_Glyph */+ /* */+ /* <Description> */+ /* Handle to an object used to model generic glyph images. It is a */+ /* pointer to the @FT_GlyphRec structure and can contain a glyph */+ /* bitmap or pointer. */+ /* */+ /* <Note> */+ /* Glyph objects are not owned by the library. You must thus release */+ /* them manually (through @FT_Done_Glyph) _before_ calling */+ /* @FT_Done_FreeType. */+ /* */+ typedef struct FT_GlyphRec_* FT_Glyph;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_GlyphRec */+ /* */+ /* <Description> */+ /* The root glyph structure contains a given glyph image plus its */+ /* advance width in 16.16 fixed float format. */+ /* */+ /* <Fields> */+ /* library :: A handle to the FreeType library object. */+ /* */+ /* clazz :: A pointer to the glyph's class. Private. */+ /* */+ /* format :: The format of the glyph's image. */+ /* */+ /* advance :: A 16.16 vector that gives the glyph's advance width. */+ /* */+ typedef struct FT_GlyphRec_+ {+ FT_Library library;+ const FT_Glyph_Class* clazz;+ FT_Glyph_Format format;+ FT_Vector advance;++ } FT_GlyphRec;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_BitmapGlyph */+ /* */+ /* <Description> */+ /* A handle to an object used to model a bitmap glyph image. This is */+ /* a sub-class of @FT_Glyph, and a pointer to @FT_BitmapGlyphRec. */+ /* */+ typedef struct FT_BitmapGlyphRec_* FT_BitmapGlyph;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_BitmapGlyphRec */+ /* */+ /* <Description> */+ /* A structure used for bitmap glyph images. This really is a */+ /* `sub-class' of @FT_GlyphRec. */+ /* */+ /* <Fields> */+ /* root :: The root @FT_Glyph fields. */+ /* */+ /* left :: The left-side bearing, i.e., the horizontal distance */+ /* from the current pen position to the left border of the */+ /* glyph bitmap. */+ /* */+ /* top :: The top-side bearing, i.e., the vertical distance from */+ /* the current pen position to the top border of the glyph */+ /* bitmap. This distance is positive for upwards~y! */+ /* */+ /* bitmap :: A descriptor for the bitmap. */+ /* */+ /* <Note> */+ /* You can typecast an @FT_Glyph to @FT_BitmapGlyph if you have */+ /* `glyph->format == FT_GLYPH_FORMAT_BITMAP'. This lets you access */+ /* the bitmap's contents easily. */+ /* */+ /* The corresponding pixel buffer is always owned by @FT_BitmapGlyph */+ /* and is thus created and destroyed with it. */+ /* */+ typedef struct FT_BitmapGlyphRec_+ {+ FT_GlyphRec root;+ FT_Int left;+ FT_Int top;+ FT_Bitmap bitmap;++ } FT_BitmapGlyphRec;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_OutlineGlyph */+ /* */+ /* <Description> */+ /* A handle to an object used to model an outline glyph image. This */+ /* is a sub-class of @FT_Glyph, and a pointer to @FT_OutlineGlyphRec. */+ /* */+ typedef struct FT_OutlineGlyphRec_* FT_OutlineGlyph;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_OutlineGlyphRec */+ /* */+ /* <Description> */+ /* A structure used for outline (vectorial) glyph images. This */+ /* really is a `sub-class' of @FT_GlyphRec. */+ /* */+ /* <Fields> */+ /* root :: The root @FT_Glyph fields. */+ /* */+ /* outline :: A descriptor for the outline. */+ /* */+ /* <Note> */+ /* You can typecast an @FT_Glyph to @FT_OutlineGlyph if you have */+ /* `glyph->format == FT_GLYPH_FORMAT_OUTLINE'. This lets you access */+ /* the outline's content easily. */+ /* */+ /* As the outline is extracted from a glyph slot, its coordinates are */+ /* expressed normally in 26.6 pixels, unless the flag */+ /* @FT_LOAD_NO_SCALE was used in @FT_Load_Glyph() or @FT_Load_Char(). */+ /* */+ /* The outline's tables are always owned by the object and are */+ /* destroyed with it. */+ /* */+ typedef struct FT_OutlineGlyphRec_+ {+ FT_GlyphRec root;+ FT_Outline outline;++ } FT_OutlineGlyphRec;+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Get_Glyph */+ /* */+ /* <Description> */+ /* A function used to extract a glyph image from a slot. Note that */+ /* the created @FT_Glyph object must be released with @FT_Done_Glyph. */+ /* */+ /* <Input> */+ /* slot :: A handle to the source glyph slot. */+ /* */+ /* <Output> */+ /* aglyph :: A handle to the glyph object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Get_Glyph( FT_GlyphSlot slot,+ FT_Glyph *aglyph );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Glyph_Copy */+ /* */+ /* <Description> */+ /* A function used to copy a glyph image. Note that the created */+ /* @FT_Glyph object must be released with @FT_Done_Glyph. */+ /* */+ /* <Input> */+ /* source :: A handle to the source glyph object. */+ /* */+ /* <Output> */+ /* target :: A handle to the target glyph object. 0~in case of */+ /* error. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Glyph_Copy( FT_Glyph source,+ FT_Glyph *target );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Glyph_Transform */+ /* */+ /* <Description> */+ /* Transform a glyph image if its format is scalable. */+ /* */+ /* <InOut> */+ /* glyph :: A handle to the target glyph object. */+ /* */+ /* <Input> */+ /* matrix :: A pointer to a 2x2 matrix to apply. */+ /* */+ /* delta :: A pointer to a 2d vector to apply. Coordinates are */+ /* expressed in 1/64th of a pixel. */+ /* */+ /* <Return> */+ /* FreeType error code (if not 0, the glyph format is not scalable). */+ /* */+ /* <Note> */+ /* The 2x2 transformation matrix is also applied to the glyph's */+ /* advance vector. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Glyph_Transform( FT_Glyph glyph,+ FT_Matrix* matrix,+ FT_Vector* delta );+++ /*************************************************************************/+ /* */+ /* <Enum> */+ /* FT_Glyph_BBox_Mode */+ /* */+ /* <Description> */+ /* The mode how the values of @FT_Glyph_Get_CBox are returned. */+ /* */+ /* <Values> */+ /* FT_GLYPH_BBOX_UNSCALED :: */+ /* Return unscaled font units. */+ /* */+ /* FT_GLYPH_BBOX_SUBPIXELS :: */+ /* Return unfitted 26.6 coordinates. */+ /* */+ /* FT_GLYPH_BBOX_GRIDFIT :: */+ /* Return grid-fitted 26.6 coordinates. */+ /* */+ /* FT_GLYPH_BBOX_TRUNCATE :: */+ /* Return coordinates in integer pixels. */+ /* */+ /* FT_GLYPH_BBOX_PIXELS :: */+ /* Return grid-fitted pixel coordinates. */+ /* */+ typedef enum FT_Glyph_BBox_Mode_+ {+ FT_GLYPH_BBOX_UNSCALED = 0,+ FT_GLYPH_BBOX_SUBPIXELS = 0,+ FT_GLYPH_BBOX_GRIDFIT = 1,+ FT_GLYPH_BBOX_TRUNCATE = 2,+ FT_GLYPH_BBOX_PIXELS = 3++ } FT_Glyph_BBox_Mode;+++ /*************************************************************************/+ /* */+ /* <Enum> */+ /* ft_glyph_bbox_xxx */+ /* */+ /* <Description> */+ /* These constants are deprecated. Use the corresponding */+ /* @FT_Glyph_BBox_Mode values instead. */+ /* */+ /* <Values> */+ /* ft_glyph_bbox_unscaled :: See @FT_GLYPH_BBOX_UNSCALED. */+ /* ft_glyph_bbox_subpixels :: See @FT_GLYPH_BBOX_SUBPIXELS. */+ /* ft_glyph_bbox_gridfit :: See @FT_GLYPH_BBOX_GRIDFIT. */+ /* ft_glyph_bbox_truncate :: See @FT_GLYPH_BBOX_TRUNCATE. */+ /* ft_glyph_bbox_pixels :: See @FT_GLYPH_BBOX_PIXELS. */+ /* */+#define ft_glyph_bbox_unscaled FT_GLYPH_BBOX_UNSCALED+#define ft_glyph_bbox_subpixels FT_GLYPH_BBOX_SUBPIXELS+#define ft_glyph_bbox_gridfit FT_GLYPH_BBOX_GRIDFIT+#define ft_glyph_bbox_truncate FT_GLYPH_BBOX_TRUNCATE+#define ft_glyph_bbox_pixels FT_GLYPH_BBOX_PIXELS+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Glyph_Get_CBox */+ /* */+ /* <Description> */+ /* Return a glyph's `control box'. The control box encloses all the */+ /* outline's points, including Bézier control points. Though it */+ /* coincides with the exact bounding box for most glyphs, it can be */+ /* slightly larger in some situations (like when rotating an outline */+ /* which contains Bézier outside arcs). */+ /* */+ /* Computing the control box is very fast, while getting the bounding */+ /* box can take much more time as it needs to walk over all segments */+ /* and arcs in the outline. To get the latter, you can use the */+ /* `ftbbox' component which is dedicated to this single task. */+ /* */+ /* <Input> */+ /* glyph :: A handle to the source glyph object. */+ /* */+ /* mode :: The mode which indicates how to interpret the returned */+ /* bounding box values. */+ /* */+ /* <Output> */+ /* acbox :: The glyph coordinate bounding box. Coordinates are */+ /* expressed in 1/64th of pixels if it is grid-fitted. */+ /* */+ /* <Note> */+ /* Coordinates are relative to the glyph origin, using the y~upwards */+ /* convention. */+ /* */+ /* If the glyph has been loaded with @FT_LOAD_NO_SCALE, `bbox_mode' */+ /* must be set to @FT_GLYPH_BBOX_UNSCALED to get unscaled font */+ /* units in 26.6 pixel format. The value @FT_GLYPH_BBOX_SUBPIXELS */+ /* is another name for this constant. */+ /* */+ /* Note that the maximum coordinates are exclusive, which means that */+ /* one can compute the width and height of the glyph image (be it in */+ /* integer or 26.6 pixels) as: */+ /* */+ /* { */+ /* width = bbox.xMax - bbox.xMin; */+ /* height = bbox.yMax - bbox.yMin; */+ /* } */+ /* */+ /* Note also that for 26.6 coordinates, if `bbox_mode' is set to */+ /* @FT_GLYPH_BBOX_GRIDFIT, the coordinates will also be grid-fitted, */+ /* which corresponds to: */+ /* */+ /* { */+ /* bbox.xMin = FLOOR(bbox.xMin); */+ /* bbox.yMin = FLOOR(bbox.yMin); */+ /* bbox.xMax = CEILING(bbox.xMax); */+ /* bbox.yMax = CEILING(bbox.yMax); */+ /* } */+ /* */+ /* To get the bbox in pixel coordinates, set `bbox_mode' to */+ /* @FT_GLYPH_BBOX_TRUNCATE. */+ /* */+ /* To get the bbox in grid-fitted pixel coordinates, set `bbox_mode' */+ /* to @FT_GLYPH_BBOX_PIXELS. */+ /* */+ FT_EXPORT( void )+ FT_Glyph_Get_CBox( FT_Glyph glyph,+ FT_UInt bbox_mode,+ FT_BBox *acbox );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Glyph_To_Bitmap */+ /* */+ /* <Description> */+ /* Convert a given glyph object to a bitmap glyph object. */+ /* */+ /* <InOut> */+ /* the_glyph :: A pointer to a handle to the target glyph. */+ /* */+ /* <Input> */+ /* render_mode :: An enumeration that describes how the data is */+ /* rendered. */+ /* */+ /* origin :: A pointer to a vector used to translate the glyph */+ /* image before rendering. Can be~0 (if no */+ /* translation). The origin is expressed in */+ /* 26.6 pixels. */+ /* */+ /* destroy :: A boolean that indicates that the original glyph */+ /* image should be destroyed by this function. It is */+ /* never destroyed in case of error. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* This function does nothing if the glyph format isn't scalable. */+ /* */+ /* The glyph image is translated with the `origin' vector before */+ /* rendering. */+ /* */+ /* The first parameter is a pointer to an @FT_Glyph handle, that will */+ /* be _replaced_ by this function (with newly allocated data). */+ /* Typically, you would use (omitting error handling): */+ /* */+ /* */+ /* { */+ /* FT_Glyph glyph; */+ /* FT_BitmapGlyph glyph_bitmap; */+ /* */+ /* */+ /* // load glyph */+ /* error = FT_Load_Char( face, glyph_index, FT_LOAD_DEFAUT ); */+ /* */+ /* // extract glyph image */+ /* error = FT_Get_Glyph( face->glyph, &glyph ); */+ /* */+ /* // convert to a bitmap (default render mode + destroying old) */+ /* if ( glyph->format != FT_GLYPH_FORMAT_BITMAP ) */+ /* { */+ /* error = FT_Glyph_To_Bitmap( &glyph, FT_RENDER_MODE_NORMAL, */+ /* 0, 1 ); */+ /* if ( error ) // `glyph' unchanged */+ /* ... */+ /* } */+ /* */+ /* // access bitmap content by typecasting */+ /* glyph_bitmap = (FT_BitmapGlyph)glyph; */+ /* */+ /* // do funny stuff with it, like blitting/drawing */+ /* ... */+ /* */+ /* // discard glyph image (bitmap or not) */+ /* FT_Done_Glyph( glyph ); */+ /* } */+ /* */+ /* */+ /* Here another example, again without error handling: */+ /* */+ /* */+ /* { */+ /* FT_Glyph glyphs[MAX_GLYPHS] */+ /* */+ /* */+ /* ... */+ /* */+ /* for ( idx = 0; i < MAX_GLYPHS; i++ ) */+ /* error = FT_Load_Glyph( face, idx, FT_LOAD_DEFAULT ) || */+ /* FT_Get_Glyph ( face->glyph, &glyph[idx] ); */+ /* */+ /* ... */+ /* */+ /* for ( idx = 0; i < MAX_GLYPHS; i++ ) */+ /* { */+ /* FT_Glyph bitmap = glyphs[idx]; */+ /* */+ /* */+ /* ... */+ /* */+ /* // after this call, `bitmap' no longer points into */+ /* // the `glyphs' array (and the old value isn't destroyed) */+ /* FT_Glyph_To_Bitmap( &bitmap, FT_RENDER_MODE_MONO, 0, 0 ); */+ /* */+ /* ... */+ /* */+ /* FT_Done_Glyph( bitmap ); */+ /* } */+ /* */+ /* ... */+ /* */+ /* for ( idx = 0; i < MAX_GLYPHS; i++ ) */+ /* FT_Done_Glyph( glyphs[idx] ); */+ /* } */+ /* */+ FT_EXPORT( FT_Error )+ FT_Glyph_To_Bitmap( FT_Glyph* the_glyph,+ FT_Render_Mode render_mode,+ FT_Vector* origin,+ FT_Bool destroy );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Done_Glyph */+ /* */+ /* <Description> */+ /* Destroy a given glyph. */+ /* */+ /* <Input> */+ /* glyph :: A handle to the target glyph object. */+ /* */+ FT_EXPORT( void )+ FT_Done_Glyph( FT_Glyph glyph );++ /* */+++ /* other helpful functions */++ /*************************************************************************/+ /* */+ /* <Section> */+ /* computations */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Matrix_Multiply */+ /* */+ /* <Description> */+ /* Perform the matrix operation `b = a*b'. */+ /* */+ /* <Input> */+ /* a :: A pointer to matrix `a'. */+ /* */+ /* <InOut> */+ /* b :: A pointer to matrix `b'. */+ /* */+ /* <Note> */+ /* The result is undefined if either `a' or `b' is zero. */+ /* */+ FT_EXPORT( void )+ FT_Matrix_Multiply( const FT_Matrix* a,+ FT_Matrix* b );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Matrix_Invert */+ /* */+ /* <Description> */+ /* Invert a 2x2 matrix. Return an error if it can't be inverted. */+ /* */+ /* <InOut> */+ /* matrix :: A pointer to the target matrix. Remains untouched in */+ /* case of error. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Matrix_Invert( FT_Matrix* matrix );+++ /* */+++FT_END_HEADER++#endif /* __FTGLYPH_H__ */+++/* END */+++/* Local Variables: */+/* coding: utf-8 */+/* End: */
+ include/freetype/ftgxval.h view
@@ -0,0 +1,358 @@+/***************************************************************************/+/* */+/* ftgxval.h */+/* */+/* FreeType API for validating TrueTypeGX/AAT tables (specification). */+/* */+/* Copyright 2004, 2005, 2006 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. */+/* */+/***************************************************************************/+++#ifndef __FTGXVAL_H__+#define __FTGXVAL_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+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* gx_validation */+ /* */+ /* <Title> */+ /* TrueTypeGX/AAT Validation */+ /* */+ /* <Abstract> */+ /* An API to validate TrueTypeGX/AAT tables. */+ /* */+ /* <Description> */+ /* This section contains the declaration of functions to validate */+ /* some TrueTypeGX tables (feat, mort, morx, bsln, just, kern, opbd, */+ /* trak, prop, lcar). */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* */+ /* Warning: Use FT_VALIDATE_XXX to validate a table. */+ /* Following definitions are for gxvalid developers. */+ /* */+ /* */+ /*************************************************************************/++#define FT_VALIDATE_feat_INDEX 0+#define FT_VALIDATE_mort_INDEX 1+#define FT_VALIDATE_morx_INDEX 2+#define FT_VALIDATE_bsln_INDEX 3+#define FT_VALIDATE_just_INDEX 4+#define FT_VALIDATE_kern_INDEX 5+#define FT_VALIDATE_opbd_INDEX 6+#define FT_VALIDATE_trak_INDEX 7+#define FT_VALIDATE_prop_INDEX 8+#define FT_VALIDATE_lcar_INDEX 9+#define FT_VALIDATE_GX_LAST_INDEX FT_VALIDATE_lcar_INDEX+++ /*************************************************************************+ *+ * @macro:+ * FT_VALIDATE_GX_LENGTH+ *+ * @description:+ * The number of tables checked in this module. Use it as a parameter+ * for the `table-length' argument of function @FT_TrueTypeGX_Validate.+ */+#define FT_VALIDATE_GX_LENGTH (FT_VALIDATE_GX_LAST_INDEX + 1)++ /* */++ /* Up to 0x1000 is used by otvalid.+ Ox2xxx is reserved for feature OT extension. */+#define FT_VALIDATE_GX_START 0x4000+#define FT_VALIDATE_GX_BITFIELD( tag ) \+ ( FT_VALIDATE_GX_START << FT_VALIDATE_##tag##_INDEX )+++ /**********************************************************************+ *+ * @enum:+ * FT_VALIDATE_GXXXX+ *+ * @description:+ * A list of bit-field constants used with @FT_TrueTypeGX_Validate to+ * indicate which TrueTypeGX/AAT Type tables should be validated.+ *+ * @values:+ * FT_VALIDATE_feat ::+ * Validate `feat' table.+ *+ * FT_VALIDATE_mort ::+ * Validate `mort' table.+ *+ * FT_VALIDATE_morx ::+ * Validate `morx' table.+ *+ * FT_VALIDATE_bsln ::+ * Validate `bsln' table.+ *+ * FT_VALIDATE_just ::+ * Validate `just' table.+ *+ * FT_VALIDATE_kern ::+ * Validate `kern' table.+ *+ * FT_VALIDATE_opbd ::+ * Validate `opbd' table.+ *+ * FT_VALIDATE_trak ::+ * Validate `trak' table.+ *+ * FT_VALIDATE_prop ::+ * Validate `prop' table.+ *+ * FT_VALIDATE_lcar ::+ * Validate `lcar' table.+ *+ * FT_VALIDATE_GX ::+ * Validate all TrueTypeGX tables (feat, mort, morx, bsln, just, kern,+ * opbd, trak, prop and lcar).+ *+ */++#define FT_VALIDATE_feat FT_VALIDATE_GX_BITFIELD( feat )+#define FT_VALIDATE_mort FT_VALIDATE_GX_BITFIELD( mort )+#define FT_VALIDATE_morx FT_VALIDATE_GX_BITFIELD( morx )+#define FT_VALIDATE_bsln FT_VALIDATE_GX_BITFIELD( bsln )+#define FT_VALIDATE_just FT_VALIDATE_GX_BITFIELD( just )+#define FT_VALIDATE_kern FT_VALIDATE_GX_BITFIELD( kern )+#define FT_VALIDATE_opbd FT_VALIDATE_GX_BITFIELD( opbd )+#define FT_VALIDATE_trak FT_VALIDATE_GX_BITFIELD( trak )+#define FT_VALIDATE_prop FT_VALIDATE_GX_BITFIELD( prop )+#define FT_VALIDATE_lcar FT_VALIDATE_GX_BITFIELD( lcar )++#define FT_VALIDATE_GX ( FT_VALIDATE_feat | \+ FT_VALIDATE_mort | \+ FT_VALIDATE_morx | \+ FT_VALIDATE_bsln | \+ FT_VALIDATE_just | \+ FT_VALIDATE_kern | \+ FT_VALIDATE_opbd | \+ FT_VALIDATE_trak | \+ FT_VALIDATE_prop | \+ FT_VALIDATE_lcar )+++ /* */++ /**********************************************************************+ *+ * @function:+ * FT_TrueTypeGX_Validate+ *+ * @description:+ * Validate various TrueTypeGX tables to assure that all offsets and+ * indices are valid. The idea is that a higher-level library which+ * actually does the text layout can access those tables without+ * error checking (which can be quite time consuming).+ *+ * @input:+ * face ::+ * A handle to the input face.+ *+ * validation_flags ::+ * A bit field which specifies the tables to be validated. See+ * @FT_VALIDATE_GXXXX for possible values.+ *+ * table_length ::+ * The size of the `tables' array. Normally, @FT_VALIDATE_GX_LENGTH+ * should be passed.+ *+ * @output:+ * tables ::+ * The array where all validated sfnt tables are stored.+ * The array itself must be allocated by a client.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * This function only works with TrueTypeGX fonts, returning an error+ * otherwise.+ *+ * After use, the application should deallocate the buffers pointed to by+ * each `tables' element, by calling @FT_TrueTypeGX_Free. A NULL value+ * indicates that the table either doesn't exist in the font, the+ * application hasn't asked for validation, or the validator doesn't have+ * the ability to validate the sfnt table.+ */+ FT_EXPORT( FT_Error )+ FT_TrueTypeGX_Validate( FT_Face face,+ FT_UInt validation_flags,+ FT_Bytes tables[FT_VALIDATE_GX_LENGTH],+ FT_UInt table_length );+++ /* */++ /**********************************************************************+ *+ * @function:+ * FT_TrueTypeGX_Free+ *+ * @description:+ * Free the buffer allocated by TrueTypeGX validator.+ *+ * @input:+ * face ::+ * A handle to the input face.+ *+ * table ::+ * The pointer to the buffer allocated by+ * @FT_TrueTypeGX_Validate.+ *+ * @note:+ * This function must be used to free the buffer allocated by+ * @FT_TrueTypeGX_Validate only.+ */+ FT_EXPORT( void )+ FT_TrueTypeGX_Free( FT_Face face,+ FT_Bytes table );+++ /* */++ /**********************************************************************+ *+ * @enum:+ * FT_VALIDATE_CKERNXXX+ *+ * @description:+ * A list of bit-field constants used with @FT_ClassicKern_Validate+ * to indicate the classic kern dialect or dialects. If the selected+ * type doesn't fit, @FT_ClassicKern_Validate regards the table as+ * invalid.+ *+ * @values:+ * FT_VALIDATE_MS ::+ * Handle the `kern' table as a classic Microsoft kern table.+ *+ * FT_VALIDATE_APPLE ::+ * Handle the `kern' table as a classic Apple kern table.+ *+ * FT_VALIDATE_CKERN ::+ * Handle the `kern' as either classic Apple or Microsoft kern table.+ */+#define FT_VALIDATE_MS ( FT_VALIDATE_GX_START << 0 )+#define FT_VALIDATE_APPLE ( FT_VALIDATE_GX_START << 1 )++#define FT_VALIDATE_CKERN ( FT_VALIDATE_MS | FT_VALIDATE_APPLE )+++ /* */++ /**********************************************************************+ *+ * @function:+ * FT_ClassicKern_Validate+ *+ * @description:+ * Validate classic (16-bit format) kern table to assure that the offsets+ * and indices are valid. The idea is that a higher-level library which+ * actually does the text layout can access those tables without error+ * checking (which can be quite time consuming).+ *+ * The `kern' table validator in @FT_TrueTypeGX_Validate deals with both+ * the new 32-bit format and the classic 16-bit format, while+ * FT_ClassicKern_Validate only supports the classic 16-bit format.+ *+ * @input:+ * face ::+ * A handle to the input face.+ *+ * validation_flags ::+ * A bit field which specifies the dialect to be validated. See+ * @FT_VALIDATE_CKERNXXX for possible values.+ *+ * @output:+ * ckern_table ::+ * A pointer to the kern table.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * After use, the application should deallocate the buffers pointed to by+ * `ckern_table', by calling @FT_ClassicKern_Free. A NULL value+ * indicates that the table doesn't exist in the font.+ */+ FT_EXPORT( FT_Error )+ FT_ClassicKern_Validate( FT_Face face,+ FT_UInt validation_flags,+ FT_Bytes *ckern_table );+++ /* */++ /**********************************************************************+ *+ * @function:+ * FT_ClassicKern_Free+ *+ * @description:+ * Free the buffer allocated by classic Kern validator.+ *+ * @input:+ * face ::+ * A handle to the input face.+ *+ * table ::+ * The pointer to the buffer that is allocated by+ * @FT_ClassicKern_Validate.+ *+ * @note:+ * This function must be used to free the buffer allocated by+ * @FT_ClassicKern_Validate only.+ */+ FT_EXPORT( void )+ FT_ClassicKern_Free( FT_Face face,+ FT_Bytes table );+++ /* */+++FT_END_HEADER++#endif /* __FTGXVAL_H__ */+++/* END */
+ include/freetype/ftgzip.h view
@@ -0,0 +1,102 @@+/***************************************************************************/+/* */+/* ftgzip.h */+/* */+/* Gzip-compressed stream support. */+/* */+/* Copyright 2002, 2003, 2004, 2006 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 __FTGZIP_H__+#define __FTGZIP_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+++FT_BEGIN_HEADER++ /*************************************************************************/+ /* */+ /* <Section> */+ /* gzip */+ /* */+ /* <Title> */+ /* GZIP Streams */+ /* */+ /* <Abstract> */+ /* Using gzip-compressed font files. */+ /* */+ /* <Description> */+ /* This section contains the declaration of Gzip-specific functions. */+ /* */+ /*************************************************************************/+++ /************************************************************************+ *+ * @function:+ * FT_Stream_OpenGzip+ *+ * @description:+ * Open a new stream to parse gzip-compressed font files. This is+ * mainly used to support the compressed `*.pcf.gz' fonts that come+ * with XFree86.+ *+ * @input:+ * stream ::+ * The target embedding stream.+ *+ * source ::+ * The source stream.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * The source stream must be opened _before_ calling this function.+ *+ * Calling the internal function `FT_Stream_Close' on the new stream will+ * *not* call `FT_Stream_Close' on the source stream. None of the stream+ * objects will be released to the heap.+ *+ * The stream implementation is very basic and resets the decompression+ * process each time seeking backwards is needed within the stream.+ *+ * In certain builds of the library, gzip compression recognition is+ * automatically handled when calling @FT_New_Face or @FT_Open_Face.+ * This means that if no font driver is capable of handling the raw+ * compressed file, the library will try to open a gzipped stream from+ * it and re-open the face with it.+ *+ * This function may return `FT_Err_Unimplemented_Feature' if your build+ * of FreeType was not compiled with zlib support.+ */+ FT_EXPORT( FT_Error )+ FT_Stream_OpenGzip( FT_Stream stream,+ FT_Stream source );++ /* */+++FT_END_HEADER++#endif /* __FTGZIP_H__ */+++/* END */
+ include/freetype/ftimage.h view
@@ -0,0 +1,1313 @@+/***************************************************************************/+/* */+/* ftimage.h */+/* */+/* FreeType glyph image formats and default raster interface */+/* (specification). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */+/* 2010 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. */+/* */+/***************************************************************************/++ /*************************************************************************/+ /* */+ /* Note: A `raster' is simply a scan-line converter, used to render */+ /* FT_Outlines into FT_Bitmaps. */+ /* */+ /*************************************************************************/+++#ifndef __FTIMAGE_H__+#define __FTIMAGE_H__+++ /* _STANDALONE_ is from ftgrays.c */+#ifndef _STANDALONE_+#include <ft2build.h>+#endif+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* basic_types */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_Pos */+ /* */+ /* <Description> */+ /* The type FT_Pos is used to store vectorial coordinates. Depending */+ /* on the context, these can represent distances in integer font */+ /* units, or 16.16, or 26.6 fixed float pixel coordinates. */+ /* */+ typedef signed long FT_Pos;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_Vector */+ /* */+ /* <Description> */+ /* A simple structure used to store a 2D vector; coordinates are of */+ /* the FT_Pos type. */+ /* */+ /* <Fields> */+ /* x :: The horizontal coordinate. */+ /* y :: The vertical coordinate. */+ /* */+ typedef struct FT_Vector_+ {+ FT_Pos x;+ FT_Pos y;++ } FT_Vector;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_BBox */+ /* */+ /* <Description> */+ /* A structure used to hold an outline's bounding box, i.e., the */+ /* coordinates of its extrema in the horizontal and vertical */+ /* directions. */+ /* */+ /* <Fields> */+ /* xMin :: The horizontal minimum (left-most). */+ /* */+ /* yMin :: The vertical minimum (bottom-most). */+ /* */+ /* xMax :: The horizontal maximum (right-most). */+ /* */+ /* yMax :: The vertical maximum (top-most). */+ /* */+ /* <Note> */+ /* The bounding box is specified with the coordinates of the lower */+ /* left and the upper right corner. In PostScript, those values are */+ /* often called (llx,lly) and (urx,ury), respectively. */+ /* */+ /* If `yMin' is negative, this value gives the glyph's descender. */+ /* Otherwise, the glyph doesn't descend below the baseline. */+ /* Similarly, if `ymax' is positive, this value gives the glyph's */+ /* ascender. */+ /* */+ /* `xMin' gives the horizontal distance from the glyph's origin to */+ /* the left edge of the glyph's bounding box. If `xMin' is negative, */+ /* the glyph extends to the left of the origin. */+ /* */+ typedef struct FT_BBox_+ {+ FT_Pos xMin, yMin;+ FT_Pos xMax, yMax;++ } FT_BBox;+++ /*************************************************************************/+ /* */+ /* <Enum> */+ /* FT_Pixel_Mode */+ /* */+ /* <Description> */+ /* An enumeration type used to describe the format of pixels in a */+ /* given bitmap. Note that additional formats may be added in the */+ /* future. */+ /* */+ /* <Values> */+ /* FT_PIXEL_MODE_NONE :: */+ /* Value~0 is reserved. */+ /* */+ /* FT_PIXEL_MODE_MONO :: */+ /* A monochrome bitmap, using 1~bit per pixel. Note that pixels */+ /* are stored in most-significant order (MSB), which means that */+ /* the left-most pixel in a byte has value 128. */+ /* */+ /* FT_PIXEL_MODE_GRAY :: */+ /* An 8-bit bitmap, generally used to represent anti-aliased glyph */+ /* images. Each pixel is stored in one byte. Note that the number */+ /* of `gray' levels is stored in the `num_grays' field of the */+ /* @FT_Bitmap structure (it generally is 256). */+ /* */+ /* FT_PIXEL_MODE_GRAY2 :: */+ /* A 2-bit per pixel bitmap, used to represent embedded */+ /* anti-aliased bitmaps in font files according to the OpenType */+ /* specification. We haven't found a single font using this */+ /* format, however. */+ /* */+ /* FT_PIXEL_MODE_GRAY4 :: */+ /* A 4-bit per pixel bitmap, representing embedded anti-aliased */+ /* bitmaps in font files according to the OpenType specification. */+ /* We haven't found a single font using this format, however. */+ /* */+ /* FT_PIXEL_MODE_LCD :: */+ /* An 8-bit bitmap, representing RGB or BGR decimated glyph images */+ /* used for display on LCD displays; the bitmap is three times */+ /* wider than the original glyph image. See also */+ /* @FT_RENDER_MODE_LCD. */+ /* */+ /* FT_PIXEL_MODE_LCD_V :: */+ /* An 8-bit bitmap, representing RGB or BGR decimated glyph images */+ /* used for display on rotated LCD displays; the bitmap is three */+ /* times taller than the original glyph image. See also */+ /* @FT_RENDER_MODE_LCD_V. */+ /* */+ typedef enum FT_Pixel_Mode_+ {+ FT_PIXEL_MODE_NONE = 0,+ FT_PIXEL_MODE_MONO,+ FT_PIXEL_MODE_GRAY,+ FT_PIXEL_MODE_GRAY2,+ FT_PIXEL_MODE_GRAY4,+ FT_PIXEL_MODE_LCD,+ FT_PIXEL_MODE_LCD_V,++ FT_PIXEL_MODE_MAX /* do not remove */++ } FT_Pixel_Mode;+++ /*************************************************************************/+ /* */+ /* <Enum> */+ /* ft_pixel_mode_xxx */+ /* */+ /* <Description> */+ /* A list of deprecated constants. Use the corresponding */+ /* @FT_Pixel_Mode values instead. */+ /* */+ /* <Values> */+ /* ft_pixel_mode_none :: See @FT_PIXEL_MODE_NONE. */+ /* ft_pixel_mode_mono :: See @FT_PIXEL_MODE_MONO. */+ /* ft_pixel_mode_grays :: See @FT_PIXEL_MODE_GRAY. */+ /* ft_pixel_mode_pal2 :: See @FT_PIXEL_MODE_GRAY2. */+ /* ft_pixel_mode_pal4 :: See @FT_PIXEL_MODE_GRAY4. */+ /* */+#define ft_pixel_mode_none FT_PIXEL_MODE_NONE+#define ft_pixel_mode_mono FT_PIXEL_MODE_MONO+#define ft_pixel_mode_grays FT_PIXEL_MODE_GRAY+#define ft_pixel_mode_pal2 FT_PIXEL_MODE_GRAY2+#define ft_pixel_mode_pal4 FT_PIXEL_MODE_GRAY4++ /* */++#if 0++ /*************************************************************************/+ /* */+ /* <Enum> */+ /* FT_Palette_Mode */+ /* */+ /* <Description> */+ /* THIS TYPE IS DEPRECATED. DO NOT USE IT! */+ /* */+ /* An enumeration type to describe the format of a bitmap palette, */+ /* used with ft_pixel_mode_pal4 and ft_pixel_mode_pal8. */+ /* */+ /* <Values> */+ /* ft_palette_mode_rgb :: The palette is an array of 3-byte RGB */+ /* records. */+ /* */+ /* ft_palette_mode_rgba :: The palette is an array of 4-byte RGBA */+ /* records. */+ /* */+ /* <Note> */+ /* As ft_pixel_mode_pal2, pal4 and pal8 are currently unused by */+ /* FreeType, these types are not handled by the library itself. */+ /* */+ typedef enum FT_Palette_Mode_+ {+ ft_palette_mode_rgb = 0,+ ft_palette_mode_rgba,++ ft_palette_mode_max /* do not remove */++ } FT_Palette_Mode;++ /* */++#endif+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_Bitmap */+ /* */+ /* <Description> */+ /* A structure used to describe a bitmap or pixmap to the raster. */+ /* Note that we now manage pixmaps of various depths through the */+ /* `pixel_mode' field. */+ /* */+ /* <Fields> */+ /* rows :: The number of bitmap rows. */+ /* */+ /* width :: The number of pixels in bitmap row. */+ /* */+ /* pitch :: The pitch's absolute value is the number of bytes */+ /* taken by one bitmap row, including padding. */+ /* However, the pitch is positive when the bitmap has */+ /* a `down' flow, and negative when it has an `up' */+ /* flow. In all cases, the pitch is an offset to add */+ /* to a bitmap pointer in order to go down one row. */+ /* */+ /* Note that `padding' means the alignment of a */+ /* bitmap to a byte border, and FreeType functions */+ /* normally align to the smallest possible integer */+ /* value. */+ /* */+ /* For the B/W rasterizer, `pitch' is always an even */+ /* number. */+ /* */+ /* To change the pitch of a bitmap (say, to make it a */+ /* multiple of 4), use @FT_Bitmap_Convert. */+ /* Alternatively, you might use callback functions to */+ /* directly render to the application's surface; see */+ /* the file `example2.cpp' in the tutorial for a */+ /* demonstration. */+ /* */+ /* buffer :: A typeless pointer to the bitmap buffer. This */+ /* value should be aligned on 32-bit boundaries in */+ /* most cases. */+ /* */+ /* num_grays :: This field is only used with */+ /* @FT_PIXEL_MODE_GRAY; it gives the number of gray */+ /* levels used in the bitmap. */+ /* */+ /* pixel_mode :: The pixel mode, i.e., how pixel bits are stored. */+ /* See @FT_Pixel_Mode for possible values. */+ /* */+ /* palette_mode :: This field is intended for paletted pixel modes; */+ /* it indicates how the palette is stored. Not */+ /* used currently. */+ /* */+ /* palette :: A typeless pointer to the bitmap palette; this */+ /* field is intended for paletted pixel modes. Not */+ /* used currently. */+ /* */+ /* <Note> */+ /* For now, the only pixel modes supported by FreeType are mono and */+ /* grays. However, drivers might be added in the future to support */+ /* more `colorful' options. */+ /* */+ typedef struct FT_Bitmap_+ {+ int rows;+ int width;+ int pitch;+ unsigned char* buffer;+ short num_grays;+ char pixel_mode;+ char palette_mode;+ void* palette;++ } FT_Bitmap;+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* outline_processing */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_Outline */+ /* */+ /* <Description> */+ /* This structure is used to describe an outline to the scan-line */+ /* converter. */+ /* */+ /* <Fields> */+ /* n_contours :: The number of contours in the outline. */+ /* */+ /* n_points :: The number of points in the outline. */+ /* */+ /* points :: A pointer to an array of `n_points' @FT_Vector */+ /* elements, giving the outline's point coordinates. */+ /* */+ /* tags :: A pointer to an array of `n_points' chars, giving */+ /* each outline point's type. */+ /* */+ /* If bit~0 is unset, the point is `off' the curve, */+ /* i.e., a Bézier control point, while it is `on' if */+ /* set. */+ /* */+ /* Bit~1 is meaningful for `off' points only. If set, */+ /* it indicates a third-order Bézier arc control point; */+ /* and a second-order control point if unset. */+ /* */+ /* If bit~2 is set, bits 5-7 contain the drop-out mode */+ /* (as defined in the OpenType specification; the value */+ /* is the same as the argument to the SCANMODE */+ /* instruction). */+ /* */+ /* Bits 3 and~4 are reserved for internal purposes. */+ /* */+ /* contours :: An array of `n_contours' shorts, giving the end */+ /* point of each contour within the outline. For */+ /* example, the first contour is defined by the points */+ /* `0' to `contours[0]', the second one is defined by */+ /* the points `contours[0]+1' to `contours[1]', etc. */+ /* */+ /* flags :: A set of bit flags used to characterize the outline */+ /* and give hints to the scan-converter and hinter on */+ /* how to convert/grid-fit it. See @FT_OUTLINE_FLAGS. */+ /* */+ /* <Note> */+ /* The B/W rasterizer only checks bit~2 in the `tags' array for the */+ /* first point of each contour. The drop-out mode as given with */+ /* @FT_OUTLINE_IGNORE_DROPOUTS, @FT_OUTLINE_SMART_DROPOUTS, and */+ /* @FT_OUTLINE_INCLUDE_STUBS in `flags' is then overridden. */+ /* */+ typedef struct FT_Outline_+ {+ short n_contours; /* number of contours in glyph */+ short n_points; /* number of points in the glyph */++ FT_Vector* points; /* the outline's points */+ char* tags; /* the points flags */+ short* contours; /* the contour end points */++ int flags; /* outline masks */++ } FT_Outline;++ /* Following limits must be consistent with */+ /* FT_Outline.{n_contours,n_points} */+#define FT_OUTLINE_CONTOURS_MAX SHRT_MAX+#define FT_OUTLINE_POINTS_MAX SHRT_MAX+++ /*************************************************************************/+ /* */+ /* <Enum> */+ /* FT_OUTLINE_FLAGS */+ /* */+ /* <Description> */+ /* A list of bit-field constants use for the flags in an outline's */+ /* `flags' field. */+ /* */+ /* <Values> */+ /* FT_OUTLINE_NONE :: */+ /* Value~0 is reserved. */+ /* */+ /* FT_OUTLINE_OWNER :: */+ /* If set, this flag indicates that the outline's field arrays */+ /* (i.e., `points', `flags', and `contours') are `owned' by the */+ /* outline object, and should thus be freed when it is destroyed. */+ /* */+ /* FT_OUTLINE_EVEN_ODD_FILL :: */+ /* By default, outlines are filled using the non-zero winding rule. */+ /* If set to 1, the outline will be filled using the even-odd fill */+ /* rule (only works with the smooth rasterizer). */+ /* */+ /* FT_OUTLINE_REVERSE_FILL :: */+ /* By default, outside contours of an outline are oriented in */+ /* clock-wise direction, as defined in the TrueType specification. */+ /* This flag is set if the outline uses the opposite direction */+ /* (typically for Type~1 fonts). This flag is ignored by the scan */+ /* converter. */+ /* */+ /* FT_OUTLINE_IGNORE_DROPOUTS :: */+ /* By default, the scan converter will try to detect drop-outs in */+ /* an outline and correct the glyph bitmap to ensure consistent */+ /* shape continuity. If set, this flag hints the scan-line */+ /* converter to ignore such cases. See below for more information. */+ /* */+ /* FT_OUTLINE_SMART_DROPOUTS :: */+ /* Select smart dropout control. If unset, use simple dropout */+ /* control. Ignored if @FT_OUTLINE_IGNORE_DROPOUTS is set. See */+ /* below for more information. */+ /* */+ /* FT_OUTLINE_INCLUDE_STUBS :: */+ /* If set, turn pixels on for `stubs', otherwise exclude them. */+ /* Ignored if @FT_OUTLINE_IGNORE_DROPOUTS is set. See below for */+ /* more information. */+ /* */+ /* FT_OUTLINE_HIGH_PRECISION :: */+ /* This flag indicates that the scan-line converter should try to */+ /* convert this outline to bitmaps with the highest possible */+ /* quality. It is typically set for small character sizes. Note */+ /* that this is only a hint that might be completely ignored by a */+ /* given scan-converter. */+ /* */+ /* FT_OUTLINE_SINGLE_PASS :: */+ /* This flag is set to force a given scan-converter to only use a */+ /* single pass over the outline to render a bitmap glyph image. */+ /* Normally, it is set for very large character sizes. It is only */+ /* a hint that might be completely ignored by a given */+ /* scan-converter. */+ /* */+ /* <Note> */+ /* The flags @FT_OUTLINE_IGNORE_DROPOUTS, @FT_OUTLINE_SMART_DROPOUTS, */+ /* and @FT_OUTLINE_INCLUDE_STUBS are ignored by the smooth */+ /* rasterizer. */+ /* */+ /* There exists a second mechanism to pass the drop-out mode to the */+ /* B/W rasterizer; see the `tags' field in @FT_Outline. */+ /* */+ /* Please refer to the description of the `SCANTYPE' instruction in */+ /* the OpenType specification (in file `ttinst1.doc') how simple */+ /* drop-outs, smart drop-outs, and stubs are defined. */+ /* */+#define FT_OUTLINE_NONE 0x0+#define FT_OUTLINE_OWNER 0x1+#define FT_OUTLINE_EVEN_ODD_FILL 0x2+#define FT_OUTLINE_REVERSE_FILL 0x4+#define FT_OUTLINE_IGNORE_DROPOUTS 0x8+#define FT_OUTLINE_SMART_DROPOUTS 0x10+#define FT_OUTLINE_INCLUDE_STUBS 0x20++#define FT_OUTLINE_HIGH_PRECISION 0x100+#define FT_OUTLINE_SINGLE_PASS 0x200+++ /*************************************************************************+ *+ * @enum:+ * ft_outline_flags+ *+ * @description:+ * These constants are deprecated. Please use the corresponding+ * @FT_OUTLINE_FLAGS values.+ *+ * @values:+ * ft_outline_none :: See @FT_OUTLINE_NONE.+ * ft_outline_owner :: See @FT_OUTLINE_OWNER.+ * ft_outline_even_odd_fill :: See @FT_OUTLINE_EVEN_ODD_FILL.+ * ft_outline_reverse_fill :: See @FT_OUTLINE_REVERSE_FILL.+ * ft_outline_ignore_dropouts :: See @FT_OUTLINE_IGNORE_DROPOUTS.+ * ft_outline_high_precision :: See @FT_OUTLINE_HIGH_PRECISION.+ * ft_outline_single_pass :: See @FT_OUTLINE_SINGLE_PASS.+ */+#define ft_outline_none FT_OUTLINE_NONE+#define ft_outline_owner FT_OUTLINE_OWNER+#define ft_outline_even_odd_fill FT_OUTLINE_EVEN_ODD_FILL+#define ft_outline_reverse_fill FT_OUTLINE_REVERSE_FILL+#define ft_outline_ignore_dropouts FT_OUTLINE_IGNORE_DROPOUTS+#define ft_outline_high_precision FT_OUTLINE_HIGH_PRECISION+#define ft_outline_single_pass FT_OUTLINE_SINGLE_PASS++ /* */++#define FT_CURVE_TAG( flag ) ( flag & 3 )++#define FT_CURVE_TAG_ON 1+#define FT_CURVE_TAG_CONIC 0+#define FT_CURVE_TAG_CUBIC 2++#define FT_CURVE_TAG_HAS_SCANMODE 4++#define FT_CURVE_TAG_TOUCH_X 8 /* reserved for the TrueType hinter */+#define FT_CURVE_TAG_TOUCH_Y 16 /* reserved for the TrueType hinter */++#define FT_CURVE_TAG_TOUCH_BOTH ( FT_CURVE_TAG_TOUCH_X | \+ FT_CURVE_TAG_TOUCH_Y )++#define FT_Curve_Tag_On FT_CURVE_TAG_ON+#define FT_Curve_Tag_Conic FT_CURVE_TAG_CONIC+#define FT_Curve_Tag_Cubic FT_CURVE_TAG_CUBIC+#define FT_Curve_Tag_Touch_X FT_CURVE_TAG_TOUCH_X+#define FT_Curve_Tag_Touch_Y FT_CURVE_TAG_TOUCH_Y+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* FT_Outline_MoveToFunc */+ /* */+ /* <Description> */+ /* A function pointer type used to describe the signature of a `move */+ /* to' function during outline walking/decomposition. */+ /* */+ /* A `move to' is emitted to start a new contour in an outline. */+ /* */+ /* <Input> */+ /* to :: A pointer to the target point of the `move to'. */+ /* */+ /* user :: A typeless pointer which is passed from the caller of the */+ /* decomposition function. */+ /* */+ /* <Return> */+ /* Error code. 0~means success. */+ /* */+ typedef int+ (*FT_Outline_MoveToFunc)( const FT_Vector* to,+ void* user );++#define FT_Outline_MoveTo_Func FT_Outline_MoveToFunc+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* FT_Outline_LineToFunc */+ /* */+ /* <Description> */+ /* A function pointer type used to describe the signature of a `line */+ /* to' function during outline walking/decomposition. */+ /* */+ /* A `line to' is emitted to indicate a segment in the outline. */+ /* */+ /* <Input> */+ /* to :: A pointer to the target point of the `line to'. */+ /* */+ /* user :: A typeless pointer which is passed from the caller of the */+ /* decomposition function. */+ /* */+ /* <Return> */+ /* Error code. 0~means success. */+ /* */+ typedef int+ (*FT_Outline_LineToFunc)( const FT_Vector* to,+ void* user );++#define FT_Outline_LineTo_Func FT_Outline_LineToFunc+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* FT_Outline_ConicToFunc */+ /* */+ /* <Description> */+ /* A function pointer type used to describe the signature of a `conic */+ /* to' function during outline walking or decomposition. */+ /* */+ /* A `conic to' is emitted to indicate a second-order Bézier arc in */+ /* the outline. */+ /* */+ /* <Input> */+ /* control :: An intermediate control point between the last position */+ /* and the new target in `to'. */+ /* */+ /* to :: A pointer to the target end point of the conic arc. */+ /* */+ /* user :: A typeless pointer which is passed from the caller of */+ /* the decomposition function. */+ /* */+ /* <Return> */+ /* Error code. 0~means success. */+ /* */+ typedef int+ (*FT_Outline_ConicToFunc)( const FT_Vector* control,+ const FT_Vector* to,+ void* user );++#define FT_Outline_ConicTo_Func FT_Outline_ConicToFunc+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* FT_Outline_CubicToFunc */+ /* */+ /* <Description> */+ /* A function pointer type used to describe the signature of a `cubic */+ /* to' function during outline walking or decomposition. */+ /* */+ /* A `cubic to' is emitted to indicate a third-order Bézier arc. */+ /* */+ /* <Input> */+ /* control1 :: A pointer to the first Bézier control point. */+ /* */+ /* control2 :: A pointer to the second Bézier control point. */+ /* */+ /* to :: A pointer to the target end point. */+ /* */+ /* user :: A typeless pointer which is passed from the caller of */+ /* the decomposition function. */+ /* */+ /* <Return> */+ /* Error code. 0~means success. */+ /* */+ typedef int+ (*FT_Outline_CubicToFunc)( const FT_Vector* control1,+ const FT_Vector* control2,+ const FT_Vector* to,+ void* user );++#define FT_Outline_CubicTo_Func FT_Outline_CubicToFunc+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_Outline_Funcs */+ /* */+ /* <Description> */+ /* A structure to hold various function pointers used during outline */+ /* decomposition in order to emit segments, conic, and cubic Béziers. */+ /* */+ /* <Fields> */+ /* move_to :: The `move to' emitter. */+ /* */+ /* line_to :: The segment emitter. */+ /* */+ /* conic_to :: The second-order Bézier arc emitter. */+ /* */+ /* cubic_to :: The third-order Bézier arc emitter. */+ /* */+ /* shift :: The shift that is applied to coordinates before they */+ /* are sent to the emitter. */+ /* */+ /* delta :: The delta that is applied to coordinates before they */+ /* are sent to the emitter, but after the shift. */+ /* */+ /* <Note> */+ /* The point coordinates sent to the emitters are the transformed */+ /* version of the original coordinates (this is important for high */+ /* accuracy during scan-conversion). The transformation is simple: */+ /* */+ /* { */+ /* x' = (x << shift) - delta */+ /* y' = (x << shift) - delta */+ /* } */+ /* */+ /* Set the values of `shift' and `delta' to~0 to get the original */+ /* point coordinates. */+ /* */+ typedef struct FT_Outline_Funcs_+ {+ FT_Outline_MoveToFunc move_to;+ FT_Outline_LineToFunc line_to;+ FT_Outline_ConicToFunc conic_to;+ FT_Outline_CubicToFunc cubic_to;++ int shift;+ FT_Pos delta;++ } FT_Outline_Funcs;+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* basic_types */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Macro> */+ /* FT_IMAGE_TAG */+ /* */+ /* <Description> */+ /* This macro converts four-letter tags to an unsigned long type. */+ /* */+ /* <Note> */+ /* Since many 16-bit compilers don't like 32-bit enumerations, you */+ /* should redefine this macro in case of problems to something like */+ /* this: */+ /* */+ /* { */+ /* #define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 ) value */+ /* } */+ /* */+ /* to get a simple enumeration without assigning special numbers. */+ /* */+#ifndef FT_IMAGE_TAG+#define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 ) \+ value = ( ( (unsigned long)_x1 << 24 ) | \+ ( (unsigned long)_x2 << 16 ) | \+ ( (unsigned long)_x3 << 8 ) | \+ (unsigned long)_x4 )+#endif /* FT_IMAGE_TAG */+++ /*************************************************************************/+ /* */+ /* <Enum> */+ /* FT_Glyph_Format */+ /* */+ /* <Description> */+ /* An enumeration type used to describe the format of a given glyph */+ /* image. Note that this version of FreeType only supports two image */+ /* formats, even though future font drivers will be able to register */+ /* their own format. */+ /* */+ /* <Values> */+ /* FT_GLYPH_FORMAT_NONE :: */+ /* The value~0 is reserved. */+ /* */+ /* FT_GLYPH_FORMAT_COMPOSITE :: */+ /* The glyph image is a composite of several other images. This */+ /* format is _only_ used with @FT_LOAD_NO_RECURSE, and is used to */+ /* report compound glyphs (like accented characters). */+ /* */+ /* FT_GLYPH_FORMAT_BITMAP :: */+ /* The glyph image is a bitmap, and can be described as an */+ /* @FT_Bitmap. You generally need to access the `bitmap' field of */+ /* the @FT_GlyphSlotRec structure to read it. */+ /* */+ /* FT_GLYPH_FORMAT_OUTLINE :: */+ /* The glyph image is a vectorial outline made of line segments */+ /* and Bézier arcs; it can be described as an @FT_Outline; you */+ /* generally want to access the `outline' field of the */+ /* @FT_GlyphSlotRec structure to read it. */+ /* */+ /* FT_GLYPH_FORMAT_PLOTTER :: */+ /* The glyph image is a vectorial path with no inside and outside */+ /* contours. Some Type~1 fonts, like those in the Hershey family, */+ /* contain glyphs in this format. These are described as */+ /* @FT_Outline, but FreeType isn't currently capable of rendering */+ /* them correctly. */+ /* */+ typedef enum FT_Glyph_Format_+ {+ FT_IMAGE_TAG( FT_GLYPH_FORMAT_NONE, 0, 0, 0, 0 ),++ FT_IMAGE_TAG( FT_GLYPH_FORMAT_COMPOSITE, 'c', 'o', 'm', 'p' ),+ FT_IMAGE_TAG( FT_GLYPH_FORMAT_BITMAP, 'b', 'i', 't', 's' ),+ FT_IMAGE_TAG( FT_GLYPH_FORMAT_OUTLINE, 'o', 'u', 't', 'l' ),+ FT_IMAGE_TAG( FT_GLYPH_FORMAT_PLOTTER, 'p', 'l', 'o', 't' )++ } FT_Glyph_Format;+++ /*************************************************************************/+ /* */+ /* <Enum> */+ /* ft_glyph_format_xxx */+ /* */+ /* <Description> */+ /* A list of deprecated constants. Use the corresponding */+ /* @FT_Glyph_Format values instead. */+ /* */+ /* <Values> */+ /* ft_glyph_format_none :: See @FT_GLYPH_FORMAT_NONE. */+ /* ft_glyph_format_composite :: See @FT_GLYPH_FORMAT_COMPOSITE. */+ /* ft_glyph_format_bitmap :: See @FT_GLYPH_FORMAT_BITMAP. */+ /* ft_glyph_format_outline :: See @FT_GLYPH_FORMAT_OUTLINE. */+ /* ft_glyph_format_plotter :: See @FT_GLYPH_FORMAT_PLOTTER. */+ /* */+#define ft_glyph_format_none FT_GLYPH_FORMAT_NONE+#define ft_glyph_format_composite FT_GLYPH_FORMAT_COMPOSITE+#define ft_glyph_format_bitmap FT_GLYPH_FORMAT_BITMAP+#define ft_glyph_format_outline FT_GLYPH_FORMAT_OUTLINE+#define ft_glyph_format_plotter FT_GLYPH_FORMAT_PLOTTER+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** R A S T E R D E F I N I T I O N S *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* A raster is a scan converter, in charge of rendering an outline into */+ /* a a bitmap. This section contains the public API for rasters. */+ /* */+ /* Note that in FreeType 2, all rasters are now encapsulated within */+ /* specific modules called `renderers'. See `freetype/ftrender.h' for */+ /* more details on renderers. */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* raster */+ /* */+ /* <Title> */+ /* Scanline Converter */+ /* */+ /* <Abstract> */+ /* How vectorial outlines are converted into bitmaps and pixmaps. */+ /* */+ /* <Description> */+ /* This section contains technical definitions. */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_Raster */+ /* */+ /* <Description> */+ /* A handle (pointer) to a raster object. Each object can be used */+ /* independently to convert an outline into a bitmap or pixmap. */+ /* */+ typedef struct FT_RasterRec_* FT_Raster;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_Span */+ /* */+ /* <Description> */+ /* A structure used to model a single span of gray (or black) pixels */+ /* when rendering a monochrome or anti-aliased bitmap. */+ /* */+ /* <Fields> */+ /* x :: The span's horizontal start position. */+ /* */+ /* len :: The span's length in pixels. */+ /* */+ /* coverage :: The span color/coverage, ranging from 0 (background) */+ /* to 255 (foreground). Only used for anti-aliased */+ /* rendering. */+ /* */+ /* <Note> */+ /* This structure is used by the span drawing callback type named */+ /* @FT_SpanFunc which takes the y~coordinate of the span as a */+ /* a parameter. */+ /* */+ /* The coverage value is always between 0 and 255. If you want less */+ /* gray values, the callback function has to reduce them. */+ /* */+ typedef struct FT_Span_+ {+ short x;+ unsigned short len;+ unsigned char coverage;++ } FT_Span;+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* FT_SpanFunc */+ /* */+ /* <Description> */+ /* A function used as a call-back by the anti-aliased renderer in */+ /* order to let client applications draw themselves the gray pixel */+ /* spans on each scan line. */+ /* */+ /* <Input> */+ /* y :: The scanline's y~coordinate. */+ /* */+ /* count :: The number of spans to draw on this scanline. */+ /* */+ /* spans :: A table of `count' spans to draw on the scanline. */+ /* */+ /* user :: User-supplied data that is passed to the callback. */+ /* */+ /* <Note> */+ /* This callback allows client applications to directly render the */+ /* gray spans of the anti-aliased bitmap to any kind of surfaces. */+ /* */+ /* This can be used to write anti-aliased outlines directly to a */+ /* given background bitmap, and even perform translucency. */+ /* */+ /* Note that the `count' field cannot be greater than a fixed value */+ /* defined by the `FT_MAX_GRAY_SPANS' configuration macro in */+ /* `ftoption.h'. By default, this value is set to~32, which means */+ /* that if there are more than 32~spans on a given scanline, the */+ /* callback is called several times with the same `y' parameter in */+ /* order to draw all callbacks. */+ /* */+ /* Otherwise, the callback is only called once per scan-line, and */+ /* only for those scanlines that do have `gray' pixels on them. */+ /* */+ typedef void+ (*FT_SpanFunc)( int y,+ int count,+ const FT_Span* spans,+ void* user );++#define FT_Raster_Span_Func FT_SpanFunc+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* FT_Raster_BitTest_Func */+ /* */+ /* <Description> */+ /* THIS TYPE IS DEPRECATED. DO NOT USE IT. */+ /* */+ /* A function used as a call-back by the monochrome scan-converter */+ /* to test whether a given target pixel is already set to the drawing */+ /* `color'. These tests are crucial to implement drop-out control */+ /* per-se the TrueType spec. */+ /* */+ /* <Input> */+ /* y :: The pixel's y~coordinate. */+ /* */+ /* x :: The pixel's x~coordinate. */+ /* */+ /* user :: User-supplied data that is passed to the callback. */+ /* */+ /* <Return> */+ /* 1~if the pixel is `set', 0~otherwise. */+ /* */+ typedef int+ (*FT_Raster_BitTest_Func)( int y,+ int x,+ void* user );+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* FT_Raster_BitSet_Func */+ /* */+ /* <Description> */+ /* THIS TYPE IS DEPRECATED. DO NOT USE IT. */+ /* */+ /* A function used as a call-back by the monochrome scan-converter */+ /* to set an individual target pixel. This is crucial to implement */+ /* drop-out control according to the TrueType specification. */+ /* */+ /* <Input> */+ /* y :: The pixel's y~coordinate. */+ /* */+ /* x :: The pixel's x~coordinate. */+ /* */+ /* user :: User-supplied data that is passed to the callback. */+ /* */+ /* <Return> */+ /* 1~if the pixel is `set', 0~otherwise. */+ /* */+ typedef void+ (*FT_Raster_BitSet_Func)( int y,+ int x,+ void* user );+++ /*************************************************************************/+ /* */+ /* <Enum> */+ /* FT_RASTER_FLAG_XXX */+ /* */+ /* <Description> */+ /* A list of bit flag constants as used in the `flags' field of a */+ /* @FT_Raster_Params structure. */+ /* */+ /* <Values> */+ /* FT_RASTER_FLAG_DEFAULT :: This value is 0. */+ /* */+ /* FT_RASTER_FLAG_AA :: This flag is set to indicate that an */+ /* anti-aliased glyph image should be */+ /* generated. Otherwise, it will be */+ /* monochrome (1-bit). */+ /* */+ /* FT_RASTER_FLAG_DIRECT :: This flag is set to indicate direct */+ /* rendering. In this mode, client */+ /* applications must provide their own span */+ /* callback. This lets them directly */+ /* draw or compose over an existing bitmap. */+ /* If this bit is not set, the target */+ /* pixmap's buffer _must_ be zeroed before */+ /* rendering. */+ /* */+ /* Note that for now, direct rendering is */+ /* only possible with anti-aliased glyphs. */+ /* */+ /* FT_RASTER_FLAG_CLIP :: This flag is only used in direct */+ /* rendering mode. If set, the output will */+ /* be clipped to a box specified in the */+ /* `clip_box' field of the */+ /* @FT_Raster_Params structure. */+ /* */+ /* Note that by default, the glyph bitmap */+ /* is clipped to the target pixmap, except */+ /* in direct rendering mode where all spans */+ /* are generated if no clipping box is set. */+ /* */+#define FT_RASTER_FLAG_DEFAULT 0x0+#define FT_RASTER_FLAG_AA 0x1+#define FT_RASTER_FLAG_DIRECT 0x2+#define FT_RASTER_FLAG_CLIP 0x4++ /* deprecated */+#define ft_raster_flag_default FT_RASTER_FLAG_DEFAULT+#define ft_raster_flag_aa FT_RASTER_FLAG_AA+#define ft_raster_flag_direct FT_RASTER_FLAG_DIRECT+#define ft_raster_flag_clip FT_RASTER_FLAG_CLIP+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_Raster_Params */+ /* */+ /* <Description> */+ /* A structure to hold the arguments used by a raster's render */+ /* function. */+ /* */+ /* <Fields> */+ /* target :: The target bitmap. */+ /* */+ /* source :: A pointer to the source glyph image (e.g., an */+ /* @FT_Outline). */+ /* */+ /* flags :: The rendering flags. */+ /* */+ /* gray_spans :: The gray span drawing callback. */+ /* */+ /* black_spans :: The black span drawing callback. UNIMPLEMENTED! */+ /* */+ /* bit_test :: The bit test callback. UNIMPLEMENTED! */+ /* */+ /* bit_set :: The bit set callback. UNIMPLEMENTED! */+ /* */+ /* user :: User-supplied data that is passed to each drawing */+ /* callback. */+ /* */+ /* clip_box :: An optional clipping box. It is only used in */+ /* direct rendering mode. Note that coordinates here */+ /* should be expressed in _integer_ pixels (and not in */+ /* 26.6 fixed-point units). */+ /* */+ /* <Note> */+ /* An anti-aliased glyph bitmap is drawn if the @FT_RASTER_FLAG_AA */+ /* bit flag is set in the `flags' field, otherwise a monochrome */+ /* bitmap is generated. */+ /* */+ /* If the @FT_RASTER_FLAG_DIRECT bit flag is set in `flags', the */+ /* raster will call the `gray_spans' callback to draw gray pixel */+ /* spans, in the case of an aa glyph bitmap, it will call */+ /* `black_spans', and `bit_test' and `bit_set' in the case of a */+ /* monochrome bitmap. This allows direct composition over a */+ /* pre-existing bitmap through user-provided callbacks to perform the */+ /* span drawing/composition. */+ /* */+ /* Note that the `bit_test' and `bit_set' callbacks are required when */+ /* rendering a monochrome bitmap, as they are crucial to implement */+ /* correct drop-out control as defined in the TrueType specification. */+ /* */+ typedef struct FT_Raster_Params_+ {+ const FT_Bitmap* target;+ const void* source;+ int flags;+ FT_SpanFunc gray_spans;+ FT_SpanFunc black_spans; /* doesn't work! */+ FT_Raster_BitTest_Func bit_test; /* doesn't work! */+ FT_Raster_BitSet_Func bit_set; /* doesn't work! */+ void* user;+ FT_BBox clip_box;++ } FT_Raster_Params;+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* FT_Raster_NewFunc */+ /* */+ /* <Description> */+ /* A function used to create a new raster object. */+ /* */+ /* <Input> */+ /* memory :: A handle to the memory allocator. */+ /* */+ /* <Output> */+ /* raster :: A handle to the new raster object. */+ /* */+ /* <Return> */+ /* Error code. 0~means success. */+ /* */+ /* <Note> */+ /* The `memory' parameter is a typeless pointer in order to avoid */+ /* un-wanted dependencies on the rest of the FreeType code. In */+ /* practice, it is an @FT_Memory object, i.e., a handle to the */+ /* standard FreeType memory allocator. However, this field can be */+ /* completely ignored by a given raster implementation. */+ /* */+ typedef int+ (*FT_Raster_NewFunc)( void* memory,+ FT_Raster* raster );++#define FT_Raster_New_Func FT_Raster_NewFunc+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* FT_Raster_DoneFunc */+ /* */+ /* <Description> */+ /* A function used to destroy a given raster object. */+ /* */+ /* <Input> */+ /* raster :: A handle to the raster object. */+ /* */+ typedef void+ (*FT_Raster_DoneFunc)( FT_Raster raster );++#define FT_Raster_Done_Func FT_Raster_DoneFunc+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* FT_Raster_ResetFunc */+ /* */+ /* <Description> */+ /* FreeType provides an area of memory called the `render pool', */+ /* available to all registered rasters. This pool can be freely used */+ /* during a given scan-conversion but is shared by all rasters. Its */+ /* content is thus transient. */+ /* */+ /* This function is called each time the render pool changes, or just */+ /* after a new raster object is created. */+ /* */+ /* <Input> */+ /* raster :: A handle to the new raster object. */+ /* */+ /* pool_base :: The address in memory of the render pool. */+ /* */+ /* pool_size :: The size in bytes of the render pool. */+ /* */+ /* <Note> */+ /* Rasters can ignore the render pool and rely on dynamic memory */+ /* allocation if they want to (a handle to the memory allocator is */+ /* passed to the raster constructor). However, this is not */+ /* recommended for efficiency purposes. */+ /* */+ typedef void+ (*FT_Raster_ResetFunc)( FT_Raster raster,+ unsigned char* pool_base,+ unsigned long pool_size );++#define FT_Raster_Reset_Func FT_Raster_ResetFunc+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* FT_Raster_SetModeFunc */+ /* */+ /* <Description> */+ /* This function is a generic facility to change modes or attributes */+ /* in a given raster. This can be used for debugging purposes, or */+ /* simply to allow implementation-specific `features' in a given */+ /* raster module. */+ /* */+ /* <Input> */+ /* raster :: A handle to the new raster object. */+ /* */+ /* mode :: A 4-byte tag used to name the mode or property. */+ /* */+ /* args :: A pointer to the new mode/property to use. */+ /* */+ typedef int+ (*FT_Raster_SetModeFunc)( FT_Raster raster,+ unsigned long mode,+ void* args );++#define FT_Raster_Set_Mode_Func FT_Raster_SetModeFunc+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* FT_Raster_RenderFunc */+ /* */+ /* <Description> */+ /* Invoke a given raster to scan-convert a given glyph image into a */+ /* target bitmap. */+ /* */+ /* <Input> */+ /* raster :: A handle to the raster object. */+ /* */+ /* params :: A pointer to an @FT_Raster_Params structure used to */+ /* store the rendering parameters. */+ /* */+ /* <Return> */+ /* Error code. 0~means success. */+ /* */+ /* <Note> */+ /* The exact format of the source image depends on the raster's glyph */+ /* format defined in its @FT_Raster_Funcs structure. It can be an */+ /* @FT_Outline or anything else in order to support a large array of */+ /* glyph formats. */+ /* */+ /* Note also that the render function can fail and return a */+ /* `FT_Err_Unimplemented_Feature' error code if the raster used does */+ /* not support direct composition. */+ /* */+ /* XXX: For now, the standard raster doesn't support direct */+ /* composition but this should change for the final release (see */+ /* the files `demos/src/ftgrays.c' and `demos/src/ftgrays2.c' */+ /* for examples of distinct implementations which support direct */+ /* composition). */+ /* */+ typedef int+ (*FT_Raster_RenderFunc)( FT_Raster raster,+ const FT_Raster_Params* params );++#define FT_Raster_Render_Func FT_Raster_RenderFunc+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_Raster_Funcs */+ /* */+ /* <Description> */+ /* A structure used to describe a given raster class to the library. */+ /* */+ /* <Fields> */+ /* glyph_format :: The supported glyph format for this raster. */+ /* */+ /* raster_new :: The raster constructor. */+ /* */+ /* raster_reset :: Used to reset the render pool within the raster. */+ /* */+ /* raster_render :: A function to render a glyph into a given bitmap. */+ /* */+ /* raster_done :: The raster destructor. */+ /* */+ typedef struct FT_Raster_Funcs_+ {+ FT_Glyph_Format glyph_format;+ FT_Raster_NewFunc raster_new;+ FT_Raster_ResetFunc raster_reset;+ FT_Raster_SetModeFunc raster_set_mode;+ FT_Raster_RenderFunc raster_render;+ FT_Raster_DoneFunc raster_done;++ } FT_Raster_Funcs;+++ /* */+++FT_END_HEADER++#endif /* __FTIMAGE_H__ */+++/* END */+++/* Local Variables: */+/* coding: utf-8 */+/* End: */
+ include/freetype/ftincrem.h view
@@ -0,0 +1,353 @@+/***************************************************************************/+/* */+/* ftincrem.h */+/* */+/* FreeType incremental loading (specification). */+/* */+/* Copyright 2002, 2003, 2006, 2007, 2008, 2010 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 __FTINCREM_H__+#define __FTINCREM_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+++FT_BEGIN_HEADER++ /***************************************************************************+ *+ * @section:+ * incremental+ *+ * @title:+ * Incremental Loading+ *+ * @abstract:+ * Custom Glyph Loading.+ *+ * @description:+ * This section contains various functions used to perform so-called+ * `incremental' glyph loading. This is a mode where all glyphs loaded+ * from a given @FT_Face are provided by the client application,+ *+ * Apart from that, all other tables are loaded normally from the font+ * file. This mode is useful when FreeType is used within another+ * engine, e.g., a PostScript Imaging Processor.+ *+ * To enable this mode, you must use @FT_Open_Face, passing an+ * @FT_Parameter with the @FT_PARAM_TAG_INCREMENTAL tag and an+ * @FT_Incremental_Interface value. See the comments for+ * @FT_Incremental_InterfaceRec for an example.+ *+ */+++ /***************************************************************************+ *+ * @type:+ * FT_Incremental+ *+ * @description:+ * An opaque type describing a user-provided object used to implement+ * `incremental' glyph loading within FreeType. This is used to support+ * embedded fonts in certain environments (e.g., PostScript interpreters),+ * where the glyph data isn't in the font file, or must be overridden by+ * different values.+ *+ * @note:+ * It is up to client applications to create and implement @FT_Incremental+ * objects, as long as they provide implementations for the methods+ * @FT_Incremental_GetGlyphDataFunc, @FT_Incremental_FreeGlyphDataFunc+ * and @FT_Incremental_GetGlyphMetricsFunc.+ *+ * See the description of @FT_Incremental_InterfaceRec to understand how+ * to use incremental objects with FreeType.+ *+ */+ typedef struct FT_IncrementalRec_* FT_Incremental;+++ /***************************************************************************+ *+ * @struct:+ * FT_Incremental_MetricsRec+ *+ * @description:+ * A small structure used to contain the basic glyph metrics returned+ * by the @FT_Incremental_GetGlyphMetricsFunc method.+ *+ * @fields:+ * bearing_x ::+ * Left bearing, in font units.+ *+ * bearing_y ::+ * Top bearing, in font units.+ *+ * advance ::+ * Horizontal component of glyph advance, in font units.+ *+ * advance_v ::+ * Vertical component of glyph advance, in font units.+ *+ * @note:+ * These correspond to horizontal or vertical metrics depending on the+ * value of the `vertical' argument to the function+ * @FT_Incremental_GetGlyphMetricsFunc.+ *+ */+ typedef struct FT_Incremental_MetricsRec_+ {+ FT_Long bearing_x;+ FT_Long bearing_y;+ FT_Long advance;+ FT_Long advance_v; /* since 2.3.12 */++ } FT_Incremental_MetricsRec;+++ /***************************************************************************+ *+ * @struct:+ * FT_Incremental_Metrics+ *+ * @description:+ * A handle to an @FT_Incremental_MetricsRec structure.+ *+ */+ typedef struct FT_Incremental_MetricsRec_* FT_Incremental_Metrics;+++ /***************************************************************************+ *+ * @type:+ * FT_Incremental_GetGlyphDataFunc+ *+ * @description:+ * A function called by FreeType to access a given glyph's data bytes+ * during @FT_Load_Glyph or @FT_Load_Char if incremental loading is+ * enabled.+ *+ * Note that the format of the glyph's data bytes depends on the font+ * file format. For TrueType, it must correspond to the raw bytes within+ * the `glyf' table. For PostScript formats, it must correspond to the+ * *unencrypted* charstring bytes, without any `lenIV' header. It is+ * undefined for any other format.+ *+ * @input:+ * incremental ::+ * Handle to an opaque @FT_Incremental handle provided by the client+ * application.+ *+ * glyph_index ::+ * Index of relevant glyph.+ *+ * @output:+ * adata ::+ * A structure describing the returned glyph data bytes (which will be+ * accessed as a read-only byte block).+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * If this function returns successfully the method+ * @FT_Incremental_FreeGlyphDataFunc will be called later to release+ * the data bytes.+ *+ * Nested calls to @FT_Incremental_GetGlyphDataFunc can happen for+ * compound glyphs.+ *+ */+ typedef FT_Error+ (*FT_Incremental_GetGlyphDataFunc)( FT_Incremental incremental,+ FT_UInt glyph_index,+ FT_Data* adata );+++ /***************************************************************************+ *+ * @type:+ * FT_Incremental_FreeGlyphDataFunc+ *+ * @description:+ * A function used to release the glyph data bytes returned by a+ * successful call to @FT_Incremental_GetGlyphDataFunc.+ *+ * @input:+ * incremental ::+ * A handle to an opaque @FT_Incremental handle provided by the client+ * application.+ *+ * data ::+ * A structure describing the glyph data bytes (which will be accessed+ * as a read-only byte block).+ *+ */+ typedef void+ (*FT_Incremental_FreeGlyphDataFunc)( FT_Incremental incremental,+ FT_Data* data );+++ /***************************************************************************+ *+ * @type:+ * FT_Incremental_GetGlyphMetricsFunc+ *+ * @description:+ * A function used to retrieve the basic metrics of a given glyph index+ * before accessing its data. This is necessary because, in certain+ * formats like TrueType, the metrics are stored in a different place from+ * the glyph images proper.+ *+ * @input:+ * incremental ::+ * A handle to an opaque @FT_Incremental handle provided by the client+ * application.+ *+ * glyph_index ::+ * Index of relevant glyph.+ *+ * vertical ::+ * If true, return vertical metrics.+ *+ * ametrics ::+ * This parameter is used for both input and output.+ * The original glyph metrics, if any, in font units. If metrics are+ * not available all the values must be set to zero.+ *+ * @output:+ * ametrics ::+ * The replacement glyph metrics in font units.+ *+ */+ typedef FT_Error+ (*FT_Incremental_GetGlyphMetricsFunc)+ ( FT_Incremental incremental,+ FT_UInt glyph_index,+ FT_Bool vertical,+ FT_Incremental_MetricsRec *ametrics );+++ /**************************************************************************+ *+ * @struct:+ * FT_Incremental_FuncsRec+ *+ * @description:+ * A table of functions for accessing fonts that load data+ * incrementally. Used in @FT_Incremental_InterfaceRec.+ *+ * @fields:+ * get_glyph_data ::+ * The function to get glyph data. Must not be null.+ *+ * free_glyph_data ::+ * The function to release glyph data. Must not be null.+ *+ * get_glyph_metrics ::+ * The function to get glyph metrics. May be null if the font does+ * not provide overriding glyph metrics.+ *+ */+ typedef struct FT_Incremental_FuncsRec_+ {+ FT_Incremental_GetGlyphDataFunc get_glyph_data;+ FT_Incremental_FreeGlyphDataFunc free_glyph_data;+ FT_Incremental_GetGlyphMetricsFunc get_glyph_metrics;++ } FT_Incremental_FuncsRec;+++ /***************************************************************************+ *+ * @struct:+ * FT_Incremental_InterfaceRec+ *+ * @description:+ * A structure to be used with @FT_Open_Face to indicate that the user+ * wants to support incremental glyph loading. You should use it with+ * @FT_PARAM_TAG_INCREMENTAL as in the following example:+ *+ * {+ * FT_Incremental_InterfaceRec inc_int;+ * FT_Parameter parameter;+ * FT_Open_Args open_args;+ *+ *+ * // set up incremental descriptor+ * inc_int.funcs = my_funcs;+ * inc_int.object = my_object;+ *+ * // set up optional parameter+ * parameter.tag = FT_PARAM_TAG_INCREMENTAL;+ * parameter.data = &inc_int;+ *+ * // set up FT_Open_Args structure+ * open_args.flags = FT_OPEN_PATHNAME | FT_OPEN_PARAMS;+ * open_args.pathname = my_font_pathname;+ * open_args.num_params = 1;+ * open_args.params = ¶meter; // we use one optional argument+ *+ * // open the font+ * error = FT_Open_Face( library, &open_args, index, &face );+ * ...+ * }+ *+ */+ typedef struct FT_Incremental_InterfaceRec_+ {+ const FT_Incremental_FuncsRec* funcs;+ FT_Incremental object;++ } FT_Incremental_InterfaceRec;+++ /***************************************************************************+ *+ * @type:+ * FT_Incremental_Interface+ *+ * @description:+ * A pointer to an @FT_Incremental_InterfaceRec structure.+ *+ */+ typedef FT_Incremental_InterfaceRec* FT_Incremental_Interface;+++ /***************************************************************************+ *+ * @constant:+ * FT_PARAM_TAG_INCREMENTAL+ *+ * @description:+ * A constant used as the tag of @FT_Parameter structures to indicate+ * an incremental loading object to be used by FreeType.+ *+ */+#define FT_PARAM_TAG_INCREMENTAL FT_MAKE_TAG( 'i', 'n', 'c', 'r' )++ /* */++FT_END_HEADER++#endif /* __FTINCREM_H__ */+++/* END */
+ include/freetype/ftlcdfil.h view
@@ -0,0 +1,213 @@+/***************************************************************************/+/* */+/* ftlcdfil.h */+/* */+/* FreeType API for color filtering of subpixel bitmap glyphs */+/* (specification). */+/* */+/* Copyright 2006, 2007, 2008, 2010 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 __FT_LCD_FILTER_H__+#define __FT_LCD_FILTER_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+++FT_BEGIN_HEADER++ /***************************************************************************+ *+ * @section:+ * lcd_filtering+ *+ * @title:+ * LCD Filtering+ *+ * @abstract:+ * Reduce color fringes of LCD-optimized 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+ * which would occur with unfiltered rendering.+ *+ * 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.+ */+++ /****************************************************************************+ *+ * @enum:+ * FT_LcdFilter+ *+ * @description:+ * A list of values to identify various types of LCD filters.+ *+ * @values:+ * FT_LCD_FILTER_NONE ::+ * Do not perform filtering. When used with subpixel rendering, this+ * results in sometimes severe color fringes.+ *+ * FT_LCD_FILTER_DEFAULT ::+ * The default filter reduces color fringes considerably, at the cost+ * of a slight blurriness in the output.+ *+ * 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.+ *+ * FT_LCD_FILTER_LEGACY ::+ * This filter corresponds to the original libXft color filter. It+ * provides high contrast output but can exhibit really bad color+ * fringes if glyphs are not extremely well hinted to the pixel grid.+ * In other words, it only works well if the TrueType bytecode+ * interpreter is enabled *and* high-quality hinted fonts are used.+ *+ * This filter is only provided for comparison purposes, and might be+ * disabled or stay unsupported in the future.+ *+ * @since:+ * 2.3.0+ */+ typedef enum FT_LcdFilter_+ {+ FT_LCD_FILTER_NONE = 0,+ FT_LCD_FILTER_DEFAULT = 1,+ FT_LCD_FILTER_LIGHT = 2,+ FT_LCD_FILTER_LEGACY = 16,++ FT_LCD_FILTER_MAX /* do not remove */++ } FT_LcdFilter;+++ /**************************************************************************+ *+ * @func:+ * FT_Library_SetLcdFilter+ *+ * @description:+ * This function is used to apply color filtering to LCD decimated+ * bitmaps, like the ones used when calling @FT_Render_Glyph with+ * @FT_RENDER_MODE_LCD or @FT_RENDER_MODE_LCD_V.+ *+ * @input:+ * library ::+ * A handle to the target library instance.+ *+ * filter ::+ * The filter type.+ *+ * You can use @FT_LCD_FILTER_NONE here to disable this feature, or+ * @FT_LCD_FILTER_DEFAULT to use a default filter that should work+ * well on most LCD screens.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * This feature is always disabled by default. Clients must make an+ * explicit call to this function with a `filter' value other than+ * @FT_LCD_FILTER_NONE in order to enable it.+ *+ * Due to *PATENTS* covering subpixel rendering, this function doesn't+ * do anything except returning `FT_Err_Unimplemented_Feature' if the+ * configuration macro FT_CONFIG_OPTION_SUBPIXEL_RENDERING is not+ * defined in your build of the library, which should correspond to all+ * default builds of FreeType.+ *+ * The filter affects glyph bitmaps rendered through @FT_Render_Glyph,+ * @FT_Outline_Get_Bitmap, @FT_Load_Glyph, and @FT_Load_Char.+ *+ * It does _not_ affect the output of @FT_Outline_Render and+ * @FT_Outline_Get_Bitmap.+ *+ * If this feature is activated, the dimensions of LCD glyph bitmaps are+ * either larger or taller than the dimensions of the corresponding+ * outline with regards to the pixel grid. For example, for+ * @FT_RENDER_MODE_LCD, the filter adds up to 3~pixels to the left, and+ * up to 3~pixels to the right.+ *+ * The bitmap offset values are adjusted correctly, so clients shouldn't+ * need to modify their layout and glyph positioning code when enabling+ * the filter.+ *+ * @since:+ * 2.3.0+ */+ FT_EXPORT( FT_Error )+ FT_Library_SetLcdFilter( FT_Library library,+ FT_LcdFilter filter );+++ /**************************************************************************+ *+ * @func:+ * FT_Library_SetLcdFilterWeights+ *+ * @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.+ *+ * @input:+ * library ::+ * A handle to the target library instance.+ *+ * weights ::+ * A pointer to an array; the function copies the first five bytes and+ * uses them to specify the filter weights.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * Due to *PATENTS* covering subpixel rendering, this function doesn't+ * do anything except returning `FT_Err_Unimplemented_Feature' if the+ * configuration macro FT_CONFIG_OPTION_SUBPIXEL_RENDERING is not+ * defined in your build of the library, which should correspond to all+ * default builds of FreeType.+ *+ * This function must be called after @FT_Library_SetLcdFilter to have+ * any effect.+ *+ * @since:+ * 2.4.0+ */+ FT_EXPORT( FT_Error )+ FT_Library_SetLcdFilterWeights( FT_Library library,+ unsigned char *weights );++ /* */+++FT_END_HEADER++#endif /* __FT_LCD_FILTER_H__ */+++/* END */
+ include/freetype/ftlist.h view
@@ -0,0 +1,277 @@+/***************************************************************************/+/* */+/* ftlist.h */+/* */+/* Generic list support for FreeType (specification). */+/* */+/* Copyright 1996-2001, 2003, 2007, 2010 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 implements functions relative to list processing. Its */+ /* data structures are defined in `freetype.h'. */+ /* */+ /*************************************************************************/+++#ifndef __FTLIST_H__+#define __FTLIST_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+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* list_processing */+ /* */+ /* <Title> */+ /* List Processing */+ /* */+ /* <Abstract> */+ /* Simple management of lists. */+ /* */+ /* <Description> */+ /* This section contains various definitions related to list */+ /* processing using doubly-linked nodes. */+ /* */+ /* <Order> */+ /* FT_List */+ /* FT_ListNode */+ /* FT_ListRec */+ /* FT_ListNodeRec */+ /* */+ /* FT_List_Add */+ /* FT_List_Insert */+ /* FT_List_Find */+ /* FT_List_Remove */+ /* FT_List_Up */+ /* FT_List_Iterate */+ /* FT_List_Iterator */+ /* FT_List_Finalize */+ /* FT_List_Destructor */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_List_Find */+ /* */+ /* <Description> */+ /* Find the list node for a given listed object. */+ /* */+ /* <Input> */+ /* list :: A pointer to the parent list. */+ /* data :: The address of the listed object. */+ /* */+ /* <Return> */+ /* List node. NULL if it wasn't found. */+ /* */+ FT_EXPORT( FT_ListNode )+ FT_List_Find( FT_List list,+ void* data );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_List_Add */+ /* */+ /* <Description> */+ /* Append an element to the end of a list. */+ /* */+ /* <InOut> */+ /* list :: A pointer to the parent list. */+ /* node :: The node to append. */+ /* */+ FT_EXPORT( void )+ FT_List_Add( FT_List list,+ FT_ListNode node );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_List_Insert */+ /* */+ /* <Description> */+ /* Insert an element at the head of a list. */+ /* */+ /* <InOut> */+ /* list :: A pointer to parent list. */+ /* node :: The node to insert. */+ /* */+ FT_EXPORT( void )+ FT_List_Insert( FT_List list,+ FT_ListNode node );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_List_Remove */+ /* */+ /* <Description> */+ /* Remove a node from a list. This function doesn't check whether */+ /* the node is in the list! */+ /* */+ /* <Input> */+ /* node :: The node to remove. */+ /* */+ /* <InOut> */+ /* list :: A pointer to the parent list. */+ /* */+ FT_EXPORT( void )+ FT_List_Remove( FT_List list,+ FT_ListNode node );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_List_Up */+ /* */+ /* <Description> */+ /* Move a node to the head/top of a list. Used to maintain LRU */+ /* lists. */+ /* */+ /* <InOut> */+ /* list :: A pointer to the parent list. */+ /* node :: The node to move. */+ /* */+ FT_EXPORT( void )+ FT_List_Up( FT_List list,+ FT_ListNode node );+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* FT_List_Iterator */+ /* */+ /* <Description> */+ /* An FT_List iterator function which is called during a list parse */+ /* by @FT_List_Iterate. */+ /* */+ /* <Input> */+ /* node :: The current iteration list node. */+ /* */+ /* user :: A typeless pointer passed to @FT_List_Iterate. */+ /* Can be used to point to the iteration's state. */+ /* */+ typedef FT_Error+ (*FT_List_Iterator)( FT_ListNode node,+ void* user );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_List_Iterate */+ /* */+ /* <Description> */+ /* Parse a list and calls a given iterator function on each element. */+ /* Note that parsing is stopped as soon as one of the iterator calls */+ /* returns a non-zero value. */+ /* */+ /* <Input> */+ /* list :: A handle to the list. */+ /* iterator :: An iterator function, called on each node of the list. */+ /* user :: A user-supplied field which is passed as the second */+ /* argument to the iterator. */+ /* */+ /* <Return> */+ /* The result (a FreeType error code) of the last iterator call. */+ /* */+ FT_EXPORT( FT_Error )+ FT_List_Iterate( FT_List list,+ FT_List_Iterator iterator,+ void* user );+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* FT_List_Destructor */+ /* */+ /* <Description> */+ /* An @FT_List iterator function which is called during a list */+ /* finalization by @FT_List_Finalize to destroy all elements in a */+ /* given list. */+ /* */+ /* <Input> */+ /* system :: The current system object. */+ /* */+ /* data :: The current object to destroy. */+ /* */+ /* user :: A typeless pointer passed to @FT_List_Iterate. It can */+ /* be used to point to the iteration's state. */+ /* */+ typedef void+ (*FT_List_Destructor)( FT_Memory memory,+ void* data,+ void* user );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_List_Finalize */+ /* */+ /* <Description> */+ /* Destroy all elements in the list as well as the list itself. */+ /* */+ /* <Input> */+ /* list :: A handle to the list. */+ /* */+ /* destroy :: A list destructor that will be applied to each element */+ /* of the list. */+ /* */+ /* memory :: The current memory object which handles deallocation. */+ /* */+ /* user :: A user-supplied field which is passed as the last */+ /* argument to the destructor. */+ /* */+ /* <Note> */+ /* This function expects that all nodes added by @FT_List_Add or */+ /* @FT_List_Insert have been dynamically allocated. */+ /* */+ FT_EXPORT( void )+ FT_List_Finalize( FT_List list,+ FT_List_Destructor destroy,+ FT_Memory memory,+ void* user );+++ /* */+++FT_END_HEADER++#endif /* __FTLIST_H__ */+++/* END */
+ include/freetype/ftlzw.h view
@@ -0,0 +1,99 @@+/***************************************************************************/+/* */+/* ftlzw.h */+/* */+/* LZW-compressed stream support. */+/* */+/* Copyright 2004, 2006 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 __FTLZW_H__+#define __FTLZW_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+++FT_BEGIN_HEADER++ /*************************************************************************/+ /* */+ /* <Section> */+ /* lzw */+ /* */+ /* <Title> */+ /* LZW Streams */+ /* */+ /* <Abstract> */+ /* Using LZW-compressed font files. */+ /* */+ /* <Description> */+ /* This section contains the declaration of LZW-specific functions. */+ /* */+ /*************************************************************************/++ /************************************************************************+ *+ * @function:+ * FT_Stream_OpenLZW+ *+ * @description:+ * Open a new stream to parse LZW-compressed font files. This is+ * mainly used to support the compressed `*.pcf.Z' fonts that come+ * with XFree86.+ *+ * @input:+ * stream :: The target embedding stream.+ *+ * source :: The source stream.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * The source stream must be opened _before_ calling this function.+ *+ * Calling the internal function `FT_Stream_Close' on the new stream will+ * *not* call `FT_Stream_Close' on the source stream. None of the stream+ * objects will be released to the heap.+ *+ * The stream implementation is very basic and resets the decompression+ * process each time seeking backwards is needed within the stream+ *+ * In certain builds of the library, LZW compression recognition is+ * automatically handled when calling @FT_New_Face or @FT_Open_Face.+ * This means that if no font driver is capable of handling the raw+ * compressed file, the library will try to open a LZW stream from it+ * and re-open the face with it.+ *+ * This function may return `FT_Err_Unimplemented_Feature' if your build+ * of FreeType was not compiled with LZW support.+ */+ FT_EXPORT( FT_Error )+ FT_Stream_OpenLZW( FT_Stream stream,+ FT_Stream source );++ /* */+++FT_END_HEADER++#endif /* __FTLZW_H__ */+++/* END */
+ include/freetype/ftmac.h view
@@ -0,0 +1,274 @@+/***************************************************************************/+/* */+/* ftmac.h */+/* */+/* Additional Mac-specific API. */+/* */+/* Copyright 1996-2001, 2004, 2006, 2007 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. */+/* */+/***************************************************************************/+++/***************************************************************************/+/* */+/* NOTE: Include this file after <freetype/freetype.h> and after any */+/* Mac-specific headers (because this header uses Mac types such as */+/* Handle, FSSpec, FSRef, etc.) */+/* */+/***************************************************************************/+++#ifndef __FTMAC_H__+#define __FTMAC_H__+++#include <ft2build.h>+++FT_BEGIN_HEADER+++/* gcc-3.4.1 and later can warn about functions tagged as deprecated */+#ifndef FT_DEPRECATED_ATTRIBUTE+#if defined(__GNUC__) && \+ ((__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)))+#define FT_DEPRECATED_ATTRIBUTE __attribute__((deprecated))+#else+#define FT_DEPRECATED_ATTRIBUTE+#endif+#endif+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* mac_specific */+ /* */+ /* <Title> */+ /* Mac Specific Interface */+ /* */+ /* <Abstract> */+ /* Only available on the Macintosh. */+ /* */+ /* <Description> */+ /* The following definitions are only available if FreeType is */+ /* compiled on a Macintosh. */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_New_Face_From_FOND */+ /* */+ /* <Description> */+ /* Create a new face object from a FOND resource. */+ /* */+ /* <InOut> */+ /* library :: A handle to the library resource. */+ /* */+ /* <Input> */+ /* fond :: A FOND resource. */+ /* */+ /* face_index :: Only supported for the -1 `sanity check' special */+ /* case. */+ /* */+ /* <Output> */+ /* aface :: A handle to a new face object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Notes> */+ /* This function can be used to create @FT_Face objects from fonts */+ /* that are installed in the system as follows. */+ /* */+ /* { */+ /* fond = GetResource( 'FOND', fontName ); */+ /* error = FT_New_Face_From_FOND( library, fond, 0, &face ); */+ /* } */+ /* */+ FT_EXPORT( FT_Error )+ FT_New_Face_From_FOND( FT_Library library,+ Handle fond,+ FT_Long face_index,+ FT_Face *aface )+ FT_DEPRECATED_ATTRIBUTE;+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_GetFile_From_Mac_Name */+ /* */+ /* <Description> */+ /* Return an FSSpec for the disk file containing the named font. */+ /* */+ /* <Input> */+ /* fontName :: Mac OS name of the font (e.g., Times New Roman */+ /* Bold). */+ /* */+ /* <Output> */+ /* pathSpec :: FSSpec to the file. For passing to */+ /* @FT_New_Face_From_FSSpec. */+ /* */+ /* face_index :: Index of the face. For passing to */+ /* @FT_New_Face_From_FSSpec. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ FT_EXPORT( FT_Error )+ FT_GetFile_From_Mac_Name( const char* fontName,+ FSSpec* pathSpec,+ FT_Long* face_index )+ FT_DEPRECATED_ATTRIBUTE;+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_GetFile_From_Mac_ATS_Name */+ /* */+ /* <Description> */+ /* Return an FSSpec for the disk file containing the named font. */+ /* */+ /* <Input> */+ /* fontName :: Mac OS name of the font in ATS framework. */+ /* */+ /* <Output> */+ /* pathSpec :: FSSpec to the file. For passing to */+ /* @FT_New_Face_From_FSSpec. */+ /* */+ /* face_index :: Index of the face. For passing to */+ /* @FT_New_Face_From_FSSpec. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ FT_EXPORT( FT_Error )+ FT_GetFile_From_Mac_ATS_Name( const char* fontName,+ FSSpec* pathSpec,+ FT_Long* face_index )+ FT_DEPRECATED_ATTRIBUTE;+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_GetFilePath_From_Mac_ATS_Name */+ /* */+ /* <Description> */+ /* Return a pathname of the disk file and face index for given font */+ /* name which is handled by ATS framework. */+ /* */+ /* <Input> */+ /* fontName :: Mac OS name of the font in ATS framework. */+ /* */+ /* <Output> */+ /* path :: Buffer to store pathname of the file. For passing */+ /* to @FT_New_Face. The client must allocate this */+ /* buffer before calling this function. */+ /* */+ /* maxPathSize :: Lengths of the buffer `path' that client allocated. */+ /* */+ /* face_index :: Index of the face. For passing to @FT_New_Face. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ FT_EXPORT( FT_Error )+ FT_GetFilePath_From_Mac_ATS_Name( const char* fontName,+ UInt8* path,+ UInt32 maxPathSize,+ FT_Long* face_index )+ FT_DEPRECATED_ATTRIBUTE;+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_New_Face_From_FSSpec */+ /* */+ /* <Description> */+ /* Create a new face object from a given resource and typeface index */+ /* using an FSSpec to the font file. */+ /* */+ /* <InOut> */+ /* library :: A handle to the library resource. */+ /* */+ /* <Input> */+ /* spec :: FSSpec to the font file. */+ /* */+ /* face_index :: The index of the face within the resource. The */+ /* first face has index~0. */+ /* <Output> */+ /* aface :: A handle to a new face object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* @FT_New_Face_From_FSSpec is identical to @FT_New_Face except */+ /* it accepts an FSSpec instead of a path. */+ /* */+ FT_EXPORT( FT_Error )+ FT_New_Face_From_FSSpec( FT_Library library,+ const FSSpec *spec,+ FT_Long face_index,+ FT_Face *aface )+ FT_DEPRECATED_ATTRIBUTE;+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_New_Face_From_FSRef */+ /* */+ /* <Description> */+ /* Create a new face object from a given resource and typeface index */+ /* using an FSRef to the font file. */+ /* */+ /* <InOut> */+ /* library :: A handle to the library resource. */+ /* */+ /* <Input> */+ /* spec :: FSRef to the font file. */+ /* */+ /* face_index :: The index of the face within the resource. The */+ /* first face has index~0. */+ /* <Output> */+ /* aface :: A handle to a new face object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* @FT_New_Face_From_FSRef is identical to @FT_New_Face except */+ /* it accepts an FSRef instead of a path. */+ /* */+ FT_EXPORT( FT_Error )+ FT_New_Face_From_FSRef( FT_Library library,+ const FSRef *ref,+ FT_Long face_index,+ FT_Face *aface )+ FT_DEPRECATED_ATTRIBUTE;++ /* */+++FT_END_HEADER+++#endif /* __FTMAC_H__ */+++/* END */
+ include/freetype/ftmm.h view
@@ -0,0 +1,378 @@+/***************************************************************************/+/* */+/* ftmm.h */+/* */+/* FreeType Multiple Master font interface (specification). */+/* */+/* Copyright 1996-2001, 2003, 2004, 2006, 2009 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 __FTMM_H__+#define __FTMM_H__+++#include <ft2build.h>+#include FT_TYPE1_TABLES_H+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* multiple_masters */+ /* */+ /* <Title> */+ /* Multiple Masters */+ /* */+ /* <Abstract> */+ /* How to manage Multiple Masters fonts. */+ /* */+ /* <Description> */+ /* The following types and functions are used to manage Multiple */+ /* Master fonts, i.e., the selection of specific design instances by */+ /* setting design axis coordinates. */+ /* */+ /* George Williams has extended this interface to make it work with */+ /* both Type~1 Multiple Masters fonts and GX distortable (var) */+ /* fonts. Some of these routines only work with MM fonts, others */+ /* will work with both types. They are similar enough that a */+ /* consistent interface makes sense. */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_MM_Axis */+ /* */+ /* <Description> */+ /* A simple structure used to model a given axis in design space for */+ /* Multiple Masters fonts. */+ /* */+ /* This structure can't be used for GX var fonts. */+ /* */+ /* <Fields> */+ /* name :: The axis's name. */+ /* */+ /* minimum :: The axis's minimum design coordinate. */+ /* */+ /* maximum :: The axis's maximum design coordinate. */+ /* */+ typedef struct FT_MM_Axis_+ {+ FT_String* name;+ FT_Long minimum;+ FT_Long maximum;++ } FT_MM_Axis;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_Multi_Master */+ /* */+ /* <Description> */+ /* A structure used to model the axes and space of a Multiple Masters */+ /* font. */+ /* */+ /* This structure can't be used for GX var fonts. */+ /* */+ /* <Fields> */+ /* num_axis :: Number of axes. Cannot exceed~4. */+ /* */+ /* num_designs :: Number of designs; should be normally 2^num_axis */+ /* even though the Type~1 specification strangely */+ /* allows for intermediate designs to be present. This */+ /* number cannot exceed~16. */+ /* */+ /* axis :: A table of axis descriptors. */+ /* */+ typedef struct FT_Multi_Master_+ {+ FT_UInt num_axis;+ FT_UInt num_designs;+ FT_MM_Axis axis[T1_MAX_MM_AXIS];++ } FT_Multi_Master;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_Var_Axis */+ /* */+ /* <Description> */+ /* A simple structure used to model a given axis in design space for */+ /* Multiple Masters and GX var fonts. */+ /* */+ /* <Fields> */+ /* name :: The axis's name. */+ /* Not always meaningful for GX. */+ /* */+ /* minimum :: The axis's minimum design coordinate. */+ /* */+ /* def :: The axis's default design coordinate. */+ /* FreeType computes meaningful default values for MM; it */+ /* is then an integer value, not in 16.16 format. */+ /* */+ /* maximum :: The axis's maximum design coordinate. */+ /* */+ /* tag :: The axis's tag (the GX equivalent to `name'). */+ /* FreeType provides default values for MM if possible. */+ /* */+ /* strid :: The entry in `name' table (another GX version of */+ /* `name'). */+ /* Not meaningful for MM. */+ /* */+ typedef struct FT_Var_Axis_+ {+ FT_String* name;++ FT_Fixed minimum;+ FT_Fixed def;+ FT_Fixed maximum;++ FT_ULong tag;+ FT_UInt strid;++ } FT_Var_Axis;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_Var_Named_Style */+ /* */+ /* <Description> */+ /* A simple structure used to model a named style in a GX var font. */+ /* */+ /* This structure can't be used for MM fonts. */+ /* */+ /* <Fields> */+ /* coords :: The design coordinates for this style. */+ /* This is an array with one entry for each axis. */+ /* */+ /* strid :: The entry in `name' table identifying this style. */+ /* */+ typedef struct FT_Var_Named_Style_+ {+ FT_Fixed* coords;+ FT_UInt strid;++ } FT_Var_Named_Style;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_MM_Var */+ /* */+ /* <Description> */+ /* A structure used to model the axes and space of a Multiple Masters */+ /* or GX var distortable font. */+ /* */+ /* Some fields are specific to one format and not to the other. */+ /* */+ /* <Fields> */+ /* num_axis :: The number of axes. The maximum value is~4 for */+ /* MM; no limit in GX. */+ /* */+ /* num_designs :: The number of designs; should be normally */+ /* 2^num_axis for MM fonts. Not meaningful for GX */+ /* (where every glyph could have a different */+ /* number of designs). */+ /* */+ /* num_namedstyles :: The number of named styles; only meaningful for */+ /* GX which allows certain design coordinates to */+ /* have a string ID (in the `name' table) */+ /* associated with them. The font can tell the */+ /* user that, for example, Weight=1.5 is `Bold'. */+ /* */+ /* axis :: A table of axis descriptors. */+ /* GX fonts contain slightly more data than MM. */+ /* */+ /* namedstyles :: A table of named styles. */+ /* Only meaningful with GX. */+ /* */+ typedef struct FT_MM_Var_+ {+ FT_UInt num_axis;+ FT_UInt num_designs;+ FT_UInt num_namedstyles;+ FT_Var_Axis* axis;+ FT_Var_Named_Style* namedstyle;++ } FT_MM_Var;+++ /* */+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Get_Multi_Master */+ /* */+ /* <Description> */+ /* Retrieve the Multiple Master descriptor of a given font. */+ /* */+ /* This function can't be used with GX fonts. */+ /* */+ /* <Input> */+ /* face :: A handle to the source face. */+ /* */+ /* <Output> */+ /* amaster :: The Multiple Masters descriptor. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Get_Multi_Master( FT_Face face,+ FT_Multi_Master *amaster );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Get_MM_Var */+ /* */+ /* <Description> */+ /* Retrieve the Multiple Master/GX var descriptor of a given font. */+ /* */+ /* <Input> */+ /* face :: A handle to the source face. */+ /* */+ /* <Output> */+ /* amaster :: The Multiple Masters/GX var descriptor. */+ /* Allocates a data structure, which the user must free */+ /* (a single call to FT_FREE will do it). */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Get_MM_Var( FT_Face face,+ FT_MM_Var* *amaster );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Set_MM_Design_Coordinates */+ /* */+ /* <Description> */+ /* For Multiple Masters fonts, choose an interpolated font design */+ /* through design coordinates. */+ /* */+ /* This function can't be used with GX fonts. */+ /* */+ /* <InOut> */+ /* face :: A handle to the source face. */+ /* */+ /* <Input> */+ /* num_coords :: The number of design coordinates (must be equal to */+ /* the number of axes in the font). */+ /* */+ /* coords :: An array of design coordinates. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Set_MM_Design_Coordinates( FT_Face face,+ FT_UInt num_coords,+ FT_Long* coords );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Set_Var_Design_Coordinates */+ /* */+ /* <Description> */+ /* For Multiple Master or GX Var fonts, choose an interpolated font */+ /* design through design coordinates. */+ /* */+ /* <InOut> */+ /* face :: A handle to the source face. */+ /* */+ /* <Input> */+ /* num_coords :: The number of design coordinates (must be equal to */+ /* the number of axes in the font). */+ /* */+ /* coords :: An array of design coordinates. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Set_Var_Design_Coordinates( FT_Face face,+ FT_UInt num_coords,+ FT_Fixed* coords );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Set_MM_Blend_Coordinates */+ /* */+ /* <Description> */+ /* For Multiple Masters and GX var fonts, choose an interpolated font */+ /* design through normalized blend coordinates. */+ /* */+ /* <InOut> */+ /* face :: A handle to the source face. */+ /* */+ /* <Input> */+ /* num_coords :: The number of design coordinates (must be equal to */+ /* the number of axes in the font). */+ /* */+ /* coords :: The design coordinates array (each element must be */+ /* between 0 and 1.0). */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Set_MM_Blend_Coordinates( FT_Face face,+ FT_UInt num_coords,+ FT_Fixed* coords );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Set_Var_Blend_Coordinates */+ /* */+ /* <Description> */+ /* This is another name of @FT_Set_MM_Blend_Coordinates. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Set_Var_Blend_Coordinates( FT_Face face,+ FT_UInt num_coords,+ FT_Fixed* coords );+++ /* */+++FT_END_HEADER++#endif /* __FTMM_H__ */+++/* END */
+ include/freetype/ftmodapi.h view
@@ -0,0 +1,483 @@+/***************************************************************************/+/* */+/* ftmodapi.h */+/* */+/* FreeType modules public interface (specification). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2006, 2008, 2009, 2010 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 __FTMODAPI_H__+#define __FTMODAPI_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+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* module_management */+ /* */+ /* <Title> */+ /* Module Management */+ /* */+ /* <Abstract> */+ /* How to add, upgrade, and remove modules from FreeType. */+ /* */+ /* <Description> */+ /* The definitions below are used to manage modules within FreeType. */+ /* Modules can be added, upgraded, and removed at runtime. */+ /* */+ /*************************************************************************/+++ /* module bit flags */+#define FT_MODULE_FONT_DRIVER 1 /* this module is a font driver */+#define FT_MODULE_RENDERER 2 /* this module is a renderer */+#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 */+ /* scalable fonts */+#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 */+ /* own hinter */+++ /* deprecated values */+#define ft_module_font_driver FT_MODULE_FONT_DRIVER+#define ft_module_renderer FT_MODULE_RENDERER+#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+++ typedef FT_Pointer FT_Module_Interface;+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* FT_Module_Constructor */+ /* */+ /* <Description> */+ /* A function used to initialize (not create) a new module object. */+ /* */+ /* <Input> */+ /* module :: The module to initialize. */+ /* */+ typedef FT_Error+ (*FT_Module_Constructor)( FT_Module module );+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* FT_Module_Destructor */+ /* */+ /* <Description> */+ /* A function used to finalize (not destroy) a given module object. */+ /* */+ /* <Input> */+ /* module :: The module to finalize. */+ /* */+ typedef void+ (*FT_Module_Destructor)( FT_Module module );+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* FT_Module_Requester */+ /* */+ /* <Description> */+ /* A function used to query a given module for a specific interface. */+ /* */+ /* <Input> */+ /* module :: The module to finalize. */+ /* */+ /* name :: The name of the interface in the module. */+ /* */+ typedef FT_Module_Interface+ (*FT_Module_Requester)( FT_Module module,+ const char* name );+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_Module_Class */+ /* */+ /* <Description> */+ /* The module class descriptor. */+ /* */+ /* <Fields> */+ /* module_flags :: Bit flags describing the module. */+ /* */+ /* module_size :: The size of one module object/instance in */+ /* bytes. */+ /* */+ /* module_name :: The name of the module. */+ /* */+ /* module_version :: The version, as a 16.16 fixed number */+ /* (major.minor). */+ /* */+ /* module_requires :: The version of FreeType this module requires, */+ /* as a 16.16 fixed number (major.minor). Starts */+ /* at version 2.0, i.e., 0x20000. */+ /* */+ /* module_init :: The initializing function. */+ /* */+ /* module_done :: The finalizing function. */+ /* */+ /* get_interface :: The interface requesting function. */+ /* */+ typedef struct FT_Module_Class_+ {+ FT_ULong module_flags;+ FT_Long module_size;+ const FT_String* module_name;+ FT_Fixed module_version;+ FT_Fixed module_requires;++ const void* module_interface;++ FT_Module_Constructor module_init;+ FT_Module_Destructor module_done;+ FT_Module_Requester get_interface;++ } FT_Module_Class;+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Add_Module */+ /* */+ /* <Description> */+ /* Add a new module to a given library instance. */+ /* */+ /* <InOut> */+ /* library :: A handle to the library object. */+ /* */+ /* <Input> */+ /* clazz :: A pointer to class descriptor for the module. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* An error will be returned if a module already exists by that name, */+ /* or if the module requires a version of FreeType that is too great. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Add_Module( FT_Library library,+ const FT_Module_Class* clazz );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Get_Module */+ /* */+ /* <Description> */+ /* Find a module by its name. */+ /* */+ /* <Input> */+ /* library :: A handle to the library object. */+ /* */+ /* module_name :: The module's name (as an ASCII string). */+ /* */+ /* <Return> */+ /* A module handle. 0~if none was found. */+ /* */+ /* <Note> */+ /* FreeType's internal modules aren't documented very well, and you */+ /* should look up the source code for details. */+ /* */+ FT_EXPORT( FT_Module )+ FT_Get_Module( FT_Library library,+ const char* module_name );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Remove_Module */+ /* */+ /* <Description> */+ /* Remove a given module from a library instance. */+ /* */+ /* <InOut> */+ /* library :: A handle to a library object. */+ /* */+ /* <Input> */+ /* module :: A handle to a module object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* The module object is destroyed by the function in case of success. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Remove_Module( FT_Library library,+ FT_Module module );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Reference_Library */+ /* */+ /* <Description> */+ /* A counter gets initialized to~1 at the time an @FT_Library */+ /* structure is created. This function increments the counter. */+ /* @FT_Done_Library then only destroys a library if the counter is~1, */+ /* otherwise it simply decrements the counter. */+ /* */+ /* This function helps in managing life-cycles of structures which */+ /* reference @FT_Library objects. */+ /* */+ /* <Input> */+ /* library :: A handle to a target library object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Since> */+ /* 2.4.2 */+ /* */+ FT_EXPORT( FT_Error )+ FT_Reference_Library( FT_Library library );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_New_Library */+ /* */+ /* <Description> */+ /* This function is used to create a new FreeType library instance */+ /* from a given memory object. It is thus possible to use libraries */+ /* with distinct memory allocators within the same program. */+ /* */+ /* Normally, you would call this function (followed by a call to */+ /* @FT_Add_Default_Modules or a series of calls to @FT_Add_Module) */+ /* instead of @FT_Init_FreeType to initialize the FreeType library. */+ /* */+ /* Don't use @FT_Done_FreeType but @FT_Done_Library to destroy a */+ /* library instance. */+ /* */+ /* <Input> */+ /* memory :: A handle to the original memory object. */+ /* */+ /* <Output> */+ /* alibrary :: A pointer to handle of a new library object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* See the discussion of reference counters in the description of */+ /* @FT_Reference_Library. */+ /* */+ FT_EXPORT( FT_Error )+ FT_New_Library( FT_Memory memory,+ FT_Library *alibrary );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Done_Library */+ /* */+ /* <Description> */+ /* Discard a given library object. This closes all drivers and */+ /* discards all resource objects. */+ /* */+ /* <Input> */+ /* library :: A handle to the target library. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* See the discussion of reference counters in the description of */+ /* @FT_Reference_Library. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Done_Library( FT_Library library );++/* */++ typedef void+ (*FT_DebugHook_Func)( void* arg );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Set_Debug_Hook */+ /* */+ /* <Description> */+ /* Set a debug hook function for debugging the interpreter of a font */+ /* format. */+ /* */+ /* <InOut> */+ /* library :: A handle to the library object. */+ /* */+ /* <Input> */+ /* hook_index :: The index of the debug hook. You should use the */+ /* values defined in `ftobjs.h', e.g., */+ /* `FT_DEBUG_HOOK_TRUETYPE'. */+ /* */+ /* debug_hook :: The function used to debug the interpreter. */+ /* */+ /* <Note> */+ /* Currently, four debug hook slots are available, but only two (for */+ /* the TrueType and the Type~1 interpreter) are defined. */+ /* */+ /* Since the internal headers of FreeType are no longer installed, */+ /* the symbol `FT_DEBUG_HOOK_TRUETYPE' isn't available publicly. */+ /* This is a bug and will be fixed in a forthcoming release. */+ /* */+ FT_EXPORT( void )+ FT_Set_Debug_Hook( FT_Library library,+ FT_UInt hook_index,+ FT_DebugHook_Func debug_hook );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Add_Default_Modules */+ /* */+ /* <Description> */+ /* Add the set of default drivers to a given library object. */+ /* This is only useful when you create a library object with */+ /* @FT_New_Library (usually to plug a custom memory manager). */+ /* */+ /* <InOut> */+ /* library :: A handle to a new library object. */+ /* */+ FT_EXPORT( void )+ FT_Add_Default_Modules( FT_Library library );++++ /**************************************************************************+ *+ * @section:+ * truetype_engine+ *+ * @title:+ * The TrueType Engine+ *+ * @abstract:+ * TrueType bytecode support.+ *+ * @description:+ * This section contains a function used to query the level of TrueType+ * bytecode support compiled in this version of the library.+ *+ */+++ /**************************************************************************+ *+ * @enum:+ * FT_TrueTypeEngineType+ *+ * @description:+ * A list of values describing which kind of TrueType bytecode+ * engine is implemented in a given FT_Library instance. It is used+ * by the @FT_Get_TrueType_Engine_Type function.+ *+ * @values:+ * FT_TRUETYPE_ENGINE_TYPE_NONE ::+ * The library doesn't implement any kind of bytecode interpreter.+ *+ * FT_TRUETYPE_ENGINE_TYPE_UNPATENTED ::+ * The library implements a bytecode interpreter that doesn't+ * support the patented operations of the TrueType virtual machine.+ *+ * Its main use is to load certain Asian fonts which position and+ * scale glyph components with bytecode instructions. It produces+ * bad output for most other fonts.+ *+ * FT_TRUETYPE_ENGINE_TYPE_PATENTED ::+ * The library implements a bytecode interpreter that covers+ * the full instruction set of the TrueType virtual machine (this+ * was governed by patents until May 2010, hence the name).+ *+ * @since:+ * 2.2+ *+ */+ typedef enum FT_TrueTypeEngineType_+ {+ FT_TRUETYPE_ENGINE_TYPE_NONE = 0,+ FT_TRUETYPE_ENGINE_TYPE_UNPATENTED,+ FT_TRUETYPE_ENGINE_TYPE_PATENTED++ } FT_TrueTypeEngineType;+++ /**************************************************************************+ *+ * @func:+ * FT_Get_TrueType_Engine_Type+ *+ * @description:+ * Return an @FT_TrueTypeEngineType value to indicate which level of+ * the TrueType virtual machine a given library instance supports.+ *+ * @input:+ * library ::+ * A library instance.+ *+ * @return:+ * A value indicating which level is supported.+ *+ * @since:+ * 2.2+ *+ */+ FT_EXPORT( FT_TrueTypeEngineType )+ FT_Get_TrueType_Engine_Type( FT_Library library );+++ /* */+++FT_END_HEADER++#endif /* __FTMODAPI_H__ */+++/* END */
+ include/freetype/ftmoderr.h view
@@ -0,0 +1,155 @@+/***************************************************************************/+/* */+/* ftmoderr.h */+/* */+/* FreeType module error offsets (specification). */+/* */+/* Copyright 2001, 2002, 2003, 2004, 2005 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 FreeType module error offsets. */+ /* */+ /* The lower byte gives the error code, the higher byte gives the */+ /* module. The base module has error offset 0. For example, the error */+ /* `FT_Err_Invalid_File_Format' has value 0x003, the error */+ /* `TT_Err_Invalid_File_Format' has value 0x1103, the error */+ /* `T1_Err_Invalid_File_Format' has value 0x1203, etc. */+ /* */+ /* Undefine the macro FT_CONFIG_OPTION_USE_MODULE_ERRORS in ftoption.h */+ /* to make the higher byte always zero (disabling the module error */+ /* mechanism). */+ /* */+ /* It can also be used to create a module error message table easily */+ /* with something like */+ /* */+ /* { */+ /* #undef __FTMODERR_H__ */+ /* #define FT_MODERRDEF( e, v, s ) { FT_Mod_Err_ ## e, s }, */+ /* #define FT_MODERR_START_LIST { */+ /* #define FT_MODERR_END_LIST { 0, 0 } }; */+ /* */+ /* const struct */+ /* { */+ /* int mod_err_offset; */+ /* const char* mod_err_msg */+ /* } ft_mod_errors[] = */+ /* */+ /* #include FT_MODULE_ERRORS_H */+ /* } */+ /* */+ /* To use such a table, all errors must be ANDed with 0xFF00 to remove */+ /* the error code. */+ /* */+ /*************************************************************************/+++#ifndef __FTMODERR_H__+#define __FTMODERR_H__+++ /*******************************************************************/+ /*******************************************************************/+ /***** *****/+ /***** SETUP MACROS *****/+ /***** *****/+ /*******************************************************************/+ /*******************************************************************/+++#undef FT_NEED_EXTERN_C++#ifndef FT_MODERRDEF++#ifdef FT_CONFIG_OPTION_USE_MODULE_ERRORS+#define FT_MODERRDEF( e, v, s ) FT_Mod_Err_ ## e = v,+#else+#define FT_MODERRDEF( e, v, s ) FT_Mod_Err_ ## e = 0,+#endif++#define FT_MODERR_START_LIST enum {+#define FT_MODERR_END_LIST FT_Mod_Err_Max };++#ifdef __cplusplus+#define FT_NEED_EXTERN_C+ extern "C" {+#endif++#endif /* !FT_MODERRDEF */+++ /*******************************************************************/+ /*******************************************************************/+ /***** *****/+ /***** LIST MODULE ERROR BASES *****/+ /***** *****/+ /*******************************************************************/+ /*******************************************************************/+++#ifdef FT_MODERR_START_LIST+ FT_MODERR_START_LIST+#endif+++ FT_MODERRDEF( Base, 0x000, "base module" )+ FT_MODERRDEF( Autofit, 0x100, "autofitter module" )+ FT_MODERRDEF( BDF, 0x200, "BDF module" )+ FT_MODERRDEF( Cache, 0x300, "cache module" )+ FT_MODERRDEF( CFF, 0x400, "CFF module" )+ FT_MODERRDEF( CID, 0x500, "CID module" )+ FT_MODERRDEF( Gzip, 0x600, "Gzip module" )+ FT_MODERRDEF( LZW, 0x700, "LZW module" )+ FT_MODERRDEF( OTvalid, 0x800, "OpenType validation module" )+ FT_MODERRDEF( PCF, 0x900, "PCF module" )+ FT_MODERRDEF( PFR, 0xA00, "PFR module" )+ FT_MODERRDEF( PSaux, 0xB00, "PS auxiliary module" )+ FT_MODERRDEF( PShinter, 0xC00, "PS hinter module" )+ FT_MODERRDEF( PSnames, 0xD00, "PS names module" )+ FT_MODERRDEF( Raster, 0xE00, "raster module" )+ FT_MODERRDEF( SFNT, 0xF00, "SFNT module" )+ FT_MODERRDEF( Smooth, 0x1000, "smooth raster module" )+ FT_MODERRDEF( TrueType, 0x1100, "TrueType module" )+ FT_MODERRDEF( Type1, 0x1200, "Type 1 module" )+ FT_MODERRDEF( Type42, 0x1300, "Type 42 module" )+ FT_MODERRDEF( Winfonts, 0x1400, "Windows FON/FNT module" )+++#ifdef FT_MODERR_END_LIST+ FT_MODERR_END_LIST+#endif+++ /*******************************************************************/+ /*******************************************************************/+ /***** *****/+ /***** CLEANUP *****/+ /***** *****/+ /*******************************************************************/+ /*******************************************************************/+++#ifdef FT_NEED_EXTERN_C+ }+#endif++#undef FT_MODERR_START_LIST+#undef FT_MODERR_END_LIST+#undef FT_MODERRDEF+#undef FT_NEED_EXTERN_C+++#endif /* __FTMODERR_H__ */+++/* END */
+ include/freetype/ftotval.h view
@@ -0,0 +1,203 @@+/***************************************************************************/+/* */+/* ftotval.h */+/* */+/* FreeType API for validating OpenType tables (specification). */+/* */+/* Copyright 2004, 2005, 2006, 2007 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. */+/* */+/***************************************************************************/+++/***************************************************************************/+/* */+/* */+/* Warning: This module might be moved to a different library in the */+/* future to avoid a tight dependency between FreeType and the */+/* OpenType specification. */+/* */+/* */+/***************************************************************************/+++#ifndef __FTOTVAL_H__+#define __FTOTVAL_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+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* ot_validation */+ /* */+ /* <Title> */+ /* OpenType Validation */+ /* */+ /* <Abstract> */+ /* An API to validate OpenType tables. */+ /* */+ /* <Description> */+ /* This section contains the declaration of functions to validate */+ /* some OpenType tables (BASE, GDEF, GPOS, GSUB, JSTF, MATH). */+ /* */+ /*************************************************************************/+++ /**********************************************************************+ *+ * @enum:+ * FT_VALIDATE_OTXXX+ *+ * @description:+ * A list of bit-field constants used with @FT_OpenType_Validate to+ * indicate which OpenType tables should be validated.+ *+ * @values:+ * FT_VALIDATE_BASE ::+ * Validate BASE table.+ *+ * FT_VALIDATE_GDEF ::+ * Validate GDEF table.+ *+ * FT_VALIDATE_GPOS ::+ * Validate GPOS table.+ *+ * FT_VALIDATE_GSUB ::+ * Validate GSUB table.+ *+ * FT_VALIDATE_JSTF ::+ * Validate JSTF table.+ *+ * FT_VALIDATE_MATH ::+ * Validate MATH table.+ *+ * FT_VALIDATE_OT ::+ * Validate all OpenType tables (BASE, GDEF, GPOS, GSUB, JSTF, MATH).+ *+ */+#define FT_VALIDATE_BASE 0x0100+#define FT_VALIDATE_GDEF 0x0200+#define FT_VALIDATE_GPOS 0x0400+#define FT_VALIDATE_GSUB 0x0800+#define FT_VALIDATE_JSTF 0x1000+#define FT_VALIDATE_MATH 0x2000++#define FT_VALIDATE_OT FT_VALIDATE_BASE | \+ FT_VALIDATE_GDEF | \+ FT_VALIDATE_GPOS | \+ FT_VALIDATE_GSUB | \+ FT_VALIDATE_JSTF | \+ FT_VALIDATE_MATH++ /* */++ /**********************************************************************+ *+ * @function:+ * FT_OpenType_Validate+ *+ * @description:+ * Validate various OpenType tables to assure that all offsets and+ * indices are valid. The idea is that a higher-level library which+ * actually does the text layout can access those tables without+ * error checking (which can be quite time consuming).+ *+ * @input:+ * face ::+ * A handle to the input face.+ *+ * validation_flags ::+ * A bit field which specifies the tables to be validated. See+ * @FT_VALIDATE_OTXXX for possible values.+ *+ * @output:+ * BASE_table ::+ * A pointer to the BASE table.+ *+ * GDEF_table ::+ * A pointer to the GDEF table.+ *+ * GPOS_table ::+ * A pointer to the GPOS table.+ *+ * GSUB_table ::+ * A pointer to the GSUB table.+ *+ * JSTF_table ::+ * A pointer to the JSTF table.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * This function only works with OpenType fonts, returning an error+ * otherwise.+ *+ * After use, the application should deallocate the five tables with+ * @FT_OpenType_Free. A NULL value indicates that the table either+ * doesn't exist in the font, or the application hasn't asked for+ * validation.+ */+ FT_EXPORT( 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 );++ /* */++ /**********************************************************************+ *+ * @function:+ * FT_OpenType_Free+ *+ * @description:+ * Free the buffer allocated by OpenType validator.+ *+ * @input:+ * face ::+ * A handle to the input face.+ *+ * table ::+ * The pointer to the buffer that is allocated by+ * @FT_OpenType_Validate.+ *+ * @note:+ * This function must be used to free the buffer allocated by+ * @FT_OpenType_Validate only.+ */+ FT_EXPORT( void )+ FT_OpenType_Free( FT_Face face,+ FT_Bytes table );+++ /* */+++FT_END_HEADER++#endif /* __FTOTVAL_H__ */+++/* END */
+ include/freetype/ftoutln.h view
@@ -0,0 +1,537 @@+/***************************************************************************/+/* */+/* ftoutln.h */+/* */+/* Support for the FT_Outline type used to store glyph shapes of */+/* most scalable font formats (specification). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009, 2010 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 __FTOUTLN_H__+#define __FTOUTLN_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+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* outline_processing */+ /* */+ /* <Title> */+ /* Outline Processing */+ /* */+ /* <Abstract> */+ /* Functions to create, transform, and render vectorial glyph images. */+ /* */+ /* <Description> */+ /* This section contains routines used to create and destroy scalable */+ /* glyph images known as `outlines'. These can also be measured, */+ /* transformed, and converted into bitmaps and pixmaps. */+ /* */+ /* <Order> */+ /* FT_Outline */+ /* FT_OUTLINE_FLAGS */+ /* FT_Outline_New */+ /* FT_Outline_Done */+ /* FT_Outline_Copy */+ /* FT_Outline_Translate */+ /* FT_Outline_Transform */+ /* FT_Outline_Embolden */+ /* FT_Outline_Reverse */+ /* FT_Outline_Check */+ /* */+ /* FT_Outline_Get_CBox */+ /* FT_Outline_Get_BBox */+ /* */+ /* FT_Outline_Get_Bitmap */+ /* FT_Outline_Render */+ /* */+ /* FT_Outline_Decompose */+ /* FT_Outline_Funcs */+ /* FT_Outline_MoveTo_Func */+ /* FT_Outline_LineTo_Func */+ /* FT_Outline_ConicTo_Func */+ /* FT_Outline_CubicTo_Func */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Outline_Decompose */+ /* */+ /* <Description> */+ /* Walk over an outline's structure to decompose it into individual */+ /* segments and Bézier arcs. This function also emits `move to' */+ /* operations to indicate the start of new contours in the outline. */+ /* */+ /* <Input> */+ /* outline :: A pointer to the source target. */+ /* */+ /* func_interface :: A table of `emitters', i.e., function pointers */+ /* called during decomposition to indicate path */+ /* operations. */+ /* */+ /* <InOut> */+ /* user :: A typeless pointer which is passed to each */+ /* emitter during the decomposition. It can be */+ /* used to store the state during the */+ /* decomposition. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Outline_Decompose( FT_Outline* outline,+ const FT_Outline_Funcs* func_interface,+ void* user );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Outline_New */+ /* */+ /* <Description> */+ /* Create a new outline of a given size. */+ /* */+ /* <Input> */+ /* library :: A handle to the library object from where the */+ /* outline is allocated. Note however that the new */+ /* outline will *not* necessarily be *freed*, when */+ /* destroying the library, by @FT_Done_FreeType. */+ /* */+ /* numPoints :: The maximal number of points within the outline. */+ /* */+ /* numContours :: The maximal number of contours within the outline. */+ /* */+ /* <Output> */+ /* anoutline :: A handle to the new outline. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* The reason why this function takes a `library' parameter is simply */+ /* to use the library's memory allocator. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Outline_New( FT_Library library,+ FT_UInt numPoints,+ FT_Int numContours,+ FT_Outline *anoutline );+++ FT_EXPORT( FT_Error )+ FT_Outline_New_Internal( FT_Memory memory,+ FT_UInt numPoints,+ FT_Int numContours,+ FT_Outline *anoutline );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Outline_Done */+ /* */+ /* <Description> */+ /* Destroy an outline created with @FT_Outline_New. */+ /* */+ /* <Input> */+ /* library :: A handle of the library object used to allocate the */+ /* outline. */+ /* */+ /* outline :: A pointer to the outline object to be discarded. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* If the outline's `owner' field is not set, only the outline */+ /* descriptor will be released. */+ /* */+ /* The reason why this function takes an `library' parameter is */+ /* simply to use ft_mem_free(). */+ /* */+ FT_EXPORT( FT_Error )+ FT_Outline_Done( FT_Library library,+ FT_Outline* outline );+++ FT_EXPORT( FT_Error )+ FT_Outline_Done_Internal( FT_Memory memory,+ FT_Outline* outline );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Outline_Check */+ /* */+ /* <Description> */+ /* Check the contents of an outline descriptor. */+ /* */+ /* <Input> */+ /* outline :: A handle to a source outline. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Outline_Check( FT_Outline* outline );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Outline_Get_CBox */+ /* */+ /* <Description> */+ /* Return an outline's `control box'. The control box encloses all */+ /* the outline's points, including Bézier control points. Though it */+ /* coincides with the exact bounding box for most glyphs, it can be */+ /* slightly larger in some situations (like when rotating an outline */+ /* which contains Bézier outside arcs). */+ /* */+ /* Computing the control box is very fast, while getting the bounding */+ /* box can take much more time as it needs to walk over all segments */+ /* and arcs in the outline. To get the latter, you can use the */+ /* `ftbbox' component which is dedicated to this single task. */+ /* */+ /* <Input> */+ /* outline :: A pointer to the source outline descriptor. */+ /* */+ /* <Output> */+ /* acbox :: The outline's control box. */+ /* */+ FT_EXPORT( void )+ FT_Outline_Get_CBox( const FT_Outline* outline,+ FT_BBox *acbox );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Outline_Translate */+ /* */+ /* <Description> */+ /* Apply a simple translation to the points of an outline. */+ /* */+ /* <InOut> */+ /* outline :: A pointer to the target outline descriptor. */+ /* */+ /* <Input> */+ /* xOffset :: The horizontal offset. */+ /* */+ /* yOffset :: The vertical offset. */+ /* */+ FT_EXPORT( void )+ FT_Outline_Translate( const FT_Outline* outline,+ FT_Pos xOffset,+ FT_Pos yOffset );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Outline_Copy */+ /* */+ /* <Description> */+ /* Copy an outline into another one. Both objects must have the */+ /* same sizes (number of points & number of contours) when this */+ /* function is called. */+ /* */+ /* <Input> */+ /* source :: A handle to the source outline. */+ /* */+ /* <Output> */+ /* target :: A handle to the target outline. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Outline_Copy( const FT_Outline* source,+ FT_Outline *target );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Outline_Transform */+ /* */+ /* <Description> */+ /* Apply a simple 2x2 matrix to all of an outline's points. Useful */+ /* for applying rotations, slanting, flipping, etc. */+ /* */+ /* <InOut> */+ /* outline :: A pointer to the target outline descriptor. */+ /* */+ /* <Input> */+ /* matrix :: A pointer to the transformation matrix. */+ /* */+ /* <Note> */+ /* You can use @FT_Outline_Translate if you need to translate the */+ /* outline's points. */+ /* */+ FT_EXPORT( void )+ FT_Outline_Transform( const FT_Outline* outline,+ const FT_Matrix* matrix );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Outline_Embolden */+ /* */+ /* <Description> */+ /* Embolden an outline. The new outline will be at most 4~times */+ /* `strength' pixels wider and higher. You may think of the left and */+ /* bottom borders as unchanged. */+ /* */+ /* Negative `strength' values to reduce the outline thickness are */+ /* possible also. */+ /* */+ /* <InOut> */+ /* outline :: A handle to the target outline. */+ /* */+ /* <Input> */+ /* strength :: How strong the glyph is emboldened. Expressed in */+ /* 26.6 pixel format. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* The used algorithm to increase or decrease the thickness of the */+ /* glyph doesn't change the number of points; this means that certain */+ /* situations like acute angles or intersections are sometimes */+ /* handled incorrectly. */+ /* */+ /* If you need `better' metrics values you should call */+ /* @FT_Outline_Get_CBox ot @FT_Outline_Get_BBox. */+ /* */+ /* Example call: */+ /* */+ /* { */+ /* FT_Load_Glyph( face, index, FT_LOAD_DEFAULT ); */+ /* if ( face->slot->format == FT_GLYPH_FORMAT_OUTLINE ) */+ /* FT_Outline_Embolden( &face->slot->outline, strength ); */+ /* } */+ /* */+ FT_EXPORT( FT_Error )+ FT_Outline_Embolden( FT_Outline* outline,+ FT_Pos strength );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Outline_Reverse */+ /* */+ /* <Description> */+ /* Reverse the drawing direction of an outline. This is used to */+ /* ensure consistent fill conventions for mirrored glyphs. */+ /* */+ /* <InOut> */+ /* outline :: A pointer to the target outline descriptor. */+ /* */+ /* <Note> */+ /* This function toggles the bit flag @FT_OUTLINE_REVERSE_FILL in */+ /* the outline's `flags' field. */+ /* */+ /* It shouldn't be used by a normal client application, unless it */+ /* knows what it is doing. */+ /* */+ FT_EXPORT( void )+ FT_Outline_Reverse( FT_Outline* outline );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Outline_Get_Bitmap */+ /* */+ /* <Description> */+ /* Render an outline within a bitmap. The outline's image is simply */+ /* OR-ed to the target bitmap. */+ /* */+ /* <Input> */+ /* library :: A handle to a FreeType library object. */+ /* */+ /* outline :: A pointer to the source outline descriptor. */+ /* */+ /* <InOut> */+ /* abitmap :: A pointer to the target bitmap descriptor. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* This function does NOT CREATE the bitmap, it only renders an */+ /* outline image within the one you pass to it! Consequently, the */+ /* various fields in `abitmap' should be set accordingly. */+ /* */+ /* It will use the raster corresponding to the default glyph format. */+ /* */+ /* The value of the `num_grays' field in `abitmap' is ignored. If */+ /* you select the gray-level rasterizer, and you want less than 256 */+ /* gray levels, you have to use @FT_Outline_Render directly. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Outline_Get_Bitmap( FT_Library library,+ FT_Outline* outline,+ const FT_Bitmap *abitmap );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Outline_Render */+ /* */+ /* <Description> */+ /* Render an outline within a bitmap using the current scan-convert. */+ /* This function uses an @FT_Raster_Params structure as an argument, */+ /* allowing advanced features like direct composition, translucency, */+ /* etc. */+ /* */+ /* <Input> */+ /* library :: A handle to a FreeType library object. */+ /* */+ /* outline :: A pointer to the source outline descriptor. */+ /* */+ /* <InOut> */+ /* params :: A pointer to an @FT_Raster_Params structure used to */+ /* describe the rendering operation. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* You should know what you are doing and how @FT_Raster_Params works */+ /* to use this function. */+ /* */+ /* The field `params.source' will be set to `outline' before the scan */+ /* converter is called, which means that the value you give to it is */+ /* actually ignored. */+ /* */+ /* The gray-level rasterizer always uses 256 gray levels. If you */+ /* want less gray levels, you have to provide your own span callback. */+ /* See the @FT_RASTER_FLAG_DIRECT value of the `flags' field in the */+ /* @FT_Raster_Params structure for more details. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Outline_Render( FT_Library library,+ FT_Outline* outline,+ FT_Raster_Params* params );+++ /**************************************************************************+ *+ * @enum:+ * FT_Orientation+ *+ * @description:+ * A list of values used to describe an outline's contour orientation.+ *+ * The TrueType and PostScript specifications use different conventions+ * to determine whether outline contours should be filled or unfilled.+ *+ * @values:+ * FT_ORIENTATION_TRUETYPE ::+ * According to the TrueType specification, clockwise contours must+ * be filled, and counter-clockwise ones must be unfilled.+ *+ * FT_ORIENTATION_POSTSCRIPT ::+ * According to the PostScript specification, counter-clockwise contours+ * must be filled, and clockwise ones must be unfilled.+ *+ * FT_ORIENTATION_FILL_RIGHT ::+ * This is identical to @FT_ORIENTATION_TRUETYPE, but is used to+ * remember that in TrueType, everything that is to the right of+ * the drawing direction of a contour must be filled.+ *+ * FT_ORIENTATION_FILL_LEFT ::+ * This is identical to @FT_ORIENTATION_POSTSCRIPT, but is used to+ * remember that in PostScript, everything that is to the left of+ * the drawing direction of a contour must be filled.+ *+ * FT_ORIENTATION_NONE ::+ * The orientation cannot be determined. That is, different parts of+ * the glyph have different orientation.+ *+ */+ typedef enum FT_Orientation_+ {+ FT_ORIENTATION_TRUETYPE = 0,+ FT_ORIENTATION_POSTSCRIPT = 1,+ FT_ORIENTATION_FILL_RIGHT = FT_ORIENTATION_TRUETYPE,+ FT_ORIENTATION_FILL_LEFT = FT_ORIENTATION_POSTSCRIPT,+ FT_ORIENTATION_NONE++ } FT_Orientation;+++ /**************************************************************************+ *+ * @function:+ * FT_Outline_Get_Orientation+ *+ * @description:+ * This function analyzes a glyph outline and tries to compute its+ * fill orientation (see @FT_Orientation). This is done by computing+ * the direction of each global horizontal and/or vertical extrema+ * within the outline.+ *+ * Note that this will return @FT_ORIENTATION_TRUETYPE for empty+ * outlines.+ *+ * @input:+ * outline ::+ * A handle to the source outline.+ *+ * @return:+ * The orientation.+ *+ */+ FT_EXPORT( FT_Orientation )+ FT_Outline_Get_Orientation( FT_Outline* outline );+++ /* */+++FT_END_HEADER++#endif /* __FTOUTLN_H__ */+++/* END */+++/* Local Variables: */+/* coding: utf-8 */+/* End: */
+ include/freetype/ftpfr.h view
@@ -0,0 +1,172 @@+/***************************************************************************/+/* */+/* ftpfr.h */+/* */+/* FreeType API for accessing PFR-specific data (specification only). */+/* */+/* Copyright 2002, 2003, 2004, 2006, 2008, 2009 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 __FTPFR_H__+#define __FTPFR_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+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* pfr_fonts */+ /* */+ /* <Title> */+ /* PFR Fonts */+ /* */+ /* <Abstract> */+ /* PFR/TrueDoc specific API. */+ /* */+ /* <Description> */+ /* This section contains the declaration of PFR-specific functions. */+ /* */+ /*************************************************************************/+++ /**********************************************************************+ *+ * @function:+ * FT_Get_PFR_Metrics+ *+ * @description:+ * Return the outline and metrics resolutions of a given PFR face.+ *+ * @input:+ * face :: Handle to the input face. It can be a non-PFR face.+ *+ * @output:+ * aoutline_resolution ::+ * Outline resolution. This is equivalent to `face->units_per_EM'+ * for non-PFR fonts. Optional (parameter can be NULL).+ *+ * ametrics_resolution ::+ * Metrics resolution. This is equivalent to `outline_resolution'+ * for non-PFR fonts. Optional (parameter can be NULL).+ *+ * ametrics_x_scale ::+ * A 16.16 fixed-point number used to scale distance expressed+ * in metrics units to device sub-pixels. This is equivalent to+ * `face->size->x_scale', but for metrics only. Optional (parameter+ * can be NULL).+ *+ * ametrics_y_scale ::+ * Same as `ametrics_x_scale' but for the vertical direction.+ * optional (parameter can be NULL).+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * If the input face is not a PFR, this function will return an error.+ * However, in all cases, it will return valid values.+ */+ FT_EXPORT( 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 );+++ /**********************************************************************+ *+ * @function:+ * FT_Get_PFR_Kerning+ *+ * @description:+ * Return the kerning pair corresponding to two glyphs in a PFR face.+ * The distance is expressed in metrics units, unlike the result of+ * @FT_Get_Kerning.+ *+ * @input:+ * face :: A handle to the input face.+ *+ * left :: Index of the left glyph.+ *+ * right :: Index of the right glyph.+ *+ * @output:+ * avector :: A kerning vector.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * This function always return distances in original PFR metrics+ * units. This is unlike @FT_Get_Kerning with the @FT_KERNING_UNSCALED+ * mode, which always returns distances converted to outline units.+ *+ * You can use the value of the `x_scale' and `y_scale' parameters+ * returned by @FT_Get_PFR_Metrics to scale these to device sub-pixels.+ */+ FT_EXPORT( FT_Error )+ FT_Get_PFR_Kerning( FT_Face face,+ FT_UInt left,+ FT_UInt right,+ FT_Vector *avector );+++ /**********************************************************************+ *+ * @function:+ * FT_Get_PFR_Advance+ *+ * @description:+ * Return a given glyph advance, expressed in original metrics units,+ * from a PFR font.+ *+ * @input:+ * face :: A handle to the input face.+ *+ * gindex :: The glyph index.+ *+ * @output:+ * aadvance :: The glyph advance in metrics units.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * You can use the `x_scale' or `y_scale' results of @FT_Get_PFR_Metrics+ * to convert the advance to device sub-pixels (i.e., 1/64th of pixels).+ */+ FT_EXPORT( FT_Error )+ FT_Get_PFR_Advance( FT_Face face,+ FT_UInt gindex,+ FT_Pos *aadvance );++ /* */+++FT_END_HEADER++#endif /* __FTPFR_H__ */+++/* END */
+ include/freetype/ftrender.h view
@@ -0,0 +1,230 @@+/***************************************************************************/+/* */+/* ftrender.h */+/* */+/* FreeType renderer modules public interface (specification). */+/* */+/* Copyright 1996-2001, 2005, 2006, 2010 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 __FTRENDER_H__+#define __FTRENDER_H__+++#include <ft2build.h>+#include FT_MODULE_H+#include FT_GLYPH_H+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* module_management */+ /* */+ /*************************************************************************/+++ /* create a new glyph object */+ typedef FT_Error+ (*FT_Glyph_InitFunc)( FT_Glyph glyph,+ FT_GlyphSlot slot );++ /* destroys a given glyph object */+ typedef void+ (*FT_Glyph_DoneFunc)( FT_Glyph glyph );++ typedef void+ (*FT_Glyph_TransformFunc)( FT_Glyph glyph,+ const FT_Matrix* matrix,+ const FT_Vector* delta );++ typedef void+ (*FT_Glyph_GetBBoxFunc)( FT_Glyph glyph,+ FT_BBox* abbox );++ typedef FT_Error+ (*FT_Glyph_CopyFunc)( FT_Glyph source,+ FT_Glyph target );++ typedef FT_Error+ (*FT_Glyph_PrepareFunc)( FT_Glyph glyph,+ FT_GlyphSlot slot );++/* deprecated */+#define FT_Glyph_Init_Func FT_Glyph_InitFunc+#define FT_Glyph_Done_Func FT_Glyph_DoneFunc+#define FT_Glyph_Transform_Func FT_Glyph_TransformFunc+#define FT_Glyph_BBox_Func FT_Glyph_GetBBoxFunc+#define FT_Glyph_Copy_Func FT_Glyph_CopyFunc+#define FT_Glyph_Prepare_Func FT_Glyph_PrepareFunc+++ struct FT_Glyph_Class_+ {+ FT_Long glyph_size;+ FT_Glyph_Format glyph_format;+ FT_Glyph_InitFunc glyph_init;+ FT_Glyph_DoneFunc glyph_done;+ FT_Glyph_CopyFunc glyph_copy;+ FT_Glyph_TransformFunc glyph_transform;+ FT_Glyph_GetBBoxFunc glyph_bbox;+ FT_Glyph_PrepareFunc glyph_prepare;+ };+++ typedef FT_Error+ (*FT_Renderer_RenderFunc)( FT_Renderer renderer,+ FT_GlyphSlot slot,+ FT_UInt mode,+ const FT_Vector* origin );++ typedef FT_Error+ (*FT_Renderer_TransformFunc)( FT_Renderer renderer,+ FT_GlyphSlot slot,+ const FT_Matrix* matrix,+ const FT_Vector* delta );+++ typedef void+ (*FT_Renderer_GetCBoxFunc)( FT_Renderer renderer,+ FT_GlyphSlot slot,+ FT_BBox* cbox );+++ typedef FT_Error+ (*FT_Renderer_SetModeFunc)( FT_Renderer renderer,+ FT_ULong mode_tag,+ FT_Pointer mode_ptr );++/* deprecated identifiers */+#define FTRenderer_render FT_Renderer_RenderFunc+#define FTRenderer_transform FT_Renderer_TransformFunc+#define FTRenderer_getCBox FT_Renderer_GetCBoxFunc+#define FTRenderer_setMode FT_Renderer_SetModeFunc+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_Renderer_Class */+ /* */+ /* <Description> */+ /* The renderer module class descriptor. */+ /* */+ /* <Fields> */+ /* root :: The root @FT_Module_Class fields. */+ /* */+ /* glyph_format :: The glyph image format this renderer handles. */+ /* */+ /* render_glyph :: A method used to render the image that is in a */+ /* given glyph slot into a bitmap. */+ /* */+ /* transform_glyph :: A method used to transform the image that is in */+ /* a given glyph slot. */+ /* */+ /* get_glyph_cbox :: A method used to access the glyph's cbox. */+ /* */+ /* set_mode :: A method used to pass additional parameters. */+ /* */+ /* raster_class :: For @FT_GLYPH_FORMAT_OUTLINE renderers only. */+ /* This is a pointer to its raster's class. */+ /* */+ typedef struct FT_Renderer_Class_+ {+ FT_Module_Class root;++ FT_Glyph_Format glyph_format;++ FT_Renderer_RenderFunc render_glyph;+ FT_Renderer_TransformFunc transform_glyph;+ FT_Renderer_GetCBoxFunc get_glyph_cbox;+ FT_Renderer_SetModeFunc set_mode;++ FT_Raster_Funcs* raster_class;++ } FT_Renderer_Class;+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Get_Renderer */+ /* */+ /* <Description> */+ /* Retrieve the current renderer for a given glyph format. */+ /* */+ /* <Input> */+ /* library :: A handle to the library object. */+ /* */+ /* format :: The glyph format. */+ /* */+ /* <Return> */+ /* A renderer handle. 0~if none found. */+ /* */+ /* <Note> */+ /* An error will be returned if a module already exists by that name, */+ /* or if the module requires a version of FreeType that is too great. */+ /* */+ /* To add a new renderer, simply use @FT_Add_Module. To retrieve a */+ /* renderer by its name, use @FT_Get_Module. */+ /* */+ FT_EXPORT( FT_Renderer )+ FT_Get_Renderer( FT_Library library,+ FT_Glyph_Format format );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Set_Renderer */+ /* */+ /* <Description> */+ /* Set the current renderer to use, and set additional mode. */+ /* */+ /* <InOut> */+ /* library :: A handle to the library object. */+ /* */+ /* <Input> */+ /* renderer :: A handle to the renderer object. */+ /* */+ /* num_params :: The number of additional parameters. */+ /* */+ /* parameters :: Additional parameters. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* In case of success, the renderer will be used to convert glyph */+ /* images in the renderer's known format into bitmaps. */+ /* */+ /* This doesn't change the current renderer for other formats. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Set_Renderer( FT_Library library,+ FT_Renderer renderer,+ FT_UInt num_params,+ FT_Parameter* parameters );+++ /* */+++FT_END_HEADER++#endif /* __FTRENDER_H__ */+++/* END */
+ include/freetype/ftsizes.h view
@@ -0,0 +1,159 @@+/***************************************************************************/+/* */+/* ftsizes.h */+/* */+/* FreeType size objects management (specification). */+/* */+/* Copyright 1996-2001, 2003, 2004, 2006, 2009 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. */+/* */+/***************************************************************************/+++ /*************************************************************************/+ /* */+ /* Typical application would normally not need to use these functions. */+ /* However, they have been placed in a public API for the rare cases */+ /* where they are needed. */+ /* */+ /*************************************************************************/+++#ifndef __FTSIZES_H__+#define __FTSIZES_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+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* sizes_management */+ /* */+ /* <Title> */+ /* Size Management */+ /* */+ /* <Abstract> */+ /* Managing multiple sizes per face. */+ /* */+ /* <Description> */+ /* When creating a new face object (e.g., with @FT_New_Face), an */+ /* @FT_Size object is automatically created and used to store all */+ /* pixel-size dependent information, available in the `face->size' */+ /* field. */+ /* */+ /* It is however possible to create more sizes for a given face, */+ /* mostly in order to manage several character pixel sizes of the */+ /* same font family and style. See @FT_New_Size and @FT_Done_Size. */+ /* */+ /* Note that @FT_Set_Pixel_Sizes and @FT_Set_Char_Size only */+ /* modify the contents of the current `active' size; you thus need */+ /* to use @FT_Activate_Size to change it. */+ /* */+ /* 99% of applications won't need the functions provided here, */+ /* especially if they use the caching sub-system, so be cautious */+ /* when using these. */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_New_Size */+ /* */+ /* <Description> */+ /* Create a new size object from a given face object. */+ /* */+ /* <Input> */+ /* face :: A handle to a parent face object. */+ /* */+ /* <Output> */+ /* asize :: A handle to a new size object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* You need to call @FT_Activate_Size in order to select the new size */+ /* for upcoming calls to @FT_Set_Pixel_Sizes, @FT_Set_Char_Size, */+ /* @FT_Load_Glyph, @FT_Load_Char, etc. */+ /* */+ FT_EXPORT( FT_Error )+ FT_New_Size( FT_Face face,+ FT_Size* size );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Done_Size */+ /* */+ /* <Description> */+ /* Discard a given size object. Note that @FT_Done_Face */+ /* automatically discards all size objects allocated with */+ /* @FT_New_Size. */+ /* */+ /* <Input> */+ /* size :: A handle to a target size object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Done_Size( FT_Size size );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Activate_Size */+ /* */+ /* <Description> */+ /* Even though it is possible to create several size objects for a */+ /* given face (see @FT_New_Size for details), functions like */+ /* @FT_Load_Glyph or @FT_Load_Char only use the one which has been */+ /* activated last to determine the `current character pixel size'. */+ /* */+ /* This function can be used to `activate' a previously created size */+ /* object. */+ /* */+ /* <Input> */+ /* size :: A handle to a target size object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* If `face' is the size's parent face object, this function changes */+ /* the value of `face->size' to the input size handle. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Activate_Size( FT_Size size );++ /* */+++FT_END_HEADER++#endif /* __FTSIZES_H__ */+++/* END */
+ include/freetype/ftsnames.h view
@@ -0,0 +1,200 @@+/***************************************************************************/+/* */+/* ftsnames.h */+/* */+/* Simple interface to access SFNT name tables (which are used */+/* to hold font names, copyright info, notices, etc.) (specification). */+/* */+/* This is _not_ used to retrieve glyph names! */+/* */+/* Copyright 1996-2001, 2002, 2003, 2006, 2009, 2010 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 __FT_SFNT_NAMES_H__+#define __FT_SFNT_NAMES_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+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* sfnt_names */+ /* */+ /* <Title> */+ /* SFNT Names */+ /* */+ /* <Abstract> */+ /* Access the names embedded in TrueType and OpenType files. */+ /* */+ /* <Description> */+ /* The TrueType and OpenType specifications allow the inclusion of */+ /* a special `names table' in font files. This table contains */+ /* textual (and internationalized) information regarding the font, */+ /* like family name, copyright, version, etc. */+ /* */+ /* The definitions below are used to access them if available. */+ /* */+ /* Note that this has nothing to do with glyph names! */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_SfntName */+ /* */+ /* <Description> */+ /* A structure used to model an SFNT `name' table entry. */+ /* */+ /* <Fields> */+ /* platform_id :: The platform ID for `string'. */+ /* */+ /* encoding_id :: The encoding ID for `string'. */+ /* */+ /* language_id :: The language ID for `string'. */+ /* */+ /* name_id :: An identifier for `string'. */+ /* */+ /* string :: The `name' string. Note that its format differs */+ /* depending on the (platform,encoding) pair. It can */+ /* be a Pascal String, a UTF-16 one, etc. */+ /* */+ /* Generally speaking, the string is not */+ /* zero-terminated. Please refer to the TrueType */+ /* specification for details. */+ /* */+ /* string_len :: The length of `string' in bytes. */+ /* */+ /* <Note> */+ /* Possible values for `platform_id', `encoding_id', `language_id', */+ /* and `name_id' are given in the file `ttnameid.h'. For details */+ /* please refer to the TrueType or OpenType specification. */+ /* */+ /* See also @TT_PLATFORM_XXX, @TT_APPLE_ID_XXX, @TT_MAC_ID_XXX, */+ /* @TT_ISO_ID_XXX, and @TT_MS_ID_XXX. */+ /* */+ typedef struct FT_SfntName_+ {+ FT_UShort platform_id;+ FT_UShort encoding_id;+ FT_UShort language_id;+ FT_UShort name_id;++ FT_Byte* string; /* this string is *not* null-terminated! */+ FT_UInt string_len; /* in bytes */++ } FT_SfntName;+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Get_Sfnt_Name_Count */+ /* */+ /* <Description> */+ /* Retrieve the number of name strings in the SFNT `name' table. */+ /* */+ /* <Input> */+ /* face :: A handle to the source face. */+ /* */+ /* <Return> */+ /* The number of strings in the `name' table. */+ /* */+ FT_EXPORT( FT_UInt )+ FT_Get_Sfnt_Name_Count( FT_Face face );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Get_Sfnt_Name */+ /* */+ /* <Description> */+ /* Retrieve a string of the SFNT `name' table for a given index. */+ /* */+ /* <Input> */+ /* face :: A handle to the source face. */+ /* */+ /* idx :: The index of the `name' string. */+ /* */+ /* <Output> */+ /* aname :: The indexed @FT_SfntName structure. */+ /* */+ /* <Return> */+ /* FreeType error code. 0~means success. */+ /* */+ /* <Note> */+ /* The `string' array returned in the `aname' structure is not */+ /* null-terminated. The application should deallocate it if it is no */+ /* longer in use. */+ /* */+ /* Use @FT_Get_Sfnt_Name_Count to get the total number of available */+ /* `name' table entries, then do a loop until you get the right */+ /* platform, encoding, and name ID. */+ /* */+ FT_EXPORT( FT_Error )+ FT_Get_Sfnt_Name( FT_Face face,+ FT_UInt idx,+ FT_SfntName *aname );+++ /***************************************************************************+ *+ * @constant:+ * FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY+ *+ * @description:+ * A constant used as the tag of @FT_Parameter structures to make+ * FT_Open_Face() ignore preferred family subfamily names in `name'+ * table since OpenType version 1.4. For backwards compatibility with+ * legacy systems which has 4-face-per-family restriction.+ *+ */+#define FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY FT_MAKE_TAG( 'i', 'g', 'p', 'f' )+++ /***************************************************************************+ *+ * @constant:+ * FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY+ *+ * @description:+ * A constant used as the tag of @FT_Parameter structures to make+ * FT_Open_Face() ignore preferred subfamily names in `name' table since+ * OpenType version 1.4. For backwards compatibility with legacy+ * systems which has 4-face-per-family restriction.+ *+ */+#define FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY FT_MAKE_TAG( 'i', 'g', 'p', 's' )++ /* */+++FT_END_HEADER++#endif /* __FT_SFNT_NAMES_H__ */+++/* END */
+ include/freetype/ftstroke.h view
@@ -0,0 +1,716 @@+/***************************************************************************/+/* */+/* ftstroke.h */+/* */+/* FreeType path stroker (specification). */+/* */+/* Copyright 2002, 2003, 2004, 2005, 2006, 2008, 2009 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 __FT_STROKE_H__+#define __FT_STROKE_H__++#include <ft2build.h>+#include FT_OUTLINE_H+#include FT_GLYPH_H+++FT_BEGIN_HEADER+++ /************************************************************************+ *+ * @section:+ * glyph_stroker+ *+ * @title:+ * Glyph Stroker+ *+ * @abstract:+ * Generating bordered and stroked glyphs.+ *+ * @description:+ * This component generates stroked outlines of a given vectorial+ * glyph. It also allows you to retrieve the `outside' and/or the+ * `inside' borders of the stroke.+ *+ * This can be useful to generate `bordered' glyph, i.e., glyphs+ * displayed with a coloured (and anti-aliased) border around their+ * shape.+ */+++ /**************************************************************+ *+ * @type:+ * FT_Stroker+ *+ * @description:+ * Opaque handler to a path stroker object.+ */+ typedef struct FT_StrokerRec_* FT_Stroker;+++ /**************************************************************+ *+ * @enum:+ * FT_Stroker_LineJoin+ *+ * @description:+ * These values determine how two joining lines are rendered+ * in a stroker.+ *+ * @values:+ * FT_STROKER_LINEJOIN_ROUND ::+ * Used to render rounded line joins. Circular arcs are used+ * to join two lines smoothly.+ *+ * FT_STROKER_LINEJOIN_BEVEL ::+ * Used to render beveled line joins; i.e., the two joining lines+ * are extended until they intersect.+ *+ * FT_STROKER_LINEJOIN_MITER ::+ * Same as beveled rendering, except that an additional line+ * break is added if the angle between the two joining lines+ * is too closed (this is useful to avoid unpleasant spikes+ * in beveled rendering).+ */+ typedef enum FT_Stroker_LineJoin_+ {+ FT_STROKER_LINEJOIN_ROUND = 0,+ FT_STROKER_LINEJOIN_BEVEL,+ FT_STROKER_LINEJOIN_MITER++ } FT_Stroker_LineJoin;+++ /**************************************************************+ *+ * @enum:+ * FT_Stroker_LineCap+ *+ * @description:+ * These values determine how the end of opened sub-paths are+ * rendered in a stroke.+ *+ * @values:+ * FT_STROKER_LINECAP_BUTT ::+ * The end of lines is rendered as a full stop on the last+ * point itself.+ *+ * FT_STROKER_LINECAP_ROUND ::+ * The end of lines is rendered as a half-circle around the+ * last point.+ *+ * FT_STROKER_LINECAP_SQUARE ::+ * The end of lines is rendered as a square around the+ * last point.+ */+ typedef enum FT_Stroker_LineCap_+ {+ FT_STROKER_LINECAP_BUTT = 0,+ FT_STROKER_LINECAP_ROUND,+ FT_STROKER_LINECAP_SQUARE++ } FT_Stroker_LineCap;+++ /**************************************************************+ *+ * @enum:+ * FT_StrokerBorder+ *+ * @description:+ * These values are used to select a given stroke border+ * in @FT_Stroker_GetBorderCounts and @FT_Stroker_ExportBorder.+ *+ * @values:+ * FT_STROKER_BORDER_LEFT ::+ * Select the left border, relative to the drawing direction.+ *+ * FT_STROKER_BORDER_RIGHT ::+ * Select the right border, relative to the drawing direction.+ *+ * @note:+ * Applications are generally interested in the `inside' and `outside'+ * borders. However, there is no direct mapping between these and the+ * `left' and `right' ones, since this really depends on the glyph's+ * drawing orientation, which varies between font formats.+ *+ * You can however use @FT_Outline_GetInsideBorder and+ * @FT_Outline_GetOutsideBorder to get these.+ */+ typedef enum FT_StrokerBorder_+ {+ FT_STROKER_BORDER_LEFT = 0,+ FT_STROKER_BORDER_RIGHT++ } FT_StrokerBorder;+++ /**************************************************************+ *+ * @function:+ * FT_Outline_GetInsideBorder+ *+ * @description:+ * Retrieve the @FT_StrokerBorder value corresponding to the+ * `inside' borders of a given outline.+ *+ * @input:+ * outline ::+ * The source outline handle.+ *+ * @return:+ * The border index. @FT_STROKER_BORDER_RIGHT for empty or invalid+ * outlines.+ */+ FT_EXPORT( FT_StrokerBorder )+ FT_Outline_GetInsideBorder( FT_Outline* outline );+++ /**************************************************************+ *+ * @function:+ * FT_Outline_GetOutsideBorder+ *+ * @description:+ * Retrieve the @FT_StrokerBorder value corresponding to the+ * `outside' borders of a given outline.+ *+ * @input:+ * outline ::+ * The source outline handle.+ *+ * @return:+ * The border index. @FT_STROKER_BORDER_LEFT for empty or invalid+ * outlines.+ */+ FT_EXPORT( FT_StrokerBorder )+ FT_Outline_GetOutsideBorder( FT_Outline* outline );+++ /**************************************************************+ *+ * @function:+ * FT_Stroker_New+ *+ * @description:+ * Create a new stroker object.+ *+ * @input:+ * library ::+ * FreeType library handle.+ *+ * @output:+ * astroker ::+ * A new stroker object handle. NULL in case of error.+ *+ * @return:+ * FreeType error code. 0~means success.+ */+ FT_EXPORT( FT_Error )+ FT_Stroker_New( FT_Library library,+ FT_Stroker *astroker );+++ /**************************************************************+ *+ * @function:+ * FT_Stroker_Set+ *+ * @description:+ * Reset a stroker object's attributes.+ *+ * @input:+ * stroker ::+ * The target stroker handle.+ *+ * radius ::+ * The border radius.+ *+ * line_cap ::+ * The line cap style.+ *+ * line_join ::+ * The line join style.+ *+ * miter_limit ::+ * The miter limit for the FT_STROKER_LINEJOIN_MITER style,+ * expressed as 16.16 fixed point value.+ *+ * @note:+ * The radius is expressed in the same units as the outline+ * coordinates.+ */+ FT_EXPORT( void )+ FT_Stroker_Set( FT_Stroker stroker,+ FT_Fixed radius,+ FT_Stroker_LineCap line_cap,+ FT_Stroker_LineJoin line_join,+ FT_Fixed miter_limit );+++ /**************************************************************+ *+ * @function:+ * FT_Stroker_Rewind+ *+ * @description:+ * Reset a stroker object without changing its attributes.+ * You should call this function before beginning a new+ * series of calls to @FT_Stroker_BeginSubPath or+ * @FT_Stroker_EndSubPath.+ *+ * @input:+ * stroker ::+ * The target stroker handle.+ */+ FT_EXPORT( void )+ FT_Stroker_Rewind( FT_Stroker stroker );+++ /**************************************************************+ *+ * @function:+ * FT_Stroker_ParseOutline+ *+ * @description:+ * A convenience function used to parse a whole outline with+ * the stroker. The resulting outline(s) can be retrieved+ * later by functions like @FT_Stroker_GetCounts and @FT_Stroker_Export.+ *+ * @input:+ * stroker ::+ * The target stroker handle.+ *+ * outline ::+ * The source outline.+ *+ * opened ::+ * A boolean. If~1, the outline is treated as an open path instead+ * of a closed one.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * If `opened' is~0 (the default), the outline is treated as a closed+ * path, and the stroker generates two distinct `border' outlines.+ *+ * If `opened' is~1, the outline is processed as an open path, and the+ * stroker generates a single `stroke' outline.+ *+ * This function calls @FT_Stroker_Rewind automatically.+ */+ FT_EXPORT( FT_Error )+ FT_Stroker_ParseOutline( FT_Stroker stroker,+ FT_Outline* outline,+ FT_Bool opened );+++ /**************************************************************+ *+ * @function:+ * FT_Stroker_BeginSubPath+ *+ * @description:+ * Start a new sub-path in the stroker.+ *+ * @input:+ * stroker ::+ * The target stroker handle.+ *+ * to ::+ * A pointer to the start vector.+ *+ * open ::+ * A boolean. If~1, the sub-path is treated as an open one.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * This function is useful when you need to stroke a path that is+ * not stored as an @FT_Outline object.+ */+ FT_EXPORT( FT_Error )+ FT_Stroker_BeginSubPath( FT_Stroker stroker,+ FT_Vector* to,+ FT_Bool open );+++ /**************************************************************+ *+ * @function:+ * FT_Stroker_EndSubPath+ *+ * @description:+ * Close the current sub-path in the stroker.+ *+ * @input:+ * stroker ::+ * The target stroker handle.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * You should call this function after @FT_Stroker_BeginSubPath.+ * If the subpath was not `opened', this function `draws' a+ * single line segment to the start position when needed.+ */+ FT_EXPORT( FT_Error )+ FT_Stroker_EndSubPath( FT_Stroker stroker );+++ /**************************************************************+ *+ * @function:+ * FT_Stroker_LineTo+ *+ * @description:+ * `Draw' a single line segment in the stroker's current sub-path,+ * from the last position.+ *+ * @input:+ * stroker ::+ * The target stroker handle.+ *+ * to ::+ * A pointer to the destination point.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * You should call this function between @FT_Stroker_BeginSubPath and+ * @FT_Stroker_EndSubPath.+ */+ FT_EXPORT( FT_Error )+ FT_Stroker_LineTo( FT_Stroker stroker,+ FT_Vector* to );+++ /**************************************************************+ *+ * @function:+ * FT_Stroker_ConicTo+ *+ * @description:+ * `Draw' a single quadratic Bézier in the stroker's current sub-path,+ * from the last position.+ *+ * @input:+ * stroker ::+ * The target stroker handle.+ *+ * control ::+ * A pointer to a Bézier control point.+ *+ * to ::+ * A pointer to the destination point.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * You should call this function between @FT_Stroker_BeginSubPath and+ * @FT_Stroker_EndSubPath.+ */+ FT_EXPORT( FT_Error )+ FT_Stroker_ConicTo( FT_Stroker stroker,+ FT_Vector* control,+ FT_Vector* to );+++ /**************************************************************+ *+ * @function:+ * FT_Stroker_CubicTo+ *+ * @description:+ * `Draw' a single cubic Bézier in the stroker's current sub-path,+ * from the last position.+ *+ * @input:+ * stroker ::+ * The target stroker handle.+ *+ * control1 ::+ * A pointer to the first Bézier control point.+ *+ * control2 ::+ * A pointer to second Bézier control point.+ *+ * to ::+ * A pointer to the destination point.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * You should call this function between @FT_Stroker_BeginSubPath and+ * @FT_Stroker_EndSubPath.+ */+ FT_EXPORT( FT_Error )+ FT_Stroker_CubicTo( FT_Stroker stroker,+ FT_Vector* control1,+ FT_Vector* control2,+ FT_Vector* to );+++ /**************************************************************+ *+ * @function:+ * FT_Stroker_GetBorderCounts+ *+ * @description:+ * Call this function once you have finished parsing your paths+ * with the stroker. It returns the number of points and+ * contours necessary to export one of the `border' or `stroke'+ * outlines generated by the stroker.+ *+ * @input:+ * stroker ::+ * The target stroker handle.+ *+ * border ::+ * The border index.+ *+ * @output:+ * anum_points ::+ * The number of points.+ *+ * anum_contours ::+ * The number of contours.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * When an outline, or a sub-path, is `closed', the stroker generates+ * two independent `border' outlines, named `left' and `right'.+ *+ * When the outline, or a sub-path, is `opened', the stroker merges+ * the `border' outlines with caps. The `left' border receives all+ * points, while the `right' border becomes empty.+ *+ * Use the function @FT_Stroker_GetCounts instead if you want to+ * retrieve the counts associated to both borders.+ */+ FT_EXPORT( FT_Error )+ FT_Stroker_GetBorderCounts( FT_Stroker stroker,+ FT_StrokerBorder border,+ FT_UInt *anum_points,+ FT_UInt *anum_contours );+++ /**************************************************************+ *+ * @function:+ * FT_Stroker_ExportBorder+ *+ * @description:+ * Call this function after @FT_Stroker_GetBorderCounts to+ * export the corresponding border to your own @FT_Outline+ * structure.+ *+ * Note that this function appends the border points and+ * contours to your outline, but does not try to resize its+ * arrays.+ *+ * @input:+ * stroker ::+ * The target stroker handle.+ *+ * border ::+ * The border index.+ *+ * outline ::+ * The target outline handle.+ *+ * @note:+ * Always call this function after @FT_Stroker_GetBorderCounts to+ * get sure that there is enough room in your @FT_Outline object to+ * receive all new data.+ *+ * When an outline, or a sub-path, is `closed', the stroker generates+ * two independent `border' outlines, named `left' and `right'+ *+ * When the outline, or a sub-path, is `opened', the stroker merges+ * the `border' outlines with caps. The `left' border receives all+ * points, while the `right' border becomes empty.+ *+ * Use the function @FT_Stroker_Export instead if you want to+ * retrieve all borders at once.+ */+ FT_EXPORT( void )+ FT_Stroker_ExportBorder( FT_Stroker stroker,+ FT_StrokerBorder border,+ FT_Outline* outline );+++ /**************************************************************+ *+ * @function:+ * FT_Stroker_GetCounts+ *+ * @description:+ * Call this function once you have finished parsing your paths+ * with the stroker. It returns the number of points and+ * contours necessary to export all points/borders from the stroked+ * outline/path.+ *+ * @input:+ * stroker ::+ * The target stroker handle.+ *+ * @output:+ * anum_points ::+ * The number of points.+ *+ * anum_contours ::+ * The number of contours.+ *+ * @return:+ * FreeType error code. 0~means success.+ */+ FT_EXPORT( FT_Error )+ FT_Stroker_GetCounts( FT_Stroker stroker,+ FT_UInt *anum_points,+ FT_UInt *anum_contours );+++ /**************************************************************+ *+ * @function:+ * FT_Stroker_Export+ *+ * @description:+ * Call this function after @FT_Stroker_GetBorderCounts to+ * export all borders to your own @FT_Outline structure.+ *+ * Note that this function appends the border points and+ * contours to your outline, but does not try to resize its+ * arrays.+ *+ * @input:+ * stroker ::+ * The target stroker handle.+ *+ * outline ::+ * The target outline handle.+ */+ FT_EXPORT( void )+ FT_Stroker_Export( FT_Stroker stroker,+ FT_Outline* outline );+++ /**************************************************************+ *+ * @function:+ * FT_Stroker_Done+ *+ * @description:+ * Destroy a stroker object.+ *+ * @input:+ * stroker ::+ * A stroker handle. Can be NULL.+ */+ FT_EXPORT( void )+ FT_Stroker_Done( FT_Stroker stroker );+++ /**************************************************************+ *+ * @function:+ * FT_Glyph_Stroke+ *+ * @description:+ * Stroke a given outline glyph object with a given stroker.+ *+ * @inout:+ * pglyph ::+ * Source glyph handle on input, new glyph handle on output.+ *+ * @input:+ * stroker ::+ * A stroker handle.+ *+ * destroy ::+ * A Boolean. If~1, the source glyph object is destroyed+ * on success.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * The source glyph is untouched in case of error.+ */+ FT_EXPORT( FT_Error )+ FT_Glyph_Stroke( FT_Glyph *pglyph,+ FT_Stroker stroker,+ FT_Bool destroy );+++ /**************************************************************+ *+ * @function:+ * FT_Glyph_StrokeBorder+ *+ * @description:+ * Stroke a given outline glyph object with a given stroker, but+ * only return either its inside or outside border.+ *+ * @inout:+ * pglyph ::+ * Source glyph handle on input, new glyph handle on output.+ *+ * @input:+ * stroker ::+ * A stroker handle.+ *+ * inside ::+ * A Boolean. If~1, return the inside border, otherwise+ * the outside border.+ *+ * destroy ::+ * A Boolean. If~1, the source glyph object is destroyed+ * on success.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * The source glyph is untouched in case of error.+ */+ FT_EXPORT( FT_Error )+ FT_Glyph_StrokeBorder( FT_Glyph *pglyph,+ FT_Stroker stroker,+ FT_Bool inside,+ FT_Bool destroy );++ /* */++FT_END_HEADER++#endif /* __FT_STROKE_H__ */+++/* END */+++/* Local Variables: */+/* coding: utf-8 */+/* End: */
+ include/freetype/ftsynth.h view
@@ -0,0 +1,80 @@+/***************************************************************************/+/* */+/* ftsynth.h */+/* */+/* FreeType synthesizing code for emboldening and slanting */+/* (specification). */+/* */+/* Copyright 2000-2001, 2003, 2006, 2008 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. */+/* */+/***************************************************************************/+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /********* *********/+ /********* WARNING, THIS IS ALPHA CODE! THIS API *********/+ /********* IS DUE TO CHANGE UNTIL STRICTLY NOTIFIED BY THE *********/+ /********* FREETYPE DEVELOPMENT TEAM *********/+ /********* *********/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ /* Main reason for not lifting the functions in this module to a */+ /* `standard' API is that the used parameters for emboldening and */+ /* slanting are not configurable. Consider the functions as a */+ /* code resource which should be copied into the application and */+ /* adapted to the particular needs. */+++#ifndef __FTSYNTH_H__+#define __FTSYNTH_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+++FT_BEGIN_HEADER++ /* Embolden a glyph by a `reasonable' value (which is highly a matter of */+ /* taste). This function is actually a convenience function, providing */+ /* a wrapper for @FT_Outline_Embolden and @FT_Bitmap_Embolden. */+ /* */+ /* For emboldened outlines the metrics are estimates only; if you need */+ /* precise values you should call @FT_Outline_Get_CBox. */+ FT_EXPORT( void )+ FT_GlyphSlot_Embolden( FT_GlyphSlot slot );++ /* Slant an outline glyph to the right by about 12 degrees. */+ FT_EXPORT( void )+ FT_GlyphSlot_Oblique( FT_GlyphSlot slot );++ /* */++FT_END_HEADER++#endif /* __FTSYNTH_H__ */+++/* END */
+ include/freetype/ftsystem.h view
@@ -0,0 +1,347 @@+/***************************************************************************/+/* */+/* ftsystem.h */+/* */+/* FreeType low-level system interface definition (specification). */+/* */+/* Copyright 1996-2001, 2002, 2005, 2010 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 __FTSYSTEM_H__+#define __FTSYSTEM_H__+++#include <ft2build.h>+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* system_interface */+ /* */+ /* <Title> */+ /* System Interface */+ /* */+ /* <Abstract> */+ /* How FreeType manages memory and i/o. */+ /* */+ /* <Description> */+ /* This section contains various definitions related to memory */+ /* management and i/o access. You need to understand this */+ /* information if you want to use a custom memory manager or you own */+ /* i/o streams. */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* M E M O R Y M A N A G E M E N T */+ /* */+ /*************************************************************************/+++ /*************************************************************************+ *+ * @type:+ * FT_Memory+ *+ * @description:+ * A handle to a given memory manager object, defined with an+ * @FT_MemoryRec structure.+ *+ */+ typedef struct FT_MemoryRec_* FT_Memory;+++ /*************************************************************************+ *+ * @functype:+ * FT_Alloc_Func+ *+ * @description:+ * A function used to allocate `size' bytes from `memory'.+ *+ * @input:+ * memory ::+ * A handle to the source memory manager.+ *+ * size ::+ * The size in bytes to allocate.+ *+ * @return:+ * Address of new memory block. 0~in case of failure.+ *+ */+ typedef void*+ (*FT_Alloc_Func)( FT_Memory memory,+ long size );+++ /*************************************************************************+ *+ * @functype:+ * FT_Free_Func+ *+ * @description:+ * A function used to release a given block of memory.+ *+ * @input:+ * memory ::+ * A handle to the source memory manager.+ *+ * block ::+ * The address of the target memory block.+ *+ */+ typedef void+ (*FT_Free_Func)( FT_Memory memory,+ void* block );+++ /*************************************************************************+ *+ * @functype:+ * FT_Realloc_Func+ *+ * @description:+ * A function used to re-allocate a given block of memory.+ *+ * @input:+ * memory ::+ * A handle to the source memory manager.+ *+ * cur_size ::+ * The block's current size in bytes.+ *+ * new_size ::+ * The block's requested new size.+ *+ * block ::+ * The block's current address.+ *+ * @return:+ * New block address. 0~in case of memory shortage.+ *+ * @note:+ * In case of error, the old block must still be available.+ *+ */+ typedef void*+ (*FT_Realloc_Func)( FT_Memory memory,+ long cur_size,+ long new_size,+ void* block );+++ /*************************************************************************+ *+ * @struct:+ * FT_MemoryRec+ *+ * @description:+ * A structure used to describe a given memory manager to FreeType~2.+ *+ * @fields:+ * user ::+ * A generic typeless pointer for user data.+ *+ * alloc ::+ * A pointer type to an allocation function.+ *+ * free ::+ * A pointer type to an memory freeing function.+ *+ * realloc ::+ * A pointer type to a reallocation function.+ *+ */+ struct FT_MemoryRec_+ {+ void* user;+ FT_Alloc_Func alloc;+ FT_Free_Func free;+ FT_Realloc_Func realloc;+ };+++ /*************************************************************************/+ /* */+ /* I / O M A N A G E M E N T */+ /* */+ /*************************************************************************/+++ /*************************************************************************+ *+ * @type:+ * FT_Stream+ *+ * @description:+ * A handle to an input stream.+ *+ */+ typedef struct FT_StreamRec_* FT_Stream;+++ /*************************************************************************+ *+ * @struct:+ * FT_StreamDesc+ *+ * @description:+ * A union type used to store either a long or a pointer. This is used+ * to store a file descriptor or a `FILE*' in an input stream.+ *+ */+ typedef union FT_StreamDesc_+ {+ long value;+ void* pointer;++ } FT_StreamDesc;+++ /*************************************************************************+ *+ * @functype:+ * FT_Stream_IoFunc+ *+ * @description:+ * A function used to seek and read data from a given input stream.+ *+ * @input:+ * stream ::+ * A handle to the source stream.+ *+ * offset ::+ * The offset of read in stream (always from start).+ *+ * buffer ::+ * The address of the read buffer.+ *+ * count ::+ * The number of bytes to read from the stream.+ *+ * @return:+ * The number of bytes effectively read by the stream.+ *+ * @note:+ * This function might be called to perform a seek or skip operation+ * with a `count' of~0. A non-zero return value then indicates an+ * error.+ *+ */+ typedef unsigned long+ (*FT_Stream_IoFunc)( FT_Stream stream,+ unsigned long offset,+ unsigned char* buffer,+ unsigned long count );+++ /*************************************************************************+ *+ * @functype:+ * FT_Stream_CloseFunc+ *+ * @description:+ * A function used to close a given input stream.+ *+ * @input:+ * stream ::+ * A handle to the target stream.+ *+ */+ typedef void+ (*FT_Stream_CloseFunc)( FT_Stream stream );+++ /*************************************************************************+ *+ * @struct:+ * FT_StreamRec+ *+ * @description:+ * A structure used to describe an input stream.+ *+ * @input:+ * base ::+ * For memory-based streams, this is the address of the first stream+ * byte in memory. This field should always be set to NULL for+ * disk-based streams.+ *+ * size ::+ * The stream size in bytes.+ *+ * pos ::+ * The current position within the stream.+ *+ * descriptor ::+ * This field is a union that can hold an integer or a pointer. It is+ * used by stream implementations to store file descriptors or `FILE*'+ * pointers.+ *+ * pathname ::+ * This field is completely ignored by FreeType. However, it is often+ * useful during debugging to use it to store the stream's filename+ * (where available).+ *+ * read ::+ * The stream's input function.+ *+ * close ::+ * The stream's close function.+ *+ * memory ::+ * The memory manager to use to preload frames. This is set+ * internally by FreeType and shouldn't be touched by stream+ * implementations.+ *+ * cursor ::+ * This field is set and used internally by FreeType when parsing+ * frames.+ *+ * limit ::+ * This field is set and used internally by FreeType when parsing+ * frames.+ *+ */+ typedef struct FT_StreamRec_+ {+ unsigned char* base;+ unsigned long size;+ unsigned long pos;++ FT_StreamDesc descriptor;+ FT_StreamDesc pathname;+ FT_Stream_IoFunc read;+ FT_Stream_CloseFunc close;++ FT_Memory memory;+ unsigned char* cursor;+ unsigned char* limit;++ } FT_StreamRec;+++ /* */+++FT_END_HEADER++#endif /* __FTSYSTEM_H__ */+++/* END */
+ include/freetype/fttrigon.h view
@@ -0,0 +1,350 @@+/***************************************************************************/+/* */+/* fttrigon.h */+/* */+/* FreeType trigonometric functions (specification). */+/* */+/* Copyright 2001, 2003, 2005, 2007 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 __FTTRIGON_H__+#define __FTTRIGON_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+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* computations */+ /* */+ /*************************************************************************/+++ /*************************************************************************+ *+ * @type:+ * FT_Angle+ *+ * @description:+ * This type is used to model angle values in FreeType. Note that the+ * angle is a 16.16 fixed float value expressed in degrees.+ *+ */+ typedef FT_Fixed FT_Angle;+++ /*************************************************************************+ *+ * @macro:+ * FT_ANGLE_PI+ *+ * @description:+ * The angle pi expressed in @FT_Angle units.+ *+ */+#define FT_ANGLE_PI ( 180L << 16 )+++ /*************************************************************************+ *+ * @macro:+ * FT_ANGLE_2PI+ *+ * @description:+ * The angle 2*pi expressed in @FT_Angle units.+ *+ */+#define FT_ANGLE_2PI ( FT_ANGLE_PI * 2 )+++ /*************************************************************************+ *+ * @macro:+ * FT_ANGLE_PI2+ *+ * @description:+ * The angle pi/2 expressed in @FT_Angle units.+ *+ */+#define FT_ANGLE_PI2 ( FT_ANGLE_PI / 2 )+++ /*************************************************************************+ *+ * @macro:+ * FT_ANGLE_PI4+ *+ * @description:+ * The angle pi/4 expressed in @FT_Angle units.+ *+ */+#define FT_ANGLE_PI4 ( FT_ANGLE_PI / 4 )+++ /*************************************************************************+ *+ * @function:+ * FT_Sin+ *+ * @description:+ * Return the sinus of a given angle in fixed point format.+ *+ * @input:+ * angle ::+ * The input angle.+ *+ * @return:+ * The sinus value.+ *+ * @note:+ * If you need both the sinus and cosinus for a given angle, use the+ * function @FT_Vector_Unit.+ *+ */+ FT_EXPORT( FT_Fixed )+ FT_Sin( FT_Angle angle );+++ /*************************************************************************+ *+ * @function:+ * FT_Cos+ *+ * @description:+ * Return the cosinus of a given angle in fixed point format.+ *+ * @input:+ * angle ::+ * The input angle.+ *+ * @return:+ * The cosinus value.+ *+ * @note:+ * If you need both the sinus and cosinus for a given angle, use the+ * function @FT_Vector_Unit.+ *+ */+ FT_EXPORT( FT_Fixed )+ FT_Cos( FT_Angle angle );+++ /*************************************************************************+ *+ * @function:+ * FT_Tan+ *+ * @description:+ * Return the tangent of a given angle in fixed point format.+ *+ * @input:+ * angle ::+ * The input angle.+ *+ * @return:+ * The tangent value.+ *+ */+ FT_EXPORT( FT_Fixed )+ FT_Tan( FT_Angle angle );+++ /*************************************************************************+ *+ * @function:+ * FT_Atan2+ *+ * @description:+ * Return the arc-tangent corresponding to a given vector (x,y) in+ * the 2d plane.+ *+ * @input:+ * x ::+ * The horizontal vector coordinate.+ *+ * y ::+ * The vertical vector coordinate.+ *+ * @return:+ * The arc-tangent value (i.e. angle).+ *+ */+ FT_EXPORT( FT_Angle )+ FT_Atan2( FT_Fixed x,+ FT_Fixed y );+++ /*************************************************************************+ *+ * @function:+ * FT_Angle_Diff+ *+ * @description:+ * Return the difference between two angles. The result is always+ * constrained to the ]-PI..PI] interval.+ *+ * @input:+ * angle1 ::+ * First angle.+ *+ * angle2 ::+ * Second angle.+ *+ * @return:+ * Constrained value of `value2-value1'.+ *+ */+ FT_EXPORT( FT_Angle )+ FT_Angle_Diff( FT_Angle angle1,+ FT_Angle angle2 );+++ /*************************************************************************+ *+ * @function:+ * FT_Vector_Unit+ *+ * @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)'.+ *+ * This function is useful to retrieve both the sinus and cosinus of a+ * given angle quickly.+ *+ * @output:+ * vec ::+ * The address of target vector.+ *+ * @input:+ * angle ::+ * The address of angle.+ *+ */+ FT_EXPORT( void )+ FT_Vector_Unit( FT_Vector* vec,+ FT_Angle angle );+++ /*************************************************************************+ *+ * @function:+ * FT_Vector_Rotate+ *+ * @description:+ * Rotate a vector by a given angle.+ *+ * @inout:+ * vec ::+ * The address of target vector.+ *+ * @input:+ * angle ::+ * The address of angle.+ *+ */+ FT_EXPORT( void )+ FT_Vector_Rotate( FT_Vector* vec,+ FT_Angle angle );+++ /*************************************************************************+ *+ * @function:+ * FT_Vector_Length+ *+ * @description:+ * Return the length of a given vector.+ *+ * @input:+ * vec ::+ * The address of target vector.+ *+ * @return:+ * The vector length, expressed in the same units that the original+ * vector coordinates.+ *+ */+ FT_EXPORT( FT_Fixed )+ FT_Vector_Length( FT_Vector* vec );+++ /*************************************************************************+ *+ * @function:+ * FT_Vector_Polarize+ *+ * @description:+ * Compute both the length and angle of a given vector.+ *+ * @input:+ * vec ::+ * The address of source vector.+ *+ * @output:+ * length ::+ * The vector length.+ *+ * angle ::+ * The vector angle.+ *+ */+ FT_EXPORT( void )+ FT_Vector_Polarize( FT_Vector* vec,+ FT_Fixed *length,+ FT_Angle *angle );+++ /*************************************************************************+ *+ * @function:+ * FT_Vector_From_Polar+ *+ * @description:+ * Compute vector coordinates from a length and angle.+ *+ * @output:+ * vec ::+ * The address of source vector.+ *+ * @input:+ * length ::+ * The vector length.+ *+ * angle ::+ * The vector angle.+ *+ */+ FT_EXPORT( void )+ FT_Vector_From_Polar( FT_Vector* vec,+ FT_Fixed length,+ FT_Angle angle );++ /* */+++FT_END_HEADER++#endif /* __FTTRIGON_H__ */+++/* END */
+ include/freetype/fttypes.h view
@@ -0,0 +1,588 @@+/***************************************************************************/+/* */+/* fttypes.h */+/* */+/* FreeType simple types definitions (specification only). */+/* */+/* Copyright 1996-2001, 2002, 2004, 2006, 2007, 2008 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 __FTTYPES_H__+#define __FTTYPES_H__+++#include <ft2build.h>+#include FT_CONFIG_CONFIG_H+#include FT_SYSTEM_H+#include FT_IMAGE_H++#include <stddef.h>+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* basic_types */+ /* */+ /* <Title> */+ /* Basic Data Types */+ /* */+ /* <Abstract> */+ /* The basic data types defined by the library. */+ /* */+ /* <Description> */+ /* This section contains the basic data types defined by FreeType~2, */+ /* ranging from simple scalar types to bitmap descriptors. More */+ /* font-specific structures are defined in a different section. */+ /* */+ /* <Order> */+ /* FT_Byte */+ /* FT_Bytes */+ /* FT_Char */+ /* FT_Int */+ /* FT_UInt */+ /* FT_Int16 */+ /* FT_UInt16 */+ /* FT_Int32 */+ /* FT_UInt32 */+ /* FT_Short */+ /* FT_UShort */+ /* FT_Long */+ /* FT_ULong */+ /* FT_Bool */+ /* FT_Offset */+ /* FT_PtrDist */+ /* FT_String */+ /* FT_Tag */+ /* FT_Error */+ /* FT_Fixed */+ /* FT_Pointer */+ /* FT_Pos */+ /* FT_Vector */+ /* FT_BBox */+ /* FT_Matrix */+ /* FT_FWord */+ /* FT_UFWord */+ /* FT_F2Dot14 */+ /* FT_UnitVector */+ /* FT_F26Dot6 */+ /* */+ /* */+ /* FT_Generic */+ /* FT_Generic_Finalizer */+ /* */+ /* FT_Bitmap */+ /* FT_Pixel_Mode */+ /* FT_Palette_Mode */+ /* FT_Glyph_Format */+ /* FT_IMAGE_TAG */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_Bool */+ /* */+ /* <Description> */+ /* A typedef of unsigned char, used for simple booleans. As usual, */+ /* values 1 and~0 represent true and false, respectively. */+ /* */+ typedef unsigned char FT_Bool;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_FWord */+ /* */+ /* <Description> */+ /* A signed 16-bit integer used to store a distance in original font */+ /* units. */+ /* */+ typedef signed short FT_FWord; /* distance in FUnits */+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_UFWord */+ /* */+ /* <Description> */+ /* An unsigned 16-bit integer used to store a distance in original */+ /* font units. */+ /* */+ typedef unsigned short FT_UFWord; /* unsigned distance */+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_Char */+ /* */+ /* <Description> */+ /* A simple typedef for the _signed_ char type. */+ /* */+ typedef signed char FT_Char;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_Byte */+ /* */+ /* <Description> */+ /* A simple typedef for the _unsigned_ char type. */+ /* */+ typedef unsigned char FT_Byte;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_Bytes */+ /* */+ /* <Description> */+ /* A typedef for constant memory areas. */+ /* */+ typedef const FT_Byte* FT_Bytes;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_Tag */+ /* */+ /* <Description> */+ /* A typedef for 32-bit tags (as used in the SFNT format). */+ /* */+ typedef FT_UInt32 FT_Tag;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_String */+ /* */+ /* <Description> */+ /* A simple typedef for the char type, usually used for strings. */+ /* */+ typedef char FT_String;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_Short */+ /* */+ /* <Description> */+ /* A typedef for signed short. */+ /* */+ typedef signed short FT_Short;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_UShort */+ /* */+ /* <Description> */+ /* A typedef for unsigned short. */+ /* */+ typedef unsigned short FT_UShort;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_Int */+ /* */+ /* <Description> */+ /* A typedef for the int type. */+ /* */+ typedef signed int FT_Int;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_UInt */+ /* */+ /* <Description> */+ /* A typedef for the unsigned int type. */+ /* */+ typedef unsigned int FT_UInt;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_Long */+ /* */+ /* <Description> */+ /* A typedef for signed long. */+ /* */+ typedef signed long FT_Long;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_ULong */+ /* */+ /* <Description> */+ /* A typedef for unsigned long. */+ /* */+ typedef unsigned long FT_ULong;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_F2Dot14 */+ /* */+ /* <Description> */+ /* A signed 2.14 fixed float type used for unit vectors. */+ /* */+ typedef signed short FT_F2Dot14;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_F26Dot6 */+ /* */+ /* <Description> */+ /* A signed 26.6 fixed float type used for vectorial pixel */+ /* coordinates. */+ /* */+ typedef signed long FT_F26Dot6;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_Fixed */+ /* */+ /* <Description> */+ /* This type is used to store 16.16 fixed float values, like scaling */+ /* values or matrix coefficients. */+ /* */+ typedef signed long FT_Fixed;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_Error */+ /* */+ /* <Description> */+ /* The FreeType error code type. A value of~0 is always interpreted */+ /* as a successful operation. */+ /* */+ typedef int FT_Error;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_Pointer */+ /* */+ /* <Description> */+ /* A simple typedef for a typeless pointer. */+ /* */+ typedef void* FT_Pointer;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_Offset */+ /* */+ /* <Description> */+ /* This is equivalent to the ANSI~C `size_t' type, i.e., the largest */+ /* _unsigned_ integer type used to express a file size or position, */+ /* or a memory block size. */+ /* */+ typedef size_t FT_Offset;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_PtrDist */+ /* */+ /* <Description> */+ /* This is equivalent to the ANSI~C `ptrdiff_t' type, i.e., the */+ /* largest _signed_ integer type used to express the distance */+ /* between two pointers. */+ /* */+ typedef ft_ptrdiff_t FT_PtrDist;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_UnitVector */+ /* */+ /* <Description> */+ /* A simple structure used to store a 2D vector unit vector. Uses */+ /* FT_F2Dot14 types. */+ /* */+ /* <Fields> */+ /* x :: Horizontal coordinate. */+ /* */+ /* y :: Vertical coordinate. */+ /* */+ typedef struct FT_UnitVector_+ {+ FT_F2Dot14 x;+ FT_F2Dot14 y;++ } FT_UnitVector;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_Matrix */+ /* */+ /* <Description> */+ /* A simple structure used to store a 2x2 matrix. Coefficients are */+ /* in 16.16 fixed float format. The computation performed is: */+ /* */+ /* { */+ /* x' = x*xx + y*xy */+ /* y' = x*yx + y*yy */+ /* } */+ /* */+ /* <Fields> */+ /* xx :: Matrix coefficient. */+ /* */+ /* xy :: Matrix coefficient. */+ /* */+ /* yx :: Matrix coefficient. */+ /* */+ /* yy :: Matrix coefficient. */+ /* */+ typedef struct FT_Matrix_+ {+ FT_Fixed xx, xy;+ FT_Fixed yx, yy;++ } FT_Matrix;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_Data */+ /* */+ /* <Description> */+ /* Read-only binary data represented as a pointer and a length. */+ /* */+ /* <Fields> */+ /* pointer :: The data. */+ /* */+ /* length :: The length of the data in bytes. */+ /* */+ typedef struct FT_Data_+ {+ const FT_Byte* pointer;+ FT_Int length;++ } FT_Data;+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* FT_Generic_Finalizer */+ /* */+ /* <Description> */+ /* Describe a function used to destroy the `client' data of any */+ /* FreeType object. See the description of the @FT_Generic type for */+ /* details of usage. */+ /* */+ /* <Input> */+ /* The address of the FreeType object which is under finalization. */+ /* Its client data is accessed through its `generic' field. */+ /* */+ typedef void (*FT_Generic_Finalizer)(void* object);+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_Generic */+ /* */+ /* <Description> */+ /* Client applications often need to associate their own data to a */+ /* variety of FreeType core objects. For example, a text layout API */+ /* might want to associate a glyph cache to a given size object. */+ /* */+ /* Most FreeType object contains a `generic' field, of type */+ /* FT_Generic, which usage is left to client applications and font */+ /* servers. */+ /* */+ /* It can be used to store a pointer to client-specific data, as well */+ /* as the address of a `finalizer' function, which will be called by */+ /* FreeType when the object is destroyed (for example, the previous */+ /* client example would put the address of the glyph cache destructor */+ /* in the `finalizer' field). */+ /* */+ /* <Fields> */+ /* data :: A typeless pointer to any client-specified data. This */+ /* field is completely ignored by the FreeType library. */+ /* */+ /* finalizer :: A pointer to a `generic finalizer' function, which */+ /* will be called when the object is destroyed. If this */+ /* field is set to NULL, no code will be called. */+ /* */+ typedef struct FT_Generic_+ {+ void* data;+ FT_Generic_Finalizer finalizer;++ } FT_Generic;+++ /*************************************************************************/+ /* */+ /* <Macro> */+ /* FT_MAKE_TAG */+ /* */+ /* <Description> */+ /* This macro converts four-letter tags which are used to label */+ /* TrueType tables into an unsigned long to be used within FreeType. */+ /* */+ /* <Note> */+ /* The produced values *must* be 32-bit integers. Don't redefine */+ /* this macro. */+ /* */+#define FT_MAKE_TAG( _x1, _x2, _x3, _x4 ) \+ (FT_Tag) \+ ( ( (FT_ULong)_x1 << 24 ) | \+ ( (FT_ULong)_x2 << 16 ) | \+ ( (FT_ULong)_x3 << 8 ) | \+ (FT_ULong)_x4 )+++ /*************************************************************************/+ /*************************************************************************/+ /* */+ /* L I S T M A N A G E M E N T */+ /* */+ /*************************************************************************/+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* list_processing */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_ListNode */+ /* */+ /* <Description> */+ /* Many elements and objects in FreeType are listed through an */+ /* @FT_List record (see @FT_ListRec). As its name suggests, an */+ /* FT_ListNode is a handle to a single list element. */+ /* */+ typedef struct FT_ListNodeRec_* FT_ListNode;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* FT_List */+ /* */+ /* <Description> */+ /* A handle to a list record (see @FT_ListRec). */+ /* */+ typedef struct FT_ListRec_* FT_List;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_ListNodeRec */+ /* */+ /* <Description> */+ /* A structure used to hold a single list element. */+ /* */+ /* <Fields> */+ /* prev :: The previous element in the list. NULL if first. */+ /* */+ /* next :: The next element in the list. NULL if last. */+ /* */+ /* data :: A typeless pointer to the listed object. */+ /* */+ typedef struct FT_ListNodeRec_+ {+ FT_ListNode prev;+ FT_ListNode next;+ void* data;++ } FT_ListNodeRec;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_ListRec */+ /* */+ /* <Description> */+ /* A structure used to hold a simple doubly-linked list. These are */+ /* used in many parts of FreeType. */+ /* */+ /* <Fields> */+ /* head :: The head (first element) of doubly-linked list. */+ /* */+ /* tail :: The tail (last element) of doubly-linked list. */+ /* */+ typedef struct FT_ListRec_+ {+ FT_ListNode head;+ FT_ListNode tail;++ } FT_ListRec;+++ /* */++#define FT_IS_EMPTY( list ) ( (list).head == 0 )++ /* return base error code (without module-specific prefix) */+#define FT_ERROR_BASE( x ) ( (x) & 0xFF )++ /* return module error code */+#define FT_ERROR_MODULE( x ) ( (x) & 0xFF00U )++#define FT_BOOL( x ) ( (FT_Bool)( x ) )++FT_END_HEADER++#endif /* __FTTYPES_H__ */+++/* END */
+ include/freetype/ftwinfnt.h view
@@ -0,0 +1,274 @@+/***************************************************************************/+/* */+/* ftwinfnt.h */+/* */+/* FreeType API for accessing Windows fnt-specific data. */+/* */+/* Copyright 2003, 2004, 2008 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 __FTWINFNT_H__+#define __FTWINFNT_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+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* winfnt_fonts */+ /* */+ /* <Title> */+ /* Window FNT Files */+ /* */+ /* <Abstract> */+ /* Windows FNT specific API. */+ /* */+ /* <Description> */+ /* This section contains the declaration of Windows FNT specific */+ /* functions. */+ /* */+ /*************************************************************************/+++ /*************************************************************************+ *+ * @enum:+ * FT_WinFNT_ID_XXX+ *+ * @description:+ * A list of valid values for the `charset' byte in+ * @FT_WinFNT_HeaderRec. Exact mapping tables for the various cpXXXX+ * encodings (except for cp1361) can be found at ftp://ftp.unicode.org+ * in the MAPPINGS/VENDORS/MICSFT/WINDOWS subdirectory. cp1361 is+ * roughly a superset of MAPPINGS/OBSOLETE/EASTASIA/KSC/JOHAB.TXT.+ *+ * @values:+ * FT_WinFNT_ID_DEFAULT ::+ * This is used for font enumeration and font creation as a+ * `don't care' value. Valid font files don't contain this value.+ * When querying for information about the character set of the font+ * that is currently selected into a specified device context, this+ * return value (of the related Windows API) simply denotes failure.+ *+ * FT_WinFNT_ID_SYMBOL ::+ * There is no known mapping table available.+ *+ * FT_WinFNT_ID_MAC ::+ * Mac Roman encoding.+ *+ * FT_WinFNT_ID_OEM ::+ * From Michael Pöttgen <michael@poettgen.de>:+ *+ * The `Windows Font Mapping' article says that FT_WinFNT_ID_OEM+ * is used for the charset of vector fonts, like `modern.fon',+ * `roman.fon', and `script.fon' on Windows.+ *+ * The `CreateFont' documentation says: The FT_WinFNT_ID_OEM value+ * specifies a character set that is operating-system dependent.+ *+ * The `IFIMETRICS' documentation from the `Windows Driver+ * Development Kit' says: This font supports an OEM-specific+ * character set. The OEM character set is system dependent.+ *+ * In general OEM, as opposed to ANSI (i.e., cp1252), denotes the+ * second default codepage that most international versions of+ * Windows have. It is one of the OEM codepages from+ *+ * http://www.microsoft.com/globaldev/reference/cphome.mspx,+ *+ * and is used for the `DOS boxes', to support legacy applications.+ * A German Windows version for example usually uses ANSI codepage+ * 1252 and OEM codepage 850.+ *+ * FT_WinFNT_ID_CP874 ::+ * A superset of Thai TIS 620 and ISO 8859-11.+ *+ * FT_WinFNT_ID_CP932 ::+ * A superset of Japanese Shift-JIS (with minor deviations).+ *+ * FT_WinFNT_ID_CP936 ::+ * A superset of simplified Chinese GB 2312-1980 (with different+ * ordering and minor deviations).+ *+ * FT_WinFNT_ID_CP949 ::+ * A superset of Korean Hangul KS~C 5601-1987 (with different+ * ordering and minor deviations).+ *+ * FT_WinFNT_ID_CP950 ::+ * A superset of traditional Chinese Big~5 ETen (with different+ * ordering and minor deviations).+ *+ * FT_WinFNT_ID_CP1250 ::+ * A superset of East European ISO 8859-2 (with slightly different+ * ordering).+ *+ * FT_WinFNT_ID_CP1251 ::+ * A superset of Russian ISO 8859-5 (with different ordering).+ *+ * FT_WinFNT_ID_CP1252 ::+ * ANSI encoding. A superset of ISO 8859-1.+ *+ * FT_WinFNT_ID_CP1253 ::+ * A superset of Greek ISO 8859-7 (with minor modifications).+ *+ * FT_WinFNT_ID_CP1254 ::+ * A superset of Turkish ISO 8859-9.+ *+ * FT_WinFNT_ID_CP1255 ::+ * A superset of Hebrew ISO 8859-8 (with some modifications).+ *+ * FT_WinFNT_ID_CP1256 ::+ * A superset of Arabic ISO 8859-6 (with different ordering).+ *+ * FT_WinFNT_ID_CP1257 ::+ * A superset of Baltic ISO 8859-13 (with some deviations).+ *+ * FT_WinFNT_ID_CP1258 ::+ * For Vietnamese. This encoding doesn't cover all necessary+ * characters.+ *+ * FT_WinFNT_ID_CP1361 ::+ * Korean (Johab).+ */++#define FT_WinFNT_ID_CP1252 0+#define FT_WinFNT_ID_DEFAULT 1+#define FT_WinFNT_ID_SYMBOL 2+#define FT_WinFNT_ID_MAC 77+#define FT_WinFNT_ID_CP932 128+#define FT_WinFNT_ID_CP949 129+#define FT_WinFNT_ID_CP1361 130+#define FT_WinFNT_ID_CP936 134+#define FT_WinFNT_ID_CP950 136+#define FT_WinFNT_ID_CP1253 161+#define FT_WinFNT_ID_CP1254 162+#define FT_WinFNT_ID_CP1258 163+#define FT_WinFNT_ID_CP1255 177+#define FT_WinFNT_ID_CP1256 178+#define FT_WinFNT_ID_CP1257 186+#define FT_WinFNT_ID_CP1251 204+#define FT_WinFNT_ID_CP874 222+#define FT_WinFNT_ID_CP1250 238+#define FT_WinFNT_ID_OEM 255+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_WinFNT_HeaderRec */+ /* */+ /* <Description> */+ /* Windows FNT Header info. */+ /* */+ typedef struct FT_WinFNT_HeaderRec_+ {+ FT_UShort version;+ FT_ULong file_size;+ FT_Byte copyright[60];+ FT_UShort file_type;+ FT_UShort nominal_point_size;+ FT_UShort vertical_resolution;+ FT_UShort horizontal_resolution;+ FT_UShort ascent;+ FT_UShort internal_leading;+ FT_UShort external_leading;+ FT_Byte italic;+ FT_Byte underline;+ FT_Byte strike_out;+ FT_UShort weight;+ FT_Byte charset;+ FT_UShort pixel_width;+ FT_UShort pixel_height;+ FT_Byte pitch_and_family;+ FT_UShort avg_width;+ FT_UShort max_width;+ FT_Byte first_char;+ FT_Byte last_char;+ FT_Byte default_char;+ FT_Byte break_char;+ FT_UShort bytes_per_row;+ FT_ULong device_offset;+ FT_ULong face_name_offset;+ FT_ULong bits_pointer;+ FT_ULong bits_offset;+ FT_Byte reserved;+ FT_ULong flags;+ FT_UShort A_space;+ FT_UShort B_space;+ FT_UShort C_space;+ FT_UShort color_table_offset;+ FT_ULong reserved1[4];++ } FT_WinFNT_HeaderRec;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_WinFNT_Header */+ /* */+ /* <Description> */+ /* A handle to an @FT_WinFNT_HeaderRec structure. */+ /* */+ typedef struct FT_WinFNT_HeaderRec_* FT_WinFNT_Header;+++ /**********************************************************************+ *+ * @function:+ * FT_Get_WinFNT_Header+ *+ * @description:+ * Retrieve a Windows FNT font info header.+ *+ * @input:+ * face :: A handle to the input face.+ *+ * @output:+ * aheader :: The WinFNT header.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * This function only works with Windows FNT faces, returning an error+ * otherwise.+ */+ FT_EXPORT( FT_Error )+ FT_Get_WinFNT_Header( FT_Face face,+ FT_WinFNT_HeaderRec *aheader );+++ /* */++FT_END_HEADER++#endif /* __FTWINFNT_H__ */+++/* END */+++/* Local Variables: */+/* coding: utf-8 */+/* End: */
+ include/freetype/ftxf86.h view
@@ -0,0 +1,83 @@+/***************************************************************************/+/* */+/* ftxf86.h */+/* */+/* Support functions for X11. */+/* */+/* Copyright 2002, 2003, 2004, 2006, 2007 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 __FTXF86_H__+#define __FTXF86_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+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* font_formats */+ /* */+ /* <Title> */+ /* Font Formats */+ /* */+ /* <Abstract> */+ /* Getting the font format. */+ /* */+ /* <Description> */+ /* The single function in this section can be used to get the font */+ /* format. Note that this information is not needed normally; */+ /* however, there are special cases (like in PDF devices) where it is */+ /* important to differentiate, in spite of FreeType's uniform API. */+ /* */+ /* This function is in the X11/xf86 namespace for historical reasons */+ /* and in no way depends on that windowing system. */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Get_X11_Font_Format */+ /* */+ /* <Description> */+ /* Return a string describing the format of a given face, using values */+ /* which can be used as an X11 FONT_PROPERTY. Possible values are */+ /* `TrueType', `Type~1', `BDF', `PCF', `Type~42', `CID~Type~1', `CFF', */+ /* `PFR', and `Windows~FNT'. */+ /* */+ /* <Input> */+ /* face :: */+ /* Input face handle. */+ /* */+ /* <Return> */+ /* Font format string. NULL in case of error. */+ /* */+ FT_EXPORT( const char* )+ FT_Get_X11_Font_Format( FT_Face face );++ /* */++FT_END_HEADER++#endif /* __FTXF86_H__ */
+ include/freetype/internal/autohint.h view
@@ -0,0 +1,231 @@+/***************************************************************************/+/* */+/* autohint.h */+/* */+/* High-level `autohint' module-specific interface (specification). */+/* */+/* Copyright 1996-2001, 2002, 2007 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++ /*************************************************************************/+ /* */+ /* The auto-hinter is used to load and automatically hint glyphs if a */+ /* format-specific hinter isn't available. */+ /* */+ /*************************************************************************/+++#ifndef __AUTOHINT_H__+#define __AUTOHINT_H__+++ /*************************************************************************/+ /* */+ /* A small technical note regarding automatic hinting in order to */+ /* clarify this module interface. */+ /* */+ /* An automatic hinter might compute two kinds of data for a given face: */+ /* */+ /* - global hints: Usually some metrics that describe global properties */+ /* of the face. It is computed by scanning more or less */+ /* aggressively the glyphs in the face, and thus can be */+ /* very slow to compute (even if the size of global */+ /* hints is really small). */+ /* */+ /* - glyph hints: These describe some important features of the glyph */+ /* outline, as well as how to align them. They are */+ /* generally much faster to compute than global hints. */+ /* */+ /* The current FreeType auto-hinter does a pretty good job while */+ /* performing fast computations for both global and glyph hints. */+ /* However, we might be interested in introducing more complex and */+ /* powerful algorithms in the future, like the one described in the John */+ /* D. Hobby paper, which unfortunately requires a lot more horsepower. */+ /* */+ /* Because a sufficiently sophisticated font management system would */+ /* typically implement an LRU cache of opened face objects to reduce */+ /* memory usage, it is a good idea to be able to avoid recomputing */+ /* global hints every time the same face is re-opened. */+ /* */+ /* We thus provide the ability to cache global hints outside of the face */+ /* object, in order to speed up font re-opening time. Of course, this */+ /* feature is purely optional, so most client programs won't even notice */+ /* it. */+ /* */+ /* I initially thought that it would be a good idea to cache the glyph */+ /* hints too. However, my general idea now is that if you really need */+ /* to cache these too, you are simply in need of a new font format, */+ /* where all this information could be stored within the font file and */+ /* decoded on the fly. */+ /* */+ /*************************************************************************/+++#include <ft2build.h>+#include FT_FREETYPE_H+++FT_BEGIN_HEADER+++ typedef struct FT_AutoHinterRec_ *FT_AutoHinter;+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* FT_AutoHinter_GlobalGetFunc */+ /* */+ /* <Description> */+ /* Retrieves the global hints computed for a given face object the */+ /* resulting data is dissociated from the face and will survive a */+ /* call to FT_Done_Face(). It must be discarded through the API */+ /* FT_AutoHinter_GlobalDoneFunc(). */+ /* */+ /* <Input> */+ /* hinter :: A handle to the source auto-hinter. */+ /* */+ /* face :: A handle to the source face object. */+ /* */+ /* <Output> */+ /* global_hints :: A typeless pointer to the global hints. */+ /* */+ /* global_len :: The size in bytes of the global hints. */+ /* */+ typedef void+ (*FT_AutoHinter_GlobalGetFunc)( FT_AutoHinter hinter,+ FT_Face face,+ void** global_hints,+ long* global_len );+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* FT_AutoHinter_GlobalDoneFunc */+ /* */+ /* <Description> */+ /* Discards the global hints retrieved through */+ /* FT_AutoHinter_GlobalGetFunc(). This is the only way these hints */+ /* are freed from memory. */+ /* */+ /* <Input> */+ /* hinter :: A handle to the auto-hinter module. */+ /* */+ /* global :: A pointer to retrieved global hints to discard. */+ /* */+ typedef void+ (*FT_AutoHinter_GlobalDoneFunc)( FT_AutoHinter hinter,+ void* global );+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* FT_AutoHinter_GlobalResetFunc */+ /* */+ /* <Description> */+ /* This function is used to recompute the global metrics in a given */+ /* font. This is useful when global font data changes (e.g. Multiple */+ /* Masters fonts where blend coordinates change). */+ /* */+ /* <Input> */+ /* hinter :: A handle to the source auto-hinter. */+ /* */+ /* face :: A handle to the face. */+ /* */+ typedef void+ (*FT_AutoHinter_GlobalResetFunc)( FT_AutoHinter hinter,+ FT_Face face );+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* FT_AutoHinter_GlyphLoadFunc */+ /* */+ /* <Description> */+ /* This function is used to load, scale, and automatically hint a */+ /* glyph from a given face. */+ /* */+ /* <Input> */+ /* face :: A handle to the face. */+ /* */+ /* glyph_index :: The glyph index. */+ /* */+ /* load_flags :: The load flags. */+ /* */+ /* <Note> */+ /* This function is capable of loading composite glyphs by hinting */+ /* each sub-glyph independently (which improves quality). */+ /* */+ /* It will call the font driver with FT_Load_Glyph(), with */+ /* FT_LOAD_NO_SCALE set. */+ /* */+ typedef FT_Error+ (*FT_AutoHinter_GlyphLoadFunc)( FT_AutoHinter hinter,+ FT_GlyphSlot slot,+ FT_Size size,+ FT_UInt glyph_index,+ FT_Int32 load_flags );+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_AutoHinter_ServiceRec */+ /* */+ /* <Description> */+ /* The auto-hinter module's interface. */+ /* */+ typedef struct FT_AutoHinter_ServiceRec_+ {+ FT_AutoHinter_GlobalResetFunc reset_face;+ FT_AutoHinter_GlobalGetFunc get_global_hints;+ FT_AutoHinter_GlobalDoneFunc done_global_hints;+ FT_AutoHinter_GlyphLoadFunc load_glyph;++ } FT_AutoHinter_ServiceRec, *FT_AutoHinter_Service;++#ifndef FT_CONFIG_OPTION_PIC++#define FT_DEFINE_AUTOHINTER_SERVICE(class_, reset_face_, get_global_hints_, \+ done_global_hints_, load_glyph_) \+ FT_CALLBACK_TABLE_DEF \+ const FT_AutoHinter_ServiceRec class_ = \+ { \+ reset_face_, get_global_hints_, done_global_hints_, load_glyph_ \+ };++#else /* FT_CONFIG_OPTION_PIC */ ++#define FT_DEFINE_AUTOHINTER_SERVICE(class_, reset_face_, get_global_hints_, \+ done_global_hints_, load_glyph_) \+ void \+ FT_Init_Class_##class_( FT_Library library, \+ FT_AutoHinter_ServiceRec* clazz) \+ { \+ FT_UNUSED(library); \+ clazz->reset_face = reset_face_; \+ clazz->get_global_hints = get_global_hints_; \+ clazz->done_global_hints = done_global_hints_; \+ clazz->load_glyph = load_glyph_; \+ } ++#endif /* FT_CONFIG_OPTION_PIC */ ++FT_END_HEADER++#endif /* __AUTOHINT_H__ */+++/* END */
+ include/freetype/internal/ftcalc.h view
@@ -0,0 +1,179 @@+/***************************************************************************/+/* */+/* ftcalc.h */+/* */+/* Arithmetic computations (specification). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009 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 __FTCALC_H__+#define __FTCALC_H__+++#include <ft2build.h>+#include FT_FREETYPE_H+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_FixedSqrt */+ /* */+ /* <Description> */+ /* Computes the square root of a 16.16 fixed point value. */+ /* */+ /* <Input> */+ /* x :: The value to compute the root for. */+ /* */+ /* <Return> */+ /* The result of `sqrt(x)'. */+ /* */+ /* <Note> */+ /* This function is not very fast. */+ /* */+ FT_BASE( FT_Int32 )+ FT_SqrtFixed( FT_Int32 x );+++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Sqrt32 */+ /* */+ /* <Description> */+ /* Computes the square root of an Int32 integer (which will be */+ /* handled as an unsigned long value). */+ /* */+ /* <Input> */+ /* x :: The value to compute the root for. */+ /* */+ /* <Return> */+ /* The result of `sqrt(x)'. */+ /* */+ FT_EXPORT( FT_Int32 )+ FT_Sqrt32( FT_Int32 x );++#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */+++ /*************************************************************************/+ /* */+ /* FT_MulDiv() and FT_MulFix() are declared in freetype.h. */+ /* */+ /*************************************************************************/+++#ifdef TT_USE_BYTECODE_INTERPRETER++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_MulDiv_No_Round */+ /* */+ /* <Description> */+ /* A very simple function used to perform the computation `(a*b)/c' */+ /* (without rounding) with maximal accuracy (it uses a 64-bit */+ /* intermediate integer whenever necessary). */+ /* */+ /* This function isn't necessarily as fast as some processor specific */+ /* operations, but is at least completely portable. */+ /* */+ /* <Input> */+ /* a :: The first multiplier. */+ /* b :: The second multiplier. */+ /* c :: The divisor. */+ /* */+ /* <Return> */+ /* The result of `(a*b)/c'. This function never traps when trying to */+ /* divide by zero; it simply returns `MaxInt' or `MinInt' depending */+ /* on the signs of `a' and `b'. */+ /* */+ FT_BASE( FT_Long )+ FT_MulDiv_No_Round( FT_Long a,+ FT_Long b,+ FT_Long c );++#endif /* TT_USE_BYTECODE_INTERPRETER */+++ /*+ * A variant of FT_Matrix_Multiply which scales its result afterwards.+ * The idea is that both `a' and `b' are scaled by factors of 10 so that+ * the values are as precise as possible to get a correct result during+ * the 64bit multiplication. Let `sa' and `sb' be the scaling factors of+ * `a' and `b', respectively, then the scaling factor of the result is+ * `sa*sb'.+ */+ FT_BASE( void )+ FT_Matrix_Multiply_Scaled( const FT_Matrix* a,+ FT_Matrix *b,+ FT_Long scaling );+++ /*+ * A variant of FT_Vector_Transform. See comments for+ * FT_Matrix_Multiply_Scaled.+ */++ FT_BASE( void )+ FT_Vector_Transform_Scaled( FT_Vector* vector,+ const FT_Matrix* matrix,+ FT_Long scaling );+++ /*+ * 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+ * left, -1 to the right, and 0 for undecidable cases.+ */+ FT_BASE( FT_Int )+ ft_corner_orientation( FT_Pos in_x,+ FT_Pos in_y,+ FT_Pos out_x,+ FT_Pos out_y );++ /*+ * Return TRUE if a corner is flat or nearly flat. This is equivalent to+ * saying that the angle difference between the `in' and `out' vectors is+ * very small.+ */+ FT_BASE( FT_Int )+ ft_corner_is_flat( FT_Pos in_x,+ FT_Pos in_y,+ FT_Pos out_x,+ FT_Pos out_y );+++#define INT_TO_F26DOT6( x ) ( (FT_Long)(x) << 6 )+#define INT_TO_F2DOT14( x ) ( (FT_Long)(x) << 14 )+#define INT_TO_FIXED( x ) ( (FT_Long)(x) << 16 )+#define F2DOT14_TO_FIXED( x ) ( (FT_Long)(x) << 2 )+#define FLOAT_TO_FIXED( x ) ( (FT_Long)( x * 65536.0 ) )+#define FIXED_TO_INT( x ) ( FT_RoundFix( x ) >> 16 )++#define ROUND_F26DOT6( x ) ( x >= 0 ? ( ( (x) + 32 ) & -64 ) \+ : ( -( ( 32 - (x) ) & -64 ) ) )+++FT_END_HEADER++#endif /* __FTCALC_H__ */+++/* END */
+ include/freetype/internal/ftdebug.h view
@@ -0,0 +1,250 @@+/***************************************************************************/+/* */+/* ftdebug.h */+/* */+/* Debugging and logging component (specification). */+/* */+/* Copyright 1996-2001, 2002, 2004, 2006, 2007, 2008, 2009 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. */+/* */+/* */+/* IMPORTANT: A description of FreeType's debugging support can be */+/* found in `docs/DEBUG.TXT'. Read it if you need to use or */+/* understand this code. */+/* */+/***************************************************************************/+++#ifndef __FTDEBUG_H__+#define __FTDEBUG_H__+++#include <ft2build.h>+#include FT_CONFIG_CONFIG_H+#include FT_FREETYPE_H+++FT_BEGIN_HEADER+++ /* force the definition of FT_DEBUG_LEVEL_ERROR if FT_DEBUG_LEVEL_TRACE */+ /* is already defined; this simplifies the following #ifdefs */+ /* */+#ifdef FT_DEBUG_LEVEL_TRACE+#undef FT_DEBUG_LEVEL_ERROR+#define FT_DEBUG_LEVEL_ERROR+#endif+++ /*************************************************************************/+ /* */+ /* Define the trace enums as well as the trace levels array when they */+ /* are needed. */+ /* */+ /*************************************************************************/++#ifdef FT_DEBUG_LEVEL_TRACE++#define FT_TRACE_DEF( x ) trace_ ## x ,++ /* defining the enumeration */+ typedef enum FT_Trace_+ {+#include FT_INTERNAL_TRACE_H+ trace_count++ } FT_Trace;+++ /* defining the array of trace levels, provided by `src/base/ftdebug.c' */+ extern int ft_trace_levels[trace_count];++#undef FT_TRACE_DEF++#endif /* FT_DEBUG_LEVEL_TRACE */+++ /*************************************************************************/+ /* */+ /* Define the FT_TRACE macro */+ /* */+ /* IMPORTANT! */+ /* */+ /* Each component must define the macro FT_COMPONENT to a valid FT_Trace */+ /* value before using any TRACE macro. */+ /* */+ /*************************************************************************/++#ifdef FT_DEBUG_LEVEL_TRACE++#define FT_TRACE( level, varformat ) \+ do \+ { \+ if ( ft_trace_levels[FT_COMPONENT] >= level ) \+ FT_Message varformat; \+ } while ( 0 )++#else /* !FT_DEBUG_LEVEL_TRACE */++#define FT_TRACE( level, varformat ) do { } while ( 0 ) /* nothing */++#endif /* !FT_DEBUG_LEVEL_TRACE */+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Trace_Get_Count */+ /* */+ /* <Description> */+ /* Return the number of available trace components. */+ /* */+ /* <Return> */+ /* The number of trace components. 0 if FreeType 2 is not built with */+ /* FT_DEBUG_LEVEL_TRACE definition. */+ /* */+ /* <Note> */+ /* This function may be useful if you want to access elements of */+ /* the internal `ft_trace_levels' array by an index. */+ /* */+ FT_BASE( FT_Int )+ FT_Trace_Get_Count( void );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Trace_Get_Name */+ /* */+ /* <Description> */+ /* Return the name of a trace component. */+ /* */+ /* <Input> */+ /* The index of the trace component. */+ /* */+ /* <Return> */+ /* The name of the trace component. This is a statically allocated */+ /* C string, so do not free it after use. NULL if FreeType 2 is not */+ /* built with FT_DEBUG_LEVEL_TRACE definition. */+ /* */+ /* <Note> */+ /* Use @FT_Trace_Get_Count to get the number of available trace */+ /* components. */+ /* */+ /* This function may be useful if you want to control FreeType 2's */+ /* debug level in your application. */+ /* */+ FT_BASE( const char * )+ FT_Trace_Get_Name( FT_Int idx );+++ /*************************************************************************/+ /* */+ /* You need two opening and closing parentheses! */+ /* */+ /* Example: FT_TRACE0(( "Value is %i", foo )) */+ /* */+ /* Output of the FT_TRACEX macros is sent to stderr. */+ /* */+ /*************************************************************************/++#define FT_TRACE0( varformat ) FT_TRACE( 0, varformat )+#define FT_TRACE1( varformat ) FT_TRACE( 1, varformat )+#define FT_TRACE2( varformat ) FT_TRACE( 2, varformat )+#define FT_TRACE3( varformat ) FT_TRACE( 3, varformat )+#define FT_TRACE4( varformat ) FT_TRACE( 4, varformat )+#define FT_TRACE5( varformat ) FT_TRACE( 5, varformat )+#define FT_TRACE6( varformat ) FT_TRACE( 6, varformat )+#define FT_TRACE7( varformat ) FT_TRACE( 7, varformat )+++ /*************************************************************************/+ /* */+ /* Define the FT_ERROR macro. */+ /* */+ /* Output of this macro is sent to stderr. */+ /* */+ /*************************************************************************/++#ifdef FT_DEBUG_LEVEL_ERROR++#define FT_ERROR( varformat ) FT_Message varformat++#else /* !FT_DEBUG_LEVEL_ERROR */++#define FT_ERROR( varformat ) do { } while ( 0 ) /* nothing */++#endif /* !FT_DEBUG_LEVEL_ERROR */+++ /*************************************************************************/+ /* */+ /* Define the FT_ASSERT macro. */+ /* */+ /*************************************************************************/++#ifdef FT_DEBUG_LEVEL_ERROR++#define FT_ASSERT( condition ) \+ do \+ { \+ if ( !( condition ) ) \+ FT_Panic( "assertion failed on line %d of file %s\n", \+ __LINE__, __FILE__ ); \+ } while ( 0 )++#else /* !FT_DEBUG_LEVEL_ERROR */++#define FT_ASSERT( condition ) do { } while ( 0 )++#endif /* !FT_DEBUG_LEVEL_ERROR */+++ /*************************************************************************/+ /* */+ /* Define `FT_Message' and `FT_Panic' when needed. */+ /* */+ /*************************************************************************/++#ifdef FT_DEBUG_LEVEL_ERROR++#include "stdio.h" /* for vfprintf() */++ /* print a message */+ FT_BASE( void )+ FT_Message( const char* fmt,+ ... );++ /* print a message and exit */+ FT_BASE( void )+ FT_Panic( const char* fmt,+ ... );++#endif /* FT_DEBUG_LEVEL_ERROR */+++ FT_BASE( void )+ ft_debug_init( void );+++#if defined( _MSC_VER ) /* Visual C++ (and Intel C++) */++ /* We disable the warning `conditional expression is constant' here */+ /* in order to compile cleanly with the maximum level of warnings. */+#pragma warning( disable : 4127 )++#endif /* _MSC_VER */+++FT_END_HEADER++#endif /* __FTDEBUG_H__ */+++/* END */
+ include/freetype/internal/ftdriver.h view
@@ -0,0 +1,422 @@+/***************************************************************************/+/* */+/* ftdriver.h */+/* */+/* FreeType font driver interface (specification). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2006, 2008 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 __FTDRIVER_H__+#define __FTDRIVER_H__+++#include <ft2build.h>+#include FT_MODULE_H+++FT_BEGIN_HEADER+++ typedef FT_Error+ (*FT_Face_InitFunc)( FT_Stream stream,+ FT_Face face,+ FT_Int typeface_index,+ FT_Int num_params,+ FT_Parameter* parameters );++ typedef void+ (*FT_Face_DoneFunc)( FT_Face face );+++ typedef FT_Error+ (*FT_Size_InitFunc)( FT_Size size );++ typedef void+ (*FT_Size_DoneFunc)( FT_Size size );+++ typedef FT_Error+ (*FT_Slot_InitFunc)( FT_GlyphSlot slot );++ typedef void+ (*FT_Slot_DoneFunc)( FT_GlyphSlot slot );+++ typedef FT_Error+ (*FT_Size_RequestFunc)( FT_Size size,+ FT_Size_Request req );++ typedef FT_Error+ (*FT_Size_SelectFunc)( FT_Size size,+ FT_ULong size_index );++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS++ typedef FT_Error+ (*FT_Size_ResetPointsFunc)( FT_Size size,+ FT_F26Dot6 char_width,+ FT_F26Dot6 char_height,+ FT_UInt horz_resolution,+ FT_UInt vert_resolution );++ typedef FT_Error+ (*FT_Size_ResetPixelsFunc)( FT_Size size,+ FT_UInt pixel_width,+ FT_UInt pixel_height );++#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */++ typedef FT_Error+ (*FT_Slot_LoadFunc)( FT_GlyphSlot slot,+ FT_Size size,+ FT_UInt glyph_index,+ FT_Int32 load_flags );+++ typedef FT_UInt+ (*FT_CharMap_CharIndexFunc)( FT_CharMap charmap,+ FT_Long charcode );++ typedef FT_Long+ (*FT_CharMap_CharNextFunc)( FT_CharMap charmap,+ FT_Long charcode );+++ typedef FT_Error+ (*FT_Face_GetKerningFunc)( FT_Face face,+ FT_UInt left_glyph,+ FT_UInt right_glyph,+ FT_Vector* kerning );+++ typedef FT_Error+ (*FT_Face_AttachFunc)( FT_Face face,+ FT_Stream stream );+++ typedef FT_Error+ (*FT_Face_GetAdvancesFunc)( FT_Face face,+ FT_UInt first,+ FT_UInt count,+ FT_Int32 flags,+ FT_Fixed* advances );+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_Driver_ClassRec */+ /* */+ /* <Description> */+ /* The font driver class. This structure mostly contains pointers to */+ /* driver methods. */+ /* */+ /* <Fields> */+ /* root :: The parent module. */+ /* */+ /* face_object_size :: The size of a face object in bytes. */+ /* */+ /* size_object_size :: The size of a size object in bytes. */+ /* */+ /* slot_object_size :: The size of a glyph object in bytes. */+ /* */+ /* init_face :: The format-specific face constructor. */+ /* */+ /* done_face :: The format-specific face destructor. */+ /* */+ /* init_size :: The format-specific size constructor. */+ /* */+ /* done_size :: The format-specific size destructor. */+ /* */+ /* init_slot :: The format-specific slot constructor. */+ /* */+ /* done_slot :: The format-specific slot destructor. */+ /* */+ /* */+ /* load_glyph :: A function handle to load a glyph to a slot. */+ /* This field is mandatory! */+ /* */+ /* get_kerning :: A function handle to return the unscaled */+ /* kerning for a given pair of glyphs. Can be */+ /* set to 0 if the format doesn't support */+ /* kerning. */+ /* */+ /* attach_file :: This function handle is used to read */+ /* additional data for a face from another */+ /* file/stream. For example, this can be used to */+ /* add data from AFM or PFM files on a Type 1 */+ /* face, or a CIDMap on a CID-keyed face. */+ /* */+ /* get_advances :: A function handle used to return advance */+ /* widths of `count' glyphs (in font units), */+ /* starting at `first'. The `vertical' flag must */+ /* be set to get vertical advance heights. The */+ /* `advances' buffer is caller-allocated. */+ /* Currently not implemented. The idea of this */+ /* function is to be able to perform */+ /* device-independent text layout without loading */+ /* a single glyph image. */+ /* */+ /* request_size :: A handle to a function used to request the new */+ /* character size. Can be set to 0 if the */+ /* scaling done in the base layer suffices. */+ /* */+ /* select_size :: A handle to a function used to select a new */+ /* fixed size. It is used only if */+ /* @FT_FACE_FLAG_FIXED_SIZES is set. Can be set */+ /* to 0 if the scaling done in the base layer */+ /* suffices. */+ /* <Note> */+ /* Most function pointers, with the exception of `load_glyph', can be */+ /* set to 0 to indicate a default behaviour. */+ /* */+ typedef struct FT_Driver_ClassRec_+ {+ FT_Module_Class root;++ FT_Long face_object_size;+ FT_Long size_object_size;+ FT_Long slot_object_size;++ FT_Face_InitFunc init_face;+ FT_Face_DoneFunc done_face;++ FT_Size_InitFunc init_size;+ FT_Size_DoneFunc done_size;++ FT_Slot_InitFunc init_slot;+ FT_Slot_DoneFunc done_slot;++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS++ FT_Size_ResetPointsFunc set_char_sizes;+ FT_Size_ResetPixelsFunc set_pixel_sizes;++#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */++ FT_Slot_LoadFunc load_glyph;++ FT_Face_GetKerningFunc get_kerning;+ FT_Face_AttachFunc attach_file;+ FT_Face_GetAdvancesFunc get_advances;++ /* since version 2.2 */+ FT_Size_RequestFunc request_size;+ FT_Size_SelectFunc select_size;++ } FT_Driver_ClassRec, *FT_Driver_Class;+++ /*+ * The following functions are used as stubs for `set_char_sizes' and+ * `set_pixel_sizes'; the code uses `request_size' and `select_size'+ * functions instead.+ *+ * Implementation is in `src/base/ftobjs.c'.+ */+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS++ FT_BASE( FT_Error )+ ft_stub_set_char_sizes( FT_Size size,+ FT_F26Dot6 width,+ FT_F26Dot6 height,+ FT_UInt horz_res,+ FT_UInt vert_res );++ FT_BASE( FT_Error )+ ft_stub_set_pixel_sizes( FT_Size size,+ FT_UInt width,+ FT_UInt height );++#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */++ /*************************************************************************/+ /* */+ /* <Macro> */+ /* FT_DECLARE_DRIVER */+ /* */+ /* <Description> */+ /* Used to create a forward declaration of a */+ /* FT_Driver_ClassRec stract instance. */+ /* */+ /* <Macro> */+ /* FT_DEFINE_DRIVER */+ /* */+ /* <Description> */+ /* Used to initialize an instance of FT_Driver_ClassRec struct. */+ /* */+ /* When FT_CONFIG_OPTION_PIC is defined a Create funtion will need */+ /* to called with a pointer where the allocated stracture is returned.*/+ /* And when it is no longer needed a Destroy function needs */+ /* to be called to release that allocation. */+ /* fcinit.c (ft_create_default_module_classes) already contains */+ /* a mechanism to call these functions for the default modules */+ /* described in ftmodule.h */+ /* */+ /* Notice that the created Create and Destroy functions call */+ /* pic_init and pic_free function to allow you to manually allocate */+ /* and initialize any additional global data, like module specific */+ /* interface, and put them in the global pic container defined in */+ /* ftpic.h. if you don't need them just implement the functions as */+ /* empty to resolve the link error. */+ /* */+ /* When FT_CONFIG_OPTION_PIC is not defined the struct will be */+ /* allocated in the global scope (or the scope where the macro */+ /* is used). */+ /* */+#ifndef FT_CONFIG_OPTION_PIC++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS+#define FT_DEFINE_DRIVERS_OLD_INTERNALS(a_,b_) \+ a_, b_,+#else+ #define FT_DEFINE_DRIVERS_OLD_INTERNALS(a_,b_)+#endif++#define FT_DECLARE_DRIVER(class_) \+ FT_CALLBACK_TABLE \+ const FT_Driver_ClassRec class_; ++#define FT_DEFINE_DRIVER(class_, \+ flags_, size_, name_, version_, requires_, \+ interface_, init_, done_, get_interface_, \+ face_object_size_, size_object_size_, \+ slot_object_size_, init_face_, done_face_, \+ init_size_, done_size_, init_slot_, done_slot_, \+ old_set_char_sizes_, old_set_pixel_sizes_, \+ load_glyph_, get_kerning_, attach_file_, \+ get_advances_, request_size_, select_size_ ) \+ FT_CALLBACK_TABLE_DEF \+ const FT_Driver_ClassRec class_ = \+ { \+ FT_DEFINE_ROOT_MODULE(flags_,size_,name_,version_,requires_,interface_, \+ init_,done_,get_interface_) \+ \+ face_object_size_, \+ size_object_size_, \+ slot_object_size_, \+ \+ init_face_, \+ done_face_, \+ \+ init_size_, \+ done_size_, \+ \+ init_slot_, \+ done_slot_, \+ \+ FT_DEFINE_DRIVERS_OLD_INTERNALS(old_set_char_sizes_, old_set_pixel_sizes_) \+ \+ load_glyph_, \+ \+ get_kerning_, \+ attach_file_, \+ get_advances_, \+ \+ request_size_, \+ select_size_ \+ };++#else /* FT_CONFIG_OPTION_PIC */ ++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS+#define FT_DEFINE_DRIVERS_OLD_INTERNALS(a_,b_) \+ clazz->set_char_sizes = a_; \+ clazz->set_pixel_sizes = b_;+#else+ #define FT_DEFINE_DRIVERS_OLD_INTERNALS(a_,b_)+#endif++#define FT_DECLARE_DRIVER(class_) FT_DECLARE_MODULE(class_)++#define FT_DEFINE_DRIVER(class_, \+ flags_, size_, name_, version_, requires_, \+ interface_, init_, done_, get_interface_, \+ face_object_size_, size_object_size_, \+ slot_object_size_, init_face_, done_face_, \+ init_size_, done_size_, init_slot_, done_slot_, \+ old_set_char_sizes_, old_set_pixel_sizes_, \+ load_glyph_, get_kerning_, attach_file_, \+ get_advances_, request_size_, select_size_ ) \+ void class_##_pic_free( FT_Library library ); \+ FT_Error class_##_pic_init( FT_Library library ); \+ \+ void \+ FT_Destroy_Class_##class_( FT_Library library, \+ FT_Module_Class* clazz ) \+ { \+ FT_Memory memory = library->memory; \+ FT_Driver_Class dclazz = (FT_Driver_Class)clazz; \+ class_##_pic_free( library ); \+ if ( dclazz ) \+ FT_FREE( dclazz ); \+ } \+ \+ FT_Error \+ FT_Create_Class_##class_( FT_Library library, \+ FT_Module_Class** output_class ) \+ { \+ FT_Driver_Class clazz; \+ FT_Error error; \+ FT_Memory memory = library->memory; \+ \+ if ( FT_ALLOC( clazz, sizeof(*clazz) ) ) \+ return error; \+ \+ error = class_##_pic_init( library ); \+ if(error) \+ { \+ FT_FREE( clazz ); \+ return error; \+ } \+ \+ FT_DEFINE_ROOT_MODULE(flags_,size_,name_,version_,requires_,interface_, \+ init_,done_,get_interface_) \+ \+ clazz->face_object_size = face_object_size_; \+ clazz->size_object_size = size_object_size_; \+ clazz->slot_object_size = slot_object_size_; \+ \+ clazz->init_face = init_face_; \+ clazz->done_face = done_face_; \+ \+ clazz->init_size = init_size_; \+ clazz->done_size = done_size_; \+ \+ clazz->init_slot = init_slot_; \+ clazz->done_slot = done_slot_; \+ \+ FT_DEFINE_DRIVERS_OLD_INTERNALS(old_set_char_sizes_, old_set_pixel_sizes_) \+ \+ clazz->load_glyph = load_glyph_; \+ \+ clazz->get_kerning = get_kerning_; \+ clazz->attach_file = attach_file_; \+ clazz->get_advances = get_advances_; \+ \+ clazz->request_size = request_size_; \+ clazz->select_size = select_size_; \+ \+ *output_class = (FT_Module_Class*)clazz; \+ return FT_Err_Ok; \+ } +++#endif /* FT_CONFIG_OPTION_PIC */++FT_END_HEADER++#endif /* __FTDRIVER_H__ */+++/* END */
+ include/freetype/internal/ftgloadr.h view
@@ -0,0 +1,168 @@+/***************************************************************************/+/* */+/* ftgloadr.h */+/* */+/* The FreeType glyph loader (specification). */+/* */+/* Copyright 2002, 2003, 2005, 2006 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 __FTGLOADR_H__+#define __FTGLOADR_H__+++#include <ft2build.h>+#include FT_FREETYPE_H+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_GlyphLoader */+ /* */+ /* <Description> */+ /* The glyph loader is an internal object used to load several glyphs */+ /* together (for example, in the case of composites). */+ /* */+ /* <Note> */+ /* The glyph loader implementation is not part of the high-level API, */+ /* hence the forward structure declaration. */+ /* */+ typedef struct FT_GlyphLoaderRec_* FT_GlyphLoader ;+++#if 0 /* moved to freetype.h in version 2.2 */+#define FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS 1+#define FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES 2+#define FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID 4+#define FT_SUBGLYPH_FLAG_SCALE 8+#define FT_SUBGLYPH_FLAG_XY_SCALE 0x40+#define FT_SUBGLYPH_FLAG_2X2 0x80+#define FT_SUBGLYPH_FLAG_USE_MY_METRICS 0x200+#endif+++ typedef struct FT_SubGlyphRec_+ {+ FT_Int index;+ FT_UShort flags;+ FT_Int arg1;+ FT_Int arg2;+ FT_Matrix transform;++ } FT_SubGlyphRec;+++ typedef struct FT_GlyphLoadRec_+ {+ FT_Outline outline; /* outline */+ FT_Vector* extra_points; /* extra points table */+ FT_Vector* extra_points2; /* second extra points table */+ FT_UInt num_subglyphs; /* number of subglyphs */+ FT_SubGlyph subglyphs; /* subglyphs */++ } FT_GlyphLoadRec, *FT_GlyphLoad;+++ typedef struct FT_GlyphLoaderRec_+ {+ FT_Memory memory;+ FT_UInt max_points;+ FT_UInt max_contours;+ FT_UInt max_subglyphs;+ FT_Bool use_extra;++ FT_GlyphLoadRec base;+ FT_GlyphLoadRec current;++ void* other; /* for possible future extension? */++ } FT_GlyphLoaderRec;+++ /* create new empty glyph loader */+ FT_BASE( FT_Error )+ FT_GlyphLoader_New( FT_Memory memory,+ FT_GlyphLoader *aloader );++ /* add an extra points table to a glyph loader */+ FT_BASE( FT_Error )+ FT_GlyphLoader_CreateExtra( FT_GlyphLoader loader );++ /* destroy a glyph loader */+ FT_BASE( void )+ FT_GlyphLoader_Done( FT_GlyphLoader loader );++ /* reset a glyph loader (frees everything int it) */+ FT_BASE( void )+ FT_GlyphLoader_Reset( FT_GlyphLoader loader );++ /* rewind a glyph loader */+ FT_BASE( void )+ FT_GlyphLoader_Rewind( FT_GlyphLoader loader );++ /* check that there is enough space to add `n_points' and `n_contours' */+ /* to the glyph loader */+ FT_BASE( FT_Error )+ FT_GlyphLoader_CheckPoints( FT_GlyphLoader loader,+ FT_UInt n_points,+ FT_UInt n_contours );+++#define FT_GLYPHLOADER_CHECK_P( _loader, _count ) \+ ( (_count) == 0 || ((_loader)->base.outline.n_points + \+ (_loader)->current.outline.n_points + \+ (unsigned long)(_count)) <= (_loader)->max_points )++#define FT_GLYPHLOADER_CHECK_C( _loader, _count ) \+ ( (_count) == 0 || ((_loader)->base.outline.n_contours + \+ (_loader)->current.outline.n_contours + \+ (unsigned long)(_count)) <= (_loader)->max_contours )++#define FT_GLYPHLOADER_CHECK_POINTS( _loader, _points,_contours ) \+ ( ( FT_GLYPHLOADER_CHECK_P( _loader, _points ) && \+ FT_GLYPHLOADER_CHECK_C( _loader, _contours ) ) \+ ? 0 \+ : FT_GlyphLoader_CheckPoints( (_loader), (_points), (_contours) ) )+++ /* check that there is enough space to add `n_subs' sub-glyphs to */+ /* a glyph loader */+ FT_BASE( FT_Error )+ FT_GlyphLoader_CheckSubGlyphs( FT_GlyphLoader loader,+ FT_UInt n_subs );++ /* prepare a glyph loader, i.e. empty the current glyph */+ FT_BASE( void )+ FT_GlyphLoader_Prepare( FT_GlyphLoader loader );++ /* add the current glyph to the base glyph */+ FT_BASE( void )+ FT_GlyphLoader_Add( FT_GlyphLoader loader );++ /* copy points from one glyph loader to another */+ FT_BASE( FT_Error )+ FT_GlyphLoader_CopyPoints( FT_GlyphLoader target,+ FT_GlyphLoader source );++ /* */+++FT_END_HEADER++#endif /* __FTGLOADR_H__ */+++/* END */
+ include/freetype/internal/ftmemory.h view
@@ -0,0 +1,380 @@+/***************************************************************************/+/* */+/* ftmemory.h */+/* */+/* The FreeType memory management macros (specification). */+/* */+/* Copyright 1996-2001, 2002, 2004, 2005, 2006, 2007, 2010 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 __FTMEMORY_H__+#define __FTMEMORY_H__+++#include <ft2build.h>+#include FT_CONFIG_CONFIG_H+#include FT_TYPES_H+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Macro> */+ /* FT_SET_ERROR */+ /* */+ /* <Description> */+ /* This macro is used to set an implicit `error' variable to a given */+ /* expression's value (usually a function call), and convert it to a */+ /* boolean which is set whenever the value is != 0. */+ /* */+#undef FT_SET_ERROR+#define FT_SET_ERROR( expression ) \+ ( ( error = (expression) ) != 0 )++++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** ****/+ /**** M E M O R Y ****/+ /**** ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ /*+ * C++ refuses to handle statements like p = (void*)anything, with `p' a+ * typed pointer. Since we don't have a `typeof' operator in standard+ * C++, we have to use a template to emulate it.+ */++#ifdef __cplusplus++ extern "C++"+ template <typename T> inline T*+ cplusplus_typeof( T*,+ void *v )+ {+ return static_cast <T*> ( v );+ }++#define FT_ASSIGNP( p, val ) (p) = cplusplus_typeof( (p), (val) )++#else++#define FT_ASSIGNP( p, val ) (p) = (val)++#endif++++#ifdef FT_DEBUG_MEMORY++ FT_BASE( const char* ) _ft_debug_file;+ FT_BASE( long ) _ft_debug_lineno;++#define FT_DEBUG_INNER( exp ) ( _ft_debug_file = __FILE__, \+ _ft_debug_lineno = __LINE__, \+ (exp) )++#define FT_ASSIGNP_INNER( p, exp ) ( _ft_debug_file = __FILE__, \+ _ft_debug_lineno = __LINE__, \+ FT_ASSIGNP( p, exp ) )++#else /* !FT_DEBUG_MEMORY */++#define FT_DEBUG_INNER( exp ) (exp)+#define FT_ASSIGNP_INNER( p, exp ) FT_ASSIGNP( p, exp )++#endif /* !FT_DEBUG_MEMORY */+++ /*+ * The allocation functions return a pointer, and the error code+ * is written to through the `p_error' parameter. See below for+ * for documentation.+ */++ FT_BASE( FT_Pointer )+ ft_mem_alloc( FT_Memory memory,+ FT_Long size,+ FT_Error *p_error );++ FT_BASE( FT_Pointer )+ ft_mem_qalloc( FT_Memory memory,+ FT_Long size,+ FT_Error *p_error );++ FT_BASE( FT_Pointer )+ ft_mem_realloc( FT_Memory memory,+ FT_Long item_size,+ FT_Long cur_count,+ FT_Long new_count,+ void* block,+ FT_Error *p_error );++ FT_BASE( FT_Pointer )+ ft_mem_qrealloc( FT_Memory memory,+ FT_Long item_size,+ FT_Long cur_count,+ FT_Long new_count,+ void* block,+ FT_Error *p_error );++ FT_BASE( void )+ ft_mem_free( FT_Memory memory,+ const void* P );+++#define FT_MEM_ALLOC( ptr, size ) \+ FT_ASSIGNP_INNER( ptr, ft_mem_alloc( memory, (size), &error ) )++#define FT_MEM_FREE( ptr ) \+ FT_BEGIN_STMNT \+ ft_mem_free( memory, (ptr) ); \+ (ptr) = NULL; \+ FT_END_STMNT++#define FT_MEM_NEW( ptr ) \+ FT_MEM_ALLOC( ptr, sizeof ( *(ptr) ) )++#define FT_MEM_REALLOC( ptr, cursz, newsz ) \+ FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory, 1, \+ (cursz), (newsz), \+ (ptr), &error ) )++#define FT_MEM_QALLOC( ptr, size ) \+ FT_ASSIGNP_INNER( ptr, ft_mem_qalloc( memory, (size), &error ) )++#define FT_MEM_QNEW( ptr ) \+ FT_MEM_QALLOC( ptr, sizeof ( *(ptr) ) )++#define FT_MEM_QREALLOC( ptr, cursz, newsz ) \+ FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory, 1, \+ (cursz), (newsz), \+ (ptr), &error ) )++#define FT_MEM_QRENEW_ARRAY( ptr, cursz, newsz ) \+ FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory, sizeof ( *(ptr) ), \+ (cursz), (newsz), \+ (ptr), &error ) )++#define FT_MEM_ALLOC_MULT( ptr, count, item_size ) \+ FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory, (item_size), \+ 0, (count), \+ NULL, &error ) )++#define FT_MEM_REALLOC_MULT( ptr, oldcnt, newcnt, itmsz ) \+ FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory, (itmsz), \+ (oldcnt), (newcnt), \+ (ptr), &error ) )++#define FT_MEM_QALLOC_MULT( ptr, count, item_size ) \+ FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory, (item_size), \+ 0, (count), \+ NULL, &error ) )++#define FT_MEM_QREALLOC_MULT( ptr, oldcnt, newcnt, itmsz) \+ FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory, (itmsz), \+ (oldcnt), (newcnt), \+ (ptr), &error ) )+++#define FT_MEM_SET_ERROR( cond ) ( (cond), error != 0 )+++#define FT_MEM_SET( dest, byte, count ) ft_memset( dest, byte, count )++#define FT_MEM_COPY( dest, source, count ) ft_memcpy( dest, source, count )++#define FT_MEM_MOVE( dest, source, count ) ft_memmove( dest, source, count )+++#define FT_MEM_ZERO( dest, count ) FT_MEM_SET( dest, 0, count )++#define FT_ZERO( p ) FT_MEM_ZERO( p, sizeof ( *(p) ) )+++#define FT_ARRAY_ZERO( dest, count ) \+ FT_MEM_ZERO( dest, (count) * sizeof ( *(dest) ) )++#define FT_ARRAY_COPY( dest, source, count ) \+ FT_MEM_COPY( dest, source, (count) * sizeof ( *(dest) ) )++#define FT_ARRAY_MOVE( dest, source, count ) \+ FT_MEM_MOVE( dest, source, (count) * sizeof ( *(dest) ) )+++ /*+ * Return the maximum number of addressable elements in an array.+ * We limit ourselves to INT_MAX, rather than UINT_MAX, to avoid+ * any problems.+ */+#define FT_ARRAY_MAX( ptr ) ( FT_INT_MAX / sizeof ( *(ptr) ) )++#define FT_ARRAY_CHECK( ptr, count ) ( (count) <= FT_ARRAY_MAX( ptr ) )+++ /*************************************************************************/+ /* */+ /* The following functions macros expect that their pointer argument is */+ /* _typed_ in order to automatically compute array element sizes. */+ /* */++#define FT_MEM_NEW_ARRAY( ptr, count ) \+ FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory, sizeof ( *(ptr) ), \+ 0, (count), \+ NULL, &error ) )++#define FT_MEM_RENEW_ARRAY( ptr, cursz, newsz ) \+ FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory, sizeof ( *(ptr) ), \+ (cursz), (newsz), \+ (ptr), &error ) )++#define FT_MEM_QNEW_ARRAY( ptr, count ) \+ FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory, sizeof ( *(ptr) ), \+ 0, (count), \+ NULL, &error ) )++#define FT_MEM_QRENEW_ARRAY( ptr, cursz, newsz ) \+ FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory, sizeof ( *(ptr) ), \+ (cursz), (newsz), \+ (ptr), &error ) )+++#define FT_ALLOC( ptr, size ) \+ FT_MEM_SET_ERROR( FT_MEM_ALLOC( ptr, size ) )++#define FT_REALLOC( ptr, cursz, newsz ) \+ FT_MEM_SET_ERROR( FT_MEM_REALLOC( ptr, cursz, newsz ) )++#define FT_ALLOC_MULT( ptr, count, item_size ) \+ FT_MEM_SET_ERROR( FT_MEM_ALLOC_MULT( ptr, count, item_size ) )++#define FT_REALLOC_MULT( ptr, oldcnt, newcnt, itmsz ) \+ FT_MEM_SET_ERROR( FT_MEM_REALLOC_MULT( ptr, oldcnt, \+ newcnt, itmsz ) )++#define FT_QALLOC( ptr, size ) \+ FT_MEM_SET_ERROR( FT_MEM_QALLOC( ptr, size ) )++#define FT_QREALLOC( ptr, cursz, newsz ) \+ FT_MEM_SET_ERROR( FT_MEM_QREALLOC( ptr, cursz, newsz ) )++#define FT_QALLOC_MULT( ptr, count, item_size ) \+ FT_MEM_SET_ERROR( FT_MEM_QALLOC_MULT( ptr, count, item_size ) )++#define FT_QREALLOC_MULT( ptr, oldcnt, newcnt, itmsz ) \+ FT_MEM_SET_ERROR( FT_MEM_QREALLOC_MULT( ptr, oldcnt, \+ newcnt, itmsz ) )++#define FT_FREE( ptr ) FT_MEM_FREE( ptr )++#define FT_NEW( ptr ) FT_MEM_SET_ERROR( FT_MEM_NEW( ptr ) )++#define FT_NEW_ARRAY( ptr, count ) \+ FT_MEM_SET_ERROR( FT_MEM_NEW_ARRAY( ptr, count ) )++#define FT_RENEW_ARRAY( ptr, curcnt, newcnt ) \+ FT_MEM_SET_ERROR( FT_MEM_RENEW_ARRAY( ptr, curcnt, newcnt ) )++#define FT_QNEW( ptr ) \+ FT_MEM_SET_ERROR( FT_MEM_QNEW( ptr ) )++#define FT_QNEW_ARRAY( ptr, count ) \+ FT_MEM_SET_ERROR( FT_MEM_NEW_ARRAY( ptr, count ) )++#define FT_QRENEW_ARRAY( ptr, curcnt, newcnt ) \+ FT_MEM_SET_ERROR( FT_MEM_RENEW_ARRAY( ptr, curcnt, newcnt ) )+++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS++ FT_BASE( FT_Error )+ FT_Alloc( FT_Memory memory,+ FT_Long size,+ void* *P );++ FT_BASE( FT_Error )+ FT_QAlloc( FT_Memory memory,+ FT_Long size,+ void* *p );++ FT_BASE( FT_Error )+ FT_Realloc( FT_Memory memory,+ FT_Long current,+ FT_Long size,+ void* *P );++ FT_BASE( FT_Error )+ FT_QRealloc( FT_Memory memory,+ FT_Long current,+ FT_Long size,+ void* *p );++ FT_BASE( void )+ FT_Free( FT_Memory memory,+ void* *P );++#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */+++ FT_BASE( FT_Pointer )+ ft_mem_strdup( FT_Memory memory,+ const char* str,+ FT_Error *p_error );++ FT_BASE( FT_Pointer )+ ft_mem_dup( FT_Memory memory,+ const void* address,+ FT_ULong size,+ FT_Error *p_error );++#define FT_MEM_STRDUP( dst, str ) \+ (dst) = (char*)ft_mem_strdup( memory, (const char*)(str), &error )++#define FT_STRDUP( dst, str ) \+ FT_MEM_SET_ERROR( FT_MEM_STRDUP( dst, str ) )++#define FT_MEM_DUP( dst, address, size ) \+ (dst) = ft_mem_dup( memory, (address), (FT_ULong)(size), &error )++#define FT_DUP( dst, address, size ) \+ FT_MEM_SET_ERROR( FT_MEM_DUP( dst, address, size ) )+++ /* Return >= 1 if a truncation occurs. */+ /* Return 0 if the source string fits the buffer. */+ /* This is *not* the same as strlcpy(). */+ FT_BASE( FT_Int )+ ft_mem_strcpyn( char* dst,+ const char* src,+ FT_ULong size );++#define FT_STRCPYN( dst, src, size ) \+ ft_mem_strcpyn( (char*)dst, (const char*)(src), (FT_ULong)(size) )++ /* */+++FT_END_HEADER++#endif /* __FTMEMORY_H__ */+++/* END */
+ include/freetype/internal/ftobjs.h view
@@ -0,0 +1,1428 @@+/***************************************************************************/+/* */+/* ftobjs.h */+/* */+/* The FreeType private base classes (specification). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2008, 2010 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++ /*************************************************************************/+ /* */+ /* This file contains the definition of all internal FreeType classes. */+ /* */+ /*************************************************************************/+++#ifndef __FTOBJS_H__+#define __FTOBJS_H__++#include <ft2build.h>+#include FT_RENDER_H+#include FT_SIZES_H+#include FT_LCD_FILTER_H+#include FT_INTERNAL_MEMORY_H+#include FT_INTERNAL_GLYPH_LOADER_H+#include FT_INTERNAL_DRIVER_H+#include FT_INTERNAL_AUTOHINT_H+#include FT_INTERNAL_SERVICE_H+#include FT_INTERNAL_PIC_H++#ifdef FT_CONFIG_OPTION_INCREMENTAL+#include FT_INCREMENTAL_H+#endif+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* Some generic definitions. */+ /* */+#ifndef TRUE+#define TRUE 1+#endif++#ifndef FALSE+#define FALSE 0+#endif++#ifndef NULL+#define NULL (void*)0+#endif+++ /*************************************************************************/+ /* */+ /* The min and max functions missing in C. As usual, be careful not to */+ /* write things like FT_MIN( a++, b++ ) to avoid side effects. */+ /* */+#define FT_MIN( a, b ) ( (a) < (b) ? (a) : (b) )+#define FT_MAX( a, b ) ( (a) > (b) ? (a) : (b) )++#define FT_ABS( a ) ( (a) < 0 ? -(a) : (a) )+++#define FT_PAD_FLOOR( x, n ) ( (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) & ~63 )+#define FT_PIX_ROUND( x ) FT_PIX_FLOOR( (x) + 32 )+#define FT_PIX_CEIL( x ) FT_PIX_FLOOR( (x) + 63 )+++ /*+ * Return the highest power of 2 that is <= value; this correspond to+ * the highest bit in a given 32-bit value.+ */+ FT_BASE( FT_UInt32 )+ ft_highpow2( FT_UInt32 value );+++ /*+ * character classification functions -- since these are used to parse+ * font files, we must not use those in <ctypes.h> which are+ * locale-dependent+ */+#define ft_isdigit( x ) ( ( (unsigned)(x) - '0' ) < 10U )++#define ft_isxdigit( x ) ( ( (unsigned)(x) - '0' ) < 10U || \+ ( (unsigned)(x) - 'a' ) < 6U || \+ ( (unsigned)(x) - 'A' ) < 6U )++ /* the next two macros assume ASCII representation */+#define ft_isupper( x ) ( ( (unsigned)(x) - 'A' ) < 26U )+#define ft_islower( x ) ( ( (unsigned)(x) - 'a' ) < 26U )++#define ft_isalpha( x ) ( ft_isupper( x ) || ft_islower( x ) )+#define ft_isalnum( x ) ( ft_isdigit( x ) || ft_isalpha( x ) )+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** ****/+ /**** C H A R M A P S ****/+ /**** ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/++ /* handle to internal charmap object */+ typedef struct FT_CMapRec_* FT_CMap;++ /* handle to charmap class structure */+ typedef const struct FT_CMap_ClassRec_* FT_CMap_Class;++ /* internal charmap object structure */+ typedef struct FT_CMapRec_+ {+ FT_CharMapRec charmap;+ FT_CMap_Class clazz;++ } FT_CMapRec;++ /* typecase any pointer to a charmap handle */+#define FT_CMAP( x ) ((FT_CMap)( x ))++ /* obvious macros */+#define FT_CMAP_PLATFORM_ID( x ) FT_CMAP( x )->charmap.platform_id+#define FT_CMAP_ENCODING_ID( x ) FT_CMAP( x )->charmap.encoding_id+#define FT_CMAP_ENCODING( x ) FT_CMAP( x )->charmap.encoding+#define FT_CMAP_FACE( x ) FT_CMAP( x )->charmap.face+++ /* class method definitions */+ typedef FT_Error+ (*FT_CMap_InitFunc)( FT_CMap cmap,+ FT_Pointer init_data );++ typedef void+ (*FT_CMap_DoneFunc)( FT_CMap cmap );++ typedef FT_UInt+ (*FT_CMap_CharIndexFunc)( FT_CMap cmap,+ FT_UInt32 char_code );++ typedef FT_UInt+ (*FT_CMap_CharNextFunc)( FT_CMap cmap,+ FT_UInt32 *achar_code );++ typedef FT_UInt+ (*FT_CMap_CharVarIndexFunc)( FT_CMap cmap,+ FT_CMap unicode_cmap,+ FT_UInt32 char_code,+ FT_UInt32 variant_selector );++ typedef FT_Bool+ (*FT_CMap_CharVarIsDefaultFunc)( FT_CMap cmap,+ FT_UInt32 char_code,+ FT_UInt32 variant_selector );++ typedef FT_UInt32 *+ (*FT_CMap_VariantListFunc)( FT_CMap cmap,+ FT_Memory mem );++ typedef FT_UInt32 *+ (*FT_CMap_CharVariantListFunc)( FT_CMap cmap,+ FT_Memory mem,+ FT_UInt32 char_code );++ typedef FT_UInt32 *+ (*FT_CMap_VariantCharListFunc)( FT_CMap cmap,+ FT_Memory mem,+ FT_UInt32 variant_selector );+++ typedef struct FT_CMap_ClassRec_+ {+ FT_ULong size;+ FT_CMap_InitFunc init;+ FT_CMap_DoneFunc done;+ FT_CMap_CharIndexFunc char_index;+ FT_CMap_CharNextFunc char_next;++ /* Subsequent entries are special ones for format 14 -- the variant */+ /* selector subtable which behaves like no other */++ FT_CMap_CharVarIndexFunc char_var_index;+ FT_CMap_CharVarIsDefaultFunc char_var_default;+ FT_CMap_VariantListFunc variant_list;+ FT_CMap_CharVariantListFunc charvariant_list;+ FT_CMap_VariantCharListFunc variantchar_list;++ } FT_CMap_ClassRec;++#ifndef FT_CONFIG_OPTION_PIC++#define FT_DECLARE_CMAP_CLASS(class_) \+ FT_CALLBACK_TABLE const FT_CMap_ClassRec class_;++#define FT_DEFINE_CMAP_CLASS(class_, size_, init_, done_, char_index_, \+ char_next_, char_var_index_, char_var_default_, variant_list_, \+ charvariant_list_, variantchar_list_) \+ FT_CALLBACK_TABLE_DEF \+ const FT_CMap_ClassRec class_ = \+ { \+ size_, init_, done_, char_index_, char_next_, char_var_index_, \+ char_var_default_, variant_list_, charvariant_list_, variantchar_list_ \+ };+#else /* FT_CONFIG_OPTION_PIC */++#define FT_DECLARE_CMAP_CLASS(class_) \+ void FT_Init_Class_##class_( FT_Library library, FT_CMap_ClassRec* clazz);++#define FT_DEFINE_CMAP_CLASS(class_, size_, init_, done_, char_index_, \+ char_next_, char_var_index_, char_var_default_, variant_list_, \+ charvariant_list_, variantchar_list_) \+ void \+ FT_Init_Class_##class_( FT_Library library, \+ FT_CMap_ClassRec* clazz) \+ { \+ FT_UNUSED(library); \+ clazz->size = size_; \+ clazz->init = init_; \+ clazz->done = done_; \+ clazz->char_index = char_index_; \+ clazz->char_next = char_next_; \+ clazz->char_var_index = char_var_index_; \+ clazz->char_var_default = char_var_default_; \+ clazz->variant_list = variant_list_; \+ clazz->charvariant_list = charvariant_list_; \+ clazz->variantchar_list = variantchar_list_; \+ } +#endif /* FT_CONFIG_OPTION_PIC */++ /* create a new charmap and add it to charmap->face */+ FT_BASE( FT_Error )+ FT_CMap_New( FT_CMap_Class clazz,+ FT_Pointer init_data,+ FT_CharMap charmap,+ FT_CMap *acmap );++ /* destroy a charmap and remove it from face's list */+ FT_BASE( void )+ FT_CMap_Done( FT_CMap cmap );+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_Face_InternalRec */+ /* */+ /* <Description> */+ /* This structure contains the internal fields of each FT_Face */+ /* object. These fields may change between different releases of */+ /* FreeType. */+ /* */+ /* <Fields> */+ /* max_points :: */+ /* The maximal number of points used to store the vectorial outline */+ /* of any glyph in this face. If this value cannot be known in */+ /* advance, or if the face isn't scalable, this should be set to 0. */+ /* Only relevant for scalable formats. */+ /* */+ /* max_contours :: */+ /* The maximal number of contours used to store the vectorial */+ /* outline of any glyph in this face. If this value cannot be */+ /* known in advance, or if the face isn't scalable, this should be */+ /* set to 0. Only relevant for scalable formats. */+ /* */+ /* transform_matrix :: */+ /* A 2x2 matrix of 16.16 coefficients used to transform glyph */+ /* outlines after they are loaded from the font. Only used by the */+ /* convenience functions. */+ /* */+ /* transform_delta :: */+ /* A translation vector used to transform glyph outlines after they */+ /* are loaded from the font. Only used by the convenience */+ /* functions. */+ /* */+ /* transform_flags :: */+ /* Some flags used to classify the transform. Only used by the */+ /* convenience functions. */+ /* */+ /* services :: */+ /* A cache for frequently used services. It should be only */+ /* accessed with the macro `FT_FACE_LOOKUP_SERVICE'. */+ /* */+ /* incremental_interface :: */+ /* If non-null, the interface through which glyph data and metrics */+ /* are loaded incrementally for faces that do not provide all of */+ /* this data when first opened. This field exists only if */+ /* @FT_CONFIG_OPTION_INCREMENTAL is defined. */+ /* */+ /* ignore_unpatented_hinter :: */+ /* This boolean flag instructs the glyph loader to ignore the */+ /* native font hinter, if one is found. This is exclusively used */+ /* in the case when the unpatented hinter is compiled within the */+ /* library. */+ /* */+ /* refcount :: */+ /* A counter initialized to~1 at the time an @FT_Face structure is */+ /* created. @FT_Reference_Face increments this counter, and */+ /* @FT_Done_Face only destroys a face if the counter is~1, */+ /* otherwise it simply decrements it. */+ /* */+ typedef struct FT_Face_InternalRec_+ {+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS+ FT_UShort reserved1;+ FT_Short reserved2;+#endif+ FT_Matrix transform_matrix;+ FT_Vector transform_delta;+ FT_Int transform_flags;++ FT_ServiceCacheRec services;++#ifdef FT_CONFIG_OPTION_INCREMENTAL+ FT_Incremental_InterfaceRec* incremental_interface;+#endif++ FT_Bool ignore_unpatented_hinter;+ FT_UInt refcount;++ } FT_Face_InternalRec;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_Slot_InternalRec */+ /* */+ /* <Description> */+ /* This structure contains the internal fields of each FT_GlyphSlot */+ /* object. These fields may change between different releases of */+ /* FreeType. */+ /* */+ /* <Fields> */+ /* loader :: The glyph loader object used to load outlines */+ /* into the glyph slot. */+ /* */+ /* flags :: Possible values are zero or */+ /* FT_GLYPH_OWN_BITMAP. The latter indicates */+ /* that the FT_GlyphSlot structure owns the */+ /* bitmap buffer. */+ /* */+ /* glyph_transformed :: Boolean. Set to TRUE when the loaded glyph */+ /* must be transformed through a specific */+ /* font transformation. This is _not_ the same */+ /* as the face transform set through */+ /* FT_Set_Transform(). */+ /* */+ /* glyph_matrix :: The 2x2 matrix corresponding to the glyph */+ /* transformation, if necessary. */+ /* */+ /* glyph_delta :: The 2d translation vector corresponding to */+ /* the glyph transformation, if necessary. */+ /* */+ /* glyph_hints :: Format-specific glyph hints management. */+ /* */++#define FT_GLYPH_OWN_BITMAP 0x1++ typedef struct FT_Slot_InternalRec_+ {+ FT_GlyphLoader loader;+ FT_UInt flags;+ FT_Bool glyph_transformed;+ FT_Matrix glyph_matrix;+ FT_Vector glyph_delta;+ void* glyph_hints;++ } FT_GlyphSlot_InternalRec;+++#if 0++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_Size_InternalRec */+ /* */+ /* <Description> */+ /* This structure contains the internal fields of each FT_Size */+ /* object. Currently, it's empty. */+ /* */+ /*************************************************************************/++ typedef struct FT_Size_InternalRec_+ {+ /* empty */++ } FT_Size_InternalRec;++#endif+++ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** ****/+ /**** M O D U L E S ****/+ /**** ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_ModuleRec */+ /* */+ /* <Description> */+ /* A module object instance. */+ /* */+ /* <Fields> */+ /* clazz :: A pointer to the module's class. */+ /* */+ /* library :: A handle to the parent library object. */+ /* */+ /* memory :: A handle to the memory manager. */+ /* */+ /* generic :: A generic structure for user-level extensibility (?). */+ /* */+ typedef struct FT_ModuleRec_+ {+ FT_Module_Class* clazz;+ FT_Library library;+ FT_Memory memory;+ FT_Generic generic;++ } FT_ModuleRec;+++ /* typecast an object to a FT_Module */+#define FT_MODULE( x ) ((FT_Module)( x ))+#define FT_MODULE_CLASS( x ) FT_MODULE( x )->clazz+#define FT_MODULE_LIBRARY( x ) FT_MODULE( x )->library+#define FT_MODULE_MEMORY( x ) FT_MODULE( x )->memory+++#define FT_MODULE_IS_DRIVER( x ) ( FT_MODULE_CLASS( x )->module_flags & \+ FT_MODULE_FONT_DRIVER )++#define FT_MODULE_IS_RENDERER( x ) ( FT_MODULE_CLASS( x )->module_flags & \+ FT_MODULE_RENDERER )++#define FT_MODULE_IS_HINTER( x ) ( FT_MODULE_CLASS( x )->module_flags & \+ FT_MODULE_HINTER )++#define FT_MODULE_IS_STYLER( x ) ( FT_MODULE_CLASS( x )->module_flags & \+ FT_MODULE_STYLER )++#define FT_DRIVER_IS_SCALABLE( x ) ( FT_MODULE_CLASS( x )->module_flags & \+ FT_MODULE_DRIVER_SCALABLE )++#define FT_DRIVER_USES_OUTLINES( x ) !( FT_MODULE_CLASS( x )->module_flags & \+ FT_MODULE_DRIVER_NO_OUTLINES )++#define FT_DRIVER_HAS_HINTER( x ) ( FT_MODULE_CLASS( x )->module_flags & \+ FT_MODULE_DRIVER_HAS_HINTER )+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Get_Module_Interface */+ /* */+ /* <Description> */+ /* Finds a module and returns its specific interface as a typeless */+ /* pointer. */+ /* */+ /* <Input> */+ /* library :: A handle to the library object. */+ /* */+ /* module_name :: The module's name (as an ASCII string). */+ /* */+ /* <Return> */+ /* A module-specific interface if available, 0 otherwise. */+ /* */+ /* <Note> */+ /* You should better be familiar with FreeType internals to know */+ /* which module to look for, and what its interface is :-) */+ /* */+ FT_BASE( const void* )+ FT_Get_Module_Interface( FT_Library library,+ const char* mod_name );++ FT_BASE( FT_Pointer )+ ft_module_get_service( FT_Module module,+ const char* service_id );++ /* */+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** ****/+ /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/+ /**** ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/++ /* a few macros used to perform easy typecasts with minimal brain damage */++#define FT_FACE( x ) ((FT_Face)(x))+#define FT_SIZE( x ) ((FT_Size)(x))+#define FT_SLOT( x ) ((FT_GlyphSlot)(x))++#define FT_FACE_DRIVER( x ) FT_FACE( x )->driver+#define FT_FACE_LIBRARY( x ) FT_FACE_DRIVER( x )->root.library+#define FT_FACE_MEMORY( x ) FT_FACE( x )->memory+#define FT_FACE_STREAM( x ) FT_FACE( x )->stream++#define FT_SIZE_FACE( x ) FT_SIZE( x )->face+#define FT_SLOT_FACE( x ) FT_SLOT( x )->face++#define FT_FACE_SLOT( x ) FT_FACE( x )->glyph+#define FT_FACE_SIZE( x ) FT_FACE( x )->size+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_New_GlyphSlot */+ /* */+ /* <Description> */+ /* It is sometimes useful to have more than one glyph slot for a */+ /* given face object. This function is used to create additional */+ /* slots. All of them are automatically discarded when the face is */+ /* destroyed. */+ /* */+ /* <Input> */+ /* face :: A handle to a parent face object. */+ /* */+ /* <Output> */+ /* aslot :: A handle to a new glyph slot object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_BASE( FT_Error )+ FT_New_GlyphSlot( FT_Face face,+ FT_GlyphSlot *aslot );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Done_GlyphSlot */+ /* */+ /* <Description> */+ /* Destroys a given glyph slot. Remember however that all slots are */+ /* automatically destroyed with its parent. Using this function is */+ /* not always mandatory. */+ /* */+ /* <Input> */+ /* slot :: A handle to a target glyph slot. */+ /* */+ FT_BASE( void )+ FT_Done_GlyphSlot( FT_GlyphSlot slot );++ /* */++#define FT_REQUEST_WIDTH( req ) \+ ( (req)->horiResolution \+ ? (FT_Pos)( (req)->width * (req)->horiResolution + 36 ) / 72 \+ : (req)->width )++#define FT_REQUEST_HEIGHT( req ) \+ ( (req)->vertResolution \+ ? (FT_Pos)( (req)->height * (req)->vertResolution + 36 ) / 72 \+ : (req)->height )+++ /* Set the metrics according to a bitmap strike. */+ FT_BASE( void )+ FT_Select_Metrics( FT_Face face,+ FT_ULong strike_index );+++ /* Set the metrics according to a size request. */+ FT_BASE( void )+ FT_Request_Metrics( FT_Face face,+ FT_Size_Request req );+++ /* Match a size request against `available_sizes'. */+ FT_BASE( FT_Error )+ FT_Match_Size( FT_Face face,+ FT_Size_Request req,+ FT_Bool ignore_width,+ FT_ULong* size_index );+++ /* Use the horizontal metrics to synthesize the vertical metrics. */+ /* If `advance' is zero, it is also synthesized. */+ FT_BASE( void )+ ft_synthesize_vertical_metrics( FT_Glyph_Metrics* metrics,+ FT_Pos advance );+++ /* Free the bitmap of a given glyphslot when needed (i.e., only when it */+ /* was allocated with ft_glyphslot_alloc_bitmap). */+ FT_BASE( void )+ ft_glyphslot_free_bitmap( FT_GlyphSlot slot );+++ /* Allocate a new bitmap buffer in a glyph slot. */+ FT_BASE( FT_Error )+ ft_glyphslot_alloc_bitmap( FT_GlyphSlot slot,+ FT_ULong size );+++ /* Set the bitmap buffer in a glyph slot to a given pointer. The buffer */+ /* will not be freed by a later call to ft_glyphslot_free_bitmap. */+ FT_BASE( void )+ ft_glyphslot_set_bitmap( FT_GlyphSlot slot,+ FT_Byte* buffer );+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** ****/+ /**** R E N D E R E R S ****/+ /**** ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++#define FT_RENDERER( x ) ((FT_Renderer)( x ))+#define FT_GLYPH( x ) ((FT_Glyph)( x ))+#define FT_BITMAP_GLYPH( x ) ((FT_BitmapGlyph)( x ))+#define FT_OUTLINE_GLYPH( x ) ((FT_OutlineGlyph)( x ))+++ typedef struct FT_RendererRec_+ {+ FT_ModuleRec root;+ FT_Renderer_Class* clazz;+ FT_Glyph_Format glyph_format;+ FT_Glyph_Class glyph_class;++ FT_Raster raster;+ FT_Raster_Render_Func raster_render;+ FT_Renderer_RenderFunc render;++ } FT_RendererRec;+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** ****/+ /**** F O N T D R I V E R S ****/+ /**** ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ /* typecast a module into a driver easily */+#define FT_DRIVER( x ) ((FT_Driver)(x))++ /* typecast a module as a driver, and get its driver class */+#define FT_DRIVER_CLASS( x ) FT_DRIVER( x )->clazz+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_DriverRec */+ /* */+ /* <Description> */+ /* The root font driver class. A font driver is responsible for */+ /* managing and loading font files of a given format. */+ /* */+ /* <Fields> */+ /* root :: Contains the fields of the root module class. */+ /* */+ /* clazz :: A pointer to the font driver's class. Note that */+ /* this is NOT root.clazz. `class' wasn't used */+ /* as it is a reserved word in C++. */+ /* */+ /* faces_list :: The list of faces currently opened by this */+ /* driver. */+ /* */+ /* extensions :: A typeless pointer to the driver's extensions */+ /* registry, if they are supported through the */+ /* configuration macro FT_CONFIG_OPTION_EXTENSIONS. */+ /* */+ /* glyph_loader :: The glyph loader for all faces managed by this */+ /* driver. This object isn't defined for unscalable */+ /* formats. */+ /* */+ typedef struct FT_DriverRec_+ {+ FT_ModuleRec root;+ FT_Driver_Class clazz;++ FT_ListRec faces_list;+ void* extensions;++ FT_GlyphLoader glyph_loader;++ } FT_DriverRec;+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** ****/+ /**** L I B R A R I E S ****/+ /**** ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ /* This hook is used by the TrueType debugger. It must be set to an */+ /* alternate truetype bytecode interpreter function. */+#define FT_DEBUG_HOOK_TRUETYPE 0+++ /* Set this debug hook to a non-null pointer to force unpatented hinting */+ /* for all faces when both TT_USE_BYTECODE_INTERPRETER and */+ /* TT_CONFIG_OPTION_UNPATENTED_HINTING are defined. This is only used */+ /* during debugging. */+#define FT_DEBUG_HOOK_UNPATENTED_HINTING 1+++ typedef void (*FT_Bitmap_LcdFilterFunc)( FT_Bitmap* bitmap,+ FT_Render_Mode render_mode,+ FT_Library library );+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* FT_LibraryRec */+ /* */+ /* <Description> */+ /* The FreeType library class. This is the root of all FreeType */+ /* data. Use FT_New_Library() to create a library object, and */+ /* FT_Done_Library() to discard it and all child objects. */+ /* */+ /* <Fields> */+ /* memory :: The library's memory object. Manages memory */+ /* allocation. */+ /* */+ /* generic :: Client data variable. Used to extend the */+ /* Library class by higher levels and clients. */+ /* */+ /* version_major :: The major version number of the library. */+ /* */+ /* version_minor :: The minor version number of the library. */+ /* */+ /* version_patch :: The current patch level of the library. */+ /* */+ /* num_modules :: The number of modules currently registered */+ /* within this library. This is set to 0 for new */+ /* libraries. New modules are added through the */+ /* FT_Add_Module() API function. */+ /* */+ /* modules :: A table used to store handles to the currently */+ /* registered modules. Note that each font driver */+ /* contains a list of its opened faces. */+ /* */+ /* renderers :: The list of renderers currently registered */+ /* within the library. */+ /* */+ /* cur_renderer :: The current outline renderer. This is a */+ /* shortcut used to avoid parsing the list on */+ /* each call to FT_Outline_Render(). It is a */+ /* handle to the current renderer for the */+ /* FT_GLYPH_FORMAT_OUTLINE format. */+ /* */+ /* auto_hinter :: XXX */+ /* */+ /* raster_pool :: The raster object's render pool. This can */+ /* ideally be changed dynamically at run-time. */+ /* */+ /* raster_pool_size :: The size of the render pool in bytes. */+ /* */+ /* debug_hooks :: XXX */+ /* */+ /* lcd_filter :: If subpixel rendering is activated, the */+ /* selected LCD filter mode. */+ /* */+ /* lcd_extra :: If subpixel rendering is activated, the number */+ /* of extra pixels needed for the LCD filter. */+ /* */+ /* lcd_weights :: If subpixel rendering is activated, the LCD */+ /* filter weights, if any. */+ /* */+ /* lcd_filter_func :: If subpixel rendering is activated, the LCD */+ /* filtering callback function. */+ /* */+ /* pic_container :: Contains global structs and tables, instead */+ /* of defining them globallly. */+ /* */+ /* refcount :: A counter initialized to~1 at the time an */+ /* @FT_Library structure is created. */+ /* @FT_Reference_Library increments this counter, */+ /* and @FT_Done_Library only destroys a library */+ /* if the counter is~1, otherwise it simply */+ /* decrements it. */+ /* */+ typedef struct FT_LibraryRec_+ {+ FT_Memory memory; /* library's memory manager */++ FT_Generic generic;++ FT_Int version_major;+ FT_Int version_minor;+ FT_Int version_patch;++ FT_UInt num_modules;+ FT_Module modules[FT_MAX_MODULES]; /* module objects */++ FT_ListRec renderers; /* list of renderers */+ FT_Renderer cur_renderer; /* current outline renderer */+ FT_Module auto_hinter;++ FT_Byte* raster_pool; /* scan-line conversion */+ /* render pool */+ FT_ULong raster_pool_size; /* size of render pool in bytes */++ FT_DebugHook_Func debug_hooks[4];++#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING+ FT_LcdFilter lcd_filter;+ FT_Int lcd_extra; /* number of extra pixels */+ FT_Byte lcd_weights[7]; /* filter weights, if any */+ FT_Bitmap_LcdFilterFunc lcd_filter_func; /* filtering callback */+#endif++#ifdef FT_CONFIG_OPTION_PIC+ FT_PIC_Container pic_container;+#endif++ FT_UInt refcount;++ } FT_LibraryRec;+++ FT_BASE( FT_Renderer )+ FT_Lookup_Renderer( FT_Library library,+ FT_Glyph_Format format,+ FT_ListNode* node );++ FT_BASE( FT_Error )+ FT_Render_Glyph_Internal( FT_Library library,+ FT_GlyphSlot slot,+ FT_Render_Mode render_mode );++ typedef const char*+ (*FT_Face_GetPostscriptNameFunc)( FT_Face face );++ typedef FT_Error+ (*FT_Face_GetGlyphNameFunc)( FT_Face face,+ FT_UInt glyph_index,+ FT_Pointer buffer,+ FT_UInt buffer_max );++ typedef FT_UInt+ (*FT_Face_GetGlyphNameIndexFunc)( FT_Face face,+ FT_String* glyph_name );+++#ifndef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_New_Memory */+ /* */+ /* <Description> */+ /* Creates a new memory object. */+ /* */+ /* <Return> */+ /* A pointer to the new memory object. 0 in case of error. */+ /* */+ FT_BASE( FT_Memory )+ FT_New_Memory( void );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Done_Memory */+ /* */+ /* <Description> */+ /* Discards memory manager. */+ /* */+ /* <Input> */+ /* memory :: A handle to the memory manager. */+ /* */+ FT_BASE( void )+ FT_Done_Memory( FT_Memory memory );++#endif /* !FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM */+++ /* Define default raster's interface. The default raster is located in */+ /* `src/base/ftraster.c'. */+ /* */+ /* Client applications can register new rasters through the */+ /* FT_Set_Raster() API. */++#ifndef FT_NO_DEFAULT_RASTER+ FT_EXPORT_VAR( FT_Raster_Funcs ) ft_default_raster;+#endif++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** ****/+ /**** PIC-Support Macros for ftimage.h ****/+ /**** ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Macro> */+ /* FT_DEFINE_OUTLINE_FUNCS */+ /* */+ /* <Description> */+ /* Used to initialize an instance of FT_Outline_Funcs struct. */+ /* When FT_CONFIG_OPTION_PIC is defined an init funtion will need to */+ /* called with a pre-allocated stracture to be filled. */+ /* When FT_CONFIG_OPTION_PIC is not defined the struct will be */+ /* allocated in the global scope (or the scope where the macro */+ /* is used). */+ /* */+#ifndef FT_CONFIG_OPTION_PIC++#define FT_DEFINE_OUTLINE_FUNCS(class_, move_to_, line_to_, conic_to_, \+ cubic_to_, shift_, delta_) \+ static const FT_Outline_Funcs class_ = \+ { \+ move_to_, line_to_, conic_to_, cubic_to_, shift_, delta_ \+ };++#else /* FT_CONFIG_OPTION_PIC */ ++#define FT_DEFINE_OUTLINE_FUNCS(class_, move_to_, line_to_, conic_to_, \+ cubic_to_, shift_, delta_) \+ static FT_Error \+ Init_Class_##class_( FT_Outline_Funcs* clazz ) \+ { \+ clazz->move_to = move_to_; \+ clazz->line_to = line_to_; \+ clazz->conic_to = conic_to_; \+ clazz->cubic_to = cubic_to_; \+ clazz->shift = shift_; \+ clazz->delta = delta_; \+ return FT_Err_Ok; \+ } ++#endif /* FT_CONFIG_OPTION_PIC */ ++ /*************************************************************************/+ /* */+ /* <Macro> */+ /* FT_DEFINE_RASTER_FUNCS */+ /* */+ /* <Description> */+ /* Used to initialize an instance of FT_Raster_Funcs struct. */+ /* When FT_CONFIG_OPTION_PIC is defined an init funtion will need to */+ /* called with a pre-allocated stracture to be filled. */+ /* When FT_CONFIG_OPTION_PIC is not defined the struct will be */+ /* allocated in the global scope (or the scope where the macro */+ /* is used). */+ /* */+#ifndef FT_CONFIG_OPTION_PIC++#define FT_DEFINE_RASTER_FUNCS(class_, glyph_format_, raster_new_, \+ raster_reset_, raster_set_mode_, \+ raster_render_, raster_done_) \+ const FT_Raster_Funcs class_ = \+ { \+ glyph_format_, raster_new_, raster_reset_, \+ raster_set_mode_, raster_render_, raster_done_ \+ };++#else /* FT_CONFIG_OPTION_PIC */ ++#define FT_DEFINE_RASTER_FUNCS(class_, glyph_format_, raster_new_, \+ raster_reset_, raster_set_mode_, raster_render_, raster_done_) \+ void \+ FT_Init_Class_##class_( FT_Raster_Funcs* clazz ) \+ { \+ clazz->glyph_format = glyph_format_; \+ clazz->raster_new = raster_new_; \+ clazz->raster_reset = raster_reset_; \+ clazz->raster_set_mode = raster_set_mode_; \+ clazz->raster_render = raster_render_; \+ clazz->raster_done = raster_done_; \+ } ++#endif /* FT_CONFIG_OPTION_PIC */ ++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** ****/+ /**** PIC-Support Macros for ftrender.h ****/+ /**** ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/++++ /*************************************************************************/+ /* */+ /* <Macro> */+ /* FT_DEFINE_GLYPH */+ /* */+ /* <Description> */+ /* Used to initialize an instance of FT_Glyph_Class struct. */+ /* When FT_CONFIG_OPTION_PIC is defined an init funtion will need to */+ /* called with a pre-allocated stracture to be filled. */+ /* When FT_CONFIG_OPTION_PIC is not defined the struct will be */+ /* allocated in the global scope (or the scope where the macro */+ /* is used). */+ /* */+#ifndef FT_CONFIG_OPTION_PIC++#define FT_DEFINE_GLYPH(class_, size_, format_, init_, done_, copy_, \+ transform_, bbox_, prepare_) \+ FT_CALLBACK_TABLE_DEF \+ const FT_Glyph_Class class_ = \+ { \+ size_, format_, init_, done_, copy_, transform_, bbox_, prepare_ \+ };++#else /* FT_CONFIG_OPTION_PIC */ ++#define FT_DEFINE_GLYPH(class_, size_, format_, init_, done_, copy_, \+ transform_, bbox_, prepare_) \+ void \+ FT_Init_Class_##class_( FT_Glyph_Class* clazz ) \+ { \+ clazz->glyph_size = size_; \+ clazz->glyph_format = format_; \+ clazz->glyph_init = init_; \+ clazz->glyph_done = done_; \+ clazz->glyph_copy = copy_; \+ clazz->glyph_transform = transform_; \+ clazz->glyph_bbox = bbox_; \+ clazz->glyph_prepare = prepare_; \+ } ++#endif /* FT_CONFIG_OPTION_PIC */ ++ /*************************************************************************/+ /* */+ /* <Macro> */+ /* FT_DECLARE_RENDERER */+ /* */+ /* <Description> */+ /* Used to create a forward declaration of a */+ /* FT_Renderer_Class stract instance. */+ /* */+ /* <Macro> */+ /* FT_DEFINE_RENDERER */+ /* */+ /* <Description> */+ /* Used to initialize an instance of FT_Renderer_Class struct. */+ /* */+ /* When FT_CONFIG_OPTION_PIC is defined a Create funtion will need */+ /* to called with a pointer where the allocated stracture is returned.*/+ /* And when it is no longer needed a Destroy function needs */+ /* to be called to release that allocation. */+ /* fcinit.c (ft_create_default_module_classes) already contains */+ /* a mechanism to call these functions for the default modules */+ /* described in ftmodule.h */+ /* */+ /* Notice that the created Create and Destroy functions call */+ /* pic_init and pic_free function to allow you to manually allocate */+ /* and initialize any additional global data, like module specific */+ /* interface, and put them in the global pic container defined in */+ /* ftpic.h. if you don't need them just implement the functions as */+ /* empty to resolve the link error. */+ /* */+ /* When FT_CONFIG_OPTION_PIC is not defined the struct will be */+ /* allocated in the global scope (or the scope where the macro */+ /* is used). */+ /* */+#ifndef FT_CONFIG_OPTION_PIC++#define FT_DECLARE_RENDERER(class_) \+ FT_EXPORT_VAR( const FT_Renderer_Class ) class_;++#define FT_DEFINE_RENDERER(class_, \+ flags_, size_, name_, version_, requires_, \+ interface_, init_, done_, get_interface_, \+ glyph_format_, render_glyph_, transform_glyph_, \+ get_glyph_cbox_, set_mode_, raster_class_ ) \+ FT_CALLBACK_TABLE_DEF \+ const FT_Renderer_Class class_ = \+ { \+ FT_DEFINE_ROOT_MODULE(flags_,size_,name_,version_,requires_, \+ interface_,init_,done_,get_interface_) \+ glyph_format_, \+ \+ render_glyph_, \+ transform_glyph_, \+ get_glyph_cbox_, \+ set_mode_, \+ \+ raster_class_ \+ };++#else /* FT_CONFIG_OPTION_PIC */ ++#define FT_DECLARE_RENDERER(class_) FT_DECLARE_MODULE(class_)++#define FT_DEFINE_RENDERER(class_, \+ flags_, size_, name_, version_, requires_, \+ interface_, init_, done_, get_interface_, \+ glyph_format_, render_glyph_, transform_glyph_, \+ get_glyph_cbox_, set_mode_, raster_class_ ) \+ void class_##_pic_free( FT_Library library ); \+ FT_Error class_##_pic_init( FT_Library library ); \+ \+ void \+ FT_Destroy_Class_##class_( FT_Library library, \+ FT_Module_Class* clazz ) \+ { \+ FT_Renderer_Class* rclazz = (FT_Renderer_Class*)clazz; \+ FT_Memory memory = library->memory; \+ class_##_pic_free( library ); \+ if ( rclazz ) \+ FT_FREE( rclazz ); \+ } \+ \+ FT_Error \+ FT_Create_Class_##class_( FT_Library library, \+ FT_Module_Class** output_class ) \+ { \+ FT_Renderer_Class* clazz; \+ FT_Error error; \+ FT_Memory memory = library->memory; \+ \+ if ( FT_ALLOC( clazz, sizeof(*clazz) ) ) \+ return error; \+ \+ error = class_##_pic_init( library ); \+ if(error) \+ { \+ FT_FREE( clazz ); \+ return error; \+ } \+ \+ FT_DEFINE_ROOT_MODULE(flags_,size_,name_,version_,requires_, \+ interface_,init_,done_,get_interface_) \+ \+ clazz->glyph_format = glyph_format_; \+ \+ clazz->render_glyph = render_glyph_; \+ clazz->transform_glyph = transform_glyph_; \+ clazz->get_glyph_cbox = get_glyph_cbox_; \+ clazz->set_mode = set_mode_; \+ \+ clazz->raster_class = raster_class_; \+ \+ *output_class = (FT_Module_Class*)clazz; \+ return FT_Err_Ok; \+ } ++++#endif /* FT_CONFIG_OPTION_PIC */ ++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** ****/+ /**** PIC-Support Macros for ftmodapi.h ****/+ /**** ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++#ifdef FT_CONFIG_OPTION_PIC++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* FT_Module_Creator */+ /* */+ /* <Description> */+ /* A function used to create (allocate) a new module class object. */+ /* The object's members are initialized, but the module itself is */+ /* not. */+ /* */+ /* <Input> */+ /* memory :: A handle to the memory manager. */+ /* output_class :: Initialized with the newly allocated class. */+ /* */+ typedef FT_Error+ (*FT_Module_Creator)( FT_Memory memory,+ FT_Module_Class** output_class );++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* FT_Module_Destroyer */+ /* */+ /* <Description> */+ /* A function used to destroy (deallocate) a module class object. */+ /* */+ /* <Input> */+ /* memory :: A handle to the memory manager. */+ /* clazz :: Module class to destroy. */+ /* */+ typedef void+ (*FT_Module_Destroyer)( FT_Memory memory,+ FT_Module_Class* clazz );++#endif++ /*************************************************************************/+ /* */+ /* <Macro> */+ /* FT_DECLARE_MODULE */+ /* */+ /* <Description> */+ /* Used to create a forward declaration of a */+ /* FT_Module_Class stract instance. */+ /* */+ /* <Macro> */+ /* FT_DEFINE_MODULE */+ /* */+ /* <Description> */+ /* Used to initialize an instance of FT_Module_Class struct. */+ /* */+ /* When FT_CONFIG_OPTION_PIC is defined a Create funtion will need */+ /* to called with a pointer where the allocated stracture is returned.*/+ /* And when it is no longer needed a Destroy function needs */+ /* to be called to release that allocation. */+ /* fcinit.c (ft_create_default_module_classes) already contains */+ /* a mechanism to call these functions for the default modules */+ /* described in ftmodule.h */+ /* */+ /* Notice that the created Create and Destroy functions call */+ /* pic_init and pic_free function to allow you to manually allocate */+ /* and initialize any additional global data, like module specific */+ /* interface, and put them in the global pic container defined in */+ /* ftpic.h. if you don't need them just implement the functions as */+ /* empty to resolve the link error. */+ /* */+ /* When FT_CONFIG_OPTION_PIC is not defined the struct will be */+ /* allocated in the global scope (or the scope where the macro */+ /* is used). */+ /* */+ /* <Macro> */+ /* FT_DEFINE_ROOT_MODULE */+ /* */+ /* <Description> */+ /* Used to initialize an instance of FT_Module_Class struct inside */+ /* another stract that contains it or in a function that initializes */+ /* that containing stract */+ /* */+#ifndef FT_CONFIG_OPTION_PIC++#define FT_DECLARE_MODULE(class_) \+ FT_CALLBACK_TABLE \+ const FT_Module_Class class_; \++#define FT_DEFINE_ROOT_MODULE(flags_, size_, name_, version_, requires_, \+ interface_, init_, done_, get_interface_) \+ { \+ flags_, \+ size_, \+ \+ name_, \+ version_, \+ requires_, \+ \+ interface_, \+ \+ init_, \+ done_, \+ get_interface_, \+ },++#define FT_DEFINE_MODULE(class_, flags_, size_, name_, version_, requires_, \+ interface_, init_, done_, get_interface_) \+ FT_CALLBACK_TABLE_DEF \+ const FT_Module_Class class_ = \+ { \+ flags_, \+ size_, \+ \+ name_, \+ version_, \+ requires_, \+ \+ interface_, \+ \+ init_, \+ done_, \+ get_interface_, \+ };+++#else /* FT_CONFIG_OPTION_PIC */++#define FT_DECLARE_MODULE(class_) \+ FT_Error FT_Create_Class_##class_( FT_Library library, \+ FT_Module_Class** output_class ); \+ void FT_Destroy_Class_##class_( FT_Library library, \+ FT_Module_Class* clazz );++#define FT_DEFINE_ROOT_MODULE(flags_, size_, name_, version_, requires_, \+ interface_, init_, done_, get_interface_) \+ clazz->root.module_flags = flags_; \+ clazz->root.module_size = size_; \+ clazz->root.module_name = name_; \+ clazz->root.module_version = version_; \+ clazz->root.module_requires = requires_; \+ \+ clazz->root.module_interface = interface_; \+ \+ clazz->root.module_init = init_; \+ clazz->root.module_done = done_; \+ clazz->root.get_interface = get_interface_; ++#define FT_DEFINE_MODULE(class_, flags_, size_, name_, version_, requires_, \+ interface_, init_, done_, get_interface_) \+ void class_##_pic_free( FT_Library library ); \+ FT_Error class_##_pic_init( FT_Library library ); \+ \+ void \+ FT_Destroy_Class_##class_( FT_Library library, \+ FT_Module_Class* clazz ) \+ { \+ FT_Memory memory = library->memory; \+ class_##_pic_free( library ); \+ if ( clazz ) \+ FT_FREE( clazz ); \+ } \+ \+ FT_Error \+ FT_Create_Class_##class_( FT_Library library, \+ FT_Module_Class** output_class ) \+ { \+ FT_Memory memory = library->memory; \+ FT_Module_Class* clazz; \+ FT_Error error; \+ \+ if ( FT_ALLOC( clazz, sizeof(*clazz) ) ) \+ return error; \+ error = class_##_pic_init( library ); \+ if(error) \+ { \+ FT_FREE( clazz ); \+ return error; \+ } \+ \+ clazz->module_flags = flags_; \+ clazz->module_size = size_; \+ clazz->module_name = name_; \+ clazz->module_version = version_; \+ clazz->module_requires = requires_; \+ \+ clazz->module_interface = interface_; \+ \+ clazz->module_init = init_; \+ clazz->module_done = done_; \+ clazz->get_interface = get_interface_; \+ \+ *output_class = clazz; \+ return FT_Err_Ok; \+ } ++#endif /* FT_CONFIG_OPTION_PIC */+++FT_END_HEADER++#endif /* __FTOBJS_H__ */+++/* END */
+ include/freetype/internal/ftpic.h view
@@ -0,0 +1,67 @@+/***************************************************************************/+/* */+/* ftpic.h */+/* */+/* The FreeType position independent code services (declaration). */+/* */+/* Copyright 2009 by */+/* Oran Agra and Mickey Gabel. */+/* */+/* 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. */+/* */+/***************************************************************************/++ /*************************************************************************/+ /* */+ /* Modules that ordinarily have const global data that need address */+ /* can instead define pointers here. */+ /* */+ /*************************************************************************/+++#ifndef __FTPIC_H__+#define __FTPIC_H__++ +FT_BEGIN_HEADER++#ifdef FT_CONFIG_OPTION_PIC++ typedef struct FT_PIC_Container_+ {+ /* pic containers for base */+ void* base;+ /* pic containers for modules */+ void* autofit; + void* cff; + void* pshinter; + void* psnames; + void* raster; + void* sfnt; + void* smooth; + void* truetype; + } FT_PIC_Container;++ /* Initialize the various function tables, structs, etc. stored in the container. */+ FT_BASE( FT_Error )+ ft_pic_container_init( FT_Library library );+++ /* Destroy the contents of the container. */+ FT_BASE( void )+ ft_pic_container_destroy( FT_Library library );++#endif /* FT_CONFIG_OPTION_PIC */++ /* */++FT_END_HEADER++#endif /* __FTPIC_H__ */+++/* END */
+ include/freetype/internal/ftrfork.h view
@@ -0,0 +1,196 @@+/***************************************************************************/+/* */+/* ftrfork.h */+/* */+/* Embedded resource forks accessor (specification). */+/* */+/* Copyright 2004, 2006, 2007 by */+/* Masatake YAMATO and Redhat K.K. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/++/***************************************************************************/+/* Development of the code in this file is support of */+/* Information-technology Promotion Agency, Japan. */+/***************************************************************************/+++#ifndef __FTRFORK_H__+#define __FTRFORK_H__+++#include <ft2build.h>+#include FT_INTERNAL_OBJECTS_H+++FT_BEGIN_HEADER+++ /* Number of guessing rules supported in `FT_Raccess_Guess'. */+ /* Don't forget to increment the number if you add a new guessing rule. */+#define FT_RACCESS_N_RULES 9+++ /* A structure to describe a reference in a resource by its resource ID */+ /* and internal offset. The `POST' resource expects to be concatenated */+ /* by the order of resource IDs instead of its appearance in the file. */++ typedef struct FT_RFork_Ref_+ {+ FT_UShort res_id;+ FT_ULong offset;++ } FT_RFork_Ref;+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Raccess_Guess */+ /* */+ /* <Description> */+ /* Guess a file name and offset where the actual resource fork is */+ /* stored. The macro FT_RACCESS_N_RULES holds the number of */+ /* guessing rules; the guessed result for the Nth rule is */+ /* represented as a triplet: a new file name (new_names[N]), a file */+ /* offset (offsets[N]), and an error code (errors[N]). */+ /* */+ /* <Input> */+ /* library :: */+ /* A FreeType library instance. */+ /* */+ /* stream :: */+ /* A file stream containing the resource fork. */+ /* */+ /* base_name :: */+ /* The (base) file name of the resource fork used for some */+ /* guessing rules. */+ /* */+ /* <Output> */+ /* new_names :: */+ /* An array of guessed file names in which the resource forks may */+ /* exist. If `new_names[N]' is NULL, the guessed file name is */+ /* equal to `base_name'. */+ /* */+ /* offsets :: */+ /* An array of guessed file offsets. `offsets[N]' holds the file */+ /* offset of the possible start of the resource fork in file */+ /* `new_names[N]'. */+ /* */+ /* errors :: */+ /* An array of FreeType error codes. `errors[N]' is the error */+ /* code of Nth guessing rule function. If `errors[N]' is not */+ /* FT_Err_Ok, `new_names[N]' and `offsets[N]' are meaningless. */+ /* */+ FT_BASE( void )+ FT_Raccess_Guess( FT_Library library,+ FT_Stream stream,+ char* base_name,+ char** new_names,+ FT_Long* offsets,+ FT_Error* errors );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Raccess_Get_HeaderInfo */+ /* */+ /* <Description> */+ /* Get the information from the header of resource fork. The */+ /* information includes the file offset where the resource map */+ /* starts, and the file offset where the resource data starts. */+ /* `FT_Raccess_Get_DataOffsets' requires these two data. */+ /* */+ /* <Input> */+ /* library :: */+ /* A FreeType library instance. */+ /* */+ /* stream :: */+ /* A file stream containing the resource fork. */+ /* */+ /* rfork_offset :: */+ /* The file offset where the resource fork starts. */+ /* */+ /* <Output> */+ /* map_offset :: */+ /* The file offset where the resource map starts. */+ /* */+ /* rdata_pos :: */+ /* The file offset where the resource data starts. */+ /* */+ /* <Return> */+ /* FreeType error code. FT_Err_Ok means success. */+ /* */+ FT_BASE( FT_Error )+ FT_Raccess_Get_HeaderInfo( FT_Library library,+ FT_Stream stream,+ FT_Long rfork_offset,+ FT_Long *map_offset,+ FT_Long *rdata_pos );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Raccess_Get_DataOffsets */+ /* */+ /* <Description> */+ /* Get the data offsets for a tag in a resource fork. Offsets are */+ /* stored in an array because, in some cases, resources in a resource */+ /* fork have the same tag. */+ /* */+ /* <Input> */+ /* library :: */+ /* A FreeType library instance. */+ /* */+ /* stream :: */+ /* A file stream containing the resource fork. */+ /* */+ /* map_offset :: */+ /* The file offset where the resource map starts. */+ /* */+ /* rdata_pos :: */+ /* The file offset where the resource data starts. */+ /* */+ /* tag :: */+ /* The resource tag. */+ /* */+ /* <Output> */+ /* offsets :: */+ /* The stream offsets for the resource data specified by `tag'. */+ /* This array is allocated by the function, so you have to call */+ /* @ft_mem_free after use. */+ /* */+ /* count :: */+ /* The length of offsets array. */+ /* */+ /* <Return> */+ /* FreeType error code. FT_Err_Ok means success. */+ /* */+ /* <Note> */+ /* Normally you should use `FT_Raccess_Get_HeaderInfo' to get the */+ /* value for `map_offset' and `rdata_pos'. */+ /* */+ FT_BASE( FT_Error )+ FT_Raccess_Get_DataOffsets( FT_Library library,+ FT_Stream stream,+ FT_Long map_offset,+ FT_Long rdata_pos,+ FT_Long tag,+ FT_Long **offsets,+ FT_Long *count );+++FT_END_HEADER++#endif /* __FTRFORK_H__ */+++/* END */
+ include/freetype/internal/ftserv.h view
@@ -0,0 +1,620 @@+/***************************************************************************/+/* */+/* ftserv.h */+/* */+/* The FreeType services (specification only). */+/* */+/* Copyright 2003, 2004, 2005, 2006, 2007 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. */+/* */+/***************************************************************************/++ /*************************************************************************/+ /* */+ /* Each module can export one or more `services'. Each service is */+ /* identified by a constant string and modeled by a pointer; the latter */+ /* generally corresponds to a structure containing function pointers. */+ /* */+ /* Note that a service's data cannot be a mere function pointer because */+ /* in C it is possible that function pointers might be implemented */+ /* differently than data pointers (e.g. 48 bits instead of 32). */+ /* */+ /*************************************************************************/+++#ifndef __FTSERV_H__+#define __FTSERV_H__+++FT_BEGIN_HEADER++#if defined( _MSC_VER ) /* Visual C++ (and Intel C++) */++ /* we disable the warning `conditional expression is constant' here */+ /* in order to compile cleanly with the maximum level of warnings */+#pragma warning( disable : 4127 )++#endif /* _MSC_VER */++ /*+ * @macro:+ * FT_FACE_FIND_SERVICE+ *+ * @description:+ * This macro is used to look up a service from a face's driver module.+ *+ * @input:+ * face ::+ * The source face handle.+ *+ * id ::+ * A string describing the service as defined in the service's+ * header files (e.g. FT_SERVICE_ID_MULTI_MASTERS which expands to+ * `multi-masters'). It is automatically prefixed with+ * `FT_SERVICE_ID_'.+ *+ * @output:+ * ptr ::+ * A variable that receives the service pointer. Will be NULL+ * if not found.+ */+#ifdef __cplusplus++#define FT_FACE_FIND_SERVICE( face, ptr, id ) \+ FT_BEGIN_STMNT \+ FT_Module module = FT_MODULE( FT_FACE( face )->driver ); \+ FT_Pointer _tmp_ = NULL; \+ FT_Pointer* _pptr_ = (FT_Pointer*)&(ptr); \+ \+ \+ if ( module->clazz->get_interface ) \+ _tmp_ = module->clazz->get_interface( module, FT_SERVICE_ID_ ## id ); \+ *_pptr_ = _tmp_; \+ FT_END_STMNT++#else /* !C++ */++#define FT_FACE_FIND_SERVICE( face, ptr, id ) \+ FT_BEGIN_STMNT \+ FT_Module module = FT_MODULE( FT_FACE( face )->driver ); \+ FT_Pointer _tmp_ = NULL; \+ \+ if ( module->clazz->get_interface ) \+ _tmp_ = module->clazz->get_interface( module, FT_SERVICE_ID_ ## id ); \+ ptr = _tmp_; \+ FT_END_STMNT++#endif /* !C++ */++ /*+ * @macro:+ * FT_FACE_FIND_GLOBAL_SERVICE+ *+ * @description:+ * This macro is used to look up a service from all modules.+ *+ * @input:+ * face ::+ * The source face handle.+ *+ * id ::+ * A string describing the service as defined in the service's+ * header files (e.g. FT_SERVICE_ID_MULTI_MASTERS which expands to+ * `multi-masters'). It is automatically prefixed with+ * `FT_SERVICE_ID_'.+ *+ * @output:+ * ptr ::+ * A variable that receives the service pointer. Will be NULL+ * if not found.+ */+#ifdef __cplusplus++#define FT_FACE_FIND_GLOBAL_SERVICE( face, ptr, id ) \+ FT_BEGIN_STMNT \+ FT_Module module = FT_MODULE( FT_FACE( face )->driver ); \+ FT_Pointer _tmp_; \+ FT_Pointer* _pptr_ = (FT_Pointer*)&(ptr); \+ \+ \+ _tmp_ = ft_module_get_service( module, FT_SERVICE_ID_ ## id ); \+ *_pptr_ = _tmp_; \+ FT_END_STMNT++#else /* !C++ */++#define FT_FACE_FIND_GLOBAL_SERVICE( face, ptr, id ) \+ FT_BEGIN_STMNT \+ FT_Module module = FT_MODULE( FT_FACE( face )->driver ); \+ FT_Pointer _tmp_; \+ \+ \+ _tmp_ = ft_module_get_service( module, FT_SERVICE_ID_ ## id ); \+ ptr = _tmp_; \+ FT_END_STMNT++#endif /* !C++ */+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** S E R V I C E D E S C R I P T O R S *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /*+ * The following structure is used to _describe_ a given service+ * to the library. This is useful to build simple static service lists.+ */+ typedef struct FT_ServiceDescRec_+ {+ const char* serv_id; /* service name */+ const void* serv_data; /* service pointer/data */++ } FT_ServiceDescRec;++ typedef const FT_ServiceDescRec* FT_ServiceDesc;++ /*************************************************************************/+ /* */+ /* <Macro> */+ /* FT_DEFINE_SERVICEDESCREC1 .. FT_DEFINE_SERVICEDESCREC6 */+ /* */+ /* <Description> */+ /* Used to initialize an array of FT_ServiceDescRec structs. */+ /* */+ /* When FT_CONFIG_OPTION_PIC is defined a Create funtion will need */+ /* to called with a pointer where the allocated array is returned. */+ /* And when it is no longer needed a Destroy function needs */+ /* to be called to release that allocation. */+ /* */+ /* These functions should be manyally called from the pic_init and */+ /* pic_free functions of your module (see FT_DEFINE_MODULE) */+ /* */+ /* When FT_CONFIG_OPTION_PIC is not defined the array will be */+ /* allocated in the global scope (or the scope where the macro */+ /* is used). */+ /* */+#ifndef FT_CONFIG_OPTION_PIC++#define FT_DEFINE_SERVICEDESCREC1(class_, serv_id_1, serv_data_1) \+ static const FT_ServiceDescRec class_[] = \+ { \+ {serv_id_1, serv_data_1}, \+ {NULL, NULL} \+ };+#define FT_DEFINE_SERVICEDESCREC2(class_, serv_id_1, serv_data_1, \+ serv_id_2, serv_data_2) \+ static const FT_ServiceDescRec class_[] = \+ { \+ {serv_id_1, serv_data_1}, \+ {serv_id_2, serv_data_2}, \+ {NULL, NULL} \+ };+#define FT_DEFINE_SERVICEDESCREC3(class_, serv_id_1, serv_data_1, \+ serv_id_2, serv_data_2, serv_id_3, serv_data_3) \+ static const FT_ServiceDescRec class_[] = \+ { \+ {serv_id_1, serv_data_1}, \+ {serv_id_2, serv_data_2}, \+ {serv_id_3, serv_data_3}, \+ {NULL, NULL} \+ };+#define FT_DEFINE_SERVICEDESCREC4(class_, serv_id_1, serv_data_1, \+ serv_id_2, serv_data_2, serv_id_3, serv_data_3, \+ serv_id_4, serv_data_4) \+ static const FT_ServiceDescRec class_[] = \+ { \+ {serv_id_1, serv_data_1}, \+ {serv_id_2, serv_data_2}, \+ {serv_id_3, serv_data_3}, \+ {serv_id_4, serv_data_4}, \+ {NULL, NULL} \+ };+#define FT_DEFINE_SERVICEDESCREC5(class_, serv_id_1, serv_data_1, \+ serv_id_2, serv_data_2, serv_id_3, serv_data_3, \+ serv_id_4, serv_data_4, serv_id_5, serv_data_5) \+ static const FT_ServiceDescRec class_[] = \+ { \+ {serv_id_1, serv_data_1}, \+ {serv_id_2, serv_data_2}, \+ {serv_id_3, serv_data_3}, \+ {serv_id_4, serv_data_4}, \+ {serv_id_5, serv_data_5}, \+ {NULL, NULL} \+ };+#define FT_DEFINE_SERVICEDESCREC6(class_, serv_id_1, serv_data_1, \+ serv_id_2, serv_data_2, serv_id_3, serv_data_3, \+ serv_id_4, serv_data_4, serv_id_5, serv_data_5, \+ serv_id_6, serv_data_6) \+ static const FT_ServiceDescRec class_[] = \+ { \+ {serv_id_1, serv_data_1}, \+ {serv_id_2, serv_data_2}, \+ {serv_id_3, serv_data_3}, \+ {serv_id_4, serv_data_4}, \+ {serv_id_5, serv_data_5}, \+ {serv_id_6, serv_data_6}, \+ {NULL, NULL} \+ };++#else /* FT_CONFIG_OPTION_PIC */ ++#define FT_DEFINE_SERVICEDESCREC1(class_, serv_id_1, serv_data_1) \+ void \+ FT_Destroy_Class_##class_( FT_Library library, \+ FT_ServiceDescRec* clazz ) \+ { \+ FT_Memory memory = library->memory; \+ if ( clazz ) \+ FT_FREE( clazz ); \+ } \+ \+ FT_Error \+ FT_Create_Class_##class_( FT_Library library, \+ FT_ServiceDescRec** output_class) \+ { \+ FT_ServiceDescRec* clazz; \+ FT_Error error; \+ FT_Memory memory = library->memory; \+ \+ if ( FT_ALLOC( clazz, sizeof(*clazz)*2 ) ) \+ return error; \+ clazz[0].serv_id = serv_id_1; \+ clazz[0].serv_data = serv_data_1; \+ clazz[1].serv_id = NULL; \+ clazz[1].serv_data = NULL; \+ *output_class = clazz; \+ return FT_Err_Ok; \+ } ++#define FT_DEFINE_SERVICEDESCREC2(class_, serv_id_1, serv_data_1, \+ serv_id_2, serv_data_2) \+ void \+ FT_Destroy_Class_##class_( FT_Library library, \+ FT_ServiceDescRec* clazz ) \+ { \+ FT_Memory memory = library->memory; \+ if ( clazz ) \+ FT_FREE( clazz ); \+ } \+ \+ FT_Error \+ FT_Create_Class_##class_( FT_Library library, \+ FT_ServiceDescRec** output_class) \+ { \+ FT_ServiceDescRec* clazz; \+ FT_Error error; \+ FT_Memory memory = library->memory; \+ \+ if ( FT_ALLOC( clazz, sizeof(*clazz)*3 ) ) \+ return error; \+ clazz[0].serv_id = serv_id_1; \+ clazz[0].serv_data = serv_data_1; \+ clazz[1].serv_id = serv_id_2; \+ clazz[1].serv_data = serv_data_2; \+ clazz[2].serv_id = NULL; \+ clazz[2].serv_data = NULL; \+ *output_class = clazz; \+ return FT_Err_Ok; \+ } ++#define FT_DEFINE_SERVICEDESCREC3(class_, serv_id_1, serv_data_1, \+ serv_id_2, serv_data_2, serv_id_3, serv_data_3) \+ void \+ FT_Destroy_Class_##class_( FT_Library library, \+ FT_ServiceDescRec* clazz ) \+ { \+ FT_Memory memory = library->memory; \+ if ( clazz ) \+ FT_FREE( clazz ); \+ } \+ \+ FT_Error \+ FT_Create_Class_##class_( FT_Library library, \+ FT_ServiceDescRec** output_class) \+ { \+ FT_ServiceDescRec* clazz; \+ FT_Error error; \+ FT_Memory memory = library->memory; \+ \+ if ( FT_ALLOC( clazz, sizeof(*clazz)*4 ) ) \+ return error; \+ clazz[0].serv_id = serv_id_1; \+ clazz[0].serv_data = serv_data_1; \+ clazz[1].serv_id = serv_id_2; \+ clazz[1].serv_data = serv_data_2; \+ clazz[2].serv_id = serv_id_3; \+ clazz[2].serv_data = serv_data_3; \+ clazz[3].serv_id = NULL; \+ clazz[3].serv_data = NULL; \+ *output_class = clazz; \+ return FT_Err_Ok; \+ } ++#define FT_DEFINE_SERVICEDESCREC4(class_, serv_id_1, serv_data_1, \+ serv_id_2, serv_data_2, serv_id_3, serv_data_3, \+ serv_id_4, serv_data_4) \+ void \+ FT_Destroy_Class_##class_( FT_Library library, \+ FT_ServiceDescRec* clazz ) \+ { \+ FT_Memory memory = library->memory; \+ if ( clazz ) \+ FT_FREE( clazz ); \+ } \+ \+ FT_Error \+ FT_Create_Class_##class_( FT_Library library, \+ FT_ServiceDescRec** output_class) \+ { \+ FT_ServiceDescRec* clazz; \+ FT_Error error; \+ FT_Memory memory = library->memory; \+ \+ if ( FT_ALLOC( clazz, sizeof(*clazz)*5 ) ) \+ return error; \+ clazz[0].serv_id = serv_id_1; \+ clazz[0].serv_data = serv_data_1; \+ clazz[1].serv_id = serv_id_2; \+ clazz[1].serv_data = serv_data_2; \+ clazz[2].serv_id = serv_id_3; \+ clazz[2].serv_data = serv_data_3; \+ clazz[3].serv_id = serv_id_4; \+ clazz[3].serv_data = serv_data_4; \+ clazz[4].serv_id = NULL; \+ clazz[4].serv_data = NULL; \+ *output_class = clazz; \+ return FT_Err_Ok; \+ } ++#define FT_DEFINE_SERVICEDESCREC5(class_, serv_id_1, serv_data_1, \+ serv_id_2, serv_data_2, serv_id_3, serv_data_3, serv_id_4, \+ serv_data_4, serv_id_5, serv_data_5) \+ void \+ FT_Destroy_Class_##class_( FT_Library library, \+ FT_ServiceDescRec* clazz ) \+ { \+ FT_Memory memory = library->memory; \+ if ( clazz ) \+ FT_FREE( clazz ); \+ } \+ \+ FT_Error \+ FT_Create_Class_##class_( FT_Library library, \+ FT_ServiceDescRec** output_class) \+ { \+ FT_ServiceDescRec* clazz; \+ FT_Error error; \+ FT_Memory memory = library->memory; \+ \+ if ( FT_ALLOC( clazz, sizeof(*clazz)*6 ) ) \+ return error; \+ clazz[0].serv_id = serv_id_1; \+ clazz[0].serv_data = serv_data_1; \+ clazz[1].serv_id = serv_id_2; \+ clazz[1].serv_data = serv_data_2; \+ clazz[2].serv_id = serv_id_3; \+ clazz[2].serv_data = serv_data_3; \+ clazz[3].serv_id = serv_id_4; \+ clazz[3].serv_data = serv_data_4; \+ clazz[4].serv_id = serv_id_5; \+ clazz[4].serv_data = serv_data_5; \+ clazz[5].serv_id = NULL; \+ clazz[5].serv_data = NULL; \+ *output_class = clazz; \+ return FT_Err_Ok; \+ } ++#define FT_DEFINE_SERVICEDESCREC6(class_, serv_id_1, serv_data_1, \+ serv_id_2, serv_data_2, serv_id_3, serv_data_3, \+ serv_id_4, serv_data_4, serv_id_5, serv_data_5, \+ serv_id_6, serv_data_6) \+ void \+ FT_Destroy_Class_##class_( FT_Library library, \+ FT_ServiceDescRec* clazz ) \+ { \+ FT_Memory memory = library->memory; \+ if ( clazz ) \+ FT_FREE( clazz ); \+ } \+ \+ FT_Error \+ FT_Create_Class_##class_( FT_Library library, \+ FT_ServiceDescRec** output_class) \+ { \+ FT_ServiceDescRec* clazz; \+ FT_Error error; \+ FT_Memory memory = library->memory; \+ \+ if ( FT_ALLOC( clazz, sizeof(*clazz)*7 ) ) \+ return error; \+ clazz[0].serv_id = serv_id_1; \+ clazz[0].serv_data = serv_data_1; \+ clazz[1].serv_id = serv_id_2; \+ clazz[1].serv_data = serv_data_2; \+ clazz[2].serv_id = serv_id_3; \+ clazz[2].serv_data = serv_data_3; \+ clazz[3].serv_id = serv_id_4; \+ clazz[3].serv_data = serv_data_4; \+ clazz[4].serv_id = serv_id_5; \+ clazz[4].serv_data = serv_data_5; \+ clazz[5].serv_id = serv_id_6; \+ clazz[5].serv_data = serv_data_6; \+ clazz[6].serv_id = NULL; \+ clazz[6].serv_data = NULL; \+ *output_class = clazz; \+ return FT_Err_Ok; \+ } +#endif /* FT_CONFIG_OPTION_PIC */ ++ /*+ * Parse a list of FT_ServiceDescRec descriptors and look for+ * a specific service by ID. Note that the last element in the+ * array must be { NULL, NULL }, and that the function should+ * return NULL if the service isn't available.+ *+ * This function can be used by modules to implement their+ * `get_service' method.+ */+ FT_BASE( FT_Pointer )+ ft_service_list_lookup( FT_ServiceDesc service_descriptors,+ const char* service_id );+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** S E R V I C E S C A C H E *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /*+ * This structure is used to store a cache for several frequently used+ * services. It is the type of `face->internal->services'. You+ * should only use FT_FACE_LOOKUP_SERVICE to access it.+ *+ * All fields should have the type FT_Pointer to relax compilation+ * dependencies. We assume the developer isn't completely stupid.+ *+ * Each field must be named `service_XXXX' where `XXX' corresponds to+ * the correct FT_SERVICE_ID_XXXX macro. See the definition of+ * FT_FACE_LOOKUP_SERVICE below how this is implemented.+ *+ */+ typedef struct FT_ServiceCacheRec_+ {+ FT_Pointer service_POSTSCRIPT_FONT_NAME;+ FT_Pointer service_MULTI_MASTERS;+ FT_Pointer service_GLYPH_DICT;+ FT_Pointer service_PFR_METRICS;+ FT_Pointer service_WINFNT;++ } FT_ServiceCacheRec, *FT_ServiceCache;+++ /*+ * A magic number used within the services cache.+ */+#define FT_SERVICE_UNAVAILABLE ((FT_Pointer)-2) /* magic number */+++ /*+ * @macro:+ * FT_FACE_LOOKUP_SERVICE+ *+ * @description:+ * This macro is used to lookup a service from a face's driver module+ * using its cache.+ *+ * @input:+ * face::+ * The source face handle containing the cache.+ *+ * field ::+ * The field name in the cache.+ *+ * id ::+ * The service ID.+ *+ * @output:+ * ptr ::+ * A variable receiving the service data. NULL if not available.+ */+#ifdef __cplusplus++#define FT_FACE_LOOKUP_SERVICE( face, ptr, id ) \+ FT_BEGIN_STMNT \+ FT_Pointer svc; \+ FT_Pointer* Pptr = (FT_Pointer*)&(ptr); \+ \+ \+ svc = FT_FACE( face )->internal->services. service_ ## id; \+ if ( svc == FT_SERVICE_UNAVAILABLE ) \+ svc = NULL; \+ else if ( svc == NULL ) \+ { \+ FT_FACE_FIND_SERVICE( face, svc, id ); \+ \+ FT_FACE( face )->internal->services. service_ ## id = \+ (FT_Pointer)( svc != NULL ? svc \+ : FT_SERVICE_UNAVAILABLE ); \+ } \+ *Pptr = svc; \+ FT_END_STMNT++#else /* !C++ */++#define FT_FACE_LOOKUP_SERVICE( face, ptr, id ) \+ FT_BEGIN_STMNT \+ FT_Pointer svc; \+ \+ \+ svc = FT_FACE( face )->internal->services. service_ ## id; \+ if ( svc == FT_SERVICE_UNAVAILABLE ) \+ svc = NULL; \+ else if ( svc == NULL ) \+ { \+ FT_FACE_FIND_SERVICE( face, svc, id ); \+ \+ FT_FACE( face )->internal->services. service_ ## id = \+ (FT_Pointer)( svc != NULL ? svc \+ : FT_SERVICE_UNAVAILABLE ); \+ } \+ ptr = svc; \+ FT_END_STMNT++#endif /* !C++ */++ /*+ * A macro used to define new service structure types.+ */++#define FT_DEFINE_SERVICE( name ) \+ typedef struct FT_Service_ ## name ## Rec_ \+ FT_Service_ ## name ## Rec ; \+ typedef struct FT_Service_ ## name ## Rec_ \+ const * FT_Service_ ## name ; \+ struct FT_Service_ ## name ## Rec_++ /* */++ /*+ * The header files containing the services.+ */++#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_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_XFREE86_NAME_H <freetype/internal/services/svxf86nm.h>+#define FT_SERVICE_TRUETYPE_GLYF_H <freetype/internal/services/svttglyf.h>++ /* */++FT_END_HEADER++#endif /* __FTSERV_H__ */+++/* END */
+ include/freetype/internal/ftstream.h view
@@ -0,0 +1,539 @@+/***************************************************************************/+/* */+/* ftstream.h */+/* */+/* Stream handling (specification). */+/* */+/* Copyright 1996-2001, 2002, 2004, 2005, 2006 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 __FTSTREAM_H__+#define __FTSTREAM_H__+++#include <ft2build.h>+#include FT_SYSTEM_H+#include FT_INTERNAL_OBJECTS_H+++FT_BEGIN_HEADER+++ /* format of an 8-bit frame_op value: */+ /* */+ /* bit 76543210 */+ /* xxxxxxes */+ /* */+ /* s is set to 1 if the value is signed. */+ /* e is set to 1 if the value is little-endian. */+ /* xxx is a command. */++#define FT_FRAME_OP_SHIFT 2+#define FT_FRAME_OP_SIGNED 1+#define FT_FRAME_OP_LITTLE 2+#define FT_FRAME_OP_COMMAND( x ) ( x >> FT_FRAME_OP_SHIFT )++#define FT_MAKE_FRAME_OP( command, little, sign ) \+ ( ( command << FT_FRAME_OP_SHIFT ) | ( little << 1 ) | sign )++#define FT_FRAME_OP_END 0+#define FT_FRAME_OP_START 1 /* start a new frame */+#define FT_FRAME_OP_BYTE 2 /* read 1-byte value */+#define FT_FRAME_OP_SHORT 3 /* read 2-byte value */+#define FT_FRAME_OP_LONG 4 /* read 4-byte value */+#define FT_FRAME_OP_OFF3 5 /* read 3-byte value */+#define FT_FRAME_OP_BYTES 6 /* read a bytes sequence */+++ typedef enum FT_Frame_Op_+ {+ ft_frame_end = 0,+ ft_frame_start = FT_MAKE_FRAME_OP( FT_FRAME_OP_START, 0, 0 ),++ ft_frame_byte = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTE, 0, 0 ),+ ft_frame_schar = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTE, 0, 1 ),++ ft_frame_ushort_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 0, 0 ),+ ft_frame_short_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 0, 1 ),+ ft_frame_ushort_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 1, 0 ),+ ft_frame_short_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 1, 1 ),++ ft_frame_ulong_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 0, 0 ),+ ft_frame_long_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 0, 1 ),+ ft_frame_ulong_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 1, 0 ),+ ft_frame_long_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 1, 1 ),++ ft_frame_uoff3_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 0, 0 ),+ ft_frame_off3_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 0, 1 ),+ ft_frame_uoff3_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 1, 0 ),+ ft_frame_off3_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 1, 1 ),++ ft_frame_bytes = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTES, 0, 0 ),+ ft_frame_skip = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTES, 0, 1 )++ } FT_Frame_Op;+++ typedef struct FT_Frame_Field_+ {+ FT_Byte value;+ FT_Byte size;+ FT_UShort offset;++ } FT_Frame_Field;+++ /* Construct an FT_Frame_Field out of a structure type and a field name. */+ /* The structure type must be set in the FT_STRUCTURE macro before */+ /* calling the FT_FRAME_START() macro. */+ /* */+#define FT_FIELD_SIZE( f ) \+ (FT_Byte)sizeof ( ((FT_STRUCTURE*)0)->f )++#define FT_FIELD_SIZE_DELTA( f ) \+ (FT_Byte)sizeof ( ((FT_STRUCTURE*)0)->f[0] )++#define FT_FIELD_OFFSET( f ) \+ (FT_UShort)( offsetof( FT_STRUCTURE, f ) )++#define FT_FRAME_FIELD( frame_op, field ) \+ { \+ frame_op, \+ FT_FIELD_SIZE( field ), \+ FT_FIELD_OFFSET( field ) \+ }++#define FT_MAKE_EMPTY_FIELD( frame_op ) { frame_op, 0, 0 }++#define FT_FRAME_START( size ) { ft_frame_start, 0, size }+#define FT_FRAME_END { ft_frame_end, 0, 0 }++#define FT_FRAME_LONG( f ) FT_FRAME_FIELD( ft_frame_long_be, f )+#define FT_FRAME_ULONG( f ) FT_FRAME_FIELD( ft_frame_ulong_be, f )+#define FT_FRAME_SHORT( f ) FT_FRAME_FIELD( ft_frame_short_be, f )+#define FT_FRAME_USHORT( f ) FT_FRAME_FIELD( ft_frame_ushort_be, f )+#define FT_FRAME_OFF3( f ) FT_FRAME_FIELD( ft_frame_off3_be, f )+#define FT_FRAME_UOFF3( f ) FT_FRAME_FIELD( ft_frame_uoff3_be, f )+#define FT_FRAME_BYTE( f ) FT_FRAME_FIELD( ft_frame_byte, f )+#define FT_FRAME_CHAR( f ) FT_FRAME_FIELD( ft_frame_schar, f )++#define FT_FRAME_LONG_LE( f ) FT_FRAME_FIELD( ft_frame_long_le, f )+#define FT_FRAME_ULONG_LE( f ) FT_FRAME_FIELD( ft_frame_ulong_le, f )+#define FT_FRAME_SHORT_LE( f ) FT_FRAME_FIELD( ft_frame_short_le, f )+#define FT_FRAME_USHORT_LE( f ) FT_FRAME_FIELD( ft_frame_ushort_le, f )+#define FT_FRAME_OFF3_LE( f ) FT_FRAME_FIELD( ft_frame_off3_le, f )+#define FT_FRAME_UOFF3_LE( f ) FT_FRAME_FIELD( ft_frame_uoff3_le, f )++#define FT_FRAME_SKIP_LONG { ft_frame_long_be, 0, 0 }+#define FT_FRAME_SKIP_SHORT { ft_frame_short_be, 0, 0 }+#define FT_FRAME_SKIP_BYTE { ft_frame_byte, 0, 0 }++#define FT_FRAME_BYTES( field, count ) \+ { \+ ft_frame_bytes, \+ count, \+ FT_FIELD_OFFSET( field ) \+ }++#define FT_FRAME_SKIP_BYTES( count ) { ft_frame_skip, count, 0 }+++ /*************************************************************************/+ /* */+ /* Integer extraction macros -- the `buffer' parameter must ALWAYS be of */+ /* type `char*' or equivalent (1-byte elements). */+ /* */++#define FT_BYTE_( p, i ) ( ((const FT_Byte*)(p))[(i)] )+#define FT_INT8_( p, i ) ( ((const FT_Char*)(p))[(i)] )++#define FT_INT16( x ) ( (FT_Int16)(x) )+#define FT_UINT16( x ) ( (FT_UInt16)(x) )+#define FT_INT32( x ) ( (FT_Int32)(x) )+#define FT_UINT32( x ) ( (FT_UInt32)(x) )++#define FT_BYTE_I16( p, i, s ) ( FT_INT16( FT_BYTE_( p, i ) ) << (s) )+#define FT_BYTE_U16( p, i, s ) ( FT_UINT16( FT_BYTE_( p, i ) ) << (s) )+#define FT_BYTE_I32( p, i, s ) ( FT_INT32( FT_BYTE_( p, i ) ) << (s) )+#define FT_BYTE_U32( p, i, s ) ( FT_UINT32( FT_BYTE_( p, i ) ) << (s) )++#define FT_INT8_I16( p, i, s ) ( FT_INT16( FT_INT8_( p, i ) ) << (s) )+#define FT_INT8_U16( p, i, s ) ( FT_UINT16( FT_INT8_( p, i ) ) << (s) )+#define FT_INT8_I32( p, i, s ) ( FT_INT32( FT_INT8_( p, i ) ) << (s) )+#define FT_INT8_U32( p, i, s ) ( FT_UINT32( FT_INT8_( p, i ) ) << (s) )+++#define FT_PEEK_SHORT( p ) FT_INT16( FT_INT8_I16( p, 0, 8) | \+ FT_BYTE_I16( p, 1, 0) )++#define FT_PEEK_USHORT( p ) FT_UINT16( FT_BYTE_U16( p, 0, 8 ) | \+ FT_BYTE_U16( p, 1, 0 ) )++#define FT_PEEK_LONG( p ) FT_INT32( FT_INT8_I32( p, 0, 24 ) | \+ FT_BYTE_I32( p, 1, 16 ) | \+ FT_BYTE_I32( p, 2, 8 ) | \+ FT_BYTE_I32( p, 3, 0 ) )++#define FT_PEEK_ULONG( p ) FT_UINT32( FT_BYTE_U32( p, 0, 24 ) | \+ FT_BYTE_U32( p, 1, 16 ) | \+ FT_BYTE_U32( p, 2, 8 ) | \+ FT_BYTE_U32( p, 3, 0 ) )++#define FT_PEEK_OFF3( p ) FT_INT32( FT_INT8_I32( p, 0, 16 ) | \+ FT_BYTE_I32( p, 1, 8 ) | \+ FT_BYTE_I32( p, 2, 0 ) )++#define FT_PEEK_UOFF3( p ) FT_UINT32( FT_BYTE_U32( p, 0, 16 ) | \+ FT_BYTE_U32( p, 1, 8 ) | \+ FT_BYTE_U32( p, 2, 0 ) )++#define FT_PEEK_SHORT_LE( p ) FT_INT16( FT_INT8_I16( p, 1, 8 ) | \+ FT_BYTE_I16( p, 0, 0 ) )++#define FT_PEEK_USHORT_LE( p ) FT_UINT16( FT_BYTE_U16( p, 1, 8 ) | \+ FT_BYTE_U16( p, 0, 0 ) )++#define FT_PEEK_LONG_LE( p ) FT_INT32( FT_INT8_I32( p, 3, 24 ) | \+ FT_BYTE_I32( p, 2, 16 ) | \+ FT_BYTE_I32( p, 1, 8 ) | \+ FT_BYTE_I32( p, 0, 0 ) )++#define FT_PEEK_ULONG_LE( p ) FT_UINT32( FT_BYTE_U32( p, 3, 24 ) | \+ FT_BYTE_U32( p, 2, 16 ) | \+ FT_BYTE_U32( p, 1, 8 ) | \+ FT_BYTE_U32( p, 0, 0 ) )++#define FT_PEEK_OFF3_LE( p ) FT_INT32( FT_INT8_I32( p, 2, 16 ) | \+ FT_BYTE_I32( p, 1, 8 ) | \+ FT_BYTE_I32( p, 0, 0 ) )++#define FT_PEEK_UOFF3_LE( p ) FT_UINT32( FT_BYTE_U32( p, 2, 16 ) | \+ FT_BYTE_U32( p, 1, 8 ) | \+ FT_BYTE_U32( p, 0, 0 ) )+++#define FT_NEXT_CHAR( buffer ) \+ ( (signed char)*buffer++ )++#define FT_NEXT_BYTE( buffer ) \+ ( (unsigned char)*buffer++ )++#define FT_NEXT_SHORT( buffer ) \+ ( (short)( buffer += 2, FT_PEEK_SHORT( buffer - 2 ) ) )++#define FT_NEXT_USHORT( buffer ) \+ ( (unsigned short)( buffer += 2, FT_PEEK_USHORT( buffer - 2 ) ) )++#define FT_NEXT_OFF3( buffer ) \+ ( (long)( buffer += 3, FT_PEEK_OFF3( buffer - 3 ) ) )++#define FT_NEXT_UOFF3( buffer ) \+ ( (unsigned long)( buffer += 3, FT_PEEK_UOFF3( buffer - 3 ) ) )++#define FT_NEXT_LONG( buffer ) \+ ( (long)( buffer += 4, FT_PEEK_LONG( buffer - 4 ) ) )++#define FT_NEXT_ULONG( buffer ) \+ ( (unsigned long)( buffer += 4, FT_PEEK_ULONG( buffer - 4 ) ) )+++#define FT_NEXT_SHORT_LE( buffer ) \+ ( (short)( buffer += 2, FT_PEEK_SHORT_LE( buffer - 2 ) ) )++#define FT_NEXT_USHORT_LE( buffer ) \+ ( (unsigned short)( buffer += 2, FT_PEEK_USHORT_LE( buffer - 2 ) ) )++#define FT_NEXT_OFF3_LE( buffer ) \+ ( (long)( buffer += 3, FT_PEEK_OFF3_LE( buffer - 3 ) ) )++#define FT_NEXT_UOFF3_LE( buffer ) \+ ( (unsigned long)( buffer += 3, FT_PEEK_UOFF3_LE( buffer - 3 ) ) )++#define FT_NEXT_LONG_LE( buffer ) \+ ( (long)( buffer += 4, FT_PEEK_LONG_LE( buffer - 4 ) ) )++#define FT_NEXT_ULONG_LE( buffer ) \+ ( (unsigned long)( buffer += 4, FT_PEEK_ULONG_LE( buffer - 4 ) ) )+++ /*************************************************************************/+ /* */+ /* Each GET_xxxx() macro uses an implicit `stream' variable. */+ /* */+#if 0+#define FT_GET_MACRO( type ) FT_NEXT_ ## type ( stream->cursor )++#define FT_GET_CHAR() FT_GET_MACRO( CHAR )+#define FT_GET_BYTE() FT_GET_MACRO( BYTE )+#define FT_GET_SHORT() FT_GET_MACRO( SHORT )+#define FT_GET_USHORT() FT_GET_MACRO( USHORT )+#define FT_GET_OFF3() FT_GET_MACRO( OFF3 )+#define FT_GET_UOFF3() FT_GET_MACRO( UOFF3 )+#define FT_GET_LONG() FT_GET_MACRO( LONG )+#define FT_GET_ULONG() FT_GET_MACRO( ULONG )+#define FT_GET_TAG4() FT_GET_MACRO( ULONG )++#define FT_GET_SHORT_LE() FT_GET_MACRO( SHORT_LE )+#define FT_GET_USHORT_LE() FT_GET_MACRO( USHORT_LE )+#define FT_GET_LONG_LE() FT_GET_MACRO( LONG_LE )+#define FT_GET_ULONG_LE() FT_GET_MACRO( ULONG_LE )++#else+#define FT_GET_MACRO( func, type ) ( (type)func( stream ) )++#define FT_GET_CHAR() FT_GET_MACRO( FT_Stream_GetChar, FT_Char )+#define FT_GET_BYTE() FT_GET_MACRO( FT_Stream_GetChar, FT_Byte )+#define FT_GET_SHORT() FT_GET_MACRO( FT_Stream_GetShort, FT_Short )+#define FT_GET_USHORT() FT_GET_MACRO( FT_Stream_GetShort, FT_UShort )+#define FT_GET_OFF3() FT_GET_MACRO( FT_Stream_GetOffset, FT_Long )+#define FT_GET_UOFF3() FT_GET_MACRO( FT_Stream_GetOffset, FT_ULong )+#define FT_GET_LONG() FT_GET_MACRO( FT_Stream_GetLong, FT_Long )+#define FT_GET_ULONG() FT_GET_MACRO( FT_Stream_GetLong, FT_ULong )+#define FT_GET_TAG4() FT_GET_MACRO( FT_Stream_GetLong, FT_ULong )++#define FT_GET_SHORT_LE() FT_GET_MACRO( FT_Stream_GetShortLE, FT_Short )+#define FT_GET_USHORT_LE() FT_GET_MACRO( FT_Stream_GetShortLE, FT_UShort )+#define FT_GET_LONG_LE() FT_GET_MACRO( FT_Stream_GetLongLE, FT_Long )+#define FT_GET_ULONG_LE() FT_GET_MACRO( FT_Stream_GetLongLE, FT_ULong )+#endif++#define FT_READ_MACRO( func, type, var ) \+ ( var = (type)func( stream, &error ), \+ error != FT_Err_Ok )++#define FT_READ_BYTE( var ) FT_READ_MACRO( FT_Stream_ReadChar, FT_Byte, var )+#define FT_READ_CHAR( var ) FT_READ_MACRO( FT_Stream_ReadChar, FT_Char, var )+#define FT_READ_SHORT( var ) FT_READ_MACRO( FT_Stream_ReadShort, FT_Short, var )+#define FT_READ_USHORT( var ) FT_READ_MACRO( FT_Stream_ReadShort, FT_UShort, var )+#define FT_READ_OFF3( var ) FT_READ_MACRO( FT_Stream_ReadOffset, FT_Long, var )+#define FT_READ_UOFF3( var ) FT_READ_MACRO( FT_Stream_ReadOffset, FT_ULong, var )+#define FT_READ_LONG( var ) FT_READ_MACRO( FT_Stream_ReadLong, FT_Long, var )+#define FT_READ_ULONG( var ) FT_READ_MACRO( FT_Stream_ReadLong, FT_ULong, var )++#define FT_READ_SHORT_LE( var ) FT_READ_MACRO( FT_Stream_ReadShortLE, FT_Short, var )+#define FT_READ_USHORT_LE( var ) FT_READ_MACRO( FT_Stream_ReadShortLE, FT_UShort, var )+#define FT_READ_LONG_LE( var ) FT_READ_MACRO( FT_Stream_ReadLongLE, FT_Long, var )+#define FT_READ_ULONG_LE( var ) FT_READ_MACRO( FT_Stream_ReadLongLE, FT_ULong, var )+++#ifndef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM++ /* initialize a stream for reading a regular system stream */+ FT_BASE( FT_Error )+ FT_Stream_Open( FT_Stream stream,+ const char* filepathname );++#endif /* FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM */+++ /* create a new (input) stream from an FT_Open_Args structure */+ FT_BASE( FT_Error )+ FT_Stream_New( FT_Library library,+ const FT_Open_Args* args,+ FT_Stream *astream );++ /* free a stream */+ FT_BASE( void )+ FT_Stream_Free( FT_Stream stream,+ FT_Int external );++ /* initialize a stream for reading in-memory data */+ FT_BASE( void )+ FT_Stream_OpenMemory( FT_Stream stream,+ const FT_Byte* base,+ FT_ULong size );++ /* close a stream (does not destroy the stream structure) */+ FT_BASE( void )+ FT_Stream_Close( FT_Stream stream );+++ /* seek within a stream. position is relative to start of stream */+ FT_BASE( FT_Error )+ FT_Stream_Seek( FT_Stream stream,+ FT_ULong pos );++ /* skip bytes in a stream */+ FT_BASE( FT_Error )+ FT_Stream_Skip( FT_Stream stream,+ FT_Long distance );++ /* return current stream position */+ FT_BASE( FT_Long )+ FT_Stream_Pos( FT_Stream stream );++ /* read bytes from a stream into a user-allocated buffer, returns an */+ /* error if not all bytes could be read. */+ FT_BASE( FT_Error )+ FT_Stream_Read( FT_Stream stream,+ FT_Byte* buffer,+ FT_ULong count );++ /* read bytes from a stream at a given position */+ FT_BASE( FT_Error )+ FT_Stream_ReadAt( FT_Stream stream,+ FT_ULong pos,+ FT_Byte* buffer,+ FT_ULong count );++ /* try to read bytes at the end of a stream; return number of bytes */+ /* really available */+ FT_BASE( FT_ULong )+ FT_Stream_TryRead( FT_Stream stream,+ FT_Byte* buffer,+ FT_ULong count );++ /* Enter a frame of `count' consecutive bytes in a stream. Returns an */+ /* error if the frame could not be read/accessed. The caller can use */+ /* the FT_Stream_Get_XXX functions to retrieve frame data without */+ /* error checks. */+ /* */+ /* You must _always_ call FT_Stream_ExitFrame() once you have entered */+ /* a stream frame! */+ /* */+ FT_BASE( FT_Error )+ FT_Stream_EnterFrame( FT_Stream stream,+ FT_ULong count );++ /* exit a stream frame */+ FT_BASE( void )+ FT_Stream_ExitFrame( FT_Stream stream );++ /* Extract a stream frame. If the stream is disk-based, a heap block */+ /* is allocated and the frame bytes are read into it. If the stream */+ /* is memory-based, this function simply set a pointer to the data. */+ /* */+ /* Useful to optimize access to memory-based streams transparently. */+ /* */+ /* All extracted frames must be `freed' with a call to the function */+ /* FT_Stream_ReleaseFrame(). */+ /* */+ FT_BASE( FT_Error )+ FT_Stream_ExtractFrame( FT_Stream stream,+ FT_ULong count,+ FT_Byte** pbytes );++ /* release an extract frame (see FT_Stream_ExtractFrame) */+ FT_BASE( void )+ FT_Stream_ReleaseFrame( FT_Stream stream,+ FT_Byte** pbytes );++ /* read a byte from an entered frame */+ FT_BASE( FT_Char )+ FT_Stream_GetChar( FT_Stream stream );++ /* read a 16-bit big-endian integer from an entered frame */+ FT_BASE( FT_Short )+ FT_Stream_GetShort( FT_Stream stream );++ /* read a 24-bit big-endian integer from an entered frame */+ FT_BASE( FT_Long )+ FT_Stream_GetOffset( FT_Stream stream );++ /* read a 32-bit big-endian integer from an entered frame */+ FT_BASE( FT_Long )+ FT_Stream_GetLong( FT_Stream stream );++ /* read a 16-bit little-endian integer from an entered frame */+ FT_BASE( FT_Short )+ FT_Stream_GetShortLE( FT_Stream stream );++ /* read a 32-bit little-endian integer from an entered frame */+ FT_BASE( FT_Long )+ FT_Stream_GetLongLE( FT_Stream stream );+++ /* read a byte from a stream */+ FT_BASE( FT_Char )+ FT_Stream_ReadChar( FT_Stream stream,+ FT_Error* error );++ /* read a 16-bit big-endian integer from a stream */+ FT_BASE( FT_Short )+ FT_Stream_ReadShort( FT_Stream stream,+ FT_Error* error );++ /* read a 24-bit big-endian integer from a stream */+ FT_BASE( FT_Long )+ FT_Stream_ReadOffset( FT_Stream stream,+ FT_Error* error );++ /* read a 32-bit big-endian integer from a stream */+ FT_BASE( FT_Long )+ FT_Stream_ReadLong( FT_Stream stream,+ FT_Error* error );++ /* read a 16-bit little-endian integer from a stream */+ FT_BASE( FT_Short )+ FT_Stream_ReadShortLE( FT_Stream stream,+ FT_Error* error );++ /* read a 32-bit little-endian integer from a stream */+ FT_BASE( FT_Long )+ FT_Stream_ReadLongLE( FT_Stream stream,+ FT_Error* error );++ /* Read a structure from a stream. The structure must be described */+ /* by an array of FT_Frame_Field records. */+ FT_BASE( FT_Error )+ FT_Stream_ReadFields( FT_Stream stream,+ const FT_Frame_Field* fields,+ void* structure );+++#define FT_STREAM_POS() \+ FT_Stream_Pos( stream )++#define FT_STREAM_SEEK( position ) \+ FT_SET_ERROR( FT_Stream_Seek( stream, position ) )++#define FT_STREAM_SKIP( distance ) \+ FT_SET_ERROR( FT_Stream_Skip( stream, distance ) )++#define FT_STREAM_READ( buffer, count ) \+ FT_SET_ERROR( FT_Stream_Read( stream, \+ (FT_Byte*)buffer, \+ count ) )++#define FT_STREAM_READ_AT( position, buffer, count ) \+ FT_SET_ERROR( FT_Stream_ReadAt( stream, \+ position, \+ (FT_Byte*)buffer, \+ count ) )++#define FT_STREAM_READ_FIELDS( fields, object ) \+ FT_SET_ERROR( FT_Stream_ReadFields( stream, fields, object ) )+++#define FT_FRAME_ENTER( size ) \+ FT_SET_ERROR( \+ FT_DEBUG_INNER( FT_Stream_EnterFrame( stream, size ) ) )++#define FT_FRAME_EXIT() \+ FT_DEBUG_INNER( FT_Stream_ExitFrame( stream ) )++#define FT_FRAME_EXTRACT( size, bytes ) \+ FT_SET_ERROR( \+ FT_DEBUG_INNER( FT_Stream_ExtractFrame( stream, size, \+ (FT_Byte**)&(bytes) ) ) )++#define FT_FRAME_RELEASE( bytes ) \+ FT_DEBUG_INNER( FT_Stream_ReleaseFrame( stream, \+ (FT_Byte**)&(bytes) ) )+++FT_END_HEADER++#endif /* __FTSTREAM_H__ */+++/* END */
+ include/freetype/internal/fttrace.h view
@@ -0,0 +1,139 @@+/***************************************************************************/+/* */+/* fttrace.h */+/* */+/* Tracing handling (specification only). */+/* */+/* Copyright 2002, 2004, 2005, 2006, 2007 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. */+/* */+/***************************************************************************/+++ /* definitions of trace levels for FreeType 2 */++ /* the first level must always be `trace_any' */+FT_TRACE_DEF( any )++ /* base components */+FT_TRACE_DEF( calc ) /* calculations (ftcalc.c) */+FT_TRACE_DEF( memory ) /* memory manager (ftobjs.c) */+FT_TRACE_DEF( stream ) /* stream manager (ftstream.c) */+FT_TRACE_DEF( io ) /* i/o interface (ftsystem.c) */+FT_TRACE_DEF( list ) /* list management (ftlist.c) */+FT_TRACE_DEF( init ) /* initialization (ftinit.c) */+FT_TRACE_DEF( objs ) /* base objects (ftobjs.c) */+FT_TRACE_DEF( outline ) /* outline management (ftoutln.c) */+FT_TRACE_DEF( glyph ) /* glyph management (ftglyph.c) */+FT_TRACE_DEF( gloader ) /* glyph loader (ftgloadr.c) */++FT_TRACE_DEF( raster ) /* monochrome rasterizer (ftraster.c) */+FT_TRACE_DEF( smooth ) /* anti-aliasing raster (ftgrays.c) */+FT_TRACE_DEF( mm ) /* MM interface (ftmm.c) */+FT_TRACE_DEF( raccess ) /* resource fork accessor (ftrfork.c) */+FT_TRACE_DEF( synth ) /* bold/slant synthesizer (ftsynth.c) */++ /* Cache sub-system */+FT_TRACE_DEF( cache ) /* cache sub-system (ftcache.c, etc.) */++ /* SFNT driver components */+FT_TRACE_DEF( sfdriver ) /* SFNT font driver (sfdriver.c) */+FT_TRACE_DEF( sfobjs ) /* SFNT object handler (sfobjs.c) */+FT_TRACE_DEF( ttcmap ) /* charmap handler (ttcmap.c) */+FT_TRACE_DEF( ttkern ) /* kerning handler (ttkern.c) */+FT_TRACE_DEF( ttload ) /* basic TrueType tables (ttload.c) */+FT_TRACE_DEF( ttmtx ) /* metrics-related tables (ttmtx.c) */+FT_TRACE_DEF( ttpost ) /* PS table processing (ttpost.c) */+FT_TRACE_DEF( ttsbit ) /* TrueType sbit handling (ttsbit.c) */+FT_TRACE_DEF( ttbdf ) /* TrueType embedded BDF (ttbdf.c) */++ /* TrueType driver components */+FT_TRACE_DEF( ttdriver ) /* TT font driver (ttdriver.c) */+FT_TRACE_DEF( ttgload ) /* TT glyph loader (ttgload.c) */+FT_TRACE_DEF( ttinterp ) /* bytecode interpreter (ttinterp.c) */+FT_TRACE_DEF( ttobjs ) /* TT objects manager (ttobjs.c) */+FT_TRACE_DEF( ttpload ) /* TT data/program loader (ttpload.c) */+FT_TRACE_DEF( ttgxvar ) /* TrueType GX var handler (ttgxvar.c) */++ /* Type 1 driver components */+FT_TRACE_DEF( t1afm )+FT_TRACE_DEF( t1driver )+FT_TRACE_DEF( t1gload )+FT_TRACE_DEF( t1hint )+FT_TRACE_DEF( t1load )+FT_TRACE_DEF( t1objs )+FT_TRACE_DEF( t1parse )++ /* PostScript helper module `psaux' */+FT_TRACE_DEF( t1decode )+FT_TRACE_DEF( psobjs )++ /* PostScript hinting module `pshinter' */+FT_TRACE_DEF( pshrec )+FT_TRACE_DEF( pshalgo1 )+FT_TRACE_DEF( pshalgo2 )++ /* Type 2 driver components */+FT_TRACE_DEF( cffdriver )+FT_TRACE_DEF( cffgload )+FT_TRACE_DEF( cffload )+FT_TRACE_DEF( cffobjs )+FT_TRACE_DEF( cffparse )++ /* Type 42 driver component */+FT_TRACE_DEF( t42 )++ /* CID driver components */+FT_TRACE_DEF( cidafm )+FT_TRACE_DEF( ciddriver )+FT_TRACE_DEF( cidgload )+FT_TRACE_DEF( cidload )+FT_TRACE_DEF( cidobjs )+FT_TRACE_DEF( cidparse )++ /* Windows font component */+FT_TRACE_DEF( winfnt )++ /* PCF font components */+FT_TRACE_DEF( pcfdriver )+FT_TRACE_DEF( pcfread )++ /* BDF font components */+FT_TRACE_DEF( bdfdriver )+FT_TRACE_DEF( bdflib )++ /* PFR font component */+FT_TRACE_DEF( pfr )++ /* OpenType validation components */+FT_TRACE_DEF( otvmodule )+FT_TRACE_DEF( otvcommon )+FT_TRACE_DEF( otvbase )+FT_TRACE_DEF( otvgdef )+FT_TRACE_DEF( otvgpos )+FT_TRACE_DEF( otvgsub )+FT_TRACE_DEF( otvjstf )+FT_TRACE_DEF( otvmath )++ /* TrueTypeGX/AAT validation components */+FT_TRACE_DEF( gxvmodule )+FT_TRACE_DEF( gxvcommon )+FT_TRACE_DEF( gxvfeat )+FT_TRACE_DEF( gxvmort )+FT_TRACE_DEF( gxvmorx )+FT_TRACE_DEF( gxvbsln )+FT_TRACE_DEF( gxvjust )+FT_TRACE_DEF( gxvkern )+FT_TRACE_DEF( gxvopbd )+FT_TRACE_DEF( gxvtrak )+FT_TRACE_DEF( gxvprop )+FT_TRACE_DEF( gxvlcar )+++/* END */
+ include/freetype/internal/ftvalid.h view
@@ -0,0 +1,150 @@+/***************************************************************************/+/* */+/* ftvalid.h */+/* */+/* FreeType validation support (specification). */+/* */+/* Copyright 2004 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 __FTVALID_H__+#define __FTVALID_H__++#include <ft2build.h>+#include FT_CONFIG_STANDARD_LIBRARY_H /* for ft_setjmp and ft_longjmp */+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** ****/+ /**** V A L I D A T I O N ****/+ /**** ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/++ /* handle to a validation object */+ typedef struct FT_ValidatorRec_ volatile* FT_Validator;+++ /*************************************************************************/+ /* */+ /* There are three distinct validation levels defined here: */+ /* */+ /* FT_VALIDATE_DEFAULT :: */+ /* A table that passes this validation level can be used reliably by */+ /* FreeType. It generally means that all offsets have been checked to */+ /* prevent out-of-bound reads, that array counts are correct, etc. */+ /* */+ /* FT_VALIDATE_TIGHT :: */+ /* A table that passes this validation level can be used reliably and */+ /* doesn't contain invalid data. For example, a charmap table that */+ /* returns invalid glyph indices will not pass, even though it can */+ /* be used with FreeType in default mode (the library will simply */+ /* return an error later when trying to load the glyph). */+ /* */+ /* It also checks that fields which must be a multiple of 2, 4, or 8, */+ /* don't have incorrect values, etc. */+ /* */+ /* FT_VALIDATE_PARANOID :: */+ /* Only for font debugging. Checks that a table follows the */+ /* specification by 100%. Very few fonts will be able to pass this */+ /* level anyway but it can be useful for certain tools like font */+ /* editors/converters. */+ /* */+ typedef enum FT_ValidationLevel_+ {+ FT_VALIDATE_DEFAULT = 0,+ FT_VALIDATE_TIGHT,+ FT_VALIDATE_PARANOID++ } FT_ValidationLevel;+++ /* validator structure */+ typedef struct FT_ValidatorRec_+ {+ const FT_Byte* base; /* address of table in memory */+ const FT_Byte* limit; /* `base' + sizeof(table) in memory */+ FT_ValidationLevel level; /* validation level */+ FT_Error error; /* error returned. 0 means success */++ ft_jmp_buf jump_buffer; /* used for exception handling */++ } FT_ValidatorRec;+++#define FT_VALIDATOR( x ) ((FT_Validator)( x ))+++ FT_BASE( void )+ ft_validator_init( FT_Validator valid,+ const FT_Byte* base,+ const FT_Byte* limit,+ FT_ValidationLevel level );++ /* Do not use this. It's broken and will cause your validator to crash */+ /* if you run it on an invalid font. */+ FT_BASE( FT_Int )+ ft_validator_run( FT_Validator valid );++ /* Sets the error field in a validator, then calls `longjmp' to return */+ /* to high-level caller. Using `setjmp/longjmp' avoids many stupid */+ /* error checks within the validation routines. */+ /* */+ FT_BASE( void )+ ft_validator_error( FT_Validator valid,+ FT_Error error );+++ /* Calls ft_validate_error. Assumes that the `valid' local variable */+ /* holds a pointer to the current validator object. */+ /* */+ /* Use preprocessor prescan to pass FT_ERR_PREFIX. */+ /* */+#define FT_INVALID( _prefix, _error ) FT_INVALID_( _prefix, _error )+#define FT_INVALID_( _prefix, _error ) \+ ft_validator_error( valid, _prefix ## _error )++ /* called when a broken table is detected */+#define FT_INVALID_TOO_SHORT \+ FT_INVALID( FT_ERR_PREFIX, Invalid_Table )++ /* called when an invalid offset is detected */+#define FT_INVALID_OFFSET \+ FT_INVALID( FT_ERR_PREFIX, Invalid_Offset )++ /* called when an invalid format/value is detected */+#define FT_INVALID_FORMAT \+ FT_INVALID( FT_ERR_PREFIX, Invalid_Table )++ /* called when an invalid glyph index is detected */+#define FT_INVALID_GLYPH_ID \+ FT_INVALID( FT_ERR_PREFIX, Invalid_Glyph_Index )++ /* called when an invalid field value is detected */+#define FT_INVALID_DATA \+ FT_INVALID( FT_ERR_PREFIX, Invalid_Table )+++FT_END_HEADER++#endif /* __FTVALID_H__ */+++/* END */
+ include/freetype/internal/internal.h view
@@ -0,0 +1,51 @@+/***************************************************************************/+/* */+/* internal.h */+/* */+/* Internal header files (specification only). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004 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 automatically included by `ft2build.h'. */+ /* Do not include it manually! */+ /* */+ /*************************************************************************/+++#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>+++/* END */
+ include/freetype/internal/pcftypes.h view
@@ -0,0 +1,56 @@+/* pcftypes.h++ FreeType font driver for pcf fonts++ Copyright (C) 2000, 2001, 2002 by+ Francesco Zappa Nardelli++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in+all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+THE SOFTWARE.+*/+++#ifndef __PCFTYPES_H__+#define __PCFTYPES_H__+++#include <ft2build.h>+#include FT_FREETYPE_H+++FT_BEGIN_HEADER+++ typedef struct PCF_Public_FaceRec_+ {+ FT_FaceRec root;+ FT_StreamRec gzip_stream;+ FT_Stream gzip_source;++ char* charset_encoding;+ char* charset_registry;++ } PCF_Public_FaceRec, *PCF_Public_Face;+++FT_END_HEADER++#endif /* __PCFTYPES_H__ */+++/* END */
+ include/freetype/internal/psaux.h view
@@ -0,0 +1,873 @@+/***************************************************************************/+/* */+/* psaux.h */+/* */+/* Auxiliary functions and data structures related to PostScript fonts */+/* (specification). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2008, 2009 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 __PSAUX_H__+#define __PSAUX_H__+++#include <ft2build.h>+#include FT_INTERNAL_OBJECTS_H+#include FT_INTERNAL_TYPE1_TYPES_H+#include FT_SERVICE_POSTSCRIPT_CMAPS_H+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** T1_TABLE *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+++ typedef struct PS_TableRec_* PS_Table;+ typedef const struct PS_Table_FuncsRec_* PS_Table_Funcs;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* PS_Table_FuncsRec */+ /* */+ /* <Description> */+ /* A set of function pointers to manage PS_Table objects. */+ /* */+ /* <Fields> */+ /* table_init :: Used to initialize a table. */+ /* */+ /* table_done :: Finalizes resp. destroy a given table. */+ /* */+ /* table_add :: Adds a new object to a table. */+ /* */+ /* table_release :: Releases table data, then finalizes it. */+ /* */+ typedef struct PS_Table_FuncsRec_+ {+ FT_Error+ (*init)( PS_Table table,+ FT_Int count,+ FT_Memory memory );++ void+ (*done)( PS_Table table );++ FT_Error+ (*add)( PS_Table table,+ FT_Int idx,+ void* object,+ FT_PtrDist length );++ void+ (*release)( PS_Table table );++ } PS_Table_FuncsRec;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* PS_TableRec */+ /* */+ /* <Description> */+ /* A PS_Table is a simple object used to store an array of objects in */+ /* a single memory block. */+ /* */+ /* <Fields> */+ /* block :: The address in memory of the growheap's block. This */+ /* can change between two object adds, due to */+ /* reallocation. */+ /* */+ /* cursor :: The current top of the grow heap within its block. */+ /* */+ /* capacity :: The current size of the heap block. Increments by */+ /* 1kByte chunks. */+ /* */+ /* max_elems :: The maximum number of elements in table. */+ /* */+ /* num_elems :: The current number of elements in table. */+ /* */+ /* elements :: A table of element addresses within the block. */+ /* */+ /* lengths :: A table of element sizes within the block. */+ /* */+ /* memory :: The object used for memory operations */+ /* (alloc/realloc). */+ /* */+ /* funcs :: A table of method pointers for this object. */+ /* */+ typedef struct PS_TableRec_+ {+ FT_Byte* block; /* current memory block */+ FT_Offset cursor; /* current cursor in memory block */+ FT_Offset capacity; /* current size of memory block */+ FT_Long init;++ FT_Int max_elems;+ FT_Int num_elems;+ FT_Byte** elements; /* addresses of table elements */+ FT_PtrDist* lengths; /* lengths of table elements */++ FT_Memory memory;+ PS_Table_FuncsRec funcs;++ } PS_TableRec;+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** T1 FIELDS & TOKENS *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ typedef struct PS_ParserRec_* PS_Parser;++ typedef struct T1_TokenRec_* T1_Token;++ typedef struct T1_FieldRec_* T1_Field;+++ /* simple enumeration type used to identify token types */+ typedef enum T1_TokenType_+ {+ T1_TOKEN_TYPE_NONE = 0,+ T1_TOKEN_TYPE_ANY,+ T1_TOKEN_TYPE_STRING,+ T1_TOKEN_TYPE_ARRAY,+ T1_TOKEN_TYPE_KEY, /* aka `name' */++ /* do not remove */+ T1_TOKEN_TYPE_MAX++ } T1_TokenType;+++ /* a simple structure used to identify tokens */+ typedef struct T1_TokenRec_+ {+ FT_Byte* start; /* first character of token in input stream */+ FT_Byte* limit; /* first character after the token */+ T1_TokenType type; /* type of token */++ } T1_TokenRec;+++ /* enumeration type used to identify object fields */+ typedef enum T1_FieldType_+ {+ T1_FIELD_TYPE_NONE = 0,+ T1_FIELD_TYPE_BOOL,+ T1_FIELD_TYPE_INTEGER,+ T1_FIELD_TYPE_FIXED,+ T1_FIELD_TYPE_FIXED_1000,+ T1_FIELD_TYPE_STRING,+ T1_FIELD_TYPE_KEY,+ T1_FIELD_TYPE_BBOX,+ T1_FIELD_TYPE_INTEGER_ARRAY,+ T1_FIELD_TYPE_FIXED_ARRAY,+ T1_FIELD_TYPE_CALLBACK,++ /* do not remove */+ T1_FIELD_TYPE_MAX++ } T1_FieldType;+++ typedef enum T1_FieldLocation_+ {+ T1_FIELD_LOCATION_CID_INFO,+ T1_FIELD_LOCATION_FONT_DICT,+ T1_FIELD_LOCATION_FONT_EXTRA,+ T1_FIELD_LOCATION_FONT_INFO,+ T1_FIELD_LOCATION_PRIVATE,+ T1_FIELD_LOCATION_BBOX,+ T1_FIELD_LOCATION_LOADER,+ T1_FIELD_LOCATION_FACE,+ T1_FIELD_LOCATION_BLEND,++ /* do not remove */+ T1_FIELD_LOCATION_MAX++ } T1_FieldLocation;+++ typedef void+ (*T1_Field_ParseFunc)( FT_Face face,+ FT_Pointer parser );+++ /* structure type used to model object fields */+ typedef struct T1_FieldRec_+ {+ const char* ident; /* field identifier */+ T1_FieldLocation location;+ T1_FieldType type; /* type of field */+ T1_Field_ParseFunc reader;+ FT_UInt offset; /* offset of field in object */+ FT_Byte size; /* size of field in bytes */+ FT_UInt array_max; /* maximal number of elements for */+ /* array */+ FT_UInt count_offset; /* offset of element count for */+ /* arrays; must not be zero if in */+ /* use -- in other words, a */+ /* `num_FOO' element must not */+ /* start the used structure if we */+ /* parse a `FOO' array */+ FT_UInt dict; /* where we expect it */+ } T1_FieldRec;++#define T1_FIELD_DICT_FONTDICT ( 1 << 0 ) /* also FontInfo and FDArray */+#define T1_FIELD_DICT_PRIVATE ( 1 << 1 )++++#define T1_NEW_SIMPLE_FIELD( _ident, _type, _fname, _dict ) \+ { \+ _ident, T1CODE, _type, \+ 0, \+ FT_FIELD_OFFSET( _fname ), \+ FT_FIELD_SIZE( _fname ), \+ 0, 0, \+ _dict \+ },++#define T1_NEW_CALLBACK_FIELD( _ident, _reader, _dict ) \+ { \+ _ident, T1CODE, T1_FIELD_TYPE_CALLBACK, \+ (T1_Field_ParseFunc)_reader, \+ 0, 0, \+ 0, 0, \+ _dict \+ },++#define T1_NEW_TABLE_FIELD( _ident, _type, _fname, _max, _dict ) \+ { \+ _ident, T1CODE, _type, \+ 0, \+ FT_FIELD_OFFSET( _fname ), \+ FT_FIELD_SIZE_DELTA( _fname ), \+ _max, \+ FT_FIELD_OFFSET( num_ ## _fname ), \+ _dict \+ },++#define T1_NEW_TABLE_FIELD2( _ident, _type, _fname, _max, _dict ) \+ { \+ _ident, T1CODE, _type, \+ 0, \+ FT_FIELD_OFFSET( _fname ), \+ FT_FIELD_SIZE_DELTA( _fname ), \+ _max, 0, \+ _dict \+ },+++#define T1_FIELD_BOOL( _ident, _fname, _dict ) \+ T1_NEW_SIMPLE_FIELD( _ident, T1_FIELD_TYPE_BOOL, _fname, _dict )++#define T1_FIELD_NUM( _ident, _fname, _dict ) \+ T1_NEW_SIMPLE_FIELD( _ident, T1_FIELD_TYPE_INTEGER, _fname, _dict )++#define T1_FIELD_FIXED( _ident, _fname, _dict ) \+ T1_NEW_SIMPLE_FIELD( _ident, T1_FIELD_TYPE_FIXED, _fname, _dict )++#define T1_FIELD_FIXED_1000( _ident, _fname, _dict ) \+ T1_NEW_SIMPLE_FIELD( _ident, T1_FIELD_TYPE_FIXED_1000, _fname, \+ _dict )++#define T1_FIELD_STRING( _ident, _fname, _dict ) \+ T1_NEW_SIMPLE_FIELD( _ident, T1_FIELD_TYPE_STRING, _fname, _dict )++#define T1_FIELD_KEY( _ident, _fname, _dict ) \+ T1_NEW_SIMPLE_FIELD( _ident, T1_FIELD_TYPE_KEY, _fname, _dict )++#define T1_FIELD_BBOX( _ident, _fname, _dict ) \+ T1_NEW_SIMPLE_FIELD( _ident, T1_FIELD_TYPE_BBOX, _fname, _dict )+++#define T1_FIELD_NUM_TABLE( _ident, _fname, _fmax, _dict ) \+ T1_NEW_TABLE_FIELD( _ident, T1_FIELD_TYPE_INTEGER_ARRAY, \+ _fname, _fmax, _dict )++#define T1_FIELD_FIXED_TABLE( _ident, _fname, _fmax, _dict ) \+ T1_NEW_TABLE_FIELD( _ident, T1_FIELD_TYPE_FIXED_ARRAY, \+ _fname, _fmax, _dict )++#define T1_FIELD_NUM_TABLE2( _ident, _fname, _fmax, _dict ) \+ T1_NEW_TABLE_FIELD2( _ident, T1_FIELD_TYPE_INTEGER_ARRAY, \+ _fname, _fmax, _dict )++#define T1_FIELD_FIXED_TABLE2( _ident, _fname, _fmax, _dict ) \+ T1_NEW_TABLE_FIELD2( _ident, T1_FIELD_TYPE_FIXED_ARRAY, \+ _fname, _fmax, _dict )++#define T1_FIELD_CALLBACK( _ident, _name, _dict ) \+ T1_NEW_CALLBACK_FIELD( _ident, _name, _dict )+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** T1 PARSER *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ typedef const struct PS_Parser_FuncsRec_* PS_Parser_Funcs;++ typedef struct PS_Parser_FuncsRec_+ {+ void+ (*init)( PS_Parser parser,+ FT_Byte* base,+ FT_Byte* limit,+ FT_Memory memory );++ void+ (*done)( PS_Parser parser );++ void+ (*skip_spaces)( PS_Parser parser );+ void+ (*skip_PS_token)( PS_Parser parser );++ FT_Long+ (*to_int)( PS_Parser parser );+ FT_Fixed+ (*to_fixed)( PS_Parser parser,+ FT_Int power_ten );++ FT_Error+ (*to_bytes)( PS_Parser parser,+ FT_Byte* bytes,+ FT_Offset max_bytes,+ FT_Long* pnum_bytes,+ FT_Bool delimiters );++ FT_Int+ (*to_coord_array)( PS_Parser parser,+ FT_Int max_coords,+ FT_Short* coords );+ FT_Int+ (*to_fixed_array)( PS_Parser parser,+ FT_Int max_values,+ FT_Fixed* values,+ FT_Int power_ten );++ void+ (*to_token)( PS_Parser parser,+ T1_Token token );+ void+ (*to_token_array)( PS_Parser parser,+ T1_Token tokens,+ FT_UInt max_tokens,+ FT_Int* pnum_tokens );++ FT_Error+ (*load_field)( PS_Parser parser,+ const T1_Field field,+ void** objects,+ FT_UInt max_objects,+ FT_ULong* pflags );++ FT_Error+ (*load_field_table)( PS_Parser parser,+ const T1_Field field,+ void** objects,+ FT_UInt max_objects,+ FT_ULong* pflags );++ } PS_Parser_FuncsRec;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* PS_ParserRec */+ /* */+ /* <Description> */+ /* A PS_Parser is an object used to parse a Type 1 font very quickly. */+ /* */+ /* <Fields> */+ /* cursor :: The current position in the text. */+ /* */+ /* base :: Start of the processed text. */+ /* */+ /* limit :: End of the processed text. */+ /* */+ /* error :: The last error returned. */+ /* */+ /* memory :: The object used for memory operations (alloc/realloc). */+ /* */+ /* funcs :: A table of functions for the parser. */+ /* */+ typedef struct PS_ParserRec_+ {+ FT_Byte* cursor;+ FT_Byte* base;+ FT_Byte* limit;+ FT_Error error;+ FT_Memory memory;++ PS_Parser_FuncsRec funcs;++ } PS_ParserRec;+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** T1 BUILDER *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+++ typedef struct T1_BuilderRec_* T1_Builder;+++ typedef FT_Error+ (*T1_Builder_Check_Points_Func)( T1_Builder builder,+ FT_Int count );++ typedef void+ (*T1_Builder_Add_Point_Func)( T1_Builder builder,+ FT_Pos x,+ FT_Pos y,+ FT_Byte flag );++ typedef FT_Error+ (*T1_Builder_Add_Point1_Func)( T1_Builder builder,+ FT_Pos x,+ FT_Pos y );++ typedef FT_Error+ (*T1_Builder_Add_Contour_Func)( T1_Builder builder );++ typedef FT_Error+ (*T1_Builder_Start_Point_Func)( T1_Builder builder,+ FT_Pos x,+ FT_Pos y );++ typedef void+ (*T1_Builder_Close_Contour_Func)( T1_Builder builder );+++ typedef const struct T1_Builder_FuncsRec_* T1_Builder_Funcs;++ typedef struct T1_Builder_FuncsRec_+ {+ void+ (*init)( T1_Builder builder,+ FT_Face face,+ FT_Size size,+ FT_GlyphSlot slot,+ FT_Bool hinting );++ void+ (*done)( T1_Builder builder );++ T1_Builder_Check_Points_Func check_points;+ T1_Builder_Add_Point_Func add_point;+ T1_Builder_Add_Point1_Func add_point1;+ T1_Builder_Add_Contour_Func add_contour;+ T1_Builder_Start_Point_Func start_point;+ T1_Builder_Close_Contour_Func close_contour;++ } T1_Builder_FuncsRec;+++ /* an enumeration type to handle charstring parsing states */+ typedef enum T1_ParseState_+ {+ T1_Parse_Start,+ T1_Parse_Have_Width,+ T1_Parse_Have_Moveto,+ T1_Parse_Have_Path++ } T1_ParseState;+++ /*************************************************************************/+ /* */+ /* <Structure> */+ /* T1_BuilderRec */+ /* */+ /* <Description> */+ /* A structure used during glyph loading to store its outline. */+ /* */+ /* <Fields> */+ /* memory :: The current memory object. */+ /* */+ /* face :: The current face object. */+ /* */+ /* glyph :: The current glyph slot. */+ /* */+ /* loader :: XXX */+ /* */+ /* base :: The base glyph outline. */+ /* */+ /* current :: The current glyph outline. */+ /* */+ /* max_points :: maximum points in builder outline */+ /* */+ /* max_contours :: Maximal number of contours in builder outline. */+ /* */+ /* pos_x :: The horizontal translation (if composite glyph). */+ /* */+ /* pos_y :: The vertical translation (if composite glyph). */+ /* */+ /* left_bearing :: The left side bearing point. */+ /* */+ /* advance :: The horizontal advance vector. */+ /* */+ /* bbox :: Unused. */+ /* */+ /* parse_state :: An enumeration which controls the charstring */+ /* parsing state. */+ /* */+ /* load_points :: If this flag is not set, no points are loaded. */+ /* */+ /* no_recurse :: Set but not used. */+ /* */+ /* metrics_only :: A boolean indicating that we only want to compute */+ /* the metrics of a given glyph, not load all of its */+ /* points. */+ /* */+ /* funcs :: An array of function pointers for the builder. */+ /* */+ typedef struct T1_BuilderRec_+ {+ FT_Memory memory;+ FT_Face face;+ FT_GlyphSlot glyph;+ FT_GlyphLoader loader;+ FT_Outline* base;+ FT_Outline* current;++ FT_Pos pos_x;+ FT_Pos pos_y;++ FT_Vector left_bearing;+ FT_Vector advance;++ FT_BBox bbox; /* bounding box */+ T1_ParseState parse_state;+ FT_Bool load_points;+ FT_Bool no_recurse;++ FT_Bool metrics_only;++ void* hints_funcs; /* hinter-specific */+ void* hints_globals; /* hinter-specific */++ T1_Builder_FuncsRec funcs;++ } T1_BuilderRec;+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** T1 DECODER *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++#if 0++ /*************************************************************************/+ /* */+ /* T1_MAX_SUBRS_CALLS details the maximum number of nested sub-routine */+ /* calls during glyph loading. */+ /* */+#define T1_MAX_SUBRS_CALLS 8+++ /*************************************************************************/+ /* */+ /* T1_MAX_CHARSTRING_OPERANDS is the charstring stack's capacity. A */+ /* minimum of 16 is required. */+ /* */+#define T1_MAX_CHARSTRINGS_OPERANDS 32++#endif /* 0 */+++ typedef struct T1_Decoder_ZoneRec_+ {+ FT_Byte* cursor;+ FT_Byte* base;+ FT_Byte* limit;++ } T1_Decoder_ZoneRec, *T1_Decoder_Zone;+++ typedef struct T1_DecoderRec_* T1_Decoder;+ typedef const struct T1_Decoder_FuncsRec_* T1_Decoder_Funcs;+++ typedef FT_Error+ (*T1_Decoder_Callback)( T1_Decoder decoder,+ FT_UInt glyph_index );+++ typedef struct T1_Decoder_FuncsRec_+ {+ FT_Error+ (*init)( T1_Decoder decoder,+ FT_Face face,+ FT_Size size,+ FT_GlyphSlot slot,+ FT_Byte** glyph_names,+ PS_Blend blend,+ FT_Bool hinting,+ FT_Render_Mode hint_mode,+ T1_Decoder_Callback callback );++ void+ (*done)( T1_Decoder decoder );++ FT_Error+ (*parse_charstrings)( T1_Decoder decoder,+ FT_Byte* base,+ FT_UInt len );++ } T1_Decoder_FuncsRec;+++ typedef struct T1_DecoderRec_+ {+ T1_BuilderRec builder;++ FT_Long stack[T1_MAX_CHARSTRINGS_OPERANDS];+ FT_Long* top;++ T1_Decoder_ZoneRec zones[T1_MAX_SUBRS_CALLS + 1];+ T1_Decoder_Zone zone;++ FT_Service_PsCMaps psnames; /* for seac */+ FT_UInt num_glyphs;+ FT_Byte** glyph_names;++ FT_Int lenIV; /* internal for sub routine calls */+ FT_UInt num_subrs;+ FT_Byte** subrs;+ FT_PtrDist* subrs_len; /* array of subrs length (optional) */++ FT_Matrix font_matrix;+ FT_Vector font_offset;++ FT_Int flex_state;+ FT_Int num_flex_vectors;+ FT_Vector flex_vectors[7];++ PS_Blend blend; /* for multiple master support */++ FT_Render_Mode hint_mode;++ T1_Decoder_Callback parse_callback;+ T1_Decoder_FuncsRec funcs;++ FT_Long* buildchar;+ FT_UInt len_buildchar;++ FT_Bool seac;++ } T1_DecoderRec;+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** AFM PARSER *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ typedef struct AFM_ParserRec_* AFM_Parser;++ typedef struct AFM_Parser_FuncsRec_+ {+ FT_Error+ (*init)( AFM_Parser parser,+ FT_Memory memory,+ FT_Byte* base,+ FT_Byte* limit );++ void+ (*done)( AFM_Parser parser );++ FT_Error+ (*parse)( AFM_Parser parser );++ } AFM_Parser_FuncsRec;+++ typedef struct AFM_StreamRec_* AFM_Stream;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* AFM_ParserRec */+ /* */+ /* <Description> */+ /* An AFM_Parser is a parser for the AFM files. */+ /* */+ /* <Fields> */+ /* memory :: The object used for memory operations (alloc and */+ /* realloc). */+ /* */+ /* stream :: This is an opaque object. */+ /* */+ /* FontInfo :: The result will be stored here. */+ /* */+ /* get_index :: A user provided function to get a glyph index by its */+ /* name. */+ /* */+ typedef struct AFM_ParserRec_+ {+ FT_Memory memory;+ AFM_Stream stream;++ AFM_FontInfo FontInfo;++ FT_Int+ (*get_index)( const char* name,+ FT_Offset len,+ void* user_data );++ void* user_data;++ } AFM_ParserRec;+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** TYPE1 CHARMAPS *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ typedef const struct T1_CMap_ClassesRec_* T1_CMap_Classes;++ typedef struct T1_CMap_ClassesRec_+ {+ FT_CMap_Class standard;+ FT_CMap_Class expert;+ FT_CMap_Class custom;+ FT_CMap_Class unicode;++ } T1_CMap_ClassesRec;+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** PSAux Module Interface *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ typedef struct PSAux_ServiceRec_+ {+ /* don't use `PS_Table_Funcs' and friends to avoid compiler warnings */+ const PS_Table_FuncsRec* ps_table_funcs;+ const PS_Parser_FuncsRec* ps_parser_funcs;+ const T1_Builder_FuncsRec* t1_builder_funcs;+ const T1_Decoder_FuncsRec* t1_decoder_funcs;++ void+ (*t1_decrypt)( FT_Byte* buffer,+ FT_Offset length,+ FT_UShort seed );++ T1_CMap_Classes t1_cmap_classes;++ /* fields after this comment line were added after version 2.1.10 */+ const AFM_Parser_FuncsRec* afm_parser_funcs;++ } PSAux_ServiceRec, *PSAux_Service;++ /* backwards-compatible type definition */+ typedef PSAux_ServiceRec PSAux_Interface;+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** Some convenience functions *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++#define IS_PS_NEWLINE( ch ) \+ ( (ch) == '\r' || \+ (ch) == '\n' )++#define IS_PS_SPACE( ch ) \+ ( (ch) == ' ' || \+ IS_PS_NEWLINE( ch ) || \+ (ch) == '\t' || \+ (ch) == '\f' || \+ (ch) == '\0' )++#define IS_PS_SPECIAL( ch ) \+ ( (ch) == '/' || \+ (ch) == '(' || (ch) == ')' || \+ (ch) == '<' || (ch) == '>' || \+ (ch) == '[' || (ch) == ']' || \+ (ch) == '{' || (ch) == '}' || \+ (ch) == '%' )++#define IS_PS_DELIM( ch ) \+ ( IS_PS_SPACE( ch ) || \+ IS_PS_SPECIAL( ch ) )++#define IS_PS_DIGIT( ch ) \+ ( (ch) >= '0' && (ch) <= '9' )++#define IS_PS_XDIGIT( ch ) \+ ( IS_PS_DIGIT( ch ) || \+ ( (ch) >= 'A' && (ch) <= 'F' ) || \+ ( (ch) >= 'a' && (ch) <= 'f' ) )++#define IS_PS_BASE85( ch ) \+ ( (ch) >= '!' && (ch) <= 'u' )++#define IS_PS_TOKEN( cur, limit, token ) \+ ( (char)(cur)[0] == (token)[0] && \+ ( (cur) + sizeof ( (token) ) == (limit) || \+ ( (cur) + sizeof( (token) ) < (limit) && \+ IS_PS_DELIM( (cur)[sizeof ( (token) ) - 1] ) ) ) && \+ ft_strncmp( (char*)(cur), (token), sizeof ( (token) ) - 1 ) == 0 )+++FT_END_HEADER++#endif /* __PSAUX_H__ */+++/* END */
+ include/freetype/internal/pshints.h view
@@ -0,0 +1,712 @@+/***************************************************************************/+/* */+/* pshints.h */+/* */+/* Interface to Postscript-specific (Type 1 and Type 2) hints */+/* recorders (specification only). These are used to support native */+/* T1/T2 hints in the `type1', `cid', and `cff' font drivers. */+/* */+/* Copyright 2001, 2002, 2003, 2005, 2006, 2007, 2009 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 __PSHINTS_H__+#define __PSHINTS_H__+++#include <ft2build.h>+#include FT_FREETYPE_H+#include FT_TYPE1_TABLES_H+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** INTERNAL REPRESENTATION OF GLOBALS *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ typedef struct PSH_GlobalsRec_* PSH_Globals;++ typedef FT_Error+ (*PSH_Globals_NewFunc)( FT_Memory memory,+ T1_Private* private_dict,+ PSH_Globals* aglobals );++ typedef FT_Error+ (*PSH_Globals_SetScaleFunc)( PSH_Globals globals,+ FT_Fixed x_scale,+ FT_Fixed y_scale,+ FT_Fixed x_delta,+ FT_Fixed y_delta );++ typedef void+ (*PSH_Globals_DestroyFunc)( PSH_Globals globals );+++ typedef struct PSH_Globals_FuncsRec_+ {+ PSH_Globals_NewFunc create;+ PSH_Globals_SetScaleFunc set_scale;+ PSH_Globals_DestroyFunc destroy;++ } PSH_Globals_FuncsRec, *PSH_Globals_Funcs;+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** PUBLIC TYPE 1 HINTS RECORDER *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /*************************************************************************+ *+ * @type:+ * T1_Hints+ *+ * @description:+ * This is a handle to an opaque structure used to record glyph hints+ * from a Type 1 character glyph character string.+ *+ * The methods used to operate on this object are defined by the+ * @T1_Hints_FuncsRec structure. Recording glyph hints is normally+ * achieved through the following scheme:+ *+ * - Open a new hint recording session by calling the `open' method.+ * This rewinds the recorder and prepare it for new input.+ *+ * - For each hint found in the glyph charstring, call the corresponding+ * method (`stem', `stem3', or `reset'). Note that these functions do+ * not return an error code.+ *+ * - Close the recording session by calling the `close' method. It+ * returns an error code if the hints were invalid or something+ * strange happened (e.g., memory shortage).+ *+ * The hints accumulated in the object can later be used by the+ * PostScript hinter.+ *+ */+ typedef struct T1_HintsRec_* T1_Hints;+++ /*************************************************************************+ *+ * @type:+ * T1_Hints_Funcs+ *+ * @description:+ * A pointer to the @T1_Hints_FuncsRec structure that defines the API of+ * a given @T1_Hints object.+ *+ */+ typedef const struct T1_Hints_FuncsRec_* T1_Hints_Funcs;+++ /*************************************************************************+ *+ * @functype:+ * T1_Hints_OpenFunc+ *+ * @description:+ * A method of the @T1_Hints class used to prepare it for a new Type 1+ * hints recording session.+ *+ * @input:+ * hints ::+ * A handle to the Type 1 hints recorder.+ *+ * @note:+ * You should always call the @T1_Hints_CloseFunc method in order to+ * close an opened recording session.+ *+ */+ typedef void+ (*T1_Hints_OpenFunc)( T1_Hints hints );+++ /*************************************************************************+ *+ * @functype:+ * T1_Hints_SetStemFunc+ *+ * @description:+ * A method of the @T1_Hints class used to record a new horizontal or+ * vertical stem. This corresponds to the Type 1 `hstem' and `vstem'+ * operators.+ *+ * @input:+ * hints ::+ * A handle to the Type 1 hints recorder.+ *+ * dimension ::+ * 0 for horizontal stems (hstem), 1 for vertical ones (vstem).+ *+ * coords ::+ * Array of 2 coordinates in 16.16 format, used as (position,length)+ * stem descriptor.+ *+ * @note:+ * Use vertical coordinates (y) for horizontal stems (dim=0). Use+ * horizontal coordinates (x) for vertical stems (dim=1).+ *+ * `coords[0]' is the absolute stem position (lowest coordinate);+ * `coords[1]' is the length.+ *+ * The length can be negative, in which case it must be either -20 or+ * -21. It is interpreted as a `ghost' stem, according to the Type 1+ * specification.+ *+ * If the length is -21 (corresponding to a bottom ghost stem), then+ * the real stem position is `coords[0]+coords[1]'.+ *+ */+ typedef void+ (*T1_Hints_SetStemFunc)( T1_Hints hints,+ FT_UInt dimension,+ FT_Fixed* coords );+++ /*************************************************************************+ *+ * @functype:+ * T1_Hints_SetStem3Func+ *+ * @description:+ * A method of the @T1_Hints class used to record three+ * counter-controlled horizontal or vertical stems at once.+ *+ * @input:+ * hints ::+ * A handle to the Type 1 hints recorder.+ *+ * dimension ::+ * 0 for horizontal stems, 1 for vertical ones.+ *+ * coords ::+ * An array of 6 values in 16.16 format, holding 3 (position,length)+ * pairs for the counter-controlled stems.+ *+ * @note:+ * Use vertical coordinates (y) for horizontal stems (dim=0). Use+ * horizontal coordinates (x) for vertical stems (dim=1).+ *+ * The lengths cannot be negative (ghost stems are never+ * counter-controlled).+ *+ */+ typedef void+ (*T1_Hints_SetStem3Func)( T1_Hints hints,+ FT_UInt dimension,+ FT_Fixed* coords );+++ /*************************************************************************+ *+ * @functype:+ * T1_Hints_ResetFunc+ *+ * @description:+ * A method of the @T1_Hints class used to reset the stems hints in a+ * recording session.+ *+ * @input:+ * hints ::+ * A handle to the Type 1 hints recorder.+ *+ * end_point ::+ * The index of the last point in the input glyph in which the+ * previously defined hints apply.+ *+ */+ typedef void+ (*T1_Hints_ResetFunc)( T1_Hints hints,+ FT_UInt end_point );+++ /*************************************************************************+ *+ * @functype:+ * T1_Hints_CloseFunc+ *+ * @description:+ * A method of the @T1_Hints class used to close a hint recording+ * session.+ *+ * @input:+ * hints ::+ * A handle to the Type 1 hints recorder.+ *+ * end_point ::+ * The index of the last point in the input glyph.+ *+ * @return:+ * FreeType error code. 0 means success.+ *+ * @note:+ * The error code is set to indicate that an error occurred during the+ * recording session.+ *+ */+ typedef FT_Error+ (*T1_Hints_CloseFunc)( T1_Hints hints,+ FT_UInt end_point );+++ /*************************************************************************+ *+ * @functype:+ * T1_Hints_ApplyFunc+ *+ * @description:+ * A method of the @T1_Hints class used to apply hints to the+ * corresponding glyph outline. Must be called once all hints have been+ * recorded.+ *+ * @input:+ * hints ::+ * A handle to the Type 1 hints recorder.+ *+ * outline ::+ * A pointer to the target outline descriptor.+ *+ * globals ::+ * The hinter globals for this font.+ *+ * hint_mode ::+ * Hinting information.+ *+ * @return:+ * FreeType error code. 0 means success.+ *+ * @note:+ * On input, all points within the outline are in font coordinates. On+ * output, they are in 1/64th of pixels.+ *+ * The scaling transformation is taken from the `globals' object which+ * must correspond to the same font as the glyph.+ *+ */+ typedef FT_Error+ (*T1_Hints_ApplyFunc)( T1_Hints hints,+ FT_Outline* outline,+ PSH_Globals globals,+ FT_Render_Mode hint_mode );+++ /*************************************************************************+ *+ * @struct:+ * T1_Hints_FuncsRec+ *+ * @description:+ * The structure used to provide the API to @T1_Hints objects.+ *+ * @fields:+ * hints ::+ * A handle to the T1 Hints recorder.+ *+ * open ::+ * The function to open a recording session.+ *+ * close ::+ * The function to close a recording session.+ *+ * stem ::+ * The function to set a simple stem.+ *+ * stem3 ::+ * The function to set counter-controlled stems.+ *+ * reset ::+ * The function to reset stem hints.+ *+ * apply ::+ * The function to apply the hints to the corresponding glyph outline.+ *+ */+ typedef struct T1_Hints_FuncsRec_+ {+ T1_Hints hints;+ T1_Hints_OpenFunc open;+ T1_Hints_CloseFunc close;+ T1_Hints_SetStemFunc stem;+ T1_Hints_SetStem3Func stem3;+ T1_Hints_ResetFunc reset;+ T1_Hints_ApplyFunc apply;++ } T1_Hints_FuncsRec;+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** PUBLIC TYPE 2 HINTS RECORDER *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /*************************************************************************+ *+ * @type:+ * T2_Hints+ *+ * @description:+ * This is a handle to an opaque structure used to record glyph hints+ * from a Type 2 character glyph character string.+ *+ * The methods used to operate on this object are defined by the+ * @T2_Hints_FuncsRec structure. Recording glyph hints is normally+ * achieved through the following scheme:+ *+ * - Open a new hint recording session by calling the `open' method.+ * This rewinds the recorder and prepare it for new input.+ *+ * - For each hint found in the glyph charstring, call the corresponding+ * method (`stems', `hintmask', `counters'). Note that these+ * functions do not return an error code.+ *+ * - Close the recording session by calling the `close' method. It+ * returns an error code if the hints were invalid or something+ * strange happened (e.g., memory shortage).+ *+ * The hints accumulated in the object can later be used by the+ * Postscript hinter.+ *+ */+ typedef struct T2_HintsRec_* T2_Hints;+++ /*************************************************************************+ *+ * @type:+ * T2_Hints_Funcs+ *+ * @description:+ * A pointer to the @T2_Hints_FuncsRec structure that defines the API of+ * a given @T2_Hints object.+ *+ */+ typedef const struct T2_Hints_FuncsRec_* T2_Hints_Funcs;+++ /*************************************************************************+ *+ * @functype:+ * T2_Hints_OpenFunc+ *+ * @description:+ * A method of the @T2_Hints class used to prepare it for a new Type 2+ * hints recording session.+ *+ * @input:+ * hints ::+ * A handle to the Type 2 hints recorder.+ *+ * @note:+ * You should always call the @T2_Hints_CloseFunc method in order to+ * close an opened recording session.+ *+ */+ typedef void+ (*T2_Hints_OpenFunc)( T2_Hints hints );+++ /*************************************************************************+ *+ * @functype:+ * T2_Hints_StemsFunc+ *+ * @description:+ * A method of the @T2_Hints class used to set the table of stems in+ * either the vertical or horizontal dimension. Equivalent to the+ * `hstem', `vstem', `hstemhm', and `vstemhm' Type 2 operators.+ *+ * @input:+ * hints ::+ * A handle to the Type 2 hints recorder.+ *+ * dimension ::+ * 0 for horizontal stems (hstem), 1 for vertical ones (vstem).+ *+ * count ::+ * The number of stems.+ *+ * coords ::+ * An array of `count' (position,length) pairs in 16.16 format.+ *+ * @note:+ * Use vertical coordinates (y) for horizontal stems (dim=0). Use+ * horizontal coordinates (x) for vertical stems (dim=1).+ *+ * There are `2*count' elements in the `coords' array. Each even+ * element is an absolute position in font units, each odd element is a+ * length in font units.+ *+ * A length can be negative, in which case it must be either -20 or+ * -21. It is interpreted as a `ghost' stem, according to the Type 1+ * specification.+ *+ */+ typedef void+ (*T2_Hints_StemsFunc)( T2_Hints hints,+ FT_UInt dimension,+ FT_UInt count,+ FT_Fixed* coordinates );+++ /*************************************************************************+ *+ * @functype:+ * T2_Hints_MaskFunc+ *+ * @description:+ * A method of the @T2_Hints class used to set a given hintmask (this+ * corresponds to the `hintmask' Type 2 operator).+ *+ * @input:+ * hints ::+ * A handle to the Type 2 hints recorder.+ *+ * end_point ::+ * The glyph index of the last point to which the previously defined+ * or activated hints apply.+ *+ * bit_count ::+ * The number of bits in the hint mask.+ *+ * bytes ::+ * An array of bytes modelling the hint mask.+ *+ * @note:+ * If the hintmask starts the charstring (before any glyph point+ * definition), the value of `end_point' should be 0.+ *+ * `bit_count' is the number of meaningful bits in the `bytes' array; it+ * must be equal to the total number of hints defined so far (i.e.,+ * horizontal+verticals).+ *+ * The `bytes' array can come directly from the Type 2 charstring and+ * respects the same format.+ *+ */+ typedef void+ (*T2_Hints_MaskFunc)( T2_Hints hints,+ FT_UInt end_point,+ FT_UInt bit_count,+ const FT_Byte* bytes );+++ /*************************************************************************+ *+ * @functype:+ * T2_Hints_CounterFunc+ *+ * @description:+ * A method of the @T2_Hints class used to set a given counter mask+ * (this corresponds to the `hintmask' Type 2 operator).+ *+ * @input:+ * hints ::+ * A handle to the Type 2 hints recorder.+ *+ * end_point ::+ * A glyph index of the last point to which the previously defined or+ * active hints apply.+ *+ * bit_count ::+ * The number of bits in the hint mask.+ *+ * bytes ::+ * An array of bytes modelling the hint mask.+ *+ * @note:+ * If the hintmask starts the charstring (before any glyph point+ * definition), the value of `end_point' should be 0.+ *+ * `bit_count' is the number of meaningful bits in the `bytes' array; it+ * must be equal to the total number of hints defined so far (i.e.,+ * horizontal+verticals).+ *+ * The `bytes' array can come directly from the Type 2 charstring and+ * respects the same format.+ *+ */+ typedef void+ (*T2_Hints_CounterFunc)( T2_Hints hints,+ FT_UInt bit_count,+ const FT_Byte* bytes );+++ /*************************************************************************+ *+ * @functype:+ * T2_Hints_CloseFunc+ *+ * @description:+ * A method of the @T2_Hints class used to close a hint recording+ * session.+ *+ * @input:+ * hints ::+ * A handle to the Type 2 hints recorder.+ *+ * end_point ::+ * The index of the last point in the input glyph.+ *+ * @return:+ * FreeType error code. 0 means success.+ *+ * @note:+ * The error code is set to indicate that an error occurred during the+ * recording session.+ *+ */+ typedef FT_Error+ (*T2_Hints_CloseFunc)( T2_Hints hints,+ FT_UInt end_point );+++ /*************************************************************************+ *+ * @functype:+ * T2_Hints_ApplyFunc+ *+ * @description:+ * A method of the @T2_Hints class used to apply hints to the+ * corresponding glyph outline. Must be called after the `close'+ * method.+ *+ * @input:+ * hints ::+ * A handle to the Type 2 hints recorder.+ *+ * outline ::+ * A pointer to the target outline descriptor.+ *+ * globals ::+ * The hinter globals for this font.+ *+ * hint_mode ::+ * Hinting information.+ *+ * @return:+ * FreeType error code. 0 means success.+ *+ * @note:+ * On input, all points within the outline are in font coordinates. On+ * output, they are in 1/64th of pixels.+ *+ * The scaling transformation is taken from the `globals' object which+ * must correspond to the same font than the glyph.+ *+ */+ typedef FT_Error+ (*T2_Hints_ApplyFunc)( T2_Hints hints,+ FT_Outline* outline,+ PSH_Globals globals,+ FT_Render_Mode hint_mode );+++ /*************************************************************************+ *+ * @struct:+ * T2_Hints_FuncsRec+ *+ * @description:+ * The structure used to provide the API to @T2_Hints objects.+ *+ * @fields:+ * hints ::+ * A handle to the T2 hints recorder object.+ *+ * open ::+ * The function to open a recording session.+ *+ * close ::+ * The function to close a recording session.+ *+ * stems ::+ * The function to set the dimension's stems table.+ *+ * hintmask ::+ * The function to set hint masks.+ *+ * counter ::+ * The function to set counter masks.+ *+ * apply ::+ * The function to apply the hints on the corresponding glyph outline.+ *+ */+ typedef struct T2_Hints_FuncsRec_+ {+ T2_Hints hints;+ T2_Hints_OpenFunc open;+ T2_Hints_CloseFunc close;+ T2_Hints_StemsFunc stems;+ T2_Hints_MaskFunc hintmask;+ T2_Hints_CounterFunc counter;+ T2_Hints_ApplyFunc apply;++ } T2_Hints_FuncsRec;+++ /* */+++ typedef struct PSHinter_Interface_+ {+ PSH_Globals_Funcs (*get_globals_funcs)( FT_Module module );+ T1_Hints_Funcs (*get_t1_funcs) ( FT_Module module );+ T2_Hints_Funcs (*get_t2_funcs) ( FT_Module module );++ } PSHinter_Interface;++ typedef PSHinter_Interface* PSHinter_Service;++#ifndef FT_CONFIG_OPTION_PIC++#define FT_DEFINE_PSHINTER_INTERFACE(class_, get_globals_funcs_, \+ get_t1_funcs_, get_t2_funcs_) \+ static const PSHinter_Interface class_ = \+ { \+ get_globals_funcs_, get_t1_funcs_, get_t2_funcs_ \+ };++#else /* FT_CONFIG_OPTION_PIC */ ++#define FT_DEFINE_PSHINTER_INTERFACE(class_, get_globals_funcs_, \+ get_t1_funcs_, get_t2_funcs_) \+ void \+ FT_Init_Class_##class_( FT_Library library, \+ PSHinter_Interface* clazz) \+ { \+ FT_UNUSED(library); \+ clazz->get_globals_funcs = get_globals_funcs_; \+ clazz->get_t1_funcs = get_t1_funcs_; \+ clazz->get_t2_funcs = get_t2_funcs_; \+ } ++#endif /* FT_CONFIG_OPTION_PIC */ ++FT_END_HEADER++#endif /* __PSHINTS_H__ */+++/* END */
+ include/freetype/internal/services/svbdf.h view
@@ -0,0 +1,77 @@+/***************************************************************************/+/* */+/* svbdf.h */+/* */+/* The FreeType BDF services (specification). */+/* */+/* Copyright 2003 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 __SVBDF_H__+#define __SVBDF_H__++#include FT_BDF_H+#include FT_INTERNAL_SERVICE_H+++FT_BEGIN_HEADER+++#define FT_SERVICE_ID_BDF "bdf"++ typedef FT_Error+ (*FT_BDF_GetCharsetIdFunc)( FT_Face face,+ const char* *acharset_encoding,+ const char* *acharset_registry );++ typedef FT_Error+ (*FT_BDF_GetPropertyFunc)( FT_Face face,+ const char* prop_name,+ BDF_PropertyRec *aproperty );+++ FT_DEFINE_SERVICE( BDF )+ {+ FT_BDF_GetCharsetIdFunc get_charset_id;+ FT_BDF_GetPropertyFunc get_property;+ };++#ifndef FT_CONFIG_OPTION_PIC++#define FT_DEFINE_SERVICE_BDFRec(class_, get_charset_id_, get_property_) \+ static const FT_Service_BDFRec class_ = \+ { \+ get_charset_id_, get_property_ \+ };++#else /* FT_CONFIG_OPTION_PIC */ ++#define FT_DEFINE_SERVICE_BDFRec(class_, get_charset_id_, get_property_) \+ void \+ FT_Init_Class_##class_( FT_Service_BDFRec* clazz ) \+ { \+ clazz->get_charset_id = get_charset_id_; \+ clazz->get_property = get_property_; \+ } ++#endif /* FT_CONFIG_OPTION_PIC */ ++ /* */+++FT_END_HEADER+++#endif /* __SVBDF_H__ */+++/* END */
+ include/freetype/internal/services/svcid.h view
@@ -0,0 +1,83 @@+/***************************************************************************/+/* */+/* svcid.h */+/* */+/* The FreeType CID font services (specification). */+/* */+/* Copyright 2007, 2009 by Derek Clegg, 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. */+/* */+/***************************************************************************/+++#ifndef __SVCID_H__+#define __SVCID_H__++#include FT_INTERNAL_SERVICE_H+++FT_BEGIN_HEADER+++#define FT_SERVICE_ID_CID "CID"++ typedef FT_Error+ (*FT_CID_GetRegistryOrderingSupplementFunc)( FT_Face face,+ const char* *registry,+ const char* *ordering,+ FT_Int *supplement );+ typedef FT_Error+ (*FT_CID_GetIsInternallyCIDKeyedFunc)( FT_Face face,+ FT_Bool *is_cid );+ typedef FT_Error+ (*FT_CID_GetCIDFromGlyphIndexFunc)( FT_Face face,+ FT_UInt glyph_index,+ FT_UInt *cid );++ FT_DEFINE_SERVICE( CID )+ {+ FT_CID_GetRegistryOrderingSupplementFunc get_ros;+ FT_CID_GetIsInternallyCIDKeyedFunc get_is_cid;+ FT_CID_GetCIDFromGlyphIndexFunc get_cid_from_glyph_index;+ };++#ifndef FT_CONFIG_OPTION_PIC++#define FT_DEFINE_SERVICE_CIDREC(class_, get_ros_, \+ get_is_cid_, get_cid_from_glyph_index_ ) \+ static const FT_Service_CIDRec class_ = \+ { \+ get_ros_, get_is_cid_, get_cid_from_glyph_index_ \+ };++#else /* FT_CONFIG_OPTION_PIC */ ++#define FT_DEFINE_SERVICE_CIDREC(class_, get_ros_, \+ get_is_cid_, get_cid_from_glyph_index_ ) \+ void \+ FT_Init_Class_##class_( FT_Library library, \+ FT_Service_CIDRec* clazz) \+ { \+ FT_UNUSED(library); \+ clazz->get_ros = get_ros_; \+ clazz->get_is_cid = get_is_cid_; \+ clazz->get_cid_from_glyph_index = get_cid_from_glyph_index_; \+ } ++#endif /* FT_CONFIG_OPTION_PIC */ ++ /* */+++FT_END_HEADER+++#endif /* __SVCID_H__ */+++/* END */
+ include/freetype/internal/services/svgldict.h view
@@ -0,0 +1,82 @@+/***************************************************************************/+/* */+/* svgldict.h */+/* */+/* The FreeType glyph dictionary services (specification). */+/* */+/* Copyright 2003 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 __SVGLDICT_H__+#define __SVGLDICT_H__++#include FT_INTERNAL_SERVICE_H+++FT_BEGIN_HEADER+++ /*+ * A service used to retrieve glyph names, as well as to find the+ * index of a given glyph name in a font.+ *+ */++#define FT_SERVICE_ID_GLYPH_DICT "glyph-dict"+++ typedef FT_Error+ (*FT_GlyphDict_GetNameFunc)( FT_Face face,+ FT_UInt glyph_index,+ FT_Pointer buffer,+ FT_UInt buffer_max );++ typedef FT_UInt+ (*FT_GlyphDict_NameIndexFunc)( FT_Face face,+ FT_String* glyph_name );+++ FT_DEFINE_SERVICE( GlyphDict )+ {+ FT_GlyphDict_GetNameFunc get_name;+ FT_GlyphDict_NameIndexFunc name_index; /* optional */+ };++#ifndef FT_CONFIG_OPTION_PIC++#define FT_DEFINE_SERVICE_GLYPHDICTREC(class_, get_name_, name_index_) \+ static const FT_Service_GlyphDictRec class_ = \+ { \+ get_name_, name_index_ \+ };++#else /* FT_CONFIG_OPTION_PIC */ ++#define FT_DEFINE_SERVICE_GLYPHDICTREC(class_, get_name_, name_index_) \+ void \+ FT_Init_Class_##class_( FT_Library library, \+ FT_Service_GlyphDictRec* clazz) \+ { \+ FT_UNUSED(library); \+ clazz->get_name = get_name_; \+ clazz->name_index = name_index_; \+ } ++#endif /* FT_CONFIG_OPTION_PIC */ ++ /* */+++FT_END_HEADER+++#endif /* __SVGLDICT_H__ */
+ include/freetype/internal/services/svgxval.h view
@@ -0,0 +1,72 @@+/***************************************************************************/+/* */+/* svgxval.h */+/* */+/* FreeType API for validating TrueTypeGX/AAT tables (specification). */+/* */+/* Copyright 2004, 2005 by */+/* Masatake YAMATO, Red Hat 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. */+/* */+/***************************************************************************/+++#ifndef __SVGXVAL_H__+#define __SVGXVAL_H__++#include FT_GX_VALIDATE_H+#include FT_INTERNAL_VALIDATE_H++FT_BEGIN_HEADER+++#define FT_SERVICE_ID_GX_VALIDATE "truetypegx-validate"+#define FT_SERVICE_ID_CLASSICKERN_VALIDATE "classickern-validate"++ typedef FT_Error+ (*gxv_validate_func)( FT_Face face,+ FT_UInt gx_flags,+ FT_Bytes tables[FT_VALIDATE_GX_LENGTH],+ FT_UInt table_length );+++ typedef FT_Error+ (*ckern_validate_func)( FT_Face face,+ FT_UInt ckern_flags,+ FT_Bytes *ckern_table );+++ FT_DEFINE_SERVICE( GXvalidate )+ {+ gxv_validate_func validate;+ };++ FT_DEFINE_SERVICE( CKERNvalidate )+ {+ ckern_validate_func validate;+ };++ /* */+++FT_END_HEADER+++#endif /* __SVGXVAL_H__ */+++/* END */
+ include/freetype/internal/services/svkern.h view
@@ -0,0 +1,51 @@+/***************************************************************************/+/* */+/* svkern.h */+/* */+/* The FreeType Kerning service (specification). */+/* */+/* Copyright 2006 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 __SVKERN_H__+#define __SVKERN_H__++#include FT_INTERNAL_SERVICE_H+#include FT_TRUETYPE_TABLES_H+++FT_BEGIN_HEADER++#define FT_SERVICE_ID_KERNING "kerning"+++ typedef FT_Error+ (*FT_Kerning_TrackGetFunc)( FT_Face face,+ FT_Fixed point_size,+ FT_Int degree,+ FT_Fixed* akerning );++ FT_DEFINE_SERVICE( Kerning )+ {+ FT_Kerning_TrackGetFunc get_track;+ };++ /* */+++FT_END_HEADER+++#endif /* __SVKERN_H__ */+++/* END */
+ include/freetype/internal/services/svmm.h view
@@ -0,0 +1,104 @@+/***************************************************************************/+/* */+/* svmm.h */+/* */+/* The FreeType Multiple Masters and GX var services (specification). */+/* */+/* Copyright 2003, 2004 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 __SVMM_H__+#define __SVMM_H__++#include FT_INTERNAL_SERVICE_H+++FT_BEGIN_HEADER+++ /*+ * A service used to manage multiple-masters data in a given face.+ *+ * See the related APIs in `ftmm.h' (FT_MULTIPLE_MASTERS_H).+ *+ */++#define FT_SERVICE_ID_MULTI_MASTERS "multi-masters"+++ typedef FT_Error+ (*FT_Get_MM_Func)( FT_Face face,+ FT_Multi_Master* master );++ typedef FT_Error+ (*FT_Get_MM_Var_Func)( FT_Face face,+ FT_MM_Var* *master );++ typedef FT_Error+ (*FT_Set_MM_Design_Func)( FT_Face face,+ FT_UInt num_coords,+ FT_Long* coords );++ typedef FT_Error+ (*FT_Set_Var_Design_Func)( FT_Face face,+ FT_UInt num_coords,+ FT_Fixed* coords );++ typedef FT_Error+ (*FT_Set_MM_Blend_Func)( FT_Face face,+ FT_UInt num_coords,+ FT_Long* coords );+++ FT_DEFINE_SERVICE( MultiMasters )+ {+ FT_Get_MM_Func get_mm;+ FT_Set_MM_Design_Func set_mm_design;+ FT_Set_MM_Blend_Func set_mm_blend;+ FT_Get_MM_Var_Func get_mm_var;+ FT_Set_Var_Design_Func set_var_design;+ };++#ifndef FT_CONFIG_OPTION_PIC++#define FT_DEFINE_SERVICE_MULTIMASTERSREC(class_, get_mm_, set_mm_design_, \+ set_mm_blend_, get_mm_var_, set_var_design_) \+ static const FT_Service_MultiMastersRec class_ = \+ { \+ get_mm_, set_mm_design_, set_mm_blend_, get_mm_var_, set_var_design_ \+ };++#else /* FT_CONFIG_OPTION_PIC */ ++#define FT_DEFINE_SERVICE_MULTIMASTERSREC(class_, get_mm_, set_mm_design_, \+ set_mm_blend_, get_mm_var_, set_var_design_) \+ void \+ FT_Init_Class_##class_( FT_Service_MultiMastersRec* clazz ) \+ { \+ clazz->get_mm = get_mm_; \+ clazz->set_mm_design = set_mm_design_; \+ clazz->set_mm_blend = set_mm_blend_; \+ clazz->get_mm_var = get_mm_var_; \+ clazz->set_var_design = set_var_design_; \+ } ++#endif /* FT_CONFIG_OPTION_PIC */ ++ /* */+++FT_END_HEADER++#endif /* __SVMM_H__ */+++/* END */
+ include/freetype/internal/services/svotval.h view
@@ -0,0 +1,55 @@+/***************************************************************************/+/* */+/* svotval.h */+/* */+/* The FreeType OpenType validation service (specification). */+/* */+/* Copyright 2004, 2006 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 __SVOTVAL_H__+#define __SVOTVAL_H__++#include FT_OPENTYPE_VALIDATE_H+#include FT_INTERNAL_VALIDATE_H++FT_BEGIN_HEADER+++#define FT_SERVICE_ID_OPENTYPE_VALIDATE "opentype-validate"+++ typedef FT_Error+ (*otv_validate_func)( FT_Face volatile face,+ FT_UInt ot_flags,+ FT_Bytes *base,+ FT_Bytes *gdef,+ FT_Bytes *gpos,+ FT_Bytes *gsub,+ FT_Bytes *jstf );+++ FT_DEFINE_SERVICE( OTvalidate )+ {+ otv_validate_func validate;+ };++ /* */+++FT_END_HEADER+++#endif /* __SVOTVAL_H__ */+++/* END */
+ include/freetype/internal/services/svpfr.h view
@@ -0,0 +1,66 @@+/***************************************************************************/+/* */+/* svpfr.h */+/* */+/* Internal PFR service functions (specification). */+/* */+/* Copyright 2003, 2006 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 __SVPFR_H__+#define __SVPFR_H__++#include FT_PFR_H+#include FT_INTERNAL_SERVICE_H+++FT_BEGIN_HEADER+++#define FT_SERVICE_ID_PFR_METRICS "pfr-metrics"+++ typedef FT_Error+ (*FT_PFR_GetMetricsFunc)( FT_Face face,+ FT_UInt *aoutline,+ FT_UInt *ametrics,+ FT_Fixed *ax_scale,+ FT_Fixed *ay_scale );++ typedef FT_Error+ (*FT_PFR_GetKerningFunc)( FT_Face face,+ FT_UInt left,+ FT_UInt right,+ FT_Vector *avector );++ typedef FT_Error+ (*FT_PFR_GetAdvanceFunc)( FT_Face face,+ FT_UInt gindex,+ FT_Pos *aadvance );+++ FT_DEFINE_SERVICE( PfrMetrics )+ {+ FT_PFR_GetMetricsFunc get_metrics;+ FT_PFR_GetKerningFunc get_kerning;+ FT_PFR_GetAdvanceFunc get_advance;++ };++ /* */++FT_END_HEADER++#endif /* __SVPFR_H__ */+++/* END */
+ include/freetype/internal/services/svpostnm.h view
@@ -0,0 +1,79 @@+/***************************************************************************/+/* */+/* svpostnm.h */+/* */+/* The FreeType PostScript name services (specification). */+/* */+/* Copyright 2003, 2007 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 __SVPOSTNM_H__+#define __SVPOSTNM_H__++#include FT_INTERNAL_SERVICE_H+++FT_BEGIN_HEADER++ /*+ * A trivial service used to retrieve the PostScript name of a given+ * font when available. The `get_name' field should never be NULL.+ *+ * The corresponding function can return NULL to indicate that the+ * PostScript name is not available.+ *+ * The name is owned by the face and will be destroyed with it.+ */++#define FT_SERVICE_ID_POSTSCRIPT_FONT_NAME "postscript-font-name"+++ typedef const char*+ (*FT_PsName_GetFunc)( FT_Face face );+++ FT_DEFINE_SERVICE( PsFontName )+ {+ FT_PsName_GetFunc get_ps_font_name;+ };++#ifndef FT_CONFIG_OPTION_PIC++#define FT_DEFINE_SERVICE_PSFONTNAMEREC(class_, get_ps_font_name_) \+ static const FT_Service_PsFontNameRec class_ = \+ { \+ get_ps_font_name_ \+ };++#else /* FT_CONFIG_OPTION_PIC */ ++#define FT_DEFINE_SERVICE_PSFONTNAMEREC(class_, get_ps_font_name_) \+ void \+ FT_Init_Class_##class_( FT_Library library, \+ FT_Service_PsFontNameRec* clazz) \+ { \+ FT_UNUSED(library); \+ clazz->get_ps_font_name = get_ps_font_name_; \+ } ++#endif /* FT_CONFIG_OPTION_PIC */ ++ /* */+++FT_END_HEADER+++#endif /* __SVPOSTNM_H__ */+++/* END */
+ include/freetype/internal/services/svpscmap.h view
@@ -0,0 +1,164 @@+/***************************************************************************/+/* */+/* svpscmap.h */+/* */+/* The FreeType PostScript charmap service (specification). */+/* */+/* Copyright 2003, 2006 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 __SVPSCMAP_H__+#define __SVPSCMAP_H__++#include FT_INTERNAL_OBJECTS_H+++FT_BEGIN_HEADER+++#define FT_SERVICE_ID_POSTSCRIPT_CMAPS "postscript-cmaps"+++ /*+ * Adobe glyph name to unicode value.+ */+ typedef FT_UInt32+ (*PS_Unicode_ValueFunc)( const char* glyph_name );++ /*+ * Macintosh name id to glyph name. NULL if invalid index.+ */+ typedef const char*+ (*PS_Macintosh_NameFunc)( FT_UInt name_index );++ /*+ * Adobe standard string ID to glyph name. NULL if invalid index.+ */+ typedef const char*+ (*PS_Adobe_Std_StringsFunc)( FT_UInt string_index );+++ /*+ * Simple unicode -> glyph index charmap built from font glyph names+ * table.+ */+ typedef struct PS_UniMap_+ {+ FT_UInt32 unicode; /* bit 31 set: is glyph variant */+ FT_UInt glyph_index;++ } PS_UniMap;+++ typedef struct PS_UnicodesRec_* PS_Unicodes;++ typedef struct PS_UnicodesRec_+ {+ FT_CMapRec cmap;+ FT_UInt num_maps;+ PS_UniMap* maps;++ } PS_UnicodesRec;+++ /*+ * A function which returns a glyph name for a given index. Returns+ * NULL if invalid index.+ */+ typedef const char*+ (*PS_GetGlyphNameFunc)( FT_Pointer data,+ FT_UInt string_index );++ /*+ * A function used to release the glyph name returned by+ * PS_GetGlyphNameFunc, when needed+ */+ typedef void+ (*PS_FreeGlyphNameFunc)( FT_Pointer data,+ const char* name );++ typedef FT_Error+ (*PS_Unicodes_InitFunc)( FT_Memory memory,+ PS_Unicodes unicodes,+ FT_UInt num_glyphs,+ PS_GetGlyphNameFunc get_glyph_name,+ PS_FreeGlyphNameFunc free_glyph_name,+ FT_Pointer glyph_data );++ typedef FT_UInt+ (*PS_Unicodes_CharIndexFunc)( PS_Unicodes unicodes,+ FT_UInt32 unicode );++ typedef FT_UInt32+ (*PS_Unicodes_CharNextFunc)( PS_Unicodes unicodes,+ FT_UInt32 *unicode );+++ FT_DEFINE_SERVICE( PsCMaps )+ {+ PS_Unicode_ValueFunc unicode_value;++ PS_Unicodes_InitFunc unicodes_init;+ PS_Unicodes_CharIndexFunc unicodes_char_index;+ PS_Unicodes_CharNextFunc unicodes_char_next;++ PS_Macintosh_NameFunc macintosh_name;+ PS_Adobe_Std_StringsFunc adobe_std_strings;+ const unsigned short* adobe_std_encoding;+ const unsigned short* adobe_expert_encoding;+ };+++#ifndef FT_CONFIG_OPTION_PIC++#define FT_DEFINE_SERVICE_PSCMAPSREC(class_, unicode_value_, unicodes_init_, \+ unicodes_char_index_, unicodes_char_next_, macintosh_name_, \+ adobe_std_strings_, adobe_std_encoding_, adobe_expert_encoding_) \+ static const FT_Service_PsCMapsRec class_ = \+ { \+ unicode_value_, unicodes_init_, \+ unicodes_char_index_, unicodes_char_next_, macintosh_name_, \+ adobe_std_strings_, adobe_std_encoding_, adobe_expert_encoding_ \+ };++#else /* FT_CONFIG_OPTION_PIC */ ++#define FT_DEFINE_SERVICE_PSCMAPSREC(class_, unicode_value_, unicodes_init_, \+ unicodes_char_index_, unicodes_char_next_, macintosh_name_, \+ adobe_std_strings_, adobe_std_encoding_, adobe_expert_encoding_) \+ void \+ FT_Init_Class_##class_( FT_Library library, \+ FT_Service_PsCMapsRec* clazz) \+ { \+ FT_UNUSED(library); \+ clazz->unicode_value = unicode_value_; \+ clazz->unicodes_init = unicodes_init_; \+ clazz->unicodes_char_index = unicodes_char_index_; \+ clazz->unicodes_char_next = unicodes_char_next_; \+ clazz->macintosh_name = macintosh_name_; \+ clazz->adobe_std_strings = adobe_std_strings_; \+ clazz->adobe_std_encoding = adobe_std_encoding_; \+ clazz->adobe_expert_encoding = adobe_expert_encoding_; \+ } ++#endif /* FT_CONFIG_OPTION_PIC */ ++ /* */+++FT_END_HEADER+++#endif /* __SVPSCMAP_H__ */+++/* END */
+ include/freetype/internal/services/svpsinfo.h view
@@ -0,0 +1,92 @@+/***************************************************************************/+/* */+/* svpsinfo.h */+/* */+/* The FreeType PostScript info service (specification). */+/* */+/* Copyright 2003, 2004, 2009 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 __SVPSINFO_H__+#define __SVPSINFO_H__++#include FT_INTERNAL_SERVICE_H+#include FT_INTERNAL_TYPE1_TYPES_H+++FT_BEGIN_HEADER+++#define FT_SERVICE_ID_POSTSCRIPT_INFO "postscript-info"+++ typedef FT_Error+ (*PS_GetFontInfoFunc)( FT_Face face,+ PS_FontInfoRec* afont_info );++ typedef FT_Error+ (*PS_GetFontExtraFunc)( FT_Face face,+ PS_FontExtraRec* afont_extra );++ typedef FT_Int+ (*PS_HasGlyphNamesFunc)( FT_Face face );++ typedef FT_Error+ (*PS_GetFontPrivateFunc)( FT_Face face,+ PS_PrivateRec* afont_private );+++ FT_DEFINE_SERVICE( PsInfo )+ {+ PS_GetFontInfoFunc ps_get_font_info;+ PS_GetFontExtraFunc ps_get_font_extra;+ PS_HasGlyphNamesFunc ps_has_glyph_names;+ PS_GetFontPrivateFunc ps_get_font_private;+ };++#ifndef FT_CONFIG_OPTION_PIC++#define FT_DEFINE_SERVICE_PSINFOREC(class_, get_font_info_, \+ ps_get_font_extra_, has_glyph_names_, get_font_private_) \+ static const FT_Service_PsInfoRec class_ = \+ { \+ get_font_info_, ps_get_font_extra_, has_glyph_names_, \+ get_font_private_ \+ };++#else /* FT_CONFIG_OPTION_PIC */ ++#define FT_DEFINE_SERVICE_PSINFOREC(class_, get_font_info_, \+ ps_get_font_extra_, has_glyph_names_, get_font_private_) \+ void \+ FT_Init_Class_##class_( FT_Library library, \+ FT_Service_PsInfoRec* clazz) \+ { \+ FT_UNUSED(library); \+ clazz->ps_get_font_info = get_font_info_; \+ clazz->ps_get_font_extra = ps_get_font_extra_; \+ clazz->ps_has_glyph_names = has_glyph_names_; \+ clazz->ps_get_font_private = get_font_private_; \+ } ++#endif /* FT_CONFIG_OPTION_PIC */ ++ /* */+++FT_END_HEADER+++#endif /* __SVPSINFO_H__ */+++/* END */
+ include/freetype/internal/services/svsfnt.h view
@@ -0,0 +1,102 @@+/***************************************************************************/+/* */+/* svsfnt.h */+/* */+/* The FreeType SFNT table loading service (specification). */+/* */+/* Copyright 2003, 2004 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 __SVSFNT_H__+#define __SVSFNT_H__++#include FT_INTERNAL_SERVICE_H+#include FT_TRUETYPE_TABLES_H+++FT_BEGIN_HEADER+++ /*+ * SFNT table loading service.+ */++#define FT_SERVICE_ID_SFNT_TABLE "sfnt-table"+++ /*+ * Used to implement FT_Load_Sfnt_Table().+ */+ typedef FT_Error+ (*FT_SFNT_TableLoadFunc)( FT_Face face,+ FT_ULong tag,+ FT_Long offset,+ FT_Byte* buffer,+ FT_ULong* length );++ /*+ * Used to implement FT_Get_Sfnt_Table().+ */+ typedef void*+ (*FT_SFNT_TableGetFunc)( FT_Face face,+ FT_Sfnt_Tag tag );+++ /*+ * Used to implement FT_Sfnt_Table_Info().+ */+ typedef FT_Error+ (*FT_SFNT_TableInfoFunc)( FT_Face face,+ FT_UInt idx,+ FT_ULong *tag,+ FT_ULong *offset,+ FT_ULong *length );+++ FT_DEFINE_SERVICE( SFNT_Table )+ {+ FT_SFNT_TableLoadFunc load_table;+ FT_SFNT_TableGetFunc get_table;+ FT_SFNT_TableInfoFunc table_info;+ };++#ifndef FT_CONFIG_OPTION_PIC++#define FT_DEFINE_SERVICE_SFNT_TABLEREC(class_, load_, get_, info_) \+ static const FT_Service_SFNT_TableRec class_ = \+ { \+ load_, get_, info_ \+ };++#else /* FT_CONFIG_OPTION_PIC */ ++#define FT_DEFINE_SERVICE_SFNT_TABLEREC(class_, load_, get_, info_) \+ void \+ FT_Init_Class_##class_( FT_Service_SFNT_TableRec* clazz ) \+ { \+ clazz->load_table = load_; \+ clazz->get_table = get_; \+ clazz->table_info = info_; \+ } ++#endif /* FT_CONFIG_OPTION_PIC */ ++ /* */+++FT_END_HEADER+++#endif /* __SVSFNT_H__ */+++/* END */
+ include/freetype/internal/services/svttcmap.h view
@@ -0,0 +1,106 @@+/***************************************************************************/+/* */+/* svttcmap.h */+/* */+/* The FreeType TrueType/sfnt cmap extra information service. */+/* */+/* Copyright 2003 by */+/* Masatake YAMATO, Redhat K.K. */+/* */+/* Copyright 2003, 2008 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. */+/* */+/***************************************************************************/++/* Development of this service is support of+ Information-technology Promotion Agency, Japan. */++#ifndef __SVTTCMAP_H__+#define __SVTTCMAP_H__++#include FT_INTERNAL_SERVICE_H+#include FT_TRUETYPE_TABLES_H+++FT_BEGIN_HEADER+++#define FT_SERVICE_ID_TT_CMAP "tt-cmaps"+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_CMapInfo */+ /* */+ /* <Description> */+ /* A structure used to store TrueType/sfnt specific cmap information */+ /* which is not covered by the generic @FT_CharMap structure. This */+ /* structure can be accessed with the @FT_Get_TT_CMap_Info function. */+ /* */+ /* <Fields> */+ /* language :: */+ /* The language ID used in Mac fonts. Definitions of values are in */+ /* freetype/ttnameid.h. */+ /* */+ /* format :: */+ /* The cmap format. OpenType 1.5 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). */+ /* */+ typedef struct TT_CMapInfo_+ {+ FT_ULong language;+ FT_Long format;++ } TT_CMapInfo;+++ typedef FT_Error+ (*TT_CMap_Info_GetFunc)( FT_CharMap charmap,+ TT_CMapInfo *cmap_info );+++ FT_DEFINE_SERVICE( TTCMaps )+ {+ TT_CMap_Info_GetFunc get_cmap_info;+ };++#ifndef FT_CONFIG_OPTION_PIC++#define FT_DEFINE_SERVICE_TTCMAPSREC(class_, get_cmap_info_) \+ static const FT_Service_TTCMapsRec class_ = \+ { \+ get_cmap_info_ \+ };++#else /* FT_CONFIG_OPTION_PIC */ ++#define FT_DEFINE_SERVICE_TTCMAPSREC(class_, get_cmap_info_) \+ void \+ FT_Init_Class_##class_( FT_Library library, \+ FT_Service_TTCMapsRec* clazz) \+ { \+ FT_UNUSED(library); \+ clazz->get_cmap_info = get_cmap_info_; \+ } ++#endif /* FT_CONFIG_OPTION_PIC */ ++ /* */+++FT_END_HEADER++#endif /* __SVTTCMAP_H__ */+++/* END */
+ include/freetype/internal/services/svtteng.h view
@@ -0,0 +1,53 @@+/***************************************************************************/+/* */+/* svtteng.h */+/* */+/* The FreeType TrueType engine query service (specification). */+/* */+/* Copyright 2006 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 __SVTTENG_H__+#define __SVTTENG_H__++#include FT_INTERNAL_SERVICE_H+#include FT_MODULE_H+++FT_BEGIN_HEADER+++ /*+ * SFNT table loading service.+ */++#define FT_SERVICE_ID_TRUETYPE_ENGINE "truetype-engine"++ /*+ * Used to implement FT_Get_TrueType_Engine_Type+ */++ FT_DEFINE_SERVICE( TrueTypeEngine )+ {+ FT_TrueTypeEngineType engine_type;+ };++ /* */+++FT_END_HEADER+++#endif /* __SVTTENG_H__ */+++/* END */
+ include/freetype/internal/services/svttglyf.h view
@@ -0,0 +1,67 @@+/***************************************************************************/+/* */+/* svttglyf.h */+/* */+/* The FreeType TrueType glyph service. */+/* */+/* Copyright 2007 by David Turner. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/++#ifndef __SVTTGLYF_H__+#define __SVTTGLYF_H__++#include FT_INTERNAL_SERVICE_H+#include FT_TRUETYPE_TABLES_H+++FT_BEGIN_HEADER+++#define FT_SERVICE_ID_TT_GLYF "tt-glyf"+++ typedef FT_ULong+ (*TT_Glyf_GetLocationFunc)( FT_Face face,+ FT_UInt gindex,+ FT_ULong *psize );++ FT_DEFINE_SERVICE( TTGlyf )+ {+ TT_Glyf_GetLocationFunc get_location;+ };++#ifndef FT_CONFIG_OPTION_PIC++#define FT_DEFINE_SERVICE_TTGLYFREC(class_, get_location_ ) \+ static const FT_Service_TTGlyfRec class_ = \+ { \+ get_location_ \+ };++#else /* FT_CONFIG_OPTION_PIC */ ++#define FT_DEFINE_SERVICE_TTGLYFREC(class_, get_location_ ) \+ void \+ FT_Init_Class_##class_( FT_Service_TTGlyfRec* clazz ) \+ { \+ clazz->get_location = get_location_; \+ } ++#endif /* FT_CONFIG_OPTION_PIC */ ++ /* */+++FT_END_HEADER++#endif /* __SVTTGLYF_H__ */+++/* END */
+ include/freetype/internal/services/svwinfnt.h view
@@ -0,0 +1,50 @@+/***************************************************************************/+/* */+/* svwinfnt.h */+/* */+/* The FreeType Windows FNT/FONT service (specification). */+/* */+/* Copyright 2003 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 __SVWINFNT_H__+#define __SVWINFNT_H__++#include FT_INTERNAL_SERVICE_H+#include FT_WINFONTS_H+++FT_BEGIN_HEADER+++#define FT_SERVICE_ID_WINFNT "winfonts"++ typedef FT_Error+ (*FT_WinFnt_GetHeaderFunc)( FT_Face face,+ FT_WinFNT_HeaderRec *aheader );+++ FT_DEFINE_SERVICE( WinFnt )+ {+ FT_WinFnt_GetHeaderFunc get_header;+ };++ /* */+++FT_END_HEADER+++#endif /* __SVWINFNT_H__ */+++/* END */
+ include/freetype/internal/services/svxf86nm.h view
@@ -0,0 +1,55 @@+/***************************************************************************/+/* */+/* svxf86nm.h */+/* */+/* The FreeType XFree86 services (specification only). */+/* */+/* Copyright 2003 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 __SVXF86NM_H__+#define __SVXF86NM_H__++#include FT_INTERNAL_SERVICE_H+++FT_BEGIN_HEADER+++ /*+ * A trivial service used to return the name of a face's font driver,+ * according to the XFree86 nomenclature. Note that the service data+ * is a simple constant string pointer.+ */++#define FT_SERVICE_ID_XF86_NAME "xf86-driver-name"++#define FT_XF86_FORMAT_TRUETYPE "TrueType"+#define FT_XF86_FORMAT_TYPE_1 "Type 1"+#define FT_XF86_FORMAT_BDF "BDF"+#define FT_XF86_FORMAT_PCF "PCF"+#define FT_XF86_FORMAT_TYPE_42 "Type 42"+#define FT_XF86_FORMAT_CID "CID Type 1"+#define FT_XF86_FORMAT_CFF "CFF"+#define FT_XF86_FORMAT_PFR "PFR"+#define FT_XF86_FORMAT_WINFNT "Windows FNT"++ /* */+++FT_END_HEADER+++#endif /* __SVXF86NM_H__ */+++/* END */
+ include/freetype/internal/sfnt.h view
@@ -0,0 +1,897 @@+/***************************************************************************/+/* */+/* sfnt.h */+/* */+/* High-level `sfnt' driver interface (specification). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006 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 __SFNT_H__+#define __SFNT_H__+++#include <ft2build.h>+#include FT_INTERNAL_DRIVER_H+#include FT_INTERNAL_TRUETYPE_TYPES_H+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* TT_Init_Face_Func */+ /* */+ /* <Description> */+ /* First part of the SFNT face object initialization. This finds */+ /* the face in a SFNT file or collection, and load its format tag in */+ /* face->format_tag. */+ /* */+ /* <Input> */+ /* stream :: The input stream. */+ /* */+ /* face :: A handle to the target face object. */+ /* */+ /* face_index :: The index of the TrueType font, if we are opening a */+ /* collection. */+ /* */+ /* num_params :: The number of additional parameters. */+ /* */+ /* params :: Optional additional parameters. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ /* <Note> */+ /* The stream cursor must be at the font file's origin. */+ /* */+ /* This function recognizes fonts embedded in a `TrueType */+ /* collection'. */+ /* */+ /* Once the format tag has been validated by the font driver, it */+ /* should then call the TT_Load_Face_Func() callback to read the rest */+ /* of the SFNT tables in the object. */+ /* */+ typedef FT_Error+ (*TT_Init_Face_Func)( FT_Stream stream,+ TT_Face face,+ FT_Int face_index,+ FT_Int num_params,+ FT_Parameter* params );+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* TT_Load_Face_Func */+ /* */+ /* <Description> */+ /* Second part of the SFNT face object initialization. This loads */+ /* the common SFNT tables (head, OS/2, maxp, metrics, etc.) in the */+ /* face object. */+ /* */+ /* <Input> */+ /* stream :: The input stream. */+ /* */+ /* face :: A handle to the target face object. */+ /* */+ /* face_index :: The index of the TrueType font, if we are opening a */+ /* collection. */+ /* */+ /* num_params :: The number of additional parameters. */+ /* */+ /* params :: Optional additional parameters. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ /* <Note> */+ /* This function must be called after TT_Init_Face_Func(). */+ /* */+ typedef FT_Error+ (*TT_Load_Face_Func)( FT_Stream stream,+ TT_Face face,+ FT_Int face_index,+ FT_Int num_params,+ FT_Parameter* params );+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* TT_Done_Face_Func */+ /* */+ /* <Description> */+ /* A callback used to delete the common SFNT data from a face. */+ /* */+ /* <Input> */+ /* face :: A handle to the target face object. */+ /* */+ /* <Note> */+ /* This function does NOT destroy the face object. */+ /* */+ typedef void+ (*TT_Done_Face_Func)( TT_Face face );+++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* TT_Load_SFNT_HeaderRec_Func */+ /* */+ /* <Description> */+ /* Loads the header of a SFNT font file. Supports collections. */+ /* */+ /* <Input> */+ /* face :: A handle to the target face object. */+ /* */+ /* stream :: The input stream. */+ /* */+ /* face_index :: The index of the TrueType font, if we are opening a */+ /* collection. */+ /* */+ /* <Output> */+ /* sfnt :: The SFNT header. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ /* <Note> */+ /* The stream cursor must be at the font file's origin. */+ /* */+ /* This function recognizes fonts embedded in a `TrueType */+ /* collection'. */+ /* */+ /* This function checks that the header is valid by looking at the */+ /* values of `search_range', `entry_selector', and `range_shift'. */+ /* */+ typedef FT_Error+ (*TT_Load_SFNT_HeaderRec_Func)( TT_Face face,+ FT_Stream stream,+ FT_Long face_index,+ SFNT_Header sfnt );+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* TT_Load_Directory_Func */+ /* */+ /* <Description> */+ /* Loads the table directory into a face object. */+ /* */+ /* <Input> */+ /* face :: A handle to the target face object. */+ /* */+ /* stream :: The input stream. */+ /* */+ /* sfnt :: The SFNT header. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ /* <Note> */+ /* The stream cursor must be on the first byte after the 4-byte font */+ /* format tag. This is the case just after a call to */+ /* TT_Load_Format_Tag(). */+ /* */+ typedef FT_Error+ (*TT_Load_Directory_Func)( TT_Face face,+ FT_Stream stream,+ SFNT_Header sfnt );++#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* TT_Load_Any_Func */+ /* */+ /* <Description> */+ /* Load any font table into client memory. */+ /* */+ /* <Input> */+ /* face :: The face object to look for. */+ /* */+ /* tag :: The tag of table to load. Use the value 0 if you want */+ /* to access the whole font file, else set this parameter */+ /* to a valid TrueType table tag that you can forge with */+ /* the MAKE_TT_TAG macro. */+ /* */+ /* offset :: The starting offset in the table (or the file if */+ /* tag == 0). */+ /* */+ /* length :: The address of the decision variable: */+ /* */+ /* If length == NULL: */+ /* Loads the whole table. Returns an error if */+ /* `offset' == 0! */+ /* */+ /* If *length == 0: */+ /* Exits immediately; returning the length of the given */+ /* table or of the font file, depending on the value of */+ /* `tag'. */+ /* */+ /* If *length != 0: */+ /* Loads the next `length' bytes of table or font, */+ /* starting at offset `offset' (in table or font too). */+ /* */+ /* <Output> */+ /* buffer :: The address of target buffer. */+ /* */+ /* <Return> */+ /* TrueType error code. 0 means success. */+ /* */+ typedef FT_Error+ (*TT_Load_Any_Func)( TT_Face face,+ FT_ULong tag,+ FT_Long offset,+ FT_Byte *buffer,+ FT_ULong* length );+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* TT_Find_SBit_Image_Func */+ /* */+ /* <Description> */+ /* Check whether an embedded bitmap (an `sbit') exists for a given */+ /* glyph, at a given strike. */+ /* */+ /* <Input> */+ /* face :: The target face object. */+ /* */+ /* glyph_index :: The glyph index. */+ /* */+ /* strike_index :: The current strike index. */+ /* */+ /* <Output> */+ /* arange :: The SBit range containing the glyph index. */+ /* */+ /* astrike :: The SBit strike containing the glyph index. */+ /* */+ /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. Returns */+ /* SFNT_Err_Invalid_Argument if no sbit exists for the requested */+ /* glyph. */+ /* */+ typedef FT_Error+ (*TT_Find_SBit_Image_Func)( TT_Face face,+ FT_UInt glyph_index,+ FT_ULong strike_index,+ TT_SBit_Range *arange,+ TT_SBit_Strike *astrike,+ FT_ULong *aglyph_offset );+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* TT_Load_SBit_Metrics_Func */+ /* */+ /* <Description> */+ /* Get the big metrics for a given embedded bitmap. */+ /* */+ /* <Input> */+ /* stream :: The input stream. */+ /* */+ /* range :: The SBit range containing the glyph. */+ /* */+ /* <Output> */+ /* big_metrics :: A big SBit metrics structure for the glyph. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ /* <Note> */+ /* The stream cursor must be positioned at the glyph's offset within */+ /* the `EBDT' table before the call. */+ /* */+ /* If the image format uses variable metrics, the stream cursor is */+ /* positioned just after the metrics header in the `EBDT' table on */+ /* function exit. */+ /* */+ typedef FT_Error+ (*TT_Load_SBit_Metrics_Func)( FT_Stream stream,+ TT_SBit_Range range,+ TT_SBit_Metrics metrics );+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* TT_Load_SBit_Image_Func */+ /* */+ /* <Description> */+ /* Load a given glyph sbit image from the font resource. This also */+ /* returns its metrics. */+ /* */+ /* <Input> */+ /* face :: */+ /* The target face object. */+ /* */+ /* strike_index :: */+ /* The strike index. */+ /* */+ /* glyph_index :: */+ /* The current glyph index. */+ /* */+ /* load_flags :: */+ /* The current load flags. */+ /* */+ /* stream :: */+ /* The input stream. */+ /* */+ /* <Output> */+ /* amap :: */+ /* The target pixmap. */+ /* */+ /* ametrics :: */+ /* A big sbit metrics structure for the glyph image. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. Returns an error if no */+ /* glyph sbit exists for the index. */+ /* */+ /* <Note> */+ /* The `map.buffer' field is always freed before the glyph is loaded. */+ /* */+ typedef FT_Error+ (*TT_Load_SBit_Image_Func)( TT_Face face,+ FT_ULong strike_index,+ FT_UInt glyph_index,+ FT_UInt load_flags,+ FT_Stream stream,+ FT_Bitmap *amap,+ TT_SBit_MetricsRec *ametrics );+++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* TT_Set_SBit_Strike_OldFunc */+ /* */+ /* <Description> */+ /* Select an sbit strike for a given size request. */+ /* */+ /* <Input> */+ /* face :: The target face object. */+ /* */+ /* req :: The size request. */+ /* */+ /* <Output> */+ /* astrike_index :: The index of the sbit strike. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. Returns an error if no */+ /* sbit strike exists for the selected ppem values. */+ /* */+ typedef FT_Error+ (*TT_Set_SBit_Strike_OldFunc)( TT_Face face,+ FT_UInt x_ppem,+ FT_UInt y_ppem,+ FT_ULong* astrike_index );+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* TT_CharMap_Load_Func */+ /* */+ /* <Description> */+ /* Loads a given TrueType character map into memory. */+ /* */+ /* <Input> */+ /* face :: A handle to the parent face object. */+ /* */+ /* stream :: A handle to the current stream object. */+ /* */+ /* <InOut> */+ /* cmap :: A pointer to a cmap object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ /* <Note> */+ /* The function assumes that the stream is already in use (i.e., */+ /* opened). In case of error, all partially allocated tables are */+ /* released. */+ /* */+ typedef FT_Error+ (*TT_CharMap_Load_Func)( TT_Face face,+ void* cmap,+ FT_Stream input );+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* TT_CharMap_Free_Func */+ /* */+ /* <Description> */+ /* Destroys a character mapping table. */+ /* */+ /* <Input> */+ /* face :: A handle to the parent face object. */+ /* */+ /* cmap :: A handle to a cmap object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ typedef FT_Error+ (*TT_CharMap_Free_Func)( TT_Face face,+ void* cmap );++#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* TT_Set_SBit_Strike_Func */+ /* */+ /* <Description> */+ /* Select an sbit strike for a given size request. */+ /* */+ /* <Input> */+ /* face :: The target face object. */+ /* */+ /* req :: The size request. */+ /* */+ /* <Output> */+ /* astrike_index :: The index of the sbit strike. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. Returns an error if no */+ /* sbit strike exists for the selected ppem values. */+ /* */+ typedef FT_Error+ (*TT_Set_SBit_Strike_Func)( TT_Face face,+ FT_Size_Request req,+ FT_ULong* astrike_index );+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* TT_Load_Strike_Metrics_Func */+ /* */+ /* <Description> */+ /* Load the metrics of a given strike. */+ /* */+ /* <Input> */+ /* face :: The target face object. */+ /* */+ /* strike_index :: The strike index. */+ /* */+ /* <Output> */+ /* metrics :: the metrics of the strike. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. Returns an error if no */+ /* such sbit strike exists. */+ /* */+ typedef FT_Error+ (*TT_Load_Strike_Metrics_Func)( TT_Face face,+ FT_ULong strike_index,+ FT_Size_Metrics* metrics );+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* TT_Get_PS_Name_Func */+ /* */+ /* <Description> */+ /* Get the PostScript glyph name of a glyph. */+ /* */+ /* <Input> */+ /* idx :: The glyph index. */+ /* */+ /* PSname :: The address of a string pointer. Will be NULL in case */+ /* of error, otherwise it is a pointer to the glyph name. */+ /* */+ /* You must not modify the returned string! */+ /* */+ /* <Output> */+ /* FreeType error code. 0 means success. */+ /* */+ typedef FT_Error+ (*TT_Get_PS_Name_Func)( TT_Face face,+ FT_UInt idx,+ FT_String** PSname );+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* TT_Load_Metrics_Func */+ /* */+ /* <Description> */+ /* Load a metrics table, which is a table with a horizontal and a */+ /* vertical version. */+ /* */+ /* <Input> */+ /* face :: A handle to the target face object. */+ /* */+ /* stream :: The input stream. */+ /* */+ /* vertical :: A boolean flag. If set, load the vertical one. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ typedef FT_Error+ (*TT_Load_Metrics_Func)( TT_Face face,+ FT_Stream stream,+ FT_Bool vertical );+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* TT_Get_Metrics_Func */+ /* */+ /* <Description> */+ /* Load the horizontal or vertical header in a face object. */+ /* */+ /* <Input> */+ /* face :: A handle to the target face object. */+ /* */+ /* stream :: The input stream. */+ /* */+ /* vertical :: A boolean flag. If set, load vertical metrics. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ typedef FT_Error+ (*TT_Get_Metrics_Func)( TT_Face face,+ FT_Bool vertical,+ FT_UInt gindex,+ FT_Short* abearing,+ FT_UShort* aadvance );+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* TT_Load_Table_Func */+ /* */+ /* <Description> */+ /* Load a given TrueType table. */+ /* */+ /* <Input> */+ /* face :: A handle to the target face object. */+ /* */+ /* stream :: The input stream. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ /* <Note> */+ /* The function uses `face->goto_table' to seek the stream to the */+ /* start of the table, except while loading the font directory. */+ /* */+ typedef FT_Error+ (*TT_Load_Table_Func)( TT_Face face,+ FT_Stream stream );+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* TT_Free_Table_Func */+ /* */+ /* <Description> */+ /* Free a given TrueType table. */+ /* */+ /* <Input> */+ /* face :: A handle to the target face object. */+ /* */+ typedef void+ (*TT_Free_Table_Func)( TT_Face face );+++ /*+ * @functype:+ * TT_Face_GetKerningFunc+ *+ * @description:+ * Return the horizontal kerning value between two glyphs.+ *+ * @input:+ * face :: A handle to the source face object.+ * left_glyph :: The left glyph index.+ * right_glyph :: The right glyph index.+ *+ * @return:+ * The kerning value in font units.+ */+ typedef FT_Int+ (*TT_Face_GetKerningFunc)( TT_Face face,+ FT_UInt left_glyph,+ FT_UInt right_glyph );+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* SFNT_Interface */+ /* */+ /* <Description> */+ /* This structure holds pointers to the functions used to load and */+ /* free the basic tables that are required in a `sfnt' font file. */+ /* */+ /* <Fields> */+ /* Check the various xxx_Func() descriptions for details. */+ /* */+ typedef struct SFNT_Interface_+ {+ TT_Loader_GotoTableFunc goto_table;++ TT_Init_Face_Func init_face;+ TT_Load_Face_Func load_face;+ TT_Done_Face_Func done_face;+ FT_Module_Requester get_interface;++ TT_Load_Any_Func load_any;++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS+ TT_Load_SFNT_HeaderRec_Func load_sfnt_header;+ TT_Load_Directory_Func load_directory;+#endif++ /* these functions are called by `load_face' but they can also */+ /* be called from external modules, if there is a need to do so */+ TT_Load_Table_Func load_head;+ TT_Load_Metrics_Func load_hhea;+ TT_Load_Table_Func load_cmap;+ TT_Load_Table_Func load_maxp;+ TT_Load_Table_Func load_os2;+ TT_Load_Table_Func load_post;++ TT_Load_Table_Func load_name;+ TT_Free_Table_Func free_name;++ /* optional tables */+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS+ TT_Load_Table_Func load_hdmx_stub;+ TT_Free_Table_Func free_hdmx_stub;+#endif++ /* this field was called `load_kerning' up to version 2.1.10 */+ TT_Load_Table_Func load_kern;++ TT_Load_Table_Func load_gasp;+ TT_Load_Table_Func load_pclt;++ /* see `ttload.h'; this field was called `load_bitmap_header' up to */+ /* version 2.1.10 */+ TT_Load_Table_Func load_bhed;++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS++ /* see `ttsbit.h' */+ TT_Set_SBit_Strike_OldFunc set_sbit_strike_stub;+ TT_Load_Table_Func load_sbits_stub;++ /*+ * The following two fields appeared in version 2.1.8, and were placed+ * between `load_sbits' and `load_sbit_image'. We support them as a+ * special exception since they are used by Xfont library within the+ * X.Org xserver, and because the probability that other rogue clients+ * use the other version 2.1.7 fields below is _extremely_ low.+ *+ * Note that this forces us to disable an interesting memory-saving+ * optimization though...+ */++ TT_Find_SBit_Image_Func find_sbit_image;+ TT_Load_SBit_Metrics_Func load_sbit_metrics;++#endif++ TT_Load_SBit_Image_Func load_sbit_image;++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS+ TT_Free_Table_Func free_sbits_stub;+#endif++ /* see `ttpost.h' */+ TT_Get_PS_Name_Func get_psname;+ TT_Free_Table_Func free_psnames;++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS+ TT_CharMap_Load_Func load_charmap_stub;+ TT_CharMap_Free_Func free_charmap_stub;+#endif++ /* starting here, the structure differs from version 2.1.7 */++ /* this field was introduced in version 2.1.8, named `get_psname' */+ TT_Face_GetKerningFunc get_kerning;++ /* new elements introduced after version 2.1.10 */++ /* load the font directory, i.e., the offset table and */+ /* the table directory */+ TT_Load_Table_Func load_font_dir;+ TT_Load_Metrics_Func load_hmtx;++ TT_Load_Table_Func load_eblc;+ TT_Free_Table_Func free_eblc;++ TT_Set_SBit_Strike_Func set_sbit_strike;+ TT_Load_Strike_Metrics_Func load_strike_metrics;++ TT_Get_Metrics_Func get_metrics;++ } SFNT_Interface;+++ /* transitional */+ typedef SFNT_Interface* SFNT_Service;++#ifndef FT_CONFIG_OPTION_PIC++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS+#define FT_DEFINE_DRIVERS_OLD_INTERNAL(a) \+ a, +#else+ #define FT_DEFINE_DRIVERS_OLD_INTERNAL(a)+#endif+#define FT_INTERNAL(a) \+ a, ++#define FT_DEFINE_SFNT_INTERFACE(class_, \+ goto_table_, init_face_, load_face_, done_face_, get_interface_, \+ load_any_, load_sfnt_header_, load_directory_, load_head_, \+ load_hhea_, load_cmap_, load_maxp_, load_os2_, load_post_, \+ load_name_, free_name_, load_hdmx_stub_, free_hdmx_stub_, \+ load_kern_, load_gasp_, load_pclt_, load_bhed_, \+ set_sbit_strike_stub_, load_sbits_stub_, find_sbit_image_, \+ load_sbit_metrics_, load_sbit_image_, free_sbits_stub_, \+ get_psname_, free_psnames_, load_charmap_stub_, free_charmap_stub_, \+ get_kerning_, load_font_dir_, load_hmtx_, load_eblc_, free_eblc_, \+ set_sbit_strike_, load_strike_metrics_, get_metrics_ ) \+ static const SFNT_Interface class_ = \+ { \+ FT_INTERNAL(goto_table_) \+ FT_INTERNAL(init_face_) \+ FT_INTERNAL(load_face_) \+ FT_INTERNAL(done_face_) \+ FT_INTERNAL(get_interface_) \+ FT_INTERNAL(load_any_) \+ FT_DEFINE_DRIVERS_OLD_INTERNAL(load_sfnt_header_) \+ FT_DEFINE_DRIVERS_OLD_INTERNAL(load_directory_) \+ FT_INTERNAL(load_head_) \+ FT_INTERNAL(load_hhea_) \+ FT_INTERNAL(load_cmap_) \+ FT_INTERNAL(load_maxp_) \+ FT_INTERNAL(load_os2_) \+ FT_INTERNAL(load_post_) \+ FT_INTERNAL(load_name_) \+ FT_INTERNAL(free_name_) \+ FT_DEFINE_DRIVERS_OLD_INTERNAL(load_hdmx_stub_) \+ FT_DEFINE_DRIVERS_OLD_INTERNAL(free_hdmx_stub_) \+ FT_INTERNAL(load_kern_) \+ FT_INTERNAL(load_gasp_) \+ FT_INTERNAL(load_pclt_) \+ FT_INTERNAL(load_bhed_) \+ FT_DEFINE_DRIVERS_OLD_INTERNAL(set_sbit_strike_stub_) \+ FT_DEFINE_DRIVERS_OLD_INTERNAL(load_sbits_stub_) \+ FT_DEFINE_DRIVERS_OLD_INTERNAL(find_sbit_image_) \+ FT_DEFINE_DRIVERS_OLD_INTERNAL(load_sbit_metrics_) \+ FT_INTERNAL(load_sbit_image_) \+ FT_DEFINE_DRIVERS_OLD_INTERNAL(free_sbits_stub_) \+ FT_INTERNAL(get_psname_) \+ FT_INTERNAL(free_psnames_) \+ FT_DEFINE_DRIVERS_OLD_INTERNAL(load_charmap_stub_) \+ FT_DEFINE_DRIVERS_OLD_INTERNAL(free_charmap_stub_) \+ FT_INTERNAL(get_kerning_) \+ FT_INTERNAL(load_font_dir_) \+ FT_INTERNAL(load_hmtx_) \+ FT_INTERNAL(load_eblc_) \+ FT_INTERNAL(free_eblc_) \+ FT_INTERNAL(set_sbit_strike_) \+ FT_INTERNAL(load_strike_metrics_) \+ FT_INTERNAL(get_metrics_) \+ };++#else /* FT_CONFIG_OPTION_PIC */ ++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS+#define FT_DEFINE_DRIVERS_OLD_INTERNAL(a, a_) \+ clazz->a = a_;+#else+ #define FT_DEFINE_DRIVERS_OLD_INTERNAL(a, a_)+#endif+#define FT_INTERNAL(a, a_) \+ clazz->a = a_;++#define FT_DEFINE_SFNT_INTERFACE(class_, \+ goto_table_, init_face_, load_face_, done_face_, get_interface_, \+ load_any_, load_sfnt_header_, load_directory_, load_head_, \+ load_hhea_, load_cmap_, load_maxp_, load_os2_, load_post_, \+ load_name_, free_name_, load_hdmx_stub_, free_hdmx_stub_, \+ load_kern_, load_gasp_, load_pclt_, load_bhed_, \+ set_sbit_strike_stub_, load_sbits_stub_, find_sbit_image_, \+ load_sbit_metrics_, load_sbit_image_, free_sbits_stub_, \+ get_psname_, free_psnames_, load_charmap_stub_, free_charmap_stub_, \+ get_kerning_, load_font_dir_, load_hmtx_, load_eblc_, free_eblc_, \+ set_sbit_strike_, load_strike_metrics_, get_metrics_ ) \+ void \+ FT_Init_Class_##class_( FT_Library library, SFNT_Interface* clazz ) \+ { \+ FT_UNUSED(library); \+ FT_INTERNAL(goto_table,goto_table_) \+ FT_INTERNAL(init_face,init_face_) \+ FT_INTERNAL(load_face,load_face_) \+ FT_INTERNAL(done_face,done_face_) \+ FT_INTERNAL(get_interface,get_interface_) \+ FT_INTERNAL(load_any,load_any_) \+ FT_DEFINE_DRIVERS_OLD_INTERNAL(load_sfnt_header,load_sfnt_header_) \+ FT_DEFINE_DRIVERS_OLD_INTERNAL(load_directory,load_directory_) \+ FT_INTERNAL(load_head,load_head_) \+ FT_INTERNAL(load_hhea,load_hhea_) \+ FT_INTERNAL(load_cmap,load_cmap_) \+ FT_INTERNAL(load_maxp,load_maxp_) \+ FT_INTERNAL(load_os2,load_os2_) \+ FT_INTERNAL(load_post,load_post_) \+ FT_INTERNAL(load_name,load_name_) \+ FT_INTERNAL(free_name,free_name_) \+ FT_DEFINE_DRIVERS_OLD_INTERNAL(load_hdmx_stub,load_hdmx_stub_) \+ FT_DEFINE_DRIVERS_OLD_INTERNAL(free_hdmx_stub,free_hdmx_stub_) \+ FT_INTERNAL(load_kern,load_kern_) \+ FT_INTERNAL(load_gasp,load_gasp_) \+ FT_INTERNAL(load_pclt,load_pclt_) \+ FT_INTERNAL(load_bhed,load_bhed_) \+ FT_DEFINE_DRIVERS_OLD_INTERNAL(set_sbit_strike_stub,set_sbit_strike_stub_) \+ FT_DEFINE_DRIVERS_OLD_INTERNAL(load_sbits_stub,load_sbits_stub_) \+ FT_DEFINE_DRIVERS_OLD_INTERNAL(find_sbit_image,find_sbit_image_) \+ FT_DEFINE_DRIVERS_OLD_INTERNAL(load_sbit_metrics,load_sbit_metrics_) \+ FT_INTERNAL(load_sbit_image,load_sbit_image_) \+ FT_DEFINE_DRIVERS_OLD_INTERNAL(free_sbits_stub,free_sbits_stub_) \+ FT_INTERNAL(get_psname,get_psname_) \+ FT_INTERNAL(free_psnames,free_psnames_) \+ FT_DEFINE_DRIVERS_OLD_INTERNAL(load_charmap_stub,load_charmap_stub_) \+ FT_DEFINE_DRIVERS_OLD_INTERNAL(free_charmap_stub,free_charmap_stub_) \+ FT_INTERNAL(get_kerning,get_kerning_) \+ FT_INTERNAL(load_font_dir,load_font_dir_) \+ FT_INTERNAL(load_hmtx,load_hmtx_) \+ FT_INTERNAL(load_eblc,load_eblc_) \+ FT_INTERNAL(free_eblc,free_eblc_) \+ FT_INTERNAL(set_sbit_strike,set_sbit_strike_) \+ FT_INTERNAL(load_strike_metrics,load_strike_metrics_) \+ FT_INTERNAL(get_metrics,get_metrics_) \+ } ++#endif /* FT_CONFIG_OPTION_PIC */ ++FT_END_HEADER++#endif /* __SFNT_H__ */+++/* END */
+ include/freetype/internal/t1types.h view
@@ -0,0 +1,270 @@+/***************************************************************************/+/* */+/* t1types.h */+/* */+/* Basic Type1/Type2 type definitions and interface (specification */+/* only). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2008, 2009 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 __T1TYPES_H__+#define __T1TYPES_H__+++#include <ft2build.h>+#include FT_TYPE1_TABLES_H+#include FT_INTERNAL_POSTSCRIPT_HINTS_H+#include FT_INTERNAL_SERVICE_H+#include FT_SERVICE_POSTSCRIPT_CMAPS_H+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /*** ***/+ /*** ***/+ /*** REQUIRED TYPE1/TYPE2 TABLES DEFINITIONS ***/+ /*** ***/+ /*** ***/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* T1_EncodingRec */+ /* */+ /* <Description> */+ /* A structure modeling a custom encoding. */+ /* */+ /* <Fields> */+ /* num_chars :: The number of character codes in the encoding. */+ /* Usually 256. */+ /* */+ /* code_first :: The lowest valid character code in the encoding. */+ /* */+ /* code_last :: The highest valid character code in the encoding */+ /* + 1. When equal to code_first there are no valid */+ /* character codes. */+ /* */+ /* char_index :: An array of corresponding glyph indices. */+ /* */+ /* char_name :: An array of corresponding glyph names. */+ /* */+ typedef struct T1_EncodingRecRec_+ {+ FT_Int num_chars;+ FT_Int code_first;+ FT_Int code_last;++ FT_UShort* char_index;+ FT_String** char_name;++ } T1_EncodingRec, *T1_Encoding;+++ typedef enum T1_EncodingType_+ {+ T1_ENCODING_TYPE_NONE = 0,+ T1_ENCODING_TYPE_ARRAY,+ T1_ENCODING_TYPE_STANDARD,+ T1_ENCODING_TYPE_ISOLATIN1,+ T1_ENCODING_TYPE_EXPERT++ } T1_EncodingType;+++ /* used to hold extra data of PS_FontInfoRec that+ * cannot be stored in the publicly defined structure.+ *+ * Note these can't be blended with multiple-masters.+ */+ typedef struct PS_FontExtraRec_+ {+ FT_UShort fs_type;++ } PS_FontExtraRec;+++ typedef struct T1_FontRec_+ {+ PS_FontInfoRec font_info; /* font info dictionary */+ PS_FontExtraRec font_extra; /* font info extra fields */+ PS_PrivateRec private_dict; /* private dictionary */+ FT_String* font_name; /* top-level dictionary */++ T1_EncodingType encoding_type;+ T1_EncodingRec encoding;++ FT_Byte* subrs_block;+ FT_Byte* charstrings_block;+ FT_Byte* glyph_names_block;++ FT_Int num_subrs;+ FT_Byte** subrs;+ FT_PtrDist* subrs_len;++ FT_Int num_glyphs;+ FT_String** glyph_names; /* array of glyph names */+ FT_Byte** charstrings; /* array of glyph charstrings */+ FT_PtrDist* charstrings_len;++ FT_Byte paint_type;+ FT_Byte font_type;+ FT_Matrix font_matrix;+ FT_Vector font_offset;+ FT_BBox font_bbox;+ FT_Long font_id;++ FT_Fixed stroke_width;++ } T1_FontRec, *T1_Font;+++ typedef struct CID_SubrsRec_+ {+ FT_UInt num_subrs;+ FT_Byte** code;++ } CID_SubrsRec, *CID_Subrs;+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /*** ***/+ /*** ***/+ /*** AFM FONT INFORMATION STRUCTURES ***/+ /*** ***/+ /*** ***/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/++ typedef struct AFM_TrackKernRec_+ {+ FT_Int degree;+ FT_Fixed min_ptsize;+ FT_Fixed min_kern;+ FT_Fixed max_ptsize;+ FT_Fixed max_kern;++ } AFM_TrackKernRec, *AFM_TrackKern;++ typedef struct AFM_KernPairRec_+ {+ FT_Int index1;+ FT_Int index2;+ FT_Int x;+ FT_Int y;++ } AFM_KernPairRec, *AFM_KernPair;++ typedef struct AFM_FontInfoRec_+ {+ FT_Bool IsCIDFont;+ FT_BBox FontBBox;+ FT_Fixed Ascender;+ FT_Fixed Descender;+ AFM_TrackKern TrackKerns; /* free if non-NULL */+ FT_Int NumTrackKern;+ AFM_KernPair KernPairs; /* free if non-NULL */+ FT_Int NumKernPair;++ } AFM_FontInfoRec, *AFM_FontInfo;+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /*** ***/+ /*** ***/+ /*** ORIGINAL T1_FACE CLASS DEFINITION ***/+ /*** ***/+ /*** ***/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ typedef struct T1_FaceRec_* T1_Face;+ typedef struct CID_FaceRec_* CID_Face;+++ typedef struct T1_FaceRec_+ {+ FT_FaceRec root;+ T1_FontRec type1;+ const void* psnames;+ const void* psaux;+ const void* afm_data;+ FT_CharMapRec charmaprecs[2];+ FT_CharMap charmaps[2];++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS+ PS_Unicodes unicode_map;+#endif++ /* support for Multiple Masters fonts */+ PS_Blend blend;++ /* undocumented, optional: indices of subroutines that express */+ /* the NormalizeDesignVector and the ConvertDesignVector procedure, */+ /* respectively, as Type 2 charstrings; -1 if keywords not present */+ FT_Int ndv_idx;+ FT_Int cdv_idx;++ /* undocumented, optional: has the same meaning as len_buildchar */+ /* for Type 2 fonts; manipulated by othersubrs 19, 24, and 25 */+ FT_UInt len_buildchar;+ FT_Long* buildchar;++ /* since version 2.1 - interface to PostScript hinter */+ const void* pshinter;++ } T1_FaceRec;+++ typedef struct CID_FaceRec_+ {+ FT_FaceRec root;+ void* psnames;+ void* psaux;+ CID_FaceInfoRec cid;+ PS_FontExtraRec font_extra;+#if 0+ void* afm_data;+#endif+ CID_Subrs subrs;++ /* since version 2.1 - interface to PostScript hinter */+ void* pshinter;++ /* since version 2.1.8, but was originally positioned after `afm_data' */+ FT_Byte* binary_data; /* used if hex data has been converted */+ FT_Stream cid_stream;++ } CID_FaceRec;+++FT_END_HEADER++#endif /* __T1TYPES_H__ */+++/* END */
+ include/freetype/internal/tttypes.h view
@@ -0,0 +1,1543 @@+/***************************************************************************/+/* */+/* tttypes.h */+/* */+/* Basic SFNT/TrueType type definitions and interface (specification */+/* only). */+/* */+/* Copyright 1996-2001, 2002, 2004, 2005, 2006, 2007, 2008 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 __TTTYPES_H__+#define __TTTYPES_H__+++#include <ft2build.h>+#include FT_TRUETYPE_TABLES_H+#include FT_INTERNAL_OBJECTS_H++#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT+#include FT_MULTIPLE_MASTERS_H+#endif+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /*** ***/+ /*** ***/+ /*** REQUIRED TRUETYPE/OPENTYPE TABLES DEFINITIONS ***/+ /*** ***/+ /*** ***/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TTC_HeaderRec */+ /* */+ /* <Description> */+ /* TrueType collection header. This table contains the offsets of */+ /* the font headers of each distinct TrueType face in the file. */+ /* */+ /* <Fields> */+ /* tag :: Must be `ttc ' to indicate a TrueType collection. */+ /* */+ /* version :: The version number. */+ /* */+ /* count :: The number of faces in the collection. The */+ /* specification says this should be an unsigned long, but */+ /* we use a signed long since we need the value -1 for */+ /* specific purposes. */+ /* */+ /* offsets :: The offsets of the font headers, one per face. */+ /* */+ typedef struct TTC_HeaderRec_+ {+ FT_ULong tag;+ FT_Fixed version;+ FT_Long count;+ FT_ULong* offsets;++ } TTC_HeaderRec;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* SFNT_HeaderRec */+ /* */+ /* <Description> */+ /* SFNT file format header. */+ /* */+ /* <Fields> */+ /* format_tag :: The font format tag. */+ /* */+ /* num_tables :: The number of tables in file. */+ /* */+ /* search_range :: Must be `16 * (max power of 2 <= num_tables)'. */+ /* */+ /* entry_selector :: Must be log2 of `search_range / 16'. */+ /* */+ /* range_shift :: Must be `num_tables * 16 - search_range'. */+ /* */+ typedef struct SFNT_HeaderRec_+ {+ FT_ULong format_tag;+ FT_UShort num_tables;+ FT_UShort search_range;+ FT_UShort entry_selector;+ FT_UShort range_shift;++ FT_ULong offset; /* not in file */++ } SFNT_HeaderRec, *SFNT_Header;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_TableRec */+ /* */+ /* <Description> */+ /* This structure describes a given table of a TrueType font. */+ /* */+ /* <Fields> */+ /* Tag :: A four-bytes tag describing the table. */+ /* */+ /* CheckSum :: The table checksum. This value can be ignored. */+ /* */+ /* Offset :: The offset of the table from the start of the TrueType */+ /* font in its resource. */+ /* */+ /* Length :: The table length (in bytes). */+ /* */+ typedef struct TT_TableRec_+ {+ FT_ULong Tag; /* table type */+ FT_ULong CheckSum; /* table checksum */+ FT_ULong Offset; /* table file offset */+ FT_ULong Length; /* table length */++ } TT_TableRec, *TT_Table;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_LongMetricsRec */+ /* */+ /* <Description> */+ /* A structure modeling the long metrics of the `hmtx' and `vmtx' */+ /* TrueType tables. The values are expressed in font units. */+ /* */+ /* <Fields> */+ /* advance :: The advance width or height for the glyph. */+ /* */+ /* bearing :: The left-side or top-side bearing for the glyph. */+ /* */+ typedef struct TT_LongMetricsRec_+ {+ FT_UShort advance;+ FT_Short bearing;++ } TT_LongMetricsRec, *TT_LongMetrics;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* TT_ShortMetrics */+ /* */+ /* <Description> */+ /* A simple type to model the short metrics of the `hmtx' and `vmtx' */+ /* tables. */+ /* */+ typedef FT_Short TT_ShortMetrics;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_NameEntryRec */+ /* */+ /* <Description> */+ /* A structure modeling TrueType name records. Name records are used */+ /* to store important strings like family name, style name, */+ /* copyright, etc. in _localized_ versions (i.e., language, encoding, */+ /* etc). */+ /* */+ /* <Fields> */+ /* platformID :: The ID of the name's encoding platform. */+ /* */+ /* encodingID :: The platform-specific ID for the name's encoding. */+ /* */+ /* languageID :: The platform-specific ID for the name's language. */+ /* */+ /* nameID :: The ID specifying what kind of name this is. */+ /* */+ /* stringLength :: The length of the string in bytes. */+ /* */+ /* stringOffset :: The offset to the string in the `name' table. */+ /* */+ /* string :: A pointer to the string's bytes. Note that these */+ /* are usually UTF-16 encoded characters. */+ /* */+ typedef struct TT_NameEntryRec_+ {+ FT_UShort platformID;+ FT_UShort encodingID;+ FT_UShort languageID;+ FT_UShort nameID;+ FT_UShort stringLength;+ FT_ULong stringOffset;++ /* this last field is not defined in the spec */+ /* but used by the FreeType engine */++ FT_Byte* string;++ } TT_NameEntryRec, *TT_NameEntry;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_NameTableRec */+ /* */+ /* <Description> */+ /* A structure modeling the TrueType name table. */+ /* */+ /* <Fields> */+ /* format :: The format of the name table. */+ /* */+ /* numNameRecords :: The number of names in table. */+ /* */+ /* storageOffset :: The offset of the name table in the `name' */+ /* TrueType table. */+ /* */+ /* names :: An array of name records. */+ /* */+ /* stream :: the file's input stream. */+ /* */+ typedef struct TT_NameTableRec_+ {+ FT_UShort format;+ FT_UInt numNameRecords;+ FT_UInt storageOffset;+ TT_NameEntryRec* names;+ FT_Stream stream;++ } TT_NameTableRec, *TT_NameTable;+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /*** ***/+ /*** ***/+ /*** OPTIONAL TRUETYPE/OPENTYPE TABLES DEFINITIONS ***/+ /*** ***/+ /*** ***/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_GaspRangeRec */+ /* */+ /* <Description> */+ /* A tiny structure used to model a gasp range according to the */+ /* TrueType specification. */+ /* */+ /* <Fields> */+ /* maxPPEM :: The maximum ppem value to which `gaspFlag' applies. */+ /* */+ /* gaspFlag :: A flag describing the grid-fitting and anti-aliasing */+ /* modes to be used. */+ /* */+ typedef struct TT_GaspRangeRec_+ {+ FT_UShort maxPPEM;+ FT_UShort gaspFlag;++ } TT_GaspRangeRec, *TT_GaspRange;+++#define TT_GASP_GRIDFIT 0x01+#define TT_GASP_DOGRAY 0x02+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_GaspRec */+ /* */+ /* <Description> */+ /* A structure modeling the TrueType `gasp' table used to specify */+ /* grid-fitting and anti-aliasing behaviour. */+ /* */+ /* <Fields> */+ /* version :: The version number. */+ /* */+ /* numRanges :: The number of gasp ranges in table. */+ /* */+ /* gaspRanges :: An array of gasp ranges. */+ /* */+ typedef struct TT_Gasp_+ {+ FT_UShort version;+ FT_UShort numRanges;+ TT_GaspRange gaspRanges;++ } TT_GaspRec;+++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_HdmxEntryRec */+ /* */+ /* <Description> */+ /* A small structure used to model the pre-computed widths of a given */+ /* size. They are found in the `hdmx' table. */+ /* */+ /* <Fields> */+ /* ppem :: The pixels per EM value at which these metrics apply. */+ /* */+ /* max_width :: The maximum advance width for this metric. */+ /* */+ /* widths :: An array of widths. Note: These are 8-bit bytes. */+ /* */+ typedef struct TT_HdmxEntryRec_+ {+ FT_Byte ppem;+ FT_Byte max_width;+ FT_Byte* widths;++ } TT_HdmxEntryRec, *TT_HdmxEntry;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_HdmxRec */+ /* */+ /* <Description> */+ /* A structure used to model the `hdmx' table, which contains */+ /* pre-computed widths for a set of given sizes/dimensions. */+ /* */+ /* <Fields> */+ /* version :: The version number. */+ /* */+ /* num_records :: The number of hdmx records. */+ /* */+ /* records :: An array of hdmx records. */+ /* */+ typedef struct TT_HdmxRec_+ {+ FT_UShort version;+ FT_Short num_records;+ TT_HdmxEntry records;++ } TT_HdmxRec, *TT_Hdmx;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_Kern0_PairRec */+ /* */+ /* <Description> */+ /* A structure used to model a kerning pair for the kerning table */+ /* format 0. The engine now loads this table if it finds one in the */+ /* font file. */+ /* */+ /* <Fields> */+ /* left :: The index of the left glyph in pair. */+ /* */+ /* right :: The index of the right glyph in pair. */+ /* */+ /* value :: The kerning distance. A positive value spaces the */+ /* glyphs, a negative one makes them closer. */+ /* */+ typedef struct TT_Kern0_PairRec_+ {+ FT_UShort left; /* index of left glyph in pair */+ FT_UShort right; /* index of right glyph in pair */+ FT_FWord value; /* kerning value */++ } TT_Kern0_PairRec, *TT_Kern0_Pair;++#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /*** ***/+ /*** ***/+ /*** EMBEDDED BITMAPS SUPPORT ***/+ /*** ***/+ /*** ***/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_SBit_MetricsRec */+ /* */+ /* <Description> */+ /* A structure used to hold the big metrics of a given glyph bitmap */+ /* in a TrueType or OpenType font. These are usually found in the */+ /* `EBDT' (Microsoft) or `bloc' (Apple) table. */+ /* */+ /* <Fields> */+ /* height :: The glyph height in pixels. */+ /* */+ /* width :: The glyph width in pixels. */+ /* */+ /* horiBearingX :: The horizontal left bearing. */+ /* */+ /* horiBearingY :: The horizontal top bearing. */+ /* */+ /* horiAdvance :: The horizontal advance. */+ /* */+ /* vertBearingX :: The vertical left bearing. */+ /* */+ /* vertBearingY :: The vertical top bearing. */+ /* */+ /* vertAdvance :: The vertical advance. */+ /* */+ typedef struct TT_SBit_MetricsRec_+ {+ FT_Byte height;+ FT_Byte width;++ FT_Char horiBearingX;+ FT_Char horiBearingY;+ FT_Byte horiAdvance;++ FT_Char vertBearingX;+ FT_Char vertBearingY;+ FT_Byte vertAdvance;++ } TT_SBit_MetricsRec, *TT_SBit_Metrics;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_SBit_SmallMetricsRec */+ /* */+ /* <Description> */+ /* A structure used to hold the small metrics of a given glyph bitmap */+ /* in a TrueType or OpenType font. These are usually found in the */+ /* `EBDT' (Microsoft) or the `bdat' (Apple) table. */+ /* */+ /* <Fields> */+ /* height :: The glyph height in pixels. */+ /* */+ /* width :: The glyph width in pixels. */+ /* */+ /* bearingX :: The left-side bearing. */+ /* */+ /* bearingY :: The top-side bearing. */+ /* */+ /* advance :: The advance width or height. */+ /* */+ typedef struct TT_SBit_Small_Metrics_+ {+ FT_Byte height;+ FT_Byte width;++ FT_Char bearingX;+ FT_Char bearingY;+ FT_Byte advance;++ } TT_SBit_SmallMetricsRec, *TT_SBit_SmallMetrics;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_SBit_LineMetricsRec */+ /* */+ /* <Description> */+ /* A structure used to describe the text line metrics of a given */+ /* bitmap strike, for either a horizontal or vertical layout. */+ /* */+ /* <Fields> */+ /* ascender :: The ascender in pixels. */+ /* */+ /* descender :: The descender in pixels. */+ /* */+ /* max_width :: The maximum glyph width in pixels. */+ /* */+ /* caret_slope_enumerator :: Rise of the caret slope, typically set */+ /* to 1 for non-italic fonts. */+ /* */+ /* caret_slope_denominator :: Rise of the caret slope, typically set */+ /* to 0 for non-italic fonts. */+ /* */+ /* caret_offset :: Offset in pixels to move the caret for */+ /* proper positioning. */+ /* */+ /* min_origin_SB :: Minimum of horiBearingX (resp. */+ /* vertBearingY). */+ /* min_advance_SB :: Minimum of */+ /* */+ /* horizontal advance - */+ /* ( horiBearingX + width ) */+ /* */+ /* resp. */+ /* */+ /* vertical advance - */+ /* ( vertBearingY + height ) */+ /* */+ /* max_before_BL :: Maximum of horiBearingY (resp. */+ /* vertBearingY). */+ /* */+ /* min_after_BL :: Minimum of */+ /* */+ /* horiBearingY - height */+ /* */+ /* resp. */+ /* */+ /* vertBearingX - width */+ /* */+ /* pads :: Unused (to make the size of the record */+ /* a multiple of 32 bits. */+ /* */+ typedef struct TT_SBit_LineMetricsRec_+ {+ FT_Char ascender;+ FT_Char descender;+ FT_Byte max_width;+ FT_Char caret_slope_numerator;+ FT_Char caret_slope_denominator;+ FT_Char caret_offset;+ FT_Char min_origin_SB;+ FT_Char min_advance_SB;+ FT_Char max_before_BL;+ FT_Char min_after_BL;+ FT_Char pads[2];++ } TT_SBit_LineMetricsRec, *TT_SBit_LineMetrics;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_SBit_RangeRec */+ /* */+ /* <Description> */+ /* A TrueType/OpenType subIndexTable as defined in the `EBLC' */+ /* (Microsoft) or `bloc' (Apple) tables. */+ /* */+ /* <Fields> */+ /* first_glyph :: The first glyph index in the range. */+ /* */+ /* last_glyph :: The last glyph index in the range. */+ /* */+ /* index_format :: The format of index table. Valid values are 1 */+ /* to 5. */+ /* */+ /* image_format :: The format of `EBDT' image data. */+ /* */+ /* image_offset :: The offset to image data in `EBDT'. */+ /* */+ /* image_size :: For index formats 2 and 5. This is the size in */+ /* bytes of each glyph bitmap. */+ /* */+ /* big_metrics :: For index formats 2 and 5. This is the big */+ /* metrics for each glyph bitmap. */+ /* */+ /* num_glyphs :: For index formats 4 and 5. This is the number of */+ /* glyphs in the code array. */+ /* */+ /* glyph_offsets :: For index formats 1 and 3. */+ /* */+ /* glyph_codes :: For index formats 4 and 5. */+ /* */+ /* table_offset :: The offset of the index table in the `EBLC' */+ /* table. Only used during strike loading. */+ /* */+ typedef struct TT_SBit_RangeRec_+ {+ FT_UShort first_glyph;+ FT_UShort last_glyph;++ FT_UShort index_format;+ FT_UShort image_format;+ FT_ULong image_offset;++ FT_ULong image_size;+ TT_SBit_MetricsRec metrics;+ FT_ULong num_glyphs;++ FT_ULong* glyph_offsets;+ FT_UShort* glyph_codes;++ FT_ULong table_offset;++ } TT_SBit_RangeRec, *TT_SBit_Range;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_SBit_StrikeRec */+ /* */+ /* <Description> */+ /* A structure used describe a given bitmap strike in the `EBLC' */+ /* (Microsoft) or `bloc' (Apple) tables. */+ /* */+ /* <Fields> */+ /* num_index_ranges :: The number of index ranges. */+ /* */+ /* index_ranges :: An array of glyph index ranges. */+ /* */+ /* color_ref :: Unused. `color_ref' is put in for future */+ /* enhancements, but these fields are already */+ /* in use by other platforms (e.g. Newton). */+ /* For details, please see */+ /* */+ /* http://fonts.apple.com/ */+ /* TTRefMan/RM06/Chap6bloc.html */+ /* */+ /* hori :: The line metrics for horizontal layouts. */+ /* */+ /* vert :: The line metrics for vertical layouts. */+ /* */+ /* start_glyph :: The lowest glyph index for this strike. */+ /* */+ /* end_glyph :: The highest glyph index for this strike. */+ /* */+ /* x_ppem :: The number of horizontal pixels per EM. */+ /* */+ /* y_ppem :: The number of vertical pixels per EM. */+ /* */+ /* bit_depth :: The bit depth. Valid values are 1, 2, 4, */+ /* and 8. */+ /* */+ /* flags :: Is this a vertical or horizontal strike? For */+ /* details, please see */+ /* */+ /* http://fonts.apple.com/ */+ /* TTRefMan/RM06/Chap6bloc.html */+ /* */+ typedef struct TT_SBit_StrikeRec_+ {+ FT_Int num_ranges;+ TT_SBit_Range sbit_ranges;+ FT_ULong ranges_offset;++ FT_ULong color_ref;++ TT_SBit_LineMetricsRec hori;+ TT_SBit_LineMetricsRec vert;++ FT_UShort start_glyph;+ FT_UShort end_glyph;++ FT_Byte x_ppem;+ FT_Byte y_ppem;++ FT_Byte bit_depth;+ FT_Char flags;++ } TT_SBit_StrikeRec, *TT_SBit_Strike;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_SBit_ComponentRec */+ /* */+ /* <Description> */+ /* A simple structure to describe a compound sbit element. */+ /* */+ /* <Fields> */+ /* glyph_code :: The element's glyph index. */+ /* */+ /* x_offset :: The element's left bearing. */+ /* */+ /* y_offset :: The element's top bearing. */+ /* */+ typedef struct TT_SBit_ComponentRec_+ {+ FT_UShort glyph_code;+ FT_Char x_offset;+ FT_Char y_offset;++ } TT_SBit_ComponentRec, *TT_SBit_Component;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_SBit_ScaleRec */+ /* */+ /* <Description> */+ /* A structure used describe a given bitmap scaling table, as defined */+ /* in the `EBSC' table. */+ /* */+ /* <Fields> */+ /* hori :: The horizontal line metrics. */+ /* */+ /* vert :: The vertical line metrics. */+ /* */+ /* x_ppem :: The number of horizontal pixels per EM. */+ /* */+ /* y_ppem :: The number of vertical pixels per EM. */+ /* */+ /* x_ppem_substitute :: Substitution x_ppem value. */+ /* */+ /* y_ppem_substitute :: Substitution y_ppem value. */+ /* */+ typedef struct TT_SBit_ScaleRec_+ {+ TT_SBit_LineMetricsRec hori;+ TT_SBit_LineMetricsRec vert;++ FT_Byte x_ppem;+ FT_Byte y_ppem;++ FT_Byte x_ppem_substitute;+ FT_Byte y_ppem_substitute;++ } TT_SBit_ScaleRec, *TT_SBit_Scale;+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /*** ***/+ /*** ***/+ /*** POSTSCRIPT GLYPH NAMES SUPPORT ***/+ /*** ***/+ /*** ***/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_Post_20Rec */+ /* */+ /* <Description> */+ /* Postscript names sub-table, format 2.0. Stores the PS name of */+ /* each glyph in the font face. */+ /* */+ /* <Fields> */+ /* num_glyphs :: The number of named glyphs in the table. */+ /* */+ /* num_names :: The number of PS names stored in the table. */+ /* */+ /* glyph_indices :: The indices of the glyphs in the names arrays. */+ /* */+ /* glyph_names :: The PS names not in Mac Encoding. */+ /* */+ typedef struct TT_Post_20Rec_+ {+ FT_UShort num_glyphs;+ FT_UShort num_names;+ FT_UShort* glyph_indices;+ FT_Char** glyph_names;++ } TT_Post_20Rec, *TT_Post_20;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_Post_25Rec */+ /* */+ /* <Description> */+ /* Postscript names sub-table, format 2.5. Stores the PS name of */+ /* each glyph in the font face. */+ /* */+ /* <Fields> */+ /* num_glyphs :: The number of glyphs in the table. */+ /* */+ /* offsets :: An array of signed offsets in a normal Mac */+ /* Postscript name encoding. */+ /* */+ typedef struct TT_Post_25_+ {+ FT_UShort num_glyphs;+ FT_Char* offsets;++ } TT_Post_25Rec, *TT_Post_25;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_Post_NamesRec */+ /* */+ /* <Description> */+ /* Postscript names table, either format 2.0 or 2.5. */+ /* */+ /* <Fields> */+ /* loaded :: A flag to indicate whether the PS names are loaded. */+ /* */+ /* format_20 :: The sub-table used for format 2.0. */+ /* */+ /* format_25 :: The sub-table used for format 2.5. */+ /* */+ typedef struct TT_Post_NamesRec_+ {+ FT_Bool loaded;++ union+ {+ TT_Post_20Rec format_20;+ TT_Post_25Rec format_25;++ } names;++ } TT_Post_NamesRec, *TT_Post_Names;+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /*** ***/+ /*** ***/+ /*** GX VARIATION TABLE SUPPORT ***/+ /*** ***/+ /*** ***/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT+ typedef struct GX_BlendRec_ *GX_Blend;+#endif++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /*** ***/+ /*** ***/+ /*** EMBEDDED BDF PROPERTIES TABLE SUPPORT ***/+ /*** ***/+ /*** ***/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/++ /*+ * These types are used to support a `BDF ' table that isn't part of the+ * official TrueType specification. It is mainly used in SFNT-based+ * bitmap fonts that were generated from a set of BDF fonts.+ *+ * The format of the table is as follows.+ *+ * USHORT version `BDF ' table version number, should be 0x0001.+ * USHORT strikeCount Number of strikes (bitmap sizes) in this table.+ * ULONG stringTable Offset (from start of BDF table) to string+ * table.+ *+ * This is followed by an array of `strikeCount' descriptors, having the+ * following format.+ *+ * USHORT ppem Vertical pixels per EM for this strike.+ * USHORT numItems Number of items for this strike (properties and+ * atoms). Maximum is 255.+ *+ * This array in turn is followed by `strikeCount' value sets. Each+ * `value set' is an array of `numItems' items with the following format.+ *+ * ULONG item_name Offset in string table to item name.+ * USHORT item_type The item type. Possible values are+ * 0 => string (e.g., COMMENT)+ * 1 => atom (e.g., FONT or even SIZE)+ * 2 => int32+ * 3 => uint32+ * 0x10 => A flag to indicate a properties. This+ * is ORed with the above values.+ * ULONG item_value For strings => Offset into string table without+ * the corresponding double quotes.+ * For atoms => Offset into string table.+ * For integers => Direct value.+ *+ * All strings in the string table consist of bytes and are+ * zero-terminated.+ *+ */++#ifdef TT_CONFIG_OPTION_BDF++ typedef struct TT_BDFRec_+ {+ FT_Byte* table;+ FT_Byte* table_end;+ FT_Byte* strings;+ FT_ULong strings_size;+ FT_UInt num_strikes;+ FT_Bool loaded;++ } TT_BDFRec, *TT_BDF;++#endif /* TT_CONFIG_OPTION_BDF */++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /*** ***/+ /*** ***/+ /*** ORIGINAL TT_FACE CLASS DEFINITION ***/+ /*** ***/+ /*** ***/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* This structure/class is defined here because it is common to the */+ /* following formats: TTF, OpenType-TT, and OpenType-CFF. */+ /* */+ /* Note, however, that the classes TT_Size and TT_GlyphSlot are not */+ /* shared between font drivers, and are thus defined in `ttobjs.h'. */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* TT_Face */+ /* */+ /* <Description> */+ /* A handle to a TrueType face/font object. A TT_Face encapsulates */+ /* the resolution and scaling independent parts of a TrueType font */+ /* resource. */+ /* */+ /* <Note> */+ /* The TT_Face structure is also used as a `parent class' for the */+ /* OpenType-CFF class (T2_Face). */+ /* */+ typedef struct TT_FaceRec_* TT_Face;+++ /* a function type used for the truetype bytecode interpreter hooks */+ typedef FT_Error+ (*TT_Interpreter)( void* exec_context );++ /* forward declaration */+ typedef struct TT_LoaderRec_* TT_Loader;+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* TT_Loader_GotoTableFunc */+ /* */+ /* <Description> */+ /* Seeks a stream to the start of a given TrueType table. */+ /* */+ /* <Input> */+ /* face :: A handle to the target face object. */+ /* */+ /* tag :: A 4-byte tag used to name the table. */+ /* */+ /* stream :: The input stream. */+ /* */+ /* <Output> */+ /* length :: The length of the table in bytes. Set to 0 if not */+ /* needed. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ /* <Note> */+ /* The stream cursor must be at the font file's origin. */+ /* */+ typedef FT_Error+ (*TT_Loader_GotoTableFunc)( TT_Face face,+ FT_ULong tag,+ FT_Stream stream,+ FT_ULong* length );+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* TT_Loader_StartGlyphFunc */+ /* */+ /* <Description> */+ /* Seeks a stream to the start of a given glyph element, and opens a */+ /* frame for it. */+ /* */+ /* <Input> */+ /* loader :: The current TrueType glyph loader object. */+ /* */+ /* glyph index :: The index of the glyph to access. */+ /* */+ /* offset :: The offset of the glyph according to the */+ /* `locations' table. */+ /* */+ /* byte_count :: The size of the frame in bytes. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ /* <Note> */+ /* This function is normally equivalent to FT_STREAM_SEEK(offset) */+ /* followed by FT_FRAME_ENTER(byte_count) with the loader's stream, */+ /* but alternative formats (e.g. compressed ones) might use something */+ /* different. */+ /* */+ typedef FT_Error+ (*TT_Loader_StartGlyphFunc)( TT_Loader loader,+ FT_UInt glyph_index,+ FT_ULong offset,+ FT_UInt byte_count );+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* TT_Loader_ReadGlyphFunc */+ /* */+ /* <Description> */+ /* Reads one glyph element (its header, a simple glyph, or a */+ /* composite) from the loader's current stream frame. */+ /* */+ /* <Input> */+ /* loader :: The current TrueType glyph loader object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ typedef FT_Error+ (*TT_Loader_ReadGlyphFunc)( TT_Loader loader );+++ /*************************************************************************/+ /* */+ /* <FuncType> */+ /* TT_Loader_EndGlyphFunc */+ /* */+ /* <Description> */+ /* Closes the current loader stream frame for the glyph. */+ /* */+ /* <Input> */+ /* loader :: The current TrueType glyph loader object. */+ /* */+ typedef void+ (*TT_Loader_EndGlyphFunc)( TT_Loader loader );+++ /*************************************************************************/+ /* */+ /* TrueType Face Type */+ /* */+ /* <Struct> */+ /* TT_Face */+ /* */+ /* <Description> */+ /* The TrueType face class. These objects model the resolution and */+ /* point-size independent data found in a TrueType font file. */+ /* */+ /* <Fields> */+ /* root :: The base FT_Face structure, managed by the */+ /* base layer. */+ /* */+ /* ttc_header :: The TrueType collection header, used when */+ /* the file is a `ttc' rather than a `ttf'. */+ /* For ordinary font files, the field */+ /* `ttc_header.count' is set to 0. */+ /* */+ /* format_tag :: The font format tag. */+ /* */+ /* num_tables :: The number of TrueType tables in this font */+ /* file. */+ /* */+ /* dir_tables :: The directory of TrueType tables for this */+ /* font file. */+ /* */+ /* header :: The font's font header (`head' table). */+ /* Read on font opening. */+ /* */+ /* horizontal :: The font's horizontal header (`hhea' */+ /* table). This field also contains the */+ /* associated horizontal metrics table */+ /* (`hmtx'). */+ /* */+ /* max_profile :: The font's maximum profile table. Read on */+ /* font opening. Note that some maximum */+ /* values cannot be taken directly from this */+ /* table. We thus define additional fields */+ /* below to hold the computed maxima. */+ /* */+ /* vertical_info :: A boolean which is set when the font file */+ /* contains vertical metrics. If not, the */+ /* value of the `vertical' field is */+ /* undefined. */+ /* */+ /* vertical :: The font's vertical header (`vhea' table). */+ /* This field also contains the associated */+ /* vertical metrics table (`vmtx'), if found. */+ /* IMPORTANT: The contents of this field is */+ /* undefined if the `verticalInfo' field is */+ /* unset. */+ /* */+ /* num_names :: The number of name records within this */+ /* TrueType font. */+ /* */+ /* name_table :: The table of name records (`name'). */+ /* */+ /* os2 :: The font's OS/2 table (`OS/2'). */+ /* */+ /* postscript :: The font's PostScript table (`post' */+ /* table). The PostScript glyph names are */+ /* not loaded by the driver on face opening. */+ /* See the `ttpost' module for more details. */+ /* */+ /* cmap_table :: Address of the face's `cmap' SFNT table */+ /* in memory (it's an extracted frame). */+ /* */+ /* cmap_size :: The size in bytes of the `cmap_table' */+ /* described above. */+ /* */+ /* goto_table :: A function called by each TrueType table */+ /* loader to position a stream's cursor to */+ /* the start of a given table according to */+ /* its tag. It defaults to TT_Goto_Face but */+ /* can be different for strange formats (e.g. */+ /* Type 42). */+ /* */+ /* access_glyph_frame :: A function used to access the frame of a */+ /* given glyph within the face's font file. */+ /* */+ /* forget_glyph_frame :: A function used to forget the frame of a */+ /* given glyph when all data has been loaded. */+ /* */+ /* read_glyph_header :: A function used to read a glyph header. */+ /* It must be called between an `access' and */+ /* `forget'. */+ /* */+ /* read_simple_glyph :: A function used to read a simple glyph. */+ /* It must be called after the header was */+ /* read, and before the `forget'. */+ /* */+ /* read_composite_glyph :: A function used to read a composite glyph. */+ /* It must be called after the header was */+ /* read, and before the `forget'. */+ /* */+ /* sfnt :: A pointer to the SFNT service. */+ /* */+ /* psnames :: A pointer to the PostScript names service. */+ /* */+ /* hdmx :: The face's horizontal device metrics */+ /* (`hdmx' table). This table is optional in */+ /* TrueType/OpenType fonts. */+ /* */+ /* gasp :: The grid-fitting and scaling properties */+ /* table (`gasp'). This table is optional in */+ /* TrueType/OpenType fonts. */+ /* */+ /* pclt :: The `pclt' SFNT table. */+ /* */+ /* num_sbit_strikes :: The number of sbit strikes, i.e., bitmap */+ /* sizes, embedded in this font. */+ /* */+ /* sbit_strikes :: An array of sbit strikes embedded in this */+ /* font. This table is optional in a */+ /* TrueType/OpenType font. */+ /* */+ /* num_sbit_scales :: The number of sbit scales for this font. */+ /* */+ /* sbit_scales :: Array of sbit scales embedded in this */+ /* font. This table is optional in a */+ /* TrueType/OpenType font. */+ /* */+ /* postscript_names :: A table used to store the Postscript names */+ /* of the glyphs for this font. See the */+ /* file `ttconfig.h' for comments on the */+ /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES option. */+ /* */+ /* num_locations :: The number of glyph locations in this */+ /* TrueType file. This should be */+ /* identical to the number of glyphs. */+ /* Ignored for Type 2 fonts. */+ /* */+ /* glyph_locations :: An array of longs. These are offsets to */+ /* glyph data within the `glyf' table. */+ /* Ignored for Type 2 font faces. */+ /* */+ /* glyf_len :: The length of the `glyf' table. Needed */+ /* for malformed `loca' tables. */+ /* */+ /* font_program_size :: Size in bytecodes of the face's font */+ /* program. 0 if none defined. Ignored for */+ /* Type 2 fonts. */+ /* */+ /* font_program :: The face's font program (bytecode stream) */+ /* executed at load time, also used during */+ /* glyph rendering. Comes from the `fpgm' */+ /* table. Ignored for Type 2 font fonts. */+ /* */+ /* cvt_program_size :: The size in bytecodes of the face's cvt */+ /* program. Ignored for Type 2 fonts. */+ /* */+ /* cvt_program :: The face's cvt program (bytecode stream) */+ /* executed each time an instance/size is */+ /* changed/reset. Comes from the `prep' */+ /* table. Ignored for Type 2 fonts. */+ /* */+ /* cvt_size :: Size of the control value table (in */+ /* entries). Ignored for Type 2 fonts. */+ /* */+ /* cvt :: The face's original control value table. */+ /* Coordinates are expressed in unscaled font */+ /* units. Comes from the `cvt ' table. */+ /* Ignored for Type 2 fonts. */+ /* */+ /* num_kern_pairs :: The number of kerning pairs present in the */+ /* font file. The engine only loads the */+ /* first horizontal format 0 kern table it */+ /* finds in the font file. Ignored for */+ /* Type 2 fonts. */+ /* */+ /* kern_table_index :: The index of the kerning table in the font */+ /* kerning directory. Ignored for Type 2 */+ /* fonts. */+ /* */+ /* interpreter :: A pointer to the TrueType bytecode */+ /* interpreters field is also used to hook */+ /* the debugger in `ttdebug'. */+ /* */+ /* unpatented_hinting :: If true, use only unpatented methods in */+ /* the bytecode interpreter. */+ /* */+ /* doblend :: A boolean which is set if the font should */+ /* be blended (this is for GX var). */+ /* */+ /* blend :: Contains the data needed to control GX */+ /* variation tables (rather like Multiple */+ /* Master data). */+ /* */+ /* extra :: Reserved for third-party font drivers. */+ /* */+ /* postscript_name :: The PS name of the font. Used by the */+ /* postscript name service. */+ /* */+ typedef struct TT_FaceRec_+ {+ FT_FaceRec root;++ TTC_HeaderRec ttc_header;++ FT_ULong format_tag;+ FT_UShort num_tables;+ TT_Table dir_tables;++ TT_Header header; /* TrueType header table */+ TT_HoriHeader horizontal; /* TrueType horizontal header */++ TT_MaxProfile max_profile;+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS+ FT_ULong max_components; /* stubbed to 0 */+#endif++ FT_Bool vertical_info;+ TT_VertHeader vertical; /* TT Vertical header, if present */++ FT_UShort num_names; /* number of name records */+ TT_NameTableRec name_table; /* name table */++ TT_OS2 os2; /* TrueType OS/2 table */+ TT_Postscript postscript; /* TrueType Postscript table */++ FT_Byte* cmap_table; /* extracted `cmap' table */+ FT_ULong cmap_size;++ TT_Loader_GotoTableFunc goto_table;++ TT_Loader_StartGlyphFunc access_glyph_frame;+ TT_Loader_EndGlyphFunc forget_glyph_frame;+ TT_Loader_ReadGlyphFunc read_glyph_header;+ TT_Loader_ReadGlyphFunc read_simple_glyph;+ TT_Loader_ReadGlyphFunc read_composite_glyph;++ /* a typeless pointer to the SFNT_Interface table used to load */+ /* the basic TrueType tables in the face object */+ void* sfnt;++ /* a typeless pointer to the FT_Service_PsCMapsRec table used to */+ /* handle glyph names <-> unicode & Mac values */+ void* psnames;+++ /***********************************************************************/+ /* */+ /* Optional TrueType/OpenType tables */+ /* */+ /***********************************************************************/++ /* horizontal device metrics */+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS+ TT_HdmxRec hdmx;+#endif++ /* grid-fitting and scaling table */+ TT_GaspRec gasp; /* the `gasp' table */++ /* PCL 5 table */+ TT_PCLT pclt;++ /* embedded bitmaps support */+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS+ FT_ULong num_sbit_strikes;+ TT_SBit_Strike sbit_strikes;+#endif++ FT_ULong num_sbit_scales;+ TT_SBit_Scale sbit_scales;++ /* postscript names table */+ TT_Post_NamesRec postscript_names;+++ /***********************************************************************/+ /* */+ /* TrueType-specific fields (ignored by the OTF-Type2 driver) */+ /* */+ /***********************************************************************/++ /* the glyph locations */+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS+ FT_UShort num_locations_stub;+ FT_Long* glyph_locations_stub;+#endif++ /* the font program, if any */+ FT_ULong font_program_size;+ FT_Byte* font_program;++ /* the cvt program, if any */+ FT_ULong cvt_program_size;+ FT_Byte* cvt_program;++ /* the original, unscaled, control value table */+ FT_ULong cvt_size;+ FT_Short* cvt;++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS+ /* the format 0 kerning table, if any */+ FT_Int num_kern_pairs;+ FT_Int kern_table_index;+ TT_Kern0_Pair kern_pairs;+#endif++ /* A pointer to the bytecode interpreter to use. This is also */+ /* used to hook the debugger for the `ttdebug' utility. */+ TT_Interpreter interpreter;++#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING+ /* Use unpatented hinting only. */+ FT_Bool unpatented_hinting;+#endif++ /***********************************************************************/+ /* */+ /* Other tables or fields. This is used by derivative formats like */+ /* OpenType. */+ /* */+ /***********************************************************************/++ FT_Generic extra;++ const char* postscript_name;++ /* since version 2.1.8, but was originally placed after */+ /* `glyph_locations_stub' */+ FT_ULong glyf_len;++ /* since version 2.1.8, but was originally placed before `extra' */+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT+ FT_Bool doblend;+ GX_Blend blend;+#endif++ /* since version 2.2 */++ FT_Byte* horz_metrics;+ FT_ULong horz_metrics_size;++ FT_Byte* vert_metrics;+ FT_ULong vert_metrics_size;++ FT_ULong num_locations; /* in broken TTF, gid > 0xFFFF */ + FT_Byte* glyph_locations;++ FT_Byte* hdmx_table;+ FT_ULong hdmx_table_size;+ FT_UInt hdmx_record_count;+ FT_ULong hdmx_record_size;+ FT_Byte* hdmx_record_sizes;++ FT_Byte* sbit_table;+ FT_ULong sbit_table_size;+ FT_UInt sbit_num_strikes;++ FT_Byte* kern_table;+ FT_ULong kern_table_size;+ FT_UInt num_kern_tables;+ FT_UInt32 kern_avail_bits;+ FT_UInt32 kern_order_bits;++#ifdef TT_CONFIG_OPTION_BDF+ TT_BDFRec bdf;+#endif /* TT_CONFIG_OPTION_BDF */++ /* since 2.3.0 */+ FT_ULong horz_metrics_offset;+ FT_ULong vert_metrics_offset;++ } TT_FaceRec;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_GlyphZoneRec */+ /* */+ /* <Description> */+ /* A glyph zone is used to load, scale and hint glyph outline */+ /* coordinates. */+ /* */+ /* <Fields> */+ /* memory :: A handle to the memory manager. */+ /* */+ /* max_points :: The maximal size in points of the zone. */+ /* */+ /* max_contours :: Max size in links contours of the zone. */+ /* */+ /* n_points :: The current number of points in the zone. */+ /* */+ /* n_contours :: The current number of contours in the zone. */+ /* */+ /* org :: The original glyph coordinates (font */+ /* units/scaled). */+ /* */+ /* cur :: The current glyph coordinates (scaled/hinted). */+ /* */+ /* tags :: The point control tags. */+ /* */+ /* contours :: The contours end points. */+ /* */+ /* first_point :: Offset of the current subglyph's first point. */+ /* */+ typedef struct TT_GlyphZoneRec_+ {+ FT_Memory memory;+ FT_UShort max_points;+ FT_UShort max_contours;+ FT_UShort n_points; /* number of points in zone */+ FT_Short n_contours; /* number of contours */++ FT_Vector* org; /* original point coordinates */+ FT_Vector* cur; /* current point coordinates */+ FT_Vector* orus; /* original (unscaled) point coordinates */++ FT_Byte* tags; /* current touch flags */+ FT_UShort* contours; /* contour end points */++ FT_UShort first_point; /* offset of first (#0) point */++ } TT_GlyphZoneRec, *TT_GlyphZone;+++ /* handle to execution context */+ typedef struct TT_ExecContextRec_* TT_ExecContext;++ /* glyph loader structure */+ typedef struct TT_LoaderRec_+ {+ FT_Face face;+ FT_Size size;+ FT_GlyphSlot glyph;+ FT_GlyphLoader gloader;++ FT_ULong load_flags;+ FT_UInt glyph_index;++ FT_Stream stream;+ FT_Int byte_len;++ FT_Short n_contours;+ FT_BBox bbox;+ FT_Int left_bearing;+ FT_Int advance;+ FT_Int linear;+ FT_Bool linear_def;+ FT_Bool preserve_pps;+ FT_Vector pp1;+ FT_Vector pp2;++ FT_ULong glyf_offset;++ /* the zone where we load our glyphs */+ TT_GlyphZoneRec base;+ TT_GlyphZoneRec zone;++ TT_ExecContext exec;+ FT_Byte* instructions;+ FT_ULong ins_pos;++ /* for possible extensibility in other formats */+ void* other;++ /* since version 2.1.8 */+ FT_Int top_bearing;+ FT_Int vadvance;+ FT_Vector pp3;+ FT_Vector pp4;++ /* since version 2.2.1 */+ FT_Byte* cursor;+ FT_Byte* limit;++ } TT_LoaderRec;+++FT_END_HEADER++#endif /* __TTTYPES_H__ */+++/* END */
+ include/freetype/t1tables.h view
@@ -0,0 +1,504 @@+/***************************************************************************/+/* */+/* t1tables.h */+/* */+/* Basic Type 1/Type 2 tables definitions and interface (specification */+/* only). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2008, 2009 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 __T1TABLES_H__+#define __T1TABLES_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+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* type1_tables */+ /* */+ /* <Title> */+ /* Type 1 Tables */+ /* */+ /* <Abstract> */+ /* Type~1 (PostScript) specific font tables. */+ /* */+ /* <Description> */+ /* This section contains the definition of Type 1-specific tables, */+ /* including structures related to other PostScript font formats. */+ /* */+ /*************************************************************************/+++ /* Note that we separate font data in PS_FontInfoRec and PS_PrivateRec */+ /* structures in order to support Multiple Master fonts. */+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* PS_FontInfoRec */+ /* */+ /* <Description> */+ /* A structure used to model a Type~1 or Type~2 FontInfo dictionary. */+ /* Note that for Multiple Master fonts, each instance has its own */+ /* FontInfo dictionary. */+ /* */+ typedef struct PS_FontInfoRec_+ {+ FT_String* version;+ FT_String* notice;+ FT_String* full_name;+ FT_String* family_name;+ FT_String* weight;+ FT_Long italic_angle;+ FT_Bool is_fixed_pitch;+ FT_Short underline_position;+ FT_UShort underline_thickness;++ } PS_FontInfoRec;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* PS_FontInfo */+ /* */+ /* <Description> */+ /* A handle to a @PS_FontInfoRec structure. */+ /* */+ typedef struct PS_FontInfoRec_* PS_FontInfo;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* T1_FontInfo */+ /* */+ /* <Description> */+ /* This type is equivalent to @PS_FontInfoRec. It is deprecated but */+ /* kept to maintain source compatibility between various versions of */+ /* FreeType. */+ /* */+ typedef PS_FontInfoRec T1_FontInfo;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* PS_PrivateRec */+ /* */+ /* <Description> */+ /* A structure used to model a Type~1 or Type~2 private dictionary. */+ /* Note that for Multiple Master fonts, each instance has its own */+ /* Private dictionary. */+ /* */+ typedef struct PS_PrivateRec_+ {+ FT_Int unique_id;+ FT_Int lenIV;++ FT_Byte num_blue_values;+ FT_Byte num_other_blues;+ FT_Byte num_family_blues;+ FT_Byte num_family_other_blues;++ FT_Short blue_values[14];+ FT_Short other_blues[10];++ FT_Short family_blues [14];+ FT_Short family_other_blues[10];++ FT_Fixed blue_scale;+ FT_Int blue_shift;+ FT_Int blue_fuzz;++ FT_UShort standard_width[1];+ FT_UShort standard_height[1];++ FT_Byte num_snap_widths;+ FT_Byte num_snap_heights;+ FT_Bool force_bold;+ FT_Bool round_stem_up;++ FT_Short snap_widths [13]; /* including std width */+ FT_Short snap_heights[13]; /* including std height */++ FT_Fixed expansion_factor;++ FT_Long language_group;+ FT_Long password;++ FT_Short min_feature[2];++ } PS_PrivateRec;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* PS_Private */+ /* */+ /* <Description> */+ /* A handle to a @PS_PrivateRec structure. */+ /* */+ typedef struct PS_PrivateRec_* PS_Private;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* T1_Private */+ /* */+ /* <Description> */+ /* This type is equivalent to @PS_PrivateRec. It is deprecated but */+ /* kept to maintain source compatibility between various versions of */+ /* FreeType. */+ /* */+ typedef PS_PrivateRec T1_Private;+++ /*************************************************************************/+ /* */+ /* <Enum> */+ /* T1_Blend_Flags */+ /* */+ /* <Description> */+ /* A set of flags used to indicate which fields are present in a */+ /* given blend dictionary (font info or private). Used to support */+ /* Multiple Masters fonts. */+ /* */+ typedef enum T1_Blend_Flags_+ {+ /*# required fields in a FontInfo blend dictionary */+ T1_BLEND_UNDERLINE_POSITION = 0,+ T1_BLEND_UNDERLINE_THICKNESS,+ T1_BLEND_ITALIC_ANGLE,++ /*# required fields in a Private blend dictionary */+ T1_BLEND_BLUE_VALUES,+ T1_BLEND_OTHER_BLUES,+ T1_BLEND_STANDARD_WIDTH,+ T1_BLEND_STANDARD_HEIGHT,+ T1_BLEND_STEM_SNAP_WIDTHS,+ T1_BLEND_STEM_SNAP_HEIGHTS,+ T1_BLEND_BLUE_SCALE,+ T1_BLEND_BLUE_SHIFT,+ T1_BLEND_FAMILY_BLUES,+ T1_BLEND_FAMILY_OTHER_BLUES,+ T1_BLEND_FORCE_BOLD,++ /*# never remove */+ T1_BLEND_MAX++ } T1_Blend_Flags;++ /* */+++ /*# backwards compatible definitions */+#define t1_blend_underline_position T1_BLEND_UNDERLINE_POSITION+#define t1_blend_underline_thickness T1_BLEND_UNDERLINE_THICKNESS+#define t1_blend_italic_angle T1_BLEND_ITALIC_ANGLE+#define t1_blend_blue_values T1_BLEND_BLUE_VALUES+#define t1_blend_other_blues T1_BLEND_OTHER_BLUES+#define t1_blend_standard_widths T1_BLEND_STANDARD_WIDTH+#define t1_blend_standard_height T1_BLEND_STANDARD_HEIGHT+#define t1_blend_stem_snap_widths T1_BLEND_STEM_SNAP_WIDTHS+#define t1_blend_stem_snap_heights T1_BLEND_STEM_SNAP_HEIGHTS+#define t1_blend_blue_scale T1_BLEND_BLUE_SCALE+#define t1_blend_blue_shift T1_BLEND_BLUE_SHIFT+#define t1_blend_family_blues T1_BLEND_FAMILY_BLUES+#define t1_blend_family_other_blues T1_BLEND_FAMILY_OTHER_BLUES+#define t1_blend_force_bold T1_BLEND_FORCE_BOLD+#define t1_blend_max T1_BLEND_MAX+++ /* maximum number of Multiple Masters designs, as defined in the spec */+#define T1_MAX_MM_DESIGNS 16++ /* maximum number of Multiple Masters axes, as defined in the spec */+#define T1_MAX_MM_AXIS 4++ /* maximum number of elements in a design map */+#define T1_MAX_MM_MAP_POINTS 20+++ /* this structure is used to store the BlendDesignMap entry for an axis */+ typedef struct PS_DesignMap_+ {+ FT_Byte num_points;+ FT_Long* design_points;+ FT_Fixed* blend_points;++ } PS_DesignMapRec, *PS_DesignMap;++ /* backwards-compatible definition */+ typedef PS_DesignMapRec T1_DesignMap;+++ typedef struct PS_BlendRec_+ {+ FT_UInt num_designs;+ FT_UInt num_axis;++ FT_String* axis_names[T1_MAX_MM_AXIS];+ FT_Fixed* design_pos[T1_MAX_MM_DESIGNS];+ PS_DesignMapRec design_map[T1_MAX_MM_AXIS];++ FT_Fixed* weight_vector;+ FT_Fixed* default_weight_vector;++ PS_FontInfo font_infos[T1_MAX_MM_DESIGNS + 1];+ PS_Private privates [T1_MAX_MM_DESIGNS + 1];++ FT_ULong blend_bitflags;++ FT_BBox* bboxes [T1_MAX_MM_DESIGNS + 1];++ /* since 2.3.0 */++ /* undocumented, optional: the default design instance; */+ /* corresponds to default_weight_vector -- */+ /* num_default_design_vector == 0 means it is not present */+ /* in the font and associated metrics files */+ FT_UInt default_design_vector[T1_MAX_MM_DESIGNS];+ FT_UInt num_default_design_vector;++ } PS_BlendRec, *PS_Blend;+++ /* backwards-compatible definition */+ typedef PS_BlendRec T1_Blend;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* CID_FaceDictRec */+ /* */+ /* <Description> */+ /* A structure used to represent data in a CID top-level dictionary. */+ /* */+ typedef struct CID_FaceDictRec_+ {+ PS_PrivateRec private_dict;++ FT_UInt len_buildchar;+ FT_Fixed forcebold_threshold;+ FT_Pos stroke_width;+ FT_Fixed expansion_factor;++ FT_Byte paint_type;+ FT_Byte font_type;+ FT_Matrix font_matrix;+ FT_Vector font_offset;++ FT_UInt num_subrs;+ FT_ULong subrmap_offset;+ FT_Int sd_bytes;++ } CID_FaceDictRec;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* CID_FaceDict */+ /* */+ /* <Description> */+ /* A handle to a @CID_FaceDictRec structure. */+ /* */+ typedef struct CID_FaceDictRec_* CID_FaceDict;++ /* */+++ /* backwards-compatible definition */+ typedef CID_FaceDictRec CID_FontDict;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* CID_FaceInfoRec */+ /* */+ /* <Description> */+ /* A structure used to represent CID Face information. */+ /* */+ typedef struct CID_FaceInfoRec_+ {+ FT_String* cid_font_name;+ FT_Fixed cid_version;+ FT_Int cid_font_type;++ FT_String* registry;+ FT_String* ordering;+ FT_Int supplement;++ PS_FontInfoRec font_info;+ FT_BBox font_bbox;+ FT_ULong uid_base;++ FT_Int num_xuid;+ FT_ULong xuid[16];++ FT_ULong cidmap_offset;+ FT_Int fd_bytes;+ FT_Int gd_bytes;+ FT_ULong cid_count;++ FT_Int num_dicts;+ CID_FaceDict font_dicts;++ FT_ULong data_offset;++ } CID_FaceInfoRec;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* CID_FaceInfo */+ /* */+ /* <Description> */+ /* A handle to a @CID_FaceInfoRec structure. */+ /* */+ typedef struct CID_FaceInfoRec_* CID_FaceInfo;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* CID_Info */+ /* */+ /* <Description> */+ /* This type is equivalent to @CID_FaceInfoRec. It is deprecated but */+ /* kept to maintain source compatibility between various versions of */+ /* FreeType. */+ /* */+ typedef CID_FaceInfoRec CID_Info;+++ /************************************************************************+ *+ * @function:+ * FT_Has_PS_Glyph_Names+ *+ * @description:+ * Return true if a given face provides reliable PostScript glyph+ * names. This is similar to using the @FT_HAS_GLYPH_NAMES macro,+ * except that certain fonts (mostly TrueType) contain incorrect+ * glyph name tables.+ *+ * When this function returns true, the caller is sure that the glyph+ * names returned by @FT_Get_Glyph_Name are reliable.+ *+ * @input:+ * face ::+ * face handle+ *+ * @return:+ * Boolean. True if glyph names are reliable.+ *+ */+ FT_EXPORT( FT_Int )+ FT_Has_PS_Glyph_Names( FT_Face face );+++ /************************************************************************+ *+ * @function:+ * FT_Get_PS_Font_Info+ *+ * @description:+ * Retrieve the @PS_FontInfoRec structure corresponding to a given+ * PostScript font.+ *+ * @input:+ * face ::+ * PostScript face handle.+ *+ * @output:+ * afont_info ::+ * Output font info structure pointer.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * The string pointers within the font info structure are owned by+ * the face and don't need to be freed by the caller.+ *+ * If the font's format is not PostScript-based, this function will+ * return the `FT_Err_Invalid_Argument' error code.+ *+ */+ FT_EXPORT( FT_Error )+ FT_Get_PS_Font_Info( FT_Face face,+ PS_FontInfo afont_info );+++ /************************************************************************+ *+ * @function:+ * FT_Get_PS_Font_Private+ *+ * @description:+ * Retrieve the @PS_PrivateRec structure corresponding to a given+ * PostScript font.+ *+ * @input:+ * face ::+ * PostScript face handle.+ *+ * @output:+ * afont_private ::+ * Output private dictionary structure pointer.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * The string pointers within the @PS_PrivateRec structure are owned by+ * the face and don't need to be freed by the caller.+ *+ * If the font's format is not PostScript-based, this function returns+ * the `FT_Err_Invalid_Argument' error code.+ *+ */+ FT_EXPORT( FT_Error )+ FT_Get_PS_Font_Private( FT_Face face,+ PS_Private afont_private );++ /* */+++FT_END_HEADER++#endif /* __T1TABLES_H__ */+++/* END */
+ include/freetype/ttnameid.h view
@@ -0,0 +1,1247 @@+/***************************************************************************/+/* */+/* ttnameid.h */+/* */+/* TrueType name ID definitions (specification only). */+/* */+/* Copyright 1996-2002, 2003, 2004, 2006, 2007, 2008 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 __TTNAMEID_H__+#define __TTNAMEID_H__+++#include <ft2build.h>+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* truetype_tables */+ /* */+++ /*************************************************************************/+ /* */+ /* Possible values for the `platform' identifier code in the name */+ /* records of the TTF `name' table. */+ /* */+ /*************************************************************************/+++ /***********************************************************************+ *+ * @enum:+ * TT_PLATFORM_XXX+ *+ * @description:+ * A list of valid values for the `platform_id' identifier code in+ * @FT_CharMapRec and @FT_SfntName structures.+ *+ * @values:+ * TT_PLATFORM_APPLE_UNICODE ::+ * Used by Apple to indicate a Unicode character map and/or name entry.+ * See @TT_APPLE_ID_XXX for corresponding `encoding_id' values. Note+ * that name entries in this format are coded as big-endian UCS-2+ * character codes _only_.+ *+ * TT_PLATFORM_MACINTOSH ::+ * Used by Apple to indicate a MacOS-specific charmap and/or name entry.+ * See @TT_MAC_ID_XXX for corresponding `encoding_id' values. Note that+ * most TrueType fonts contain an Apple roman charmap to be usable on+ * MacOS systems (even if they contain a Microsoft charmap as well).+ *+ * TT_PLATFORM_ISO ::+ * This value was used to specify ISO/IEC 10646 charmaps. It is however+ * now deprecated. See @TT_ISO_ID_XXX for a list of corresponding+ * `encoding_id' values.+ *+ * TT_PLATFORM_MICROSOFT ::+ * Used by Microsoft to indicate Windows-specific charmaps. See+ * @TT_MS_ID_XXX for a list of corresponding `encoding_id' values.+ * Note that most fonts contain a Unicode charmap using+ * (TT_PLATFORM_MICROSOFT, @TT_MS_ID_UNICODE_CS).+ *+ * TT_PLATFORM_CUSTOM ::+ * Used to indicate application-specific charmaps.+ *+ * TT_PLATFORM_ADOBE ::+ * This value isn't part of any font format specification, but is used+ * by FreeType to report Adobe-specific charmaps in an @FT_CharMapRec+ * structure. See @TT_ADOBE_ID_XXX.+ */++#define TT_PLATFORM_APPLE_UNICODE 0+#define TT_PLATFORM_MACINTOSH 1+#define TT_PLATFORM_ISO 2 /* deprecated */+#define TT_PLATFORM_MICROSOFT 3+#define TT_PLATFORM_CUSTOM 4+#define TT_PLATFORM_ADOBE 7 /* artificial */+++ /***********************************************************************+ *+ * @enum:+ * TT_APPLE_ID_XXX+ *+ * @description:+ * A list of valid values for the `encoding_id' for+ * @TT_PLATFORM_APPLE_UNICODE charmaps and name entries.+ *+ * @values:+ * TT_APPLE_ID_DEFAULT ::+ * Unicode version 1.0.+ *+ * TT_APPLE_ID_UNICODE_1_1 ::+ * Unicode 1.1; specifies Hangul characters starting at U+34xx.+ *+ * TT_APPLE_ID_ISO_10646 ::+ * Deprecated (identical to preceding).+ *+ * TT_APPLE_ID_UNICODE_2_0 ::+ * Unicode 2.0 and beyond (UTF-16 BMP only).+ *+ * TT_APPLE_ID_UNICODE_32 ::+ * Unicode 3.1 and beyond, using UTF-32.+ *+ * TT_APPLE_ID_VARIANT_SELECTOR ::+ * From Adobe, not Apple. Not a normal cmap. Specifies variations+ * on a real cmap.+ */++#define TT_APPLE_ID_DEFAULT 0 /* Unicode 1.0 */+#define TT_APPLE_ID_UNICODE_1_1 1 /* specify Hangul at U+34xx */+#define TT_APPLE_ID_ISO_10646 2 /* deprecated */+#define TT_APPLE_ID_UNICODE_2_0 3 /* or later */+#define TT_APPLE_ID_UNICODE_32 4 /* 2.0 or later, full repertoire */+#define TT_APPLE_ID_VARIANT_SELECTOR 5 /* variation selector data */+++ /***********************************************************************+ *+ * @enum:+ * TT_MAC_ID_XXX+ *+ * @description:+ * A list of valid values for the `encoding_id' for+ * @TT_PLATFORM_MACINTOSH charmaps and name entries.+ *+ * @values:+ * TT_MAC_ID_ROMAN ::+ * TT_MAC_ID_JAPANESE ::+ * TT_MAC_ID_TRADITIONAL_CHINESE ::+ * TT_MAC_ID_KOREAN ::+ * TT_MAC_ID_ARABIC ::+ * TT_MAC_ID_HEBREW ::+ * TT_MAC_ID_GREEK ::+ * TT_MAC_ID_RUSSIAN ::+ * TT_MAC_ID_RSYMBOL ::+ * TT_MAC_ID_DEVANAGARI ::+ * TT_MAC_ID_GURMUKHI ::+ * TT_MAC_ID_GUJARATI ::+ * TT_MAC_ID_ORIYA ::+ * TT_MAC_ID_BENGALI ::+ * TT_MAC_ID_TAMIL ::+ * TT_MAC_ID_TELUGU ::+ * TT_MAC_ID_KANNADA ::+ * TT_MAC_ID_MALAYALAM ::+ * TT_MAC_ID_SINHALESE ::+ * TT_MAC_ID_BURMESE ::+ * TT_MAC_ID_KHMER ::+ * TT_MAC_ID_THAI ::+ * TT_MAC_ID_LAOTIAN ::+ * TT_MAC_ID_GEORGIAN ::+ * TT_MAC_ID_ARMENIAN ::+ * TT_MAC_ID_MALDIVIAN ::+ * TT_MAC_ID_SIMPLIFIED_CHINESE ::+ * TT_MAC_ID_TIBETAN ::+ * TT_MAC_ID_MONGOLIAN ::+ * TT_MAC_ID_GEEZ ::+ * TT_MAC_ID_SLAVIC ::+ * TT_MAC_ID_VIETNAMESE ::+ * TT_MAC_ID_SINDHI ::+ * TT_MAC_ID_UNINTERP ::+ */++#define TT_MAC_ID_ROMAN 0+#define TT_MAC_ID_JAPANESE 1+#define TT_MAC_ID_TRADITIONAL_CHINESE 2+#define TT_MAC_ID_KOREAN 3+#define TT_MAC_ID_ARABIC 4+#define TT_MAC_ID_HEBREW 5+#define TT_MAC_ID_GREEK 6+#define TT_MAC_ID_RUSSIAN 7+#define TT_MAC_ID_RSYMBOL 8+#define TT_MAC_ID_DEVANAGARI 9+#define TT_MAC_ID_GURMUKHI 10+#define TT_MAC_ID_GUJARATI 11+#define TT_MAC_ID_ORIYA 12+#define TT_MAC_ID_BENGALI 13+#define TT_MAC_ID_TAMIL 14+#define TT_MAC_ID_TELUGU 15+#define TT_MAC_ID_KANNADA 16+#define TT_MAC_ID_MALAYALAM 17+#define TT_MAC_ID_SINHALESE 18+#define TT_MAC_ID_BURMESE 19+#define TT_MAC_ID_KHMER 20+#define TT_MAC_ID_THAI 21+#define TT_MAC_ID_LAOTIAN 22+#define TT_MAC_ID_GEORGIAN 23+#define TT_MAC_ID_ARMENIAN 24+#define TT_MAC_ID_MALDIVIAN 25+#define TT_MAC_ID_SIMPLIFIED_CHINESE 25+#define TT_MAC_ID_TIBETAN 26+#define TT_MAC_ID_MONGOLIAN 27+#define TT_MAC_ID_GEEZ 28+#define TT_MAC_ID_SLAVIC 29+#define TT_MAC_ID_VIETNAMESE 30+#define TT_MAC_ID_SINDHI 31+#define TT_MAC_ID_UNINTERP 32+++ /***********************************************************************+ *+ * @enum:+ * TT_ISO_ID_XXX+ *+ * @description:+ * A list of valid values for the `encoding_id' for+ * @TT_PLATFORM_ISO charmaps and name entries.+ *+ * Their use is now deprecated.+ *+ * @values:+ * TT_ISO_ID_7BIT_ASCII ::+ * ASCII.+ * TT_ISO_ID_10646 ::+ * ISO/10646.+ * TT_ISO_ID_8859_1 ::+ * Also known as Latin-1.+ */++#define TT_ISO_ID_7BIT_ASCII 0+#define TT_ISO_ID_10646 1+#define TT_ISO_ID_8859_1 2+++ /***********************************************************************+ *+ * @enum:+ * TT_MS_ID_XXX+ *+ * @description:+ * A list of valid values for the `encoding_id' for+ * @TT_PLATFORM_MICROSOFT charmaps and name entries.+ *+ * @values:+ * TT_MS_ID_SYMBOL_CS ::+ * Corresponds to Microsoft symbol encoding. See+ * @FT_ENCODING_MS_SYMBOL.+ *+ * TT_MS_ID_UNICODE_CS ::+ * Corresponds to a Microsoft WGL4 charmap, matching Unicode. See+ * @FT_ENCODING_UNICODE.+ *+ * TT_MS_ID_SJIS ::+ * Corresponds to SJIS Japanese encoding. See @FT_ENCODING_SJIS.+ *+ * TT_MS_ID_GB2312 ::+ * Corresponds to Simplified Chinese as used in Mainland China. See+ * @FT_ENCODING_GB2312.+ *+ * TT_MS_ID_BIG_5 ::+ * Corresponds to Traditional Chinese as used in Taiwan and Hong Kong.+ * See @FT_ENCODING_BIG5.+ *+ * TT_MS_ID_WANSUNG ::+ * Corresponds to Korean Wansung encoding. See @FT_ENCODING_WANSUNG.+ *+ * TT_MS_ID_JOHAB ::+ * Corresponds to Johab encoding. See @FT_ENCODING_JOHAB.+ *+ * TT_MS_ID_UCS_4 ::+ * Corresponds to UCS-4 or UTF-32 charmaps. This has been added to+ * the OpenType specification version 1.4 (mid-2001.)+ */++#define TT_MS_ID_SYMBOL_CS 0+#define TT_MS_ID_UNICODE_CS 1+#define TT_MS_ID_SJIS 2+#define TT_MS_ID_GB2312 3+#define TT_MS_ID_BIG_5 4+#define TT_MS_ID_WANSUNG 5+#define TT_MS_ID_JOHAB 6+#define TT_MS_ID_UCS_4 10+++ /***********************************************************************+ *+ * @enum:+ * TT_ADOBE_ID_XXX+ *+ * @description:+ * A list of valid values for the `encoding_id' for+ * @TT_PLATFORM_ADOBE charmaps. This is a FreeType-specific extension!+ *+ * @values:+ * TT_ADOBE_ID_STANDARD ::+ * Adobe standard encoding.+ * TT_ADOBE_ID_EXPERT ::+ * Adobe expert encoding.+ * TT_ADOBE_ID_CUSTOM ::+ * Adobe custom encoding.+ * TT_ADOBE_ID_LATIN_1 ::+ * Adobe Latin~1 encoding.+ */++#define TT_ADOBE_ID_STANDARD 0+#define TT_ADOBE_ID_EXPERT 1+#define TT_ADOBE_ID_CUSTOM 2+#define TT_ADOBE_ID_LATIN_1 3+++ /*************************************************************************/+ /* */+ /* Possible values of the language identifier field in the name records */+ /* of the TTF `name' table if the `platform' identifier code is */+ /* TT_PLATFORM_MACINTOSH. */+ /* */+ /* The canonical source for the Apple assigned Language ID's is at */+ /* */+ /* http://fonts.apple.com/TTRefMan/RM06/Chap6name.html */+ /* */+#define TT_MAC_LANGID_ENGLISH 0+#define TT_MAC_LANGID_FRENCH 1+#define TT_MAC_LANGID_GERMAN 2+#define TT_MAC_LANGID_ITALIAN 3+#define TT_MAC_LANGID_DUTCH 4+#define TT_MAC_LANGID_SWEDISH 5+#define TT_MAC_LANGID_SPANISH 6+#define TT_MAC_LANGID_DANISH 7+#define TT_MAC_LANGID_PORTUGUESE 8+#define TT_MAC_LANGID_NORWEGIAN 9+#define TT_MAC_LANGID_HEBREW 10+#define TT_MAC_LANGID_JAPANESE 11+#define TT_MAC_LANGID_ARABIC 12+#define TT_MAC_LANGID_FINNISH 13+#define TT_MAC_LANGID_GREEK 14+#define TT_MAC_LANGID_ICELANDIC 15+#define TT_MAC_LANGID_MALTESE 16+#define TT_MAC_LANGID_TURKISH 17+#define TT_MAC_LANGID_CROATIAN 18+#define TT_MAC_LANGID_CHINESE_TRADITIONAL 19+#define TT_MAC_LANGID_URDU 20+#define TT_MAC_LANGID_HINDI 21+#define TT_MAC_LANGID_THAI 22+#define TT_MAC_LANGID_KOREAN 23+#define TT_MAC_LANGID_LITHUANIAN 24+#define TT_MAC_LANGID_POLISH 25+#define TT_MAC_LANGID_HUNGARIAN 26+#define TT_MAC_LANGID_ESTONIAN 27+#define TT_MAC_LANGID_LETTISH 28+#define TT_MAC_LANGID_SAAMISK 29+#define TT_MAC_LANGID_FAEROESE 30+#define TT_MAC_LANGID_FARSI 31+#define TT_MAC_LANGID_RUSSIAN 32+#define TT_MAC_LANGID_CHINESE_SIMPLIFIED 33+#define TT_MAC_LANGID_FLEMISH 34+#define TT_MAC_LANGID_IRISH 35+#define TT_MAC_LANGID_ALBANIAN 36+#define TT_MAC_LANGID_ROMANIAN 37+#define TT_MAC_LANGID_CZECH 38+#define TT_MAC_LANGID_SLOVAK 39+#define TT_MAC_LANGID_SLOVENIAN 40+#define TT_MAC_LANGID_YIDDISH 41+#define TT_MAC_LANGID_SERBIAN 42+#define TT_MAC_LANGID_MACEDONIAN 43+#define TT_MAC_LANGID_BULGARIAN 44+#define TT_MAC_LANGID_UKRAINIAN 45+#define TT_MAC_LANGID_BYELORUSSIAN 46+#define TT_MAC_LANGID_UZBEK 47+#define TT_MAC_LANGID_KAZAKH 48+#define TT_MAC_LANGID_AZERBAIJANI 49+#define TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT 49+#define TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT 50+#define TT_MAC_LANGID_ARMENIAN 51+#define TT_MAC_LANGID_GEORGIAN 52+#define TT_MAC_LANGID_MOLDAVIAN 53+#define TT_MAC_LANGID_KIRGHIZ 54+#define TT_MAC_LANGID_TAJIKI 55+#define TT_MAC_LANGID_TURKMEN 56+#define TT_MAC_LANGID_MONGOLIAN 57+#define TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT 57+#define TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT 58+#define TT_MAC_LANGID_PASHTO 59+#define TT_MAC_LANGID_KURDISH 60+#define TT_MAC_LANGID_KASHMIRI 61+#define TT_MAC_LANGID_SINDHI 62+#define TT_MAC_LANGID_TIBETAN 63+#define TT_MAC_LANGID_NEPALI 64+#define TT_MAC_LANGID_SANSKRIT 65+#define TT_MAC_LANGID_MARATHI 66+#define TT_MAC_LANGID_BENGALI 67+#define TT_MAC_LANGID_ASSAMESE 68+#define TT_MAC_LANGID_GUJARATI 69+#define TT_MAC_LANGID_PUNJABI 70+#define TT_MAC_LANGID_ORIYA 71+#define TT_MAC_LANGID_MALAYALAM 72+#define TT_MAC_LANGID_KANNADA 73+#define TT_MAC_LANGID_TAMIL 74+#define TT_MAC_LANGID_TELUGU 75+#define TT_MAC_LANGID_SINHALESE 76+#define TT_MAC_LANGID_BURMESE 77+#define TT_MAC_LANGID_KHMER 78+#define TT_MAC_LANGID_LAO 79+#define TT_MAC_LANGID_VIETNAMESE 80+#define TT_MAC_LANGID_INDONESIAN 81+#define TT_MAC_LANGID_TAGALOG 82+#define TT_MAC_LANGID_MALAY_ROMAN_SCRIPT 83+#define TT_MAC_LANGID_MALAY_ARABIC_SCRIPT 84+#define TT_MAC_LANGID_AMHARIC 85+#define TT_MAC_LANGID_TIGRINYA 86+#define TT_MAC_LANGID_GALLA 87+#define TT_MAC_LANGID_SOMALI 88+#define TT_MAC_LANGID_SWAHILI 89+#define TT_MAC_LANGID_RUANDA 90+#define TT_MAC_LANGID_RUNDI 91+#define TT_MAC_LANGID_CHEWA 92+#define TT_MAC_LANGID_MALAGASY 93+#define TT_MAC_LANGID_ESPERANTO 94+#define TT_MAC_LANGID_WELSH 128+#define TT_MAC_LANGID_BASQUE 129+#define TT_MAC_LANGID_CATALAN 130+#define TT_MAC_LANGID_LATIN 131+#define TT_MAC_LANGID_QUECHUA 132+#define TT_MAC_LANGID_GUARANI 133+#define TT_MAC_LANGID_AYMARA 134+#define TT_MAC_LANGID_TATAR 135+#define TT_MAC_LANGID_UIGHUR 136+#define TT_MAC_LANGID_DZONGKHA 137+#define TT_MAC_LANGID_JAVANESE 138+#define TT_MAC_LANGID_SUNDANESE 139+++#if 0 /* these seem to be errors that have been dropped */++#define TT_MAC_LANGID_SCOTTISH_GAELIC 140+#define TT_MAC_LANGID_IRISH_GAELIC 141++#endif+++ /* The following codes are new as of 2000-03-10 */+#define TT_MAC_LANGID_GALICIAN 140+#define TT_MAC_LANGID_AFRIKAANS 141+#define TT_MAC_LANGID_BRETON 142+#define TT_MAC_LANGID_INUKTITUT 143+#define TT_MAC_LANGID_SCOTTISH_GAELIC 144+#define TT_MAC_LANGID_MANX_GAELIC 145+#define TT_MAC_LANGID_IRISH_GAELIC 146+#define TT_MAC_LANGID_TONGAN 147+#define TT_MAC_LANGID_GREEK_POLYTONIC 148+#define TT_MAC_LANGID_GREELANDIC 149+#define TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT 150+++ /*************************************************************************/+ /* */+ /* Possible values of the language identifier field in the name records */+ /* of the TTF `name' table if the `platform' identifier code is */+ /* TT_PLATFORM_MICROSOFT. */+ /* */+ /* The canonical source for the MS assigned LCID's (seems to) be at */+ /* */+ /* http://www.microsoft.com/globaldev/reference/lcid-all.mspx */+ /* */+ /* It used to be at various places, among them */+ /* */+ /* http://www.microsoft.com/typography/OTSPEC/lcid-cp.txt */+ /* http://www.microsoft.com/globaldev/reference/loclanghome.asp */+ /* http://support.microsoft.com/support/kb/articles/Q224/8/04.ASP */+ /* http://msdn.microsoft.com/library/en-us/passport25/ */+ /* NET_Passport_VBScript_Documentation/Single_Sign_In/ */+ /* Advanced_Single_Sign_In/Localization_and_LCIDs.asp */+ /* */+ /* Hopefully, it seems now that the Globaldev site prevails... */+ /* (updated by Antoine, 2004-02-17) */++#define TT_MS_LANGID_ARABIC_GENERAL 0x0001+#define TT_MS_LANGID_ARABIC_SAUDI_ARABIA 0x0401+#define TT_MS_LANGID_ARABIC_IRAQ 0x0801+#define TT_MS_LANGID_ARABIC_EGYPT 0x0c01+#define TT_MS_LANGID_ARABIC_LIBYA 0x1001+#define TT_MS_LANGID_ARABIC_ALGERIA 0x1401+#define TT_MS_LANGID_ARABIC_MOROCCO 0x1801+#define TT_MS_LANGID_ARABIC_TUNISIA 0x1c01+#define TT_MS_LANGID_ARABIC_OMAN 0x2001+#define TT_MS_LANGID_ARABIC_YEMEN 0x2401+#define TT_MS_LANGID_ARABIC_SYRIA 0x2801+#define TT_MS_LANGID_ARABIC_JORDAN 0x2c01+#define TT_MS_LANGID_ARABIC_LEBANON 0x3001+#define TT_MS_LANGID_ARABIC_KUWAIT 0x3401+#define TT_MS_LANGID_ARABIC_UAE 0x3801+#define TT_MS_LANGID_ARABIC_BAHRAIN 0x3c01+#define TT_MS_LANGID_ARABIC_QATAR 0x4001+#define TT_MS_LANGID_BULGARIAN_BULGARIA 0x0402+#define TT_MS_LANGID_CATALAN_SPAIN 0x0403+#define TT_MS_LANGID_CHINESE_GENERAL 0x0004+#define TT_MS_LANGID_CHINESE_TAIWAN 0x0404+#define TT_MS_LANGID_CHINESE_PRC 0x0804+#define TT_MS_LANGID_CHINESE_HONG_KONG 0x0c04+#define TT_MS_LANGID_CHINESE_SINGAPORE 0x1004++#if 1 /* this looks like the correct value */+#define TT_MS_LANGID_CHINESE_MACAU 0x1404+#else /* but beware, Microsoft may change its mind...+ the most recent Word reference has the following: */+#define TT_MS_LANGID_CHINESE_MACAU TT_MS_LANGID_CHINESE_HONG_KONG+#endif++#if 0 /* used only with .NET `cultures'; commented out */+#define TT_MS_LANGID_CHINESE_TRADITIONAL 0x7C04+#endif++#define TT_MS_LANGID_CZECH_CZECH_REPUBLIC 0x0405+#define TT_MS_LANGID_DANISH_DENMARK 0x0406+#define TT_MS_LANGID_GERMAN_GERMANY 0x0407+#define TT_MS_LANGID_GERMAN_SWITZERLAND 0x0807+#define TT_MS_LANGID_GERMAN_AUSTRIA 0x0c07+#define TT_MS_LANGID_GERMAN_LUXEMBOURG 0x1007+#define TT_MS_LANGID_GERMAN_LIECHTENSTEI 0x1407+#define TT_MS_LANGID_GREEK_GREECE 0x0408++ /* don't ask what this one means... It is commented out currently. */+#if 0+#define TT_MS_LANGID_GREEK_GREECE2 0x2008+#endif++#define TT_MS_LANGID_ENGLISH_GENERAL 0x0009+#define TT_MS_LANGID_ENGLISH_UNITED_STATES 0x0409+#define TT_MS_LANGID_ENGLISH_UNITED_KINGDOM 0x0809+#define TT_MS_LANGID_ENGLISH_AUSTRALIA 0x0c09+#define TT_MS_LANGID_ENGLISH_CANADA 0x1009+#define TT_MS_LANGID_ENGLISH_NEW_ZEALAND 0x1409+#define TT_MS_LANGID_ENGLISH_IRELAND 0x1809+#define TT_MS_LANGID_ENGLISH_SOUTH_AFRICA 0x1c09+#define TT_MS_LANGID_ENGLISH_JAMAICA 0x2009+#define TT_MS_LANGID_ENGLISH_CARIBBEAN 0x2409+#define TT_MS_LANGID_ENGLISH_BELIZE 0x2809+#define TT_MS_LANGID_ENGLISH_TRINIDAD 0x2c09+#define TT_MS_LANGID_ENGLISH_ZIMBABWE 0x3009+#define TT_MS_LANGID_ENGLISH_PHILIPPINES 0x3409+#define TT_MS_LANGID_ENGLISH_INDONESIA 0x3809+#define TT_MS_LANGID_ENGLISH_HONG_KONG 0x3c09+#define TT_MS_LANGID_ENGLISH_INDIA 0x4009+#define TT_MS_LANGID_ENGLISH_MALAYSIA 0x4409+#define TT_MS_LANGID_ENGLISH_SINGAPORE 0x4809+#define TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT 0x040a+#define TT_MS_LANGID_SPANISH_MEXICO 0x080a+#define TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT 0x0c0a+#define TT_MS_LANGID_SPANISH_GUATEMALA 0x100a+#define TT_MS_LANGID_SPANISH_COSTA_RICA 0x140a+#define TT_MS_LANGID_SPANISH_PANAMA 0x180a+#define TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC 0x1c0a+#define TT_MS_LANGID_SPANISH_VENEZUELA 0x200a+#define TT_MS_LANGID_SPANISH_COLOMBIA 0x240a+#define TT_MS_LANGID_SPANISH_PERU 0x280a+#define TT_MS_LANGID_SPANISH_ARGENTINA 0x2c0a+#define TT_MS_LANGID_SPANISH_ECUADOR 0x300a+#define TT_MS_LANGID_SPANISH_CHILE 0x340a+#define TT_MS_LANGID_SPANISH_URUGUAY 0x380a+#define TT_MS_LANGID_SPANISH_PARAGUAY 0x3c0a+#define TT_MS_LANGID_SPANISH_BOLIVIA 0x400a+#define TT_MS_LANGID_SPANISH_EL_SALVADOR 0x440a+#define TT_MS_LANGID_SPANISH_HONDURAS 0x480a+#define TT_MS_LANGID_SPANISH_NICARAGUA 0x4c0a+#define TT_MS_LANGID_SPANISH_PUERTO_RICO 0x500a+#define TT_MS_LANGID_SPANISH_UNITED_STATES 0x540a+ /* The following ID blatantly violate MS specs by using a */+ /* sublanguage > 0x1F. */+#define TT_MS_LANGID_SPANISH_LATIN_AMERICA 0xE40aU+#define TT_MS_LANGID_FINNISH_FINLAND 0x040b+#define TT_MS_LANGID_FRENCH_FRANCE 0x040c+#define TT_MS_LANGID_FRENCH_BELGIUM 0x080c+#define TT_MS_LANGID_FRENCH_CANADA 0x0c0c+#define TT_MS_LANGID_FRENCH_SWITZERLAND 0x100c+#define TT_MS_LANGID_FRENCH_LUXEMBOURG 0x140c+#define TT_MS_LANGID_FRENCH_MONACO 0x180c+#define TT_MS_LANGID_FRENCH_WEST_INDIES 0x1c0c+#define TT_MS_LANGID_FRENCH_REUNION 0x200c+#define TT_MS_LANGID_FRENCH_CONGO 0x240c+ /* which was formerly: */+#define TT_MS_LANGID_FRENCH_ZAIRE TT_MS_LANGID_FRENCH_CONGO+#define TT_MS_LANGID_FRENCH_SENEGAL 0x280c+#define TT_MS_LANGID_FRENCH_CAMEROON 0x2c0c+#define TT_MS_LANGID_FRENCH_COTE_D_IVOIRE 0x300c+#define TT_MS_LANGID_FRENCH_MALI 0x340c+#define TT_MS_LANGID_FRENCH_MOROCCO 0x380c+#define TT_MS_LANGID_FRENCH_HAITI 0x3c0c+ /* and another violation of the spec (see 0xE40aU) */+#define TT_MS_LANGID_FRENCH_NORTH_AFRICA 0xE40cU+#define TT_MS_LANGID_HEBREW_ISRAEL 0x040d+#define TT_MS_LANGID_HUNGARIAN_HUNGARY 0x040e+#define TT_MS_LANGID_ICELANDIC_ICELAND 0x040f+#define TT_MS_LANGID_ITALIAN_ITALY 0x0410+#define TT_MS_LANGID_ITALIAN_SWITZERLAND 0x0810+#define TT_MS_LANGID_JAPANESE_JAPAN 0x0411+#define TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA 0x0412+#define TT_MS_LANGID_KOREAN_JOHAB_KOREA 0x0812+#define TT_MS_LANGID_DUTCH_NETHERLANDS 0x0413+#define TT_MS_LANGID_DUTCH_BELGIUM 0x0813+#define TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL 0x0414+#define TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK 0x0814+#define TT_MS_LANGID_POLISH_POLAND 0x0415+#define TT_MS_LANGID_PORTUGUESE_BRAZIL 0x0416+#define TT_MS_LANGID_PORTUGUESE_PORTUGAL 0x0816+#define TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND 0x0417+#define TT_MS_LANGID_ROMANIAN_ROMANIA 0x0418+#define TT_MS_LANGID_MOLDAVIAN_MOLDAVIA 0x0818+#define TT_MS_LANGID_RUSSIAN_RUSSIA 0x0419+#define TT_MS_LANGID_RUSSIAN_MOLDAVIA 0x0819+#define TT_MS_LANGID_CROATIAN_CROATIA 0x041a+#define TT_MS_LANGID_SERBIAN_SERBIA_LATIN 0x081a+#define TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC 0x0c1a++#if 0 /* this used to be this value, but it looks like we were wrong */+#define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA 0x101a+#else /* current sources say */+#define TT_MS_LANGID_CROATIAN_BOSNIA_HERZEGOVINA 0x101a+#define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA 0x141a+ /* and XPsp2 Platform SDK added (2004-07-26) */+ /* Names are shortened to be significant within 40 chars. */+#define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_LATIN 0x181a+#define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_CYRILLIC 0x181a+#endif++#define TT_MS_LANGID_SLOVAK_SLOVAKIA 0x041b+#define TT_MS_LANGID_ALBANIAN_ALBANIA 0x041c+#define TT_MS_LANGID_SWEDISH_SWEDEN 0x041d+#define TT_MS_LANGID_SWEDISH_FINLAND 0x081d+#define TT_MS_LANGID_THAI_THAILAND 0x041e+#define TT_MS_LANGID_TURKISH_TURKEY 0x041f+#define TT_MS_LANGID_URDU_PAKISTAN 0x0420+#define TT_MS_LANGID_URDU_INDIA 0x0820+#define TT_MS_LANGID_INDONESIAN_INDONESIA 0x0421+#define TT_MS_LANGID_UKRAINIAN_UKRAINE 0x0422+#define TT_MS_LANGID_BELARUSIAN_BELARUS 0x0423+#define TT_MS_LANGID_SLOVENE_SLOVENIA 0x0424+#define TT_MS_LANGID_ESTONIAN_ESTONIA 0x0425+#define TT_MS_LANGID_LATVIAN_LATVIA 0x0426+#define TT_MS_LANGID_LITHUANIAN_LITHUANIA 0x0427+#define TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA 0x0827+#define TT_MS_LANGID_TAJIK_TAJIKISTAN 0x0428+#define TT_MS_LANGID_FARSI_IRAN 0x0429+#define TT_MS_LANGID_VIETNAMESE_VIET_NAM 0x042a+#define TT_MS_LANGID_ARMENIAN_ARMENIA 0x042b+#define TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN 0x042c+#define TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC 0x082c+#define TT_MS_LANGID_BASQUE_SPAIN 0x042d+#define TT_MS_LANGID_SORBIAN_GERMANY 0x042e+#define TT_MS_LANGID_MACEDONIAN_MACEDONIA 0x042f+#define TT_MS_LANGID_SUTU_SOUTH_AFRICA 0x0430+#define TT_MS_LANGID_TSONGA_SOUTH_AFRICA 0x0431+#define TT_MS_LANGID_TSWANA_SOUTH_AFRICA 0x0432+#define TT_MS_LANGID_VENDA_SOUTH_AFRICA 0x0433+#define TT_MS_LANGID_XHOSA_SOUTH_AFRICA 0x0434+#define TT_MS_LANGID_ZULU_SOUTH_AFRICA 0x0435+#define TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA 0x0436+#define TT_MS_LANGID_GEORGIAN_GEORGIA 0x0437+#define TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS 0x0438+#define TT_MS_LANGID_HINDI_INDIA 0x0439+#define TT_MS_LANGID_MALTESE_MALTA 0x043a+ /* Added by XPsp2 Platform SDK (2004-07-26) */+#define TT_MS_LANGID_SAMI_NORTHERN_NORWAY 0x043b+#define TT_MS_LANGID_SAMI_NORTHERN_SWEDEN 0x083b+#define TT_MS_LANGID_SAMI_NORTHERN_FINLAND 0x0C3b+#define TT_MS_LANGID_SAMI_LULE_NORWAY 0x103b+#define TT_MS_LANGID_SAMI_LULE_SWEDEN 0x143b+#define TT_MS_LANGID_SAMI_SOUTHERN_NORWAY 0x183b+#define TT_MS_LANGID_SAMI_SOUTHERN_SWEDEN 0x1C3b+#define TT_MS_LANGID_SAMI_SKOLT_FINLAND 0x203b+#define TT_MS_LANGID_SAMI_INARI_FINLAND 0x243b+ /* ... and we also keep our old identifier... */+#define TT_MS_LANGID_SAAMI_LAPONIA 0x043b++#if 0 /* this seems to be a previous inversion */+#define TT_MS_LANGID_IRISH_GAELIC_IRELAND 0x043c+#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM 0x083c+#else+#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM 0x083c+#define TT_MS_LANGID_IRISH_GAELIC_IRELAND 0x043c+#endif++#define TT_MS_LANGID_YIDDISH_GERMANY 0x043d+#define TT_MS_LANGID_MALAY_MALAYSIA 0x043e+#define TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM 0x083e+#define TT_MS_LANGID_KAZAK_KAZAKSTAN 0x043f+#define TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN /* Cyrillic*/ 0x0440+ /* alias declared in Windows 2000 */+#define TT_MS_LANGID_KIRGHIZ_KIRGHIZ_REPUBLIC \+ TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN++#define TT_MS_LANGID_SWAHILI_KENYA 0x0441+#define TT_MS_LANGID_TURKMEN_TURKMENISTAN 0x0442+#define TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN 0x0443+#define TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC 0x0843+#define TT_MS_LANGID_TATAR_TATARSTAN 0x0444+#define TT_MS_LANGID_BENGALI_INDIA 0x0445+#define TT_MS_LANGID_BENGALI_BANGLADESH 0x0845+#define TT_MS_LANGID_PUNJABI_INDIA 0x0446+#define TT_MS_LANGID_PUNJABI_ARABIC_PAKISTAN 0x0846+#define TT_MS_LANGID_GUJARATI_INDIA 0x0447+#define TT_MS_LANGID_ORIYA_INDIA 0x0448+#define TT_MS_LANGID_TAMIL_INDIA 0x0449+#define TT_MS_LANGID_TELUGU_INDIA 0x044a+#define TT_MS_LANGID_KANNADA_INDIA 0x044b+#define TT_MS_LANGID_MALAYALAM_INDIA 0x044c+#define TT_MS_LANGID_ASSAMESE_INDIA 0x044d+#define TT_MS_LANGID_MARATHI_INDIA 0x044e+#define TT_MS_LANGID_SANSKRIT_INDIA 0x044f+#define TT_MS_LANGID_MONGOLIAN_MONGOLIA /* Cyrillic */ 0x0450+#define TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIAN 0x0850+#define TT_MS_LANGID_TIBETAN_CHINA 0x0451+ /* Don't use the next constant! It has */+ /* (1) the wrong spelling (Dzonghka) */+ /* (2) Microsoft doesn't officially define it -- */+ /* at least it is not in the List of Local */+ /* ID Values. */+ /* (3) Dzongkha is not the same language as */+ /* Tibetan, so merging it is wrong anyway. */+ /* */+ /* TT_MS_LANGID_TIBETAN_BHUTAN is correct, BTW. */+#define TT_MS_LANGID_DZONGHKA_BHUTAN 0x0851++#if 0+ /* the following used to be defined */+#define TT_MS_LANGID_TIBETAN_BHUTAN 0x0451+ /* ... but it was changed; */+#else+ /* So we will continue to #define it, but with the correct value */+#define TT_MS_LANGID_TIBETAN_BHUTAN TT_MS_LANGID_DZONGHKA_BHUTAN+#endif++#define TT_MS_LANGID_WELSH_WALES 0x0452+#define TT_MS_LANGID_KHMER_CAMBODIA 0x0453+#define TT_MS_LANGID_LAO_LAOS 0x0454+#define TT_MS_LANGID_BURMESE_MYANMAR 0x0455+#define TT_MS_LANGID_GALICIAN_SPAIN 0x0456+#define TT_MS_LANGID_KONKANI_INDIA 0x0457+#define TT_MS_LANGID_MANIPURI_INDIA /* Bengali */ 0x0458+#define TT_MS_LANGID_SINDHI_INDIA /* Arabic */ 0x0459+#define TT_MS_LANGID_SINDHI_PAKISTAN 0x0859+ /* Missing a LCID for Sindhi in Devanagari script */+#define TT_MS_LANGID_SYRIAC_SYRIA 0x045a+#define TT_MS_LANGID_SINHALESE_SRI_LANKA 0x045b+#define TT_MS_LANGID_CHEROKEE_UNITED_STATES 0x045c+#define TT_MS_LANGID_INUKTITUT_CANADA 0x045d+#define TT_MS_LANGID_AMHARIC_ETHIOPIA 0x045e+#define TT_MS_LANGID_TAMAZIGHT_MOROCCO /* Arabic */ 0x045f+#define TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN 0x085f+ /* Missing a LCID for Tifinagh script */+#define TT_MS_LANGID_KASHMIRI_PAKISTAN /* Arabic */ 0x0460+ /* Spelled this way by XPsp2 Platform SDK (2004-07-26) */+ /* script is yet unclear... might be Arabic, Nagari or Sharada */+#define TT_MS_LANGID_KASHMIRI_SASIA 0x0860+ /* ... and aliased (by MS) for compatibility reasons. */+#define TT_MS_LANGID_KASHMIRI_INDIA TT_MS_LANGID_KASHMIRI_SASIA+#define TT_MS_LANGID_NEPALI_NEPAL 0x0461+#define TT_MS_LANGID_NEPALI_INDIA 0x0861+#define TT_MS_LANGID_FRISIAN_NETHERLANDS 0x0462+#define TT_MS_LANGID_PASHTO_AFGHANISTAN 0x0463+#define TT_MS_LANGID_FILIPINO_PHILIPPINES 0x0464+#define TT_MS_LANGID_DHIVEHI_MALDIVES 0x0465+ /* alias declared in Windows 2000 */+#define TT_MS_LANGID_DIVEHI_MALDIVES TT_MS_LANGID_DHIVEHI_MALDIVES+#define TT_MS_LANGID_EDO_NIGERIA 0x0466+#define TT_MS_LANGID_FULFULDE_NIGERIA 0x0467+#define TT_MS_LANGID_HAUSA_NIGERIA 0x0468+#define TT_MS_LANGID_IBIBIO_NIGERIA 0x0469+#define TT_MS_LANGID_YORUBA_NIGERIA 0x046a+#define TT_MS_LANGID_QUECHUA_BOLIVIA 0x046b+#define TT_MS_LANGID_QUECHUA_ECUADOR 0x086b+#define TT_MS_LANGID_QUECHUA_PERU 0x0c6b+#define TT_MS_LANGID_SEPEDI_SOUTH_AFRICA 0x046c+ /* Also spelled by XPsp2 Platform SDK (2004-07-26) */+#define TT_MS_LANGID_SOTHO_SOUTHERN_SOUTH_AFRICA \+ TT_MS_LANGID_SEPEDI_SOUTH_AFRICA+ /* language codes 0x046d, 0x046e and 0x046f are (still) unknown. */+#define TT_MS_LANGID_IGBO_NIGERIA 0x0470+#define TT_MS_LANGID_KANURI_NIGERIA 0x0471+#define TT_MS_LANGID_OROMO_ETHIOPIA 0x0472+#define TT_MS_LANGID_TIGRIGNA_ETHIOPIA 0x0473+#define TT_MS_LANGID_TIGRIGNA_ERYTHREA 0x0873+ /* also spelled in the `Passport SDK' list as: */+#define TT_MS_LANGID_TIGRIGNA_ERYTREA TT_MS_LANGID_TIGRIGNA_ERYTHREA+#define TT_MS_LANGID_GUARANI_PARAGUAY 0x0474+#define TT_MS_LANGID_HAWAIIAN_UNITED_STATES 0x0475+#define TT_MS_LANGID_LATIN 0x0476+#define TT_MS_LANGID_SOMALI_SOMALIA 0x0477+ /* Note: Yi does not have a (proper) ISO 639-2 code, since it is mostly */+ /* not written (but OTOH the peculiar writing system is worth */+ /* studying). */+#define TT_MS_LANGID_YI_CHINA 0x0478+#define TT_MS_LANGID_PAPIAMENTU_NETHERLANDS_ANTILLES 0x0479+ /* language codes from 0x047a to 0x047f are (still) unknown. */+#define TT_MS_LANGID_UIGHUR_CHINA 0x0480+#define TT_MS_LANGID_MAORI_NEW_ZEALAND 0x0481++#if 0 /* not deemed useful for fonts */+#define TT_MS_LANGID_HUMAN_INTERFACE_DEVICE 0x04ff+#endif+++ /*************************************************************************/+ /* */+ /* Possible values of the `name' identifier field in the name records of */+ /* the TTF `name' table. These values are platform independent. */+ /* */+#define TT_NAME_ID_COPYRIGHT 0+#define TT_NAME_ID_FONT_FAMILY 1+#define TT_NAME_ID_FONT_SUBFAMILY 2+#define TT_NAME_ID_UNIQUE_ID 3+#define TT_NAME_ID_FULL_NAME 4+#define TT_NAME_ID_VERSION_STRING 5+#define TT_NAME_ID_PS_NAME 6+#define TT_NAME_ID_TRADEMARK 7++ /* the following values are from the OpenType spec */+#define TT_NAME_ID_MANUFACTURER 8+#define TT_NAME_ID_DESIGNER 9+#define TT_NAME_ID_DESCRIPTION 10+#define TT_NAME_ID_VENDOR_URL 11+#define TT_NAME_ID_DESIGNER_URL 12+#define TT_NAME_ID_LICENSE 13+#define TT_NAME_ID_LICENSE_URL 14+ /* number 15 is reserved */+#define TT_NAME_ID_PREFERRED_FAMILY 16+#define TT_NAME_ID_PREFERRED_SUBFAMILY 17+#define TT_NAME_ID_MAC_FULL_NAME 18++ /* The following code is new as of 2000-01-21 */+#define TT_NAME_ID_SAMPLE_TEXT 19++ /* This is new in OpenType 1.3 */+#define TT_NAME_ID_CID_FINDFONT_NAME 20++ /* This is new in OpenType 1.5 */+#define TT_NAME_ID_WWS_FAMILY 21+#define TT_NAME_ID_WWS_SUBFAMILY 22+++ /*************************************************************************/+ /* */+ /* Bit mask values for the Unicode Ranges from the TTF `OS2 ' table. */+ /* */+ /* Updated 08-Nov-2008. */+ /* */++ /* Bit 0 Basic Latin */+#define TT_UCR_BASIC_LATIN (1L << 0) /* U+0020-U+007E */+ /* Bit 1 C1 Controls and Latin-1 Supplement */+#define TT_UCR_LATIN1_SUPPLEMENT (1L << 1) /* U+0080-U+00FF */+ /* Bit 2 Latin Extended-A */+#define TT_UCR_LATIN_EXTENDED_A (1L << 2) /* U+0100-U+017F */+ /* Bit 3 Latin Extended-B */+#define TT_UCR_LATIN_EXTENDED_B (1L << 3) /* U+0180-U+024F */+ /* Bit 4 IPA Extensions */+ /* Phonetic Extensions */+ /* Phonetic Extensions Supplement */+#define TT_UCR_IPA_EXTENSIONS (1L << 4) /* U+0250-U+02AF */+ /* U+1D00-U+1D7F */+ /* U+1D80-U+1DBF */+ /* Bit 5 Spacing Modifier Letters */+ /* Modifier Tone Letters */+#define TT_UCR_SPACING_MODIFIER (1L << 5) /* U+02B0-U+02FF */+ /* U+A700-U+A71F */+ /* Bit 6 Combining Diacritical Marks */+ /* Combining Diacritical Marks Supplement */+#define TT_UCR_COMBINING_DIACRITICS (1L << 6) /* U+0300-U+036F */+ /* U+1DC0-U+1DFF */+ /* Bit 7 Greek and Coptic */+#define TT_UCR_GREEK (1L << 7) /* U+0370-U+03FF */+ /* Bit 8 Coptic */+#define TT_UCR_COPTIC (1L << 8) /* U+2C80-U+2CFF */+ /* Bit 9 Cyrillic */+ /* Cyrillic Supplement */+ /* Cyrillic Extended-A */+ /* Cyrillic Extended-B */+#define TT_UCR_CYRILLIC (1L << 9) /* U+0400-U+04FF */+ /* U+0500-U+052F */+ /* U+2DE0-U+2DFF */+ /* U+A640-U+A69F */+ /* Bit 10 Armenian */+#define TT_UCR_ARMENIAN (1L << 10) /* U+0530-U+058F */+ /* Bit 11 Hebrew */+#define TT_UCR_HEBREW (1L << 11) /* U+0590-U+05FF */+ /* Bit 12 Vai */+#define TT_UCR_VAI (1L << 12) /* U+A500-U+A63F */+ /* Bit 13 Arabic */+ /* Arabic Supplement */+#define TT_UCR_ARABIC (1L << 13) /* U+0600-U+06FF */+ /* U+0750-U+077F */+ /* Bit 14 NKo */+#define TT_UCR_NKO (1L << 14) /* U+07C0-U+07FF */+ /* Bit 15 Devanagari */+#define TT_UCR_DEVANAGARI (1L << 15) /* U+0900-U+097F */+ /* Bit 16 Bengali */+#define TT_UCR_BENGALI (1L << 16) /* U+0980-U+09FF */+ /* Bit 17 Gurmukhi */+#define TT_UCR_GURMUKHI (1L << 17) /* U+0A00-U+0A7F */+ /* Bit 18 Gujarati */+#define TT_UCR_GUJARATI (1L << 18) /* U+0A80-U+0AFF */+ /* Bit 19 Oriya */+#define TT_UCR_ORIYA (1L << 19) /* U+0B00-U+0B7F */+ /* Bit 20 Tamil */+#define TT_UCR_TAMIL (1L << 20) /* U+0B80-U+0BFF */+ /* Bit 21 Telugu */+#define TT_UCR_TELUGU (1L << 21) /* U+0C00-U+0C7F */+ /* Bit 22 Kannada */+#define TT_UCR_KANNADA (1L << 22) /* U+0C80-U+0CFF */+ /* Bit 23 Malayalam */+#define TT_UCR_MALAYALAM (1L << 23) /* U+0D00-U+0D7F */+ /* Bit 24 Thai */+#define TT_UCR_THAI (1L << 24) /* U+0E00-U+0E7F */+ /* Bit 25 Lao */+#define TT_UCR_LAO (1L << 25) /* U+0E80-U+0EFF */+ /* Bit 26 Georgian */+ /* Georgian Supplement */+#define TT_UCR_GEORGIAN (1L << 26) /* U+10A0-U+10FF */+ /* U+2D00-U+2D2F */+ /* Bit 27 Balinese */+#define TT_UCR_BALINESE (1L << 27) /* U+1B00-U+1B7F */+ /* Bit 28 Hangul Jamo */+#define TT_UCR_HANGUL_JAMO (1L << 28) /* U+1100-U+11FF */+ /* Bit 29 Latin Extended Additional */+ /* Latin Extended-C */+ /* Latin Extended-D */+#define TT_UCR_LATIN_EXTENDED_ADDITIONAL (1L << 29) /* U+1E00-U+1EFF */+ /* U+2C60-U+2C7F */+ /* U+A720-U+A7FF */+ /* Bit 30 Greek Extended */+#define TT_UCR_GREEK_EXTENDED (1L << 30) /* U+1F00-U+1FFF */+ /* Bit 31 General Punctuation */+ /* Supplemental Punctuation */+#define TT_UCR_GENERAL_PUNCTUATION (1L << 31) /* U+2000-U+206F */+ /* U+2E00-U+2E7F */+ /* Bit 32 Superscripts And Subscripts */+#define TT_UCR_SUPERSCRIPTS_SUBSCRIPTS (1L << 0) /* U+2070-U+209F */+ /* Bit 33 Currency Symbols */+#define TT_UCR_CURRENCY_SYMBOLS (1L << 1) /* U+20A0-U+20CF */+ /* Bit 34 Combining Diacritical Marks For Symbols */+#define TT_UCR_COMBINING_DIACRITICS_SYMB (1L << 2) /* U+20D0-U+20FF */+ /* Bit 35 Letterlike Symbols */+#define TT_UCR_LETTERLIKE_SYMBOLS (1L << 3) /* U+2100-U+214F */+ /* Bit 36 Number Forms */+#define TT_UCR_NUMBER_FORMS (1L << 4) /* U+2150-U+218F */+ /* Bit 37 Arrows */+ /* Supplemental Arrows-A */+ /* Supplemental Arrows-B */+ /* Miscellaneous Symbols and Arrows */+#define TT_UCR_ARROWS (1L << 5) /* U+2190-U+21FF */+ /* U+27F0-U+27FF */+ /* U+2900-U+297F */+ /* U+2B00-U+2BFF */+ /* Bit 38 Mathematical Operators */+ /* Supplemental Mathematical Operators */+ /* Miscellaneous Mathematical Symbols-A */+ /* Miscellaneous Mathematical Symbols-B */+#define TT_UCR_MATHEMATICAL_OPERATORS (1L << 6) /* U+2200-U+22FF */+ /* U+2A00-U+2AFF */+ /* U+27C0-U+27EF */+ /* U+2980-U+29FF */+ /* Bit 39 Miscellaneous Technical */+#define TT_UCR_MISCELLANEOUS_TECHNICAL (1L << 7) /* U+2300-U+23FF */+ /* Bit 40 Control Pictures */+#define TT_UCR_CONTROL_PICTURES (1L << 8) /* U+2400-U+243F */+ /* Bit 41 Optical Character Recognition */+#define TT_UCR_OCR (1L << 9) /* U+2440-U+245F */+ /* Bit 42 Enclosed Alphanumerics */+#define TT_UCR_ENCLOSED_ALPHANUMERICS (1L << 10) /* U+2460-U+24FF */+ /* Bit 43 Box Drawing */+#define TT_UCR_BOX_DRAWING (1L << 11) /* U+2500-U+257F */+ /* Bit 44 Block Elements */+#define TT_UCR_BLOCK_ELEMENTS (1L << 12) /* U+2580-U+259F */+ /* Bit 45 Geometric Shapes */+#define TT_UCR_GEOMETRIC_SHAPES (1L << 13) /* U+25A0-U+25FF */+ /* Bit 46 Miscellaneous Symbols */+#define TT_UCR_MISCELLANEOUS_SYMBOLS (1L << 14) /* U+2600-U+26FF */+ /* Bit 47 Dingbats */+#define TT_UCR_DINGBATS (1L << 15) /* U+2700-U+27BF */+ /* Bit 48 CJK Symbols and Punctuation */+#define TT_UCR_CJK_SYMBOLS (1L << 16) /* U+3000-U+303F */+ /* Bit 49 Hiragana */+#define TT_UCR_HIRAGANA (1L << 17) /* U+3040-U+309F */+ /* Bit 50 Katakana */+ /* Katakana Phonetic Extensions */+#define TT_UCR_KATAKANA (1L << 18) /* U+30A0-U+30FF */+ /* U+31F0-U+31FF */+ /* Bit 51 Bopomofo */+ /* Bopomofo Extended */+#define TT_UCR_BOPOMOFO (1L << 19) /* U+3100-U+312F */+ /* U+31A0-U+31BF */+ /* Bit 52 Hangul Compatibility Jamo */+#define TT_UCR_HANGUL_COMPATIBILITY_JAMO (1L << 20) /* U+3130-U+318F */+ /* Bit 53 Phags-Pa */+#define TT_UCR_CJK_MISC (1L << 21) /* U+A840-U+A87F */+#define TT_UCR_KANBUN TT_UCR_CJK_MISC /* deprecated */+#define TT_UCR_PHAGSPA+ /* Bit 54 Enclosed CJK Letters and Months */+#define TT_UCR_ENCLOSED_CJK_LETTERS_MONTHS (1L << 22) /* U+3200-U+32FF */+ /* Bit 55 CJK Compatibility */+#define TT_UCR_CJK_COMPATIBILITY (1L << 23) /* U+3300-U+33FF */+ /* Bit 56 Hangul Syllables */+#define TT_UCR_HANGUL (1L << 24) /* U+AC00-U+D7A3 */+ /* Bit 57 High Surrogates */+ /* High Private Use Surrogates */+ /* Low Surrogates */+ /* */+ /* According to OpenType specs v.1.3+, */+ /* setting bit 57 implies that there is */+ /* at least one codepoint beyond the */+ /* Basic Multilingual Plane that is */+ /* supported by this font. So it really */+ /* means >= U+10000 */+#define TT_UCR_SURROGATES (1L << 25) /* U+D800-U+DB7F */+ /* U+DB80-U+DBFF */+ /* U+DC00-U+DFFF */+#define TT_UCR_NON_PLANE_0 TT_UCR_SURROGATES+ /* Bit 58 Phoenician */+#define TT_UCR_PHOENICIAN (1L << 26) /*U+10900-U+1091F*/+ /* Bit 59 CJK Unified Ideographs */+ /* CJK Radicals Supplement */+ /* Kangxi Radicals */+ /* Ideographic Description Characters */+ /* CJK Unified Ideographs Extension A */+ /* CJK Unified Ideographs Extension B */+ /* Kanbun */+#define TT_UCR_CJK_UNIFIED_IDEOGRAPHS (1L << 27) /* U+4E00-U+9FFF */+ /* U+2E80-U+2EFF */+ /* U+2F00-U+2FDF */+ /* U+2FF0-U+2FFF */+ /* U+3400-U+4DB5 */+ /*U+20000-U+2A6DF*/+ /* U+3190-U+319F */+ /* Bit 60 Private Use */+#define TT_UCR_PRIVATE_USE (1L << 28) /* U+E000-U+F8FF */+ /* Bit 61 CJK Strokes */+ /* CJK Compatibility Ideographs */+ /* CJK Compatibility Ideographs Supplement */+#define TT_UCR_CJK_COMPATIBILITY_IDEOGRAPHS (1L << 29) /* U+31C0-U+31EF */+ /* U+F900-U+FAFF */+ /*U+2F800-U+2FA1F*/+ /* Bit 62 Alphabetic Presentation Forms */+#define TT_UCR_ALPHABETIC_PRESENTATION_FORMS (1L << 30) /* U+FB00-U+FB4F */+ /* Bit 63 Arabic Presentation Forms-A */+#define TT_UCR_ARABIC_PRESENTATIONS_A (1L << 31) /* U+FB50-U+FDFF */+ /* Bit 64 Combining Half Marks */+#define TT_UCR_COMBINING_HALF_MARKS (1L << 0) /* U+FE20-U+FE2F */+ /* Bit 65 Vertical forms */+ /* CJK Compatibility Forms */+#define TT_UCR_CJK_COMPATIBILITY_FORMS (1L << 1) /* U+FE10-U+FE1F */+ /* U+FE30-U+FE4F */+ /* Bit 66 Small Form Variants */+#define TT_UCR_SMALL_FORM_VARIANTS (1L << 2) /* U+FE50-U+FE6F */+ /* Bit 67 Arabic Presentation Forms-B */+#define TT_UCR_ARABIC_PRESENTATIONS_B (1L << 3) /* U+FE70-U+FEFE */+ /* Bit 68 Halfwidth and Fullwidth Forms */+#define TT_UCR_HALFWIDTH_FULLWIDTH_FORMS (1L << 4) /* U+FF00-U+FFEF */+ /* Bit 69 Specials */+#define TT_UCR_SPECIALS (1L << 5) /* U+FFF0-U+FFFD */+ /* Bit 70 Tibetan */+#define TT_UCR_TIBETAN (1L << 6) /* U+0F00-U+0FFF */+ /* Bit 71 Syriac */+#define TT_UCR_SYRIAC (1L << 7) /* U+0700-U+074F */+ /* Bit 72 Thaana */+#define TT_UCR_THAANA (1L << 8) /* U+0780-U+07BF */+ /* Bit 73 Sinhala */+#define TT_UCR_SINHALA (1L << 9) /* U+0D80-U+0DFF */+ /* Bit 74 Myanmar */+#define TT_UCR_MYANMAR (1L << 10) /* U+1000-U+109F */+ /* Bit 75 Ethiopic */+ /* Ethiopic Supplement */+ /* Ethiopic Extended */+#define TT_UCR_ETHIOPIC (1L << 11) /* U+1200-U+137F */+ /* U+1380-U+139F */+ /* U+2D80-U+2DDF */+ /* Bit 76 Cherokee */+#define TT_UCR_CHEROKEE (1L << 12) /* U+13A0-U+13FF */+ /* Bit 77 Unified Canadian Aboriginal Syllabics */+#define TT_UCR_CANADIAN_ABORIGINAL_SYLLABICS (1L << 13) /* U+1400-U+167F */+ /* Bit 78 Ogham */+#define TT_UCR_OGHAM (1L << 14) /* U+1680-U+169F */+ /* Bit 79 Runic */+#define TT_UCR_RUNIC (1L << 15) /* U+16A0-U+16FF */+ /* Bit 80 Khmer */+ /* Khmer Symbols */+#define TT_UCR_KHMER (1L << 16) /* U+1780-U+17FF */+ /* U+19E0-U+19FF */+ /* Bit 81 Mongolian */+#define TT_UCR_MONGOLIAN (1L << 17) /* U+1800-U+18AF */+ /* Bit 82 Braille Patterns */+#define TT_UCR_BRAILLE (1L << 18) /* U+2800-U+28FF */+ /* Bit 83 Yi Syllables */+ /* Yi Radicals */+#define TT_UCR_YI (1L << 19) /* U+A000-U+A48F */+ /* U+A490-U+A4CF */+ /* Bit 84 Tagalog */+ /* Hanunoo */+ /* Buhid */+ /* Tagbanwa */+#define TT_UCR_PHILIPPINE (1L << 20) /* U+1700-U+171F */+ /* U+1720-U+173F */+ /* U+1740-U+175F */+ /* U+1760-U+177F */+ /* Bit 85 Old Italic */+#define TT_UCR_OLD_ITALIC (1L << 21) /*U+10300-U+1032F*/+ /* Bit 86 Gothic */+#define TT_UCR_GOTHIC (1L << 22) /*U+10330-U+1034F*/+ /* Bit 87 Deseret */+#define TT_UCR_DESERET (1L << 23) /*U+10400-U+1044F*/+ /* Bit 88 Byzantine Musical Symbols */+ /* Musical Symbols */+ /* Ancient Greek Musical Notation */+#define TT_UCR_MUSICAL_SYMBOLS (1L << 24) /*U+1D000-U+1D0FF*/+ /*U+1D100-U+1D1FF*/+ /*U+1D200-U+1D24F*/+ /* Bit 89 Mathematical Alphanumeric Symbols */+#define TT_UCR_MATH_ALPHANUMERIC_SYMBOLS (1L << 25) /*U+1D400-U+1D7FF*/+ /* Bit 90 Private Use (plane 15) */+ /* Private Use (plane 16) */+#define TT_UCR_PRIVATE_USE_SUPPLEMENTARY (1L << 26) /*U+F0000-U+FFFFD*/+ /*U+100000-U+10FFFD*/+ /* Bit 91 Variation Selectors */+ /* Variation Selectors Supplement */+#define TT_UCR_VARIATION_SELECTORS (1L << 27) /* U+FE00-U+FE0F */+ /*U+E0100-U+E01EF*/+ /* Bit 92 Tags */+#define TT_UCR_TAGS (1L << 28) /*U+E0000-U+E007F*/+ /* Bit 93 Limbu */+#define TT_UCR_LIMBU (1L << 29) /* U+1900-U+194F */+ /* Bit 94 Tai Le */+#define TT_UCR_TAI_LE (1L << 30) /* U+1950-U+197F */+ /* Bit 95 New Tai Lue */+#define TT_UCR_NEW_TAI_LUE (1L << 31) /* U+1980-U+19DF */+ /* Bit 96 Buginese */+#define TT_UCR_BUGINESE (1L << 0) /* U+1A00-U+1A1F */+ /* Bit 97 Glagolitic */+#define TT_UCR_GLAGOLITIC (1L << 1) /* U+2C00-U+2C5F */+ /* Bit 98 Tifinagh */+#define TT_UCR_TIFINAGH (1L << 2) /* U+2D30-U+2D7F */+ /* Bit 99 Yijing Hexagram Symbols */+#define TT_UCR_YIJING (1L << 3) /* U+4DC0-U+4DFF */+ /* Bit 100 Syloti Nagri */+#define TT_UCR_SYLOTI_NAGRI (1L << 4) /* U+A800-U+A82F */+ /* Bit 101 Linear B Syllabary */+ /* Linear B Ideograms */+ /* Aegean Numbers */+#define TT_UCR_LINEAR_B (1L << 5) /*U+10000-U+1007F*/+ /*U+10080-U+100FF*/+ /*U+10100-U+1013F*/+ /* Bit 102 Ancient Greek Numbers */+#define TT_UCR_ANCIENT_GREEK_NUMBERS (1L << 6) /*U+10140-U+1018F*/+ /* Bit 103 Ugaritic */+#define TT_UCR_UGARITIC (1L << 7) /*U+10380-U+1039F*/+ /* Bit 104 Old Persian */+#define TT_UCR_OLD_PERSIAN (1L << 8) /*U+103A0-U+103DF*/+ /* Bit 105 Shavian */+#define TT_UCR_SHAVIAN (1L << 9) /*U+10450-U+1047F*/+ /* Bit 106 Osmanya */+#define TT_UCR_OSMANYA (1L << 10) /*U+10480-U+104AF*/+ /* Bit 107 Cypriot Syllabary */+#define TT_UCR_CYPRIOT_SYLLABARY (1L << 11) /*U+10800-U+1083F*/+ /* Bit 108 Kharoshthi */+#define TT_UCR_KHAROSHTHI (1L << 12) /*U+10A00-U+10A5F*/+ /* Bit 109 Tai Xuan Jing Symbols */+#define TT_UCR_TAI_XUAN_JING (1L << 13) /*U+1D300-U+1D35F*/+ /* Bit 110 Cuneiform */+ /* Cuneiform Numbers and Punctuation */+#define TT_UCR_CUNEIFORM (1L << 14) /*U+12000-U+123FF*/+ /*U+12400-U+1247F*/+ /* Bit 111 Counting Rod Numerals */+#define TT_UCR_COUNTING_ROD_NUMERALS (1L << 15) /*U+1D360-U+1D37F*/+ /* Bit 112 Sundanese */+#define TT_UCR_SUNDANESE (1L << 16) /* U+1B80-U+1BBF */+ /* Bit 113 Lepcha */+#define TT_UCR_LEPCHA (1L << 17) /* U+1C00-U+1C4F */+ /* Bit 114 Ol Chiki */+#define TT_UCR_OL_CHIKI (1L << 18) /* U+1C50-U+1C7F */+ /* Bit 115 Saurashtra */+#define TT_UCR_SAURASHTRA (1L << 19) /* U+A880-U+A8DF */+ /* Bit 116 Kayah Li */+#define TT_UCR_KAYAH_LI (1L << 20) /* U+A900-U+A92F */+ /* Bit 117 Rejang */+#define TT_UCR_REJANG (1L << 21) /* U+A930-U+A95F */+ /* Bit 118 Cham */+#define TT_UCR_CHAM (1L << 22) /* U+AA00-U+AA5F */+ /* Bit 119 Ancient Symbols */+#define TT_UCR_ANCIENT_SYMBOLS (1L << 23) /*U+10190-U+101CF*/+ /* Bit 120 Phaistos Disc */+#define TT_UCR_PHAISTOS_DISC (1L << 24) /*U+101D0-U+101FF*/+ /* Bit 121 Carian */+ /* Lycian */+ /* Lydian */+#define TT_UCR_OLD_ANATOLIAN (1L << 25) /*U+102A0-U+102DF*/+ /*U+10280-U+1029F*/+ /*U+10920-U+1093F*/+ /* Bit 122 Domino Tiles */+ /* Mahjong Tiles */+#define TT_UCR_GAME_TILES (1L << 26) /*U+1F030-U+1F09F*/+ /*U+1F000-U+1F02F*/+ /* Bit 123-127 Reserved for process-internal usage */+++ /*************************************************************************/+ /* */+ /* Some compilers have a very limited length of identifiers. */+ /* */+#if defined( __TURBOC__ ) && __TURBOC__ < 0x0410 || defined( __PACIFIC__ )+#define HAVE_LIMIT_ON_IDENTS+#endif+++#ifndef HAVE_LIMIT_ON_IDENTS+++ /*************************************************************************/+ /* */+ /* Here some alias #defines in order to be clearer. */+ /* */+ /* These are not always #defined to stay within the 31~character limit */+ /* which some compilers have. */+ /* */+ /* Credits go to Dave Hoo <dhoo@flash.net> for pointing out that modern */+ /* Borland compilers (read: from BC++ 3.1 on) can increase this limit. */+ /* If you get a warning with such a compiler, use the -i40 switch. */+ /* */+#define TT_UCR_ARABIC_PRESENTATION_FORMS_A \+ TT_UCR_ARABIC_PRESENTATIONS_A+#define TT_UCR_ARABIC_PRESENTATION_FORMS_B \+ TT_UCR_ARABIC_PRESENTATIONS_B++#define TT_UCR_COMBINING_DIACRITICAL_MARKS \+ TT_UCR_COMBINING_DIACRITICS+#define TT_UCR_COMBINING_DIACRITICAL_MARKS_SYMB \+ TT_UCR_COMBINING_DIACRITICS_SYMB+++#endif /* !HAVE_LIMIT_ON_IDENTS */+++FT_END_HEADER++#endif /* __TTNAMEID_H__ */+++/* END */
+ include/freetype/tttables.h view
@@ -0,0 +1,759 @@+/***************************************************************************/+/* */+/* tttables.h */+/* */+/* Basic SFNT/TrueType tables definitions and interface */+/* (specification only). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2008, 2009, 2010 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 __TTTABLES_H__+#define __TTTABLES_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+++FT_BEGIN_HEADER++ /*************************************************************************/+ /* */+ /* <Section> */+ /* truetype_tables */+ /* */+ /* <Title> */+ /* TrueType Tables */+ /* */+ /* <Abstract> */+ /* TrueType specific table types and functions. */+ /* */+ /* <Description> */+ /* This section contains the definition of TrueType-specific tables */+ /* as well as some routines used to access and process them. */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_Header */+ /* */+ /* <Description> */+ /* A structure used to model a TrueType font header table. All */+ /* fields follow the TrueType specification. */+ /* */+ typedef struct TT_Header_+ {+ FT_Fixed Table_Version;+ FT_Fixed Font_Revision;++ FT_Long CheckSum_Adjust;+ FT_Long Magic_Number;++ FT_UShort Flags;+ FT_UShort Units_Per_EM;++ FT_Long Created [2];+ FT_Long Modified[2];++ FT_Short xMin;+ FT_Short yMin;+ FT_Short xMax;+ FT_Short yMax;++ FT_UShort Mac_Style;+ FT_UShort Lowest_Rec_PPEM;++ FT_Short Font_Direction;+ FT_Short Index_To_Loc_Format;+ FT_Short Glyph_Data_Format;++ } TT_Header;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_HoriHeader */+ /* */+ /* <Description> */+ /* A structure used to model a TrueType horizontal header, the `hhea' */+ /* table, as well as the corresponding horizontal metrics table, */+ /* i.e., the `hmtx' table. */+ /* */+ /* <Fields> */+ /* Version :: The table version. */+ /* */+ /* Ascender :: The font's ascender, i.e., the distance */+ /* from the baseline to the top-most of all */+ /* glyph points found in the font. */+ /* */+ /* This value is invalid in many fonts, as */+ /* it is usually set by the font designer, */+ /* and often reflects only a portion of the */+ /* glyphs found in the font (maybe ASCII). */+ /* */+ /* You should use the `sTypoAscender' field */+ /* of the OS/2 table instead if you want */+ /* the correct one. */+ /* */+ /* Descender :: The font's descender, i.e., the distance */+ /* from the baseline to the bottom-most of */+ /* all glyph points found in the font. It */+ /* is negative. */+ /* */+ /* This value is invalid in many fonts, as */+ /* it is usually set by the font designer, */+ /* and often reflects only a portion of the */+ /* glyphs found in the font (maybe ASCII). */+ /* */+ /* You should use the `sTypoDescender' */+ /* field of the OS/2 table instead if you */+ /* want the correct one. */+ /* */+ /* Line_Gap :: The font's line gap, i.e., the distance */+ /* to add to the ascender and descender to */+ /* get the BTB, i.e., the */+ /* baseline-to-baseline distance for the */+ /* font. */+ /* */+ /* advance_Width_Max :: This field is the maximum of all advance */+ /* widths found in the font. It can be */+ /* used to compute the maximum width of an */+ /* arbitrary string of text. */+ /* */+ /* min_Left_Side_Bearing :: The minimum left side bearing of all */+ /* glyphs within the font. */+ /* */+ /* min_Right_Side_Bearing :: The minimum right side bearing of all */+ /* glyphs within the font. */+ /* */+ /* xMax_Extent :: The maximum horizontal extent (i.e., the */+ /* `width' of a glyph's bounding box) for */+ /* all glyphs in the font. */+ /* */+ /* caret_Slope_Rise :: The rise coefficient of the cursor's */+ /* slope of the cursor (slope=rise/run). */+ /* */+ /* caret_Slope_Run :: The run coefficient of the cursor's */+ /* slope. */+ /* */+ /* Reserved :: 8~reserved bytes. */+ /* */+ /* metric_Data_Format :: Always~0. */+ /* */+ /* number_Of_HMetrics :: Number of HMetrics entries in the `hmtx' */+ /* table -- this value can be smaller than */+ /* the total number of glyphs in the font. */+ /* */+ /* long_metrics :: A pointer into the `hmtx' table. */+ /* */+ /* short_metrics :: A pointer into the `hmtx' table. */+ /* */+ /* <Note> */+ /* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should */+ /* be identical except for the names of their fields which */+ /* are different. */+ /* */+ /* This ensures that a single function in the `ttload' */+ /* module is able to read both the horizontal and vertical */+ /* headers. */+ /* */+ typedef struct TT_HoriHeader_+ {+ FT_Fixed Version;+ FT_Short Ascender;+ FT_Short Descender;+ FT_Short Line_Gap;++ FT_UShort advance_Width_Max; /* advance width maximum */++ FT_Short min_Left_Side_Bearing; /* minimum left-sb */+ FT_Short min_Right_Side_Bearing; /* minimum right-sb */+ FT_Short xMax_Extent; /* xmax extents */+ FT_Short caret_Slope_Rise;+ FT_Short caret_Slope_Run;+ FT_Short caret_Offset;++ FT_Short Reserved[4];++ FT_Short metric_Data_Format;+ FT_UShort number_Of_HMetrics;++ /* The following fields are not defined by the TrueType specification */+ /* but they are used to connect the metrics header to the relevant */+ /* `HMTX' table. */++ void* long_metrics;+ void* short_metrics;++ } TT_HoriHeader;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_VertHeader */+ /* */+ /* <Description> */+ /* A structure used to model a TrueType vertical header, the `vhea' */+ /* table, as well as the corresponding vertical metrics table, i.e., */+ /* the `vmtx' table. */+ /* */+ /* <Fields> */+ /* Version :: The table version. */+ /* */+ /* Ascender :: The font's ascender, i.e., the distance */+ /* from the baseline to the top-most of */+ /* all glyph points found in the font. */+ /* */+ /* This value is invalid in many fonts, as */+ /* it is usually set by the font designer, */+ /* and often reflects only a portion of */+ /* the glyphs found in the font (maybe */+ /* ASCII). */+ /* */+ /* You should use the `sTypoAscender' */+ /* field of the OS/2 table instead if you */+ /* want the correct one. */+ /* */+ /* Descender :: The font's descender, i.e., the */+ /* distance from the baseline to the */+ /* bottom-most of all glyph points found */+ /* in the font. It is negative. */+ /* */+ /* This value is invalid in many fonts, as */+ /* it is usually set by the font designer, */+ /* and often reflects only a portion of */+ /* the glyphs found in the font (maybe */+ /* ASCII). */+ /* */+ /* You should use the `sTypoDescender' */+ /* field of the OS/2 table instead if you */+ /* want the correct one. */+ /* */+ /* Line_Gap :: The font's line gap, i.e., the distance */+ /* to add to the ascender and descender to */+ /* get the BTB, i.e., the */+ /* baseline-to-baseline distance for the */+ /* font. */+ /* */+ /* advance_Height_Max :: This field is the maximum of all */+ /* advance heights found in the font. It */+ /* can be used to compute the maximum */+ /* height of an arbitrary string of text. */+ /* */+ /* min_Top_Side_Bearing :: The minimum top side bearing of all */+ /* glyphs within the font. */+ /* */+ /* min_Bottom_Side_Bearing :: The minimum bottom side bearing of all */+ /* glyphs within the font. */+ /* */+ /* yMax_Extent :: The maximum vertical extent (i.e., the */+ /* `height' of a glyph's bounding box) for */+ /* all glyphs in the font. */+ /* */+ /* caret_Slope_Rise :: The rise coefficient of the cursor's */+ /* slope of the cursor (slope=rise/run). */+ /* */+ /* caret_Slope_Run :: The run coefficient of the cursor's */+ /* slope. */+ /* */+ /* caret_Offset :: The cursor's offset for slanted fonts. */+ /* This value is `reserved' in vmtx */+ /* version 1.0. */+ /* */+ /* Reserved :: 8~reserved bytes. */+ /* */+ /* metric_Data_Format :: Always~0. */+ /* */+ /* number_Of_HMetrics :: Number of VMetrics entries in the */+ /* `vmtx' table -- this value can be */+ /* smaller than the total number of glyphs */+ /* in the font. */+ /* */+ /* long_metrics :: A pointer into the `vmtx' table. */+ /* */+ /* short_metrics :: A pointer into the `vmtx' table. */+ /* */+ /* <Note> */+ /* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should */+ /* be identical except for the names of their fields which */+ /* are different. */+ /* */+ /* This ensures that a single function in the `ttload' */+ /* module is able to read both the horizontal and vertical */+ /* headers. */+ /* */+ typedef struct TT_VertHeader_+ {+ FT_Fixed Version;+ FT_Short Ascender;+ FT_Short Descender;+ FT_Short Line_Gap;++ FT_UShort advance_Height_Max; /* advance height maximum */++ FT_Short min_Top_Side_Bearing; /* minimum left-sb or top-sb */+ FT_Short min_Bottom_Side_Bearing; /* minimum right-sb or bottom-sb */+ FT_Short yMax_Extent; /* xmax or ymax extents */+ FT_Short caret_Slope_Rise;+ FT_Short caret_Slope_Run;+ FT_Short caret_Offset;++ FT_Short Reserved[4];++ FT_Short metric_Data_Format;+ FT_UShort number_Of_VMetrics;++ /* The following fields are not defined by the TrueType specification */+ /* but they're used to connect the metrics header to the relevant */+ /* `HMTX' or `VMTX' table. */++ void* long_metrics;+ void* short_metrics;++ } TT_VertHeader;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_OS2 */+ /* */+ /* <Description> */+ /* A structure used to model a TrueType OS/2 table. This is the long */+ /* table version. All fields comply to the TrueType specification. */+ /* */+ /* Note that we now support old Mac fonts which do not include an */+ /* OS/2 table. In this case, the `version' field is always set to */+ /* 0xFFFF. */+ /* */+ typedef struct TT_OS2_+ {+ FT_UShort version; /* 0x0001 - more or 0xFFFF */+ FT_Short xAvgCharWidth;+ FT_UShort usWeightClass;+ FT_UShort usWidthClass;+ FT_Short fsType;+ FT_Short ySubscriptXSize;+ FT_Short ySubscriptYSize;+ FT_Short ySubscriptXOffset;+ FT_Short ySubscriptYOffset;+ FT_Short ySuperscriptXSize;+ FT_Short ySuperscriptYSize;+ FT_Short ySuperscriptXOffset;+ FT_Short ySuperscriptYOffset;+ FT_Short yStrikeoutSize;+ FT_Short yStrikeoutPosition;+ FT_Short sFamilyClass;++ FT_Byte panose[10];++ FT_ULong ulUnicodeRange1; /* Bits 0-31 */+ FT_ULong ulUnicodeRange2; /* Bits 32-63 */+ FT_ULong ulUnicodeRange3; /* Bits 64-95 */+ FT_ULong ulUnicodeRange4; /* Bits 96-127 */++ FT_Char achVendID[4];++ FT_UShort fsSelection;+ FT_UShort usFirstCharIndex;+ FT_UShort usLastCharIndex;+ FT_Short sTypoAscender;+ FT_Short sTypoDescender;+ FT_Short sTypoLineGap;+ FT_UShort usWinAscent;+ FT_UShort usWinDescent;++ /* only version 1 tables: */++ FT_ULong ulCodePageRange1; /* Bits 0-31 */+ FT_ULong ulCodePageRange2; /* Bits 32-63 */++ /* only version 2 tables: */++ FT_Short sxHeight;+ FT_Short sCapHeight;+ FT_UShort usDefaultChar;+ FT_UShort usBreakChar;+ FT_UShort usMaxContext;++ } TT_OS2;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_Postscript */+ /* */+ /* <Description> */+ /* A structure used to model a TrueType PostScript table. All fields */+ /* comply to the TrueType specification. This structure does not */+ /* reference the PostScript glyph names, which can be nevertheless */+ /* accessed with the `ttpost' module. */+ /* */+ typedef struct TT_Postscript_+ {+ FT_Fixed FormatType;+ FT_Fixed italicAngle;+ FT_Short underlinePosition;+ FT_Short underlineThickness;+ FT_ULong isFixedPitch;+ FT_ULong minMemType42;+ FT_ULong maxMemType42;+ FT_ULong minMemType1;+ FT_ULong maxMemType1;++ /* Glyph names follow in the file, but we don't */+ /* load them by default. See the ttpost.c file. */++ } TT_Postscript;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_PCLT */+ /* */+ /* <Description> */+ /* A structure used to model a TrueType PCLT table. All fields */+ /* comply to the TrueType specification. */+ /* */+ typedef struct TT_PCLT_+ {+ FT_Fixed Version;+ FT_ULong FontNumber;+ FT_UShort Pitch;+ FT_UShort xHeight;+ FT_UShort Style;+ FT_UShort TypeFamily;+ FT_UShort CapHeight;+ FT_UShort SymbolSet;+ FT_Char TypeFace[16];+ FT_Char CharacterComplement[8];+ FT_Char FileName[6];+ FT_Char StrokeWeight;+ FT_Char WidthType;+ FT_Byte SerifStyle;+ FT_Byte Reserved;++ } TT_PCLT;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_MaxProfile */+ /* */+ /* <Description> */+ /* The maximum profile is a table containing many max values which */+ /* can be used to pre-allocate arrays. This ensures that no memory */+ /* allocation occurs during a glyph load. */+ /* */+ /* <Fields> */+ /* version :: The version number. */+ /* */+ /* numGlyphs :: The number of glyphs in this TrueType */+ /* font. */+ /* */+ /* maxPoints :: The maximum number of points in a */+ /* non-composite TrueType glyph. See also */+ /* the structure element */+ /* `maxCompositePoints'. */+ /* */+ /* maxContours :: The maximum number of contours in a */+ /* non-composite TrueType glyph. See also */+ /* the structure element */+ /* `maxCompositeContours'. */+ /* */+ /* maxCompositePoints :: The maximum number of points in a */+ /* composite TrueType glyph. See also the */+ /* structure element `maxPoints'. */+ /* */+ /* maxCompositeContours :: The maximum number of contours in a */+ /* composite TrueType glyph. See also the */+ /* structure element `maxContours'. */+ /* */+ /* maxZones :: The maximum number of zones used for */+ /* glyph hinting. */+ /* */+ /* maxTwilightPoints :: The maximum number of points in the */+ /* twilight zone used for glyph hinting. */+ /* */+ /* maxStorage :: The maximum number of elements in the */+ /* storage area used for glyph hinting. */+ /* */+ /* maxFunctionDefs :: The maximum number of function */+ /* definitions in the TrueType bytecode for */+ /* this font. */+ /* */+ /* maxInstructionDefs :: The maximum number of instruction */+ /* definitions in the TrueType bytecode for */+ /* this font. */+ /* */+ /* maxStackElements :: The maximum number of stack elements used */+ /* during bytecode interpretation. */+ /* */+ /* maxSizeOfInstructions :: The maximum number of TrueType opcodes */+ /* used for glyph hinting. */+ /* */+ /* maxComponentElements :: The maximum number of simple (i.e., non- */+ /* composite) glyphs in a composite glyph. */+ /* */+ /* maxComponentDepth :: The maximum nesting depth of composite */+ /* glyphs. */+ /* */+ /* <Note> */+ /* This structure is only used during font loading. */+ /* */+ typedef struct TT_MaxProfile_+ {+ FT_Fixed version;+ FT_UShort numGlyphs;+ FT_UShort maxPoints;+ FT_UShort maxContours;+ FT_UShort maxCompositePoints;+ FT_UShort maxCompositeContours;+ FT_UShort maxZones;+ FT_UShort maxTwilightPoints;+ FT_UShort maxStorage;+ FT_UShort maxFunctionDefs;+ FT_UShort maxInstructionDefs;+ FT_UShort maxStackElements;+ FT_UShort maxSizeOfInstructions;+ FT_UShort maxComponentElements;+ FT_UShort maxComponentDepth;++ } TT_MaxProfile;+++ /*************************************************************************/+ /* */+ /* <Enum> */+ /* FT_Sfnt_Tag */+ /* */+ /* <Description> */+ /* An enumeration used to specify the index of an SFNT table. */+ /* Used in the @FT_Get_Sfnt_Table API function. */+ /* */+ typedef enum FT_Sfnt_Tag_+ {+ ft_sfnt_head = 0, /* TT_Header */+ ft_sfnt_maxp = 1, /* TT_MaxProfile */+ ft_sfnt_os2 = 2, /* TT_OS2 */+ ft_sfnt_hhea = 3, /* TT_HoriHeader */+ ft_sfnt_vhea = 4, /* TT_VertHeader */+ ft_sfnt_post = 5, /* TT_Postscript */+ ft_sfnt_pclt = 6, /* TT_PCLT */++ sfnt_max /* internal end mark */++ } FT_Sfnt_Tag;++ /* */+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Get_Sfnt_Table */+ /* */+ /* <Description> */+ /* Return a pointer to a given SFNT table within a face. */+ /* */+ /* <Input> */+ /* face :: A handle to the source. */+ /* */+ /* tag :: The index of the SFNT table. */+ /* */+ /* <Return> */+ /* A type-less pointer to the table. This will be~0 in case of */+ /* error, or if the corresponding table was not found *OR* loaded */+ /* from the file. */+ /* */+ /* Use a typecast according to `tag' to access the structure */+ /* elements. */+ /* */+ /* <Note> */+ /* The table is owned by the face object and disappears with it. */+ /* */+ /* This function is only useful to access SFNT tables that are loaded */+ /* by the sfnt, truetype, and opentype drivers. See @FT_Sfnt_Tag for */+ /* a list. */+ /* */+ FT_EXPORT( void* )+ FT_Get_Sfnt_Table( FT_Face face,+ FT_Sfnt_Tag tag );+++ /**************************************************************************+ *+ * @function:+ * FT_Load_Sfnt_Table+ *+ * @description:+ * Load any font table into client memory.+ *+ * @input:+ * face ::+ * A handle to the source face.+ *+ * tag ::+ * The four-byte tag of the table to load. Use the value~0 if you want+ * to access the whole font file. Otherwise, you can use one of the+ * definitions found in the @FT_TRUETYPE_TAGS_H file, or forge a new+ * one with @FT_MAKE_TAG.+ *+ * offset ::+ * The starting offset in the table (or file if tag == 0).+ *+ * @output:+ * buffer ::+ * The target buffer address. The client must ensure that the memory+ * array is big enough to hold the data.+ *+ * @inout:+ * length ::+ * If the `length' parameter is NULL, then try to load the whole table.+ * Return an error code if it fails.+ *+ * Else, if `*length' is~0, exit immediately while returning the+ * table's (or file) full size in it.+ *+ * Else the number of bytes to read from the table or file, from the+ * starting offset.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * If you need to determine the table's length you should first call this+ * function with `*length' set to~0, as in the following example:+ *+ * {+ * FT_ULong length = 0;+ *+ *+ * error = FT_Load_Sfnt_Table( face, tag, 0, NULL, &length );+ * if ( error ) { ... table does not exist ... }+ *+ * buffer = malloc( length );+ * if ( buffer == NULL ) { ... not enough memory ... }+ *+ * error = FT_Load_Sfnt_Table( face, tag, 0, buffer, &length );+ * if ( error ) { ... could not load table ... }+ * }+ */+ FT_EXPORT( FT_Error )+ FT_Load_Sfnt_Table( FT_Face face,+ FT_ULong tag,+ FT_Long offset,+ FT_Byte* buffer,+ FT_ULong* length );+++ /**************************************************************************+ *+ * @function:+ * FT_Sfnt_Table_Info+ *+ * @description:+ * Return information on an SFNT table.+ *+ * @input:+ * face ::+ * A handle to the source face.+ *+ * table_index ::+ * The index of an SFNT table. The function returns+ * FT_Err_Table_Missing for an invalid value.+ *+ * @output:+ * tag ::+ * The name tag of the SFNT table.+ *+ * length ::+ * The length of the SFNT table.+ *+ * @return:+ * FreeType error code. 0~means success.+ *+ * @note:+ * SFNT tables with length zero are treated as missing.+ *+ */+ FT_EXPORT( FT_Error )+ FT_Sfnt_Table_Info( FT_Face face,+ FT_UInt table_index,+ FT_ULong *tag,+ FT_ULong *length );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Get_CMap_Language_ID */+ /* */+ /* <Description> */+ /* Return TrueType/sfnt specific cmap language ID. Definitions of */+ /* language ID values are in `freetype/ttnameid.h'. */+ /* */+ /* <Input> */+ /* charmap :: */+ /* The target charmap. */+ /* */+ /* <Return> */+ /* The language ID of `charmap'. If `charmap' doesn't belong to a */+ /* TrueType/sfnt face, just return~0 as the default value. */+ /* */+ FT_EXPORT( FT_ULong )+ FT_Get_CMap_Language_ID( FT_CharMap charmap );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Get_CMap_Format */+ /* */+ /* <Description> */+ /* Return TrueType/sfnt specific cmap format. */+ /* */+ /* <Input> */+ /* charmap :: */+ /* The target charmap. */+ /* */+ /* <Return> */+ /* The format of `charmap'. If `charmap' doesn't belong to a */+ /* TrueType/sfnt face, return -1. */+ /* */+ FT_EXPORT( FT_Long )+ FT_Get_CMap_Format( FT_CharMap charmap );++ /* */+++FT_END_HEADER++#endif /* __TTTABLES_H__ */+++/* END */
+ include/freetype/tttags.h view
@@ -0,0 +1,107 @@+/***************************************************************************/+/* */+/* tttags.h */+/* */+/* Tags for TrueType and OpenType tables (specification only). */+/* */+/* Copyright 1996-2001, 2004, 2005, 2007, 2008 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 __TTAGS_H__+#define __TTAGS_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+++FT_BEGIN_HEADER+++#define TTAG_avar FT_MAKE_TAG( 'a', 'v', 'a', 'r' )+#define TTAG_BASE FT_MAKE_TAG( 'B', 'A', 'S', 'E' )+#define TTAG_bdat FT_MAKE_TAG( 'b', 'd', 'a', 't' )+#define TTAG_BDF FT_MAKE_TAG( 'B', 'D', 'F', ' ' )+#define TTAG_bhed FT_MAKE_TAG( 'b', 'h', 'e', 'd' )+#define TTAG_bloc FT_MAKE_TAG( 'b', 'l', 'o', 'c' )+#define TTAG_bsln FT_MAKE_TAG( 'b', 's', 'l', 'n' )+#define TTAG_CFF FT_MAKE_TAG( 'C', 'F', 'F', ' ' )+#define TTAG_CID FT_MAKE_TAG( 'C', 'I', 'D', ' ' )+#define TTAG_cmap FT_MAKE_TAG( 'c', 'm', 'a', 'p' )+#define TTAG_cvar FT_MAKE_TAG( 'c', 'v', 'a', 'r' )+#define TTAG_cvt FT_MAKE_TAG( 'c', 'v', 't', ' ' )+#define TTAG_DSIG FT_MAKE_TAG( 'D', 'S', 'I', 'G' )+#define TTAG_EBDT FT_MAKE_TAG( 'E', 'B', 'D', 'T' )+#define TTAG_EBLC FT_MAKE_TAG( 'E', 'B', 'L', 'C' )+#define TTAG_EBSC FT_MAKE_TAG( 'E', 'B', 'S', 'C' )+#define TTAG_feat FT_MAKE_TAG( 'f', 'e', 'a', 't' )+#define TTAG_FOND FT_MAKE_TAG( 'F', 'O', 'N', 'D' )+#define TTAG_fpgm FT_MAKE_TAG( 'f', 'p', 'g', 'm' )+#define TTAG_fvar FT_MAKE_TAG( 'f', 'v', 'a', 'r' )+#define TTAG_gasp FT_MAKE_TAG( 'g', 'a', 's', 'p' )+#define TTAG_GDEF FT_MAKE_TAG( 'G', 'D', 'E', 'F' )+#define TTAG_glyf FT_MAKE_TAG( 'g', 'l', 'y', 'f' )+#define TTAG_GPOS FT_MAKE_TAG( 'G', 'P', 'O', 'S' )+#define TTAG_GSUB FT_MAKE_TAG( 'G', 'S', 'U', 'B' )+#define TTAG_gvar FT_MAKE_TAG( 'g', 'v', 'a', 'r' )+#define TTAG_hdmx FT_MAKE_TAG( 'h', 'd', 'm', 'x' )+#define TTAG_head FT_MAKE_TAG( 'h', 'e', 'a', 'd' )+#define TTAG_hhea FT_MAKE_TAG( 'h', 'h', 'e', 'a' )+#define TTAG_hmtx FT_MAKE_TAG( 'h', 'm', 't', 'x' )+#define TTAG_JSTF FT_MAKE_TAG( 'J', 'S', 'T', 'F' )+#define TTAG_just FT_MAKE_TAG( 'j', 'u', 's', 't' )+#define TTAG_kern FT_MAKE_TAG( 'k', 'e', 'r', 'n' )+#define TTAG_lcar FT_MAKE_TAG( 'l', 'c', 'a', 'r' )+#define TTAG_loca FT_MAKE_TAG( 'l', 'o', 'c', 'a' )+#define TTAG_LTSH FT_MAKE_TAG( 'L', 'T', 'S', 'H' )+#define TTAG_LWFN FT_MAKE_TAG( 'L', 'W', 'F', 'N' )+#define TTAG_MATH FT_MAKE_TAG( 'M', 'A', 'T', 'H' )+#define TTAG_maxp FT_MAKE_TAG( 'm', 'a', 'x', 'p' )+#define TTAG_META FT_MAKE_TAG( 'M', 'E', 'T', 'A' )+#define TTAG_MMFX FT_MAKE_TAG( 'M', 'M', 'F', 'X' )+#define TTAG_MMSD FT_MAKE_TAG( 'M', 'M', 'S', 'D' )+#define TTAG_mort FT_MAKE_TAG( 'm', 'o', 'r', 't' )+#define TTAG_morx FT_MAKE_TAG( 'm', 'o', 'r', 'x' )+#define TTAG_name FT_MAKE_TAG( 'n', 'a', 'm', 'e' )+#define TTAG_opbd FT_MAKE_TAG( 'o', 'p', 'b', 'd' )+#define TTAG_OS2 FT_MAKE_TAG( 'O', 'S', '/', '2' )+#define TTAG_OTTO FT_MAKE_TAG( 'O', 'T', 'T', 'O' )+#define TTAG_PCLT FT_MAKE_TAG( 'P', 'C', 'L', 'T' )+#define TTAG_POST FT_MAKE_TAG( 'P', 'O', 'S', 'T' )+#define TTAG_post FT_MAKE_TAG( 'p', 'o', 's', 't' )+#define TTAG_prep FT_MAKE_TAG( 'p', 'r', 'e', 'p' )+#define TTAG_prop FT_MAKE_TAG( 'p', 'r', 'o', 'p' )+#define TTAG_sfnt FT_MAKE_TAG( 's', 'f', 'n', 't' )+#define TTAG_SING FT_MAKE_TAG( 'S', 'I', 'N', 'G' )+#define TTAG_trak FT_MAKE_TAG( 't', 'r', 'a', 'k' )+#define TTAG_true FT_MAKE_TAG( 't', 'r', 'u', 'e' )+#define TTAG_ttc FT_MAKE_TAG( 't', 't', 'c', ' ' )+#define TTAG_ttcf FT_MAKE_TAG( 't', 't', 'c', 'f' )+#define TTAG_TYP1 FT_MAKE_TAG( 'T', 'Y', 'P', '1' )+#define TTAG_typ1 FT_MAKE_TAG( 't', 'y', 'p', '1' )+#define TTAG_VDMX FT_MAKE_TAG( 'V', 'D', 'M', 'X' )+#define TTAG_vhea FT_MAKE_TAG( 'v', 'h', 'e', 'a' )+#define TTAG_vmtx FT_MAKE_TAG( 'v', 'm', 't', 'x' )+++FT_END_HEADER++#endif /* __TTAGS_H__ */+++/* END */
+ include/freetype/ttunpat.h view
@@ -0,0 +1,59 @@+/***************************************************************************/+/* */+/* ttunpat.h */+/* */+/* Definitions for the unpatented TrueType hinting system */+/* */+/* Copyright 2003, 2006 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* Written by Graham Asher <graham.asher@btinternet.com> */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#ifndef __TTUNPAT_H__+#define __TTUNPAT_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+++FT_BEGIN_HEADER+++ /***************************************************************************+ *+ * @constant:+ * FT_PARAM_TAG_UNPATENTED_HINTING+ *+ * @description:+ * A constant used as the tag of an @FT_Parameter structure to indicate+ * that unpatented methods only should be used by the TrueType bytecode+ * interpreter for a typeface opened by @FT_Open_Face.+ *+ */+#define FT_PARAM_TAG_UNPATENTED_HINTING FT_MAKE_TAG( 'u', 'n', 'p', 'a' )++ /* */++FT_END_HEADER+++#endif /* __TTUNPAT_H__ */+++/* END */
+ include/ft2build.h view
@@ -0,0 +1,39 @@+/***************************************************************************/+/* */+/* ft2build.h */+/* */+/* FreeType 2 build and setup macros. */+/* (Generic version) */+/* */+/* Copyright 1996-2001, 2006 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 corresponds to the default `ft2build.h' file for */+ /* FreeType 2. It uses the `freetype' include root. */+ /* */+ /* Note that specific platforms might use a different configuration. */+ /* See builds/unix/ft2unix.h for an example. */+ /* */+ /*************************************************************************/+++#ifndef __FT2_BUILD_GENERIC_H__+#define __FT2_BUILD_GENERIC_H__++#include <freetype/config/ftheader.h>++#endif /* __FT2_BUILD_GENERIC_H__ */+++/* END */
+ objs/ftmodule.h view
@@ -0,0 +1,20 @@+/* This is a generated file. */+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_Driver_ClassRec, bdf_driver_class )+FT_USE_MODULE( FT_Module_Class, sfnt_module_class )+FT_USE_MODULE( FT_Module_Class, autofit_module_class )+FT_USE_MODULE( FT_Module_Class, pshinter_module_class )+FT_USE_MODULE( FT_Renderer_Class, ft_raster1_renderer_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_Module_Class, psaux_module_class )+FT_USE_MODULE( FT_Module_Class, psnames_module_class )+/* EOF */
+ src/autofit/afangles.c view
@@ -0,0 +1,292 @@+/***************************************************************************/+/* */+/* afangles.c */+/* */+/* Routines used to compute vector angles with limited accuracy */+/* and very high speed. It also contains sorting routines (body). */+/* */+/* Copyright 2003, 2004, 2005, 2006 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#include "aftypes.h"+++#if 0++ FT_LOCAL_DEF( FT_Int )+ af_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 );+ }+++ FT_LOCAL_DEF( FT_Int )+ af_corner_orientation( FT_Pos x_in,+ FT_Pos y_in,+ FT_Pos x_out,+ FT_Pos y_out )+ {+ FT_Pos delta;+++ delta = x_in * y_out - y_in * x_out;++ if ( delta == 0 )+ return 0;+ else+ return 1 - 2 * ( delta < 0 );+ }++#endif+++ /*+ * We are not using `af_angle_atan' anymore, but we keep the source+ * code below just in case...+ */+++#if 0+++ /*+ * The trick here is to realize that we don't need a very accurate angle+ * approximation. We are going to use the result of `af_angle_atan' to+ * only compare the sign of angle differences, or check whether its+ * magnitude is very small.+ *+ * The approximation+ *+ * dy * PI / (|dx|+|dy|)+ *+ * should be enough, and much faster to compute.+ */+ FT_LOCAL_DEF( AF_Angle )+ af_angle_atan( FT_Fixed dx,+ FT_Fixed dy )+ {+ AF_Angle angle;+ FT_Fixed ax = dx;+ FT_Fixed ay = dy;+++ if ( ax < 0 )+ ax = -ax;+ if ( ay < 0 )+ ay = -ay;++ ax += ay;++ if ( ax == 0 )+ angle = 0;+ else+ {+ angle = ( AF_ANGLE_PI2 * dy ) / ( ax + ay );+ if ( dx < 0 )+ {+ if ( angle >= 0 )+ angle = AF_ANGLE_PI - angle;+ else+ angle = -AF_ANGLE_PI - angle;+ }+ }++ return angle;+ }+++#elif 0+++ /* the following table has been automatically generated with */+ /* the `mather.py' Python script */++#define AF_ATAN_BITS 8++ static const FT_Byte af_arctan[1L << AF_ATAN_BITS] =+ {+ 0, 0, 1, 1, 1, 2, 2, 2,+ 3, 3, 3, 3, 4, 4, 4, 5,+ 5, 5, 6, 6, 6, 7, 7, 7,+ 8, 8, 8, 9, 9, 9, 10, 10,+ 10, 10, 11, 11, 11, 12, 12, 12,+ 13, 13, 13, 14, 14, 14, 14, 15,+ 15, 15, 16, 16, 16, 17, 17, 17,+ 18, 18, 18, 18, 19, 19, 19, 20,+ 20, 20, 21, 21, 21, 21, 22, 22,+ 22, 23, 23, 23, 24, 24, 24, 24,+ 25, 25, 25, 26, 26, 26, 26, 27,+ 27, 27, 28, 28, 28, 28, 29, 29,+ 29, 30, 30, 30, 30, 31, 31, 31,+ 31, 32, 32, 32, 33, 33, 33, 33,+ 34, 34, 34, 34, 35, 35, 35, 35,+ 36, 36, 36, 36, 37, 37, 37, 38,+ 38, 38, 38, 39, 39, 39, 39, 40,+ 40, 40, 40, 41, 41, 41, 41, 42,+ 42, 42, 42, 42, 43, 43, 43, 43,+ 44, 44, 44, 44, 45, 45, 45, 45,+ 46, 46, 46, 46, 46, 47, 47, 47,+ 47, 48, 48, 48, 48, 48, 49, 49,+ 49, 49, 50, 50, 50, 50, 50, 51,+ 51, 51, 51, 51, 52, 52, 52, 52,+ 52, 53, 53, 53, 53, 53, 54, 54,+ 54, 54, 54, 55, 55, 55, 55, 55,+ 56, 56, 56, 56, 56, 57, 57, 57,+ 57, 57, 57, 58, 58, 58, 58, 58,+ 59, 59, 59, 59, 59, 59, 60, 60,+ 60, 60, 60, 61, 61, 61, 61, 61,+ 61, 62, 62, 62, 62, 62, 62, 63,+ 63, 63, 63, 63, 63, 64, 64, 64+ };+++ FT_LOCAL_DEF( AF_Angle )+ af_angle_atan( FT_Fixed dx,+ FT_Fixed dy )+ {+ AF_Angle angle;+++ /* check trivial cases */+ if ( dy == 0 )+ {+ angle = 0;+ if ( dx < 0 )+ angle = AF_ANGLE_PI;+ return angle;+ }+ else if ( dx == 0 )+ {+ angle = AF_ANGLE_PI2;+ if ( dy < 0 )+ angle = -AF_ANGLE_PI2;+ return angle;+ }++ angle = 0;+ if ( dx < 0 )+ {+ dx = -dx;+ dy = -dy;+ angle = AF_ANGLE_PI;+ }++ if ( dy < 0 )+ {+ FT_Pos tmp;+++ tmp = dx;+ dx = -dy;+ dy = tmp;+ angle -= AF_ANGLE_PI2;+ }++ if ( dx == 0 && dy == 0 )+ return 0;++ if ( dx == dy )+ angle += AF_ANGLE_PI4;+ else if ( dx > dy )+ angle += af_arctan[FT_DivFix( dy, dx ) >> ( 16 - AF_ATAN_BITS )];+ else+ angle += AF_ANGLE_PI2 -+ af_arctan[FT_DivFix( dx, dy ) >> ( 16 - AF_ATAN_BITS )];++ if ( angle > AF_ANGLE_PI )+ angle -= AF_ANGLE_2PI;++ return angle;+ }+++#endif /* 0 */+++ FT_LOCAL_DEF( void )+ af_sort_pos( FT_UInt count,+ FT_Pos* table )+ {+ FT_UInt i, j;+ FT_Pos swap;+++ for ( i = 1; i < count; i++ )+ {+ for ( j = i; j > 0; j-- )+ {+ if ( table[j] > table[j - 1] )+ break;++ swap = table[j];+ table[j] = table[j - 1];+ table[j - 1] = swap;+ }+ }+ }+++ FT_LOCAL_DEF( void )+ af_sort_widths( FT_UInt count,+ AF_Width table )+ {+ FT_UInt i, j;+ AF_WidthRec swap;+++ for ( i = 1; i < count; i++ )+ {+ for ( j = i; j > 0; j-- )+ {+ if ( table[j].org > table[j - 1].org )+ break;++ swap = table[j];+ table[j] = table[j - 1];+ table[j - 1] = swap;+ }+ }+ }+++/* END */
+ src/autofit/afangles.h view
@@ -0,0 +1,7 @@+/*+ * afangles.h+ *+ * This is a dummy file, used to please the build system. It is never+ * included by the auto-fitter sources.+ *+ */
+ src/autofit/afcjk.c view
@@ -0,0 +1,1512 @@+/***************************************************************************/+/* */+/* afcjk.c */+/* */+/* Auto-fitter hinting routines for CJK script (body). */+/* */+/* Copyright 2006, 2007, 2008, 2009, 2010 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/++ /*+ * The algorithm is based on akito's autohint patch, available here:+ *+ * http://www.kde.gr.jp/~akito/patch/freetype2/+ *+ */++#include "aftypes.h"+#include "aflatin.h"+++#ifdef AF_CONFIG_OPTION_CJK++#include "afcjk.h"+#include "aferrors.h"+++#ifdef AF_USE_WARPER+#include "afwarp.h"+#endif+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** C J K G L O B A L M E T R I C S *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ FT_LOCAL_DEF( FT_Error )+ af_cjk_metrics_init( AF_LatinMetrics metrics,+ FT_Face face )+ {+ FT_CharMap oldmap = face->charmap;+++ metrics->units_per_em = face->units_per_EM;++ /* TODO are there blues? */++ if ( FT_Select_Charmap( face, FT_ENCODING_UNICODE ) )+ face->charmap = NULL;+ else+ {+ /* latin's version would suffice */+ af_latin_metrics_init_widths( metrics, face, 0x7530 );+ af_latin_metrics_check_digits( metrics, face );+ }++ FT_Set_Charmap( face, oldmap );++ return AF_Err_Ok;+ }+++ static void+ af_cjk_metrics_scale_dim( AF_LatinMetrics metrics,+ AF_Scaler scaler,+ AF_Dimension dim )+ {+ AF_LatinAxis axis;+++ axis = &metrics->axis[dim];++ if ( dim == AF_DIMENSION_HORZ )+ {+ axis->scale = scaler->x_scale;+ axis->delta = scaler->x_delta;+ }+ else+ {+ axis->scale = scaler->y_scale;+ axis->delta = scaler->y_delta;+ }+ }+++ FT_LOCAL_DEF( void )+ af_cjk_metrics_scale( AF_LatinMetrics metrics,+ AF_Scaler scaler )+ {+ metrics->root.scaler = *scaler;++ af_cjk_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ );+ af_cjk_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT );+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** C J K G L Y P H A N A L Y S I S *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ static FT_Error+ af_cjk_hints_compute_segments( AF_GlyphHints hints,+ AF_Dimension dim )+ {+ AF_AxisHints axis = &hints->axis[dim];+ AF_Segment segments = axis->segments;+ AF_Segment segment_limit = segments + axis->num_segments;+ FT_Error error;+ AF_Segment seg;+++ error = af_latin_hints_compute_segments( hints, dim );+ if ( error )+ return error;++ /* a segment is round if it doesn't have successive */+ /* on-curve points. */+ for ( seg = segments; seg < segment_limit; seg++ )+ {+ AF_Point pt = seg->first;+ AF_Point last = seg->last;+ AF_Flags f0 = (AF_Flags)(pt->flags & AF_FLAG_CONTROL);+ AF_Flags f1;+++ seg->flags &= ~AF_EDGE_ROUND;++ for ( ; pt != last; f0 = f1 )+ {+ pt = pt->next;+ f1 = (AF_Flags)(pt->flags & AF_FLAG_CONTROL);++ if ( !f0 && !f1 )+ break;++ if ( pt == last )+ seg->flags |= AF_EDGE_ROUND;+ }+ }++ return AF_Err_Ok;+ }+++ static void+ af_cjk_hints_link_segments( AF_GlyphHints hints,+ AF_Dimension dim )+ {+ AF_AxisHints axis = &hints->axis[dim];+ AF_Segment segments = axis->segments;+ AF_Segment segment_limit = segments + axis->num_segments;+ AF_Direction major_dir = axis->major_dir;+ AF_Segment seg1, seg2;+ FT_Pos len_threshold;+ FT_Pos dist_threshold;+++ len_threshold = AF_LATIN_CONSTANT( hints->metrics, 8 );++ dist_threshold = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale+ : hints->y_scale;+ dist_threshold = FT_DivFix( 64 * 3, dist_threshold );++ /* now compare each segment to the others */+ for ( seg1 = segments; seg1 < segment_limit; seg1++ )+ {+ /* the fake segments are for metrics hinting only */+ if ( seg1->first == seg1->last )+ continue;++ if ( seg1->dir != major_dir )+ continue;++ for ( seg2 = segments; seg2 < segment_limit; seg2++ )+ if ( seg2 != seg1 && seg1->dir + seg2->dir == 0 )+ {+ FT_Pos dist = seg2->pos - seg1->pos;+++ if ( dist < 0 )+ continue;++ {+ FT_Pos min = seg1->min_coord;+ FT_Pos max = seg1->max_coord;+ FT_Pos len;+++ if ( min < seg2->min_coord )+ min = seg2->min_coord;++ if ( max > seg2->max_coord )+ max = seg2->max_coord;++ len = max - min;+ if ( len >= len_threshold )+ {+ if ( dist * 8 < seg1->score * 9 &&+ ( dist * 8 < seg1->score * 7 || seg1->len < len ) )+ {+ seg1->score = dist;+ seg1->len = len;+ seg1->link = seg2;+ }++ if ( dist * 8 < seg2->score * 9 &&+ ( dist * 8 < seg2->score * 7 || seg2->len < len ) )+ {+ seg2->score = dist;+ seg2->len = len;+ seg2->link = seg1;+ }+ }+ }+ }+ }++ /*+ * now compute the `serif' segments+ *+ * In Hanzi, some strokes are wider on one or both of the ends.+ * We either identify the stems on the ends as serifs or remove+ * the linkage, depending on the length of the stems.+ *+ */++ {+ AF_Segment link1, link2;+++ for ( seg1 = segments; seg1 < segment_limit; seg1++ )+ {+ link1 = seg1->link;+ if ( !link1 || link1->link != seg1 || link1->pos <= seg1->pos )+ continue;++ if ( seg1->score >= dist_threshold )+ continue;++ for ( seg2 = segments; seg2 < segment_limit; seg2++ )+ {+ if ( seg2->pos > seg1->pos || seg1 == seg2 )+ continue;++ link2 = seg2->link;+ if ( !link2 || link2->link != seg2 || link2->pos < link1->pos )+ continue;++ if ( seg1->pos == seg2->pos && link1->pos == link2->pos )+ continue;++ if ( seg2->score <= seg1->score || seg1->score * 4 <= seg2->score )+ continue;++ /* seg2 < seg1 < link1 < link2 */++ if ( seg1->len >= seg2->len * 3 )+ {+ AF_Segment seg;+++ for ( seg = segments; seg < segment_limit; seg++ )+ {+ AF_Segment link = seg->link;+++ if ( link == seg2 )+ {+ seg->link = 0;+ seg->serif = link1;+ }+ else if ( link == link2 )+ {+ seg->link = 0;+ seg->serif = seg1;+ }+ }+ }+ else+ {+ seg1->link = link1->link = 0;++ break;+ }+ }+ }+ }++ for ( seg1 = segments; seg1 < segment_limit; seg1++ )+ {+ seg2 = seg1->link;++ if ( seg2 )+ {+ seg2->num_linked++;+ if ( seg2->link != seg1 )+ {+ seg1->link = 0;++ if ( seg2->score < dist_threshold || seg1->score < seg2->score * 4 )+ seg1->serif = seg2->link;+ else+ seg2->num_linked--;+ }+ }+ }+ }+++ static FT_Error+ af_cjk_hints_compute_edges( AF_GlyphHints hints,+ AF_Dimension dim )+ {+ AF_AxisHints axis = &hints->axis[dim];+ FT_Error error = AF_Err_Ok;+ FT_Memory memory = hints->memory;+ AF_LatinAxis laxis = &((AF_LatinMetrics)hints->metrics)->axis[dim];++ AF_Segment segments = axis->segments;+ AF_Segment segment_limit = segments + axis->num_segments;+ AF_Segment seg;++ FT_Fixed scale;+ FT_Pos edge_distance_threshold;+++ axis->num_edges = 0;++ scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale+ : hints->y_scale;++ /*********************************************************************/+ /* */+ /* We begin by generating a sorted table of edges for the current */+ /* direction. To do so, we simply scan each segment and try to find */+ /* an edge in our table that corresponds to its position. */+ /* */+ /* If no edge is found, we create and insert a new edge in the */+ /* sorted table. Otherwise, we simply add the segment to the edge's */+ /* list which is then processed in the second step to compute the */+ /* edge's properties. */+ /* */+ /* Note that the edges table is sorted along the segment/edge */+ /* position. */+ /* */+ /*********************************************************************/++ edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold,+ scale );+ if ( edge_distance_threshold > 64 / 4 )+ edge_distance_threshold = FT_DivFix( 64 / 4, scale );+ else+ edge_distance_threshold = laxis->edge_distance_threshold;++ for ( seg = segments; seg < segment_limit; seg++ )+ {+ AF_Edge found = 0;+ FT_Pos best = 0xFFFFU;+ FT_Int ee;+++ /* look for an edge corresponding to the segment */+ for ( ee = 0; ee < axis->num_edges; ee++ )+ {+ AF_Edge edge = axis->edges + ee;+ FT_Pos dist;+++ if ( edge->dir != seg->dir )+ continue;++ dist = seg->pos - edge->fpos;+ if ( dist < 0 )+ dist = -dist;++ if ( dist < edge_distance_threshold && dist < best )+ {+ AF_Segment link = seg->link;+++ /* check whether all linked segments of the candidate edge */+ /* can make a single edge. */+ if ( link )+ {+ AF_Segment seg1 = edge->first;+ AF_Segment link1;+ FT_Pos dist2 = 0;+++ do+ {+ link1 = seg1->link;+ if ( link1 )+ {+ dist2 = AF_SEGMENT_DIST( link, link1 );+ if ( dist2 >= edge_distance_threshold )+ break;+ }++ } while ( ( seg1 = seg1->edge_next ) != edge->first );++ if ( dist2 >= edge_distance_threshold )+ continue;+ }++ best = dist;+ found = edge;+ }+ }++ if ( !found )+ {+ AF_Edge edge;+++ /* insert a new edge in the list and */+ /* sort according to the position */+ error = af_axis_hints_new_edge( axis, seg->pos,+ (AF_Direction)seg->dir,+ memory, &edge );+ if ( error )+ goto Exit;++ /* add the segment to the new edge's list */+ FT_ZERO( edge );++ edge->first = seg;+ edge->last = seg;+ edge->fpos = seg->pos;+ edge->opos = edge->pos = FT_MulFix( seg->pos, scale );+ seg->edge_next = seg;+ edge->dir = seg->dir;+ }+ else+ {+ /* if an edge was found, simply add the segment to the edge's */+ /* list */+ seg->edge_next = found->first;+ found->last->edge_next = seg;+ found->last = seg;+ }+ }++ /*********************************************************************/+ /* */+ /* Good, we now compute each edge's properties according to segments */+ /* found on its position. Basically, these are as follows. */+ /* */+ /* - edge's main direction */+ /* - stem edge, serif edge or both (which defaults to stem then) */+ /* - rounded edge, straight or both (which defaults to straight) */+ /* - link for edge */+ /* */+ /*********************************************************************/++ /* first of all, set the `edge' field in each segment -- this is */+ /* required in order to compute edge links */+ /* */+ /* Note that removing this loop and setting the `edge' field of each */+ /* segment directly in the code above slows down execution speed for */+ /* some reasons on platforms like the Sun. */++ {+ AF_Edge edges = axis->edges;+ AF_Edge edge_limit = edges + axis->num_edges;+ AF_Edge edge;+++ for ( edge = edges; edge < edge_limit; edge++ )+ {+ seg = edge->first;+ if ( seg )+ do+ {+ seg->edge = edge;+ seg = seg->edge_next;++ } while ( seg != edge->first );+ }++ /* now compute each edge properties */+ for ( edge = edges; edge < edge_limit; edge++ )+ {+ FT_Int is_round = 0; /* does it contain round segments? */+ FT_Int is_straight = 0; /* does it contain straight segments? */+++ seg = edge->first;++ do+ {+ FT_Bool is_serif;+++ /* check for roundness of segment */+ if ( seg->flags & AF_EDGE_ROUND )+ is_round++;+ else+ is_straight++;++ /* check for links -- if seg->serif is set, then seg->link must */+ /* be ignored */+ is_serif = (FT_Bool)( seg->serif && seg->serif->edge != edge );++ if ( seg->link || is_serif )+ {+ AF_Edge edge2;+ AF_Segment seg2;+++ edge2 = edge->link;+ seg2 = seg->link;++ if ( is_serif )+ {+ seg2 = seg->serif;+ edge2 = edge->serif;+ }++ if ( edge2 )+ {+ FT_Pos edge_delta;+ FT_Pos seg_delta;+++ edge_delta = edge->fpos - edge2->fpos;+ if ( edge_delta < 0 )+ edge_delta = -edge_delta;++ seg_delta = AF_SEGMENT_DIST( seg, seg2 );++ if ( seg_delta < edge_delta )+ edge2 = seg2->edge;+ }+ else+ edge2 = seg2->edge;++ if ( is_serif )+ {+ edge->serif = edge2;+ edge2->flags |= AF_EDGE_SERIF;+ }+ else+ edge->link = edge2;+ }++ seg = seg->edge_next;++ } while ( seg != edge->first );++ /* set the round/straight flags */+ edge->flags = AF_EDGE_NORMAL;++ if ( is_round > 0 && is_round >= is_straight )+ edge->flags |= AF_EDGE_ROUND;++ /* get rid of serifs if link is set */+ /* XXX: This gets rid of many unpleasant artefacts! */+ /* Example: the `c' in cour.pfa at size 13 */++ if ( edge->serif && edge->link )+ edge->serif = 0;+ }+ }++ Exit:+ return error;+ }+++ static FT_Error+ af_cjk_hints_detect_features( AF_GlyphHints hints,+ AF_Dimension dim )+ {+ FT_Error error;+++ error = af_cjk_hints_compute_segments( hints, dim );+ if ( !error )+ {+ af_cjk_hints_link_segments( hints, dim );++ error = af_cjk_hints_compute_edges( hints, dim );+ }+ return error;+ }+++ FT_LOCAL_DEF( FT_Error )+ af_cjk_hints_init( AF_GlyphHints hints,+ AF_LatinMetrics metrics )+ {+ FT_Render_Mode mode;+ FT_UInt32 scaler_flags, other_flags;+++ af_glyph_hints_rescale( hints, (AF_ScriptMetrics)metrics );++ /*+ * correct x_scale and y_scale when needed, since they may have+ * been modified af_cjk_scale_dim above+ */+ hints->x_scale = metrics->axis[AF_DIMENSION_HORZ].scale;+ hints->x_delta = metrics->axis[AF_DIMENSION_HORZ].delta;+ hints->y_scale = metrics->axis[AF_DIMENSION_VERT].scale;+ hints->y_delta = metrics->axis[AF_DIMENSION_VERT].delta;++ /* compute flags depending on render mode, etc. */+ mode = metrics->root.scaler.render_mode;++#ifdef AF_USE_WARPER+ if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )+ metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;+#endif++ scaler_flags = hints->scaler_flags;+ other_flags = 0;++ /*+ * We snap the width of vertical stems for the monochrome and+ * horizontal LCD rendering targets only.+ */+ if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD )+ other_flags |= AF_LATIN_HINTS_HORZ_SNAP;++ /*+ * We snap the width of horizontal stems for the monochrome and+ * vertical LCD rendering targets only.+ */+ if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD_V )+ other_flags |= AF_LATIN_HINTS_VERT_SNAP;++ /*+ * We adjust stems to full pixels only if we don't use the `light' mode.+ */+ if ( mode != FT_RENDER_MODE_LIGHT )+ other_flags |= AF_LATIN_HINTS_STEM_ADJUST;++ if ( mode == FT_RENDER_MODE_MONO )+ other_flags |= AF_LATIN_HINTS_MONO;++ scaler_flags |= AF_SCALER_FLAG_NO_ADVANCE;++ hints->scaler_flags = scaler_flags;+ hints->other_flags = other_flags;++ return 0;+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** C J K G L Y P H G R I D - F I T T I N G *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /* snap a given width in scaled coordinates to one of the */+ /* current standard widths */++ static FT_Pos+ af_cjk_snap_width( AF_Width widths,+ FT_Int count,+ FT_Pos width )+ {+ int n;+ FT_Pos best = 64 + 32 + 2;+ FT_Pos reference = width;+ FT_Pos scaled;+++ for ( n = 0; n < count; n++ )+ {+ FT_Pos w;+ FT_Pos dist;+++ w = widths[n].cur;+ dist = width - w;+ if ( dist < 0 )+ dist = -dist;+ if ( dist < best )+ {+ best = dist;+ reference = w;+ }+ }++ scaled = FT_PIX_ROUND( reference );++ if ( width >= reference )+ {+ if ( width < scaled + 48 )+ width = reference;+ }+ else+ {+ if ( width > scaled - 48 )+ width = reference;+ }++ return width;+ }+++ /* compute the snapped width of a given stem */++ static FT_Pos+ af_cjk_compute_stem_width( AF_GlyphHints hints,+ AF_Dimension dim,+ FT_Pos width,+ AF_Edge_Flags base_flags,+ AF_Edge_Flags stem_flags )+ {+ AF_LatinMetrics metrics = (AF_LatinMetrics) hints->metrics;+ AF_LatinAxis axis = & metrics->axis[dim];+ FT_Pos dist = width;+ FT_Int sign = 0;+ FT_Int vertical = ( dim == AF_DIMENSION_VERT );++ FT_UNUSED( base_flags );+ FT_UNUSED( stem_flags );+++ if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) )+ return width;++ if ( dist < 0 )+ {+ dist = -width;+ sign = 1;+ }++ if ( ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) ||+ ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) )+ {+ /* smooth hinting process: very lightly quantize the stem width */++ if ( axis->width_count > 0 )+ {+ if ( FT_ABS( dist - axis->widths[0].cur ) < 40 )+ {+ dist = axis->widths[0].cur;+ if ( dist < 48 )+ dist = 48;++ goto Done_Width;+ }+ }++ if ( dist < 54 )+ dist += ( 54 - dist ) / 2 ;+ else if ( dist < 3 * 64 )+ {+ FT_Pos delta;+++ delta = dist & 63;+ dist &= -64;++ if ( delta < 10 )+ dist += delta;+ else if ( delta < 22 )+ dist += 10;+ else if ( delta < 42 )+ dist += delta;+ else if ( delta < 54 )+ dist += 54;+ else+ dist += delta;+ }+ }+ else+ {+ /* strong hinting process: snap the stem width to integer pixels */++ dist = af_cjk_snap_width( axis->widths, axis->width_count, dist );++ if ( vertical )+ {+ /* in the case of vertical hinting, always round */+ /* the stem heights to integer pixels */++ if ( dist >= 64 )+ dist = ( dist + 16 ) & ~63;+ else+ dist = 64;+ }+ else+ {+ if ( AF_LATIN_HINTS_DO_MONO( hints ) )+ {+ /* monochrome horizontal hinting: snap widths to integer pixels */+ /* with a different threshold */++ if ( dist < 64 )+ dist = 64;+ else+ dist = ( dist + 32 ) & ~63;+ }+ else+ {+ /* for horizontal anti-aliased hinting, we adopt a more subtle */+ /* approach: we strengthen small stems, round stems whose size */+ /* is between 1 and 2 pixels to an integer, otherwise nothing */++ if ( dist < 48 )+ dist = ( dist + 64 ) >> 1;++ else if ( dist < 128 )+ dist = ( dist + 22 ) & ~63;+ else+ /* round otherwise to prevent color fringes in LCD mode */+ dist = ( dist + 32 ) & ~63;+ }+ }+ }++ Done_Width:+ if ( sign )+ dist = -dist;++ return dist;+ }+++ /* align one stem edge relative to the previous stem edge */++ static void+ af_cjk_align_linked_edge( AF_GlyphHints hints,+ AF_Dimension dim,+ AF_Edge base_edge,+ AF_Edge stem_edge )+ {+ FT_Pos dist = stem_edge->opos - base_edge->opos;++ FT_Pos fitted_width = af_cjk_compute_stem_width(+ hints, dim, dist,+ (AF_Edge_Flags)base_edge->flags,+ (AF_Edge_Flags)stem_edge->flags );+++ stem_edge->pos = base_edge->pos + fitted_width;+ }+++ static void+ af_cjk_align_serif_edge( AF_GlyphHints hints,+ AF_Edge base,+ AF_Edge serif )+ {+ FT_UNUSED( hints );++ serif->pos = base->pos + ( serif->opos - base->opos );+ }+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** E D G E H I N T I N G ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++#define AF_LIGHT_MODE_MAX_HORZ_GAP 9+#define AF_LIGHT_MODE_MAX_VERT_GAP 15+#define AF_LIGHT_MODE_MAX_DELTA_ABS 14+++ static FT_Pos+ af_hint_normal_stem( AF_GlyphHints hints,+ AF_Edge edge,+ AF_Edge edge2,+ FT_Pos anchor,+ AF_Dimension dim )+ {+ FT_Pos org_len, cur_len, org_center;+ FT_Pos cur_pos1, cur_pos2;+ FT_Pos d_off1, u_off1, d_off2, u_off2, delta;+ FT_Pos offset;+ FT_Pos threshold = 64;+++ if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) )+ {+ if ( ( edge->flags & AF_EDGE_ROUND ) &&+ ( edge2->flags & AF_EDGE_ROUND ) )+ {+ if ( dim == AF_DIMENSION_VERT )+ threshold = 64 - AF_LIGHT_MODE_MAX_HORZ_GAP;+ else+ threshold = 64 - AF_LIGHT_MODE_MAX_VERT_GAP;+ }+ else+ {+ if ( dim == AF_DIMENSION_VERT )+ threshold = 64 - AF_LIGHT_MODE_MAX_HORZ_GAP / 3;+ else+ threshold = 64 - AF_LIGHT_MODE_MAX_VERT_GAP / 3;+ }+ }++ org_len = edge2->opos - edge->opos;+ cur_len = af_cjk_compute_stem_width( hints, dim, org_len,+ (AF_Edge_Flags)edge->flags,+ (AF_Edge_Flags)edge2->flags );++ org_center = ( edge->opos + edge2->opos ) / 2 + anchor;+ cur_pos1 = org_center - cur_len / 2;+ cur_pos2 = cur_pos1 + cur_len;+ d_off1 = cur_pos1 - FT_PIX_FLOOR( cur_pos1 );+ d_off2 = cur_pos2 - FT_PIX_FLOOR( cur_pos2 );+ u_off1 = 64 - d_off1;+ u_off2 = 64 - d_off2;+ delta = 0;+++ if ( d_off1 == 0 || d_off2 == 0 )+ goto Exit;++ if ( cur_len <= threshold )+ {+ if ( d_off2 < cur_len )+ {+ if ( u_off1 <= d_off2 )+ delta = u_off1;+ else+ delta = -d_off2;+ }++ goto Exit;+ }++ if ( threshold < 64 )+ {+ if ( d_off1 >= threshold || u_off1 >= threshold ||+ d_off2 >= threshold || u_off2 >= threshold )+ goto Exit;+ }++ offset = cur_len % 64;++ if ( offset < 32 )+ {+ if ( u_off1 <= offset || d_off2 <= offset )+ goto Exit;+ }+ else+ offset = 64 - threshold;++ d_off1 = threshold - u_off1;+ u_off1 = u_off1 - offset;+ u_off2 = threshold - d_off2;+ d_off2 = d_off2 - offset;++ if ( d_off1 <= u_off1 )+ u_off1 = -d_off1;++ if ( d_off2 <= u_off2 )+ u_off2 = -d_off2;++ if ( FT_ABS( u_off1 ) <= FT_ABS( u_off2 ) )+ delta = u_off1;+ else+ delta = u_off2;++ Exit:++#if 1+ if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) )+ {+ if ( delta > AF_LIGHT_MODE_MAX_DELTA_ABS )+ delta = AF_LIGHT_MODE_MAX_DELTA_ABS;+ else if ( delta < -AF_LIGHT_MODE_MAX_DELTA_ABS )+ delta = -AF_LIGHT_MODE_MAX_DELTA_ABS;+ }+#endif++ cur_pos1 += delta;++ if ( edge->opos < edge2->opos )+ {+ edge->pos = cur_pos1;+ edge2->pos = cur_pos1 + cur_len;+ }+ else+ {+ edge->pos = cur_pos1 + cur_len;+ edge2->pos = cur_pos1;+ }++ return delta;+ }+++ static void+ af_cjk_hint_edges( AF_GlyphHints hints,+ AF_Dimension dim )+ {+ AF_AxisHints axis = &hints->axis[dim];+ AF_Edge edges = axis->edges;+ AF_Edge edge_limit = edges + axis->num_edges;+ FT_PtrDist n_edges;+ AF_Edge edge;+ AF_Edge anchor = 0;+ FT_Pos delta = 0;+ FT_Int skipped = 0;+++ /* now we align all stem edges. */+ for ( edge = edges; edge < edge_limit; edge++ )+ {+ AF_Edge edge2;+++ if ( edge->flags & AF_EDGE_DONE )+ continue;++ /* skip all non-stem edges */+ edge2 = edge->link;+ if ( !edge2 )+ {+ skipped++;+ continue;+ }++ /* now align the stem */++ if ( edge2 < edge )+ {+ af_cjk_align_linked_edge( hints, dim, edge2, edge );+ edge->flags |= AF_EDGE_DONE;+ continue;+ }++ if ( dim != AF_DIMENSION_VERT && !anchor )+ {++#if 0+ if ( fixedpitch )+ {+ AF_Edge left = edge;+ AF_Edge right = edge_limit - 1;+ AF_EdgeRec left1, left2, right1, right2;+ FT_Pos target, center1, center2;+ FT_Pos delta1, delta2, d1, d2;+++ while ( right > left && !right->link )+ right--;++ left1 = *left;+ left2 = *left->link;+ right1 = *right->link;+ right2 = *right;++ delta = ( ( ( hinter->pp2.x + 32 ) & -64 ) - hinter->pp2.x ) / 2;+ target = left->opos + ( right->opos - left->opos ) / 2 + delta - 16;++ delta1 = delta;+ delta1 += af_hint_normal_stem( hints, left, left->link,+ delta1, 0 );++ if ( left->link != right )+ af_hint_normal_stem( hints, right->link, right, delta1, 0 );++ center1 = left->pos + ( right->pos - left->pos ) / 2;++ if ( center1 >= target )+ delta2 = delta - 32;+ else+ delta2 = delta + 32;++ delta2 += af_hint_normal_stem( hints, &left1, &left2, delta2, 0 );++ if ( delta1 != delta2 )+ {+ if ( left->link != right )+ af_hint_normal_stem( hints, &right1, &right2, delta2, 0 );++ center2 = left1.pos + ( right2.pos - left1.pos ) / 2;++ d1 = center1 - target;+ d2 = center2 - target;++ if ( FT_ABS( d2 ) < FT_ABS( d1 ) )+ {+ left->pos = left1.pos;+ left->link->pos = left2.pos;++ if ( left->link != right )+ {+ right->link->pos = right1.pos;+ right->pos = right2.pos;+ }++ delta1 = delta2;+ }+ }++ delta = delta1;+ right->link->flags |= AF_EDGE_DONE;+ right->flags |= AF_EDGE_DONE;+ }+ else++#endif /* 0 */++ delta = af_hint_normal_stem( hints, edge, edge2, 0,+ AF_DIMENSION_HORZ );+ }+ else+ af_hint_normal_stem( hints, edge, edge2, delta, dim );++#if 0+ printf( "stem (%d,%d) adjusted (%.1f,%.1f)\n",+ edge - edges, edge2 - edges,+ ( edge->pos - edge->opos ) / 64.0,+ ( edge2->pos - edge2->opos ) / 64.0 );+#endif++ anchor = edge;+ edge->flags |= AF_EDGE_DONE;+ edge2->flags |= AF_EDGE_DONE;+ }++ /* make sure that lowercase m's maintain their symmetry */++ /* In general, lowercase m's have six vertical edges if they are sans */+ /* serif, or twelve if they are with serifs. This implementation is */+ /* based on that assumption, and seems to work very well with most */+ /* faces. However, if for a certain face this assumption is not */+ /* true, the m is just rendered like before. In addition, any stem */+ /* correction will only be applied to symmetrical glyphs (even if the */+ /* glyph is not an m), so the potential for unwanted distortion is */+ /* relatively low. */++ /* We don't handle horizontal edges since we can't easily assure that */+ /* the third (lowest) stem aligns with the base line; it might end up */+ /* one pixel higher or lower. */++ n_edges = edge_limit - edges;+ if ( dim == AF_DIMENSION_HORZ && ( n_edges == 6 || n_edges == 12 ) )+ {+ AF_Edge edge1, edge2, edge3;+ FT_Pos dist1, dist2, span;+++ if ( n_edges == 6 )+ {+ edge1 = edges;+ edge2 = edges + 2;+ edge3 = edges + 4;+ }+ else+ {+ edge1 = edges + 1;+ edge2 = edges + 5;+ edge3 = edges + 9;+ }++ dist1 = edge2->opos - edge1->opos;+ dist2 = edge3->opos - edge2->opos;++ span = dist1 - dist2;+ if ( span < 0 )+ span = -span;++ if ( edge1->link == edge1 + 1 &&+ edge2->link == edge2 + 1 &&+ edge3->link == edge3 + 1 && span < 8 )+ {+ delta = edge3->pos - ( 2 * edge2->pos - edge1->pos );+ edge3->pos -= delta;+ if ( edge3->link )+ edge3->link->pos -= delta;++ /* move the serifs along with the stem */+ if ( n_edges == 12 )+ {+ ( edges + 8 )->pos -= delta;+ ( edges + 11 )->pos -= delta;+ }++ edge3->flags |= AF_EDGE_DONE;+ if ( edge3->link )+ edge3->link->flags |= AF_EDGE_DONE;+ }+ }++ if ( !skipped )+ return;++ /*+ * now hint the remaining edges (serifs and single) in order+ * to complete our processing+ */+ for ( edge = edges; edge < edge_limit; edge++ )+ {+ if ( edge->flags & AF_EDGE_DONE )+ continue;++ if ( edge->serif )+ {+ af_cjk_align_serif_edge( hints, edge->serif, edge );+ edge->flags |= AF_EDGE_DONE;+ skipped--;+ }+ }++ if ( !skipped )+ return;++ for ( edge = edges; edge < edge_limit; edge++ )+ {+ AF_Edge before, after;+++ if ( edge->flags & AF_EDGE_DONE )+ continue;++ before = after = edge;++ while ( --before >= edges )+ if ( before->flags & AF_EDGE_DONE )+ break;++ while ( ++after < edge_limit )+ if ( after->flags & AF_EDGE_DONE )+ break;++ if ( before >= edges || after < edge_limit )+ {+ if ( before < edges )+ af_cjk_align_serif_edge( hints, after, edge );+ else if ( after >= edge_limit )+ af_cjk_align_serif_edge( hints, before, edge );+ else+ {+ if ( after->fpos == before->fpos )+ edge->pos = before->pos;+ else+ edge->pos = before->pos ++ FT_MulDiv( edge->fpos - before->fpos,+ after->pos - before->pos,+ after->fpos - before->fpos );+ }+ }+ }+ }+++ static void+ af_cjk_align_edge_points( AF_GlyphHints hints,+ AF_Dimension dim )+ {+ AF_AxisHints axis = & hints->axis[dim];+ AF_Edge edges = axis->edges;+ AF_Edge edge_limit = edges + axis->num_edges;+ AF_Edge edge;+ FT_Bool snapping;+++ snapping = FT_BOOL( ( dim == AF_DIMENSION_HORZ &&+ AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) ||+ ( dim == AF_DIMENSION_VERT &&+ AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) );++ for ( edge = edges; edge < edge_limit; edge++ )+ {+ /* move the points of each segment */+ /* in each edge to the edge's position */+ AF_Segment seg = edge->first;+++ if ( snapping )+ {+ do+ {+ AF_Point point = seg->first;+++ for (;;)+ {+ if ( dim == AF_DIMENSION_HORZ )+ {+ point->x = edge->pos;+ point->flags |= AF_FLAG_TOUCH_X;+ }+ else+ {+ point->y = edge->pos;+ point->flags |= AF_FLAG_TOUCH_Y;+ }++ if ( point == seg->last )+ break;++ point = point->next;+ }++ seg = seg->edge_next;++ } while ( seg != edge->first );+ }+ else+ {+ FT_Pos delta = edge->pos - edge->opos;+++ do+ {+ AF_Point point = seg->first;+++ for (;;)+ {+ if ( dim == AF_DIMENSION_HORZ )+ {+ point->x += delta;+ point->flags |= AF_FLAG_TOUCH_X;+ }+ else+ {+ point->y += delta;+ point->flags |= AF_FLAG_TOUCH_Y;+ }++ if ( point == seg->last )+ break;++ point = point->next;+ }++ seg = seg->edge_next;++ } while ( seg != edge->first );+ }+ }+ }+++ FT_LOCAL_DEF( FT_Error )+ af_cjk_hints_apply( AF_GlyphHints hints,+ FT_Outline* outline,+ AF_LatinMetrics metrics )+ {+ FT_Error error;+ int dim;++ FT_UNUSED( metrics );+++ error = af_glyph_hints_reload( hints, outline );+ if ( error )+ goto Exit;++ /* analyze glyph outline */+ if ( AF_HINTS_DO_HORIZONTAL( hints ) )+ {+ error = af_cjk_hints_detect_features( hints, AF_DIMENSION_HORZ );+ if ( error )+ goto Exit;+ }++ if ( AF_HINTS_DO_VERTICAL( hints ) )+ {+ error = af_cjk_hints_detect_features( hints, AF_DIMENSION_VERT );+ if ( error )+ goto Exit;+ }++ /* grid-fit the outline */+ for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )+ {+ if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) ||+ ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) ) )+ {++#ifdef AF_USE_WARPER+ if ( dim == AF_DIMENSION_HORZ &&+ metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL )+ {+ AF_WarperRec warper;+ FT_Fixed scale;+ FT_Pos delta;+++ af_warper_compute( &warper, hints, dim, &scale, &delta );+ af_glyph_hints_scale_dim( hints, dim, scale, delta );+ continue;+ }+#endif /* AF_USE_WARPER */++ af_cjk_hint_edges( hints, (AF_Dimension)dim );+ af_cjk_align_edge_points( hints, (AF_Dimension)dim );+ af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim );+ af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim );+ }+ }++#if 0+ af_glyph_hints_dump_points( hints );+ af_glyph_hints_dump_segments( hints );+ af_glyph_hints_dump_edges( hints );+#endif++ af_glyph_hints_save( hints, outline );++ Exit:+ return error;+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** C J K S C R I P T C L A S S *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+++ static const AF_Script_UniRangeRec af_cjk_uniranges[] =+ {+#if 0+ AF_UNIRANGE_REC( 0x0100UL, 0xFFFFUL ), /* why this? */+#endif+ AF_UNIRANGE_REC( 0x2E80UL, 0x2EFFUL ), /* CJK Radicals Supplement */+ AF_UNIRANGE_REC( 0x2F00UL, 0x2FDFUL ), /* Kangxi Radicals */+ AF_UNIRANGE_REC( 0x3000UL, 0x303FUL ), /* CJK Symbols and Punctuation */+ AF_UNIRANGE_REC( 0x3040UL, 0x309FUL ), /* Hiragana */+ AF_UNIRANGE_REC( 0x30A0UL, 0x30FFUL ), /* Katakana */+ AF_UNIRANGE_REC( 0x3100UL, 0x312FUL ), /* Bopomofo */+ AF_UNIRANGE_REC( 0x3130UL, 0x318FUL ), /* Hangul Compatibility Jamo */+ AF_UNIRANGE_REC( 0x31A0UL, 0x31BFUL ), /* Bopomofo Extended */+ AF_UNIRANGE_REC( 0x31C0UL, 0x31EFUL ), /* CJK Strokes */+ AF_UNIRANGE_REC( 0x31F0UL, 0x31FFUL ), /* Katakana Phonetic Extensions */+ AF_UNIRANGE_REC( 0x3200UL, 0x32FFUL ), /* Enclosed CJK Letters and Months */+ AF_UNIRANGE_REC( 0x3300UL, 0x33FFUL ), /* CJK Compatibility */+ AF_UNIRANGE_REC( 0x3400UL, 0x4DBFUL ), /* CJK Unified Ideographs Extension A */+ AF_UNIRANGE_REC( 0x4DC0UL, 0x4DFFUL ), /* Yijing Hexagram Symbols */+ AF_UNIRANGE_REC( 0x4E00UL, 0x9FFFUL ), /* CJK Unified Ideographs */+ AF_UNIRANGE_REC( 0xF900UL, 0xFAFFUL ), /* CJK Compatibility Ideographs */+ AF_UNIRANGE_REC( 0xFE30UL, 0xFE4FUL ), /* CJK Compatibility Forms */+ AF_UNIRANGE_REC( 0xFF00UL, 0xFFEFUL ), /* Halfwidth and Fullwidth Forms */+ AF_UNIRANGE_REC( 0x20000UL, 0x2A6DFUL ), /* CJK Unified Ideographs Extension B */+ AF_UNIRANGE_REC( 0x2F800UL, 0x2FA1FUL ), /* CJK Compatibility Ideographs Supplement */+ AF_UNIRANGE_REC( 0UL, 0UL )+ };+++ AF_DEFINE_SCRIPT_CLASS(af_cjk_script_class,+ AF_SCRIPT_CJK,+ af_cjk_uniranges,++ sizeof( AF_LatinMetricsRec ),++ (AF_Script_InitMetricsFunc) af_cjk_metrics_init,+ (AF_Script_ScaleMetricsFunc)af_cjk_metrics_scale,+ (AF_Script_DoneMetricsFunc) NULL,++ (AF_Script_InitHintsFunc) af_cjk_hints_init,+ (AF_Script_ApplyHintsFunc) af_cjk_hints_apply+ )++#else /* !AF_CONFIG_OPTION_CJK */++ static const AF_Script_UniRangeRec af_cjk_uniranges[] =+ {+ AF_UNIRANGE_REC( 0UL, 0UL )+ };+++ AF_DEFINE_SCRIPT_CLASS(af_cjk_script_class,+ AF_SCRIPT_CJK,+ af_cjk_uniranges,++ sizeof( AF_LatinMetricsRec ),++ (AF_Script_InitMetricsFunc) NULL,+ (AF_Script_ScaleMetricsFunc)NULL,+ (AF_Script_DoneMetricsFunc) NULL,++ (AF_Script_InitHintsFunc) NULL,+ (AF_Script_ApplyHintsFunc) NULL+ )++#endif /* !AF_CONFIG_OPTION_CJK */+++/* END */
+ src/autofit/afcjk.h view
@@ -0,0 +1,57 @@+/***************************************************************************/+/* */+/* afcjk.h */+/* */+/* Auto-fitter hinting routines for CJK script (specification). */+/* */+/* Copyright 2006, 2007 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#ifndef __AFCJK_H__+#define __AFCJK_H__++#include "afhints.h"+++FT_BEGIN_HEADER+++ /* the CJK-specific script class */++ AF_DECLARE_SCRIPT_CLASS(af_cjk_script_class)+++ FT_LOCAL( FT_Error )+ af_cjk_metrics_init( AF_LatinMetrics metrics,+ FT_Face face );++ FT_LOCAL( void )+ af_cjk_metrics_scale( AF_LatinMetrics metrics,+ AF_Scaler scaler );++ FT_LOCAL( FT_Error )+ af_cjk_hints_init( AF_GlyphHints hints,+ AF_LatinMetrics metrics );++ FT_LOCAL( FT_Error )+ af_cjk_hints_apply( AF_GlyphHints hints,+ FT_Outline* outline,+ AF_LatinMetrics metrics );++/* */++FT_END_HEADER++#endif /* __AFCJK_H__ */+++/* END */
+ src/autofit/afdummy.c view
@@ -0,0 +1,60 @@+/***************************************************************************/+/* */+/* afdummy.c */+/* */+/* Auto-fitter dummy routines to be used if no hinting should be */+/* performed (body). */+/* */+/* Copyright 2003, 2004, 2005 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#include "afdummy.h"+#include "afhints.h"+++ static FT_Error+ af_dummy_hints_init( AF_GlyphHints hints,+ AF_ScriptMetrics metrics )+ {+ af_glyph_hints_rescale( hints,+ metrics );+ return 0;+ }+++ static FT_Error+ af_dummy_hints_apply( AF_GlyphHints hints,+ FT_Outline* outline )+ {+ FT_UNUSED( hints );+ FT_UNUSED( outline );++ return 0;+ }+++ AF_DEFINE_SCRIPT_CLASS(af_dummy_script_class,+ AF_SCRIPT_NONE,+ NULL,++ sizeof( AF_ScriptMetricsRec ),++ (AF_Script_InitMetricsFunc) NULL,+ (AF_Script_ScaleMetricsFunc)NULL,+ (AF_Script_DoneMetricsFunc) NULL,++ (AF_Script_InitHintsFunc) af_dummy_hints_init,+ (AF_Script_ApplyHintsFunc) af_dummy_hints_apply+ )+++/* END */
+ src/autofit/afdummy.h view
@@ -0,0 +1,42 @@+/***************************************************************************/+/* */+/* afdummy.h */+/* */+/* Auto-fitter dummy routines to be used if no hinting should be */+/* performed (specification). */+/* */+/* Copyright 2003, 2004, 2005 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#ifndef __AFDUMMY_H__+#define __AFDUMMY_H__++#include "aftypes.h"+++FT_BEGIN_HEADER++ /* A dummy script metrics class used when no hinting should+ * be performed. This is the default for non-latin glyphs!+ */++ AF_DECLARE_SCRIPT_CLASS(af_dummy_script_class)++/* */++FT_END_HEADER+++#endif /* __AFDUMMY_H__ */+++/* END */
+ src/autofit/aferrors.h view
@@ -0,0 +1,40 @@+/***************************************************************************/+/* */+/* aferrors.h */+/* */+/* Autofitter error codes (specification only). */+/* */+/* Copyright 2005 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++ /*************************************************************************/+ /* */+ /* This file is used to define the Autofitter error enumeration */+ /* constants. */+ /* */+ /*************************************************************************/++#ifndef __AFERRORS_H__+#define __AFERRORS_H__++#include FT_MODULE_ERRORS_H++#undef __FTERRORS_H__++#define FT_ERR_PREFIX AF_Err_+#define FT_ERR_BASE FT_Mod_Err_Autofit++#include FT_ERRORS_H++#endif /* __AFERRORS_H__ */++/* END */
+ src/autofit/afglobal.c view
@@ -0,0 +1,323 @@+/***************************************************************************/+/* */+/* afglobal.c */+/* */+/* Auto-fitter routines to compute global hinting values (body). */+/* */+/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#include "afglobal.h"+#include "afdummy.h"+#include "aflatin.h"+#include "afcjk.h"+#include "afindic.h"+#include "afpic.h"++#include "aferrors.h"++#ifdef FT_OPTION_AUTOFIT2+#include "aflatin2.h"+#endif++#ifndef FT_CONFIG_OPTION_PIC++/* when updating this table, don't forget to update + AF_SCRIPT_CLASSES_COUNT and autofit_module_class_pic_init */++ /* populate this list when you add new scripts */+ static AF_ScriptClass const af_script_classes[] =+ {+ &af_dummy_script_class,+#ifdef FT_OPTION_AUTOFIT2+ &af_latin2_script_class,+#endif+ &af_latin_script_class,+ &af_cjk_script_class,+ &af_indic_script_class, + NULL /* do not remove */+ };++#endif /* FT_CONFIG_OPTION_PIC */++ /* index of default script in `af_script_classes' */+#define AF_SCRIPT_LIST_DEFAULT 2+ /* a bit mask indicating an uncovered glyph */+#define AF_SCRIPT_LIST_NONE 0x7F+ /* if this flag is set, we have an ASCII digit */+#define AF_DIGIT 0x80+++ /*+ * Note that glyph_scripts[] is used to map each glyph into+ * an index into the `af_script_classes' array.+ *+ */+ typedef struct AF_FaceGlobalsRec_+ {+ FT_Face face;+ FT_Long glyph_count; /* same as face->num_glyphs */+ FT_Byte* glyph_scripts;++ AF_ScriptMetrics metrics[AF_SCRIPT_MAX];++ } AF_FaceGlobalsRec;+++ /* Compute the script index of each glyph within a given face. */++ static FT_Error+ af_face_globals_compute_script_coverage( AF_FaceGlobals globals )+ {+ FT_Error error = AF_Err_Ok;+ FT_Face face = globals->face;+ FT_CharMap old_charmap = face->charmap;+ FT_Byte* gscripts = globals->glyph_scripts;+ FT_UInt ss, i;+++ /* the value 255 means `uncovered glyph' */+ FT_MEM_SET( globals->glyph_scripts,+ AF_SCRIPT_LIST_NONE,+ globals->glyph_count );++ error = FT_Select_Charmap( face, FT_ENCODING_UNICODE );+ if ( error )+ {+ /*+ * Ignore this error; we simply use the default script.+ * XXX: Shouldn't we rather disable hinting?+ */+ error = AF_Err_Ok;+ goto Exit;+ }++ /* scan each script in a Unicode charmap */+ for ( ss = 0; AF_SCRIPT_CLASSES_GET[ss]; ss++ )+ {+ AF_ScriptClass clazz = AF_SCRIPT_CLASSES_GET[ss];+ AF_Script_UniRange range;+++ if ( clazz->script_uni_ranges == NULL )+ continue;++ /*+ * Scan all unicode points in the range and set the corresponding+ * glyph script index.+ */+ for ( range = clazz->script_uni_ranges; range->first != 0; range++ )+ {+ FT_ULong charcode = range->first;+ FT_UInt gindex;+++ gindex = FT_Get_Char_Index( face, charcode );++ if ( gindex != 0 &&+ gindex < (FT_ULong)globals->glyph_count &&+ gscripts[gindex] == AF_SCRIPT_LIST_NONE )+ {+ gscripts[gindex] = (FT_Byte)ss;+ }++ for (;;)+ {+ charcode = FT_Get_Next_Char( face, charcode, &gindex );++ if ( gindex == 0 || charcode > range->last )+ break;++ if ( gindex < (FT_ULong)globals->glyph_count &&+ gscripts[gindex] == AF_SCRIPT_LIST_NONE )+ {+ gscripts[gindex] = (FT_Byte)ss;+ }+ }+ }+ }++ /* mark ASCII digits */+ for ( i = 0x30; i <= 0x39; i++ )+ {+ FT_UInt gindex = FT_Get_Char_Index( face, i );+++ if ( gindex != 0 && gindex < (FT_ULong)globals->glyph_count )+ gscripts[gindex] |= AF_DIGIT;+ }++ Exit:+ /*+ * By default, all uncovered glyphs are set to the latin script.+ * XXX: Shouldn't we disable hinting or do something similar?+ */+ {+ FT_Long nn;+++ for ( nn = 0; nn < globals->glyph_count; nn++ )+ {+ if ( ( gscripts[nn] & ~AF_DIGIT ) == AF_SCRIPT_LIST_NONE )+ {+ gscripts[nn] &= ~AF_SCRIPT_LIST_NONE;+ gscripts[nn] |= AF_SCRIPT_LIST_DEFAULT;+ }+ }+ }++ FT_Set_Charmap( face, old_charmap );+ return error;+ }+++ FT_LOCAL_DEF( FT_Error )+ af_face_globals_new( FT_Face face,+ AF_FaceGlobals *aglobals )+ {+ FT_Error error;+ FT_Memory memory;+ AF_FaceGlobals globals = NULL;+++ memory = face->memory;++ if ( !FT_ALLOC( globals, sizeof ( *globals ) ++ face->num_glyphs * sizeof ( FT_Byte ) ) )+ {+ globals->face = face;+ globals->glyph_count = face->num_glyphs;+ globals->glyph_scripts = (FT_Byte*)( globals + 1 );++ error = af_face_globals_compute_script_coverage( globals );+ if ( error )+ {+ af_face_globals_free( globals );+ globals = NULL;+ }+ }++ *aglobals = globals;+ return error;+ }+++ FT_LOCAL_DEF( void )+ af_face_globals_free( AF_FaceGlobals globals )+ {+ if ( globals )+ {+ FT_Memory memory = globals->face->memory;+ FT_UInt nn;+++ for ( nn = 0; nn < AF_SCRIPT_MAX; nn++ )+ {+ if ( globals->metrics[nn] )+ {+ AF_ScriptClass clazz = AF_SCRIPT_CLASSES_GET[nn];+++ FT_ASSERT( globals->metrics[nn]->clazz == clazz );++ if ( clazz->script_metrics_done )+ clazz->script_metrics_done( globals->metrics[nn] );++ FT_FREE( globals->metrics[nn] );+ }+ }++ globals->glyph_count = 0;+ globals->glyph_scripts = NULL; /* no need to free this one! */+ globals->face = NULL;++ FT_FREE( globals );+ }+ }+++ FT_LOCAL_DEF( FT_Error )+ af_face_globals_get_metrics( AF_FaceGlobals globals,+ FT_UInt gindex,+ FT_UInt options,+ AF_ScriptMetrics *ametrics )+ {+ AF_ScriptMetrics metrics = NULL;+ FT_UInt gidx;+ AF_ScriptClass clazz;+ FT_UInt script = options & 15;+ const FT_Offset script_max = sizeof ( AF_SCRIPT_CLASSES_GET ) /+ sizeof ( AF_SCRIPT_CLASSES_GET[0] );+ FT_Error error = AF_Err_Ok;+++ if ( gindex >= (FT_ULong)globals->glyph_count )+ {+ error = AF_Err_Invalid_Argument;+ goto Exit;+ }++ gidx = script;+ if ( gidx == 0 || gidx + 1 >= script_max )+ gidx = globals->glyph_scripts[gindex] & AF_SCRIPT_LIST_NONE;++ clazz = AF_SCRIPT_CLASSES_GET[gidx];+ if ( script == 0 )+ script = clazz->script;++ metrics = globals->metrics[clazz->script];+ if ( metrics == NULL )+ {+ /* create the global metrics object when needed */+ FT_Memory memory = globals->face->memory;+++ if ( FT_ALLOC( metrics, clazz->script_metrics_size ) )+ goto Exit;++ metrics->clazz = clazz;++ if ( clazz->script_metrics_init )+ {+ error = clazz->script_metrics_init( metrics, globals->face );+ if ( error )+ {+ if ( clazz->script_metrics_done )+ clazz->script_metrics_done( metrics );++ FT_FREE( metrics );+ goto Exit;+ }+ }++ globals->metrics[clazz->script] = metrics;+ }++ Exit:+ *ametrics = metrics;++ return error;+ }+++ FT_LOCAL_DEF( FT_Bool )+ af_face_globals_is_digit( AF_FaceGlobals globals,+ FT_UInt gindex )+ {+ if ( gindex < (FT_ULong)globals->glyph_count )+ return (FT_Bool)( globals->glyph_scripts[gindex] & AF_DIGIT );++ return (FT_Bool)0;+ }+++/* END */
+ src/autofit/afglobal.h view
@@ -0,0 +1,71 @@+/***************************************************************************/+/* */+/* afglobal.h */+/* */+/* Auto-fitter routines to compute global hinting values */+/* (specification). */+/* */+/* Copyright 2003, 2004, 2005, 2007, 2009 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 __AF_GLOBAL_H__+#define __AF_GLOBAL_H__+++#include "aftypes.h"+++FT_BEGIN_HEADER+++ /************************************************************************/+ /************************************************************************/+ /***** *****/+ /***** F A C E G L O B A L S *****/+ /***** *****/+ /************************************************************************/+ /************************************************************************/+++ /*+ * model the global hints data for a given face, decomposed into+ * script-specific items+ */+ typedef struct AF_FaceGlobalsRec_* AF_FaceGlobals;+++ FT_LOCAL( FT_Error )+ af_face_globals_new( FT_Face face,+ AF_FaceGlobals *aglobals );++ FT_LOCAL( FT_Error )+ af_face_globals_get_metrics( AF_FaceGlobals globals,+ FT_UInt gindex,+ FT_UInt options,+ AF_ScriptMetrics *ametrics );++ FT_LOCAL( void )+ af_face_globals_free( AF_FaceGlobals globals );++ FT_LOCAL_DEF( FT_Bool )+ af_face_globals_is_digit( AF_FaceGlobals globals,+ FT_UInt gindex );++ /* */+++FT_END_HEADER++#endif /* __AF_GLOBALS_H__ */+++/* END */
+ src/autofit/afhints.c view
@@ -0,0 +1,1142 @@+/***************************************************************************/+/* */+/* afhints.c */+/* */+/* Auto-fitter hinting routines (body). */+/* */+/* Copyright 2003, 2004, 2005, 2006, 2007, 2009, 2010 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 "afhints.h"+#include "aferrors.h"+#include FT_INTERNAL_CALC_H+++ FT_LOCAL_DEF( FT_Error )+ af_axis_hints_new_segment( AF_AxisHints axis,+ FT_Memory memory,+ AF_Segment *asegment )+ {+ FT_Error error = AF_Err_Ok;+ AF_Segment segment = NULL;+++ if ( axis->num_segments >= axis->max_segments )+ {+ FT_Int old_max = axis->max_segments;+ FT_Int new_max = old_max;+ FT_Int big_max = (FT_Int)( FT_INT_MAX / sizeof ( *segment ) );+++ if ( old_max >= big_max )+ {+ error = AF_Err_Out_Of_Memory;+ goto Exit;+ }++ new_max += ( new_max >> 2 ) + 4;+ if ( new_max < old_max || new_max > big_max )+ new_max = big_max;++ if ( FT_RENEW_ARRAY( axis->segments, old_max, new_max ) )+ goto Exit;++ axis->max_segments = new_max;+ }++ segment = axis->segments + axis->num_segments++;++ Exit:+ *asegment = segment;+ return error;+ }+++ FT_LOCAL( FT_Error )+ af_axis_hints_new_edge( AF_AxisHints axis,+ FT_Int fpos,+ AF_Direction dir,+ FT_Memory memory,+ AF_Edge *aedge )+ {+ FT_Error error = AF_Err_Ok;+ AF_Edge edge = NULL;+ AF_Edge edges;+++ if ( axis->num_edges >= axis->max_edges )+ {+ FT_Int old_max = axis->max_edges;+ FT_Int new_max = old_max;+ FT_Int big_max = (FT_Int)( FT_INT_MAX / sizeof ( *edge ) );+++ if ( old_max >= big_max )+ {+ error = AF_Err_Out_Of_Memory;+ goto Exit;+ }++ new_max += ( new_max >> 2 ) + 4;+ if ( new_max < old_max || new_max > big_max )+ new_max = big_max;++ if ( FT_RENEW_ARRAY( axis->edges, old_max, new_max ) )+ goto Exit;++ axis->max_edges = new_max;+ }++ edges = axis->edges;+ edge = edges + axis->num_edges;++ while ( edge > edges )+ {+ if ( edge[-1].fpos < fpos )+ break;++ /* we want the edge with same position and minor direction */+ /* to appear before those in the major one in the list */+ if ( edge[-1].fpos == fpos && dir == axis->major_dir )+ break;++ edge[0] = edge[-1];+ edge--;+ }++ axis->num_edges++;++ FT_ZERO( edge );+ edge->fpos = (FT_Short)fpos;+ edge->dir = (FT_Char)dir;++ Exit:+ *aedge = edge;+ return error;+ }+++#ifdef AF_DEBUG++#include FT_CONFIG_STANDARD_LIBRARY_H++ static const char*+ af_dir_str( AF_Direction dir )+ {+ const char* result;+++ switch ( dir )+ {+ case AF_DIR_UP:+ result = "up";+ break;+ case AF_DIR_DOWN:+ result = "down";+ break;+ case AF_DIR_LEFT:+ result = "left";+ break;+ case AF_DIR_RIGHT:+ result = "right";+ break;+ default:+ result = "none";+ }++ return result;+ }+++#define AF_INDEX_NUM( ptr, base ) ( (ptr) ? ( (ptr) - (base) ) : -1 )+++ void+ af_glyph_hints_dump_points( AF_GlyphHints hints )+ {+ AF_Point points = hints->points;+ AF_Point limit = points + hints->num_points;+ AF_Point point;+++ printf( "Table of points:\n" );+ printf( " [ index | xorg | yorg | xscale | yscale "+ "| xfit | yfit | flags ]\n" );++ for ( point = points; point < limit; point++ )+ {+ printf( " [ %5d | %5d | %5d | %-5.2f | %-5.2f "+ "| %-5.2f | %-5.2f | %c%c%c%c%c%c ]\n",+ point - points,+ 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->flags & AF_FLAG_INFLECTION ) ? 'i' : ' ',+ ( point->flags & AF_FLAG_EXTREMA_X ) ? '<' : ' ',+ ( point->flags & AF_FLAG_EXTREMA_Y ) ? 'v' : ' ',+ ( point->flags & AF_FLAG_ROUND_X ) ? '(' : ' ',+ ( point->flags & AF_FLAG_ROUND_Y ) ? 'u' : ' ');+ }+ printf( "\n" );+ }+++ static const char*+ af_edge_flags_to_string( AF_Edge_Flags flags )+ {+ static char temp[32];+ int pos = 0;+++ if ( flags & AF_EDGE_ROUND )+ {+ ft_memcpy( temp + pos, "round", 5 );+ pos += 5;+ }+ if ( flags & AF_EDGE_SERIF )+ {+ if ( pos > 0 )+ temp[pos++] = ' ';+ ft_memcpy( temp + pos, "serif", 5 );+ pos += 5;+ }+ if ( pos == 0 )+ return "normal";++ temp[pos] = 0;++ return temp;+ }+++ /* A function to dump the array of linked segments. */+ void+ af_glyph_hints_dump_segments( AF_GlyphHints hints )+ {+ FT_Int dimension;+++ for ( dimension = 1; dimension >= 0; dimension-- )+ {+ AF_AxisHints axis = &hints->axis[dimension];+ AF_Segment segments = axis->segments;+ AF_Segment limit = segments + axis->num_segments;+ AF_Segment seg;+++ printf ( "Table of %s segments:\n",+ dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" );+ printf ( " [ index | pos | dir | link | serif |"+ " height | extra | flags ]\n" );++ for ( seg = segments; seg < limit; seg++ )+ {+ printf ( " [ %5d | %5.2g | %5s | %4d | %5d | %5d | %5d | %s ]\n",+ seg - segments,+ dimension == AF_DIMENSION_HORZ ? (int)seg->first->ox / 64.0+ : (int)seg->first->oy / 64.0,+ af_dir_str( (AF_Direction)seg->dir ),+ AF_INDEX_NUM( seg->link, segments ),+ AF_INDEX_NUM( seg->serif, segments ),+ seg->height,+ seg->height - ( seg->max_coord - seg->min_coord ),+ af_edge_flags_to_string( seg->flags ) );+ }+ printf( "\n" );+ }+ }+++ void+ af_glyph_hints_dump_edges( AF_GlyphHints hints )+ {+ FT_Int dimension;+++ for ( dimension = 1; dimension >= 0; dimension-- )+ {+ AF_AxisHints axis = &hints->axis[dimension];+ AF_Edge edges = axis->edges;+ AF_Edge limit = edges + axis->num_edges;+ AF_Edge edge;+++ /*+ * note: AF_DIMENSION_HORZ corresponds to _vertical_ edges+ * since they have constant a X coordinate.+ */+ printf ( "Table of %s edges:\n",+ dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" );+ printf ( " [ index | pos | dir | link |"+ " serif | blue | opos | pos | flags ]\n" );++ for ( edge = edges; edge < limit; edge++ )+ {+ printf ( " [ %5d | %5.2g | %5s | %4d |"+ " %5d | %c | %5.2f | %5.2f | %s ]\n",+ 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 ),+ edge->blue_edge ? 'y' : 'n',+ edge->opos / 64.0,+ edge->pos / 64.0,+ af_edge_flags_to_string( edge->flags ) );+ }+ printf( "\n" );+ }+ }++#else /* !AF_DEBUG */++ /* these empty stubs are only used to link the `ftgrid' test program */+ /* when debugging is disabled */++ void+ af_glyph_hints_dump_points( AF_GlyphHints hints )+ {+ FT_UNUSED( hints );+ }+++ void+ af_glyph_hints_dump_segments( AF_GlyphHints hints )+ {+ FT_UNUSED( hints );+ }+++ void+ af_glyph_hints_dump_edges( AF_GlyphHints hints )+ {+ FT_UNUSED( hints );+ }++#endif /* !AF_DEBUG */+++ /* compute the direction value of a given vector */+ FT_LOCAL_DEF( AF_Direction )+ af_direction_compute( FT_Pos dx,+ FT_Pos dy )+ {+ FT_Pos ll, ss; /* long and short arm lengths */+ AF_Direction dir; /* candidate direction */+++ if ( dy >= dx )+ {+ if ( dy >= -dx )+ {+ dir = AF_DIR_UP;+ ll = dy;+ ss = dx;+ }+ else+ {+ dir = AF_DIR_LEFT;+ ll = -dx;+ ss = dy;+ }+ }+ else /* dy < dx */+ {+ if ( dy >= -dx )+ {+ dir = AF_DIR_RIGHT;+ ll = dx;+ ss = dy;+ }+ else+ {+ dir = AF_DIR_DOWN;+ ll = dy;+ ss = dx;+ }+ }++ ss *= 14;+ if ( FT_ABS( ll ) <= FT_ABS( ss ) )+ dir = AF_DIR_NONE;++ return dir;+ }+++ FT_LOCAL_DEF( void )+ af_glyph_hints_init( AF_GlyphHints hints,+ FT_Memory memory )+ {+ FT_ZERO( hints );+ hints->memory = memory;+ }+++ FT_LOCAL_DEF( void )+ af_glyph_hints_done( AF_GlyphHints hints )+ {+ if ( hints && hints->memory )+ {+ FT_Memory memory = hints->memory;+ int dim;+++ /*+ * note that we don't need to free the segment and edge+ * buffers, since they are really within the hints->points array+ */+ for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )+ {+ AF_AxisHints axis = &hints->axis[dim];+++ axis->num_segments = 0;+ axis->max_segments = 0;+ FT_FREE( axis->segments );++ axis->num_edges = 0;+ axis->max_edges = 0;+ FT_FREE( axis->edges );+ }++ FT_FREE( hints->contours );+ hints->max_contours = 0;+ hints->num_contours = 0;++ FT_FREE( hints->points );+ hints->num_points = 0;+ hints->max_points = 0;++ hints->memory = NULL;+ }+ }+++ FT_LOCAL_DEF( void )+ af_glyph_hints_rescale( AF_GlyphHints hints,+ AF_ScriptMetrics metrics )+ {+ hints->metrics = metrics;+ hints->scaler_flags = metrics->scaler.flags;+ }+++ FT_LOCAL_DEF( FT_Error )+ af_glyph_hints_reload( AF_GlyphHints hints,+ FT_Outline* outline )+ {+ FT_Error error = AF_Err_Ok;+ AF_Point points;+ FT_UInt old_max, new_max;+ FT_Fixed x_scale = hints->x_scale;+ FT_Fixed y_scale = hints->y_scale;+ FT_Pos x_delta = hints->x_delta;+ FT_Pos y_delta = hints->y_delta;+ FT_Memory memory = hints->memory;+++ hints->num_points = 0;+ hints->num_contours = 0;++ hints->axis[0].num_segments = 0;+ hints->axis[0].num_edges = 0;+ hints->axis[1].num_segments = 0;+ hints->axis[1].num_edges = 0;++ /* first of all, reallocate the contours array when necessary */+ new_max = (FT_UInt)outline->n_contours;+ old_max = hints->max_contours;+ if ( new_max > old_max )+ {+ new_max = ( new_max + 3 ) & ~3;++ if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) )+ goto Exit;++ hints->max_contours = new_max;+ }++ /*+ * then reallocate the points arrays if necessary --+ * note that we reserve two additional point positions, used to+ * hint metrics appropriately+ */+ new_max = (FT_UInt)( outline->n_points + 2 );+ old_max = hints->max_points;+ if ( new_max > old_max )+ {+ new_max = ( new_max + 2 + 7 ) & ~7;++ if ( FT_RENEW_ARRAY( hints->points, old_max, new_max ) )+ goto Exit;++ hints->max_points = new_max;+ }++ hints->num_points = outline->n_points;+ hints->num_contours = outline->n_contours;++ /* We can't rely on the value of `FT_Outline.flags' to know the fill */+ /* direction used for a glyph, given that some fonts are broken (e.g., */+ /* the Arphic ones). We thus recompute it each time we need to. */+ /* */+ hints->axis[AF_DIMENSION_HORZ].major_dir = AF_DIR_UP;+ hints->axis[AF_DIMENSION_VERT].major_dir = AF_DIR_LEFT;++ if ( FT_Outline_Get_Orientation( outline ) == FT_ORIENTATION_POSTSCRIPT )+ {+ hints->axis[AF_DIMENSION_HORZ].major_dir = AF_DIR_DOWN;+ hints->axis[AF_DIMENSION_VERT].major_dir = AF_DIR_RIGHT;+ }++ hints->x_scale = x_scale;+ hints->y_scale = y_scale;+ hints->x_delta = x_delta;+ hints->y_delta = y_delta;++ hints->xmin_delta = 0;+ hints->xmax_delta = 0;++ points = hints->points;+ if ( hints->num_points == 0 )+ goto Exit;++ {+ AF_Point point;+ AF_Point point_limit = points + hints->num_points;+++ /* compute coordinates & Bezier flags, next and prev */+ {+ FT_Vector* vec = outline->points;+ char* tag = outline->tags;+ AF_Point end = points + outline->contours[0];+ AF_Point prev = end;+ FT_Int contour_index = 0;+++ for ( point = points; point < point_limit; point++, vec++, tag++ )+ {+ point->fx = (FT_Short)vec->x;+ point->fy = (FT_Short)vec->y;+ point->ox = point->x = FT_MulFix( vec->x, x_scale ) + x_delta;+ point->oy = point->y = FT_MulFix( vec->y, y_scale ) + y_delta;++ switch ( FT_CURVE_TAG( *tag ) )+ {+ case FT_CURVE_TAG_CONIC:+ point->flags = AF_FLAG_CONIC;+ break;+ case FT_CURVE_TAG_CUBIC:+ point->flags = AF_FLAG_CUBIC;+ break;+ default:+ point->flags = 0;+ }++ point->prev = prev;+ prev->next = point;+ prev = point;++ if ( point == end )+ {+ if ( ++contour_index < outline->n_contours )+ {+ end = points + outline->contours[contour_index];+ prev = end;+ }+ }+ }+ }++ /* set-up the contours array */+ {+ AF_Point* contour = hints->contours;+ AF_Point* contour_limit = contour + hints->num_contours;+ short* end = outline->contours;+ short idx = 0;+++ for ( ; contour < contour_limit; contour++, end++ )+ {+ contour[0] = points + idx;+ idx = (short)( end[0] + 1 );+ }+ }++ /* compute directions of in & out vectors */+ {+ AF_Point first = points;+ AF_Point prev = NULL;+ FT_Pos in_x = 0;+ FT_Pos in_y = 0;+ AF_Direction in_dir = AF_DIR_NONE;+++ for ( point = points; point < point_limit; point++ )+ {+ AF_Point next;+ FT_Pos out_x, out_y;+++ if ( point == first )+ {+ prev = first->prev;+ in_x = first->fx - prev->fx;+ in_y = first->fy - prev->fy;+ in_dir = af_direction_compute( in_x, in_y );+ first = prev + 1;+ }++ point->in_dir = (FT_Char)in_dir;++ next = point->next;+ out_x = next->fx - point->fx;+ out_y = next->fy - point->fy;++ in_dir = af_direction_compute( out_x, out_y );+ point->out_dir = (FT_Char)in_dir;++ if ( point->flags & ( AF_FLAG_CONIC | AF_FLAG_CUBIC ) )+ {+ Is_Weak_Point:+ point->flags |= AF_FLAG_WEAK_INTERPOLATION;+ }+ else if ( point->out_dir == point->in_dir )+ {+ if ( point->out_dir != AF_DIR_NONE )+ goto Is_Weak_Point;++ if ( ft_corner_is_flat( in_x, in_y, out_x, out_y ) )+ goto Is_Weak_Point;+ }+ else if ( point->in_dir == -point->out_dir )+ goto Is_Weak_Point;++ in_x = out_x;+ in_y = out_y;+ prev = point;+ }+ }+ }++ Exit:+ return error;+ }+++ FT_LOCAL_DEF( void )+ af_glyph_hints_save( AF_GlyphHints hints,+ FT_Outline* outline )+ {+ AF_Point point = hints->points;+ AF_Point limit = point + hints->num_points;+ FT_Vector* vec = outline->points;+ char* tag = outline->tags;+++ for ( ; point < limit; point++, vec++, tag++ )+ {+ vec->x = point->x;+ vec->y = point->y;++ if ( point->flags & AF_FLAG_CONIC )+ tag[0] = FT_CURVE_TAG_CONIC;+ else if ( point->flags & AF_FLAG_CUBIC )+ tag[0] = FT_CURVE_TAG_CUBIC;+ else+ tag[0] = FT_CURVE_TAG_ON;+ }+ }+++ /****************************************************************+ *+ * EDGE POINT GRID-FITTING+ *+ ****************************************************************/+++ FT_LOCAL_DEF( void )+ af_glyph_hints_align_edge_points( AF_GlyphHints hints,+ AF_Dimension dim )+ {+ AF_AxisHints axis = & hints->axis[dim];+ AF_Segment segments = axis->segments;+ AF_Segment segment_limit = segments + axis->num_segments;+ AF_Segment seg;+++ if ( dim == AF_DIMENSION_HORZ )+ {+ for ( seg = segments; seg < segment_limit; seg++ )+ {+ AF_Edge edge = seg->edge;+ AF_Point point, first, last;+++ if ( edge == NULL )+ continue;++ first = seg->first;+ last = seg->last;+ point = first;+ for (;;)+ {+ point->x = edge->pos;+ point->flags |= AF_FLAG_TOUCH_X;++ if ( point == last )+ break;++ point = point->next;++ }+ }+ }+ else+ {+ for ( seg = segments; seg < segment_limit; seg++ )+ {+ AF_Edge edge = seg->edge;+ AF_Point point, first, last;+++ if ( edge == NULL )+ continue;++ first = seg->first;+ last = seg->last;+ point = first;+ for (;;)+ {+ point->y = edge->pos;+ point->flags |= AF_FLAG_TOUCH_Y;++ if ( point == last )+ break;++ point = point->next;+ }+ }+ }+ }+++ /****************************************************************+ *+ * STRONG POINT INTERPOLATION+ *+ ****************************************************************/+++ /* hint the strong points -- this is equivalent to the TrueType `IP' */+ /* hinting instruction */++ FT_LOCAL_DEF( void )+ af_glyph_hints_align_strong_points( AF_GlyphHints hints,+ AF_Dimension dim )+ {+ AF_Point points = hints->points;+ AF_Point point_limit = points + hints->num_points;+ AF_AxisHints axis = &hints->axis[dim];+ AF_Edge edges = axis->edges;+ AF_Edge edge_limit = edges + axis->num_edges;+ AF_Flags touch_flag;+++ if ( dim == AF_DIMENSION_HORZ )+ touch_flag = AF_FLAG_TOUCH_X;+ else+ touch_flag = AF_FLAG_TOUCH_Y;++ if ( edges < edge_limit )+ {+ AF_Point point;+ AF_Edge edge;+++ for ( point = points; point < point_limit; point++ )+ {+ FT_Pos u, ou, fu; /* point position */+ FT_Pos delta;+++ if ( point->flags & touch_flag )+ continue;++ /* if this point is candidate to weak interpolation, we */+ /* interpolate it after all strong points have been processed */++ if ( ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) &&+ !( point->flags & AF_FLAG_INFLECTION ) )+ continue;++ if ( dim == AF_DIMENSION_VERT )+ {+ u = point->fy;+ ou = point->oy;+ }+ else+ {+ u = point->fx;+ ou = point->ox;+ }++ fu = u;++ /* is the point before the first edge? */+ edge = edges;+ delta = edge->fpos - u;+ if ( delta >= 0 )+ {+ u = edge->pos - ( edge->opos - ou );+ goto Store_Point;+ }++ /* is the point after the last edge? */+ edge = edge_limit - 1;+ delta = u - edge->fpos;+ if ( delta >= 0 )+ {+ u = edge->pos + ( ou - edge->opos );+ goto Store_Point;+ }++ {+ FT_PtrDist min, max, mid;+ FT_Pos fpos;+++ /* find enclosing edges */+ min = 0;+ max = edge_limit - edges;++#if 1+ /* for small edge counts, a linear search is better */+ if ( max <= 8 )+ {+ FT_PtrDist nn;++ for ( nn = 0; nn < max; nn++ )+ if ( edges[nn].fpos >= u )+ break;++ if ( edges[nn].fpos == u )+ {+ u = edges[nn].pos;+ goto Store_Point;+ }+ min = nn;+ }+ else+#endif+ while ( min < max )+ {+ mid = ( max + min ) >> 1;+ edge = edges + mid;+ fpos = edge->fpos;++ if ( u < fpos )+ max = mid;+ else if ( u > fpos )+ min = mid + 1;+ else+ {+ /* we are on the edge */+ u = edge->pos;+ goto Store_Point;+ }+ }++ {+ AF_Edge before = edges + min - 1;+ AF_Edge after = edges + min + 0;+++ /* assert( before && after && before != after ) */+ if ( before->scale == 0 )+ before->scale = FT_DivFix( after->pos - before->pos,+ after->fpos - before->fpos );++ u = before->pos + FT_MulFix( fu - before->fpos,+ before->scale );+ }+ }++ Store_Point:+ /* save the point position */+ if ( dim == AF_DIMENSION_HORZ )+ point->x = u;+ else+ point->y = u;++ point->flags |= touch_flag;+ }+ }+ }+++ /****************************************************************+ *+ * WEAK POINT INTERPOLATION+ *+ ****************************************************************/+++ static void+ af_iup_shift( AF_Point p1,+ AF_Point p2,+ AF_Point ref )+ {+ AF_Point p;+ FT_Pos delta = ref->u - ref->v;++ if ( delta == 0 )+ return;++ for ( p = p1; p < ref; p++ )+ p->u = p->v + delta;++ for ( p = ref + 1; p <= p2; p++ )+ p->u = p->v + delta;+ }+++ static void+ af_iup_interp( AF_Point p1,+ AF_Point p2,+ AF_Point ref1,+ AF_Point ref2 )+ {+ AF_Point p;+ FT_Pos u;+ FT_Pos v1 = ref1->v;+ FT_Pos v2 = ref2->v;+ FT_Pos d1 = ref1->u - v1;+ FT_Pos d2 = ref2->u - v2;+++ if ( p1 > p2 )+ return;++ if ( v1 == v2 )+ {+ for ( p = p1; p <= p2; p++ )+ {+ u = p->v;++ if ( u <= v1 )+ u += d1;+ else+ u += d2;++ p->u = u;+ }+ return;+ }++ if ( v1 < v2 )+ {+ for ( p = p1; p <= p2; p++ )+ {+ u = p->v;++ if ( u <= v1 )+ u += d1;+ else if ( u >= v2 )+ u += d2;+ else+ u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );++ p->u = u;+ }+ }+ else+ {+ for ( p = p1; p <= p2; p++ )+ {+ u = p->v;++ if ( u <= v2 )+ u += d2;+ else if ( u >= v1 )+ u += d1;+ else+ u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );++ p->u = u;+ }+ }+ }+++ FT_LOCAL_DEF( void )+ af_glyph_hints_align_weak_points( AF_GlyphHints hints,+ AF_Dimension dim )+ {+ AF_Point points = hints->points;+ AF_Point point_limit = points + hints->num_points;+ AF_Point* contour = hints->contours;+ AF_Point* contour_limit = contour + hints->num_contours;+ AF_Flags touch_flag;+ AF_Point point;+ AF_Point end_point;+ AF_Point first_point;+++ /* PASS 1: Move segment points to edge positions */++ if ( dim == AF_DIMENSION_HORZ )+ {+ touch_flag = AF_FLAG_TOUCH_X;++ for ( point = points; point < point_limit; point++ )+ {+ point->u = point->x;+ point->v = point->ox;+ }+ }+ else+ {+ touch_flag = AF_FLAG_TOUCH_Y;++ for ( point = points; point < point_limit; point++ )+ {+ point->u = point->y;+ point->v = point->oy;+ }+ }++ point = points;++ for ( ; contour < contour_limit; contour++ )+ {+ AF_Point first_touched, last_touched;+++ point = *contour;+ end_point = point->prev;+ first_point = point;++ /* find first touched point */+ for (;;)+ {+ if ( point > end_point ) /* no touched point in contour */+ goto NextContour;++ if ( point->flags & touch_flag )+ break;++ point++;+ }++ first_touched = point;+ last_touched = point;++ for (;;)+ {+ FT_ASSERT( point <= end_point &&+ ( point->flags & touch_flag ) != 0 );++ /* skip any touched neighbhours */+ while ( point < end_point && ( point[1].flags & touch_flag ) != 0 )+ point++;++ last_touched = point;++ /* find the next touched point, if any */+ point ++;+ for (;;)+ {+ if ( point > end_point )+ goto EndContour;++ if ( ( point->flags & touch_flag ) != 0 )+ break;++ point++;+ }++ /* interpolate between last_touched and point */+ af_iup_interp( last_touched + 1, point - 1,+ last_touched, point );+ }++ EndContour:+ /* special case: only one point was touched */+ if ( last_touched == first_touched )+ {+ af_iup_shift( first_point, end_point, first_touched );+ }+ else /* interpolate the last part */+ {+ if ( last_touched < end_point )+ af_iup_interp( last_touched + 1, end_point,+ last_touched, first_touched );++ if ( first_touched > points )+ af_iup_interp( first_point, first_touched - 1,+ last_touched, first_touched );+ }++ NextContour:+ ;+ }++ /* now save the interpolated values back to x/y */+ if ( dim == AF_DIMENSION_HORZ )+ {+ for ( point = points; point < point_limit; point++ )+ point->x = point->u;+ }+ else+ {+ for ( point = points; point < point_limit; point++ )+ point->y = point->u;+ }+ }+++#ifdef AF_USE_WARPER++ FT_LOCAL_DEF( void )+ af_glyph_hints_scale_dim( AF_GlyphHints hints,+ AF_Dimension dim,+ FT_Fixed scale,+ FT_Pos delta )+ {+ AF_Point points = hints->points;+ AF_Point points_limit = points + hints->num_points;+ AF_Point point;+++ if ( dim == AF_DIMENSION_HORZ )+ {+ for ( point = points; point < points_limit; point++ )+ point->x = FT_MulFix( point->fx, scale ) + delta;+ }+ else+ {+ for ( point = points; point < points_limit; point++ )+ point->y = FT_MulFix( point->fy, scale ) + delta;+ }+ }++#endif /* AF_USE_WARPER */++/* END */
+ src/autofit/afhints.h view
@@ -0,0 +1,332 @@+/***************************************************************************/+/* */+/* afhints.h */+/* */+/* Auto-fitter hinting routines (specification). */+/* */+/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2010 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#ifndef __AFHINTS_H__+#define __AFHINTS_H__++#include "aftypes.h"++#define xxAF_SORT_SEGMENTS++FT_BEGIN_HEADER++ /*+ * The definition of outline glyph hints. These are shared by all+ * script analysis routines (until now).+ */++ typedef enum AF_Dimension_+ {+ AF_DIMENSION_HORZ = 0, /* x coordinates, */+ /* i.e., vertical segments & edges */+ AF_DIMENSION_VERT = 1, /* y coordinates, */+ /* i.e., horizontal segments & edges */++ AF_DIMENSION_MAX /* do not remove */++ } AF_Dimension;+++ /* hint directions -- the values are computed so that two vectors are */+ /* in opposite directions iff `dir1 + dir2 == 0' */+ typedef enum AF_Direction_+ {+ AF_DIR_NONE = 4,+ AF_DIR_RIGHT = 1,+ AF_DIR_LEFT = -1,+ AF_DIR_UP = 2,+ AF_DIR_DOWN = -2++ } AF_Direction;+++ /* point hint flags */+ typedef enum AF_Flags_+ {+ AF_FLAG_NONE = 0,++ /* point type flags */+ AF_FLAG_CONIC = 1 << 0,+ AF_FLAG_CUBIC = 1 << 1,+ AF_FLAG_CONTROL = AF_FLAG_CONIC | AF_FLAG_CUBIC,++ /* point extremum flags */+ AF_FLAG_EXTREMA_X = 1 << 2,+ AF_FLAG_EXTREMA_Y = 1 << 3,++ /* point roundness flags */+ AF_FLAG_ROUND_X = 1 << 4,+ AF_FLAG_ROUND_Y = 1 << 5,++ /* point touch flags */+ AF_FLAG_TOUCH_X = 1 << 6,+ AF_FLAG_TOUCH_Y = 1 << 7,++ /* candidates for weak interpolation have this flag set */+ AF_FLAG_WEAK_INTERPOLATION = 1 << 8,++ /* all inflection points in the outline have this flag set */+ AF_FLAG_INFLECTION = 1 << 9++ } AF_Flags;+++ /* edge hint flags */+ typedef enum AF_Edge_Flags_+ {+ AF_EDGE_NORMAL = 0,+ AF_EDGE_ROUND = 1 << 0,+ AF_EDGE_SERIF = 1 << 1,+ AF_EDGE_DONE = 1 << 2++ } AF_Edge_Flags;+++ typedef struct AF_PointRec_* AF_Point;+ typedef struct AF_SegmentRec_* AF_Segment;+ typedef struct AF_EdgeRec_* AF_Edge;+++ typedef struct AF_PointRec_+ {+ FT_UShort flags; /* point flags used by hinter */+ FT_Char in_dir; /* direction of inwards vector */+ FT_Char out_dir; /* direction of outwards vector */++ FT_Pos ox, oy; /* original, scaled position */+ FT_Short fx, fy; /* original, unscaled position (font units) */+ FT_Pos x, y; /* current position */+ FT_Pos u, v; /* current (x,y) or (y,x) depending on context */++ AF_Point next; /* next point in contour */+ AF_Point prev; /* previous point in contour */++ } AF_PointRec;+++ typedef struct AF_SegmentRec_+ {+ FT_Byte flags; /* edge/segment flags for this segment */+ FT_Char dir; /* segment direction */+ FT_Short pos; /* position of segment */+ FT_Short min_coord; /* minimum coordinate of segment */+ FT_Short max_coord; /* maximum coordinate of segment */+ FT_Short height; /* the hinted segment height */++ AF_Edge edge; /* the segment's parent edge */+ AF_Segment edge_next; /* link to next segment in parent edge */++ AF_Segment link; /* (stem) link segment */+ AF_Segment serif; /* primary segment for serifs */+ FT_Pos num_linked; /* number of linked segments */+ FT_Pos score; /* used during stem matching */+ FT_Pos len; /* used during stem matching */++ AF_Point first; /* first point in edge segment */+ AF_Point last; /* last point in edge segment */+ AF_Point* contour; /* ptr to first point of segment's contour */++ } AF_SegmentRec;+++ typedef struct AF_EdgeRec_+ {+ FT_Short fpos; /* original, unscaled position (font units) */+ FT_Pos opos; /* original, scaled position */+ FT_Pos pos; /* current position */++ FT_Byte flags; /* edge flags */+ FT_Char dir; /* edge direction */+ FT_Fixed scale; /* used to speed up interpolation between edges */+ AF_Width blue_edge; /* non-NULL if this is a blue edge */++ AF_Edge link;+ AF_Edge serif;+ FT_Short num_linked;++ FT_Int score;++ AF_Segment first;+ AF_Segment last;++ } AF_EdgeRec;+++ typedef struct AF_AxisHintsRec_+ {+ FT_Int num_segments;+ FT_Int max_segments;+ AF_Segment segments;+#ifdef AF_SORT_SEGMENTS+ FT_Int mid_segments;+#endif++ FT_Int num_edges;+ FT_Int max_edges;+ AF_Edge edges;++ AF_Direction major_dir;++ } AF_AxisHintsRec, *AF_AxisHints;+++ typedef struct AF_GlyphHintsRec_+ {+ FT_Memory memory;++ FT_Fixed x_scale;+ FT_Pos x_delta;++ FT_Fixed y_scale;+ FT_Pos y_delta;++ FT_Pos edge_distance_threshold;++ FT_Int max_points;+ FT_Int num_points;+ AF_Point points;++ FT_Int max_contours;+ FT_Int num_contours;+ AF_Point* contours;++ AF_AxisHintsRec axis[AF_DIMENSION_MAX];++ FT_UInt32 scaler_flags; /* copy of scaler flags */+ FT_UInt32 other_flags; /* free for script-specific */+ /* implementations */+ AF_ScriptMetrics metrics;++ FT_Pos xmin_delta; /* used for warping */+ FT_Pos xmax_delta;+ + } AF_GlyphHintsRec;+++#define AF_HINTS_TEST_SCALER( h, f ) ( (h)->scaler_flags & (f) )+#define AF_HINTS_TEST_OTHER( h, f ) ( (h)->other_flags & (f) )+++#ifdef AF_DEBUG++#define AF_HINTS_DO_HORIZONTAL( h ) \+ ( !_af_debug_disable_horz_hints && \+ !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_HORIZONTAL ) )++#define AF_HINTS_DO_VERTICAL( h ) \+ ( !_af_debug_disable_vert_hints && \+ !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_VERTICAL ) )++#define AF_HINTS_DO_ADVANCE( h ) \+ !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_ADVANCE )++#define AF_HINTS_DO_BLUES( h ) ( !_af_debug_disable_blue_hints )++#else /* !AF_DEBUG */++#define AF_HINTS_DO_HORIZONTAL( h ) \+ !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_HORIZONTAL )++#define AF_HINTS_DO_VERTICAL( h ) \+ !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_VERTICAL )++#define AF_HINTS_DO_ADVANCE( h ) \+ !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_ADVANCE )++#define AF_HINTS_DO_BLUES( h ) 1++#endif /* !AF_DEBUG */+++ FT_LOCAL( AF_Direction )+ af_direction_compute( FT_Pos dx,+ FT_Pos dy );+++ FT_LOCAL( FT_Error )+ af_axis_hints_new_segment( AF_AxisHints axis,+ FT_Memory memory,+ AF_Segment *asegment );++ FT_LOCAL( FT_Error)+ af_axis_hints_new_edge( AF_AxisHints axis,+ FT_Int fpos,+ AF_Direction dir,+ FT_Memory memory,+ AF_Edge *edge );++ FT_LOCAL( void )+ af_glyph_hints_init( AF_GlyphHints hints,+ FT_Memory memory );++++ /*+ * recompute all AF_Point in a AF_GlyphHints from the definitions+ * in a source outline+ */+ FT_LOCAL( void )+ af_glyph_hints_rescale( AF_GlyphHints hints,+ AF_ScriptMetrics metrics );++ FT_LOCAL( FT_Error )+ af_glyph_hints_reload( AF_GlyphHints hints,+ FT_Outline* outline );++ FT_LOCAL( void )+ af_glyph_hints_save( AF_GlyphHints hints,+ FT_Outline* outline );++ FT_LOCAL( void )+ af_glyph_hints_align_edge_points( AF_GlyphHints hints,+ AF_Dimension dim );++ FT_LOCAL( void )+ af_glyph_hints_align_strong_points( AF_GlyphHints hints,+ AF_Dimension dim );++ FT_LOCAL( void )+ af_glyph_hints_align_weak_points( AF_GlyphHints hints,+ AF_Dimension dim );++#ifdef AF_USE_WARPER+ FT_LOCAL( void )+ af_glyph_hints_scale_dim( AF_GlyphHints hints,+ AF_Dimension dim,+ FT_Fixed scale,+ FT_Pos delta );+#endif++ FT_LOCAL( void )+ af_glyph_hints_done( AF_GlyphHints hints );++/* */++#define AF_SEGMENT_LEN( seg ) ( (seg)->max_coord - (seg)->min_coord )++#define AF_SEGMENT_DIST( seg1, seg2 ) ( ( (seg1)->pos > (seg2)->pos ) \+ ? (seg1)->pos - (seg2)->pos \+ : (seg2)->pos - (seg1)->pos )+++FT_END_HEADER++#endif /* __AFHINTS_H__ */+++/* END */
+ src/autofit/afindic.c view
@@ -0,0 +1,130 @@+/***************************************************************************/+/* */+/* afindic.c */+/* */+/* Auto-fitter hinting routines for Indic scripts (body). */+/* */+/* Copyright 2007 by */+/* Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#include "aftypes.h"+#include "aflatin.h"+++#ifdef AF_CONFIG_OPTION_INDIC++#include "afindic.h"+#include "aferrors.h"+#include "afcjk.h"+++#ifdef AF_USE_WARPER+#include "afwarp.h"+#endif+++ static FT_Error+ af_indic_metrics_init( AF_LatinMetrics metrics,+ FT_Face face )+ {+ /* use CJK routines */+ return af_cjk_metrics_init( metrics, face );+ }+++ static void+ af_indic_metrics_scale( AF_LatinMetrics metrics,+ AF_Scaler scaler )+ {+ /* use CJK routines */+ af_cjk_metrics_scale( metrics, scaler );+ }+++ static FT_Error+ af_indic_hints_init( AF_GlyphHints hints,+ AF_LatinMetrics metrics )+ {+ /* use CJK routines */+ return af_cjk_hints_init( hints, metrics );+ }+++ static FT_Error+ af_indic_hints_apply( AF_GlyphHints hints,+ FT_Outline* outline,+ AF_LatinMetrics metrics)+ {+ /* use CJK routines */+ return af_cjk_hints_apply( hints, outline, metrics );+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** I N D I C S C R I P T C L A S S *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+++ static const AF_Script_UniRangeRec af_indic_uniranges[] =+ {+#if 0+ AF_UNIRANGE_REC( 0x0100UL, 0xFFFFUL ), /* why this? */+#endif+ AF_UNIRANGE_REC( 0x0900UL, 0x0DFFUL), /* Indic Range */+ AF_UNIRANGE_REC( 0UL, 0UL)+ };+++ AF_DEFINE_SCRIPT_CLASS(af_indic_script_class,+ AF_SCRIPT_INDIC,+ af_indic_uniranges,++ sizeof( AF_LatinMetricsRec ),++ (AF_Script_InitMetricsFunc) af_indic_metrics_init,+ (AF_Script_ScaleMetricsFunc)af_indic_metrics_scale,+ (AF_Script_DoneMetricsFunc) NULL,++ (AF_Script_InitHintsFunc) af_indic_hints_init,+ (AF_Script_ApplyHintsFunc) af_indic_hints_apply+ )++#else /* !AF_CONFIG_OPTION_INDIC */++ static const AF_Script_UniRangeRec af_indic_uniranges[] =+ {+ { 0, 0 }+ };+++ AF_DEFINE_SCRIPT_CLASS(af_indic_script_class,+ AF_SCRIPT_INDIC,+ af_indic_uniranges,++ sizeof( AF_LatinMetricsRec ),++ (AF_Script_InitMetricsFunc) NULL,+ (AF_Script_ScaleMetricsFunc)NULL,+ (AF_Script_DoneMetricsFunc) NULL,++ (AF_Script_InitHintsFunc) NULL,+ (AF_Script_ApplyHintsFunc) NULL+ )++#endif /* !AF_CONFIG_OPTION_INDIC */+++/* END */
+ src/autofit/afindic.h view
@@ -0,0 +1,40 @@+/***************************************************************************/+/* */+/* afindic.h */+/* */+/* Auto-fitter hinting routines for Indic scripts (specification). */+/* */+/* Copyright 2007 by */+/* Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#ifndef __AFINDIC_H__+#define __AFINDIC_H__++#include "afhints.h"+++FT_BEGIN_HEADER+++ /* the Indic-specific script class */++ AF_DECLARE_SCRIPT_CLASS(af_indic_script_class)+++/* */++FT_END_HEADER++#endif /* __AFINDIC_H__ */+++/* END */
+ src/autofit/aflatin.c view
@@ -0,0 +1,2224 @@+/***************************************************************************/+/* */+/* aflatin.c */+/* */+/* Auto-fitter hinting routines for latin script (body). */+/* */+/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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_ADVANCES_H++#include "aflatin.h"+#include "aferrors.h"+++#ifdef AF_USE_WARPER+#include "afwarp.h"+#endif+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** L A T I N G L O B A L M E T R I C S *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ FT_LOCAL_DEF( void )+ af_latin_metrics_init_widths( AF_LatinMetrics metrics,+ FT_Face face,+ FT_ULong charcode )+ {+ /* scan the array of segments in each direction */+ AF_GlyphHintsRec hints[1];+++ af_glyph_hints_init( hints, face->memory );++ metrics->axis[AF_DIMENSION_HORZ].width_count = 0;+ metrics->axis[AF_DIMENSION_VERT].width_count = 0;++ {+ FT_Error error;+ FT_UInt glyph_index;+ int dim;+ AF_LatinMetricsRec dummy[1];+ AF_Scaler scaler = &dummy->root.scaler;+++ glyph_index = FT_Get_Char_Index( face, charcode );+ if ( glyph_index == 0 )+ goto Exit;++ error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );+ if ( error || face->glyph->outline.n_points <= 0 )+ goto Exit;++ FT_ZERO( dummy );++ dummy->units_per_em = metrics->units_per_em;+ scaler->x_scale = scaler->y_scale = 0x10000L;+ scaler->x_delta = scaler->y_delta = 0;+ scaler->face = face;+ scaler->render_mode = FT_RENDER_MODE_NORMAL;+ scaler->flags = 0;++ af_glyph_hints_rescale( hints, (AF_ScriptMetrics)dummy );++ error = af_glyph_hints_reload( hints, &face->glyph->outline );+ if ( error )+ goto Exit;++ for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )+ {+ AF_LatinAxis axis = &metrics->axis[dim];+ AF_AxisHints axhints = &hints->axis[dim];+ AF_Segment seg, limit, link;+ FT_UInt num_widths = 0;+++ error = af_latin_hints_compute_segments( hints,+ (AF_Dimension)dim );+ if ( error )+ goto Exit;++ af_latin_hints_link_segments( hints,+ (AF_Dimension)dim );++ seg = axhints->segments;+ limit = seg + axhints->num_segments;++ for ( ; seg < limit; seg++ )+ {+ link = seg->link;++ /* we only consider stem segments there! */+ if ( link && link->link == seg && link > seg )+ {+ FT_Pos dist;+++ dist = seg->pos - link->pos;+ if ( dist < 0 )+ dist = -dist;++ if ( num_widths < AF_LATIN_MAX_WIDTHS )+ axis->widths[ num_widths++ ].org = dist;+ }+ }++ af_sort_widths( num_widths, axis->widths );+ axis->width_count = num_widths;+ }++ Exit:+ for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )+ {+ AF_LatinAxis axis = &metrics->axis[dim];+ FT_Pos stdw;+++ stdw = ( axis->width_count > 0 )+ ? axis->widths[0].org+ : AF_LATIN_CONSTANT( metrics, 50 );++ /* let's try 20% of the smallest width */+ axis->edge_distance_threshold = stdw / 5;+ axis->standard_width = stdw;+ axis->extra_light = 0;+ }+ }++ af_glyph_hints_done( hints );+ }++++#define AF_LATIN_MAX_TEST_CHARACTERS 12+++ static const char af_latin_blue_chars[AF_LATIN_MAX_BLUES]+ [AF_LATIN_MAX_TEST_CHARACTERS + 1] =+ {+ "THEZOCQS",+ "HEZLOCUS",+ "fijkdbh",+ "xzroesc",+ "xzroesc",+ "pqgjy"+ };+++ static void+ af_latin_metrics_init_blues( AF_LatinMetrics metrics,+ FT_Face face )+ {+ FT_Pos flats [AF_LATIN_MAX_TEST_CHARACTERS];+ FT_Pos rounds[AF_LATIN_MAX_TEST_CHARACTERS];+ FT_Int num_flats;+ FT_Int num_rounds;+ FT_Int bb;+ AF_LatinBlue blue;+ FT_Error error;+ AF_LatinAxis axis = &metrics->axis[AF_DIMENSION_VERT];+ FT_GlyphSlot glyph = face->glyph;+++ /* we compute the blues simply by loading each character from the */+ /* 'af_latin_blue_chars[blues]' string, then compute its top-most or */+ /* bottom-most points (depending on `AF_IS_TOP_BLUE') */++ AF_LOG(( "blue zones computation\n" ));+ AF_LOG(( "------------------------------------------------\n" ));++ for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )+ {+ const char* p = af_latin_blue_chars[bb];+ const char* limit = p + AF_LATIN_MAX_TEST_CHARACTERS;+ FT_Pos* blue_ref;+ FT_Pos* blue_shoot;+++ AF_LOG(( "blue %3d: ", bb ));++ num_flats = 0;+ num_rounds = 0;++ for ( ; p < limit && *p; p++ )+ {+ FT_UInt glyph_index;+ FT_Pos best_y; /* same as points.y */+ FT_Int best_point, best_first, best_last;+ FT_Vector* points;+ FT_Bool round = 0;+++ AF_LOG(( "'%c'", *p ));++ /* load the character in the face -- skip unknown or empty ones */+ glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p );+ if ( glyph_index == 0 )+ continue;++ error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );+ if ( error || glyph->outline.n_points <= 0 )+ continue;++ /* now compute min or max point indices and coordinates */+ points = glyph->outline.points;+ best_point = -1;+ best_y = 0; /* make compiler happy */+ best_first = 0; /* ditto */+ best_last = 0; /* ditto */++ {+ FT_Int nn;+ FT_Int first = 0;+ FT_Int last = -1;+++ for ( nn = 0; nn < glyph->outline.n_contours; first = last+1, nn++ )+ {+ FT_Int old_best_point = best_point;+ FT_Int pp;+++ last = glyph->outline.contours[nn];++ /* Avoid single-point contours since they are never rasterized. */+ /* In some fonts, they correspond to mark attachment points */+ /* which are way outside of the glyph's real outline. */+ if ( last <= first )+ continue;++ if ( AF_LATIN_IS_TOP_BLUE( bb ) )+ {+ for ( pp = first; pp <= last; pp++ )+ if ( best_point < 0 || points[pp].y > best_y )+ {+ best_point = pp;+ best_y = points[pp].y;+ }+ }+ else+ {+ for ( pp = first; pp <= last; pp++ )+ if ( best_point < 0 || points[pp].y < best_y )+ {+ best_point = pp;+ best_y = points[pp].y;+ }+ }++ if ( best_point != old_best_point )+ {+ best_first = first;+ best_last = last;+ }+ }+ AF_LOG(( "%5d", best_y ));+ }++ /* 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_Int prev, next;+ FT_Pos dist;+++ /* now look for the previous and next points that are not on the */+ /* same Y coordinate. Threshold the `closeness'... */+ prev = best_point;+ next = prev;++ do+ {+ if ( prev > best_first )+ prev--;+ else+ prev = best_last;++ dist = points[prev].y - best_y;+ if ( dist < -5 || dist > 5 )+ break;++ } while ( prev != best_point );++ do+ {+ if ( next < best_last )+ next++;+ else+ next = best_first;++ dist = points[next].y - best_y;+ if ( dist < -5 || dist > 5 )+ break;++ } while ( next != best_point );++ /* now, set the `round' flag depending on the segment's kind */+ round = FT_BOOL(+ FT_CURVE_TAG( glyph->outline.tags[prev] ) != FT_CURVE_TAG_ON ||+ FT_CURVE_TAG( glyph->outline.tags[next] ) != FT_CURVE_TAG_ON );++ AF_LOG(( "%c ", round ? 'r' : 'f' ));+ }++ if ( round )+ rounds[num_rounds++] = best_y;+ else+ flats[num_flats++] = best_y;+ }++ AF_LOG(( "\n" ));++ if ( num_flats == 0 && num_rounds == 0 )+ {+ /*+ * we couldn't find a single glyph to compute this blue zone,+ * we will simply ignore it then+ */+ AF_LOG(( "empty\n" ));+ continue;+ }++ /* we have computed the contents of the `rounds' and `flats' tables, */+ /* now determine the reference and overshoot position of the blue -- */+ /* we simply take the median value after a simple sort */+ af_sort_pos( num_rounds, rounds );+ af_sort_pos( num_flats, flats );++ blue = & axis->blues[axis->blue_count];+ blue_ref = & blue->ref.org;+ blue_shoot = & blue->shoot.org;++ axis->blue_count++;++ if ( num_flats == 0 )+ {+ *blue_ref =+ *blue_shoot = rounds[num_rounds / 2];+ }+ else if ( num_rounds == 0 )+ {+ *blue_ref =+ *blue_shoot = flats[num_flats / 2];+ }+ else+ {+ *blue_ref = flats[num_flats / 2];+ *blue_shoot = rounds[num_rounds / 2];+ }++ /* there are sometimes problems: if the overshoot position of top */+ /* zones is under its reference position, or the opposite for bottom */+ /* zones. We must thus check everything there and correct the errors */+ if ( *blue_shoot != *blue_ref )+ {+ FT_Pos ref = *blue_ref;+ FT_Pos shoot = *blue_shoot;+ FT_Bool over_ref = FT_BOOL( shoot > ref );+++ if ( AF_LATIN_IS_TOP_BLUE( bb ) ^ over_ref )+ *blue_shoot = *blue_ref = ( shoot + ref ) / 2;+ }++ blue->flags = 0;+ if ( AF_LATIN_IS_TOP_BLUE( bb ) )+ blue->flags |= AF_LATIN_BLUE_TOP;++ /*+ * The following flag is used later to adjust the y and x scales+ * in order to optimize the pixel grid alignment of the top of small+ * letters.+ */+ if ( bb == AF_LATIN_BLUE_SMALL_TOP )+ blue->flags |= AF_LATIN_BLUE_ADJUSTMENT;++ AF_LOG(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));+ }++ return;+ }+++ FT_LOCAL_DEF( void )+ 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;+++ /* check whether all ASCII digits have the same advance width; */+ /* digit `0' is 0x30 in all supported charmaps */+ for ( i = 0x30; i <= 0x39; i++ )+ {+ FT_UInt glyph_index;+++ glyph_index = FT_Get_Char_Index( face, i );+ if ( glyph_index == 0 )+ continue;++ if ( FT_Get_Advance( face, glyph_index,+ FT_LOAD_NO_SCALE |+ FT_LOAD_NO_HINTING |+ FT_LOAD_IGNORE_TRANSFORM,+ &advance ) )+ continue;++ if ( started )+ {+ if ( advance != old_advance )+ {+ same_width = 0;+ break;+ }+ }+ else+ {+ old_advance = advance;+ started = 1;+ }+ }++ metrics->root.digits_have_same_width = same_width;+ }+++ FT_LOCAL_DEF( FT_Error )+ af_latin_metrics_init( AF_LatinMetrics metrics,+ FT_Face face )+ {+ FT_Error error = AF_Err_Ok;+ FT_CharMap oldmap = face->charmap;+ FT_UInt ee;++ static const FT_Encoding latin_encodings[] =+ {+ FT_ENCODING_UNICODE,+ FT_ENCODING_APPLE_ROMAN,+ FT_ENCODING_ADOBE_STANDARD,+ FT_ENCODING_ADOBE_LATIN_1,+ FT_ENCODING_NONE /* end of list */+ };+++ metrics->units_per_em = face->units_per_EM;++ /* do we have a latin charmap in there? */+ for ( ee = 0; latin_encodings[ee] != FT_ENCODING_NONE; ee++ )+ {+ error = FT_Select_Charmap( face, latin_encodings[ee] );+ if ( !error )+ break;+ }++ if ( !error )+ {+ /* For now, compute the standard width and height from the `o'. */+ af_latin_metrics_init_widths( metrics, face, 'o' );+ af_latin_metrics_init_blues( metrics, face );+ af_latin_metrics_check_digits( metrics, face );+ }++ FT_Set_Charmap( face, oldmap );+ return AF_Err_Ok;+ }+++ static void+ af_latin_metrics_scale_dim( AF_LatinMetrics metrics,+ AF_Scaler scaler,+ AF_Dimension dim )+ {+ FT_Fixed scale;+ FT_Pos delta;+ AF_LatinAxis axis;+ FT_UInt nn;+++ if ( dim == AF_DIMENSION_HORZ )+ {+ scale = scaler->x_scale;+ delta = scaler->x_delta;+ }+ else+ {+ scale = scaler->y_scale;+ delta = scaler->y_delta;+ }++ axis = &metrics->axis[dim];++ if ( axis->org_scale == scale && axis->org_delta == delta )+ return;++ axis->org_scale = scale;+ axis->org_delta = delta;++ /*+ * correct X and Y scale to optimize the alignment of the top of small+ * letters to the pixel grid+ */+ {+ AF_LatinAxis Axis = &metrics->axis[AF_DIMENSION_VERT];+ AF_LatinBlue blue = NULL;+++ for ( nn = 0; nn < Axis->blue_count; nn++ )+ {+ if ( Axis->blues[nn].flags & AF_LATIN_BLUE_ADJUSTMENT )+ {+ blue = &Axis->blues[nn];+ break;+ }+ }++ if ( blue )+ {+ FT_Pos scaled = FT_MulFix( blue->shoot.org, scaler->y_scale );+ FT_Pos fitted = ( scaled + 40 ) & ~63;+++ if ( scaled != fitted )+ {+#if 0+ if ( dim == AF_DIMENSION_HORZ )+ {+ if ( fitted < scaled )+ scale -= scale / 50; /* scale *= 0.98 */+ }+ else+#endif+ if ( dim == AF_DIMENSION_VERT )+ {+ scale = FT_MulDiv( scale, fitted, scaled );+ }+ }+ }+ }++ axis->scale = scale;+ axis->delta = delta;++ if ( dim == AF_DIMENSION_HORZ )+ {+ metrics->root.scaler.x_scale = scale;+ metrics->root.scaler.x_delta = delta;+ }+ else+ {+ metrics->root.scaler.y_scale = scale;+ metrics->root.scaler.y_delta = delta;+ }++ /* scale the standard widths */+ for ( nn = 0; nn < axis->width_count; nn++ )+ {+ AF_Width width = axis->widths + nn;+++ width->cur = FT_MulFix( width->org, scale );+ width->fit = width->cur;+ }++ /* an extra-light axis corresponds to a standard width that is */+ /* smaller than 0.75 pixels */+ axis->extra_light =+ (FT_Bool)( FT_MulFix( axis->standard_width, scale ) < 32 + 8 );++ if ( dim == AF_DIMENSION_VERT )+ {+ /* scale the blue zones */+ for ( nn = 0; nn < axis->blue_count; nn++ )+ {+ AF_LatinBlue blue = &axis->blues[nn];+ FT_Pos dist;+++ blue->ref.cur = FT_MulFix( blue->ref.org, scale ) + delta;+ blue->ref.fit = blue->ref.cur;+ blue->shoot.cur = FT_MulFix( blue->shoot.org, scale ) + delta;+ blue->shoot.fit = blue->shoot.cur;+ blue->flags &= ~AF_LATIN_BLUE_ACTIVE;++ /* a blue zone is only active if it is less than 3/4 pixels tall */+ dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale );+ if ( dist <= 48 && dist >= -48 )+ {+ FT_Pos delta1, delta2;+++ delta1 = blue->shoot.org - blue->ref.org;+ delta2 = delta1;+ if ( delta1 < 0 )+ delta2 = -delta2;++ delta2 = FT_MulFix( delta2, scale );++ if ( delta2 < 32 )+ delta2 = 0;+ else if ( delta2 < 64 )+ delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & ~31 );+ else+ delta2 = FT_PIX_ROUND( delta2 );++ if ( delta1 < 0 )+ delta2 = -delta2;++ blue->ref.fit = FT_PIX_ROUND( blue->ref.cur );+ blue->shoot.fit = blue->ref.fit + delta2;++ blue->flags |= AF_LATIN_BLUE_ACTIVE;+ }+ }+ }+ }+++ FT_LOCAL_DEF( void )+ af_latin_metrics_scale( AF_LatinMetrics metrics,+ AF_Scaler scaler )+ {+ metrics->root.scaler.render_mode = scaler->render_mode;+ metrics->root.scaler.face = scaler->face;++ af_latin_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ );+ af_latin_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT );+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** L A T I N G L Y P H A N A L Y S I S *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ FT_LOCAL_DEF( FT_Error )+ 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 = AF_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_ZERO( &seg0 );+ seg0.score = 32000;+ seg0.flags = AF_EDGE_NORMAL;++ major_dir = (AF_Direction)FT_ABS( axis->major_dir );+ segment_dir = major_dir;++ axis->num_segments = 0;++ /* set up (u,v) in each point */+ if ( dim == AF_DIMENSION_HORZ )+ {+ AF_Point point = hints->points;+ AF_Point limit = point + hints->num_points;+++ for ( ; point < limit; point++ )+ {+ point->u = point->fx;+ point->v = point->fy;+ }+ }+ else+ {+ AF_Point point = hints->points;+ AF_Point limit = point + hints->num_points;+++ for ( ; point < limit; point++ )+ {+ point->u = point->fy;+ point->v = point->fx;+ }+ }++ /* 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 */+ FT_Bool passed;+++ if ( point == last ) /* skip singletons -- just in case */+ continue;++ if ( FT_ABS( last->out_dir ) == major_dir &&+ FT_ABS( point->out_dir ) == major_dir )+ {+ /* we are already on an edge, try to locate its start */+ last = point;++ for (;;)+ {+ point = point->prev;+ if ( FT_ABS( point->out_dir ) != major_dir )+ {+ point = point->next;+ break;+ }+ if ( point == last )+ break;+ }+ }++ last = point;+ passed = 0;++ for (;;)+ {+ FT_Pos u, v;+++ if ( on_edge )+ {+ u = point->u;+ if ( u < min_pos )+ min_pos = u;+ if ( u > max_pos )+ max_pos = u;++ if ( point->out_dir != segment_dir || point == last )+ {+ /* we are just leaving an edge; record a new segment! */+ segment->last = point;+ 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 )+ segment->flags |= AF_EDGE_ROUND;++ /* compute segment size */+ min_pos = max_pos = point->v;++ v = segment->first->v;+ if ( v < min_pos )+ min_pos = v;+ if ( v > max_pos )+ max_pos = v;++ segment->min_coord = (FT_Short)min_pos;+ segment->max_coord = (FT_Short)max_pos;+ segment->height = (FT_Short)( segment->max_coord -+ segment->min_coord );++ on_edge = 0;+ segment = NULL;+ /* fallthrough */+ }+ }++ /* now exit if we are at the start/end point */+ if ( point == last )+ {+ if ( passed )+ break;+ passed = 1;+ }++ if ( !on_edge && FT_ABS( point->out_dir ) == major_dir )+ {+ /* this is the start of a new segment! */+ segment_dir = (AF_Direction)point->out_dir;++ /* clear all segment fields */+ error = af_axis_hints_new_segment( axis, memory, &segment );+ if ( error )+ goto Exit;++ segment[0] = seg0;+ segment->dir = (FT_Char)segment_dir;+ min_pos = max_pos = point->u;+ segment->first = point;+ segment->last = point;+ segment->contour = contour;+ on_edge = 1;+ }++ point = point->next;+ }++ } /* contours */+++ /* now slightly increase the height of segments when this makes */+ /* sense -- this is used to better detect and ignore serifs */+ {+ AF_Segment segments = axis->segments;+ AF_Segment segments_end = segments + axis->num_segments;+++ for ( segment = segments; segment < segments_end; segment++ )+ {+ AF_Point first = segment->first;+ AF_Point last = segment->last;+ FT_Pos first_v = first->v;+ FT_Pos last_v = last->v;+++ if ( first == last )+ continue;++ if ( first_v < last_v )+ {+ AF_Point p;+++ p = first->prev;+ if ( p->v < first_v )+ segment->height = (FT_Short)( segment->height ++ ( ( first_v - p->v ) >> 1 ) );++ p = last->next;+ if ( p->v > last_v )+ segment->height = (FT_Short)( segment->height ++ ( ( p->v - last_v ) >> 1 ) );+ }+ else+ {+ AF_Point p;+++ p = first->prev;+ if ( p->v > first_v )+ segment->height = (FT_Short)( segment->height ++ ( ( p->v - first_v ) >> 1 ) );++ p = last->next;+ if ( p->v < last_v )+ segment->height = (FT_Short)( segment->height ++ ( ( last_v - p->v ) >> 1 ) );+ }+ }+ }++ Exit:+ return error;+ }+++ FT_LOCAL_DEF( void )+ af_latin_hints_link_segments( AF_GlyphHints hints,+ AF_Dimension dim )+ {+ AF_AxisHints axis = &hints->axis[dim];+ AF_Segment segments = axis->segments;+ AF_Segment segment_limit = segments + axis->num_segments;+ FT_Pos len_threshold, len_score;+ AF_Segment seg1, seg2;+++ len_threshold = AF_LATIN_CONSTANT( hints->metrics, 8 );+ if ( len_threshold == 0 )+ len_threshold = 1;++ len_score = AF_LATIN_CONSTANT( hints->metrics, 6000 );++ /* now compare each segment to the others */+ for ( seg1 = segments; seg1 < segment_limit; seg1++ )+ {+ /* the fake segments are introduced to hint the metrics -- */+ /* we must never link them to anything */+ if ( seg1->dir != axis->major_dir || seg1->first == seg1->last )+ continue;++ for ( seg2 = segments; seg2 < segment_limit; seg2++ )+ if ( seg1->dir + seg2->dir == 0 && seg2->pos > seg1->pos )+ {+ FT_Pos pos1 = seg1->pos;+ FT_Pos pos2 = seg2->pos;+ FT_Pos dist = pos2 - pos1;+++ if ( dist < 0 )+ dist = -dist;++ {+ FT_Pos min = seg1->min_coord;+ FT_Pos max = seg1->max_coord;+ FT_Pos len, score;+++ if ( min < seg2->min_coord )+ min = seg2->min_coord;++ if ( max > seg2->max_coord )+ max = seg2->max_coord;++ len = max - min;+ if ( len >= len_threshold )+ {+ score = dist + len_score / len;++ if ( score < seg1->score )+ {+ seg1->score = score;+ seg1->link = seg2;+ }++ if ( score < seg2->score )+ {+ seg2->score = score;+ seg2->link = seg1;+ }+ }+ }+ }+ }++ /* now, compute the `serif' segments */+ for ( seg1 = segments; seg1 < segment_limit; seg1++ )+ {+ seg2 = seg1->link;++ if ( seg2 )+ {+ if ( seg2->link != seg1 )+ {+ seg1->link = 0;+ seg1->serif = seg2->link;+ }+ }+ }+ }+++ FT_LOCAL_DEF( FT_Error )+ af_latin_hints_compute_edges( AF_GlyphHints hints,+ AF_Dimension dim )+ {+ AF_AxisHints axis = &hints->axis[dim];+ FT_Error error = AF_Err_Ok;+ FT_Memory memory = hints->memory;+ AF_LatinAxis laxis = &((AF_LatinMetrics)hints->metrics)->axis[dim];++ AF_Segment segments = axis->segments;+ AF_Segment segment_limit = segments + axis->num_segments;+ AF_Segment seg;++ AF_Direction up_dir;+ FT_Fixed scale;+ FT_Pos edge_distance_threshold;+ FT_Pos segment_length_threshold;+++ axis->num_edges = 0;++ scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale+ : hints->y_scale;++ up_dir = ( dim == AF_DIMENSION_HORZ ) ? AF_DIR_UP+ : AF_DIR_RIGHT;++ /*+ * We ignore all segments that are less than 1 pixels in length,+ * to avoid many problems with serif fonts. We compute the+ * corresponding threshold in font units.+ */+ if ( dim == AF_DIMENSION_HORZ )+ segment_length_threshold = FT_DivFix( 64, hints->y_scale );+ else+ segment_length_threshold = 0;++ /*********************************************************************/+ /* */+ /* We will begin by generating a sorted table of edges for the */+ /* current direction. To do so, we simply scan each segment and try */+ /* to find an edge in our table that corresponds to its position. */+ /* */+ /* If no edge is found, we create and insert a new edge in the */+ /* sorted table. Otherwise, we simply add the segment to the edge's */+ /* list which will be processed in the second step to compute the */+ /* edge's properties. */+ /* */+ /* Note that the edges table is sorted along the segment/edge */+ /* position. */+ /* */+ /*********************************************************************/++ edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold,+ scale );+ if ( edge_distance_threshold > 64 / 4 )+ edge_distance_threshold = 64 / 4;++ edge_distance_threshold = FT_DivFix( edge_distance_threshold,+ scale );++ for ( seg = segments; seg < segment_limit; seg++ )+ {+ AF_Edge found = 0;+ FT_Int ee;+++ if ( seg->height < segment_length_threshold )+ continue;++ /* A special case for serif edges: If they are smaller than */+ /* 1.5 pixels we ignore them. */+ if ( seg->serif &&+ 2 * seg->height < 3 * segment_length_threshold )+ continue;++ /* look for an edge corresponding to the segment */+ for ( ee = 0; ee < axis->num_edges; ee++ )+ {+ AF_Edge edge = axis->edges + ee;+ FT_Pos dist;+++ dist = seg->pos - edge->fpos;+ if ( dist < 0 )+ dist = -dist;++ if ( dist < edge_distance_threshold && edge->dir == seg->dir )+ {+ found = edge;+ break;+ }+ }++ if ( !found )+ {+ AF_Edge edge;+++ /* insert a new edge in the list and */+ /* sort according to the position */+ error = af_axis_hints_new_edge( axis, seg->pos,+ (AF_Direction)seg->dir,+ memory, &edge );+ if ( error )+ goto Exit;++ /* add the segment to the new edge's list */+ FT_ZERO( edge );++ edge->first = seg;+ edge->last = seg;+ edge->fpos = seg->pos;+ edge->dir = seg->dir;+ edge->opos = edge->pos = FT_MulFix( seg->pos, scale );+ seg->edge_next = seg;+ }+ else+ {+ /* if an edge was found, simply add the segment to the edge's */+ /* list */+ seg->edge_next = found->first;+ found->last->edge_next = seg;+ found->last = seg;+ }+ }+++ /*********************************************************************/+ /* */+ /* Good, we will now compute each edge's properties according to */+ /* segments found on its position. Basically, these are: */+ /* */+ /* - edge's main direction */+ /* - stem edge, serif edge or both (which defaults to stem then) */+ /* - rounded edge, straight or both (which defaults to straight) */+ /* - link for edge */+ /* */+ /*********************************************************************/++ /* first of all, set the `edge' field in each segment -- this is */+ /* required in order to compute edge links */++ /*+ * Note that removing this loop and setting the `edge' field of each+ * segment directly in the code above slows down execution speed for+ * some reasons on platforms like the Sun.+ */+ {+ AF_Edge edges = axis->edges;+ AF_Edge edge_limit = edges + axis->num_edges;+ AF_Edge edge;+++ for ( edge = edges; edge < edge_limit; edge++ )+ {+ seg = edge->first;+ if ( seg )+ do+ {+ seg->edge = edge;+ seg = seg->edge_next;++ } while ( seg != edge->first );+ }++ /* now, compute each edge properties */+ for ( edge = edges; edge < edge_limit; edge++ )+ {+ FT_Int is_round = 0; /* does it contain round segments? */+ FT_Int is_straight = 0; /* does it contain straight segments? */+ FT_Pos ups = 0; /* number of upwards segments */+ FT_Pos downs = 0; /* number of downwards segments */+++ seg = edge->first;++ do+ {+ FT_Bool is_serif;+++ /* check for roundness of segment */+ if ( seg->flags & AF_EDGE_ROUND )+ is_round++;+ else+ is_straight++;++ /* check for segment direction */+ if ( seg->dir == up_dir )+ ups += seg->max_coord-seg->min_coord;+ else+ downs += seg->max_coord-seg->min_coord;++ /* check for links -- if seg->serif is set, then seg->link must */+ /* be ignored */+ is_serif = (FT_Bool)( seg->serif &&+ seg->serif->edge &&+ seg->serif->edge != edge );++ if ( ( seg->link && seg->link->edge != NULL ) || is_serif )+ {+ AF_Edge edge2;+ AF_Segment seg2;+++ edge2 = edge->link;+ seg2 = seg->link;++ if ( is_serif )+ {+ seg2 = seg->serif;+ edge2 = edge->serif;+ }++ if ( edge2 )+ {+ FT_Pos edge_delta;+ FT_Pos seg_delta;+++ edge_delta = edge->fpos - edge2->fpos;+ if ( edge_delta < 0 )+ edge_delta = -edge_delta;++ seg_delta = seg->pos - seg2->pos;+ if ( seg_delta < 0 )+ seg_delta = -seg_delta;++ if ( seg_delta < edge_delta )+ edge2 = seg2->edge;+ }+ else+ edge2 = seg2->edge;++ if ( is_serif )+ {+ edge->serif = edge2;+ edge2->flags |= AF_EDGE_SERIF;+ }+ else+ edge->link = edge2;+ }++ seg = seg->edge_next;++ } while ( seg != edge->first );++ /* set the round/straight flags */+ edge->flags = AF_EDGE_NORMAL;++ if ( is_round > 0 && is_round >= is_straight )+ edge->flags |= AF_EDGE_ROUND;++#if 0+ /* set the edge's main direction */+ edge->dir = AF_DIR_NONE;++ if ( ups > downs )+ edge->dir = (FT_Char)up_dir;++ else if ( ups < downs )+ edge->dir = (FT_Char)-up_dir;++ else if ( ups == downs )+ edge->dir = 0; /* both up and down! */+#endif++ /* gets rid of serifs if link is set */+ /* XXX: This gets rid of many unpleasant artefacts! */+ /* Example: the `c' in cour.pfa at size 13 */++ if ( edge->serif && edge->link )+ edge->serif = 0;+ }+ }++ Exit:+ return error;+ }+++ FT_LOCAL_DEF( FT_Error )+ af_latin_hints_detect_features( AF_GlyphHints hints,+ AF_Dimension dim )+ {+ FT_Error error;+++ error = af_latin_hints_compute_segments( hints, dim );+ if ( !error )+ {+ af_latin_hints_link_segments( hints, dim );++ error = af_latin_hints_compute_edges( hints, dim );+ }+ return error;+ }+++ FT_LOCAL_DEF( void )+ af_latin_hints_compute_blue_edges( AF_GlyphHints hints,+ AF_LatinMetrics metrics )+ {+ AF_AxisHints axis = &hints->axis[ AF_DIMENSION_VERT ];+ AF_Edge edge = axis->edges;+ AF_Edge edge_limit = edge + axis->num_edges;+ AF_LatinAxis latin = &metrics->axis[ AF_DIMENSION_VERT ];+ FT_Fixed scale = latin->scale;+++ /* compute which blue zones are active, i.e. have their scaled */+ /* size < 3/4 pixels */++ /* for each horizontal edge search the blue zone which is closest */+ for ( ; edge < edge_limit; edge++ )+ {+ FT_Int bb;+ AF_Width best_blue = NULL;+ FT_Pos best_dist; /* initial threshold */+++ /* compute the initial threshold as a fraction of the EM size */+ best_dist = FT_MulFix( metrics->units_per_em / 40, scale );++ if ( best_dist > 64 / 2 )+ best_dist = 64 / 2;++ for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )+ {+ AF_LatinBlue blue = latin->blues + bb;+ FT_Bool is_top_blue, is_major_dir;+++ /* skip inactive blue zones (i.e., those that are too small) */+ if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) )+ continue;++ /* if it is a top zone, check for right edges -- if it is a bottom */+ /* zone, check for left edges */+ /* */+ /* of course, that's for TrueType */+ is_top_blue = (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 );+ is_major_dir = FT_BOOL( edge->dir == axis->major_dir );++ /* if it is a top zone, the edge must be against the major */+ /* direction; if it is a bottom zone, it must be in the major */+ /* direction */+ if ( is_top_blue ^ is_major_dir )+ {+ FT_Pos dist;+++ /* first of all, compare it to the reference position */+ dist = edge->fpos - blue->ref.org;+ if ( dist < 0 )+ dist = -dist;++ dist = FT_MulFix( dist, scale );+ if ( dist < best_dist )+ {+ best_dist = dist;+ best_blue = & blue->ref;+ }++ /* now, compare it to the overshoot position if the edge is */+ /* rounded, and if the edge is over the reference position of a */+ /* top zone, or under the reference position of a bottom zone */+ if ( edge->flags & AF_EDGE_ROUND && dist != 0 )+ {+ FT_Bool is_under_ref = FT_BOOL( edge->fpos < blue->ref.org );+++ if ( is_top_blue ^ is_under_ref )+ {+ blue = latin->blues + bb;+ dist = edge->fpos - blue->shoot.org;+ if ( dist < 0 )+ dist = -dist;++ dist = FT_MulFix( dist, scale );+ if ( dist < best_dist )+ {+ best_dist = dist;+ best_blue = & blue->shoot;+ }+ }+ }+ }+ }++ if ( best_blue )+ edge->blue_edge = best_blue;+ }+ }+++ static FT_Error+ af_latin_hints_init( AF_GlyphHints hints,+ AF_LatinMetrics metrics )+ {+ FT_Render_Mode mode;+ FT_UInt32 scaler_flags, other_flags;+ FT_Face face = metrics->root.scaler.face;+++ af_glyph_hints_rescale( hints, (AF_ScriptMetrics)metrics );++ /*+ * correct x_scale and y_scale if needed, since they may have+ * been modified `af_latin_metrics_scale_dim' above+ */+ hints->x_scale = metrics->axis[AF_DIMENSION_HORZ].scale;+ hints->x_delta = metrics->axis[AF_DIMENSION_HORZ].delta;+ hints->y_scale = metrics->axis[AF_DIMENSION_VERT].scale;+ hints->y_delta = metrics->axis[AF_DIMENSION_VERT].delta;++ /* compute flags depending on render mode, etc. */+ mode = metrics->root.scaler.render_mode;++#if 0 /* #ifdef AF_USE_WARPER */+ if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )+ {+ metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;+ }+#endif++ scaler_flags = hints->scaler_flags;+ other_flags = 0;++ /*+ * We snap the width of vertical stems for the monochrome and+ * horizontal LCD rendering targets only.+ */+ if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD )+ other_flags |= AF_LATIN_HINTS_HORZ_SNAP;++ /*+ * We snap the width of horizontal stems for the monochrome and+ * vertical LCD rendering targets only.+ */+ if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD_V )+ other_flags |= AF_LATIN_HINTS_VERT_SNAP;++ /*+ * We adjust stems to full pixels only if we don't use the `light' mode.+ */+ if ( mode != FT_RENDER_MODE_LIGHT )+ other_flags |= AF_LATIN_HINTS_STEM_ADJUST;++ if ( mode == FT_RENDER_MODE_MONO )+ other_flags |= AF_LATIN_HINTS_MONO;++ /*+ * In `light' hinting mode we disable horizontal hinting completely.+ * We also do it if the face is italic.+ */+ if ( mode == FT_RENDER_MODE_LIGHT ||+ (face->style_flags & FT_STYLE_FLAG_ITALIC) != 0 )+ scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL;++ hints->scaler_flags = scaler_flags;+ hints->other_flags = other_flags;++ return 0;+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** L A T I N G L Y P H G R I D - F I T T I N G *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /* snap a given width in scaled coordinates to one of the */+ /* current standard widths */++ static FT_Pos+ af_latin_snap_width( AF_Width widths,+ FT_Int count,+ FT_Pos width )+ {+ int n;+ FT_Pos best = 64 + 32 + 2;+ FT_Pos reference = width;+ FT_Pos scaled;+++ for ( n = 0; n < count; n++ )+ {+ FT_Pos w;+ FT_Pos dist;+++ w = widths[n].cur;+ dist = width - w;+ if ( dist < 0 )+ dist = -dist;+ if ( dist < best )+ {+ best = dist;+ reference = w;+ }+ }++ scaled = FT_PIX_ROUND( reference );++ if ( width >= reference )+ {+ if ( width < scaled + 48 )+ width = reference;+ }+ else+ {+ if ( width > scaled - 48 )+ width = reference;+ }++ return width;+ }+++ /* compute the snapped width of a given stem */++ static FT_Pos+ af_latin_compute_stem_width( AF_GlyphHints hints,+ AF_Dimension dim,+ FT_Pos width,+ AF_Edge_Flags base_flags,+ AF_Edge_Flags stem_flags )+ {+ AF_LatinMetrics metrics = (AF_LatinMetrics) hints->metrics;+ AF_LatinAxis axis = & metrics->axis[dim];+ FT_Pos dist = width;+ FT_Int sign = 0;+ FT_Int vertical = ( dim == AF_DIMENSION_VERT );+++ if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) ||+ axis->extra_light )+ return width;++ if ( dist < 0 )+ {+ dist = -width;+ sign = 1;+ }++ if ( ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) ||+ ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) )+ {+ /* smooth hinting process: very lightly quantize the stem width */++ /* leave the widths of serifs alone */++ if ( ( stem_flags & AF_EDGE_SERIF ) && vertical && ( dist < 3 * 64 ) )+ goto Done_Width;++ else if ( ( base_flags & AF_EDGE_ROUND ) )+ {+ if ( dist < 80 )+ dist = 64;+ }+ else if ( dist < 56 )+ dist = 56;++ if ( axis->width_count > 0 )+ {+ FT_Pos delta;+++ /* compare to standard width */+ delta = dist - axis->widths[0].cur;++ if ( delta < 0 )+ delta = -delta;++ if ( delta < 40 )+ {+ dist = axis->widths[0].cur;+ if ( dist < 48 )+ dist = 48;++ goto Done_Width;+ }++ if ( dist < 3 * 64 )+ {+ delta = dist & 63;+ dist &= -64;++ if ( delta < 10 )+ dist += delta;++ else if ( delta < 32 )+ dist += 10;++ else if ( delta < 54 )+ dist += 54;++ else+ dist += delta;+ }+ else+ dist = ( dist + 32 ) & ~63;+ }+ }+ else+ {+ /* strong hinting process: snap the stem width to integer pixels */+ FT_Pos org_dist = dist;+++ dist = af_latin_snap_width( axis->widths, axis->width_count, dist );++ if ( vertical )+ {+ /* in the case of vertical hinting, always round */+ /* the stem heights to integer pixels */++ if ( dist >= 64 )+ dist = ( dist + 16 ) & ~63;+ else+ dist = 64;+ }+ else+ {+ if ( AF_LATIN_HINTS_DO_MONO( hints ) )+ {+ /* monochrome horizontal hinting: snap widths to integer pixels */+ /* with a different threshold */++ if ( dist < 64 )+ dist = 64;+ else+ dist = ( dist + 32 ) & ~63;+ }+ else+ {+ /* for horizontal anti-aliased hinting, we adopt a more subtle */+ /* approach: we strengthen small stems, round stems whose size */+ /* is between 1 and 2 pixels to an integer, otherwise nothing */++ if ( dist < 48 )+ dist = ( dist + 64 ) >> 1;++ else if ( dist < 128 )+ {+ /* We only round to an integer width if the corresponding */+ /* distortion is less than 1/4 pixel. Otherwise this */+ /* makes everything worse since the diagonals, which are */+ /* not hinted, appear a lot bolder or thinner than the */+ /* vertical stems. */++ FT_Pos delta;+++ dist = ( dist + 22 ) & ~63;+ delta = dist - org_dist;+ if ( delta < 0 )+ delta = -delta;++ if (delta >= 16)+ {+ dist = org_dist;+ if ( dist < 48 )+ dist = ( dist + 64 ) >> 1;+ }+ }+ else+ /* round otherwise to prevent color fringes in LCD mode */+ dist = ( dist + 32 ) & ~63;+ }+ }+ }++ Done_Width:+ if ( sign )+ dist = -dist;++ return dist;+ }+++ /* align one stem edge relative to the previous stem edge */++ static void+ af_latin_align_linked_edge( AF_GlyphHints hints,+ AF_Dimension dim,+ AF_Edge base_edge,+ AF_Edge stem_edge )+ {+ FT_Pos dist = stem_edge->opos - base_edge->opos;++ FT_Pos fitted_width = af_latin_compute_stem_width(+ hints, dim, dist,+ (AF_Edge_Flags)base_edge->flags,+ (AF_Edge_Flags)stem_edge->flags );+++ stem_edge->pos = base_edge->pos + fitted_width;++ AF_LOG(( "LINK: edge %d (opos=%.2f) linked to (%.2f), "+ "dist was %.2f, now %.2f\n",+ stem_edge-hints->axis[dim].edges, stem_edge->opos / 64.0,+ stem_edge->pos / 64.0, dist / 64.0, fitted_width / 64.0 ));+ }+++ static void+ af_latin_align_serif_edge( AF_GlyphHints hints,+ AF_Edge base,+ AF_Edge serif )+ {+ FT_UNUSED( hints );++ serif->pos = base->pos + (serif->opos - base->opos);+ }+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** E D G E H I N T I N G ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ FT_LOCAL_DEF( void )+ af_latin_hint_edges( AF_GlyphHints hints,+ AF_Dimension dim )+ {+ AF_AxisHints axis = &hints->axis[dim];+ AF_Edge edges = axis->edges;+ AF_Edge edge_limit = edges + axis->num_edges;+ FT_PtrDist n_edges;+ AF_Edge edge;+ AF_Edge anchor = 0;+ FT_Int has_serifs = 0;+++ /* we begin by aligning all stems relative to the blue zone */+ /* if needed -- that's only for horizontal edges */++ if ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_BLUES( hints ) )+ {+ for ( edge = edges; edge < edge_limit; edge++ )+ {+ AF_Width blue;+ AF_Edge edge1, edge2;+++ if ( edge->flags & AF_EDGE_DONE )+ continue;++ blue = edge->blue_edge;+ edge1 = NULL;+ edge2 = edge->link;++ if ( blue )+ {+ edge1 = edge;+ }+ else if ( edge2 && edge2->blue_edge )+ {+ blue = edge2->blue_edge;+ edge1 = edge2;+ edge2 = edge;+ }++ if ( !edge1 )+ continue;++ AF_LOG(( "BLUE: edge %d (opos=%.2f) snapped to (%.2f), "+ "was (%.2f)\n",+ edge1-edges, edge1->opos / 64.0, blue->fit / 64.0,+ edge1->pos / 64.0 ));++ edge1->pos = blue->fit;+ edge1->flags |= AF_EDGE_DONE;++ if ( edge2 && !edge2->blue_edge )+ {+ af_latin_align_linked_edge( hints, dim, edge1, edge2 );+ edge2->flags |= AF_EDGE_DONE;+ }++ if ( !anchor )+ anchor = edge;+ }+ }++ /* now we will align all stem edges, trying to maintain the */+ /* relative order of stems in the glyph */+ for ( edge = edges; edge < edge_limit; edge++ )+ {+ AF_Edge edge2;+++ if ( edge->flags & AF_EDGE_DONE )+ continue;++ /* skip all non-stem edges */+ edge2 = edge->link;+ if ( !edge2 )+ {+ has_serifs++;+ continue;+ }++ /* now align the stem */++ /* this should not happen, but it's better to be safe */+ if ( edge2->blue_edge )+ {+ AF_LOG(( "ASSERTION FAILED for edge %d\n", edge2-edges ));++ af_latin_align_linked_edge( hints, dim, edge2, edge );+ edge->flags |= AF_EDGE_DONE;+ continue;+ }++ if ( !anchor )+ {+ FT_Pos org_len, org_center, cur_len;+ FT_Pos cur_pos1, error1, error2, u_off, d_off;+++ org_len = edge2->opos - edge->opos;+ cur_len = af_latin_compute_stem_width(+ hints, dim, org_len,+ (AF_Edge_Flags)edge->flags,+ (AF_Edge_Flags)edge2->flags );+ if ( cur_len <= 64 )+ u_off = d_off = 32;+ else+ {+ u_off = 38;+ d_off = 26;+ }++ if ( cur_len < 96 )+ {+ org_center = edge->opos + ( org_len >> 1 );++ cur_pos1 = FT_PIX_ROUND( org_center );++ error1 = org_center - ( cur_pos1 - u_off );+ if ( error1 < 0 )+ error1 = -error1;++ error2 = org_center - ( cur_pos1 + d_off );+ if ( error2 < 0 )+ error2 = -error2;++ if ( error1 < error2 )+ cur_pos1 -= u_off;+ else+ cur_pos1 += d_off;++ edge->pos = cur_pos1 - cur_len / 2;+ edge2->pos = edge->pos + cur_len;+ }+ else+ edge->pos = FT_PIX_ROUND( edge->opos );++ AF_LOG(( "ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f) "+ "snapped to (%.2f) (%.2f)\n",+ edge-edges, edge->opos / 64.0,+ edge2-edges, edge2->opos / 64.0,+ edge->pos / 64.0, edge2->pos / 64.0 ));+ anchor = edge;++ edge->flags |= AF_EDGE_DONE;++ af_latin_align_linked_edge( hints, dim, edge, edge2 );+ }+ else+ {+ FT_Pos org_pos, org_len, org_center, cur_len;+ FT_Pos cur_pos1, cur_pos2, delta1, delta2;+++ org_pos = anchor->pos + ( edge->opos - anchor->opos );+ org_len = edge2->opos - edge->opos;+ org_center = org_pos + ( org_len >> 1 );++ cur_len = af_latin_compute_stem_width(+ hints, dim, org_len,+ (AF_Edge_Flags)edge->flags,+ (AF_Edge_Flags)edge2->flags );++ if ( edge2->flags & AF_EDGE_DONE )+ edge->pos = edge2->pos - cur_len;++ else if ( cur_len < 96 )+ {+ FT_Pos u_off, d_off;+++ cur_pos1 = FT_PIX_ROUND( org_center );++ if (cur_len <= 64 )+ u_off = d_off = 32;+ else+ {+ u_off = 38;+ d_off = 26;+ }++ delta1 = org_center - ( cur_pos1 - u_off );+ if ( delta1 < 0 )+ delta1 = -delta1;++ delta2 = org_center - ( cur_pos1 + d_off );+ if ( delta2 < 0 )+ delta2 = -delta2;++ if ( delta1 < delta2 )+ cur_pos1 -= u_off;+ else+ cur_pos1 += d_off;++ edge->pos = cur_pos1 - cur_len / 2;+ edge2->pos = cur_pos1 + cur_len / 2;++ AF_LOG(( "STEM: %d (opos=%.2f) to %d (opos=%.2f) "+ "snapped to (%.2f) and (%.2f)\n",+ edge-edges, edge->opos / 64.0,+ edge2-edges, edge2->opos / 64.0,+ edge->pos / 64.0, edge2->pos / 64.0 ));+ }+ else+ {+ org_pos = anchor->pos + ( edge->opos - anchor->opos );+ org_len = edge2->opos - edge->opos;+ org_center = org_pos + ( org_len >> 1 );++ cur_len = af_latin_compute_stem_width(+ hints, dim, org_len,+ (AF_Edge_Flags)edge->flags,+ (AF_Edge_Flags)edge2->flags );++ cur_pos1 = FT_PIX_ROUND( org_pos );+ delta1 = cur_pos1 + ( cur_len >> 1 ) - org_center;+ if ( delta1 < 0 )+ delta1 = -delta1;++ cur_pos2 = FT_PIX_ROUND( org_pos + org_len ) - cur_len;+ delta2 = cur_pos2 + ( cur_len >> 1 ) - org_center;+ if ( delta2 < 0 )+ delta2 = -delta2;++ edge->pos = ( delta1 < delta2 ) ? cur_pos1 : cur_pos2;+ edge2->pos = edge->pos + cur_len;++ AF_LOG(( "STEM: %d (opos=%.2f) to %d (opos=%.2f) "+ "snapped to (%.2f) and (%.2f)\n",+ edge-edges, edge->opos / 64.0,+ edge2-edges, edge2->opos / 64.0,+ edge->pos / 64.0, edge2->pos / 64.0 ));+ }++ edge->flags |= AF_EDGE_DONE;+ edge2->flags |= AF_EDGE_DONE;++ if ( edge > edges && edge->pos < edge[-1].pos )+ {+ AF_LOG(( "BOUND: %d (pos=%.2f) to (%.2f)\n",+ edge-edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));+ edge->pos = edge[-1].pos;+ }+ }+ }++ /* make sure that lowercase m's maintain their symmetry */++ /* In general, lowercase m's have six vertical edges if they are sans */+ /* serif, or twelve if they are with serifs. This implementation is */+ /* based on that assumption, and seems to work very well with most */+ /* faces. However, if for a certain face this assumption is not */+ /* true, the m is just rendered like before. In addition, any stem */+ /* correction will only be applied to symmetrical glyphs (even if the */+ /* glyph is not an m), so the potential for unwanted distortion is */+ /* relatively low. */++ /* We don't handle horizontal edges since we can't easily assure that */+ /* the third (lowest) stem aligns with the base line; it might end up */+ /* one pixel higher or lower. */++ n_edges = edge_limit - edges;+ if ( dim == AF_DIMENSION_HORZ && ( n_edges == 6 || n_edges == 12 ) )+ {+ AF_Edge edge1, edge2, edge3;+ FT_Pos dist1, dist2, span, delta;+++ if ( n_edges == 6 )+ {+ edge1 = edges;+ edge2 = edges + 2;+ edge3 = edges + 4;+ }+ else+ {+ edge1 = edges + 1;+ edge2 = edges + 5;+ edge3 = edges + 9;+ }++ dist1 = edge2->opos - edge1->opos;+ dist2 = edge3->opos - edge2->opos;++ span = dist1 - dist2;+ if ( span < 0 )+ span = -span;++ if ( span < 8 )+ {+ delta = edge3->pos - ( 2 * edge2->pos - edge1->pos );+ edge3->pos -= delta;+ if ( edge3->link )+ edge3->link->pos -= delta;++ /* move the serifs along with the stem */+ if ( n_edges == 12 )+ {+ ( edges + 8 )->pos -= delta;+ ( edges + 11 )->pos -= delta;+ }++ edge3->flags |= AF_EDGE_DONE;+ if ( edge3->link )+ edge3->link->flags |= AF_EDGE_DONE;+ }+ }++ if ( has_serifs || !anchor )+ {+ /*+ * now hint the remaining edges (serifs and single) in order+ * to complete our processing+ */+ for ( edge = edges; edge < edge_limit; edge++ )+ {+ FT_Pos delta;+++ if ( edge->flags & AF_EDGE_DONE )+ continue;++ delta = 1000;++ if ( edge->serif )+ {+ delta = edge->serif->opos - edge->opos;+ if ( delta < 0 )+ delta = -delta;+ }++ if ( delta < 64 + 16 )+ {+ af_latin_align_serif_edge( hints, edge->serif, edge );+ AF_LOG(( "SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f) "+ "aligned to (%.2f)\n",+ edge-edges, edge->opos / 64.0,+ edge->serif - edges, edge->serif->opos / 64.0,+ edge->pos / 64.0 ));+ }+ else if ( !anchor )+ {+ AF_LOG(( "SERIF_ANCHOR: edge %d (opos=%.2f) snapped to (%.2f)\n",+ edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));+ edge->pos = FT_PIX_ROUND( edge->opos );+ anchor = edge;+ }+ else+ {+ AF_Edge before, after;+++ for ( before = edge - 1; before >= edges; before-- )+ if ( before->flags & AF_EDGE_DONE )+ break;++ for ( after = edge + 1; after < edge_limit; after++ )+ if ( after->flags & AF_EDGE_DONE )+ break;++ if ( before >= edges && before < edge &&+ after < edge_limit && after > edge )+ {+ if ( after->opos == before->opos )+ edge->pos = before->pos;+ else+ edge->pos = before->pos ++ FT_MulDiv( edge->opos - before->opos,+ after->pos - before->pos,+ after->opos - before->opos );+ AF_LOG(( "SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f) "+ "from %d (opos=%.2f)\n",+ edge-edges, edge->opos / 64.0,+ edge->pos / 64.0, before - edges,+ before->opos / 64.0 ));+ }+ else+ {+ edge->pos = anchor->pos ++ ( ( edge->opos - anchor->opos + 16 ) & ~31 );+ AF_LOG(( "SERIF_LINK2: edge %d (opos=%.2f) snapped to (%.2f)\n",+ edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));+ }+ }++ edge->flags |= AF_EDGE_DONE;++ if ( edge > edges && edge->pos < edge[-1].pos )+ edge->pos = edge[-1].pos;++ if ( edge + 1 < edge_limit &&+ edge[1].flags & AF_EDGE_DONE &&+ edge->pos > edge[1].pos )+ edge->pos = edge[1].pos;+ }+ }+ }+++ static FT_Error+ af_latin_hints_apply( AF_GlyphHints hints,+ FT_Outline* outline,+ AF_LatinMetrics metrics )+ {+ FT_Error error;+ int dim;+++ error = af_glyph_hints_reload( hints, outline );+ if ( error )+ goto Exit;++ /* analyze glyph outline */+#ifdef AF_USE_WARPER+ if ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ||+ AF_HINTS_DO_HORIZONTAL( hints ) )+#else+ if ( AF_HINTS_DO_HORIZONTAL( hints ) )+#endif+ {+ error = af_latin_hints_detect_features( hints, AF_DIMENSION_HORZ );+ if ( error )+ goto Exit;+ }++ if ( AF_HINTS_DO_VERTICAL( hints ) )+ {+ error = af_latin_hints_detect_features( hints, AF_DIMENSION_VERT );+ if ( error )+ goto Exit;++ af_latin_hints_compute_blue_edges( hints, metrics );+ }++ /* grid-fit the outline */+ for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )+ {+#ifdef AF_USE_WARPER+ if ( ( dim == AF_DIMENSION_HORZ &&+ metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ) )+ {+ AF_WarperRec warper;+ FT_Fixed scale;+ FT_Pos delta;+++ af_warper_compute( &warper, hints, dim, &scale, &delta );+ af_glyph_hints_scale_dim( hints, dim, scale, delta );+ continue;+ }+#endif++ if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) ||+ ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) ) )+ {+ af_latin_hint_edges( hints, (AF_Dimension)dim );+ af_glyph_hints_align_edge_points( hints, (AF_Dimension)dim );+ af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim );+ af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim );+ }+ }+ af_glyph_hints_save( hints, outline );++ Exit:+ return error;+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** L A T I N S C R I P T C L A S S *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+++ /* XXX: this should probably fine tuned to differentiate better between */+ /* scripts... */++ static const AF_Script_UniRangeRec af_latin_uniranges[] =+ {+ AF_UNIRANGE_REC( 0x0020UL, 0x007FUL ), /* Basic Latin (no control chars) */+ AF_UNIRANGE_REC( 0x00A0UL, 0x00FFUL ), /* Latin-1 Supplement (no control chars) */+ AF_UNIRANGE_REC( 0x0100UL, 0x017FUL ), /* Latin Extended-A */+ AF_UNIRANGE_REC( 0x0180UL, 0x024FUL ), /* Latin Extended-B */+ AF_UNIRANGE_REC( 0x0250UL, 0x02AFUL ), /* IPA Extensions */+ AF_UNIRANGE_REC( 0x02B0UL, 0x02FFUL ), /* Spacing Modifier Letters */+ AF_UNIRANGE_REC( 0x0300UL, 0x036FUL ), /* Combining Diacritical Marks */+ AF_UNIRANGE_REC( 0x0370UL, 0x03FFUL ), /* Greek and Coptic */+ AF_UNIRANGE_REC( 0x0400UL, 0x04FFUL ), /* Cyrillic */+ AF_UNIRANGE_REC( 0x0500UL, 0x052FUL ), /* Cyrillic Supplement */+ AF_UNIRANGE_REC( 0x1D00UL, 0x1D7FUL ), /* Phonetic Extensions */+ AF_UNIRANGE_REC( 0x1D80UL, 0x1DBFUL ), /* Phonetic Extensions Supplement */+ AF_UNIRANGE_REC( 0x1DC0UL, 0x1DFFUL ), /* Combining Diacritical Marks Supplement */+ AF_UNIRANGE_REC( 0x1E00UL, 0x1EFFUL ), /* Latin Extended Additional */+ AF_UNIRANGE_REC( 0x1F00UL, 0x1FFFUL ), /* Greek Extended */+ AF_UNIRANGE_REC( 0x2000UL, 0x206FUL ), /* General Punctuation */+ AF_UNIRANGE_REC( 0x2070UL, 0x209FUL ), /* Superscripts and Subscripts */+ AF_UNIRANGE_REC( 0x20A0UL, 0x20CFUL ), /* Currency Symbols */+ AF_UNIRANGE_REC( 0x2150UL, 0x218FUL ), /* Number Forms */+ AF_UNIRANGE_REC( 0x2460UL, 0x24FFUL ), /* Enclosed Alphanumerics */+ AF_UNIRANGE_REC( 0x2C60UL, 0x2C7FUL ), /* Latin Extended-C */+ AF_UNIRANGE_REC( 0x2DE0UL, 0x2DFFUL ), /* Cyrillic Extended-A */+ AF_UNIRANGE_REC( 0xA640UL, 0xA69FUL ), /* Cyrillic Extended-B */+ AF_UNIRANGE_REC( 0xA720UL, 0xA7FFUL ), /* Latin Extended-D */+ AF_UNIRANGE_REC( 0xFB00UL, 0xFB06UL ), /* Alphab. Present. Forms (Latin Ligs) */+ AF_UNIRANGE_REC( 0x1D400UL, 0x1D7FFUL ), /* Mathematical Alphanumeric Symbols */+ AF_UNIRANGE_REC( 0UL, 0UL )+ };+++ AF_DEFINE_SCRIPT_CLASS(af_latin_script_class, + AF_SCRIPT_LATIN,+ af_latin_uniranges,++ sizeof( AF_LatinMetricsRec ),++ (AF_Script_InitMetricsFunc) af_latin_metrics_init,+ (AF_Script_ScaleMetricsFunc)af_latin_metrics_scale,+ (AF_Script_DoneMetricsFunc) NULL,++ (AF_Script_InitHintsFunc) af_latin_hints_init,+ (AF_Script_ApplyHintsFunc) af_latin_hints_apply+ )+++/* END */
+ src/autofit/aflatin.h view
@@ -0,0 +1,212 @@+/***************************************************************************/+/* */+/* aflatin.h */+/* */+/* Auto-fitter hinting routines for latin script (specification). */+/* */+/* Copyright 2003, 2004, 2005, 2006, 2007, 2009 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#ifndef __AFLATIN_H__+#define __AFLATIN_H__++#include "afhints.h"+++FT_BEGIN_HEADER+++ /* the latin-specific script class */++ AF_DECLARE_SCRIPT_CLASS(af_latin_script_class)+++/* constants are given with units_per_em == 2048 in mind */+#define AF_LATIN_CONSTANT( metrics, c ) \+ ( ( (c) * (FT_Long)( (AF_LatinMetrics)(metrics) )->units_per_em ) / 2048 )+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** L A T I N G L O B A L M E T R I C S *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+++ /*+ * The following declarations could be embedded in the file `aflatin.c';+ * they have been made semi-public to allow alternate script hinters to+ * re-use some of them.+ */+++ /* Latin (global) metrics management */++ enum+ {+ AF_LATIN_BLUE_CAPITAL_TOP,+ AF_LATIN_BLUE_CAPITAL_BOTTOM,+ AF_LATIN_BLUE_SMALL_F_TOP,+ AF_LATIN_BLUE_SMALL_TOP,+ AF_LATIN_BLUE_SMALL_BOTTOM,+ AF_LATIN_BLUE_SMALL_MINOR,++ AF_LATIN_BLUE_MAX+ };+++#define AF_LATIN_IS_TOP_BLUE( b ) ( (b) == AF_LATIN_BLUE_CAPITAL_TOP || \+ (b) == AF_LATIN_BLUE_SMALL_F_TOP || \+ (b) == AF_LATIN_BLUE_SMALL_TOP )++#define AF_LATIN_MAX_WIDTHS 16+#define AF_LATIN_MAX_BLUES AF_LATIN_BLUE_MAX+++ enum+ {+ AF_LATIN_BLUE_ACTIVE = 1 << 0,+ AF_LATIN_BLUE_TOP = 1 << 1,+ AF_LATIN_BLUE_ADJUSTMENT = 1 << 2, /* used for scale adjustment */+ /* optimization */+ AF_LATIN_BLUE_FLAG_MAX+ };+++ typedef struct AF_LatinBlueRec_+ {+ AF_WidthRec ref;+ AF_WidthRec shoot;+ FT_UInt flags;++ } AF_LatinBlueRec, *AF_LatinBlue;+++ typedef struct AF_LatinAxisRec_+ {+ FT_Fixed scale;+ FT_Pos delta;++ FT_UInt width_count;+ AF_WidthRec widths[AF_LATIN_MAX_WIDTHS];+ FT_Pos edge_distance_threshold;+ FT_Pos standard_width;+ FT_Bool extra_light;++ /* ignored for horizontal metrics */+ FT_Bool control_overshoot;+ FT_UInt blue_count;+ AF_LatinBlueRec blues[AF_LATIN_BLUE_MAX];++ FT_Fixed org_scale;+ FT_Pos org_delta;++ } AF_LatinAxisRec, *AF_LatinAxis;+++ typedef struct AF_LatinMetricsRec_+ {+ AF_ScriptMetricsRec root;+ FT_UInt units_per_em;+ AF_LatinAxisRec axis[AF_DIMENSION_MAX];++ } AF_LatinMetricsRec, *AF_LatinMetrics;+++ FT_LOCAL( FT_Error )+ af_latin_metrics_init( AF_LatinMetrics metrics,+ FT_Face face );++ FT_LOCAL( void )+ af_latin_metrics_scale( AF_LatinMetrics metrics,+ AF_Scaler scaler );++ FT_LOCAL( void )+ af_latin_metrics_init_widths( AF_LatinMetrics metrics,+ FT_Face face,+ FT_ULong charcode );++ FT_LOCAL( void )+ af_latin_metrics_check_digits( AF_LatinMetrics metrics,+ FT_Face face );+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** L A T I N G L Y P H A N A L Y S I S *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ enum+ {+ AF_LATIN_HINTS_HORZ_SNAP = 1 << 0, /* enable stem width snapping */+ AF_LATIN_HINTS_VERT_SNAP = 1 << 1, /* enable stem height snapping */+ AF_LATIN_HINTS_STEM_ADJUST = 1 << 2, /* enable stem width/height */+ /* adjustment */+ AF_LATIN_HINTS_MONO = 1 << 3 /* indicate monochrome */+ /* rendering */+ };+++#define AF_LATIN_HINTS_DO_HORZ_SNAP( h ) \+ AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_HORZ_SNAP )++#define AF_LATIN_HINTS_DO_VERT_SNAP( h ) \+ AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_VERT_SNAP )++#define AF_LATIN_HINTS_DO_STEM_ADJUST( h ) \+ AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_STEM_ADJUST )++#define AF_LATIN_HINTS_DO_MONO( h ) \+ AF_HINTS_TEST_OTHER( h, AF_LATIN_HINTS_MONO )+++ /*+ * This shouldn't normally be exported. However, other scripts might+ * like to use this function as-is.+ */+ FT_LOCAL( FT_Error )+ af_latin_hints_compute_segments( AF_GlyphHints hints,+ AF_Dimension dim );++ /*+ * This shouldn't normally be exported. However, other scripts might+ * want to use this function as-is.+ */+ FT_LOCAL( void )+ af_latin_hints_link_segments( AF_GlyphHints hints,+ AF_Dimension dim );++ /*+ * This shouldn't normally be exported. However, other scripts might+ * want to use this function as-is.+ */+ FT_LOCAL( FT_Error )+ af_latin_hints_compute_edges( AF_GlyphHints hints,+ AF_Dimension dim );++ FT_LOCAL( FT_Error )+ af_latin_hints_detect_features( AF_GlyphHints hints,+ AF_Dimension dim );++/* */++FT_END_HEADER++#endif /* __AFLATIN_H__ */+++/* END */
+ src/autofit/aflatin2.c view
@@ -0,0 +1,2345 @@+/***************************************************************************/+/* */+/* aflatin.c */+/* */+/* Auto-fitter hinting routines for latin script (body). */+/* */+/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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 FT_ADVANCES_H++#include "aflatin.h"+#include "aflatin2.h"+#include "aferrors.h"+++#ifdef AF_USE_WARPER+#include "afwarp.h"+#endif++ FT_LOCAL_DEF( FT_Error )+ af_latin2_hints_compute_segments( AF_GlyphHints hints,+ AF_Dimension dim );++ FT_LOCAL_DEF( void )+ af_latin2_hints_link_segments( AF_GlyphHints hints,+ AF_Dimension dim );++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** L A T I N G L O B A L M E T R I C S *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ FT_LOCAL_DEF( void )+ af_latin2_metrics_init_widths( AF_LatinMetrics metrics,+ FT_Face face,+ FT_ULong charcode )+ {+ /* scan the array of segments in each direction */+ AF_GlyphHintsRec hints[1];+++ af_glyph_hints_init( hints, face->memory );++ metrics->axis[AF_DIMENSION_HORZ].width_count = 0;+ metrics->axis[AF_DIMENSION_VERT].width_count = 0;++ {+ FT_Error error;+ FT_UInt glyph_index;+ int dim;+ AF_LatinMetricsRec dummy[1];+ AF_Scaler scaler = &dummy->root.scaler;+++ glyph_index = FT_Get_Char_Index( face, charcode );+ if ( glyph_index == 0 )+ goto Exit;++ error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );+ if ( error || face->glyph->outline.n_points <= 0 )+ goto Exit;++ FT_ZERO( dummy );++ dummy->units_per_em = metrics->units_per_em;+ scaler->x_scale = scaler->y_scale = 0x10000L;+ scaler->x_delta = scaler->y_delta = 0;+ scaler->face = face;+ scaler->render_mode = FT_RENDER_MODE_NORMAL;+ scaler->flags = 0;++ af_glyph_hints_rescale( hints, (AF_ScriptMetrics)dummy );++ error = af_glyph_hints_reload( hints, &face->glyph->outline );+ if ( error )+ goto Exit;++ for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )+ {+ AF_LatinAxis axis = &metrics->axis[dim];+ AF_AxisHints axhints = &hints->axis[dim];+ AF_Segment seg, limit, link;+ FT_UInt num_widths = 0;+++ error = af_latin2_hints_compute_segments( hints,+ (AF_Dimension)dim );+ if ( error )+ goto Exit;++ af_latin2_hints_link_segments( hints,+ (AF_Dimension)dim );++ seg = axhints->segments;+ limit = seg + axhints->num_segments;++ for ( ; seg < limit; seg++ )+ {+ link = seg->link;++ /* we only consider stem segments there! */+ if ( link && link->link == seg && link > seg )+ {+ FT_Pos dist;+++ dist = seg->pos - link->pos;+ if ( dist < 0 )+ dist = -dist;++ if ( num_widths < AF_LATIN_MAX_WIDTHS )+ axis->widths[ num_widths++ ].org = dist;+ }+ }++ af_sort_widths( num_widths, axis->widths );+ axis->width_count = num_widths;+ }++ Exit:+ for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )+ {+ AF_LatinAxis axis = &metrics->axis[dim];+ FT_Pos stdw;+++ stdw = ( axis->width_count > 0 )+ ? axis->widths[0].org+ : AF_LATIN_CONSTANT( metrics, 50 );++ /* let's try 20% of the smallest width */+ axis->edge_distance_threshold = stdw / 5;+ axis->standard_width = stdw;+ axis->extra_light = 0;+ }+ }++ af_glyph_hints_done( hints );+ }++++#define AF_LATIN_MAX_TEST_CHARACTERS 12+++ static const char af_latin2_blue_chars[AF_LATIN_MAX_BLUES][AF_LATIN_MAX_TEST_CHARACTERS+1] =+ {+ "THEZOCQS",+ "HEZLOCUS",+ "fijkdbh",+ "xzroesc",+ "xzroesc",+ "pqgjy"+ };+++ static void+ af_latin2_metrics_init_blues( AF_LatinMetrics metrics,+ FT_Face face )+ {+ FT_Pos flats [AF_LATIN_MAX_TEST_CHARACTERS];+ FT_Pos rounds[AF_LATIN_MAX_TEST_CHARACTERS];+ FT_Int num_flats;+ FT_Int num_rounds;+ FT_Int bb;+ AF_LatinBlue blue;+ FT_Error error;+ AF_LatinAxis axis = &metrics->axis[AF_DIMENSION_VERT];+ FT_GlyphSlot glyph = face->glyph;+++ /* we compute the blues simply by loading each character from the */+ /* 'af_latin2_blue_chars[blues]' string, then compute its top-most or */+ /* bottom-most points (depending on `AF_IS_TOP_BLUE') */++ AF_LOG(( "blue zones computation\n" ));+ AF_LOG(( "------------------------------------------------\n" ));++ for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )+ {+ const char* p = af_latin2_blue_chars[bb];+ const char* limit = p + AF_LATIN_MAX_TEST_CHARACTERS;+ FT_Pos* blue_ref;+ FT_Pos* blue_shoot;+++ AF_LOG(( "blue %3d: ", bb ));++ num_flats = 0;+ num_rounds = 0;++ for ( ; p < limit && *p; p++ )+ {+ FT_UInt glyph_index;+ FT_Int best_point, best_y, best_first, best_last;+ FT_Vector* points;+ FT_Bool round;+++ AF_LOG(( "'%c'", *p ));++ /* load the character in the face -- skip unknown or empty ones */+ glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p );+ if ( glyph_index == 0 )+ continue;++ error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );+ if ( error || glyph->outline.n_points <= 0 )+ continue;++ /* now compute min or max point indices and coordinates */+ points = glyph->outline.points;+ best_point = -1;+ best_y = 0; /* make compiler happy */+ best_first = 0; /* ditto */+ best_last = 0; /* ditto */++ {+ FT_Int nn;+ FT_Int first = 0;+ FT_Int last = -1;+++ for ( nn = 0; nn < glyph->outline.n_contours; first = last+1, nn++ )+ {+ FT_Int old_best_point = best_point;+ FT_Int pp;+++ last = glyph->outline.contours[nn];++ /* Avoid single-point contours since they are never rasterized. */+ /* In some fonts, they correspond to mark attachment points */+ /* which are way outside of the glyph's real outline. */+ if ( last == first )+ continue;++ if ( AF_LATIN_IS_TOP_BLUE( bb ) )+ {+ for ( pp = first; pp <= last; pp++ )+ if ( best_point < 0 || points[pp].y > best_y )+ {+ best_point = pp;+ best_y = points[pp].y;+ }+ }+ else+ {+ for ( pp = first; pp <= last; pp++ )+ if ( best_point < 0 || points[pp].y < best_y )+ {+ best_point = pp;+ best_y = points[pp].y;+ }+ }++ if ( best_point != old_best_point )+ {+ best_first = first;+ best_last = last;+ }+ }+ AF_LOG(( "%5d", best_y ));+ }++ /* 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 */+ {+ FT_Int start, end, prev, next;+ FT_Pos dist;+++ /* now look for the previous and next points that are not on the */+ /* same Y coordinate. Threshold the `closeness'... */+ start = end = best_point;++ do+ {+ prev = start-1;+ if ( prev < best_first )+ prev = best_last;++ dist = points[prev].y - best_y;+ if ( dist < -5 || dist > 5 )+ break;++ start = prev;++ } while ( start != best_point );++ do+ {+ next = end+1;+ if ( next > best_last )+ next = best_first;++ dist = points[next].y - best_y;+ if ( dist < -5 || dist > 5 )+ break;++ end = next;++ } while ( end != best_point );++ /* now, set the `round' flag depending on the segment's kind */+ round = FT_BOOL(+ FT_CURVE_TAG( glyph->outline.tags[start] ) != FT_CURVE_TAG_ON ||+ FT_CURVE_TAG( glyph->outline.tags[ end ] ) != FT_CURVE_TAG_ON );++ AF_LOG(( "%c ", round ? 'r' : 'f' ));+ }++ if ( round )+ rounds[num_rounds++] = best_y;+ else+ flats[num_flats++] = best_y;+ }++ AF_LOG(( "\n" ));++ if ( num_flats == 0 && num_rounds == 0 )+ {+ /*+ * we couldn't find a single glyph to compute this blue zone,+ * we will simply ignore it then+ */+ AF_LOG(( "empty\n" ));+ continue;+ }++ /* we have computed the contents of the `rounds' and `flats' tables, */+ /* now determine the reference and overshoot position of the blue -- */+ /* we simply take the median value after a simple sort */+ af_sort_pos( num_rounds, rounds );+ af_sort_pos( num_flats, flats );++ blue = & axis->blues[axis->blue_count];+ blue_ref = & blue->ref.org;+ blue_shoot = & blue->shoot.org;++ axis->blue_count++;++ if ( num_flats == 0 )+ {+ *blue_ref =+ *blue_shoot = rounds[num_rounds / 2];+ }+ else if ( num_rounds == 0 )+ {+ *blue_ref =+ *blue_shoot = flats[num_flats / 2];+ }+ else+ {+ *blue_ref = flats[num_flats / 2];+ *blue_shoot = rounds[num_rounds / 2];+ }++ /* there are sometimes problems: if the overshoot position of top */+ /* zones is under its reference position, or the opposite for bottom */+ /* zones. We must thus check everything there and correct the errors */+ if ( *blue_shoot != *blue_ref )+ {+ FT_Pos ref = *blue_ref;+ FT_Pos shoot = *blue_shoot;+ FT_Bool over_ref = FT_BOOL( shoot > ref );+++ if ( AF_LATIN_IS_TOP_BLUE( bb ) ^ over_ref )+ *blue_shoot = *blue_ref = ( shoot + ref ) / 2;+ }++ blue->flags = 0;+ if ( AF_LATIN_IS_TOP_BLUE( bb ) )+ blue->flags |= AF_LATIN_BLUE_TOP;++ /*+ * The following flags is used later to adjust the y and x scales+ * in order to optimize the pixel grid alignment of the top of small+ * letters.+ */+ if ( bb == AF_LATIN_BLUE_SMALL_TOP )+ blue->flags |= AF_LATIN_BLUE_ADJUSTMENT;++ AF_LOG(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));+ }++ return;+ }+++ FT_LOCAL_DEF( void )+ af_latin2_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;+++ /* check whether all ASCII digits have the same advance width; */+ /* digit `0' is 0x30 in all supported charmaps */+ for ( i = 0x30; i <= 0x39; i++ )+ {+ FT_UInt glyph_index;+++ glyph_index = FT_Get_Char_Index( face, i );+ if ( glyph_index == 0 )+ continue;++ if ( FT_Get_Advance( face, glyph_index,+ FT_LOAD_NO_SCALE |+ FT_LOAD_NO_HINTING |+ FT_LOAD_IGNORE_TRANSFORM,+ &advance ) )+ continue;++ if ( started )+ {+ if ( advance != old_advance )+ {+ same_width = 0;+ break;+ }+ }+ else+ {+ old_advance = advance;+ started = 1;+ }+ }++ metrics->root.digits_have_same_width = same_width;+ }+++ FT_LOCAL_DEF( FT_Error )+ af_latin2_metrics_init( AF_LatinMetrics metrics,+ FT_Face face )+ {+ FT_Error error = AF_Err_Ok;+ FT_CharMap oldmap = face->charmap;+ FT_UInt ee;++ static const FT_Encoding latin_encodings[] =+ {+ FT_ENCODING_UNICODE,+ FT_ENCODING_APPLE_ROMAN,+ FT_ENCODING_ADOBE_STANDARD,+ FT_ENCODING_ADOBE_LATIN_1,+ FT_ENCODING_NONE /* end of list */+ };+++ metrics->units_per_em = face->units_per_EM;++ /* do we have a latin charmap in there? */+ for ( ee = 0; latin_encodings[ee] != FT_ENCODING_NONE; ee++ )+ {+ error = FT_Select_Charmap( face, latin_encodings[ee] );+ if ( !error )+ break;+ }++ if ( !error )+ {+ /* For now, compute the standard width and height from the `o'. */+ af_latin2_metrics_init_widths( metrics, face, 'o' );+ af_latin2_metrics_init_blues( metrics, face );+ af_latin2_metrics_check_digits( metrics, face );+ }++ FT_Set_Charmap( face, oldmap );+ return AF_Err_Ok;+ }+++ static void+ af_latin2_metrics_scale_dim( AF_LatinMetrics metrics,+ AF_Scaler scaler,+ AF_Dimension dim )+ {+ FT_Fixed scale;+ FT_Pos delta;+ AF_LatinAxis axis;+ FT_UInt nn;+++ if ( dim == AF_DIMENSION_HORZ )+ {+ scale = scaler->x_scale;+ delta = scaler->x_delta;+ }+ else+ {+ scale = scaler->y_scale;+ delta = scaler->y_delta;+ }++ axis = &metrics->axis[dim];++ if ( axis->org_scale == scale && axis->org_delta == delta )+ return;++ axis->org_scale = scale;+ axis->org_delta = delta;++ /*+ * correct Y scale to optimize the alignment of the top of small+ * letters to the pixel grid+ */+ if ( dim == AF_DIMENSION_VERT )+ {+ AF_LatinAxis vaxis = &metrics->axis[AF_DIMENSION_VERT];+ AF_LatinBlue blue = NULL;+++ for ( nn = 0; nn < vaxis->blue_count; nn++ )+ {+ if ( vaxis->blues[nn].flags & AF_LATIN_BLUE_ADJUSTMENT )+ {+ blue = &vaxis->blues[nn];+ break;+ }+ }++ if ( blue )+ {+ FT_Pos scaled = FT_MulFix( blue->shoot.org, scaler->y_scale );+ FT_Pos fitted = ( scaled + 40 ) & ~63;++#if 1+ if ( scaled != fitted )+ {+ scale = FT_MulDiv( scale, fitted, scaled );+ AF_LOG(( "== scaled x-top = %.2g fitted = %.2g, scaling = %.4g\n", scaled/64.0, fitted/64.0, (fitted*1.0)/scaled ));+ }+#endif+ }+ }++ axis->scale = scale;+ axis->delta = delta;++ if ( dim == AF_DIMENSION_HORZ )+ {+ metrics->root.scaler.x_scale = scale;+ metrics->root.scaler.x_delta = delta;+ }+ else+ {+ metrics->root.scaler.y_scale = scale;+ metrics->root.scaler.y_delta = delta;+ }++ /* scale the standard widths */+ for ( nn = 0; nn < axis->width_count; nn++ )+ {+ AF_Width width = axis->widths + nn;+++ width->cur = FT_MulFix( width->org, scale );+ width->fit = width->cur;+ }++ /* an extra-light axis corresponds to a standard width that is */+ /* smaller than 0.75 pixels */+ axis->extra_light =+ (FT_Bool)( FT_MulFix( axis->standard_width, scale ) < 32 + 8 );++ if ( dim == AF_DIMENSION_VERT )+ {+ /* scale the blue zones */+ for ( nn = 0; nn < axis->blue_count; nn++ )+ {+ AF_LatinBlue blue = &axis->blues[nn];+ FT_Pos dist;+++ blue->ref.cur = FT_MulFix( blue->ref.org, scale ) + delta;+ blue->ref.fit = blue->ref.cur;+ blue->shoot.cur = FT_MulFix( blue->shoot.org, scale ) + delta;+ blue->shoot.fit = blue->shoot.cur;+ blue->flags &= ~AF_LATIN_BLUE_ACTIVE;++ /* a blue zone is only active if it is less than 3/4 pixels tall */+ dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale );+ if ( dist <= 48 && dist >= -48 )+ {+ FT_Pos delta1, delta2;++ delta1 = blue->shoot.org - blue->ref.org;+ delta2 = delta1;+ if ( delta1 < 0 )+ delta2 = -delta2;++ delta2 = FT_MulFix( delta2, scale );++ if ( delta2 < 32 )+ delta2 = 0;+ else if ( delta2 < 64 )+ delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & ~31 );+ else+ delta2 = FT_PIX_ROUND( delta2 );++ if ( delta1 < 0 )+ delta2 = -delta2;++ blue->ref.fit = FT_PIX_ROUND( blue->ref.cur );+ blue->shoot.fit = blue->ref.fit + delta2;++ AF_LOG(( ">> activating blue zone %d: ref.cur=%.2g ref.fit=%.2g shoot.cur=%.2g shoot.fit=%.2g\n",+ nn, blue->ref.cur/64.0, blue->ref.fit/64.0,+ blue->shoot.cur/64.0, blue->shoot.fit/64.0 ));++ blue->flags |= AF_LATIN_BLUE_ACTIVE;+ }+ }+ }+ }+++ FT_LOCAL_DEF( void )+ af_latin2_metrics_scale( AF_LatinMetrics metrics,+ AF_Scaler scaler )+ {+ metrics->root.scaler.render_mode = scaler->render_mode;+ metrics->root.scaler.face = scaler->face;++ af_latin2_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ );+ af_latin2_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT );+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** L A T I N G L Y P H A N A L Y S I S *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++#define SORT_SEGMENTS++ FT_LOCAL_DEF( FT_Error )+ af_latin2_hints_compute_segments( AF_GlyphHints hints,+ AF_Dimension dim )+ {+ AF_AxisHints axis = &hints->axis[dim];+ FT_Memory memory = hints->memory;+ FT_Error error = AF_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_ZERO( &seg0 );+ seg0.score = 32000;+ seg0.flags = AF_EDGE_NORMAL;++ major_dir = (AF_Direction)FT_ABS( axis->major_dir );+ segment_dir = major_dir;++ axis->num_segments = 0;++ /* set up (u,v) in each point */+ if ( dim == AF_DIMENSION_HORZ )+ {+ AF_Point point = hints->points;+ AF_Point limit = point + hints->num_points;+++ for ( ; point < limit; point++ )+ {+ point->u = point->fx;+ point->v = point->fy;+ }+ }+ else+ {+ AF_Point point = hints->points;+ AF_Point limit = point + hints->num_points;+++ for ( ; point < limit; point++ )+ {+ point->u = point->fy;+ point->v = point->fx;+ }+ }++ /* do each contour separately */+ for ( ; contour < contour_limit; contour++ )+ {+ AF_Point point = contour[0];+ AF_Point start = point;+ AF_Point last = point->prev;+++ if ( point == last ) /* skip singletons -- just in case */+ continue;++ /* already on an edge ?, backtrack to find its start */+ if ( FT_ABS( point->in_dir ) == major_dir )+ {+ point = point->prev;++ while ( point->in_dir == start->in_dir )+ point = point->prev;+ }+ else /* otherwise, find first segment start, if any */+ {+ while ( FT_ABS( point->out_dir ) != major_dir )+ {+ point = point->next;++ if ( point == start )+ goto NextContour;+ }+ }++ start = point;++ for (;;)+ {+ AF_Point first;+ FT_Pos min_u, min_v, max_u, max_v;++ /* we're at the start of a new segment */+ FT_ASSERT( FT_ABS( point->out_dir ) == major_dir &&+ point->in_dir != point->out_dir );+ first = point;++ min_u = max_u = point->u;+ min_v = max_v = point->v;++ point = point->next;++ while ( point->out_dir == first->out_dir )+ {+ point = point->next;++ if ( point->u < min_u )+ min_u = point->u;++ if ( point->u > max_u )+ max_u = point->u;+ }++ if ( point->v < min_v )+ min_v = point->v;++ if ( point->v > max_v )+ max_v = point->v;++ /* record new segment */+ error = af_axis_hints_new_segment( axis, memory, &segment );+ if ( error )+ goto Exit;++ segment[0] = seg0;+ segment->dir = first->out_dir;+ segment->first = first;+ segment->last = point;+ segment->contour = contour;+ segment->pos = (FT_Short)(( min_u + max_u ) >> 1);+ segment->min_coord = (FT_Short) min_v;+ segment->max_coord = (FT_Short) max_v;+ segment->height = (FT_Short)(max_v - min_v);++ /* a segment is round if it doesn't have successive */+ /* on-curve points. */+ {+ AF_Point pt = first;+ AF_Point last = point;+ AF_Flags f0 = (AF_Flags)(pt->flags & AF_FLAG_CONTROL);+ AF_Flags f1;+++ segment->flags &= ~AF_EDGE_ROUND;++ for ( ; pt != last; f0 = f1 )+ {+ pt = pt->next;+ f1 = (AF_Flags)(pt->flags & AF_FLAG_CONTROL);++ if ( !f0 && !f1 )+ break;++ if ( pt == last )+ segment->flags |= AF_EDGE_ROUND;+ }+ }++ /* this can happen in the case of a degenerate contour+ * e.g. a 2-point vertical contour+ */+ if ( point == start )+ break;++ /* jump to the start of the next segment, if any */+ while ( FT_ABS(point->out_dir) != major_dir )+ {+ point = point->next;++ if ( point == start )+ goto NextContour;+ }+ }++ NextContour:+ ;+ } /* contours */++ /* now slightly increase the height of segments when this makes */+ /* sense -- this is used to better detect and ignore serifs */+ {+ AF_Segment segments = axis->segments;+ AF_Segment segments_end = segments + axis->num_segments;+++ for ( segment = segments; segment < segments_end; segment++ )+ {+ AF_Point first = segment->first;+ AF_Point last = segment->last;+ AF_Point p;+ FT_Pos first_v = first->v;+ FT_Pos last_v = last->v;+++ if ( first == last )+ continue;++ if ( first_v < last_v )+ {+ p = first->prev;+ if ( p->v < first_v )+ segment->height = (FT_Short)( segment->height ++ ( ( first_v - p->v ) >> 1 ) );++ p = last->next;+ if ( p->v > last_v )+ segment->height = (FT_Short)( segment->height ++ ( ( p->v - last_v ) >> 1 ) );+ }+ else+ {+ p = first->prev;+ if ( p->v > first_v )+ segment->height = (FT_Short)( segment->height ++ ( ( p->v - first_v ) >> 1 ) );++ p = last->next;+ if ( p->v < last_v )+ segment->height = (FT_Short)( segment->height ++ ( ( last_v - p->v ) >> 1 ) );+ }+ }+ }++#ifdef AF_SORT_SEGMENTS+ /* place all segments with a negative direction to the start+ * of the array, used to speed up segment linking later...+ */+ {+ AF_Segment segments = axis->segments;+ FT_UInt count = axis->num_segments;+ FT_UInt ii, jj;++ for (ii = 0; ii < count; ii++)+ {+ if ( segments[ii].dir > 0 )+ {+ for (jj = ii+1; jj < count; jj++)+ {+ if ( segments[jj].dir < 0 )+ {+ AF_SegmentRec tmp;++ tmp = segments[ii];+ segments[ii] = segments[jj];+ segments[jj] = tmp;++ break;+ }+ }++ if ( jj == count )+ break;+ }+ }+ axis->mid_segments = ii;+ }+#endif++ Exit:+ return error;+ }+++ FT_LOCAL_DEF( void )+ af_latin2_hints_link_segments( AF_GlyphHints hints,+ AF_Dimension dim )+ {+ AF_AxisHints axis = &hints->axis[dim];+ AF_Segment segments = axis->segments;+ AF_Segment segment_limit = segments + axis->num_segments;+#ifdef AF_SORT_SEGMENTS+ AF_Segment segment_mid = segments + axis->mid_segments;+#endif+ FT_Pos len_threshold, len_score;+ AF_Segment seg1, seg2;+++ len_threshold = AF_LATIN_CONSTANT( hints->metrics, 8 );+ if ( len_threshold == 0 )+ len_threshold = 1;++ len_score = AF_LATIN_CONSTANT( hints->metrics, 6000 );++#ifdef AF_SORT_SEGMENTS+ for ( seg1 = segments; seg1 < segment_mid; seg1++ )+ {+ if ( seg1->dir != axis->major_dir || seg1->first == seg1->last )+ continue;++ for ( seg2 = segment_mid; seg2 < segment_limit; seg2++ )+#else+ /* now compare each segment to the others */+ for ( seg1 = segments; seg1 < segment_limit; seg1++ )+ {+ /* the fake segments are introduced to hint the metrics -- */+ /* we must never link them to anything */+ if ( seg1->dir != axis->major_dir || seg1->first == seg1->last )+ continue;++ for ( seg2 = segments; seg2 < segment_limit; seg2++ )+ if ( seg1->dir + seg2->dir == 0 && seg2->pos > seg1->pos )+#endif+ {+ FT_Pos pos1 = seg1->pos;+ FT_Pos pos2 = seg2->pos;+ FT_Pos dist = pos2 - pos1;+++ if ( dist < 0 )+ continue;++ {+ FT_Pos min = seg1->min_coord;+ FT_Pos max = seg1->max_coord;+ FT_Pos len, score;+++ if ( min < seg2->min_coord )+ min = seg2->min_coord;++ if ( max > seg2->max_coord )+ max = seg2->max_coord;++ len = max - min;+ if ( len >= len_threshold )+ {+ score = dist + len_score / len;+ if ( score < seg1->score )+ {+ seg1->score = score;+ seg1->link = seg2;+ }++ if ( score < seg2->score )+ {+ seg2->score = score;+ seg2->link = seg1;+ }+ }+ }+ }+ }+#if 0+ }+#endif++ /* now, compute the `serif' segments */+ for ( seg1 = segments; seg1 < segment_limit; seg1++ )+ {+ seg2 = seg1->link;++ if ( seg2 )+ {+ if ( seg2->link != seg1 )+ {+ seg1->link = 0;+ seg1->serif = seg2->link;+ }+ }+ }+ }+++ FT_LOCAL_DEF( FT_Error )+ af_latin2_hints_compute_edges( AF_GlyphHints hints,+ AF_Dimension dim )+ {+ AF_AxisHints axis = &hints->axis[dim];+ FT_Error error = AF_Err_Ok;+ FT_Memory memory = hints->memory;+ AF_LatinAxis laxis = &((AF_LatinMetrics)hints->metrics)->axis[dim];++ AF_Segment segments = axis->segments;+ AF_Segment segment_limit = segments + axis->num_segments;+ AF_Segment seg;++ AF_Direction up_dir;+ FT_Fixed scale;+ FT_Pos edge_distance_threshold;+ FT_Pos segment_length_threshold;+++ axis->num_edges = 0;++ scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale+ : hints->y_scale;++ up_dir = ( dim == AF_DIMENSION_HORZ ) ? AF_DIR_UP+ : AF_DIR_RIGHT;++ /*+ * We want to ignore very small (mostly serif) segments, we do that+ * by ignoring those that whose length is less than a given fraction+ * of the standard width. If there is no standard width, we ignore+ * those that are less than a given size in pixels+ *+ * also, unlink serif segments that are linked to segments farther+ * than 50% of the standard width+ */+ if ( dim == AF_DIMENSION_HORZ )+ {+ if ( laxis->width_count > 0 )+ segment_length_threshold = (laxis->standard_width * 10 ) >> 4;+ else+ segment_length_threshold = FT_DivFix( 64, hints->y_scale );+ }+ else+ segment_length_threshold = 0;++ /*********************************************************************/+ /* */+ /* We will begin by generating a sorted table of edges for the */+ /* current direction. To do so, we simply scan each segment and try */+ /* to find an edge in our table that corresponds to its position. */+ /* */+ /* If no edge is found, we create and insert a new edge in the */+ /* sorted table. Otherwise, we simply add the segment to the edge's */+ /* list which will be processed in the second step to compute the */+ /* edge's properties. */+ /* */+ /* Note that the edges table is sorted along the segment/edge */+ /* position. */+ /* */+ /*********************************************************************/++ edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold,+ scale );+ if ( edge_distance_threshold > 64 / 4 )+ edge_distance_threshold = 64 / 4;++ edge_distance_threshold = FT_DivFix( edge_distance_threshold,+ scale );++ for ( seg = segments; seg < segment_limit; seg++ )+ {+ AF_Edge found = 0;+ FT_Int ee;+++ if ( seg->height < segment_length_threshold )+ continue;++ /* A special case for serif edges: If they are smaller than */+ /* 1.5 pixels we ignore them. */+ if ( seg->serif )+ {+ FT_Pos dist = seg->serif->pos - seg->pos;++ if (dist < 0)+ dist = -dist;++ if (dist >= laxis->standard_width >> 1)+ {+ /* unlink this serif, it is too distant from its reference stem */+ seg->serif = NULL;+ }+ else if ( 2*seg->height < 3 * segment_length_threshold )+ continue;+ }++ /* look for an edge corresponding to the segment */+ for ( ee = 0; ee < axis->num_edges; ee++ )+ {+ AF_Edge edge = axis->edges + ee;+ FT_Pos dist;+++ dist = seg->pos - edge->fpos;+ if ( dist < 0 )+ dist = -dist;++ if ( dist < edge_distance_threshold && edge->dir == seg->dir )+ {+ found = edge;+ break;+ }+ }++ if ( !found )+ {+ AF_Edge edge;+++ /* insert a new edge in the list and */+ /* sort according to the position */+ error = af_axis_hints_new_edge( axis, seg->pos, seg->dir, memory, &edge );+ if ( error )+ goto Exit;++ /* add the segment to the new edge's list */+ FT_ZERO( edge );++ edge->first = seg;+ edge->last = seg;+ edge->fpos = seg->pos;+ edge->dir = seg->dir;+ edge->opos = edge->pos = FT_MulFix( seg->pos, scale );+ seg->edge_next = seg;+ }+ else+ {+ /* if an edge was found, simply add the segment to the edge's */+ /* list */+ seg->edge_next = found->first;+ found->last->edge_next = seg;+ found->last = seg;+ }+ }+++ /*********************************************************************/+ /* */+ /* Good, we will now compute each edge's properties according to */+ /* segments found on its position. Basically, these are: */+ /* */+ /* - edge's main direction */+ /* - stem edge, serif edge or both (which defaults to stem then) */+ /* - rounded edge, straight or both (which defaults to straight) */+ /* - link for edge */+ /* */+ /*********************************************************************/++ /* first of all, set the `edge' field in each segment -- this is */+ /* required in order to compute edge links */++ /*+ * Note that removing this loop and setting the `edge' field of each+ * segment directly in the code above slows down execution speed for+ * some reasons on platforms like the Sun.+ */+ {+ AF_Edge edges = axis->edges;+ AF_Edge edge_limit = edges + axis->num_edges;+ AF_Edge edge;+++ for ( edge = edges; edge < edge_limit; edge++ )+ {+ seg = edge->first;+ if ( seg )+ do+ {+ seg->edge = edge;+ seg = seg->edge_next;++ } while ( seg != edge->first );+ }++ /* now, compute each edge properties */+ for ( edge = edges; edge < edge_limit; edge++ )+ {+ FT_Int is_round = 0; /* does it contain round segments? */+ FT_Int is_straight = 0; /* does it contain straight segments? */+ FT_Pos ups = 0; /* number of upwards segments */+ FT_Pos downs = 0; /* number of downwards segments */+++ seg = edge->first;++ do+ {+ FT_Bool is_serif;+++ /* check for roundness of segment */+ if ( seg->flags & AF_EDGE_ROUND )+ is_round++;+ else+ is_straight++;++ /* check for segment direction */+ if ( seg->dir == up_dir )+ ups += seg->max_coord-seg->min_coord;+ else+ downs += seg->max_coord-seg->min_coord;++ /* check for links -- if seg->serif is set, then seg->link must */+ /* be ignored */+ is_serif = (FT_Bool)( seg->serif &&+ seg->serif->edge &&+ seg->serif->edge != edge );++ if ( ( seg->link && seg->link->edge != NULL ) || is_serif )+ {+ AF_Edge edge2;+ AF_Segment seg2;+++ edge2 = edge->link;+ seg2 = seg->link;++ if ( is_serif )+ {+ seg2 = seg->serif;+ edge2 = edge->serif;+ }++ if ( edge2 )+ {+ FT_Pos edge_delta;+ FT_Pos seg_delta;+++ edge_delta = edge->fpos - edge2->fpos;+ if ( edge_delta < 0 )+ edge_delta = -edge_delta;++ seg_delta = seg->pos - seg2->pos;+ if ( seg_delta < 0 )+ seg_delta = -seg_delta;++ if ( seg_delta < edge_delta )+ edge2 = seg2->edge;+ }+ else+ edge2 = seg2->edge;++ if ( is_serif )+ {+ edge->serif = edge2;+ edge2->flags |= AF_EDGE_SERIF;+ }+ else+ edge->link = edge2;+ }++ seg = seg->edge_next;++ } while ( seg != edge->first );++ /* set the round/straight flags */+ edge->flags = AF_EDGE_NORMAL;++ if ( is_round > 0 && is_round >= is_straight )+ edge->flags |= AF_EDGE_ROUND;++#if 0+ /* set the edge's main direction */+ edge->dir = AF_DIR_NONE;++ if ( ups > downs )+ edge->dir = (FT_Char)up_dir;++ else if ( ups < downs )+ edge->dir = (FT_Char)-up_dir;++ else if ( ups == downs )+ edge->dir = 0; /* both up and down! */+#endif++ /* gets rid of serifs if link is set */+ /* XXX: This gets rid of many unpleasant artefacts! */+ /* Example: the `c' in cour.pfa at size 13 */++ if ( edge->serif && edge->link )+ edge->serif = 0;+ }+ }++ Exit:+ return error;+ }+++ FT_LOCAL_DEF( FT_Error )+ af_latin2_hints_detect_features( AF_GlyphHints hints,+ AF_Dimension dim )+ {+ FT_Error error;+++ error = af_latin2_hints_compute_segments( hints, dim );+ if ( !error )+ {+ af_latin2_hints_link_segments( hints, dim );++ error = af_latin2_hints_compute_edges( hints, dim );+ }+ return error;+ }+++ FT_LOCAL_DEF( void )+ af_latin2_hints_compute_blue_edges( AF_GlyphHints hints,+ AF_LatinMetrics metrics )+ {+ AF_AxisHints axis = &hints->axis[ AF_DIMENSION_VERT ];+ AF_Edge edge = axis->edges;+ AF_Edge edge_limit = edge + axis->num_edges;+ AF_LatinAxis latin = &metrics->axis[ AF_DIMENSION_VERT ];+ FT_Fixed scale = latin->scale;+ FT_Pos best_dist0; /* initial threshold */+++ /* compute the initial threshold as a fraction of the EM size */+ best_dist0 = FT_MulFix( metrics->units_per_em / 40, scale );++ if ( best_dist0 > 64 / 2 )+ best_dist0 = 64 / 2;++ /* compute which blue zones are active, i.e. have their scaled */+ /* size < 3/4 pixels */++ /* for each horizontal edge search the blue zone which is closest */+ for ( ; edge < edge_limit; edge++ )+ {+ FT_Int bb;+ AF_Width best_blue = NULL;+ FT_Pos best_dist = best_dist0;++ for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )+ {+ AF_LatinBlue blue = latin->blues + bb;+ FT_Bool is_top_blue, is_major_dir;+++ /* skip inactive blue zones (i.e., those that are too small) */+ if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) )+ continue;++ /* if it is a top zone, check for right edges -- if it is a bottom */+ /* zone, check for left edges */+ /* */+ /* of course, that's for TrueType */+ is_top_blue = (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 );+ is_major_dir = FT_BOOL( edge->dir == axis->major_dir );++ /* if it is a top zone, the edge must be against the major */+ /* direction; if it is a bottom zone, it must be in the major */+ /* direction */+ if ( is_top_blue ^ is_major_dir )+ {+ FT_Pos dist;+ AF_Width compare;+++ /* if it's a rounded edge, compare it to the overshoot position */+ /* if it's a flat edge, compare it to the reference position */+ if ( edge->flags & AF_EDGE_ROUND )+ compare = &blue->shoot;+ else+ compare = &blue->ref;++ dist = edge->fpos - compare->org;+ if (dist < 0)+ dist = -dist;++ dist = FT_MulFix( dist, scale );+ if ( dist < best_dist )+ {+ best_dist = dist;+ best_blue = compare;+ }++#if 0+ /* now, compare it to the overshoot position if the edge is */+ /* rounded, and if the edge is over the reference position of a */+ /* top zone, or under the reference position of a bottom zone */+ if ( edge->flags & AF_EDGE_ROUND && dist != 0 )+ {+ FT_Bool is_under_ref = FT_BOOL( edge->fpos < blue->ref.org );+++ if ( is_top_blue ^ is_under_ref )+ {+ blue = latin->blues + bb;+ dist = edge->fpos - blue->shoot.org;+ if ( dist < 0 )+ dist = -dist;++ dist = FT_MulFix( dist, scale );+ if ( dist < best_dist )+ {+ best_dist = dist;+ best_blue = & blue->shoot;+ }+ }+ }+#endif+ }+ }++ if ( best_blue )+ edge->blue_edge = best_blue;+ }+ }+++ static FT_Error+ af_latin2_hints_init( AF_GlyphHints hints,+ AF_LatinMetrics metrics )+ {+ FT_Render_Mode mode;+ FT_UInt32 scaler_flags, other_flags;+ FT_Face face = metrics->root.scaler.face;+++ af_glyph_hints_rescale( hints, (AF_ScriptMetrics)metrics );++ /*+ * correct x_scale and y_scale if needed, since they may have+ * been modified `af_latin2_metrics_scale_dim' above+ */+ hints->x_scale = metrics->axis[AF_DIMENSION_HORZ].scale;+ hints->x_delta = metrics->axis[AF_DIMENSION_HORZ].delta;+ hints->y_scale = metrics->axis[AF_DIMENSION_VERT].scale;+ hints->y_delta = metrics->axis[AF_DIMENSION_VERT].delta;++ /* compute flags depending on render mode, etc. */+ mode = metrics->root.scaler.render_mode;++#if 0 /* #ifdef AF_USE_WARPER */+ if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )+ {+ metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;+ }+#endif++ scaler_flags = hints->scaler_flags;+ other_flags = 0;++ /*+ * We snap the width of vertical stems for the monochrome and+ * horizontal LCD rendering targets only.+ */+ if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD )+ other_flags |= AF_LATIN_HINTS_HORZ_SNAP;++ /*+ * We snap the width of horizontal stems for the monochrome and+ * vertical LCD rendering targets only.+ */+ if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD_V )+ other_flags |= AF_LATIN_HINTS_VERT_SNAP;++ /*+ * We adjust stems to full pixels only if we don't use the `light' mode.+ */+ if ( mode != FT_RENDER_MODE_LIGHT )+ other_flags |= AF_LATIN_HINTS_STEM_ADJUST;++ if ( mode == FT_RENDER_MODE_MONO )+ other_flags |= AF_LATIN_HINTS_MONO;++ /*+ * In `light' hinting mode we disable horizontal hinting completely.+ * We also do it if the face is italic.+ */+ if ( mode == FT_RENDER_MODE_LIGHT ||+ (face->style_flags & FT_STYLE_FLAG_ITALIC) != 0 )+ scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL;++ hints->scaler_flags = scaler_flags;+ hints->other_flags = other_flags;++ return 0;+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** L A T I N G L Y P H G R I D - F I T T I N G *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /* snap a given width in scaled coordinates to one of the */+ /* current standard widths */++ static FT_Pos+ af_latin2_snap_width( AF_Width widths,+ FT_Int count,+ FT_Pos width )+ {+ int n;+ FT_Pos best = 64 + 32 + 2;+ FT_Pos reference = width;+ FT_Pos scaled;+++ for ( n = 0; n < count; n++ )+ {+ FT_Pos w;+ FT_Pos dist;+++ w = widths[n].cur;+ dist = width - w;+ if ( dist < 0 )+ dist = -dist;+ if ( dist < best )+ {+ best = dist;+ reference = w;+ }+ }++ scaled = FT_PIX_ROUND( reference );++ if ( width >= reference )+ {+ if ( width < scaled + 48 )+ width = reference;+ }+ else+ {+ if ( width > scaled - 48 )+ width = reference;+ }++ return width;+ }+++ /* compute the snapped width of a given stem */++ static FT_Pos+ af_latin2_compute_stem_width( AF_GlyphHints hints,+ AF_Dimension dim,+ FT_Pos width,+ AF_Edge_Flags base_flags,+ AF_Edge_Flags stem_flags )+ {+ AF_LatinMetrics metrics = (AF_LatinMetrics) hints->metrics;+ AF_LatinAxis axis = & metrics->axis[dim];+ FT_Pos dist = width;+ FT_Int sign = 0;+ FT_Int vertical = ( dim == AF_DIMENSION_VERT );+++ FT_UNUSED(base_flags);++ if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) ||+ axis->extra_light )+ return width;++ if ( dist < 0 )+ {+ dist = -width;+ sign = 1;+ }++ if ( ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) ||+ ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) )+ {+ /* smooth hinting process: very lightly quantize the stem width */++ /* leave the widths of serifs alone */++ if ( ( stem_flags & AF_EDGE_SERIF ) && vertical && ( dist < 3 * 64 ) )+ goto Done_Width;++#if 0+ else if ( ( base_flags & AF_EDGE_ROUND ) )+ {+ if ( dist < 80 )+ dist = 64;+ }+ else if ( dist < 56 )+ dist = 56;+#endif+ if ( axis->width_count > 0 )+ {+ FT_Pos delta;+++ /* compare to standard width */+ if ( axis->width_count > 0 )+ {+ delta = dist - axis->widths[0].cur;++ if ( delta < 0 )+ delta = -delta;++ if ( delta < 40 )+ {+ dist = axis->widths[0].cur;+ if ( dist < 48 )+ dist = 48;++ goto Done_Width;+ }+ }++ if ( dist < 3 * 64 )+ {+ delta = dist & 63;+ dist &= -64;++ if ( delta < 10 )+ dist += delta;++ else if ( delta < 32 )+ dist += 10;++ else if ( delta < 54 )+ dist += 54;++ else+ dist += delta;+ }+ else+ dist = ( dist + 32 ) & ~63;+ }+ }+ else+ {+ /* strong hinting process: snap the stem width to integer pixels */+ FT_Pos org_dist = dist;+++ dist = af_latin2_snap_width( axis->widths, axis->width_count, dist );++ if ( vertical )+ {+ /* in the case of vertical hinting, always round */+ /* the stem heights to integer pixels */++ if ( dist >= 64 )+ dist = ( dist + 16 ) & ~63;+ else+ dist = 64;+ }+ else+ {+ if ( AF_LATIN_HINTS_DO_MONO( hints ) )+ {+ /* monochrome horizontal hinting: snap widths to integer pixels */+ /* with a different threshold */++ if ( dist < 64 )+ dist = 64;+ else+ dist = ( dist + 32 ) & ~63;+ }+ else+ {+ /* for horizontal anti-aliased hinting, we adopt a more subtle */+ /* approach: we strengthen small stems, round stems whose size */+ /* is between 1 and 2 pixels to an integer, otherwise nothing */++ if ( dist < 48 )+ dist = ( dist + 64 ) >> 1;++ else if ( dist < 128 )+ {+ /* We only round to an integer width if the corresponding */+ /* distortion is less than 1/4 pixel. Otherwise this */+ /* makes everything worse since the diagonals, which are */+ /* not hinted, appear a lot bolder or thinner than the */+ /* vertical stems. */++ FT_Int delta;+++ dist = ( dist + 22 ) & ~63;+ delta = dist - org_dist;+ if ( delta < 0 )+ delta = -delta;++ if (delta >= 16)+ {+ dist = org_dist;+ if ( dist < 48 )+ dist = ( dist + 64 ) >> 1;+ }+ }+ else+ /* round otherwise to prevent color fringes in LCD mode */+ dist = ( dist + 32 ) & ~63;+ }+ }+ }++ Done_Width:+ if ( sign )+ dist = -dist;++ return dist;+ }+++ /* align one stem edge relative to the previous stem edge */++ static void+ af_latin2_align_linked_edge( AF_GlyphHints hints,+ AF_Dimension dim,+ AF_Edge base_edge,+ AF_Edge stem_edge )+ {+ FT_Pos dist = stem_edge->opos - base_edge->opos;++ FT_Pos fitted_width = af_latin2_compute_stem_width(+ hints, dim, dist,+ (AF_Edge_Flags)base_edge->flags,+ (AF_Edge_Flags)stem_edge->flags );+++ stem_edge->pos = base_edge->pos + fitted_width;++ AF_LOG(( "LINK: edge %d (opos=%.2f) linked to (%.2f), "+ "dist was %.2f, now %.2f\n",+ stem_edge-hints->axis[dim].edges, stem_edge->opos / 64.0,+ stem_edge->pos / 64.0, dist / 64.0, fitted_width / 64.0 ));+ }+++ static void+ af_latin2_align_serif_edge( AF_GlyphHints hints,+ AF_Edge base,+ AF_Edge serif )+ {+ FT_UNUSED( hints );++ serif->pos = base->pos + (serif->opos - base->opos);+ }+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** E D G E H I N T I N G ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ FT_LOCAL_DEF( void )+ af_latin2_hint_edges( AF_GlyphHints hints,+ AF_Dimension dim )+ {+ AF_AxisHints axis = &hints->axis[dim];+ AF_Edge edges = axis->edges;+ AF_Edge edge_limit = edges + axis->num_edges;+ AF_Edge edge;+ AF_Edge anchor = 0;+ FT_Int has_serifs = 0;+ FT_Pos anchor_drift = 0;++++ AF_LOG(( "==== hinting %s edges =====\n", dim == AF_DIMENSION_HORZ ? "vertical" : "horizontal" ));++ /* we begin by aligning all stems relative to the blue zone */+ /* if needed -- that's only for horizontal edges */++ if ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_BLUES( hints ) )+ {+ for ( edge = edges; edge < edge_limit; edge++ )+ {+ AF_Width blue;+ AF_Edge edge1, edge2;+++ if ( edge->flags & AF_EDGE_DONE )+ continue;++ blue = edge->blue_edge;+ edge1 = NULL;+ edge2 = edge->link;++ if ( blue )+ {+ edge1 = edge;+ }+ else if ( edge2 && edge2->blue_edge )+ {+ blue = edge2->blue_edge;+ edge1 = edge2;+ edge2 = edge;+ }++ if ( !edge1 )+ continue;++ AF_LOG(( "BLUE: edge %d (opos=%.2f) snapped to (%.2f), "+ "was (%.2f)\n",+ edge1-edges, edge1->opos / 64.0, blue->fit / 64.0,+ edge1->pos / 64.0 ));++ edge1->pos = blue->fit;+ edge1->flags |= AF_EDGE_DONE;++ if ( edge2 && !edge2->blue_edge )+ {+ af_latin2_align_linked_edge( hints, dim, edge1, edge2 );+ edge2->flags |= AF_EDGE_DONE;+ }++ if ( !anchor )+ {+ anchor = edge;++ anchor_drift = (anchor->pos - anchor->opos);+ if (edge2)+ anchor_drift = (anchor_drift + (edge2->pos - edge2->opos)) >> 1;+ }+ }+ }++ /* now we will align all stem edges, trying to maintain the */+ /* relative order of stems in the glyph */+ for ( edge = edges; edge < edge_limit; edge++ )+ {+ AF_Edge edge2;+++ if ( edge->flags & AF_EDGE_DONE )+ continue;++ /* skip all non-stem edges */+ edge2 = edge->link;+ if ( !edge2 )+ {+ has_serifs++;+ continue;+ }++ /* now align the stem */++ /* this should not happen, but it's better to be safe */+ if ( edge2->blue_edge )+ {+ AF_LOG(( "ASSERTION FAILED for edge %d\n", edge2-edges ));++ af_latin2_align_linked_edge( hints, dim, edge2, edge );+ edge->flags |= AF_EDGE_DONE;+ continue;+ }++ if ( !anchor )+ {+ FT_Pos org_len, org_center, cur_len;+ FT_Pos cur_pos1, error1, error2, u_off, d_off;+++ org_len = edge2->opos - edge->opos;+ cur_len = af_latin2_compute_stem_width(+ hints, dim, org_len,+ (AF_Edge_Flags)edge->flags,+ (AF_Edge_Flags)edge2->flags );+ if ( cur_len <= 64 )+ u_off = d_off = 32;+ else+ {+ u_off = 38;+ d_off = 26;+ }++ if ( cur_len < 96 )+ {+ org_center = edge->opos + ( org_len >> 1 );++ cur_pos1 = FT_PIX_ROUND( org_center );++ error1 = org_center - ( cur_pos1 - u_off );+ if ( error1 < 0 )+ error1 = -error1;++ error2 = org_center - ( cur_pos1 + d_off );+ if ( error2 < 0 )+ error2 = -error2;++ if ( error1 < error2 )+ cur_pos1 -= u_off;+ else+ cur_pos1 += d_off;++ edge->pos = cur_pos1 - cur_len / 2;+ edge2->pos = edge->pos + cur_len;+ }+ else+ edge->pos = FT_PIX_ROUND( edge->opos );++ AF_LOG(( "ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f) "+ "snapped to (%.2f) (%.2f)\n",+ edge-edges, edge->opos / 64.0,+ edge2-edges, edge2->opos / 64.0,+ edge->pos / 64.0, edge2->pos / 64.0 ));+ anchor = edge;++ edge->flags |= AF_EDGE_DONE;++ af_latin2_align_linked_edge( hints, dim, edge, edge2 );++ edge2->flags |= AF_EDGE_DONE;++ anchor_drift = ( (anchor->pos - anchor->opos) ++ (edge2->pos - edge2->opos)) >> 1;++ AF_LOG(( "DRIFT: %.2f\n", anchor_drift/64.0 ));+ }+ else+ {+ FT_Pos org_pos, org_len, org_center, cur_center, cur_len;+ FT_Pos org_left, org_right;+++ org_pos = edge->opos + anchor_drift;+ org_len = edge2->opos - edge->opos;+ org_center = org_pos + ( org_len >> 1 );++ cur_len = af_latin2_compute_stem_width(+ hints, dim, org_len,+ (AF_Edge_Flags)edge->flags,+ (AF_Edge_Flags)edge2->flags );++ org_left = org_pos + ((org_len - cur_len) >> 1);+ org_right = org_pos + ((org_len + cur_len) >> 1);++ AF_LOG(( "ALIGN: left=%.2f right=%.2f ", org_left/64.0, org_right/64.0 ));+ cur_center = org_center;++ if ( edge2->flags & AF_EDGE_DONE )+ {+ AF_LOG(( "\n" ));+ edge->pos = edge2->pos - cur_len;+ }+ else+ {+ /* we want to compare several displacement, and choose+ * the one that increases fitness while minimizing+ * distortion as well+ */+ FT_Pos displacements[6], scores[6], org, fit, delta;+ FT_UInt count = 0;++ /* note: don't even try to fit tiny stems */+ if ( cur_len < 32 )+ {+ AF_LOG(( "tiny stem\n" ));+ goto AlignStem;+ }++ /* if the span is within a single pixel, don't touch it */+ if ( FT_PIX_FLOOR(org_left) == FT_PIX_CEIL(org_right) )+ {+ AF_LOG(( "single pixel stem\n" ));+ goto AlignStem;+ }++ if (cur_len <= 96)+ {+ /* we want to avoid the absolute worst case which is+ * when the left and right edges of the span each represent+ * about 50% of the gray. we'd better want to change this+ * to 25/75%, since this is much more pleasant to the eye with+ * very acceptable distortion+ */+ FT_Pos frac_left = (org_left) & 63;+ FT_Pos frac_right = (org_right) & 63;++ if ( frac_left >= 22 && frac_left <= 42 &&+ frac_right >= 22 && frac_right <= 42 )+ {+ org = frac_left;+ fit = (org <= 32) ? 16 : 48;+ delta = FT_ABS(fit - org);+ displacements[count] = fit - org;+ scores[count++] = delta;+ AF_LOG(( "dispA=%.2f (%d) ", (fit - org)/64.0, delta ));++ org = frac_right;+ fit = (org <= 32) ? 16 : 48;+ delta = FT_ABS(fit - org);+ displacements[count] = fit - org;+ scores[count++] = delta;+ AF_LOG(( "dispB=%.2f (%d) ", (fit - org)/64.0, delta ));+ }+ }++ /* snapping the left edge to the grid */+ org = org_left;+ fit = FT_PIX_ROUND(org);+ delta = FT_ABS(fit - org);+ displacements[count] = fit - org;+ scores[count++] = delta;+ AF_LOG(( "dispC=%.2f (%d) ", (fit - org)/64.0, delta ));++ /* snapping the right edge to the grid */+ org = org_right;+ fit = FT_PIX_ROUND(org);+ delta = FT_ABS(fit - org);+ displacements[count] = fit - org;+ scores[count++] = delta;+ AF_LOG(( "dispD=%.2f (%d) ", (fit - org)/64.0, delta ));++ /* now find the best displacement */+ {+ FT_Pos best_score = scores[0];+ FT_Pos best_disp = displacements[0];+ FT_UInt nn;++ for (nn = 1; nn < count; nn++)+ {+ if (scores[nn] < best_score)+ {+ best_score = scores[nn];+ best_disp = displacements[nn];+ }+ }++ cur_center = org_center + best_disp;+ }+ AF_LOG(( "\n" ));+ }++ AlignStem:+ edge->pos = cur_center - (cur_len >> 1);+ edge2->pos = edge->pos + cur_len;++ AF_LOG(( "STEM1: %d (opos=%.2f) to %d (opos=%.2f) "+ "snapped to (%.2f) and (%.2f), org_len = %.2f cur_len=%.2f\n",+ edge-edges, edge->opos / 64.0,+ edge2-edges, edge2->opos / 64.0,+ edge->pos / 64.0, edge2->pos / 64.0,+ org_len / 64.0, cur_len / 64.0 ));++ edge->flags |= AF_EDGE_DONE;+ edge2->flags |= AF_EDGE_DONE;++ if ( edge > edges && edge->pos < edge[-1].pos )+ {+ AF_LOG(( "BOUND: %d (pos=%.2f) to (%.2f)\n",+ edge-edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));+ edge->pos = edge[-1].pos;+ }+ }+ }++ /* make sure that lowercase m's maintain their symmetry */++ /* In general, lowercase m's have six vertical edges if they are sans */+ /* serif, or twelve if they are with serifs. This implementation is */+ /* based on that assumption, and seems to work very well with most */+ /* faces. However, if for a certain face this assumption is not */+ /* true, the m is just rendered like before. In addition, any stem */+ /* correction will only be applied to symmetrical glyphs (even if the */+ /* glyph is not an m), so the potential for unwanted distortion is */+ /* relatively low. */++ /* We don't handle horizontal edges since we can't easily assure that */+ /* the third (lowest) stem aligns with the base line; it might end up */+ /* one pixel higher or lower. */++#if 0+ {+ FT_Int n_edges = edge_limit - edges;+++ if ( dim == AF_DIMENSION_HORZ && ( n_edges == 6 || n_edges == 12 ) )+ {+ AF_Edge edge1, edge2, edge3;+ FT_Pos dist1, dist2, span, delta;+++ if ( n_edges == 6 )+ {+ edge1 = edges;+ edge2 = edges + 2;+ edge3 = edges + 4;+ }+ else+ {+ edge1 = edges + 1;+ edge2 = edges + 5;+ edge3 = edges + 9;+ }++ dist1 = edge2->opos - edge1->opos;+ dist2 = edge3->opos - edge2->opos;++ span = dist1 - dist2;+ if ( span < 0 )+ span = -span;++ if ( span < 8 )+ {+ delta = edge3->pos - ( 2 * edge2->pos - edge1->pos );+ edge3->pos -= delta;+ if ( edge3->link )+ edge3->link->pos -= delta;++ /* move the serifs along with the stem */+ if ( n_edges == 12 )+ {+ ( edges + 8 )->pos -= delta;+ ( edges + 11 )->pos -= delta;+ }++ edge3->flags |= AF_EDGE_DONE;+ if ( edge3->link )+ edge3->link->flags |= AF_EDGE_DONE;+ }+ }+ }+#endif++ if ( has_serifs || !anchor )+ {+ /*+ * now hint the remaining edges (serifs and single) in order+ * to complete our processing+ */+ for ( edge = edges; edge < edge_limit; edge++ )+ {+ FT_Pos delta;+++ if ( edge->flags & AF_EDGE_DONE )+ continue;++ delta = 1000;++ if ( edge->serif )+ {+ delta = edge->serif->opos - edge->opos;+ if ( delta < 0 )+ delta = -delta;+ }++ if ( delta < 64 + 16 )+ {+ af_latin2_align_serif_edge( hints, edge->serif, edge );+ AF_LOG(( "SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f) "+ "aligned to (%.2f)\n",+ edge-edges, edge->opos / 64.0,+ edge->serif - edges, edge->serif->opos / 64.0,+ edge->pos / 64.0 ));+ }+ else if ( !anchor )+ {+ AF_LOG(( "SERIF_ANCHOR: edge %d (opos=%.2f) snapped to (%.2f)\n",+ edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));+ edge->pos = FT_PIX_ROUND( edge->opos );+ anchor = edge;+ }+ else+ {+ AF_Edge before, after;+++ for ( before = edge - 1; before >= edges; before-- )+ if ( before->flags & AF_EDGE_DONE )+ break;++ for ( after = edge + 1; after < edge_limit; after++ )+ if ( after->flags & AF_EDGE_DONE )+ break;++ if ( before >= edges && before < edge &&+ after < edge_limit && after > edge )+ {+ if ( after->opos == before->opos )+ edge->pos = before->pos;+ else+ edge->pos = before->pos ++ FT_MulDiv( edge->opos - before->opos,+ after->pos - before->pos,+ after->opos - before->opos );+ AF_LOG(( "SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f) from %d (opos=%.2f)\n",+ edge-edges, edge->opos / 64.0, edge->pos / 64.0, before - edges, before->opos / 64.0 ));+ }+ else+ {+ edge->pos = anchor->pos + (( edge->opos - anchor->opos + 16) & ~31);++ AF_LOG(( "SERIF_LINK2: edge %d (opos=%.2f) snapped to (%.2f)\n",+ edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));+ }+ }++ edge->flags |= AF_EDGE_DONE;++ if ( edge > edges && edge->pos < edge[-1].pos )+ edge->pos = edge[-1].pos;++ if ( edge + 1 < edge_limit &&+ edge[1].flags & AF_EDGE_DONE &&+ edge->pos > edge[1].pos )+ edge->pos = edge[1].pos;+ }+ }+ }+++ static FT_Error+ af_latin2_hints_apply( AF_GlyphHints hints,+ FT_Outline* outline,+ AF_LatinMetrics metrics )+ {+ FT_Error error;+ int dim;+++ error = af_glyph_hints_reload( hints, outline );+ if ( error )+ goto Exit;++ /* analyze glyph outline */+#ifdef AF_USE_WARPER+ if ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ||+ AF_HINTS_DO_HORIZONTAL( hints ) )+#else+ if ( AF_HINTS_DO_HORIZONTAL( hints ) )+#endif+ {+ error = af_latin2_hints_detect_features( hints, AF_DIMENSION_HORZ );+ if ( error )+ goto Exit;+ }++ if ( AF_HINTS_DO_VERTICAL( hints ) )+ {+ error = af_latin2_hints_detect_features( hints, AF_DIMENSION_VERT );+ if ( error )+ goto Exit;++ af_latin2_hints_compute_blue_edges( hints, metrics );+ }++ /* grid-fit the outline */+ for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )+ {+#ifdef AF_USE_WARPER+ if ( ( dim == AF_DIMENSION_HORZ &&+ metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ) )+ {+ AF_WarperRec warper;+ FT_Fixed scale;+ FT_Pos delta;+++ af_warper_compute( &warper, hints, dim, &scale, &delta );+ af_glyph_hints_scale_dim( hints, dim, scale, delta );+ continue;+ }+#endif++ if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) ||+ ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) ) )+ {+ af_latin2_hint_edges( hints, (AF_Dimension)dim );+ af_glyph_hints_align_edge_points( hints, (AF_Dimension)dim );+ af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim );+ af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim );+ }+ }+ af_glyph_hints_save( hints, outline );++ Exit:+ return error;+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** L A T I N S C R I P T C L A S S *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+++ static const AF_Script_UniRangeRec af_latin2_uniranges[] =+ {+ AF_UNIRANGE_REC( 32UL, 127UL ), /* XXX: TODO: Add new Unicode ranges here! */+ AF_UNIRANGE_REC( 160UL, 255UL ),+ AF_UNIRANGE_REC( 0UL, 0UL )+ };+++ AF_DEFINE_SCRIPT_CLASS(af_latin2_script_class,+ AF_SCRIPT_LATIN2,+ af_latin2_uniranges,++ sizeof( AF_LatinMetricsRec ),++ (AF_Script_InitMetricsFunc) af_latin2_metrics_init,+ (AF_Script_ScaleMetricsFunc)af_latin2_metrics_scale,+ (AF_Script_DoneMetricsFunc) NULL,++ (AF_Script_InitHintsFunc) af_latin2_hints_init,+ (AF_Script_ApplyHintsFunc) af_latin2_hints_apply+ )+++/* END */
+ src/autofit/aflatin2.h view
@@ -0,0 +1,39 @@+/***************************************************************************/+/* */+/* aflatin2.h */+/* */+/* Auto-fitter hinting routines for latin script (specification). */+/* */+/* Copyright 2003, 2004, 2005, 2006, 2007 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 __AFLATIN2_H__+#define __AFLATIN2_H__++#include "afhints.h"+++FT_BEGIN_HEADER+++ /* the latin-specific script class */++ AF_DECLARE_SCRIPT_CLASS(af_latin2_script_class)++/* */++FT_END_HEADER++#endif /* __AFLATIN_H__ */+++/* END */
+ src/autofit/afloader.c view
@@ -0,0 +1,539 @@+/***************************************************************************/+/* */+/* afloader.c */+/* */+/* Auto-fitter glyph loading routines (body). */+/* */+/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 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 "afloader.h"+#include "afhints.h"+#include "afglobal.h"+#include "aferrors.h"+++ FT_LOCAL_DEF( FT_Error )+ af_loader_init( AF_Loader loader,+ FT_Memory memory )+ {+ FT_ZERO( loader );++ af_glyph_hints_init( &loader->hints, memory );+#ifdef AF_DEBUG+ _af_debug_hints = &loader->hints;+#endif+ return FT_GlyphLoader_New( memory, &loader->gloader );+ }+++ FT_LOCAL_DEF( FT_Error )+ af_loader_reset( AF_Loader loader,+ FT_Face face )+ {+ FT_Error error = AF_Err_Ok;+++ loader->face = face;+ loader->globals = (AF_FaceGlobals)face->autohint.data;++ FT_GlyphLoader_Rewind( loader->gloader );++ if ( loader->globals == NULL )+ {+ error = af_face_globals_new( face, &loader->globals );+ if ( !error )+ {+ face->autohint.data =+ (FT_Pointer)loader->globals;+ face->autohint.finalizer =+ (FT_Generic_Finalizer)af_face_globals_free;+ }+ }++ return error;+ }+++ FT_LOCAL_DEF( void )+ af_loader_done( AF_Loader loader )+ {+ af_glyph_hints_done( &loader->hints );++ loader->face = NULL;+ loader->globals = NULL;++#ifdef AF_DEBUG+ _af_debug_hints = NULL;+#endif+ FT_GlyphLoader_Done( loader->gloader );+ loader->gloader = NULL;+ }+++ static FT_Error+ af_loader_load_g( AF_Loader loader,+ AF_Scaler scaler,+ FT_UInt glyph_index,+ FT_Int32 load_flags,+ FT_UInt depth )+ {+ FT_Error error;+ FT_Face face = loader->face;+ FT_GlyphLoader gloader = loader->gloader;+ AF_ScriptMetrics metrics = loader->metrics;+ AF_GlyphHints hints = &loader->hints;+ FT_GlyphSlot slot = face->glyph;+ FT_Slot_Internal internal = slot->internal;+++ error = FT_Load_Glyph( face, glyph_index, load_flags );+ if ( error )+ goto Exit;++ loader->transformed = internal->glyph_transformed;+ if ( loader->transformed )+ {+ FT_Matrix inverse;+++ loader->trans_matrix = internal->glyph_matrix;+ loader->trans_delta = internal->glyph_delta;++ inverse = loader->trans_matrix;+ FT_Matrix_Invert( &inverse );+ FT_Vector_Transform( &loader->trans_delta, &inverse );+ }++ /* set linear metrics */+ slot->linearHoriAdvance = slot->metrics.horiAdvance;+ slot->linearVertAdvance = slot->metrics.vertAdvance;++ switch ( slot->format )+ {+ case FT_GLYPH_FORMAT_OUTLINE:+ /* translate the loaded glyph when an internal transform is needed */+ if ( loader->transformed )+ FT_Outline_Translate( &slot->outline,+ loader->trans_delta.x,+ loader->trans_delta.y );++ /* copy the outline points in the loader's current */+ /* extra points which is used to keep original glyph coordinates */+ error = FT_GLYPHLOADER_CHECK_POINTS( gloader,+ slot->outline.n_points + 4,+ slot->outline.n_contours );+ if ( error )+ goto Exit;++ FT_ARRAY_COPY( gloader->current.outline.points,+ slot->outline.points,+ slot->outline.n_points );++ FT_ARRAY_COPY( gloader->current.outline.contours,+ slot->outline.contours,+ slot->outline.n_contours );++ FT_ARRAY_COPY( gloader->current.outline.tags,+ slot->outline.tags,+ slot->outline.n_points );++ gloader->current.outline.n_points = slot->outline.n_points;+ gloader->current.outline.n_contours = slot->outline.n_contours;++ /* compute original horizontal phantom points (and ignore */+ /* vertical ones) */+ loader->pp1.x = hints->x_delta;+ loader->pp1.y = hints->y_delta;+ loader->pp2.x = FT_MulFix( slot->metrics.horiAdvance,+ hints->x_scale ) + hints->x_delta;+ loader->pp2.y = hints->y_delta;++ /* be sure to check for spacing glyphs */+ if ( slot->outline.n_points == 0 )+ goto Hint_Metrics;++ /* now load the slot image into the auto-outline and run the */+ /* automatic hinting process */+ if ( metrics->clazz->script_hints_apply )+ metrics->clazz->script_hints_apply( hints,+ &gloader->current.outline,+ metrics );++ /* we now need to hint the metrics according to the change in */+ /* width/positioning that occurred during the hinting process */+ if ( scaler->render_mode != FT_RENDER_MODE_LIGHT )+ {+ FT_Pos old_rsb, old_lsb, new_lsb;+ FT_Pos pp1x_uh, pp2x_uh;+ AF_AxisHints axis = &hints->axis[AF_DIMENSION_HORZ];+ AF_Edge edge1 = axis->edges; /* leftmost edge */+ AF_Edge edge2 = edge1 ++ axis->num_edges - 1; /* rightmost edge */+++ if ( axis->num_edges > 1 && AF_HINTS_DO_ADVANCE( hints ) )+ {+ old_rsb = loader->pp2.x - edge2->opos;+ old_lsb = edge1->opos;+ new_lsb = edge1->pos;++ /* remember unhinted values to later account */+ /* for rounding errors */++ pp1x_uh = new_lsb - old_lsb;+ pp2x_uh = edge2->pos + old_rsb;++ /* prefer too much space over too little space */+ /* for very small sizes */++ if ( old_lsb < 24 )+ pp1x_uh -= 8;++ if ( old_rsb < 24 )+ pp2x_uh += 8;++ loader->pp1.x = FT_PIX_ROUND( pp1x_uh );+ loader->pp2.x = FT_PIX_ROUND( pp2x_uh );++ if ( loader->pp1.x >= new_lsb && old_lsb > 0 )+ loader->pp1.x -= 64;++ if ( loader->pp2.x <= edge2->pos && old_rsb > 0 )+ loader->pp2.x += 64;++ slot->lsb_delta = loader->pp1.x - pp1x_uh;+ slot->rsb_delta = loader->pp2.x - pp2x_uh;+ }+ else+ {+ FT_Pos pp1x = loader->pp1.x;+ FT_Pos pp2x = loader->pp2.x;+++ loader->pp1.x = FT_PIX_ROUND( pp1x );+ loader->pp2.x = FT_PIX_ROUND( pp2x );++ slot->lsb_delta = loader->pp1.x - pp1x;+ slot->rsb_delta = loader->pp2.x - pp2x;+ }+ }+ else+ {+ FT_Pos pp1x = loader->pp1.x;+ FT_Pos pp2x = loader->pp2.x;+++ loader->pp1.x = FT_PIX_ROUND( pp1x + hints->xmin_delta );+ loader->pp2.x = FT_PIX_ROUND( pp2x + hints->xmax_delta );++ slot->lsb_delta = loader->pp1.x - pp1x;+ slot->rsb_delta = loader->pp2.x - pp2x;+ }++ /* good, we simply add the glyph to our loader's base */+ FT_GlyphLoader_Add( gloader );+ break;++ case FT_GLYPH_FORMAT_COMPOSITE:+ {+ FT_UInt nn, num_subglyphs = slot->num_subglyphs;+ FT_UInt num_base_subgs, start_point;+ FT_SubGlyph subglyph;+++ start_point = gloader->base.outline.n_points;++ /* first of all, copy the subglyph descriptors in the glyph loader */+ error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs );+ if ( error )+ goto Exit;++ FT_ARRAY_COPY( gloader->current.subglyphs,+ slot->subglyphs,+ num_subglyphs );++ gloader->current.num_subglyphs = num_subglyphs;+ num_base_subgs = gloader->base.num_subglyphs;++ /* now, read each subglyph independently */+ for ( nn = 0; nn < num_subglyphs; nn++ )+ {+ FT_Vector pp1, pp2;+ FT_Pos x, y;+ FT_UInt num_points, num_new_points, num_base_points;+++ /* gloader.current.subglyphs can change during glyph loading due */+ /* to re-allocation -- we must recompute the current subglyph on */+ /* each iteration */+ subglyph = gloader->base.subglyphs + num_base_subgs + nn;++ pp1 = loader->pp1;+ pp2 = loader->pp2;++ num_base_points = gloader->base.outline.n_points;++ error = af_loader_load_g( loader, scaler, subglyph->index,+ load_flags, depth + 1 );+ if ( error )+ goto Exit;++ /* recompute subglyph pointer */+ subglyph = gloader->base.subglyphs + num_base_subgs + nn;++ if ( subglyph->flags & FT_SUBGLYPH_FLAG_USE_MY_METRICS )+ {+ pp1 = loader->pp1;+ pp2 = loader->pp2;+ }+ else+ {+ loader->pp1 = pp1;+ loader->pp2 = pp2;+ }++ num_points = gloader->base.outline.n_points;+ num_new_points = num_points - num_base_points;++ /* now perform the transform required for this subglyph */++ if ( subglyph->flags & ( FT_SUBGLYPH_FLAG_SCALE |+ FT_SUBGLYPH_FLAG_XY_SCALE |+ FT_SUBGLYPH_FLAG_2X2 ) )+ {+ FT_Vector* cur = gloader->base.outline.points ++ num_base_points;+ FT_Vector* limit = cur + num_new_points;+++ for ( ; cur < limit; cur++ )+ FT_Vector_Transform( cur, &subglyph->transform );+ }++ /* apply offset */++ if ( !( subglyph->flags & FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES ) )+ {+ FT_Int k = subglyph->arg1;+ FT_UInt l = subglyph->arg2;+ FT_Vector* p1;+ FT_Vector* p2;+++ if ( start_point + k >= num_base_points ||+ l >= (FT_UInt)num_new_points )+ {+ error = AF_Err_Invalid_Composite;+ goto Exit;+ }++ l += num_base_points;++ /* for now, only use the current point coordinates; */+ /* we may consider another approach in the near future */+ p1 = gloader->base.outline.points + start_point + k;+ p2 = gloader->base.outline.points + start_point + l;++ x = p1->x - p2->x;+ y = p1->y - p2->y;+ }+ else+ {+ x = FT_MulFix( subglyph->arg1, hints->x_scale ) + hints->x_delta;+ y = FT_MulFix( subglyph->arg2, hints->y_scale ) + hints->y_delta;++ x = FT_PIX_ROUND( x );+ y = FT_PIX_ROUND( y );+ }++ {+ FT_Outline dummy = gloader->base.outline;+++ dummy.points += num_base_points;+ dummy.n_points = (short)num_new_points;++ FT_Outline_Translate( &dummy, x, y );+ }+ }+ }+ break;++ default:+ /* we don't support other formats (yet?) */+ error = AF_Err_Unimplemented_Feature;+ }++ Hint_Metrics:+ if ( depth == 0 )+ {+ FT_BBox bbox;+ FT_Vector vvector;+++ vvector.x = slot->metrics.vertBearingX - slot->metrics.horiBearingX;+ vvector.y = slot->metrics.vertBearingY - slot->metrics.horiBearingY;+ vvector.x = FT_MulFix( vvector.x, metrics->scaler.x_scale );+ vvector.y = FT_MulFix( vvector.y, metrics->scaler.y_scale );++ /* transform the hinted outline if needed */+ if ( loader->transformed )+ {+ FT_Outline_Transform( &gloader->base.outline, &loader->trans_matrix );+ FT_Vector_Transform( &vvector, &loader->trans_matrix );+ }+#if 1+ /* we must translate our final outline by -pp1.x and compute */+ /* the new metrics */+ if ( loader->pp1.x )+ FT_Outline_Translate( &gloader->base.outline, -loader->pp1.x, 0 );+#endif+ FT_Outline_Get_CBox( &gloader->base.outline, &bbox );++ bbox.xMin = FT_PIX_FLOOR( bbox.xMin );+ bbox.yMin = FT_PIX_FLOOR( bbox.yMin );+ bbox.xMax = FT_PIX_CEIL( bbox.xMax );+ bbox.yMax = FT_PIX_CEIL( bbox.yMax );++ slot->metrics.width = bbox.xMax - bbox.xMin;+ slot->metrics.height = bbox.yMax - bbox.yMin;+ slot->metrics.horiBearingX = bbox.xMin;+ slot->metrics.horiBearingY = bbox.yMax;++ slot->metrics.vertBearingX = FT_PIX_FLOOR( bbox.xMin + vvector.x );+ slot->metrics.vertBearingY = FT_PIX_FLOOR( bbox.yMax + vvector.y );++ /* for mono-width fonts (like Andale, Courier, etc.) we need */+ /* to keep the original rounded advance width; ditto for */+ /* digits if all have the same advance width */+#if 0+ if ( !FT_IS_FIXED_WIDTH( slot->face ) )+ slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;+ else+ slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,+ x_scale );+#else+ if ( FT_IS_FIXED_WIDTH( slot->face ) ||+ ( af_face_globals_is_digit( loader->globals, glyph_index ) &&+ metrics->digits_have_same_width ) )+ {+ slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,+ metrics->scaler.x_scale );++ /* Set delta values to 0. Otherwise code that uses them is */+ /* going to ruin the fixed advance width. */+ slot->lsb_delta = 0;+ slot->rsb_delta = 0;+ }+ else+ {+ /* non-spacing glyphs must stay as-is */+ if ( slot->metrics.horiAdvance )+ slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;+ }+#endif++ slot->metrics.vertAdvance = FT_MulFix( slot->metrics.vertAdvance,+ metrics->scaler.y_scale );++ slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance );+ slot->metrics.vertAdvance = FT_PIX_ROUND( slot->metrics.vertAdvance );++ /* now copy outline into glyph slot */+ FT_GlyphLoader_Rewind( internal->loader );+ error = FT_GlyphLoader_CopyPoints( internal->loader, gloader );+ if ( error )+ goto Exit;++ slot->outline = internal->loader->base.outline;+ slot->format = FT_GLYPH_FORMAT_OUTLINE;+ }++#ifdef DEBUG_HINTER+ af_debug_hinter = hinter;+#endif++ Exit:+ return error;+ }+++ FT_LOCAL_DEF( FT_Error )+ af_loader_load_glyph( AF_Loader loader,+ FT_Face face,+ FT_UInt gindex,+ FT_UInt32 load_flags )+ {+ FT_Error error;+ FT_Size size = face->size;+ AF_ScalerRec scaler;+++ if ( !size )+ return AF_Err_Invalid_Argument;++ FT_ZERO( &scaler );++ scaler.face = face;+ scaler.x_scale = size->metrics.x_scale;+ scaler.x_delta = 0; /* XXX: TODO: add support for sub-pixel hinting */+ scaler.y_scale = size->metrics.y_scale;+ scaler.y_delta = 0; /* XXX: TODO: add support for sub-pixel hinting */++ scaler.render_mode = FT_LOAD_TARGET_MODE( load_flags );+ scaler.flags = 0; /* XXX: fix this */++ error = af_loader_reset( loader, face );+ if ( !error )+ {+ AF_ScriptMetrics metrics;+ FT_UInt options = 0;+++#ifdef FT_OPTION_AUTOFIT2+ /* XXX: undocumented hook to activate the latin2 hinter */+ if ( load_flags & ( 1UL << 20 ) )+ options = 2;+#endif++ error = af_face_globals_get_metrics( loader->globals, gindex,+ options, &metrics );+ if ( !error )+ {+ loader->metrics = metrics;++ if ( metrics->clazz->script_metrics_scale )+ metrics->clazz->script_metrics_scale( metrics, &scaler );+ else+ metrics->scaler = scaler;++ load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_TRANSFORM;+ load_flags &= ~FT_LOAD_RENDER;++ if ( metrics->clazz->script_hints_init )+ {+ error = metrics->clazz->script_hints_init( &loader->hints,+ metrics );+ if ( error )+ goto Exit;+ }++ error = af_loader_load_g( loader, &scaler, gindex, load_flags, 0 );+ }+ }+ Exit:+ return error;+ }+++/* END */
+ src/autofit/afloader.h view
@@ -0,0 +1,73 @@+/***************************************************************************/+/* */+/* afloader.h */+/* */+/* Auto-fitter glyph loading routines (specification). */+/* */+/* Copyright 2003, 2004, 2005 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 __AF_LOADER_H__+#define __AF_LOADER_H__++#include "afhints.h"+#include "afglobal.h"+++FT_BEGIN_HEADER++ typedef struct AF_LoaderRec_+ {+ FT_Face face; /* current face */+ AF_FaceGlobals globals; /* current face globals */+ FT_GlyphLoader gloader; /* glyph loader */+ AF_GlyphHintsRec hints;+ AF_ScriptMetrics metrics;+ FT_Bool transformed;+ FT_Matrix trans_matrix;+ FT_Vector trans_delta;+ FT_Vector pp1;+ FT_Vector pp2;+ /* we don't handle vertical phantom points */++ } AF_LoaderRec, *AF_Loader;+++ FT_LOCAL( FT_Error )+ af_loader_init( AF_Loader loader,+ FT_Memory memory );+++ FT_LOCAL( FT_Error )+ af_loader_reset( AF_Loader loader,+ FT_Face face );+++ FT_LOCAL( void )+ af_loader_done( AF_Loader loader );+++ FT_LOCAL( FT_Error )+ af_loader_load_glyph( AF_Loader loader,+ FT_Face face,+ FT_UInt gindex,+ FT_UInt32 load_flags );++/* */+++FT_END_HEADER++#endif /* __AF_LOADER_H__ */+++/* END */
+ src/autofit/afmodule.c view
@@ -0,0 +1,94 @@+/***************************************************************************/+/* */+/* afmodule.c */+/* */+/* Auto-fitter module implementation (body). */+/* */+/* Copyright 2003, 2004, 2005, 2006 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 "afmodule.h"+#include "afloader.h"+#include "afpic.h"++#ifdef AF_DEBUG+ int _af_debug;+ int _af_debug_disable_horz_hints;+ int _af_debug_disable_vert_hints;+ int _af_debug_disable_blue_hints;+ void* _af_debug_hints;+#endif++#include FT_INTERNAL_OBJECTS_H+++ typedef struct FT_AutofitterRec_+ {+ FT_ModuleRec root;+ AF_LoaderRec loader[1];++ } FT_AutofitterRec, *FT_Autofitter;+++ FT_CALLBACK_DEF( FT_Error )+ af_autofitter_init( FT_Autofitter module )+ {+ return af_loader_init( module->loader, module->root.library->memory );+ }+++ FT_CALLBACK_DEF( void )+ af_autofitter_done( FT_Autofitter module )+ {+ af_loader_done( module->loader );+ }+++ FT_CALLBACK_DEF( FT_Error )+ af_autofitter_load_glyph( FT_Autofitter module,+ FT_GlyphSlot slot,+ FT_Size size,+ FT_UInt glyph_index,+ FT_Int32 load_flags )+ {+ FT_UNUSED( size );++ return af_loader_load_glyph( module->loader, slot->face,+ glyph_index, load_flags );+ }+++ FT_DEFINE_AUTOHINTER_SERVICE(af_autofitter_service,+ NULL,+ NULL,+ NULL,+ (FT_AutoHinter_GlyphLoadFunc)af_autofitter_load_glyph+ )++ FT_DEFINE_MODULE(autofit_module_class,++ FT_MODULE_HINTER,+ sizeof ( FT_AutofitterRec ),++ "autofitter",+ 0x10000L, /* version 1.0 of the autofitter */+ 0x20000L, /* requires FreeType 2.0 or above */++ (const void*)&AF_AF_AUTOFITTER_SERVICE_GET,++ (FT_Module_Constructor)af_autofitter_init,+ (FT_Module_Destructor) af_autofitter_done,+ (FT_Module_Requester) NULL+ )+++/* END */
+ src/autofit/afmodule.h view
@@ -0,0 +1,37 @@+/***************************************************************************/+/* */+/* afmodule.h */+/* */+/* Auto-fitter module implementation (specification). */+/* */+/* Copyright 2003, 2004, 2005 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#ifndef __AFMODULE_H__+#define __AFMODULE_H__++#include <ft2build.h>+#include FT_INTERNAL_OBJECTS_H+#include FT_MODULE_H+++FT_BEGIN_HEADER++FT_DECLARE_MODULE(autofit_module_class)+++FT_END_HEADER++#endif /* __AFMODULE_H__ */+++/* END */
+ src/autofit/afpic.c view
@@ -0,0 +1,94 @@+/***************************************************************************/+/* */+/* afpic.c */+/* */+/* The FreeType position independent code services for autofit module. */+/* */+/* Copyright 2009, 2010 by */+/* Oran Agra and Mickey Gabel. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#include <ft2build.h>+#include FT_FREETYPE_H+#include FT_INTERNAL_OBJECTS_H+#include "afpic.h"++#ifdef FT_CONFIG_OPTION_PIC++ /* forward declaration of PIC init functions from afmodule.c */+ void FT_Init_Class_af_autofitter_service( FT_Library, FT_AutoHinter_ServiceRec*);++ /* forward declaration of PIC init functions from script classes */+#include "aflatin.h"+#include "aflatin2.h"+#include "afcjk.h"+#include "afdummy.h"+#include "afindic.h"++ void+ autofit_module_class_pic_free( FT_Library library )+ {+ FT_PIC_Container* pic_container = &library->pic_container;+ FT_Memory memory = library->memory;+ if ( pic_container->autofit )+ {+ FT_FREE( pic_container->autofit );+ pic_container->autofit = NULL;+ }+ }+++ FT_Error+ autofit_module_class_pic_init( FT_Library library )+ {+ FT_PIC_Container* pic_container = &library->pic_container;+ FT_UInt ss;+ FT_Error error = AF_Err_Ok;+ AFModulePIC* container;+ FT_Memory memory = library->memory;+++ /* allocate pointer, clear and set global container pointer */+ if ( FT_ALLOC ( container, sizeof ( *container ) ) )+ return error;+ FT_MEM_SET( container, 0, sizeof ( *container ) );+ pic_container->autofit = container;++ /* initialize pointer table - this is how the module usually expects this data */+ for ( ss = 0 ; ss < AF_SCRIPT_CLASSES_REC_COUNT ; ss++ )+ {+ container->af_script_classes[ss] = &container->af_script_classes_rec[ss];+ }+ container->af_script_classes[AF_SCRIPT_CLASSES_COUNT-1] = NULL;+ + /* add call to initialization function when you add new scripts */+ ss = 0;+ FT_Init_Class_af_dummy_script_class(&container->af_script_classes_rec[ss++]);+#ifdef FT_OPTION_AUTOFIT2+ FT_Init_Class_af_latin2_script_class(&container->af_script_classes_rec[ss++]);+#endif+ FT_Init_Class_af_latin_script_class(&container->af_script_classes_rec[ss++]);+ FT_Init_Class_af_cjk_script_class(&container->af_script_classes_rec[ss++]);+ FT_Init_Class_af_indic_script_class(&container->af_script_classes_rec[ss++]); ++ FT_Init_Class_af_autofitter_service(library, &container->af_autofitter_service);++/*Exit:*/+ if(error)+ autofit_module_class_pic_free(library);+ return error;+ }+++#endif /* FT_CONFIG_OPTION_PIC */+++/* END */
+ src/autofit/afpic.h view
@@ -0,0 +1,64 @@+/***************************************************************************/+/* */+/* afpic.h */+/* */+/* The FreeType position independent code services for autofit module. */+/* */+/* Copyright 2009 by */+/* Oran Agra and Mickey Gabel. */+/* */+/* 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 __AFPIC_H__+#define __AFPIC_H__++ +FT_BEGIN_HEADER++#include FT_INTERNAL_PIC_H++#ifndef FT_CONFIG_OPTION_PIC++#define AF_SCRIPT_CLASSES_GET af_script_classes+#define AF_AF_AUTOFITTER_SERVICE_GET af_autofitter_service++#else /* FT_CONFIG_OPTION_PIC */++#include "aftypes.h"++/* increase these when you add new scripts, and update autofit_module_class_pic_init */+#ifdef FT_OPTION_AUTOFIT2+ #define AF_SCRIPT_CLASSES_COUNT 6+#else+ #define AF_SCRIPT_CLASSES_COUNT 5 +#endif+#define AF_SCRIPT_CLASSES_REC_COUNT (AF_SCRIPT_CLASSES_COUNT-1) ++ typedef struct AFModulePIC_+ {+ AF_ScriptClass af_script_classes[AF_SCRIPT_CLASSES_COUNT];+ AF_ScriptClassRec af_script_classes_rec[AF_SCRIPT_CLASSES_REC_COUNT];+ FT_AutoHinter_ServiceRec af_autofitter_service;+ } AFModulePIC;++#define GET_PIC(lib) ((AFModulePIC*)((lib)->pic_container.autofit))+#define AF_SCRIPT_CLASSES_GET (GET_PIC(FT_FACE_LIBRARY(globals->face))->af_script_classes)+#define AF_AF_AUTOFITTER_SERVICE_GET (GET_PIC(library)->af_autofitter_service)++#endif /* FT_CONFIG_OPTION_PIC */++ /* */++FT_END_HEADER++#endif /* __AFPIC_H__ */+++/* END */
+ src/autofit/aftypes.h view
@@ -0,0 +1,403 @@+/***************************************************************************/+/* */+/* aftypes.h */+/* */+/* Auto-fitter types (specification only). */+/* */+/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++ /*************************************************************************+ *+ * The auto-fitter is a complete rewrite of the old auto-hinter.+ * Its main feature is the ability to differentiate between different+ * scripts in order to apply language-specific rules.+ *+ * The code has also been compartmentized into several entities that+ * should make algorithmic experimentation easier than with the old+ * code.+ *+ * Finally, we get rid of the Catharon license, since this code is+ * released under the FreeType one.+ *+ *************************************************************************/+++#ifndef __AFTYPES_H__+#define __AFTYPES_H__++#include <ft2build.h>++#include FT_FREETYPE_H+#include FT_OUTLINE_H+#include FT_INTERNAL_OBJECTS_H+#include FT_INTERNAL_DEBUG_H+++FT_BEGIN_HEADER++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** D E B U G G I N G *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++#define xxAF_USE_WARPER /* only define to use warp hinting */+#define xxAF_DEBUG++#ifdef AF_DEBUG++#include FT_CONFIG_STANDARD_LIBRARY_H++#define AF_LOG( x ) do { if ( _af_debug ) printf x; } while ( 0 )++extern int _af_debug;+extern int _af_debug_disable_horz_hints;+extern int _af_debug_disable_vert_hints;+extern int _af_debug_disable_blue_hints;+extern void* _af_debug_hints;++#else /* !AF_DEBUG */++#define AF_LOG( x ) do { } while ( 0 ) /* nothing */++#endif /* !AF_DEBUG */+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** U T I L I T Y S T U F F *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ typedef struct AF_WidthRec_+ {+ FT_Pos org; /* original position/width in font units */+ FT_Pos cur; /* current/scaled position/width in device sub-pixels */+ FT_Pos fit; /* current/fitted position/width in device sub-pixels */++ } AF_WidthRec, *AF_Width;+++ FT_LOCAL( void )+ af_sort_pos( FT_UInt count,+ FT_Pos* table );++ FT_LOCAL( void )+ af_sort_widths( FT_UInt count,+ AF_Width widths );+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** A N G L E T Y P E S *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /*+ * The auto-fitter doesn't need a very high angular accuracy;+ * this allows us to speed up some computations considerably with a+ * light Cordic algorithm (see afangles.c).+ */++ typedef FT_Int AF_Angle;+++#define AF_ANGLE_PI 256+#define AF_ANGLE_2PI ( AF_ANGLE_PI * 2 )+#define AF_ANGLE_PI2 ( AF_ANGLE_PI / 2 )+#define AF_ANGLE_PI4 ( AF_ANGLE_PI / 4 )+++#if 0+ /*+ * compute the angle of a given 2-D vector+ */+ FT_LOCAL( AF_Angle )+ af_angle_atan( FT_Pos dx,+ FT_Pos dy );+++ /*+ * compute `angle2 - angle1'; the result is always within+ * the range [-AF_ANGLE_PI .. AF_ANGLE_PI - 1]+ */+ FT_LOCAL( AF_Angle )+ af_angle_diff( AF_Angle angle1,+ AF_Angle angle2 );+#endif /* 0 */+++#define AF_ANGLE_DIFF( result, angle1, angle2 ) \+ FT_BEGIN_STMNT \+ AF_Angle _delta = (angle2) - (angle1); \+ \+ \+ _delta %= AF_ANGLE_2PI; \+ if ( _delta < 0 ) \+ _delta += AF_ANGLE_2PI; \+ \+ if ( _delta > AF_ANGLE_PI ) \+ _delta -= AF_ANGLE_2PI; \+ \+ result = _delta; \+ FT_END_STMNT+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** O U T L I N E S *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /* opaque handle to glyph-specific hints -- see `afhints.h' for more+ * details+ */+ typedef struct AF_GlyphHintsRec_* AF_GlyphHints;++ /* This structure is used to model an input glyph outline to+ * the auto-hinter. The latter will set the `hints' field+ * depending on the glyph's script.+ */+ typedef struct AF_OutlineRec_+ {+ FT_Face face;+ FT_Outline outline;+ FT_UInt outline_resolution;++ FT_Int advance;+ FT_UInt metrics_resolution;++ AF_GlyphHints hints;++ } AF_OutlineRec;+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** S C A L E R S *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /*+ * A scaler models the target pixel device that will receive the+ * auto-hinted glyph image.+ */++ typedef enum AF_ScalerFlags_+ {+ AF_SCALER_FLAG_NO_HORIZONTAL = 1, /* disable horizontal hinting */+ AF_SCALER_FLAG_NO_VERTICAL = 2, /* disable vertical hinting */+ AF_SCALER_FLAG_NO_ADVANCE = 4 /* disable advance hinting */++ } AF_ScalerFlags;+++ typedef struct AF_ScalerRec_+ {+ FT_Face face; /* source font face */+ FT_Fixed x_scale; /* from font units to 1/64th device pixels */+ FT_Fixed y_scale; /* from font units to 1/64th device pixels */+ FT_Pos x_delta; /* in 1/64th device pixels */+ FT_Pos y_delta; /* in 1/64th device pixels */+ FT_Render_Mode render_mode; /* monochrome, anti-aliased, LCD, etc. */+ FT_UInt32 flags; /* additional control flags, see above */++ } AF_ScalerRec, *AF_Scaler;+++#define AF_SCALER_EQUAL_SCALES( a, b ) \+ ( (a)->x_scale == (b)->x_scale && \+ (a)->y_scale == (b)->y_scale && \+ (a)->x_delta == (b)->x_delta && \+ (a)->y_delta == (b)->y_delta )+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** S C R I P T S *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /*+ * The list of know scripts. Each different script corresponds to the+ * following information:+ *+ * - A set of Unicode ranges to test whether the face supports the+ * script.+ *+ * - A specific global analyzer that will compute global metrics+ * specific to the script.+ *+ * - A specific glyph analyzer that will compute segments and+ * edges for each glyph covered by the script.+ *+ * - A specific grid-fitting algorithm that will distort the+ * scaled glyph outline according to the results of the glyph+ * analyzer.+ *+ * Note that a given analyzer and/or grid-fitting algorithm can be+ * used by more than one script.+ */++ typedef enum AF_Script_+ {+ AF_SCRIPT_NONE = 0,+ AF_SCRIPT_LATIN = 1,+ AF_SCRIPT_CJK = 2,+ AF_SCRIPT_INDIC = 3, +#ifdef FT_OPTION_AUTOFIT2+ AF_SCRIPT_LATIN2,+#endif++ /* add new scripts here. Don't forget to update the list in */+ /* `afglobal.c'. */++ AF_SCRIPT_MAX /* do not remove */++ } AF_Script;+++ typedef struct AF_ScriptClassRec_ const* AF_ScriptClass;++ typedef struct AF_ScriptMetricsRec_+ {+ AF_ScriptClass clazz;+ AF_ScalerRec scaler;+ FT_Bool digits_have_same_width;++ } AF_ScriptMetricsRec, *AF_ScriptMetrics;+++ /* This function parses an FT_Face to compute global metrics for+ * a specific script.+ */+ typedef FT_Error+ (*AF_Script_InitMetricsFunc)( AF_ScriptMetrics metrics,+ FT_Face face );++ typedef void+ (*AF_Script_ScaleMetricsFunc)( AF_ScriptMetrics metrics,+ AF_Scaler scaler );++ typedef void+ (*AF_Script_DoneMetricsFunc)( AF_ScriptMetrics metrics );+++ typedef FT_Error+ (*AF_Script_InitHintsFunc)( AF_GlyphHints hints,+ AF_ScriptMetrics metrics );++ typedef void+ (*AF_Script_ApplyHintsFunc)( AF_GlyphHints hints,+ FT_Outline* outline,+ AF_ScriptMetrics metrics );+++ typedef struct AF_Script_UniRangeRec_+ {+ FT_UInt32 first;+ FT_UInt32 last;++ } AF_Script_UniRangeRec;++#define AF_UNIRANGE_REC( a, b ) { (FT_UInt32)(a), (FT_UInt32)(b) }++ typedef const AF_Script_UniRangeRec *AF_Script_UniRange;+++ typedef struct AF_ScriptClassRec_+ {+ AF_Script script;+ AF_Script_UniRange script_uni_ranges; /* last must be { 0, 0 } */++ FT_Offset script_metrics_size;+ AF_Script_InitMetricsFunc script_metrics_init;+ AF_Script_ScaleMetricsFunc script_metrics_scale;+ AF_Script_DoneMetricsFunc script_metrics_done;++ AF_Script_InitHintsFunc script_hints_init;+ AF_Script_ApplyHintsFunc script_hints_apply;++ } AF_ScriptClassRec;++/* Declare and define vtables for classes */+#ifndef FT_CONFIG_OPTION_PIC++#define AF_DECLARE_SCRIPT_CLASS(script_class) \+ FT_CALLBACK_TABLE const AF_ScriptClassRec \+ script_class;++#define AF_DEFINE_SCRIPT_CLASS(script_class, script_, ranges, m_size, \+ m_init, m_scale, m_done, h_init, h_apply) \+ FT_CALLBACK_TABLE_DEF const AF_ScriptClassRec \+ script_class = \+ { \+ script_, \+ ranges, \+ \+ m_size, \+ \+ m_init, \+ m_scale, \+ m_done, \+ \+ h_init, \+ h_apply \+ };++#else ++#define AF_DECLARE_SCRIPT_CLASS(script_class) \+ FT_LOCAL(void) \+ FT_Init_Class_##script_class(AF_ScriptClassRec* ac);++#define AF_DEFINE_SCRIPT_CLASS(script_class, script_, ranges, m_size, \+ m_init, m_scale, m_done, h_init, h_apply) \+ FT_LOCAL_DEF(void) \+ FT_Init_Class_##script_class(AF_ScriptClassRec* ac) \+ { \+ ac->script = script_; \+ ac->script_uni_ranges = ranges; \+ \+ ac->script_metrics_size = m_size; \+ \+ ac->script_metrics_init = m_init; \+ ac->script_metrics_scale = m_scale; \+ ac->script_metrics_done = m_done; \+ \+ ac->script_hints_init = h_init; \+ ac->script_hints_apply = h_apply; \+ }+#endif+++/* */++FT_END_HEADER++#endif /* __AFTYPES_H__ */+++/* END */
+ src/autofit/afwarp.c view
@@ -0,0 +1,338 @@+/***************************************************************************/+/* */+/* afwarp.c */+/* */+/* Auto-fitter warping algorithm (body). */+/* */+/* Copyright 2006, 2007 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 "afwarp.h"++#ifdef AF_USE_WARPER++#if 1+ static const AF_WarpScore+ af_warper_weights[64] =+ {+ 35, 32, 30, 25, 20, 15, 12, 10, 5, 1, 0, 0, 0, 0, 0, 0,+ 0, 0, 0, 0, 0, 0, -1, -2, -5, -8,-10,-10,-20,-20,-30,-30,++ -30,-30,-20,-20,-10,-10, -8, -5, -2, -1, 0, 0, 0, 0, 0, 0,+ 0, 0, 0, 0, 0, 0, 0, 1, 5, 10, 12, 15, 20, 25, 30, 32,+ };+#else+ static const AF_WarpScore+ af_warper_weights[64] =+ {+ 30, 20, 10, 5, 4, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0,+ 0, 0, 0, 0, 0, 0, 0, -1, -2, -2, -5, -5,-10,-10,-15,-20,++ -20,-15,-15,-10,-10, -5, -5, -2, -2, -1, 0, 0, 0, 0, 0, 0,+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 4, 5, 10, 20,+ };+#endif+++ static void+ af_warper_compute_line_best( AF_Warper warper,+ FT_Fixed scale,+ FT_Pos delta,+ FT_Pos xx1,+ FT_Pos xx2,+ AF_WarpScore base_distort,+ AF_Segment segments,+ FT_UInt num_segments )+ {+ FT_Int idx_min, idx_max, idx0;+ FT_UInt nn;+ AF_WarpScore scores[65];+++ for ( nn = 0; nn < 65; nn++ )+ scores[nn] = 0;++ idx0 = xx1 - warper->t1;++ /* compute minimum and maximum indices */+ {+ FT_Pos xx1min = warper->x1min;+ FT_Pos xx1max = warper->x1max;+ FT_Pos w = xx2 - xx1;+++ if ( xx1min + w < warper->x2min )+ xx1min = warper->x2min - w;++ xx1max = warper->x1max;+ if ( xx1max + w > warper->x2max )+ xx1max = warper->x2max - w;++ idx_min = xx1min - warper->t1;+ idx_max = xx1max - warper->t1;++ if ( idx_min < 0 || idx_min > idx_max || idx_max > 64 )+ {+ AF_LOG(( "invalid indices:\n"+ " min=%d max=%d, xx1=%ld xx2=%ld,\n"+ " x1min=%ld x1max=%ld, x2min=%ld x2max=%ld\n",+ idx_min, idx_max, xx1, xx2,+ warper->x1min, warper->x1max,+ warper->x2min, warper->x2max ));+ return;+ }+ }++ for ( nn = 0; nn < num_segments; nn++ )+ {+ FT_Pos len = segments[nn].max_coord - segments[nn].min_coord;+ FT_Pos y0 = FT_MulFix( segments[nn].pos, scale ) + delta;+ FT_Pos y = y0 + ( idx_min - idx0 );+ FT_Int idx;+++ for ( idx = idx_min; idx <= idx_max; idx++, y++ )+ scores[idx] += af_warper_weights[y & 63] * len;+ }++ /* find best score */+ {+ FT_Int idx;+++ for ( idx = idx_min; idx <= idx_max; idx++ )+ {+ AF_WarpScore score = scores[idx];+ AF_WarpScore distort = base_distort + ( idx - idx0 );+++ if ( score > warper->best_score ||+ ( score == warper->best_score &&+ distort < warper->best_distort ) )+ {+ warper->best_score = score;+ warper->best_distort = distort;+ warper->best_scale = scale;+ warper->best_delta = delta + ( idx - idx0 );+ }+ }+ }+ }+++ FT_LOCAL_DEF( void )+ af_warper_compute( AF_Warper warper,+ AF_GlyphHints hints,+ AF_Dimension dim,+ FT_Fixed *a_scale,+ FT_Pos *a_delta )+ {+ AF_AxisHints axis;+ AF_Point points;++ FT_Fixed org_scale;+ FT_Pos org_delta;++ FT_UInt nn, num_points, num_segments;+ FT_Int X1, X2;+ FT_Int w;++ AF_WarpScore base_distort;+ AF_Segment segments;+++ /* get original scaling transformation */+ if ( dim == AF_DIMENSION_VERT )+ {+ org_scale = hints->y_scale;+ org_delta = hints->y_delta;+ }+ else+ {+ org_scale = hints->x_scale;+ org_delta = hints->x_delta;+ }++ warper->best_scale = org_scale;+ warper->best_delta = org_delta;+ warper->best_score = INT_MIN;+ warper->best_distort = 0;++ axis = &hints->axis[dim];+ segments = axis->segments;+ num_segments = axis->num_segments;+ points = hints->points;+ num_points = hints->num_points;++ *a_scale = org_scale;+ *a_delta = org_delta;++ /* get X1 and X2, minimum and maximum in original coordinates */+ if ( num_segments < 1 )+ return;++#if 1+ X1 = X2 = points[0].fx;+ for ( nn = 1; nn < num_points; nn++ )+ {+ FT_Int X = points[nn].fx;+++ if ( X < X1 )+ X1 = X;+ if ( X > X2 )+ X2 = X;+ }+#else+ X1 = X2 = segments[0].pos;+ for ( nn = 1; nn < num_segments; nn++ )+ {+ FT_Int X = segments[nn].pos;+++ if ( X < X1 )+ X1 = X;+ if ( X > X2 )+ X2 = X;+ }+#endif++ if ( X1 >= X2 )+ return;++ warper->x1 = FT_MulFix( X1, org_scale ) + org_delta;+ warper->x2 = FT_MulFix( X2, org_scale ) + org_delta;++ warper->t1 = AF_WARPER_FLOOR( warper->x1 );+ warper->t2 = AF_WARPER_CEIL( warper->x2 );++ warper->x1min = warper->x1 & ~31;+ warper->x1max = warper->x1min + 32;+ warper->x2min = warper->x2 & ~31;+ warper->x2max = warper->x2min + 32;++ if ( warper->x1max > warper->x2 )+ warper->x1max = warper->x2;++ if ( warper->x2min < warper->x1 )+ warper->x2min = warper->x1;++ warper->w0 = warper->x2 - warper->x1;++ if ( warper->w0 <= 64 )+ {+ warper->x1max = warper->x1;+ warper->x2min = warper->x2;+ }++ warper->wmin = warper->x2min - warper->x1max;+ warper->wmax = warper->x2max - warper->x1min;++#if 1+ {+ int margin = 16;+++ if ( warper->w0 <= 128 )+ {+ margin = 8;+ if ( warper->w0 <= 96 )+ margin = 4;+ }++ if ( warper->wmin < warper->w0 - margin )+ warper->wmin = warper->w0 - margin;++ if ( warper->wmax > warper->w0 + margin )+ warper->wmax = warper->w0 + margin;+ }++ if ( warper->wmin < warper->w0 * 3 / 4 )+ warper->wmin = warper->w0 * 3 / 4;++ if ( warper->wmax > warper->w0 * 5 / 4 )+ warper->wmax = warper->w0 * 5 / 4;+#else+ /* no scaling, just translation */+ warper->wmin = warper->wmax = warper->w0;+#endif++ for ( w = warper->wmin; w <= warper->wmax; w++ )+ {+ FT_Fixed new_scale;+ FT_Pos new_delta;+ FT_Pos xx1, xx2;+++ xx1 = warper->x1;+ xx2 = warper->x2;+ if ( w >= warper->w0 )+ {+ xx1 -= w - warper->w0;+ if ( xx1 < warper->x1min )+ {+ xx2 += warper->x1min - xx1;+ xx1 = warper->x1min;+ }+ }+ else+ {+ xx1 -= w - warper->w0;+ if ( xx1 > warper->x1max )+ {+ xx2 -= xx1 - warper->x1max;+ xx1 = warper->x1max;+ }+ }++ if ( xx1 < warper->x1 )+ base_distort = warper->x1 - xx1;+ else+ base_distort = xx1 - warper->x1;++ if ( xx2 < warper->x2 )+ base_distort += warper->x2 - xx2;+ else+ base_distort += xx2 - warper->x2;++ base_distort *= 10;++ new_scale = org_scale + FT_DivFix( w - warper->w0, X2 - X1 );+ new_delta = xx1 - FT_MulFix( X1, new_scale );++ af_warper_compute_line_best( warper, new_scale, new_delta, xx1, xx2,+ base_distort,+ segments, num_segments );+ }++ {+ FT_Fixed best_scale = warper->best_scale;+ FT_Pos best_delta = warper->best_delta;+ ++ hints->xmin_delta = FT_MulFix( X1, best_scale - org_scale )+ + best_delta;+ hints->xmax_delta = FT_MulFix( X2, best_scale - org_scale )+ + best_delta;++ *a_scale = best_scale;+ *a_delta = best_delta;+ }+ }++#else /* !AF_USE_WARPER */++char af_warper_dummy = 0; /* make compiler happy */++#endif /* !AF_USE_WARPER */++/* END */
+ src/autofit/afwarp.h view
@@ -0,0 +1,64 @@+/***************************************************************************/+/* */+/* afwarp.h */+/* */+/* Auto-fitter warping algorithm (specification). */+/* */+/* Copyright 2006, 2007 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 __AFWARP_H__+#define __AFWARP_H__++#include "afhints.h"++FT_BEGIN_HEADER++#define AF_WARPER_SCALE++#define AF_WARPER_FLOOR( x ) ( (x) & ~63 )+#define AF_WARPER_CEIL( x ) AF_WARPER_FLOOR( (x) + 63 )+++ typedef FT_Int32 AF_WarpScore;++ typedef struct AF_WarperRec_+ {+ FT_Pos x1, x2;+ FT_Pos t1, t2;+ FT_Pos x1min, x1max;+ FT_Pos x2min, x2max;+ FT_Pos w0, wmin, wmax;++ FT_Fixed best_scale;+ FT_Pos best_delta;+ AF_WarpScore best_score;+ AF_WarpScore best_distort;++ } AF_WarperRec, *AF_Warper;+++ FT_LOCAL( void )+ af_warper_compute( AF_Warper warper,+ AF_GlyphHints hints,+ AF_Dimension dim,+ FT_Fixed *a_scale,+ FT_Fixed *a_delta );+++FT_END_HEADER+++#endif /* __AFWARP_H__ */+++/* END */
+ src/autofit/autofit.c view
@@ -0,0 +1,41 @@+/***************************************************************************/+/* */+/* autofit.c */+/* */+/* Auto-fitter module (body). */+/* */+/* Copyright 2003, 2004, 2005, 2006, 2007 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 "afpic.c"+#include "afangles.c"+#include "afglobal.c"+#include "afhints.c"++#include "afdummy.c"+#include "aflatin.c"+#ifdef FT_OPTION_AUTOFIT2+#include "aflatin2.c"+#endif+#include "afcjk.c"+#include "afindic.c"++#include "afloader.c"+#include "afmodule.c"++#ifdef AF_USE_WARPER+#include "afwarp.c"+#endif++/* END */
+ src/base/basepic.c view
@@ -0,0 +1,83 @@+/***************************************************************************/+/* */+/* basepic.c */+/* */+/* The FreeType position independent code services for base. */+/* */+/* Copyright 2009 by */+/* Oran Agra and Mickey Gabel. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#include <ft2build.h>+#include FT_FREETYPE_H+#include FT_INTERNAL_OBJECTS_H+#include "basepic.h"++#ifdef FT_CONFIG_OPTION_PIC++ /* forward declaration of PIC init functions from ftglyph.c */+ void FT_Init_Class_ft_outline_glyph_class(FT_Glyph_Class*);+ void FT_Init_Class_ft_bitmap_glyph_class(FT_Glyph_Class*);++ /* forward declaration of PIC init functions from ftinit.c */+ FT_Error ft_create_default_module_classes(FT_Library);+ void ft_destroy_default_module_classes(FT_Library);++ void+ ft_base_pic_free( FT_Library library )+ {+ FT_PIC_Container* pic_container = &library->pic_container;+ FT_Memory memory = library->memory;+ if ( pic_container->base )+ {+ /* Destroy default module classes (in case FT_Add_Default_Modules was used) */+ ft_destroy_default_module_classes( library );++ FT_FREE( pic_container->base );+ pic_container->base = NULL;+ }+ }+++ FT_Error+ ft_base_pic_init( FT_Library library )+ {+ FT_PIC_Container* pic_container = &library->pic_container;+ FT_Error error = FT_Err_Ok;+ BasePIC* container;+ FT_Memory memory = library->memory;++ /* allocate pointer, clear and set global container pointer */+ if ( FT_ALLOC ( container, sizeof ( *container ) ) )+ return error;+ FT_MEM_SET( container, 0, sizeof(*container) );+ pic_container->base = container;++ /* initialize default modules list and pointers */+ error = ft_create_default_module_classes( library );+ if ( error )+ goto Exit;++ /* initialize pointer table - this is how the module usually expects this data */+ FT_Init_Class_ft_outline_glyph_class(&container->ft_outline_glyph_class);+ FT_Init_Class_ft_bitmap_glyph_class(&container->ft_bitmap_glyph_class);++Exit:+ if(error)+ ft_base_pic_free(library);+ return error;+ }+++#endif /* FT_CONFIG_OPTION_PIC */+++/* END */
+ src/base/basepic.h view
@@ -0,0 +1,62 @@+/***************************************************************************/+/* */+/* basepic.h */+/* */+/* The FreeType position independent code services for base. */+/* */+/* Copyright 2009 by */+/* Oran Agra and Mickey Gabel. */+/* */+/* 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 __BASEPIC_H__+#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+#define FT_BITMAP_GLYPH_CLASS_GET &ft_bitmap_glyph_class+#define FT_DEFAULT_MODULES_GET ft_default_modules++#else /* FT_CONFIG_OPTION_PIC */++#include FT_GLYPH_H++ typedef struct BasePIC_+ {+ FT_Module_Class** default_module_classes;+ FT_Glyph_Class ft_outline_glyph_class;+ FT_Glyph_Class ft_bitmap_glyph_class;+ } BasePIC;++#define GET_PIC(lib) ((BasePIC*)((lib)->pic_container.base))+#define FT_OUTLINE_GLYPH_CLASS_GET (&GET_PIC(library)->ft_outline_glyph_class)+#define FT_BITMAP_GLYPH_CLASS_GET (&GET_PIC(library)->ft_bitmap_glyph_class)+#define FT_DEFAULT_MODULES_GET (GET_PIC(library)->default_module_classes)++ void+ ft_base_pic_free( FT_Library library );++ FT_Error+ ft_base_pic_init( FT_Library library );++#endif /* FT_CONFIG_OPTION_PIC */+ /* */++FT_END_HEADER++#endif /* __BASEPIC_H__ */+++/* END */
+ src/base/ftadvanc.c view
@@ -0,0 +1,163 @@+/***************************************************************************/+/* */+/* ftadvanc.c */+/* */+/* Quick computation of advance widths (body). */+/* */+/* Copyright 2008, 2009 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_ADVANCES_H+#include FT_INTERNAL_OBJECTS_H+++ static FT_Error+ _ft_face_scale_advances( FT_Face face,+ FT_Fixed* advances,+ FT_UInt count,+ FT_Int32 flags )+ {+ FT_Fixed scale;+ FT_UInt nn;+++ if ( flags & FT_LOAD_NO_SCALE )+ return FT_Err_Ok;++ if ( face->size == NULL )+ return FT_Err_Invalid_Size_Handle;++ if ( flags & FT_LOAD_VERTICAL_LAYOUT )+ scale = face->size->metrics.y_scale;+ else+ scale = face->size->metrics.x_scale;++ /* this must be the same scaling as to get linear{Hori,Vert}Advance */+ /* (see `FT_Load_Glyph' implementation in src/base/ftobjs.c) */++ for ( nn = 0; nn < count; nn++ )+ advances[nn] = FT_MulDiv( advances[nn], scale, 64 );++ return FT_Err_Ok;+ }+++ /* at the moment, we can perform fast advance retrieval only in */+ /* the following cases: */+ /* */+ /* - unscaled load */+ /* - unhinted load */+ /* - light-hinted load */++#define LOAD_ADVANCE_FAST_CHECK( flags ) \+ ( flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) || \+ FT_LOAD_TARGET_MODE( flags ) == FT_RENDER_MODE_LIGHT )+++ /* documentation is in ftadvanc.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Get_Advance( FT_Face face,+ FT_UInt gindex,+ FT_Int32 flags,+ FT_Fixed *padvance )+ {+ FT_Face_GetAdvancesFunc func;+++ if ( !face )+ return FT_Err_Invalid_Face_Handle;++ if ( gindex >= (FT_UInt)face->num_glyphs )+ return FT_Err_Invalid_Glyph_Index;++ func = face->driver->clazz->get_advances;+ if ( func && LOAD_ADVANCE_FAST_CHECK( flags ) )+ {+ FT_Error error;+++ error = func( face, gindex, 1, flags, padvance );+ if ( !error )+ return _ft_face_scale_advances( face, padvance, 1, flags );++ if ( error != FT_ERROR_BASE( FT_Err_Unimplemented_Feature ) )+ return error;+ }++ return FT_Get_Advances( face, gindex, 1, flags, padvance );+ }+++ /* documentation is in ftadvanc.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Get_Advances( FT_Face face,+ FT_UInt start,+ FT_UInt count,+ FT_Int32 flags,+ FT_Fixed *padvances )+ {+ FT_Face_GetAdvancesFunc func;+ FT_UInt num, end, nn;+ FT_Error error = FT_Err_Ok;+++ if ( !face )+ return FT_Err_Invalid_Face_Handle;++ num = (FT_UInt)face->num_glyphs;+ end = start + count;+ if ( start >= num || end < start || end > num )+ return FT_Err_Invalid_Glyph_Index;++ if ( count == 0 )+ return FT_Err_Ok;++ func = face->driver->clazz->get_advances;+ if ( func && LOAD_ADVANCE_FAST_CHECK( flags ) )+ {+ error = func( face, start, count, flags, padvances );+ if ( !error )+ goto Exit;++ if ( error != FT_ERROR_BASE( FT_Err_Unimplemented_Feature ) )+ return error;+ }++ error = FT_Err_Ok;++ if ( flags & FT_ADVANCE_FLAG_FAST_ONLY )+ return FT_Err_Unimplemented_Feature;++ flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY;+ for ( nn = 0; nn < count; nn++ )+ {+ error = FT_Load_Glyph( face, start + nn, flags );+ if ( error )+ break;++ padvances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT )+ ? face->glyph->advance.y+ : face->glyph->advance.x;+ }++ if ( error )+ return error;++ Exit:+ return _ft_face_scale_advances( face, padvances, count, flags );+ }+++/* END */
+ src/base/ftapi.c view
@@ -0,0 +1,121 @@+/***************************************************************************/+/* */+/* ftapi.c */+/* */+/* The FreeType compatibility functions (body). */+/* */+/* Copyright 2002 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_LIST_H+#include FT_OUTLINE_H+#include FT_INTERNAL_OBJECTS_H+#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_STREAM_H+#include FT_TRUETYPE_TABLES_H+#include FT_OUTLINE_H+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** ****/+ /**** C O M P A T I B I L I T Y ****/+ /**** ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/++ /* backwards compatibility API */++ FT_BASE_DEF( void )+ FT_New_Memory_Stream( FT_Library library,+ FT_Byte* base,+ FT_ULong size,+ FT_Stream stream )+ {+ FT_UNUSED( library );++ FT_Stream_OpenMemory( stream, base, size );+ }+++ FT_BASE_DEF( FT_Error )+ FT_Seek_Stream( FT_Stream stream,+ FT_ULong pos )+ {+ return FT_Stream_Seek( stream, pos );+ }+++ FT_BASE_DEF( FT_Error )+ FT_Skip_Stream( FT_Stream stream,+ FT_Long distance )+ {+ return FT_Stream_Skip( stream, distance );+ }+++ FT_BASE_DEF( FT_Error )+ FT_Read_Stream( FT_Stream stream,+ FT_Byte* buffer,+ FT_ULong count )+ {+ return FT_Stream_Read( stream, buffer, count );+ }+++ FT_BASE_DEF( FT_Error )+ FT_Read_Stream_At( FT_Stream stream,+ FT_ULong pos,+ FT_Byte* buffer,+ FT_ULong count )+ {+ return FT_Stream_ReadAt( stream, pos, buffer, count );+ }+++ FT_BASE_DEF( FT_Error )+ FT_Extract_Frame( FT_Stream stream,+ FT_ULong count,+ FT_Byte** pbytes )+ {+ return FT_Stream_ExtractFrame( stream, count, pbytes );+ }+++ FT_BASE_DEF( void )+ FT_Release_Frame( FT_Stream stream,+ FT_Byte** pbytes )+ {+ FT_Stream_ReleaseFrame( stream, pbytes );+ }++ FT_BASE_DEF( FT_Error )+ FT_Access_Frame( FT_Stream stream,+ FT_ULong count )+ {+ return FT_Stream_EnterFrame( stream, count );+ }+++ FT_BASE_DEF( void )+ FT_Forget_Frame( FT_Stream stream )+ {+ FT_Stream_ExitFrame( stream );+ }+++/* END */
+ src/base/ftbase.c view
@@ -0,0 +1,41 @@+/***************************************************************************/+/* */+/* ftbase.c */+/* */+/* Single object library component (body only). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009 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>++#define FT_MAKE_OPTION_SINGLE_OBJECT++#include "ftpic.c"+#include "basepic.c"+#include "ftadvanc.c"+#include "ftcalc.c"+#include "ftdbgmem.c"+#include "ftgloadr.c"+#include "ftobjs.c"+#include "ftoutln.c"+#include "ftrfork.c"+#include "ftsnames.c"+#include "ftstream.c"+#include "fttrigon.c"+#include "ftutil.c"++#if defined( FT_MACINTOSH ) && !defined ( DARWIN_NO_CARBON )+#include "ftmac.c"+#endif++/* END */
+ src/base/ftbase.h view
@@ -0,0 +1,68 @@+/***************************************************************************/+/* */+/* ftbase.h */+/* */+/* The FreeType private functions used in base module (specification). */+/* */+/* Copyright 2008, 2010 by */+/* David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#ifndef __FTBASE_H__+#define __FTBASE_H__+++#include <ft2build.h>+#include FT_INTERNAL_OBJECTS_H+++FT_BEGIN_HEADER+++ /* Assume the stream is sfnt-wrapped PS Type1 or sfnt-wrapped CID-keyed */+ /* font, and try to load a face specified by the face_index. */+ FT_LOCAL( FT_Error )+ open_face_PS_from_sfnt_stream( FT_Library library,+ FT_Stream stream,+ FT_Long face_index,+ FT_Int num_params,+ FT_Parameter *params,+ FT_Face *aface );+++ /* Create a new FT_Face given a buffer and a driver name. */+ /* From ftmac.c. */+ FT_LOCAL( FT_Error )+ open_face_from_buffer( FT_Library library,+ FT_Byte* base,+ FT_ULong size,+ FT_Long face_index,+ const char* driver_name,+ FT_Face *aface );+++#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK+ /* Mac OS X/Darwin kernel often changes recommended method to access */+ /* the resource fork and older methods makes the kernel issue the */+ /* warning of deprecated method. To calm it down, the methods based */+ /* on Darwin VFS should be grouped and skip the rest methods after */+ /* the case the resource is opened but found to lack a font in it. */+ FT_LOCAL( FT_Bool )+ raccess_rule_by_darwin_vfs( FT_UInt rule_index );+#endif /* FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */+++FT_END_HEADER++#endif /* __FTBASE_H__ */+++/* END */
+ src/base/ftbbox.c view
@@ -0,0 +1,662 @@+/***************************************************************************/+/* */+/* ftbbox.c */+/* */+/* FreeType bbox computation (body). */+/* */+/* Copyright 1996-2001, 2002, 2004, 2006, 2010 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used */+/* modified and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++ /*************************************************************************/+ /* */+ /* This component has a _single_ role: to compute exact outline bounding */+ /* boxes. */+ /* */+ /*************************************************************************/+++#include <ft2build.h>+#include FT_BBOX_H+#include FT_IMAGE_H+#include FT_OUTLINE_H+#include FT_INTERNAL_CALC_H+#include FT_INTERNAL_OBJECTS_H+++ typedef struct TBBox_Rec_+ {+ FT_Vector last;+ FT_BBox bbox;++ } TBBox_Rec;+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* BBox_Move_To */+ /* */+ /* <Description> */+ /* This function is used as a `move_to' and `line_to' emitter during */+ /* FT_Outline_Decompose(). It simply records the destination point */+ /* in `user->last'; no further computations are necessary since we */+ /* use the cbox as the starting bbox which must be refined. */+ /* */+ /* <Input> */+ /* to :: A pointer to the destination vector. */+ /* */+ /* <InOut> */+ /* user :: A pointer to the current walk context. */+ /* */+ /* <Return> */+ /* Always 0. Needed for the interface only. */+ /* */+ static int+ BBox_Move_To( FT_Vector* to,+ TBBox_Rec* user )+ {+ user->last = *to;++ return 0;+ }+++#define CHECK_X( p, bbox ) \+ ( p->x < bbox.xMin || p->x > bbox.xMax )++#define CHECK_Y( p, bbox ) \+ ( p->y < bbox.yMin || p->y > bbox.yMax )+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* BBox_Conic_Check */+ /* */+ /* <Description> */+ /* Finds the extrema of a 1-dimensional conic Bezier curve and update */+ /* a bounding range. This version uses direct computation, as it */+ /* doesn't need square roots. */+ /* */+ /* <Input> */+ /* y1 :: The start coordinate. */+ /* */+ /* y2 :: The coordinate of the control point. */+ /* */+ /* y3 :: The end coordinate. */+ /* */+ /* <InOut> */+ /* min :: The address of the current minimum. */+ /* */+ /* max :: The address of the current maximum. */+ /* */+ static void+ BBox_Conic_Check( FT_Pos y1,+ FT_Pos y2,+ FT_Pos y3,+ FT_Pos* min,+ FT_Pos* max )+ {+ if ( y1 <= y3 && y2 == y1 ) /* flat arc */+ goto Suite;++ if ( y1 < y3 )+ {+ if ( y2 >= y1 && y2 <= y3 ) /* ascending arc */+ goto Suite;+ }+ else+ {+ if ( y2 >= y3 && y2 <= y1 ) /* descending arc */+ {+ y2 = y1;+ y1 = y3;+ y3 = y2;+ goto Suite;+ }+ }++ y1 = y3 = y1 - FT_MulDiv( y2 - y1, y2 - y1, y1 - 2*y2 + y3 );++ Suite:+ if ( y1 < *min ) *min = y1;+ if ( y3 > *max ) *max = y3;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* BBox_Conic_To */+ /* */+ /* <Description> */+ /* This function is used as a `conic_to' emitter during */+ /* FT_Outline_Decompose(). It checks a conic Bezier curve with the */+ /* current bounding box, and computes its extrema if necessary to */+ /* update it. */+ /* */+ /* <Input> */+ /* control :: A pointer to a control point. */+ /* */+ /* to :: A pointer to the destination vector. */+ /* */+ /* <InOut> */+ /* user :: The address of the current walk context. */+ /* */+ /* <Return> */+ /* Always 0. Needed for the interface only. */+ /* */+ /* <Note> */+ /* In the case of a non-monotonous arc, we compute directly the */+ /* extremum coordinates, as it is sufficiently fast. */+ /* */+ static int+ BBox_Conic_To( FT_Vector* control,+ FT_Vector* to,+ TBBox_Rec* user )+ {+ /* we don't need to check `to' since it is always an `on' point, thus */+ /* within the bbox */++ if ( CHECK_X( control, user->bbox ) )+ BBox_Conic_Check( user->last.x,+ control->x,+ to->x,+ &user->bbox.xMin,+ &user->bbox.xMax );++ if ( CHECK_Y( control, user->bbox ) )+ BBox_Conic_Check( user->last.y,+ control->y,+ to->y,+ &user->bbox.yMin,+ &user->bbox.yMax );++ user->last = *to;++ return 0;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* BBox_Cubic_Check */+ /* */+ /* <Description> */+ /* Finds the extrema of a 1-dimensional cubic Bezier curve and */+ /* updates a bounding range. This version uses splitting because we */+ /* don't want to use square roots and extra accuracy. */+ /* */+ /* <Input> */+ /* p1 :: The start coordinate. */+ /* */+ /* p2 :: The coordinate of the first control point. */+ /* */+ /* p3 :: The coordinate of the second control point. */+ /* */+ /* p4 :: The end coordinate. */+ /* */+ /* <InOut> */+ /* min :: The address of the current minimum. */+ /* */+ /* max :: The address of the current maximum. */+ /* */++#if 0++ static void+ BBox_Cubic_Check( FT_Pos p1,+ FT_Pos p2,+ FT_Pos p3,+ FT_Pos p4,+ FT_Pos* min,+ FT_Pos* max )+ {+ FT_Pos stack[32*3 + 1], *arc;+++ arc = stack;++ arc[0] = p1;+ arc[1] = p2;+ arc[2] = p3;+ arc[3] = p4;++ do+ {+ FT_Pos y1 = arc[0];+ FT_Pos y2 = arc[1];+ FT_Pos y3 = arc[2];+ FT_Pos y4 = arc[3];+++ if ( y1 == y4 )+ {+ if ( y1 == y2 && y1 == y3 ) /* flat */+ goto Test;+ }+ else if ( y1 < y4 )+ {+ if ( y2 >= y1 && y2 <= y4 && y3 >= y1 && y3 <= y4 ) /* ascending */+ goto Test;+ }+ else+ {+ if ( y2 >= y4 && y2 <= y1 && y3 >= y4 && y3 <= y1 ) /* descending */+ {+ y2 = y1;+ y1 = y4;+ y4 = y2;+ goto Test;+ }+ }++ /* unknown direction -- split the arc in two */+ arc[6] = y4;+ arc[1] = y1 = ( y1 + y2 ) / 2;+ arc[5] = y4 = ( y4 + y3 ) / 2;+ y2 = ( y2 + y3 ) / 2;+ arc[2] = y1 = ( y1 + y2 ) / 2;+ arc[4] = y4 = ( y4 + y2 ) / 2;+ arc[3] = ( y1 + y4 ) / 2;++ arc += 3;+ goto Suite;++ Test:+ if ( y1 < *min ) *min = y1;+ if ( y4 > *max ) *max = y4;+ arc -= 3;++ Suite:+ ;+ } while ( arc >= stack );+ }++#else++ static void+ test_cubic_extrema( FT_Pos y1,+ FT_Pos y2,+ FT_Pos y3,+ FT_Pos y4,+ FT_Fixed u,+ FT_Pos* min,+ FT_Pos* max )+ {+ /* FT_Pos a = y4 - 3*y3 + 3*y2 - y1; */+ FT_Pos b = y3 - 2*y2 + y1;+ FT_Pos c = y2 - y1;+ FT_Pos d = y1;+ FT_Pos y;+ FT_Fixed uu;++ FT_UNUSED ( y4 );+++ /* The polynomial is */+ /* */+ /* P(x) = a*x^3 + 3b*x^2 + 3c*x + d , */+ /* */+ /* dP/dx = 3a*x^2 + 6b*x + 3c . */+ /* */+ /* However, we also have */+ /* */+ /* dP/dx(u) = 0 , */+ /* */+ /* which implies by subtraction that */+ /* */+ /* P(u) = b*u^2 + 2c*u + d . */++ if ( u > 0 && u < 0x10000L )+ {+ uu = FT_MulFix( u, u );+ y = d + FT_MulFix( c, 2*u ) + FT_MulFix( b, uu );++ if ( y < *min ) *min = y;+ if ( y > *max ) *max = y;+ }+ }+++ static void+ BBox_Cubic_Check( FT_Pos y1,+ FT_Pos y2,+ FT_Pos y3,+ FT_Pos y4,+ FT_Pos* min,+ FT_Pos* max )+ {+ /* always compare first and last points */+ if ( y1 < *min ) *min = y1;+ else if ( y1 > *max ) *max = y1;++ if ( y4 < *min ) *min = y4;+ else if ( y4 > *max ) *max = y4;++ /* now, try to see if there are split points here */+ if ( y1 <= y4 )+ {+ /* flat or ascending arc test */+ if ( y1 <= y2 && y2 <= y4 && y1 <= y3 && y3 <= y4 )+ return;+ }+ else /* y1 > y4 */+ {+ /* descending arc test */+ if ( y1 >= y2 && y2 >= y4 && y1 >= y3 && y3 >= y4 )+ return;+ }++ /* There are some split points. Find them. */+ {+ FT_Pos a = y4 - 3*y3 + 3*y2 - y1;+ FT_Pos b = y3 - 2*y2 + y1;+ FT_Pos c = y2 - y1;+ FT_Pos d;+ FT_Fixed t;+++ /* We need to solve `ax^2+2bx+c' here, without floating points! */+ /* The trick is to normalize to a different representation in order */+ /* to use our 16.16 fixed point routines. */+ /* */+ /* We compute FT_MulFix(b,b) and FT_MulFix(a,c) after normalization. */+ /* These values must fit into a single 16.16 value. */+ /* */+ /* We normalize a, b, and c to `8.16' fixed float values to ensure */+ /* that its product is held in a `16.16' value. */++ {+ FT_ULong t1, t2;+ int shift = 0;+++ /* The following computation is based on the fact that for */+ /* any value `y', if `n' is the position of the most */+ /* significant bit of `abs(y)' (starting from 0 for the */+ /* least significant bit), then `y' is in the range */+ /* */+ /* -2^n..2^n-1 */+ /* */+ /* We want to shift `a', `b', and `c' concurrently in order */+ /* to ensure that they all fit in 8.16 values, which maps */+ /* to the integer range `-2^23..2^23-1'. */+ /* */+ /* Necessarily, we need to shift `a', `b', and `c' so that */+ /* the most significant bit of its absolute values is at */+ /* _most_ at position 23. */+ /* */+ /* We begin by computing `t1' as the bitwise `OR' of the */+ /* absolute values of `a', `b', `c'. */++ t1 = (FT_ULong)( ( a >= 0 ) ? a : -a );+ t2 = (FT_ULong)( ( b >= 0 ) ? b : -b );+ t1 |= t2;+ t2 = (FT_ULong)( ( c >= 0 ) ? c : -c );+ t1 |= t2;++ /* Now we can be sure that the most significant bit of `t1' */+ /* is the most significant bit of either `a', `b', or `c', */+ /* depending on the greatest integer range of the particular */+ /* variable. */+ /* */+ /* Next, we compute the `shift', by shifting `t1' as many */+ /* times as necessary to move its MSB to position 23. This */+ /* corresponds to a value of `t1' that is in the range */+ /* 0x40_0000..0x7F_FFFF. */+ /* */+ /* Finally, we shift `a', `b', and `c' by the same amount. */+ /* This ensures that all values are now in the range */+ /* -2^23..2^23, i.e., they are now expressed as 8.16 */+ /* fixed-float numbers. This also means that we are using */+ /* 24 bits of precision to compute the zeros, independently */+ /* of the range of the original polynomial coefficients. */+ /* */+ /* This algorithm should ensure reasonably accurate values */+ /* for the zeros. Note that they are only expressed with */+ /* 16 bits when computing the extrema (the zeros need to */+ /* be in 0..1 exclusive to be considered part of the arc). */++ if ( t1 == 0 ) /* all coefficients are 0! */+ return;++ if ( t1 > 0x7FFFFFUL )+ {+ do+ {+ shift++;+ t1 >>= 1;++ } while ( t1 > 0x7FFFFFUL );++ /* this loses some bits of precision, but we use 24 of them */+ /* for the computation anyway */+ a >>= shift;+ b >>= shift;+ c >>= shift;+ }+ else if ( t1 < 0x400000UL )+ {+ do+ {+ shift++;+ t1 <<= 1;++ } while ( t1 < 0x400000UL );++ a <<= shift;+ b <<= shift;+ c <<= shift;+ }+ }++ /* handle a == 0 */+ if ( a == 0 )+ {+ if ( b != 0 )+ {+ t = - FT_DivFix( c, b ) / 2;+ test_cubic_extrema( y1, y2, y3, y4, t, min, max );+ }+ }+ else+ {+ /* solve the equation now */+ d = FT_MulFix( b, b ) - FT_MulFix( a, c );+ if ( d < 0 )+ return;++ if ( d == 0 )+ {+ /* there is a single split point at -b/a */+ t = - FT_DivFix( b, a );+ test_cubic_extrema( y1, y2, y3, y4, t, min, max );+ }+ else+ {+ /* there are two solutions; we need to filter them */+ d = FT_SqrtFixed( (FT_Int32)d );+ t = - FT_DivFix( b - d, a );+ test_cubic_extrema( y1, y2, y3, y4, t, min, max );++ t = - FT_DivFix( b + d, a );+ test_cubic_extrema( y1, y2, y3, y4, t, min, max );+ }+ }+ }+ }++#endif+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* BBox_Cubic_To */+ /* */+ /* <Description> */+ /* This function is used as a `cubic_to' emitter during */+ /* FT_Outline_Decompose(). It checks a cubic Bezier curve with the */+ /* current bounding box, and computes its extrema if necessary to */+ /* update it. */+ /* */+ /* <Input> */+ /* control1 :: A pointer to the first control point. */+ /* */+ /* control2 :: A pointer to the second control point. */+ /* */+ /* to :: A pointer to the destination vector. */+ /* */+ /* <InOut> */+ /* user :: The address of the current walk context. */+ /* */+ /* <Return> */+ /* Always 0. Needed for the interface only. */+ /* */+ /* <Note> */+ /* In the case of a non-monotonous arc, we don't compute directly */+ /* extremum coordinates, we subdivide instead. */+ /* */+ static int+ BBox_Cubic_To( FT_Vector* control1,+ FT_Vector* control2,+ FT_Vector* to,+ TBBox_Rec* user )+ {+ /* we don't need to check `to' since it is always an `on' point, thus */+ /* within the bbox */++ if ( CHECK_X( control1, user->bbox ) ||+ CHECK_X( control2, user->bbox ) )+ BBox_Cubic_Check( user->last.x,+ control1->x,+ control2->x,+ to->x,+ &user->bbox.xMin,+ &user->bbox.xMax );++ if ( CHECK_Y( control1, user->bbox ) ||+ CHECK_Y( control2, user->bbox ) )+ BBox_Cubic_Check( user->last.y,+ control1->y,+ control2->y,+ to->y,+ &user->bbox.yMin,+ &user->bbox.yMax );++ user->last = *to;++ return 0;+ }++FT_DEFINE_OUTLINE_FUNCS(bbox_interface,+ (FT_Outline_MoveTo_Func) BBox_Move_To,+ (FT_Outline_LineTo_Func) BBox_Move_To,+ (FT_Outline_ConicTo_Func)BBox_Conic_To,+ (FT_Outline_CubicTo_Func)BBox_Cubic_To,+ 0, 0+ )++ /* documentation is in ftbbox.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Outline_Get_BBox( FT_Outline* outline,+ FT_BBox *abbox )+ {+ FT_BBox cbox;+ FT_BBox bbox;+ FT_Vector* vec;+ FT_UShort n;+++ if ( !abbox )+ return FT_Err_Invalid_Argument;++ if ( !outline )+ return FT_Err_Invalid_Outline;++ /* if outline is empty, return (0,0,0,0) */+ if ( outline->n_points == 0 || outline->n_contours <= 0 )+ {+ abbox->xMin = abbox->xMax = 0;+ abbox->yMin = abbox->yMax = 0;+ return 0;+ }++ /* We compute the control box as well as the bounding box of */+ /* all `on' points in the outline. Then, if the two boxes */+ /* coincide, we exit immediately. */++ vec = outline->points;+ bbox.xMin = bbox.xMax = cbox.xMin = cbox.xMax = vec->x;+ bbox.yMin = bbox.yMax = cbox.yMin = cbox.yMax = vec->y;+ vec++;++ for ( n = 1; n < outline->n_points; n++ )+ {+ FT_Pos x = vec->x;+ FT_Pos y = vec->y;+++ /* update control box */+ if ( x < cbox.xMin ) cbox.xMin = x;+ if ( x > cbox.xMax ) cbox.xMax = x;++ if ( y < cbox.yMin ) cbox.yMin = y;+ if ( y > cbox.yMax ) cbox.yMax = y;++ if ( FT_CURVE_TAG( outline->tags[n] ) == FT_CURVE_TAG_ON )+ {+ /* update bbox for `on' points only */+ if ( x < bbox.xMin ) bbox.xMin = x;+ if ( x > bbox.xMax ) bbox.xMax = x;++ if ( y < bbox.yMin ) bbox.yMin = y;+ if ( y > bbox.yMax ) bbox.yMax = y;+ }++ vec++;+ }++ /* test two boxes for equality */+ if ( cbox.xMin < bbox.xMin || cbox.xMax > bbox.xMax ||+ cbox.yMin < bbox.yMin || cbox.yMax > bbox.yMax )+ {+ /* the two boxes are different, now walk over the outline to */+ /* get the Bezier arc extrema. */++ FT_Error error;+ TBBox_Rec user;++#ifdef FT_CONFIG_OPTION_PIC+ FT_Outline_Funcs bbox_interface;+ Init_Class_bbox_interface(&bbox_interface);+#endif++ user.bbox = bbox;++ error = FT_Outline_Decompose( outline, &bbox_interface, &user );+ if ( error )+ return error;++ *abbox = user.bbox;+ }+ else+ *abbox = bbox;++ return FT_Err_Ok;+ }+++/* END */
+ src/base/ftbdf.c view
@@ -0,0 +1,88 @@+/***************************************************************************/+/* */+/* ftbdf.c */+/* */+/* FreeType API for accessing BDF-specific strings (body). */+/* */+/* Copyright 2002, 2003, 2004 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_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;+++ error = FT_Err_Invalid_Argument;++ if ( face )+ {+ FT_Service_BDF service;+++ FT_FACE_FIND_SERVICE( face, service, BDF );++ if ( service && service->get_charset_id )+ error = service->get_charset_id( face, &encoding, ®istry );+ }++ 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;+++ error = FT_Err_Invalid_Argument;++ aproperty->type = BDF_PROPERTY_TYPE_NONE;++ if ( face )+ {+ FT_Service_BDF service;+++ FT_FACE_FIND_SERVICE( face, service, BDF );++ if ( service && service->get_property )+ error = service->get_property( face, prop_name, aproperty );+ }++ return error;+ }+++/* END */
+ src/base/ftbitmap.c view
@@ -0,0 +1,663 @@+/***************************************************************************/+/* */+/* ftbitmap.c */+/* */+/* FreeType utility functions for bitmaps (body). */+/* */+/* Copyright 2004, 2005, 2006, 2007, 2008, 2009 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_BITMAP_H+#include FT_IMAGE_H+#include FT_INTERNAL_OBJECTS_H+++ static+ const FT_Bitmap null_bitmap = { 0, 0, 0, 0, 0, 0, 0, 0 };+++ /* documentation is in ftbitmap.h */++ FT_EXPORT_DEF( void )+ FT_Bitmap_New( FT_Bitmap *abitmap )+ {+ *abitmap = null_bitmap;+ }+++ /* documentation is in ftbitmap.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Bitmap_Copy( FT_Library library,+ const FT_Bitmap *source,+ FT_Bitmap *target)+ {+ FT_Memory memory = library->memory;+ FT_Error error = FT_Err_Ok;+ FT_Int pitch = source->pitch;+ FT_ULong size;+++ if ( source == target )+ return FT_Err_Ok;++ if ( source->buffer == NULL )+ {+ *target = *source;++ return FT_Err_Ok;+ }++ if ( pitch < 0 )+ pitch = -pitch;+ size = (FT_ULong)( pitch * source->rows );++ if ( target->buffer )+ {+ FT_Int target_pitch = target->pitch;+ FT_ULong target_size;+++ if ( target_pitch < 0 )+ target_pitch = -target_pitch;+ target_size = (FT_ULong)( target_pitch * target->rows );++ if ( target_size != size )+ (void)FT_QREALLOC( target->buffer, target_size, size );+ }+ else+ (void)FT_QALLOC( target->buffer, size );++ if ( !error )+ {+ unsigned char *p;+++ p = target->buffer;+ *target = *source;+ target->buffer = p;++ FT_MEM_COPY( target->buffer, source->buffer, size );+ }++ return error;+ }+++ static FT_Error+ ft_bitmap_assure_buffer( FT_Memory memory,+ FT_Bitmap* bitmap,+ FT_UInt xpixels,+ FT_UInt ypixels )+ {+ FT_Error error;+ int pitch;+ int new_pitch;+ FT_UInt bpp;+ FT_Int i, width, height;+ unsigned char* buffer;+++ width = bitmap->width;+ height = bitmap->rows;+ pitch = bitmap->pitch;+ if ( pitch < 0 )+ pitch = -pitch;++ switch ( bitmap->pixel_mode )+ {+ case FT_PIXEL_MODE_MONO:+ bpp = 1;+ new_pitch = ( width + xpixels + 7 ) >> 3;+ break;+ case FT_PIXEL_MODE_GRAY2:+ bpp = 2;+ new_pitch = ( width + xpixels + 3 ) >> 2;+ break;+ case FT_PIXEL_MODE_GRAY4:+ bpp = 4;+ new_pitch = ( width + xpixels + 1 ) >> 1;+ break;+ case FT_PIXEL_MODE_GRAY:+ case FT_PIXEL_MODE_LCD:+ case FT_PIXEL_MODE_LCD_V:+ bpp = 8;+ new_pitch = ( width + xpixels );+ break;+ default:+ return FT_Err_Invalid_Glyph_Format;+ }++ /* if no need to allocate memory */+ if ( ypixels == 0 && new_pitch <= pitch )+ {+ /* zero the padding */+ FT_Int bit_width = pitch * 8;+ FT_Int bit_last = ( width + xpixels ) * bpp;+++ if ( bit_last < bit_width )+ {+ FT_Byte* line = bitmap->buffer + ( bit_last >> 3 );+ FT_Byte* end = bitmap->buffer + pitch;+ FT_Int shift = bit_last & 7;+ FT_UInt mask = 0xFF00U >> shift;+ FT_Int count = height;+++ for ( ; count > 0; count--, line += pitch, end += pitch )+ {+ FT_Byte* write = line;+++ if ( shift > 0 )+ {+ write[0] = (FT_Byte)( write[0] & mask );+ write++;+ }+ if ( write < end )+ FT_MEM_ZERO( write, end-write );+ }+ }++ return FT_Err_Ok;+ }++ if ( FT_QALLOC_MULT( buffer, new_pitch, bitmap->rows + ypixels ) )+ return error;++ if ( bitmap->pitch > 0 )+ {+ FT_Int len = ( width * bpp + 7 ) >> 3;+++ for ( i = 0; i < bitmap->rows; i++ )+ FT_MEM_COPY( buffer + new_pitch * ( ypixels + i ),+ bitmap->buffer + pitch * i, len );+ }+ else+ {+ FT_Int len = ( width * bpp + 7 ) >> 3;+++ for ( i = 0; i < bitmap->rows; i++ )+ FT_MEM_COPY( buffer + new_pitch * i,+ bitmap->buffer + pitch * i, len );+ }++ FT_FREE( bitmap->buffer );+ bitmap->buffer = buffer;++ if ( bitmap->pitch < 0 )+ new_pitch = -new_pitch;++ /* set pitch only, width and height are left untouched */+ bitmap->pitch = new_pitch;++ return FT_Err_Ok;+ }+++ /* documentation is in ftbitmap.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Bitmap_Embolden( FT_Library library,+ FT_Bitmap* bitmap,+ FT_Pos xStrength,+ FT_Pos yStrength )+ {+ FT_Error error;+ unsigned char* p;+ FT_Int i, x, y, pitch;+ FT_Int xstr, ystr;+++ if ( !library )+ return FT_Err_Invalid_Library_Handle;++ if ( !bitmap || !bitmap->buffer )+ return FT_Err_Invalid_Argument;++ if ( ( ( FT_PIX_ROUND( xStrength ) >> 6 ) > FT_INT_MAX ) ||+ ( ( FT_PIX_ROUND( yStrength ) >> 6 ) > FT_INT_MAX ) )+ return FT_Err_Invalid_Argument;+ + xstr = (FT_Int)FT_PIX_ROUND( xStrength ) >> 6;+ ystr = (FT_Int)FT_PIX_ROUND( yStrength ) >> 6;++ if ( xstr == 0 && ystr == 0 )+ return FT_Err_Ok;+ else if ( xstr < 0 || ystr < 0 )+ return FT_Err_Invalid_Argument;++ switch ( bitmap->pixel_mode )+ {+ case FT_PIXEL_MODE_GRAY2:+ case FT_PIXEL_MODE_GRAY4:+ {+ FT_Bitmap tmp;+ FT_Int align;+++ if ( bitmap->pixel_mode == FT_PIXEL_MODE_GRAY2 )+ align = ( bitmap->width + xstr + 3 ) / 4;+ else+ align = ( bitmap->width + xstr + 1 ) / 2;++ FT_Bitmap_New( &tmp );++ error = FT_Bitmap_Convert( library, bitmap, &tmp, align );+ if ( error )+ return error;++ FT_Bitmap_Done( library, bitmap );+ *bitmap = tmp;+ }+ break;++ case FT_PIXEL_MODE_MONO:+ if ( xstr > 8 )+ xstr = 8;+ break;++ case FT_PIXEL_MODE_LCD:+ xstr *= 3;+ break;++ case FT_PIXEL_MODE_LCD_V:+ ystr *= 3;+ break;+ }++ error = ft_bitmap_assure_buffer( library->memory, bitmap, xstr, ystr );+ if ( error )+ return error;++ pitch = bitmap->pitch;+ if ( pitch > 0 )+ p = bitmap->buffer + pitch * ystr;+ else+ {+ pitch = -pitch;+ p = bitmap->buffer + pitch * ( bitmap->rows - 1 );+ }++ /* for each row */+ for ( y = 0; y < bitmap->rows ; y++ )+ {+ /*+ * Horizontally:+ *+ * From the last pixel on, make each pixel or'ed with the+ * `xstr' pixels before it.+ */+ for ( x = pitch - 1; x >= 0; x-- )+ {+ unsigned char tmp;+++ tmp = p[x];+ for ( i = 1; i <= xstr; i++ )+ {+ if ( bitmap->pixel_mode == FT_PIXEL_MODE_MONO )+ {+ p[x] |= tmp >> i;++ /* the maximum value of 8 for `xstr' comes from here */+ if ( x > 0 )+ p[x] |= p[x - 1] << ( 8 - i );++#if 0+ if ( p[x] == 0xff )+ break;+#endif+ }+ else+ {+ if ( x - i >= 0 )+ {+ if ( p[x] + p[x - i] > bitmap->num_grays - 1 )+ {+ p[x] = (unsigned char)(bitmap->num_grays - 1);+ break;+ }+ else+ {+ p[x] = (unsigned char)(p[x] + p[x-i]);+ if ( p[x] == bitmap->num_grays - 1 )+ break;+ }+ }+ else+ break;+ }+ }+ }++ /*+ * Vertically:+ *+ * Make the above `ystr' rows or'ed with it.+ */+ for ( x = 1; x <= ystr; x++ )+ {+ unsigned char* q;+++ q = p - bitmap->pitch * x;+ for ( i = 0; i < pitch; i++ )+ q[i] |= p[i];+ }++ p += bitmap->pitch;+ }++ bitmap->width += xstr;+ bitmap->rows += ystr;++ return FT_Err_Ok;+ }+++ /* documentation is in ftbitmap.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Bitmap_Convert( FT_Library library,+ const FT_Bitmap *source,+ FT_Bitmap *target,+ FT_Int alignment )+ {+ FT_Error error = FT_Err_Ok;+ FT_Memory memory;+++ if ( !library )+ return FT_Err_Invalid_Library_Handle;++ memory = library->memory;++ switch ( source->pixel_mode )+ {+ case FT_PIXEL_MODE_MONO:+ case FT_PIXEL_MODE_GRAY:+ case FT_PIXEL_MODE_GRAY2:+ case FT_PIXEL_MODE_GRAY4:+ case FT_PIXEL_MODE_LCD:+ case FT_PIXEL_MODE_LCD_V:+ {+ FT_Int pad;+ FT_Long old_size;+++ old_size = target->rows * target->pitch;+ if ( old_size < 0 )+ old_size = -old_size;++ target->pixel_mode = FT_PIXEL_MODE_GRAY;+ target->rows = source->rows;+ target->width = source->width;++ pad = 0;+ if ( alignment > 0 )+ {+ pad = source->width % alignment;+ if ( pad != 0 )+ pad = alignment - pad;+ }++ target->pitch = source->width + pad;++ if ( target->rows * target->pitch > old_size &&+ FT_QREALLOC( target->buffer,+ old_size, target->rows * target->pitch ) )+ return error;+ }+ break;++ default:+ error = FT_Err_Invalid_Argument;+ }++ switch ( source->pixel_mode )+ {+ case FT_PIXEL_MODE_MONO:+ {+ FT_Byte* s = source->buffer;+ FT_Byte* t = target->buffer;+ FT_Int i;+++ target->num_grays = 2;++ for ( i = source->rows; i > 0; i-- )+ {+ FT_Byte* ss = s;+ FT_Byte* tt = t;+ FT_Int j;+++ /* get the full bytes */+ for ( j = source->width >> 3; j > 0; j-- )+ {+ FT_Int val = ss[0]; /* avoid a byte->int cast on each line */+++ tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7 );+ tt[1] = (FT_Byte)( ( val & 0x40 ) >> 6 );+ tt[2] = (FT_Byte)( ( val & 0x20 ) >> 5 );+ tt[3] = (FT_Byte)( ( val & 0x10 ) >> 4 );+ tt[4] = (FT_Byte)( ( val & 0x08 ) >> 3 );+ tt[5] = (FT_Byte)( ( val & 0x04 ) >> 2 );+ tt[6] = (FT_Byte)( ( val & 0x02 ) >> 1 );+ tt[7] = (FT_Byte)( val & 0x01 );++ tt += 8;+ ss += 1;+ }++ /* get remaining pixels (if any) */+ j = source->width & 7;+ if ( j > 0 )+ {+ FT_Int val = *ss;+++ for ( ; j > 0; j-- )+ {+ tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7);+ val <<= 1;+ tt += 1;+ }+ }++ s += source->pitch;+ t += target->pitch;+ }+ }+ break;+++ case FT_PIXEL_MODE_GRAY:+ case FT_PIXEL_MODE_LCD:+ case FT_PIXEL_MODE_LCD_V:+ {+ FT_Int width = source->width;+ FT_Byte* s = source->buffer;+ FT_Byte* t = target->buffer;+ FT_Int s_pitch = source->pitch;+ FT_Int t_pitch = target->pitch;+ FT_Int i;+++ target->num_grays = 256;++ for ( i = source->rows; i > 0; i-- )+ {+ FT_ARRAY_COPY( t, s, width );++ s += s_pitch;+ t += t_pitch;+ }+ }+ break;+++ case FT_PIXEL_MODE_GRAY2:+ {+ FT_Byte* s = source->buffer;+ FT_Byte* t = target->buffer;+ FT_Int i;+++ target->num_grays = 4;++ for ( i = source->rows; i > 0; i-- )+ {+ FT_Byte* ss = s;+ FT_Byte* tt = t;+ FT_Int j;+++ /* get the full bytes */+ for ( j = source->width >> 2; j > 0; j-- )+ {+ FT_Int val = ss[0];+++ tt[0] = (FT_Byte)( ( val & 0xC0 ) >> 6 );+ tt[1] = (FT_Byte)( ( val & 0x30 ) >> 4 );+ tt[2] = (FT_Byte)( ( val & 0x0C ) >> 2 );+ tt[3] = (FT_Byte)( ( val & 0x03 ) );++ ss += 1;+ tt += 4;+ }++ j = source->width & 3;+ if ( j > 0 )+ {+ FT_Int val = ss[0];+++ for ( ; j > 0; j-- )+ {+ tt[0] = (FT_Byte)( ( val & 0xC0 ) >> 6 );+ val <<= 2;+ tt += 1;+ }+ }++ s += source->pitch;+ t += target->pitch;+ }+ }+ break;+++ case FT_PIXEL_MODE_GRAY4:+ {+ FT_Byte* s = source->buffer;+ FT_Byte* t = target->buffer;+ FT_Int i;+++ target->num_grays = 16;++ for ( i = source->rows; i > 0; i-- )+ {+ FT_Byte* ss = s;+ FT_Byte* tt = t;+ FT_Int j;+++ /* get the full bytes */+ for ( j = source->width >> 1; j > 0; j-- )+ {+ FT_Int val = ss[0];+++ tt[0] = (FT_Byte)( ( val & 0xF0 ) >> 4 );+ tt[1] = (FT_Byte)( ( val & 0x0F ) );++ ss += 1;+ tt += 2;+ }++ if ( source->width & 1 )+ tt[0] = (FT_Byte)( ( ss[0] & 0xF0 ) >> 4 );++ s += source->pitch;+ t += target->pitch;+ }+ }+ break;+++ default:+ ;+ }++ return error;+ }+++ /* documentation is in ftbitmap.h */++ FT_EXPORT_DEF( FT_Error )+ FT_GlyphSlot_Own_Bitmap( FT_GlyphSlot slot )+ {+ if ( slot && slot->format == FT_GLYPH_FORMAT_BITMAP &&+ !( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) )+ {+ FT_Bitmap bitmap;+ FT_Error error;+++ FT_Bitmap_New( &bitmap );+ error = FT_Bitmap_Copy( slot->library, &slot->bitmap, &bitmap );+ if ( error )+ return error;++ slot->bitmap = bitmap;+ slot->internal->flags |= FT_GLYPH_OWN_BITMAP;+ }++ return FT_Err_Ok;+ }+++ /* documentation is in ftbitmap.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Bitmap_Done( FT_Library library,+ FT_Bitmap *bitmap )+ {+ FT_Memory memory;+++ if ( !library )+ return FT_Err_Invalid_Library_Handle;++ if ( !bitmap )+ return FT_Err_Invalid_Argument;++ memory = library->memory;++ FT_FREE( bitmap->buffer );+ *bitmap = null_bitmap;++ return FT_Err_Ok;+ }+++/* END */
+ src/base/ftcalc.c view
@@ -0,0 +1,957 @@+/***************************************************************************/+/* */+/* ftcalc.c */+/* */+/* Arithmetic computations (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2008 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. */+/* */+/***************************************************************************/++ /*************************************************************************/+ /* */+ /* Support for 1-complement arithmetic has been totally dropped in this */+ /* release. You can still write your own code if you need it. */+ /* */+ /*************************************************************************/++ /*************************************************************************/+ /* */+ /* Implementing basic computation routines. */+ /* */+ /* FT_MulDiv(), FT_MulFix(), FT_DivFix(), FT_RoundFix(), FT_CeilFix(), */+ /* and FT_FloorFix() are declared in freetype.h. */+ /* */+ /*************************************************************************/+++#include <ft2build.h>+#include FT_GLYPH_H+#include FT_INTERNAL_CALC_H+#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_OBJECTS_H++#ifdef FT_MULFIX_INLINED+#undef FT_MulFix+#endif++/* we need to define a 64-bits data type here */++#ifdef FT_LONG64++ typedef FT_INT64 FT_Int64;++#else++ typedef struct FT_Int64_+ {+ FT_UInt32 lo;+ FT_UInt32 hi;++ } FT_Int64;++#endif /* FT_LONG64 */+++ /*************************************************************************/+ /* */+ /* 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_calc+++ /* The following three functions are available regardless of whether */+ /* FT_LONG64 is defined. */++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Fixed )+ FT_RoundFix( FT_Fixed a )+ {+ return ( a >= 0 ) ? ( a + 0x8000L ) & ~0xFFFFL+ : -((-a + 0x8000L ) & ~0xFFFFL );+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Fixed )+ FT_CeilFix( FT_Fixed a )+ {+ return ( a >= 0 ) ? ( a + 0xFFFFL ) & ~0xFFFFL+ : -((-a + 0xFFFFL ) & ~0xFFFFL );+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Fixed )+ FT_FloorFix( FT_Fixed a )+ {+ return ( a >= 0 ) ? a & ~0xFFFFL+ : -((-a) & ~0xFFFFL );+ }+++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS++ /* documentation is in ftcalc.h */++ FT_EXPORT_DEF( FT_Int32 )+ FT_Sqrt32( FT_Int32 x )+ {+ FT_UInt32 val, root, newroot, mask;+++ root = 0;+ mask = (FT_UInt32)0x40000000UL;+ val = (FT_UInt32)x;++ do+ {+ newroot = root + mask;+ if ( newroot <= val )+ {+ val -= newroot;+ root = newroot + mask;+ }++ root >>= 1;+ mask >>= 2;++ } while ( mask != 0 );++ return root;+ }++#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */+++#ifdef FT_LONG64+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Long )+ FT_MulDiv( FT_Long a,+ FT_Long b,+ FT_Long c )+ {+ FT_Int s;+ FT_Long d;+++ s = 1;+ if ( a < 0 ) { a = -a; s = -1; }+ if ( b < 0 ) { b = -b; s = -s; }+ if ( c < 0 ) { c = -c; s = -s; }++ d = (FT_Long)( c > 0 ? ( (FT_Int64)a * b + ( c >> 1 ) ) / c+ : 0x7FFFFFFFL );++ return ( s > 0 ) ? d : -d;+ }+++#ifdef TT_USE_BYTECODE_INTERPRETER++ /* documentation is in ftcalc.h */++ FT_BASE_DEF( FT_Long )+ FT_MulDiv_No_Round( FT_Long a,+ FT_Long b,+ FT_Long c )+ {+ FT_Int s;+ FT_Long d;+++ s = 1;+ if ( a < 0 ) { a = -a; s = -1; }+ if ( b < 0 ) { b = -b; s = -s; }+ if ( c < 0 ) { c = -c; s = -s; }++ d = (FT_Long)( c > 0 ? (FT_Int64)a * b / c+ : 0x7FFFFFFFL );++ return ( s > 0 ) ? d : -d;+ }++#endif /* TT_USE_BYTECODE_INTERPRETER */+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Long )+ FT_MulFix( FT_Long a,+ FT_Long b )+ {+#ifdef FT_MULFIX_ASSEMBLER++ return FT_MULFIX_ASSEMBLER( a, b );++#else++ FT_Int s = 1;+ FT_Long c;+++ if ( a < 0 )+ {+ a = -a;+ s = -1;+ }++ if ( b < 0 )+ {+ b = -b;+ s = -s;+ }++ c = (FT_Long)( ( (FT_Int64)a * b + 0x8000L ) >> 16 );++ return ( s > 0 ) ? c : -c;++#endif /* FT_MULFIX_ASSEMBLER */+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Long )+ FT_DivFix( FT_Long a,+ FT_Long b )+ {+ FT_Int32 s;+ FT_UInt32 q;++ s = 1;+ if ( a < 0 ) { a = -a; s = -1; }+ if ( b < 0 ) { b = -b; s = -s; }++ if ( b == 0 )+ /* check for division by 0 */+ q = 0x7FFFFFFFL;+ else+ /* compute result directly */+ q = (FT_UInt32)( ( ( (FT_Int64)a << 16 ) + ( b >> 1 ) ) / b );++ return ( s < 0 ? -(FT_Long)q : (FT_Long)q );+ }+++#else /* !FT_LONG64 */+++ static void+ ft_multo64( FT_UInt32 x,+ FT_UInt32 y,+ FT_Int64 *z )+ {+ FT_UInt32 lo1, hi1, lo2, hi2, lo, hi, i1, i2;+++ lo1 = x & 0x0000FFFFU; hi1 = x >> 16;+ lo2 = y & 0x0000FFFFU; hi2 = y >> 16;++ lo = lo1 * lo2;+ i1 = lo1 * hi2;+ i2 = lo2 * hi1;+ hi = hi1 * hi2;++ /* Check carry overflow of i1 + i2 */+ i1 += i2;+ hi += (FT_UInt32)( i1 < i2 ) << 16;++ hi += i1 >> 16;+ i1 = i1 << 16;++ /* Check carry overflow of i1 + lo */+ lo += i1;+ hi += ( lo < i1 );++ z->lo = lo;+ z->hi = hi;+ }+++ static FT_UInt32+ ft_div64by32( FT_UInt32 hi,+ FT_UInt32 lo,+ FT_UInt32 y )+ {+ FT_UInt32 r, q;+ FT_Int i;+++ q = 0;+ r = hi;++ if ( r >= y )+ return (FT_UInt32)0x7FFFFFFFL;++ i = 32;+ do+ {+ r <<= 1;+ q <<= 1;+ r |= lo >> 31;++ if ( r >= (FT_UInt32)y )+ {+ r -= y;+ q |= 1;+ }+ lo <<= 1;+ } while ( --i );++ return q;+ }+++ static void+ FT_Add64( FT_Int64* x,+ FT_Int64* y,+ FT_Int64 *z )+ {+ register FT_UInt32 lo, hi;+++ lo = x->lo + y->lo;+ hi = x->hi + y->hi + ( lo < x->lo );++ z->lo = lo;+ z->hi = hi;+ }+++ /* documentation is in freetype.h */++ /* The FT_MulDiv function has been optimized thanks to ideas from */+ /* Graham Asher. The trick is to optimize computation when everything */+ /* fits within 32-bits (a rather common case). */+ /* */+ /* we compute 'a*b+c/2', then divide it by 'c'. (positive values) */+ /* */+ /* 46340 is FLOOR(SQRT(2^31-1)). */+ /* */+ /* if ( a <= 46340 && b <= 46340 ) then ( a*b <= 0x7FFEA810 ) */+ /* */+ /* 0x7FFFFFFF - 0x7FFEA810 = 0x157F0 */+ /* */+ /* if ( c < 0x157F0*2 ) then ( a*b+c/2 <= 0x7FFFFFFF ) */+ /* */+ /* and 2*0x157F0 = 176096 */+ /* */++ FT_EXPORT_DEF( FT_Long )+ FT_MulDiv( FT_Long a,+ FT_Long b,+ FT_Long c )+ {+ long s;+++ /* XXX: this function does not allow 64-bit arguments */+ if ( a == 0 || b == c )+ return a;++ s = a; a = FT_ABS( a );+ s ^= b; b = FT_ABS( b );+ s ^= c; c = FT_ABS( c );++ if ( a <= 46340L && b <= 46340L && c <= 176095L && c > 0 )+ a = ( a * b + ( c >> 1 ) ) / c;++ else if ( c > 0 )+ {+ FT_Int64 temp, temp2;+++ ft_multo64( (FT_Int32)a, (FT_Int32)b, &temp );++ temp2.hi = 0;+ temp2.lo = (FT_UInt32)(c >> 1);+ FT_Add64( &temp, &temp2, &temp );+ a = ft_div64by32( temp.hi, temp.lo, (FT_Int32)c );+ }+ else+ a = 0x7FFFFFFFL;++ return ( s < 0 ? -a : a );+ }+++#ifdef TT_USE_BYTECODE_INTERPRETER++ FT_BASE_DEF( FT_Long )+ FT_MulDiv_No_Round( FT_Long a,+ FT_Long b,+ FT_Long c )+ {+ long s;+++ if ( a == 0 || b == c )+ return a;++ s = a; a = FT_ABS( a );+ s ^= b; b = FT_ABS( b );+ s ^= c; c = FT_ABS( c );++ if ( a <= 46340L && b <= 46340L && c > 0 )+ a = a * b / c;++ else if ( c > 0 )+ {+ FT_Int64 temp;+++ ft_multo64( (FT_Int32)a, (FT_Int32)b, &temp );+ a = ft_div64by32( temp.hi, temp.lo, (FT_Int32)c );+ }+ else+ a = 0x7FFFFFFFL;++ return ( s < 0 ? -a : a );+ }++#endif /* TT_USE_BYTECODE_INTERPRETER */+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Long )+ FT_MulFix( FT_Long a,+ FT_Long b )+ {+#ifdef FT_MULFIX_ASSEMBLER++ return FT_MULFIX_ASSEMBLER( a, b );++#elif 0++ /*+ * This code is nonportable. See comment below.+ *+ * However, on a platform where right-shift of a signed quantity fills+ * the leftmost bits by copying the sign bit, it might be faster.+ */++ FT_Long sa, sb;+ FT_ULong ua, ub;+++ 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+ * stored in `sa'; 0 means `a' was positive or zero, and -1 means `a'+ * was negative. (Similarly for `b' and `sb').+ *+ * Unfortunately, it doesn't work (at least not portably).+ *+ * It makes the assumption that right-shift on a negative signed value+ * fills the leftmost bits by copying the sign bit. This is wrong. + * According to K&R 2nd ed, section `A7.8 Shift Operators' on page 206,+ * the result of right-shift of a negative signed value is+ * implementation-defined. At least one implementation fills the+ * leftmost bits with 0s (i.e., it is exactly the same as an unsigned+ * right shift). This means that when `a' is negative, `sa' ends up+ * with the value 1 rather than -1. After that, everything else goes+ * wrong.+ */+ sa = ( a >> ( sizeof ( a ) * 8 - 1 ) );+ a = ( a ^ sa ) - sa;+ sb = ( b >> ( sizeof ( b ) * 8 - 1 ) );+ b = ( b ^ sb ) - sb;++ ua = (FT_ULong)a;+ ub = (FT_ULong)b;++ if ( ua <= 2048 && ub <= 1048576L )+ ua = ( ua * ub + 0x8000U ) >> 16;+ else+ {+ FT_ULong al = ua & 0xFFFFU;+++ ua = ( ua >> 16 ) * ub + al * ( ub >> 16 ) ++ ( ( al * ( ub & 0xFFFFU ) + 0x8000U ) >> 16 );+ }++ sa ^= sb,+ ua = (FT_ULong)(( ua ^ sa ) - sa);++ return (FT_Long)ua;++#else /* 0 */++ FT_Long s;+ FT_ULong ua, ub;+++ if ( a == 0 || b == 0x10000L )+ return a;++ s = a; a = FT_ABS( a );+ s ^= b; b = FT_ABS( b );++ ua = (FT_ULong)a;+ ub = (FT_ULong)b;++ if ( ua <= 2048 && ub <= 1048576L )+ ua = ( ua * ub + 0x8000UL ) >> 16;+ else+ {+ FT_ULong al = ua & 0xFFFFUL;+++ ua = ( ua >> 16 ) * ub + al * ( ub >> 16 ) ++ ( ( al * ( ub & 0xFFFFUL ) + 0x8000UL ) >> 16 );+ }++ return ( s < 0 ? -(FT_Long)ua : (FT_Long)ua );++#endif /* 0 */++ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Long )+ FT_DivFix( FT_Long a,+ FT_Long b )+ {+ FT_Int32 s;+ FT_UInt32 q;+++ /* XXX: this function does not allow 64-bit arguments */+ s = (FT_Int32)a; a = FT_ABS( a );+ s ^= (FT_Int32)b; b = FT_ABS( b );++ if ( b == 0 )+ {+ /* check for division by 0 */+ q = (FT_UInt32)0x7FFFFFFFL;+ }+ else if ( ( a >> 16 ) == 0 )+ {+ /* compute result directly */+ q = (FT_UInt32)( (a << 16) + (b >> 1) ) / (FT_UInt32)b;+ }+ else+ {+ /* we need more bits; we have to do it by hand */+ FT_Int64 temp, temp2;++ temp.hi = (FT_Int32) (a >> 16);+ temp.lo = (FT_UInt32)(a << 16);+ temp2.hi = 0;+ temp2.lo = (FT_UInt32)( b >> 1 );+ FT_Add64( &temp, &temp2, &temp );+ q = ft_div64by32( temp.hi, temp.lo, (FT_Int32)b );+ }++ return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );+ }+++#if 0++ /* documentation is in ftcalc.h */++ FT_EXPORT_DEF( void )+ FT_MulTo64( FT_Int32 x,+ FT_Int32 y,+ FT_Int64 *z )+ {+ FT_Int32 s;+++ s = x; x = FT_ABS( x );+ s ^= y; y = FT_ABS( y );++ ft_multo64( x, y, z );++ if ( s < 0 )+ {+ z->lo = (FT_UInt32)-(FT_Int32)z->lo;+ z->hi = ~z->hi + !( z->lo );+ }+ }+++ /* apparently, the second version of this code is not compiled correctly */+ /* on Mac machines with the MPW C compiler.. tsk, tsk, tsk... */++#if 1++ FT_EXPORT_DEF( FT_Int32 )+ FT_Div64by32( FT_Int64* x,+ FT_Int32 y )+ {+ FT_Int32 s;+ FT_UInt32 q, r, i, lo;+++ s = x->hi;+ if ( s < 0 )+ {+ x->lo = (FT_UInt32)-(FT_Int32)x->lo;+ x->hi = ~x->hi + !x->lo;+ }+ s ^= y; y = FT_ABS( y );++ /* Shortcut */+ if ( x->hi == 0 )+ {+ if ( y > 0 )+ q = x->lo / y;+ else+ q = 0x7FFFFFFFL;++ return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );+ }++ r = x->hi;+ lo = x->lo;++ if ( r >= (FT_UInt32)y ) /* we know y is to be treated as unsigned here */+ return ( s < 0 ? 0x80000001UL : 0x7FFFFFFFUL );+ /* Return Max/Min Int32 if division overflow. */+ /* This includes division by zero! */+ q = 0;+ for ( i = 0; i < 32; i++ )+ {+ r <<= 1;+ q <<= 1;+ r |= lo >> 31;++ if ( r >= (FT_UInt32)y )+ {+ r -= y;+ q |= 1;+ }+ lo <<= 1;+ }++ return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );+ }++#else /* 0 */++ FT_EXPORT_DEF( FT_Int32 )+ FT_Div64by32( FT_Int64* x,+ FT_Int32 y )+ {+ FT_Int32 s;+ FT_UInt32 q;+++ s = x->hi;+ if ( s < 0 )+ {+ x->lo = (FT_UInt32)-(FT_Int32)x->lo;+ x->hi = ~x->hi + !x->lo;+ }+ s ^= y; y = FT_ABS( y );++ /* Shortcut */+ if ( x->hi == 0 )+ {+ if ( y > 0 )+ q = ( x->lo + ( y >> 1 ) ) / y;+ else+ q = 0x7FFFFFFFL;++ return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );+ }++ q = ft_div64by32( x->hi, x->lo, y );++ return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );+ }++#endif /* 0 */++#endif /* 0 */+++#endif /* FT_LONG64 */+++ /* documentation is in ftglyph.h */++ FT_EXPORT_DEF( void )+ FT_Matrix_Multiply( const FT_Matrix* a,+ FT_Matrix *b )+ {+ FT_Fixed xx, xy, yx, yy;+++ if ( !a || !b )+ return;++ xx = FT_MulFix( a->xx, b->xx ) + FT_MulFix( a->xy, b->yx );+ xy = FT_MulFix( a->xx, b->xy ) + FT_MulFix( a->xy, b->yy );+ yx = FT_MulFix( a->yx, b->xx ) + FT_MulFix( a->yy, b->yx );+ yy = FT_MulFix( a->yx, b->xy ) + FT_MulFix( a->yy, b->yy );++ b->xx = xx; b->xy = xy;+ b->yx = yx; b->yy = yy;+ }+++ /* documentation is in ftglyph.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Matrix_Invert( FT_Matrix* matrix )+ {+ FT_Pos delta, xx, yy;+++ if ( !matrix )+ return FT_Err_Invalid_Argument;++ /* compute discriminant */+ delta = FT_MulFix( matrix->xx, matrix->yy ) -+ FT_MulFix( matrix->xy, matrix->yx );++ if ( !delta )+ return FT_Err_Invalid_Argument; /* matrix can't be inverted */++ matrix->xy = - FT_DivFix( matrix->xy, delta );+ matrix->yx = - FT_DivFix( matrix->yx, delta );++ xx = matrix->xx;+ yy = matrix->yy;++ matrix->xx = FT_DivFix( yy, delta );+ matrix->yy = FT_DivFix( xx, delta );++ return FT_Err_Ok;+ }+++ /* documentation is in ftcalc.h */++ FT_BASE_DEF( void )+ FT_Matrix_Multiply_Scaled( const FT_Matrix* a,+ FT_Matrix *b,+ FT_Long scaling )+ {+ FT_Fixed xx, xy, yx, yy;++ FT_Long val = 0x10000L * scaling;+++ if ( !a || !b )+ return;++ xx = FT_MulDiv( a->xx, b->xx, val ) + FT_MulDiv( a->xy, b->yx, val );+ xy = FT_MulDiv( a->xx, b->xy, val ) + FT_MulDiv( a->xy, b->yy, val );+ yx = FT_MulDiv( a->yx, b->xx, val ) + FT_MulDiv( a->yy, b->yx, val );+ yy = FT_MulDiv( a->yx, b->xy, val ) + FT_MulDiv( a->yy, b->yy, val );++ b->xx = xx; b->xy = xy;+ b->yx = yx; b->yy = yy;+ }+++ /* documentation is in ftcalc.h */++ FT_BASE_DEF( void )+ FT_Vector_Transform_Scaled( FT_Vector* vector,+ const FT_Matrix* matrix,+ FT_Long scaling )+ {+ FT_Pos xz, yz;++ FT_Long val = 0x10000L * scaling;+++ if ( !vector || !matrix )+ return;++ xz = FT_MulDiv( vector->x, matrix->xx, val ) ++ FT_MulDiv( vector->y, matrix->xy, val );++ yz = FT_MulDiv( vector->x, matrix->yx, val ) ++ FT_MulDiv( vector->y, matrix->yy, val );++ vector->x = xz;+ vector->y = yz;+ }+++ /* documentation is in ftcalc.h */++ FT_BASE_DEF( FT_Int32 )+ FT_SqrtFixed( FT_Int32 x )+ {+ FT_UInt32 root, rem_hi, rem_lo, test_div;+ FT_Int count;+++ root = 0;++ if ( x > 0 )+ {+ rem_hi = 0;+ rem_lo = x;+ count = 24;+ do+ {+ rem_hi = ( rem_hi << 2 ) | ( rem_lo >> 30 );+ rem_lo <<= 2;+ root <<= 1;+ test_div = ( root << 1 ) + 1;++ if ( rem_hi >= test_div )+ {+ rem_hi -= test_div;+ root += 1;+ }+ } while ( --count );+ }++ return (FT_Int32)root;+ }+++ /* documentation is in ftcalc.h */++ FT_BASE_DEF( FT_Int )+ ft_corner_orientation( FT_Pos in_x,+ FT_Pos in_y,+ 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;+++ if ( delta == 0 )+ result = 0;+ else+ result = 1 - 2 * ( delta < 0 );++#else++ FT_Int64 z1, z2;+++ /* XXX: this function does not allow 64-bit arguments */+ ft_multo64( (FT_Int32)in_x, (FT_Int32)out_y, &z1 );+ ft_multo64( (FT_Int32)in_y, (FT_Int32)out_x, &z2 );++ if ( z1.hi > z2.hi )+ result = +1;+ else if ( z1.hi < z2.hi )+ result = -1;+ else if ( z1.lo > z2.lo )+ result = +1;+ else if ( z1.lo < z2.lo )+ result = -1;+ else+ result = 0;++#endif+ }++ /* XXX: only the sign of return value, +1/0/-1 must be used */+ return (FT_Int)result;+ }+++ /* documentation is in ftcalc.h */++ FT_BASE_DEF( FT_Int )+ ft_corner_is_flat( FT_Pos in_x,+ FT_Pos in_y,+ FT_Pos out_x,+ FT_Pos out_y )+ {+ FT_Pos ax = in_x;+ FT_Pos ay = in_y;++ FT_Pos d_in, d_out, d_corner;+++ if ( ax < 0 )+ ax = -ax;+ if ( ay < 0 )+ ay = -ay;+ d_in = ax + ay;++ ax = out_x;+ if ( ax < 0 )+ ax = -ax;+ ay = out_y;+ if ( ay < 0 )+ ay = -ay;+ d_out = ax + ay;++ ax = out_x + in_x;+ if ( ax < 0 )+ ax = -ax;+ ay = out_y + in_y;+ if ( ay < 0 )+ ay = -ay;+ d_corner = ax + ay;++ return ( d_in + d_out - d_corner ) < ( d_corner >> 4 );+ }+++/* END */
+ src/base/ftcid.c view
@@ -0,0 +1,117 @@+/***************************************************************************/+/* */+/* ftcid.c */+/* */+/* FreeType API for accessing CID font information. */+/* */+/* Copyright 2007, 2009 by Derek Clegg, 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 */
+ src/base/ftdbgmem.c view
@@ -0,0 +1,997 @@+/***************************************************************************/+/* */+/* ftdbgmem.c */+/* */+/* Memory debugger (body). */+/* */+/* Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2009 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#include <ft2build.h>+#include FT_CONFIG_CONFIG_H+#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_MEMORY_H+#include FT_SYSTEM_H+#include FT_ERRORS_H+#include FT_TYPES_H+++#ifdef FT_DEBUG_MEMORY++#define KEEPALIVE /* `Keep alive' means that freed blocks aren't released+ * to the heap. This is useful to detect double-frees+ * or weird heap corruption, but it uses large amounts of+ * memory, however.+ */++#include FT_CONFIG_STANDARD_LIBRARY_H++ FT_BASE_DEF( const char* ) _ft_debug_file = 0;+ FT_BASE_DEF( long ) _ft_debug_lineno = 0;++ extern void+ FT_DumpMemory( FT_Memory memory );+++ typedef struct FT_MemSourceRec_* FT_MemSource;+ typedef struct FT_MemNodeRec_* FT_MemNode;+ typedef struct FT_MemTableRec_* FT_MemTable;+++#define FT_MEM_VAL( addr ) ((FT_PtrDist)(FT_Pointer)( addr ))++ /*+ * This structure holds statistics for a single allocation/release+ * site. This is useful to know where memory operations happen the+ * most.+ */+ typedef struct FT_MemSourceRec_+ {+ const char* file_name;+ long line_no;++ FT_Long cur_blocks; /* current number of allocated blocks */+ FT_Long max_blocks; /* max. number of allocated blocks */+ FT_Long all_blocks; /* total number of blocks allocated */++ FT_Long cur_size; /* current cumulative allocated size */+ FT_Long max_size; /* maximum cumulative allocated size */+ FT_Long all_size; /* total cumulative allocated size */++ FT_Long cur_max; /* current maximum allocated size */++ FT_UInt32 hash;+ FT_MemSource link;++ } FT_MemSourceRec;+++ /*+ * We don't need a resizable array for the memory sources, because+ * their number is pretty limited within FreeType.+ */+#define FT_MEM_SOURCE_BUCKETS 128++ /*+ * This structure holds information related to a single allocated+ * memory block. If KEEPALIVE is defined, blocks that are freed by+ * FreeType are never released to the system. Instead, their `size'+ * field is set to -size. This is mainly useful to detect double frees,+ * at the price of large memory footprint during execution.+ */+ typedef struct FT_MemNodeRec_+ {+ FT_Byte* address;+ FT_Long size; /* < 0 if the block was freed */++ FT_MemSource source;++#ifdef KEEPALIVE+ const char* free_file_name;+ FT_Long free_line_no;+#endif++ FT_MemNode link;++ } FT_MemNodeRec;+++ /*+ * The global structure, containing compound statistics and all hash+ * tables.+ */+ typedef struct FT_MemTableRec_+ {+ FT_ULong size;+ FT_ULong nodes;+ FT_MemNode* buckets;++ FT_ULong alloc_total;+ FT_ULong alloc_current;+ FT_ULong alloc_max;+ FT_ULong alloc_count;++ FT_Bool bound_total;+ FT_ULong alloc_total_max;++ FT_Bool bound_count;+ FT_ULong alloc_count_max;++ FT_MemSource sources[FT_MEM_SOURCE_BUCKETS];++ FT_Bool keep_alive;++ FT_Memory memory;+ FT_Pointer memory_user;+ FT_Alloc_Func alloc;+ FT_Free_Func free;+ FT_Realloc_Func realloc;++ } FT_MemTableRec;+++#define FT_MEM_SIZE_MIN 7+#define FT_MEM_SIZE_MAX 13845163++#define FT_FILENAME( x ) ((x) ? (x) : "unknown file")+++ /*+ * Prime numbers are ugly to handle. It would be better to implement+ * L-Hashing, which is 10% faster and doesn't require divisions.+ */+ static const FT_UInt ft_mem_primes[] =+ {+ 7,+ 11,+ 19,+ 37,+ 73,+ 109,+ 163,+ 251,+ 367,+ 557,+ 823,+ 1237,+ 1861,+ 2777,+ 4177,+ 6247,+ 9371,+ 14057,+ 21089,+ 31627,+ 47431,+ 71143,+ 106721,+ 160073,+ 240101,+ 360163,+ 540217,+ 810343,+ 1215497,+ 1823231,+ 2734867,+ 4102283,+ 6153409,+ 9230113,+ 13845163,+ };+++ static FT_ULong+ ft_mem_closest_prime( FT_ULong num )+ {+ FT_UInt i;+++ for ( i = 0;+ i < sizeof ( ft_mem_primes ) / sizeof ( ft_mem_primes[0] ); i++ )+ if ( ft_mem_primes[i] > num )+ return ft_mem_primes[i];++ return FT_MEM_SIZE_MAX;+ }+++ extern void+ ft_mem_debug_panic( const char* fmt,+ ... )+ {+ va_list ap;+++ printf( "FreeType.Debug: " );++ va_start( ap, fmt );+ vprintf( fmt, ap );+ va_end( ap );++ printf( "\n" );+ exit( EXIT_FAILURE );+ }+++ static FT_Pointer+ ft_mem_table_alloc( FT_MemTable table,+ FT_Long size )+ {+ FT_Memory memory = table->memory;+ FT_Pointer block;+++ memory->user = table->memory_user;+ block = table->alloc( memory, size );+ memory->user = table;++ return block;+ }+++ static void+ ft_mem_table_free( FT_MemTable table,+ FT_Pointer block )+ {+ FT_Memory memory = table->memory;+++ memory->user = table->memory_user;+ table->free( memory, block );+ memory->user = table;+ }+++ static void+ ft_mem_table_resize( FT_MemTable table )+ {+ FT_ULong new_size;+++ new_size = ft_mem_closest_prime( table->nodes );+ if ( new_size != table->size )+ {+ FT_MemNode* new_buckets;+ FT_ULong i;+++ new_buckets = (FT_MemNode *)+ ft_mem_table_alloc( table,+ new_size * sizeof ( FT_MemNode ) );+ if ( new_buckets == NULL )+ return;++ FT_ARRAY_ZERO( new_buckets, new_size );++ for ( i = 0; i < table->size; i++ )+ {+ FT_MemNode node, next, *pnode;+ FT_PtrDist hash;+++ node = table->buckets[i];+ while ( node )+ {+ next = node->link;+ hash = FT_MEM_VAL( node->address ) % new_size;+ pnode = new_buckets + hash;++ node->link = pnode[0];+ pnode[0] = node;++ node = next;+ }+ }++ if ( table->buckets )+ ft_mem_table_free( table, table->buckets );++ table->buckets = new_buckets;+ table->size = new_size;+ }+ }+++ static FT_MemTable+ ft_mem_table_new( FT_Memory memory )+ {+ FT_MemTable table;+++ table = (FT_MemTable)memory->alloc( memory, sizeof ( *table ) );+ if ( table == NULL )+ goto Exit;++ FT_ZERO( table );++ table->size = FT_MEM_SIZE_MIN;+ table->nodes = 0;++ table->memory = memory;++ table->memory_user = memory->user;++ table->alloc = memory->alloc;+ table->realloc = memory->realloc;+ table->free = memory->free;++ table->buckets = (FT_MemNode *)+ memory->alloc( memory,+ table->size * sizeof ( FT_MemNode ) );+ if ( table->buckets )+ FT_ARRAY_ZERO( table->buckets, table->size );+ else+ {+ memory->free( memory, table );+ table = NULL;+ }++ Exit:+ return table;+ }+++ static void+ ft_mem_table_destroy( FT_MemTable table )+ {+ FT_ULong i;+++ FT_DumpMemory( table->memory );++ if ( table )+ {+ FT_Long leak_count = 0;+ FT_ULong leaks = 0;+++ /* remove all blocks from the table, revealing leaked ones */+ for ( i = 0; i < table->size; i++ )+ {+ FT_MemNode *pnode = table->buckets + i, next, node = *pnode;+++ while ( node )+ {+ next = node->link;+ node->link = 0;++ if ( node->size > 0 )+ {+ printf(+ "leaked memory block at address %p, size %8ld in (%s:%ld)\n",+ node->address, node->size,+ FT_FILENAME( node->source->file_name ),+ node->source->line_no );++ leak_count++;+ leaks += node->size;++ ft_mem_table_free( table, node->address );+ }++ node->address = NULL;+ node->size = 0;++ ft_mem_table_free( table, node );+ node = next;+ }+ table->buckets[i] = 0;+ }++ ft_mem_table_free( table, table->buckets );+ table->buckets = NULL;++ table->size = 0;+ table->nodes = 0;++ /* remove all sources */+ for ( i = 0; i < FT_MEM_SOURCE_BUCKETS; i++ )+ {+ FT_MemSource source, next;+++ for ( source = table->sources[i]; source != NULL; source = next )+ {+ next = source->link;+ ft_mem_table_free( table, source );+ }++ table->sources[i] = NULL;+ }++ printf(+ "FreeType: total memory allocations = %ld\n", table->alloc_total );+ printf(+ "FreeType: maximum memory footprint = %ld\n", table->alloc_max );++ ft_mem_table_free( table, table );++ if ( leak_count > 0 )+ ft_mem_debug_panic(+ "FreeType: %ld bytes of memory leaked in %ld blocks\n",+ leaks, leak_count );++ printf( "FreeType: no memory leaks detected\n" );+ }+ }+++ static FT_MemNode*+ ft_mem_table_get_nodep( FT_MemTable table,+ FT_Byte* address )+ {+ FT_PtrDist hash;+ FT_MemNode *pnode, node;+++ hash = FT_MEM_VAL( address );+ pnode = table->buckets + ( hash % table->size );++ for (;;)+ {+ node = pnode[0];+ if ( !node )+ break;++ if ( node->address == address )+ break;++ pnode = &node->link;+ }+ return pnode;+ }+++ static FT_MemSource+ ft_mem_table_get_source( FT_MemTable table )+ {+ FT_UInt32 hash;+ FT_MemSource node, *pnode;+++ /* cast to FT_PtrDist first since void* can be larger */+ /* than FT_UInt32 and GCC 4.1.1 emits a warning */+ hash = (FT_UInt32)(FT_PtrDist)(void*)_ft_debug_file ++ (FT_UInt32)( 5 * _ft_debug_lineno );+ pnode = &table->sources[hash % FT_MEM_SOURCE_BUCKETS];++ for ( ;; )+ {+ node = *pnode;+ if ( node == NULL )+ break;++ if ( node->file_name == _ft_debug_file &&+ node->line_no == _ft_debug_lineno )+ goto Exit;++ pnode = &node->link;+ }++ node = (FT_MemSource)ft_mem_table_alloc( table, sizeof ( *node ) );+ if ( node == NULL )+ ft_mem_debug_panic(+ "not enough memory to perform memory debugging\n" );++ node->file_name = _ft_debug_file;+ node->line_no = _ft_debug_lineno;++ node->cur_blocks = 0;+ node->max_blocks = 0;+ node->all_blocks = 0;++ node->cur_size = 0;+ node->max_size = 0;+ node->all_size = 0;++ node->cur_max = 0;++ node->link = NULL;+ node->hash = hash;+ *pnode = node;++ Exit:+ return node;+ }+++ static void+ ft_mem_table_set( FT_MemTable table,+ FT_Byte* address,+ FT_ULong size,+ FT_Long delta )+ {+ FT_MemNode *pnode, node;+++ if ( table )+ {+ FT_MemSource source;+++ pnode = ft_mem_table_get_nodep( table, address );+ node = *pnode;+ if ( node )+ {+ if ( node->size < 0 )+ {+ /* This block was already freed. Our memory is now completely */+ /* corrupted! */+ /* This can only happen in keep-alive mode. */+ ft_mem_debug_panic(+ "memory heap corrupted (allocating freed block)" );+ }+ else+ {+ /* This block was already allocated. This means that our memory */+ /* is also corrupted! */+ ft_mem_debug_panic(+ "memory heap corrupted (re-allocating allocated block at"+ " %p, of size %ld)\n"+ "org=%s:%d new=%s:%d\n",+ node->address, node->size,+ FT_FILENAME( node->source->file_name ), node->source->line_no,+ FT_FILENAME( _ft_debug_file ), _ft_debug_lineno );+ }+ }++ /* we need to create a new node in this table */+ node = (FT_MemNode)ft_mem_table_alloc( table, sizeof ( *node ) );+ if ( node == NULL )+ ft_mem_debug_panic( "not enough memory to run memory tests" );++ node->address = address;+ node->size = size;+ node->source = source = ft_mem_table_get_source( table );++ if ( delta == 0 )+ {+ /* this is an allocation */+ source->all_blocks++;+ source->cur_blocks++;+ if ( source->cur_blocks > source->max_blocks )+ source->max_blocks = source->cur_blocks;+ }++ if ( size > (FT_ULong)source->cur_max )+ source->cur_max = size;++ if ( delta != 0 )+ {+ /* we are growing or shrinking a reallocated block */+ source->cur_size += delta;+ table->alloc_current += delta;+ }+ else+ {+ /* we are allocating a new block */+ source->cur_size += size;+ table->alloc_current += size;+ }++ source->all_size += size;++ if ( source->cur_size > source->max_size )+ source->max_size = source->cur_size;++ node->free_file_name = NULL;+ node->free_line_no = 0;++ node->link = pnode[0];++ pnode[0] = node;+ table->nodes++;++ table->alloc_total += size;++ if ( table->alloc_current > table->alloc_max )+ table->alloc_max = table->alloc_current;++ if ( table->nodes * 3 < table->size ||+ table->size * 3 < table->nodes )+ ft_mem_table_resize( table );+ }+ }+++ static void+ ft_mem_table_remove( FT_MemTable table,+ FT_Byte* address,+ FT_Long delta )+ {+ if ( table )+ {+ FT_MemNode *pnode, node;+++ pnode = ft_mem_table_get_nodep( table, address );+ node = *pnode;+ if ( node )+ {+ FT_MemSource source;+++ if ( node->size < 0 )+ ft_mem_debug_panic(+ "freeing memory block at %p more than once at (%s:%ld)\n"+ "block allocated at (%s:%ld) and released at (%s:%ld)",+ address,+ FT_FILENAME( _ft_debug_file ), _ft_debug_lineno,+ FT_FILENAME( node->source->file_name ), node->source->line_no,+ FT_FILENAME( node->free_file_name ), node->free_line_no );++ /* scramble the node's content for additional safety */+ FT_MEM_SET( address, 0xF3, node->size );++ if ( delta == 0 )+ {+ source = node->source;++ source->cur_blocks--;+ source->cur_size -= node->size;++ table->alloc_current -= node->size;+ }++ if ( table->keep_alive )+ {+ /* we simply invert the node's size to indicate that the node */+ /* was freed. */+ node->size = -node->size;+ node->free_file_name = _ft_debug_file;+ node->free_line_no = _ft_debug_lineno;+ }+ else+ {+ table->nodes--;++ *pnode = node->link;++ node->size = 0;+ node->source = NULL;++ ft_mem_table_free( table, node );++ if ( table->nodes * 3 < table->size ||+ table->size * 3 < table->nodes )+ ft_mem_table_resize( table );+ }+ }+ else+ ft_mem_debug_panic(+ "trying to free unknown block at %p in (%s:%ld)\n",+ address,+ FT_FILENAME( _ft_debug_file ), _ft_debug_lineno );+ }+ }+++ extern FT_Pointer+ ft_mem_debug_alloc( FT_Memory memory,+ FT_Long size )+ {+ FT_MemTable table = (FT_MemTable)memory->user;+ FT_Byte* block;+++ if ( size <= 0 )+ ft_mem_debug_panic( "negative block size allocation (%ld)", size );++ /* return NULL if the maximum number of allocations was reached */+ if ( table->bound_count &&+ table->alloc_count >= table->alloc_count_max )+ return NULL;++ /* return NULL if this allocation would overflow the maximum heap size */+ if ( table->bound_total &&+ table->alloc_total_max - table->alloc_current > (FT_ULong)size )+ return NULL;++ block = (FT_Byte *)ft_mem_table_alloc( table, size );+ if ( block )+ {+ ft_mem_table_set( table, block, (FT_ULong)size, 0 );++ table->alloc_count++;+ }++ _ft_debug_file = "<unknown>";+ _ft_debug_lineno = 0;++ return (FT_Pointer)block;+ }+++ extern void+ ft_mem_debug_free( FT_Memory memory,+ FT_Pointer block )+ {+ FT_MemTable table = (FT_MemTable)memory->user;+++ if ( block == NULL )+ ft_mem_debug_panic( "trying to free NULL in (%s:%ld)",+ FT_FILENAME( _ft_debug_file ),+ _ft_debug_lineno );++ ft_mem_table_remove( table, (FT_Byte*)block, 0 );++ if ( !table->keep_alive )+ ft_mem_table_free( table, block );++ table->alloc_count--;++ _ft_debug_file = "<unknown>";+ _ft_debug_lineno = 0;+ }+++ extern FT_Pointer+ ft_mem_debug_realloc( FT_Memory memory,+ FT_Long cur_size,+ FT_Long new_size,+ FT_Pointer block )+ {+ FT_MemTable table = (FT_MemTable)memory->user;+ FT_MemNode node, *pnode;+ FT_Pointer new_block;+ FT_Long delta;++ const char* file_name = FT_FILENAME( _ft_debug_file );+ FT_Long line_no = _ft_debug_lineno;+++ /* unlikely, but possible */+ if ( new_size == cur_size )+ return block;++ /* the following is valid according to ANSI C */+#if 0+ if ( block == NULL || cur_size == 0 )+ ft_mem_debug_panic( "trying to reallocate NULL in (%s:%ld)",+ file_name, line_no );+#endif++ /* while the following is allowed in ANSI C also, we abort since */+ /* such case should be handled by FreeType. */+ if ( new_size <= 0 )+ ft_mem_debug_panic(+ "trying to reallocate %p to size 0 (current is %ld) in (%s:%ld)",+ block, cur_size, file_name, line_no );++ /* check `cur_size' value */+ pnode = ft_mem_table_get_nodep( table, (FT_Byte*)block );+ node = *pnode;+ if ( !node )+ ft_mem_debug_panic(+ "trying to reallocate unknown block at %p in (%s:%ld)",+ block, file_name, line_no );++ if ( node->size <= 0 )+ ft_mem_debug_panic(+ "trying to reallocate freed block at %p in (%s:%ld)",+ block, file_name, line_no );++ if ( node->size != cur_size )+ ft_mem_debug_panic( "invalid ft_realloc request for %p. cur_size is "+ "%ld instead of %ld in (%s:%ld)",+ block, cur_size, node->size, file_name, line_no );++ /* return NULL if the maximum number of allocations was reached */+ if ( table->bound_count &&+ table->alloc_count >= table->alloc_count_max )+ return NULL;++ delta = (FT_Long)( new_size - cur_size );++ /* return NULL if this allocation would overflow the maximum heap size */+ if ( delta > 0 &&+ table->bound_total &&+ table->alloc_current + (FT_ULong)delta > table->alloc_total_max )+ return NULL;++ new_block = (FT_Byte *)ft_mem_table_alloc( table, new_size );+ if ( new_block == NULL )+ return NULL;++ ft_mem_table_set( table, (FT_Byte*)new_block, new_size, delta );++ ft_memcpy( new_block, block, cur_size < new_size ? cur_size : new_size );++ ft_mem_table_remove( table, (FT_Byte*)block, delta );++ _ft_debug_file = "<unknown>";+ _ft_debug_lineno = 0;++ if ( !table->keep_alive )+ ft_mem_table_free( table, block );++ return new_block;+ }+++ extern FT_Int+ ft_mem_debug_init( FT_Memory memory )+ {+ FT_MemTable table;+ FT_Int result = 0;+++ if ( getenv( "FT2_DEBUG_MEMORY" ) )+ {+ table = ft_mem_table_new( memory );+ if ( table )+ {+ const char* p;+++ memory->user = table;+ memory->alloc = ft_mem_debug_alloc;+ memory->realloc = ft_mem_debug_realloc;+ memory->free = ft_mem_debug_free;++ p = getenv( "FT2_ALLOC_TOTAL_MAX" );+ if ( p != NULL )+ {+ FT_Long total_max = ft_atol( p );+++ if ( total_max > 0 )+ {+ table->bound_total = 1;+ table->alloc_total_max = (FT_ULong)total_max;+ }+ }++ p = getenv( "FT2_ALLOC_COUNT_MAX" );+ if ( p != NULL )+ {+ FT_Long total_count = ft_atol( p );+++ if ( total_count > 0 )+ {+ table->bound_count = 1;+ table->alloc_count_max = (FT_ULong)total_count;+ }+ }++ p = getenv( "FT2_KEEP_ALIVE" );+ if ( p != NULL )+ {+ FT_Long keep_alive = ft_atol( p );+++ if ( keep_alive > 0 )+ table->keep_alive = 1;+ }++ result = 1;+ }+ }+ return result;+ }+++ extern void+ ft_mem_debug_done( FT_Memory memory )+ {+ FT_MemTable table = (FT_MemTable)memory->user;+++ if ( table )+ {+ memory->free = table->free;+ memory->realloc = table->realloc;+ memory->alloc = table->alloc;++ ft_mem_table_destroy( table );+ memory->user = NULL;+ }+ }++++ static int+ ft_mem_source_compare( const void* p1,+ const void* p2 )+ {+ FT_MemSource s1 = *(FT_MemSource*)p1;+ FT_MemSource s2 = *(FT_MemSource*)p2;+++ if ( s2->max_size > s1->max_size )+ return 1;+ else if ( s2->max_size < s1->max_size )+ return -1;+ else+ return 0;+ }+++ extern void+ FT_DumpMemory( FT_Memory memory )+ {+ FT_MemTable table = (FT_MemTable)memory->user;+++ if ( table )+ {+ FT_MemSource* bucket = table->sources;+ FT_MemSource* limit = bucket + FT_MEM_SOURCE_BUCKETS;+ FT_MemSource* sources;+ FT_UInt nn, count;+ const char* fmt;+++ count = 0;+ for ( ; bucket < limit; bucket++ )+ {+ FT_MemSource source = *bucket;+++ for ( ; source; source = source->link )+ count++;+ }++ sources = (FT_MemSource*)ft_mem_table_alloc(+ table, sizeof ( *sources ) * count );++ count = 0;+ for ( bucket = table->sources; bucket < limit; bucket++ )+ {+ FT_MemSource source = *bucket;+++ for ( ; source; source = source->link )+ sources[count++] = source;+ }++ ft_qsort( sources, count, sizeof ( *sources ), ft_mem_source_compare );++ printf( "FreeType Memory Dump: "+ "current=%ld max=%ld total=%ld count=%ld\n",+ table->alloc_current, table->alloc_max,+ table->alloc_total, table->alloc_count );+ printf( " block block sizes sizes sizes source\n" );+ printf( " count high sum highsum max location\n" );+ printf( "-------------------------------------------------\n" );++ fmt = "%6ld %6ld %8ld %8ld %8ld %s:%d\n";++ for ( nn = 0; nn < count; nn++ )+ {+ FT_MemSource source = sources[nn];+++ printf( fmt,+ source->cur_blocks, source->max_blocks,+ source->cur_size, source->max_size, source->cur_max,+ FT_FILENAME( source->file_name ),+ source->line_no );+ }+ printf( "------------------------------------------------\n" );++ ft_mem_table_free( table, sources );+ }+ }++#else /* !FT_DEBUG_MEMORY */++ /* ANSI C doesn't like empty source files */+ typedef int _debug_mem_dummy;++#endif /* !FT_DEBUG_MEMORY */+++/* END */
+ src/base/ftdebug.c view
@@ -0,0 +1,246 @@+/***************************************************************************/+/* */+/* ftdebug.c */+/* */+/* Debugging and logging component (body). */+/* */+/* Copyright 1996-2001, 2002, 2004, 2008 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++ /*************************************************************************/+ /* */+ /* This component contains various macros and functions used to ease the */+ /* debugging of the FreeType engine. Its main purpose is in assertion */+ /* checking, tracing, and error detection. */+ /* */+ /* There are now three debugging modes: */+ /* */+ /* - trace mode */+ /* */+ /* Error and trace messages are sent to the log file (which can be the */+ /* standard error output). */+ /* */+ /* - error mode */+ /* */+ /* Only error messages are generated. */+ /* */+ /* - release mode: */+ /* */+ /* No error message is sent or generated. The code is free from any */+ /* debugging parts. */+ /* */+ /*************************************************************************/+++#include <ft2build.h>+#include FT_FREETYPE_H+#include FT_INTERNAL_DEBUG_H+++#ifdef FT_DEBUG_LEVEL_ERROR++ /* documentation is in ftdebug.h */++ FT_BASE_DEF( void )+ FT_Message( const char* fmt, ... )+ {+ va_list ap;+++ va_start( ap, fmt );+ vfprintf( stderr, fmt, ap );+ va_end( ap );+ }+++ /* documentation is in ftdebug.h */++ FT_BASE_DEF( void )+ FT_Panic( const char* fmt, ... )+ {+ va_list ap;+++ va_start( ap, fmt );+ vfprintf( stderr, fmt, ap );+ va_end( ap );++ exit( EXIT_FAILURE );+ }++#endif /* FT_DEBUG_LEVEL_ERROR */++++#ifdef FT_DEBUG_LEVEL_TRACE++ /* array of trace levels, initialized to 0 */+ int ft_trace_levels[trace_count];+++ /* define array of trace toggle names */+#define FT_TRACE_DEF( x ) #x ,++ static const char* ft_trace_toggles[trace_count + 1] =+ {+#include FT_INTERNAL_TRACE_H+ NULL+ };++#undef FT_TRACE_DEF+++ /* documentation is in ftdebug.h */++ FT_BASE_DEF( FT_Int )+ FT_Trace_Get_Count( void )+ {+ return trace_count;+ }+++ /* documentation is in ftdebug.h */++ FT_BASE_DEF( const char * )+ FT_Trace_Get_Name( FT_Int idx )+ {+ int max = FT_Trace_Get_Count();+++ if ( idx < max )+ return ft_trace_toggles[idx];+ else+ return NULL;+ }+++ /*************************************************************************/+ /* */+ /* Initialize the tracing sub-system. This is done by retrieving the */+ /* value of the `FT2_DEBUG' environment variable. It must be a list of */+ /* toggles, separated by spaces, `;', or `,'. Example: */+ /* */+ /* export FT2_DEBUG="any:3 memory:7 stream:5" */+ /* */+ /* This requests that all levels be set to 3, except the trace level for */+ /* the memory and stream components which are set to 7 and 5, */+ /* respectively. */+ /* */+ /* See the file <include/freetype/internal/fttrace.h> for details of the */+ /* available toggle names. */+ /* */+ /* The level must be between 0 and 7; 0 means quiet (except for serious */+ /* runtime errors), and 7 means _very_ verbose. */+ /* */+ FT_BASE_DEF( void )+ ft_debug_init( void )+ {+ const char* ft2_debug = getenv( "FT2_DEBUG" );+++ if ( ft2_debug )+ {+ const char* p = ft2_debug;+ const char* q;+++ for ( ; *p; p++ )+ {+ /* skip leading whitespace and separators */+ if ( *p == ' ' || *p == '\t' || *p == ',' || *p == ';' || *p == '=' )+ continue;++ /* read toggle name, followed by ':' */+ q = p;+ while ( *p && *p != ':' )+ p++;++ if ( *p == ':' && p > q )+ {+ FT_Int n, i, len = (FT_Int)( p - q );+ FT_Int level = -1, found = -1;+++ for ( n = 0; n < trace_count; n++ )+ {+ const char* toggle = ft_trace_toggles[n];+++ for ( i = 0; i < len; i++ )+ {+ if ( toggle[i] != q[i] )+ break;+ }++ if ( i == len && toggle[i] == 0 )+ {+ found = n;+ break;+ }+ }++ /* read level */+ p++;+ if ( *p )+ {+ level = *p++ - '0';+ if ( level < 0 || level > 7 )+ level = -1;+ }++ if ( found >= 0 && level >= 0 )+ {+ if ( found == trace_any )+ {+ /* special case for `any' */+ for ( n = 0; n < trace_count; n++ )+ ft_trace_levels[n] = level;+ }+ else+ ft_trace_levels[found] = level;+ }+ }+ }+ }+ }+++#else /* !FT_DEBUG_LEVEL_TRACE */+++ FT_BASE_DEF( void )+ ft_debug_init( void )+ {+ /* nothing */+ }+++ FT_BASE_DEF( FT_Int )+ FT_Trace_Get_Count( void )+ {+ return 0;+ }+++ FT_BASE_DEF( const char * )+ FT_Trace_Get_Name( FT_Int idx )+ {+ FT_UNUSED( idx );++ return NULL;+ }+++#endif /* !FT_DEBUG_LEVEL_TRACE */+++/* END */
+ src/base/ftfstype.c view
@@ -0,0 +1,62 @@+/***************************************************************************/+/* */+/* ftfstype.c */+/* */+/* FreeType utility file to access FSType data (body). */+/* */+/* Copyright 2008, 2009 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_TYPE1_TABLES_H+#include FT_TRUETYPE_TABLES_H+#include FT_INTERNAL_SERVICE_H+#include FT_SERVICE_POSTSCRIPT_INFO_H+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_UShort )+ FT_Get_FSType_Flags( FT_Face face )+ {+ TT_OS2* os2;+++ /* first, try to get the fs_type directly from the font */+ if ( face )+ {+ FT_Service_PsInfo service = NULL;+++ FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );++ if ( service && service->ps_get_font_extra )+ {+ PS_FontExtraRec extra;+++ if ( !service->ps_get_font_extra( face, &extra ) &&+ extra.fs_type != 0 )+ return extra.fs_type;+ }+ }++ /* look at FSType before fsType for Type42 */++ if ( ( os2 = (TT_OS2*)FT_Get_Sfnt_Table( face, ft_sfnt_os2 ) ) != NULL &&+ os2->version != 0xFFFFU )+ return os2->fsType;++ return 0;+ }+++/* END */
+ src/base/ftgasp.c view
@@ -0,0 +1,61 @@+/***************************************************************************/+/* */+/* ftgasp.c */+/* */+/* Access of TrueType's `gasp' table (body). */+/* */+/* Copyright 2007 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_GASP_H+#include FT_INTERNAL_TRUETYPE_TYPES_H+++ FT_EXPORT_DEF( FT_Int )+ FT_Get_Gasp( FT_Face face,+ FT_UInt ppem )+ {+ FT_Int result = FT_GASP_NO_TABLE;+++ if ( face && FT_IS_SFNT( face ) )+ {+ TT_Face ttface = (TT_Face)face;+++ if ( ttface->gasp.numRanges > 0 )+ {+ TT_GaspRange range = ttface->gasp.gaspRanges;+ TT_GaspRange range_end = range + ttface->gasp.numRanges;+++ while ( ppem > range->maxPPEM )+ {+ range++;+ if ( range >= range_end )+ goto Exit;+ }++ result = range->gaspFlag;++ /* ensure that we don't have spurious bits */+ if ( ttface->gasp.version == 0 )+ result &= 3;+ }+ }+ Exit:+ return result;+ }+++/* END */
+ src/base/ftgloadr.c view
@@ -0,0 +1,401 @@+/***************************************************************************/+/* */+/* ftgloadr.c */+/* */+/* The FreeType glyph loader (body). */+/* */+/* Copyright 2002, 2003, 2004, 2005, 2006, 2010 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_GLYPH_LOADER_H+#include FT_INTERNAL_MEMORY_H+#include FT_INTERNAL_OBJECTS_H++#undef FT_COMPONENT+#define FT_COMPONENT trace_gloader+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** *****/+ /***** G L Y P H L O A D E R *****/+ /***** *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/++ /*************************************************************************/+ /* */+ /* The glyph loader is a simple object which is used to load a set of */+ /* glyphs easily. It is critical for the correct loading of composites. */+ /* */+ /* Ideally, one can see it as a stack of abstract `glyph' objects. */+ /* */+ /* loader.base Is really the bottom of the stack. It describes a */+ /* single glyph image made of the juxtaposition of */+ /* several glyphs (those `in the stack'). */+ /* */+ /* loader.current Describes the top of the stack, on which a new */+ /* glyph can be loaded. */+ /* */+ /* Rewind Clears the stack. */+ /* Prepare Set up `loader.current' for addition of a new glyph */+ /* image. */+ /* Add Add the `current' glyph image to the `base' one, */+ /* and prepare for another one. */+ /* */+ /* The glyph loader is now a base object. Each driver used to */+ /* re-implement it in one way or the other, which wasted code and */+ /* energy. */+ /* */+ /*************************************************************************/+++ /* create a new glyph loader */+ FT_BASE_DEF( FT_Error )+ FT_GlyphLoader_New( FT_Memory memory,+ FT_GlyphLoader *aloader )+ {+ FT_GlyphLoader loader = NULL;+ FT_Error error;+++ if ( !FT_NEW( loader ) )+ {+ loader->memory = memory;+ *aloader = loader;+ }+ return error;+ }+++ /* rewind the glyph loader - reset counters to 0 */+ FT_BASE_DEF( void )+ FT_GlyphLoader_Rewind( FT_GlyphLoader loader )+ {+ FT_GlyphLoad base = &loader->base;+ FT_GlyphLoad current = &loader->current;+++ base->outline.n_points = 0;+ base->outline.n_contours = 0;+ base->num_subglyphs = 0;++ *current = *base;+ }+++ /* reset the glyph loader, frees all allocated tables */+ /* and starts from zero */+ FT_BASE_DEF( void )+ FT_GlyphLoader_Reset( FT_GlyphLoader loader )+ {+ FT_Memory memory = loader->memory;+++ FT_FREE( loader->base.outline.points );+ FT_FREE( loader->base.outline.tags );+ FT_FREE( loader->base.outline.contours );+ FT_FREE( loader->base.extra_points );+ FT_FREE( loader->base.subglyphs );++ loader->base.extra_points2 = NULL;++ loader->max_points = 0;+ loader->max_contours = 0;+ loader->max_subglyphs = 0;++ FT_GlyphLoader_Rewind( loader );+ }+++ /* delete a glyph loader */+ FT_BASE_DEF( void )+ FT_GlyphLoader_Done( FT_GlyphLoader loader )+ {+ if ( loader )+ {+ FT_Memory memory = loader->memory;+++ FT_GlyphLoader_Reset( loader );+ FT_FREE( loader );+ }+ }+++ /* re-adjust the `current' outline fields */+ static void+ FT_GlyphLoader_Adjust_Points( FT_GlyphLoader loader )+ {+ FT_Outline* base = &loader->base.outline;+ FT_Outline* current = &loader->current.outline;+++ current->points = base->points + base->n_points;+ current->tags = base->tags + base->n_points;+ current->contours = base->contours + base->n_contours;++ /* handle extra points table - if any */+ if ( loader->use_extra )+ {+ loader->current.extra_points = loader->base.extra_points ++ base->n_points;++ loader->current.extra_points2 = loader->base.extra_points2 ++ base->n_points;+ }+ }+++ FT_BASE_DEF( FT_Error )+ FT_GlyphLoader_CreateExtra( FT_GlyphLoader loader )+ {+ FT_Error error;+ FT_Memory memory = loader->memory;+++ if ( !FT_NEW_ARRAY( loader->base.extra_points, 2 * loader->max_points ) )+ {+ loader->use_extra = 1;+ loader->base.extra_points2 = loader->base.extra_points ++ loader->max_points;++ FT_GlyphLoader_Adjust_Points( loader );+ }+ return error;+ }+++ /* re-adjust the `current' subglyphs field */+ static void+ FT_GlyphLoader_Adjust_Subglyphs( FT_GlyphLoader loader )+ {+ FT_GlyphLoad base = &loader->base;+ FT_GlyphLoad current = &loader->current;+++ current->subglyphs = base->subglyphs + base->num_subglyphs;+ }+++ /* Ensure that we can add `n_points' and `n_contours' to our glyph. */+ /* This function reallocates its outline tables if necessary. Note that */+ /* it DOESN'T change the number of points within the loader! */+ /* */+ FT_BASE_DEF( FT_Error )+ FT_GlyphLoader_CheckPoints( FT_GlyphLoader loader,+ FT_UInt n_points,+ FT_UInt n_contours )+ {+ FT_Memory memory = loader->memory;+ FT_Error error = FT_Err_Ok;+ FT_Outline* base = &loader->base.outline;+ FT_Outline* current = &loader->current.outline;+ FT_Bool adjust = 0;++ FT_UInt new_max, old_max;+++ /* check points & tags */+ new_max = base->n_points + current->n_points + n_points;+ old_max = loader->max_points;++ if ( new_max > old_max )+ {+ new_max = FT_PAD_CEIL( new_max, 8 );++ if ( new_max > FT_OUTLINE_POINTS_MAX )+ return FT_Err_Array_Too_Large;++ if ( FT_RENEW_ARRAY( base->points, old_max, new_max ) ||+ FT_RENEW_ARRAY( base->tags, old_max, new_max ) )+ goto Exit;++ if ( loader->use_extra )+ {+ if ( FT_RENEW_ARRAY( loader->base.extra_points,+ old_max * 2, new_max * 2 ) )+ goto Exit;++ FT_ARRAY_MOVE( loader->base.extra_points + new_max,+ loader->base.extra_points + old_max,+ old_max );++ loader->base.extra_points2 = loader->base.extra_points + new_max;+ }++ adjust = 1;+ loader->max_points = new_max;+ }++ /* check contours */+ old_max = loader->max_contours;+ new_max = base->n_contours + current->n_contours ++ n_contours;+ if ( new_max > old_max )+ {+ new_max = FT_PAD_CEIL( new_max, 4 );++ if ( new_max > FT_OUTLINE_CONTOURS_MAX )+ return FT_Err_Array_Too_Large;++ if ( FT_RENEW_ARRAY( base->contours, old_max, new_max ) )+ goto Exit;++ adjust = 1;+ loader->max_contours = new_max;+ }++ if ( adjust )+ FT_GlyphLoader_Adjust_Points( loader );++ Exit:+ return error;+ }+++ /* Ensure that we can add `n_subglyphs' to our glyph. this function */+ /* reallocates its subglyphs table if necessary. Note that it DOES */+ /* NOT change the number of subglyphs within the loader! */+ /* */+ FT_BASE_DEF( FT_Error )+ FT_GlyphLoader_CheckSubGlyphs( FT_GlyphLoader loader,+ FT_UInt n_subs )+ {+ FT_Memory memory = loader->memory;+ FT_Error error = FT_Err_Ok;+ FT_UInt new_max, old_max;++ FT_GlyphLoad base = &loader->base;+ FT_GlyphLoad current = &loader->current;+++ new_max = base->num_subglyphs + current->num_subglyphs + n_subs;+ old_max = loader->max_subglyphs;+ if ( new_max > old_max )+ {+ new_max = FT_PAD_CEIL( new_max, 2 );+ if ( FT_RENEW_ARRAY( base->subglyphs, old_max, new_max ) )+ goto Exit;++ loader->max_subglyphs = new_max;++ FT_GlyphLoader_Adjust_Subglyphs( loader );+ }++ Exit:+ return error;+ }+++ /* prepare loader for the addition of a new glyph on top of the base one */+ FT_BASE_DEF( void )+ FT_GlyphLoader_Prepare( FT_GlyphLoader loader )+ {+ FT_GlyphLoad current = &loader->current;+++ current->outline.n_points = 0;+ current->outline.n_contours = 0;+ current->num_subglyphs = 0;++ FT_GlyphLoader_Adjust_Points ( loader );+ FT_GlyphLoader_Adjust_Subglyphs( loader );+ }+++ /* add current glyph to the base image - and prepare for another */+ FT_BASE_DEF( void )+ FT_GlyphLoader_Add( FT_GlyphLoader loader )+ {+ FT_GlyphLoad base;+ FT_GlyphLoad current;++ FT_UInt n_curr_contours;+ FT_UInt n_base_points;+ FT_UInt n;+++ if ( !loader )+ return;++ base = &loader->base;+ current = &loader->current;++ n_curr_contours = current->outline.n_contours;+ n_base_points = base->outline.n_points;++ base->outline.n_points =+ (short)( base->outline.n_points + current->outline.n_points );+ base->outline.n_contours =+ (short)( base->outline.n_contours + current->outline.n_contours );++ base->num_subglyphs += current->num_subglyphs;++ /* adjust contours count in newest outline */+ for ( n = 0; n < n_curr_contours; n++ )+ current->outline.contours[n] =+ (short)( current->outline.contours[n] + n_base_points );++ /* prepare for another new glyph image */+ FT_GlyphLoader_Prepare( loader );+ }+++ FT_BASE_DEF( FT_Error )+ FT_GlyphLoader_CopyPoints( FT_GlyphLoader target,+ FT_GlyphLoader source )+ {+ FT_Error error;+ FT_UInt num_points = source->base.outline.n_points;+ FT_UInt num_contours = source->base.outline.n_contours;+++ error = FT_GlyphLoader_CheckPoints( target, num_points, num_contours );+ if ( !error )+ {+ FT_Outline* out = &target->base.outline;+ FT_Outline* in = &source->base.outline;+++ FT_ARRAY_COPY( out->points, in->points,+ num_points );+ FT_ARRAY_COPY( out->tags, in->tags,+ num_points );+ FT_ARRAY_COPY( out->contours, in->contours,+ num_contours );++ /* do we need to copy the extra points? */+ if ( target->use_extra && source->use_extra )+ {+ FT_ARRAY_COPY( target->base.extra_points, source->base.extra_points,+ num_points );+ FT_ARRAY_COPY( target->base.extra_points2, source->base.extra_points2,+ num_points );+ }++ out->n_points = (short)num_points;+ out->n_contours = (short)num_contours;++ FT_GlyphLoader_Adjust_Points( target );+ }++ return error;+ }+++/* END */
+ src/base/ftglyph.c view
@@ -0,0 +1,627 @@+/***************************************************************************/+/* */+/* ftglyph.c */+/* */+/* FreeType convenience functions to handle glyphs (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2007, 2008, 2010 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/++ /*************************************************************************/+ /* */+ /* This file contains the definition of several convenience functions */+ /* that can be used by client applications to easily retrieve glyph */+ /* bitmaps and outlines from a given face. */+ /* */+ /* These functions should be optional if you are writing a font server */+ /* or text layout engine on top of FreeType. However, they are pretty */+ /* handy for many other simple uses of the library. */+ /* */+ /*************************************************************************/+++#include <ft2build.h>+#include FT_GLYPH_H+#include FT_OUTLINE_H+#include FT_BITMAP_H+#include FT_INTERNAL_OBJECTS_H++#include "basepic.h"++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_glyph+++ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** FT_BitmapGlyph support ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/++ FT_CALLBACK_DEF( FT_Error )+ ft_bitmap_glyph_init( FT_Glyph bitmap_glyph,+ FT_GlyphSlot slot )+ {+ FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph;+ FT_Error error = FT_Err_Ok;+ FT_Library library = FT_GLYPH( glyph )->library;+++ if ( slot->format != FT_GLYPH_FORMAT_BITMAP )+ {+ error = FT_Err_Invalid_Glyph_Format;+ goto Exit;+ }++ glyph->left = slot->bitmap_left;+ glyph->top = slot->bitmap_top;++ /* do lazy copying whenever possible */+ if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )+ {+ glyph->bitmap = slot->bitmap;+ slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;+ }+ else+ {+ FT_Bitmap_New( &glyph->bitmap );+ error = FT_Bitmap_Copy( library, &slot->bitmap, &glyph->bitmap );+ }++ Exit:+ return error;+ }+++ FT_CALLBACK_DEF( FT_Error )+ ft_bitmap_glyph_copy( FT_Glyph bitmap_source,+ FT_Glyph bitmap_target )+ {+ FT_Library library = bitmap_source->library;+ FT_BitmapGlyph source = (FT_BitmapGlyph)bitmap_source;+ FT_BitmapGlyph target = (FT_BitmapGlyph)bitmap_target;+++ target->left = source->left;+ target->top = source->top;++ return FT_Bitmap_Copy( library, &source->bitmap, &target->bitmap );+ }+++ FT_CALLBACK_DEF( void )+ ft_bitmap_glyph_done( FT_Glyph bitmap_glyph )+ {+ FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph;+ FT_Library library = FT_GLYPH( glyph )->library;+++ FT_Bitmap_Done( library, &glyph->bitmap );+ }+++ FT_CALLBACK_DEF( void )+ ft_bitmap_glyph_bbox( FT_Glyph bitmap_glyph,+ FT_BBox* cbox )+ {+ FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph;+++ cbox->xMin = glyph->left << 6;+ cbox->xMax = cbox->xMin + ( glyph->bitmap.width << 6 );+ cbox->yMax = glyph->top << 6;+ cbox->yMin = cbox->yMax - ( glyph->bitmap.rows << 6 );+ }+++ FT_DEFINE_GLYPH(ft_bitmap_glyph_class,+ sizeof ( FT_BitmapGlyphRec ),+ FT_GLYPH_FORMAT_BITMAP,++ ft_bitmap_glyph_init,+ ft_bitmap_glyph_done,+ ft_bitmap_glyph_copy,+ 0, /* FT_Glyph_TransformFunc */+ ft_bitmap_glyph_bbox,+ 0 /* FT_Glyph_PrepareFunc */+ )+++ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** FT_OutlineGlyph support ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+++ FT_CALLBACK_DEF( FT_Error )+ ft_outline_glyph_init( FT_Glyph outline_glyph,+ FT_GlyphSlot slot )+ {+ FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;+ FT_Error error = FT_Err_Ok;+ FT_Library library = FT_GLYPH( glyph )->library;+ FT_Outline* source = &slot->outline;+ FT_Outline* target = &glyph->outline;+++ /* check format in glyph slot */+ if ( slot->format != FT_GLYPH_FORMAT_OUTLINE )+ {+ error = FT_Err_Invalid_Glyph_Format;+ goto Exit;+ }++ /* allocate new outline */+ error = FT_Outline_New( library, source->n_points, source->n_contours,+ &glyph->outline );+ if ( error )+ goto Exit;++ FT_Outline_Copy( source, target );++ Exit:+ return error;+ }+++ FT_CALLBACK_DEF( void )+ ft_outline_glyph_done( FT_Glyph outline_glyph )+ {+ FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;+++ FT_Outline_Done( FT_GLYPH( glyph )->library, &glyph->outline );+ }+++ FT_CALLBACK_DEF( FT_Error )+ ft_outline_glyph_copy( FT_Glyph outline_source,+ FT_Glyph outline_target )+ {+ FT_OutlineGlyph source = (FT_OutlineGlyph)outline_source;+ FT_OutlineGlyph target = (FT_OutlineGlyph)outline_target;+ FT_Error error;+ FT_Library library = FT_GLYPH( source )->library;+++ error = FT_Outline_New( library, source->outline.n_points,+ source->outline.n_contours, &target->outline );+ if ( !error )+ FT_Outline_Copy( &source->outline, &target->outline );++ return error;+ }+++ FT_CALLBACK_DEF( void )+ ft_outline_glyph_transform( FT_Glyph outline_glyph,+ const FT_Matrix* matrix,+ const FT_Vector* delta )+ {+ FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;+++ if ( matrix )+ FT_Outline_Transform( &glyph->outline, matrix );++ if ( delta )+ FT_Outline_Translate( &glyph->outline, delta->x, delta->y );+ }+++ FT_CALLBACK_DEF( void )+ ft_outline_glyph_bbox( FT_Glyph outline_glyph,+ FT_BBox* bbox )+ {+ FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;+++ FT_Outline_Get_CBox( &glyph->outline, bbox );+ }+++ FT_CALLBACK_DEF( FT_Error )+ ft_outline_glyph_prepare( FT_Glyph outline_glyph,+ FT_GlyphSlot slot )+ {+ FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;+++ slot->format = FT_GLYPH_FORMAT_OUTLINE;+ slot->outline = glyph->outline;+ slot->outline.flags &= ~FT_OUTLINE_OWNER;++ return FT_Err_Ok;+ }+++ FT_DEFINE_GLYPH( ft_outline_glyph_class, + sizeof ( FT_OutlineGlyphRec ),+ FT_GLYPH_FORMAT_OUTLINE,++ ft_outline_glyph_init,+ ft_outline_glyph_done,+ ft_outline_glyph_copy,+ ft_outline_glyph_transform,+ ft_outline_glyph_bbox,+ ft_outline_glyph_prepare+ )+++ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** FT_Glyph class and API ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/++ static FT_Error+ ft_new_glyph( FT_Library library,+ const FT_Glyph_Class* clazz,+ FT_Glyph* aglyph )+ {+ FT_Memory memory = library->memory;+ FT_Error error;+ FT_Glyph glyph = NULL;+++ *aglyph = 0;++ if ( !FT_ALLOC( glyph, clazz->glyph_size ) )+ {+ glyph->library = library;+ glyph->clazz = clazz;+ glyph->format = clazz->glyph_format;++ *aglyph = glyph;+ }++ return error;+ }+++ /* documentation is in ftglyph.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Glyph_Copy( FT_Glyph source,+ FT_Glyph *target )+ {+ FT_Glyph copy;+ FT_Error error;+ const FT_Glyph_Class* clazz;+++ /* check arguments */+ if ( !target )+ {+ error = FT_Err_Invalid_Argument;+ goto Exit;+ }++ *target = 0;++ if ( !source || !source->clazz )+ {+ error = FT_Err_Invalid_Argument;+ goto Exit;+ }++ clazz = source->clazz;+ error = ft_new_glyph( source->library, clazz, © );+ if ( error )+ goto Exit;++ copy->advance = source->advance;+ copy->format = source->format;++ if ( clazz->glyph_copy )+ error = clazz->glyph_copy( source, copy );++ if ( error )+ FT_Done_Glyph( copy );+ else+ *target = copy;++ Exit:+ return error;+ }+++ /* documentation is in ftglyph.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Get_Glyph( FT_GlyphSlot slot,+ FT_Glyph *aglyph )+ {+ FT_Library library;+ FT_Error error;+ FT_Glyph glyph;++ const FT_Glyph_Class* clazz = 0;+++ if ( !slot )+ return FT_Err_Invalid_Slot_Handle;++ library = slot->library;++ if ( !aglyph )+ return FT_Err_Invalid_Argument;++ /* if it is a bitmap, that's easy :-) */+ if ( slot->format == FT_GLYPH_FORMAT_BITMAP )+ clazz = FT_BITMAP_GLYPH_CLASS_GET;++ /* if it is an outline */+ else if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )+ clazz = FT_OUTLINE_GLYPH_CLASS_GET;++ else+ {+ /* try to find a renderer that supports the glyph image format */+ FT_Renderer render = FT_Lookup_Renderer( library, slot->format, 0 );+++ if ( render )+ clazz = &render->glyph_class;+ }++ if ( !clazz )+ {+ error = FT_Err_Invalid_Glyph_Format;+ goto Exit;+ }++ /* create FT_Glyph object */+ error = ft_new_glyph( library, clazz, &glyph );+ 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;++ /* now import the image from the glyph slot */+ error = clazz->glyph_init( glyph, slot );++ /* if an error occurred, destroy the glyph */+ if ( error )+ FT_Done_Glyph( glyph );+ else+ *aglyph = glyph;++ Exit:+ return error;+ }+++ /* documentation is in ftglyph.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Glyph_Transform( FT_Glyph glyph,+ FT_Matrix* matrix,+ FT_Vector* delta )+ {+ const FT_Glyph_Class* clazz;+ FT_Error error = FT_Err_Ok;+++ if ( !glyph || !glyph->clazz )+ error = FT_Err_Invalid_Argument;+ else+ {+ clazz = glyph->clazz;+ if ( clazz->glyph_transform )+ {+ /* transform glyph image */+ clazz->glyph_transform( glyph, matrix, delta );++ /* transform advance vector */+ if ( matrix )+ FT_Vector_Transform( &glyph->advance, matrix );+ }+ else+ error = FT_Err_Invalid_Glyph_Format;+ }+ return error;+ }+++ /* documentation is in ftglyph.h */++ FT_EXPORT_DEF( void )+ FT_Glyph_Get_CBox( FT_Glyph glyph,+ FT_UInt bbox_mode,+ FT_BBox *acbox )+ {+ const FT_Glyph_Class* clazz;+++ if ( !acbox )+ return;++ acbox->xMin = acbox->yMin = acbox->xMax = acbox->yMax = 0;++ if ( !glyph || !glyph->clazz )+ return;+ else+ {+ clazz = glyph->clazz;+ if ( !clazz->glyph_bbox )+ return;+ else+ {+ /* retrieve bbox in 26.6 coordinates */+ clazz->glyph_bbox( glyph, acbox );++ /* perform grid fitting if needed */+ if ( bbox_mode == FT_GLYPH_BBOX_GRIDFIT ||+ bbox_mode == FT_GLYPH_BBOX_PIXELS )+ {+ acbox->xMin = FT_PIX_FLOOR( acbox->xMin );+ acbox->yMin = FT_PIX_FLOOR( acbox->yMin );+ acbox->xMax = FT_PIX_CEIL( acbox->xMax );+ acbox->yMax = FT_PIX_CEIL( acbox->yMax );+ }++ /* convert to integer pixels if needed */+ if ( bbox_mode == FT_GLYPH_BBOX_TRUNCATE ||+ bbox_mode == FT_GLYPH_BBOX_PIXELS )+ {+ acbox->xMin >>= 6;+ acbox->yMin >>= 6;+ acbox->xMax >>= 6;+ acbox->yMax >>= 6;+ }+ }+ }+ return;+ }+++ /* documentation is in ftglyph.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Glyph_To_Bitmap( FT_Glyph* the_glyph,+ FT_Render_Mode render_mode,+ FT_Vector* origin,+ FT_Bool destroy )+ {+ FT_GlyphSlotRec dummy;+ FT_GlyphSlot_InternalRec dummy_internal;+ FT_Error error = FT_Err_Ok;+ FT_Glyph glyph;+ FT_BitmapGlyph bitmap = NULL;++ const FT_Glyph_Class* clazz;++#ifdef FT_CONFIG_OPTION_PIC+ FT_Library library = FT_GLYPH( glyph )->library;+#endif+++ /* check argument */+ if ( !the_glyph )+ goto Bad;++ /* we render the glyph into a glyph bitmap using a `dummy' glyph slot */+ /* then calling FT_Render_Glyph_Internal() */++ glyph = *the_glyph;+ if ( !glyph )+ goto Bad;++ clazz = glyph->clazz;++ /* when called with a bitmap glyph, do nothing and return successfully */+ if ( clazz == FT_BITMAP_GLYPH_CLASS_GET )+ goto Exit;++ if ( !clazz || !clazz->glyph_prepare )+ goto Bad;++ FT_MEM_ZERO( &dummy, sizeof ( dummy ) );+ FT_MEM_ZERO( &dummy_internal, sizeof ( dummy_internal ) );+ dummy.internal = &dummy_internal;+ dummy.library = glyph->library;+ dummy.format = clazz->glyph_format;++ /* create result bitmap glyph */+ error = ft_new_glyph( glyph->library, FT_BITMAP_GLYPH_CLASS_GET,+ (FT_Glyph*)(void*)&bitmap );+ if ( error )+ goto Exit;++#if 1+ /* if `origin' is set, translate the glyph image */+ if ( origin )+ FT_Glyph_Transform( glyph, 0, origin );+#else+ FT_UNUSED( origin );+#endif++ /* prepare dummy slot for rendering */+ error = clazz->glyph_prepare( glyph, &dummy );+ if ( !error )+ error = FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode );++#if 1+ if ( !destroy && origin )+ {+ FT_Vector v;+++ v.x = -origin->x;+ v.y = -origin->y;+ FT_Glyph_Transform( glyph, 0, &v );+ }+#endif++ if ( error )+ goto Exit;++ /* in case of success, copy the bitmap to the glyph bitmap */+ error = ft_bitmap_glyph_init( (FT_Glyph)bitmap, &dummy );+ if ( error )+ goto Exit;++ /* copy advance */+ bitmap->root.advance = glyph->advance;++ if ( destroy )+ FT_Done_Glyph( glyph );++ *the_glyph = FT_GLYPH( bitmap );++ Exit:+ if ( error && bitmap )+ FT_Done_Glyph( FT_GLYPH( bitmap ) );++ return error;++ Bad:+ error = FT_Err_Invalid_Argument;+ goto Exit;+ }+++ /* documentation is in ftglyph.h */++ FT_EXPORT_DEF( void )+ FT_Done_Glyph( FT_Glyph glyph )+ {+ if ( glyph )+ {+ FT_Memory memory = glyph->library->memory;+ const FT_Glyph_Class* clazz = glyph->clazz;+++ if ( clazz->glyph_done )+ clazz->glyph_done( glyph );++ FT_FREE( glyph );+ }+ }+++/* END */
+ src/base/ftgxval.c view
@@ -0,0 +1,140 @@+/***************************************************************************/+/* */+/* ftgxval.c */+/* */+/* FreeType API for validating TrueTyepGX/AAT tables (body). */+/* */+/* Copyright 2004, 2005, 2006, 2010 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_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_Err_Invalid_Face_Handle;+ goto Exit;+ }++ if ( tables == NULL )+ {+ error = FT_Err_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_Err_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_Err_Invalid_Face_Handle;+ goto Exit;+ }++ if ( ckern_table == NULL )+ {+ error = FT_Err_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_Err_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 */
+ src/base/ftinit.c view
@@ -0,0 +1,253 @@+/***************************************************************************/+/* */+/* ftinit.c */+/* */+/* FreeType initialization layer (body). */+/* */+/* Copyright 1996-2001, 2002, 2005, 2007, 2009 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/++ /*************************************************************************/+ /* */+ /* The purpose of this file is to implement the following two */+ /* functions: */+ /* */+ /* FT_Add_Default_Modules(): */+ /* This function is used to add the set of default modules to a */+ /* fresh new library object. The set is taken from the header file */+ /* `freetype/config/ftmodule.h'. See the document `FreeType 2.0 */+ /* Build System' for more information. */+ /* */+ /* FT_Init_FreeType(): */+ /* This function creates a system object for the current platform, */+ /* builds a library out of it, then calls FT_Default_Drivers(). */+ /* */+ /* Note that even if FT_Init_FreeType() uses the implementation of the */+ /* system object defined at build time, client applications are still */+ /* able to provide their own `ftsystem.c'. */+ /* */+ /*************************************************************************/+++#include <ft2build.h>+#include FT_CONFIG_CONFIG_H+#include FT_INTERNAL_OBJECTS_H+#include FT_INTERNAL_DEBUG_H+#include FT_MODULE_H+#include "basepic.h"+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_init++#ifndef FT_CONFIG_OPTION_PIC++#undef FT_USE_MODULE+#ifdef __cplusplus+#define FT_USE_MODULE( type, x ) extern "C" const type x;+#else+#define FT_USE_MODULE( type, x ) extern const type x;+#endif+++#include FT_CONFIG_MODULES_H+++#undef FT_USE_MODULE+#define FT_USE_MODULE( type, x ) (const FT_Module_Class*)&(x),++ static+ const FT_Module_Class* const ft_default_modules[] =+ {+#include FT_CONFIG_MODULES_H+ 0+ };++#else /* FT_CONFIG_OPTION_PIC */++#ifdef __cplusplus+#define FT_EXTERNC extern "C"+#else+#define FT_EXTERNC extern+#endif++ /* declare the module's class creation/destruction functions */+#undef FT_USE_MODULE+#define FT_USE_MODULE( type, x ) \+ FT_EXTERNC FT_Error FT_Create_Class_##x( FT_Library library, FT_Module_Class** output_class ); \+ FT_EXTERNC void FT_Destroy_Class_##x( FT_Library library, FT_Module_Class* clazz );++#include FT_CONFIG_MODULES_H+++ /* count all module classes */+#undef FT_USE_MODULE+#define FT_USE_MODULE( type, x ) MODULE_CLASS_##x,++ enum+ {+#include FT_CONFIG_MODULES_H+ FT_NUM_MODULE_CLASSES+ };++ /* destroy all module classes */ +#undef FT_USE_MODULE+#define FT_USE_MODULE( type, x ) \+ if ( classes[i] ) { FT_Destroy_Class_##x(library, classes[i]); } \+ i++; \++ FT_BASE_DEF( void )+ ft_destroy_default_module_classes( FT_Library library )+ {+ FT_Module_Class** classes;+ FT_Memory memory;+ FT_UInt i;+ BasePIC* pic_container = (BasePIC*)library->pic_container.base;++ if ( !pic_container->default_module_classes )+ return;++ memory = library->memory;+ classes = pic_container->default_module_classes;+ i = 0;++#include FT_CONFIG_MODULES_H++ FT_FREE( classes );+ pic_container->default_module_classes = 0;+ }++ /* initialize all module classes and the pointer table */+#undef FT_USE_MODULE+#define FT_USE_MODULE( type, x ) \+ error = FT_Create_Class_##x(library, &clazz); \+ if (error) goto Exit; \+ classes[i++] = clazz;++ FT_BASE_DEF( FT_Error )+ ft_create_default_module_classes( FT_Library library )+ {+ FT_Error error;+ FT_Memory memory;+ FT_Module_Class** classes;+ FT_Module_Class* clazz;+ FT_UInt i;+ BasePIC* pic_container = (BasePIC*)library->pic_container.base;++ memory = library->memory; + pic_container->default_module_classes = 0;++ if ( FT_ALLOC(classes, sizeof(FT_Module_Class*) * (FT_NUM_MODULE_CLASSES + 1) ) )+ return error;+ /* initialize all pointers to 0, especially the last one */+ for (i = 0; i < FT_NUM_MODULE_CLASSES; i++)+ classes[i] = 0;+ classes[FT_NUM_MODULE_CLASSES] = 0;++ i = 0;++#include FT_CONFIG_MODULES_H++Exit: + if (error) ft_destroy_default_module_classes( library );+ else pic_container->default_module_classes = classes;++ return error; + }+++#endif /* FT_CONFIG_OPTION_PIC */++ /* documentation is in ftmodapi.h */++ FT_EXPORT_DEF( void )+ FT_Add_Default_Modules( FT_Library library )+ {+ FT_Error error;+ const FT_Module_Class* const* cur;+++ /* test for valid `library' delayed to FT_Add_Module() */++ cur = FT_DEFAULT_MODULES_GET;+ while ( *cur )+ {+ error = FT_Add_Module( library, *cur );+ /* notify errors, but don't stop */+ if ( error )+ FT_TRACE0(( "FT_Add_Default_Module:"+ " Cannot install `%s', error = 0x%x\n",+ (*cur)->module_name, error ));+ cur++;+ }+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Init_FreeType( FT_Library *alibrary )+ {+ FT_Error error;+ FT_Memory memory;+++ /* First of all, allocate a new system object -- this function is part */+ /* of the system-specific component, i.e. `ftsystem.c'. */++ memory = FT_New_Memory();+ if ( !memory )+ {+ FT_ERROR(( "FT_Init_FreeType: cannot find memory manager\n" ));+ return FT_Err_Unimplemented_Feature;+ }++ /* build a library out of it, then fill it with the set of */+ /* default drivers. */++ error = FT_New_Library( memory, alibrary );+ if ( error )+ FT_Done_Memory( memory );+ else+ FT_Add_Default_Modules( *alibrary );++ return error;+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Done_FreeType( FT_Library library )+ {+ if ( library )+ {+ FT_Memory memory = library->memory;+++ /* Discard the library object */+ FT_Done_Library( library );++ /* discard memory manager */+ FT_Done_Memory( memory );+ }++ return FT_Err_Ok;+ }+++/* END */
+ src/base/ftlcdfil.c view
@@ -0,0 +1,376 @@+/***************************************************************************/+/* */+/* ftlcdfil.c */+/* */+/* FreeType API for color filtering of subpixel bitmap glyphs (body). */+/* */+/* Copyright 2006, 2008, 2009, 2010 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_LCD_FILTER_H+#include FT_IMAGE_H+#include FT_INTERNAL_OBJECTS_H+++#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING++/* define USE_LEGACY to implement the legacy filter */+#define USE_LEGACY++ /* FIR filter used by the default and light filters */+ static void+ _ft_lcd_filter_fir( FT_Bitmap* bitmap,+ FT_Render_Mode mode,+ FT_Library library )+ {+ FT_Byte* weights = library->lcd_weights;+ FT_UInt width = (FT_UInt)bitmap->width;+ FT_UInt height = (FT_UInt)bitmap->rows;+++ /* horizontal in-place FIR filter */+ if ( mode == FT_RENDER_MODE_LCD && width >= 4 )+ {+ FT_Byte* line = bitmap->buffer;+++ for ( ; height > 0; height--, line += bitmap->pitch )+ {+ FT_UInt fir[5];+ FT_UInt val1, xx;+++ val1 = line[0];+ fir[0] = weights[2] * val1;+ fir[1] = weights[3] * val1;+ fir[2] = weights[4] * val1;+ fir[3] = 0;+ fir[4] = 0;++ val1 = line[1];+ fir[0] += weights[1] * val1;+ fir[1] += weights[2] * val1;+ fir[2] += weights[3] * val1;+ fir[3] += weights[4] * val1;++ for ( xx = 2; xx < width; xx++ )+ {+ FT_UInt val, pix;+++ val = line[xx];+ pix = fir[0] + weights[0] * val;+ fir[0] = fir[1] + weights[1] * val;+ fir[1] = fir[2] + weights[2] * val;+ fir[2] = fir[3] + weights[3] * val;+ fir[3] = weights[4] * val;++ pix >>= 8;+ pix |= -( pix >> 8 );+ line[xx - 2] = (FT_Byte)pix;+ }++ {+ FT_UInt pix;+++ pix = fir[0] >> 8;+ pix |= -( pix >> 8 );+ line[xx - 2] = (FT_Byte)pix;++ pix = fir[1] >> 8;+ pix |= -( pix >> 8 );+ line[xx - 1] = (FT_Byte)pix;+ }+ }+ }++ /* vertical in-place FIR filter */+ else if ( mode == FT_RENDER_MODE_LCD_V && height >= 4 )+ {+ FT_Byte* column = bitmap->buffer;+ FT_Int pitch = bitmap->pitch;+++ for ( ; width > 0; width--, column++ )+ {+ FT_Byte* col = column;+ FT_UInt fir[5];+ FT_UInt val1, yy;+++ val1 = col[0];+ fir[0] = weights[2] * val1;+ fir[1] = weights[3] * val1;+ fir[2] = weights[4] * val1;+ fir[3] = 0;+ fir[4] = 0;+ col += pitch;++ val1 = col[0];+ fir[0] += weights[1] * val1;+ fir[1] += weights[2] * val1;+ fir[2] += weights[3] * val1;+ fir[3] += weights[4] * val1;+ col += pitch;++ for ( yy = 2; yy < height; yy++ )+ {+ FT_UInt val, pix;+++ val = col[0];+ pix = fir[0] + weights[0] * val;+ fir[0] = fir[1] + weights[1] * val;+ fir[1] = fir[2] + weights[2] * val;+ fir[2] = fir[3] + weights[3] * val;+ fir[3] = weights[4] * val;++ pix >>= 8;+ pix |= -( pix >> 8 );+ col[-2 * pitch] = (FT_Byte)pix;+ col += pitch;+ }++ {+ FT_UInt pix;+++ pix = fir[0] >> 8;+ pix |= -( pix >> 8 );+ col[-2 * pitch] = (FT_Byte)pix;++ pix = fir[1] >> 8;+ pix |= -( pix >> 8 );+ col[-pitch] = (FT_Byte)pix;+ }+ }+ }+ }+++#ifdef USE_LEGACY++ /* intra-pixel filter used by the legacy filter */+ static void+ _ft_lcd_filter_legacy( FT_Bitmap* bitmap,+ FT_Render_Mode mode,+ FT_Library library )+ {+ FT_UInt width = (FT_UInt)bitmap->width;+ FT_UInt height = (FT_UInt)bitmap->rows;+ FT_Int pitch = bitmap->pitch;++ static const int filters[3][3] =+ {+ { 65538 * 9/13, 65538 * 1/6, 65538 * 1/13 },+ { 65538 * 3/13, 65538 * 4/6, 65538 * 3/13 },+ { 65538 * 1/13, 65538 * 1/6, 65538 * 9/13 }+ };++ FT_UNUSED( library );+++ /* horizontal in-place intra-pixel filter */+ if ( mode == FT_RENDER_MODE_LCD && width >= 3 )+ {+ FT_Byte* line = bitmap->buffer;+++ for ( ; height > 0; height--, line += pitch )+ {+ FT_UInt xx;+++ for ( xx = 0; xx < width; xx += 3 )+ {+ FT_UInt r = 0;+ FT_UInt g = 0;+ FT_UInt b = 0;+ FT_UInt p;+++ p = line[xx];+ r += filters[0][0] * p;+ g += filters[0][1] * p;+ b += filters[0][2] * p;++ p = line[xx + 1];+ r += filters[1][0] * p;+ g += filters[1][1] * p;+ b += filters[1][2] * p;++ p = line[xx + 2];+ r += filters[2][0] * p;+ g += filters[2][1] * p;+ b += filters[2][2] * p;++ line[xx] = (FT_Byte)( r / 65536 );+ line[xx + 1] = (FT_Byte)( g / 65536 );+ line[xx + 2] = (FT_Byte)( b / 65536 );+ }+ }+ }+ else if ( mode == FT_RENDER_MODE_LCD_V && height >= 3 )+ {+ FT_Byte* column = bitmap->buffer;+++ for ( ; width > 0; width--, column++ )+ {+ FT_Byte* col = column;+ FT_Byte* col_end = col + height * pitch;+++ for ( ; col < col_end; col += 3 * pitch )+ {+ FT_UInt r = 0;+ FT_UInt g = 0;+ FT_UInt b = 0;+ FT_UInt p;+++ p = col[0];+ r += filters[0][0] * p;+ g += filters[0][1] * p;+ b += filters[0][2] * p;++ p = col[pitch];+ r += filters[1][0] * p;+ g += filters[1][1] * p;+ b += filters[1][2] * p;++ p = col[pitch * 2];+ r += filters[2][0] * p;+ g += filters[2][1] * p;+ b += filters[2][2] * p;++ col[0] = (FT_Byte)( r / 65536 );+ col[pitch] = (FT_Byte)( g / 65536 );+ col[2 * pitch] = (FT_Byte)( b / 65536 );+ }+ }+ }+ }++#endif /* USE_LEGACY */+++ FT_EXPORT_DEF( FT_Error )+ FT_Library_SetLcdFilterWeights( FT_Library library,+ unsigned char *weights )+ {+ if ( !library || !weights )+ return FT_Err_Invalid_Argument;++ ft_memcpy( library->lcd_weights, weights, 5 );++ return FT_Err_Ok;+ }+++ FT_EXPORT_DEF( FT_Error )+ FT_Library_SetLcdFilter( FT_Library library,+ FT_LcdFilter filter )+ {+ 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 )+ return FT_Err_Invalid_Argument;++ switch ( filter )+ {+ case FT_LCD_FILTER_NONE:+ library->lcd_filter_func = NULL;+ library->lcd_extra = 0;+ break;++ case FT_LCD_FILTER_DEFAULT:+#if defined( FT_FORCE_LEGACY_LCD_FILTER )++ library->lcd_filter_func = _ft_lcd_filter_legacy;+ library->lcd_extra = 0;++#elif defined( FT_FORCE_LIGHT_LCD_FILTER )++ ft_memcpy( library->lcd_weights, light_filter, 5 );+ library->lcd_filter_func = _ft_lcd_filter_fir;+ library->lcd_extra = 2;++#else++ ft_memcpy( library->lcd_weights, default_filter, 5 );+ library->lcd_filter_func = _ft_lcd_filter_fir;+ library->lcd_extra = 2;++#endif++ break;++ case FT_LCD_FILTER_LIGHT:+ ft_memcpy( library->lcd_weights, light_filter, 5 );+ library->lcd_filter_func = _ft_lcd_filter_fir;+ library->lcd_extra = 2;+ break;++#ifdef USE_LEGACY++ case FT_LCD_FILTER_LEGACY:+ library->lcd_filter_func = _ft_lcd_filter_legacy;+ library->lcd_extra = 0;+ break;++#endif++ default:+ return FT_Err_Invalid_Argument;+ }++ library->lcd_filter = filter;++ return FT_Err_Ok;+ }++#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */++ FT_EXPORT_DEF( FT_Error )+ FT_Library_SetLcdFilterWeights( FT_Library library,+ unsigned char *weights )+ {+ FT_UNUSED( library );+ FT_UNUSED( weights );++ return FT_Err_Unimplemented_Feature;+ }+++ FT_EXPORT_DEF( FT_Error )+ FT_Library_SetLcdFilter( FT_Library library,+ FT_LcdFilter filter )+ {+ FT_UNUSED( library );+ FT_UNUSED( filter );++ return FT_Err_Unimplemented_Feature;+ }++#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */+++/* END */
+ src/base/ftmac.c view
@@ -0,0 +1,1057 @@+/***************************************************************************/+/* */+/* 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-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, */+/* 2009 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+++ /* 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_Err_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_Err_Unknown_File_Format;++ if ( noErr != FT_ATSFontGetFileReference( ats_font_id, ats_font_ref ) )+ return FT_Err_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;+++ err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );+ if ( FT_Err_Ok != err )+ return err;++ if ( noErr != FSRefMakePath( &ref, path, maxPathSize ) )+ return FT_Err_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_Err_Unimplemented_Feature;+#else+ FSRef ref;+ FT_Error err;+++ err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );+ if ( FT_Err_Ok != err )+ return err;++ if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone, NULL, NULL,+ pathSpec, NULL ) )+ return FT_Err_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_Err_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;+ FamRec* fond;+ short i, face, face_all;+++ fond = (FamRec*)fond_data;+ 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) );+ p += sizeof ( short );++ for ( i = 0; i < string_count && i < 64; 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] <= FT_MIN( string_count, 64 ) )+ {+ 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_Err_Invalid_Argument;++ if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,+ NULL, NULL, NULL, &par_ref ) )+ return FT_Err_Invalid_Argument;++ if ( noErr != FSRefMakePath( &par_ref, path_lwfn, path_size ) )+ return FT_Err_Invalid_Argument;++ if ( ft_strlen( (char *)path_lwfn ) + 1 + base_lwfn[0] > path_size )+ return FT_Err_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_Err_Cannot_Open_Resource;++ if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,+ NULL, NULL, NULL, NULL ) )+ return FT_Err_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 ( FT_Err_Ok == 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 += GetHandleSize( post_data ) - 2;+ last_code = code;++ /* detect integer overflows */+ if ( total_size < old_total_size )+ {+ error = FT_Err_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_Err_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_Err_Invalid_Handle;++ sfnt_size = (FT_ULong)GetHandleSize( sfnt );+ 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, num_faces_in_fond;+++ if ( noErr != FT_FSPathMakeRes( pathname, &res_ref ) )+ return FT_Err_Cannot_Open_Resource;++ UseResFile( res_ref );+ if ( ResError() )+ return FT_Err_Cannot_Open_Resource;++ num_faces_in_res = 0;+ for ( res_index = 1; ; ++res_index )+ {+ 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 ( FT_Err_Ok == error && NULL != aface && NULL != *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;+++ GetResInfo( fond, &fond_id, &fond_type, fond_name );+ if ( ResError() != noErr || fond_type != TTAG_FOND )+ return FT_Err_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 ( FT_Err_Ok == 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_Err_Unknown_File_Format;++ found_no_lwfn_file:+ if ( have_sfnt && FT_Err_Ok != 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_Err_Invalid_Argument;++ error = FT_Err_Ok;+ *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];+++ if ( !ref )+ return FT_Err_Invalid_Argument;++ err = FSRefMakePath( ref, pathname, sizeof ( pathname ) );+ if ( err )+ error = FT_Err_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_Err_Unimplemented_Feature;+#else+ FSRef ref;+++ if ( !spec || FSpMakeFSRef( spec, &ref ) != noErr )+ return FT_Err_Invalid_Argument;+ else+ return FT_New_Face_From_FSRef( library, &ref, face_index, aface );+#endif+ }+++/* END */
+ src/base/ftmm.c view
@@ -0,0 +1,202 @@+/***************************************************************************/+/* */+/* ftmm.c */+/* */+/* Multiple Master font support (body). */+/* */+/* Copyright 1996-2001, 2003, 2004, 2009 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_MULTIPLE_MASTERS_H+#include FT_INTERNAL_OBJECTS_H+#include FT_SERVICE_MULTIPLE_MASTERS_H+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_mm+++ static FT_Error+ ft_face_get_mm_service( FT_Face face,+ FT_Service_MultiMasters *aservice )+ {+ FT_Error error;+++ *aservice = NULL;++ if ( !face )+ return FT_Err_Invalid_Face_Handle;++ error = FT_Err_Invalid_Argument;++ if ( FT_HAS_MULTIPLE_MASTERS( face ) )+ {+ FT_FACE_LOOKUP_SERVICE( face,+ *aservice,+ MULTI_MASTERS );++ if ( *aservice )+ error = FT_Err_Ok;+ }++ return error;+ }+++ /* documentation is in ftmm.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Get_Multi_Master( FT_Face face,+ FT_Multi_Master *amaster )+ {+ FT_Error error;+ FT_Service_MultiMasters service;+++ error = ft_face_get_mm_service( face, &service );+ if ( !error )+ {+ error = FT_Err_Invalid_Argument;+ if ( service->get_mm )+ error = service->get_mm( face, amaster );+ }++ return error;+ }+++ /* documentation is in ftmm.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Get_MM_Var( FT_Face face,+ FT_MM_Var* *amaster )+ {+ FT_Error error;+ FT_Service_MultiMasters service;+++ error = ft_face_get_mm_service( face, &service );+ if ( !error )+ {+ error = FT_Err_Invalid_Argument;+ if ( service->get_mm_var )+ error = service->get_mm_var( face, amaster );+ }++ return error;+ }+++ /* documentation is in ftmm.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Set_MM_Design_Coordinates( FT_Face face,+ FT_UInt num_coords,+ FT_Long* coords )+ {+ FT_Error error;+ FT_Service_MultiMasters service;+++ error = ft_face_get_mm_service( face, &service );+ if ( !error )+ {+ error = FT_Err_Invalid_Argument;+ if ( service->set_mm_design )+ error = service->set_mm_design( face, num_coords, coords );+ }++ return error;+ }+++ /* documentation is in ftmm.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Set_Var_Design_Coordinates( FT_Face face,+ FT_UInt num_coords,+ FT_Fixed* coords )+ {+ FT_Error error;+ FT_Service_MultiMasters service;+++ error = ft_face_get_mm_service( face, &service );+ if ( !error )+ {+ error = FT_Err_Invalid_Argument;+ if ( service->set_var_design )+ error = service->set_var_design( face, num_coords, coords );+ }++ return error;+ }+++ /* documentation is in ftmm.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Set_MM_Blend_Coordinates( FT_Face face,+ FT_UInt num_coords,+ FT_Fixed* coords )+ {+ FT_Error error;+ FT_Service_MultiMasters service;+++ error = ft_face_get_mm_service( face, &service );+ if ( !error )+ {+ error = FT_Err_Invalid_Argument;+ if ( service->set_mm_blend )+ error = service->set_mm_blend( face, num_coords, coords );+ }++ return error;+ }+++ /* documentation is in ftmm.h */++ /* This is exactly the same as the previous function. It exists for */+ /* orthogonality. */++ FT_EXPORT_DEF( FT_Error )+ FT_Set_Var_Blend_Coordinates( FT_Face face,+ FT_UInt num_coords,+ FT_Fixed* coords )+ {+ FT_Error error;+ FT_Service_MultiMasters service;+++ error = ft_face_get_mm_service( face, &service );+ if ( !error )+ {+ error = FT_Err_Invalid_Argument;+ if ( service->set_mm_blend )+ error = service->set_mm_blend( face, num_coords, coords );+ }++ return error;+ }+++/* END */
+ src/base/ftobjs.c view
@@ -0,0 +1,4664 @@+/***************************************************************************/+/* */+/* ftobjs.c */+/* */+/* The FreeType private base classes (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */+/* 2010 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_LIST_H+#include FT_OUTLINE_H+#include FT_INTERNAL_VALIDATE_H+#include FT_INTERNAL_OBJECTS_H+#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_RFORK_H+#include FT_INTERNAL_STREAM_H+#include FT_INTERNAL_SFNT_H /* for SFNT_Load_Table_Func */+#include FT_TRUETYPE_TABLES_H+#include FT_TRUETYPE_TAGS_H+#include FT_TRUETYPE_IDS_H++#include FT_SERVICE_SFNT_H+#include FT_SERVICE_POSTSCRIPT_NAME_H+#include FT_SERVICE_GLYPH_DICT_H+#include FT_SERVICE_TT_CMAP_H+#include FT_SERVICE_KERNING_H+#include FT_SERVICE_TRUETYPE_ENGINE_H++#ifdef FT_CONFIG_OPTION_MAC_FONTS+#include "ftbase.h"+#endif++#define GRID_FIT_METRICS+++ FT_BASE_DEF( FT_Pointer )+ ft_service_list_lookup( FT_ServiceDesc service_descriptors,+ const char* service_id )+ {+ FT_Pointer result = NULL;+ FT_ServiceDesc desc = service_descriptors;+++ if ( desc && service_id )+ {+ for ( ; desc->serv_id != NULL; desc++ )+ {+ if ( ft_strcmp( desc->serv_id, service_id ) == 0 )+ {+ result = (FT_Pointer)desc->serv_data;+ break;+ }+ }+ }++ return result;+ }+++ FT_BASE_DEF( void )+ ft_validator_init( FT_Validator valid,+ const FT_Byte* base,+ const FT_Byte* limit,+ FT_ValidationLevel level )+ {+ valid->base = base;+ valid->limit = limit;+ valid->level = level;+ valid->error = FT_Err_Ok;+ }+++ FT_BASE_DEF( FT_Int )+ ft_validator_run( FT_Validator valid )+ {+ /* This function doesn't work! None should call it. */+ FT_UNUSED( valid );++ return -1;+ }+++ FT_BASE_DEF( void )+ ft_validator_error( FT_Validator valid,+ FT_Error error )+ {+ /* since the cast below also disables the compiler's */+ /* type check, we introduce a dummy variable, which */+ /* will be optimized away */+ volatile ft_jmp_buf* jump_buffer = &valid->jump_buffer;+++ valid->error = error;++ /* throw away volatileness; use `jump_buffer' or the */+ /* compiler may warn about an unused local variable */+ ft_longjmp( *(ft_jmp_buf*) jump_buffer, 1 );+ }+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** ****/+ /**** S T R E A M ****/+ /**** ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ /* create a new input stream from an FT_Open_Args structure */+ /* */+ FT_BASE_DEF( FT_Error )+ FT_Stream_New( FT_Library library,+ const FT_Open_Args* args,+ FT_Stream *astream )+ {+ FT_Error error;+ FT_Memory memory;+ FT_Stream stream;+++ *astream = 0;++ if ( !library )+ return FT_Err_Invalid_Library_Handle;++ if ( !args )+ return FT_Err_Invalid_Argument;++ memory = library->memory;++ if ( FT_NEW( stream ) )+ goto Exit;++ stream->memory = memory;++ if ( args->flags & FT_OPEN_MEMORY )+ {+ /* create a memory-based stream */+ FT_Stream_OpenMemory( stream,+ (const FT_Byte*)args->memory_base,+ args->memory_size );+ }+ else if ( args->flags & FT_OPEN_PATHNAME )+ {+ /* create a normal system stream */+ error = FT_Stream_Open( stream, args->pathname );+ stream->pathname.pointer = args->pathname;+ }+ else if ( ( args->flags & FT_OPEN_STREAM ) && args->stream )+ {+ /* use an existing, user-provided stream */++ /* in this case, we do not need to allocate a new stream object */+ /* since the caller is responsible for closing it himself */+ FT_FREE( stream );+ stream = args->stream;+ }+ else+ error = FT_Err_Invalid_Argument;++ if ( error )+ FT_FREE( stream );+ else+ stream->memory = memory; /* just to be certain */++ *astream = stream;++ Exit:+ return error;+ }+++ FT_BASE_DEF( void )+ FT_Stream_Free( FT_Stream stream,+ FT_Int external )+ {+ if ( stream )+ {+ FT_Memory memory = stream->memory;+++ FT_Stream_Close( stream );++ if ( !external )+ FT_FREE( stream );+ }+ }+++ /*************************************************************************/+ /* */+ /* 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_objs+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** ****/+ /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/+ /**** ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ static FT_Error+ ft_glyphslot_init( FT_GlyphSlot slot )+ {+ FT_Driver driver = slot->face->driver;+ FT_Driver_Class clazz = driver->clazz;+ FT_Memory memory = driver->root.memory;+ FT_Error error = FT_Err_Ok;+ FT_Slot_Internal internal = NULL;+++ slot->library = driver->root.library;++ if ( FT_NEW( internal ) )+ goto Exit;++ slot->internal = internal;++ if ( FT_DRIVER_USES_OUTLINES( driver ) )+ error = FT_GlyphLoader_New( memory, &internal->loader );++ if ( !error && clazz->init_slot )+ error = clazz->init_slot( slot );++ Exit:+ return error;+ }+++ FT_BASE_DEF( void )+ ft_glyphslot_free_bitmap( FT_GlyphSlot slot )+ {+ if ( slot->internal && ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) )+ {+ FT_Memory memory = FT_FACE_MEMORY( slot->face );+++ FT_FREE( slot->bitmap.buffer );+ slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;+ }+ else+ {+ /* assume that the bitmap buffer was stolen or not */+ /* allocated from the heap */+ slot->bitmap.buffer = NULL;+ }+ }+++ FT_BASE_DEF( void )+ ft_glyphslot_set_bitmap( FT_GlyphSlot slot,+ FT_Byte* buffer )+ {+ ft_glyphslot_free_bitmap( slot );++ slot->bitmap.buffer = buffer;++ FT_ASSERT( (slot->internal->flags & FT_GLYPH_OWN_BITMAP) == 0 );+ }+++ FT_BASE_DEF( FT_Error )+ ft_glyphslot_alloc_bitmap( FT_GlyphSlot slot,+ FT_ULong size )+ {+ FT_Memory memory = FT_FACE_MEMORY( slot->face );+ FT_Error error;+++ if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )+ FT_FREE( slot->bitmap.buffer );+ else+ slot->internal->flags |= FT_GLYPH_OWN_BITMAP;++ (void)FT_ALLOC( slot->bitmap.buffer, size );+ return error;+ }+++ static void+ ft_glyphslot_clear( FT_GlyphSlot slot )+ {+ /* free bitmap if needed */+ ft_glyphslot_free_bitmap( slot );++ /* clear all public fields in the glyph slot */+ FT_ZERO( &slot->metrics );+ FT_ZERO( &slot->outline );++ slot->bitmap.width = 0;+ slot->bitmap.rows = 0;+ slot->bitmap.pitch = 0;+ slot->bitmap.pixel_mode = 0;+ /* `slot->bitmap.buffer' has been handled by ft_glyphslot_free_bitmap */++ slot->bitmap_left = 0;+ slot->bitmap_top = 0;+ slot->num_subglyphs = 0;+ slot->subglyphs = 0;+ slot->control_data = 0;+ slot->control_len = 0;+ slot->other = 0;+ slot->format = FT_GLYPH_FORMAT_NONE;++ slot->linearHoriAdvance = 0;+ slot->linearVertAdvance = 0;+ slot->lsb_delta = 0;+ slot->rsb_delta = 0;+ }+++ static void+ ft_glyphslot_done( FT_GlyphSlot slot )+ {+ FT_Driver driver = slot->face->driver;+ FT_Driver_Class clazz = driver->clazz;+ FT_Memory memory = driver->root.memory;+++ if ( clazz->done_slot )+ clazz->done_slot( slot );++ /* free bitmap buffer if needed */+ ft_glyphslot_free_bitmap( slot );++ /* slot->internal might be NULL in out-of-memory situations */+ if ( slot->internal )+ {+ /* free glyph loader */+ if ( FT_DRIVER_USES_OUTLINES( driver ) )+ {+ FT_GlyphLoader_Done( slot->internal->loader );+ slot->internal->loader = 0;+ }++ FT_FREE( slot->internal );+ }+ }+++ /* documentation is in ftobjs.h */++ FT_BASE_DEF( FT_Error )+ FT_New_GlyphSlot( FT_Face face,+ FT_GlyphSlot *aslot )+ {+ FT_Error error;+ FT_Driver driver;+ FT_Driver_Class clazz;+ FT_Memory memory;+ FT_GlyphSlot slot;+++ if ( !face || !face->driver )+ return FT_Err_Invalid_Argument;++ driver = face->driver;+ clazz = driver->clazz;+ memory = driver->root.memory;++ FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ));+ if ( !FT_ALLOC( slot, clazz->slot_object_size ) )+ {+ slot->face = face;++ error = ft_glyphslot_init( slot );+ if ( error )+ {+ ft_glyphslot_done( slot );+ FT_FREE( slot );+ goto Exit;+ }++ slot->next = face->glyph;+ face->glyph = slot;++ if ( aslot )+ *aslot = slot;+ }+ else if ( aslot )+ *aslot = 0;+++ Exit:+ FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error ));+ return error;+ }+++ /* documentation is in ftobjs.h */++ FT_BASE_DEF( void )+ FT_Done_GlyphSlot( FT_GlyphSlot slot )+ {+ if ( slot )+ {+ FT_Driver driver = slot->face->driver;+ FT_Memory memory = driver->root.memory;+ FT_GlyphSlot prev;+ FT_GlyphSlot cur;+++ /* Remove slot from its parent face's list */+ prev = NULL;+ cur = slot->face->glyph;++ while ( cur )+ {+ if ( cur == slot )+ {+ if ( !prev )+ slot->face->glyph = cur->next;+ else+ prev->next = cur->next;++ ft_glyphslot_done( slot );+ FT_FREE( slot );+ break;+ }+ prev = cur;+ cur = cur->next;+ }+ }+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( void )+ FT_Set_Transform( FT_Face face,+ FT_Matrix* matrix,+ FT_Vector* delta )+ {+ FT_Face_Internal internal;+++ if ( !face )+ return;++ internal = face->internal;++ internal->transform_flags = 0;++ if ( !matrix )+ {+ internal->transform_matrix.xx = 0x10000L;+ internal->transform_matrix.xy = 0;+ internal->transform_matrix.yx = 0;+ internal->transform_matrix.yy = 0x10000L;+ matrix = &internal->transform_matrix;+ }+ else+ internal->transform_matrix = *matrix;++ /* set transform_flags bit flag 0 if `matrix' isn't the identity */+ if ( ( matrix->xy | matrix->yx ) ||+ matrix->xx != 0x10000L ||+ matrix->yy != 0x10000L )+ internal->transform_flags |= 1;++ if ( !delta )+ {+ internal->transform_delta.x = 0;+ internal->transform_delta.y = 0;+ delta = &internal->transform_delta;+ }+ else+ internal->transform_delta = *delta;++ /* set transform_flags bit flag 1 if `delta' isn't the null vector */+ if ( delta->x | delta->y )+ internal->transform_flags |= 2;+ }+++ static FT_Renderer+ ft_lookup_glyph_renderer( FT_GlyphSlot slot );+++#ifdef GRID_FIT_METRICS+ static void+ ft_glyphslot_grid_fit_metrics( FT_GlyphSlot slot,+ FT_Bool vertical )+ {+ FT_Glyph_Metrics* metrics = &slot->metrics;+ FT_Pos right, bottom;+++ if ( vertical )+ {+ metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX );+ metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY );++ right = FT_PIX_CEIL( metrics->vertBearingX + metrics->width );+ bottom = FT_PIX_CEIL( metrics->vertBearingY + metrics->height );++ metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX );+ metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY );++ metrics->width = right - metrics->vertBearingX;+ metrics->height = bottom - metrics->vertBearingY;+ }+ else+ {+ metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX );+ metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY );++ right = FT_PIX_CEIL ( metrics->horiBearingX + metrics->width );+ bottom = FT_PIX_FLOOR( metrics->horiBearingY - metrics->height );++ metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX );+ metrics->horiBearingY = FT_PIX_CEIL ( metrics->horiBearingY );++ metrics->width = right - metrics->horiBearingX;+ metrics->height = metrics->horiBearingY - bottom;+ }++ metrics->horiAdvance = FT_PIX_ROUND( metrics->horiAdvance );+ metrics->vertAdvance = FT_PIX_ROUND( metrics->vertAdvance );+ }+#endif /* GRID_FIT_METRICS */+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Load_Glyph( FT_Face face,+ FT_UInt glyph_index,+ FT_Int32 load_flags )+ {+ FT_Error error;+ FT_Driver driver;+ FT_GlyphSlot slot;+ FT_Library library;+ FT_Bool autohint = FALSE;+ FT_Module hinter;+++ if ( !face || !face->size || !face->glyph )+ return FT_Err_Invalid_Face_Handle;++ /* The validity test for `glyph_index' is performed by the */+ /* font drivers. */++ slot = face->glyph;+ ft_glyphslot_clear( slot );++ driver = face->driver;+ library = driver->root.library;+ hinter = library->auto_hinter;++ /* resolve load flags dependencies */++ if ( load_flags & FT_LOAD_NO_RECURSE )+ load_flags |= FT_LOAD_NO_SCALE |+ FT_LOAD_IGNORE_TRANSFORM;++ if ( load_flags & FT_LOAD_NO_SCALE )+ {+ load_flags |= FT_LOAD_NO_HINTING |+ FT_LOAD_NO_BITMAP;++ load_flags &= ~FT_LOAD_RENDER;+ }++ /*+ * Determine whether we need to auto-hint or not.+ * The general rules are:+ *+ * - Do only auto-hinting if we have a hinter module, a scalable font+ * format dealing with outlines, and no transforms except simple+ * slants and/or rotations by integer multiples of 90 degrees.+ *+ * - Then, auto-hint if FT_LOAD_FORCE_AUTOHINT is set or if we don't+ * have a native font hinter.+ *+ * - Otherwise, auto-hint for LIGHT hinting mode.+ *+ * - Exception: The font is `tricky' and requires the native hinter to+ * load properly.+ */++ if ( hinter &&+ !( load_flags & FT_LOAD_NO_HINTING ) &&+ !( load_flags & FT_LOAD_NO_AUTOHINT ) &&+ FT_DRIVER_IS_SCALABLE( driver ) &&+ FT_DRIVER_USES_OUTLINES( driver ) &&+ !FT_IS_TRICKY( face ) &&+ ( ( face->internal->transform_matrix.yx == 0 &&+ face->internal->transform_matrix.xx != 0 ) ||+ ( face->internal->transform_matrix.xx == 0 &&+ face->internal->transform_matrix.yx != 0 ) ) )+ {+ if ( ( load_flags & FT_LOAD_FORCE_AUTOHINT ) ||+ !FT_DRIVER_HAS_HINTER( driver ) )+ autohint = TRUE;+ else+ {+ FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags );+++ if ( mode == FT_RENDER_MODE_LIGHT ||+ face->internal->ignore_unpatented_hinter )+ autohint = TRUE;+ }+ }++ if ( autohint )+ {+ FT_AutoHinter_Service hinting;+++ /* try to load embedded bitmaps first if available */+ /* */+ /* XXX: This is really a temporary hack that should disappear */+ /* promptly with FreeType 2.1! */+ /* */+ if ( FT_HAS_FIXED_SIZES( face ) &&+ ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )+ {+ error = driver->clazz->load_glyph( slot, face->size,+ glyph_index,+ load_flags | FT_LOAD_SBITS_ONLY );++ if ( !error && slot->format == FT_GLYPH_FORMAT_BITMAP )+ goto Load_Ok;+ }++ {+ FT_Face_Internal internal = face->internal;+ FT_Int transform_flags = internal->transform_flags;+++ /* since the auto-hinter calls FT_Load_Glyph by itself, */+ /* make sure that glyphs aren't transformed */+ internal->transform_flags = 0;++ /* load auto-hinted outline */+ hinting = (FT_AutoHinter_Service)hinter->clazz->module_interface;++ error = hinting->load_glyph( (FT_AutoHinter)hinter,+ slot, face->size,+ glyph_index, load_flags );++ internal->transform_flags = transform_flags;+ }+ }+ else+ {+ error = driver->clazz->load_glyph( slot,+ face->size,+ glyph_index,+ load_flags );+ if ( error )+ goto Exit;++ if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )+ {+ /* check that the loaded outline is correct */+ error = FT_Outline_Check( &slot->outline );+ if ( error )+ goto Exit;++#ifdef GRID_FIT_METRICS+ if ( !( load_flags & FT_LOAD_NO_HINTING ) )+ ft_glyphslot_grid_fit_metrics( slot,+ FT_BOOL( load_flags & FT_LOAD_VERTICAL_LAYOUT ) );+#endif+ }+ }++ Load_Ok:+ /* compute the advance */+ if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )+ {+ slot->advance.x = 0;+ slot->advance.y = slot->metrics.vertAdvance;+ }+ else+ {+ slot->advance.x = slot->metrics.horiAdvance;+ slot->advance.y = 0;+ }++ /* compute the linear advance in 16.16 pixels */+ if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 &&+ ( FT_IS_SCALABLE( face ) ) )+ {+ FT_Size_Metrics* metrics = &face->size->metrics;+++ /* it's tricky! */+ slot->linearHoriAdvance = FT_MulDiv( slot->linearHoriAdvance,+ metrics->x_scale, 64 );++ slot->linearVertAdvance = FT_MulDiv( slot->linearVertAdvance,+ metrics->y_scale, 64 );+ }++ if ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) == 0 )+ {+ FT_Face_Internal internal = face->internal;+++ /* now, transform the glyph image if needed */+ if ( internal->transform_flags )+ {+ /* get renderer */+ FT_Renderer renderer = ft_lookup_glyph_renderer( slot );+++ if ( renderer )+ error = renderer->clazz->transform_glyph(+ renderer, slot,+ &internal->transform_matrix,+ &internal->transform_delta );+ else if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )+ {+ /* apply `standard' transformation if no renderer is available */+ if ( &internal->transform_matrix )+ FT_Outline_Transform( &slot->outline,+ &internal->transform_matrix );++ if ( &internal->transform_delta )+ FT_Outline_Translate( &slot->outline,+ internal->transform_delta.x,+ internal->transform_delta.y );+ }++ /* transform advance */+ FT_Vector_Transform( &slot->advance, &internal->transform_matrix );+ }+ }++ FT_TRACE5(( " x advance: %d\n" , slot->advance.x ));+ FT_TRACE5(( " y advance: %d\n" , slot->advance.y ));++ FT_TRACE5(( " linear x advance: %d\n" , slot->linearHoriAdvance ));+ FT_TRACE5(( " linear y advance: %d\n" , slot->linearVertAdvance ));++ /* do we need to render the image now? */+ if ( !error &&+ slot->format != FT_GLYPH_FORMAT_BITMAP &&+ slot->format != FT_GLYPH_FORMAT_COMPOSITE &&+ load_flags & FT_LOAD_RENDER )+ {+ FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags );+++ if ( mode == FT_RENDER_MODE_NORMAL &&+ (load_flags & FT_LOAD_MONOCHROME ) )+ mode = FT_RENDER_MODE_MONO;++ error = FT_Render_Glyph( slot, mode );+ }++ Exit:+ return error;+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Load_Char( FT_Face face,+ FT_ULong char_code,+ FT_Int32 load_flags )+ {+ FT_UInt glyph_index;+++ if ( !face )+ return FT_Err_Invalid_Face_Handle;++ glyph_index = (FT_UInt)char_code;+ if ( face->charmap )+ glyph_index = FT_Get_Char_Index( face, char_code );++ return FT_Load_Glyph( face, glyph_index, load_flags );+ }+++ /* destructor for sizes list */+ static void+ destroy_size( FT_Memory memory,+ FT_Size size,+ FT_Driver driver )+ {+ /* finalize client-specific data */+ if ( size->generic.finalizer )+ size->generic.finalizer( size );++ /* finalize format-specific stuff */+ if ( driver->clazz->done_size )+ driver->clazz->done_size( size );++ FT_FREE( size->internal );+ FT_FREE( size );+ }+++ static void+ ft_cmap_done_internal( FT_CMap cmap );+++ static void+ destroy_charmaps( FT_Face face,+ FT_Memory memory )+ {+ FT_Int n;+++ if ( !face )+ return;++ for ( n = 0; n < face->num_charmaps; n++ )+ {+ FT_CMap cmap = FT_CMAP( face->charmaps[n] );+++ ft_cmap_done_internal( cmap );++ face->charmaps[n] = NULL;+ }++ FT_FREE( face->charmaps );+ face->num_charmaps = 0;+ }+++ /* destructor for faces list */+ static void+ destroy_face( FT_Memory memory,+ FT_Face face,+ FT_Driver driver )+ {+ FT_Driver_Class clazz = driver->clazz;+++ /* discard auto-hinting data */+ if ( face->autohint.finalizer )+ face->autohint.finalizer( face->autohint.data );++ /* Discard glyph slots for this face. */+ /* Beware! FT_Done_GlyphSlot() changes the field `face->glyph' */+ while ( face->glyph )+ FT_Done_GlyphSlot( face->glyph );++ /* discard all sizes for this face */+ FT_List_Finalize( &face->sizes_list,+ (FT_List_Destructor)destroy_size,+ memory,+ driver );+ face->size = 0;++ /* now discard client data */+ if ( face->generic.finalizer )+ face->generic.finalizer( face );++ /* discard charmaps */+ destroy_charmaps( face, memory );++ /* finalize format-specific stuff */+ if ( clazz->done_face )+ clazz->done_face( face );++ /* close the stream for this face if needed */+ FT_Stream_Free(+ face->stream,+ ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );++ face->stream = 0;++ /* get rid of it */+ if ( face->internal )+ {+ FT_FREE( face->internal );+ }+ FT_FREE( face );+ }+++ static void+ Destroy_Driver( FT_Driver driver )+ {+ FT_List_Finalize( &driver->faces_list,+ (FT_List_Destructor)destroy_face,+ driver->root.memory,+ driver );++ /* check whether we need to drop the driver's glyph loader */+ if ( FT_DRIVER_USES_OUTLINES( driver ) )+ FT_GlyphLoader_Done( driver->glyph_loader );+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* find_unicode_charmap */+ /* */+ /* <Description> */+ /* This function finds a Unicode charmap, if there is one. */+ /* And if there is more than one, it tries to favour the more */+ /* extensive one, i.e., one that supports UCS-4 against those which */+ /* are limited to the BMP (said UCS-2 encoding.) */+ /* */+ /* This function is called from open_face() (just below), and also */+ /* from FT_Select_Charmap( ..., FT_ENCODING_UNICODE ). */+ /* */+ static FT_Error+ find_unicode_charmap( FT_Face face )+ {+ FT_CharMap* first;+ FT_CharMap* cur;+++ /* caller should have already checked that `face' is valid */+ FT_ASSERT( face );++ first = face->charmaps;++ if ( !first )+ return FT_Err_Invalid_CharMap_Handle;++ /*+ * The original TrueType specification(s) only specified charmap+ * formats that are capable of mapping 8 or 16 bit character codes to+ * glyph indices.+ *+ * However, recent updates to the Apple and OpenType specifications+ * introduced new formats that are capable of mapping 32-bit character+ * codes as well. And these are already used on some fonts, mainly to+ * map non-BMP Asian ideographs as defined in Unicode.+ *+ * For compatibility purposes, these fonts generally come with+ * *several* Unicode charmaps:+ *+ * - One of them in the "old" 16-bit format, that cannot access+ * all glyphs in the font.+ *+ * - Another one in the "new" 32-bit format, that can access all+ * the glyphs.+ *+ * This function has been written to always favor a 32-bit charmap+ * when found. Otherwise, a 16-bit one is returned when found.+ */++ /* Since the `interesting' table, with IDs (3,10), is normally the */+ /* last one, we loop backwards. This loses with type1 fonts with */+ /* non-BMP characters (<.0001%), this wins with .ttf with non-BMP */+ /* chars (.01% ?), and this is the same about 99.99% of the time! */++ cur = first + face->num_charmaps; /* points after the last one */++ for ( ; --cur >= first; )+ {+ if ( cur[0]->encoding == FT_ENCODING_UNICODE )+ {+ /* XXX If some new encodings to represent UCS-4 are added, */+ /* they should be added here. */+ if ( ( cur[0]->platform_id == TT_PLATFORM_MICROSOFT &&+ cur[0]->encoding_id == TT_MS_ID_UCS_4 ) ||+ ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE &&+ cur[0]->encoding_id == TT_APPLE_ID_UNICODE_32 ) )+ {+#ifdef FT_MAX_CHARMAP_CACHEABLE+ if ( cur - first > FT_MAX_CHARMAP_CACHEABLE )+ {+ FT_ERROR(( "find_unicode_charmap: UCS-4 cmap is found "+ "at too late position (%d)\n", cur - first ));+ continue;+ }+#endif+ face->charmap = cur[0];+ return FT_Err_Ok;+ }+ }+ }++ /* We do not have any UCS-4 charmap. */+ /* Do the loop again and search for UCS-2 charmaps. */+ cur = first + face->num_charmaps;++ for ( ; --cur >= first; )+ {+ if ( cur[0]->encoding == FT_ENCODING_UNICODE )+ {+#ifdef FT_MAX_CHARMAP_CACHEABLE+ if ( cur - first > FT_MAX_CHARMAP_CACHEABLE )+ {+ FT_ERROR(( "find_unicode_charmap: UCS-2 cmap is found "+ "at too late position (%d)\n", cur - first ));+ continue;+ }+#endif+ face->charmap = cur[0];+ return FT_Err_Ok;+ }+ }++ return FT_Err_Invalid_CharMap_Handle;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* find_variant_selector_charmap */+ /* */+ /* <Description> */+ /* This function finds the variant selector charmap, if there is one. */+ /* There can only be one (platform=0, specific=5, format=14). */+ /* */+ static FT_CharMap+ find_variant_selector_charmap( FT_Face face )+ {+ FT_CharMap* first;+ FT_CharMap* end;+ FT_CharMap* cur;+++ /* caller should have already checked that `face' is valid */+ FT_ASSERT( face );++ first = face->charmaps;++ if ( !first )+ return NULL;++ end = first + face->num_charmaps; /* points after the last one */++ for ( cur = first; cur < end; ++cur )+ {+ if ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE &&+ cur[0]->encoding_id == TT_APPLE_ID_VARIANT_SELECTOR &&+ FT_Get_CMap_Format( cur[0] ) == 14 )+ {+#ifdef FT_MAX_CHARMAP_CACHEABLE+ if ( cur - first > FT_MAX_CHARMAP_CACHEABLE )+ {+ FT_ERROR(( "find_unicode_charmap: UVS cmap is found "+ "at too late position (%d)\n", cur - first ));+ continue;+ }+#endif+ return cur[0];+ }+ }++ return NULL;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* open_face */+ /* */+ /* <Description> */+ /* This function does some work for FT_Open_Face(). */+ /* */+ static FT_Error+ open_face( FT_Driver driver,+ FT_Stream stream,+ FT_Long face_index,+ FT_Int num_params,+ FT_Parameter* params,+ FT_Face *aface )+ {+ FT_Memory memory;+ FT_Driver_Class clazz;+ FT_Face face = 0;+ FT_Error error, error2;+ FT_Face_Internal internal = NULL;+++ clazz = driver->clazz;+ memory = driver->root.memory;++ /* allocate the face object and perform basic initialization */+ if ( FT_ALLOC( face, clazz->face_object_size ) )+ goto Fail;++ if ( FT_NEW( internal ) )+ goto Fail;++ face->internal = internal;++ face->driver = driver;+ face->memory = memory;+ face->stream = stream;++#ifdef FT_CONFIG_OPTION_INCREMENTAL+ {+ int i;+++ face->internal->incremental_interface = 0;+ for ( i = 0; i < num_params && !face->internal->incremental_interface;+ i++ )+ if ( params[i].tag == FT_PARAM_TAG_INCREMENTAL )+ face->internal->incremental_interface =+ (FT_Incremental_Interface)params[i].data;+ }+#endif++ if ( clazz->init_face )+ error = clazz->init_face( stream,+ face,+ (FT_Int)face_index,+ num_params,+ params );+ if ( error )+ goto Fail;++ /* select Unicode charmap by default */+ error2 = find_unicode_charmap( face );++ /* if no Unicode charmap can be found, FT_Err_Invalid_CharMap_Handle */+ /* is returned. */++ /* no error should happen, but we want to play safe */+ if ( error2 && error2 != FT_Err_Invalid_CharMap_Handle )+ {+ error = error2;+ goto Fail;+ }++ *aface = face;++ Fail:+ if ( error )+ {+ destroy_charmaps( face, memory );+ if ( clazz->done_face )+ clazz->done_face( face );+ FT_FREE( internal );+ FT_FREE( face );+ *aface = 0;+ }++ return error;+ }+++ /* there's a Mac-specific extended implementation of FT_New_Face() */+ /* in src/base/ftmac.c */++#if !defined( FT_MACINTOSH ) || defined( DARWIN_NO_CARBON )++ /* documentation is 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;+++ /* test for valid `library' and `aface' delayed to FT_Open_Face() */+ if ( !pathname )+ return FT_Err_Invalid_Argument;++ args.flags = FT_OPEN_PATHNAME;+ args.pathname = (char*)pathname;+ args.stream = NULL;++ return FT_Open_Face( library, &args, face_index, aface );+ }++#endif /* defined( FT_MACINTOSH ) && !defined( DARWIN_NO_CARBON ) */+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Error )+ FT_New_Memory_Face( FT_Library library,+ const FT_Byte* file_base,+ FT_Long file_size,+ FT_Long face_index,+ FT_Face *aface )+ {+ FT_Open_Args args;+++ /* test for valid `library' and `face' delayed to FT_Open_Face() */+ if ( !file_base )+ return FT_Err_Invalid_Argument;++ args.flags = FT_OPEN_MEMORY;+ args.memory_base = file_base;+ args.memory_size = file_size;+ args.stream = NULL;++ return FT_Open_Face( library, &args, face_index, aface );+ }+++#ifdef FT_CONFIG_OPTION_MAC_FONTS++ /* The behavior here is very similar to that in base/ftmac.c, but it */+ /* is designed to work on non-mac systems, so no mac specific calls. */+ /* */+ /* We look at the file and determine if it is a mac dfont file or a mac */+ /* resource file, or a macbinary file containing a mac resource file. */+ /* */+ /* Unlike ftmac I'm not going to look at a `FOND'. I don't really see */+ /* the point, especially since there may be multiple `FOND' resources. */+ /* Instead I'll just look for `sfnt' and `POST' resources, ordered as */+ /* they occur in the file. */+ /* */+ /* Note that multiple `POST' resources do not mean multiple postscript */+ /* fonts; they all get jammed together to make what is essentially a */+ /* pfb file. */+ /* */+ /* We aren't interested in `NFNT' or `FONT' bitmap resources. */+ /* */+ /* As soon as we get an `sfnt' load it into memory and pass it off to */+ /* FT_Open_Face. */+ /* */+ /* If we have a (set of) `POST' resources, massage them into a (memory) */+ /* pfb file and pass that to FT_Open_Face. (As with ftmac.c I'm not */+ /* going to try to save the kerning info. After all that lives in the */+ /* `FOND' which isn't in the file containing the `POST' resources so */+ /* we don't really have access to it. */+++ /* Finalizer for a memory stream; gets called by FT_Done_Face(). */+ /* It frees the memory it uses. */+ /* From ftmac.c. */+ static void+ memory_stream_close( FT_Stream stream )+ {+ FT_Memory memory = stream->memory;+++ FT_FREE( stream->base );++ stream->size = 0;+ stream->base = 0;+ stream->close = 0;+ }+++ /* Create a new memory stream from a buffer and a size. */+ /* From ftmac.c. */+ static FT_Error+ new_memory_stream( FT_Library library,+ FT_Byte* base,+ FT_ULong size,+ FT_Stream_CloseFunc close,+ FT_Stream *astream )+ {+ FT_Error error;+ FT_Memory memory;+ FT_Stream stream;+++ if ( !library )+ return FT_Err_Invalid_Library_Handle;++ if ( !base )+ return FT_Err_Invalid_Argument;++ *astream = 0;+ memory = library->memory;+ if ( FT_NEW( stream ) )+ goto Exit;++ FT_Stream_OpenMemory( stream, base, size );++ stream->close = close;++ *astream = stream;++ Exit:+ return error;+ }+++ /* Create a new FT_Face given a buffer and a driver name. */+ /* from ftmac.c */+ FT_LOCAL_DEF( FT_Error )+ open_face_from_buffer( FT_Library library,+ FT_Byte* base,+ FT_ULong size,+ FT_Long face_index,+ const char* driver_name,+ FT_Face *aface )+ {+ FT_Open_Args args;+ FT_Error error;+ FT_Stream stream = NULL;+ FT_Memory memory = library->memory;+++ error = new_memory_stream( library,+ base,+ size,+ memory_stream_close,+ &stream );+ if ( error )+ {+ FT_FREE( base );+ return error;+ }++ args.flags = FT_OPEN_STREAM;+ args.stream = stream;+ if ( driver_name )+ {+ args.flags = args.flags | FT_OPEN_DRIVER;+ args.driver = FT_Get_Module( library, driver_name );+ }++#ifdef FT_MACINTOSH+ /* At this point, 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;+#endif++ error = FT_Open_Face( library, &args, face_index, aface );++ if ( error == FT_Err_Ok )+ (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;+ else+#ifdef FT_MACINTOSH+ FT_Stream_Free( stream, 0 );+#else+ {+ FT_Stream_Close( stream );+ FT_FREE( stream );+ }+#endif++ return error;+ }+++ /* Look up `TYP1' or `CID ' table from sfnt table directory. */+ /* `offset' and `length' must exclude the binary header in tables. */++ /* Type 1 and CID-keyed font drivers should recognize sfnt-wrapped */+ /* format too. Here, since we can't expect that the TrueType font */+ /* driver is loaded unconditially, we must parse the font by */+ /* ourselves. We are only interested in the name of the table and */+ /* the offset. */++ static FT_Error+ ft_lookup_PS_in_sfnt_stream( FT_Stream stream,+ FT_Long face_index,+ FT_ULong* offset,+ FT_ULong* length,+ FT_Bool* is_sfnt_cid )+ {+ FT_Error error;+ FT_UShort numTables;+ FT_Long pstable_index;+ FT_ULong tag;+ int i;+++ *offset = 0;+ *length = 0;+ *is_sfnt_cid = FALSE;++ /* TODO: support for sfnt-wrapped PS/CID in TTC format */++ /* version check for 'typ1' (should be ignored?) */+ if ( FT_READ_ULONG( tag ) )+ return error;+ if ( tag != TTAG_typ1 )+ return FT_Err_Unknown_File_Format;++ if ( FT_READ_USHORT( numTables ) )+ return error;+ if ( FT_STREAM_SKIP( 2 * 3 ) ) /* skip binary search header */+ return error;++ pstable_index = -1;+ *is_sfnt_cid = FALSE;++ for ( i = 0; i < numTables; i++ )+ {+ if ( FT_READ_ULONG( tag ) || FT_STREAM_SKIP( 4 ) ||+ FT_READ_ULONG( *offset ) || FT_READ_ULONG( *length ) )+ return error;++ if ( tag == TTAG_CID )+ {+ pstable_index++;+ *offset += 22;+ *length -= 22;+ *is_sfnt_cid = TRUE;+ if ( face_index < 0 )+ return FT_Err_Ok;+ }+ else if ( tag == TTAG_TYP1 )+ {+ pstable_index++;+ *offset += 24;+ *length -= 24;+ *is_sfnt_cid = FALSE;+ if ( face_index < 0 )+ return FT_Err_Ok;+ }+ if ( face_index >= 0 && pstable_index == face_index )+ return FT_Err_Ok;+ }+ return FT_Err_Table_Missing;+ }+++ FT_LOCAL_DEF( FT_Error )+ open_face_PS_from_sfnt_stream( FT_Library library,+ FT_Stream stream,+ FT_Long face_index,+ FT_Int num_params,+ FT_Parameter *params,+ FT_Face *aface )+ {+ FT_Error error;+ FT_Memory memory = library->memory;+ FT_ULong offset, length;+ FT_Long pos;+ FT_Bool is_sfnt_cid;+ FT_Byte* sfnt_ps;++ FT_UNUSED( num_params );+ FT_UNUSED( params );+++ pos = FT_Stream_Pos( stream );++ error = ft_lookup_PS_in_sfnt_stream( stream,+ face_index,+ &offset,+ &length,+ &is_sfnt_cid );+ if ( error )+ goto Exit;++ if ( FT_Stream_Seek( stream, pos + offset ) )+ goto Exit;++ if ( FT_ALLOC( sfnt_ps, (FT_Long)length ) )+ goto Exit;++ error = FT_Stream_Read( stream, (FT_Byte *)sfnt_ps, length );+ if ( error )+ goto Exit;++ error = open_face_from_buffer( library,+ sfnt_ps,+ length,+ face_index < 0 ? face_index : 0,+ is_sfnt_cid ? "cid" : "type1",+ aface );+ Exit:+ {+ FT_Error error1;+++ if ( error == FT_Err_Unknown_File_Format )+ {+ error1 = FT_Stream_Seek( stream, pos );+ if ( error1 )+ return error1;+ }++ return error;+ }+ }+++#if !defined( FT_MACINTOSH ) || defined( DARWIN_NO_CARBON )++ /* The resource header says we've got resource_cnt `POST' (type1) */+ /* resources in this file. They all need to be coalesced into */+ /* one lump which gets passed on to the type1 driver. */+ /* Here can be only one PostScript font in a file so face_index */+ /* must be 0 (or -1). */+ /* */+ static FT_Error+ Mac_Read_POST_Resource( FT_Library library,+ FT_Stream stream,+ FT_Long *offsets,+ FT_Long resource_cnt,+ FT_Long face_index,+ FT_Face *aface )+ {+ FT_Error error = FT_Err_Cannot_Open_Resource;+ FT_Memory memory = library->memory;+ FT_Byte* pfb_data;+ int i, type, flags;+ FT_Long len;+ FT_Long pfb_len, pfb_pos, pfb_lenpos;+ FT_Long rlen, temp;+++ if ( face_index == -1 )+ face_index = 0;+ if ( face_index != 0 )+ return error;++ /* Find the length of all the POST resources, concatenated. Assume */+ /* worst case (each resource in its own section). */+ pfb_len = 0;+ for ( i = 0; i < resource_cnt; ++i )+ {+ error = FT_Stream_Seek( stream, offsets[i] );+ if ( error )+ goto Exit;+ if ( FT_READ_LONG( temp ) )+ goto Exit;+ pfb_len += temp + 6;+ }++ if ( FT_ALLOC( pfb_data, (FT_Long)pfb_len + 2 ) )+ goto Exit;++ pfb_data[0] = 0x80;+ pfb_data[1] = 1; /* Ascii section */+ pfb_data[2] = 0; /* 4-byte length, fill in later */+ pfb_data[3] = 0;+ pfb_data[4] = 0;+ pfb_data[5] = 0;+ pfb_pos = 6;+ pfb_lenpos = 2;++ len = 0;+ type = 1;+ for ( i = 0; i < resource_cnt; ++i )+ {+ error = FT_Stream_Seek( stream, offsets[i] );+ if ( error )+ goto Exit2;+ if ( FT_READ_LONG( rlen ) )+ goto Exit;+ if ( FT_READ_USHORT( flags ) )+ goto Exit;+ FT_TRACE3(( "POST fragment[%d]: offsets=0x%08x, rlen=0x%08x, flags=0x%04x\n",+ i, offsets[i], rlen, flags ));++ /* postpone the check of rlen longer than buffer until FT_Stream_Read() */+ if ( ( flags >> 8 ) == 0 ) /* Comment, should not be loaded */+ continue;++ /* the flags are part of the resource, so rlen >= 2. */+ /* but some fonts declare rlen = 0 for empty fragment */+ if ( rlen > 2 )+ rlen -= 2;+ else+ rlen = 0;++ if ( ( flags >> 8 ) == type )+ len += rlen;+ else+ {+ if ( pfb_lenpos + 3 > pfb_len + 2 )+ goto Exit2;+ pfb_data[pfb_lenpos ] = (FT_Byte)( len );+ pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 );+ pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 );+ pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 );++ if ( ( flags >> 8 ) == 5 ) /* End of font mark */+ break;++ if ( pfb_pos + 6 > pfb_len + 2 )+ goto Exit2;+ pfb_data[pfb_pos++] = 0x80;++ type = flags >> 8;+ len = rlen;++ pfb_data[pfb_pos++] = (FT_Byte)type;+ pfb_lenpos = pfb_pos;+ pfb_data[pfb_pos++] = 0; /* 4-byte length, fill in later */+ pfb_data[pfb_pos++] = 0;+ pfb_data[pfb_pos++] = 0;+ pfb_data[pfb_pos++] = 0;+ }++ error = FT_Err_Cannot_Open_Resource;+ if ( pfb_pos > pfb_len || pfb_pos + rlen > pfb_len )+ goto Exit2;++ error = FT_Stream_Read( stream, (FT_Byte *)pfb_data + pfb_pos, rlen );+ if ( error )+ goto Exit2;+ pfb_pos += rlen;+ }++ if ( pfb_pos + 2 > pfb_len + 2 )+ goto Exit2;+ pfb_data[pfb_pos++] = 0x80;+ pfb_data[pfb_pos++] = 3;++ if ( pfb_lenpos + 3 > pfb_len + 2 )+ goto Exit2;+ pfb_data[pfb_lenpos ] = (FT_Byte)( len );+ pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 );+ pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 );+ pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 );++ return open_face_from_buffer( library,+ pfb_data,+ pfb_pos,+ face_index,+ "type1",+ aface );++ Exit2:+ FT_FREE( pfb_data );++ Exit:+ return error;+ }+++ /* 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. */+ /* */+ static FT_Error+ Mac_Read_sfnt_Resource( FT_Library library,+ FT_Stream stream,+ FT_Long *offsets,+ FT_Long resource_cnt,+ FT_Long face_index,+ FT_Face *aface )+ {+ FT_Memory memory = library->memory;+ FT_Byte* sfnt_data;+ FT_Error error;+ FT_Long flag_offset;+ FT_Long rlen;+ int is_cff;+ FT_Long face_index_in_resource = 0;+++ if ( face_index == -1 )+ face_index = 0;+ if ( face_index >= resource_cnt )+ return FT_Err_Cannot_Open_Resource;++ flag_offset = offsets[face_index];+ error = FT_Stream_Seek( stream, flag_offset );+ if ( error )+ goto Exit;++ if ( FT_READ_LONG( rlen ) )+ goto Exit;+ if ( rlen == -1 )+ return FT_Err_Cannot_Open_Resource;++ error = open_face_PS_from_sfnt_stream( library,+ stream,+ face_index,+ 0, NULL,+ aface );+ if ( !error )+ goto Exit;++ /* rewind sfnt stream before open_face_PS_from_sfnt_stream() */+ if ( FT_Stream_Seek( stream, flag_offset + 4 ) )+ goto Exit;++ if ( FT_ALLOC( sfnt_data, (FT_Long)rlen ) )+ return error;+ error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, rlen );+ if ( error )+ goto Exit;++ is_cff = rlen > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );+ error = open_face_from_buffer( library,+ sfnt_data,+ rlen,+ face_index_in_resource,+ is_cff ? "cff" : "truetype",+ aface );++ Exit:+ return error;+ }+++ /* Check for a valid resource fork header, or a valid dfont */+ /* header. In a resource fork the first 16 bytes are repeated */+ /* at the location specified by bytes 4-7. In a dfont bytes */+ /* 4-7 point to 16 bytes of zeroes instead. */+ /* */+ static FT_Error+ IsMacResource( FT_Library library,+ FT_Stream stream,+ FT_Long resource_offset,+ FT_Long face_index,+ FT_Face *aface )+ {+ FT_Memory memory = library->memory;+ FT_Error error;+ FT_Long map_offset, rdara_pos;+ FT_Long *data_offsets;+ FT_Long count;+++ error = FT_Raccess_Get_HeaderInfo( library, stream, resource_offset,+ &map_offset, &rdara_pos );+ if ( error )+ return error;++ error = FT_Raccess_Get_DataOffsets( library, stream,+ map_offset, rdara_pos,+ TTAG_POST,+ &data_offsets, &count );+ if ( !error )+ {+ error = Mac_Read_POST_Resource( library, stream, data_offsets, count,+ face_index, aface );+ FT_FREE( data_offsets );+ /* POST exists in an LWFN providing a single face */+ if ( !error )+ (*aface)->num_faces = 1;+ return error;+ }++ error = FT_Raccess_Get_DataOffsets( library, stream,+ map_offset, rdara_pos,+ TTAG_sfnt,+ &data_offsets, &count );+ if ( !error )+ {+ FT_Long face_index_internal = face_index % count;+++ error = Mac_Read_sfnt_Resource( library, stream, data_offsets, count,+ face_index_internal, aface );+ FT_FREE( data_offsets );+ if ( !error )+ (*aface)->num_faces = count;+ }++ return error;+ }+++ /* Check for a valid macbinary header, and if we find one */+ /* check that the (flattened) resource fork in it is valid. */+ /* */+ static FT_Error+ IsMacBinary( FT_Library library,+ FT_Stream stream,+ FT_Long face_index,+ FT_Face *aface )+ {+ unsigned char header[128];+ FT_Error error;+ FT_Long dlen, offset;+++ if ( NULL == stream )+ return FT_Err_Invalid_Stream_Operation;++ error = FT_Stream_Seek( stream, 0 );+ if ( error )+ goto Exit;++ error = FT_Stream_Read( stream, (FT_Byte*)header, 128 );+ 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 )+ return FT_Err_Unknown_File_Format;++ dlen = ( header[0x53] << 24 ) |+ ( header[0x54] << 16 ) |+ ( header[0x55] << 8 ) |+ header[0x56];+#if 0+ rlen = ( header[0x57] << 24 ) |+ ( header[0x58] << 16 ) |+ ( header[0x59] << 8 ) |+ header[0x5a];+#endif /* 0 */+ offset = 128 + ( ( dlen + 127 ) & ~127 );++ return IsMacResource( library, stream, offset, face_index, aface );++ Exit:+ return error;+ }+++ static FT_Error+ load_face_in_embedded_rfork( FT_Library library,+ FT_Stream stream,+ FT_Long face_index,+ FT_Face *aface,+ const FT_Open_Args *args )+ {++#undef FT_COMPONENT+#define FT_COMPONENT trace_raccess++ FT_Memory memory = library->memory;+ FT_Error error = FT_Err_Unknown_File_Format;+ int i;++ char * file_names[FT_RACCESS_N_RULES];+ FT_Long offsets[FT_RACCESS_N_RULES];+ FT_Error errors[FT_RACCESS_N_RULES];+ FT_Bool is_darwin_vfs, vfs_rfork_has_no_font = FALSE; /* not tested */++ FT_Open_Args args2;+ FT_Stream stream2 = 0;+++ FT_Raccess_Guess( library, stream,+ args->pathname, file_names, offsets, errors );++ for ( i = 0; i < FT_RACCESS_N_RULES; i++ )+ {+ is_darwin_vfs = raccess_rule_by_darwin_vfs( i );+ if ( is_darwin_vfs && vfs_rfork_has_no_font )+ {+ FT_TRACE3(( "Skip rule %d: darwin vfs resource fork"+ " is already checked and"+ " no font is found\n", i ));+ continue;+ } ++ if ( errors[i] )+ {+ FT_TRACE3(( "Error[%d] has occurred in rule %d\n", errors[i], i ));+ continue;+ }++ args2.flags = FT_OPEN_PATHNAME;+ args2.pathname = file_names[i] ? file_names[i] : args->pathname;++ FT_TRACE3(( "Try rule %d: %s (offset=%d) ...",+ i, args2.pathname, offsets[i] ));++ error = FT_Stream_New( library, &args2, &stream2 );+ if ( is_darwin_vfs && error == FT_Err_Cannot_Open_Stream )+ vfs_rfork_has_no_font = TRUE;++ if ( error )+ {+ FT_TRACE3(( "failed\n" ));+ continue;+ }++ error = IsMacResource( library, stream2, offsets[i],+ face_index, aface );+ FT_Stream_Free( stream2, 0 );++ FT_TRACE3(( "%s\n", error ? "failed": "successful" ));++ if ( !error )+ break;+ else if ( is_darwin_vfs )+ vfs_rfork_has_no_font = TRUE;+ }++ for (i = 0; i < FT_RACCESS_N_RULES; i++)+ {+ if ( file_names[i] )+ FT_FREE( file_names[i] );+ }++ /* Caller (load_mac_face) requires FT_Err_Unknown_File_Format. */+ if ( error )+ error = FT_Err_Unknown_File_Format;++ return error;++#undef FT_COMPONENT+#define FT_COMPONENT trace_objs++ }+++ /* Check for some macintosh formats without Carbon framework. */+ /* Is this a macbinary file? If so look at the resource fork. */+ /* Is this a mac dfont file? */+ /* Is this an old style resource fork? (in data) */+ /* Else call load_face_in_embedded_rfork to try extra rules */+ /* (defined in `ftrfork.c'). */+ /* */+ static FT_Error+ load_mac_face( FT_Library library,+ FT_Stream stream,+ FT_Long face_index,+ FT_Face *aface,+ const FT_Open_Args *args )+ {+ FT_Error error;+ FT_UNUSED( args );+++ error = IsMacBinary( library, stream, face_index, aface );+ if ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format )+ {++#undef FT_COMPONENT+#define FT_COMPONENT trace_raccess++ FT_TRACE3(( "Try as dfont: %s ...", args->pathname ));++ error = IsMacResource( library, stream, 0, face_index, aface );++ FT_TRACE3(( "%s\n", error ? "failed" : "successful" ));++#undef FT_COMPONENT+#define FT_COMPONENT trace_objs++ }++ if ( ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format ||+ FT_ERROR_BASE( error ) == FT_Err_Invalid_Stream_Operation ) &&+ ( args->flags & FT_OPEN_PATHNAME ) )+ error = load_face_in_embedded_rfork( library, stream,+ face_index, aface, args );+ return error;+ }+#endif++#endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Open_Face( FT_Library library,+ const FT_Open_Args* args,+ FT_Long face_index,+ FT_Face *aface )+ {+ FT_Error error;+ FT_Driver driver;+ FT_Memory memory;+ FT_Stream stream = NULL;+ FT_Face face = NULL;+ FT_ListNode node = NULL;+ FT_Bool external_stream;+ FT_Module* cur;+ FT_Module* limit;+++ /* test for valid `library' delayed to */+ /* FT_Stream_New() */++ if ( ( !aface && face_index >= 0 ) || !args )+ return FT_Err_Invalid_Argument;++ external_stream = FT_BOOL( ( args->flags & FT_OPEN_STREAM ) &&+ args->stream );++ /* create input stream */+ error = FT_Stream_New( library, args, &stream );+ if ( error )+ goto Fail3;++ memory = library->memory;++ /* If the font driver is specified in the `args' structure, use */+ /* it. Otherwise, we scan the list of registered drivers. */+ if ( ( args->flags & FT_OPEN_DRIVER ) && args->driver )+ {+ driver = FT_DRIVER( args->driver );++ /* not all modules are drivers, so check... */+ if ( FT_MODULE_IS_DRIVER( driver ) )+ {+ FT_Int num_params = 0;+ FT_Parameter* params = 0;+++ if ( args->flags & FT_OPEN_PARAMS )+ {+ num_params = args->num_params;+ params = args->params;+ }++ error = open_face( driver, stream, face_index,+ num_params, params, &face );+ if ( !error )+ goto Success;+ }+ else+ error = FT_Err_Invalid_Handle;++ FT_Stream_Free( stream, external_stream );+ goto Fail;+ }+ else+ {+ /* check each font driver for an appropriate format */+ cur = library->modules;+ limit = cur + library->num_modules;+++ for ( ; cur < limit; cur++ )+ {+ /* not all modules are font drivers, so check... */+ if ( FT_MODULE_IS_DRIVER( cur[0] ) )+ {+ FT_Int num_params = 0;+ FT_Parameter* params = 0;+++ driver = FT_DRIVER( cur[0] );++ if ( args->flags & FT_OPEN_PARAMS )+ {+ num_params = args->num_params;+ params = args->params;+ }++ error = open_face( driver, stream, face_index,+ num_params, params, &face );+ if ( !error )+ goto Success;++#ifdef FT_CONFIG_OPTION_MAC_FONTS+ if ( ft_strcmp( cur[0]->clazz->module_name, "truetype" ) == 0 &&+ FT_ERROR_BASE( error ) == FT_Err_Table_Missing )+ {+ /* TrueType but essential tables are missing */+ if ( FT_Stream_Seek( stream, 0 ) )+ break;++ error = open_face_PS_from_sfnt_stream( library,+ stream,+ face_index,+ num_params,+ params,+ aface );+ if ( !error )+ {+ FT_Stream_Free( stream, external_stream );+ return error;+ }+ }+#endif++ if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )+ goto Fail3;+ }+ }++ Fail3:+ /* If we are on the mac, and we get an FT_Err_Invalid_Stream_Operation */+ /* it may be because we have an empty data fork, so we need to check */+ /* the resource fork. */+ if ( FT_ERROR_BASE( error ) != FT_Err_Cannot_Open_Stream &&+ FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format &&+ FT_ERROR_BASE( error ) != FT_Err_Invalid_Stream_Operation )+ goto Fail2;++#if !defined( FT_MACINTOSH ) && defined( FT_CONFIG_OPTION_MAC_FONTS )+ error = load_mac_face( library, stream, face_index, aface, args );+ if ( !error )+ {+ /* We don't want to go to Success here. We've already done that. */+ /* On the other hand, if we succeeded we still need to close this */+ /* stream (we opened a different stream which extracted the */+ /* interesting information out of this stream here. That stream */+ /* will still be open and the face will point to it). */+ FT_Stream_Free( stream, external_stream );+ return error;+ }++ if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )+ goto Fail2;+#endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */++ /* no driver is able to handle this format */+ error = FT_Err_Unknown_File_Format;++ Fail2:+ FT_Stream_Free( stream, external_stream );+ goto Fail;+ }++ Success:+ FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" ));++ /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */+ if ( external_stream )+ face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;++ /* add the face object to its driver's list */+ if ( FT_NEW( node ) )+ goto Fail;++ node->data = face;+ /* don't assume driver is the same as face->driver, so use */+ /* face->driver instead. */+ FT_List_Add( &face->driver->faces_list, node );++ /* now allocate a glyph slot object for the face */+ FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" ));++ if ( face_index >= 0 )+ {+ error = FT_New_GlyphSlot( face, NULL );+ if ( error )+ goto Fail;++ /* finally, allocate a size object for the face */+ {+ FT_Size size;+++ FT_TRACE4(( "FT_Open_Face: Creating size object\n" ));++ error = FT_New_Size( face, &size );+ if ( error )+ goto Fail;++ face->size = size;+ }+ }++ /* some checks */++ if ( FT_IS_SCALABLE( face ) )+ {+ if ( face->height < 0 )+ face->height = (FT_Short)-face->height;++ if ( !FT_HAS_VERTICAL( face ) )+ face->max_advance_height = (FT_Short)face->height;+ }++ if ( FT_HAS_FIXED_SIZES( face ) )+ {+ FT_Int i;+++ for ( i = 0; i < face->num_fixed_sizes; i++ )+ {+ FT_Bitmap_Size* bsize = face->available_sizes + i;+++ if ( bsize->height < 0 )+ bsize->height = (FT_Short)-bsize->height;+ if ( bsize->x_ppem < 0 )+ bsize->x_ppem = (FT_Short)-bsize->x_ppem;+ if ( bsize->y_ppem < 0 )+ bsize->y_ppem = -bsize->y_ppem;+ }+ }++ /* initialize internal face data */+ {+ FT_Face_Internal internal = face->internal;+++ internal->transform_matrix.xx = 0x10000L;+ internal->transform_matrix.xy = 0;+ internal->transform_matrix.yx = 0;+ internal->transform_matrix.yy = 0x10000L;++ internal->transform_delta.x = 0;+ internal->transform_delta.y = 0;++ internal->refcount = 1;+ }++ if ( aface )+ *aface = face;+ else+ FT_Done_Face( face );++ goto Exit;++ Fail:+ FT_Done_Face( face );++ Exit:+ FT_TRACE4(( "FT_Open_Face: Return %d\n", error ));++ return error;+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Attach_File( FT_Face face,+ const char* filepathname )+ {+ FT_Open_Args open;+++ /* test for valid `face' delayed to FT_Attach_Stream() */++ if ( !filepathname )+ return FT_Err_Invalid_Argument;++ open.stream = NULL;+ open.flags = FT_OPEN_PATHNAME;+ open.pathname = (char*)filepathname;++ return FT_Attach_Stream( face, &open );+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Attach_Stream( FT_Face face,+ FT_Open_Args* parameters )+ {+ FT_Stream stream;+ FT_Error error;+ FT_Driver driver;++ FT_Driver_Class clazz;+++ /* test for valid `parameters' delayed to FT_Stream_New() */++ if ( !face )+ return FT_Err_Invalid_Face_Handle;++ driver = face->driver;+ if ( !driver )+ return FT_Err_Invalid_Driver_Handle;++ error = FT_Stream_New( driver->root.library, parameters, &stream );+ if ( error )+ goto Exit;++ /* we implement FT_Attach_Stream in each driver through the */+ /* `attach_file' interface */++ error = FT_Err_Unimplemented_Feature;+ clazz = driver->clazz;+ if ( clazz->attach_file )+ error = clazz->attach_file( face, stream );++ /* close the attached stream */+ FT_Stream_Free( stream,+ (FT_Bool)( parameters->stream &&+ ( parameters->flags & FT_OPEN_STREAM ) ) );++ Exit:+ return error;+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Reference_Face( FT_Face face )+ {+ face->internal->refcount++;++ return FT_Err_Ok;+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Done_Face( FT_Face face )+ {+ FT_Error error;+ FT_Driver driver;+ FT_Memory memory;+ FT_ListNode node;+++ error = FT_Err_Invalid_Face_Handle;+ if ( face && face->driver )+ {+ face->internal->refcount--;+ if ( face->internal->refcount > 0 )+ error = FT_Err_Ok;+ else+ {+ driver = face->driver;+ memory = driver->root.memory;++ /* find face in driver's list */+ node = FT_List_Find( &driver->faces_list, face );+ if ( node )+ {+ /* remove face object from the driver's list */+ FT_List_Remove( &driver->faces_list, node );+ FT_FREE( node );++ /* now destroy the object proper */+ destroy_face( memory, face, driver );+ error = FT_Err_Ok;+ }+ }+ }++ return error;+ }+++ /* documentation is in ftobjs.h */++ FT_EXPORT_DEF( FT_Error )+ FT_New_Size( FT_Face face,+ FT_Size *asize )+ {+ FT_Error error;+ FT_Memory memory;+ FT_Driver driver;+ FT_Driver_Class clazz;++ FT_Size size = 0;+ FT_ListNode node = 0;+++ if ( !face )+ return FT_Err_Invalid_Face_Handle;++ if ( !asize )+ return FT_Err_Invalid_Size_Handle;++ if ( !face->driver )+ return FT_Err_Invalid_Driver_Handle;++ *asize = 0;++ driver = face->driver;+ clazz = driver->clazz;+ memory = face->memory;++ /* Allocate new size object and perform basic initialisation */+ if ( FT_ALLOC( size, clazz->size_object_size ) || FT_NEW( node ) )+ goto Exit;++ size->face = face;++ /* for now, do not use any internal fields in size objects */+ size->internal = 0;++ if ( clazz->init_size )+ error = clazz->init_size( size );++ /* in case of success, add to the face's list */+ if ( !error )+ {+ *asize = size;+ node->data = size;+ FT_List_Add( &face->sizes_list, node );+ }++ Exit:+ if ( error )+ {+ FT_FREE( node );+ FT_FREE( size );+ }++ return error;+ }+++ /* documentation is in ftobjs.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Done_Size( FT_Size size )+ {+ FT_Error error;+ FT_Driver driver;+ FT_Memory memory;+ FT_Face face;+ FT_ListNode node;+++ if ( !size )+ return FT_Err_Invalid_Size_Handle;++ face = size->face;+ if ( !face )+ return FT_Err_Invalid_Face_Handle;++ driver = face->driver;+ if ( !driver )+ return FT_Err_Invalid_Driver_Handle;++ memory = driver->root.memory;++ error = FT_Err_Ok;+ node = FT_List_Find( &face->sizes_list, size );+ if ( node )+ {+ FT_List_Remove( &face->sizes_list, node );+ FT_FREE( node );++ if ( face->size == size )+ {+ face->size = 0;+ if ( face->sizes_list.head )+ face->size = (FT_Size)(face->sizes_list.head->data);+ }++ destroy_size( memory, size, driver );+ }+ else+ error = FT_Err_Invalid_Size_Handle;++ return error;+ }+++ /* documentation is in ftobjs.h */++ FT_BASE_DEF( FT_Error )+ FT_Match_Size( FT_Face face,+ FT_Size_Request req,+ FT_Bool ignore_width,+ FT_ULong* size_index )+ {+ FT_Int i;+ FT_Long w, h;+++ if ( !FT_HAS_FIXED_SIZES( face ) )+ return FT_Err_Invalid_Face_Handle;++ /* FT_Bitmap_Size doesn't provide enough info... */+ if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )+ return FT_Err_Unimplemented_Feature;++ w = FT_REQUEST_WIDTH ( req );+ h = FT_REQUEST_HEIGHT( req );++ if ( req->width && !req->height )+ h = w;+ else if ( !req->width && req->height )+ w = h;++ w = FT_PIX_ROUND( w );+ h = FT_PIX_ROUND( h );++ for ( i = 0; i < face->num_fixed_sizes; i++ )+ {+ FT_Bitmap_Size* bsize = face->available_sizes + i;+++ if ( h != FT_PIX_ROUND( bsize->y_ppem ) )+ continue;++ if ( w == FT_PIX_ROUND( bsize->x_ppem ) || ignore_width )+ {+ if ( size_index )+ *size_index = (FT_ULong)i;++ return FT_Err_Ok;+ }+ }++ return FT_Err_Invalid_Pixel_Size;+ }+++ /* documentation is in ftobjs.h */++ FT_BASE_DEF( void )+ ft_synthesize_vertical_metrics( FT_Glyph_Metrics* metrics,+ FT_Pos advance )+ {+ FT_Pos height = metrics->height;+++ /* compensate for glyph with bbox above/below the baseline */+ if ( metrics->horiBearingY < 0 )+ {+ if ( height < metrics->horiBearingY )+ height = metrics->horiBearingY;+ }+ else if ( metrics->horiBearingY > 0 )+ height -= metrics->horiBearingY;++ /* the factor 1.2 is a heuristical value */+ if ( !advance )+ advance = height * 12 / 10;++ metrics->vertBearingX = metrics->horiBearingX - metrics->horiAdvance / 2;+ metrics->vertBearingY = ( advance - height ) / 2;+ metrics->vertAdvance = advance;+ }+++ static void+ ft_recompute_scaled_metrics( FT_Face face,+ FT_Size_Metrics* metrics )+ {+ /* Compute root ascender, descender, test height, and max_advance */++#ifdef GRID_FIT_METRICS+ metrics->ascender = FT_PIX_CEIL( FT_MulFix( face->ascender,+ metrics->y_scale ) );++ metrics->descender = FT_PIX_FLOOR( FT_MulFix( face->descender,+ metrics->y_scale ) );++ metrics->height = FT_PIX_ROUND( FT_MulFix( face->height,+ metrics->y_scale ) );++ metrics->max_advance = FT_PIX_ROUND( FT_MulFix( face->max_advance_width,+ metrics->x_scale ) );+#else /* !GRID_FIT_METRICS */+ metrics->ascender = FT_MulFix( face->ascender,+ metrics->y_scale );++ metrics->descender = FT_MulFix( face->descender,+ metrics->y_scale );++ metrics->height = FT_MulFix( face->height,+ metrics->y_scale );++ metrics->max_advance = FT_MulFix( face->max_advance_width,+ metrics->x_scale );+#endif /* !GRID_FIT_METRICS */+ }+++ FT_BASE_DEF( void )+ FT_Select_Metrics( FT_Face face,+ FT_ULong strike_index )+ {+ FT_Size_Metrics* metrics;+ FT_Bitmap_Size* bsize;+++ metrics = &face->size->metrics;+ bsize = face->available_sizes + strike_index;++ metrics->x_ppem = (FT_UShort)( ( bsize->x_ppem + 32 ) >> 6 );+ metrics->y_ppem = (FT_UShort)( ( bsize->y_ppem + 32 ) >> 6 );++ if ( FT_IS_SCALABLE( face ) )+ {+ metrics->x_scale = FT_DivFix( bsize->x_ppem,+ face->units_per_EM );+ metrics->y_scale = FT_DivFix( bsize->y_ppem,+ face->units_per_EM );++ ft_recompute_scaled_metrics( face, metrics );+ }+ else+ {+ metrics->x_scale = 1L << 16;+ metrics->y_scale = 1L << 16;+ metrics->ascender = bsize->y_ppem;+ metrics->descender = 0;+ metrics->height = bsize->height << 6;+ metrics->max_advance = bsize->x_ppem;+ }+ }+++ FT_BASE_DEF( void )+ FT_Request_Metrics( FT_Face face,+ FT_Size_Request req )+ {+ FT_Size_Metrics* metrics;+++ metrics = &face->size->metrics;++ if ( FT_IS_SCALABLE( face ) )+ {+ FT_Long w = 0, h = 0, scaled_w = 0, scaled_h = 0;+++ switch ( req->type )+ {+ case FT_SIZE_REQUEST_TYPE_NOMINAL:+ w = h = face->units_per_EM;+ break;++ case FT_SIZE_REQUEST_TYPE_REAL_DIM:+ w = h = face->ascender - face->descender;+ break;++ case FT_SIZE_REQUEST_TYPE_BBOX:+ w = face->bbox.xMax - face->bbox.xMin;+ h = face->bbox.yMax - face->bbox.yMin;+ break;++ case FT_SIZE_REQUEST_TYPE_CELL:+ w = face->max_advance_width;+ h = face->ascender - face->descender;+ break;++ case FT_SIZE_REQUEST_TYPE_SCALES:+ metrics->x_scale = (FT_Fixed)req->width;+ metrics->y_scale = (FT_Fixed)req->height;+ if ( !metrics->x_scale )+ metrics->x_scale = metrics->y_scale;+ else if ( !metrics->y_scale )+ metrics->y_scale = metrics->x_scale;+ goto Calculate_Ppem;++ case FT_SIZE_REQUEST_TYPE_MAX:+ break;+ }++ /* to be on the safe side */+ if ( w < 0 )+ w = -w;++ if ( h < 0 )+ h = -h;++ scaled_w = FT_REQUEST_WIDTH ( req );+ scaled_h = FT_REQUEST_HEIGHT( req );++ /* determine scales */+ if ( req->width )+ {+ metrics->x_scale = FT_DivFix( scaled_w, w );++ if ( req->height )+ {+ metrics->y_scale = FT_DivFix( scaled_h, h );++ if ( req->type == FT_SIZE_REQUEST_TYPE_CELL )+ {+ if ( metrics->y_scale > metrics->x_scale )+ metrics->y_scale = metrics->x_scale;+ else+ metrics->x_scale = metrics->y_scale;+ }+ }+ else+ {+ metrics->y_scale = metrics->x_scale;+ scaled_h = FT_MulDiv( scaled_w, h, w );+ }+ }+ else+ {+ metrics->x_scale = metrics->y_scale = FT_DivFix( scaled_h, h );+ scaled_w = FT_MulDiv( scaled_h, w, h );+ }++ Calculate_Ppem:+ /* calculate the ppems */+ if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )+ {+ scaled_w = FT_MulFix( face->units_per_EM, metrics->x_scale );+ scaled_h = FT_MulFix( face->units_per_EM, metrics->y_scale );+ }++ metrics->x_ppem = (FT_UShort)( ( scaled_w + 32 ) >> 6 );+ metrics->y_ppem = (FT_UShort)( ( scaled_h + 32 ) >> 6 );++ ft_recompute_scaled_metrics( face, metrics );+ }+ else+ {+ FT_ZERO( metrics );+ metrics->x_scale = 1L << 16;+ metrics->y_scale = 1L << 16;+ }+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Select_Size( FT_Face face,+ FT_Int strike_index )+ {+ FT_Driver_Class clazz;+++ if ( !face || !FT_HAS_FIXED_SIZES( face ) )+ return FT_Err_Invalid_Face_Handle;++ if ( strike_index < 0 || strike_index >= face->num_fixed_sizes )+ return FT_Err_Invalid_Argument;++ clazz = face->driver->clazz;++ if ( clazz->select_size )+ return clazz->select_size( face->size, (FT_ULong)strike_index );++ FT_Select_Metrics( face, (FT_ULong)strike_index );++ return FT_Err_Ok;+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Request_Size( FT_Face face,+ FT_Size_Request req )+ {+ FT_Driver_Class clazz;+ FT_ULong strike_index;+++ if ( !face )+ return FT_Err_Invalid_Face_Handle;++ if ( !req || req->width < 0 || req->height < 0 ||+ req->type >= FT_SIZE_REQUEST_TYPE_MAX )+ return FT_Err_Invalid_Argument;++ clazz = face->driver->clazz;++ if ( clazz->request_size )+ return clazz->request_size( face->size, req );++ /*+ * The reason that a driver doesn't have `request_size' defined is+ * either that the scaling here suffices or that the supported formats+ * are bitmap-only and size matching is not implemented.+ *+ * In the latter case, a simple size matching is done.+ */+ if ( !FT_IS_SCALABLE( face ) && FT_HAS_FIXED_SIZES( face ) )+ {+ FT_Error error;+++ error = FT_Match_Size( face, req, 0, &strike_index );+ if ( error )+ return error;++ FT_TRACE3(( "FT_Request_Size: bitmap strike %lu matched\n",+ strike_index ));++ return FT_Select_Size( face, (FT_Int)strike_index );+ }++ FT_Request_Metrics( face, req );++ return FT_Err_Ok;+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Set_Char_Size( FT_Face face,+ FT_F26Dot6 char_width,+ FT_F26Dot6 char_height,+ FT_UInt horz_resolution,+ FT_UInt vert_resolution )+ {+ FT_Size_RequestRec req;+++ if ( !char_width )+ char_width = char_height;+ else if ( !char_height )+ char_height = char_width;++ if ( !horz_resolution )+ horz_resolution = vert_resolution;+ else if ( !vert_resolution )+ vert_resolution = horz_resolution;++ if ( char_width < 1 * 64 )+ char_width = 1 * 64;+ if ( char_height < 1 * 64 )+ char_height = 1 * 64;++ if ( !horz_resolution )+ horz_resolution = vert_resolution = 72;++ req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;+ req.width = char_width;+ req.height = char_height;+ req.horiResolution = horz_resolution;+ req.vertResolution = vert_resolution;++ return FT_Request_Size( face, &req );+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Set_Pixel_Sizes( FT_Face face,+ FT_UInt pixel_width,+ FT_UInt pixel_height )+ {+ FT_Size_RequestRec req;+++ if ( pixel_width == 0 )+ pixel_width = pixel_height;+ else if ( pixel_height == 0 )+ pixel_height = pixel_width;++ if ( pixel_width < 1 )+ pixel_width = 1;+ if ( pixel_height < 1 )+ pixel_height = 1;++ /* use `>=' to avoid potential compiler warning on 16bit platforms */+ if ( pixel_width >= 0xFFFFU )+ pixel_width = 0xFFFFU;+ if ( pixel_height >= 0xFFFFU )+ pixel_height = 0xFFFFU;++ req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;+ req.width = pixel_width << 6;+ req.height = pixel_height << 6;+ req.horiResolution = 0;+ req.vertResolution = 0;++ return FT_Request_Size( face, &req );+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Get_Kerning( FT_Face face,+ FT_UInt left_glyph,+ FT_UInt right_glyph,+ FT_UInt kern_mode,+ FT_Vector *akerning )+ {+ FT_Error error = FT_Err_Ok;+ FT_Driver driver;+++ if ( !face )+ return FT_Err_Invalid_Face_Handle;++ if ( !akerning )+ return FT_Err_Invalid_Argument;++ driver = face->driver;++ akerning->x = 0;+ akerning->y = 0;++ if ( driver->clazz->get_kerning )+ {+ error = driver->clazz->get_kerning( face,+ left_glyph,+ right_glyph,+ akerning );+ if ( !error )+ {+ if ( kern_mode != FT_KERNING_UNSCALED )+ {+ akerning->x = FT_MulFix( akerning->x, face->size->metrics.x_scale );+ akerning->y = FT_MulFix( akerning->y, face->size->metrics.y_scale );++ if ( kern_mode != FT_KERNING_UNFITTED )+ {+ /* 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,+ face->size->metrics.x_ppem, 25 );+ if ( face->size->metrics.y_ppem < 25 )+ akerning->y = FT_MulDiv( akerning->y,+ face->size->metrics.y_ppem, 25 );++ akerning->x = FT_PIX_ROUND( akerning->x );+ akerning->y = FT_PIX_ROUND( akerning->y );+ }+ }+ }+ }++ return error;+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Get_Track_Kerning( FT_Face face,+ FT_Fixed point_size,+ FT_Int degree,+ FT_Fixed* akerning )+ {+ FT_Service_Kerning service;+ FT_Error error = FT_Err_Ok;+++ if ( !face )+ return FT_Err_Invalid_Face_Handle;++ if ( !akerning )+ return FT_Err_Invalid_Argument;++ FT_FACE_FIND_SERVICE( face, service, KERNING );+ if ( !service )+ return FT_Err_Unimplemented_Feature;++ error = service->get_track( face,+ point_size,+ degree,+ akerning );++ return error;+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Select_Charmap( FT_Face face,+ FT_Encoding encoding )+ {+ FT_CharMap* cur;+ FT_CharMap* limit;+++ if ( !face )+ return FT_Err_Invalid_Face_Handle;++ if ( encoding == FT_ENCODING_NONE )+ return FT_Err_Invalid_Argument;++ /* FT_ENCODING_UNICODE is special. We try to find the `best' Unicode */+ /* charmap available, i.e., one with UCS-4 characters, if possible. */+ /* */+ /* This is done by find_unicode_charmap() above, to share code. */+ if ( encoding == FT_ENCODING_UNICODE )+ return find_unicode_charmap( face );++ cur = face->charmaps;+ if ( !cur )+ return FT_Err_Invalid_CharMap_Handle;++ limit = cur + face->num_charmaps;++ for ( ; cur < limit; cur++ )+ {+ if ( cur[0]->encoding == encoding )+ {+#ifdef FT_MAX_CHARMAP_CACHEABLE+ if ( cur - face->charmaps > FT_MAX_CHARMAP_CACHEABLE )+ {+ FT_ERROR(( "FT_Select_Charmap: requested charmap is found (%d), "+ "but in too late position to cache\n",+ cur - face->charmaps ));+ continue;+ }+#endif+ face->charmap = cur[0];+ return 0;+ }+ }++ return FT_Err_Invalid_Argument;+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Set_Charmap( FT_Face face,+ FT_CharMap charmap )+ {+ FT_CharMap* cur;+ FT_CharMap* limit;+++ if ( !face )+ return FT_Err_Invalid_Face_Handle;++ cur = face->charmaps;+ if ( !cur )+ return FT_Err_Invalid_CharMap_Handle;+ if ( FT_Get_CMap_Format( charmap ) == 14 )+ return FT_Err_Invalid_Argument;++ limit = cur + face->num_charmaps;++ for ( ; cur < limit; cur++ )+ {+ if ( cur[0] == charmap )+ {+#ifdef FT_MAX_CHARMAP_CACHEABLE+ if ( cur - face->charmaps > FT_MAX_CHARMAP_CACHEABLE )+ {+ FT_ERROR(( "FT_Set_Charmap: requested charmap is found (%d), "+ "but in too late position to cache\n",+ cur - face->charmaps ));+ continue;+ }+#endif+ face->charmap = cur[0];+ return 0;+ }+ }+ return FT_Err_Invalid_Argument;+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Int )+ FT_Get_Charmap_Index( FT_CharMap charmap )+ {+ FT_Int i;+++ if ( !charmap || !charmap->face )+ return -1;++ for ( i = 0; i < charmap->face->num_charmaps; i++ )+ if ( charmap->face->charmaps[i] == charmap )+ break;++ FT_ASSERT( i < charmap->face->num_charmaps );++#ifdef FT_MAX_CHARMAP_CACHEABLE+ if ( i > FT_MAX_CHARMAP_CACHEABLE )+ {+ FT_ERROR(( "FT_Get_Charmap_Index: requested charmap is found (%d), "+ "but in too late position to cache\n",+ i ));+ return -i;+ }+#endif+ return i;+ }+++ static void+ ft_cmap_done_internal( FT_CMap cmap )+ {+ FT_CMap_Class clazz = cmap->clazz;+ FT_Face face = cmap->charmap.face;+ FT_Memory memory = FT_FACE_MEMORY(face);+++ if ( clazz->done )+ clazz->done( cmap );++ FT_FREE( cmap );+ }+++ FT_BASE_DEF( void )+ FT_CMap_Done( FT_CMap cmap )+ {+ if ( cmap )+ {+ FT_Face face = cmap->charmap.face;+ FT_Memory memory = FT_FACE_MEMORY( face );+ FT_Error error;+ FT_Int i, j;+++ for ( i = 0; i < face->num_charmaps; i++ )+ {+ if ( (FT_CMap)face->charmaps[i] == cmap )+ {+ FT_CharMap last_charmap = face->charmaps[face->num_charmaps - 1];+++ if ( FT_RENEW_ARRAY( face->charmaps,+ face->num_charmaps,+ face->num_charmaps - 1 ) )+ return;++ /* remove it from our list of charmaps */+ for ( j = i + 1; j < face->num_charmaps; j++ )+ {+ if ( j == face->num_charmaps - 1 )+ face->charmaps[j - 1] = last_charmap;+ else+ face->charmaps[j - 1] = face->charmaps[j];+ }++ face->num_charmaps--;++ if ( (FT_CMap)face->charmap == cmap )+ face->charmap = NULL;++ ft_cmap_done_internal( cmap );++ break;+ }+ }+ }+ }+++ FT_BASE_DEF( FT_Error )+ FT_CMap_New( FT_CMap_Class clazz,+ FT_Pointer init_data,+ FT_CharMap charmap,+ FT_CMap *acmap )+ {+ FT_Error error = FT_Err_Ok;+ FT_Face face;+ FT_Memory memory;+ FT_CMap cmap;+++ if ( clazz == NULL || charmap == NULL || charmap->face == NULL )+ return FT_Err_Invalid_Argument;++ face = charmap->face;+ memory = FT_FACE_MEMORY( face );++ if ( !FT_ALLOC( cmap, clazz->size ) )+ {+ cmap->charmap = *charmap;+ cmap->clazz = clazz;++ if ( clazz->init )+ {+ error = clazz->init( cmap, init_data );+ if ( error )+ goto Fail;+ }++ /* add it to our list of charmaps */+ if ( FT_RENEW_ARRAY( face->charmaps,+ face->num_charmaps,+ face->num_charmaps + 1 ) )+ goto Fail;++ face->charmaps[face->num_charmaps++] = (FT_CharMap)cmap;+ }++ Exit:+ if ( acmap )+ *acmap = cmap;++ return error;++ Fail:+ ft_cmap_done_internal( cmap );+ cmap = NULL;+ goto Exit;+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_UInt )+ FT_Get_Char_Index( FT_Face face,+ FT_ULong charcode )+ {+ FT_UInt result = 0;+++ if ( face && face->charmap )+ {+ FT_CMap cmap = FT_CMAP( face->charmap );+++ if ( charcode > 0xFFFFFFFFUL )+ {+ 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 );+ }+ return result;+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_ULong )+ FT_Get_First_Char( FT_Face face,+ FT_UInt *agindex )+ {+ FT_ULong result = 0;+ FT_UInt gindex = 0;+++ if ( face && face->charmap && face->num_glyphs )+ {+ gindex = FT_Get_Char_Index( face, 0 );+ if ( gindex == 0 || gindex >= (FT_UInt)face->num_glyphs )+ result = FT_Get_Next_Char( face, 0, &gindex );+ }++ if ( agindex )+ *agindex = gindex;++ return result;+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_ULong )+ FT_Get_Next_Char( FT_Face face,+ FT_ULong charcode,+ FT_UInt *agindex )+ {+ FT_ULong result = 0;+ FT_UInt gindex = 0;+++ if ( face && face->charmap && face->num_glyphs )+ {+ FT_UInt32 code = (FT_UInt32)charcode;+ FT_CMap cmap = FT_CMAP( face->charmap );+++ do {+ gindex = cmap->clazz->char_next( cmap, &code );+ } while ( gindex >= (FT_UInt)face->num_glyphs );++ result = ( gindex == 0 ) ? 0 : code;+ }++ if ( agindex )+ *agindex = gindex;++ return result;+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_UInt )+ FT_Face_GetCharVariantIndex( FT_Face face,+ FT_ULong charcode,+ FT_ULong variantSelector )+ {+ FT_UInt result = 0;+++ if ( face && face->charmap &&+ face->charmap->encoding == FT_ENCODING_UNICODE )+ {+ FT_CharMap charmap = find_variant_selector_charmap( face );+ FT_CMap ucmap = FT_CMAP( face->charmap );+++ if ( charmap != NULL )+ {+ FT_CMap vcmap = FT_CMAP( charmap );+++ if ( charcode > 0xFFFFFFFFUL )+ {+ FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));+ FT_TRACE1(( " 0x%x is truncated\n", charcode ));+ }+ if ( variantSelector > 0xFFFFFFFFUL )+ {+ FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" ));+ FT_TRACE1(( " 0x%x is truncated\n", variantSelector ));+ }++ result = vcmap->clazz->char_var_index( vcmap, ucmap,+ (FT_UInt32)charcode,+ (FT_UInt32)variantSelector );+ }+ }++ return result;+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Int )+ FT_Face_GetCharVariantIsDefault( FT_Face face,+ FT_ULong charcode,+ FT_ULong variantSelector )+ {+ FT_Int result = -1;+++ if ( face )+ {+ FT_CharMap charmap = find_variant_selector_charmap( face );+++ if ( charmap != NULL )+ {+ FT_CMap vcmap = FT_CMAP( charmap );+++ if ( charcode > 0xFFFFFFFFUL )+ {+ FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));+ FT_TRACE1(( " 0x%x is truncated\n", charcode ));+ }+ if ( variantSelector > 0xFFFFFFFFUL )+ {+ FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" ));+ FT_TRACE1(( " 0x%x is truncated\n", variantSelector ));+ }++ result = vcmap->clazz->char_var_default( vcmap,+ (FT_UInt32)charcode,+ (FT_UInt32)variantSelector );+ }+ }++ return result;+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_UInt32* )+ FT_Face_GetVariantSelectors( FT_Face face )+ {+ FT_UInt32 *result = NULL;+++ if ( face )+ {+ FT_CharMap charmap = find_variant_selector_charmap( face );+++ if ( charmap != NULL )+ {+ FT_CMap vcmap = FT_CMAP( charmap );+ FT_Memory memory = FT_FACE_MEMORY( face );+++ result = vcmap->clazz->variant_list( vcmap, memory );+ }+ }++ return result;+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_UInt32* )+ FT_Face_GetVariantsOfChar( FT_Face face,+ FT_ULong charcode )+ {+ FT_UInt32 *result = NULL;+++ if ( face )+ {+ FT_CharMap charmap = find_variant_selector_charmap( face );+++ if ( charmap != NULL )+ {+ FT_CMap vcmap = FT_CMAP( charmap );+ FT_Memory memory = FT_FACE_MEMORY( face );+++ if ( charcode > 0xFFFFFFFFUL )+ {+ FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));+ FT_TRACE1(( " 0x%x is truncated\n", charcode ));+ }++ result = vcmap->clazz->charvariant_list( vcmap, memory,+ (FT_UInt32)charcode );+ }+ }+ return result;+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_UInt32* )+ FT_Face_GetCharsOfVariant( FT_Face face,+ FT_ULong variantSelector )+ {+ FT_UInt32 *result = NULL;+++ if ( face )+ {+ FT_CharMap charmap = find_variant_selector_charmap( face );+++ if ( charmap != NULL )+ {+ FT_CMap vcmap = FT_CMAP( charmap );+ FT_Memory memory = FT_FACE_MEMORY( face );+++ if ( variantSelector > 0xFFFFFFFFUL )+ {+ FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" ));+ FT_TRACE1(( " 0x%x is truncated\n", variantSelector ));+ }++ result = vcmap->clazz->variantchar_list( vcmap, memory,+ (FT_UInt32)variantSelector );+ }+ }++ return result;+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_UInt )+ FT_Get_Name_Index( FT_Face face,+ FT_String* glyph_name )+ {+ FT_UInt result = 0;+++ if ( face && FT_HAS_GLYPH_NAMES( face ) )+ {+ FT_Service_GlyphDict service;+++ FT_FACE_LOOKUP_SERVICE( face,+ service,+ GLYPH_DICT );++ if ( service && service->name_index )+ result = service->name_index( face, glyph_name );+ }++ return result;+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Get_Glyph_Name( FT_Face face,+ FT_UInt glyph_index,+ FT_Pointer buffer,+ FT_UInt buffer_max )+ {+ FT_Error error = FT_Err_Invalid_Argument;+++ /* clean up buffer */+ if ( buffer && buffer_max > 0 )+ ((FT_Byte*)buffer)[0] = 0;++ if ( face &&+ (FT_Long)glyph_index <= face->num_glyphs &&+ FT_HAS_GLYPH_NAMES( face ) )+ {+ FT_Service_GlyphDict service;+++ FT_FACE_LOOKUP_SERVICE( face,+ service,+ GLYPH_DICT );++ if ( service && service->get_name )+ error = service->get_name( face, glyph_index, buffer, buffer_max );+ }++ return error;+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( const char* )+ FT_Get_Postscript_Name( FT_Face face )+ {+ const char* result = NULL;+++ if ( !face )+ goto Exit;++ if ( !result )+ {+ FT_Service_PsFontName service;+++ FT_FACE_LOOKUP_SERVICE( face,+ service,+ POSTSCRIPT_FONT_NAME );++ if ( service && service->get_ps_font_name )+ result = service->get_ps_font_name( face );+ }++ Exit:+ return result;+ }+++ /* documentation is in tttables.h */++ FT_EXPORT_DEF( void* )+ FT_Get_Sfnt_Table( FT_Face face,+ FT_Sfnt_Tag tag )+ {+ void* table = 0;+ FT_Service_SFNT_Table service;+++ if ( face && FT_IS_SFNT( face ) )+ {+ FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );+ if ( service != NULL )+ table = service->get_table( face, tag );+ }++ return table;+ }+++ /* documentation is in tttables.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Load_Sfnt_Table( FT_Face face,+ FT_ULong tag,+ FT_Long offset,+ FT_Byte* buffer,+ FT_ULong* length )+ {+ FT_Service_SFNT_Table service;+++ if ( !face || !FT_IS_SFNT( face ) )+ return FT_Err_Invalid_Face_Handle;++ FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );+ if ( service == NULL )+ return FT_Err_Unimplemented_Feature;++ return service->load_table( face, tag, offset, buffer, length );+ }+++ /* documentation is in tttables.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Sfnt_Table_Info( FT_Face face,+ FT_UInt table_index,+ FT_ULong *tag,+ FT_ULong *length )+ {+ FT_Service_SFNT_Table service;+ FT_ULong offset;+++ if ( !face || !FT_IS_SFNT( face ) )+ return FT_Err_Invalid_Face_Handle;++ FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );+ if ( service == NULL )+ return FT_Err_Unimplemented_Feature;++ return service->table_info( face, table_index, tag, &offset, length );+ }+++ /* documentation is in tttables.h */++ FT_EXPORT_DEF( FT_ULong )+ FT_Get_CMap_Language_ID( FT_CharMap charmap )+ {+ FT_Service_TTCMaps service;+ FT_Face face;+ TT_CMapInfo cmap_info;+++ if ( !charmap || !charmap->face )+ return 0;++ face = charmap->face;+ FT_FACE_FIND_SERVICE( face, service, TT_CMAP );+ if ( service == NULL )+ return 0;+ if ( service->get_cmap_info( charmap, &cmap_info ))+ return 0;++ return cmap_info.language;+ }+++ /* documentation is in tttables.h */++ FT_EXPORT_DEF( FT_Long )+ FT_Get_CMap_Format( FT_CharMap charmap )+ {+ FT_Service_TTCMaps service;+ FT_Face face;+ TT_CMapInfo cmap_info;+++ if ( !charmap || !charmap->face )+ return -1;++ face = charmap->face;+ FT_FACE_FIND_SERVICE( face, service, TT_CMAP );+ if ( service == NULL )+ return -1;+ if ( service->get_cmap_info( charmap, &cmap_info ))+ return -1;++ return cmap_info.format;+ }+++ /* documentation is in ftsizes.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Activate_Size( FT_Size size )+ {+ FT_Face face;+++ if ( size == NULL )+ return FT_Err_Invalid_Argument;++ face = size->face;+ if ( face == NULL || face->driver == NULL )+ return FT_Err_Invalid_Argument;++ /* we don't need anything more complex than that; all size objects */+ /* are already listed by the face */+ face->size = size;++ return FT_Err_Ok;+ }+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** ****/+ /**** R E N D E R E R S ****/+ /**** ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/++ /* lookup a renderer by glyph format in the library's list */+ FT_BASE_DEF( FT_Renderer )+ FT_Lookup_Renderer( FT_Library library,+ FT_Glyph_Format format,+ FT_ListNode* node )+ {+ FT_ListNode cur;+ FT_Renderer result = 0;+++ if ( !library )+ goto Exit;++ cur = library->renderers.head;++ if ( node )+ {+ if ( *node )+ cur = (*node)->next;+ *node = 0;+ }++ while ( cur )+ {+ FT_Renderer renderer = FT_RENDERER( cur->data );+++ if ( renderer->glyph_format == format )+ {+ if ( node )+ *node = cur;++ result = renderer;+ break;+ }+ cur = cur->next;+ }++ Exit:+ return result;+ }+++ static FT_Renderer+ ft_lookup_glyph_renderer( FT_GlyphSlot slot )+ {+ FT_Face face = slot->face;+ FT_Library library = FT_FACE_LIBRARY( face );+ FT_Renderer result = library->cur_renderer;+++ if ( !result || result->glyph_format != slot->format )+ result = FT_Lookup_Renderer( library, slot->format, 0 );++ return result;+ }+++ static void+ ft_set_current_renderer( FT_Library library )+ {+ FT_Renderer renderer;+++ renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, 0 );+ library->cur_renderer = renderer;+ }+++ static FT_Error+ ft_add_renderer( FT_Module module )+ {+ FT_Library library = module->library;+ FT_Memory memory = library->memory;+ FT_Error error;+ FT_ListNode node = NULL;+++ if ( FT_NEW( node ) )+ goto Exit;++ {+ FT_Renderer render = FT_RENDERER( module );+ FT_Renderer_Class* clazz = (FT_Renderer_Class*)module->clazz;+++ render->clazz = clazz;+ render->glyph_format = clazz->glyph_format;++ /* allocate raster object if needed */+ if ( clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&+ clazz->raster_class->raster_new )+ {+ error = clazz->raster_class->raster_new( memory, &render->raster );+ if ( error )+ goto Fail;++ render->raster_render = clazz->raster_class->raster_render;+ render->render = clazz->render_glyph;+ }++ /* add to list */+ node->data = module;+ FT_List_Add( &library->renderers, node );++ ft_set_current_renderer( library );+ }++ Fail:+ if ( error )+ FT_FREE( node );++ Exit:+ return error;+ }+++ static void+ ft_remove_renderer( FT_Module module )+ {+ FT_Library library = module->library;+ FT_Memory memory = library->memory;+ FT_ListNode node;+++ node = FT_List_Find( &library->renderers, module );+ if ( node )+ {+ FT_Renderer render = FT_RENDERER( module );+++ /* release raster object, if any */+ if ( render->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&+ render->raster )+ render->clazz->raster_class->raster_done( render->raster );++ /* remove from list */+ FT_List_Remove( &library->renderers, node );+ FT_FREE( node );++ ft_set_current_renderer( library );+ }+ }+++ /* documentation is in ftrender.h */++ FT_EXPORT_DEF( FT_Renderer )+ FT_Get_Renderer( FT_Library library,+ FT_Glyph_Format format )+ {+ /* test for valid `library' delayed to FT_Lookup_Renderer() */++ return FT_Lookup_Renderer( library, format, 0 );+ }+++ /* documentation is in ftrender.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Set_Renderer( FT_Library library,+ FT_Renderer renderer,+ FT_UInt num_params,+ FT_Parameter* parameters )+ {+ FT_ListNode node;+ FT_Error error = FT_Err_Ok;+++ if ( !library )+ return FT_Err_Invalid_Library_Handle;++ if ( !renderer )+ return FT_Err_Invalid_Argument;++ node = FT_List_Find( &library->renderers, renderer );+ if ( !node )+ {+ error = FT_Err_Invalid_Argument;+ goto Exit;+ }++ FT_List_Up( &library->renderers, node );++ if ( renderer->glyph_format == FT_GLYPH_FORMAT_OUTLINE )+ library->cur_renderer = renderer;++ if ( num_params > 0 )+ {+ FT_Renderer_SetModeFunc set_mode = renderer->clazz->set_mode;+++ for ( ; num_params > 0; num_params-- )+ {+ error = set_mode( renderer, parameters->tag, parameters->data );+ if ( error )+ break;+ }+ }++ Exit:+ return error;+ }+++ FT_BASE_DEF( FT_Error )+ FT_Render_Glyph_Internal( FT_Library library,+ FT_GlyphSlot slot,+ FT_Render_Mode render_mode )+ {+ FT_Error error = FT_Err_Ok;+ FT_Renderer renderer;+++ /* if it is already a bitmap, no need to do anything */+ switch ( slot->format )+ {+ case FT_GLYPH_FORMAT_BITMAP: /* already a bitmap, don't do anything */+ break;++ default:+ {+ FT_ListNode node = 0;+ FT_Bool update = 0;+++ /* small shortcut for the very common case */+ if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )+ {+ renderer = library->cur_renderer;+ node = library->renderers.head;+ }+ else+ renderer = FT_Lookup_Renderer( library, slot->format, &node );++ error = FT_Err_Unimplemented_Feature;+ while ( renderer )+ {+ error = renderer->render( renderer, slot, render_mode, NULL );+ if ( !error ||+ FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )+ break;++ /* FT_Err_Cannot_Render_Glyph is returned if the render mode */+ /* is unsupported by the current renderer for this glyph image */+ /* format. */++ /* now, look for another renderer that supports the same */+ /* format. */+ renderer = FT_Lookup_Renderer( library, slot->format, &node );+ update = 1;+ }++ /* if we changed the current renderer for the glyph image format */+ /* we need to select it as the next current one */+ if ( !error && update && renderer )+ FT_Set_Renderer( library, renderer, 0, 0 );+ }+ }++ return error;+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Render_Glyph( FT_GlyphSlot slot,+ FT_Render_Mode render_mode )+ {+ FT_Library library;+++ if ( !slot || !slot->face )+ return FT_Err_Invalid_Argument;++ library = FT_FACE_LIBRARY( slot->face );++ return FT_Render_Glyph_Internal( library, slot, render_mode );+ }+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** ****/+ /**** M O D U L E S ****/+ /**** ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Destroy_Module */+ /* */+ /* <Description> */+ /* Destroys a given module object. For drivers, this also destroys */+ /* all child faces. */+ /* */+ /* <InOut> */+ /* module :: A handle to the target driver object. */+ /* */+ /* <Note> */+ /* The driver _must_ be LOCKED! */+ /* */+ static void+ Destroy_Module( FT_Module module )+ {+ FT_Memory memory = module->memory;+ FT_Module_Class* clazz = module->clazz;+ FT_Library library = module->library;+++ /* finalize client-data - before anything else */+ if ( module->generic.finalizer )+ module->generic.finalizer( module );++ if ( library && library->auto_hinter == module )+ library->auto_hinter = 0;++ /* if the module is a renderer */+ if ( FT_MODULE_IS_RENDERER( module ) )+ ft_remove_renderer( module );++ /* if the module is a font driver, add some steps */+ if ( FT_MODULE_IS_DRIVER( module ) )+ Destroy_Driver( FT_DRIVER( module ) );++ /* finalize the module object */+ if ( clazz->module_done )+ clazz->module_done( module );++ /* discard it */+ FT_FREE( module );+ }+++ /* documentation is in ftmodapi.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Add_Module( FT_Library library,+ const FT_Module_Class* clazz )+ {+ FT_Error error;+ FT_Memory memory;+ FT_Module module;+ FT_UInt nn;+++#define FREETYPE_VER_FIXED ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \+ FREETYPE_MINOR )++ if ( !library )+ return FT_Err_Invalid_Library_Handle;++ if ( !clazz )+ return FT_Err_Invalid_Argument;++ /* check freetype version */+ if ( clazz->module_requires > FREETYPE_VER_FIXED )+ return FT_Err_Invalid_Version;++ /* look for a module with the same name in the library's table */+ for ( nn = 0; nn < library->num_modules; nn++ )+ {+ module = library->modules[nn];+ if ( ft_strcmp( module->clazz->module_name, clazz->module_name ) == 0 )+ {+ /* this installed module has the same name, compare their versions */+ if ( clazz->module_version <= module->clazz->module_version )+ return FT_Err_Lower_Module_Version;++ /* remove the module from our list, then exit the loop to replace */+ /* it by our new version.. */+ FT_Remove_Module( library, module );+ break;+ }+ }++ memory = library->memory;+ error = FT_Err_Ok;++ if ( library->num_modules >= FT_MAX_MODULES )+ {+ error = FT_Err_Too_Many_Drivers;+ goto Exit;+ }++ /* allocate module object */+ if ( FT_ALLOC( module, clazz->module_size ) )+ goto Exit;++ /* base initialization */+ module->library = library;+ module->memory = memory;+ module->clazz = (FT_Module_Class*)clazz;++ /* check whether the module is a renderer - this must be performed */+ /* before the normal module initialization */+ if ( FT_MODULE_IS_RENDERER( module ) )+ {+ /* add to the renderers list */+ error = ft_add_renderer( module );+ if ( error )+ goto Fail;+ }++ /* is the module a auto-hinter? */+ if ( FT_MODULE_IS_HINTER( module ) )+ library->auto_hinter = module;++ /* if the module is a font driver */+ if ( FT_MODULE_IS_DRIVER( module ) )+ {+ /* allocate glyph loader if needed */+ FT_Driver driver = FT_DRIVER( module );+++ driver->clazz = (FT_Driver_Class)module->clazz;+ if ( FT_DRIVER_USES_OUTLINES( driver ) )+ {+ error = FT_GlyphLoader_New( memory, &driver->glyph_loader );+ if ( error )+ goto Fail;+ }+ }++ if ( clazz->module_init )+ {+ error = clazz->module_init( module );+ if ( error )+ goto Fail;+ }++ /* add module to the library's table */+ library->modules[library->num_modules++] = module;++ Exit:+ return error;++ Fail:+ if ( FT_MODULE_IS_DRIVER( module ) )+ {+ FT_Driver driver = FT_DRIVER( module );+++ if ( FT_DRIVER_USES_OUTLINES( driver ) )+ FT_GlyphLoader_Done( driver->glyph_loader );+ }++ if ( FT_MODULE_IS_RENDERER( module ) )+ {+ FT_Renderer renderer = FT_RENDERER( module );+++ if ( renderer->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE && + renderer->raster )+ renderer->clazz->raster_class->raster_done( renderer->raster );+ }++ FT_FREE( module );+ goto Exit;+ }+++ /* documentation is in ftmodapi.h */++ FT_EXPORT_DEF( FT_Module )+ FT_Get_Module( FT_Library library,+ const char* module_name )+ {+ FT_Module result = 0;+ FT_Module* cur;+ FT_Module* limit;+++ if ( !library || !module_name )+ return result;++ cur = library->modules;+ limit = cur + library->num_modules;++ for ( ; cur < limit; cur++ )+ if ( ft_strcmp( cur[0]->clazz->module_name, module_name ) == 0 )+ {+ result = cur[0];+ break;+ }++ return result;+ }+++ /* documentation is in ftobjs.h */++ FT_BASE_DEF( const void* )+ FT_Get_Module_Interface( FT_Library library,+ const char* mod_name )+ {+ FT_Module module;+++ /* test for valid `library' delayed to FT_Get_Module() */++ module = FT_Get_Module( library, mod_name );++ return module ? module->clazz->module_interface : 0;+ }+++ FT_BASE_DEF( FT_Pointer )+ ft_module_get_service( FT_Module module,+ const char* service_id )+ {+ FT_Pointer result = NULL;++ if ( module )+ {+ FT_ASSERT( module->clazz && module->clazz->get_interface );++ /* first, look for the service in the module+ */+ if ( module->clazz->get_interface )+ result = module->clazz->get_interface( module, service_id );++ if ( result == NULL )+ {+ /* we didn't find it, look in all other modules then+ */+ FT_Library library = module->library;+ FT_Module* cur = library->modules;+ FT_Module* limit = cur + library->num_modules;++ for ( ; cur < limit; cur++ )+ {+ if ( cur[0] != module )+ {+ FT_ASSERT( cur[0]->clazz );++ if ( cur[0]->clazz->get_interface )+ {+ result = cur[0]->clazz->get_interface( cur[0], service_id );+ if ( result != NULL )+ break;+ }+ }+ }+ }+ }++ return result;+ }+++ /* documentation is in ftmodapi.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Remove_Module( FT_Library library,+ FT_Module module )+ {+ /* try to find the module from the table, then remove it from there */++ if ( !library )+ return FT_Err_Invalid_Library_Handle;++ if ( module )+ {+ FT_Module* cur = library->modules;+ FT_Module* limit = cur + library->num_modules;+++ for ( ; cur < limit; cur++ )+ {+ if ( cur[0] == module )+ {+ /* remove it from the table */+ library->num_modules--;+ limit--;+ while ( cur < limit )+ {+ cur[0] = cur[1];+ cur++;+ }+ limit[0] = 0;++ /* destroy the module */+ Destroy_Module( module );++ return FT_Err_Ok;+ }+ }+ }+ return FT_Err_Invalid_Driver_Handle;+ }+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** ****/+ /**** L I B R A R Y ****/+ /**** ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ /* documentation is in ftmodapi.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Reference_Library( FT_Library library )+ {+ library->refcount++;++ return FT_Err_Ok;+ }+++ /* documentation is in ftmodapi.h */++ FT_EXPORT_DEF( FT_Error )+ FT_New_Library( FT_Memory memory,+ FT_Library *alibrary )+ {+ FT_Library library = NULL;+ FT_Error error;+++ if ( !memory )+ return FT_Err_Invalid_Argument;++#ifdef FT_DEBUG_LEVEL_ERROR+ /* init debugging support */+ ft_debug_init();+#endif++ /* first of all, allocate the library object */+ if ( FT_NEW( library ) )+ return error;++ library->memory = memory;++#ifdef FT_CONFIG_OPTION_PIC+ /* initialize position independent code containers */+ error = ft_pic_container_init( library );+ if ( error )+ goto Fail;+#endif++ /* allocate the render pool */+ library->raster_pool_size = FT_RENDER_POOL_SIZE;+#if FT_RENDER_POOL_SIZE > 0+ if ( FT_ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) )+ goto Fail;+#endif++ library->version_major = FREETYPE_MAJOR;+ library->version_minor = FREETYPE_MINOR;+ library->version_patch = FREETYPE_PATCH;++ library->refcount = 1;++ /* That's ok now */+ *alibrary = library;++ return FT_Err_Ok;++ Fail:+#ifdef FT_CONFIG_OPTION_PIC+ ft_pic_container_destroy( library );+#endif+ FT_FREE( library );+ return error;+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( void )+ FT_Library_Version( FT_Library library,+ FT_Int *amajor,+ FT_Int *aminor,+ FT_Int *apatch )+ {+ FT_Int major = 0;+ FT_Int minor = 0;+ FT_Int patch = 0;+++ if ( library )+ {+ major = library->version_major;+ minor = library->version_minor;+ patch = library->version_patch;+ }++ if ( amajor )+ *amajor = major;++ if ( aminor )+ *aminor = minor;++ if ( apatch )+ *apatch = patch;+ }+++ /* documentation is in ftmodapi.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Done_Library( FT_Library library )+ {+ FT_Memory memory;+++ if ( !library )+ return FT_Err_Invalid_Library_Handle;++ library->refcount--;+ if ( library->refcount > 0 )+ goto Exit;++ memory = library->memory;++ /* Discard client-data */+ if ( library->generic.finalizer )+ library->generic.finalizer( library );++ /*+ * Close all faces in the library. If we don't do this, we can have+ * some subtle memory leaks.+ *+ * Example:+ *+ * - the cff font driver uses the pshinter module in cff_size_done+ * - if the pshinter module is destroyed before the cff font driver,+ * opened FT_Face objects managed by the driver are not properly+ * destroyed, resulting in a memory leak+ *+ * Some faces are dependent on other faces, like Type42 faces that+ * depend on TrueType faces synthesized internally.+ *+ * The order of drivers should be specified in driver_name[].+ */+ {+ FT_UInt m, n;+ const char* driver_name[] = { "type42", NULL };+++ for ( m = 0;+ m < sizeof ( driver_name ) / sizeof ( driver_name[0] );+ m++ )+ {+ for ( n = 0; n < library->num_modules; n++ )+ {+ FT_Module module = library->modules[n];+ const char* module_name = module->clazz->module_name;+ FT_List faces;+++ if ( driver_name[m] &&+ ft_strcmp( module_name, driver_name[m] ) != 0 )+ continue;++ if ( ( module->clazz->module_flags & FT_MODULE_FONT_DRIVER ) == 0 )+ continue;++ FT_TRACE7(( "FT_Done_Library: close faces for %s\n", module_name ));++ faces = &FT_DRIVER( module )->faces_list;+ while ( faces->head )+ {+ FT_Done_Face( FT_FACE( faces->head->data ) );+ if ( faces->head )+ FT_TRACE0(( "FT_Done_Library: failed to free some faces\n" ));+ }+ }+ }+ }++ /* Close all other modules in the library */+#if 1+ /* XXX Modules are removed in the reversed order so that */+ /* type42 module is removed before truetype module. This */+ /* avoids double free in some occasions. It is a hack. */+ while ( library->num_modules > 0 )+ FT_Remove_Module( library,+ library->modules[library->num_modules - 1] );+#else+ {+ FT_UInt n;+++ for ( n = 0; n < library->num_modules; n++ )+ {+ FT_Module module = library->modules[n];+++ if ( module )+ {+ Destroy_Module( module );+ library->modules[n] = 0;+ }+ }+ }+#endif++ /* Destroy raster objects */+ FT_FREE( library->raster_pool );+ library->raster_pool_size = 0;++#ifdef FT_CONFIG_OPTION_PIC+ /* Destroy pic container contents */+ ft_pic_container_destroy( library );+#endif++ FT_FREE( library );++ Exit:+ return FT_Err_Ok;+ }+++ /* documentation is in ftmodapi.h */++ FT_EXPORT_DEF( void )+ FT_Set_Debug_Hook( FT_Library library,+ FT_UInt hook_index,+ FT_DebugHook_Func debug_hook )+ {+ if ( library && debug_hook &&+ hook_index <+ ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) )+ library->debug_hooks[hook_index] = debug_hook;+ }+++ /* documentation is in ftmodapi.h */++ FT_EXPORT_DEF( FT_TrueTypeEngineType )+ FT_Get_TrueType_Engine_Type( FT_Library library )+ {+ FT_TrueTypeEngineType result = FT_TRUETYPE_ENGINE_TYPE_NONE;+++ if ( library )+ {+ FT_Module module = FT_Get_Module( library, "truetype" );+++ if ( module )+ {+ FT_Service_TrueTypeEngine service;+++ service = (FT_Service_TrueTypeEngine)+ ft_module_get_service( module,+ FT_SERVICE_ID_TRUETYPE_ENGINE );+ if ( service )+ result = service->engine_type;+ }+ }++ return result;+ }+++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS++ FT_BASE_DEF( FT_Error )+ ft_stub_set_char_sizes( FT_Size size,+ FT_F26Dot6 width,+ FT_F26Dot6 height,+ FT_UInt horz_res,+ FT_UInt vert_res )+ {+ FT_Size_RequestRec req;+ FT_Driver driver = size->face->driver;+++ if ( driver->clazz->request_size )+ {+ req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;+ req.width = width;+ req.height = height;++ if ( horz_res == 0 )+ horz_res = vert_res;++ if ( vert_res == 0 )+ vert_res = horz_res;++ if ( horz_res == 0 )+ horz_res = vert_res = 72;++ req.horiResolution = horz_res;+ req.vertResolution = vert_res;++ return driver->clazz->request_size( size, &req );+ }++ return 0;+ }+++ FT_BASE_DEF( FT_Error )+ ft_stub_set_pixel_sizes( FT_Size size,+ FT_UInt width,+ FT_UInt height )+ {+ FT_Size_RequestRec req;+ FT_Driver driver = size->face->driver;+++ if ( driver->clazz->request_size )+ {+ req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;+ req.width = width << 6;+ req.height = height << 6;+ req.horiResolution = 0;+ req.vertResolution = 0;++ return driver->clazz->request_size( size, &req );+ }++ return 0;+ }++#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Get_SubGlyph_Info( FT_GlyphSlot glyph,+ FT_UInt sub_index,+ FT_Int *p_index,+ FT_UInt *p_flags,+ FT_Int *p_arg1,+ FT_Int *p_arg2,+ FT_Matrix *p_transform )+ {+ FT_Error error = FT_Err_Invalid_Argument;+++ if ( glyph &&+ glyph->subglyphs &&+ glyph->format == FT_GLYPH_FORMAT_COMPOSITE &&+ sub_index < glyph->num_subglyphs )+ {+ FT_SubGlyph subg = glyph->subglyphs + sub_index;+++ *p_index = subg->index;+ *p_flags = subg->flags;+ *p_arg1 = subg->arg1;+ *p_arg2 = subg->arg2;+ *p_transform = subg->transform;+ }++ return error;+ }+++/* END */
+ src/base/ftotval.c view
@@ -0,0 +1,89 @@+/***************************************************************************/+/* */+/* ftotval.c */+/* */+/* FreeType API for validating OpenType tables (body). */+/* */+/* Copyright 2004, 2006, 2008, 2010 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_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_Err_Invalid_Face_Handle;+ goto Exit;+ }++ if ( !( BASE_table &&+ GDEF_table &&+ GPOS_table &&+ GSUB_table &&+ JSTF_table ) )+ {+ error = FT_Err_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_Err_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 */
+ src/base/ftoutln.c view
@@ -0,0 +1,1129 @@+/***************************************************************************/+/* */+/* ftoutln.c */+/* */+/* FreeType outline management (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 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. */+/* */+/***************************************************************************/+++ /*************************************************************************/+ /* */+ /* All functions are declared in freetype.h. */+ /* */+ /*************************************************************************/+++#include <ft2build.h>+#include FT_OUTLINE_H+#include FT_INTERNAL_OBJECTS_H+#include FT_INTERNAL_DEBUG_H+#include FT_TRIGONOMETRY_H+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_outline+++ static+ const FT_Outline null_outline = { 0, 0, 0, 0, 0, 0 };+++ /* documentation is in ftoutln.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Outline_Decompose( FT_Outline* outline,+ const FT_Outline_Funcs* func_interface,+ void* user )+ {+#undef SCALED+#define SCALED( x ) ( ( (x) << shift ) - delta )++ FT_Vector v_last;+ FT_Vector v_control;+ FT_Vector v_start;++ FT_Vector* point;+ FT_Vector* limit;+ char* tags;++ FT_Error error;++ FT_Int n; /* index of contour in outline */+ FT_UInt first; /* index of first point in contour */+ FT_Int tag; /* current point's state */++ FT_Int shift;+ FT_Pos delta;+++ if ( !outline || !func_interface )+ return FT_Err_Invalid_Argument;++ shift = func_interface->shift;+ delta = func_interface->delta;+ first = 0;++ for ( n = 0; n < outline->n_contours; n++ )+ {+ FT_Int last; /* index of last point in contour */+++ FT_TRACE5(( "FT_Outline_Decompose: Outline %d\n", n ));++ last = outline->contours[n];+ if ( last < 0 )+ goto Invalid_Outline;+ limit = outline->points + last;++ v_start = outline->points[first];+ v_start.x = SCALED( v_start.x );+ v_start.y = SCALED( v_start.y );++ v_last = outline->points[last];+ v_last.x = SCALED( v_last.x );+ v_last.y = SCALED( v_last.y );++ v_control = v_start;++ point = outline->points + first;+ tags = outline->tags + first;+ tag = FT_CURVE_TAG( tags[0] );++ /* A contour cannot start with a cubic control point! */+ if ( tag == FT_CURVE_TAG_CUBIC )+ goto Invalid_Outline;++ /* check first point to determine origin */+ if ( tag == FT_CURVE_TAG_CONIC )+ {+ /* first point is conic control. Yes, this happens. */+ if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON )+ {+ /* start at last point if it is on the curve */+ v_start = v_last;+ limit--;+ }+ else+ {+ /* if both first and last points are conic, */+ /* start at their middle and record its position */+ /* for closure */+ v_start.x = ( v_start.x + v_last.x ) / 2;+ v_start.y = ( v_start.y + v_last.y ) / 2;++ v_last = v_start;+ }+ point--;+ tags--;+ }++ FT_TRACE5(( " move to (%.2f, %.2f)\n",+ v_start.x / 64.0, v_start.y / 64.0 ));+ error = func_interface->move_to( &v_start, user );+ if ( error )+ goto Exit;++ while ( point < limit )+ {+ point++;+ tags++;++ tag = FT_CURVE_TAG( tags[0] );+ switch ( tag )+ {+ case FT_CURVE_TAG_ON: /* emit a single line_to */+ {+ FT_Vector vec;+++ vec.x = SCALED( point->x );+ vec.y = SCALED( point->y );++ FT_TRACE5(( " line to (%.2f, %.2f)\n",+ vec.x / 64.0, vec.y / 64.0 ));+ error = func_interface->line_to( &vec, user );+ if ( error )+ goto Exit;+ continue;+ }++ case FT_CURVE_TAG_CONIC: /* consume conic arcs */+ v_control.x = SCALED( point->x );+ v_control.y = SCALED( point->y );++ Do_Conic:+ if ( point < limit )+ {+ FT_Vector vec;+ FT_Vector v_middle;+++ point++;+ tags++;+ tag = FT_CURVE_TAG( tags[0] );++ vec.x = SCALED( point->x );+ vec.y = SCALED( point->y );++ if ( tag == FT_CURVE_TAG_ON )+ {+ FT_TRACE5(( " conic to (%.2f, %.2f)"+ " with control (%.2f, %.2f)\n",+ vec.x / 64.0, vec.y / 64.0,+ v_control.x / 64.0, v_control.y / 64.0 ));+ error = func_interface->conic_to( &v_control, &vec, user );+ if ( error )+ goto Exit;+ continue;+ }++ if ( tag != FT_CURVE_TAG_CONIC )+ goto Invalid_Outline;++ v_middle.x = ( v_control.x + vec.x ) / 2;+ v_middle.y = ( v_control.y + vec.y ) / 2;++ FT_TRACE5(( " conic to (%.2f, %.2f)"+ " with control (%.2f, %.2f)\n",+ v_middle.x / 64.0, v_middle.y / 64.0,+ v_control.x / 64.0, v_control.y / 64.0 ));+ error = func_interface->conic_to( &v_control, &v_middle, user );+ if ( error )+ goto Exit;++ v_control = vec;+ goto Do_Conic;+ }++ FT_TRACE5(( " conic to (%.2f, %.2f)"+ " with control (%.2f, %.2f)\n",+ v_start.x / 64.0, v_start.y / 64.0,+ v_control.x / 64.0, v_control.y / 64.0 ));+ error = func_interface->conic_to( &v_control, &v_start, user );+ goto Close;++ default: /* FT_CURVE_TAG_CUBIC */+ {+ FT_Vector vec1, vec2;+++ if ( point + 1 > limit ||+ FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )+ goto Invalid_Outline;++ point += 2;+ tags += 2;++ vec1.x = SCALED( point[-2].x );+ vec1.y = SCALED( point[-2].y );++ vec2.x = SCALED( point[-1].x );+ vec2.y = SCALED( point[-1].y );++ if ( point <= limit )+ {+ FT_Vector vec;+++ vec.x = SCALED( point->x );+ vec.y = SCALED( point->y );++ FT_TRACE5(( " cubic to (%.2f, %.2f)"+ " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",+ vec.x / 64.0, vec.y / 64.0,+ vec1.x / 64.0, vec1.y / 64.0,+ vec2.x / 64.0, vec2.y / 64.0 ));+ error = func_interface->cubic_to( &vec1, &vec2, &vec, user );+ if ( error )+ goto Exit;+ continue;+ }++ FT_TRACE5(( " cubic to (%.2f, %.2f)"+ " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",+ v_start.x / 64.0, v_start.y / 64.0,+ vec1.x / 64.0, vec1.y / 64.0,+ vec2.x / 64.0, vec2.y / 64.0 ));+ error = func_interface->cubic_to( &vec1, &vec2, &v_start, user );+ goto Close;+ }+ }+ }++ /* close the contour with a line segment */+ FT_TRACE5(( " line to (%.2f, %.2f)\n",+ v_start.x / 64.0, v_start.y / 64.0 ));+ error = func_interface->line_to( &v_start, user );++ Close:+ if ( error )+ goto Exit;++ first = last + 1;+ }++ FT_TRACE5(( "FT_Outline_Decompose: Done\n", n ));+ return FT_Err_Ok;++ Exit:+ FT_TRACE5(( "FT_Outline_Decompose: Error %d\n", error ));+ return error;++ Invalid_Outline:+ return FT_Err_Invalid_Outline;+ }+++ FT_EXPORT_DEF( FT_Error )+ FT_Outline_New_Internal( FT_Memory memory,+ FT_UInt numPoints,+ FT_Int numContours,+ FT_Outline *anoutline )+ {+ FT_Error error;+++ if ( !anoutline || !memory )+ return FT_Err_Invalid_Argument;++ *anoutline = null_outline;++ if ( FT_NEW_ARRAY( anoutline->points, numPoints ) ||+ FT_NEW_ARRAY( anoutline->tags, numPoints ) ||+ FT_NEW_ARRAY( anoutline->contours, numContours ) )+ goto Fail;++ anoutline->n_points = (FT_UShort)numPoints;+ anoutline->n_contours = (FT_Short)numContours;+ anoutline->flags |= FT_OUTLINE_OWNER;++ return FT_Err_Ok;++ Fail:+ anoutline->flags |= FT_OUTLINE_OWNER;+ FT_Outline_Done_Internal( memory, anoutline );++ return error;+ }+++ /* documentation is in ftoutln.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Outline_New( FT_Library library,+ FT_UInt numPoints,+ FT_Int numContours,+ FT_Outline *anoutline )+ {+ if ( !library )+ return FT_Err_Invalid_Library_Handle;++ return FT_Outline_New_Internal( library->memory, numPoints,+ numContours, anoutline );+ }+++ /* documentation is in ftoutln.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Outline_Check( FT_Outline* outline )+ {+ if ( outline )+ {+ FT_Int n_points = outline->n_points;+ FT_Int n_contours = outline->n_contours;+ FT_Int end0, end;+ FT_Int n;+++ /* empty glyph? */+ if ( n_points == 0 && n_contours == 0 )+ return 0;++ /* check point and contour counts */+ if ( n_points <= 0 || n_contours <= 0 )+ goto Bad;++ end0 = end = -1;+ for ( n = 0; n < n_contours; n++ )+ {+ end = outline->contours[n];++ /* note that we don't accept empty contours */+ if ( end <= end0 || end >= n_points )+ goto Bad;++ end0 = end;+ }++ if ( end != n_points - 1 )+ goto Bad;++ /* XXX: check the tags array */+ return 0;+ }++ Bad:+ return FT_Err_Invalid_Argument;+ }+++ /* documentation is in ftoutln.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Outline_Copy( const FT_Outline* source,+ FT_Outline *target )+ {+ FT_Int is_owner;+++ if ( !source || !target ||+ source->n_points != target->n_points ||+ source->n_contours != target->n_contours )+ return FT_Err_Invalid_Argument;++ if ( source == target )+ return FT_Err_Ok;++ FT_ARRAY_COPY( target->points, source->points, source->n_points );++ FT_ARRAY_COPY( target->tags, source->tags, source->n_points );++ FT_ARRAY_COPY( target->contours, source->contours, source->n_contours );++ /* copy all flags, except the `FT_OUTLINE_OWNER' one */+ is_owner = target->flags & FT_OUTLINE_OWNER;+ target->flags = source->flags;++ target->flags &= ~FT_OUTLINE_OWNER;+ target->flags |= is_owner;++ return FT_Err_Ok;+ }+++ FT_EXPORT_DEF( FT_Error )+ FT_Outline_Done_Internal( FT_Memory memory,+ FT_Outline* outline )+ {+ if ( memory && outline )+ {+ if ( outline->flags & FT_OUTLINE_OWNER )+ {+ FT_FREE( outline->points );+ FT_FREE( outline->tags );+ FT_FREE( outline->contours );+ }+ *outline = null_outline;++ return FT_Err_Ok;+ }+ else+ return FT_Err_Invalid_Argument;+ }+++ /* documentation is in ftoutln.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Outline_Done( FT_Library library,+ FT_Outline* outline )+ {+ /* check for valid `outline' in FT_Outline_Done_Internal() */++ if ( !library )+ return FT_Err_Invalid_Library_Handle;++ return FT_Outline_Done_Internal( library->memory, outline );+ }+++ /* documentation is in ftoutln.h */++ FT_EXPORT_DEF( void )+ FT_Outline_Get_CBox( const FT_Outline* outline,+ FT_BBox *acbox )+ {+ FT_Pos xMin, yMin, xMax, yMax;+++ if ( outline && acbox )+ {+ if ( outline->n_points == 0 )+ {+ xMin = 0;+ yMin = 0;+ xMax = 0;+ yMax = 0;+ }+ else+ {+ FT_Vector* vec = outline->points;+ FT_Vector* limit = vec + outline->n_points;+++ xMin = xMax = vec->x;+ yMin = yMax = vec->y;+ vec++;++ for ( ; vec < limit; vec++ )+ {+ FT_Pos x, y;+++ x = vec->x;+ if ( x < xMin ) xMin = x;+ if ( x > xMax ) xMax = x;++ y = vec->y;+ if ( y < yMin ) yMin = y;+ if ( y > yMax ) yMax = y;+ }+ }+ acbox->xMin = xMin;+ acbox->xMax = xMax;+ acbox->yMin = yMin;+ acbox->yMax = yMax;+ }+ }+++ /* documentation is in ftoutln.h */++ FT_EXPORT_DEF( void )+ FT_Outline_Translate( const FT_Outline* outline,+ FT_Pos xOffset,+ FT_Pos yOffset )+ {+ FT_UShort n;+ FT_Vector* vec;+++ if ( !outline )+ return;++ vec = outline->points;++ for ( n = 0; n < outline->n_points; n++ )+ {+ vec->x += xOffset;+ vec->y += yOffset;+ vec++;+ }+ }+++ /* documentation is in ftoutln.h */++ FT_EXPORT_DEF( void )+ FT_Outline_Reverse( FT_Outline* outline )+ {+ FT_UShort n;+ FT_Int first, last;+++ if ( !outline )+ return;++ first = 0;++ for ( n = 0; n < outline->n_contours; n++ )+ {+ last = outline->contours[n];++ /* reverse point table */+ {+ FT_Vector* p = outline->points + first;+ FT_Vector* q = outline->points + last;+ FT_Vector swap;+++ while ( p < q )+ {+ swap = *p;+ *p = *q;+ *q = swap;+ p++;+ q--;+ }+ }++ /* reverse tags table */+ {+ char* p = outline->tags + first;+ char* q = outline->tags + last;+ char swap;+++ while ( p < q )+ {+ swap = *p;+ *p = *q;+ *q = swap;+ p++;+ q--;+ }+ }++ first = last + 1;+ }++ outline->flags ^= FT_OUTLINE_REVERSE_FILL;+ }+++ /* documentation is in ftoutln.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Outline_Render( FT_Library library,+ FT_Outline* outline,+ FT_Raster_Params* params )+ {+ FT_Error error;+ FT_Bool update = FALSE;+ FT_Renderer renderer;+ FT_ListNode node;+++ if ( !library )+ return FT_Err_Invalid_Library_Handle;++ if ( !outline || !params )+ return FT_Err_Invalid_Argument;++ renderer = library->cur_renderer;+ node = library->renderers.head;++ params->source = (void*)outline;++ error = FT_Err_Cannot_Render_Glyph;+ while ( renderer )+ {+ error = renderer->raster_render( renderer->raster, params );+ if ( !error || FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )+ break;++ /* FT_Err_Cannot_Render_Glyph is returned if the render mode */+ /* is unsupported by the current renderer for this glyph image */+ /* format */++ /* now, look for another renderer that supports the same */+ /* format */+ renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE,+ &node );+ update = TRUE;+ }++ /* if we changed the current renderer for the glyph image format */+ /* we need to select it as the next current one */+ if ( !error && update && renderer )+ FT_Set_Renderer( library, renderer, 0, 0 );++ return error;+ }+++ /* documentation is in ftoutln.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Outline_Get_Bitmap( FT_Library library,+ FT_Outline* outline,+ const FT_Bitmap *abitmap )+ {+ FT_Raster_Params params;+++ if ( !abitmap )+ return FT_Err_Invalid_Argument;++ /* other checks are delayed to FT_Outline_Render() */++ params.target = abitmap;+ params.flags = 0;++ if ( abitmap->pixel_mode == FT_PIXEL_MODE_GRAY ||+ abitmap->pixel_mode == FT_PIXEL_MODE_LCD ||+ abitmap->pixel_mode == FT_PIXEL_MODE_LCD_V )+ params.flags |= FT_RASTER_FLAG_AA;++ return FT_Outline_Render( library, outline, ¶ms );+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( void )+ FT_Vector_Transform( FT_Vector* vector,+ const FT_Matrix* matrix )+ {+ FT_Pos xz, yz;+++ if ( !vector || !matrix )+ return;++ xz = FT_MulFix( vector->x, matrix->xx ) ++ FT_MulFix( vector->y, matrix->xy );++ yz = FT_MulFix( vector->x, matrix->yx ) ++ FT_MulFix( vector->y, matrix->yy );++ vector->x = xz;+ vector->y = yz;+ }+++ /* documentation is in ftoutln.h */++ FT_EXPORT_DEF( void )+ FT_Outline_Transform( const FT_Outline* outline,+ const FT_Matrix* matrix )+ {+ FT_Vector* vec;+ FT_Vector* limit;+++ if ( !outline || !matrix )+ return;++ vec = outline->points;+ limit = vec + outline->n_points;++ for ( ; vec < limit; vec++ )+ FT_Vector_Transform( vec, matrix );+ }+++#if 0++#define FT_OUTLINE_GET_CONTOUR( outline, c, first, last ) \+ do { \+ (first) = ( c > 0 ) ? (outline)->points + \+ (outline)->contours[c - 1] + 1 \+ : (outline)->points; \+ (last) = (outline)->points + (outline)->contours[c]; \+ } while ( 0 )+++ /* Is a point in some contour? */+ /* */+ /* We treat every point of the contour as if it */+ /* it were ON. That is, we allow false positives, */+ /* but disallow false negatives. (XXX really?) */+ static FT_Bool+ ft_contour_has( FT_Outline* outline,+ FT_Short c,+ FT_Vector* point )+ {+ FT_Vector* first;+ FT_Vector* last;+ FT_Vector* a;+ FT_Vector* b;+ FT_UInt n = 0;+++ FT_OUTLINE_GET_CONTOUR( outline, c, first, last );++ for ( a = first; a <= last; a++ )+ {+ FT_Pos x;+ FT_Int intersect;+++ b = ( a == last ) ? first : a + 1;++ intersect = ( a->y - point->y ) ^ ( b->y - point->y );++ /* a and b are on the same side */+ if ( intersect >= 0 )+ {+ if ( intersect == 0 && a->y == point->y )+ {+ if ( ( a->x <= point->x && b->x >= point->x ) ||+ ( a->x >= point->x && b->x <= point->x ) )+ return 1;+ }++ continue;+ }++ x = a->x + ( b->x - a->x ) * (point->y - a->y ) / ( b->y - a->y );++ if ( x < point->x )+ n++;+ else if ( x == point->x )+ return 1;+ }++ return ( n % 2 );+ }+++ static FT_Bool+ ft_contour_enclosed( FT_Outline* outline,+ FT_UShort c )+ {+ FT_Vector* first;+ FT_Vector* last;+ FT_Short i;+++ FT_OUTLINE_GET_CONTOUR( outline, c, first, last );++ for ( i = 0; i < outline->n_contours; i++ )+ {+ if ( i != c && ft_contour_has( outline, i, first ) )+ {+ FT_Vector* pt;+++ for ( pt = first + 1; pt <= last; pt++ )+ if ( !ft_contour_has( outline, i, pt ) )+ return 0;++ return 1;+ }+ }++ return 0;+ }+++ /* This version differs from the public one in that each */+ /* part (contour not enclosed in another contour) of the */+ /* outline is checked for orientation. This is */+ /* necessary for some buggy CJK fonts. */+ static FT_Orientation+ ft_outline_get_orientation( FT_Outline* outline )+ {+ FT_Short i;+ FT_Vector* first;+ FT_Vector* last;+ FT_Orientation orient = FT_ORIENTATION_NONE;+++ first = outline->points;+ for ( i = 0; i < outline->n_contours; i++, first = last + 1 )+ {+ FT_Vector* point;+ FT_Vector* xmin_point;+ FT_Pos xmin;+++ last = outline->points + outline->contours[i];++ /* skip degenerate contours */+ if ( last < first + 2 )+ continue;++ if ( ft_contour_enclosed( outline, i ) )+ continue;++ xmin = first->x;+ xmin_point = first;++ for ( point = first + 1; point <= last; point++ )+ {+ if ( point->x < xmin )+ {+ xmin = point->x;+ xmin_point = point;+ }+ }++ /* check the orientation of the contour */+ {+ FT_Vector* prev;+ FT_Vector* next;+ FT_Orientation o;+++ prev = ( xmin_point == first ) ? last : xmin_point - 1;+ next = ( xmin_point == last ) ? first : xmin_point + 1;++ if ( FT_Atan2( prev->x - xmin_point->x, prev->y - xmin_point->y ) >+ FT_Atan2( next->x - xmin_point->x, next->y - xmin_point->y ) )+ o = FT_ORIENTATION_POSTSCRIPT;+ else+ o = FT_ORIENTATION_TRUETYPE;++ if ( orient == FT_ORIENTATION_NONE )+ orient = o;+ else if ( orient != o )+ return FT_ORIENTATION_NONE;+ }+ }++ return orient;+ }++#endif /* 0 */+++ /* documentation is in ftoutln.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Outline_Embolden( FT_Outline* outline,+ FT_Pos strength )+ {+ FT_Vector* points;+ FT_Vector v_prev, v_first, v_next, v_cur;+ FT_Angle rotate, angle_in, angle_out;+ FT_Int c, n, first;+ FT_Int orientation;+++ if ( !outline )+ return FT_Err_Invalid_Argument;++ strength /= 2;+ if ( strength == 0 )+ return FT_Err_Ok;++ orientation = FT_Outline_Get_Orientation( outline );+ if ( orientation == FT_ORIENTATION_NONE )+ {+ if ( outline->n_contours )+ return FT_Err_Invalid_Argument;+ else+ return FT_Err_Ok;+ }++ if ( orientation == FT_ORIENTATION_TRUETYPE )+ rotate = -FT_ANGLE_PI2;+ else+ rotate = FT_ANGLE_PI2;++ points = outline->points;++ first = 0;+ for ( c = 0; c < outline->n_contours; c++ )+ {+ int last = outline->contours[c];+++ v_first = points[first];+ v_prev = points[last];+ v_cur = v_first;++ for ( n = first; n <= last; n++ )+ {+ FT_Vector in, out;+ FT_Angle angle_diff;+ FT_Pos d;+ FT_Fixed scale;+++ if ( n < last )+ v_next = points[n + 1];+ else+ v_next = v_first;++ /* compute the in and out vectors */+ in.x = v_cur.x - v_prev.x;+ in.y = v_cur.y - v_prev.y;++ out.x = v_next.x - v_cur.x;+ out.y = v_next.y - v_cur.y;++ angle_in = FT_Atan2( in.x, in.y );+ angle_out = FT_Atan2( out.x, out.y );+ angle_diff = FT_Angle_Diff( angle_in, angle_out );+ scale = FT_Cos( angle_diff / 2 );++ if ( scale < 0x4000L && scale > -0x4000L )+ in.x = in.y = 0;+ else+ {+ d = FT_DivFix( strength, scale );++ FT_Vector_From_Polar( &in, d, angle_in + angle_diff / 2 - rotate );+ }++ outline->points[n].x = v_cur.x + strength + in.x;+ outline->points[n].y = v_cur.y + strength + in.y;++ v_prev = v_cur;+ v_cur = v_next;+ }++ first = last + 1;+ }++ return FT_Err_Ok;+ }+++ /* documentation is in ftoutln.h */++ FT_EXPORT_DEF( FT_Orientation )+ FT_Outline_Get_Orientation( FT_Outline* outline )+ {+ FT_Pos xmin = 32768L;+ FT_Pos xmin_ymin = 32768L;+ FT_Pos xmin_ymax = -32768L;+ FT_Vector* xmin_first = NULL;+ FT_Vector* xmin_last = NULL;++ short* contour;++ FT_Vector* first;+ FT_Vector* last;+ FT_Vector* prev;+ FT_Vector* point;++ int i;+ FT_Pos ray_y[3];+ FT_Orientation result[3] =+ { FT_ORIENTATION_NONE, FT_ORIENTATION_NONE, FT_ORIENTATION_NONE };+++ if ( !outline || outline->n_points <= 0 )+ return FT_ORIENTATION_TRUETYPE;++ /* We use the nonzero winding rule to find the orientation. */+ /* Since glyph outlines behave much more `regular' than arbitrary */+ /* cubic or quadratic curves, this test deals with the polygon */+ /* only which is spanned up by the control points. */++ first = outline->points;+ for ( contour = outline->contours;+ contour < outline->contours + outline->n_contours;+ contour++, first = last + 1 )+ {+ FT_Pos contour_xmin = 32768L;+ FT_Pos contour_xmax = -32768L;+ FT_Pos contour_ymin = 32768L;+ FT_Pos contour_ymax = -32768L;+++ last = outline->points + *contour;++ /* skip degenerate contours */+ if ( last < first + 2 )+ continue;++ for ( point = first; point <= last; ++point )+ {+ if ( point->x < contour_xmin )+ contour_xmin = point->x;++ if ( point->x > contour_xmax )+ contour_xmax = point->x;++ if ( point->y < contour_ymin )+ contour_ymin = point->y;++ if ( point->y > contour_ymax )+ contour_ymax = point->y;+ }++ if ( contour_xmin < xmin &&+ contour_xmin != contour_xmax &&+ contour_ymin != contour_ymax )+ {+ xmin = contour_xmin;+ xmin_ymin = contour_ymin;+ xmin_ymax = contour_ymax;+ xmin_first = first;+ xmin_last = last;+ }+ }++ if ( xmin == 32768L )+ return FT_ORIENTATION_TRUETYPE;++ ray_y[0] = ( xmin_ymin * 3 + xmin_ymax ) >> 2;+ ray_y[1] = ( xmin_ymin + xmin_ymax ) >> 1;+ ray_y[2] = ( xmin_ymin + xmin_ymax * 3 ) >> 2;++ for ( i = 0; i < 3; i++ )+ {+ FT_Pos left_x;+ FT_Pos right_x;+ FT_Vector* left1;+ FT_Vector* left2;+ FT_Vector* right1;+ FT_Vector* right2;+++ RedoRay:+ left_x = 32768L;+ right_x = -32768L;++ left1 = left2 = right1 = right2 = NULL;++ prev = xmin_last;+ for ( point = xmin_first; point <= xmin_last; prev = point, ++point )+ {+ FT_Pos tmp_x;+++ if ( point->y == ray_y[i] || prev->y == ray_y[i] )+ {+ ray_y[i]++;+ goto RedoRay;+ }++ if ( ( point->y < ray_y[i] && prev->y < ray_y[i] ) ||+ ( point->y > ray_y[i] && prev->y > ray_y[i] ) )+ continue;++ tmp_x = FT_MulDiv( point->x - prev->x,+ ray_y[i] - prev->y,+ point->y - prev->y ) + prev->x;++ if ( tmp_x < left_x )+ {+ left_x = tmp_x;+ left1 = prev;+ left2 = point;+ }++ if ( tmp_x > right_x )+ {+ right_x = tmp_x;+ right1 = prev;+ right2 = point;+ }+ }++ if ( left1 && right1 )+ {+ if ( left1->y < left2->y && right1->y > right2->y )+ result[i] = FT_ORIENTATION_TRUETYPE;+ else if ( left1->y > left2->y && right1->y < right2->y )+ result[i] = FT_ORIENTATION_POSTSCRIPT;+ else+ result[i] = FT_ORIENTATION_NONE;+ }+ }++ if ( result[0] != FT_ORIENTATION_NONE &&+ ( result[0] == result[1] || result[0] == result[2] ) )+ return result[0];++ if ( result[1] != FT_ORIENTATION_NONE && result[1] == result[2] )+ return result[1];++ return FT_ORIENTATION_TRUETYPE;+ }+++/* END */
+ src/base/ftpatent.c view
@@ -0,0 +1,286 @@+/***************************************************************************/+/* */+/* ftpatent.c */+/* */+/* FreeType API for checking patented TrueType bytecode instructions */+/* (body). */+/* */+/* Copyright 2007, 2008, 2010 by David Turner. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/++#include <ft2build.h>+#include FT_FREETYPE_H+#include FT_TRUETYPE_TAGS_H+#include FT_INTERNAL_OBJECTS_H+#include FT_INTERNAL_STREAM_H+#include FT_SERVICE_SFNT_H+#include FT_SERVICE_TRUETYPE_GLYF_H+++ static FT_Bool+ _tt_check_patents_in_range( FT_Stream stream,+ FT_ULong size )+ {+ FT_Bool result = FALSE;+ FT_Error error;+ FT_Bytes p, end;+++ if ( FT_FRAME_ENTER( size ) )+ return 0;++ p = stream->cursor;+ end = p + size;++ while ( p < end )+ {+ switch (p[0])+ {+ case 0x06: /* SPvTL // */+ case 0x07: /* SPvTL + */+ case 0x08: /* SFvTL // */+ case 0x09: /* SFvTL + */+ case 0x0A: /* SPvFS */+ case 0x0B: /* SFvFS */+ result = TRUE;+ goto Exit;++ case 0x40:+ if ( p + 1 >= end )+ goto Exit;++ p += p[1] + 2;+ break;++ case 0x41:+ if ( p + 1 >= end )+ goto Exit;++ p += p[1] * 2 + 2;+ break;++ case 0x71: /* DELTAP2 */+ case 0x72: /* DELTAP3 */+ case 0x73: /* DELTAC0 */+ case 0x74: /* DELTAC1 */+ case 0x75: /* DELTAC2 */+ result = TRUE;+ goto Exit;++ case 0xB0:+ case 0xB1:+ case 0xB2:+ case 0xB3:+ case 0xB4:+ case 0xB5:+ case 0xB6:+ case 0xB7:+ p += ( p[0] - 0xB0 ) + 2;+ break;++ case 0xB8:+ case 0xB9:+ case 0xBA:+ case 0xBB:+ case 0xBC:+ case 0xBD:+ case 0xBE:+ case 0xBF:+ p += ( p[0] - 0xB8 ) * 2 + 3;+ break;++ default:+ p += 1;+ break;+ }+ }++ Exit:+ FT_UNUSED( error );+ FT_FRAME_EXIT();+ return result;+ }+++ static FT_Bool+ _tt_check_patents_in_table( FT_Face face,+ FT_ULong tag )+ {+ FT_Stream stream = face->stream;+ FT_Error error = FT_Err_Ok;+ FT_Service_SFNT_Table service;+ FT_Bool result = FALSE;+++ FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );++ if ( service )+ {+ FT_UInt i = 0;+ FT_ULong tag_i = 0, offset_i = 0, length_i = 0;+++ for ( i = 0; !error && tag_i != tag ; i++ )+ error = service->table_info( face, i,+ &tag_i, &offset_i, &length_i );++ if ( error ||+ FT_STREAM_SEEK( offset_i ) )+ goto Exit;++ result = _tt_check_patents_in_range( stream, length_i );+ }++ Exit:+ return result;+ }+++ static FT_Bool+ _tt_face_check_patents( FT_Face face )+ {+ FT_Stream stream = face->stream;+ FT_UInt gindex;+ FT_Error error;+ FT_Bool result;++ FT_Service_TTGlyf service;+++ result = _tt_check_patents_in_table( face, TTAG_fpgm );+ if ( result )+ goto Exit;++ result = _tt_check_patents_in_table( face, TTAG_prep );+ if ( result )+ goto Exit;++ FT_FACE_FIND_SERVICE( face, service, TT_GLYF );+ if ( service == NULL )+ goto Exit;++ for ( gindex = 0; gindex < (FT_UInt)face->num_glyphs; gindex++ )+ {+ FT_ULong offset, num_ins, size;+ FT_Int num_contours;+++ offset = service->get_location( face, gindex, &size );+ if ( size == 0 )+ continue;++ if ( FT_STREAM_SEEK( offset ) ||+ FT_READ_SHORT( num_contours ) )+ continue;++ if ( num_contours >= 0 ) /* simple glyph */+ {+ if ( FT_STREAM_SKIP( 8 + num_contours * 2 ) )+ continue;+ }+ else /* compound glyph */+ {+ FT_Bool has_instr = 0;+++ if ( FT_STREAM_SKIP( 8 ) )+ continue;++ /* now read each component */+ for (;;)+ {+ FT_UInt flags, toskip;+++ if( FT_READ_USHORT( flags ) )+ break;++ toskip = 2 + 1 + 1;++ if ( ( flags & ( 1 << 0 ) ) != 0 ) /* ARGS_ARE_WORDS */+ toskip += 2;++ if ( ( flags & ( 1 << 3 ) ) != 0 ) /* WE_HAVE_A_SCALE */+ toskip += 2;+ else if ( ( flags & ( 1 << 6 ) ) != 0 ) /* WE_HAVE_X_Y_SCALE */+ toskip += 4;+ else if ( ( flags & ( 1 << 7 ) ) != 0 ) /* WE_HAVE_A_2x2 */+ toskip += 8;++ if ( ( flags & ( 1 << 8 ) ) != 0 ) /* WE_HAVE_INSTRUCTIONS */+ has_instr = 1;++ if ( FT_STREAM_SKIP( toskip ) )+ goto NextGlyph;++ if ( ( flags & ( 1 << 5 ) ) == 0 ) /* MORE_COMPONENTS */+ break;+ }++ if ( !has_instr )+ goto NextGlyph;+ }++ if ( FT_READ_USHORT( num_ins ) )+ continue;++ result = _tt_check_patents_in_range( stream, num_ins );+ if ( result )+ goto Exit;++ NextGlyph:+ ;+ }++ Exit:+ return result;+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Bool )+ FT_Face_CheckTrueTypePatents( FT_Face face )+ {+ FT_Bool result = FALSE;+++ if ( face && FT_IS_SFNT( face ) )+ result = _tt_face_check_patents( face );++ return result;+ }+++ /* documentation is in freetype.h */++ FT_EXPORT_DEF( FT_Bool )+ FT_Face_SetUnpatentedHinting( FT_Face face,+ FT_Bool value )+ {+ FT_Bool result = FALSE;+++#if defined( TT_CONFIG_OPTION_UNPATENTED_HINTING ) && \+ !defined( TT_CONFIG_OPTION_BYTECODE_INTEPRETER )+ if ( face && FT_IS_SFNT( face ) )+ {+ result = !face->internal->ignore_unpatented_hinter;+ face->internal->ignore_unpatented_hinter = !value;+ }+#else+ FT_UNUSED( face );+ FT_UNUSED( value );+#endif++ return result;+ }++/* END */
+ src/base/ftpfr.c view
@@ -0,0 +1,144 @@+/***************************************************************************/+/* */+/* ftpfr.c */+/* */+/* FreeType API for accessing PFR-specific data (body). */+/* */+/* Copyright 2002, 2003, 2004, 2008, 2010 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_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_Err_Invalid_Argument;++ 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_Err_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_Err_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;+++ 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_Err_Invalid_Argument;++ return error;+ }+++/* END */
+ src/base/ftpic.c view
@@ -0,0 +1,54 @@+/***************************************************************************/+/* */+/* ftpic.c */+/* */+/* The FreeType position independent code services (body). */+/* */+/* Copyright 2009 by */+/* Oran Agra and Mickey Gabel. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#include <ft2build.h>+#include FT_FREETYPE_H+#include FT_INTERNAL_OBJECTS_H+#include "basepic.h"++#ifdef FT_CONFIG_OPTION_PIC++ /* documentation is in ftpic.h */++ FT_BASE_DEF( FT_Error )+ ft_pic_container_init( FT_Library library )+ {+ FT_PIC_Container* pic_container = &library->pic_container;+ FT_Error error = FT_Err_Ok;++ FT_MEM_SET( pic_container, 0, sizeof(*pic_container) );++ error = ft_base_pic_init( library );+ if(error)+ return error;++ return FT_Err_Ok;+ }+++ /* Destroy the contents of the container. */+ FT_BASE_DEF( void )+ ft_pic_container_destroy( FT_Library library )+ {+ ft_base_pic_free( library );+ }++#endif /* FT_CONFIG_OPTION_PIC */+++/* END */
+ src/base/ftrfork.c view
@@ -0,0 +1,871 @@+/***************************************************************************/+/* */+/* ftrfork.c */+/* */+/* Embedded resource forks accessor (body). */+/* */+/* Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010 by */+/* Masatake YAMATO and Redhat K.K. */+/* */+/* FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are */+/* derived from ftobjs.c. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/++/***************************************************************************/+/* Development of the code in this file is support of */+/* Information-technology Promotion Agency, Japan. */+/***************************************************************************/+++#include <ft2build.h>+#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_STREAM_H+#include FT_INTERNAL_RFORK_H+++#undef FT_COMPONENT+#define FT_COMPONENT trace_raccess+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** ****/+ /**** Resource fork directory access ****/+ /**** ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/++ FT_BASE_DEF( FT_Error )+ FT_Raccess_Get_HeaderInfo( FT_Library library,+ FT_Stream stream,+ FT_Long rfork_offset,+ FT_Long *map_offset,+ FT_Long *rdata_pos )+ {+ FT_Error error;+ unsigned char head[16], head2[16];+ FT_Long map_pos, rdata_len;+ int allzeros, allmatch, i;+ FT_Long type_list;++ FT_UNUSED( library );+++ error = FT_Stream_Seek( stream, rfork_offset );+ if ( error )+ return error;++ error = FT_Stream_Read( stream, (FT_Byte *)head, 16 );+ 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];++ /* map_len = head[12] .. head[15] */++ if ( *rdata_pos + rdata_len != map_pos || map_pos == rfork_offset )+ return FT_Err_Unknown_File_Format;++ error = FT_Stream_Seek( stream, map_pos );+ if ( error )+ return error;++ head2[15] = (FT_Byte)( head[15] + 1 ); /* make it be different */++ error = FT_Stream_Read( stream, (FT_Byte*)head2, 16 );+ if ( error )+ return error;++ allzeros = 1;+ allmatch = 1;+ for ( i = 0; i < 16; ++i )+ {+ if ( head2[i] != 0 )+ allzeros = 0;+ if ( head2[i] != head[i] )+ allmatch = 0;+ }+ if ( !allzeros && !allmatch )+ return FT_Err_Unknown_File_Format;++ /* If we have reached this point then it is probably a mac resource */+ /* file. Now, does it contain any interesting resources? */+ /* Skip handle to next resource map, the file resource number, and */+ /* attributes. */+ (void)FT_STREAM_SKIP( 4 /* skip handle to next resource map */+ + 2 /* skip file resource number */+ + 2 ); /* skip attributes */++ if ( FT_READ_USHORT( type_list ) )+ return error;+ if ( type_list == -1 )+ return FT_Err_Unknown_File_Format;++ error = FT_Stream_Seek( stream, map_pos + type_list );+ if ( error )+ return error;++ *map_offset = map_pos + type_list;+ return FT_Err_Ok;+ }+++ static int+ ft_raccess_sort_ref_by_id( FT_RFork_Ref* a,+ FT_RFork_Ref* b )+ {+ if ( a->res_id < b->res_id )+ return -1;+ else if ( a->res_id > b->res_id )+ return 1;+ else+ return 0;+ }+++ FT_BASE_DEF( FT_Error )+ FT_Raccess_Get_DataOffsets( FT_Library library,+ FT_Stream stream,+ FT_Long map_offset,+ FT_Long rdata_pos,+ FT_Long tag,+ FT_Long **offsets,+ FT_Long *count )+ {+ FT_Error error;+ int i, j, cnt, subcnt;+ FT_Long tag_internal, rpos;+ FT_Memory memory = library->memory;+ FT_Long temp;+ FT_Long *offsets_internal;+ FT_RFork_Ref *ref;+++ error = FT_Stream_Seek( stream, map_offset );+ if ( error )+ return error;++ if ( FT_READ_USHORT( cnt ) )+ return error;+ cnt++;++ for ( i = 0; i < cnt; ++i )+ {+ if ( FT_READ_LONG( tag_internal ) ||+ FT_READ_USHORT( subcnt ) ||+ FT_READ_USHORT( rpos ) )+ return error;++ FT_TRACE2(( "Resource tags: %c%c%c%c\n",+ (char)( 0xff & ( tag_internal >> 24 ) ),+ (char)( 0xff & ( tag_internal >> 16 ) ),+ (char)( 0xff & ( tag_internal >> 8 ) ),+ (char)( 0xff & ( tag_internal >> 0 ) ) ));++ if ( tag_internal == tag )+ {+ *count = subcnt + 1;+ rpos += map_offset;++ error = FT_Stream_Seek( stream, rpos );+ if ( error )+ return error;++ if ( FT_NEW_ARRAY( ref, *count ) )+ return error;++ for ( j = 0; j < *count; ++j )+ {+ if ( FT_READ_USHORT( ref[j].res_id ) )+ goto Exit;+ if ( FT_STREAM_SKIP( 2 ) ) /* resource name */+ goto Exit;+ if ( FT_READ_LONG( temp ) )+ goto Exit;+ if ( FT_STREAM_SKIP( 4 ) ) /* mbz */+ goto Exit;++ ref[j].offset = temp & 0xFFFFFFL;+ }++ ft_qsort( ref, *count, sizeof ( FT_RFork_Ref ),+ ( int(*)(const void*, const void*) )+ ft_raccess_sort_ref_by_id );++ if ( FT_NEW_ARRAY( offsets_internal, *count ) )+ goto Exit;++ /* XXX: duplicated reference ID,+ * gap between reference IDs are acceptable?+ * further investigation on Apple implementation is needed.+ */+ for ( j = 0; j < *count; ++j )+ offsets_internal[j] = rdata_pos + ref[j].offset;++ *offsets = offsets_internal;+ error = FT_Err_Ok;++ Exit:+ FT_FREE( ref );+ return error;+ }+ }++ return FT_Err_Cannot_Open_Resource;+ }+++#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** ****/+ /**** Guessing functions ****/+ /**** ****/+ /**** When you add a new guessing function, ****/+ /**** update FT_RACCESS_N_RULES in ftrfork.h. ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/++ typedef FT_Error+ (*raccess_guess_func)( FT_Library library,+ FT_Stream stream,+ char *base_file_name,+ char **result_file_name,+ FT_Long *result_offset );+++ static FT_Error+ raccess_guess_apple_double( FT_Library library,+ FT_Stream stream,+ char *base_file_name,+ char **result_file_name,+ FT_Long *result_offset );++ static FT_Error+ raccess_guess_apple_single( FT_Library library,+ FT_Stream stream,+ char *base_file_name,+ char **result_file_name,+ FT_Long *result_offset );++ static FT_Error+ raccess_guess_darwin_ufs_export( FT_Library library,+ FT_Stream stream,+ char *base_file_name,+ char **result_file_name,+ FT_Long *result_offset );++ static FT_Error+ raccess_guess_darwin_newvfs( FT_Library library,+ FT_Stream stream,+ char *base_file_name,+ char **result_file_name,+ FT_Long *result_offset );++ static FT_Error+ raccess_guess_darwin_hfsplus( FT_Library library,+ FT_Stream stream,+ char *base_file_name,+ char **result_file_name,+ FT_Long *result_offset );++ static FT_Error+ raccess_guess_vfat( FT_Library library,+ FT_Stream stream,+ char *base_file_name,+ char **result_file_name,+ FT_Long *result_offset );++ static FT_Error+ raccess_guess_linux_cap( FT_Library library,+ FT_Stream stream,+ char *base_file_name,+ char **result_file_name,+ FT_Long *result_offset );++ static FT_Error+ raccess_guess_linux_double( FT_Library library,+ FT_Stream stream,+ char *base_file_name,+ char **result_file_name,+ FT_Long *result_offset );++ static FT_Error+ raccess_guess_linux_netatalk( FT_Library library,+ FT_Stream stream,+ char *base_file_name,+ char **result_file_name,+ FT_Long *result_offset );+++ /*************************************************************************/+ /**** ****/+ /**** Helper functions ****/+ /**** ****/+ /*************************************************************************/++ static FT_Error+ raccess_guess_apple_generic( FT_Library library,+ FT_Stream stream,+ char *base_file_name,+ FT_Int32 magic,+ FT_Long *result_offset );++ static FT_Error+ raccess_guess_linux_double_from_file_name( FT_Library library,+ char * file_name,+ FT_Long *result_offset );++ static char *+ raccess_make_file_name( FT_Memory memory,+ const char *original_name,+ const char *insertion );+++ typedef enum FT_RFork_Rule_ {+ FT_RFork_Rule_invalid = -2,+ FT_RFork_Rule_uknown, /* -1 */+ FT_RFork_Rule_apple_double,+ FT_RFork_Rule_apple_single,+ FT_RFork_Rule_darwin_ufs_export,+ FT_RFork_Rule_darwin_newvfs,+ FT_RFork_Rule_darwin_hfsplus,+ FT_RFork_Rule_vfat,+ FT_RFork_Rule_linux_cap,+ FT_RFork_Rule_linux_double,+ FT_RFork_Rule_linux_netatalk+ } FT_RFork_Rule;++ /* For fast translation between rule index and rule type,+ * the macros FT_RFORK_xxx should be kept consistent with+ * the raccess_guess_funcs table+ */+ typedef struct raccess_guess_rec_ {+ raccess_guess_func func;+ FT_RFork_Rule type;+ } raccess_guess_rec;++ static raccess_guess_rec raccess_guess_table[FT_RACCESS_N_RULES] =+ {+ { raccess_guess_apple_double, FT_RFork_Rule_apple_double, },+ { raccess_guess_apple_single, FT_RFork_Rule_apple_single, },+ { raccess_guess_darwin_ufs_export, FT_RFork_Rule_darwin_ufs_export, },+ { raccess_guess_darwin_newvfs, FT_RFork_Rule_darwin_newvfs, },+ { raccess_guess_darwin_hfsplus, FT_RFork_Rule_darwin_hfsplus, },+ { raccess_guess_vfat, FT_RFork_Rule_vfat, },+ { raccess_guess_linux_cap, FT_RFork_Rule_linux_cap, },+ { raccess_guess_linux_double, FT_RFork_Rule_linux_double, },+ { raccess_guess_linux_netatalk, FT_RFork_Rule_linux_netatalk, },+ };++ FT_BASE_DEF( void )+ FT_Raccess_Guess( FT_Library library,+ FT_Stream stream,+ char* base_name,+ char **new_names,+ FT_Long *offsets,+ FT_Error *errors )+ {+ FT_Long i;+++ for ( i = 0; i < FT_RACCESS_N_RULES; i++ )+ {+ new_names[i] = NULL;+ if ( NULL != stream )+ errors[i] = FT_Stream_Seek( stream, 0 );+ else+ errors[i] = FT_Err_Ok;++ if ( errors[i] )+ continue ;++ errors[i] = (raccess_guess_table[i].func)( library,+ stream, base_name,+ &(new_names[i]),+ &(offsets[i]) );+ }++ return;+ }+++ static FT_RFork_Rule+ raccess_get_rule_type_from_rule_index( FT_UInt rule_index )+ {+ if ( rule_index >= FT_RACCESS_N_RULES )+ return FT_RFork_Rule_invalid;++ return raccess_guess_table[rule_index].type;+ }+++ FT_LOCAL_DEF( FT_Bool )+ raccess_rule_by_darwin_vfs( FT_UInt rule_index )+ {+ switch( raccess_get_rule_type_from_rule_index( rule_index ) )+ {+ case FT_RFork_Rule_darwin_newvfs:+ case FT_RFork_Rule_darwin_hfsplus:+ return TRUE;++ default:+ return FALSE;+ }+ }+++ static FT_Error+ raccess_guess_apple_double( FT_Library library,+ FT_Stream stream,+ char *base_file_name,+ char **result_file_name,+ FT_Long *result_offset )+ {+ FT_Int32 magic = ( 0x00 << 24 ) |+ ( 0x05 << 16 ) |+ ( 0x16 << 8 ) |+ 0x07;+++ *result_file_name = NULL;+ if ( NULL == stream )+ return FT_Err_Cannot_Open_Stream;++ return raccess_guess_apple_generic( library, stream, base_file_name,+ magic, result_offset );+ }+++ static FT_Error+ raccess_guess_apple_single( FT_Library library,+ FT_Stream stream,+ char *base_file_name,+ char **result_file_name,+ FT_Long *result_offset )+ {+ FT_Int32 magic = ( 0x00 << 24 ) |+ ( 0x05 << 16 ) |+ ( 0x16 << 8 ) |+ 0x00;+++ *result_file_name = NULL;+ if ( NULL == stream )+ return FT_Err_Cannot_Open_Stream;++ return raccess_guess_apple_generic( library, stream, base_file_name,+ magic, result_offset );+ }+++ static FT_Error+ raccess_guess_darwin_ufs_export( FT_Library library,+ FT_Stream stream,+ char *base_file_name,+ char **result_file_name,+ FT_Long *result_offset )+ {+ char* newpath;+ FT_Error error;+ FT_Memory memory;++ FT_UNUSED( stream );+++ memory = library->memory;+ newpath = raccess_make_file_name( memory, base_file_name, "._" );+ if ( !newpath )+ return FT_Err_Out_Of_Memory;++ error = raccess_guess_linux_double_from_file_name( library, newpath,+ result_offset );+ if ( !error )+ *result_file_name = newpath;+ else+ FT_FREE( newpath );++ return error;+ }+++ static FT_Error+ raccess_guess_darwin_hfsplus( FT_Library library,+ FT_Stream stream,+ char *base_file_name,+ char **result_file_name,+ FT_Long *result_offset )+ {+ /*+ Only meaningful on systems with hfs+ drivers (or Macs).+ */+ FT_Error error;+ char* newpath;+ FT_Memory memory;+ FT_Long base_file_len = ft_strlen( base_file_name );++ FT_UNUSED( stream );+++ memory = library->memory;++ if ( base_file_len + 6 > FT_INT_MAX )+ return FT_Err_Array_Too_Large;++ if ( FT_ALLOC( newpath, base_file_len + 6 ) )+ return error;++ FT_MEM_COPY( newpath, base_file_name, base_file_len );+ FT_MEM_COPY( newpath + base_file_len, "/rsrc", 6 );++ *result_file_name = newpath;+ *result_offset = 0;++ return FT_Err_Ok;+ }+++ static FT_Error+ raccess_guess_darwin_newvfs( FT_Library library,+ FT_Stream stream,+ char *base_file_name,+ char **result_file_name,+ FT_Long *result_offset )+ {+ /*+ Only meaningful on systems with Mac OS X (> 10.1).+ */+ FT_Error error;+ char* newpath;+ FT_Memory memory;+ FT_Long base_file_len = ft_strlen( base_file_name );++ FT_UNUSED( stream );+++ memory = library->memory;++ if ( base_file_len + 18 > FT_INT_MAX )+ return FT_Err_Array_Too_Large;++ if ( FT_ALLOC( newpath, base_file_len + 18 ) )+ return error;++ FT_MEM_COPY( newpath, base_file_name, base_file_len );+ FT_MEM_COPY( newpath + base_file_len, "/..namedfork/rsrc", 18 );++ *result_file_name = newpath;+ *result_offset = 0;++ return FT_Err_Ok;+ }+++ static FT_Error+ raccess_guess_vfat( FT_Library library,+ FT_Stream stream,+ char *base_file_name,+ char **result_file_name,+ FT_Long *result_offset )+ {+ char* newpath;+ FT_Memory memory;++ FT_UNUSED( stream );+++ memory = library->memory;++ newpath = raccess_make_file_name( memory, base_file_name,+ "resource.frk/" );+ if ( !newpath )+ return FT_Err_Out_Of_Memory;++ *result_file_name = newpath;+ *result_offset = 0;++ return FT_Err_Ok;+ }+++ static FT_Error+ raccess_guess_linux_cap( FT_Library library,+ FT_Stream stream,+ char *base_file_name,+ char **result_file_name,+ FT_Long *result_offset )+ {+ char* newpath;+ FT_Memory memory;++ FT_UNUSED( stream );+++ memory = library->memory;++ newpath = raccess_make_file_name( memory, base_file_name, ".resource/" );+ if ( !newpath )+ return FT_Err_Out_Of_Memory;++ *result_file_name = newpath;+ *result_offset = 0;++ return FT_Err_Ok;+ }+++ static FT_Error+ raccess_guess_linux_double( FT_Library library,+ FT_Stream stream,+ char *base_file_name,+ char **result_file_name,+ FT_Long *result_offset )+ {+ char* newpath;+ FT_Error error;+ FT_Memory memory;++ FT_UNUSED( stream );+++ memory = library->memory;++ newpath = raccess_make_file_name( memory, base_file_name, "%" );+ if ( !newpath )+ return FT_Err_Out_Of_Memory;++ error = raccess_guess_linux_double_from_file_name( library, newpath,+ result_offset );+ if ( !error )+ *result_file_name = newpath;+ else+ FT_FREE( newpath );++ return error;+ }+++ static FT_Error+ raccess_guess_linux_netatalk( FT_Library library,+ FT_Stream stream,+ char *base_file_name,+ char **result_file_name,+ FT_Long *result_offset )+ {+ char* newpath;+ FT_Error error;+ FT_Memory memory;++ FT_UNUSED( stream );+++ memory = library->memory;++ newpath = raccess_make_file_name( memory, base_file_name,+ ".AppleDouble/" );+ if ( !newpath )+ return FT_Err_Out_Of_Memory;++ error = raccess_guess_linux_double_from_file_name( library, newpath,+ result_offset );+ if ( !error )+ *result_file_name = newpath;+ else+ FT_FREE( newpath );++ return error;+ }+++ static FT_Error+ raccess_guess_apple_generic( FT_Library library,+ FT_Stream stream,+ char *base_file_name,+ FT_Int32 magic,+ FT_Long *result_offset )+ {+ FT_Int32 magic_from_stream;+ FT_Error error;+ FT_Int32 version_number = 0;+ FT_UShort n_of_entries;++ int i;+ FT_UInt32 entry_id, entry_offset, entry_length = 0;++ const FT_UInt32 resource_fork_entry_id = 0x2;++ FT_UNUSED( library );+ FT_UNUSED( base_file_name );+ FT_UNUSED( version_number );+ FT_UNUSED( entry_length );+++ if ( FT_READ_LONG( magic_from_stream ) )+ return error;+ if ( magic_from_stream != magic )+ return FT_Err_Unknown_File_Format;++ if ( FT_READ_LONG( version_number ) )+ return error;++ /* filler */+ error = FT_Stream_Skip( stream, 16 );+ if ( error )+ return error;++ if ( FT_READ_USHORT( n_of_entries ) )+ return error;+ if ( n_of_entries == 0 )+ return FT_Err_Unknown_File_Format;++ for ( i = 0; i < n_of_entries; i++ )+ {+ if ( FT_READ_LONG( entry_id ) )+ return error;+ if ( entry_id == resource_fork_entry_id )+ {+ if ( FT_READ_LONG( entry_offset ) ||+ FT_READ_LONG( entry_length ) )+ continue;+ *result_offset = entry_offset;++ return FT_Err_Ok;+ }+ else+ {+ error = FT_Stream_Skip( stream, 4 + 4 ); /* offset + length */+ if ( error )+ return error;+ }+ }++ return FT_Err_Unknown_File_Format;+ }+++ static FT_Error+ raccess_guess_linux_double_from_file_name( FT_Library library,+ char *file_name,+ FT_Long *result_offset )+ {+ FT_Open_Args args2;+ FT_Stream stream2;+ char * nouse = NULL;+ FT_Error error;+++ args2.flags = FT_OPEN_PATHNAME;+ args2.pathname = file_name;+ error = FT_Stream_New( library, &args2, &stream2 );+ if ( error )+ return error;++ error = raccess_guess_apple_double( library, stream2, file_name,+ &nouse, result_offset );++ FT_Stream_Free( stream2, 0 );++ return error;+ }+++ static char*+ raccess_make_file_name( FT_Memory memory,+ const char *original_name,+ const char *insertion )+ {+ char* new_name = NULL;+ const char* tmp;+ const char* slash;+ size_t new_length;+ FT_Error error = FT_Err_Ok;++ FT_UNUSED( error );+++ new_length = ft_strlen( original_name ) + ft_strlen( insertion );+ if ( FT_ALLOC( new_name, new_length + 1 ) )+ return NULL;++ tmp = ft_strrchr( original_name, '/' );+ if ( tmp )+ {+ ft_strncpy( new_name, original_name, tmp - original_name + 1 );+ new_name[tmp - original_name + 1] = '\0';+ slash = tmp + 1;+ }+ else+ {+ slash = original_name;+ new_name[0] = '\0';+ }++ ft_strcat( new_name, insertion );+ ft_strcat( new_name, slash );++ return new_name;+ }+++#else /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */+++ /*************************************************************************/+ /* Dummy function; just sets errors */+ /*************************************************************************/++ FT_BASE_DEF( void )+ FT_Raccess_Guess( FT_Library library,+ FT_Stream stream,+ char *base_name,+ char **new_names,+ FT_Long *offsets,+ FT_Error *errors )+ {+ int i;++ FT_UNUSED( library );+ FT_UNUSED( stream );+ FT_UNUSED( base_name );+++ for ( i = 0; i < FT_RACCESS_N_RULES; i++ )+ {+ new_names[i] = NULL;+ offsets[i] = 0;+ errors[i] = FT_Err_Unimplemented_Feature;+ }+ }+++#endif /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */+++/* END */
+ src/base/ftsnames.c view
@@ -0,0 +1,94 @@+/***************************************************************************/+/* */+/* ftsnames.c */+/* */+/* Simple interface to access SFNT name tables (which are used */+/* to hold font names, copyright info, notices, etc.) (body). */+/* */+/* This is _not_ used to retrieve glyph names! */+/* */+/* Copyright 1996-2001, 2002, 2009 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_SFNT_NAMES_H+#include FT_INTERNAL_TRUETYPE_TYPES_H+#include FT_INTERNAL_STREAM_H+++#ifdef TT_CONFIG_OPTION_SFNT_NAMES+++ /* documentation is in ftsnames.h */++ FT_EXPORT_DEF( FT_UInt )+ FT_Get_Sfnt_Name_Count( FT_Face face )+ {+ return ( face && FT_IS_SFNT( face ) ) ? ((TT_Face)face)->num_names : 0;+ }+++ /* documentation is in ftsnames.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Get_Sfnt_Name( FT_Face face,+ FT_UInt idx,+ FT_SfntName *aname )+ {+ FT_Error error = FT_Err_Invalid_Argument;+++ if ( aname && face && FT_IS_SFNT( face ) )+ {+ TT_Face ttface = (TT_Face)face;+++ if ( idx < (FT_UInt)ttface->num_names )+ {+ TT_NameEntryRec* entry = ttface->name_table.names + idx;+++ /* load name on demand */+ if ( entry->stringLength > 0 && entry->string == NULL )+ {+ FT_Memory memory = face->memory;+ FT_Stream stream = face->stream;+++ if ( FT_NEW_ARRAY ( entry->string, entry->stringLength ) ||+ FT_STREAM_SEEK( entry->stringOffset ) ||+ FT_STREAM_READ( entry->string, entry->stringLength ) )+ {+ FT_FREE( entry->string );+ entry->stringLength = 0;+ }+ }++ aname->platform_id = entry->platformID;+ aname->encoding_id = entry->encodingID;+ aname->language_id = entry->languageID;+ aname->name_id = entry->nameID;+ aname->string = (FT_Byte*)entry->string;+ aname->string_len = entry->stringLength;++ error = FT_Err_Ok;+ }+ }++ return error;+ }+++#endif /* TT_CONFIG_OPTION_SFNT_NAMES */+++/* END */
+ src/base/ftstream.c view
@@ -0,0 +1,864 @@+/***************************************************************************/+/* */+/* ftstream.c */+/* */+/* I/O stream support (body). */+/* */+/* Copyright 2000-2001, 2002, 2004, 2005, 2006, 2008, 2009, 2010 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_STREAM_H+#include FT_INTERNAL_DEBUG_H+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_stream+++ FT_BASE_DEF( void )+ FT_Stream_OpenMemory( FT_Stream stream,+ const FT_Byte* base,+ FT_ULong size )+ {+ stream->base = (FT_Byte*) base;+ stream->size = size;+ stream->pos = 0;+ stream->cursor = 0;+ stream->read = 0;+ stream->close = 0;+ }+++ FT_BASE_DEF( void )+ FT_Stream_Close( FT_Stream stream )+ {+ if ( stream && stream->close )+ stream->close( stream );+ }+++ FT_BASE_DEF( FT_Error )+ FT_Stream_Seek( FT_Stream stream,+ FT_ULong pos )+ {+ FT_Error error = FT_Err_Ok;+++ if ( stream->read )+ {+ if ( stream->read( stream, pos, 0, 0 ) )+ {+ FT_ERROR(( "FT_Stream_Seek:"+ " invalid i/o; pos = 0x%lx, size = 0x%lx\n",+ pos, stream->size ));++ error = FT_Err_Invalid_Stream_Operation;+ }+ }+ /* note that seeking to the first position after the file is valid */+ else if ( pos > stream->size )+ {+ FT_ERROR(( "FT_Stream_Seek:"+ " invalid i/o; pos = 0x%lx, size = 0x%lx\n",+ pos, stream->size ));++ error = FT_Err_Invalid_Stream_Operation;+ }++ if ( !error )+ stream->pos = pos;++ return error;+ }+++ FT_BASE_DEF( FT_Error )+ FT_Stream_Skip( FT_Stream stream,+ FT_Long distance )+ {+ if ( distance < 0 )+ return FT_Err_Invalid_Stream_Operation;++ return FT_Stream_Seek( stream, (FT_ULong)( stream->pos + distance ) );+ }+++ FT_BASE_DEF( FT_Long )+ FT_Stream_Pos( FT_Stream stream )+ {+ return stream->pos;+ }+++ FT_BASE_DEF( FT_Error )+ FT_Stream_Read( FT_Stream stream,+ FT_Byte* buffer,+ FT_ULong count )+ {+ return FT_Stream_ReadAt( stream, stream->pos, buffer, count );+ }+++ FT_BASE_DEF( FT_Error )+ FT_Stream_ReadAt( FT_Stream stream,+ FT_ULong pos,+ FT_Byte* buffer,+ FT_ULong count )+ {+ FT_Error error = FT_Err_Ok;+ FT_ULong read_bytes;+++ if ( pos >= stream->size )+ {+ FT_ERROR(( "FT_Stream_ReadAt:"+ " invalid i/o; pos = 0x%lx, size = 0x%lx\n",+ pos, stream->size ));++ return FT_Err_Invalid_Stream_Operation;+ }++ if ( stream->read )+ read_bytes = stream->read( stream, pos, buffer, count );+ else+ {+ read_bytes = stream->size - pos;+ if ( read_bytes > count )+ read_bytes = count;++ FT_MEM_COPY( buffer, stream->base + pos, read_bytes );+ }++ stream->pos = pos + read_bytes;++ if ( read_bytes < count )+ {+ FT_ERROR(( "FT_Stream_ReadAt:"+ " invalid read; expected %lu bytes, got %lu\n",+ count, read_bytes ));++ error = FT_Err_Invalid_Stream_Operation;+ }++ return error;+ }+++ FT_BASE_DEF( FT_ULong )+ FT_Stream_TryRead( FT_Stream stream,+ FT_Byte* buffer,+ FT_ULong count )+ {+ FT_ULong read_bytes = 0;+++ if ( stream->pos >= stream->size )+ goto Exit;++ if ( stream->read )+ read_bytes = stream->read( stream, stream->pos, buffer, count );+ else+ {+ read_bytes = stream->size - stream->pos;+ if ( read_bytes > count )+ read_bytes = count;++ FT_MEM_COPY( buffer, stream->base + stream->pos, read_bytes );+ }++ stream->pos += read_bytes;++ Exit:+ return read_bytes;+ }+++ FT_BASE_DEF( FT_Error )+ FT_Stream_ExtractFrame( FT_Stream stream,+ FT_ULong count,+ FT_Byte** pbytes )+ {+ FT_Error error;+++ error = FT_Stream_EnterFrame( stream, count );+ if ( !error )+ {+ *pbytes = (FT_Byte*)stream->cursor;++ /* equivalent to FT_Stream_ExitFrame(), with no memory block release */+ stream->cursor = 0;+ stream->limit = 0;+ }++ return error;+ }+++ FT_BASE_DEF( void )+ FT_Stream_ReleaseFrame( FT_Stream stream,+ FT_Byte** pbytes )+ {+ if ( stream && stream->read )+ {+ FT_Memory memory = stream->memory;++#ifdef FT_DEBUG_MEMORY+ ft_mem_free( memory, *pbytes );+ *pbytes = NULL;+#else+ FT_FREE( *pbytes );+#endif+ }+ *pbytes = 0;+ }+++ FT_BASE_DEF( FT_Error )+ FT_Stream_EnterFrame( FT_Stream stream,+ FT_ULong count )+ {+ FT_Error error = FT_Err_Ok;+ FT_ULong read_bytes;+++ /* check for nested frame access */+ FT_ASSERT( stream && stream->cursor == 0 );++ if ( stream->read )+ {+ /* allocate the frame in memory */+ FT_Memory memory = stream->memory;+++ /* simple sanity check */+ if ( count > stream->size )+ {+ FT_ERROR(( "FT_Stream_EnterFrame:"+ " frame size (%lu) larger than stream size (%lu)\n",+ count, stream->size ));++ error = FT_Err_Invalid_Stream_Operation;+ goto Exit;+ }++#ifdef FT_DEBUG_MEMORY+ /* assume _ft_debug_file and _ft_debug_lineno are already set */+ stream->base = (unsigned char*)ft_mem_qalloc( memory, count, &error );+ if ( error )+ goto Exit;+#else+ if ( FT_QALLOC( stream->base, count ) )+ goto Exit;+#endif+ /* read it */+ read_bytes = stream->read( stream, stream->pos,+ stream->base, count );+ if ( read_bytes < count )+ {+ FT_ERROR(( "FT_Stream_EnterFrame:"+ " invalid read; expected %lu bytes, got %lu\n",+ count, read_bytes ));++ FT_FREE( stream->base );+ error = FT_Err_Invalid_Stream_Operation;+ }+ stream->cursor = stream->base;+ stream->limit = stream->cursor + count;+ stream->pos += read_bytes;+ }+ else+ {+ /* check current and new position */+ if ( stream->pos >= stream->size ||+ stream->size - stream->pos < count )+ {+ FT_ERROR(( "FT_Stream_EnterFrame:"+ " invalid i/o; pos = 0x%lx, count = %lu, size = 0x%lx\n",+ stream->pos, count, stream->size ));++ error = FT_Err_Invalid_Stream_Operation;+ goto Exit;+ }++ /* set cursor */+ stream->cursor = stream->base + stream->pos;+ stream->limit = stream->cursor + count;+ stream->pos += count;+ }++ Exit:+ return error;+ }+++ FT_BASE_DEF( void )+ FT_Stream_ExitFrame( FT_Stream stream )+ {+ /* IMPORTANT: The assertion stream->cursor != 0 was removed, given */+ /* that it is possible to access a frame of length 0 in */+ /* some weird fonts (usually, when accessing an array of */+ /* 0 records, like in some strange kern tables). */+ /* */+ /* In this case, the loader code handles the 0-length table */+ /* gracefully; however, stream.cursor is really set to 0 by the */+ /* FT_Stream_EnterFrame() call, and this is not an error. */+ /* */+ FT_ASSERT( stream );++ if ( stream->read )+ {+ FT_Memory memory = stream->memory;++#ifdef FT_DEBUG_MEMORY+ ft_mem_free( memory, stream->base );+ stream->base = NULL;+#else+ FT_FREE( stream->base );+#endif+ }+ stream->cursor = 0;+ stream->limit = 0;+ }+++ FT_BASE_DEF( FT_Char )+ FT_Stream_GetChar( FT_Stream stream )+ {+ FT_Char result;+++ FT_ASSERT( stream && stream->cursor );++ result = 0;+ if ( stream->cursor < stream->limit )+ result = *stream->cursor++;++ return result;+ }+++ FT_BASE_DEF( FT_Short )+ FT_Stream_GetShort( FT_Stream stream )+ {+ FT_Byte* p;+ FT_Short result;+++ FT_ASSERT( stream && stream->cursor );++ result = 0;+ p = stream->cursor;+ if ( p + 1 < stream->limit )+ result = FT_NEXT_SHORT( p );+ stream->cursor = p;++ return result;+ }+++ FT_BASE_DEF( FT_Short )+ FT_Stream_GetShortLE( FT_Stream stream )+ {+ FT_Byte* p;+ FT_Short result;+++ FT_ASSERT( stream && stream->cursor );++ result = 0;+ p = stream->cursor;+ if ( p + 1 < stream->limit )+ result = FT_NEXT_SHORT_LE( p );+ stream->cursor = p;++ return result;+ }+++ FT_BASE_DEF( FT_Long )+ FT_Stream_GetOffset( FT_Stream stream )+ {+ FT_Byte* p;+ FT_Long result;+++ FT_ASSERT( stream && stream->cursor );++ result = 0;+ p = stream->cursor;+ if ( p + 2 < stream->limit )+ result = FT_NEXT_OFF3( p );+ stream->cursor = p;+ return result;+ }+++ FT_BASE_DEF( FT_Long )+ FT_Stream_GetLong( FT_Stream stream )+ {+ FT_Byte* p;+ FT_Long result;+++ FT_ASSERT( stream && stream->cursor );++ result = 0;+ p = stream->cursor;+ if ( p + 3 < stream->limit )+ result = FT_NEXT_LONG( p );+ stream->cursor = p;+ return result;+ }+++ FT_BASE_DEF( FT_Long )+ FT_Stream_GetLongLE( FT_Stream stream )+ {+ FT_Byte* p;+ FT_Long result;+++ FT_ASSERT( stream && stream->cursor );++ result = 0;+ p = stream->cursor;+ if ( p + 3 < stream->limit )+ result = FT_NEXT_LONG_LE( p );+ stream->cursor = p;+ return result;+ }+++ FT_BASE_DEF( FT_Char )+ FT_Stream_ReadChar( FT_Stream stream,+ FT_Error* error )+ {+ FT_Byte result = 0;+++ FT_ASSERT( stream );++ *error = FT_Err_Ok;++ if ( stream->read )+ {+ if ( stream->read( stream, stream->pos, &result, 1L ) != 1L )+ goto Fail;+ }+ else+ {+ if ( stream->pos < stream->size )+ result = stream->base[stream->pos];+ else+ goto Fail;+ }+ stream->pos++;++ return result;++ Fail:+ *error = FT_Err_Invalid_Stream_Operation;+ FT_ERROR(( "FT_Stream_ReadChar:"+ " invalid i/o; pos = 0x%lx, size = 0x%lx\n",+ stream->pos, stream->size ));++ return 0;+ }+++ FT_BASE_DEF( FT_Short )+ FT_Stream_ReadShort( FT_Stream stream,+ FT_Error* error )+ {+ FT_Byte reads[2];+ FT_Byte* p = 0;+ FT_Short result = 0;+++ FT_ASSERT( stream );++ *error = FT_Err_Ok;++ if ( stream->pos + 1 < stream->size )+ {+ if ( stream->read )+ {+ if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )+ goto Fail;++ p = reads;+ }+ else+ {+ p = stream->base + stream->pos;+ }++ if ( p )+ result = FT_NEXT_SHORT( p );+ }+ else+ goto Fail;++ stream->pos += 2;++ return result;++ Fail:+ *error = FT_Err_Invalid_Stream_Operation;+ FT_ERROR(( "FT_Stream_ReadShort:"+ " invalid i/o; pos = 0x%lx, size = 0x%lx\n",+ stream->pos, stream->size ));++ return 0;+ }+++ FT_BASE_DEF( FT_Short )+ FT_Stream_ReadShortLE( FT_Stream stream,+ FT_Error* error )+ {+ FT_Byte reads[2];+ FT_Byte* p = 0;+ FT_Short result = 0;+++ FT_ASSERT( stream );++ *error = FT_Err_Ok;++ if ( stream->pos + 1 < stream->size )+ {+ if ( stream->read )+ {+ if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )+ goto Fail;++ p = reads;+ }+ else+ {+ p = stream->base + stream->pos;+ }++ if ( p )+ result = FT_NEXT_SHORT_LE( p );+ }+ else+ goto Fail;++ stream->pos += 2;++ return result;++ Fail:+ *error = FT_Err_Invalid_Stream_Operation;+ FT_ERROR(( "FT_Stream_ReadShortLE:"+ " invalid i/o; pos = 0x%lx, size = 0x%lx\n",+ stream->pos, stream->size ));++ return 0;+ }+++ FT_BASE_DEF( FT_Long )+ FT_Stream_ReadOffset( FT_Stream stream,+ FT_Error* error )+ {+ FT_Byte reads[3];+ FT_Byte* p = 0;+ FT_Long result = 0;+++ FT_ASSERT( stream );++ *error = FT_Err_Ok;++ if ( stream->pos + 2 < stream->size )+ {+ if ( stream->read )+ {+ if (stream->read( stream, stream->pos, reads, 3L ) != 3L )+ goto Fail;++ p = reads;+ }+ else+ {+ p = stream->base + stream->pos;+ }++ if ( p )+ result = FT_NEXT_OFF3( p );+ }+ else+ goto Fail;++ stream->pos += 3;++ return result;++ Fail:+ *error = FT_Err_Invalid_Stream_Operation;+ FT_ERROR(( "FT_Stream_ReadOffset:"+ " invalid i/o; pos = 0x%lx, size = 0x%lx\n",+ stream->pos, stream->size ));++ return 0;+ }+++ FT_BASE_DEF( FT_Long )+ FT_Stream_ReadLong( FT_Stream stream,+ FT_Error* error )+ {+ FT_Byte reads[4];+ FT_Byte* p = 0;+ FT_Long result = 0;+++ FT_ASSERT( stream );++ *error = FT_Err_Ok;++ if ( stream->pos + 3 < stream->size )+ {+ if ( stream->read )+ {+ if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )+ goto Fail;++ p = reads;+ }+ else+ {+ p = stream->base + stream->pos;+ }++ if ( p )+ result = FT_NEXT_LONG( p );+ }+ else+ goto Fail;++ stream->pos += 4;++ return result;++ Fail:+ *error = FT_Err_Invalid_Stream_Operation;+ FT_ERROR(( "FT_Stream_ReadLong:"+ " invalid i/o; pos = 0x%lx, size = 0x%lx\n",+ stream->pos, stream->size ));++ return 0;+ }+++ FT_BASE_DEF( FT_Long )+ FT_Stream_ReadLongLE( FT_Stream stream,+ FT_Error* error )+ {+ FT_Byte reads[4];+ FT_Byte* p = 0;+ FT_Long result = 0;+++ FT_ASSERT( stream );++ *error = FT_Err_Ok;++ if ( stream->pos + 3 < stream->size )+ {+ if ( stream->read )+ {+ if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )+ goto Fail;++ p = reads;+ }+ else+ {+ p = stream->base + stream->pos;+ }++ if ( p )+ result = FT_NEXT_LONG_LE( p );+ }+ else+ goto Fail;++ stream->pos += 4;++ return result;++ Fail:+ *error = FT_Err_Invalid_Stream_Operation;+ FT_ERROR(( "FT_Stream_ReadLongLE:"+ " invalid i/o; pos = 0x%lx, size = 0x%lx\n",+ stream->pos, stream->size ));++ return 0;+ }+++ FT_BASE_DEF( FT_Error )+ FT_Stream_ReadFields( FT_Stream stream,+ const FT_Frame_Field* fields,+ void* structure )+ {+ FT_Error error;+ FT_Bool frame_accessed = 0;+ FT_Byte* cursor;++ if ( !fields || !stream )+ return FT_Err_Invalid_Argument;++ cursor = stream->cursor;++ error = FT_Err_Ok;+ do+ {+ FT_ULong value;+ FT_Int sign_shift;+ FT_Byte* p;+++ switch ( fields->value )+ {+ case ft_frame_start: /* access a new frame */+ error = FT_Stream_EnterFrame( stream, fields->offset );+ if ( error )+ goto Exit;++ frame_accessed = 1;+ cursor = stream->cursor;+ fields++;+ continue; /* loop! */++ case ft_frame_bytes: /* read a byte sequence */+ case ft_frame_skip: /* skip some bytes */+ {+ FT_UInt len = fields->size;+++ if ( cursor + len > stream->limit )+ {+ error = FT_Err_Invalid_Stream_Operation;+ goto Exit;+ }++ if ( fields->value == ft_frame_bytes )+ {+ p = (FT_Byte*)structure + fields->offset;+ FT_MEM_COPY( p, cursor, len );+ }+ cursor += len;+ fields++;+ continue;+ }++ case ft_frame_byte:+ case ft_frame_schar: /* read a single byte */+ value = FT_NEXT_BYTE(cursor);+ sign_shift = 24;+ break;++ case ft_frame_short_be:+ case ft_frame_ushort_be: /* read a 2-byte big-endian short */+ value = FT_NEXT_USHORT(cursor);+ sign_shift = 16;+ break;++ case ft_frame_short_le:+ case ft_frame_ushort_le: /* read a 2-byte little-endian short */+ value = FT_NEXT_USHORT_LE(cursor);+ sign_shift = 16;+ break;++ case ft_frame_long_be:+ case ft_frame_ulong_be: /* read a 4-byte big-endian long */+ value = FT_NEXT_ULONG(cursor);+ sign_shift = 0;+ break;++ case ft_frame_long_le:+ case ft_frame_ulong_le: /* read a 4-byte little-endian long */+ value = FT_NEXT_ULONG_LE(cursor);+ sign_shift = 0;+ break;++ case ft_frame_off3_be:+ case ft_frame_uoff3_be: /* read a 3-byte big-endian long */+ value = FT_NEXT_UOFF3(cursor);+ sign_shift = 8;+ break;++ case ft_frame_off3_le:+ case ft_frame_uoff3_le: /* read a 3-byte little-endian long */+ value = FT_NEXT_UOFF3_LE(cursor);+ sign_shift = 8;+ break;++ default:+ /* otherwise, exit the loop */+ stream->cursor = cursor;+ goto Exit;+ }++ /* now, compute the signed value is necessary */+ if ( fields->value & FT_FRAME_OP_SIGNED )+ value = (FT_ULong)( (FT_Int32)( value << sign_shift ) >> sign_shift );++ /* finally, store the value in the object */++ p = (FT_Byte*)structure + fields->offset;+ switch ( fields->size )+ {+ case (8 / FT_CHAR_BIT):+ *(FT_Byte*)p = (FT_Byte)value;+ break;++ case (16 / FT_CHAR_BIT):+ *(FT_UShort*)p = (FT_UShort)value;+ break;++ case (32 / FT_CHAR_BIT):+ *(FT_UInt32*)p = (FT_UInt32)value;+ break;++ default: /* for 64-bit systems */+ *(FT_ULong*)p = (FT_ULong)value;+ }++ /* go to next field */+ fields++;+ }+ while ( 1 );++ Exit:+ /* close the frame if it was opened by this read */+ if ( frame_accessed )+ FT_Stream_ExitFrame( stream );++ return error;+ }+++/* END */
+ src/base/ftstroke.c view
@@ -0,0 +1,2039 @@+/***************************************************************************/+/* */+/* ftstroke.c */+/* */+/* FreeType path stroker (body). */+/* */+/* Copyright 2002, 2003, 2004, 2005, 2006, 2008, 2009, 2010 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_STROKER_H+#include FT_TRIGONOMETRY_H+#include FT_OUTLINE_H+#include FT_INTERNAL_MEMORY_H+#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_OBJECTS_H+++ /* documentation is in ftstroke.h */++ FT_EXPORT_DEF( FT_StrokerBorder )+ FT_Outline_GetInsideBorder( FT_Outline* outline )+ {+ FT_Orientation o = FT_Outline_Get_Orientation( outline );+++ return o == FT_ORIENTATION_TRUETYPE ? FT_STROKER_BORDER_RIGHT+ : FT_STROKER_BORDER_LEFT ;+ }+++ /* documentation is in ftstroke.h */++ FT_EXPORT_DEF( FT_StrokerBorder )+ FT_Outline_GetOutsideBorder( FT_Outline* outline )+ {+ FT_Orientation o = FT_Outline_Get_Orientation( outline );+++ return o == FT_ORIENTATION_TRUETYPE ? FT_STROKER_BORDER_LEFT+ : FT_STROKER_BORDER_RIGHT ;+ }+++ /***************************************************************************/+ /***************************************************************************/+ /***** *****/+ /***** BEZIER COMPUTATIONS *****/+ /***** *****/+ /***************************************************************************/+ /***************************************************************************/++#define FT_SMALL_CONIC_THRESHOLD ( FT_ANGLE_PI / 6 )+#define FT_SMALL_CUBIC_THRESHOLD ( FT_ANGLE_PI / 6 )+#define FT_EPSILON 2++#define FT_IS_SMALL( x ) ( (x) > -FT_EPSILON && (x) < FT_EPSILON )+++ static FT_Pos+ ft_pos_abs( FT_Pos x )+ {+ return x >= 0 ? x : -x ;+ }+++ static void+ ft_conic_split( FT_Vector* base )+ {+ FT_Pos a, b;+++ base[4].x = base[2].x;+ b = base[1].x;+ a = base[3].x = ( base[2].x + b ) / 2;+ b = base[1].x = ( base[0].x + b ) / 2;+ base[2].x = ( a + b ) / 2;++ base[4].y = base[2].y;+ b = base[1].y;+ a = base[3].y = ( base[2].y + b ) / 2;+ b = base[1].y = ( base[0].y + b ) / 2;+ base[2].y = ( a + b ) / 2;+ }+++ static FT_Bool+ ft_conic_is_small_enough( FT_Vector* base,+ FT_Angle *angle_in,+ FT_Angle *angle_out )+ {+ FT_Vector d1, d2;+ FT_Angle theta;+ FT_Int close1, close2;+++ d1.x = base[1].x - base[2].x;+ d1.y = base[1].y - base[2].y;+ d2.x = base[0].x - base[1].x;+ d2.y = base[0].y - base[1].y;++ close1 = FT_IS_SMALL( d1.x ) && FT_IS_SMALL( d1.y );+ close2 = FT_IS_SMALL( d2.x ) && FT_IS_SMALL( d2.y );++ if ( close1 )+ {+ if ( close2 )+ *angle_in = *angle_out = 0;+ else+ *angle_in = *angle_out = FT_Atan2( d2.x, d2.y );+ }+ else if ( close2 )+ {+ *angle_in = *angle_out = FT_Atan2( d1.x, d1.y );+ }+ else+ {+ *angle_in = FT_Atan2( d1.x, d1.y );+ *angle_out = FT_Atan2( d2.x, d2.y );+ }++ theta = ft_pos_abs( FT_Angle_Diff( *angle_in, *angle_out ) );++ return FT_BOOL( theta < FT_SMALL_CONIC_THRESHOLD );+ }+++ static void+ ft_cubic_split( FT_Vector* base )+ {+ FT_Pos a, b, c, d;+++ base[6].x = base[3].x;+ c = base[1].x;+ d = base[2].x;+ base[1].x = a = ( base[0].x + c ) / 2;+ base[5].x = b = ( base[3].x + d ) / 2;+ c = ( c + d ) / 2;+ base[2].x = a = ( a + c ) / 2;+ base[4].x = b = ( b + c ) / 2;+ base[3].x = ( a + b ) / 2;++ base[6].y = base[3].y;+ c = base[1].y;+ d = base[2].y;+ base[1].y = a = ( base[0].y + c ) / 2;+ base[5].y = b = ( base[3].y + d ) / 2;+ c = ( c + d ) / 2;+ base[2].y = a = ( a + c ) / 2;+ base[4].y = b = ( b + c ) / 2;+ base[3].y = ( a + b ) / 2;+ }+++ static FT_Bool+ ft_cubic_is_small_enough( FT_Vector* base,+ FT_Angle *angle_in,+ FT_Angle *angle_mid,+ FT_Angle *angle_out )+ {+ FT_Vector d1, d2, d3;+ FT_Angle theta1, theta2;+ FT_Int close1, close2, close3;+++ d1.x = base[2].x - base[3].x;+ d1.y = base[2].y - base[3].y;+ d2.x = base[1].x - base[2].x;+ d2.y = base[1].y - base[2].y;+ d3.x = base[0].x - base[1].x;+ d3.y = base[0].y - base[1].y;++ close1 = FT_IS_SMALL( d1.x ) && FT_IS_SMALL( d1.y );+ close2 = FT_IS_SMALL( d2.x ) && FT_IS_SMALL( d2.y );+ close3 = FT_IS_SMALL( d3.x ) && FT_IS_SMALL( d3.y );++ if ( close1 || close3 )+ {+ if ( close2 )+ {+ /* basically a point */+ *angle_in = *angle_out = *angle_mid = 0;+ }+ else if ( close1 )+ {+ *angle_in = *angle_mid = FT_Atan2( d2.x, d2.y );+ *angle_out = FT_Atan2( d3.x, d3.y );+ }+ else /* close2 */+ {+ *angle_in = FT_Atan2( d1.x, d1.y );+ *angle_mid = *angle_out = FT_Atan2( d2.x, d2.y );+ }+ }+ else if ( close2 )+ {+ *angle_in = *angle_mid = FT_Atan2( d1.x, d1.y );+ *angle_out = FT_Atan2( d3.x, d3.y );+ }+ else+ {+ *angle_in = FT_Atan2( d1.x, d1.y );+ *angle_mid = FT_Atan2( d2.x, d2.y );+ *angle_out = FT_Atan2( d3.x, d3.y );+ }++ theta1 = ft_pos_abs( FT_Angle_Diff( *angle_in, *angle_mid ) );+ theta2 = ft_pos_abs( FT_Angle_Diff( *angle_mid, *angle_out ) );++ return FT_BOOL( theta1 < FT_SMALL_CUBIC_THRESHOLD &&+ theta2 < FT_SMALL_CUBIC_THRESHOLD );+ }+++ /***************************************************************************/+ /***************************************************************************/+ /***** *****/+ /***** STROKE BORDERS *****/+ /***** *****/+ /***************************************************************************/+ /***************************************************************************/++ typedef enum FT_StrokeTags_+ {+ FT_STROKE_TAG_ON = 1, /* on-curve point */+ FT_STROKE_TAG_CUBIC = 2, /* cubic off-point */+ FT_STROKE_TAG_BEGIN = 4, /* sub-path start */+ FT_STROKE_TAG_END = 8 /* sub-path end */++ } FT_StrokeTags;++#define FT_STROKE_TAG_BEGIN_END (FT_STROKE_TAG_BEGIN|FT_STROKE_TAG_END)++ typedef struct FT_StrokeBorderRec_+ {+ FT_UInt num_points;+ FT_UInt max_points;+ FT_Vector* points;+ FT_Byte* tags;+ FT_Bool movable;+ FT_Int start; /* index of current sub-path start point */+ FT_Memory memory;+ FT_Bool valid;++ } FT_StrokeBorderRec, *FT_StrokeBorder;+++ static FT_Error+ ft_stroke_border_grow( FT_StrokeBorder border,+ FT_UInt new_points )+ {+ FT_UInt old_max = border->max_points;+ FT_UInt new_max = border->num_points + new_points;+ FT_Error error = FT_Err_Ok;+++ if ( new_max > old_max )+ {+ FT_UInt cur_max = old_max;+ FT_Memory memory = border->memory;+++ while ( cur_max < new_max )+ cur_max += ( cur_max >> 1 ) + 16;++ if ( FT_RENEW_ARRAY( border->points, old_max, cur_max ) ||+ FT_RENEW_ARRAY( border->tags, old_max, cur_max ) )+ goto Exit;++ border->max_points = cur_max;+ }++ Exit:+ return error;+ }+++ static void+ ft_stroke_border_close( FT_StrokeBorder border,+ FT_Bool reverse )+ {+ FT_UInt start = border->start;+ FT_UInt count = border->num_points;+++ FT_ASSERT( border->start >= 0 );++ /* don't record empty paths! */+ if ( count <= start + 1U )+ border->num_points = start;+ else+ {+ /* copy the last point to the start of this sub-path, since */+ /* it contains the `adjusted' starting coordinates */+ border->num_points = --count;+ border->points[start] = border->points[count];++ if ( reverse )+ {+ /* reverse the points */+ {+ FT_Vector* vec1 = border->points + start + 1;+ FT_Vector* vec2 = border->points + count - 1;+++ for ( ; vec1 < vec2; vec1++, vec2-- )+ {+ FT_Vector tmp;+++ tmp = *vec1;+ *vec1 = *vec2;+ *vec2 = tmp;+ }+ }++ /* then the tags */+ {+ FT_Byte* tag1 = border->tags + start + 1;+ FT_Byte* tag2 = border->tags + count - 1;+++ for ( ; tag1 < tag2; tag1++, tag2-- )+ {+ FT_Byte tmp;+++ tmp = *tag1;+ *tag1 = *tag2;+ *tag2 = tmp;+ }+ }+ }++ border->tags[start ] |= FT_STROKE_TAG_BEGIN;+ border->tags[count - 1] |= FT_STROKE_TAG_END;+ }++ border->start = -1;+ border->movable = FALSE;+ }+++ static FT_Error+ ft_stroke_border_lineto( FT_StrokeBorder border,+ FT_Vector* to,+ FT_Bool movable )+ {+ FT_Error error = FT_Err_Ok;+++ FT_ASSERT( border->start >= 0 );++ if ( border->movable )+ {+ /* move last point */+ border->points[border->num_points - 1] = *to;+ }+ else+ {+ /* add one point */+ error = ft_stroke_border_grow( border, 1 );+ if ( !error )+ {+ FT_Vector* vec = border->points + border->num_points;+ FT_Byte* tag = border->tags + border->num_points;+++ vec[0] = *to;+ tag[0] = FT_STROKE_TAG_ON;++ border->num_points += 1;+ }+ }+ border->movable = movable;+ return error;+ }+++ static FT_Error+ ft_stroke_border_conicto( FT_StrokeBorder border,+ FT_Vector* control,+ FT_Vector* to )+ {+ FT_Error error;+++ FT_ASSERT( border->start >= 0 );++ error = ft_stroke_border_grow( border, 2 );+ if ( !error )+ {+ FT_Vector* vec = border->points + border->num_points;+ FT_Byte* tag = border->tags + border->num_points;++ vec[0] = *control;+ vec[1] = *to;++ tag[0] = 0;+ tag[1] = FT_STROKE_TAG_ON;++ border->num_points += 2;+ }+ border->movable = FALSE;+ return error;+ }+++ static FT_Error+ ft_stroke_border_cubicto( FT_StrokeBorder border,+ FT_Vector* control1,+ FT_Vector* control2,+ FT_Vector* to )+ {+ FT_Error error;+++ FT_ASSERT( border->start >= 0 );++ error = ft_stroke_border_grow( border, 3 );+ if ( !error )+ {+ FT_Vector* vec = border->points + border->num_points;+ FT_Byte* tag = border->tags + border->num_points;+++ vec[0] = *control1;+ vec[1] = *control2;+ vec[2] = *to;++ tag[0] = FT_STROKE_TAG_CUBIC;+ tag[1] = FT_STROKE_TAG_CUBIC;+ tag[2] = FT_STROKE_TAG_ON;++ border->num_points += 3;+ }+ border->movable = FALSE;+ return error;+ }+++#define FT_ARC_CUBIC_ANGLE ( FT_ANGLE_PI / 2 )+++ static FT_Error+ ft_stroke_border_arcto( FT_StrokeBorder border,+ FT_Vector* center,+ FT_Fixed radius,+ FT_Angle angle_start,+ FT_Angle angle_diff )+ {+ FT_Angle total, angle, step, rotate, next, theta;+ FT_Vector a, b, a2, b2;+ FT_Fixed length;+ FT_Error error = FT_Err_Ok;+++ /* compute start point */+ FT_Vector_From_Polar( &a, radius, angle_start );+ a.x += center->x;+ a.y += center->y;++ total = angle_diff;+ angle = angle_start;+ rotate = ( angle_diff >= 0 ) ? FT_ANGLE_PI2 : -FT_ANGLE_PI2;++ while ( total != 0 )+ {+ step = total;+ if ( step > FT_ARC_CUBIC_ANGLE )+ step = FT_ARC_CUBIC_ANGLE;++ else if ( step < -FT_ARC_CUBIC_ANGLE )+ step = -FT_ARC_CUBIC_ANGLE;++ next = angle + step;+ theta = step;+ if ( theta < 0 )+ theta = -theta;++ theta >>= 1;++ /* compute end point */+ FT_Vector_From_Polar( &b, radius, next );+ b.x += center->x;+ b.y += center->y;++ /* compute first and second control points */+ length = FT_MulDiv( radius, FT_Sin( theta ) * 4,+ ( 0x10000L + FT_Cos( theta ) ) * 3 );++ FT_Vector_From_Polar( &a2, length, angle + rotate );+ a2.x += a.x;+ a2.y += a.y;++ FT_Vector_From_Polar( &b2, length, next - rotate );+ b2.x += b.x;+ b2.y += b.y;++ /* add cubic arc */+ error = ft_stroke_border_cubicto( border, &a2, &b2, &b );+ if ( error )+ break;++ /* process the rest of the arc ?? */+ a = b;+ total -= step;+ angle = next;+ }++ return error;+ }+++ static FT_Error+ ft_stroke_border_moveto( FT_StrokeBorder border,+ FT_Vector* to )+ {+ /* close current open path if any ? */+ if ( border->start >= 0 )+ ft_stroke_border_close( border, FALSE );++ border->start = border->num_points;+ border->movable = FALSE;++ return ft_stroke_border_lineto( border, to, FALSE );+ }+++ static void+ ft_stroke_border_init( FT_StrokeBorder border,+ FT_Memory memory )+ {+ border->memory = memory;+ border->points = NULL;+ border->tags = NULL;++ border->num_points = 0;+ border->max_points = 0;+ border->start = -1;+ border->valid = FALSE;+ }+++ static void+ ft_stroke_border_reset( FT_StrokeBorder border )+ {+ border->num_points = 0;+ border->start = -1;+ border->valid = FALSE;+ }+++ static void+ ft_stroke_border_done( FT_StrokeBorder border )+ {+ FT_Memory memory = border->memory;+++ FT_FREE( border->points );+ FT_FREE( border->tags );++ border->num_points = 0;+ border->max_points = 0;+ border->start = -1;+ border->valid = FALSE;+ }+++ static FT_Error+ ft_stroke_border_get_counts( FT_StrokeBorder border,+ FT_UInt *anum_points,+ FT_UInt *anum_contours )+ {+ FT_Error error = FT_Err_Ok;+ FT_UInt num_points = 0;+ FT_UInt num_contours = 0;++ FT_UInt count = border->num_points;+ FT_Vector* point = border->points;+ FT_Byte* tags = border->tags;+ FT_Int in_contour = 0;+++ for ( ; count > 0; count--, num_points++, point++, tags++ )+ {+ if ( tags[0] & FT_STROKE_TAG_BEGIN )+ {+ if ( in_contour != 0 )+ goto Fail;++ in_contour = 1;+ }+ else if ( in_contour == 0 )+ goto Fail;++ if ( tags[0] & FT_STROKE_TAG_END )+ {+ in_contour = 0;+ num_contours++;+ }+ }++ if ( in_contour != 0 )+ goto Fail;++ border->valid = TRUE;++ Exit:+ *anum_points = num_points;+ *anum_contours = num_contours;+ return error;++ Fail:+ num_points = 0;+ num_contours = 0;+ goto Exit;+ }+++ static void+ ft_stroke_border_export( FT_StrokeBorder border,+ FT_Outline* outline )+ {+ /* copy point locations */+ FT_ARRAY_COPY( outline->points + outline->n_points,+ border->points,+ border->num_points );++ /* copy tags */+ {+ FT_UInt count = border->num_points;+ FT_Byte* read = border->tags;+ FT_Byte* write = (FT_Byte*)outline->tags + outline->n_points;+++ for ( ; count > 0; count--, read++, write++ )+ {+ if ( *read & FT_STROKE_TAG_ON )+ *write = FT_CURVE_TAG_ON;+ else if ( *read & FT_STROKE_TAG_CUBIC )+ *write = FT_CURVE_TAG_CUBIC;+ else+ *write = FT_CURVE_TAG_CONIC;+ }+ }++ /* copy contours */+ {+ FT_UInt count = border->num_points;+ FT_Byte* tags = border->tags;+ FT_Short* write = outline->contours + outline->n_contours;+ FT_Short idx = (FT_Short)outline->n_points;+++ for ( ; count > 0; count--, tags++, idx++ )+ {+ if ( *tags & FT_STROKE_TAG_END )+ {+ *write++ = idx;+ outline->n_contours++;+ }+ }+ }++ outline->n_points = (short)( outline->n_points + border->num_points );++ FT_ASSERT( FT_Outline_Check( outline ) == 0 );+ }+++ /***************************************************************************/+ /***************************************************************************/+ /***** *****/+ /***** STROKER *****/+ /***** *****/+ /***************************************************************************/+ /***************************************************************************/++#define FT_SIDE_TO_ROTATE( s ) ( FT_ANGLE_PI2 - (s) * FT_ANGLE_PI )++ typedef struct FT_StrokerRec_+ {+ FT_Angle angle_in;+ FT_Angle angle_out;+ FT_Vector center;+ FT_Bool first_point;+ FT_Bool subpath_open;+ FT_Angle subpath_angle;+ FT_Vector subpath_start;++ FT_Stroker_LineCap line_cap;+ FT_Stroker_LineJoin line_join;+ FT_Fixed miter_limit;+ FT_Fixed radius;++ FT_Bool valid;+ FT_StrokeBorderRec borders[2];+ FT_Library library;++ } FT_StrokerRec;+++ /* documentation is in ftstroke.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Stroker_New( FT_Library library,+ FT_Stroker *astroker )+ {+ FT_Error error;+ FT_Memory memory;+ FT_Stroker stroker;+++ if ( !library )+ return FT_Err_Invalid_Argument;++ memory = library->memory;++ if ( !FT_NEW( stroker ) )+ {+ stroker->library = library;++ ft_stroke_border_init( &stroker->borders[0], memory );+ ft_stroke_border_init( &stroker->borders[1], memory );+ }+ *astroker = stroker;+ return error;+ }+++ /* documentation is in ftstroke.h */++ FT_EXPORT_DEF( void )+ FT_Stroker_Set( FT_Stroker stroker,+ FT_Fixed radius,+ FT_Stroker_LineCap line_cap,+ FT_Stroker_LineJoin line_join,+ FT_Fixed miter_limit )+ {+ stroker->radius = radius;+ stroker->line_cap = line_cap;+ stroker->line_join = line_join;+ stroker->miter_limit = miter_limit;++ FT_Stroker_Rewind( stroker );+ }+++ /* documentation is in ftstroke.h */++ FT_EXPORT_DEF( void )+ FT_Stroker_Rewind( FT_Stroker stroker )+ {+ if ( stroker )+ {+ ft_stroke_border_reset( &stroker->borders[0] );+ ft_stroke_border_reset( &stroker->borders[1] );+ }+ }+++ /* documentation is in ftstroke.h */++ FT_EXPORT_DEF( void )+ FT_Stroker_Done( FT_Stroker stroker )+ {+ if ( stroker )+ {+ FT_Memory memory = stroker->library->memory;+++ ft_stroke_border_done( &stroker->borders[0] );+ ft_stroke_border_done( &stroker->borders[1] );++ stroker->library = NULL;+ FT_FREE( stroker );+ }+ }+++ /* creates a circular arc at a corner or cap */+ static FT_Error+ ft_stroker_arcto( FT_Stroker stroker,+ FT_Int side )+ {+ FT_Angle total, rotate;+ FT_Fixed radius = stroker->radius;+ FT_Error error = FT_Err_Ok;+ FT_StrokeBorder border = stroker->borders + side;+++ rotate = FT_SIDE_TO_ROTATE( side );++ total = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );+ if ( total == FT_ANGLE_PI )+ total = -rotate * 2;++ error = ft_stroke_border_arcto( border,+ &stroker->center,+ radius,+ stroker->angle_in + rotate,+ total );+ border->movable = FALSE;+ return error;+ }+++ /* adds a cap at the end of an opened path */+ static FT_Error+ ft_stroker_cap( FT_Stroker stroker,+ FT_Angle angle,+ FT_Int side )+ {+ FT_Error error = FT_Err_Ok;+++ if ( stroker->line_cap == FT_STROKER_LINECAP_ROUND )+ {+ /* add a round cap */+ stroker->angle_in = angle;+ stroker->angle_out = angle + FT_ANGLE_PI;+ error = ft_stroker_arcto( stroker, side );+ }+ else if ( stroker->line_cap == FT_STROKER_LINECAP_SQUARE )+ {+ /* add a square cap */+ FT_Vector delta, delta2;+ FT_Angle rotate = FT_SIDE_TO_ROTATE( side );+ FT_Fixed radius = stroker->radius;+ FT_StrokeBorder border = stroker->borders + side;+++ FT_Vector_From_Polar( &delta2, radius, angle + rotate );+ FT_Vector_From_Polar( &delta, radius, angle );++ delta.x += stroker->center.x + delta2.x;+ delta.y += stroker->center.y + delta2.y;++ error = ft_stroke_border_lineto( border, &delta, FALSE );+ if ( error )+ goto Exit;++ FT_Vector_From_Polar( &delta2, radius, angle - rotate );+ FT_Vector_From_Polar( &delta, radius, angle );++ delta.x += delta2.x + stroker->center.x;+ delta.y += delta2.y + stroker->center.y;++ error = ft_stroke_border_lineto( border, &delta, FALSE );+ }+ else if ( stroker->line_cap == FT_STROKER_LINECAP_BUTT )+ {+ /* add a butt ending */+ FT_Vector delta;+ FT_Angle rotate = FT_SIDE_TO_ROTATE( side );+ FT_Fixed radius = stroker->radius;+ FT_StrokeBorder border = stroker->borders + side;+++ FT_Vector_From_Polar( &delta, radius, angle + rotate );++ delta.x += stroker->center.x;+ delta.y += stroker->center.y;++ error = ft_stroke_border_lineto( border, &delta, FALSE );+ if ( error )+ goto Exit;++ FT_Vector_From_Polar( &delta, radius, angle - rotate );++ delta.x += stroker->center.x;+ delta.y += stroker->center.y;++ error = ft_stroke_border_lineto( border, &delta, FALSE ); + }++ Exit:+ return error;+ }+++ /* process an inside corner, i.e. compute intersection */+ static FT_Error+ ft_stroker_inside( FT_Stroker stroker,+ FT_Int side)+ {+ FT_StrokeBorder border = stroker->borders + side;+ FT_Angle phi, theta, rotate;+ FT_Fixed length, thcos, sigma;+ FT_Vector delta;+ FT_Error error = FT_Err_Ok;+++ rotate = FT_SIDE_TO_ROTATE( side );++ /* compute median angle */+ theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );+ if ( theta == FT_ANGLE_PI )+ theta = rotate;+ else+ theta = theta / 2;++ phi = stroker->angle_in + theta;++ thcos = FT_Cos( theta );+ sigma = FT_MulFix( stroker->miter_limit, thcos );++ /* TODO: find better criterion to switch off the optimization */+ if ( sigma < 0x10000L )+ {+ FT_Vector_From_Polar( &delta, stroker->radius,+ stroker->angle_out + rotate );+ delta.x += stroker->center.x;+ delta.y += stroker->center.y;+ border->movable = FALSE;+ }+ else+ {+ length = FT_DivFix( stroker->radius, thcos );++ FT_Vector_From_Polar( &delta, length, phi + rotate );+ delta.x += stroker->center.x;+ delta.y += stroker->center.y;+ }++ error = ft_stroke_border_lineto( border, &delta, FALSE );++ return error;+ }+++ /* process an outside corner, i.e. compute bevel/miter/round */+ static FT_Error+ ft_stroker_outside( FT_Stroker stroker,+ FT_Int side )+ {+ FT_StrokeBorder border = stroker->borders + side;+ FT_Error error;+ FT_Angle rotate;+++ if ( stroker->line_join == FT_STROKER_LINEJOIN_ROUND )+ error = ft_stroker_arcto( stroker, side );+ else+ {+ /* this is a mitered or beveled corner */+ FT_Fixed sigma, radius = stroker->radius;+ FT_Angle theta, phi;+ FT_Fixed thcos;+ FT_Bool miter;+++ rotate = FT_SIDE_TO_ROTATE( side );+ miter = FT_BOOL( stroker->line_join == FT_STROKER_LINEJOIN_MITER );++ theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );+ if ( theta == FT_ANGLE_PI )+ {+ theta = rotate;+ phi = stroker->angle_in;+ }+ else+ {+ theta = theta / 2;+ phi = stroker->angle_in + theta + rotate;+ }++ thcos = FT_Cos( theta );+ sigma = FT_MulFix( stroker->miter_limit, thcos );++ /* FT_Sin(x) = 0 for x <= 57 */+ if ( sigma >= 0x10000L || ft_pos_abs( theta ) <= 57 )+ miter = FALSE;++ if ( miter ) /* this is a miter (broken angle) */+ {+ FT_Vector middle, delta;+ FT_Fixed length;+++ /* compute middle point */+ FT_Vector_From_Polar( &middle,+ FT_MulFix( radius, stroker->miter_limit ),+ phi );+ middle.x += stroker->center.x;+ middle.y += stroker->center.y;++ /* compute first angle point */+ length = FT_MulFix( radius,+ FT_DivFix( 0x10000L - sigma,+ ft_pos_abs( FT_Sin( theta ) ) ) );++ FT_Vector_From_Polar( &delta, length, phi + rotate );+ delta.x += middle.x;+ delta.y += middle.y;++ error = ft_stroke_border_lineto( border, &delta, FALSE );+ if ( error )+ goto Exit;++ /* compute second angle point */+ FT_Vector_From_Polar( &delta, length, phi - rotate );+ delta.x += middle.x;+ delta.y += middle.y;++ error = ft_stroke_border_lineto( border, &delta, FALSE );+ if ( error )+ goto Exit;++ /* finally, add a movable end point */+ FT_Vector_From_Polar( &delta, radius, stroker->angle_out + rotate );+ delta.x += stroker->center.x;+ delta.y += stroker->center.y;++ error = ft_stroke_border_lineto( border, &delta, TRUE );+ }++ else /* this is a bevel (intersection) */+ {+ FT_Fixed length;+ FT_Vector delta;+++ length = FT_DivFix( stroker->radius, thcos );++ FT_Vector_From_Polar( &delta, length, phi );+ delta.x += stroker->center.x;+ delta.y += stroker->center.y;++ error = ft_stroke_border_lineto( border, &delta, FALSE );+ if ( error )+ goto Exit;++ /* now add end point */+ FT_Vector_From_Polar( &delta, stroker->radius,+ stroker->angle_out + rotate );+ delta.x += stroker->center.x;+ delta.y += stroker->center.y;++ error = ft_stroke_border_lineto( border, &delta, TRUE );+ }+ }++ Exit:+ return error;+ }+++ static FT_Error+ ft_stroker_process_corner( FT_Stroker stroker )+ {+ FT_Error error = FT_Err_Ok;+ FT_Angle turn;+ FT_Int inside_side;+++ turn = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );++ /* no specific corner processing is required if the turn is 0 */+ if ( turn == 0 )+ goto Exit;++ /* when we turn to the right, the inside side is 0 */+ inside_side = 0;++ /* otherwise, the inside side is 1 */+ if ( turn < 0 )+ inside_side = 1;++ /* process the inside side */+ error = ft_stroker_inside( stroker, inside_side );+ if ( error )+ goto Exit;++ /* process the outside side */+ error = ft_stroker_outside( stroker, 1 - inside_side );++ Exit:+ return error;+ }+++ /* add two points to the left and right borders corresponding to the */+ /* start of the subpath */+ static FT_Error+ ft_stroker_subpath_start( FT_Stroker stroker,+ FT_Angle start_angle )+ {+ FT_Vector delta;+ FT_Vector point;+ FT_Error error;+ FT_StrokeBorder border;+++ FT_Vector_From_Polar( &delta, stroker->radius,+ start_angle + FT_ANGLE_PI2 );++ point.x = stroker->center.x + delta.x;+ point.y = stroker->center.y + delta.y;++ border = stroker->borders;+ error = ft_stroke_border_moveto( border, &point );+ if ( error )+ goto Exit;++ point.x = stroker->center.x - delta.x;+ point.y = stroker->center.y - delta.y;++ border++;+ error = ft_stroke_border_moveto( border, &point );++ /* save angle for last cap */+ stroker->subpath_angle = start_angle;+ stroker->first_point = FALSE;++ Exit:+ return error;+ }+++ /* documentation is in ftstroke.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Stroker_LineTo( FT_Stroker stroker,+ FT_Vector* to )+ {+ FT_Error error = FT_Err_Ok;+ FT_StrokeBorder border;+ FT_Vector delta;+ FT_Angle angle;+ FT_Int side;++ delta.x = to->x - stroker->center.x;+ delta.y = to->y - stroker->center.y;++ angle = FT_Atan2( delta.x, delta.y );+ FT_Vector_From_Polar( &delta, stroker->radius, angle + FT_ANGLE_PI2 );++ /* process corner if necessary */+ if ( stroker->first_point )+ {+ /* This is the first segment of a subpath. We need to */+ /* add a point to each border at their respective starting */+ /* point locations. */+ error = ft_stroker_subpath_start( stroker, angle );+ if ( error )+ goto Exit;+ }+ else+ {+ /* process the current corner */+ stroker->angle_out = angle;+ error = ft_stroker_process_corner( stroker );+ if ( error )+ goto Exit;+ }++ /* now add a line segment to both the `inside' and `outside' paths */++ for ( border = stroker->borders, side = 1; side >= 0; side--, border++ )+ {+ FT_Vector point;+++ point.x = to->x + delta.x;+ point.y = to->y + delta.y;++ error = ft_stroke_border_lineto( border, &point, TRUE );+ if ( error )+ goto Exit;++ delta.x = -delta.x;+ delta.y = -delta.y;+ }++ stroker->angle_in = angle;+ stroker->center = *to;++ Exit:+ return error;+ }+++ /* documentation is in ftstroke.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Stroker_ConicTo( FT_Stroker stroker,+ FT_Vector* control,+ FT_Vector* to )+ {+ FT_Error error = FT_Err_Ok;+ FT_Vector bez_stack[34];+ FT_Vector* arc;+ FT_Vector* limit = bez_stack + 30;+ FT_Angle start_angle;+ FT_Bool first_arc = TRUE;+++ arc = bez_stack;+ arc[0] = *to;+ arc[1] = *control;+ arc[2] = stroker->center;++ while ( arc >= bez_stack )+ {+ FT_Angle angle_in, angle_out;+++ angle_in = angle_out = 0; /* remove compiler warnings */++ if ( arc < limit &&+ !ft_conic_is_small_enough( arc, &angle_in, &angle_out ) )+ {+ ft_conic_split( arc );+ arc += 2;+ continue;+ }++ if ( first_arc )+ {+ first_arc = FALSE;++ start_angle = angle_in;++ /* process corner if necessary */+ if ( stroker->first_point )+ error = ft_stroker_subpath_start( stroker, start_angle );+ else+ {+ stroker->angle_out = start_angle;+ error = ft_stroker_process_corner( stroker );+ }+ }++ /* the arc's angle is small enough; we can add it directly to each */+ /* border */+ {+ FT_Vector ctrl, end;+ FT_Angle theta, phi, rotate;+ FT_Fixed length;+ FT_Int side;+++ theta = FT_Angle_Diff( angle_in, angle_out ) / 2;+ phi = angle_in + theta;+ length = FT_DivFix( stroker->radius, FT_Cos( theta ) );++ for ( side = 0; side <= 1; side++ )+ {+ rotate = FT_SIDE_TO_ROTATE( side );++ /* compute control point */+ FT_Vector_From_Polar( &ctrl, length, phi + rotate );+ ctrl.x += arc[1].x;+ ctrl.y += arc[1].y;++ /* compute end point */+ FT_Vector_From_Polar( &end, stroker->radius, angle_out + rotate );+ end.x += arc[0].x;+ end.y += arc[0].y;++ error = ft_stroke_border_conicto( stroker->borders + side,+ &ctrl, &end );+ if ( error )+ goto Exit;+ }+ }++ arc -= 2;++ if ( arc < bez_stack )+ stroker->angle_in = angle_out;+ }++ stroker->center = *to;++ Exit:+ return error;+ }+++ /* documentation is in ftstroke.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Stroker_CubicTo( FT_Stroker stroker,+ FT_Vector* control1,+ FT_Vector* control2,+ FT_Vector* to )+ {+ FT_Error error = FT_Err_Ok;+ FT_Vector bez_stack[37];+ FT_Vector* arc;+ FT_Vector* limit = bez_stack + 32;+ FT_Angle start_angle;+ FT_Bool first_arc = TRUE;+++ arc = bez_stack;+ arc[0] = *to;+ arc[1] = *control2;+ arc[2] = *control1;+ arc[3] = stroker->center;++ while ( arc >= bez_stack )+ {+ FT_Angle angle_in, angle_mid, angle_out;+++ /* remove compiler warnings */+ angle_in = angle_out = angle_mid = 0;++ if ( arc < limit &&+ !ft_cubic_is_small_enough( arc, &angle_in,+ &angle_mid, &angle_out ) )+ {+ ft_cubic_split( arc );+ arc += 3;+ continue;+ }++ if ( first_arc )+ {+ first_arc = FALSE;++ /* process corner if necessary */+ start_angle = angle_in;++ if ( stroker->first_point )+ error = ft_stroker_subpath_start( stroker, start_angle );+ else+ {+ stroker->angle_out = start_angle;+ error = ft_stroker_process_corner( stroker );+ }+ if ( error )+ goto Exit;+ }++ /* the arc's angle is small enough; we can add it directly to each */+ /* border */+ {+ FT_Vector ctrl1, ctrl2, end;+ FT_Angle theta1, phi1, theta2, phi2, rotate;+ FT_Fixed length1, length2;+ FT_Int side;+++ theta1 = ft_pos_abs( angle_mid - angle_in ) / 2;+ theta2 = ft_pos_abs( angle_out - angle_mid ) / 2;+ phi1 = (angle_mid + angle_in ) / 2;+ phi2 = (angle_mid + angle_out ) / 2;+ length1 = FT_DivFix( stroker->radius, FT_Cos( theta1 ) );+ length2 = FT_DivFix( stroker->radius, FT_Cos( theta2 ) );++ for ( side = 0; side <= 1; side++ )+ {+ rotate = FT_SIDE_TO_ROTATE( side );++ /* compute control points */+ FT_Vector_From_Polar( &ctrl1, length1, phi1 + rotate );+ ctrl1.x += arc[2].x;+ ctrl1.y += arc[2].y;++ FT_Vector_From_Polar( &ctrl2, length2, phi2 + rotate );+ ctrl2.x += arc[1].x;+ ctrl2.y += arc[1].y;++ /* compute end point */+ FT_Vector_From_Polar( &end, stroker->radius, angle_out + rotate );+ end.x += arc[0].x;+ end.y += arc[0].y;++ error = ft_stroke_border_cubicto( stroker->borders + side,+ &ctrl1, &ctrl2, &end );+ if ( error )+ goto Exit;+ }+ }++ arc -= 3;+ if ( arc < bez_stack )+ stroker->angle_in = angle_out;+ }++ stroker->center = *to;++ Exit:+ return error;+ }+++ /* documentation is in ftstroke.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Stroker_BeginSubPath( FT_Stroker stroker,+ FT_Vector* to,+ FT_Bool open )+ {+ /* We cannot process the first point, because there is not enough */+ /* information regarding its corner/cap. The latter will be processed */+ /* in the `FT_Stroker_EndSubPath' routine. */+ /* */+ stroker->first_point = TRUE;+ stroker->center = *to;+ stroker->subpath_open = open;++ /* record the subpath start point for each border */+ stroker->subpath_start = *to;++ return FT_Err_Ok;+ }+++ static FT_Error+ ft_stroker_add_reverse_left( FT_Stroker stroker,+ FT_Bool open )+ {+ FT_StrokeBorder right = stroker->borders + 0;+ FT_StrokeBorder left = stroker->borders + 1;+ FT_Int new_points;+ FT_Error error = FT_Err_Ok;+++ FT_ASSERT( left->start >= 0 );++ new_points = left->num_points - left->start;+ if ( new_points > 0 )+ {+ error = ft_stroke_border_grow( right, (FT_UInt)new_points );+ if ( error )+ goto Exit;++ {+ FT_Vector* dst_point = right->points + right->num_points;+ FT_Byte* dst_tag = right->tags + right->num_points;+ FT_Vector* src_point = left->points + left->num_points - 1;+ FT_Byte* src_tag = left->tags + left->num_points - 1;++ while ( src_point >= left->points + left->start )+ {+ *dst_point = *src_point;+ *dst_tag = *src_tag;++ if ( open )+ dst_tag[0] &= ~FT_STROKE_TAG_BEGIN_END;+ else+ {+ FT_Byte ttag = (FT_Byte)( dst_tag[0] & FT_STROKE_TAG_BEGIN_END );+++ /* switch begin/end tags if necessary */+ if ( ttag == FT_STROKE_TAG_BEGIN ||+ ttag == FT_STROKE_TAG_END )+ dst_tag[0] ^= FT_STROKE_TAG_BEGIN_END;++ }++ src_point--;+ src_tag--;+ dst_point++;+ dst_tag++;+ }+ }++ left->num_points = left->start;+ right->num_points += new_points;++ right->movable = FALSE;+ left->movable = FALSE;+ }++ Exit:+ return error;+ }+++ /* documentation is in ftstroke.h */++ /* there's a lot of magic in this function! */+ FT_EXPORT_DEF( FT_Error )+ FT_Stroker_EndSubPath( FT_Stroker stroker )+ {+ FT_Error error = FT_Err_Ok;+++ if ( stroker->subpath_open )+ {+ FT_StrokeBorder right = stroker->borders;++ /* All right, this is an opened path, we need to add a cap between */+ /* right & left, add the reverse of left, then add a final cap */+ /* between left & right. */+ error = ft_stroker_cap( stroker, stroker->angle_in, 0 );+ if ( error )+ goto Exit;++ /* add reversed points from `left' to `right' */+ error = ft_stroker_add_reverse_left( stroker, TRUE );+ if ( error )+ goto Exit;++ /* now add the final cap */+ stroker->center = stroker->subpath_start;+ error = ft_stroker_cap( stroker,+ stroker->subpath_angle + FT_ANGLE_PI, 0 );+ if ( error )+ goto Exit;++ /* Now end the right subpath accordingly. The left one is */+ /* rewind and doesn't need further processing. */+ ft_stroke_border_close( right, FALSE );+ }+ else+ {+ FT_Angle turn;+ FT_Int inside_side;++ /* close the path if needed */+ if ( stroker->center.x != stroker->subpath_start.x ||+ stroker->center.y != stroker->subpath_start.y )+ {+ error = FT_Stroker_LineTo( stroker, &stroker->subpath_start );+ if ( error )+ goto Exit;+ }++ /* process the corner */+ stroker->angle_out = stroker->subpath_angle;+ turn = FT_Angle_Diff( stroker->angle_in,+ stroker->angle_out );++ /* no specific corner processing is required if the turn is 0 */+ if ( turn != 0 )+ {+ /* when we turn to the right, the inside side is 0 */+ inside_side = 0;++ /* otherwise, the inside side is 1 */+ if ( turn < 0 )+ inside_side = 1;++ error = ft_stroker_inside( stroker, inside_side );+ if ( error )+ goto Exit;++ /* process the outside side */+ error = ft_stroker_outside( stroker, 1 - inside_side );+ if ( error )+ goto Exit;+ }++ /* then end our two subpaths */+ ft_stroke_border_close( stroker->borders + 0, TRUE );+ ft_stroke_border_close( stroker->borders + 1, FALSE );+ }++ Exit:+ return error;+ }+++ /* documentation is in ftstroke.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Stroker_GetBorderCounts( FT_Stroker stroker,+ FT_StrokerBorder border,+ FT_UInt *anum_points,+ FT_UInt *anum_contours )+ {+ FT_UInt num_points = 0, num_contours = 0;+ FT_Error error;+++ if ( !stroker || border > 1 )+ {+ error = FT_Err_Invalid_Argument;+ goto Exit;+ }++ error = ft_stroke_border_get_counts( stroker->borders + border,+ &num_points, &num_contours );+ Exit:+ if ( anum_points )+ *anum_points = num_points;++ if ( anum_contours )+ *anum_contours = num_contours;++ return error;+ }+++ /* documentation is in ftstroke.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Stroker_GetCounts( FT_Stroker stroker,+ FT_UInt *anum_points,+ FT_UInt *anum_contours )+ {+ FT_UInt count1, count2, num_points = 0;+ FT_UInt count3, count4, num_contours = 0;+ FT_Error error;+++ error = ft_stroke_border_get_counts( stroker->borders + 0,+ &count1, &count2 );+ if ( error )+ goto Exit;++ error = ft_stroke_border_get_counts( stroker->borders + 1,+ &count3, &count4 );+ if ( error )+ goto Exit;++ num_points = count1 + count3;+ num_contours = count2 + count4;++ Exit:+ *anum_points = num_points;+ *anum_contours = num_contours;+ return error;+ }+++ /* documentation is in ftstroke.h */++ FT_EXPORT_DEF( void )+ FT_Stroker_ExportBorder( FT_Stroker stroker,+ FT_StrokerBorder border,+ FT_Outline* outline )+ {+ if ( border == FT_STROKER_BORDER_LEFT ||+ border == FT_STROKER_BORDER_RIGHT )+ {+ FT_StrokeBorder sborder = & stroker->borders[border];+++ if ( sborder->valid )+ ft_stroke_border_export( sborder, outline );+ }+ }+++ /* documentation is in ftstroke.h */++ FT_EXPORT_DEF( void )+ FT_Stroker_Export( FT_Stroker stroker,+ FT_Outline* outline )+ {+ FT_Stroker_ExportBorder( stroker, FT_STROKER_BORDER_LEFT, outline );+ FT_Stroker_ExportBorder( stroker, FT_STROKER_BORDER_RIGHT, outline );+ }+++ /* documentation is in ftstroke.h */++ /*+ * The following is very similar to FT_Outline_Decompose, except+ * that we do support opened paths, and do not scale the outline.+ */+ FT_EXPORT_DEF( FT_Error )+ FT_Stroker_ParseOutline( FT_Stroker stroker,+ FT_Outline* outline,+ FT_Bool opened )+ {+ FT_Vector v_last;+ FT_Vector v_control;+ FT_Vector v_start;++ FT_Vector* point;+ FT_Vector* limit;+ char* tags;++ FT_Error error;++ FT_Int n; /* index of contour in outline */+ FT_UInt first; /* index of first point in contour */+ FT_Int tag; /* current point's state */+++ if ( !outline || !stroker )+ return FT_Err_Invalid_Argument;++ FT_Stroker_Rewind( stroker );++ first = 0;++ for ( n = 0; n < outline->n_contours; n++ )+ {+ FT_UInt last; /* index of last point in contour */+++ last = outline->contours[n];+ limit = outline->points + last;++ /* skip empty points; we don't stroke these */+ if ( last <= first )+ {+ first = last + 1;+ continue;+ }++ v_start = outline->points[first];+ v_last = outline->points[last];++ v_control = v_start;++ point = outline->points + first;+ tags = outline->tags + first;+ tag = FT_CURVE_TAG( tags[0] );++ /* A contour cannot start with a cubic control point! */+ if ( tag == FT_CURVE_TAG_CUBIC )+ goto Invalid_Outline;++ /* check first point to determine origin */+ if ( tag == FT_CURVE_TAG_CONIC )+ {+ /* First point is conic control. Yes, this happens. */+ if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON )+ {+ /* start at last point if it is on the curve */+ v_start = v_last;+ limit--;+ }+ else+ {+ /* if both first and last points are conic, */+ /* start at their middle */+ v_start.x = ( v_start.x + v_last.x ) / 2;+ v_start.y = ( v_start.y + v_last.y ) / 2;+ }+ point--;+ tags--;+ }++ error = FT_Stroker_BeginSubPath( stroker, &v_start, opened );+ if ( error )+ goto Exit;++ while ( point < limit )+ {+ point++;+ tags++;++ tag = FT_CURVE_TAG( tags[0] );+ switch ( tag )+ {+ case FT_CURVE_TAG_ON: /* emit a single line_to */+ {+ FT_Vector vec;+++ vec.x = point->x;+ vec.y = point->y;++ error = FT_Stroker_LineTo( stroker, &vec );+ if ( error )+ goto Exit;+ continue;+ }++ case FT_CURVE_TAG_CONIC: /* consume conic arcs */+ v_control.x = point->x;+ v_control.y = point->y;++ Do_Conic:+ if ( point < limit )+ {+ FT_Vector vec;+ FT_Vector v_middle;+++ point++;+ tags++;+ tag = FT_CURVE_TAG( tags[0] );++ vec = point[0];++ if ( tag == FT_CURVE_TAG_ON )+ {+ error = FT_Stroker_ConicTo( stroker, &v_control, &vec );+ if ( error )+ goto Exit;+ continue;+ }++ if ( tag != FT_CURVE_TAG_CONIC )+ goto Invalid_Outline;++ v_middle.x = ( v_control.x + vec.x ) / 2;+ v_middle.y = ( v_control.y + vec.y ) / 2;++ error = FT_Stroker_ConicTo( stroker, &v_control, &v_middle );+ if ( error )+ goto Exit;++ v_control = vec;+ goto Do_Conic;+ }++ error = FT_Stroker_ConicTo( stroker, &v_control, &v_start );+ goto Close;++ default: /* FT_CURVE_TAG_CUBIC */+ {+ FT_Vector vec1, vec2;+++ if ( point + 1 > limit ||+ FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )+ goto Invalid_Outline;++ point += 2;+ tags += 2;++ vec1 = point[-2];+ vec2 = point[-1];++ if ( point <= limit )+ {+ FT_Vector vec;+++ vec = point[0];++ error = FT_Stroker_CubicTo( stroker, &vec1, &vec2, &vec );+ if ( error )+ goto Exit;+ continue;+ }++ error = FT_Stroker_CubicTo( stroker, &vec1, &vec2, &v_start );+ goto Close;+ }+ }+ }++ Close:+ if ( error )+ goto Exit;++ error = FT_Stroker_EndSubPath( stroker );+ if ( error )+ goto Exit;++ first = last + 1;+ }++ return FT_Err_Ok;++ Exit:+ return error;++ Invalid_Outline:+ return FT_Err_Invalid_Outline;+ }++/* declare an extern to access ft_outline_glyph_class global 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 )+ FT_Glyph_Stroke( FT_Glyph *pglyph,+ FT_Stroker stroker,+ FT_Bool destroy )+ {+ FT_Error error = FT_Err_Invalid_Argument;+ FT_Glyph glyph = NULL;+ FT_Library library = stroker->library;+ FT_UNUSED(library);++ if ( pglyph == NULL )+ goto Exit;++ glyph = *pglyph;+ if ( glyph == NULL || glyph->clazz != FT_OUTLINE_GLYPH_CLASS_GET )+ goto Exit;++ {+ FT_Glyph copy;+++ error = FT_Glyph_Copy( glyph, © );+ if ( error )+ goto Exit;++ glyph = copy;+ }++ {+ FT_OutlineGlyph oglyph = (FT_OutlineGlyph) glyph;+ FT_Outline* outline = &oglyph->outline;+ FT_UInt num_points, num_contours;+++ error = FT_Stroker_ParseOutline( stroker, outline, FALSE );+ if ( error )+ goto Fail;++ (void)FT_Stroker_GetCounts( stroker, &num_points, &num_contours );++ FT_Outline_Done( glyph->library, outline );++ error = FT_Outline_New( glyph->library,+ num_points, num_contours, outline );+ if ( error )+ goto Fail;++ outline->n_points = 0;+ outline->n_contours = 0;++ FT_Stroker_Export( stroker, outline );+ }++ if ( destroy )+ FT_Done_Glyph( *pglyph );++ *pglyph = glyph;+ goto Exit;++ Fail:+ FT_Done_Glyph( glyph );+ glyph = NULL;++ if ( !destroy )+ *pglyph = NULL;++ Exit:+ return error;+ }+++ /* documentation is in ftstroke.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Glyph_StrokeBorder( FT_Glyph *pglyph,+ FT_Stroker stroker,+ FT_Bool inside,+ FT_Bool destroy )+ {+ FT_Error error = FT_Err_Invalid_Argument;+ FT_Glyph glyph = NULL;+ FT_Library library = stroker->library;+ FT_UNUSED(library);++ if ( pglyph == NULL )+ goto Exit;++ glyph = *pglyph;+ if ( glyph == NULL || glyph->clazz != FT_OUTLINE_GLYPH_CLASS_GET )+ goto Exit;++ {+ FT_Glyph copy;+++ error = FT_Glyph_Copy( glyph, © );+ if ( error )+ goto Exit;++ glyph = copy;+ }++ {+ FT_OutlineGlyph oglyph = (FT_OutlineGlyph) glyph;+ FT_StrokerBorder border;+ FT_Outline* outline = &oglyph->outline;+ FT_UInt num_points, num_contours;+++ border = FT_Outline_GetOutsideBorder( outline );+ if ( inside )+ {+ if ( border == FT_STROKER_BORDER_LEFT )+ border = FT_STROKER_BORDER_RIGHT;+ else+ border = FT_STROKER_BORDER_LEFT;+ }++ error = FT_Stroker_ParseOutline( stroker, outline, FALSE );+ if ( error )+ goto Fail;++ (void)FT_Stroker_GetBorderCounts( stroker, border,+ &num_points, &num_contours );++ FT_Outline_Done( glyph->library, outline );++ error = FT_Outline_New( glyph->library,+ num_points,+ num_contours,+ outline );+ if ( error )+ goto Fail;++ outline->n_points = 0;+ outline->n_contours = 0;++ FT_Stroker_ExportBorder( stroker, border, outline );+ }++ if ( destroy )+ FT_Done_Glyph( *pglyph );++ *pglyph = glyph;+ goto Exit;++ Fail:+ FT_Done_Glyph( glyph );+ glyph = NULL;++ if ( !destroy )+ *pglyph = NULL;++ Exit:+ return error;+ }+++/* END */
+ src/base/ftsynth.c view
@@ -0,0 +1,160 @@+/***************************************************************************/+/* */+/* ftsynth.c */+/* */+/* FreeType synthesizing code for emboldening and slanting (body). */+/* */+/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2010 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_SYNTHESIS_H+#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_OBJECTS_H+#include FT_OUTLINE_H+#include FT_BITMAP_H+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_synth++ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** EXPERIMENTAL OBLIQUING SUPPORT ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/++ /* documentation is in ftsynth.h */++ FT_EXPORT_DEF( void )+ FT_GlyphSlot_Oblique( FT_GlyphSlot slot )+ {+ FT_Matrix transform;+ FT_Outline* outline = &slot->outline;+++ /* only oblique outline glyphs */+ if ( slot->format != FT_GLYPH_FORMAT_OUTLINE )+ return;++ /* we don't touch the advance width */++ /* For italic, simply apply a shear transform, with an angle */+ /* of about 12 degrees. */++ transform.xx = 0x10000L;+ transform.yx = 0x00000L;++ transform.xy = 0x06000L;+ transform.yy = 0x10000L;++ FT_Outline_Transform( outline, &transform );+ }+++ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** EXPERIMENTAL EMBOLDENING/OUTLINING SUPPORT ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+++ /* documentation is in ftsynth.h */++ FT_EXPORT_DEF( void )+ FT_GlyphSlot_Embolden( FT_GlyphSlot slot )+ {+ FT_Library library = slot->library;+ FT_Face face = slot->face;+ FT_Error error;+ FT_Pos xstr, ystr;+++ if ( slot->format != FT_GLYPH_FORMAT_OUTLINE &&+ slot->format != FT_GLYPH_FORMAT_BITMAP )+ return;++ /* some reasonable strength */+ xstr = FT_MulFix( face->units_per_EM,+ face->size->metrics.y_scale ) / 24;+ ystr = xstr;++ if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )+ {+ /* ignore error */+ (void)FT_Outline_Embolden( &slot->outline, xstr );++ /* this is more than enough for most glyphs; if you need accurate */+ /* values, you have to call FT_Outline_Get_CBox */+ xstr = xstr * 2;+ ystr = xstr;+ }+ else /* slot->format == FT_GLYPH_FORMAT_BITMAP */+ {+ /* round to full pixels */+ xstr &= ~63;+ if ( xstr == 0 )+ xstr = 1 << 6;+ ystr &= ~63;++ /*+ * XXX: overflow check for 16-bit system, for compatibility+ * with FT_GlyphSlot_Embolden() since freetype-2.1.10.+ * unfortunately, this function return no informations+ * about the cause of error.+ */+ if ( ( ystr >> 6 ) > FT_INT_MAX || ( ystr >> 6 ) < FT_INT_MIN )+ {+ FT_TRACE1(( "FT_GlyphSlot_Embolden:" ));+ FT_TRACE1(( "too strong embolding parameter ystr=%d\n", ystr ));+ return;+ }+ error = FT_GlyphSlot_Own_Bitmap( slot );+ if ( error )+ return;++ error = FT_Bitmap_Embolden( library, &slot->bitmap, xstr, ystr );+ if ( error )+ return;+ }++ if ( slot->advance.x )+ slot->advance.x += xstr;++ if ( slot->advance.y )+ slot->advance.y += ystr;++ slot->metrics.width += xstr;+ slot->metrics.height += ystr;+ slot->metrics.horiBearingY += ystr;+ slot->metrics.horiAdvance += xstr;+ slot->metrics.vertBearingX -= xstr / 2;+ slot->metrics.vertBearingY += ystr;+ slot->metrics.vertAdvance += ystr;++ /* XXX: 16-bit overflow case must be excluded before here */+ if ( slot->format == FT_GLYPH_FORMAT_BITMAP )+ slot->bitmap_top += (FT_Int)( ystr >> 6 );+ }+++/* END */
+ src/base/ftsystem.c view
@@ -0,0 +1,318 @@+/***************************************************************************/+/* */+/* ftsystem.c */+/* */+/* ANSI-specific FreeType low-level system interface (body). */+/* */+/* Copyright 1996-2001, 2002, 2006, 2008, 2009, 2010 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/++ /*************************************************************************/+ /* */+ /* This file contains the default interface used by FreeType to access */+ /* low-level, i.e. memory management, i/o access as well as thread */+ /* synchronisation. It can be replaced by user-specific routines if */+ /* necessary. */+ /* */+ /*************************************************************************/+++#include <ft2build.h>+#include FT_CONFIG_CONFIG_H+#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_STREAM_H+#include FT_SYSTEM_H+#include FT_ERRORS_H+#include FT_TYPES_H+++ /*************************************************************************/+ /* */+ /* MEMORY MANAGEMENT INTERFACE */+ /* */+ /*************************************************************************/++ /*************************************************************************/+ /* */+ /* It is not necessary to do any error checking for the */+ /* allocation-related functions. This will be done by the higher level */+ /* routines like ft_mem_alloc() or ft_mem_realloc(). */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* ft_alloc */+ /* */+ /* <Description> */+ /* The memory allocation function. */+ /* */+ /* <Input> */+ /* memory :: A pointer to the memory object. */+ /* */+ /* size :: The requested size in bytes. */+ /* */+ /* <Return> */+ /* The address of newly allocated block. */+ /* */+ FT_CALLBACK_DEF( void* )+ ft_alloc( FT_Memory memory,+ long size )+ {+ FT_UNUSED( memory );++ return ft_smalloc( size );+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* ft_realloc */+ /* */+ /* <Description> */+ /* The memory reallocation function. */+ /* */+ /* <Input> */+ /* memory :: A pointer to the memory object. */+ /* */+ /* cur_size :: The current size of the allocated memory block. */+ /* */+ /* new_size :: The newly requested size in bytes. */+ /* */+ /* block :: The current address of the block in memory. */+ /* */+ /* <Return> */+ /* The address of the reallocated memory block. */+ /* */+ FT_CALLBACK_DEF( void* )+ ft_realloc( FT_Memory memory,+ long cur_size,+ long new_size,+ void* block )+ {+ FT_UNUSED( memory );+ FT_UNUSED( cur_size );++ return ft_srealloc( block, new_size );+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* ft_free */+ /* */+ /* <Description> */+ /* The memory release function. */+ /* */+ /* <Input> */+ /* memory :: A pointer to the memory object. */+ /* */+ /* block :: The address of block in memory to be freed. */+ /* */+ FT_CALLBACK_DEF( void )+ ft_free( FT_Memory memory,+ void* block )+ {+ FT_UNUSED( memory );++ ft_sfree( block );+ }+++ /*************************************************************************/+ /* */+ /* RESOURCE MANAGEMENT INTERFACE */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* 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_io++ /* We use the macro STREAM_FILE for convenience to extract the */+ /* system-specific stream handle from a given FreeType stream object */+#define STREAM_FILE( stream ) ( (FT_FILE*)stream->descriptor.pointer )+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* ft_ansi_stream_close */+ /* */+ /* <Description> */+ /* The function to close a stream. */+ /* */+ /* <Input> */+ /* stream :: A pointer to the stream object. */+ /* */+ FT_CALLBACK_DEF( void )+ ft_ansi_stream_close( FT_Stream stream )+ {+ ft_fclose( STREAM_FILE( stream ) );++ stream->descriptor.pointer = NULL;+ stream->size = 0;+ stream->base = 0;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* ft_ansi_stream_io */+ /* */+ /* <Description> */+ /* The function to open a stream. */+ /* */+ /* <Input> */+ /* stream :: A pointer to the stream object. */+ /* */+ /* offset :: The position in the data stream to start reading. */+ /* */+ /* buffer :: The address of buffer to store the read data. */+ /* */+ /* count :: The number of bytes to read from the stream. */+ /* */+ /* <Return> */+ /* The number of bytes actually read. If `count' is zero (this is, */+ /* the function is used for seeking), a non-zero return value */+ /* indicates an error. */+ /* */+ FT_CALLBACK_DEF( unsigned long )+ ft_ansi_stream_io( FT_Stream stream,+ unsigned long offset,+ unsigned char* buffer,+ unsigned long count )+ {+ FT_FILE* file;+++ if ( !count && offset > stream->size )+ return 1;++ file = STREAM_FILE( stream );++ if ( stream->pos != offset )+ ft_fseek( file, offset, SEEK_SET );++ return (unsigned long)ft_fread( buffer, 1, count, file );+ }+++ /* documentation is in ftstream.h */++ FT_BASE_DEF( FT_Error )+ FT_Stream_Open( FT_Stream stream,+ const char* filepathname )+ {+ FT_FILE* file;+++ if ( !stream )+ return FT_Err_Invalid_Stream_Handle;++ stream->descriptor.pointer = NULL;+ stream->pathname.pointer = (char*)filepathname;+ stream->base = 0;+ stream->pos = 0;+ stream->read = NULL;+ stream->close = NULL;++ file = ft_fopen( filepathname, "rb" );+ if ( !file )+ {+ FT_ERROR(( "FT_Stream_Open:"+ " could not open `%s'\n", filepathname ));++ return FT_Err_Cannot_Open_Resource;+ }++ ft_fseek( file, 0, SEEK_END );+ stream->size = ft_ftell( file );+ if ( !stream->size )+ {+ FT_ERROR(( "FT_Stream_Open:" ));+ FT_ERROR(( " opened `%s' but zero-sized\n", filepathname ));+ ft_fclose( file );+ return FT_Err_Cannot_Open_Stream;+ }+ ft_fseek( file, 0, SEEK_SET );++ stream->descriptor.pointer = file;+ stream->read = ft_ansi_stream_io;+ stream->close = ft_ansi_stream_close;++ FT_TRACE1(( "FT_Stream_Open:" ));+ FT_TRACE1(( " opened `%s' (%d bytes) successfully\n",+ filepathname, stream->size ));++ return FT_Err_Ok;+ }+++#ifdef FT_DEBUG_MEMORY++ extern FT_Int+ ft_mem_debug_init( FT_Memory memory );++ extern void+ ft_mem_debug_done( FT_Memory memory );++#endif+++ /* documentation is in ftobjs.h */++ FT_BASE_DEF( FT_Memory )+ FT_New_Memory( void )+ {+ FT_Memory memory;+++ memory = (FT_Memory)ft_smalloc( sizeof ( *memory ) );+ if ( memory )+ {+ memory->user = 0;+ memory->alloc = ft_alloc;+ memory->realloc = ft_realloc;+ memory->free = ft_free;+#ifdef FT_DEBUG_MEMORY+ ft_mem_debug_init( memory );+#endif+ }++ return memory;+ }+++ /* documentation is in ftobjs.h */++ FT_BASE_DEF( void )+ FT_Done_Memory( FT_Memory memory )+ {+#ifdef FT_DEBUG_MEMORY+ ft_mem_debug_done( memory );+#endif+ ft_sfree( memory );+ }+++/* END */
+ src/base/fttrigon.c view
@@ -0,0 +1,546 @@+/***************************************************************************/+/* */+/* fttrigon.c */+/* */+/* FreeType trigonometric functions (body). */+/* */+/* Copyright 2001, 2002, 2003, 2004, 2005 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_OBJECTS_H+#include FT_TRIGONOMETRY_H+++ /* the following is 0.2715717684432231 * 2^30 */+#define FT_TRIG_COSCALE 0x11616E8EUL++ /* this table was generated for FT_PI = 180L << 16, i.e. degrees */+#define FT_TRIG_MAX_ITERS 23++ static const FT_Fixed+ ft_trig_arctan_table[24] =+ {+ 4157273L, 2949120L, 1740967L, 919879L, 466945L, 234379L, 117304L,+ 58666L, 29335L, 14668L, 7334L, 3667L, 1833L, 917L, 458L, 229L, 115L,+ 57L, 29L, 14L, 7L, 4L, 2L, 1L+ };++ /* the Cordic shrink factor, multiplied by 2^32 */+#define FT_TRIG_SCALE 1166391785UL /* 0x4585BA38UL */+++#ifdef FT_CONFIG_HAS_INT64++ /* multiply a given value by the CORDIC shrink factor */+ static FT_Fixed+ ft_trig_downscale( FT_Fixed val )+ {+ FT_Fixed s;+ FT_Int64 v;+++ s = val;+ val = ( val >= 0 ) ? val : -val;++ v = ( val * (FT_Int64)FT_TRIG_SCALE ) + 0x100000000UL;+ val = (FT_Fixed)( v >> 32 );++ return ( s >= 0 ) ? val : -val;+ }++#else /* !FT_CONFIG_HAS_INT64 */++ /* multiply a given value by the CORDIC shrink factor */+ static FT_Fixed+ ft_trig_downscale( FT_Fixed val )+ {+ FT_Fixed s;+ FT_UInt32 v1, v2, k1, k2, hi, lo1, lo2, lo3;+++ s = val;+ val = ( val >= 0 ) ? val : -val;++ v1 = (FT_UInt32)val >> 16;+ v2 = (FT_UInt32)(val & 0xFFFFL);++ k1 = (FT_UInt32)FT_TRIG_SCALE >> 16; /* constant */+ k2 = (FT_UInt32)(FT_TRIG_SCALE & 0xFFFFL); /* constant */++ hi = k1 * v1;+ lo1 = k1 * v2 + k2 * v1; /* can't overflow */++ lo2 = ( k2 * v2 ) >> 16;+ lo3 = ( lo1 >= lo2 ) ? lo1 : lo2;+ lo1 += lo2;++ hi += lo1 >> 16;+ if ( lo1 < lo3 )+ hi += (FT_UInt32)0x10000UL;++ val = (FT_Fixed)hi;++ return ( s >= 0 ) ? val : -val;+ }++#endif /* !FT_CONFIG_HAS_INT64 */+++ static FT_Int+ ft_trig_prenorm( FT_Vector* vec )+ {+ FT_Fixed x, y, z;+ FT_Int shift;+++ x = vec->x;+ y = vec->y;++ z = ( ( x >= 0 ) ? x : - x ) | ( (y >= 0) ? y : -y );+ shift = 0;++#if 1+ /* determine msb bit index in `shift' */+ if ( z >= ( 1L << 16 ) )+ {+ z >>= 16;+ shift += 16;+ }+ if ( z >= ( 1L << 8 ) )+ {+ z >>= 8;+ shift += 8;+ }+ if ( z >= ( 1L << 4 ) )+ {+ z >>= 4;+ shift += 4;+ }+ if ( z >= ( 1L << 2 ) )+ {+ z >>= 2;+ shift += 2;+ }+ if ( z >= ( 1L << 1 ) )+ {+ z >>= 1;+ shift += 1;+ }++ if ( shift <= 27 )+ {+ shift = 27 - shift;+ vec->x = x << shift;+ vec->y = y << shift;+ }+ else+ {+ shift -= 27;+ vec->x = x >> shift;+ vec->y = y >> shift;+ shift = -shift;+ }++#else /* 0 */++ if ( z < ( 1L << 27 ) )+ {+ do+ {+ shift++;+ z <<= 1;+ } while ( z < ( 1L << 27 ) );+ vec->x = x << shift;+ vec->y = y << shift;+ }+ else if ( z > ( 1L << 28 ) )+ {+ do+ {+ shift++;+ z >>= 1;+ } while ( z > ( 1L << 28 ) );++ vec->x = x >> shift;+ vec->y = y >> shift;+ shift = -shift;+ }++#endif /* 0 */++ return shift;+ }+++ static void+ ft_trig_pseudo_rotate( FT_Vector* vec,+ FT_Angle theta )+ {+ FT_Int i;+ FT_Fixed x, y, xtemp;+ const FT_Fixed *arctanptr;+++ x = vec->x;+ y = vec->y;++ /* Get angle between -90 and 90 degrees */+ while ( theta <= -FT_ANGLE_PI2 )+ {+ x = -x;+ y = -y;+ theta += FT_ANGLE_PI;+ }++ while ( theta > FT_ANGLE_PI2 )+ {+ x = -x;+ y = -y;+ theta -= FT_ANGLE_PI;+ }++ /* Initial pseudorotation, with left shift */+ arctanptr = ft_trig_arctan_table;++ if ( theta < 0 )+ {+ xtemp = x + ( y << 1 );+ y = y - ( x << 1 );+ x = xtemp;+ theta += *arctanptr++;+ }+ else+ {+ xtemp = x - ( y << 1 );+ y = y + ( x << 1 );+ x = xtemp;+ theta -= *arctanptr++;+ }++ /* Subsequent pseudorotations, with right shifts */+ i = 0;+ do+ {+ if ( theta < 0 )+ {+ xtemp = x + ( y >> i );+ y = y - ( x >> i );+ x = xtemp;+ theta += *arctanptr++;+ }+ else+ {+ xtemp = x - ( y >> i );+ y = y + ( x >> i );+ x = xtemp;+ theta -= *arctanptr++;+ }+ } while ( ++i < FT_TRIG_MAX_ITERS );++ vec->x = x;+ vec->y = y;+ }+++ static void+ ft_trig_pseudo_polarize( FT_Vector* vec )+ {+ FT_Fixed theta;+ FT_Fixed yi, i;+ FT_Fixed x, y;+ const FT_Fixed *arctanptr;+++ x = vec->x;+ y = vec->y;++ /* Get the vector into the right half plane */+ theta = 0;+ if ( x < 0 )+ {+ x = -x;+ y = -y;+ theta = 2 * FT_ANGLE_PI2;+ }++ if ( y > 0 )+ theta = - theta;++ arctanptr = ft_trig_arctan_table;++ if ( y < 0 )+ {+ /* Rotate positive */+ yi = y + ( x << 1 );+ x = x - ( y << 1 );+ y = yi;+ theta -= *arctanptr++; /* Subtract angle */+ }+ else+ {+ /* Rotate negative */+ yi = y - ( x << 1 );+ x = x + ( y << 1 );+ y = yi;+ theta += *arctanptr++; /* Add angle */+ }++ i = 0;+ do+ {+ if ( y < 0 )+ {+ /* Rotate positive */+ yi = y + ( x >> i );+ x = x - ( y >> i );+ y = yi;+ theta -= *arctanptr++;+ }+ else+ {+ /* Rotate negative */+ yi = y - ( x >> i );+ x = x + ( y >> i );+ y = yi;+ theta += *arctanptr++;+ }+ } while ( ++i < FT_TRIG_MAX_ITERS );++ /* round theta */+ if ( theta >= 0 )+ theta = FT_PAD_ROUND( theta, 32 );+ else+ theta = -FT_PAD_ROUND( -theta, 32 );++ vec->x = x;+ vec->y = theta;+ }+++ /* documentation is in fttrigon.h */++ FT_EXPORT_DEF( FT_Fixed )+ FT_Cos( FT_Angle angle )+ {+ FT_Vector v;+++ v.x = FT_TRIG_COSCALE >> 2;+ v.y = 0;+ ft_trig_pseudo_rotate( &v, angle );++ return v.x / ( 1 << 12 );+ }+++ /* documentation is in fttrigon.h */++ FT_EXPORT_DEF( FT_Fixed )+ FT_Sin( FT_Angle angle )+ {+ return FT_Cos( FT_ANGLE_PI2 - angle );+ }+++ /* documentation is in fttrigon.h */++ FT_EXPORT_DEF( FT_Fixed )+ FT_Tan( FT_Angle angle )+ {+ FT_Vector v;+++ v.x = FT_TRIG_COSCALE >> 2;+ v.y = 0;+ ft_trig_pseudo_rotate( &v, angle );++ return FT_DivFix( v.y, v.x );+ }+++ /* documentation is in fttrigon.h */++ FT_EXPORT_DEF( FT_Angle )+ FT_Atan2( FT_Fixed dx,+ FT_Fixed dy )+ {+ FT_Vector v;+++ if ( dx == 0 && dy == 0 )+ return 0;++ v.x = dx;+ v.y = dy;+ ft_trig_prenorm( &v );+ ft_trig_pseudo_polarize( &v );++ return v.y;+ }+++ /* documentation is in fttrigon.h */++ FT_EXPORT_DEF( void )+ FT_Vector_Unit( FT_Vector* vec,+ FT_Angle angle )+ {+ vec->x = FT_TRIG_COSCALE >> 2;+ vec->y = 0;+ ft_trig_pseudo_rotate( vec, angle );+ vec->x >>= 12;+ vec->y >>= 12;+ }+++ /* these macros return 0 for positive numbers,+ and -1 for negative ones */+#define FT_SIGN_LONG( x ) ( (x) >> ( FT_SIZEOF_LONG * 8 - 1 ) )+#define FT_SIGN_INT( x ) ( (x) >> ( FT_SIZEOF_INT * 8 - 1 ) )+#define FT_SIGN_INT32( x ) ( (x) >> 31 )+#define FT_SIGN_INT16( x ) ( (x) >> 15 )+++ /* documentation is in fttrigon.h */++ FT_EXPORT_DEF( void )+ FT_Vector_Rotate( FT_Vector* vec,+ FT_Angle angle )+ {+ FT_Int shift;+ FT_Vector v;+++ v.x = vec->x;+ v.y = vec->y;++ if ( angle && ( v.x != 0 || v.y != 0 ) )+ {+ shift = ft_trig_prenorm( &v );+ ft_trig_pseudo_rotate( &v, angle );+ v.x = ft_trig_downscale( v.x );+ v.y = ft_trig_downscale( v.y );++ if ( shift > 0 )+ {+ FT_Int32 half = (FT_Int32)1L << ( shift - 1 );+++ vec->x = ( v.x + half + FT_SIGN_LONG( v.x ) ) >> shift;+ vec->y = ( v.y + half + FT_SIGN_LONG( v.y ) ) >> shift;+ }+ else+ {+ shift = -shift;+ vec->x = v.x << shift;+ vec->y = v.y << shift;+ }+ }+ }+++ /* documentation is in fttrigon.h */++ FT_EXPORT_DEF( FT_Fixed )+ FT_Vector_Length( FT_Vector* vec )+ {+ FT_Int shift;+ FT_Vector v;+++ v = *vec;++ /* handle trivial cases */+ if ( v.x == 0 )+ {+ return ( v.y >= 0 ) ? v.y : -v.y;+ }+ else if ( v.y == 0 )+ {+ return ( v.x >= 0 ) ? v.x : -v.x;+ }++ /* general case */+ shift = ft_trig_prenorm( &v );+ ft_trig_pseudo_polarize( &v );++ v.x = ft_trig_downscale( v.x );++ if ( shift > 0 )+ return ( v.x + ( 1 << ( shift - 1 ) ) ) >> shift;++ return v.x << -shift;+ }+++ /* documentation is in fttrigon.h */++ FT_EXPORT_DEF( void )+ FT_Vector_Polarize( FT_Vector* vec,+ FT_Fixed *length,+ FT_Angle *angle )+ {+ FT_Int shift;+ FT_Vector v;+++ v = *vec;++ if ( v.x == 0 && v.y == 0 )+ return;++ shift = ft_trig_prenorm( &v );+ ft_trig_pseudo_polarize( &v );++ v.x = ft_trig_downscale( v.x );++ *length = ( shift >= 0 ) ? ( v.x >> shift ) : ( v.x << -shift );+ *angle = v.y;+ }+++ /* documentation is in fttrigon.h */++ FT_EXPORT_DEF( void )+ FT_Vector_From_Polar( FT_Vector* vec,+ FT_Fixed length,+ FT_Angle angle )+ {+ vec->x = length;+ vec->y = 0;++ FT_Vector_Rotate( vec, angle );+ }+++ /* documentation is in fttrigon.h */++ FT_EXPORT_DEF( FT_Angle )+ FT_Angle_Diff( FT_Angle angle1,+ FT_Angle angle2 )+ {+ FT_Angle delta = angle2 - angle1;+++ delta %= FT_ANGLE_2PI;+ if ( delta < 0 )+ delta += FT_ANGLE_2PI;++ if ( delta > FT_ANGLE_PI )+ delta -= FT_ANGLE_2PI;++ return delta;+ }+++/* END */
+ src/base/fttype1.c view
@@ -0,0 +1,94 @@+/***************************************************************************/+/* */+/* fttype1.c */+/* */+/* FreeType utility file for PS names support (body). */+/* */+/* Copyright 2002, 2003, 2004 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_OBJECTS_H+#include FT_INTERNAL_SERVICE_H+#include FT_SERVICE_POSTSCRIPT_INFO_H+++ /* documentation is in t1tables.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Get_PS_Font_Info( FT_Face face,+ PS_FontInfoRec* afont_info )+ {+ FT_Error error = FT_Err_Invalid_Argument;+++ if ( face )+ {+ FT_Service_PsInfo service = NULL;+++ FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );++ if ( service && service->ps_get_font_info )+ error = service->ps_get_font_info( face, afont_info );+ }++ return error;+ }+++ /* documentation is in t1tables.h */++ FT_EXPORT_DEF( FT_Int )+ FT_Has_PS_Glyph_Names( FT_Face face )+ {+ FT_Int result = 0;+ FT_Service_PsInfo service = NULL;+++ if ( face )+ {+ FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );++ if ( service && service->ps_has_glyph_names )+ result = service->ps_has_glyph_names( face );+ }++ return result;+ }+++ /* documentation is in t1tables.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Get_PS_Font_Private( FT_Face face,+ PS_PrivateRec* afont_private )+ {+ FT_Error error = FT_Err_Invalid_Argument;+++ if ( face )+ {+ FT_Service_PsInfo service = NULL;+++ FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );++ if ( service && service->ps_get_font_private )+ error = service->ps_get_font_private( face, afont_private );+ }++ return error;+ }+++/* END */
+ src/base/ftutil.c view
@@ -0,0 +1,501 @@+/***************************************************************************/+/* */+/* ftutil.c */+/* */+/* FreeType utility file for memory and list management (body). */+/* */+/* Copyright 2002, 2004, 2005, 2006, 2007 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_MEMORY_H+#include FT_INTERNAL_OBJECTS_H+#include FT_LIST_H+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_memory+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** *****/+ /***** M E M O R Y M A N A G E M E N T *****/+ /***** *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ FT_BASE_DEF( FT_Pointer )+ ft_mem_alloc( FT_Memory memory,+ FT_Long size,+ FT_Error *p_error )+ {+ FT_Error error;+ FT_Pointer block = ft_mem_qalloc( memory, size, &error );++ if ( !error && size > 0 )+ FT_MEM_ZERO( block, size );++ *p_error = error;+ return block;+ }+++ FT_BASE_DEF( FT_Pointer )+ ft_mem_qalloc( FT_Memory memory,+ FT_Long size,+ FT_Error *p_error )+ {+ FT_Error error = FT_Err_Ok;+ FT_Pointer block = NULL;+++ if ( size > 0 )+ {+ block = memory->alloc( memory, size );+ if ( block == NULL )+ error = FT_Err_Out_Of_Memory;+ }+ else if ( size < 0 )+ {+ /* may help catch/prevent security issues */+ error = FT_Err_Invalid_Argument;+ }++ *p_error = error;+ return block;+ }+++ FT_BASE_DEF( FT_Pointer )+ ft_mem_realloc( FT_Memory memory,+ FT_Long item_size,+ FT_Long cur_count,+ FT_Long new_count,+ void* block,+ FT_Error *p_error )+ {+ FT_Error error = FT_Err_Ok;++ block = ft_mem_qrealloc( memory, item_size,+ cur_count, new_count, block, &error );+ if ( !error && new_count > cur_count )+ FT_MEM_ZERO( (char*)block + cur_count * item_size,+ ( new_count - cur_count ) * item_size );++ *p_error = error;+ return block;+ }+++ FT_BASE_DEF( FT_Pointer )+ ft_mem_qrealloc( FT_Memory memory,+ FT_Long item_size,+ FT_Long cur_count,+ FT_Long new_count,+ void* block,+ FT_Error *p_error )+ {+ FT_Error error = FT_Err_Ok;+++ /* Note that we now accept `item_size == 0' as a valid parameter, in+ * order to cover very weird cases where an ALLOC_MULT macro would be+ * called.+ */+ if ( cur_count < 0 || new_count < 0 || item_size < 0 )+ {+ /* may help catch/prevent nasty security issues */+ error = FT_Err_Invalid_Argument;+ }+ else if ( new_count == 0 || item_size == 0 )+ {+ ft_mem_free( memory, block );+ block = NULL;+ }+ else if ( new_count > FT_INT_MAX/item_size )+ {+ error = FT_Err_Array_Too_Large;+ }+ else if ( cur_count == 0 )+ {+ FT_ASSERT( block == NULL );++ block = ft_mem_alloc( memory, new_count*item_size, &error );+ }+ else+ {+ FT_Pointer block2;+ FT_Long cur_size = cur_count*item_size;+ FT_Long new_size = new_count*item_size;+++ block2 = memory->realloc( memory, cur_size, new_size, block );+ if ( block2 == NULL )+ error = FT_Err_Out_Of_Memory;+ else+ block = block2;+ }++ *p_error = error;+ return block;+ }+++ FT_BASE_DEF( void )+ ft_mem_free( FT_Memory memory,+ const void *P )+ {+ if ( P )+ memory->free( memory, (void*)P );+ }+++ FT_BASE_DEF( FT_Pointer )+ ft_mem_dup( FT_Memory memory,+ const void* address,+ FT_ULong size,+ FT_Error *p_error )+ {+ FT_Error error;+ FT_Pointer p = ft_mem_qalloc( memory, size, &error );+++ if ( !error && address )+ ft_memcpy( p, address, size );++ *p_error = error;+ return p;+ }+++ FT_BASE_DEF( FT_Pointer )+ ft_mem_strdup( FT_Memory memory,+ const char* str,+ FT_Error *p_error )+ {+ FT_ULong len = str ? (FT_ULong)ft_strlen( str ) + 1+ : 0;+++ return ft_mem_dup( memory, str, len, p_error );+ }+++ FT_BASE_DEF( FT_Int )+ ft_mem_strcpyn( char* dst,+ const char* src,+ FT_ULong size )+ {+ while ( size > 1 && *src != 0 )+ {+ *dst++ = *src++;+ size--;+ }++ *dst = 0; /* always zero-terminate */++ return *src != 0;+ }+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** *****/+ /***** D O U B L Y L I N K E D L I S T S *****/+ /***** *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/++#undef FT_COMPONENT+#define FT_COMPONENT trace_list++ /* documentation is in ftlist.h */++ FT_EXPORT_DEF( FT_ListNode )+ FT_List_Find( FT_List list,+ void* data )+ {+ FT_ListNode cur;+++ cur = list->head;+ while ( cur )+ {+ if ( cur->data == data )+ return cur;++ cur = cur->next;+ }++ return (FT_ListNode)0;+ }+++ /* documentation is in ftlist.h */++ FT_EXPORT_DEF( void )+ FT_List_Add( FT_List list,+ FT_ListNode node )+ {+ FT_ListNode before = list->tail;+++ node->next = 0;+ node->prev = before;++ if ( before )+ before->next = node;+ else+ list->head = node;++ list->tail = node;+ }+++ /* documentation is in ftlist.h */++ FT_EXPORT_DEF( void )+ FT_List_Insert( FT_List list,+ FT_ListNode node )+ {+ FT_ListNode after = list->head;+++ node->next = after;+ node->prev = 0;++ if ( !after )+ list->tail = node;+ else+ after->prev = node;++ list->head = node;+ }+++ /* documentation is in ftlist.h */++ FT_EXPORT_DEF( void )+ FT_List_Remove( FT_List list,+ FT_ListNode node )+ {+ FT_ListNode before, after;+++ before = node->prev;+ after = node->next;++ if ( before )+ before->next = after;+ else+ list->head = after;++ if ( after )+ after->prev = before;+ else+ list->tail = before;+ }+++ /* documentation is in ftlist.h */++ FT_EXPORT_DEF( void )+ FT_List_Up( FT_List list,+ FT_ListNode node )+ {+ FT_ListNode before, after;+++ before = node->prev;+ after = node->next;++ /* check whether we are already on top of the list */+ if ( !before )+ return;++ before->next = after;++ if ( after )+ after->prev = before;+ else+ list->tail = before;++ node->prev = 0;+ node->next = list->head;+ list->head->prev = node;+ list->head = node;+ }+++ /* documentation is in ftlist.h */++ FT_EXPORT_DEF( FT_Error )+ FT_List_Iterate( FT_List list,+ FT_List_Iterator iterator,+ void* user )+ {+ FT_ListNode cur = list->head;+ FT_Error error = FT_Err_Ok;+++ while ( cur )+ {+ FT_ListNode next = cur->next;+++ error = iterator( cur, user );+ if ( error )+ break;++ cur = next;+ }++ return error;+ }+++ /* documentation is in ftlist.h */++ FT_EXPORT_DEF( void )+ FT_List_Finalize( FT_List list,+ FT_List_Destructor destroy,+ FT_Memory memory,+ void* user )+ {+ FT_ListNode cur;+++ cur = list->head;+ while ( cur )+ {+ FT_ListNode next = cur->next;+ void* data = cur->data;+++ if ( destroy )+ destroy( memory, data, user );++ FT_FREE( cur );+ cur = next;+ }++ list->head = 0;+ list->tail = 0;+ }+++ FT_BASE_DEF( FT_UInt32 )+ ft_highpow2( FT_UInt32 value )+ {+ FT_UInt32 value2;+++ /*+ * We simply clear the lowest bit in each iteration. When+ * we reach 0, we know that the previous value was our result.+ */+ for ( ;; )+ {+ value2 = value & (value - 1); /* clear lowest bit */+ if ( value2 == 0 )+ break;++ value = value2;+ }+ return value;+ }+++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS++ FT_BASE_DEF( FT_Error )+ FT_Alloc( FT_Memory memory,+ FT_Long size,+ void* *P )+ {+ FT_Error error;+++ (void)FT_ALLOC( *P, size );+ return error;+ }+++ FT_BASE_DEF( FT_Error )+ FT_QAlloc( FT_Memory memory,+ FT_Long size,+ void* *p )+ {+ FT_Error error;+++ (void)FT_QALLOC( *p, size );+ return error;+ }+++ FT_BASE_DEF( FT_Error )+ FT_Realloc( FT_Memory memory,+ FT_Long current,+ FT_Long size,+ void* *P )+ {+ FT_Error error;+++ (void)FT_REALLOC( *P, current, size );+ return error;+ }+++ FT_BASE_DEF( FT_Error )+ FT_QRealloc( FT_Memory memory,+ FT_Long current,+ FT_Long size,+ void* *p )+ {+ FT_Error error;+++ (void)FT_QREALLOC( *p, current, size );+ return error;+ }+++ FT_BASE_DEF( void )+ FT_Free( FT_Memory memory,+ void* *P )+ {+ if ( *P )+ FT_MEM_FREE( *P );+ }++#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */++/* END */
+ src/base/ftwinfnt.c view
@@ -0,0 +1,51 @@+/***************************************************************************/+/* */+/* ftwinfnt.c */+/* */+/* FreeType API for accessing Windows FNT specific info (body). */+/* */+/* Copyright 2003, 2004 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_WINFONTS_H+#include FT_INTERNAL_OBJECTS_H+#include FT_SERVICE_WINFNT_H+++ /* documentation is in ftwinfnt.h */++ FT_EXPORT_DEF( FT_Error )+ FT_Get_WinFNT_Header( FT_Face face,+ FT_WinFNT_HeaderRec *header )+ {+ FT_Service_WinFnt service;+ FT_Error error;+++ error = FT_Err_Invalid_Argument;++ if ( face != NULL )+ {+ FT_FACE_LOOKUP_SERVICE( face, service, WINFNT );++ if ( service != NULL )+ {+ error = service->get_header( face, header );+ }+ }++ return error;+ }+++/* END */
+ src/base/ftxf86.c view
@@ -0,0 +1,40 @@+/***************************************************************************/+/* */+/* ftxf86.c */+/* */+/* FreeType utility file for X11 support (body). */+/* */+/* Copyright 2002, 2003, 2004 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_XFREE86_H+#include FT_INTERNAL_OBJECTS_H+#include FT_SERVICE_XFREE86_NAME_H+++ /* documentation is in ftxf86.h */++ FT_EXPORT_DEF( const char* )+ FT_Get_X11_Font_Format( FT_Face face )+ {+ const char* result = NULL;+++ if ( face )+ FT_FACE_FIND_SERVICE( face, result, XF86_NAME );++ return result;+ }+++/* END */
+ src/bdf/bdf.c view
@@ -0,0 +1,34 @@+/* bdf.c++ FreeType font driver for bdf files++ Copyright (C) 2001, 2002 by+ Francesco Zappa Nardelli++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in+all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+THE SOFTWARE.+*/++#define FT_MAKE_OPTION_SINGLE_OBJECT++#include <ft2build.h>+#include "bdflib.c"+#include "bdfdrivr.c"+++/* END */
+ src/bdf/bdf.h view
@@ -0,0 +1,295 @@+/*+ * Copyright 2000 Computing Research Labs, New Mexico State University+ * Copyright 2001, 2002, 2003, 2004 Francesco Zappa Nardelli+ *+ * Permission is hereby granted, free of charge, to any person obtaining a+ * copy of this software and associated documentation files (the "Software"),+ * to deal in the Software without restriction, including without limitation+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,+ * and/or sell copies of the Software, and to permit persons to whom the+ * Software is furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL+ * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT+ * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE.+ */+++#ifndef __BDF_H__+#define __BDF_H__+++/*+ * Based on bdf.h,v 1.16 2000/03/16 20:08:51 mleisher+ */++#include <ft2build.h>+#include FT_INTERNAL_OBJECTS_H+#include FT_INTERNAL_STREAM_H+++FT_BEGIN_HEADER+++/* Imported from bdfP.h */++#define _bdf_glyph_modified( map, e ) \+ ( (map)[(e) >> 5] & ( 1 << ( (e) & 31 ) ) )+#define _bdf_set_glyph_modified( map, e ) \+ ( (map)[(e) >> 5] |= ( 1 << ( (e) & 31 ) ) )+#define _bdf_clear_glyph_modified( map, e ) \+ ( (map)[(e) >> 5] &= ~( 1 << ( (e) & 31 ) ) )++/* end of bdfP.h */+++ /*************************************************************************/+ /* */+ /* BDF font options macros and types. */+ /* */+ /*************************************************************************/+++#define BDF_CORRECT_METRICS 0x01 /* Correct invalid metrics when loading. */+#define BDF_KEEP_COMMENTS 0x02 /* Preserve the font comments. */+#define BDF_KEEP_UNENCODED 0x04 /* Keep the unencoded glyphs. */+#define BDF_PROPORTIONAL 0x08 /* Font has proportional spacing. */+#define BDF_MONOWIDTH 0x10 /* Font has mono width. */+#define BDF_CHARCELL 0x20 /* Font has charcell spacing. */++#define BDF_ALL_SPACING ( BDF_PROPORTIONAL | \+ BDF_MONOWIDTH | \+ BDF_CHARCELL )++#define BDF_DEFAULT_LOAD_OPTIONS ( BDF_CORRECT_METRICS | \+ BDF_KEEP_COMMENTS | \+ BDF_KEEP_UNENCODED | \+ BDF_PROPORTIONAL )+++ typedef struct bdf_options_t_+ {+ int correct_metrics;+ int keep_unencoded;+ int keep_comments;+ int font_spacing;++ } bdf_options_t;+++ /* Callback function type for unknown configuration options. */+ typedef int+ (*bdf_options_callback_t)( bdf_options_t* opts,+ char** params,+ unsigned long nparams,+ void* client_data );+++ /*************************************************************************/+ /* */+ /* BDF font property macros and types. */+ /* */+ /*************************************************************************/+++#define BDF_ATOM 1+#define BDF_INTEGER 2+#define BDF_CARDINAL 3+++ /* This structure represents a particular property of a font. */+ /* There are a set of defaults and each font has their own. */+ typedef struct bdf_property_t_+ {+ char* name; /* Name of the property. */+ int format; /* Format of the property. */+ int builtin; /* A builtin property. */+ union+ {+ char* atom;+ long l;+ unsigned long ul;++ } value; /* Value of the property. */++ } bdf_property_t;+++ /*************************************************************************/+ /* */+ /* BDF font metric and glyph types. */+ /* */+ /*************************************************************************/+++ typedef struct bdf_bbx_t_+ {+ unsigned short width;+ unsigned short height;++ short x_offset;+ short y_offset;++ short ascent;+ short descent;++ } bdf_bbx_t;+++ typedef struct bdf_glyph_t_+ {+ char* name; /* Glyph name. */+ long encoding; /* Glyph encoding. */+ unsigned short swidth; /* Scalable width. */+ unsigned short dwidth; /* Device width. */+ bdf_bbx_t bbx; /* Glyph bounding box. */+ unsigned char* bitmap; /* Glyph bitmap. */+ unsigned long bpr; /* Number of bytes used per row. */+ unsigned short bytes; /* Number of bytes used for the bitmap. */++ } bdf_glyph_t;+++ typedef struct _hashnode_+ {+ const char* key;+ size_t data;++ } _hashnode, *hashnode;+++ typedef struct hashtable_+ {+ int limit;+ int size;+ int used;+ hashnode* table;++ } hashtable;+++ typedef struct bdf_glyphlist_t_+ {+ unsigned short pad; /* Pad to 4-byte boundary. */+ unsigned short bpp; /* Bits per pixel. */+ long start; /* Beginning encoding value of glyphs. */+ long end; /* Ending encoding value of glyphs. */+ bdf_glyph_t* glyphs; /* Glyphs themselves. */+ unsigned long glyphs_size; /* Glyph structures allocated. */+ unsigned long glyphs_used; /* Glyph structures used. */+ bdf_bbx_t bbx; /* Overall bounding box of glyphs. */++ } bdf_glyphlist_t;+++ typedef struct bdf_font_t_+ {+ char* name; /* Name of the font. */+ bdf_bbx_t bbx; /* Font bounding box. */++ long point_size; /* Point size of the font. */+ unsigned long resolution_x; /* Font horizontal resolution. */+ unsigned long resolution_y; /* Font vertical resolution. */++ int spacing; /* Font spacing value. */++ unsigned short monowidth; /* Logical width for monowidth font. */++ long default_char; /* Encoding of the default glyph. */++ long font_ascent; /* Font ascent. */+ long font_descent; /* Font descent. */++ unsigned long glyphs_size; /* Glyph structures allocated. */+ unsigned long glyphs_used; /* Glyph structures used. */+ bdf_glyph_t* glyphs; /* Glyphs themselves. */++ unsigned long unencoded_size; /* Unencoded glyph struct. allocated. */+ unsigned long unencoded_used; /* Unencoded glyph struct. used. */+ bdf_glyph_t* unencoded; /* Unencoded glyphs themselves. */++ unsigned long props_size; /* Font properties allocated. */+ unsigned long props_used; /* Font properties used. */+ bdf_property_t* props; /* Font properties themselves. */++ char* comments; /* Font comments. */+ unsigned long comments_len; /* Length of comment string. */++ bdf_glyphlist_t overflow; /* Storage used for glyph insertion. */++ void* internal; /* Internal data for the font. */++ unsigned long nmod[2048]; /* Bitmap indicating modified glyphs. */+ unsigned long umod[2048]; /* Bitmap indicating modified */+ /* unencoded glyphs. */+ unsigned short modified; /* Boolean indicating font modified. */+ unsigned short bpp; /* Bits per pixel. */++ FT_Memory memory;++ bdf_property_t* user_props;+ unsigned long nuser_props;+ hashtable proptbl;++ } bdf_font_t;+++ /*************************************************************************/+ /* */+ /* Types for load/save callbacks. */+ /* */+ /*************************************************************************/+++ /* Error codes. */+#define BDF_MISSING_START -1+#define BDF_MISSING_FONTNAME -2+#define BDF_MISSING_SIZE -3+#define BDF_MISSING_CHARS -4+#define BDF_MISSING_STARTCHAR -5+#define BDF_MISSING_ENCODING -6+#define BDF_MISSING_BBX -7++#define BDF_OUT_OF_MEMORY -20++#define BDF_INVALID_LINE -100+++ /*************************************************************************/+ /* */+ /* BDF font API. */+ /* */+ /*************************************************************************/++ FT_LOCAL( FT_Error )+ bdf_load_font( FT_Stream stream,+ FT_Memory memory,+ bdf_options_t* opts,+ bdf_font_t* *font );++ FT_LOCAL( void )+ bdf_free_font( bdf_font_t* font );++ FT_LOCAL( bdf_property_t * )+ bdf_get_property( char* name,+ bdf_font_t* font );++ FT_LOCAL( bdf_property_t * )+ bdf_get_font_property( bdf_font_t* font,+ const char* name );+++FT_END_HEADER+++#endif /* __BDF_H__ */+++/* END */
+ src/bdf/bdfdrivr.c view
@@ -0,0 +1,881 @@+/* bdfdrivr.c++ FreeType font driver for bdf files++ Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by+ Francesco Zappa Nardelli++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in+all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+THE SOFTWARE.+*/++#include <ft2build.h>++#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_STREAM_H+#include FT_INTERNAL_OBJECTS_H+#include FT_BDF_H+#include FT_TRUETYPE_IDS_H ++#include FT_SERVICE_BDF_H+#include FT_SERVICE_XFREE86_NAME_H++#include "bdf.h"+#include "bdfdrivr.h"++#include "bdferror.h"+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_bdfdriver+++ typedef struct BDF_CMapRec_+ {+ FT_CMapRec cmap;+ FT_ULong num_encodings; /* ftobjs.h: FT_CMap->clazz->size */+ BDF_encoding_el* encodings;++ } BDF_CMapRec, *BDF_CMap;+++ FT_CALLBACK_DEF( FT_Error )+ bdf_cmap_init( FT_CMap bdfcmap,+ FT_Pointer init_data )+ {+ BDF_CMap cmap = (BDF_CMap)bdfcmap;+ BDF_Face face = (BDF_Face)FT_CMAP_FACE( cmap );+ FT_UNUSED( init_data );+++ cmap->num_encodings = face->bdffont->glyphs_used;+ cmap->encodings = face->en_table;++ return BDF_Err_Ok;+ }+++ FT_CALLBACK_DEF( void )+ bdf_cmap_done( FT_CMap bdfcmap )+ {+ BDF_CMap cmap = (BDF_CMap)bdfcmap;+++ cmap->encodings = NULL;+ cmap->num_encodings = 0;+ }+++ FT_CALLBACK_DEF( FT_UInt )+ bdf_cmap_char_index( FT_CMap bdfcmap,+ FT_UInt32 charcode )+ {+ BDF_CMap cmap = (BDF_CMap)bdfcmap;+ BDF_encoding_el* encodings = cmap->encodings;+ FT_ULong min, max, mid; /* num_encodings */+ FT_UShort result = 0; /* encodings->glyph */+++ min = 0;+ max = cmap->num_encodings;++ while ( min < max )+ {+ FT_ULong code;+++ mid = ( min + max ) >> 1;+ code = encodings[mid].enc;++ if ( charcode == code )+ {+ /* increase glyph index by 1 -- */+ /* we reserve slot 0 for the undefined glyph */+ result = encodings[mid].glyph + 1;+ break;+ }++ if ( charcode < code )+ max = mid;+ else+ min = mid + 1;+ }++ return result;+ }+++ FT_CALLBACK_DEF( FT_UInt )+ bdf_cmap_char_next( FT_CMap bdfcmap,+ FT_UInt32 *acharcode )+ {+ BDF_CMap cmap = (BDF_CMap)bdfcmap;+ BDF_encoding_el* encodings = cmap->encodings;+ FT_ULong min, max, mid; /* num_encodings */+ FT_UShort result = 0; /* encodings->glyph */+ FT_ULong charcode = *acharcode + 1;+++ min = 0;+ max = cmap->num_encodings;++ while ( min < max )+ {+ FT_ULong code; /* same as BDF_encoding_el.enc */+++ mid = ( min + max ) >> 1;+ code = encodings[mid].enc;++ if ( charcode == code )+ {+ /* increase glyph index by 1 -- */+ /* we reserve slot 0 for the undefined glyph */+ result = encodings[mid].glyph + 1;+ goto Exit;+ }++ if ( charcode < code )+ max = mid;+ else+ min = mid + 1;+ }++ charcode = 0;+ if ( min < cmap->num_encodings )+ {+ charcode = encodings[min].enc;+ result = encodings[min].glyph + 1;+ }++ Exit:+ if ( charcode > 0xFFFFFFFFUL )+ {+ FT_TRACE1(( "bdf_cmap_char_next: charcode 0x%x > 32bit API" ));+ *acharcode = 0;+ /* XXX: result should be changed to indicate an overflow error */+ }+ else+ *acharcode = (FT_UInt32)charcode;+ return result;+ }+++ FT_CALLBACK_TABLE_DEF+ const FT_CMap_ClassRec bdf_cmap_class =+ {+ sizeof ( BDF_CMapRec ),+ bdf_cmap_init,+ bdf_cmap_done,+ bdf_cmap_char_index,+ bdf_cmap_char_next,++ NULL, NULL, NULL, NULL, NULL+ };+++ static FT_Error+ bdf_interpret_style( BDF_Face bdf )+ {+ FT_Error error = BDF_Err_Ok;+ FT_Face face = FT_FACE( bdf );+ FT_Memory memory = face->memory;+ bdf_font_t* font = bdf->bdffont;+ bdf_property_t* prop;++ char* strings[4] = { NULL, NULL, NULL, NULL };+ size_t nn, len, lengths[4];+++ face->style_flags = 0;++ prop = bdf_get_font_property( font, (char *)"SLANT" );+ if ( prop && prop->format == BDF_ATOM &&+ prop->value.atom &&+ ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' ||+ *(prop->value.atom) == 'I' || *(prop->value.atom) == 'i' ) )+ {+ face->style_flags |= FT_STYLE_FLAG_ITALIC;+ strings[2] = ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' )+ ? (char *)"Oblique"+ : (char *)"Italic";+ }++ prop = bdf_get_font_property( font, (char *)"WEIGHT_NAME" );+ if ( prop && prop->format == BDF_ATOM &&+ prop->value.atom &&+ ( *(prop->value.atom) == 'B' || *(prop->value.atom) == 'b' ) )+ {+ face->style_flags |= FT_STYLE_FLAG_BOLD;+ strings[1] = (char *)"Bold";+ }++ prop = bdf_get_font_property( font, (char *)"SETWIDTH_NAME" );+ if ( prop && prop->format == BDF_ATOM &&+ prop->value.atom && *(prop->value.atom) &&+ !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )+ strings[3] = (char *)(prop->value.atom);++ prop = bdf_get_font_property( font, (char *)"ADD_STYLE_NAME" );+ if ( prop && prop->format == BDF_ATOM &&+ prop->value.atom && *(prop->value.atom) &&+ !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )+ strings[0] = (char *)(prop->value.atom);++ len = 0;++ for ( len = 0, nn = 0; nn < 4; nn++ )+ {+ lengths[nn] = 0;+ if ( strings[nn] )+ {+ lengths[nn] = ft_strlen( strings[nn] );+ len += lengths[nn] + 1;+ }+ }++ if ( len == 0 )+ {+ strings[0] = (char *)"Regular";+ lengths[0] = ft_strlen( strings[0] );+ len = lengths[0] + 1;+ }++ {+ char* s;+++ if ( FT_ALLOC( face->style_name, len ) )+ return error;++ s = face->style_name;++ for ( nn = 0; nn < 4; nn++ )+ {+ char* src = strings[nn];+++ len = lengths[nn];++ if ( src == NULL )+ continue;++ /* separate elements with a space */+ if ( s != face->style_name )+ *s++ = ' ';++ ft_memcpy( s, src, len );++ /* need to convert spaces to dashes for */+ /* add_style_name and setwidth_name */+ if ( nn == 0 || nn == 3 )+ {+ size_t mm;+++ for ( mm = 0; mm < len; mm++ )+ if ( s[mm] == ' ' )+ s[mm] = '-';+ }++ s += len;+ }+ *s = 0;+ }++ return error;+ }+++ FT_CALLBACK_DEF( void )+ BDF_Face_Done( FT_Face bdfface ) /* BDF_Face */+ {+ BDF_Face face = (BDF_Face)bdfface;+ FT_Memory memory;+++ if ( !face )+ return;++ memory = FT_FACE_MEMORY( face );++ bdf_free_font( face->bdffont );++ FT_FREE( face->en_table );++ FT_FREE( face->charset_encoding );+ FT_FREE( face->charset_registry );+ FT_FREE( bdfface->family_name );+ FT_FREE( bdfface->style_name );++ FT_FREE( bdfface->available_sizes );++ FT_FREE( face->bdffont );++ FT_TRACE4(( "BDF_Face_Done: done face\n" ));+ }+++ FT_CALLBACK_DEF( FT_Error )+ BDF_Face_Init( FT_Stream stream,+ FT_Face bdfface, /* BDF_Face */+ FT_Int face_index,+ FT_Int num_params,+ FT_Parameter* params )+ {+ FT_Error error = BDF_Err_Ok;+ BDF_Face face = (BDF_Face)bdfface;+ FT_Memory memory = FT_FACE_MEMORY( face );++ bdf_font_t* font = NULL;+ bdf_options_t options;++ FT_UNUSED( num_params );+ FT_UNUSED( params );+ FT_UNUSED( face_index );+++ if ( FT_STREAM_SEEK( 0 ) )+ goto Exit;++ options.correct_metrics = 1; /* FZ XXX: options semantics */+ options.keep_unencoded = 1;+ options.keep_comments = 0;+ options.font_spacing = BDF_PROPORTIONAL;++ error = bdf_load_font( stream, memory, &options, &font );+ if ( error == BDF_Err_Missing_Startfont_Field )+ {+ FT_TRACE2(( "[not a valid BDF file]\n" ));+ goto Fail;+ }+ else if ( error )+ goto Exit;++ /* we have a bdf font: let's construct the face object */+ face->bdffont = font;+ {+ bdf_property_t* prop = NULL;+++ FT_TRACE4(( "number of glyphs: %d (%d)\n",+ font->glyphs_size,+ font->glyphs_used ));+ FT_TRACE4(( "number of unencoded glyphs: %d (%d)\n",+ font->unencoded_size,+ font->unencoded_used ));++ bdfface->num_faces = 1;+ bdfface->face_index = 0;+ bdfface->face_flags = FT_FACE_FLAG_FIXED_SIZES |+ FT_FACE_FLAG_HORIZONTAL |+ FT_FACE_FLAG_FAST_GLYPHS;++ prop = bdf_get_font_property( font, "SPACING" );+ if ( prop && prop->format == BDF_ATOM &&+ prop->value.atom &&+ ( *(prop->value.atom) == 'M' || *(prop->value.atom) == 'm' ||+ *(prop->value.atom) == 'C' || *(prop->value.atom) == 'c' ) )+ bdfface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;++ /* FZ XXX: TO DO: FT_FACE_FLAGS_VERTICAL */+ /* FZ XXX: I need a font to implement this */++ prop = bdf_get_font_property( font, "FAMILY_NAME" );+ if ( prop && prop->value.atom )+ {+ if ( FT_STRDUP( bdfface->family_name, prop->value.atom ) )+ goto Exit;+ }+ else+ bdfface->family_name = 0;++ if ( ( error = bdf_interpret_style( face ) ) != 0 )+ goto Exit;++ /* the number of glyphs (with one slot for the undefined glyph */+ /* at position 0 and all unencoded glyphs) */+ bdfface->num_glyphs = font->glyphs_size + 1;++ bdfface->num_fixed_sizes = 1;+ if ( FT_NEW_ARRAY( bdfface->available_sizes, 1 ) )+ goto Exit;++ {+ FT_Bitmap_Size* bsize = bdfface->available_sizes;+ FT_Short resolution_x = 0, resolution_y = 0;+++ FT_MEM_ZERO( bsize, sizeof ( FT_Bitmap_Size ) );++ bsize->height = (FT_Short)( font->font_ascent + font->font_descent );++ prop = bdf_get_font_property( font, "AVERAGE_WIDTH" );+ if ( prop )+ bsize->width = (FT_Short)( ( prop->value.l + 5 ) / 10 );+ else+ bsize->width = (FT_Short)( bsize->height * 2/3 );++ prop = bdf_get_font_property( font, "POINT_SIZE" );+ if ( prop )+ /* convert from 722.7 decipoints to 72 points per inch */+ bsize->size =+ (FT_Pos)( ( prop->value.l * 64 * 7200 + 36135L ) / 72270L );+ else+ bsize->size = bsize->width << 6;++ prop = bdf_get_font_property( font, "PIXEL_SIZE" );+ if ( prop )+ bsize->y_ppem = (FT_Short)prop->value.l << 6;++ prop = bdf_get_font_property( font, "RESOLUTION_X" );+ if ( prop )+ resolution_x = (FT_Short)prop->value.l;++ prop = bdf_get_font_property( font, "RESOLUTION_Y" );+ if ( prop )+ resolution_y = (FT_Short)prop->value.l;++ if ( bsize->y_ppem == 0 )+ {+ bsize->y_ppem = bsize->size;+ if ( resolution_y )+ bsize->y_ppem = bsize->y_ppem * resolution_y / 72;+ }+ if ( resolution_x && resolution_y )+ bsize->x_ppem = bsize->y_ppem * resolution_x / resolution_y;+ else+ bsize->x_ppem = bsize->y_ppem;+ }++ /* encoding table */+ {+ bdf_glyph_t* cur = font->glyphs;+ unsigned long n;+++ if ( FT_NEW_ARRAY( face->en_table, font->glyphs_size ) )+ goto Exit;++ face->default_glyph = 0;+ for ( n = 0; n < font->glyphs_size; n++ )+ {+ (face->en_table[n]).enc = cur[n].encoding;+ FT_TRACE4(( "idx %d, val 0x%lX\n", n, cur[n].encoding ));+ (face->en_table[n]).glyph = (FT_Short)n;++ if ( cur[n].encoding == font->default_char )+ {+ if ( n < FT_UINT_MAX )+ face->default_glyph = (FT_UInt)n;+ else+ FT_TRACE1(( "idx %d is too large for this system\n", n ));+ }+ }+ }++ /* charmaps */+ {+ bdf_property_t *charset_registry = 0, *charset_encoding = 0;+ FT_Bool unicode_charmap = 0;+++ charset_registry =+ bdf_get_font_property( font, "CHARSET_REGISTRY" );+ charset_encoding =+ bdf_get_font_property( font, "CHARSET_ENCODING" );+ if ( charset_registry && charset_encoding )+ {+ if ( charset_registry->format == BDF_ATOM &&+ charset_encoding->format == BDF_ATOM &&+ charset_registry->value.atom &&+ charset_encoding->value.atom )+ {+ const char* s;+++ if ( FT_STRDUP( face->charset_encoding,+ charset_encoding->value.atom ) ||+ FT_STRDUP( face->charset_registry,+ charset_registry->value.atom ) )+ goto Exit;++ /* Uh, oh, compare first letters manually to avoid dependency */+ /* on locales. */+ s = face->charset_registry;+ if ( ( s[0] == 'i' || s[0] == 'I' ) &&+ ( s[1] == 's' || s[1] == 'S' ) &&+ ( s[2] == 'o' || s[2] == 'O' ) )+ {+ s += 3;+ if ( !ft_strcmp( s, "10646" ) ||+ ( !ft_strcmp( s, "8859" ) &&+ !ft_strcmp( face->charset_encoding, "1" ) ) )+ unicode_charmap = 1;+ }++ {+ FT_CharMapRec charmap;+++ charmap.face = FT_FACE( face );+ charmap.encoding = FT_ENCODING_NONE;+ /* initial platform/encoding should indicate unset status? */+ charmap.platform_id = TT_PLATFORM_APPLE_UNICODE;+ charmap.encoding_id = TT_APPLE_ID_DEFAULT;++ if ( unicode_charmap )+ {+ charmap.encoding = FT_ENCODING_UNICODE;+ charmap.platform_id = TT_PLATFORM_MICROSOFT;+ charmap.encoding_id = TT_MS_ID_UNICODE_CS;+ }++ error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );++#if 0+ /* Select default charmap */+ if ( bdfface->num_charmaps )+ bdfface->charmap = bdfface->charmaps[0];+#endif+ }++ goto Exit;+ }+ }++ /* otherwise assume Adobe standard encoding */++ {+ FT_CharMapRec charmap;+++ charmap.face = FT_FACE( face );+ charmap.encoding = FT_ENCODING_ADOBE_STANDARD;+ charmap.platform_id = TT_PLATFORM_ADOBE;+ charmap.encoding_id = TT_ADOBE_ID_STANDARD;++ error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );++ /* Select default charmap */+ if ( bdfface->num_charmaps )+ bdfface->charmap = bdfface->charmaps[0];+ }+ }+ }++ Exit:+ return error;++ Fail:+ BDF_Face_Done( bdfface );+ return BDF_Err_Unknown_File_Format;+ }+++ FT_CALLBACK_DEF( FT_Error )+ BDF_Size_Select( FT_Size size,+ FT_ULong strike_index )+ {+ bdf_font_t* bdffont = ( (BDF_Face)size->face )->bdffont;+++ FT_Select_Metrics( size->face, strike_index );++ size->metrics.ascender = bdffont->font_ascent << 6;+ size->metrics.descender = -bdffont->font_descent << 6;+ size->metrics.max_advance = bdffont->bbx.width << 6;++ return BDF_Err_Ok;+ }+++ FT_CALLBACK_DEF( FT_Error )+ BDF_Size_Request( FT_Size size,+ FT_Size_Request req )+ {+ FT_Face face = size->face;+ FT_Bitmap_Size* bsize = face->available_sizes;+ bdf_font_t* bdffont = ( (BDF_Face)face )->bdffont;+ FT_Error error = BDF_Err_Invalid_Pixel_Size;+ FT_Long height;+++ height = FT_REQUEST_HEIGHT( req );+ height = ( height + 32 ) >> 6;++ switch ( req->type )+ {+ case FT_SIZE_REQUEST_TYPE_NOMINAL:+ if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) )+ error = BDF_Err_Ok;+ break;++ case FT_SIZE_REQUEST_TYPE_REAL_DIM:+ if ( height == ( bdffont->font_ascent ++ bdffont->font_descent ) )+ error = BDF_Err_Ok;+ break;++ default:+ error = BDF_Err_Unimplemented_Feature;+ break;+ }++ if ( error )+ return error;+ else+ return BDF_Size_Select( size, 0 );+ }++++ FT_CALLBACK_DEF( FT_Error )+ BDF_Glyph_Load( FT_GlyphSlot slot,+ FT_Size size,+ FT_UInt glyph_index,+ FT_Int32 load_flags )+ {+ BDF_Face bdf = (BDF_Face)FT_SIZE_FACE( size );+ FT_Face face = FT_FACE( bdf );+ FT_Error error = BDF_Err_Ok;+ FT_Bitmap* bitmap = &slot->bitmap;+ bdf_glyph_t glyph;+ int bpp = bdf->bdffont->bpp;++ FT_UNUSED( load_flags );+++ if ( !face || glyph_index >= (FT_UInt)face->num_glyphs )+ {+ error = BDF_Err_Invalid_Argument;+ goto Exit;+ }++ /* index 0 is the undefined glyph */+ if ( glyph_index == 0 )+ glyph_index = bdf->default_glyph;+ else+ glyph_index--;++ /* slot, bitmap => freetype, glyph => bdflib */+ glyph = bdf->bdffont->glyphs[glyph_index];++ bitmap->rows = glyph.bbx.height;+ bitmap->width = glyph.bbx.width;+ if ( glyph.bpr > INT_MAX )+ FT_TRACE1(( "BDF_Glyph_Load: too large pitch %d is truncated\n",+ glyph.bpr ));+ bitmap->pitch = (int)glyph.bpr; /* same as FT_Bitmap.pitch */++ /* note: we don't allocate a new array to hold the bitmap; */+ /* we can simply point to it */+ ft_glyphslot_set_bitmap( slot, glyph.bitmap );++ switch ( bpp )+ {+ case 1:+ bitmap->pixel_mode = FT_PIXEL_MODE_MONO;+ break;+ case 2:+ bitmap->pixel_mode = FT_PIXEL_MODE_GRAY2;+ break;+ case 4:+ bitmap->pixel_mode = FT_PIXEL_MODE_GRAY4;+ break;+ case 8:+ bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;+ bitmap->num_grays = 256;+ break;+ }++ slot->format = FT_GLYPH_FORMAT_BITMAP;+ slot->bitmap_left = glyph.bbx.x_offset;+ slot->bitmap_top = glyph.bbx.ascent;++ slot->metrics.horiAdvance = glyph.dwidth << 6;+ slot->metrics.horiBearingX = glyph.bbx.x_offset << 6;+ slot->metrics.horiBearingY = glyph.bbx.ascent << 6;+ slot->metrics.width = bitmap->width << 6;+ slot->metrics.height = bitmap->rows << 6;++ /*+ * XXX DWIDTH1 and VVECTOR should be parsed and+ * used here, provided such fonts do exist.+ */+ ft_synthesize_vertical_metrics( &slot->metrics,+ bdf->bdffont->bbx.height << 6 );++ Exit:+ return error;+ }+++ /*+ *+ * BDF SERVICE+ *+ */++ static FT_Error+ bdf_get_bdf_property( BDF_Face face,+ const char* prop_name,+ BDF_PropertyRec *aproperty )+ {+ bdf_property_t* prop;+++ FT_ASSERT( face && face->bdffont );++ prop = bdf_get_font_property( face->bdffont, prop_name );+ if ( prop )+ {+ switch ( prop->format )+ {+ case BDF_ATOM:+ aproperty->type = BDF_PROPERTY_TYPE_ATOM;+ aproperty->u.atom = prop->value.atom;+ break;++ case BDF_INTEGER:+ if ( prop->value.l > 0x7FFFFFFFL || prop->value.l < ( -1 - 0x7FFFFFFFL ) )+ {+ FT_TRACE1(( "bdf_get_bdf_property: " ));+ FT_TRACE1(( "too large integer 0x%x is truncated\n" ));+ }+ aproperty->type = BDF_PROPERTY_TYPE_INTEGER;+ aproperty->u.integer = (FT_Int32)prop->value.l;+ break;++ case BDF_CARDINAL:+ if ( prop->value.ul > 0xFFFFFFFFUL )+ {+ FT_TRACE1(( "bdf_get_bdf_property: " ));+ FT_TRACE1(( "too large cardinal 0x%x is truncated\n" ));+ }+ aproperty->type = BDF_PROPERTY_TYPE_CARDINAL;+ aproperty->u.cardinal = (FT_UInt32)prop->value.ul;+ break;++ default:+ goto Fail;+ }+ return 0;+ }++ Fail:+ return BDF_Err_Invalid_Argument;+ }+++ static FT_Error+ bdf_get_charset_id( BDF_Face face,+ const char* *acharset_encoding,+ const char* *acharset_registry )+ {+ *acharset_encoding = face->charset_encoding;+ *acharset_registry = face->charset_registry;++ return 0;+ }+++ static const FT_Service_BDFRec bdf_service_bdf =+ {+ (FT_BDF_GetCharsetIdFunc)bdf_get_charset_id,+ (FT_BDF_GetPropertyFunc) bdf_get_bdf_property+ };+++ /*+ *+ * SERVICES LIST+ *+ */++ static const FT_ServiceDescRec bdf_services[] =+ {+ { FT_SERVICE_ID_BDF, &bdf_service_bdf },+ { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_BDF },+ { NULL, NULL }+ };+++ FT_CALLBACK_DEF( FT_Module_Interface )+ bdf_driver_requester( FT_Module module,+ const char* name )+ {+ FT_UNUSED( module );++ return ft_service_list_lookup( bdf_services, name );+ }++++ FT_CALLBACK_TABLE_DEF+ const FT_Driver_ClassRec bdf_driver_class =+ {+ {+ FT_MODULE_FONT_DRIVER |+ FT_MODULE_DRIVER_NO_OUTLINES,+ sizeof ( FT_DriverRec ),++ "bdf",+ 0x10000L,+ 0x20000L,++ 0,++ (FT_Module_Constructor)0,+ (FT_Module_Destructor) 0,+ (FT_Module_Requester) bdf_driver_requester+ },++ sizeof ( BDF_FaceRec ),+ sizeof ( FT_SizeRec ),+ sizeof ( FT_GlyphSlotRec ),++ BDF_Face_Init,+ BDF_Face_Done,+ 0, /* FT_Size_InitFunc */+ 0, /* FT_Size_DoneFunc */+ 0, /* FT_Slot_InitFunc */+ 0, /* FT_Slot_DoneFunc */++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS+ ft_stub_set_char_sizes,+ ft_stub_set_pixel_sizes,+#endif+ BDF_Glyph_Load,++ 0, /* FT_Face_GetKerningFunc */+ 0, /* FT_Face_AttachFunc */+ 0, /* FT_Face_GetAdvancesFunc */++ BDF_Size_Request,+ BDF_Size_Select+ };+++/* END */
+ src/bdf/bdfdrivr.h view
@@ -0,0 +1,80 @@+/* bdfdrivr.h++ FreeType font driver for bdf fonts++ Copyright (C) 2001, 2002, 2003, 2004 by+ Francesco Zappa Nardelli++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in+all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+THE SOFTWARE.+*/+++#ifndef __BDFDRIVR_H__+#define __BDFDRIVR_H__++#include <ft2build.h>+#include FT_INTERNAL_DRIVER_H++#include "bdf.h"+++FT_BEGIN_HEADER++#ifdef FT_CONFIG_OPTION_PIC+#error "this module does not support PIC yet"+#endif +++ typedef struct BDF_encoding_el_+ {+ FT_ULong enc;+ FT_UShort glyph;++ } BDF_encoding_el;+++ typedef struct BDF_FaceRec_+ {+ FT_FaceRec root;++ char* charset_encoding;+ char* charset_registry;++ bdf_font_t* bdffont;++ BDF_encoding_el* en_table;++ FT_CharMap charmap_handle;+ FT_CharMapRec charmap; /* a single charmap per face */++ FT_UInt default_glyph;++ } BDF_FaceRec, *BDF_Face;+++ FT_EXPORT_VAR( const FT_Driver_ClassRec ) bdf_driver_class;+++FT_END_HEADER+++#endif /* __BDFDRIVR_H__ */+++/* END */
+ src/bdf/bdferror.h view
@@ -0,0 +1,44 @@+/*+ * Copyright 2001, 2002 Francesco Zappa Nardelli+ *+ * Permission is hereby granted, free of charge, to any person obtaining a+ * copy of this software and associated documentation files (the "Software"),+ * to deal in the Software without restriction, including without limitation+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,+ * and/or sell copies of the Software, and to permit persons to whom the+ * Software is furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL+ * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT+ * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE.+ */++ /*************************************************************************/+ /* */+ /* This file is used to define the BDF error enumeration constants. */+ /* */+ /*************************************************************************/++#ifndef __BDFERROR_H__+#define __BDFERROR_H__++#include FT_MODULE_ERRORS_H++#undef __FTERRORS_H__++#define FT_ERR_PREFIX BDF_Err_+#define FT_ERR_BASE FT_Mod_Err_BDF++#include FT_ERRORS_H++#endif /* __BDFERROR_H__ */+++/* END */
+ src/bdf/bdflib.c view
@@ -0,0 +1,2542 @@+/*+ * Copyright 2000 Computing Research Labs, New Mexico State University+ * Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010+ * Francesco Zappa Nardelli+ *+ * Permission is hereby granted, free of charge, to any person obtaining a+ * copy of this software and associated documentation files (the "Software"),+ * to deal in the Software without restriction, including without limitation+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,+ * and/or sell copies of the Software, and to permit persons to whom the+ * Software is furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL+ * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT+ * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE.+ */++ /*************************************************************************/+ /* */+ /* This file is based on bdf.c,v 1.22 2000/03/16 20:08:50 */+ /* */+ /* taken from Mark Leisher's xmbdfed package */+ /* */+ /*************************************************************************/+++#include <ft2build.h>++#include FT_FREETYPE_H+#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_STREAM_H+#include FT_INTERNAL_OBJECTS_H++#include "bdf.h"+#include "bdferror.h"+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_bdflib+++ /*************************************************************************/+ /* */+ /* Default BDF font options. */+ /* */+ /*************************************************************************/+++ static const bdf_options_t _bdf_opts =+ {+ 1, /* Correct metrics. */+ 1, /* Preserve unencoded glyphs. */+ 0, /* Preserve comments. */+ BDF_PROPORTIONAL /* Default spacing. */+ };+++ /*************************************************************************/+ /* */+ /* Builtin BDF font properties. */+ /* */+ /*************************************************************************/++ /* List of most properties that might appear in a font. Doesn't include */+ /* the RAW_* and AXIS_* properties in X11R6 polymorphic fonts. */++ static const bdf_property_t _bdf_properties[] =+ {+ { (char *)"ADD_STYLE_NAME", BDF_ATOM, 1, { 0 } },+ { (char *)"AVERAGE_WIDTH", BDF_INTEGER, 1, { 0 } },+ { (char *)"AVG_CAPITAL_WIDTH", BDF_INTEGER, 1, { 0 } },+ { (char *)"AVG_LOWERCASE_WIDTH", BDF_INTEGER, 1, { 0 } },+ { (char *)"CAP_HEIGHT", BDF_INTEGER, 1, { 0 } },+ { (char *)"CHARSET_COLLECTIONS", BDF_ATOM, 1, { 0 } },+ { (char *)"CHARSET_ENCODING", BDF_ATOM, 1, { 0 } },+ { (char *)"CHARSET_REGISTRY", BDF_ATOM, 1, { 0 } },+ { (char *)"COMMENT", BDF_ATOM, 1, { 0 } },+ { (char *)"COPYRIGHT", BDF_ATOM, 1, { 0 } },+ { (char *)"DEFAULT_CHAR", BDF_CARDINAL, 1, { 0 } },+ { (char *)"DESTINATION", BDF_CARDINAL, 1, { 0 } },+ { (char *)"DEVICE_FONT_NAME", BDF_ATOM, 1, { 0 } },+ { (char *)"END_SPACE", BDF_INTEGER, 1, { 0 } },+ { (char *)"FACE_NAME", BDF_ATOM, 1, { 0 } },+ { (char *)"FAMILY_NAME", BDF_ATOM, 1, { 0 } },+ { (char *)"FIGURE_WIDTH", BDF_INTEGER, 1, { 0 } },+ { (char *)"FONT", BDF_ATOM, 1, { 0 } },+ { (char *)"FONTNAME_REGISTRY", BDF_ATOM, 1, { 0 } },+ { (char *)"FONT_ASCENT", BDF_INTEGER, 1, { 0 } },+ { (char *)"FONT_DESCENT", BDF_INTEGER, 1, { 0 } },+ { (char *)"FOUNDRY", BDF_ATOM, 1, { 0 } },+ { (char *)"FULL_NAME", BDF_ATOM, 1, { 0 } },+ { (char *)"ITALIC_ANGLE", BDF_INTEGER, 1, { 0 } },+ { (char *)"MAX_SPACE", BDF_INTEGER, 1, { 0 } },+ { (char *)"MIN_SPACE", BDF_INTEGER, 1, { 0 } },+ { (char *)"NORM_SPACE", BDF_INTEGER, 1, { 0 } },+ { (char *)"NOTICE", BDF_ATOM, 1, { 0 } },+ { (char *)"PIXEL_SIZE", BDF_INTEGER, 1, { 0 } },+ { (char *)"POINT_SIZE", BDF_INTEGER, 1, { 0 } },+ { (char *)"QUAD_WIDTH", BDF_INTEGER, 1, { 0 } },+ { (char *)"RAW_ASCENT", BDF_INTEGER, 1, { 0 } },+ { (char *)"RAW_AVERAGE_WIDTH", BDF_INTEGER, 1, { 0 } },+ { (char *)"RAW_AVG_CAPITAL_WIDTH", BDF_INTEGER, 1, { 0 } },+ { (char *)"RAW_AVG_LOWERCASE_WIDTH", BDF_INTEGER, 1, { 0 } },+ { (char *)"RAW_CAP_HEIGHT", BDF_INTEGER, 1, { 0 } },+ { (char *)"RAW_DESCENT", BDF_INTEGER, 1, { 0 } },+ { (char *)"RAW_END_SPACE", BDF_INTEGER, 1, { 0 } },+ { (char *)"RAW_FIGURE_WIDTH", BDF_INTEGER, 1, { 0 } },+ { (char *)"RAW_MAX_SPACE", BDF_INTEGER, 1, { 0 } },+ { (char *)"RAW_MIN_SPACE", BDF_INTEGER, 1, { 0 } },+ { (char *)"RAW_NORM_SPACE", BDF_INTEGER, 1, { 0 } },+ { (char *)"RAW_PIXEL_SIZE", BDF_INTEGER, 1, { 0 } },+ { (char *)"RAW_POINT_SIZE", BDF_INTEGER, 1, { 0 } },+ { (char *)"RAW_PIXELSIZE", BDF_INTEGER, 1, { 0 } },+ { (char *)"RAW_POINTSIZE", BDF_INTEGER, 1, { 0 } },+ { (char *)"RAW_QUAD_WIDTH", BDF_INTEGER, 1, { 0 } },+ { (char *)"RAW_SMALL_CAP_SIZE", BDF_INTEGER, 1, { 0 } },+ { (char *)"RAW_STRIKEOUT_ASCENT", BDF_INTEGER, 1, { 0 } },+ { (char *)"RAW_STRIKEOUT_DESCENT", BDF_INTEGER, 1, { 0 } },+ { (char *)"RAW_SUBSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } },+ { (char *)"RAW_SUBSCRIPT_X", BDF_INTEGER, 1, { 0 } },+ { (char *)"RAW_SUBSCRIPT_Y", BDF_INTEGER, 1, { 0 } },+ { (char *)"RAW_SUPERSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } },+ { (char *)"RAW_SUPERSCRIPT_X", BDF_INTEGER, 1, { 0 } },+ { (char *)"RAW_SUPERSCRIPT_Y", BDF_INTEGER, 1, { 0 } },+ { (char *)"RAW_UNDERLINE_POSITION", BDF_INTEGER, 1, { 0 } },+ { (char *)"RAW_UNDERLINE_THICKNESS", BDF_INTEGER, 1, { 0 } },+ { (char *)"RAW_X_HEIGHT", BDF_INTEGER, 1, { 0 } },+ { (char *)"RELATIVE_SETWIDTH", BDF_CARDINAL, 1, { 0 } },+ { (char *)"RELATIVE_WEIGHT", BDF_CARDINAL, 1, { 0 } },+ { (char *)"RESOLUTION", BDF_INTEGER, 1, { 0 } },+ { (char *)"RESOLUTION_X", BDF_CARDINAL, 1, { 0 } },+ { (char *)"RESOLUTION_Y", BDF_CARDINAL, 1, { 0 } },+ { (char *)"SETWIDTH_NAME", BDF_ATOM, 1, { 0 } },+ { (char *)"SLANT", BDF_ATOM, 1, { 0 } },+ { (char *)"SMALL_CAP_SIZE", BDF_INTEGER, 1, { 0 } },+ { (char *)"SPACING", BDF_ATOM, 1, { 0 } },+ { (char *)"STRIKEOUT_ASCENT", BDF_INTEGER, 1, { 0 } },+ { (char *)"STRIKEOUT_DESCENT", BDF_INTEGER, 1, { 0 } },+ { (char *)"SUBSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } },+ { (char *)"SUBSCRIPT_X", BDF_INTEGER, 1, { 0 } },+ { (char *)"SUBSCRIPT_Y", BDF_INTEGER, 1, { 0 } },+ { (char *)"SUPERSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } },+ { (char *)"SUPERSCRIPT_X", BDF_INTEGER, 1, { 0 } },+ { (char *)"SUPERSCRIPT_Y", BDF_INTEGER, 1, { 0 } },+ { (char *)"UNDERLINE_POSITION", BDF_INTEGER, 1, { 0 } },+ { (char *)"UNDERLINE_THICKNESS", BDF_INTEGER, 1, { 0 } },+ { (char *)"WEIGHT", BDF_CARDINAL, 1, { 0 } },+ { (char *)"WEIGHT_NAME", BDF_ATOM, 1, { 0 } },+ { (char *)"X_HEIGHT", BDF_INTEGER, 1, { 0 } },+ { (char *)"_MULE_BASELINE_OFFSET", BDF_INTEGER, 1, { 0 } },+ { (char *)"_MULE_RELATIVE_COMPOSE", BDF_INTEGER, 1, { 0 } },+ };++ static const unsigned long+ _num_bdf_properties = sizeof ( _bdf_properties ) /+ sizeof ( _bdf_properties[0] );+++ /*************************************************************************/+ /* */+ /* Hash table utilities for the properties. */+ /* */+ /*************************************************************************/++ /* XXX: Replace this with FreeType's hash functions */+++#define INITIAL_HT_SIZE 241++ typedef void+ (*hash_free_func)( hashnode node );++ static hashnode*+ hash_bucket( const char* key,+ hashtable* ht )+ {+ const char* kp = key;+ unsigned long res = 0;+ hashnode* bp = ht->table, *ndp;+++ /* Mocklisp hash function. */+ while ( *kp )+ res = ( res << 5 ) - res + *kp++;++ ndp = bp + ( res % ht->size );+ while ( *ndp )+ {+ kp = (*ndp)->key;+ if ( kp[0] == key[0] && ft_strcmp( kp, key ) == 0 )+ break;+ ndp--;+ if ( ndp < bp )+ ndp = bp + ( ht->size - 1 );+ }++ return ndp;+ }+++ static FT_Error+ hash_rehash( hashtable* ht,+ FT_Memory memory )+ {+ hashnode* obp = ht->table, *bp, *nbp;+ int i, sz = ht->size;+ FT_Error error = BDF_Err_Ok;+++ ht->size <<= 1;+ ht->limit = ht->size / 3;++ if ( FT_NEW_ARRAY( ht->table, ht->size ) )+ goto Exit;++ for ( i = 0, bp = obp; i < sz; i++, bp++ )+ {+ if ( *bp )+ {+ nbp = hash_bucket( (*bp)->key, ht );+ *nbp = *bp;+ }+ }+ FT_FREE( obp );++ Exit:+ return error;+ }+++ static FT_Error+ hash_init( hashtable* ht,+ FT_Memory memory )+ {+ int sz = INITIAL_HT_SIZE;+ FT_Error error = BDF_Err_Ok;+++ ht->size = sz;+ ht->limit = sz / 3;+ ht->used = 0;++ if ( FT_NEW_ARRAY( ht->table, sz ) )+ goto Exit;++ Exit:+ return error;+ }+++ static void+ hash_free( hashtable* ht,+ FT_Memory memory )+ {+ if ( ht != 0 )+ {+ int i, sz = ht->size;+ hashnode* bp = ht->table;+++ for ( i = 0; i < sz; i++, bp++ )+ FT_FREE( *bp );++ FT_FREE( ht->table );+ }+ }+++ static FT_Error+ hash_insert( char* key,+ size_t data,+ hashtable* ht,+ FT_Memory memory )+ {+ hashnode nn, *bp = hash_bucket( key, ht );+ FT_Error error = BDF_Err_Ok;+++ nn = *bp;+ if ( !nn )+ {+ if ( FT_NEW( nn ) )+ goto Exit;+ *bp = nn;++ nn->key = key;+ nn->data = data;++ if ( ht->used >= ht->limit )+ {+ error = hash_rehash( ht, memory );+ if ( error )+ goto Exit;+ }+ ht->used++;+ }+ else+ nn->data = data;++ Exit:+ return error;+ }+++ static hashnode+ hash_lookup( const char* key,+ hashtable* ht )+ {+ hashnode *np = hash_bucket( key, ht );+++ return *np;+ }+++ /*************************************************************************/+ /* */+ /* Utility types and functions. */+ /* */+ /*************************************************************************/+++ /* Function type for parsing lines of a BDF font. */++ typedef FT_Error+ (*_bdf_line_func_t)( char* line,+ unsigned long linelen,+ unsigned long lineno,+ void* call_data,+ void* client_data );+++ /* List structure for splitting lines into fields. */++ typedef struct _bdf_list_t_+ {+ char** field;+ unsigned long size;+ unsigned long used;+ FT_Memory memory;++ } _bdf_list_t;+++ /* Structure used while loading BDF fonts. */++ typedef struct _bdf_parse_t_+ {+ unsigned long flags;+ unsigned long cnt;+ unsigned long row;++ short minlb;+ short maxlb;+ short maxrb;+ short maxas;+ short maxds;++ short rbearing;++ char* glyph_name;+ long glyph_enc;++ bdf_font_t* font;+ bdf_options_t* opts;++ unsigned long have[2048];+ _bdf_list_t list;++ FT_Memory memory;++ } _bdf_parse_t;+++#define setsbit( m, cc ) \+ ( m[(FT_Byte)(cc) >> 3] |= (FT_Byte)( 1 << ( (cc) & 7 ) ) )+#define sbitset( m, cc ) \+ ( m[(FT_Byte)(cc) >> 3] & ( 1 << ( (cc) & 7 ) ) )+++ static void+ _bdf_list_init( _bdf_list_t* list,+ FT_Memory memory )+ {+ FT_ZERO( list );+ list->memory = memory;+ }+++ static void+ _bdf_list_done( _bdf_list_t* list )+ {+ FT_Memory memory = list->memory;+++ if ( memory )+ {+ FT_FREE( list->field );+ FT_ZERO( list );+ }+ }+++ static FT_Error+ _bdf_list_ensure( _bdf_list_t* list,+ unsigned long num_items ) /* same as _bdf_list_t.used */+ {+ FT_Error error = BDF_Err_Ok;+++ if ( num_items > list->size )+ {+ unsigned long oldsize = list->size; /* same as _bdf_list_t.size */+ unsigned long newsize = oldsize + ( oldsize >> 1 ) + 4;+ unsigned long bigsize = (unsigned long)( FT_INT_MAX / sizeof ( char* ) );+ FT_Memory memory = list->memory;+++ if ( oldsize == bigsize )+ {+ error = BDF_Err_Out_Of_Memory;+ goto Exit;+ }+ else if ( newsize < oldsize || newsize > bigsize )+ newsize = bigsize;++ if ( FT_RENEW_ARRAY( list->field, oldsize, newsize ) )+ goto Exit;++ list->size = newsize;+ }++ Exit:+ return error;+ }+++ static void+ _bdf_list_shift( _bdf_list_t* list,+ unsigned long n )+ {+ unsigned long i, u;+++ if ( list == 0 || list->used == 0 || n == 0 )+ return;++ if ( n >= list->used )+ {+ list->used = 0;+ return;+ }++ for ( u = n, i = 0; u < list->used; i++, u++ )+ list->field[i] = list->field[u];+ list->used -= n;+ }+++ /* An empty string for empty fields. */++ static const char empty[1] = { 0 }; /* XXX eliminate this */+++ static char *+ _bdf_list_join( _bdf_list_t* list,+ int c,+ unsigned long *alen )+ {+ unsigned long i, j;+ char *fp, *dp;+++ *alen = 0;++ if ( list == 0 || list->used == 0 )+ return 0;++ dp = list->field[0];+ for ( i = j = 0; i < list->used; i++ )+ {+ fp = list->field[i];+ while ( *fp )+ dp[j++] = *fp++;++ if ( i + 1 < list->used )+ dp[j++] = (char)c;+ }+ if ( dp != empty )+ dp[j] = 0;++ *alen = j;+ return dp;+ }+++ static FT_Error+ _bdf_list_split( _bdf_list_t* list,+ char* separators,+ char* line,+ unsigned long linelen )+ {+ int mult, final_empty;+ char *sp, *ep, *end;+ char seps[32];+ FT_Error error = BDF_Err_Ok;+++ /* Initialize the list. */+ list->used = 0;++ /* If the line is empty, then simply return. */+ if ( linelen == 0 || line[0] == 0 )+ goto Exit;++ /* In the original code, if the `separators' parameter is NULL or */+ /* empty, the list is split into individual bytes. We don't need */+ /* this, so an error is signaled. */+ if ( separators == 0 || *separators == 0 )+ {+ error = BDF_Err_Invalid_Argument;+ goto Exit;+ }++ /* Prepare the separator bitmap. */+ FT_MEM_ZERO( seps, 32 );++ /* If the very last character of the separator string is a plus, then */+ /* set the `mult' flag to indicate that multiple separators should be */+ /* collapsed into one. */+ for ( mult = 0, sp = separators; sp && *sp; sp++ )+ {+ if ( *sp == '+' && *( sp + 1 ) == 0 )+ mult = 1;+ else+ setsbit( seps, *sp );+ }++ /* Break the line up into fields. */+ for ( final_empty = 0, sp = ep = line, end = sp + linelen;+ sp < end && *sp; )+ {+ /* Collect everything that is not a separator. */+ for ( ; *ep && !sbitset( seps, *ep ); ep++ )+ ;++ /* Resize the list if necessary. */+ if ( list->used == list->size )+ {+ error = _bdf_list_ensure( list, list->used + 1 );+ if ( error )+ goto Exit;+ }++ /* Assign the field appropriately. */+ list->field[list->used++] = ( ep > sp ) ? sp : (char*)empty;++ sp = ep;++ if ( mult )+ {+ /* If multiple separators should be collapsed, do it now by */+ /* setting all the separator characters to 0. */+ for ( ; *ep && sbitset( seps, *ep ); ep++ )+ *ep = 0;+ }+ else if ( *ep != 0 )+ /* Don't collapse multiple separators by making them 0, so just */+ /* make the one encountered 0. */+ *ep++ = 0;++ final_empty = ( ep > sp && *ep == 0 );+ sp = ep;+ }++ /* Finally, NULL-terminate the list. */+ if ( list->used + final_empty >= list->size )+ {+ error = _bdf_list_ensure( list, list->used + final_empty + 1 );+ if ( error )+ goto Exit;+ }++ if ( final_empty )+ list->field[list->used++] = (char*)empty;++ list->field[list->used] = 0;++ Exit:+ return error;+ }+++#define NO_SKIP 256 /* this value cannot be stored in a 'char' */+++ static FT_Error+ _bdf_readstream( FT_Stream stream,+ _bdf_line_func_t callback,+ void* client_data,+ unsigned long *lno )+ {+ _bdf_line_func_t cb;+ unsigned long lineno, buf_size;+ int refill, hold, to_skip;+ ptrdiff_t bytes, start, end, cursor, avail;+ char* buf = 0;+ FT_Memory memory = stream->memory;+ FT_Error error = BDF_Err_Ok;+++ if ( callback == 0 )+ {+ error = BDF_Err_Invalid_Argument;+ goto Exit;+ }++ /* initial size and allocation of the input buffer */+ buf_size = 1024;++ if ( FT_NEW_ARRAY( buf, buf_size ) )+ goto Exit;++ cb = callback;+ lineno = 1;+ buf[0] = 0;+ start = 0;+ end = 0;+ avail = 0;+ cursor = 0;+ refill = 1;+ to_skip = NO_SKIP;+ bytes = 0; /* make compiler happy */++ for (;;)+ {+ if ( refill )+ {+ bytes = (ptrdiff_t)FT_Stream_TryRead(+ stream, (FT_Byte*)buf + cursor,+ (FT_ULong)( buf_size - cursor ) );+ avail = cursor + bytes;+ cursor = 0;+ refill = 0;+ }++ end = start;++ /* should we skip an optional character like \n or \r? */+ if ( start < avail && buf[start] == to_skip )+ {+ start += 1;+ to_skip = NO_SKIP;+ continue;+ }++ /* try to find the end of the line */+ while ( end < avail && buf[end] != '\n' && buf[end] != '\r' )+ end++;++ /* if we hit the end of the buffer, try shifting its content */+ /* or even resizing it */+ if ( end >= avail )+ {+ if ( bytes == 0 ) /* last line in file doesn't end in \r or \n */+ break; /* ignore it then exit */++ if ( start == 0 )+ {+ /* this line is definitely too long; try resizing the input */+ /* buffer a bit to handle it. */+ FT_ULong new_size;+++ if ( buf_size >= 65536UL ) /* limit ourselves to 64KByte */+ {+ error = BDF_Err_Invalid_Argument;+ goto Exit;+ }++ new_size = buf_size * 2;+ if ( FT_RENEW_ARRAY( buf, buf_size, new_size ) )+ goto Exit;++ cursor = buf_size;+ buf_size = new_size;+ }+ else+ {+ bytes = avail - start;++ FT_MEM_COPY( buf, buf + start, bytes );++ cursor = bytes;+ avail -= bytes;+ start = 0;+ }+ refill = 1;+ continue;+ }++ /* Temporarily NUL-terminate the line. */+ hold = buf[end];+ buf[end] = 0;++ /* XXX: Use encoding independent value for 0x1a */+ if ( buf[start] != '#' && buf[start] != 0x1a && end > start )+ {+ error = (*cb)( buf + start, end - start, lineno,+ (void*)&cb, client_data );+ /* Redo if we have encountered CHARS without properties. */+ if ( error == -1 )+ error = (*cb)( buf + start, end - start, lineno,+ (void*)&cb, client_data );+ if ( error )+ break;+ }++ lineno += 1;+ buf[end] = (char)hold;+ start = end + 1;++ if ( hold == '\n' )+ to_skip = '\r';+ else if ( hold == '\r' )+ to_skip = '\n';+ else+ to_skip = NO_SKIP;+ }++ *lno = lineno;++ Exit:+ FT_FREE( buf );+ return error;+ }+++ /* XXX: make this work with EBCDIC also */++ static const unsigned char a2i[128] =+ {+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00+ };++ static const unsigned char odigits[32] =+ {+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ };++ static const unsigned char ddigits[32] =+ {+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ };++ static const unsigned char hdigits[32] =+ {+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03,+ 0x7e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+ };+++#define isdigok( m, d ) (m[(d) >> 3] & ( 1 << ( (d) & 7 ) ) )+++ /* Routine to convert an ASCII string into an unsigned long integer. */+ static unsigned long+ _bdf_atoul( char* s,+ char** end,+ int base )+ {+ unsigned long v;+ const unsigned char* dmap;+++ if ( s == 0 || *s == 0 )+ return 0;++ /* Make sure the radix is something recognizable. Default to 10. */+ switch ( base )+ {+ case 8:+ dmap = odigits;+ break;+ case 16:+ dmap = hdigits;+ break;+ default:+ base = 10;+ dmap = ddigits;+ break;+ }++ /* Check for the special hex prefix. */+ if ( *s == '0' &&+ ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) )+ {+ base = 16;+ dmap = hdigits;+ s += 2;+ }++ for ( v = 0; isdigok( dmap, *s ); s++ )+ v = v * base + a2i[(int)*s];++ if ( end != 0 )+ *end = s;++ return v;+ }+++ /* Routine to convert an ASCII string into an signed long integer. */+ static long+ _bdf_atol( char* s,+ char** end,+ int base )+ {+ long v, neg;+ const unsigned char* dmap;+++ if ( s == 0 || *s == 0 )+ return 0;++ /* Make sure the radix is something recognizable. Default to 10. */+ switch ( base )+ {+ case 8:+ dmap = odigits;+ break;+ case 16:+ dmap = hdigits;+ break;+ default:+ base = 10;+ dmap = ddigits;+ break;+ }++ /* Check for a minus sign. */+ neg = 0;+ if ( *s == '-' )+ {+ s++;+ neg = 1;+ }++ /* Check for the special hex prefix. */+ if ( *s == '0' &&+ ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) )+ {+ base = 16;+ dmap = hdigits;+ s += 2;+ }++ for ( v = 0; isdigok( dmap, *s ); s++ )+ v = v * base + a2i[(int)*s];++ if ( end != 0 )+ *end = s;++ return ( !neg ) ? v : -v;+ }+++ /* Routine to convert an ASCII string into an signed short integer. */+ static short+ _bdf_atos( char* s,+ char** end,+ int base )+ {+ short v, neg;+ const unsigned char* dmap;+++ if ( s == 0 || *s == 0 )+ return 0;++ /* Make sure the radix is something recognizable. Default to 10. */+ switch ( base )+ {+ case 8:+ dmap = odigits;+ break;+ case 16:+ dmap = hdigits;+ break;+ default:+ base = 10;+ dmap = ddigits;+ break;+ }++ /* Check for a minus. */+ neg = 0;+ if ( *s == '-' )+ {+ s++;+ neg = 1;+ }++ /* Check for the special hex prefix. */+ if ( *s == '0' &&+ ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) )+ {+ base = 16;+ dmap = hdigits;+ s += 2;+ }++ for ( v = 0; isdigok( dmap, *s ); s++ )+ v = (short)( v * base + a2i[(int)*s] );++ if ( end != 0 )+ *end = s;++ return (short)( ( !neg ) ? v : -v );+ }+++ /* Routine to compare two glyphs by encoding so they can be sorted. */+ static int+ by_encoding( const void* a,+ const void* b )+ {+ bdf_glyph_t *c1, *c2;+++ c1 = (bdf_glyph_t *)a;+ c2 = (bdf_glyph_t *)b;++ if ( c1->encoding < c2->encoding )+ return -1;++ if ( c1->encoding > c2->encoding )+ return 1;++ return 0;+ }+++ static FT_Error+ bdf_create_property( char* name,+ int format,+ bdf_font_t* font )+ {+ size_t n;+ bdf_property_t* p;+ FT_Memory memory = font->memory;+ FT_Error error = BDF_Err_Ok;+++ /* First check to see if the property has */+ /* already been added or not. If it has, then */+ /* simply ignore it. */+ if ( hash_lookup( name, &(font->proptbl) ) )+ goto Exit;++ if ( FT_RENEW_ARRAY( font->user_props,+ font->nuser_props,+ font->nuser_props + 1 ) )+ goto Exit;++ p = font->user_props + font->nuser_props;+ FT_ZERO( p );++ n = ft_strlen( name ) + 1;+ if ( n > FT_ULONG_MAX )+ return BDF_Err_Invalid_Argument;++ if ( FT_NEW_ARRAY( p->name, n ) )+ goto Exit;++ FT_MEM_COPY( (char *)p->name, name, n );++ p->format = format;+ p->builtin = 0;++ n = _num_bdf_properties + font->nuser_props;++ error = hash_insert( p->name, n, &(font->proptbl), memory );+ if ( error )+ goto Exit;++ font->nuser_props++;++ Exit:+ return error;+ }+++ FT_LOCAL_DEF( bdf_property_t * )+ bdf_get_property( char* name,+ bdf_font_t* font )+ {+ hashnode hn;+ size_t propid;+++ if ( name == 0 || *name == 0 )+ return 0;++ if ( ( hn = hash_lookup( name, &(font->proptbl) ) ) == 0 )+ return 0;++ propid = hn->data;+ if ( propid >= _num_bdf_properties )+ return font->user_props + ( propid - _num_bdf_properties );++ return (bdf_property_t*)_bdf_properties + propid;+ }+++ /*************************************************************************/+ /* */+ /* BDF font file parsing flags and functions. */+ /* */+ /*************************************************************************/+++ /* Parse flags. */++#define _BDF_START 0x0001+#define _BDF_FONT_NAME 0x0002+#define _BDF_SIZE 0x0004+#define _BDF_FONT_BBX 0x0008+#define _BDF_PROPS 0x0010+#define _BDF_GLYPHS 0x0020+#define _BDF_GLYPH 0x0040+#define _BDF_ENCODING 0x0080+#define _BDF_SWIDTH 0x0100+#define _BDF_DWIDTH 0x0200+#define _BDF_BBX 0x0400+#define _BDF_BITMAP 0x0800++#define _BDF_SWIDTH_ADJ 0x1000++#define _BDF_GLYPH_BITS ( _BDF_GLYPH | \+ _BDF_ENCODING | \+ _BDF_SWIDTH | \+ _BDF_DWIDTH | \+ _BDF_BBX | \+ _BDF_BITMAP )++#define _BDF_GLYPH_WIDTH_CHECK 0x40000000UL+#define _BDF_GLYPH_HEIGHT_CHECK 0x80000000UL+++ /* Auto correction messages. */+#define ACMSG1 "FONT_ASCENT property missing. " \+ "Added \"FONT_ASCENT %hd\".\n"+#define ACMSG2 "FONT_DESCENT property missing. " \+ "Added \"FONT_DESCENT %hd\".\n"+#define ACMSG3 "Font width != actual width. Old: %hd New: %hd.\n"+#define ACMSG4 "Font left bearing != actual left bearing. " \+ "Old: %hd New: %hd.\n"+#define ACMSG5 "Font ascent != actual ascent. Old: %hd New: %hd.\n"+#define ACMSG6 "Font descent != actual descent. Old: %hd New: %hd.\n"+#define ACMSG7 "Font height != actual height. Old: %hd New: %hd.\n"+#define ACMSG8 "Glyph scalable width (SWIDTH) adjustments made.\n"+#define ACMSG9 "SWIDTH field missing at line %ld. Set automatically.\n"+#define ACMSG10 "DWIDTH field missing at line %ld. Set to glyph width.\n"+#define ACMSG11 "SIZE bits per pixel field adjusted to %hd.\n"+#define ACMSG12 "Duplicate encoding %ld (%s) changed to unencoded.\n"+#define ACMSG13 "Glyph %ld extra rows removed.\n"+#define ACMSG14 "Glyph %ld extra columns removed.\n"+#define ACMSG15 "Incorrect glyph count: %ld indicated but %ld found.\n"++ /* Error messages. */+#define ERRMSG1 "[line %ld] Missing \"%s\" line.\n"+#define ERRMSG2 "[line %ld] Font header corrupted or missing fields.\n"+#define ERRMSG3 "[line %ld] Font glyphs corrupted or missing fields.\n"+#define ERRMSG4 "[line %ld] BBX too big.\n"+++ static FT_Error+ _bdf_add_comment( bdf_font_t* font,+ char* comment,+ unsigned long len )+ {+ char* cp;+ FT_Memory memory = font->memory;+ FT_Error error = BDF_Err_Ok;+++ if ( FT_RENEW_ARRAY( font->comments,+ font->comments_len,+ font->comments_len + len + 1 ) )+ goto Exit;++ cp = font->comments + font->comments_len;++ FT_MEM_COPY( cp, comment, len );+ cp[len] = '\n';++ font->comments_len += len + 1;++ Exit:+ return error;+ }+++ /* Set the spacing from the font name if it exists, or set it to the */+ /* default specified in the options. */+ static FT_Error+ _bdf_set_default_spacing( bdf_font_t* font,+ bdf_options_t* opts )+ {+ size_t len;+ char name[256];+ _bdf_list_t list;+ FT_Memory memory;+ FT_Error error = BDF_Err_Ok;+++ if ( font == 0 || font->name == 0 || font->name[0] == 0 )+ {+ error = BDF_Err_Invalid_Argument;+ goto Exit;+ }++ memory = font->memory;++ _bdf_list_init( &list, memory );++ font->spacing = opts->font_spacing;++ len = ft_strlen( font->name ) + 1;+ /* Limit ourselves to 256 characters in the font name. */+ if ( len >= 256 )+ {+ error = BDF_Err_Invalid_Argument;+ goto Exit;+ }++ FT_MEM_COPY( name, font->name, len );++ error = _bdf_list_split( &list, (char *)"-", name, len );+ if ( error )+ goto Fail;++ if ( list.used == 15 )+ {+ switch ( list.field[11][0] )+ {+ case 'C':+ case 'c':+ font->spacing = BDF_CHARCELL;+ break;+ case 'M':+ case 'm':+ font->spacing = BDF_MONOWIDTH;+ break;+ case 'P':+ case 'p':+ font->spacing = BDF_PROPORTIONAL;+ break;+ }+ }++ Fail:+ _bdf_list_done( &list );++ Exit:+ return error;+ }+++ /* Determine whether the property is an atom or not. If it is, then */+ /* clean it up so the double quotes are removed if they exist. */+ static int+ _bdf_is_atom( char* line,+ unsigned long linelen,+ char** name,+ char** value,+ bdf_font_t* font )+ {+ int hold;+ char *sp, *ep;+ bdf_property_t* p;+++ *name = sp = ep = line;++ while ( *ep && *ep != ' ' && *ep != '\t' )+ ep++;++ hold = -1;+ if ( *ep )+ {+ hold = *ep;+ *ep = 0;+ }++ p = bdf_get_property( sp, font );++ /* Restore the character that was saved before any return can happen. */+ if ( hold != -1 )+ *ep = (char)hold;++ /* If the property exists and is not an atom, just return here. */+ if ( p && p->format != BDF_ATOM )+ return 0;++ /* The property is an atom. Trim all leading and trailing whitespace */+ /* and double quotes for the atom value. */+ sp = ep;+ ep = line + linelen;++ /* Trim the leading whitespace if it exists. */+ *sp++ = 0;+ while ( *sp &&+ ( *sp == ' ' || *sp == '\t' ) )+ sp++;++ /* Trim the leading double quote if it exists. */+ if ( *sp == '"' )+ sp++;+ *value = sp;++ /* Trim the trailing whitespace if it exists. */+ while ( ep > sp &&+ ( *( ep - 1 ) == ' ' || *( ep - 1 ) == '\t' ) )+ *--ep = 0;++ /* Trim the trailing double quote if it exists. */+ if ( ep > sp && *( ep - 1 ) == '"' )+ *--ep = 0;++ return 1;+ }+++ static FT_Error+ _bdf_add_property( bdf_font_t* font,+ char* name,+ char* value )+ {+ size_t propid;+ hashnode hn;+ bdf_property_t *prop, *fp;+ FT_Memory memory = font->memory;+ FT_Error error = BDF_Err_Ok;+++ /* First, check to see if the property already exists in the font. */+ if ( ( hn = hash_lookup( name, (hashtable *)font->internal ) ) != 0 )+ {+ /* The property already exists in the font, so simply replace */+ /* the value of the property with the current value. */+ fp = font->props + hn->data;++ switch ( fp->format )+ {+ case BDF_ATOM:+ /* Delete the current atom if it exists. */+ FT_FREE( fp->value.atom );++ if ( value && value[0] != 0 )+ {+ if ( FT_STRDUP( fp->value.atom, value ) )+ goto Exit;+ }+ break;++ case BDF_INTEGER:+ fp->value.l = _bdf_atol( value, 0, 10 );+ break;++ case BDF_CARDINAL:+ fp->value.ul = _bdf_atoul( value, 0, 10 );+ break;++ default:+ ;+ }++ goto Exit;+ }++ /* See whether this property type exists yet or not. */+ /* If not, create it. */+ hn = hash_lookup( name, &(font->proptbl) );+ if ( hn == 0 )+ {+ error = bdf_create_property( name, BDF_ATOM, font );+ if ( error )+ goto Exit;+ hn = hash_lookup( name, &(font->proptbl) );+ }++ /* Allocate another property if this is overflow. */+ if ( font->props_used == font->props_size )+ {+ if ( font->props_size == 0 )+ {+ if ( FT_NEW_ARRAY( font->props, 1 ) )+ goto Exit;+ }+ else+ {+ if ( FT_RENEW_ARRAY( font->props,+ font->props_size,+ font->props_size + 1 ) )+ goto Exit;+ }++ fp = font->props + font->props_size;+ FT_MEM_ZERO( fp, sizeof ( bdf_property_t ) );+ font->props_size++;+ }++ propid = hn->data;+ if ( propid >= _num_bdf_properties )+ prop = font->user_props + ( propid - _num_bdf_properties );+ else+ prop = (bdf_property_t*)_bdf_properties + propid;++ fp = font->props + font->props_used;++ fp->name = prop->name;+ fp->format = prop->format;+ fp->builtin = prop->builtin;++ switch ( prop->format )+ {+ case BDF_ATOM:+ fp->value.atom = 0;+ if ( value != 0 && value[0] )+ {+ if ( FT_STRDUP( fp->value.atom, value ) )+ goto Exit;+ }+ break;++ case BDF_INTEGER:+ fp->value.l = _bdf_atol( value, 0, 10 );+ break;++ case BDF_CARDINAL:+ fp->value.ul = _bdf_atoul( value, 0, 10 );+ break;+ }++ /* If the property happens to be a comment, then it doesn't need */+ /* to be added to the internal hash table. */+ if ( ft_memcmp( name, "COMMENT", 7 ) != 0 )+ {+ /* Add the property to the font property table. */+ error = hash_insert( fp->name,+ font->props_used,+ (hashtable *)font->internal,+ memory );+ if ( error )+ goto Exit;+ }++ font->props_used++;++ /* Some special cases need to be handled here. The DEFAULT_CHAR */+ /* property needs to be located if it exists in the property list, the */+ /* FONT_ASCENT and FONT_DESCENT need to be assigned if they are */+ /* present, and the SPACING property should override the default */+ /* spacing. */+ if ( ft_memcmp( name, "DEFAULT_CHAR", 12 ) == 0 )+ font->default_char = fp->value.l;+ else if ( ft_memcmp( name, "FONT_ASCENT", 11 ) == 0 )+ font->font_ascent = fp->value.l;+ else if ( ft_memcmp( name, "FONT_DESCENT", 12 ) == 0 )+ font->font_descent = fp->value.l;+ else if ( ft_memcmp( name, "SPACING", 7 ) == 0 )+ {+ if ( !fp->value.atom )+ {+ error = BDF_Err_Invalid_File_Format;+ goto Exit;+ }++ if ( fp->value.atom[0] == 'p' || fp->value.atom[0] == 'P' )+ font->spacing = BDF_PROPORTIONAL;+ else if ( fp->value.atom[0] == 'm' || fp->value.atom[0] == 'M' )+ font->spacing = BDF_MONOWIDTH;+ else if ( fp->value.atom[0] == 'c' || fp->value.atom[0] == 'C' )+ font->spacing = BDF_CHARCELL;+ }++ Exit:+ return error;+ }+++ static const unsigned char nibble_mask[8] =+ {+ 0xFF, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE+ };+++ /* Actually parse the glyph info and bitmaps. */+ static FT_Error+ _bdf_parse_glyphs( char* line,+ unsigned long linelen,+ unsigned long lineno,+ void* call_data,+ void* client_data )+ {+ int c, mask_index;+ char* s;+ unsigned char* bp;+ unsigned long i, slen, nibbles;++ _bdf_parse_t* p;+ bdf_glyph_t* glyph;+ bdf_font_t* font;++ FT_Memory memory;+ FT_Error error = BDF_Err_Ok;++ FT_UNUSED( call_data );+ FT_UNUSED( lineno ); /* only used in debug mode */+++ p = (_bdf_parse_t *)client_data;++ font = p->font;+ memory = font->memory;++ /* Check for a comment. */+ if ( ft_memcmp( line, "COMMENT", 7 ) == 0 )+ {+ linelen -= 7;++ s = line + 7;+ if ( *s != 0 )+ {+ s++;+ linelen--;+ }+ error = _bdf_add_comment( p->font, s, linelen );+ goto Exit;+ }++ /* The very first thing expected is the number of glyphs. */+ if ( !( p->flags & _BDF_GLYPHS ) )+ {+ if ( ft_memcmp( line, "CHARS", 5 ) != 0 )+ {+ FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "CHARS" ));+ error = BDF_Err_Missing_Chars_Field;+ goto Exit;+ }++ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );+ if ( error )+ goto Exit;+ p->cnt = font->glyphs_size = _bdf_atoul( p->list.field[1], 0, 10 );++ /* Make sure the number of glyphs is non-zero. */+ if ( p->cnt == 0 )+ font->glyphs_size = 64;++ /* Limit ourselves to 1,114,112 glyphs in the font (this is the */+ /* number of code points available in Unicode). */+ if ( p->cnt >= 1114112UL )+ {+ error = BDF_Err_Invalid_Argument;+ goto Exit;+ }++ if ( FT_NEW_ARRAY( font->glyphs, font->glyphs_size ) )+ goto Exit;++ p->flags |= _BDF_GLYPHS;++ goto Exit;+ }++ /* Check for the ENDFONT field. */+ if ( ft_memcmp( line, "ENDFONT", 7 ) == 0 )+ {+ /* Sort the glyphs by encoding. */+ ft_qsort( (char *)font->glyphs,+ font->glyphs_used,+ sizeof ( bdf_glyph_t ),+ by_encoding );++ p->flags &= ~_BDF_START;++ goto Exit;+ }++ /* Check for the ENDCHAR field. */+ if ( ft_memcmp( line, "ENDCHAR", 7 ) == 0 )+ {+ p->glyph_enc = 0;+ p->flags &= ~_BDF_GLYPH_BITS;++ goto Exit;+ }++ /* Check to see whether a glyph is being scanned but should be */+ /* ignored because it is an unencoded glyph. */+ if ( ( p->flags & _BDF_GLYPH ) &&+ p->glyph_enc == -1 &&+ p->opts->keep_unencoded == 0 )+ goto Exit;++ /* Check for the STARTCHAR field. */+ if ( ft_memcmp( line, "STARTCHAR", 9 ) == 0 )+ {+ /* Set the character name in the parse info first until the */+ /* encoding can be checked for an unencoded character. */+ FT_FREE( p->glyph_name );++ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );+ if ( error )+ goto Exit;++ _bdf_list_shift( &p->list, 1 );++ s = _bdf_list_join( &p->list, ' ', &slen );++ if ( !s )+ {+ error = BDF_Err_Invalid_File_Format;+ goto Exit;+ }++ if ( FT_NEW_ARRAY( p->glyph_name, slen + 1 ) )+ goto Exit;++ FT_MEM_COPY( p->glyph_name, s, slen + 1 );++ p->flags |= _BDF_GLYPH;++ goto Exit;+ }++ /* Check for the ENCODING field. */+ if ( ft_memcmp( line, "ENCODING", 8 ) == 0 )+ {+ if ( !( p->flags & _BDF_GLYPH ) )+ {+ /* Missing STARTCHAR field. */+ FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "STARTCHAR" ));+ error = BDF_Err_Missing_Startchar_Field;+ goto Exit;+ }++ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );+ if ( error )+ goto Exit;++ p->glyph_enc = _bdf_atol( p->list.field[1], 0, 10 );++ /* Check that the encoding is in the range [0,65536] because */+ /* otherwise p->have (a bitmap with static size) overflows. */+ if ( (size_t)p->glyph_enc >= sizeof ( p->have ) * 8 )+ {+ error = BDF_Err_Invalid_File_Format;+ goto Exit;+ }++ /* Check to see whether this encoding has already been encountered. */+ /* If it has then change it to unencoded so it gets added if */+ /* indicated. */+ if ( p->glyph_enc >= 0 )+ {+ if ( _bdf_glyph_modified( p->have, p->glyph_enc ) )+ {+ /* Emit a message saying a glyph has been moved to the */+ /* unencoded area. */+ FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG12,+ p->glyph_enc, p->glyph_name ));+ p->glyph_enc = -1;+ font->modified = 1;+ }+ else+ _bdf_set_glyph_modified( p->have, p->glyph_enc );+ }++ if ( p->glyph_enc >= 0 )+ {+ /* Make sure there are enough glyphs allocated in case the */+ /* number of characters happen to be wrong. */+ if ( font->glyphs_used == font->glyphs_size )+ {+ if ( FT_RENEW_ARRAY( font->glyphs,+ font->glyphs_size,+ font->glyphs_size + 64 ) )+ goto Exit;++ font->glyphs_size += 64;+ }++ glyph = font->glyphs + font->glyphs_used++;+ glyph->name = p->glyph_name;+ glyph->encoding = p->glyph_enc;++ /* Reset the initial glyph info. */+ p->glyph_name = 0;+ }+ else+ {+ /* Unencoded glyph. Check to see whether it should */+ /* be added or not. */+ if ( p->opts->keep_unencoded != 0 )+ {+ /* Allocate the next unencoded glyph. */+ if ( font->unencoded_used == font->unencoded_size )+ {+ if ( FT_RENEW_ARRAY( font->unencoded ,+ font->unencoded_size,+ font->unencoded_size + 4 ) )+ goto Exit;++ font->unencoded_size += 4;+ }++ glyph = font->unencoded + font->unencoded_used;+ glyph->name = p->glyph_name;+ glyph->encoding = font->unencoded_used++;+ }+ else+ /* Free up the glyph name if the unencoded shouldn't be */+ /* kept. */+ FT_FREE( p->glyph_name );++ p->glyph_name = 0;+ }++ /* Clear the flags that might be added when width and height are */+ /* checked for consistency. */+ p->flags &= ~( _BDF_GLYPH_WIDTH_CHECK | _BDF_GLYPH_HEIGHT_CHECK );++ p->flags |= _BDF_ENCODING;++ goto Exit;+ }++ /* Point at the glyph being constructed. */+ if ( p->glyph_enc == -1 )+ glyph = font->unencoded + ( font->unencoded_used - 1 );+ else+ glyph = font->glyphs + ( font->glyphs_used - 1 );++ /* Check to see whether a bitmap is being constructed. */+ if ( p->flags & _BDF_BITMAP )+ {+ /* If there are more rows than are specified in the glyph metrics, */+ /* ignore the remaining lines. */+ if ( p->row >= (unsigned long)glyph->bbx.height )+ {+ if ( !( p->flags & _BDF_GLYPH_HEIGHT_CHECK ) )+ {+ FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG13, glyph->encoding ));+ p->flags |= _BDF_GLYPH_HEIGHT_CHECK;+ font->modified = 1;+ }++ goto Exit;+ }++ /* Only collect the number of nibbles indicated by the glyph */+ /* metrics. If there are more columns, they are simply ignored. */+ nibbles = glyph->bpr << 1;+ bp = glyph->bitmap + p->row * glyph->bpr;++ for ( i = 0; i < nibbles; i++ )+ {+ c = line[i];+ *bp = (FT_Byte)( ( *bp << 4 ) + a2i[c] );+ if ( i + 1 < nibbles && ( i & 1 ) )+ *++bp = 0;+ }++ /* Remove possible garbage at the right. */+ mask_index = ( glyph->bbx.width * p->font->bpp ) & 7;+ if ( glyph->bbx.width )+ *bp &= nibble_mask[mask_index];++ /* If any line has extra columns, indicate they have been removed. */+ if ( ( line[nibbles] == '0' || a2i[(int)line[nibbles]] != 0 ) &&+ !( p->flags & _BDF_GLYPH_WIDTH_CHECK ) )+ {+ FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG14, glyph->encoding ));+ p->flags |= _BDF_GLYPH_WIDTH_CHECK;+ font->modified = 1;+ }++ p->row++;+ goto Exit;+ }++ /* Expect the SWIDTH (scalable width) field next. */+ if ( ft_memcmp( line, "SWIDTH", 6 ) == 0 )+ {+ if ( !( p->flags & _BDF_ENCODING ) )+ {+ /* Missing ENCODING field. */+ FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "ENCODING" ));+ error = BDF_Err_Missing_Encoding_Field;+ goto Exit;+ }++ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );+ if ( error )+ goto Exit;++ glyph->swidth = (unsigned short)_bdf_atoul( p->list.field[1], 0, 10 );+ p->flags |= _BDF_SWIDTH;++ goto Exit;+ }++ /* Expect the DWIDTH (scalable width) field next. */+ if ( ft_memcmp( line, "DWIDTH", 6 ) == 0 )+ {+ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );+ if ( error )+ goto Exit;++ glyph->dwidth = (unsigned short)_bdf_atoul( p->list.field[1], 0, 10 );++ if ( !( p->flags & _BDF_SWIDTH ) )+ {+ /* Missing SWIDTH field. Emit an auto correction message and set */+ /* the scalable width from the device width. */+ FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG9, lineno ));++ glyph->swidth = (unsigned short)FT_MulDiv(+ glyph->dwidth, 72000L,+ (FT_Long)( font->point_size *+ font->resolution_x ) );+ }++ p->flags |= _BDF_DWIDTH;+ goto Exit;+ }++ /* Expect the BBX field next. */+ if ( ft_memcmp( line, "BBX", 3 ) == 0 )+ {+ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );+ if ( error )+ goto Exit;++ glyph->bbx.width = _bdf_atos( p->list.field[1], 0, 10 );+ glyph->bbx.height = _bdf_atos( p->list.field[2], 0, 10 );+ glyph->bbx.x_offset = _bdf_atos( p->list.field[3], 0, 10 );+ glyph->bbx.y_offset = _bdf_atos( p->list.field[4], 0, 10 );++ /* Generate the ascent and descent of the character. */+ glyph->bbx.ascent = (short)( glyph->bbx.height + glyph->bbx.y_offset );+ glyph->bbx.descent = (short)( -glyph->bbx.y_offset );++ /* Determine the overall font bounding box as the characters are */+ /* loaded so corrections can be done later if indicated. */+ p->maxas = (short)FT_MAX( glyph->bbx.ascent, p->maxas );+ p->maxds = (short)FT_MAX( glyph->bbx.descent, p->maxds );++ p->rbearing = (short)( glyph->bbx.width + glyph->bbx.x_offset );++ p->maxrb = (short)FT_MAX( p->rbearing, p->maxrb );+ p->minlb = (short)FT_MIN( glyph->bbx.x_offset, p->minlb );+ p->maxlb = (short)FT_MAX( glyph->bbx.x_offset, p->maxlb );++ if ( !( p->flags & _BDF_DWIDTH ) )+ {+ /* Missing DWIDTH field. Emit an auto correction message and set */+ /* the device width to the glyph width. */+ FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG10, lineno ));+ glyph->dwidth = glyph->bbx.width;+ }++ /* If the BDF_CORRECT_METRICS flag is set, then adjust the SWIDTH */+ /* value if necessary. */+ if ( p->opts->correct_metrics != 0 )+ {+ /* Determine the point size of the glyph. */+ unsigned short sw = (unsigned short)FT_MulDiv(+ glyph->dwidth, 72000L,+ (FT_Long)( font->point_size *+ font->resolution_x ) );+++ if ( sw != glyph->swidth )+ {+ glyph->swidth = sw;++ if ( p->glyph_enc == -1 )+ _bdf_set_glyph_modified( font->umod,+ font->unencoded_used - 1 );+ else+ _bdf_set_glyph_modified( font->nmod, glyph->encoding );++ p->flags |= _BDF_SWIDTH_ADJ;+ font->modified = 1;+ }+ }++ p->flags |= _BDF_BBX;+ goto Exit;+ }++ /* And finally, gather up the bitmap. */+ if ( ft_memcmp( line, "BITMAP", 6 ) == 0 )+ {+ unsigned long bitmap_size;+++ if ( !( p->flags & _BDF_BBX ) )+ {+ /* Missing BBX field. */+ FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "BBX" ));+ error = BDF_Err_Missing_Bbx_Field;+ goto Exit;+ }++ /* Allocate enough space for the bitmap. */+ glyph->bpr = ( glyph->bbx.width * p->font->bpp + 7 ) >> 3;++ bitmap_size = glyph->bpr * glyph->bbx.height;+ if ( bitmap_size > 0xFFFFU )+ {+ FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG4, lineno ));+ error = BDF_Err_Bbx_Too_Big;+ goto Exit;+ }+ else+ glyph->bytes = (unsigned short)bitmap_size;++ if ( FT_NEW_ARRAY( glyph->bitmap, glyph->bytes ) )+ goto Exit;++ p->row = 0;+ p->flags |= _BDF_BITMAP;++ goto Exit;+ }++ error = BDF_Err_Invalid_File_Format;++ Exit:+ if ( error && ( p->flags & _BDF_GLYPH ) )+ FT_FREE( p->glyph_name );++ return error;+ }+++ /* Load the font properties. */+ static FT_Error+ _bdf_parse_properties( char* line,+ unsigned long linelen,+ unsigned long lineno,+ void* call_data,+ void* client_data )+ {+ unsigned long vlen;+ _bdf_line_func_t* next;+ _bdf_parse_t* p;+ char* name;+ char* value;+ char nbuf[128];+ FT_Error error = BDF_Err_Ok;++ FT_UNUSED( lineno );+++ next = (_bdf_line_func_t *)call_data;+ p = (_bdf_parse_t *) client_data;++ /* Check for the end of the properties. */+ if ( ft_memcmp( line, "ENDPROPERTIES", 13 ) == 0 )+ {+ /* If the FONT_ASCENT or FONT_DESCENT properties have not been */+ /* encountered yet, then make sure they are added as properties and */+ /* make sure they are set from the font bounding box info. */+ /* */+ /* This is *always* done regardless of the options, because X11 */+ /* requires these two fields to compile fonts. */+ if ( bdf_get_font_property( p->font, "FONT_ASCENT" ) == 0 )+ {+ p->font->font_ascent = p->font->bbx.ascent;+ ft_sprintf( nbuf, "%hd", p->font->bbx.ascent );+ error = _bdf_add_property( p->font, (char *)"FONT_ASCENT", nbuf );+ if ( error )+ goto Exit;++ FT_TRACE2(( "_bdf_parse_properties: " ACMSG1, p->font->bbx.ascent ));+ p->font->modified = 1;+ }++ if ( bdf_get_font_property( p->font, "FONT_DESCENT" ) == 0 )+ {+ p->font->font_descent = p->font->bbx.descent;+ ft_sprintf( nbuf, "%hd", p->font->bbx.descent );+ error = _bdf_add_property( p->font, (char *)"FONT_DESCENT", nbuf );+ if ( error )+ goto Exit;++ FT_TRACE2(( "_bdf_parse_properties: " ACMSG2, p->font->bbx.descent ));+ p->font->modified = 1;+ }++ p->flags &= ~_BDF_PROPS;+ *next = _bdf_parse_glyphs;++ goto Exit;+ }++ /* Ignore the _XFREE86_GLYPH_RANGES properties. */+ if ( ft_memcmp( line, "_XFREE86_GLYPH_RANGES", 21 ) == 0 )+ goto Exit;++ /* Handle COMMENT fields and properties in a special way to preserve */+ /* the spacing. */+ if ( ft_memcmp( line, "COMMENT", 7 ) == 0 )+ {+ name = value = line;+ value += 7;+ if ( *value )+ *value++ = 0;+ error = _bdf_add_property( p->font, name, value );+ if ( error )+ goto Exit;+ }+ else if ( _bdf_is_atom( line, linelen, &name, &value, p->font ) )+ {+ error = _bdf_add_property( p->font, name, value );+ if ( error )+ goto Exit;+ }+ else+ {+ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );+ if ( error )+ goto Exit;+ name = p->list.field[0];++ _bdf_list_shift( &p->list, 1 );+ value = _bdf_list_join( &p->list, ' ', &vlen );++ error = _bdf_add_property( p->font, name, value );+ if ( error )+ goto Exit;+ }++ Exit:+ return error;+ }+++ /* Load the font header. */+ static FT_Error+ _bdf_parse_start( char* line,+ unsigned long linelen,+ unsigned long lineno,+ void* call_data,+ void* client_data )+ {+ unsigned long slen;+ _bdf_line_func_t* next;+ _bdf_parse_t* p;+ bdf_font_t* font;+ char *s;++ FT_Memory memory = NULL;+ FT_Error error = BDF_Err_Ok;++ FT_UNUSED( lineno ); /* only used in debug mode */+++ next = (_bdf_line_func_t *)call_data;+ p = (_bdf_parse_t *) client_data;++ if ( p->font )+ memory = p->font->memory;++ /* Check for a comment. This is done to handle those fonts that have */+ /* comments before the STARTFONT line for some reason. */+ if ( ft_memcmp( line, "COMMENT", 7 ) == 0 )+ {+ if ( p->opts->keep_comments != 0 && p->font != 0 )+ {+ linelen -= 7;++ s = line + 7;+ if ( *s != 0 )+ {+ s++;+ linelen--;+ }++ error = _bdf_add_comment( p->font, s, linelen );+ if ( error )+ goto Exit;+ /* here font is not defined! */+ }++ goto Exit;+ }++ if ( !( p->flags & _BDF_START ) )+ {+ memory = p->memory;++ if ( ft_memcmp( line, "STARTFONT", 9 ) != 0 )+ {+ /* No STARTFONT field is a good indication of a problem. */+ error = BDF_Err_Missing_Startfont_Field;+ goto Exit;+ }++ p->flags = _BDF_START;+ font = p->font = 0;++ if ( FT_NEW( font ) )+ goto Exit;+ p->font = font;++ font->memory = p->memory;+ p->memory = 0;++ { /* setup */+ size_t i;+ bdf_property_t* prop;+++ error = hash_init( &(font->proptbl), memory );+ if ( error )+ goto Exit;+ for ( i = 0, prop = (bdf_property_t*)_bdf_properties;+ i < _num_bdf_properties; i++, prop++ )+ {+ error = hash_insert( prop->name, i,+ &(font->proptbl), memory );+ if ( error )+ goto Exit;+ }+ }++ if ( FT_ALLOC( p->font->internal, sizeof ( hashtable ) ) )+ goto Exit;+ error = hash_init( (hashtable *)p->font->internal,memory );+ if ( error )+ goto Exit;+ p->font->spacing = p->opts->font_spacing;+ p->font->default_char = -1;++ goto Exit;+ }++ /* Check for the start of the properties. */+ if ( ft_memcmp( line, "STARTPROPERTIES", 15 ) == 0 )+ {+ if ( !( p->flags & _BDF_FONT_BBX ) )+ {+ /* Missing the FONTBOUNDINGBOX field. */+ FT_ERROR(( "_bdf_parse_start: " ERRMSG1, lineno, "FONTBOUNDINGBOX" ));+ error = BDF_Err_Missing_Fontboundingbox_Field;+ goto Exit;+ }++ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );+ if ( error )+ goto Exit;+ /* at this point, `p->font' can't be NULL */+ p->cnt = p->font->props_size = _bdf_atoul( p->list.field[1], 0, 10 );++ if ( FT_NEW_ARRAY( p->font->props, p->cnt ) )+ goto Exit;++ p->flags |= _BDF_PROPS;+ *next = _bdf_parse_properties;++ goto Exit;+ }++ /* Check for the FONTBOUNDINGBOX field. */+ if ( ft_memcmp( line, "FONTBOUNDINGBOX", 15 ) == 0 )+ {+ if ( !( p->flags & _BDF_SIZE ) )+ {+ /* Missing the SIZE field. */+ FT_ERROR(( "_bdf_parse_start: " ERRMSG1, lineno, "SIZE" ));+ error = BDF_Err_Missing_Size_Field;+ goto Exit;+ }++ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );+ if ( error )+ goto Exit;++ p->font->bbx.width = _bdf_atos( p->list.field[1], 0, 10 );+ p->font->bbx.height = _bdf_atos( p->list.field[2], 0, 10 );++ p->font->bbx.x_offset = _bdf_atos( p->list.field[3], 0, 10 );+ p->font->bbx.y_offset = _bdf_atos( p->list.field[4], 0, 10 );++ p->font->bbx.ascent = (short)( p->font->bbx.height ++ p->font->bbx.y_offset );++ p->font->bbx.descent = (short)( -p->font->bbx.y_offset );++ p->flags |= _BDF_FONT_BBX;++ goto Exit;+ }++ /* The next thing to check for is the FONT field. */+ if ( ft_memcmp( line, "FONT", 4 ) == 0 )+ {+ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );+ if ( error )+ goto Exit;+ _bdf_list_shift( &p->list, 1 );++ s = _bdf_list_join( &p->list, ' ', &slen );++ if ( !s )+ {+ error = BDF_Err_Invalid_File_Format;+ goto Exit;+ }++ /* Allowing multiple `FONT' lines (which is invalid) doesn't hurt... */+ FT_FREE( p->font->name );++ if ( FT_NEW_ARRAY( p->font->name, slen + 1 ) )+ goto Exit;+ FT_MEM_COPY( p->font->name, s, slen + 1 );++ /* If the font name is an XLFD name, set the spacing to the one in */+ /* the font name. If there is no spacing fall back on the default. */+ error = _bdf_set_default_spacing( p->font, p->opts );+ if ( error )+ goto Exit;++ p->flags |= _BDF_FONT_NAME;++ goto Exit;+ }++ /* Check for the SIZE field. */+ if ( ft_memcmp( line, "SIZE", 4 ) == 0 )+ {+ if ( !( p->flags & _BDF_FONT_NAME ) )+ {+ /* Missing the FONT field. */+ FT_ERROR(( "_bdf_parse_start: " ERRMSG1, lineno, "FONT" ));+ error = BDF_Err_Missing_Font_Field;+ goto Exit;+ }++ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );+ if ( error )+ goto Exit;++ p->font->point_size = _bdf_atoul( p->list.field[1], 0, 10 );+ p->font->resolution_x = _bdf_atoul( p->list.field[2], 0, 10 );+ p->font->resolution_y = _bdf_atoul( p->list.field[3], 0, 10 );++ /* Check for the bits per pixel field. */+ if ( p->list.used == 5 )+ {+ unsigned short bitcount, i, shift;+++ p->font->bpp = (unsigned short)_bdf_atos( p->list.field[4], 0, 10 );++ /* Only values 1, 2, 4, 8 are allowed. */+ shift = p->font->bpp;+ bitcount = 0;+ for ( i = 0; shift > 0; i++ )+ {+ if ( shift & 1 )+ bitcount = i;+ shift >>= 1;+ }++ shift = (short)( ( bitcount > 3 ) ? 8 : ( 1 << bitcount ) );++ if ( p->font->bpp > shift || p->font->bpp != shift )+ {+ /* select next higher value */+ p->font->bpp = (unsigned short)( shift << 1 );+ FT_TRACE2(( "_bdf_parse_start: " ACMSG11, p->font->bpp ));+ }+ }+ else+ p->font->bpp = 1;++ p->flags |= _BDF_SIZE;++ goto Exit;+ }++ /* Check for the CHARS field -- font properties are optional */+ if ( ft_memcmp( line, "CHARS", 5 ) == 0 )+ {+ char nbuf[128];+++ if ( !( p->flags & _BDF_FONT_BBX ) )+ {+ /* Missing the FONTBOUNDINGBOX field. */+ FT_ERROR(( "_bdf_parse_start: " ERRMSG1, lineno, "FONTBOUNDINGBOX" ));+ error = BDF_Err_Missing_Fontboundingbox_Field;+ goto Exit;+ }++ /* Add the two standard X11 properties which are required */+ /* for compiling fonts. */+ p->font->font_ascent = p->font->bbx.ascent;+ ft_sprintf( nbuf, "%hd", p->font->bbx.ascent );+ error = _bdf_add_property( p->font, (char *)"FONT_ASCENT", nbuf );+ if ( error )+ goto Exit;+ FT_TRACE2(( "_bdf_parse_properties: " ACMSG1, p->font->bbx.ascent ));++ p->font->font_descent = p->font->bbx.descent;+ ft_sprintf( nbuf, "%hd", p->font->bbx.descent );+ error = _bdf_add_property( p->font, (char *)"FONT_DESCENT", nbuf );+ if ( error )+ goto Exit;+ FT_TRACE2(( "_bdf_parse_properties: " ACMSG2, p->font->bbx.descent ));++ p->font->modified = 1;++ *next = _bdf_parse_glyphs;++ /* A special return value. */+ error = -1;+ goto Exit;+ }++ error = BDF_Err_Invalid_File_Format;++ Exit:+ return error;+ }+++ /*************************************************************************/+ /* */+ /* API. */+ /* */+ /*************************************************************************/+++ FT_LOCAL_DEF( FT_Error )+ bdf_load_font( FT_Stream stream,+ FT_Memory extmemory,+ bdf_options_t* opts,+ bdf_font_t* *font )+ {+ unsigned long lineno = 0; /* make compiler happy */+ _bdf_parse_t *p = NULL;++ FT_Memory memory = extmemory;+ FT_Error error = BDF_Err_Ok;+++ if ( FT_NEW( p ) )+ goto Exit;++ memory = NULL;+ p->opts = (bdf_options_t*)( ( opts != 0 ) ? opts : &_bdf_opts );+ p->minlb = 32767;+ p->memory = extmemory; /* only during font creation */++ _bdf_list_init( &p->list, extmemory );++ error = _bdf_readstream( stream, _bdf_parse_start,+ (void *)p, &lineno );+ if ( error )+ goto Fail;++ if ( p->font != 0 )+ {+ /* If the font is not proportional, set the font's monowidth */+ /* field to the width of the font bounding box. */+ memory = p->font->memory;++ if ( p->font->spacing != BDF_PROPORTIONAL )+ p->font->monowidth = p->font->bbx.width;++ /* If the number of glyphs loaded is not that of the original count, */+ /* indicate the difference. */+ if ( p->cnt != p->font->glyphs_used + p->font->unencoded_used )+ {+ FT_TRACE2(( "bdf_load_font: " ACMSG15, p->cnt,+ p->font->glyphs_used + p->font->unencoded_used ));+ p->font->modified = 1;+ }++ /* Once the font has been loaded, adjust the overall font metrics if */+ /* necessary. */+ if ( p->opts->correct_metrics != 0 &&+ ( p->font->glyphs_used > 0 || p->font->unencoded_used > 0 ) )+ {+ if ( p->maxrb - p->minlb != p->font->bbx.width )+ {+ FT_TRACE2(( "bdf_load_font: " ACMSG3,+ p->font->bbx.width, p->maxrb - p->minlb ));+ p->font->bbx.width = (unsigned short)( p->maxrb - p->minlb );+ p->font->modified = 1;+ }++ if ( p->font->bbx.x_offset != p->minlb )+ {+ FT_TRACE2(( "bdf_load_font: " ACMSG4,+ p->font->bbx.x_offset, p->minlb ));+ p->font->bbx.x_offset = p->minlb;+ p->font->modified = 1;+ }++ if ( p->font->bbx.ascent != p->maxas )+ {+ FT_TRACE2(( "bdf_load_font: " ACMSG5,+ p->font->bbx.ascent, p->maxas ));+ p->font->bbx.ascent = p->maxas;+ p->font->modified = 1;+ }++ if ( p->font->bbx.descent != p->maxds )+ {+ FT_TRACE2(( "bdf_load_font: " ACMSG6,+ p->font->bbx.descent, p->maxds ));+ p->font->bbx.descent = p->maxds;+ p->font->bbx.y_offset = (short)( -p->maxds );+ p->font->modified = 1;+ }++ if ( p->maxas + p->maxds != p->font->bbx.height )+ {+ FT_TRACE2(( "bdf_load_font: " ACMSG7,+ p->font->bbx.height, p->maxas + p->maxds ));+ p->font->bbx.height = (unsigned short)( p->maxas + p->maxds );+ }++ if ( p->flags & _BDF_SWIDTH_ADJ )+ FT_TRACE2(( "bdf_load_font: " ACMSG8 ));+ }+ }++ if ( p->flags & _BDF_START )+ {+ {+ /* The ENDFONT field was never reached or did not exist. */+ if ( !( p->flags & _BDF_GLYPHS ) )+ {+ /* Error happened while parsing header. */+ FT_ERROR(( "bdf_load_font: " ERRMSG2, lineno ));+ error = BDF_Err_Corrupted_Font_Header;+ goto Exit;+ }+ else+ {+ /* Error happened when parsing glyphs. */+ FT_ERROR(( "bdf_load_font: " ERRMSG3, lineno ));+ error = BDF_Err_Corrupted_Font_Glyphs;+ goto Exit;+ }+ }+ }++ if ( p->font != 0 )+ {+ /* Make sure the comments are NULL terminated if they exist. */+ memory = p->font->memory;++ if ( p->font->comments_len > 0 )+ {+ if ( FT_RENEW_ARRAY( p->font->comments,+ p->font->comments_len,+ p->font->comments_len + 1 ) )+ goto Fail;++ p->font->comments[p->font->comments_len] = 0;+ }+ }+ else if ( error == BDF_Err_Ok )+ error = BDF_Err_Invalid_File_Format;++ *font = p->font;++ Exit:+ if ( p )+ {+ _bdf_list_done( &p->list );++ memory = extmemory;++ FT_FREE( p );+ }++ return error;++ Fail:+ bdf_free_font( p->font );++ memory = extmemory;++ FT_FREE( p->font );++ goto Exit;+ }+++ FT_LOCAL_DEF( void )+ bdf_free_font( bdf_font_t* font )+ {+ bdf_property_t* prop;+ unsigned long i;+ bdf_glyph_t* glyphs;+ FT_Memory memory;+++ if ( font == 0 )+ return;++ memory = font->memory;++ FT_FREE( font->name );++ /* Free up the internal hash table of property names. */+ if ( font->internal )+ {+ hash_free( (hashtable *)font->internal, memory );+ FT_FREE( font->internal );+ }++ /* Free up the comment info. */+ FT_FREE( font->comments );++ /* Free up the properties. */+ for ( i = 0; i < font->props_size; i++ )+ {+ if ( font->props[i].format == BDF_ATOM )+ FT_FREE( font->props[i].value.atom );+ }++ FT_FREE( font->props );++ /* Free up the character info. */+ for ( i = 0, glyphs = font->glyphs;+ i < font->glyphs_used; i++, glyphs++ )+ {+ FT_FREE( glyphs->name );+ FT_FREE( glyphs->bitmap );+ }++ for ( i = 0, glyphs = font->unencoded; i < font->unencoded_used;+ i++, glyphs++ )+ {+ FT_FREE( glyphs->name );+ FT_FREE( glyphs->bitmap );+ }++ FT_FREE( font->glyphs );+ FT_FREE( font->unencoded );++ /* Free up the overflow storage if it was used. */+ for ( i = 0, glyphs = font->overflow.glyphs;+ i < font->overflow.glyphs_used; i++, glyphs++ )+ {+ FT_FREE( glyphs->name );+ FT_FREE( glyphs->bitmap );+ }++ FT_FREE( font->overflow.glyphs );++ /* bdf_cleanup */+ hash_free( &(font->proptbl), memory );++ /* Free up the user defined properties. */+ for ( prop = font->user_props, i = 0;+ i < font->nuser_props; i++, prop++ )+ {+ FT_FREE( prop->name );+ if ( prop->format == BDF_ATOM )+ FT_FREE( prop->value.atom );+ }++ FT_FREE( font->user_props );++ /* FREE( font ); */ /* XXX Fixme */+ }+++ FT_LOCAL_DEF( bdf_property_t * )+ bdf_get_font_property( bdf_font_t* font,+ const char* name )+ {+ hashnode hn;+++ if ( font == 0 || font->props_size == 0 || name == 0 || *name == 0 )+ return 0;++ hn = hash_lookup( name, (hashtable *)font->internal );++ return hn ? ( font->props + hn->data ) : 0;+ }+++/* END */
+ src/cache/ftcache.c view
@@ -0,0 +1,31 @@+/***************************************************************************/+/* */+/* ftcache.c */+/* */+/* The FreeType Caching sub-system (body only). */+/* */+/* Copyright 2000-2001, 2003 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 */
+ src/cache/ftcbasic.c view
@@ -0,0 +1,851 @@+/***************************************************************************/+/* */+/* ftcbasic.c */+/* */+/* The FreeType basic cache interface (body). */+/* */+/* Copyright 2003, 2004, 2005, 2006, 2007, 2009, 2010 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_CACHE_H+#include "ftcglyph.h"+#include "ftcimage.h"+#include "ftcsbits.h"++#include "ftccback.h"+#include "ftcerror.h"++#define FT_COMPONENT trace_cache+++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS++ /*+ * These structures correspond to the FTC_Font and FTC_ImageDesc types+ * that were defined in version 2.1.7.+ */+ typedef struct FTC_OldFontRec_+ {+ FTC_FaceID face_id;+ FT_UShort pix_width;+ FT_UShort pix_height;++ } FTC_OldFontRec, *FTC_OldFont;+++ typedef struct FTC_OldImageDescRec_+ {+ FTC_OldFontRec font;+ FT_UInt32 flags;++ } FTC_OldImageDescRec, *FTC_OldImageDesc;+++ /*+ * Notice that FTC_OldImageDescRec and FTC_ImageTypeRec are nearly+ * identical, bit-wise. The only difference is that the `width' and+ * `height' fields are expressed as 16-bit integers in the old structure,+ * and as normal `int' in the new one.+ *+ * We are going to perform a weird hack to detect which structure is+ * being passed to the image and sbit caches. If the new structure's+ * `width' is larger than 0x10000, we assume that we are really receiving+ * an FTC_OldImageDesc.+ */++#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */+++ /*+ * Basic Families+ *+ */+ typedef struct FTC_BasicAttrRec_+ {+ FTC_ScalerRec scaler;+ FT_UInt load_flags;++ } FTC_BasicAttrRec, *FTC_BasicAttrs;++#define FTC_BASIC_ATTR_COMPARE( a, b ) \+ FT_BOOL( FTC_SCALER_COMPARE( &(a)->scaler, &(b)->scaler ) && \+ (a)->load_flags == (b)->load_flags )++#define FTC_BASIC_ATTR_HASH( a ) \+ ( FTC_SCALER_HASH( &(a)->scaler ) + 31*(a)->load_flags )+++ typedef struct FTC_BasicQueryRec_+ {+ FTC_GQueryRec gquery;+ FTC_BasicAttrRec attrs;++ } FTC_BasicQueryRec, *FTC_BasicQuery;+++ typedef struct FTC_BasicFamilyRec_+ {+ FTC_FamilyRec family;+ FTC_BasicAttrRec attrs;++ } FTC_BasicFamilyRec, *FTC_BasicFamily;+++ FT_CALLBACK_DEF( FT_Bool )+ ftc_basic_family_compare( FTC_MruNode ftcfamily,+ FT_Pointer ftcquery )+ {+ FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;+ FTC_BasicQuery query = (FTC_BasicQuery)ftcquery;+++ return FTC_BASIC_ATTR_COMPARE( &family->attrs, &query->attrs );+ }+++ FT_CALLBACK_DEF( FT_Error )+ ftc_basic_family_init( FTC_MruNode ftcfamily,+ FT_Pointer ftcquery,+ FT_Pointer ftccache )+ {+ FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;+ FTC_BasicQuery query = (FTC_BasicQuery)ftcquery;+ FTC_Cache cache = (FTC_Cache)ftccache;+++ FTC_Family_Init( FTC_FAMILY( family ), cache );+ family->attrs = query->attrs;+ return 0;+ }+++ FT_CALLBACK_DEF( FT_UInt )+ ftc_basic_family_get_count( FTC_Family ftcfamily,+ FTC_Manager manager )+ {+ FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;+ FT_Error error;+ FT_Face face;+ FT_UInt result = 0;+++ error = FTC_Manager_LookupFace( manager, family->attrs.scaler.face_id,+ &face );++ if ( error || !face )+ return result;++ if ( (FT_ULong)face->num_glyphs > FT_UINT_MAX || 0 > face->num_glyphs )+ {+ FT_TRACE1(( "ftc_basic_family_get_count: too large number of glyphs " ));+ FT_TRACE1(( "in this face, truncated\n", face->num_glyphs ));+ }++ if ( !error )+ result = (FT_UInt)face->num_glyphs;++ return result;+ }+++ FT_CALLBACK_DEF( FT_Error )+ ftc_basic_family_load_bitmap( FTC_Family ftcfamily,+ FT_UInt gindex,+ FTC_Manager manager,+ FT_Face *aface )+ {+ FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;+ FT_Error error;+ FT_Size size;+++ error = FTC_Manager_LookupSize( manager, &family->attrs.scaler, &size );+ if ( !error )+ {+ FT_Face face = size->face;+++ error = FT_Load_Glyph( face, gindex,+ family->attrs.load_flags | FT_LOAD_RENDER );+ if ( !error )+ *aface = face;+ }++ return error;+ }+++ FT_CALLBACK_DEF( FT_Error )+ ftc_basic_family_load_glyph( FTC_Family ftcfamily,+ FT_UInt gindex,+ FTC_Cache cache,+ FT_Glyph *aglyph )+ {+ FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily;+ FT_Error error;+ FTC_Scaler scaler = &family->attrs.scaler;+ FT_Face face;+ FT_Size size;+++ /* we will now load the glyph image */+ error = FTC_Manager_LookupSize( cache->manager,+ scaler,+ &size );+ if ( !error )+ {+ face = size->face;++ error = FT_Load_Glyph( face, gindex, family->attrs.load_flags );+ if ( !error )+ {+ if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP ||+ face->glyph->format == FT_GLYPH_FORMAT_OUTLINE )+ {+ /* ok, copy it */+ FT_Glyph glyph;+++ error = FT_Get_Glyph( face->glyph, &glyph );+ if ( !error )+ {+ *aglyph = glyph;+ goto Exit;+ }+ }+ else+ error = FTC_Err_Invalid_Argument;+ }+ }++ Exit:+ return error;+ }+++ FT_CALLBACK_DEF( FT_Bool )+ ftc_basic_gnode_compare_faceid( FTC_Node ftcgnode,+ FT_Pointer ftcface_id,+ FTC_Cache cache )+ {+ FTC_GNode gnode = (FTC_GNode)ftcgnode;+ FTC_FaceID face_id = (FTC_FaceID)ftcface_id;+ FTC_BasicFamily family = (FTC_BasicFamily)gnode->family;+ FT_Bool result;+++ result = FT_BOOL( family->attrs.scaler.face_id == face_id );+ if ( result )+ {+ /* we must call this function to avoid this node from appearing+ * in later lookups with the same face_id!+ */+ FTC_GNode_UnselectFamily( gnode, cache );+ }+ return result;+ }+++ /*+ *+ * basic image cache+ *+ */++ FT_CALLBACK_TABLE_DEF+ const FTC_IFamilyClassRec ftc_basic_image_family_class =+ {+ {+ sizeof ( FTC_BasicFamilyRec ),+ ftc_basic_family_compare,+ ftc_basic_family_init,+ 0, /* FTC_MruNode_ResetFunc */+ 0 /* FTC_MruNode_DoneFunc */+ },+ ftc_basic_family_load_glyph+ };+++ FT_CALLBACK_TABLE_DEF+ const FTC_GCacheClassRec ftc_basic_image_cache_class =+ {+ {+ ftc_inode_new,+ ftc_inode_weight,+ ftc_gnode_compare,+ ftc_basic_gnode_compare_faceid,+ ftc_inode_free,++ sizeof ( FTC_GCacheRec ),+ ftc_gcache_init,+ ftc_gcache_done+ },+ (FTC_MruListClass)&ftc_basic_image_family_class+ };+++ /* documentation is in ftcache.h */++ FT_EXPORT_DEF( FT_Error )+ FTC_ImageCache_New( FTC_Manager manager,+ FTC_ImageCache *acache )+ {+ return FTC_GCache_New( manager, &ftc_basic_image_cache_class,+ (FTC_GCache*)acache );+ }+++ /* documentation is in ftcache.h */++ FT_EXPORT_DEF( FT_Error )+ FTC_ImageCache_Lookup( FTC_ImageCache cache,+ FTC_ImageType type,+ FT_UInt gindex,+ FT_Glyph *aglyph,+ FTC_Node *anode )+ {+ FTC_BasicQueryRec query;+ FTC_Node node = 0; /* make compiler happy */+ FT_Error error;+ FT_PtrDist hash;+++ /* some argument checks are delayed to FTC_Cache_Lookup */+ if ( !aglyph )+ {+ error = FTC_Err_Invalid_Argument;+ goto Exit;+ }++ *aglyph = NULL;+ if ( anode )+ *anode = NULL;++#if defined( FT_CONFIG_OPTION_OLD_INTERNALS ) && ( FT_INT_MAX > 0xFFFFU )++ /*+ * This one is a major hack used to detect whether we are passed a+ * regular FTC_ImageType handle, or a legacy FTC_OldImageDesc one.+ */+ if ( (FT_ULong)type->width >= 0x10000L )+ {+ FTC_OldImageDesc desc = (FTC_OldImageDesc)type;+++ query.attrs.scaler.face_id = desc->font.face_id;+ query.attrs.scaler.width = desc->font.pix_width;+ query.attrs.scaler.height = desc->font.pix_height;+ query.attrs.load_flags = desc->flags;+ }+ else++#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */++ {+ if ( (FT_ULong)(type->flags - FT_INT_MIN) > FT_UINT_MAX )+ {+ FT_TRACE1(( "FTC_ImageCache_Lookup: higher bits in load_flags" ));+ FT_TRACE1(( "0x%x are dropped\n", (type->flags & ~((FT_ULong)FT_UINT_MAX)) ));+ }++ query.attrs.scaler.face_id = type->face_id;+ query.attrs.scaler.width = type->width;+ query.attrs.scaler.height = type->height;+ query.attrs.load_flags = (FT_UInt)type->flags;+ }++ query.attrs.scaler.pixel = 1;+ query.attrs.scaler.x_res = 0; /* make compilers happy */+ query.attrs.scaler.y_res = 0;++ hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;++#if 1 /* inlining is about 50% faster! */+ FTC_GCACHE_LOOKUP_CMP( cache,+ ftc_basic_family_compare,+ FTC_GNode_Compare,+ hash, gindex,+ &query,+ node,+ error );+#else+ error = FTC_GCache_Lookup( FTC_GCACHE( cache ),+ hash, gindex,+ FTC_GQUERY( &query ),+ &node );+#endif+ if ( !error )+ {+ *aglyph = FTC_INODE( node )->glyph;++ if ( anode )+ {+ *anode = node;+ node->ref_count++;+ }+ }++ Exit:+ return error;+ }+++ /* documentation is in ftcache.h */++ FT_EXPORT_DEF( FT_Error )+ FTC_ImageCache_LookupScaler( FTC_ImageCache cache,+ FTC_Scaler scaler,+ FT_ULong load_flags,+ FT_UInt gindex,+ FT_Glyph *aglyph,+ FTC_Node *anode )+ {+ FTC_BasicQueryRec query;+ FTC_Node node = 0; /* make compiler happy */+ FT_Error error;+ FT_PtrDist hash;+++ /* some argument checks are delayed to FTC_Cache_Lookup */+ if ( !aglyph || !scaler )+ {+ error = FTC_Err_Invalid_Argument;+ goto Exit;+ }++ *aglyph = NULL;+ if ( anode )+ *anode = NULL;++ /* FT_Load_Glyph(), FT_Load_Char() take FT_UInt flags */+ if ( load_flags > FT_UINT_MAX )+ {+ FT_TRACE1(( "FTC_ImageCache_LookupScaler: higher bits in load_flags" ));+ FT_TRACE1(( "0x%x are dropped\n", (load_flags & ~((FT_ULong)FT_UINT_MAX)) ));+ }++ query.attrs.scaler = scaler[0];+ query.attrs.load_flags = (FT_UInt)load_flags;++ hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;++ FTC_GCACHE_LOOKUP_CMP( cache,+ ftc_basic_family_compare,+ FTC_GNode_Compare,+ hash, gindex,+ &query,+ node,+ error );+ if ( !error )+ {+ *aglyph = FTC_INODE( node )->glyph;++ if ( anode )+ {+ *anode = node;+ node->ref_count++;+ }+ }++ Exit:+ return error;+ }+++ +#ifdef FT_CONFIG_OPTION_OLD_INTERNALS++ /* yet another backwards-legacy structure */+ typedef struct FTC_OldImage_Desc_+ {+ FTC_FontRec font;+ FT_UInt image_type;++ } FTC_OldImage_Desc;+++#define FTC_OLD_IMAGE_FORMAT( x ) ( (x) & 7 )+++#define ftc_old_image_format_bitmap 0x0000+#define ftc_old_image_format_outline 0x0001++#define ftc_old_image_format_mask 0x000F++#define ftc_old_image_flag_monochrome 0x0010+#define ftc_old_image_flag_unhinted 0x0020+#define ftc_old_image_flag_autohinted 0x0040+#define ftc_old_image_flag_unscaled 0x0080+#define ftc_old_image_flag_no_sbits 0x0100++ /* monochrome bitmap */+#define ftc_old_image_mono ftc_old_image_format_bitmap | \+ ftc_old_image_flag_monochrome++ /* anti-aliased bitmap */+#define ftc_old_image_grays ftc_old_image_format_bitmap++ /* scaled outline */+#define ftc_old_image_outline ftc_old_image_format_outline+++ static void+ ftc_image_type_from_old_desc( FTC_ImageType typ,+ FTC_OldImage_Desc* desc )+ {+ typ->face_id = desc->font.face_id;+ typ->width = desc->font.pix_width;+ typ->height = desc->font.pix_height;++ /* convert image type flags to load flags */+ {+ FT_UInt load_flags = FT_LOAD_DEFAULT;+ FT_UInt type = desc->image_type;+++ /* determine load flags, depending on the font description's */+ /* image type */++ if ( FTC_OLD_IMAGE_FORMAT( type ) == ftc_old_image_format_bitmap )+ {+ if ( type & ftc_old_image_flag_monochrome )+ load_flags |= FT_LOAD_MONOCHROME;++ /* disable embedded bitmaps loading if necessary */+ if ( type & ftc_old_image_flag_no_sbits )+ load_flags |= FT_LOAD_NO_BITMAP;+ }+ else+ {+ /* we want an outline, don't load embedded bitmaps */+ load_flags |= FT_LOAD_NO_BITMAP;++ if ( type & ftc_old_image_flag_unscaled )+ load_flags |= FT_LOAD_NO_SCALE;+ }++ /* always render glyphs to bitmaps */+ load_flags |= FT_LOAD_RENDER;++ if ( type & ftc_old_image_flag_unhinted )+ load_flags |= FT_LOAD_NO_HINTING;++ if ( type & ftc_old_image_flag_autohinted )+ load_flags |= FT_LOAD_FORCE_AUTOHINT;++ typ->flags = load_flags;+ }+ }+++ FT_EXPORT( FT_Error )+ FTC_Image_Cache_New( FTC_Manager manager,+ FTC_ImageCache *acache );++ FT_EXPORT( FT_Error )+ FTC_Image_Cache_Lookup( FTC_ImageCache icache,+ FTC_OldImage_Desc* desc,+ FT_UInt gindex,+ FT_Glyph *aglyph );+++ FT_EXPORT_DEF( FT_Error )+ FTC_Image_Cache_New( FTC_Manager manager,+ FTC_ImageCache *acache )+ {+ return FTC_ImageCache_New( manager, (FTC_ImageCache*)acache );+ }++++ FT_EXPORT_DEF( FT_Error )+ FTC_Image_Cache_Lookup( FTC_ImageCache icache,+ FTC_OldImage_Desc* desc,+ FT_UInt gindex,+ FT_Glyph *aglyph )+ {+ FTC_ImageTypeRec type0;+++ if ( !desc )+ return FTC_Err_Invalid_Argument;++ ftc_image_type_from_old_desc( &type0, desc );++ return FTC_ImageCache_Lookup( (FTC_ImageCache)icache,+ &type0,+ gindex,+ aglyph,+ NULL );+ }++#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */+++ /*+ *+ * basic small bitmap cache+ *+ */+++ FT_CALLBACK_TABLE_DEF+ const FTC_SFamilyClassRec ftc_basic_sbit_family_class =+ {+ {+ sizeof( FTC_BasicFamilyRec ),+ ftc_basic_family_compare,+ ftc_basic_family_init,+ 0, /* FTC_MruNode_ResetFunc */+ 0 /* FTC_MruNode_DoneFunc */+ },+ ftc_basic_family_get_count,+ ftc_basic_family_load_bitmap+ };+++ FT_CALLBACK_TABLE_DEF+ const FTC_GCacheClassRec ftc_basic_sbit_cache_class =+ {+ {+ ftc_snode_new,+ ftc_snode_weight,+ ftc_snode_compare,+ ftc_basic_gnode_compare_faceid,+ ftc_snode_free,++ sizeof ( FTC_GCacheRec ),+ ftc_gcache_init,+ ftc_gcache_done+ },+ (FTC_MruListClass)&ftc_basic_sbit_family_class+ };+++ /* documentation is in ftcache.h */++ FT_EXPORT_DEF( FT_Error )+ FTC_SBitCache_New( FTC_Manager manager,+ FTC_SBitCache *acache )+ {+ return FTC_GCache_New( manager, &ftc_basic_sbit_cache_class,+ (FTC_GCache*)acache );+ }+++ /* documentation is in ftcache.h */++ FT_EXPORT_DEF( FT_Error )+ FTC_SBitCache_Lookup( FTC_SBitCache cache,+ FTC_ImageType type,+ FT_UInt gindex,+ FTC_SBit *ansbit,+ FTC_Node *anode )+ {+ FT_Error error;+ FTC_BasicQueryRec query;+ FTC_Node node = 0; /* make compiler happy */+ FT_PtrDist hash;+++ if ( anode )+ *anode = NULL;++ /* other argument checks delayed to FTC_Cache_Lookup */+ if ( !ansbit )+ return FTC_Err_Invalid_Argument;++ *ansbit = NULL;++#if defined( FT_CONFIG_OPTION_OLD_INTERNALS ) && ( FT_INT_MAX > 0xFFFFU )++ /* This one is a major hack used to detect whether we are passed a+ * regular FTC_ImageType handle, or a legacy FTC_OldImageDesc one.+ */+ if ( (FT_ULong)type->width >= 0x10000L )+ {+ FTC_OldImageDesc desc = (FTC_OldImageDesc)type;+++ query.attrs.scaler.face_id = desc->font.face_id;+ query.attrs.scaler.width = desc->font.pix_width;+ query.attrs.scaler.height = desc->font.pix_height;+ query.attrs.load_flags = desc->flags;+ }+ else++#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */++ {+ if ( (FT_ULong)(type->flags - FT_INT_MIN) > FT_UINT_MAX )+ {+ FT_TRACE1(( "FTC_ImageCache_Lookup: higher bits in load_flags" ));+ FT_TRACE1(( "0x%x are dropped\n", (type->flags & ~((FT_ULong)FT_UINT_MAX)) ));+ }++ query.attrs.scaler.face_id = type->face_id;+ query.attrs.scaler.width = type->width;+ query.attrs.scaler.height = type->height;+ query.attrs.load_flags = (FT_UInt)type->flags;+ }++ query.attrs.scaler.pixel = 1;+ query.attrs.scaler.x_res = 0; /* make compilers happy */+ query.attrs.scaler.y_res = 0;++ /* beware, the hash must be the same for all glyph ranges! */+ hash = FTC_BASIC_ATTR_HASH( &query.attrs ) ++ gindex / FTC_SBIT_ITEMS_PER_NODE;++#if 1 /* inlining is about 50% faster! */+ FTC_GCACHE_LOOKUP_CMP( cache,+ ftc_basic_family_compare,+ FTC_SNode_Compare,+ hash, gindex,+ &query,+ node,+ error );+#else+ error = FTC_GCache_Lookup( FTC_GCACHE( cache ),+ hash,+ gindex,+ FTC_GQUERY( &query ),+ &node );+#endif+ if ( error )+ goto Exit;++ *ansbit = FTC_SNODE( node )->sbits ++ ( gindex - FTC_GNODE( node )->gindex );++ if ( anode )+ {+ *anode = node;+ node->ref_count++;+ }++ Exit:+ return error;+ }+++ /* documentation is in ftcache.h */++ FT_EXPORT_DEF( FT_Error )+ FTC_SBitCache_LookupScaler( FTC_SBitCache cache,+ FTC_Scaler scaler,+ FT_ULong load_flags,+ FT_UInt gindex,+ FTC_SBit *ansbit,+ FTC_Node *anode )+ {+ FT_Error error;+ FTC_BasicQueryRec query;+ FTC_Node node = 0; /* make compiler happy */+ FT_PtrDist hash;+++ if ( anode )+ *anode = NULL;++ /* other argument checks delayed to FTC_Cache_Lookup */+ if ( !ansbit || !scaler )+ return FTC_Err_Invalid_Argument;++ *ansbit = NULL;++ /* FT_Load_Glyph(), FT_Load_Char() take FT_UInt flags */+ if ( load_flags > FT_UINT_MAX )+ {+ FT_TRACE1(( "FTC_ImageCache_LookupScaler: higher bits in load_flags" ));+ FT_TRACE1(( "0x%x are dropped\n", (load_flags & ~((FT_ULong)FT_UINT_MAX)) ));+ }++ query.attrs.scaler = scaler[0];+ query.attrs.load_flags = (FT_UInt)load_flags;++ /* beware, the hash must be the same for all glyph ranges! */+ hash = FTC_BASIC_ATTR_HASH( &query.attrs ) ++ gindex / FTC_SBIT_ITEMS_PER_NODE;++ FTC_GCACHE_LOOKUP_CMP( cache,+ ftc_basic_family_compare,+ FTC_SNode_Compare,+ hash, gindex,+ &query,+ node,+ error );+ if ( error )+ goto Exit;++ *ansbit = FTC_SNODE( node )->sbits ++ ( gindex - FTC_GNODE( node )->gindex );++ if ( anode )+ {+ *anode = node;+ node->ref_count++;+ }++ Exit:+ return error;+ }+++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS++ FT_EXPORT( FT_Error )+ FTC_SBit_Cache_New( FTC_Manager manager,+ FTC_SBitCache *acache );++ FT_EXPORT( FT_Error )+ FTC_SBit_Cache_Lookup( FTC_SBitCache cache,+ FTC_OldImage_Desc* desc,+ FT_UInt gindex,+ FTC_SBit *ansbit );+++ FT_EXPORT_DEF( FT_Error )+ FTC_SBit_Cache_New( FTC_Manager manager,+ FTC_SBitCache *acache )+ {+ return FTC_SBitCache_New( manager, (FTC_SBitCache*)acache );+ }+++ FT_EXPORT_DEF( FT_Error )+ FTC_SBit_Cache_Lookup( FTC_SBitCache cache,+ FTC_OldImage_Desc* desc,+ FT_UInt gindex,+ FTC_SBit *ansbit )+ {+ FTC_ImageTypeRec type0;+++ if ( !desc )+ return FTC_Err_Invalid_Argument;++ ftc_image_type_from_old_desc( &type0, desc );++ return FTC_SBitCache_Lookup( (FTC_SBitCache)cache,+ &type0,+ gindex,+ ansbit,+ NULL );+ }++#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */+++/* END */
+ src/cache/ftccache.c view
@@ -0,0 +1,595 @@+/***************************************************************************/+/* */+/* ftccache.c */+/* */+/* The FreeType internal cache interface (body). */+/* */+/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 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 "ftcmanag.h"+#include FT_INTERNAL_OBJECTS_H+#include FT_INTERNAL_DEBUG_H++#include "ftccback.h"+#include "ftcerror.h"++#undef FT_COMPONENT+#define FT_COMPONENT trace_cache+++#define FTC_HASH_MAX_LOAD 2+#define FTC_HASH_MIN_LOAD 1+#define FTC_HASH_SUB_LOAD ( FTC_HASH_MAX_LOAD - FTC_HASH_MIN_LOAD )++/* this one _must_ be a power of 2! */+#define FTC_HASH_INITIAL_SIZE 8+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** CACHE NODE DEFINITIONS *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /* add a new node to the head of the manager's circular MRU list */+ static void+ ftc_node_mru_link( FTC_Node node,+ FTC_Manager manager )+ {+ void *nl = &manager->nodes_list;+++ FTC_MruNode_Prepend( (FTC_MruNode*)nl,+ (FTC_MruNode)node );+ manager->num_nodes++;+ }+++ /* remove a node from the manager's MRU list */+ static void+ ftc_node_mru_unlink( FTC_Node node,+ FTC_Manager manager )+ {+ void *nl = &manager->nodes_list;+++ FTC_MruNode_Remove( (FTC_MruNode*)nl,+ (FTC_MruNode)node );+ manager->num_nodes--;+ }+++#ifndef FTC_INLINE++ /* move a node to the head of the manager's MRU list */+ static void+ ftc_node_mru_up( FTC_Node node,+ FTC_Manager manager )+ {+ FTC_MruNode_Up( (FTC_MruNode*)&manager->nodes_list,+ (FTC_MruNode)node );+ }++#endif /* !FTC_INLINE */+++ /* Note that this function cannot fail. If we cannot re-size the+ * buckets array appropriately, we simply degrade the hash table's+ * performance!+ */+ static void+ ftc_cache_resize( FTC_Cache cache )+ {+ for (;;)+ {+ FTC_Node node, *pnode;+ FT_UFast p = cache->p;+ FT_UFast mask = cache->mask;+ FT_UFast count = mask + p + 1; /* number of buckets */+++ /* do we need to shrink the buckets array? */+ if ( cache->slack < 0 )+ {+ FTC_Node new_list = NULL;+++ /* try to expand the buckets array _before_ splitting+ * the bucket lists+ */+ if ( p >= mask )+ {+ FT_Memory memory = cache->memory;+ FT_Error error;+++ /* if we can't expand the array, leave immediately */+ if ( FT_RENEW_ARRAY( cache->buckets, (mask+1)*2, (mask+1)*4 ) )+ break;+ }++ /* split a single bucket */+ pnode = cache->buckets + p;++ for (;;)+ {+ node = *pnode;+ if ( node == NULL )+ break;++ if ( node->hash & ( mask + 1 ) )+ {+ *pnode = node->link;+ node->link = new_list;+ new_list = node;+ }+ else+ pnode = &node->link;+ }++ cache->buckets[p + mask + 1] = new_list;++ cache->slack += FTC_HASH_MAX_LOAD;++ if ( p >= mask )+ {+ cache->mask = 2 * mask + 1;+ cache->p = 0;+ }+ else+ cache->p = p + 1;+ }++ /* do we need to expand the buckets array? */+ else if ( cache->slack > (FT_Long)count * FTC_HASH_SUB_LOAD )+ {+ FT_UFast old_index = p + mask;+ FTC_Node* pold;+++ if ( old_index + 1 <= FTC_HASH_INITIAL_SIZE )+ break;++ if ( p == 0 )+ {+ FT_Memory memory = cache->memory;+ FT_Error error;+++ /* if we can't shrink the array, leave immediately */+ if ( FT_RENEW_ARRAY( cache->buckets,+ ( mask + 1 ) * 2, mask + 1 ) )+ break;++ cache->mask >>= 1;+ p = cache->mask;+ }+ else+ p--;++ pnode = cache->buckets + p;+ while ( *pnode )+ pnode = &(*pnode)->link;++ pold = cache->buckets + old_index;+ *pnode = *pold;+ *pold = NULL;++ cache->slack -= FTC_HASH_MAX_LOAD;+ cache->p = p;+ }+ else /* the hash table is balanced */+ break;+ }+ }+++ /* remove a node from its cache's hash table */+ static void+ ftc_node_hash_unlink( FTC_Node node0,+ FTC_Cache cache )+ {+ FTC_Node *pnode;+ FT_UInt idx;+++ idx = (FT_UInt)( node0->hash & cache->mask );+ if ( idx < cache->p )+ idx = (FT_UInt)( node0->hash & ( 2 * cache->mask + 1 ) );++ pnode = cache->buckets + idx;++ for (;;)+ {+ FTC_Node node = *pnode;+++ if ( node == NULL )+ {+ FT_TRACE0(( "ftc_node_hash_unlink: unknown node\n" ));+ return;+ }++ if ( node == node0 )+ break;++ pnode = &(*pnode)->link;+ }++ *pnode = node0->link;+ node0->link = NULL;++ cache->slack++;+ ftc_cache_resize( cache );+ }+++ /* add a node to the `top' of its cache's hash table */+ static void+ ftc_node_hash_link( FTC_Node node,+ FTC_Cache cache )+ {+ FTC_Node *pnode;+ FT_UInt idx;+++ idx = (FT_UInt)( node->hash & cache->mask );+ if ( idx < cache->p )+ idx = (FT_UInt)( node->hash & (2 * cache->mask + 1 ) );++ pnode = cache->buckets + idx;++ node->link = *pnode;+ *pnode = node;++ cache->slack--;+ ftc_cache_resize( cache );+ }+++ /* remove a node from the cache manager */+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS+ FT_BASE_DEF( void )+#else+ FT_LOCAL_DEF( void )+#endif+ ftc_node_destroy( FTC_Node node,+ FTC_Manager manager )+ {+ FTC_Cache cache;+++#ifdef FT_DEBUG_ERROR+ /* find node's cache */+ if ( node->cache_index >= manager->num_caches )+ {+ FT_TRACE0(( "ftc_node_destroy: invalid node handle\n" ));+ return;+ }+#endif++ cache = manager->caches[node->cache_index];++#ifdef FT_DEBUG_ERROR+ if ( cache == NULL )+ {+ FT_TRACE0(( "ftc_node_destroy: invalid node handle\n" ));+ return;+ }+#endif++ manager->cur_weight -= cache->clazz.node_weight( node, cache );++ /* remove node from mru list */+ ftc_node_mru_unlink( node, manager );++ /* remove node from cache's hash table */+ ftc_node_hash_unlink( node, cache );++ /* now finalize it */+ cache->clazz.node_free( node, cache );++#if 0+ /* check, just in case of general corruption :-) */+ if ( manager->num_nodes == 0 )+ FT_TRACE0(( "ftc_node_destroy: invalid cache node count (%d)\n",+ manager->num_nodes ));+#endif+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** ABSTRACT CACHE CLASS *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+++ FT_LOCAL_DEF( FT_Error )+ FTC_Cache_Init( FTC_Cache cache )+ {+ return ftc_cache_init( cache );+ }+++ FT_LOCAL_DEF( FT_Error )+ ftc_cache_init( FTC_Cache cache )+ {+ FT_Memory memory = cache->memory;+ FT_Error error;+++ cache->p = 0;+ cache->mask = FTC_HASH_INITIAL_SIZE - 1;+ cache->slack = FTC_HASH_INITIAL_SIZE * FTC_HASH_MAX_LOAD;++ (void)FT_NEW_ARRAY( cache->buckets, FTC_HASH_INITIAL_SIZE * 2 );+ return error;+ }+++ static void+ FTC_Cache_Clear( FTC_Cache cache )+ {+ if ( cache && cache->buckets )+ {+ FTC_Manager manager = cache->manager;+ FT_UFast i;+ FT_UFast count;+++ count = cache->p + cache->mask + 1;++ for ( i = 0; i < count; i++ )+ {+ FTC_Node *pnode = cache->buckets + i, next, node = *pnode;+++ while ( node )+ {+ next = node->link;+ node->link = NULL;++ /* remove node from mru list */+ ftc_node_mru_unlink( node, manager );++ /* now finalize it */+ manager->cur_weight -= cache->clazz.node_weight( node, cache );++ cache->clazz.node_free( node, cache );+ node = next;+ }+ cache->buckets[i] = NULL;+ }+ ftc_cache_resize( cache );+ }+ }+++ FT_LOCAL_DEF( void )+ ftc_cache_done( FTC_Cache cache )+ {+ if ( cache->memory )+ {+ FT_Memory memory = cache->memory;+++ FTC_Cache_Clear( cache );++ FT_FREE( cache->buckets );+ cache->mask = 0;+ cache->p = 0;+ cache->slack = 0;++ cache->memory = NULL;+ }+ }+++ FT_LOCAL_DEF( void )+ FTC_Cache_Done( FTC_Cache cache )+ {+ ftc_cache_done( cache );+ }+++ static void+ ftc_cache_add( FTC_Cache cache,+ FT_PtrDist hash,+ FTC_Node node )+ {+ node->hash = hash;+ node->cache_index = (FT_UInt16) cache->index;+ node->ref_count = 0;++ ftc_node_hash_link( node, cache );+ ftc_node_mru_link( node, cache->manager );++ {+ FTC_Manager manager = cache->manager;+++ manager->cur_weight += cache->clazz.node_weight( node, cache );++ if ( manager->cur_weight >= manager->max_weight )+ {+ node->ref_count++;+ FTC_Manager_Compress( manager );+ node->ref_count--;+ }+ }+ }+++ FT_LOCAL_DEF( FT_Error )+ FTC_Cache_NewNode( FTC_Cache cache,+ FT_PtrDist hash,+ FT_Pointer query,+ FTC_Node *anode )+ {+ FT_Error error;+ FTC_Node node;+++ /*+ * We use the FTC_CACHE_TRYLOOP macros to support out-of-memory+ * errors (OOM) correctly, i.e., by flushing the cache progressively+ * in order to make more room.+ */++ FTC_CACHE_TRYLOOP( cache )+ {+ error = cache->clazz.node_new( &node, query, cache );+ }+ FTC_CACHE_TRYLOOP_END();++ if ( error )+ node = NULL;+ else+ {+ /* don't assume that the cache has the same number of buckets, since+ * our allocation request might have triggered global cache flushing+ */+ ftc_cache_add( cache, hash, node );+ }++ *anode = node;+ return error;+ }+++#ifndef FTC_INLINE++ FT_LOCAL_DEF( FT_Error )+ FTC_Cache_Lookup( FTC_Cache cache,+ FT_PtrDist hash,+ FT_Pointer query,+ FTC_Node *anode )+ {+ FT_UFast idx;+ FTC_Node* bucket;+ FTC_Node* pnode;+ FTC_Node node;+ FT_Error error = FTC_Err_Ok;++ FTC_Node_CompareFunc compare = cache->clazz.node_compare;+++ if ( cache == NULL || anode == NULL )+ return FTC_Err_Invalid_Argument;++ idx = hash & cache->mask;+ if ( idx < cache->p )+ idx = hash & ( cache->mask * 2 + 1 );++ bucket = cache->buckets + idx;+ pnode = bucket;+ for (;;)+ {+ node = *pnode;+ if ( node == NULL )+ goto NewNode;++ if ( node->hash == hash && compare( node, query, cache ) )+ break;++ pnode = &node->link;+ }++ if ( node != *bucket )+ {+ *pnode = node->link;+ node->link = *bucket;+ *bucket = node;+ }++ /* move to head of MRU list */+ {+ FTC_Manager manager = cache->manager;+++ if ( node != manager->nodes_list )+ ftc_node_mru_up( node, manager );+ }+ *anode = node;+ return error;++ NewNode:+ return FTC_Cache_NewNode( cache, hash, query, anode );+ }++#endif /* !FTC_INLINE */+++ FT_LOCAL_DEF( void )+ FTC_Cache_RemoveFaceID( FTC_Cache cache,+ FTC_FaceID face_id )+ {+ FT_UFast i, count;+ FTC_Manager manager = cache->manager;+ FTC_Node frees = NULL;+++ count = cache->p + cache->mask;+ for ( i = 0; i < count; i++ )+ {+ FTC_Node* bucket = cache->buckets + i;+ FTC_Node* pnode = bucket;+++ for ( ;; )+ {+ FTC_Node node = *pnode;+++ if ( node == NULL )+ break;++ if ( cache->clazz.node_remove_faceid( node, face_id, cache ) )+ {+ *pnode = node->link;+ node->link = frees;+ frees = node;+ }+ else+ pnode = &node->link;+ }+ }++ /* remove all nodes in the free list */+ while ( frees )+ {+ FTC_Node node;+++ node = frees;+ frees = node->link;++ manager->cur_weight -= cache->clazz.node_weight( node, cache );+ ftc_node_mru_unlink( node, manager );++ cache->clazz.node_free( node, cache );++ cache->slack++;+ }++ ftc_cache_resize( cache );+ }+++/* END */
+ src/cache/ftccache.h view
@@ -0,0 +1,319 @@+/***************************************************************************/+/* */+/* ftccache.h */+/* */+/* FreeType internal cache interface (specification). */+/* */+/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#ifndef __FTCCACHE_H__+#define __FTCCACHE_H__+++#include "ftcmru.h"++FT_BEGIN_HEADER++#define _FTC_FACE_ID_HASH( i ) \+ ((FT_PtrDist)(( (FT_PtrDist)(i) >> 3 ) ^ ( (FT_PtrDist)(i) << 7 )))++ /* handle to cache object */+ typedef struct FTC_CacheRec_* FTC_Cache;++ /* handle to cache class */+ typedef const struct FTC_CacheClassRec_* FTC_CacheClass;+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** CACHE NODE DEFINITIONS *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /*************************************************************************/+ /* */+ /* Each cache controls one or more cache nodes. Each node is part of */+ /* the global_lru list of the manager. Its `data' field however is used */+ /* as a reference count for now. */+ /* */+ /* A node can be anything, depending on the type of information held by */+ /* the cache. It can be an individual glyph image, a set of bitmaps */+ /* glyphs for a given size, some metrics, etc. */+ /* */+ /*************************************************************************/++ /* structure size should be 20 bytes on 32-bits machines */+ typedef struct FTC_NodeRec_+ {+ FTC_MruNodeRec mru; /* circular mru list pointer */+ FTC_Node link; /* used for hashing */+ FT_PtrDist hash; /* used for hashing too */+ FT_UShort cache_index; /* index of cache the node belongs to */+ FT_Short ref_count; /* reference count for this node */++ } FTC_NodeRec;+++#define FTC_NODE( x ) ( (FTC_Node)(x) )+#define FTC_NODE_P( x ) ( (FTC_Node*)(x) )++#define FTC_NODE__NEXT( x ) FTC_NODE( (x)->mru.next )+#define FTC_NODE__PREV( x ) FTC_NODE( (x)->mru.prev )+++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS+ FT_BASE( void )+ ftc_node_destroy( FTC_Node node,+ FTC_Manager manager );+#endif+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** CACHE DEFINITIONS *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /* initialize a new cache node */+ typedef FT_Error+ (*FTC_Node_NewFunc)( FTC_Node *pnode,+ FT_Pointer query,+ FTC_Cache cache );++ typedef FT_Offset+ (*FTC_Node_WeightFunc)( FTC_Node node,+ FTC_Cache cache );++ /* compare a node to a given key pair */+ typedef FT_Bool+ (*FTC_Node_CompareFunc)( FTC_Node node,+ FT_Pointer key,+ FTC_Cache cache );+++ typedef void+ (*FTC_Node_FreeFunc)( FTC_Node node,+ FTC_Cache cache );++ typedef FT_Error+ (*FTC_Cache_InitFunc)( FTC_Cache cache );++ typedef void+ (*FTC_Cache_DoneFunc)( FTC_Cache cache );+++ typedef struct FTC_CacheClassRec_+ {+ FTC_Node_NewFunc node_new;+ FTC_Node_WeightFunc node_weight;+ FTC_Node_CompareFunc node_compare;+ FTC_Node_CompareFunc node_remove_faceid;+ FTC_Node_FreeFunc node_free;++ FT_Offset cache_size;+ FTC_Cache_InitFunc cache_init;+ FTC_Cache_DoneFunc cache_done;++ } FTC_CacheClassRec;+++ /* each cache really implements a dynamic hash table to manage its nodes */+ typedef struct FTC_CacheRec_+ {+ FT_UFast p;+ FT_UFast mask;+ FT_Long slack;+ FTC_Node* buckets;++ FTC_CacheClassRec clazz; /* local copy, for speed */++ FTC_Manager manager;+ FT_Memory memory;+ FT_UInt index; /* in manager's table */++ FTC_CacheClass org_class; /* original class pointer */++ } FTC_CacheRec;+++#define FTC_CACHE( x ) ( (FTC_Cache)(x) )+#define FTC_CACHE_P( x ) ( (FTC_Cache*)(x) )+++ /* default cache initialize */+ FT_LOCAL( FT_Error )+ FTC_Cache_Init( FTC_Cache cache );++ /* default cache finalizer */+ FT_LOCAL( void )+ FTC_Cache_Done( FTC_Cache cache );++ /* Call this function to lookup the cache. If no corresponding+ * node is found, a new one is automatically created. This function+ * is capable of flushing the cache adequately to make room for the+ * new cache object.+ */++#ifndef FTC_INLINE+ FT_LOCAL( FT_Error )+ FTC_Cache_Lookup( FTC_Cache cache,+ FT_PtrDist hash,+ FT_Pointer query,+ FTC_Node *anode );+#endif++ FT_LOCAL( FT_Error )+ FTC_Cache_NewNode( FTC_Cache cache,+ FT_PtrDist hash,+ FT_Pointer query,+ FTC_Node *anode );++ /* Remove all nodes that relate to a given face_id. This is useful+ * when un-installing fonts. Note that if a cache node relates to+ * the face_id, but is locked (i.e., has `ref_count > 0'), the node+ * will _not_ be destroyed, but its internal face_id reference will+ * be modified.+ *+ * The final result will be that the node will never come back+ * in further lookup requests, and will be flushed on demand from+ * the cache normally when its reference count reaches 0.+ */+ FT_LOCAL( void )+ FTC_Cache_RemoveFaceID( FTC_Cache cache,+ FTC_FaceID face_id );+++#ifdef FTC_INLINE++#define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \+ FT_BEGIN_STMNT \+ FTC_Node *_bucket, *_pnode, _node; \+ FTC_Cache _cache = FTC_CACHE(cache); \+ FT_PtrDist _hash = (FT_PtrDist)(hash); \+ FTC_Node_CompareFunc _nodcomp = (FTC_Node_CompareFunc)(nodecmp); \+ FT_UFast _idx; \+ \+ \+ error = FTC_Err_Ok; \+ node = NULL; \+ _idx = _hash & _cache->mask; \+ if ( _idx < _cache->p ) \+ _idx = _hash & ( _cache->mask*2 + 1 ); \+ \+ _bucket = _pnode = _cache->buckets + _idx; \+ for (;;) \+ { \+ _node = *_pnode; \+ if ( _node == NULL ) \+ goto _NewNode; \+ \+ if ( _node->hash == _hash && _nodcomp( _node, query, _cache ) ) \+ break; \+ \+ _pnode = &_node->link; \+ } \+ \+ if ( _node != *_bucket ) \+ { \+ *_pnode = _node->link; \+ _node->link = *_bucket; \+ *_bucket = _node; \+ } \+ \+ { \+ FTC_Manager _manager = _cache->manager; \+ void* _nl = &_manager->nodes_list; \+ \+ \+ if ( _node != _manager->nodes_list ) \+ FTC_MruNode_Up( (FTC_MruNode*)_nl, \+ (FTC_MruNode)_node ); \+ } \+ goto _Ok; \+ \+ _NewNode: \+ error = FTC_Cache_NewNode( _cache, _hash, query, &_node ); \+ \+ _Ok: \+ node = _node; \+ FT_END_STMNT++#else /* !FTC_INLINE */++#define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \+ FT_BEGIN_STMNT \+ error = FTC_Cache_Lookup( FTC_CACHE( cache ), hash, query, \+ (FTC_Node*)&(node) ); \+ FT_END_STMNT++#endif /* !FTC_INLINE */+++ /*+ * This macro, together with FTC_CACHE_TRYLOOP_END, defines a retry+ * loop to flush the cache repeatedly in case of memory overflows.+ *+ * It is used when creating a new cache node, or within a lookup+ * that needs to allocate data (e.g., the sbit cache lookup).+ *+ * Example:+ *+ * {+ * FTC_CACHE_TRYLOOP( cache )+ * error = load_data( ... );+ * FTC_CACHE_TRYLOOP_END()+ * }+ *+ */+#define FTC_CACHE_TRYLOOP( cache ) \+ { \+ FTC_Manager _try_manager = FTC_CACHE( cache )->manager; \+ FT_UInt _try_count = 4; \+ \+ \+ for (;;) \+ { \+ FT_UInt _try_done;+++#define FTC_CACHE_TRYLOOP_END() \+ if ( !error || error != FTC_Err_Out_Of_Memory ) \+ break; \+ \+ _try_done = FTC_Manager_FlushN( _try_manager, _try_count ); \+ if ( _try_done == 0 ) \+ break; \+ \+ if ( _try_done == _try_count ) \+ { \+ _try_count *= 2; \+ if ( _try_count < _try_done || \+ _try_count > _try_manager->num_nodes ) \+ _try_count = _try_manager->num_nodes; \+ } \+ } \+ }++ /* */++FT_END_HEADER+++#endif /* __FTCCACHE_H__ */+++/* END */
+ src/cache/ftccback.h view
@@ -0,0 +1,90 @@+/***************************************************************************/+/* */+/* ftccback.h */+/* */+/* Callback functions of the caching sub-system (specification only). */+/* */+/* Copyright 2004, 2005, 2006 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/++#ifndef __FTCCBACK_H__+#define __FTCCBACK_H__++#include <ft2build.h>+#include FT_CACHE_H+#include "ftcmru.h"+#include "ftcimage.h"+#include "ftcmanag.h"+#include "ftcglyph.h"+#include "ftcsbits.h"+++ FT_LOCAL( void )+ ftc_inode_free( FTC_Node inode,+ FTC_Cache cache );++ FT_LOCAL( FT_Error )+ ftc_inode_new( FTC_Node *pinode,+ FT_Pointer gquery,+ FTC_Cache cache );++ FT_LOCAL( FT_Offset )+ ftc_inode_weight( FTC_Node inode,+ FTC_Cache cache );+++ FT_LOCAL( void )+ ftc_snode_free( FTC_Node snode,+ FTC_Cache cache );++ FT_LOCAL( FT_Error )+ ftc_snode_new( FTC_Node *psnode,+ FT_Pointer gquery,+ FTC_Cache cache );++ FT_LOCAL( FT_Offset )+ ftc_snode_weight( FTC_Node snode,+ FTC_Cache cache );++ FT_LOCAL( FT_Bool )+ ftc_snode_compare( FTC_Node snode,+ FT_Pointer gquery,+ FTC_Cache cache );+++ FT_LOCAL( FT_Bool )+ ftc_gnode_compare( FTC_Node gnode,+ FT_Pointer gquery,+ FTC_Cache cache );+++ FT_LOCAL( FT_Error )+ ftc_gcache_init( FTC_Cache cache );++ FT_LOCAL( void )+ ftc_gcache_done( FTC_Cache cache );+++ FT_LOCAL( FT_Error )+ ftc_cache_init( FTC_Cache cache );++ FT_LOCAL( void )+ ftc_cache_done( FTC_Cache cache );++#ifndef FT_CONFIG_OPTION_OLD_INTERNALS+ FT_LOCAL( void )+ ftc_node_destroy( FTC_Node node,+ FTC_Manager manager );+#endif++#endif /* __FTCCBACK_H__ */++/* END */
+ src/cache/ftccmap.c view
@@ -0,0 +1,430 @@+/***************************************************************************/+/* */+/* ftccmap.c */+/* */+/* FreeType CharMap cache (body) */+/* */+/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */+/* 2010 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#include <ft2build.h>+#include FT_FREETYPE_H+#include FT_CACHE_H+#include "ftcmanag.h"+#include FT_INTERNAL_MEMORY_H+#include FT_INTERNAL_DEBUG_H++#include "ftccback.h"+#include "ftcerror.h"++#undef FT_COMPONENT+#define FT_COMPONENT trace_cache+++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS++ typedef enum FTC_OldCMapType_+ {+ FTC_OLD_CMAP_BY_INDEX = 0,+ FTC_OLD_CMAP_BY_ENCODING = 1,+ FTC_OLD_CMAP_BY_ID = 2++ } FTC_OldCMapType;+++ typedef struct FTC_OldCMapIdRec_+ {+ FT_UInt platform;+ FT_UInt encoding;++ } FTC_OldCMapIdRec, *FTC_OldCMapId;+++ typedef struct FTC_OldCMapDescRec_+ {+ FTC_FaceID face_id;+ FTC_OldCMapType type;++ union+ {+ FT_UInt index;+ FT_Encoding encoding;+ FTC_OldCMapIdRec id;++ } u;++ } FTC_OldCMapDescRec, *FTC_OldCMapDesc;++#endif /* FT_CONFIG_OLD_INTERNALS */+++ /*************************************************************************/+ /* */+ /* Each FTC_CMapNode contains a simple array to map a range of character */+ /* codes to equivalent glyph indices. */+ /* */+ /* For now, the implementation is very basic: Each node maps a range of */+ /* 128 consecutive character codes to their corresponding glyph indices. */+ /* */+ /* We could do more complex things, but I don't think it is really very */+ /* useful. */+ /* */+ /*************************************************************************/+++ /* number of glyph indices / character code per node */+#define FTC_CMAP_INDICES_MAX 128++ /* compute a query/node hash */+#define FTC_CMAP_HASH( faceid, index, charcode ) \+ ( _FTC_FACE_ID_HASH( faceid ) + 211 * (index) + \+ ( (charcode) / FTC_CMAP_INDICES_MAX ) )++ /* the charmap query */+ typedef struct FTC_CMapQueryRec_+ {+ FTC_FaceID face_id;+ FT_UInt cmap_index;+ FT_UInt32 char_code;++ } FTC_CMapQueryRec, *FTC_CMapQuery;++#define FTC_CMAP_QUERY( x ) ((FTC_CMapQuery)(x))+#define FTC_CMAP_QUERY_HASH( x ) \+ FTC_CMAP_HASH( (x)->face_id, (x)->cmap_index, (x)->char_code )++ /* the cmap cache node */+ typedef struct FTC_CMapNodeRec_+ {+ FTC_NodeRec node;+ FTC_FaceID face_id;+ FT_UInt cmap_index;+ FT_UInt32 first; /* first character in node */+ FT_UInt16 indices[FTC_CMAP_INDICES_MAX]; /* array of glyph indices */++ } FTC_CMapNodeRec, *FTC_CMapNode;++#define FTC_CMAP_NODE( x ) ( (FTC_CMapNode)( x ) )+#define FTC_CMAP_NODE_HASH( x ) \+ FTC_CMAP_HASH( (x)->face_id, (x)->cmap_index, (x)->first )++ /* if (indices[n] == FTC_CMAP_UNKNOWN), we assume that the corresponding */+ /* glyph indices haven't been queried through FT_Get_Glyph_Index() yet */+#define FTC_CMAP_UNKNOWN ( (FT_UInt16)-1 )+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** CHARMAP NODES *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+++ FT_CALLBACK_DEF( void )+ ftc_cmap_node_free( FTC_Node ftcnode,+ FTC_Cache cache )+ {+ FTC_CMapNode node = (FTC_CMapNode)ftcnode;+ FT_Memory memory = cache->memory;+++ FT_FREE( node );+ }+++ /* initialize a new cmap node */+ FT_CALLBACK_DEF( FT_Error )+ ftc_cmap_node_new( FTC_Node *ftcanode,+ FT_Pointer ftcquery,+ FTC_Cache cache )+ {+ FTC_CMapNode *anode = (FTC_CMapNode*)ftcanode;+ FTC_CMapQuery query = (FTC_CMapQuery)ftcquery;+ FT_Error error;+ FT_Memory memory = cache->memory;+ FTC_CMapNode node = NULL;+ FT_UInt nn;+++ if ( !FT_NEW( node ) )+ {+ node->face_id = query->face_id;+ node->cmap_index = query->cmap_index;+ node->first = (query->char_code / FTC_CMAP_INDICES_MAX) *+ FTC_CMAP_INDICES_MAX;++ for ( nn = 0; nn < FTC_CMAP_INDICES_MAX; nn++ )+ node->indices[nn] = FTC_CMAP_UNKNOWN;+ }++ *anode = node;+ return error;+ }+++ /* compute the weight of a given cmap node */+ FT_CALLBACK_DEF( FT_Offset )+ ftc_cmap_node_weight( FTC_Node cnode,+ FTC_Cache cache )+ {+ FT_UNUSED( cnode );+ FT_UNUSED( cache );++ return sizeof ( *cnode );+ }+++ /* compare a cmap node to a given query */+ FT_CALLBACK_DEF( FT_Bool )+ ftc_cmap_node_compare( FTC_Node ftcnode,+ FT_Pointer ftcquery,+ FTC_Cache cache )+ {+ FTC_CMapNode node = (FTC_CMapNode)ftcnode;+ FTC_CMapQuery query = (FTC_CMapQuery)ftcquery;+ FT_UNUSED( cache );+++ if ( node->face_id == query->face_id &&+ node->cmap_index == query->cmap_index )+ {+ FT_UInt32 offset = (FT_UInt32)( query->char_code - node->first );+++ return FT_BOOL( offset < FTC_CMAP_INDICES_MAX );+ }++ return 0;+ }+++ FT_CALLBACK_DEF( FT_Bool )+ ftc_cmap_node_remove_faceid( FTC_Node ftcnode,+ FT_Pointer ftcface_id,+ FTC_Cache cache )+ {+ FTC_CMapNode node = (FTC_CMapNode)ftcnode;+ FTC_FaceID face_id = (FTC_FaceID)ftcface_id;+ FT_UNUSED( cache );++ return FT_BOOL( node->face_id == face_id );+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** GLYPH IMAGE CACHE *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+++ FT_CALLBACK_TABLE_DEF+ const FTC_CacheClassRec ftc_cmap_cache_class =+ {+ ftc_cmap_node_new,+ ftc_cmap_node_weight,+ ftc_cmap_node_compare,+ ftc_cmap_node_remove_faceid,+ ftc_cmap_node_free,++ sizeof ( FTC_CacheRec ),+ ftc_cache_init,+ ftc_cache_done,+ };+++ /* documentation is in ftcache.h */++ FT_EXPORT_DEF( FT_Error )+ FTC_CMapCache_New( FTC_Manager manager,+ FTC_CMapCache *acache )+ {+ return FTC_Manager_RegisterCache( manager,+ &ftc_cmap_cache_class,+ FTC_CACHE_P( acache ) );+ }+++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS++ /*+ * Unfortunately, it is not possible to support binary backwards+ * compatibility in the cmap cache. The FTC_CMapCache_Lookup signature+ * changes were too deep, and there is no clever hackish way to detect+ * what kind of structure we are being passed.+ *+ * On the other hand it seems that no production code is using this+ * function on Unix distributions.+ */++#endif+++ /* documentation is in ftcache.h */++ FT_EXPORT_DEF( FT_UInt )+ FTC_CMapCache_Lookup( FTC_CMapCache cmap_cache,+ FTC_FaceID face_id,+ FT_Int cmap_index,+ FT_UInt32 char_code )+ {+ FTC_Cache cache = FTC_CACHE( cmap_cache );+ FTC_CMapQueryRec query;+ FTC_Node node;+ FT_Error error;+ FT_UInt gindex = 0;+ FT_PtrDist hash;+ FT_Int no_cmap_change = 0;+++ if ( cmap_index < 0 )+ {+ /* Treat a negative cmap index as a special value, meaning that you */+ /* don't want to change the FT_Face's character map through this */+ /* call. This can be useful if the face requester callback already */+ /* sets the face's charmap to the appropriate value. */++ no_cmap_change = 1;+ cmap_index = 0;+ }++ if ( !cache )+ {+ FT_TRACE0(( "FTC_CMapCache_Lookup: bad arguments, returning 0\n" ));+ return 0;+ }++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS++ /*+ * If cmap_index is greater than the maximum number of cachable+ * charmaps, we assume the request is from a legacy rogue client + * using old internal header. See include/config/ftoption.h.+ */+ if ( cmap_index > FT_MAX_CHARMAP_CACHEABLE && !no_cmap_change )+ {+ FTC_OldCMapDesc desc = (FTC_OldCMapDesc) face_id;+++ char_code = (FT_UInt32)cmap_index;+ query.face_id = desc->face_id;+++ switch ( desc->type )+ {+ case FTC_OLD_CMAP_BY_INDEX:+ query.cmap_index = desc->u.index;+ query.char_code = (FT_UInt32)cmap_index;+ break;++ case FTC_OLD_CMAP_BY_ENCODING:+ {+ FT_Face face;+++ error = FTC_Manager_LookupFace( cache->manager, desc->face_id,+ &face );+ if ( error )+ return 0;++ FT_Select_Charmap( face, desc->u.encoding );++ return FT_Get_Char_Index( face, char_code );+ }++ default:+ return 0;+ }+ }+ else++#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */++ {+ query.face_id = face_id;+ query.cmap_index = (FT_UInt)cmap_index;+ query.char_code = char_code;+ }++ hash = FTC_CMAP_HASH( face_id, cmap_index, char_code );++#if 1+ FTC_CACHE_LOOKUP_CMP( cache, ftc_cmap_node_compare, hash, &query,+ node, error );+#else+ error = FTC_Cache_Lookup( cache, hash, &query, &node );+#endif+ if ( error )+ goto Exit;++ FT_ASSERT( (FT_UInt)( char_code - FTC_CMAP_NODE( node )->first ) <+ FTC_CMAP_INDICES_MAX );++ /* something rotten can happen with rogue clients */+ if ( (FT_UInt)( char_code - FTC_CMAP_NODE( node )->first >=+ FTC_CMAP_INDICES_MAX ) )+ return 0; /* XXX: should return appropriate error */++ gindex = FTC_CMAP_NODE( node )->indices[char_code -+ FTC_CMAP_NODE( node )->first];+ if ( gindex == FTC_CMAP_UNKNOWN )+ {+ FT_Face face;+++ gindex = 0;++ error = FTC_Manager_LookupFace( cache->manager,+ FTC_CMAP_NODE( node )->face_id,+ &face );+ if ( error )+ goto Exit;++#ifdef FT_MAX_CHARMAP_CACHEABLE+ /* something rotten can happen with rogue clients */+ if ( cmap_index > FT_MAX_CHARMAP_CACHEABLE )+ return 0; /* XXX: should return appropriate error */+#endif++ if ( (FT_UInt)cmap_index < (FT_UInt)face->num_charmaps )+ {+ FT_CharMap old, cmap = NULL;+++ old = face->charmap;+ cmap = face->charmaps[cmap_index];++ if ( old != cmap && !no_cmap_change )+ FT_Set_Charmap( face, cmap );++ gindex = FT_Get_Char_Index( face, char_code );++ if ( old != cmap && !no_cmap_change )+ FT_Set_Charmap( face, old );+ }++ FTC_CMAP_NODE( node )->indices[char_code -+ FTC_CMAP_NODE( node )->first]+ = (FT_UShort)gindex;+ }++ Exit:+ return gindex;+ }+++/* END */
+ src/cache/ftcerror.h view
@@ -0,0 +1,40 @@+/***************************************************************************/+/* */+/* ftcerror.h */+/* */+/* Caching sub-system error codes (specification only). */+/* */+/* Copyright 2001 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__++#define FT_ERR_PREFIX FTC_Err_+#define FT_ERR_BASE FT_Mod_Err_Cache++#include FT_ERRORS_H++#endif /* __FTCERROR_H__ */++/* END */
+ src/cache/ftcglyph.c view
@@ -0,0 +1,209 @@+/***************************************************************************/+/* */+/* ftcglyph.c */+/* */+/* FreeType Glyph Image (FT_Glyph) cache (body). */+/* */+/* Copyright 2000-2001, 2003, 2004, 2006, 2009 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 "ftcglyph.h"+#include FT_ERRORS_H++#include "ftccback.h"+#include "ftcerror.h"+++ /* create a new chunk node, setting its cache index and ref count */+ FT_LOCAL_DEF( void )+ FTC_GNode_Init( FTC_GNode gnode,+ FT_UInt gindex,+ FTC_Family family )+ {+ gnode->family = family;+ gnode->gindex = gindex;+ family->num_nodes++;+ }+++ FT_LOCAL_DEF( void )+ FTC_GNode_UnselectFamily( FTC_GNode gnode,+ FTC_Cache cache )+ {+ FTC_Family family = gnode->family;+++ gnode->family = NULL;+ if ( family && --family->num_nodes == 0 )+ FTC_FAMILY_FREE( family, cache );+ }+++ FT_LOCAL_DEF( void )+ FTC_GNode_Done( FTC_GNode gnode,+ FTC_Cache cache )+ {+ /* finalize the node */+ gnode->gindex = 0;++ FTC_GNode_UnselectFamily( gnode, cache );+ }+++ FT_LOCAL_DEF( FT_Bool )+ ftc_gnode_compare( FTC_Node ftcgnode,+ FT_Pointer ftcgquery,+ FTC_Cache cache )+ {+ FTC_GNode gnode = (FTC_GNode)ftcgnode;+ FTC_GQuery gquery = (FTC_GQuery)ftcgquery;+ FT_UNUSED( cache );+++ return FT_BOOL( gnode->family == gquery->family &&+ gnode->gindex == gquery->gindex );+ }+++ FT_LOCAL_DEF( FT_Bool )+ FTC_GNode_Compare( FTC_GNode gnode,+ FTC_GQuery gquery )+ {+ return ftc_gnode_compare( FTC_NODE( gnode ), gquery, NULL );+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** CHUNK SETS *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ FT_LOCAL_DEF( void )+ FTC_Family_Init( FTC_Family family,+ FTC_Cache cache )+ {+ FTC_GCacheClass clazz = FTC_CACHE__GCACHE_CLASS( cache );+++ family->clazz = clazz->family_class;+ family->num_nodes = 0;+ family->cache = cache;+ }+++ FT_LOCAL_DEF( FT_Error )+ ftc_gcache_init( FTC_Cache ftccache )+ {+ FTC_GCache cache = (FTC_GCache)ftccache;+ FT_Error error;+++ error = FTC_Cache_Init( FTC_CACHE( cache ) );+ if ( !error )+ {+ FTC_GCacheClass clazz = (FTC_GCacheClass)FTC_CACHE( cache )->org_class;++ FTC_MruList_Init( &cache->families,+ clazz->family_class,+ 0, /* no maximum here! */+ cache,+ FTC_CACHE( cache )->memory );+ }++ return error;+ }+++#if 0++ FT_LOCAL_DEF( FT_Error )+ FTC_GCache_Init( FTC_GCache cache )+ {+ return ftc_gcache_init( FTC_CACHE( cache ) );+ }++#endif /* 0 */+++ FT_LOCAL_DEF( void )+ ftc_gcache_done( FTC_Cache ftccache )+ {+ FTC_GCache cache = (FTC_GCache)ftccache;+++ FTC_Cache_Done( (FTC_Cache)cache );+ FTC_MruList_Done( &cache->families );+ }+++#if 0++ FT_LOCAL_DEF( void )+ FTC_GCache_Done( FTC_GCache cache )+ {+ ftc_gcache_done( FTC_CACHE( cache ) );+ }++#endif /* 0 */+++ FT_LOCAL_DEF( FT_Error )+ FTC_GCache_New( FTC_Manager manager,+ FTC_GCacheClass clazz,+ FTC_GCache *acache )+ {+ return FTC_Manager_RegisterCache( manager, (FTC_CacheClass)clazz,+ (FTC_Cache*)acache );+ }+++#ifndef FTC_INLINE++ FT_LOCAL_DEF( FT_Error )+ FTC_GCache_Lookup( FTC_GCache cache,+ FT_PtrDist hash,+ FT_UInt gindex,+ FTC_GQuery query,+ FTC_Node *anode )+ {+ FT_Error error;+++ query->gindex = gindex;++ FTC_MRULIST_LOOKUP( &cache->families, query, query->family, error );+ if ( !error )+ {+ FTC_Family family = query->family;+++ /* prevent the family from being destroyed too early when an */+ /* out-of-memory condition occurs during glyph node initialization. */+ family->num_nodes++;++ error = FTC_Cache_Lookup( FTC_CACHE( cache ), hash, query, anode );++ if ( --family->num_nodes == 0 )+ FTC_FAMILY_FREE( family, cache );+ }+ return error;+ }++#endif /* !FTC_INLINE */+++/* END */
+ src/cache/ftcglyph.h view
@@ -0,0 +1,323 @@+/***************************************************************************/+/* */+/* ftcglyph.h */+/* */+/* FreeType abstract glyph cache (specification). */+/* */+/* Copyright 2000-2001, 2003, 2004, 2006, 2007 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++ /*+ *+ * FTC_GCache is an _abstract_ cache object optimized to store glyph+ * data. It works as follows:+ *+ * - It manages FTC_GNode objects. Each one of them can hold one or more+ * glyph `items'. Item types are not specified in the FTC_GCache but+ * in classes that extend it.+ *+ * - Glyph attributes, like face ID, character size, render mode, etc.,+ * can be grouped into abstract `glyph families'. This avoids storing+ * the attributes within the FTC_GCache, since it is likely that many+ * FTC_GNodes will belong to the same family in typical uses.+ *+ * - Each FTC_GNode is thus an FTC_Node with two additional fields:+ *+ * * gindex: A glyph index, or the first index in a glyph range.+ * * family: A pointer to a glyph `family'.+ *+ * - Family types are not fully specific in the FTC_Family type, but+ * by classes that extend it.+ *+ * Note that both FTC_ImageCache and FTC_SBitCache extend FTC_GCache.+ * They share an FTC_Family sub-class called FTC_BasicFamily which is+ * used to store the following data: face ID, pixel/point sizes, load+ * flags. For more details see the file `src/cache/ftcbasic.c'.+ *+ * Client applications can extend FTC_GNode with their own FTC_GNode+ * and FTC_Family sub-classes to implement more complex caches (e.g.,+ * handling automatic synthesis, like obliquing & emboldening, colored+ * glyphs, etc.).+ *+ * See also the FTC_ICache & FTC_SCache classes in `ftcimage.h' and+ * `ftcsbits.h', which both extend FTC_GCache with additional+ * optimizations.+ *+ * A typical FTC_GCache implementation must provide at least the+ * following:+ *+ * - FTC_GNode sub-class, e.g. MyNode, with relevant methods:+ * my_node_new (must call FTC_GNode_Init)+ * my_node_free (must call FTC_GNode_Done)+ * my_node_compare (must call FTC_GNode_Compare)+ * my_node_remove_faceid (must call ftc_gnode_unselect in case+ * of match)+ *+ * - FTC_Family sub-class, e.g. MyFamily, with relevant methods:+ * my_family_compare+ * my_family_init+ * my_family_reset (optional)+ * my_family_done+ *+ * - FTC_GQuery sub-class, e.g. MyQuery, to hold cache-specific query+ * data.+ *+ * - Constant structures for a FTC_GNodeClass.+ *+ * - MyCacheNew() can be implemented easily as a call to the convenience+ * function FTC_GCache_New.+ *+ * - MyCacheLookup with a call to FTC_GCache_Lookup. This function will+ * automatically:+ *+ * - Search for the corresponding family in the cache, or create+ * a new one if necessary. Put it in FTC_GQUERY(myquery).family+ *+ * - Call FTC_Cache_Lookup.+ *+ * If it returns NULL, you should create a new node, then call+ * ftc_cache_add as usual.+ */+++ /*************************************************************************/+ /* */+ /* Important: The functions defined in this file are only used to */+ /* implement an abstract glyph cache class. You need to */+ /* provide additional logic to implement a complete cache. */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /********* *********/+ /********* WARNING, THIS IS BETA CODE. *********/+ /********* *********/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++#ifndef __FTCGLYPH_H__+#define __FTCGLYPH_H__+++#include <ft2build.h>+#include "ftcmanag.h"+++FT_BEGIN_HEADER+++ /*+ * We can group glyphs into `families'. Each family correspond to a+ * given face ID, character size, transform, etc.+ *+ * Families are implemented as MRU list nodes. They are+ * reference-counted.+ */++ typedef struct FTC_FamilyRec_+ {+ FTC_MruNodeRec mrunode;+ FT_UInt num_nodes; /* current number of nodes in this family */+ FTC_Cache cache;+ FTC_MruListClass clazz;++ } FTC_FamilyRec, *FTC_Family;++#define FTC_FAMILY(x) ( (FTC_Family)(x) )+#define FTC_FAMILY_P(x) ( (FTC_Family*)(x) )+++ typedef struct FTC_GNodeRec_+ {+ FTC_NodeRec node;+ FTC_Family family;+ FT_UInt gindex;++ } FTC_GNodeRec, *FTC_GNode;++#define FTC_GNODE( x ) ( (FTC_GNode)(x) )+#define FTC_GNODE_P( x ) ( (FTC_GNode*)(x) )+++ typedef struct FTC_GQueryRec_+ {+ FT_UInt gindex;+ FTC_Family family;++ } FTC_GQueryRec, *FTC_GQuery;++#define FTC_GQUERY( x ) ( (FTC_GQuery)(x) )+++ /*************************************************************************/+ /* */+ /* These functions are exported so that they can be called from */+ /* user-provided cache classes; otherwise, they are really part of the */+ /* cache sub-system internals. */+ /* */++ /* must be called by derived FTC_Node_InitFunc routines */+ FT_LOCAL( void )+ FTC_GNode_Init( FTC_GNode node,+ FT_UInt gindex, /* glyph index for node */+ FTC_Family family );++ /* returns TRUE iff the query's glyph index correspond to the node; */+ /* this assumes that the `family' and `hash' fields of the query are */+ /* already correctly set */+ FT_LOCAL( FT_Bool )+ FTC_GNode_Compare( FTC_GNode gnode,+ FTC_GQuery gquery );++ /* call this function to clear a node's family -- this is necessary */+ /* to implement the `node_remove_faceid' cache method correctly */+ FT_LOCAL( void )+ FTC_GNode_UnselectFamily( FTC_GNode gnode,+ FTC_Cache cache );++ /* must be called by derived FTC_Node_DoneFunc routines */+ FT_LOCAL( void )+ FTC_GNode_Done( FTC_GNode node,+ FTC_Cache cache );+++ FT_LOCAL( void )+ FTC_Family_Init( FTC_Family family,+ FTC_Cache cache );++ typedef struct FTC_GCacheRec_+ {+ FTC_CacheRec cache;+ FTC_MruListRec families;++ } FTC_GCacheRec, *FTC_GCache;++#define FTC_GCACHE( x ) ((FTC_GCache)(x))+++#if 0+ /* can be used as @FTC_Cache_InitFunc */+ FT_LOCAL( FT_Error )+ FTC_GCache_Init( FTC_GCache cache );+#endif+++#if 0+ /* can be used as @FTC_Cache_DoneFunc */+ FT_LOCAL( void )+ FTC_GCache_Done( FTC_GCache cache );+#endif+++ /* the glyph cache class adds fields for the family implementation */+ typedef struct FTC_GCacheClassRec_+ {+ FTC_CacheClassRec clazz;+ FTC_MruListClass family_class;++ } FTC_GCacheClassRec;++ typedef const FTC_GCacheClassRec* FTC_GCacheClass;++#define FTC_GCACHE_CLASS( x ) ((FTC_GCacheClass)(x))++#define FTC_CACHE__GCACHE_CLASS( x ) \+ FTC_GCACHE_CLASS( FTC_CACHE(x)->org_class )+#define FTC_CACHE__FAMILY_CLASS( x ) \+ ( (FTC_MruListClass)FTC_CACHE__GCACHE_CLASS( x )->family_class )+++ /* convenience function; use it instead of FTC_Manager_Register_Cache */+ FT_LOCAL( FT_Error )+ FTC_GCache_New( FTC_Manager manager,+ FTC_GCacheClass clazz,+ FTC_GCache *acache );++#ifndef FTC_INLINE+ FT_LOCAL( FT_Error )+ FTC_GCache_Lookup( FTC_GCache cache,+ FT_PtrDist hash,+ FT_UInt gindex,+ FTC_GQuery query,+ FTC_Node *anode );+#endif+++ /* */+++#define FTC_FAMILY_FREE( family, cache ) \+ FTC_MruList_Remove( &FTC_GCACHE((cache))->families, \+ (FTC_MruNode)(family) )+++#ifdef FTC_INLINE++#define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash, \+ gindex, query, node, error ) \+ FT_BEGIN_STMNT \+ FTC_GCache _gcache = FTC_GCACHE( cache ); \+ FTC_GQuery _gquery = (FTC_GQuery)( query ); \+ FTC_MruNode_CompareFunc _fcompare = (FTC_MruNode_CompareFunc)(famcmp); \+ FTC_MruNode _mrunode; \+ \+ \+ _gquery->gindex = (gindex); \+ \+ FTC_MRULIST_LOOKUP_CMP( &_gcache->families, _gquery, _fcompare, \+ _mrunode, error ); \+ _gquery->family = FTC_FAMILY( _mrunode ); \+ if ( !error ) \+ { \+ FTC_Family _gqfamily = _gquery->family; \+ \+ \+ _gqfamily->num_nodes++; \+ \+ FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ); \+ \+ if ( --_gqfamily->num_nodes == 0 ) \+ FTC_FAMILY_FREE( _gqfamily, _gcache ); \+ } \+ FT_END_STMNT+ /* */++#else /* !FTC_INLINE */++#define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash, \+ gindex, query, node, error ) \+ FT_BEGIN_STMNT \+ \+ error = FTC_GCache_Lookup( FTC_GCACHE( cache ), hash, gindex, \+ FTC_GQUERY( query ), node ); \+ \+ FT_END_STMNT++#endif /* !FTC_INLINE */+++FT_END_HEADER+++#endif /* __FTCGLYPH_H__ */+++/* END */
+ src/cache/ftcimage.c view
@@ -0,0 +1,163 @@+/***************************************************************************/+/* */+/* ftcimage.c */+/* */+/* FreeType Image cache (body). */+/* */+/* Copyright 2000-2001, 2003, 2004, 2006, 2010 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 "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_labs( bitg->bitmap.pitch ) ++ sizeof ( *bitg );+ }+ break;++ case FT_GLYPH_FORMAT_OUTLINE:+ {+ FT_OutlineGlyph outg;+++ outg = (FT_OutlineGlyph)glyph;+ size = outg->outline.n_points *+ ( sizeof ( FT_Vector ) + sizeof ( FT_Byte ) ) ++ 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 */
+ src/cache/ftcimage.h view
@@ -0,0 +1,107 @@+/***************************************************************************/+/* */+/* ftcimage.h */+/* */+/* FreeType Generic Image cache (specification) */+/* */+/* Copyright 2000-2001, 2002, 2003, 2006 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 */
+ src/cache/ftcmanag.c view
@@ -0,0 +1,743 @@+/***************************************************************************/+/* */+/* ftcmanag.c */+/* */+/* FreeType Cache Manager (body). */+/* */+/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009, 2010 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++#define FTC_LRU_GET_MANAGER( lru ) ( (FTC_Manager)(lru)->user_data )+++ 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, scaler->width, 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 );+ }+++ FT_CALLBACK_TABLE_DEF+ 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 == NULL )+ return FTC_Err_Invalid_Argument;++ *asize = NULL;++ if ( !manager )+ return FTC_Err_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 );+ }+++ FT_CALLBACK_TABLE_DEF+ 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 == NULL )+ return FTC_Err_Invalid_Argument;++ *aface = NULL;++ if ( !manager )+ return FTC_Err_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 FTC_Err_Invalid_Library_Handle;++ 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 )+ {+ FTC_MruList_Reset( &manager->sizes );+ FTC_MruList_Reset( &manager->faces );+ }+ /* XXX: FIXME: flush the caches? */+ }+++#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_ULong 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 = FTC_Err_Invalid_Argument;+ FTC_Cache cache = NULL;+++ if ( manager && clazz && acache )+ {+ FT_Memory memory = manager->memory;+++ if ( manager->num_caches >= FTC_MAX_CACHES )+ {+ error = FTC_Err_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;++ /* 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 && (FT_UInt)node->cache_index < manager->num_caches )+ node->ref_count--;+ }+++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS++ FT_EXPORT_DEF( FT_Error )+ FTC_Manager_Lookup_Face( FTC_Manager manager,+ FTC_FaceID face_id,+ FT_Face *aface )+ {+ return FTC_Manager_LookupFace( manager, face_id, aface );+ }+++ FT_EXPORT( FT_Error )+ FTC_Manager_Lookup_Size( FTC_Manager manager,+ FTC_Font font,+ FT_Face *aface,+ FT_Size *asize )+ {+ FTC_ScalerRec scaler;+ FT_Error error;+ FT_Size size;+ FT_Face face;+++ scaler.face_id = font->face_id;+ scaler.width = font->pix_width;+ scaler.height = font->pix_height;+ scaler.pixel = TRUE;+ scaler.x_res = 0;+ scaler.y_res = 0;++ error = FTC_Manager_LookupSize( manager, &scaler, &size );+ if ( error )+ {+ face = NULL;+ size = NULL;+ }+ else+ face = size->face;++ if ( aface )+ *aface = face;++ if ( asize )+ *asize = size;++ return error;+ }++#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */+++/* END */
+ src/cache/ftcmanag.h view
@@ -0,0 +1,175 @@+/***************************************************************************/+/* */+/* ftcmanag.h */+/* */+/* FreeType Cache Manager (specification). */+/* */+/* Copyright 2000-2001, 2003, 2004, 2006 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++ /*************************************************************************/+ /* */+ /* A cache manager is in charge of the following: */+ /* */+ /* - Maintain a mapping between generic FTC_FaceIDs and live FT_Face */+ /* objects. The mapping itself is performed through a user-provided */+ /* callback. However, the manager maintains a small cache of FT_Face */+ /* and FT_Size objects in order to speed up things considerably. */+ /* */+ /* - Manage one or more cache objects. Each cache is in charge of */+ /* holding a varying number of `cache nodes'. Each cache node */+ /* represents a minimal amount of individually accessible cached */+ /* data. For example, a cache node can be an FT_Glyph image */+ /* containing a vector outline, or some glyph metrics, or anything */+ /* else. */+ /* */+ /* Each cache node has a certain size in bytes that is added to the */+ /* total amount of `cache memory' within the manager. */+ /* */+ /* All cache nodes are located in a global LRU list, where the oldest */+ /* node is at the tail of the list. */+ /* */+ /* Each node belongs to a single cache, and includes a reference */+ /* count to avoid destroying it (due to caching). */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /********* *********/+ /********* WARNING, THIS IS BETA CODE. *********/+ /********* *********/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++#ifndef __FTCMANAG_H__+#define __FTCMANAG_H__+++#include <ft2build.h>+#include FT_CACHE_H+#include "ftcmru.h"+#include "ftccache.h"+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Section> */+ /* cache_subsystem */+ /* */+ /*************************************************************************/+++#define FTC_MAX_FACES_DEFAULT 2+#define FTC_MAX_SIZES_DEFAULT 4+#define FTC_MAX_BYTES_DEFAULT 200000L /* ~200kByte by default */++ /* maximum number of caches registered in a single manager */+#define FTC_MAX_CACHES 16+++ typedef struct FTC_ManagerRec_+ {+ FT_Library library;+ FT_Memory memory;++ FTC_Node nodes_list;+ FT_ULong max_weight;+ FT_ULong cur_weight;+ FT_UInt num_nodes;++ FTC_Cache caches[FTC_MAX_CACHES];+ FT_UInt num_caches;++ FTC_MruListRec faces;+ FTC_MruListRec sizes;++ FT_Pointer request_data;+ FTC_Face_Requester request_face;++ } FTC_ManagerRec;+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FTC_Manager_Compress */+ /* */+ /* <Description> */+ /* This function is used to check the state of the cache manager if */+ /* its `num_bytes' field is greater than its `max_bytes' field. It */+ /* will flush as many old cache nodes as possible (ignoring cache */+ /* nodes with a non-zero reference count). */+ /* */+ /* <InOut> */+ /* manager :: A handle to the cache manager. */+ /* */+ /* <Note> */+ /* Client applications should not call this function directly. It is */+ /* normally invoked by specific cache implementations. */+ /* */+ /* The reason this function is exported is to allow client-specific */+ /* cache classes. */+ /* */+ FT_LOCAL( void )+ FTC_Manager_Compress( FTC_Manager manager );+++ /* try to flush `count' old nodes from the cache; return the number+ * of really flushed nodes+ */+ FT_LOCAL( FT_UInt )+ FTC_Manager_FlushN( FTC_Manager manager,+ FT_UInt count );+++ /* this must be used internally for the moment */+ FT_LOCAL( FT_Error )+ FTC_Manager_RegisterCache( FTC_Manager manager,+ FTC_CacheClass clazz,+ FTC_Cache *acache );++ /* */++#define FTC_SCALER_COMPARE( a, b ) \+ ( (a)->face_id == (b)->face_id && \+ (a)->width == (b)->width && \+ (a)->height == (b)->height && \+ ((a)->pixel != 0) == ((b)->pixel != 0) && \+ ( (a)->pixel || \+ ( (a)->x_res == (b)->x_res && \+ (a)->y_res == (b)->y_res ) ) )++#define FTC_SCALER_HASH( q ) \+ ( _FTC_FACE_ID_HASH( (q)->face_id ) + \+ (q)->width + (q)->height*7 + \+ ( (q)->pixel ? 0 : ( (q)->x_res*33 ^ (q)->y_res*61 ) ) )++ /* */++FT_END_HEADER++#endif /* __FTCMANAG_H__ */+++/* END */
+ src/cache/ftcmru.c view
@@ -0,0 +1,357 @@+/***************************************************************************/+/* */+/* ftcmru.c */+/* */+/* FreeType MRU support (body). */+/* */+/* Copyright 2003, 2004, 2006, 2009 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 "ftcmru.h"+#include FT_INTERNAL_OBJECTS_H+#include FT_INTERNAL_DEBUG_H++#include "ftcerror.h"+++ FT_LOCAL_DEF( void )+ FTC_MruNode_Prepend( FTC_MruNode *plist,+ FTC_MruNode node )+ {+ FTC_MruNode first = *plist;+++ if ( first )+ {+ FTC_MruNode last = first->prev;+++#ifdef FT_DEBUG_ERROR+ {+ FTC_MruNode cnode = first;+++ do+ {+ if ( cnode == node )+ {+ fprintf( stderr, "FTC_MruNode_Prepend: invalid action\n" );+ exit( 2 );+ }+ cnode = cnode->next;++ } while ( cnode != first );+ }+#endif++ first->prev = node;+ last->next = node;+ node->next = first;+ node->prev = last;+ }+ else+ {+ node->next = node;+ node->prev = node;+ }+ *plist = node;+ }+++ FT_LOCAL_DEF( void )+ FTC_MruNode_Up( FTC_MruNode *plist,+ FTC_MruNode node )+ {+ FTC_MruNode first = *plist;+++ FT_ASSERT( first != NULL );++ if ( first != node )+ {+ FTC_MruNode prev, next, last;+++#ifdef FT_DEBUG_ERROR+ {+ FTC_MruNode cnode = first;+ do+ {+ if ( cnode == node )+ goto Ok;+ cnode = cnode->next;++ } while ( cnode != first );++ fprintf( stderr, "FTC_MruNode_Up: invalid action\n" );+ exit( 2 );+ Ok:+ }+#endif+ prev = node->prev;+ next = node->next;++ prev->next = next;+ next->prev = prev;++ last = first->prev;++ last->next = node;+ first->prev = node;++ node->next = first;+ node->prev = last;++ *plist = node;+ }+ }+++ FT_LOCAL_DEF( void )+ FTC_MruNode_Remove( FTC_MruNode *plist,+ FTC_MruNode node )+ {+ FTC_MruNode first = *plist;+ FTC_MruNode prev, next;+++ FT_ASSERT( first != NULL );++#ifdef FT_DEBUG_ERROR+ {+ FTC_MruNode cnode = first;+++ do+ {+ if ( cnode == node )+ goto Ok;+ cnode = cnode->next;++ } while ( cnode != first );++ fprintf( stderr, "FTC_MruNode_Remove: invalid action\n" );+ exit( 2 );+ Ok:+ }+#endif++ prev = node->prev;+ next = node->next;++ prev->next = next;+ next->prev = prev;++ if ( node == next )+ {+ FT_ASSERT( first == node );+ FT_ASSERT( prev == node );++ *plist = NULL;+ }+ else if ( node == first )+ *plist = next;+ }+++ FT_LOCAL_DEF( void )+ FTC_MruList_Init( FTC_MruList list,+ FTC_MruListClass clazz,+ FT_UInt max_nodes,+ FT_Pointer data,+ FT_Memory memory )+ {+ list->num_nodes = 0;+ list->max_nodes = max_nodes;+ list->nodes = NULL;+ list->clazz = *clazz;+ list->data = data;+ list->memory = memory;+ }+++ FT_LOCAL_DEF( void )+ FTC_MruList_Reset( FTC_MruList list )+ {+ while ( list->nodes )+ FTC_MruList_Remove( list, list->nodes );++ FT_ASSERT( list->num_nodes == 0 );+ }+++ FT_LOCAL_DEF( void )+ FTC_MruList_Done( FTC_MruList list )+ {+ FTC_MruList_Reset( list );+ }+++#ifndef FTC_INLINE+ FT_LOCAL_DEF( FTC_MruNode )+ FTC_MruList_Find( FTC_MruList list,+ FT_Pointer key )+ {+ FTC_MruNode_CompareFunc compare = list->clazz.node_compare;+ FTC_MruNode first, node;+++ first = list->nodes;+ node = NULL;++ if ( first )+ {+ node = first;+ do+ {+ if ( compare( node, key ) )+ {+ if ( node != first )+ FTC_MruNode_Up( &list->nodes, node );++ return node;+ }++ node = node->next;++ } while ( node != first);+ }++ return NULL;+ }+#endif++ FT_LOCAL_DEF( FT_Error )+ FTC_MruList_New( FTC_MruList list,+ FT_Pointer key,+ FTC_MruNode *anode )+ {+ FT_Error error;+ FTC_MruNode node;+ FT_Memory memory = list->memory;+++ if ( list->num_nodes >= list->max_nodes && list->max_nodes > 0 )+ {+ node = list->nodes->prev;++ FT_ASSERT( node );++ if ( list->clazz.node_reset )+ {+ FTC_MruNode_Up( &list->nodes, node );++ error = list->clazz.node_reset( node, key, list->data );+ if ( !error )+ goto Exit;+ }++ FTC_MruNode_Remove( &list->nodes, node );+ list->num_nodes--;++ if ( list->clazz.node_done )+ list->clazz.node_done( node, list->data );+ }+ else if ( FT_ALLOC( node, list->clazz.node_size ) )+ goto Exit;++ error = list->clazz.node_init( node, key, list->data );+ if ( error )+ goto Fail;++ FTC_MruNode_Prepend( &list->nodes, node );+ list->num_nodes++;++ Exit:+ *anode = node;+ return error;++ Fail:+ if ( list->clazz.node_done )+ list->clazz.node_done( node, list->data );++ FT_FREE( node );+ goto Exit;+ }+++#ifndef FTC_INLINE+ FT_LOCAL_DEF( FT_Error )+ FTC_MruList_Lookup( FTC_MruList list,+ FT_Pointer key,+ FTC_MruNode *anode )+ {+ FTC_MruNode node;+++ node = FTC_MruList_Find( list, key );+ if ( node == NULL )+ return FTC_MruList_New( list, key, anode );++ *anode = node;+ return 0;+ }+#endif /* FTC_INLINE */++ FT_LOCAL_DEF( void )+ FTC_MruList_Remove( FTC_MruList list,+ FTC_MruNode node )+ {+ FTC_MruNode_Remove( &list->nodes, node );+ list->num_nodes--;++ {+ FT_Memory memory = list->memory;+++ if ( list->clazz.node_done )+ list->clazz.node_done( node, list->data );++ FT_FREE( node );+ }+ }+++ FT_LOCAL_DEF( void )+ FTC_MruList_RemoveSelection( FTC_MruList list,+ FTC_MruNode_CompareFunc selection,+ FT_Pointer key )+ {+ FTC_MruNode first, node, next;+++ first = list->nodes;+ while ( first && ( selection == NULL || selection( first, key ) ) )+ {+ FTC_MruList_Remove( list, first );+ first = list->nodes;+ }++ if ( first )+ {+ node = first->next;+ while ( node != first )+ {+ next = node->next;++ if ( selection( node, key ) )+ FTC_MruList_Remove( list, node );++ node = next;+ }+ }+ }+++/* END */
+ src/cache/ftcmru.h view
@@ -0,0 +1,246 @@+/***************************************************************************/+/* */+/* ftcmru.h */+/* */+/* Simple MRU list-cache (specification). */+/* */+/* Copyright 2000-2001, 2003, 2004, 2005, 2006, 2010 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 = FTC_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 */
+ src/cache/ftcsbits.c view
@@ -0,0 +1,408 @@+/***************************************************************************/+/* */+/* ftcsbits.c */+/* */+/* FreeType sbits manager (body). */+/* */+/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2009, 2010 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 "ftcsbits.h"+#include FT_INTERNAL_OBJECTS_H+#include FT_INTERNAL_DEBUG_H+#include FT_ERRORS_H++#include "ftccback.h"+#include "ftcerror.h"++#undef FT_COMPONENT+#define FT_COMPONENT trace_cache+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** SBIT CACHE NODES *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+++ static FT_Error+ ftc_sbit_copy_bitmap( FTC_SBit sbit,+ FT_Bitmap* bitmap,+ FT_Memory memory )+ {+ FT_Error error;+ FT_Int pitch = bitmap->pitch;+ FT_ULong size;+++ if ( pitch < 0 )+ pitch = -pitch;++ size = (FT_ULong)( pitch * bitmap->rows );++ if ( !FT_ALLOC( sbit->buffer, size ) )+ FT_MEM_COPY( sbit->buffer, bitmap->buffer, size );++ return error;+ }+++ FT_LOCAL_DEF( void )+ ftc_snode_free( FTC_Node ftcsnode,+ FTC_Cache cache )+ {+ FTC_SNode snode = (FTC_SNode)ftcsnode;+ FTC_SBit sbit = snode->sbits;+ FT_UInt count = snode->count;+ FT_Memory memory = cache->memory;+++ for ( ; count > 0; sbit++, count-- )+ FT_FREE( sbit->buffer );++ FTC_GNode_Done( FTC_GNODE( snode ), cache );++ FT_FREE( snode );+ }+++ FT_LOCAL_DEF( void )+ FTC_SNode_Free( FTC_SNode snode,+ FTC_Cache cache )+ {+ ftc_snode_free( FTC_NODE( snode ), cache );+ }+++ /*+ * This function tries to load a small bitmap within a given FTC_SNode.+ * Note that it returns a non-zero error code _only_ in the case of+ * out-of-memory condition. For all other errors (e.g., corresponding+ * to a bad font file), this function will mark the sbit as `unavailable'+ * and return a value of 0.+ *+ * You should also read the comment within the @ftc_snode_compare+ * function below to see how out-of-memory is handled during a lookup.+ */+ static FT_Error+ ftc_snode_load( FTC_SNode snode,+ FTC_Manager manager,+ FT_UInt gindex,+ FT_ULong *asize )+ {+ FT_Error error;+ FTC_GNode gnode = FTC_GNODE( snode );+ FTC_Family family = gnode->family;+ FT_Memory memory = manager->memory;+ FT_Face face;+ FTC_SBit sbit;+ FTC_SFamilyClass clazz;+++ if ( (FT_UInt)(gindex - gnode->gindex) >= snode->count )+ {+ FT_ERROR(( "ftc_snode_load: invalid glyph index" ));+ return FTC_Err_Invalid_Argument;+ }++ sbit = snode->sbits + ( gindex - gnode->gindex );+ clazz = (FTC_SFamilyClass)family->clazz;++ sbit->buffer = 0;++ error = clazz->family_load_glyph( family, gindex, manager, &face );+ if ( error )+ goto BadGlyph;++ {+ FT_Int temp;+ FT_GlyphSlot slot = face->glyph;+ FT_Bitmap* bitmap = &slot->bitmap;+ FT_Pos xadvance, yadvance; /* FT_GlyphSlot->advance.{x|y} */+++ if ( slot->format != FT_GLYPH_FORMAT_BITMAP )+ {+ FT_TRACE0(( "ftc_snode_load:"+ " glyph loaded didn't return a bitmap\n" ));+ goto BadGlyph;+ }++ /* Check that our values fit into 8-bit containers! */+ /* If this is not the case, our bitmap is too large */+ /* and we will leave it as `missing' with sbit.buffer = 0 */++#define CHECK_CHAR( d ) ( temp = (FT_Char)d, temp == d )+#define CHECK_BYTE( d ) ( temp = (FT_Byte)d, temp == d )++ /* horizontal advance in pixels */+ xadvance = ( slot->advance.x + 32 ) >> 6;+ yadvance = ( slot->advance.y + 32 ) >> 6;++ if ( !CHECK_BYTE( bitmap->rows ) ||+ !CHECK_BYTE( bitmap->width ) ||+ !CHECK_CHAR( bitmap->pitch ) ||+ !CHECK_CHAR( slot->bitmap_left ) ||+ !CHECK_CHAR( slot->bitmap_top ) ||+ !CHECK_CHAR( xadvance ) ||+ !CHECK_CHAR( yadvance ) )+ {+ FT_TRACE2(( "ftc_snode_load:"+ " glyph too large for small bitmap cache\n"));+ goto BadGlyph;+ }++ sbit->width = (FT_Byte)bitmap->width;+ sbit->height = (FT_Byte)bitmap->rows;+ sbit->pitch = (FT_Char)bitmap->pitch;+ sbit->left = (FT_Char)slot->bitmap_left;+ sbit->top = (FT_Char)slot->bitmap_top;+ sbit->xadvance = (FT_Char)xadvance;+ sbit->yadvance = (FT_Char)yadvance;+ sbit->format = (FT_Byte)bitmap->pixel_mode;+ sbit->max_grays = (FT_Byte)(bitmap->num_grays - 1);++ /* copy the bitmap into a new buffer -- ignore error */+ error = ftc_sbit_copy_bitmap( sbit, bitmap, memory );++ /* now, compute size */+ if ( asize )+ *asize = FT_ABS( sbit->pitch ) * sbit->height;++ } /* glyph loading successful */++ /* ignore the errors that might have occurred -- */+ /* we mark unloaded glyphs with `sbit.buffer == 0' */+ /* and `width == 255', `height == 0' */+ /* */+ if ( error && error != FTC_Err_Out_Of_Memory )+ {+ BadGlyph:+ sbit->width = 255;+ sbit->height = 0;+ sbit->buffer = NULL;+ error = FTC_Err_Ok;+ if ( asize )+ *asize = 0;+ }++ return error;+ }+++ FT_LOCAL_DEF( FT_Error )+ FTC_SNode_New( FTC_SNode *psnode,+ FTC_GQuery gquery,+ FTC_Cache cache )+ {+ FT_Memory memory = cache->memory;+ FT_Error error;+ FTC_SNode snode = NULL;+ FT_UInt gindex = gquery->gindex;+ FTC_Family family = gquery->family;++ FTC_SFamilyClass clazz = FTC_CACHE__SFAMILY_CLASS( cache );+ FT_UInt total;+++ total = clazz->family_get_count( family, cache->manager );+ if ( total == 0 || gindex >= total )+ {+ error = FTC_Err_Invalid_Argument;+ goto Exit;+ }++ if ( !FT_NEW( snode ) )+ {+ FT_UInt count, start;+++ start = gindex - ( gindex % FTC_SBIT_ITEMS_PER_NODE );+ count = total - start;+ if ( count > FTC_SBIT_ITEMS_PER_NODE )+ count = FTC_SBIT_ITEMS_PER_NODE;++ FTC_GNode_Init( FTC_GNODE( snode ), start, family );++ snode->count = count;++ error = ftc_snode_load( snode,+ cache->manager,+ gindex,+ NULL );+ if ( error )+ {+ FTC_SNode_Free( snode, cache );+ snode = NULL;+ }+ }++ Exit:+ *psnode = snode;+ return error;+ }+++ FT_LOCAL_DEF( FT_Error )+ ftc_snode_new( FTC_Node *ftcpsnode,+ FT_Pointer ftcgquery,+ FTC_Cache cache )+ {+ FTC_SNode *psnode = (FTC_SNode*)ftcpsnode;+ FTC_GQuery gquery = (FTC_GQuery)ftcgquery;+++ return FTC_SNode_New( psnode, gquery, cache );+ }+++ FT_LOCAL_DEF( FT_Offset )+ ftc_snode_weight( FTC_Node ftcsnode,+ FTC_Cache cache )+ {+ FTC_SNode snode = (FTC_SNode)ftcsnode;+ FT_UInt count = snode->count;+ FTC_SBit sbit = snode->sbits;+ FT_Int pitch;+ FT_Offset size;++ FT_UNUSED( cache );+++ FT_ASSERT( snode->count <= FTC_SBIT_ITEMS_PER_NODE );++ /* the node itself */+ size = sizeof ( *snode );++ for ( ; count > 0; count--, sbit++ )+ {+ if ( sbit->buffer )+ {+ pitch = sbit->pitch;+ if ( pitch < 0 )+ pitch = -pitch;++ /* add the size of a given glyph image */+ size += pitch * sbit->height;+ }+ }++ return size;+ }+++#if 0++ FT_LOCAL_DEF( FT_Offset )+ FTC_SNode_Weight( FTC_SNode snode )+ {+ return ftc_snode_weight( FTC_NODE( snode ), NULL );+ }++#endif /* 0 */+++ FT_LOCAL_DEF( FT_Bool )+ ftc_snode_compare( FTC_Node ftcsnode,+ FT_Pointer ftcgquery,+ FTC_Cache cache )+ {+ FTC_SNode snode = (FTC_SNode)ftcsnode;+ FTC_GQuery gquery = (FTC_GQuery)ftcgquery;+ FTC_GNode gnode = FTC_GNODE( snode );+ FT_UInt gindex = gquery->gindex;+ FT_Bool result;+++ result = FT_BOOL( gnode->family == gquery->family &&+ (FT_UInt)( gindex - gnode->gindex ) < snode->count );+ if ( result )+ {+ /* check if we need to load the glyph bitmap now */+ FTC_SBit sbit = snode->sbits + ( gindex - gnode->gindex );+++ /*+ * The following code illustrates what to do when you want to+ * perform operations that may fail within a lookup function.+ *+ * Here, we want to load a small bitmap on-demand; we thus+ * need to call the `ftc_snode_load' function which may return+ * a non-zero error code only when we are out of memory (OOM).+ *+ * The correct thing to do is to use @FTC_CACHE_TRYLOOP and+ * @FTC_CACHE_TRYLOOP_END in order to implement a retry loop+ * that is capable of flushing the cache incrementally when+ * an OOM errors occur.+ *+ * However, we need to `lock' the node before this operation to+ * prevent it from being flushed within the loop.+ *+ * When we exit the loop, we unlock the node, then check the `error'+ * variable. If it is non-zero, this means that the cache was+ * completely flushed and that no usable memory was found to load+ * the bitmap.+ *+ * We then prefer to return a value of 0 (i.e., NO MATCH). This+ * ensures that the caller will try to allocate a new node.+ * This operation consequently _fail_ and the lookup function+ * returns the appropriate OOM error code.+ *+ * Note that `buffer == NULL && width == 255' is a hack used to+ * tag `unavailable' bitmaps in the array. We should never try+ * to load these.+ *+ */++ if ( sbit->buffer == NULL && sbit->width != 255 )+ {+ FT_ULong size;+ FT_Error error;+++ ftcsnode->ref_count++; /* lock node to prevent flushing */+ /* in retry loop */++ FTC_CACHE_TRYLOOP( cache )+ {+ error = ftc_snode_load( snode, cache->manager, gindex, &size );+ }+ FTC_CACHE_TRYLOOP_END();++ ftcsnode->ref_count--; /* unlock the node */++ if ( error )+ result = 0;+ else+ cache->manager->cur_weight += size;+ }+ }++ return result;+ }+++ FT_LOCAL_DEF( FT_Bool )+ FTC_SNode_Compare( FTC_SNode snode,+ FTC_GQuery gquery,+ FTC_Cache cache )+ {+ return ftc_snode_compare( FTC_NODE( snode ), gquery, cache );+ }+++/* END */
+ src/cache/ftcsbits.h view
@@ -0,0 +1,98 @@+/***************************************************************************/+/* */+/* ftcsbits.h */+/* */+/* A small-bitmap cache (specification). */+/* */+/* Copyright 2000-2001, 2002, 2003, 2006 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#ifndef __FTCSBITS_H__+#define __FTCSBITS_H__+++#include <ft2build.h>+#include FT_CACHE_H+#include "ftcglyph.h"+++FT_BEGIN_HEADER++#define FTC_SBIT_ITEMS_PER_NODE 16++ typedef struct FTC_SNodeRec_+ {+ FTC_GNodeRec gnode;+ FT_UInt count;+ FTC_SBitRec sbits[FTC_SBIT_ITEMS_PER_NODE];++ } FTC_SNodeRec, *FTC_SNode;+++#define FTC_SNODE( x ) ( (FTC_SNode)( x ) )+#define FTC_SNODE_GINDEX( x ) FTC_GNODE( x )->gindex+#define FTC_SNODE_FAMILY( x ) FTC_GNODE( x )->family++ typedef FT_UInt+ (*FTC_SFamily_GetCountFunc)( FTC_Family family,+ FTC_Manager manager );++ typedef FT_Error+ (*FTC_SFamily_LoadGlyphFunc)( FTC_Family family,+ FT_UInt gindex,+ FTC_Manager manager,+ FT_Face *aface );++ typedef struct FTC_SFamilyClassRec_+ {+ FTC_MruListClassRec clazz;+ FTC_SFamily_GetCountFunc family_get_count;+ FTC_SFamily_LoadGlyphFunc family_load_glyph;++ } FTC_SFamilyClassRec;++ typedef const FTC_SFamilyClassRec* FTC_SFamilyClass;++#define FTC_SFAMILY_CLASS( x ) ((FTC_SFamilyClass)(x))++#define FTC_CACHE__SFAMILY_CLASS( x ) \+ FTC_SFAMILY_CLASS( FTC_CACHE__GCACHE_CLASS( x )->family_class )+++ FT_LOCAL( void )+ FTC_SNode_Free( FTC_SNode snode,+ FTC_Cache cache );++ FT_LOCAL( FT_Error )+ FTC_SNode_New( FTC_SNode *psnode,+ FTC_GQuery gquery,+ FTC_Cache cache );++#if 0+ FT_LOCAL( FT_ULong )+ FTC_SNode_Weight( FTC_SNode inode );+#endif+++ FT_LOCAL( FT_Bool )+ FTC_SNode_Compare( FTC_SNode snode,+ FTC_GQuery gquery,+ FTC_Cache cache );++ /* */++FT_END_HEADER++#endif /* __FTCSBITS_H__ */+++/* END */
+ src/cff/cff.c view
@@ -0,0 +1,30 @@+/***************************************************************************/+/* */+/* cff.c */+/* */+/* FreeType OpenType driver component (body only). */+/* */+/* Copyright 1996-2001, 2002 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 "cffpic.c"+#include "cffdrivr.c"+#include "cffparse.c"+#include "cffload.c"+#include "cffobjs.c"+#include "cffgload.c"+#include "cffcmap.c"++/* END */
+ src/cff/cffcmap.c view
@@ -0,0 +1,208 @@+/***************************************************************************/+/* */+/* cffcmap.c */+/* */+/* CFF character mapping table (cmap) support (body). */+/* */+/* Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2010 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 "cffcmap.h"+#include "cffload.h"++#include "cfferrs.h"+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** CFF STANDARD (AND EXPERT) ENCODING CMAPS *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ FT_CALLBACK_DEF( FT_Error )+ cff_cmap_encoding_init( CFF_CMapStd cmap )+ {+ TT_Face face = (TT_Face)FT_CMAP_FACE( cmap );+ CFF_Font cff = (CFF_Font)face->extra.data;+ CFF_Encoding encoding = &cff->encoding;+++ cmap->gids = encoding->codes;++ return 0;+ }+++ FT_CALLBACK_DEF( void )+ cff_cmap_encoding_done( CFF_CMapStd cmap )+ {+ cmap->gids = NULL;+ }+++ FT_CALLBACK_DEF( FT_UInt )+ cff_cmap_encoding_char_index( CFF_CMapStd cmap,+ FT_UInt32 char_code )+ {+ FT_UInt result = 0;+++ if ( char_code < 256 )+ result = cmap->gids[char_code];++ return result;+ }+++ FT_CALLBACK_DEF( FT_UInt32 )+ cff_cmap_encoding_char_next( CFF_CMapStd cmap,+ FT_UInt32 *pchar_code )+ {+ FT_UInt result = 0;+ FT_UInt32 char_code = *pchar_code;+++ *pchar_code = 0;++ if ( char_code < 255 )+ {+ FT_UInt code = (FT_UInt)(char_code + 1);+++ for (;;)+ {+ if ( code >= 256 )+ break;++ result = cmap->gids[code];+ if ( result != 0 )+ {+ *pchar_code = code;+ break;+ }++ code++;+ }+ }+ return result;+ }+++ FT_DEFINE_CMAP_CLASS(cff_cmap_encoding_class_rec,+ sizeof ( CFF_CMapStdRec ),++ (FT_CMap_InitFunc) cff_cmap_encoding_init,+ (FT_CMap_DoneFunc) cff_cmap_encoding_done,+ (FT_CMap_CharIndexFunc)cff_cmap_encoding_char_index,+ (FT_CMap_CharNextFunc) cff_cmap_encoding_char_next,++ NULL, NULL, NULL, NULL, NULL+ )+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** CFF SYNTHETIC UNICODE ENCODING CMAP *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ FT_CALLBACK_DEF( const char* )+ cff_sid_to_glyph_name( TT_Face face,+ FT_UInt idx )+ {+ CFF_Font cff = (CFF_Font)face->extra.data;+ CFF_Charset charset = &cff->charset;+ FT_UInt sid = charset->sids[idx];+++ return cff_index_get_sid_string( cff, sid );+ }+++ FT_CALLBACK_DEF( FT_Error )+ cff_cmap_unicode_init( PS_Unicodes unicodes )+ {+ TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes );+ FT_Memory memory = FT_FACE_MEMORY( face );+ CFF_Font cff = (CFF_Font)face->extra.data;+ CFF_Charset charset = &cff->charset;+ FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames;+++ /* can't build Unicode map for CID-keyed font */+ /* because we don't know glyph names. */+ if ( !charset->sids )+ return CFF_Err_No_Unicode_Glyph_Name;++ return psnames->unicodes_init( memory,+ unicodes,+ cff->num_glyphs,+ (PS_GetGlyphNameFunc)&cff_sid_to_glyph_name,+ (PS_FreeGlyphNameFunc)NULL,+ (FT_Pointer)face );+ }+++ FT_CALLBACK_DEF( void )+ cff_cmap_unicode_done( PS_Unicodes unicodes )+ {+ FT_Face face = FT_CMAP_FACE( unicodes );+ FT_Memory memory = FT_FACE_MEMORY( face );+++ FT_FREE( unicodes->maps );+ unicodes->num_maps = 0;+ }+++ FT_CALLBACK_DEF( FT_UInt )+ cff_cmap_unicode_char_index( PS_Unicodes unicodes,+ FT_UInt32 char_code )+ {+ TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes );+ CFF_Font cff = (CFF_Font)face->extra.data;+ FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames;+++ return psnames->unicodes_char_index( unicodes, char_code );+ }+++ FT_CALLBACK_DEF( FT_UInt32 )+ cff_cmap_unicode_char_next( PS_Unicodes unicodes,+ FT_UInt32 *pchar_code )+ {+ TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes );+ CFF_Font cff = (CFF_Font)face->extra.data;+ FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames;+++ return psnames->unicodes_char_next( unicodes, pchar_code );+ }+++ FT_DEFINE_CMAP_CLASS(cff_cmap_unicode_class_rec,+ sizeof ( PS_UnicodesRec ),++ (FT_CMap_InitFunc) cff_cmap_unicode_init,+ (FT_CMap_DoneFunc) cff_cmap_unicode_done,+ (FT_CMap_CharIndexFunc)cff_cmap_unicode_char_index,+ (FT_CMap_CharNextFunc) cff_cmap_unicode_char_next,++ NULL, NULL, NULL, NULL, NULL+ )++/* END */
+ src/cff/cffcmap.h view
@@ -0,0 +1,67 @@+/***************************************************************************/+/* */+/* cffcmap.h */+/* */+/* CFF character mapping table (cmap) support (specification). */+/* */+/* Copyright 2002, 2003, 2006 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 __CFFCMAP_H__+#define __CFFCMAP_H__++#include "cffobjs.h"++FT_BEGIN_HEADER+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** TYPE1 STANDARD (AND EXPERT) ENCODING CMAPS *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /* standard (and expert) encoding cmaps */+ typedef struct CFF_CMapStdRec_* CFF_CMapStd;++ typedef struct CFF_CMapStdRec_+ {+ FT_CMapRec cmap;+ FT_UShort* gids; /* up to 256 elements */++ } CFF_CMapStdRec;+++ FT_DECLARE_CMAP_CLASS(cff_cmap_encoding_class_rec)+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** CFF SYNTHETIC UNICODE ENCODING CMAP *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /* unicode (synthetic) cmaps */++ FT_DECLARE_CMAP_CLASS(cff_cmap_unicode_class_rec)+++FT_END_HEADER++#endif /* __CFFCMAP_H__ */+++/* END */
+ src/cff/cffdrivr.c view
@@ -0,0 +1,671 @@+/***************************************************************************/+/* */+/* cffdrivr.c */+/* */+/* OpenType font driver implementation (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */+/* 2010 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#include <ft2build.h>+#include FT_FREETYPE_H+#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_STREAM_H+#include FT_INTERNAL_SFNT_H+#include FT_SERVICE_CID_H+#include FT_SERVICE_POSTSCRIPT_INFO_H+#include FT_SERVICE_POSTSCRIPT_NAME_H+#include FT_SERVICE_TT_CMAP_H++#include "cffdrivr.h"+#include "cffgload.h"+#include "cffload.h"+#include "cffcmap.h"+#include "cffparse.h"++#include "cfferrs.h"+#include "cffpic.h"++#include FT_SERVICE_XFREE86_NAME_H+#include FT_SERVICE_GLYPH_DICT_H+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_cffdriver+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** ****/+ /**** F A C E S ****/+ /**** ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++#undef PAIR_TAG+#define PAIR_TAG( left, right ) ( ( (FT_ULong)left << 16 ) | \+ (FT_ULong)right )+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* cff_get_kerning */+ /* */+ /* <Description> */+ /* A driver method used to return the kerning vector between two */+ /* glyphs of the same face. */+ /* */+ /* <Input> */+ /* face :: A handle to the source face object. */+ /* */+ /* left_glyph :: The index of the left glyph in the kern pair. */+ /* */+ /* right_glyph :: The index of the right glyph in the kern pair. */+ /* */+ /* <Output> */+ /* kerning :: The kerning vector. This is in font units for */+ /* scalable formats, and in pixels for fixed-sizes */+ /* formats. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ /* <Note> */+ /* Only horizontal layouts (left-to-right & right-to-left) are */+ /* supported by this function. Other layouts, or more sophisticated */+ /* kernings, are out of scope of this method (the basic driver */+ /* interface is meant to be simple). */+ /* */+ /* They can be implemented by format-specific interfaces. */+ /* */+ FT_CALLBACK_DEF( FT_Error )+ cff_get_kerning( FT_Face ttface, /* TT_Face */+ FT_UInt left_glyph,+ FT_UInt right_glyph,+ FT_Vector* kerning )+ {+ TT_Face face = (TT_Face)ttface;+ SFNT_Service sfnt = (SFNT_Service)face->sfnt;+++ kerning->x = 0;+ kerning->y = 0;++ if ( sfnt )+ kerning->x = sfnt->get_kerning( face, left_glyph, right_glyph );++ return CFF_Err_Ok;+ }+++#undef PAIR_TAG+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Load_Glyph */+ /* */+ /* <Description> */+ /* A driver method used to load a glyph within a given glyph slot. */+ /* */+ /* <Input> */+ /* slot :: A handle to the target slot object where the glyph */+ /* will be loaded. */+ /* */+ /* size :: A handle to the source face size at which the glyph */+ /* must be scaled, loaded, etc. */+ /* */+ /* glyph_index :: The index of the glyph in the font file. */+ /* */+ /* load_flags :: A flag indicating what to load for this glyph. The */+ /* FT_LOAD_??? constants can be used to control the */+ /* glyph loading process (e.g., whether the outline */+ /* should be scaled, whether to load bitmaps or not, */+ /* whether to hint the outline, etc). */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_CALLBACK_DEF( FT_Error )+ Load_Glyph( FT_GlyphSlot cffslot, /* CFF_GlyphSlot */+ FT_Size cffsize, /* CFF_Size */+ FT_UInt glyph_index,+ FT_Int32 load_flags )+ {+ FT_Error error;+ CFF_GlyphSlot slot = (CFF_GlyphSlot)cffslot;+ CFF_Size size = (CFF_Size)cffsize;+++ if ( !slot )+ return CFF_Err_Invalid_Slot_Handle;++ /* check whether we want a scaled outline or bitmap */+ if ( !size )+ load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;++ /* reset the size object if necessary */+ if ( load_flags & FT_LOAD_NO_SCALE )+ size = NULL;++ if ( size )+ {+ /* these two objects must have the same parent */+ if ( cffsize->face != cffslot->face )+ return CFF_Err_Invalid_Face_Handle;+ }++ /* now load the glyph outline if necessary */+ error = cff_slot_load( slot, size, glyph_index, load_flags );++ /* force drop-out mode to 2 - irrelevant now */+ /* slot->outline.dropout_mode = 2; */++ return error;+ }+++ FT_CALLBACK_DEF( FT_Error )+ cff_get_advances( FT_Face face,+ FT_UInt start,+ FT_UInt count,+ FT_Int32 flags,+ FT_Fixed* advances )+ {+ FT_UInt nn;+ FT_Error error = CFF_Err_Ok;+ FT_GlyphSlot slot = face->glyph;+++ flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY;++ for ( nn = 0; nn < count; nn++ )+ {+ error = Load_Glyph( slot, face->size, start + nn, flags );+ if ( error )+ break;++ advances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT )+ ? slot->linearVertAdvance+ : slot->linearHoriAdvance;+ }++ return error;+ }+++ /*+ * GLYPH DICT SERVICE+ *+ */++ static FT_Error+ cff_get_glyph_name( CFF_Face face,+ FT_UInt glyph_index,+ FT_Pointer buffer,+ FT_UInt buffer_max )+ {+ CFF_Font font = (CFF_Font)face->extra.data;+ FT_String* gname;+ FT_UShort sid;+ FT_Error error;+++ if ( !font->psnames )+ {+ FT_ERROR(( "cff_get_glyph_name:"+ " cannot get glyph name from CFF & CEF fonts\n"+ " "+ " without the `PSNames' module\n" ));+ error = CFF_Err_Unknown_File_Format;+ goto Exit;+ }++ /* first, locate the sid in the charset table */+ sid = font->charset.sids[glyph_index];++ /* now, lookup the name itself */+ gname = cff_index_get_sid_string( font, sid );++ if ( gname )+ FT_STRCPYN( buffer, gname, buffer_max );++ error = CFF_Err_Ok;++ Exit:+ return error;+ }+++ static FT_UInt+ cff_get_name_index( CFF_Face face,+ FT_String* glyph_name )+ {+ CFF_Font cff;+ CFF_Charset charset;+ FT_Service_PsCMaps psnames;+ FT_String* name;+ FT_UShort sid;+ FT_UInt i;+++ cff = (CFF_FontRec *)face->extra.data;+ charset = &cff->charset;++ FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );+ if ( !psnames )+ return 0;++ for ( i = 0; i < cff->num_glyphs; i++ )+ {+ sid = charset->sids[i];++ if ( sid > 390 )+ name = cff_index_get_string( cff, sid - 391 );+ else+ name = (FT_String *)psnames->adobe_std_strings( sid );++ if ( !name )+ continue;++ if ( !ft_strcmp( glyph_name, name ) )+ return i;+ }++ return 0;+ }+++ FT_DEFINE_SERVICE_GLYPHDICTREC(cff_service_glyph_dict,+ (FT_GlyphDict_GetNameFunc) cff_get_glyph_name,+ (FT_GlyphDict_NameIndexFunc)cff_get_name_index+ )+++ /*+ * POSTSCRIPT INFO SERVICE+ *+ */++ static FT_Int+ cff_ps_has_glyph_names( FT_Face face )+ {+ return ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) > 0;+ }+++ static FT_Error+ cff_ps_get_font_info( CFF_Face face,+ PS_FontInfoRec* afont_info )+ {+ CFF_Font cff = (CFF_Font)face->extra.data;+ FT_Error error = CFF_Err_Ok;+++ if ( cff && cff->font_info == NULL )+ {+ CFF_FontRecDict dict = &cff->top_font.font_dict;+ PS_FontInfoRec *font_info;+ FT_Memory memory = face->root.memory;+++ if ( FT_ALLOC( font_info, sizeof ( *font_info ) ) )+ goto Fail;++ font_info->version = cff_index_get_sid_string( cff,+ dict->version );+ font_info->notice = cff_index_get_sid_string( cff,+ dict->notice );+ font_info->full_name = cff_index_get_sid_string( cff,+ dict->full_name );+ font_info->family_name = cff_index_get_sid_string( cff,+ dict->family_name );+ font_info->weight = cff_index_get_sid_string( cff,+ dict->weight );+ font_info->italic_angle = dict->italic_angle;+ font_info->is_fixed_pitch = dict->is_fixed_pitch;+ font_info->underline_position = (FT_Short)dict->underline_position;+ font_info->underline_thickness = (FT_Short)dict->underline_thickness;++ cff->font_info = font_info;+ }++ if ( cff )+ *afont_info = *cff->font_info;++ Fail:+ return error;+ }+++ 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 */+ )+++ /*+ * POSTSCRIPT NAME SERVICE+ *+ */++ static const char*+ cff_get_ps_name( CFF_Face face )+ {+ CFF_Font cff = (CFF_Font)face->extra.data;+++ return (const char*)cff->font_name;+ }+++ FT_DEFINE_SERVICE_PSFONTNAMEREC(cff_service_ps_name,+ (FT_PsName_GetFunc)cff_get_ps_name+ )+++ /*+ * TT CMAP INFO+ *+ * If the charmap is a synthetic Unicode encoding cmap or+ * a Type 1 standard (or expert) encoding cmap, hide TT CMAP INFO+ * service defined in SFNT module.+ *+ * Otherwise call the service function in the sfnt module.+ *+ */+ static FT_Error+ cff_get_cmap_info( FT_CharMap charmap,+ TT_CMapInfo *cmap_info )+ {+ FT_CMap cmap = FT_CMAP( charmap );+ FT_Error error = CFF_Err_Ok;+ FT_Face face = FT_CMAP_FACE( cmap );+ FT_Library library = FT_FACE_LIBRARY( face );+++ cmap_info->language = 0;+ cmap_info->format = 0;++ if ( cmap->clazz != &FT_CFF_CMAP_ENCODING_CLASS_REC_GET &&+ cmap->clazz != &FT_CFF_CMAP_UNICODE_CLASS_REC_GET )+ {+ FT_Module sfnt = FT_Get_Module( library, "sfnt" );+ FT_Service_TTCMaps service =+ (FT_Service_TTCMaps)ft_module_get_service( sfnt,+ FT_SERVICE_ID_TT_CMAP );+++ if ( service && service->get_cmap_info )+ error = service->get_cmap_info( charmap, cmap_info );+ }++ return error;+ }+++ FT_DEFINE_SERVICE_TTCMAPSREC(cff_service_get_cmap_info,+ (TT_CMap_Info_GetFunc)cff_get_cmap_info+ )+++ /*+ * CID INFO SERVICE+ *+ */+ static FT_Error+ cff_get_ros( CFF_Face face,+ const char* *registry,+ const char* *ordering,+ FT_Int *supplement )+ {+ FT_Error error = CFF_Err_Ok;+ CFF_Font cff = (CFF_Font)face->extra.data;+++ if ( cff )+ {+ CFF_FontRecDict dict = &cff->top_font.font_dict;+++ if ( dict->cid_registry == 0xFFFFU )+ {+ error = CFF_Err_Invalid_Argument;+ goto Fail;+ }++ if ( registry )+ {+ if ( cff->registry == NULL )+ cff->registry = cff_index_get_sid_string( cff,+ dict->cid_registry );+ *registry = cff->registry;+ }+ + if ( ordering )+ {+ if ( cff->ordering == NULL )+ cff->ordering = cff_index_get_sid_string( cff,+ dict->cid_ordering );+ *ordering = cff->ordering;+ }++ /*+ * XXX: According to Adobe TechNote #5176, the supplement in CFF+ * can be a real number. We truncate it to fit public API+ * since freetype-2.3.6.+ */+ if ( supplement )+ {+ if ( dict->cid_supplement < FT_INT_MIN ||+ dict->cid_supplement > FT_INT_MAX )+ FT_TRACE1(( "cff_get_ros: too large supplement %d is truncated\n",+ dict->cid_supplement ));+ *supplement = (FT_Int)dict->cid_supplement;+ }+ }+ + Fail:+ return error;+ }+++ static FT_Error+ cff_get_is_cid( CFF_Face face,+ FT_Bool *is_cid )+ {+ FT_Error error = CFF_Err_Ok;+ CFF_Font cff = (CFF_Font)face->extra.data;+++ *is_cid = 0;++ if ( cff )+ {+ CFF_FontRecDict dict = &cff->top_font.font_dict;+++ if ( dict->cid_registry != 0xFFFFU )+ *is_cid = 1;+ }++ return error;+ }+++ static FT_Error+ cff_get_cid_from_glyph_index( CFF_Face face,+ FT_UInt glyph_index,+ FT_UInt *cid )+ {+ FT_Error error = CFF_Err_Ok;+ CFF_Font cff;+++ cff = (CFF_Font)face->extra.data;++ if ( cff )+ {+ FT_UInt c;+ CFF_FontRecDict dict = &cff->top_font.font_dict;+++ if ( dict->cid_registry == 0xFFFFU )+ {+ error = CFF_Err_Invalid_Argument;+ goto Fail;+ }++ if ( glyph_index > cff->num_glyphs )+ {+ error = CFF_Err_Invalid_Argument;+ goto Fail;+ }++ c = cff->charset.sids[glyph_index];++ if ( cid )+ *cid = c;+ }++ Fail:+ return error;+ }+++ 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+ )+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** ****/+ /**** D R I V E R I N T E R F A C E ****/+ /**** ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES+ FT_DEFINE_SERVICEDESCREC6(cff_services,+ FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_CFF,+ FT_SERVICE_ID_POSTSCRIPT_INFO, &FT_CFF_SERVICE_PS_INFO_GET,+ FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &FT_CFF_SERVICE_PS_NAME_GET,+ FT_SERVICE_ID_GLYPH_DICT, &FT_CFF_SERVICE_GLYPH_DICT_GET,+ FT_SERVICE_ID_TT_CMAP, &FT_CFF_SERVICE_GET_CMAP_INFO_GET,+ FT_SERVICE_ID_CID, &FT_CFF_SERVICE_CID_INFO_GET+ )+#else+ FT_DEFINE_SERVICEDESCREC5(cff_services,+ FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_CFF,+ FT_SERVICE_ID_POSTSCRIPT_INFO, &FT_CFF_SERVICE_PS_INFO_GET,+ FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &FT_CFF_SERVICE_PS_NAME_GET,+ FT_SERVICE_ID_TT_CMAP, &FT_CFF_SERVICE_GET_CMAP_INFO_GET,+ FT_SERVICE_ID_CID, &FT_CFF_SERVICE_CID_INFO_GET+ )+#endif++ FT_CALLBACK_DEF( FT_Module_Interface )+ cff_get_interface( FT_Module driver, /* CFF_Driver */+ const char* module_interface )+ {+ FT_Module sfnt;+ FT_Module_Interface result;+++ result = ft_service_list_lookup( FT_CFF_SERVICES_GET, module_interface );+ if ( result != NULL )+ return result;++ if ( !driver )+ return NULL;++ /* we pass our request to the `sfnt' module */+ sfnt = FT_Get_Module( driver->library, "sfnt" );++ return sfnt ? sfnt->clazz->get_interface( sfnt, module_interface ) : 0;+ }+++ /* The FT_DriverInterface structure is defined in ftdriver.h. */++#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS+#define CFF_SIZE_SELECT cff_size_select+#else+#define CFF_SIZE_SELECT 0+#endif++ FT_DEFINE_DRIVER(cff_driver_class,+ FT_MODULE_FONT_DRIVER |+ FT_MODULE_DRIVER_SCALABLE |+ FT_MODULE_DRIVER_HAS_HINTER,++ sizeof( CFF_DriverRec ),+ "cff",+ 0x10000L,+ 0x20000L,++ 0, /* module-specific interface */++ cff_driver_init,+ cff_driver_done,+ cff_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,++ ft_stub_set_char_sizes, /* FT_CONFIG_OPTION_OLD_INTERNALS */+ ft_stub_set_pixel_sizes, /* FT_CONFIG_OPTION_OLD_INTERNALS */++ Load_Glyph,++ cff_get_kerning,+ 0, /* FT_Face_AttachFunc */+ cff_get_advances, /* FT_Face_GetAdvancesFunc */++ cff_size_request,++ CFF_SIZE_SELECT+ )+++/* END */
+ src/cff/cffdrivr.h view
@@ -0,0 +1,38 @@+/***************************************************************************/+/* */+/* cffdrivr.h */+/* */+/* High-level OpenType driver interface (specification). */+/* */+/* Copyright 1996-2001, 2002 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 __CFFDRIVER_H__+#define __CFFDRIVER_H__+++#include <ft2build.h>+#include FT_INTERNAL_DRIVER_H+++FT_BEGIN_HEADER+++ FT_DECLARE_DRIVER( cff_driver_class )+++FT_END_HEADER++#endif /* __CFFDRIVER_H__ */+++/* END */
+ src/cff/cfferrs.h view
@@ -0,0 +1,41 @@+/***************************************************************************/+/* */+/* cfferrs.h */+/* */+/* CFF error codes (specification only). */+/* */+/* Copyright 2001 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 CFF error enumeration constants. */+ /* */+ /*************************************************************************/++#ifndef __CFFERRS_H__+#define __CFFERRS_H__++#include FT_MODULE_ERRORS_H++#undef __FTERRORS_H__++#define FT_ERR_PREFIX CFF_Err_+#define FT_ERR_BASE FT_Mod_Err_CFF+++#include FT_ERRORS_H++#endif /* __CFFERRS_H__ */+++/* END */
+ src/cff/cffgload.c view
@@ -0,0 +1,2972 @@+/***************************************************************************/+/* */+/* cffgload.c */+/* */+/* OpenType Glyph Loader (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */+/* 2010 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_STREAM_H+#include FT_INTERNAL_SFNT_H+#include FT_OUTLINE_H++#include "cffobjs.h"+#include "cffload.h"+#include "cffgload.h"++#include "cfferrs.h"+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_cffgload+++ typedef enum CFF_Operator_+ {+ cff_op_unknown = 0,++ cff_op_rmoveto,+ cff_op_hmoveto,+ cff_op_vmoveto,++ cff_op_rlineto,+ cff_op_hlineto,+ cff_op_vlineto,++ cff_op_rrcurveto,+ cff_op_hhcurveto,+ cff_op_hvcurveto,+ cff_op_rcurveline,+ cff_op_rlinecurve,+ cff_op_vhcurveto,+ cff_op_vvcurveto,++ cff_op_flex,+ cff_op_hflex,+ cff_op_hflex1,+ cff_op_flex1,++ cff_op_endchar,++ cff_op_hstem,+ cff_op_vstem,+ cff_op_hstemhm,+ cff_op_vstemhm,++ cff_op_hintmask,+ cff_op_cntrmask,+ cff_op_dotsection, /* deprecated, acts as no-op */++ cff_op_abs,+ cff_op_add,+ cff_op_sub,+ cff_op_div,+ cff_op_neg,+ cff_op_random,+ cff_op_mul,+ cff_op_sqrt,++ cff_op_blend,++ cff_op_drop,+ cff_op_exch,+ cff_op_index,+ cff_op_roll,+ cff_op_dup,++ cff_op_put,+ cff_op_get,+ cff_op_store,+ cff_op_load,++ cff_op_and,+ cff_op_or,+ cff_op_not,+ cff_op_eq,+ cff_op_ifelse,++ cff_op_callsubr,+ cff_op_callgsubr,+ cff_op_return,++ /* Type 1 opcodes: invalid but seen in real life */+ cff_op_hsbw,+ cff_op_closepath,+ cff_op_callothersubr,+ cff_op_pop,+ cff_op_seac,+ cff_op_sbw,+ cff_op_setcurrentpoint,++ /* do not remove */+ cff_op_max++ } CFF_Operator;+++#define CFF_COUNT_CHECK_WIDTH 0x80+#define CFF_COUNT_EXACT 0x40+#define CFF_COUNT_CLEAR_STACK 0x20++ /* count values which have the `CFF_COUNT_CHECK_WIDTH' flag set are */+ /* used for checking the width and requested numbers of arguments */+ /* only; they are set to zero afterwards */++ /* the other two flags are informative only and unused currently */++ static const FT_Byte cff_argument_counts[] =+ {+ 0, /* unknown */++ 2 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, /* rmoveto */+ 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,+ 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,++ 0 | CFF_COUNT_CLEAR_STACK, /* rlineto */+ 0 | CFF_COUNT_CLEAR_STACK,+ 0 | CFF_COUNT_CLEAR_STACK,++ 0 | CFF_COUNT_CLEAR_STACK, /* rrcurveto */+ 0 | CFF_COUNT_CLEAR_STACK,+ 0 | CFF_COUNT_CLEAR_STACK,+ 0 | CFF_COUNT_CLEAR_STACK,+ 0 | CFF_COUNT_CLEAR_STACK,+ 0 | CFF_COUNT_CLEAR_STACK,+ 0 | CFF_COUNT_CLEAR_STACK,++ 13, /* flex */+ 7,+ 9,+ 11,++ 0 | CFF_COUNT_CHECK_WIDTH, /* endchar */++ 2 | CFF_COUNT_CHECK_WIDTH, /* hstem */+ 2 | CFF_COUNT_CHECK_WIDTH,+ 2 | CFF_COUNT_CHECK_WIDTH,+ 2 | CFF_COUNT_CHECK_WIDTH,++ 0 | CFF_COUNT_CHECK_WIDTH, /* hintmask */+ 0 | CFF_COUNT_CHECK_WIDTH, /* cntrmask */+ 0, /* dotsection */++ 1, /* abs */+ 2,+ 2,+ 2,+ 1,+ 0,+ 2,+ 1,++ 1, /* blend */++ 1, /* drop */+ 2,+ 1,+ 2,+ 1,++ 2, /* put */+ 1,+ 4,+ 3,++ 2, /* and */+ 2,+ 1,+ 2,+ 4,++ 1, /* callsubr */+ 1,+ 0,++ 2, /* hsbw */+ 0,+ 0,+ 0,+ 5, /* seac */+ 4, /* sbw */+ 2 /* setcurrentpoint */+ };+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /********** *********/+ /********** *********/+ /********** GENERIC CHARSTRING PARSING *********/+ /********** *********/+ /********** *********/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* cff_builder_init */+ /* */+ /* <Description> */+ /* Initializes a given glyph builder. */+ /* */+ /* <InOut> */+ /* builder :: A pointer to the glyph builder to initialize. */+ /* */+ /* <Input> */+ /* face :: The current face object. */+ /* */+ /* size :: The current size object. */+ /* */+ /* glyph :: The current glyph object. */+ /* */+ /* hinting :: Whether hinting is active. */+ /* */+ static void+ cff_builder_init( CFF_Builder* builder,+ TT_Face face,+ CFF_Size size,+ CFF_GlyphSlot glyph,+ FT_Bool hinting )+ {+ builder->path_begun = 0;+ builder->load_points = 1;++ builder->face = face;+ builder->glyph = glyph;+ builder->memory = face->root.memory;++ if ( glyph )+ {+ FT_GlyphLoader loader = glyph->root.internal->loader;+++ builder->loader = loader;+ builder->base = &loader->base.outline;+ builder->current = &loader->current.outline;+ FT_GlyphLoader_Rewind( loader );++ builder->hints_globals = 0;+ builder->hints_funcs = 0;++ if ( hinting && size )+ {+ CFF_Internal internal = (CFF_Internal)size->root.internal;+++ builder->hints_globals = (void *)internal->topfont;+ builder->hints_funcs = glyph->root.internal->glyph_hints;+ }+ }++ builder->pos_x = 0;+ builder->pos_y = 0;++ builder->left_bearing.x = 0;+ builder->left_bearing.y = 0;+ builder->advance.x = 0;+ builder->advance.y = 0;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* cff_builder_done */+ /* */+ /* <Description> */+ /* Finalizes a given glyph builder. Its contents can still be used */+ /* after the call, but the function saves important information */+ /* within the corresponding glyph slot. */+ /* */+ /* <Input> */+ /* builder :: A pointer to the glyph builder to finalize. */+ /* */+ static void+ cff_builder_done( CFF_Builder* builder )+ {+ CFF_GlyphSlot glyph = builder->glyph;+++ if ( glyph )+ glyph->root.outline = *builder->base;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* cff_compute_bias */+ /* */+ /* <Description> */+ /* Computes the bias value in dependence of the number of glyph */+ /* subroutines. */+ /* */+ /* <Input> */+ /* in_charstring_type :: The `CharstringType' value of the top DICT */+ /* dictionary. */+ /* */+ /* num_subrs :: The number of glyph subroutines. */+ /* */+ /* <Return> */+ /* The bias value. */+ static FT_Int+ cff_compute_bias( FT_Int in_charstring_type,+ FT_UInt num_subrs )+ {+ FT_Int result;+++ if ( in_charstring_type == 1 )+ result = 0;+ else if ( num_subrs < 1240 )+ result = 107;+ else if ( num_subrs < 33900U )+ result = 1131;+ else+ result = 32768U;++ return result;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* cff_decoder_init */+ /* */+ /* <Description> */+ /* Initializes a given glyph decoder. */+ /* */+ /* <InOut> */+ /* decoder :: A pointer to the glyph builder to initialize. */+ /* */+ /* <Input> */+ /* face :: The current face object. */+ /* */+ /* size :: The current size object. */+ /* */+ /* slot :: The current glyph object. */+ /* */+ /* hinting :: Whether hinting is active. */+ /* */+ /* hint_mode :: The hinting mode. */+ /* */+ FT_LOCAL_DEF( void )+ cff_decoder_init( CFF_Decoder* decoder,+ TT_Face face,+ CFF_Size size,+ CFF_GlyphSlot slot,+ FT_Bool hinting,+ FT_Render_Mode hint_mode )+ {+ CFF_Font cff = (CFF_Font)face->extra.data;+++ /* clear everything */+ FT_MEM_ZERO( decoder, sizeof ( *decoder ) );++ /* initialize builder */+ cff_builder_init( &decoder->builder, face, size, slot, hinting );++ /* initialize Type2 decoder */+ decoder->cff = cff;+ decoder->num_globals = cff->global_subrs_index.count;+ decoder->globals = cff->global_subrs;+ decoder->globals_bias = cff_compute_bias(+ cff->top_font.font_dict.charstring_type,+ decoder->num_globals );++ decoder->hint_mode = hint_mode;+ }+++ /* this function is used to select the subfont */+ /* and the locals subrs array */+ FT_LOCAL_DEF( FT_Error )+ cff_decoder_prepare( CFF_Decoder* decoder,+ CFF_Size size,+ FT_UInt glyph_index )+ {+ CFF_Builder *builder = &decoder->builder;+ CFF_Font cff = (CFF_Font)builder->face->extra.data;+ CFF_SubFont sub = &cff->top_font;+ FT_Error error = CFF_Err_Ok;+++ /* manage CID fonts */+ if ( cff->num_subfonts )+ {+ FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, glyph_index );+++ if ( fd_index >= cff->num_subfonts )+ {+ FT_TRACE4(( "cff_decoder_prepare: invalid CID subfont index\n" ));+ error = CFF_Err_Invalid_File_Format;+ goto Exit;+ }++ FT_TRACE3(( "glyph index %d (subfont %d):\n", glyph_index, fd_index ));++ sub = cff->subfonts[fd_index];++ if ( builder->hints_funcs && size )+ {+ CFF_Internal internal = (CFF_Internal)size->root.internal;+++ /* for CFFs without subfonts, this value has already been set */+ builder->hints_globals = (void *)internal->subfonts[fd_index];+ }+ }+#ifdef FT_DEBUG_LEVEL_TRACE+ else+ FT_TRACE3(( "glyph index %d:\n", glyph_index ));+#endif++ decoder->num_locals = sub->local_subrs_index.count;+ decoder->locals = sub->local_subrs;+ decoder->locals_bias = cff_compute_bias(+ decoder->cff->top_font.font_dict.charstring_type,+ decoder->num_locals );++ decoder->glyph_width = sub->private_dict.default_width;+ decoder->nominal_width = sub->private_dict.nominal_width;++ Exit:+ return error;+ }+++ /* check that there is enough space for `count' more points */+ static FT_Error+ check_points( CFF_Builder* builder,+ FT_Int count )+ {+ return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );+ }+++ /* add a new point, do not check space */+ static void+ cff_builder_add_point( CFF_Builder* builder,+ FT_Pos x,+ FT_Pos y,+ FT_Byte flag )+ {+ FT_Outline* outline = builder->current;+++ if ( builder->load_points )+ {+ FT_Vector* point = outline->points + outline->n_points;+ FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;+++ point->x = x >> 16;+ point->y = y >> 16;+ *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );+ }++ outline->n_points++;+ }+++ /* check space for a new on-curve point, then add it */+ static FT_Error+ cff_builder_add_point1( CFF_Builder* builder,+ FT_Pos x,+ FT_Pos y )+ {+ FT_Error error;+++ error = check_points( builder, 1 );+ if ( !error )+ cff_builder_add_point( builder, x, y, 1 );++ return error;+ }+++ /* check space for a new contour, then add it */+ static FT_Error+ cff_builder_add_contour( CFF_Builder* builder )+ {+ FT_Outline* outline = builder->current;+ FT_Error error;+++ if ( !builder->load_points )+ {+ outline->n_contours++;+ return CFF_Err_Ok;+ }++ error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );+ if ( !error )+ {+ if ( outline->n_contours > 0 )+ outline->contours[outline->n_contours - 1] =+ (short)( outline->n_points - 1 );++ outline->n_contours++;+ }++ return error;+ }+++ /* if a path was begun, add its first on-curve point */+ static FT_Error+ cff_builder_start_point( CFF_Builder* builder,+ FT_Pos x,+ FT_Pos y )+ {+ FT_Error error = CFF_Err_Ok;+++ /* test whether we are building a new contour */+ if ( !builder->path_begun )+ {+ builder->path_begun = 1;+ error = cff_builder_add_contour( builder );+ if ( !error )+ error = cff_builder_add_point1( builder, x, y );+ }++ return error;+ }+++ /* close the current contour */+ static void+ cff_builder_close_contour( CFF_Builder* builder )+ {+ FT_Outline* outline = builder->current;+ FT_Int first;+++ if ( !outline )+ return;++ first = outline->n_contours <= 1+ ? 0 : outline->contours[outline->n_contours - 2] + 1;++ /* We must not include the last point in the path if it */+ /* is located on the first point. */+ if ( outline->n_points > 1 )+ {+ FT_Vector* p1 = outline->points + first;+ FT_Vector* p2 = outline->points + outline->n_points - 1;+ FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1;+++ /* `delete' last point only if it coincides with the first */+ /* point and if it is not a control point (which can happen). */+ if ( p1->x == p2->x && p1->y == p2->y )+ if ( *control == FT_CURVE_TAG_ON )+ outline->n_points--;+ }++ if ( outline->n_contours > 0 )+ {+ /* Don't add contours only consisting of one point, i.e., */+ /* check whether begin point and last point are the same. */+ if ( first == outline->n_points - 1 )+ {+ outline->n_contours--;+ outline->n_points--;+ }+ else+ outline->contours[outline->n_contours - 1] =+ (short)( outline->n_points - 1 );+ }+ }+++ static FT_Int+ cff_lookup_glyph_by_stdcharcode( CFF_Font cff,+ FT_Int charcode )+ {+ FT_UInt n;+ FT_UShort glyph_sid;+++ /* CID-keyed fonts don't have glyph names */+ if ( !cff->charset.sids )+ return -1;++ /* check range of standard char code */+ if ( charcode < 0 || charcode > 255 )+ return -1;++ /* Get code to SID mapping from `cff_standard_encoding'. */+ glyph_sid = cff_get_standard_encoding( (FT_UInt)charcode );++ for ( n = 0; n < cff->num_glyphs; n++ )+ {+ if ( cff->charset.sids[n] == glyph_sid )+ return n;+ }++ return -1;+ }+++ static FT_Error+ cff_get_glyph_data( TT_Face face,+ FT_UInt glyph_index,+ FT_Byte** pointer,+ FT_ULong* length )+ {+#ifdef FT_CONFIG_OPTION_INCREMENTAL+ /* For incremental fonts get the character data using the */+ /* callback function. */+ if ( face->root.internal->incremental_interface )+ {+ FT_Data data;+ FT_Error error =+ face->root.internal->incremental_interface->funcs->get_glyph_data(+ face->root.internal->incremental_interface->object,+ glyph_index, &data );+++ *pointer = (FT_Byte*)data.pointer;+ *length = data.length;++ return error;+ }+ else+#endif /* FT_CONFIG_OPTION_INCREMENTAL */++ {+ CFF_Font cff = (CFF_Font)(face->extra.data);+++ return cff_index_access_element( &cff->charstrings_index, glyph_index,+ pointer, length );+ }+ }+++ static void+ cff_free_glyph_data( TT_Face face,+ FT_Byte** pointer,+ FT_ULong length )+ {+#ifndef FT_CONFIG_OPTION_INCREMENTAL+ FT_UNUSED( length );+#endif++#ifdef FT_CONFIG_OPTION_INCREMENTAL+ /* For incremental fonts get the character data using the */+ /* callback function. */+ if ( face->root.internal->incremental_interface )+ {+ FT_Data data;+++ data.pointer = *pointer;+ data.length = length;++ face->root.internal->incremental_interface->funcs->free_glyph_data(+ face->root.internal->incremental_interface->object, &data );+ }+ else+#endif /* FT_CONFIG_OPTION_INCREMENTAL */++ {+ CFF_Font cff = (CFF_Font)(face->extra.data);+++ cff_index_forget_element( &cff->charstrings_index, pointer );+ }+ }+++ static FT_Error+ cff_operator_seac( CFF_Decoder* decoder,+ FT_Pos asb,+ FT_Pos adx,+ FT_Pos ady,+ FT_Int bchar,+ FT_Int achar )+ {+ FT_Error error;+ CFF_Builder* builder = &decoder->builder;+ FT_Int bchar_index, achar_index;+ TT_Face face = decoder->builder.face;+ FT_Vector left_bearing, advance;+ FT_Byte* charstring;+ FT_ULong charstring_len;+ FT_Pos glyph_width;+++ if ( decoder->seac )+ {+ FT_ERROR(( "cff_operator_seac: invalid nested seac\n" ));+ return CFF_Err_Syntax_Error;+ }++ adx += decoder->builder.left_bearing.x;+ ady += decoder->builder.left_bearing.y;++#ifdef FT_CONFIG_OPTION_INCREMENTAL+ /* Incremental fonts don't necessarily have valid charsets. */+ /* They use the character code, not the glyph index, in this case. */+ if ( face->root.internal->incremental_interface )+ {+ bchar_index = bchar;+ achar_index = achar;+ }+ else+#endif /* FT_CONFIG_OPTION_INCREMENTAL */+ {+ CFF_Font cff = (CFF_Font)(face->extra.data);+++ bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar );+ achar_index = cff_lookup_glyph_by_stdcharcode( cff, achar );+ }++ if ( bchar_index < 0 || achar_index < 0 )+ {+ FT_ERROR(( "cff_operator_seac:"+ " invalid seac character code arguments\n" ));+ return CFF_Err_Syntax_Error;+ }++ /* If we are trying to load a composite glyph, do not load the */+ /* accent character and return the array of subglyphs. */+ if ( builder->no_recurse )+ {+ FT_GlyphSlot glyph = (FT_GlyphSlot)builder->glyph;+ FT_GlyphLoader loader = glyph->internal->loader;+ FT_SubGlyph subg;+++ /* reallocate subglyph array if necessary */+ error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );+ if ( error )+ goto Exit;++ subg = loader->current.subglyphs;++ /* subglyph 0 = base character */+ subg->index = bchar_index;+ subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |+ FT_SUBGLYPH_FLAG_USE_MY_METRICS;+ subg->arg1 = 0;+ subg->arg2 = 0;+ subg++;++ /* subglyph 1 = accent character */+ subg->index = achar_index;+ subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;+ subg->arg1 = (FT_Int)( adx >> 16 );+ subg->arg2 = (FT_Int)( ady >> 16 );++ /* set up remaining glyph fields */+ glyph->num_subglyphs = 2;+ glyph->subglyphs = loader->base.subglyphs;+ glyph->format = FT_GLYPH_FORMAT_COMPOSITE;++ loader->current.num_subglyphs = 2;+ }++ FT_GlyphLoader_Prepare( builder->loader );++ /* First load `bchar' in builder */+ error = cff_get_glyph_data( face, bchar_index,+ &charstring, &charstring_len );+ if ( !error )+ {+ /* the seac operator must not be nested */+ decoder->seac = TRUE;+ error = cff_decoder_parse_charstrings( decoder, charstring,+ charstring_len );+ decoder->seac = FALSE;++ cff_free_glyph_data( face, &charstring, charstring_len );++ if ( error )+ goto Exit;+ }++ /* Save the left bearing, advance and glyph width of the base */+ /* character as they will be erased by the next load. */++ left_bearing = builder->left_bearing;+ advance = builder->advance;+ glyph_width = decoder->glyph_width;++ builder->left_bearing.x = 0;+ builder->left_bearing.y = 0;++ builder->pos_x = adx - asb;+ builder->pos_y = ady;++ /* Now load `achar' on top of the base outline. */+ error = cff_get_glyph_data( face, achar_index,+ &charstring, &charstring_len );+ if ( !error )+ {+ /* the seac operator must not be nested */+ decoder->seac = TRUE;+ error = cff_decoder_parse_charstrings( decoder, charstring,+ charstring_len );+ decoder->seac = FALSE;++ cff_free_glyph_data( face, &charstring, charstring_len );++ if ( error )+ goto Exit;+ }++ /* Restore the left side bearing, advance and glyph width */+ /* of the base character. */+ builder->left_bearing = left_bearing;+ builder->advance = advance;+ decoder->glyph_width = glyph_width;++ builder->pos_x = 0;+ builder->pos_y = 0;++ Exit:+ return error;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* cff_decoder_parse_charstrings */+ /* */+ /* <Description> */+ /* Parses a given Type 2 charstrings program. */+ /* */+ /* <InOut> */+ /* decoder :: The current Type 1 decoder. */+ /* */+ /* <Input> */+ /* charstring_base :: The base of the charstring stream. */+ /* */+ /* charstring_len :: The length in bytes of the charstring stream. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ cff_decoder_parse_charstrings( CFF_Decoder* decoder,+ FT_Byte* charstring_base,+ FT_ULong charstring_len )+ {+ FT_Error error;+ CFF_Decoder_Zone* zone;+ FT_Byte* ip;+ FT_Byte* limit;+ CFF_Builder* builder = &decoder->builder;+ FT_Pos x, y;+ FT_Fixed seed;+ FT_Fixed* stack;+ FT_Int charstring_type =+ decoder->cff->top_font.font_dict.charstring_type;++ T2_Hints_Funcs hinter;+++ /* set default width */+ decoder->num_hints = 0;+ decoder->read_width = 1;++ /* compute random seed from stack address of parameter */+ seed = (FT_Fixed)( ( (FT_PtrDist)(char*)&seed ^+ (FT_PtrDist)(char*)&decoder ^+ (FT_PtrDist)(char*)&charstring_base ) &+ FT_ULONG_MAX ) ;+ seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL;+ if ( seed == 0 )+ seed = 0x7384;++ /* initialize the decoder */+ decoder->top = decoder->stack;+ decoder->zone = decoder->zones;+ zone = decoder->zones;+ stack = decoder->top;++ hinter = (T2_Hints_Funcs)builder->hints_funcs;++ builder->path_begun = 0;++ zone->base = charstring_base;+ limit = zone->limit = charstring_base + charstring_len;+ ip = zone->cursor = zone->base;++ error = CFF_Err_Ok;++ x = builder->pos_x;+ y = builder->pos_y;++ /* begin hints recording session, if any */+ if ( hinter )+ hinter->open( hinter->hints );++ /* now execute loop */+ while ( ip < limit )+ {+ CFF_Operator op;+ FT_Byte v;+++ /********************************************************************/+ /* */+ /* Decode operator or operand */+ /* */+ v = *ip++;+ if ( v >= 32 || v == 28 )+ {+ FT_Int shift = 16;+ FT_Int32 val;+++ /* this is an operand, push it on the stack */+ if ( v == 28 )+ {+ if ( ip + 1 >= limit )+ goto Syntax_Error;+ val = (FT_Short)( ( (FT_Short)ip[0] << 8 ) | ip[1] );+ ip += 2;+ }+ else if ( v < 247 )+ val = (FT_Int32)v - 139;+ else if ( v < 251 )+ {+ if ( ip >= limit )+ goto Syntax_Error;+ val = ( (FT_Int32)v - 247 ) * 256 + *ip++ + 108;+ }+ else if ( v < 255 )+ {+ if ( ip >= limit )+ goto Syntax_Error;+ val = -( (FT_Int32)v - 251 ) * 256 - *ip++ - 108;+ }+ else+ {+ if ( ip + 3 >= limit )+ goto Syntax_Error;+ val = ( (FT_Int32)ip[0] << 24 ) |+ ( (FT_Int32)ip[1] << 16 ) |+ ( (FT_Int32)ip[2] << 8 ) |+ ip[3];+ ip += 4;+ if ( charstring_type == 2 )+ shift = 0;+ }+ if ( decoder->top - stack >= CFF_MAX_OPERANDS )+ goto Stack_Overflow;++ val <<= shift;+ *decoder->top++ = val;++#ifdef FT_DEBUG_LEVEL_TRACE+ if ( !( val & 0xFFFFL ) )+ FT_TRACE4(( " %ld", (FT_Int32)( val >> 16 ) ));+ else+ FT_TRACE4(( " %.2f", val / 65536.0 ));+#endif++ }+ else+ {+ /* The specification says that normally arguments are to be taken */+ /* from the bottom of the stack. However, this seems not to be */+ /* correct, at least for Acroread 7.0.8 on GNU/Linux: It pops the */+ /* arguments similar to a PS interpreter. */++ FT_Fixed* args = decoder->top;+ FT_Int num_args = (FT_Int)( args - decoder->stack );+ FT_Int req_args;+++ /* find operator */+ op = cff_op_unknown;++ switch ( v )+ {+ case 1:+ op = cff_op_hstem;+ break;+ case 3:+ op = cff_op_vstem;+ break;+ case 4:+ op = cff_op_vmoveto;+ break;+ case 5:+ op = cff_op_rlineto;+ break;+ case 6:+ op = cff_op_hlineto;+ break;+ case 7:+ op = cff_op_vlineto;+ break;+ case 8:+ op = cff_op_rrcurveto;+ break;+ case 9:+ op = cff_op_closepath;+ break;+ case 10:+ op = cff_op_callsubr;+ break;+ case 11:+ op = cff_op_return;+ break;+ case 12:+ {+ if ( ip >= limit )+ goto Syntax_Error;+ v = *ip++;++ switch ( v )+ {+ case 0:+ op = cff_op_dotsection;+ break;+ case 1: /* this is actually the Type1 vstem3 operator */+ op = cff_op_vstem;+ break;+ case 2: /* this is actually the Type1 hstem3 operator */+ op = cff_op_hstem;+ break;+ case 3:+ op = cff_op_and;+ break;+ case 4:+ op = cff_op_or;+ break;+ case 5:+ op = cff_op_not;+ break;+ case 6:+ op = cff_op_seac;+ break;+ case 7:+ op = cff_op_sbw;+ break;+ case 8:+ op = cff_op_store;+ break;+ case 9:+ op = cff_op_abs;+ break;+ case 10:+ op = cff_op_add;+ break;+ case 11:+ op = cff_op_sub;+ break;+ case 12:+ op = cff_op_div;+ break;+ case 13:+ op = cff_op_load;+ break;+ case 14:+ op = cff_op_neg;+ break;+ case 15:+ op = cff_op_eq;+ break;+ case 16:+ op = cff_op_callothersubr;+ break;+ case 17:+ op = cff_op_pop;+ break;+ case 18:+ op = cff_op_drop;+ break;+ case 20:+ op = cff_op_put;+ break;+ case 21:+ op = cff_op_get;+ break;+ case 22:+ op = cff_op_ifelse;+ break;+ case 23:+ op = cff_op_random;+ break;+ case 24:+ op = cff_op_mul;+ break;+ case 26:+ op = cff_op_sqrt;+ break;+ case 27:+ op = cff_op_dup;+ break;+ case 28:+ op = cff_op_exch;+ break;+ case 29:+ op = cff_op_index;+ break;+ case 30:+ op = cff_op_roll;+ break;+ case 33:+ op = cff_op_setcurrentpoint;+ break;+ case 34:+ op = cff_op_hflex;+ break;+ case 35:+ op = cff_op_flex;+ break;+ case 36:+ op = cff_op_hflex1;+ break;+ case 37:+ op = cff_op_flex1;+ break;+ default:+ /* decrement ip for syntax error message */+ ip--;+ }+ }+ break;+ case 13:+ op = cff_op_hsbw;+ break;+ case 14:+ op = cff_op_endchar;+ break;+ case 16:+ op = cff_op_blend;+ break;+ case 18:+ op = cff_op_hstemhm;+ break;+ case 19:+ op = cff_op_hintmask;+ break;+ case 20:+ op = cff_op_cntrmask;+ break;+ case 21:+ op = cff_op_rmoveto;+ break;+ case 22:+ op = cff_op_hmoveto;+ break;+ case 23:+ op = cff_op_vstemhm;+ break;+ case 24:+ op = cff_op_rcurveline;+ break;+ case 25:+ op = cff_op_rlinecurve;+ break;+ case 26:+ op = cff_op_vvcurveto;+ break;+ case 27:+ op = cff_op_hhcurveto;+ break;+ case 29:+ op = cff_op_callgsubr;+ break;+ case 30:+ op = cff_op_vhcurveto;+ break;+ case 31:+ op = cff_op_hvcurveto;+ break;+ default:+ break;+ }++ if ( op == cff_op_unknown )+ goto Syntax_Error;++ /* check arguments */+ req_args = cff_argument_counts[op];+ if ( req_args & CFF_COUNT_CHECK_WIDTH )+ {+ if ( num_args > 0 && decoder->read_width )+ {+ /* If `nominal_width' is non-zero, the number is really a */+ /* difference against `nominal_width'. Else, the number here */+ /* is truly a width, not a difference against `nominal_width'. */+ /* If the font does not set `nominal_width', then */+ /* `nominal_width' defaults to zero, and so we can set */+ /* `glyph_width' to `nominal_width' plus number on the stack */+ /* -- for either case. */++ FT_Int set_width_ok;+++ switch ( op )+ {+ case cff_op_hmoveto:+ case cff_op_vmoveto:+ set_width_ok = num_args & 2;+ break;++ case cff_op_hstem:+ case cff_op_vstem:+ case cff_op_hstemhm:+ case cff_op_vstemhm:+ case cff_op_rmoveto:+ case cff_op_hintmask:+ case cff_op_cntrmask:+ set_width_ok = num_args & 1;+ break;++ case cff_op_endchar:+ /* If there is a width specified for endchar, we either have */+ /* 1 argument or 5 arguments. We like to argue. */+ set_width_ok = ( num_args == 5 ) || ( num_args == 1 );+ break;++ default:+ set_width_ok = 0;+ break;+ }++ if ( set_width_ok )+ {+ decoder->glyph_width = decoder->nominal_width ++ ( stack[0] >> 16 );++ if ( decoder->width_only )+ {+ /* we only want the advance width; stop here */+ break;+ }++ /* Consumed an argument. */+ num_args--;+ }+ }++ decoder->read_width = 0;+ req_args = 0;+ }++ req_args &= 0x000F;+ if ( num_args < req_args )+ goto Stack_Underflow;+ args -= req_args;+ num_args -= req_args;++ /* At this point, `args' points to the first argument of the */+ /* operand in case `req_args' isn't zero. Otherwise, we have */+ /* to adjust `args' manually. */++ /* Note that we only pop arguments from the stack which we */+ /* really need and can digest so that we can continue in case */+ /* of superfluous stack elements. */++ switch ( op )+ {+ case cff_op_hstem:+ case cff_op_vstem:+ case cff_op_hstemhm:+ case cff_op_vstemhm:+ /* the number of arguments is always even here */+ FT_TRACE4((+ op == cff_op_hstem ? " hstem\n" :+ ( op == cff_op_vstem ? " vstem\n" :+ ( op == cff_op_hstemhm ? " hstemhm\n" : " vstemhm\n" ) ) ));++ if ( hinter )+ hinter->stems( hinter->hints,+ ( op == cff_op_hstem || op == cff_op_hstemhm ),+ num_args / 2,+ args - ( num_args & ~1 ) );++ decoder->num_hints += num_args / 2;+ args = stack;+ break;++ case cff_op_hintmask:+ case cff_op_cntrmask:+ FT_TRACE4(( op == cff_op_hintmask ? " hintmask" : " cntrmask" ));++ /* implement vstem when needed -- */+ /* the specification doesn't say it, but this also works */+ /* with the 'cntrmask' operator */+ /* */+ if ( num_args > 0 )+ {+ if ( hinter )+ hinter->stems( hinter->hints,+ 0,+ num_args / 2,+ args - ( num_args & ~1 ) );++ decoder->num_hints += num_args / 2;+ }++ /* In a valid charstring there must be at least one byte */+ /* after `hintmask' or `cntrmask' (e.g., for a `return' */+ /* instruction). Additionally, there must be space for */+ /* `num_hints' bits. */++ if ( ( ip + ( ( decoder->num_hints + 7 ) >> 3 ) ) >= limit )+ goto Syntax_Error;++ if ( hinter )+ {+ if ( op == cff_op_hintmask )+ hinter->hintmask( hinter->hints,+ builder->current->n_points,+ decoder->num_hints,+ ip );+ else+ hinter->counter( hinter->hints,+ decoder->num_hints,+ ip );+ }++#ifdef FT_DEBUG_LEVEL_TRACE+ {+ FT_UInt maskbyte;+++ FT_TRACE4(( " (maskbytes:" ));++ for ( maskbyte = 0;+ maskbyte < (FT_UInt)( ( decoder->num_hints + 7 ) >> 3 );+ maskbyte++, ip++ )+ FT_TRACE4(( " 0x%02X", *ip ));++ FT_TRACE4(( ")\n" ));+ }+#else+ ip += ( decoder->num_hints + 7 ) >> 3;+#endif+ args = stack;+ break;++ case cff_op_rmoveto:+ FT_TRACE4(( " rmoveto\n" ));++ cff_builder_close_contour( builder );+ builder->path_begun = 0;+ x += args[-2];+ y += args[-1];+ args = stack;+ break;++ case cff_op_vmoveto:+ FT_TRACE4(( " vmoveto\n" ));++ cff_builder_close_contour( builder );+ builder->path_begun = 0;+ y += args[-1];+ args = stack;+ break;++ case cff_op_hmoveto:+ FT_TRACE4(( " hmoveto\n" ));++ cff_builder_close_contour( builder );+ builder->path_begun = 0;+ x += args[-1];+ args = stack;+ break;++ case cff_op_rlineto:+ FT_TRACE4(( " rlineto\n" ));++ if ( cff_builder_start_point ( builder, x, y ) ||+ check_points( builder, num_args / 2 ) )+ goto Fail;++ if ( num_args < 2 )+ goto Stack_Underflow;++ args -= num_args & ~1;+ while ( args < decoder->top )+ {+ x += args[0];+ y += args[1];+ cff_builder_add_point( builder, x, y, 1 );+ args += 2;+ }+ args = stack;+ break;++ case cff_op_hlineto:+ case cff_op_vlineto:+ {+ FT_Int phase = ( op == cff_op_hlineto );+++ FT_TRACE4(( op == cff_op_hlineto ? " hlineto\n"+ : " vlineto\n" ));++ if ( num_args < 1 )+ goto Stack_Underflow;++ if ( cff_builder_start_point ( builder, x, y ) ||+ check_points( builder, num_args ) )+ goto Fail;++ args = stack;+ while ( args < decoder->top )+ {+ if ( phase )+ x += args[0];+ else+ y += args[0];++ if ( cff_builder_add_point1( builder, x, y ) )+ goto Fail;++ args++;+ phase ^= 1;+ }+ args = stack;+ }+ break;++ case cff_op_rrcurveto:+ {+ FT_Int nargs;+++ FT_TRACE4(( " rrcurveto\n" ));++ if ( num_args < 6 )+ goto Stack_Underflow;++ nargs = num_args - num_args % 6;++ if ( cff_builder_start_point ( builder, x, y ) ||+ check_points( builder, nargs / 2 ) )+ goto Fail;++ args -= nargs;+ while ( args < decoder->top )+ {+ x += args[0];+ y += args[1];+ cff_builder_add_point( builder, x, y, 0 );+ x += args[2];+ y += args[3];+ cff_builder_add_point( builder, x, y, 0 );+ x += args[4];+ y += args[5];+ cff_builder_add_point( builder, x, y, 1 );+ args += 6;+ }+ args = stack;+ }+ break;++ case cff_op_vvcurveto:+ {+ FT_Int nargs;+++ FT_TRACE4(( " vvcurveto\n" ));++ if ( num_args < 4 )+ goto Stack_Underflow;++ /* if num_args isn't of the form 4n or 4n+1, */+ /* we reduce it to 4n+1 */++ nargs = num_args - num_args % 4;+ if ( num_args - nargs > 0 )+ nargs += 1;++ if ( cff_builder_start_point( builder, x, y ) )+ goto Fail;++ args -= nargs;++ if ( nargs & 1 )+ {+ x += args[0];+ args++;+ nargs--;+ }++ if ( check_points( builder, 3 * ( nargs / 4 ) ) )+ goto Fail;++ while ( args < decoder->top )+ {+ y += args[0];+ cff_builder_add_point( builder, x, y, 0 );+ x += args[1];+ y += args[2];+ cff_builder_add_point( builder, x, y, 0 );+ y += args[3];+ cff_builder_add_point( builder, x, y, 1 );+ args += 4;+ }+ args = stack;+ }+ break;++ case cff_op_hhcurveto:+ {+ FT_Int nargs;+++ FT_TRACE4(( " hhcurveto\n" ));++ if ( num_args < 4 )+ goto Stack_Underflow;++ /* if num_args isn't of the form 4n or 4n+1, */+ /* we reduce it to 4n+1 */++ nargs = num_args - num_args % 4;+ if ( num_args - nargs > 0 )+ nargs += 1;++ if ( cff_builder_start_point( builder, x, y ) )+ goto Fail;++ args -= nargs;+ if ( nargs & 1 )+ {+ y += args[0];+ args++;+ nargs--;+ }++ if ( check_points( builder, 3 * ( nargs / 4 ) ) )+ goto Fail;++ while ( args < decoder->top )+ {+ x += args[0];+ cff_builder_add_point( builder, x, y, 0 );+ x += args[1];+ y += args[2];+ cff_builder_add_point( builder, x, y, 0 );+ x += args[3];+ cff_builder_add_point( builder, x, y, 1 );+ args += 4;+ }+ args = stack;+ }+ break;++ case cff_op_vhcurveto:+ case cff_op_hvcurveto:+ {+ FT_Int phase;+ FT_Int nargs;+++ FT_TRACE4(( op == cff_op_vhcurveto ? " vhcurveto\n"+ : " hvcurveto\n" ));++ if ( cff_builder_start_point( builder, x, y ) )+ goto Fail;++ if ( num_args < 4 )+ goto Stack_Underflow;++ /* if num_args isn't of the form 8n, 8n+1, 8n+4, or 8n+5, */+ /* we reduce it to the largest one which fits */++ nargs = num_args - num_args % 4;+ if ( num_args - nargs > 0 )+ nargs += 1;++ args -= nargs;+ if ( check_points( builder, ( nargs / 4 ) * 3 ) )+ goto Stack_Underflow;++ phase = ( op == cff_op_hvcurveto );++ while ( nargs >= 4 )+ {+ nargs -= 4;+ if ( phase )+ {+ x += args[0];+ cff_builder_add_point( builder, x, y, 0 );+ x += args[1];+ y += args[2];+ cff_builder_add_point( builder, x, y, 0 );+ y += args[3];+ if ( nargs == 1 )+ x += args[4];+ cff_builder_add_point( builder, x, y, 1 );+ }+ else+ {+ y += args[0];+ cff_builder_add_point( builder, x, y, 0 );+ x += args[1];+ y += args[2];+ cff_builder_add_point( builder, x, y, 0 );+ x += args[3];+ if ( nargs == 1 )+ y += args[4];+ cff_builder_add_point( builder, x, y, 1 );+ }+ args += 4;+ phase ^= 1;+ }+ args = stack;+ }+ break;++ case cff_op_rlinecurve:+ {+ FT_Int num_lines;+ FT_Int nargs;+++ FT_TRACE4(( " rlinecurve\n" ));++ if ( num_args < 8 )+ goto Stack_Underflow;++ nargs = num_args & ~1;+ num_lines = ( nargs - 6 ) / 2;++ if ( cff_builder_start_point( builder, x, y ) ||+ check_points( builder, num_lines + 3 ) )+ goto Fail;++ args -= nargs;++ /* first, add the line segments */+ while ( num_lines > 0 )+ {+ x += args[0];+ y += args[1];+ cff_builder_add_point( builder, x, y, 1 );+ args += 2;+ num_lines--;+ }++ /* then the curve */+ x += args[0];+ y += args[1];+ cff_builder_add_point( builder, x, y, 0 );+ x += args[2];+ y += args[3];+ cff_builder_add_point( builder, x, y, 0 );+ x += args[4];+ y += args[5];+ cff_builder_add_point( builder, x, y, 1 );+ args = stack;+ }+ break;++ case cff_op_rcurveline:+ {+ FT_Int num_curves;+ FT_Int nargs;+++ FT_TRACE4(( " rcurveline\n" ));++ if ( num_args < 8 )+ goto Stack_Underflow;++ nargs = num_args - 2;+ nargs = nargs - nargs % 6 + 2;+ num_curves = ( nargs - 2 ) / 6;++ if ( cff_builder_start_point ( builder, x, y ) ||+ check_points( builder, num_curves * 3 + 2 ) )+ goto Fail;++ args -= nargs;++ /* first, add the curves */+ while ( num_curves > 0 )+ {+ x += args[0];+ y += args[1];+ cff_builder_add_point( builder, x, y, 0 );+ x += args[2];+ y += args[3];+ cff_builder_add_point( builder, x, y, 0 );+ x += args[4];+ y += args[5];+ cff_builder_add_point( builder, x, y, 1 );+ args += 6;+ num_curves--;+ }++ /* then the final line */+ x += args[0];+ y += args[1];+ cff_builder_add_point( builder, x, y, 1 );+ args = stack;+ }+ break;++ case cff_op_hflex1:+ {+ FT_Pos start_y;+++ FT_TRACE4(( " hflex1\n" ));++ /* adding five more points: 4 control points, 1 on-curve point */+ /* -- make sure we have enough space for the start point if it */+ /* needs to be added */+ if ( cff_builder_start_point( builder, x, y ) ||+ check_points( builder, 6 ) )+ goto Fail;++ /* record the starting point's y position for later use */+ start_y = y;++ /* first control point */+ x += args[0];+ y += args[1];+ cff_builder_add_point( builder, x, y, 0 );++ /* second control point */+ x += args[2];+ y += args[3];+ cff_builder_add_point( builder, x, y, 0 );++ /* join point; on curve, with y-value the same as the last */+ /* control point's y-value */+ x += args[4];+ cff_builder_add_point( builder, x, y, 1 );++ /* third control point, with y-value the same as the join */+ /* point's y-value */+ x += args[5];+ cff_builder_add_point( builder, x, y, 0 );++ /* fourth control point */+ x += args[6];+ y += args[7];+ cff_builder_add_point( builder, x, y, 0 );++ /* ending point, with y-value the same as the start */+ x += args[8];+ y = start_y;+ cff_builder_add_point( builder, x, y, 1 );++ args = stack;+ break;+ }++ case cff_op_hflex:+ {+ FT_Pos start_y;+++ FT_TRACE4(( " hflex\n" ));++ /* adding six more points; 4 control points, 2 on-curve points */+ if ( cff_builder_start_point( builder, x, y ) ||+ check_points( builder, 6 ) )+ goto Fail;++ /* record the starting point's y-position for later use */+ start_y = y;++ /* first control point */+ x += args[0];+ cff_builder_add_point( builder, x, y, 0 );++ /* second control point */+ x += args[1];+ y += args[2];+ cff_builder_add_point( builder, x, y, 0 );++ /* join point; on curve, with y-value the same as the last */+ /* control point's y-value */+ x += args[3];+ cff_builder_add_point( builder, x, y, 1 );++ /* third control point, with y-value the same as the join */+ /* point's y-value */+ x += args[4];+ cff_builder_add_point( builder, x, y, 0 );++ /* fourth control point */+ x += args[5];+ y = start_y;+ cff_builder_add_point( builder, x, y, 0 );++ /* ending point, with y-value the same as the start point's */+ /* y-value -- we don't add this point, though */+ x += args[6];+ cff_builder_add_point( builder, x, y, 1 );++ args = stack;+ break;+ }++ case cff_op_flex1:+ {+ FT_Pos start_x, start_y; /* record start x, y values for */+ /* alter use */+ FT_Fixed dx = 0, dy = 0; /* used in horizontal/vertical */+ /* algorithm below */+ FT_Int horizontal, count;+ FT_Fixed* temp;+++ FT_TRACE4(( " flex1\n" ));++ /* adding six more points; 4 control points, 2 on-curve points */+ if ( cff_builder_start_point( builder, x, y ) ||+ check_points( builder, 6 ) )+ goto Fail;++ /* record the starting point's x, y position for later use */+ start_x = x;+ start_y = y;++ /* XXX: figure out whether this is supposed to be a horizontal */+ /* or vertical flex; the Type 2 specification is vague... */++ temp = args;++ /* grab up to the last argument */+ for ( count = 5; count > 0; count-- )+ {+ dx += temp[0];+ dy += temp[1];+ temp += 2;+ }++ if ( dx < 0 )+ dx = -dx;+ if ( dy < 0 )+ dy = -dy;++ /* strange test, but here it is... */+ horizontal = ( dx > dy );++ for ( count = 5; count > 0; count-- )+ {+ x += args[0];+ y += args[1];+ cff_builder_add_point( builder, x, y,+ (FT_Bool)( count == 3 ) );+ args += 2;+ }++ /* is last operand an x- or y-delta? */+ if ( horizontal )+ {+ x += args[0];+ y = start_y;+ }+ else+ {+ x = start_x;+ y += args[0];+ }++ cff_builder_add_point( builder, x, y, 1 );++ args = stack;+ break;+ }++ case cff_op_flex:+ {+ FT_UInt count;+++ FT_TRACE4(( " flex\n" ));++ if ( cff_builder_start_point( builder, x, y ) ||+ check_points( builder, 6 ) )+ goto Fail;++ for ( count = 6; count > 0; count-- )+ {+ x += args[0];+ y += args[1];+ cff_builder_add_point( builder, x, y,+ (FT_Bool)( count == 4 || count == 1 ) );+ args += 2;+ }++ args = stack;+ }+ break;++ case cff_op_seac:+ FT_TRACE4(( " seac\n" ));++ error = cff_operator_seac( decoder,+ args[0], args[1], args[2],+ (FT_Int)( args[3] >> 16 ),+ (FT_Int)( args[4] >> 16 ) );++ /* add current outline to the glyph slot */+ FT_GlyphLoader_Add( builder->loader );++ /* return now! */+ FT_TRACE4(( "\n" ));+ return error;++ case cff_op_endchar:+ FT_TRACE4(( " endchar\n" ));++ /* We are going to emulate the seac operator. */+ if ( num_args >= 4 )+ {+ /* Save glyph width so that the subglyphs don't overwrite it. */+ FT_Pos glyph_width = decoder->glyph_width;++ error = cff_operator_seac( decoder,+ 0L, args[-4], args[-3],+ (FT_Int)( args[-2] >> 16 ),+ (FT_Int)( args[-1] >> 16 ) );++ decoder->glyph_width = glyph_width;+ }+ else+ {+ if ( !error )+ error = CFF_Err_Ok;++ cff_builder_close_contour( builder );++ /* close hints recording session */+ if ( hinter )+ {+ if ( hinter->close( hinter->hints,+ builder->current->n_points ) )+ goto Syntax_Error;++ /* apply hints to the loaded glyph outline now */+ hinter->apply( hinter->hints,+ builder->current,+ (PSH_Globals)builder->hints_globals,+ decoder->hint_mode );+ }++ /* add current outline to the glyph slot */+ FT_GlyphLoader_Add( builder->loader );+ }++ /* return now! */+ FT_TRACE4(( "\n" ));+ return error;++ case cff_op_abs:+ FT_TRACE4(( " abs\n" ));++ if ( args[0] < 0 )+ args[0] = -args[0];+ args++;+ break;++ case cff_op_add:+ FT_TRACE4(( " add\n" ));++ args[0] += args[1];+ args++;+ break;++ case cff_op_sub:+ FT_TRACE4(( " sub\n" ));++ args[0] -= args[1];+ args++;+ break;++ case cff_op_div:+ FT_TRACE4(( " div\n" ));++ args[0] = FT_DivFix( args[0], args[1] );+ args++;+ break;++ case cff_op_neg:+ FT_TRACE4(( " neg\n" ));++ args[0] = -args[0];+ args++;+ break;++ case cff_op_random:+ {+ FT_Fixed Rand;+++ FT_TRACE4(( " rand\n" ));++ Rand = seed;+ if ( Rand >= 0x8000L )+ Rand++;++ args[0] = Rand;+ seed = FT_MulFix( seed, 0x10000L - seed );+ if ( seed == 0 )+ seed += 0x2873;+ args++;+ }+ break;++ case cff_op_mul:+ FT_TRACE4(( " mul\n" ));++ args[0] = FT_MulFix( args[0], args[1] );+ args++;+ break;++ case cff_op_sqrt:+ FT_TRACE4(( " sqrt\n" ));++ if ( args[0] > 0 )+ {+ FT_Int count = 9;+ FT_Fixed root = args[0];+ FT_Fixed new_root;+++ for (;;)+ {+ new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1;+ if ( new_root == root || count <= 0 )+ break;+ root = new_root;+ }+ args[0] = new_root;+ }+ else+ args[0] = 0;+ args++;+ break;++ case cff_op_drop:+ /* nothing */+ FT_TRACE4(( " drop\n" ));++ break;++ case cff_op_exch:+ {+ FT_Fixed tmp;+++ FT_TRACE4(( " exch\n" ));++ tmp = args[0];+ args[0] = args[1];+ args[1] = tmp;+ args += 2;+ }+ break;++ case cff_op_index:+ {+ FT_Int idx = (FT_Int)( args[0] >> 16 );+++ FT_TRACE4(( " index\n" ));++ if ( idx < 0 )+ idx = 0;+ else if ( idx > num_args - 2 )+ idx = num_args - 2;+ args[0] = args[-( idx + 1 )];+ args++;+ }+ break;++ case cff_op_roll:+ {+ FT_Int count = (FT_Int)( args[0] >> 16 );+ FT_Int idx = (FT_Int)( args[1] >> 16 );+++ FT_TRACE4(( " roll\n" ));++ if ( count <= 0 )+ count = 1;++ args -= count;+ if ( args < stack )+ goto Stack_Underflow;++ if ( idx >= 0 )+ {+ while ( idx > 0 )+ {+ FT_Fixed tmp = args[count - 1];+ FT_Int i;+++ for ( i = count - 2; i >= 0; i-- )+ args[i + 1] = args[i];+ args[0] = tmp;+ idx--;+ }+ }+ else+ {+ while ( idx < 0 )+ {+ FT_Fixed tmp = args[0];+ FT_Int i;+++ for ( i = 0; i < count - 1; i++ )+ args[i] = args[i + 1];+ args[count - 1] = tmp;+ idx++;+ }+ }+ args += count;+ }+ break;++ case cff_op_dup:+ FT_TRACE4(( " dup\n" ));++ args[1] = args[0];+ args += 2;+ break;++ case cff_op_put:+ {+ FT_Fixed val = args[0];+ FT_Int idx = (FT_Int)( args[1] >> 16 );+++ FT_TRACE4(( " put\n" ));++ if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS )+ decoder->buildchar[idx] = val;+ }+ break;++ case cff_op_get:+ {+ FT_Int idx = (FT_Int)( args[0] >> 16 );+ FT_Fixed val = 0;+++ FT_TRACE4(( " get\n" ));++ if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS )+ val = decoder->buildchar[idx];++ args[0] = val;+ args++;+ }+ break;++ case cff_op_store:+ FT_TRACE4(( " store\n"));++ goto Unimplemented;++ case cff_op_load:+ FT_TRACE4(( " load\n" ));++ goto Unimplemented;++ case cff_op_dotsection:+ /* this operator is deprecated and ignored by the parser */+ FT_TRACE4(( " dotsection\n" ));+ break;++ case cff_op_closepath:+ /* this is an invalid Type 2 operator; however, there */+ /* exist fonts which are incorrectly converted from probably */+ /* Type 1 to CFF, and some parsers seem to accept it */++ FT_TRACE4(( " closepath (invalid op)\n" ));++ args = stack;+ break;++ case cff_op_hsbw:+ /* this is an invalid Type 2 operator; however, there */+ /* exist fonts which are incorrectly converted from probably */+ /* Type 1 to CFF, and some parsers seem to accept it */++ FT_TRACE4(( " hsbw (invalid op)\n" ));++ decoder->glyph_width = decoder->nominal_width + ( args[1] >> 16 );++ decoder->builder.left_bearing.x = args[0];+ decoder->builder.left_bearing.y = 0;++ x = decoder->builder.pos_x + args[0];+ y = decoder->builder.pos_y;+ args = stack;+ break;++ case cff_op_sbw:+ /* this is an invalid Type 2 operator; however, there */+ /* exist fonts which are incorrectly converted from probably */+ /* Type 1 to CFF, and some parsers seem to accept it */++ FT_TRACE4(( " sbw (invalid op)\n" ));++ decoder->glyph_width = decoder->nominal_width + ( args[2] >> 16 );++ decoder->builder.left_bearing.x = args[0];+ decoder->builder.left_bearing.y = args[1];++ x = decoder->builder.pos_x + args[0];+ y = decoder->builder.pos_y + args[1];+ args = stack;+ break;++ case cff_op_setcurrentpoint:+ /* this is an invalid Type 2 operator; however, there */+ /* exist fonts which are incorrectly converted from probably */+ /* Type 1 to CFF, and some parsers seem to accept it */++ FT_TRACE4(( " setcurrentpoint (invalid op)\n" ));++ x = decoder->builder.pos_x + args[0];+ y = decoder->builder.pos_y + args[1];+ args = stack;+ break;++ case cff_op_callothersubr:+ /* this is an invalid Type 2 operator; however, there */+ /* exist fonts which are incorrectly converted from probably */+ /* Type 1 to CFF, and some parsers seem to accept it */++ FT_TRACE4(( " callothersubr (invalid op)\n" ));++ /* subsequent `pop' operands should add the arguments, */+ /* this is the implementation described for `unknown' other */+ /* subroutines in the Type1 spec. */+ /* */+ /* XXX Fix return arguments (see discussion below). */+ args -= 2 + ( args[-2] >> 16 );+ if ( args < stack )+ goto Stack_Underflow;+ break;++ case cff_op_pop:+ /* this is an invalid Type 2 operator; however, there */+ /* exist fonts which are incorrectly converted from probably */+ /* Type 1 to CFF, and some parsers seem to accept it */++ FT_TRACE4(( " pop (invalid op)\n" ));++ /* XXX Increasing `args' is wrong: After a certain number of */+ /* `pop's we get a stack overflow. Reason for doing it is */+ /* code like this (actually found in a CFF font): */+ /* */+ /* 17 1 3 callothersubr */+ /* pop */+ /* callsubr */+ /* */+ /* Since we handle `callothersubr' as a no-op, and */+ /* `callsubr' needs at least one argument, `pop' can't be a */+ /* no-op too as it basically should be. */+ /* */+ /* The right solution would be to provide real support for */+ /* `callothersubr' as done in `t1decode.c', however, given */+ /* the fact that CFF fonts with `pop' are invalid, it is */+ /* questionable whether it is worth the time. */+ args++;+ break;++ case cff_op_and:+ {+ FT_Fixed cond = args[0] && args[1];+++ FT_TRACE4(( " and\n" ));++ args[0] = cond ? 0x10000L : 0;+ args++;+ }+ break;++ case cff_op_or:+ {+ FT_Fixed cond = args[0] || args[1];+++ FT_TRACE4(( " or\n" ));++ args[0] = cond ? 0x10000L : 0;+ args++;+ }+ break;++ case cff_op_eq:+ {+ FT_Fixed cond = !args[0];+++ FT_TRACE4(( " eq\n" ));++ args[0] = cond ? 0x10000L : 0;+ args++;+ }+ break;++ case cff_op_ifelse:+ {+ FT_Fixed cond = ( args[2] <= args[3] );+++ FT_TRACE4(( " ifelse\n" ));++ if ( !cond )+ args[0] = args[1];+ args++;+ }+ break;++ case cff_op_callsubr:+ {+ FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) ++ decoder->locals_bias );+++ FT_TRACE4(( " callsubr(%d)\n", idx ));++ if ( idx >= decoder->num_locals )+ {+ FT_ERROR(( "cff_decoder_parse_charstrings:"+ " invalid local subr index\n" ));+ goto Syntax_Error;+ }++ if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )+ {+ FT_ERROR(( "cff_decoder_parse_charstrings:"+ " too many nested subrs\n" ));+ goto Syntax_Error;+ }++ zone->cursor = ip; /* save current instruction pointer */++ zone++;+ zone->base = decoder->locals[idx];+ zone->limit = decoder->locals[idx + 1];+ zone->cursor = zone->base;++ if ( !zone->base || zone->limit == zone->base )+ {+ FT_ERROR(( "cff_decoder_parse_charstrings:"+ " invoking empty subrs\n" ));+ goto Syntax_Error;+ }++ decoder->zone = zone;+ ip = zone->base;+ limit = zone->limit;+ }+ break;++ case cff_op_callgsubr:+ {+ FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) ++ decoder->globals_bias );+++ FT_TRACE4(( " callgsubr(%d)\n", idx ));++ if ( idx >= decoder->num_globals )+ {+ FT_ERROR(( "cff_decoder_parse_charstrings:"+ " invalid global subr index\n" ));+ goto Syntax_Error;+ }++ if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )+ {+ FT_ERROR(( "cff_decoder_parse_charstrings:"+ " too many nested subrs\n" ));+ goto Syntax_Error;+ }++ zone->cursor = ip; /* save current instruction pointer */++ zone++;+ zone->base = decoder->globals[idx];+ zone->limit = decoder->globals[idx + 1];+ zone->cursor = zone->base;++ if ( !zone->base || zone->limit == zone->base )+ {+ FT_ERROR(( "cff_decoder_parse_charstrings:"+ " invoking empty subrs\n" ));+ goto Syntax_Error;+ }++ decoder->zone = zone;+ ip = zone->base;+ limit = zone->limit;+ }+ break;++ case cff_op_return:+ FT_TRACE4(( " return\n" ));++ if ( decoder->zone <= decoder->zones )+ {+ FT_ERROR(( "cff_decoder_parse_charstrings:"+ " unexpected return\n" ));+ goto Syntax_Error;+ }++ decoder->zone--;+ zone = decoder->zone;+ ip = zone->cursor;+ limit = zone->limit;+ break;++ default:+ Unimplemented:+ FT_ERROR(( "Unimplemented opcode: %d", ip[-1] ));++ if ( ip[-1] == 12 )+ FT_ERROR(( " %d", ip[0] ));+ FT_ERROR(( "\n" ));++ return CFF_Err_Unimplemented_Feature;+ }++ decoder->top = args;++ if ( decoder->top - stack >= CFF_MAX_OPERANDS )+ goto Stack_Overflow;++ } /* general operator processing */++ } /* while ip < limit */++ FT_TRACE4(( "..end..\n\n" ));++ Fail:+ return error;++ Syntax_Error:+ FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error\n" ));+ return CFF_Err_Invalid_File_Format;++ Stack_Underflow:+ FT_TRACE4(( "cff_decoder_parse_charstrings: stack underflow\n" ));+ return CFF_Err_Too_Few_Arguments;++ Stack_Overflow:+ FT_TRACE4(( "cff_decoder_parse_charstrings: stack overflow\n" ));+ return CFF_Err_Stack_Overflow;+ }+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /********** *********/+ /********** *********/+ /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/+ /********** *********/+ /********** The following code is in charge of computing *********/+ /********** the maximum advance width of the font. It *********/+ /********** quickly processes each glyph charstring to *********/+ /********** extract the value from either a `sbw' or `seac' *********/+ /********** operator. *********/+ /********** *********/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++#if 0 /* unused until we support pure CFF fonts */+++ FT_LOCAL_DEF( FT_Error )+ cff_compute_max_advance( TT_Face face,+ FT_Int* max_advance )+ {+ FT_Error error = CFF_Err_Ok;+ CFF_Decoder decoder;+ FT_Int glyph_index;+ CFF_Font cff = (CFF_Font)face->other;+++ *max_advance = 0;++ /* Initialize load decoder */+ cff_decoder_init( &decoder, face, 0, 0, 0, 0 );++ decoder.builder.metrics_only = 1;+ decoder.builder.load_points = 0;++ /* For each glyph, parse the glyph charstring and extract */+ /* the advance width. */+ for ( glyph_index = 0; glyph_index < face->root.num_glyphs;+ glyph_index++ )+ {+ FT_Byte* charstring;+ FT_ULong charstring_len;+++ /* now get load the unscaled outline */+ error = cff_get_glyph_data( face, glyph_index,+ &charstring, &charstring_len );+ if ( !error )+ {+ error = cff_decoder_prepare( &decoder, size, glyph_index );+ if ( !error )+ error = cff_decoder_parse_charstrings( &decoder,+ charstring,+ charstring_len );++ cff_free_glyph_data( face, &charstring, &charstring_len );+ }++ /* ignore the error if one has occurred -- skip to next glyph */+ error = CFF_Err_Ok;+ }++ *max_advance = decoder.builder.advance.x;++ return CFF_Err_Ok;+ }+++#endif /* 0 */+++ FT_LOCAL_DEF( FT_Error )+ cff_slot_load( CFF_GlyphSlot glyph,+ CFF_Size size,+ FT_UInt glyph_index,+ FT_Int32 load_flags )+ {+ FT_Error error;+ CFF_Decoder decoder;+ TT_Face face = (TT_Face)glyph->root.face;+ FT_Bool hinting, force_scaling;+ CFF_Font cff = (CFF_Font)face->extra.data;++ FT_Matrix font_matrix;+ FT_Vector font_offset;+++ force_scaling = FALSE;++ /* in a CID-keyed font, consider `glyph_index' as a CID and map */+ /* it immediately to the real glyph_index -- if it isn't a */+ /* subsetted font, glyph_indices and CIDs are identical, though */+ if ( cff->top_font.font_dict.cid_registry != 0xFFFFU &&+ cff->charset.cids )+ {+ /* don't handle CID 0 (.notdef) which is directly mapped to GID 0 */+ if ( glyph_index != 0 )+ {+ glyph_index = cff_charset_cid_to_gindex( &cff->charset,+ glyph_index );+ if ( glyph_index == 0 )+ return CFF_Err_Invalid_Argument;+ }+ }+ else if ( glyph_index >= cff->num_glyphs )+ return CFF_Err_Invalid_Argument;++ if ( load_flags & FT_LOAD_NO_RECURSE )+ load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;++ glyph->x_scale = 0x10000L;+ glyph->y_scale = 0x10000L;+ if ( size )+ {+ glyph->x_scale = size->root.metrics.x_scale;+ glyph->y_scale = size->root.metrics.y_scale;+ }++#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS++ /* try to load embedded bitmap if any */+ /* */+ /* XXX: The convention should be emphasized in */+ /* the documents because it can be confusing. */+ if ( size )+ {+ CFF_Face cff_face = (CFF_Face)size->root.face;+ SFNT_Service sfnt = (SFNT_Service)cff_face->sfnt;+ FT_Stream stream = cff_face->root.stream;+++ if ( size->strike_index != 0xFFFFFFFFUL &&+ sfnt->load_eblc &&+ ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )+ {+ TT_SBit_MetricsRec metrics;+++ error = sfnt->load_sbit_image( face,+ size->strike_index,+ glyph_index,+ (FT_Int)load_flags,+ stream,+ &glyph->root.bitmap,+ &metrics );++ if ( !error )+ {+ glyph->root.outline.n_points = 0;+ glyph->root.outline.n_contours = 0;++ glyph->root.metrics.width = (FT_Pos)metrics.width << 6;+ glyph->root.metrics.height = (FT_Pos)metrics.height << 6;++ glyph->root.metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;+ glyph->root.metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;+ glyph->root.metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6;++ glyph->root.metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;+ glyph->root.metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;+ glyph->root.metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6;++ glyph->root.format = FT_GLYPH_FORMAT_BITMAP;++ if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )+ {+ glyph->root.bitmap_left = metrics.vertBearingX;+ glyph->root.bitmap_top = metrics.vertBearingY;+ }+ else+ {+ glyph->root.bitmap_left = metrics.horiBearingX;+ glyph->root.bitmap_top = metrics.horiBearingY;+ }+ return error;+ }+ }+ }++#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */++ /* return immediately if we only want the embedded bitmaps */+ if ( load_flags & FT_LOAD_SBITS_ONLY )+ return CFF_Err_Invalid_Argument;++ /* if we have a CID subfont, use its matrix (which has already */+ /* been multiplied with the root matrix) */++ /* this scaling is only relevant if the PS hinter isn't active */+ if ( cff->num_subfonts )+ {+ FT_ULong top_upm, sub_upm;+ FT_Byte fd_index = cff_fd_select_get( &cff->fd_select,+ glyph_index );++ if ( fd_index >= cff->num_subfonts ) + fd_index = cff->num_subfonts - 1;++ top_upm = cff->top_font.font_dict.units_per_em;+ sub_upm = cff->subfonts[fd_index]->font_dict.units_per_em;+++ font_matrix = cff->subfonts[fd_index]->font_dict.font_matrix;+ font_offset = cff->subfonts[fd_index]->font_dict.font_offset;++ if ( top_upm != sub_upm )+ {+ glyph->x_scale = FT_MulDiv( glyph->x_scale, top_upm, sub_upm );+ glyph->y_scale = FT_MulDiv( glyph->y_scale, top_upm, sub_upm );++ force_scaling = TRUE;+ }+ }+ else+ {+ font_matrix = cff->top_font.font_dict.font_matrix;+ font_offset = cff->top_font.font_dict.font_offset;+ }++ glyph->root.outline.n_points = 0;+ glyph->root.outline.n_contours = 0;++ hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 &&+ ( load_flags & FT_LOAD_NO_HINTING ) == 0 );++ glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; /* by default */++ {+ FT_Byte* charstring;+ FT_ULong charstring_len;+++ cff_decoder_init( &decoder, face, size, glyph, hinting,+ FT_LOAD_TARGET_MODE( load_flags ) );++ if ( load_flags & FT_LOAD_ADVANCE_ONLY )+ decoder.width_only = TRUE;++ decoder.builder.no_recurse =+ (FT_Bool)( load_flags & FT_LOAD_NO_RECURSE );++ /* now load the unscaled outline */+ error = cff_get_glyph_data( face, glyph_index,+ &charstring, &charstring_len );+ if ( error )+ goto Glyph_Build_Finished;++ error = cff_decoder_prepare( &decoder, size, glyph_index );+ if ( error )+ goto Glyph_Build_Finished;++ error = cff_decoder_parse_charstrings( &decoder,+ charstring,+ charstring_len );++ cff_free_glyph_data( face, &charstring, charstring_len );++ if ( error )+ goto Glyph_Build_Finished;++#ifdef FT_CONFIG_OPTION_INCREMENTAL+ /* Control data and length may not be available for incremental */+ /* fonts. */+ if ( face->root.internal->incremental_interface )+ {+ glyph->root.control_data = 0;+ glyph->root.control_len = 0;+ }+ else+#endif /* FT_CONFIG_OPTION_INCREMENTAL */++ /* We set control_data and control_len if charstrings is loaded. */+ /* See how charstring loads at cff_index_access_element() in */+ /* cffload.c. */+ {+ CFF_Index csindex = &cff->charstrings_index;+++ if ( csindex->offsets )+ {+ glyph->root.control_data = csindex->bytes ++ csindex->offsets[glyph_index] - 1;+ glyph->root.control_len = charstring_len;+ }+ }++ Glyph_Build_Finished:+ /* save new glyph tables, if no error */+ if ( !error )+ cff_builder_done( &decoder.builder );+ /* XXX: anything to do for broken glyph entry? */+ }++#ifdef FT_CONFIG_OPTION_INCREMENTAL++ /* Incremental fonts can optionally override the metrics. */+ if ( !error &&+ face->root.internal->incremental_interface &&+ face->root.internal->incremental_interface->funcs->get_glyph_metrics )+ {+ FT_Incremental_MetricsRec metrics;+++ metrics.bearing_x = decoder.builder.left_bearing.x;+ metrics.bearing_y = 0;+ metrics.advance = decoder.builder.advance.x;+ metrics.advance_v = decoder.builder.advance.y;++ error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(+ face->root.internal->incremental_interface->object,+ glyph_index, FALSE, &metrics );++ decoder.builder.left_bearing.x = metrics.bearing_x;+ decoder.builder.advance.x = metrics.advance;+ decoder.builder.advance.y = metrics.advance_v;+ }++#endif /* FT_CONFIG_OPTION_INCREMENTAL */++ if ( !error )+ {+ /* Now, set the metrics -- this is rather simple, as */+ /* the left side bearing is the xMin, and the top side */+ /* bearing the yMax. */++ /* For composite glyphs, return only left side bearing and */+ /* advance width. */+ if ( load_flags & FT_LOAD_NO_RECURSE )+ {+ FT_Slot_Internal internal = glyph->root.internal;+++ glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;+ glyph->root.metrics.horiAdvance = decoder.glyph_width;+ internal->glyph_matrix = font_matrix;+ internal->glyph_delta = font_offset;+ internal->glyph_transformed = 1;+ }+ else+ {+ FT_BBox cbox;+ FT_Glyph_Metrics* metrics = &glyph->root.metrics;+ FT_Vector advance;+ FT_Bool has_vertical_info;+++ /* copy the _unscaled_ advance width */+ metrics->horiAdvance = decoder.glyph_width;+ glyph->root.linearHoriAdvance = decoder.glyph_width;+ glyph->root.internal->glyph_transformed = 0;++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS+ has_vertical_info = FT_BOOL( face->vertical_info &&+ face->vertical.number_Of_VMetrics > 0 &&+ face->vertical.long_metrics );+#else+ has_vertical_info = FT_BOOL( face->vertical_info &&+ face->vertical.number_Of_VMetrics > 0 );+#endif++ /* get the vertical metrics from the vtmx table if we have one */+ if ( has_vertical_info )+ {+ FT_Short vertBearingY = 0;+ FT_UShort vertAdvance = 0;+++ ( (SFNT_Service)face->sfnt )->get_metrics( face, 1,+ glyph_index,+ &vertBearingY,+ &vertAdvance );+ metrics->vertBearingY = vertBearingY;+ metrics->vertAdvance = vertAdvance;+ }+ else+ {+ /* make up vertical ones */+ if ( face->os2.version != 0xFFFFU )+ metrics->vertAdvance = (FT_Pos)( face->os2.sTypoAscender -+ face->os2.sTypoDescender );+ else+ metrics->vertAdvance = (FT_Pos)( face->horizontal.Ascender -+ face->horizontal.Descender );+ }++ glyph->root.linearVertAdvance = metrics->vertAdvance;++ glyph->root.format = FT_GLYPH_FORMAT_OUTLINE;++ glyph->root.outline.flags = 0;+ if ( size && size->root.metrics.y_ppem < 24 )+ glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION;++ 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 ) )+ 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 );++ advance.x = metrics->horiAdvance;+ advance.y = 0;+ FT_Vector_Transform( &advance, &font_matrix );+ metrics->horiAdvance = advance.x + font_offset.x;++ advance.x = 0;+ advance.y = metrics->vertAdvance;+ FT_Vector_Transform( &advance, &font_matrix );+ metrics->vertAdvance = advance.y + font_offset.y;++ if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || force_scaling )+ {+ /* scale the outline and the metrics */+ FT_Int n;+ FT_Outline* cur = &glyph->root.outline;+ FT_Vector* vec = cur->points;+ FT_Fixed x_scale = glyph->x_scale;+ FT_Fixed y_scale = glyph->y_scale;+++ /* First of all, scale the points */+ if ( !hinting || !decoder.builder.hints_funcs )+ for ( n = cur->n_points; n > 0; n--, vec++ )+ {+ vec->x = FT_MulFix( vec->x, x_scale );+ vec->y = FT_MulFix( vec->y, y_scale );+ }++ /* Then scale the metrics */+ metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );+ metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );+ }++ /* compute the other metrics */+ FT_Outline_Get_CBox( &glyph->root.outline, &cbox );++ metrics->width = cbox.xMax - cbox.xMin;+ metrics->height = cbox.yMax - cbox.yMin;++ metrics->horiBearingX = cbox.xMin;+ metrics->horiBearingY = cbox.yMax;++ if ( has_vertical_info )+ metrics->vertBearingX = metrics->horiBearingX -+ metrics->horiAdvance / 2;+ else + {+ if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )+ ft_synthesize_vertical_metrics( metrics,+ metrics->vertAdvance );+ }+ }+ }++ return error;+ }+++/* END */
+ src/cff/cffgload.h view
@@ -0,0 +1,201 @@+/***************************************************************************/+/* */+/* cffgload.h */+/* */+/* OpenType Glyph Loader (specification). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009 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 __CFFGLOAD_H__+#define __CFFGLOAD_H__+++#include <ft2build.h>+#include FT_FREETYPE_H+#include "cffobjs.h"+++FT_BEGIN_HEADER+++#define CFF_MAX_OPERANDS 48+#define CFF_MAX_SUBRS_CALLS 32+#define CFF_MAX_TRANS_ELEMENTS 32+++ /*************************************************************************/+ /* */+ /* <Structure> */+ /* CFF_Builder */+ /* */+ /* <Description> */+ /* A structure used during glyph loading to store its outline. */+ /* */+ /* <Fields> */+ /* memory :: The current memory object. */+ /* */+ /* face :: The current face object. */+ /* */+ /* glyph :: The current glyph slot. */+ /* */+ /* loader :: The current glyph loader. */+ /* */+ /* base :: The base glyph outline. */+ /* */+ /* current :: The current glyph outline. */+ /* */+ /* pos_x :: The horizontal translation (if composite glyph). */+ /* */+ /* pos_y :: The vertical translation (if composite glyph). */+ /* */+ /* left_bearing :: The left side bearing point. */+ /* */+ /* advance :: The horizontal advance vector. */+ /* */+ /* bbox :: Unused. */+ /* */+ /* path_begun :: A flag which indicates that a new path has begun. */+ /* */+ /* load_points :: If this flag is not set, no points are loaded. */+ /* */+ /* no_recurse :: Set but not used. */+ /* */+ /* metrics_only :: A boolean indicating that we only want to compute */+ /* the metrics of a given glyph, not load all of its */+ /* points. */+ /* */+ /* hints_funcs :: Auxiliary pointer for hinting. */+ /* */+ /* hints_globals :: Auxiliary pointer for hinting. */+ /* */+ typedef struct CFF_Builder_+ {+ FT_Memory memory;+ TT_Face face;+ CFF_GlyphSlot glyph;+ FT_GlyphLoader loader;+ FT_Outline* base;+ FT_Outline* current;++ FT_Pos pos_x;+ FT_Pos pos_y;++ FT_Vector left_bearing;+ FT_Vector advance;++ FT_BBox bbox; /* bounding box */+ FT_Bool path_begun;+ FT_Bool load_points;+ FT_Bool no_recurse;++ FT_Bool metrics_only;++ void* hints_funcs; /* hinter-specific */+ void* hints_globals; /* hinter-specific */++ } CFF_Builder;+++ /* execution context charstring zone */++ typedef struct CFF_Decoder_Zone_+ {+ FT_Byte* base;+ FT_Byte* limit;+ FT_Byte* cursor;++ } CFF_Decoder_Zone;+++ typedef struct CFF_Decoder_+ {+ CFF_Builder builder;+ CFF_Font cff;++ FT_Fixed stack[CFF_MAX_OPERANDS + 1];+ FT_Fixed* top;++ CFF_Decoder_Zone zones[CFF_MAX_SUBRS_CALLS + 1];+ CFF_Decoder_Zone* zone;++ FT_Int flex_state;+ FT_Int num_flex_vectors;+ FT_Vector flex_vectors[7];++ FT_Pos glyph_width;+ FT_Pos nominal_width;++ FT_Bool read_width;+ FT_Bool width_only;+ FT_Int num_hints;+ FT_Fixed buildchar[CFF_MAX_TRANS_ELEMENTS];++ FT_UInt num_locals;+ FT_UInt num_globals;++ FT_Int locals_bias;+ FT_Int globals_bias;++ FT_Byte** locals;+ FT_Byte** globals;++ FT_Byte** glyph_names; /* for pure CFF fonts only */+ FT_UInt num_glyphs; /* number of glyphs in font */++ FT_Render_Mode hint_mode;++ FT_Bool seac;++ } CFF_Decoder;+++ FT_LOCAL( void )+ cff_decoder_init( CFF_Decoder* decoder,+ TT_Face face,+ CFF_Size size,+ CFF_GlyphSlot slot,+ FT_Bool hinting,+ FT_Render_Mode hint_mode );++ FT_LOCAL( FT_Error )+ cff_decoder_prepare( CFF_Decoder* decoder,+ CFF_Size size,+ FT_UInt glyph_index );++#if 0 /* unused until we support pure CFF fonts */++ /* Compute the maximum advance width of a font through quick parsing */+ FT_LOCAL( FT_Error )+ cff_compute_max_advance( TT_Face face,+ FT_Int* max_advance );++#endif /* 0 */++ FT_LOCAL( FT_Error )+ cff_decoder_parse_charstrings( CFF_Decoder* decoder,+ FT_Byte* charstring_base,+ FT_ULong charstring_len );++ FT_LOCAL( FT_Error )+ cff_slot_load( CFF_GlyphSlot glyph,+ CFF_Size size,+ FT_UInt glyph_index,+ FT_Int32 load_flags );+++FT_END_HEADER++#endif /* __CFFGLOAD_H__ */+++/* END */
+ src/cff/cffload.c view
@@ -0,0 +1,1661 @@+/***************************************************************************/+/* */+/* cffload.c */+/* */+/* OpenType and CFF data/program tables loader (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */+/* 2010 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_INTERNAL_STREAM_H+#include FT_TRUETYPE_TAGS_H+#include FT_TYPE1_TABLES_H++#include "cffload.h"+#include "cffparse.h"++#include "cfferrs.h"+++#if 1++ static const FT_UShort cff_isoadobe_charset[229] =+ {+ 0, 1, 2, 3, 4, 5, 6, 7,+ 8, 9, 10, 11, 12, 13, 14, 15,+ 16, 17, 18, 19, 20, 21, 22, 23,+ 24, 25, 26, 27, 28, 29, 30, 31,+ 32, 33, 34, 35, 36, 37, 38, 39,+ 40, 41, 42, 43, 44, 45, 46, 47,+ 48, 49, 50, 51, 52, 53, 54, 55,+ 56, 57, 58, 59, 60, 61, 62, 63,+ 64, 65, 66, 67, 68, 69, 70, 71,+ 72, 73, 74, 75, 76, 77, 78, 79,+ 80, 81, 82, 83, 84, 85, 86, 87,+ 88, 89, 90, 91, 92, 93, 94, 95,+ 96, 97, 98, 99, 100, 101, 102, 103,+ 104, 105, 106, 107, 108, 109, 110, 111,+ 112, 113, 114, 115, 116, 117, 118, 119,+ 120, 121, 122, 123, 124, 125, 126, 127,+ 128, 129, 130, 131, 132, 133, 134, 135,+ 136, 137, 138, 139, 140, 141, 142, 143,+ 144, 145, 146, 147, 148, 149, 150, 151,+ 152, 153, 154, 155, 156, 157, 158, 159,+ 160, 161, 162, 163, 164, 165, 166, 167,+ 168, 169, 170, 171, 172, 173, 174, 175,+ 176, 177, 178, 179, 180, 181, 182, 183,+ 184, 185, 186, 187, 188, 189, 190, 191,+ 192, 193, 194, 195, 196, 197, 198, 199,+ 200, 201, 202, 203, 204, 205, 206, 207,+ 208, 209, 210, 211, 212, 213, 214, 215,+ 216, 217, 218, 219, 220, 221, 222, 223,+ 224, 225, 226, 227, 228+ };++ static const FT_UShort cff_expert_charset[166] =+ {+ 0, 1, 229, 230, 231, 232, 233, 234,+ 235, 236, 237, 238, 13, 14, 15, 99,+ 239, 240, 241, 242, 243, 244, 245, 246,+ 247, 248, 27, 28, 249, 250, 251, 252,+ 253, 254, 255, 256, 257, 258, 259, 260,+ 261, 262, 263, 264, 265, 266, 109, 110,+ 267, 268, 269, 270, 271, 272, 273, 274,+ 275, 276, 277, 278, 279, 280, 281, 282,+ 283, 284, 285, 286, 287, 288, 289, 290,+ 291, 292, 293, 294, 295, 296, 297, 298,+ 299, 300, 301, 302, 303, 304, 305, 306,+ 307, 308, 309, 310, 311, 312, 313, 314,+ 315, 316, 317, 318, 158, 155, 163, 319,+ 320, 321, 322, 323, 324, 325, 326, 150,+ 164, 169, 327, 328, 329, 330, 331, 332,+ 333, 334, 335, 336, 337, 338, 339, 340,+ 341, 342, 343, 344, 345, 346, 347, 348,+ 349, 350, 351, 352, 353, 354, 355, 356,+ 357, 358, 359, 360, 361, 362, 363, 364,+ 365, 366, 367, 368, 369, 370, 371, 372,+ 373, 374, 375, 376, 377, 378+ };++ static const FT_UShort cff_expertsubset_charset[87] =+ {+ 0, 1, 231, 232, 235, 236, 237, 238,+ 13, 14, 15, 99, 239, 240, 241, 242,+ 243, 244, 245, 246, 247, 248, 27, 28,+ 249, 250, 251, 253, 254, 255, 256, 257,+ 258, 259, 260, 261, 262, 263, 264, 265,+ 266, 109, 110, 267, 268, 269, 270, 272,+ 300, 301, 302, 305, 314, 315, 158, 155,+ 163, 320, 321, 322, 323, 324, 325, 326,+ 150, 164, 169, 327, 328, 329, 330, 331,+ 332, 333, 334, 335, 336, 337, 338, 339,+ 340, 341, 342, 343, 344, 345, 346+ };++ static const FT_UShort cff_standard_encoding[256] =+ {+ 0, 0, 0, 0, 0, 0, 0, 0,+ 0, 0, 0, 0, 0, 0, 0, 0,+ 0, 0, 0, 0, 0, 0, 0, 0,+ 0, 0, 0, 0, 0, 0, 0, 0,+ 1, 2, 3, 4, 5, 6, 7, 8,+ 9, 10, 11, 12, 13, 14, 15, 16,+ 17, 18, 19, 20, 21, 22, 23, 24,+ 25, 26, 27, 28, 29, 30, 31, 32,+ 33, 34, 35, 36, 37, 38, 39, 40,+ 41, 42, 43, 44, 45, 46, 47, 48,+ 49, 50, 51, 52, 53, 54, 55, 56,+ 57, 58, 59, 60, 61, 62, 63, 64,+ 65, 66, 67, 68, 69, 70, 71, 72,+ 73, 74, 75, 76, 77, 78, 79, 80,+ 81, 82, 83, 84, 85, 86, 87, 88,+ 89, 90, 91, 92, 93, 94, 95, 0,+ 0, 0, 0, 0, 0, 0, 0, 0,+ 0, 0, 0, 0, 0, 0, 0, 0,+ 0, 0, 0, 0, 0, 0, 0, 0,+ 0, 0, 0, 0, 0, 0, 0, 0,+ 0, 96, 97, 98, 99, 100, 101, 102,+ 103, 104, 105, 106, 107, 108, 109, 110,+ 0, 111, 112, 113, 114, 0, 115, 116,+ 117, 118, 119, 120, 121, 122, 0, 123,+ 0, 124, 125, 126, 127, 128, 129, 130,+ 131, 0, 132, 133, 0, 134, 135, 136,+ 137, 0, 0, 0, 0, 0, 0, 0,+ 0, 0, 0, 0, 0, 0, 0, 0,+ 0, 138, 0, 139, 0, 0, 0, 0,+ 140, 141, 142, 143, 0, 0, 0, 0,+ 0, 144, 0, 0, 0, 145, 0, 0,+ 146, 147, 148, 149, 0, 0, 0, 0+ };++ static const FT_UShort cff_expert_encoding[256] =+ {+ 0, 0, 0, 0, 0, 0, 0, 0,+ 0, 0, 0, 0, 0, 0, 0, 0,+ 0, 0, 0, 0, 0, 0, 0, 0,+ 0, 0, 0, 0, 0, 0, 0, 0,+ 1, 229, 230, 0, 231, 232, 233, 234,+ 235, 236, 237, 238, 13, 14, 15, 99,+ 239, 240, 241, 242, 243, 244, 245, 246,+ 247, 248, 27, 28, 249, 250, 251, 252,+ 0, 253, 254, 255, 256, 257, 0, 0,+ 0, 258, 0, 0, 259, 260, 261, 262,+ 0, 0, 263, 264, 265, 0, 266, 109,+ 110, 267, 268, 269, 0, 270, 271, 272,+ 273, 274, 275, 276, 277, 278, 279, 280,+ 281, 282, 283, 284, 285, 286, 287, 288,+ 289, 290, 291, 292, 293, 294, 295, 296,+ 297, 298, 299, 300, 301, 302, 303, 0,+ 0, 0, 0, 0, 0, 0, 0, 0,+ 0, 0, 0, 0, 0, 0, 0, 0,+ 0, 0, 0, 0, 0, 0, 0, 0,+ 0, 0, 0, 0, 0, 0, 0, 0,+ 0, 304, 305, 306, 0, 0, 307, 308,+ 309, 310, 311, 0, 312, 0, 0, 312,+ 0, 0, 314, 315, 0, 0, 316, 317,+ 318, 0, 0, 0, 158, 155, 163, 319,+ 320, 321, 322, 323, 324, 325, 0, 0,+ 326, 150, 164, 169, 327, 328, 329, 330,+ 331, 332, 333, 334, 335, 336, 337, 338,+ 339, 340, 341, 342, 343, 344, 345, 346,+ 347, 348, 349, 350, 351, 352, 353, 354,+ 355, 356, 357, 358, 359, 360, 361, 362,+ 363, 364, 365, 366, 367, 368, 369, 370,+ 371, 372, 373, 374, 375, 376, 377, 378+ };++#endif /* 1 */+++ FT_LOCAL_DEF( FT_UShort )+ cff_get_standard_encoding( FT_UInt charcode )+ {+ return (FT_UShort)( charcode < 256 ? cff_standard_encoding[charcode]+ : 0 );+ }+++ /*************************************************************************/+ /* */+ /* 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_cffload+++ /* read an offset from the index's stream current position */+ static FT_ULong+ cff_index_read_offset( CFF_Index idx,+ FT_Error *errorp )+ {+ FT_Error error;+ FT_Stream stream = idx->stream;+ FT_Byte tmp[4];+ FT_ULong result = 0;+++ if ( !FT_STREAM_READ( tmp, idx->off_size ) )+ {+ FT_Int nn;+++ for ( nn = 0; nn < idx->off_size; nn++ )+ result = ( result << 8 ) | tmp[nn];+ }++ *errorp = error;+ return result;+ }+++ static FT_Error+ cff_index_init( CFF_Index idx,+ FT_Stream stream,+ FT_Bool load )+ {+ FT_Error error;+ FT_Memory memory = stream->memory;+ FT_UShort count;+++ FT_MEM_ZERO( idx, sizeof ( *idx ) );++ idx->stream = stream;+ idx->start = FT_STREAM_POS();+ if ( !FT_READ_USHORT( count ) &&+ count > 0 )+ {+ FT_Byte offsize;+ FT_ULong size;+++ /* there is at least one element; read the offset size, */+ /* then access the offset table to compute the index's total size */+ if ( FT_READ_BYTE( offsize ) )+ goto Exit;++ if ( offsize < 1 || offsize > 4 )+ {+ error = CFF_Err_Invalid_Table;+ goto Exit;+ }++ idx->count = count;+ idx->off_size = offsize;+ size = (FT_ULong)( count + 1 ) * offsize;++ idx->data_offset = idx->start + 3 + size;++ if ( FT_STREAM_SKIP( size - offsize ) )+ goto Exit;++ size = cff_index_read_offset( idx, &error );+ if ( error )+ goto Exit;++ if ( size == 0 )+ {+ error = CFF_Err_Invalid_Table;+ goto Exit;+ }++ idx->data_size = --size;++ if ( load )+ {+ /* load the data */+ if ( FT_FRAME_EXTRACT( size, idx->bytes ) )+ goto Exit;+ }+ else+ {+ /* skip the data */+ if ( FT_STREAM_SKIP( size ) )+ goto Exit;+ }+ }++ Exit:+ if ( error )+ FT_FREE( idx->offsets );++ return error;+ }+++ static void+ cff_index_done( CFF_Index idx )+ {+ if ( idx->stream )+ {+ FT_Stream stream = idx->stream;+ FT_Memory memory = stream->memory;+++ if ( idx->bytes )+ FT_FRAME_RELEASE( idx->bytes );++ FT_FREE( idx->offsets );+ FT_MEM_ZERO( idx, sizeof ( *idx ) );+ }+ }+++ static FT_Error+ cff_index_load_offsets( CFF_Index idx )+ {+ FT_Error error = CFF_Err_Ok;+ FT_Stream stream = idx->stream;+ FT_Memory memory = stream->memory;+++ if ( idx->count > 0 && idx->offsets == NULL )+ {+ FT_Byte offsize = idx->off_size;+ FT_ULong data_size;+ FT_Byte* p;+ FT_Byte* p_end;+ FT_ULong* poff;+++ data_size = (FT_ULong)( idx->count + 1 ) * offsize;++ if ( FT_NEW_ARRAY( idx->offsets, idx->count + 1 ) ||+ FT_STREAM_SEEK( idx->start + 3 ) ||+ FT_FRAME_ENTER( data_size ) )+ goto Exit;++ poff = idx->offsets;+ p = (FT_Byte*)stream->cursor;+ p_end = p + data_size;++ switch ( offsize )+ {+ case 1:+ for ( ; p < p_end; p++, poff++ )+ poff[0] = p[0];+ break;++ case 2:+ for ( ; p < p_end; p += 2, poff++ )+ poff[0] = FT_PEEK_USHORT( p );+ break;++ case 3:+ for ( ; p < p_end; p += 3, poff++ )+ poff[0] = FT_PEEK_OFF3( p );+ break;++ default:+ for ( ; p < p_end; p += 4, poff++ )+ poff[0] = FT_PEEK_ULONG( p );+ }++ FT_FRAME_EXIT();+ }++ Exit:+ if ( error )+ FT_FREE( idx->offsets );++ return error;+ }+++ /* Allocate a table containing pointers to an index's elements. */+ /* The `pool' argument makes this function convert the index */+ /* entries to C-style strings (this is, NULL-terminated). */+ static FT_Error+ cff_index_get_pointers( CFF_Index idx,+ FT_Byte*** table,+ FT_Byte** pool )+ {+ FT_Error error = CFF_Err_Ok;+ FT_Memory memory = idx->stream->memory;+ FT_Byte** t;+ FT_Byte* new_bytes = NULL;+++ *table = NULL;++ if ( idx->offsets == NULL )+ {+ error = cff_index_load_offsets( idx );+ if ( error )+ goto Exit;+ }++ if ( idx->count > 0 &&+ !FT_NEW_ARRAY( t, idx->count + 1 ) &&+ ( !pool || !FT_ALLOC( new_bytes,+ idx->data_size + idx->count ) ) )+ {+ FT_ULong n, cur_offset;+ FT_ULong extra = 0;+ FT_Byte* org_bytes = idx->bytes;+++ /* at this point, `idx->offsets' can't be NULL */+ cur_offset = idx->offsets[0] - 1;++ /* sanity check */+ if ( cur_offset >= idx->data_size )+ {+ FT_TRACE0(( "cff_index_get_pointers:"+ " invalid first offset value %d set to zero\n",+ cur_offset ));+ cur_offset = 0;+ }++ if ( !pool )+ t[0] = org_bytes + cur_offset;+ else+ t[0] = new_bytes + cur_offset;++ for ( n = 1; n <= idx->count; n++ )+ {+ FT_ULong next_offset = idx->offsets[n] - 1;+++ /* empty slot + two sanity checks for invalid offset tables */+ if ( next_offset == 0 ||+ next_offset < cur_offset ||+ ( next_offset >= idx->data_size && n < idx->count ) )+ next_offset = cur_offset;++ if ( !pool )+ t[n] = org_bytes + next_offset;+ else+ {+ t[n] = new_bytes + next_offset + extra;++ if ( next_offset != cur_offset )+ {+ FT_MEM_COPY( t[n - 1], org_bytes + cur_offset, t[n] - t[n - 1] );+ t[n][0] = '\0';+ t[n] += 1;+ extra++;+ }+ }++ cur_offset = next_offset;+ }+ *table = t;++ if ( pool )+ *pool = new_bytes;+ }++ Exit:+ return error;+ }+++ FT_LOCAL_DEF( FT_Error )+ cff_index_access_element( CFF_Index idx,+ FT_UInt element,+ FT_Byte** pbytes,+ FT_ULong* pbyte_len )+ {+ FT_Error error = CFF_Err_Ok;+++ if ( idx && idx->count > element )+ {+ /* compute start and end offsets */+ FT_Stream stream = idx->stream;+ FT_ULong off1, off2 = 0;+++ /* load offsets from file or the offset table */+ if ( !idx->offsets )+ {+ FT_ULong pos = element * idx->off_size;+++ if ( FT_STREAM_SEEK( idx->start + 3 + pos ) )+ goto Exit;++ off1 = cff_index_read_offset( idx, &error );+ if ( error )+ goto Exit;++ if ( off1 != 0 )+ {+ do+ {+ element++;+ off2 = cff_index_read_offset( idx, &error );+ }+ while ( off2 == 0 && element < idx->count );+ }+ }+ else /* use offsets table */+ {+ off1 = idx->offsets[element];+ if ( off1 )+ {+ do+ {+ element++;+ off2 = idx->offsets[element];++ } while ( off2 == 0 && element < idx->count );+ }+ }++ /* XXX: should check off2 does not exceed the end of this entry; */+ /* at present, only truncate off2 at the end of this stream */+ if ( off2 > stream->size + 1 ||+ idx->data_offset > stream->size - off2 + 1 )+ {+ FT_ERROR(( "cff_index_access_element:"+ " offset to next entry (%d)"+ " exceeds the end of stream (%d)\n",+ off2, stream->size - idx->data_offset + 1 ));+ off2 = stream->size - idx->data_offset + 1;+ }++ /* access element */+ if ( off1 && off2 > off1 )+ {+ *pbyte_len = off2 - off1;++ if ( idx->bytes )+ {+ /* this index was completely loaded in memory, that's easy */+ *pbytes = idx->bytes + off1 - 1;+ }+ else+ {+ /* this index is still on disk/file, access it through a frame */+ if ( FT_STREAM_SEEK( idx->data_offset + off1 - 1 ) ||+ FT_FRAME_EXTRACT( off2 - off1, *pbytes ) )+ goto Exit;+ }+ }+ else+ {+ /* empty index element */+ *pbytes = 0;+ *pbyte_len = 0;+ }+ }+ else+ error = CFF_Err_Invalid_Argument;++ Exit:+ return error;+ }+++ FT_LOCAL_DEF( void )+ cff_index_forget_element( CFF_Index idx,+ FT_Byte** pbytes )+ {+ if ( idx->bytes == 0 )+ {+ FT_Stream stream = idx->stream;+++ FT_FRAME_RELEASE( *pbytes );+ }+ }+++ /* get an entry from Name INDEX */+ FT_LOCAL_DEF( FT_String* )+ cff_index_get_name( CFF_Font font,+ FT_UInt element )+ {+ CFF_Index idx = &font->name_index;+ FT_Memory memory = idx->stream->memory;+ FT_Byte* bytes;+ FT_ULong byte_len;+ FT_Error error;+ FT_String* name = 0;+++ error = cff_index_access_element( idx, element, &bytes, &byte_len );+ if ( error )+ goto Exit;++ if ( !FT_ALLOC( name, byte_len + 1 ) )+ {+ FT_MEM_COPY( name, bytes, byte_len );+ name[byte_len] = 0;+ }+ cff_index_forget_element( idx, &bytes );++ Exit:+ return name;+ }+++ /* get an entry from String INDEX */+ FT_LOCAL_DEF( FT_String* )+ cff_index_get_string( CFF_Font font,+ FT_UInt element )+ {+ return ( element < font->num_strings )+ ? (FT_String*)font->strings[element]+ : NULL;+ }+++ FT_LOCAL_DEF( FT_String* )+ cff_index_get_sid_string( CFF_Font font,+ FT_UInt sid )+ {+ /* value 0xFFFFU indicates a missing dictionary entry */+ if ( sid == 0xFFFFU )+ return NULL;++ /* if it is not a standard string, return it */+ if ( sid > 390 )+ return cff_index_get_string( font, sid - 391 );++ /* CID-keyed CFF fonts don't have glyph names */+ if ( !font->psnames )+ return NULL;++ /* this is a standard string */+ return (FT_String *)font->psnames->adobe_std_strings( sid );+ }+++ /*************************************************************************/+ /*************************************************************************/+ /*** ***/+ /*** FD Select table support ***/+ /*** ***/+ /*************************************************************************/+ /*************************************************************************/+++ static void+ CFF_Done_FD_Select( CFF_FDSelect fdselect,+ FT_Stream stream )+ {+ if ( fdselect->data )+ FT_FRAME_RELEASE( fdselect->data );++ fdselect->data_size = 0;+ fdselect->format = 0;+ fdselect->range_count = 0;+ }+++ static FT_Error+ CFF_Load_FD_Select( CFF_FDSelect fdselect,+ FT_UInt num_glyphs,+ FT_Stream stream,+ FT_ULong offset )+ {+ FT_Error error;+ FT_Byte format;+ FT_UInt num_ranges;+++ /* read format */+ if ( FT_STREAM_SEEK( offset ) || FT_READ_BYTE( format ) )+ goto Exit;++ fdselect->format = format;+ fdselect->cache_count = 0; /* clear cache */++ switch ( format )+ {+ case 0: /* format 0, that's simple */+ fdselect->data_size = num_glyphs;+ goto Load_Data;++ case 3: /* format 3, a tad more complex */+ if ( FT_READ_USHORT( num_ranges ) )+ goto Exit;++ fdselect->data_size = num_ranges * 3 + 2;++ Load_Data:+ if ( FT_FRAME_EXTRACT( fdselect->data_size, fdselect->data ) )+ goto Exit;+ break;++ default: /* hmm... that's wrong */+ error = CFF_Err_Invalid_File_Format;+ }++ Exit:+ return error;+ }+++ FT_LOCAL_DEF( FT_Byte )+ cff_fd_select_get( CFF_FDSelect fdselect,+ FT_UInt glyph_index )+ {+ FT_Byte fd = 0;+++ switch ( fdselect->format )+ {+ case 0:+ fd = fdselect->data[glyph_index];+ break;++ case 3:+ /* first, compare to cache */+ if ( (FT_UInt)( glyph_index - fdselect->cache_first ) <+ fdselect->cache_count )+ {+ fd = fdselect->cache_fd;+ break;+ }++ /* then, lookup the ranges array */+ {+ FT_Byte* p = fdselect->data;+ FT_Byte* p_limit = p + fdselect->data_size;+ FT_Byte fd2;+ FT_UInt first, limit;+++ first = FT_NEXT_USHORT( p );+ do+ {+ if ( glyph_index < first )+ break;++ fd2 = *p++;+ limit = FT_NEXT_USHORT( p );++ if ( glyph_index < limit )+ {+ fd = fd2;++ /* update cache */+ fdselect->cache_first = first;+ fdselect->cache_count = limit-first;+ fdselect->cache_fd = fd2;+ break;+ }+ first = limit;++ } while ( p < p_limit );+ }+ break;++ default:+ ;+ }++ return fd;+ }+++ /*************************************************************************/+ /*************************************************************************/+ /*** ***/+ /*** CFF font support ***/+ /*** ***/+ /*************************************************************************/+ /*************************************************************************/++ static FT_Error+ cff_charset_compute_cids( CFF_Charset charset,+ FT_UInt num_glyphs,+ FT_Memory memory )+ {+ FT_Error error = CFF_Err_Ok;+ FT_UInt i;+ FT_Long j;+ FT_UShort max_cid = 0;+++ if ( charset->max_cid > 0 )+ goto Exit;++ for ( i = 0; i < num_glyphs; i++ )+ {+ if ( charset->sids[i] > max_cid )+ max_cid = charset->sids[i];+ }++ if ( FT_NEW_ARRAY( charset->cids, (FT_ULong)max_cid + 1 ) )+ goto Exit;++ /* When multiple GIDs map to the same CID, we choose the lowest */+ /* GID. This is not described in any spec, but it matches the */+ /* behaviour of recent Acroread versions. */+ for ( j = num_glyphs - 1; j >= 0 ; j-- )+ charset->cids[charset->sids[j]] = (FT_UShort)j;++ charset->max_cid = max_cid;+ charset->num_glyphs = num_glyphs;++ Exit:+ return error;+ }+++ FT_LOCAL_DEF( FT_UInt )+ cff_charset_cid_to_gindex( CFF_Charset charset,+ FT_UInt cid )+ {+ FT_UInt result = 0;+++ if ( cid <= charset->max_cid )+ result = charset->cids[cid];++ return result;+ }+++ static void+ cff_charset_free_cids( CFF_Charset charset,+ FT_Memory memory )+ {+ FT_FREE( charset->cids );+ charset->max_cid = 0;+ }+++ static void+ cff_charset_done( CFF_Charset charset,+ FT_Stream stream )+ {+ FT_Memory memory = stream->memory;+++ cff_charset_free_cids( charset, memory );++ FT_FREE( charset->sids );+ charset->format = 0;+ charset->offset = 0;+ }+++ static FT_Error+ cff_charset_load( CFF_Charset charset,+ FT_UInt num_glyphs,+ FT_Stream stream,+ FT_ULong base_offset,+ FT_ULong offset,+ FT_Bool invert )+ {+ FT_Memory memory = stream->memory;+ FT_Error error = CFF_Err_Ok;+ FT_UShort glyph_sid;+++ /* If the the offset is greater than 2, we have to parse the */+ /* charset table. */+ if ( offset > 2 )+ {+ FT_UInt j;+++ charset->offset = base_offset + offset;++ /* Get the format of the table. */+ if ( FT_STREAM_SEEK( charset->offset ) ||+ FT_READ_BYTE( charset->format ) )+ goto Exit;++ /* Allocate memory for sids. */+ if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )+ goto Exit;++ /* assign the .notdef glyph */+ charset->sids[0] = 0;++ switch ( charset->format )+ {+ case 0:+ if ( num_glyphs > 0 )+ {+ if ( FT_FRAME_ENTER( ( num_glyphs - 1 ) * 2 ) )+ goto Exit;++ for ( j = 1; j < num_glyphs; j++ )+ charset->sids[j] = FT_GET_USHORT();++ FT_FRAME_EXIT();+ }+ break;++ case 1:+ case 2:+ {+ FT_UInt nleft;+ FT_UInt i;+++ j = 1;++ while ( j < num_glyphs )+ {+ /* Read the first glyph sid of the range. */+ if ( FT_READ_USHORT( glyph_sid ) )+ goto Exit;++ /* Read the number of glyphs in the range. */+ if ( charset->format == 2 )+ {+ if ( FT_READ_USHORT( nleft ) )+ goto Exit;+ }+ else+ {+ if ( FT_READ_BYTE( nleft ) )+ goto Exit;+ }++ /* try to rescue some of the SIDs if `nleft' is too large */+ if ( glyph_sid > 0xFFFFL - nleft )+ {+ FT_ERROR(( "cff_charset_load: invalid SID range trimmed"+ " nleft=%d -> %d\n", nleft, 0xFFFFL - glyph_sid ));+ nleft = ( FT_UInt )( 0xFFFFL - glyph_sid );+ }++ /* Fill in the range of sids -- `nleft + 1' glyphs. */+ for ( i = 0; j < num_glyphs && i <= nleft; i++, j++, glyph_sid++ )+ charset->sids[j] = glyph_sid;+ }+ }+ break;++ default:+ FT_ERROR(( "cff_charset_load: invalid table format\n" ));+ error = CFF_Err_Invalid_File_Format;+ goto Exit;+ }+ }+ else+ {+ /* Parse default tables corresponding to offset == 0, 1, or 2. */+ /* CFF specification intimates the following: */+ /* */+ /* In order to use a predefined charset, the following must be */+ /* true: The charset constructed for the glyphs in the font's */+ /* charstrings dictionary must match the predefined charset in */+ /* the first num_glyphs. */++ charset->offset = offset; /* record charset type */++ switch ( (FT_UInt)offset )+ {+ case 0:+ if ( num_glyphs > 229 )+ {+ FT_ERROR(( "cff_charset_load: implicit charset larger than\n"+ "predefined charset (Adobe ISO-Latin)\n" ));+ error = CFF_Err_Invalid_File_Format;+ goto Exit;+ }++ /* Allocate memory for sids. */+ if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )+ goto Exit;++ /* Copy the predefined charset into the allocated memory. */+ FT_ARRAY_COPY( charset->sids, cff_isoadobe_charset, num_glyphs );++ break;++ case 1:+ if ( num_glyphs > 166 )+ {+ FT_ERROR(( "cff_charset_load: implicit charset larger than\n"+ "predefined charset (Adobe Expert)\n" ));+ error = CFF_Err_Invalid_File_Format;+ goto Exit;+ }++ /* Allocate memory for sids. */+ if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )+ goto Exit;++ /* Copy the predefined charset into the allocated memory. */+ FT_ARRAY_COPY( charset->sids, cff_expert_charset, num_glyphs );++ break;++ case 2:+ if ( num_glyphs > 87 )+ {+ FT_ERROR(( "cff_charset_load: implicit charset larger than\n"+ "predefined charset (Adobe Expert Subset)\n" ));+ error = CFF_Err_Invalid_File_Format;+ goto Exit;+ }++ /* Allocate memory for sids. */+ if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )+ goto Exit;++ /* Copy the predefined charset into the allocated memory. */+ FT_ARRAY_COPY( charset->sids, cff_expertsubset_charset, num_glyphs );++ break;++ default:+ error = CFF_Err_Invalid_File_Format;+ goto Exit;+ }+ }++ /* we have to invert the `sids' array for subsetted CID-keyed fonts */+ if ( invert )+ error = cff_charset_compute_cids( charset, num_glyphs, memory );++ Exit:+ /* Clean up if there was an error. */+ if ( error )+ {+ FT_FREE( charset->sids );+ FT_FREE( charset->cids );+ charset->format = 0;+ charset->offset = 0;+ charset->sids = 0;+ }++ return error;+ }+++ static void+ cff_encoding_done( CFF_Encoding encoding )+ {+ encoding->format = 0;+ encoding->offset = 0;+ encoding->count = 0;+ }+++ static FT_Error+ cff_encoding_load( CFF_Encoding encoding,+ CFF_Charset charset,+ FT_UInt num_glyphs,+ FT_Stream stream,+ FT_ULong base_offset,+ FT_ULong offset )+ {+ FT_Error error = CFF_Err_Ok;+ FT_UInt count;+ FT_UInt j;+ FT_UShort glyph_sid;+ FT_UInt glyph_code;+++ /* Check for charset->sids. If we do not have this, we fail. */+ if ( !charset->sids )+ {+ error = CFF_Err_Invalid_File_Format;+ goto Exit;+ }++ /* Zero out the code to gid/sid mappings. */+ for ( j = 0; j < 256; j++ )+ {+ encoding->sids [j] = 0;+ encoding->codes[j] = 0;+ }++ /* Note: The encoding table in a CFF font is indexed by glyph index; */+ /* the first encoded glyph index is 1. Hence, we read the character */+ /* code (`glyph_code') at index j and make the assignment: */+ /* */+ /* encoding->codes[glyph_code] = j + 1 */+ /* */+ /* We also make the assignment: */+ /* */+ /* encoding->sids[glyph_code] = charset->sids[j + 1] */+ /* */+ /* This gives us both a code to GID and a code to SID mapping. */++ if ( offset > 1 )+ {+ encoding->offset = base_offset + offset;++ /* we need to parse the table to determine its size */+ if ( FT_STREAM_SEEK( encoding->offset ) ||+ FT_READ_BYTE( encoding->format ) ||+ FT_READ_BYTE( count ) )+ goto Exit;++ switch ( encoding->format & 0x7F )+ {+ case 0:+ {+ FT_Byte* p;+++ /* By convention, GID 0 is always ".notdef" and is never */+ /* coded in the font. Hence, the number of codes found */+ /* in the table is `count+1'. */+ /* */+ encoding->count = count + 1;++ if ( FT_FRAME_ENTER( count ) )+ goto Exit;++ p = (FT_Byte*)stream->cursor;++ for ( j = 1; j <= count; j++ )+ {+ glyph_code = *p++;++ /* Make sure j is not too big. */+ if ( j < num_glyphs )+ {+ /* Assign code to GID mapping. */+ encoding->codes[glyph_code] = (FT_UShort)j;++ /* Assign code to SID mapping. */+ encoding->sids[glyph_code] = charset->sids[j];+ }+ }++ FT_FRAME_EXIT();+ }+ break;++ case 1:+ {+ FT_UInt nleft;+ FT_UInt i = 1;+ FT_UInt k;+++ encoding->count = 0;++ /* Parse the Format1 ranges. */+ for ( j = 0; j < count; j++, i += nleft )+ {+ /* Read the first glyph code of the range. */+ if ( FT_READ_BYTE( glyph_code ) )+ goto Exit;++ /* Read the number of codes in the range. */+ if ( FT_READ_BYTE( nleft ) )+ goto Exit;++ /* Increment nleft, so we read `nleft + 1' codes/sids. */+ nleft++;++ /* compute max number of character codes */+ if ( (FT_UInt)nleft > encoding->count )+ encoding->count = nleft;++ /* Fill in the range of codes/sids. */+ for ( k = i; k < nleft + i; k++, glyph_code++ )+ {+ /* Make sure k is not too big. */+ if ( k < num_glyphs && glyph_code < 256 )+ {+ /* Assign code to GID mapping. */+ encoding->codes[glyph_code] = (FT_UShort)k;++ /* Assign code to SID mapping. */+ encoding->sids[glyph_code] = charset->sids[k];+ }+ }+ }++ /* simple check; one never knows what can be found in a font */+ if ( encoding->count > 256 )+ encoding->count = 256;+ }+ break;++ default:+ FT_ERROR(( "cff_encoding_load: invalid table format\n" ));+ error = CFF_Err_Invalid_File_Format;+ goto Exit;+ }++ /* Parse supplemental encodings, if any. */+ if ( encoding->format & 0x80 )+ {+ FT_UInt gindex;+++ /* count supplements */+ if ( FT_READ_BYTE( count ) )+ goto Exit;++ for ( j = 0; j < count; j++ )+ {+ /* Read supplemental glyph code. */+ if ( FT_READ_BYTE( glyph_code ) )+ goto Exit;++ /* Read the SID associated with this glyph code. */+ if ( FT_READ_USHORT( glyph_sid ) )+ goto Exit;++ /* Assign code to SID mapping. */+ encoding->sids[glyph_code] = glyph_sid;++ /* First, look up GID which has been assigned to */+ /* SID glyph_sid. */+ for ( gindex = 0; gindex < num_glyphs; gindex++ )+ {+ if ( charset->sids[gindex] == glyph_sid )+ {+ encoding->codes[glyph_code] = (FT_UShort)gindex;+ break;+ }+ }+ }+ }+ }+ else+ {+ /* We take into account the fact a CFF font can use a predefined */+ /* encoding without containing all of the glyphs encoded by this */+ /* encoding (see the note at the end of section 12 in the CFF */+ /* specification). */++ switch ( (FT_UInt)offset )+ {+ case 0:+ /* First, copy the code to SID mapping. */+ FT_ARRAY_COPY( encoding->sids, cff_standard_encoding, 256 );+ goto Populate;++ case 1:+ /* First, copy the code to SID mapping. */+ FT_ARRAY_COPY( encoding->sids, cff_expert_encoding, 256 );++ Populate:+ /* Construct code to GID mapping from code to SID mapping */+ /* and charset. */++ encoding->count = 0;++ error = cff_charset_compute_cids( charset, num_glyphs,+ stream->memory );+ if ( error )+ goto Exit;++ for ( j = 0; j < 256; j++ )+ {+ FT_UInt sid = encoding->sids[j];+ FT_UInt gid = 0;+++ if ( sid )+ gid = cff_charset_cid_to_gindex( charset, sid );++ if ( gid != 0 )+ {+ encoding->codes[j] = (FT_UShort)gid;+ encoding->count = j + 1;+ }+ else+ {+ encoding->codes[j] = 0;+ encoding->sids [j] = 0;+ }+ }+ break;++ default:+ FT_ERROR(( "cff_encoding_load: invalid table format\n" ));+ error = CFF_Err_Invalid_File_Format;+ goto Exit;+ }+ }++ Exit:++ /* Clean up if there was an error. */+ return error;+ }+++ static FT_Error+ cff_subfont_load( CFF_SubFont font,+ CFF_Index idx,+ FT_UInt font_index,+ FT_Stream stream,+ FT_ULong base_offset,+ FT_Library library )+ {+ FT_Error error;+ CFF_ParserRec parser;+ FT_Byte* dict = NULL;+ FT_ULong dict_len;+ CFF_FontRecDict top = &font->font_dict;+ CFF_Private priv = &font->private_dict;+++ cff_parser_init( &parser, CFF_CODE_TOPDICT, &font->font_dict, library );++ /* set defaults */+ FT_MEM_ZERO( top, sizeof ( *top ) );++ top->underline_position = -100L << 16;+ top->underline_thickness = 50L << 16;+ top->charstring_type = 2;+ top->font_matrix.xx = 0x10000L;+ top->font_matrix.yy = 0x10000L;+ top->cid_count = 8720;++ /* we use the implementation specific SID value 0xFFFF to indicate */+ /* missing entries */+ top->version = 0xFFFFU;+ top->notice = 0xFFFFU;+ top->copyright = 0xFFFFU;+ top->full_name = 0xFFFFU;+ top->family_name = 0xFFFFU;+ top->weight = 0xFFFFU;+ top->embedded_postscript = 0xFFFFU;++ top->cid_registry = 0xFFFFU;+ top->cid_ordering = 0xFFFFU;+ top->cid_font_name = 0xFFFFU;++ error = cff_index_access_element( idx, font_index, &dict, &dict_len );+ if ( !error )+ error = cff_parser_run( &parser, dict, dict + dict_len );++ cff_index_forget_element( idx, &dict );++ if ( error )+ goto Exit;++ /* if it is a CID font, we stop there */+ if ( top->cid_registry != 0xFFFFU )+ goto Exit;++ /* parse the private dictionary, if any */+ if ( top->private_offset && top->private_size )+ {+ /* set defaults */+ FT_MEM_ZERO( priv, sizeof ( *priv ) );++ priv->blue_shift = 7;+ priv->blue_fuzz = 1;+ priv->lenIV = -1;+ priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L );+ priv->blue_scale = (FT_Fixed)( 0.039625 * 0x10000L * 1000 );++ cff_parser_init( &parser, CFF_CODE_PRIVATE, priv, library );++ if ( FT_STREAM_SEEK( base_offset + font->font_dict.private_offset ) ||+ FT_FRAME_ENTER( font->font_dict.private_size ) )+ goto Exit;++ error = cff_parser_run( &parser,+ (FT_Byte*)stream->cursor,+ (FT_Byte*)stream->limit );+ FT_FRAME_EXIT();+ if ( error )+ goto Exit;++ /* ensure that `num_blue_values' is even */+ priv->num_blue_values &= ~1;+ }++ /* read the local subrs, if any */+ if ( priv->local_subrs_offset )+ {+ if ( FT_STREAM_SEEK( base_offset + top->private_offset ++ priv->local_subrs_offset ) )+ goto Exit;++ error = cff_index_init( &font->local_subrs_index, stream, 1 );+ if ( error )+ goto Exit;++ error = cff_index_get_pointers( &font->local_subrs_index,+ &font->local_subrs, NULL );+ if ( error )+ goto Exit;+ }++ Exit:+ return error;+ }+++ static void+ cff_subfont_done( FT_Memory memory,+ CFF_SubFont subfont )+ {+ if ( subfont )+ {+ cff_index_done( &subfont->local_subrs_index );+ FT_FREE( subfont->local_subrs );+ }+ }+++ FT_LOCAL_DEF( FT_Error )+ cff_font_load( FT_Library library,+ FT_Stream stream,+ FT_Int face_index,+ CFF_Font font,+ FT_Bool pure_cff )+ {+ static const FT_Frame_Field cff_header_fields[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE CFF_FontRec++ FT_FRAME_START( 4 ),+ FT_FRAME_BYTE( version_major ),+ FT_FRAME_BYTE( version_minor ),+ FT_FRAME_BYTE( header_size ),+ FT_FRAME_BYTE( absolute_offsize ),+ FT_FRAME_END+ };++ FT_Error error;+ FT_Memory memory = stream->memory;+ FT_ULong base_offset;+ CFF_FontRecDict dict;+ CFF_IndexRec string_index;+++ FT_ZERO( font );+ FT_ZERO( &string_index );++ font->stream = stream;+ font->memory = memory;+ dict = &font->top_font.font_dict;+ base_offset = FT_STREAM_POS();++ /* read CFF font header */+ if ( FT_STREAM_READ_FIELDS( cff_header_fields, font ) )+ goto Exit;++ /* check format */+ if ( font->version_major != 1 ||+ font->header_size < 4 ||+ font->absolute_offsize > 4 )+ {+ FT_TRACE2(( "[not a CFF font header]\n" ));+ error = CFF_Err_Unknown_File_Format;+ goto Exit;+ }++ /* skip the rest of the header */+ if ( FT_STREAM_SKIP( font->header_size - 4 ) )+ goto Exit;++ /* read the name, top dict, string and global subrs index */+ if ( FT_SET_ERROR( cff_index_init( &font->name_index,+ stream, 0 ) ) ||+ FT_SET_ERROR( cff_index_init( &font->font_dict_index,+ stream, 0 ) ) ||+ FT_SET_ERROR( cff_index_init( &string_index,+ stream, 1 ) ) ||+ FT_SET_ERROR( cff_index_init( &font->global_subrs_index,+ stream, 1 ) ) ||+ FT_SET_ERROR( cff_index_get_pointers( &string_index,+ &font->strings,+ &font->string_pool ) ) )+ goto Exit;++ font->num_strings = string_index.count;++ /* well, we don't really forget the `disabled' fonts... */+ font->num_faces = font->name_index.count;+ if ( face_index >= (FT_Int)font->num_faces )+ {+ FT_ERROR(( "cff_font_load: incorrect face index = %d\n",+ face_index ));+ error = CFF_Err_Invalid_Argument;+ }++ /* in case of a font format check, simply exit now */+ if ( face_index < 0 )+ goto Exit;++ /* now, parse the top-level font dictionary */+ error = cff_subfont_load( &font->top_font,+ &font->font_dict_index,+ face_index,+ stream,+ base_offset,+ library );+ if ( error )+ goto Exit;++ if ( FT_STREAM_SEEK( base_offset + dict->charstrings_offset ) )+ goto Exit;++ error = cff_index_init( &font->charstrings_index, stream, 0 );+ if ( error )+ goto Exit;++ /* now, check for a CID font */+ if ( dict->cid_registry != 0xFFFFU )+ {+ CFF_IndexRec fd_index;+ CFF_SubFont sub;+ FT_UInt idx;+++ /* this is a CID-keyed font, we must now allocate a table of */+ /* sub-fonts, then load each of them separately */+ if ( FT_STREAM_SEEK( base_offset + dict->cid_fd_array_offset ) )+ goto Exit;++ error = cff_index_init( &fd_index, stream, 0 );+ if ( error )+ goto Exit;++ if ( fd_index.count > CFF_MAX_CID_FONTS )+ {+ FT_TRACE0(( "cff_font_load: FD array too large in CID font\n" ));+ goto Fail_CID;+ }++ /* allocate & read each font dict independently */+ font->num_subfonts = fd_index.count;+ if ( FT_NEW_ARRAY( sub, fd_index.count ) )+ goto Fail_CID;++ /* set up pointer table */+ for ( idx = 0; idx < fd_index.count; idx++ )+ font->subfonts[idx] = sub + idx;++ /* now load each subfont independently */+ for ( idx = 0; idx < fd_index.count; idx++ )+ {+ sub = font->subfonts[idx];+ error = cff_subfont_load( sub, &fd_index, idx,+ stream, base_offset, library );+ if ( error )+ goto Fail_CID;+ }++ /* now load the FD Select array */+ error = CFF_Load_FD_Select( &font->fd_select,+ font->charstrings_index.count,+ stream,+ base_offset + dict->cid_fd_select_offset );++ Fail_CID:+ cff_index_done( &fd_index );++ if ( error )+ goto Exit;+ }+ else+ font->num_subfonts = 0;++ /* read the charstrings index now */+ if ( dict->charstrings_offset == 0 )+ {+ FT_ERROR(( "cff_font_load: no charstrings offset\n" ));+ error = CFF_Err_Unknown_File_Format;+ goto Exit;+ }++ font->num_glyphs = font->charstrings_index.count;++ error = cff_index_get_pointers( &font->global_subrs_index,+ &font->global_subrs, NULL );++ if ( error )+ goto Exit;++ /* read the Charset and Encoding tables if available */+ if ( font->num_glyphs > 0 )+ {+ FT_Bool invert = FT_BOOL( dict->cid_registry != 0xFFFFU && pure_cff );+++ error = cff_charset_load( &font->charset, font->num_glyphs, stream,+ base_offset, dict->charset_offset, invert );+ if ( error )+ goto Exit;++ /* CID-keyed CFFs don't have an encoding */+ if ( dict->cid_registry == 0xFFFFU )+ {+ error = cff_encoding_load( &font->encoding,+ &font->charset,+ font->num_glyphs,+ stream,+ base_offset,+ dict->encoding_offset );+ if ( error )+ goto Exit;+ }+ }++ /* get the font name (/CIDFontName for CID-keyed fonts, */+ /* /FontName otherwise) */+ font->font_name = cff_index_get_name( font, face_index );++ Exit:+ cff_index_done( &string_index );++ return error;+ }+++ FT_LOCAL_DEF( void )+ cff_font_done( CFF_Font font )+ {+ FT_Memory memory = font->memory;+ FT_UInt idx;+++ cff_index_done( &font->global_subrs_index );+ cff_index_done( &font->font_dict_index );+ cff_index_done( &font->name_index );+ cff_index_done( &font->charstrings_index );++ /* release font dictionaries, but only if working with */+ /* a CID keyed CFF font */+ if ( font->num_subfonts > 0 )+ {+ for ( idx = 0; idx < font->num_subfonts; idx++ )+ cff_subfont_done( memory, font->subfonts[idx] );++ /* the subfonts array has been allocated as a single block */+ FT_FREE( font->subfonts[0] );+ }++ cff_encoding_done( &font->encoding );+ cff_charset_done( &font->charset, font->stream );++ cff_subfont_done( memory, &font->top_font );++ CFF_Done_FD_Select( &font->fd_select, font->stream );++ FT_FREE( font->font_info );++ FT_FREE( font->font_name );+ FT_FREE( font->global_subrs );+ FT_FREE( font->strings );+ FT_FREE( font->string_pool );+ }+++/* END */
+ src/cff/cffload.h view
@@ -0,0 +1,83 @@+/***************************************************************************/+/* */+/* cffload.h */+/* */+/* OpenType & CFF data/program tables loader (specification). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2007, 2008, 2010 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 __CFFLOAD_H__+#define __CFFLOAD_H__+++#include <ft2build.h>+#include "cfftypes.h"+++FT_BEGIN_HEADER++ FT_LOCAL( FT_UShort )+ cff_get_standard_encoding( FT_UInt charcode );+++ FT_LOCAL( FT_String* )+ cff_index_get_string( CFF_Font font,+ FT_UInt element );++ FT_LOCAL( FT_String* )+ cff_index_get_sid_string( CFF_Font font,+ FT_UInt sid );+++ FT_LOCAL( FT_Error )+ cff_index_access_element( CFF_Index idx,+ FT_UInt element,+ FT_Byte** pbytes,+ FT_ULong* pbyte_len );++ FT_LOCAL( void )+ cff_index_forget_element( CFF_Index idx,+ FT_Byte** pbytes );++ FT_LOCAL( FT_String* )+ cff_index_get_name( CFF_Font font,+ FT_UInt element );+++ FT_LOCAL( FT_UInt )+ cff_charset_cid_to_gindex( CFF_Charset charset,+ FT_UInt cid );+++ FT_LOCAL( FT_Error )+ cff_font_load( FT_Library library, + FT_Stream stream,+ FT_Int face_index,+ CFF_Font font,+ FT_Bool pure_cff );++ FT_LOCAL( void )+ cff_font_done( CFF_Font font );+++ FT_LOCAL( FT_Byte )+ cff_fd_select_get( CFF_FDSelect fdselect,+ FT_UInt glyph_index );+++FT_END_HEADER++#endif /* __CFFLOAD_H__ */+++/* END */
+ src/cff/cffobjs.c view
@@ -0,0 +1,1008 @@+/***************************************************************************/+/* */+/* cffobjs.c */+/* */+/* OpenType objects manager (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */+/* 2010 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_CALC_H+#include FT_INTERNAL_STREAM_H+#include FT_ERRORS_H+#include FT_TRUETYPE_IDS_H+#include FT_TRUETYPE_TAGS_H+#include FT_INTERNAL_SFNT_H+#include "cffobjs.h"+#include "cffload.h"+#include "cffcmap.h"+#include "cfferrs.h"+#include "cffpic.h"+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_cffobjs+++ /*************************************************************************/+ /* */+ /* SIZE FUNCTIONS */+ /* */+ /* Note that we store the global hints in the size's `internal' root */+ /* field. */+ /* */+ /*************************************************************************/+++ static PSH_Globals_Funcs+ cff_size_get_globals_funcs( CFF_Size size )+ {+ CFF_Face face = (CFF_Face)size->root.face;+ CFF_Font font = (CFF_Font)face->extra.data;+ PSHinter_Service pshinter = font->pshinter;+ FT_Module module;+++ module = FT_Get_Module( size->root.face->driver->root.library,+ "pshinter" );+ return ( module && pshinter && pshinter->get_globals_funcs )+ ? pshinter->get_globals_funcs( module )+ : 0;+ }+++ FT_LOCAL_DEF( void )+ cff_size_done( FT_Size cffsize ) /* CFF_Size */+ {+ CFF_Size size = (CFF_Size)cffsize;+ CFF_Face face = (CFF_Face)size->root.face;+ CFF_Font font = (CFF_Font)face->extra.data;+ CFF_Internal internal = (CFF_Internal)cffsize->internal;+++ if ( internal )+ {+ PSH_Globals_Funcs funcs;+++ funcs = cff_size_get_globals_funcs( size );+ if ( funcs )+ {+ FT_UInt i;+++ funcs->destroy( internal->topfont );++ for ( i = font->num_subfonts; i > 0; i-- )+ funcs->destroy( internal->subfonts[i - 1] );+ }++ /* `internal' is freed by destroy_size (in ftobjs.c) */+ }+ }+++ /* CFF and Type 1 private dictionaries have slightly different */+ /* structures; we need to synthesize a Type 1 dictionary on the fly */++ static void+ cff_make_private_dict( CFF_SubFont subfont,+ PS_Private priv )+ {+ CFF_Private cpriv = &subfont->private_dict;+ FT_UInt n, count;+++ FT_MEM_ZERO( priv, sizeof ( *priv ) );++ count = priv->num_blue_values = cpriv->num_blue_values;+ for ( n = 0; n < count; n++ )+ priv->blue_values[n] = (FT_Short)cpriv->blue_values[n];++ count = priv->num_other_blues = cpriv->num_other_blues;+ for ( n = 0; n < count; n++ )+ priv->other_blues[n] = (FT_Short)cpriv->other_blues[n];++ count = priv->num_family_blues = cpriv->num_family_blues;+ for ( n = 0; n < count; n++ )+ priv->family_blues[n] = (FT_Short)cpriv->family_blues[n];++ count = priv->num_family_other_blues = cpriv->num_family_other_blues;+ for ( n = 0; n < count; n++ )+ priv->family_other_blues[n] = (FT_Short)cpriv->family_other_blues[n];++ priv->blue_scale = cpriv->blue_scale;+ priv->blue_shift = (FT_Int)cpriv->blue_shift;+ priv->blue_fuzz = (FT_Int)cpriv->blue_fuzz;++ priv->standard_width[0] = (FT_UShort)cpriv->standard_width;+ priv->standard_height[0] = (FT_UShort)cpriv->standard_height;++ count = priv->num_snap_widths = cpriv->num_snap_widths;+ for ( n = 0; n < count; n++ )+ priv->snap_widths[n] = (FT_Short)cpriv->snap_widths[n];++ count = priv->num_snap_heights = cpriv->num_snap_heights;+ for ( n = 0; n < count; n++ )+ priv->snap_heights[n] = (FT_Short)cpriv->snap_heights[n];++ priv->force_bold = cpriv->force_bold;+ priv->language_group = cpriv->language_group;+ priv->lenIV = cpriv->lenIV;+ }+++ FT_LOCAL_DEF( FT_Error )+ cff_size_init( FT_Size cffsize ) /* CFF_Size */+ {+ CFF_Size size = (CFF_Size)cffsize;+ FT_Error error = CFF_Err_Ok;+ PSH_Globals_Funcs funcs = cff_size_get_globals_funcs( size );+++ if ( funcs )+ {+ CFF_Face face = (CFF_Face)cffsize->face;+ CFF_Font font = (CFF_Font)face->extra.data;+ CFF_Internal internal;++ PS_PrivateRec priv;+ FT_Memory memory = cffsize->face->memory;++ FT_UInt i;+++ if ( FT_NEW( internal ) )+ goto Exit;++ cff_make_private_dict( &font->top_font, &priv );+ error = funcs->create( cffsize->face->memory, &priv,+ &internal->topfont );+ if ( error )+ goto Exit;++ for ( i = font->num_subfonts; i > 0; i-- )+ {+ CFF_SubFont sub = font->subfonts[i - 1];+++ cff_make_private_dict( sub, &priv );+ error = funcs->create( cffsize->face->memory, &priv,+ &internal->subfonts[i - 1] );+ if ( error )+ goto Exit;+ }++ cffsize->internal = (FT_Size_Internal)(void*)internal;+ }++ size->strike_index = 0xFFFFFFFFUL;++ Exit:+ return error;+ }+++#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS++ FT_LOCAL_DEF( FT_Error )+ cff_size_select( FT_Size size,+ FT_ULong strike_index )+ {+ CFF_Size cffsize = (CFF_Size)size;+ PSH_Globals_Funcs funcs;+++ cffsize->strike_index = strike_index;++ FT_Select_Metrics( size->face, strike_index );++ funcs = cff_size_get_globals_funcs( cffsize );++ if ( funcs )+ {+ CFF_Face face = (CFF_Face)size->face;+ CFF_Font font = (CFF_Font)face->extra.data;+ CFF_Internal internal = (CFF_Internal)size->internal;++ FT_ULong top_upm = font->top_font.font_dict.units_per_em;+ FT_UInt i;+++ funcs->set_scale( internal->topfont,+ size->metrics.x_scale, size->metrics.y_scale,+ 0, 0 );++ for ( i = font->num_subfonts; i > 0; i-- )+ {+ CFF_SubFont sub = font->subfonts[i - 1];+ FT_ULong sub_upm = sub->font_dict.units_per_em;+ FT_Pos x_scale, y_scale;+++ if ( top_upm != sub_upm )+ {+ x_scale = FT_MulDiv( size->metrics.x_scale, top_upm, sub_upm );+ y_scale = FT_MulDiv( size->metrics.y_scale, top_upm, sub_upm );+ }+ else+ {+ x_scale = size->metrics.x_scale;+ y_scale = size->metrics.y_scale;+ }++ funcs->set_scale( internal->subfonts[i - 1],+ x_scale, y_scale, 0, 0 );+ }+ }++ return CFF_Err_Ok;+ }++#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */+++ FT_LOCAL_DEF( FT_Error )+ cff_size_request( FT_Size size,+ FT_Size_Request req )+ {+ CFF_Size cffsize = (CFF_Size)size;+ PSH_Globals_Funcs funcs;+++#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS++ if ( FT_HAS_FIXED_SIZES( size->face ) )+ {+ CFF_Face cffface = (CFF_Face)size->face;+ SFNT_Service sfnt = (SFNT_Service)cffface->sfnt;+ FT_ULong strike_index;+++ if ( sfnt->set_sbit_strike( cffface, req, &strike_index ) )+ cffsize->strike_index = 0xFFFFFFFFUL;+ else+ return cff_size_select( size, strike_index );+ }++#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */++ FT_Request_Metrics( size->face, req );++ funcs = cff_size_get_globals_funcs( cffsize );++ if ( funcs )+ {+ CFF_Face cffface = (CFF_Face)size->face;+ CFF_Font font = (CFF_Font)cffface->extra.data;+ CFF_Internal internal = (CFF_Internal)size->internal;++ FT_ULong top_upm = font->top_font.font_dict.units_per_em;+ FT_UInt i;+++ funcs->set_scale( internal->topfont,+ size->metrics.x_scale, size->metrics.y_scale,+ 0, 0 );++ for ( i = font->num_subfonts; i > 0; i-- )+ {+ CFF_SubFont sub = font->subfonts[i - 1];+ FT_ULong sub_upm = sub->font_dict.units_per_em;+ FT_Pos x_scale, y_scale;+++ if ( top_upm != sub_upm )+ {+ x_scale = FT_MulDiv( size->metrics.x_scale, top_upm, sub_upm );+ y_scale = FT_MulDiv( size->metrics.y_scale, top_upm, sub_upm );+ }+ else+ {+ x_scale = size->metrics.x_scale;+ y_scale = size->metrics.y_scale;+ }++ funcs->set_scale( internal->subfonts[i - 1],+ x_scale, y_scale, 0, 0 );+ }+ }++ return CFF_Err_Ok;+ }+++ /*************************************************************************/+ /* */+ /* SLOT FUNCTIONS */+ /* */+ /*************************************************************************/++ FT_LOCAL_DEF( void )+ cff_slot_done( FT_GlyphSlot slot )+ {+ slot->internal->glyph_hints = 0;+ }+++ FT_LOCAL_DEF( FT_Error )+ cff_slot_init( FT_GlyphSlot slot )+ {+ CFF_Face face = (CFF_Face)slot->face;+ CFF_Font font = (CFF_Font)face->extra.data;+ PSHinter_Service pshinter = font->pshinter;+++ if ( pshinter )+ {+ FT_Module module;+++ module = FT_Get_Module( slot->face->driver->root.library,+ "pshinter" );+ if ( module )+ {+ T2_Hints_Funcs funcs;+++ funcs = pshinter->get_t2_funcs( module );+ slot->internal->glyph_hints = (void*)funcs;+ }+ }++ return CFF_Err_Ok;+ }+++ /*************************************************************************/+ /* */+ /* FACE FUNCTIONS */+ /* */+ /*************************************************************************/++ static FT_String*+ cff_strcpy( FT_Memory memory,+ const FT_String* source )+ {+ FT_Error error;+ FT_String* result;+++ (void)FT_STRDUP( result, source );++ FT_UNUSED( error );++ return result;+ }+++ /* Strip all subset prefixes of the form `ABCDEF+'. Usually, there */+ /* is only one, but font names like `APCOOG+JFABTD+FuturaBQ-Bold' */+ /* have been seen in the wild. */++ static void+ remove_subset_prefix( FT_String* name )+ {+ FT_Int32 idx = 0;+ FT_Int32 length = strlen( name ) + 1;+ FT_Bool continue_search = 1;+ ++ while ( continue_search )+ {+ if ( length >= 7 && name[6] == '+' )+ {+ for ( idx = 0; idx < 6; idx++ )+ {+ /* ASCII uppercase letters */+ if ( !( 'A' <= name[idx] && name[idx] <= 'Z' ) )+ continue_search = 0;+ }++ if ( continue_search )+ {+ for ( idx = 7; idx < length; idx++ )+ name[idx - 7] = name[idx];+ }+ }+ else+ continue_search = 0;+ }+ }+++ FT_LOCAL_DEF( FT_Error )+ cff_face_init( FT_Stream stream,+ FT_Face cffface, /* CFF_Face */+ FT_Int face_index,+ FT_Int num_params,+ FT_Parameter* params )+ {+ CFF_Face face = (CFF_Face)cffface;+ FT_Error error;+ SFNT_Service sfnt;+ FT_Service_PsCMaps psnames;+ PSHinter_Service pshinter;+ FT_Bool pure_cff = 1;+ FT_Bool sfnt_format = 0;+ FT_Library library = cffface->driver->root.library;+++ sfnt = (SFNT_Service)FT_Get_Module_Interface(+ library, "sfnt" );+ if ( !sfnt )+ goto Bad_Format;++ FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );++ pshinter = (PSHinter_Service)FT_Get_Module_Interface(+ library, "pshinter" );++ /* create input stream from resource */+ if ( FT_STREAM_SEEK( 0 ) )+ goto Exit;++ /* check whether we have a valid OpenType file */+ error = sfnt->init_face( stream, face, face_index, num_params, params );+ if ( !error )+ {+ if ( face->format_tag != TTAG_OTTO ) /* `OTTO'; OpenType/CFF font */+ {+ FT_TRACE2(( "[not a valid OpenType/CFF font]\n" ));+ goto Bad_Format;+ }++ /* if we are performing a simple font format check, exit immediately */+ if ( face_index < 0 )+ return CFF_Err_Ok;++ /* UNDOCUMENTED! A CFF in an SFNT can have only a single font. */+ if ( face_index > 0 )+ {+ FT_ERROR(( "cff_face_init: invalid face index\n" ));+ error = CFF_Err_Invalid_Argument;+ goto Exit;+ }++ sfnt_format = 1;++ /* now, the font can be either an OpenType/CFF font, or an SVG CEF */+ /* font; in the latter case it doesn't have a `head' table */+ error = face->goto_table( face, TTAG_head, stream, 0 );+ if ( !error )+ {+ pure_cff = 0;++ /* load font directory */+ error = sfnt->load_face( stream, face, 0, num_params, params );+ if ( error )+ goto Exit;+ }+ else+ {+ /* load the `cmap' table explicitly */+ error = sfnt->load_cmap( face, stream );+ if ( error )+ goto Exit;++ /* XXX: we don't load the GPOS table, as OpenType Layout */+ /* support will be added later to a layout library on top of */+ /* FreeType 2 */+ }++ /* now load the CFF part of the file */+ error = face->goto_table( face, TTAG_CFF, stream, 0 );+ if ( error )+ goto Exit;+ }+ else+ {+ /* rewind to start of file; we are going to load a pure-CFF font */+ if ( FT_STREAM_SEEK( 0 ) )+ goto Exit;+ error = CFF_Err_Ok;+ }++ /* now load and parse the CFF table in the file */+ {+ CFF_Font cff;+ CFF_FontRecDict dict;+ FT_Memory memory = cffface->memory;+ FT_Int32 flags;+ FT_UInt i;+++ if ( FT_NEW( cff ) )+ goto Exit;++ face->extra.data = cff;+ error = cff_font_load( library, stream, face_index, cff, pure_cff );+ if ( error )+ goto Exit;++ cff->pshinter = pshinter;+ cff->psnames = psnames;++ cffface->face_index = face_index;++ /* Complement the root flags with some interesting information. */+ /* Note that this is only necessary for pure CFF and CEF fonts; */+ /* SFNT based fonts use the `name' table instead. */++ cffface->num_glyphs = cff->num_glyphs;++ dict = &cff->top_font.font_dict;++ /* we need the `PSNames' module for CFF and CEF formats */+ /* which aren't CID-keyed */+ if ( dict->cid_registry == 0xFFFFU && !psnames )+ {+ FT_ERROR(( "cff_face_init:"+ " cannot open CFF & CEF fonts\n"+ " "+ " without the `PSNames' module\n" ));+ goto Bad_Format;+ }++ if ( !dict->units_per_em )+ dict->units_per_em = pure_cff ? 1000 : face->root.units_per_EM;++ /* Normalize the font matrix so that `matrix->xx' 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). */+ /* */+ /* Note that the offsets must be expressed in integer font */+ /* units. */++ {+ FT_Matrix* matrix = &dict->font_matrix;+ FT_Vector* offset = &dict->font_offset;+ FT_ULong* upm = &dict->units_per_em;+ FT_Fixed temp = FT_ABS( matrix->yy );+++ if ( temp != 0x10000L )+ {+ *upm = FT_DivFix( *upm, temp );++ matrix->xx = FT_DivFix( matrix->xx, temp );+ matrix->yx = FT_DivFix( matrix->yx, temp );+ matrix->xy = FT_DivFix( matrix->xy, temp );+ matrix->yy = FT_DivFix( matrix->yy, temp );+ offset->x = FT_DivFix( offset->x, temp );+ offset->y = FT_DivFix( offset->y, temp );+ }++ offset->x >>= 16;+ offset->y >>= 16;+ }++ for ( i = cff->num_subfonts; i > 0; i-- )+ {+ CFF_FontRecDict sub = &cff->subfonts[i - 1]->font_dict;+ CFF_FontRecDict top = &cff->top_font.font_dict;++ FT_Matrix* matrix;+ FT_Vector* offset;+ FT_ULong* upm;+ FT_Fixed temp;+++ if ( sub->units_per_em )+ {+ FT_Long scaling;+++ if ( top->units_per_em > 1 && sub->units_per_em > 1 )+ scaling = FT_MIN( top->units_per_em, sub->units_per_em );+ else+ scaling = 1;++ FT_Matrix_Multiply_Scaled( &top->font_matrix,+ &sub->font_matrix,+ scaling );+ FT_Vector_Transform_Scaled( &sub->font_offset,+ &top->font_matrix,+ scaling );++ sub->units_per_em = FT_MulDiv( sub->units_per_em,+ top->units_per_em,+ scaling );+ }+ else+ {+ sub->font_matrix = top->font_matrix;+ sub->font_offset = top->font_offset;++ sub->units_per_em = top->units_per_em;+ }++ matrix = &sub->font_matrix;+ offset = &sub->font_offset;+ upm = &sub->units_per_em;+ temp = FT_ABS( matrix->yy );++ if ( temp != 0x10000L )+ {+ *upm = FT_DivFix( *upm, temp );++ /* if *upm is larger than 100*1000 we divide by 1000 -- */+ /* this can happen if e.g. there is no top-font FontMatrix */+ /* and the subfont FontMatrix already contains the complete */+ /* scaling for the subfont (see section 5.11 of the PLRM) */++ /* 100 is a heuristic value */++ if ( *upm > 100L * 1000L )+ *upm = ( *upm + 500 ) / 1000;++ matrix->xx = FT_DivFix( matrix->xx, temp );+ matrix->yx = FT_DivFix( matrix->yx, temp );+ matrix->xy = FT_DivFix( matrix->xy, temp );+ matrix->yy = FT_DivFix( matrix->yy, temp );+ offset->x = FT_DivFix( offset->x, temp );+ offset->y = FT_DivFix( offset->y, temp );+ }++ offset->x >>= 16;+ offset->y >>= 16;+ }++ if ( pure_cff )+ {+ char* style_name = NULL;+++ /* set up num_faces */+ cffface->num_faces = cff->num_faces;++ /* compute number of glyphs */+ if ( dict->cid_registry != 0xFFFFU )+ cffface->num_glyphs = cff->charset.max_cid + 1;+ else+ cffface->num_glyphs = cff->charstrings_index.count;++ /* set global bbox, as well as EM size */+ cffface->bbox.xMin = dict->font_bbox.xMin >> 16;+ cffface->bbox.yMin = dict->font_bbox.yMin >> 16;+ /* no `U' suffix here to 0xFFFF! */+ cffface->bbox.xMax = ( dict->font_bbox.xMax + 0xFFFF ) >> 16;+ cffface->bbox.yMax = ( dict->font_bbox.yMax + 0xFFFF ) >> 16;++ cffface->units_per_EM = (FT_UShort)( dict->units_per_em );++ cffface->ascender = (FT_Short)( cffface->bbox.yMax );+ cffface->descender = (FT_Short)( cffface->bbox.yMin );++ cffface->height = (FT_Short)( ( cffface->units_per_EM * 12 ) / 10 );+ if ( cffface->height < cffface->ascender - cffface->descender )+ cffface->height = (FT_Short)( cffface->ascender - cffface->descender );++ cffface->underline_position =+ (FT_Short)( dict->underline_position >> 16 );+ cffface->underline_thickness =+ (FT_Short)( dict->underline_thickness >> 16 );++ /* retrieve font family & style name */+ cffface->family_name = cff_index_get_name( cff, face_index );+ if ( cffface->family_name )+ {+ char* full = cff_index_get_sid_string( cff,+ dict->full_name );+ char* fullp = full;+ char* family = cffface->family_name;+ char* family_name = NULL;+++ remove_subset_prefix( cffface->family_name ); ++ if ( dict->family_name )+ {+ family_name = cff_index_get_sid_string( cff,+ dict->family_name );+ if ( family_name )+ family = family_name;+ }++ /* We try to extract the style name from the full name. */+ /* We need to ignore spaces and dashes during the search. */+ if ( full && family )+ {+ while ( *fullp )+ {+ /* skip common characters at the start of both strings */+ if ( *fullp == *family )+ {+ family++;+ fullp++;+ continue;+ }++ /* ignore spaces and dashes in full name during comparison */+ if ( *fullp == ' ' || *fullp == '-' )+ {+ fullp++;+ continue;+ }++ /* ignore spaces and dashes in family name during comparison */+ if ( *family == ' ' || *family == '-' )+ {+ family++;+ continue;+ }++ if ( !*family && *fullp )+ {+ /* The full name begins with the same characters as the */+ /* family name, with spaces and dashes removed. In this */+ /* case, the remaining string in `fullp' will be used as */+ /* the style name. */+ style_name = cff_strcpy( memory, fullp );+ }+ break;+ }+ }+ }+ else+ {+ char *cid_font_name =+ cff_index_get_sid_string( cff,+ dict->cid_font_name );+++ /* do we have a `/FontName' for a CID-keyed font? */+ if ( cid_font_name )+ cffface->family_name = cff_strcpy( memory, cid_font_name );+ }++ if ( style_name )+ cffface->style_name = style_name;+ else+ /* assume "Regular" style if we don't know better */+ cffface->style_name = cff_strcpy( memory, (char *)"Regular" );++ /*******************************************************************/+ /* */+ /* Compute face flags. */+ /* */+ flags = (FT_UInt32)( FT_FACE_FLAG_SCALABLE | /* scalable outlines */+ FT_FACE_FLAG_HORIZONTAL | /* horizontal data */+ FT_FACE_FLAG_HINTER ); /* has native hinter */++ if ( sfnt_format )+ flags |= (FT_UInt32)FT_FACE_FLAG_SFNT;++ /* fixed width font? */+ if ( dict->is_fixed_pitch )+ flags |= (FT_UInt32)FT_FACE_FLAG_FIXED_WIDTH;++ /* XXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */+#if 0+ /* kerning available? */+ if ( face->kern_pairs )+ flags |= (FT_UInt32)FT_FACE_FLAG_KERNING;+#endif++ cffface->face_flags = flags;++ /*******************************************************************/+ /* */+ /* Compute style flags. */+ /* */+ flags = 0;++ if ( dict->italic_angle )+ flags |= FT_STYLE_FLAG_ITALIC;++ {+ char *weight = cff_index_get_sid_string( cff,+ dict->weight );+++ if ( weight )+ if ( !ft_strcmp( weight, "Bold" ) ||+ !ft_strcmp( weight, "Black" ) )+ flags |= FT_STYLE_FLAG_BOLD;+ }++ /* double check */+ if ( !(flags & FT_STYLE_FLAG_BOLD) && cffface->style_name )+ if ( !ft_strncmp( cffface->style_name, "Bold", 4 ) ||+ !ft_strncmp( cffface->style_name, "Black", 5 ) )+ flags |= FT_STYLE_FLAG_BOLD;++ cffface->style_flags = flags;+ }+++#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES+ /* CID-keyed CFF fonts don't have glyph names -- the SFNT loader */+ /* has unset this flag because of the 3.0 `post' table. */+ if ( dict->cid_registry == 0xFFFFU )+ cffface->face_flags |= FT_FACE_FLAG_GLYPH_NAMES;+#endif++ if ( dict->cid_registry != 0xFFFFU && pure_cff )+ cffface->face_flags |= FT_FACE_FLAG_CID_KEYED;+++ /*******************************************************************/+ /* */+ /* Compute char maps. */+ /* */++ /* Try to synthesize a Unicode charmap if there is none available */+ /* already. If an OpenType font contains a Unicode "cmap", we */+ /* will use it, whatever be in the CFF part of the file. */+ {+ FT_CharMapRec cmaprec;+ FT_CharMap cmap;+ FT_UInt nn;+ CFF_Encoding encoding = &cff->encoding;+++ for ( nn = 0; nn < (FT_UInt)cffface->num_charmaps; nn++ )+ {+ cmap = cffface->charmaps[nn];++ /* Windows Unicode? */+ if ( cmap->platform_id == TT_PLATFORM_MICROSOFT &&+ cmap->encoding_id == TT_MS_ID_UNICODE_CS )+ goto Skip_Unicode;++ /* Apple Unicode platform id? */+ if ( cmap->platform_id == TT_PLATFORM_APPLE_UNICODE )+ goto Skip_Unicode; /* Apple Unicode */+ }++ /* since CID-keyed fonts don't contain glyph names, we can't */+ /* construct a cmap */+ if ( pure_cff && cff->top_font.font_dict.cid_registry != 0xFFFFU )+ goto Exit;++#ifdef FT_MAX_CHARMAP_CACHEABLE+ if ( nn + 1 > FT_MAX_CHARMAP_CACHEABLE )+ {+ FT_ERROR(( "cff_face_init: no Unicode cmap is found, "+ "and too many subtables (%d) to add synthesized cmap\n",+ nn ));+ goto Exit;+ }+#endif++ /* we didn't find a Unicode charmap -- synthesize one */+ cmaprec.face = cffface;+ cmaprec.platform_id = TT_PLATFORM_MICROSOFT;+ cmaprec.encoding_id = TT_MS_ID_UNICODE_CS;+ cmaprec.encoding = FT_ENCODING_UNICODE;++ nn = (FT_UInt)cffface->num_charmaps;++ error = FT_CMap_New( &FT_CFF_CMAP_UNICODE_CLASS_REC_GET, NULL,+ &cmaprec, NULL );+ if ( error && FT_Err_No_Unicode_Glyph_Name != error )+ goto Exit;+ error = FT_Err_Ok;++ /* if no Unicode charmap was previously selected, select this one */+ if ( cffface->charmap == NULL && nn != (FT_UInt)cffface->num_charmaps )+ cffface->charmap = cffface->charmaps[nn];++ Skip_Unicode:+#ifdef FT_MAX_CHARMAP_CACHEABLE+ if ( nn > FT_MAX_CHARMAP_CACHEABLE )+ {+ FT_ERROR(( "cff_face_init: Unicode cmap is found, "+ "but too many preceding subtables (%d) to access\n",+ nn - 1 ));+ goto Exit;+ }+#endif+ if ( encoding->count > 0 )+ {+ FT_CMap_Class clazz;+++ cmaprec.face = cffface;+ cmaprec.platform_id = TT_PLATFORM_ADOBE; /* Adobe platform id */++ if ( encoding->offset == 0 )+ {+ cmaprec.encoding_id = TT_ADOBE_ID_STANDARD;+ cmaprec.encoding = FT_ENCODING_ADOBE_STANDARD;+ clazz = &FT_CFF_CMAP_ENCODING_CLASS_REC_GET;+ }+ else if ( encoding->offset == 1 )+ {+ cmaprec.encoding_id = TT_ADOBE_ID_EXPERT;+ cmaprec.encoding = FT_ENCODING_ADOBE_EXPERT;+ clazz = &FT_CFF_CMAP_ENCODING_CLASS_REC_GET;+ }+ else+ {+ cmaprec.encoding_id = TT_ADOBE_ID_CUSTOM;+ cmaprec.encoding = FT_ENCODING_ADOBE_CUSTOM;+ clazz = &FT_CFF_CMAP_ENCODING_CLASS_REC_GET;+ }++ error = FT_CMap_New( clazz, NULL, &cmaprec, NULL );+ }+ }+ }++ Exit:+ return error;++ Bad_Format:+ error = CFF_Err_Unknown_File_Format;+ goto Exit;+ }+++ FT_LOCAL_DEF( void )+ cff_face_done( FT_Face cffface ) /* CFF_Face */+ {+ CFF_Face face = (CFF_Face)cffface;+ FT_Memory memory;+ SFNT_Service sfnt;+++ if ( !face )+ return;++ memory = cffface->memory;+ sfnt = (SFNT_Service)face->sfnt;++ if ( sfnt )+ sfnt->done_face( face );++ {+ CFF_Font cff = (CFF_Font)face->extra.data;+++ if ( cff )+ {+ cff_font_done( cff );+ FT_FREE( face->extra.data );+ }+ }+ }+++ FT_LOCAL_DEF( FT_Error )+ cff_driver_init( FT_Module module )+ {+ FT_UNUSED( module );++ return CFF_Err_Ok;+ }+++ FT_LOCAL_DEF( void )+ cff_driver_done( FT_Module module )+ {+ FT_UNUSED( module );+ }+++/* END */
+ src/cff/cffobjs.h view
@@ -0,0 +1,181 @@+/***************************************************************************/+/* */+/* cffobjs.h */+/* */+/* OpenType objects manager (specification). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007, 2008 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 __CFFOBJS_H__+#define __CFFOBJS_H__+++#include <ft2build.h>+#include FT_INTERNAL_OBJECTS_H+#include "cfftypes.h"+#include FT_INTERNAL_TRUETYPE_TYPES_H+#include FT_SERVICE_POSTSCRIPT_CMAPS_H+#include FT_INTERNAL_POSTSCRIPT_HINTS_H+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* CFF_Driver */+ /* */+ /* <Description> */+ /* A handle to an OpenType driver object. */+ /* */+ typedef struct CFF_DriverRec_* CFF_Driver;++ typedef TT_Face CFF_Face;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* CFF_Size */+ /* */+ /* <Description> */+ /* A handle to an OpenType size object. */+ /* */+ typedef struct CFF_SizeRec_+ {+ FT_SizeRec root;+ FT_ULong strike_index; /* 0xFFFFFFFF to indicate invalid */++ } CFF_SizeRec, *CFF_Size;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* CFF_GlyphSlot */+ /* */+ /* <Description> */+ /* A handle to an OpenType glyph slot object. */+ /* */+ typedef struct CFF_GlyphSlotRec_+ {+ FT_GlyphSlotRec root;++ FT_Bool hint;+ FT_Bool scaled;++ FT_Fixed x_scale;+ FT_Fixed y_scale;++ } CFF_GlyphSlotRec, *CFF_GlyphSlot;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* CFF_Internal */+ /* */+ /* <Description> */+ /* The interface to the `internal' field of `FT_Size'. */+ /* */+ typedef struct CFF_InternalRec_+ {+ PSH_Globals topfont;+ PSH_Globals subfonts[CFF_MAX_CID_FONTS];++ } CFF_InternalRec, *CFF_Internal;+++ /*************************************************************************/+ /* */+ /* Subglyph transformation record. */+ /* */+ typedef struct CFF_Transform_+ {+ FT_Fixed xx, xy; /* transformation matrix coefficients */+ FT_Fixed yx, yy;+ FT_F26Dot6 ox, oy; /* offsets */++ } CFF_Transform;+++ /***********************************************************************/+ /* */+ /* TrueType driver class. */+ /* */+ typedef struct CFF_DriverRec_+ {+ FT_DriverRec root;+ void* extension_component;++ } CFF_DriverRec;+++ FT_LOCAL( FT_Error )+ cff_size_init( FT_Size size ); /* CFF_Size */++ FT_LOCAL( void )+ cff_size_done( FT_Size size ); /* CFF_Size */++ FT_LOCAL( FT_Error )+ cff_size_request( FT_Size size,+ FT_Size_Request req );++#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS++ FT_LOCAL( FT_Error )+ cff_size_select( FT_Size size,+ FT_ULong strike_index );++#endif++ FT_LOCAL( void )+ cff_slot_done( FT_GlyphSlot slot );++ FT_LOCAL( FT_Error )+ cff_slot_init( FT_GlyphSlot slot );+++ /*************************************************************************/+ /* */+ /* Face functions */+ /* */+ FT_LOCAL( FT_Error )+ cff_face_init( FT_Stream stream,+ FT_Face face, /* CFF_Face */+ FT_Int face_index,+ FT_Int num_params,+ FT_Parameter* params );++ FT_LOCAL( void )+ cff_face_done( FT_Face face ); /* CFF_Face */+++ /*************************************************************************/+ /* */+ /* Driver functions */+ /* */+ FT_LOCAL( FT_Error )+ cff_driver_init( FT_Module module );++ FT_LOCAL( void )+ cff_driver_done( FT_Module module );+++FT_END_HEADER++#endif /* __CFFOBJS_H__ */+++/* END */
+ src/cff/cffparse.c view
@@ -0,0 +1,924 @@+/***************************************************************************/+/* */+/* cffparse.c */+/* */+/* CFF token stream parser (body) */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2007, 2008, 2009, 2010 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 "cffparse.h"+#include FT_INTERNAL_STREAM_H+#include FT_INTERNAL_DEBUG_H++#include "cfferrs.h"+#include "cffpic.h"+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_cffparse+++++ FT_LOCAL_DEF( void )+ cff_parser_init( CFF_Parser parser,+ FT_UInt code,+ void* object,+ FT_Library library)+ {+ FT_MEM_ZERO( parser, sizeof ( *parser ) );++ parser->top = parser->stack;+ parser->object_code = code;+ parser->object = object;+ parser->library = library;+ }+++ /* read an integer */+ static FT_Long+ cff_parse_integer( FT_Byte* start,+ FT_Byte* limit )+ {+ FT_Byte* p = start;+ FT_Int v = *p++;+ FT_Long val = 0;+++ if ( v == 28 )+ {+ if ( p + 2 > limit )+ goto Bad;++ val = (FT_Short)( ( (FT_Int)p[0] << 8 ) | p[1] );+ p += 2;+ }+ else if ( v == 29 )+ {+ if ( p + 4 > limit )+ goto Bad;++ val = ( (FT_Long)p[0] << 24 ) |+ ( (FT_Long)p[1] << 16 ) |+ ( (FT_Long)p[2] << 8 ) |+ p[3];+ p += 4;+ }+ else if ( v < 247 )+ {+ val = v - 139;+ }+ else if ( v < 251 )+ {+ if ( p + 1 > limit )+ goto Bad;++ val = ( v - 247 ) * 256 + p[0] + 108;+ p++;+ }+ else+ {+ if ( p + 1 > limit )+ goto Bad;++ val = -( v - 251 ) * 256 - p[0] - 108;+ p++;+ }++ Exit:+ return val;++ Bad:+ val = 0;+ goto Exit;+ }+++ static const FT_Long power_tens[] =+ {+ 1L,+ 10L,+ 100L,+ 1000L,+ 10000L,+ 100000L,+ 1000000L,+ 10000000L,+ 100000000L,+ 1000000000L+ };+++ /* read a real */+ static FT_Fixed+ cff_parse_real( FT_Byte* start,+ FT_Byte* limit,+ FT_Long power_ten,+ FT_Long* scaling )+ {+ FT_Byte* p = start;+ FT_UInt nib;+ FT_UInt phase;++ FT_Long result, number, exponent;+ FT_Int sign = 0, exponent_sign = 0;+ FT_Long exponent_add, integer_length, fraction_length;+++ if ( scaling )+ *scaling = 0;++ result = 0;++ number = 0;+ exponent = 0;++ exponent_add = 0;+ integer_length = 0;+ fraction_length = 0;++ /* First of all, read the integer part. */+ phase = 4;++ for (;;)+ {+ /* If we entered this iteration with phase == 4, we need to */+ /* read a new byte. This also skips past the initial 0x1E. */+ if ( phase )+ {+ p++;++ /* Make sure we don't read past the end. */+ if ( p >= limit )+ goto Exit;+ }++ /* Get the nibble. */+ nib = ( p[0] >> phase ) & 0xF;+ phase = 4 - phase;++ if ( nib == 0xE )+ sign = 1;+ else if ( nib > 9 )+ break;+ else+ {+ /* Increase exponent if we can't add the digit. */+ if ( number >= 0xCCCCCCCL )+ exponent_add++;+ /* Skip leading zeros. */+ else if ( nib || number )+ {+ integer_length++;+ number = number * 10 + nib;+ }+ }+ }++ /* Read fraction part, if any. */+ if ( nib == 0xa )+ for (;;)+ {+ /* If we entered this iteration with phase == 4, we need */+ /* to read a new byte. */+ if ( phase )+ {+ p++;++ /* Make sure we don't read past the end. */+ if ( p >= limit )+ goto Exit;+ }++ /* Get the nibble. */+ nib = ( p[0] >> phase ) & 0xF;+ phase = 4 - phase;+ if ( nib >= 10 )+ break;++ /* Skip leading zeros if possible. */+ if ( !nib && !number )+ exponent_add--;+ /* Only add digit if we don't overflow. */+ else if ( number < 0xCCCCCCCL && fraction_length < 9 )+ {+ fraction_length++;+ number = number * 10 + nib;+ }+ }++ /* Read exponent, if any. */+ if ( nib == 12 )+ {+ exponent_sign = 1;+ nib = 11;+ }++ if ( nib == 11 )+ {+ for (;;)+ {+ /* If we entered this iteration with phase == 4, */+ /* we need to read a new byte. */+ if ( phase )+ {+ p++;++ /* Make sure we don't read past the end. */+ if ( p >= limit )+ goto Exit;+ }++ /* Get the nibble. */+ nib = ( p[0] >> phase ) & 0xF;+ phase = 4 - phase;+ if ( nib >= 10 )+ break;++ exponent = exponent * 10 + nib;++ /* Arbitrarily limit exponent. */+ if ( exponent > 1000 )+ goto Exit;+ }++ if ( exponent_sign )+ exponent = -exponent;+ }++ /* We don't check `power_ten' and `exponent_add'. */+ exponent += power_ten + exponent_add;++ if ( scaling )+ {+ /* Only use `fraction_length'. */+ fraction_length += integer_length;+ exponent += integer_length;++ if ( fraction_length <= 5 )+ {+ if ( number > 0x7FFFL )+ {+ result = FT_DivFix( number, 10 );+ *scaling = exponent - fraction_length + 1;+ }+ else+ {+ if ( exponent > 0 )+ {+ FT_Long new_fraction_length, shift;+++ /* Make `scaling' as small as possible. */+ new_fraction_length = FT_MIN( exponent, 5 );+ exponent -= new_fraction_length;+ shift = new_fraction_length - fraction_length;++ number *= power_tens[shift];+ if ( number > 0x7FFFL )+ {+ number /= 10;+ exponent += 1;+ }+ }+ else+ exponent -= fraction_length;++ result = number << 16;+ *scaling = exponent;+ }+ }+ else+ {+ if ( ( number / power_tens[fraction_length - 5] ) > 0x7FFFL )+ {+ result = FT_DivFix( number, power_tens[fraction_length - 4] );+ *scaling = exponent - 4;+ }+ else+ {+ result = FT_DivFix( number, power_tens[fraction_length - 5] );+ *scaling = exponent - 5;+ }+ }+ }+ else+ {+ integer_length += exponent;+ fraction_length -= exponent;++ /* Check for overflow and underflow. */+ if ( FT_ABS( integer_length ) > 5 )+ goto Exit;++ /* Remove non-significant digits. */+ if ( integer_length < 0 )+ {+ number /= power_tens[-integer_length];+ fraction_length += integer_length;+ }++ /* this can only happen if exponent was non-zero */+ if ( fraction_length == 10 )+ {+ number /= 10;+ fraction_length -= 1;+ }++ /* Convert into 16.16 format. */+ if ( fraction_length > 0 )+ {+ if ( ( number / power_tens[fraction_length] ) > 0x7FFFL )+ goto Exit;++ result = FT_DivFix( number, power_tens[fraction_length] );+ }+ else+ {+ number *= power_tens[-fraction_length];++ if ( number > 0x7FFFL )+ goto Exit;++ result = number << 16;+ }+ }++ if ( sign )+ result = -result;++ Exit:+ return result;+ }+++ /* read a number, either integer or real */+ static FT_Long+ cff_parse_num( FT_Byte** d )+ {+ return **d == 30 ? ( cff_parse_real( d[0], d[1], 0, NULL ) >> 16 )+ : cff_parse_integer( d[0], d[1] );+ }+++ /* read a floating point number, either integer or real */+ static FT_Fixed+ cff_parse_fixed( FT_Byte** d )+ {+ return **d == 30 ? cff_parse_real( d[0], d[1], 0, NULL )+ : cff_parse_integer( d[0], d[1] ) << 16;+ }+++ /* read a floating point number, either integer or real, */+ /* but return `10^scaling' times the number read in */+ static FT_Fixed+ cff_parse_fixed_scaled( FT_Byte** d,+ FT_Long scaling )+ {+ return **d == 30 ? cff_parse_real( d[0], d[1], scaling, NULL )+ : ( cff_parse_integer( d[0], d[1] ) *+ power_tens[scaling] ) << 16;+ }+++ /* read a floating point number, either integer or real, */+ /* and return it as precise as possible -- `scaling' returns */+ /* the scaling factor (as a power of 10) */+ static FT_Fixed+ cff_parse_fixed_dynamic( FT_Byte** d,+ FT_Long* scaling )+ {+ FT_ASSERT( scaling );++ if ( **d == 30 )+ return cff_parse_real( d[0], d[1], 0, scaling );+ else+ {+ FT_Long number;+ FT_Int integer_length;+++ number = cff_parse_integer( d[0], d[1] );++ if ( number > 0x7FFFL )+ {+ for ( integer_length = 5; integer_length < 10; integer_length++ )+ if ( number < power_tens[integer_length] )+ break;++ if ( ( number / power_tens[integer_length - 5] ) > 0x7FFFL )+ {+ *scaling = integer_length - 4;+ return FT_DivFix( number, power_tens[integer_length - 4] );+ }+ else+ {+ *scaling = integer_length - 5;+ return FT_DivFix( number, power_tens[integer_length - 5] );+ }+ }+ else+ {+ *scaling = 0;+ return number << 16;+ }+ }+ }+++ static FT_Error+ cff_parse_font_matrix( CFF_Parser parser )+ {+ CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;+ FT_Matrix* matrix = &dict->font_matrix;+ FT_Vector* offset = &dict->font_offset;+ FT_ULong* upm = &dict->units_per_em;+ FT_Byte** data = parser->stack;+ FT_Error error = CFF_Err_Stack_Underflow;+++ if ( parser->top >= parser->stack + 6 )+ {+ FT_Long scaling;+++ error = CFF_Err_Ok;++ /* We expect a well-formed font matrix, this is, the matrix elements */+ /* `xx' and `yy' are of approximately the same magnitude. To avoid */+ /* loss of precision, we use the magnitude of element `xx' to scale */+ /* all other elements. The scaling factor is then contained in the */+ /* `units_per_em' value. */++ matrix->xx = cff_parse_fixed_dynamic( data++, &scaling );++ scaling = -scaling;++ if ( scaling < 0 || scaling > 9 )+ {+ /* Return default matrix in case of unlikely values. */+ matrix->xx = 0x10000L;+ matrix->yx = 0;+ matrix->yx = 0;+ matrix->yy = 0x10000L;+ offset->x = 0;+ offset->y = 0;+ *upm = 1;++ goto Exit;+ }++ matrix->yx = cff_parse_fixed_scaled( data++, scaling );+ matrix->xy = cff_parse_fixed_scaled( data++, scaling );+ matrix->yy = cff_parse_fixed_scaled( data++, scaling );+ offset->x = cff_parse_fixed_scaled( data++, scaling );+ offset->y = cff_parse_fixed_scaled( data, scaling );++ *upm = power_tens[scaling];+ }++ Exit:+ return error;+ }+++ static FT_Error+ cff_parse_font_bbox( CFF_Parser parser )+ {+ CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;+ FT_BBox* bbox = &dict->font_bbox;+ FT_Byte** data = parser->stack;+ FT_Error error;+++ error = CFF_Err_Stack_Underflow;++ if ( parser->top >= parser->stack + 4 )+ {+ bbox->xMin = FT_RoundFix( cff_parse_fixed( data++ ) );+ bbox->yMin = FT_RoundFix( cff_parse_fixed( data++ ) );+ bbox->xMax = FT_RoundFix( cff_parse_fixed( data++ ) );+ bbox->yMax = FT_RoundFix( cff_parse_fixed( data ) );+ error = CFF_Err_Ok;+ }++ return error;+ }+++ static FT_Error+ cff_parse_private_dict( CFF_Parser parser )+ {+ CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;+ FT_Byte** data = parser->stack;+ FT_Error error;+++ error = CFF_Err_Stack_Underflow;++ if ( parser->top >= parser->stack + 2 )+ {+ dict->private_size = cff_parse_num( data++ );+ dict->private_offset = cff_parse_num( data );+ error = CFF_Err_Ok;+ }++ return error;+ }+++ static FT_Error+ cff_parse_cid_ros( CFF_Parser parser )+ {+ CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;+ FT_Byte** data = parser->stack;+ FT_Error error;+++ error = CFF_Err_Stack_Underflow;++ if ( parser->top >= parser->stack + 3 )+ {+ dict->cid_registry = (FT_UInt)cff_parse_num ( data++ );+ dict->cid_ordering = (FT_UInt)cff_parse_num ( data++ );+ if ( **data == 30 )+ FT_TRACE1(( "cff_parse_cid_ros: real supplement is rounded\n" ));+ dict->cid_supplement = cff_parse_num( data );+ if ( dict->cid_supplement < 0 )+ FT_TRACE1(( "cff_parse_cid_ros: negative supplement %d is found\n",+ dict->cid_supplement ));+ error = CFF_Err_Ok;+ }++ return error;+ }+++#define CFF_FIELD_NUM( code, name ) \+ CFF_FIELD( code, name, cff_kind_num )+#define CFF_FIELD_FIXED( code, name ) \+ CFF_FIELD( code, name, cff_kind_fixed )+#define CFF_FIELD_FIXED_1000( code, name ) \+ CFF_FIELD( code, name, cff_kind_fixed_thousand )+#define CFF_FIELD_STRING( code, name ) \+ CFF_FIELD( code, name, cff_kind_string )+#define CFF_FIELD_BOOL( code, name ) \+ CFF_FIELD( code, name, cff_kind_bool )+#define CFF_FIELD_DELTA( code, name, max ) \+ CFF_FIELD( code, name, cff_kind_delta )++#define CFFCODE_TOPDICT 0x1000+#define CFFCODE_PRIVATE 0x2000++#ifndef FT_CONFIG_OPTION_PIC++#define CFF_FIELD_CALLBACK( code, name ) \+ { \+ cff_kind_callback, \+ code | CFFCODE, \+ 0, 0, \+ cff_parse_ ## name, \+ 0, 0 \+ },++#undef CFF_FIELD+#define CFF_FIELD( code, name, kind ) \+ { \+ kind, \+ code | CFFCODE, \+ FT_FIELD_OFFSET( name ), \+ FT_FIELD_SIZE( name ), \+ 0, 0, 0 \+ },++#undef CFF_FIELD_DELTA+#define CFF_FIELD_DELTA( code, name, max ) \+ { \+ cff_kind_delta, \+ code | CFFCODE, \+ FT_FIELD_OFFSET( name ), \+ FT_FIELD_SIZE_DELTA( name ), \+ 0, \+ max, \+ FT_FIELD_OFFSET( num_ ## name ) \+ },++ static const CFF_Field_Handler cff_field_handlers[] =+ {++#include "cfftoken.h"++ { 0, 0, 0, 0, 0, 0, 0 }+ };+++#else /* FT_CONFIG_OPTION_PIC */++ void FT_Destroy_Class_cff_field_handlers(FT_Library library, CFF_Field_Handler* clazz)+ {+ FT_Memory memory = library->memory;+ if ( clazz )+ FT_FREE( clazz );+ }++ FT_Error FT_Create_Class_cff_field_handlers(FT_Library library, CFF_Field_Handler** output_class)+ {+ CFF_Field_Handler* clazz;+ FT_Error error;+ FT_Memory memory = library->memory;+ int i=0;++#undef CFF_FIELD+#undef CFF_FIELD_DELTA+#undef CFF_FIELD_CALLBACK+#define CFF_FIELD_CALLBACK( code, name ) i++;+#define CFF_FIELD( code, name, kind ) i++;+#define CFF_FIELD_DELTA( code, name, max ) i++;++#include "cfftoken.h"+ i++;/*{ 0, 0, 0, 0, 0, 0, 0 }*/++ if ( FT_ALLOC( clazz, sizeof(CFF_Field_Handler)*i ) )+ return error;++ i=0;+#undef CFF_FIELD+#undef CFF_FIELD_DELTA+#undef CFF_FIELD_CALLBACK++#define CFF_FIELD_CALLBACK( code_, name_ ) \+ clazz[i].kind = cff_kind_callback; \+ clazz[i].code = code_ | CFFCODE; \+ clazz[i].offset = 0; \+ clazz[i].size = 0; \+ clazz[i].reader = cff_parse_ ## name_; \+ clazz[i].array_max = 0; \+ clazz[i].count_offset = 0; \+ i++;++#undef CFF_FIELD+#define CFF_FIELD( code_, name_, kind_ ) \+ clazz[i].kind = kind_; \+ clazz[i].code = code_ | CFFCODE; \+ clazz[i].offset = FT_FIELD_OFFSET( name_ ); \+ clazz[i].size = FT_FIELD_SIZE( name_ ); \+ clazz[i].reader = 0; \+ clazz[i].array_max = 0; \+ clazz[i].count_offset = 0; \+ i++; \++#undef CFF_FIELD_DELTA+#define CFF_FIELD_DELTA( code_, name_, max_ ) \+ clazz[i].kind = cff_kind_delta; \+ clazz[i].code = code_ | CFFCODE; \+ clazz[i].offset = FT_FIELD_OFFSET( name_ ); \+ clazz[i].size = FT_FIELD_SIZE_DELTA( name_ ); \+ clazz[i].reader = 0; \+ clazz[i].array_max = max_; \+ clazz[i].count_offset = FT_FIELD_OFFSET( num_ ## name_ ); \+ i++;++#include "cfftoken.h"++ clazz[i].kind = 0;+ clazz[i].code = 0;+ clazz[i].offset = 0;+ clazz[i].size = 0;+ clazz[i].reader = 0;+ clazz[i].array_max = 0;+ clazz[i].count_offset = 0;++ *output_class = clazz;+ return CFF_Err_Ok;+ }+++#endif /* FT_CONFIG_OPTION_PIC */+++ FT_LOCAL_DEF( FT_Error )+ cff_parser_run( CFF_Parser parser,+ FT_Byte* start,+ FT_Byte* limit )+ {+ FT_Byte* p = start;+ FT_Error error = CFF_Err_Ok;+ FT_Library library = parser->library;+ FT_UNUSED(library);+++ parser->top = parser->stack;+ parser->start = start;+ parser->limit = limit;+ parser->cursor = start;++ while ( p < limit )+ {+ FT_UInt v = *p;+++ if ( v >= 27 && v != 31 )+ {+ /* it's a number; we will push its position on the stack */+ if ( parser->top - parser->stack >= CFF_MAX_STACK_DEPTH )+ goto Stack_Overflow;++ *parser->top ++ = p;++ /* now, skip it */+ if ( v == 30 )+ {+ /* skip real number */+ p++;+ for (;;)+ {+ /* An unterminated floating point number at the */+ /* end of a dictionary is invalid but harmless. */+ if ( p >= limit )+ goto Exit;+ v = p[0] >> 4;+ if ( v == 15 )+ break;+ v = p[0] & 0xF;+ if ( v == 15 )+ break;+ p++;+ }+ }+ else if ( v == 28 )+ p += 2;+ else if ( v == 29 )+ p += 4;+ else if ( v > 246 )+ p += 1;+ }+ else+ {+ /* This is not a number, hence it's an operator. Compute its code */+ /* and look for it in our current list. */++ FT_UInt code;+ FT_UInt num_args = (FT_UInt)+ ( parser->top - parser->stack );+ const CFF_Field_Handler* field;+++ *parser->top = p;+ code = v;+ if ( v == 12 )+ {+ /* two byte operator */+ p++;+ if ( p >= limit )+ goto Syntax_Error;++ code = 0x100 | p[0];+ }+ code = code | parser->object_code;++ for ( field = FT_CFF_FIELD_HANDLERS_GET; field->kind; field++ )+ {+ if ( field->code == (FT_Int)code )+ {+ /* we found our field's handler; read it */+ FT_Long val;+ FT_Byte* q = (FT_Byte*)parser->object + field->offset;+++ /* check that we have enough arguments -- except for */+ /* delta encoded arrays, which can be empty */+ if ( field->kind != cff_kind_delta && num_args < 1 )+ goto Stack_Underflow;++ switch ( field->kind )+ {+ case cff_kind_bool:+ case cff_kind_string:+ case cff_kind_num:+ val = cff_parse_num( parser->stack );+ goto Store_Number;++ case cff_kind_fixed:+ val = cff_parse_fixed( parser->stack );+ goto Store_Number;++ case cff_kind_fixed_thousand:+ val = cff_parse_fixed_scaled( parser->stack, 3 );++ Store_Number:+ switch ( field->size )+ {+ case (8 / FT_CHAR_BIT):+ *(FT_Byte*)q = (FT_Byte)val;+ break;++ case (16 / FT_CHAR_BIT):+ *(FT_Short*)q = (FT_Short)val;+ break;++ case (32 / FT_CHAR_BIT):+ *(FT_Int32*)q = (FT_Int)val;+ break;++ default: /* for 64-bit systems */+ *(FT_Long*)q = val;+ }+ break;++ case cff_kind_delta:+ {+ FT_Byte* qcount = (FT_Byte*)parser->object ++ field->count_offset;++ FT_Byte** data = parser->stack;+++ if ( num_args > field->array_max )+ num_args = field->array_max;++ /* store count */+ *qcount = (FT_Byte)num_args;++ val = 0;+ while ( num_args > 0 )+ {+ val += cff_parse_num( data++ );+ switch ( field->size )+ {+ case (8 / FT_CHAR_BIT):+ *(FT_Byte*)q = (FT_Byte)val;+ break;++ case (16 / FT_CHAR_BIT):+ *(FT_Short*)q = (FT_Short)val;+ break;++ case (32 / FT_CHAR_BIT):+ *(FT_Int32*)q = (FT_Int)val;+ break;++ default: /* for 64-bit systems */+ *(FT_Long*)q = val;+ }++ q += field->size;+ num_args--;+ }+ }+ break;++ default: /* callback */+ error = field->reader( parser );+ if ( error )+ goto Exit;+ }+ goto Found;+ }+ }++ /* this is an unknown operator, or it is unsupported; */+ /* we will ignore it for now. */++ Found:+ /* clear stack */+ parser->top = parser->stack;+ }+ p++;+ }++ Exit:+ return error;++ Stack_Overflow:+ error = CFF_Err_Invalid_Argument;+ goto Exit;++ Stack_Underflow:+ error = CFF_Err_Invalid_Argument;+ goto Exit;++ Syntax_Error:+ error = CFF_Err_Invalid_Argument;+ goto Exit;+ }+++/* END */
+ src/cff/cffparse.h view
@@ -0,0 +1,102 @@+/***************************************************************************/+/* */+/* cffparse.h */+/* */+/* CFF token stream parser (specification) */+/* */+/* Copyright 1996-2001, 2002, 2003 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 __CFF_PARSE_H__+#define __CFF_PARSE_H__+++#include <ft2build.h>+#include "cfftypes.h"+#include FT_INTERNAL_OBJECTS_H+++FT_BEGIN_HEADER+++#define CFF_MAX_STACK_DEPTH 96++#define CFF_CODE_TOPDICT 0x1000+#define CFF_CODE_PRIVATE 0x2000+++ typedef struct CFF_ParserRec_+ {+ FT_Library library;+ FT_Byte* start;+ FT_Byte* limit;+ FT_Byte* cursor;++ FT_Byte* stack[CFF_MAX_STACK_DEPTH + 1];+ FT_Byte** top;++ FT_UInt object_code;+ void* object;++ } CFF_ParserRec, *CFF_Parser;+++ FT_LOCAL( void )+ cff_parser_init( CFF_Parser parser,+ FT_UInt code,+ void* object,+ FT_Library library);++ FT_LOCAL( FT_Error )+ cff_parser_run( CFF_Parser parser,+ FT_Byte* start,+ FT_Byte* limit );+++ enum+ {+ cff_kind_none = 0,+ cff_kind_num,+ cff_kind_fixed,+ cff_kind_fixed_thousand,+ cff_kind_string,+ cff_kind_bool,+ cff_kind_delta,+ cff_kind_callback,++ cff_kind_max /* do not remove */+ };+++ /* now generate handlers for the most simple fields */+ typedef FT_Error (*CFF_Field_Reader)( CFF_Parser parser );++ typedef struct CFF_Field_Handler_+ {+ int kind;+ int code;+ FT_UInt offset;+ FT_Byte size;+ CFF_Field_Reader reader;+ FT_UInt array_max;+ FT_UInt count_offset;++ } CFF_Field_Handler;+++FT_END_HEADER+++#endif /* __CFF_PARSE_H__ */+++/* END */
+ src/cff/cffpic.c view
@@ -0,0 +1,101 @@+/***************************************************************************/+/* */+/* cffpic.c */+/* */+/* The FreeType position independent code services for cff module. */+/* */+/* Copyright 2009, 2010 by */+/* Oran Agra and Mickey Gabel. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#include <ft2build.h>+#include FT_FREETYPE_H+#include FT_INTERNAL_OBJECTS_H+#include "cffpic.h"++#ifdef FT_CONFIG_OPTION_PIC++ /* forward declaration of PIC init functions from cffdrivr.c */+ FT_Error FT_Create_Class_cff_services( FT_Library, FT_ServiceDescRec**);+ void FT_Destroy_Class_cff_services( FT_Library, FT_ServiceDescRec*);+ void FT_Init_Class_cff_service_ps_info( FT_Library, FT_Service_PsInfoRec*);+ void FT_Init_Class_cff_service_glyph_dict( FT_Library, FT_Service_GlyphDictRec*);+ void FT_Init_Class_cff_service_ps_name( FT_Library, FT_Service_PsFontNameRec*);+ void FT_Init_Class_cff_service_get_cmap_info( FT_Library, FT_Service_TTCMapsRec*);+ void FT_Init_Class_cff_service_cid_info( FT_Library, FT_Service_CIDRec*);++ /* forward declaration of PIC init functions from cffparse.c */+ FT_Error FT_Create_Class_cff_field_handlers( FT_Library, CFF_Field_Handler**);+ void FT_Destroy_Class_cff_field_handlers( FT_Library, CFF_Field_Handler*);++ /* forward declaration of PIC init functions from cffcmap.c */+ void FT_Init_Class_cff_cmap_encoding_class_rec( FT_Library, FT_CMap_ClassRec*);+ void FT_Init_Class_cff_cmap_unicode_class_rec( FT_Library, FT_CMap_ClassRec*);++ void+ cff_driver_class_pic_free( FT_Library library )+ {+ FT_PIC_Container* pic_container = &library->pic_container;+ FT_Memory memory = library->memory;+ if ( pic_container->cff )+ {+ CffModulePIC* container = (CffModulePIC*)pic_container->cff;+ if(container->cff_services)+ FT_Destroy_Class_cff_services(library, container->cff_services);+ container->cff_services = NULL;+ if(container->cff_field_handlers)+ FT_Destroy_Class_cff_field_handlers(library, container->cff_field_handlers);+ container->cff_field_handlers = NULL;+ FT_FREE( container );+ pic_container->cff = NULL;+ }+ }+++ FT_Error+ cff_driver_class_pic_init( FT_Library library )+ {+ FT_PIC_Container* pic_container = &library->pic_container;+ FT_Error error = CFF_Err_Ok;+ CffModulePIC* container;+ FT_Memory memory = library->memory;+++ /* allocate pointer, clear and set global container pointer */+ if ( FT_ALLOC ( container, sizeof ( *container ) ) )+ return error;+ FT_MEM_SET( container, 0, sizeof ( *container ) );+ pic_container->cff = container;++ /* initialize pointer table - this is how the module usually expects this data */+ error = FT_Create_Class_cff_services(library, &container->cff_services);+ if(error) + goto Exit;+ error = FT_Create_Class_cff_field_handlers(library, &container->cff_field_handlers);+ if(error) + goto Exit;+ FT_Init_Class_cff_service_ps_info(library, &container->cff_service_ps_info);+ FT_Init_Class_cff_service_glyph_dict(library, &container->cff_service_glyph_dict);+ FT_Init_Class_cff_service_ps_name(library, &container->cff_service_ps_name);+ FT_Init_Class_cff_service_get_cmap_info(library, &container->cff_service_get_cmap_info);+ FT_Init_Class_cff_service_cid_info(library, &container->cff_service_cid_info);+ FT_Init_Class_cff_cmap_encoding_class_rec(library, &container->cff_cmap_encoding_class_rec);+ FT_Init_Class_cff_cmap_unicode_class_rec(library, &container->cff_cmap_unicode_class_rec);+Exit:+ if(error)+ cff_driver_class_pic_free(library);+ return error;+ }++#endif /* FT_CONFIG_OPTION_PIC */+++/* END */
+ src/cff/cffpic.h view
@@ -0,0 +1,80 @@+/***************************************************************************/+/* */+/* cffpic.h */+/* */+/* The FreeType position independent code services for cff module. */+/* */+/* Copyright 2009 by */+/* Oran Agra and Mickey Gabel. */+/* */+/* 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 __CFFPIC_H__+#define __CFFPIC_H__++ +FT_BEGIN_HEADER++#include FT_INTERNAL_PIC_H++#ifndef FT_CONFIG_OPTION_PIC+#define FT_CFF_SERVICE_PS_INFO_GET cff_service_ps_info+#define FT_CFF_SERVICE_GLYPH_DICT_GET cff_service_glyph_dict+#define FT_CFF_SERVICE_PS_NAME_GET cff_service_ps_name+#define FT_CFF_SERVICE_GET_CMAP_INFO_GET cff_service_get_cmap_info+#define FT_CFF_SERVICE_CID_INFO_GET cff_service_cid_info+#define FT_CFF_SERVICES_GET cff_services+#define FT_CFF_CMAP_ENCODING_CLASS_REC_GET cff_cmap_encoding_class_rec+#define FT_CFF_CMAP_UNICODE_CLASS_REC_GET cff_cmap_unicode_class_rec+#define FT_CFF_FIELD_HANDLERS_GET cff_field_handlers++#else /* FT_CONFIG_OPTION_PIC */++#include FT_SERVICE_GLYPH_DICT_H+#include "cffparse.h"+#include FT_SERVICE_POSTSCRIPT_INFO_H+#include FT_SERVICE_POSTSCRIPT_NAME_H+#include FT_SERVICE_TT_CMAP_H+#include FT_SERVICE_CID_H++ typedef struct CffModulePIC_+ {+ FT_ServiceDescRec* cff_services;+ CFF_Field_Handler* cff_field_handlers;+ FT_Service_PsInfoRec cff_service_ps_info;+ FT_Service_GlyphDictRec cff_service_glyph_dict;+ FT_Service_PsFontNameRec cff_service_ps_name;+ FT_Service_TTCMapsRec cff_service_get_cmap_info;+ FT_Service_CIDRec cff_service_cid_info;+ FT_CMap_ClassRec cff_cmap_encoding_class_rec;+ FT_CMap_ClassRec cff_cmap_unicode_class_rec;+ } CffModulePIC;++#define GET_PIC(lib) ((CffModulePIC*)((lib)->pic_container.cff))+#define FT_CFF_SERVICE_PS_INFO_GET (GET_PIC(library)->cff_service_ps_info)+#define FT_CFF_SERVICE_GLYPH_DICT_GET (GET_PIC(library)->cff_service_glyph_dict)+#define FT_CFF_SERVICE_PS_NAME_GET (GET_PIC(library)->cff_service_ps_name)+#define FT_CFF_SERVICE_GET_CMAP_INFO_GET (GET_PIC(library)->cff_service_get_cmap_info)+#define FT_CFF_SERVICE_CID_INFO_GET (GET_PIC(library)->cff_service_cid_info)+#define FT_CFF_SERVICES_GET (GET_PIC(library)->cff_services)+#define FT_CFF_CMAP_ENCODING_CLASS_REC_GET (GET_PIC(library)->cff_cmap_encoding_class_rec)+#define FT_CFF_CMAP_UNICODE_CLASS_REC_GET (GET_PIC(library)->cff_cmap_unicode_class_rec)+#define FT_CFF_FIELD_HANDLERS_GET (GET_PIC(library)->cff_field_handlers)++#endif /* FT_CONFIG_OPTION_PIC */++ /* */++FT_END_HEADER++#endif /* __CFFPIC_H__ */+++/* END */
+ src/cff/cfftoken.h view
@@ -0,0 +1,97 @@+/***************************************************************************/+/* */+/* cfftoken.h */+/* */+/* CFF token definitions (specification only). */+/* */+/* Copyright 1996-2001, 2002, 2003 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. */+/* */+/***************************************************************************/+++#undef FT_STRUCTURE+#define FT_STRUCTURE CFF_FontRecDictRec++#undef CFFCODE+#define CFFCODE CFFCODE_TOPDICT++ CFF_FIELD_STRING ( 0, version )+ CFF_FIELD_STRING ( 1, notice )+ CFF_FIELD_STRING ( 0x100, copyright )+ CFF_FIELD_STRING ( 2, full_name )+ CFF_FIELD_STRING ( 3, family_name )+ CFF_FIELD_STRING ( 4, weight )+ CFF_FIELD_BOOL ( 0x101, is_fixed_pitch )+ CFF_FIELD_FIXED ( 0x102, italic_angle )+ CFF_FIELD_FIXED ( 0x103, underline_position )+ CFF_FIELD_FIXED ( 0x104, underline_thickness )+ CFF_FIELD_NUM ( 0x105, paint_type )+ CFF_FIELD_NUM ( 0x106, charstring_type )+ CFF_FIELD_CALLBACK( 0x107, font_matrix )+ CFF_FIELD_NUM ( 13, unique_id )+ CFF_FIELD_CALLBACK( 5, font_bbox )+ CFF_FIELD_NUM ( 0x108, stroke_width )+ CFF_FIELD_NUM ( 15, charset_offset )+ CFF_FIELD_NUM ( 16, encoding_offset )+ CFF_FIELD_NUM ( 17, charstrings_offset )+ CFF_FIELD_CALLBACK( 18, private_dict )+ CFF_FIELD_NUM ( 0x114, synthetic_base )+ CFF_FIELD_STRING ( 0x115, embedded_postscript )++#if 0+ CFF_FIELD_STRING ( 0x116, base_font_name )+ CFF_FIELD_DELTA ( 0x117, base_font_blend, 16 )+ CFF_FIELD_CALLBACK( 0x118, multiple_master )+ CFF_FIELD_CALLBACK( 0x119, blend_axis_types )+#endif++ CFF_FIELD_CALLBACK( 0x11E, cid_ros )+ CFF_FIELD_NUM ( 0x11F, cid_font_version )+ CFF_FIELD_NUM ( 0x120, cid_font_revision )+ CFF_FIELD_NUM ( 0x121, cid_font_type )+ CFF_FIELD_NUM ( 0x122, cid_count )+ CFF_FIELD_NUM ( 0x123, cid_uid_base )+ CFF_FIELD_NUM ( 0x124, cid_fd_array_offset )+ CFF_FIELD_NUM ( 0x125, cid_fd_select_offset )+ CFF_FIELD_STRING ( 0x126, cid_font_name )++#if 0+ CFF_FIELD_NUM ( 0x127, chameleon )+#endif+++#undef FT_STRUCTURE+#define FT_STRUCTURE CFF_PrivateRec+#undef CFFCODE+#define CFFCODE CFFCODE_PRIVATE++ CFF_FIELD_DELTA ( 6, blue_values, 14 )+ CFF_FIELD_DELTA ( 7, other_blues, 10 )+ CFF_FIELD_DELTA ( 8, family_blues, 14 )+ CFF_FIELD_DELTA ( 9, family_other_blues, 10 )+ CFF_FIELD_FIXED_1000( 0x109, blue_scale )+ CFF_FIELD_NUM ( 0x10A, blue_shift )+ CFF_FIELD_NUM ( 0x10B, blue_fuzz )+ CFF_FIELD_NUM ( 10, standard_width )+ CFF_FIELD_NUM ( 11, standard_height )+ CFF_FIELD_DELTA ( 0x10C, snap_widths, 13 )+ CFF_FIELD_DELTA ( 0x10D, snap_heights, 13 )+ CFF_FIELD_BOOL ( 0x10E, force_bold )+ CFF_FIELD_FIXED ( 0x10F, force_bold_threshold )+ CFF_FIELD_NUM ( 0x110, lenIV )+ CFF_FIELD_NUM ( 0x111, language_group )+ CFF_FIELD_FIXED ( 0x112, expansion_factor )+ CFF_FIELD_NUM ( 0x113, initial_random_seed )+ CFF_FIELD_NUM ( 19, local_subrs_offset )+ CFF_FIELD_NUM ( 20, default_width )+ CFF_FIELD_NUM ( 21, nominal_width )+++/* END */
+ src/cff/cfftypes.h view
@@ -0,0 +1,281 @@+/***************************************************************************/+/* */+/* cfftypes.h */+/* */+/* Basic OpenType/CFF type definitions and interface (specification */+/* only). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2006, 2007, 2008, 2010 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#ifndef __CFFTYPES_H__+#define __CFFTYPES_H__+++#include <ft2build.h>+#include FT_FREETYPE_H+#include FT_TYPE1_TABLES_H+#include FT_INTERNAL_SERVICE_H+#include FT_SERVICE_POSTSCRIPT_CMAPS_H+#include FT_INTERNAL_POSTSCRIPT_HINTS_H+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* CFF_IndexRec */+ /* */+ /* <Description> */+ /* A structure used to model a CFF Index table. */+ /* */+ /* <Fields> */+ /* stream :: The source input stream. */+ /* */+ /* start :: The position of the first index byte in the */+ /* input stream. */+ /* */+ /* count :: The number of elements in the index. */+ /* */+ /* off_size :: The size in bytes of object offsets in index. */+ /* */+ /* data_offset :: The position of first data byte in the index's */+ /* bytes. */+ /* */+ /* data_size :: The size of the data table in this index. */+ /* */+ /* offsets :: A table of element offsets in the index. Must be */+ /* loaded explicitly. */+ /* */+ /* bytes :: If the index is loaded in memory, its bytes. */+ /* */+ typedef struct CFF_IndexRec_+ {+ FT_Stream stream;+ FT_ULong start;+ FT_UInt count;+ FT_Byte off_size;+ FT_ULong data_offset;+ FT_ULong data_size;++ FT_ULong* offsets;+ FT_Byte* bytes;++ } CFF_IndexRec, *CFF_Index;+++ typedef struct CFF_EncodingRec_+ {+ FT_UInt format;+ FT_ULong offset;++ FT_UInt count;+ FT_UShort sids [256]; /* avoid dynamic allocations */+ FT_UShort codes[256];++ } CFF_EncodingRec, *CFF_Encoding;+++ typedef struct CFF_CharsetRec_+ {++ FT_UInt format;+ FT_ULong offset;++ FT_UShort* sids;+ FT_UShort* cids; /* the inverse mapping of `sids'; only needed */+ /* for CID-keyed fonts */+ FT_UInt max_cid;+ FT_UInt num_glyphs;++ } CFF_CharsetRec, *CFF_Charset;+++ typedef struct CFF_FontRecDictRec_+ {+ FT_UInt version;+ FT_UInt notice;+ FT_UInt copyright;+ FT_UInt full_name;+ FT_UInt family_name;+ FT_UInt weight;+ FT_Bool is_fixed_pitch;+ FT_Fixed italic_angle;+ FT_Fixed underline_position;+ FT_Fixed underline_thickness;+ FT_Int paint_type;+ FT_Int charstring_type;+ FT_Matrix font_matrix;+ FT_ULong units_per_em; /* temporarily used as scaling value also */+ FT_Vector font_offset;+ FT_ULong unique_id;+ FT_BBox font_bbox;+ FT_Pos stroke_width;+ FT_ULong charset_offset;+ FT_ULong encoding_offset;+ FT_ULong charstrings_offset;+ FT_ULong private_offset;+ FT_ULong private_size;+ FT_Long synthetic_base;+ FT_UInt embedded_postscript;++ /* these should only be used for the top-level font dictionary */+ FT_UInt cid_registry;+ FT_UInt cid_ordering;+ FT_Long cid_supplement;++ FT_Long cid_font_version;+ FT_Long cid_font_revision;+ FT_Long cid_font_type;+ FT_ULong cid_count;+ FT_ULong cid_uid_base;+ FT_ULong cid_fd_array_offset;+ FT_ULong cid_fd_select_offset;+ FT_UInt cid_font_name;++ } CFF_FontRecDictRec, *CFF_FontRecDict;+++ typedef struct CFF_PrivateRec_+ {+ FT_Byte num_blue_values;+ FT_Byte num_other_blues;+ FT_Byte num_family_blues;+ FT_Byte num_family_other_blues;++ FT_Pos blue_values[14];+ FT_Pos other_blues[10];+ FT_Pos family_blues[14];+ FT_Pos family_other_blues[10];++ FT_Fixed blue_scale;+ FT_Pos blue_shift;+ FT_Pos blue_fuzz;+ FT_Pos standard_width;+ FT_Pos standard_height;++ FT_Byte num_snap_widths;+ FT_Byte num_snap_heights;+ FT_Pos snap_widths[13];+ FT_Pos snap_heights[13];+ FT_Bool force_bold;+ FT_Fixed force_bold_threshold;+ FT_Int lenIV;+ FT_Int language_group;+ FT_Fixed expansion_factor;+ FT_Long initial_random_seed;+ FT_ULong local_subrs_offset;+ FT_Pos default_width;+ FT_Pos nominal_width;++ } CFF_PrivateRec, *CFF_Private;+++ typedef struct CFF_FDSelectRec_+ {+ FT_Byte format;+ FT_UInt range_count;++ /* that's the table, taken from the file `as is' */+ FT_Byte* data;+ FT_UInt data_size;++ /* small cache for format 3 only */+ FT_UInt cache_first;+ FT_UInt cache_count;+ FT_Byte cache_fd;++ } CFF_FDSelectRec, *CFF_FDSelect;+++ /* A SubFont packs a font dict and a private dict together. They are */+ /* needed to support CID-keyed CFF fonts. */+ typedef struct CFF_SubFontRec_+ {+ CFF_FontRecDictRec font_dict;+ CFF_PrivateRec private_dict;++ CFF_IndexRec local_subrs_index;+ FT_Byte** local_subrs; /* array of pointers into Local Subrs INDEX data */++ } CFF_SubFontRec, *CFF_SubFont;+++ /* maximum number of sub-fonts in a CID-keyed file */+#define CFF_MAX_CID_FONTS 32+++ typedef struct CFF_FontRec_+ {+ FT_Stream stream;+ FT_Memory memory;+ FT_UInt num_faces;+ FT_UInt num_glyphs;++ FT_Byte version_major;+ FT_Byte version_minor;+ FT_Byte header_size;+ FT_Byte absolute_offsize;+++ CFF_IndexRec name_index;+ CFF_IndexRec top_dict_index;+ CFF_IndexRec global_subrs_index;++ CFF_EncodingRec encoding;+ CFF_CharsetRec charset;++ CFF_IndexRec charstrings_index;+ CFF_IndexRec font_dict_index;+ CFF_IndexRec private_index;+ CFF_IndexRec local_subrs_index;++ FT_String* font_name;++ /* array of pointers into Global Subrs INDEX data */+ FT_Byte** global_subrs;++ /* array of pointers into String INDEX data stored at string_pool */+ FT_UInt num_strings;+ FT_Byte** strings;+ FT_Byte* string_pool;++ CFF_SubFontRec top_font;+ FT_UInt num_subfonts;+ CFF_SubFont subfonts[CFF_MAX_CID_FONTS];++ CFF_FDSelectRec fd_select;++ /* interface to PostScript hinter */+ PSHinter_Service pshinter;++ /* interface to Postscript Names service */+ FT_Service_PsCMaps psnames;++ /* since version 2.3.0 */+ PS_FontInfoRec* font_info; /* font info dictionary */++ /* since version 2.3.6 */+ FT_String* registry;+ FT_String* ordering;+ + } CFF_FontRec, *CFF_Font;+++FT_END_HEADER++#endif /* __CFFTYPES_H__ */+++/* END */
+ src/cid/ciderrs.h view
@@ -0,0 +1,40 @@+/***************************************************************************/+/* */+/* ciderrs.h */+/* */+/* CID error codes (specification only). */+/* */+/* Copyright 2001 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 CID error enumeration constants. */+ /* */+ /*************************************************************************/++#ifndef __CIDERRS_H__+#define __CIDERRS_H__++#include FT_MODULE_ERRORS_H++#undef __FTERRORS_H__++#define FT_ERR_PREFIX CID_Err_+#define FT_ERR_BASE FT_Mod_Err_CID++#include FT_ERRORS_H++#endif /* __CIDERRS_H__ */+++/* END */
+ src/cid/cidgload.c view
@@ -0,0 +1,442 @@+/***************************************************************************/+/* */+/* cidgload.c */+/* */+/* CID-keyed Type1 Glyph Loader (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 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 "cidload.h"+#include "cidgload.h"+#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_STREAM_H+#include FT_OUTLINE_H+#include FT_INTERNAL_CALC_H++#include "ciderrs.h"+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_cidgload+++ FT_CALLBACK_DEF( FT_Error )+ cid_load_glyph( T1_Decoder decoder,+ FT_UInt glyph_index )+ {+ CID_Face face = (CID_Face)decoder->builder.face;+ CID_FaceInfo cid = &face->cid;+ FT_Byte* p;+ FT_UInt fd_select;+ FT_Stream stream = face->cid_stream;+ FT_Error error = CID_Err_Ok;+ FT_Byte* charstring = 0;+ FT_Memory memory = face->root.memory;+ FT_ULong glyph_length = 0;+ PSAux_Service psaux = (PSAux_Service)face->psaux;++#ifdef FT_CONFIG_OPTION_INCREMENTAL+ FT_Incremental_InterfaceRec *inc =+ face->root.internal->incremental_interface;+#endif+++ FT_TRACE4(( "cid_load_glyph: glyph index %d\n", glyph_index ));++#ifdef FT_CONFIG_OPTION_INCREMENTAL++ /* For incremental fonts get the character data using */+ /* the callback function. */+ if ( inc )+ {+ FT_Data glyph_data;+++ error = inc->funcs->get_glyph_data( inc->object,+ glyph_index, &glyph_data );+ if ( error )+ goto Exit;++ p = (FT_Byte*)glyph_data.pointer;+ fd_select = (FT_UInt)cid_get_offset( &p, (FT_Byte)cid->fd_bytes );++ if ( glyph_data.length != 0 )+ {+ glyph_length = glyph_data.length - cid->fd_bytes;+ (void)FT_ALLOC( charstring, glyph_length );+ if ( !error )+ ft_memcpy( charstring, glyph_data.pointer + cid->fd_bytes,+ glyph_length );+ }++ inc->funcs->free_glyph_data( inc->object, &glyph_data );++ if ( error )+ goto Exit;+ }++ else++#endif /* FT_CONFIG_OPTION_INCREMENTAL */++ /* For ordinary fonts read the CID font dictionary index */+ /* and charstring offset from the CIDMap. */+ {+ FT_UInt entry_len = cid->fd_bytes + cid->gd_bytes;+ FT_ULong off1;+++ if ( FT_STREAM_SEEK( cid->data_offset + cid->cidmap_offset ++ glyph_index * entry_len ) ||+ FT_FRAME_ENTER( 2 * entry_len ) )+ goto Exit;++ p = (FT_Byte*)stream->cursor;+ fd_select = (FT_UInt) cid_get_offset( &p, (FT_Byte)cid->fd_bytes );+ off1 = (FT_ULong)cid_get_offset( &p, (FT_Byte)cid->gd_bytes );+ p += cid->fd_bytes;+ glyph_length = cid_get_offset( &p, (FT_Byte)cid->gd_bytes ) - off1;+ FT_FRAME_EXIT();++ if ( fd_select >= (FT_UInt)cid->num_dicts )+ {+ error = CID_Err_Invalid_Offset;+ goto Exit;+ }+ if ( glyph_length == 0 )+ goto Exit;+ if ( FT_ALLOC( charstring, glyph_length ) )+ goto Exit;+ if ( FT_STREAM_READ_AT( cid->data_offset + off1,+ charstring, glyph_length ) )+ goto Exit;+ }++ /* Now set up the subrs array and parse the charstrings. */+ {+ CID_FaceDict dict;+ CID_Subrs cid_subrs = face->subrs + fd_select;+ FT_Int cs_offset;+++ /* Set up subrs */+ decoder->num_subrs = cid_subrs->num_subrs;+ decoder->subrs = cid_subrs->code;+ decoder->subrs_len = 0;++ /* Set up font matrix */+ dict = cid->font_dicts + fd_select;++ decoder->font_matrix = dict->font_matrix;+ decoder->font_offset = dict->font_offset;+ decoder->lenIV = dict->private_dict.lenIV;++ /* Decode the charstring. */++ /* Adjustment for seed bytes. */+ cs_offset = ( decoder->lenIV >= 0 ? decoder->lenIV : 0 );++ /* Decrypt only if lenIV >= 0. */+ if ( decoder->lenIV >= 0 )+ psaux->t1_decrypt( charstring, glyph_length, 4330 );++ error = decoder->funcs.parse_charstrings(+ decoder, charstring + cs_offset,+ (FT_Int)glyph_length - cs_offset );+ }++ FT_FREE( charstring );++#ifdef FT_CONFIG_OPTION_INCREMENTAL++ /* Incremental fonts can optionally override the metrics. */+ if ( !error && inc && inc->funcs->get_glyph_metrics )+ {+ FT_Incremental_MetricsRec metrics;+++ metrics.bearing_x = FIXED_TO_INT( decoder->builder.left_bearing.x );+ metrics.bearing_y = 0;+ metrics.advance = FIXED_TO_INT( decoder->builder.advance.x );+ metrics.advance_v = FIXED_TO_INT( decoder->builder.advance.y );++ error = inc->funcs->get_glyph_metrics( inc->object,+ glyph_index, FALSE, &metrics );++ decoder->builder.left_bearing.x = INT_TO_FIXED( metrics.bearing_x );+ decoder->builder.advance.x = INT_TO_FIXED( metrics.advance );+ decoder->builder.advance.y = INT_TO_FIXED( metrics.advance_v );+ }++#endif /* FT_CONFIG_OPTION_INCREMENTAL */++ Exit:+ return error;+ }+++#if 0+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /********** *********/+ /********** *********/+ /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/+ /********** *********/+ /********** The following code is in charge of computing *********/+ /********** the maximum advance width of the font. It *********/+ /********** quickly processes each glyph charstring to *********/+ /********** extract the value from either a `sbw' or `seac' *********/+ /********** operator. *********/+ /********** *********/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ FT_LOCAL_DEF( FT_Error )+ cid_face_compute_max_advance( CID_Face face,+ FT_Int* max_advance )+ {+ FT_Error error;+ T1_DecoderRec decoder;+ FT_Int glyph_index;++ PSAux_Service psaux = (PSAux_Service)face->psaux;+++ *max_advance = 0;++ /* Initialize load decoder */+ error = psaux->t1_decoder_funcs->init( &decoder,+ (FT_Face)face,+ 0, /* size */+ 0, /* glyph slot */+ 0, /* glyph names! XXX */+ 0, /* blend == 0 */+ 0, /* hinting == 0 */+ cid_load_glyph );+ if ( error )+ return error;++ /* TODO: initialize decoder.len_buildchar and decoder.buildchar */+ /* if we ever support CID-keyed multiple master fonts */++ decoder.builder.metrics_only = 1;+ decoder.builder.load_points = 0;++ /* for each glyph, parse the glyph charstring and extract */+ /* the advance width */+ for ( glyph_index = 0; glyph_index < face->root.num_glyphs;+ glyph_index++ )+ {+ /* now get load the unscaled outline */+ error = cid_load_glyph( &decoder, glyph_index );+ /* ignore the error if one occurred - skip to next glyph */+ }++ *max_advance = FIXED_TO_INT( decoder.builder.advance.x );++ psaux->t1_decoder_funcs->done( &decoder );++ return CID_Err_Ok;+ }+++#endif /* 0 */+++ FT_LOCAL_DEF( FT_Error )+ cid_slot_load_glyph( FT_GlyphSlot cidglyph, /* CID_GlyphSlot */+ FT_Size cidsize, /* CID_Size */+ FT_UInt glyph_index,+ FT_Int32 load_flags )+ {+ CID_GlyphSlot glyph = (CID_GlyphSlot)cidglyph;+ FT_Error error;+ T1_DecoderRec decoder;+ CID_Face face = (CID_Face)cidglyph->face;+ FT_Bool hinting;++ PSAux_Service psaux = (PSAux_Service)face->psaux;+ FT_Matrix font_matrix;+ FT_Vector font_offset;+++ if ( glyph_index >= (FT_UInt)face->root.num_glyphs )+ {+ error = CID_Err_Invalid_Argument;+ goto Exit;+ }++ if ( load_flags & FT_LOAD_NO_RECURSE )+ load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;++ glyph->x_scale = cidsize->metrics.x_scale;+ glyph->y_scale = cidsize->metrics.y_scale;++ cidglyph->outline.n_points = 0;+ cidglyph->outline.n_contours = 0;++ hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 &&+ ( load_flags & FT_LOAD_NO_HINTING ) == 0 );++ cidglyph->format = FT_GLYPH_FORMAT_OUTLINE;++ error = psaux->t1_decoder_funcs->init( &decoder,+ cidglyph->face,+ cidsize,+ cidglyph,+ 0, /* glyph names -- XXX */+ 0, /* blend == 0 */+ hinting,+ FT_LOAD_TARGET_MODE( load_flags ),+ cid_load_glyph );+ if ( error )+ goto Exit;++ /* TODO: initialize decoder.len_buildchar and decoder.buildchar */+ /* if we ever support CID-keyed multiple master fonts */++ /* set up the decoder */+ decoder.builder.no_recurse = FT_BOOL(+ ( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 ) );++ error = cid_load_glyph( &decoder, glyph_index );+ if ( error )+ goto Exit;++ font_matrix = decoder.font_matrix;+ font_offset = decoder.font_offset;++ /* save new glyph tables */+ psaux->t1_decoder_funcs->done( &decoder );++ /* now set the metrics -- this is rather simple, as */+ /* the left side bearing is the xMin, and the top side */+ /* bearing the yMax */+ cidglyph->outline.flags &= FT_OUTLINE_OWNER;+ cidglyph->outline.flags |= FT_OUTLINE_REVERSE_FILL;++ /* for composite glyphs, return only left side bearing and */+ /* advance width */+ if ( load_flags & FT_LOAD_NO_RECURSE )+ {+ FT_Slot_Internal internal = cidglyph->internal;+++ cidglyph->metrics.horiBearingX =+ FIXED_TO_INT( decoder.builder.left_bearing.x );+ cidglyph->metrics.horiAdvance =+ FIXED_TO_INT( decoder.builder.advance.x );++ internal->glyph_matrix = font_matrix;+ internal->glyph_delta = font_offset;+ internal->glyph_transformed = 1;+ }+ else+ {+ FT_BBox cbox;+ FT_Glyph_Metrics* metrics = &cidglyph->metrics;+ FT_Vector advance;+++ /* copy the _unscaled_ advance width */+ metrics->horiAdvance =+ FIXED_TO_INT( decoder.builder.advance.x );+ cidglyph->linearHoriAdvance =+ FIXED_TO_INT( decoder.builder.advance.x );+ cidglyph->internal->glyph_transformed = 0;++ /* make up vertical ones */+ metrics->vertAdvance = ( face->cid.font_bbox.yMax -+ face->cid.font_bbox.yMin ) >> 16;+ cidglyph->linearVertAdvance = metrics->vertAdvance;++ cidglyph->format = FT_GLYPH_FORMAT_OUTLINE;++ if ( cidsize->metrics.y_ppem < 24 )+ cidglyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;++ /* apply the font matrix */+ FT_Outline_Transform( &cidglyph->outline, &font_matrix );++ FT_Outline_Translate( &cidglyph->outline,+ font_offset.x,+ font_offset.y );++ advance.x = metrics->horiAdvance;+ advance.y = 0;+ FT_Vector_Transform( &advance, &font_matrix );+ metrics->horiAdvance = advance.x + font_offset.x;++ advance.x = 0;+ advance.y = metrics->vertAdvance;+ FT_Vector_Transform( &advance, &font_matrix );+ metrics->vertAdvance = advance.y + font_offset.y;++ if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )+ {+ /* scale the outline and the metrics */+ FT_Int n;+ FT_Outline* cur = decoder.builder.base;+ FT_Vector* vec = cur->points;+ FT_Fixed x_scale = glyph->x_scale;+ FT_Fixed y_scale = glyph->y_scale;+++ /* First of all, scale the points */+ if ( !hinting || !decoder.builder.hints_funcs )+ for ( n = cur->n_points; n > 0; n--, vec++ )+ {+ vec->x = FT_MulFix( vec->x, x_scale );+ vec->y = FT_MulFix( vec->y, y_scale );+ }++ /* Then scale the metrics */+ metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );+ metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );+ }++ /* compute the other metrics */+ FT_Outline_Get_CBox( &cidglyph->outline, &cbox );++ metrics->width = cbox.xMax - cbox.xMin;+ metrics->height = cbox.yMax - cbox.yMin;++ metrics->horiBearingX = cbox.xMin;+ metrics->horiBearingY = cbox.yMax;++ if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) + {+ /* make up vertical ones */+ ft_synthesize_vertical_metrics( metrics,+ metrics->vertAdvance );+ }+ }++ Exit:+ return error;+ }+++/* END */
+ src/cid/cidgload.h view
@@ -0,0 +1,51 @@+/***************************************************************************/+/* */+/* cidgload.h */+/* */+/* OpenType Glyph Loader (specification). */+/* */+/* Copyright 1996-2001, 2002, 2004 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 __CIDGLOAD_H__+#define __CIDGLOAD_H__+++#include <ft2build.h>+#include "cidobjs.h"+++FT_BEGIN_HEADER+++#if 0++ /* Compute the maximum advance width of a font through quick parsing */+ FT_LOCAL( FT_Error )+ cid_face_compute_max_advance( CID_Face face,+ FT_Int* max_advance );++#endif /* 0 */++ FT_LOCAL( FT_Error )+ cid_slot_load_glyph( FT_GlyphSlot glyph, /* CID_Glyph_Slot */+ FT_Size size, /* CID_Size */+ FT_UInt glyph_index,+ FT_Int32 load_flags );+++FT_END_HEADER++#endif /* __CIDGLOAD_H__ */+++/* END */
+ src/cid/cidload.c view
@@ -0,0 +1,672 @@+/***************************************************************************/+/* */+/* cidload.c */+/* */+/* CID-keyed Type1 font loader (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2009 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_CONFIG_CONFIG_H+#include FT_MULTIPLE_MASTERS_H+#include FT_INTERNAL_TYPE1_TYPES_H++#include "cidload.h"++#include "ciderrs.h"+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_cidload+++ /* read a single offset */+ FT_LOCAL_DEF( FT_Long )+ cid_get_offset( FT_Byte* *start,+ FT_Byte offsize )+ {+ FT_Long result;+ FT_Byte* p = *start;+++ for ( result = 0; offsize > 0; offsize-- )+ {+ result <<= 8;+ result |= *p++;+ }++ *start = p;+ return result;+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** TYPE 1 SYMBOL PARSING *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+++ static FT_Error+ cid_load_keyword( CID_Face face,+ CID_Loader* loader,+ const T1_Field keyword )+ {+ FT_Error error;+ CID_Parser* parser = &loader->parser;+ FT_Byte* object;+ void* dummy_object;+ CID_FaceInfo cid = &face->cid;+++ /* if the keyword has a dedicated callback, call it */+ if ( keyword->type == T1_FIELD_TYPE_CALLBACK )+ {+ keyword->reader( (FT_Face)face, parser );+ error = parser->root.error;+ goto Exit;+ }++ /* we must now compute the address of our target object */+ switch ( keyword->location )+ {+ case T1_FIELD_LOCATION_CID_INFO:+ object = (FT_Byte*)cid;+ break;++ case T1_FIELD_LOCATION_FONT_INFO:+ object = (FT_Byte*)&cid->font_info;+ break;++ case T1_FIELD_LOCATION_FONT_EXTRA:+ object = (FT_Byte*)&face->font_extra;+ break;++ case T1_FIELD_LOCATION_BBOX:+ object = (FT_Byte*)&cid->font_bbox;+ break;++ default:+ {+ CID_FaceDict dict;+++ if ( parser->num_dict < 0 )+ {+ FT_ERROR(( "cid_load_keyword: invalid use of `%s'\n",+ keyword->ident ));+ error = CID_Err_Syntax_Error;+ goto Exit;+ }++ dict = cid->font_dicts + parser->num_dict;+ switch ( keyword->location )+ {+ case T1_FIELD_LOCATION_PRIVATE:+ object = (FT_Byte*)&dict->private_dict;+ break;++ default:+ object = (FT_Byte*)dict;+ }+ }+ }++ dummy_object = object;++ /* now, load the keyword data in the object's field(s) */+ if ( keyword->type == T1_FIELD_TYPE_INTEGER_ARRAY ||+ keyword->type == T1_FIELD_TYPE_FIXED_ARRAY )+ error = cid_parser_load_field_table( &loader->parser, keyword,+ &dummy_object );+ else+ error = cid_parser_load_field( &loader->parser,+ keyword, &dummy_object );+ Exit:+ return error;+ }+++ FT_CALLBACK_DEF( FT_Error )+ parse_font_matrix( CID_Face face,+ CID_Parser* parser )+ {+ FT_Matrix* matrix;+ FT_Vector* offset;+ CID_FaceDict dict;+ FT_Face root = (FT_Face)&face->root;+ FT_Fixed temp[6];+ FT_Fixed temp_scale;+++ if ( parser->num_dict >= 0 )+ {+ dict = face->cid.font_dicts + parser->num_dict;+ matrix = &dict->font_matrix;+ offset = &dict->font_offset;++ (void)cid_parser_to_fixed_array( parser, 6, temp, 3 );++ temp_scale = FT_ABS( temp[3] );++ /* Set units per EM based on FontMatrix values. We set the value to */+ /* `1000/temp_scale', because temp_scale was already multiplied by */+ /* 1000 (in `t1_tofixed', from psobjs.c). */+ root->units_per_EM = (FT_UShort)( FT_DivFix( 0x10000L,+ FT_DivFix( temp_scale, 1000 ) ) );++ /* we need to scale the values by 1.0/temp[3] */+ if ( temp_scale != 0x10000L )+ {+ temp[0] = FT_DivFix( temp[0], temp_scale );+ temp[1] = FT_DivFix( temp[1], temp_scale );+ temp[2] = FT_DivFix( temp[2], temp_scale );+ temp[4] = FT_DivFix( temp[4], temp_scale );+ temp[5] = FT_DivFix( temp[5], temp_scale );+ temp[3] = 0x10000L;+ }++ matrix->xx = temp[0];+ matrix->yx = temp[1];+ matrix->xy = temp[2];+ matrix->yy = temp[3];++ /* note that the font offsets are expressed in integer font units */+ offset->x = temp[4] >> 16;+ offset->y = temp[5] >> 16;+ }++ return CID_Err_Ok; /* this is a callback function; */+ /* we must return an error code */+ }+++ FT_CALLBACK_DEF( FT_Error )+ parse_fd_array( CID_Face face,+ CID_Parser* parser )+ {+ CID_FaceInfo cid = &face->cid;+ FT_Memory memory = face->root.memory;+ FT_Error error = CID_Err_Ok;+ FT_Long num_dicts;+++ num_dicts = cid_parser_to_int( parser );++ if ( !cid->font_dicts )+ {+ FT_Int n;+++ if ( FT_NEW_ARRAY( cid->font_dicts, num_dicts ) )+ goto Exit;++ cid->num_dicts = (FT_UInt)num_dicts;++ /* don't forget to set a few defaults */+ for ( n = 0; n < cid->num_dicts; n++ )+ {+ CID_FaceDict dict = cid->font_dicts + n;+++ /* default value for lenIV */+ dict->private_dict.lenIV = 4;+ }+ }++ Exit:+ return error;+ }+++ /* by mistake, `expansion_factor' appears both in PS_PrivateRec */+ /* and CID_FaceDictRec (both are public header files and can't */+ /* changed); we simply copy the value */++ FT_CALLBACK_DEF( FT_Error )+ parse_expansion_factor( CID_Face face,+ CID_Parser* parser )+ {+ CID_FaceDict dict;+++ if ( parser->num_dict >= 0 )+ {+ dict = face->cid.font_dicts + parser->num_dict;++ dict->expansion_factor = cid_parser_to_fixed( parser, 0 );+ dict->private_dict.expansion_factor = dict->expansion_factor;+ }++ return CID_Err_Ok;+ }+++ static+ const T1_FieldRec cid_field_records[] =+ {++#include "cidtoken.h"++ T1_FIELD_CALLBACK( "FDArray", parse_fd_array, 0 )+ T1_FIELD_CALLBACK( "FontMatrix", parse_font_matrix, 0 )+ T1_FIELD_CALLBACK( "ExpansionFactor", parse_expansion_factor, 0 )++ { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 }+ };+++ static FT_Error+ cid_parse_dict( CID_Face face,+ CID_Loader* loader,+ FT_Byte* base,+ FT_Long size )+ {+ CID_Parser* parser = &loader->parser;+++ parser->root.cursor = base;+ parser->root.limit = base + size;+ parser->root.error = CID_Err_Ok;++ {+ FT_Byte* cur = base;+ FT_Byte* limit = cur + size;+++ for (;;)+ {+ FT_Byte* newlimit;+++ parser->root.cursor = cur;+ cid_parser_skip_spaces( parser );++ if ( parser->root.cursor >= limit )+ newlimit = limit - 1 - 17;+ else+ newlimit = parser->root.cursor - 17;++ /* look for `%ADOBeginFontDict' */+ for ( ; cur < newlimit; cur++ )+ {+ if ( *cur == '%' &&+ ft_strncmp( (char*)cur, "%ADOBeginFontDict", 17 ) == 0 )+ {+ /* if /FDArray was found, then cid->num_dicts is > 0, and */+ /* we can start increasing parser->num_dict */+ if ( face->cid.num_dicts > 0 )+ parser->num_dict++;+ }+ }++ cur = parser->root.cursor;+ /* no error can occur in cid_parser_skip_spaces */+ if ( cur >= limit )+ break;++ cid_parser_skip_PS_token( parser );+ if ( parser->root.cursor >= limit || parser->root.error )+ break;++ /* look for immediates */+ if ( *cur == '/' && cur + 2 < limit )+ {+ FT_PtrDist len;+++ cur++;+ len = parser->root.cursor - cur;++ if ( len > 0 && len < 22 )+ {+ /* now compare the immediate name to the keyword table */+ T1_Field keyword = (T1_Field)cid_field_records;+++ for (;;)+ {+ FT_Byte* name;+++ name = (FT_Byte*)keyword->ident;+ if ( !name )+ break;++ if ( cur[0] == name[0] &&+ len == (FT_PtrDist)ft_strlen( (const char*)name ) )+ {+ FT_PtrDist n;+++ for ( n = 1; n < len; n++ )+ if ( cur[n] != name[n] )+ break;++ if ( n >= len )+ {+ /* we found it - run the parsing callback */+ parser->root.error = cid_load_keyword( face,+ loader,+ keyword );+ if ( parser->root.error )+ return parser->root.error;+ break;+ }+ }+ keyword++;+ }+ }+ }++ cur = parser->root.cursor;+ }+ }+ return parser->root.error;+ }+++ /* read the subrmap and the subrs of each font dict */+ static FT_Error+ cid_read_subrs( CID_Face face )+ {+ CID_FaceInfo cid = &face->cid;+ FT_Memory memory = face->root.memory;+ FT_Stream stream = face->cid_stream;+ FT_Error error;+ FT_Int n;+ CID_Subrs subr;+ FT_UInt max_offsets = 0;+ FT_ULong* offsets = 0;+ PSAux_Service psaux = (PSAux_Service)face->psaux;+++ if ( FT_NEW_ARRAY( face->subrs, cid->num_dicts ) )+ goto Exit;++ subr = face->subrs;+ for ( n = 0; n < cid->num_dicts; n++, subr++ )+ {+ CID_FaceDict dict = cid->font_dicts + n;+ FT_Int lenIV = dict->private_dict.lenIV;+ FT_UInt count, num_subrs = dict->num_subrs;+ FT_ULong data_len;+ FT_Byte* p;+++ /* reallocate offsets array if needed */+ if ( num_subrs + 1 > max_offsets )+ {+ FT_UInt new_max = FT_PAD_CEIL( num_subrs + 1, 4 );+++ if ( FT_RENEW_ARRAY( offsets, max_offsets, new_max ) )+ goto Fail;++ max_offsets = new_max;+ }++ /* read the subrmap's offsets */+ if ( FT_STREAM_SEEK( cid->data_offset + dict->subrmap_offset ) ||+ FT_FRAME_ENTER( ( num_subrs + 1 ) * dict->sd_bytes ) )+ goto Fail;++ p = (FT_Byte*)stream->cursor;+ for ( count = 0; count <= num_subrs; count++ )+ offsets[count] = cid_get_offset( &p, (FT_Byte)dict->sd_bytes );++ FT_FRAME_EXIT();++ /* now, compute the size of subrs charstrings, */+ /* allocate, and read them */+ data_len = offsets[num_subrs] - offsets[0];++ if ( FT_NEW_ARRAY( subr->code, num_subrs + 1 ) ||+ FT_ALLOC( subr->code[0], data_len ) )+ goto Fail;++ if ( FT_STREAM_SEEK( cid->data_offset + offsets[0] ) ||+ FT_STREAM_READ( subr->code[0], data_len ) )+ goto Fail;++ /* set up pointers */+ for ( count = 1; count <= num_subrs; count++ )+ {+ FT_ULong len;+++ len = offsets[count] - offsets[count - 1];+ subr->code[count] = subr->code[count - 1] + len;+ }++ /* decrypt subroutines, but only if lenIV >= 0 */+ if ( lenIV >= 0 )+ {+ for ( count = 0; count < num_subrs; count++ )+ {+ FT_ULong len;+++ len = offsets[count + 1] - offsets[count];+ psaux->t1_decrypt( subr->code[count], len, 4330 );+ }+ }++ subr->num_subrs = num_subrs;+ }++ Exit:+ FT_FREE( offsets );+ return error;++ Fail:+ if ( face->subrs )+ {+ for ( n = 0; n < cid->num_dicts; n++ )+ {+ if ( face->subrs[n].code )+ FT_FREE( face->subrs[n].code[0] );++ FT_FREE( face->subrs[n].code );+ }+ FT_FREE( face->subrs );+ }+ goto Exit;+ }+++ static void+ t1_init_loader( CID_Loader* loader,+ CID_Face face )+ {+ FT_UNUSED( face );++ FT_MEM_ZERO( loader, sizeof ( *loader ) );+ }+++ static void+ t1_done_loader( CID_Loader* loader )+ {+ CID_Parser* parser = &loader->parser;+++ /* finalize parser */+ cid_parser_done( parser );+ }+++ static FT_Error+ cid_hex_to_binary( FT_Byte* data,+ FT_Long data_len,+ FT_ULong offset,+ CID_Face face )+ {+ FT_Stream stream = face->root.stream;+ FT_Error error;++ FT_Byte buffer[256];+ FT_Byte *p, *plimit;+ FT_Byte *d, *dlimit;+ FT_Byte val;++ FT_Bool upper_nibble, done;+++ if ( FT_STREAM_SEEK( offset ) )+ goto Exit;++ d = data;+ dlimit = d + data_len;+ p = buffer;+ plimit = p;++ upper_nibble = 1;+ done = 0;++ while ( d < dlimit )+ {+ if ( p >= plimit )+ {+ FT_ULong oldpos = FT_STREAM_POS();+ FT_ULong size = stream->size - oldpos;+++ if ( size == 0 )+ {+ error = CID_Err_Syntax_Error;+ goto Exit;+ }++ if ( FT_STREAM_READ( buffer, 256 > size ? size : 256 ) )+ goto Exit;+ p = buffer;+ plimit = p + FT_STREAM_POS() - oldpos;+ }++ if ( ft_isdigit( *p ) )+ val = (FT_Byte)( *p - '0' );+ else if ( *p >= 'a' && *p <= 'f' )+ val = (FT_Byte)( *p - 'a' );+ else if ( *p >= 'A' && *p <= 'F' )+ val = (FT_Byte)( *p - 'A' + 10 );+ else if ( *p == ' ' ||+ *p == '\t' ||+ *p == '\r' ||+ *p == '\n' ||+ *p == '\f' ||+ *p == '\0' )+ {+ p++;+ continue;+ }+ else if ( *p == '>' )+ {+ val = 0;+ done = 1;+ }+ else+ {+ error = CID_Err_Syntax_Error;+ goto Exit;+ }++ if ( upper_nibble )+ *d = (FT_Byte)( val << 4 );+ else+ {+ *d = (FT_Byte)( *d + val );+ d++;+ }++ upper_nibble = (FT_Byte)( 1 - upper_nibble );++ if ( done )+ break;++ p++;+ }++ error = CID_Err_Ok;++ Exit:+ return error;+ }+++ FT_LOCAL_DEF( FT_Error )+ cid_face_open( CID_Face face,+ FT_Int face_index )+ {+ CID_Loader loader;+ CID_Parser* parser;+ FT_Memory memory = face->root.memory;+ FT_Error error;+++ t1_init_loader( &loader, face );++ parser = &loader.parser;+ error = cid_parser_new( parser, face->root.stream, face->root.memory,+ (PSAux_Service)face->psaux );+ if ( error )+ goto Exit;++ error = cid_parse_dict( face, &loader,+ parser->postscript,+ parser->postscript_len );+ if ( error )+ goto Exit;++ if ( face_index < 0 )+ goto Exit;++ if ( FT_NEW( face->cid_stream ) )+ goto Exit;++ if ( parser->binary_length )+ {+ /* we must convert the data section from hexadecimal to binary */+ if ( FT_ALLOC( face->binary_data, parser->binary_length ) ||+ cid_hex_to_binary( face->binary_data, parser->binary_length,+ parser->data_offset, face ) )+ goto Exit;++ FT_Stream_OpenMemory( face->cid_stream,+ face->binary_data, parser->binary_length );+ face->cid.data_offset = 0;+ }+ else+ {+ *face->cid_stream = *face->root.stream;+ face->cid.data_offset = loader.parser.data_offset;+ }++ error = cid_read_subrs( face );++ Exit:+ t1_done_loader( &loader );+ return error;+ }+++/* END */
+ src/cid/cidload.h view
@@ -0,0 +1,53 @@+/***************************************************************************/+/* */+/* cidload.h */+/* */+/* CID-keyed Type1 font loader (specification). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004 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 __CIDLOAD_H__+#define __CIDLOAD_H__+++#include <ft2build.h>+#include FT_INTERNAL_STREAM_H+#include "cidparse.h"+++FT_BEGIN_HEADER+++ typedef struct CID_Loader_+ {+ CID_Parser parser; /* parser used to read the stream */+ FT_Int num_chars; /* number of characters in encoding */++ } CID_Loader;+++ FT_LOCAL( FT_Long )+ cid_get_offset( FT_Byte** start,+ FT_Byte offsize );++ FT_LOCAL( FT_Error )+ cid_face_open( CID_Face face,+ FT_Int face_index );+++FT_END_HEADER++#endif /* __CIDLOAD_H__ */+++/* END */
+ src/cid/cidobjs.c view
@@ -0,0 +1,482 @@+/***************************************************************************/+/* */+/* cidobjs.c */+/* */+/* CID objects manager (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2008, 2010 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_STREAM_H++#include "cidgload.h"+#include "cidload.h"++#include FT_SERVICE_POSTSCRIPT_CMAPS_H+#include FT_INTERNAL_POSTSCRIPT_AUX_H+#include FT_INTERNAL_POSTSCRIPT_HINTS_H++#include "ciderrs.h"+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_cidobjs+++ /*************************************************************************/+ /* */+ /* SLOT FUNCTIONS */+ /* */+ /*************************************************************************/++ FT_LOCAL_DEF( void )+ cid_slot_done( FT_GlyphSlot slot )+ {+ slot->internal->glyph_hints = 0;+ }+++ FT_LOCAL_DEF( FT_Error )+ cid_slot_init( FT_GlyphSlot slot )+ {+ CID_Face face;+ PSHinter_Service pshinter;+++ face = (CID_Face)slot->face;+ pshinter = (PSHinter_Service)face->pshinter;++ if ( pshinter )+ {+ FT_Module module;+++ module = FT_Get_Module( slot->face->driver->root.library,+ "pshinter" );+ if ( module )+ {+ T1_Hints_Funcs funcs;+++ funcs = pshinter->get_t1_funcs( module );+ slot->internal->glyph_hints = (void*)funcs;+ }+ }++ return 0;+ }+++ /*************************************************************************/+ /* */+ /* SIZE FUNCTIONS */+ /* */+ /*************************************************************************/+++ static PSH_Globals_Funcs+ cid_size_get_globals_funcs( CID_Size size )+ {+ CID_Face face = (CID_Face)size->root.face;+ PSHinter_Service pshinter = (PSHinter_Service)face->pshinter;+ FT_Module module;+++ module = FT_Get_Module( size->root.face->driver->root.library,+ "pshinter" );+ return ( module && pshinter && pshinter->get_globals_funcs )+ ? pshinter->get_globals_funcs( module )+ : 0;+ }+++ FT_LOCAL_DEF( void )+ cid_size_done( FT_Size cidsize ) /* CID_Size */+ {+ CID_Size size = (CID_Size)cidsize;+++ if ( cidsize->internal )+ {+ PSH_Globals_Funcs funcs;+++ funcs = cid_size_get_globals_funcs( size );+ if ( funcs )+ funcs->destroy( (PSH_Globals)cidsize->internal );++ cidsize->internal = 0;+ }+ }+++ FT_LOCAL_DEF( FT_Error )+ cid_size_init( FT_Size cidsize ) /* CID_Size */+ {+ CID_Size size = (CID_Size)cidsize;+ FT_Error error = CID_Err_Ok;+ PSH_Globals_Funcs funcs = cid_size_get_globals_funcs( size );+++ if ( funcs )+ {+ PSH_Globals globals;+ CID_Face face = (CID_Face)cidsize->face;+ CID_FaceDict dict = face->cid.font_dicts + face->root.face_index;+ PS_Private priv = &dict->private_dict;+++ error = funcs->create( cidsize->face->memory, priv, &globals );+ if ( !error )+ cidsize->internal = (FT_Size_Internal)(void*)globals;+ }++ return error;+ }+++ FT_LOCAL( FT_Error )+ cid_size_request( FT_Size size,+ FT_Size_Request req )+ {+ PSH_Globals_Funcs funcs;+++ FT_Request_Metrics( size->face, req );++ funcs = cid_size_get_globals_funcs( (CID_Size)size );++ if ( funcs )+ funcs->set_scale( (PSH_Globals)size->internal,+ size->metrics.x_scale,+ size->metrics.y_scale,+ 0, 0 );++ return CID_Err_Ok;+ }+++ /*************************************************************************/+ /* */+ /* FACE FUNCTIONS */+ /* */+ /*************************************************************************/++ /*************************************************************************/+ /* */+ /* <Function> */+ /* cid_face_done */+ /* */+ /* <Description> */+ /* Finalizes a given face object. */+ /* */+ /* <Input> */+ /* face :: A pointer to the face object to destroy. */+ /* */+ FT_LOCAL_DEF( void )+ cid_face_done( FT_Face cidface ) /* CID_Face */+ {+ CID_Face face = (CID_Face)cidface;+ FT_Memory memory;+ CID_FaceInfo cid;+ PS_FontInfo info;+++ if ( !face )+ return;++ cid = &face->cid;+ info = &cid->font_info;+ memory = cidface->memory;++ /* release subrs */+ if ( face->subrs )+ {+ FT_Int n;+++ for ( n = 0; n < cid->num_dicts; n++ )+ {+ CID_Subrs subr = face->subrs + n;+++ if ( subr->code )+ {+ FT_FREE( subr->code[0] );+ FT_FREE( subr->code );+ }+ }++ FT_FREE( face->subrs );+ }++ /* release FontInfo strings */+ FT_FREE( info->version );+ FT_FREE( info->notice );+ FT_FREE( info->full_name );+ FT_FREE( info->family_name );+ FT_FREE( info->weight );++ /* release font dictionaries */+ FT_FREE( cid->font_dicts );+ cid->num_dicts = 0;++ /* release other strings */+ FT_FREE( cid->cid_font_name );+ FT_FREE( cid->registry );+ FT_FREE( cid->ordering );++ cidface->family_name = 0;+ cidface->style_name = 0;++ FT_FREE( face->binary_data );+ FT_FREE( face->cid_stream );+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* cid_face_init */+ /* */+ /* <Description> */+ /* Initializes a given CID face object. */+ /* */+ /* <Input> */+ /* stream :: The source font stream. */+ /* */+ /* face_index :: The index of the font face in the resource. */+ /* */+ /* num_params :: Number of additional generic parameters. Ignored. */+ /* */+ /* params :: Additional generic parameters. Ignored. */+ /* */+ /* <InOut> */+ /* face :: The newly built face object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ cid_face_init( FT_Stream stream,+ FT_Face cidface, /* CID_Face */+ FT_Int face_index,+ FT_Int num_params,+ FT_Parameter* params )+ {+ CID_Face face = (CID_Face)cidface;+ FT_Error error;+ PSAux_Service psaux;+ PSHinter_Service pshinter;++ FT_UNUSED( num_params );+ FT_UNUSED( params );+ FT_UNUSED( stream );+++ cidface->num_faces = 1;++ psaux = (PSAux_Service)face->psaux;+ if ( !psaux )+ {+ psaux = (PSAux_Service)FT_Get_Module_Interface(+ FT_FACE_LIBRARY( face ), "psaux" );++ face->psaux = psaux;+ }++ pshinter = (PSHinter_Service)face->pshinter;+ if ( !pshinter )+ {+ pshinter = (PSHinter_Service)FT_Get_Module_Interface(+ FT_FACE_LIBRARY( face ), "pshinter" );++ face->pshinter = pshinter;+ }++ /* open the tokenizer; this will also check the font format */+ if ( FT_STREAM_SEEK( 0 ) )+ goto Exit;++ error = cid_face_open( face, face_index );+ if ( error )+ goto Exit;++ /* if we just wanted to check the format, leave successfully now */+ if ( face_index < 0 )+ goto Exit;++ /* check the face index */+ /* XXX: handle CID fonts with more than a single face */+ if ( face_index != 0 )+ {+ FT_ERROR(( "cid_face_init: invalid face index\n" ));+ error = CID_Err_Invalid_Argument;+ goto Exit;+ }++ /* now load the font program into the face object */++ /* initialize the face object fields */++ /* set up root face fields */+ {+ CID_FaceInfo cid = &face->cid;+ PS_FontInfo info = &cid->font_info;+++ cidface->num_glyphs = cid->cid_count;+ cidface->num_charmaps = 0;++ cidface->face_index = face_index;+ cidface->face_flags = FT_FACE_FLAG_SCALABLE | /* scalable outlines */+ FT_FACE_FLAG_HORIZONTAL | /* horizontal data */+ FT_FACE_FLAG_HINTER; /* has native hinter */++ if ( info->is_fixed_pitch )+ cidface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;++ /* XXX: TODO: add kerning with .afm support */++ /* get style name -- be careful, some broken fonts only */+ /* have a /FontName dictionary entry! */+ cidface->family_name = info->family_name;+ /* assume "Regular" style if we don't know better */+ cidface->style_name = (char *)"Regular";+ if ( cidface->family_name )+ {+ char* full = info->full_name;+ char* family = cidface->family_name;+++ if ( full )+ {+ while ( *full )+ {+ if ( *full == *family )+ {+ family++;+ full++;+ }+ else+ {+ if ( *full == ' ' || *full == '-' )+ full++;+ else if ( *family == ' ' || *family == '-' )+ family++;+ else+ {+ if ( !*family )+ cidface->style_name = full;+ break;+ }+ }+ }+ }+ }+ else+ {+ /* do we have a `/FontName'? */+ if ( cid->cid_font_name )+ cidface->family_name = cid->cid_font_name;+ }++ /* compute style flags */+ cidface->style_flags = 0;+ if ( info->italic_angle )+ cidface->style_flags |= FT_STYLE_FLAG_ITALIC;+ if ( info->weight )+ {+ if ( !ft_strcmp( info->weight, "Bold" ) ||+ !ft_strcmp( info->weight, "Black" ) )+ cidface->style_flags |= FT_STYLE_FLAG_BOLD;+ }++ /* no embedded bitmap support */+ cidface->num_fixed_sizes = 0;+ cidface->available_sizes = 0;++ cidface->bbox.xMin = cid->font_bbox.xMin >> 16;+ cidface->bbox.yMin = cid->font_bbox.yMin >> 16;+ /* no `U' suffix here to 0xFFFF! */+ cidface->bbox.xMax = ( cid->font_bbox.xMax + 0xFFFF ) >> 16;+ cidface->bbox.yMax = ( cid->font_bbox.yMax + 0xFFFF ) >> 16;++ if ( !cidface->units_per_EM )+ cidface->units_per_EM = 1000;++ cidface->ascender = (FT_Short)( cidface->bbox.yMax );+ cidface->descender = (FT_Short)( cidface->bbox.yMin );++ cidface->height = (FT_Short)( ( cidface->units_per_EM * 12 ) / 10 );+ if ( cidface->height < cidface->ascender - cidface->descender )+ cidface->height = (FT_Short)( cidface->ascender - cidface->descender );++ cidface->underline_position = (FT_Short)info->underline_position;+ cidface->underline_thickness = (FT_Short)info->underline_thickness;+ }++ Exit:+ return error;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* cid_driver_init */+ /* */+ /* <Description> */+ /* Initializes a given CID driver object. */+ /* */+ /* <Input> */+ /* driver :: A handle to the target driver object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ cid_driver_init( FT_Module driver )+ {+ FT_UNUSED( driver );++ return CID_Err_Ok;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* cid_driver_done */+ /* */+ /* <Description> */+ /* Finalizes a given CID driver. */+ /* */+ /* <Input> */+ /* driver :: A handle to the target CID driver. */+ /* */+ FT_LOCAL_DEF( void )+ cid_driver_done( FT_Module driver )+ {+ FT_UNUSED( driver );+ }+++/* END */
+ src/cid/cidobjs.h view
@@ -0,0 +1,154 @@+/***************************************************************************/+/* */+/* cidobjs.h */+/* */+/* CID objects manager (specification). */+/* */+/* Copyright 1996-2001, 2002, 2004, 2006 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 __CIDOBJS_H__+#define __CIDOBJS_H__+++#include <ft2build.h>+#include FT_INTERNAL_OBJECTS_H+#include FT_CONFIG_CONFIG_H+#include FT_INTERNAL_TYPE1_TYPES_H+++FT_BEGIN_HEADER+++ /* The following structures must be defined by the hinter */+ typedef struct CID_Size_Hints_ CID_Size_Hints;+ typedef struct CID_Glyph_Hints_ CID_Glyph_Hints;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* CID_Driver */+ /* */+ /* <Description> */+ /* A handle to a Type 1 driver object. */+ /* */+ typedef struct CID_DriverRec_* CID_Driver;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* CID_Size */+ /* */+ /* <Description> */+ /* A handle to a Type 1 size object. */+ /* */+ typedef struct CID_SizeRec_* CID_Size;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* CID_GlyphSlot */+ /* */+ /* <Description> */+ /* A handle to a Type 1 glyph slot object. */+ /* */+ typedef struct CID_GlyphSlotRec_* CID_GlyphSlot;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* CID_CharMap */+ /* */+ /* <Description> */+ /* A handle to a Type 1 character mapping object. */+ /* */+ /* <Note> */+ /* The Type 1 format doesn't use a charmap but an encoding table. */+ /* The driver is responsible for making up charmap objects */+ /* corresponding to these tables. */+ /* */+ typedef struct CID_CharMapRec_* CID_CharMap;+++ /*************************************************************************/+ /* */+ /* HERE BEGINS THE TYPE 1 SPECIFIC STUFF */+ /* */+ /*************************************************************************/+++ typedef struct CID_SizeRec_+ {+ FT_SizeRec root;+ FT_Bool valid;++ } CID_SizeRec;+++ typedef struct CID_GlyphSlotRec_+ {+ FT_GlyphSlotRec root;++ FT_Bool hint;+ FT_Bool scaled;++ FT_Fixed x_scale;+ FT_Fixed y_scale;++ } CID_GlyphSlotRec;+++ FT_LOCAL( void )+ cid_slot_done( FT_GlyphSlot slot );++ FT_LOCAL( FT_Error )+ cid_slot_init( FT_GlyphSlot slot );+++ FT_LOCAL( void )+ cid_size_done( FT_Size size ); /* CID_Size */++ FT_LOCAL( FT_Error )+ cid_size_init( FT_Size size ); /* CID_Size */++ FT_LOCAL( FT_Error )+ cid_size_request( FT_Size size, /* CID_Size */+ FT_Size_Request req );++ FT_LOCAL( FT_Error )+ cid_face_init( FT_Stream stream,+ FT_Face face, /* CID_Face */+ FT_Int face_index,+ FT_Int num_params,+ FT_Parameter* params );++ FT_LOCAL( void )+ cid_face_done( FT_Face face ); /* CID_Face */+++ FT_LOCAL( FT_Error )+ cid_driver_init( FT_Module driver );++ FT_LOCAL( void )+ cid_driver_done( FT_Module driver );+++FT_END_HEADER++#endif /* __CIDOBJS_H__ */+++/* END */
+ src/cid/cidparse.c view
@@ -0,0 +1,225 @@+/***************************************************************************/+/* */+/* cidparse.c */+/* */+/* CID-keyed Type1 parser (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009 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_INTERNAL_STREAM_H++#include "cidparse.h"++#include "ciderrs.h"+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_cidparse+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** INPUT STREAM PARSER *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ FT_LOCAL_DEF( FT_Error )+ cid_parser_new( CID_Parser* parser,+ FT_Stream stream,+ FT_Memory memory,+ PSAux_Service psaux )+ {+ FT_Error error;+ FT_ULong base_offset, offset, ps_len;+ FT_Byte *cur, *limit;+ FT_Byte *arg1, *arg2;+++ FT_MEM_ZERO( parser, sizeof ( *parser ) );+ psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );++ parser->stream = stream;++ base_offset = FT_STREAM_POS();++ /* first of all, check the font format in the header */+ if ( FT_FRAME_ENTER( 31 ) )+ goto Exit;++ if ( ft_strncmp( (char *)stream->cursor,+ "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) )+ {+ FT_TRACE2(( "[not a valid CID-keyed font]\n" ));+ error = CID_Err_Unknown_File_Format;+ }++ FT_FRAME_EXIT();+ if ( error )+ goto Exit;++ Again:+ /* now, read the rest of the file until we find */+ /* `StartData' or `/sfnts' */+ {+ FT_Byte buffer[256 + 10];+ FT_Long read_len = 256 + 10; /* same as signed FT_Stream->size */+ FT_Byte* p = buffer;+++ for ( offset = FT_STREAM_POS(); ; offset += 256 )+ {+ FT_Long stream_len; /* same as signed FT_Stream->size */+++ stream_len = stream->size - FT_STREAM_POS();+ if ( stream_len == 0 )+ {+ FT_TRACE2(( "cid_parser_new: no `StartData' keyword found\n" ));+ error = CID_Err_Unknown_File_Format;+ goto Exit;+ }++ read_len = FT_MIN( read_len, stream_len );+ if ( FT_STREAM_READ( p, read_len ) )+ goto Exit;++ if ( read_len < 256 )+ p[read_len] = '\0';++ limit = p + read_len - 10;++ for ( p = buffer; p < limit; p++ )+ {+ if ( p[0] == 'S' && ft_strncmp( (char*)p, "StartData", 9 ) == 0 )+ {+ /* save offset of binary data after `StartData' */+ offset += p - buffer + 10;+ goto Found;+ }+ else if ( p[1] == 's' && ft_strncmp( (char*)p, "/sfnts", 6 ) == 0 )+ {+ offset += p - buffer + 7;+ goto Found;+ }+ }++ FT_MEM_MOVE( buffer, p, 10 );+ read_len = 256;+ p = buffer + 10;+ }+ }++ Found:+ /* We have found the start of the binary data or the `/sfnts' token. */+ /* Now rewind and extract the frame corresponding to this PostScript */+ /* section. */++ ps_len = offset - base_offset;+ if ( FT_STREAM_SEEK( base_offset ) ||+ FT_FRAME_EXTRACT( ps_len, parser->postscript ) )+ goto Exit;++ parser->data_offset = offset;+ parser->postscript_len = ps_len;+ parser->root.base = parser->postscript;+ parser->root.cursor = parser->postscript;+ parser->root.limit = parser->root.cursor + ps_len;+ parser->num_dict = -1;++ /* Finally, we check whether `StartData' or `/sfnts' was real -- */+ /* it could be in a comment or string. We also get the arguments */+ /* of `StartData' to find out whether the data is represented in */+ /* binary or hex format. */++ arg1 = parser->root.cursor;+ cid_parser_skip_PS_token( parser );+ cid_parser_skip_spaces ( parser );+ arg2 = parser->root.cursor;+ cid_parser_skip_PS_token( parser );+ cid_parser_skip_spaces ( parser );++ limit = parser->root.limit;+ cur = parser->root.cursor;++ while ( cur < limit )+ {+ if ( parser->root.error )+ {+ error = parser->root.error;+ goto Exit;+ }++ if ( cur[0] == 'S' && ft_strncmp( (char*)cur, "StartData", 9 ) == 0 )+ {+ if ( ft_strncmp( (char*)arg1, "(Hex)", 5 ) == 0 )+ parser->binary_length = ft_atol( (const char *)arg2 );++ limit = parser->root.limit;+ cur = parser->root.cursor;+ goto Exit;+ }+ else if ( cur[1] == 's' && ft_strncmp( (char*)cur, "/sfnts", 6 ) == 0 )+ {+ FT_TRACE2(( "cid_parser_new: cannot handle Type 11 fonts\n" ));+ error = CID_Err_Unknown_File_Format;+ goto Exit;+ }++ cid_parser_skip_PS_token( parser );+ cid_parser_skip_spaces ( parser );+ arg1 = arg2;+ arg2 = cur;+ cur = parser->root.cursor;+ }++ /* we haven't found the correct `StartData'; go back and continue */+ /* searching */+ FT_FRAME_RELEASE( parser->postscript );+ if ( !FT_STREAM_SEEK( offset ) )+ goto Again;++ Exit:+ return error;+ }+++ FT_LOCAL_DEF( void )+ cid_parser_done( CID_Parser* parser )+ {+ /* always free the private dictionary */+ if ( parser->postscript )+ {+ FT_Stream stream = parser->stream;+++ FT_FRAME_RELEASE( parser->postscript );+ }+ parser->root.funcs.done( &parser->root );+ }+++/* END */
+ src/cid/cidparse.h view
@@ -0,0 +1,123 @@+/***************************************************************************/+/* */+/* cidparse.h */+/* */+/* CID-keyed Type1 parser (specification). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004 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 __CIDPARSE_H__+#define __CIDPARSE_H__+++#include <ft2build.h>+#include FT_INTERNAL_TYPE1_TYPES_H+#include FT_INTERNAL_STREAM_H+#include FT_INTERNAL_POSTSCRIPT_AUX_H+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* CID_Parser */+ /* */+ /* <Description> */+ /* A CID_Parser is an object used to parse a Type 1 fonts very */+ /* quickly. */+ /* */+ /* <Fields> */+ /* root :: The root PS_ParserRec fields. */+ /* */+ /* stream :: The current input stream. */+ /* */+ /* postscript :: A pointer to the data to be parsed. */+ /* */+ /* postscript_len :: The length of the data to be parsed. */+ /* */+ /* data_offset :: The start position of the binary data (i.e., the */+ /* end of the data to be parsed. */+ /* */+ /* binary_length :: The length of the data after the `StartData' */+ /* command if the data format is hexadecimal. */+ /* */+ /* cid :: A structure which holds the information about */+ /* the current font. */+ /* */+ /* num_dict :: The number of font dictionaries. */+ /* */+ typedef struct CID_Parser_+ {+ PS_ParserRec root;+ FT_Stream stream;++ FT_Byte* postscript;+ FT_Long postscript_len;++ FT_ULong data_offset;++ FT_Long binary_length;++ CID_FaceInfo cid;+ FT_Int num_dict;++ } CID_Parser;+++ FT_LOCAL( FT_Error )+ cid_parser_new( CID_Parser* parser,+ FT_Stream stream,+ FT_Memory memory,+ PSAux_Service psaux );++ FT_LOCAL( void )+ cid_parser_done( CID_Parser* parser );+++ /*************************************************************************/+ /* */+ /* PARSING ROUTINES */+ /* */+ /*************************************************************************/++#define cid_parser_skip_spaces( p ) \+ (p)->root.funcs.skip_spaces( &(p)->root )+#define cid_parser_skip_PS_token( p ) \+ (p)->root.funcs.skip_PS_token( &(p)->root )++#define cid_parser_to_int( p ) (p)->root.funcs.to_int( &(p)->root )+#define cid_parser_to_fixed( p, t ) (p)->root.funcs.to_fixed( &(p)->root, t )++#define cid_parser_to_coord_array( p, m, c ) \+ (p)->root.funcs.to_coord_array( &(p)->root, m, c )+#define cid_parser_to_fixed_array( p, m, f, t ) \+ (p)->root.funcs.to_fixed_array( &(p)->root, m, f, t )+#define cid_parser_to_token( p, t ) \+ (p)->root.funcs.to_token( &(p)->root, t )+#define cid_parser_to_token_array( p, t, m, c ) \+ (p)->root.funcs.to_token_array( &(p)->root, t, m, c )++#define cid_parser_load_field( p, f, o ) \+ (p)->root.funcs.load_field( &(p)->root, f, o, 0, 0 )+#define cid_parser_load_field_table( p, f, o ) \+ (p)->root.funcs.load_field_table( &(p)->root, f, o, 0, 0 )+++FT_END_HEADER++#endif /* __CIDPARSE_H__ */+++/* END */
+ src/cid/cidriver.c view
@@ -0,0 +1,240 @@+/***************************************************************************/+/* */+/* cidriver.c */+/* */+/* CID driver interface (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2008, 2009 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 "cidriver.h"+#include "cidgload.h"+#include FT_INTERNAL_DEBUG_H++#include "ciderrs.h"++#include FT_SERVICE_POSTSCRIPT_NAME_H+#include FT_SERVICE_XFREE86_NAME_H+#include FT_SERVICE_POSTSCRIPT_INFO_H+#include FT_SERVICE_CID_H+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_ciddriver+++ /*+ * POSTSCRIPT NAME SERVICE+ *+ */++ static const char*+ cid_get_postscript_name( CID_Face face )+ {+ const char* result = face->cid.cid_font_name;+++ if ( result && result[0] == '/' )+ result++;++ return result;+ }+++ static const FT_Service_PsFontNameRec cid_service_ps_name =+ {+ (FT_PsName_GetFunc) cid_get_postscript_name+ };+++ /*+ * POSTSCRIPT INFO SERVICE+ *+ */++ static FT_Error+ cid_ps_get_font_info( FT_Face face,+ PS_FontInfoRec* afont_info )+ {+ *afont_info = ((CID_Face)face)->cid.font_info;++ return CID_Err_Ok;+ }++ static FT_Error+ cid_ps_get_font_extra( FT_Face face,+ PS_FontExtraRec* afont_extra )+ {+ *afont_extra = ((CID_Face)face)->font_extra;++ return CID_Err_Ok;+ }++ static const FT_Service_PsInfoRec cid_service_ps_info =+ {+ (PS_GetFontInfoFunc) cid_ps_get_font_info,+ (PS_GetFontExtraFunc) cid_ps_get_font_extra,+ (PS_HasGlyphNamesFunc) NULL, /* unsupported with CID fonts */+ (PS_GetFontPrivateFunc)NULL /* unsupported */+ };+++ /*+ * CID INFO SERVICE+ *+ */+ static FT_Error+ cid_get_ros( CID_Face face,+ const char* *registry,+ const char* *ordering,+ FT_Int *supplement )+ {+ CID_FaceInfo cid = &face->cid;+++ if ( registry )+ *registry = cid->registry;+ + if ( ordering )+ *ordering = cid->ordering;++ if ( supplement )+ *supplement = cid->supplement;+ + return CID_Err_Ok;+ }+++ static FT_Error+ cid_get_is_cid( CID_Face face,+ FT_Bool *is_cid )+ {+ FT_Error error = CID_Err_Ok;+ FT_UNUSED( face );+++ if ( is_cid )+ *is_cid = 1; /* cid driver is only used for CID keyed fonts */++ return error;+ }+++ static FT_Error+ cid_get_cid_from_glyph_index( CID_Face face,+ FT_UInt glyph_index,+ FT_UInt *cid )+ {+ FT_Error error = CID_Err_Ok;+ FT_UNUSED( face );+++ if ( cid )+ *cid = glyph_index; /* identity mapping */++ return error;+ }+++ static const FT_Service_CIDRec cid_service_cid_info =+ {+ (FT_CID_GetRegistryOrderingSupplementFunc)cid_get_ros,+ (FT_CID_GetIsInternallyCIDKeyedFunc) cid_get_is_cid,+ (FT_CID_GetCIDFromGlyphIndexFunc) cid_get_cid_from_glyph_index+ };+++ /*+ * SERVICE LIST+ *+ */++ static const FT_ServiceDescRec cid_services[] =+ {+ { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_CID },+ { FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cid_service_ps_name },+ { FT_SERVICE_ID_POSTSCRIPT_INFO, &cid_service_ps_info },+ { FT_SERVICE_ID_CID, &cid_service_cid_info },+ { NULL, NULL }+ };+++ FT_CALLBACK_DEF( FT_Module_Interface )+ cid_get_interface( FT_Module module,+ const char* cid_interface )+ {+ FT_UNUSED( module );++ return ft_service_list_lookup( cid_services, cid_interface );+ }++++ FT_CALLBACK_TABLE_DEF+ const FT_Driver_ClassRec t1cid_driver_class =+ {+ /* first of all, the FT_Module_Class fields */+ {+ FT_MODULE_FONT_DRIVER |+ FT_MODULE_DRIVER_SCALABLE |+ FT_MODULE_DRIVER_HAS_HINTER,++ sizeof( FT_DriverRec ),+ "t1cid", /* module name */+ 0x10000L, /* version 1.0 of driver */+ 0x20000L, /* requires FreeType 2.0 */++ 0,++ cid_driver_init,+ cid_driver_done,+ cid_get_interface+ },++ /* then the other font drivers fields */+ sizeof( CID_FaceRec ),+ sizeof( CID_SizeRec ),+ sizeof( CID_GlyphSlotRec ),++ cid_face_init,+ cid_face_done,++ cid_size_init,+ cid_size_done,+ cid_slot_init,+ cid_slot_done,++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS+ ft_stub_set_char_sizes,+ ft_stub_set_pixel_sizes,+#endif++ cid_slot_load_glyph,++ 0, /* FT_Face_GetKerningFunc */+ 0, /* FT_Face_AttachFunc */++ 0, /* FT_Face_GetAdvancesFunc */++ cid_size_request,+ 0 /* FT_Size_SelectFunc */+ };+++/* END */
+ src/cid/cidriver.h view
@@ -0,0 +1,43 @@+/***************************************************************************/+/* */+/* cidriver.h */+/* */+/* High-level CID driver interface (specification). */+/* */+/* Copyright 1996-2001, 2002 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 __CIDRIVER_H__+#define __CIDRIVER_H__+++#include <ft2build.h>+#include FT_INTERNAL_DRIVER_H+++FT_BEGIN_HEADER++#ifdef FT_CONFIG_OPTION_PIC+#error "this module does not support PIC yet"+#endif +++ FT_CALLBACK_TABLE+ const FT_Driver_ClassRec t1cid_driver_class;+++FT_END_HEADER++#endif /* __CIDRIVER_H__ */+++/* END */
+ src/cid/cidtoken.h view
@@ -0,0 +1,112 @@+/***************************************************************************/+/* */+/* cidtoken.h */+/* */+/* CID token definitions (specification only). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2006, 2008, 2009 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. */+/* */+/***************************************************************************/+++#undef FT_STRUCTURE+#define FT_STRUCTURE CID_FaceInfoRec+#undef T1CODE+#define T1CODE T1_FIELD_LOCATION_CID_INFO++ T1_FIELD_KEY ( "CIDFontName", cid_font_name, 0 )+ T1_FIELD_FIXED ( "CIDFontVersion", cid_version, 0 )+ T1_FIELD_NUM ( "CIDFontType", cid_font_type, 0 )+ T1_FIELD_STRING( "Registry", registry, 0 )+ T1_FIELD_STRING( "Ordering", ordering, 0 )+ T1_FIELD_NUM ( "Supplement", supplement, 0 )+ T1_FIELD_NUM ( "UIDBase", uid_base, 0 )+ T1_FIELD_NUM ( "CIDMapOffset", cidmap_offset, 0 )+ T1_FIELD_NUM ( "FDBytes", fd_bytes, 0 )+ T1_FIELD_NUM ( "GDBytes", gd_bytes, 0 )+ T1_FIELD_NUM ( "CIDCount", cid_count, 0 )+++#undef FT_STRUCTURE+#define FT_STRUCTURE PS_FontInfoRec+#undef T1CODE+#define T1CODE T1_FIELD_LOCATION_FONT_INFO++ T1_FIELD_STRING( "version", version, 0 )+ T1_FIELD_STRING( "Notice", notice, 0 )+ T1_FIELD_STRING( "FullName", full_name, 0 )+ T1_FIELD_STRING( "FamilyName", family_name, 0 )+ T1_FIELD_STRING( "Weight", weight, 0 )+ T1_FIELD_NUM ( "ItalicAngle", italic_angle, 0 )+ T1_FIELD_BOOL ( "isFixedPitch", is_fixed_pitch, 0 )+ T1_FIELD_NUM ( "UnderlinePosition", underline_position, 0 )+ T1_FIELD_NUM ( "UnderlineThickness", underline_thickness, 0 )++#undef FT_STRUCTURE+#define FT_STRUCTURE PS_FontExtraRec+#undef T1CODE+#define T1CODE T1_FIELD_LOCATION_FONT_EXTRA++ T1_FIELD_NUM ( "FSType", fs_type, 0 )+++#undef FT_STRUCTURE+#define FT_STRUCTURE CID_FaceDictRec+#undef T1CODE+#define T1CODE T1_FIELD_LOCATION_FONT_DICT++ T1_FIELD_NUM ( "PaintType", paint_type, 0 )+ T1_FIELD_NUM ( "FontType", font_type, 0 )+ T1_FIELD_NUM ( "SubrMapOffset", subrmap_offset, 0 )+ T1_FIELD_NUM ( "SDBytes", sd_bytes, 0 )+ T1_FIELD_NUM ( "SubrCount", num_subrs, 0 )+ T1_FIELD_NUM ( "lenBuildCharArray", len_buildchar, 0 )+ T1_FIELD_FIXED( "ForceBoldThreshold", forcebold_threshold, 0 )+ T1_FIELD_FIXED( "StrokeWidth", stroke_width, 0 )+++#undef FT_STRUCTURE+#define FT_STRUCTURE PS_PrivateRec+#undef T1CODE+#define T1CODE T1_FIELD_LOCATION_PRIVATE++ T1_FIELD_NUM ( "UniqueID", unique_id, 0 )+ T1_FIELD_NUM ( "lenIV", lenIV, 0 )+ T1_FIELD_NUM ( "LanguageGroup", language_group, 0 )+ T1_FIELD_NUM ( "password", password, 0 )++ T1_FIELD_FIXED_1000( "BlueScale", blue_scale, 0 )+ T1_FIELD_NUM ( "BlueShift", blue_shift, 0 )+ T1_FIELD_NUM ( "BlueFuzz", blue_fuzz, 0 )++ T1_FIELD_NUM_TABLE ( "BlueValues", blue_values, 14, 0 )+ T1_FIELD_NUM_TABLE ( "OtherBlues", other_blues, 10, 0 )+ T1_FIELD_NUM_TABLE ( "FamilyBlues", family_blues, 14, 0 )+ T1_FIELD_NUM_TABLE ( "FamilyOtherBlues", family_other_blues, 10, 0 )++ T1_FIELD_NUM_TABLE2( "StdHW", standard_width, 1, 0 )+ T1_FIELD_NUM_TABLE2( "StdVW", standard_height, 1, 0 )+ T1_FIELD_NUM_TABLE2( "MinFeature", min_feature, 2, 0 )++ T1_FIELD_NUM_TABLE ( "StemSnapH", snap_widths, 12, 0 )+ T1_FIELD_NUM_TABLE ( "StemSnapV", snap_heights, 12, 0 )++ T1_FIELD_BOOL ( "ForceBold", force_bold, 0 )+++#undef FT_STRUCTURE+#define FT_STRUCTURE FT_BBox+#undef T1CODE+#define T1CODE T1_FIELD_LOCATION_BBOX++ T1_FIELD_BBOX( "FontBBox", xMin, 0 )+++/* END */
+ src/cid/type1cid.c view
@@ -0,0 +1,29 @@+/***************************************************************************/+/* */+/* type1cid.c */+/* */+/* FreeType OpenType driver component (body only). */+/* */+/* Copyright 1996-2001 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 "cidparse.c"+#include "cidload.c"+#include "cidobjs.c"+#include "cidriver.c"+#include "cidgload.c"+++/* END */
+ src/gzip/adler32.c view
@@ -0,0 +1,48 @@+/* adler32.c -- compute the Adler-32 checksum of a data stream+ * Copyright (C) 1995-2002 Mark Adler+ * For conditions of distribution and use, see copyright notice in zlib.h+ */++/* @(#) $Id$ */++#include "zlib.h"++#define BASE 65521L /* largest prime smaller than 65536 */+#define NMAX 5552+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */++#define DO1(buf,i) {s1 += buf[i]; s2 += s1;}+#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);+#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);+#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);+#define DO16(buf) DO8(buf,0); DO8(buf,8);++/* ========================================================================= */+ZEXPORT(uLong) adler32( /* adler, buf, len) */+ uLong adler,+ const Bytef *buf,+ uInt len )+{+ unsigned long s1 = adler & 0xffff;+ unsigned long s2 = (adler >> 16) & 0xffff;+ int k;++ if (buf == Z_NULL) return 1L;++ while (len > 0) {+ k = len < NMAX ? len : NMAX;+ len -= k;+ while (k >= 16) {+ DO16(buf);+ buf += 16;+ k -= 16;+ }+ if (k != 0) do {+ s1 += *buf++;+ s2 += s1;+ } while (--k);+ s1 %= BASE;+ s2 %= BASE;+ }+ return (s2 << 16) | s1;+}
+ src/gzip/ftgzip.c view
@@ -0,0 +1,688 @@+/***************************************************************************/+/* */+/* ftgzip.c */+/* */+/* FreeType support for .gz compressed files. */+/* */+/* This optional component relies on zlib. It should mainly be used to */+/* parse compressed PCF fonts, as found with many X11 server */+/* distributions. */+/* */+/* Copyright 2002, 2003, 2004, 2005, 2006, 2009, 2010 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_MEMORY_H+#include FT_INTERNAL_STREAM_H+#include FT_INTERNAL_DEBUG_H+#include FT_GZIP_H+#include FT_CONFIG_STANDARD_LIBRARY_H+++#include FT_MODULE_ERRORS_H++#undef __FTERRORS_H__++#define FT_ERR_PREFIX Gzip_Err_+#define FT_ERR_BASE FT_Mod_Err_Gzip++#include FT_ERRORS_H+++#ifdef FT_CONFIG_OPTION_USE_ZLIB++#ifdef FT_CONFIG_OPTION_PIC+#error "gzip code does not support PIC yet"+#endif ++#ifdef FT_CONFIG_OPTION_SYSTEM_ZLIB++#include <zlib.h>++#else /* !FT_CONFIG_OPTION_SYSTEM_ZLIB */++ /* In this case, we include our own modified sources of the ZLib */+ /* within the "ftgzip" component. The modifications were necessary */+ /* to #include all files without conflicts, as well as preventing */+ /* the definition of "extern" functions that may cause linking */+ /* conflicts when a program is linked with both FreeType and the */+ /* original ZLib. */++#define NO_DUMMY_DECL+#ifndef USE_ZLIB_ZCALLOC+#define MY_ZCALLOC /* prevent all zcalloc() & zfree() in zutils.c */+#endif++#include "zlib.h"++#undef SLOW+#define SLOW 1 /* we can't use asm-optimized sources here! */++ /* Urgh. `inflate_mask' must not be declared twice -- C++ doesn't like+ this. We temporarily disable it and load all necessary header files. */+#define NO_INFLATE_MASK+#include "zutil.h"+#include "inftrees.h"+#include "infblock.h"+#include "infcodes.h"+#include "infutil.h"+#undef NO_INFLATE_MASK++ /* infutil.c must be included before infcodes.c */+#include "zutil.c"+#include "inftrees.c"+#include "infutil.c"+#include "infcodes.c"+#include "infblock.c"+#include "inflate.c"+#include "adler32.c"++#endif /* !FT_CONFIG_OPTION_SYSTEM_ZLIB */+++/***************************************************************************/+/***************************************************************************/+/***** *****/+/***** Z L I B M E M O R Y M A N A G E M E N T *****/+/***** *****/+/***************************************************************************/+/***************************************************************************/++ /* it is better to use FreeType memory routines instead of raw+ 'malloc/free' */++ static voidpf+ ft_gzip_alloc( FT_Memory memory,+ uInt items,+ uInt size )+ {+ FT_ULong sz = (FT_ULong)size * items;+ FT_Error error;+ FT_Pointer p = NULL;+++ (void)FT_ALLOC( p, sz );+ return p;+ }+++ static void+ ft_gzip_free( FT_Memory memory,+ voidpf address )+ {+ FT_MEM_FREE( address );+ }+++#if !defined( FT_CONFIG_OPTION_SYSTEM_ZLIB ) && !defined( USE_ZLIB_ZCALLOC )++ local voidpf+ zcalloc ( voidpf opaque,+ unsigned items,+ unsigned size )+ {+ return ft_gzip_alloc( (FT_Memory)opaque, items, size );+ }++ local void+ zcfree( voidpf opaque,+ voidpf ptr )+ {+ ft_gzip_free( (FT_Memory)opaque, ptr );+ }++#endif /* !SYSTEM_ZLIB && !USE_ZLIB_ZCALLOC */+++/***************************************************************************/+/***************************************************************************/+/***** *****/+/***** Z L I B F I L E D E S C R I P T O R *****/+/***** *****/+/***************************************************************************/+/***************************************************************************/++#define FT_GZIP_BUFFER_SIZE 4096++ typedef struct FT_GZipFileRec_+ {+ FT_Stream source; /* parent/source stream */+ FT_Stream stream; /* embedding stream */+ FT_Memory memory; /* memory allocator */+ z_stream zstream; /* zlib input stream */++ FT_ULong start; /* starting position, after .gz header */+ FT_Byte input[FT_GZIP_BUFFER_SIZE]; /* input read buffer */++ FT_Byte buffer[FT_GZIP_BUFFER_SIZE]; /* output buffer */+ FT_ULong pos; /* position in output */+ FT_Byte* cursor;+ FT_Byte* limit;++ } FT_GZipFileRec, *FT_GZipFile;+++ /* gzip flag byte */+#define FT_GZIP_ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */+#define FT_GZIP_HEAD_CRC 0x02 /* bit 1 set: header CRC present */+#define FT_GZIP_EXTRA_FIELD 0x04 /* bit 2 set: extra field present */+#define FT_GZIP_ORIG_NAME 0x08 /* bit 3 set: original file name present */+#define FT_GZIP_COMMENT 0x10 /* bit 4 set: file comment present */+#define FT_GZIP_RESERVED 0xE0 /* bits 5..7: reserved */+++ /* check and skip .gz header - we don't support `transparent' compression */+ static FT_Error+ ft_gzip_check_header( FT_Stream stream )+ {+ FT_Error error;+ FT_Byte head[4];+++ if ( FT_STREAM_SEEK( 0 ) ||+ FT_STREAM_READ( head, 4 ) )+ goto Exit;++ /* head[0] && head[1] are the magic numbers; */+ /* head[2] is the method, and head[3] the flags */+ if ( head[0] != 0x1f ||+ head[1] != 0x8b ||+ head[2] != Z_DEFLATED ||+ (head[3] & FT_GZIP_RESERVED) )+ {+ error = Gzip_Err_Invalid_File_Format;+ goto Exit;+ }++ /* skip time, xflags and os code */+ (void)FT_STREAM_SKIP( 6 );++ /* skip the extra field */+ if ( head[3] & FT_GZIP_EXTRA_FIELD )+ {+ FT_UInt len;+++ if ( FT_READ_USHORT_LE( len ) ||+ FT_STREAM_SKIP( len ) )+ goto Exit;+ }++ /* skip original file name */+ if ( head[3] & FT_GZIP_ORIG_NAME )+ for (;;)+ {+ FT_UInt c;+++ if ( FT_READ_BYTE( c ) )+ goto Exit;++ if ( c == 0 )+ break;+ }++ /* skip .gz comment */+ if ( head[3] & FT_GZIP_COMMENT )+ for (;;)+ {+ FT_UInt c;+++ if ( FT_READ_BYTE( c ) )+ goto Exit;++ if ( c == 0 )+ break;+ }++ /* skip CRC */+ if ( head[3] & FT_GZIP_HEAD_CRC )+ if ( FT_STREAM_SKIP( 2 ) )+ goto Exit;++ Exit:+ return error;+ }+++ static FT_Error+ ft_gzip_file_init( FT_GZipFile zip,+ FT_Stream stream,+ FT_Stream source )+ {+ z_stream* zstream = &zip->zstream;+ FT_Error error = Gzip_Err_Ok;+++ zip->stream = stream;+ zip->source = source;+ zip->memory = stream->memory;++ zip->limit = zip->buffer + FT_GZIP_BUFFER_SIZE;+ zip->cursor = zip->limit;+ zip->pos = 0;++ /* check and skip .gz header */+ {+ stream = source;++ error = ft_gzip_check_header( stream );+ if ( error )+ goto Exit;++ zip->start = FT_STREAM_POS();+ }++ /* initialize zlib -- there is no zlib header in the compressed stream */+ zstream->zalloc = (alloc_func)ft_gzip_alloc;+ zstream->zfree = (free_func) ft_gzip_free;+ zstream->opaque = stream->memory;++ zstream->avail_in = 0;+ zstream->next_in = zip->buffer;++ if ( inflateInit2( zstream, -MAX_WBITS ) != Z_OK ||+ zstream->next_in == NULL )+ error = Gzip_Err_Invalid_File_Format;++ Exit:+ return error;+ }+++ static void+ ft_gzip_file_done( FT_GZipFile zip )+ {+ z_stream* zstream = &zip->zstream;+++ inflateEnd( zstream );++ /* clear the rest */+ zstream->zalloc = NULL;+ zstream->zfree = NULL;+ zstream->opaque = NULL;+ zstream->next_in = NULL;+ zstream->next_out = NULL;+ zstream->avail_in = 0;+ zstream->avail_out = 0;++ zip->memory = NULL;+ zip->source = NULL;+ zip->stream = NULL;+ }+++ static FT_Error+ ft_gzip_file_reset( FT_GZipFile zip )+ {+ FT_Stream stream = zip->source;+ FT_Error error;+++ if ( !FT_STREAM_SEEK( zip->start ) )+ {+ z_stream* zstream = &zip->zstream;+++ inflateReset( zstream );++ zstream->avail_in = 0;+ zstream->next_in = zip->input;+ zstream->avail_out = 0;+ zstream->next_out = zip->buffer;++ zip->limit = zip->buffer + FT_GZIP_BUFFER_SIZE;+ zip->cursor = zip->limit;+ zip->pos = 0;+ }++ return error;+ }+++ static FT_Error+ ft_gzip_file_fill_input( FT_GZipFile zip )+ {+ z_stream* zstream = &zip->zstream;+ FT_Stream stream = zip->source;+ FT_ULong size;+++ if ( stream->read )+ {+ size = stream->read( stream, stream->pos, zip->input,+ FT_GZIP_BUFFER_SIZE );+ if ( size == 0 )+ return Gzip_Err_Invalid_Stream_Operation;+ }+ else+ {+ size = stream->size - stream->pos;+ if ( size > FT_GZIP_BUFFER_SIZE )+ size = FT_GZIP_BUFFER_SIZE;++ if ( size == 0 )+ return Gzip_Err_Invalid_Stream_Operation;++ FT_MEM_COPY( zip->input, stream->base + stream->pos, size );+ }+ stream->pos += size;++ zstream->next_in = zip->input;+ zstream->avail_in = size;++ return Gzip_Err_Ok;+ }+++ static FT_Error+ ft_gzip_file_fill_output( FT_GZipFile zip )+ {+ z_stream* zstream = &zip->zstream;+ FT_Error error = Gzip_Err_Ok;+++ zip->cursor = zip->buffer;+ zstream->next_out = zip->cursor;+ zstream->avail_out = FT_GZIP_BUFFER_SIZE;++ while ( zstream->avail_out > 0 )+ {+ int err;+++ if ( zstream->avail_in == 0 )+ {+ error = ft_gzip_file_fill_input( zip );+ if ( error )+ break;+ }++ err = inflate( zstream, Z_NO_FLUSH );++ if ( err == Z_STREAM_END )+ {+ zip->limit = zstream->next_out;+ if ( zip->limit == zip->cursor )+ error = Gzip_Err_Invalid_Stream_Operation;+ break;+ }+ else if ( err != Z_OK )+ {+ error = Gzip_Err_Invalid_Stream_Operation;+ break;+ }+ }++ return error;+ }+++ /* fill output buffer; `count' must be <= FT_GZIP_BUFFER_SIZE */+ static FT_Error+ ft_gzip_file_skip_output( FT_GZipFile zip,+ FT_ULong count )+ {+ FT_Error error = Gzip_Err_Ok;+ FT_ULong delta;+++ for (;;)+ {+ delta = (FT_ULong)( zip->limit - zip->cursor );+ if ( delta >= count )+ delta = count;++ zip->cursor += delta;+ zip->pos += delta;++ count -= delta;+ if ( count == 0 )+ break;++ error = ft_gzip_file_fill_output( zip );+ if ( error )+ break;+ }++ return error;+ }+++ static FT_ULong+ ft_gzip_file_io( FT_GZipFile zip,+ FT_ULong pos,+ FT_Byte* buffer,+ FT_ULong count )+ {+ FT_ULong result = 0;+ FT_Error error;+++ /* Reset inflate stream if we're seeking backwards. */+ /* Yes, that is not too efficient, but it saves memory :-) */+ if ( pos < zip->pos )+ {+ error = ft_gzip_file_reset( zip );+ if ( error )+ goto Exit;+ }++ /* skip unwanted bytes */+ if ( pos > zip->pos )+ {+ error = ft_gzip_file_skip_output( zip, (FT_ULong)( pos - zip->pos ) );+ if ( error )+ goto Exit;+ }++ if ( count == 0 )+ goto Exit;++ /* now read the data */+ for (;;)+ {+ FT_ULong delta;+++ delta = (FT_ULong)( zip->limit - zip->cursor );+ if ( delta >= count )+ delta = count;++ FT_MEM_COPY( buffer, zip->cursor, delta );+ buffer += delta;+ result += delta;+ zip->cursor += delta;+ zip->pos += delta;++ count -= delta;+ if ( count == 0 )+ break;++ error = ft_gzip_file_fill_output( zip );+ if ( error )+ break;+ }++ Exit:+ return result;+ }+++/***************************************************************************/+/***************************************************************************/+/***** *****/+/***** G Z E M B E D D I N G S T R E A M *****/+/***** *****/+/***************************************************************************/+/***************************************************************************/++ static void+ ft_gzip_stream_close( FT_Stream stream )+ {+ FT_GZipFile zip = (FT_GZipFile)stream->descriptor.pointer;+ FT_Memory memory = stream->memory;+++ if ( zip )+ {+ /* finalize gzip file descriptor */+ ft_gzip_file_done( zip );++ FT_FREE( zip );++ stream->descriptor.pointer = NULL;+ }+ }+++ static FT_ULong+ ft_gzip_stream_io( FT_Stream stream,+ FT_ULong pos,+ FT_Byte* buffer,+ FT_ULong count )+ {+ FT_GZipFile zip = (FT_GZipFile)stream->descriptor.pointer;+++ return ft_gzip_file_io( zip, pos, buffer, count );+ }+++ static FT_ULong+ ft_gzip_get_uncompressed_size( FT_Stream stream )+ {+ FT_Error error;+ FT_ULong old_pos;+ FT_ULong result = 0;+++ old_pos = stream->pos;+ if ( !FT_Stream_Seek( stream, stream->size - 4 ) )+ {+ result = (FT_ULong)FT_Stream_ReadLong( stream, &error );+ if ( error )+ result = 0;++ (void)FT_Stream_Seek( stream, old_pos );+ }++ return result;+ }+++ FT_EXPORT_DEF( FT_Error )+ FT_Stream_OpenGzip( FT_Stream stream,+ FT_Stream source )+ {+ FT_Error error;+ FT_Memory memory = source->memory;+ FT_GZipFile zip;+++ /*+ * check the header right now; this prevents allocating un-necessary+ * objects when we don't need them+ */+ error = ft_gzip_check_header( source );+ if ( error )+ goto Exit;++ FT_ZERO( stream );+ stream->memory = memory;++ if ( !FT_QNEW( zip ) )+ {+ error = ft_gzip_file_init( zip, stream, source );+ if ( error )+ {+ FT_FREE( zip );+ goto Exit;+ }++ stream->descriptor.pointer = zip;+ }++ /*+ * We use the following trick to try to dramatically improve the+ * performance while dealing with small files. If the original stream+ * size is less than a certain threshold, we try to load the whole font+ * file into memory. This saves us from using the 32KB buffer needed+ * to inflate the file, plus the two 4KB intermediate input/output+ * buffers used in the `FT_GZipFile' structure.+ */+ {+ FT_ULong zip_size = ft_gzip_get_uncompressed_size( source );+++ if ( zip_size != 0 && zip_size < 40 * 1024 )+ {+ FT_Byte* zip_buff;+++ if ( !FT_ALLOC( zip_buff, zip_size ) )+ {+ FT_ULong count;+++ count = ft_gzip_file_io( zip, 0, zip_buff, zip_size );+ if ( count == zip_size )+ {+ ft_gzip_file_done( zip );+ FT_FREE( zip );++ stream->descriptor.pointer = NULL;++ stream->size = zip_size;+ stream->pos = 0;+ stream->base = zip_buff;+ stream->read = NULL;+ stream->close = ft_gzip_stream_close;++ goto Exit;+ }++ ft_gzip_file_io( zip, 0, NULL, 0 );+ FT_FREE( zip_buff );+ }+ error = Gzip_Err_Ok;+ }+ }++ stream->size = 0x7FFFFFFFL; /* don't know the real size! */+ stream->pos = 0;+ stream->base = 0;+ stream->read = ft_gzip_stream_io;+ stream->close = ft_gzip_stream_close;++ Exit:+ return error;+ }++#else /* !FT_CONFIG_OPTION_USE_ZLIB */++ FT_EXPORT_DEF( FT_Error )+ FT_Stream_OpenGzip( FT_Stream stream,+ FT_Stream source )+ {+ FT_UNUSED( stream );+ FT_UNUSED( source );++ return Gzip_Err_Unimplemented_Feature;+ }++#endif /* !FT_CONFIG_OPTION_USE_ZLIB */+++/* END */
+ src/gzip/infblock.c view
@@ -0,0 +1,387 @@+/* infblock.c -- interpret and process block types to last block+ * Copyright (C) 1995-2002 Mark Adler+ * For conditions of distribution and use, see copyright notice in zlib.h+ */++#include "zutil.h"+#include "infblock.h"+#include "inftrees.h"+#include "infcodes.h"+#include "infutil.h"+++/* simplify the use of the inflate_huft type with some defines */+#define exop word.what.Exop+#define bits word.what.Bits++/* Table for deflate from PKZIP's appnote.txt. */+local const uInt border[] = { /* Order of the bit length code lengths */+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};++/*+ Notes beyond the 1.93a appnote.txt:++ 1. Distance pointers never point before the beginning of the output+ stream.+ 2. Distance pointers can point back across blocks, up to 32k away.+ 3. There is an implied maximum of 7 bits for the bit length table and+ 15 bits for the actual data.+ 4. If only one code exists, then it is encoded using one bit. (Zero+ would be more efficient, but perhaps a little confusing.) If two+ codes exist, they are coded using one bit each (0 and 1).+ 5. There is no way of sending zero distance codes--a dummy must be+ sent if there are none. (History: a pre 2.0 version of PKZIP would+ store blocks with no distance codes, but this was discovered to be+ too harsh a criterion.) Valid only for 1.93a. 2.04c does allow+ zero distance codes, which is sent as one code of zero bits in+ length.+ 6. There are up to 286 literal/length codes. Code 256 represents the+ end-of-block. Note however that the static length tree defines+ 288 codes just to fill out the Huffman codes. Codes 286 and 287+ cannot be used though, since there is no length base or extra bits+ defined for them. Similarily, there are up to 30 distance codes.+ However, static trees define 32 codes (all 5 bits) to fill out the+ Huffman codes, but the last two had better not show up in the data.+ 7. Unzip can check dynamic Huffman blocks for complete code sets.+ The exception is that a single code would not be complete (see #4).+ 8. The five bits following the block type is really the number of+ literal codes sent minus 257.+ 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits+ (1+6+6). Therefore, to output three times the length, you output+ three codes (1+1+1), whereas to output four times the same length,+ you only need two codes (1+3). Hmm.+ 10. In the tree reconstruction algorithm, Code = Code + Increment+ only if BitLength(i) is not zero. (Pretty obvious.)+ 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)+ 12. Note: length code 284 can represent 227-258, but length code 285+ really is 258. The last length deserves its own, short code+ since it gets used a lot in very redundant files. The length+ 258 is special since 258 - 3 (the min match length) is 255.+ 13. The literal/length and distance code bit lengths are read as a+ single stream of lengths. It is possible (and advantageous) for+ a repeat code (16, 17, or 18) to go across the boundary between+ the two sets of lengths.+ */+++local void inflate_blocks_reset( /* s, z, c) */+inflate_blocks_statef *s,+z_streamp z,+uLongf *c )+{+ if (c != Z_NULL)+ *c = s->check;+ if (s->mode == BTREE || s->mode == DTREE)+ ZFREE(z, s->sub.trees.blens);+ if (s->mode == CODES)+ inflate_codes_free(s->sub.decode.codes, z);+ s->mode = TYPE;+ s->bitk = 0;+ s->bitb = 0;+ s->read = s->write = s->window;+ if (s->checkfn != Z_NULL)+ z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0);+ Tracev((stderr, "inflate: blocks reset\n"));+}+++local inflate_blocks_statef *inflate_blocks_new( /* z, c, w) */+z_streamp z,+check_func c,+uInt w )+{+ inflate_blocks_statef *s;++ if ((s = (inflate_blocks_statef *)ZALLOC+ (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)+ return s;+ if ((s->hufts =+ (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL)+ {+ ZFREE(z, s);+ return Z_NULL;+ }+ if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)+ {+ ZFREE(z, s->hufts);+ ZFREE(z, s);+ return Z_NULL;+ }+ s->end = s->window + w;+ s->checkfn = c;+ s->mode = TYPE;+ Tracev((stderr, "inflate: blocks allocated\n"));+ inflate_blocks_reset(s, z, Z_NULL);+ return s;+}+++local int inflate_blocks( /* s, z, r) */+inflate_blocks_statef *s,+z_streamp z,+int r )+{+ uInt t; /* temporary storage */+ uLong b; /* bit buffer */+ uInt k; /* bits in bit buffer */+ Bytef *p; /* input data pointer */+ uInt n; /* bytes available there */+ Bytef *q; /* output window write pointer */+ uInt m; /* bytes to end of window or read pointer */++ /* copy input/output information to locals (UPDATE macro restores) */+ LOAD++ /* process input based on current state */+ while (1) switch (s->mode)+ {+ case TYPE:+ NEEDBITS(3)+ t = (uInt)b & 7;+ s->last = t & 1;+ switch (t >> 1)+ {+ case 0: /* stored */+ Tracev((stderr, "inflate: stored block%s\n",+ s->last ? " (last)" : ""));+ DUMPBITS(3)+ t = k & 7; /* go to byte boundary */+ DUMPBITS(t)+ s->mode = LENS; /* get length of stored block */+ break;+ case 1: /* fixed */+ Tracev((stderr, "inflate: fixed codes block%s\n",+ s->last ? " (last)" : ""));+ {+ uInt bl, bd;+ inflate_huft *tl, *td;++ inflate_trees_fixed(&bl, &bd, (const inflate_huft**)&tl,+ (const inflate_huft**)&td, z);+ s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);+ if (s->sub.decode.codes == Z_NULL)+ {+ r = Z_MEM_ERROR;+ LEAVE+ }+ }+ DUMPBITS(3)+ s->mode = CODES;+ break;+ case 2: /* dynamic */+ Tracev((stderr, "inflate: dynamic codes block%s\n",+ s->last ? " (last)" : ""));+ DUMPBITS(3)+ s->mode = TABLE;+ break;+ case 3: /* illegal */+ DUMPBITS(3)+ s->mode = BAD;+ z->msg = (char*)"invalid block type";+ r = Z_DATA_ERROR;+ LEAVE+ }+ break;+ case LENS:+ NEEDBITS(32)+ if ((((~b) >> 16) & 0xffff) != (b & 0xffff))+ {+ s->mode = BAD;+ z->msg = (char*)"invalid stored block lengths";+ r = Z_DATA_ERROR;+ LEAVE+ }+ s->sub.left = (uInt)b & 0xffff;+ b = k = 0; /* dump bits */+ Tracev((stderr, "inflate: stored length %u\n", s->sub.left));+ s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE);+ break;+ case STORED:+ if (n == 0)+ LEAVE+ NEEDOUT+ t = s->sub.left;+ if (t > n) t = n;+ if (t > m) t = m;+ zmemcpy(q, p, t);+ p += t; n -= t;+ q += t; m -= t;+ if ((s->sub.left -= t) != 0)+ break;+ Tracev((stderr, "inflate: stored end, %lu total out\n",+ z->total_out + (q >= s->read ? q - s->read :+ (s->end - s->read) + (q - s->window))));+ s->mode = s->last ? DRY : TYPE;+ break;+ case TABLE:+ NEEDBITS(14)+ s->sub.trees.table = t = (uInt)b & 0x3fff;+#ifndef PKZIP_BUG_WORKAROUND+ if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)+ {+ s->mode = BAD;+ z->msg = (char*)"too many length or distance symbols";+ r = Z_DATA_ERROR;+ LEAVE+ }+#endif+ t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);+ if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)+ {+ r = Z_MEM_ERROR;+ LEAVE+ }+ DUMPBITS(14)+ s->sub.trees.index = 0;+ Tracev((stderr, "inflate: table sizes ok\n"));+ s->mode = BTREE;+ case BTREE:+ while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))+ {+ NEEDBITS(3)+ s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;+ DUMPBITS(3)+ }+ while (s->sub.trees.index < 19)+ s->sub.trees.blens[border[s->sub.trees.index++]] = 0;+ s->sub.trees.bb = 7;+ t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,+ &s->sub.trees.tb, s->hufts, z);+ if (t != Z_OK)+ {+ r = t;+ if (r == Z_DATA_ERROR)+ {+ ZFREE(z, s->sub.trees.blens);+ s->mode = BAD;+ }+ LEAVE+ }+ s->sub.trees.index = 0;+ Tracev((stderr, "inflate: bits tree ok\n"));+ s->mode = DTREE;+ case DTREE:+ while (t = s->sub.trees.table,+ s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))+ {+ inflate_huft *h;+ uInt i, j, c;++ t = s->sub.trees.bb;+ NEEDBITS(t)+ h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);+ t = h->bits;+ c = h->base;+ if (c < 16)+ {+ DUMPBITS(t)+ s->sub.trees.blens[s->sub.trees.index++] = c;+ }+ else /* c == 16..18 */+ {+ i = c == 18 ? 7 : c - 14;+ j = c == 18 ? 11 : 3;+ NEEDBITS(t + i)+ DUMPBITS(t)+ j += (uInt)b & inflate_mask[i];+ DUMPBITS(i)+ i = s->sub.trees.index;+ t = s->sub.trees.table;+ if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||+ (c == 16 && i < 1))+ {+ ZFREE(z, s->sub.trees.blens);+ s->mode = BAD;+ z->msg = (char*)"invalid bit length repeat";+ r = Z_DATA_ERROR;+ LEAVE+ }+ c = c == 16 ? s->sub.trees.blens[i - 1] : 0;+ do {+ s->sub.trees.blens[i++] = c;+ } while (--j);+ s->sub.trees.index = i;+ }+ }+ s->sub.trees.tb = Z_NULL;+ {+ uInt bl, bd;+ inflate_huft *tl, *td;+ inflate_codes_statef *c;++ bl = 9; /* must be <= 9 for lookahead assumptions */+ bd = 6; /* must be <= 9 for lookahead assumptions */+ t = s->sub.trees.table;+ t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),+ s->sub.trees.blens, &bl, &bd, &tl, &td,+ s->hufts, z);+ if (t != Z_OK)+ {+ if (t == (uInt)Z_DATA_ERROR)+ {+ ZFREE(z, s->sub.trees.blens);+ s->mode = BAD;+ }+ r = t;+ LEAVE+ }+ Tracev((stderr, "inflate: trees ok\n"));+ if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)+ {+ r = Z_MEM_ERROR;+ LEAVE+ }+ s->sub.decode.codes = c;+ }+ ZFREE(z, s->sub.trees.blens);+ s->mode = CODES;+ case CODES:+ UPDATE+ if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)+ return inflate_flush(s, z, r);+ r = Z_OK;+ inflate_codes_free(s->sub.decode.codes, z);+ LOAD+ Tracev((stderr, "inflate: codes end, %lu total out\n",+ z->total_out + (q >= s->read ? q - s->read :+ (s->end - s->read) + (q - s->window))));+ if (!s->last)+ {+ s->mode = TYPE;+ break;+ }+ s->mode = DRY;+ case DRY:+ FLUSH+ if (s->read != s->write)+ LEAVE+ s->mode = DONE;+ case DONE:+ r = Z_STREAM_END;+ LEAVE+ case BAD:+ r = Z_DATA_ERROR;+ LEAVE+ default:+ r = Z_STREAM_ERROR;+ LEAVE+ }+#ifdef NEED_DUMMY_RETURN+ return 0;+#endif+}+++local int inflate_blocks_free( /* s, z) */+inflate_blocks_statef *s,+z_streamp z )+{+ inflate_blocks_reset(s, z, Z_NULL);+ ZFREE(z, s->window);+ ZFREE(z, s->hufts);+ ZFREE(z, s);+ Tracev((stderr, "inflate: blocks freed\n"));+ return Z_OK;+}++
+ src/gzip/infblock.h view
@@ -0,0 +1,36 @@+/* infblock.h -- header to use infblock.c+ * Copyright (C) 1995-2002 Mark Adler+ * For conditions of distribution and use, see copyright notice in zlib.h+ */++/* WARNING: this file should *not* be used by applications. It is+ part of the implementation of the compression library and is+ subject to change. Applications should only use zlib.h.+ */++#ifndef _INFBLOCK_H+#define _INFBLOCK_H++struct inflate_blocks_state;+typedef struct inflate_blocks_state FAR inflate_blocks_statef;++local inflate_blocks_statef * inflate_blocks_new OF((+ z_streamp z,+ check_func c, /* check function */+ uInt w)); /* window size */++local int inflate_blocks OF((+ inflate_blocks_statef *,+ z_streamp ,+ int)); /* initial return code */++local void inflate_blocks_reset OF((+ inflate_blocks_statef *,+ z_streamp ,+ uLongf *)); /* check value on output */++local int inflate_blocks_free OF((+ inflate_blocks_statef *,+ z_streamp));++#endif /* _INFBLOCK_H */
+ src/gzip/infcodes.c view
@@ -0,0 +1,250 @@+/* infcodes.c -- process literals and length/distance pairs+ * Copyright (C) 1995-2002 Mark Adler+ * For conditions of distribution and use, see copyright notice in zlib.h+ */++#include "zutil.h"+#include "inftrees.h"+#include "infblock.h"+#include "infcodes.h"+#include "infutil.h"++/* simplify the use of the inflate_huft type with some defines */+#define exop word.what.Exop+#define bits word.what.Bits++typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */+ START, /* x: set up for LEN */+ LEN, /* i: get length/literal/eob next */+ LENEXT, /* i: getting length extra (have base) */+ DIST, /* i: get distance next */+ DISTEXT, /* i: getting distance extra */+ COPY, /* o: copying bytes in window, waiting for space */+ LIT, /* o: got literal, waiting for output space */+ WASH, /* o: got eob, possibly still output waiting */+ END, /* x: got eob and all data flushed */+ BADCODE} /* x: got error */+inflate_codes_mode;++/* inflate codes private state */+struct inflate_codes_state {++ /* mode */+ inflate_codes_mode mode; /* current inflate_codes mode */++ /* mode dependent information */+ uInt len;+ union {+ struct {+ inflate_huft *tree; /* pointer into tree */+ uInt need; /* bits needed */+ } code; /* if LEN or DIST, where in tree */+ uInt lit; /* if LIT, literal */+ struct {+ uInt get; /* bits to get for extra */+ uInt dist; /* distance back to copy from */+ } copy; /* if EXT or COPY, where and how much */+ } sub; /* submode */++ /* mode independent information */+ Byte lbits; /* ltree bits decoded per branch */+ Byte dbits; /* dtree bits decoder per branch */+ inflate_huft *ltree; /* literal/length/eob tree */+ inflate_huft *dtree; /* distance tree */++};+++local inflate_codes_statef *inflate_codes_new( /* bl, bd, tl, td, z) */+uInt bl, uInt bd,+inflate_huft *tl,+inflate_huft *td, /* need separate declaration for Borland C++ */+z_streamp z )+{+ inflate_codes_statef *c;++ if ((c = (inflate_codes_statef *)+ ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)+ {+ c->mode = START;+ c->lbits = (Byte)bl;+ c->dbits = (Byte)bd;+ c->ltree = tl;+ c->dtree = td;+ Tracev((stderr, "inflate: codes new\n"));+ }+ return c;+}+++local int inflate_codes( /* s, z, r) */+inflate_blocks_statef *s,+z_streamp z,+int r )+{+ uInt j; /* temporary storage */+ inflate_huft *t; /* temporary pointer */+ uInt e; /* extra bits or operation */+ uLong b; /* bit buffer */+ uInt k; /* bits in bit buffer */+ Bytef *p; /* input data pointer */+ uInt n; /* bytes available there */+ Bytef *q; /* output window write pointer */+ uInt m; /* bytes to end of window or read pointer */+ Bytef *f; /* pointer to copy strings from */+ inflate_codes_statef *c = s->sub.decode.codes; /* codes state */++ /* copy input/output information to locals (UPDATE macro restores) */+ LOAD++ /* process input and output based on current state */+ while (1) switch (c->mode)+ { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */+ case START: /* x: set up for LEN */+#ifndef SLOW+ if (m >= 258 && n >= 10)+ {+ UPDATE+ r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);+ LOAD+ if (r != Z_OK)+ {+ c->mode = r == Z_STREAM_END ? WASH : BADCODE;+ break;+ }+ }+#endif /* !SLOW */+ c->sub.code.need = c->lbits;+ c->sub.code.tree = c->ltree;+ c->mode = LEN;+ case LEN: /* i: get length/literal/eob next */+ j = c->sub.code.need;+ NEEDBITS(j)+ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);+ DUMPBITS(t->bits)+ e = (uInt)(t->exop);+ if (e == 0) /* literal */+ {+ c->sub.lit = t->base;+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?+ "inflate: literal '%c'\n" :+ "inflate: literal 0x%02x\n", t->base));+ c->mode = LIT;+ break;+ }+ if (e & 16) /* length */+ {+ c->sub.copy.get = e & 15;+ c->len = t->base;+ c->mode = LENEXT;+ break;+ }+ if ((e & 64) == 0) /* next table */+ {+ c->sub.code.need = e;+ c->sub.code.tree = t + t->base;+ break;+ }+ if (e & 32) /* end of block */+ {+ Tracevv((stderr, "inflate: end of block\n"));+ c->mode = WASH;+ break;+ }+ c->mode = BADCODE; /* invalid code */+ z->msg = (char*)"invalid literal/length code";+ r = Z_DATA_ERROR;+ LEAVE+ case LENEXT: /* i: getting length extra (have base) */+ j = c->sub.copy.get;+ NEEDBITS(j)+ c->len += (uInt)b & inflate_mask[j];+ DUMPBITS(j)+ c->sub.code.need = c->dbits;+ c->sub.code.tree = c->dtree;+ Tracevv((stderr, "inflate: length %u\n", c->len));+ c->mode = DIST;+ case DIST: /* i: get distance next */+ j = c->sub.code.need;+ NEEDBITS(j)+ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);+ DUMPBITS(t->bits)+ e = (uInt)(t->exop);+ if (e & 16) /* distance */+ {+ c->sub.copy.get = e & 15;+ c->sub.copy.dist = t->base;+ c->mode = DISTEXT;+ break;+ }+ if ((e & 64) == 0) /* next table */+ {+ c->sub.code.need = e;+ c->sub.code.tree = t + t->base;+ break;+ }+ c->mode = BADCODE; /* invalid code */+ z->msg = (char*)"invalid distance code";+ r = Z_DATA_ERROR;+ LEAVE+ case DISTEXT: /* i: getting distance extra */+ j = c->sub.copy.get;+ NEEDBITS(j)+ c->sub.copy.dist += (uInt)b & inflate_mask[j];+ DUMPBITS(j)+ Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist));+ c->mode = COPY;+ case COPY: /* o: copying bytes in window, waiting for space */+ f = q - c->sub.copy.dist;+ while (f < s->window) /* modulo window size-"while" instead */+ f += s->end - s->window; /* of "if" handles invalid distances */+ while (c->len)+ {+ NEEDOUT+ OUTBYTE(*f++)+ if (f == s->end)+ f = s->window;+ c->len--;+ }+ c->mode = START;+ break;+ case LIT: /* o: got literal, waiting for output space */+ NEEDOUT+ OUTBYTE(c->sub.lit)+ c->mode = START;+ break;+ case WASH: /* o: got eob, possibly more output */+ if (k > 7) /* return unused byte, if any */+ {+ Assert(k < 16, "inflate_codes grabbed too many bytes")+ k -= 8;+ n++;+ p--; /* can always return one */+ }+ FLUSH+ if (s->read != s->write)+ LEAVE+ c->mode = END;+ case END:+ r = Z_STREAM_END;+ LEAVE+ case BADCODE: /* x: got error */+ r = Z_DATA_ERROR;+ LEAVE+ default:+ r = Z_STREAM_ERROR;+ LEAVE+ }+#ifdef NEED_DUMMY_RETURN+ return Z_STREAM_ERROR; /* Some dumb compilers complain without this */+#endif+}+++local void inflate_codes_free( /* c, z) */+inflate_codes_statef *c,+z_streamp z )+{+ ZFREE(z, c);+ Tracev((stderr, "inflate: codes free\n"));+}
+ src/gzip/infcodes.h view
@@ -0,0 +1,31 @@+/* infcodes.h -- header to use infcodes.c+ * Copyright (C) 1995-2002 Mark Adler+ * For conditions of distribution and use, see copyright notice in zlib.h+ */++/* WARNING: this file should *not* be used by applications. It is+ part of the implementation of the compression library and is+ subject to change. Applications should only use zlib.h.+ */++#ifndef _INFCODES_H+#define _INFCODES_H++struct inflate_codes_state;+typedef struct inflate_codes_state FAR inflate_codes_statef;++local inflate_codes_statef *inflate_codes_new OF((+ uInt, uInt,+ inflate_huft *, inflate_huft *,+ z_streamp ));++local int inflate_codes OF((+ inflate_blocks_statef *,+ z_streamp ,+ int));++local void inflate_codes_free OF((+ inflate_codes_statef *,+ z_streamp ));++#endif /* _INFCODES_H */
+ src/gzip/inffixed.h view
@@ -0,0 +1,151 @@+/* inffixed.h -- table for decoding fixed codes+ * Generated automatically by the maketree.c program+ */++/* WARNING: this file should *not* be used by applications. It is+ part of the implementation of the compression library and is+ subject to change. Applications should only use zlib.h.+ */++local const uInt fixed_bl = 9;+local const uInt fixed_bd = 5;+local const inflate_huft fixed_tl[] = {+ {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},+ {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192},+ {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160},+ {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224},+ {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144},+ {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208},+ {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176},+ {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240},+ {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},+ {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200},+ {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168},+ {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232},+ {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152},+ {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216},+ {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184},+ {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248},+ {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},+ {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196},+ {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164},+ {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228},+ {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148},+ {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212},+ {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180},+ {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244},+ {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},+ {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204},+ {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172},+ {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236},+ {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156},+ {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220},+ {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188},+ {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252},+ {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},+ {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194},+ {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162},+ {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226},+ {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146},+ {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210},+ {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178},+ {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242},+ {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},+ {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202},+ {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170},+ {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234},+ {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154},+ {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218},+ {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186},+ {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250},+ {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},+ {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198},+ {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166},+ {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230},+ {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150},+ {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214},+ {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182},+ {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246},+ {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},+ {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206},+ {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174},+ {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238},+ {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158},+ {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222},+ {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190},+ {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254},+ {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},+ {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193},+ {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161},+ {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225},+ {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145},+ {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209},+ {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177},+ {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241},+ {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},+ {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201},+ {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169},+ {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233},+ {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153},+ {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217},+ {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185},+ {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249},+ {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},+ {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197},+ {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165},+ {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229},+ {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149},+ {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213},+ {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181},+ {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245},+ {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},+ {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205},+ {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173},+ {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237},+ {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157},+ {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221},+ {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189},+ {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253},+ {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},+ {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195},+ {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163},+ {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227},+ {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147},+ {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211},+ {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179},+ {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243},+ {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},+ {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203},+ {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171},+ {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235},+ {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155},+ {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219},+ {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187},+ {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251},+ {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},+ {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199},+ {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167},+ {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231},+ {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151},+ {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215},+ {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183},+ {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247},+ {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},+ {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207},+ {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175},+ {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239},+ {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159},+ {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223},+ {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191},+ {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255}+ };+local const inflate_huft fixed_td[] = {+ {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097},+ {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385},+ {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193},+ {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577},+ {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145},+ {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577},+ {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289},+ {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577}+ };
+ src/gzip/inflate.c view
@@ -0,0 +1,273 @@+/* inflate.c -- zlib interface to inflate modules+ * Copyright (C) 1995-2002 Mark Adler+ * For conditions of distribution and use, see copyright notice in zlib.h+ */++#include "zutil.h"+#include "infblock.h"++#define DONE INFLATE_DONE+#define BAD INFLATE_BAD++typedef enum {+ METHOD, /* waiting for method byte */+ FLAG, /* waiting for flag byte */+ DICT4, /* four dictionary check bytes to go */+ DICT3, /* three dictionary check bytes to go */+ DICT2, /* two dictionary check bytes to go */+ DICT1, /* one dictionary check byte to go */+ DICT0, /* waiting for inflateSetDictionary */+ BLOCKS, /* decompressing blocks */+ CHECK4, /* four check bytes to go */+ CHECK3, /* three check bytes to go */+ CHECK2, /* two check bytes to go */+ CHECK1, /* one check byte to go */+ DONE, /* finished check, done */+ BAD} /* got an error--stay here */+inflate_mode;++/* inflate private state */+struct internal_state {++ /* mode */+ inflate_mode mode; /* current inflate mode */++ /* mode dependent information */+ union {+ uInt method; /* if FLAGS, method byte */+ struct {+ uLong was; /* computed check value */+ uLong need; /* stream check value */+ } check; /* if CHECK, check values to compare */+ uInt marker; /* if BAD, inflateSync's marker bytes count */+ } sub; /* submode */++ /* mode independent information */+ int nowrap; /* flag for no wrapper */+ uInt wbits; /* log2(window size) (8..15, defaults to 15) */+ inflate_blocks_statef+ *blocks; /* current inflate_blocks state */++};+++ZEXPORT(int) inflateReset( /* z) */+z_streamp z )+{+ if (z == Z_NULL || z->state == Z_NULL)+ return Z_STREAM_ERROR;+ z->total_in = z->total_out = 0;+ z->msg = Z_NULL;+ z->state->mode = z->state->nowrap ? BLOCKS : METHOD;+ inflate_blocks_reset(z->state->blocks, z, Z_NULL);+ Tracev((stderr, "inflate: reset\n"));+ return Z_OK;+}+++ZEXPORT(int) inflateEnd( /* z) */+z_streamp z )+{+ if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)+ return Z_STREAM_ERROR;+ if (z->state->blocks != Z_NULL)+ inflate_blocks_free(z->state->blocks, z);+ ZFREE(z, z->state);+ z->state = Z_NULL;+ Tracev((stderr, "inflate: end\n"));+ return Z_OK;+}+++ZEXPORT(int) inflateInit2_( /* z, w, version, stream_size) */+z_streamp z,+int w,+const char *version,+int stream_size )+{+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||+ stream_size != sizeof(z_stream))+ return Z_VERSION_ERROR;++ /* initialize state */+ if (z == Z_NULL)+ return Z_STREAM_ERROR;+ z->msg = Z_NULL;+ if (z->zalloc == Z_NULL)+ {+ z->zalloc = zcalloc;+ z->opaque = (voidpf)0;+ }+ if (z->zfree == Z_NULL) z->zfree = zcfree;+ if ((z->state = (struct internal_state FAR *)+ ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)+ return Z_MEM_ERROR;+ z->state->blocks = Z_NULL;++ /* handle undocumented nowrap option (no zlib header or check) */+ z->state->nowrap = 0;+ if (w < 0)+ {+ w = - w;+ z->state->nowrap = 1;+ }++ /* set window size */+ if (w < 8 || w > 15)+ {+ inflateEnd(z);+ return Z_STREAM_ERROR;+ }+ z->state->wbits = (uInt)w;++ /* create inflate_blocks state */+ if ((z->state->blocks =+ inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))+ == Z_NULL)+ {+ inflateEnd(z);+ return Z_MEM_ERROR;+ }+ Tracev((stderr, "inflate: allocated\n"));++ /* reset state */+ inflateReset(z);+ return Z_OK;+}++++#undef NEEDBYTE+#define NEEDBYTE {if(z->avail_in==0)return r;r=f;}++#undef NEXTBYTE+#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)+++ZEXPORT(int) inflate( /* z, f) */+z_streamp z,+int f )+{+ int r;+ uInt b;++ if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL)+ return Z_STREAM_ERROR;+ f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;+ r = Z_BUF_ERROR;+ while (1) switch (z->state->mode)+ {+ case METHOD:+ NEEDBYTE+ if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)+ {+ z->state->mode = BAD;+ z->msg = (char*)"unknown compression method";+ z->state->sub.marker = 5; /* can't try inflateSync */+ break;+ }+ if ((z->state->sub.method >> 4) + 8 > z->state->wbits)+ {+ z->state->mode = BAD;+ z->msg = (char*)"invalid window size";+ z->state->sub.marker = 5; /* can't try inflateSync */+ break;+ }+ z->state->mode = FLAG;+ case FLAG:+ NEEDBYTE+ b = NEXTBYTE;+ if (((z->state->sub.method << 8) + b) % 31)+ {+ z->state->mode = BAD;+ z->msg = (char*)"incorrect header check";+ z->state->sub.marker = 5; /* can't try inflateSync */+ break;+ }+ Tracev((stderr, "inflate: zlib header ok\n"));+ if (!(b & PRESET_DICT))+ {+ z->state->mode = BLOCKS;+ break;+ }+ z->state->mode = DICT4;+ case DICT4:+ NEEDBYTE+ z->state->sub.check.need = (uLong)NEXTBYTE << 24;+ z->state->mode = DICT3;+ case DICT3:+ NEEDBYTE+ z->state->sub.check.need += (uLong)NEXTBYTE << 16;+ z->state->mode = DICT2;+ case DICT2:+ NEEDBYTE+ z->state->sub.check.need += (uLong)NEXTBYTE << 8;+ z->state->mode = DICT1;+ case DICT1:+ NEEDBYTE+ z->state->sub.check.need += (uLong)NEXTBYTE;+ z->adler = z->state->sub.check.need;+ z->state->mode = DICT0;+ return Z_NEED_DICT;+ case DICT0:+ z->state->mode = BAD;+ z->msg = (char*)"need dictionary";+ z->state->sub.marker = 0; /* can try inflateSync */+ return Z_STREAM_ERROR;+ case BLOCKS:+ r = inflate_blocks(z->state->blocks, z, r);+ if (r == Z_DATA_ERROR)+ {+ z->state->mode = BAD;+ z->state->sub.marker = 0; /* can try inflateSync */+ break;+ }+ if (r == Z_OK)+ r = f;+ if (r != Z_STREAM_END)+ return r;+ r = f;+ inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);+ if (z->state->nowrap)+ {+ z->state->mode = DONE;+ break;+ }+ z->state->mode = CHECK4;+ case CHECK4:+ NEEDBYTE+ z->state->sub.check.need = (uLong)NEXTBYTE << 24;+ z->state->mode = CHECK3;+ case CHECK3:+ NEEDBYTE+ z->state->sub.check.need += (uLong)NEXTBYTE << 16;+ z->state->mode = CHECK2;+ case CHECK2:+ NEEDBYTE+ z->state->sub.check.need += (uLong)NEXTBYTE << 8;+ z->state->mode = CHECK1;+ case CHECK1:+ NEEDBYTE+ z->state->sub.check.need += (uLong)NEXTBYTE;++ if (z->state->sub.check.was != z->state->sub.check.need)+ {+ z->state->mode = BAD;+ z->msg = (char*)"incorrect data check";+ z->state->sub.marker = 5; /* can't try inflateSync */+ break;+ }+ Tracev((stderr, "inflate: zlib check ok\n"));+ z->state->mode = DONE;+ case DONE:+ return Z_STREAM_END;+ case BAD:+ return Z_DATA_ERROR;+ default:+ return Z_STREAM_ERROR;+ }+#ifdef NEED_DUMMY_RETURN+ return Z_STREAM_ERROR; /* Some dumb compilers complain without this */+#endif+}+
+ src/gzip/inftrees.c view
@@ -0,0 +1,468 @@+/* inftrees.c -- generate Huffman trees for efficient decoding+ * Copyright (C) 1995-2002 Mark Adler+ * For conditions of distribution and use, see copyright notice in zlib.h+ */++#include "zutil.h"+#include "inftrees.h"++#if !defined(BUILDFIXED) && !defined(STDC)+# define BUILDFIXED /* non ANSI compilers may not accept inffixed.h */+#endif+++#if 0+local const char inflate_copyright[] =+ " inflate 1.1.4 Copyright 1995-2002 Mark Adler ";+#endif+/*+ If you use the zlib library in a product, an acknowledgment is welcome+ in the documentation of your product. If for some reason you cannot+ include such an acknowledgment, I would appreciate that you keep this+ copyright string in the executable of your product.+ */++/* simplify the use of the inflate_huft type with some defines */+#define exop word.what.Exop+#define bits word.what.Bits+++local int huft_build OF((+ uIntf *, /* code lengths in bits */+ uInt, /* number of codes */+ uInt, /* number of "simple" codes */+ const uIntf *, /* list of base values for non-simple codes */+ const uIntf *, /* list of extra bits for non-simple codes */+ inflate_huft * FAR*,/* result: starting table */+ uIntf *, /* maximum lookup bits (returns actual) */+ inflate_huft *, /* space for trees */+ uInt *, /* hufts used in space */+ uIntf * )); /* space for values */++/* Tables for deflate from PKZIP's appnote.txt. */+local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};+ /* see note #13 above about 258 */+local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */+local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,+ 8193, 12289, 16385, 24577};+local const uInt cpdext[30] = { /* Extra bits for distance codes */+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,+ 12, 12, 13, 13};++/*+ Huffman code decoding is performed using a multi-level table lookup.+ The fastest way to decode is to simply build a lookup table whose+ size is determined by the longest code. However, the time it takes+ to build this table can also be a factor if the data being decoded+ is not very long. The most common codes are necessarily the+ shortest codes, so those codes dominate the decoding time, and hence+ the speed. The idea is you can have a shorter table that decodes the+ shorter, more probable codes, and then point to subsidiary tables for+ the longer codes. The time it costs to decode the longer codes is+ then traded against the time it takes to make longer tables.++ This results of this trade are in the variables lbits and dbits+ below. lbits is the number of bits the first level table for literal/+ length codes can decode in one step, and dbits is the same thing for+ the distance codes. Subsequent tables are also less than or equal to+ those sizes. These values may be adjusted either when all of the+ codes are shorter than that, in which case the longest code length in+ bits is used, or when the shortest code is *longer* than the requested+ table size, in which case the length of the shortest code in bits is+ used.++ There are two different values for the two tables, since they code a+ different number of possibilities each. The literal/length table+ codes 286 possible values, or in a flat code, a little over eight+ bits. The distance table codes 30 possible values, or a little less+ than five bits, flat. The optimum values for speed end up being+ about one bit more than those, so lbits is 8+1 and dbits is 5+1.+ The optimum values may differ though from machine to machine, and+ possibly even between compilers. Your mileage may vary.+ */+++/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */+#define BMAX 15 /* maximum bit length of any code */++local int huft_build( /* b, n, s, d, e, t, m, hp, hn, v) */+uIntf *b, /* code lengths in bits (all assumed <= BMAX) */+uInt n, /* number of codes (assumed <= 288) */+uInt s, /* number of simple-valued codes (0..s-1) */+const uIntf *d, /* list of base values for non-simple codes */+const uIntf *e, /* list of extra bits for non-simple codes */+inflate_huft * FAR *t, /* result: starting table */+uIntf *m, /* maximum lookup bits, returns actual */+inflate_huft *hp, /* space for trees */+uInt *hn, /* hufts used in space */+uIntf *v /* working area: values in order of bit length */+/* Given a list of code lengths and a maximum table size, make a set of+ tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR+ if the given code set is incomplete (the tables are still built in this+ case), or Z_DATA_ERROR if the input is invalid. */+)+{++ uInt a; /* counter for codes of length k */+ uInt c[BMAX+1]; /* bit length count table */+ uInt f; /* i repeats in table every f entries */+ int g; /* maximum code length */+ int h; /* table level */+ register uInt i; /* counter, current code */+ register uInt j; /* counter */+ register int k; /* number of bits in current code */+ int l; /* bits per table (returned in m) */+ uInt mask; /* (1 << w) - 1, to avoid cc -O bug on HP */+ register uIntf *p; /* pointer into c[], b[], or v[] */+ inflate_huft *q; /* points to current table */+ struct inflate_huft_s r; /* table entry for structure assignment */+ inflate_huft *u[BMAX]; /* table stack */+ register int w; /* bits before this table == (l * h) */+ uInt x[BMAX+1]; /* bit offsets, then code stack */+ uIntf *xp; /* pointer into x */+ int y; /* number of dummy codes added */+ uInt z; /* number of entries in current table */+++ /* Make compiler happy */+ r.base = 0;++ /* Generate counts for each bit length */+ p = c;+#define C0 *p++ = 0;+#define C2 C0 C0 C0 C0+#define C4 C2 C2 C2 C2+ C4 /* clear c[]--assume BMAX+1 is 16 */+ p = b; i = n;+ do {+ c[*p++]++; /* assume all entries <= BMAX */+ } while (--i);+ if (c[0] == n) /* null input--all zero length codes */+ {+ *t = (inflate_huft *)Z_NULL;+ *m = 0;+ return Z_OK;+ }+++ /* Find minimum and maximum length, bound *m by those */+ l = *m;+ for (j = 1; j <= BMAX; j++)+ if (c[j])+ break;+ k = j; /* minimum code length */+ if ((uInt)l < j)+ l = j;+ for (i = BMAX; i; i--)+ if (c[i])+ break;+ g = i; /* maximum code length */+ if ((uInt)l > i)+ l = i;+ *m = l;+++ /* Adjust last length count to fill out codes, if needed */+ for (y = 1 << j; j < i; j++, y <<= 1)+ if ((y -= c[j]) < 0)+ return Z_DATA_ERROR;+ if ((y -= c[i]) < 0)+ return Z_DATA_ERROR;+ c[i] += y;+++ /* Generate starting offsets into the value table for each length */+ x[1] = j = 0;+ p = c + 1; xp = x + 2;+ while (--i) { /* note that i == g from above */+ *xp++ = (j += *p++);+ }+++ /* Make a table of values in order of bit lengths */+ p = b; i = 0;+ do {+ if ((j = *p++) != 0)+ v[x[j]++] = i;+ } while (++i < n);+ n = x[g]; /* set n to length of v */+++ /* Generate the Huffman codes and for each, make the table entries */+ x[0] = i = 0; /* first Huffman code is zero */+ p = v; /* grab values in bit order */+ h = -1; /* no tables yet--level -1 */+ w = -l; /* bits decoded == (l * h) */+ u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */+ q = (inflate_huft *)Z_NULL; /* ditto */+ z = 0; /* ditto */++ /* go through the bit lengths (k already is bits in shortest code) */+ for (; k <= g; k++)+ {+ a = c[k];+ while (a--)+ {+ /* here i is the Huffman code of length k bits for value *p */+ /* make tables up to required level */+ while (k > w + l)+ {+ h++;+ w += l; /* previous table always l bits */++ /* compute minimum size table less than or equal to l bits */+ z = g - w;+ z = z > (uInt)l ? (uInt)l : z; /* table size upper limit */+ if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */+ { /* too few codes for k-w bit table */+ f -= a + 1; /* deduct codes from patterns left */+ xp = c + k;+ if (j < z)+ while (++j < z) /* try smaller tables up to z bits */+ {+ if ((f <<= 1) <= *++xp)+ break; /* enough codes to use up j bits */+ f -= *xp; /* else deduct codes from patterns */+ }+ }+ z = 1 << j; /* table entries for j-bit table */++ /* allocate new table */+ if (*hn + z > MANY) /* (note: doesn't matter for fixed) */+ return Z_DATA_ERROR; /* overflow of MANY */+ u[h] = q = hp + *hn;+ *hn += z;++ /* connect to last table, if there is one */+ if (h)+ {+ x[h] = i; /* save pattern for backing up */+ r.bits = (Byte)l; /* bits to dump before this table */+ r.exop = (Byte)j; /* bits in this table */+ j = i >> (w - l);+ r.base = (uInt)(q - u[h-1] - j); /* offset to this table */+ u[h-1][j] = r; /* connect to last table */+ }+ else+ *t = q; /* first table is returned result */+ }++ /* set up table entry in r */+ r.bits = (Byte)(k - w);+ if (p >= v + n)+ r.exop = 128 + 64; /* out of values--invalid code */+ else if (*p < s)+ {+ r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */+ r.base = *p++; /* simple code is just the value */+ }+ else+ {+ r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */+ r.base = d[*p++ - s];+ }++ /* fill code-like entries with r */+ f = 1 << (k - w);+ for (j = i >> w; j < z; j += f)+ q[j] = r;++ /* backwards increment the k-bit code i */+ for (j = 1 << (k - 1); i & j; j >>= 1)+ i ^= j;+ i ^= j;++ /* backup over finished tables */+ mask = (1 << w) - 1; /* needed on HP, cc -O bug */+ while ((i & mask) != x[h])+ {+ h--; /* don't need to update q */+ w -= l;+ mask = (1 << w) - 1;+ }+ }+ }+++ /* Return Z_BUF_ERROR if we were given an incomplete table */+ return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;+}+++local int inflate_trees_bits( /* c, bb, tb, hp, z) */+uIntf *c, /* 19 code lengths */+uIntf *bb, /* bits tree desired/actual depth */+inflate_huft * FAR *tb, /* bits tree result */+inflate_huft *hp, /* space for trees */+z_streamp z /* for messages */+)+{+ int r;+ uInt hn = 0; /* hufts used in space */+ uIntf *v; /* work area for huft_build */++ if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL)+ return Z_MEM_ERROR;+ r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL,+ tb, bb, hp, &hn, v);+ if (r == Z_DATA_ERROR)+ z->msg = (char*)"oversubscribed dynamic bit lengths tree";+ else if (r == Z_BUF_ERROR || *bb == 0)+ {+ z->msg = (char*)"incomplete dynamic bit lengths tree";+ r = Z_DATA_ERROR;+ }+ ZFREE(z, v);+ return r;+}+++local int inflate_trees_dynamic( /* nl, nd, c, bl, bd, tl, td, hp, z) */+uInt nl, /* number of literal/length codes */+uInt nd, /* number of distance codes */+uIntf *c, /* that many (total) code lengths */+uIntf *bl, /* literal desired/actual bit depth */+uIntf *bd, /* distance desired/actual bit depth */+inflate_huft * FAR *tl, /* literal/length tree result */+inflate_huft * FAR *td, /* distance tree result */+inflate_huft *hp, /* space for trees */+z_streamp z /* for messages */+)+{+ int r;+ uInt hn = 0; /* hufts used in space */+ uIntf *v; /* work area for huft_build */++ /* allocate work area */+ if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)+ return Z_MEM_ERROR;++ /* build literal/length tree */+ r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v);+ if (r != Z_OK || *bl == 0)+ {+ if (r == Z_DATA_ERROR)+ z->msg = (char*)"oversubscribed literal/length tree";+ else if (r != Z_MEM_ERROR)+ {+ z->msg = (char*)"incomplete literal/length tree";+ r = Z_DATA_ERROR;+ }+ ZFREE(z, v);+ return r;+ }++ /* build distance tree */+ r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v);+ if (r != Z_OK || (*bd == 0 && nl > 257))+ {+ if (r == Z_DATA_ERROR)+ z->msg = (char*)"oversubscribed distance tree";+ else if (r == Z_BUF_ERROR) {+#if 0+ {+#endif+#ifdef PKZIP_BUG_WORKAROUND+ r = Z_OK;+ }+#else+ z->msg = (char*)"incomplete distance tree";+ r = Z_DATA_ERROR;+ }+ else if (r != Z_MEM_ERROR)+ {+ z->msg = (char*)"empty distance tree with lengths";+ r = Z_DATA_ERROR;+ }+ ZFREE(z, v);+ return r;+#endif+ }++ /* done */+ ZFREE(z, v);+ return Z_OK;+}+++/* build fixed tables only once--keep them here */+#ifdef BUILDFIXED+local int fixed_built = 0;+#define FIXEDH 544 /* number of hufts used by fixed tables */+local inflate_huft fixed_mem[FIXEDH];+local uInt fixed_bl;+local uInt fixed_bd;+local inflate_huft *fixed_tl;+local inflate_huft *fixed_td;+#else+#include "inffixed.h"+#endif+++local int inflate_trees_fixed( /* bl, bd, tl, td, z) */+uIntf *bl, /* literal desired/actual bit depth */+uIntf *bd, /* distance desired/actual bit depth */+const inflate_huft * FAR *tl, /* literal/length tree result */+const inflate_huft * FAR *td, /* distance tree result */+z_streamp z /* for memory allocation */+)+{+#ifdef BUILDFIXED+ /* build fixed tables if not already */+ if (!fixed_built)+ {+ int k; /* temporary variable */+ uInt f = 0; /* number of hufts used in fixed_mem */+ uIntf *c; /* length list for huft_build */+ uIntf *v; /* work area for huft_build */++ /* allocate memory */+ if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)+ return Z_MEM_ERROR;+ if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)+ {+ ZFREE(z, c);+ return Z_MEM_ERROR;+ }++ /* literal table */+ for (k = 0; k < 144; k++)+ c[k] = 8;+ for (; k < 256; k++)+ c[k] = 9;+ for (; k < 280; k++)+ c[k] = 7;+ for (; k < 288; k++)+ c[k] = 8;+ fixed_bl = 9;+ huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl,+ fixed_mem, &f, v);++ /* distance table */+ for (k = 0; k < 30; k++)+ c[k] = 5;+ fixed_bd = 5;+ huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd,+ fixed_mem, &f, v);++ /* done */+ ZFREE(z, v);+ ZFREE(z, c);+ fixed_built = 1;+ }+#else+ FT_UNUSED(z);+#endif+ *bl = fixed_bl;+ *bd = fixed_bd;+ *tl = fixed_tl;+ *td = fixed_td;+ return Z_OK;+}
+ src/gzip/inftrees.h view
@@ -0,0 +1,63 @@+/* inftrees.h -- header to use inftrees.c+ * Copyright (C) 1995-2002 Mark Adler+ * For conditions of distribution and use, see copyright notice in zlib.h+ */++/* WARNING: this file should *not* be used by applications. It is+ part of the implementation of the compression library and is+ subject to change. Applications should only use zlib.h.+ */++/* Huffman code lookup table entry--this entry is four bytes for machines+ that have 16-bit pointers (e.g. PC's in the small or medium model). */++#ifndef _INFTREES_H+#define _INFTREES_H++typedef struct inflate_huft_s FAR inflate_huft;++struct inflate_huft_s {+ union {+ struct {+ Byte Exop; /* number of extra bits or operation */+ Byte Bits; /* number of bits in this code or subcode */+ } what;+ uInt pad; /* pad structure to a power of 2 (4 bytes for */+ } word; /* 16-bit, 8 bytes for 32-bit int's) */+ uInt base; /* literal, length base, distance base,+ or table offset */+};++/* Maximum size of dynamic tree. The maximum found in a long but non-+ exhaustive search was 1004 huft structures (850 for length/literals+ and 154 for distances, the latter actually the result of an+ exhaustive search). The actual maximum is not known, but the+ value below is more than safe. */+#define MANY 1440++local int inflate_trees_bits OF((+ uIntf *, /* 19 code lengths */+ uIntf *, /* bits tree desired/actual depth */+ inflate_huft * FAR *, /* bits tree result */+ inflate_huft *, /* space for trees */+ z_streamp)); /* for messages */++local int inflate_trees_dynamic OF((+ uInt, /* number of literal/length codes */+ uInt, /* number of distance codes */+ uIntf *, /* that many (total) code lengths */+ uIntf *, /* literal desired/actual bit depth */+ uIntf *, /* distance desired/actual bit depth */+ inflate_huft * FAR *, /* literal/length tree result */+ inflate_huft * FAR *, /* distance tree result */+ inflate_huft *, /* space for trees */+ z_streamp)); /* for messages */++local int inflate_trees_fixed OF((+ uIntf *, /* literal desired/actual bit depth */+ uIntf *, /* distance desired/actual bit depth */+ const inflate_huft * FAR *, /* literal/length tree result */+ const inflate_huft * FAR *, /* distance tree result */+ z_streamp)); /* for memory allocation */++#endif /* _INFTREES_H */
+ src/gzip/infutil.c view
@@ -0,0 +1,86 @@+/* inflate_util.c -- data and routines common to blocks and codes+ * Copyright (C) 1995-2002 Mark Adler+ * For conditions of distribution and use, see copyright notice in zlib.h+ */++#include "zutil.h"+#include "infblock.h"+#include "inftrees.h"+#include "infcodes.h"+#include "infutil.h"+++/* And'ing with mask[n] masks the lower n bits */+local const uInt inflate_mask[17] = {+ 0x0000,+ 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,+ 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff+};+++/* copy as much as possible from the sliding window to the output area */+local int inflate_flush( /* s, z, r) */+inflate_blocks_statef *s,+z_streamp z,+int r )+{+ uInt n;+ Bytef *p;+ Bytef *q;++ /* local copies of source and destination pointers */+ p = z->next_out;+ q = s->read;++ /* compute number of bytes to copy as far as end of window */+ n = (uInt)((q <= s->write ? s->write : s->end) - q);+ if (n > z->avail_out) n = z->avail_out;+ if (n && r == Z_BUF_ERROR) r = Z_OK;++ /* update counters */+ z->avail_out -= n;+ z->total_out += n;++ /* update check information */+ if (s->checkfn != Z_NULL)+ z->adler = s->check = (*s->checkfn)(s->check, q, n);++ /* copy as far as end of window */+ zmemcpy(p, q, n);+ p += n;+ q += n;++ /* see if more to copy at beginning of window */+ if (q == s->end)+ {+ /* wrap pointers */+ q = s->window;+ if (s->write == s->end)+ s->write = s->window;++ /* compute bytes to copy */+ n = (uInt)(s->write - q);+ if (n > z->avail_out) n = z->avail_out;+ if (n && r == Z_BUF_ERROR) r = Z_OK;++ /* update counters */+ z->avail_out -= n;+ z->total_out += n;++ /* update check information */+ if (s->checkfn != Z_NULL)+ z->adler = s->check = (*s->checkfn)(s->check, q, n);++ /* copy */+ zmemcpy(p, q, n);+ p += n;+ q += n;+ }++ /* update pointers */+ z->next_out = p;+ s->read = q;++ /* done */+ return r;+}
+ src/gzip/infutil.h view
@@ -0,0 +1,98 @@+/* infutil.h -- types and macros common to blocks and codes+ * Copyright (C) 1995-2002 Mark Adler+ * For conditions of distribution and use, see copyright notice in zlib.h+ */++/* WARNING: this file should *not* be used by applications. It is+ part of the implementation of the compression library and is+ subject to change. Applications should only use zlib.h.+ */++#ifndef _INFUTIL_H+#define _INFUTIL_H++typedef enum {+ TYPE, /* get type bits (3, including end bit) */+ LENS, /* get lengths for stored */+ STORED, /* processing stored block */+ TABLE, /* get table lengths */+ BTREE, /* get bit lengths tree for a dynamic block */+ DTREE, /* get length, distance trees for a dynamic block */+ CODES, /* processing fixed or dynamic block */+ DRY, /* output remaining window bytes */+ DONE, /* finished last block, done */+ BAD} /* got a data error--stuck here */+inflate_block_mode;++/* inflate blocks semi-private state */+struct inflate_blocks_state {++ /* mode */+ inflate_block_mode mode; /* current inflate_block mode */++ /* mode dependent information */+ union {+ uInt left; /* if STORED, bytes left to copy */+ struct {+ uInt table; /* table lengths (14 bits) */+ uInt index; /* index into blens (or border) */+ uIntf *blens; /* bit lengths of codes */+ uInt bb; /* bit length tree depth */+ inflate_huft *tb; /* bit length decoding tree */+ } trees; /* if DTREE, decoding info for trees */+ struct {+ inflate_codes_statef+ *codes;+ } decode; /* if CODES, current state */+ } sub; /* submode */+ uInt last; /* true if this block is the last block */++ /* mode independent information */+ uInt bitk; /* bits in bit buffer */+ uLong bitb; /* bit buffer */+ inflate_huft *hufts; /* single malloc for tree space */+ Bytef *window; /* sliding window */+ Bytef *end; /* one byte after sliding window */+ Bytef *read; /* window read pointer */+ Bytef *write; /* window write pointer */+ check_func checkfn; /* check function */+ uLong check; /* check on output */++};+++/* defines for inflate input/output */+/* update pointers and return */+#define UPDBITS {s->bitb=b;s->bitk=k;}+#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}+#define UPDOUT {s->write=q;}+#define UPDATE {UPDBITS UPDIN UPDOUT}+#define LEAVE {UPDATE return inflate_flush(s,z,r);}+/* get bytes and bits */+#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}+#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}+#define NEXTBYTE (n--,*p++)+#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}+#define DUMPBITS(j) {b>>=(j);k-=(j);}+/* output bytes */+#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q)+#define LOADOUT {q=s->write;m=(uInt)WAVAIL;}+#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}}+#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}+#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}+#define OUTBYTE(a) {*q++=(Byte)(a);m--;}+/* load local pointers */+#define LOAD {LOADIN LOADOUT}++/* masks for lower bits (size given to avoid silly warnings with Visual C++) */+#ifndef NO_INFLATE_MASK+local uInt inflate_mask[17];+#endif++/* copy as much as possible from the sliding window to the output area */+local int inflate_flush OF((+ inflate_blocks_statef *,+ z_streamp ,+ int));++#endif
+ src/gzip/zconf.h view
@@ -0,0 +1,284 @@+/* zconf.h -- configuration of the zlib compression library+ * Copyright (C) 1995-2002 Jean-loup Gailly.+ * For conditions of distribution and use, see copyright notice in zlib.h+ */++/* @(#) $Id$ */++#ifndef _ZCONF_H+#define _ZCONF_H++/*+ * If you *really* need a unique prefix for all types and library functions,+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.+ */+#ifdef Z_PREFIX+# define deflateInit_ z_deflateInit_+# define deflate z_deflate+# define deflateEnd z_deflateEnd+# define inflateInit_ z_inflateInit_+# define inflate z_inflate+# define inflateEnd z_inflateEnd+# define deflateInit2_ z_deflateInit2_+# define deflateSetDictionary z_deflateSetDictionary+# define deflateCopy z_deflateCopy+# define deflateReset z_deflateReset+# define deflateParams z_deflateParams+# define inflateInit2_ z_inflateInit2_+# define inflateSetDictionary z_inflateSetDictionary+# define inflateSync z_inflateSync+# define inflateSyncPoint z_inflateSyncPoint+# define inflateReset z_inflateReset+# define compress z_compress+# define compress2 z_compress2+# define uncompress z_uncompress+# define adler32 z_adler32+# define crc32 z_crc32+# define get_crc_table z_get_crc_table++# define Byte z_Byte+# define uInt z_uInt+# define uLong z_uLong+# define Bytef z_Bytef+# define charf z_charf+# define intf z_intf+# define uIntf z_uIntf+# define uLongf z_uLongf+# define voidpf z_voidpf+# define voidp z_voidp+#endif++#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)+# define WIN32+#endif+#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386)+# ifndef __32BIT__+# define __32BIT__+# endif+#endif+#if defined(__MSDOS__) && !defined(MSDOS)+# define MSDOS+#endif++/* WinCE doesn't have errno.h */+#ifdef _WIN32_WCE+# define NO_ERRNO_H+#endif+++/*+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more+ * than 64k bytes at a time (needed on systems with 16-bit int).+ */+#if defined(MSDOS) && !defined(__32BIT__)+# define MAXSEG_64K+#endif+#ifdef MSDOS+# define UNALIGNED_OK+#endif++#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC)+# define STDC+#endif+#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__)+# ifndef STDC+# define STDC+# endif+#endif++#ifndef STDC+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */+# define const+# endif+#endif++/* Some Mac compilers merge all .h files incorrectly: */+#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__)+# define NO_DUMMY_DECL+#endif++/* Old Borland C and LCC incorrectly complains about missing returns: */+#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500)+# define NEED_DUMMY_RETURN+#endif++#if defined(__LCC__)+# define NEED_DUMMY_RETURN+#endif++/* Maximum value for memLevel in deflateInit2 */+#ifndef MAX_MEM_LEVEL+# ifdef MAXSEG_64K+# define MAX_MEM_LEVEL 8+# else+# define MAX_MEM_LEVEL 9+# endif+#endif++/* Maximum value for windowBits in deflateInit2 and inflateInit2.+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files+ * created by gzip. (Files created by minigzip can still be extracted by+ * gzip.)+ */+#ifndef MAX_WBITS+# define MAX_WBITS 15 /* 32K LZ77 window */+#endif++/* The memory requirements for deflate are (in bytes):+ (1 << (windowBits+2)) + (1 << (memLevel+9))+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)+ plus a few kilobytes for small objects. For example, if you want to reduce+ the default memory requirements from 256K to 128K, compile with+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"+ Of course this will generally degrade compression (there's no free lunch).++ The memory requirements for inflate are (in bytes) 1 << windowBits+ that is, 32K for windowBits=15 (default value) plus a few kilobytes+ for small objects.+*/++ /* Type declarations */++#ifndef OF /* function prototypes */+# ifdef STDC+# define OF(args) args+# else+# define OF(args) ()+# endif+#endif++/* The following definitions for FAR are needed only for MSDOS mixed+ * model programming (small or medium model with some far allocations).+ * This was tested only with MSC; for other MSDOS compilers you may have+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,+ * just define FAR to be empty.+ */+#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__)+ /* MSC small or medium model */+# define SMALL_MEDIUM+# ifdef _MSC_VER+# define FAR _far+# else+# define FAR far+# endif+#endif+#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__))+# ifndef __32BIT__+# define SMALL_MEDIUM+# define FAR _far+# endif+#endif++/* Compile with -DZLIB_DLL for Windows DLL support */+#if defined(ZLIB_DLL)+# if defined(_WINDOWS) || defined(WINDOWS)+# ifdef FAR+# undef FAR+# endif+# include <windows.h>+# define ZEXPORT(x) x WINAPI+# ifdef WIN32+# define ZEXPORTVA(x) x WINAPIV+# else+# define ZEXPORTVA(x) x FAR _cdecl _export+# endif+# endif+# if defined (__BORLANDC__)+# if (__BORLANDC__ >= 0x0500) && defined (WIN32)+# include <windows.h>+# define ZEXPORT(x) x __declspec(dllexport) WINAPI+# define ZEXPORTRVA(x) x __declspec(dllexport) WINAPIV+# else+# if defined (_Windows) && defined (__DLL__)+# define ZEXPORT(x) x _export+# define ZEXPORTVA(x) x _export+# endif+# endif+# endif+#endif+++#ifndef ZEXPORT+# define ZEXPORT(x) static x+#endif+#ifndef ZEXPORTVA+# define ZEXPORTVA(x) static x+#endif+#ifndef ZEXTERN+# define ZEXTERN(x) static x+#endif+#ifndef ZEXTERNDEF+# define ZEXTERNDEF(x) static x+#endif++#ifndef FAR+# define FAR+#endif++#if !defined(MACOS) && !defined(TARGET_OS_MAC)+typedef unsigned char Byte; /* 8 bits */+#endif+typedef unsigned int uInt; /* 16 bits or more */+typedef unsigned long uLong; /* 32 bits or more */++#ifdef SMALL_MEDIUM+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */+# define Bytef Byte FAR+#else+ typedef Byte FAR Bytef;+#endif+typedef char FAR charf;+typedef int FAR intf;+typedef uInt FAR uIntf;+typedef uLong FAR uLongf;++#ifdef STDC+ typedef void FAR *voidpf;+ typedef void *voidp;+#else+ typedef Byte FAR *voidpf;+ typedef Byte *voidp;+#endif++#ifdef HAVE_UNISTD_H+# include <sys/types.h> /* for off_t */+# include <unistd.h> /* for SEEK_* and off_t */+# define z_off_t off_t+#endif+#ifndef SEEK_SET+# define SEEK_SET 0 /* Seek from beginning of file. */+# define SEEK_CUR 1 /* Seek from current position. */+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */+#endif+#ifndef z_off_t+# define z_off_t long+#endif++/* MVS linker does not support external names larger than 8 bytes */+#if defined(__MVS__)+# pragma map(deflateInit_,"DEIN")+# pragma map(deflateInit2_,"DEIN2")+# pragma map(deflateEnd,"DEEND")+# pragma map(inflateInit_,"ININ")+# pragma map(inflateInit2_,"ININ2")+# pragma map(inflateEnd,"INEND")+# pragma map(inflateSync,"INSY")+# pragma map(inflateSetDictionary,"INSEDI")+# pragma map(inflate_blocks,"INBL")+# pragma map(inflate_blocks_new,"INBLNE")+# pragma map(inflate_blocks_free,"INBLFR")+# pragma map(inflate_blocks_reset,"INBLRE")+# pragma map(inflate_codes_free,"INCOFR")+# pragma map(inflate_codes,"INCO")+# pragma map(inflate_fast,"INFA")+# pragma map(inflate_flush,"INFLU")+# pragma map(inflate_mask,"INMA")+# pragma map(inflate_set_dictionary,"INSEDI2")+# pragma map(inflate_copyright,"INCOPY")+# pragma map(inflate_trees_bits,"INTRBI")+# pragma map(inflate_trees_dynamic,"INTRDY")+# pragma map(inflate_trees_fixed,"INTRFI")+# pragma map(inflate_trees_free,"INTRFR")+#endif++#endif /* _ZCONF_H */
+ src/gzip/zlib.h view
@@ -0,0 +1,830 @@+/* zlib.h -- interface of the 'zlib' general purpose compression library+ version 1.1.4, March 11th, 2002++ Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler++ This software is provided 'as-is', without any express or implied+ warranty. In no event will the authors be held liable for any damages+ arising from the use of this software.++ Permission is granted to anyone to use this software for any purpose,+ including commercial applications, and to alter it and redistribute it+ freely, subject to the following restrictions:++ 1. The origin of this software must not be misrepresented; you must not+ claim that you wrote the original software. If you use this software+ in a product, an acknowledgment in the product documentation would be+ appreciated but is not required.+ 2. Altered source versions must be plainly marked as such, and must not be+ misrepresented as being the original software.+ 3. This notice may not be removed or altered from any source distribution.++ Jean-loup Gailly Mark Adler+ jloup@gzip.org madler@alumni.caltech.edu+++ The data format used by the zlib library is described by RFCs (Request for+ Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt+ (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).+*/++#ifndef _ZLIB_H+#define _ZLIB_H++#include "zconf.h"++#ifdef __cplusplus+extern "C" {+#endif++#define ZLIB_VERSION "1.1.4"++/*+ The 'zlib' compression library provides in-memory compression and+ decompression functions, including integrity checks of the uncompressed+ data. This version of the library supports only one compression method+ (deflation) but other algorithms will be added later and will have the same+ stream interface.++ Compression can be done in a single step if the buffers are large+ enough (for example if an input file is mmap'ed), or can be done by+ repeated calls of the compression function. In the latter case, the+ application must provide more input and/or consume the output+ (providing more output space) before each call.++ The library also supports reading and writing files in gzip (.gz) format+ with an interface similar to that of stdio.++ The library does not install any signal handler. The decoder checks+ the consistency of the compressed data, so the library should never+ crash even in case of corrupted input.+*/++typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));+typedef void (*free_func) OF((voidpf opaque, voidpf address));++struct internal_state;++typedef struct z_stream_s {+ Bytef *next_in; /* next input byte */+ uInt avail_in; /* number of bytes available at next_in */+ uLong total_in; /* total nb of input bytes read so far */++ Bytef *next_out; /* next output byte should be put there */+ uInt avail_out; /* remaining free space at next_out */+ uLong total_out; /* total nb of bytes output so far */++ char *msg; /* last error message, NULL if no error */+ struct internal_state FAR *state; /* not visible by applications */++ alloc_func zalloc; /* used to allocate the internal state */+ free_func zfree; /* used to free the internal state */+ voidpf opaque; /* private data object passed to zalloc and zfree */++ int data_type; /* best guess about the data type: ascii or binary */+ uLong adler; /* adler32 value of the uncompressed data */+ uLong reserved; /* reserved for future use */+} z_stream;++typedef z_stream FAR *z_streamp;++/*+ The application must update next_in and avail_in when avail_in has+ dropped to zero. It must update next_out and avail_out when avail_out+ has dropped to zero. The application must initialize zalloc, zfree and+ opaque before calling the init function. All other fields are set by the+ compression library and must not be updated by the application.++ The opaque value provided by the application will be passed as the first+ parameter for calls of zalloc and zfree. This can be useful for custom+ memory management. The compression library attaches no meaning to the+ opaque value.++ zalloc must return Z_NULL if there is not enough memory for the object.+ If zlib is used in a multi-threaded application, zalloc and zfree must be+ thread safe.++ On 16-bit systems, the functions zalloc and zfree must be able to allocate+ exactly 65536 bytes, but will not be required to allocate more than this+ if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,+ pointers returned by zalloc for objects of exactly 65536 bytes *must*+ have their offset normalized to zero. The default allocation function+ provided by this library ensures this (see zutil.c). To reduce memory+ requirements and avoid any allocation of 64K objects, at the expense of+ compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).++ The fields total_in and total_out can be used for statistics or+ progress reports. After compression, total_in holds the total size of+ the uncompressed data and may be saved for use in the decompressor+ (particularly if the decompressor wants to decompress everything in+ a single step).+*/++ /* constants */++#define Z_NO_FLUSH 0+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */+#define Z_SYNC_FLUSH 2+#define Z_FULL_FLUSH 3+#define Z_FINISH 4+/* Allowed flush values; see deflate() below for details */++#define Z_OK 0+#define Z_STREAM_END 1+#define Z_NEED_DICT 2+#define Z_ERRNO (-1)+#define Z_STREAM_ERROR (-2)+#define Z_DATA_ERROR (-3)+#define Z_MEM_ERROR (-4)+#define Z_BUF_ERROR (-5)+#define Z_VERSION_ERROR (-6)+/* Return codes for the compression/decompression functions. Negative+ * values are errors, positive values are used for special but normal events.+ */++#define Z_NO_COMPRESSION 0+#define Z_BEST_SPEED 1+#define Z_BEST_COMPRESSION 9+#define Z_DEFAULT_COMPRESSION (-1)+/* compression levels */++#define Z_FILTERED 1+#define Z_HUFFMAN_ONLY 2+#define Z_DEFAULT_STRATEGY 0+/* compression strategy; see deflateInit2() below for details */++#define Z_BINARY 0+#define Z_ASCII 1+#define Z_UNKNOWN 2+/* Possible values of the data_type field */++#define Z_DEFLATED 8+/* The deflate compression method (the only one supported in this version) */++#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */+++ /* basic functions */++/* The application can compare zlibVersion and ZLIB_VERSION for consistency.+ If the first character differs, the library code actually used is+ not compatible with the zlib.h header file used by the application.+ This check is automatically made by deflateInit and inflateInit.+ */++/*+ZEXTERN(int) deflateInit OF((z_streamp strm, int level));++ Initializes the internal stream state for compression. The fields+ zalloc, zfree and opaque must be initialized before by the caller.+ If zalloc and zfree are set to Z_NULL, deflateInit updates them to+ use default allocation functions.++ The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:+ 1 gives best speed, 9 gives best compression, 0 gives no compression at+ all (the input data is simply copied a block at a time).+ Z_DEFAULT_COMPRESSION requests a default compromise between speed and+ compression (currently equivalent to level 6).++ deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not+ enough memory, Z_STREAM_ERROR if level is not a valid compression level,+ Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible+ with the version assumed by the caller (ZLIB_VERSION).+ msg is set to null if there is no error message. deflateInit does not+ perform any compression: this will be done by deflate().+*/+++/*+ deflate compresses as much data as possible, and stops when the input+ buffer becomes empty or the output buffer becomes full. It may introduce some+ output latency (reading input without producing any output) except when+ forced to flush.++ The detailed semantics are as follows. deflate performs one or both of the+ following actions:++ - Compress more input starting at next_in and update next_in and avail_in+ accordingly. If not all input can be processed (because there is not+ enough room in the output buffer), next_in and avail_in are updated and+ processing will resume at this point for the next call of deflate().++ - Provide more output starting at next_out and update next_out and avail_out+ accordingly. This action is forced if the parameter flush is non zero.+ Forcing flush frequently degrades the compression ratio, so this parameter+ should be set only when necessary (in interactive applications).+ Some output may be provided even if flush is not set.++ Before the call of deflate(), the application should ensure that at least+ one of the actions is possible, by providing more input and/or consuming+ more output, and updating avail_in or avail_out accordingly; avail_out+ should never be zero before the call. The application can consume the+ compressed output when it wants, for example when the output buffer is full+ (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK+ and with zero avail_out, it must be called again after making room in the+ output buffer because there might be more output pending.++ If the parameter flush is set to Z_SYNC_FLUSH, all pending output is+ flushed to the output buffer and the output is aligned on a byte boundary, so+ that the decompressor can get all input data available so far. (In particular+ avail_in is zero after the call if enough output space has been provided+ before the call.) Flushing may degrade compression for some compression+ algorithms and so it should be used only when necessary.++ If flush is set to Z_FULL_FLUSH, all output is flushed as with+ Z_SYNC_FLUSH, and the compression state is reset so that decompression can+ restart from this point if previous compressed data has been damaged or if+ random access is desired. Using Z_FULL_FLUSH too often can seriously degrade+ the compression.++ If deflate returns with avail_out == 0, this function must be called again+ with the same value of the flush parameter and more output space (updated+ avail_out), until the flush is complete (deflate returns with non-zero+ avail_out).++ If the parameter flush is set to Z_FINISH, pending input is processed,+ pending output is flushed and deflate returns with Z_STREAM_END if there+ was enough output space; if deflate returns with Z_OK, this function must be+ called again with Z_FINISH and more output space (updated avail_out) but no+ more input data, until it returns with Z_STREAM_END or an error. After+ deflate has returned Z_STREAM_END, the only possible operations on the+ stream are deflateReset or deflateEnd.++ Z_FINISH can be used immediately after deflateInit if all the compression+ is to be done in a single step. In this case, avail_out must be at least+ 0.1% larger than avail_in plus 12 bytes. If deflate does not return+ Z_STREAM_END, then it must be called again as described above.++ deflate() sets strm->adler to the adler32 checksum of all input read+ so far (that is, total_in bytes).++ deflate() may update data_type if it can make a good guess about+ the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered+ binary. This field is only for information purposes and does not affect+ the compression algorithm in any manner.++ deflate() returns Z_OK if some progress has been made (more input+ processed or more output produced), Z_STREAM_END if all input has been+ consumed and all output has been produced (only when flush is set to+ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example+ if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible+ (for example avail_in or avail_out was zero).+*/+++/*+ All dynamically allocated data structures for this stream are freed.+ This function discards any unprocessed input and does not flush any+ pending output.++ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the+ stream state was inconsistent, Z_DATA_ERROR if the stream was freed+ prematurely (some input or output was discarded). In the error case,+ msg may be set but then points to a static string (which must not be+ deallocated).+*/+++/*+ZEXTERN(int) inflateInit OF((z_streamp strm));++ Initializes the internal stream state for decompression. The fields+ next_in, avail_in, zalloc, zfree and opaque must be initialized before by+ the caller. If next_in is not Z_NULL and avail_in is large enough (the exact+ value depends on the compression method), inflateInit determines the+ compression method from the zlib header and allocates all data structures+ accordingly; otherwise the allocation will be deferred to the first call of+ inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to+ use default allocation functions.++ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the+ version assumed by the caller. msg is set to null if there is no error+ message. inflateInit does not perform any decompression apart from reading+ the zlib header if present: this will be done by inflate(). (So next_in and+ avail_in may be modified, but next_out and avail_out are unchanged.)+*/+++ZEXTERN(int) inflate OF((z_streamp strm, int flush));+/*+ inflate decompresses as much data as possible, and stops when the input+ buffer becomes empty or the output buffer becomes full. It may some+ introduce some output latency (reading input without producing any output)+ except when forced to flush.++ The detailed semantics are as follows. inflate performs one or both of the+ following actions:++ - Decompress more input starting at next_in and update next_in and avail_in+ accordingly. If not all input can be processed (because there is not+ enough room in the output buffer), next_in is updated and processing+ will resume at this point for the next call of inflate().++ - Provide more output starting at next_out and update next_out and avail_out+ accordingly. inflate() provides as much output as possible, until there+ is no more input data or no more space in the output buffer (see below+ about the flush parameter).++ Before the call of inflate(), the application should ensure that at least+ one of the actions is possible, by providing more input and/or consuming+ more output, and updating the next_* and avail_* values accordingly.+ The application can consume the uncompressed output when it wants, for+ example when the output buffer is full (avail_out == 0), or after each+ call of inflate(). If inflate returns Z_OK and with zero avail_out, it+ must be called again after making room in the output buffer because there+ might be more output pending.++ If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much+ output as possible to the output buffer. The flushing behavior of inflate is+ not specified for values of the flush parameter other than Z_SYNC_FLUSH+ and Z_FINISH, but the current implementation actually flushes as much output+ as possible anyway.++ inflate() should normally be called until it returns Z_STREAM_END or an+ error. However if all decompression is to be performed in a single step+ (a single call of inflate), the parameter flush should be set to+ Z_FINISH. In this case all pending input is processed and all pending+ output is flushed; avail_out must be large enough to hold all the+ uncompressed data. (The size of the uncompressed data may have been saved+ by the compressor for this purpose.) The next operation on this stream must+ be inflateEnd to deallocate the decompression state. The use of Z_FINISH+ is never required, but can be used to inform inflate that a faster routine+ may be used for the single inflate() call.++ If a preset dictionary is needed at this point (see inflateSetDictionary+ below), inflate sets strm-adler to the adler32 checksum of the+ dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise+ it sets strm->adler to the adler32 checksum of all output produced+ so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or+ an error code as described below. At the end of the stream, inflate()+ checks that its computed adler32 checksum is equal to that saved by the+ compressor and returns Z_STREAM_END only if the checksum is correct.++ inflate() returns Z_OK if some progress has been made (more input processed+ or more output produced), Z_STREAM_END if the end of the compressed data has+ been reached and all uncompressed output has been produced, Z_NEED_DICT if a+ preset dictionary is needed at this point, Z_DATA_ERROR if the input data was+ corrupted (input stream not conforming to the zlib format or incorrect+ adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent+ (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not+ enough memory, Z_BUF_ERROR if no progress is possible or if there was not+ enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR+ case, the application may then call inflateSync to look for a good+ compression block.+*/+++ZEXTERN(int) inflateEnd OF((z_streamp strm));+/*+ All dynamically allocated data structures for this stream are freed.+ This function discards any unprocessed input and does not flush any+ pending output.++ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state+ was inconsistent. In the error case, msg may be set but then points to a+ static string (which must not be deallocated).+*/++ /* Advanced functions */++/*+ The following functions are needed only in some special applications.+*/++/*+ZEXTERN(int) deflateInit2 OF((z_streamp strm,+ int level,+ int method,+ int windowBits,+ int memLevel,+ int strategy));++ This is another version of deflateInit with more compression options. The+ fields next_in, zalloc, zfree and opaque must be initialized before by+ the caller.++ The method parameter is the compression method. It must be Z_DEFLATED in+ this version of the library.++ The windowBits parameter is the base two logarithm of the window size+ (the size of the history buffer). It should be in the range 8..15 for this+ version of the library. Larger values of this parameter result in better+ compression at the expense of memory usage. The default value is 15 if+ deflateInit is used instead.++ The memLevel parameter specifies how much memory should be allocated+ for the internal compression state. memLevel=1 uses minimum memory but+ is slow and reduces compression ratio; memLevel=9 uses maximum memory+ for optimal speed. The default value is 8. See zconf.h for total memory+ usage as a function of windowBits and memLevel.++ The strategy parameter is used to tune the compression algorithm. Use the+ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a+ filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no+ string match). Filtered data consists mostly of small values with a+ somewhat random distribution. In this case, the compression algorithm is+ tuned to compress them better. The effect of Z_FILTERED is to force more+ Huffman coding and less string matching; it is somewhat intermediate+ between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects+ the compression ratio but not the correctness of the compressed output even+ if it is not set appropriately.++ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough+ memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid+ method). msg is set to null if there is no error message. deflateInit2 does+ not perform any compression: this will be done by deflate().+*/++/*+ Initializes the compression dictionary from the given byte sequence+ without producing any compressed output. This function must be called+ immediately after deflateInit, deflateInit2 or deflateReset, before any+ call of deflate. The compressor and decompressor must use exactly the same+ dictionary (see inflateSetDictionary).++ The dictionary should consist of strings (byte sequences) that are likely+ to be encountered later in the data to be compressed, with the most commonly+ used strings preferably put towards the end of the dictionary. Using a+ dictionary is most useful when the data to be compressed is short and can be+ predicted with good accuracy; the data can then be compressed better than+ with the default empty dictionary.++ Depending on the size of the compression data structures selected by+ deflateInit or deflateInit2, a part of the dictionary may in effect be+ discarded, for example if the dictionary is larger than the window size in+ deflate or deflate2. Thus the strings most likely to be useful should be+ put at the end of the dictionary, not at the front.++ Upon return of this function, strm->adler is set to the Adler32 value+ of the dictionary; the decompressor may later use this value to determine+ which dictionary has been used by the compressor. (The Adler32 value+ applies to the whole dictionary even if only a subset of the dictionary is+ actually used by the compressor.)++ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a+ parameter is invalid (such as NULL dictionary) or the stream state is+ inconsistent (for example if deflate has already been called for this stream+ or if the compression method is bsort). deflateSetDictionary does not+ perform any compression: this will be done by deflate().+*/++/*+ Sets the destination stream as a complete copy of the source stream.++ This function can be useful when several compression strategies will be+ tried, for example when there are several ways of pre-processing the input+ data with a filter. The streams that will be discarded should then be freed+ by calling deflateEnd. Note that deflateCopy duplicates the internal+ compression state which can be quite large, so this strategy is slow and+ can consume lots of memory.++ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent+ (such as zalloc being NULL). msg is left unchanged in both source and+ destination.+*/++/*+ This function is equivalent to deflateEnd followed by deflateInit,+ but does not free and reallocate all the internal compression state.+ The stream will keep the same compression level and any other attributes+ that may have been set by deflateInit2.++ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source+ stream state was inconsistent (such as zalloc or state being NULL).+*/++/*+ Dynamically update the compression level and compression strategy. The+ interpretation of level and strategy is as in deflateInit2. This can be+ used to switch between compression and straight copy of the input data, or+ to switch to a different kind of input data requiring a different+ strategy. If the compression level is changed, the input available so far+ is compressed with the old level (and may be flushed); the new level will+ take effect only at the next call of deflate().++ Before the call of deflateParams, the stream state must be set as for+ a call of deflate(), since the currently available input may have to+ be compressed and flushed. In particular, strm->avail_out must be non-zero.++ deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source+ stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR+ if strm->avail_out was zero.+*/++/*+ZEXTERN(int) inflateInit2 OF((z_streamp strm,+ int windowBits));++ This is another version of inflateInit with an extra parameter. The+ fields next_in, avail_in, zalloc, zfree and opaque must be initialized+ before by the caller.++ The windowBits parameter is the base two logarithm of the maximum window+ size (the size of the history buffer). It should be in the range 8..15 for+ this version of the library. The default value is 15 if inflateInit is used+ instead. If a compressed stream with a larger window size is given as+ input, inflate() will return with the error code Z_DATA_ERROR instead of+ trying to allocate a larger window.++ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough+ memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative+ memLevel). msg is set to null if there is no error message. inflateInit2+ does not perform any decompression apart from reading the zlib header if+ present: this will be done by inflate(). (So next_in and avail_in may be+ modified, but next_out and avail_out are unchanged.)+*/++/*+ Initializes the decompression dictionary from the given uncompressed byte+ sequence. This function must be called immediately after a call of inflate+ if this call returned Z_NEED_DICT. The dictionary chosen by the compressor+ can be determined from the Adler32 value returned by this call of+ inflate. The compressor and decompressor must use exactly the same+ dictionary (see deflateSetDictionary).++ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a+ parameter is invalid (such as NULL dictionary) or the stream state is+ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the+ expected one (incorrect Adler32 value). inflateSetDictionary does not+ perform any decompression: this will be done by subsequent calls of+ inflate().+*/++/*+ Skips invalid compressed data until a full flush point (see above the+ description of deflate with Z_FULL_FLUSH) can be found, or until all+ available input is skipped. No output is provided.++ inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR+ if no more input was provided, Z_DATA_ERROR if no flush point has been found,+ or Z_STREAM_ERROR if the stream structure was inconsistent. In the success+ case, the application may save the current current value of total_in which+ indicates where valid compressed data was found. In the error case, the+ application may repeatedly call inflateSync, providing more input each time,+ until success or end of the input data.+*/++ZEXTERN(int) inflateReset OF((z_streamp strm));+/*+ This function is equivalent to inflateEnd followed by inflateInit,+ but does not free and reallocate all the internal decompression state.+ The stream will keep attributes that may have been set by inflateInit2.++ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source+ stream state was inconsistent (such as zalloc or state being NULL).+*/+++ /* utility functions */++/*+ The following utility functions are implemented on top of the+ basic stream-oriented functions. To simplify the interface, some+ default options are assumed (compression level and memory usage,+ standard memory allocation functions). The source code of these+ utility functions can easily be modified if you need special options.+*/++/*+ Compresses the source buffer into the destination buffer. sourceLen is+ the byte length of the source buffer. Upon entry, destLen is the total+ size of the destination buffer, which must be at least 0.1% larger than+ sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the+ compressed buffer.+ This function can be used to compress a whole file at once if the+ input file is mmap'ed.+ compress returns Z_OK if success, Z_MEM_ERROR if there was not+ enough memory, Z_BUF_ERROR if there was not enough room in the output+ buffer.+*/++/*+ Compresses the source buffer into the destination buffer. The level+ parameter has the same meaning as in deflateInit. sourceLen is the byte+ length of the source buffer. Upon entry, destLen is the total size of the+ destination buffer, which must be at least 0.1% larger than sourceLen plus+ 12 bytes. Upon exit, destLen is the actual size of the compressed buffer.++ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,+ Z_STREAM_ERROR if the level parameter is invalid.+*/++/*+ Decompresses the source buffer into the destination buffer. sourceLen is+ the byte length of the source buffer. Upon entry, destLen is the total+ size of the destination buffer, which must be large enough to hold the+ entire uncompressed data. (The size of the uncompressed data must have+ been saved previously by the compressor and transmitted to the decompressor+ by some mechanism outside the scope of this compression library.)+ Upon exit, destLen is the actual size of the compressed buffer.+ This function can be used to decompress a whole file at once if the+ input file is mmap'ed.++ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not+ enough memory, Z_BUF_ERROR if there was not enough room in the output+ buffer, or Z_DATA_ERROR if the input data was corrupted.+*/+++/*+ Opens a gzip (.gz) file for reading or writing. The mode parameter+ is as in fopen ("rb" or "wb") but can also include a compression level+ ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for+ Huffman only compression as in "wb1h". (See the description+ of deflateInit2 for more information about the strategy parameter.)++ gzopen can be used to read a file which is not in gzip format; in this+ case gzread will directly read from the file without decompression.++ gzopen returns NULL if the file could not be opened or if there was+ insufficient memory to allocate the (de)compression state; errno+ can be checked to distinguish the two cases (if errno is zero, the+ zlib error is Z_MEM_ERROR). */++/*+ gzdopen() associates a gzFile with the file descriptor fd. File+ descriptors are obtained from calls like open, dup, creat, pipe or+ fileno (in the file has been previously opened with fopen).+ The mode parameter is as in gzopen.+ The next call of gzclose on the returned gzFile will also close the+ file descriptor fd, just like fclose(fdopen(fd), mode) closes the file+ descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).+ gzdopen returns NULL if there was insufficient memory to allocate+ the (de)compression state.+*/++/*+ Dynamically update the compression level or strategy. See the description+ of deflateInit2 for the meaning of these parameters.+ gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not+ opened for writing.+*/++/*+ Reads the given number of uncompressed bytes from the compressed file.+ If the input file was not in gzip format, gzread copies the given number+ of bytes into the buffer.+ gzread returns the number of uncompressed bytes actually read (0 for+ end of file, -1 for error). */++/*+ Writes the given number of uncompressed bytes into the compressed file.+ gzwrite returns the number of uncompressed bytes actually written+ (0 in case of error).+*/++/*+ Converts, formats, and writes the args to the compressed file under+ control of the format string, as in fprintf. gzprintf returns the number of+ uncompressed bytes actually written (0 in case of error).+*/++/*+ Writes the given null-terminated string to the compressed file, excluding+ the terminating null character.+ gzputs returns the number of characters written, or -1 in case of error.+*/++/*+ Reads bytes from the compressed file until len-1 characters are read, or+ a newline character is read and transferred to buf, or an end-of-file+ condition is encountered. The string is then terminated with a null+ character.+ gzgets returns buf, or Z_NULL in case of error.+*/++/*+ Writes c, converted to an unsigned char, into the compressed file.+ gzputc returns the value that was written, or -1 in case of error.+*/++/*+ Reads one byte from the compressed file. gzgetc returns this byte+ or -1 in case of end of file or error.+*/++/*+ Flushes all pending output into the compressed file. The parameter+ flush is as in the deflate() function. The return value is the zlib+ error number (see function gzerror below). gzflush returns Z_OK if+ the flush parameter is Z_FINISH and all output could be flushed.+ gzflush should be called only when strictly necessary because it can+ degrade compression.+*/++/*+ Sets the starting position for the next gzread or gzwrite on the+ given compressed file. The offset represents a number of bytes in the+ uncompressed data stream. The whence parameter is defined as in lseek(2);+ the value SEEK_END is not supported.+ If the file is opened for reading, this function is emulated but can be+ extremely slow. If the file is opened for writing, only forward seeks are+ supported; gzseek then compresses a sequence of zeroes up to the new+ starting position.++ gzseek returns the resulting offset location as measured in bytes from+ the beginning of the uncompressed stream, or -1 in case of error, in+ particular if the file is opened for writing and the new starting position+ would be before the current position.+*/++/*+ Rewinds the given file. This function is supported only for reading.++ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)+*/++/*+ Returns the starting position for the next gzread or gzwrite on the+ given compressed file. This position represents a number of bytes in the+ uncompressed data stream.++ gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)+*/++/*+ Returns 1 when EOF has previously been detected reading the given+ input stream, otherwise zero.+*/++/*+ Flushes all pending output if necessary, closes the compressed file+ and deallocates all the (de)compression state. The return value is the zlib+ error number (see function gzerror below).+*/++/*+ Returns the error message for the last error which occurred on the+ given compressed file. errnum is set to zlib error number. If an+ error occurred in the file system and not in the compression library,+ errnum is set to Z_ERRNO and the application may consult errno+ to get the exact error code.+*/++ /* checksum functions */++/*+ These functions are not related to compression but are exported+ anyway because they might be useful in applications using the+ compression library.+*/++ZEXTERN(uLong) adler32 OF((uLong adler, const Bytef *buf, uInt len));++/*+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and+ return the updated checksum. If buf is NULL, this function returns+ the required initial value for the checksum.+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed+ much faster. Usage example:++ uLong adler = adler32(0L, Z_NULL, 0);++ while (read_buffer(buffer, length) != EOF) {+ adler = adler32(adler, buffer, length);+ }+ if (adler != original_adler) error();+*/++/*+ Update a running crc with the bytes buf[0..len-1] and return the updated+ crc. If buf is NULL, this function returns the required initial value+ for the crc. Pre- and post-conditioning (one's complement) is performed+ within this function so it shouldn't be done by the application.+ Usage example:++ uLong crc = crc32(0L, Z_NULL, 0);++ while (read_buffer(buffer, length) != EOF) {+ crc = crc32(crc, buffer, length);+ }+ if (crc != original_crc) error();+*/+++ /* various hacks, don't look :) */++/* deflateInit and inflateInit are macros to allow checking the zlib version+ * and the compiler's view of z_stream:+ */+ZEXTERN(int) inflateInit2_ OF((z_streamp strm, int windowBits,+ const char *version, int stream_size));+#define deflateInit(strm, level) \+ deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))+#define inflateInit(strm) \+ inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\+ (strategy), ZLIB_VERSION, sizeof(z_stream))+#define inflateInit2(strm, windowBits) \+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))+++#ifdef __cplusplus+}+#endif++#endif /* _ZLIB_H */
+ src/gzip/zutil.c view
@@ -0,0 +1,181 @@+/* zutil.c -- target dependent utility functions for the compression library+ * Copyright (C) 1995-2002 Jean-loup Gailly.+ * For conditions of distribution and use, see copyright notice in zlib.h+ */++/* @(#) $Id$ */++#include "zutil.h"++#ifndef STDC+extern void exit OF((int));+#endif+++#ifndef HAVE_MEMCPY++void zmemcpy(dest, source, len)+ Bytef* dest;+ const Bytef* source;+ uInt len;+{+ if (len == 0) return;+ do {+ *dest++ = *source++; /* ??? to be unrolled */+ } while (--len != 0);+}++int zmemcmp(s1, s2, len)+ const Bytef* s1;+ const Bytef* s2;+ uInt len;+{+ uInt j;++ for (j = 0; j < len; j++) {+ if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;+ }+ return 0;+}++void zmemzero(dest, len)+ Bytef* dest;+ uInt len;+{+ if (len == 0) return;+ do {+ *dest++ = 0; /* ??? to be unrolled */+ } while (--len != 0);+}+#endif++#if defined( MSDOS ) && defined( __TURBOC__ ) && !defined( MY_ZCALLOC )+#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__)+/* Small and medium model in Turbo C are for now limited to near allocation+ * with reduced MAX_WBITS and MAX_MEM_LEVEL+ */+# define MY_ZCALLOC++/* Turbo C malloc() does not allow dynamic allocation of 64K bytes+ * and farmalloc(64K) returns a pointer with an offset of 8, so we+ * must fix the pointer. Warning: the pointer must be put back to its+ * original form in order to free it, use zcfree().+ */++#define MAX_PTR 10+/* 10*64K = 640K */++local int next_ptr = 0;++typedef struct ptr_table_s {+ voidpf org_ptr;+ voidpf new_ptr;+} ptr_table;++local ptr_table table[MAX_PTR];+/* This table is used to remember the original form of pointers+ * to large buffers (64K). Such pointers are normalized with a zero offset.+ * Since MSDOS is not a preemptive multitasking OS, this table is not+ * protected from concurrent access. This hack doesn't work anyway on+ * a protected system like OS/2. Use Microsoft C instead.+ */++voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)+{+ voidpf buf = opaque; /* just to make some compilers happy */+ ulg bsize = (ulg)items*size;++ /* If we allocate less than 65520 bytes, we assume that farmalloc+ * will return a usable pointer which doesn't have to be normalized.+ */+ if (bsize < 65520L) {+ buf = farmalloc(bsize);+ if (*(ush*)&buf != 0) return buf;+ } else {+ buf = farmalloc(bsize + 16L);+ }+ if (buf == NULL || next_ptr >= MAX_PTR) return NULL;+ table[next_ptr].org_ptr = buf;++ /* Normalize the pointer to seg:0 */+ *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;+ *(ush*)&buf = 0;+ table[next_ptr++].new_ptr = buf;+ return buf;+}++void zcfree (voidpf opaque, voidpf ptr)+{+ int n;+ if (*(ush*)&ptr != 0) { /* object < 64K */+ farfree(ptr);+ return;+ }+ /* Find the original pointer */+ for (n = 0; n < next_ptr; n++) {+ if (ptr != table[n].new_ptr) continue;++ farfree(table[n].org_ptr);+ while (++n < next_ptr) {+ table[n-1] = table[n];+ }+ next_ptr--;+ return;+ }+ ptr = opaque; /* just to make some compilers happy */+ Assert(0, "zcfree: ptr not found");+}+#endif+#endif /* MSDOS && __TURBOC__ */+++#if defined(M_I86) && !defined(__32BIT__) && !defined( MY_ZCALLOC )+/* Microsoft C in 16-bit mode */++# define MY_ZCALLOC++#if (!defined(_MSC_VER) || (_MSC_VER <= 600))+# define _halloc halloc+# define _hfree hfree+#endif++voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)+{+ if (opaque) opaque = 0; /* to make compiler happy */+ return _halloc((long)items, size);+}++void zcfree (voidpf opaque, voidpf ptr)+{+ if (opaque) opaque = 0; /* to make compiler happy */+ _hfree(ptr);+}++#endif /* MSC */+++#ifndef MY_ZCALLOC /* Any system without a special alloc function */++#ifndef STDC+extern voidp ft_scalloc OF((uInt items, uInt size));+extern void ft_sfree OF((voidpf ptr));+#endif++voidpf zcalloc (opaque, items, size)+ voidpf opaque;+ unsigned items;+ unsigned size;+{+ if (opaque) items += size - size; /* make compiler happy */+ return (voidpf)ft_scalloc(items, size);+}++void zcfree (opaque, ptr)+ voidpf opaque;+ voidpf ptr;+{+ ft_sfree(ptr);+ if (opaque) return; /* make compiler happy */+}++#endif /* MY_ZCALLOC */
+ src/gzip/zutil.h view
@@ -0,0 +1,215 @@+/* zutil.h -- internal interface and configuration of the compression library+ * Copyright (C) 1995-2002 Jean-loup Gailly.+ * For conditions of distribution and use, see copyright notice in zlib.h+ */++/* WARNING: this file should *not* be used by applications. It is+ part of the implementation of the compression library and is+ subject to change. Applications should only use zlib.h.+ */++/* @(#) $Id$ */++#ifndef _Z_UTIL_H+#define _Z_UTIL_H++#include "zlib.h"++#ifdef STDC+# include <stddef.h>+# include <string.h>+# include <stdlib.h>+#endif+#ifdef NO_ERRNO_H+ extern int errno;+#else+# include <errno.h>+#endif++#ifndef local+# define local static+#endif+/* compile with -Dlocal if your debugger can't find static symbols */++typedef unsigned char uch;+typedef uch FAR uchf;+typedef unsigned short ush;+typedef ush FAR ushf;+typedef unsigned long ulg;+++#define ERR_RETURN(strm,err) \+ return (strm->msg = (char*)ERR_MSG(err), (err))+/* To be used only when the state is known to be valid */++ /* common constants */++#ifndef DEF_WBITS+# define DEF_WBITS MAX_WBITS+#endif+/* default windowBits for decompression. MAX_WBITS is for compression only */++#if MAX_MEM_LEVEL >= 8+# define DEF_MEM_LEVEL 8+#else+# define DEF_MEM_LEVEL MAX_MEM_LEVEL+#endif+/* default memLevel */++#define STORED_BLOCK 0+#define STATIC_TREES 1+#define DYN_TREES 2+/* The three kinds of block type */++#define MIN_MATCH 3+#define MAX_MATCH 258+/* The minimum and maximum match lengths */++#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */++ /* target dependencies */++#ifdef MSDOS+# define OS_CODE 0x00+# if defined(__TURBOC__) || defined(__BORLANDC__)+# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))+ /* Allow compilation with ANSI keywords only enabled */+ void _Cdecl farfree( void *block );+ void *_Cdecl farmalloc( unsigned long nbytes );+# else+# include <alloc.h>+# endif+# else /* MSC or DJGPP */+# endif+#endif++#ifdef OS2+# define OS_CODE 0x06+#endif++#ifdef WIN32 /* Window 95 & Windows NT */+# define OS_CODE 0x0b+#endif++#if defined(VAXC) || defined(VMS)+# define OS_CODE 0x02+# define F_OPEN(name, mode) \+ ft_fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")+#endif++#ifdef AMIGA+# define OS_CODE 0x01+#endif++#if defined(ATARI) || defined(atarist)+# define OS_CODE 0x05+#endif++#if defined(MACOS) || defined(TARGET_OS_MAC)+# define OS_CODE 0x07+# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os+# include <unix.h> /* for fdopen */+# else+# ifndef fdopen+# define fdopen(fd,mode) NULL /* No fdopen() */+# endif+# endif+#endif++#ifdef __50SERIES /* Prime/PRIMOS */+# define OS_CODE 0x0F+#endif++#ifdef TOPS20+# define OS_CODE 0x0a+#endif++#if defined(_BEOS_) || defined(RISCOS)+# define fdopen(fd,mode) NULL /* No fdopen() */+#endif++#if (defined(_MSC_VER) && (_MSC_VER > 600))+# define fdopen(fd,type) _fdopen(fd,type)+#endif+++ /* Common defaults */++#ifndef OS_CODE+# define OS_CODE 0x03 /* assume Unix */+#endif++#ifndef F_OPEN+# define F_OPEN(name, mode) ft_fopen((name), (mode))+#endif++ /* functions */++#ifdef HAVE_STRERROR+ extern char *strerror OF((int));+# define zstrerror(errnum) strerror(errnum)+#else+# define zstrerror(errnum) ""+#endif++#if defined(pyr)+# define NO_MEMCPY+#endif+#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)+ /* Use our own functions for small and medium model with MSC <= 5.0.+ * You may have to use the same strategy for Borland C (untested).+ * The __SC__ check is for Symantec.+ */+# define NO_MEMCPY+#endif+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)+# define HAVE_MEMCPY+#endif+#ifdef HAVE_MEMCPY+# ifdef SMALL_MEDIUM /* MSDOS small or medium model */+# define zmemcpy _fmemcpy+# define zmemcmp _fmemcmp+# define zmemzero(dest, len) _fmemset(dest, 0, len)+# else+# define zmemcpy ft_memcpy+# define zmemcmp ft_memcmp+# define zmemzero(dest, len) ft_memset(dest, 0, len)+# endif+#else+ extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));+ extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));+ extern void zmemzero OF((Bytef* dest, uInt len));+#endif++/* Diagnostic functions */+#ifdef DEBUG+# include <stdio.h>+ extern int z_verbose;+ extern void z_error OF((char *m));+# define Assert(cond,msg) {if(!(cond)) z_error(msg);}+# define Trace(x) {if (z_verbose>=0) fprintf x ;}+# define Tracev(x) {if (z_verbose>0) fprintf x ;}+# define Tracevv(x) {if (z_verbose>1) fprintf x ;}+# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}+# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}+#else+# define Assert(cond,msg)+# define Trace(x)+# define Tracev(x)+# define Tracevv(x)+# define Tracec(c,x)+# define Tracecv(c,x)+#endif+++typedef uLong (*check_func) OF((uLong check, const Bytef *buf,+ uInt len));+local voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));+local void zcfree OF((voidpf opaque, voidpf ptr));++#define ZALLOC(strm, items, size) \+ (*((strm)->zalloc))((strm)->opaque, (items), (size))+#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}++#endif /* _Z_UTIL_H */
+ src/lzw/ftlzw.c view
@@ -0,0 +1,412 @@+/***************************************************************************/+/* */+/* ftlzw.c */+/* */+/* FreeType support for .Z compressed files. */+/* */+/* This optional component relies on NetBSD's zopen(). It should mainly */+/* be used to parse compressed PCF fonts, as found with many X11 server */+/* distributions. */+/* */+/* Copyright 2004, 2005, 2006, 2009, 2010 by */+/* Albert Chin-A-Young. */+/* */+/* Based on code in src/gzip/ftgzip.c, Copyright 2004 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_MEMORY_H+#include FT_INTERNAL_STREAM_H+#include FT_INTERNAL_DEBUG_H+#include FT_LZW_H+#include FT_CONFIG_STANDARD_LIBRARY_H+++#include FT_MODULE_ERRORS_H++#undef __FTERRORS_H__++#define FT_ERR_PREFIX LZW_Err_+#define FT_ERR_BASE FT_Mod_Err_LZW++#include FT_ERRORS_H+++#ifdef FT_CONFIG_OPTION_USE_LZW++#ifdef FT_CONFIG_OPTION_PIC+#error "lzw code does not support PIC yet"+#endif ++#include "ftzopen.h"+++/***************************************************************************/+/***************************************************************************/+/***** *****/+/***** M E M O R Y M A N A G E M E N T *****/+/***** *****/+/***************************************************************************/+/***************************************************************************/++/***************************************************************************/+/***************************************************************************/+/***** *****/+/***** F I L E D E S C R I P T O R *****/+/***** *****/+/***************************************************************************/+/***************************************************************************/++#define FT_LZW_BUFFER_SIZE 4096++ typedef struct FT_LZWFileRec_+ {+ FT_Stream source; /* parent/source stream */+ FT_Stream stream; /* embedding stream */+ FT_Memory memory; /* memory allocator */+ FT_LzwStateRec lzw; /* lzw decompressor state */++ FT_Byte buffer[FT_LZW_BUFFER_SIZE]; /* output buffer */+ FT_ULong pos; /* position in output */+ FT_Byte* cursor;+ FT_Byte* limit;++ } FT_LZWFileRec, *FT_LZWFile;+++ /* check and skip .Z header */+ static FT_Error+ ft_lzw_check_header( FT_Stream stream )+ {+ FT_Error error;+ FT_Byte head[2];+++ if ( FT_STREAM_SEEK( 0 ) ||+ FT_STREAM_READ( head, 2 ) )+ goto Exit;++ /* head[0] && head[1] are the magic numbers */+ if ( head[0] != 0x1f ||+ head[1] != 0x9d )+ error = LZW_Err_Invalid_File_Format;++ Exit:+ return error;+ }+++ static FT_Error+ ft_lzw_file_init( FT_LZWFile zip,+ FT_Stream stream,+ FT_Stream source )+ {+ FT_LzwState lzw = &zip->lzw;+ FT_Error error = LZW_Err_Ok;+++ zip->stream = stream;+ zip->source = source;+ zip->memory = stream->memory;++ zip->limit = zip->buffer + FT_LZW_BUFFER_SIZE;+ zip->cursor = zip->limit;+ zip->pos = 0;++ /* check and skip .Z header */+ error = ft_lzw_check_header( source );+ if ( error )+ goto Exit;++ /* initialize internal lzw variable */+ ft_lzwstate_init( lzw, source );++ Exit:+ return error;+ }+++ static void+ ft_lzw_file_done( FT_LZWFile zip )+ {+ /* clear the rest */+ ft_lzwstate_done( &zip->lzw );++ zip->memory = NULL;+ zip->source = NULL;+ zip->stream = NULL;+ }+++ static FT_Error+ ft_lzw_file_reset( FT_LZWFile zip )+ {+ FT_Stream stream = zip->source;+ FT_Error error;+++ if ( !FT_STREAM_SEEK( 0 ) )+ {+ ft_lzwstate_reset( &zip->lzw );++ zip->limit = zip->buffer + FT_LZW_BUFFER_SIZE;+ zip->cursor = zip->limit;+ zip->pos = 0;+ }++ return error;+ }+++ static FT_Error+ ft_lzw_file_fill_output( FT_LZWFile zip )+ {+ FT_LzwState lzw = &zip->lzw;+ FT_ULong count;+ FT_Error error = LZW_Err_Ok;+++ zip->cursor = zip->buffer;++ count = ft_lzwstate_io( lzw, zip->buffer, FT_LZW_BUFFER_SIZE );++ zip->limit = zip->cursor + count;++ if ( count == 0 )+ error = LZW_Err_Invalid_Stream_Operation;++ return error;+ }+++ /* fill output buffer; `count' must be <= FT_LZW_BUFFER_SIZE */+ static FT_Error+ ft_lzw_file_skip_output( FT_LZWFile zip,+ FT_ULong count )+ {+ FT_Error error = LZW_Err_Ok;+++ /* first, we skip what we can from the output buffer */+ {+ FT_ULong delta = (FT_ULong)( zip->limit - zip->cursor );+++ if ( delta >= count )+ delta = count;++ zip->cursor += delta;+ zip->pos += delta;++ count -= delta;+ }++ /* next, we skip as many bytes remaining as possible */+ while ( count > 0 )+ {+ FT_ULong delta = FT_LZW_BUFFER_SIZE;+ FT_ULong numread;+++ if ( delta > count )+ delta = count;++ numread = ft_lzwstate_io( &zip->lzw, NULL, delta );+ if ( numread < delta )+ {+ /* not enough bytes */+ error = LZW_Err_Invalid_Stream_Operation;+ break;+ }++ zip->pos += delta;+ count -= delta;+ }++ return error;+ }+++ static FT_ULong+ ft_lzw_file_io( FT_LZWFile zip,+ FT_ULong pos,+ FT_Byte* buffer,+ FT_ULong count )+ {+ FT_ULong result = 0;+ FT_Error error;+++ /* seeking backwards. */+ if ( pos < zip->pos )+ {+ /* If the new position is within the output buffer, simply */+ /* decrement pointers, otherwise we reset the stream completely! */+ if ( ( zip->pos - pos ) <= (FT_ULong)( zip->cursor - zip->buffer ) )+ {+ zip->cursor -= zip->pos - pos;+ zip->pos = pos;+ }+ else+ {+ error = ft_lzw_file_reset( zip );+ if ( error )+ goto Exit;+ }+ }++ /* skip unwanted bytes */+ if ( pos > zip->pos )+ {+ error = ft_lzw_file_skip_output( zip, (FT_ULong)( pos - zip->pos ) );+ if ( error )+ goto Exit;+ }++ if ( count == 0 )+ goto Exit;++ /* now read the data */+ for (;;)+ {+ FT_ULong delta;+++ delta = (FT_ULong)( zip->limit - zip->cursor );+ if ( delta >= count )+ delta = count;++ FT_MEM_COPY( buffer + result, zip->cursor, delta );+ result += delta;+ zip->cursor += delta;+ zip->pos += delta;++ count -= delta;+ if ( count == 0 )+ break;++ error = ft_lzw_file_fill_output( zip );+ if ( error )+ break;+ }++ Exit:+ return result;+ }+++/***************************************************************************/+/***************************************************************************/+/***** *****/+/***** L Z W E M B E D D I N G S T R E A M *****/+/***** *****/+/***************************************************************************/+/***************************************************************************/++ static void+ ft_lzw_stream_close( FT_Stream stream )+ {+ FT_LZWFile zip = (FT_LZWFile)stream->descriptor.pointer;+ FT_Memory memory = stream->memory;+++ if ( zip )+ {+ /* finalize lzw file descriptor */+ ft_lzw_file_done( zip );++ FT_FREE( zip );++ stream->descriptor.pointer = NULL;+ }+ }+++ static FT_ULong+ ft_lzw_stream_io( FT_Stream stream,+ FT_ULong pos,+ FT_Byte* buffer,+ FT_ULong count )+ {+ FT_LZWFile zip = (FT_LZWFile)stream->descriptor.pointer;+++ return ft_lzw_file_io( zip, pos, buffer, count );+ }+++ FT_EXPORT_DEF( FT_Error )+ FT_Stream_OpenLZW( FT_Stream stream,+ FT_Stream source )+ {+ FT_Error error;+ FT_Memory memory = source->memory;+ FT_LZWFile zip;+++ /*+ * Check the header right now; this prevents allocation of a huge+ * LZWFile object (400 KByte of heap memory) if not necessary.+ *+ * Did I mention that you should never use .Z compressed font+ * files?+ */+ error = ft_lzw_check_header( source );+ if ( error )+ goto Exit;++ FT_ZERO( stream );+ stream->memory = memory;++ if ( !FT_NEW( zip ) )+ {+ error = ft_lzw_file_init( zip, stream, source );+ if ( error )+ {+ FT_FREE( zip );+ goto Exit;+ }++ stream->descriptor.pointer = zip;+ }++ stream->size = 0x7FFFFFFFL; /* don't know the real size! */+ stream->pos = 0;+ stream->base = 0;+ stream->read = ft_lzw_stream_io;+ stream->close = ft_lzw_stream_close;++ Exit:+ return error;+ }+++#include "ftzopen.c"+++#else /* !FT_CONFIG_OPTION_USE_LZW */+++ FT_EXPORT_DEF( FT_Error )+ FT_Stream_OpenLZW( FT_Stream stream,+ FT_Stream source )+ {+ FT_UNUSED( stream );+ FT_UNUSED( source );++ return LZW_Err_Unimplemented_Feature;+ }+++#endif /* !FT_CONFIG_OPTION_USE_LZW */+++/* END */
+ src/lzw/ftzopen.c view
@@ -0,0 +1,401 @@+/***************************************************************************/+/* */+/* ftzopen.c */+/* */+/* FreeType support for .Z compressed files. */+/* */+/* This optional component relies on NetBSD's zopen(). It should mainly */+/* be used to parse compressed PCF fonts, as found with many X11 server */+/* distributions. */+/* */+/* Copyright 2005, 2006, 2007, 2009 by David Turner. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/++#include "ftzopen.h"+#include FT_INTERNAL_MEMORY_H+#include FT_INTERNAL_STREAM_H+#include FT_INTERNAL_DEBUG_H+++ static int+ ft_lzwstate_refill( FT_LzwState state )+ {+ FT_ULong count;+++ if ( state->in_eof )+ return -1;++ count = FT_Stream_TryRead( state->source,+ state->buf_tab,+ state->num_bits ); /* WHY? */++ state->buf_size = (FT_UInt)count;+ state->buf_total += count;+ state->in_eof = FT_BOOL( count < state->num_bits );+ state->buf_offset = 0;+ state->buf_size = ( state->buf_size << 3 ) - ( state->num_bits - 1 );++ if ( count == 0 ) /* end of file */+ return -1;++ return 0;+ }+++ static FT_Int32+ ft_lzwstate_get_code( FT_LzwState state )+ {+ FT_UInt num_bits = state->num_bits;+ FT_Int offset = state->buf_offset;+ FT_Byte* p;+ FT_Int result;+++ if ( state->buf_clear ||+ offset >= state->buf_size ||+ state->free_ent >= state->free_bits )+ {+ if ( state->free_ent >= state->free_bits )+ {+ state->num_bits = ++num_bits;+ state->free_bits = state->num_bits < state->max_bits+ ? (FT_UInt)( ( 1UL << num_bits ) - 256 )+ : state->max_free + 1;+ }++ if ( state->buf_clear )+ {+ state->num_bits = num_bits = LZW_INIT_BITS;+ state->free_bits = (FT_UInt)( ( 1UL << num_bits ) - 256 );+ state->buf_clear = 0;+ }++ if ( ft_lzwstate_refill( state ) < 0 )+ return -1;++ offset = 0;+ }++ state->buf_offset = offset + num_bits;++ p = &state->buf_tab[offset >> 3];+ offset &= 7;+ result = *p++ >> offset;+ offset = 8 - offset;+ num_bits -= offset;++ if ( num_bits >= 8 )+ {+ result |= *p++ << offset;+ offset += 8;+ num_bits -= 8;+ }+ if ( num_bits > 0 )+ result |= ( *p & LZW_MASK( num_bits ) ) << offset;++ return result;+ }+++ /* grow the character stack */+ static int+ ft_lzwstate_stack_grow( FT_LzwState state )+ {+ if ( state->stack_top >= state->stack_size )+ {+ FT_Memory memory = state->memory;+ FT_Error error;+ FT_Offset old_size = state->stack_size;+ FT_Offset new_size = old_size;++ new_size = new_size + ( new_size >> 1 ) + 4;++ if ( state->stack == state->stack_0 )+ {+ state->stack = NULL;+ old_size = 0;+ }++ if ( FT_RENEW_ARRAY( state->stack, old_size, new_size ) )+ return -1;++ state->stack_size = new_size;+ }+ return 0;+ }+++ /* grow the prefix/suffix arrays */+ static int+ ft_lzwstate_prefix_grow( FT_LzwState state )+ {+ FT_UInt old_size = state->prefix_size;+ FT_UInt new_size = old_size;+ FT_Memory memory = state->memory;+ FT_Error error;+++ if ( new_size == 0 ) /* first allocation -> 9 bits */+ new_size = 512;+ else+ new_size += new_size >> 2; /* don't grow too fast */++ /*+ * Note that the `suffix' array is located in the same memory block+ * pointed to by `prefix'.+ *+ * I know that sizeof(FT_Byte) == 1 by definition, but it is clearer+ * to write it literally.+ *+ */+ if ( FT_REALLOC_MULT( state->prefix, old_size, new_size,+ sizeof ( FT_UShort ) + sizeof ( FT_Byte ) ) )+ return -1;++ /* now adjust `suffix' and move the data accordingly */+ state->suffix = (FT_Byte*)( state->prefix + new_size );++ FT_MEM_MOVE( state->suffix,+ state->prefix + old_size,+ old_size * sizeof ( FT_Byte ) );++ state->prefix_size = new_size;+ return 0;+ }+++ FT_LOCAL_DEF( void )+ ft_lzwstate_reset( FT_LzwState state )+ {+ state->in_eof = 0;+ state->buf_offset = 0;+ state->buf_size = 0;+ state->buf_clear = 0;+ state->buf_total = 0;+ state->stack_top = 0;+ state->num_bits = LZW_INIT_BITS;+ state->phase = FT_LZW_PHASE_START;+ }+++ FT_LOCAL_DEF( void )+ ft_lzwstate_init( FT_LzwState state,+ FT_Stream source )+ {+ FT_ZERO( state );++ state->source = source;+ state->memory = source->memory;++ state->prefix = NULL;+ state->suffix = NULL;+ state->prefix_size = 0;++ state->stack = state->stack_0;+ state->stack_size = sizeof ( state->stack_0 );++ ft_lzwstate_reset( state );+ }+++ FT_LOCAL_DEF( void )+ ft_lzwstate_done( FT_LzwState state )+ {+ FT_Memory memory = state->memory;+++ ft_lzwstate_reset( state );++ if ( state->stack != state->stack_0 )+ FT_FREE( state->stack );++ FT_FREE( state->prefix );+ state->suffix = NULL;++ FT_ZERO( state );+ }+++#define FTLZW_STACK_PUSH( c ) \+ FT_BEGIN_STMNT \+ if ( state->stack_top >= state->stack_size && \+ ft_lzwstate_stack_grow( state ) < 0 ) \+ goto Eof; \+ \+ state->stack[state->stack_top++] = (FT_Byte)(c); \+ FT_END_STMNT+++ FT_LOCAL_DEF( FT_ULong )+ ft_lzwstate_io( FT_LzwState state,+ FT_Byte* buffer,+ FT_ULong out_size )+ {+ FT_ULong result = 0;++ FT_UInt old_char = state->old_char;+ FT_UInt old_code = state->old_code;+ FT_UInt in_code = state->in_code;+++ if ( out_size == 0 )+ goto Exit;++ switch ( state->phase )+ {+ case FT_LZW_PHASE_START:+ {+ FT_Byte max_bits;+ FT_Int32 c;+++ /* skip magic bytes, and read max_bits + block_flag */+ if ( FT_Stream_Seek( state->source, 2 ) != 0 ||+ FT_Stream_TryRead( state->source, &max_bits, 1 ) != 1 )+ goto Eof;++ state->max_bits = max_bits & LZW_BIT_MASK;+ state->block_mode = max_bits & LZW_BLOCK_MASK;+ state->max_free = (FT_UInt)( ( 1UL << state->max_bits ) - 256 );++ if ( state->max_bits > LZW_MAX_BITS )+ goto Eof;++ state->num_bits = LZW_INIT_BITS;+ state->free_ent = ( state->block_mode ? LZW_FIRST+ : LZW_CLEAR ) - 256;+ in_code = 0;++ state->free_bits = state->num_bits < state->max_bits+ ? (FT_UInt)( ( 1UL << state->num_bits ) - 256 )+ : state->max_free + 1;++ c = ft_lzwstate_get_code( state );+ if ( c < 0 )+ goto Eof;++ old_code = old_char = (FT_UInt)c;++ if ( buffer )+ buffer[result] = (FT_Byte)old_char;++ if ( ++result >= out_size )+ goto Exit;++ state->phase = FT_LZW_PHASE_CODE;+ }+ /* fall-through */++ case FT_LZW_PHASE_CODE:+ {+ FT_Int32 c;+ FT_UInt code;+++ NextCode:+ c = ft_lzwstate_get_code( state );+ if ( c < 0 )+ goto Eof;++ code = (FT_UInt)c;++ if ( code == LZW_CLEAR && state->block_mode )+ {+ /* why not LZW_FIRST-256 ? */+ state->free_ent = ( LZW_FIRST - 1 ) - 256;+ state->buf_clear = 1;+ c = ft_lzwstate_get_code( state );+ if ( c < 0 )+ goto Eof;++ code = (FT_UInt)c;+ }++ in_code = code; /* save code for later */++ if ( code >= 256U )+ {+ /* special case for KwKwKwK */+ if ( code - 256U >= state->free_ent )+ {+ FTLZW_STACK_PUSH( old_char );+ code = old_code;+ }++ while ( code >= 256U )+ {+ if ( !state->prefix )+ goto Eof;++ FTLZW_STACK_PUSH( state->suffix[code - 256] );+ code = state->prefix[code - 256];+ }+ }++ old_char = code;+ FTLZW_STACK_PUSH( old_char );++ state->phase = FT_LZW_PHASE_STACK;+ }+ /* fall-through */++ case FT_LZW_PHASE_STACK:+ {+ while ( state->stack_top > 0 )+ {+ --state->stack_top;++ if ( buffer )+ buffer[result] = state->stack[state->stack_top];++ if ( ++result == out_size )+ goto Exit;+ }++ /* now create new entry */+ if ( state->free_ent < state->max_free )+ {+ if ( state->free_ent >= state->prefix_size &&+ ft_lzwstate_prefix_grow( state ) < 0 )+ goto Eof;++ FT_ASSERT( state->free_ent < state->prefix_size );++ state->prefix[state->free_ent] = (FT_UShort)old_code;+ state->suffix[state->free_ent] = (FT_Byte) old_char;++ state->free_ent += 1;+ }++ old_code = in_code;++ state->phase = FT_LZW_PHASE_CODE;+ goto NextCode;+ }++ default: /* state == EOF */+ ;+ }++ Exit:+ state->old_code = old_code;+ state->old_char = old_char;+ state->in_code = in_code;++ return result;++ Eof:+ state->phase = FT_LZW_PHASE_EOF;+ goto Exit;+ }+++/* END */
+ src/lzw/ftzopen.h view
@@ -0,0 +1,171 @@+/***************************************************************************/+/* */+/* ftzopen.h */+/* */+/* FreeType support for .Z compressed files. */+/* */+/* This optional component relies on NetBSD's zopen(). It should mainly */+/* be used to parse compressed PCF fonts, as found with many X11 server */+/* distributions. */+/* */+/* Copyright 2005, 2006, 2007, 2008 by David Turner. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/++#ifndef __FT_ZOPEN_H__+#define __FT_ZOPEN_H__++#include <ft2build.h>+#include FT_FREETYPE_H+++ /*+ * This is a complete re-implementation of the LZW file reader,+ * since the old one was incredibly badly written, using+ * 400 KByte of heap memory before decompressing anything.+ *+ */++#define FT_LZW_IN_BUFF_SIZE 64+#define FT_LZW_DEFAULT_STACK_SIZE 64++#define LZW_INIT_BITS 9+#define LZW_MAX_BITS 16++#define LZW_CLEAR 256+#define LZW_FIRST 257++#define LZW_BIT_MASK 0x1f+#define LZW_BLOCK_MASK 0x80+#define LZW_MASK( n ) ( ( 1U << (n) ) - 1U )+++ typedef enum FT_LzwPhase_+ {+ FT_LZW_PHASE_START = 0,+ FT_LZW_PHASE_CODE,+ FT_LZW_PHASE_STACK,+ FT_LZW_PHASE_EOF++ } FT_LzwPhase;+++ /*+ * state of LZW decompressor+ *+ * small technical note+ * --------------------+ *+ * We use a few tricks in this implementation that are explained here to+ * ease debugging and maintenance.+ *+ * - First of all, the `prefix' and `suffix' arrays contain the suffix+ * and prefix for codes over 256; this means that+ *+ * prefix_of(code) == state->prefix[code-256]+ * suffix_of(code) == state->suffix[code-256]+ *+ * Each prefix is a 16-bit code, and each suffix an 8-bit byte.+ *+ * Both arrays are stored in a single memory block, pointed to by+ * `state->prefix'. This means that the following equality is always+ * true:+ *+ * state->suffix == (FT_Byte*)(state->prefix + state->prefix_size)+ *+ * Of course, state->prefix_size is the number of prefix/suffix slots+ * in the arrays, corresponding to codes 256..255+prefix_size.+ *+ * - `free_ent' is the index of the next free entry in the `prefix'+ * and `suffix' arrays. This means that the corresponding `next free+ * code' is really `256+free_ent'.+ *+ * Moreover, `max_free' is the maximum value that `free_ent' can reach.+ *+ * `max_free' corresponds to `(1 << max_bits) - 256'. Note that this+ * value is always <= 0xFF00, which means that both `free_ent' and+ * `max_free' can be stored in an FT_UInt variable, even on 16-bit+ * machines.+ *+ * If `free_ent == max_free', you cannot add new codes to the+ * prefix/suffix table.+ *+ * - `num_bits' is the current number of code bits, starting at 9 and+ * growing each time `free_ent' reaches the value of `free_bits'. The+ * latter is computed as follows+ *+ * if num_bits < max_bits:+ * free_bits = (1 << num_bits)-256+ * else:+ * free_bits = max_free + 1+ *+ * Since the value of `max_free + 1' can never be reached by+ * `free_ent', `num_bits' cannot grow larger than `max_bits'.+ */++ typedef struct FT_LzwStateRec_+ {+ FT_LzwPhase phase;+ FT_Int in_eof;++ FT_Byte buf_tab[16];+ FT_Int buf_offset;+ FT_Int buf_size;+ FT_Bool buf_clear;+ FT_Offset buf_total;++ FT_UInt max_bits; /* max code bits, from file header */+ FT_Int block_mode; /* block mode flag, from file header */+ FT_UInt max_free; /* (1 << max_bits) - 256 */++ FT_UInt num_bits; /* current code bit number */+ FT_UInt free_ent; /* index of next free entry */+ FT_UInt free_bits; /* if reached by free_ent, increment num_bits */+ FT_UInt old_code;+ FT_UInt old_char;+ FT_UInt in_code;++ FT_UShort* prefix; /* always dynamically allocated / reallocated */+ FT_Byte* suffix; /* suffix = (FT_Byte*)(prefix + prefix_size) */+ FT_UInt prefix_size; /* number of slots in `prefix' or `suffix' */++ FT_Byte* stack; /* character stack */+ FT_UInt stack_top;+ FT_Offset stack_size;+ FT_Byte stack_0[FT_LZW_DEFAULT_STACK_SIZE]; /* minimize heap alloc */++ FT_Stream source; /* source stream */+ FT_Memory memory;++ } FT_LzwStateRec, *FT_LzwState;+++ FT_LOCAL( void )+ ft_lzwstate_init( FT_LzwState state,+ FT_Stream source );++ FT_LOCAL( void )+ ft_lzwstate_done( FT_LzwState state );+++ FT_LOCAL( void )+ ft_lzwstate_reset( FT_LzwState state );+++ FT_LOCAL( FT_ULong )+ ft_lzwstate_io( FT_LzwState state,+ FT_Byte* buffer,+ FT_ULong out_size );++/* */++#endif /* __FT_ZOPEN_H__ */+++/* END */
+ src/pcf/pcf.c view
@@ -0,0 +1,36 @@+/* pcf.c++ FreeType font driver for pcf fonts++ Copyright 2000-2001, 2003 by+ Francesco Zappa Nardelli++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in+all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+THE SOFTWARE.+*/+++#define FT_MAKE_OPTION_SINGLE_OBJECT+++#include <ft2build.h>+#include "pcfutil.c"+#include "pcfread.c"+#include "pcfdrivr.c"++/* END */
+ src/pcf/pcf.h view
@@ -0,0 +1,237 @@+/* pcf.h++ FreeType font driver for pcf fonts++ Copyright (C) 2000, 2001, 2002, 2003, 2006 by+ Francesco Zappa Nardelli++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in+all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+THE SOFTWARE.+*/+++#ifndef __PCF_H__+#define __PCF_H__+++#include <ft2build.h>+#include FT_INTERNAL_DRIVER_H+#include FT_INTERNAL_STREAM_H+++FT_BEGIN_HEADER++ typedef struct PCF_TableRec_+ {+ FT_ULong type;+ FT_ULong format;+ FT_ULong size;+ FT_ULong offset;++ } PCF_TableRec, *PCF_Table;+++ typedef struct PCF_TocRec_+ {+ FT_ULong version;+ FT_ULong count;+ PCF_Table tables;++ } PCF_TocRec, *PCF_Toc;+++ typedef struct PCF_ParsePropertyRec_+ {+ FT_Long name;+ FT_Byte isString;+ FT_Long value;++ } PCF_ParsePropertyRec, *PCF_ParseProperty;+++ typedef struct PCF_PropertyRec_+ {+ FT_String* name;+ FT_Byte isString;++ union+ {+ FT_String* atom;+ FT_Long l;+ FT_ULong ul;++ } value;++ } PCF_PropertyRec, *PCF_Property;+++ typedef struct PCF_Compressed_MetricRec_+ {+ FT_Byte leftSideBearing;+ FT_Byte rightSideBearing;+ FT_Byte characterWidth;+ FT_Byte ascent;+ FT_Byte descent;++ } PCF_Compressed_MetricRec, *PCF_Compressed_Metric;+++ typedef struct PCF_MetricRec_+ {+ FT_Short leftSideBearing;+ FT_Short rightSideBearing;+ FT_Short characterWidth;+ FT_Short ascent;+ FT_Short descent;+ FT_Short attributes;+ FT_ULong bits;++ } PCF_MetricRec, *PCF_Metric;+++ typedef struct PCF_AccelRec_+ {+ FT_Byte noOverlap;+ FT_Byte constantMetrics;+ FT_Byte terminalFont;+ FT_Byte constantWidth;+ FT_Byte inkInside;+ FT_Byte inkMetrics;+ FT_Byte drawDirection;+ FT_Long fontAscent;+ FT_Long fontDescent;+ FT_Long maxOverlap;+ PCF_MetricRec minbounds;+ PCF_MetricRec maxbounds;+ PCF_MetricRec ink_minbounds;+ PCF_MetricRec ink_maxbounds;++ } PCF_AccelRec, *PCF_Accel;+++ typedef struct PCF_EncodingRec_+ {+ FT_Long enc;+ FT_UShort glyph;++ } PCF_EncodingRec, *PCF_Encoding;+++ typedef struct PCF_FaceRec_+ {+ FT_FaceRec root;++ FT_StreamRec gzip_stream;+ FT_Stream gzip_source;++ char* charset_encoding;+ char* charset_registry;++ PCF_TocRec toc;+ PCF_AccelRec accel;++ int nprops;+ PCF_Property properties;++ FT_Long nmetrics;+ PCF_Metric metrics;+ FT_Long nencodings;+ PCF_Encoding encodings;++ FT_Short defaultChar;++ FT_ULong bitmapsFormat;++ FT_CharMap charmap_handle;+ FT_CharMapRec charmap; /* a single charmap per face */++ } PCF_FaceRec, *PCF_Face;+++ /* macros for pcf font format */++#define LSBFirst 0+#define MSBFirst 1++#define PCF_FILE_VERSION ( ( 'p' << 24 ) | \+ ( 'c' << 16 ) | \+ ( 'f' << 8 ) | 1 )+#define PCF_FORMAT_MASK 0xFFFFFF00UL++#define PCF_DEFAULT_FORMAT 0x00000000UL+#define PCF_INKBOUNDS 0x00000200UL+#define PCF_ACCEL_W_INKBOUNDS 0x00000100UL+#define PCF_COMPRESSED_METRICS 0x00000100UL++#define PCF_FORMAT_MATCH( a, b ) \+ ( ( (a) & PCF_FORMAT_MASK ) == ( (b) & PCF_FORMAT_MASK ) )++#define PCF_GLYPH_PAD_MASK ( 3 << 0 )+#define PCF_BYTE_MASK ( 1 << 2 )+#define PCF_BIT_MASK ( 1 << 3 )+#define PCF_SCAN_UNIT_MASK ( 3 << 4 )++#define PCF_BYTE_ORDER( f ) \+ ( ( (f) & PCF_BYTE_MASK ) ? MSBFirst : LSBFirst )+#define PCF_BIT_ORDER( f ) \+ ( ( (f) & PCF_BIT_MASK ) ? MSBFirst : LSBFirst )+#define PCF_GLYPH_PAD_INDEX( f ) \+ ( (f) & PCF_GLYPH_PAD_MASK )+#define PCF_GLYPH_PAD( f ) \+ ( 1 << PCF_GLYPH_PAD_INDEX( f ) )+#define PCF_SCAN_UNIT_INDEX( f ) \+ ( ( (f) & PCF_SCAN_UNIT_MASK ) >> 4 )+#define PCF_SCAN_UNIT( f ) \+ ( 1 << PCF_SCAN_UNIT_INDEX( f ) )+#define PCF_FORMAT_BITS( f ) \+ ( (f) & ( PCF_GLYPH_PAD_MASK | \+ PCF_BYTE_MASK | \+ PCF_BIT_MASK | \+ PCF_SCAN_UNIT_MASK ) )++#define PCF_SIZE_TO_INDEX( s ) ( (s) == 4 ? 2 : (s) == 2 ? 1 : 0 )+#define PCF_INDEX_TO_SIZE( b ) ( 1 << b )++#define PCF_FORMAT( bit, byte, glyph, scan ) \+ ( ( PCF_SIZE_TO_INDEX( scan ) << 4 ) | \+ ( ( (bit) == MSBFirst ? 1 : 0 ) << 3 ) | \+ ( ( (byte) == MSBFirst ? 1 : 0 ) << 2 ) | \+ ( PCF_SIZE_TO_INDEX( glyph ) << 0 ) )++#define PCF_PROPERTIES ( 1 << 0 )+#define PCF_ACCELERATORS ( 1 << 1 )+#define PCF_METRICS ( 1 << 2 )+#define PCF_BITMAPS ( 1 << 3 )+#define PCF_INK_METRICS ( 1 << 4 )+#define PCF_BDF_ENCODINGS ( 1 << 5 )+#define PCF_SWIDTHS ( 1 << 6 )+#define PCF_GLYPH_NAMES ( 1 << 7 )+#define PCF_BDF_ACCELERATORS ( 1 << 8 )++#define GLYPHPADOPTIONS 4 /* I'm not sure about this */++ FT_LOCAL( FT_Error )+ pcf_load_font( FT_Stream,+ PCF_Face );++FT_END_HEADER++#endif /* __PCF_H__ */+++/* END */
+ src/pcf/pcfdrivr.c view
@@ -0,0 +1,698 @@+/* pcfdrivr.c++ FreeType font driver for pcf files++ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009 by+ Francesco Zappa Nardelli++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in+all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+THE SOFTWARE.+*/+++#include <ft2build.h>++#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_STREAM_H+#include FT_INTERNAL_OBJECTS_H+#include FT_GZIP_H+#include FT_LZW_H+#include FT_ERRORS_H+#include FT_BDF_H+#include FT_TRUETYPE_IDS_H ++#include "pcf.h"+#include "pcfdrivr.h"+#include "pcfread.h"++#include "pcferror.h"+#include "pcfutil.h"++#undef FT_COMPONENT+#define FT_COMPONENT trace_pcfread++#include FT_SERVICE_BDF_H+#include FT_SERVICE_XFREE86_NAME_H+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_pcfdriver+++ typedef struct PCF_CMapRec_+ {+ FT_CMapRec root;+ FT_UInt num_encodings;+ PCF_Encoding encodings;++ } PCF_CMapRec, *PCF_CMap;+++ FT_CALLBACK_DEF( FT_Error )+ pcf_cmap_init( FT_CMap pcfcmap, /* PCF_CMap */+ FT_Pointer init_data )+ {+ PCF_CMap cmap = (PCF_CMap)pcfcmap;+ PCF_Face face = (PCF_Face)FT_CMAP_FACE( pcfcmap );++ FT_UNUSED( init_data );+++ cmap->num_encodings = (FT_UInt)face->nencodings;+ cmap->encodings = face->encodings;++ return PCF_Err_Ok;+ }+++ FT_CALLBACK_DEF( void )+ pcf_cmap_done( FT_CMap pcfcmap ) /* PCF_CMap */+ {+ PCF_CMap cmap = (PCF_CMap)pcfcmap;+++ cmap->encodings = NULL;+ cmap->num_encodings = 0;+ }+++ FT_CALLBACK_DEF( FT_UInt )+ pcf_cmap_char_index( FT_CMap pcfcmap, /* PCF_CMap */+ FT_UInt32 charcode )+ {+ PCF_CMap cmap = (PCF_CMap)pcfcmap;+ PCF_Encoding encodings = cmap->encodings;+ FT_UInt min, max, mid;+ FT_UInt result = 0;+++ min = 0;+ max = cmap->num_encodings;++ while ( min < max )+ {+ FT_ULong code;+++ mid = ( min + max ) >> 1;+ code = encodings[mid].enc;++ if ( charcode == code )+ {+ result = encodings[mid].glyph + 1;+ break;+ }++ if ( charcode < code )+ max = mid;+ else+ min = mid + 1;+ }++ return result;+ }+++ FT_CALLBACK_DEF( FT_UInt )+ pcf_cmap_char_next( FT_CMap pcfcmap, /* PCF_CMap */+ FT_UInt32 *acharcode )+ {+ PCF_CMap cmap = (PCF_CMap)pcfcmap;+ PCF_Encoding encodings = cmap->encodings;+ FT_UInt min, max, mid;+ FT_ULong charcode = *acharcode + 1;+ FT_UInt result = 0;+++ min = 0;+ max = cmap->num_encodings;++ while ( min < max )+ {+ FT_ULong code;+++ mid = ( min + max ) >> 1;+ code = encodings[mid].enc;++ if ( charcode == code )+ {+ result = encodings[mid].glyph + 1;+ goto Exit;+ }++ if ( charcode < code )+ max = mid;+ else+ min = mid + 1;+ }++ charcode = 0;+ if ( min < cmap->num_encodings )+ {+ charcode = encodings[min].enc;+ result = encodings[min].glyph + 1;+ }++ Exit:+ if ( charcode > 0xFFFFFFFFUL )+ {+ FT_TRACE1(( "pcf_cmap_char_next: charcode 0x%x > 32bit API" ));+ *acharcode = 0;+ /* XXX: result should be changed to indicate an overflow error */+ }+ else+ *acharcode = (FT_UInt32)charcode;+ return result;+ }+++ FT_CALLBACK_TABLE_DEF+ const FT_CMap_ClassRec pcf_cmap_class =+ {+ sizeof ( PCF_CMapRec ),+ pcf_cmap_init,+ pcf_cmap_done,+ pcf_cmap_char_index,+ pcf_cmap_char_next,++ NULL, NULL, NULL, NULL, NULL+ };+++ FT_CALLBACK_DEF( void )+ PCF_Face_Done( FT_Face pcfface ) /* PCF_Face */+ {+ PCF_Face face = (PCF_Face)pcfface;+ FT_Memory memory;+++ if ( !face )+ return;++ memory = FT_FACE_MEMORY( face );++ FT_FREE( face->encodings );+ FT_FREE( face->metrics );++ /* free properties */+ {+ PCF_Property prop;+ FT_Int i;+++ if ( face->properties )+ {+ for ( i = 0; i < face->nprops; i++ )+ {+ prop = &face->properties[i];++ if ( prop )+ {+ FT_FREE( prop->name );+ if ( prop->isString )+ FT_FREE( prop->value.atom );+ }+ }+ }+ FT_FREE( face->properties );+ }++ FT_FREE( face->toc.tables );+ FT_FREE( pcfface->family_name );+ FT_FREE( pcfface->style_name );+ FT_FREE( pcfface->available_sizes );+ FT_FREE( face->charset_encoding );+ FT_FREE( face->charset_registry );++ FT_TRACE4(( "PCF_Face_Done: done face\n" ));++ /* close gzip/LZW stream if any */+ if ( pcfface->stream == &face->gzip_stream )+ {+ FT_Stream_Close( &face->gzip_stream );+ pcfface->stream = face->gzip_source;+ }+ }+++ FT_CALLBACK_DEF( FT_Error )+ PCF_Face_Init( FT_Stream stream,+ FT_Face pcfface, /* PCF_Face */+ FT_Int face_index,+ FT_Int num_params,+ FT_Parameter* params )+ {+ PCF_Face face = (PCF_Face)pcfface;+ FT_Error error = PCF_Err_Ok;++ FT_UNUSED( num_params );+ FT_UNUSED( params );+ FT_UNUSED( face_index );+++ error = pcf_load_font( stream, face );+ if ( error )+ {+ PCF_Face_Done( pcfface );++#if defined( FT_CONFIG_OPTION_USE_ZLIB ) || \+ defined( FT_CONFIG_OPTION_USE_LZW )++#ifdef FT_CONFIG_OPTION_USE_ZLIB+ {+ FT_Error error2;+++ /* this didn't work, try gzip support! */+ error2 = FT_Stream_OpenGzip( &face->gzip_stream, stream );+ if ( FT_ERROR_BASE( error2 ) == FT_Err_Unimplemented_Feature )+ goto Fail;++ error = error2;+ }+#endif /* FT_CONFIG_OPTION_USE_ZLIB */++#ifdef FT_CONFIG_OPTION_USE_LZW+ if ( error )+ {+ FT_Error error3;+++ /* this didn't work, try LZW support! */+ error3 = FT_Stream_OpenLZW( &face->gzip_stream, stream );+ if ( FT_ERROR_BASE( error3 ) == FT_Err_Unimplemented_Feature )+ goto Fail;++ error = error3;+ }+#endif /* FT_CONFIG_OPTION_USE_LZW */++ if ( error )+ goto Fail;++ face->gzip_source = stream;+ pcfface->stream = &face->gzip_stream;++ stream = pcfface->stream;++ error = pcf_load_font( stream, face );+ if ( error )+ goto Fail;++#else /* !(FT_CONFIG_OPTION_USE_ZLIB || FT_CONFIG_OPTION_USE_LZW) */++ goto Fail;++#endif+ }++ /* set up charmap */+ {+ FT_String *charset_registry = face->charset_registry;+ FT_String *charset_encoding = face->charset_encoding;+ FT_Bool unicode_charmap = 0;+++ if ( charset_registry && charset_encoding )+ {+ char* s = charset_registry;+++ /* Uh, oh, compare first letters manually to avoid dependency+ on locales. */+ if ( ( s[0] == 'i' || s[0] == 'I' ) &&+ ( s[1] == 's' || s[1] == 'S' ) &&+ ( s[2] == 'o' || s[2] == 'O' ) )+ {+ s += 3;+ if ( !ft_strcmp( s, "10646" ) ||+ ( !ft_strcmp( s, "8859" ) &&+ !ft_strcmp( face->charset_encoding, "1" ) ) )+ unicode_charmap = 1;+ }+ }++ {+ FT_CharMapRec charmap;+++ charmap.face = FT_FACE( face );+ charmap.encoding = FT_ENCODING_NONE;+ /* initial platform/encoding should indicate unset status? */+ charmap.platform_id = TT_PLATFORM_APPLE_UNICODE;+ charmap.encoding_id = TT_APPLE_ID_DEFAULT;++ if ( unicode_charmap )+ {+ charmap.encoding = FT_ENCODING_UNICODE;+ charmap.platform_id = TT_PLATFORM_MICROSOFT;+ charmap.encoding_id = TT_MS_ID_UNICODE_CS;+ }++ error = FT_CMap_New( &pcf_cmap_class, NULL, &charmap, NULL );++#if 0+ /* Select default charmap */+ if ( pcfface->num_charmaps )+ pcfface->charmap = pcfface->charmaps[0];+#endif+ }+ }++ Exit:+ return error;++ Fail:+ FT_TRACE2(( "[not a valid PCF file]\n" ));+ PCF_Face_Done( pcfface );+ error = PCF_Err_Unknown_File_Format; /* error */+ goto Exit;+ }+++ FT_CALLBACK_DEF( FT_Error )+ PCF_Size_Select( FT_Size size,+ FT_ULong strike_index )+ {+ PCF_Accel accel = &( (PCF_Face)size->face )->accel;+++ FT_Select_Metrics( size->face, strike_index );++ size->metrics.ascender = accel->fontAscent << 6;+ size->metrics.descender = -accel->fontDescent << 6;+ size->metrics.max_advance = accel->maxbounds.characterWidth << 6;++ return PCF_Err_Ok;+ }+++ FT_CALLBACK_DEF( FT_Error )+ PCF_Size_Request( FT_Size size,+ FT_Size_Request req )+ {+ PCF_Face face = (PCF_Face)size->face;+ FT_Bitmap_Size* bsize = size->face->available_sizes;+ FT_Error error = PCF_Err_Invalid_Pixel_Size;+ FT_Long height;+++ height = FT_REQUEST_HEIGHT( req );+ height = ( height + 32 ) >> 6;++ switch ( req->type )+ {+ case FT_SIZE_REQUEST_TYPE_NOMINAL:+ if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) )+ error = PCF_Err_Ok;+ break;++ case FT_SIZE_REQUEST_TYPE_REAL_DIM:+ if ( height == ( face->accel.fontAscent ++ face->accel.fontDescent ) )+ error = PCF_Err_Ok;+ break;++ default:+ error = PCF_Err_Unimplemented_Feature;+ break;+ }++ if ( error )+ return error;+ else+ return PCF_Size_Select( size, 0 );+ }+++ FT_CALLBACK_DEF( FT_Error )+ PCF_Glyph_Load( FT_GlyphSlot slot,+ FT_Size size,+ FT_UInt glyph_index,+ FT_Int32 load_flags )+ {+ PCF_Face face = (PCF_Face)FT_SIZE_FACE( size );+ FT_Stream stream;+ FT_Error error = PCF_Err_Ok;+ FT_Bitmap* bitmap = &slot->bitmap;+ PCF_Metric metric;+ FT_Offset bytes;++ FT_UNUSED( load_flags );+++ FT_TRACE4(( "load_glyph %d ---", glyph_index ));++ if ( !face || glyph_index >= (FT_UInt)face->root.num_glyphs )+ {+ error = PCF_Err_Invalid_Argument;+ goto Exit;+ }++ stream = face->root.stream;++ if ( glyph_index > 0 )+ glyph_index--;++ metric = face->metrics + glyph_index;++ bitmap->rows = metric->ascent + metric->descent;+ bitmap->width = metric->rightSideBearing - metric->leftSideBearing;+ bitmap->num_grays = 1;+ bitmap->pixel_mode = FT_PIXEL_MODE_MONO;++ FT_TRACE6(( "BIT_ORDER %d ; BYTE_ORDER %d ; GLYPH_PAD %d\n",+ PCF_BIT_ORDER( face->bitmapsFormat ),+ PCF_BYTE_ORDER( face->bitmapsFormat ),+ PCF_GLYPH_PAD( face->bitmapsFormat ) ));++ switch ( PCF_GLYPH_PAD( face->bitmapsFormat ) )+ {+ case 1:+ bitmap->pitch = ( bitmap->width + 7 ) >> 3;+ break;++ case 2:+ bitmap->pitch = ( ( bitmap->width + 15 ) >> 4 ) << 1;+ break;++ case 4:+ bitmap->pitch = ( ( bitmap->width + 31 ) >> 5 ) << 2;+ break;++ case 8:+ bitmap->pitch = ( ( bitmap->width + 63 ) >> 6 ) << 3;+ break;++ default:+ return PCF_Err_Invalid_File_Format;+ }++ /* XXX: to do: are there cases that need repadding the bitmap? */+ bytes = bitmap->pitch * bitmap->rows;++ error = ft_glyphslot_alloc_bitmap( slot, bytes );+ if ( error )+ goto Exit;++ if ( FT_STREAM_SEEK( metric->bits ) ||+ FT_STREAM_READ( bitmap->buffer, bytes ) )+ goto Exit;++ if ( PCF_BIT_ORDER( face->bitmapsFormat ) != MSBFirst )+ BitOrderInvert( bitmap->buffer, bytes );++ if ( ( PCF_BYTE_ORDER( face->bitmapsFormat ) !=+ PCF_BIT_ORDER( face->bitmapsFormat ) ) )+ {+ switch ( PCF_SCAN_UNIT( face->bitmapsFormat ) )+ {+ case 1:+ break;++ case 2:+ TwoByteSwap( bitmap->buffer, bytes );+ break;++ case 4:+ FourByteSwap( bitmap->buffer, bytes );+ break;+ }+ }++ slot->format = FT_GLYPH_FORMAT_BITMAP;+ slot->bitmap_left = metric->leftSideBearing;+ slot->bitmap_top = metric->ascent;++ slot->metrics.horiAdvance = metric->characterWidth << 6;+ slot->metrics.horiBearingX = metric->leftSideBearing << 6;+ slot->metrics.horiBearingY = metric->ascent << 6;+ slot->metrics.width = ( metric->rightSideBearing -+ metric->leftSideBearing ) << 6;+ slot->metrics.height = bitmap->rows << 6;++ ft_synthesize_vertical_metrics( &slot->metrics,+ ( face->accel.fontAscent ++ face->accel.fontDescent ) << 6 );++ FT_TRACE4(( " --- ok\n" ));++ Exit:+ return error;+ }+++ /*+ *+ * BDF SERVICE+ *+ */++ static FT_Error+ pcf_get_bdf_property( PCF_Face face,+ const char* prop_name,+ BDF_PropertyRec *aproperty )+ {+ PCF_Property prop;+++ prop = pcf_find_property( face, prop_name );+ if ( prop != NULL )+ {+ if ( prop->isString )+ {+ aproperty->type = BDF_PROPERTY_TYPE_ATOM;+ aproperty->u.atom = prop->value.atom;+ }+ else+ {+ if ( prop->value.l > 0x7FFFFFFFL || prop->value.l < ( -1 - 0x7FFFFFFFL ) )+ {+ FT_TRACE1(( "pcf_get_bdf_property: " ));+ FT_TRACE1(( "too large integer 0x%x is truncated\n" ));+ }+ /* Apparently, the PCF driver loads all properties as signed integers!+ * This really doesn't seem to be a problem, because this is+ * sufficient for any meaningful values.+ */+ aproperty->type = BDF_PROPERTY_TYPE_INTEGER;+ aproperty->u.integer = (FT_Int32)prop->value.l;+ }+ return 0;+ }++ return PCF_Err_Invalid_Argument;+ }+++ static FT_Error+ pcf_get_charset_id( PCF_Face face,+ const char* *acharset_encoding,+ const char* *acharset_registry )+ {+ *acharset_encoding = face->charset_encoding;+ *acharset_registry = face->charset_registry;++ return 0;+ }+++ static const FT_Service_BDFRec pcf_service_bdf =+ {+ (FT_BDF_GetCharsetIdFunc)pcf_get_charset_id,+ (FT_BDF_GetPropertyFunc) pcf_get_bdf_property+ };+++ /*+ *+ * SERVICE LIST+ *+ */++ static const FT_ServiceDescRec pcf_services[] =+ {+ { FT_SERVICE_ID_BDF, &pcf_service_bdf },+ { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_PCF },+ { NULL, NULL }+ };+++ FT_CALLBACK_DEF( FT_Module_Interface )+ pcf_driver_requester( FT_Module module,+ const char* name )+ {+ FT_UNUSED( module );++ return ft_service_list_lookup( pcf_services, name );+ }+++ FT_CALLBACK_TABLE_DEF+ const FT_Driver_ClassRec pcf_driver_class =+ {+ {+ FT_MODULE_FONT_DRIVER |+ FT_MODULE_DRIVER_NO_OUTLINES,+ sizeof ( FT_DriverRec ),++ "pcf",+ 0x10000L,+ 0x20000L,++ 0,++ 0,+ 0,+ pcf_driver_requester+ },++ sizeof ( PCF_FaceRec ),+ sizeof ( FT_SizeRec ),+ sizeof ( FT_GlyphSlotRec ),++ PCF_Face_Init,+ PCF_Face_Done,+ 0, /* FT_Size_InitFunc */+ 0, /* FT_Size_DoneFunc */+ 0, /* FT_Slot_InitFunc */+ 0, /* FT_Slot_DoneFunc */++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS+ ft_stub_set_char_sizes,+ ft_stub_set_pixel_sizes,+#endif+ PCF_Glyph_Load,++ 0, /* FT_Face_GetKerningFunc */+ 0, /* FT_Face_AttachFunc */+ 0, /* FT_Face_GetAdvancesFunc */++ PCF_Size_Request,+ PCF_Size_Select+ };+++/* END */
+ src/pcf/pcfdrivr.h view
@@ -0,0 +1,48 @@+/* pcfdrivr.h++ FreeType font driver for pcf fonts++ Copyright 2000-2001, 2002 by+ Francesco Zappa Nardelli++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in+all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+THE SOFTWARE.+*/+++#ifndef __PCFDRIVR_H__+#define __PCFDRIVR_H__++#include <ft2build.h>+#include FT_INTERNAL_DRIVER_H++FT_BEGIN_HEADER++#ifdef FT_CONFIG_OPTION_PIC+#error "this module does not support PIC yet"+#endif ++ FT_EXPORT_VAR( const FT_Driver_ClassRec ) pcf_driver_class;++FT_END_HEADER+++#endif /* __PCFDRIVR_H__ */+++/* END */
+ src/pcf/pcferror.h view
@@ -0,0 +1,40 @@+/***************************************************************************/+/* */+/* pcferror.h */+/* */+/* PCF error codes (specification only). */+/* */+/* Copyright 2001 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 PCF error enumeration constants. */+ /* */+ /*************************************************************************/++#ifndef __PCFERROR_H__+#define __PCFERROR_H__++#include FT_MODULE_ERRORS_H++#undef __FTERRORS_H__++#define FT_ERR_PREFIX PCF_Err_+#define FT_ERR_BASE FT_Mod_Err_PCF++#include FT_ERRORS_H++#endif /* __PCFERROR_H__ */+++/* END */
+ src/pcf/pcfread.c view
@@ -0,0 +1,1278 @@+/* pcfread.c++ FreeType font driver for pcf fonts++ Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,+ 2010 by+ Francesco Zappa Nardelli++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in+all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+THE SOFTWARE.+*/+++#include <ft2build.h>++#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_STREAM_H+#include FT_INTERNAL_OBJECTS_H++#include "pcf.h"+#include "pcfread.h"++#include "pcferror.h"+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_pcfread+++#ifdef FT_DEBUG_LEVEL_TRACE+ static const char* const tableNames[] =+ {+ "prop", "accl", "mtrcs", "bmps", "imtrcs",+ "enc", "swidth", "names", "accel"+ };+#endif+++ static+ const FT_Frame_Field pcf_toc_header[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE PCF_TocRec++ FT_FRAME_START( 8 ),+ FT_FRAME_ULONG_LE( version ),+ FT_FRAME_ULONG_LE( count ),+ FT_FRAME_END+ };+++ static+ const FT_Frame_Field pcf_table_header[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE PCF_TableRec++ FT_FRAME_START( 16 ),+ FT_FRAME_ULONG_LE( type ),+ FT_FRAME_ULONG_LE( format ),+ FT_FRAME_ULONG_LE( size ),+ FT_FRAME_ULONG_LE( offset ),+ FT_FRAME_END+ };+++ static FT_Error+ pcf_read_TOC( FT_Stream stream,+ PCF_Face face )+ {+ FT_Error error;+ PCF_Toc toc = &face->toc;+ PCF_Table tables;++ FT_Memory memory = FT_FACE(face)->memory;+ FT_UInt n;+++ if ( FT_STREAM_SEEK ( 0 ) ||+ FT_STREAM_READ_FIELDS ( pcf_toc_header, toc ) )+ return PCF_Err_Cannot_Open_Resource;++ if ( toc->version != PCF_FILE_VERSION ||+ toc->count > FT_ARRAY_MAX( face->toc.tables ) ||+ toc->count == 0 )+ return PCF_Err_Invalid_File_Format;++ if ( FT_NEW_ARRAY( face->toc.tables, toc->count ) )+ return PCF_Err_Out_Of_Memory;++ tables = face->toc.tables;+ for ( n = 0; n < toc->count; n++ )+ {+ if ( FT_STREAM_READ_FIELDS( pcf_table_header, tables ) )+ goto Exit;+ tables++;+ }++ /* Sort tables and check for overlaps. Because they are almost */+ /* always ordered already, an in-place bubble sort with simultaneous */+ /* boundary checking seems appropriate. */+ tables = face->toc.tables;++ for ( n = 0; n < toc->count - 1; n++ )+ {+ FT_UInt i, have_change;+++ have_change = 0;++ for ( i = 0; i < toc->count - 1 - n; i++ )+ {+ PCF_TableRec tmp;+++ if ( tables[i].offset > tables[i + 1].offset )+ {+ tmp = tables[i];+ tables[i] = tables[i + 1];+ tables[i + 1] = tmp;++ have_change = 1;+ }++ if ( ( tables[i].size > tables[i + 1].offset ) ||+ ( tables[i].offset > tables[i + 1].offset - tables[i].size ) )+ return PCF_Err_Invalid_Offset;+ }++ if ( !have_change )+ break;+ }++#ifdef FT_DEBUG_LEVEL_TRACE++ {+ FT_UInt i, j;+ const char* name = "?";+++ FT_TRACE4(( "pcf_read_TOC:\n" ));++ FT_TRACE4(( " number of tables: %ld\n", face->toc.count ));++ tables = face->toc.tables;+ for ( i = 0; i < toc->count; i++ )+ {+ for ( j = 0; j < sizeof ( tableNames ) / sizeof ( tableNames[0] );+ j++ )+ if ( tables[i].type == (FT_UInt)( 1 << j ) )+ name = tableNames[j];++ FT_TRACE4(( " %d: type=%s, format=0x%X, "+ "size=%ld (0x%lX), offset=%ld (0x%lX)\n",+ i, name,+ tables[i].format,+ tables[i].size, tables[i].size,+ tables[i].offset, tables[i].offset ));+ }+ }++#endif++ return PCF_Err_Ok;++ Exit:+ FT_FREE( face->toc.tables );+ return error;+ }+++#define PCF_METRIC_SIZE 12++ static+ const FT_Frame_Field pcf_metric_header[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE PCF_MetricRec++ FT_FRAME_START( PCF_METRIC_SIZE ),+ FT_FRAME_SHORT_LE( leftSideBearing ),+ FT_FRAME_SHORT_LE( rightSideBearing ),+ FT_FRAME_SHORT_LE( characterWidth ),+ FT_FRAME_SHORT_LE( ascent ),+ FT_FRAME_SHORT_LE( descent ),+ FT_FRAME_SHORT_LE( attributes ),+ FT_FRAME_END+ };+++ static+ const FT_Frame_Field pcf_metric_msb_header[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE PCF_MetricRec++ FT_FRAME_START( PCF_METRIC_SIZE ),+ FT_FRAME_SHORT( leftSideBearing ),+ FT_FRAME_SHORT( rightSideBearing ),+ FT_FRAME_SHORT( characterWidth ),+ FT_FRAME_SHORT( ascent ),+ FT_FRAME_SHORT( descent ),+ FT_FRAME_SHORT( attributes ),+ FT_FRAME_END+ };+++#define PCF_COMPRESSED_METRIC_SIZE 5++ static+ const FT_Frame_Field pcf_compressed_metric_header[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE PCF_Compressed_MetricRec++ FT_FRAME_START( PCF_COMPRESSED_METRIC_SIZE ),+ FT_FRAME_BYTE( leftSideBearing ),+ FT_FRAME_BYTE( rightSideBearing ),+ FT_FRAME_BYTE( characterWidth ),+ FT_FRAME_BYTE( ascent ),+ FT_FRAME_BYTE( descent ),+ FT_FRAME_END+ };+++ static FT_Error+ pcf_get_metric( FT_Stream stream,+ FT_ULong format,+ PCF_Metric metric )+ {+ FT_Error error = PCF_Err_Ok;+++ if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )+ {+ const FT_Frame_Field* fields;+++ /* parsing normal metrics */+ fields = PCF_BYTE_ORDER( format ) == MSBFirst+ ? pcf_metric_msb_header+ : pcf_metric_header;++ /* the following sets `error' but doesn't return in case of failure */+ (void)FT_STREAM_READ_FIELDS( fields, metric );+ }+ else+ {+ PCF_Compressed_MetricRec compr;+++ /* parsing compressed metrics */+ if ( FT_STREAM_READ_FIELDS( pcf_compressed_metric_header, &compr ) )+ goto Exit;++ metric->leftSideBearing = (FT_Short)( compr.leftSideBearing - 0x80 );+ metric->rightSideBearing = (FT_Short)( compr.rightSideBearing - 0x80 );+ metric->characterWidth = (FT_Short)( compr.characterWidth - 0x80 );+ metric->ascent = (FT_Short)( compr.ascent - 0x80 );+ metric->descent = (FT_Short)( compr.descent - 0x80 );+ metric->attributes = 0;+ }++ Exit:+ return error;+ }+++ static FT_Error+ pcf_seek_to_table_type( FT_Stream stream,+ PCF_Table tables,+ FT_ULong ntables, /* same as PCF_Toc->count */+ FT_ULong type,+ FT_ULong *aformat,+ FT_ULong *asize )+ {+ FT_Error error = PCF_Err_Invalid_File_Format;+ FT_ULong i;+++ for ( i = 0; i < ntables; i++ )+ if ( tables[i].type == type )+ {+ if ( stream->pos > tables[i].offset )+ {+ error = PCF_Err_Invalid_Stream_Skip;+ goto Fail;+ }++ if ( FT_STREAM_SKIP( tables[i].offset - stream->pos ) )+ {+ error = PCF_Err_Invalid_Stream_Skip;+ goto Fail;+ }++ *asize = tables[i].size;+ *aformat = tables[i].format;++ return PCF_Err_Ok;+ }++ Fail:+ *asize = 0;+ return error;+ }+++ static FT_Bool+ pcf_has_table_type( PCF_Table tables,+ FT_ULong ntables, /* same as PCF_Toc->count */+ FT_ULong type )+ {+ FT_ULong i;+++ for ( i = 0; i < ntables; i++ )+ if ( tables[i].type == type )+ return TRUE;++ return FALSE;+ }+++#define PCF_PROPERTY_SIZE 9++ static+ const FT_Frame_Field pcf_property_header[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE PCF_ParsePropertyRec++ FT_FRAME_START( PCF_PROPERTY_SIZE ),+ FT_FRAME_LONG_LE( name ),+ FT_FRAME_BYTE ( isString ),+ FT_FRAME_LONG_LE( value ),+ FT_FRAME_END+ };+++ static+ const FT_Frame_Field pcf_property_msb_header[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE PCF_ParsePropertyRec++ FT_FRAME_START( PCF_PROPERTY_SIZE ),+ FT_FRAME_LONG( name ),+ FT_FRAME_BYTE( isString ),+ FT_FRAME_LONG( value ),+ FT_FRAME_END+ };+++ FT_LOCAL_DEF( PCF_Property )+ pcf_find_property( PCF_Face face,+ const FT_String* prop )+ {+ PCF_Property properties = face->properties;+ FT_Bool found = 0;+ int i;+++ for ( i = 0 ; i < face->nprops && !found; i++ )+ {+ if ( !ft_strcmp( properties[i].name, prop ) )+ found = 1;+ }++ if ( found )+ return properties + i - 1;+ else+ return NULL;+ }+++ static FT_Error+ pcf_get_properties( FT_Stream stream,+ PCF_Face face )+ {+ PCF_ParseProperty props = 0;+ PCF_Property properties;+ FT_ULong nprops, i;+ FT_ULong format, size;+ FT_Error error;+ FT_Memory memory = FT_FACE(face)->memory;+ FT_ULong string_size;+ FT_String* strings = 0;+++ error = pcf_seek_to_table_type( stream,+ face->toc.tables,+ face->toc.count,+ PCF_PROPERTIES,+ &format,+ &size );+ if ( error )+ goto Bail;++ if ( FT_READ_ULONG_LE( format ) )+ goto Bail;++ FT_TRACE4(( "pcf_get_properties:\n" ));++ FT_TRACE4(( " format = %ld\n", format ));++ if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )+ goto Bail;++ if ( PCF_BYTE_ORDER( format ) == MSBFirst )+ (void)FT_READ_ULONG( nprops );+ else+ (void)FT_READ_ULONG_LE( nprops );+ if ( error )+ goto Bail;++ FT_TRACE4(( " nprop = %d (truncate %d props)\n",+ (int)nprops, nprops - (int)nprops ));++ nprops = (int)nprops;++ /* rough estimate */+ if ( nprops > size / PCF_PROPERTY_SIZE )+ {+ error = PCF_Err_Invalid_Table;+ goto Bail;+ }++ face->nprops = (int)nprops;++ if ( FT_NEW_ARRAY( props, nprops ) )+ goto Bail;++ for ( i = 0; i < nprops; i++ )+ {+ if ( PCF_BYTE_ORDER( format ) == MSBFirst )+ {+ if ( FT_STREAM_READ_FIELDS( pcf_property_msb_header, props + i ) )+ goto Bail;+ }+ else+ {+ if ( FT_STREAM_READ_FIELDS( pcf_property_header, props + i ) )+ goto Bail;+ }+ }++ /* pad the property array */+ /* */+ /* clever here - nprops is the same as the number of odd-units read, */+ /* as only isStringProp are odd length (Keith Packard) */+ /* */+ if ( nprops & 3 )+ {+ i = 4 - ( nprops & 3 );+ if ( FT_STREAM_SKIP( i ) )+ {+ error = PCF_Err_Invalid_Stream_Skip;+ goto Bail;+ }+ }++ if ( PCF_BYTE_ORDER( format ) == MSBFirst )+ (void)FT_READ_ULONG( string_size );+ else+ (void)FT_READ_ULONG_LE( string_size );+ if ( error )+ goto Bail;++ FT_TRACE4(( " string_size = %ld\n", string_size ));++ /* rough estimate */+ if ( string_size > size - nprops * PCF_PROPERTY_SIZE )+ {+ error = PCF_Err_Invalid_Table;+ goto Bail;+ }++ if ( FT_NEW_ARRAY( strings, string_size ) )+ goto Bail;++ error = FT_Stream_Read( stream, (FT_Byte*)strings, string_size );+ if ( error )+ goto Bail;++ if ( FT_NEW_ARRAY( properties, nprops ) )+ goto Bail;++ face->properties = properties;++ for ( i = 0; i < nprops; i++ )+ {+ FT_Long name_offset = props[i].name;+++ if ( ( name_offset < 0 ) ||+ ( (FT_ULong)name_offset > string_size ) )+ {+ error = PCF_Err_Invalid_Offset;+ goto Bail;+ }++ if ( FT_STRDUP( properties[i].name, strings + name_offset ) )+ goto Bail;++ FT_TRACE4(( " %s:", properties[i].name ));++ properties[i].isString = props[i].isString;++ if ( props[i].isString )+ {+ FT_Long value_offset = props[i].value;+++ if ( ( value_offset < 0 ) ||+ ( (FT_ULong)value_offset > string_size ) )+ {+ error = PCF_Err_Invalid_Offset;+ goto Bail;+ }++ if ( FT_STRDUP( properties[i].value.atom, strings + value_offset ) )+ goto Bail;++ FT_TRACE4(( " `%s'\n", properties[i].value.atom ));+ }+ else+ {+ properties[i].value.l = props[i].value;++ FT_TRACE4(( " %d\n", properties[i].value.l ));+ }+ }++ error = PCF_Err_Ok;++ Bail:+ FT_FREE( props );+ FT_FREE( strings );++ return error;+ }+++ static FT_Error+ pcf_get_metrics( FT_Stream stream,+ PCF_Face face )+ {+ FT_Error error = PCF_Err_Ok;+ FT_Memory memory = FT_FACE(face)->memory;+ FT_ULong format, size;+ PCF_Metric metrics = 0;+ FT_ULong nmetrics, i;+++ error = pcf_seek_to_table_type( stream,+ face->toc.tables,+ face->toc.count,+ PCF_METRICS,+ &format,+ &size );+ if ( error )+ return error;++ if ( FT_READ_ULONG_LE( format ) )+ goto Bail;++ if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) &&+ !PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) )+ return PCF_Err_Invalid_File_Format;++ if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )+ {+ if ( PCF_BYTE_ORDER( format ) == MSBFirst )+ (void)FT_READ_ULONG( nmetrics );+ else+ (void)FT_READ_ULONG_LE( nmetrics );+ }+ else+ {+ if ( PCF_BYTE_ORDER( format ) == MSBFirst )+ (void)FT_READ_USHORT( nmetrics );+ else+ (void)FT_READ_USHORT_LE( nmetrics );+ }+ if ( error )+ return PCF_Err_Invalid_File_Format;++ face->nmetrics = nmetrics;++ if ( !nmetrics )+ return PCF_Err_Invalid_Table;++ FT_TRACE4(( "pcf_get_metrics:\n" ));++ FT_TRACE4(( " number of metrics: %d\n", nmetrics ));++ /* rough estimate */+ if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )+ {+ if ( nmetrics > size / PCF_METRIC_SIZE )+ return PCF_Err_Invalid_Table;+ }+ else+ {+ if ( nmetrics > size / PCF_COMPRESSED_METRIC_SIZE )+ return PCF_Err_Invalid_Table;+ }++ if ( FT_NEW_ARRAY( face->metrics, nmetrics ) )+ return PCF_Err_Out_Of_Memory;++ metrics = face->metrics;+ for ( i = 0; i < nmetrics; i++ )+ {+ error = pcf_get_metric( stream, format, metrics + i );++ metrics[i].bits = 0;++ FT_TRACE5(( " idx %d: width=%d, "+ "lsb=%d, rsb=%d, ascent=%d, descent=%d, swidth=%d\n",+ i,+ ( metrics + i )->characterWidth,+ ( metrics + i )->leftSideBearing,+ ( metrics + i )->rightSideBearing,+ ( metrics + i )->ascent,+ ( metrics + i )->descent,+ ( metrics + i )->attributes ));++ if ( error )+ break;+ }++ if ( error )+ FT_FREE( face->metrics );++ Bail:+ return error;+ }+++ static FT_Error+ pcf_get_bitmaps( FT_Stream stream,+ PCF_Face face )+ {+ FT_Error error = PCF_Err_Ok;+ FT_Memory memory = FT_FACE(face)->memory;+ FT_Long* offsets;+ FT_Long bitmapSizes[GLYPHPADOPTIONS];+ FT_ULong format, size;+ FT_ULong nbitmaps, i, sizebitmaps = 0;+++ error = pcf_seek_to_table_type( stream,+ face->toc.tables,+ face->toc.count,+ PCF_BITMAPS,+ &format,+ &size );+ if ( error )+ return error;++ error = FT_Stream_EnterFrame( stream, 8 );+ if ( error )+ return error;++ format = FT_GET_ULONG_LE();+ if ( PCF_BYTE_ORDER( format ) == MSBFirst )+ nbitmaps = FT_GET_ULONG();+ else+ nbitmaps = FT_GET_ULONG_LE();++ FT_Stream_ExitFrame( stream );++ if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )+ return PCF_Err_Invalid_File_Format;++ FT_TRACE4(( "pcf_get_bitmaps:\n" ));++ FT_TRACE4(( " number of bitmaps: %d\n", nbitmaps ));++ /* XXX: PCF_Face->nmetrics is singed FT_Long, see pcf.h */+ if ( face->nmetrics < 0 || nbitmaps != ( FT_ULong )face->nmetrics )+ return PCF_Err_Invalid_File_Format;++ if ( FT_NEW_ARRAY( offsets, nbitmaps ) )+ return error;++ for ( i = 0; i < nbitmaps; i++ )+ {+ if ( PCF_BYTE_ORDER( format ) == MSBFirst )+ (void)FT_READ_LONG( offsets[i] );+ else+ (void)FT_READ_LONG_LE( offsets[i] );++ FT_TRACE5(( " bitmap %d: offset %ld (0x%lX)\n",+ i, offsets[i], offsets[i] ));+ }+ if ( error )+ goto Bail;++ for ( i = 0; i < GLYPHPADOPTIONS; i++ )+ {+ if ( PCF_BYTE_ORDER( format ) == MSBFirst )+ (void)FT_READ_LONG( bitmapSizes[i] );+ else+ (void)FT_READ_LONG_LE( bitmapSizes[i] );+ if ( error )+ goto Bail;++ sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX( format )];++ FT_TRACE4(( " padding %d implies a size of %ld\n", i, bitmapSizes[i] ));+ }++ FT_TRACE4(( " %d bitmaps, padding index %ld\n",+ nbitmaps,+ PCF_GLYPH_PAD_INDEX( format ) ));+ FT_TRACE4(( " bitmap size = %d\n", sizebitmaps ));++ FT_UNUSED( sizebitmaps ); /* only used for debugging */++ for ( i = 0; i < nbitmaps; i++ )+ {+ /* rough estimate */+ if ( ( offsets[i] < 0 ) ||+ ( (FT_ULong)offsets[i] > size ) )+ {+ FT_TRACE0(( "pcf_get_bitmaps:"+ " invalid offset to bitmap data of glyph %d\n", i ));+ }+ else+ face->metrics[i].bits = stream->pos + offsets[i];+ }++ face->bitmapsFormat = format;++ Bail:+ FT_FREE( offsets );+ return error;+ }+++ static FT_Error+ pcf_get_encodings( FT_Stream stream,+ PCF_Face face )+ {+ FT_Error error = PCF_Err_Ok;+ FT_Memory memory = FT_FACE(face)->memory;+ FT_ULong format, size;+ int firstCol, lastCol;+ int firstRow, lastRow;+ int nencoding, encodingOffset;+ int i, j;+ PCF_Encoding tmpEncoding, encoding = 0;+++ error = pcf_seek_to_table_type( stream,+ face->toc.tables,+ face->toc.count,+ PCF_BDF_ENCODINGS,+ &format,+ &size );+ if ( error )+ return error;++ error = FT_Stream_EnterFrame( stream, 14 );+ if ( error )+ return error;++ format = FT_GET_ULONG_LE();++ if ( PCF_BYTE_ORDER( format ) == MSBFirst )+ {+ firstCol = FT_GET_SHORT();+ lastCol = FT_GET_SHORT();+ firstRow = FT_GET_SHORT();+ lastRow = FT_GET_SHORT();+ face->defaultChar = FT_GET_SHORT();+ }+ else+ {+ firstCol = FT_GET_SHORT_LE();+ lastCol = FT_GET_SHORT_LE();+ firstRow = FT_GET_SHORT_LE();+ lastRow = FT_GET_SHORT_LE();+ face->defaultChar = FT_GET_SHORT_LE();+ }++ FT_Stream_ExitFrame( stream );++ if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )+ return PCF_Err_Invalid_File_Format;++ FT_TRACE4(( "pdf_get_encodings:\n" ));++ FT_TRACE4(( " firstCol %d, lastCol %d, firstRow %d, lastRow %d\n",+ firstCol, lastCol, firstRow, lastRow ));++ nencoding = ( lastCol - firstCol + 1 ) * ( lastRow - firstRow + 1 );++ if ( FT_NEW_ARRAY( tmpEncoding, nencoding ) )+ return PCF_Err_Out_Of_Memory;++ error = FT_Stream_EnterFrame( stream, 2 * nencoding );+ if ( error )+ goto Bail;++ for ( i = 0, j = 0 ; i < nencoding; i++ )+ {+ if ( PCF_BYTE_ORDER( format ) == MSBFirst )+ encodingOffset = FT_GET_SHORT();+ else+ encodingOffset = FT_GET_SHORT_LE();++ if ( encodingOffset != -1 )+ {+ tmpEncoding[j].enc = ( ( ( i / ( lastCol - firstCol + 1 ) ) ++ firstRow ) * 256 ) ++ ( ( i % ( lastCol - firstCol + 1 ) ) ++ firstCol );++ tmpEncoding[j].glyph = (FT_Short)encodingOffset;++ FT_TRACE5(( " code %d (0x%04X): idx %d\n",+ tmpEncoding[j].enc, tmpEncoding[j].enc,+ tmpEncoding[j].glyph ));++ j++;+ }+ }+ FT_Stream_ExitFrame( stream );++ if ( FT_NEW_ARRAY( encoding, j ) )+ goto Bail;++ for ( i = 0; i < j; i++ )+ {+ encoding[i].enc = tmpEncoding[i].enc;+ encoding[i].glyph = tmpEncoding[i].glyph;+ }++ face->nencodings = j;+ face->encodings = encoding;+ FT_FREE( tmpEncoding );++ return error;++ Bail:+ FT_FREE( encoding );+ FT_FREE( tmpEncoding );+ return error;+ }+++ static+ const FT_Frame_Field pcf_accel_header[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE PCF_AccelRec++ FT_FRAME_START( 20 ),+ FT_FRAME_BYTE ( noOverlap ),+ FT_FRAME_BYTE ( constantMetrics ),+ FT_FRAME_BYTE ( terminalFont ),+ FT_FRAME_BYTE ( constantWidth ),+ FT_FRAME_BYTE ( inkInside ),+ FT_FRAME_BYTE ( inkMetrics ),+ FT_FRAME_BYTE ( drawDirection ),+ FT_FRAME_SKIP_BYTES( 1 ),+ FT_FRAME_LONG_LE ( fontAscent ),+ FT_FRAME_LONG_LE ( fontDescent ),+ FT_FRAME_LONG_LE ( maxOverlap ),+ FT_FRAME_END+ };+++ static+ const FT_Frame_Field pcf_accel_msb_header[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE PCF_AccelRec++ FT_FRAME_START( 20 ),+ FT_FRAME_BYTE ( noOverlap ),+ FT_FRAME_BYTE ( constantMetrics ),+ FT_FRAME_BYTE ( terminalFont ),+ FT_FRAME_BYTE ( constantWidth ),+ FT_FRAME_BYTE ( inkInside ),+ FT_FRAME_BYTE ( inkMetrics ),+ FT_FRAME_BYTE ( drawDirection ),+ FT_FRAME_SKIP_BYTES( 1 ),+ FT_FRAME_LONG ( fontAscent ),+ FT_FRAME_LONG ( fontDescent ),+ FT_FRAME_LONG ( maxOverlap ),+ FT_FRAME_END+ };+++ static FT_Error+ pcf_get_accel( FT_Stream stream,+ PCF_Face face,+ FT_ULong type )+ {+ FT_ULong format, size;+ FT_Error error = PCF_Err_Ok;+ PCF_Accel accel = &face->accel;+++ error = pcf_seek_to_table_type( stream,+ face->toc.tables,+ face->toc.count,+ type,+ &format,+ &size );+ if ( error )+ goto Bail;++ if ( FT_READ_ULONG_LE( format ) )+ goto Bail;++ if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) &&+ !PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )+ goto Bail;++ if ( PCF_BYTE_ORDER( format ) == MSBFirst )+ {+ if ( FT_STREAM_READ_FIELDS( pcf_accel_msb_header, accel ) )+ goto Bail;+ }+ else+ {+ if ( FT_STREAM_READ_FIELDS( pcf_accel_header, accel ) )+ goto Bail;+ }++ error = pcf_get_metric( stream,+ format & ( ~PCF_FORMAT_MASK ),+ &(accel->minbounds) );+ if ( error )+ goto Bail;++ error = pcf_get_metric( stream,+ format & ( ~PCF_FORMAT_MASK ),+ &(accel->maxbounds) );+ if ( error )+ goto Bail;++ if ( PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )+ {+ error = pcf_get_metric( stream,+ format & ( ~PCF_FORMAT_MASK ),+ &(accel->ink_minbounds) );+ if ( error )+ goto Bail;++ error = pcf_get_metric( stream,+ format & ( ~PCF_FORMAT_MASK ),+ &(accel->ink_maxbounds) );+ if ( error )+ goto Bail;+ }+ else+ {+ accel->ink_minbounds = accel->minbounds; /* I'm not sure about this */+ accel->ink_maxbounds = accel->maxbounds;+ }++ Bail:+ return error;+ }+++ static FT_Error+ pcf_interpret_style( PCF_Face pcf )+ {+ FT_Error error = PCF_Err_Ok;+ FT_Face face = FT_FACE( pcf );+ FT_Memory memory = face->memory;++ PCF_Property prop;++ size_t nn, len;+ char* strings[4] = { NULL, NULL, NULL, NULL };+ size_t lengths[4];+++ face->style_flags = 0;++ prop = pcf_find_property( pcf, "SLANT" );+ if ( prop && prop->isString &&+ ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' ||+ *(prop->value.atom) == 'I' || *(prop->value.atom) == 'i' ) )+ {+ face->style_flags |= FT_STYLE_FLAG_ITALIC;+ strings[2] = ( *(prop->value.atom) == 'O' ||+ *(prop->value.atom) == 'o' ) ? (char *)"Oblique"+ : (char *)"Italic";+ }++ prop = pcf_find_property( pcf, "WEIGHT_NAME" );+ if ( prop && prop->isString &&+ ( *(prop->value.atom) == 'B' || *(prop->value.atom) == 'b' ) )+ {+ face->style_flags |= FT_STYLE_FLAG_BOLD;+ strings[1] = (char *)"Bold";+ }++ prop = pcf_find_property( pcf, "SETWIDTH_NAME" );+ if ( prop && prop->isString &&+ *(prop->value.atom) &&+ !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )+ strings[3] = (char *)(prop->value.atom);++ prop = pcf_find_property( pcf, "ADD_STYLE_NAME" );+ if ( prop && prop->isString &&+ *(prop->value.atom) &&+ !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )+ strings[0] = (char *)(prop->value.atom);++ for ( len = 0, nn = 0; nn < 4; nn++ )+ {+ lengths[nn] = 0;+ if ( strings[nn] )+ {+ lengths[nn] = ft_strlen( strings[nn] );+ len += lengths[nn] + 1;+ }+ }++ if ( len == 0 )+ {+ strings[0] = (char *)"Regular";+ lengths[0] = ft_strlen( strings[0] );+ len = lengths[0] + 1;+ }++ {+ char* s;+++ if ( FT_ALLOC( face->style_name, len ) )+ return error;++ s = face->style_name;++ for ( nn = 0; nn < 4; nn++ )+ {+ char* src = strings[nn];+++ len = lengths[nn];++ if ( src == NULL )+ continue;++ /* separate elements with a space */+ if ( s != face->style_name )+ *s++ = ' ';++ ft_memcpy( s, src, len );++ /* need to convert spaces to dashes for */+ /* add_style_name and setwidth_name */+ if ( nn == 0 || nn == 3 )+ {+ size_t mm;+++ for ( mm = 0; mm < len; mm++ )+ if (s[mm] == ' ')+ s[mm] = '-';+ }++ s += len;+ }+ *s = 0;+ }++ return error;+ }+++ FT_LOCAL_DEF( FT_Error )+ pcf_load_font( FT_Stream stream,+ PCF_Face face )+ {+ FT_Error error = PCF_Err_Ok;+ FT_Memory memory = FT_FACE(face)->memory;+ FT_Bool hasBDFAccelerators;+++ error = pcf_read_TOC( stream, face );+ if ( error )+ goto Exit;++ error = pcf_get_properties( stream, face );+ if ( error )+ goto Exit;++ /* Use the old accelerators if no BDF accelerators are in the file. */+ hasBDFAccelerators = pcf_has_table_type( face->toc.tables,+ face->toc.count,+ PCF_BDF_ACCELERATORS );+ if ( !hasBDFAccelerators )+ {+ error = pcf_get_accel( stream, face, PCF_ACCELERATORS );+ if ( error )+ goto Exit;+ }++ /* metrics */+ error = pcf_get_metrics( stream, face );+ if ( error )+ goto Exit;++ /* bitmaps */+ error = pcf_get_bitmaps( stream, face );+ if ( error )+ goto Exit;++ /* encodings */+ error = pcf_get_encodings( stream, face );+ if ( error )+ goto Exit;++ /* BDF style accelerators (i.e. bounds based on encoded glyphs) */+ if ( hasBDFAccelerators )+ {+ error = pcf_get_accel( stream, face, PCF_BDF_ACCELERATORS );+ if ( error )+ goto Exit;+ }++ /* XXX: TO DO: inkmetrics and glyph_names are missing */++ /* now construct the face object */+ {+ FT_Face root = FT_FACE( face );+ PCF_Property prop;+++ root->num_faces = 1;+ root->face_index = 0;+ root->face_flags = FT_FACE_FLAG_FIXED_SIZES |+ FT_FACE_FLAG_HORIZONTAL |+ FT_FACE_FLAG_FAST_GLYPHS;++ if ( face->accel.constantWidth )+ root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;++ if ( ( error = pcf_interpret_style( face ) ) != 0 )+ goto Exit;++ prop = pcf_find_property( face, "FAMILY_NAME" );+ if ( prop && prop->isString )+ {+ if ( FT_STRDUP( root->family_name, prop->value.atom ) )+ goto Exit;+ }+ else+ root->family_name = NULL;++ /*+ * Note: We shift all glyph indices by +1 since we must+ * respect the convention that glyph 0 always corresponds+ * to the `missing glyph'.+ *+ * This implies bumping the number of `available' glyphs by 1.+ */+ root->num_glyphs = face->nmetrics + 1;++ root->num_fixed_sizes = 1;+ if ( FT_NEW_ARRAY( root->available_sizes, 1 ) )+ goto Exit;++ {+ FT_Bitmap_Size* bsize = root->available_sizes;+ FT_Short resolution_x = 0, resolution_y = 0;+++ FT_MEM_ZERO( bsize, sizeof ( FT_Bitmap_Size ) );++#if 0+ bsize->height = face->accel.maxbounds.ascent << 6;+#endif+ bsize->height = (FT_Short)( face->accel.fontAscent ++ face->accel.fontDescent );++ prop = pcf_find_property( face, "AVERAGE_WIDTH" );+ if ( prop )+ bsize->width = (FT_Short)( ( prop->value.l + 5 ) / 10 );+ else+ bsize->width = (FT_Short)( bsize->height * 2/3 );++ prop = pcf_find_property( face, "POINT_SIZE" );+ if ( prop )+ /* convert from 722.7 decipoints to 72 points per inch */+ bsize->size =+ (FT_Pos)( ( prop->value.l * 64 * 7200 + 36135L ) / 72270L );++ prop = pcf_find_property( face, "PIXEL_SIZE" );+ if ( prop )+ bsize->y_ppem = (FT_Short)prop->value.l << 6;++ prop = pcf_find_property( face, "RESOLUTION_X" );+ if ( prop )+ resolution_x = (FT_Short)prop->value.l;++ prop = pcf_find_property( face, "RESOLUTION_Y" );+ if ( prop )+ resolution_y = (FT_Short)prop->value.l;++ if ( bsize->y_ppem == 0 )+ {+ bsize->y_ppem = bsize->size;+ if ( resolution_y )+ bsize->y_ppem = bsize->y_ppem * resolution_y / 72;+ }+ if ( resolution_x && resolution_y )+ bsize->x_ppem = bsize->y_ppem * resolution_x / resolution_y;+ else+ bsize->x_ppem = bsize->y_ppem;+ }++ /* set up charset */+ {+ PCF_Property charset_registry = 0, charset_encoding = 0;+++ charset_registry = pcf_find_property( face, "CHARSET_REGISTRY" );+ charset_encoding = pcf_find_property( face, "CHARSET_ENCODING" );++ if ( charset_registry && charset_registry->isString &&+ charset_encoding && charset_encoding->isString )+ {+ if ( FT_STRDUP( face->charset_encoding,+ charset_encoding->value.atom ) ||+ FT_STRDUP( face->charset_registry,+ charset_registry->value.atom ) )+ goto Exit;+ }+ }+ }++ Exit:+ if ( error )+ {+ /* This is done to respect the behaviour of the original */+ /* PCF font driver. */+ error = PCF_Err_Invalid_File_Format;+ }++ return error;+ }+++/* END */
+ src/pcf/pcfread.h view
@@ -0,0 +1,45 @@+/* pcfread.h++ FreeType font driver for pcf fonts++ Copyright 2003 by+ Francesco Zappa Nardelli++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in+all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+THE SOFTWARE.+*/+++#ifndef __PCFREAD_H__+#define __PCFREAD_H__+++#include <ft2build.h>++FT_BEGIN_HEADER++ FT_LOCAL( PCF_Property )+ pcf_find_property( PCF_Face face,+ const FT_String* prop );++FT_END_HEADER++#endif /* __PCFREAD_H__ */+++/* END */
+ src/pcf/pcfutil.c view
@@ -0,0 +1,104 @@+/*++Copyright 1990, 1994, 1998 The Open Group++Permission to use, copy, modify, distribute, and sell this software and its+documentation for any purpose is hereby granted without fee, provided that+the above copyright notice appear in all copies and that both that+copyright notice and this permission notice appear in supporting+documentation.++The above copyright notice and this permission notice shall be included in+all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.++Except as contained in this notice, the name of The Open Group shall not be+used in advertising or otherwise to promote the sale, use or other dealings+in this Software without prior written authorization from The Open Group.++*/+/* $XFree86: xc/lib/font/util/utilbitmap.c,v 1.3 1999/08/22 08:58:58 dawes Exp $ */++/*+ * Author: Keith Packard, MIT X Consortium+ */++/* Modified for use with FreeType */+++#include <ft2build.h>+#include "pcfutil.h"+++ /*+ * Invert bit order within each BYTE of an array.+ */++ FT_LOCAL_DEF( void )+ BitOrderInvert( unsigned char* buf,+ size_t nbytes )+ {+ for ( ; nbytes > 0; nbytes--, buf++ )+ {+ unsigned int val = *buf;+++ val = ( ( val >> 1 ) & 0x55 ) | ( ( val << 1 ) & 0xAA );+ val = ( ( val >> 2 ) & 0x33 ) | ( ( val << 2 ) & 0xCC );+ val = ( ( val >> 4 ) & 0x0F ) | ( ( val << 4 ) & 0xF0 );++ *buf = (unsigned char)val;+ }+ }+++ /*+ * Invert byte order within each 16-bits of an array.+ */++ FT_LOCAL_DEF( void )+ TwoByteSwap( unsigned char* buf,+ size_t nbytes )+ {+ unsigned char c;+++ for ( ; nbytes >= 2; nbytes -= 2, buf += 2 )+ {+ c = buf[0];+ buf[0] = buf[1];+ buf[1] = c;+ }+ }++ /*+ * Invert byte order within each 32-bits of an array.+ */++ FT_LOCAL_DEF( void )+ FourByteSwap( unsigned char* buf,+ size_t nbytes )+ {+ unsigned char c;+++ for ( ; nbytes >= 4; nbytes -= 4, buf += 4 )+ {+ c = buf[0];+ buf[0] = buf[3];+ buf[3] = c;++ c = buf[1];+ buf[1] = buf[2];+ buf[2] = c;+ }+ }+++/* END */
+ src/pcf/pcfutil.h view
@@ -0,0 +1,55 @@+/* pcfutil.h++ FreeType font driver for pcf fonts++ Copyright 2000, 2001, 2004 by+ Francesco Zappa Nardelli++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in+all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+THE SOFTWARE.+*/+++#ifndef __PCFUTIL_H__+#define __PCFUTIL_H__+++#include <ft2build.h>+#include FT_CONFIG_CONFIG_H+++FT_BEGIN_HEADER++ FT_LOCAL( void )+ BitOrderInvert( unsigned char* buf,+ size_t nbytes );++ FT_LOCAL( void )+ TwoByteSwap( unsigned char* buf,+ size_t nbytes );++ FT_LOCAL( void )+ FourByteSwap( unsigned char* buf,+ size_t nbytes );++FT_END_HEADER++#endif /* __PCFUTIL_H__ */+++/* END */
+ src/pfr/pfr.c view
@@ -0,0 +1,29 @@+/***************************************************************************/+/* */+/* pfr.c */+/* */+/* FreeType PFR driver component. */+/* */+/* Copyright 2002 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 "pfrload.c"+#include "pfrgload.c"+#include "pfrcmap.c"+#include "pfrobjs.c"+#include "pfrdrivr.c"+#include "pfrsbit.c"++/* END */
+ src/pfr/pfrcmap.c view
@@ -0,0 +1,166 @@+/***************************************************************************/+/* */+/* pfrcmap.c */+/* */+/* FreeType PFR cmap handling (body). */+/* */+/* Copyright 2002, 2007, 2009 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 "pfrcmap.h"+#include "pfrobjs.h"++#include "pfrerror.h"+++ FT_CALLBACK_DEF( FT_Error )+ pfr_cmap_init( PFR_CMap cmap )+ {+ FT_Error error = PFR_Err_Ok;+ PFR_Face face = (PFR_Face)FT_CMAP_FACE( cmap );+++ cmap->num_chars = face->phy_font.num_chars;+ cmap->chars = face->phy_font.chars;++ /* just for safety, check that the character entries are correctly */+ /* sorted in increasing character code order */+ {+ FT_UInt n;+++ for ( n = 1; n < cmap->num_chars; n++ )+ {+ if ( cmap->chars[n - 1].char_code >= cmap->chars[n].char_code )+ {+ error = PFR_Err_Invalid_Table;+ goto Exit;+ }+ }+ }++ Exit:+ return error;+ }+++ FT_CALLBACK_DEF( void )+ pfr_cmap_done( PFR_CMap cmap )+ {+ cmap->chars = NULL;+ cmap->num_chars = 0;+ }+++ FT_CALLBACK_DEF( FT_UInt )+ pfr_cmap_char_index( PFR_CMap cmap,+ FT_UInt32 char_code )+ {+ FT_UInt min = 0;+ FT_UInt max = cmap->num_chars;+ FT_UInt mid;+ PFR_Char gchar;+++ while ( min < max )+ {+ mid = min + ( max - min ) / 2;+ gchar = cmap->chars + mid;++ if ( gchar->char_code == char_code )+ return mid + 1;++ if ( gchar->char_code < char_code )+ min = mid + 1;+ else+ max = mid;+ }+ return 0;+ }+++ FT_CALLBACK_DEF( FT_UInt32 )+ pfr_cmap_char_next( PFR_CMap cmap,+ FT_UInt32 *pchar_code )+ {+ FT_UInt result = 0;+ FT_UInt32 char_code = *pchar_code + 1;+++ Restart:+ {+ FT_UInt min = 0;+ FT_UInt max = cmap->num_chars;+ FT_UInt mid;+ PFR_Char gchar;+++ while ( min < max )+ {+ mid = min + ( ( max - min ) >> 1 );+ gchar = cmap->chars + mid;++ if ( gchar->char_code == char_code )+ {+ result = mid;+ if ( result != 0 )+ {+ result++;+ goto Exit;+ }++ char_code++;+ goto Restart;+ }++ if ( gchar->char_code < char_code )+ min = mid+1;+ else+ max = mid;+ }++ /* we didn't find it, but we have a pair just above it */+ char_code = 0;++ if ( min < cmap->num_chars )+ {+ gchar = cmap->chars + min;+ result = min;+ if ( result != 0 )+ {+ result++;+ char_code = gchar->char_code;+ }+ }+ }++ Exit:+ *pchar_code = char_code;+ return result;+ }+++ FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec+ pfr_cmap_class_rec =+ {+ sizeof ( PFR_CMapRec ),++ (FT_CMap_InitFunc) pfr_cmap_init,+ (FT_CMap_DoneFunc) pfr_cmap_done,+ (FT_CMap_CharIndexFunc)pfr_cmap_char_index,+ (FT_CMap_CharNextFunc) pfr_cmap_char_next,++ NULL, NULL, NULL, NULL, NULL+ };+++/* END */
+ src/pfr/pfrcmap.h view
@@ -0,0 +1,46 @@+/***************************************************************************/+/* */+/* pfrcmap.h */+/* */+/* FreeType PFR cmap handling (specification). */+/* */+/* Copyright 2002 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 __PFRCMAP_H__+#define __PFRCMAP_H__++#include <ft2build.h>+#include FT_INTERNAL_OBJECTS_H+#include "pfrtypes.h"+++FT_BEGIN_HEADER++ typedef struct PFR_CMapRec_+ {+ FT_CMapRec cmap;+ FT_UInt num_chars;+ PFR_Char chars;++ } PFR_CMapRec, *PFR_CMap;+++ FT_CALLBACK_TABLE const FT_CMap_ClassRec pfr_cmap_class_rec;++FT_END_HEADER+++#endif /* __PFRCMAP_H__ */+++/* END */
+ src/pfr/pfrdrivr.c view
@@ -0,0 +1,214 @@+/***************************************************************************/+/* */+/* pfrdrivr.c */+/* */+/* FreeType PFR driver interface (body). */+/* */+/* Copyright 2002, 2003, 2004, 2006, 2008, 2010 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_STREAM_H+#include FT_SERVICE_PFR_H+#include FT_SERVICE_XFREE86_NAME_H+#include "pfrdrivr.h"+#include "pfrobjs.h"++#include "pfrerror.h"+++ FT_CALLBACK_DEF( FT_Error )+ pfr_get_kerning( FT_Face pfrface, /* PFR_Face */+ FT_UInt left,+ FT_UInt right,+ FT_Vector *avector )+ {+ PFR_Face face = (PFR_Face)pfrface;+ PFR_PhyFont phys = &face->phy_font;+++ pfr_face_get_kerning( pfrface, left, right, avector );++ /* convert from metrics to outline units when necessary */+ if ( phys->outline_resolution != phys->metrics_resolution )+ {+ if ( avector->x != 0 )+ avector->x = FT_MulDiv( avector->x, phys->outline_resolution,+ phys->metrics_resolution );++ if ( avector->y != 0 )+ avector->y = FT_MulDiv( avector->x, phys->outline_resolution,+ phys->metrics_resolution );+ }++ return PFR_Err_Ok;+ }+++ /*+ * PFR METRICS SERVICE+ *+ */++ FT_CALLBACK_DEF( FT_Error )+ pfr_get_advance( FT_Face pfrface, /* PFR_Face */+ FT_UInt gindex,+ FT_Pos *anadvance )+ {+ PFR_Face face = (PFR_Face)pfrface;+ FT_Error error = PFR_Err_Invalid_Argument;+++ *anadvance = 0;++ if ( !gindex )+ goto Exit;++ gindex--;++ if ( face )+ {+ PFR_PhyFont phys = &face->phy_font;+++ if ( gindex < phys->num_chars )+ {+ *anadvance = phys->chars[gindex].advance;+ error = PFR_Err_Ok;+ }+ }++ Exit:+ return error;+ }+++ FT_CALLBACK_DEF( FT_Error )+ pfr_get_metrics( FT_Face pfrface, /* PFR_Face */+ FT_UInt *anoutline_resolution,+ FT_UInt *ametrics_resolution,+ FT_Fixed *ametrics_x_scale,+ FT_Fixed *ametrics_y_scale )+ {+ PFR_Face face = (PFR_Face)pfrface;+ PFR_PhyFont phys = &face->phy_font;+ FT_Fixed x_scale, y_scale;+ FT_Size size = face->root.size;+++ if ( anoutline_resolution )+ *anoutline_resolution = phys->outline_resolution;++ if ( ametrics_resolution )+ *ametrics_resolution = phys->metrics_resolution;++ x_scale = 0x10000L;+ y_scale = 0x10000L;++ if ( size )+ {+ x_scale = FT_DivFix( size->metrics.x_ppem << 6,+ phys->metrics_resolution );++ y_scale = FT_DivFix( size->metrics.y_ppem << 6,+ phys->metrics_resolution );+ }++ if ( ametrics_x_scale )+ *ametrics_x_scale = x_scale;++ if ( ametrics_y_scale )+ *ametrics_y_scale = y_scale;++ return PFR_Err_Ok;+ }+++ FT_CALLBACK_TABLE_DEF+ const FT_Service_PfrMetricsRec pfr_metrics_service_rec =+ {+ pfr_get_metrics,+ pfr_face_get_kerning,+ pfr_get_advance+ };+++ /*+ * SERVICE LIST+ *+ */++ static const FT_ServiceDescRec pfr_services[] =+ {+ { FT_SERVICE_ID_PFR_METRICS, &pfr_metrics_service_rec },+ { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_PFR },+ { NULL, NULL }+ };+++ FT_CALLBACK_DEF( FT_Module_Interface )+ pfr_get_service( FT_Module module,+ const FT_String* service_id )+ {+ FT_UNUSED( module );++ return ft_service_list_lookup( pfr_services, service_id );+ }+++ FT_CALLBACK_TABLE_DEF+ const FT_Driver_ClassRec pfr_driver_class =+ {+ {+ FT_MODULE_FONT_DRIVER |+ FT_MODULE_DRIVER_SCALABLE,++ sizeof( FT_DriverRec ),++ "pfr",+ 0x10000L,+ 0x20000L,++ NULL,++ 0,+ 0,+ pfr_get_service+ },++ sizeof( PFR_FaceRec ),+ sizeof( PFR_SizeRec ),+ sizeof( PFR_SlotRec ),++ pfr_face_init,+ pfr_face_done,+ 0, /* FT_Size_InitFunc */+ 0, /* FT_Size_DoneFunc */+ pfr_slot_init,+ pfr_slot_done,++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS+ ft_stub_set_char_sizes,+ ft_stub_set_pixel_sizes,+#endif+ pfr_slot_load,++ pfr_get_kerning,+ 0, /* FT_Face_AttachFunc */+ 0, /* FT_Face_GetAdvancesFunc */+ 0, /* FT_Size_RequestFunc */+ 0, /* FT_Size_SelectFunc */+ };+++/* END */
+ src/pfr/pfrdrivr.h view
@@ -0,0 +1,43 @@+/***************************************************************************/+/* */+/* pfrdrivr.h */+/* */+/* High-level Type PFR driver interface (specification). */+/* */+/* Copyright 2002 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 __PFRDRIVR_H__+#define __PFRDRIVR_H__+++#include <ft2build.h>+#include FT_INTERNAL_DRIVER_H+++FT_BEGIN_HEADER++#ifdef FT_CONFIG_OPTION_PIC+#error "this module does not support PIC yet"+#endif +++ FT_EXPORT_VAR( const FT_Driver_ClassRec ) pfr_driver_class;+++FT_END_HEADER+++#endif /* __PFRDRIVR_H__ */+++/* END */
+ src/pfr/pfrerror.h view
@@ -0,0 +1,40 @@+/***************************************************************************/+/* */+/* pfrerror.h */+/* */+/* PFR error codes (specification only). */+/* */+/* Copyright 2002 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 PFR error enumeration constants. */+ /* */+ /*************************************************************************/++#ifndef __PFRERROR_H__+#define __PFRERROR_H__++#include FT_MODULE_ERRORS_H++#undef __FTERRORS_H__++#define FT_ERR_PREFIX PFR_Err_+#define FT_ERR_BASE FT_Mod_Err_PFR++#include FT_ERRORS_H++#endif /* __PFRERROR_H__ */+++/* END */
+ src/pfr/pfrgload.c view
@@ -0,0 +1,844 @@+/***************************************************************************/+/* */+/* pfrgload.c */+/* */+/* FreeType PFR glyph loader (body). */+/* */+/* Copyright 2002, 2003, 2005, 2007, 2010 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 "pfrgload.h"+#include "pfrsbit.h"+#include "pfrload.h" /* for macro definitions */+#include FT_INTERNAL_DEBUG_H++#include "pfrerror.h"++#undef FT_COMPONENT+#define FT_COMPONENT trace_pfr+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** PFR GLYPH BUILDER *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+++ FT_LOCAL_DEF( void )+ pfr_glyph_init( PFR_Glyph glyph,+ FT_GlyphLoader loader )+ {+ FT_ZERO( glyph );++ glyph->loader = loader;+ glyph->path_begun = 0;++ FT_GlyphLoader_Rewind( loader );+ }+++ FT_LOCAL_DEF( void )+ pfr_glyph_done( PFR_Glyph glyph )+ {+ FT_Memory memory = glyph->loader->memory;+++ FT_FREE( glyph->x_control );+ glyph->y_control = NULL;++ glyph->max_xy_control = 0;+#if 0+ glyph->num_x_control = 0;+ glyph->num_y_control = 0;+#endif++ FT_FREE( glyph->subs );++ glyph->max_subs = 0;+ glyph->num_subs = 0;++ glyph->loader = NULL;+ glyph->path_begun = 0;+ }+++ /* close current contour, if any */+ static void+ pfr_glyph_close_contour( PFR_Glyph glyph )+ {+ FT_GlyphLoader loader = glyph->loader;+ FT_Outline* outline = &loader->current.outline;+ FT_Int last, first;+++ if ( !glyph->path_begun )+ return;++ /* compute first and last point indices in current glyph outline */+ last = outline->n_points - 1;+ first = 0;+ if ( outline->n_contours > 0 )+ first = outline->contours[outline->n_contours - 1];++ /* if the last point falls on the same location than the first one */+ /* we need to delete it */+ if ( last > first )+ {+ FT_Vector* p1 = outline->points + first;+ FT_Vector* p2 = outline->points + last;+++ if ( p1->x == p2->x && p1->y == p2->y )+ {+ outline->n_points--;+ last--;+ }+ }++ /* don't add empty contours */+ if ( last >= first )+ outline->contours[outline->n_contours++] = (short)last;++ glyph->path_begun = 0;+ }+++ /* reset glyph to start the loading of a new glyph */+ static void+ pfr_glyph_start( PFR_Glyph glyph )+ {+ glyph->path_begun = 0;+ }+++ static FT_Error+ pfr_glyph_line_to( PFR_Glyph glyph,+ FT_Vector* to )+ {+ FT_GlyphLoader loader = glyph->loader;+ FT_Outline* outline = &loader->current.outline;+ FT_Error error;+++ /* check that we have begun a new path */+ if ( !glyph->path_begun )+ {+ error = PFR_Err_Invalid_Table;+ FT_ERROR(( "pfr_glyph_line_to: invalid glyph data\n" ));+ goto Exit;+ }++ error = FT_GLYPHLOADER_CHECK_POINTS( loader, 1, 0 );+ if ( !error )+ {+ FT_UInt n = outline->n_points;+++ outline->points[n] = *to;+ outline->tags [n] = FT_CURVE_TAG_ON;++ outline->n_points++;+ }++ Exit:+ return error;+ }+++ static FT_Error+ pfr_glyph_curve_to( PFR_Glyph glyph,+ FT_Vector* control1,+ FT_Vector* control2,+ FT_Vector* to )+ {+ FT_GlyphLoader loader = glyph->loader;+ FT_Outline* outline = &loader->current.outline;+ FT_Error error;+++ /* check that we have begun a new path */+ if ( !glyph->path_begun )+ {+ error = PFR_Err_Invalid_Table;+ FT_ERROR(( "pfr_glyph_line_to: invalid glyph data\n" ));+ goto Exit;+ }++ error = FT_GLYPHLOADER_CHECK_POINTS( loader, 3, 0 );+ if ( !error )+ {+ FT_Vector* vec = outline->points + outline->n_points;+ FT_Byte* tag = (FT_Byte*)outline->tags + outline->n_points;+++ vec[0] = *control1;+ vec[1] = *control2;+ vec[2] = *to;+ tag[0] = FT_CURVE_TAG_CUBIC;+ tag[1] = FT_CURVE_TAG_CUBIC;+ tag[2] = FT_CURVE_TAG_ON;++ outline->n_points = (FT_Short)( outline->n_points + 3 );+ }++ Exit:+ return error;+ }+++ static FT_Error+ pfr_glyph_move_to( PFR_Glyph glyph,+ FT_Vector* to )+ {+ FT_GlyphLoader loader = glyph->loader;+ FT_Error error;+++ /* close current contour if any */+ pfr_glyph_close_contour( glyph );++ /* indicate that a new contour has started */+ glyph->path_begun = 1;++ /* check that there is space for a new contour and a new point */+ error = FT_GLYPHLOADER_CHECK_POINTS( loader, 1, 1 );+ if ( !error )+ /* add new start point */+ error = pfr_glyph_line_to( glyph, to );++ return error;+ }+++ static void+ pfr_glyph_end( PFR_Glyph glyph )+ {+ /* close current contour if any */+ pfr_glyph_close_contour( glyph );++ /* merge the current glyph into the stack */+ FT_GlyphLoader_Add( glyph->loader );+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** PFR GLYPH LOADER *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+++ /* load a simple glyph */+ static FT_Error+ pfr_glyph_load_simple( PFR_Glyph glyph,+ FT_Byte* p,+ FT_Byte* limit )+ {+ FT_Error error = PFR_Err_Ok;+ FT_Memory memory = glyph->loader->memory;+ FT_UInt flags, x_count, y_count, i, count, mask;+ FT_Int x;+++ PFR_CHECK( 1 );+ flags = PFR_NEXT_BYTE( p );++ /* test for composite glyphs */+ if ( flags & PFR_GLYPH_IS_COMPOUND )+ goto Failure;++ x_count = 0;+ y_count = 0;++ if ( flags & PFR_GLYPH_1BYTE_XYCOUNT )+ {+ PFR_CHECK( 1 );+ count = PFR_NEXT_BYTE( p );+ x_count = count & 15;+ y_count = count >> 4;+ }+ else+ {+ if ( flags & PFR_GLYPH_XCOUNT )+ {+ PFR_CHECK( 1 );+ x_count = PFR_NEXT_BYTE( p );+ }++ if ( flags & PFR_GLYPH_YCOUNT )+ {+ PFR_CHECK( 1 );+ y_count = PFR_NEXT_BYTE( p );+ }+ }++ count = x_count + y_count;++ /* re-allocate array when necessary */+ if ( count > glyph->max_xy_control )+ {+ FT_UInt new_max = FT_PAD_CEIL( count, 8 );+++ if ( FT_RENEW_ARRAY( glyph->x_control,+ glyph->max_xy_control,+ new_max ) )+ goto Exit;++ glyph->max_xy_control = new_max;+ }++ glyph->y_control = glyph->x_control + x_count;++ mask = 0;+ x = 0;++ for ( i = 0; i < count; i++ )+ {+ if ( ( i & 7 ) == 0 )+ {+ PFR_CHECK( 1 );+ mask = PFR_NEXT_BYTE( p );+ }++ if ( mask & 1 )+ {+ PFR_CHECK( 2 );+ x = PFR_NEXT_SHORT( p );+ }+ else+ {+ PFR_CHECK( 1 );+ x += PFR_NEXT_BYTE( p );+ }++ glyph->x_control[i] = x;++ mask >>= 1;+ }++ /* XXX: for now we ignore the secondary stroke and edge definitions */+ /* since we don't want to support native PFR hinting */+ /* */+ if ( flags & PFR_GLYPH_EXTRA_ITEMS )+ {+ error = pfr_extra_items_skip( &p, limit );+ if ( error )+ goto Exit;+ }++ pfr_glyph_start( glyph );++ /* now load a simple glyph */+ {+ FT_Vector pos[4];+ FT_Vector* cur;+++ pos[0].x = pos[0].y = 0;+ pos[3] = pos[0];++ for (;;)+ {+ FT_UInt format, format_low, args_format = 0, args_count, n;+++ /***************************************************************/+ /* read instruction */+ /* */+ PFR_CHECK( 1 );+ format = PFR_NEXT_BYTE( p );+ format_low = format & 15;++ switch ( format >> 4 )+ {+ case 0: /* end glyph */+ FT_TRACE6(( "- end glyph" ));+ args_count = 0;+ break;++ case 1: /* general line operation */+ FT_TRACE6(( "- general line" ));+ goto Line1;++ case 4: /* move to inside contour */+ FT_TRACE6(( "- move to inside" ));+ goto Line1;++ case 5: /* move to outside contour */+ FT_TRACE6(( "- move to outside" ));+ Line1:+ args_format = format_low;+ args_count = 1;+ break;++ case 2: /* horizontal line to */+ FT_TRACE6(( "- horizontal line to cx.%d", format_low ));+ if ( format_low >= x_count )+ goto Failure;+ pos[0].x = glyph->x_control[format_low];+ pos[0].y = pos[3].y;+ pos[3] = pos[0];+ args_count = 0;+ break;++ case 3: /* vertical line to */+ FT_TRACE6(( "- vertical line to cy.%d", format_low ));+ if ( format_low >= y_count )+ goto Failure;+ pos[0].x = pos[3].x;+ pos[0].y = glyph->y_control[format_low];+ pos[3] = pos[0];+ args_count = 0;+ break;++ case 6: /* horizontal to vertical curve */+ FT_TRACE6(( "- hv curve " ));+ args_format = 0xB8E;+ args_count = 3;+ break;++ case 7: /* vertical to horizontal curve */+ FT_TRACE6(( "- vh curve" ));+ args_format = 0xE2B;+ args_count = 3;+ break;++ default: /* general curve to */+ FT_TRACE6(( "- general curve" ));+ args_count = 4;+ args_format = format_low;+ }++ /***********************************************************/+ /* now read arguments */+ /* */+ cur = pos;+ for ( n = 0; n < args_count; n++ )+ {+ FT_UInt idx;+ FT_Int delta;+++ /* read the X argument */+ switch ( args_format & 3 )+ {+ case 0: /* 8-bit index */+ PFR_CHECK( 1 );+ idx = PFR_NEXT_BYTE( p );+ if ( idx >= x_count )+ goto Failure;+ cur->x = glyph->x_control[idx];+ FT_TRACE7(( " cx#%d", idx ));+ break;++ case 1: /* 16-bit value */+ PFR_CHECK( 2 );+ cur->x = PFR_NEXT_SHORT( p );+ FT_TRACE7(( " x.%d", cur->x ));+ break;++ case 2: /* 8-bit delta */+ PFR_CHECK( 1 );+ delta = PFR_NEXT_INT8( p );+ cur->x = pos[3].x + delta;+ FT_TRACE7(( " dx.%d", delta ));+ break;++ default:+ FT_TRACE7(( " |" ));+ cur->x = pos[3].x;+ }++ /* read the Y argument */+ switch ( ( args_format >> 2 ) & 3 )+ {+ case 0: /* 8-bit index */+ PFR_CHECK( 1 );+ idx = PFR_NEXT_BYTE( p );+ if ( idx >= y_count )+ goto Failure;+ cur->y = glyph->y_control[idx];+ FT_TRACE7(( " cy#%d", idx ));+ break;++ case 1: /* 16-bit absolute value */+ PFR_CHECK( 2 );+ cur->y = PFR_NEXT_SHORT( p );+ FT_TRACE7(( " y.%d", cur->y ));+ break;++ case 2: /* 8-bit delta */+ PFR_CHECK( 1 );+ delta = PFR_NEXT_INT8( p );+ cur->y = pos[3].y + delta;+ FT_TRACE7(( " dy.%d", delta ));+ break;++ default:+ FT_TRACE7(( " -" ));+ cur->y = pos[3].y;+ }++ /* read the additional format flag for the general curve */+ if ( n == 0 && args_count == 4 )+ {+ PFR_CHECK( 1 );+ args_format = PFR_NEXT_BYTE( p );+ args_count--;+ }+ else+ args_format >>= 4;++ /* save the previous point */+ pos[3] = cur[0];+ cur++;+ }++ FT_TRACE7(( "\n" ));++ /***********************************************************/+ /* finally, execute instruction */+ /* */+ switch ( format >> 4 )+ {+ case 0: /* end glyph => EXIT */+ pfr_glyph_end( glyph );+ goto Exit;++ case 1: /* line operations */+ case 2:+ case 3:+ error = pfr_glyph_line_to( glyph, pos );+ goto Test_Error;++ case 4: /* move to inside contour */+ case 5: /* move to outside contour */+ error = pfr_glyph_move_to( glyph, pos );+ goto Test_Error;++ default: /* curve operations */+ error = pfr_glyph_curve_to( glyph, pos, pos + 1, pos + 2 );++ Test_Error: /* test error condition */+ if ( error )+ goto Exit;+ }+ } /* for (;;) */+ }++ Exit:+ return error;++ Failure:+ Too_Short:+ error = PFR_Err_Invalid_Table;+ FT_ERROR(( "pfr_glyph_load_simple: invalid glyph data\n" ));+ goto Exit;+ }+++ /* load a composite/compound glyph */+ static FT_Error+ pfr_glyph_load_compound( PFR_Glyph glyph,+ FT_Byte* p,+ FT_Byte* limit )+ {+ FT_Error error = PFR_Err_Ok;+ FT_GlyphLoader loader = glyph->loader;+ FT_Memory memory = loader->memory;+ PFR_SubGlyph subglyph;+ FT_UInt flags, i, count, org_count;+ FT_Int x_pos, y_pos;+++ PFR_CHECK( 1 );+ flags = PFR_NEXT_BYTE( p );++ /* test for composite glyphs */+ if ( !( flags & PFR_GLYPH_IS_COMPOUND ) )+ goto Failure;++ count = flags & 0x3F;++ /* ignore extra items when present */+ /* */+ if ( flags & PFR_GLYPH_EXTRA_ITEMS )+ {+ error = pfr_extra_items_skip( &p, limit );+ if (error) goto Exit;+ }++ /* we can't rely on the FT_GlyphLoader to load sub-glyphs, because */+ /* the PFR format is dumb, using direct file offsets to point to the */+ /* sub-glyphs (instead of glyph indices). Sigh. */+ /* */+ /* For now, we load the list of sub-glyphs into a different array */+ /* but this will prevent us from using the auto-hinter at its best */+ /* quality. */+ /* */+ org_count = glyph->num_subs;++ if ( org_count + count > glyph->max_subs )+ {+ FT_UInt new_max = ( org_count + count + 3 ) & (FT_UInt)-4;+++ /* we arbitrarily limit the number of subglyphs */+ /* to avoid endless recursion */+ if ( new_max > 64 )+ {+ error = PFR_Err_Invalid_Table;+ FT_ERROR(( "pfr_glyph_load_compound:"+ " too many compound glyphs components\n" ));+ goto Exit;+ }++ if ( FT_RENEW_ARRAY( glyph->subs, glyph->max_subs, new_max ) )+ goto Exit;++ glyph->max_subs = new_max;+ }++ subglyph = glyph->subs + org_count;++ for ( i = 0; i < count; i++, subglyph++ )+ {+ FT_UInt format;+++ x_pos = 0;+ y_pos = 0;++ PFR_CHECK( 1 );+ format = PFR_NEXT_BYTE( p );++ /* read scale when available */+ subglyph->x_scale = 0x10000L;+ if ( format & PFR_SUBGLYPH_XSCALE )+ {+ PFR_CHECK( 2 );+ subglyph->x_scale = PFR_NEXT_SHORT( p ) << 4;+ }++ subglyph->y_scale = 0x10000L;+ if ( format & PFR_SUBGLYPH_YSCALE )+ {+ PFR_CHECK( 2 );+ subglyph->y_scale = PFR_NEXT_SHORT( p ) << 4;+ }++ /* read offset */+ switch ( format & 3 )+ {+ case 1:+ PFR_CHECK( 2 );+ x_pos = PFR_NEXT_SHORT( p );+ break;++ case 2:+ PFR_CHECK( 1 );+ x_pos += PFR_NEXT_INT8( p );+ break;++ default:+ ;+ }++ switch ( ( format >> 2 ) & 3 )+ {+ case 1:+ PFR_CHECK( 2 );+ y_pos = PFR_NEXT_SHORT( p );+ break;++ case 2:+ PFR_CHECK( 1 );+ y_pos += PFR_NEXT_INT8( p );+ break;++ default:+ ;+ }++ subglyph->x_delta = x_pos;+ subglyph->y_delta = y_pos;++ /* read glyph position and size now */+ if ( format & PFR_SUBGLYPH_2BYTE_SIZE )+ {+ PFR_CHECK( 2 );+ subglyph->gps_size = PFR_NEXT_USHORT( p );+ }+ else+ {+ PFR_CHECK( 1 );+ subglyph->gps_size = PFR_NEXT_BYTE( p );+ }++ if ( format & PFR_SUBGLYPH_3BYTE_OFFSET )+ {+ PFR_CHECK( 3 );+ subglyph->gps_offset = PFR_NEXT_LONG( p );+ }+ else+ {+ PFR_CHECK( 2 );+ subglyph->gps_offset = PFR_NEXT_USHORT( p );+ }++ glyph->num_subs++;+ }++ Exit:+ return error;++ Failure:+ Too_Short:+ error = PFR_Err_Invalid_Table;+ FT_ERROR(( "pfr_glyph_load_compound: invalid glyph data\n" ));+ goto Exit;+ }+++ static FT_Error+ pfr_glyph_load_rec( PFR_Glyph glyph,+ FT_Stream stream,+ FT_ULong gps_offset,+ FT_ULong offset,+ FT_ULong size )+ {+ FT_Error error;+ FT_Byte* p;+ FT_Byte* limit;+++ if ( FT_STREAM_SEEK( gps_offset + offset ) ||+ FT_FRAME_ENTER( size ) )+ goto Exit;++ p = (FT_Byte*)stream->cursor;+ limit = p + size;++ if ( size > 0 && *p & PFR_GLYPH_IS_COMPOUND )+ {+ FT_Int n, old_count, count;+ FT_GlyphLoader loader = glyph->loader;+ FT_Outline* base = &loader->base.outline;+++ old_count = glyph->num_subs;++ /* this is a compound glyph - load it */+ error = pfr_glyph_load_compound( glyph, p, limit );++ FT_FRAME_EXIT();++ if ( error )+ goto Exit;++ count = glyph->num_subs - old_count;++ FT_TRACE4(( "compound glyph with %d elements (offset %lu):\n",+ count, offset ));++ /* now, load each individual glyph */+ for ( n = 0; n < count; n++ )+ {+ FT_Int i, old_points, num_points;+ PFR_SubGlyph subglyph;+++ FT_TRACE4(( "subglyph %d:\n", n ));++ subglyph = glyph->subs + old_count + n;+ old_points = base->n_points;++ error = pfr_glyph_load_rec( glyph, stream, gps_offset,+ subglyph->gps_offset,+ subglyph->gps_size );+ if ( error )+ break;++ /* note that `glyph->subs' might have been re-allocated */+ subglyph = glyph->subs + old_count + n;+ num_points = base->n_points - old_points;++ /* translate and eventually scale the new glyph points */+ if ( subglyph->x_scale != 0x10000L || subglyph->y_scale != 0x10000L )+ {+ FT_Vector* vec = base->points + old_points;+++ for ( i = 0; i < num_points; i++, vec++ )+ {+ vec->x = FT_MulFix( vec->x, subglyph->x_scale ) ++ subglyph->x_delta;+ vec->y = FT_MulFix( vec->y, subglyph->y_scale ) ++ subglyph->y_delta;+ }+ }+ else+ {+ FT_Vector* vec = loader->base.outline.points + old_points;+++ for ( i = 0; i < num_points; i++, vec++ )+ {+ vec->x += subglyph->x_delta;+ vec->y += subglyph->y_delta;+ }+ }++ /* proceed to next sub-glyph */+ }++ FT_TRACE4(( "end compound glyph with %d elements\n", count ));+ }+ else+ {+ FT_TRACE4(( "simple glyph (offset %lu)\n", offset ));++ /* load a simple glyph */+ error = pfr_glyph_load_simple( glyph, p, limit );++ FT_FRAME_EXIT();+ }++ Exit:+ return error;+ }+++ FT_LOCAL_DEF( FT_Error )+ pfr_glyph_load( PFR_Glyph glyph,+ FT_Stream stream,+ FT_ULong gps_offset,+ FT_ULong offset,+ FT_ULong size )+ {+ /* initialize glyph loader */+ FT_GlyphLoader_Rewind( glyph->loader );++ glyph->num_subs = 0;++ /* load the glyph, recursively when needed */+ return pfr_glyph_load_rec( glyph, stream, gps_offset, offset, size );+ }+++/* END */
+ src/pfr/pfrgload.h view
@@ -0,0 +1,49 @@+/***************************************************************************/+/* */+/* pfrgload.h */+/* */+/* FreeType PFR glyph loader (specification). */+/* */+/* Copyright 2002 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 __PFRGLOAD_H__+#define __PFRGLOAD_H__++#include "pfrtypes.h"++FT_BEGIN_HEADER+++ FT_LOCAL( void )+ pfr_glyph_init( PFR_Glyph glyph,+ FT_GlyphLoader loader );++ FT_LOCAL( void )+ pfr_glyph_done( PFR_Glyph glyph );+++ FT_LOCAL( FT_Error )+ pfr_glyph_load( PFR_Glyph glyph,+ FT_Stream stream,+ FT_ULong gps_offset,+ FT_ULong offset,+ FT_ULong size );+++FT_END_HEADER+++#endif /* __PFRGLOAD_H__ */+++/* END */
+ src/pfr/pfrload.c view
@@ -0,0 +1,941 @@+/***************************************************************************/+/* */+/* pfrload.c */+/* */+/* FreeType PFR loader (body). */+/* */+/* Copyright 2002, 2003, 2004, 2005, 2007, 2009, 2010 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 = PFR_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 = PFR_Err_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_UInt *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 = 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 PFR_Err_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 = PFR_Err_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 = PFR_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 = PFR_Err_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 = PFR_Err_Ok;+ FT_Memory memory = phy_font->memory;+ FT_PtrDist len = 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;+ FT_Error error = PFR_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 = PFR_Err_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 = PFR_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 + ( 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 = PFR_Err_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 = PFR_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 );+ q += 16;+ 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 + ( 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 )+ : (FT_Int) 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 = PFR_Err_Invalid_Table;+ FT_ERROR(( "pfr_phy_font_load: invalid physical font table\n" ));+ goto Fail;+ }+++/* END */
+ src/pfr/pfrload.h view
@@ -0,0 +1,118 @@+/***************************************************************************/+/* */+/* pfrload.h */+/* */+/* FreeType PFR loader (specification). */+/* */+/* Copyright 2002 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 __PFRLOAD_H__+#define __PFRLOAD_H__++#include "pfrobjs.h"+#include FT_INTERNAL_STREAM_H+++FT_BEGIN_HEADER++#ifdef PFR_CONFIG_NO_CHECKS+#define PFR_CHECK( x ) do { } while ( 0 )+#else+#define PFR_CHECK( x ) do \+ { \+ if ( p + (x) > limit ) \+ goto Too_Short; \+ } while ( 0 )+#endif++#define PFR_NEXT_BYTE( p ) FT_NEXT_BYTE( p )+#define PFR_NEXT_INT8( p ) FT_NEXT_CHAR( p )+#define PFR_NEXT_SHORT( p ) FT_NEXT_SHORT( p )+#define PFR_NEXT_USHORT( p ) FT_NEXT_USHORT( p )+#define PFR_NEXT_LONG( p ) FT_NEXT_OFF3( p )+#define PFR_NEXT_ULONG( p ) FT_NEXT_UOFF3( p )+++ /* handling extra items */++ typedef FT_Error+ (*PFR_ExtraItem_ParseFunc)( FT_Byte* p,+ FT_Byte* limit,+ FT_Pointer data );++ typedef struct PFR_ExtraItemRec_+ {+ FT_UInt type;+ PFR_ExtraItem_ParseFunc parser;++ } PFR_ExtraItemRec;++ typedef const struct PFR_ExtraItemRec_* PFR_ExtraItem;+++ FT_LOCAL( FT_Error )+ pfr_extra_items_skip( FT_Byte* *pp,+ FT_Byte* limit );++ FT_LOCAL( FT_Error )+ pfr_extra_items_parse( FT_Byte* *pp,+ FT_Byte* limit,+ PFR_ExtraItem item_list,+ FT_Pointer item_data );+++ /* load a PFR header */+ FT_LOCAL( FT_Error )+ pfr_header_load( PFR_Header header,+ FT_Stream stream );++ /* check a PFR header */+ FT_LOCAL( FT_Bool )+ pfr_header_check( PFR_Header header );+++ /* return number of logical fonts in this file */+ FT_LOCAL( FT_Error )+ pfr_log_font_count( FT_Stream stream,+ FT_UInt32 log_section_offset,+ FT_UInt *acount );++ /* load a pfr logical font entry */+ FT_LOCAL( FT_Error )+ pfr_log_font_load( PFR_LogFont log_font,+ FT_Stream stream,+ FT_UInt face_index,+ FT_UInt32 section_offset,+ FT_Bool size_increment );+++ /* load a physical font entry */+ FT_LOCAL( FT_Error )+ pfr_phy_font_load( PFR_PhyFont phy_font,+ FT_Stream stream,+ FT_UInt32 offset,+ FT_UInt32 size );++ /* finalize a physical font */+ FT_LOCAL( void )+ pfr_phy_font_done( PFR_PhyFont phy_font,+ FT_Memory memory );++ /* */++FT_END_HEADER++#endif /* __PFRLOAD_H__ */+++/* END */
+ src/pfr/pfrobjs.c view
@@ -0,0 +1,591 @@+/***************************************************************************/+/* */+/* pfrobjs.c */+/* */+/* FreeType PFR object methods (body). */+/* */+/* Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 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 "pfrobjs.h"+#include "pfrload.h"+#include "pfrgload.h"+#include "pfrcmap.h"+#include "pfrsbit.h"+#include FT_OUTLINE_H+#include FT_INTERNAL_DEBUG_H+#include FT_TRUETYPE_IDS_H ++#include "pfrerror.h"++#undef FT_COMPONENT+#define FT_COMPONENT trace_pfr+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** FACE OBJECT METHODS *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ FT_LOCAL_DEF( void )+ pfr_face_done( FT_Face pfrface ) /* PFR_Face */+ {+ PFR_Face face = (PFR_Face)pfrface;+ FT_Memory memory;+++ if ( !face )+ return;++ memory = pfrface->driver->root.memory;++ /* we don't want dangling pointers */+ pfrface->family_name = NULL;+ pfrface->style_name = NULL;++ /* finalize the physical font record */+ pfr_phy_font_done( &face->phy_font, FT_FACE_MEMORY( face ) );++ /* no need to finalize the logical font or the header */+ FT_FREE( pfrface->available_sizes );+ }+++ FT_LOCAL_DEF( FT_Error )+ pfr_face_init( FT_Stream stream,+ FT_Face pfrface,+ FT_Int face_index,+ FT_Int num_params,+ FT_Parameter* params )+ {+ PFR_Face face = (PFR_Face)pfrface;+ FT_Error error;++ FT_UNUSED( num_params );+ FT_UNUSED( params );+++ /* load the header and check it */+ error = pfr_header_load( &face->header, stream );+ if ( error )+ goto Exit;++ if ( !pfr_header_check( &face->header ) )+ {+ FT_TRACE4(( "pfr_face_init: not a valid PFR font\n" ));+ error = PFR_Err_Unknown_File_Format;+ goto Exit;+ }++ /* check face index */+ {+ FT_UInt num_faces;+++ error = pfr_log_font_count( stream,+ face->header.log_dir_offset,+ &num_faces );+ if ( error )+ goto Exit;++ pfrface->num_faces = num_faces;+ }++ if ( face_index < 0 )+ goto Exit;++ if ( face_index >= pfrface->num_faces )+ {+ FT_ERROR(( "pfr_face_init: invalid face index\n" ));+ error = PFR_Err_Invalid_Argument;+ goto Exit;+ }++ /* load the face */+ error = pfr_log_font_load(+ &face->log_font, stream, face_index,+ face->header.log_dir_offset,+ FT_BOOL( face->header.phy_font_max_size_high != 0 ) );+ if ( error )+ goto Exit;++ /* now load the physical font descriptor */+ error = pfr_phy_font_load( &face->phy_font, stream,+ face->log_font.phys_offset,+ face->log_font.phys_size );+ if ( error )+ goto Exit;++ /* now set up all root face fields */+ {+ PFR_PhyFont phy_font = &face->phy_font;+++ pfrface->face_index = face_index;+ pfrface->num_glyphs = phy_font->num_chars + 1;+ pfrface->face_flags = FT_FACE_FLAG_SCALABLE;++ /* if all characters point to the same gps_offset 0, we */+ /* assume that the font only contains bitmaps */+ {+ FT_UInt nn;+++ for ( nn = 0; nn < phy_font->num_chars; nn++ )+ if ( phy_font->chars[nn].gps_offset != 0 )+ break;++ if ( nn == phy_font->num_chars )+ {+ if ( phy_font->num_strikes > 0 )+ pfrface->face_flags = 0; /* not scalable */+ else+ {+ FT_ERROR(( "pfr_face_init: font doesn't contain glyphs\n" ));+ error = PFR_Err_Invalid_File_Format;+ goto Exit;+ }+ }+ }++ if ( (phy_font->flags & PFR_PHY_PROPORTIONAL) == 0 )+ pfrface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;++ if ( phy_font->flags & PFR_PHY_VERTICAL )+ pfrface->face_flags |= FT_FACE_FLAG_VERTICAL;+ else+ pfrface->face_flags |= FT_FACE_FLAG_HORIZONTAL;++ if ( phy_font->num_strikes > 0 )+ pfrface->face_flags |= FT_FACE_FLAG_FIXED_SIZES;++ if ( phy_font->num_kern_pairs > 0 )+ pfrface->face_flags |= FT_FACE_FLAG_KERNING;++ /* If no family name was found in the "undocumented" auxiliary+ * data, use the font ID instead. This sucks but is better than+ * nothing.+ */+ pfrface->family_name = phy_font->family_name;+ if ( pfrface->family_name == NULL )+ pfrface->family_name = phy_font->font_id;++ /* note that the style name can be NULL in certain PFR fonts,+ * probably meaning "Regular"+ */+ pfrface->style_name = phy_font->style_name;++ pfrface->num_fixed_sizes = 0;+ pfrface->available_sizes = 0;++ pfrface->bbox = phy_font->bbox;+ pfrface->units_per_EM = (FT_UShort)phy_font->outline_resolution;+ pfrface->ascender = (FT_Short) phy_font->bbox.yMax;+ pfrface->descender = (FT_Short) phy_font->bbox.yMin;++ pfrface->height = (FT_Short)( ( pfrface->units_per_EM * 12 ) / 10 );+ if ( pfrface->height < pfrface->ascender - pfrface->descender )+ pfrface->height = (FT_Short)(pfrface->ascender - pfrface->descender);++ if ( phy_font->num_strikes > 0 )+ {+ FT_UInt n, count = phy_font->num_strikes;+ FT_Bitmap_Size* size;+ PFR_Strike strike;+ FT_Memory memory = pfrface->stream->memory;+++ if ( FT_NEW_ARRAY( pfrface->available_sizes, count ) )+ goto Exit;++ size = pfrface->available_sizes;+ strike = phy_font->strikes;+ for ( n = 0; n < count; n++, size++, strike++ )+ {+ size->height = (FT_UShort)strike->y_ppm;+ size->width = (FT_UShort)strike->x_ppm;+ size->size = strike->y_ppm << 6;+ size->x_ppem = strike->x_ppm << 6;+ size->y_ppem = strike->y_ppm << 6;+ }+ pfrface->num_fixed_sizes = count;+ }++ /* now compute maximum advance width */+ if ( ( phy_font->flags & PFR_PHY_PROPORTIONAL ) == 0 )+ pfrface->max_advance_width = (FT_Short)phy_font->standard_advance;+ else+ {+ FT_Int max = 0;+ FT_UInt count = phy_font->num_chars;+ PFR_Char gchar = phy_font->chars;+++ for ( ; count > 0; count--, gchar++ )+ {+ if ( max < gchar->advance )+ max = gchar->advance;+ }++ pfrface->max_advance_width = (FT_Short)max;+ }++ pfrface->max_advance_height = pfrface->height;++ pfrface->underline_position = (FT_Short)( -pfrface->units_per_EM / 10 );+ pfrface->underline_thickness = (FT_Short)( pfrface->units_per_EM / 30 );++ /* create charmap */+ {+ FT_CharMapRec charmap;+++ charmap.face = pfrface;+ charmap.platform_id = TT_PLATFORM_MICROSOFT;+ charmap.encoding_id = TT_MS_ID_UNICODE_CS;+ charmap.encoding = FT_ENCODING_UNICODE;++ error = FT_CMap_New( &pfr_cmap_class_rec, NULL, &charmap, NULL );++#if 0+ /* Select default charmap */+ if ( pfrface->num_charmaps )+ pfrface->charmap = pfrface->charmaps[0];+#endif+ }++ /* check whether we've loaded any kerning pairs */+ if ( phy_font->num_kern_pairs )+ pfrface->face_flags |= FT_FACE_FLAG_KERNING;+ }++ Exit:+ return error;+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** SLOT OBJECT METHOD *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ FT_LOCAL_DEF( FT_Error )+ pfr_slot_init( FT_GlyphSlot pfrslot ) /* PFR_Slot */+ {+ PFR_Slot slot = (PFR_Slot)pfrslot;+ FT_GlyphLoader loader = pfrslot->internal->loader;+++ pfr_glyph_init( &slot->glyph, loader );++ return 0;+ }+++ FT_LOCAL_DEF( void )+ pfr_slot_done( FT_GlyphSlot pfrslot ) /* PFR_Slot */+ {+ PFR_Slot slot = (PFR_Slot)pfrslot;+++ pfr_glyph_done( &slot->glyph );+ }+++ FT_LOCAL_DEF( FT_Error )+ pfr_slot_load( FT_GlyphSlot pfrslot, /* PFR_Slot */+ FT_Size pfrsize, /* PFR_Size */+ FT_UInt gindex,+ FT_Int32 load_flags )+ {+ PFR_Slot slot = (PFR_Slot)pfrslot;+ PFR_Size size = (PFR_Size)pfrsize;+ FT_Error error;+ PFR_Face face = (PFR_Face)pfrslot->face;+ PFR_Char gchar;+ FT_Outline* outline = &pfrslot->outline;+ FT_ULong gps_offset;+++ if ( gindex > 0 )+ gindex--;++ if ( !face || gindex >= face->phy_font.num_chars )+ {+ error = PFR_Err_Invalid_Argument;+ goto Exit;+ }++ /* try to load an embedded bitmap */+ if ( ( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP ) ) == 0 )+ {+ error = pfr_slot_load_bitmap( slot, size, gindex );+ if ( error == 0 )+ goto Exit;+ }++ if ( load_flags & FT_LOAD_SBITS_ONLY )+ {+ error = PFR_Err_Invalid_Argument;+ goto Exit;+ }++ gchar = face->phy_font.chars + gindex;+ pfrslot->format = FT_GLYPH_FORMAT_OUTLINE;+ outline->n_points = 0;+ outline->n_contours = 0;+ gps_offset = face->header.gps_section_offset;++ /* load the glyph outline (FT_LOAD_NO_RECURSE isn't supported) */+ error = pfr_glyph_load( &slot->glyph, face->root.stream,+ gps_offset, gchar->gps_offset, gchar->gps_size );++ if ( !error )+ {+ FT_BBox cbox;+ FT_Glyph_Metrics* metrics = &pfrslot->metrics;+ FT_Pos advance;+ FT_Int em_metrics, em_outline;+ FT_Bool scaling;+++ scaling = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 );++ /* copy outline data */+ *outline = slot->glyph.loader->base.outline;++ outline->flags &= ~FT_OUTLINE_OWNER;+ outline->flags |= FT_OUTLINE_REVERSE_FILL;++ if ( size && pfrsize->metrics.y_ppem < 24 )+ outline->flags |= FT_OUTLINE_HIGH_PRECISION;++ /* compute the advance vector */+ metrics->horiAdvance = 0;+ metrics->vertAdvance = 0;++ advance = gchar->advance;+ em_metrics = face->phy_font.metrics_resolution;+ em_outline = face->phy_font.outline_resolution;++ if ( em_metrics != em_outline )+ advance = FT_MulDiv( advance, em_outline, em_metrics );++ if ( face->phy_font.flags & PFR_PHY_VERTICAL )+ metrics->vertAdvance = advance;+ else+ metrics->horiAdvance = advance;++ pfrslot->linearHoriAdvance = metrics->horiAdvance;+ pfrslot->linearVertAdvance = metrics->vertAdvance;++ /* make-up vertical metrics(?) */+ metrics->vertBearingX = 0;+ metrics->vertBearingY = 0;++#if 0 /* some fonts seem to be broken here! */++ /* Apply the font matrix, if any. */+ /* TODO: Test existing fonts with unusual matrix */+ /* whether we have to adjust Units per EM. */+ {+ FT_Matrix font_matrix;+++ font_matrix.xx = face->log_font.matrix[0] << 8;+ font_matrix.yx = face->log_font.matrix[1] << 8;+ font_matrix.xy = face->log_font.matrix[2] << 8;+ font_matrix.yy = face->log_font.matrix[3] << 8;++ FT_Outline_Transform( outline, &font_matrix );+ }+#endif++ /* scale when needed */+ if ( scaling )+ {+ FT_Int n;+ FT_Fixed x_scale = pfrsize->metrics.x_scale;+ FT_Fixed y_scale = pfrsize->metrics.y_scale;+ FT_Vector* vec = outline->points;+++ /* scale outline points */+ for ( n = 0; n < outline->n_points; n++, vec++ )+ {+ vec->x = FT_MulFix( vec->x, x_scale );+ vec->y = FT_MulFix( vec->y, y_scale );+ }++ /* scale the advance */+ metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );+ metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );+ }++ /* compute the rest of the metrics */+ FT_Outline_Get_CBox( outline, &cbox );++ metrics->width = cbox.xMax - cbox.xMin;+ metrics->height = cbox.yMax - cbox.yMin;+ metrics->horiBearingX = cbox.xMin;+ metrics->horiBearingY = cbox.yMax - metrics->height;+ }++ Exit:+ return error;+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** KERNING METHOD *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ FT_LOCAL_DEF( FT_Error )+ pfr_face_get_kerning( FT_Face pfrface, /* PFR_Face */+ FT_UInt glyph1,+ FT_UInt glyph2,+ FT_Vector* kerning )+ {+ PFR_Face face = (PFR_Face)pfrface;+ FT_Error error = PFR_Err_Ok;+ PFR_PhyFont phy_font = &face->phy_font;+ FT_UInt32 code1, code2, pair;+++ kerning->x = 0;+ kerning->y = 0;++ if ( glyph1 > 0 )+ glyph1--;++ if ( glyph2 > 0 )+ glyph2--;++ /* convert glyph indices to character codes */+ if ( glyph1 > phy_font->num_chars ||+ glyph2 > phy_font->num_chars )+ goto Exit;++ code1 = phy_font->chars[glyph1].char_code;+ code2 = phy_font->chars[glyph2].char_code;+ pair = PFR_KERN_INDEX( code1, code2 );++ /* now search the list of kerning items */+ {+ PFR_KernItem item = phy_font->kern_items;+ FT_Stream stream = pfrface->stream;+++ for ( ; item; item = item->next )+ {+ if ( pair >= item->pair1 && pair <= item->pair2 )+ goto FoundPair;+ }+ goto Exit;++ FoundPair: /* we found an item, now parse it and find the value if any */+ if ( FT_STREAM_SEEK( item->offset ) ||+ FT_FRAME_ENTER( item->pair_count * item->pair_size ) )+ goto Exit;++ {+ FT_UInt count = item->pair_count;+ FT_UInt size = item->pair_size;+ FT_UInt power = (FT_UInt)ft_highpow2( (FT_UInt32)count );+ FT_UInt probe = power * size;+ FT_UInt extra = count - power;+ FT_Byte* base = stream->cursor;+ FT_Bool twobytes = FT_BOOL( item->flags & 1 );+ FT_Bool twobyte_adj = FT_BOOL( item->flags & 2 );+ FT_Byte* p;+ FT_UInt32 cpair;+++ if ( extra > 0 )+ {+ p = base + extra * size;++ if ( twobytes )+ cpair = FT_NEXT_ULONG( p );+ else+ cpair = PFR_NEXT_KPAIR( p );++ if ( cpair == pair )+ goto Found;++ if ( cpair < pair )+ {+ if ( twobyte_adj )+ p += 2;+ else+ p++;+ base = p;+ }+ }++ while ( probe > size )+ {+ probe >>= 1;+ p = base + probe;++ if ( twobytes )+ cpair = FT_NEXT_ULONG( p );+ else+ cpair = PFR_NEXT_KPAIR( p );++ if ( cpair == pair )+ goto Found;++ if ( cpair < pair )+ base += probe;+ }++ p = base;++ if ( twobytes )+ cpair = FT_NEXT_ULONG( p );+ else+ cpair = PFR_NEXT_KPAIR( p );++ if ( cpair == pair )+ {+ FT_Int value;+++ Found:+ if ( twobyte_adj )+ value = FT_PEEK_SHORT( p );+ else+ value = p[0];++ kerning->x = item->base_adj + value;+ }+ }++ FT_FRAME_EXIT();+ }++ Exit:+ return error;+ }++/* END */
+ src/pfr/pfrobjs.h view
@@ -0,0 +1,96 @@+/***************************************************************************/+/* */+/* pfrobjs.h */+/* */+/* FreeType PFR object methods (specification). */+/* */+/* Copyright 2002, 2003, 2004 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 __PFROBJS_H__+#define __PFROBJS_H__++#include "pfrtypes.h"+++FT_BEGIN_HEADER++ typedef struct PFR_FaceRec_* PFR_Face;++ typedef struct PFR_SizeRec_* PFR_Size;++ typedef struct PFR_SlotRec_* PFR_Slot;+++ typedef struct PFR_FaceRec_+ {+ FT_FaceRec root;+ PFR_HeaderRec header;+ PFR_LogFontRec log_font;+ PFR_PhyFontRec phy_font;++ } PFR_FaceRec;+++ typedef struct PFR_SizeRec_+ {+ FT_SizeRec root;++ } PFR_SizeRec;+++ typedef struct PFR_SlotRec_+ {+ FT_GlyphSlotRec root;+ PFR_GlyphRec glyph;++ } PFR_SlotRec;+++ FT_LOCAL( FT_Error )+ pfr_face_init( FT_Stream stream,+ FT_Face face, /* PFR_Face */+ FT_Int face_index,+ FT_Int num_params,+ FT_Parameter* params );++ FT_LOCAL( void )+ pfr_face_done( FT_Face face ); /* PFR_Face */+++ FT_LOCAL( FT_Error )+ pfr_face_get_kerning( FT_Face face, /* PFR_Face */+ FT_UInt glyph1,+ FT_UInt glyph2,+ FT_Vector* kerning );+++ FT_LOCAL( FT_Error )+ pfr_slot_init( FT_GlyphSlot slot ); /* PFR_Slot */++ FT_LOCAL( void )+ pfr_slot_done( FT_GlyphSlot slot ); /* PFR_Slot */+++ FT_LOCAL( FT_Error )+ pfr_slot_load( FT_GlyphSlot slot, /* PFR_Slot */+ FT_Size size, /* PFR_Size */+ FT_UInt gindex,+ FT_Int32 load_flags );+++FT_END_HEADER++#endif /* __PFROBJS_H__ */+++/* END */
+ src/pfr/pfrsbit.c view
@@ -0,0 +1,698 @@+/***************************************************************************/+/* */+/* pfrsbit.c */+/* */+/* FreeType PFR bitmap loader (body). */+/* */+/* Copyright 2002, 2003, 2006, 2009, 2010 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 "pfrsbit.h"+#include "pfrload.h"+#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_STREAM_H++#include "pfrerror.h"++#undef FT_COMPONENT+#define FT_COMPONENT trace_pfr+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** PFR BIT WRITER *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ typedef struct PFR_BitWriter_+ {+ FT_Byte* line; /* current line start */+ FT_Int pitch; /* line size in bytes */+ FT_Int width; /* width in pixels/bits */+ FT_Int rows; /* number of remaining rows to scan */+ FT_Int total; /* total number of bits to draw */++ } PFR_BitWriterRec, *PFR_BitWriter;+++ static void+ pfr_bitwriter_init( PFR_BitWriter writer,+ FT_Bitmap* target,+ FT_Bool decreasing )+ {+ writer->line = target->buffer;+ writer->pitch = target->pitch;+ writer->width = target->width;+ writer->rows = target->rows;+ writer->total = writer->width * writer->rows;++ if ( !decreasing )+ {+ writer->line += writer->pitch * ( target->rows-1 );+ writer->pitch = -writer->pitch;+ }+ }+++ static void+ pfr_bitwriter_decode_bytes( PFR_BitWriter writer,+ FT_Byte* p,+ FT_Byte* limit )+ {+ FT_Int n, reload;+ FT_Int left = writer->width;+ FT_Byte* cur = writer->line;+ FT_UInt mask = 0x80;+ FT_UInt val = 0;+ FT_UInt c = 0;+++ n = (FT_Int)( limit - p ) * 8;+ if ( n > writer->total )+ n = writer->total;++ reload = n & 7;++ for ( ; n > 0; n-- )+ {+ if ( ( n & 7 ) == reload )+ val = *p++;++ if ( val & 0x80 )+ c |= mask;++ val <<= 1;+ mask >>= 1;++ if ( --left <= 0 )+ {+ cur[0] = (FT_Byte)c;+ left = writer->width;+ mask = 0x80;++ writer->line += writer->pitch;+ cur = writer->line;+ c = 0;+ }+ else if ( mask == 0 )+ {+ cur[0] = (FT_Byte)c;+ mask = 0x80;+ c = 0;+ cur ++;+ }+ }++ if ( mask != 0x80 )+ cur[0] = (FT_Byte)c;+ }+++ static void+ pfr_bitwriter_decode_rle1( PFR_BitWriter writer,+ FT_Byte* p,+ FT_Byte* limit )+ {+ FT_Int n, phase, count, counts[2], reload;+ FT_Int left = writer->width;+ FT_Byte* cur = writer->line;+ FT_UInt mask = 0x80;+ FT_UInt c = 0;+++ n = writer->total;++ phase = 1;+ counts[0] = 0;+ counts[1] = 0;+ count = 0;+ reload = 1;++ for ( ; n > 0; n-- )+ {+ if ( reload )+ {+ do+ {+ if ( phase )+ {+ FT_Int v;+++ if ( p >= limit )+ break;++ v = *p++;+ counts[0] = v >> 4;+ counts[1] = v & 15;+ phase = 0;+ count = counts[0];+ }+ else+ {+ phase = 1;+ count = counts[1];+ }++ } while ( count == 0 );+ }++ if ( phase )+ c |= mask;++ mask >>= 1;++ if ( --left <= 0 )+ {+ cur[0] = (FT_Byte) c;+ left = writer->width;+ mask = 0x80;++ writer->line += writer->pitch;+ cur = writer->line;+ c = 0;+ }+ else if ( mask == 0 )+ {+ cur[0] = (FT_Byte)c;+ mask = 0x80;+ c = 0;+ cur ++;+ }++ reload = ( --count <= 0 );+ }++ if ( mask != 0x80 )+ cur[0] = (FT_Byte) c;+ }+++ static void+ pfr_bitwriter_decode_rle2( PFR_BitWriter writer,+ FT_Byte* p,+ FT_Byte* limit )+ {+ FT_Int n, phase, count, reload;+ FT_Int left = writer->width;+ FT_Byte* cur = writer->line;+ FT_UInt mask = 0x80;+ FT_UInt c = 0;+++ n = writer->total;++ phase = 1;+ count = 0;+ reload = 1;++ for ( ; n > 0; n-- )+ {+ if ( reload )+ {+ do+ {+ if ( p >= limit )+ break;++ count = *p++;+ phase = phase ^ 1;++ } while ( count == 0 );+ }++ if ( phase )+ c |= mask;++ mask >>= 1;++ if ( --left <= 0 )+ {+ cur[0] = (FT_Byte) c;+ c = 0;+ mask = 0x80;+ left = writer->width;++ writer->line += writer->pitch;+ cur = writer->line;+ }+ else if ( mask == 0 )+ {+ cur[0] = (FT_Byte)c;+ c = 0;+ mask = 0x80;+ cur ++;+ }++ reload = ( --count <= 0 );+ }++ if ( mask != 0x80 )+ cur[0] = (FT_Byte) c;+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** BITMAP DATA DECODING *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ static void+ pfr_lookup_bitmap_data( FT_Byte* base,+ FT_Byte* limit,+ FT_UInt count,+ FT_UInt flags,+ FT_UInt char_code,+ FT_ULong* found_offset,+ FT_ULong* found_size )+ {+ FT_UInt left, right, char_len;+ FT_Bool two = FT_BOOL( flags & 1 );+ FT_Byte* buff;+++ char_len = 4;+ if ( two ) char_len += 1;+ if ( flags & 2 ) char_len += 1;+ if ( flags & 4 ) char_len += 1;++ left = 0;+ right = count;++ while ( left < right )+ {+ FT_UInt middle, code;+++ middle = ( left + right ) >> 1;+ buff = base + middle * char_len;++ /* check that we are not outside of the table -- */+ /* this is possible with broken fonts... */+ if ( buff + char_len > limit )+ goto Fail;++ if ( two )+ code = PFR_NEXT_USHORT( buff );+ else+ code = PFR_NEXT_BYTE( buff );++ if ( code == char_code )+ goto Found_It;++ if ( code < char_code )+ left = middle;+ else+ right = middle;+ }++ Fail:+ /* Not found */+ *found_size = 0;+ *found_offset = 0;+ return;++ Found_It:+ if ( flags & 2 )+ *found_size = PFR_NEXT_USHORT( buff );+ else+ *found_size = PFR_NEXT_BYTE( buff );++ if ( flags & 4 )+ *found_offset = PFR_NEXT_ULONG( buff );+ else+ *found_offset = PFR_NEXT_USHORT( buff );+ }+++ /* load bitmap metrics. "*padvance" must be set to the default value */+ /* before calling this function... */+ /* */+ static FT_Error+ pfr_load_bitmap_metrics( FT_Byte** pdata,+ FT_Byte* limit,+ FT_Long scaled_advance,+ FT_Long *axpos,+ FT_Long *aypos,+ FT_UInt *axsize,+ FT_UInt *aysize,+ FT_Long *aadvance,+ FT_UInt *aformat )+ {+ FT_Error error = PFR_Err_Ok;+ FT_Byte flags;+ FT_Char b;+ FT_Byte* p = *pdata;+ FT_Long xpos, ypos, advance;+ FT_UInt xsize, ysize;+++ PFR_CHECK( 1 );+ flags = PFR_NEXT_BYTE( p );++ xpos = 0;+ ypos = 0;+ xsize = 0;+ ysize = 0;+ advance = 0;++ switch ( flags & 3 )+ {+ case 0:+ PFR_CHECK( 1 );+ b = PFR_NEXT_INT8( p );+ xpos = b >> 4;+ ypos = ( (FT_Char)( b << 4 ) ) >> 4;+ break;++ case 1:+ PFR_CHECK( 2 );+ xpos = PFR_NEXT_INT8( p );+ ypos = PFR_NEXT_INT8( p );+ break;++ case 2:+ PFR_CHECK( 4 );+ xpos = PFR_NEXT_SHORT( p );+ ypos = PFR_NEXT_SHORT( p );+ break;++ case 3:+ PFR_CHECK( 6 );+ xpos = PFR_NEXT_LONG( p );+ ypos = PFR_NEXT_LONG( p );+ break;++ default:+ ;+ }++ flags >>= 2;+ switch ( flags & 3 )+ {+ case 0:+ /* blank image */+ xsize = 0;+ ysize = 0;+ break;++ case 1:+ PFR_CHECK( 1 );+ b = PFR_NEXT_BYTE( p );+ xsize = ( b >> 4 ) & 0xF;+ ysize = b & 0xF;+ break;++ case 2:+ PFR_CHECK( 2 );+ xsize = PFR_NEXT_BYTE( p );+ ysize = PFR_NEXT_BYTE( p );+ break;++ case 3:+ PFR_CHECK( 4 );+ xsize = PFR_NEXT_USHORT( p );+ ysize = PFR_NEXT_USHORT( p );+ break;++ default:+ ;+ }++ flags >>= 2;+ switch ( flags & 3 )+ {+ case 0:+ advance = scaled_advance;+ break;++ case 1:+ PFR_CHECK( 1 );+ advance = PFR_NEXT_INT8( p ) << 8;+ break;++ case 2:+ PFR_CHECK( 2 );+ advance = PFR_NEXT_SHORT( p );+ break;++ case 3:+ PFR_CHECK( 3 );+ advance = PFR_NEXT_LONG( p );+ break;++ default:+ ;+ }++ *axpos = xpos;+ *aypos = ypos;+ *axsize = xsize;+ *aysize = ysize;+ *aadvance = advance;+ *aformat = flags >> 2;+ *pdata = p;++ Exit:+ return error;++ Too_Short:+ error = PFR_Err_Invalid_Table;+ FT_ERROR(( "pfr_load_bitmap_metrics: invalid glyph data\n" ));+ goto Exit;+ }+++ static FT_Error+ pfr_load_bitmap_bits( FT_Byte* p,+ FT_Byte* limit,+ FT_UInt format,+ FT_Bool decreasing,+ FT_Bitmap* target )+ {+ FT_Error error = PFR_Err_Ok;+ PFR_BitWriterRec writer;+++ if ( target->rows > 0 && target->width > 0 )+ {+ pfr_bitwriter_init( &writer, target, decreasing );++ switch ( format )+ {+ case 0: /* packed bits */+ pfr_bitwriter_decode_bytes( &writer, p, limit );+ break;++ case 1: /* RLE1 */+ pfr_bitwriter_decode_rle1( &writer, p, limit );+ break;++ case 2: /* RLE2 */+ pfr_bitwriter_decode_rle2( &writer, p, limit );+ break;++ default:+ FT_ERROR(( "pfr_read_bitmap_data: invalid image type\n" ));+ error = PFR_Err_Invalid_File_Format;+ }+ }++ return error;+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** BITMAP LOADING *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ FT_LOCAL( FT_Error )+ pfr_slot_load_bitmap( PFR_Slot glyph,+ PFR_Size size,+ FT_UInt glyph_index )+ {+ FT_Error error;+ PFR_Face face = (PFR_Face) glyph->root.face;+ FT_Stream stream = face->root.stream;+ PFR_PhyFont phys = &face->phy_font;+ FT_ULong gps_offset;+ FT_ULong gps_size;+ PFR_Char character;+ PFR_Strike strike;+++ character = &phys->chars[glyph_index];++ /* Look-up a bitmap strike corresponding to the current */+ /* character dimensions */+ {+ FT_UInt n;+++ strike = phys->strikes;+ for ( n = 0; n < phys->num_strikes; n++ )+ {+ if ( strike->x_ppm == (FT_UInt)size->root.metrics.x_ppem &&+ strike->y_ppm == (FT_UInt)size->root.metrics.y_ppem )+ {+ goto Found_Strike;+ }++ strike++;+ }++ /* couldn't find it */+ return PFR_Err_Invalid_Argument;+ }++ Found_Strike:++ /* Now lookup the glyph's position within the file */+ {+ FT_UInt char_len;+++ char_len = 4;+ if ( strike->flags & 1 ) char_len += 1;+ if ( strike->flags & 2 ) char_len += 1;+ if ( strike->flags & 4 ) char_len += 1;++ /* Access data directly in the frame to speed lookups */+ if ( FT_STREAM_SEEK( phys->bct_offset + strike->bct_offset ) ||+ FT_FRAME_ENTER( char_len * strike->num_bitmaps ) )+ goto Exit;++ pfr_lookup_bitmap_data( stream->cursor,+ stream->limit,+ strike->num_bitmaps,+ strike->flags,+ character->char_code,+ &gps_offset,+ &gps_size );++ FT_FRAME_EXIT();++ if ( gps_size == 0 )+ {+ /* Could not find a bitmap program string for this glyph */+ error = PFR_Err_Invalid_Argument;+ goto Exit;+ }+ }++ /* get the bitmap metrics */+ {+ FT_Long xpos = 0, ypos = 0, advance = 0;+ FT_UInt xsize = 0, ysize = 0, format = 0;+ FT_Byte* p;+++ /* compute linear advance */+ advance = character->advance;+ if ( phys->metrics_resolution != phys->outline_resolution )+ advance = FT_MulDiv( advance,+ phys->outline_resolution,+ phys->metrics_resolution );++ glyph->root.linearHoriAdvance = advance;++ /* compute default advance, i.e., scaled advance. This can be */+ /* overridden in the bitmap header of certain glyphs. */+ advance = FT_MulDiv( (FT_Fixed)size->root.metrics.x_ppem << 8,+ character->advance,+ phys->metrics_resolution );++ if ( FT_STREAM_SEEK( face->header.gps_section_offset + gps_offset ) ||+ FT_FRAME_ENTER( gps_size ) )+ goto Exit;++ p = stream->cursor;+ error = pfr_load_bitmap_metrics( &p, stream->limit,+ advance,+ &xpos, &ypos,+ &xsize, &ysize,+ &advance, &format );++ /*+ * XXX: on 16bit system, we return an error for huge bitmap+ * which causes a size truncation, because truncated+ * size properties makes bitmap glyph broken.+ */+ if ( xpos > FT_INT_MAX || ( ypos + ysize ) > FT_INT_MAX )+ {+ FT_TRACE1(( "pfr_slot_load_bitmap:" ));+ FT_TRACE1(( "huge bitmap glyph %dx%d over FT_GlyphSlot\n",+ xpos, ypos ));+ error = PFR_Err_Invalid_Pixel_Size;+ }++ if ( !error )+ {+ glyph->root.format = FT_GLYPH_FORMAT_BITMAP;++ /* Set up glyph bitmap and metrics */++ /* XXX: needs casts to fit FT_Bitmap.{width|rows|pitch} */+ glyph->root.bitmap.width = (FT_Int)xsize;+ glyph->root.bitmap.rows = (FT_Int)ysize;+ glyph->root.bitmap.pitch = (FT_Int)( xsize + 7 ) >> 3;+ glyph->root.bitmap.pixel_mode = FT_PIXEL_MODE_MONO;++ /* XXX: needs casts to fit FT_Glyph_Metrics.{width|height} */+ glyph->root.metrics.width = (FT_Pos)xsize << 6;+ glyph->root.metrics.height = (FT_Pos)ysize << 6;+ glyph->root.metrics.horiBearingX = xpos << 6;+ glyph->root.metrics.horiBearingY = ypos << 6;+ glyph->root.metrics.horiAdvance = FT_PIX_ROUND( ( advance >> 2 ) );+ glyph->root.metrics.vertBearingX = - glyph->root.metrics.width >> 1;+ glyph->root.metrics.vertBearingY = 0;+ glyph->root.metrics.vertAdvance = size->root.metrics.height;++ /* XXX: needs casts fit FT_GlyphSlotRec.bitmap_{left|top} */+ glyph->root.bitmap_left = (FT_Int)xpos;+ glyph->root.bitmap_top = (FT_Int)(ypos + ysize);++ /* Allocate and read bitmap data */+ {+ FT_ULong len = glyph->root.bitmap.pitch * ysize;+++ error = ft_glyphslot_alloc_bitmap( &glyph->root, len );+ if ( !error )+ {+ error = pfr_load_bitmap_bits(+ p,+ stream->limit,+ format,+ FT_BOOL(face->header.color_flags & 2),+ &glyph->root.bitmap );+ }+ }+ }++ FT_FRAME_EXIT();+ }++ Exit:+ return error;+ }++/* END */
+ src/pfr/pfrsbit.h view
@@ -0,0 +1,36 @@+/***************************************************************************/+/* */+/* pfrsbit.h */+/* */+/* FreeType PFR bitmap loader (specification). */+/* */+/* Copyright 2002 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 __PFRSBIT_H__+#define __PFRSBIT_H__++#include "pfrobjs.h"++FT_BEGIN_HEADER++ FT_LOCAL( FT_Error )+ pfr_slot_load_bitmap( PFR_Slot glyph,+ PFR_Size size,+ FT_UInt glyph_index );++FT_END_HEADER++#endif /* __PFR_SBIT_H__ */+++/* END */
+ src/pfr/pfrtypes.h view
@@ -0,0 +1,362 @@+/***************************************************************************/+/* */+/* pfrtypes.h */+/* */+/* FreeType PFR data structures (specification only). */+/* */+/* Copyright 2002, 2003, 2005, 2007 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 __PFRTYPES_H__+#define __PFRTYPES_H__++#include <ft2build.h>+#include FT_INTERNAL_OBJECTS_H++FT_BEGIN_HEADER++ /************************************************************************/++ /* the PFR Header structure */+ typedef struct PFR_HeaderRec_+ {+ FT_UInt32 signature;+ FT_UInt version;+ FT_UInt signature2;+ FT_UInt header_size;++ FT_UInt log_dir_size;+ FT_UInt log_dir_offset;++ FT_UInt log_font_max_size;+ FT_UInt32 log_font_section_size;+ FT_UInt32 log_font_section_offset;++ FT_UInt32 phy_font_max_size;+ FT_UInt32 phy_font_section_size;+ FT_UInt32 phy_font_section_offset;++ FT_UInt gps_max_size;+ FT_UInt32 gps_section_size;+ FT_UInt32 gps_section_offset;++ FT_UInt max_blue_values;+ FT_UInt max_x_orus;+ FT_UInt max_y_orus;++ FT_UInt phy_font_max_size_high;+ FT_UInt color_flags;++ FT_UInt32 bct_max_size;+ FT_UInt32 bct_set_max_size;+ FT_UInt32 phy_bct_set_max_size;++ FT_UInt num_phy_fonts;+ FT_UInt max_vert_stem_snap;+ FT_UInt max_horz_stem_snap;+ FT_UInt max_chars;++ } PFR_HeaderRec, *PFR_Header;+++ /* used in `color_flags' field of the PFR_Header */+ typedef enum PFR_HeaderFlags_+ {+ PFR_FLAG_BLACK_PIXEL = 1,+ PFR_FLAG_INVERT_BITMAP = 2++ } PFR_HeaderFlags;+++ /************************************************************************/++ typedef struct PFR_LogFontRec_+ {+ FT_UInt32 size;+ FT_UInt32 offset;++ FT_Int32 matrix[4];+ FT_UInt stroke_flags;+ FT_Int stroke_thickness;+ FT_Int bold_thickness;+ FT_Int32 miter_limit;++ FT_UInt32 phys_size;+ FT_UInt32 phys_offset;++ } PFR_LogFontRec, *PFR_LogFont;+++ typedef enum PFR_LogFlags_+ {+ PFR_LOG_EXTRA_ITEMS = 0x40,+ PFR_LOG_2BYTE_BOLD = 0x20,+ PFR_LOG_BOLD = 0x10,+ PFR_LOG_2BYTE_STROKE = 8,+ PFR_LOG_STROKE = 4,+ PFR_LINE_JOIN_MASK = 3++ } PFR_LogFlags;+++ typedef enum PFR_LineJoinFlags_+ {+ PFR_LINE_JOIN_MITER = 0,+ PFR_LINE_JOIN_ROUND = 1,+ PFR_LINE_JOIN_BEVEL = 2++ } PFR_LineJoinFlags;+++ /************************************************************************/++ typedef enum PFR_BitmapFlags_+ {+ PFR_BITMAP_3BYTE_OFFSET = 4,+ PFR_BITMAP_2BYTE_SIZE = 2,+ PFR_BITMAP_2BYTE_CHARCODE = 1++ } PFR_BitmapFlags;+++ typedef struct PFR_BitmapCharRec_+ {+ FT_UInt char_code;+ FT_UInt gps_size;+ FT_UInt32 gps_offset;++ } PFR_BitmapCharRec, *PFR_BitmapChar;+++ typedef enum PFR_StrikeFlags_+ {+ PFR_STRIKE_2BYTE_COUNT = 0x10,+ PFR_STRIKE_3BYTE_OFFSET = 0x08,+ PFR_STRIKE_3BYTE_SIZE = 0x04,+ PFR_STRIKE_2BYTE_YPPM = 0x02,+ PFR_STRIKE_2BYTE_XPPM = 0x01++ } PFR_StrikeFlags;+++ typedef struct PFR_StrikeRec_+ {+ FT_UInt x_ppm;+ FT_UInt y_ppm;+ FT_UInt flags;++ FT_UInt32 gps_size;+ FT_UInt32 gps_offset;++ FT_UInt32 bct_size;+ FT_UInt32 bct_offset;++ /* optional */+ FT_UInt num_bitmaps;+ PFR_BitmapChar bitmaps;++ } PFR_StrikeRec, *PFR_Strike;+++ /************************************************************************/++ typedef struct PFR_CharRec_+ {+ FT_UInt char_code;+ FT_Int advance;+ FT_UInt gps_size;+ FT_UInt32 gps_offset;++ } PFR_CharRec, *PFR_Char;+++ /************************************************************************/++ typedef struct PFR_DimensionRec_+ {+ FT_UInt standard;+ FT_UInt num_stem_snaps;+ FT_Int* stem_snaps;++ } PFR_DimensionRec, *PFR_Dimension;++ /************************************************************************/++ typedef struct PFR_KernItemRec_* PFR_KernItem;++ typedef struct PFR_KernItemRec_+ {+ PFR_KernItem next;+ FT_Byte pair_count;+ FT_Byte flags;+ FT_Short base_adj;+ FT_UInt pair_size;+ FT_Offset offset;+ FT_UInt32 pair1;+ FT_UInt32 pair2;++ } PFR_KernItemRec;+++#define PFR_KERN_INDEX( g1, g2 ) \+ ( ( (FT_UInt32)(g1) << 16 ) | (FT_UInt16)(g2) )++#define PFR_KERN_PAIR_INDEX( pair ) \+ PFR_KERN_INDEX( (pair)->glyph1, (pair)->glyph2 )++#define PFR_NEXT_KPAIR( p ) ( p += 2, \+ ( (FT_UInt32)p[-2] << 16 ) | p[-1] )+++ /************************************************************************/++ typedef struct PFR_PhyFontRec_+ {+ FT_Memory memory;+ FT_UInt32 offset;++ FT_UInt font_ref_number;+ FT_UInt outline_resolution;+ FT_UInt metrics_resolution;+ FT_BBox bbox;+ FT_UInt flags;+ FT_UInt standard_advance;++ FT_Int ascent; /* optional, bbox.yMax if not present */+ FT_Int descent; /* optional, bbox.yMin if not present */+ FT_Int leading; /* optional, 0 if not present */++ PFR_DimensionRec horizontal;+ PFR_DimensionRec vertical;++ FT_String* font_id;+ FT_String* family_name;+ FT_String* style_name;++ FT_UInt num_strikes;+ FT_UInt max_strikes;+ PFR_StrikeRec* strikes;++ FT_UInt num_blue_values;+ FT_Int *blue_values;+ FT_UInt blue_fuzz;+ FT_UInt blue_scale;++ FT_UInt num_chars;+ FT_Offset chars_offset;+ PFR_Char chars;++ FT_UInt num_kern_pairs;+ PFR_KernItem kern_items;+ PFR_KernItem* kern_items_tail;++ /* not part of the spec, but used during load */+ FT_Long bct_offset;+ FT_Byte* cursor;++ } PFR_PhyFontRec, *PFR_PhyFont;+++ typedef enum PFR_PhyFlags_+ {+ PFR_PHY_EXTRA_ITEMS = 0x80,+ PFR_PHY_3BYTE_GPS_OFFSET = 0x20,+ PFR_PHY_2BYTE_GPS_SIZE = 0x10,+ PFR_PHY_ASCII_CODE = 0x08,+ PFR_PHY_PROPORTIONAL = 0x04,+ PFR_PHY_2BYTE_CHARCODE = 0x02,+ PFR_PHY_VERTICAL = 0x01++ } PFR_PhyFlags;+++ typedef enum PFR_KernFlags_+ {+ PFR_KERN_2BYTE_CHAR = 0x01,+ PFR_KERN_2BYTE_ADJ = 0x02++ } PFR_KernFlags;+++ /************************************************************************/++ typedef enum PFR_GlyphFlags_+ {+ PFR_GLYPH_IS_COMPOUND = 0x80,+ PFR_GLYPH_EXTRA_ITEMS = 0x08,+ PFR_GLYPH_1BYTE_XYCOUNT = 0x04,+ PFR_GLYPH_XCOUNT = 0x02,+ PFR_GLYPH_YCOUNT = 0x01++ } PFR_GlyphFlags;+++ /* controlled coordinate */+ typedef struct PFR_CoordRec_+ {+ FT_UInt org;+ FT_UInt cur;++ } PFR_CoordRec, *PFR_Coord;+++ typedef struct PFR_SubGlyphRec_+ {+ FT_Fixed x_scale;+ FT_Fixed y_scale;+ FT_Int x_delta;+ FT_Int y_delta;+ FT_UInt32 gps_offset;+ FT_UInt gps_size;++ } PFR_SubGlyphRec, *PFR_SubGlyph;+++ typedef enum PFR_SubgGlyphFlags_+ {+ PFR_SUBGLYPH_3BYTE_OFFSET = 0x80,+ PFR_SUBGLYPH_2BYTE_SIZE = 0x40,+ PFR_SUBGLYPH_YSCALE = 0x20,+ PFR_SUBGLYPH_XSCALE = 0x10++ } PFR_SubGlyphFlags;+++ typedef struct PFR_GlyphRec_+ {+ FT_Byte format;++#if 0+ FT_UInt num_x_control;+ FT_UInt num_y_control;+#endif+ FT_UInt max_xy_control;+ FT_Pos* x_control;+ FT_Pos* y_control;+++ FT_UInt num_subs;+ FT_UInt max_subs;+ PFR_SubGlyphRec* subs;++ FT_GlyphLoader loader;+ FT_Bool path_begun;++ } PFR_GlyphRec, *PFR_Glyph;+++FT_END_HEADER++#endif /* __PFRTYPES_H__ */+++/* END */
+ src/psaux/afmparse.c view
@@ -0,0 +1,964 @@+/***************************************************************************/+/* */+/* afmparse.c */+/* */+/* AFM parser (body). */+/* */+/* Copyright 2006, 2007, 2008, 2009, 2010 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/++#include <ft2build.h>+#include FT_FREETYPE_H+#include FT_INTERNAL_POSTSCRIPT_AUX_H++#include "afmparse.h"+#include "psconv.h"++#include "psauxerr.h"+++/***************************************************************************/+/* */+/* AFM_Stream */+/* */+/* The use of AFM_Stream is largely inspired by parseAFM.[ch] from t1lib. */+/* */+/* */++ enum+ {+ AFM_STREAM_STATUS_NORMAL,+ AFM_STREAM_STATUS_EOC,+ AFM_STREAM_STATUS_EOL,+ AFM_STREAM_STATUS_EOF+ };+++ typedef struct AFM_StreamRec_+ {+ FT_Byte* cursor;+ FT_Byte* base;+ FT_Byte* limit;++ FT_Int status;++ } AFM_StreamRec;+++#ifndef EOF+#define EOF -1+#endif+++ /* this works because empty lines are ignored */+#define AFM_IS_NEWLINE( ch ) ( (ch) == '\r' || (ch) == '\n' )++#define AFM_IS_EOF( ch ) ( (ch) == EOF || (ch) == '\x1a' )+#define AFM_IS_SPACE( ch ) ( (ch) == ' ' || (ch) == '\t' )++ /* column separator; there is no `column' in the spec actually */+#define AFM_IS_SEP( ch ) ( (ch) == ';' )++#define AFM_GETC() \+ ( ( (stream)->cursor < (stream)->limit ) ? *(stream)->cursor++ \+ : EOF )++#define AFM_STREAM_KEY_BEGIN( stream ) \+ (char*)( (stream)->cursor - 1 )++#define AFM_STREAM_KEY_LEN( stream, key ) \+ ( (char*)(stream)->cursor - key - 1 )++#define AFM_STATUS_EOC( stream ) \+ ( (stream)->status >= AFM_STREAM_STATUS_EOC )++#define AFM_STATUS_EOL( stream ) \+ ( (stream)->status >= AFM_STREAM_STATUS_EOL )++#define AFM_STATUS_EOF( stream ) \+ ( (stream)->status >= AFM_STREAM_STATUS_EOF )+++ static int+ afm_stream_skip_spaces( AFM_Stream stream )+ {+ int ch = 0; /* make stupid compiler happy */+++ if ( AFM_STATUS_EOC( stream ) )+ return ';';++ while ( 1 )+ {+ ch = AFM_GETC();+ if ( !AFM_IS_SPACE( ch ) )+ break;+ }++ if ( AFM_IS_NEWLINE( ch ) )+ stream->status = AFM_STREAM_STATUS_EOL;+ else if ( AFM_IS_SEP( ch ) )+ stream->status = AFM_STREAM_STATUS_EOC;+ else if ( AFM_IS_EOF( ch ) )+ stream->status = AFM_STREAM_STATUS_EOF;++ return ch;+ }+++ /* read a key or value in current column */+ static char*+ afm_stream_read_one( AFM_Stream stream )+ {+ char* str;+ int ch;+++ afm_stream_skip_spaces( stream );+ if ( AFM_STATUS_EOC( stream ) )+ return NULL;++ str = AFM_STREAM_KEY_BEGIN( stream );++ while ( 1 )+ {+ ch = AFM_GETC();+ if ( AFM_IS_SPACE( ch ) )+ break;+ else if ( AFM_IS_NEWLINE( ch ) )+ {+ stream->status = AFM_STREAM_STATUS_EOL;+ break;+ }+ else if ( AFM_IS_SEP( ch ) )+ {+ stream->status = AFM_STREAM_STATUS_EOC;+ break;+ }+ else if ( AFM_IS_EOF( ch ) )+ {+ stream->status = AFM_STREAM_STATUS_EOF;+ break;+ }+ }++ return str;+ }+++ /* read a string (i.e., read to EOL) */+ static char*+ afm_stream_read_string( AFM_Stream stream )+ {+ char* str;+ int ch;+++ afm_stream_skip_spaces( stream );+ if ( AFM_STATUS_EOL( stream ) )+ return NULL;++ str = AFM_STREAM_KEY_BEGIN( stream );++ /* scan to eol */+ while ( 1 )+ {+ ch = AFM_GETC();+ if ( AFM_IS_NEWLINE( ch ) )+ {+ stream->status = AFM_STREAM_STATUS_EOL;+ break;+ }+ else if ( AFM_IS_EOF( ch ) )+ {+ stream->status = AFM_STREAM_STATUS_EOF;+ break;+ }+ }++ return str;+ }+++ /*************************************************************************/+ /* */+ /* AFM_Parser */+ /* */+ /* */++ /* all keys defined in Ch. 7-10 of 5004.AFM_Spec.pdf */+ typedef enum AFM_Token_+ {+ AFM_TOKEN_ASCENDER,+ AFM_TOKEN_AXISLABEL,+ AFM_TOKEN_AXISTYPE,+ AFM_TOKEN_B,+ AFM_TOKEN_BLENDAXISTYPES,+ AFM_TOKEN_BLENDDESIGNMAP,+ AFM_TOKEN_BLENDDESIGNPOSITIONS,+ AFM_TOKEN_C,+ AFM_TOKEN_CC,+ AFM_TOKEN_CH,+ AFM_TOKEN_CAPHEIGHT,+ AFM_TOKEN_CHARWIDTH,+ AFM_TOKEN_CHARACTERSET,+ AFM_TOKEN_CHARACTERS,+ AFM_TOKEN_DESCENDER,+ AFM_TOKEN_ENCODINGSCHEME,+ AFM_TOKEN_ENDAXIS,+ AFM_TOKEN_ENDCHARMETRICS,+ AFM_TOKEN_ENDCOMPOSITES,+ AFM_TOKEN_ENDDIRECTION,+ AFM_TOKEN_ENDFONTMETRICS,+ AFM_TOKEN_ENDKERNDATA,+ AFM_TOKEN_ENDKERNPAIRS,+ AFM_TOKEN_ENDTRACKKERN,+ AFM_TOKEN_ESCCHAR,+ AFM_TOKEN_FAMILYNAME,+ AFM_TOKEN_FONTBBOX,+ AFM_TOKEN_FONTNAME,+ AFM_TOKEN_FULLNAME,+ AFM_TOKEN_ISBASEFONT,+ AFM_TOKEN_ISCIDFONT,+ AFM_TOKEN_ISFIXEDPITCH,+ AFM_TOKEN_ISFIXEDV,+ AFM_TOKEN_ITALICANGLE,+ AFM_TOKEN_KP,+ AFM_TOKEN_KPH,+ AFM_TOKEN_KPX,+ AFM_TOKEN_KPY,+ AFM_TOKEN_L,+ AFM_TOKEN_MAPPINGSCHEME,+ AFM_TOKEN_METRICSSETS,+ AFM_TOKEN_N,+ AFM_TOKEN_NOTICE,+ AFM_TOKEN_PCC,+ AFM_TOKEN_STARTAXIS,+ AFM_TOKEN_STARTCHARMETRICS,+ AFM_TOKEN_STARTCOMPOSITES,+ AFM_TOKEN_STARTDIRECTION,+ AFM_TOKEN_STARTFONTMETRICS,+ AFM_TOKEN_STARTKERNDATA,+ AFM_TOKEN_STARTKERNPAIRS,+ AFM_TOKEN_STARTKERNPAIRS0,+ AFM_TOKEN_STARTKERNPAIRS1,+ AFM_TOKEN_STARTTRACKKERN,+ AFM_TOKEN_STDHW,+ AFM_TOKEN_STDVW,+ AFM_TOKEN_TRACKKERN,+ AFM_TOKEN_UNDERLINEPOSITION,+ AFM_TOKEN_UNDERLINETHICKNESS,+ AFM_TOKEN_VV,+ AFM_TOKEN_VVECTOR,+ AFM_TOKEN_VERSION,+ AFM_TOKEN_W,+ AFM_TOKEN_W0,+ AFM_TOKEN_W0X,+ AFM_TOKEN_W0Y,+ AFM_TOKEN_W1,+ AFM_TOKEN_W1X,+ AFM_TOKEN_W1Y,+ AFM_TOKEN_WX,+ AFM_TOKEN_WY,+ AFM_TOKEN_WEIGHT,+ AFM_TOKEN_WEIGHTVECTOR,+ AFM_TOKEN_XHEIGHT,+ N_AFM_TOKENS,+ AFM_TOKEN_UNKNOWN++ } AFM_Token;+++ static const char* const afm_key_table[N_AFM_TOKENS] =+ {+ "Ascender",+ "AxisLabel",+ "AxisType",+ "B",+ "BlendAxisTypes",+ "BlendDesignMap",+ "BlendDesignPositions",+ "C",+ "CC",+ "CH",+ "CapHeight",+ "CharWidth",+ "CharacterSet",+ "Characters",+ "Descender",+ "EncodingScheme",+ "EndAxis",+ "EndCharMetrics",+ "EndComposites",+ "EndDirection",+ "EndFontMetrics",+ "EndKernData",+ "EndKernPairs",+ "EndTrackKern",+ "EscChar",+ "FamilyName",+ "FontBBox",+ "FontName",+ "FullName",+ "IsBaseFont",+ "IsCIDFont",+ "IsFixedPitch",+ "IsFixedV",+ "ItalicAngle",+ "KP",+ "KPH",+ "KPX",+ "KPY",+ "L",+ "MappingScheme",+ "MetricsSets",+ "N",+ "Notice",+ "PCC",+ "StartAxis",+ "StartCharMetrics",+ "StartComposites",+ "StartDirection",+ "StartFontMetrics",+ "StartKernData",+ "StartKernPairs",+ "StartKernPairs0",+ "StartKernPairs1",+ "StartTrackKern",+ "StdHW",+ "StdVW",+ "TrackKern",+ "UnderlinePosition",+ "UnderlineThickness",+ "VV",+ "VVector",+ "Version",+ "W",+ "W0",+ "W0X",+ "W0Y",+ "W1",+ "W1X",+ "W1Y",+ "WX",+ "WY",+ "Weight",+ "WeightVector",+ "XHeight"+ };+++ /*+ * `afm_parser_read_vals' and `afm_parser_next_key' provide+ * high-level operations to an AFM_Stream. The rest of the+ * parser functions should use them without accessing the+ * AFM_Stream directly.+ */++ FT_LOCAL_DEF( FT_Int )+ afm_parser_read_vals( AFM_Parser parser,+ AFM_Value vals,+ FT_UInt n )+ {+ AFM_Stream stream = parser->stream;+ char* str;+ FT_UInt i;+++ if ( n > AFM_MAX_ARGUMENTS )+ return 0;++ for ( i = 0; i < n; i++ )+ {+ FT_Offset len;+ AFM_Value val = vals + i;+++ if ( val->type == AFM_VALUE_TYPE_STRING )+ str = afm_stream_read_string( stream );+ else+ str = afm_stream_read_one( stream );++ if ( !str )+ break;++ len = AFM_STREAM_KEY_LEN( stream, str );++ switch ( val->type )+ {+ case AFM_VALUE_TYPE_STRING:+ case AFM_VALUE_TYPE_NAME:+ {+ FT_Memory memory = parser->memory;+ FT_Error error;+++ if ( !FT_QALLOC( val->u.s, len + 1 ) )+ {+ ft_memcpy( val->u.s, str, len );+ val->u.s[len] = '\0';+ }+ }+ break;++ case AFM_VALUE_TYPE_FIXED:+ val->u.f = PS_Conv_ToFixed( (FT_Byte**)(void*)&str,+ (FT_Byte*)str + len, 0 );+ break;++ case AFM_VALUE_TYPE_INTEGER:+ val->u.i = PS_Conv_ToInt( (FT_Byte**)(void*)&str,+ (FT_Byte*)str + len );+ break;++ case AFM_VALUE_TYPE_BOOL:+ val->u.b = FT_BOOL( len == 4 &&+ !ft_strncmp( str, "true", 4 ) );+ break;++ case AFM_VALUE_TYPE_INDEX:+ if ( parser->get_index )+ val->u.i = parser->get_index( str, len, parser->user_data );+ else+ val->u.i = 0;+ break;+ }+ }++ return i;+ }+++ FT_LOCAL_DEF( char* )+ afm_parser_next_key( AFM_Parser parser,+ FT_Bool line,+ FT_Offset* len )+ {+ AFM_Stream stream = parser->stream;+ char* key = 0; /* make stupid compiler happy */+++ if ( line )+ {+ while ( 1 )+ {+ /* skip current line */+ if ( !AFM_STATUS_EOL( stream ) )+ afm_stream_read_string( stream );++ stream->status = AFM_STREAM_STATUS_NORMAL;+ key = afm_stream_read_one( stream );++ /* skip empty line */+ if ( !key &&+ !AFM_STATUS_EOF( stream ) &&+ AFM_STATUS_EOL( stream ) )+ continue;++ break;+ }+ }+ else+ {+ while ( 1 )+ {+ /* skip current column */+ while ( !AFM_STATUS_EOC( stream ) )+ afm_stream_read_one( stream );++ stream->status = AFM_STREAM_STATUS_NORMAL;+ key = afm_stream_read_one( stream );++ /* skip empty column */+ if ( !key &&+ !AFM_STATUS_EOF( stream ) &&+ AFM_STATUS_EOC( stream ) )+ continue;++ break;+ }+ }++ if ( len )+ *len = ( key ) ? (FT_Offset)AFM_STREAM_KEY_LEN( stream, key )+ : 0;++ return key;+ }+++ static AFM_Token+ afm_tokenize( const char* key,+ FT_Offset len )+ {+ int n;+++ for ( n = 0; n < N_AFM_TOKENS; n++ )+ {+ if ( *( afm_key_table[n] ) == *key )+ {+ for ( ; n < N_AFM_TOKENS; n++ )+ {+ if ( *( afm_key_table[n] ) != *key )+ return AFM_TOKEN_UNKNOWN;++ if ( ft_strncmp( afm_key_table[n], key, len ) == 0 )+ return (AFM_Token) n;+ }+ }+ }++ return AFM_TOKEN_UNKNOWN;+ }+++ FT_LOCAL_DEF( FT_Error )+ afm_parser_init( AFM_Parser parser,+ FT_Memory memory,+ FT_Byte* base,+ FT_Byte* limit )+ {+ AFM_Stream stream = NULL;+ FT_Error error;+++ if ( FT_NEW( stream ) )+ return error;++ stream->cursor = stream->base = base;+ stream->limit = limit;++ /* don't skip the first line during the first call */+ stream->status = AFM_STREAM_STATUS_EOL;++ parser->memory = memory;+ parser->stream = stream;+ parser->FontInfo = NULL;+ parser->get_index = NULL;++ return PSaux_Err_Ok;+ }+++ FT_LOCAL( void )+ afm_parser_done( AFM_Parser parser )+ {+ FT_Memory memory = parser->memory;+++ FT_FREE( parser->stream );+ }+++ FT_LOCAL_DEF( FT_Error )+ afm_parser_read_int( AFM_Parser parser,+ FT_Int* aint )+ {+ AFM_ValueRec val;+++ val.type = AFM_VALUE_TYPE_INTEGER;++ if ( afm_parser_read_vals( parser, &val, 1 ) == 1 )+ {+ *aint = val.u.i;++ return PSaux_Err_Ok;+ }+ else+ return PSaux_Err_Syntax_Error;+ }+++ static FT_Error+ afm_parse_track_kern( AFM_Parser parser )+ {+ AFM_FontInfo fi = parser->FontInfo;+ AFM_TrackKern tk;+ char* key;+ FT_Offset len;+ int n = -1;+++ if ( afm_parser_read_int( parser, &fi->NumTrackKern ) )+ goto Fail;++ if ( fi->NumTrackKern )+ {+ FT_Memory memory = parser->memory;+ FT_Error error;+++ if ( FT_QNEW_ARRAY( fi->TrackKerns, fi->NumTrackKern ) )+ return error;+ }++ while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )+ {+ AFM_ValueRec shared_vals[5];+++ switch ( afm_tokenize( key, len ) )+ {+ case AFM_TOKEN_TRACKKERN:+ n++;++ if ( n >= fi->NumTrackKern )+ goto Fail;++ tk = fi->TrackKerns + n;++ shared_vals[0].type = AFM_VALUE_TYPE_INTEGER;+ shared_vals[1].type = AFM_VALUE_TYPE_FIXED;+ shared_vals[2].type = AFM_VALUE_TYPE_FIXED;+ shared_vals[3].type = AFM_VALUE_TYPE_FIXED;+ shared_vals[4].type = AFM_VALUE_TYPE_FIXED;+ if ( afm_parser_read_vals( parser, shared_vals, 5 ) != 5 )+ goto Fail;++ tk->degree = shared_vals[0].u.i;+ tk->min_ptsize = shared_vals[1].u.f;+ tk->min_kern = shared_vals[2].u.f;+ tk->max_ptsize = shared_vals[3].u.f;+ tk->max_kern = shared_vals[4].u.f;++ /* is this correct? */+ if ( tk->degree < 0 && tk->min_kern > 0 )+ tk->min_kern = -tk->min_kern;+ break;++ case AFM_TOKEN_ENDTRACKKERN:+ case AFM_TOKEN_ENDKERNDATA:+ case AFM_TOKEN_ENDFONTMETRICS:+ fi->NumTrackKern = n + 1;+ return PSaux_Err_Ok;++ case AFM_TOKEN_UNKNOWN:+ break;++ default:+ goto Fail;+ }+ }++ Fail:+ return PSaux_Err_Syntax_Error;+ }+++#undef KERN_INDEX+#define KERN_INDEX( g1, g2 ) ( ( (FT_ULong)g1 << 16 ) | g2 )+++ /* compare two kerning pairs */+ FT_CALLBACK_DEF( int )+ afm_compare_kern_pairs( const void* a,+ const void* b )+ {+ AFM_KernPair kp1 = (AFM_KernPair)a;+ AFM_KernPair kp2 = (AFM_KernPair)b;++ FT_ULong index1 = KERN_INDEX( kp1->index1, kp1->index2 );+ FT_ULong index2 = KERN_INDEX( kp2->index1, kp2->index2 );+++ if ( index1 > index2 )+ return 1;+ else if ( index1 < index2 )+ return -1;+ else+ return 0;+ }+++ static FT_Error+ afm_parse_kern_pairs( AFM_Parser parser )+ {+ AFM_FontInfo fi = parser->FontInfo;+ AFM_KernPair kp;+ char* key;+ FT_Offset len;+ int n = -1;+++ if ( afm_parser_read_int( parser, &fi->NumKernPair ) )+ goto Fail;++ if ( fi->NumKernPair )+ {+ FT_Memory memory = parser->memory;+ FT_Error error;+++ if ( FT_QNEW_ARRAY( fi->KernPairs, fi->NumKernPair ) )+ return error;+ }++ while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )+ {+ AFM_Token token = afm_tokenize( key, len );+++ switch ( token )+ {+ case AFM_TOKEN_KP:+ case AFM_TOKEN_KPX:+ case AFM_TOKEN_KPY:+ {+ FT_Int r;+ AFM_ValueRec shared_vals[4];+++ n++;++ if ( n >= fi->NumKernPair )+ goto Fail;++ kp = fi->KernPairs + n;++ shared_vals[0].type = AFM_VALUE_TYPE_INDEX;+ shared_vals[1].type = AFM_VALUE_TYPE_INDEX;+ shared_vals[2].type = AFM_VALUE_TYPE_INTEGER;+ shared_vals[3].type = AFM_VALUE_TYPE_INTEGER;+ r = afm_parser_read_vals( parser, shared_vals, 4 );+ if ( r < 3 )+ goto Fail;++ kp->index1 = shared_vals[0].u.i;+ kp->index2 = shared_vals[1].u.i;+ if ( token == AFM_TOKEN_KPY )+ {+ kp->x = 0;+ kp->y = shared_vals[2].u.i;+ }+ else+ {+ kp->x = shared_vals[2].u.i;+ kp->y = ( token == AFM_TOKEN_KP && r == 4 )+ ? shared_vals[3].u.i : 0;+ }+ }+ break;++ case AFM_TOKEN_ENDKERNPAIRS:+ case AFM_TOKEN_ENDKERNDATA:+ case AFM_TOKEN_ENDFONTMETRICS:+ fi->NumKernPair = n + 1;+ ft_qsort( fi->KernPairs, fi->NumKernPair,+ sizeof( AFM_KernPairRec ),+ afm_compare_kern_pairs );+ return PSaux_Err_Ok;++ case AFM_TOKEN_UNKNOWN:+ break;++ default:+ goto Fail;+ }+ }++ Fail:+ return PSaux_Err_Syntax_Error;+ }+++ static FT_Error+ afm_parse_kern_data( AFM_Parser parser )+ {+ FT_Error error;+ char* key;+ FT_Offset len;+++ while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )+ {+ switch ( afm_tokenize( key, len ) )+ {+ case AFM_TOKEN_STARTTRACKKERN:+ error = afm_parse_track_kern( parser );+ if ( error )+ return error;+ break;++ case AFM_TOKEN_STARTKERNPAIRS:+ case AFM_TOKEN_STARTKERNPAIRS0:+ error = afm_parse_kern_pairs( parser );+ if ( error )+ return error;+ break;++ case AFM_TOKEN_ENDKERNDATA:+ case AFM_TOKEN_ENDFONTMETRICS:+ return PSaux_Err_Ok;++ case AFM_TOKEN_UNKNOWN:+ break;++ default:+ goto Fail;+ }+ }++ Fail:+ return PSaux_Err_Syntax_Error;+ }+++ static FT_Error+ afm_parser_skip_section( AFM_Parser parser,+ FT_UInt n,+ AFM_Token end_section )+ {+ char* key;+ FT_Offset len;+++ while ( n-- > 0 )+ {+ key = afm_parser_next_key( parser, 1, NULL );+ if ( !key )+ goto Fail;+ }++ while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )+ {+ AFM_Token token = afm_tokenize( key, len );+++ if ( token == end_section || token == AFM_TOKEN_ENDFONTMETRICS )+ return PSaux_Err_Ok;+ }++ Fail:+ return PSaux_Err_Syntax_Error;+ }+++ FT_LOCAL_DEF( FT_Error )+ afm_parser_parse( AFM_Parser parser )+ {+ FT_Memory memory = parser->memory;+ AFM_FontInfo fi = parser->FontInfo;+ FT_Error error = PSaux_Err_Syntax_Error;+ char* key;+ FT_Offset len;+ FT_Int metrics_sets = 0;+++ if ( !fi )+ return PSaux_Err_Invalid_Argument;++ key = afm_parser_next_key( parser, 1, &len );+ if ( !key || len != 16 ||+ ft_strncmp( key, "StartFontMetrics", 16 ) != 0 )+ return PSaux_Err_Unknown_File_Format;++ while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )+ {+ AFM_ValueRec shared_vals[4];+++ switch ( afm_tokenize( key, len ) )+ {+ case AFM_TOKEN_METRICSSETS:+ if ( afm_parser_read_int( parser, &metrics_sets ) )+ goto Fail;++ if ( metrics_sets != 0 && metrics_sets != 2 )+ {+ error = PSaux_Err_Unimplemented_Feature;++ goto Fail;+ }+ break;++ case AFM_TOKEN_ISCIDFONT:+ shared_vals[0].type = AFM_VALUE_TYPE_BOOL;+ if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 )+ goto Fail;++ fi->IsCIDFont = shared_vals[0].u.b;+ break;++ case AFM_TOKEN_FONTBBOX:+ shared_vals[0].type = AFM_VALUE_TYPE_FIXED;+ shared_vals[1].type = AFM_VALUE_TYPE_FIXED;+ shared_vals[2].type = AFM_VALUE_TYPE_FIXED;+ shared_vals[3].type = AFM_VALUE_TYPE_FIXED;+ if ( afm_parser_read_vals( parser, shared_vals, 4 ) != 4 )+ goto Fail;++ fi->FontBBox.xMin = shared_vals[0].u.f;+ fi->FontBBox.yMin = shared_vals[1].u.f;+ fi->FontBBox.xMax = shared_vals[2].u.f;+ fi->FontBBox.yMax = shared_vals[3].u.f;+ break;++ case AFM_TOKEN_ASCENDER:+ shared_vals[0].type = AFM_VALUE_TYPE_FIXED;+ if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 )+ goto Fail;++ fi->Ascender = shared_vals[0].u.f;+ break;++ case AFM_TOKEN_DESCENDER:+ shared_vals[0].type = AFM_VALUE_TYPE_FIXED;+ if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 )+ goto Fail;++ fi->Descender = shared_vals[0].u.f;+ break;++ case AFM_TOKEN_STARTCHARMETRICS:+ {+ FT_Int n = 0;+++ if ( afm_parser_read_int( parser, &n ) )+ goto Fail;++ error = afm_parser_skip_section( parser, n,+ AFM_TOKEN_ENDCHARMETRICS );+ if ( error )+ return error;+ }+ break;++ case AFM_TOKEN_STARTKERNDATA:+ error = afm_parse_kern_data( parser );+ if ( error )+ goto Fail;+ /* fall through since we only support kern data */++ case AFM_TOKEN_ENDFONTMETRICS:+ return PSaux_Err_Ok;++ default:+ break;+ }+ }++ Fail:+ FT_FREE( fi->TrackKerns );+ fi->NumTrackKern = 0;++ FT_FREE( fi->KernPairs );+ fi->NumKernPair = 0;++ fi->IsCIDFont = 0;++ return error;+ }+++/* END */
+ src/psaux/afmparse.h view
@@ -0,0 +1,88 @@+/***************************************************************************/+/* */+/* afmparse.h */+/* */+/* AFM parser (specification). */+/* */+/* Copyright 2006 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 __AFMPARSE_H__+#define __AFMPARSE_H__+++#include <ft2build.h>+#include FT_INTERNAL_POSTSCRIPT_AUX_H+++FT_BEGIN_HEADER+++ FT_LOCAL( FT_Error )+ afm_parser_init( AFM_Parser parser,+ FT_Memory memory,+ FT_Byte* base,+ FT_Byte* limit );+++ FT_LOCAL( void )+ afm_parser_done( AFM_Parser parser );+++ FT_LOCAL( FT_Error )+ afm_parser_parse( AFM_Parser parser );+++ enum AFM_ValueType_+ {+ AFM_VALUE_TYPE_STRING,+ AFM_VALUE_TYPE_NAME,+ AFM_VALUE_TYPE_FIXED, /* real number */+ AFM_VALUE_TYPE_INTEGER,+ AFM_VALUE_TYPE_BOOL,+ AFM_VALUE_TYPE_INDEX /* glyph index */+ };+++ typedef struct AFM_ValueRec_+ {+ enum AFM_ValueType_ type;+ union+ {+ char* s;+ FT_Fixed f;+ FT_Int i;+ FT_Bool b;++ } u;++ } AFM_ValueRec, *AFM_Value;++#define AFM_MAX_ARGUMENTS 5++ FT_LOCAL( FT_Int )+ afm_parser_read_vals( AFM_Parser parser,+ AFM_Value vals,+ FT_UInt n );++ /* read the next key from the next line or column */+ FT_LOCAL( char* )+ afm_parser_next_key( AFM_Parser parser,+ FT_Bool line,+ FT_Offset* len );++FT_END_HEADER++#endif /* __AFMPARSE_H__ */+++/* END */
+ src/psaux/psaux.c view
@@ -0,0 +1,34 @@+/***************************************************************************/+/* */+/* psaux.c */+/* */+/* FreeType auxiliary PostScript driver component (body only). */+/* */+/* Copyright 1996-2001, 2002, 2006 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 "psobjs.c"+#include "psauxmod.c"+#include "t1decode.c"+#include "t1cmap.c"++#ifndef T1_CONFIG_OPTION_NO_AFM+#include "afmparse.c"+#endif++#include "psconv.c"+++/* END */
+ src/psaux/psauxerr.h view
@@ -0,0 +1,41 @@+/***************************************************************************/+/* */+/* psauxerr.h */+/* */+/* PS auxiliary module error codes (specification only). */+/* */+/* Copyright 2001 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 PS auxiliary module error enumeration */+ /* constants. */+ /* */+ /*************************************************************************/++#ifndef __PSAUXERR_H__+#define __PSAUXERR_H__++#include FT_MODULE_ERRORS_H++#undef __FTERRORS_H__++#define FT_ERR_PREFIX PSaux_Err_+#define FT_ERR_BASE FT_Mod_Err_PSaux++#include FT_ERRORS_H++#endif /* __PSAUXERR_H__ */+++/* END */
+ src/psaux/psauxmod.c view
@@ -0,0 +1,139 @@+/***************************************************************************/+/* */+/* psauxmod.c */+/* */+/* FreeType auxiliary PostScript module implementation (body). */+/* */+/* Copyright 2000-2001, 2002, 2003, 2006 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 "psauxmod.h"+#include "psobjs.h"+#include "t1decode.h"+#include "t1cmap.h"++#ifndef T1_CONFIG_OPTION_NO_AFM+#include "afmparse.h"+#endif+++ FT_CALLBACK_TABLE_DEF+ const PS_Table_FuncsRec ps_table_funcs =+ {+ ps_table_new,+ ps_table_done,+ ps_table_add,+ ps_table_release+ };+++ FT_CALLBACK_TABLE_DEF+ const PS_Parser_FuncsRec ps_parser_funcs =+ {+ ps_parser_init,+ ps_parser_done,+ ps_parser_skip_spaces,+ ps_parser_skip_PS_token,+ ps_parser_to_int,+ ps_parser_to_fixed,+ ps_parser_to_bytes,+ ps_parser_to_coord_array,+ ps_parser_to_fixed_array,+ ps_parser_to_token,+ ps_parser_to_token_array,+ ps_parser_load_field,+ ps_parser_load_field_table+ };+++ FT_CALLBACK_TABLE_DEF+ const T1_Builder_FuncsRec t1_builder_funcs =+ {+ t1_builder_init,+ t1_builder_done,+ t1_builder_check_points,+ t1_builder_add_point,+ t1_builder_add_point1,+ t1_builder_add_contour,+ t1_builder_start_point,+ t1_builder_close_contour+ };+++ FT_CALLBACK_TABLE_DEF+ const T1_Decoder_FuncsRec t1_decoder_funcs =+ {+ t1_decoder_init,+ t1_decoder_done,+ t1_decoder_parse_charstrings+ };+++#ifndef T1_CONFIG_OPTION_NO_AFM+ FT_CALLBACK_TABLE_DEF+ const AFM_Parser_FuncsRec afm_parser_funcs =+ {+ afm_parser_init,+ afm_parser_done,+ afm_parser_parse+ };+#endif+++ FT_CALLBACK_TABLE_DEF+ const T1_CMap_ClassesRec t1_cmap_classes =+ {+ &t1_cmap_standard_class_rec,+ &t1_cmap_expert_class_rec,+ &t1_cmap_custom_class_rec,+ &t1_cmap_unicode_class_rec+ };+++ static+ const PSAux_Interface psaux_interface =+ {+ &ps_table_funcs,+ &ps_parser_funcs,+ &t1_builder_funcs,+ &t1_decoder_funcs,+ t1_decrypt,++ (const T1_CMap_ClassesRec*) &t1_cmap_classes,++#ifndef T1_CONFIG_OPTION_NO_AFM+ &afm_parser_funcs,+#else+ 0,+#endif+ };+++ FT_CALLBACK_TABLE_DEF+ const FT_Module_Class psaux_module_class =+ {+ 0,+ sizeof( FT_ModuleRec ),+ "psaux",+ 0x20000L,+ 0x20000L,++ &psaux_interface, /* module-specific interface */++ (FT_Module_Constructor)0,+ (FT_Module_Destructor) 0,+ (FT_Module_Requester) 0+ };+++/* END */
+ src/psaux/psauxmod.h view
@@ -0,0 +1,42 @@+/***************************************************************************/+/* */+/* psauxmod.h */+/* */+/* FreeType auxiliary PostScript module implementation (specification). */+/* */+/* Copyright 2000-2001 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 __PSAUXMOD_H__+#define __PSAUXMOD_H__+++#include <ft2build.h>+#include FT_MODULE_H+++FT_BEGIN_HEADER++#ifdef FT_CONFIG_OPTION_PIC+#error "this module does not support PIC yet"+#endif +++ FT_EXPORT_VAR( const FT_Module_Class ) psaux_driver_class;+++FT_END_HEADER++#endif /* __PSAUXMOD_H__ */+++/* END */
+ src/psaux/psconv.c view
@@ -0,0 +1,472 @@+/***************************************************************************/+/* */+/* psconv.c */+/* */+/* Some convenience conversions (body). */+/* */+/* Copyright 2006, 2008, 2009 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_POSTSCRIPT_AUX_H++#include "psconv.h"+#include "psauxerr.h"+++ /* The following array is used by various functions to quickly convert */+ /* digits (both decimal and non-decimal) into numbers. */++#if 'A' == 65+ /* ASCII */++ static const FT_Char ft_char_table[128] =+ {+ /* 0x00 */+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,+ -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,+ -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,+ };++ /* no character >= 0x80 can represent a valid number */+#define OP >=++#endif /* 'A' == 65 */++#if 'A' == 193+ /* EBCDIC */++ static const FT_Char ft_char_table[128] =+ {+ /* 0x80 */+ -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1,+ -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1,+ -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1,+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,+ -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1,+ -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1,+ -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1,+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,+ };++ /* no character < 0x80 can represent a valid number */+#define OP <++#endif /* 'A' == 193 */+++ FT_LOCAL_DEF( FT_Int )+ PS_Conv_Strtol( FT_Byte** cursor,+ FT_Byte* limit,+ FT_Int base )+ {+ FT_Byte* p = *cursor;+ FT_Int num = 0;+ FT_Bool sign = 0;+++ if ( p == limit || base < 2 || base > 36 )+ return 0;++ if ( *p == '-' || *p == '+' )+ {+ sign = FT_BOOL( *p == '-' );++ p++;+ if ( p == limit )+ return 0;+ }++ for ( ; p < limit; p++ )+ {+ FT_Char c;+++ if ( IS_PS_SPACE( *p ) || *p OP 0x80 )+ break;++ c = ft_char_table[*p & 0x7f];++ if ( c < 0 || c >= base )+ break;++ num = num * base + c;+ }++ if ( sign )+ num = -num;++ *cursor = p;++ return num;+ }+++ FT_LOCAL_DEF( FT_Int )+ PS_Conv_ToInt( FT_Byte** cursor,+ FT_Byte* limit )++ {+ FT_Byte* p;+ FT_Int num;+++ num = PS_Conv_Strtol( cursor, limit, 10 );+ p = *cursor;++ if ( p < limit && *p == '#' )+ {+ *cursor = p + 1;++ return PS_Conv_Strtol( cursor, limit, num );+ }+ else+ return num;+ }+++ FT_LOCAL_DEF( FT_Fixed )+ PS_Conv_ToFixed( FT_Byte** cursor,+ FT_Byte* limit,+ FT_Int power_ten )+ {+ FT_Byte* p = *cursor;+ FT_Fixed integral;+ FT_Long decimal = 0, divider = 1;+ FT_Bool sign = 0;+++ if ( p == limit )+ return 0;++ if ( *p == '-' || *p == '+' )+ {+ sign = FT_BOOL( *p == '-' );++ p++;+ if ( p == limit )+ return 0;+ }++ if ( *p != '.' )+ integral = PS_Conv_ToInt( &p, limit ) << 16;+ else+ integral = 0;++ /* read the decimal part */+ if ( p < limit && *p == '.' )+ {+ p++;++ for ( ; p < limit; p++ )+ {+ FT_Char c;+++ if ( IS_PS_SPACE( *p ) || *p OP 0x80 )+ break;++ c = ft_char_table[*p & 0x7f];++ if ( c < 0 || c >= 10 )+ break;++ if ( !integral && power_ten > 0 )+ {+ power_ten--;+ decimal = decimal * 10 + c;+ }+ else+ {+ if ( divider < 10000000L )+ {+ decimal = decimal * 10 + c;+ divider *= 10;+ }+ }+ }+ }++ /* read exponent, if any */+ if ( p + 1 < limit && ( *p == 'e' || *p == 'E' ) )+ {+ p++;+ power_ten += PS_Conv_ToInt( &p, limit );+ }++ while ( power_ten > 0 )+ {+ integral *= 10;+ decimal *= 10;+ power_ten--;+ }++ while ( power_ten < 0 )+ {+ integral /= 10;+ divider *= 10;+ power_ten++;+ }++ if ( decimal )+ integral += FT_DivFix( decimal, divider );++ if ( sign )+ integral = -integral;++ *cursor = p;++ return integral;+ }+++#if 0+ FT_LOCAL_DEF( FT_UInt )+ PS_Conv_StringDecode( FT_Byte** cursor,+ FT_Byte* limit,+ FT_Byte* buffer,+ FT_Offset n )+ {+ FT_Byte* p;+ FT_UInt r = 0;+++ for ( p = *cursor; r < n && p < limit; p++ )+ {+ FT_Byte b;+++ if ( *p != '\\' )+ {+ buffer[r++] = *p;++ continue;+ }++ p++;++ switch ( *p )+ {+ case 'n':+ b = '\n';+ break;+ case 'r':+ b = '\r';+ break;+ case 't':+ b = '\t';+ break;+ case 'b':+ b = '\b';+ break;+ case 'f':+ b = '\f';+ break;+ case '\r':+ p++;+ if ( *p != '\n' )+ {+ b = *p;++ break;+ }+ /* no break */+ case '\n':+ continue;+ break;+ default:+ if ( IS_PS_DIGIT( *p ) )+ {+ b = *p - '0';++ p++;++ if ( IS_PS_DIGIT( *p ) )+ {+ b = b * 8 + *p - '0';++ p++;++ if ( IS_PS_DIGIT( *p ) )+ b = b * 8 + *p - '0';+ else+ {+ buffer[r++] = b;+ b = *p;+ }+ }+ else+ {+ buffer[r++] = b;+ b = *p;+ }+ }+ else+ b = *p;+ break;+ }++ buffer[r++] = b;+ }++ *cursor = p;++ return r;+ }+#endif /* 0 */+++ FT_LOCAL_DEF( FT_UInt )+ PS_Conv_ASCIIHexDecode( FT_Byte** cursor,+ FT_Byte* limit,+ FT_Byte* buffer,+ FT_Offset n )+ {+ FT_Byte* p;+ FT_UInt r = 0;+ FT_UInt w = 0;+ FT_UInt pad = 0x01;+++ n *= 2;++#if 1++ p = *cursor;+ if ( n > (FT_UInt)( limit - p ) )+ n = (FT_UInt)( limit - p );++ /* we try to process two nibbles at a time to be as fast as possible */+ for ( ; r < n; r++ )+ {+ FT_UInt c = p[r];+++ if ( IS_PS_SPACE( c ) )+ continue;++ if ( c OP 0x80 )+ break;++ c = ft_char_table[c & 0x7F];+ if ( (unsigned)c >= 16 )+ break;++ pad = ( pad << 4 ) | c;+ if ( pad & 0x100 )+ {+ buffer[w++] = (FT_Byte)pad;+ pad = 0x01;+ }+ }++ if ( pad != 0x01 )+ buffer[w++] = (FT_Byte)( pad << 4 );++ *cursor = p + r;++ return w;++#else /* 0 */++ for ( r = 0; r < n; r++ )+ {+ FT_Char c;+++ if ( IS_PS_SPACE( *p ) )+ continue;++ if ( *p OP 0x80 )+ break;++ c = ft_char_table[*p & 0x7f];++ if ( (unsigned)c >= 16 )+ break;++ if ( r & 1 )+ {+ *buffer = (FT_Byte)(*buffer + c);+ buffer++;+ }+ else+ *buffer = (FT_Byte)(c << 4);++ r++;+ }++ *cursor = p;++ return ( r + 1 ) / 2;++#endif /* 0 */++ }+++ FT_LOCAL_DEF( FT_UInt )+ PS_Conv_EexecDecode( FT_Byte** cursor,+ FT_Byte* limit,+ FT_Byte* buffer,+ FT_Offset n,+ FT_UShort* seed )+ {+ FT_Byte* p;+ FT_UInt r;+ FT_UInt s = *seed;+++#if 1++ p = *cursor;+ if ( n > (FT_UInt)(limit - p) )+ n = (FT_UInt)(limit - p);++ for ( r = 0; r < n; r++ )+ {+ FT_UInt val = p[r];+ FT_UInt b = ( val ^ ( s >> 8 ) );+++ s = ( (val + s)*52845U + 22719 ) & 0xFFFFU;+ buffer[r] = (FT_Byte) b;+ }++ *cursor = p + n;+ *seed = (FT_UShort)s;++#else /* 0 */++ for ( r = 0, p = *cursor; r < n && p < limit; r++, p++ )+ {+ FT_Byte b = (FT_Byte)( *p ^ ( s >> 8 ) );+++ s = (FT_UShort)( ( *p + s ) * 52845U + 22719 );+ *buffer++ = b;+ }+ *cursor = p;+ *seed = s;++#endif /* 0 */++ return r;+ }+++/* END */
+ src/psaux/psconv.h view
@@ -0,0 +1,71 @@+/***************************************************************************/+/* */+/* psconv.h */+/* */+/* Some convenience conversions (specification). */+/* */+/* Copyright 2006 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 __PSCONV_H__+#define __PSCONV_H__+++#include <ft2build.h>+#include FT_INTERNAL_POSTSCRIPT_AUX_H++FT_BEGIN_HEADER+++ FT_LOCAL( FT_Int )+ PS_Conv_Strtol( FT_Byte** cursor,+ FT_Byte* limit,+ FT_Int base );+++ FT_LOCAL( FT_Int )+ PS_Conv_ToInt( FT_Byte** cursor,+ FT_Byte* limit );++ FT_LOCAL( FT_Fixed )+ PS_Conv_ToFixed( FT_Byte** cursor,+ FT_Byte* limit,+ FT_Int power_ten );++#if 0+ FT_LOCAL( FT_UInt )+ PS_Conv_StringDecode( FT_Byte** cursor,+ FT_Byte* limit,+ FT_Byte* buffer,+ FT_Offset n );+#endif++ FT_LOCAL( FT_UInt )+ PS_Conv_ASCIIHexDecode( FT_Byte** cursor,+ FT_Byte* limit,+ FT_Byte* buffer,+ FT_Offset n );++ FT_LOCAL( FT_UInt )+ PS_Conv_EexecDecode( FT_Byte** cursor,+ FT_Byte* limit,+ FT_Byte* buffer,+ FT_Offset n,+ FT_UShort* seed );+++FT_END_HEADER++#endif /* __PSCONV_H__ */+++/* END */
+ src/psaux/psobjs.c view
@@ -0,0 +1,1711 @@+/***************************************************************************/+/* */+/* psobjs.c */+/* */+/* Auxiliary functions for PostScript fonts (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */+/* 2010 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_POSTSCRIPT_AUX_H+#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_CALC_H++#include "psobjs.h"+#include "psconv.h"++#include "psauxerr.h"+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_psobjs+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** PS_TABLE *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /*************************************************************************/+ /* */+ /* <Function> */+ /* ps_table_new */+ /* */+ /* <Description> */+ /* Initializes a PS_Table. */+ /* */+ /* <InOut> */+ /* table :: The address of the target table. */+ /* */+ /* <Input> */+ /* count :: The table size = the maximum number of elements. */+ /* */+ /* memory :: The memory object to use for all subsequent */+ /* reallocations. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ ps_table_new( PS_Table table,+ FT_Int count,+ FT_Memory memory )+ {+ FT_Error error;+++ table->memory = memory;+ if ( FT_NEW_ARRAY( table->elements, count ) ||+ FT_NEW_ARRAY( table->lengths, count ) )+ goto Exit;++ table->max_elems = count;+ table->init = 0xDEADBEEFUL;+ table->num_elems = 0;+ table->block = 0;+ table->capacity = 0;+ table->cursor = 0;++ *(PS_Table_FuncsRec*)&table->funcs = ps_table_funcs;++ Exit:+ if ( error )+ FT_FREE( table->elements );++ return error;+ }+++ static void+ shift_elements( PS_Table table,+ FT_Byte* old_base )+ {+ FT_PtrDist delta = table->block - old_base;+ FT_Byte** offset = table->elements;+ FT_Byte** limit = offset + table->max_elems;+++ for ( ; offset < limit; offset++ )+ {+ if ( offset[0] )+ offset[0] += delta;+ }+ }+++ static FT_Error+ reallocate_t1_table( PS_Table table,+ FT_Long new_size )+ {+ FT_Memory memory = table->memory;+ FT_Byte* old_base = table->block;+ FT_Error error;+++ /* allocate new base block */+ if ( FT_ALLOC( table->block, new_size ) )+ {+ table->block = old_base;+ return error;+ }++ /* copy elements and shift offsets */+ if ( old_base )+ {+ FT_MEM_COPY( table->block, old_base, table->capacity );+ shift_elements( table, old_base );+ FT_FREE( old_base );+ }++ table->capacity = new_size;++ return PSaux_Err_Ok;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* ps_table_add */+ /* */+ /* <Description> */+ /* Adds an object to a PS_Table, possibly growing its memory block. */+ /* */+ /* <InOut> */+ /* table :: The target table. */+ /* */+ /* <Input> */+ /* idx :: The index of the object in the table. */+ /* */+ /* object :: The address of the object to copy in memory. */+ /* */+ /* length :: The length in bytes of the source object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. An error is returned if a */+ /* reallocation fails. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ ps_table_add( PS_Table table,+ FT_Int idx,+ void* object,+ FT_PtrDist length )+ {+ if ( idx < 0 || idx >= table->max_elems )+ {+ FT_ERROR(( "ps_table_add: invalid index\n" ));+ return PSaux_Err_Invalid_Argument;+ }++ if ( length < 0 )+ {+ FT_ERROR(( "ps_table_add: invalid length\n" ));+ return PSaux_Err_Invalid_Argument;+ }++ /* grow the base block if needed */+ if ( table->cursor + length > table->capacity )+ {+ FT_Error error;+ FT_Offset new_size = table->capacity;+ FT_Long in_offset;+++ in_offset = (FT_Long)((FT_Byte*)object - table->block);+ if ( (FT_ULong)in_offset >= table->capacity )+ in_offset = -1;++ while ( new_size < table->cursor + length )+ {+ /* increase size by 25% and round up to the nearest multiple+ of 1024 */+ new_size += ( new_size >> 2 ) + 1;+ new_size = FT_PAD_CEIL( new_size, 1024 );+ }++ error = reallocate_t1_table( table, new_size );+ if ( error )+ return error;++ if ( in_offset >= 0 )+ object = table->block + in_offset;+ }++ /* add the object to the base block and adjust offset */+ table->elements[idx] = table->block + table->cursor;+ table->lengths [idx] = length;+ FT_MEM_COPY( table->block + table->cursor, object, length );++ table->cursor += length;+ return PSaux_Err_Ok;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* ps_table_done */+ /* */+ /* <Description> */+ /* Finalizes a PS_TableRec (i.e., reallocate it to its current */+ /* cursor). */+ /* */+ /* <InOut> */+ /* table :: The target table. */+ /* */+ /* <Note> */+ /* This function does NOT release the heap's memory block. It is up */+ /* to the caller to clean it, or reference it in its own structures. */+ /* */+ FT_LOCAL_DEF( void )+ ps_table_done( PS_Table table )+ {+ FT_Memory memory = table->memory;+ FT_Error error;+ FT_Byte* old_base = table->block;+++ /* should never fail, because rec.cursor <= rec.size */+ if ( !old_base )+ return;++ if ( FT_ALLOC( table->block, table->cursor ) )+ return;+ FT_MEM_COPY( table->block, old_base, table->cursor );+ shift_elements( table, old_base );++ table->capacity = table->cursor;+ FT_FREE( old_base );++ FT_UNUSED( error );+ }+++ FT_LOCAL_DEF( void )+ ps_table_release( PS_Table table )+ {+ FT_Memory memory = table->memory;+++ if ( (FT_ULong)table->init == 0xDEADBEEFUL )+ {+ FT_FREE( table->block );+ FT_FREE( table->elements );+ FT_FREE( table->lengths );+ table->init = 0;+ }+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** T1 PARSER *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+++ /* first character must be already part of the comment */++ static void+ skip_comment( FT_Byte* *acur,+ FT_Byte* limit )+ {+ FT_Byte* cur = *acur;+++ while ( cur < limit )+ {+ if ( IS_PS_NEWLINE( *cur ) )+ break;+ cur++;+ }++ *acur = cur;+ }+++ static void+ skip_spaces( FT_Byte* *acur,+ FT_Byte* limit )+ {+ FT_Byte* cur = *acur;+++ while ( cur < limit )+ {+ if ( !IS_PS_SPACE( *cur ) )+ {+ if ( *cur == '%' )+ /* According to the PLRM, a comment is equal to a space. */+ skip_comment( &cur, limit );+ else+ break;+ }+ cur++;+ }++ *acur = cur;+ }+++#define IS_OCTAL_DIGIT( c ) ( '0' <= (c) && (c) <= '7' )+++ /* first character must be `('; */+ /* *acur is positioned at the character after the closing `)' */++ static FT_Error+ skip_literal_string( FT_Byte* *acur,+ FT_Byte* limit )+ {+ FT_Byte* cur = *acur;+ FT_Int embed = 0;+ FT_Error error = PSaux_Err_Invalid_File_Format;+ unsigned int i;+++ while ( cur < limit )+ {+ FT_Byte c = *cur;+++ ++cur;++ if ( c == '\\' )+ {+ /* Red Book 3rd ed., section `Literal Text Strings', p. 29: */+ /* A backslash can introduce three different types */+ /* of escape sequences: */+ /* - a special escaped char like \r, \n, etc. */+ /* - a one-, two-, or three-digit octal number */+ /* - none of the above in which case the backslash is ignored */++ if ( cur == limit )+ /* error (or to be ignored?) */+ break;++ switch ( *cur )+ {+ /* skip `special' escape */+ case 'n':+ case 'r':+ case 't':+ case 'b':+ case 'f':+ case '\\':+ case '(':+ case ')':+ ++cur;+ break;++ default:+ /* skip octal escape or ignore backslash */+ for ( i = 0; i < 3 && cur < limit; ++i )+ {+ if ( !IS_OCTAL_DIGIT( *cur ) )+ break;++ ++cur;+ }+ }+ }+ else if ( c == '(' )+ embed++;+ else if ( c == ')' )+ {+ embed--;+ if ( embed == 0 )+ {+ error = PSaux_Err_Ok;+ break;+ }+ }+ }++ *acur = cur;++ return error;+ }+++ /* first character must be `<' */++ static FT_Error+ skip_string( FT_Byte* *acur,+ FT_Byte* limit )+ {+ FT_Byte* cur = *acur;+ FT_Error err = PSaux_Err_Ok;+++ while ( ++cur < limit )+ {+ /* All whitespace characters are ignored. */+ skip_spaces( &cur, limit );+ if ( cur >= limit )+ break;++ if ( !IS_PS_XDIGIT( *cur ) )+ break;+ }++ if ( cur < limit && *cur != '>' )+ {+ FT_ERROR(( "skip_string: missing closing delimiter `>'\n" ));+ err = PSaux_Err_Invalid_File_Format;+ }+ else+ cur++;++ *acur = cur;+ return err;+ }+++ /* first character must be the opening brace that */+ /* starts the procedure */++ /* NB: [ and ] need not match: */+ /* `/foo {[} def' is a valid PostScript fragment, */+ /* even within a Type1 font */++ static FT_Error+ skip_procedure( FT_Byte* *acur,+ FT_Byte* limit )+ {+ FT_Byte* cur;+ FT_Int embed = 0;+ FT_Error error = PSaux_Err_Ok;+++ FT_ASSERT( **acur == '{' );++ for ( cur = *acur; cur < limit && error == PSaux_Err_Ok; ++cur )+ {+ switch ( *cur )+ {+ case '{':+ ++embed;+ break;++ case '}':+ --embed;+ if ( embed == 0 )+ {+ ++cur;+ goto end;+ }+ break;++ case '(':+ error = skip_literal_string( &cur, limit );+ break;++ case '<':+ error = skip_string( &cur, limit );+ break;++ case '%':+ skip_comment( &cur, limit );+ break;+ }+ }++ end:+ if ( embed != 0 )+ error = PSaux_Err_Invalid_File_Format;++ *acur = cur;++ return error;+ }+++ /***********************************************************************/+ /* */+ /* All exported parsing routines handle leading whitespace and stop at */+ /* the first character which isn't part of the just handled token. */+ /* */+ /***********************************************************************/+++ FT_LOCAL_DEF( void )+ ps_parser_skip_PS_token( PS_Parser parser )+ {+ /* Note: PostScript allows any non-delimiting, non-whitespace */+ /* character in a name (PS Ref Manual, 3rd ed, p31). */+ /* PostScript delimiters are (, ), <, >, [, ], {, }, /, and %. */++ FT_Byte* cur = parser->cursor;+ FT_Byte* limit = parser->limit;+ FT_Error error = PSaux_Err_Ok;+++ skip_spaces( &cur, limit ); /* this also skips comments */+ if ( cur >= limit )+ goto Exit;++ /* self-delimiting, single-character tokens */+ if ( *cur == '[' || *cur == ']' )+ {+ cur++;+ goto Exit;+ }++ /* skip balanced expressions (procedures and strings) */++ if ( *cur == '{' ) /* {...} */+ {+ error = skip_procedure( &cur, limit );+ goto Exit;+ }++ if ( *cur == '(' ) /* (...) */+ {+ error = skip_literal_string( &cur, limit );+ goto Exit;+ }++ if ( *cur == '<' ) /* <...> */+ {+ if ( cur + 1 < limit && *(cur + 1) == '<' ) /* << */+ {+ cur++;+ cur++;+ }+ else+ error = skip_string( &cur, limit );++ goto Exit;+ }++ if ( *cur == '>' )+ {+ cur++;+ if ( cur >= limit || *cur != '>' ) /* >> */+ {+ FT_ERROR(( "ps_parser_skip_PS_token:"+ " unexpected closing delimiter `>'\n" ));+ error = PSaux_Err_Invalid_File_Format;+ goto Exit;+ }+ cur++;+ goto Exit;+ }++ if ( *cur == '/' )+ cur++;++ /* anything else */+ while ( cur < limit )+ {+ /* *cur might be invalid (e.g., ')' or '}'), but this */+ /* is handled by the test `cur == parser->cursor' below */+ if ( IS_PS_DELIM( *cur ) )+ break;++ cur++;+ }++ Exit:+ if ( cur == parser->cursor )+ {+ FT_ERROR(( "ps_parser_skip_PS_token:"+ " current token is `%c' which is self-delimiting\n"+ " "+ " but invalid at this point\n",+ *cur ));++ error = PSaux_Err_Invalid_File_Format;+ }++ parser->error = error;+ parser->cursor = cur;+ }+++ FT_LOCAL_DEF( void )+ ps_parser_skip_spaces( PS_Parser parser )+ {+ skip_spaces( &parser->cursor, parser->limit );+ }+++ /* `token' here means either something between balanced delimiters */+ /* or the next token; the delimiters are not removed. */++ FT_LOCAL_DEF( void )+ ps_parser_to_token( PS_Parser parser,+ T1_Token token )+ {+ FT_Byte* cur;+ FT_Byte* limit;+ FT_Int embed;+++ token->type = T1_TOKEN_TYPE_NONE;+ token->start = 0;+ token->limit = 0;++ /* first of all, skip leading whitespace */+ ps_parser_skip_spaces( parser );++ cur = parser->cursor;+ limit = parser->limit;++ if ( cur >= limit )+ return;++ switch ( *cur )+ {+ /************* check for literal string *****************/+ case '(':+ token->type = T1_TOKEN_TYPE_STRING;+ token->start = cur;++ if ( skip_literal_string( &cur, limit ) == PSaux_Err_Ok )+ token->limit = cur;+ break;++ /************* check for programs/array *****************/+ case '{':+ token->type = T1_TOKEN_TYPE_ARRAY;+ token->start = cur;++ if ( skip_procedure( &cur, limit ) == PSaux_Err_Ok )+ token->limit = cur;+ break;++ /************* check for table/array ********************/+ /* XXX: in theory we should also look for "<<" */+ /* since this is semantically equivalent to "["; */+ /* in practice it doesn't matter (?) */+ case '[':+ token->type = T1_TOKEN_TYPE_ARRAY;+ embed = 1;+ token->start = cur++;++ /* we need this to catch `[ ]' */+ parser->cursor = cur;+ ps_parser_skip_spaces( parser );+ cur = parser->cursor;++ while ( cur < limit && !parser->error )+ {+ /* XXX: this is wrong because it does not */+ /* skip comments, procedures, and strings */+ if ( *cur == '[' )+ embed++;+ else if ( *cur == ']' )+ {+ embed--;+ if ( embed <= 0 )+ {+ token->limit = ++cur;+ break;+ }+ }++ parser->cursor = cur;+ ps_parser_skip_PS_token( parser );+ /* we need this to catch `[XXX ]' */+ ps_parser_skip_spaces ( parser );+ cur = parser->cursor;+ }+ break;++ /* ************ otherwise, it is any token **************/+ default:+ token->start = cur;+ token->type = ( *cur == '/' ? T1_TOKEN_TYPE_KEY : T1_TOKEN_TYPE_ANY );+ ps_parser_skip_PS_token( parser );+ cur = parser->cursor;+ if ( !parser->error )+ token->limit = cur;+ }++ if ( !token->limit )+ {+ token->start = 0;+ token->type = T1_TOKEN_TYPE_NONE;+ }++ parser->cursor = cur;+ }+++ /* NB: `tokens' can be NULL if we only want to count */+ /* the number of array elements */++ FT_LOCAL_DEF( void )+ ps_parser_to_token_array( PS_Parser parser,+ T1_Token tokens,+ FT_UInt max_tokens,+ FT_Int* pnum_tokens )+ {+ T1_TokenRec master;+++ *pnum_tokens = -1;++ /* this also handles leading whitespace */+ ps_parser_to_token( parser, &master );++ if ( master.type == T1_TOKEN_TYPE_ARRAY )+ {+ FT_Byte* old_cursor = parser->cursor;+ FT_Byte* old_limit = parser->limit;+ T1_Token cur = tokens;+ T1_Token limit = cur + max_tokens;+++ /* don't include outermost delimiters */+ parser->cursor = master.start + 1;+ parser->limit = master.limit - 1;++ while ( parser->cursor < parser->limit )+ {+ T1_TokenRec token;+++ ps_parser_to_token( parser, &token );+ if ( !token.type )+ break;++ if ( tokens != NULL && cur < limit )+ *cur = token;++ cur++;+ }++ *pnum_tokens = (FT_Int)( cur - tokens );++ parser->cursor = old_cursor;+ parser->limit = old_limit;+ }+ }+++ /* first character must be a delimiter or a part of a number */+ /* NB: `coords' can be NULL if we just want to skip the */+ /* array; in this case we ignore `max_coords' */++ static FT_Int+ ps_tocoordarray( FT_Byte* *acur,+ FT_Byte* limit,+ FT_Int max_coords,+ FT_Short* coords )+ {+ FT_Byte* cur = *acur;+ FT_Int count = 0;+ FT_Byte c, ender;+++ if ( cur >= limit )+ goto Exit;++ /* check for the beginning of an array; otherwise, only one number */+ /* will be read */+ c = *cur;+ ender = 0;++ if ( c == '[' )+ ender = ']';+ else if ( c == '{' )+ ender = '}';++ if ( ender )+ cur++;++ /* now, read the coordinates */+ while ( cur < limit )+ {+ FT_Short dummy;+ FT_Byte* old_cur;+++ /* skip whitespace in front of data */+ skip_spaces( &cur, limit );+ if ( cur >= limit )+ goto Exit;++ if ( *cur == ender )+ {+ cur++;+ break;+ }++ old_cur = cur;++ if ( coords != NULL && count >= max_coords )+ break;++ /* call PS_Conv_ToFixed() even if coords == NULL */+ /* to properly parse number at `cur' */+ *( coords != NULL ? &coords[count] : &dummy ) =+ (FT_Short)( PS_Conv_ToFixed( &cur, limit, 0 ) >> 16 );++ if ( old_cur == cur )+ {+ count = -1;+ goto Exit;+ }+ else+ count++;++ if ( !ender )+ break;+ }++ Exit:+ *acur = cur;+ return count;+ }+++ /* first character must be a delimiter or a part of a number */+ /* NB: `values' can be NULL if we just want to skip the */+ /* array; in this case we ignore `max_values' */++ static FT_Int+ ps_tofixedarray( FT_Byte* *acur,+ FT_Byte* limit,+ FT_Int max_values,+ FT_Fixed* values,+ FT_Int power_ten )+ {+ FT_Byte* cur = *acur;+ FT_Int count = 0;+ FT_Byte c, ender;+++ if ( cur >= limit )+ goto Exit;++ /* Check for the beginning of an array. Otherwise, only one number */+ /* will be read. */+ c = *cur;+ ender = 0;++ if ( c == '[' )+ ender = ']';+ else if ( c == '{' )+ ender = '}';++ if ( ender )+ cur++;++ /* now, read the values */+ while ( cur < limit )+ {+ FT_Fixed dummy;+ FT_Byte* old_cur;+++ /* skip whitespace in front of data */+ skip_spaces( &cur, limit );+ if ( cur >= limit )+ goto Exit;++ if ( *cur == ender )+ {+ cur++;+ break;+ }++ old_cur = cur;++ if ( values != NULL && count >= max_values )+ break;++ /* call PS_Conv_ToFixed() even if coords == NULL */+ /* to properly parse number at `cur' */+ *( values != NULL ? &values[count] : &dummy ) =+ PS_Conv_ToFixed( &cur, limit, power_ten );++ if ( old_cur == cur )+ {+ count = -1;+ goto Exit;+ }+ else+ count++;++ if ( !ender )+ break;+ }++ Exit:+ *acur = cur;+ return count;+ }+++#if 0++ static FT_String*+ ps_tostring( FT_Byte** cursor,+ FT_Byte* limit,+ FT_Memory memory )+ {+ FT_Byte* cur = *cursor;+ FT_PtrDist len = 0;+ FT_Int count;+ FT_String* result;+ FT_Error error;+++ /* XXX: some stupid fonts have a `Notice' or `Copyright' string */+ /* that simply doesn't begin with an opening parenthesis, even */+ /* though they have a closing one! E.g. "amuncial.pfb" */+ /* */+ /* We must deal with these ill-fated cases there. Note that */+ /* these fonts didn't work with the old Type 1 driver as the */+ /* notice/copyright was not recognized as a valid string token */+ /* and made the old token parser commit errors. */++ while ( cur < limit && ( *cur == ' ' || *cur == '\t' ) )+ cur++;+ if ( cur + 1 >= limit )+ return 0;++ if ( *cur == '(' )+ cur++; /* skip the opening parenthesis, if there is one */++ *cursor = cur;+ count = 0;++ /* then, count its length */+ for ( ; cur < limit; cur++ )+ {+ if ( *cur == '(' )+ count++;++ else if ( *cur == ')' )+ {+ count--;+ if ( count < 0 )+ break;+ }+ }++ len = cur - *cursor;+ if ( cur >= limit || FT_ALLOC( result, len + 1 ) )+ return 0;++ /* now copy the string */+ FT_MEM_COPY( result, *cursor, len );+ result[len] = '\0';+ *cursor = cur;+ return result;+ }++#endif /* 0 */+++ static int+ ps_tobool( FT_Byte* *acur,+ FT_Byte* limit )+ {+ FT_Byte* cur = *acur;+ FT_Bool result = 0;+++ /* return 1 if we find `true', 0 otherwise */+ if ( cur + 3 < limit &&+ cur[0] == 't' &&+ cur[1] == 'r' &&+ cur[2] == 'u' &&+ cur[3] == 'e' )+ {+ result = 1;+ cur += 5;+ }+ else if ( cur + 4 < limit &&+ cur[0] == 'f' &&+ cur[1] == 'a' &&+ cur[2] == 'l' &&+ cur[3] == 's' &&+ cur[4] == 'e' )+ {+ result = 0;+ cur += 6;+ }++ *acur = cur;+ return result;+ }+++ /* load a simple field (i.e. non-table) into the current list of objects */++ FT_LOCAL_DEF( FT_Error )+ ps_parser_load_field( PS_Parser parser,+ const T1_Field field,+ void** objects,+ FT_UInt max_objects,+ FT_ULong* pflags )+ {+ T1_TokenRec token;+ FT_Byte* cur;+ FT_Byte* limit;+ FT_UInt count;+ FT_UInt idx;+ FT_Error error;+++ /* this also skips leading whitespace */+ ps_parser_to_token( parser, &token );+ if ( !token.type )+ goto Fail;++ count = 1;+ idx = 0;+ cur = token.start;+ limit = token.limit;++ /* we must detect arrays in /FontBBox */+ if ( field->type == T1_FIELD_TYPE_BBOX )+ {+ T1_TokenRec token2;+ FT_Byte* old_cur = parser->cursor;+ FT_Byte* old_limit = parser->limit;+++ /* don't include delimiters */+ parser->cursor = token.start + 1;+ parser->limit = token.limit - 1;++ ps_parser_to_token( parser, &token2 );+ parser->cursor = old_cur;+ parser->limit = old_limit;++ if ( token2.type == T1_TOKEN_TYPE_ARRAY )+ goto FieldArray;+ }+ else if ( token.type == T1_TOKEN_TYPE_ARRAY )+ {+ FieldArray:+ /* if this is an array and we have no blend, an error occurs */+ if ( max_objects == 0 )+ goto Fail;++ count = max_objects;+ idx = 1;++ /* don't include delimiters */+ cur++;+ limit--;+ }++ for ( ; count > 0; count--, idx++ )+ {+ FT_Byte* q = (FT_Byte*)objects[idx] + field->offset;+ FT_Long val;+ FT_String* string;+++ skip_spaces( &cur, limit );++ switch ( field->type )+ {+ case T1_FIELD_TYPE_BOOL:+ val = ps_tobool( &cur, limit );+ goto Store_Integer;++ case T1_FIELD_TYPE_FIXED:+ val = PS_Conv_ToFixed( &cur, limit, 0 );+ goto Store_Integer;++ case T1_FIELD_TYPE_FIXED_1000:+ val = PS_Conv_ToFixed( &cur, limit, 3 );+ goto Store_Integer;++ case T1_FIELD_TYPE_INTEGER:+ val = PS_Conv_ToInt( &cur, limit );+ /* fall through */++ Store_Integer:+ switch ( field->size )+ {+ case (8 / FT_CHAR_BIT):+ *(FT_Byte*)q = (FT_Byte)val;+ break;++ case (16 / FT_CHAR_BIT):+ *(FT_UShort*)q = (FT_UShort)val;+ break;++ case (32 / FT_CHAR_BIT):+ *(FT_UInt32*)q = (FT_UInt32)val;+ break;++ default: /* for 64-bit systems */+ *(FT_Long*)q = val;+ }+ break;++ case T1_FIELD_TYPE_STRING:+ case T1_FIELD_TYPE_KEY:+ {+ FT_Memory memory = parser->memory;+ FT_UInt len = (FT_UInt)( limit - cur );+++ if ( cur >= limit )+ break;++ /* we allow both a string or a name */+ /* for cases like /FontName (foo) def */+ if ( token.type == T1_TOKEN_TYPE_KEY )+ {+ /* don't include leading `/' */+ len--;+ cur++;+ }+ else if ( token.type == T1_TOKEN_TYPE_STRING )+ {+ /* don't include delimiting parentheses */+ /* XXX we don't handle <<...>> here */+ /* XXX should we convert octal escapes? */+ /* if so, what encoding should we use? */+ cur++;+ len -= 2;+ }+ else+ {+ FT_ERROR(( "ps_parser_load_field:"+ " expected a name or string\n"+ " "+ " but found token of type %d instead\n",+ token.type ));+ error = PSaux_Err_Invalid_File_Format;+ goto Exit;+ }++ /* for this to work (FT_String**)q must have been */+ /* initialized to NULL */+ if ( *(FT_String**)q != NULL )+ {+ FT_TRACE0(( "ps_parser_load_field: overwriting field %s\n",+ field->ident ));+ FT_FREE( *(FT_String**)q );+ *(FT_String**)q = NULL;+ }++ if ( FT_ALLOC( string, len + 1 ) )+ goto Exit;++ FT_MEM_COPY( string, cur, len );+ string[len] = 0;++ *(FT_String**)q = string;+ }+ break;++ case T1_FIELD_TYPE_BBOX:+ {+ FT_Fixed temp[4];+ FT_BBox* bbox = (FT_BBox*)q;+ FT_Int result;+++ result = ps_tofixedarray( &cur, limit, 4, temp, 0 );++ if ( result < 0 )+ {+ FT_ERROR(( "ps_parser_load_field:"+ " expected four integers in bounding box\n" ));+ error = PSaux_Err_Invalid_File_Format;+ goto Exit;+ }++ bbox->xMin = FT_RoundFix( temp[0] );+ bbox->yMin = FT_RoundFix( temp[1] );+ bbox->xMax = FT_RoundFix( temp[2] );+ bbox->yMax = FT_RoundFix( temp[3] );+ }+ break;++ default:+ /* an error occurred */+ goto Fail;+ }+ }++#if 0 /* obsolete -- keep for reference */+ if ( pflags )+ *pflags |= 1L << field->flag_bit;+#else+ FT_UNUSED( pflags );+#endif++ error = PSaux_Err_Ok;++ Exit:+ return error;++ Fail:+ error = PSaux_Err_Invalid_File_Format;+ goto Exit;+ }+++#define T1_MAX_TABLE_ELEMENTS 32+++ FT_LOCAL_DEF( FT_Error )+ ps_parser_load_field_table( PS_Parser parser,+ const T1_Field field,+ void** objects,+ FT_UInt max_objects,+ FT_ULong* pflags )+ {+ T1_TokenRec elements[T1_MAX_TABLE_ELEMENTS];+ T1_Token token;+ FT_Int num_elements;+ FT_Error error = PSaux_Err_Ok;+ FT_Byte* old_cursor;+ FT_Byte* old_limit;+ T1_FieldRec fieldrec = *(T1_Field)field;+++ fieldrec.type = T1_FIELD_TYPE_INTEGER;+ if ( field->type == T1_FIELD_TYPE_FIXED_ARRAY ||+ field->type == T1_FIELD_TYPE_BBOX )+ fieldrec.type = T1_FIELD_TYPE_FIXED;++ ps_parser_to_token_array( parser, elements,+ T1_MAX_TABLE_ELEMENTS, &num_elements );+ if ( num_elements < 0 )+ {+ error = PSaux_Err_Ignore;+ goto Exit;+ }+ if ( (FT_UInt)num_elements > field->array_max )+ num_elements = field->array_max;++ old_cursor = parser->cursor;+ old_limit = parser->limit;++ /* we store the elements count if necessary; */+ /* we further assume that `count_offset' can't be zero */+ if ( field->type != T1_FIELD_TYPE_BBOX && field->count_offset != 0 )+ *(FT_Byte*)( (FT_Byte*)objects[0] + field->count_offset ) =+ (FT_Byte)num_elements;++ /* we now load each element, adjusting the field.offset on each one */+ token = elements;+ for ( ; num_elements > 0; num_elements--, token++ )+ {+ parser->cursor = token->start;+ parser->limit = token->limit;+ ps_parser_load_field( parser, &fieldrec, objects, max_objects, 0 );+ fieldrec.offset += fieldrec.size;+ }++#if 0 /* obsolete -- keep for reference */+ if ( pflags )+ *pflags |= 1L << field->flag_bit;+#else+ FT_UNUSED( pflags );+#endif++ parser->cursor = old_cursor;+ parser->limit = old_limit;++ Exit:+ return error;+ }+++ FT_LOCAL_DEF( FT_Long )+ ps_parser_to_int( PS_Parser parser )+ {+ ps_parser_skip_spaces( parser );+ return PS_Conv_ToInt( &parser->cursor, parser->limit );+ }+++ /* first character must be `<' if `delimiters' is non-zero */++ FT_LOCAL_DEF( FT_Error )+ ps_parser_to_bytes( PS_Parser parser,+ FT_Byte* bytes,+ FT_Offset max_bytes,+ FT_Long* pnum_bytes,+ FT_Bool delimiters )+ {+ FT_Error error = PSaux_Err_Ok;+ FT_Byte* cur;+++ ps_parser_skip_spaces( parser );+ cur = parser->cursor;++ if ( cur >= parser->limit )+ goto Exit;++ if ( delimiters )+ {+ if ( *cur != '<' )+ {+ FT_ERROR(( "ps_parser_to_bytes: Missing starting delimiter `<'\n" ));+ error = PSaux_Err_Invalid_File_Format;+ goto Exit;+ }++ cur++;+ }++ *pnum_bytes = PS_Conv_ASCIIHexDecode( &cur,+ parser->limit,+ bytes,+ max_bytes );++ if ( delimiters )+ {+ if ( cur < parser->limit && *cur != '>' )+ {+ FT_ERROR(( "ps_parser_to_bytes: Missing closing delimiter `>'\n" ));+ error = PSaux_Err_Invalid_File_Format;+ goto Exit;+ }++ cur++;+ }++ parser->cursor = cur;++ Exit:+ return error;+ }+++ FT_LOCAL_DEF( FT_Fixed )+ ps_parser_to_fixed( PS_Parser parser,+ FT_Int power_ten )+ {+ ps_parser_skip_spaces( parser );+ return PS_Conv_ToFixed( &parser->cursor, parser->limit, power_ten );+ }+++ FT_LOCAL_DEF( FT_Int )+ ps_parser_to_coord_array( PS_Parser parser,+ FT_Int max_coords,+ FT_Short* coords )+ {+ ps_parser_skip_spaces( parser );+ return ps_tocoordarray( &parser->cursor, parser->limit,+ max_coords, coords );+ }+++ FT_LOCAL_DEF( FT_Int )+ ps_parser_to_fixed_array( PS_Parser parser,+ FT_Int max_values,+ FT_Fixed* values,+ FT_Int power_ten )+ {+ ps_parser_skip_spaces( parser );+ return ps_tofixedarray( &parser->cursor, parser->limit,+ max_values, values, power_ten );+ }+++#if 0++ FT_LOCAL_DEF( FT_String* )+ T1_ToString( PS_Parser parser )+ {+ return ps_tostring( &parser->cursor, parser->limit, parser->memory );+ }+++ FT_LOCAL_DEF( FT_Bool )+ T1_ToBool( PS_Parser parser )+ {+ return ps_tobool( &parser->cursor, parser->limit );+ }++#endif /* 0 */+++ FT_LOCAL_DEF( void )+ ps_parser_init( PS_Parser parser,+ FT_Byte* base,+ FT_Byte* limit,+ FT_Memory memory )+ {+ parser->error = PSaux_Err_Ok;+ parser->base = base;+ parser->limit = limit;+ parser->cursor = base;+ parser->memory = memory;+ parser->funcs = ps_parser_funcs;+ }+++ FT_LOCAL_DEF( void )+ ps_parser_done( PS_Parser parser )+ {+ FT_UNUSED( parser );+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** T1 BUILDER *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /*************************************************************************/+ /* */+ /* <Function> */+ /* t1_builder_init */+ /* */+ /* <Description> */+ /* Initializes a given glyph builder. */+ /* */+ /* <InOut> */+ /* builder :: A pointer to the glyph builder to initialize. */+ /* */+ /* <Input> */+ /* face :: The current face object. */+ /* */+ /* size :: The current size object. */+ /* */+ /* glyph :: The current glyph object. */+ /* */+ /* hinting :: Whether hinting should be applied. */+ /* */+ FT_LOCAL_DEF( void )+ t1_builder_init( T1_Builder builder,+ FT_Face face,+ FT_Size size,+ FT_GlyphSlot glyph,+ FT_Bool hinting )+ {+ builder->parse_state = T1_Parse_Start;+ builder->load_points = 1;++ builder->face = face;+ builder->glyph = glyph;+ builder->memory = face->memory;++ if ( glyph )+ {+ FT_GlyphLoader loader = glyph->internal->loader;+++ builder->loader = loader;+ builder->base = &loader->base.outline;+ builder->current = &loader->current.outline;+ FT_GlyphLoader_Rewind( loader );++ builder->hints_globals = size->internal;+ builder->hints_funcs = 0;++ if ( hinting )+ builder->hints_funcs = glyph->internal->glyph_hints;+ }++ builder->pos_x = 0;+ builder->pos_y = 0;++ builder->left_bearing.x = 0;+ builder->left_bearing.y = 0;+ builder->advance.x = 0;+ builder->advance.y = 0;++ builder->funcs = t1_builder_funcs;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* t1_builder_done */+ /* */+ /* <Description> */+ /* Finalizes a given glyph builder. Its contents can still be used */+ /* after the call, but the function saves important information */+ /* within the corresponding glyph slot. */+ /* */+ /* <Input> */+ /* builder :: A pointer to the glyph builder to finalize. */+ /* */+ FT_LOCAL_DEF( void )+ t1_builder_done( T1_Builder builder )+ {+ FT_GlyphSlot glyph = builder->glyph;+++ if ( glyph )+ glyph->outline = *builder->base;+ }+++ /* check that there is enough space for `count' more points */+ FT_LOCAL_DEF( FT_Error )+ t1_builder_check_points( T1_Builder builder,+ FT_Int count )+ {+ return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );+ }+++ /* add a new point, do not check space */+ FT_LOCAL_DEF( void )+ t1_builder_add_point( T1_Builder builder,+ FT_Pos x,+ FT_Pos y,+ FT_Byte flag )+ {+ FT_Outline* outline = builder->current;+++ if ( builder->load_points )+ {+ FT_Vector* point = outline->points + outline->n_points;+ FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;+++ point->x = FIXED_TO_INT( x );+ point->y = FIXED_TO_INT( y );+ *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );+ }+ outline->n_points++;+ }+++ /* check space for a new on-curve point, then add it */+ FT_LOCAL_DEF( FT_Error )+ t1_builder_add_point1( T1_Builder builder,+ FT_Pos x,+ FT_Pos y )+ {+ FT_Error error;+++ error = t1_builder_check_points( builder, 1 );+ if ( !error )+ t1_builder_add_point( builder, x, y, 1 );++ return error;+ }+++ /* check space for a new contour, then add it */+ FT_LOCAL_DEF( FT_Error )+ t1_builder_add_contour( T1_Builder builder )+ {+ FT_Outline* outline = builder->current;+ FT_Error error;+++ /* this might happen in invalid fonts */+ if ( !outline )+ {+ FT_ERROR(( "t1_builder_add_contour: no outline to add points to\n" ));+ return PSaux_Err_Invalid_File_Format;+ }++ if ( !builder->load_points )+ {+ outline->n_contours++;+ return PSaux_Err_Ok;+ }++ error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );+ if ( !error )+ {+ if ( outline->n_contours > 0 )+ outline->contours[outline->n_contours - 1] =+ (short)( outline->n_points - 1 );++ outline->n_contours++;+ }++ return error;+ }+++ /* if a path was begun, add its first on-curve point */+ FT_LOCAL_DEF( FT_Error )+ t1_builder_start_point( T1_Builder builder,+ FT_Pos x,+ FT_Pos y )+ {+ FT_Error error = PSaux_Err_Invalid_File_Format;+++ /* test whether we are building a new contour */++ if ( builder->parse_state == T1_Parse_Have_Path )+ error = PSaux_Err_Ok;+ else+ {+ builder->parse_state = T1_Parse_Have_Path;+ error = t1_builder_add_contour( builder );+ if ( !error )+ error = t1_builder_add_point1( builder, x, y );+ }++ return error;+ }+++ /* close the current contour */+ FT_LOCAL_DEF( void )+ t1_builder_close_contour( T1_Builder builder )+ {+ FT_Outline* outline = builder->current;+ FT_Int first;+++ if ( !outline )+ return;++ first = outline->n_contours <= 1+ ? 0 : outline->contours[outline->n_contours - 2] + 1;++ /* We must not include the last point in the path if it */+ /* is located on the first point. */+ if ( outline->n_points > 1 )+ {+ FT_Vector* p1 = outline->points + first;+ FT_Vector* p2 = outline->points + outline->n_points - 1;+ FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1;+++ /* `delete' last point only if it coincides with the first */+ /* point and it is not a control point (which can happen). */+ if ( p1->x == p2->x && p1->y == p2->y )+ if ( *control == FT_CURVE_TAG_ON )+ outline->n_points--;+ }++ if ( outline->n_contours > 0 )+ {+ /* Don't add contours only consisting of one point, i.e., */+ /* check whether the first and the last point is the same. */+ if ( first == outline->n_points - 1 )+ {+ outline->n_contours--;+ outline->n_points--;+ }+ else+ outline->contours[outline->n_contours - 1] =+ (short)( outline->n_points - 1 );+ }+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** OTHER *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ FT_LOCAL_DEF( void )+ t1_decrypt( FT_Byte* buffer,+ FT_Offset length,+ FT_UShort seed )+ {+ PS_Conv_EexecDecode( &buffer,+ buffer + length,+ buffer,+ length,+ &seed );+ }+++/* END */
+ src/psaux/psobjs.h view
@@ -0,0 +1,212 @@+/***************************************************************************/+/* */+/* psobjs.h */+/* */+/* Auxiliary functions for PostScript fonts (specification). */+/* */+/* Copyright 1996-2001, 2002, 2003 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 __PSOBJS_H__+#define __PSOBJS_H__+++#include <ft2build.h>+#include FT_INTERNAL_POSTSCRIPT_AUX_H+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** T1_TABLE *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+++ FT_CALLBACK_TABLE+ const PS_Table_FuncsRec ps_table_funcs;++ FT_CALLBACK_TABLE+ const PS_Parser_FuncsRec ps_parser_funcs;++ FT_CALLBACK_TABLE+ const T1_Builder_FuncsRec t1_builder_funcs;+++ FT_LOCAL( FT_Error )+ ps_table_new( PS_Table table,+ FT_Int count,+ FT_Memory memory );++ FT_LOCAL( FT_Error )+ ps_table_add( PS_Table table,+ FT_Int idx,+ void* object,+ FT_PtrDist length );++ FT_LOCAL( void )+ ps_table_done( PS_Table table );+++ FT_LOCAL( void )+ ps_table_release( PS_Table table );+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** T1 PARSER *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+++ FT_LOCAL( void )+ ps_parser_skip_spaces( PS_Parser parser );++ FT_LOCAL( void )+ ps_parser_skip_PS_token( PS_Parser parser );++ FT_LOCAL( void )+ ps_parser_to_token( PS_Parser parser,+ T1_Token token );++ FT_LOCAL( void )+ ps_parser_to_token_array( PS_Parser parser,+ T1_Token tokens,+ FT_UInt max_tokens,+ FT_Int* pnum_tokens );++ FT_LOCAL( FT_Error )+ ps_parser_load_field( PS_Parser parser,+ const T1_Field field,+ void** objects,+ FT_UInt max_objects,+ FT_ULong* pflags );++ FT_LOCAL( FT_Error )+ ps_parser_load_field_table( PS_Parser parser,+ const T1_Field field,+ void** objects,+ FT_UInt max_objects,+ FT_ULong* pflags );++ FT_LOCAL( FT_Long )+ ps_parser_to_int( PS_Parser parser );+++ FT_LOCAL( FT_Error )+ ps_parser_to_bytes( PS_Parser parser,+ FT_Byte* bytes,+ FT_Offset max_bytes,+ FT_Long* pnum_bytes,+ FT_Bool delimiters );+++ FT_LOCAL( FT_Fixed )+ ps_parser_to_fixed( PS_Parser parser,+ FT_Int power_ten );+++ FT_LOCAL( FT_Int )+ ps_parser_to_coord_array( PS_Parser parser,+ FT_Int max_coords,+ FT_Short* coords );++ FT_LOCAL( FT_Int )+ ps_parser_to_fixed_array( PS_Parser parser,+ FT_Int max_values,+ FT_Fixed* values,+ FT_Int power_ten );+++ FT_LOCAL( void )+ ps_parser_init( PS_Parser parser,+ FT_Byte* base,+ FT_Byte* limit,+ FT_Memory memory );++ FT_LOCAL( void )+ ps_parser_done( PS_Parser parser );+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** T1 BUILDER *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ FT_LOCAL( void )+ t1_builder_init( T1_Builder builder,+ FT_Face face,+ FT_Size size,+ FT_GlyphSlot glyph,+ FT_Bool hinting );++ FT_LOCAL( void )+ t1_builder_done( T1_Builder builder );++ FT_LOCAL( FT_Error )+ t1_builder_check_points( T1_Builder builder,+ FT_Int count );++ FT_LOCAL( void )+ t1_builder_add_point( T1_Builder builder,+ FT_Pos x,+ FT_Pos y,+ FT_Byte flag );++ FT_LOCAL( FT_Error )+ t1_builder_add_point1( T1_Builder builder,+ FT_Pos x,+ FT_Pos y );++ FT_LOCAL( FT_Error )+ t1_builder_add_contour( T1_Builder builder );+++ FT_LOCAL( FT_Error )+ t1_builder_start_point( T1_Builder builder,+ FT_Pos x,+ FT_Pos y );+++ FT_LOCAL( void )+ t1_builder_close_contour( T1_Builder builder );+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** OTHER *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ FT_LOCAL( void )+ t1_decrypt( FT_Byte* buffer,+ FT_Offset length,+ FT_UShort seed );+++FT_END_HEADER++#endif /* __PSOBJS_H__ */+++/* END */
+ src/psaux/t1cmap.c view
@@ -0,0 +1,341 @@+/***************************************************************************/+/* */+/* t1cmap.c */+/* */+/* Type 1 character map support (body). */+/* */+/* Copyright 2002, 2003, 2006, 2007 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 "t1cmap.h"++#include FT_INTERNAL_DEBUG_H++#include "psauxerr.h"+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** TYPE1 STANDARD (AND EXPERT) ENCODING CMAPS *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ static void+ t1_cmap_std_init( T1_CMapStd cmap,+ FT_Int is_expert )+ {+ T1_Face face = (T1_Face)FT_CMAP_FACE( cmap );+ FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames;+++ cmap->num_glyphs = face->type1.num_glyphs;+ cmap->glyph_names = (const char* const*)face->type1.glyph_names;+ cmap->sid_to_string = psnames->adobe_std_strings;+ cmap->code_to_sid = is_expert ? psnames->adobe_expert_encoding+ : psnames->adobe_std_encoding;++ FT_ASSERT( cmap->code_to_sid != NULL );+ }+++ FT_CALLBACK_DEF( void )+ t1_cmap_std_done( T1_CMapStd cmap )+ {+ cmap->num_glyphs = 0;+ cmap->glyph_names = NULL;+ cmap->sid_to_string = NULL;+ cmap->code_to_sid = NULL;+ }+++ FT_CALLBACK_DEF( FT_UInt )+ t1_cmap_std_char_index( T1_CMapStd cmap,+ FT_UInt32 char_code )+ {+ FT_UInt result = 0;+++ if ( char_code < 256 )+ {+ FT_UInt code, n;+ const char* glyph_name;+++ /* convert character code to Adobe SID string */+ code = cmap->code_to_sid[char_code];+ glyph_name = cmap->sid_to_string( code );++ /* look for the corresponding glyph name */+ for ( n = 0; n < cmap->num_glyphs; n++ )+ {+ const char* gname = cmap->glyph_names[n];+++ if ( gname && gname[0] == glyph_name[0] &&+ ft_strcmp( gname, glyph_name ) == 0 )+ {+ result = n;+ break;+ }+ }+ }++ return result;+ }+++ FT_CALLBACK_DEF( FT_UInt32 )+ t1_cmap_std_char_next( T1_CMapStd cmap,+ FT_UInt32 *pchar_code )+ {+ FT_UInt result = 0;+ FT_UInt32 char_code = *pchar_code + 1;+++ while ( char_code < 256 )+ {+ result = t1_cmap_std_char_index( cmap, char_code );+ if ( result != 0 )+ goto Exit;++ char_code++;+ }+ char_code = 0;++ Exit:+ *pchar_code = char_code;+ return result;+ }+++ FT_CALLBACK_DEF( FT_Error )+ t1_cmap_standard_init( T1_CMapStd cmap )+ {+ t1_cmap_std_init( cmap, 0 );+ return 0;+ }+++ FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec+ t1_cmap_standard_class_rec =+ {+ sizeof ( T1_CMapStdRec ),++ (FT_CMap_InitFunc) t1_cmap_standard_init,+ (FT_CMap_DoneFunc) t1_cmap_std_done,+ (FT_CMap_CharIndexFunc)t1_cmap_std_char_index,+ (FT_CMap_CharNextFunc) t1_cmap_std_char_next,++ NULL, NULL, NULL, NULL, NULL+ };+++ FT_CALLBACK_DEF( FT_Error )+ t1_cmap_expert_init( T1_CMapStd cmap )+ {+ t1_cmap_std_init( cmap, 1 );+ return 0;+ }++ FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec+ t1_cmap_expert_class_rec =+ {+ sizeof ( T1_CMapStdRec ),++ (FT_CMap_InitFunc) t1_cmap_expert_init,+ (FT_CMap_DoneFunc) t1_cmap_std_done,+ (FT_CMap_CharIndexFunc)t1_cmap_std_char_index,+ (FT_CMap_CharNextFunc) t1_cmap_std_char_next,++ NULL, NULL, NULL, NULL, NULL+ };+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** TYPE1 CUSTOM ENCODING CMAP *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+++ FT_CALLBACK_DEF( FT_Error )+ t1_cmap_custom_init( T1_CMapCustom cmap )+ {+ T1_Face face = (T1_Face)FT_CMAP_FACE( cmap );+ T1_Encoding encoding = &face->type1.encoding;+++ cmap->first = encoding->code_first;+ cmap->count = (FT_UInt)( encoding->code_last - cmap->first );+ cmap->indices = encoding->char_index;++ FT_ASSERT( cmap->indices != NULL );+ FT_ASSERT( encoding->code_first <= encoding->code_last );++ return 0;+ }+++ FT_CALLBACK_DEF( void )+ t1_cmap_custom_done( T1_CMapCustom cmap )+ {+ cmap->indices = NULL;+ cmap->first = 0;+ cmap->count = 0;+ }+++ FT_CALLBACK_DEF( FT_UInt )+ t1_cmap_custom_char_index( T1_CMapCustom cmap,+ FT_UInt32 char_code )+ {+ FT_UInt result = 0;+++ if ( ( char_code >= cmap->first ) &&+ ( char_code < ( cmap->first + cmap->count ) ) )+ result = cmap->indices[char_code];++ return result;+ }+++ FT_CALLBACK_DEF( FT_UInt32 )+ t1_cmap_custom_char_next( T1_CMapCustom cmap,+ FT_UInt32 *pchar_code )+ {+ FT_UInt result = 0;+ FT_UInt32 char_code = *pchar_code;+++ ++char_code;++ if ( char_code < cmap->first )+ char_code = cmap->first;++ for ( ; char_code < ( cmap->first + cmap->count ); char_code++ )+ {+ result = cmap->indices[char_code];+ if ( result != 0 )+ goto Exit;+ }++ char_code = 0;++ Exit:+ *pchar_code = char_code;+ return result;+ }+++ FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec+ t1_cmap_custom_class_rec =+ {+ sizeof ( T1_CMapCustomRec ),++ (FT_CMap_InitFunc) t1_cmap_custom_init,+ (FT_CMap_DoneFunc) t1_cmap_custom_done,+ (FT_CMap_CharIndexFunc)t1_cmap_custom_char_index,+ (FT_CMap_CharNextFunc) t1_cmap_custom_char_next,++ NULL, NULL, NULL, NULL, NULL+ };+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** TYPE1 SYNTHETIC UNICODE ENCODING CMAP *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ FT_CALLBACK_DEF( const char * )+ t1_get_glyph_name( T1_Face face,+ FT_UInt idx )+ {+ return face->type1.glyph_names[idx];+ }+++ FT_CALLBACK_DEF( FT_Error )+ t1_cmap_unicode_init( PS_Unicodes unicodes )+ {+ T1_Face face = (T1_Face)FT_CMAP_FACE( unicodes );+ FT_Memory memory = FT_FACE_MEMORY( face );+ FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames;+++ return psnames->unicodes_init( memory,+ unicodes,+ face->type1.num_glyphs,+ (PS_GetGlyphNameFunc)&t1_get_glyph_name,+ (PS_FreeGlyphNameFunc)NULL,+ (FT_Pointer)face );+ }+++ FT_CALLBACK_DEF( void )+ t1_cmap_unicode_done( PS_Unicodes unicodes )+ {+ FT_Face face = FT_CMAP_FACE( unicodes );+ FT_Memory memory = FT_FACE_MEMORY( face );+++ FT_FREE( unicodes->maps );+ unicodes->num_maps = 0;+ }+++ FT_CALLBACK_DEF( FT_UInt )+ t1_cmap_unicode_char_index( PS_Unicodes unicodes,+ FT_UInt32 char_code )+ {+ T1_Face face = (T1_Face)FT_CMAP_FACE( unicodes );+ FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames;+++ return psnames->unicodes_char_index( unicodes, char_code );+ }+++ FT_CALLBACK_DEF( FT_UInt32 )+ t1_cmap_unicode_char_next( PS_Unicodes unicodes,+ FT_UInt32 *pchar_code )+ {+ T1_Face face = (T1_Face)FT_CMAP_FACE( unicodes );+ FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames;+++ return psnames->unicodes_char_next( unicodes, pchar_code );+ }+++ FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec+ t1_cmap_unicode_class_rec =+ {+ sizeof ( PS_UnicodesRec ),++ (FT_CMap_InitFunc) t1_cmap_unicode_init,+ (FT_CMap_DoneFunc) t1_cmap_unicode_done,+ (FT_CMap_CharIndexFunc)t1_cmap_unicode_char_index,+ (FT_CMap_CharNextFunc) t1_cmap_unicode_char_next,++ NULL, NULL, NULL, NULL, NULL+ };+++/* END */
+ src/psaux/t1cmap.h view
@@ -0,0 +1,105 @@+/***************************************************************************/+/* */+/* t1cmap.h */+/* */+/* Type 1 character map support (specification). */+/* */+/* Copyright 2002, 2003, 2006 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 __T1CMAP_H__+#define __T1CMAP_H__++#include <ft2build.h>+#include FT_INTERNAL_OBJECTS_H+#include FT_INTERNAL_TYPE1_TYPES_H++FT_BEGIN_HEADER+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** TYPE1 STANDARD (AND EXPERT) ENCODING CMAPS *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /* standard (and expert) encoding cmaps */+ typedef struct T1_CMapStdRec_* T1_CMapStd;++ typedef struct T1_CMapStdRec_+ {+ FT_CMapRec cmap;++ const FT_UShort* code_to_sid;+ PS_Adobe_Std_StringsFunc sid_to_string;++ FT_UInt num_glyphs;+ const char* const* glyph_names;++ } T1_CMapStdRec;+++ FT_CALLBACK_TABLE const FT_CMap_ClassRec+ t1_cmap_standard_class_rec;++ FT_CALLBACK_TABLE const FT_CMap_ClassRec+ t1_cmap_expert_class_rec;+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** TYPE1 CUSTOM ENCODING CMAP *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ typedef struct T1_CMapCustomRec_* T1_CMapCustom;++ typedef struct T1_CMapCustomRec_+ {+ FT_CMapRec cmap;+ FT_UInt first;+ FT_UInt count;+ FT_UShort* indices;++ } T1_CMapCustomRec;+++ FT_CALLBACK_TABLE const FT_CMap_ClassRec+ t1_cmap_custom_class_rec;+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** TYPE1 SYNTHETIC UNICODE ENCODING CMAP *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /* unicode (synthetic) cmaps */++ FT_CALLBACK_TABLE const FT_CMap_ClassRec+ t1_cmap_unicode_class_rec;++ /* */+++FT_END_HEADER++#endif /* __T1CMAP_H__ */+++/* END */
+ src/psaux/t1decode.c view
@@ -0,0 +1,1601 @@+/***************************************************************************/+/* */+/* t1decode.c */+/* */+/* PostScript Type 1 decoding routines (body). */+/* */+/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 */+/* 2010 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_CALC_H+#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_POSTSCRIPT_HINTS_H+#include FT_OUTLINE_H++#include "t1decode.h"+#include "psobjs.h"++#include "psauxerr.h"+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_t1decode+++ typedef enum T1_Operator_+ {+ op_none = 0,+ op_endchar,+ op_hsbw,+ op_seac,+ op_sbw,+ op_closepath,+ op_hlineto,+ op_hmoveto,+ op_hvcurveto,+ op_rlineto,+ op_rmoveto,+ op_rrcurveto,+ op_vhcurveto,+ op_vlineto,+ op_vmoveto,+ op_dotsection,+ op_hstem,+ op_hstem3,+ op_vstem,+ op_vstem3,+ op_div,+ op_callothersubr,+ op_callsubr,+ op_pop,+ op_return,+ op_setcurrentpoint,+ op_unknown15,++ op_max /* never remove this one */++ } T1_Operator;+++ static+ const FT_Int t1_args_count[op_max] =+ {+ 0, /* none */+ 0, /* endchar */+ 2, /* hsbw */+ 5, /* seac */+ 4, /* sbw */+ 0, /* closepath */+ 1, /* hlineto */+ 1, /* hmoveto */+ 4, /* hvcurveto */+ 2, /* rlineto */+ 2, /* rmoveto */+ 6, /* rrcurveto */+ 4, /* vhcurveto */+ 1, /* vlineto */+ 1, /* vmoveto */+ 0, /* dotsection */+ 2, /* hstem */+ 6, /* hstem3 */+ 2, /* vstem */+ 6, /* vstem3 */+ 2, /* div */+ -1, /* callothersubr */+ 1, /* callsubr */+ 0, /* pop */+ 0, /* return */+ 2, /* setcurrentpoint */+ 2 /* opcode 15 (undocumented and obsolete) */+ };+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* t1_lookup_glyph_by_stdcharcode */+ /* */+ /* <Description> */+ /* Looks up a given glyph by its StandardEncoding charcode. Used to */+ /* implement the SEAC Type 1 operator. */+ /* */+ /* <Input> */+ /* face :: The current face object. */+ /* */+ /* charcode :: The character code to look for. */+ /* */+ /* <Return> */+ /* A glyph index in the font face. Returns -1 if the corresponding */+ /* glyph wasn't found. */+ /* */+ static FT_Int+ t1_lookup_glyph_by_stdcharcode( T1_Decoder decoder,+ FT_Int charcode )+ {+ FT_UInt n;+ const FT_String* glyph_name;+ FT_Service_PsCMaps psnames = decoder->psnames;+++ /* check range of standard char code */+ if ( charcode < 0 || charcode > 255 )+ return -1;++ glyph_name = psnames->adobe_std_strings(+ psnames->adobe_std_encoding[charcode]);++ for ( n = 0; n < decoder->num_glyphs; n++ )+ {+ FT_String* name = (FT_String*)decoder->glyph_names[n];+++ if ( name &&+ name[0] == glyph_name[0] &&+ ft_strcmp( name, glyph_name ) == 0 )+ return n;+ }++ return -1;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* t1operator_seac */+ /* */+ /* <Description> */+ /* Implements the `seac' Type 1 operator for a Type 1 decoder. */+ /* */+ /* <Input> */+ /* decoder :: The current CID decoder. */+ /* */+ /* asb :: The accent's side bearing. */+ /* */+ /* adx :: The horizontal offset of the accent. */+ /* */+ /* ady :: The vertical offset of the accent. */+ /* */+ /* bchar :: The base character's StandardEncoding charcode. */+ /* */+ /* achar :: The accent character's StandardEncoding charcode. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ static FT_Error+ t1operator_seac( T1_Decoder decoder,+ FT_Pos asb,+ FT_Pos adx,+ FT_Pos ady,+ FT_Int bchar,+ FT_Int achar )+ {+ FT_Error error;+ FT_Int bchar_index, achar_index;+#if 0+ FT_Int n_base_points;+ FT_Outline* base = decoder->builder.base;+#endif+ FT_Vector left_bearing, advance;++#ifdef FT_CONFIG_OPTION_INCREMENTAL+ T1_Face face = (T1_Face)decoder->builder.face;+#endif +++ if ( decoder->seac )+ {+ FT_ERROR(( "t1operator_seac: invalid nested seac\n" ));+ return PSaux_Err_Syntax_Error;+ }++ /* seac weirdness */+ adx += decoder->builder.left_bearing.x;++ /* `glyph_names' is set to 0 for CID fonts which do not */+ /* include an encoding. How can we deal with these? */+#ifdef FT_CONFIG_OPTION_INCREMENTAL+ if ( decoder->glyph_names == 0 &&+ !face->root.internal->incremental_interface )+#else+ if ( decoder->glyph_names == 0 )+#endif /* FT_CONFIG_OPTION_INCREMENTAL */+ {+ FT_ERROR(( "t1operator_seac:"+ " glyph names table not available in this font\n" ));+ return PSaux_Err_Syntax_Error;+ }++#ifdef FT_CONFIG_OPTION_INCREMENTAL+ if ( face->root.internal->incremental_interface )+ {+ /* the caller must handle the font encoding also */+ bchar_index = bchar;+ achar_index = achar;+ }+ else+#endif+ {+ bchar_index = t1_lookup_glyph_by_stdcharcode( decoder, bchar );+ achar_index = t1_lookup_glyph_by_stdcharcode( decoder, achar );+ }++ if ( bchar_index < 0 || achar_index < 0 )+ {+ FT_ERROR(( "t1operator_seac:"+ " invalid seac character code arguments\n" ));+ return PSaux_Err_Syntax_Error;+ }++ /* if we are trying to load a composite glyph, do not load the */+ /* accent character and return the array of subglyphs. */+ if ( decoder->builder.no_recurse )+ {+ FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph;+ FT_GlyphLoader loader = glyph->internal->loader;+ FT_SubGlyph subg;+++ /* reallocate subglyph array if necessary */+ error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );+ if ( error )+ goto Exit;++ subg = loader->current.subglyphs;++ /* subglyph 0 = base character */+ subg->index = bchar_index;+ subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |+ FT_SUBGLYPH_FLAG_USE_MY_METRICS;+ subg->arg1 = 0;+ subg->arg2 = 0;+ subg++;++ /* subglyph 1 = accent character */+ subg->index = achar_index;+ subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;+ subg->arg1 = (FT_Int)FIXED_TO_INT( adx - asb );+ subg->arg2 = (FT_Int)FIXED_TO_INT( ady );++ /* set up remaining glyph fields */+ glyph->num_subglyphs = 2;+ glyph->subglyphs = loader->base.subglyphs;+ glyph->format = FT_GLYPH_FORMAT_COMPOSITE;++ loader->current.num_subglyphs = 2;+ goto Exit;+ }++ /* First load `bchar' in builder */+ /* now load the unscaled outline */++ FT_GlyphLoader_Prepare( decoder->builder.loader ); /* prepare loader */++ /* the seac operator must not be nested */+ decoder->seac = TRUE;+ error = t1_decoder_parse_glyph( decoder, bchar_index );+ decoder->seac = FALSE;+ if ( error )+ goto Exit;++ /* save the left bearing and width of the base character */+ /* as they will be erased by the next load. */++ left_bearing = decoder->builder.left_bearing;+ advance = decoder->builder.advance;++ decoder->builder.left_bearing.x = 0;+ decoder->builder.left_bearing.y = 0;++ decoder->builder.pos_x = adx - asb;+ decoder->builder.pos_y = ady;++ /* Now load `achar' on top of */+ /* the base outline */++ /* the seac operator must not be nested */+ decoder->seac = TRUE;+ error = t1_decoder_parse_glyph( decoder, achar_index );+ decoder->seac = FALSE;+ if ( error )+ goto Exit;++ /* restore the left side bearing and */+ /* advance width of the base character */++ decoder->builder.left_bearing = left_bearing;+ decoder->builder.advance = advance;++ decoder->builder.pos_x = 0;+ decoder->builder.pos_y = 0;++ Exit:+ return error;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* t1_decoder_parse_charstrings */+ /* */+ /* <Description> */+ /* Parses a given Type 1 charstrings program. */+ /* */+ /* <Input> */+ /* decoder :: The current Type 1 decoder. */+ /* */+ /* charstring_base :: The base address of the charstring stream. */+ /* */+ /* charstring_len :: The length in bytes of the charstring stream. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ t1_decoder_parse_charstrings( T1_Decoder decoder,+ FT_Byte* charstring_base,+ FT_UInt charstring_len )+ {+ FT_Error error;+ T1_Decoder_Zone zone;+ FT_Byte* ip;+ FT_Byte* limit;+ T1_Builder builder = &decoder->builder;+ FT_Pos x, y, orig_x, orig_y;+ FT_Int known_othersubr_result_cnt = 0;+ FT_Int unknown_othersubr_result_cnt = 0;+ FT_Bool large_int;+ FT_Fixed seed;++ T1_Hints_Funcs hinter;++#ifdef FT_DEBUG_LEVEL_TRACE+ FT_Bool bol = TRUE;+#endif+++ /* compute random seed from stack address of parameter */+ seed = (FT_Fixed)( ( (FT_PtrDist)(char*)&seed ^+ (FT_PtrDist)(char*)&decoder ^+ (FT_PtrDist)(char*)&charstring_base ) &+ FT_ULONG_MAX ) ;+ seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL;+ if ( seed == 0 )+ seed = 0x7384;++ /* First of all, initialize the decoder */+ decoder->top = decoder->stack;+ decoder->zone = decoder->zones;+ zone = decoder->zones;++ builder->parse_state = T1_Parse_Start;++ hinter = (T1_Hints_Funcs)builder->hints_funcs;++ /* a font that reads BuildCharArray without setting */+ /* its values first is buggy, but ... */+ FT_ASSERT( ( decoder->len_buildchar == 0 ) ==+ ( decoder->buildchar == NULL ) );++ if ( decoder->len_buildchar > 0 )+ ft_memset( &decoder->buildchar[0],+ 0,+ sizeof( decoder->buildchar[0] ) * decoder->len_buildchar );++ FT_TRACE4(( "\n"+ "Start charstring\n" ));++ zone->base = charstring_base;+ limit = zone->limit = charstring_base + charstring_len;+ ip = zone->cursor = zone->base;++ error = PSaux_Err_Ok;++ x = orig_x = builder->pos_x;+ y = orig_y = builder->pos_y;++ /* begin hints recording session, if any */+ if ( hinter )+ hinter->open( hinter->hints );++ large_int = FALSE;++ /* now, execute loop */+ while ( ip < limit )+ {+ FT_Long* top = decoder->top;+ T1_Operator op = op_none;+ FT_Int32 value = 0;+++ FT_ASSERT( known_othersubr_result_cnt == 0 ||+ unknown_othersubr_result_cnt == 0 );++#ifdef FT_DEBUG_LEVEL_TRACE+ if ( bol )+ {+ FT_TRACE5(( " (%d)", decoder->top - decoder->stack ));+ bol = FALSE;+ }+#endif++ /*********************************************************************/+ /* */+ /* Decode operator or operand */+ /* */+ /* */++ /* first of all, decompress operator or value */+ switch ( *ip++ )+ {+ case 1:+ op = op_hstem;+ break;++ case 3:+ op = op_vstem;+ break;+ case 4:+ op = op_vmoveto;+ break;+ case 5:+ op = op_rlineto;+ break;+ case 6:+ op = op_hlineto;+ break;+ case 7:+ op = op_vlineto;+ break;+ case 8:+ op = op_rrcurveto;+ break;+ case 9:+ op = op_closepath;+ break;+ case 10:+ op = op_callsubr;+ break;+ case 11:+ op = op_return;+ break;++ case 13:+ op = op_hsbw;+ break;+ case 14:+ op = op_endchar;+ break;++ case 15: /* undocumented, obsolete operator */+ op = op_unknown15;+ break;++ case 21:+ op = op_rmoveto;+ break;+ case 22:+ op = op_hmoveto;+ break;++ case 30:+ op = op_vhcurveto;+ break;+ case 31:+ op = op_hvcurveto;+ break;++ case 12:+ if ( ip > limit )+ {+ FT_ERROR(( "t1_decoder_parse_charstrings:"+ " invalid escape (12+EOF)\n" ));+ goto Syntax_Error;+ }++ switch ( *ip++ )+ {+ case 0:+ op = op_dotsection;+ break;+ case 1:+ op = op_vstem3;+ break;+ case 2:+ op = op_hstem3;+ break;+ case 6:+ op = op_seac;+ break;+ case 7:+ op = op_sbw;+ break;+ case 12:+ op = op_div;+ break;+ case 16:+ op = op_callothersubr;+ break;+ case 17:+ op = op_pop;+ break;+ case 33:+ op = op_setcurrentpoint;+ break;++ default:+ FT_ERROR(( "t1_decoder_parse_charstrings:"+ " invalid escape (12+%d)\n",+ ip[-1] ));+ goto Syntax_Error;+ }+ break;++ case 255: /* four bytes integer */+ if ( ip + 4 > limit )+ {+ FT_ERROR(( "t1_decoder_parse_charstrings:"+ " unexpected EOF in integer\n" ));+ goto Syntax_Error;+ }++ value = (FT_Int32)( ( (FT_Long)ip[0] << 24 ) |+ ( (FT_Long)ip[1] << 16 ) |+ ( (FT_Long)ip[2] << 8 ) |+ ip[3] );+ ip += 4;++ /* According to the specification, values > 32000 or < -32000 must */+ /* be followed by a `div' operator to make the result be in the */+ /* range [-32000;32000]. We expect that the second argument of */+ /* `div' is not a large number. Additionally, we don't handle */+ /* stuff like `<large1> <large2> <num> div <num> div' or */+ /* <large1> <large2> <num> div div'. This is probably not allowed */+ /* anyway. */+ if ( value > 32000 || value < -32000 )+ {+ if ( large_int )+ {+ FT_ERROR(( "t1_decoder_parse_charstrings:"+ " no `div' after large integer\n" ));+ }+ else+ large_int = TRUE;+ }+ else+ {+ if ( !large_int )+ value <<= 16;+ }++ break;++ default:+ if ( ip[-1] >= 32 )+ {+ if ( ip[-1] < 247 )+ value = (FT_Int32)ip[-1] - 139;+ else+ {+ if ( ++ip > limit )+ {+ FT_ERROR(( "t1_decoder_parse_charstrings:"+ " unexpected EOF in integer\n" ));+ goto Syntax_Error;+ }++ if ( ip[-2] < 251 )+ value = ( ( (FT_Int32)ip[-2] - 247 ) << 8 ) + ip[-1] + 108;+ else+ value = -( ( ( (FT_Int32)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 );+ }++ if ( !large_int )+ value <<= 16;+ }+ else+ {+ FT_ERROR(( "t1_decoder_parse_charstrings:"+ " invalid byte (%d)\n", ip[-1] ));+ goto Syntax_Error;+ }+ }++ if ( unknown_othersubr_result_cnt > 0 )+ {+ switch ( op )+ {+ case op_callsubr:+ case op_return:+ case op_none:+ case op_pop:+ break;++ default:+ /* all operands have been transferred by previous pops */+ unknown_othersubr_result_cnt = 0;+ break;+ }+ }++ if ( large_int && !( op == op_none || op == op_div ) )+ {+ FT_ERROR(( "t1_decoder_parse_charstrings:"+ " no `div' after large integer\n" ));++ large_int = FALSE;+ }++ /*********************************************************************/+ /* */+ /* Push value on stack, or process operator */+ /* */+ /* */+ if ( op == op_none )+ {+ if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )+ {+ FT_ERROR(( "t1_decoder_parse_charstrings: stack overflow\n" ));+ goto Syntax_Error;+ }++#ifdef FT_DEBUG_LEVEL_TRACE+ if ( large_int )+ FT_TRACE4(( " %ld", value ));+ else+ FT_TRACE4(( " %ld", (FT_Int32)( value >> 16 ) ));+#endif++ *top++ = value;+ decoder->top = top;+ }+ else if ( op == op_callothersubr ) /* callothersubr */+ {+ FT_Int subr_no;+ FT_Int arg_cnt;+++#ifdef FT_DEBUG_LEVEL_TRACE+ FT_TRACE4(( " callothersubr\n" ));+ bol = TRUE;+#endif++ if ( top - decoder->stack < 2 )+ goto Stack_Underflow;++ top -= 2;++ subr_no = (FT_Int)( top[1] >> 16 );+ arg_cnt = (FT_Int)( top[0] >> 16 );++ /***********************************************************/+ /* */+ /* remove all operands to callothersubr from the stack */+ /* */+ /* for handled othersubrs, where we know the number of */+ /* arguments, we increase the stack by the value of */+ /* known_othersubr_result_cnt */+ /* */+ /* for unhandled othersubrs the following pops adjust the */+ /* stack pointer as necessary */++ if ( arg_cnt > top - decoder->stack )+ goto Stack_Underflow;++ top -= arg_cnt;++ known_othersubr_result_cnt = 0;+ unknown_othersubr_result_cnt = 0;++ /* XXX TODO: The checks to `arg_count == <whatever>' */+ /* might not be correct; an othersubr expects a certain */+ /* number of operands on the PostScript stack (as opposed */+ /* to the T1 stack) but it doesn't have to put them there */+ /* by itself; previous othersubrs might have left the */+ /* operands there if they were not followed by an */+ /* appropriate number of pops */+ /* */+ /* On the other hand, Adobe Reader 7.0.8 for Linux doesn't */+ /* accept a font that contains charstrings like */+ /* */+ /* 100 200 2 20 callothersubr */+ /* 300 1 20 callothersubr pop */+ /* */+ /* Perhaps this is the reason why BuildCharArray exists. */++ switch ( subr_no )+ {+ case 1: /* start flex feature */+ if ( arg_cnt != 0 )+ goto Unexpected_OtherSubr;++ decoder->flex_state = 1;+ decoder->num_flex_vectors = 0;+ if ( ( error = t1_builder_start_point( builder, x, y ) )+ != PSaux_Err_Ok ||+ ( error = t1_builder_check_points( builder, 6 ) )+ != PSaux_Err_Ok )+ goto Fail;+ break;++ case 2: /* add flex vectors */+ {+ FT_Int idx;+++ if ( arg_cnt != 0 )+ goto Unexpected_OtherSubr;++ /* note that we should not add a point for index 0; */+ /* this will move our current position to the flex */+ /* point without adding any point to the outline */+ idx = decoder->num_flex_vectors++;+ if ( idx > 0 && idx < 7 )+ t1_builder_add_point( builder,+ x,+ y,+ (FT_Byte)( idx == 3 || idx == 6 ) );+ }+ break;++ case 0: /* end flex feature */+ if ( arg_cnt != 3 )+ goto Unexpected_OtherSubr;++ if ( decoder->flex_state == 0 ||+ decoder->num_flex_vectors != 7 )+ {+ FT_ERROR(( "t1_decoder_parse_charstrings:"+ " unexpected flex end\n" ));+ goto Syntax_Error;+ }++ /* the two `results' are popped by the following setcurrentpoint */+ top[0] = x;+ top[1] = y;+ known_othersubr_result_cnt = 2;+ break;++ case 3: /* change hints */+ if ( arg_cnt != 1 )+ goto Unexpected_OtherSubr;++ known_othersubr_result_cnt = 1;++ if ( hinter )+ hinter->reset( hinter->hints, builder->current->n_points );+ break;++ case 12:+ case 13:+ /* counter control hints, clear stack */+ top = decoder->stack;+ break;++ case 14:+ case 15:+ case 16:+ case 17:+ case 18: /* multiple masters */+ {+ PS_Blend blend = decoder->blend;+ FT_UInt num_points, nn, mm;+ FT_Long* delta;+ FT_Long* values;+++ if ( !blend )+ {+ FT_ERROR(( "t1_decoder_parse_charstrings:"+ " unexpected multiple masters operator\n" ));+ goto Syntax_Error;+ }++ num_points = (FT_UInt)subr_no - 13 + ( subr_no == 18 );+ if ( arg_cnt != (FT_Int)( num_points * blend->num_designs ) )+ {+ FT_ERROR(( "t1_decoder_parse_charstrings:"+ " incorrect number of multiple masters arguments\n" ));+ goto Syntax_Error;+ }++ /* we want to compute: */+ /* */+ /* a0*w0 + a1*w1 + ... + ak*wk */+ /* */+ /* but we only have the a0, a1-a0, a2-a0, .. ak-a0 */+ /* however, given that w0 + w1 + ... + wk == 1, we can */+ /* rewrite it easily as: */+ /* */+ /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk */+ /* */+ /* where k == num_designs-1 */+ /* */+ /* I guess that's why it's written in this `compact' */+ /* form. */+ /* */+ delta = top + num_points;+ values = top;+ for ( nn = 0; nn < num_points; nn++ )+ {+ FT_Long tmp = values[0];+++ for ( mm = 1; mm < blend->num_designs; mm++ )+ tmp += FT_MulFix( *delta++, blend->weight_vector[mm] );++ *values++ = tmp;+ }++ known_othersubr_result_cnt = num_points;+ break;+ }++ case 19:+ /* <idx> 1 19 callothersubr */+ /* => replace elements starting from index cvi( <idx> ) */+ /* of BuildCharArray with WeightVector */+ {+ FT_Int idx;+ PS_Blend blend = decoder->blend;+++ if ( arg_cnt != 1 || blend == NULL )+ goto Unexpected_OtherSubr;++ idx = (FT_Int)( top[0] >> 16 );++ if ( idx < 0 ||+ idx + blend->num_designs > decoder->len_buildchar )+ goto Unexpected_OtherSubr;++ ft_memcpy( &decoder->buildchar[idx],+ blend->weight_vector,+ blend->num_designs *+ sizeof( blend->weight_vector[0] ) );+ }+ break;++ case 20:+ /* <arg1> <arg2> 2 20 callothersubr pop */+ /* ==> push <arg1> + <arg2> onto T1 stack */+ if ( arg_cnt != 2 )+ goto Unexpected_OtherSubr;++ top[0] += top[1]; /* XXX (over|under)flow */++ known_othersubr_result_cnt = 1;+ break;++ case 21:+ /* <arg1> <arg2> 2 21 callothersubr pop */+ /* ==> push <arg1> - <arg2> onto T1 stack */+ if ( arg_cnt != 2 )+ goto Unexpected_OtherSubr;++ top[0] -= top[1]; /* XXX (over|under)flow */++ known_othersubr_result_cnt = 1;+ break;++ case 22:+ /* <arg1> <arg2> 2 22 callothersubr pop */+ /* ==> push <arg1> * <arg2> onto T1 stack */+ if ( arg_cnt != 2 )+ goto Unexpected_OtherSubr;++ top[0] = FT_MulFix( top[0], top[1] );++ known_othersubr_result_cnt = 1;+ break;++ case 23:+ /* <arg1> <arg2> 2 23 callothersubr pop */+ /* ==> push <arg1> / <arg2> onto T1 stack */+ if ( arg_cnt != 2 || top[1] == 0 )+ goto Unexpected_OtherSubr;++ top[0] = FT_DivFix( top[0], top[1] );++ known_othersubr_result_cnt = 1;+ break;++ case 24:+ /* <val> <idx> 2 24 callothersubr */+ /* ==> set BuildCharArray[cvi( <idx> )] = <val> */+ {+ FT_Int idx;+ PS_Blend blend = decoder->blend;+++ if ( arg_cnt != 2 || blend == NULL )+ goto Unexpected_OtherSubr;++ idx = (FT_Int)( top[1] >> 16 );++ if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar )+ goto Unexpected_OtherSubr;++ decoder->buildchar[idx] = top[0];+ }+ break;++ case 25:+ /* <idx> 1 25 callothersubr pop */+ /* ==> push BuildCharArray[cvi( idx )] */+ /* onto T1 stack */+ {+ FT_Int idx;+ PS_Blend blend = decoder->blend;+++ if ( arg_cnt != 1 || blend == NULL )+ goto Unexpected_OtherSubr;++ idx = (FT_Int)( top[0] >> 16 );++ if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar )+ goto Unexpected_OtherSubr;++ top[0] = decoder->buildchar[idx];+ }++ known_othersubr_result_cnt = 1;+ break;++#if 0+ case 26:+ /* <val> mark <idx> ==> set BuildCharArray[cvi( <idx> )] = <val>, */+ /* leave mark on T1 stack */+ /* <val> <idx> ==> set BuildCharArray[cvi( <idx> )] = <val> */+ XXX which routine has left its mark on the (PostScript) stack?;+ break;+#endif++ case 27:+ /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */+ /* ==> push <res1> onto T1 stack if <val1> <= <val2>, */+ /* otherwise push <res2> */+ if ( arg_cnt != 4 )+ goto Unexpected_OtherSubr;++ if ( top[2] > top[3] )+ top[0] = top[1];++ known_othersubr_result_cnt = 1;+ break;++ case 28:+ /* 0 28 callothersubr pop */+ /* => push random value from interval [0, 1) onto stack */+ if ( arg_cnt != 0 )+ goto Unexpected_OtherSubr;++ {+ FT_Fixed Rand;+++ Rand = seed;+ if ( Rand >= 0x8000L )+ Rand++;++ top[0] = Rand;++ seed = FT_MulFix( seed, 0x10000L - seed );+ if ( seed == 0 )+ seed += 0x2873;+ }++ known_othersubr_result_cnt = 1;+ break;++ default:+ FT_ERROR(( "t1_decoder_parse_charstrings:"+ " unknown othersubr [%d %d], wish me luck\n",+ arg_cnt, subr_no ));+ unknown_othersubr_result_cnt = arg_cnt;+ break;++ Unexpected_OtherSubr:+ FT_ERROR(( "t1_decoder_parse_charstrings:"+ " invalid othersubr [%d %d]\n", arg_cnt, subr_no ));+ goto Syntax_Error;+ }++ top += known_othersubr_result_cnt;++ decoder->top = top;+ }+ else /* general operator */+ {+ FT_Int num_args = t1_args_count[op];+++ FT_ASSERT( num_args >= 0 );++ if ( top - decoder->stack < num_args )+ goto Stack_Underflow;++ /* XXX Operators usually take their operands from the */+ /* bottom of the stack, i.e., the operands are */+ /* decoder->stack[0], ..., decoder->stack[num_args - 1]; */+ /* only div, callsubr, and callothersubr are different. */+ /* In practice it doesn't matter (?). */++#ifdef FT_DEBUG_LEVEL_TRACE++ switch ( op )+ {+ case op_callsubr:+ case op_div:+ case op_callothersubr:+ case op_pop:+ case op_return:+ break;++ default:+ if ( top - decoder->stack != num_args )+ FT_TRACE0(( "t1_decoder_parse_charstrings:"+ " too much operands on the stack"+ " (seen %d, expected %d)\n",+ top - decoder->stack, num_args ));+ break;+ }++#endif /* FT_DEBUG_LEVEL_TRACE */++ top -= num_args;++ switch ( op )+ {+ case op_endchar:+ FT_TRACE4(( " endchar\n" ));++ t1_builder_close_contour( builder );++ /* close hints recording session */+ if ( hinter )+ {+ if ( hinter->close( hinter->hints, builder->current->n_points ) )+ goto Syntax_Error;++ /* apply hints to the loaded glyph outline now */+ hinter->apply( hinter->hints,+ builder->current,+ (PSH_Globals)builder->hints_globals,+ decoder->hint_mode );+ }++ /* add current outline to the glyph slot */+ FT_GlyphLoader_Add( builder->loader );++ /* the compiler should optimize away this empty loop but ... */++#ifdef FT_DEBUG_LEVEL_TRACE++ if ( decoder->len_buildchar > 0 )+ {+ FT_UInt i;+++ FT_TRACE4(( "BuildCharArray = [ " ));++ for ( i = 0; i < decoder->len_buildchar; ++i )+ FT_TRACE4(( "%d ", decoder->buildchar[ i ] ));++ FT_TRACE4(( "]\n" ));+ }++#endif /* FT_DEBUG_LEVEL_TRACE */++ FT_TRACE4(( "\n" ));++ /* return now! */+ return PSaux_Err_Ok;++ case op_hsbw:+ FT_TRACE4(( " hsbw" ));++ builder->parse_state = T1_Parse_Have_Width;++ builder->left_bearing.x += top[0];+ builder->advance.x = top[1];+ builder->advance.y = 0;++ orig_x = x = builder->pos_x + top[0];+ orig_y = y = builder->pos_y;++ FT_UNUSED( orig_y );++ /* the `metrics_only' indicates that we only want to compute */+ /* the glyph's metrics (lsb + advance width), not load the */+ /* rest of it; so exit immediately */+ if ( builder->metrics_only )+ return PSaux_Err_Ok;++ break;++ case op_seac:+ return t1operator_seac( decoder,+ top[0],+ top[1],+ top[2],+ (FT_Int)( top[3] >> 16 ),+ (FT_Int)( top[4] >> 16 ) );++ case op_sbw:+ FT_TRACE4(( " sbw" ));++ builder->parse_state = T1_Parse_Have_Width;++ builder->left_bearing.x += top[0];+ builder->left_bearing.y += top[1];+ builder->advance.x = top[2];+ builder->advance.y = top[3];++ x = builder->pos_x + top[0];+ y = builder->pos_y + top[1];++ /* the `metrics_only' indicates that we only want to compute */+ /* the glyph's metrics (lsb + advance width), not load the */+ /* rest of it; so exit immediately */+ if ( builder->metrics_only )+ return PSaux_Err_Ok;++ break;++ case op_closepath:+ FT_TRACE4(( " closepath" ));++ /* if there is no path, `closepath' is a no-op */+ if ( builder->parse_state == T1_Parse_Have_Path ||+ builder->parse_state == T1_Parse_Have_Moveto )+ t1_builder_close_contour( builder );++ builder->parse_state = T1_Parse_Have_Width;+ break;++ case op_hlineto:+ FT_TRACE4(( " hlineto" ));++ if ( ( error = t1_builder_start_point( builder, x, y ) )+ != PSaux_Err_Ok )+ goto Fail;++ x += top[0];+ goto Add_Line;++ case op_hmoveto:+ FT_TRACE4(( " hmoveto" ));++ x += top[0];+ if ( !decoder->flex_state )+ {+ if ( builder->parse_state == T1_Parse_Start )+ goto Syntax_Error;+ builder->parse_state = T1_Parse_Have_Moveto;+ }+ break;++ case op_hvcurveto:+ FT_TRACE4(( " hvcurveto" ));++ if ( ( error = t1_builder_start_point( builder, x, y ) )+ != PSaux_Err_Ok ||+ ( error = t1_builder_check_points( builder, 3 ) )+ != PSaux_Err_Ok )+ goto Fail;++ x += top[0];+ t1_builder_add_point( builder, x, y, 0 );+ x += top[1];+ y += top[2];+ t1_builder_add_point( builder, x, y, 0 );+ y += top[3];+ t1_builder_add_point( builder, x, y, 1 );+ break;++ case op_rlineto:+ FT_TRACE4(( " rlineto" ));++ if ( ( error = t1_builder_start_point( builder, x, y ) )+ != PSaux_Err_Ok )+ goto Fail;++ x += top[0];+ y += top[1];++ Add_Line:+ if ( ( error = t1_builder_add_point1( builder, x, y ) )+ != PSaux_Err_Ok )+ goto Fail;+ break;++ case op_rmoveto:+ FT_TRACE4(( " rmoveto" ));++ x += top[0];+ y += top[1];+ if ( !decoder->flex_state )+ {+ if ( builder->parse_state == T1_Parse_Start )+ goto Syntax_Error;+ builder->parse_state = T1_Parse_Have_Moveto;+ }+ break;++ case op_rrcurveto:+ FT_TRACE4(( " rrcurveto" ));++ if ( ( error = t1_builder_start_point( builder, x, y ) )+ != PSaux_Err_Ok ||+ ( error = t1_builder_check_points( builder, 3 ) )+ != PSaux_Err_Ok )+ goto Fail;++ x += top[0];+ y += top[1];+ t1_builder_add_point( builder, x, y, 0 );++ x += top[2];+ y += top[3];+ t1_builder_add_point( builder, x, y, 0 );++ x += top[4];+ y += top[5];+ t1_builder_add_point( builder, x, y, 1 );+ break;++ case op_vhcurveto:+ FT_TRACE4(( " vhcurveto" ));++ if ( ( error = t1_builder_start_point( builder, x, y ) )+ != PSaux_Err_Ok ||+ ( error = t1_builder_check_points( builder, 3 ) )+ != PSaux_Err_Ok )+ goto Fail;++ y += top[0];+ t1_builder_add_point( builder, x, y, 0 );+ x += top[1];+ y += top[2];+ t1_builder_add_point( builder, x, y, 0 );+ x += top[3];+ t1_builder_add_point( builder, x, y, 1 );+ break;++ case op_vlineto:+ FT_TRACE4(( " vlineto" ));++ if ( ( error = t1_builder_start_point( builder, x, y ) )+ != PSaux_Err_Ok )+ goto Fail;++ y += top[0];+ goto Add_Line;++ case op_vmoveto:+ FT_TRACE4(( " vmoveto" ));++ y += top[0];+ if ( !decoder->flex_state )+ {+ if ( builder->parse_state == T1_Parse_Start )+ goto Syntax_Error;+ builder->parse_state = T1_Parse_Have_Moveto;+ }+ break;++ case op_div:+ FT_TRACE4(( " div" ));++ /* if `large_int' is set, we divide unscaled numbers; */+ /* otherwise, we divide numbers in 16.16 format -- */+ /* in both cases, it is the same operation */+ *top = FT_DivFix( top[0], top[1] );+ ++top;++ large_int = FALSE;+ break;++ case op_callsubr:+ {+ FT_Int idx;+++ FT_TRACE4(( " callsubr" ));++ idx = (FT_Int)( top[0] >> 16 );+ if ( idx < 0 || idx >= (FT_Int)decoder->num_subrs )+ {+ FT_ERROR(( "t1_decoder_parse_charstrings:"+ " invalid subrs index\n" ));+ goto Syntax_Error;+ }++ if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )+ {+ FT_ERROR(( "t1_decoder_parse_charstrings:"+ " too many nested subrs\n" ));+ goto Syntax_Error;+ }++ zone->cursor = ip; /* save current instruction pointer */++ zone++;++ /* The Type 1 driver stores subroutines without the seed bytes. */+ /* The CID driver stores subroutines with seed bytes. This */+ /* case is taken care of when decoder->subrs_len == 0. */+ zone->base = decoder->subrs[idx];++ if ( decoder->subrs_len )+ zone->limit = zone->base + decoder->subrs_len[idx];+ else+ {+ /* We are using subroutines from a CID font. We must adjust */+ /* for the seed bytes. */+ zone->base += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 );+ zone->limit = decoder->subrs[idx + 1];+ }++ zone->cursor = zone->base;++ if ( !zone->base )+ {+ FT_ERROR(( "t1_decoder_parse_charstrings:"+ " invoking empty subrs\n" ));+ goto Syntax_Error;+ }++ decoder->zone = zone;+ ip = zone->base;+ limit = zone->limit;+ break;+ }++ case op_pop:+ FT_TRACE4(( " pop" ));++ if ( known_othersubr_result_cnt > 0 )+ {+ known_othersubr_result_cnt--;+ /* ignore, we pushed the operands ourselves */+ break;+ }++ if ( unknown_othersubr_result_cnt == 0 )+ {+ FT_ERROR(( "t1_decoder_parse_charstrings:"+ " no more operands for othersubr\n" ));+ goto Syntax_Error;+ }++ unknown_othersubr_result_cnt--;+ top++; /* `push' the operand to callothersubr onto the stack */+ break;++ case op_return:+ FT_TRACE4(( " return" ));++ if ( zone <= decoder->zones )+ {+ FT_ERROR(( "t1_decoder_parse_charstrings:"+ " unexpected return\n" ));+ goto Syntax_Error;+ }++ zone--;+ ip = zone->cursor;+ limit = zone->limit;+ decoder->zone = zone;+ break;++ case op_dotsection:+ FT_TRACE4(( " dotsection" ));++ break;++ case op_hstem:+ FT_TRACE4(( " hstem" ));++ /* record horizontal hint */+ if ( hinter )+ {+ /* top[0] += builder->left_bearing.y; */+ hinter->stem( hinter->hints, 1, top );+ }+ break;++ case op_hstem3:+ FT_TRACE4(( " hstem3" ));++ /* record horizontal counter-controlled hints */+ if ( hinter )+ hinter->stem3( hinter->hints, 1, top );+ break;++ case op_vstem:+ FT_TRACE4(( " vstem" ));++ /* record vertical hint */+ if ( hinter )+ {+ top[0] += orig_x;+ hinter->stem( hinter->hints, 0, top );+ }+ break;++ case op_vstem3:+ FT_TRACE4(( " vstem3" ));++ /* record vertical counter-controlled hints */+ if ( hinter )+ {+ FT_Pos dx = orig_x;+++ top[0] += dx;+ top[2] += dx;+ top[4] += dx;+ hinter->stem3( hinter->hints, 0, top );+ }+ break;++ case op_setcurrentpoint:+ FT_TRACE4(( " setcurrentpoint" ));++ /* From the T1 specification, section 6.4: */+ /* */+ /* The setcurrentpoint command is used only in */+ /* conjunction with results from OtherSubrs procedures. */++ /* known_othersubr_result_cnt != 0 is already handled */+ /* above. */++ /* Note, however, that both Ghostscript and Adobe */+ /* Distiller handle this situation by silently ignoring */+ /* the inappropriate `setcurrentpoint' instruction. So */+ /* we do the same. */+#if 0++ if ( decoder->flex_state != 1 )+ {+ FT_ERROR(( "t1_decoder_parse_charstrings:"+ " unexpected `setcurrentpoint'\n" ));+ goto Syntax_Error;+ }+ else+ ...+#endif++ x = top[0];+ y = top[1];+ decoder->flex_state = 0;+ break;++ case op_unknown15:+ FT_TRACE4(( " opcode_15" ));+ /* nothing to do except to pop the two arguments */+ break;++ default:+ FT_ERROR(( "t1_decoder_parse_charstrings:"+ " unhandled opcode %d\n", op ));+ goto Syntax_Error;+ }++ /* XXX Operators usually clear the operand stack; */+ /* only div, callsubr, callothersubr, pop, and */+ /* return are different. */+ /* In practice it doesn't matter (?). */++ decoder->top = top;++#ifdef FT_DEBUG_LEVEL_TRACE+ FT_TRACE4(( "\n" ));+ bol = TRUE;+#endif++ } /* general operator processing */++ } /* while ip < limit */++ FT_TRACE4(( "..end..\n\n" ));++ Fail:+ return error;++ Syntax_Error:+ return PSaux_Err_Syntax_Error;++ Stack_Underflow:+ return PSaux_Err_Stack_Underflow;+ }+++ /* parse a single Type 1 glyph */+ FT_LOCAL_DEF( FT_Error )+ t1_decoder_parse_glyph( T1_Decoder decoder,+ FT_UInt glyph )+ {+ return decoder->parse_callback( decoder, glyph );+ }+++ /* initialize T1 decoder */+ FT_LOCAL_DEF( FT_Error )+ t1_decoder_init( T1_Decoder decoder,+ FT_Face face,+ FT_Size size,+ FT_GlyphSlot slot,+ FT_Byte** glyph_names,+ PS_Blend blend,+ FT_Bool hinting,+ FT_Render_Mode hint_mode,+ T1_Decoder_Callback parse_callback )+ {+ FT_MEM_ZERO( decoder, sizeof ( *decoder ) );++ /* retrieve PSNames interface from list of current modules */+ {+ FT_Service_PsCMaps psnames = 0;+++ FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );+ if ( !psnames )+ {+ FT_ERROR(( "t1_decoder_init:"+ " the `psnames' module is not available\n" ));+ return PSaux_Err_Unimplemented_Feature;+ }++ decoder->psnames = psnames;+ }++ t1_builder_init( &decoder->builder, face, size, slot, hinting );++ /* decoder->buildchar and decoder->len_buildchar have to be */+ /* initialized by the caller since we cannot know the length */+ /* of the BuildCharArray */++ decoder->num_glyphs = (FT_UInt)face->num_glyphs;+ decoder->glyph_names = glyph_names;+ decoder->hint_mode = hint_mode;+ decoder->blend = blend;+ decoder->parse_callback = parse_callback;++ decoder->funcs = t1_decoder_funcs;++ return PSaux_Err_Ok;+ }+++ /* finalize T1 decoder */+ FT_LOCAL_DEF( void )+ t1_decoder_done( T1_Decoder decoder )+ {+ t1_builder_done( &decoder->builder );+ }+++/* END */
+ src/psaux/t1decode.h view
@@ -0,0 +1,64 @@+/***************************************************************************/+/* */+/* t1decode.h */+/* */+/* PostScript Type 1 decoding routines (specification). */+/* */+/* Copyright 2000-2001, 2002, 2003 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 __T1DECODE_H__+#define __T1DECODE_H__+++#include <ft2build.h>+#include FT_INTERNAL_POSTSCRIPT_AUX_H+#include FT_INTERNAL_TYPE1_TYPES_H+++FT_BEGIN_HEADER+++ FT_CALLBACK_TABLE+ const T1_Decoder_FuncsRec t1_decoder_funcs;+++ FT_LOCAL( FT_Error )+ t1_decoder_parse_glyph( T1_Decoder decoder,+ FT_UInt glyph_index );++ FT_LOCAL( FT_Error )+ t1_decoder_parse_charstrings( T1_Decoder decoder,+ FT_Byte* base,+ FT_UInt len );++ FT_LOCAL( FT_Error )+ t1_decoder_init( T1_Decoder decoder,+ FT_Face face,+ FT_Size size,+ FT_GlyphSlot slot,+ FT_Byte** glyph_names,+ PS_Blend blend,+ FT_Bool hinting,+ FT_Render_Mode hint_mode,+ T1_Decoder_Callback parse_glyph );++ FT_LOCAL( void )+ t1_decoder_done( T1_Decoder decoder );+++FT_END_HEADER++#endif /* __T1DECODE_H__ */+++/* END */
+ src/pshinter/pshalgo.c view
@@ -0,0 +1,2306 @@+/***************************************************************************/+/* */+/* pshalgo.c */+/* */+/* PostScript hinting algorithm (body). */+/* */+/* Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 */+/* 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_OBJECTS_H+#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_CALC_H+#include "pshalgo.h"++#include "pshnterr.h"+++#undef FT_COMPONENT+#define FT_COMPONENT trace_pshalgo2+++#ifdef DEBUG_HINTER+ PSH_Hint_Table ps_debug_hint_table = 0;+ PSH_HintFunc ps_debug_hint_func = 0;+ PSH_Glyph ps_debug_glyph = 0;+#endif+++#define COMPUTE_INFLEXS /* compute inflection points to optimize `S' */+ /* and similar glyphs */+#define STRONGER /* slightly increase the contrast of smooth */+ /* hinting */+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** BASIC HINTS RECORDINGS *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /* return true if two stem hints overlap */+ static FT_Int+ psh_hint_overlap( PSH_Hint hint1,+ PSH_Hint hint2 )+ {+ return hint1->org_pos + hint1->org_len >= hint2->org_pos &&+ hint2->org_pos + hint2->org_len >= hint1->org_pos;+ }+++ /* destroy hints table */+ static void+ psh_hint_table_done( PSH_Hint_Table table,+ FT_Memory memory )+ {+ FT_FREE( table->zones );+ table->num_zones = 0;+ table->zone = 0;++ FT_FREE( table->sort );+ FT_FREE( table->hints );+ table->num_hints = 0;+ table->max_hints = 0;+ table->sort_global = 0;+ }+++ /* deactivate all hints in a table */+ static void+ psh_hint_table_deactivate( PSH_Hint_Table table )+ {+ FT_UInt count = table->max_hints;+ PSH_Hint hint = table->hints;+++ for ( ; count > 0; count--, hint++ )+ {+ psh_hint_deactivate( hint );+ hint->order = -1;+ }+ }+++ /* internal function to record a new hint */+ static void+ psh_hint_table_record( PSH_Hint_Table table,+ FT_UInt idx )+ {+ PSH_Hint hint = table->hints + idx;+++ if ( idx >= table->max_hints )+ {+ FT_TRACE0(( "psh_hint_table_record: invalid hint index %d\n", idx ));+ return;+ }++ /* ignore active hints */+ if ( psh_hint_is_active( hint ) )+ return;++ psh_hint_activate( hint );++ /* now scan the current active hint set to check */+ /* whether `hint' overlaps with another hint */+ {+ PSH_Hint* sorted = table->sort_global;+ FT_UInt count = table->num_hints;+ PSH_Hint hint2;+++ hint->parent = 0;+ for ( ; count > 0; count--, sorted++ )+ {+ hint2 = sorted[0];++ if ( psh_hint_overlap( hint, hint2 ) )+ {+ hint->parent = hint2;+ break;+ }+ }+ }++ if ( table->num_hints < table->max_hints )+ table->sort_global[table->num_hints++] = hint;+ else+ FT_TRACE0(( "psh_hint_table_record: too many sorted hints! BUG!\n" ));+ }+++ static void+ psh_hint_table_record_mask( PSH_Hint_Table table,+ PS_Mask hint_mask )+ {+ FT_Int mask = 0, val = 0;+ FT_Byte* cursor = hint_mask->bytes;+ FT_UInt idx, limit;+++ limit = hint_mask->num_bits;++ for ( idx = 0; idx < limit; idx++ )+ {+ if ( mask == 0 )+ {+ val = *cursor++;+ mask = 0x80;+ }++ if ( val & mask )+ psh_hint_table_record( table, idx );++ mask >>= 1;+ }+ }+++ /* create hints table */+ static FT_Error+ psh_hint_table_init( PSH_Hint_Table table,+ PS_Hint_Table hints,+ PS_Mask_Table hint_masks,+ PS_Mask_Table counter_masks,+ FT_Memory memory )+ {+ FT_UInt count;+ FT_Error error;++ FT_UNUSED( counter_masks );+++ count = hints->num_hints;++ /* allocate our tables */+ if ( FT_NEW_ARRAY( table->sort, 2 * count ) ||+ FT_NEW_ARRAY( table->hints, count ) ||+ FT_NEW_ARRAY( table->zones, 2 * count + 1 ) )+ goto Exit;++ table->max_hints = count;+ table->sort_global = table->sort + count;+ table->num_hints = 0;+ table->num_zones = 0;+ table->zone = 0;++ /* initialize the `table->hints' array */+ {+ PSH_Hint write = table->hints;+ PS_Hint read = hints->hints;+++ for ( ; count > 0; count--, write++, read++ )+ {+ write->org_pos = read->pos;+ write->org_len = read->len;+ write->flags = read->flags;+ }+ }++ /* we now need to determine the initial `parent' stems; first */+ /* activate the hints that are given by the initial hint masks */+ if ( hint_masks )+ {+ PS_Mask mask = hint_masks->masks;+++ count = hint_masks->num_masks;+ table->hint_masks = hint_masks;++ for ( ; count > 0; count--, mask++ )+ psh_hint_table_record_mask( table, mask );+ }++ /* finally, do a linear parse in case some hints were left alone */+ if ( table->num_hints != table->max_hints )+ {+ FT_UInt idx;+++ FT_TRACE0(( "psh_hint_table_init: missing/incorrect hint masks\n" ));++ count = table->max_hints;+ for ( idx = 0; idx < count; idx++ )+ psh_hint_table_record( table, idx );+ }++ Exit:+ return error;+ }+++ static void+ psh_hint_table_activate_mask( PSH_Hint_Table table,+ PS_Mask hint_mask )+ {+ FT_Int mask = 0, val = 0;+ FT_Byte* cursor = hint_mask->bytes;+ FT_UInt idx, limit, count;+++ limit = hint_mask->num_bits;+ count = 0;++ psh_hint_table_deactivate( table );++ for ( idx = 0; idx < limit; idx++ )+ {+ if ( mask == 0 )+ {+ val = *cursor++;+ mask = 0x80;+ }++ if ( val & mask )+ {+ PSH_Hint hint = &table->hints[idx];+++ if ( !psh_hint_is_active( hint ) )+ {+ FT_UInt count2;++#if 0+ PSH_Hint* sort = table->sort;+ PSH_Hint hint2;+++ for ( count2 = count; count2 > 0; count2--, sort++ )+ {+ hint2 = sort[0];+ if ( psh_hint_overlap( hint, hint2 ) )+ FT_TRACE0(( "psh_hint_table_activate_mask:"+ " found overlapping hints\n" ))+ }+#else+ count2 = 0;+#endif++ if ( count2 == 0 )+ {+ psh_hint_activate( hint );+ if ( count < table->max_hints )+ table->sort[count++] = hint;+ else+ FT_TRACE0(( "psh_hint_tableactivate_mask:"+ " too many active hints\n" ));+ }+ }+ }++ mask >>= 1;+ }+ table->num_hints = count;++ /* now, sort the hints; they are guaranteed to not overlap */+ /* so we can compare their "org_pos" field directly */+ {+ FT_Int i1, i2;+ PSH_Hint hint1, hint2;+ PSH_Hint* sort = table->sort;+++ /* a simple bubble sort will do, since in 99% of cases, the hints */+ /* will be already sorted -- and the sort will be linear */+ for ( i1 = 1; i1 < (FT_Int)count; i1++ )+ {+ hint1 = sort[i1];+ for ( i2 = i1 - 1; i2 >= 0; i2-- )+ {+ hint2 = sort[i2];++ if ( hint2->org_pos < hint1->org_pos )+ break;++ sort[i2 + 1] = hint2;+ sort[i2] = hint1;+ }+ }+ }+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** HINTS GRID-FITTING AND OPTIMIZATION *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++#if 1+ static FT_Pos+ psh_dimension_quantize_len( PSH_Dimension dim,+ FT_Pos len,+ FT_Bool do_snapping )+ {+ if ( len <= 64 )+ len = 64;+ else+ {+ FT_Pos delta = len - dim->stdw.widths[0].cur;+++ if ( delta < 0 )+ delta = -delta;++ if ( delta < 40 )+ {+ len = dim->stdw.widths[0].cur;+ if ( len < 48 )+ len = 48;+ }++ if ( len < 3 * 64 )+ {+ delta = ( len & 63 );+ len &= -64;++ if ( delta < 10 )+ len += delta;++ else if ( delta < 32 )+ len += 10;++ else if ( delta < 54 )+ len += 54;++ else+ len += delta;+ }+ else+ len = FT_PIX_ROUND( len );+ }++ if ( do_snapping )+ len = FT_PIX_ROUND( len );++ return len;+ }+#endif /* 0 */+++#ifdef DEBUG_HINTER++ static void+ ps_simple_scale( PSH_Hint_Table table,+ FT_Fixed scale,+ FT_Fixed delta,+ FT_Int dimension )+ {+ PSH_Hint hint;+ FT_UInt count;+++ for ( count = 0; count < table->max_hints; count++ )+ {+ hint = table->hints + count;++ hint->cur_pos = FT_MulFix( hint->org_pos, scale ) + delta;+ hint->cur_len = FT_MulFix( hint->org_len, scale );++ if ( ps_debug_hint_func )+ ps_debug_hint_func( hint, dimension );+ }+ }++#endif /* DEBUG_HINTER */+++ static FT_Fixed+ psh_hint_snap_stem_side_delta( FT_Fixed pos,+ FT_Fixed len )+ {+ FT_Fixed delta1 = FT_PIX_ROUND( pos ) - pos;+ FT_Fixed delta2 = FT_PIX_ROUND( pos + len ) - pos - len;+++ if ( FT_ABS( delta1 ) <= FT_ABS( delta2 ) )+ return delta1;+ else+ return delta2;+ }+++ static void+ psh_hint_align( PSH_Hint hint,+ PSH_Globals globals,+ FT_Int dimension,+ PSH_Glyph glyph )+ {+ PSH_Dimension dim = &globals->dimension[dimension];+ FT_Fixed scale = dim->scale_mult;+ FT_Fixed delta = dim->scale_delta;+++ if ( !psh_hint_is_fitted( hint ) )+ {+ FT_Pos pos = FT_MulFix( hint->org_pos, scale ) + delta;+ FT_Pos len = FT_MulFix( hint->org_len, scale );++ FT_Int do_snapping;+ FT_Pos fit_len;+ PSH_AlignmentRec align;+++ /* ignore stem alignments when requested through the hint flags */+ if ( ( dimension == 0 && !glyph->do_horz_hints ) ||+ ( dimension == 1 && !glyph->do_vert_hints ) )+ {+ hint->cur_pos = pos;+ hint->cur_len = len;++ psh_hint_set_fitted( hint );+ return;+ }++ /* perform stem snapping when requested - this is necessary+ * for monochrome and LCD hinting modes only+ */+ do_snapping = ( dimension == 0 && glyph->do_horz_snapping ) ||+ ( dimension == 1 && glyph->do_vert_snapping );++ hint->cur_len = fit_len = len;++ /* check blue zones for horizontal stems */+ align.align = PSH_BLUE_ALIGN_NONE;+ align.align_bot = align.align_top = 0;++ if ( dimension == 1 )+ psh_blues_snap_stem( &globals->blues,+ hint->org_pos + hint->org_len,+ hint->org_pos,+ &align );++ switch ( align.align )+ {+ case PSH_BLUE_ALIGN_TOP:+ /* the top of the stem is aligned against a blue zone */+ hint->cur_pos = align.align_top - fit_len;+ break;++ case PSH_BLUE_ALIGN_BOT:+ /* the bottom of the stem is aligned against a blue zone */+ hint->cur_pos = align.align_bot;+ break;++ case PSH_BLUE_ALIGN_TOP | PSH_BLUE_ALIGN_BOT:+ /* both edges of the stem are aligned against blue zones */+ hint->cur_pos = align.align_bot;+ hint->cur_len = align.align_top - align.align_bot;+ break;++ default:+ {+ PSH_Hint parent = hint->parent;+++ if ( parent )+ {+ FT_Pos par_org_center, par_cur_center;+ FT_Pos cur_org_center, cur_delta;+++ /* ensure that parent is already fitted */+ if ( !psh_hint_is_fitted( parent ) )+ psh_hint_align( parent, globals, dimension, glyph );++ /* keep original relation between hints, this is, use the */+ /* scaled distance between the centers of the hints to */+ /* compute the new position */+ par_org_center = parent->org_pos + ( parent->org_len >> 1 );+ par_cur_center = parent->cur_pos + ( parent->cur_len >> 1 );+ cur_org_center = hint->org_pos + ( hint->org_len >> 1 );++ cur_delta = FT_MulFix( cur_org_center - par_org_center, scale );+ pos = par_cur_center + cur_delta - ( len >> 1 );+ }++ hint->cur_pos = pos;+ hint->cur_len = fit_len;++ /* Stem adjustment tries to snap stem widths to standard+ * ones. This is important to prevent unpleasant rounding+ * artefacts.+ */+ if ( glyph->do_stem_adjust )+ {+ if ( len <= 64 )+ {+ /* the stem is less than one pixel; we will center it+ * around the nearest pixel center+ */+ if ( len >= 32 )+ {+ /* This is a special case where we also widen the stem+ * and align it to the pixel grid.+ *+ * stem_center = pos + (len/2)+ * nearest_pixel_center = FT_ROUND(stem_center-32)+32+ * new_pos = nearest_pixel_center-32+ * = FT_ROUND(stem_center-32)+ * = FT_FLOOR(stem_center-32+32)+ * = FT_FLOOR(stem_center)+ * new_len = 64+ */+ pos = FT_PIX_FLOOR( pos + ( len >> 1 ) );+ len = 64;+ }+ else if ( len > 0 )+ {+ /* This is a very small stem; we simply align it to the+ * pixel grid, trying to find the minimal displacement.+ *+ * left = pos+ * right = pos + len+ * left_nearest_edge = ROUND(pos)+ * right_nearest_edge = ROUND(right)+ *+ * if ( ABS(left_nearest_edge - left) <=+ * ABS(right_nearest_edge - right) )+ * new_pos = left+ * else+ * new_pos = right+ */+ FT_Pos left_nearest = FT_PIX_ROUND( pos );+ FT_Pos right_nearest = FT_PIX_ROUND( pos + len );+ FT_Pos left_disp = left_nearest - pos;+ FT_Pos right_disp = right_nearest - ( pos + len );+++ if ( left_disp < 0 )+ left_disp = -left_disp;+ if ( right_disp < 0 )+ right_disp = -right_disp;+ if ( left_disp <= right_disp )+ pos = left_nearest;+ else+ pos = right_nearest;+ }+ else+ {+ /* this is a ghost stem; we simply round it */+ pos = FT_PIX_ROUND( pos );+ }+ }+ else+ {+ len = psh_dimension_quantize_len( dim, len, 0 );+ }+ }++ /* now that we have a good hinted stem width, try to position */+ /* the stem along a pixel grid integer coordinate */+ hint->cur_pos = pos + psh_hint_snap_stem_side_delta( pos, len );+ hint->cur_len = len;+ }+ }++ if ( do_snapping )+ {+ pos = hint->cur_pos;+ len = hint->cur_len;++ if ( len < 64 )+ len = 64;+ else+ len = FT_PIX_ROUND( len );++ switch ( align.align )+ {+ case PSH_BLUE_ALIGN_TOP:+ hint->cur_pos = align.align_top - len;+ hint->cur_len = len;+ break;++ case PSH_BLUE_ALIGN_BOT:+ hint->cur_len = len;+ break;++ case PSH_BLUE_ALIGN_BOT | PSH_BLUE_ALIGN_TOP:+ /* don't touch */+ break;+++ default:+ hint->cur_len = len;+ if ( len & 64 )+ pos = FT_PIX_FLOOR( pos + ( len >> 1 ) ) + 32;+ else+ pos = FT_PIX_ROUND( pos + ( len >> 1 ) );++ hint->cur_pos = pos - ( len >> 1 );+ hint->cur_len = len;+ }+ }++ psh_hint_set_fitted( hint );++#ifdef DEBUG_HINTER+ if ( ps_debug_hint_func )+ ps_debug_hint_func( hint, dimension );+#endif+ }+ }+++#if 0 /* not used for now, experimental */++ /*+ * A variant to perform "light" hinting (i.e. FT_RENDER_MODE_LIGHT)+ * of stems+ */+ static void+ psh_hint_align_light( PSH_Hint hint,+ PSH_Globals globals,+ FT_Int dimension,+ PSH_Glyph glyph )+ {+ PSH_Dimension dim = &globals->dimension[dimension];+ FT_Fixed scale = dim->scale_mult;+ FT_Fixed delta = dim->scale_delta;+++ if ( !psh_hint_is_fitted( hint ) )+ {+ FT_Pos pos = FT_MulFix( hint->org_pos, scale ) + delta;+ FT_Pos len = FT_MulFix( hint->org_len, scale );++ FT_Pos fit_len;++ PSH_AlignmentRec align;+++ /* ignore stem alignments when requested through the hint flags */+ if ( ( dimension == 0 && !glyph->do_horz_hints ) ||+ ( dimension == 1 && !glyph->do_vert_hints ) )+ {+ hint->cur_pos = pos;+ hint->cur_len = len;++ psh_hint_set_fitted( hint );+ return;+ }++ fit_len = len;++ hint->cur_len = fit_len;++ /* check blue zones for horizontal stems */+ align.align = PSH_BLUE_ALIGN_NONE;+ align.align_bot = align.align_top = 0;++ if ( dimension == 1 )+ psh_blues_snap_stem( &globals->blues,+ hint->org_pos + hint->org_len,+ hint->org_pos,+ &align );++ switch ( align.align )+ {+ case PSH_BLUE_ALIGN_TOP:+ /* the top of the stem is aligned against a blue zone */+ hint->cur_pos = align.align_top - fit_len;+ break;++ case PSH_BLUE_ALIGN_BOT:+ /* the bottom of the stem is aligned against a blue zone */+ hint->cur_pos = align.align_bot;+ break;++ case PSH_BLUE_ALIGN_TOP | PSH_BLUE_ALIGN_BOT:+ /* both edges of the stem are aligned against blue zones */+ hint->cur_pos = align.align_bot;+ hint->cur_len = align.align_top - align.align_bot;+ break;++ default:+ {+ PSH_Hint parent = hint->parent;+++ if ( parent )+ {+ FT_Pos par_org_center, par_cur_center;+ FT_Pos cur_org_center, cur_delta;+++ /* ensure that parent is already fitted */+ if ( !psh_hint_is_fitted( parent ) )+ psh_hint_align_light( parent, globals, dimension, glyph );++ par_org_center = parent->org_pos + ( parent->org_len / 2 );+ par_cur_center = parent->cur_pos + ( parent->cur_len / 2 );+ cur_org_center = hint->org_pos + ( hint->org_len / 2 );++ cur_delta = FT_MulFix( cur_org_center - par_org_center, scale );+ pos = par_cur_center + cur_delta - ( len >> 1 );+ }++ /* Stems less than one pixel wide are easy -- we want to+ * make them as dark as possible, so they must fall within+ * one pixel. If the stem is split between two pixels+ * then snap the edge that is nearer to the pixel boundary+ * to the pixel boundary.+ */+ if ( len <= 64 )+ {+ if ( ( pos + len + 63 ) / 64 != pos / 64 + 1 )+ pos += psh_hint_snap_stem_side_delta ( pos, len );+ }++ /* Position stems other to minimize the amount of mid-grays.+ * There are, in general, two positions that do this,+ * illustrated as A) and B) below.+ *+ * + + + ++ *+ * A) |--------------------------------|+ * B) |--------------------------------|+ * C) |--------------------------------|+ *+ * Position A) (split the excess stem equally) should be better+ * for stems of width N + f where f < 0.5.+ *+ * Position B) (split the deficiency equally) should be better+ * for stems of width N + f where f > 0.5.+ *+ * It turns out though that minimizing the total number of lit+ * pixels is also important, so position C), with one edge+ * aligned with a pixel boundary is actually preferable+ * to A). There are also more possibile positions for C) than+ * for A) or B), so it involves less distortion of the overall+ * character shape.+ */+ else /* len > 64 */+ {+ FT_Fixed frac_len = len & 63;+ FT_Fixed center = pos + ( len >> 1 );+ FT_Fixed delta_a, delta_b;+++ if ( ( len / 64 ) & 1 )+ {+ delta_a = FT_PIX_FLOOR( center ) + 32 - center;+ delta_b = FT_PIX_ROUND( center ) - center;+ }+ else+ {+ delta_a = FT_PIX_ROUND( center ) - center;+ delta_b = FT_PIX_FLOOR( center ) + 32 - center;+ }++ /* We choose between B) and C) above based on the amount+ * of fractinal stem width; for small amounts, choose+ * C) always, for large amounts, B) always, and inbetween,+ * pick whichever one involves less stem movement.+ */+ if ( frac_len < 32 )+ {+ pos += psh_hint_snap_stem_side_delta ( pos, len );+ }+ else if ( frac_len < 48 )+ {+ FT_Fixed side_delta = psh_hint_snap_stem_side_delta ( pos,+ len );++ if ( FT_ABS( side_delta ) < FT_ABS( delta_b ) )+ pos += side_delta;+ else+ pos += delta_b;+ }+ else+ {+ pos += delta_b;+ }+ }++ hint->cur_pos = pos;+ }+ } /* switch */++ psh_hint_set_fitted( hint );++#ifdef DEBUG_HINTER+ if ( ps_debug_hint_func )+ ps_debug_hint_func( hint, dimension );+#endif+ }+ }++#endif /* 0 */+++ static void+ psh_hint_table_align_hints( PSH_Hint_Table table,+ PSH_Globals globals,+ FT_Int dimension,+ PSH_Glyph glyph )+ {+ PSH_Hint hint;+ FT_UInt count;++#ifdef DEBUG_HINTER++ PSH_Dimension dim = &globals->dimension[dimension];+ FT_Fixed scale = dim->scale_mult;+ FT_Fixed delta = dim->scale_delta;+++ if ( ps_debug_no_vert_hints && dimension == 0 )+ {+ ps_simple_scale( table, scale, delta, dimension );+ return;+ }++ if ( ps_debug_no_horz_hints && dimension == 1 )+ {+ ps_simple_scale( table, scale, delta, dimension );+ return;+ }++#endif /* DEBUG_HINTER*/++ hint = table->hints;+ count = table->max_hints;++ for ( ; count > 0; count--, hint++ )+ psh_hint_align( hint, globals, dimension, glyph );+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** POINTS INTERPOLATION ROUTINES *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++#define PSH_ZONE_MIN -3200000L+#define PSH_ZONE_MAX +3200000L++#define xxDEBUG_ZONES+++#ifdef DEBUG_ZONES++#include FT_CONFIG_STANDARD_LIBRARY_H++ static void+ psh_print_zone( PSH_Zone zone )+ {+ printf( "zone [scale,delta,min,max] = [%.3f,%.3f,%d,%d]\n",+ zone->scale / 65536.0,+ zone->delta / 64.0,+ zone->min,+ zone->max );+ }++#else++#define psh_print_zone( x ) do { } while ( 0 )++#endif /* DEBUG_ZONES */+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** HINTER GLYPH MANAGEMENT *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++#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++ /* compute all inflex points in a given glyph */+ static void+ psh_glyph_compute_inflections( PSH_Glyph glyph )+ {+ FT_UInt n;+++ for ( n = 0; n < glyph->num_contours; n++ )+ {+ PSH_Point first, start, end, before, after;+ FT_Pos in_x, in_y, out_x, out_y;+ FT_Int orient_prev, orient_cur;+ FT_Int finished = 0;+++ /* we need at least 4 points to create an inflection point */+ if ( glyph->contours[n].count < 4 )+ continue;++ /* compute first segment in contour */+ first = glyph->contours[n].start;++ start = end = first;+ do+ {+ end = end->next;+ if ( end == first )+ goto Skip;++ in_x = end->org_u - start->org_u;+ in_y = end->org_v - start->org_v;++ } while ( in_x == 0 && in_y == 0 );++ /* extend the segment start whenever possible */+ before = start;+ do+ {+ do+ {+ start = before;+ before = before->prev;+ if ( before == first )+ goto Skip;++ out_x = start->org_u - before->org_u;+ out_y = start->org_v - before->org_v;++ } while ( out_x == 0 && out_y == 0 );++ orient_prev = psh_corner_orientation( in_x, in_y, out_x, out_y );++ } while ( orient_prev == 0 );++ first = start;+ in_x = out_x;+ in_y = out_y;++ /* now, process all segments in the contour */+ do+ {+ /* first, extend current segment's end whenever possible */+ after = end;+ do+ {+ do+ {+ end = after;+ after = after->next;+ if ( after == first )+ finished = 1;++ out_x = after->org_u - end->org_u;+ out_y = after->org_v - end->org_v;++ } while ( out_x == 0 && out_y == 0 );++ orient_cur = psh_corner_orientation( in_x, in_y, out_x, out_y );++ } while ( orient_cur == 0 );++ if ( ( orient_cur ^ orient_prev ) < 0 )+ {+ do+ {+ psh_point_set_inflex( start );+ start = start->next;+ }+ while ( start != end );++ psh_point_set_inflex( start );+ }++ start = end;+ end = after;+ orient_prev = orient_cur;+ in_x = out_x;+ in_y = out_y;++ } while ( !finished );++ Skip:+ ;+ }+ }++#endif /* COMPUTE_INFLEXS */+++ static void+ psh_glyph_done( PSH_Glyph glyph )+ {+ FT_Memory memory = glyph->memory;+++ psh_hint_table_done( &glyph->hint_tables[1], memory );+ psh_hint_table_done( &glyph->hint_tables[0], memory );++ FT_FREE( glyph->points );+ FT_FREE( glyph->contours );++ glyph->num_points = 0;+ glyph->num_contours = 0;++ glyph->memory = 0;+ }+++ static int+ psh_compute_dir( FT_Pos dx,+ FT_Pos dy )+ {+ FT_Pos ax, ay;+ int result = PSH_DIR_NONE;+++ ax = ( dx >= 0 ) ? dx : -dx;+ ay = ( dy >= 0 ) ? dy : -dy;++ if ( ay * 12 < ax )+ {+ /* |dy| <<< |dx| means a near-horizontal segment */+ result = ( dx >= 0 ) ? PSH_DIR_RIGHT : PSH_DIR_LEFT;+ }+ else if ( ax * 12 < ay )+ {+ /* |dx| <<< |dy| means a near-vertical segment */+ result = ( dy >= 0 ) ? PSH_DIR_UP : PSH_DIR_DOWN;+ }++ return result;+ }+++ /* load outline point coordinates into hinter glyph */+ static void+ psh_glyph_load_points( PSH_Glyph glyph,+ FT_Int dimension )+ {+ FT_Vector* vec = glyph->outline->points;+ PSH_Point point = glyph->points;+ FT_UInt count = glyph->num_points;+++ for ( ; count > 0; count--, point++, vec++ )+ {+ point->flags2 = 0;+ point->hint = NULL;+ if ( dimension == 0 )+ {+ point->org_u = vec->x;+ point->org_v = vec->y;+ }+ else+ {+ point->org_u = vec->y;+ point->org_v = vec->x;+ }++#ifdef DEBUG_HINTER+ point->org_x = vec->x;+ point->org_y = vec->y;+#endif++ }+ }+++ /* save hinted point coordinates back to outline */+ static void+ psh_glyph_save_points( PSH_Glyph glyph,+ FT_Int dimension )+ {+ FT_UInt n;+ PSH_Point point = glyph->points;+ FT_Vector* vec = glyph->outline->points;+ char* tags = glyph->outline->tags;+++ for ( n = 0; n < glyph->num_points; n++ )+ {+ if ( dimension == 0 )+ vec[n].x = point->cur_u;+ else+ vec[n].y = point->cur_u;++ if ( psh_point_is_strong( point ) )+ tags[n] |= (char)( ( dimension == 0 ) ? 32 : 64 );++#ifdef DEBUG_HINTER++ if ( dimension == 0 )+ {+ point->cur_x = point->cur_u;+ point->flags_x = point->flags2 | point->flags;+ }+ else+ {+ point->cur_y = point->cur_u;+ point->flags_y = point->flags2 | point->flags;+ }++#endif++ point++;+ }+ }+++ static FT_Error+ psh_glyph_init( PSH_Glyph glyph,+ FT_Outline* outline,+ PS_Hints ps_hints,+ PSH_Globals globals )+ {+ FT_Error error;+ FT_Memory memory;+++ /* clear all fields */+ FT_MEM_ZERO( glyph, sizeof ( *glyph ) );++ memory = glyph->memory = globals->memory;++ /* allocate and setup points + contours arrays */+ if ( FT_NEW_ARRAY( glyph->points, outline->n_points ) ||+ FT_NEW_ARRAY( glyph->contours, outline->n_contours ) )+ goto Exit;++ glyph->num_points = outline->n_points;+ glyph->num_contours = outline->n_contours;++ {+ FT_UInt first = 0, next, n;+ PSH_Point points = glyph->points;+ PSH_Contour contour = glyph->contours;+++ for ( n = 0; n < glyph->num_contours; n++ )+ {+ FT_Int count;+ PSH_Point point;+++ next = outline->contours[n] + 1;+ count = next - first;++ contour->start = points + first;+ contour->count = (FT_UInt)count;++ if ( count > 0 )+ {+ point = points + first;++ point->prev = points + next - 1;+ point->contour = contour;++ for ( ; count > 1; count-- )+ {+ point[0].next = point + 1;+ point[1].prev = point;+ point++;+ point->contour = contour;+ }+ point->next = points + first;+ }++ contour++;+ first = next;+ }+ }++ {+ PSH_Point points = glyph->points;+ PSH_Point point = points;+ FT_Vector* vec = outline->points;+ FT_UInt n;+++ for ( n = 0; n < glyph->num_points; n++, point++ )+ {+ FT_Int n_prev = (FT_Int)( point->prev - points );+ FT_Int n_next = (FT_Int)( point->next - points );+ FT_Pos dxi, dyi, dxo, dyo;+++ if ( !( outline->tags[n] & FT_CURVE_TAG_ON ) )+ point->flags = PSH_POINT_OFF;++ dxi = vec[n].x - vec[n_prev].x;+ dyi = vec[n].y - vec[n_prev].y;++ point->dir_in = (FT_Char)psh_compute_dir( dxi, dyi );++ dxo = vec[n_next].x - vec[n].x;+ dyo = vec[n_next].y - vec[n].y;++ point->dir_out = (FT_Char)psh_compute_dir( dxo, dyo );++ /* detect smooth points */+ if ( point->flags & PSH_POINT_OFF )+ point->flags |= PSH_POINT_SMOOTH;++ else if ( point->dir_in == point->dir_out )+ {+ if ( point->dir_out != PSH_DIR_NONE ||+ psh_corner_is_flat( dxi, dyi, dxo, dyo ) )+ point->flags |= PSH_POINT_SMOOTH;+ }+ }+ }++ glyph->outline = outline;+ glyph->globals = globals;++#ifdef COMPUTE_INFLEXS+ psh_glyph_load_points( glyph, 0 );+ psh_glyph_compute_inflections( glyph );+#endif /* COMPUTE_INFLEXS */++ /* now deal with hints tables */+ error = psh_hint_table_init( &glyph->hint_tables [0],+ &ps_hints->dimension[0].hints,+ &ps_hints->dimension[0].masks,+ &ps_hints->dimension[0].counters,+ memory );+ if ( error )+ goto Exit;++ error = psh_hint_table_init( &glyph->hint_tables [1],+ &ps_hints->dimension[1].hints,+ &ps_hints->dimension[1].masks,+ &ps_hints->dimension[1].counters,+ memory );+ if ( error )+ goto Exit;++ Exit:+ return error;+ }+++ /* compute all extrema in a glyph for a given dimension */+ static void+ psh_glyph_compute_extrema( PSH_Glyph glyph )+ {+ FT_UInt n;+++ /* first of all, compute all local extrema */+ for ( n = 0; n < glyph->num_contours; n++ )+ {+ PSH_Point first = glyph->contours[n].start;+ PSH_Point point, before, after;+++ if ( glyph->contours[n].count == 0 )+ continue;++ point = first;+ before = point;+ after = point;++ do+ {+ before = before->prev;+ if ( before == first )+ goto Skip;++ } while ( before->org_u == point->org_u );++ first = point = before->next;++ for (;;)+ {+ after = point;+ do+ {+ after = after->next;+ if ( after == first )+ goto Next;++ } while ( after->org_u == point->org_u );++ if ( before->org_u < point->org_u )+ {+ if ( after->org_u < point->org_u )+ {+ /* local maximum */+ goto Extremum;+ }+ }+ else /* before->org_u > point->org_u */+ {+ if ( after->org_u > point->org_u )+ {+ /* local minimum */+ Extremum:+ do+ {+ psh_point_set_extremum( point );+ point = point->next;++ } while ( point != after );+ }+ }++ before = after->prev;+ point = after;++ } /* for */++ Next:+ ;+ }++ /* for each extremum, determine its direction along the */+ /* orthogonal axis */+ for ( n = 0; n < glyph->num_points; n++ )+ {+ PSH_Point point, before, after;+++ point = &glyph->points[n];+ before = point;+ after = point;++ if ( psh_point_is_extremum( point ) )+ {+ do+ {+ before = before->prev;+ if ( before == point )+ goto Skip;++ } while ( before->org_v == point->org_v );++ do+ {+ after = after->next;+ if ( after == point )+ goto Skip;++ } while ( after->org_v == point->org_v );+ }++ if ( before->org_v < point->org_v &&+ after->org_v > point->org_v )+ {+ psh_point_set_positive( point );+ }+ else if ( before->org_v > point->org_v &&+ after->org_v < point->org_v )+ {+ psh_point_set_negative( point );+ }++ Skip:+ ;+ }+ }+++ /* major_dir is the direction for points on the bottom/left of the stem; */+ /* Points on the top/right of the stem will have a direction of */+ /* -major_dir. */++ static void+ psh_hint_table_find_strong_points( PSH_Hint_Table table,+ PSH_Point point,+ FT_UInt count,+ FT_Int threshold,+ FT_Int major_dir )+ {+ PSH_Hint* sort = table->sort;+ FT_UInt num_hints = table->num_hints;+++ for ( ; count > 0; count--, point++ )+ {+ FT_Int point_dir = 0;+ FT_Pos org_u = point->org_u;+++ if ( psh_point_is_strong( point ) )+ continue;++ if ( PSH_DIR_COMPARE( point->dir_in, major_dir ) )+ point_dir = point->dir_in;++ else if ( PSH_DIR_COMPARE( point->dir_out, major_dir ) )+ point_dir = point->dir_out;++ if ( point_dir )+ {+ if ( point_dir == major_dir )+ {+ FT_UInt nn;+++ for ( nn = 0; nn < num_hints; nn++ )+ {+ PSH_Hint hint = sort[nn];+ FT_Pos d = org_u - hint->org_pos;+++ if ( d < threshold && -d < threshold )+ {+ psh_point_set_strong( point );+ point->flags2 |= PSH_POINT_EDGE_MIN;+ point->hint = hint;+ break;+ }+ }+ }+ else if ( point_dir == -major_dir )+ {+ FT_UInt nn;+++ for ( nn = 0; nn < num_hints; nn++ )+ {+ PSH_Hint hint = sort[nn];+ FT_Pos d = org_u - hint->org_pos - hint->org_len;+++ if ( d < threshold && -d < threshold )+ {+ psh_point_set_strong( point );+ point->flags2 |= PSH_POINT_EDGE_MAX;+ point->hint = hint;+ break;+ }+ }+ }+ }++#if 1+ else if ( psh_point_is_extremum( point ) )+ {+ /* treat extrema as special cases for stem edge alignment */+ FT_UInt nn, min_flag, max_flag;+++ if ( major_dir == PSH_DIR_HORIZONTAL )+ {+ min_flag = PSH_POINT_POSITIVE;+ max_flag = PSH_POINT_NEGATIVE;+ }+ else+ {+ min_flag = PSH_POINT_NEGATIVE;+ max_flag = PSH_POINT_POSITIVE;+ }++ if ( point->flags2 & min_flag )+ {+ for ( nn = 0; nn < num_hints; nn++ )+ {+ PSH_Hint hint = sort[nn];+ FT_Pos d = org_u - hint->org_pos;+++ if ( d < threshold && -d < threshold )+ {+ point->flags2 |= PSH_POINT_EDGE_MIN;+ point->hint = hint;+ psh_point_set_strong( point );+ break;+ }+ }+ }+ else if ( point->flags2 & max_flag )+ {+ for ( nn = 0; nn < num_hints; nn++ )+ {+ PSH_Hint hint = sort[nn];+ FT_Pos d = org_u - hint->org_pos - hint->org_len;+++ if ( d < threshold && -d < threshold )+ {+ point->flags2 |= PSH_POINT_EDGE_MAX;+ point->hint = hint;+ psh_point_set_strong( point );+ break;+ }+ }+ }++ if ( point->hint == NULL )+ {+ for ( nn = 0; nn < num_hints; nn++ )+ {+ PSH_Hint hint = sort[nn];+++ if ( org_u >= hint->org_pos &&+ org_u <= hint->org_pos + hint->org_len )+ {+ point->hint = hint;+ break;+ }+ }+ }+ }++#endif /* 1 */+ }+ }+++ /* the accepted shift for strong points in fractional pixels */+#define PSH_STRONG_THRESHOLD 32++ /* the maximum shift value in font units */+#define PSH_STRONG_THRESHOLD_MAXIMUM 30+++ /* find strong points in a glyph */+ static void+ psh_glyph_find_strong_points( PSH_Glyph glyph,+ FT_Int dimension )+ {+ /* a point is `strong' if it is located on a stem edge and */+ /* has an `in' or `out' tangent parallel to the hint's direction */++ PSH_Hint_Table table = &glyph->hint_tables[dimension];+ PS_Mask mask = table->hint_masks->masks;+ FT_UInt num_masks = table->hint_masks->num_masks;+ FT_UInt first = 0;+ FT_Int major_dir = dimension == 0 ? PSH_DIR_VERTICAL+ : PSH_DIR_HORIZONTAL;+ PSH_Dimension dim = &glyph->globals->dimension[dimension];+ FT_Fixed scale = dim->scale_mult;+ FT_Int threshold;+++ threshold = (FT_Int)FT_DivFix( PSH_STRONG_THRESHOLD, scale );+ if ( threshold > PSH_STRONG_THRESHOLD_MAXIMUM )+ threshold = PSH_STRONG_THRESHOLD_MAXIMUM;++ /* process secondary hints to `selected' points */+ if ( num_masks > 1 && glyph->num_points > 0 )+ {+ /* the `endchar' op can reduce the number of points */+ first = mask->end_point > glyph->num_points+ ? glyph->num_points+ : mask->end_point;+ mask++;+ for ( ; num_masks > 1; num_masks--, mask++ )+ {+ FT_UInt next;+ FT_Int count;+++ next = mask->end_point > glyph->num_points+ ? glyph->num_points+ : mask->end_point;+ count = next - first;+ if ( count > 0 )+ {+ PSH_Point point = glyph->points + first;+++ psh_hint_table_activate_mask( table, mask );++ psh_hint_table_find_strong_points( table, point, count,+ threshold, major_dir );+ }+ first = next;+ }+ }++ /* process primary hints for all points */+ if ( num_masks == 1 )+ {+ FT_UInt count = glyph->num_points;+ PSH_Point point = glyph->points;+++ psh_hint_table_activate_mask( table, table->hint_masks->masks );++ psh_hint_table_find_strong_points( table, point, count,+ threshold, major_dir );+ }++ /* now, certain points may have been attached to a hint and */+ /* not marked as strong; update their flags then */+ {+ FT_UInt count = glyph->num_points;+ PSH_Point point = glyph->points;+++ for ( ; count > 0; count--, point++ )+ if ( point->hint && !psh_point_is_strong( point ) )+ psh_point_set_strong( point );+ }+ }+++ /* find points in a glyph which are in a blue zone and have `in' or */+ /* `out' tangents parallel to the horizontal axis */+ static void+ psh_glyph_find_blue_points( PSH_Blues blues,+ PSH_Glyph glyph )+ {+ PSH_Blue_Table table;+ PSH_Blue_Zone zone;+ FT_UInt glyph_count = glyph->num_points;+ FT_UInt blue_count;+ PSH_Point point = glyph->points;+++ for ( ; glyph_count > 0; glyph_count--, point++ )+ {+ FT_Pos y;+++ /* check tangents */+ if ( !PSH_DIR_COMPARE( point->dir_in, PSH_DIR_HORIZONTAL ) &&+ !PSH_DIR_COMPARE( point->dir_out, PSH_DIR_HORIZONTAL ) )+ continue;++ /* skip strong points */+ if ( psh_point_is_strong( point ) )+ continue;++ y = point->org_u;++ /* look up top zones */+ table = &blues->normal_top;+ blue_count = table->count;+ zone = table->zones;++ for ( ; blue_count > 0; blue_count--, zone++ )+ {+ FT_Pos delta = y - zone->org_bottom;+++ if ( delta < -blues->blue_fuzz )+ break;++ if ( y <= zone->org_top + blues->blue_fuzz )+ if ( blues->no_overshoots || delta <= blues->blue_threshold )+ {+ point->cur_u = zone->cur_bottom;+ psh_point_set_strong( point );+ psh_point_set_fitted( point );+ }+ }++ /* look up bottom zones */+ table = &blues->normal_bottom;+ blue_count = table->count;+ zone = table->zones + blue_count - 1;++ for ( ; blue_count > 0; blue_count--, zone-- )+ {+ FT_Pos delta = zone->org_top - y;+++ if ( delta < -blues->blue_fuzz )+ break;++ if ( y >= zone->org_bottom - blues->blue_fuzz )+ if ( blues->no_overshoots || delta < blues->blue_threshold )+ {+ point->cur_u = zone->cur_top;+ psh_point_set_strong( point );+ psh_point_set_fitted( point );+ }+ }+ }+ }+++ /* interpolate strong points with the help of hinted coordinates */+ static void+ psh_glyph_interpolate_strong_points( PSH_Glyph glyph,+ FT_Int dimension )+ {+ PSH_Dimension dim = &glyph->globals->dimension[dimension];+ FT_Fixed scale = dim->scale_mult;++ FT_UInt count = glyph->num_points;+ PSH_Point point = glyph->points;+++ for ( ; count > 0; count--, point++ )+ {+ PSH_Hint hint = point->hint;+++ if ( hint )+ {+ FT_Pos delta;+++ if ( psh_point_is_edge_min( point ) )+ point->cur_u = hint->cur_pos;++ else if ( psh_point_is_edge_max( point ) )+ point->cur_u = hint->cur_pos + hint->cur_len;++ else+ {+ delta = point->org_u - hint->org_pos;++ if ( delta <= 0 )+ point->cur_u = hint->cur_pos + FT_MulFix( delta, scale );++ else if ( delta >= hint->org_len )+ point->cur_u = hint->cur_pos + hint->cur_len ++ FT_MulFix( delta - hint->org_len, scale );++ else /* hint->org_len > 0 */+ point->cur_u = hint->cur_pos ++ FT_MulDiv( delta, hint->cur_len,+ hint->org_len );+ }+ psh_point_set_fitted( point );+ }+ }+ }+++#define PSH_MAX_STRONG_INTERNAL 16++ static void+ psh_glyph_interpolate_normal_points( PSH_Glyph glyph,+ FT_Int dimension )+ {++#if 1+ /* first technique: a point is strong if it is a local extremum */++ PSH_Dimension dim = &glyph->globals->dimension[dimension];+ FT_Fixed scale = dim->scale_mult;+ FT_Memory memory = glyph->memory;++ PSH_Point* strongs = NULL;+ PSH_Point strongs_0[PSH_MAX_STRONG_INTERNAL];+ FT_UInt num_strongs = 0;++ PSH_Point points = glyph->points;+ PSH_Point points_end = points + glyph->num_points;+ PSH_Point point;+++ /* first count the number of strong points */+ for ( point = points; point < points_end; point++ )+ {+ if ( psh_point_is_strong( point ) )+ num_strongs++;+ }++ if ( num_strongs == 0 ) /* nothing to do here */+ return;++ /* allocate an array to store a list of points, */+ /* stored in increasing org_u order */+ if ( num_strongs <= PSH_MAX_STRONG_INTERNAL )+ strongs = strongs_0;+ else+ {+ FT_Error error;+++ if ( FT_NEW_ARRAY( strongs, num_strongs ) )+ return;+ }++ num_strongs = 0;+ for ( point = points; point < points_end; point++ )+ {+ PSH_Point* insert;+++ if ( !psh_point_is_strong( point ) )+ continue;++ for ( insert = strongs + num_strongs; insert > strongs; insert-- )+ {+ if ( insert[-1]->org_u <= point->org_u )+ break;++ insert[0] = insert[-1];+ }+ insert[0] = point;+ num_strongs++;+ }++ /* now try to interpolate all normal points */+ for ( point = points; point < points_end; point++ )+ {+ if ( psh_point_is_strong( point ) )+ continue;++ /* sometimes, some local extrema are smooth points */+ if ( psh_point_is_smooth( point ) )+ {+ if ( point->dir_in == PSH_DIR_NONE ||+ point->dir_in != point->dir_out )+ continue;++ if ( !psh_point_is_extremum( point ) &&+ !psh_point_is_inflex( point ) )+ continue;++ point->flags &= ~PSH_POINT_SMOOTH;+ }++ /* find best enclosing point coordinates then interpolate */+ {+ PSH_Point before, after;+ FT_UInt nn;+++ for ( nn = 0; nn < num_strongs; nn++ )+ if ( strongs[nn]->org_u > point->org_u )+ break;++ if ( nn == 0 ) /* point before the first strong point */+ {+ after = strongs[0];++ point->cur_u = after->cur_u ++ FT_MulFix( point->org_u - after->org_u,+ scale );+ }+ else+ {+ before = strongs[nn - 1];++ for ( nn = num_strongs; nn > 0; nn-- )+ if ( strongs[nn - 1]->org_u < point->org_u )+ break;++ if ( nn == num_strongs ) /* point is after last strong point */+ {+ before = strongs[nn - 1];++ point->cur_u = before->cur_u ++ FT_MulFix( point->org_u - before->org_u,+ scale );+ }+ else+ {+ FT_Pos u;+++ after = strongs[nn];++ /* now interpolate point between before and after */+ u = point->org_u;++ if ( u == before->org_u )+ point->cur_u = before->cur_u;++ else if ( u == after->org_u )+ point->cur_u = after->cur_u;++ else+ point->cur_u = before->cur_u ++ FT_MulDiv( u - before->org_u,+ after->cur_u - before->cur_u,+ after->org_u - before->org_u );+ }+ }+ psh_point_set_fitted( point );+ }+ }++ if ( strongs != strongs_0 )+ FT_FREE( strongs );++#endif /* 1 */++ }+++ /* interpolate other points */+ static void+ psh_glyph_interpolate_other_points( PSH_Glyph glyph,+ FT_Int dimension )+ {+ PSH_Dimension dim = &glyph->globals->dimension[dimension];+ FT_Fixed scale = dim->scale_mult;+ FT_Fixed delta = dim->scale_delta;+ PSH_Contour contour = glyph->contours;+ FT_UInt num_contours = glyph->num_contours;+++ for ( ; num_contours > 0; num_contours--, contour++ )+ {+ PSH_Point start = contour->start;+ PSH_Point first, next, point;+ FT_UInt fit_count;+++ /* count the number of strong points in this contour */+ next = start + contour->count;+ fit_count = 0;+ first = 0;++ for ( point = start; point < next; point++ )+ if ( psh_point_is_fitted( point ) )+ {+ if ( !first )+ first = point;++ fit_count++;+ }++ /* if there are less than 2 fitted points in the contour, we */+ /* simply scale and eventually translate the contour points */+ if ( fit_count < 2 )+ {+ if ( fit_count == 1 )+ delta = first->cur_u - FT_MulFix( first->org_u, scale );++ for ( point = start; point < next; point++ )+ if ( point != first )+ point->cur_u = FT_MulFix( point->org_u, scale ) + delta;++ goto Next_Contour;+ }++ /* there are more than 2 strong points in this contour; we */+ /* need to interpolate weak points between them */+ start = first;+ do+ {+ point = first;++ /* skip consecutive fitted points */+ for (;;)+ {+ next = first->next;+ if ( next == start )+ goto Next_Contour;++ if ( !psh_point_is_fitted( next ) )+ break;++ first = next;+ }++ /* find next fitted point after unfitted one */+ for (;;)+ {+ next = next->next;+ if ( psh_point_is_fitted( next ) )+ break;+ }++ /* now interpolate between them */+ {+ FT_Pos org_a, org_ab, cur_a, cur_ab;+ FT_Pos org_c, org_ac, cur_c;+ FT_Fixed scale_ab;+++ if ( first->org_u <= next->org_u )+ {+ org_a = first->org_u;+ cur_a = first->cur_u;+ org_ab = next->org_u - org_a;+ cur_ab = next->cur_u - cur_a;+ }+ else+ {+ org_a = next->org_u;+ cur_a = next->cur_u;+ org_ab = first->org_u - org_a;+ cur_ab = first->cur_u - cur_a;+ }++ scale_ab = 0x10000L;+ if ( org_ab > 0 )+ scale_ab = FT_DivFix( cur_ab, org_ab );++ point = first->next;+ do+ {+ org_c = point->org_u;+ org_ac = org_c - org_a;++ if ( org_ac <= 0 )+ {+ /* on the left of the interpolation zone */+ cur_c = cur_a + FT_MulFix( org_ac, scale );+ }+ else if ( org_ac >= org_ab )+ {+ /* on the right on the interpolation zone */+ cur_c = cur_a + cur_ab + FT_MulFix( org_ac - org_ab, scale );+ }+ else+ {+ /* within the interpolation zone */+ cur_c = cur_a + FT_MulFix( org_ac, scale_ab );+ }++ point->cur_u = cur_c;++ point = point->next;++ } while ( point != next );+ }++ /* keep going until all points in the contours have been processed */+ first = next;++ } while ( first != start );++ Next_Contour:+ ;+ }+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** HIGH-LEVEL INTERFACE *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ FT_Error+ ps_hints_apply( PS_Hints ps_hints,+ FT_Outline* outline,+ PSH_Globals globals,+ FT_Render_Mode hint_mode )+ {+ PSH_GlyphRec glyphrec;+ PSH_Glyph glyph = &glyphrec;+ FT_Error error;+#ifdef DEBUG_HINTER+ FT_Memory memory;+#endif+ FT_Int dimension;+++ /* something to do? */+ if ( outline->n_points == 0 || outline->n_contours == 0 )+ return PSH_Err_Ok;++#ifdef DEBUG_HINTER++ memory = globals->memory;++ if ( ps_debug_glyph )+ {+ psh_glyph_done( ps_debug_glyph );+ FT_FREE( ps_debug_glyph );+ }++ if ( FT_NEW( glyph ) )+ return error;++ ps_debug_glyph = glyph;++#endif /* DEBUG_HINTER */++ error = psh_glyph_init( glyph, outline, ps_hints, globals );+ if ( error )+ goto Exit;++ /* try to optimize the y_scale so that the top of non-capital letters+ * is aligned on a pixel boundary whenever possible+ */+ {+ PSH_Dimension dim_x = &glyph->globals->dimension[0];+ PSH_Dimension dim_y = &glyph->globals->dimension[1];++ FT_Fixed x_scale = dim_x->scale_mult;+ FT_Fixed y_scale = dim_y->scale_mult;++ FT_Fixed old_x_scale = x_scale;+ FT_Fixed old_y_scale = y_scale;++ FT_Fixed scaled;+ FT_Fixed fitted;++ FT_Bool rescale = FALSE;+++ scaled = FT_MulFix( globals->blues.normal_top.zones->org_ref, y_scale );+ fitted = FT_PIX_ROUND( scaled );++ if ( fitted != 0 && scaled != fitted )+ {+ rescale = TRUE;++ y_scale = FT_MulDiv( y_scale, fitted, scaled );++ if ( fitted < scaled )+ x_scale -= x_scale / 50;++ psh_globals_set_scale( glyph->globals, x_scale, y_scale, 0, 0 );+ }++ glyph->do_horz_hints = 1;+ glyph->do_vert_hints = 1;++ glyph->do_horz_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO ||+ hint_mode == FT_RENDER_MODE_LCD );++ glyph->do_vert_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO ||+ hint_mode == FT_RENDER_MODE_LCD_V );++ glyph->do_stem_adjust = FT_BOOL( hint_mode != FT_RENDER_MODE_LIGHT );++ for ( dimension = 0; dimension < 2; dimension++ )+ {+ /* load outline coordinates into glyph */+ psh_glyph_load_points( glyph, dimension );++ /* compute local extrema */+ psh_glyph_compute_extrema( glyph );++ /* compute aligned stem/hints positions */+ psh_hint_table_align_hints( &glyph->hint_tables[dimension],+ glyph->globals,+ dimension,+ glyph );++ /* find strong points, align them, then interpolate others */+ psh_glyph_find_strong_points( glyph, dimension );+ if ( dimension == 1 )+ psh_glyph_find_blue_points( &globals->blues, glyph );+ psh_glyph_interpolate_strong_points( glyph, dimension );+ psh_glyph_interpolate_normal_points( glyph, dimension );+ psh_glyph_interpolate_other_points( glyph, dimension );++ /* save hinted coordinates back to outline */+ psh_glyph_save_points( glyph, dimension );++ if ( rescale )+ psh_globals_set_scale( glyph->globals,+ old_x_scale, old_y_scale, 0, 0 );+ }+ }++ Exit:++#ifndef DEBUG_HINTER+ psh_glyph_done( glyph );+#endif++ return error;+ }+++/* END */
+ src/pshinter/pshalgo.h view
@@ -0,0 +1,255 @@+/***************************************************************************/+/* */+/* pshalgo.h */+/* */+/* PostScript hinting algorithm (specification). */+/* */+/* Copyright 2001, 2002, 2003, 2008 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 __PSHALGO_H__+#define __PSHALGO_H__+++#include "pshrec.h"+#include "pshglob.h"+#include FT_TRIGONOMETRY_H+++FT_BEGIN_HEADER+++ /* handle to Hint structure */+ typedef struct PSH_HintRec_* PSH_Hint;++ /* hint bit-flags */+ typedef enum PSH_Hint_Flags_+ {+ PSH_HINT_GHOST = PS_HINT_FLAG_GHOST,+ PSH_HINT_BOTTOM = PS_HINT_FLAG_BOTTOM,+ PSH_HINT_ACTIVE = 4,+ PSH_HINT_FITTED = 8++ } PSH_Hint_Flags;+++#define psh_hint_is_active( x ) ( ( (x)->flags & PSH_HINT_ACTIVE ) != 0 )+#define psh_hint_is_ghost( x ) ( ( (x)->flags & PSH_HINT_GHOST ) != 0 )+#define psh_hint_is_fitted( x ) ( ( (x)->flags & PSH_HINT_FITTED ) != 0 )++#define psh_hint_activate( x ) (x)->flags |= PSH_HINT_ACTIVE+#define psh_hint_deactivate( x ) (x)->flags &= ~PSH_HINT_ACTIVE+#define psh_hint_set_fitted( x ) (x)->flags |= PSH_HINT_FITTED++ /* hint structure */+ typedef struct PSH_HintRec_+ {+ FT_Int org_pos;+ FT_Int org_len;+ FT_Pos cur_pos;+ FT_Pos cur_len;+ FT_UInt flags;+ PSH_Hint parent;+ FT_Int order;++ } PSH_HintRec;+++ /* this is an interpolation zone used for strong points; */+ /* weak points are interpolated according to their strong */+ /* neighbours */+ typedef struct PSH_ZoneRec_+ {+ FT_Fixed scale;+ FT_Fixed delta;+ FT_Pos min;+ FT_Pos max;++ } PSH_ZoneRec, *PSH_Zone;+++ typedef struct PSH_Hint_TableRec_+ {+ FT_UInt max_hints;+ FT_UInt num_hints;+ PSH_Hint hints;+ PSH_Hint* sort;+ PSH_Hint* sort_global;+ FT_UInt num_zones;+ PSH_ZoneRec* zones;+ PSH_Zone zone;+ PS_Mask_Table hint_masks;+ PS_Mask_Table counter_masks;++ } PSH_Hint_TableRec, *PSH_Hint_Table;+++ typedef struct PSH_PointRec_* PSH_Point;+ typedef struct PSH_ContourRec_* PSH_Contour;++ enum+ {+ PSH_DIR_NONE = 4,+ PSH_DIR_UP = -1,+ PSH_DIR_DOWN = 1,+ PSH_DIR_LEFT = -2,+ PSH_DIR_RIGHT = 2+ };++#define PSH_DIR_HORIZONTAL 2+#define PSH_DIR_VERTICAL 1++#define PSH_DIR_COMPARE( d1, d2 ) ( (d1) == (d2) || (d1) == -(d2) )+#define PSH_DIR_IS_HORIZONTAL( d ) PSH_DIR_COMPARE( d, PSH_DIR_HORIZONTAL )+#define PSH_DIR_IS_VERTICAL( d ) PSH_DIR_COMPARE( d, PSH_DIR_VERTICAL )+++ /* the following bit-flags are computed once by the glyph */+ /* analyzer, for both dimensions */+ enum+ {+ PSH_POINT_OFF = 1, /* point is off the curve */+ PSH_POINT_SMOOTH = 2, /* point is smooth */+ PSH_POINT_INFLEX = 4 /* point is inflection */+ };++#define psh_point_is_smooth( p ) ( (p)->flags & PSH_POINT_SMOOTH )+#define psh_point_is_off( p ) ( (p)->flags & PSH_POINT_OFF )+#define psh_point_is_inflex( p ) ( (p)->flags & PSH_POINT_INFLEX )++#define psh_point_set_smooth( p ) (p)->flags |= PSH_POINT_SMOOTH+#define psh_point_set_off( p ) (p)->flags |= PSH_POINT_OFF+#define psh_point_set_inflex( p ) (p)->flags |= PSH_POINT_INFLEX++ /* the following bit-flags are re-computed for each dimension */+ enum+ {+ PSH_POINT_STRONG = 16, /* point is strong */+ PSH_POINT_FITTED = 32, /* point is already fitted */+ PSH_POINT_EXTREMUM = 64, /* point is local extremum */+ PSH_POINT_POSITIVE = 128, /* extremum has positive contour flow */+ PSH_POINT_NEGATIVE = 256, /* extremum has negative contour flow */+ PSH_POINT_EDGE_MIN = 512, /* point is aligned to left/bottom stem edge */+ PSH_POINT_EDGE_MAX = 1024 /* point is aligned to top/right stem edge */+ };++#define psh_point_is_strong( p ) ( (p)->flags2 & PSH_POINT_STRONG )+#define psh_point_is_fitted( p ) ( (p)->flags2 & PSH_POINT_FITTED )+#define psh_point_is_extremum( p ) ( (p)->flags2 & PSH_POINT_EXTREMUM )+#define psh_point_is_positive( p ) ( (p)->flags2 & PSH_POINT_POSITIVE )+#define psh_point_is_negative( p ) ( (p)->flags2 & PSH_POINT_NEGATIVE )+#define psh_point_is_edge_min( p ) ( (p)->flags2 & PSH_POINT_EDGE_MIN )+#define psh_point_is_edge_max( p ) ( (p)->flags2 & PSH_POINT_EDGE_MAX )++#define psh_point_set_strong( p ) (p)->flags2 |= PSH_POINT_STRONG+#define psh_point_set_fitted( p ) (p)->flags2 |= PSH_POINT_FITTED+#define psh_point_set_extremum( p ) (p)->flags2 |= PSH_POINT_EXTREMUM+#define psh_point_set_positive( p ) (p)->flags2 |= PSH_POINT_POSITIVE+#define psh_point_set_negative( p ) (p)->flags2 |= PSH_POINT_NEGATIVE+#define psh_point_set_edge_min( p ) (p)->flags2 |= PSH_POINT_EDGE_MIN+#define psh_point_set_edge_max( p ) (p)->flags2 |= PSH_POINT_EDGE_MAX+++ typedef struct PSH_PointRec_+ {+ PSH_Point prev;+ PSH_Point next;+ PSH_Contour contour;+ FT_UInt flags;+ FT_UInt flags2;+ FT_Char dir_in;+ FT_Char dir_out;+ FT_Angle angle_in;+ FT_Angle angle_out;+ PSH_Hint hint;+ FT_Pos org_u;+ FT_Pos org_v;+ FT_Pos cur_u;+#ifdef DEBUG_HINTER+ FT_Pos org_x;+ FT_Pos cur_x;+ FT_Pos org_y;+ FT_Pos cur_y;+ FT_UInt flags_x;+ FT_UInt flags_y;+#endif++ } PSH_PointRec;+++#define PSH_POINT_EQUAL_ORG( a, b ) ( (a)->org_u == (b)->org_u && \+ (a)->org_v == (b)->org_v )++#define PSH_POINT_ANGLE( a, b ) FT_Atan2( (b)->org_u - (a)->org_u, \+ (b)->org_v - (a)->org_v )++ typedef struct PSH_ContourRec_+ {+ PSH_Point start;+ FT_UInt count;++ } PSH_ContourRec;+++ typedef struct PSH_GlyphRec_+ {+ FT_UInt num_points;+ FT_UInt num_contours;++ PSH_Point points;+ PSH_Contour contours;++ FT_Memory memory;+ FT_Outline* outline;+ PSH_Globals globals;+ PSH_Hint_TableRec hint_tables[2];++ FT_Bool vertical;+ FT_Int major_dir;+ FT_Int minor_dir;++ FT_Bool do_horz_hints;+ FT_Bool do_vert_hints;+ FT_Bool do_horz_snapping;+ FT_Bool do_vert_snapping;+ FT_Bool do_stem_adjust;++ } PSH_GlyphRec, *PSH_Glyph;+++#ifdef DEBUG_HINTER+ extern PSH_Hint_Table ps_debug_hint_table;++ typedef void+ (*PSH_HintFunc)( PSH_Hint hint,+ FT_Bool vertical );++ extern PSH_HintFunc ps_debug_hint_func;++ extern PSH_Glyph ps_debug_glyph;+#endif+++ extern FT_Error+ ps_hints_apply( PS_Hints ps_hints,+ FT_Outline* outline,+ PSH_Globals globals,+ FT_Render_Mode hint_mode );+++FT_END_HEADER+++#endif /* __PSHALGO_H__ */+++/* END */
+ src/pshinter/pshglob.c view
@@ -0,0 +1,750 @@+/***************************************************************************/+/* */+/* pshglob.c */+/* */+/* PostScript hinter global hinting management (body). */+/* Inspired by the new auto-hinter module. */+/* */+/* Copyright 2001, 2002, 2003, 2004, 2006, 2010 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used */+/* modified and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#include <ft2build.h>+#include FT_FREETYPE_H+#include FT_INTERNAL_OBJECTS_H+#include "pshglob.h"++#ifdef DEBUG_HINTER+ PSH_Globals ps_debug_globals = 0;+#endif+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** STANDARD WIDTHS *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+++ /* scale the widths/heights table */+ static void+ psh_globals_scale_widths( PSH_Globals globals,+ FT_UInt direction )+ {+ PSH_Dimension dim = &globals->dimension[direction];+ PSH_Widths stdw = &dim->stdw;+ FT_UInt count = stdw->count;+ PSH_Width width = stdw->widths;+ PSH_Width stand = width; /* standard width/height */+ FT_Fixed scale = dim->scale_mult;+++ if ( count > 0 )+ {+ width->cur = FT_MulFix( width->org, scale );+ width->fit = FT_PIX_ROUND( width->cur );++ width++;+ count--;++ for ( ; count > 0; count--, width++ )+ {+ FT_Pos w, dist;+++ w = FT_MulFix( width->org, scale );+ dist = w - stand->cur;++ if ( dist < 0 )+ dist = -dist;++ if ( dist < 128 )+ w = stand->cur;++ width->cur = w;+ width->fit = FT_PIX_ROUND( w );+ }+ }+ }+++#if 0++ /* org_width is is font units, result in device pixels, 26.6 format */+ FT_LOCAL_DEF( FT_Pos )+ psh_dimension_snap_width( PSH_Dimension dimension,+ FT_Int org_width )+ {+ FT_UInt n;+ FT_Pos width = FT_MulFix( org_width, dimension->scale_mult );+ FT_Pos best = 64 + 32 + 2;+ FT_Pos reference = width;+++ for ( n = 0; n < dimension->stdw.count; n++ )+ {+ FT_Pos w;+ FT_Pos dist;+++ w = dimension->stdw.widths[n].cur;+ dist = width - w;+ if ( dist < 0 )+ dist = -dist;+ if ( dist < best )+ {+ best = dist;+ reference = w;+ }+ }++ if ( width >= reference )+ {+ width -= 0x21;+ if ( width < reference )+ width = reference;+ }+ else+ {+ width += 0x21;+ if ( width > reference )+ width = reference;+ }++ return width;+ }++#endif /* 0 */+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** BLUE ZONES *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ static void+ psh_blues_set_zones_0( PSH_Blues target,+ FT_Bool is_others,+ FT_UInt read_count,+ FT_Short* read,+ PSH_Blue_Table top_table,+ PSH_Blue_Table bot_table )+ {+ FT_UInt count_top = top_table->count;+ FT_UInt count_bot = bot_table->count;+ FT_Bool first = 1;++ FT_UNUSED( target );+++ for ( ; read_count > 1; read_count -= 2 )+ {+ FT_Int reference, delta;+ FT_UInt count;+ PSH_Blue_Zone zones, zone;+ FT_Bool top;+++ /* read blue zone entry, and select target top/bottom zone */+ top = 0;+ if ( first || is_others )+ {+ reference = read[1];+ delta = read[0] - reference;++ zones = bot_table->zones;+ count = count_bot;+ first = 0;+ }+ else+ {+ reference = read[0];+ delta = read[1] - reference;++ zones = top_table->zones;+ count = count_top;+ top = 1;+ }++ /* insert into sorted table */+ zone = zones;+ for ( ; count > 0; count--, zone++ )+ {+ if ( reference < zone->org_ref )+ break;++ if ( reference == zone->org_ref )+ {+ FT_Int delta0 = zone->org_delta;+++ /* we have two zones on the same reference position -- */+ /* only keep the largest one */+ if ( delta < 0 )+ {+ if ( delta < delta0 )+ zone->org_delta = delta;+ }+ else+ {+ if ( delta > delta0 )+ zone->org_delta = delta;+ }+ goto Skip;+ }+ }++ for ( ; count > 0; count-- )+ zone[count] = zone[count-1];++ zone->org_ref = reference;+ zone->org_delta = delta;++ if ( top )+ count_top++;+ else+ count_bot++;++ Skip:+ read += 2;+ }++ top_table->count = count_top;+ bot_table->count = count_bot;+ }+++ /* Re-read blue zones from the original fonts and store them into out */+ /* private structure. This function re-orders, sanitizes and */+ /* fuzz-expands the zones as well. */+ static void+ psh_blues_set_zones( PSH_Blues target,+ FT_UInt count,+ FT_Short* blues,+ FT_UInt count_others,+ FT_Short* other_blues,+ FT_Int fuzz,+ FT_Int family )+ {+ PSH_Blue_Table top_table, bot_table;+ FT_Int count_top, count_bot;+++ if ( family )+ {+ top_table = &target->family_top;+ bot_table = &target->family_bottom;+ }+ else+ {+ top_table = &target->normal_top;+ bot_table = &target->normal_bottom;+ }++ /* read the input blue zones, and build two sorted tables */+ /* (one for the top zones, the other for the bottom zones) */+ top_table->count = 0;+ bot_table->count = 0;++ /* first, the blues */+ psh_blues_set_zones_0( target, 0,+ count, blues, top_table, bot_table );+ psh_blues_set_zones_0( target, 1,+ count_others, other_blues, top_table, bot_table );++ count_top = top_table->count;+ count_bot = bot_table->count;++ /* sanitize top table */+ if ( count_top > 0 )+ {+ PSH_Blue_Zone zone = top_table->zones;+++ for ( count = count_top; count > 0; count--, zone++ )+ {+ FT_Int delta;+++ if ( count > 1 )+ {+ delta = zone[1].org_ref - zone[0].org_ref;+ if ( zone->org_delta > delta )+ zone->org_delta = delta;+ }++ zone->org_bottom = zone->org_ref;+ zone->org_top = zone->org_delta + zone->org_ref;+ }+ }++ /* sanitize bottom table */+ if ( count_bot > 0 )+ {+ PSH_Blue_Zone zone = bot_table->zones;+++ for ( count = count_bot; count > 0; count--, zone++ )+ {+ FT_Int delta;+++ if ( count > 1 )+ {+ delta = zone[0].org_ref - zone[1].org_ref;+ if ( zone->org_delta < delta )+ zone->org_delta = delta;+ }++ zone->org_top = zone->org_ref;+ zone->org_bottom = zone->org_delta + zone->org_ref;+ }+ }++ /* expand top and bottom tables with blue fuzz */+ {+ FT_Int dim, top, bot, delta;+ PSH_Blue_Zone zone;+++ zone = top_table->zones;+ count = count_top;++ for ( dim = 1; dim >= 0; dim-- )+ {+ if ( count > 0 )+ {+ /* expand the bottom of the lowest zone normally */+ zone->org_bottom -= fuzz;++ /* expand the top and bottom of intermediate zones; */+ /* checking that the interval is smaller than the fuzz */+ top = zone->org_top;++ for ( count--; count > 0; count-- )+ {+ bot = zone[1].org_bottom;+ delta = bot - top;++ if ( delta < 2 * fuzz )+ zone[0].org_top = zone[1].org_bottom = top + delta / 2;+ else+ {+ zone[0].org_top = top + fuzz;+ zone[1].org_bottom = bot - fuzz;+ }++ zone++;+ top = zone->org_top;+ }++ /* expand the top of the highest zone normally */+ zone->org_top = top + fuzz;+ }+ zone = bot_table->zones;+ count = count_bot;+ }+ }+ }+++ /* reset the blues table when the device transform changes */+ static void+ psh_blues_scale_zones( PSH_Blues blues,+ FT_Fixed scale,+ FT_Pos delta )+ {+ FT_UInt count;+ FT_UInt num;+ PSH_Blue_Table table = 0;++ /* */+ /* Determine whether we need to suppress overshoots or */+ /* not. We simply need to compare the vertical scale */+ /* parameter to the raw bluescale value. Here is why: */+ /* */+ /* We need to suppress overshoots for all pointsizes. */+ /* At 300dpi that satisfies: */+ /* */+ /* pointsize < 240*bluescale + 0.49 */+ /* */+ /* This corresponds to: */+ /* */+ /* pixelsize < 1000*bluescale + 49/24 */+ /* */+ /* scale*EM_Size < 1000*bluescale + 49/24 */+ /* */+ /* However, for normal Type 1 fonts, EM_Size is 1000! */+ /* We thus only check: */+ /* */+ /* scale < bluescale + 49/24000 */+ /* */+ /* which we shorten to */+ /* */+ /* "scale < bluescale" */+ /* */+ /* Note that `blue_scale' is stored 1000 times its real */+ /* value, and that `scale' converts from font units to */+ /* fractional pixels. */+ /* */++ /* 1000 / 64 = 125 / 8 */+ if ( scale >= 0x20C49BAL )+ blues->no_overshoots = FT_BOOL( scale < blues->blue_scale * 8 / 125 );+ else+ blues->no_overshoots = FT_BOOL( scale * 125 < blues->blue_scale * 8 );++ /* */+ /* The blue threshold is the font units distance under */+ /* which overshoots are suppressed due to the BlueShift */+ /* even if the scale is greater than BlueScale. */+ /* */+ /* It is the smallest distance such that */+ /* */+ /* dist <= BlueShift && dist*scale <= 0.5 pixels */+ /* */+ {+ FT_Int threshold = blues->blue_shift;+++ while ( threshold > 0 && FT_MulFix( threshold, scale ) > 32 )+ threshold--;++ blues->blue_threshold = threshold;+ }++ for ( num = 0; num < 4; num++ )+ {+ PSH_Blue_Zone zone;+++ switch ( num )+ {+ case 0:+ table = &blues->normal_top;+ break;+ case 1:+ table = &blues->normal_bottom;+ break;+ case 2:+ table = &blues->family_top;+ break;+ default:+ table = &blues->family_bottom;+ break;+ }++ zone = table->zones;+ count = table->count;+ for ( ; count > 0; count--, zone++ )+ {+ zone->cur_top = FT_MulFix( zone->org_top, scale ) + delta;+ zone->cur_bottom = FT_MulFix( zone->org_bottom, scale ) + delta;+ zone->cur_ref = FT_MulFix( zone->org_ref, scale ) + delta;+ zone->cur_delta = FT_MulFix( zone->org_delta, scale );++ /* round scaled reference position */+ zone->cur_ref = FT_PIX_ROUND( zone->cur_ref );++#if 0+ if ( zone->cur_ref > zone->cur_top )+ zone->cur_ref -= 64;+ else if ( zone->cur_ref < zone->cur_bottom )+ zone->cur_ref += 64;+#endif+ }+ }++ /* process the families now */++ for ( num = 0; num < 2; num++ )+ {+ PSH_Blue_Zone zone1, zone2;+ FT_UInt count1, count2;+ PSH_Blue_Table normal, family;+++ switch ( num )+ {+ case 0:+ normal = &blues->normal_top;+ family = &blues->family_top;+ break;++ default:+ normal = &blues->normal_bottom;+ family = &blues->family_bottom;+ }++ zone1 = normal->zones;+ count1 = normal->count;++ for ( ; count1 > 0; count1--, zone1++ )+ {+ /* try to find a family zone whose reference position is less */+ /* than 1 pixel far from the current zone */+ zone2 = family->zones;+ count2 = family->count;++ for ( ; count2 > 0; count2--, zone2++ )+ {+ FT_Pos Delta;+++ Delta = zone1->org_ref - zone2->org_ref;+ if ( Delta < 0 )+ Delta = -Delta;++ if ( FT_MulFix( Delta, scale ) < 64 )+ {+ zone1->cur_top = zone2->cur_top;+ zone1->cur_bottom = zone2->cur_bottom;+ zone1->cur_ref = zone2->cur_ref;+ zone1->cur_delta = zone2->cur_delta;+ break;+ }+ }+ }+ }+ }+++ FT_LOCAL_DEF( void )+ psh_blues_snap_stem( PSH_Blues blues,+ FT_Int stem_top,+ FT_Int stem_bot,+ PSH_Alignment alignment )+ {+ PSH_Blue_Table table;+ FT_UInt count;+ FT_Pos delta;+ PSH_Blue_Zone zone;+ FT_Int no_shoots;+++ alignment->align = PSH_BLUE_ALIGN_NONE;++ no_shoots = blues->no_overshoots;++ /* look up stem top in top zones table */+ table = &blues->normal_top;+ count = table->count;+ zone = table->zones;++ for ( ; count > 0; count--, zone++ )+ {+ delta = stem_top - zone->org_bottom;+ if ( delta < -blues->blue_fuzz )+ break;++ if ( stem_top <= zone->org_top + blues->blue_fuzz )+ {+ if ( no_shoots || delta <= blues->blue_threshold )+ {+ alignment->align |= PSH_BLUE_ALIGN_TOP;+ alignment->align_top = zone->cur_ref;+ }+ break;+ }+ }++ /* look up stem bottom in bottom zones table */+ table = &blues->normal_bottom;+ count = table->count;+ zone = table->zones + count-1;++ for ( ; count > 0; count--, zone-- )+ {+ delta = zone->org_top - stem_bot;+ if ( delta < -blues->blue_fuzz )+ break;++ if ( stem_bot >= zone->org_bottom - blues->blue_fuzz )+ {+ if ( no_shoots || delta < blues->blue_threshold )+ {+ alignment->align |= PSH_BLUE_ALIGN_BOT;+ alignment->align_bot = zone->cur_ref;+ }+ break;+ }+ }+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** GLOBAL HINTS *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ static void+ psh_globals_destroy( PSH_Globals globals )+ {+ if ( globals )+ {+ FT_Memory memory;+++ memory = globals->memory;+ globals->dimension[0].stdw.count = 0;+ globals->dimension[1].stdw.count = 0;++ globals->blues.normal_top.count = 0;+ globals->blues.normal_bottom.count = 0;+ globals->blues.family_top.count = 0;+ globals->blues.family_bottom.count = 0;++ FT_FREE( globals );++#ifdef DEBUG_HINTER+ ps_debug_globals = 0;+#endif+ }+ }+++ static FT_Error+ psh_globals_new( FT_Memory memory,+ T1_Private* priv,+ PSH_Globals *aglobals )+ {+ PSH_Globals globals = NULL;+ FT_Error error;+++ if ( !FT_NEW( globals ) )+ {+ FT_UInt count;+ FT_Short* read;+++ globals->memory = memory;++ /* copy standard widths */+ {+ PSH_Dimension dim = &globals->dimension[1];+ PSH_Width write = dim->stdw.widths;+++ write->org = priv->standard_width[0];+ write++;++ read = priv->snap_widths;+ for ( count = priv->num_snap_widths; count > 0; count-- )+ {+ write->org = *read;+ write++;+ read++;+ }++ dim->stdw.count = priv->num_snap_widths + 1;+ }++ /* copy standard heights */+ {+ PSH_Dimension dim = &globals->dimension[0];+ PSH_Width write = dim->stdw.widths;+++ write->org = priv->standard_height[0];+ write++;+ read = priv->snap_heights;+ for ( count = priv->num_snap_heights; count > 0; count-- )+ {+ write->org = *read;+ write++;+ read++;+ }++ dim->stdw.count = priv->num_snap_heights + 1;+ }++ /* copy blue zones */+ psh_blues_set_zones( &globals->blues, priv->num_blue_values,+ priv->blue_values, priv->num_other_blues,+ priv->other_blues, priv->blue_fuzz, 0 );++ psh_blues_set_zones( &globals->blues, priv->num_family_blues,+ priv->family_blues, priv->num_family_other_blues,+ priv->family_other_blues, priv->blue_fuzz, 1 );++ globals->blues.blue_scale = priv->blue_scale;+ globals->blues.blue_shift = priv->blue_shift;+ globals->blues.blue_fuzz = priv->blue_fuzz;++ globals->dimension[0].scale_mult = 0;+ globals->dimension[0].scale_delta = 0;+ globals->dimension[1].scale_mult = 0;+ globals->dimension[1].scale_delta = 0;++#ifdef DEBUG_HINTER+ ps_debug_globals = globals;+#endif+ }++ *aglobals = globals;+ return error;+ }+++ FT_LOCAL_DEF( FT_Error )+ psh_globals_set_scale( PSH_Globals globals,+ FT_Fixed x_scale,+ FT_Fixed y_scale,+ FT_Fixed x_delta,+ FT_Fixed y_delta )+ {+ PSH_Dimension dim = &globals->dimension[0];+++ dim = &globals->dimension[0];+ if ( x_scale != dim->scale_mult ||+ x_delta != dim->scale_delta )+ {+ dim->scale_mult = x_scale;+ dim->scale_delta = x_delta;++ psh_globals_scale_widths( globals, 0 );+ }++ dim = &globals->dimension[1];+ if ( y_scale != dim->scale_mult ||+ y_delta != dim->scale_delta )+ {+ dim->scale_mult = y_scale;+ dim->scale_delta = y_delta;++ psh_globals_scale_widths( globals, 1 );+ psh_blues_scale_zones( &globals->blues, y_scale, y_delta );+ }++ return 0;+ }+++ FT_LOCAL_DEF( void )+ psh_globals_funcs_init( PSH_Globals_FuncsRec* funcs )+ {+ funcs->create = psh_globals_new;+ funcs->set_scale = psh_globals_set_scale;+ funcs->destroy = psh_globals_destroy;+ }+++/* END */
+ src/pshinter/pshglob.h view
@@ -0,0 +1,196 @@+/***************************************************************************/+/* */+/* pshglob.h */+/* */+/* PostScript hinter global hinting management. */+/* */+/* Copyright 2001, 2002, 2003 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 __PSHGLOB_H__+#define __PSHGLOB_H__+++#include FT_FREETYPE_H+#include FT_INTERNAL_POSTSCRIPT_HINTS_H+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** GLOBAL HINTS INTERNALS *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* @constant: */+ /* PS_GLOBALS_MAX_BLUE_ZONES */+ /* */+ /* @description: */+ /* The maximum number of blue zones in a font global hints structure. */+ /* See @PS_Globals_BluesRec. */+ /* */+#define PS_GLOBALS_MAX_BLUE_ZONES 16+++ /*************************************************************************/+ /* */+ /* @constant: */+ /* PS_GLOBALS_MAX_STD_WIDTHS */+ /* */+ /* @description: */+ /* The maximum number of standard and snap widths in either the */+ /* horizontal or vertical direction. See @PS_Globals_WidthsRec. */+ /* */+#define PS_GLOBALS_MAX_STD_WIDTHS 16+++ /* standard and snap width */+ typedef struct PSH_WidthRec_+ {+ FT_Int org;+ FT_Pos cur;+ FT_Pos fit;++ } PSH_WidthRec, *PSH_Width;+++ /* standard and snap widths table */+ typedef struct PSH_WidthsRec_+ {+ FT_UInt count;+ PSH_WidthRec widths[PS_GLOBALS_MAX_STD_WIDTHS];++ } PSH_WidthsRec, *PSH_Widths;+++ typedef struct PSH_DimensionRec_+ {+ PSH_WidthsRec stdw;+ FT_Fixed scale_mult;+ FT_Fixed scale_delta;++ } PSH_DimensionRec, *PSH_Dimension;+++ /* blue zone descriptor */+ typedef struct PSH_Blue_ZoneRec_+ {+ FT_Int org_ref;+ FT_Int org_delta;+ FT_Int org_top;+ FT_Int org_bottom;++ FT_Pos cur_ref;+ FT_Pos cur_delta;+ FT_Pos cur_bottom;+ FT_Pos cur_top;++ } PSH_Blue_ZoneRec, *PSH_Blue_Zone;+++ typedef struct PSH_Blue_TableRec_+ {+ FT_UInt count;+ PSH_Blue_ZoneRec zones[PS_GLOBALS_MAX_BLUE_ZONES];++ } PSH_Blue_TableRec, *PSH_Blue_Table;+++ /* blue zones table */+ typedef struct PSH_BluesRec_+ {+ PSH_Blue_TableRec normal_top;+ PSH_Blue_TableRec normal_bottom;+ PSH_Blue_TableRec family_top;+ PSH_Blue_TableRec family_bottom;++ FT_Fixed blue_scale;+ FT_Int blue_shift;+ FT_Int blue_threshold;+ FT_Int blue_fuzz;+ FT_Bool no_overshoots;++ } PSH_BluesRec, *PSH_Blues;+++ /* font globals. */+ /* dimension 0 => X coordinates + vertical hints/stems */+ /* dimension 1 => Y coordinates + horizontal hints/stems */+ typedef struct PSH_GlobalsRec_+ {+ FT_Memory memory;+ PSH_DimensionRec dimension[2];+ PSH_BluesRec blues;++ } PSH_GlobalsRec;+++#define PSH_BLUE_ALIGN_NONE 0+#define PSH_BLUE_ALIGN_TOP 1+#define PSH_BLUE_ALIGN_BOT 2+++ typedef struct PSH_AlignmentRec_+ {+ int align;+ FT_Pos align_top;+ FT_Pos align_bot;++ } PSH_AlignmentRec, *PSH_Alignment;+++ FT_LOCAL( void )+ psh_globals_funcs_init( PSH_Globals_FuncsRec* funcs );+++#if 0+ /* snap a stem width to fitter coordinates. `org_width' is in font */+ /* units. The result is in device pixels (26.6 format). */+ FT_LOCAL( FT_Pos )+ psh_dimension_snap_width( PSH_Dimension dimension,+ FT_Int org_width );+#endif++ FT_LOCAL( FT_Error )+ psh_globals_set_scale( PSH_Globals globals,+ FT_Fixed x_scale,+ FT_Fixed y_scale,+ FT_Fixed x_delta,+ FT_Fixed y_delta );++ /* snap a stem to one or two blue zones */+ FT_LOCAL( void )+ psh_blues_snap_stem( PSH_Blues blues,+ FT_Int stem_top,+ FT_Int stem_bot,+ PSH_Alignment alignment );+ /* */++#ifdef DEBUG_HINTER+ extern PSH_Globals ps_debug_globals;+#endif+++FT_END_HEADER+++#endif /* __PSHGLOB_H__ */+++/* END */
+ src/pshinter/pshinter.c view
@@ -0,0 +1,29 @@+/***************************************************************************/+/* */+/* pshinter.c */+/* */+/* FreeType PostScript Hinting module */+/* */+/* Copyright 2001, 2003 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 "pshpic.c"+#include "pshrec.c"+#include "pshglob.c"+#include "pshalgo.c"+#include "pshmod.c"+++/* END */
+ src/pshinter/pshmod.c view
@@ -0,0 +1,118 @@+/***************************************************************************/+/* */+/* pshmod.c */+/* */+/* FreeType PostScript hinter module implementation (body). */+/* */+/* Copyright 2001, 2002, 2007 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_OBJECTS_H+#include "pshrec.h"+#include "pshalgo.h"+#include "pshpic.h"+++ /* the Postscript Hinter module structure */+ typedef struct PS_Hinter_Module_Rec_+ {+ FT_ModuleRec root;+ PS_HintsRec ps_hints;++ PSH_Globals_FuncsRec globals_funcs;+ T1_Hints_FuncsRec t1_funcs;+ T2_Hints_FuncsRec t2_funcs;++ } PS_Hinter_ModuleRec, *PS_Hinter_Module;+++ /* finalize module */+ FT_CALLBACK_DEF( void )+ ps_hinter_done( PS_Hinter_Module module )+ {+ module->t1_funcs.hints = NULL;+ module->t2_funcs.hints = NULL;++ ps_hints_done( &module->ps_hints );+ }+++ /* initialize module, create hints recorder and the interface */+ FT_CALLBACK_DEF( FT_Error )+ ps_hinter_init( PS_Hinter_Module module )+ {+ FT_Memory memory = module->root.memory;+ void* ph = &module->ps_hints;+++ ps_hints_init( &module->ps_hints, memory );++ psh_globals_funcs_init( &module->globals_funcs );++ t1_hints_funcs_init( &module->t1_funcs );+ module->t1_funcs.hints = (T1_Hints)ph;++ t2_hints_funcs_init( &module->t2_funcs );+ module->t2_funcs.hints = (T2_Hints)ph;++ return 0;+ }+++ /* returns global hints interface */+ FT_CALLBACK_DEF( PSH_Globals_Funcs )+ pshinter_get_globals_funcs( FT_Module module )+ {+ return &((PS_Hinter_Module)module)->globals_funcs;+ }+++ /* return Type 1 hints interface */+ FT_CALLBACK_DEF( T1_Hints_Funcs )+ pshinter_get_t1_funcs( FT_Module module )+ {+ return &((PS_Hinter_Module)module)->t1_funcs;+ }+++ /* return Type 2 hints interface */+ FT_CALLBACK_DEF( T2_Hints_Funcs )+ pshinter_get_t2_funcs( FT_Module module )+ {+ return &((PS_Hinter_Module)module)->t2_funcs;+ }+++ FT_DEFINE_PSHINTER_INTERFACE(pshinter_interface,+ pshinter_get_globals_funcs,+ pshinter_get_t1_funcs,+ pshinter_get_t2_funcs+ )+++ FT_DEFINE_MODULE(pshinter_module_class,++ 0,+ sizeof ( PS_Hinter_ModuleRec ),+ "pshinter",+ 0x10000L,+ 0x20000L,++ &FTPSHINTER_INTERFACE_GET, /* module-specific interface */++ (FT_Module_Constructor)ps_hinter_init,+ (FT_Module_Destructor) ps_hinter_done,+ (FT_Module_Requester) 0 /* no additional interface for now */+ )++/* END */
+ src/pshinter/pshmod.h view
@@ -0,0 +1,39 @@+/***************************************************************************/+/* */+/* pshmod.h */+/* */+/* PostScript hinter module interface (specification). */+/* */+/* Copyright 2001 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 __PSHMOD_H__+#define __PSHMOD_H__+++#include <ft2build.h>+#include FT_MODULE_H+++FT_BEGIN_HEADER+++ FT_DECLARE_MODULE( pshinter_module_class )+++FT_END_HEADER+++#endif /* __PSHMOD_H__ */+++/* END */
+ src/pshinter/pshnterr.h view
@@ -0,0 +1,40 @@+/***************************************************************************/+/* */+/* pshnterr.h */+/* */+/* PS Hinter error codes (specification only). */+/* */+/* Copyright 2003 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 PSHinter error enumeration constants. */+ /* */+ /*************************************************************************/++#ifndef __PSHNTERR_H__+#define __PSHNTERR_H__++#include FT_MODULE_ERRORS_H++#undef __FTERRORS_H__++#define FT_ERR_PREFIX PSH_Err_+#define FT_ERR_BASE FT_Mod_Err_PShinter++#include FT_ERRORS_H++#endif /* __PSHNTERR_H__ */+++/* END */
+ src/pshinter/pshpic.c view
@@ -0,0 +1,69 @@+/***************************************************************************/+/* */+/* pshpic.c */+/* */+/* The FreeType position independent code services for pshinter module. */+/* */+/* Copyright 2009, 2010 by */+/* Oran Agra and Mickey Gabel. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#include <ft2build.h>+#include FT_FREETYPE_H+#include FT_INTERNAL_OBJECTS_H+#include "pshpic.h"++#ifdef FT_CONFIG_OPTION_PIC++ /* forward declaration of PIC init functions from pshmod.c */+ void FT_Init_Class_pshinter_interface( FT_Library, PSHinter_Interface*);++ void+ pshinter_module_class_pic_free( FT_Library library )+ {+ FT_PIC_Container* pic_container = &library->pic_container;+ FT_Memory memory = library->memory;+ if ( pic_container->pshinter )+ {+ FT_FREE( pic_container->pshinter );+ pic_container->pshinter = NULL;+ }+ }+++ FT_Error+ pshinter_module_class_pic_init( FT_Library library )+ {+ FT_PIC_Container* pic_container = &library->pic_container;+ FT_Error error = PSH_Err_Ok;+ PSHinterPIC* container;+ FT_Memory memory = library->memory;+++ /* allocate pointer, clear and set global container pointer */+ if ( FT_ALLOC ( container, sizeof ( *container ) ) )+ return error;+ FT_MEM_SET( container, 0, sizeof ( *container ) );+ pic_container->pshinter = container;+ + /* add call to initialization function when you add new scripts */+ FT_Init_Class_pshinter_interface(library, &container->pshinter_interface);++/*Exit:*/+ if(error)+ pshinter_module_class_pic_free(library);+ return error;+ }+++#endif /* FT_CONFIG_OPTION_PIC */++/* END */
+ src/pshinter/pshpic.h view
@@ -0,0 +1,53 @@+/***************************************************************************/+/* */+/* pshpic.h */+/* */+/* The FreeType position independent code services for pshinter module. */+/* */+/* Copyright 2009 by */+/* Oran Agra and Mickey Gabel. */+/* */+/* 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 __PSHPIC_H__+#define __PSHPIC_H__++ +FT_BEGIN_HEADER++#include FT_INTERNAL_PIC_H++#ifndef FT_CONFIG_OPTION_PIC++#define FTPSHINTER_INTERFACE_GET pshinter_interface++#else /* FT_CONFIG_OPTION_PIC */++#include FT_INTERNAL_POSTSCRIPT_HINTS_H++ typedef struct PSHinterPIC_+ {+ PSHinter_Interface pshinter_interface;+ } PSHinterPIC;++#define GET_PIC(lib) ((PSHinterPIC*)((lib)->pic_container.autofit))+#define FTPSHINTER_INTERFACE_GET (GET_PIC(library)->pshinter_interface)+++#endif /* FT_CONFIG_OPTION_PIC */++ /* */++FT_END_HEADER++#endif /* __PSHPIC_H__ */+++/* END */
+ src/pshinter/pshrec.c view
@@ -0,0 +1,1224 @@+/***************************************************************************/+/* */+/* pshrec.c */+/* */+/* FreeType PostScript hints recorder (body). */+/* */+/* Copyright 2001, 2002, 2003, 2004, 2007, 2009 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#include <ft2build.h>+#include FT_FREETYPE_H+#include FT_INTERNAL_OBJECTS_H+#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_CALC_H++#include "pshrec.h"+#include "pshalgo.h"++#include "pshnterr.h"++#undef FT_COMPONENT+#define FT_COMPONENT trace_pshrec++#ifdef DEBUG_HINTER+ PS_Hints ps_debug_hints = 0;+ int ps_debug_no_horz_hints = 0;+ int ps_debug_no_vert_hints = 0;+#endif+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** PS_HINT MANAGEMENT *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /* destroy hints table */+ static void+ ps_hint_table_done( PS_Hint_Table table,+ FT_Memory memory )+ {+ FT_FREE( table->hints );+ table->num_hints = 0;+ table->max_hints = 0;+ }+++ /* ensure that a table can contain "count" elements */+ static FT_Error+ ps_hint_table_ensure( PS_Hint_Table table,+ FT_UInt count,+ FT_Memory memory )+ {+ FT_UInt old_max = table->max_hints;+ FT_UInt new_max = count;+ FT_Error error = PSH_Err_Ok;+++ if ( new_max > old_max )+ {+ /* try to grow the table */+ new_max = FT_PAD_CEIL( new_max, 8 );+ if ( !FT_RENEW_ARRAY( table->hints, old_max, new_max ) )+ table->max_hints = new_max;+ }+ return error;+ }+++ static FT_Error+ ps_hint_table_alloc( PS_Hint_Table table,+ FT_Memory memory,+ PS_Hint *ahint )+ {+ FT_Error error = PSH_Err_Ok;+ FT_UInt count;+ PS_Hint hint = 0;+++ count = table->num_hints;+ count++;++ if ( count >= table->max_hints )+ {+ error = ps_hint_table_ensure( table, count, memory );+ if ( error )+ goto Exit;+ }++ hint = table->hints + count - 1;+ hint->pos = 0;+ hint->len = 0;+ hint->flags = 0;++ table->num_hints = count;++ Exit:+ *ahint = hint;+ return error;+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** PS_MASK MANAGEMENT *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /* destroy mask */+ static void+ ps_mask_done( PS_Mask mask,+ FT_Memory memory )+ {+ FT_FREE( mask->bytes );+ mask->num_bits = 0;+ mask->max_bits = 0;+ mask->end_point = 0;+ }+++ /* ensure that a mask can contain "count" bits */+ static FT_Error+ ps_mask_ensure( PS_Mask mask,+ FT_UInt count,+ FT_Memory memory )+ {+ FT_UInt old_max = ( mask->max_bits + 7 ) >> 3;+ FT_UInt new_max = ( count + 7 ) >> 3;+ FT_Error error = PSH_Err_Ok;+++ if ( new_max > old_max )+ {+ new_max = FT_PAD_CEIL( new_max, 8 );+ if ( !FT_RENEW_ARRAY( mask->bytes, old_max, new_max ) )+ mask->max_bits = new_max * 8;+ }+ return error;+ }+++ /* test a bit value in a given mask */+ static FT_Int+ ps_mask_test_bit( PS_Mask mask,+ FT_Int idx )+ {+ if ( (FT_UInt)idx >= mask->num_bits )+ return 0;++ return mask->bytes[idx >> 3] & ( 0x80 >> ( idx & 7 ) );+ }+++ /* clear a given bit */+ static void+ ps_mask_clear_bit( PS_Mask mask,+ FT_Int idx )+ {+ FT_Byte* p;+++ if ( (FT_UInt)idx >= mask->num_bits )+ return;++ p = mask->bytes + ( idx >> 3 );+ p[0] = (FT_Byte)( p[0] & ~( 0x80 >> ( idx & 7 ) ) );+ }+++ /* set a given bit, possibly grow the mask */+ static FT_Error+ ps_mask_set_bit( PS_Mask mask,+ FT_Int idx,+ FT_Memory memory )+ {+ FT_Error error = PSH_Err_Ok;+ FT_Byte* p;+++ if ( idx < 0 )+ goto Exit;++ if ( (FT_UInt)idx >= mask->num_bits )+ {+ error = ps_mask_ensure( mask, idx + 1, memory );+ if ( error )+ goto Exit;++ mask->num_bits = idx + 1;+ }++ p = mask->bytes + ( idx >> 3 );+ p[0] = (FT_Byte)( p[0] | ( 0x80 >> ( idx & 7 ) ) );++ Exit:+ return error;+ }+++ /* destroy mask table */+ static void+ ps_mask_table_done( PS_Mask_Table table,+ FT_Memory memory )+ {+ FT_UInt count = table->max_masks;+ PS_Mask mask = table->masks;+++ for ( ; count > 0; count--, mask++ )+ ps_mask_done( mask, memory );++ FT_FREE( table->masks );+ table->num_masks = 0;+ table->max_masks = 0;+ }+++ /* ensure that a mask table can contain "count" masks */+ static FT_Error+ ps_mask_table_ensure( PS_Mask_Table table,+ FT_UInt count,+ FT_Memory memory )+ {+ FT_UInt old_max = table->max_masks;+ FT_UInt new_max = count;+ FT_Error error = PSH_Err_Ok;+++ if ( new_max > old_max )+ {+ new_max = FT_PAD_CEIL( new_max, 8 );+ if ( !FT_RENEW_ARRAY( table->masks, old_max, new_max ) )+ table->max_masks = new_max;+ }+ return error;+ }+++ /* allocate a new mask in a table */+ static FT_Error+ ps_mask_table_alloc( PS_Mask_Table table,+ FT_Memory memory,+ PS_Mask *amask )+ {+ FT_UInt count;+ FT_Error error = PSH_Err_Ok;+ PS_Mask mask = 0;+++ count = table->num_masks;+ count++;++ if ( count > table->max_masks )+ {+ error = ps_mask_table_ensure( table, count, memory );+ if ( error )+ goto Exit;+ }++ mask = table->masks + count - 1;+ mask->num_bits = 0;+ mask->end_point = 0;+ table->num_masks = count;++ Exit:+ *amask = mask;+ return error;+ }+++ /* return last hint mask in a table, create one if the table is empty */+ static FT_Error+ ps_mask_table_last( PS_Mask_Table table,+ FT_Memory memory,+ PS_Mask *amask )+ {+ FT_Error error = PSH_Err_Ok;+ FT_UInt count;+ PS_Mask mask;+++ count = table->num_masks;+ if ( count == 0 )+ {+ error = ps_mask_table_alloc( table, memory, &mask );+ if ( error )+ goto Exit;+ }+ else+ mask = table->masks + count - 1;++ Exit:+ *amask = mask;+ return error;+ }+++ /* set a new mask to a given bit range */+ static FT_Error+ ps_mask_table_set_bits( PS_Mask_Table table,+ const FT_Byte* source,+ FT_UInt bit_pos,+ FT_UInt bit_count,+ FT_Memory memory )+ {+ FT_Error error = PSH_Err_Ok;+ PS_Mask mask;+++ error = ps_mask_table_last( table, memory, &mask );+ if ( error )+ goto Exit;++ error = ps_mask_ensure( mask, bit_count, memory );+ if ( error )+ goto Exit;++ mask->num_bits = bit_count;++ /* now, copy bits */+ {+ FT_Byte* read = (FT_Byte*)source + ( bit_pos >> 3 );+ FT_Int rmask = 0x80 >> ( bit_pos & 7 );+ FT_Byte* write = mask->bytes;+ FT_Int wmask = 0x80;+ FT_Int val;+++ for ( ; bit_count > 0; bit_count-- )+ {+ val = write[0] & ~wmask;++ if ( read[0] & rmask )+ val |= wmask;++ write[0] = (FT_Byte)val;++ rmask >>= 1;+ if ( rmask == 0 )+ {+ read++;+ rmask = 0x80;+ }++ wmask >>= 1;+ if ( wmask == 0 )+ {+ write++;+ wmask = 0x80;+ }+ }+ }++ Exit:+ return error;+ }+++ /* test whether two masks in a table intersect */+ static FT_Int+ ps_mask_table_test_intersect( PS_Mask_Table table,+ FT_Int index1,+ FT_Int index2 )+ {+ PS_Mask mask1 = table->masks + index1;+ PS_Mask mask2 = table->masks + index2;+ FT_Byte* p1 = mask1->bytes;+ FT_Byte* p2 = mask2->bytes;+ FT_UInt count1 = mask1->num_bits;+ FT_UInt count2 = mask2->num_bits;+ FT_UInt count;+++ count = ( count1 <= count2 ) ? count1 : count2;+ for ( ; count >= 8; count -= 8 )+ {+ if ( p1[0] & p2[0] )+ return 1;++ p1++;+ p2++;+ }++ if ( count == 0 )+ return 0;++ return ( p1[0] & p2[0] ) & ~( 0xFF >> count );+ }+++ /* merge two masks, used by ps_mask_table_merge_all */+ static FT_Error+ ps_mask_table_merge( PS_Mask_Table table,+ FT_Int index1,+ FT_Int index2,+ FT_Memory memory )+ {+ FT_UInt temp;+ FT_Error error = PSH_Err_Ok;+++ /* swap index1 and index2 so that index1 < index2 */+ if ( index1 > index2 )+ {+ temp = index1;+ index1 = index2;+ index2 = temp;+ }++ if ( index1 < index2 && index1 >= 0 && index2 < (FT_Int)table->num_masks )+ {+ /* we need to merge the bitsets of index1 and index2 with a */+ /* simple union */+ PS_Mask mask1 = table->masks + index1;+ PS_Mask mask2 = table->masks + index2;+ FT_UInt count1 = mask1->num_bits;+ FT_UInt count2 = mask2->num_bits;+ FT_Int delta;+++ if ( count2 > 0 )+ {+ FT_UInt pos;+ FT_Byte* read;+ FT_Byte* write;+++ /* if "count2" is greater than "count1", we need to grow the */+ /* first bitset, and clear the highest bits */+ if ( count2 > count1 )+ {+ error = ps_mask_ensure( mask1, count2, memory );+ if ( error )+ goto Exit;++ for ( pos = count1; pos < count2; pos++ )+ ps_mask_clear_bit( mask1, pos );+ }++ /* merge (unite) the bitsets */+ read = mask2->bytes;+ write = mask1->bytes;+ pos = (FT_UInt)( ( count2 + 7 ) >> 3 );++ for ( ; pos > 0; pos-- )+ {+ write[0] = (FT_Byte)( write[0] | read[0] );+ write++;+ read++;+ }+ }++ /* Now, remove "mask2" from the list. We need to keep the masks */+ /* sorted in order of importance, so move table elements. */+ mask2->num_bits = 0;+ mask2->end_point = 0;++ delta = table->num_masks - 1 - index2; /* number of masks to move */+ if ( delta > 0 )+ {+ /* move to end of table for reuse */+ PS_MaskRec dummy = *mask2;+++ ft_memmove( mask2, mask2 + 1, delta * sizeof ( PS_MaskRec ) );++ mask2[delta] = dummy;+ }++ table->num_masks--;+ }+ else+ FT_TRACE0(( "ps_mask_table_merge: ignoring invalid indices (%d,%d)\n",+ index1, index2 ));++ Exit:+ return error;+ }+++ /* Try to merge all masks in a given table. This is used to merge */+ /* all counter masks into independent counter "paths". */+ /* */+ static FT_Error+ ps_mask_table_merge_all( PS_Mask_Table table,+ FT_Memory memory )+ {+ FT_Int index1, index2;+ FT_Error error = PSH_Err_Ok;+++ for ( index1 = table->num_masks - 1; index1 > 0; index1-- )+ {+ for ( index2 = index1 - 1; index2 >= 0; index2-- )+ {+ if ( ps_mask_table_test_intersect( table, index1, index2 ) )+ {+ error = ps_mask_table_merge( table, index2, index1, memory );+ if ( error )+ goto Exit;++ break;+ }+ }+ }++ Exit:+ return error;+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** PS_DIMENSION MANAGEMENT *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+++ /* finalize a given dimension */+ static void+ ps_dimension_done( PS_Dimension dimension,+ FT_Memory memory )+ {+ ps_mask_table_done( &dimension->counters, memory );+ ps_mask_table_done( &dimension->masks, memory );+ ps_hint_table_done( &dimension->hints, memory );+ }+++ /* initialize a given dimension */+ static void+ ps_dimension_init( PS_Dimension dimension )+ {+ dimension->hints.num_hints = 0;+ dimension->masks.num_masks = 0;+ dimension->counters.num_masks = 0;+ }+++#if 0++ /* set a bit at a given index in the current hint mask */+ static FT_Error+ ps_dimension_set_mask_bit( PS_Dimension dim,+ FT_UInt idx,+ FT_Memory memory )+ {+ PS_Mask mask;+ FT_Error error = PSH_Err_Ok;+++ /* get last hint mask */+ error = ps_mask_table_last( &dim->masks, memory, &mask );+ if ( error )+ goto Exit;++ error = ps_mask_set_bit( mask, idx, memory );++ Exit:+ return error;+ }++#endif++ /* set the end point in a mask, called from "End" & "Reset" methods */+ static void+ ps_dimension_end_mask( PS_Dimension dim,+ FT_UInt end_point )+ {+ FT_UInt count = dim->masks.num_masks;+ PS_Mask mask;+++ if ( count > 0 )+ {+ mask = dim->masks.masks + count - 1;+ mask->end_point = end_point;+ }+ }+++ /* set the end point in the current mask, then create a new empty one */+ /* (called by "Reset" method) */+ static FT_Error+ ps_dimension_reset_mask( PS_Dimension dim,+ FT_UInt end_point,+ FT_Memory memory )+ {+ PS_Mask mask;+++ /* end current mask */+ ps_dimension_end_mask( dim, end_point );++ /* allocate new one */+ return ps_mask_table_alloc( &dim->masks, memory, &mask );+ }+++ /* set a new mask, called from the "T2Stem" method */+ static FT_Error+ ps_dimension_set_mask_bits( PS_Dimension dim,+ const FT_Byte* source,+ FT_UInt source_pos,+ FT_UInt source_bits,+ FT_UInt end_point,+ FT_Memory memory )+ {+ FT_Error error = PSH_Err_Ok;+++ /* reset current mask, if any */+ error = ps_dimension_reset_mask( dim, end_point, memory );+ if ( error )+ goto Exit;++ /* set bits in new mask */+ error = ps_mask_table_set_bits( &dim->masks, source,+ source_pos, source_bits, memory );++ Exit:+ return error;+ }+++ /* add a new single stem (called from "T1Stem" method) */+ static FT_Error+ ps_dimension_add_t1stem( PS_Dimension dim,+ FT_Int pos,+ FT_Int len,+ FT_Memory memory,+ FT_Int *aindex )+ {+ FT_Error error = PSH_Err_Ok;+ FT_UInt flags = 0;+++ /* detect ghost stem */+ if ( len < 0 )+ {+ flags |= PS_HINT_FLAG_GHOST;+ if ( len == -21 )+ {+ flags |= PS_HINT_FLAG_BOTTOM;+ pos += len;+ }+ len = 0;+ }++ if ( aindex )+ *aindex = -1;++ /* now, lookup stem in the current hints table */+ {+ PS_Mask mask;+ FT_UInt idx;+ FT_UInt max = dim->hints.num_hints;+ PS_Hint hint = dim->hints.hints;+++ for ( idx = 0; idx < max; idx++, hint++ )+ {+ if ( hint->pos == pos && hint->len == len )+ break;+ }++ /* we need to create a new hint in the table */+ if ( idx >= max )+ {+ error = ps_hint_table_alloc( &dim->hints, memory, &hint );+ if ( error )+ goto Exit;++ hint->pos = pos;+ hint->len = len;+ hint->flags = flags;+ }++ /* now, store the hint in the current mask */+ error = ps_mask_table_last( &dim->masks, memory, &mask );+ if ( error )+ goto Exit;++ error = ps_mask_set_bit( mask, idx, memory );+ if ( error )+ goto Exit;++ if ( aindex )+ *aindex = (FT_Int)idx;+ }++ Exit:+ return error;+ }+++ /* add a "hstem3/vstem3" counter to our dimension table */+ static FT_Error+ ps_dimension_add_counter( PS_Dimension dim,+ FT_Int hint1,+ FT_Int hint2,+ FT_Int hint3,+ FT_Memory memory )+ {+ FT_Error error = PSH_Err_Ok;+ FT_UInt count = dim->counters.num_masks;+ PS_Mask counter = dim->counters.masks;+++ /* try to find an existing counter mask that already uses */+ /* one of these stems here */+ for ( ; count > 0; count--, counter++ )+ {+ if ( ps_mask_test_bit( counter, hint1 ) ||+ ps_mask_test_bit( counter, hint2 ) ||+ ps_mask_test_bit( counter, hint3 ) )+ break;+ }++ /* create a new counter when needed */+ if ( count == 0 )+ {+ error = ps_mask_table_alloc( &dim->counters, memory, &counter );+ if ( error )+ goto Exit;+ }++ /* now, set the bits for our hints in the counter mask */+ error = ps_mask_set_bit( counter, hint1, memory );+ if ( error )+ goto Exit;++ error = ps_mask_set_bit( counter, hint2, memory );+ if ( error )+ goto Exit;++ error = ps_mask_set_bit( counter, hint3, memory );+ if ( error )+ goto Exit;++ Exit:+ return error;+ }+++ /* end of recording session for a given dimension */+ static FT_Error+ ps_dimension_end( PS_Dimension dim,+ FT_UInt end_point,+ FT_Memory memory )+ {+ /* end hint mask table */+ ps_dimension_end_mask( dim, end_point );++ /* merge all counter masks into independent "paths" */+ return ps_mask_table_merge_all( &dim->counters, memory );+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** PS_RECORDER MANAGEMENT *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+++ /* destroy hints */+ FT_LOCAL( void )+ ps_hints_done( PS_Hints hints )+ {+ FT_Memory memory = hints->memory;+++ ps_dimension_done( &hints->dimension[0], memory );+ ps_dimension_done( &hints->dimension[1], memory );++ hints->error = PSH_Err_Ok;+ hints->memory = 0;+ }+++ FT_LOCAL( FT_Error )+ ps_hints_init( PS_Hints hints,+ FT_Memory memory )+ {+ FT_MEM_ZERO( hints, sizeof ( *hints ) );+ hints->memory = memory;+ return PSH_Err_Ok;+ }+++ /* initialize a hints for a new session */+ static void+ ps_hints_open( PS_Hints hints,+ PS_Hint_Type hint_type )+ {+ switch ( hint_type )+ {+ case PS_HINT_TYPE_1:+ case PS_HINT_TYPE_2:+ hints->error = PSH_Err_Ok;+ hints->hint_type = hint_type;++ ps_dimension_init( &hints->dimension[0] );+ ps_dimension_init( &hints->dimension[1] );+ break;++ default:+ hints->error = PSH_Err_Invalid_Argument;+ hints->hint_type = hint_type;++ FT_TRACE0(( "ps_hints_open: invalid charstring type\n" ));+ break;+ }+ }+++ /* add one or more stems to the current hints table */+ static void+ ps_hints_stem( PS_Hints hints,+ FT_Int dimension,+ FT_UInt count,+ FT_Long* stems )+ {+ if ( !hints->error )+ {+ /* limit "dimension" to 0..1 */+ if ( dimension < 0 || dimension > 1 )+ {+ FT_TRACE0(( "ps_hints_stem: invalid dimension (%d) used\n",+ dimension ));+ dimension = ( dimension != 0 );+ }++ /* record the stems in the current hints/masks table */+ switch ( hints->hint_type )+ {+ case PS_HINT_TYPE_1: /* Type 1 "hstem" or "vstem" operator */+ case PS_HINT_TYPE_2: /* Type 2 "hstem" or "vstem" operator */+ {+ PS_Dimension dim = &hints->dimension[dimension];+++ for ( ; count > 0; count--, stems += 2 )+ {+ FT_Error error;+ FT_Memory memory = hints->memory;+++ error = ps_dimension_add_t1stem(+ dim, (FT_Int)stems[0], (FT_Int)stems[1],+ memory, NULL );+ if ( error )+ {+ FT_ERROR(( "ps_hints_stem: could not add stem"+ " (%d,%d) to hints table\n", stems[0], stems[1] ));++ hints->error = error;+ return;+ }+ }+ break;+ }++ default:+ FT_TRACE0(( "ps_hints_stem: called with invalid hint type (%d)\n",+ hints->hint_type ));+ break;+ }+ }+ }+++ /* add one Type1 counter stem to the current hints table */+ static void+ ps_hints_t1stem3( PS_Hints hints,+ FT_Int dimension,+ FT_Fixed* stems )+ {+ FT_Error error = PSH_Err_Ok;+++ if ( !hints->error )+ {+ PS_Dimension dim;+ FT_Memory memory = hints->memory;+ FT_Int count;+ FT_Int idx[3];+++ /* limit "dimension" to 0..1 */+ if ( dimension < 0 || dimension > 1 )+ {+ FT_TRACE0(( "ps_hints_t1stem3: invalid dimension (%d) used\n",+ dimension ));+ dimension = ( dimension != 0 );+ }++ dim = &hints->dimension[dimension];++ /* there must be 6 elements in the 'stem' array */+ if ( hints->hint_type == PS_HINT_TYPE_1 )+ {+ /* add the three stems to our hints/masks table */+ for ( count = 0; count < 3; count++, stems += 2 )+ {+ error = ps_dimension_add_t1stem( dim,+ (FT_Int)FIXED_TO_INT( stems[0] ),+ (FT_Int)FIXED_TO_INT( stems[1] ),+ memory, &idx[count] );+ if ( error )+ goto Fail;+ }++ /* now, add the hints to the counters table */+ error = ps_dimension_add_counter( dim, idx[0], idx[1], idx[2],+ memory );+ if ( error )+ goto Fail;+ }+ else+ {+ FT_ERROR(( "ps_hints_t1stem3: called with invalid hint type\n" ));+ error = PSH_Err_Invalid_Argument;+ goto Fail;+ }+ }++ return;++ Fail:+ FT_ERROR(( "ps_hints_t1stem3: could not add counter stems to table\n" ));+ hints->error = error;+ }+++ /* reset hints (only with Type 1 hints) */+ static void+ ps_hints_t1reset( PS_Hints hints,+ FT_UInt end_point )+ {+ FT_Error error = PSH_Err_Ok;+++ if ( !hints->error )+ {+ FT_Memory memory = hints->memory;+++ if ( hints->hint_type == PS_HINT_TYPE_1 )+ {+ error = ps_dimension_reset_mask( &hints->dimension[0],+ end_point, memory );+ if ( error )+ goto Fail;++ error = ps_dimension_reset_mask( &hints->dimension[1],+ end_point, memory );+ if ( error )+ goto Fail;+ }+ else+ {+ /* invalid hint type */+ error = PSH_Err_Invalid_Argument;+ goto Fail;+ }+ }+ return;++ Fail:+ hints->error = error;+ }+++ /* Type2 "hintmask" operator, add a new hintmask to each direction */+ static void+ ps_hints_t2mask( PS_Hints hints,+ FT_UInt end_point,+ FT_UInt bit_count,+ const FT_Byte* bytes )+ {+ FT_Error error;+++ if ( !hints->error )+ {+ PS_Dimension dim = hints->dimension;+ FT_Memory memory = hints->memory;+ FT_UInt count1 = dim[0].hints.num_hints;+ FT_UInt count2 = dim[1].hints.num_hints;+++ /* check bit count; must be equal to current total hint count */+ if ( bit_count != count1 + count2 )+ {+ FT_TRACE0(( "ps_hints_t2mask:"+ " called with invalid bitcount %d (instead of %d)\n",+ bit_count, count1 + count2 ));++ /* simply ignore the operator */+ return;+ }++ /* set-up new horizontal and vertical hint mask now */+ error = ps_dimension_set_mask_bits( &dim[0], bytes, count2, count1,+ end_point, memory );+ if ( error )+ goto Fail;++ error = ps_dimension_set_mask_bits( &dim[1], bytes, 0, count2,+ end_point, memory );+ if ( error )+ goto Fail;+ }+ return;++ Fail:+ hints->error = error;+ }+++ static void+ ps_hints_t2counter( PS_Hints hints,+ FT_UInt bit_count,+ const FT_Byte* bytes )+ {+ FT_Error error;+++ if ( !hints->error )+ {+ PS_Dimension dim = hints->dimension;+ FT_Memory memory = hints->memory;+ FT_UInt count1 = dim[0].hints.num_hints;+ FT_UInt count2 = dim[1].hints.num_hints;+++ /* check bit count, must be equal to current total hint count */+ if ( bit_count != count1 + count2 )+ {+ FT_TRACE0(( "ps_hints_t2counter:"+ " called with invalid bitcount %d (instead of %d)\n",+ bit_count, count1 + count2 ));++ /* simply ignore the operator */+ return;+ }++ /* set-up new horizontal and vertical hint mask now */+ error = ps_dimension_set_mask_bits( &dim[0], bytes, 0, count1,+ 0, memory );+ if ( error )+ goto Fail;++ error = ps_dimension_set_mask_bits( &dim[1], bytes, count1, count2,+ 0, memory );+ if ( error )+ goto Fail;+ }+ return;++ Fail:+ hints->error = error;+ }+++ /* end recording session */+ static FT_Error+ ps_hints_close( PS_Hints hints,+ FT_UInt end_point )+ {+ FT_Error error;+++ error = hints->error;+ if ( !error )+ {+ FT_Memory memory = hints->memory;+ PS_Dimension dim = hints->dimension;+++ error = ps_dimension_end( &dim[0], end_point, memory );+ if ( !error )+ {+ error = ps_dimension_end( &dim[1], end_point, memory );+ }+ }++#ifdef DEBUG_HINTER+ if ( !error )+ ps_debug_hints = hints;+#endif+ return error;+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** TYPE 1 HINTS RECORDING INTERFACE *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ static void+ t1_hints_open( T1_Hints hints )+ {+ ps_hints_open( (PS_Hints)hints, PS_HINT_TYPE_1 );+ }++ static void+ t1_hints_stem( T1_Hints hints,+ FT_Int dimension,+ FT_Fixed* coords )+ {+ FT_Pos stems[2];+++ stems[0] = FIXED_TO_INT( coords[0] );+ stems[1] = FIXED_TO_INT( coords[1] );++ ps_hints_stem( (PS_Hints)hints, dimension, 1, stems );+ }+++ FT_LOCAL_DEF( void )+ t1_hints_funcs_init( T1_Hints_FuncsRec* funcs )+ {+ FT_MEM_ZERO( (char*)funcs, sizeof ( *funcs ) );++ funcs->open = (T1_Hints_OpenFunc) t1_hints_open;+ funcs->close = (T1_Hints_CloseFunc) ps_hints_close;+ funcs->stem = (T1_Hints_SetStemFunc) t1_hints_stem;+ funcs->stem3 = (T1_Hints_SetStem3Func)ps_hints_t1stem3;+ funcs->reset = (T1_Hints_ResetFunc) ps_hints_t1reset;+ funcs->apply = (T1_Hints_ApplyFunc) ps_hints_apply;+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** TYPE 2 HINTS RECORDING INTERFACE *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ static void+ t2_hints_open( T2_Hints hints )+ {+ ps_hints_open( (PS_Hints)hints, PS_HINT_TYPE_2 );+ }+++ static void+ t2_hints_stems( T2_Hints hints,+ FT_Int dimension,+ FT_Int count,+ FT_Fixed* coords )+ {+ FT_Pos stems[32], y, n;+ FT_Int total = count;+++ y = 0;+ while ( total > 0 )+ {+ /* determine number of stems to write */+ count = total;+ if ( count > 16 )+ count = 16;++ /* compute integer stem positions in font units */+ for ( n = 0; n < count * 2; n++ )+ {+ y += coords[n];+ stems[n] = FIXED_TO_INT( y );+ }++ /* compute lengths */+ for ( n = 0; n < count * 2; n += 2 )+ stems[n + 1] = stems[n + 1] - stems[n];++ /* add them to the current dimension */+ ps_hints_stem( (PS_Hints)hints, dimension, count, stems );++ total -= count;+ }+ }+++ FT_LOCAL_DEF( void )+ t2_hints_funcs_init( T2_Hints_FuncsRec* funcs )+ {+ FT_MEM_ZERO( funcs, sizeof ( *funcs ) );++ funcs->open = (T2_Hints_OpenFunc) t2_hints_open;+ funcs->close = (T2_Hints_CloseFunc) ps_hints_close;+ funcs->stems = (T2_Hints_StemsFunc) t2_hints_stems;+ funcs->hintmask= (T2_Hints_MaskFunc) ps_hints_t2mask;+ funcs->counter = (T2_Hints_CounterFunc)ps_hints_t2counter;+ funcs->apply = (T2_Hints_ApplyFunc) ps_hints_apply;+ }+++/* END */
+ src/pshinter/pshrec.h view
@@ -0,0 +1,176 @@+/***************************************************************************/+/* */+/* pshrec.h */+/* */+/* Postscript (Type1/Type2) hints recorder (specification). */+/* */+/* Copyright 2001, 2002, 2003, 2006, 2008 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++ /**************************************************************************/+ /* */+ /* The functions defined here are called from the Type 1, CID and CFF */+ /* font drivers to record the hints of a given character/glyph. */+ /* */+ /* The hints are recorded in a unified format, and are later processed */+ /* by the `optimizer' and `fitter' to adjust the outlines to the pixel */+ /* grid. */+ /* */+ /**************************************************************************/+++#ifndef __PSHREC_H__+#define __PSHREC_H__+++#include <ft2build.h>+#include FT_INTERNAL_POSTSCRIPT_HINTS_H+#include "pshglob.h"+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** GLYPH HINTS RECORDER INTERNALS *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /* handle to hint record */+ typedef struct PS_HintRec_* PS_Hint;++ /* hint types */+ typedef enum PS_Hint_Type_+ {+ PS_HINT_TYPE_1 = 1,+ PS_HINT_TYPE_2 = 2++ } PS_Hint_Type;+++ /* hint flags */+ typedef enum PS_Hint_Flags_+ {+ PS_HINT_FLAG_GHOST = 1,+ PS_HINT_FLAG_BOTTOM = 2++ } PS_Hint_Flags;+++ /* hint descriptor */+ typedef struct PS_HintRec_+ {+ FT_Int pos;+ FT_Int len;+ FT_UInt flags;++ } PS_HintRec;+++#define ps_hint_is_active( x ) ( (x)->flags & PS_HINT_FLAG_ACTIVE )+#define ps_hint_is_ghost( x ) ( (x)->flags & PS_HINT_FLAG_GHOST )+#define ps_hint_is_bottom( x ) ( (x)->flags & PS_HINT_FLAG_BOTTOM )+++ /* hints table descriptor */+ typedef struct PS_Hint_TableRec_+ {+ FT_UInt num_hints;+ FT_UInt max_hints;+ PS_Hint hints;++ } PS_Hint_TableRec, *PS_Hint_Table;+++ /* hint and counter mask descriptor */+ typedef struct PS_MaskRec_+ {+ FT_UInt num_bits;+ FT_UInt max_bits;+ FT_Byte* bytes;+ FT_UInt end_point;++ } PS_MaskRec, *PS_Mask;+++ /* masks and counters table descriptor */+ typedef struct PS_Mask_TableRec_+ {+ FT_UInt num_masks;+ FT_UInt max_masks;+ PS_Mask masks;++ } PS_Mask_TableRec, *PS_Mask_Table;+++ /* dimension-specific hints descriptor */+ typedef struct PS_DimensionRec_+ {+ PS_Hint_TableRec hints;+ PS_Mask_TableRec masks;+ PS_Mask_TableRec counters;++ } PS_DimensionRec, *PS_Dimension;+++ /* glyph hints descriptor */+ /* dimension 0 => X coordinates + vertical hints/stems */+ /* dimension 1 => Y coordinates + horizontal hints/stems */+ typedef struct PS_HintsRec_+ {+ FT_Memory memory;+ FT_Error error;+ FT_UInt32 magic;+ PS_Hint_Type hint_type;+ PS_DimensionRec dimension[2];++ } PS_HintsRec, *PS_Hints;++ /* */++ /* initialize hints recorder */+ FT_LOCAL( FT_Error )+ ps_hints_init( PS_Hints hints,+ FT_Memory memory );++ /* finalize hints recorder */+ FT_LOCAL( void )+ ps_hints_done( PS_Hints hints );++ /* initialize Type1 hints recorder interface */+ FT_LOCAL( void )+ t1_hints_funcs_init( T1_Hints_FuncsRec* funcs );++ /* initialize Type2 hints recorder interface */+ FT_LOCAL( void )+ t2_hints_funcs_init( T2_Hints_FuncsRec* funcs );+++#ifdef DEBUG_HINTER+ extern PS_Hints ps_debug_hints;+ extern int ps_debug_no_horz_hints;+ extern int ps_debug_no_vert_hints;+#endif++ /* */+++FT_END_HEADER+++#endif /* __PS_HINTER_RECORD_H__ */+++/* END */
+ src/psnames/psmodule.c view
@@ -0,0 +1,597 @@+/***************************************************************************/+/* */+/* psmodule.c */+/* */+/* PSNames module implementation (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2005, 2006, 2007, 2008 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_OBJECTS_H+#include FT_SERVICE_POSTSCRIPT_CMAPS_H++#include "psmodule.h"+#include "pstables.h"++#include "psnamerr.h"+#include "pspic.h"+++#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES+++#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST+++#define VARIANT_BIT 0x80000000UL+#define BASE_GLYPH( code ) ( (FT_UInt32)( (code) & ~VARIANT_BIT ) )+++ /* Return the Unicode value corresponding to a given glyph. Note that */+ /* we do deal with glyph variants by detecting a non-initial dot in */+ /* the name, as in `A.swash' or `e.final'; in this case, the */+ /* VARIANT_BIT is set in the return value. */+ /* */+ static FT_UInt32+ ps_unicode_value( const char* glyph_name )+ {+ /* If the name begins with `uni', then the glyph name may be a */+ /* hard-coded unicode character code. */+ if ( glyph_name[0] == 'u' &&+ glyph_name[1] == 'n' &&+ glyph_name[2] == 'i' )+ {+ /* determine whether the next four characters following are */+ /* hexadecimal. */++ /* XXX: Add code to deal with ligatures, i.e. glyph names like */+ /* `uniXXXXYYYYZZZZ'... */++ FT_Int count;+ FT_UInt32 value = 0;+ const char* p = glyph_name + 3;+++ for ( count = 4; count > 0; count--, p++ )+ {+ char c = *p;+ unsigned int d;+++ d = (unsigned char)c - '0';+ if ( d >= 10 )+ {+ d = (unsigned char)c - 'A';+ if ( d >= 6 )+ d = 16;+ else+ d += 10;+ }++ /* Exit if a non-uppercase hexadecimal character was found */+ /* -- this also catches character codes below `0' since such */+ /* negative numbers cast to `unsigned int' are far too big. */+ if ( d >= 16 )+ break;++ value = ( value << 4 ) + d;+ }++ /* there must be exactly four hex digits */+ if ( count == 0 )+ {+ if ( *p == '\0' )+ return value;+ if ( *p == '.' )+ return (FT_UInt32)( value | VARIANT_BIT );+ }+ }++ /* If the name begins with `u', followed by four to six uppercase */+ /* hexadecimal digits, it is a hard-coded unicode character code. */+ if ( glyph_name[0] == 'u' )+ {+ FT_Int count;+ FT_UInt32 value = 0;+ const char* p = glyph_name + 1;+++ for ( count = 6; count > 0; count--, p++ )+ {+ char c = *p;+ unsigned int d;+++ d = (unsigned char)c - '0';+ if ( d >= 10 )+ {+ d = (unsigned char)c - 'A';+ if ( d >= 6 )+ d = 16;+ else+ d += 10;+ }++ if ( d >= 16 )+ break;++ value = ( value << 4 ) + d;+ }++ if ( count <= 2 )+ {+ if ( *p == '\0' )+ return value;+ if ( *p == '.' )+ return (FT_UInt32)( value | VARIANT_BIT );+ }+ }++ /* Look for a non-initial dot in the glyph name in order to */+ /* find variants like `A.swash', `e.final', etc. */+ {+ const char* p = glyph_name;+ const char* dot = NULL;+++ for ( ; *p; p++ )+ {+ if ( *p == '.' && p > glyph_name )+ {+ dot = p;+ break;+ }+ }++ /* now look up the glyph in the Adobe Glyph List */+ if ( !dot )+ return (FT_UInt32)ft_get_adobe_glyph_index( glyph_name, p );+ else+ return (FT_UInt32)( ft_get_adobe_glyph_index( glyph_name, dot ) |+ VARIANT_BIT );+ }+ }+++ /* ft_qsort callback to sort the unicode map */+ FT_CALLBACK_DEF( int )+ compare_uni_maps( const void* a,+ const void* b )+ {+ PS_UniMap* map1 = (PS_UniMap*)a;+ PS_UniMap* map2 = (PS_UniMap*)b;+ FT_UInt32 unicode1 = BASE_GLYPH( map1->unicode );+ FT_UInt32 unicode2 = BASE_GLYPH( map2->unicode );+++ /* sort base glyphs before glyph variants */+ if ( unicode1 == unicode2 )+ {+ if ( map1->unicode > map2->unicode )+ return 1;+ else if ( map1->unicode < map2->unicode )+ return -1;+ else+ return 0;+ }+ else+ {+ if ( unicode1 > unicode2 )+ return 1;+ else if ( unicode1 < unicode2 )+ return -1;+ else+ return 0;+ }+ }+++ /* support for extra glyphs not handled (well) in AGL; */+ /* we add extra mappings for them if necessary */++#define EXTRA_GLYPH_LIST_SIZE 10++ static const FT_UInt32 ft_extra_glyph_unicodes[EXTRA_GLYPH_LIST_SIZE] =+ {+ /* WGL 4 */+ 0x0394,+ 0x03A9,+ 0x2215,+ 0x00AD,+ 0x02C9,+ 0x03BC,+ 0x2219,+ 0x00A0,+ /* Romanian */+ 0x021A,+ 0x021B+ };++ static const char ft_extra_glyph_names[] =+ {+ 'D','e','l','t','a',0,+ 'O','m','e','g','a',0,+ 'f','r','a','c','t','i','o','n',0,+ 'h','y','p','h','e','n',0,+ 'm','a','c','r','o','n',0,+ 'm','u',0,+ 'p','e','r','i','o','d','c','e','n','t','e','r','e','d',0,+ 's','p','a','c','e',0,+ 'T','c','o','m','m','a','a','c','c','e','n','t',0,+ 't','c','o','m','m','a','a','c','c','e','n','t',0+ };++ static const FT_Int+ ft_extra_glyph_name_offsets[EXTRA_GLYPH_LIST_SIZE] =+ {+ 0,+ 6,+ 12,+ 21,+ 28,+ 35,+ 38,+ 53,+ 59,+ 72+ };+++ static void+ ps_check_extra_glyph_name( const char* gname,+ FT_UInt glyph,+ FT_UInt* extra_glyphs,+ FT_UInt *states )+ {+ FT_UInt n;+++ for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )+ {+ if ( ft_strcmp( ft_extra_glyph_names ++ ft_extra_glyph_name_offsets[n], gname ) == 0 )+ {+ if ( states[n] == 0 )+ {+ /* mark this extra glyph as a candidate for the cmap */+ states[n] = 1;+ extra_glyphs[n] = glyph;+ }++ return;+ }+ }+ }+++ static void+ ps_check_extra_glyph_unicode( FT_UInt32 uni_char,+ FT_UInt *states )+ {+ FT_UInt n;+++ for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )+ {+ if ( uni_char == ft_extra_glyph_unicodes[n] )+ {+ /* disable this extra glyph from being added to the cmap */+ states[n] = 2;++ return;+ }+ }+ }+++ /* Build a table that maps Unicode values to glyph indices. */+ static FT_Error+ ps_unicodes_init( FT_Memory memory,+ PS_Unicodes table,+ FT_UInt num_glyphs,+ PS_GetGlyphNameFunc get_glyph_name,+ PS_FreeGlyphNameFunc free_glyph_name,+ FT_Pointer glyph_data )+ {+ FT_Error error;++ FT_UInt extra_glyph_list_states[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };+ FT_UInt extra_glyphs[EXTRA_GLYPH_LIST_SIZE];+++ /* we first allocate the table */+ table->num_maps = 0;+ table->maps = 0;++ if ( !FT_NEW_ARRAY( table->maps, num_glyphs + EXTRA_GLYPH_LIST_SIZE ) )+ {+ FT_UInt n;+ FT_UInt count;+ PS_UniMap* map;+ FT_UInt32 uni_char;+++ map = table->maps;++ for ( n = 0; n < num_glyphs; n++ )+ {+ const char* gname = get_glyph_name( glyph_data, n );+++ if ( gname )+ {+ ps_check_extra_glyph_name( gname, n,+ extra_glyphs, extra_glyph_list_states );+ uni_char = ps_unicode_value( gname );++ if ( BASE_GLYPH( uni_char ) != 0 )+ {+ ps_check_extra_glyph_unicode( uni_char,+ extra_glyph_list_states );+ map->unicode = uni_char;+ map->glyph_index = n;+ map++;+ }++ if ( free_glyph_name )+ free_glyph_name( glyph_data, gname );+ }+ }++ for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )+ {+ if ( extra_glyph_list_states[n] == 1 )+ {+ /* This glyph name has an additional representation. */+ /* Add it to the cmap. */++ map->unicode = ft_extra_glyph_unicodes[n];+ map->glyph_index = extra_glyphs[n];+ map++;+ }+ }++ /* now compress the table a bit */+ count = (FT_UInt)( map - table->maps );++ if ( count == 0 )+ {+ /* No unicode chars here! */+ FT_FREE( table->maps );+ if ( !error )+ error = PSnames_Err_No_Unicode_Glyph_Name;+ }+ else+ {+ /* Reallocate if the number of used entries is much smaller. */+ if ( count < num_glyphs / 2 )+ {+ (void)FT_RENEW_ARRAY( table->maps, num_glyphs, count );+ error = PSnames_Err_Ok;+ }++ /* Sort the table in increasing order of unicode values, */+ /* taking care of glyph variants. */+ ft_qsort( table->maps, count, sizeof ( PS_UniMap ),+ compare_uni_maps );+ }++ table->num_maps = count;+ }++ return error;+ }+++ static FT_UInt+ ps_unicodes_char_index( PS_Unicodes table,+ FT_UInt32 unicode )+ {+ PS_UniMap *min, *max, *mid, *result = NULL;+++ /* Perform a binary search on the table. */++ min = table->maps;+ max = min + table->num_maps - 1;++ while ( min <= max )+ {+ FT_UInt32 base_glyph;+++ mid = min + ( ( max - min ) >> 1 );++ if ( mid->unicode == unicode )+ {+ result = mid;+ break;+ }++ base_glyph = BASE_GLYPH( mid->unicode );++ if ( base_glyph == unicode )+ result = mid; /* remember match but continue search for base glyph */++ if ( min == max )+ break;++ if ( base_glyph < unicode )+ min = mid + 1;+ else+ max = mid - 1;+ }++ if ( result )+ return result->glyph_index;+ else+ return 0;+ }+++ static FT_UInt32+ ps_unicodes_char_next( PS_Unicodes table,+ FT_UInt32 *unicode )+ {+ FT_UInt result = 0;+ FT_UInt32 char_code = *unicode + 1;+++ {+ FT_UInt min = 0;+ FT_UInt max = table->num_maps;+ FT_UInt mid;+ PS_UniMap* map;+ FT_UInt32 base_glyph;+++ while ( min < max )+ {+ mid = min + ( ( max - min ) >> 1 );+ map = table->maps + mid;++ if ( map->unicode == char_code )+ {+ result = map->glyph_index;+ goto Exit;+ }++ base_glyph = BASE_GLYPH( map->unicode );++ if ( base_glyph == char_code )+ result = map->glyph_index;++ if ( base_glyph < char_code )+ min = mid + 1;+ else+ max = mid;+ }++ if ( result )+ goto Exit; /* we have a variant glyph */++ /* we didn't find it; check whether we have a map just above it */+ char_code = 0;++ if ( min < table->num_maps )+ {+ map = table->maps + min;+ result = map->glyph_index;+ char_code = BASE_GLYPH( map->unicode );+ }+ }++ Exit:+ *unicode = char_code;+ return result;+ }+++#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */+++ static const char*+ ps_get_macintosh_name( FT_UInt name_index )+ {+ if ( name_index >= FT_NUM_MAC_NAMES )+ name_index = 0;++ return ft_standard_glyph_names + ft_mac_names[name_index];+ }+++ static const char*+ ps_get_standard_strings( FT_UInt sid )+ {+ if ( sid >= FT_NUM_SID_NAMES )+ return 0;++ return ft_standard_glyph_names + ft_sid_names[sid];+ }+++#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST+ 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_Macintosh_NameFunc) ps_get_macintosh_name,+ (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,++ t1_standard_encoding,+ t1_expert_encoding+ )++#else++ FT_DEFINE_SERVICE_PSCMAPSREC(pscmaps_interface, + 0,+ 0,+ 0,+ 0,++ (PS_Macintosh_NameFunc) ps_get_macintosh_name,+ (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,++ t1_standard_encoding,+ t1_expert_encoding+ )++#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */+++ FT_DEFINE_SERVICEDESCREC1(pscmaps_services, + FT_SERVICE_ID_POSTSCRIPT_CMAPS, &FT_PSCMAPS_INTERFACE_GET+ )+++++ static FT_Pointer+ psnames_get_service( FT_Module module,+ const char* service_id )+ {+ FT_UNUSED( module );++ return ft_service_list_lookup( FT_PSCMAPS_SERVICES_GET, service_id );+ }++#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */+++#ifndef FT_CONFIG_OPTION_POSTSCRIPT_NAMES+#define PUT_PS_NAMES_SERVICE(a) 0+#else+#define PUT_PS_NAMES_SERVICE(a) a+#endif++ FT_DEFINE_MODULE(psnames_module_class,+ + 0, /* this is not a font driver, nor a renderer */+ sizeof ( FT_ModuleRec ),++ "psnames", /* driver name */+ 0x10000L, /* driver version */+ 0x20000L, /* driver requires FreeType 2 or above */++ PUT_PS_NAMES_SERVICE((void*)&FT_PSCMAPS_INTERFACE_GET), /* module specific interface */+ (FT_Module_Constructor)0,+ (FT_Module_Destructor) 0,+ (FT_Module_Requester) PUT_PS_NAMES_SERVICE(psnames_get_service)+ )++++/* END */
+ src/psnames/psmodule.h view
@@ -0,0 +1,38 @@+/***************************************************************************/+/* */+/* psmodule.h */+/* */+/* High-level PSNames module interface (specification). */+/* */+/* Copyright 1996-2001 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 __PSMODULE_H__+#define __PSMODULE_H__+++#include <ft2build.h>+#include FT_MODULE_H+++FT_BEGIN_HEADER+++ FT_DECLARE_MODULE( psnames_module_class )+++FT_END_HEADER++#endif /* __PSMODULE_H__ */+++/* END */
+ src/psnames/psnamerr.h view
@@ -0,0 +1,41 @@+/***************************************************************************/+/* */+/* psnamerr.h */+/* */+/* PS names module error codes (specification only). */+/* */+/* Copyright 2001 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 PS names module error enumeration */+ /* constants. */+ /* */+ /*************************************************************************/++#ifndef __PSNAMERR_H__+#define __PSNAMERR_H__++#include FT_MODULE_ERRORS_H++#undef __FTERRORS_H__++#define FT_ERR_PREFIX PSnames_Err_+#define FT_ERR_BASE FT_Mod_Err_PSnames++#include FT_ERRORS_H++#endif /* __PSNAMERR_H__ */+++/* END */
+ src/psnames/psnames.c view
@@ -0,0 +1,26 @@+/***************************************************************************/+/* */+/* psnames.c */+/* */+/* FreeType PSNames module component (body only). */+/* */+/* Copyright 1996-2001 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 "pspic.c"+#include "psmodule.c"+++/* END */
+ src/psnames/pspic.c view
@@ -0,0 +1,79 @@+/***************************************************************************/+/* */+/* pspic.c */+/* */+/* The FreeType position independent code services for psnames module. */+/* */+/* Copyright 2009, 2010 by */+/* Oran Agra and Mickey Gabel. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#include <ft2build.h>+#include FT_FREETYPE_H+#include FT_INTERNAL_OBJECTS_H+#include "pspic.h"++#ifdef FT_CONFIG_OPTION_PIC++ /* forward declaration of PIC init functions from psmodule.c */+ FT_Error FT_Create_Class_pscmaps_services( FT_Library, FT_ServiceDescRec**);+ void FT_Destroy_Class_pscmaps_services( FT_Library, FT_ServiceDescRec*);+ void FT_Init_Class_pscmaps_interface( FT_Library, FT_Service_PsCMapsRec*);++ void+ psnames_module_class_pic_free( FT_Library library )+ {+ FT_PIC_Container* pic_container = &library->pic_container;+ FT_Memory memory = library->memory;+ if ( pic_container->psnames )+ {+ PSModulePIC* container = (PSModulePIC*)pic_container->psnames;+ if(container->pscmaps_services)+ FT_Destroy_Class_pscmaps_services(library, container->pscmaps_services);+ container->pscmaps_services = NULL;+ FT_FREE( container );+ pic_container->psnames = NULL;+ }+ }+++ FT_Error+ psnames_module_class_pic_init( FT_Library library )+ {+ FT_PIC_Container* pic_container = &library->pic_container;+ FT_Error error = PSnames_Err_Ok;+ PSModulePIC* container;+ FT_Memory memory = library->memory;+++ /* allocate pointer, clear and set global container pointer */+ if ( FT_ALLOC ( container, sizeof ( *container ) ) )+ return error;+ FT_MEM_SET( container, 0, sizeof(*container) );+ pic_container->psnames = container;++ /* initialize pointer table - this is how the module usually expects this data */+ error = FT_Create_Class_pscmaps_services(library, &container->pscmaps_services);+ if(error) + goto Exit;+ FT_Init_Class_pscmaps_interface(library, &container->pscmaps_interface);+ +Exit:+ if(error)+ psnames_module_class_pic_free(library);+ return error;+ }+++#endif /* FT_CONFIG_OPTION_PIC */+++/* END */
+ src/psnames/pspic.h view
@@ -0,0 +1,54 @@+/***************************************************************************/+/* */+/* pspic.h */+/* */+/* The FreeType position independent code services for psnames module. */+/* */+/* Copyright 2009 by */+/* Oran Agra and Mickey Gabel. */+/* */+/* 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 __PSPIC_H__+#define __PSPIC_H__++ +FT_BEGIN_HEADER++#include FT_INTERNAL_PIC_H++#ifndef FT_CONFIG_OPTION_PIC+#define FT_PSCMAPS_SERVICES_GET pscmaps_services+#define FT_PSCMAPS_INTERFACE_GET pscmaps_interface++#else /* FT_CONFIG_OPTION_PIC */++#include FT_SERVICE_POSTSCRIPT_CMAPS_H++ typedef struct PSModulePIC_+ {+ FT_ServiceDescRec* pscmaps_services;+ FT_Service_PsCMapsRec pscmaps_interface;+ } PSModulePIC;++#define GET_PIC(lib) ((PSModulePIC*)((lib)->pic_container.psnames))+#define FT_PSCMAPS_SERVICES_GET (GET_PIC(library)->pscmaps_services)+#define FT_PSCMAPS_INTERFACE_GET (GET_PIC(library)->pscmaps_interface)++#endif /* FT_CONFIG_OPTION_PIC */++ /* */++FT_END_HEADER++#endif /* __PSPIC_H__ */+++/* END */
+ src/psnames/pstables.h view
@@ -0,0 +1,4095 @@+/***************************************************************************/+/* */+/* pstables.h */+/* */+/* PostScript glyph names. */+/* */+/* Copyright 2005, 2008 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 has been generated automatically -- do not edit! */+++ static const char ft_standard_glyph_names[3696] =+ {+ '.','n','u','l','l', 0,+ 'n','o','n','m','a','r','k','i','n','g','r','e','t','u','r','n', 0,+ 'n','o','t','e','q','u','a','l', 0,+ 'i','n','f','i','n','i','t','y', 0,+ 'l','e','s','s','e','q','u','a','l', 0,+ 'g','r','e','a','t','e','r','e','q','u','a','l', 0,+ 'p','a','r','t','i','a','l','d','i','f','f', 0,+ 's','u','m','m','a','t','i','o','n', 0,+ 'p','r','o','d','u','c','t', 0,+ 'p','i', 0,+ 'i','n','t','e','g','r','a','l', 0,+ 'O','m','e','g','a', 0,+ 'r','a','d','i','c','a','l', 0,+ 'a','p','p','r','o','x','e','q','u','a','l', 0,+ 'D','e','l','t','a', 0,+ 'n','o','n','b','r','e','a','k','i','n','g','s','p','a','c','e', 0,+ 'l','o','z','e','n','g','e', 0,+ 'a','p','p','l','e', 0,+ 'f','r','a','n','c', 0,+ 'G','b','r','e','v','e', 0,+ 'g','b','r','e','v','e', 0,+ 'I','d','o','t','a','c','c','e','n','t', 0,+ 'S','c','e','d','i','l','l','a', 0,+ 's','c','e','d','i','l','l','a', 0,+ 'C','a','c','u','t','e', 0,+ 'c','a','c','u','t','e', 0,+ 'C','c','a','r','o','n', 0,+ 'c','c','a','r','o','n', 0,+ 'd','c','r','o','a','t', 0,+ '.','n','o','t','d','e','f', 0,+ 's','p','a','c','e', 0,+ 'e','x','c','l','a','m', 0,+ 'q','u','o','t','e','d','b','l', 0,+ 'n','u','m','b','e','r','s','i','g','n', 0,+ 'd','o','l','l','a','r', 0,+ 'p','e','r','c','e','n','t', 0,+ 'a','m','p','e','r','s','a','n','d', 0,+ 'q','u','o','t','e','r','i','g','h','t', 0,+ 'p','a','r','e','n','l','e','f','t', 0,+ 'p','a','r','e','n','r','i','g','h','t', 0,+ 'a','s','t','e','r','i','s','k', 0,+ 'p','l','u','s', 0,+ 'c','o','m','m','a', 0,+ 'h','y','p','h','e','n', 0,+ 'p','e','r','i','o','d', 0,+ 's','l','a','s','h', 0,+ 'z','e','r','o', 0,+ 'o','n','e', 0,+ 't','w','o', 0,+ 't','h','r','e','e', 0,+ 'f','o','u','r', 0,+ 'f','i','v','e', 0,+ 's','i','x', 0,+ 's','e','v','e','n', 0,+ 'e','i','g','h','t', 0,+ 'n','i','n','e', 0,+ 'c','o','l','o','n', 0,+ 's','e','m','i','c','o','l','o','n', 0,+ 'l','e','s','s', 0,+ 'e','q','u','a','l', 0,+ 'g','r','e','a','t','e','r', 0,+ 'q','u','e','s','t','i','o','n', 0,+ 'a','t', 0,+ 'A', 0,+ 'B', 0,+ 'C', 0,+ 'D', 0,+ 'E', 0,+ 'F', 0,+ 'G', 0,+ 'H', 0,+ 'I', 0,+ 'J', 0,+ 'K', 0,+ 'L', 0,+ 'M', 0,+ 'N', 0,+ 'O', 0,+ 'P', 0,+ 'Q', 0,+ 'R', 0,+ 'S', 0,+ 'T', 0,+ 'U', 0,+ 'V', 0,+ 'W', 0,+ 'X', 0,+ 'Y', 0,+ 'Z', 0,+ 'b','r','a','c','k','e','t','l','e','f','t', 0,+ 'b','a','c','k','s','l','a','s','h', 0,+ 'b','r','a','c','k','e','t','r','i','g','h','t', 0,+ 'a','s','c','i','i','c','i','r','c','u','m', 0,+ 'u','n','d','e','r','s','c','o','r','e', 0,+ 'q','u','o','t','e','l','e','f','t', 0,+ 'a', 0,+ 'b', 0,+ 'c', 0,+ 'd', 0,+ 'e', 0,+ 'f', 0,+ 'g', 0,+ 'h', 0,+ 'i', 0,+ 'j', 0,+ 'k', 0,+ 'l', 0,+ 'm', 0,+ 'n', 0,+ 'o', 0,+ 'p', 0,+ 'q', 0,+ 'r', 0,+ 's', 0,+ 't', 0,+ 'u', 0,+ 'v', 0,+ 'w', 0,+ 'x', 0,+ 'y', 0,+ 'z', 0,+ 'b','r','a','c','e','l','e','f','t', 0,+ 'b','a','r', 0,+ 'b','r','a','c','e','r','i','g','h','t', 0,+ 'a','s','c','i','i','t','i','l','d','e', 0,+ 'e','x','c','l','a','m','d','o','w','n', 0,+ 'c','e','n','t', 0,+ 's','t','e','r','l','i','n','g', 0,+ 'f','r','a','c','t','i','o','n', 0,+ 'y','e','n', 0,+ 'f','l','o','r','i','n', 0,+ 's','e','c','t','i','o','n', 0,+ 'c','u','r','r','e','n','c','y', 0,+ 'q','u','o','t','e','s','i','n','g','l','e', 0,+ 'q','u','o','t','e','d','b','l','l','e','f','t', 0,+ 'g','u','i','l','l','e','m','o','t','l','e','f','t', 0,+ 'g','u','i','l','s','i','n','g','l','l','e','f','t', 0,+ 'g','u','i','l','s','i','n','g','l','r','i','g','h','t', 0,+ 'f','i', 0,+ 'f','l', 0,+ 'e','n','d','a','s','h', 0,+ 'd','a','g','g','e','r', 0,+ 'd','a','g','g','e','r','d','b','l', 0,+ 'p','e','r','i','o','d','c','e','n','t','e','r','e','d', 0,+ 'p','a','r','a','g','r','a','p','h', 0,+ 'b','u','l','l','e','t', 0,+ 'q','u','o','t','e','s','i','n','g','l','b','a','s','e', 0,+ 'q','u','o','t','e','d','b','l','b','a','s','e', 0,+ 'q','u','o','t','e','d','b','l','r','i','g','h','t', 0,+ 'g','u','i','l','l','e','m','o','t','r','i','g','h','t', 0,+ 'e','l','l','i','p','s','i','s', 0,+ 'p','e','r','t','h','o','u','s','a','n','d', 0,+ 'q','u','e','s','t','i','o','n','d','o','w','n', 0,+ 'g','r','a','v','e', 0,+ 'a','c','u','t','e', 0,+ 'c','i','r','c','u','m','f','l','e','x', 0,+ 't','i','l','d','e', 0,+ 'm','a','c','r','o','n', 0,+ 'b','r','e','v','e', 0,+ 'd','o','t','a','c','c','e','n','t', 0,+ 'd','i','e','r','e','s','i','s', 0,+ 'r','i','n','g', 0,+ 'c','e','d','i','l','l','a', 0,+ 'h','u','n','g','a','r','u','m','l','a','u','t', 0,+ 'o','g','o','n','e','k', 0,+ 'c','a','r','o','n', 0,+ 'e','m','d','a','s','h', 0,+ 'A','E', 0,+ 'o','r','d','f','e','m','i','n','i','n','e', 0,+ 'L','s','l','a','s','h', 0,+ 'O','s','l','a','s','h', 0,+ 'O','E', 0,+ 'o','r','d','m','a','s','c','u','l','i','n','e', 0,+ 'a','e', 0,+ 'd','o','t','l','e','s','s','i', 0,+ 'l','s','l','a','s','h', 0,+ 'o','s','l','a','s','h', 0,+ 'o','e', 0,+ 'g','e','r','m','a','n','d','b','l','s', 0,+ 'o','n','e','s','u','p','e','r','i','o','r', 0,+ 'l','o','g','i','c','a','l','n','o','t', 0,+ 'm','u', 0,+ 't','r','a','d','e','m','a','r','k', 0,+ 'E','t','h', 0,+ 'o','n','e','h','a','l','f', 0,+ 'p','l','u','s','m','i','n','u','s', 0,+ 'T','h','o','r','n', 0,+ 'o','n','e','q','u','a','r','t','e','r', 0,+ 'd','i','v','i','d','e', 0,+ 'b','r','o','k','e','n','b','a','r', 0,+ 'd','e','g','r','e','e', 0,+ 't','h','o','r','n', 0,+ 't','h','r','e','e','q','u','a','r','t','e','r','s', 0,+ 't','w','o','s','u','p','e','r','i','o','r', 0,+ 'r','e','g','i','s','t','e','r','e','d', 0,+ 'm','i','n','u','s', 0,+ 'e','t','h', 0,+ 'm','u','l','t','i','p','l','y', 0,+ 't','h','r','e','e','s','u','p','e','r','i','o','r', 0,+ 'c','o','p','y','r','i','g','h','t', 0,+ 'A','a','c','u','t','e', 0,+ 'A','c','i','r','c','u','m','f','l','e','x', 0,+ 'A','d','i','e','r','e','s','i','s', 0,+ 'A','g','r','a','v','e', 0,+ 'A','r','i','n','g', 0,+ 'A','t','i','l','d','e', 0,+ 'C','c','e','d','i','l','l','a', 0,+ 'E','a','c','u','t','e', 0,+ 'E','c','i','r','c','u','m','f','l','e','x', 0,+ 'E','d','i','e','r','e','s','i','s', 0,+ 'E','g','r','a','v','e', 0,+ 'I','a','c','u','t','e', 0,+ 'I','c','i','r','c','u','m','f','l','e','x', 0,+ 'I','d','i','e','r','e','s','i','s', 0,+ 'I','g','r','a','v','e', 0,+ 'N','t','i','l','d','e', 0,+ 'O','a','c','u','t','e', 0,+ 'O','c','i','r','c','u','m','f','l','e','x', 0,+ 'O','d','i','e','r','e','s','i','s', 0,+ 'O','g','r','a','v','e', 0,+ 'O','t','i','l','d','e', 0,+ 'S','c','a','r','o','n', 0,+ 'U','a','c','u','t','e', 0,+ 'U','c','i','r','c','u','m','f','l','e','x', 0,+ 'U','d','i','e','r','e','s','i','s', 0,+ 'U','g','r','a','v','e', 0,+ 'Y','a','c','u','t','e', 0,+ 'Y','d','i','e','r','e','s','i','s', 0,+ 'Z','c','a','r','o','n', 0,+ 'a','a','c','u','t','e', 0,+ 'a','c','i','r','c','u','m','f','l','e','x', 0,+ 'a','d','i','e','r','e','s','i','s', 0,+ 'a','g','r','a','v','e', 0,+ 'a','r','i','n','g', 0,+ 'a','t','i','l','d','e', 0,+ 'c','c','e','d','i','l','l','a', 0,+ 'e','a','c','u','t','e', 0,+ 'e','c','i','r','c','u','m','f','l','e','x', 0,+ 'e','d','i','e','r','e','s','i','s', 0,+ 'e','g','r','a','v','e', 0,+ 'i','a','c','u','t','e', 0,+ 'i','c','i','r','c','u','m','f','l','e','x', 0,+ 'i','d','i','e','r','e','s','i','s', 0,+ 'i','g','r','a','v','e', 0,+ 'n','t','i','l','d','e', 0,+ 'o','a','c','u','t','e', 0,+ 'o','c','i','r','c','u','m','f','l','e','x', 0,+ 'o','d','i','e','r','e','s','i','s', 0,+ 'o','g','r','a','v','e', 0,+ 'o','t','i','l','d','e', 0,+ 's','c','a','r','o','n', 0,+ 'u','a','c','u','t','e', 0,+ 'u','c','i','r','c','u','m','f','l','e','x', 0,+ 'u','d','i','e','r','e','s','i','s', 0,+ 'u','g','r','a','v','e', 0,+ 'y','a','c','u','t','e', 0,+ 'y','d','i','e','r','e','s','i','s', 0,+ 'z','c','a','r','o','n', 0,+ 'e','x','c','l','a','m','s','m','a','l','l', 0,+ 'H','u','n','g','a','r','u','m','l','a','u','t','s','m','a','l','l', 0,+ 'd','o','l','l','a','r','o','l','d','s','t','y','l','e', 0,+ 'd','o','l','l','a','r','s','u','p','e','r','i','o','r', 0,+ 'a','m','p','e','r','s','a','n','d','s','m','a','l','l', 0,+ 'A','c','u','t','e','s','m','a','l','l', 0,+ 'p','a','r','e','n','l','e','f','t','s','u','p','e','r','i','o','r', 0,+ 'p','a','r','e','n','r','i','g','h','t','s','u','p','e','r','i','o','r', 0,+ 't','w','o','d','o','t','e','n','l','e','a','d','e','r', 0,+ 'o','n','e','d','o','t','e','n','l','e','a','d','e','r', 0,+ 'z','e','r','o','o','l','d','s','t','y','l','e', 0,+ 'o','n','e','o','l','d','s','t','y','l','e', 0,+ 't','w','o','o','l','d','s','t','y','l','e', 0,+ 't','h','r','e','e','o','l','d','s','t','y','l','e', 0,+ 'f','o','u','r','o','l','d','s','t','y','l','e', 0,+ 'f','i','v','e','o','l','d','s','t','y','l','e', 0,+ 's','i','x','o','l','d','s','t','y','l','e', 0,+ 's','e','v','e','n','o','l','d','s','t','y','l','e', 0,+ 'e','i','g','h','t','o','l','d','s','t','y','l','e', 0,+ 'n','i','n','e','o','l','d','s','t','y','l','e', 0,+ 'c','o','m','m','a','s','u','p','e','r','i','o','r', 0,+ 't','h','r','e','e','q','u','a','r','t','e','r','s','e','m','d','a','s','h', 0,+ 'p','e','r','i','o','d','s','u','p','e','r','i','o','r', 0,+ 'q','u','e','s','t','i','o','n','s','m','a','l','l', 0,+ 'a','s','u','p','e','r','i','o','r', 0,+ 'b','s','u','p','e','r','i','o','r', 0,+ 'c','e','n','t','s','u','p','e','r','i','o','r', 0,+ 'd','s','u','p','e','r','i','o','r', 0,+ 'e','s','u','p','e','r','i','o','r', 0,+ 'i','s','u','p','e','r','i','o','r', 0,+ 'l','s','u','p','e','r','i','o','r', 0,+ 'm','s','u','p','e','r','i','o','r', 0,+ 'n','s','u','p','e','r','i','o','r', 0,+ 'o','s','u','p','e','r','i','o','r', 0,+ 'r','s','u','p','e','r','i','o','r', 0,+ 's','s','u','p','e','r','i','o','r', 0,+ 't','s','u','p','e','r','i','o','r', 0,+ 'f','f', 0,+ 'f','f','i', 0,+ 'f','f','l', 0,+ 'p','a','r','e','n','l','e','f','t','i','n','f','e','r','i','o','r', 0,+ 'p','a','r','e','n','r','i','g','h','t','i','n','f','e','r','i','o','r', 0,+ 'C','i','r','c','u','m','f','l','e','x','s','m','a','l','l', 0,+ 'h','y','p','h','e','n','s','u','p','e','r','i','o','r', 0,+ 'G','r','a','v','e','s','m','a','l','l', 0,+ 'A','s','m','a','l','l', 0,+ 'B','s','m','a','l','l', 0,+ 'C','s','m','a','l','l', 0,+ 'D','s','m','a','l','l', 0,+ 'E','s','m','a','l','l', 0,+ 'F','s','m','a','l','l', 0,+ 'G','s','m','a','l','l', 0,+ 'H','s','m','a','l','l', 0,+ 'I','s','m','a','l','l', 0,+ 'J','s','m','a','l','l', 0,+ 'K','s','m','a','l','l', 0,+ 'L','s','m','a','l','l', 0,+ 'M','s','m','a','l','l', 0,+ 'N','s','m','a','l','l', 0,+ 'O','s','m','a','l','l', 0,+ 'P','s','m','a','l','l', 0,+ 'Q','s','m','a','l','l', 0,+ 'R','s','m','a','l','l', 0,+ 'S','s','m','a','l','l', 0,+ 'T','s','m','a','l','l', 0,+ 'U','s','m','a','l','l', 0,+ 'V','s','m','a','l','l', 0,+ 'W','s','m','a','l','l', 0,+ 'X','s','m','a','l','l', 0,+ 'Y','s','m','a','l','l', 0,+ 'Z','s','m','a','l','l', 0,+ 'c','o','l','o','n','m','o','n','e','t','a','r','y', 0,+ 'o','n','e','f','i','t','t','e','d', 0,+ 'r','u','p','i','a','h', 0,+ 'T','i','l','d','e','s','m','a','l','l', 0,+ 'e','x','c','l','a','m','d','o','w','n','s','m','a','l','l', 0,+ 'c','e','n','t','o','l','d','s','t','y','l','e', 0,+ 'L','s','l','a','s','h','s','m','a','l','l', 0,+ 'S','c','a','r','o','n','s','m','a','l','l', 0,+ 'Z','c','a','r','o','n','s','m','a','l','l', 0,+ 'D','i','e','r','e','s','i','s','s','m','a','l','l', 0,+ 'B','r','e','v','e','s','m','a','l','l', 0,+ 'C','a','r','o','n','s','m','a','l','l', 0,+ 'D','o','t','a','c','c','e','n','t','s','m','a','l','l', 0,+ 'M','a','c','r','o','n','s','m','a','l','l', 0,+ 'f','i','g','u','r','e','d','a','s','h', 0,+ 'h','y','p','h','e','n','i','n','f','e','r','i','o','r', 0,+ 'O','g','o','n','e','k','s','m','a','l','l', 0,+ 'R','i','n','g','s','m','a','l','l', 0,+ 'C','e','d','i','l','l','a','s','m','a','l','l', 0,+ 'q','u','e','s','t','i','o','n','d','o','w','n','s','m','a','l','l', 0,+ 'o','n','e','e','i','g','h','t','h', 0,+ 't','h','r','e','e','e','i','g','h','t','h','s', 0,+ 'f','i','v','e','e','i','g','h','t','h','s', 0,+ 's','e','v','e','n','e','i','g','h','t','h','s', 0,+ 'o','n','e','t','h','i','r','d', 0,+ 't','w','o','t','h','i','r','d','s', 0,+ 'z','e','r','o','s','u','p','e','r','i','o','r', 0,+ 'f','o','u','r','s','u','p','e','r','i','o','r', 0,+ 'f','i','v','e','s','u','p','e','r','i','o','r', 0,+ 's','i','x','s','u','p','e','r','i','o','r', 0,+ 's','e','v','e','n','s','u','p','e','r','i','o','r', 0,+ 'e','i','g','h','t','s','u','p','e','r','i','o','r', 0,+ 'n','i','n','e','s','u','p','e','r','i','o','r', 0,+ 'z','e','r','o','i','n','f','e','r','i','o','r', 0,+ 'o','n','e','i','n','f','e','r','i','o','r', 0,+ 't','w','o','i','n','f','e','r','i','o','r', 0,+ 't','h','r','e','e','i','n','f','e','r','i','o','r', 0,+ 'f','o','u','r','i','n','f','e','r','i','o','r', 0,+ 'f','i','v','e','i','n','f','e','r','i','o','r', 0,+ 's','i','x','i','n','f','e','r','i','o','r', 0,+ 's','e','v','e','n','i','n','f','e','r','i','o','r', 0,+ 'e','i','g','h','t','i','n','f','e','r','i','o','r', 0,+ 'n','i','n','e','i','n','f','e','r','i','o','r', 0,+ 'c','e','n','t','i','n','f','e','r','i','o','r', 0,+ 'd','o','l','l','a','r','i','n','f','e','r','i','o','r', 0,+ 'p','e','r','i','o','d','i','n','f','e','r','i','o','r', 0,+ 'c','o','m','m','a','i','n','f','e','r','i','o','r', 0,+ 'A','g','r','a','v','e','s','m','a','l','l', 0,+ 'A','a','c','u','t','e','s','m','a','l','l', 0,+ 'A','c','i','r','c','u','m','f','l','e','x','s','m','a','l','l', 0,+ 'A','t','i','l','d','e','s','m','a','l','l', 0,+ 'A','d','i','e','r','e','s','i','s','s','m','a','l','l', 0,+ 'A','r','i','n','g','s','m','a','l','l', 0,+ 'A','E','s','m','a','l','l', 0,+ 'C','c','e','d','i','l','l','a','s','m','a','l','l', 0,+ 'E','g','r','a','v','e','s','m','a','l','l', 0,+ 'E','a','c','u','t','e','s','m','a','l','l', 0,+ 'E','c','i','r','c','u','m','f','l','e','x','s','m','a','l','l', 0,+ 'E','d','i','e','r','e','s','i','s','s','m','a','l','l', 0,+ 'I','g','r','a','v','e','s','m','a','l','l', 0,+ 'I','a','c','u','t','e','s','m','a','l','l', 0,+ 'I','c','i','r','c','u','m','f','l','e','x','s','m','a','l','l', 0,+ 'I','d','i','e','r','e','s','i','s','s','m','a','l','l', 0,+ 'E','t','h','s','m','a','l','l', 0,+ 'N','t','i','l','d','e','s','m','a','l','l', 0,+ 'O','g','r','a','v','e','s','m','a','l','l', 0,+ 'O','a','c','u','t','e','s','m','a','l','l', 0,+ 'O','c','i','r','c','u','m','f','l','e','x','s','m','a','l','l', 0,+ 'O','t','i','l','d','e','s','m','a','l','l', 0,+ 'O','d','i','e','r','e','s','i','s','s','m','a','l','l', 0,+ 'O','E','s','m','a','l','l', 0,+ 'O','s','l','a','s','h','s','m','a','l','l', 0,+ 'U','g','r','a','v','e','s','m','a','l','l', 0,+ 'U','a','c','u','t','e','s','m','a','l','l', 0,+ 'U','c','i','r','c','u','m','f','l','e','x','s','m','a','l','l', 0,+ 'U','d','i','e','r','e','s','i','s','s','m','a','l','l', 0,+ 'Y','a','c','u','t','e','s','m','a','l','l', 0,+ 'T','h','o','r','n','s','m','a','l','l', 0,+ 'Y','d','i','e','r','e','s','i','s','s','m','a','l','l', 0,+ '0','0','1','.','0','0','0', 0,+ '0','0','1','.','0','0','1', 0,+ '0','0','1','.','0','0','2', 0,+ '0','0','1','.','0','0','3', 0,+ 'B','l','a','c','k', 0,+ 'B','o','l','d', 0,+ 'B','o','o','k', 0,+ 'L','i','g','h','t', 0,+ 'M','e','d','i','u','m', 0,+ 'R','e','g','u','l','a','r', 0,+ 'R','o','m','a','n', 0,+ 'S','e','m','i','b','o','l','d', 0,+ };+++#define FT_NUM_MAC_NAMES 258++ /* Values are offsets into the `ft_standard_glyph_names' table */++ static const short ft_mac_names[FT_NUM_MAC_NAMES] =+ {+ 253, 0, 6, 261, 267, 274, 283, 294, 301, 309, 758, 330, 340, 351,+ 360, 365, 371, 378, 385, 391, 396, 400, 404, 410, 415, 420, 424, 430,+ 436, 441, 447, 457, 462, 468, 476, 485, 488, 490, 492, 494, 496, 498,+ 500, 502, 504, 506, 508, 510, 512, 514, 516, 518, 520, 522, 524, 526,+ 528, 530, 532, 534, 536, 538, 540, 552, 562, 575, 587, 979, 608, 610,+ 612, 614, 616, 618, 620, 622, 624, 626, 628, 630, 632, 634, 636, 638,+ 640, 642, 644, 646, 648, 650, 652, 654, 656, 658, 660, 670, 674, 685,+ 1375,1392,1405,1414,1486,1512,1562,1603,1632,1610,1622,1645,1639,1652,+ 1661,1690,1668,1680,1697,1726,1704,1716,1733,1740,1769,1747,1759,1776,+ 1790,1819,1797,1809, 839,1263, 707, 712, 741, 881, 871,1160,1302,1346,+ 1197, 985,1031, 23,1086,1108, 32,1219, 41, 51, 730,1194, 64, 76,+ 86, 94, 97,1089,1118, 106,1131,1150, 966, 696,1183, 112, 734, 120,+ 132, 783, 930, 945, 138,1385,1398,1529,1115,1157, 832,1079, 770, 916,+ 598, 319,1246, 155,1833,1586, 721, 749, 797, 811, 826, 829, 846, 856,+ 888, 903, 954,1363,1421,1356,1433,1443,1450,1457,1469,1479,1493,1500,+ 163,1522,1543,1550,1572,1134, 991,1002,1008,1015,1021,1040,1045,1053,+ 1066,1073,1101,1143,1536,1783,1596,1843,1253,1207,1319,1579,1826,1229,+ 1270,1313,1323,1171,1290,1332,1211,1235,1276, 169, 175, 182, 189, 200,+ 209, 218, 225, 232, 239, 246+ };+++#define FT_NUM_SID_NAMES 391++ /* Values are offsets into the `ft_standard_glyph_names' table */++ static const short ft_sid_names[FT_NUM_SID_NAMES] =+ {+ 253, 261, 267, 274, 283, 294, 301, 309, 319, 330, 340, 351, 360, 365,+ 371, 378, 385, 391, 396, 400, 404, 410, 415, 420, 424, 430, 436, 441,+ 447, 457, 462, 468, 476, 485, 488, 490, 492, 494, 496, 498, 500, 502,+ 504, 506, 508, 510, 512, 514, 516, 518, 520, 522, 524, 526, 528, 530,+ 532, 534, 536, 538, 540, 552, 562, 575, 587, 598, 608, 610, 612, 614,+ 616, 618, 620, 622, 624, 626, 628, 630, 632, 634, 636, 638, 640, 642,+ 644, 646, 648, 650, 652, 654, 656, 658, 660, 670, 674, 685, 696, 707,+ 712, 721, 730, 734, 741, 749, 758, 770, 783, 797, 811, 826, 829, 832,+ 839, 846, 856, 871, 881, 888, 903, 916, 930, 945, 954, 966, 979, 985,+ 991,1002,1008,1015,1021,1031,1040,1045,1053,1066,1073,1079,1086,1089,+ 1101,1108,1115,1118,1131,1134,1143,1150,1157,1160,1171,1183,1194,1197,+ 1207,1211,1219,1229,1235,1246,1253,1263,1270,1276,1290,1302,1313,1319,+ 1323,1332,1346,1356,1363,1375,1385,1392,1398,1405,1414,1421,1433,1443,+ 1450,1457,1469,1479,1486,1493,1500,1512,1522,1529,1536,1543,1550,1562,+ 1572,1579,1586,1596,1603,1610,1622,1632,1639,1645,1652,1661,1668,1680,+ 1690,1697,1704,1716,1726,1733,1740,1747,1759,1769,1776,1783,1790,1797,+ 1809,1819,1826,1833,1843,1850,1862,1880,1895,1910,1925,1936,1954,1973,+ 1988,2003,2016,2028,2040,2054,2067,2080,2092,2106,2120,2133,2147,2167,+ 2182,2196,2206,2216,2229,2239,2249,2259,2269,2279,2289,2299,2309,2319,+ 2329,2332,2336,2340,2358,2377,2393,2408,2419,2426,2433,2440,2447,2454,+ 2461,2468,2475,2482,2489,2496,2503,2510,2517,2524,2531,2538,2545,2552,+ 2559,2566,2573,2580,2587,2594,2601,2615,2625,2632,2643,2659,2672,2684,+ 2696,2708,2722,2733,2744,2759,2771,2782,2797,2809,2819,2832,2850,2860,+ 2873,2885,2898,2907,2917,2930,2943,2956,2968,2982,2996,3009,3022,3034,+ 3046,3060,3073,3086,3098,3112,3126,3139,3152,3167,3182,3196,3208,3220,+ 3237,3249,3264,3275,3283,3297,3309,3321,3338,3353,3365,3377,3394,3409,+ 3418,3430,3442,3454,3471,3483,3498,3506,3518,3530,3542,3559,3574,3586,+ 3597,3612,3620,3628,3636,3644,3650,3655,3660,3666,3673,3681,3687+ };+++ /* the following are indices into the SID name table */+ static const unsigned short t1_standard_encoding[256] =+ {+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,+ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,+ 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 0,+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,+ 0, 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,+ 0,111,112,113,114, 0,115,116,117,118,119,120,121,122, 0,123,+ 0,124,125,126,127,128,129,130,131, 0,132,133, 0,134,135,136,+ 137, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,+ 0,138, 0,139, 0, 0, 0, 0,140,141,142,143, 0, 0, 0, 0,+ 0,144, 0, 0, 0,145, 0, 0,146,147,148,149, 0, 0, 0, 0+ };+++ /* the following are indices into the SID name table */+ static const unsigned short t1_expert_encoding[256] =+ {+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,+ 1,229,230, 0,231,232,233,234,235,236,237,238, 13, 14, 15, 99,+ 239,240,241,242,243,244,245,246,247,248, 27, 28,249,250,251,252,+ 0,253,254,255,256,257, 0, 0, 0,258, 0, 0,259,260,261,262,+ 0, 0,263,264,265, 0,266,109,110,267,268,269, 0,270,271,272,+ 273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,+ 289,290,291,292,293,294,295,296,297,298,299,300,301,302,303, 0,+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,+ 0,304,305,306, 0, 0,307,308,309,310,311, 0,312, 0, 0,313,+ 0, 0,314,315, 0, 0,316,317,318, 0, 0, 0,158,155,163,319,+ 320,321,322,323,324,325, 0, 0,326,150,164,169,327,328,329,330,+ 331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,+ 347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,+ 363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378+ };+++ /*+ * This table is a compressed version of the Adobe Glyph List (AGL),+ * optimized for efficient searching. It has been generated by the+ * `glnames.py' python script located in the `src/tools' directory.+ *+ * The lookup function to get the Unicode value for a given string+ * is defined below the table.+ */++#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST++ static const unsigned char ft_adobe_glyph_list[54791L] =+ {+ 0, 52, 0,106, 2,167, 3, 63, 4,220, 6,125, 9,143, 10, 23,+ 11,137, 12,199, 14,246, 15, 87, 16,233, 17,219, 18,104, 19, 88,+ 22,110, 23, 32, 23, 71, 24, 77, 27,156, 29, 73, 31,247, 32,107,+ 32,222, 33, 55, 34,154, 35,218, 53, 84, 59,196, 68, 6, 75,183,+ 83,178, 88,135, 93,242,101,165,109,185,111, 55,117,254,123, 73,+ 130,238,138,206,145, 31,153,182,156,189,163,249,178,221,193, 17,+ 197, 99,199,240,204, 27,204,155,210,100, 65,143, 0, 65, 0,140,+ 0,175, 0,193, 1, 15, 1,147, 1,233, 1,251, 2, 7, 2, 40,+ 2, 57, 2, 82, 2, 91, 2,128, 2,136, 2,154, 69,131, 0,198,+ 0,150, 0,158, 0,167,225,227,245,244,101,128, 1,252,237,225,+ 227,242,239,110,128, 1,226,243,237,225,236,108,128,247,230,225,+ 227,245,244,101,129, 0,193, 0,185,243,237,225,236,108,128,247,+ 225,226,242,229,246,101,134, 1, 2, 0,213, 0,221, 0,232, 0,+ 243, 0,251, 1, 7,225,227,245,244,101,128, 30,174,227,249,242,+ 233,236,236,233, 99,128, 4,208,228,239,244,226,229,236,239,119,+ 128, 30,182,231,242,225,246,101,128, 30,176,232,239,239,235,225,+ 226,239,246,101,128, 30,178,244,233,236,228,101,128, 30,180, 99,+ 4, 1, 25, 1, 32, 1,121, 1,137,225,242,239,110,128, 1,205,+ 233,242, 99, 2, 1, 40, 1, 45,236,101,128, 36,182,245,237,230,+ 236,229,120,134, 0,194, 1, 66, 1, 74, 1, 85, 1, 93, 1,105,+ 1,113,225,227,245,244,101,128, 30,164,228,239,244,226,229,236,+ 239,119,128, 30,172,231,242,225,246,101,128, 30,166,232,239,239,+ 235,225,226,239,246,101,128, 30,168,243,237,225,236,108,128,247,+ 226,244,233,236,228,101,128, 30,170,245,244,101,129,246,201, 1,+ 129,243,237,225,236,108,128,247,180,249,242,233,236,236,233, 99,+ 128, 4, 16,100, 3, 1,155, 1,165, 1,209,226,236,231,242,225,+ 246,101,128, 2, 0,233,229,242,229,243,233,115,131, 0,196, 1,+ 181, 1,192, 1,201,227,249,242,233,236,236,233, 99,128, 4,210,+ 237,225,227,242,239,110,128, 1,222,243,237,225,236,108,128,247,+ 228,239,116, 2, 1,216, 1,224,226,229,236,239,119,128, 30,160,+ 237,225,227,242,239,110,128, 1,224,231,242,225,246,101,129, 0,+ 192, 1,243,243,237,225,236,108,128,247,224,232,239,239,235,225,+ 226,239,246,101,128, 30,162,105, 2, 2, 13, 2, 25,229,227,249,+ 242,233,236,236,233, 99,128, 4,212,238,246,229,242,244,229,228,+ 226,242,229,246,101,128, 2, 2,236,240,232, 97,129, 3,145, 2,+ 49,244,239,238,239,115,128, 3,134,109, 2, 2, 63, 2, 71,225,+ 227,242,239,110,128, 1, 0,239,238,239,243,240,225,227,101,128,+ 255, 33,239,231,239,238,229,107,128, 1, 4,242,233,238,103,131,+ 0,197, 2,104, 2,112, 2,120,225,227,245,244,101,128, 1,250,+ 226,229,236,239,119,128, 30, 0,243,237,225,236,108,128,247,229,+ 243,237,225,236,108,128,247, 97,244,233,236,228,101,129, 0,195,+ 2,146,243,237,225,236,108,128,247,227,249,226,225,242,237,229,+ 238,233,225,110,128, 5, 49, 66,137, 0, 66, 2,189, 2,198, 2,+ 223, 3, 3, 3, 10, 3, 22, 3, 34, 3, 46, 3, 54,227,233,242,+ 227,236,101,128, 36,183,228,239,116, 2, 2,206, 2,215,225,227,+ 227,229,238,116,128, 30, 2,226,229,236,239,119,128, 30, 4,101,+ 3, 2,231, 2,242, 2,254,227,249,242,233,236,236,233, 99,128,+ 4, 17,238,225,242,237,229,238,233,225,110,128, 5, 50,244, 97,+ 128, 3,146,232,239,239,107,128, 1,129,236,233,238,229,226,229,+ 236,239,119,128, 30, 6,237,239,238,239,243,240,225,227,101,128,+ 255, 34,242,229,246,229,243,237,225,236,108,128,246,244,243,237,+ 225,236,108,128,247, 98,244,239,240,226,225,114,128, 1,130, 67,+ 137, 0, 67, 3, 85, 3,127, 3,193, 3,210, 3,224, 4,171, 4,+ 188, 4,200, 4,212, 97, 3, 3, 93, 3,104, 3,111,225,242,237,+ 229,238,233,225,110,128, 5, 62,227,245,244,101,128, 1, 6,242,+ 239,110,129,246,202, 3,119,243,237,225,236,108,128,246,245, 99,+ 3, 3,135, 3,142, 3,171,225,242,239,110,128, 1, 12,229,228,+ 233,236,236, 97,130, 0,199, 3,155, 3,163,225,227,245,244,101,+ 128, 30, 8,243,237,225,236,108,128,247,231,233,242, 99, 2, 3,+ 179, 3,184,236,101,128, 36,184,245,237,230,236,229,120,128, 1,+ 8,228,239,116,129, 1, 10, 3,201,225,227,227,229,238,116,128,+ 1, 10,229,228,233,236,236,225,243,237,225,236,108,128,247,184,+ 104, 4, 3,234, 3,246, 4,161, 4,165,225,225,242,237,229,238,+ 233,225,110,128, 5, 73,101, 6, 4, 4, 4, 24, 4, 35, 4,103,+ 4,115, 4,136,225,226,235,232,225,243,233,225,238,227,249,242,+ 233,236,236,233, 99,128, 4,188,227,249,242,233,236,236,233, 99,+ 128, 4, 39,100, 2, 4, 41, 4, 85,229,243,227,229,238,228,229,+ 114, 2, 4, 54, 4, 74,225,226,235,232,225,243,233,225,238,227,+ 249,242,233,236,236,233, 99,128, 4,190,227,249,242,233,236,236,+ 233, 99,128, 4,182,233,229,242,229,243,233,243,227,249,242,233,+ 236,236,233, 99,128, 4,244,232,225,242,237,229,238,233,225,110,+ 128, 5, 67,235,232,225,235,225,243,243,233,225,238,227,249,242,+ 233,236,236,233, 99,128, 4,203,246,229,242,244,233,227,225,236,+ 243,244,242,239,235,229,227,249,242,233,236,236,233, 99,128, 4,+ 184,105,128, 3,167,239,239,107,128, 1,135,233,242,227,245,237,+ 230,236,229,248,243,237,225,236,108,128,246,246,237,239,238,239,+ 243,240,225,227,101,128,255, 35,239,225,242,237,229,238,233,225,+ 110,128, 5, 81,243,237,225,236,108,128,247, 99, 68,142, 0, 68,+ 4,252, 5, 10, 5, 36, 5, 96, 5,121, 5,166, 5,173, 5,231,+ 5,244, 6, 0, 6, 12, 6, 28, 6, 48, 6, 57, 90,129, 1,241,+ 5, 2,227,225,242,239,110,128, 1,196, 97, 2, 5, 16, 5, 27,+ 225,242,237,229,238,233,225,110,128, 5, 52,230,242,233,227,225,+ 110,128, 1,137, 99, 4, 5, 46, 5, 53, 5, 62, 5, 89,225,242,+ 239,110,128, 1, 14,229,228,233,236,236, 97,128, 30, 16,233,242,+ 99, 2, 5, 70, 5, 75,236,101,128, 36,185,245,237,230,236,229,+ 248,226,229,236,239,119,128, 30, 18,242,239,225,116,128, 1, 16,+ 228,239,116, 2, 5,104, 5,113,225,227,227,229,238,116,128, 30,+ 10,226,229,236,239,119,128, 30, 12,101, 3, 5,129, 5,140, 5,+ 150,227,249,242,233,236,236,233, 99,128, 4, 20,233,227,239,240,+ 244,233, 99,128, 3,238,236,244, 97,129, 34, 6, 5,158,231,242,+ 229,229,107,128, 3,148,232,239,239,107,128, 1,138,105, 2, 5,+ 179, 5,218,229,242,229,243,233,115,131,246,203, 5,194, 5,202,+ 5,210,193,227,245,244,101,128,246,204,199,242,225,246,101,128,+ 246,205,243,237,225,236,108,128,247,168,231,225,237,237,225,231,+ 242,229,229,107,128, 3,220,234,229,227,249,242,233,236,236,233,+ 99,128, 4, 2,236,233,238,229,226,229,236,239,119,128, 30, 14,+ 237,239,238,239,243,240,225,227,101,128,255, 36,239,244,225,227,+ 227,229,238,244,243,237,225,236,108,128,246,247,115, 2, 6, 34,+ 6, 41,236,225,243,104,128, 1, 16,237,225,236,108,128,247,100,+ 244,239,240,226,225,114,128, 1,139,122,131, 1,242, 6, 67, 6,+ 75, 6,112,227,225,242,239,110,128, 1,197,101, 2, 6, 81, 6,+ 101,225,226,235,232,225,243,233,225,238,227,249,242,233,236,236,+ 233, 99,128, 4,224,227,249,242,233,236,236,233, 99,128, 4, 5,+ 232,229,227,249,242,233,236,236,233, 99,128, 4, 15, 69,146, 0,+ 69, 6,165, 6,183, 6,191, 7, 89, 7,153, 7,165, 7,183, 7,+ 211, 8, 7, 8, 36, 8, 94, 8,169, 8,189, 8,208, 8,248, 9,+ 44, 9,109, 9,115,225,227,245,244,101,129, 0,201, 6,175,243,+ 237,225,236,108,128,247,233,226,242,229,246,101,128, 1, 20, 99,+ 5, 6,203, 6,210, 6,224, 6,236, 7, 79,225,242,239,110,128,+ 1, 26,229,228,233,236,236,225,226,242,229,246,101,128, 30, 28,+ 232,225,242,237,229,238,233,225,110,128, 5, 53,233,242, 99, 2,+ 6,244, 6,249,236,101,128, 36,186,245,237,230,236,229,120,135,+ 0,202, 7, 16, 7, 24, 7, 32, 7, 43, 7, 51, 7, 63, 7, 71,+ 225,227,245,244,101,128, 30,190,226,229,236,239,119,128, 30, 24,+ 228,239,244,226,229,236,239,119,128, 30,198,231,242,225,246,101,+ 128, 30,192,232,239,239,235,225,226,239,246,101,128, 30,194,243,+ 237,225,236,108,128,247,234,244,233,236,228,101,128, 30,196,249,+ 242,233,236,236,233, 99,128, 4, 4,100, 3, 7, 97, 7,107, 7,+ 127,226,236,231,242,225,246,101,128, 2, 4,233,229,242,229,243,+ 233,115,129, 0,203, 7,119,243,237,225,236,108,128,247,235,239,+ 116,130, 1, 22, 7,136, 7,145,225,227,227,229,238,116,128, 1,+ 22,226,229,236,239,119,128, 30,184,230,227,249,242,233,236,236,+ 233, 99,128, 4, 36,231,242,225,246,101,129, 0,200, 7,175,243,+ 237,225,236,108,128,247,232,104, 2, 7,189, 7,200,225,242,237,+ 229,238,233,225,110,128, 5, 55,239,239,235,225,226,239,246,101,+ 128, 30,186,105, 3, 7,219, 7,230, 7,245,231,232,244,242,239,+ 237,225,110,128, 33,103,238,246,229,242,244,229,228,226,242,229,+ 246,101,128, 2, 6,239,244,233,230,233,229,228,227,249,242,233,+ 236,236,233, 99,128, 4,100,108, 2, 8, 13, 8, 24,227,249,242,+ 233,236,236,233, 99,128, 4, 27,229,246,229,238,242,239,237,225,+ 110,128, 33,106,109, 3, 8, 44, 8, 72, 8, 83,225,227,242,239,+ 110,130, 1, 18, 8, 56, 8, 64,225,227,245,244,101,128, 30, 22,+ 231,242,225,246,101,128, 30, 20,227,249,242,233,236,236,233, 99,+ 128, 4, 28,239,238,239,243,240,225,227,101,128,255, 37,110, 4,+ 8,104, 8,115, 8,135, 8,154,227,249,242,233,236,236,233, 99,+ 128, 4, 29,228,229,243,227,229,238,228,229,242,227,249,242,233,+ 236,236,233, 99,128, 4,162,103,129, 1, 74, 8,141,232,229,227,+ 249,242,233,236,236,233, 99,128, 4,164,232,239,239,235,227,249,+ 242,233,236,236,233, 99,128, 4,199,111, 2, 8,175, 8,183,231,+ 239,238,229,107,128, 1, 24,240,229,110,128, 1,144,240,243,233,+ 236,239,110,129, 3,149, 8,200,244,239,238,239,115,128, 3,136,+ 114, 2, 8,214, 8,225,227,249,242,233,236,236,233, 99,128, 4,+ 32,229,246,229,242,243,229,100,129, 1,142, 8,237,227,249,242,+ 233,236,236,233, 99,128, 4, 45,115, 4, 9, 2, 9, 13, 9, 33,+ 9, 37,227,249,242,233,236,236,233, 99,128, 4, 33,228,229,243,+ 227,229,238,228,229,242,227,249,242,233,236,236,233, 99,128, 4,+ 170,104,128, 1,169,237,225,236,108,128,247,101,116, 3, 9, 52,+ 9, 78, 9, 92, 97,130, 3,151, 9, 60, 9, 70,242,237,229,238,+ 233,225,110,128, 5, 56,244,239,238,239,115,128, 3,137,104,129,+ 0,208, 9, 84,243,237,225,236,108,128,247,240,233,236,228,101,+ 129, 30,188, 9,101,226,229,236,239,119,128, 30, 26,245,242,111,+ 128, 32,172,250,104,130, 1,183, 9,124, 9,132,227,225,242,239,+ 110,128, 1,238,242,229,246,229,242,243,229,100,128, 1,184, 70,+ 136, 0, 70, 9,163, 9,172, 9,184, 9,212, 9,219, 9,248, 10,+ 4, 10, 15,227,233,242,227,236,101,128, 36,187,228,239,244,225,+ 227,227,229,238,116,128, 30, 30,101, 2, 9,190, 9,202,232,225,+ 242,237,229,238,233,225,110,128, 5, 86,233,227,239,240,244,233,+ 99,128, 3,228,232,239,239,107,128, 1,145,105, 2, 9,225, 9,+ 238,244,225,227,249,242,233,236,236,233, 99,128, 4,114,246,229,+ 242,239,237,225,110,128, 33,100,237,239,238,239,243,240,225,227,+ 101,128,255, 38,239,245,242,242,239,237,225,110,128, 33, 99,243,+ 237,225,236,108,128,247,102, 71,140, 0, 71, 10, 51, 10, 61, 10,+ 107, 10,115, 10,176, 10,193, 10,205, 11, 39, 11, 52, 11, 65, 11,+ 90, 11,107,194,243,241,245,225,242,101,128, 51,135, 97, 3, 10,+ 69, 10, 76, 10, 94,227,245,244,101,128, 1,244,237,237, 97,129,+ 3,147, 10, 84,225,230,242,233,227,225,110,128, 1,148,238,231,+ 233,225,227,239,240,244,233, 99,128, 3,234,226,242,229,246,101,+ 128, 1, 30, 99, 4, 10,125, 10,132, 10,141, 10,163,225,242,239,+ 110,128, 1,230,229,228,233,236,236, 97,128, 1, 34,233,242, 99,+ 2, 10,149, 10,154,236,101,128, 36,188,245,237,230,236,229,120,+ 128, 1, 28,239,237,237,225,225,227,227,229,238,116,128, 1, 34,+ 228,239,116,129, 1, 32, 10,184,225,227,227,229,238,116,128, 1,+ 32,229,227,249,242,233,236,236,233, 99,128, 4, 19,104, 3, 10,+ 213, 10,226, 11, 33,225,228,225,242,237,229,238,233,225,110,128,+ 5, 66,101, 3, 10,234, 10,255, 11, 16,237,233,228,228,236,229,+ 232,239,239,235,227,249,242,233,236,236,233, 99,128, 4,148,243,+ 244,242,239,235,229,227,249,242,233,236,236,233, 99,128, 4,146,+ 245,240,244,245,242,238,227,249,242,233,236,236,233, 99,128, 4,+ 144,239,239,107,128, 1,147,233,237,225,242,237,229,238,233,225,+ 110,128, 5, 51,234,229,227,249,242,233,236,236,233, 99,128, 4,+ 3,109, 2, 11, 71, 11, 79,225,227,242,239,110,128, 30, 32,239,+ 238,239,243,240,225,227,101,128,255, 39,242,225,246,101,129,246,+ 206, 11, 99,243,237,225,236,108,128,247, 96,115, 2, 11,113, 11,+ 129,237,225,236,108,129,247,103, 11,122,232,239,239,107,128, 2,+ 155,244,242,239,235,101,128, 1,228, 72,140, 0, 72, 11,165, 11,+ 190, 11,198, 11,208, 12, 17, 12, 40, 12, 77, 12,117, 12,129, 12,+ 157, 12,165, 12,189,177,184, 53, 3, 11,175, 11,180, 11,185,179,+ 51,128, 37,207,180, 51,128, 37,170,181, 49,128, 37,171,178,178,+ 176,183, 51,128, 37,161,208,243,241,245,225,242,101,128, 51,203,+ 97, 3, 11,216, 11,236, 12, 0,225,226,235,232,225,243,233,225,+ 238,227,249,242,233,236,236,233, 99,128, 4,168,228,229,243,227,+ 229,238,228,229,242,227,249,242,233,236,236,233, 99,128, 4,178,+ 242,228,243,233,231,238,227,249,242,233,236,236,233, 99,128, 4,+ 42, 98, 2, 12, 23, 12, 28,225,114,128, 1, 38,242,229,246,229,+ 226,229,236,239,119,128, 30, 42, 99, 2, 12, 46, 12, 55,229,228,+ 233,236,236, 97,128, 30, 40,233,242, 99, 2, 12, 63, 12, 68,236,+ 101,128, 36,189,245,237,230,236,229,120,128, 1, 36,100, 2, 12,+ 83, 12, 93,233,229,242,229,243,233,115,128, 30, 38,239,116, 2,+ 12,100, 12,109,225,227,227,229,238,116,128, 30, 34,226,229,236,+ 239,119,128, 30, 36,237,239,238,239,243,240,225,227,101,128,255,+ 40,111, 2, 12,135, 12,146,225,242,237,229,238,233,225,110,128,+ 5, 64,242,233,227,239,240,244,233, 99,128, 3,232,243,237,225,+ 236,108,128,247,104,245,238,231,225,242,245,237,236,225,245,116,+ 129,246,207, 12,181,243,237,225,236,108,128,246,248,250,243,241,+ 245,225,242,101,128, 51,144, 73,146, 0, 73, 12,239, 12,251, 12,+ 255, 13, 11, 13, 29, 13, 37, 13, 94, 13,181, 13,214, 13,224, 13,+ 242, 13,254, 14, 48, 14, 86, 14, 99, 14,166, 14,187, 14,205,193,+ 227,249,242,233,236,236,233, 99,128, 4, 47, 74,128, 1, 50,213,+ 227,249,242,233,236,236,233, 99,128, 4, 46,225,227,245,244,101,+ 129, 0,205, 13, 21,243,237,225,236,108,128,247,237,226,242,229,+ 246,101,128, 1, 44, 99, 3, 13, 45, 13, 52, 13, 84,225,242,239,+ 110,128, 1,207,233,242, 99, 2, 13, 60, 13, 65,236,101,128, 36,+ 190,245,237,230,236,229,120,129, 0,206, 13, 76,243,237,225,236,+ 108,128,247,238,249,242,233,236,236,233, 99,128, 4, 6,100, 3,+ 13,102, 13,112, 13,155,226,236,231,242,225,246,101,128, 2, 8,+ 233,229,242,229,243,233,115,131, 0,207, 13,128, 13,136, 13,147,+ 225,227,245,244,101,128, 30, 46,227,249,242,233,236,236,233, 99,+ 128, 4,228,243,237,225,236,108,128,247,239,239,116,130, 1, 48,+ 13,164, 13,173,225,227,227,229,238,116,128, 1, 48,226,229,236,+ 239,119,128, 30,202,101, 2, 13,187, 13,203,226,242,229,246,229,+ 227,249,242,233,236,236,233, 99,128, 4,214,227,249,242,233,236,+ 236,233, 99,128, 4, 21,230,242,225,235,244,245,114,128, 33, 17,+ 231,242,225,246,101,129, 0,204, 13,234,243,237,225,236,108,128,+ 247,236,232,239,239,235,225,226,239,246,101,128, 30,200,105, 3,+ 14, 6, 14, 17, 14, 32,227,249,242,233,236,236,233, 99,128, 4,+ 24,238,246,229,242,244,229,228,226,242,229,246,101,128, 2, 10,+ 243,232,239,242,244,227,249,242,233,236,236,233, 99,128, 4, 25,+ 109, 2, 14, 54, 14, 75,225,227,242,239,110,129, 1, 42, 14, 64,+ 227,249,242,233,236,236,233, 99,128, 4,226,239,238,239,243,240,+ 225,227,101,128,255, 41,238,233,225,242,237,229,238,233,225,110,+ 128, 5, 59,111, 3, 14,107, 14,118, 14,126,227,249,242,233,236,+ 236,233, 99,128, 4, 1,231,239,238,229,107,128, 1, 46,244, 97,+ 131, 3,153, 14,137, 14,147, 14,158,225,230,242,233,227,225,110,+ 128, 1,150,228,233,229,242,229,243,233,115,128, 3,170,244,239,+ 238,239,115,128, 3,138,115, 2, 14,172, 14,179,237,225,236,108,+ 128,247,105,244,242,239,235,101,128, 1,151,244,233,236,228,101,+ 129, 1, 40, 14,197,226,229,236,239,119,128, 30, 44,250,232,233,+ 244,243, 97, 2, 14,216, 14,227,227,249,242,233,236,236,233, 99,+ 128, 4,116,228,226,236,231,242,225,246,229,227,249,242,233,236,+ 236,233, 99,128, 4,118, 74,134, 0, 74, 15, 6, 15, 18, 15, 41,+ 15, 53, 15, 67, 15, 79,225,225,242,237,229,238,233,225,110,128,+ 5, 65,227,233,242, 99, 2, 15, 27, 15, 32,236,101,128, 36,191,+ 245,237,230,236,229,120,128, 1, 52,229,227,249,242,233,236,236,+ 233, 99,128, 4, 8,232,229,232,225,242,237,229,238,233,225,110,+ 128, 5, 75,237,239,238,239,243,240,225,227,101,128,255, 42,243,+ 237,225,236,108,128,247,106, 75,140, 0, 75, 15,115, 15,125, 15,+ 135, 16, 18, 16, 65, 16, 76, 16,106, 16,143, 16,156, 16,168, 16,+ 180, 16,208,194,243,241,245,225,242,101,128, 51,133,203,243,241,+ 245,225,242,101,128, 51,205, 97, 7, 15,151, 15,169, 15,191, 15,+ 211, 15,226, 15,232, 15,249,226,225,243,232,235,233,242,227,249,+ 242,233,236,236,233, 99,128, 4,160, 99, 2, 15,175, 15,181,245,+ 244,101,128, 30, 48,249,242,233,236,236,233, 99,128, 4, 26,228,+ 229,243,227,229,238,228,229,242,227,249,242,233,236,236,233, 99,+ 128, 4,154,232,239,239,235,227,249,242,233,236,236,233, 99,128,+ 4,195,240,240, 97,128, 3,154,243,244,242,239,235,229,227,249,+ 242,233,236,236,233, 99,128, 4,158,246,229,242,244,233,227,225,+ 236,243,244,242,239,235,229,227,249,242,233,236,236,233, 99,128,+ 4,156, 99, 4, 16, 28, 16, 35, 16, 44, 16, 52,225,242,239,110,+ 128, 1,232,229,228,233,236,236, 97,128, 1, 54,233,242,227,236,+ 101,128, 36,192,239,237,237,225,225,227,227,229,238,116,128, 1,+ 54,228,239,244,226,229,236,239,119,128, 30, 50,101, 2, 16, 82,+ 16, 94,232,225,242,237,229,238,233,225,110,128, 5, 84,238,225,+ 242,237,229,238,233,225,110,128, 5, 63,104, 3, 16,114, 16,126,+ 16,137,225,227,249,242,233,236,236,233, 99,128, 4, 37,229,233,+ 227,239,240,244,233, 99,128, 3,230,239,239,107,128, 1,152,234,+ 229,227,249,242,233,236,236,233, 99,128, 4, 12,236,233,238,229,+ 226,229,236,239,119,128, 30, 52,237,239,238,239,243,240,225,227,+ 101,128,255, 43,239,240,240, 97, 2, 16,189, 16,200,227,249,242,+ 233,236,236,233, 99,128, 4,128,231,242,229,229,107,128, 3,222,+ 115, 2, 16,214, 16,226,233,227,249,242,233,236,236,233, 99,128,+ 4,110,237,225,236,108,128,247,107, 76,138, 0, 76, 17, 1, 17,+ 5, 17, 9, 17, 29, 17, 95, 17,133, 17,147, 17,165, 17,177, 17,+ 189, 74,128, 1,199, 76,128,246,191, 97, 2, 17, 15, 17, 22,227,+ 245,244,101,128, 1, 57,237,226,228, 97,128, 3,155, 99, 4, 17,+ 39, 17, 46, 17, 55, 17, 82,225,242,239,110,128, 1, 61,229,228,+ 233,236,236, 97,128, 1, 59,233,242, 99, 2, 17, 63, 17, 68,236,+ 101,128, 36,193,245,237,230,236,229,248,226,229,236,239,119,128,+ 30, 60,239,237,237,225,225,227,227,229,238,116,128, 1, 59,228,+ 239,116,130, 1, 63, 17,105, 17,114,225,227,227,229,238,116,128,+ 1, 63,226,229,236,239,119,129, 30, 54, 17,124,237,225,227,242,+ 239,110,128, 30, 56,233,247,238,225,242,237,229,238,233,225,110,+ 128, 5, 60,106,129, 1,200, 17,153,229,227,249,242,233,236,236,+ 233, 99,128, 4, 9,236,233,238,229,226,229,236,239,119,128, 30,+ 58,237,239,238,239,243,240,225,227,101,128,255, 44,115, 2, 17,+ 195, 17,212,236,225,243,104,129, 1, 65, 17,204,243,237,225,236,+ 108,128,246,249,237,225,236,108,128,247,108, 77,137, 0, 77, 17,+ 241, 17,251, 18, 24, 18, 33, 18, 58, 18, 71, 18, 83, 18, 91, 18,+ 100,194,243,241,245,225,242,101,128, 51,134,225, 99, 2, 18, 2,+ 18, 18,242,239,110,129,246,208, 18, 10,243,237,225,236,108,128,+ 247,175,245,244,101,128, 30, 62,227,233,242,227,236,101,128, 36,+ 194,228,239,116, 2, 18, 41, 18, 50,225,227,227,229,238,116,128,+ 30, 64,226,229,236,239,119,128, 30, 66,229,238,225,242,237,229,+ 238,233,225,110,128, 5, 68,237,239,238,239,243,240,225,227,101,+ 128,255, 45,243,237,225,236,108,128,247,109,244,245,242,238,229,+ 100,128, 1,156,117,128, 3,156, 78,141, 0, 78, 18,134, 18,138,+ 18,146, 18,212, 18,237, 18,248, 19, 3, 19, 21, 19, 33, 19, 45,+ 19, 58, 19, 66, 19, 84, 74,128, 1,202,225,227,245,244,101,128,+ 1, 67, 99, 4, 18,156, 18,163, 18,172, 18,199,225,242,239,110,+ 128, 1, 71,229,228,233,236,236, 97,128, 1, 69,233,242, 99, 2,+ 18,180, 18,185,236,101,128, 36,195,245,237,230,236,229,248,226,+ 229,236,239,119,128, 30, 74,239,237,237,225,225,227,227,229,238,+ 116,128, 1, 69,228,239,116, 2, 18,220, 18,229,225,227,227,229,+ 238,116,128, 30, 68,226,229,236,239,119,128, 30, 70,232,239,239,+ 235,236,229,230,116,128, 1,157,233,238,229,242,239,237,225,110,+ 128, 33,104,106,129, 1,203, 19, 9,229,227,249,242,233,236,236,+ 233, 99,128, 4, 10,236,233,238,229,226,229,236,239,119,128, 30,+ 72,237,239,238,239,243,240,225,227,101,128,255, 46,239,247,225,+ 242,237,229,238,233,225,110,128, 5, 70,243,237,225,236,108,128,+ 247,110,244,233,236,228,101,129, 0,209, 19, 76,243,237,225,236,+ 108,128,247,241,117,128, 3,157, 79,141, 0, 79, 19,118, 19,132,+ 19,150, 19,203, 20, 78, 20,152, 20,187, 21, 48, 21, 69, 21,213,+ 21,223, 21,254, 22, 53, 69,129, 1, 82, 19,124,243,237,225,236,+ 108,128,246,250,225,227,245,244,101,129, 0,211, 19,142,243,237,+ 225,236,108,128,247,243, 98, 2, 19,156, 19,196,225,242,242,229,+ 100, 2, 19,166, 19,177,227,249,242,233,236,236,233, 99,128, 4,+ 232,228,233,229,242,229,243,233,243,227,249,242,233,236,236,233,+ 99,128, 4,234,242,229,246,101,128, 1, 78, 99, 4, 19,213, 19,+ 220, 19,235, 20, 68,225,242,239,110,128, 1,209,229,238,244,229,+ 242,229,228,244,233,236,228,101,128, 1,159,233,242, 99, 2, 19,+ 243, 19,248,236,101,128, 36,196,245,237,230,236,229,120,134, 0,+ 212, 20, 13, 20, 21, 20, 32, 20, 40, 20, 52, 20, 60,225,227,245,+ 244,101,128, 30,208,228,239,244,226,229,236,239,119,128, 30,216,+ 231,242,225,246,101,128, 30,210,232,239,239,235,225,226,239,246,+ 101,128, 30,212,243,237,225,236,108,128,247,244,244,233,236,228,+ 101,128, 30,214,249,242,233,236,236,233, 99,128, 4, 30,100, 3,+ 20, 86, 20,109, 20,142,226,108, 2, 20, 93, 20,101,225,227,245,+ 244,101,128, 1, 80,231,242,225,246,101,128, 2, 12,233,229,242,+ 229,243,233,115,130, 0,214, 20,123, 20,134,227,249,242,233,236,+ 236,233, 99,128, 4,230,243,237,225,236,108,128,247,246,239,244,+ 226,229,236,239,119,128, 30,204,103, 2, 20,158, 20,170,239,238,+ 229,235,243,237,225,236,108,128,246,251,242,225,246,101,129, 0,+ 210, 20,179,243,237,225,236,108,128,247,242,104, 4, 20,197, 20,+ 208, 20,212, 21, 34,225,242,237,229,238,233,225,110,128, 5, 85,+ 109,128, 33, 38,111, 2, 20,218, 20,228,239,235,225,226,239,246,+ 101,128, 30,206,242,110,133, 1,160, 20,243, 20,251, 21, 6, 21,+ 14, 21, 26,225,227,245,244,101,128, 30,218,228,239,244,226,229,+ 236,239,119,128, 30,226,231,242,225,246,101,128, 30,220,232,239,+ 239,235,225,226,239,246,101,128, 30,222,244,233,236,228,101,128,+ 30,224,245,238,231,225,242,245,237,236,225,245,116,128, 1, 80,+ 105,129, 1,162, 21, 54,238,246,229,242,244,229,228,226,242,229,+ 246,101,128, 2, 14,109, 4, 21, 79, 21,107, 21,184, 21,202,225,+ 227,242,239,110,130, 1, 76, 21, 91, 21, 99,225,227,245,244,101,+ 128, 30, 82,231,242,225,246,101,128, 30, 80,229,231, 97,132, 33,+ 38, 21,121, 21,132, 21,140, 21,156,227,249,242,233,236,236,233,+ 99,128, 4, 96,231,242,229,229,107,128, 3,169,242,239,245,238,+ 228,227,249,242,233,236,236,233, 99,128, 4,122,116, 2, 21,162,+ 21,177,233,244,236,239,227,249,242,233,236,236,233, 99,128, 4,+ 124,239,238,239,115,128, 3,143,233,227,242,239,110,129, 3,159,+ 21,194,244,239,238,239,115,128, 3,140,239,238,239,243,240,225,+ 227,101,128,255, 47,238,229,242,239,237,225,110,128, 33, 96,111,+ 2, 21,229, 21,248,231,239,238,229,107,129, 1,234, 21,239,237,+ 225,227,242,239,110,128, 1,236,240,229,110,128, 1,134,115, 3,+ 22, 6, 22, 33, 22, 40,236,225,243,104,130, 0,216, 22, 17, 22,+ 25,225,227,245,244,101,128, 1,254,243,237,225,236,108,128,247,+ 248,237,225,236,108,128,247,111,244,242,239,235,229,225,227,245,+ 244,101,128, 1,254,116, 2, 22, 59, 22, 70,227,249,242,233,236,+ 236,233, 99,128, 4,126,233,236,228,101,131, 0,213, 22, 83, 22,+ 91, 22,102,225,227,245,244,101,128, 30, 76,228,233,229,242,229,+ 243,233,115,128, 30, 78,243,237,225,236,108,128,247,245, 80,136,+ 0, 80, 22,130, 22,138, 22,147, 22,159, 22,211, 22,227, 22,246,+ 23, 2,225,227,245,244,101,128, 30, 84,227,233,242,227,236,101,+ 128, 36,197,228,239,244,225,227,227,229,238,116,128, 30, 86,101,+ 3, 22,167, 22,178, 22,190,227,249,242,233,236,236,233, 99,128,+ 4, 31,232,225,242,237,229,238,233,225,110,128, 5, 74,237,233,+ 228,228,236,229,232,239,239,235,227,249,242,233,236,236,233, 99,+ 128, 4,166,104, 2, 22,217, 22,221,105,128, 3,166,239,239,107,+ 128, 1,164,105,129, 3,160, 22,233,247,242,225,242,237,229,238,+ 233,225,110,128, 5, 83,237,239,238,239,243,240,225,227,101,128,+ 255, 48,115, 2, 23, 8, 23, 25,105,129, 3,168, 23, 14,227,249,+ 242,233,236,236,233, 99,128, 4,112,237,225,236,108,128,247,112,+ 81,131, 0, 81, 23, 42, 23, 51, 23, 63,227,233,242,227,236,101,+ 128, 36,198,237,239,238,239,243,240,225,227,101,128,255, 49,243,+ 237,225,236,108,128,247,113, 82,138, 0, 82, 23, 95, 23,119, 23,+ 166, 23,217, 23,230, 23,240, 23,245, 24, 19, 24, 31, 24, 43, 97,+ 2, 23,101, 23,112,225,242,237,229,238,233,225,110,128, 5, 76,+ 227,245,244,101,128, 1, 84, 99, 4, 23,129, 23,136, 23,145, 23,+ 153,225,242,239,110,128, 1, 88,229,228,233,236,236, 97,128, 1,+ 86,233,242,227,236,101,128, 36,199,239,237,237,225,225,227,227,+ 229,238,116,128, 1, 86,100, 2, 23,172, 23,182,226,236,231,242,+ 225,246,101,128, 2, 16,239,116, 2, 23,189, 23,198,225,227,227,+ 229,238,116,128, 30, 88,226,229,236,239,119,129, 30, 90, 23,208,+ 237,225,227,242,239,110,128, 30, 92,229,232,225,242,237,229,238,+ 233,225,110,128, 5, 80,230,242,225,235,244,245,114,128, 33, 28,+ 232,111,128, 3,161,233,110, 2, 23,252, 24, 5,231,243,237,225,+ 236,108,128,246,252,246,229,242,244,229,228,226,242,229,246,101,+ 128, 2, 18,236,233,238,229,226,229,236,239,119,128, 30, 94,237,+ 239,238,239,243,240,225,227,101,128,255, 50,243,237,225,236,108,+ 129,247,114, 24, 53,233,238,246,229,242,244,229,100,129, 2,129,+ 24, 66,243,245,240,229,242,233,239,114,128, 2,182, 83,139, 0,+ 83, 24,103, 26, 17, 26, 55, 26,182, 26,221, 26,250, 27, 84, 27,+ 105, 27,117, 27,135, 27,143, 70, 6, 24,117, 24,209, 24,241, 25,+ 77, 25,119, 25,221, 48, 9, 24,137, 24,145, 24,153, 24,161, 24,+ 169, 24,177, 24,185, 24,193, 24,201,177,176,176,176, 48,128, 37,+ 12,178,176,176,176, 48,128, 37, 20,179,176,176,176, 48,128, 37,+ 16,180,176,176,176, 48,128, 37, 24,181,176,176,176, 48,128, 37,+ 60,182,176,176,176, 48,128, 37, 44,183,176,176,176, 48,128, 37,+ 52,184,176,176,176, 48,128, 37, 28,185,176,176,176, 48,128, 37,+ 36, 49, 3, 24,217, 24,225, 24,233,176,176,176,176, 48,128, 37,+ 0,177,176,176,176, 48,128, 37, 2,185,176,176,176, 48,128, 37,+ 97, 50, 9, 25, 5, 25, 13, 25, 21, 25, 29, 25, 37, 25, 45, 25,+ 53, 25, 61, 25, 69,176,176,176,176, 48,128, 37, 98,177,176,176,+ 176, 48,128, 37, 86,178,176,176,176, 48,128, 37, 85,179,176,176,+ 176, 48,128, 37, 99,180,176,176,176, 48,128, 37, 81,181,176,176,+ 176, 48,128, 37, 87,182,176,176,176, 48,128, 37, 93,183,176,176,+ 176, 48,128, 37, 92,184,176,176,176, 48,128, 37, 91, 51, 4, 25,+ 87, 25, 95, 25,103, 25,111,182,176,176,176, 48,128, 37, 94,183,+ 176,176,176, 48,128, 37, 95,184,176,176,176, 48,128, 37, 90,185,+ 176,176,176, 48,128, 37, 84, 52, 10, 25,141, 25,149, 25,157, 25,+ 165, 25,173, 25,181, 25,189, 25,197, 25,205, 25,213,176,176,176,+ 176, 48,128, 37,105,177,176,176,176, 48,128, 37,102,178,176,176,+ 176, 48,128, 37, 96,179,176,176,176, 48,128, 37, 80,180,176,176,+ 176, 48,128, 37,108,181,176,176,176, 48,128, 37,103,182,176,176,+ 176, 48,128, 37,104,183,176,176,176, 48,128, 37,100,184,176,176,+ 176, 48,128, 37,101,185,176,176,176, 48,128, 37, 89, 53, 5, 25,+ 233, 25,241, 25,249, 26, 1, 26, 9,176,176,176,176, 48,128, 37,+ 88,177,176,176,176, 48,128, 37, 82,178,176,176,176, 48,128, 37,+ 83,179,176,176,176, 48,128, 37,107,180,176,176,176, 48,128, 37,+ 106, 97, 2, 26, 23, 26, 44,227,245,244,101,129, 1, 90, 26, 32,+ 228,239,244,225,227,227,229,238,116,128, 30,100,237,240,233,231,+ 242,229,229,107,128, 3,224, 99, 5, 26, 67, 26, 98, 26,107, 26,+ 147, 26,169,225,242,239,110,130, 1, 96, 26, 78, 26, 90,228,239,+ 244,225,227,227,229,238,116,128, 30,102,243,237,225,236,108,128,+ 246,253,229,228,233,236,236, 97,128, 1, 94,232,247, 97,130, 1,+ 143, 26,117, 26,128,227,249,242,233,236,236,233, 99,128, 4,216,+ 228,233,229,242,229,243,233,243,227,249,242,233,236,236,233, 99,+ 128, 4,218,233,242, 99, 2, 26,155, 26,160,236,101,128, 36,200,+ 245,237,230,236,229,120,128, 1, 92,239,237,237,225,225,227,227,+ 229,238,116,128, 2, 24,228,239,116, 2, 26,190, 26,199,225,227,+ 227,229,238,116,128, 30, 96,226,229,236,239,119,129, 30, 98, 26,+ 209,228,239,244,225,227,227,229,238,116,128, 30,104,101, 2, 26,+ 227, 26,239,232,225,242,237,229,238,233,225,110,128, 5, 77,246,+ 229,238,242,239,237,225,110,128, 33,102,104, 5, 27, 6, 27, 34,+ 27, 48, 27, 59, 27, 72, 97, 2, 27, 12, 27, 23,225,242,237,229,+ 238,233,225,110,128, 5, 71,227,249,242,233,236,236,233, 99,128,+ 4, 40,227,232,225,227,249,242,233,236,236,233, 99,128, 4, 41,+ 229,233,227,239,240,244,233, 99,128, 3,226,232,225,227,249,242,+ 233,236,236,233, 99,128, 4,186,233,237,225,227,239,240,244,233,+ 99,128, 3,236,105, 2, 27, 90, 27, 96,231,237, 97,128, 3,163,+ 248,242,239,237,225,110,128, 33,101,237,239,238,239,243,240,225,+ 227,101,128,255, 51,239,230,244,243,233,231,238,227,249,242,233,+ 236,236,233, 99,128, 4, 44,243,237,225,236,108,128,247,115,244,+ 233,231,237,225,231,242,229,229,107,128, 3,218, 84,141, 0, 84,+ 27,186, 27,191, 27,197, 28, 7, 28, 32, 28, 96, 28,147, 28,177,+ 28,189, 28,201, 28,246, 29, 6, 29, 46,225,117,128, 3,164,226,+ 225,114,128, 1,102, 99, 4, 27,207, 27,214, 27,223, 27,250,225,+ 242,239,110,128, 1,100,229,228,233,236,236, 97,128, 1, 98,233,+ 242, 99, 2, 27,231, 27,236,236,101,128, 36,201,245,237,230,236,+ 229,248,226,229,236,239,119,128, 30,112,239,237,237,225,225,227,+ 227,229,238,116,128, 1, 98,228,239,116, 2, 28, 15, 28, 24,225,+ 227,227,229,238,116,128, 30,106,226,229,236,239,119,128, 30,108,+ 101, 4, 28, 42, 28, 53, 28, 73, 28, 82,227,249,242,233,236,236,+ 233, 99,128, 4, 34,228,229,243,227,229,238,228,229,242,227,249,+ 242,233,236,236,233, 99,128, 4,172,238,242,239,237,225,110,128,+ 33,105,244,243,229,227,249,242,233,236,236,233, 99,128, 4,180,+ 104, 3, 28,104, 28,110, 28,136,229,244, 97,128, 3,152,111, 2,+ 28,116, 28,121,239,107,128, 1,172,242,110,129, 0,222, 28,128,+ 243,237,225,236,108,128,247,254,242,229,229,242,239,237,225,110,+ 128, 33, 98,105, 2, 28,153, 28,164,236,228,229,243,237,225,236,+ 108,128,246,254,247,238,225,242,237,229,238,233,225,110,128, 5,+ 79,236,233,238,229,226,229,236,239,119,128, 30,110,237,239,238,+ 239,243,240,225,227,101,128,255, 52,111, 2, 28,207, 28,218,225,+ 242,237,229,238,233,225,110,128, 5, 57,238,101, 3, 28,227, 28,+ 234, 28,240,230,233,246,101,128, 1,188,243,233,120,128, 1,132,+ 244,247,111,128, 1,167,242,229,244,242,239,230,236,229,248,232,+ 239,239,107,128, 1,174,115, 3, 29, 14, 29, 26, 29, 39,229,227,+ 249,242,233,236,236,233, 99,128, 4, 38,232,229,227,249,242,233,+ 236,236,233, 99,128, 4, 11,237,225,236,108,128,247,116,119, 2,+ 29, 52, 29, 64,229,236,246,229,242,239,237,225,110,128, 33,107,+ 239,242,239,237,225,110,128, 33, 97, 85,142, 0, 85, 29,105, 29,+ 123, 29,131, 29,198, 30, 69, 30, 87, 30,198, 30,214, 30,226, 31,+ 21, 31, 30, 31,142, 31,149, 31,219,225,227,245,244,101,129, 0,+ 218, 29,115,243,237,225,236,108,128,247,250,226,242,229,246,101,+ 128, 1,108, 99, 3, 29,139, 29,146, 29,188,225,242,239,110,128,+ 1,211,233,242, 99, 2, 29,154, 29,159,236,101,128, 36,202,245,+ 237,230,236,229,120,130, 0,219, 29,172, 29,180,226,229,236,239,+ 119,128, 30,118,243,237,225,236,108,128,247,251,249,242,233,236,+ 236,233, 99,128, 4, 35,100, 3, 29,206, 29,229, 30, 59,226,108,+ 2, 29,213, 29,221,225,227,245,244,101,128, 1,112,231,242,225,+ 246,101,128, 2, 20,233,229,242,229,243,233,115,134, 0,220, 29,+ 251, 30, 3, 30, 11, 30, 34, 30, 42, 30, 51,225,227,245,244,101,+ 128, 1,215,226,229,236,239,119,128, 30,114, 99, 2, 30, 17, 30,+ 24,225,242,239,110,128, 1,217,249,242,233,236,236,233, 99,128,+ 4,240,231,242,225,246,101,128, 1,219,237,225,227,242,239,110,+ 128, 1,213,243,237,225,236,108,128,247,252,239,244,226,229,236,+ 239,119,128, 30,228,231,242,225,246,101,129, 0,217, 30, 79,243,+ 237,225,236,108,128,247,249,104, 2, 30, 93, 30,171,111, 2, 30,+ 99, 30,109,239,235,225,226,239,246,101,128, 30,230,242,110,133,+ 1,175, 30,124, 30,132, 30,143, 30,151, 30,163,225,227,245,244,+ 101,128, 30,232,228,239,244,226,229,236,239,119,128, 30,240,231,+ 242,225,246,101,128, 30,234,232,239,239,235,225,226,239,246,101,+ 128, 30,236,244,233,236,228,101,128, 30,238,245,238,231,225,242,+ 245,237,236,225,245,116,129, 1,112, 30,187,227,249,242,233,236,+ 236,233, 99,128, 4,242,233,238,246,229,242,244,229,228,226,242,+ 229,246,101,128, 2, 22,235,227,249,242,233,236,236,233, 99,128,+ 4,120,109, 2, 30,232, 31, 10,225,227,242,239,110,130, 1,106,+ 30,244, 30,255,227,249,242,233,236,236,233, 99,128, 4,238,228,+ 233,229,242,229,243,233,115,128, 30,122,239,238,239,243,240,225,+ 227,101,128,255, 53,239,231,239,238,229,107,128, 1,114,240,243,+ 233,236,239,110,133, 3,165, 31, 49, 31, 53, 31, 90, 31,121, 31,+ 134, 49,128, 3,210, 97, 2, 31, 59, 31, 81,227,245,244,229,232,+ 239,239,235,243,249,237,226,239,236,231,242,229,229,107,128, 3,+ 211,230,242,233,227,225,110,128, 1,177,228,233,229,242,229,243,+ 233,115,129, 3,171, 31,103,232,239,239,235,243,249,237,226,239,+ 236,231,242,229,229,107,128, 3,212,232,239,239,235,243,249,237,+ 226,239,108,128, 3,210,244,239,238,239,115,128, 3,142,242,233,+ 238,103,128, 1,110,115, 3, 31,157, 31,172, 31,179,232,239,242,+ 244,227,249,242,233,236,236,233, 99,128, 4, 14,237,225,236,108,+ 128,247,117,244,242,225,233,231,232,116, 2, 31,191, 31,202,227,+ 249,242,233,236,236,233, 99,128, 4,174,243,244,242,239,235,229,+ 227,249,242,233,236,236,233, 99,128, 4,176,244,233,236,228,101,+ 130, 1,104, 31,231, 31,239,225,227,245,244,101,128, 30,120,226,+ 229,236,239,119,128, 30,116, 86,136, 0, 86, 32, 11, 32, 20, 32,+ 31, 32, 60, 32, 67, 32, 79, 32, 91, 32, 99,227,233,242,227,236,+ 101,128, 36,203,228,239,244,226,229,236,239,119,128, 30,126,101,+ 2, 32, 37, 32, 48,227,249,242,233,236,236,233, 99,128, 4, 18,+ 247,225,242,237,229,238,233,225,110,128, 5, 78,232,239,239,107,+ 128, 1,178,237,239,238,239,243,240,225,227,101,128,255, 54,239,+ 225,242,237,229,238,233,225,110,128, 5, 72,243,237,225,236,108,+ 128,247,118,244,233,236,228,101,128, 30,124, 87,134, 0, 87, 32,+ 123, 32,131, 32,154, 32,194, 32,202, 32,214,225,227,245,244,101,+ 128, 30,130,227,233,242, 99, 2, 32,140, 32,145,236,101,128, 36,+ 204,245,237,230,236,229,120,128, 1,116,100, 2, 32,160, 32,170,+ 233,229,242,229,243,233,115,128, 30,132,239,116, 2, 32,177, 32,+ 186,225,227,227,229,238,116,128, 30,134,226,229,236,239,119,128,+ 30,136,231,242,225,246,101,128, 30,128,237,239,238,239,243,240,+ 225,227,101,128,255, 55,243,237,225,236,108,128,247,119, 88,134,+ 0, 88, 32,238, 32,247, 33, 18, 33, 31, 33, 35, 33, 47,227,233,+ 242,227,236,101,128, 36,205,100, 2, 32,253, 33, 7,233,229,242,+ 229,243,233,115,128, 30,140,239,244,225,227,227,229,238,116,128,+ 30,138,229,232,225,242,237,229,238,233,225,110,128, 5, 61,105,+ 128, 3,158,237,239,238,239,243,240,225,227,101,128,255, 56,243,+ 237,225,236,108,128,247,120, 89,139, 0, 89, 33, 81, 33,116, 33,+ 139, 33,189, 33,228, 33,236, 33,253, 34, 40, 34, 52, 34, 60, 34,+ 68, 97, 2, 33, 87, 33,104,227,245,244,101,129, 0,221, 33, 96,+ 243,237,225,236,108,128,247,253,244,227,249,242,233,236,236,233,+ 99,128, 4, 98,227,233,242, 99, 2, 33,125, 33,130,236,101,128,+ 36,206,245,237,230,236,229,120,128, 1,118,100, 2, 33,145, 33,+ 165,233,229,242,229,243,233,115,129, 1,120, 33,157,243,237,225,+ 236,108,128,247,255,239,116, 2, 33,172, 33,181,225,227,227,229,+ 238,116,128, 30,142,226,229,236,239,119,128, 30,244,229,114, 2,+ 33,196, 33,208,233,227,249,242,233,236,236,233, 99,128, 4, 43,+ 245,228,233,229,242,229,243,233,243,227,249,242,233,236,236,233,+ 99,128, 4,248,231,242,225,246,101,128, 30,242,232,239,239,107,+ 129, 1,179, 33,245,225,226,239,246,101,128, 30,246,105, 3, 34,+ 5, 34, 16, 34, 27,225,242,237,229,238,233,225,110,128, 5, 69,+ 227,249,242,233,236,236,233, 99,128, 4, 7,247,238,225,242,237,+ 229,238,233,225,110,128, 5, 82,237,239,238,239,243,240,225,227,+ 101,128,255, 57,243,237,225,236,108,128,247,121,244,233,236,228,+ 101,128, 30,248,245,115, 2, 34, 75, 34,113,226,233,103, 2, 34,+ 83, 34, 94,227,249,242,233,236,236,233, 99,128, 4,106,233,239,+ 244,233,230,233,229,228,227,249,242,233,236,236,233, 99,128, 4,+ 108,236,233,244,244,236,101, 2, 34,124, 34,135,227,249,242,233,+ 236,236,233, 99,128, 4,102,233,239,244,233,230,233,229,228,227,+ 249,242,233,236,236,233, 99,128, 4,104, 90,136, 0, 90, 34,174,+ 34,198, 34,243, 35, 14, 35, 81, 35,173, 35,185, 35,197, 97, 2,+ 34,180, 34,191,225,242,237,229,238,233,225,110,128, 5, 54,227,+ 245,244,101,128, 1,121, 99, 2, 34,204, 34,221,225,242,239,110,+ 129, 1,125, 34,213,243,237,225,236,108,128,246,255,233,242, 99,+ 2, 34,229, 34,234,236,101,128, 36,207,245,237,230,236,229,120,+ 128, 30,144,228,239,116,130, 1,123, 34,253, 35, 6,225,227,227,+ 229,238,116,128, 1,123,226,229,236,239,119,128, 30,146,101, 3,+ 35, 22, 35, 33, 35, 76,227,249,242,233,236,236,233, 99,128, 4,+ 23,100, 2, 35, 39, 35, 58,229,243,227,229,238,228,229,242,227,+ 249,242,233,236,236,233, 99,128, 4,152,233,229,242,229,243,233,+ 243,227,249,242,233,236,236,233, 99,128, 4,222,244, 97,128, 3,+ 150,232,101, 4, 35, 92, 35,103, 35,119, 35,130,225,242,237,229,+ 238,233,225,110,128, 5, 58,226,242,229,246,229,227,249,242,233,+ 236,236,233, 99,128, 4,193,227,249,242,233,236,236,233, 99,128,+ 4, 22,100, 2, 35,136, 35,155,229,243,227,229,238,228,229,242,+ 227,249,242,233,236,236,233, 99,128, 4,150,233,229,242,229,243,+ 233,243,227,249,242,233,236,236,233, 99,128, 4,220,236,233,238,+ 229,226,229,236,239,119,128, 30,148,237,239,238,239,243,240,225,+ 227,101,128,255, 58,115, 2, 35,203, 35,210,237,225,236,108,128,+ 247,122,244,242,239,235,101,128, 1,181, 97,149, 0, 97, 36, 8,+ 36,144, 37, 35, 37,211, 38, 55, 38, 91, 45, 10, 45, 47, 45, 74,+ 46, 43, 46, 81, 47,170, 47,242, 48,197, 48,206, 49, 79, 51, 87,+ 52, 77, 52,124, 53, 19, 53, 33, 97, 7, 36, 24, 36, 34, 36, 41,+ 36, 48, 36, 73, 36, 89, 36,100,226,229,238,231,225,236,105,128,+ 9,134,227,245,244,101,128, 0,225,228,229,246, 97,128, 9, 6,+ 231,117, 2, 36, 55, 36, 64,234,225,242,225,244,105,128, 10,134,+ 242,237,245,235,232,105,128, 10, 6,237,225,244,242,225,231,245,+ 242,237,245,235,232,105,128, 10, 62,242,245,243,241,245,225,242,+ 101,128, 51, 3,246,239,247,229,236,243,233,231,110, 3, 36,116,+ 36,126, 36,133,226,229,238,231,225,236,105,128, 9,190,228,229,+ 246, 97,128, 9, 62,231,245,234,225,242,225,244,105,128, 10,190,+ 98, 4, 36,154, 36,195, 36,204, 36,214,226,242,229,246,233,225,+ 244,233,239,110, 2, 36,169, 36,184,237,225,242,235,225,242,237,+ 229,238,233,225,110,128, 5, 95,243,233,231,238,228,229,246, 97,+ 128, 9,112,229,238,231,225,236,105,128, 9,133,239,240,239,237,+ 239,230,111,128, 49, 26,242,229,246,101,134, 1, 3, 36,233, 36,+ 241, 36,252, 37, 7, 37, 15, 37, 27,225,227,245,244,101,128, 30,+ 175,227,249,242,233,236,236,233, 99,128, 4,209,228,239,244,226,+ 229,236,239,119,128, 30,183,231,242,225,246,101,128, 30,177,232,+ 239,239,235,225,226,239,246,101,128, 30,179,244,233,236,228,101,+ 128, 30,181, 99, 4, 37, 45, 37, 52, 37,131, 37,201,225,242,239,+ 110,128, 1,206,233,242, 99, 2, 37, 60, 37, 65,236,101,128, 36,+ 208,245,237,230,236,229,120,133, 0,226, 37, 84, 37, 92, 37,103,+ 37,111, 37,123,225,227,245,244,101,128, 30,165,228,239,244,226,+ 229,236,239,119,128, 30,173,231,242,225,246,101,128, 30,167,232,+ 239,239,235,225,226,239,246,101,128, 30,169,244,233,236,228,101,+ 128, 30,171,245,244,101,133, 0,180, 37,147, 37,158, 37,175, 37,+ 182, 37,191,226,229,236,239,247,227,237, 98,128, 3, 23, 99, 2,+ 37,164, 37,169,237, 98,128, 3, 1,239,237, 98,128, 3, 1,228,+ 229,246, 97,128, 9, 84,236,239,247,237,239,100,128, 2,207,244,+ 239,238,229,227,237, 98,128, 3, 65,249,242,233,236,236,233, 99,+ 128, 4, 48,100, 5, 37,223, 37,233, 37,247, 37,253, 38, 31,226,+ 236,231,242,225,246,101,128, 2, 1,228,225,235,231,245,242,237,+ 245,235,232,105,128, 10,113,229,246, 97,128, 9, 5,233,229,242,+ 229,243,233,115,130, 0,228, 38, 11, 38, 22,227,249,242,233,236,+ 236,233, 99,128, 4,211,237,225,227,242,239,110,128, 1,223,239,+ 116, 2, 38, 38, 38, 46,226,229,236,239,119,128, 30,161,237,225,+ 227,242,239,110,128, 1,225,101,131, 0,230, 38, 65, 38, 73, 38,+ 82,225,227,245,244,101,128, 1,253,235,239,242,229,225,110,128,+ 49, 80,237,225,227,242,239,110,128, 1,227,230,233,105, 6, 38,+ 107, 38,127, 41, 64, 41, 70, 41, 85, 44,185, 48, 2, 38,113, 38,+ 120,176,178,176, 56,128, 32, 21,184,185,180, 49,128, 32,164,177,+ 48, 3, 38,136, 40,160, 41, 39, 48, 9, 38,156, 38,176, 38,238,+ 39, 44, 39,106, 39,168, 39,230, 40, 36, 40, 98, 49, 3, 38,164,+ 38,168, 38,172, 55,128, 4, 16, 56,128, 4, 17, 57,128, 4, 18,+ 50, 10, 38,198, 38,202, 38,206, 38,210, 38,214, 38,218, 38,222,+ 38,226, 38,230, 38,234, 48,128, 4, 19, 49,128, 4, 20, 50,128,+ 4, 21, 51,128, 4, 1, 52,128, 4, 22, 53,128, 4, 23, 54,128,+ 4, 24, 55,128, 4, 25, 56,128, 4, 26, 57,128, 4, 27, 51, 10,+ 39, 4, 39, 8, 39, 12, 39, 16, 39, 20, 39, 24, 39, 28, 39, 32,+ 39, 36, 39, 40, 48,128, 4, 28, 49,128, 4, 29, 50,128, 4, 30,+ 51,128, 4, 31, 52,128, 4, 32, 53,128, 4, 33, 54,128, 4, 34,+ 55,128, 4, 35, 56,128, 4, 36, 57,128, 4, 37, 52, 10, 39, 66,+ 39, 70, 39, 74, 39, 78, 39, 82, 39, 86, 39, 90, 39, 94, 39, 98,+ 39,102, 48,128, 4, 38, 49,128, 4, 39, 50,128, 4, 40, 51,128,+ 4, 41, 52,128, 4, 42, 53,128, 4, 43, 54,128, 4, 44, 55,128,+ 4, 45, 56,128, 4, 46, 57,128, 4, 47, 53, 10, 39,128, 39,132,+ 39,136, 39,140, 39,144, 39,148, 39,152, 39,156, 39,160, 39,164,+ 48,128, 4,144, 49,128, 4, 2, 50,128, 4, 3, 51,128, 4, 4,+ 52,128, 4, 5, 53,128, 4, 6, 54,128, 4, 7, 55,128, 4, 8,+ 56,128, 4, 9, 57,128, 4, 10, 54, 10, 39,190, 39,194, 39,198,+ 39,202, 39,206, 39,210, 39,214, 39,218, 39,222, 39,226, 48,128,+ 4, 11, 49,128, 4, 12, 50,128, 4, 14, 51,128,246,196, 52,128,+ 246,197, 53,128, 4, 48, 54,128, 4, 49, 55,128, 4, 50, 56,128,+ 4, 51, 57,128, 4, 52, 55, 10, 39,252, 40, 0, 40, 4, 40, 8,+ 40, 12, 40, 16, 40, 20, 40, 24, 40, 28, 40, 32, 48,128, 4, 53,+ 49,128, 4, 81, 50,128, 4, 54, 51,128, 4, 55, 52,128, 4, 56,+ 53,128, 4, 57, 54,128, 4, 58, 55,128, 4, 59, 56,128, 4, 60,+ 57,128, 4, 61, 56, 10, 40, 58, 40, 62, 40, 66, 40, 70, 40, 74,+ 40, 78, 40, 82, 40, 86, 40, 90, 40, 94, 48,128, 4, 62, 49,128,+ 4, 63, 50,128, 4, 64, 51,128, 4, 65, 52,128, 4, 66, 53,128,+ 4, 67, 54,128, 4, 68, 55,128, 4, 69, 56,128, 4, 70, 57,128,+ 4, 71, 57, 10, 40,120, 40,124, 40,128, 40,132, 40,136, 40,140,+ 40,144, 40,148, 40,152, 40,156, 48,128, 4, 72, 49,128, 4, 73,+ 50,128, 4, 74, 51,128, 4, 75, 52,128, 4, 76, 53,128, 4, 77,+ 54,128, 4, 78, 55,128, 4, 79, 56,128, 4,145, 57,128, 4, 82,+ 49, 4, 40,170, 40,232, 40,237, 41, 7, 48, 10, 40,192, 40,196,+ 40,200, 40,204, 40,208, 40,212, 40,216, 40,220, 40,224, 40,228,+ 48,128, 4, 83, 49,128, 4, 84, 50,128, 4, 85, 51,128, 4, 86,+ 52,128, 4, 87, 53,128, 4, 88, 54,128, 4, 89, 55,128, 4, 90,+ 56,128, 4, 91, 57,128, 4, 92,177, 48,128, 4, 94, 52, 4, 40,+ 247, 40,251, 40,255, 41, 3, 53,128, 4, 15, 54,128, 4, 98, 55,+ 128, 4,114, 56,128, 4,116, 57, 5, 41, 19, 41, 23, 41, 27, 41,+ 31, 41, 35, 50,128,246,198, 51,128, 4, 95, 52,128, 4, 99, 53,+ 128, 4,115, 54,128, 4,117, 56, 2, 41, 45, 41, 59, 51, 2, 41,+ 51, 41, 55, 49,128,246,199, 50,128,246,200,180, 54,128, 4,217,+ 178,185, 57,128, 32, 14,179, 48, 2, 41, 77, 41, 81, 48,128, 32,+ 15, 49,128, 32, 13,181, 55, 7, 41,102, 41,172, 42,237, 43, 58,+ 44, 15, 44,108, 44,179, 51, 2, 41,108, 41,122, 56, 2, 41,114,+ 41,118, 49,128, 6,106, 56,128, 6, 12, 57, 8, 41,140, 41,144,+ 41,148, 41,152, 41,156, 41,160, 41,164, 41,168, 50,128, 6, 96,+ 51,128, 6, 97, 52,128, 6, 98, 53,128, 6, 99, 54,128, 6,100,+ 55,128, 6,101, 56,128, 6,102, 57,128, 6,103, 52, 7, 41,188,+ 41,220, 42, 26, 42, 88, 42,120, 42,176, 42,232, 48, 5, 41,200,+ 41,204, 41,208, 41,212, 41,216, 48,128, 6,104, 49,128, 6,105,+ 51,128, 6, 27, 55,128, 6, 31, 57,128, 6, 33, 49, 10, 41,242,+ 41,246, 41,250, 41,254, 42, 2, 42, 6, 42, 10, 42, 14, 42, 18,+ 42, 22, 48,128, 6, 34, 49,128, 6, 35, 50,128, 6, 36, 51,128,+ 6, 37, 52,128, 6, 38, 53,128, 6, 39, 54,128, 6, 40, 55,128,+ 6, 41, 56,128, 6, 42, 57,128, 6, 43, 50, 10, 42, 48, 42, 52,+ 42, 56, 42, 60, 42, 64, 42, 68, 42, 72, 42, 76, 42, 80, 42, 84,+ 48,128, 6, 44, 49,128, 6, 45, 50,128, 6, 46, 51,128, 6, 47,+ 52,128, 6, 48, 53,128, 6, 49, 54,128, 6, 50, 55,128, 6, 51,+ 56,128, 6, 52, 57,128, 6, 53, 51, 5, 42,100, 42,104, 42,108,+ 42,112, 42,116, 48,128, 6, 54, 49,128, 6, 55, 50,128, 6, 56,+ 51,128, 6, 57, 52,128, 6, 58, 52, 9, 42,140, 42,144, 42,148,+ 42,152, 42,156, 42,160, 42,164, 42,168, 42,172, 48,128, 6, 64,+ 49,128, 6, 65, 50,128, 6, 66, 51,128, 6, 67, 52,128, 6, 68,+ 53,128, 6, 69, 54,128, 6, 70, 56,128, 6, 72, 57,128, 6, 73,+ 53, 9, 42,196, 42,200, 42,204, 42,208, 42,212, 42,216, 42,220,+ 42,224, 42,228, 48,128, 6, 74, 49,128, 6, 75, 50,128, 6, 76,+ 51,128, 6, 77, 52,128, 6, 78, 53,128, 6, 79, 54,128, 6, 80,+ 55,128, 6, 81, 56,128, 6, 82,183, 48,128, 6, 71, 53, 3, 42,+ 245, 43, 21, 43, 53, 48, 5, 43, 1, 43, 5, 43, 9, 43, 13, 43,+ 17, 53,128, 6,164, 54,128, 6,126, 55,128, 6,134, 56,128, 6,+ 152, 57,128, 6,175, 49, 5, 43, 33, 43, 37, 43, 41, 43, 45, 43,+ 49, 49,128, 6,121, 50,128, 6,136, 51,128, 6,145, 52,128, 6,+ 186, 57,128, 6,210,179, 52,128, 6,213, 54, 7, 43, 74, 43, 79,+ 43, 84, 43, 89, 43,127, 43,189, 43,251,179, 54,128, 32,170,180,+ 53,128, 5,190,181, 56,128, 5,195, 54, 6, 43,103, 43,107, 43,+ 111, 43,115, 43,119, 43,123, 52,128, 5,208, 53,128, 5,209, 54,+ 128, 5,210, 55,128, 5,211, 56,128, 5,212, 57,128, 5,213, 55,+ 10, 43,149, 43,153, 43,157, 43,161, 43,165, 43,169, 43,173, 43,+ 177, 43,181, 43,185, 48,128, 5,214, 49,128, 5,215, 50,128, 5,+ 216, 51,128, 5,217, 52,128, 5,218, 53,128, 5,219, 54,128, 5,+ 220, 55,128, 5,221, 56,128, 5,222, 57,128, 5,223, 56, 10, 43,+ 211, 43,215, 43,219, 43,223, 43,227, 43,231, 43,235, 43,239, 43,+ 243, 43,247, 48,128, 5,224, 49,128, 5,225, 50,128, 5,226, 51,+ 128, 5,227, 52,128, 5,228, 53,128, 5,229, 54,128, 5,230, 55,+ 128, 5,231, 56,128, 5,232, 57,128, 5,233, 57, 3, 44, 3, 44,+ 7, 44, 11, 48,128, 5,234, 52,128,251, 42, 53,128,251, 43, 55,+ 4, 44, 25, 44, 39, 44, 59, 44, 64, 48, 2, 44, 31, 44, 35, 48,+ 128,251, 75, 53,128,251, 31, 49, 3, 44, 47, 44, 51, 44, 55, 54,+ 128, 5,240, 55,128, 5,241, 56,128, 5,242,178, 51,128,251, 53,+ 57, 7, 44, 80, 44, 84, 44, 88, 44, 92, 44, 96, 44,100, 44,104,+ 51,128, 5,180, 52,128, 5,181, 53,128, 5,182, 54,128, 5,187,+ 55,128, 5,184, 56,128, 5,183, 57,128, 5,176, 56, 3, 44,116,+ 44,160, 44,165, 48, 7, 44,132, 44,136, 44,140, 44,144, 44,148,+ 44,152, 44,156, 48,128, 5,178, 49,128, 5,177, 50,128, 5,179,+ 51,128, 5,194, 52,128, 5,193, 54,128, 5,185, 55,128, 5,188,+ 179, 57,128, 5,189, 52, 2, 44,171, 44,175, 49,128, 5,191, 50,+ 128, 5,192,185,178, 57,128, 2,188, 54, 3, 44,193, 44,252, 45,+ 3, 49, 4, 44,203, 44,219, 44,225, 44,246, 50, 2, 44,209, 44,+ 214,180, 56,128, 33, 5,184, 57,128, 33, 19,179,181, 50,128, 33,+ 22,181, 55, 3, 44,234, 44,238, 44,242, 51,128, 32, 44, 52,128,+ 32, 45, 53,128, 32, 46,182,182, 52,128, 32, 12,179,177,182, 55,+ 128, 6,109,180,185,179, 55,128, 2,189,103, 2, 45, 16, 45, 23,+ 242,225,246,101,128, 0,224,117, 2, 45, 29, 45, 38,234,225,242,+ 225,244,105,128, 10,133,242,237,245,235,232,105,128, 10, 5,104,+ 2, 45, 53, 45, 63,233,242,225,231,225,238, 97,128, 48, 66,239,+ 239,235,225,226,239,246,101,128, 30,163,105, 7, 45, 90, 45,115,+ 45,122, 45,134, 45,159, 45,175, 45,255, 98, 2, 45, 96, 45,105,+ 229,238,231,225,236,105,128, 9,144,239,240,239,237,239,230,111,+ 128, 49, 30,228,229,246, 97,128, 9, 16,229,227,249,242,233,236,+ 236,233, 99,128, 4,213,231,117, 2, 45,141, 45,150,234,225,242,+ 225,244,105,128, 10,144,242,237,245,235,232,105,128, 10, 16,237,+ 225,244,242,225,231,245,242,237,245,235,232,105,128, 10, 72,110,+ 5, 45,187, 45,196, 45,210, 45,226, 45,241,225,242,225,226,233,+ 99,128, 6, 57,230,233,238,225,236,225,242,225,226,233, 99,128,+ 254,202,233,238,233,244,233,225,236,225,242,225,226,233, 99,128,+ 254,203,237,229,228,233,225,236,225,242,225,226,233, 99,128,254,+ 204,246,229,242,244,229,228,226,242,229,246,101,128, 2, 3,246,+ 239,247,229,236,243,233,231,110, 3, 46, 15, 46, 25, 46, 32,226,+ 229,238,231,225,236,105,128, 9,200,228,229,246, 97,128, 9, 72,+ 231,245,234,225,242,225,244,105,128, 10,200,107, 2, 46, 49, 46,+ 73,225,244,225,235,225,238, 97,129, 48,162, 46, 61,232,225,236,+ 230,247,233,228,244,104,128,255,113,239,242,229,225,110,128, 49,+ 79,108, 3, 46, 89, 47,145, 47,154,101, 2, 46, 95, 47,140,102,+ 136, 5,208, 46,115, 46,124, 46,139, 46,153, 46,242, 47, 0, 47,+ 111, 47,125,225,242,225,226,233, 99,128, 6, 39,228,225,231,229,+ 243,232,232,229,226,242,229,119,128,251, 48,230,233,238,225,236,+ 225,242,225,226,233, 99,128,254,142,104, 2, 46,159, 46,234,225,+ 237,250, 97, 2, 46,168, 46,201,225,226,239,246,101, 2, 46,178,+ 46,187,225,242,225,226,233, 99,128, 6, 35,230,233,238,225,236,+ 225,242,225,226,233, 99,128,254,132,226,229,236,239,119, 2, 46,+ 211, 46,220,225,242,225,226,233, 99,128, 6, 37,230,233,238,225,+ 236,225,242,225,226,233, 99,128,254,136,229,226,242,229,119,128,+ 5,208,236,225,237,229,228,232,229,226,242,229,119,128,251, 79,+ 237, 97, 2, 47, 7, 47, 43,228,228,225,225,226,239,246,101, 2,+ 47, 20, 47, 29,225,242,225,226,233, 99,128, 6, 34,230,233,238,+ 225,236,225,242,225,226,233, 99,128,254,130,235,243,245,242, 97,+ 4, 47, 57, 47, 66, 47, 80, 47, 96,225,242,225,226,233, 99,128,+ 6, 73,230,233,238,225,236,225,242,225,226,233, 99,128,254,240,+ 233,238,233,244,233,225,236,225,242,225,226,233, 99,128,254,243,+ 237,229,228,233,225,236,225,242,225,226,233, 99,128,254,244,240,+ 225,244,225,232,232,229,226,242,229,119,128,251, 46,241,225,237,+ 225,244,243,232,229,226,242,229,119,128,251, 47,240,104,128, 33,+ 53,236,229,241,245,225,108,128, 34, 76,240,232, 97,129, 3,177,+ 47,162,244,239,238,239,115,128, 3,172,109, 4, 47,180, 47,188,+ 47,199, 47,233,225,227,242,239,110,128, 1, 1,239,238,239,243,+ 240,225,227,101,128,255, 65,240,229,242,243,225,238,100,130, 0,+ 38, 47,213, 47,225,237,239,238,239,243,240,225,227,101,128,255,+ 6,243,237,225,236,108,128,247, 38,243,241,245,225,242,101,128,+ 51,194,110, 4, 47,252, 48, 7, 48,129, 48,139,226,239,240,239,+ 237,239,230,111,128, 49, 34,103, 4, 48, 17, 48, 28, 48, 42, 48,+ 121,226,239,240,239,237,239,230,111,128, 49, 36,235,232,225,238,+ 235,232,245,244,232,225,105,128, 14, 90,236,101,131, 34, 32, 48,+ 53, 48,106, 48,113,226,242,225,227,235,229,116, 2, 48, 65, 48,+ 85,236,229,230,116,129, 48, 8, 48, 74,246,229,242,244,233,227,+ 225,108,128,254, 63,242,233,231,232,116,129, 48, 9, 48, 95,246,+ 229,242,244,233,227,225,108,128,254, 64,236,229,230,116,128, 35,+ 41,242,233,231,232,116,128, 35, 42,243,244,242,239,109,128, 33,+ 43,239,244,229,236,229,233, 97,128, 3,135,117, 2, 48,145, 48,+ 157,228,225,244,244,225,228,229,246, 97,128, 9, 82,243,246,225,+ 242, 97, 3, 48,169, 48,179, 48,186,226,229,238,231,225,236,105,+ 128, 9,130,228,229,246, 97,128, 9, 2,231,245,234,225,242,225,+ 244,105,128, 10,130,239,231,239,238,229,107,128, 1, 5,112, 3,+ 48,214, 48,238, 49, 12, 97, 2, 48,220, 48,232,225,244,239,243,+ 241,245,225,242,101,128, 51, 0,242,229,110,128, 36,156,239,243,+ 244,242,239,240,232,101, 2, 48,251, 49, 6,225,242,237,229,238,+ 233,225,110,128, 5, 90,237,239,100,128, 2,188,112, 2, 49, 18,+ 49, 23,236,101,128,248,255,242,111, 2, 49, 30, 49, 38,225,227,+ 232,229,115,128, 34, 80,120, 2, 49, 44, 49, 64,229,241,245,225,+ 108,129, 34, 72, 49, 54,239,242,233,237,225,231,101,128, 34, 82,+ 233,237,225,244,229,236,249,229,241,245,225,108,128, 34, 69,114,+ 4, 49, 89, 49,116, 49,120, 49,165,225,229, 97, 2, 49, 97, 49,+ 107,229,235,239,242,229,225,110,128, 49,142,235,239,242,229,225,+ 110,128, 49,141, 99,128, 35, 18,105, 2, 49,126, 49,140,231,232,+ 244,232,225,236,230,242,233,238,103,128, 30,154,238,103,130, 0,+ 229, 49,149, 49,157,225,227,245,244,101,128, 1,251,226,229,236,+ 239,119,128, 30, 1,242,239,119, 8, 49,185, 49,192, 50, 65, 50,+ 131, 50,181, 50,236, 51, 3, 51, 78,226,239,244,104,128, 33,148,+ 100, 3, 49,200, 49,239, 50, 30,225,243,104, 4, 49,212, 49,219,+ 49,226, 49,234,228,239,247,110,128, 33,227,236,229,230,116,128,+ 33,224,242,233,231,232,116,128, 33,226,245,112,128, 33,225,226,+ 108, 5, 49,252, 50, 3, 50, 10, 50, 17, 50, 25,226,239,244,104,+ 128, 33,212,228,239,247,110,128, 33,211,236,229,230,116,128, 33,+ 208,242,233,231,232,116,128, 33,210,245,112,128, 33,209,239,247,+ 110,131, 33,147, 50, 42, 50, 49, 50, 57,236,229,230,116,128, 33,+ 153,242,233,231,232,116,128, 33,152,247,232,233,244,101,128, 33,+ 233,104, 2, 50, 71, 50,122,229,225,100, 4, 50, 83, 50, 93, 50,+ 103, 50,114,228,239,247,238,237,239,100,128, 2,197,236,229,230,+ 244,237,239,100,128, 2,194,242,233,231,232,244,237,239,100,128,+ 2,195,245,240,237,239,100,128, 2,196,239,242,233,250,229,120,+ 128,248,231,236,229,230,116,131, 33,144, 50,144, 50,161, 50,173,+ 228,226,108,129, 33,208, 50,152,243,244,242,239,235,101,128, 33,+ 205,239,246,229,242,242,233,231,232,116,128, 33,198,247,232,233,+ 244,101,128, 33,230,242,233,231,232,116,132, 33,146, 50,197, 50,+ 209, 50,217, 50,228,228,226,236,243,244,242,239,235,101,128, 33,+ 207,232,229,225,246,121,128, 39,158,239,246,229,242,236,229,230,+ 116,128, 33,196,247,232,233,244,101,128, 33,232,244,225, 98, 2,+ 50,244, 50,251,236,229,230,116,128, 33,228,242,233,231,232,116,+ 128, 33,229,245,112,132, 33,145, 51, 16, 51, 44, 51, 62, 51, 70,+ 100, 2, 51, 22, 51, 34,110,129, 33,149, 51, 28,226,243,101,128,+ 33,168,239,247,238,226,225,243,101,128, 33,168,236,229,230,116,+ 129, 33,150, 51, 53,239,230,228,239,247,110,128, 33,197,242,233,+ 231,232,116,128, 33,151,247,232,233,244,101,128, 33,231,246,229,+ 242,244,229,120,128,248,230,115, 5, 51, 99, 51,175, 51,220, 52,+ 47, 52, 57, 99, 2, 51,105, 51,157,233,105, 2, 51,112, 51,135,+ 227,233,242,227,245,109,129, 0, 94, 51,123,237,239,238,239,243,+ 240,225,227,101,128,255, 62,244,233,236,228,101,129, 0,126, 51,+ 145,237,239,238,239,243,240,225,227,101,128,255, 94,242,233,240,+ 116,129, 2, 81, 51,166,244,245,242,238,229,100,128, 2, 82,237,+ 225,236,108, 2, 51,184, 51,195,232,233,242,225,231,225,238, 97,+ 128, 48, 65,235,225,244,225,235,225,238, 97,129, 48,161, 51,208,+ 232,225,236,230,247,233,228,244,104,128,255,103,244,229,242,233,+ 115, 2, 51,230, 52, 43,107,131, 0, 42, 51,240, 52, 12, 52, 35,+ 97, 2, 51,246, 52, 4,236,244,239,238,229,225,242,225,226,233,+ 99,128, 6,109,242,225,226,233, 99,128, 6,109,109, 2, 52, 18,+ 52, 24,225,244,104,128, 34, 23,239,238,239,243,240,225,227,101,+ 128,255, 10,243,237,225,236,108,128,254, 97,109,128, 32, 66,245,+ 240,229,242,233,239,114,128,246,233,249,237,240,244,239,244,233,+ 227,225,236,236,249,229,241,245,225,108,128, 34, 67,116,132, 0,+ 64, 52, 89, 52, 96, 52,108, 52,116,233,236,228,101,128, 0,227,+ 237,239,238,239,243,240,225,227,101,128,255, 32,243,237,225,236,+ 108,128,254,107,245,242,238,229,100,128, 2, 80,117, 6, 52,138,+ 52,163, 52,170, 52,195, 52,215, 52,231, 98, 2, 52,144, 52,153,+ 229,238,231,225,236,105,128, 9,148,239,240,239,237,239,230,111,+ 128, 49, 32,228,229,246, 97,128, 9, 20,231,117, 2, 52,177, 52,+ 186,234,225,242,225,244,105,128, 10,148,242,237,245,235,232,105,+ 128, 10, 20,236,229,238,231,244,232,237,225,242,235,226,229,238,+ 231,225,236,105,128, 9,215,237,225,244,242,225,231,245,242,237,+ 245,235,232,105,128, 10, 76,246,239,247,229,236,243,233,231,110,+ 3, 52,247, 53, 1, 53, 8,226,229,238,231,225,236,105,128, 9,+ 204,228,229,246, 97,128, 9, 76,231,245,234,225,242,225,244,105,+ 128, 10,204,246,225,231,242,225,232,225,228,229,246, 97,128, 9,+ 61,121, 2, 53, 39, 53, 51,226,225,242,237,229,238,233,225,110,+ 128, 5, 97,233,110,130, 5,226, 53, 60, 53, 75,225,236,244,239,+ 238,229,232,229,226,242,229,119,128,251, 32,232,229,226,242,229,+ 119,128, 5,226, 98,144, 0, 98, 53,120, 53,255, 54, 10, 54, 19,+ 54, 44, 55, 85, 55,147, 55,220, 57,146, 57,158, 57,201, 57,209,+ 57,219, 59, 89, 59,113, 59,122, 97, 7, 53,136, 53,146, 53,170,+ 53,177, 53,202, 53,226, 53,237,226,229,238,231,225,236,105,128,+ 9,172,227,235,243,236,225,243,104,129, 0, 92, 53,158,237,239,+ 238,239,243,240,225,227,101,128,255, 60,228,229,246, 97,128, 9,+ 44,231,117, 2, 53,184, 53,193,234,225,242,225,244,105,128, 10,+ 172,242,237,245,235,232,105,128, 10, 44,104, 2, 53,208, 53,218,+ 233,242,225,231,225,238, 97,128, 48,112,244,244,232,225,105,128,+ 14, 63,235,225,244,225,235,225,238, 97,128, 48,208,114,129, 0,+ 124, 53,243,237,239,238,239,243,240,225,227,101,128,255, 92,226,+ 239,240,239,237,239,230,111,128, 49, 5,227,233,242,227,236,101,+ 128, 36,209,228,239,116, 2, 54, 27, 54, 36,225,227,227,229,238,+ 116,128, 30, 3,226,229,236,239,119,128, 30, 5,101, 6, 54, 58,+ 54, 79, 54,102, 54,244, 54,255, 55, 11,225,237,229,228,243,233,+ 248,244,229,229,238,244,232,238,239,244,229,115,128, 38,108, 99,+ 2, 54, 85, 54, 92,225,245,243,101,128, 34, 53,249,242,233,236,+ 236,233, 99,128, 4, 49,104, 5, 54,114, 54,123, 54,137, 54,167,+ 54,226,225,242,225,226,233, 99,128, 6, 40,230,233,238,225,236,+ 225,242,225,226,233, 99,128,254,144,105, 2, 54,143, 54,158,238,+ 233,244,233,225,236,225,242,225,226,233, 99,128,254,145,242,225,+ 231,225,238, 97,128, 48,121,237,101, 2, 54,174, 54,187,228,233,+ 225,236,225,242,225,226,233, 99,128,254,146,229,237,105, 2, 54,+ 195, 54,210,238,233,244,233,225,236,225,242,225,226,233, 99,128,+ 252,159,243,239,236,225,244,229,228,225,242,225,226,233, 99,128,+ 252, 8,238,239,239,238,230,233,238,225,236,225,242,225,226,233,+ 99,128,252,109,235,225,244,225,235,225,238, 97,128, 48,217,238,+ 225,242,237,229,238,233,225,110,128, 5, 98,116,132, 5,209, 55,+ 23, 55, 43, 55, 63, 55, 72, 97,129, 3,178, 55, 29,243,249,237,+ 226,239,236,231,242,229,229,107,128, 3,208,228,225,231,229,243,+ 104,129,251, 49, 55, 54,232,229,226,242,229,119,128,251, 49,232,+ 229,226,242,229,119,128, 5,209,242,225,230,229,232,229,226,242,+ 229,119,128,251, 76,104, 2, 55, 91, 55,141, 97, 3, 55, 99, 55,+ 109, 55,116,226,229,238,231,225,236,105,128, 9,173,228,229,246,+ 97,128, 9, 45,231,117, 2, 55,123, 55,132,234,225,242,225,244,+ 105,128, 10,173,242,237,245,235,232,105,128, 10, 45,239,239,107,+ 128, 2, 83,105, 5, 55,159, 55,170, 55,181, 55,195, 55,209,232,+ 233,242,225,231,225,238, 97,128, 48,115,235,225,244,225,235,225,+ 238, 97,128, 48,211,236,225,226,233,225,236,227,236,233,227,107,+ 128, 2,152,238,228,233,231,245,242,237,245,235,232,105,128, 10,+ 2,242,245,243,241,245,225,242,101,128, 51, 49,108, 3, 55,228,+ 57,129, 57,140, 97, 2, 55,234, 57,124,227,107, 6, 55,249, 56,+ 2, 56, 39, 56,188, 56,243, 57, 39,227,233,242,227,236,101,128,+ 37,207,100, 2, 56, 8, 56, 17,233,225,237,239,238,100,128, 37,+ 198,239,247,238,240,239,233,238,244,233,238,231,244,242,233,225,+ 238,231,236,101,128, 37,188,108, 2, 56, 45, 56,148,101, 2, 56,+ 51, 56, 87,230,244,240,239,233,238,244,233,238,103, 2, 56, 66,+ 56, 76,240,239,233,238,244,229,114,128, 37,196,244,242,233,225,+ 238,231,236,101,128, 37,192,238,244,233,227,245,236,225,242,226,+ 242,225,227,235,229,116, 2, 56,107, 56,127,236,229,230,116,129,+ 48, 16, 56,116,246,229,242,244,233,227,225,108,128,254, 59,242,+ 233,231,232,116,129, 48, 17, 56,137,246,229,242,244,233,227,225,+ 108,128,254, 60,239,247,229,114, 2, 56,157, 56,172,236,229,230,+ 244,244,242,233,225,238,231,236,101,128, 37,227,242,233,231,232,+ 244,244,242,233,225,238,231,236,101,128, 37,226,114, 2, 56,194,+ 56,205,229,227,244,225,238,231,236,101,128, 37,172,233,231,232,+ 244,240,239,233,238,244,233,238,103, 2, 56,222, 56,232,240,239,+ 233,238,244,229,114,128, 37,186,244,242,233,225,238,231,236,101,+ 128, 37,182,115, 3, 56,251, 57, 25, 57, 33,109, 2, 57, 1, 57,+ 13,225,236,236,243,241,245,225,242,101,128, 37,170,233,236,233,+ 238,231,230,225,227,101,128, 38, 59,241,245,225,242,101,128, 37,+ 160,244,225,114,128, 38, 5,245,240,112, 2, 57, 47, 57, 85,229,+ 114, 2, 57, 54, 57, 69,236,229,230,244,244,242,233,225,238,231,+ 236,101,128, 37,228,242,233,231,232,244,244,242,233,225,238,231,+ 236,101,128, 37,229,239,233,238,244,233,238,103, 2, 57, 97, 57,+ 113,243,237,225,236,236,244,242,233,225,238,231,236,101,128, 37,+ 180,244,242,233,225,238,231,236,101,128, 37,178,238,107,128, 36,+ 35,233,238,229,226,229,236,239,119,128, 30, 7,239,227,107,128,+ 37,136,237,239,238,239,243,240,225,227,101,128,255, 66,111, 3,+ 57,166, 57,179, 57,190,226,225,233,237,225,233,244,232,225,105,+ 128, 14, 26,232,233,242,225,231,225,238, 97,128, 48,124,235,225,+ 244,225,235,225,238, 97,128, 48,220,240,225,242,229,110,128, 36,+ 157,241,243,241,245,225,242,101,128, 51,195,114, 4, 57,229, 58,+ 223, 59, 40, 59, 79,225, 99, 2, 57,236, 58,130,101, 3, 57,244,+ 57,249, 58, 61,229,120,128,248,244,236,229,230,116,133, 0,123,+ 58, 10, 58, 15, 58, 37, 58, 45, 58, 50,226,116,128,248,243,109,+ 2, 58, 21, 58, 26,233,100,128,248,242,239,238,239,243,240,225,+ 227,101,128,255, 91,243,237,225,236,108,128,254, 91,244,112,128,+ 248,241,246,229,242,244,233,227,225,108,128,254, 55,242,233,231,+ 232,116,133, 0,125, 58, 79, 58, 84, 58,106, 58,114, 58,119,226,+ 116,128,248,254,109, 2, 58, 90, 58, 95,233,100,128,248,253,239,+ 238,239,243,240,225,227,101,128,255, 93,243,237,225,236,108,128,+ 254, 92,244,112,128,248,252,246,229,242,244,233,227,225,108,128,+ 254, 56,235,229,116, 2, 58,138, 58,180,236,229,230,116,132, 0,+ 91, 58,153, 58,158, 58,163, 58,175,226,116,128,248,240,229,120,+ 128,248,239,237,239,238,239,243,240,225,227,101,128,255, 59,244,+ 112,128,248,238,242,233,231,232,116,132, 0, 93, 58,196, 58,201,+ 58,206, 58,218,226,116,128,248,251,229,120,128,248,250,237,239,+ 238,239,243,240,225,227,101,128,255, 61,244,112,128,248,249,229,+ 246,101,131, 2,216, 58,235, 58,246, 58,252,226,229,236,239,247,+ 227,237, 98,128, 3, 46,227,237, 98,128, 3, 6,233,238,246,229,+ 242,244,229,100, 3, 59, 11, 59, 22, 59, 28,226,229,236,239,247,+ 227,237, 98,128, 3, 47,227,237, 98,128, 3, 17,228,239,245,226,+ 236,229,227,237, 98,128, 3, 97,233,228,231,101, 2, 59, 49, 59,+ 60,226,229,236,239,247,227,237, 98,128, 3, 42,233,238,246,229,+ 242,244,229,228,226,229,236,239,247,227,237, 98,128, 3, 58,239,+ 235,229,238,226,225,114,128, 0,166,115, 2, 59, 95, 59,103,244,+ 242,239,235,101,128, 1,128,245,240,229,242,233,239,114,128,246,+ 234,244,239,240,226,225,114,128, 1,131,117, 3, 59,130, 59,141,+ 59,152,232,233,242,225,231,225,238, 97,128, 48,118,235,225,244,+ 225,235,225,238, 97,128, 48,214,236,108, 2, 59,159, 59,189,229,+ 116,130, 32, 34, 59,168, 59,178,233,238,246,229,242,243,101,128,+ 37,216,239,240,229,242,225,244,239,114,128, 34, 25,243,229,249,+ 101,128, 37,206, 99,143, 0, 99, 59,230, 60,179, 60,190, 60,254,+ 61, 29, 61,122, 63, 33, 64, 17, 64,117, 64,166, 67,158, 67,166,+ 67,176, 67,188, 67,221, 97, 9, 59,250, 60, 5, 60, 15, 60, 22,+ 60, 29, 60, 54, 60, 64, 60,116, 60,125,225,242,237,229,238,233,+ 225,110,128, 5,110,226,229,238,231,225,236,105,128, 9,154,227,+ 245,244,101,128, 1, 7,228,229,246, 97,128, 9, 26,231,117, 2,+ 60, 36, 60, 45,234,225,242,225,244,105,128, 10,154,242,237,245,+ 235,232,105,128, 10, 26,236,243,241,245,225,242,101,128, 51,136,+ 238,228,242,225,226,233,238,228,117, 4, 60, 82, 60, 92, 60, 98,+ 60,105,226,229,238,231,225,236,105,128, 9,129,227,237, 98,128,+ 3, 16,228,229,246, 97,128, 9, 1,231,245,234,225,242,225,244,+ 105,128, 10,129,240,243,236,239,227,107,128, 33,234,114, 3, 60,+ 133, 60,139, 60,165,229,239,102,128, 33, 5,239,110,130, 2,199,+ 60,148, 60,159,226,229,236,239,247,227,237, 98,128, 3, 44,227,+ 237, 98,128, 3, 12,242,233,225,231,229,242,229,244,245,242,110,+ 128, 33,181,226,239,240,239,237,239,230,111,128, 49, 24, 99, 4,+ 60,200, 60,207, 60,226, 60,248,225,242,239,110,128, 1, 13,229,+ 228,233,236,236, 97,129, 0,231, 60,218,225,227,245,244,101,128,+ 30, 9,233,242, 99, 2, 60,234, 60,239,236,101,128, 36,210,245,+ 237,230,236,229,120,128, 1, 9,245,242,108,128, 2, 85,100, 2,+ 61, 4, 61, 20,239,116,129, 1, 11, 61, 11,225,227,227,229,238,+ 116,128, 1, 11,243,241,245,225,242,101,128, 51,197,101, 2, 61,+ 35, 61, 51,228,233,236,236, 97,129, 0,184, 61, 45,227,237, 98,+ 128, 3, 39,238,116,132, 0,162, 61, 64, 61, 88, 61,100, 61,111,+ 105, 2, 61, 70, 61, 78,231,242,225,228,101,128, 33, 3,238,230,+ 229,242,233,239,114,128,246,223,237,239,238,239,243,240,225,227,+ 101,128,255,224,239,236,228,243,244,249,236,101,128,247,162,243,+ 245,240,229,242,233,239,114,128,246,224,104, 5, 61,134, 61,197,+ 61,208, 62,136, 62,228, 97, 4, 61,144, 61,155, 61,165, 61,172,+ 225,242,237,229,238,233,225,110,128, 5,121,226,229,238,231,225,+ 236,105,128, 9,155,228,229,246, 97,128, 9, 27,231,117, 2, 61,+ 179, 61,188,234,225,242,225,244,105,128, 10,155,242,237,245,235,+ 232,105,128, 10, 27,226,239,240,239,237,239,230,111,128, 49, 20,+ 101, 6, 61,222, 61,242, 62, 10, 62, 78, 62, 90, 62,111,225,226,+ 235,232,225,243,233,225,238,227,249,242,233,236,236,233, 99,128,+ 4,189, 99, 2, 61,248, 62, 0,235,237,225,242,107,128, 39, 19,+ 249,242,233,236,236,233, 99,128, 4, 71,100, 2, 62, 16, 62, 60,+ 229,243,227,229,238,228,229,114, 2, 62, 29, 62, 49,225,226,235,+ 232,225,243,233,225,238,227,249,242,233,236,236,233, 99,128, 4,+ 191,227,249,242,233,236,236,233, 99,128, 4,183,233,229,242,229,+ 243,233,243,227,249,242,233,236,236,233, 99,128, 4,245,232,225,+ 242,237,229,238,233,225,110,128, 5,115,235,232,225,235,225,243,+ 243,233,225,238,227,249,242,233,236,236,233, 99,128, 4,204,246,+ 229,242,244,233,227,225,236,243,244,242,239,235,229,227,249,242,+ 233,236,236,233, 99,128, 4,185,105,129, 3,199, 62,142,229,245,+ 227,104, 4, 62,155, 62,190, 62,205, 62,214, 97, 2, 62,161, 62,+ 176,227,233,242,227,236,229,235,239,242,229,225,110,128, 50,119,+ 240,225,242,229,238,235,239,242,229,225,110,128, 50, 23,227,233,+ 242,227,236,229,235,239,242,229,225,110,128, 50,105,235,239,242,+ 229,225,110,128, 49, 74,240,225,242,229,238,235,239,242,229,225,+ 110,128, 50, 9,111, 2, 62,234, 63, 28,227,104, 3, 62,243, 63,+ 9, 63, 19,225,110, 2, 62,250, 63, 2,231,244,232,225,105,128,+ 14, 10,244,232,225,105,128, 14, 8,233,238,231,244,232,225,105,+ 128, 14, 9,239,229,244,232,225,105,128, 14, 12,239,107,128, 1,+ 136,105, 2, 63, 39, 63,141,229,245, 99, 5, 63, 53, 63, 88, 63,+ 103, 63,112, 63,126, 97, 2, 63, 59, 63, 74,227,233,242,227,236,+ 229,235,239,242,229,225,110,128, 50,118,240,225,242,229,238,235,+ 239,242,229,225,110,128, 50, 22,227,233,242,227,236,229,235,239,+ 242,229,225,110,128, 50,104,235,239,242,229,225,110,128, 49, 72,+ 240,225,242,229,238,235,239,242,229,225,110,128, 50, 8,245,240,+ 225,242,229,238,235,239,242,229,225,110,128, 50, 28,242, 99, 2,+ 63,148, 63,243,236,101,132, 37,203, 63,161, 63,172, 63,177, 63,+ 201,237,245,236,244,233,240,236,121,128, 34,151,239,116,128, 34,+ 153,112, 2, 63,183, 63,189,236,245,115,128, 34,149,239,243,244,+ 225,236,237,225,242,107,128, 48, 54,247,233,244,104, 2, 63,210,+ 63,226,236,229,230,244,232,225,236,230,226,236,225,227,107,128,+ 37,208,242,233,231,232,244,232,225,236,230,226,236,225,227,107,+ 128, 37,209,245,237,230,236,229,120,130, 2,198, 64, 0, 64, 11,+ 226,229,236,239,247,227,237, 98,128, 3, 45,227,237, 98,128, 3,+ 2,108, 3, 64, 25, 64, 31, 64, 85,229,225,114,128, 35, 39,233,+ 227,107, 4, 64, 43, 64, 54, 64, 63, 64, 73,225,236,246,229,239,+ 236,225,114,128, 1,194,228,229,238,244,225,108,128, 1,192,236,+ 225,244,229,242,225,108,128, 1,193,242,229,244,242,239,230,236,+ 229,120,128, 1,195,245, 98,129, 38, 99, 64, 92,243,245,233,116,+ 2, 64,101, 64,109,226,236,225,227,107,128, 38, 99,247,232,233,+ 244,101,128, 38,103,109, 3, 64,125, 64,139, 64,150,227,245,226,+ 229,228,243,241,245,225,242,101,128, 51,164,239,238,239,243,240,+ 225,227,101,128,255, 67,243,241,245,225,242,229,228,243,241,245,+ 225,242,101,128, 51,160,111, 8, 64,184, 64,195, 65, 26, 65,224,+ 66,253, 67, 28, 67,135, 67,144,225,242,237,229,238,233,225,110,+ 128, 5,129,236,239,110,131, 0, 58, 64,207, 64,232, 64,251,237,+ 239,110, 2, 64,215, 64,223,229,244,225,242,121,128, 32,161,239,+ 243,240,225,227,101,128,255, 26,115, 2, 64,238, 64,244,233,231,+ 110,128, 32,161,237,225,236,108,128,254, 85,244,242,233,225,238,+ 231,245,236,225,114, 2, 65, 10, 65, 20,232,225,236,230,237,239,+ 100,128, 2,209,237,239,100,128, 2,208,109, 2, 65, 32, 65,217,+ 237, 97,134, 0, 44, 65, 49, 65,113, 65,124, 65,136, 65,166, 65,+ 189, 97, 3, 65, 57, 65, 83, 65, 91,226,239,246,101, 2, 65, 66,+ 65, 72,227,237, 98,128, 3, 19,242,233,231,232,244,227,237, 98,+ 128, 3, 21,227,227,229,238,116,128,246,195,114, 2, 65, 97, 65,+ 104,225,226,233, 99,128, 6, 12,237,229,238,233,225,110,128, 5,+ 93,233,238,230,229,242,233,239,114,128,246,225,237,239,238,239,+ 243,240,225,227,101,128,255, 12,242,229,246,229,242,243,229,100,+ 2, 65,149, 65,160,225,226,239,246,229,227,237, 98,128, 3, 20,+ 237,239,100,128, 2,189,115, 2, 65,172, 65,179,237,225,236,108,+ 128,254, 80,245,240,229,242,233,239,114,128,246,226,244,245,242,+ 238,229,100, 2, 65,200, 65,211,225,226,239,246,229,227,237, 98,+ 128, 3, 18,237,239,100,128, 2,187,240,225,243,115,128, 38, 60,+ 110, 2, 65,230, 65,239,231,242,245,229,238,116,128, 34, 69,116,+ 2, 65,245, 66, 3,239,245,242,233,238,244,229,231,242,225,108,+ 128, 34, 46,242,239,108,142, 35, 3, 66, 37, 66, 43, 66, 58, 66,+ 73, 66,117, 66,162, 66,176, 66,181, 66,186, 66,191, 66,197, 66,+ 202, 66,243, 66,248,193,195, 75,128, 0, 6, 66, 2, 66, 49, 66,+ 54,197, 76,128, 0, 7, 83,128, 0, 8, 67, 2, 66, 64, 66, 69,+ 193, 78,128, 0, 24, 82,128, 0, 13, 68, 3, 66, 81, 66,107, 66,+ 112, 67, 4, 66, 91, 66, 95, 66, 99, 66,103, 49,128, 0, 17, 50,+ 128, 0, 18, 51,128, 0, 19, 52,128, 0, 20,197, 76,128, 0,127,+ 204, 69,128, 0, 16, 69, 5, 66,129, 66,133, 66,138, 66,143, 66,+ 148, 77,128, 0, 25,206, 81,128, 0, 5,207, 84,128, 0, 4,211,+ 67,128, 0, 27, 84, 2, 66,154, 66,158, 66,128, 0, 23, 88,128,+ 0, 3, 70, 2, 66,168, 66,172, 70,128, 0, 12, 83,128, 0, 28,+ 199, 83,128, 0, 29,200, 84,128, 0, 9,204, 70,128, 0, 10,206,+ 193, 75,128, 0, 21,210, 83,128, 0, 30, 83, 5, 66,214, 66,218,+ 66,228, 66,233, 66,238, 73,128, 0, 15, 79,129, 0, 14, 66,224,+ 84,128, 0, 2,212, 88,128, 0, 1,213, 66,128, 0, 26,217, 78,+ 128, 0, 22,213, 83,128, 0, 31,214, 84,128, 0, 11,240,249,242,+ 233,231,232,116,129, 0,169, 67, 9,115, 2, 67, 15, 67, 21,225,+ 238,115,128,248,233,229,242,233,102,128,246,217,114, 2, 67, 34,+ 67,118,238,229,242,226,242,225,227,235,229,116, 2, 67, 49, 67,+ 83,236,229,230,116,130, 48, 12, 67, 60, 67, 72,232,225,236,230,+ 247,233,228,244,104,128,255, 98,246,229,242,244,233,227,225,108,+ 128,254, 65,242,233,231,232,116,130, 48, 13, 67, 95, 67,107,232,+ 225,236,230,247,233,228,244,104,128,255, 99,246,229,242,244,233,+ 227,225,108,128,254, 66,240,239,242,225,244,233,239,238,243,241,+ 245,225,242,101,128, 51,127,243,241,245,225,242,101,128, 51,199,+ 246,229,242,235,231,243,241,245,225,242,101,128, 51,198,240,225,+ 242,229,110,128, 36,158,242,245,250,229,233,242,111,128, 32,162,+ 243,244,242,229,244,227,232,229,100,128, 2,151,245,114, 2, 67,+ 195, 67,213,236,121, 2, 67,202, 67,208,225,238,100,128, 34,207,+ 239,114,128, 34,206,242,229,238,227,121,128, 0,164,249,114, 4,+ 67,232, 67,240, 67,247, 67,255,194,242,229,246,101,128,246,209,+ 198,236,229,120,128,246,210,226,242,229,246,101,128,246,212,230,+ 236,229,120,128,246,213,100,146, 0,100, 68, 46, 69,184, 70,208,+ 71, 12, 71,188, 72,142, 72,204, 73,133, 73,146, 73,155, 73,181,+ 73,206, 73,215, 75, 26, 75, 34, 75, 45, 75, 65, 75, 93, 97, 11,+ 68, 70, 68, 81, 68, 91, 68,163, 68,226, 68,237, 68,248, 69, 61,+ 69,123, 69,129, 69,159,225,242,237,229,238,233,225,110,128, 5,+ 100,226,229,238,231,225,236,105,128, 9,166,100, 5, 68,103, 68,+ 112, 68,118, 68,132, 68,148,225,242,225,226,233, 99,128, 6, 54,+ 229,246, 97,128, 9, 38,230,233,238,225,236,225,242,225,226,233,+ 99,128,254,190,233,238,233,244,233,225,236,225,242,225,226,233,+ 99,128,254,191,237,229,228,233,225,236,225,242,225,226,233, 99,+ 128,254,192,103, 3, 68,171, 68,188, 68,202,229,243,104,129, 5,+ 188, 68,179,232,229,226,242,229,119,128, 5,188,231,229,114,129,+ 32, 32, 68,196,228,226,108,128, 32, 33,117, 2, 68,208, 68,217,+ 234,225,242,225,244,105,128, 10,166,242,237,245,235,232,105,128,+ 10, 38,232,233,242,225,231,225,238, 97,128, 48, 96,235,225,244,+ 225,235,225,238, 97,128, 48,192,108, 3, 69, 0, 69, 9, 69, 47,+ 225,242,225,226,233, 99,128, 6, 47,229,116,130, 5,211, 69, 18,+ 69, 38,228,225,231,229,243,104,129,251, 51, 69, 29,232,229,226,+ 242,229,119,128,251, 51,232,229,226,242,229,119,128, 5,211,230,+ 233,238,225,236,225,242,225,226,233, 99,128,254,170,237,237, 97,+ 3, 69, 71, 69, 80, 69, 92,225,242,225,226,233, 99,128, 6, 79,+ 236,239,247,225,242,225,226,233, 99,128, 6, 79,244,225,238, 97,+ 2, 69,101, 69,115,236,244,239,238,229,225,242,225,226,233, 99,+ 128, 6, 76,242,225,226,233, 99,128, 6, 76,238,228, 97,128, 9,+ 100,242,231, 97, 2, 69,137, 69,146,232,229,226,242,229,119,128,+ 5,167,236,229,230,244,232,229,226,242,229,119,128, 5,167,243,+ 233,225,240,238,229,245,237,225,244,225,227,249,242,233,236,236,+ 233,227,227,237, 98,128, 4,133, 98, 3, 69,192, 70,189, 70,199,+ 108, 9, 69,212, 69,220, 70, 77, 70, 85, 70,101, 70,112, 70,130,+ 70,144, 70,155,199,242,225,246,101,128,246,211, 97, 2, 69,226,+ 70, 27,238,231,236,229,226,242,225,227,235,229,116, 2, 69,242,+ 70, 6,236,229,230,116,129, 48, 10, 69,251,246,229,242,244,233,+ 227,225,108,128,254, 61,242,233,231,232,116,129, 48, 11, 70, 16,+ 246,229,242,244,233,227,225,108,128,254, 62,114, 2, 70, 33, 70,+ 54,227,232,233,238,246,229,242,244,229,228,226,229,236,239,247,+ 227,237, 98,128, 3, 43,242,239,119, 2, 70, 62, 70, 69,236,229,+ 230,116,128, 33,212,242,233,231,232,116,128, 33,210,228,225,238,+ 228, 97,128, 9,101,231,242,225,246,101,129,246,214, 70, 95,227,+ 237, 98,128, 3, 15,233,238,244,229,231,242,225,108,128, 34, 44,+ 236,239,247,236,233,238,101,129, 32, 23, 70,124,227,237, 98,128,+ 3, 51,239,246,229,242,236,233,238,229,227,237, 98,128, 3, 63,+ 240,242,233,237,229,237,239,100,128, 2,186,246,229,242,244,233,+ 227,225,108, 2, 70,168, 70,174,226,225,114,128, 32, 22,236,233,+ 238,229,225,226,239,246,229,227,237, 98,128, 3, 14,239,240,239,+ 237,239,230,111,128, 49, 9,243,241,245,225,242,101,128, 51,200,+ 99, 4, 70,218, 70,225, 70,234, 71, 5,225,242,239,110,128, 1,+ 15,229,228,233,236,236, 97,128, 30, 17,233,242, 99, 2, 70,242,+ 70,247,236,101,128, 36,211,245,237,230,236,229,248,226,229,236,+ 239,119,128, 30, 19,242,239,225,116,128, 1, 17,100, 4, 71, 22,+ 71,103, 71,113, 71,164, 97, 4, 71, 32, 71, 42, 71, 49, 71, 74,+ 226,229,238,231,225,236,105,128, 9,161,228,229,246, 97,128, 9,+ 33,231,117, 2, 71, 56, 71, 65,234,225,242,225,244,105,128, 10,+ 161,242,237,245,235,232,105,128, 10, 33,108, 2, 71, 80, 71, 89,+ 225,242,225,226,233, 99,128, 6,136,230,233,238,225,236,225,242,+ 225,226,233, 99,128,251,137,228,232,225,228,229,246, 97,128, 9,+ 92,232, 97, 3, 71,122, 71,132, 71,139,226,229,238,231,225,236,+ 105,128, 9,162,228,229,246, 97,128, 9, 34,231,117, 2, 71,146,+ 71,155,234,225,242,225,244,105,128, 10,162,242,237,245,235,232,+ 105,128, 10, 34,239,116, 2, 71,171, 71,180,225,227,227,229,238,+ 116,128, 30, 11,226,229,236,239,119,128, 30, 13,101, 8, 71,206,+ 72, 3, 72, 10, 72, 35, 72, 45, 72, 56, 72,101, 72,137, 99, 2,+ 71,212, 71,249,233,237,225,236,243,229,240,225,242,225,244,239,+ 114, 2, 71,230, 71,239,225,242,225,226,233, 99,128, 6,107,240,+ 229,242,243,233,225,110,128, 6,107,249,242,233,236,236,233, 99,+ 128, 4, 52,231,242,229,101,128, 0,176,232,105, 2, 72, 17, 72,+ 26,232,229,226,242,229,119,128, 5,173,242,225,231,225,238, 97,+ 128, 48,103,233,227,239,240,244,233, 99,128, 3,239,235,225,244,+ 225,235,225,238, 97,128, 48,199,108, 2, 72, 62, 72, 85,229,244,+ 101, 2, 72, 70, 72, 77,236,229,230,116,128, 35, 43,242,233,231,+ 232,116,128, 35, 38,244, 97,129, 3,180, 72, 92,244,245,242,238,+ 229,100,128, 1,141,238,239,237,233,238,225,244,239,242,237,233,+ 238,245,243,239,238,229,238,245,237,229,242,225,244,239,242,226,+ 229,238,231,225,236,105,128, 9,248,250,104,128, 2,164,104, 2,+ 72,148, 72,198, 97, 3, 72,156, 72,166, 72,173,226,229,238,231,+ 225,236,105,128, 9,167,228,229,246, 97,128, 9, 39,231,117, 2,+ 72,180, 72,189,234,225,242,225,244,105,128, 10,167,242,237,245,+ 235,232,105,128, 10, 39,239,239,107,128, 2, 87,105, 6, 72,218,+ 73, 11, 73, 71, 73, 82, 73, 93, 73,103, 97, 2, 72,224, 72,246,+ 236,249,244,233,235,225,244,239,238,239,115,129, 3,133, 72,240,+ 227,237, 98,128, 3, 68,237,239,238,100,129, 38,102, 72,255,243,+ 245,233,244,247,232,233,244,101,128, 38, 98,229,242,229,243,233,+ 115,133, 0,168, 73, 30, 73, 38, 73, 49, 73, 55, 73, 63,225,227,+ 245,244,101,128,246,215,226,229,236,239,247,227,237, 98,128, 3,+ 36,227,237, 98,128, 3, 8,231,242,225,246,101,128,246,216,244,+ 239,238,239,115,128, 3,133,232,233,242,225,231,225,238, 97,128,+ 48, 98,235,225,244,225,235,225,238, 97,128, 48,194,244,244,239,+ 237,225,242,107,128, 48, 3,246,105, 2, 73,110, 73,121,228,101,+ 129, 0,247, 73,117,115,128, 34, 35,243,233,239,238,243,236,225,+ 243,104,128, 34, 21,234,229,227,249,242,233,236,236,233, 99,128,+ 4, 82,235,243,232,225,228,101,128, 37,147,108, 2, 73,161, 73,+ 172,233,238,229,226,229,236,239,119,128, 30, 15,243,241,245,225,+ 242,101,128, 51,151,109, 2, 73,187, 73,195,225,227,242,239,110,+ 128, 1, 17,239,238,239,243,240,225,227,101,128,255, 68,238,226,+ 236,239,227,107,128, 37,132,111, 10, 73,237, 73,249, 74, 3, 74,+ 14, 74, 25, 74, 97, 74,102, 74,113, 74,228, 74,254,227,232,225,+ 228,225,244,232,225,105,128, 14, 14,228,229,235,244,232,225,105,+ 128, 14, 20,232,233,242,225,231,225,238, 97,128, 48,105,235,225,+ 244,225,235,225,238, 97,128, 48,201,236,236,225,114,132, 0, 36,+ 74, 40, 74, 51, 74, 63, 74, 74,233,238,230,229,242,233,239,114,+ 128,246,227,237,239,238,239,243,240,225,227,101,128,255, 4,239,+ 236,228,243,244,249,236,101,128,247, 36,115, 2, 74, 80, 74, 87,+ 237,225,236,108,128,254,105,245,240,229,242,233,239,114,128,246,+ 228,238,103,128, 32,171,242,245,243,241,245,225,242,101,128, 51,+ 38,116, 6, 74,127, 74,144, 74,166, 74,177, 74,209, 74,216,225,+ 227,227,229,238,116,129, 2,217, 74,138,227,237, 98,128, 3, 7,+ 226,229,236,239,247, 99, 2, 74,155, 74,160,237, 98,128, 3, 35,+ 239,237, 98,128, 3, 35,235,225,244,225,235,225,238, 97,128, 48,+ 251,236,229,243,115, 2, 74,186, 74,190,105,128, 1, 49,106,129,+ 246,190, 74,196,243,244,242,239,235,229,232,239,239,107,128, 2,+ 132,237,225,244,104,128, 34,197,244,229,228,227,233,242,227,236,+ 101,128, 37,204,245,226,236,229,249,239,228,240,225,244,225,104,+ 129,251, 31, 74,245,232,229,226,242,229,119,128,251, 31,247,238,+ 244,225,227,107, 2, 75, 9, 75, 20,226,229,236,239,247,227,237,+ 98,128, 3, 30,237,239,100,128, 2,213,240,225,242,229,110,128,+ 36,159,243,245,240,229,242,233,239,114,128,246,235,116, 2, 75,+ 51, 75, 57,225,233,108,128, 2, 86,239,240,226,225,114,128, 1,+ 140,117, 2, 75, 71, 75, 82,232,233,242,225,231,225,238, 97,128,+ 48,101,235,225,244,225,235,225,238, 97,128, 48,197,122,132, 1,+ 243, 75,105, 75,114, 75,133, 75,170,225,236,244,239,238,101,128,+ 2,163, 99, 2, 75,120, 75,127,225,242,239,110,128, 1,198,245,+ 242,108,128, 2,165,101, 2, 75,139, 75,159,225,226,235,232,225,+ 243,233,225,238,227,249,242,233,236,236,233, 99,128, 4,225,227,+ 249,242,233,236,236,233, 99,128, 4, 85,232,229,227,249,242,233,+ 236,236,233, 99,128, 4, 95,101,151, 0,101, 75,233, 75,252, 76,+ 30, 77, 4, 77, 66, 77, 99, 77,111, 77,134, 77,187, 79, 43, 79,+ 101, 79,203, 80, 63, 80,198, 81, 17, 81, 48, 81,110, 81,163, 82,+ 98, 82,231, 82,251, 83, 39, 83,130, 97, 2, 75,239, 75,246,227,+ 245,244,101,128, 0,233,242,244,104,128, 38, 65, 98, 3, 76, 4,+ 76, 13, 76, 23,229,238,231,225,236,105,128, 9,143,239,240,239,+ 237,239,230,111,128, 49, 28,242,229,246,101,128, 1, 21, 99, 5,+ 76, 42, 76,115, 76,129, 76,161, 76,250, 97, 2, 76, 48, 76,109,+ 238,228,242, 97, 3, 76, 59, 76, 66, 76, 77,228,229,246, 97,128,+ 9, 13,231,245,234,225,242,225,244,105,128, 10,141,246,239,247,+ 229,236,243,233,231,110, 2, 76, 91, 76, 98,228,229,246, 97,128,+ 9, 69,231,245,234,225,242,225,244,105,128, 10,197,242,239,110,+ 128, 1, 27,229,228,233,236,236,225,226,242,229,246,101,128, 30,+ 29,104, 2, 76,135, 76,146,225,242,237,229,238,233,225,110,128,+ 5,101,249,233,247,238,225,242,237,229,238,233,225,110,128, 5,+ 135,233,242, 99, 2, 76,169, 76,174,236,101,128, 36,212,245,237,+ 230,236,229,120,134, 0,234, 76,195, 76,203, 76,211, 76,222, 76,+ 230, 76,242,225,227,245,244,101,128, 30,191,226,229,236,239,119,+ 128, 30, 25,228,239,244,226,229,236,239,119,128, 30,199,231,242,+ 225,246,101,128, 30,193,232,239,239,235,225,226,239,246,101,128,+ 30,195,244,233,236,228,101,128, 30,197,249,242,233,236,236,233,+ 99,128, 4, 84,100, 4, 77, 14, 77, 24, 77, 30, 77, 40,226,236,+ 231,242,225,246,101,128, 2, 5,229,246, 97,128, 9, 15,233,229,+ 242,229,243,233,115,128, 0,235,239,116,130, 1, 23, 77, 49, 77,+ 58,225,227,227,229,238,116,128, 1, 23,226,229,236,239,119,128,+ 30,185,101, 2, 77, 72, 77, 83,231,245,242,237,245,235,232,105,+ 128, 10, 15,237,225,244,242,225,231,245,242,237,245,235,232,105,+ 128, 10, 71,230,227,249,242,233,236,236,233, 99,128, 4, 68,103,+ 2, 77,117, 77,124,242,225,246,101,128, 0,232,245,234,225,242,+ 225,244,105,128, 10,143,104, 4, 77,144, 77,155, 77,166, 77,176,+ 225,242,237,229,238,233,225,110,128, 5,103,226,239,240,239,237,+ 239,230,111,128, 49, 29,233,242,225,231,225,238, 97,128, 48, 72,+ 239,239,235,225,226,239,246,101,128, 30,187,105, 4, 77,197, 77,+ 208, 79, 10, 79, 25,226,239,240,239,237,239,230,111,128, 49, 31,+ 231,232,116,142, 0, 56, 77,242, 77,251, 78, 5, 78, 35, 78, 42,+ 78, 80, 78,105, 78,150, 78,184, 78,196, 78,207, 78,240, 78,248,+ 79, 3,225,242,225,226,233, 99,128, 6,104,226,229,238,231,225,+ 236,105,128, 9,238,227,233,242,227,236,101,129, 36,103, 78, 16,+ 233,238,246,229,242,243,229,243,225,238,243,243,229,242,233,102,+ 128, 39,145,228,229,246, 97,128, 9,110,229,229,110, 2, 78, 50,+ 78, 59,227,233,242,227,236,101,128, 36,113,112, 2, 78, 65, 78,+ 72,225,242,229,110,128, 36,133,229,242,233,239,100,128, 36,153,+ 231,117, 2, 78, 87, 78, 96,234,225,242,225,244,105,128, 10,238,+ 242,237,245,235,232,105,128, 10,110,104, 2, 78,111, 78,137, 97,+ 2, 78,117, 78,128,227,235,225,242,225,226,233, 99,128, 6,104,+ 238,231,250,232,239,117,128, 48, 40,238,239,244,229,226,229,225,+ 237,229,100,128, 38,107,105, 2, 78,156, 78,174,228,229,239,231,+ 242,225,240,232,233,227,240,225,242,229,110,128, 50, 39,238,230,+ 229,242,233,239,114,128, 32,136,237,239,238,239,243,240,225,227,+ 101,128,255, 24,239,236,228,243,244,249,236,101,128,247, 56,112,+ 2, 78,213, 78,220,225,242,229,110,128, 36,123,229,114, 2, 78,+ 227, 78,233,233,239,100,128, 36,143,243,233,225,110,128, 6,248,+ 242,239,237,225,110,128, 33,119,243,245,240,229,242,233,239,114,+ 128, 32,120,244,232,225,105,128, 14, 88,238,246,229,242,244,229,+ 228,226,242,229,246,101,128, 2, 7,239,244,233,230,233,229,228,+ 227,249,242,233,236,236,233, 99,128, 4,101,107, 2, 79, 49, 79,+ 73,225,244,225,235,225,238, 97,129, 48,168, 79, 61,232,225,236,+ 230,247,233,228,244,104,128,255,116,111, 2, 79, 79, 79, 94,238,+ 235,225,242,231,245,242,237,245,235,232,105,128, 10,116,242,229,+ 225,110,128, 49, 84,108, 3, 79,109, 79,120, 79,181,227,249,242,+ 233,236,236,233, 99,128, 4, 59,101, 2, 79,126, 79,133,237,229,+ 238,116,128, 34, 8,246,229,110, 3, 79,143, 79,152, 79,173,227,+ 233,242,227,236,101,128, 36,106,112, 2, 79,158, 79,165,225,242,+ 229,110,128, 36,126,229,242,233,239,100,128, 36,146,242,239,237,+ 225,110,128, 33,122,236,233,240,243,233,115,129, 32, 38, 79,192,+ 246,229,242,244,233,227,225,108,128, 34,238,109, 5, 79,215, 79,+ 243, 79,254, 80, 18, 80, 29,225,227,242,239,110,130, 1, 19, 79,+ 227, 79,235,225,227,245,244,101,128, 30, 23,231,242,225,246,101,+ 128, 30, 21,227,249,242,233,236,236,233, 99,128, 4, 60,228,225,+ 243,104,129, 32, 20, 80, 7,246,229,242,244,233,227,225,108,128,+ 254, 49,239,238,239,243,240,225,227,101,128,255, 69,112, 2, 80,+ 35, 80, 55,232,225,243,233,243,237,225,242,235,225,242,237,229,+ 238,233,225,110,128, 5, 91,244,249,243,229,116,128, 34, 5,110,+ 6, 80, 77, 80, 88, 80, 99, 80,143, 80,175, 80,190,226,239,240,+ 239,237,239,230,111,128, 49, 35,227,249,242,233,236,236,233, 99,+ 128, 4, 61,100, 2, 80,105, 80,124,225,243,104,129, 32, 19, 80,+ 113,246,229,242,244,233,227,225,108,128,254, 50,229,243,227,229,+ 238,228,229,242,227,249,242,233,236,236,233, 99,128, 4,163,103,+ 130, 1, 75, 80,151, 80,162,226,239,240,239,237,239,230,111,128,+ 49, 37,232,229,227,249,242,233,236,236,233, 99,128, 4,165,232,+ 239,239,235,227,249,242,233,236,236,233, 99,128, 4,200,243,240,+ 225,227,101,128, 32, 2,111, 3, 80,206, 80,214, 80,223,231,239,+ 238,229,107,128, 1, 25,235,239,242,229,225,110,128, 49, 83,240,+ 229,110,130, 2, 91, 80,233, 80,242,227,236,239,243,229,100,128,+ 2,154,242,229,246,229,242,243,229,100,130, 2, 92, 81, 1, 81,+ 10,227,236,239,243,229,100,128, 2, 94,232,239,239,107,128, 2,+ 93,112, 2, 81, 23, 81, 30,225,242,229,110,128, 36,160,243,233,+ 236,239,110,129, 3,181, 81, 40,244,239,238,239,115,128, 3,173,+ 241,117, 2, 81, 55, 81, 99,225,108,130, 0, 61, 81, 64, 81, 76,+ 237,239,238,239,243,240,225,227,101,128,255, 29,115, 2, 81, 82,+ 81, 89,237,225,236,108,128,254,102,245,240,229,242,233,239,114,+ 128, 32,124,233,246,225,236,229,238,227,101,128, 34, 97,114, 3,+ 81,118, 81,129, 81,140,226,239,240,239,237,239,230,111,128, 49,+ 38,227,249,242,233,236,236,233, 99,128, 4, 64,229,246,229,242,+ 243,229,100,129, 2, 88, 81,152,227,249,242,233,236,236,233, 99,+ 128, 4, 77,115, 6, 81,177, 81,188, 81,208, 82, 33, 82, 78, 82,+ 88,227,249,242,233,236,236,233, 99,128, 4, 65,228,229,243,227,+ 229,238,228,229,242,227,249,242,233,236,236,233, 99,128, 4,171,+ 104,132, 2,131, 81,220, 81,227, 82, 2, 82, 17,227,245,242,108,+ 128, 2,134,239,242,116, 2, 81,235, 81,242,228,229,246, 97,128,+ 9, 14,246,239,247,229,236,243,233,231,238,228,229,246, 97,128,+ 9, 70,242,229,246,229,242,243,229,228,236,239,239,112,128, 1,+ 170,243,241,245,225,244,242,229,246,229,242,243,229,100,128, 2,+ 133,237,225,236,108, 2, 82, 42, 82, 53,232,233,242,225,231,225,+ 238, 97,128, 48, 71,235,225,244,225,235,225,238, 97,129, 48,167,+ 82, 66,232,225,236,230,247,233,228,244,104,128,255,106,244,233,+ 237,225,244,229,100,128, 33, 46,245,240,229,242,233,239,114,128,+ 246,236,116, 5, 82,110, 82,136, 82,140, 82,157, 82,223, 97,130,+ 3,183, 82,118, 82,128,242,237,229,238,233,225,110,128, 5,104,+ 244,239,238,239,115,128, 3,174,104,128, 0,240,233,236,228,101,+ 129, 30,189, 82,149,226,229,236,239,119,128, 30, 27,238,225,232,+ 244, 97, 3, 82,169, 82,201, 82,210,230,239,245,235,104, 2, 82,+ 179, 82,188,232,229,226,242,229,119,128, 5,145,236,229,230,244,+ 232,229,226,242,229,119,128, 5,145,232,229,226,242,229,119,128,+ 5,145,236,229,230,244,232,229,226,242,229,119,128, 5,145,245,+ 242,238,229,100,128, 1,221,117, 2, 82,237, 82,246,235,239,242,+ 229,225,110,128, 49, 97,242,111,128, 32,172,246,239,247,229,236,+ 243,233,231,110, 3, 83, 11, 83, 21, 83, 28,226,229,238,231,225,+ 236,105,128, 9,199,228,229,246, 97,128, 9, 71,231,245,234,225,+ 242,225,244,105,128, 10,199,120, 2, 83, 45, 83,118,227,236,225,+ 109,132, 0, 33, 83, 60, 83, 71, 83, 98, 83,110,225,242,237,229,+ 238,233,225,110,128, 5, 92,100, 2, 83, 77, 83, 82,226,108,128,+ 32, 60,239,247,110,129, 0,161, 83, 90,243,237,225,236,108,128,+ 247,161,237,239,238,239,243,240,225,227,101,128,255, 1,243,237,+ 225,236,108,128,247, 33,233,243,244,229,238,244,233,225,108,128,+ 34, 3,250,104,131, 2,146, 83,141, 83,160, 83,171, 99, 2, 83,+ 147, 83,154,225,242,239,110,128, 1,239,245,242,108,128, 2,147,+ 242,229,246,229,242,243,229,100,128, 1,185,244,225,233,108,128,+ 1,186,102,140, 0,102, 83,206, 84, 32, 84, 43, 84, 52, 84, 64,+ 84,167, 84,183, 86,191, 86,204, 86,230, 88,107, 88,115, 97, 4,+ 83,216, 83,223, 83,234, 83,245,228,229,246, 97,128, 9, 94,231,+ 245,242,237,245,235,232,105,128, 10, 94,232,242,229,238,232,229,+ 233,116,128, 33, 9,244,232, 97, 3, 83,255, 84, 8, 84, 20,225,+ 242,225,226,233, 99,128, 6, 78,236,239,247,225,242,225,226,233,+ 99,128, 6, 78,244,225,238,225,242,225,226,233, 99,128, 6, 75,+ 226,239,240,239,237,239,230,111,128, 49, 8,227,233,242,227,236,+ 101,128, 36,213,228,239,244,225,227,227,229,238,116,128, 30, 31,+ 101, 3, 84, 72, 84,150, 84,160,104, 4, 84, 82, 84,105, 84,119,+ 84,135,225,114, 2, 84, 89, 84, 96,225,226,233, 99,128, 6, 65,+ 237,229,238,233,225,110,128, 5,134,230,233,238,225,236,225,242,+ 225,226,233, 99,128,254,210,233,238,233,244,233,225,236,225,242,+ 225,226,233, 99,128,254,211,237,229,228,233,225,236,225,242,225,+ 226,233, 99,128,254,212,233,227,239,240,244,233, 99,128, 3,229,+ 237,225,236,101,128, 38, 64,102,130,251, 0, 84,175, 84,179,105,+ 128,251, 3,108,128,251, 4,105,136,251, 1, 84,203, 84,243, 84,+ 254, 85, 20, 85,142, 85,159, 85,167, 85,180,230,244,229,229,110,+ 2, 84,213, 84,222,227,233,242,227,236,101,128, 36,110,112, 2,+ 84,228, 84,235,225,242,229,110,128, 36,130,229,242,233,239,100,+ 128, 36,150,231,245,242,229,228,225,243,104,128, 32, 18,236,236,+ 229,100, 2, 85, 7, 85, 13,226,239,120,128, 37,160,242,229,227,+ 116,128, 37,172,238,225,108, 5, 85, 34, 85, 73, 85, 90, 85,107,+ 85,123,235,225,102,130, 5,218, 85, 44, 85, 64,228,225,231,229,+ 243,104,129,251, 58, 85, 55,232,229,226,242,229,119,128,251, 58,+ 232,229,226,242,229,119,128, 5,218,237,229,109,129, 5,221, 85,+ 81,232,229,226,242,229,119,128, 5,221,238,245,110,129, 5,223,+ 85, 98,232,229,226,242,229,119,128, 5,223,240,101,129, 5,227,+ 85,114,232,229,226,242,229,119,128, 5,227,244,243,225,228,105,+ 129, 5,229, 85,133,232,229,226,242,229,119,128, 5,229,242,243,+ 244,244,239,238,229,227,232,233,238,229,243,101,128, 2,201,243,+ 232,229,249,101,128, 37,201,244,225,227,249,242,233,236,236,233,+ 99,128, 4,115,246,101,142, 0, 53, 85,213, 85,222, 85,232, 86,+ 6, 86, 13, 86, 23, 86, 48, 86, 75, 86,109, 86,121, 86,132, 86,+ 165, 86,173, 86,184,225,242,225,226,233, 99,128, 6,101,226,229,+ 238,231,225,236,105,128, 9,235,227,233,242,227,236,101,129, 36,+ 100, 85,243,233,238,246,229,242,243,229,243,225,238,243,243,229,+ 242,233,102,128, 39,142,228,229,246, 97,128, 9,107,229,233,231,+ 232,244,232,115,128, 33, 93,231,117, 2, 86, 30, 86, 39,234,225,+ 242,225,244,105,128, 10,235,242,237,245,235,232,105,128, 10,107,+ 232, 97, 2, 86, 55, 86, 66,227,235,225,242,225,226,233, 99,128,+ 6,101,238,231,250,232,239,117,128, 48, 37,105, 2, 86, 81, 86,+ 99,228,229,239,231,242,225,240,232,233,227,240,225,242,229,110,+ 128, 50, 36,238,230,229,242,233,239,114,128, 32,133,237,239,238,+ 239,243,240,225,227,101,128,255, 21,239,236,228,243,244,249,236,+ 101,128,247, 53,112, 2, 86,138, 86,145,225,242,229,110,128, 36,+ 120,229,114, 2, 86,152, 86,158,233,239,100,128, 36,140,243,233,+ 225,110,128, 6,245,242,239,237,225,110,128, 33,116,243,245,240,+ 229,242,233,239,114,128, 32,117,244,232,225,105,128, 14, 85,108,+ 129,251, 2, 86,197,239,242,233,110,128, 1,146,109, 2, 86,210,+ 86,221,239,238,239,243,240,225,227,101,128,255, 70,243,241,245,+ 225,242,101,128, 51,153,111, 4, 86,240, 87, 6, 87, 18, 87, 25,+ 230, 97, 2, 86,247, 86,255,238,244,232,225,105,128, 14, 31,244,+ 232,225,105,128, 14, 29,238,231,237,225,238,244,232,225,105,128,+ 14, 79,242,225,236,108,128, 34, 0,245,114,142, 0, 52, 87, 58,+ 87, 67, 87, 77, 87,107, 87,114, 87,139, 87,166, 87,200, 87,212,+ 87,231, 87,242, 88, 19, 88, 27, 88, 38,225,242,225,226,233, 99,+ 128, 6,100,226,229,238,231,225,236,105,128, 9,234,227,233,242,+ 227,236,101,129, 36, 99, 87, 88,233,238,246,229,242,243,229,243,+ 225,238,243,243,229,242,233,102,128, 39,141,228,229,246, 97,128,+ 9,106,231,117, 2, 87,121, 87,130,234,225,242,225,244,105,128,+ 10,234,242,237,245,235,232,105,128, 10,106,232, 97, 2, 87,146,+ 87,157,227,235,225,242,225,226,233, 99,128, 6,100,238,231,250,+ 232,239,117,128, 48, 36,105, 2, 87,172, 87,190,228,229,239,231,+ 242,225,240,232,233,227,240,225,242,229,110,128, 50, 35,238,230,+ 229,242,233,239,114,128, 32,132,237,239,238,239,243,240,225,227,+ 101,128,255, 20,238,245,237,229,242,225,244,239,242,226,229,238,+ 231,225,236,105,128, 9,247,239,236,228,243,244,249,236,101,128,+ 247, 52,112, 2, 87,248, 87,255,225,242,229,110,128, 36,119,229,+ 114, 2, 88, 6, 88, 12,233,239,100,128, 36,139,243,233,225,110,+ 128, 6,244,242,239,237,225,110,128, 33,115,243,245,240,229,242,+ 233,239,114,128, 32,116,116, 2, 88, 44, 88, 82,229,229,110, 2,+ 88, 52, 88, 61,227,233,242,227,236,101,128, 36,109,112, 2, 88,+ 67, 88, 74,225,242,229,110,128, 36,129,229,242,233,239,100,128,+ 36,149,104, 2, 88, 88, 88, 93,225,105,128, 14, 84,244,239,238,+ 229,227,232,233,238,229,243,101,128, 2,203,240,225,242,229,110,+ 128, 36,161,242, 97, 2, 88,122, 88,130,227,244,233,239,110,128,+ 32, 68,238, 99,128, 32,163,103,144, 0,103, 88,171, 89,117, 89,+ 140, 89,201, 89,218, 90,139, 91,132, 91,217, 91,230, 92, 88, 92,+ 113, 92,141, 92,163, 93,108, 93,130, 93,232, 97, 9, 88,191, 88,+ 201, 88,208, 88,215, 89, 23, 89, 48, 89, 59, 89, 70, 89,104,226,+ 229,238,231,225,236,105,128, 9,151,227,245,244,101,128, 1,245,+ 228,229,246, 97,128, 9, 23,102, 4, 88,225, 88,234, 88,248, 89,+ 8,225,242,225,226,233, 99,128, 6,175,230,233,238,225,236,225,+ 242,225,226,233, 99,128,251,147,233,238,233,244,233,225,236,225,+ 242,225,226,233, 99,128,251,148,237,229,228,233,225,236,225,242,+ 225,226,233, 99,128,251,149,231,117, 2, 89, 30, 89, 39,234,225,+ 242,225,244,105,128, 10,151,242,237,245,235,232,105,128, 10, 23,+ 232,233,242,225,231,225,238, 97,128, 48, 76,235,225,244,225,235,+ 225,238, 97,128, 48,172,237,237, 97,130, 3,179, 89, 80, 89, 93,+ 236,225,244,233,238,243,237,225,236,108,128, 2, 99,243,245,240,+ 229,242,233,239,114,128, 2,224,238,231,233,225,227,239,240,244,+ 233, 99,128, 3,235, 98, 2, 89,123, 89,133,239,240,239,237,239,+ 230,111,128, 49, 13,242,229,246,101,128, 1, 31, 99, 4, 89,150,+ 89,157, 89,166, 89,188,225,242,239,110,128, 1,231,229,228,233,+ 236,236, 97,128, 1, 35,233,242, 99, 2, 89,174, 89,179,236,101,+ 128, 36,214,245,237,230,236,229,120,128, 1, 29,239,237,237,225,+ 225,227,227,229,238,116,128, 1, 35,228,239,116,129, 1, 33, 89,+ 209,225,227,227,229,238,116,128, 1, 33,101, 6, 89,232, 89,243,+ 89,254, 90, 9, 90, 28, 90,130,227,249,242,233,236,236,233, 99,+ 128, 4, 51,232,233,242,225,231,225,238, 97,128, 48, 82,235,225,+ 244,225,235,225,238, 97,128, 48,178,239,237,229,244,242,233,227,+ 225,236,236,249,229,241,245,225,108,128, 34, 81,114, 3, 90, 36,+ 90, 85, 90, 95,229,243,104, 3, 90, 46, 90, 61, 90, 70,225,227,+ 227,229,238,244,232,229,226,242,229,119,128, 5,156,232,229,226,+ 242,229,119,128, 5,243,237,245,241,228,225,237,232,229,226,242,+ 229,119,128, 5,157,237,225,238,228,226,236,115,128, 0,223,243,+ 232,225,249,233,109, 2, 90,106, 90,121,225,227,227,229,238,244,+ 232,229,226,242,229,119,128, 5,158,232,229,226,242,229,119,128,+ 5,244,244,225,237,225,242,107,128, 48, 19,104, 5, 90,151, 91,+ 28, 91, 91, 91,116, 91,122, 97, 4, 90,161, 90,171, 90,194, 90,+ 219,226,229,238,231,225,236,105,128, 9,152,100, 2, 90,177, 90,+ 188,225,242,237,229,238,233,225,110,128, 5,114,229,246, 97,128,+ 9, 24,231,117, 2, 90,201, 90,210,234,225,242,225,244,105,128,+ 10,152,242,237,245,235,232,105,128, 10, 24,233,110, 4, 90,230,+ 90,239, 90,253, 91, 13,225,242,225,226,233, 99,128, 6, 58,230,+ 233,238,225,236,225,242,225,226,233, 99,128,254,206,233,238,233,+ 244,233,225,236,225,242,225,226,233, 99,128,254,207,237,229,228,+ 233,225,236,225,242,225,226,233, 99,128,254,208,101, 3, 91, 36,+ 91, 57, 91, 74,237,233,228,228,236,229,232,239,239,235,227,249,+ 242,233,236,236,233, 99,128, 4,149,243,244,242,239,235,229,227,+ 249,242,233,236,236,233, 99,128, 4,147,245,240,244,245,242,238,+ 227,249,242,233,236,236,233, 99,128, 4,145,232, 97, 2, 91, 98,+ 91,105,228,229,246, 97,128, 9, 90,231,245,242,237,245,235,232,+ 105,128, 10, 90,239,239,107,128, 2, 96,250,243,241,245,225,242,+ 101,128, 51,147,105, 3, 91,140, 91,151, 91,162,232,233,242,225,+ 231,225,238, 97,128, 48, 78,235,225,244,225,235,225,238, 97,128,+ 48,174,109, 2, 91,168, 91,179,225,242,237,229,238,233,225,110,+ 128, 5, 99,229,108,130, 5,210, 91,188, 91,208,228,225,231,229,+ 243,104,129,251, 50, 91,199,232,229,226,242,229,119,128,251, 50,+ 232,229,226,242,229,119,128, 5,210,234,229,227,249,242,233,236,+ 236,233, 99,128, 4, 83,236,239,244,244,225,108, 2, 91,241, 92,+ 2,233,238,246,229,242,244,229,228,243,244,242,239,235,101,128,+ 1,190,243,244,239,112,132, 2,148, 92, 17, 92, 28, 92, 34, 92,+ 66,233,238,246,229,242,244,229,100,128, 2,150,237,239,100,128,+ 2,192,242,229,246,229,242,243,229,100,130, 2,149, 92, 49, 92,+ 55,237,239,100,128, 2,193,243,245,240,229,242,233,239,114,128,+ 2,228,243,244,242,239,235,101,129, 2,161, 92, 77,242,229,246,+ 229,242,243,229,100,128, 2,162,109, 2, 92, 94, 92,102,225,227,+ 242,239,110,128, 30, 33,239,238,239,243,240,225,227,101,128,255,+ 71,111, 2, 92,119, 92,130,232,233,242,225,231,225,238, 97,128,+ 48, 84,235,225,244,225,235,225,238, 97,128, 48,180,240, 97, 2,+ 92,148, 92,154,242,229,110,128, 36,162,243,241,245,225,242,101,+ 128, 51,172,114, 2, 92,169, 93, 10, 97, 2, 92,175, 92,183,228,+ 233,229,238,116,128, 34, 7,246,101,134, 0, 96, 92,200, 92,211,+ 92,228, 92,235, 92,244, 93, 0,226,229,236,239,247,227,237, 98,+ 128, 3, 22, 99, 2, 92,217, 92,222,237, 98,128, 3, 0,239,237,+ 98,128, 3, 0,228,229,246, 97,128, 9, 83,236,239,247,237,239,+ 100,128, 2,206,237,239,238,239,243,240,225,227,101,128,255, 64,+ 244,239,238,229,227,237, 98,128, 3, 64,229,225,244,229,114,132,+ 0, 62, 93, 26, 93, 45, 93, 57, 93,100,229,241,245,225,108,129,+ 34,101, 93, 36,239,242,236,229,243,115,128, 34,219,237,239,238,+ 239,243,240,225,227,101,128,255, 30,111, 2, 93, 63, 93, 89,114,+ 2, 93, 69, 93, 82,229,241,245,233,246,225,236,229,238,116,128,+ 34,115,236,229,243,115,128, 34,119,246,229,242,229,241,245,225,+ 108,128, 34,103,243,237,225,236,108,128,254,101,115, 2, 93,114,+ 93,122,227,242,233,240,116,128, 2, 97,244,242,239,235,101,128,+ 1,229,117, 4, 93,140, 93,151, 93,208, 93,219,232,233,242,225,+ 231,225,238, 97,128, 48, 80,233,108, 2, 93,158, 93,183,236,229,+ 237,239,116, 2, 93,168, 93,175,236,229,230,116,128, 0,171,242,+ 233,231,232,116,128, 0,187,243,233,238,231,108, 2, 93,193, 93,+ 200,236,229,230,116,128, 32, 57,242,233,231,232,116,128, 32, 58,+ 235,225,244,225,235,225,238, 97,128, 48,176,242,225,237,245,243,+ 241,245,225,242,101,128, 51, 24,249,243,241,245,225,242,101,128,+ 51,201,104,144, 0,104, 94, 22, 96,164, 96,199, 96,236, 97, 20,+ 98,164, 98,184, 99,149, 99,161, 99,173,100,241,100,249,101, 4,+ 101, 13,101, 93,101, 97, 97, 13, 94, 50, 94, 89, 94, 99, 94,129,+ 94,154, 94,232, 94,244, 95, 13, 95, 28, 95, 57, 95, 70, 95,128,+ 95,137, 97, 2, 94, 56, 94, 75,226,235,232,225,243,233,225,238,+ 227,249,242,233,236,236,233, 99,128, 4,169,236,244,239,238,229,+ 225,242,225,226,233, 99,128, 6,193,226,229,238,231,225,236,105,+ 128, 9,185,228,101, 2, 94,106, 94,124,243,227,229,238,228,229,+ 242,227,249,242,233,236,236,233, 99,128, 4,179,246, 97,128, 9,+ 57,231,117, 2, 94,136, 94,145,234,225,242,225,244,105,128, 10,+ 185,242,237,245,235,232,105,128, 10, 57,104, 4, 94,164, 94,173,+ 94,187, 94,217,225,242,225,226,233, 99,128, 6, 45,230,233,238,+ 225,236,225,242,225,226,233, 99,128,254,162,105, 2, 94,193, 94,+ 208,238,233,244,233,225,236,225,242,225,226,233, 99,128,254,163,+ 242,225,231,225,238, 97,128, 48,111,237,229,228,233,225,236,225,+ 242,225,226,233, 99,128,254,164,233,244,245,243,241,245,225,242,+ 101,128, 51, 42,235,225,244,225,235,225,238, 97,129, 48,207, 95,+ 1,232,225,236,230,247,233,228,244,104,128,255,138,236,225,238,+ 244,231,245,242,237,245,235,232,105,128, 10, 77,237,250, 97, 2,+ 95, 36, 95, 45,225,242,225,226,233, 99,128, 6, 33,236,239,247,+ 225,242,225,226,233, 99,128, 6, 33,238,231,245,236,230,233,236,+ 236,229,114,128, 49,100,114, 2, 95, 76, 95, 92,228,243,233,231,+ 238,227,249,242,233,236,236,233, 99,128, 4, 74,240,239,239,110,+ 2, 95,101, 95,114,236,229,230,244,226,225,242,226,245,112,128,+ 33,188,242,233,231,232,244,226,225,242,226,245,112,128, 33,192,+ 243,241,245,225,242,101,128, 51,202,244,225,102, 3, 95,147, 95,+ 239, 96, 74,240,225,244,225,104,134, 5,178, 95,167, 95,172, 95,+ 186, 95,195, 95,210, 95,226,177, 54,128, 5,178, 50, 2, 95,178,+ 95,182, 51,128, 5,178,102,128, 5,178,232,229,226,242,229,119,+ 128, 5,178,238,225,242,242,239,247,232,229,226,242,229,119,128,+ 5,178,241,245,225,242,244,229,242,232,229,226,242,229,119,128,+ 5,178,247,233,228,229,232,229,226,242,229,119,128, 5,178,241,+ 225,237,225,244,115,135, 5,179, 96, 6, 96, 11, 96, 16, 96, 21,+ 96, 30, 96, 45, 96, 61,177, 98,128, 5,179,178, 56,128, 5,179,+ 179, 52,128, 5,179,232,229,226,242,229,119,128, 5,179,238,225,+ 242,242,239,247,232,229,226,242,229,119,128, 5,179,241,245,225,+ 242,244,229,242,232,229,226,242,229,119,128, 5,179,247,233,228,+ 229,232,229,226,242,229,119,128, 5,179,243,229,231,239,108,135,+ 5,177, 96, 96, 96,101, 96,106, 96,111, 96,120, 96,135, 96,151,+ 177, 55,128, 5,177,178, 52,128, 5,177,179, 48,128, 5,177,232,+ 229,226,242,229,119,128, 5,177,238,225,242,242,239,247,232,229,+ 226,242,229,119,128, 5,177,241,245,225,242,244,229,242,232,229,+ 226,242,229,119,128, 5,177,247,233,228,229,232,229,226,242,229,+ 119,128, 5,177, 98, 3, 96,172, 96,177, 96,187,225,114,128, 1,+ 39,239,240,239,237,239,230,111,128, 49, 15,242,229,246,229,226,+ 229,236,239,119,128, 30, 43, 99, 2, 96,205, 96,214,229,228,233,+ 236,236, 97,128, 30, 41,233,242, 99, 2, 96,222, 96,227,236,101,+ 128, 36,215,245,237,230,236,229,120,128, 1, 37,100, 2, 96,242,+ 96,252,233,229,242,229,243,233,115,128, 30, 39,239,116, 2, 97,+ 3, 97, 12,225,227,227,229,238,116,128, 30, 35,226,229,236,239,+ 119,128, 30, 37,101,136, 5,212, 97, 40, 97, 73, 97, 93, 98, 66,+ 98, 82, 98,127, 98,136, 98,149,225,242,116,129, 38,101, 97, 48,+ 243,245,233,116, 2, 97, 57, 97, 65,226,236,225,227,107,128, 38,+ 101,247,232,233,244,101,128, 38, 97,228,225,231,229,243,104,129,+ 251, 52, 97, 84,232,229,226,242,229,119,128,251, 52,104, 6, 97,+ 107, 97,135, 97,143, 97,193, 97,239, 98, 32, 97, 2, 97,113, 97,+ 127,236,244,239,238,229,225,242,225,226,233, 99,128, 6,193,242,+ 225,226,233, 99,128, 6, 71,229,226,242,229,119,128, 5,212,230,+ 233,238,225,236, 97, 2, 97,154, 97,185,236,116, 2, 97,161, 97,+ 173,239,238,229,225,242,225,226,233, 99,128,251,167,244,247,239,+ 225,242,225,226,233, 99,128,254,234,242,225,226,233, 99,128,254,+ 234,232,225,237,250,225,225,226,239,246,101, 2, 97,208, 97,222,+ 230,233,238,225,236,225,242,225,226,233, 99,128,251,165,233,243,+ 239,236,225,244,229,228,225,242,225,226,233, 99,128,251,164,105,+ 2, 97,245, 98, 23,238,233,244,233,225,236, 97, 2, 98, 1, 98,+ 15,236,244,239,238,229,225,242,225,226,233, 99,128,251,168,242,+ 225,226,233, 99,128,254,235,242,225,231,225,238, 97,128, 48,120,+ 237,229,228,233,225,236, 97, 2, 98, 44, 98, 58,236,244,239,238,+ 229,225,242,225,226,233, 99,128,251,169,242,225,226,233, 99,128,+ 254,236,233,243,229,233,229,242,225,243,241,245,225,242,101,128,+ 51,123,107, 2, 98, 88, 98,112,225,244,225,235,225,238, 97,129,+ 48,216, 98,100,232,225,236,230,247,233,228,244,104,128,255,141,+ 245,244,225,225,242,245,243,241,245,225,242,101,128, 51, 54,238,+ 231,232,239,239,107,128, 2,103,242,245,244,245,243,241,245,225,+ 242,101,128, 51, 57,116,129, 5,215, 98,155,232,229,226,242,229,+ 119,128, 5,215,232,239,239,107,129, 2,102, 98,173,243,245,240,+ 229,242,233,239,114,128, 2,177,105, 4, 98,194, 99, 23, 99, 34,+ 99, 59,229,245,104, 4, 98,206, 98,241, 99, 0, 99, 9, 97, 2,+ 98,212, 98,227,227,233,242,227,236,229,235,239,242,229,225,110,+ 128, 50,123,240,225,242,229,238,235,239,242,229,225,110,128, 50,+ 27,227,233,242,227,236,229,235,239,242,229,225,110,128, 50,109,+ 235,239,242,229,225,110,128, 49, 78,240,225,242,229,238,235,239,+ 242,229,225,110,128, 50, 13,232,233,242,225,231,225,238, 97,128,+ 48,114,235,225,244,225,235,225,238, 97,129, 48,210, 99, 47,232,+ 225,236,230,247,233,228,244,104,128,255,139,242,233,113,134, 5,+ 180, 99, 77, 99, 82, 99, 96, 99,105, 99,120, 99,136,177, 52,128,+ 5,180, 50, 2, 99, 88, 99, 92, 49,128, 5,180,100,128, 5,180,+ 232,229,226,242,229,119,128, 5,180,238,225,242,242,239,247,232,+ 229,226,242,229,119,128, 5,180,241,245,225,242,244,229,242,232,+ 229,226,242,229,119,128, 5,180,247,233,228,229,232,229,226,242,+ 229,119,128, 5,180,236,233,238,229,226,229,236,239,119,128, 30,+ 150,237,239,238,239,243,240,225,227,101,128,255, 72,111, 9, 99,+ 193, 99,204, 99,228, 99,253,100, 85,100, 98,100,184,100,224,100,+ 235,225,242,237,229,238,233,225,110,128, 5,112,232,105, 2, 99,+ 211, 99,219,240,244,232,225,105,128, 14, 43,242,225,231,225,238,+ 97,128, 48,123,235,225,244,225,235,225,238, 97,129, 48,219, 99,+ 241,232,225,236,230,247,233,228,244,104,128,255,142,236,225,109,+ 135, 5,185,100, 17,100, 22,100, 27,100, 32,100, 41,100, 56,100,+ 72,177, 57,128, 5,185,178, 54,128, 5,185,179, 50,128, 5,185,+ 232,229,226,242,229,119,128, 5,185,238,225,242,242,239,247,232,+ 229,226,242,229,119,128, 5,185,241,245,225,242,244,229,242,232,+ 229,226,242,229,119,128, 5,185,247,233,228,229,232,229,226,242,+ 229,119,128, 5,185,238,239,235,232,245,235,244,232,225,105,128,+ 14, 46,111, 2,100,104,100,174,107, 4,100,114,100,126,100,132,+ 100,154,225,226,239,246,229,227,239,237, 98,128, 3, 9,227,237,+ 98,128, 3, 9,240,225,236,225,244,225,236,233,250,229,228,226,+ 229,236,239,247,227,237, 98,128, 3, 33,242,229,244,242,239,230,+ 236,229,248,226,229,236,239,247,227,237, 98,128, 3, 34,238,243,+ 241,245,225,242,101,128, 51, 66,114, 2,100,190,100,217,105, 2,+ 100,196,100,205,227,239,240,244,233, 99,128, 3,233,250,239,238,+ 244,225,236,226,225,114,128, 32, 21,238,227,237, 98,128, 3, 27,+ 244,243,240,242,233,238,231,115,128, 38,104,245,243,101,128, 35,+ 2,240,225,242,229,110,128, 36,163,243,245,240,229,242,233,239,+ 114,128, 2,176,244,245,242,238,229,100,128, 2,101,117, 4,101,+ 23,101, 34,101, 47,101, 72,232,233,242,225,231,225,238, 97,128,+ 48,117,233,233,244,239,243,241,245,225,242,101,128, 51, 51,235,+ 225,244,225,235,225,238, 97,129, 48,213,101, 60,232,225,236,230,+ 247,233,228,244,104,128,255,140,238,231,225,242,245,237,236,225,+ 245,116,129, 2,221,101, 87,227,237, 98,128, 3, 11,118,128, 1,+ 149,249,240,232,229,110,132, 0, 45,101,113,101,124,101,136,101,+ 159,233,238,230,229,242,233,239,114,128,246,229,237,239,238,239,+ 243,240,225,227,101,128,255, 13,115, 2,101,142,101,149,237,225,+ 236,108,128,254, 99,245,240,229,242,233,239,114,128,246,230,244,+ 247,111,128, 32, 16,105,149, 0,105,101,211,101,234,102, 12,102,+ 59,105,197,106, 61,106, 98,106,125,107, 31,107, 35,107, 73,107,+ 95,107,179,108, 88,108,163,108,171,108,184,109, 15,109, 72,109,+ 100,109,144,225, 99, 2,101,218,101,224,245,244,101,128, 0,237,+ 249,242,233,236,236,233, 99,128, 4, 79, 98, 3,101,242,101,251,+ 102, 5,229,238,231,225,236,105,128, 9,135,239,240,239,237,239,+ 230,111,128, 49, 39,242,229,246,101,128, 1, 45, 99, 3,102, 20,+ 102, 27,102, 49,225,242,239,110,128, 1,208,233,242, 99, 2,102,+ 35,102, 40,236,101,128, 36,216,245,237,230,236,229,120,128, 0,+ 238,249,242,233,236,236,233, 99,128, 4, 86,100, 4,102, 69,102,+ 79,105,154,105,187,226,236,231,242,225,246,101,128, 2, 9,101,+ 2,102, 85,105,149,239,231,242,225,240,104, 7,102,106,102,120,+ 102,133,105, 62,105, 93,105,106,105,118,229,225,242,244,232,227,+ 233,242,227,236,101,128, 50,143,230,233,242,229,227,233,242,227,+ 236,101,128, 50,139,233, 99, 14,102,164,102,180,103, 23,103, 77,+ 103,143,103,172,103,188,103,245,104, 38,104, 50,104, 77,104,144,+ 105, 26,105, 55,225,236,236,233,225,238,227,229,240,225,242,229,+ 110,128, 50, 63, 99, 4,102,190,102,201,102,215,102,222,225,236,+ 236,240,225,242,229,110,128, 50, 58,229,238,244,242,229,227,233,+ 242,227,236,101,128, 50,165,236,239,243,101,128, 48, 6,111, 3,+ 102,230,102,245,103, 9,237,237, 97,129, 48, 1,102,238,236,229,+ 230,116,128,255,100,238,231,242,225,244,245,236,225,244,233,239,+ 238,240,225,242,229,110,128, 50, 55,242,242,229,227,244,227,233,+ 242,227,236,101,128, 50,163,101, 3,103, 31,103, 43,103, 60,225,+ 242,244,232,240,225,242,229,110,128, 50, 47,238,244,229,242,240,+ 242,233,243,229,240,225,242,229,110,128, 50, 61,248,227,229,236,+ 236,229,238,244,227,233,242,227,236,101,128, 50,157,102, 2,103,+ 83,103, 98,229,243,244,233,246,225,236,240,225,242,229,110,128,+ 50, 64,105, 2,103,104,103,133,238,225,238,227,233,225,108, 2,+ 103,116,103,125,227,233,242,227,236,101,128, 50,150,240,225,242,+ 229,110,128, 50, 54,242,229,240,225,242,229,110,128, 50, 43,104,+ 2,103,149,103,160,225,246,229,240,225,242,229,110,128, 50, 50,+ 233,231,232,227,233,242,227,236,101,128, 50,164,233,244,229,242,+ 225,244,233,239,238,237,225,242,107,128, 48, 5,108, 3,103,196,+ 103,222,103,234,225,226,239,114, 2,103,205,103,214,227,233,242,+ 227,236,101,128, 50,152,240,225,242,229,110,128, 50, 56,229,230,+ 244,227,233,242,227,236,101,128, 50,167,239,247,227,233,242,227,+ 236,101,128, 50,166,109, 2,103,251,104, 27,101, 2,104, 1,104,+ 16,228,233,227,233,238,229,227,233,242,227,236,101,128, 50,169,+ 244,225,236,240,225,242,229,110,128, 50, 46,239,239,238,240,225,+ 242,229,110,128, 50, 42,238,225,237,229,240,225,242,229,110,128,+ 50, 52,112, 2,104, 56,104, 64,229,242,233,239,100,128, 48, 2,+ 242,233,238,244,227,233,242,227,236,101,128, 50,158,114, 2,104,+ 83,104,131,101, 3,104, 91,104,102,104,117,225,227,232,240,225,+ 242,229,110,128, 50, 67,240,242,229,243,229,238,244,240,225,242,+ 229,110,128, 50, 57,243,239,245,242,227,229,240,225,242,229,110,+ 128, 50, 62,233,231,232,244,227,233,242,227,236,101,128, 50,168,+ 115, 5,104,156,104,185,104,199,104,224,104,252,101, 2,104,162,+ 104,175,227,242,229,244,227,233,242,227,236,101,128, 50,153,236,+ 230,240,225,242,229,110,128, 50, 66,239,227,233,229,244,249,240,+ 225,242,229,110,128, 50, 51,112, 2,104,205,104,211,225,227,101,+ 128, 48, 0,229,227,233,225,236,240,225,242,229,110,128, 50, 53,+ 116, 2,104,230,104,241,239,227,235,240,225,242,229,110,128, 50,+ 49,245,228,249,240,225,242,229,110,128, 50, 59,117, 2,105, 2,+ 105, 11,238,240,225,242,229,110,128, 50, 48,240,229,242,246,233,+ 243,229,240,225,242,229,110,128, 50, 60,119, 2,105, 32,105, 44,+ 225,244,229,242,240,225,242,229,110,128, 50, 44,239,239,228,240,+ 225,242,229,110,128, 50, 45,250,229,242,111,128, 48, 7,109, 2,+ 105, 68,105, 81,229,244,225,236,227,233,242,227,236,101,128, 50,+ 142,239,239,238,227,233,242,227,236,101,128, 50,138,238,225,237,+ 229,227,233,242,227,236,101,128, 50,148,243,245,238,227,233,242,+ 227,236,101,128, 50,144,119, 2,105,124,105,137,225,244,229,242,+ 227,233,242,227,236,101,128, 50,140,239,239,228,227,233,242,227,+ 236,101,128, 50,141,246, 97,128, 9, 7,233,229,242,229,243,233,+ 115,130, 0,239,105,168,105,176,225,227,245,244,101,128, 30, 47,+ 227,249,242,233,236,236,233, 99,128, 4,229,239,244,226,229,236,+ 239,119,128, 30,203,101, 3,105,205,105,221,105,232,226,242,229,+ 246,229,227,249,242,233,236,236,233, 99,128, 4,215,227,249,242,+ 233,236,236,233, 99,128, 4, 53,245,238,103, 4,105,244,106, 23,+ 106, 38,106, 47, 97, 2,105,250,106, 9,227,233,242,227,236,229,+ 235,239,242,229,225,110,128, 50,117,240,225,242,229,238,235,239,+ 242,229,225,110,128, 50, 21,227,233,242,227,236,229,235,239,242,+ 229,225,110,128, 50,103,235,239,242,229,225,110,128, 49, 71,240,+ 225,242,229,238,235,239,242,229,225,110,128, 50, 7,103, 2,106,+ 67,106, 74,242,225,246,101,128, 0,236,117, 2,106, 80,106, 89,+ 234,225,242,225,244,105,128, 10,135,242,237,245,235,232,105,128,+ 10, 7,104, 2,106,104,106,114,233,242,225,231,225,238, 97,128,+ 48, 68,239,239,235,225,226,239,246,101,128, 30,201,105, 8,106,+ 143,106,153,106,164,106,171,106,196,106,212,106,227,106,243,226,+ 229,238,231,225,236,105,128, 9,136,227,249,242,233,236,236,233,+ 99,128, 4, 56,228,229,246, 97,128, 9, 8,231,117, 2,106,178,+ 106,187,234,225,242,225,244,105,128, 10,136,242,237,245,235,232,+ 105,128, 10, 8,237,225,244,242,225,231,245,242,237,245,235,232,+ 105,128, 10, 64,238,246,229,242,244,229,228,226,242,229,246,101,+ 128, 2, 11,243,232,239,242,244,227,249,242,233,236,236,233, 99,+ 128, 4, 57,246,239,247,229,236,243,233,231,110, 3,107, 3,107,+ 13,107, 20,226,229,238,231,225,236,105,128, 9,192,228,229,246,+ 97,128, 9, 64,231,245,234,225,242,225,244,105,128, 10,192,106,+ 128, 1, 51,107, 2,107, 41,107, 65,225,244,225,235,225,238, 97,+ 129, 48,164,107, 53,232,225,236,230,247,233,228,244,104,128,255,+ 114,239,242,229,225,110,128, 49, 99,108, 2,107, 79,107, 84,228,+ 101,128, 2,220,245,249,232,229,226,242,229,119,128, 5,172,109,+ 2,107,101,107,168, 97, 3,107,109,107,129,107,154,227,242,239,+ 110,129, 1, 43,107,118,227,249,242,233,236,236,233, 99,128, 4,+ 227,231,229,239,242,225,240,240,242,239,248,233,237,225,244,229,+ 236,249,229,241,245,225,108,128, 34, 83,244,242,225,231,245,242,+ 237,245,235,232,105,128, 10, 63,239,238,239,243,240,225,227,101,+ 128,255, 73,110, 5,107,191,107,201,107,210,107,222,108, 50,227,+ 242,229,237,229,238,116,128, 34, 6,230,233,238,233,244,121,128,+ 34, 30,233,225,242,237,229,238,233,225,110,128, 5,107,116, 2,+ 107,228,108, 40,101, 2,107,234,108, 29,231,242,225,108,131, 34,+ 43,107,247,108, 9,108, 14, 98, 2,107,253,108, 5,239,244,244,+ 239,109,128, 35, 33,116,128, 35, 33,229,120,128,248,245,116, 2,+ 108, 20,108, 25,239,112,128, 35, 32,112,128, 35, 32,242,243,229,+ 227,244,233,239,110,128, 34, 41,233,243,241,245,225,242,101,128,+ 51, 5,118, 3,108, 58,108, 67,108, 76,226,245,236,236,229,116,+ 128, 37,216,227,233,242,227,236,101,128, 37,217,243,237,233,236,+ 229,230,225,227,101,128, 38, 59,111, 3,108, 96,108,107,108,115,+ 227,249,242,233,236,236,233, 99,128, 4, 81,231,239,238,229,107,+ 128, 1, 47,244, 97,131, 3,185,108,126,108,147,108,155,228,233,+ 229,242,229,243,233,115,129, 3,202,108,139,244,239,238,239,115,+ 128, 3,144,236,225,244,233,110,128, 2,105,244,239,238,239,115,+ 128, 3,175,240,225,242,229,110,128, 36,164,242,233,231,245,242,+ 237,245,235,232,105,128, 10,114,115, 4,108,194,108,239,108,253,+ 109, 5,237,225,236,108, 2,108,203,108,214,232,233,242,225,231,+ 225,238, 97,128, 48, 67,235,225,244,225,235,225,238, 97,129, 48,+ 163,108,227,232,225,236,230,247,233,228,244,104,128,255,104,243,+ 232,225,242,226,229,238,231,225,236,105,128, 9,250,244,242,239,+ 235,101,128, 2,104,245,240,229,242,233,239,114,128,246,237,116,+ 2,109, 21,109, 55,229,242,225,244,233,239,110, 2,109, 33,109,+ 44,232,233,242,225,231,225,238, 97,128, 48,157,235,225,244,225,+ 235,225,238, 97,128, 48,253,233,236,228,101,129, 1, 41,109, 64,+ 226,229,236,239,119,128, 30, 45,117, 2,109, 78,109, 89,226,239,+ 240,239,237,239,230,111,128, 49, 41,227,249,242,233,236,236,233,+ 99,128, 4, 78,246,239,247,229,236,243,233,231,110, 3,109,116,+ 109,126,109,133,226,229,238,231,225,236,105,128, 9,191,228,229,+ 246, 97,128, 9, 63,231,245,234,225,242,225,244,105,128, 10,191,+ 250,232,233,244,243, 97, 2,109,155,109,166,227,249,242,233,236,+ 236,233, 99,128, 4,117,228,226,236,231,242,225,246,229,227,249,+ 242,233,236,236,233, 99,128, 4,119,106,138, 0,106,109,209,110,+ 16,110, 27,110, 77,110, 93,110,206,111, 19,111, 24,111, 36,111,+ 44, 97, 4,109,219,109,230,109,240,109,247,225,242,237,229,238,+ 233,225,110,128, 5,113,226,229,238,231,225,236,105,128, 9,156,+ 228,229,246, 97,128, 9, 28,231,117, 2,109,254,110, 7,234,225,+ 242,225,244,105,128, 10,156,242,237,245,235,232,105,128, 10, 28,+ 226,239,240,239,237,239,230,111,128, 49, 16, 99, 3,110, 35,110,+ 42,110, 64,225,242,239,110,128, 1,240,233,242, 99, 2,110, 50,+ 110, 55,236,101,128, 36,217,245,237,230,236,229,120,128, 1, 53,+ 242,239,243,243,229,228,244,225,233,108,128, 2,157,228,239,244,+ 236,229,243,243,243,244,242,239,235,101,128, 2, 95,101, 3,110,+ 101,110,112,110,177,227,249,242,233,236,236,233, 99,128, 4, 88,+ 229,109, 4,110,123,110,132,110,146,110,162,225,242,225,226,233,+ 99,128, 6, 44,230,233,238,225,236,225,242,225,226,233, 99,128,+ 254,158,233,238,233,244,233,225,236,225,242,225,226,233, 99,128,+ 254,159,237,229,228,233,225,236,225,242,225,226,233, 99,128,254,+ 160,104, 2,110,183,110,192,225,242,225,226,233, 99,128, 6,152,+ 230,233,238,225,236,225,242,225,226,233, 99,128,251,139,104, 2,+ 110,212,111, 6, 97, 3,110,220,110,230,110,237,226,229,238,231,+ 225,236,105,128, 9,157,228,229,246, 97,128, 9, 29,231,117, 2,+ 110,244,110,253,234,225,242,225,244,105,128, 10,157,242,237,245,+ 235,232,105,128, 10, 29,229,232,225,242,237,229,238,233,225,110,+ 128, 5,123,233,115,128, 48, 4,237,239,238,239,243,240,225,227,+ 101,128,255, 74,240,225,242,229,110,128, 36,165,243,245,240,229,+ 242,233,239,114,128, 2,178,107,146, 0,107,111, 95,113,184,113,+ 195,114, 1,114, 12,114,102,114,116,115,224,116,164,116,177,116,+ 203,116,252,117,134,117,156,117,169,117,192,117,234,117,244, 97,+ 12,111,121,111,153,111,175,111,205,112, 63,112, 88,112,118,112,+ 143,112,249,113, 7,113,130,113,159, 98, 2,111,127,111,144,225,+ 243,232,235,233,242,227,249,242,233,236,236,233, 99,128, 4,161,+ 229,238,231,225,236,105,128, 9,149, 99, 2,111,159,111,165,245,+ 244,101,128, 30, 49,249,242,233,236,236,233, 99,128, 4, 58,228,+ 101, 2,111,182,111,200,243,227,229,238,228,229,242,227,249,242,+ 233,236,236,233, 99,128, 4,155,246, 97,128, 9, 21,102,135, 5,+ 219,111,223,111,232,111,252,112, 10,112, 19,112, 35,112, 50,225,+ 242,225,226,233, 99,128, 6, 67,228,225,231,229,243,104,129,251,+ 59,111,243,232,229,226,242,229,119,128,251, 59,230,233,238,225,+ 236,225,242,225,226,233, 99,128,254,218,232,229,226,242,229,119,+ 128, 5,219,233,238,233,244,233,225,236,225,242,225,226,233, 99,+ 128,254,219,237,229,228,233,225,236,225,242,225,226,233, 99,128,+ 254,220,242,225,230,229,232,229,226,242,229,119,128,251, 77,231,+ 117, 2,112, 70,112, 79,234,225,242,225,244,105,128, 10,149,242,+ 237,245,235,232,105,128, 10, 21,104, 2,112, 94,112,104,233,242,+ 225,231,225,238, 97,128, 48, 75,239,239,235,227,249,242,233,236,+ 236,233, 99,128, 4,196,235,225,244,225,235,225,238, 97,129, 48,+ 171,112,131,232,225,236,230,247,233,228,244,104,128,255,118,112,+ 2,112,149,112,170,240, 97,129, 3,186,112,156,243,249,237,226,+ 239,236,231,242,229,229,107,128, 3,240,249,229,239,245,110, 3,+ 112,182,112,196,112,230,237,233,229,245,237,235,239,242,229,225,+ 110,128, 49,113,112, 2,112,202,112,217,232,233,229,245,240,232,+ 235,239,242,229,225,110,128, 49,132,233,229,245,240,235,239,242,+ 229,225,110,128, 49,120,243,243,225,238,231,240,233,229,245,240,+ 235,239,242,229,225,110,128, 49,121,242,239,242,233,233,243,241,+ 245,225,242,101,128, 51, 13,115, 5,113, 19,113, 63,113, 78,113,+ 86,113,114,232,233,228,225,225,245,244,111, 2,113, 32,113, 41,+ 225,242,225,226,233, 99,128, 6, 64,238,239,243,233,228,229,226,+ 229,225,242,233,238,231,225,242,225,226,233, 99,128, 6, 64,237,+ 225,236,236,235,225,244,225,235,225,238, 97,128, 48,245,241,245,+ 225,242,101,128, 51,132,242, 97, 2,113, 93,113,102,225,242,225,+ 226,233, 99,128, 6, 80,244,225,238,225,242,225,226,233, 99,128,+ 6, 77,244,242,239,235,229,227,249,242,233,236,236,233, 99,128,+ 4,159,244,225,232,233,242,225,240,242,239,236,239,238,231,237,+ 225,242,235,232,225,236,230,247,233,228,244,104,128,255,112,246,+ 229,242,244,233,227,225,236,243,244,242,239,235,229,227,249,242,+ 233,236,236,233, 99,128, 4,157,226,239,240,239,237,239,230,111,+ 128, 49, 14, 99, 4,113,205,113,227,113,236,113,244, 97, 2,113,+ 211,113,221,236,243,241,245,225,242,101,128, 51,137,242,239,110,+ 128, 1,233,229,228,233,236,236, 97,128, 1, 55,233,242,227,236,+ 101,128, 36,218,239,237,237,225,225,227,227,229,238,116,128, 1,+ 55,228,239,244,226,229,236,239,119,128, 30, 51,101, 4,114, 22,+ 114, 49,114, 74,114, 86,104, 2,114, 28,114, 39,225,242,237,229,+ 238,233,225,110,128, 5,132,233,242,225,231,225,238, 97,128, 48,+ 81,235,225,244,225,235,225,238, 97,129, 48,177,114, 62,232,225,+ 236,230,247,233,228,244,104,128,255,121,238,225,242,237,229,238,+ 233,225,110,128, 5,111,243,237,225,236,236,235,225,244,225,235,+ 225,238, 97,128, 48,246,231,242,229,229,238,236,225,238,228,233,+ 99,128, 1, 56,104, 6,114,130,115, 3,115, 14,115, 39,115,126,+ 115,214, 97, 5,114,142,114,152,114,163,114,170,114,195,226,229,+ 238,231,225,236,105,128, 9,150,227,249,242,233,236,236,233, 99,+ 128, 4, 69,228,229,246, 97,128, 9, 22,231,117, 2,114,177,114,+ 186,234,225,242,225,244,105,128, 10,150,242,237,245,235,232,105,+ 128, 10, 22,104, 4,114,205,114,214,114,228,114,244,225,242,225,+ 226,233, 99,128, 6, 46,230,233,238,225,236,225,242,225,226,233,+ 99,128,254,166,233,238,233,244,233,225,236,225,242,225,226,233,+ 99,128,254,167,237,229,228,233,225,236,225,242,225,226,233, 99,+ 128,254,168,229,233,227,239,240,244,233, 99,128, 3,231,232, 97,+ 2,115, 21,115, 28,228,229,246, 97,128, 9, 89,231,245,242,237,+ 245,235,232,105,128, 10, 89,233,229,245,235,104, 4,115, 53,115,+ 88,115,103,115,112, 97, 2,115, 59,115, 74,227,233,242,227,236,+ 229,235,239,242,229,225,110,128, 50,120,240,225,242,229,238,235,+ 239,242,229,225,110,128, 50, 24,227,233,242,227,236,229,235,239,+ 242,229,225,110,128, 50,106,235,239,242,229,225,110,128, 49, 75,+ 240,225,242,229,238,235,239,242,229,225,110,128, 50, 10,111, 4,+ 115,136,115,185,115,195,115,200,235,104, 4,115,147,115,156,115,+ 165,115,175,225,233,244,232,225,105,128, 14, 2,239,238,244,232,+ 225,105,128, 14, 5,245,225,244,244,232,225,105,128, 14, 3,247,+ 225,233,244,232,225,105,128, 14, 4,237,245,244,244,232,225,105,+ 128, 14, 91,239,107,128, 1,153,242,225,235,232,225,238,231,244,+ 232,225,105,128, 14, 6,250,243,241,245,225,242,101,128, 51,145,+ 105, 4,115,234,115,245,116, 14,116, 63,232,233,242,225,231,225,+ 238, 97,128, 48, 77,235,225,244,225,235,225,238, 97,129, 48,173,+ 116, 2,232,225,236,230,247,233,228,244,104,128,255,119,242,111,+ 3,116, 23,116, 38,116, 54,231,245,242,225,237,245,243,241,245,+ 225,242,101,128, 51, 21,237,229,229,244,239,242,245,243,241,245,+ 225,242,101,128, 51, 22,243,241,245,225,242,101,128, 51, 20,249,+ 229,239,107, 5,116, 78,116,113,116,128,116,137,116,151, 97, 2,+ 116, 84,116, 99,227,233,242,227,236,229,235,239,242,229,225,110,+ 128, 50,110,240,225,242,229,238,235,239,242,229,225,110,128, 50,+ 14,227,233,242,227,236,229,235,239,242,229,225,110,128, 50, 96,+ 235,239,242,229,225,110,128, 49, 49,240,225,242,229,238,235,239,+ 242,229,225,110,128, 50, 0,243,233,239,243,235,239,242,229,225,+ 110,128, 49, 51,234,229,227,249,242,233,236,236,233, 99,128, 4,+ 92,108, 2,116,183,116,194,233,238,229,226,229,236,239,119,128,+ 30, 53,243,241,245,225,242,101,128, 51,152,109, 3,116,211,116,+ 225,116,236,227,245,226,229,228,243,241,245,225,242,101,128, 51,+ 166,239,238,239,243,240,225,227,101,128,255, 75,243,241,245,225,+ 242,229,228,243,241,245,225,242,101,128, 51,162,111, 5,117, 8,+ 117, 34,117, 72,117, 84,117, 98,104, 2,117, 14,117, 24,233,242,+ 225,231,225,238, 97,128, 48, 83,237,243,241,245,225,242,101,128,+ 51,192,235, 97, 2,117, 41,117, 49,233,244,232,225,105,128, 14,+ 1,244,225,235,225,238, 97,129, 48,179,117, 60,232,225,236,230,+ 247,233,228,244,104,128,255,122,239,240,239,243,241,245,225,242,+ 101,128, 51, 30,240,240,225,227,249,242,233,236,236,233, 99,128,+ 4,129,114, 2,117,104,117,124,229,225,238,243,244,225,238,228,+ 225,242,228,243,249,237,226,239,108,128, 50,127,239,238,233,243,+ 227,237, 98,128, 3, 67,240, 97, 2,117,141,117,147,242,229,110,+ 128, 36,166,243,241,245,225,242,101,128, 51,170,243,233,227,249,+ 242,233,236,236,233, 99,128, 4,111,116, 2,117,175,117,184,243,+ 241,245,225,242,101,128, 51,207,245,242,238,229,100,128, 2,158,+ 117, 2,117,198,117,209,232,233,242,225,231,225,238, 97,128, 48,+ 79,235,225,244,225,235,225,238, 97,129, 48,175,117,222,232,225,+ 236,230,247,233,228,244,104,128,255,120,246,243,241,245,225,242,+ 101,128, 51,184,247,243,241,245,225,242,101,128, 51,190,108,146,+ 0,108,118, 38,120, 65,120, 94,120,160,120,198,121, 94,121,103,+ 121,119,121,143,121,161,122, 23,122, 64,122,199,122,207,122,240,+ 122,249,123, 1,123, 63, 97, 7,118, 54,118, 64,118, 71,118, 78,+ 118,103,118,119,120, 53,226,229,238,231,225,236,105,128, 9,178,+ 227,245,244,101,128, 1, 58,228,229,246, 97,128, 9, 50,231,117,+ 2,118, 85,118, 94,234,225,242,225,244,105,128, 10,178,242,237,+ 245,235,232,105,128, 10, 50,235,235,232,225,238,231,249,225,239,+ 244,232,225,105,128, 14, 69,109, 10,118,141,119, 80,119, 97,119,+ 135,119,149,119,168,119,184,119,204,119,224,119,247, 97, 2,118,+ 147,119, 72,236,229,102, 4,118,159,118,173,119, 9,119, 26,230,+ 233,238,225,236,225,242,225,226,233, 99,128,254,252,232,225,237,+ 250, 97, 2,118,183,118,224,225,226,239,246,101, 2,118,193,118,+ 207,230,233,238,225,236,225,242,225,226,233, 99,128,254,248,233,+ 243,239,236,225,244,229,228,225,242,225,226,233, 99,128,254,247,+ 226,229,236,239,119, 2,118,234,118,248,230,233,238,225,236,225,+ 242,225,226,233, 99,128,254,250,233,243,239,236,225,244,229,228,+ 225,242,225,226,233, 99,128,254,249,233,243,239,236,225,244,229,+ 228,225,242,225,226,233, 99,128,254,251,237,225,228,228,225,225,+ 226,239,246,101, 2,119, 41,119, 55,230,233,238,225,236,225,242,+ 225,226,233, 99,128,254,246,233,243,239,236,225,244,229,228,225,+ 242,225,226,233, 99,128,254,245,242,225,226,233, 99,128, 6, 68,+ 226,228, 97,129, 3,187,119, 88,243,244,242,239,235,101,128, 1,+ 155,229,100,130, 5,220,119,106,119,126,228,225,231,229,243,104,+ 129,251, 60,119,117,232,229,226,242,229,119,128,251, 60,232,229,+ 226,242,229,119,128, 5,220,230,233,238,225,236,225,242,225,226,+ 233, 99,128,254,222,232,225,232,233,238,233,244,233,225,236,225,+ 242,225,226,233, 99,128,252,202,233,238,233,244,233,225,236,225,+ 242,225,226,233, 99,128,254,223,234,229,229,237,233,238,233,244,+ 233,225,236,225,242,225,226,233, 99,128,252,201,235,232,225,232,+ 233,238,233,244,233,225,236,225,242,225,226,233, 99,128,252,203,+ 236,225,237,232,229,232,233,243,239,236,225,244,229,228,225,242,+ 225,226,233, 99,128,253,242,237,101, 2,119,254,120, 11,228,233,+ 225,236,225,242,225,226,233, 99,128,254,224,229,109, 2,120, 18,+ 120, 37,232,225,232,233,238,233,244,233,225,236,225,242,225,226,+ 233, 99,128,253,136,233,238,233,244,233,225,236,225,242,225,226,+ 233, 99,128,252,204,242,231,229,227,233,242,227,236,101,128, 37,+ 239, 98, 3,120, 73,120, 78,120, 84,225,114,128, 1,154,229,236,+ 116,128, 2,108,239,240,239,237,239,230,111,128, 49, 12, 99, 4,+ 120,104,120,111,120,120,120,147,225,242,239,110,128, 1, 62,229,+ 228,233,236,236, 97,128, 1, 60,233,242, 99, 2,120,128,120,133,+ 236,101,128, 36,219,245,237,230,236,229,248,226,229,236,239,119,+ 128, 30, 61,239,237,237,225,225,227,227,229,238,116,128, 1, 60,+ 228,239,116,130, 1, 64,120,170,120,179,225,227,227,229,238,116,+ 128, 1, 64,226,229,236,239,119,129, 30, 55,120,189,237,225,227,+ 242,239,110,128, 30, 57,101, 3,120,206,120,244,121, 89,230,116,+ 2,120,213,120,229,225,238,231,236,229,225,226,239,246,229,227,+ 237, 98,128, 3, 26,244,225,227,235,226,229,236,239,247,227,237,+ 98,128, 3, 24,243,115,132, 0, 60,121, 1,121, 23,121, 35,121,+ 81,229,241,245,225,108,129, 34,100,121, 11,239,242,231,242,229,+ 225,244,229,114,128, 34,218,237,239,238,239,243,240,225,227,101,+ 128,255, 28,111, 2,121, 41,121, 70,114, 2,121, 47,121, 60,229,+ 241,245,233,246,225,236,229,238,116,128, 34,114,231,242,229,225,+ 244,229,114,128, 34,118,246,229,242,229,241,245,225,108,128, 34,+ 102,243,237,225,236,108,128,254,100,250,104,128, 2,110,230,226,+ 236,239,227,107,128, 37,140,232,239,239,235,242,229,244,242,239,+ 230,236,229,120,128, 2,109,105, 2,121,125,121,130,242, 97,128,+ 32,164,247,238,225,242,237,229,238,233,225,110,128, 5,108,106,+ 129, 1,201,121,149,229,227,249,242,233,236,236,233, 99,128, 4,+ 89,108,132,246,192,121,173,121,197,121,208,121,217, 97, 2,121,+ 179,121,186,228,229,246, 97,128, 9, 51,231,245,234,225,242,225,+ 244,105,128, 10,179,233,238,229,226,229,236,239,119,128, 30, 59,+ 236,225,228,229,246, 97,128, 9, 52,246,239,227,225,236,233, 99,+ 3,121,231,121,241,121,248,226,229,238,231,225,236,105,128, 9,+ 225,228,229,246, 97,128, 9, 97,246,239,247,229,236,243,233,231,+ 110, 2,122, 6,122, 16,226,229,238,231,225,236,105,128, 9,227,+ 228,229,246, 97,128, 9, 99,109, 3,122, 31,122, 44,122, 55,233,+ 228,228,236,229,244,233,236,228,101,128, 2,107,239,238,239,243,+ 240,225,227,101,128,255, 76,243,241,245,225,242,101,128, 51,208,+ 111, 6,122, 78,122, 90,122,132,122,143,122,149,122,191,227,232,+ 245,236,225,244,232,225,105,128, 14, 44,231,233,227,225,108, 3,+ 122,102,122,108,122,127,225,238,100,128, 34, 39,238,239,116,129,+ 0,172,122,116,242,229,246,229,242,243,229,100,128, 35, 16,239,+ 114,128, 34, 40,236,233,238,231,244,232,225,105,128, 14, 37,238,+ 231,115,128, 1,127,247,236,233,238,101, 2,122,159,122,182, 99,+ 2,122,165,122,177,229,238,244,229,242,236,233,238,101,128,254,+ 78,237, 98,128, 3, 50,228,225,243,232,229,100,128,254, 77,250,+ 229,238,231,101,128, 37,202,240,225,242,229,110,128, 36,167,115,+ 3,122,215,122,222,122,230,236,225,243,104,128, 1, 66,241,245,+ 225,242,101,128, 33, 19,245,240,229,242,233,239,114,128,246,238,+ 244,243,232,225,228,101,128, 37,145,245,244,232,225,105,128, 14,+ 38,246,239,227,225,236,233, 99, 3,123, 15,123, 25,123, 32,226,+ 229,238,231,225,236,105,128, 9,140,228,229,246, 97,128, 9, 12,+ 246,239,247,229,236,243,233,231,110, 2,123, 46,123, 56,226,229,+ 238,231,225,236,105,128, 9,226,228,229,246, 97,128, 9, 98,248,+ 243,241,245,225,242,101,128, 51,211,109,144, 0,109,123,109,125,+ 218,125,243,126, 14,126, 39,127, 92,127,114,128,169,128,199,128,+ 248,129, 99,129,121,129,146,129,155,130,182,130,210, 97, 12,123,+ 135,123,145,123,209,123,216,123,241,124, 33,125,125,125,150,125,+ 155,125,169,125,181,125,186,226,229,238,231,225,236,105,128, 9,+ 174, 99, 2,123,151,123,203,242,239,110,132, 0,175,123,165,123,+ 176,123,182,123,191,226,229,236,239,247,227,237, 98,128, 3, 49,+ 227,237, 98,128, 3, 4,236,239,247,237,239,100,128, 2,205,237,+ 239,238,239,243,240,225,227,101,128,255,227,245,244,101,128, 30,+ 63,228,229,246, 97,128, 9, 46,231,117, 2,123,223,123,232,234,+ 225,242,225,244,105,128, 10,174,242,237,245,235,232,105,128, 10,+ 46,104, 2,123,247,124, 23,225,240,225,235,104, 2,124, 1,124,+ 10,232,229,226,242,229,119,128, 5,164,236,229,230,244,232,229,+ 226,242,229,119,128, 5,164,233,242,225,231,225,238, 97,128, 48,+ 126,105, 5,124, 45,124,114,124,177,124,207,125,113,227,232,225,+ 244,244,225,247, 97, 3,124, 60,124, 91,124, 98,236,239,119, 2,+ 124, 68,124, 79,236,229,230,244,244,232,225,105,128,248,149,242,+ 233,231,232,244,244,232,225,105,128,248,148,244,232,225,105,128,+ 14, 75,245,240,240,229,242,236,229,230,244,244,232,225,105,128,+ 248,147,229,107, 3,124,123,124,154,124,161,236,239,119, 2,124,+ 131,124,142,236,229,230,244,244,232,225,105,128,248,140,242,233,+ 231,232,244,244,232,225,105,128,248,139,244,232,225,105,128, 14,+ 72,245,240,240,229,242,236,229,230,244,244,232,225,105,128,248,+ 138,232,225,238,225,235,225,116, 2,124,189,124,200,236,229,230,+ 244,244,232,225,105,128,248,132,244,232,225,105,128, 14, 49,116,+ 3,124,215,124,243,125, 50,225,233,235,232,117, 2,124,225,124,+ 236,236,229,230,244,244,232,225,105,128,248,137,244,232,225,105,+ 128, 14, 71,232,111, 3,124,252,125, 27,125, 34,236,239,119, 2,+ 125, 4,125, 15,236,229,230,244,244,232,225,105,128,248,143,242,+ 233,231,232,244,244,232,225,105,128,248,142,244,232,225,105,128,+ 14, 73,245,240,240,229,242,236,229,230,244,244,232,225,105,128,+ 248,141,242,105, 3,125, 59,125, 90,125, 97,236,239,119, 2,125,+ 67,125, 78,236,229,230,244,244,232,225,105,128,248,146,242,233,+ 231,232,244,244,232,225,105,128,248,145,244,232,225,105,128, 14,+ 74,245,240,240,229,242,236,229,230,244,244,232,225,105,128,248,+ 144,249,225,237,239,235,244,232,225,105,128, 14, 70,235,225,244,+ 225,235,225,238, 97,129, 48,222,125,138,232,225,236,230,247,233,+ 228,244,104,128,255,143,236,101,128, 38, 66,238,243,249,239,238,+ 243,241,245,225,242,101,128, 51, 71,241,225,230,232,229,226,242,+ 229,119,128, 5,190,242,115,128, 38, 66,115, 2,125,192,125,210,+ 239,242,225,227,233,242,227,236,229,232,229,226,242,229,119,128,+ 5,175,241,245,225,242,101,128, 51,131, 98, 2,125,224,125,234,+ 239,240,239,237,239,230,111,128, 49, 7,243,241,245,225,242,101,+ 128, 51,212, 99, 2,125,249,126, 1,233,242,227,236,101,128, 36,+ 220,245,226,229,228,243,241,245,225,242,101,128, 51,165,228,239,+ 116, 2,126, 22,126, 31,225,227,227,229,238,116,128, 30, 65,226,+ 229,236,239,119,128, 30, 67,101, 7,126, 55,126,182,126,193,126,+ 208,126,233,127, 14,127, 26,101, 2,126, 61,126,169,109, 4,126,+ 71,126, 80,126, 94,126,110,225,242,225,226,233, 99,128, 6, 69,+ 230,233,238,225,236,225,242,225,226,233, 99,128,254,226,233,238,+ 233,244,233,225,236,225,242,225,226,233, 99,128,254,227,237,101,+ 2,126,117,126,130,228,233,225,236,225,242,225,226,233, 99,128,+ 254,228,229,237,105, 2,126,138,126,153,238,233,244,233,225,236,+ 225,242,225,226,233, 99,128,252,209,243,239,236,225,244,229,228,+ 225,242,225,226,233, 99,128,252, 72,244,239,242,245,243,241,245,+ 225,242,101,128, 51, 77,232,233,242,225,231,225,238, 97,128, 48,+ 129,233,250,233,229,242,225,243,241,245,225,242,101,128, 51,126,+ 235,225,244,225,235,225,238, 97,129, 48,225,126,221,232,225,236,+ 230,247,233,228,244,104,128,255,146,109,130, 5,222,126,241,127,+ 5,228,225,231,229,243,104,129,251, 62,126,252,232,229,226,242,+ 229,119,128,251, 62,232,229,226,242,229,119,128, 5,222,238,225,+ 242,237,229,238,233,225,110,128, 5,116,242,235,232, 97, 3,127,+ 37,127, 46,127, 79,232,229,226,242,229,119,128, 5,165,235,229,+ 230,245,236, 97, 2,127, 57,127, 66,232,229,226,242,229,119,128,+ 5,166,236,229,230,244,232,229,226,242,229,119,128, 5,166,236,+ 229,230,244,232,229,226,242,229,119,128, 5,165,104, 2,127, 98,+ 127,104,239,239,107,128, 2,113,250,243,241,245,225,242,101,128,+ 51,146,105, 6,127,128,127,165,128, 46,128, 57,128, 82,128,139,+ 228,100, 2,127,135,127,160,236,229,228,239,244,235,225,244,225,+ 235,225,238,225,232,225,236,230,247,233,228,244,104,128,255,101,+ 239,116,128, 0,183,229,245,109, 5,127,179,127,214,127,229,127,+ 238,128, 33, 97, 2,127,185,127,200,227,233,242,227,236,229,235,+ 239,242,229,225,110,128, 50,114,240,225,242,229,238,235,239,242,+ 229,225,110,128, 50, 18,227,233,242,227,236,229,235,239,242,229,+ 225,110,128, 50,100,235,239,242,229,225,110,128, 49, 65,112, 2,+ 127,244,128, 20, 97, 2,127,250,128, 8,238,243,233,239,243,235,+ 239,242,229,225,110,128, 49,112,242,229,238,235,239,242,229,225,+ 110,128, 50, 4,233,229,245,240,235,239,242,229,225,110,128, 49,+ 110,243,233,239,243,235,239,242,229,225,110,128, 49,111,232,233,+ 242,225,231,225,238, 97,128, 48,127,235,225,244,225,235,225,238,+ 97,129, 48,223,128, 70,232,225,236,230,247,233,228,244,104,128,+ 255,144,238,117, 2,128, 89,128,134,115,132, 34, 18,128,101,128,+ 112,128,121,128,127,226,229,236,239,247,227,237, 98,128, 3, 32,+ 227,233,242,227,236,101,128, 34,150,237,239,100,128, 2,215,240,+ 236,245,115,128, 34, 19,244,101,128, 32, 50,242,105, 2,128,146,+ 128,160,226,225,225,242,245,243,241,245,225,242,101,128, 51, 74,+ 243,241,245,225,242,101,128, 51, 73,108, 2,128,175,128,190,239,+ 238,231,236,229,231,244,245,242,238,229,100,128, 2,112,243,241,+ 245,225,242,101,128, 51,150,109, 3,128,207,128,221,128,232,227,+ 245,226,229,228,243,241,245,225,242,101,128, 51,163,239,238,239,+ 243,240,225,227,101,128,255, 77,243,241,245,225,242,229,228,243,+ 241,245,225,242,101,128, 51,159,111, 5,129, 4,129, 30,129, 55,+ 129, 65,129, 74,104, 2,129, 10,129, 20,233,242,225,231,225,238,+ 97,128, 48,130,237,243,241,245,225,242,101,128, 51,193,235,225,+ 244,225,235,225,238, 97,129, 48,226,129, 43,232,225,236,230,247,+ 233,228,244,104,128,255,147,236,243,241,245,225,242,101,128, 51,+ 214,237,225,244,232,225,105,128, 14, 33,246,229,242,243,243,241,+ 245,225,242,101,129, 51,167,129, 89,228,243,241,245,225,242,101,+ 128, 51,168,240, 97, 2,129,106,129,112,242,229,110,128, 36,168,+ 243,241,245,225,242,101,128, 51,171,115, 2,129,127,129,136,243,+ 241,245,225,242,101,128, 51,179,245,240,229,242,233,239,114,128,+ 246,239,244,245,242,238,229,100,128, 2,111,117,141, 0,181,129,+ 185,129,189,129,199,129,223,129,233,129,255,130, 10,130, 35,130,+ 58,130, 68,130, 98,130,162,130,172, 49,128, 0,181,225,243,241,+ 245,225,242,101,128, 51,130,227,104, 2,129,206,129,216,231,242,+ 229,225,244,229,114,128, 34,107,236,229,243,115,128, 34,106,230,+ 243,241,245,225,242,101,128, 51,140,103, 2,129,239,129,246,242,+ 229,229,107,128, 3,188,243,241,245,225,242,101,128, 51,141,232,+ 233,242,225,231,225,238, 97,128, 48,128,235,225,244,225,235,225,+ 238, 97,129, 48,224,130, 23,232,225,236,230,247,233,228,244,104,+ 128,255,145,108, 2,130, 41,130, 50,243,241,245,225,242,101,128,+ 51,149,244,233,240,236,121,128, 0,215,237,243,241,245,225,242,+ 101,128, 51,155,238,225,104, 2,130, 76,130, 85,232,229,226,242,+ 229,119,128, 5,163,236,229,230,244,232,229,226,242,229,119,128,+ 5,163,115, 2,130,104,130,153,233, 99, 3,130,113,130,130,130,+ 141,225,236,238,239,244,101,129, 38,106,130,124,228,226,108,128,+ 38,107,230,236,225,244,243,233,231,110,128, 38,109,243,232,225,+ 242,240,243,233,231,110,128, 38,111,243,241,245,225,242,101,128,+ 51,178,246,243,241,245,225,242,101,128, 51,182,247,243,241,245,+ 225,242,101,128, 51,188,118, 2,130,188,130,201,237,229,231,225,+ 243,241,245,225,242,101,128, 51,185,243,241,245,225,242,101,128,+ 51,183,119, 2,130,216,130,229,237,229,231,225,243,241,245,225,+ 242,101,128, 51,191,243,241,245,225,242,101,128, 51,189,110,150,+ 0,110,131, 30,131,164,131,188,131,254,132, 23,132, 81,132, 91,+ 132,158,132,201,134,235,134,253,135, 22,135, 53,135, 79,135,144,+ 137,126,137,134,137,159,137,167,138,135,138,145,138,155, 97, 8,+ 131, 48,131, 68,131, 75,131, 82,131,107,131,118,131,143,131,155,+ 98, 2,131, 54,131, 63,229,238,231,225,236,105,128, 9,168,236,+ 97,128, 34, 7,227,245,244,101,128, 1, 68,228,229,246, 97,128,+ 9, 40,231,117, 2,131, 89,131, 98,234,225,242,225,244,105,128,+ 10,168,242,237,245,235,232,105,128, 10, 40,232,233,242,225,231,+ 225,238, 97,128, 48,106,235,225,244,225,235,225,238, 97,129, 48,+ 202,131,131,232,225,236,230,247,233,228,244,104,128,255,133,240,+ 239,243,244,242,239,240,232,101,128, 1, 73,243,241,245,225,242,+ 101,128, 51,129, 98, 2,131,170,131,180,239,240,239,237,239,230,+ 111,128, 49, 11,243,240,225,227,101,128, 0,160, 99, 4,131,198,+ 131,205,131,214,131,241,225,242,239,110,128, 1, 72,229,228,233,+ 236,236, 97,128, 1, 70,233,242, 99, 2,131,222,131,227,236,101,+ 128, 36,221,245,237,230,236,229,248,226,229,236,239,119,128, 30,+ 75,239,237,237,225,225,227,227,229,238,116,128, 1, 70,228,239,+ 116, 2,132, 6,132, 15,225,227,227,229,238,116,128, 30, 69,226,+ 229,236,239,119,128, 30, 71,101, 3,132, 31,132, 42,132, 67,232,+ 233,242,225,231,225,238, 97,128, 48,109,235,225,244,225,235,225,+ 238, 97,129, 48,205,132, 55,232,225,236,230,247,233,228,244,104,+ 128,255,136,247,243,232,229,241,229,236,243,233,231,110,128, 32,+ 170,230,243,241,245,225,242,101,128, 51,139,103, 2,132, 97,132,+ 147, 97, 3,132,105,132,115,132,122,226,229,238,231,225,236,105,+ 128, 9,153,228,229,246, 97,128, 9, 25,231,117, 2,132,129,132,+ 138,234,225,242,225,244,105,128, 10,153,242,237,245,235,232,105,+ 128, 10, 25,239,238,231,245,244,232,225,105,128, 14, 7,104, 2,+ 132,164,132,174,233,242,225,231,225,238, 97,128, 48,147,239,239,+ 107, 2,132,182,132,189,236,229,230,116,128, 2,114,242,229,244,+ 242,239,230,236,229,120,128, 2,115,105, 4,132,211,133,124,133,+ 135,133,193,229,245,110, 7,132,229,133, 8,133, 40,133, 54,133,+ 63,133, 96,133,109, 97, 2,132,235,132,250,227,233,242,227,236,+ 229,235,239,242,229,225,110,128, 50,111,240,225,242,229,238,235,+ 239,242,229,225,110,128, 50, 15,227,105, 2,133, 15,133, 27,229,+ 245,227,235,239,242,229,225,110,128, 49, 53,242,227,236,229,235,+ 239,242,229,225,110,128, 50, 97,232,233,229,245,232,235,239,242,+ 229,225,110,128, 49, 54,235,239,242,229,225,110,128, 49, 52,240,+ 97, 2,133, 70,133, 84,238,243,233,239,243,235,239,242,229,225,+ 110,128, 49,104,242,229,238,235,239,242,229,225,110,128, 50, 1,+ 243,233,239,243,235,239,242,229,225,110,128, 49,103,244,233,235,+ 229,245,244,235,239,242,229,225,110,128, 49,102,232,233,242,225,+ 231,225,238, 97,128, 48,107,107, 2,133,141,133,165,225,244,225,+ 235,225,238, 97,129, 48,203,133,153,232,225,236,230,247,233,228,+ 244,104,128,255,134,232,225,232,233,116, 2,133,175,133,186,236,+ 229,230,244,244,232,225,105,128,248,153,244,232,225,105,128, 14,+ 77,238,101,141, 0, 57,133,224,133,233,133,243,134, 17,134, 24,+ 134, 49,134, 76,134,110,134,122,134,133,134,166,134,174,134,185,+ 225,242,225,226,233, 99,128, 6,105,226,229,238,231,225,236,105,+ 128, 9,239,227,233,242,227,236,101,129, 36,104,133,254,233,238,+ 246,229,242,243,229,243,225,238,243,243,229,242,233,102,128, 39,+ 146,228,229,246, 97,128, 9,111,231,117, 2,134, 31,134, 40,234,+ 225,242,225,244,105,128, 10,239,242,237,245,235,232,105,128, 10,+ 111,232, 97, 2,134, 56,134, 67,227,235,225,242,225,226,233, 99,+ 128, 6,105,238,231,250,232,239,117,128, 48, 41,105, 2,134, 82,+ 134,100,228,229,239,231,242,225,240,232,233,227,240,225,242,229,+ 110,128, 50, 40,238,230,229,242,233,239,114,128, 32,137,237,239,+ 238,239,243,240,225,227,101,128,255, 25,239,236,228,243,244,249,+ 236,101,128,247, 57,112, 2,134,139,134,146,225,242,229,110,128,+ 36,124,229,114, 2,134,153,134,159,233,239,100,128, 36,144,243,+ 233,225,110,128, 6,249,242,239,237,225,110,128, 33,120,243,245,+ 240,229,242,233,239,114,128, 32,121,116, 2,134,191,134,229,229,+ 229,110, 2,134,199,134,208,227,233,242,227,236,101,128, 36,114,+ 112, 2,134,214,134,221,225,242,229,110,128, 36,134,229,242,233,+ 239,100,128, 36,154,232,225,105,128, 14, 89,106,129, 1,204,134,+ 241,229,227,249,242,233,236,236,233, 99,128, 4, 90,235,225,244,+ 225,235,225,238, 97,129, 48,243,135, 10,232,225,236,230,247,233,+ 228,244,104,128,255,157,108, 2,135, 28,135, 42,229,231,242,233,+ 231,232,244,236,239,238,103,128, 1,158,233,238,229,226,229,236,+ 239,119,128, 30, 73,109, 2,135, 59,135, 70,239,238,239,243,240,+ 225,227,101,128,255, 78,243,241,245,225,242,101,128, 51,154,110,+ 2,135, 85,135,135, 97, 3,135, 93,135,103,135,110,226,229,238,+ 231,225,236,105,128, 9,163,228,229,246, 97,128, 9, 35,231,117,+ 2,135,117,135,126,234,225,242,225,244,105,128, 10,163,242,237,+ 245,235,232,105,128, 10, 35,238,225,228,229,246, 97,128, 9, 41,+ 111, 6,135,158,135,169,135,194,135,235,136,187,137,114,232,233,+ 242,225,231,225,238, 97,128, 48,110,235,225,244,225,235,225,238,+ 97,129, 48,206,135,182,232,225,236,230,247,233,228,244,104,128,+ 255,137,110, 3,135,202,135,218,135,227,226,242,229,225,235,233,+ 238,231,243,240,225,227,101,128, 0,160,229,238,244,232,225,105,+ 128, 14, 19,245,244,232,225,105,128, 14, 25,239,110, 7,135,252,+ 136, 5,136, 19,136, 53,136, 69,136,110,136,169,225,242,225,226,+ 233, 99,128, 6, 70,230,233,238,225,236,225,242,225,226,233, 99,+ 128,254,230,231,232,245,238,238, 97, 2,136, 30,136, 39,225,242,+ 225,226,233, 99,128, 6,186,230,233,238,225,236,225,242,225,226,+ 233, 99,128,251,159,233,238,233,244,233,225,236,225,242,225,226,+ 233, 99,128,254,231,234,229,229,237,105, 2,136, 79,136, 94,238,+ 233,244,233,225,236,225,242,225,226,233, 99,128,252,210,243,239,+ 236,225,244,229,228,225,242,225,226,233, 99,128,252, 75,237,101,+ 2,136,117,136,130,228,233,225,236,225,242,225,226,233, 99,128,+ 254,232,229,237,105, 2,136,138,136,153,238,233,244,233,225,236,+ 225,242,225,226,233, 99,128,252,213,243,239,236,225,244,229,228,+ 225,242,225,226,233, 99,128,252, 78,238,239,239,238,230,233,238,+ 225,236,225,242,225,226,233, 99,128,252,141,116, 7,136,203,136,+ 214,136,243,137, 22,137, 34,137, 54,137, 80,227,239,238,244,225,+ 233,238,115,128, 34, 12,101, 2,136,220,136,236,236,229,237,229,+ 238,116,129, 34, 9,136,231,239,102,128, 34, 9,241,245,225,108,+ 128, 34, 96,231,242,229,225,244,229,114,129, 34,111,136,255,238,+ 239,114, 2,137, 7,137, 15,229,241,245,225,108,128, 34,113,236,+ 229,243,115,128, 34,121,233,228,229,238,244,233,227,225,108,128,+ 34, 98,236,229,243,115,129, 34,110,137, 43,238,239,242,229,241,+ 245,225,108,128, 34,112,112, 2,137, 60,137, 70,225,242,225,236,+ 236,229,108,128, 34, 38,242,229,227,229,228,229,115,128, 34,128,+ 243,117, 3,137, 89,137, 96,137,105,226,243,229,116,128, 34,132,+ 227,227,229,229,228,115,128, 34,129,240,229,242,243,229,116,128,+ 34,133,247,225,242,237,229,238,233,225,110,128, 5,118,240,225,+ 242,229,110,128, 36,169,115, 2,137,140,137,149,243,241,245,225,+ 242,101,128, 51,177,245,240,229,242,233,239,114,128, 32,127,244,+ 233,236,228,101,128, 0,241,117,132, 3,189,137,179,137,190,138,+ 15,138, 98,232,233,242,225,231,225,238, 97,128, 48,108,107, 2,+ 137,196,137,220,225,244,225,235,225,238, 97,129, 48,204,137,208,+ 232,225,236,230,247,233,228,244,104,128,255,135,244, 97, 3,137,+ 229,137,239,137,246,226,229,238,231,225,236,105,128, 9,188,228,+ 229,246, 97,128, 9, 60,231,117, 2,137,253,138, 6,234,225,242,+ 225,244,105,128, 10,188,242,237,245,235,232,105,128, 10, 60,109,+ 2,138, 21,138, 55,226,229,242,243,233,231,110,130, 0, 35,138,+ 35,138, 47,237,239,238,239,243,240,225,227,101,128,255, 3,243,+ 237,225,236,108,128,254, 95,229,114, 2,138, 62,138, 94,225,236,+ 243,233,231,110, 2,138, 73,138, 81,231,242,229,229,107,128, 3,+ 116,236,239,247,229,242,231,242,229,229,107,128, 3,117,111,128,+ 33, 22,110,130, 5,224,138,106,138,126,228,225,231,229,243,104,+ 129,251, 64,138,117,232,229,226,242,229,119,128,251, 64,232,229,+ 226,242,229,119,128, 5,224,246,243,241,245,225,242,101,128, 51,+ 181,247,243,241,245,225,242,101,128, 51,187,249, 97, 3,138,164,+ 138,174,138,181,226,229,238,231,225,236,105,128, 9,158,228,229,+ 246, 97,128, 9, 30,231,117, 2,138,188,138,197,234,225,242,225,+ 244,105,128, 10,158,242,237,245,235,232,105,128, 10, 30,111,147,+ 0,111,138,248,139, 14,139, 92,140, 6,140, 78,140, 93,140,133,+ 141, 0,141, 21,141, 59,141, 70,141,248,143, 82,143,146,143,179,+ 143,225,144, 98,144,145,144,157, 97, 2,138,254,139, 5,227,245,+ 244,101,128, 0,243,238,231,244,232,225,105,128, 14, 45, 98, 4,+ 139, 24,139, 66,139, 75,139, 85,225,242,242,229,100,130, 2,117,+ 139, 36,139, 47,227,249,242,233,236,236,233, 99,128, 4,233,228,+ 233,229,242,229,243,233,243,227,249,242,233,236,236,233, 99,128,+ 4,235,229,238,231,225,236,105,128, 9,147,239,240,239,237,239,+ 230,111,128, 49, 27,242,229,246,101,128, 1, 79, 99, 3,139,100,+ 139,173,139,252, 97, 2,139,106,139,167,238,228,242, 97, 3,139,+ 117,139,124,139,135,228,229,246, 97,128, 9, 17,231,245,234,225,+ 242,225,244,105,128, 10,145,246,239,247,229,236,243,233,231,110,+ 2,139,149,139,156,228,229,246, 97,128, 9, 73,231,245,234,225,+ 242,225,244,105,128, 10,201,242,239,110,128, 1,210,233,242, 99,+ 2,139,181,139,186,236,101,128, 36,222,245,237,230,236,229,120,+ 133, 0,244,139,205,139,213,139,224,139,232,139,244,225,227,245,+ 244,101,128, 30,209,228,239,244,226,229,236,239,119,128, 30,217,+ 231,242,225,246,101,128, 30,211,232,239,239,235,225,226,239,246,+ 101,128, 30,213,244,233,236,228,101,128, 30,215,249,242,233,236,+ 236,233, 99,128, 4, 62,100, 4,140, 16,140, 39,140, 45,140, 68,+ 226,108, 2,140, 23,140, 31,225,227,245,244,101,128, 1, 81,231,+ 242,225,246,101,128, 2, 13,229,246, 97,128, 9, 19,233,229,242,+ 229,243,233,115,129, 0,246,140, 57,227,249,242,233,236,236,233,+ 99,128, 4,231,239,244,226,229,236,239,119,128, 30,205,101,129,+ 1, 83,140, 84,235,239,242,229,225,110,128, 49, 90,103, 3,140,+ 101,140,116,140,123,239,238,229,107,129, 2,219,140,110,227,237,+ 98,128, 3, 40,242,225,246,101,128, 0,242,245,234,225,242,225,+ 244,105,128, 10,147,104, 4,140,143,140,154,140,164,140,242,225,+ 242,237,229,238,233,225,110,128, 5,133,233,242,225,231,225,238,+ 97,128, 48, 74,111, 2,140,170,140,180,239,235,225,226,239,246,+ 101,128, 30,207,242,110,133, 1,161,140,195,140,203,140,214,140,+ 222,140,234,225,227,245,244,101,128, 30,219,228,239,244,226,229,+ 236,239,119,128, 30,227,231,242,225,246,101,128, 30,221,232,239,+ 239,235,225,226,239,246,101,128, 30,223,244,233,236,228,101,128,+ 30,225,245,238,231,225,242,245,237,236,225,245,116,128, 1, 81,+ 105,129, 1,163,141, 6,238,246,229,242,244,229,228,226,242,229,+ 246,101,128, 2, 15,107, 2,141, 27,141, 51,225,244,225,235,225,+ 238, 97,129, 48,170,141, 39,232,225,236,230,247,233,228,244,104,+ 128,255,117,239,242,229,225,110,128, 49, 87,236,229,232,229,226,+ 242,229,119,128, 5,171,109, 6,141, 84,141,112,141,119,141,208,+ 141,219,141,237,225,227,242,239,110,130, 1, 77,141, 96,141,104,+ 225,227,245,244,101,128, 30, 83,231,242,225,246,101,128, 30, 81,+ 228,229,246, 97,128, 9, 80,229,231, 97,133, 3,201,141,135,141,+ 139,141,150,141,164,141,180, 49,128, 3,214,227,249,242,233,236,+ 236,233, 99,128, 4, 97,236,225,244,233,238,227,236,239,243,229,+ 100,128, 2,119,242,239,245,238,228,227,249,242,233,236,236,233,+ 99,128, 4,123,116, 2,141,186,141,201,233,244,236,239,227,249,+ 242,233,236,236,233, 99,128, 4,125,239,238,239,115,128, 3,206,+ 231,245,234,225,242,225,244,105,128, 10,208,233,227,242,239,110,+ 129, 3,191,141,229,244,239,238,239,115,128, 3,204,239,238,239,+ 243,240,225,227,101,128,255, 79,238,101,145, 0, 49,142, 31,142,+ 40,142, 50,142, 80,142,105,142,114,142,123,142,148,142,182,142,+ 216,142,228,142,247,143, 2,143, 35,143, 45,143, 53,143, 64,225,+ 242,225,226,233, 99,128, 6, 97,226,229,238,231,225,236,105,128,+ 9,231,227,233,242,227,236,101,129, 36, 96,142, 61,233,238,246,+ 229,242,243,229,243,225,238,243,243,229,242,233,102,128, 39,138,+ 100, 2,142, 86,142, 92,229,246, 97,128, 9,103,239,244,229,238,+ 236,229,225,228,229,114,128, 32, 36,229,233,231,232,244,104,128,+ 33, 91,230,233,244,244,229,100,128,246,220,231,117, 2,142,130,+ 142,139,234,225,242,225,244,105,128, 10,231,242,237,245,235,232,+ 105,128, 10,103,232, 97, 3,142,157,142,168,142,173,227,235,225,+ 242,225,226,233, 99,128, 6, 97,236,102,128, 0,189,238,231,250,+ 232,239,117,128, 48, 33,105, 2,142,188,142,206,228,229,239,231,+ 242,225,240,232,233,227,240,225,242,229,110,128, 50, 32,238,230,+ 229,242,233,239,114,128, 32,129,237,239,238,239,243,240,225,227,+ 101,128,255, 17,238,245,237,229,242,225,244,239,242,226,229,238,+ 231,225,236,105,128, 9,244,239,236,228,243,244,249,236,101,128,+ 247, 49,112, 2,143, 8,143, 15,225,242,229,110,128, 36,116,229,+ 114, 2,143, 22,143, 28,233,239,100,128, 36,136,243,233,225,110,+ 128, 6,241,241,245,225,242,244,229,114,128, 0,188,242,239,237,+ 225,110,128, 33,112,243,245,240,229,242,233,239,114,128, 0,185,+ 244,104, 2,143, 71,143, 76,225,105,128, 14, 81,233,242,100,128,+ 33, 83,111, 3,143, 90,143,124,143,140,103, 2,143, 96,143,114,+ 239,238,229,107,129, 1,235,143,105,237,225,227,242,239,110,128,+ 1,237,245,242,237,245,235,232,105,128, 10, 19,237,225,244,242,+ 225,231,245,242,237,245,235,232,105,128, 10, 75,240,229,110,128,+ 2, 84,112, 3,143,154,143,161,143,172,225,242,229,110,128, 36,+ 170,229,238,226,245,236,236,229,116,128, 37,230,244,233,239,110,+ 128, 35, 37,114, 2,143,185,143,214,100, 2,143,191,143,202,230,+ 229,237,233,238,233,238,101,128, 0,170,237,225,243,227,245,236,+ 233,238,101,128, 0,186,244,232,239,231,239,238,225,108,128, 34,+ 31,115, 5,143,237,144, 13,144, 30,144, 75,144, 88,232,239,242,+ 116, 2,143,246,143,253,228,229,246, 97,128, 9, 18,246,239,247,+ 229,236,243,233,231,238,228,229,246, 97,128, 9, 74,236,225,243,+ 104,129, 0,248,144, 22,225,227,245,244,101,128, 1,255,237,225,+ 236,108, 2,144, 39,144, 50,232,233,242,225,231,225,238, 97,128,+ 48, 73,235,225,244,225,235,225,238, 97,129, 48,169,144, 63,232,+ 225,236,230,247,233,228,244,104,128,255,107,244,242,239,235,229,+ 225,227,245,244,101,128, 1,255,245,240,229,242,233,239,114,128,+ 246,240,116, 2,144,104,144,115,227,249,242,233,236,236,233, 99,+ 128, 4,127,233,236,228,101,130, 0,245,144,126,144,134,225,227,+ 245,244,101,128, 30, 77,228,233,229,242,229,243,233,115,128, 30,+ 79,245,226,239,240,239,237,239,230,111,128, 49, 33,118, 2,144,+ 163,144,244,229,114, 2,144,170,144,236,236,233,238,101,131, 32,+ 62,144,183,144,206,144,229, 99, 2,144,189,144,201,229,238,244,+ 229,242,236,233,238,101,128,254, 74,237, 98,128, 3, 5,100, 2,+ 144,212,144,220,225,243,232,229,100,128,254, 73,226,236,247,225,+ 246,121,128,254, 76,247,225,246,121,128,254, 75,243,227,239,242,+ 101,128, 0,175,239,247,229,236,243,233,231,110, 3,145, 3,145,+ 13,145, 20,226,229,238,231,225,236,105,128, 9,203,228,229,246,+ 97,128, 9, 75,231,245,234,225,242,225,244,105,128, 10,203,112,+ 145, 0,112,145, 69,147,197,147,208,147,217,147,229,149,154,149,+ 164,150,156,151,175,152, 9,152, 35,152,166,152,174,153, 76,153,+ 134,153,162,153,172, 97, 14,145, 99,145,131,145,141,145,148,145,+ 155,145,203,145,214,145,228,145,239,146, 30,146, 44,147, 56,147,+ 95,147,185, 97, 2,145,105,145,117,237,240,243,243,241,245,225,+ 242,101,128, 51,128,243,229,238,244,239,243,241,245,225,242,101,+ 128, 51, 43,226,229,238,231,225,236,105,128, 9,170,227,245,244,+ 101,128, 30, 85,228,229,246, 97,128, 9, 42,103, 2,145,161,145,+ 179,101, 2,145,167,145,174,228,239,247,110,128, 33,223,245,112,+ 128, 33,222,117, 2,145,185,145,194,234,225,242,225,244,105,128,+ 10,170,242,237,245,235,232,105,128, 10, 42,232,233,242,225,231,+ 225,238, 97,128, 48,113,233,249,225,238,238,239,233,244,232,225,+ 105,128, 14, 47,235,225,244,225,235,225,238, 97,128, 48,209,108,+ 2,145,245,146, 14,225,244,225,236,233,250,225,244,233,239,238,+ 227,249,242,233,236,236,233,227,227,237, 98,128, 4,132,239,227,+ 232,235,225,227,249,242,233,236,236,233, 99,128, 4,192,238,243,+ 233,239,243,235,239,242,229,225,110,128, 49,127,114, 3,146, 52,+ 146, 73,147, 45, 97, 2,146, 58,146, 66,231,242,225,240,104,128,+ 0,182,236,236,229,108,128, 34, 37,229,110, 2,146, 80,146,190,+ 236,229,230,116,136, 0, 40,146,103,146,118,146,123,146,128,146,+ 139,146,151,146,174,146,179,225,236,244,239,238,229,225,242,225,+ 226,233, 99,128,253, 62,226,116,128,248,237,229,120,128,248,236,+ 233,238,230,229,242,233,239,114,128, 32,141,237,239,238,239,243,+ 240,225,227,101,128,255, 8,115, 2,146,157,146,164,237,225,236,+ 108,128,254, 89,245,240,229,242,233,239,114,128, 32,125,244,112,+ 128,248,235,246,229,242,244,233,227,225,108,128,254, 53,242,233,+ 231,232,116,136, 0, 41,146,214,146,229,146,234,146,239,146,250,+ 147, 6,147, 29,147, 34,225,236,244,239,238,229,225,242,225,226,+ 233, 99,128,253, 63,226,116,128,248,248,229,120,128,248,247,233,+ 238,230,229,242,233,239,114,128, 32,142,237,239,238,239,243,240,+ 225,227,101,128,255, 9,115, 2,147, 12,147, 19,237,225,236,108,+ 128,254, 90,245,240,229,242,233,239,114,128, 32,126,244,112,128,+ 248,246,246,229,242,244,233,227,225,108,128,254, 54,244,233,225,+ 236,228,233,230,102,128, 34, 2,115, 3,147, 64,147, 75,147, 87,+ 229,241,232,229,226,242,229,119,128, 5,192,232,244,225,232,229,+ 226,242,229,119,128, 5,153,241,245,225,242,101,128, 51,169,244,+ 225,104,134, 5,183,147,113,147,127,147,132,147,141,147,156,147,+ 172, 49, 2,147,119,147,123, 49,128, 5,183,100,128, 5,183,178,+ 97,128, 5,183,232,229,226,242,229,119,128, 5,183,238,225,242,+ 242,239,247,232,229,226,242,229,119,128, 5,183,241,245,225,242,+ 244,229,242,232,229,226,242,229,119,128, 5,183,247,233,228,229,+ 232,229,226,242,229,119,128, 5,183,250,229,242,232,229,226,242,+ 229,119,128, 5,161,226,239,240,239,237,239,230,111,128, 49, 6,+ 227,233,242,227,236,101,128, 36,223,228,239,244,225,227,227,229,+ 238,116,128, 30, 87,101,137, 5,228,147,251,148, 6,148, 26,148,+ 38,148, 58,148,160,148,171,148,192,149,147,227,249,242,233,236,+ 236,233, 99,128, 4, 63,228,225,231,229,243,104,129,251, 68,148,+ 17,232,229,226,242,229,119,128,251, 68,229,250,233,243,241,245,+ 225,242,101,128, 51, 59,230,233,238,225,236,228,225,231,229,243,+ 232,232,229,226,242,229,119,128,251, 67,104, 5,148, 70,148, 93,+ 148,101,148,115,148,145,225,114, 2,148, 77,148, 84,225,226,233,+ 99,128, 6,126,237,229,238,233,225,110,128, 5,122,229,226,242,+ 229,119,128, 5,228,230,233,238,225,236,225,242,225,226,233, 99,+ 128,251, 87,105, 2,148,121,148,136,238,233,244,233,225,236,225,+ 242,225,226,233, 99,128,251, 88,242,225,231,225,238, 97,128, 48,+ 122,237,229,228,233,225,236,225,242,225,226,233, 99,128,251, 89,+ 235,225,244,225,235,225,238, 97,128, 48,218,237,233,228,228,236,+ 229,232,239,239,235,227,249,242,233,236,236,233, 99,128, 4,167,+ 114, 5,148,204,148,216,149, 2,149,123,149,136,225,230,229,232,+ 229,226,242,229,119,128,251, 78,227,229,238,116,131, 0, 37,148,+ 229,148,238,148,250,225,242,225,226,233, 99,128, 6,106,237,239,+ 238,239,243,240,225,227,101,128,255, 5,243,237,225,236,108,128,+ 254,106,105, 2,149, 8,149,105,239,100,134, 0, 46,149, 25,149,+ 36,149, 47,149, 59,149, 70,149, 82,225,242,237,229,238,233,225,+ 110,128, 5,137,227,229,238,244,229,242,229,100,128, 0,183,232,+ 225,236,230,247,233,228,244,104,128,255, 97,233,238,230,229,242,+ 233,239,114,128,246,231,237,239,238,239,243,240,225,227,101,128,+ 255, 14,115, 2,149, 88,149, 95,237,225,236,108,128,254, 82,245,+ 240,229,242,233,239,114,128,246,232,243,240,239,237,229,238,233,+ 231,242,229,229,235,227,237, 98,128, 3, 66,240,229,238,228,233,+ 227,245,236,225,114,128, 34,165,244,232,239,245,243,225,238,100,+ 128, 32, 48,243,229,244, 97,128, 32,167,230,243,241,245,225,242,+ 101,128, 51,138,104, 3,149,172,149,222,150,103, 97, 3,149,180,+ 149,190,149,197,226,229,238,231,225,236,105,128, 9,171,228,229,+ 246, 97,128, 9, 43,231,117, 2,149,204,149,213,234,225,242,225,+ 244,105,128, 10,171,242,237,245,235,232,105,128, 10, 43,105,133,+ 3,198,149,236,149,240,150, 70,150, 78,150, 89, 49,128, 3,213,+ 229,245,240,104, 4,149,253,150, 32,150, 47,150, 56, 97, 2,150,+ 3,150, 18,227,233,242,227,236,229,235,239,242,229,225,110,128,+ 50,122,240,225,242,229,238,235,239,242,229,225,110,128, 50, 26,+ 227,233,242,227,236,229,235,239,242,229,225,110,128, 50,108,235,+ 239,242,229,225,110,128, 49, 77,240,225,242,229,238,235,239,242,+ 229,225,110,128, 50, 12,236,225,244,233,110,128, 2,120,238,244,+ 232,245,244,232,225,105,128, 14, 58,243,249,237,226,239,236,231,+ 242,229,229,107,128, 3,213,111, 3,150,111,150,116,150,142,239,+ 107,128, 1,165,240,104, 2,150,123,150,132,225,238,244,232,225,+ 105,128, 14, 30,245,238,231,244,232,225,105,128, 14, 28,243,225,+ 237,240,232,225,239,244,232,225,105,128, 14, 32,105,133, 3,192,+ 150,170,151,126,151,137,151,148,151,162,229,245,112, 6,150,186,+ 150,221,150,253,151, 25,151, 39,151, 91, 97, 2,150,192,150,207,+ 227,233,242,227,236,229,235,239,242,229,225,110,128, 50,115,240,+ 225,242,229,238,235,239,242,229,225,110,128, 50, 19,227,105, 2,+ 150,228,150,240,229,245,227,235,239,242,229,225,110,128, 49,118,+ 242,227,236,229,235,239,242,229,225,110,128, 50,101,107, 2,151,+ 3,151, 17,233,249,229,239,235,235,239,242,229,225,110,128, 49,+ 114,239,242,229,225,110,128, 49, 66,240,225,242,229,238,235,239,+ 242,229,225,110,128, 50, 5,243,233,239,115, 2,151, 48,151, 76,+ 107, 2,151, 54,151, 68,233,249,229,239,235,235,239,242,229,225,+ 110,128, 49,116,239,242,229,225,110,128, 49, 68,244,233,235,229,+ 245,244,235,239,242,229,225,110,128, 49,117,116, 2,151, 97,151,+ 112,232,233,229,245,244,232,235,239,242,229,225,110,128, 49,119,+ 233,235,229,245,244,235,239,242,229,225,110,128, 49,115,232,233,+ 242,225,231,225,238, 97,128, 48,116,235,225,244,225,235,225,238,+ 97,128, 48,212,243,249,237,226,239,236,231,242,229,229,107,128,+ 3,214,247,242,225,242,237,229,238,233,225,110,128, 5,131,236,+ 245,115,132, 0, 43,151,189,151,200,151,209,151,242,226,229,236,+ 239,247,227,237, 98,128, 3, 31,227,233,242,227,236,101,128, 34,+ 149,109, 2,151,215,151,222,233,238,245,115,128, 0,177,111, 2,+ 151,228,151,232,100,128, 2,214,238,239,243,240,225,227,101,128,+ 255, 11,115, 2,151,248,151,255,237,225,236,108,128,254, 98,245,+ 240,229,242,233,239,114,128, 32,122,109, 2,152, 15,152, 26,239,+ 238,239,243,240,225,227,101,128,255, 80,243,241,245,225,242,101,+ 128, 51,216,111, 5,152, 47,152, 58,152,125,152,136,152,146,232,+ 233,242,225,231,225,238, 97,128, 48,125,233,238,244,233,238,231,+ 233,238,228,229,120, 4,152, 78,152, 90,152,102,152,115,228,239,+ 247,238,247,232,233,244,101,128, 38, 31,236,229,230,244,247,232,+ 233,244,101,128, 38, 28,242,233,231,232,244,247,232,233,244,101,+ 128, 38, 30,245,240,247,232,233,244,101,128, 38, 29,235,225,244,+ 225,235,225,238, 97,128, 48,221,240,236,225,244,232,225,105,128,+ 14, 27,243,244,225,236,237,225,242,107,129, 48, 18,152,159,230,+ 225,227,101,128, 48, 32,240,225,242,229,110,128, 36,171,114, 3,+ 152,182,152,208,152,233,101, 2,152,188,152,196,227,229,228,229,+ 115,128, 34,122,243,227,242,233,240,244,233,239,110,128, 33, 30,+ 233,237,101, 2,152,216,152,222,237,239,100,128, 2,185,242,229,+ 246,229,242,243,229,100,128, 32, 53,111, 4,152,243,152,250,153,+ 4,153, 17,228,245,227,116,128, 34, 15,234,229,227,244,233,246,+ 101,128, 35, 5,236,239,238,231,229,228,235,225,238, 97,128, 48,+ 252,112, 2,153, 23,153, 60,101, 2,153, 29,153, 36,236,236,239,+ 114,128, 35, 24,242,243,117, 2,153, 44,153, 51,226,243,229,116,+ 128, 34,130,240,229,242,243,229,116,128, 34,131,239,242,244,233,+ 239,110,129, 34, 55,153, 71,225,108,128, 34, 29,115, 2,153, 82,+ 153,125,105,130, 3,200,153, 90,153,101,227,249,242,233,236,236,+ 233, 99,128, 4,113,236,233,240,238,229,245,237,225,244,225,227,+ 249,242,233,236,236,233,227,227,237, 98,128, 4,134,243,241,245,+ 225,242,101,128, 51,176,117, 2,153,140,153,151,232,233,242,225,+ 231,225,238, 97,128, 48,119,235,225,244,225,235,225,238, 97,128,+ 48,215,246,243,241,245,225,242,101,128, 51,180,247,243,241,245,+ 225,242,101,128, 51,186,113,136, 0,113,153,202,154,251,155, 6,+ 155, 15,155, 22,155, 34,155, 72,155, 80, 97, 4,153,212,153,235,+ 154, 43,154,234,100, 2,153,218,153,224,229,246, 97,128, 9, 88,+ 237,225,232,229,226,242,229,119,128, 5,168,102, 4,153,245,153,+ 254,154, 12,154, 28,225,242,225,226,233, 99,128, 6, 66,230,233,+ 238,225,236,225,242,225,226,233, 99,128,254,214,233,238,233,244,+ 233,225,236,225,242,225,226,233, 99,128,254,215,237,229,228,233,+ 225,236,225,242,225,226,233, 99,128,254,216,237,225,244,115,136,+ 5,184,154, 66,154, 86,154,100,154,105,154,110,154,119,154,134,+ 154,221, 49, 3,154, 74,154, 78,154, 82, 48,128, 5,184, 97,128,+ 5,184, 99,128, 5,184, 50, 2,154, 92,154, 96, 55,128, 5,184,+ 57,128, 5,184,179, 51,128, 5,184,228,101,128, 5,184,232,229,+ 226,242,229,119,128, 5,184,238,225,242,242,239,247,232,229,226,+ 242,229,119,128, 5,184,113, 2,154,140,154,206,225,244,225,110,+ 4,154,153,154,162,154,177,154,193,232,229,226,242,229,119,128,+ 5,184,238,225,242,242,239,247,232,229,226,242,229,119,128, 5,+ 184,241,245,225,242,244,229,242,232,229,226,242,229,119,128, 5,+ 184,247,233,228,229,232,229,226,242,229,119,128, 5,184,245,225,+ 242,244,229,242,232,229,226,242,229,119,128, 5,184,247,233,228,+ 229,232,229,226,242,229,119,128, 5,184,242,238,229,249,240,225,+ 242,225,232,229,226,242,229,119,128, 5,159,226,239,240,239,237,+ 239,230,111,128, 49, 17,227,233,242,227,236,101,128, 36,224,232,+ 239,239,107,128, 2,160,237,239,238,239,243,240,225,227,101,128,+ 255, 81,239,102,130, 5,231,155, 43,155, 63,228,225,231,229,243,+ 104,129,251, 71,155, 54,232,229,226,242,229,119,128,251, 71,232,+ 229,226,242,229,119,128, 5,231,240,225,242,229,110,128, 36,172,+ 117, 4,155, 90,155,102,155,191,156, 22,225,242,244,229,242,238,+ 239,244,101,128, 38,105,226,245,244,115,135, 5,187,155,123,155,+ 128,155,133,155,138,155,147,155,162,155,178,177, 56,128, 5,187,+ 178, 53,128, 5,187,179, 49,128, 5,187,232,229,226,242,229,119,+ 128, 5,187,238,225,242,242,239,247,232,229,226,242,229,119,128,+ 5,187,241,245,225,242,244,229,242,232,229,226,242,229,119,128,+ 5,187,247,233,228,229,232,229,226,242,229,119,128, 5,187,229,+ 243,244,233,239,110,133, 0, 63,155,210,155,233,155,250,156, 2,+ 156, 14,225,114, 2,155,217,155,224,225,226,233, 99,128, 6, 31,+ 237,229,238,233,225,110,128, 5, 94,228,239,247,110,129, 0,191,+ 155,242,243,237,225,236,108,128,247,191,231,242,229,229,107,128,+ 3,126,237,239,238,239,243,240,225,227,101,128,255, 31,243,237,+ 225,236,108,128,247, 63,239,244,101, 4,156, 34,156,105,156,125,+ 156,154,228,226,108,133, 0, 34,156, 50,156, 57,156, 64,156, 76,+ 156, 97,226,225,243,101,128, 32, 30,236,229,230,116,128, 32, 28,+ 237,239,238,239,243,240,225,227,101,128,255, 2,240,242,233,237,+ 101,129, 48, 30,156, 86,242,229,246,229,242,243,229,100,128, 48,+ 29,242,233,231,232,116,128, 32, 29,236,229,230,116,129, 32, 24,+ 156,114,242,229,246,229,242,243,229,100,128, 32, 27,114, 2,156,+ 131,156,141,229,246,229,242,243,229,100,128, 32, 27,233,231,232,+ 116,129, 32, 25,156,150,110,128, 1, 73,243,233,238,231,108, 2,+ 156,164,156,171,226,225,243,101,128, 32, 26,101,129, 0, 39,156,+ 177,237,239,238,239,243,240,225,227,101,128,255, 7,114,145, 0,+ 114,156,227,157,231,157,242,158, 33,158, 84,159,101,159,125,159,+ 220,161,254,162, 35,162, 47,162,101,162,109,163, 15,163, 26,163,+ 61,163,161, 97, 11,156,251,157, 6,157, 16,157, 23,157, 88,157,+ 104,157,129,157,140,157,165,157,188,157,225,225,242,237,229,238,+ 233,225,110,128, 5,124,226,229,238,231,225,236,105,128, 9,176,+ 227,245,244,101,128, 1, 85,100, 4,157, 33,157, 39,157, 53,157,+ 79,229,246, 97,128, 9, 48,233,227,225,108,129, 34, 26,157, 48,+ 229,120,128,248,229,239,246,229,242,243,243,241,245,225,242,101,+ 129, 51,174,157, 69,228,243,241,245,225,242,101,128, 51,175,243,+ 241,245,225,242,101,128, 51,173,230,101,129, 5,191,157, 95,232,+ 229,226,242,229,119,128, 5,191,231,117, 2,157,111,157,120,234,+ 225,242,225,244,105,128, 10,176,242,237,245,235,232,105,128, 10,+ 48,232,233,242,225,231,225,238, 97,128, 48,137,235,225,244,225,+ 235,225,238, 97,129, 48,233,157,153,232,225,236,230,247,233,228,+ 244,104,128,255,151,236,239,247,229,242,228,233,225,231,239,238,+ 225,236,226,229,238,231,225,236,105,128, 9,241,109, 2,157,194,+ 157,217,233,228,228,236,229,228,233,225,231,239,238,225,236,226,+ 229,238,231,225,236,105,128, 9,240,243,232,239,242,110,128, 2,+ 100,244,233,111,128, 34, 54,226,239,240,239,237,239,230,111,128,+ 49, 22, 99, 4,157,252,158, 3,158, 12,158, 20,225,242,239,110,+ 128, 1, 89,229,228,233,236,236, 97,128, 1, 87,233,242,227,236,+ 101,128, 36,225,239,237,237,225,225,227,227,229,238,116,128, 1,+ 87,100, 2,158, 39,158, 49,226,236,231,242,225,246,101,128, 2,+ 17,239,116, 2,158, 56,158, 65,225,227,227,229,238,116,128, 30,+ 89,226,229,236,239,119,129, 30, 91,158, 75,237,225,227,242,239,+ 110,128, 30, 93,101, 6,158, 98,158,143,158,178,158,233,159, 2,+ 159, 35,102, 2,158,104,158,117,229,242,229,238,227,229,237,225,+ 242,107,128, 32, 59,236,229,248,243,117, 2,158,127,158,134,226,+ 243,229,116,128, 34,134,240,229,242,243,229,116,128, 34,135,231,+ 233,243,244,229,114, 2,158,154,158,159,229,100,128, 0,174,115,+ 2,158,165,158,171,225,238,115,128,248,232,229,242,233,102,128,+ 246,218,104, 3,158,186,158,209,158,223,225,114, 2,158,193,158,+ 200,225,226,233, 99,128, 6, 49,237,229,238,233,225,110,128, 5,+ 128,230,233,238,225,236,225,242,225,226,233, 99,128,254,174,233,+ 242,225,231,225,238, 97,128, 48,140,235,225,244,225,235,225,238,+ 97,129, 48,236,158,246,232,225,236,230,247,233,228,244,104,128,+ 255,154,243,104,130, 5,232,159, 11,159, 26,228,225,231,229,243,+ 232,232,229,226,242,229,119,128,251, 72,232,229,226,242,229,119,+ 128, 5,232,118, 3,159, 43,159, 56,159, 88,229,242,243,229,228,+ 244,233,236,228,101,128, 34, 61,233, 97, 2,159, 63,159, 72,232,+ 229,226,242,229,119,128, 5,151,237,245,231,242,225,243,232,232,+ 229,226,242,229,119,128, 5,151,236,239,231,233,227,225,236,238,+ 239,116,128, 35, 16,230,233,243,232,232,239,239,107,129, 2,126,+ 159,114,242,229,246,229,242,243,229,100,128, 2,127,104, 2,159,+ 131,159,154, 97, 2,159,137,159,147,226,229,238,231,225,236,105,+ 128, 9,221,228,229,246, 97,128, 9, 93,111,131, 3,193,159,164,+ 159,193,159,207,239,107,129, 2,125,159,171,244,245,242,238,229,+ 100,129, 2,123,159,182,243,245,240,229,242,233,239,114,128, 2,+ 181,243,249,237,226,239,236,231,242,229,229,107,128, 3,241,244,+ 233,227,232,239,239,235,237,239,100,128, 2,222,105, 6,159,234,+ 161, 22,161, 68,161, 79,161,104,161,240,229,245,108, 9,160, 0,+ 160, 35,160, 50,160, 64,160,110,160,124,160,210,160,223,161, 2,+ 97, 2,160, 6,160, 21,227,233,242,227,236,229,235,239,242,229,+ 225,110,128, 50,113,240,225,242,229,238,235,239,242,229,225,110,+ 128, 50, 17,227,233,242,227,236,229,235,239,242,229,225,110,128,+ 50, 99,232,233,229,245,232,235,239,242,229,225,110,128, 49, 64,+ 107, 2,160, 70,160,102,233,249,229,239,107, 2,160, 80,160, 89,+ 235,239,242,229,225,110,128, 49, 58,243,233,239,243,235,239,242,+ 229,225,110,128, 49,105,239,242,229,225,110,128, 49, 57,237,233,+ 229,245,237,235,239,242,229,225,110,128, 49, 59,112, 3,160,132,+ 160,164,160,179, 97, 2,160,138,160,152,238,243,233,239,243,235,+ 239,242,229,225,110,128, 49,108,242,229,238,235,239,242,229,225,+ 110,128, 50, 3,232,233,229,245,240,232,235,239,242,229,225,110,+ 128, 49, 63,233,229,245,112, 2,160,188,160,197,235,239,242,229,+ 225,110,128, 49, 60,243,233,239,243,235,239,242,229,225,110,128,+ 49,107,243,233,239,243,235,239,242,229,225,110,128, 49, 61,116,+ 2,160,229,160,244,232,233,229,245,244,232,235,239,242,229,225,+ 110,128, 49, 62,233,235,229,245,244,235,239,242,229,225,110,128,+ 49,106,249,229,239,242,233,238,232,233,229,245,232,235,239,242,+ 229,225,110,128, 49,109,231,232,116, 2,161, 30,161, 38,225,238,+ 231,236,101,128, 34, 31,116, 2,161, 44,161, 58,225,227,235,226,+ 229,236,239,247,227,237, 98,128, 3, 25,242,233,225,238,231,236,+ 101,128, 34,191,232,233,242,225,231,225,238, 97,128, 48,138,235,+ 225,244,225,235,225,238, 97,129, 48,234,161, 92,232,225,236,230,+ 247,233,228,244,104,128,255,152,110, 2,161,110,161,226,103,131,+ 2,218,161,120,161,131,161,137,226,229,236,239,247,227,237, 98,+ 128, 3, 37,227,237, 98,128, 3, 10,232,225,236,102, 2,161,146,+ 161,192,236,229,230,116,131, 2,191,161,159,161,170,161,181,225,+ 242,237,229,238,233,225,110,128, 5, 89,226,229,236,239,247,227,+ 237, 98,128, 3, 28,227,229,238,244,229,242,229,100,128, 2,211,+ 242,233,231,232,116,130, 2,190,161,204,161,215,226,229,236,239,+ 247,227,237, 98,128, 3, 57,227,229,238,244,229,242,229,100,128,+ 2,210,246,229,242,244,229,228,226,242,229,246,101,128, 2, 19,+ 244,244,239,242,245,243,241,245,225,242,101,128, 51, 81,108, 2,+ 162, 4,162, 15,233,238,229,226,229,236,239,119,128, 30, 95,239,+ 238,231,236,229,103,129, 2,124,162, 26,244,245,242,238,229,100,+ 128, 2,122,237,239,238,239,243,240,225,227,101,128,255, 82,111,+ 3,162, 55,162, 66,162, 91,232,233,242,225,231,225,238, 97,128,+ 48,141,235,225,244,225,235,225,238, 97,129, 48,237,162, 79,232,+ 225,236,230,247,233,228,244,104,128,255,155,242,245,225,244,232,+ 225,105,128, 14, 35,240,225,242,229,110,128, 36,173,114, 3,162,+ 117,162,153,162,183, 97, 3,162,125,162,135,162,142,226,229,238,+ 231,225,236,105,128, 9,220,228,229,246, 97,128, 9, 49,231,245,+ 242,237,245,235,232,105,128, 10, 92,229,104, 2,162,160,162,169,+ 225,242,225,226,233, 99,128, 6,145,230,233,238,225,236,225,242,+ 225,226,233, 99,128,251,141,246,239,227,225,236,233, 99, 4,162,+ 199,162,209,162,216,162,227,226,229,238,231,225,236,105,128, 9,+ 224,228,229,246, 97,128, 9, 96,231,245,234,225,242,225,244,105,+ 128, 10,224,246,239,247,229,236,243,233,231,110, 3,162,243,162,+ 253,163, 4,226,229,238,231,225,236,105,128, 9,196,228,229,246,+ 97,128, 9, 68,231,245,234,225,242,225,244,105,128, 10,196,243,+ 245,240,229,242,233,239,114,128,246,241,116, 2,163, 32,163, 40,+ 226,236,239,227,107,128, 37,144,245,242,238,229,100,129, 2,121,+ 163, 50,243,245,240,229,242,233,239,114,128, 2,180,117, 4,163,+ 71,163, 82,163,107,163,154,232,233,242,225,231,225,238, 97,128,+ 48,139,235,225,244,225,235,225,238, 97,129, 48,235,163, 95,232,+ 225,236,230,247,233,228,244,104,128,255,153,112, 2,163,113,163,+ 148,229,101, 2,163,120,163,134,237,225,242,235,226,229,238,231,+ 225,236,105,128, 9,242,243,233,231,238,226,229,238,231,225,236,+ 105,128, 9,243,233,225,104,128,246,221,244,232,225,105,128, 14,+ 36,246,239,227,225,236,233, 99, 4,163,177,163,187,163,194,163,+ 205,226,229,238,231,225,236,105,128, 9,139,228,229,246, 97,128,+ 9, 11,231,245,234,225,242,225,244,105,128, 10,139,246,239,247,+ 229,236,243,233,231,110, 3,163,221,163,231,163,238,226,229,238,+ 231,225,236,105,128, 9,195,228,229,246, 97,128, 9, 67,231,245,+ 234,225,242,225,244,105,128, 10,195,115,147, 0,115,164, 35,166,+ 5,166, 16,166,142,166,181,169,123,169,134,172, 21,174,159,174,+ 205,174,232,175,167,175,234,177, 11,177, 21,177,207,178, 24,178,+ 194,178,204, 97, 9,164, 55,164, 65,164, 86,164,158,164,183,164,+ 194,164,219,164,251,165, 35,226,229,238,231,225,236,105,128, 9,+ 184,227,245,244,101,129, 1, 91,164, 74,228,239,244,225,227,227,+ 229,238,116,128, 30,101,100, 5,164, 98,164,107,164,113,164,127,+ 164,143,225,242,225,226,233, 99,128, 6, 53,229,246, 97,128, 9,+ 56,230,233,238,225,236,225,242,225,226,233, 99,128,254,186,233,+ 238,233,244,233,225,236,225,242,225,226,233, 99,128,254,187,237,+ 229,228,233,225,236,225,242,225,226,233, 99,128,254,188,231,117,+ 2,164,165,164,174,234,225,242,225,244,105,128, 10,184,242,237,+ 245,235,232,105,128, 10, 56,232,233,242,225,231,225,238, 97,128,+ 48, 85,235,225,244,225,235,225,238, 97,129, 48,181,164,207,232,+ 225,236,230,247,233,228,244,104,128,255,123,236,236,225,236,236,+ 225,232,239,245,225,236,225,249,232,229,247,225,243,225,236,236,+ 225,237,225,242,225,226,233, 99,128,253,250,237,229,235,104,130,+ 5,225,165, 6,165, 26,228,225,231,229,243,104,129,251, 65,165,+ 17,232,229,226,242,229,119,128,251, 65,232,229,226,242,229,119,+ 128, 5,225,242, 97, 5,165, 48,165,122,165,130,165,180,165,188,+ 97, 5,165, 60,165, 68,165, 76,165,107,165,115,225,244,232,225,+ 105,128, 14, 50,229,244,232,225,105,128, 14, 65,233,237,225,233,+ 109, 2,165, 86,165, 97,225,236,225,233,244,232,225,105,128, 14,+ 68,245,225,238,244,232,225,105,128, 14, 67,237,244,232,225,105,+ 128, 14, 51,244,232,225,105,128, 14, 48,229,244,232,225,105,128,+ 14, 64,105, 3,165,138,165,162,165,173,105, 2,165,144,165,155,+ 236,229,230,244,244,232,225,105,128,248,134,244,232,225,105,128,+ 14, 53,236,229,230,244,244,232,225,105,128,248,133,244,232,225,+ 105,128, 14, 52,239,244,232,225,105,128, 14, 66,117, 3,165,196,+ 165,246,165,253,101, 3,165,204,165,228,165,239,101, 2,165,210,+ 165,221,236,229,230,244,244,232,225,105,128,248,136,244,232,225,+ 105,128, 14, 55,236,229,230,244,244,232,225,105,128,248,135,244,+ 232,225,105,128, 14, 54,244,232,225,105,128, 14, 56,245,244,232,+ 225,105,128, 14, 57,226,239,240,239,237,239,230,111,128, 49, 25,+ 99, 5,166, 28,166, 49,166, 58,166,107,166,129,225,242,239,110,+ 129, 1, 97,166, 37,228,239,244,225,227,227,229,238,116,128, 30,+ 103,229,228,233,236,236, 97,128, 1, 95,232,247, 97,131, 2, 89,+ 166, 70,166, 81,166,100,227,249,242,233,236,236,233, 99,128, 4,+ 217,228,233,229,242,229,243,233,243,227,249,242,233,236,236,233,+ 99,128, 4,219,232,239,239,107,128, 2, 90,233,242, 99, 2,166,+ 115,166,120,236,101,128, 36,226,245,237,230,236,229,120,128, 1,+ 93,239,237,237,225,225,227,227,229,238,116,128, 2, 25,228,239,+ 116, 2,166,150,166,159,225,227,227,229,238,116,128, 30, 97,226,+ 229,236,239,119,129, 30, 99,166,169,228,239,244,225,227,227,229,+ 238,116,128, 30,105,101, 9,166,201,166,217,166,252,167, 61,167,+ 164,167,191,167,216,168, 41,168, 68,225,231,245,236,236,226,229,+ 236,239,247,227,237, 98,128, 3, 60, 99, 2,166,223,166,245,239,+ 238,100,129, 32, 51,166,231,244,239,238,229,227,232,233,238,229,+ 243,101,128, 2,202,244,233,239,110,128, 0,167,229,110, 4,167,+ 7,167, 16,167, 30,167, 46,225,242,225,226,233, 99,128, 6, 51,+ 230,233,238,225,236,225,242,225,226,233, 99,128,254,178,233,238,+ 233,244,233,225,236,225,242,225,226,233, 99,128,254,179,237,229,+ 228,233,225,236,225,242,225,226,233, 99,128,254,180,231,239,108,+ 135, 5,182,167, 81,167, 95,167,100,167,109,167,124,167,140,167,+ 151, 49, 2,167, 87,167, 91, 51,128, 5,182,102,128, 5,182,178,+ 99,128, 5,182,232,229,226,242,229,119,128, 5,182,238,225,242,+ 242,239,247,232,229,226,242,229,119,128, 5,182,241,245,225,242,+ 244,229,242,232,229,226,242,229,119,128, 5,182,244,225,232,229,+ 226,242,229,119,128, 5,146,247,233,228,229,232,229,226,242,229,+ 119,128, 5,182,104, 2,167,170,167,181,225,242,237,229,238,233,+ 225,110,128, 5,125,233,242,225,231,225,238, 97,128, 48, 91,235,+ 225,244,225,235,225,238, 97,129, 48,187,167,204,232,225,236,230,+ 247,233,228,244,104,128,255,126,237,105, 2,167,223,168, 10,227,+ 239,236,239,110,131, 0, 59,167,237,167,246,168, 2,225,242,225,+ 226,233, 99,128, 6, 27,237,239,238,239,243,240,225,227,101,128,+ 255, 27,243,237,225,236,108,128,254, 84,246,239,233,227,229,228,+ 237,225,242,235,235,225,238, 97,129, 48,156,168, 29,232,225,236,+ 230,247,233,228,244,104,128,255,159,238,116, 2,168, 48,168, 58,+ 233,243,241,245,225,242,101,128, 51, 34,239,243,241,245,225,242,+ 101,128, 51, 35,246,229,110,142, 0, 55,168,102,168,111,168,121,+ 168,151,168,158,168,168,168,193,168,220,168,254,169, 10,169, 21,+ 169, 54,169, 62,169, 73,225,242,225,226,233, 99,128, 6,103,226,+ 229,238,231,225,236,105,128, 9,237,227,233,242,227,236,101,129,+ 36,102,168,132,233,238,246,229,242,243,229,243,225,238,243,243,+ 229,242,233,102,128, 39,144,228,229,246, 97,128, 9,109,229,233,+ 231,232,244,232,115,128, 33, 94,231,117, 2,168,175,168,184,234,+ 225,242,225,244,105,128, 10,237,242,237,245,235,232,105,128, 10,+ 109,232, 97, 2,168,200,168,211,227,235,225,242,225,226,233, 99,+ 128, 6,103,238,231,250,232,239,117,128, 48, 39,105, 2,168,226,+ 168,244,228,229,239,231,242,225,240,232,233,227,240,225,242,229,+ 110,128, 50, 38,238,230,229,242,233,239,114,128, 32,135,237,239,+ 238,239,243,240,225,227,101,128,255, 23,239,236,228,243,244,249,+ 236,101,128,247, 55,112, 2,169, 27,169, 34,225,242,229,110,128,+ 36,122,229,114, 2,169, 41,169, 47,233,239,100,128, 36,142,243,+ 233,225,110,128, 6,247,242,239,237,225,110,128, 33,118,243,245,+ 240,229,242,233,239,114,128, 32,119,116, 2,169, 79,169,117,229,+ 229,110, 2,169, 87,169, 96,227,233,242,227,236,101,128, 36,112,+ 112, 2,169,102,169,109,225,242,229,110,128, 36,132,229,242,233,+ 239,100,128, 36,152,232,225,105,128, 14, 87,230,244,232,249,240,+ 232,229,110,128, 0,173,104, 7,169,150,170,124,170,135,170,149,+ 171, 94,171,107,172, 15, 97, 6,169,164,169,175,169,185,169,196,+ 170, 83,170,108,225,242,237,229,238,233,225,110,128, 5,119,226,+ 229,238,231,225,236,105,128, 9,182,227,249,242,233,236,236,233,+ 99,128, 4, 72,100, 2,169,202,170, 42,228, 97, 4,169,213,169,+ 222,169,253,170, 11,225,242,225,226,233, 99,128, 6, 81,228,225,+ 237,237, 97, 2,169,232,169,241,225,242,225,226,233, 99,128,252,+ 97,244,225,238,225,242,225,226,233, 99,128,252, 94,230,225,244,+ 232,225,225,242,225,226,233, 99,128,252, 96,235,225,243,242, 97,+ 2,170, 21,170, 30,225,242,225,226,233, 99,128,252, 98,244,225,+ 238,225,242,225,226,233, 99,128,252, 95,101,132, 37,146,170, 54,+ 170, 61,170, 69,170, 78,228,225,242,107,128, 37,147,236,233,231,+ 232,116,128, 37,145,237,229,228,233,245,109,128, 37,146,246, 97,+ 128, 9, 54,231,117, 2,170, 90,170, 99,234,225,242,225,244,105,+ 128, 10,182,242,237,245,235,232,105,128, 10, 54,236,243,232,229,+ 236,229,244,232,229,226,242,229,119,128, 5,147,226,239,240,239,+ 237,239,230,111,128, 49, 21,227,232,225,227,249,242,233,236,236,+ 233, 99,128, 4, 73,101, 4,170,159,170,224,170,234,170,251,229,+ 110, 4,170,170,170,179,170,193,170,209,225,242,225,226,233, 99,+ 128, 6, 52,230,233,238,225,236,225,242,225,226,233, 99,128,254,+ 182,233,238,233,244,233,225,236,225,242,225,226,233, 99,128,254,+ 183,237,229,228,233,225,236,225,242,225,226,233, 99,128,254,184,+ 233,227,239,240,244,233, 99,128, 3,227,241,229,108,129, 32,170,+ 170,242,232,229,226,242,229,119,128, 32,170,246, 97,134, 5,176,+ 171, 12,171, 27,171, 41,171, 50,171, 65,171, 81, 49, 2,171, 18,+ 171, 23,177, 53,128, 5,176, 53,128, 5,176, 50, 2,171, 33,171,+ 37, 50,128, 5,176,101,128, 5,176,232,229,226,242,229,119,128,+ 5,176,238,225,242,242,239,247,232,229,226,242,229,119,128, 5,+ 176,241,245,225,242,244,229,242,232,229,226,242,229,119,128, 5,+ 176,247,233,228,229,232,229,226,242,229,119,128, 5,176,232,225,+ 227,249,242,233,236,236,233, 99,128, 4,187,105, 2,171,113,171,+ 124,237,225,227,239,240,244,233, 99,128, 3,237,110,131, 5,233,+ 171,134,171,217,171,226,100, 2,171,140,171,206,225,231,229,243,+ 104,130,251, 73,171,152,171,161,232,229,226,242,229,119,128,251,+ 73,115, 2,171,167,171,187,232,233,238,228,239,116,129,251, 44,+ 171,178,232,229,226,242,229,119,128,251, 44,233,238,228,239,116,+ 129,251, 45,171,197,232,229,226,242,229,119,128,251, 45,239,244,+ 232,229,226,242,229,119,128, 5,193,232,229,226,242,229,119,128,+ 5,233,115, 2,171,232,171,252,232,233,238,228,239,116,129,251,+ 42,171,243,232,229,226,242,229,119,128,251, 42,233,238,228,239,+ 116,129,251, 43,172, 6,232,229,226,242,229,119,128,251, 43,239,+ 239,107,128, 2,130,105, 8,172, 39,172, 83,172, 94,172,119,172,+ 149,172,157,172,170,173, 85,231,237, 97,131, 3,195,172, 51,172,+ 55,172, 63, 49,128, 3,194,230,233,238,225,108,128, 3,194,236,+ 245,238,225,244,229,243,249,237,226,239,236,231,242,229,229,107,+ 128, 3,242,232,233,242,225,231,225,238, 97,128, 48, 87,235,225,+ 244,225,235,225,238, 97,129, 48,183,172,107,232,225,236,230,247,+ 233,228,244,104,128,255,124,236,245,113, 2,172,127,172,136,232,+ 229,226,242,229,119,128, 5,189,236,229,230,244,232,229,226,242,+ 229,119,128, 5,189,237,233,236,225,114,128, 34, 60,238,228,239,+ 244,232,229,226,242,229,119,128, 5,194,239,115, 6,172,185,172,+ 220,172,252,173, 24,173, 38,173, 70, 97, 2,172,191,172,206,227,+ 233,242,227,236,229,235,239,242,229,225,110,128, 50,116,240,225,+ 242,229,238,235,239,242,229,225,110,128, 50, 20,227,105, 2,172,+ 227,172,239,229,245,227,235,239,242,229,225,110,128, 49,126,242,+ 227,236,229,235,239,242,229,225,110,128, 50,102,107, 2,173, 2,+ 173, 16,233,249,229,239,235,235,239,242,229,225,110,128, 49,122,+ 239,242,229,225,110,128, 49, 69,238,233,229,245,238,235,239,242,+ 229,225,110,128, 49,123,112, 2,173, 44,173, 57,225,242,229,238,+ 235,239,242,229,225,110,128, 50, 6,233,229,245,240,235,239,242,+ 229,225,110,128, 49,125,244,233,235,229,245,244,235,239,242,229,+ 225,110,128, 49,124,120,141, 0, 54,173,115,173,124,173,134,173,+ 164,173,171,173,196,173,223,174, 1,174, 13,174, 24,174, 57,174,+ 65,174, 76,225,242,225,226,233, 99,128, 6,102,226,229,238,231,+ 225,236,105,128, 9,236,227,233,242,227,236,101,129, 36,101,173,+ 145,233,238,246,229,242,243,229,243,225,238,243,243,229,242,233,+ 102,128, 39,143,228,229,246, 97,128, 9,108,231,117, 2,173,178,+ 173,187,234,225,242,225,244,105,128, 10,236,242,237,245,235,232,+ 105,128, 10,108,232, 97, 2,173,203,173,214,227,235,225,242,225,+ 226,233, 99,128, 6,102,238,231,250,232,239,117,128, 48, 38,105,+ 2,173,229,173,247,228,229,239,231,242,225,240,232,233,227,240,+ 225,242,229,110,128, 50, 37,238,230,229,242,233,239,114,128, 32,+ 134,237,239,238,239,243,240,225,227,101,128,255, 22,239,236,228,+ 243,244,249,236,101,128,247, 54,112, 2,174, 30,174, 37,225,242,+ 229,110,128, 36,121,229,114, 2,174, 44,174, 50,233,239,100,128,+ 36,141,243,233,225,110,128, 6,246,242,239,237,225,110,128, 33,+ 117,243,245,240,229,242,233,239,114,128, 32,118,116, 2,174, 82,+ 174,153,229,229,110, 2,174, 90,174,132, 99, 2,174, 96,174,104,+ 233,242,227,236,101,128, 36,111,245,242,242,229,238,227,249,228,+ 229,238,239,237,233,238,225,244,239,242,226,229,238,231,225,236,+ 105,128, 9,249,112, 2,174,138,174,145,225,242,229,110,128, 36,+ 131,229,242,233,239,100,128, 36,151,232,225,105,128, 14, 86,108,+ 2,174,165,174,185,225,243,104,129, 0, 47,174,173,237,239,238,+ 239,243,240,225,227,101,128,255, 15,239,238,103,129, 1,127,174,+ 193,228,239,244,225,227,227,229,238,116,128, 30,155,109, 2,174,+ 211,174,221,233,236,229,230,225,227,101,128, 38, 58,239,238,239,+ 243,240,225,227,101,128,255, 83,111, 6,174,246,175, 40,175, 51,+ 175, 76,175,121,175,132,102, 2,174,252,175, 10,240,225,243,245,+ 241,232,229,226,242,229,119,128, 5,195,116, 2,175, 16,175, 25,+ 232,249,240,232,229,110,128, 0,173,243,233,231,238,227,249,242,+ 233,236,236,233, 99,128, 4, 76,232,233,242,225,231,225,238, 97,+ 128, 48, 93,235,225,244,225,235,225,238, 97,129, 48,189,175, 64,+ 232,225,236,230,247,233,228,244,104,128,255,127,236,233,228,245,+ 115, 2,175, 86,175,103,236,239,238,231,239,246,229,242,236,225,+ 249,227,237, 98,128, 3, 56,243,232,239,242,244,239,246,229,242,+ 236,225,249,227,237, 98,128, 3, 55,242,245,243,233,244,232,225,+ 105,128, 14, 41,115, 3,175,140,175,150,175,158,225,236,225,244,+ 232,225,105,128, 14, 40,239,244,232,225,105,128, 14, 11,245,225,+ 244,232,225,105,128, 14, 42,240, 97, 3,175,176,175,196,175,228,+ 227,101,129, 0, 32,175,183,232,225,227,235,225,242,225,226,233,+ 99,128, 0, 32,228,101,129, 38, 96,175,203,243,245,233,116, 2,+ 175,212,175,220,226,236,225,227,107,128, 38, 96,247,232,233,244,+ 101,128, 38,100,242,229,110,128, 36,174,241,245,225,242,101, 11,+ 176, 6,176, 17,176, 31,176, 56,176, 73,176, 99,176,114,176,147,+ 176,174,176,230,176,245,226,229,236,239,247,227,237, 98,128, 3,+ 59, 99, 2,176, 23,176, 27, 99,128, 51,196,109,128, 51,157,228,+ 233,225,231,239,238,225,236,227,242,239,243,243,232,225,244,227,+ 232,230,233,236,108,128, 37,169,232,239,242,233,250,239,238,244,+ 225,236,230,233,236,108,128, 37,164,107, 2,176, 79,176, 83,103,+ 128, 51,143,109,129, 51,158,176, 89,227,225,240,233,244,225,108,+ 128, 51,206,108, 2,176,105,176,109,110,128, 51,209,239,103,128,+ 51,210,109, 4,176,124,176,128,176,133,176,137,103,128, 51,142,+ 233,108,128, 51,213,109,128, 51,156,243,241,245,225,242,229,100,+ 128, 51,161,239,242,244,232,239,231,239,238,225,236,227,242,239,+ 243,243,232,225,244,227,232,230,233,236,108,128, 37,166,245,240,+ 240,229,114, 2,176,184,176,207,236,229,230,244,244,239,236,239,+ 247,229,242,242,233,231,232,244,230,233,236,108,128, 37,167,242,+ 233,231,232,244,244,239,236,239,247,229,242,236,229,230,244,230,+ 233,236,108,128, 37,168,246,229,242,244,233,227,225,236,230,233,+ 236,108,128, 37,165,247,232,233,244,229,247,233,244,232,243,237,+ 225,236,236,226,236,225,227,107,128, 37,163,242,243,241,245,225,+ 242,101,128, 51,219,115, 2,177, 27,177,197, 97, 4,177, 37,177,+ 47,177, 54,177, 65,226,229,238,231,225,236,105,128, 9,183,228,+ 229,246, 97,128, 9, 55,231,245,234,225,242,225,244,105,128, 10,+ 183,238,103, 8,177, 84,177, 98,177,112,177,126,177,141,177,155,+ 177,169,177,182,227,233,229,245,227,235,239,242,229,225,110,128,+ 49, 73,232,233,229,245,232,235,239,242,229,225,110,128, 49,133,+ 233,229,245,238,231,235,239,242,229,225,110,128, 49,128,235,233,+ 249,229,239,235,235,239,242,229,225,110,128, 49, 50,238,233,229,+ 245,238,235,239,242,229,225,110,128, 49,101,240,233,229,245,240,+ 235,239,242,229,225,110,128, 49, 67,243,233,239,243,235,239,242,+ 229,225,110,128, 49, 70,244,233,235,229,245,244,235,239,242,229,+ 225,110,128, 49, 56,245,240,229,242,233,239,114,128,246,242,116,+ 2,177,213,177,236,229,242,236,233,238,103,129, 0,163,177,224,+ 237,239,238,239,243,240,225,227,101,128,255,225,242,239,235,101,+ 2,177,245,178, 6,236,239,238,231,239,246,229,242,236,225,249,+ 227,237, 98,128, 3, 54,243,232,239,242,244,239,246,229,242,236,+ 225,249,227,237, 98,128, 3, 53,117, 7,178, 40,178, 72,178, 94,+ 178,105,178,146,178,156,178,160,226,243,229,116,130, 34,130,178,+ 51,178, 62,238,239,244,229,241,245,225,108,128, 34,138,239,242,+ 229,241,245,225,108,128, 34,134, 99, 2,178, 78,178, 86,227,229,+ 229,228,115,128, 34,123,232,244,232,225,116,128, 34, 11,232,233,+ 242,225,231,225,238, 97,128, 48, 89,107, 2,178,111,178,135,225,+ 244,225,235,225,238, 97,129, 48,185,178,123,232,225,236,230,247,+ 233,228,244,104,128,255,125,245,238,225,242,225,226,233, 99,128,+ 6, 82,237,237,225,244,233,239,110,128, 34, 17,110,128, 38, 60,+ 240,229,242,243,229,116,130, 34,131,178,173,178,184,238,239,244,+ 229,241,245,225,108,128, 34,139,239,242,229,241,245,225,108,128,+ 34,135,246,243,241,245,225,242,101,128, 51,220,249,239,245,247,+ 225,229,242,225,243,241,245,225,242,101,128, 51,124,116,144, 0,+ 116,179, 1,180, 10,180, 31,180,174,180,214,183, 6,186,144,187,+ 219,187,231,187,243,189, 20,189, 45,189,131,190, 55,190,239,191,+ 73, 97, 10,179, 23,179, 33,179, 54,179, 61,179, 86,179,164,179,+ 181,179,206,179,220,179,224,226,229,238,231,225,236,105,128, 9,+ 164,227,107, 2,179, 40,179, 47,228,239,247,110,128, 34,164,236,+ 229,230,116,128, 34,163,228,229,246, 97,128, 9, 36,231,117, 2,+ 179, 68,179, 77,234,225,242,225,244,105,128, 10,164,242,237,245,+ 235,232,105,128, 10, 36,104, 4,179, 96,179,105,179,119,179,149,+ 225,242,225,226,233, 99,128, 6, 55,230,233,238,225,236,225,242,+ 225,226,233, 99,128,254,194,105, 2,179,125,179,140,238,233,244,+ 233,225,236,225,242,225,226,233, 99,128,254,195,242,225,231,225,+ 238, 97,128, 48, 95,237,229,228,233,225,236,225,242,225,226,233,+ 99,128,254,196,233,243,249,239,245,229,242,225,243,241,245,225,+ 242,101,128, 51,125,235,225,244,225,235,225,238, 97,129, 48,191,+ 179,194,232,225,236,230,247,233,228,244,104,128,255,128,244,247,+ 229,229,236,225,242,225,226,233, 99,128, 6, 64,117,128, 3,196,+ 118,130, 5,234,179,232,180, 1,228,225,231,229,115,129,251, 74,+ 179,242,104,129,251, 74,179,248,232,229,226,242,229,119,128,251,+ 74,232,229,226,242,229,119,128, 5,234, 98, 2,180, 16,180, 21,+ 225,114,128, 1,103,239,240,239,237,239,230,111,128, 49, 10, 99,+ 6,180, 45,180, 52,180, 59,180, 68,180,134,180,161,225,242,239,+ 110,128, 1,101,227,245,242,108,128, 2,168,229,228,233,236,236,+ 97,128, 1, 99,232,229,104, 4,180, 80,180, 89,180,103,180,119,+ 225,242,225,226,233, 99,128, 6,134,230,233,238,225,236,225,242,+ 225,226,233, 99,128,251,123,233,238,233,244,233,225,236,225,242,+ 225,226,233, 99,128,251,124,237,229,228,233,225,236,225,242,225,+ 226,233, 99,128,251,125,233,242, 99, 2,180,142,180,147,236,101,+ 128, 36,227,245,237,230,236,229,248,226,229,236,239,119,128, 30,+ 113,239,237,237,225,225,227,227,229,238,116,128, 1, 99,100, 2,+ 180,180,180,190,233,229,242,229,243,233,115,128, 30,151,239,116,+ 2,180,197,180,206,225,227,227,229,238,116,128, 30,107,226,229,+ 236,239,119,128, 30,109,101, 9,180,234,180,245,181, 9,182, 19,+ 182, 44,182,108,182,175,182,180,182,232,227,249,242,233,236,236,+ 233, 99,128, 4, 66,228,229,243,227,229,238,228,229,242,227,249,+ 242,233,236,236,233, 99,128, 4,173,104, 7,181, 25,181, 34,181,+ 48,181, 88,181,118,181,159,182, 1,225,242,225,226,233, 99,128,+ 6, 42,230,233,238,225,236,225,242,225,226,233, 99,128,254,150,+ 232,225,232,105, 2,181, 57,181, 72,238,233,244,233,225,236,225,+ 242,225,226,233, 99,128,252,162,243,239,236,225,244,229,228,225,+ 242,225,226,233, 99,128,252, 12,105, 2,181, 94,181,109,238,233,+ 244,233,225,236,225,242,225,226,233, 99,128,254,151,242,225,231,+ 225,238, 97,128, 48,102,234,229,229,237,105, 2,181,128,181,143,+ 238,233,244,233,225,236,225,242,225,226,233, 99,128,252,161,243,+ 239,236,225,244,229,228,225,242,225,226,233, 99,128,252, 11,109,+ 2,181,165,181,199,225,242,226,245,244, 97, 2,181,176,181,185,+ 225,242,225,226,233, 99,128, 6, 41,230,233,238,225,236,225,242,+ 225,226,233, 99,128,254,148,101, 2,181,205,181,218,228,233,225,+ 236,225,242,225,226,233, 99,128,254,152,229,237,105, 2,181,226,+ 181,241,238,233,244,233,225,236,225,242,225,226,233, 99,128,252,+ 164,243,239,236,225,244,229,228,225,242,225,226,233, 99,128,252,+ 14,238,239,239,238,230,233,238,225,236,225,242,225,226,233, 99,+ 128,252,115,235,225,244,225,235,225,238, 97,129, 48,198,182, 32,+ 232,225,236,230,247,233,228,244,104,128,255,131,108, 2,182, 50,+ 182, 69,229,240,232,239,238,101,129, 33, 33,182, 61,226,236,225,+ 227,107,128, 38, 14,233,243,232, 97, 2,182, 78,182, 93,231,229,+ 228,239,236,225,232,229,226,242,229,119,128, 5,160,241,229,244,+ 225,238,225,232,229,226,242,229,119,128, 5,169,110, 4,182,118,+ 182,127,182,146,182,167,227,233,242,227,236,101,128, 36,105,233,+ 228,229,239,231,242,225,240,232,233,227,240,225,242,229,110,128,+ 50, 41,112, 2,182,152,182,159,225,242,229,110,128, 36,125,229,+ 242,233,239,100,128, 36,145,242,239,237,225,110,128, 33,121,243,+ 104,128, 2,167,116,131, 5,216,182,190,182,210,182,219,228,225,+ 231,229,243,104,129,251, 56,182,201,232,229,226,242,229,119,128,+ 251, 56,232,229,226,242,229,119,128, 5,216,243,229,227,249,242,+ 233,236,236,233, 99,128, 4,181,246,233,114, 2,182,240,182,249,+ 232,229,226,242,229,119,128, 5,155,236,229,230,244,232,229,226,+ 242,229,119,128, 5,155,104, 6,183, 20,183,172,184, 38,184,170,+ 185, 77,186,134, 97, 5,183, 32,183, 42,183, 49,183, 74,183,103,+ 226,229,238,231,225,236,105,128, 9,165,228,229,246, 97,128, 9,+ 37,231,117, 2,183, 56,183, 65,234,225,242,225,244,105,128, 10,+ 165,242,237,245,235,232,105,128, 10, 37,108, 2,183, 80,183, 89,+ 225,242,225,226,233, 99,128, 6, 48,230,233,238,225,236,225,242,+ 225,226,233, 99,128,254,172,238,244,232,225,235,232,225,116, 3,+ 183,118,183,149,183,156,236,239,119, 2,183,126,183,137,236,229,+ 230,244,244,232,225,105,128,248,152,242,233,231,232,244,244,232,+ 225,105,128,248,151,244,232,225,105,128, 14, 76,245,240,240,229,+ 242,236,229,230,244,244,232,225,105,128,248,150,101, 3,183,180,+ 183,244,184, 11,104, 4,183,190,183,199,183,213,183,229,225,242,+ 225,226,233, 99,128, 6, 43,230,233,238,225,236,225,242,225,226,+ 233, 99,128,254,154,233,238,233,244,233,225,236,225,242,225,226,+ 233, 99,128,254,155,237,229,228,233,225,236,225,242,225,226,233,+ 99,128,254,156,242,101, 2,183,251,184, 4,229,248,233,243,244,+ 115,128, 34, 3,230,239,242,101,128, 34, 52,244, 97,130, 3,184,+ 184, 20,184, 24, 49,128, 3,209,243,249,237,226,239,236,231,242,+ 229,229,107,128, 3,209,105, 2,184, 44,184,130,229,245,244,104,+ 4,184, 57,184, 92,184,107,184,116, 97, 2,184, 63,184, 78,227,+ 233,242,227,236,229,235,239,242,229,225,110,128, 50,121,240,225,+ 242,229,238,235,239,242,229,225,110,128, 50, 25,227,233,242,227,+ 236,229,235,239,242,229,225,110,128, 50,107,235,239,242,229,225,+ 110,128, 49, 76,240,225,242,229,238,235,239,242,229,225,110,128,+ 50, 11,242,244,229,229,110, 2,184,140,184,149,227,233,242,227,+ 236,101,128, 36,108,112, 2,184,155,184,162,225,242,229,110,128,+ 36,128,229,242,233,239,100,128, 36,148,111, 6,184,184,184,201,+ 184,206,184,220,184,225,185, 22,238,225,238,231,237,239,238,244,+ 232,239,244,232,225,105,128, 14, 17,239,107,128, 1,173,240,232,+ 245,244,232,225,239,244,232,225,105,128, 14, 18,242,110,128, 0,+ 254,244,104, 3,184,234,185, 2,185, 12, 97, 2,184,240,184,250,+ 232,225,238,244,232,225,105,128, 14, 23,238,244,232,225,105,128,+ 14, 16,239,238,231,244,232,225,105,128, 14, 24,245,238,231,244,+ 232,225,105,128, 14, 22,245,243,225,238,100, 2,185, 32,185, 43,+ 227,249,242,233,236,236,233, 99,128, 4,130,243,243,229,240,225,+ 242,225,244,239,114, 2,185, 58,185, 67,225,242,225,226,233, 99,+ 128, 6,108,240,229,242,243,233,225,110,128, 6,108,242,229,101,+ 144, 0, 51,185,115,185,124,185,134,185,164,185,171,185,181,185,+ 206,185,233,186, 11,186, 23,186, 42,186, 53,186, 86,186,108,186,+ 116,186,127,225,242,225,226,233, 99,128, 6, 99,226,229,238,231,+ 225,236,105,128, 9,233,227,233,242,227,236,101,129, 36, 98,185,+ 145,233,238,246,229,242,243,229,243,225,238,243,243,229,242,233,+ 102,128, 39,140,228,229,246, 97,128, 9,105,229,233,231,232,244,+ 232,115,128, 33, 92,231,117, 2,185,188,185,197,234,225,242,225,+ 244,105,128, 10,233,242,237,245,235,232,105,128, 10,105,232, 97,+ 2,185,213,185,224,227,235,225,242,225,226,233, 99,128, 6, 99,+ 238,231,250,232,239,117,128, 48, 35,105, 2,185,239,186, 1,228,+ 229,239,231,242,225,240,232,233,227,240,225,242,229,110,128, 50,+ 34,238,230,229,242,233,239,114,128, 32,131,237,239,238,239,243,+ 240,225,227,101,128,255, 19,238,245,237,229,242,225,244,239,242,+ 226,229,238,231,225,236,105,128, 9,246,239,236,228,243,244,249,+ 236,101,128,247, 51,112, 2,186, 59,186, 66,225,242,229,110,128,+ 36,118,229,114, 2,186, 73,186, 79,233,239,100,128, 36,138,243,+ 233,225,110,128, 6,243,241,245,225,242,244,229,242,115,129, 0,+ 190,186, 99,229,237,228,225,243,104,128,246,222,242,239,237,225,+ 110,128, 33,114,243,245,240,229,242,233,239,114,128, 0,179,244,+ 232,225,105,128, 14, 83,250,243,241,245,225,242,101,128, 51,148,+ 105, 7,186,160,186,171,187, 30,187,128,187,140,187,189,187,206,+ 232,233,242,225,231,225,238, 97,128, 48, 97,107, 2,186,177,186,+ 201,225,244,225,235,225,238, 97,129, 48,193,186,189,232,225,236,+ 230,247,233,228,244,104,128,255,129,229,245,116, 4,186,213,186,+ 248,187, 7,187, 16, 97, 2,186,219,186,234,227,233,242,227,236,+ 229,235,239,242,229,225,110,128, 50,112,240,225,242,229,238,235,+ 239,242,229,225,110,128, 50, 16,227,233,242,227,236,229,235,239,+ 242,229,225,110,128, 50, 98,235,239,242,229,225,110,128, 49, 55,+ 240,225,242,229,238,235,239,242,229,225,110,128, 50, 2,236,228,+ 101,133, 2,220,187, 46,187, 57,187, 74,187, 86,187,114,226,229,+ 236,239,247,227,237, 98,128, 3, 48, 99, 2,187, 63,187, 68,237,+ 98,128, 3, 3,239,237, 98,128, 3, 3,228,239,245,226,236,229,+ 227,237, 98,128, 3, 96,111, 2,187, 92,187,102,240,229,242,225,+ 244,239,114,128, 34, 60,246,229,242,236,225,249,227,237, 98,128,+ 3, 52,246,229,242,244,233,227,225,236,227,237, 98,128, 3, 62,+ 237,229,243,227,233,242,227,236,101,128, 34,151,112, 2,187,146,+ 187,176,229,232, 97, 2,187,154,187,163,232,229,226,242,229,119,+ 128, 5,150,236,229,230,244,232,229,226,242,229,119,128, 5,150,+ 240,233,231,245,242,237,245,235,232,105,128, 10,112,244,236,239,+ 227,249,242,233,236,236,233,227,227,237, 98,128, 4,131,247,238,+ 225,242,237,229,238,233,225,110,128, 5,127,236,233,238,229,226,+ 229,236,239,119,128, 30,111,237,239,238,239,243,240,225,227,101,+ 128,255, 84,111, 7,188, 3,188, 14,188, 25,188, 50,188,170,188,+ 182,189, 10,225,242,237,229,238,233,225,110,128, 5,105,232,233,+ 242,225,231,225,238, 97,128, 48,104,235,225,244,225,235,225,238,+ 97,129, 48,200,188, 38,232,225,236,230,247,233,228,244,104,128,+ 255,132,110, 3,188, 58,188,156,188,161,101, 4,188, 68,188,137,+ 188,144,188,150,226,225,114, 4,188, 80,188,109,188,119,188,128,+ 229,248,244,242, 97, 2,188, 90,188,100,232,233,231,232,237,239,+ 100,128, 2,229,236,239,247,237,239,100,128, 2,233,232,233,231,+ 232,237,239,100,128, 2,230,236,239,247,237,239,100,128, 2,232,+ 237,233,228,237,239,100,128, 2,231,230,233,246,101,128, 1,189,+ 243,233,120,128, 1,133,244,247,111,128, 1,168,239,115,128, 3,+ 132,243,241,245,225,242,101,128, 51, 39,240,225,244,225,235,244,+ 232,225,105,128, 14, 15,242,244,239,233,243,229,243,232,229,236,+ 236,226,242,225,227,235,229,116, 2,188,205,188,235,236,229,230,+ 116,130, 48, 20,188,216,188,224,243,237,225,236,108,128,254, 93,+ 246,229,242,244,233,227,225,108,128,254, 57,242,233,231,232,116,+ 130, 48, 21,188,247,188,255,243,237,225,236,108,128,254, 94,246,+ 229,242,244,233,227,225,108,128,254, 58,244,225,239,244,232,225,+ 105,128, 14, 21,240, 97, 2,189, 27,189, 39,236,225,244,225,236,+ 232,239,239,107,128, 1,171,242,229,110,128, 36,175,114, 3,189,+ 53,189, 84,189, 99,225,228,229,237,225,242,107,129, 33, 34,189,+ 65,115, 2,189, 71,189, 77,225,238,115,128,248,234,229,242,233,+ 102,128,246,219,229,244,242,239,230,236,229,248,232,239,239,107,+ 128, 2,136,233,225,103, 4,189,111,189,116,189,121,189,126,228,+ 110,128, 37,188,236,102,128, 37,196,242,116,128, 37,186,245,112,+ 128, 37,178,115,132, 2,166,189,143,189,182,190, 32,190, 45,225,+ 228,105,130, 5,230,189,153,189,173,228,225,231,229,243,104,129,+ 251, 70,189,164,232,229,226,242,229,119,128,251, 70,232,229,226,+ 242,229,119,128, 5,230,101, 2,189,188,189,199,227,249,242,233,+ 236,236,233, 99,128, 4, 70,242,101,134, 5,181,189,216,189,230,+ 189,235,189,244,190, 3,190, 19, 49, 2,189,222,189,226, 50,128,+ 5,181,101,128, 5,181,178, 98,128, 5,181,232,229,226,242,229,+ 119,128, 5,181,238,225,242,242,239,247,232,229,226,242,229,119,+ 128, 5,181,241,245,225,242,244,229,242,232,229,226,242,229,119,+ 128, 5,181,247,233,228,229,232,229,226,242,229,119,128, 5,181,+ 232,229,227,249,242,233,236,236,233, 99,128, 4, 91,245,240,229,+ 242,233,239,114,128,246,243,116, 4,190, 65,190,115,190,180,190,+ 231, 97, 3,190, 73,190, 83,190, 90,226,229,238,231,225,236,105,+ 128, 9,159,228,229,246, 97,128, 9, 31,231,117, 2,190, 97,190,+ 106,234,225,242,225,244,105,128, 10,159,242,237,245,235,232,105,+ 128, 10, 31,229,104, 4,190,126,190,135,190,149,190,165,225,242,+ 225,226,233, 99,128, 6,121,230,233,238,225,236,225,242,225,226,+ 233, 99,128,251,103,233,238,233,244,233,225,236,225,242,225,226,+ 233, 99,128,251,104,237,229,228,233,225,236,225,242,225,226,233,+ 99,128,251,105,232, 97, 3,190,189,190,199,190,206,226,229,238,+ 231,225,236,105,128, 9,160,228,229,246, 97,128, 9, 32,231,117,+ 2,190,213,190,222,234,225,242,225,244,105,128, 10,160,242,237,+ 245,235,232,105,128, 10, 32,245,242,238,229,100,128, 2,135,117,+ 3,190,247,191, 2,191, 27,232,233,242,225,231,225,238, 97,128,+ 48,100,235,225,244,225,235,225,238, 97,129, 48,196,191, 15,232,+ 225,236,230,247,233,228,244,104,128,255,130,243,237,225,236,108,+ 2,191, 37,191, 48,232,233,242,225,231,225,238, 97,128, 48, 99,+ 235,225,244,225,235,225,238, 97,129, 48,195,191, 61,232,225,236,+ 230,247,233,228,244,104,128,255,111,119, 2,191, 79,191,184,101,+ 2,191, 85,191,133,236,246,101, 3,191, 95,191,104,191,125,227,+ 233,242,227,236,101,128, 36,107,112, 2,191,110,191,117,225,242,+ 229,110,128, 36,127,229,242,233,239,100,128, 36,147,242,239,237,+ 225,110,128, 33,123,238,244,121, 3,191,143,191,152,191,163,227,+ 233,242,227,236,101,128, 36,115,232,225,238,231,250,232,239,117,+ 128, 83, 68,112, 2,191,169,191,176,225,242,229,110,128, 36,135,+ 229,242,233,239,100,128, 36,155,111,142, 0, 50,191,216,191,225,+ 191,235,192, 9,192, 61,192, 86,192,113,192,147,192,159,192,178,+ 192,189,192,222,192,230,192,254,225,242,225,226,233, 99,128, 6,+ 98,226,229,238,231,225,236,105,128, 9,232,227,233,242,227,236,+ 101,129, 36, 97,191,246,233,238,246,229,242,243,229,243,225,238,+ 243,243,229,242,233,102,128, 39,139,100, 2,192, 15,192, 21,229,+ 246, 97,128, 9,104,239,116, 2,192, 28,192, 39,229,238,236,229,+ 225,228,229,114,128, 32, 37,236,229,225,228,229,114,129, 32, 37,+ 192, 50,246,229,242,244,233,227,225,108,128,254, 48,231,117, 2,+ 192, 68,192, 77,234,225,242,225,244,105,128, 10,232,242,237,245,+ 235,232,105,128, 10,104,232, 97, 2,192, 93,192,104,227,235,225,+ 242,225,226,233, 99,128, 6, 98,238,231,250,232,239,117,128, 48,+ 34,105, 2,192,119,192,137,228,229,239,231,242,225,240,232,233,+ 227,240,225,242,229,110,128, 50, 33,238,230,229,242,233,239,114,+ 128, 32,130,237,239,238,239,243,240,225,227,101,128,255, 18,238,+ 245,237,229,242,225,244,239,242,226,229,238,231,225,236,105,128,+ 9,245,239,236,228,243,244,249,236,101,128,247, 50,112, 2,192,+ 195,192,202,225,242,229,110,128, 36,117,229,114, 2,192,209,192,+ 215,233,239,100,128, 36,137,243,233,225,110,128, 6,242,242,239,+ 237,225,110,128, 33,113,115, 2,192,236,192,244,244,242,239,235,+ 101,128, 1,187,245,240,229,242,233,239,114,128, 0,178,244,104,+ 2,193, 5,193, 10,225,105,128, 14, 82,233,242,228,115,128, 33,+ 84,117,145, 0,117,193, 55,193, 63,193,104,193,161,194, 43,194,+ 80,194,203,194,219,195, 14,195, 84,195,165,195,174,196, 37,196,+ 61,196,169,196,197,197, 55,225,227,245,244,101,128, 0,250, 98,+ 4,193, 73,193, 78,193, 87,193, 97,225,114,128, 2,137,229,238,+ 231,225,236,105,128, 9,137,239,240,239,237,239,230,111,128, 49,+ 40,242,229,246,101,128, 1,109, 99, 3,193,112,193,119,193,151,+ 225,242,239,110,128, 1,212,233,242, 99, 2,193,127,193,132,236,+ 101,128, 36,228,245,237,230,236,229,120,129, 0,251,193,143,226,+ 229,236,239,119,128, 30,119,249,242,233,236,236,233, 99,128, 4,+ 67,100, 5,193,173,193,184,193,207,193,213,194, 33,225,244,244,+ 225,228,229,246, 97,128, 9, 81,226,108, 2,193,191,193,199,225,+ 227,245,244,101,128, 1,113,231,242,225,246,101,128, 2, 21,229,+ 246, 97,128, 9, 9,233,229,242,229,243,233,115,133, 0,252,193,+ 233,193,241,193,249,194, 16,194, 24,225,227,245,244,101,128, 1,+ 216,226,229,236,239,119,128, 30,115, 99, 2,193,255,194, 6,225,+ 242,239,110,128, 1,218,249,242,233,236,236,233, 99,128, 4,241,+ 231,242,225,246,101,128, 1,220,237,225,227,242,239,110,128, 1,+ 214,239,244,226,229,236,239,119,128, 30,229,103, 2,194, 49,194,+ 56,242,225,246,101,128, 0,249,117, 2,194, 62,194, 71,234,225,+ 242,225,244,105,128, 10,137,242,237,245,235,232,105,128, 10, 9,+ 104, 3,194, 88,194, 98,194,176,233,242,225,231,225,238, 97,128,+ 48, 70,111, 2,194,104,194,114,239,235,225,226,239,246,101,128,+ 30,231,242,110,133, 1,176,194,129,194,137,194,148,194,156,194,+ 168,225,227,245,244,101,128, 30,233,228,239,244,226,229,236,239,+ 119,128, 30,241,231,242,225,246,101,128, 30,235,232,239,239,235,+ 225,226,239,246,101,128, 30,237,244,233,236,228,101,128, 30,239,+ 245,238,231,225,242,245,237,236,225,245,116,129, 1,113,194,192,+ 227,249,242,233,236,236,233, 99,128, 4,243,233,238,246,229,242,+ 244,229,228,226,242,229,246,101,128, 2, 23,107, 3,194,227,194,+ 251,195, 6,225,244,225,235,225,238, 97,129, 48,166,194,239,232,+ 225,236,230,247,233,228,244,104,128,255,115,227,249,242,233,236,+ 236,233, 99,128, 4,121,239,242,229,225,110,128, 49, 92,109, 2,+ 195, 20,195, 73, 97, 2,195, 26,195, 59,227,242,239,110,130, 1,+ 107,195, 37,195, 48,227,249,242,233,236,236,233, 99,128, 4,239,+ 228,233,229,242,229,243,233,115,128, 30,123,244,242,225,231,245,+ 242,237,245,235,232,105,128, 10, 65,239,238,239,243,240,225,227,+ 101,128,255, 85,110, 2,195, 90,195,145,228,229,242,243,227,239,+ 242,101,132, 0, 95,195,109,195,115,195,127,195,138,228,226,108,+ 128, 32, 23,237,239,238,239,243,240,225,227,101,128,255, 63,246,+ 229,242,244,233,227,225,108,128,254, 51,247,225,246,121,128,254,+ 79,105, 2,195,151,195,156,239,110,128, 34, 42,246,229,242,243,+ 225,108,128, 34, 0,239,231,239,238,229,107,128, 1,115,112, 5,+ 195,186,195,193,195,201,195,216,196, 11,225,242,229,110,128, 36,+ 176,226,236,239,227,107,128, 37,128,240,229,242,228,239,244,232,+ 229,226,242,229,119,128, 5,196,243,233,236,239,110,131, 3,197,+ 195,230,195,251,196, 3,228,233,229,242,229,243,233,115,129, 3,+ 203,195,243,244,239,238,239,115,128, 3,176,236,225,244,233,110,+ 128, 2,138,244,239,238,239,115,128, 3,205,244,225,227,107, 2,+ 196, 20,196, 31,226,229,236,239,247,227,237, 98,128, 3, 29,237,+ 239,100,128, 2,212,114, 2,196, 43,196, 55,225,231,245,242,237,+ 245,235,232,105,128, 10,115,233,238,103,128, 1,111,115, 3,196,+ 69,196, 84,196,129,232,239,242,244,227,249,242,233,236,236,233,+ 99,128, 4, 94,237,225,236,108, 2,196, 93,196,104,232,233,242,+ 225,231,225,238, 97,128, 48, 69,235,225,244,225,235,225,238, 97,+ 129, 48,165,196,117,232,225,236,230,247,233,228,244,104,128,255,+ 105,244,242,225,233,231,232,116, 2,196,141,196,152,227,249,242,+ 233,236,236,233, 99,128, 4,175,243,244,242,239,235,229,227,249,+ 242,233,236,236,233, 99,128, 4,177,244,233,236,228,101,130, 1,+ 105,196,181,196,189,225,227,245,244,101,128, 30,121,226,229,236,+ 239,119,128, 30,117,117, 5,196,209,196,219,196,226,196,251,197,+ 11,226,229,238,231,225,236,105,128, 9,138,228,229,246, 97,128,+ 9, 10,231,117, 2,196,233,196,242,234,225,242,225,244,105,128,+ 10,138,242,237,245,235,232,105,128, 10, 10,237,225,244,242,225,+ 231,245,242,237,245,235,232,105,128, 10, 66,246,239,247,229,236,+ 243,233,231,110, 3,197, 27,197, 37,197, 44,226,229,238,231,225,+ 236,105,128, 9,194,228,229,246, 97,128, 9, 66,231,245,234,225,+ 242,225,244,105,128, 10,194,246,239,247,229,236,243,233,231,110,+ 3,197, 71,197, 81,197, 88,226,229,238,231,225,236,105,128, 9,+ 193,228,229,246, 97,128, 9, 65,231,245,234,225,242,225,244,105,+ 128, 10,193,118,139, 0,118,197,125,198, 17,198, 26,198, 37,198,+ 222,198,229,199, 71,199, 83,199,183,199,191,199,212, 97, 4,197,+ 135,197,142,197,167,197,178,228,229,246, 97,128, 9, 53,231,117,+ 2,197,149,197,158,234,225,242,225,244,105,128, 10,181,242,237,+ 245,235,232,105,128, 10, 53,235,225,244,225,235,225,238, 97,128,+ 48,247,118,132, 5,213,197,190,197,217,197,249,198, 5,228,225,+ 231,229,243,104,130,251, 53,197,203,197,208,182, 53,128,251, 53,+ 232,229,226,242,229,119,128,251, 53,104, 2,197,223,197,231,229,+ 226,242,229,119,128, 5,213,239,236,225,109,129,251, 75,197,240,+ 232,229,226,242,229,119,128,251, 75,246,225,246,232,229,226,242,+ 229,119,128, 5,240,249,239,228,232,229,226,242,229,119,128, 5,+ 241,227,233,242,227,236,101,128, 36,229,228,239,244,226,229,236,+ 239,119,128, 30,127,101, 6,198, 51,198, 62,198,126,198,137,198,+ 143,198,210,227,249,242,233,236,236,233, 99,128, 4, 50,104, 4,+ 198, 72,198, 81,198, 95,198,111,225,242,225,226,233, 99,128, 6,+ 164,230,233,238,225,236,225,242,225,226,233, 99,128,251,107,233,+ 238,233,244,233,225,236,225,242,225,226,233, 99,128,251,108,237,+ 229,228,233,225,236,225,242,225,226,233, 99,128,251,109,235,225,+ 244,225,235,225,238, 97,128, 48,249,238,245,115,128, 38, 64,242,+ 244,233,227,225,108, 2,198,154,198,160,226,225,114,128, 0,124,+ 236,233,238,101, 4,198,173,198,184,198,195,198,204,225,226,239,+ 246,229,227,237, 98,128, 3, 13,226,229,236,239,247,227,237, 98,+ 128, 3, 41,236,239,247,237,239,100,128, 2,204,237,239,100,128,+ 2,200,247,225,242,237,229,238,233,225,110,128, 5,126,232,239,+ 239,107,128, 2,139,105, 3,198,237,198,248,199, 31,235,225,244,+ 225,235,225,238, 97,128, 48,248,242,225,237, 97, 3,199, 3,199,+ 13,199, 20,226,229,238,231,225,236,105,128, 9,205,228,229,246,+ 97,128, 9, 77,231,245,234,225,242,225,244,105,128, 10,205,243,+ 225,242,231, 97, 3,199, 43,199, 53,199, 60,226,229,238,231,225,+ 236,105,128, 9,131,228,229,246, 97,128, 9, 3,231,245,234,225,+ 242,225,244,105,128, 10,131,237,239,238,239,243,240,225,227,101,+ 128,255, 86,111, 3,199, 91,199,102,199,172,225,242,237,229,238,+ 233,225,110,128, 5,120,233,227,229,100, 2,199,111,199,147,233,+ 244,229,242,225,244,233,239,110, 2,199,125,199,136,232,233,242,+ 225,231,225,238, 97,128, 48,158,235,225,244,225,235,225,238, 97,+ 128, 48,254,237,225,242,235,235,225,238, 97,129, 48,155,199,160,+ 232,225,236,230,247,233,228,244,104,128,255,158,235,225,244,225,+ 235,225,238, 97,128, 48,250,240,225,242,229,110,128, 36,177,116,+ 2,199,197,199,204,233,236,228,101,128, 30,125,245,242,238,229,+ 100,128, 2,140,117, 2,199,218,199,229,232,233,242,225,231,225,+ 238, 97,128, 48,148,235,225,244,225,235,225,238, 97,128, 48,244,+ 119,143, 0,119,200, 18,200,251,201, 5,201, 28,201, 68,201,135,+ 201,143,203,114,203,155,203,167,203,242,203,250,204, 1,204, 12,+ 204, 21, 97, 8,200, 36,200, 43,200, 53,200, 64,200,102,200,134,+ 200,146,200,182,227,245,244,101,128, 30,131,229,235,239,242,229,+ 225,110,128, 49, 89,232,233,242,225,231,225,238, 97,128, 48,143,+ 107, 2,200, 70,200, 94,225,244,225,235,225,238, 97,129, 48,239,+ 200, 82,232,225,236,230,247,233,228,244,104,128,255,156,239,242,+ 229,225,110,128, 49, 88,243,237,225,236,108, 2,200,112,200,123,+ 232,233,242,225,231,225,238, 97,128, 48,142,235,225,244,225,235,+ 225,238, 97,128, 48,238,244,244,239,243,241,245,225,242,101,128,+ 51, 87,118, 2,200,152,200,160,229,228,225,243,104,128, 48, 28,+ 249,245,238,228,229,242,243,227,239,242,229,246,229,242,244,233,+ 227,225,108,128,254, 52,119, 3,200,190,200,199,200,213,225,242,+ 225,226,233, 99,128, 6, 72,230,233,238,225,236,225,242,225,226,+ 233, 99,128,254,238,232,225,237,250,225,225,226,239,246,101, 2,+ 200,228,200,237,225,242,225,226,233, 99,128, 6, 36,230,233,238,+ 225,236,225,242,225,226,233, 99,128,254,134,226,243,241,245,225,+ 242,101,128, 51,221,227,233,242, 99, 2,201, 14,201, 19,236,101,+ 128, 36,230,245,237,230,236,229,120,128, 1,117,100, 2,201, 34,+ 201, 44,233,229,242,229,243,233,115,128, 30,133,239,116, 2,201,+ 51,201, 60,225,227,227,229,238,116,128, 30,135,226,229,236,239,+ 119,128, 30,137,101, 4,201, 78,201, 89,201,101,201,125,232,233,+ 242,225,231,225,238, 97,128, 48,145,233,229,242,243,244,242,225,+ 243,115,128, 33, 24,107, 2,201,107,201,117,225,244,225,235,225,+ 238, 97,128, 48,241,239,242,229,225,110,128, 49, 94,239,235,239,+ 242,229,225,110,128, 49, 93,231,242,225,246,101,128, 30,129,232,+ 233,244,101, 8,201,164,201,173,202, 1,202, 91,202,175,202,220,+ 203, 16,203, 72,226,245,236,236,229,116,128, 37,230, 99, 2,201,+ 179,201,199,233,242,227,236,101,129, 37,203,201,189,233,238,246,+ 229,242,243,101,128, 37,217,239,242,238,229,242,226,242,225,227,+ 235,229,116, 2,201,216,201,236,236,229,230,116,129, 48, 14,201,+ 225,246,229,242,244,233,227,225,108,128,254, 67,242,233,231,232,+ 116,129, 48, 15,201,246,246,229,242,244,233,227,225,108,128,254,+ 68,100, 2,202, 7,202, 48,233,225,237,239,238,100,129, 37,199,+ 202, 18,227,239,238,244,225,233,238,233,238,231,226,236,225,227,+ 235,243,237,225,236,236,228,233,225,237,239,238,100,128, 37,200,+ 239,247,238,240,239,233,238,244,233,238,103, 2,202, 64,202, 80,+ 243,237,225,236,236,244,242,233,225,238,231,236,101,128, 37,191,+ 244,242,233,225,238,231,236,101,128, 37,189,236,101, 2,202, 98,+ 202,140,230,244,240,239,233,238,244,233,238,103, 2,202,113,202,+ 129,243,237,225,236,236,244,242,233,225,238,231,236,101,128, 37,+ 195,244,242,233,225,238,231,236,101,128, 37,193,238,244,233,227,+ 245,236,225,242,226,242,225,227,235,229,116, 2,202,160,202,167,+ 236,229,230,116,128, 48, 22,242,233,231,232,116,128, 48, 23,242,+ 233,231,232,244,240,239,233,238,244,233,238,103, 2,202,193,202,+ 209,243,237,225,236,236,244,242,233,225,238,231,236,101,128, 37,+ 185,244,242,233,225,238,231,236,101,128, 37,183,115, 3,202,228,+ 203, 2,203, 10,109, 2,202,234,202,246,225,236,236,243,241,245,+ 225,242,101,128, 37,171,233,236,233,238,231,230,225,227,101,128,+ 38, 58,241,245,225,242,101,128, 37,161,244,225,114,128, 38, 6,+ 116, 2,203, 22,203, 33,229,236,229,240,232,239,238,101,128, 38,+ 15,239,242,244,239,233,243,229,243,232,229,236,236,226,242,225,+ 227,235,229,116, 2,203, 57,203, 64,236,229,230,116,128, 48, 24,+ 242,233,231,232,116,128, 48, 25,245,240,240,239,233,238,244,233,+ 238,103, 2,203, 87,203,103,243,237,225,236,236,244,242,233,225,+ 238,231,236,101,128, 37,181,244,242,233,225,238,231,236,101,128,+ 37,179,105, 2,203,120,203,131,232,233,242,225,231,225,238, 97,+ 128, 48,144,107, 2,203,137,203,147,225,244,225,235,225,238, 97,+ 128, 48,240,239,242,229,225,110,128, 49, 95,237,239,238,239,243,+ 240,225,227,101,128,255, 87,111, 4,203,177,203,188,203,213,203,+ 231,232,233,242,225,231,225,238, 97,128, 48,146,235,225,244,225,+ 235,225,238, 97,129, 48,242,203,201,232,225,236,230,247,233,228,+ 244,104,128,255,102,110,129, 32,169,203,219,237,239,238,239,243,+ 240,225,227,101,128,255,230,247,225,229,238,244,232,225,105,128,+ 14, 39,240,225,242,229,110,128, 36,178,242,233,238,103,128, 30,+ 152,243,245,240,229,242,233,239,114,128, 2,183,244,245,242,238,+ 229,100,128, 2,141,249,238,110,128, 1,191,120,137, 0,120,204,+ 49,204, 60,204, 71,204, 80,204,107,204,120,204,124,204,136,204,+ 144,225,226,239,246,229,227,237, 98,128, 3, 61,226,239,240,239,+ 237,239,230,111,128, 49, 18,227,233,242,227,236,101,128, 36,231,+ 100, 2,204, 86,204, 96,233,229,242,229,243,233,115,128, 30,141,+ 239,244,225,227,227,229,238,116,128, 30,139,229,232,225,242,237,+ 229,238,233,225,110,128, 5,109,105,128, 3,190,237,239,238,239,+ 243,240,225,227,101,128,255, 88,240,225,242,229,110,128, 36,179,+ 243,245,240,229,242,233,239,114,128, 2,227,121,143, 0,121,204,+ 189,205,148,205,171,205,211,207,177,207,185,207,202,208, 10,208,+ 22,209, 19,209, 59,209, 71,209, 82,209,103,210, 76, 97, 11,204,+ 213,204,225,204,235,204,242,204,249,205, 3,205, 28,205, 39,205,+ 77,205, 90,205,136,225,228,239,243,241,245,225,242,101,128, 51,+ 78,226,229,238,231,225,236,105,128, 9,175,227,245,244,101,128,+ 0,253,228,229,246, 97,128, 9, 47,229,235,239,242,229,225,110,+ 128, 49, 82,231,117, 2,205, 10,205, 19,234,225,242,225,244,105,+ 128, 10,175,242,237,245,235,232,105,128, 10, 47,232,233,242,225,+ 231,225,238, 97,128, 48,132,107, 2,205, 45,205, 69,225,244,225,+ 235,225,238, 97,129, 48,228,205, 57,232,225,236,230,247,233,228,+ 244,104,128,255,148,239,242,229,225,110,128, 49, 81,237,225,235,+ 235,225,238,244,232,225,105,128, 14, 78,243,237,225,236,108, 2,+ 205,100,205,111,232,233,242,225,231,225,238, 97,128, 48,131,235,+ 225,244,225,235,225,238, 97,129, 48,227,205,124,232,225,236,230,+ 247,233,228,244,104,128,255,108,244,227,249,242,233,236,236,233,+ 99,128, 4, 99,227,233,242, 99, 2,205,157,205,162,236,101,128,+ 36,232,245,237,230,236,229,120,128, 1,119,100, 2,205,177,205,+ 187,233,229,242,229,243,233,115,128, 0,255,239,116, 2,205,194,+ 205,203,225,227,227,229,238,116,128, 30,143,226,229,236,239,119,+ 128, 30,245,101, 7,205,227,206,235,206,244,207, 6,207, 38,207,+ 114,207,165,104, 8,205,245,205,254,206, 32,206, 46,206,119,206,+ 135,206,194,206,212,225,242,225,226,233, 99,128, 6, 74,226,225,+ 242,242,229,101, 2,206, 9,206, 18,225,242,225,226,233, 99,128,+ 6,210,230,233,238,225,236,225,242,225,226,233, 99,128,251,175,+ 230,233,238,225,236,225,242,225,226,233, 99,128,254,242,232,225,+ 237,250,225,225,226,239,246,101, 4,206, 65,206, 74,206, 88,206,+ 104,225,242,225,226,233, 99,128, 6, 38,230,233,238,225,236,225,+ 242,225,226,233, 99,128,254,138,233,238,233,244,233,225,236,225,+ 242,225,226,233, 99,128,254,139,237,229,228,233,225,236,225,242,+ 225,226,233, 99,128,254,140,233,238,233,244,233,225,236,225,242,+ 225,226,233, 99,128,254,243,237,101, 2,206,142,206,155,228,233,+ 225,236,225,242,225,226,233, 99,128,254,244,229,237,105, 2,206,+ 163,206,178,238,233,244,233,225,236,225,242,225,226,233, 99,128,+ 252,221,243,239,236,225,244,229,228,225,242,225,226,233, 99,128,+ 252, 88,238,239,239,238,230,233,238,225,236,225,242,225,226,233,+ 99,128,252,148,244,232,242,229,229,228,239,244,243,226,229,236,+ 239,247,225,242,225,226,233, 99,128, 6,209,235,239,242,229,225,+ 110,128, 49, 86,110,129, 0,165,206,250,237,239,238,239,243,240,+ 225,227,101,128,255,229,111, 2,207, 12,207, 21,235,239,242,229,+ 225,110,128, 49, 85,242,233,238,232,233,229,245,232,235,239,242,+ 229,225,110,128, 49,134,114, 3,207, 46,207, 82,207, 94,225,232,+ 226,229,238,249,239,237,111, 2,207, 60,207, 69,232,229,226,242,+ 229,119,128, 5,170,236,229,230,244,232,229,226,242,229,119,128,+ 5,170,233,227,249,242,233,236,236,233, 99,128, 4, 75,245,228,+ 233,229,242,229,243,233,243,227,249,242,233,236,236,233, 99,128,+ 4,249,243,233,229,245,238,103, 3,207,127,207,136,207,152,235,+ 239,242,229,225,110,128, 49,129,240,225,238,243,233,239,243,235,+ 239,242,229,225,110,128, 49,131,243,233,239,243,235,239,242,229,+ 225,110,128, 49,130,244,233,246,232,229,226,242,229,119,128, 5,+ 154,231,242,225,246,101,128, 30,243,232,239,239,107,129, 1,180,+ 207,194,225,226,239,246,101,128, 30,247,105, 5,207,214,207,225,+ 207,236,207,245,207,253,225,242,237,229,238,233,225,110,128, 5,+ 117,227,249,242,233,236,236,233, 99,128, 4, 87,235,239,242,229,+ 225,110,128, 49, 98,238,249,225,238,103,128, 38, 47,247,238,225,+ 242,237,229,238,233,225,110,128, 5,130,237,239,238,239,243,240,+ 225,227,101,128,255, 89,111, 7,208, 38,208,108,208,119,208,129,+ 208,167,208,213,208,222,100,131, 5,217,208, 48,208, 68,208, 77,+ 228,225,231,229,243,104,129,251, 57,208, 59,232,229,226,242,229,+ 119,128,251, 57,232,229,226,242,229,119,128, 5,217,249,239,100,+ 2,208, 85,208, 94,232,229,226,242,229,119,128, 5,242,240,225,+ 244,225,232,232,229,226,242,229,119,128,251, 31,232,233,242,225,+ 231,225,238, 97,128, 48,136,233,235,239,242,229,225,110,128, 49,+ 137,107, 2,208,135,208,159,225,244,225,235,225,238, 97,129, 48,+ 232,208,147,232,225,236,230,247,233,228,244,104,128,255,150,239,+ 242,229,225,110,128, 49, 91,243,237,225,236,108, 2,208,177,208,+ 188,232,233,242,225,231,225,238, 97,128, 48,135,235,225,244,225,+ 235,225,238, 97,129, 48,231,208,201,232,225,236,230,247,233,228,+ 244,104,128,255,110,244,231,242,229,229,107,128, 3,243,121, 2,+ 208,228,209, 9, 97, 2,208,234,208,244,229,235,239,242,229,225,+ 110,128, 49,136,107, 2,208,250,209, 2,239,242,229,225,110,128,+ 49,135,244,232,225,105,128, 14, 34,233,238,231,244,232,225,105,+ 128, 14, 13,112, 2,209, 25,209, 32,225,242,229,110,128, 36,180,+ 239,231,229,231,242,225,237,237,229,238,105,129, 3,122,209, 48,+ 231,242,229,229,235,227,237, 98,128, 3, 69,114,129, 1,166,209,+ 65,233,238,103,128, 30,153,243,245,240,229,242,233,239,114,128,+ 2,184,116, 2,209, 88,209, 95,233,236,228,101,128, 30,249,245,+ 242,238,229,100,128, 2,142,117, 5,209,115,209,126,209,136,209,+ 174,210, 50,232,233,242,225,231,225,238, 97,128, 48,134,233,235,+ 239,242,229,225,110,128, 49,140,107, 2,209,142,209,166,225,244,+ 225,235,225,238, 97,129, 48,230,209,154,232,225,236,230,247,233,+ 228,244,104,128,255,149,239,242,229,225,110,128, 49, 96,115, 3,+ 209,182,209,220,210, 5,226,233,103, 2,209,190,209,201,227,249,+ 242,233,236,236,233, 99,128, 4,107,233,239,244,233,230,233,229,+ 228,227,249,242,233,236,236,233, 99,128, 4,109,236,233,244,244,+ 236,101, 2,209,231,209,242,227,249,242,233,236,236,233, 99,128,+ 4,103,233,239,244,233,230,233,229,228,227,249,242,233,236,236,+ 233, 99,128, 4,105,237,225,236,108, 2,210, 14,210, 25,232,233,+ 242,225,231,225,238, 97,128, 48,133,235,225,244,225,235,225,238,+ 97,129, 48,229,210, 38,232,225,236,230,247,233,228,244,104,128,+ 255,109,249,101, 2,210, 57,210, 66,235,239,242,229,225,110,128,+ 49,139,239,235,239,242,229,225,110,128, 49,138,249, 97, 2,210,+ 83,210, 93,226,229,238,231,225,236,105,128, 9,223,228,229,246,+ 97,128, 9, 95,122,142, 0,122,210,132,211,140,211,151,211,194,+ 211,221,213, 0,213,108,213,150,213,162,213,174,213,202,213,210,+ 213,226,213,235, 97, 10,210,154,210,165,210,172,210,179,210,190,+ 211, 12,211, 42,211, 53,211, 89,211,101,225,242,237,229,238,233,+ 225,110,128, 5,102,227,245,244,101,128, 1,122,228,229,246, 97,+ 128, 9, 91,231,245,242,237,245,235,232,105,128, 10, 91,104, 4,+ 210,200,210,209,210,223,210,253,225,242,225,226,233, 99,128, 6,+ 56,230,233,238,225,236,225,242,225,226,233, 99,128,254,198,105,+ 2,210,229,210,244,238,233,244,233,225,236,225,242,225,226,233,+ 99,128,254,199,242,225,231,225,238, 97,128, 48, 86,237,229,228,+ 233,225,236,225,242,225,226,233, 99,128,254,200,233,110, 2,211,+ 19,211, 28,225,242,225,226,233, 99,128, 6, 50,230,233,238,225,+ 236,225,242,225,226,233, 99,128,254,176,235,225,244,225,235,225,+ 238, 97,128, 48,182,241,229,102, 2,211, 61,211, 75,231,225,228,+ 239,236,232,229,226,242,229,119,128, 5,149,241,225,244,225,238,+ 232,229,226,242,229,119,128, 5,148,242,241,225,232,229,226,242,+ 229,119,128, 5,152,249,233,110,130, 5,214,211,111,211,131,228,+ 225,231,229,243,104,129,251, 54,211,122,232,229,226,242,229,119,+ 128,251, 54,232,229,226,242,229,119,128, 5,214,226,239,240,239,+ 237,239,230,111,128, 49, 23, 99, 3,211,159,211,166,211,188,225,+ 242,239,110,128, 1,126,233,242, 99, 2,211,174,211,179,236,101,+ 128, 36,233,245,237,230,236,229,120,128, 30,145,245,242,108,128,+ 2,145,228,239,116,130, 1,124,211,204,211,213,225,227,227,229,+ 238,116,128, 1,124,226,229,236,239,119,128, 30,147,101, 6,211,+ 235,211,246,212, 33,212, 44,212, 55,212,251,227,249,242,233,236,+ 236,233, 99,128, 4, 55,100, 2,211,252,212, 15,229,243,227,229,+ 238,228,229,242,227,249,242,233,236,236,233, 99,128, 4,153,233,+ 229,242,229,243,233,243,227,249,242,233,236,236,233, 99,128, 4,+ 223,232,233,242,225,231,225,238, 97,128, 48, 92,235,225,244,225,+ 235,225,238, 97,128, 48,188,242,111,140, 0, 48,212, 84,212, 93,+ 212,103,212,110,212,135,212,148,212,159,212,171,212,182,212,192,+ 212,203,212,210,225,242,225,226,233, 99,128, 6, 96,226,229,238,+ 231,225,236,105,128, 9,230,228,229,246, 97,128, 9,102,231,117,+ 2,212,117,212,126,234,225,242,225,244,105,128, 10,230,242,237,+ 245,235,232,105,128, 10,102,232,225,227,235,225,242,225,226,233,+ 99,128, 6, 96,233,238,230,229,242,233,239,114,128, 32,128,237,+ 239,238,239,243,240,225,227,101,128,255, 16,239,236,228,243,244,+ 249,236,101,128,247, 48,240,229,242,243,233,225,110,128, 6,240,+ 243,245,240,229,242,233,239,114,128, 32,112,244,232,225,105,128,+ 14, 80,247,233,228,244,104, 3,212,222,212,231,212,243,234,239,+ 233,238,229,114,128,254,255,238,239,238,234,239,233,238,229,114,+ 128, 32, 12,243,240,225,227,101,128, 32, 11,244, 97,128, 3,182,+ 104, 2,213, 6,213, 17,226,239,240,239,237,239,230,111,128, 49,+ 19,101, 4,213, 27,213, 38,213, 54,213, 65,225,242,237,229,238,+ 233,225,110,128, 5,106,226,242,229,246,229,227,249,242,233,236,+ 236,233, 99,128, 4,194,227,249,242,233,236,236,233, 99,128, 4,+ 54,100, 2,213, 71,213, 90,229,243,227,229,238,228,229,242,227,+ 249,242,233,236,236,233, 99,128, 4,151,233,229,242,229,243,233,+ 243,227,249,242,233,236,236,233, 99,128, 4,221,105, 3,213,116,+ 213,127,213,138,232,233,242,225,231,225,238, 97,128, 48, 88,235,+ 225,244,225,235,225,238, 97,128, 48,184,238,239,242,232,229,226,+ 242,229,119,128, 5,174,236,233,238,229,226,229,236,239,119,128,+ 30,149,237,239,238,239,243,240,225,227,101,128,255, 90,111, 2,+ 213,180,213,191,232,233,242,225,231,225,238, 97,128, 48, 94,235,+ 225,244,225,235,225,238, 97,128, 48,190,240,225,242,229,110,128,+ 36,181,242,229,244,242,239,230,236,229,248,232,239,239,107,128,+ 2,144,243,244,242,239,235,101,128, 1,182,117, 2,213,241,213,+ 252,232,233,242,225,231,225,238, 97,128, 48, 90,235,225,244,225,+ 235,225,238, 97,128, 48,186+ };+++ /*+ * This function searches the compressed table efficiently.+ */+ static unsigned long+ ft_get_adobe_glyph_index( const char* name,+ const char* limit )+ {+ int c = 0;+ int count, min, max;+ const unsigned char* p = ft_adobe_glyph_list;+++ if ( name == 0 || name >= limit )+ goto NotFound;++ c = *name++;+ count = p[1];+ p += 2;++ min = 0;+ max = count;++ while ( min < max )+ {+ int mid = ( min + max ) >> 1;+ const unsigned char* q = p + mid * 2;+ int c2;+++ q = ft_adobe_glyph_list + ( ( (int)q[0] << 8 ) | q[1] );++ c2 = q[0] & 127;+ if ( c2 == c )+ {+ p = q;+ goto Found;+ }+ if ( c2 < c )+ min = mid + 1;+ else+ max = mid;+ }+ goto NotFound;++ Found:+ for (;;)+ {+ /* assert (*p & 127) == c */++ if ( name >= limit )+ {+ if ( (p[0] & 128) == 0 &&+ (p[1] & 128) != 0 )+ return (unsigned long)( ( (int)p[2] << 8 ) | p[3] );++ goto NotFound;+ }+ c = *name++;+ if ( p[0] & 128 )+ {+ p++;+ if ( c != (p[0] & 127) )+ goto NotFound;++ continue;+ }++ p++;+ count = p[0] & 127;+ if ( p[0] & 128 )+ p += 2;++ p++;++ for ( ; count > 0; count--, p += 2 )+ {+ int offset = ( (int)p[0] << 8 ) | p[1];+ const unsigned char* q = ft_adobe_glyph_list + offset;++ if ( c == ( q[0] & 127 ) )+ {+ p = q;+ goto NextIter;+ }+ }+ goto NotFound;++ NextIter:+ ;+ }++ NotFound:+ return 0;+ }++#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */+++/* END */
+ src/raster/ftmisc.h view
@@ -0,0 +1,121 @@+/***************************************************************************/+/* */+/* ftmisc.h */+/* */+/* Miscellaneous macros for stand-alone rasterizer (specification */+/* only). */+/* */+/* Copyright 2005, 2009, 2010 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 *not* portable! You have to adapt */+ /* its definitions to your platform. */+ /* */+ /***************************************************/++#ifndef __FTMISC_H__+#define __FTMISC_H__+++ /* memset */+#include FT_CONFIG_STANDARD_LIBRARY_H++#define FT_BEGIN_HEADER+#define FT_END_HEADER++#define FT_LOCAL_DEF( x ) static x+++ /* from include/freetype2/fttypes.h */++ typedef unsigned char FT_Byte;+ typedef signed int FT_Int;+ typedef unsigned int FT_UInt;+ typedef signed long FT_Long;+ typedef unsigned long FT_ULong;+ typedef signed long FT_F26Dot6;+ typedef int FT_Error;++#define FT_MAKE_TAG( _x1, _x2, _x3, _x4 ) \+ ( ( (FT_ULong)_x1 << 24 ) | \+ ( (FT_ULong)_x2 << 16 ) | \+ ( (FT_ULong)_x3 << 8 ) | \+ (FT_ULong)_x4 )+++ /* from include/freetype2/ftsystem.h */++ typedef struct FT_MemoryRec_* FT_Memory;++ typedef void* (*FT_Alloc_Func)( FT_Memory memory,+ long size );++ typedef void (*FT_Free_Func)( FT_Memory memory,+ void* block );++ typedef void* (*FT_Realloc_Func)( FT_Memory memory,+ long cur_size,+ long new_size,+ void* block );++ typedef struct FT_MemoryRec_+ {+ void* user;++ FT_Alloc_Func alloc;+ FT_Free_Func free;+ FT_Realloc_Func realloc;++ } FT_MemoryRec;+++ /* from src/ftcalc.c */++#if ( defined _WIN32 || defined _WIN64 )++ typedef __int64 FT_Int64;++#else++#include "inttypes.h"++ typedef int64_t FT_Int64;++#endif+++ static FT_Long+ FT_MulDiv( FT_Long a,+ FT_Long b,+ FT_Long c )+ {+ FT_Int s;+ FT_Long d;+++ s = 1;+ if ( a < 0 ) { a = -a; s = -1; }+ if ( b < 0 ) { b = -b; s = -s; }+ if ( c < 0 ) { c = -c; s = -s; }++ d = (FT_Long)( c > 0 ? ( (FT_Int64)a * b + ( c >> 1 ) ) / c+ : 0x7FFFFFFFL );++ return ( s > 0 ) ? d : -d;+ }++#endif /* __FTMISC_H__ */+++/* END */
+ src/raster/ftraster.c view
@@ -0,0 +1,3563 @@+/***************************************************************************/+/* */+/* ftraster.c */+/* */+/* The FreeType glyph rasterizer (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2005, 2007, 2008, 2009, 2010 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 can be compiled without the rest of the FreeType engine, by */+ /* defining the _STANDALONE_ macro when compiling it. You also need to */+ /* put the files `ftimage.h' and `ftmisc.h' into the $(incdir) */+ /* directory. Typically, you should do something like */+ /* */+ /* - copy `src/raster/ftraster.c' (this file) 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 */+ /* */+ /* cc -c -D_STANDALONE_ ftraster.c */+ /* */+ /* The renderer can be initialized with a call to */+ /* `ft_standard_raster.raster_new'; a bitmap can be generated */+ /* with a call to `ft_standard_raster.raster_render'. */+ /* */+ /* See the comments and documentation in the file `ftimage.h' for more */+ /* details on how the raster works. */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* This is a rewrite of the FreeType 1.x scan-line converter */+ /* */+ /*************************************************************************/++#ifdef _STANDALONE_++#define FT_CONFIG_STANDARD_LIBRARY_H <stdlib.h>++#include <string.h> /* for memset */++#include "ftmisc.h"+#include "ftimage.h"++#else /* !_STANDALONE_ */++#include <ft2build.h>+#include "ftraster.h"+#include FT_INTERNAL_CALC_H /* for FT_MulDiv only */++#include "rastpic.h"++#endif /* !_STANDALONE_ */+++ /*************************************************************************/+ /* */+ /* A simple technical note on how the raster works */+ /* ----------------------------------------------- */+ /* */+ /* Converting an outline into a bitmap is achieved in several steps: */+ /* */+ /* 1 - Decomposing the outline into successive `profiles'. Each */+ /* profile is simply an array of scanline intersections on a given */+ /* dimension. A profile's main attributes are */+ /* */+ /* o its scanline position boundaries, i.e. `Ymin' and `Ymax' */+ /* */+ /* o an array of intersection coordinates for each scanline */+ /* between `Ymin' and `Ymax' */+ /* */+ /* o a direction, indicating whether it was built going `up' or */+ /* `down', as this is very important for filling rules */+ /* */+ /* o its drop-out mode */+ /* */+ /* 2 - Sweeping the target map's scanlines in order to compute segment */+ /* `spans' which are then filled. Additionally, this pass */+ /* performs drop-out control. */+ /* */+ /* The outline data is parsed during step 1 only. The profiles are */+ /* built from the bottom of the render pool, used as a stack. The */+ /* following graphics shows the profile list under construction: */+ /* */+ /* __________________________________________________________ _ _ */+ /* | | | | | */+ /* | profile | coordinates for | profile | coordinates for |--> */+ /* | 1 | profile 1 | 2 | profile 2 |--> */+ /* |_________|_________________|_________|_________________|__ _ _ */+ /* */+ /* ^ ^ */+ /* | | */+ /* start of render pool top */+ /* */+ /* The top of the profile stack is kept in the `top' variable. */+ /* */+ /* As you can see, a profile record is pushed on top of the render */+ /* pool, which is then followed by its coordinates/intersections. If */+ /* a change of direction is detected in the outline, a new profile is */+ /* generated until the end of the outline. */+ /* */+ /* Note that when all profiles have been generated, the function */+ /* Finalize_Profile_Table() is used to record, for each profile, its */+ /* bottom-most scanline as well as the scanline above its upmost */+ /* boundary. These positions are called `y-turns' because they (sort */+ /* of) correspond to local extrema. They are stored in a sorted list */+ /* built from the top of the render pool as a downwards stack: */+ /* */+ /* _ _ _______________________________________ */+ /* | | */+ /* <--| sorted list of | */+ /* <--| extrema scanlines | */+ /* _ _ __________________|____________________| */+ /* */+ /* ^ ^ */+ /* | | */+ /* maxBuff sizeBuff = end of pool */+ /* */+ /* This list is later used during the sweep phase in order to */+ /* optimize performance (see technical note on the sweep below). */+ /* */+ /* Of course, the raster detects whether the two stacks collide and */+ /* handles the situation properly. */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /*************************************************************************/+ /** **/+ /** CONFIGURATION MACROS **/+ /** **/+ /*************************************************************************/+ /*************************************************************************/++ /* define DEBUG_RASTER if you want to compile a debugging version */+/* #define DEBUG_RASTER */++ /* define FT_RASTER_OPTION_ANTI_ALIASING if you want to support */+ /* 5-levels anti-aliasing */+/* #define FT_RASTER_OPTION_ANTI_ALIASING */++ /* The size of the two-lines intermediate bitmap used */+ /* for anti-aliasing, in bytes. */+#define RASTER_GRAY_LINES 2048+++ /*************************************************************************/+ /*************************************************************************/+ /** **/+ /** OTHER MACROS (do not change) **/+ /** **/+ /*************************************************************************/+ /*************************************************************************/++ /*************************************************************************/+ /* */+ /* 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_raster+++#ifdef _STANDALONE_+++ /* This macro is used to indicate that a function parameter is unused. */+ /* Its purpose is simply to reduce compiler warnings. Note also that */+ /* simply defining it as `(void)x' doesn't avoid warnings with certain */+ /* ANSI compilers (e.g. LCC). */+#define FT_UNUSED( x ) (x) = (x)++ /* Disable the tracing mechanism for simplicity -- developers can */+ /* activate it easily by redefining these two macros. */+#ifndef FT_ERROR+#define FT_ERROR( x ) do { } while ( 0 ) /* nothing */+#endif++#ifndef FT_TRACE+#define FT_TRACE( x ) do { } while ( 0 ) /* nothing */+#define FT_TRACE1( x ) do { } while ( 0 ) /* nothing */+#define FT_TRACE6( x ) do { } while ( 0 ) /* nothing */+#endif++#define Raster_Err_None 0+#define Raster_Err_Not_Ini -1+#define Raster_Err_Overflow -2+#define Raster_Err_Neg_Height -3+#define Raster_Err_Invalid -4+#define Raster_Err_Unsupported -5++#define ft_memset memset++#define FT_DEFINE_RASTER_FUNCS( class_, glyph_format_, raster_new_, \+ raster_reset_, raster_set_mode_, \+ raster_render_, raster_done_ ) \+ const FT_Raster_Funcs class_ = \+ { \+ glyph_format_, \+ raster_new_, \+ raster_reset_, \+ raster_set_mode_, \+ raster_render_, \+ raster_done_ \+ };++#else /* !_STANDALONE_ */+++#include FT_INTERNAL_OBJECTS_H+#include FT_INTERNAL_DEBUG_H /* for FT_TRACE() and FT_ERROR() */++#include "rasterrs.h"++#define Raster_Err_None Raster_Err_Ok+#define Raster_Err_Not_Ini Raster_Err_Raster_Uninitialized+#define Raster_Err_Overflow Raster_Err_Raster_Overflow+#define Raster_Err_Neg_Height Raster_Err_Raster_Negative_Height+#define Raster_Err_Invalid Raster_Err_Invalid_Outline+#define Raster_Err_Unsupported Raster_Err_Cannot_Render_Glyph+++#endif /* !_STANDALONE_ */+++#ifndef FT_MEM_SET+#define FT_MEM_SET( d, s, c ) ft_memset( d, s, c )+#endif++#ifndef FT_MEM_ZERO+#define FT_MEM_ZERO( dest, count ) FT_MEM_SET( dest, 0, count )+#endif++ /* FMulDiv means `Fast MulDiv'; it is used in case where `b' is */+ /* typically a small value and the result of a*b is known to fit into */+ /* 32 bits. */+#define FMulDiv( a, b, c ) ( (a) * (b) / (c) )++ /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */+ /* for clipping computations. It simply uses the FT_MulDiv() function */+ /* defined in `ftcalc.h'. */+#define SMulDiv FT_MulDiv++ /* The rasterizer is a very general purpose component; please leave */+ /* the following redefinitions there (you never know your target */+ /* environment). */++#ifndef TRUE+#define TRUE 1+#endif++#ifndef FALSE+#define FALSE 0+#endif++#ifndef NULL+#define NULL (void*)0+#endif++#ifndef SUCCESS+#define SUCCESS 0+#endif++#ifndef FAILURE+#define FAILURE 1+#endif+++#define MaxBezier 32 /* The maximum number of stacked Bezier curves. */+ /* Setting this constant to more than 32 is a */+ /* pure waste of space. */++#define Pixel_Bits 6 /* fractional bits of *input* coordinates */+++ /*************************************************************************/+ /*************************************************************************/+ /** **/+ /** SIMPLE TYPE DECLARATIONS **/+ /** **/+ /*************************************************************************/+ /*************************************************************************/++ typedef int Int;+ typedef unsigned int UInt;+ typedef short Short;+ typedef unsigned short UShort, *PUShort;+ typedef long Long, *PLong;++ typedef unsigned char Byte, *PByte;+ typedef char Bool;+++ typedef union Alignment_+ {+ long l;+ void* p;+ void (*f)(void);++ } Alignment, *PAlignment;+++ typedef struct TPoint_+ {+ Long x;+ Long y;++ } TPoint;+++ /* values for the `flags' bit field */+#define Flow_Up 0x8+#define Overshoot_Top 0x10+#define Overshoot_Bottom 0x20+++ /* States of each line, arc, and profile */+ typedef enum TStates_+ {+ Unknown_State,+ Ascending_State,+ Descending_State,+ Flat_State++ } TStates;+++ typedef struct TProfile_ TProfile;+ typedef TProfile* PProfile;++ struct TProfile_+ {+ FT_F26Dot6 X; /* current coordinate during sweep */+ PProfile link; /* link to next profile (various purposes) */+ PLong offset; /* start of profile's data in render pool */+ unsigned flags; /* Bit 0-2: drop-out mode */+ /* Bit 3: profile orientation (up/down) */+ /* Bit 4: is top profile? */+ /* Bit 5: is bottom profile? */+ long height; /* profile's height in scanlines */+ long start; /* profile's starting scanline */++ unsigned countL; /* number of lines to step before this */+ /* profile becomes drawable */++ PProfile next; /* next profile in same contour, used */+ /* during drop-out control */+ };++ typedef PProfile TProfileList;+ typedef PProfile* PProfileList;+++ /* Simple record used to implement a stack of bands, required */+ /* by the sub-banding mechanism */+ typedef struct TBand_+ {+ Short y_min; /* band's minimum */+ Short y_max; /* band's maximum */++ } TBand;+++#define AlignProfileSize \+ ( ( sizeof ( TProfile ) + sizeof ( Alignment ) - 1 ) / sizeof ( long ) )+++#ifdef FT_STATIC_RASTER+++#define RAS_ARGS /* void */+#define RAS_ARG /* void */++#define RAS_VARS /* void */+#define RAS_VAR /* void */++#define FT_UNUSED_RASTER do { } while ( 0 )+++#else /* !FT_STATIC_RASTER */+++#define RAS_ARGS PWorker worker,+#define RAS_ARG PWorker worker++#define RAS_VARS worker,+#define RAS_VAR worker++#define FT_UNUSED_RASTER FT_UNUSED( worker )+++#endif /* !FT_STATIC_RASTER */+++ typedef struct TWorker_ TWorker, *PWorker;+++ /* prototypes used for sweep function dispatch */+ typedef void+ Function_Sweep_Init( RAS_ARGS Short* min,+ Short* max );++ typedef void+ Function_Sweep_Span( RAS_ARGS Short y,+ FT_F26Dot6 x1,+ FT_F26Dot6 x2,+ PProfile left,+ PProfile right );++ typedef void+ Function_Sweep_Step( RAS_ARG );+++ /* NOTE: These operations are only valid on 2's complement processors */++#define FLOOR( x ) ( (x) & -ras.precision )+#define CEILING( x ) ( ( (x) + ras.precision - 1 ) & -ras.precision )+#define TRUNC( x ) ( (signed long)(x) >> ras.precision_bits )+#define FRAC( x ) ( (x) & ( ras.precision - 1 ) )+#define SCALED( x ) ( ( (x) << ras.scale_shift ) - ras.precision_half )++#define IS_BOTTOM_OVERSHOOT( x ) ( CEILING( x ) - x >= ras.precision_half )+#define IS_TOP_OVERSHOOT( x ) ( x - FLOOR( x ) >= ras.precision_half )++ /* The most used variables are positioned at the top of the structure. */+ /* Thus, their offset can be coded with less opcodes, resulting in a */+ /* smaller executable. */++ struct TWorker_+ {+ Int precision_bits; /* precision related variables */+ Int precision;+ Int precision_half;+ Int precision_shift;+ Int precision_step;+ Int precision_jitter;++ Int scale_shift; /* == precision_shift for bitmaps */+ /* == precision_shift+1 for pixmaps */++ PLong buff; /* The profiles buffer */+ PLong sizeBuff; /* Render pool size */+ PLong maxBuff; /* Profiles buffer size */+ PLong top; /* Current cursor in buffer */++ FT_Error error;++ Int numTurns; /* number of Y-turns in outline */++ TPoint* arc; /* current Bezier arc pointer */++ UShort bWidth; /* target bitmap width */+ PByte bTarget; /* target bitmap buffer */+ PByte gTarget; /* target pixmap buffer */++ Long lastX, lastY;+ Long minY, maxY;++ UShort num_Profs; /* current number of profiles */++ Bool fresh; /* signals a fresh new profile which */+ /* `start' field must be completed */+ Bool joint; /* signals that the last arc ended */+ /* exactly on a scanline. Allows */+ /* removal of doublets */+ PProfile cProfile; /* current profile */+ PProfile fProfile; /* head of linked list of profiles */+ PProfile gProfile; /* contour's first profile in case */+ /* of impact */++ TStates state; /* rendering state */++ FT_Bitmap target; /* description of target bit/pixmap */+ FT_Outline outline;++ Long traceOfs; /* current offset in target bitmap */+ Long traceG; /* current offset in target pixmap */++ Short traceIncr; /* sweep's increment in target bitmap */++ Short gray_min_x; /* current min x during gray rendering */+ Short gray_max_x; /* current max x during gray rendering */++ /* dispatch variables */++ Function_Sweep_Init* Proc_Sweep_Init;+ Function_Sweep_Span* Proc_Sweep_Span;+ Function_Sweep_Span* Proc_Sweep_Drop;+ Function_Sweep_Step* Proc_Sweep_Step;++ Byte dropOutControl; /* current drop_out control method */++ Bool second_pass; /* indicates whether a horizontal pass */+ /* should be performed to control */+ /* drop-out accurately when calling */+ /* Render_Glyph. Note that there is */+ /* no horizontal pass during gray */+ /* rendering. */++ TPoint arcs[3 * MaxBezier + 1]; /* The Bezier stack */++ TBand band_stack[16]; /* band stack used for sub-banding */+ Int band_top; /* band stack top */++#ifdef FT_RASTER_OPTION_ANTI_ALIASING++ Byte* grays;++ Byte gray_lines[RASTER_GRAY_LINES];+ /* Intermediate table used to render the */+ /* graylevels pixmaps. */+ /* gray_lines is a buffer holding two */+ /* monochrome scanlines */++ Short gray_width; /* width in bytes of one monochrome */+ /* intermediate scanline of gray_lines. */+ /* Each gray pixel takes 2 bits long there */++ /* The gray_lines must hold 2 lines, thus with size */+ /* in bytes of at least `gray_width*2'. */++#endif /* FT_RASTER_ANTI_ALIASING */++ };+++ typedef struct TRaster_+ {+ char* buffer;+ long buffer_size;+ void* memory;+ PWorker worker;+ Byte grays[5];+ Short gray_width;++ } TRaster, *PRaster;++#ifdef FT_STATIC_RASTER++ static TWorker cur_ras;+#define ras cur_ras++#else /* !FT_STATIC_RASTER */++#define ras (*worker)++#endif /* !FT_STATIC_RASTER */+++#ifdef FT_RASTER_OPTION_ANTI_ALIASING++ /* A lookup table used to quickly count set bits in four gray 2x2 */+ /* cells. The values of the table have been produced with the */+ /* following code: */+ /* */+ /* for ( i = 0; i < 256; i++ ) */+ /* { */+ /* l = 0; */+ /* j = i; */+ /* */+ /* for ( c = 0; c < 4; c++ ) */+ /* { */+ /* l <<= 4; */+ /* */+ /* if ( j & 0x80 ) l++; */+ /* if ( j & 0x40 ) l++; */+ /* */+ /* j = ( j << 2 ) & 0xFF; */+ /* } */+ /* printf( "0x%04X", l ); */+ /* } */+ /* */++ static const short count_table[256] =+ {+ 0x0000, 0x0001, 0x0001, 0x0002, 0x0010, 0x0011, 0x0011, 0x0012,+ 0x0010, 0x0011, 0x0011, 0x0012, 0x0020, 0x0021, 0x0021, 0x0022,+ 0x0100, 0x0101, 0x0101, 0x0102, 0x0110, 0x0111, 0x0111, 0x0112,+ 0x0110, 0x0111, 0x0111, 0x0112, 0x0120, 0x0121, 0x0121, 0x0122,+ 0x0100, 0x0101, 0x0101, 0x0102, 0x0110, 0x0111, 0x0111, 0x0112,+ 0x0110, 0x0111, 0x0111, 0x0112, 0x0120, 0x0121, 0x0121, 0x0122,+ 0x0200, 0x0201, 0x0201, 0x0202, 0x0210, 0x0211, 0x0211, 0x0212,+ 0x0210, 0x0211, 0x0211, 0x0212, 0x0220, 0x0221, 0x0221, 0x0222,+ 0x1000, 0x1001, 0x1001, 0x1002, 0x1010, 0x1011, 0x1011, 0x1012,+ 0x1010, 0x1011, 0x1011, 0x1012, 0x1020, 0x1021, 0x1021, 0x1022,+ 0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,+ 0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,+ 0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,+ 0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,+ 0x1200, 0x1201, 0x1201, 0x1202, 0x1210, 0x1211, 0x1211, 0x1212,+ 0x1210, 0x1211, 0x1211, 0x1212, 0x1220, 0x1221, 0x1221, 0x1222,+ 0x1000, 0x1001, 0x1001, 0x1002, 0x1010, 0x1011, 0x1011, 0x1012,+ 0x1010, 0x1011, 0x1011, 0x1012, 0x1020, 0x1021, 0x1021, 0x1022,+ 0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,+ 0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,+ 0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,+ 0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,+ 0x1200, 0x1201, 0x1201, 0x1202, 0x1210, 0x1211, 0x1211, 0x1212,+ 0x1210, 0x1211, 0x1211, 0x1212, 0x1220, 0x1221, 0x1221, 0x1222,+ 0x2000, 0x2001, 0x2001, 0x2002, 0x2010, 0x2011, 0x2011, 0x2012,+ 0x2010, 0x2011, 0x2011, 0x2012, 0x2020, 0x2021, 0x2021, 0x2022,+ 0x2100, 0x2101, 0x2101, 0x2102, 0x2110, 0x2111, 0x2111, 0x2112,+ 0x2110, 0x2111, 0x2111, 0x2112, 0x2120, 0x2121, 0x2121, 0x2122,+ 0x2100, 0x2101, 0x2101, 0x2102, 0x2110, 0x2111, 0x2111, 0x2112,+ 0x2110, 0x2111, 0x2111, 0x2112, 0x2120, 0x2121, 0x2121, 0x2122,+ 0x2200, 0x2201, 0x2201, 0x2202, 0x2210, 0x2211, 0x2211, 0x2212,+ 0x2210, 0x2211, 0x2211, 0x2212, 0x2220, 0x2221, 0x2221, 0x2222+ };++#endif /* FT_RASTER_OPTION_ANTI_ALIASING */++++ /*************************************************************************/+ /*************************************************************************/+ /** **/+ /** PROFILES COMPUTATION **/+ /** **/+ /*************************************************************************/+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Set_High_Precision */+ /* */+ /* <Description> */+ /* Set precision variables according to param flag. */+ /* */+ /* <Input> */+ /* High :: Set to True for high precision (typically for ppem < 18), */+ /* false otherwise. */+ /* */+ static void+ Set_High_Precision( RAS_ARGS Int High )+ {+ if ( High )+ {+ ras.precision_bits = 12;+ ras.precision_step = 256;+ ras.precision_jitter = 50;+ }+ else+ {+ ras.precision_bits = 6;+ ras.precision_step = 32;+ ras.precision_jitter = 2;+ }++ FT_TRACE6(( "Set_High_Precision(%s)\n", High ? "true" : "false" ));++ ras.precision = 1 << ras.precision_bits;+ ras.precision_half = ras.precision / 2;+ ras.precision_shift = ras.precision_bits - Pixel_Bits;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* New_Profile */+ /* */+ /* <Description> */+ /* Create a new profile in the render pool. */+ /* */+ /* <Input> */+ /* aState :: The state/orientation of the new profile. */+ /* */+ /* overshoot :: Whether the profile's unrounded start position */+ /* differs by at least a half pixel. */+ /* */+ /* <Return> */+ /* SUCCESS on success. FAILURE in case of overflow or of incoherent */+ /* profile. */+ /* */+ static Bool+ New_Profile( RAS_ARGS TStates aState,+ Bool overshoot )+ {+ if ( !ras.fProfile )+ {+ ras.cProfile = (PProfile)ras.top;+ ras.fProfile = ras.cProfile;+ ras.top += AlignProfileSize;+ }++ if ( ras.top >= ras.maxBuff )+ {+ ras.error = Raster_Err_Overflow;+ return FAILURE;+ }++ ras.cProfile->flags = 0;+ ras.cProfile->start = 0;+ ras.cProfile->height = 0;+ ras.cProfile->offset = ras.top;+ ras.cProfile->link = (PProfile)0;+ ras.cProfile->next = (PProfile)0;+ ras.cProfile->flags = ras.dropOutControl;++ switch ( aState )+ {+ case Ascending_State:+ ras.cProfile->flags |= Flow_Up;+ if ( overshoot )+ ras.cProfile->flags |= Overshoot_Bottom;++ FT_TRACE6(( "New ascending profile = %p\n", ras.cProfile ));+ break;++ case Descending_State:+ if ( overshoot )+ ras.cProfile->flags |= Overshoot_Top;+ FT_TRACE6(( "New descending profile = %p\n", ras.cProfile ));+ break;++ default:+ FT_ERROR(( "New_Profile: invalid profile direction\n" ));+ ras.error = Raster_Err_Invalid;+ return FAILURE;+ }++ if ( !ras.gProfile )+ ras.gProfile = ras.cProfile;++ ras.state = aState;+ ras.fresh = TRUE;+ ras.joint = FALSE;++ return SUCCESS;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* End_Profile */+ /* */+ /* <Description> */+ /* Finalize the current profile. */+ /* */+ /* <Input> */+ /* overshoot :: Whether the profile's unrounded end position differs */+ /* by at least a half pixel. */+ /* */+ /* <Return> */+ /* SUCCESS on success. FAILURE in case of overflow or incoherency. */+ /* */+ static Bool+ End_Profile( RAS_ARGS Bool overshoot )+ {+ Long h;+ PProfile oldProfile;+++ h = (Long)( ras.top - ras.cProfile->offset );++ if ( h < 0 )+ {+ FT_ERROR(( "End_Profile: negative height encountered\n" ));+ ras.error = Raster_Err_Neg_Height;+ return FAILURE;+ }++ if ( h > 0 )+ {+ FT_TRACE6(( "Ending profile %p, start = %ld, height = %ld\n",+ ras.cProfile, ras.cProfile->start, h ));++ ras.cProfile->height = h;+ if ( overshoot )+ {+ if ( ras.cProfile->flags & Flow_Up )+ ras.cProfile->flags |= Overshoot_Top;+ else+ ras.cProfile->flags |= Overshoot_Bottom;+ }++ oldProfile = ras.cProfile;+ ras.cProfile = (PProfile)ras.top;++ ras.top += AlignProfileSize;++ ras.cProfile->height = 0;+ ras.cProfile->offset = ras.top;++ oldProfile->next = ras.cProfile;+ ras.num_Profs++;+ }++ if ( ras.top >= ras.maxBuff )+ {+ FT_TRACE1(( "overflow in End_Profile\n" ));+ ras.error = Raster_Err_Overflow;+ return FAILURE;+ }++ ras.joint = FALSE;++ return SUCCESS;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Insert_Y_Turn */+ /* */+ /* <Description> */+ /* Insert a salient into the sorted list placed on top of the render */+ /* pool. */+ /* */+ /* <Input> */+ /* New y scanline position. */+ /* */+ /* <Return> */+ /* SUCCESS on success. FAILURE in case of overflow. */+ /* */+ static Bool+ Insert_Y_Turn( RAS_ARGS Int y )+ {+ PLong y_turns;+ Int y2, n;+++ n = ras.numTurns - 1;+ y_turns = ras.sizeBuff - ras.numTurns;++ /* look for first y value that is <= */+ while ( n >= 0 && y < y_turns[n] )+ n--;++ /* if it is <, simply insert it, ignore if == */+ if ( n >= 0 && y > y_turns[n] )+ while ( n >= 0 )+ {+ y2 = (Int)y_turns[n];+ y_turns[n] = y;+ y = y2;+ n--;+ }++ if ( n < 0 )+ {+ ras.maxBuff--;+ if ( ras.maxBuff <= ras.top )+ {+ ras.error = Raster_Err_Overflow;+ return FAILURE;+ }+ ras.numTurns++;+ ras.sizeBuff[-ras.numTurns] = y;+ }++ return SUCCESS;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Finalize_Profile_Table */+ /* */+ /* <Description> */+ /* Adjust all links in the profiles list. */+ /* */+ /* <Return> */+ /* SUCCESS on success. FAILURE in case of overflow. */+ /* */+ static Bool+ Finalize_Profile_Table( RAS_ARG )+ {+ Int bottom, top;+ UShort n;+ PProfile p;+++ n = ras.num_Profs;+ p = ras.fProfile;++ if ( n > 1 && p )+ {+ while ( n > 0 )+ {+ if ( n > 1 )+ p->link = (PProfile)( p->offset + p->height );+ else+ p->link = NULL;++ if ( p->flags & Flow_Up )+ {+ bottom = (Int)p->start;+ top = (Int)( p->start + p->height - 1 );+ }+ else+ {+ bottom = (Int)( p->start - p->height + 1 );+ top = (Int)p->start;+ p->start = bottom;+ p->offset += p->height - 1;+ }++ if ( Insert_Y_Turn( RAS_VARS bottom ) ||+ Insert_Y_Turn( RAS_VARS top + 1 ) )+ return FAILURE;++ p = p->link;+ n--;+ }+ }+ else+ ras.fProfile = NULL;++ return SUCCESS;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Split_Conic */+ /* */+ /* <Description> */+ /* Subdivide one conic Bezier into two joint sub-arcs in the Bezier */+ /* stack. */+ /* */+ /* <Input> */+ /* None (subdivided Bezier is taken from the top of the stack). */+ /* */+ /* <Note> */+ /* This routine is the `beef' of this component. It is _the_ inner */+ /* loop that should be optimized to hell to get the best performance. */+ /* */+ static void+ Split_Conic( TPoint* base )+ {+ Long a, b;+++ base[4].x = base[2].x;+ b = base[1].x;+ a = base[3].x = ( base[2].x + b ) / 2;+ b = base[1].x = ( base[0].x + b ) / 2;+ base[2].x = ( a + b ) / 2;++ base[4].y = base[2].y;+ b = base[1].y;+ a = base[3].y = ( base[2].y + b ) / 2;+ b = base[1].y = ( base[0].y + b ) / 2;+ base[2].y = ( a + b ) / 2;++ /* hand optimized. gcc doesn't seem to be too good at common */+ /* expression substitution and instruction scheduling ;-) */+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Split_Cubic */+ /* */+ /* <Description> */+ /* Subdivide a third-order Bezier arc into two joint sub-arcs in the */+ /* Bezier stack. */+ /* */+ /* <Note> */+ /* This routine is the `beef' of the component. It is one of _the_ */+ /* inner loops that should be optimized like hell to get the best */+ /* performance. */+ /* */+ static void+ Split_Cubic( TPoint* base )+ {+ Long a, b, c, d;+++ base[6].x = base[3].x;+ c = base[1].x;+ d = base[2].x;+ base[1].x = a = ( base[0].x + c + 1 ) >> 1;+ base[5].x = b = ( base[3].x + d + 1 ) >> 1;+ c = ( c + d + 1 ) >> 1;+ base[2].x = a = ( a + c + 1 ) >> 1;+ base[4].x = b = ( b + c + 1 ) >> 1;+ base[3].x = ( a + b + 1 ) >> 1;++ base[6].y = base[3].y;+ c = base[1].y;+ d = base[2].y;+ base[1].y = a = ( base[0].y + c + 1 ) >> 1;+ base[5].y = b = ( base[3].y + d + 1 ) >> 1;+ c = ( c + d + 1 ) >> 1;+ base[2].y = a = ( a + c + 1 ) >> 1;+ base[4].y = b = ( b + c + 1 ) >> 1;+ base[3].y = ( a + b + 1 ) >> 1;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Line_Up */+ /* */+ /* <Description> */+ /* Compute the x-coordinates of an ascending line segment and store */+ /* them in the render pool. */+ /* */+ /* <Input> */+ /* x1 :: The x-coordinate of the segment's start point. */+ /* */+ /* y1 :: The y-coordinate of the segment's start point. */+ /* */+ /* x2 :: The x-coordinate of the segment's end point. */+ /* */+ /* y2 :: The y-coordinate of the segment's end point. */+ /* */+ /* miny :: A lower vertical clipping bound value. */+ /* */+ /* maxy :: An upper vertical clipping bound value. */+ /* */+ /* <Return> */+ /* SUCCESS on success, FAILURE on render pool overflow. */+ /* */+ static Bool+ Line_Up( RAS_ARGS Long x1,+ Long y1,+ Long x2,+ Long y2,+ Long miny,+ Long maxy )+ {+ Long Dx, Dy;+ Int e1, e2, f1, f2, size; /* XXX: is `Short' sufficient? */+ Long Ix, Rx, Ax;++ PLong top;+++ Dx = x2 - x1;+ Dy = y2 - y1;++ if ( Dy <= 0 || y2 < miny || y1 > maxy )+ return SUCCESS;++ if ( y1 < miny )+ {+ /* Take care: miny-y1 can be a very large value; we use */+ /* a slow MulDiv function to avoid clipping bugs */+ x1 += SMulDiv( Dx, miny - y1, Dy );+ e1 = (Int)TRUNC( miny );+ f1 = 0;+ }+ else+ {+ e1 = (Int)TRUNC( y1 );+ f1 = (Int)FRAC( y1 );+ }++ if ( y2 > maxy )+ {+ /* x2 += FMulDiv( Dx, maxy - y2, Dy ); UNNECESSARY */+ e2 = (Int)TRUNC( maxy );+ f2 = 0;+ }+ else+ {+ e2 = (Int)TRUNC( y2 );+ f2 = (Int)FRAC( y2 );+ }++ if ( f1 > 0 )+ {+ if ( e1 == e2 )+ return SUCCESS;+ else+ {+ x1 += SMulDiv( Dx, ras.precision - f1, Dy );+ e1 += 1;+ }+ }+ else+ if ( ras.joint )+ {+ ras.top--;+ ras.joint = FALSE;+ }++ ras.joint = (char)( f2 == 0 );++ if ( ras.fresh )+ {+ ras.cProfile->start = e1;+ ras.fresh = FALSE;+ }++ size = e2 - e1 + 1;+ if ( ras.top + size >= ras.maxBuff )+ {+ ras.error = Raster_Err_Overflow;+ return FAILURE;+ }++ if ( Dx > 0 )+ {+ Ix = SMulDiv( ras.precision, Dx, Dy);+ Rx = ( ras.precision * Dx ) % Dy;+ Dx = 1;+ }+ else+ {+ Ix = SMulDiv( ras.precision, -Dx, Dy) * -1;+ Rx = ( ras.precision * -Dx ) % Dy;+ Dx = -1;+ }++ Ax = -Dy;+ top = ras.top;++ while ( size > 0 )+ {+ *top++ = x1;++ x1 += Ix;+ Ax += Rx;+ if ( Ax >= 0 )+ {+ Ax -= Dy;+ x1 += Dx;+ }+ size--;+ }++ ras.top = top;+ return SUCCESS;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Line_Down */+ /* */+ /* <Description> */+ /* Compute the x-coordinates of an descending line segment and store */+ /* them in the render pool. */+ /* */+ /* <Input> */+ /* x1 :: The x-coordinate of the segment's start point. */+ /* */+ /* y1 :: The y-coordinate of the segment's start point. */+ /* */+ /* x2 :: The x-coordinate of the segment's end point. */+ /* */+ /* y2 :: The y-coordinate of the segment's end point. */+ /* */+ /* miny :: A lower vertical clipping bound value. */+ /* */+ /* maxy :: An upper vertical clipping bound value. */+ /* */+ /* <Return> */+ /* SUCCESS on success, FAILURE on render pool overflow. */+ /* */+ static Bool+ Line_Down( RAS_ARGS Long x1,+ Long y1,+ Long x2,+ Long y2,+ Long miny,+ Long maxy )+ {+ Bool result, fresh;+++ fresh = ras.fresh;++ result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny );++ if ( fresh && !ras.fresh )+ ras.cProfile->start = -ras.cProfile->start;++ return result;+ }+++ /* A function type describing the functions used to split Bezier arcs */+ typedef void (*TSplitter)( TPoint* base );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Bezier_Up */+ /* */+ /* <Description> */+ /* Compute the x-coordinates of an ascending Bezier arc and store */+ /* them in the render pool. */+ /* */+ /* <Input> */+ /* degree :: The degree of the Bezier arc (either 2 or 3). */+ /* */+ /* splitter :: The function to split Bezier arcs. */+ /* */+ /* miny :: A lower vertical clipping bound value. */+ /* */+ /* maxy :: An upper vertical clipping bound value. */+ /* */+ /* <Return> */+ /* SUCCESS on success, FAILURE on render pool overflow. */+ /* */+ static Bool+ Bezier_Up( RAS_ARGS Int degree,+ TSplitter splitter,+ Long miny,+ Long maxy )+ {+ Long y1, y2, e, e2, e0;+ Short f1;++ TPoint* arc;+ TPoint* start_arc;++ PLong top;+++ arc = ras.arc;+ y1 = arc[degree].y;+ y2 = arc[0].y;+ top = ras.top;++ if ( y2 < miny || y1 > maxy )+ goto Fin;++ e2 = FLOOR( y2 );++ if ( e2 > maxy )+ e2 = maxy;++ e0 = miny;++ if ( y1 < miny )+ e = miny;+ else+ {+ e = CEILING( y1 );+ f1 = (Short)( FRAC( y1 ) );+ e0 = e;++ if ( f1 == 0 )+ {+ if ( ras.joint )+ {+ top--;+ ras.joint = FALSE;+ }++ *top++ = arc[degree].x;++ e += ras.precision;+ }+ }++ if ( ras.fresh )+ {+ ras.cProfile->start = TRUNC( e0 );+ ras.fresh = FALSE;+ }++ if ( e2 < e )+ goto Fin;++ if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff )+ {+ ras.top = top;+ ras.error = Raster_Err_Overflow;+ return FAILURE;+ }++ start_arc = arc;++ while ( arc >= start_arc && e <= e2 )+ {+ ras.joint = FALSE;++ y2 = arc[0].y;++ if ( y2 > e )+ {+ y1 = arc[degree].y;+ if ( y2 - y1 >= ras.precision_step )+ {+ splitter( arc );+ arc += degree;+ }+ else+ {+ *top++ = arc[degree].x + FMulDiv( arc[0].x - arc[degree].x,+ e - y1, y2 - y1 );+ arc -= degree;+ e += ras.precision;+ }+ }+ else+ {+ if ( y2 == e )+ {+ ras.joint = TRUE;+ *top++ = arc[0].x;++ e += ras.precision;+ }+ arc -= degree;+ }+ }++ Fin:+ ras.top = top;+ ras.arc -= degree;+ return SUCCESS;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Bezier_Down */+ /* */+ /* <Description> */+ /* Compute the x-coordinates of an descending Bezier arc and store */+ /* them in the render pool. */+ /* */+ /* <Input> */+ /* degree :: The degree of the Bezier arc (either 2 or 3). */+ /* */+ /* splitter :: The function to split Bezier arcs. */+ /* */+ /* miny :: A lower vertical clipping bound value. */+ /* */+ /* maxy :: An upper vertical clipping bound value. */+ /* */+ /* <Return> */+ /* SUCCESS on success, FAILURE on render pool overflow. */+ /* */+ static Bool+ Bezier_Down( RAS_ARGS Int degree,+ TSplitter splitter,+ Long miny,+ Long maxy )+ {+ TPoint* arc = ras.arc;+ Bool result, fresh;+++ arc[0].y = -arc[0].y;+ arc[1].y = -arc[1].y;+ arc[2].y = -arc[2].y;+ if ( degree > 2 )+ arc[3].y = -arc[3].y;++ fresh = ras.fresh;++ result = Bezier_Up( RAS_VARS degree, splitter, -maxy, -miny );++ if ( fresh && !ras.fresh )+ ras.cProfile->start = -ras.cProfile->start;++ arc[0].y = -arc[0].y;+ return result;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Line_To */+ /* */+ /* <Description> */+ /* Inject a new line segment and adjust the Profiles list. */+ /* */+ /* <Input> */+ /* x :: The x-coordinate of the segment's end point (its start point */+ /* is stored in `lastX'). */+ /* */+ /* y :: The y-coordinate of the segment's end point (its start point */+ /* is stored in `lastY'). */+ /* */+ /* <Return> */+ /* SUCCESS on success, FAILURE on render pool overflow or incorrect */+ /* profile. */+ /* */+ static Bool+ Line_To( RAS_ARGS Long x,+ Long y )+ {+ /* First, detect a change of direction */++ switch ( ras.state )+ {+ case Unknown_State:+ if ( y > ras.lastY )+ {+ if ( New_Profile( RAS_VARS Ascending_State,+ IS_BOTTOM_OVERSHOOT( ras.lastY ) ) )+ return FAILURE;+ }+ else+ {+ if ( y < ras.lastY )+ if ( New_Profile( RAS_VARS Descending_State,+ IS_TOP_OVERSHOOT( ras.lastY ) ) )+ return FAILURE;+ }+ break;++ case Ascending_State:+ if ( y < ras.lastY )+ {+ if ( End_Profile( RAS_VARS IS_TOP_OVERSHOOT( ras.lastY ) ) ||+ New_Profile( RAS_VARS Descending_State,+ IS_TOP_OVERSHOOT( ras.lastY ) ) )+ return FAILURE;+ }+ break;++ case Descending_State:+ if ( y > ras.lastY )+ {+ if ( End_Profile( RAS_VARS IS_BOTTOM_OVERSHOOT( ras.lastY ) ) ||+ New_Profile( RAS_VARS Ascending_State,+ IS_BOTTOM_OVERSHOOT( ras.lastY ) ) )+ return FAILURE;+ }+ break;++ default:+ ;+ }++ /* Then compute the lines */++ switch ( ras.state )+ {+ case Ascending_State:+ if ( Line_Up( RAS_VARS ras.lastX, ras.lastY,+ x, y, ras.minY, ras.maxY ) )+ return FAILURE;+ break;++ case Descending_State:+ if ( Line_Down( RAS_VARS ras.lastX, ras.lastY,+ x, y, ras.minY, ras.maxY ) )+ return FAILURE;+ break;++ default:+ ;+ }++ ras.lastX = x;+ ras.lastY = y;++ return SUCCESS;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Conic_To */+ /* */+ /* <Description> */+ /* Inject a new conic arc and adjust the profile list. */+ /* */+ /* <Input> */+ /* cx :: The x-coordinate of the arc's new control point. */+ /* */+ /* cy :: The y-coordinate of the arc's new control point. */+ /* */+ /* x :: The x-coordinate of the arc's end point (its start point is */+ /* stored in `lastX'). */+ /* */+ /* y :: The y-coordinate of the arc's end point (its start point is */+ /* stored in `lastY'). */+ /* */+ /* <Return> */+ /* SUCCESS on success, FAILURE on render pool overflow or incorrect */+ /* profile. */+ /* */+ static Bool+ Conic_To( RAS_ARGS Long cx,+ Long cy,+ Long x,+ Long y )+ {+ Long y1, y2, y3, x3, ymin, ymax;+ TStates state_bez;+++ ras.arc = ras.arcs;+ ras.arc[2].x = ras.lastX;+ ras.arc[2].y = ras.lastY;+ ras.arc[1].x = cx;+ ras.arc[1].y = cy;+ ras.arc[0].x = x;+ ras.arc[0].y = y;++ do+ {+ y1 = ras.arc[2].y;+ y2 = ras.arc[1].y;+ y3 = ras.arc[0].y;+ x3 = ras.arc[0].x;++ /* first, categorize the Bezier arc */++ if ( y1 <= y3 )+ {+ ymin = y1;+ ymax = y3;+ }+ else+ {+ ymin = y3;+ ymax = y1;+ }++ if ( y2 < ymin || y2 > ymax )+ {+ /* this arc has no given direction, split it! */+ Split_Conic( ras.arc );+ ras.arc += 2;+ }+ else if ( y1 == y3 )+ {+ /* this arc is flat, ignore it and pop it from the Bezier stack */+ ras.arc -= 2;+ }+ else+ {+ /* the arc is y-monotonous, either ascending or descending */+ /* detect a change of direction */+ state_bez = y1 < y3 ? Ascending_State : Descending_State;+ if ( ras.state != state_bez )+ {+ Bool o = state_bez == Ascending_State ? IS_BOTTOM_OVERSHOOT( y1 )+ : IS_TOP_OVERSHOOT( y1 );+++ /* finalize current profile if any */+ if ( ras.state != Unknown_State &&+ End_Profile( RAS_VARS o ) )+ goto Fail;++ /* create a new profile */+ if ( New_Profile( RAS_VARS state_bez, o ) )+ goto Fail;+ }++ /* now call the appropriate routine */+ if ( state_bez == Ascending_State )+ {+ if ( Bezier_Up( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )+ goto Fail;+ }+ else+ if ( Bezier_Down( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )+ goto Fail;+ }++ } while ( ras.arc >= ras.arcs );++ ras.lastX = x3;+ ras.lastY = y3;++ return SUCCESS;++ Fail:+ return FAILURE;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Cubic_To */+ /* */+ /* <Description> */+ /* Inject a new cubic arc and adjust the profile list. */+ /* */+ /* <Input> */+ /* cx1 :: The x-coordinate of the arc's first new control point. */+ /* */+ /* cy1 :: The y-coordinate of the arc's first new control point. */+ /* */+ /* cx2 :: The x-coordinate of the arc's second new control point. */+ /* */+ /* cy2 :: The y-coordinate of the arc's second new control point. */+ /* */+ /* x :: The x-coordinate of the arc's end point (its start point is */+ /* stored in `lastX'). */+ /* */+ /* y :: The y-coordinate of the arc's end point (its start point is */+ /* stored in `lastY'). */+ /* */+ /* <Return> */+ /* SUCCESS on success, FAILURE on render pool overflow or incorrect */+ /* profile. */+ /* */+ static Bool+ Cubic_To( RAS_ARGS Long cx1,+ Long cy1,+ Long cx2,+ Long cy2,+ Long x,+ Long y )+ {+ Long y1, y2, y3, y4, x4, ymin1, ymax1, ymin2, ymax2;+ TStates state_bez;+++ ras.arc = ras.arcs;+ ras.arc[3].x = ras.lastX;+ ras.arc[3].y = ras.lastY;+ ras.arc[2].x = cx1;+ ras.arc[2].y = cy1;+ ras.arc[1].x = cx2;+ ras.arc[1].y = cy2;+ ras.arc[0].x = x;+ ras.arc[0].y = y;++ do+ {+ y1 = ras.arc[3].y;+ y2 = ras.arc[2].y;+ y3 = ras.arc[1].y;+ y4 = ras.arc[0].y;+ x4 = ras.arc[0].x;++ /* first, categorize the Bezier arc */++ if ( y1 <= y4 )+ {+ ymin1 = y1;+ ymax1 = y4;+ }+ else+ {+ ymin1 = y4;+ ymax1 = y1;+ }++ if ( y2 <= y3 )+ {+ ymin2 = y2;+ ymax2 = y3;+ }+ else+ {+ ymin2 = y3;+ ymax2 = y2;+ }++ if ( ymin2 < ymin1 || ymax2 > ymax1 )+ {+ /* this arc has no given direction, split it! */+ Split_Cubic( ras.arc );+ ras.arc += 3;+ }+ else if ( y1 == y4 )+ {+ /* this arc is flat, ignore it and pop it from the Bezier stack */+ ras.arc -= 3;+ }+ else+ {+ state_bez = ( y1 <= y4 ) ? Ascending_State : Descending_State;++ /* detect a change of direction */+ if ( ras.state != state_bez )+ {+ Bool o = state_bez == Ascending_State ? IS_BOTTOM_OVERSHOOT( y1 )+ : IS_TOP_OVERSHOOT( y1 );+++ /* finalize current profile if any */+ if ( ras.state != Unknown_State &&+ End_Profile( RAS_VARS o ) )+ goto Fail;++ if ( New_Profile( RAS_VARS state_bez, o ) )+ goto Fail;+ }++ /* compute intersections */+ if ( state_bez == Ascending_State )+ {+ if ( Bezier_Up( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )+ goto Fail;+ }+ else+ if ( Bezier_Down( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )+ goto Fail;+ }++ } while ( ras.arc >= ras.arcs );++ ras.lastX = x4;+ ras.lastY = y4;++ return SUCCESS;++ Fail:+ return FAILURE;+ }+++#undef SWAP_+#define SWAP_( x, y ) do \+ { \+ Long swap = x; \+ \+ \+ x = y; \+ y = swap; \+ } while ( 0 )+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Decompose_Curve */+ /* */+ /* <Description> */+ /* Scan the outline arrays in order to emit individual segments and */+ /* Beziers by calling Line_To() and Bezier_To(). It handles all */+ /* weird cases, like when the first point is off the curve, or when */+ /* there are simply no `on' points in the contour! */+ /* */+ /* <Input> */+ /* first :: The index of the first point in the contour. */+ /* */+ /* last :: The index of the last point in the contour. */+ /* */+ /* flipped :: If set, flip the direction of the curve. */+ /* */+ /* <Return> */+ /* SUCCESS on success, FAILURE on error. */+ /* */+ static Bool+ Decompose_Curve( RAS_ARGS UShort first,+ UShort last,+ int flipped )+ {+ FT_Vector v_last;+ FT_Vector v_control;+ FT_Vector v_start;++ FT_Vector* points;+ FT_Vector* point;+ FT_Vector* limit;+ char* tags;++ unsigned tag; /* current point's state */+++ points = ras.outline.points;+ limit = points + last;++ v_start.x = SCALED( points[first].x );+ v_start.y = SCALED( points[first].y );+ v_last.x = SCALED( points[last].x );+ v_last.y = SCALED( points[last].y );++ if ( flipped )+ {+ SWAP_( v_start.x, v_start.y );+ SWAP_( v_last.x, v_last.y );+ }++ v_control = v_start;++ point = points + first;+ tags = ras.outline.tags + first;++ /* set scan mode if necessary */+ if ( tags[0] & FT_CURVE_TAG_HAS_SCANMODE )+ ras.dropOutControl = (Byte)tags[0] >> 5;++ tag = FT_CURVE_TAG( tags[0] );++ /* A contour cannot start with a cubic control point! */+ if ( tag == FT_CURVE_TAG_CUBIC )+ goto Invalid_Outline;++ /* check first point to determine origin */+ if ( tag == FT_CURVE_TAG_CONIC )+ {+ /* first point is conic control. Yes, this happens. */+ if ( FT_CURVE_TAG( ras.outline.tags[last] ) == FT_CURVE_TAG_ON )+ {+ /* start at last point if it is on the curve */+ v_start = v_last;+ limit--;+ }+ else+ {+ /* if both first and last points are conic, */+ /* start at their middle and record its position */+ /* for closure */+ v_start.x = ( v_start.x + v_last.x ) / 2;+ v_start.y = ( v_start.y + v_last.y ) / 2;++ v_last = v_start;+ }+ point--;+ tags--;+ }++ ras.lastX = v_start.x;+ ras.lastY = v_start.y;++ while ( point < limit )+ {+ point++;+ tags++;++ tag = FT_CURVE_TAG( tags[0] );++ switch ( tag )+ {+ case FT_CURVE_TAG_ON: /* emit a single line_to */+ {+ Long x, y;+++ x = SCALED( point->x );+ y = SCALED( point->y );+ if ( flipped )+ SWAP_( x, y );++ if ( Line_To( RAS_VARS x, y ) )+ goto Fail;+ continue;+ }++ case FT_CURVE_TAG_CONIC: /* consume conic arcs */+ v_control.x = SCALED( point[0].x );+ v_control.y = SCALED( point[0].y );++ if ( flipped )+ SWAP_( v_control.x, v_control.y );++ Do_Conic:+ if ( point < limit )+ {+ FT_Vector v_middle;+ Long x, y;+++ point++;+ tags++;+ tag = FT_CURVE_TAG( tags[0] );++ x = SCALED( point[0].x );+ y = SCALED( point[0].y );++ if ( flipped )+ SWAP_( x, y );++ if ( tag == FT_CURVE_TAG_ON )+ {+ if ( Conic_To( RAS_VARS v_control.x, v_control.y, x, y ) )+ goto Fail;+ continue;+ }++ if ( tag != FT_CURVE_TAG_CONIC )+ goto Invalid_Outline;++ v_middle.x = ( v_control.x + x ) / 2;+ v_middle.y = ( v_control.y + y ) / 2;++ if ( Conic_To( RAS_VARS v_control.x, v_control.y,+ v_middle.x, v_middle.y ) )+ goto Fail;++ v_control.x = x;+ v_control.y = y;++ goto Do_Conic;+ }++ if ( Conic_To( RAS_VARS v_control.x, v_control.y,+ v_start.x, v_start.y ) )+ goto Fail;++ goto Close;++ default: /* FT_CURVE_TAG_CUBIC */+ {+ Long x1, y1, x2, y2, x3, y3;+++ if ( point + 1 > limit ||+ FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )+ goto Invalid_Outline;++ point += 2;+ tags += 2;++ x1 = SCALED( point[-2].x );+ y1 = SCALED( point[-2].y );+ x2 = SCALED( point[-1].x );+ y2 = SCALED( point[-1].y );++ if ( flipped )+ {+ SWAP_( x1, y1 );+ SWAP_( x2, y2 );+ }++ if ( point <= limit )+ {+ x3 = SCALED( point[0].x );+ y3 = SCALED( point[0].y );++ if ( flipped )+ SWAP_( x3, y3 );++ if ( Cubic_To( RAS_VARS x1, y1, x2, y2, x3, y3 ) )+ goto Fail;+ continue;+ }++ if ( Cubic_To( RAS_VARS x1, y1, x2, y2, v_start.x, v_start.y ) )+ goto Fail;+ goto Close;+ }+ }+ }++ /* close the contour with a line segment */+ if ( Line_To( RAS_VARS v_start.x, v_start.y ) )+ goto Fail;++ Close:+ return SUCCESS;++ Invalid_Outline:+ ras.error = Raster_Err_Invalid;++ Fail:+ return FAILURE;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Convert_Glyph */+ /* */+ /* <Description> */+ /* Convert a glyph into a series of segments and arcs and make a */+ /* profiles list with them. */+ /* */+ /* <Input> */+ /* flipped :: If set, flip the direction of curve. */+ /* */+ /* <Return> */+ /* SUCCESS on success, FAILURE if any error was encountered during */+ /* rendering. */+ /* */+ static Bool+ Convert_Glyph( RAS_ARGS int flipped )+ {+ int i;+ unsigned start;++ PProfile lastProfile;+++ ras.fProfile = NULL;+ ras.joint = FALSE;+ ras.fresh = FALSE;++ ras.maxBuff = ras.sizeBuff - AlignProfileSize;++ ras.numTurns = 0;++ ras.cProfile = (PProfile)ras.top;+ ras.cProfile->offset = ras.top;+ ras.num_Profs = 0;++ start = 0;++ for ( i = 0; i < ras.outline.n_contours; i++ )+ {+ Bool o;+++ ras.state = Unknown_State;+ ras.gProfile = NULL;++ if ( Decompose_Curve( RAS_VARS (unsigned short)start,+ ras.outline.contours[i],+ flipped ) )+ return FAILURE;++ start = ras.outline.contours[i] + 1;++ /* we must now check whether the extreme arcs join or not */+ if ( FRAC( ras.lastY ) == 0 &&+ ras.lastY >= ras.minY &&+ ras.lastY <= ras.maxY )+ if ( ras.gProfile &&+ ( ras.gProfile->flags & Flow_Up ) ==+ ( ras.cProfile->flags & Flow_Up ) )+ ras.top--;+ /* Note that ras.gProfile can be nil if the contour was too small */+ /* to be drawn. */++ lastProfile = ras.cProfile;+ if ( ras.cProfile->flags & Flow_Up )+ o = IS_TOP_OVERSHOOT( ras.lastY );+ else+ o = IS_BOTTOM_OVERSHOOT( ras.lastY );+ if ( End_Profile( RAS_VARS o ) )+ return FAILURE;++ /* close the `next profile in contour' linked list */+ if ( ras.gProfile )+ lastProfile->next = ras.gProfile;+ }++ if ( Finalize_Profile_Table( RAS_VAR ) )+ return FAILURE;++ return (Bool)( ras.top < ras.maxBuff ? SUCCESS : FAILURE );+ }+++ /*************************************************************************/+ /*************************************************************************/+ /** **/+ /** SCAN-LINE SWEEPS AND DRAWING **/+ /** **/+ /*************************************************************************/+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* Init_Linked */+ /* */+ /* Initializes an empty linked list. */+ /* */+ static void+ Init_Linked( TProfileList* l )+ {+ *l = NULL;+ }+++ /*************************************************************************/+ /* */+ /* InsNew */+ /* */+ /* Inserts a new profile in a linked list. */+ /* */+ static void+ InsNew( PProfileList list,+ PProfile profile )+ {+ PProfile *old, current;+ Long x;+++ old = list;+ current = *old;+ x = profile->X;++ while ( current )+ {+ if ( x < current->X )+ break;+ old = ¤t->link;+ current = *old;+ }++ profile->link = current;+ *old = profile;+ }+++ /*************************************************************************/+ /* */+ /* DelOld */+ /* */+ /* Removes an old profile from a linked list. */+ /* */+ static void+ DelOld( PProfileList list,+ PProfile profile )+ {+ PProfile *old, current;+++ old = list;+ current = *old;++ while ( current )+ {+ if ( current == profile )+ {+ *old = current->link;+ return;+ }++ old = ¤t->link;+ current = *old;+ }++ /* we should never get there, unless the profile was not part of */+ /* the list. */+ }+++ /*************************************************************************/+ /* */+ /* Sort */+ /* */+ /* Sorts a trace list. In 95%, the list is already sorted. We need */+ /* an algorithm which is fast in this case. Bubble sort is enough */+ /* and simple. */+ /* */+ static void+ Sort( PProfileList list )+ {+ PProfile *old, current, next;+++ /* First, set the new X coordinate of each profile */+ current = *list;+ while ( current )+ {+ current->X = *current->offset;+ current->offset += current->flags & Flow_Up ? 1 : -1;+ current->height--;+ current = current->link;+ }++ /* Then sort them */+ old = list;+ current = *old;++ if ( !current )+ return;++ next = current->link;++ while ( next )+ {+ if ( current->X <= next->X )+ {+ old = ¤t->link;+ current = *old;++ if ( !current )+ return;+ }+ else+ {+ *old = next;+ current->link = next->link;+ next->link = current;++ old = list;+ current = *old;+ }++ next = current->link;+ }+ }+++ /*************************************************************************/+ /* */+ /* Vertical Sweep Procedure Set */+ /* */+ /* These four routines are used during the vertical black/white sweep */+ /* phase by the generic Draw_Sweep() function. */+ /* */+ /*************************************************************************/++ static void+ Vertical_Sweep_Init( RAS_ARGS Short* min,+ Short* max )+ {+ Long pitch = ras.target.pitch;++ FT_UNUSED( max );+++ ras.traceIncr = (Short)-pitch;+ ras.traceOfs = -*min * pitch;+ if ( pitch > 0 )+ ras.traceOfs += ( ras.target.rows - 1 ) * pitch;++ ras.gray_min_x = 0;+ ras.gray_max_x = 0;+ }+++ static void+ Vertical_Sweep_Span( RAS_ARGS Short y,+ FT_F26Dot6 x1,+ FT_F26Dot6 x2,+ PProfile left,+ PProfile right )+ {+ Long e1, e2;+ int c1, c2;+ Byte f1, f2;+ Byte* target;++ FT_UNUSED( y );+ FT_UNUSED( left );+ FT_UNUSED( right );+++ /* Drop-out control */++ e1 = TRUNC( CEILING( x1 ) );++ if ( x2 - x1 - ras.precision <= ras.precision_jitter )+ e2 = e1;+ else+ e2 = TRUNC( FLOOR( x2 ) );++ if ( e2 >= 0 && e1 < ras.bWidth )+ {+ if ( e1 < 0 )+ e1 = 0;+ if ( e2 >= ras.bWidth )+ e2 = ras.bWidth - 1;++ c1 = (Short)( e1 >> 3 );+ c2 = (Short)( e2 >> 3 );++ f1 = (Byte) ( 0xFF >> ( e1 & 7 ) );+ f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) );++ if ( ras.gray_min_x > c1 )+ ras.gray_min_x = (short)c1;+ if ( ras.gray_max_x < c2 )+ ras.gray_max_x = (short)c2;++ target = ras.bTarget + ras.traceOfs + c1;+ c2 -= c1;++ if ( c2 > 0 )+ {+ target[0] |= f1;++ /* memset() is slower than the following code on many platforms. */+ /* This is due to the fact that, in the vast majority of cases, */+ /* the span length in bytes is relatively small. */+ c2--;+ while ( c2 > 0 )+ {+ *(++target) = 0xFF;+ c2--;+ }+ target[1] |= f2;+ }+ else+ *target |= ( f1 & f2 );+ }+ }+++ static void+ Vertical_Sweep_Drop( RAS_ARGS Short y,+ FT_F26Dot6 x1,+ FT_F26Dot6 x2,+ PProfile left,+ PProfile right )+ {+ Long e1, e2, pxl;+ Short c1, f1;+++ /* Drop-out control */++ /* e2 x2 x1 e1 */+ /* */+ /* ^ | */+ /* | | */+ /* +-------------+---------------------+------------+ */+ /* | | */+ /* | v */+ /* */+ /* pixel contour contour pixel */+ /* center center */++ /* drop-out mode scan conversion rules (as defined in OpenType) */+ /* --------------------------------------------------------------- */+ /* 0 1, 2, 3 */+ /* 1 1, 2, 4 */+ /* 2 1, 2 */+ /* 3 same as mode 2 */+ /* 4 1, 2, 5 */+ /* 5 1, 2, 6 */+ /* 6, 7 same as mode 2 */++ e1 = CEILING( x1 );+ e2 = FLOOR ( x2 );+ pxl = e1;++ if ( e1 > e2 )+ {+ Int dropOutControl = left->flags & 7;+++ if ( e1 == e2 + ras.precision )+ {+ switch ( dropOutControl )+ {+ case 0: /* simple drop-outs including stubs */+ pxl = e2;+ break;++ case 4: /* smart drop-outs including stubs */+ pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );+ break;++ case 1: /* simple drop-outs excluding stubs */+ case 5: /* smart drop-outs excluding stubs */++ /* Drop-out Control Rules #4 and #6 */++ /* The specification neither provides an exact definition */+ /* of a `stub' nor gives exact rules to exclude them. */+ /* */+ /* Here the constraints we use to recognize a stub. */+ /* */+ /* upper stub: */+ /* */+ /* - P_Left and P_Right are in the same contour */+ /* - P_Right is the successor of P_Left in that contour */+ /* - y is the top of P_Left and P_Right */+ /* */+ /* lower stub: */+ /* */+ /* - P_Left and P_Right are in the same contour */+ /* - P_Left is the successor of P_Right in that contour */+ /* - y is the bottom of P_Left */+ /* */+ /* We draw a stub if the following constraints are met. */+ /* */+ /* - for an upper or lower stub, there is top or bottom */+ /* overshoot, respectively */+ /* - the covered interval is greater or equal to a half */+ /* pixel */++ /* upper stub test */+ if ( left->next == right &&+ left->height <= 0 &&+ !( left->flags & Overshoot_Top &&+ x2 - x1 >= ras.precision_half ) )+ return;++ /* lower stub test */+ if ( right->next == left &&+ left->start == y &&+ !( left->flags & Overshoot_Bottom &&+ x2 - x1 >= ras.precision_half ) )+ return;++ if ( dropOutControl == 1 )+ pxl = e2;+ else+ pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );+ break;++ default: /* modes 2, 3, 6, 7 */+ return; /* no drop-out control */+ }++ /* check that the other pixel isn't set */+ e1 = pxl == e1 ? e2 : e1;++ e1 = TRUNC( e1 );++ c1 = (Short)( e1 >> 3 );+ f1 = (Short)( e1 & 7 );++ if ( e1 >= 0 && e1 < ras.bWidth &&+ ras.bTarget[ras.traceOfs + c1] & ( 0x80 >> f1 ) )+ return;+ }+ else+ return;+ }++ e1 = TRUNC( pxl );++ if ( e1 >= 0 && e1 < ras.bWidth )+ {+ c1 = (Short)( e1 >> 3 );+ f1 = (Short)( e1 & 7 );++ if ( ras.gray_min_x > c1 )+ ras.gray_min_x = c1;+ if ( ras.gray_max_x < c1 )+ ras.gray_max_x = c1;++ ras.bTarget[ras.traceOfs + c1] |= (char)( 0x80 >> f1 );+ }+ }+++ static void+ Vertical_Sweep_Step( RAS_ARG )+ {+ ras.traceOfs += ras.traceIncr;+ }+++ /***********************************************************************/+ /* */+ /* Horizontal Sweep Procedure Set */+ /* */+ /* These four routines are used during the horizontal black/white */+ /* sweep phase by the generic Draw_Sweep() function. */+ /* */+ /***********************************************************************/++ static void+ Horizontal_Sweep_Init( RAS_ARGS Short* min,+ Short* max )+ {+ /* nothing, really */+ FT_UNUSED_RASTER;+ FT_UNUSED( min );+ FT_UNUSED( max );+ }+++ static void+ Horizontal_Sweep_Span( RAS_ARGS Short y,+ FT_F26Dot6 x1,+ FT_F26Dot6 x2,+ PProfile left,+ PProfile right )+ {+ Long e1, e2;+ PByte bits;+ Byte f1;++ FT_UNUSED( left );+ FT_UNUSED( right );+++ if ( x2 - x1 < ras.precision )+ {+ e1 = CEILING( x1 );+ e2 = FLOOR ( x2 );++ if ( e1 == e2 )+ {+ bits = ras.bTarget + ( y >> 3 );+ f1 = (Byte)( 0x80 >> ( y & 7 ) );++ e1 = TRUNC( e1 );++ if ( e1 >= 0 && e1 < ras.target.rows )+ {+ PByte p;+++ p = bits - e1 * ras.target.pitch;+ if ( ras.target.pitch > 0 )+ p += ( ras.target.rows - 1 ) * ras.target.pitch;++ p[0] |= f1;+ }+ }+ }+ }+++ static void+ Horizontal_Sweep_Drop( RAS_ARGS Short y,+ FT_F26Dot6 x1,+ FT_F26Dot6 x2,+ PProfile left,+ PProfile right )+ {+ Long e1, e2, pxl;+ PByte bits;+ Byte f1;+++ /* During the horizontal sweep, we only take care of drop-outs */++ /* e1 + <-- pixel center */+ /* | */+ /* x1 ---+--> <-- contour */+ /* | */+ /* | */+ /* x2 <--+--- <-- contour */+ /* | */+ /* | */+ /* e2 + <-- pixel center */++ e1 = CEILING( x1 );+ e2 = FLOOR ( x2 );+ pxl = e1;++ if ( e1 > e2 )+ {+ Int dropOutControl = left->flags & 7;+++ if ( e1 == e2 + ras.precision )+ {+ switch ( dropOutControl )+ {+ case 0: /* simple drop-outs including stubs */+ pxl = e2;+ break;++ case 4: /* smart drop-outs including stubs */+ pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );+ break;++ case 1: /* simple drop-outs excluding stubs */+ case 5: /* smart drop-outs excluding stubs */+ /* see Vertical_Sweep_Drop for details */++ /* rightmost stub test */+ if ( left->next == right &&+ left->height <= 0 &&+ !( left->flags & Overshoot_Top &&+ x2 - x1 >= ras.precision_half ) )+ return;++ /* leftmost stub test */+ if ( right->next == left &&+ left->start == y &&+ !( left->flags & Overshoot_Bottom &&+ x2 - x1 >= ras.precision_half ) )+ return;++ if ( dropOutControl == 1 )+ pxl = e2;+ else+ pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );+ break;++ default: /* modes 2, 3, 6, 7 */+ return; /* no drop-out control */+ }++ /* check that the other pixel isn't set */+ e1 = pxl == e1 ? e2 : e1;++ e1 = TRUNC( e1 );++ bits = ras.bTarget + ( y >> 3 );+ f1 = (Byte)( 0x80 >> ( y & 7 ) );++ bits -= e1 * ras.target.pitch;+ if ( ras.target.pitch > 0 )+ bits += ( ras.target.rows - 1 ) * ras.target.pitch;++ if ( e1 >= 0 &&+ e1 < ras.target.rows &&+ *bits & f1 )+ return;+ }+ else+ return;+ }++ bits = ras.bTarget + ( y >> 3 );+ f1 = (Byte)( 0x80 >> ( y & 7 ) );++ e1 = TRUNC( pxl );++ if ( e1 >= 0 && e1 < ras.target.rows )+ {+ bits -= e1 * ras.target.pitch;+ if ( ras.target.pitch > 0 )+ bits += ( ras.target.rows - 1 ) * ras.target.pitch;++ bits[0] |= f1;+ }+ }+++ static void+ Horizontal_Sweep_Step( RAS_ARG )+ {+ /* Nothing, really */+ FT_UNUSED_RASTER;+ }+++#ifdef FT_RASTER_OPTION_ANTI_ALIASING+++ /*************************************************************************/+ /* */+ /* Vertical Gray Sweep Procedure Set */+ /* */+ /* These two routines are used during the vertical gray-levels sweep */+ /* phase by the generic Draw_Sweep() function. */+ /* */+ /* NOTES */+ /* */+ /* - The target pixmap's width *must* be a multiple of 4. */+ /* */+ /* - You have to use the function Vertical_Sweep_Span() for the gray */+ /* span call. */+ /* */+ /*************************************************************************/++ static void+ Vertical_Gray_Sweep_Init( RAS_ARGS Short* min,+ Short* max )+ {+ Long pitch, byte_len;+++ *min = *min & -2;+ *max = ( *max + 3 ) & -2;++ ras.traceOfs = 0;+ pitch = ras.target.pitch;+ byte_len = -pitch;+ ras.traceIncr = (Short)byte_len;+ ras.traceG = ( *min / 2 ) * byte_len;++ if ( pitch > 0 )+ {+ ras.traceG += ( ras.target.rows - 1 ) * pitch;+ byte_len = -byte_len;+ }++ ras.gray_min_x = (Short)byte_len;+ ras.gray_max_x = -(Short)byte_len;+ }+++ static void+ Vertical_Gray_Sweep_Step( RAS_ARG )+ {+ Int c1, c2;+ PByte pix, bit, bit2;+ short* count = (short*)count_table;+ Byte* grays;+++ ras.traceOfs += ras.gray_width;++ if ( ras.traceOfs > ras.gray_width )+ {+ pix = ras.gTarget + ras.traceG + ras.gray_min_x * 4;+ grays = ras.grays;++ if ( ras.gray_max_x >= 0 )+ {+ Long last_pixel = ras.target.width - 1;+ Int last_cell = last_pixel >> 2;+ Int last_bit = last_pixel & 3;+ Bool over = 0;+++ if ( ras.gray_max_x >= last_cell && last_bit != 3 )+ {+ ras.gray_max_x = last_cell - 1;+ over = 1;+ }++ if ( ras.gray_min_x < 0 )+ ras.gray_min_x = 0;++ bit = ras.bTarget + ras.gray_min_x;+ bit2 = bit + ras.gray_width;++ c1 = ras.gray_max_x - ras.gray_min_x;++ while ( c1 >= 0 )+ {+ c2 = count[*bit] + count[*bit2];++ if ( c2 )+ {+ pix[0] = grays[(c2 >> 12) & 0x000F];+ pix[1] = grays[(c2 >> 8 ) & 0x000F];+ pix[2] = grays[(c2 >> 4 ) & 0x000F];+ pix[3] = grays[ c2 & 0x000F];++ *bit = 0;+ *bit2 = 0;+ }++ bit++;+ bit2++;+ pix += 4;+ c1--;+ }++ if ( over )+ {+ c2 = count[*bit] + count[*bit2];+ if ( c2 )+ {+ switch ( last_bit )+ {+ case 2:+ pix[2] = grays[(c2 >> 4 ) & 0x000F];+ case 1:+ pix[1] = grays[(c2 >> 8 ) & 0x000F];+ default:+ pix[0] = grays[(c2 >> 12) & 0x000F];+ }++ *bit = 0;+ *bit2 = 0;+ }+ }+ }++ ras.traceOfs = 0;+ ras.traceG += ras.traceIncr;++ ras.gray_min_x = 32000;+ ras.gray_max_x = -32000;+ }+ }+++ static void+ Horizontal_Gray_Sweep_Span( RAS_ARGS Short y,+ FT_F26Dot6 x1,+ FT_F26Dot6 x2,+ PProfile left,+ PProfile right )+ {+ /* nothing, really */+ FT_UNUSED_RASTER;+ FT_UNUSED( y );+ FT_UNUSED( x1 );+ FT_UNUSED( x2 );+ FT_UNUSED( left );+ FT_UNUSED( right );+ }+++ static void+ Horizontal_Gray_Sweep_Drop( RAS_ARGS Short y,+ FT_F26Dot6 x1,+ FT_F26Dot6 x2,+ PProfile left,+ PProfile right )+ {+ Long e1, e2;+ PByte pixel;+ Byte color;+++ /* During the horizontal sweep, we only take care of drop-outs */++ e1 = CEILING( x1 );+ e2 = FLOOR ( x2 );++ if ( e1 > e2 )+ {+ Int dropOutControl = left->flags & 7;+++ if ( e1 == e2 + ras.precision )+ {+ switch ( dropOutControl )+ {+ case 0: /* simple drop-outs including stubs */+ e1 = e2;+ break;++ case 4: /* smart drop-outs including stubs */+ e1 = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );+ break;++ case 1: /* simple drop-outs excluding stubs */+ case 5: /* smart drop-outs excluding stubs */+ /* see Vertical_Sweep_Drop for details */++ /* rightmost stub test */+ if ( left->next == right && left->height <= 0 )+ return;++ /* leftmost stub test */+ if ( right->next == left && left->start == y )+ return;++ if ( dropOutControl == 1 )+ e1 = e2;+ else+ e1 = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );++ break;++ default: /* modes 2, 3, 6, 7 */+ return; /* no drop-out control */+ }+ }+ else+ return;+ }++ if ( e1 >= 0 )+ {+ if ( x2 - x1 >= ras.precision_half )+ color = ras.grays[2];+ else+ color = ras.grays[1];++ e1 = TRUNC( e1 ) / 2;+ if ( e1 < ras.target.rows )+ {+ pixel = ras.gTarget - e1 * ras.target.pitch + y / 2;+ if ( ras.target.pitch > 0 )+ pixel += ( ras.target.rows - 1 ) * ras.target.pitch;++ if ( pixel[0] == ras.grays[0] )+ pixel[0] = color;+ }+ }+ }+++#endif /* FT_RASTER_OPTION_ANTI_ALIASING */+++ /*************************************************************************/+ /* */+ /* Generic Sweep Drawing routine */+ /* */+ /*************************************************************************/++ static Bool+ Draw_Sweep( RAS_ARG )+ {+ Short y, y_change, y_height;++ PProfile P, Q, P_Left, P_Right;++ Short min_Y, max_Y, top, bottom, dropouts;++ Long x1, x2, xs, e1, e2;++ TProfileList waiting;+ TProfileList draw_left, draw_right;+++ /* initialize empty linked lists */++ Init_Linked( &waiting );++ Init_Linked( &draw_left );+ Init_Linked( &draw_right );++ /* first, compute min and max Y */++ P = ras.fProfile;+ max_Y = (Short)TRUNC( ras.minY );+ min_Y = (Short)TRUNC( ras.maxY );++ while ( P )+ {+ Q = P->link;++ bottom = (Short)P->start;+ top = (Short)( P->start + P->height - 1 );++ if ( min_Y > bottom )+ min_Y = bottom;+ if ( max_Y < top )+ max_Y = top;++ P->X = 0;+ InsNew( &waiting, P );++ P = Q;+ }++ /* check the Y-turns */+ if ( ras.numTurns == 0 )+ {+ ras.error = Raster_Err_Invalid;+ return FAILURE;+ }++ /* now initialize the sweep */++ ras.Proc_Sweep_Init( RAS_VARS &min_Y, &max_Y );++ /* then compute the distance of each profile from min_Y */++ P = waiting;++ while ( P )+ {+ P->countL = (UShort)( P->start - min_Y );+ P = P->link;+ }++ /* let's go */++ y = min_Y;+ y_height = 0;++ if ( ras.numTurns > 0 &&+ ras.sizeBuff[-ras.numTurns] == min_Y )+ ras.numTurns--;++ while ( ras.numTurns > 0 )+ {+ /* check waiting list for new activations */++ P = waiting;++ while ( P )+ {+ Q = P->link;+ P->countL -= y_height;+ if ( P->countL == 0 )+ {+ DelOld( &waiting, P );++ if ( P->flags & Flow_Up )+ InsNew( &draw_left, P );+ else+ InsNew( &draw_right, P );+ }++ P = Q;+ }++ /* sort the drawing lists */++ Sort( &draw_left );+ Sort( &draw_right );++ y_change = (Short)ras.sizeBuff[-ras.numTurns--];+ y_height = (Short)( y_change - y );++ while ( y < y_change )+ {+ /* let's trace */++ dropouts = 0;++ P_Left = draw_left;+ P_Right = draw_right;++ while ( P_Left )+ {+ x1 = P_Left ->X;+ x2 = P_Right->X;++ if ( x1 > x2 )+ {+ xs = x1;+ x1 = x2;+ x2 = xs;+ }++ e1 = FLOOR( x1 );+ e2 = CEILING( x2 );++ if ( x2 - x1 <= ras.precision &&+ e1 != x1 && e2 != x2 )+ {+ if ( e1 > e2 || e2 == e1 + ras.precision )+ {+ Int dropOutControl = P_Left->flags & 7;+++ if ( dropOutControl != 2 )+ {+ /* a drop-out was detected */++ P_Left ->X = x1;+ P_Right->X = x2;++ /* mark profile for drop-out processing */+ P_Left->countL = 1;+ dropouts++;+ }++ goto Skip_To_Next;+ }+ }++ ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right );++ Skip_To_Next:++ P_Left = P_Left->link;+ P_Right = P_Right->link;+ }++ /* handle drop-outs _after_ the span drawing -- */+ /* drop-out processing has been moved out of the loop */+ /* for performance tuning */+ if ( dropouts > 0 )+ goto Scan_DropOuts;++ Next_Line:++ ras.Proc_Sweep_Step( RAS_VAR );++ y++;++ if ( y < y_change )+ {+ Sort( &draw_left );+ Sort( &draw_right );+ }+ }++ /* now finalize the profiles that need it */++ P = draw_left;+ while ( P )+ {+ Q = P->link;+ if ( P->height == 0 )+ DelOld( &draw_left, P );+ P = Q;+ }++ P = draw_right;+ while ( P )+ {+ Q = P->link;+ if ( P->height == 0 )+ DelOld( &draw_right, P );+ P = Q;+ }+ }++ /* for gray-scaling, flush the bitmap scanline cache */+ while ( y <= max_Y )+ {+ ras.Proc_Sweep_Step( RAS_VAR );+ y++;+ }++ return SUCCESS;++ Scan_DropOuts:++ P_Left = draw_left;+ P_Right = draw_right;++ while ( P_Left )+ {+ if ( P_Left->countL )+ {+ P_Left->countL = 0;+#if 0+ dropouts--; /* -- this is useful when debugging only */+#endif+ ras.Proc_Sweep_Drop( RAS_VARS y,+ P_Left->X,+ P_Right->X,+ P_Left,+ P_Right );+ }++ P_Left = P_Left->link;+ P_Right = P_Right->link;+ }++ goto Next_Line;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Render_Single_Pass */+ /* */+ /* <Description> */+ /* Perform one sweep with sub-banding. */+ /* */+ /* <Input> */+ /* flipped :: If set, flip the direction of the outline. */+ /* */+ /* <Return> */+ /* Renderer error code. */+ /* */+ static int+ Render_Single_Pass( RAS_ARGS Bool flipped )+ {+ Short i, j, k;+++ while ( ras.band_top >= 0 )+ {+ ras.maxY = (Long)ras.band_stack[ras.band_top].y_max * ras.precision;+ ras.minY = (Long)ras.band_stack[ras.band_top].y_min * ras.precision;++ ras.top = ras.buff;++ ras.error = Raster_Err_None;++ if ( Convert_Glyph( RAS_VARS flipped ) )+ {+ if ( ras.error != Raster_Err_Overflow )+ return FAILURE;++ ras.error = Raster_Err_None;++ /* sub-banding */++#ifdef DEBUG_RASTER+ ClearBand( RAS_VARS TRUNC( ras.minY ), TRUNC( ras.maxY ) );+#endif++ i = ras.band_stack[ras.band_top].y_min;+ j = ras.band_stack[ras.band_top].y_max;++ k = (Short)( ( i + j ) / 2 );++ if ( ras.band_top >= 7 || k < i )+ {+ ras.band_top = 0;+ ras.error = Raster_Err_Invalid;++ return ras.error;+ }++ ras.band_stack[ras.band_top + 1].y_min = k;+ ras.band_stack[ras.band_top + 1].y_max = j;++ ras.band_stack[ras.band_top].y_max = (Short)( k - 1 );++ ras.band_top++;+ }+ else+ {+ if ( ras.fProfile )+ if ( Draw_Sweep( RAS_VAR ) )+ return ras.error;+ ras.band_top--;+ }+ }++ return SUCCESS;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Render_Glyph */+ /* */+ /* <Description> */+ /* Render a glyph in a bitmap. Sub-banding if needed. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ Render_Glyph( RAS_ARG )+ {+ FT_Error error;+++ Set_High_Precision( RAS_VARS ras.outline.flags &+ FT_OUTLINE_HIGH_PRECISION );+ ras.scale_shift = ras.precision_shift;++ if ( ras.outline.flags & FT_OUTLINE_IGNORE_DROPOUTS )+ ras.dropOutControl = 2;+ else+ {+ if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS )+ ras.dropOutControl = 4;+ else+ ras.dropOutControl = 0;++ if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) )+ ras.dropOutControl += 1;+ }++ ras.second_pass = (FT_Byte)( !( ras.outline.flags &+ FT_OUTLINE_SINGLE_PASS ) );++ /* Vertical Sweep */+ ras.Proc_Sweep_Init = Vertical_Sweep_Init;+ ras.Proc_Sweep_Span = Vertical_Sweep_Span;+ ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;+ ras.Proc_Sweep_Step = Vertical_Sweep_Step;++ ras.band_top = 0;+ ras.band_stack[0].y_min = 0;+ ras.band_stack[0].y_max = (short)( ras.target.rows - 1 );++ ras.bWidth = (unsigned short)ras.target.width;+ ras.bTarget = (Byte*)ras.target.buffer;++ if ( ( error = Render_Single_Pass( RAS_VARS 0 ) ) != 0 )+ return error;++ /* Horizontal Sweep */+ if ( ras.second_pass && ras.dropOutControl != 2 )+ {+ ras.Proc_Sweep_Init = Horizontal_Sweep_Init;+ ras.Proc_Sweep_Span = Horizontal_Sweep_Span;+ ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop;+ ras.Proc_Sweep_Step = Horizontal_Sweep_Step;++ ras.band_top = 0;+ ras.band_stack[0].y_min = 0;+ ras.band_stack[0].y_max = (short)( ras.target.width - 1 );++ if ( ( error = Render_Single_Pass( RAS_VARS 1 ) ) != 0 )+ return error;+ }++ return Raster_Err_None;+ }+++#ifdef FT_RASTER_OPTION_ANTI_ALIASING++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Render_Gray_Glyph */+ /* */+ /* <Description> */+ /* Render a glyph with grayscaling. Sub-banding if needed. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ Render_Gray_Glyph( RAS_ARG )+ {+ Long pixel_width;+ FT_Error error;+++ Set_High_Precision( RAS_VARS ras.outline.flags &+ FT_OUTLINE_HIGH_PRECISION );+ ras.scale_shift = ras.precision_shift + 1;++ if ( ras.outline.flags & FT_OUTLINE_IGNORE_DROPOUTS )+ ras.dropOutControl = 2;+ else+ {+ if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS )+ ras.dropOutControl = 4;+ else+ ras.dropOutControl = 0;++ if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) )+ ras.dropOutControl += 1;+ }++ ras.second_pass = !( ras.outline.flags & FT_OUTLINE_SINGLE_PASS );++ /* Vertical Sweep */++ ras.band_top = 0;+ ras.band_stack[0].y_min = 0;+ ras.band_stack[0].y_max = 2 * ras.target.rows - 1;++ ras.bWidth = ras.gray_width;+ pixel_width = 2 * ( ( ras.target.width + 3 ) >> 2 );++ if ( ras.bWidth > pixel_width )+ ras.bWidth = pixel_width;++ ras.bWidth = ras.bWidth * 8;+ ras.bTarget = (Byte*)ras.gray_lines;+ ras.gTarget = (Byte*)ras.target.buffer;++ ras.Proc_Sweep_Init = Vertical_Gray_Sweep_Init;+ ras.Proc_Sweep_Span = Vertical_Sweep_Span;+ ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;+ ras.Proc_Sweep_Step = Vertical_Gray_Sweep_Step;++ error = Render_Single_Pass( RAS_VARS 0 );+ if ( error )+ return error;++ /* Horizontal Sweep */+ if ( ras.second_pass && ras.dropOutControl != 2 )+ {+ ras.Proc_Sweep_Init = Horizontal_Sweep_Init;+ ras.Proc_Sweep_Span = Horizontal_Gray_Sweep_Span;+ ras.Proc_Sweep_Drop = Horizontal_Gray_Sweep_Drop;+ ras.Proc_Sweep_Step = Horizontal_Sweep_Step;++ ras.band_top = 0;+ ras.band_stack[0].y_min = 0;+ ras.band_stack[0].y_max = ras.target.width * 2 - 1;++ error = Render_Single_Pass( RAS_VARS 1 );+ if ( error )+ return error;+ }++ return Raster_Err_None;+ }++#else /* !FT_RASTER_OPTION_ANTI_ALIASING */++ FT_LOCAL_DEF( FT_Error )+ Render_Gray_Glyph( RAS_ARG )+ {+ FT_UNUSED_RASTER;++ return Raster_Err_Unsupported;+ }++#endif /* !FT_RASTER_OPTION_ANTI_ALIASING */+++ static void+ ft_black_init( PRaster raster )+ {+#ifdef FT_RASTER_OPTION_ANTI_ALIASING+ FT_UInt n;+++ /* set default 5-levels gray palette */+ for ( n = 0; n < 5; n++ )+ raster->grays[n] = n * 255 / 4;++ raster->gray_width = RASTER_GRAY_LINES / 2;+#else+ FT_UNUSED( raster );+#endif+ }+++ /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/+ /**** a static object. *****/+++#ifdef _STANDALONE_+++ static int+ ft_black_new( void* memory,+ FT_Raster *araster )+ {+ static TRaster the_raster;+ FT_UNUSED( memory );+++ *araster = (FT_Raster)&the_raster;+ FT_MEM_ZERO( &the_raster, sizeof ( the_raster ) );+ ft_black_init( &the_raster );++ return 0;+ }+++ static void+ ft_black_done( FT_Raster raster )+ {+ /* nothing */+ FT_UNUSED( raster );+ }+++#else /* !_STANDALONE_ */+++ static int+ ft_black_new( FT_Memory memory,+ PRaster *araster )+ {+ FT_Error error;+ PRaster raster = NULL;+++ *araster = 0;+ if ( !FT_NEW( raster ) )+ {+ raster->memory = memory;+ ft_black_init( raster );++ *araster = raster;+ }++ return error;+ }+++ static void+ ft_black_done( PRaster raster )+ {+ FT_Memory memory = (FT_Memory)raster->memory;+ FT_FREE( raster );+ }+++#endif /* !_STANDALONE_ */+++ static void+ ft_black_reset( PRaster raster,+ char* pool_base,+ long pool_size )+ {+ if ( raster )+ {+ if ( pool_base && pool_size >= (long)sizeof(TWorker) + 2048 )+ {+ PWorker worker = (PWorker)pool_base;+++ raster->buffer = pool_base + ( ( sizeof ( *worker ) + 7 ) & ~7 );+ raster->buffer_size = pool_base + pool_size - (char*)raster->buffer;+ raster->worker = worker;+ }+ else+ {+ raster->buffer = NULL;+ raster->buffer_size = 0;+ raster->worker = NULL;+ }+ }+ }+++ static void+ ft_black_set_mode( PRaster raster,+ unsigned long mode,+ const char* palette )+ {+#ifdef FT_RASTER_OPTION_ANTI_ALIASING++ if ( mode == FT_MAKE_TAG( 'p', 'a', 'l', '5' ) )+ {+ /* set 5-levels gray palette */+ raster->grays[0] = palette[0];+ raster->grays[1] = palette[1];+ raster->grays[2] = palette[2];+ raster->grays[3] = palette[3];+ raster->grays[4] = palette[4];+ }++#else++ FT_UNUSED( raster );+ FT_UNUSED( mode );+ FT_UNUSED( palette );++#endif+ }+++ static int+ ft_black_render( PRaster raster,+ const FT_Raster_Params* params )+ {+ const FT_Outline* outline = (const FT_Outline*)params->source;+ const FT_Bitmap* target_map = params->target;+ PWorker worker;+++ if ( !raster || !raster->buffer || !raster->buffer_size )+ return Raster_Err_Not_Ini;++ if ( !outline )+ return Raster_Err_Invalid;++ /* return immediately if the outline is empty */+ if ( outline->n_points == 0 || outline->n_contours <= 0 )+ return Raster_Err_None;++ if ( !outline->contours || !outline->points )+ return Raster_Err_Invalid;++ if ( outline->n_points !=+ outline->contours[outline->n_contours - 1] + 1 )+ return Raster_Err_Invalid;++ worker = raster->worker;++ /* this version of the raster does not support direct rendering, sorry */+ if ( params->flags & FT_RASTER_FLAG_DIRECT )+ return Raster_Err_Unsupported;++ if ( !target_map )+ return Raster_Err_Invalid;++ /* nothing to do */+ if ( !target_map->width || !target_map->rows )+ return Raster_Err_None;++ if ( !target_map->buffer )+ return Raster_Err_Invalid;++ ras.outline = *outline;+ ras.target = *target_map;++ worker->buff = (PLong) raster->buffer;+ worker->sizeBuff = worker->buff ++ raster->buffer_size / sizeof ( Long );+#ifdef FT_RASTER_OPTION_ANTI_ALIASING+ worker->grays = raster->grays;+ worker->gray_width = raster->gray_width;++ FT_MEM_ZERO( worker->gray_lines, worker->gray_width * 2 );+#endif++ return ( params->flags & FT_RASTER_FLAG_AA )+ ? Render_Gray_Glyph( RAS_VAR )+ : Render_Glyph( RAS_VAR );+ }+++ FT_DEFINE_RASTER_FUNCS( ft_standard_raster,+ FT_GLYPH_FORMAT_OUTLINE,+ (FT_Raster_New_Func) ft_black_new,+ (FT_Raster_Reset_Func) ft_black_reset,+ (FT_Raster_Set_Mode_Func)ft_black_set_mode,+ (FT_Raster_Render_Func) ft_black_render,+ (FT_Raster_Done_Func) ft_black_done+ )+++/* END */
+ src/raster/ftraster.h view
@@ -0,0 +1,46 @@+/***************************************************************************/+/* */+/* ftraster.h */+/* */+/* The FreeType glyph rasterizer (specification). */+/* */+/* Copyright 1996-2001 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 __FTRASTER_H__+#define __FTRASTER_H__+++#include <ft2build.h>+#include FT_CONFIG_CONFIG_H+#include FT_IMAGE_H+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* Uncomment the following line if you are using ftraster.c as a */+ /* standalone module, fully independent of FreeType. */+ /* */+/* #define _STANDALONE_ */++ FT_EXPORT_VAR( const FT_Raster_Funcs ) ft_standard_raster;+++FT_END_HEADER++#endif /* __FTRASTER_H__ */+++/* END */
+ src/raster/ftrend1.c view
@@ -0,0 +1,291 @@+/***************************************************************************/+/* */+/* ftrend1.c */+/* */+/* The FreeType glyph rasterizer interface (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2005, 2006 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_OBJECTS_H+#include FT_OUTLINE_H+#include "ftrend1.h"+#include "ftraster.h"+#include "rastpic.h"++#include "rasterrs.h"+++ /* initialize renderer -- init its raster */+ static FT_Error+ ft_raster1_init( FT_Renderer render )+ {+ FT_Library library = FT_MODULE_LIBRARY( render );+++ render->clazz->raster_class->raster_reset( render->raster,+ library->raster_pool,+ library->raster_pool_size );++ return Raster_Err_Ok;+ }+++ /* set render-specific mode */+ static FT_Error+ ft_raster1_set_mode( FT_Renderer render,+ FT_ULong mode_tag,+ FT_Pointer data )+ {+ /* we simply pass it to the raster */+ return render->clazz->raster_class->raster_set_mode( render->raster,+ mode_tag,+ data );+ }+++ /* transform a given glyph image */+ static FT_Error+ ft_raster1_transform( FT_Renderer render,+ FT_GlyphSlot slot,+ const FT_Matrix* matrix,+ const FT_Vector* delta )+ {+ FT_Error error = Raster_Err_Ok;+++ if ( slot->format != render->glyph_format )+ {+ error = Raster_Err_Invalid_Argument;+ goto Exit;+ }++ if ( matrix )+ FT_Outline_Transform( &slot->outline, matrix );++ if ( delta )+ FT_Outline_Translate( &slot->outline, delta->x, delta->y );++ Exit:+ return error;+ }+++ /* return the glyph's control box */+ static void+ ft_raster1_get_cbox( FT_Renderer render,+ FT_GlyphSlot slot,+ FT_BBox* cbox )+ {+ FT_MEM_ZERO( cbox, sizeof ( *cbox ) );++ if ( slot->format == render->glyph_format )+ FT_Outline_Get_CBox( &slot->outline, cbox );+ }+++ /* convert a slot's glyph image into a bitmap */+ static FT_Error+ ft_raster1_render( FT_Renderer render,+ FT_GlyphSlot slot,+ FT_Render_Mode mode,+ const FT_Vector* origin )+ {+ FT_Error error;+ FT_Outline* outline;+ FT_BBox cbox;+ FT_UInt width, height, pitch;+ FT_Bitmap* bitmap;+ FT_Memory memory;++ FT_Raster_Params params;+++ /* check glyph image format */+ if ( slot->format != render->glyph_format )+ {+ error = Raster_Err_Invalid_Argument;+ goto Exit;+ }++ /* check rendering mode */+#ifndef FT_CONFIG_OPTION_PIC+ if ( mode != FT_RENDER_MODE_MONO )+ {+ /* raster1 is only capable of producing monochrome bitmaps */+ if ( render->clazz == &ft_raster1_renderer_class )+ return Raster_Err_Cannot_Render_Glyph;+ }+ else+ {+ /* raster5 is only capable of producing 5-gray-levels bitmaps */+ if ( render->clazz == &ft_raster5_renderer_class )+ return Raster_Err_Cannot_Render_Glyph;+ }+#else /* FT_CONFIG_OPTION_PIC */+ /* When PIC is enabled, we cannot get to the class object */+ /* so instead we check the final character in the class name */+ /* ("raster5" or "raster1"). Yes this is a hack. */+ /* The "correct" thing to do is have different render function */+ /* for each of the classes. */+ if ( mode != FT_RENDER_MODE_MONO )+ {+ /* raster1 is only capable of producing monochrome bitmaps */+ if ( render->clazz->root.module_name[6] == '1' )+ return Raster_Err_Cannot_Render_Glyph;+ }+ else+ {+ /* raster5 is only capable of producing 5-gray-levels bitmaps */+ if ( render->clazz->root.module_name[6] == '5' )+ return Raster_Err_Cannot_Render_Glyph;+ }+#endif /* FT_CONFIG_OPTION_PIC */++ outline = &slot->outline;++ /* translate the outline to the new origin if needed */+ if ( origin )+ FT_Outline_Translate( outline, origin->x, origin->y );++ /* compute the control box, and grid fit it */+ FT_Outline_Get_CBox( outline, &cbox );++ cbox.xMin = FT_PIX_FLOOR( cbox.xMin );+ cbox.yMin = FT_PIX_FLOOR( cbox.yMin );+ cbox.xMax = FT_PIX_CEIL( cbox.xMax );+ cbox.yMax = FT_PIX_CEIL( cbox.yMax );++ width = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 );+ height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 );+ bitmap = &slot->bitmap;+ memory = render->root.memory;++ /* release old bitmap buffer */+ if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )+ {+ FT_FREE( bitmap->buffer );+ slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;+ }++ /* allocate new one, depends on pixel format */+ if ( !( mode & FT_RENDER_MODE_MONO ) )+ {+ /* we pad to 32 bits, only for backwards compatibility with FT 1.x */+ pitch = FT_PAD_CEIL( width, 4 );+ bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;+ bitmap->num_grays = 256;+ }+ else+ {+ pitch = ( ( width + 15 ) >> 4 ) << 1;+ bitmap->pixel_mode = FT_PIXEL_MODE_MONO;+ }++ bitmap->width = width;+ bitmap->rows = height;+ bitmap->pitch = pitch;++ if ( FT_ALLOC_MULT( bitmap->buffer, pitch, height ) )+ goto Exit;++ slot->internal->flags |= FT_GLYPH_OWN_BITMAP;++ /* translate outline to render it into the bitmap */+ FT_Outline_Translate( outline, -cbox.xMin, -cbox.yMin );++ /* set up parameters */+ params.target = bitmap;+ params.source = outline;+ params.flags = 0;++ if ( bitmap->pixel_mode == FT_PIXEL_MODE_GRAY )+ params.flags |= FT_RASTER_FLAG_AA;++ /* render outline into the bitmap */+ error = render->raster_render( render->raster, ¶ms );++ FT_Outline_Translate( outline, cbox.xMin, cbox.yMin );++ if ( error )+ goto Exit;++ slot->format = FT_GLYPH_FORMAT_BITMAP;+ slot->bitmap_left = (FT_Int)( cbox.xMin >> 6 );+ slot->bitmap_top = (FT_Int)( cbox.yMax >> 6 );++ Exit:+ return error;+ }+++ FT_DEFINE_RENDERER(ft_raster1_renderer_class,+ + FT_MODULE_RENDERER,+ sizeof( FT_RendererRec ),++ "raster1",+ 0x10000L,+ 0x20000L,++ 0, /* module specific interface */++ (FT_Module_Constructor)ft_raster1_init,+ (FT_Module_Destructor) 0,+ (FT_Module_Requester) 0+ ,++ FT_GLYPH_FORMAT_OUTLINE,++ (FT_Renderer_RenderFunc) ft_raster1_render,+ (FT_Renderer_TransformFunc)ft_raster1_transform,+ (FT_Renderer_GetCBoxFunc) ft_raster1_get_cbox,+ (FT_Renderer_SetModeFunc) ft_raster1_set_mode,++ (FT_Raster_Funcs*) &FT_STANDARD_RASTER_GET+ )+++ /* This renderer is _NOT_ part of the default modules; you will need */+ /* to register it by hand in your application. It should only be */+ /* used for backwards-compatibility with FT 1.x anyway. */+ /* */+ FT_DEFINE_RENDERER(ft_raster5_renderer_class,+ + + FT_MODULE_RENDERER,+ sizeof( FT_RendererRec ),++ "raster5",+ 0x10000L,+ 0x20000L,++ 0, /* module specific interface */++ (FT_Module_Constructor)ft_raster1_init,+ (FT_Module_Destructor) 0,+ (FT_Module_Requester) 0+ ,++ FT_GLYPH_FORMAT_OUTLINE,++ (FT_Renderer_RenderFunc) ft_raster1_render,+ (FT_Renderer_TransformFunc)ft_raster1_transform,+ (FT_Renderer_GetCBoxFunc) ft_raster1_get_cbox,+ (FT_Renderer_SetModeFunc) ft_raster1_set_mode,++ (FT_Raster_Funcs*) &FT_STANDARD_RASTER_GET+ )+++/* END */
+ src/raster/ftrend1.h view
@@ -0,0 +1,44 @@+/***************************************************************************/+/* */+/* ftrend1.h */+/* */+/* The FreeType glyph rasterizer interface (specification). */+/* */+/* Copyright 1996-2001 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 __FTREND1_H__+#define __FTREND1_H__+++#include <ft2build.h>+#include FT_RENDER_H+++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++#endif /* __FTREND1_H__ */+++/* END */
+ src/raster/raster.c view
@@ -0,0 +1,27 @@+/***************************************************************************/+/* */+/* raster.c */+/* */+/* FreeType monochrome rasterer module component (body only). */+/* */+/* Copyright 1996-2001 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 "rastpic.c"+#include "ftraster.c"+#include "ftrend1.c"+++/* END */
+ src/raster/rasterrs.h view
@@ -0,0 +1,41 @@+/***************************************************************************/+/* */+/* rasterrs.h */+/* */+/* monochrome renderer error codes (specification only). */+/* */+/* Copyright 2001 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 monochrome renderer error enumeration */+ /* constants. */+ /* */+ /*************************************************************************/++#ifndef __RASTERRS_H__+#define __RASTERRS_H__++#include FT_MODULE_ERRORS_H++#undef __FTERRORS_H__++#define FT_ERR_PREFIX Raster_Err_+#define FT_ERR_BASE FT_Mod_Err_Raster++#include FT_ERRORS_H++#endif /* __RASTERRS_H__ */+++/* END */
+ src/raster/rastpic.c view
@@ -0,0 +1,90 @@+/***************************************************************************/+/* */+/* rastpic.c */+/* */+/* The FreeType position independent code services for raster module. */+/* */+/* Copyright 2009, 2010 by */+/* Oran Agra and Mickey Gabel. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#include <ft2build.h>+#include FT_FREETYPE_H+#include FT_INTERNAL_OBJECTS_H+#include "rastpic.h"++#ifdef FT_CONFIG_OPTION_PIC++ /* forward declaration of PIC init functions from ftraster.c */+ void FT_Init_Class_ft_standard_raster(FT_Raster_Funcs*);++ void+ ft_raster1_renderer_class_pic_free( FT_Library library )+ {+ FT_PIC_Container* pic_container = &library->pic_container;+ FT_Memory memory = library->memory;+ if ( pic_container->raster )+ {+ RasterPIC* container = (RasterPIC*)pic_container->raster;+ if(--container->ref_count)+ return;+ FT_FREE( container );+ pic_container->raster = NULL;+ }+ }+++ FT_Error+ ft_raster1_renderer_class_pic_init( FT_Library library )+ {+ FT_PIC_Container* pic_container = &library->pic_container;+ FT_Error error = Raster_Err_Ok;+ RasterPIC* container;+ FT_Memory memory = library->memory;+++ /* since this function also serve raster5 renderer, + it implements reference counting */+ if ( pic_container->raster )+ {+ ((RasterPIC*)pic_container->raster)->ref_count++;+ return error;+ }++ /* allocate pointer, clear and set global container pointer */+ if ( FT_ALLOC ( container, sizeof ( *container ) ) )+ return error;+ FT_MEM_SET( container, 0, sizeof(*container) );+ pic_container->raster = container;+ container->ref_count = 1;++ /* initialize pointer table - this is how the module usually expects this data */+ FT_Init_Class_ft_standard_raster(&container->ft_standard_raster);+/*Exit:*/+ if(error)+ ft_raster1_renderer_class_pic_free(library);+ 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 */+++/* END */
+ src/raster/rastpic.h view
@@ -0,0 +1,50 @@+/***************************************************************************/+/* */+/* rastpic.h */+/* */+/* The FreeType position independent code services for raster module. */+/* */+/* Copyright 2009 by */+/* Oran Agra and Mickey Gabel. */+/* */+/* 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 __RASTPIC_H__+#define __RASTPIC_H__++ +FT_BEGIN_HEADER++#include FT_INTERNAL_PIC_H++#ifndef FT_CONFIG_OPTION_PIC+#define FT_STANDARD_RASTER_GET ft_standard_raster++#else /* FT_CONFIG_OPTION_PIC */++ typedef struct RasterPIC_+ {+ int ref_count;+ FT_Raster_Funcs ft_standard_raster;+ } RasterPIC;++#define GET_PIC(lib) ((RasterPIC*)((lib)->pic_container.raster))+#define FT_STANDARD_RASTER_GET (GET_PIC(library)->ft_standard_raster)++#endif /* FT_CONFIG_OPTION_PIC */++ /* */++FT_END_HEADER++#endif /* __RASTPIC_H__ */+++/* END */
+ src/sfnt/sfdriver.c view
@@ -0,0 +1,651 @@+/***************************************************************************/+/* */+/* sfdriver.c */+/* */+/* High-level SFNT driver interface (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 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_SFNT_H+#include FT_INTERNAL_OBJECTS_H++#include "sfdriver.h"+#include "ttload.h"+#include "sfobjs.h"+#include "sfntpic.h"++#include "sferrors.h"++#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS+#include "ttsbit.h"+#endif++#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES+#include "ttpost.h"+#endif++#ifdef TT_CONFIG_OPTION_BDF+#include "ttbdf.h"+#include FT_SERVICE_BDF_H+#endif++#include "ttcmap.h"+#include "ttkern.h"+#include "ttmtx.h"++#include FT_SERVICE_GLYPH_DICT_H+#include FT_SERVICE_POSTSCRIPT_NAME_H+#include FT_SERVICE_SFNT_H+#include FT_SERVICE_TT_CMAP_H++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_sfdriver+++ /*+ * SFNT TABLE SERVICE+ *+ */++ static void*+ get_sfnt_table( TT_Face face,+ FT_Sfnt_Tag tag )+ {+ void* table;+++ switch ( tag )+ {+ case ft_sfnt_head:+ table = &face->header;+ break;++ case ft_sfnt_hhea:+ table = &face->horizontal;+ break;++ case ft_sfnt_vhea:+ table = face->vertical_info ? &face->vertical : 0;+ break;++ case ft_sfnt_os2:+ table = face->os2.version == 0xFFFFU ? 0 : &face->os2;+ break;++ case ft_sfnt_post:+ table = &face->postscript;+ break;++ case ft_sfnt_maxp:+ table = &face->max_profile;+ break;++ case ft_sfnt_pclt:+ table = face->pclt.Version ? &face->pclt : 0;+ break;++ default:+ table = 0;+ }++ return table;+ }+++ static FT_Error+ sfnt_table_info( TT_Face face,+ FT_UInt idx,+ FT_ULong *tag,+ FT_ULong *offset,+ FT_ULong *length )+ {+ if ( !tag || !offset || !length )+ return SFNT_Err_Invalid_Argument;++ if ( idx >= face->num_tables )+ return SFNT_Err_Table_Missing;++ *tag = face->dir_tables[idx].Tag;+ *offset = face->dir_tables[idx].Offset;+ *length = face->dir_tables[idx].Length;++ return SFNT_Err_Ok;+ }+++ 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+ )+++#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES++ /*+ * GLYPH DICT SERVICE+ *+ */++ static FT_Error+ sfnt_get_glyph_name( TT_Face face,+ FT_UInt glyph_index,+ FT_Pointer buffer,+ FT_UInt buffer_max )+ {+ FT_String* gname;+ FT_Error error;+++ error = tt_face_get_ps_name( face, glyph_index, &gname );+ if ( !error )+ FT_STRCPYN( buffer, gname, buffer_max );++ return error;+ }+++ static FT_UInt+ sfnt_get_name_index( TT_Face face,+ FT_String* glyph_name )+ {+ FT_Face root = &face->root;+ FT_UInt i, max_gid = FT_UINT_MAX;+++ if ( root->num_glyphs < 0 )+ return 0;+ else if ( ( FT_ULong ) root->num_glyphs < FT_UINT_MAX )+ max_gid = ( FT_UInt ) root->num_glyphs;+ else+ FT_TRACE0(( "Ignore glyph names for invalid GID 0x%08x - 0x%08x\n",+ FT_UINT_MAX, root->num_glyphs ));++ for ( i = 0; i < max_gid; i++ )+ {+ FT_String* gname;+ FT_Error error = tt_face_get_ps_name( face, i, &gname );+++ if ( error )+ continue;++ if ( !ft_strcmp( glyph_name, gname ) )+ return i;+ }++ return 0;+ }+++ FT_DEFINE_SERVICE_GLYPHDICTREC(sfnt_service_glyph_dict,+ (FT_GlyphDict_GetNameFunc) sfnt_get_glyph_name,+ (FT_GlyphDict_NameIndexFunc)sfnt_get_name_index+ )++#endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */+++ /*+ * POSTSCRIPT NAME SERVICE+ *+ */++ static const char*+ sfnt_get_ps_name( TT_Face face )+ {+ FT_Int n, found_win, found_apple;+ const char* result = NULL;+++ /* shouldn't happen, but just in case to avoid memory leaks */+ if ( face->postscript_name )+ return face->postscript_name;++ /* scan the name table to see whether we have a Postscript name here, */+ /* either in Macintosh or Windows platform encodings */+ found_win = -1;+ found_apple = -1;++ for ( n = 0; n < face->num_names; n++ )+ {+ TT_NameEntryRec* name = face->name_table.names + n;+++ if ( name->nameID == 6 && name->stringLength > 0 )+ {+ if ( name->platformID == 3 &&+ name->encodingID == 1 &&+ name->languageID == 0x409 )+ found_win = n;++ if ( name->platformID == 1 &&+ name->encodingID == 0 &&+ name->languageID == 0 )+ found_apple = n;+ }+ }++ if ( found_win != -1 )+ {+ FT_Memory memory = face->root.memory;+ TT_NameEntryRec* name = face->name_table.names + found_win;+ FT_UInt len = name->stringLength / 2;+ FT_Error error = SFNT_Err_Ok;++ FT_UNUSED( error );+++ if ( !FT_ALLOC( result, name->stringLength + 1 ) )+ {+ FT_Stream stream = face->name_table.stream;+ FT_String* r = (FT_String*)result;+ FT_Byte* p = (FT_Byte*)name->string;+++ if ( FT_STREAM_SEEK( name->stringOffset ) ||+ FT_FRAME_ENTER( name->stringLength ) )+ {+ FT_FREE( result );+ name->stringLength = 0;+ name->stringOffset = 0;+ FT_FREE( name->string );++ goto Exit;+ }++ p = (FT_Byte*)stream->cursor;++ for ( ; len > 0; len--, p += 2 )+ {+ if ( p[0] == 0 && p[1] >= 32 && p[1] < 128 )+ *r++ = p[1];+ }+ *r = '\0';++ FT_FRAME_EXIT();+ }+ goto Exit;+ }++ if ( found_apple != -1 )+ {+ FT_Memory memory = face->root.memory;+ TT_NameEntryRec* name = face->name_table.names + found_apple;+ FT_UInt len = name->stringLength;+ FT_Error error = SFNT_Err_Ok;++ FT_UNUSED( error );+++ if ( !FT_ALLOC( result, len + 1 ) )+ {+ FT_Stream stream = face->name_table.stream;+++ if ( FT_STREAM_SEEK( name->stringOffset ) ||+ FT_STREAM_READ( result, len ) )+ {+ name->stringOffset = 0;+ name->stringLength = 0;+ FT_FREE( name->string );+ FT_FREE( result );+ goto Exit;+ }+ ((char*)result)[len] = '\0';+ }+ }++ Exit:+ face->postscript_name = result;+ return result;+ }++ FT_DEFINE_SERVICE_PSFONTNAMEREC(sfnt_service_ps_name,+ (FT_PsName_GetFunc)sfnt_get_ps_name+ )+++ /*+ * TT CMAP INFO+ */+ FT_DEFINE_SERVICE_TTCMAPSREC(tt_service_get_cmap_info,+ (TT_CMap_Info_GetFunc)tt_get_cmap_info+ )+++#ifdef TT_CONFIG_OPTION_BDF++ static FT_Error+ sfnt_get_charset_id( TT_Face face,+ const char* *acharset_encoding,+ const char* *acharset_registry )+ {+ BDF_PropertyRec encoding, registry;+ FT_Error error;+++ /* XXX: I don't know whether this is correct, since+ * tt_face_find_bdf_prop only returns something correct if we have+ * previously selected a size that is listed in the BDF table.+ * Should we change the BDF table format to include single offsets+ * for `CHARSET_REGISTRY' and `CHARSET_ENCODING'?+ */+ error = tt_face_find_bdf_prop( face, "CHARSET_REGISTRY", ®istry );+ if ( !error )+ {+ error = tt_face_find_bdf_prop( face, "CHARSET_ENCODING", &encoding );+ if ( !error )+ {+ if ( registry.type == BDF_PROPERTY_TYPE_ATOM &&+ encoding.type == BDF_PROPERTY_TYPE_ATOM )+ {+ *acharset_encoding = encoding.u.atom;+ *acharset_registry = registry.u.atom;+ }+ else+ error = SFNT_Err_Invalid_Argument;+ }+ }++ return error;+ }+++ FT_DEFINE_SERVICE_BDFRec(sfnt_service_bdf,+ (FT_BDF_GetCharsetIdFunc) sfnt_get_charset_id,+ (FT_BDF_GetPropertyFunc) tt_face_find_bdf_prop+ )++#endif /* TT_CONFIG_OPTION_BDF */+++ /*+ * SERVICE LIST+ */++#if defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES && defined TT_CONFIG_OPTION_BDF+ FT_DEFINE_SERVICEDESCREC5(sfnt_services,+ FT_SERVICE_ID_SFNT_TABLE, &FT_SFNT_SERVICE_SFNT_TABLE_GET,+ FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &FT_SFNT_SERVICE_PS_NAME_GET,+ FT_SERVICE_ID_GLYPH_DICT, &FT_SFNT_SERVICE_GLYPH_DICT_GET,+ FT_SERVICE_ID_BDF, &FT_SFNT_SERVICE_BDF_GET,+ FT_SERVICE_ID_TT_CMAP, &FT_TT_SERVICE_GET_CMAP_INFO_GET+ )+#elif defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES+ FT_DEFINE_SERVICEDESCREC4(sfnt_services,+ FT_SERVICE_ID_SFNT_TABLE, &FT_SFNT_SERVICE_SFNT_TABLE_GET,+ FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &FT_SFNT_SERVICE_PS_NAME_GET,+ FT_SERVICE_ID_GLYPH_DICT, &FT_SFNT_SERVICE_GLYPH_DICT_GET,+ FT_SERVICE_ID_TT_CMAP, &FT_TT_SERVICE_GET_CMAP_INFO_GET+ )+#elif defined TT_CONFIG_OPTION_BDF+ FT_DEFINE_SERVICEDESCREC4(sfnt_services,+ FT_SERVICE_ID_SFNT_TABLE, &FT_SFNT_SERVICE_SFNT_TABLE_GET,+ FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &FT_SFNT_SERVICE_PS_NAME_GET,+ FT_SERVICE_ID_BDF, &FT_SFNT_SERVICE_BDF_GET,+ FT_SERVICE_ID_TT_CMAP, &FT_TT_SERVICE_GET_CMAP_INFO_GET+ )+#else+ FT_DEFINE_SERVICEDESCREC3(sfnt_services,+ FT_SERVICE_ID_SFNT_TABLE, &FT_SFNT_SERVICE_SFNT_TABLE_GET,+ FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &FT_SFNT_SERVICE_PS_NAME_GET,+ FT_SERVICE_ID_TT_CMAP, &FT_TT_SERVICE_GET_CMAP_INFO_GET+ )+#endif+++ FT_CALLBACK_DEF( FT_Module_Interface )+ sfnt_get_interface( FT_Module module,+ const char* module_interface )+ {+ FT_UNUSED( module );++ return ft_service_list_lookup( FT_SFNT_SERVICES_GET, module_interface );+ }+++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS++ FT_CALLBACK_DEF( FT_Error )+ tt_face_load_sfnt_header_stub( TT_Face face,+ FT_Stream stream,+ FT_Long face_index,+ SFNT_Header header )+ {+ FT_UNUSED( face );+ FT_UNUSED( stream );+ FT_UNUSED( face_index );+ FT_UNUSED( header );++ return SFNT_Err_Unimplemented_Feature;+ }+++ FT_CALLBACK_DEF( FT_Error )+ tt_face_load_directory_stub( TT_Face face,+ FT_Stream stream,+ SFNT_Header header )+ {+ FT_UNUSED( face );+ FT_UNUSED( stream );+ FT_UNUSED( header );++ return SFNT_Err_Unimplemented_Feature;+ }+++ FT_CALLBACK_DEF( FT_Error )+ tt_face_load_hdmx_stub( TT_Face face,+ FT_Stream stream )+ {+ FT_UNUSED( face );+ FT_UNUSED( stream );++ return SFNT_Err_Unimplemented_Feature;+ }+++ FT_CALLBACK_DEF( void )+ tt_face_free_hdmx_stub( TT_Face face )+ {+ FT_UNUSED( face );+ }+++ FT_CALLBACK_DEF( FT_Error )+ tt_face_set_sbit_strike_stub( TT_Face face,+ FT_UInt x_ppem,+ FT_UInt y_ppem,+ FT_ULong* astrike_index )+ {+ /*+ * We simply forge a FT_Size_Request and call the real function+ * that does all the work.+ *+ * This stub might be called by libXfont in the X.Org Xserver,+ * compiled against version 2.1.8 or newer.+ */++ FT_Size_RequestRec req;+++ req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;+ req.width = (FT_F26Dot6)x_ppem;+ req.height = (FT_F26Dot6)y_ppem;+ req.horiResolution = 0;+ req.vertResolution = 0;++ *astrike_index = 0x7FFFFFFFUL;++ return tt_face_set_sbit_strike( face, &req, astrike_index );+ }+++ FT_CALLBACK_DEF( FT_Error )+ tt_face_load_sbit_stub( TT_Face face,+ FT_Stream stream )+ {+ FT_UNUSED( face );+ FT_UNUSED( stream );++ /*+ * This function was originally implemented to load the sbit table.+ * However, it has been replaced by `tt_face_load_eblc', and this stub+ * is only there for some rogue clients which would want to call it+ * directly (which doesn't make much sense).+ */+ return SFNT_Err_Unimplemented_Feature;+ }+++ FT_CALLBACK_DEF( void )+ tt_face_free_sbit_stub( TT_Face face )+ {+ /* nothing to do in this stub */+ FT_UNUSED( face );+ }+++ FT_CALLBACK_DEF( FT_Error )+ tt_face_load_charmap_stub( TT_Face face,+ void* cmap,+ FT_Stream input )+ {+ FT_UNUSED( face );+ FT_UNUSED( cmap );+ FT_UNUSED( input );++ return SFNT_Err_Unimplemented_Feature;+ }+++ FT_CALLBACK_DEF( FT_Error )+ tt_face_free_charmap_stub( TT_Face face,+ void* cmap )+ {+ FT_UNUSED( face );+ FT_UNUSED( cmap );++ return SFNT_Err_Ok;+ }++#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */++#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS+#define PUT_EMBEDDED_BITMAPS(a) a +#else+#define PUT_EMBEDDED_BITMAPS(a) 0 +#endif+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES+#define PUT_PS_NAMES(a) a +#else+#define PUT_PS_NAMES(a) 0 +#endif++ FT_DEFINE_SFNT_INTERFACE(sfnt_interface,+ tt_face_goto_table,++ sfnt_init_face,+ sfnt_load_face,+ sfnt_done_face,+ sfnt_get_interface,++ tt_face_load_any,++ tt_face_load_sfnt_header_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */+ tt_face_load_directory_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */++ tt_face_load_head,+ tt_face_load_hhea,+ tt_face_load_cmap,+ tt_face_load_maxp,+ tt_face_load_os2,+ tt_face_load_post,++ tt_face_load_name,+ tt_face_free_name,++ tt_face_load_hdmx_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */+ tt_face_free_hdmx_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */++ tt_face_load_kern,+ tt_face_load_gasp,+ tt_face_load_pclt,++ /* see `ttload.h' */+ PUT_EMBEDDED_BITMAPS(tt_face_load_bhed),++ tt_face_set_sbit_strike_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */+ tt_face_load_sbit_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */++ tt_find_sbit_image, /* FT_CONFIG_OPTION_OLD_INTERNALS */+ tt_load_sbit_metrics, /* FT_CONFIG_OPTION_OLD_INTERNALS */++ PUT_EMBEDDED_BITMAPS(tt_face_load_sbit_image),++ tt_face_free_sbit_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */++ /* see `ttpost.h' */+ PUT_PS_NAMES(tt_face_get_ps_name),+ PUT_PS_NAMES(tt_face_free_ps_names),++ tt_face_load_charmap_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */+ tt_face_free_charmap_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */++ /* since version 2.1.8 */++ tt_face_get_kerning,++ /* since version 2.2 */++ tt_face_load_font_dir,+ tt_face_load_hmtx,++ /* see `ttsbit.h' and `sfnt.h' */+ PUT_EMBEDDED_BITMAPS(tt_face_load_eblc),+ PUT_EMBEDDED_BITMAPS(tt_face_free_eblc),++ PUT_EMBEDDED_BITMAPS(tt_face_set_sbit_strike),+ PUT_EMBEDDED_BITMAPS(tt_face_load_strike_metrics),++ tt_face_get_metrics+ )+++ FT_DEFINE_MODULE(sfnt_module_class,+ + 0, /* not a font driver or renderer */+ sizeof( FT_ModuleRec ),++ "sfnt", /* driver name */+ 0x10000L, /* driver version 1.0 */+ 0x20000L, /* driver requires FreeType 2.0 or higher */++ (const void*)&FT_SFNT_INTERFACE_GET, /* module specific interface */++ (FT_Module_Constructor)0,+ (FT_Module_Destructor) 0,+ (FT_Module_Requester) sfnt_get_interface+ )+++/* END */
+ src/sfnt/sfdriver.h view
@@ -0,0 +1,38 @@+/***************************************************************************/+/* */+/* sfdriver.h */+/* */+/* High-level SFNT driver interface (specification). */+/* */+/* Copyright 1996-2001 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 __SFDRIVER_H__+#define __SFDRIVER_H__+++#include <ft2build.h>+#include FT_MODULE_H+++FT_BEGIN_HEADER+++ FT_DECLARE_MODULE( sfnt_module_class )+++FT_END_HEADER++#endif /* __SFDRIVER_H__ */+++/* END */
+ src/sfnt/sferrors.h view
@@ -0,0 +1,41 @@+/***************************************************************************/+/* */+/* sferrors.h */+/* */+/* SFNT error codes (specification only). */+/* */+/* Copyright 2001, 2004 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 SFNT error enumeration constants. */+ /* */+ /*************************************************************************/++#ifndef __SFERRORS_H__+#define __SFERRORS_H__++#include FT_MODULE_ERRORS_H++#undef __FTERRORS_H__++#define FT_ERR_PREFIX SFNT_Err_+#define FT_ERR_BASE FT_Mod_Err_SFNT++#define FT_KEEP_ERR_PREFIX++#include FT_ERRORS_H++#endif /* __SFERRORS_H__ */++/* END */
+ src/sfnt/sfnt.c view
@@ -0,0 +1,42 @@+/***************************************************************************/+/* */+/* sfnt.c */+/* */+/* Single object library component. */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006 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 "sfntpic.c"+#include "ttload.c"+#include "ttmtx.c"+#include "ttcmap.c"+#include "ttkern.c"+#include "sfobjs.c"+#include "sfdriver.c"++#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS+#include "ttsbit.c"+#endif++#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES+#include "ttpost.c"+#endif++#ifdef TT_CONFIG_OPTION_BDF+#include "ttbdf.c"+#endif++/* END */
+ src/sfnt/sfntpic.c view
@@ -0,0 +1,102 @@+/***************************************************************************/+/* */+/* sfntpic.c */+/* */+/* The FreeType position independent code services for sfnt module. */+/* */+/* Copyright 2009, 2010 by */+/* Oran Agra and Mickey Gabel. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#include <ft2build.h>+#include FT_FREETYPE_H+#include FT_INTERNAL_OBJECTS_H+#include "sfntpic.h"++#ifdef FT_CONFIG_OPTION_PIC++ /* forward declaration of PIC init functions from sfdriver.c */+ FT_Error FT_Create_Class_sfnt_services( FT_Library, FT_ServiceDescRec**);+ void FT_Destroy_Class_sfnt_services( FT_Library, FT_ServiceDescRec*);+ void FT_Init_Class_sfnt_service_bdf( FT_Service_BDFRec*);+ void FT_Init_Class_sfnt_interface( FT_Library, SFNT_Interface*);+ void FT_Init_Class_sfnt_service_glyph_dict( FT_Library, FT_Service_GlyphDictRec*);+ void FT_Init_Class_sfnt_service_ps_name( FT_Library, FT_Service_PsFontNameRec*);+ void FT_Init_Class_tt_service_get_cmap_info( FT_Library, FT_Service_TTCMapsRec*);+ void FT_Init_Class_sfnt_service_sfnt_table( FT_Service_SFNT_TableRec*);++ /* forward declaration of PIC init functions from ttcmap.c */+ FT_Error FT_Create_Class_tt_cmap_classes( FT_Library, TT_CMap_Class**);+ void FT_Destroy_Class_tt_cmap_classes( FT_Library, TT_CMap_Class*);++ void+ sfnt_module_class_pic_free( FT_Library library )+ {+ FT_PIC_Container* pic_container = &library->pic_container;+ FT_Memory memory = library->memory;+ if ( pic_container->sfnt )+ {+ sfntModulePIC* container = (sfntModulePIC*)pic_container->sfnt;+ if(container->sfnt_services)+ FT_Destroy_Class_sfnt_services(library, container->sfnt_services);+ container->sfnt_services = NULL;+ if(container->tt_cmap_classes)+ FT_Destroy_Class_tt_cmap_classes(library, container->tt_cmap_classes);+ container->tt_cmap_classes = NULL;+ FT_FREE( container );+ pic_container->sfnt = NULL;+ }+ }+++ FT_Error+ sfnt_module_class_pic_init( FT_Library library )+ {+ FT_PIC_Container* pic_container = &library->pic_container;+ FT_Error error = SFNT_Err_Ok;+ sfntModulePIC* container;+ FT_Memory memory = library->memory;+++ /* allocate pointer, clear and set global container pointer */+ if ( FT_ALLOC ( container, sizeof ( *container ) ) )+ return error;+ FT_MEM_SET( container, 0, sizeof ( *container ) );+ pic_container->sfnt = container;++ /* initialize pointer table - this is how the module usually expects this data */+ error = FT_Create_Class_sfnt_services(library, &container->sfnt_services);+ if(error) + goto Exit;+ error = FT_Create_Class_tt_cmap_classes(library, &container->tt_cmap_classes);+ if(error) + goto Exit;+ FT_Init_Class_sfnt_service_glyph_dict(library, &container->sfnt_service_glyph_dict);+ FT_Init_Class_sfnt_service_ps_name(library, &container->sfnt_service_ps_name);+ FT_Init_Class_tt_service_get_cmap_info(library, &container->tt_service_get_cmap_info);+ FT_Init_Class_sfnt_service_sfnt_table(&container->sfnt_service_sfnt_table);+#ifdef TT_CONFIG_OPTION_BDF+ FT_Init_Class_sfnt_service_bdf(&container->sfnt_service_bdf);+#endif+ FT_Init_Class_sfnt_interface(library, &container->sfnt_interface);++Exit:+ if(error)+ sfnt_module_class_pic_free(library);+ return error;+ }++++#endif /* FT_CONFIG_OPTION_PIC */+++/* END */
+ src/sfnt/sfntpic.h view
@@ -0,0 +1,88 @@+/***************************************************************************/+/* */+/* sfntpic.h */+/* */+/* The FreeType position independent code services for sfnt module. */+/* */+/* Copyright 2009 by */+/* Oran Agra and Mickey Gabel. */+/* */+/* 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 __SFNTPIC_H__+#define __SFNTPIC_H__++ +FT_BEGIN_HEADER++#include FT_INTERNAL_PIC_H++ #ifndef FT_CONFIG_OPTION_PIC+#define FT_SFNT_SERVICES_GET sfnt_services+#define FT_SFNT_SERVICE_GLYPH_DICT_GET sfnt_service_glyph_dict+#define FT_SFNT_SERVICE_PS_NAME_GET sfnt_service_ps_name+#define FT_TT_SERVICE_GET_CMAP_INFO_GET tt_service_get_cmap_info+#define FT_SFNT_SERVICES_GET sfnt_services+#define FT_TT_CMAP_CLASSES_GET tt_cmap_classes+#define FT_SFNT_SERVICE_SFNT_TABLE_GET sfnt_service_sfnt_table+#define FT_SFNT_SERVICE_BDF_GET sfnt_service_bdf+#define FT_SFNT_INTERFACE_GET sfnt_interface++#else /* FT_CONFIG_OPTION_PIC */++/* some include files required for members of sfntModulePIC */+#include FT_SERVICE_GLYPH_DICT_H+#include FT_SERVICE_POSTSCRIPT_NAME_H+#include FT_SERVICE_SFNT_H+#include FT_SERVICE_TT_CMAP_H+#ifdef TT_CONFIG_OPTION_BDF+#include "ttbdf.h"+#include FT_SERVICE_BDF_H+#endif+#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_STREAM_H+#include FT_INTERNAL_SFNT_H+#include "ttcmap.h"++typedef struct sfntModulePIC_+ {+ FT_ServiceDescRec* sfnt_services;+ FT_Service_GlyphDictRec sfnt_service_glyph_dict;+ FT_Service_PsFontNameRec sfnt_service_ps_name;+ FT_Service_TTCMapsRec tt_service_get_cmap_info;+ TT_CMap_Class* tt_cmap_classes;+ FT_Service_SFNT_TableRec sfnt_service_sfnt_table;+#ifdef TT_CONFIG_OPTION_BDF+ FT_Service_BDFRec sfnt_service_bdf;+#endif+ SFNT_Interface sfnt_interface;+ } sfntModulePIC;++#define GET_PIC(lib) ((sfntModulePIC*)((lib)->pic_container.sfnt))+#define FT_SFNT_SERVICES_GET (GET_PIC(library)->sfnt_services)+#define FT_SFNT_SERVICE_GLYPH_DICT_GET (GET_PIC(library)->sfnt_service_glyph_dict)+#define FT_SFNT_SERVICE_PS_NAME_GET (GET_PIC(library)->sfnt_service_ps_name)+#define FT_TT_SERVICE_GET_CMAP_INFO_GET (GET_PIC(library)->tt_service_get_cmap_info)+#define FT_SFNT_SERVICES_GET (GET_PIC(library)->sfnt_services)+#define FT_TT_CMAP_CLASSES_GET (GET_PIC(library)->tt_cmap_classes)+#define FT_SFNT_SERVICE_SFNT_TABLE_GET (GET_PIC(library)->sfnt_service_sfnt_table)+#define FT_SFNT_SERVICE_BDF_GET (GET_PIC(library)->sfnt_service_bdf)+#define FT_SFNT_INTERFACE_GET (GET_PIC(library)->sfnt_interface)++#endif /* FT_CONFIG_OPTION_PIC */++/* */++FT_END_HEADER++#endif /* __SFNTPIC_H__ */+++/* END */
+ src/sfnt/sfobjs.c view
@@ -0,0 +1,1147 @@+/***************************************************************************/+/* */+/* sfobjs.c */+/* */+/* SFNT object management (base). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 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 "sfobjs.h"+#include "ttload.h"+#include "ttcmap.h"+#include "ttkern.h"+#include FT_INTERNAL_SFNT_H+#include FT_INTERNAL_DEBUG_H+#include FT_TRUETYPE_IDS_H+#include FT_TRUETYPE_TAGS_H+#include FT_SERVICE_POSTSCRIPT_CMAPS_H+#include FT_SFNT_NAMES_H+#include "sferrors.h"++#ifdef TT_CONFIG_OPTION_BDF+#include "ttbdf.h"+#endif+++ /*************************************************************************/+ /* */+ /* 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_sfobjs++++ /* convert a UTF-16 name entry to ASCII */+ static FT_String*+ tt_name_entry_ascii_from_utf16( TT_NameEntry entry,+ FT_Memory memory )+ {+ FT_String* string = NULL;+ FT_UInt len, code, n;+ FT_Byte* read = (FT_Byte*)entry->string;+ FT_Error error;+++ len = (FT_UInt)entry->stringLength / 2;++ if ( FT_NEW_ARRAY( string, len + 1 ) )+ return NULL;++ for ( n = 0; n < len; n++ )+ {+ code = FT_NEXT_USHORT( read );+ if ( code < 32 || code > 127 )+ code = '?';++ string[n] = (char)code;+ }++ string[len] = 0;++ return string;+ }+++ /* convert an Apple Roman or symbol name entry to ASCII */+ static FT_String*+ tt_name_entry_ascii_from_other( TT_NameEntry entry,+ FT_Memory memory )+ {+ FT_String* string = NULL;+ FT_UInt len, code, n;+ FT_Byte* read = (FT_Byte*)entry->string;+ FT_Error error;+++ len = (FT_UInt)entry->stringLength;++ if ( FT_NEW_ARRAY( string, len + 1 ) )+ return NULL;++ for ( n = 0; n < len; n++ )+ {+ code = *read++;+ if ( code < 32 || code > 127 )+ code = '?';++ string[n] = (char)code;+ }++ string[len] = 0;++ return string;+ }+++ typedef FT_String* (*TT_NameEntry_ConvertFunc)( TT_NameEntry entry,+ 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+ tt_face_get_name( TT_Face face,+ FT_UShort nameid,+ FT_String** name )+ {+ FT_Memory memory = face->root.memory;+ FT_Error error = SFNT_Err_Ok;+ FT_String* result = NULL;+ FT_UShort n;+ TT_NameEntryRec* rec;+ FT_Int found_apple = -1;+ FT_Int found_apple_roman = -1;+ FT_Int found_apple_english = -1;+ FT_Int found_win = -1;+ FT_Int found_unicode = -1;++ FT_Bool is_english = 0;++ TT_NameEntry_ConvertFunc convert;+++ FT_ASSERT( name );++ rec = face->name_table.names;+ for ( n = 0; n < face->num_names; n++, rec++ )+ {+ /* According to the OpenType 1.3 specification, only Microsoft or */+ /* Apple platform IDs might be used in the `name' table. The */+ /* `Unicode' platform is reserved for the `cmap' table, and the */+ /* `ISO' one is deprecated. */+ /* */+ /* However, the Apple TrueType specification doesn't say the same */+ /* thing and goes to suggest that all Unicode `name' table entries */+ /* should be coded in UTF-16 (in big-endian format I suppose). */+ /* */+ if ( rec->nameID == nameid && rec->stringLength > 0 )+ {+ switch ( rec->platformID )+ {+ case TT_PLATFORM_APPLE_UNICODE:+ case TT_PLATFORM_ISO:+ /* there is `languageID' to check there. We should use this */+ /* field only as a last solution when nothing else is */+ /* available. */+ /* */+ found_unicode = n;+ break;++ case TT_PLATFORM_MACINTOSH:+ /* This is a bit special because some fonts will use either */+ /* an English language id, or a Roman encoding id, to indicate */+ /* the English version of its font name. */+ /* */+ if ( rec->languageID == TT_MAC_LANGID_ENGLISH )+ found_apple_english = n;+ else if ( rec->encodingID == TT_MAC_ID_ROMAN )+ found_apple_roman = n;+ break;++ case TT_PLATFORM_MICROSOFT:+ /* we only take a non-English name when there is nothing */+ /* else available in the font */+ /* */+ if ( found_win == -1 || ( rec->languageID & 0x3FF ) == 0x009 )+ {+ switch ( rec->encodingID )+ {+ case TT_MS_ID_SYMBOL_CS:+ case TT_MS_ID_UNICODE_CS:+ case TT_MS_ID_UCS_4:+ is_english = FT_BOOL( ( rec->languageID & 0x3FF ) == 0x009 );+ found_win = n;+ break;++ default:+ ;+ }+ }+ break;++ default:+ ;+ }+ }+ }++ found_apple = found_apple_roman;+ if ( found_apple_english >= 0 )+ found_apple = found_apple_english;++ /* some fonts contain invalid Unicode or Macintosh formatted entries; */+ /* we will thus favor names encoded in Windows formats if available */+ /* (provided it is an English name) */+ /* */+ convert = NULL;+ if ( found_win >= 0 && !( found_apple >= 0 && !is_english ) )+ {+ rec = face->name_table.names + found_win;+ switch ( rec->encodingID )+ {+ /* all Unicode strings are encoded using UTF-16BE */+ case TT_MS_ID_UNICODE_CS:+ case TT_MS_ID_SYMBOL_CS:+ convert = tt_name_entry_ascii_from_utf16;+ break;++ case TT_MS_ID_UCS_4:+ /* Apparently, if this value is found in a name table entry, it is */+ /* documented as `full Unicode repertoire'. Experience with the */+ /* MsGothic font shipped with Windows Vista shows that this really */+ /* means UTF-16 encoded names (UCS-4 values are only used within */+ /* charmaps). */+ convert = tt_name_entry_ascii_from_utf16;+ break;++ default:+ ;+ }+ }+ else if ( found_apple >= 0 )+ {+ rec = face->name_table.names + found_apple;+ convert = tt_name_entry_ascii_from_other;+ }+ else if ( found_unicode >= 0 )+ {+ rec = face->name_table.names + found_unicode;+ convert = tt_name_entry_ascii_from_utf16;+ }++ if ( rec && convert )+ {+ if ( rec->string == NULL )+ {+ FT_Stream stream = face->name_table.stream;+++ if ( FT_QNEW_ARRAY ( rec->string, rec->stringLength ) ||+ FT_STREAM_SEEK( rec->stringOffset ) ||+ FT_STREAM_READ( rec->string, rec->stringLength ) )+ {+ FT_FREE( rec->string );+ rec->stringLength = 0;+ result = NULL;+ goto Exit;+ }+ }++ result = convert( rec, memory );+ }++ Exit:+ *name = result;+ return error;+ }+++ static FT_Encoding+ sfnt_find_encoding( int platform_id,+ int encoding_id )+ {+ typedef struct TEncoding_+ {+ int platform_id;+ int encoding_id;+ FT_Encoding encoding;++ } TEncoding;++ static+ const TEncoding tt_encodings[] =+ {+ { TT_PLATFORM_ISO, -1, FT_ENCODING_UNICODE },++ { TT_PLATFORM_APPLE_UNICODE, -1, FT_ENCODING_UNICODE },++ { TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN, FT_ENCODING_APPLE_ROMAN },++ { TT_PLATFORM_MICROSOFT, TT_MS_ID_SYMBOL_CS, FT_ENCODING_MS_SYMBOL },+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_UCS_4, FT_ENCODING_UNICODE },+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, FT_ENCODING_UNICODE },+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_SJIS, FT_ENCODING_SJIS },+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_GB2312, FT_ENCODING_GB2312 },+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_BIG_5, FT_ENCODING_BIG5 },+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_WANSUNG, FT_ENCODING_WANSUNG },+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_JOHAB, FT_ENCODING_JOHAB }+ };++ const TEncoding *cur, *limit;+++ cur = tt_encodings;+ limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] );++ for ( ; cur < limit; cur++ )+ {+ if ( cur->platform_id == platform_id )+ {+ if ( cur->encoding_id == encoding_id ||+ cur->encoding_id == -1 )+ return cur->encoding;+ }+ }++ return FT_ENCODING_NONE;+ }+++ /* Fill in face->ttc_header. If the font is not a TTC, it is */+ /* synthesized into a TTC with one offset table. */+ static FT_Error+ sfnt_open_font( FT_Stream stream,+ TT_Face face )+ {+ FT_Memory memory = stream->memory;+ FT_Error error;+ FT_ULong tag, offset;++ static const FT_Frame_Field ttc_header_fields[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE TTC_HeaderRec++ FT_FRAME_START( 8 ),+ FT_FRAME_LONG( version ),+ FT_FRAME_LONG( count ),+ FT_FRAME_END+ };+++ face->ttc_header.tag = 0;+ face->ttc_header.version = 0;+ face->ttc_header.count = 0;++ offset = FT_STREAM_POS();++ if ( FT_READ_ULONG( tag ) )+ return error;++ if ( tag != 0x00010000UL &&+ tag != TTAG_ttcf &&+ tag != TTAG_OTTO &&+ tag != TTAG_true &&+ tag != TTAG_typ1 &&+ tag != 0x00020000UL )+ return SFNT_Err_Unknown_File_Format;++ face->ttc_header.tag = TTAG_ttcf;++ if ( tag == TTAG_ttcf )+ {+ FT_Int n;+++ FT_TRACE3(( "sfnt_open_font: file is a collection\n" ));++ if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) )+ return error;++ /* now read the offsets of each font in the file */+ if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) )+ return error;++ if ( FT_FRAME_ENTER( face->ttc_header.count * 4L ) )+ return error;++ for ( n = 0; n < face->ttc_header.count; n++ )+ face->ttc_header.offsets[n] = FT_GET_ULONG();++ FT_FRAME_EXIT();+ }+ else+ {+ FT_TRACE3(( "sfnt_open_font: synthesize TTC\n" ));++ face->ttc_header.version = 1 << 16;+ face->ttc_header.count = 1;++ if ( FT_NEW( face->ttc_header.offsets ) )+ return error;++ face->ttc_header.offsets[0] = offset;+ }++ return error;+ }+++ FT_LOCAL_DEF( FT_Error )+ sfnt_init_face( FT_Stream stream,+ TT_Face face,+ FT_Int face_index,+ FT_Int num_params,+ FT_Parameter* params )+ {+ FT_Error error;+ FT_Library library = face->root.driver->root.library;+ SFNT_Service sfnt;+++ /* for now, parameters are unused */+ FT_UNUSED( num_params );+ FT_UNUSED( params );+++ sfnt = (SFNT_Service)face->sfnt;+ if ( !sfnt )+ {+ sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" );+ if ( !sfnt )+ return SFNT_Err_Invalid_File_Format;++ face->sfnt = sfnt;+ face->goto_table = sfnt->goto_table;+ }++ FT_FACE_FIND_GLOBAL_SERVICE( face, face->psnames, POSTSCRIPT_CMAPS );++ error = sfnt_open_font( stream, face );+ if ( error )+ return error;++ FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face, face_index ));++ if ( face_index < 0 )+ face_index = 0;++ if ( face_index >= face->ttc_header.count )+ return SFNT_Err_Invalid_Argument;++ if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) )+ return error;++ /* check that we have a valid TrueType file */+ error = sfnt->load_font_dir( face, stream );+ if ( error )+ return error;++ face->root.num_faces = face->ttc_header.count;+ face->root.face_index = face_index;++ return error;+ }+++#define LOAD_( x ) \+ do { \+ FT_TRACE2(( "`" #x "' " )); \+ FT_TRACE3(( "-->\n" )); \+ \+ error = sfnt->load_##x( face, stream ); \+ \+ FT_TRACE2(( "%s\n", ( !error ) \+ ? "loaded" \+ : ( error == SFNT_Err_Table_Missing ) \+ ? "missing" \+ : "failed to load" )); \+ FT_TRACE3(( "\n" )); \+ } while ( 0 )++#define LOADM_( x, vertical ) \+ do { \+ FT_TRACE2(( "`%s" #x "' ", \+ vertical ? "vertical " : "" )); \+ FT_TRACE3(( "-->\n" )); \+ \+ error = sfnt->load_##x( face, stream, vertical ); \+ \+ FT_TRACE2(( "%s\n", ( !error ) \+ ? "loaded" \+ : ( error == SFNT_Err_Table_Missing ) \+ ? "missing" \+ : "failed to load" )); \+ FT_TRACE3(( "\n" )); \+ } while ( 0 )++#define GET_NAME( id, field ) \+ do { \+ error = tt_face_get_name( face, TT_NAME_ID_##id, field ); \+ if ( error ) \+ goto Exit; \+ } while ( 0 )+++ FT_LOCAL_DEF( FT_Error )+ sfnt_load_face( FT_Stream stream,+ TT_Face face,+ FT_Int face_index,+ FT_Int num_params,+ FT_Parameter* params )+ {+ FT_Error error;+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES+ FT_Error psnames_error;+#endif+ FT_Bool has_outline;+ FT_Bool is_apple_sbit;+ FT_Bool ignore_preferred_family = FALSE;+ FT_Bool ignore_preferred_subfamily = FALSE;++ SFNT_Service sfnt = (SFNT_Service)face->sfnt;++ FT_UNUSED( face_index );++ /* Check parameters */+ + {+ FT_Int i;+++ for ( i = 0; i < num_params; i++ )+ {+ if ( params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY )+ ignore_preferred_family = TRUE;+ else if ( params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY )+ ignore_preferred_subfamily = TRUE;+ }+ }++ /* Load tables */++ /* We now support two SFNT-based bitmapped font formats. They */+ /* are recognized easily as they do not include a `glyf' */+ /* table. */+ /* */+ /* The first format comes from Apple, and uses a table named */+ /* `bhed' instead of `head' to store the font header (using */+ /* the same format). It also doesn't include horizontal and */+ /* vertical metrics tables (i.e. `hhea' and `vhea' tables are */+ /* missing). */+ /* */+ /* The other format comes from Microsoft, and is used with */+ /* WinCE/PocketPC. It looks like a standard TTF, except that */+ /* it doesn't contain outlines. */+ /* */++ FT_TRACE2(( "sfnt_load_face: %08p\n\n", face ));++ /* do we have outlines in there? */+#ifdef FT_CONFIG_OPTION_INCREMENTAL+ has_outline = FT_BOOL( face->root.internal->incremental_interface != 0 ||+ tt_face_lookup_table( face, TTAG_glyf ) != 0 ||+ tt_face_lookup_table( face, TTAG_CFF ) != 0 );+#else+ has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) != 0 ||+ tt_face_lookup_table( face, TTAG_CFF ) != 0 );+#endif++ is_apple_sbit = 0;++ /* if this font doesn't contain outlines, we try to load */+ /* a `bhed' table */+ if ( !has_outline && sfnt->load_bhed )+ {+ LOAD_( bhed );+ is_apple_sbit = FT_BOOL( !error );+ }++ /* load the font header (`head' table) if this isn't an Apple */+ /* sbit font file */+ if ( !is_apple_sbit )+ {+ LOAD_( head );+ if ( error )+ goto Exit;+ }++ if ( face->header.Units_Per_EM == 0 )+ {+ error = SFNT_Err_Invalid_Table;++ goto Exit;+ }++ /* the following tables are often not present in embedded TrueType */+ /* fonts within PDF documents, so don't check for them. */+ LOAD_( maxp );+ LOAD_( cmap );++ /* the following tables are optional in PCL fonts -- */+ /* don't check for errors */+ LOAD_( name );+ LOAD_( post );++#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES+ psnames_error = error;+#endif++ /* do not load the metrics headers and tables if this is an Apple */+ /* sbit font file */+ if ( !is_apple_sbit )+ {+ /* load the `hhea' and `hmtx' tables */+ LOADM_( hhea, 0 );+ if ( !error )+ {+ LOADM_( hmtx, 0 );+ if ( error == SFNT_Err_Table_Missing )+ {+ error = SFNT_Err_Hmtx_Table_Missing;++#ifdef FT_CONFIG_OPTION_INCREMENTAL+ /* If this is an incrementally loaded font and there are */+ /* overriding metrics, tolerate a missing `hmtx' table. */+ if ( face->root.internal->incremental_interface &&+ face->root.internal->incremental_interface->funcs->+ get_glyph_metrics )+ {+ face->horizontal.number_Of_HMetrics = 0;+ error = SFNT_Err_Ok;+ }+#endif+ }+ }+ else if ( error == SFNT_Err_Table_Missing )+ {+ /* No `hhea' table necessary for SFNT Mac fonts. */+ if ( face->format_tag == TTAG_true )+ {+ FT_TRACE2(( "This is an SFNT Mac font.\n" ));+ has_outline = 0;+ error = SFNT_Err_Ok;+ }+ else+ {+ error = SFNT_Err_Horiz_Header_Missing;++#ifdef FT_CONFIG_OPTION_INCREMENTAL+ /* If this is an incrementally loaded font and there are */+ /* overriding metrics, tolerate a missing `hhea' table. */+ if ( face->root.internal->incremental_interface &&+ face->root.internal->incremental_interface->funcs->+ get_glyph_metrics )+ {+ face->horizontal.number_Of_HMetrics = 0;+ error = SFNT_Err_Ok;+ }+#endif++ }+ }++ if ( error )+ goto Exit;++ /* try to load the `vhea' and `vmtx' tables */+ LOADM_( hhea, 1 );+ if ( !error )+ {+ LOADM_( hmtx, 1 );+ if ( !error )+ face->vertical_info = 1;+ }++ if ( error && error != SFNT_Err_Table_Missing )+ goto Exit;++ LOAD_( os2 );+ if ( error )+ {+ /* we treat the table as missing if there are any errors */+ face->os2.version = 0xFFFFU;+ }+ }++ /* the optional tables */++ /* embedded bitmap support */+ if ( sfnt->load_eblc )+ {+ LOAD_( eblc );+ if ( error )+ {+ /* a font which contains neither bitmaps nor outlines is */+ /* still valid (although rather useless in most cases); */+ /* however, you can find such stripped fonts in PDFs */+ if ( error == SFNT_Err_Table_Missing )+ error = SFNT_Err_Ok;+ else+ goto Exit;+ }+ }++ LOAD_( pclt );+ if ( error )+ {+ if ( error != SFNT_Err_Table_Missing )+ goto Exit;++ face->pclt.Version = 0;+ }++ /* consider the kerning and gasp tables as optional */+ LOAD_( gasp );+ LOAD_( kern );++ face->root.num_glyphs = face->max_profile.numGlyphs;++ /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes */+ /* a WWS-only font face. `WWS' stands for `weight', width', and */+ /* `slope', a term used by Microsoft's Windows Presentation */+ /* Foundation (WPF). This flag has been introduced in version */+ /* 1.5 of the OpenType specification (May 2008). */++ face->root.family_name = NULL;+ face->root.style_name = NULL;+ if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 256 )+ {+ if ( !ignore_preferred_family )+ GET_NAME( PREFERRED_FAMILY, &face->root.family_name );+ if ( !face->root.family_name )+ GET_NAME( FONT_FAMILY, &face->root.family_name );++ if ( !ignore_preferred_subfamily )+ GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name );+ if ( !face->root.style_name )+ GET_NAME( FONT_SUBFAMILY, &face->root.style_name );+ }+ else+ {+ GET_NAME( WWS_FAMILY, &face->root.family_name );+ if ( !face->root.family_name && !ignore_preferred_family )+ GET_NAME( PREFERRED_FAMILY, &face->root.family_name );+ if ( !face->root.family_name )+ GET_NAME( FONT_FAMILY, &face->root.family_name );++ GET_NAME( WWS_SUBFAMILY, &face->root.style_name );+ if ( !face->root.style_name && !ignore_preferred_subfamily )+ GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name );+ if ( !face->root.style_name )+ GET_NAME( FONT_SUBFAMILY, &face->root.style_name );+ }++ /* now set up root fields */+ {+ FT_Face root = &face->root;+ FT_Long flags = root->face_flags;+++ /*********************************************************************/+ /* */+ /* Compute face flags. */+ /* */+ if ( has_outline == TRUE )+ flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */++ /* The sfnt driver only supports bitmap fonts natively, thus we */+ /* don't set FT_FACE_FLAG_HINTER. */+ flags |= FT_FACE_FLAG_SFNT | /* SFNT file format */+ FT_FACE_FLAG_HORIZONTAL; /* horizontal data */++#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES+ if ( psnames_error == SFNT_Err_Ok &&+ face->postscript.FormatType != 0x00030000L )+ flags |= FT_FACE_FLAG_GLYPH_NAMES;+#endif++ /* fixed width font? */+ if ( face->postscript.isFixedPitch )+ flags |= FT_FACE_FLAG_FIXED_WIDTH;++ /* vertical information? */+ if ( face->vertical_info )+ flags |= FT_FACE_FLAG_VERTICAL;++ /* kerning available ? */+ if ( TT_FACE_HAS_KERNING( face ) )+ flags |= FT_FACE_FLAG_KERNING;++#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT+ /* Don't bother to load the tables unless somebody asks for them. */+ /* No need to do work which will (probably) not be used. */+ if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 &&+ tt_face_lookup_table( face, TTAG_fvar ) != 0 &&+ tt_face_lookup_table( face, TTAG_gvar ) != 0 )+ flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;+#endif++ root->face_flags = flags;++ /*********************************************************************/+ /* */+ /* Compute style flags. */+ /* */++ flags = 0;+ if ( has_outline == TRUE && face->os2.version != 0xFFFFU )+ {+ /* We have an OS/2 table; use the `fsSelection' field. Bit 9 */+ /* indicates an oblique font face. This flag has been */+ /* introduced in version 1.5 of the OpenType specification. */++ if ( face->os2.fsSelection & 512 ) /* bit 9 */+ flags |= FT_STYLE_FLAG_ITALIC;+ else if ( face->os2.fsSelection & 1 ) /* bit 0 */+ flags |= FT_STYLE_FLAG_ITALIC;++ if ( face->os2.fsSelection & 32 ) /* bit 5 */+ flags |= FT_STYLE_FLAG_BOLD;+ }+ else+ {+ /* this is an old Mac font, use the header field */++ if ( face->header.Mac_Style & 1 )+ flags |= FT_STYLE_FLAG_BOLD;++ if ( face->header.Mac_Style & 2 )+ flags |= FT_STYLE_FLAG_ITALIC;+ }++ root->style_flags = flags;++ /*********************************************************************/+ /* */+ /* Polish the charmaps. */+ /* */+ /* Try to set the charmap encoding according to the platform & */+ /* encoding ID of each charmap. */+ /* */++ tt_face_build_cmaps( face ); /* ignore errors */+++ /* set the encoding fields */+ {+ FT_Int m;+++ for ( m = 0; m < root->num_charmaps; m++ )+ {+ FT_CharMap charmap = root->charmaps[m];+++ charmap->encoding = sfnt_find_encoding( charmap->platform_id,+ charmap->encoding_id );++#if 0+ if ( root->charmap == NULL &&+ charmap->encoding == FT_ENCODING_UNICODE )+ {+ /* set 'root->charmap' to the first Unicode encoding we find */+ root->charmap = charmap;+ }+#endif+ }+ }++#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS++ /*+ * Now allocate the root array of FT_Bitmap_Size records and+ * populate them. Unfortunately, it isn't possible to indicate bit+ * depths in the FT_Bitmap_Size record. This is a design error.+ */+ {+ FT_UInt i, count;+++#ifndef FT_CONFIG_OPTION_OLD_INTERNALS+ count = face->sbit_num_strikes;+#else+ count = (FT_UInt)face->num_sbit_strikes;+#endif++ if ( count > 0 )+ {+ FT_Memory memory = face->root.stream->memory;+ FT_UShort em_size = face->header.Units_Per_EM;+ FT_Short avgwidth = face->os2.xAvgCharWidth;+ FT_Size_Metrics metrics;+++ if ( em_size == 0 || face->os2.version == 0xFFFFU )+ {+ avgwidth = 0;+ em_size = 1;+ }++ if ( FT_NEW_ARRAY( root->available_sizes, count ) )+ goto Exit;++ for ( i = 0; i < count; i++ )+ {+ FT_Bitmap_Size* bsize = root->available_sizes + i;+++ error = sfnt->load_strike_metrics( face, i, &metrics );+ if ( error )+ goto Exit;++ bsize->height = (FT_Short)( metrics.height >> 6 );+ bsize->width = (FT_Short)(+ ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size );++ bsize->x_ppem = metrics.x_ppem << 6;+ bsize->y_ppem = metrics.y_ppem << 6;++ /* assume 72dpi */+ bsize->size = metrics.y_ppem << 6;+ }++ root->face_flags |= FT_FACE_FLAG_FIXED_SIZES;+ root->num_fixed_sizes = (FT_Int)count;+ }+ }++#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */++ /* a font with no bitmaps and no outlines is scalable; */+ /* it has only empty glyphs then */+ if ( !FT_HAS_FIXED_SIZES( root ) && !FT_IS_SCALABLE( root ) )+ root->face_flags |= FT_FACE_FLAG_SCALABLE;+++ /*********************************************************************/+ /* */+ /* Set up metrics. */+ /* */+ if ( FT_IS_SCALABLE( root ) )+ {+ /* XXX What about if outline header is missing */+ /* (e.g. sfnt wrapped bitmap)? */+ root->bbox.xMin = face->header.xMin;+ root->bbox.yMin = face->header.yMin;+ root->bbox.xMax = face->header.xMax;+ root->bbox.yMax = face->header.yMax;+ root->units_per_EM = face->header.Units_Per_EM;+++ /* XXX: Computing the ascender/descender/height is very different */+ /* from what the specification tells you. Apparently, we */+ /* must be careful because */+ /* */+ /* - not all fonts have an OS/2 table; in this case, we take */+ /* the values in the horizontal header. However, these */+ /* values very often are not reliable. */+ /* */+ /* - otherwise, the correct typographic values are in the */+ /* sTypoAscender, sTypoDescender & sTypoLineGap fields. */+ /* */+ /* However, certain fonts have these fields set to 0. */+ /* Rather, they have usWinAscent & usWinDescent correctly */+ /* set (but with different values). */+ /* */+ /* As an example, Arial Narrow is implemented through four */+ /* files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */+ /* */+ /* Strangely, all fonts have the same values in their */+ /* sTypoXXX fields, except ARIALNB which sets them to 0. */+ /* */+ /* On the other hand, they all have different */+ /* usWinAscent/Descent values -- as a conclusion, the OS/2 */+ /* table cannot be used to compute the text height reliably! */+ /* */++ /* The ascender/descender/height are computed from the OS/2 table */+ /* when found. Otherwise, they're taken from the horizontal */+ /* header. */+ /* */++ root->ascender = face->horizontal.Ascender;+ root->descender = face->horizontal.Descender;++ root->height = (FT_Short)( root->ascender - root->descender ++ face->horizontal.Line_Gap );++#if 0+ /* if the line_gap is 0, we add an extra 15% to the text height -- */+ /* this computation is based on various versions of Times New Roman */+ if ( face->horizontal.Line_Gap == 0 )+ root->height = (FT_Short)( ( root->height * 115 + 50 ) / 100 );+#endif /* 0 */++#if 0+ /* some fonts have the OS/2 "sTypoAscender", "sTypoDescender" & */+ /* "sTypoLineGap" fields set to 0, like ARIALNB.TTF */+ if ( face->os2.version != 0xFFFFU && root->ascender )+ {+ FT_Int height;+++ root->ascender = face->os2.sTypoAscender;+ root->descender = -face->os2.sTypoDescender;++ height = root->ascender + root->descender + face->os2.sTypoLineGap;+ if ( height > root->height )+ root->height = height;+ }+#endif /* 0 */++ root->max_advance_width = face->horizontal.advance_Width_Max;+ root->max_advance_height = (FT_Short)( face->vertical_info+ ? face->vertical.advance_Height_Max+ : root->height );++ /* See http://www.microsoft.com/OpenType/OTSpec/post.htm -- */+ /* Adjust underline position from top edge to centre of */+ /* stroke to convert TrueType meaning to FreeType meaning. */+ root->underline_position = face->postscript.underlinePosition -+ face->postscript.underlineThickness / 2;+ root->underline_thickness = face->postscript.underlineThickness;+ }++ }++ Exit:+ FT_TRACE2(( "sfnt_load_face: done\n" ));++ return error;+ }+++#undef LOAD_+#undef LOADM_+#undef GET_NAME+++ FT_LOCAL_DEF( void )+ sfnt_done_face( TT_Face face )+ {+ FT_Memory memory;+ SFNT_Service sfnt;+++ if ( !face )+ return;++ memory = face->root.memory;+ sfnt = (SFNT_Service)face->sfnt;++ if ( sfnt )+ {+ /* destroy the postscript names table if it is loaded */+ if ( sfnt->free_psnames )+ sfnt->free_psnames( face );++ /* destroy the embedded bitmaps table if it is loaded */+ if ( sfnt->free_eblc )+ sfnt->free_eblc( face );+ }++#ifdef TT_CONFIG_OPTION_BDF+ /* freeing the embedded BDF properties */+ tt_face_free_bdf_props( face );+#endif++ /* freeing the kerning table */+ tt_face_done_kern( face );++ /* freeing the collection table */+ FT_FREE( face->ttc_header.offsets );+ face->ttc_header.count = 0;++ /* freeing table directory */+ FT_FREE( face->dir_tables );+ face->num_tables = 0;++ {+ FT_Stream stream = FT_FACE_STREAM( face );+++ /* simply release the 'cmap' table frame */+ FT_FRAME_RELEASE( face->cmap_table );+ face->cmap_size = 0;+ }++ /* freeing the horizontal metrics */+#ifndef FT_CONFIG_OPTION_OLD_INTERNALS+ {+ FT_Stream stream = FT_FACE_STREAM( face );+++ FT_FRAME_RELEASE( face->horz_metrics );+ FT_FRAME_RELEASE( face->vert_metrics );+ face->horz_metrics_size = 0;+ face->vert_metrics_size = 0;+ }+#else+ FT_FREE( face->horizontal.long_metrics );+ FT_FREE( face->horizontal.short_metrics );+#endif++ /* freeing the vertical ones, if any */+ if ( face->vertical_info )+ {+ FT_FREE( face->vertical.long_metrics );+ FT_FREE( face->vertical.short_metrics );+ face->vertical_info = 0;+ }++ /* freeing the gasp table */+ FT_FREE( face->gasp.gaspRanges );+ face->gasp.numRanges = 0;++ /* freeing the name table */+ if ( sfnt )+ sfnt->free_name( face );++ /* freeing family and style name */+ FT_FREE( face->root.family_name );+ FT_FREE( face->root.style_name );++ /* freeing sbit size table */+ FT_FREE( face->root.available_sizes );+ face->root.num_fixed_sizes = 0;++ FT_FREE( face->postscript_name );++ face->sfnt = 0;+ }+++/* END */
+ src/sfnt/sfobjs.h view
@@ -0,0 +1,54 @@+/***************************************************************************/+/* */+/* sfobjs.h */+/* */+/* SFNT object management (specification). */+/* */+/* Copyright 1996-2001, 2002 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 __SFOBJS_H__+#define __SFOBJS_H__+++#include <ft2build.h>+#include FT_INTERNAL_SFNT_H+#include FT_INTERNAL_OBJECTS_H+++FT_BEGIN_HEADER+++ FT_LOCAL( FT_Error )+ sfnt_init_face( FT_Stream stream,+ TT_Face face,+ FT_Int face_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 num_params,+ FT_Parameter* params );++ FT_LOCAL( void )+ sfnt_done_face( TT_Face face );+++FT_END_HEADER++#endif /* __SFDRIVER_H__ */+++/* END */
+ src/sfnt/ttbdf.c view
@@ -0,0 +1,250 @@+/***************************************************************************/+/* */+/* ttbdf.c */+/* */+/* TrueType and OpenType embedded BDF properties (body). */+/* */+/* Copyright 2005, 2006, 2010 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_STREAM_H+#include FT_TRUETYPE_TAGS_H+#include "ttbdf.h"++#include "sferrors.h"+++#ifdef TT_CONFIG_OPTION_BDF++ /*************************************************************************/+ /* */+ /* 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_ttbdf+++ FT_LOCAL_DEF( void )+ tt_face_free_bdf_props( TT_Face face )+ {+ TT_BDF bdf = &face->bdf;+++ if ( bdf->loaded )+ {+ FT_Stream stream = FT_FACE(face)->stream;+++ if ( bdf->table != NULL )+ FT_FRAME_RELEASE( bdf->table );++ bdf->table_end = NULL;+ bdf->strings = NULL;+ bdf->strings_size = 0;+ }+ }+++ static FT_Error+ tt_face_load_bdf_props( TT_Face face,+ FT_Stream stream )+ {+ TT_BDF bdf = &face->bdf;+ FT_ULong length;+ FT_Error error;+++ FT_ZERO( bdf );++ error = tt_face_goto_table( face, TTAG_BDF, stream, &length );+ if ( error ||+ length < 8 ||+ FT_FRAME_EXTRACT( length, bdf->table ) )+ {+ error = SFNT_Err_Invalid_Table;+ goto Exit;+ }++ bdf->table_end = bdf->table + length;++ {+ FT_Byte* p = bdf->table;+ FT_UInt version = FT_NEXT_USHORT( p );+ FT_UInt num_strikes = FT_NEXT_USHORT( p );+ FT_ULong strings = FT_NEXT_ULONG ( p );+ FT_UInt count;+ FT_Byte* strike;+++ if ( version != 0x0001 ||+ strings < 8 ||+ ( strings - 8 ) / 4 < num_strikes ||+ strings + 1 > length )+ {+ goto BadTable;+ }++ bdf->num_strikes = num_strikes;+ bdf->strings = bdf->table + strings;+ bdf->strings_size = length - strings;++ count = bdf->num_strikes;+ p = bdf->table + 8;+ strike = p + count * 4;+++ for ( ; count > 0; count-- )+ {+ FT_UInt num_items = FT_PEEK_USHORT( p + 2 );++ /*+ * We don't need to check the value sets themselves, since this+ * is done later.+ */+ strike += 10 * num_items;++ p += 4;+ }++ if ( strike > bdf->strings )+ goto BadTable;+ }++ bdf->loaded = 1;++ Exit:+ return error;++ BadTable:+ FT_FRAME_RELEASE( bdf->table );+ FT_ZERO( bdf );+ error = SFNT_Err_Invalid_Table;+ goto Exit;+ }+++ FT_LOCAL_DEF( FT_Error )+ tt_face_find_bdf_prop( TT_Face face,+ const char* property_name,+ BDF_PropertyRec *aprop )+ {+ TT_BDF bdf = &face->bdf;+ FT_Size size = FT_FACE(face)->size;+ FT_Error error = SFNT_Err_Ok;+ FT_Byte* p;+ FT_UInt count;+ FT_Byte* strike;+ FT_Offset property_len;+++ aprop->type = BDF_PROPERTY_TYPE_NONE;++ if ( bdf->loaded == 0 )+ {+ error = tt_face_load_bdf_props( face, FT_FACE( face )->stream );+ if ( error )+ goto Exit;+ }++ count = bdf->num_strikes;+ p = bdf->table + 8;+ strike = p + 4 * count;++ error = SFNT_Err_Invalid_Argument;++ if ( size == NULL || property_name == NULL )+ goto Exit;++ property_len = ft_strlen( property_name );+ if ( property_len == 0 )+ goto Exit;++ for ( ; count > 0; count-- )+ {+ FT_UInt _ppem = FT_NEXT_USHORT( p );+ FT_UInt _count = FT_NEXT_USHORT( p );++ if ( _ppem == size->metrics.y_ppem )+ {+ count = _count;+ goto FoundStrike;+ }++ strike += 10 * _count;+ }+ goto Exit;++ FoundStrike:+ p = strike;+ for ( ; count > 0; count-- )+ {+ FT_UInt type = FT_PEEK_USHORT( p + 4 );++ if ( ( type & 0x10 ) != 0 )+ {+ FT_UInt32 name_offset = FT_PEEK_ULONG( p );+ FT_UInt32 value = FT_PEEK_ULONG( p + 6 );++ /* be a bit paranoid for invalid entries here */+ if ( name_offset < bdf->strings_size &&+ property_len < bdf->strings_size - name_offset &&+ ft_strncmp( property_name,+ (const char*)bdf->strings + name_offset,+ bdf->strings_size - name_offset ) == 0 )+ {+ switch ( type & 0x0F )+ {+ case 0x00: /* string */+ case 0x01: /* atoms */+ /* check that the content is really 0-terminated */+ if ( value < bdf->strings_size &&+ ft_memchr( bdf->strings + value, 0, bdf->strings_size ) )+ {+ aprop->type = BDF_PROPERTY_TYPE_ATOM;+ aprop->u.atom = (const char*)bdf->strings + value;+ error = SFNT_Err_Ok;+ goto Exit;+ }+ break;++ case 0x02:+ aprop->type = BDF_PROPERTY_TYPE_INTEGER;+ aprop->u.integer = (FT_Int32)value;+ error = SFNT_Err_Ok;+ goto Exit;++ case 0x03:+ aprop->type = BDF_PROPERTY_TYPE_CARDINAL;+ aprop->u.cardinal = value;+ error = SFNT_Err_Ok;+ goto Exit;++ default:+ ;+ }+ }+ }+ p += 10;+ }++ Exit:+ return error;+ }++#endif /* TT_CONFIG_OPTION_BDF */+++/* END */
+ src/sfnt/ttbdf.h view
@@ -0,0 +1,46 @@+/***************************************************************************/+/* */+/* ttbdf.h */+/* */+/* TrueType and OpenType embedded BDF properties (specification). */+/* */+/* Copyright 2005 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 __TTBDF_H__+#define __TTBDF_H__+++#include <ft2build.h>+#include "ttload.h"+#include FT_BDF_H+++FT_BEGIN_HEADER+++ FT_LOCAL( void )+ tt_face_free_bdf_props( TT_Face face );+++ FT_LOCAL( FT_Error )+ tt_face_find_bdf_prop( TT_Face face,+ const char* property_name,+ BDF_PropertyRec *aprop );+++FT_END_HEADER++#endif /* __TTBDF_H__ */+++/* END */
+ src/sfnt/ttcmap.c view
@@ -0,0 +1,3512 @@+/***************************************************************************/+/* */+/* ttcmap.c */+/* */+/* TrueType character mapping table (cmap) support (body). */+/* */+/* Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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 "sferrors.h" /* must come before FT_INTERNAL_VALIDATE_H */++#include FT_INTERNAL_VALIDATE_H+#include FT_INTERNAL_STREAM_H+#include "ttload.h"+#include "ttcmap.h"+#include "sfntpic.h"+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_ttcmap+++#define TT_PEEK_SHORT FT_PEEK_SHORT+#define TT_PEEK_USHORT FT_PEEK_USHORT+#define TT_PEEK_UINT24 FT_PEEK_UOFF3+#define TT_PEEK_LONG FT_PEEK_LONG+#define TT_PEEK_ULONG FT_PEEK_ULONG++#define TT_NEXT_SHORT FT_NEXT_SHORT+#define TT_NEXT_USHORT FT_NEXT_USHORT+#define TT_NEXT_UINT24 FT_NEXT_UOFF3+#define TT_NEXT_LONG FT_NEXT_LONG+#define TT_NEXT_ULONG FT_NEXT_ULONG+++ FT_CALLBACK_DEF( FT_Error )+ tt_cmap_init( TT_CMap cmap,+ FT_Byte* table )+ {+ cmap->data = table;+ return SFNT_Err_Ok;+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** FORMAT 0 *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /*************************************************************************/+ /* */+ /* TABLE OVERVIEW */+ /* -------------- */+ /* */+ /* NAME OFFSET TYPE DESCRIPTION */+ /* */+ /* format 0 USHORT must be 0 */+ /* length 2 USHORT table length in bytes */+ /* language 4 USHORT Mac language code */+ /* glyph_ids 6 BYTE[256] array of glyph indices */+ /* 262 */+ /* */++#ifdef TT_CONFIG_CMAP_FORMAT_0++ FT_CALLBACK_DEF( FT_Error )+ tt_cmap0_validate( FT_Byte* table,+ FT_Validator valid )+ {+ FT_Byte* p = table + 2;+ FT_UInt length = TT_NEXT_USHORT( p );+++ if ( table + length > valid->limit || length < 262 )+ FT_INVALID_TOO_SHORT;++ /* check glyph indices whenever necessary */+ if ( valid->level >= FT_VALIDATE_TIGHT )+ {+ FT_UInt n, idx;+++ p = table + 6;+ for ( n = 0; n < 256; n++ )+ {+ idx = *p++;+ if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )+ FT_INVALID_GLYPH_ID;+ }+ }++ return SFNT_Err_Ok;+ }+++ FT_CALLBACK_DEF( FT_UInt )+ tt_cmap0_char_index( TT_CMap cmap,+ FT_UInt32 char_code )+ {+ FT_Byte* table = cmap->data;+++ return char_code < 256 ? table[6 + char_code] : 0;+ }+++ FT_CALLBACK_DEF( FT_UInt32 )+ tt_cmap0_char_next( TT_CMap cmap,+ FT_UInt32 *pchar_code )+ {+ FT_Byte* table = cmap->data;+ FT_UInt32 charcode = *pchar_code;+ FT_UInt32 result = 0;+ FT_UInt gindex = 0;+++ table += 6; /* go to glyph IDs */+ while ( ++charcode < 256 )+ {+ gindex = table[charcode];+ if ( gindex != 0 )+ {+ result = charcode;+ break;+ }+ }++ *pchar_code = result;+ return gindex;+ }+++ FT_CALLBACK_DEF( FT_Error )+ tt_cmap0_get_info( TT_CMap cmap,+ TT_CMapInfo *cmap_info )+ {+ FT_Byte* p = cmap->data + 4;+++ cmap_info->format = 0;+ cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );++ return SFNT_Err_Ok;+ }+++ FT_DEFINE_TT_CMAP(tt_cmap0_class_rec,+ sizeof ( TT_CMapRec ),++ (FT_CMap_InitFunc) tt_cmap_init,+ (FT_CMap_DoneFunc) NULL,+ (FT_CMap_CharIndexFunc)tt_cmap0_char_index,+ (FT_CMap_CharNextFunc) tt_cmap0_char_next,++ NULL, NULL, NULL, NULL, NULL+ ,+ 0,+ (TT_CMap_ValidateFunc) tt_cmap0_validate,+ (TT_CMap_Info_GetFunc) tt_cmap0_get_info+ )++#endif /* TT_CONFIG_CMAP_FORMAT_0 */+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** FORMAT 2 *****/+ /***** *****/+ /***** This is used for certain CJK encodings that encode text in a *****/+ /***** 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). *****/+ /***** *****/+ /***** * Certain byte values signal the first byte of a 2-byte *****/+ /***** character code (but these values are also valid as the *****/+ /***** second byte of a 2-byte character). *****/+ /***** *****/+ /***** The following charmap lookup and iteration functions all *****/+ /***** assume that the value "charcode" correspond to following: *****/+ /***** *****/+ /***** - 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: *****/+ /***** *****/+ /***** (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 *****/+ /***** arguments. *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /*************************************************************************/+ /* */+ /* TABLE OVERVIEW */+ /* -------------- */+ /* */+ /* NAME OFFSET TYPE DESCRIPTION */+ /* */+ /* format 0 USHORT must be 2 */+ /* length 2 USHORT table length in bytes */+ /* language 4 USHORT Mac language code */+ /* keys 6 USHORT[256] sub-header keys */+ /* subs 518 SUBHEAD[NSUBS] sub-headers array */+ /* glyph_ids 518+NSUB*8 USHORT[] glyph ID array */+ /* */+ /* The `keys' table is used to map charcode high-bytes to sub-headers. */+ /* The value of `NSUBS' is the number of sub-headers defined in the */+ /* table and is computed by finding the maximum of the `keys' table. */+ /* */+ /* Note that for any n, `keys[n]' is a byte offset within the `subs' */+ /* table, i.e., it is the corresponding sub-header index multiplied */+ /* by 8. */+ /* */+ /* Each sub-header has the following format: */+ /* */+ /* NAME OFFSET TYPE DESCRIPTION */+ /* */+ /* first 0 USHORT first valid low-byte */+ /* count 2 USHORT number of valid low-bytes */+ /* delta 4 SHORT see below */+ /* offset 6 USHORT see below */+ /* */+ /* A sub-header defines, for each high-byte, the range of valid */+ /* low-bytes within the charmap. Note that the range defined by `first' */+ /* and `count' must be completely included in the interval [0..255] */+ /* 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: */+ /* */+ /* * 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). */+ /* */+ /* * 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 */+ /* added to it (modulo 65536) to form a new glyph index. */+ /* */+ /* It is up to the validation routine to check that all offsets fall */+ /* within the glyph IDs table (and not within the `subs' table itself or */+ /* outside of the CMap). */+ /* */++#ifdef TT_CONFIG_CMAP_FORMAT_2++ FT_CALLBACK_DEF( FT_Error )+ tt_cmap2_validate( FT_Byte* table,+ FT_Validator valid )+ {+ FT_Byte* p = table + 2; /* skip format */+ FT_UInt length = TT_PEEK_USHORT( p );+ FT_UInt n, max_subs;+ FT_Byte* keys; /* keys table */+ FT_Byte* subs; /* sub-headers */+ FT_Byte* glyph_ids; /* glyph ID array */+++ if ( table + length > valid->limit || length < 6 + 512 )+ FT_INVALID_TOO_SHORT;++ keys = table + 6;++ /* parse keys to compute sub-headers count */+ p = keys;+ max_subs = 0;+ for ( n = 0; n < 256; n++ )+ {+ FT_UInt idx = TT_NEXT_USHORT( p );+++ /* value must be multiple of 8 */+ if ( valid->level >= FT_VALIDATE_PARANOID && ( idx & 7 ) != 0 )+ FT_INVALID_DATA;++ idx >>= 3;++ if ( idx > max_subs )+ max_subs = idx;+ }++ FT_ASSERT( p == table + 518 );++ subs = p;+ glyph_ids = subs + (max_subs + 1) * 8;+ if ( glyph_ids > valid->limit )+ FT_INVALID_TOO_SHORT;++ /* parse sub-headers */+ for ( n = 0; n <= max_subs; n++ )+ {+ FT_UInt first_code, code_count, offset;+ FT_Int delta;+ FT_Byte* ids;+++ first_code = TT_NEXT_USHORT( p );+ code_count = TT_NEXT_USHORT( p );+ delta = TT_NEXT_SHORT( p );+ offset = TT_NEXT_USHORT( p );++ /* many Dynalab fonts have empty sub-headers */+ if ( code_count == 0 )+ continue;++ /* check range within 0..255 */+ if ( valid->level >= FT_VALIDATE_PARANOID )+ {+ if ( first_code >= 256 || first_code + code_count > 256 )+ FT_INVALID_DATA;+ }++ /* check offset */+ if ( offset != 0 )+ {+ ids = p - 2 + offset;+ if ( ids < glyph_ids || ids + code_count*2 > table + length )+ FT_INVALID_OFFSET;++ /* check glyph IDs */+ if ( valid->level >= FT_VALIDATE_TIGHT )+ {+ FT_Byte* limit = p + code_count * 2;+ FT_UInt idx;+++ for ( ; p < limit; )+ {+ idx = TT_NEXT_USHORT( p );+ if ( idx != 0 )+ {+ idx = ( idx + delta ) & 0xFFFFU;+ if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )+ FT_INVALID_GLYPH_ID;+ }+ }+ }+ }+ }++ return SFNT_Err_Ok;+ }+++ /* return sub header corresponding to a given character code */+ /* NULL on invalid charcode */+ static FT_Byte*+ tt_cmap2_get_subheader( FT_Byte* table,+ FT_UInt32 char_code )+ {+ FT_Byte* result = NULL;+++ if ( char_code < 0x10000UL )+ {+ FT_UInt char_lo = (FT_UInt)( char_code & 0xFF );+ FT_UInt char_hi = (FT_UInt)( char_code >> 8 );+ FT_Byte* p = table + 6; /* keys table */+ FT_Byte* subs = table + 518; /* subheaders table */+ FT_Byte* sub;+++ if ( char_hi == 0 )+ {+ /* an 8-bit character code -- we use subHeader 0 in this case */+ /* to test whether the character code is in the charmap */+ /* */+ sub = subs; /* jump to first sub-header */++ /* check that the sub-header for this byte is 0, which */+ /* indicates that it is really a valid one-byte value */+ /* Otherwise, return 0 */+ /* */+ p += char_lo * 2;+ if ( TT_PEEK_USHORT( p ) != 0 )+ goto Exit;+ }+ else+ {+ /* a 16-bit character code */++ /* jump to key entry */+ p += char_hi * 2;+ /* jump to sub-header */+ sub = subs + ( FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 8 ) );++ /* check that the high byte isn't a valid one-byte value */+ if ( sub == subs )+ goto Exit;+ }+ result = sub;+ }+ Exit:+ return result;+ }+++ FT_CALLBACK_DEF( FT_UInt )+ tt_cmap2_char_index( TT_CMap cmap,+ FT_UInt32 char_code )+ {+ FT_Byte* table = cmap->data;+ FT_UInt result = 0;+ FT_Byte* subheader;+++ subheader = tt_cmap2_get_subheader( table, char_code );+ if ( subheader )+ {+ FT_Byte* p = subheader;+ FT_UInt idx = (FT_UInt)(char_code & 0xFF);+ FT_UInt start, count;+ FT_Int delta;+ FT_UInt offset;+++ start = TT_NEXT_USHORT( p );+ count = TT_NEXT_USHORT( p );+ delta = TT_NEXT_SHORT ( p );+ offset = TT_PEEK_USHORT( p );++ idx -= start;+ if ( idx < count && offset != 0 )+ {+ p += offset + 2 * idx;+ idx = TT_PEEK_USHORT( p );++ if ( idx != 0 )+ result = (FT_UInt)( idx + delta ) & 0xFFFFU;+ }+ }+ return result;+ }+++ FT_CALLBACK_DEF( FT_UInt32 )+ tt_cmap2_char_next( TT_CMap cmap,+ FT_UInt32 *pcharcode )+ {+ FT_Byte* table = cmap->data;+ FT_UInt gindex = 0;+ FT_UInt32 result = 0;+ FT_UInt32 charcode = *pcharcode + 1;+ FT_Byte* subheader;+++ while ( charcode < 0x10000UL )+ {+ subheader = tt_cmap2_get_subheader( table, charcode );+ if ( subheader )+ {+ FT_Byte* p = subheader;+ FT_UInt start = TT_NEXT_USHORT( p );+ FT_UInt count = TT_NEXT_USHORT( p );+ FT_Int delta = TT_NEXT_SHORT ( p );+ FT_UInt offset = TT_PEEK_USHORT( p );+ FT_UInt char_lo = (FT_UInt)( charcode & 0xFF );+ FT_UInt pos, idx;+++ if ( offset == 0 )+ goto Next_SubHeader;++ if ( char_lo < start )+ {+ char_lo = start;+ pos = 0;+ }+ else+ pos = (FT_UInt)( char_lo - start );++ p += offset + pos * 2;+ charcode = FT_PAD_FLOOR( charcode, 256 ) + char_lo;++ for ( ; pos < count; pos++, charcode++ )+ {+ idx = TT_NEXT_USHORT( p );++ if ( idx != 0 )+ {+ gindex = ( idx + delta ) & 0xFFFFU;+ if ( gindex != 0 )+ {+ result = charcode;+ goto Exit;+ }+ }+ }+ }++ /* jump to next sub-header, i.e. higher byte value */+ Next_SubHeader:+ charcode = FT_PAD_FLOOR( charcode, 256 ) + 256;+ }++ Exit:+ *pcharcode = result;++ return gindex;+ }+++ FT_CALLBACK_DEF( FT_Error )+ tt_cmap2_get_info( TT_CMap cmap,+ TT_CMapInfo *cmap_info )+ {+ FT_Byte* p = cmap->data + 4;+++ cmap_info->format = 2;+ cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );++ return SFNT_Err_Ok;+ }+++ FT_DEFINE_TT_CMAP(tt_cmap2_class_rec,+ sizeof ( TT_CMapRec ),++ (FT_CMap_InitFunc) tt_cmap_init,+ (FT_CMap_DoneFunc) NULL,+ (FT_CMap_CharIndexFunc)tt_cmap2_char_index,+ (FT_CMap_CharNextFunc) tt_cmap2_char_next,++ NULL, NULL, NULL, NULL, NULL+ ,+ 2,+ (TT_CMap_ValidateFunc) tt_cmap2_validate,+ (TT_CMap_Info_GetFunc) tt_cmap2_get_info+ )++#endif /* TT_CONFIG_CMAP_FORMAT_2 */+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** FORMAT 4 *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /*************************************************************************/+ /* */+ /* TABLE OVERVIEW */+ /* -------------- */+ /* */+ /* NAME OFFSET TYPE DESCRIPTION */+ /* */+ /* format 0 USHORT must be 4 */+ /* length 2 USHORT table length */+ /* in bytes */+ /* language 4 USHORT Mac language code */+ /* */+ /* segCountX2 6 USHORT 2*NUM_SEGS */+ /* searchRange 8 USHORT 2*(1 << LOG_SEGS) */+ /* entrySelector 10 USHORT LOG_SEGS */+ /* rangeShift 12 USHORT segCountX2 - */+ /* searchRange */+ /* */+ /* endCount 14 USHORT[NUM_SEGS] end charcode for */+ /* each segment; last */+ /* is 0xFFFF */+ /* */+ /* pad 14+NUM_SEGS*2 USHORT padding */+ /* */+ /* startCount 16+NUM_SEGS*2 USHORT[NUM_SEGS] first charcode for */+ /* each segment */+ /* */+ /* idDelta 16+NUM_SEGS*4 SHORT[NUM_SEGS] delta for each */+ /* segment */+ /* idOffset 16+NUM_SEGS*6 SHORT[NUM_SEGS] range offset for */+ /* each segment; can be */+ /* zero */+ /* */+ /* glyphIds 16+NUM_SEGS*8 USHORT[] array of glyph ID */+ /* ranges */+ /* */+ /* Character codes are modelled by a series of ordered (increasing) */+ /* intervals called segments. Each segment has start and end codes, */+ /* provided by the `startCount' and `endCount' arrays. Segments must */+ /* not overlap, and the last segment should always contain the value */+ /* 0xFFFF for `endCount'. */+ /* */+ /* The fields `searchRange', `entrySelector' and `rangeShift' are better */+ /* ignored (they are traces of over-engineering in the TrueType */+ /* specification). */+ /* */+ /* Each segment also has a signed `delta', as well as an optional offset */+ /* within the `glyphIds' table. */+ /* */+ /* If a segment's idOffset is 0, the glyph index corresponding to any */+ /* charcode within the segment is obtained by adding the value of */+ /* `idDelta' directly to the charcode, modulo 65536. */+ /* */+ /* Otherwise, a glyph index is taken from the glyph IDs sub-array for */+ /* the segment, and the value of `idDelta' is added to it. */+ /* */+ /* */+ /* Finally, note that a lot of fonts contain an invalid last segment, */+ /* where `start' and `end' are correctly set to 0xFFFF but both `delta' */+ /* and `offset' are incorrect (e.g., `opens___.ttf' which comes with */+ /* OpenOffice.org). We need special code to deal with them correctly. */+ /* */++#ifdef TT_CONFIG_CMAP_FORMAT_4++ typedef struct TT_CMap4Rec_+ {+ TT_CMapRec cmap;+ FT_UInt32 cur_charcode; /* current charcode */+ FT_UInt cur_gindex; /* current glyph index */++ FT_UInt num_ranges;+ FT_UInt cur_range;+ FT_UInt cur_start;+ FT_UInt cur_end;+ FT_Int cur_delta;+ FT_Byte* cur_values;++ } TT_CMap4Rec, *TT_CMap4;+++ FT_CALLBACK_DEF( FT_Error )+ tt_cmap4_init( TT_CMap4 cmap,+ FT_Byte* table )+ {+ FT_Byte* p;+++ cmap->cmap.data = table;++ p = table + 6;+ cmap->num_ranges = FT_PEEK_USHORT( p ) >> 1;+ cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL;+ cmap->cur_gindex = 0;++ return SFNT_Err_Ok;+ }+++ static FT_Int+ tt_cmap4_set_range( TT_CMap4 cmap,+ FT_UInt range_index )+ {+ FT_Byte* table = cmap->cmap.data;+ FT_Byte* p;+ FT_UInt num_ranges = cmap->num_ranges;+++ while ( range_index < num_ranges )+ {+ FT_UInt offset;+++ p = table + 14 + range_index * 2;+ cmap->cur_end = FT_PEEK_USHORT( p );++ p += 2 + num_ranges * 2;+ cmap->cur_start = FT_PEEK_USHORT( p );++ p += num_ranges * 2;+ cmap->cur_delta = FT_PEEK_SHORT( p );++ p += num_ranges * 2;+ offset = FT_PEEK_USHORT( p );++ /* some fonts have an incorrect last segment; */+ /* we have to catch it */+ if ( range_index >= num_ranges - 1 &&+ cmap->cur_start == 0xFFFFU &&+ cmap->cur_end == 0xFFFFU )+ {+ TT_Face face = (TT_Face)cmap->cmap.cmap.charmap.face;+ FT_Byte* limit = face->cmap_table + face->cmap_size;+++ if ( offset && p + offset + 2 > limit )+ {+ cmap->cur_delta = 1;+ offset = 0;+ }+ }++ if ( offset != 0xFFFFU )+ {+ cmap->cur_values = offset ? p + offset : NULL;+ cmap->cur_range = range_index;+ return 0;+ }++ /* we skip empty segments */+ range_index++;+ }++ return -1;+ }+++ /* search the index of the charcode next to cmap->cur_charcode; */+ /* caller should call tt_cmap4_set_range with proper range */+ /* before calling this function */+ /* */+ static void+ tt_cmap4_next( TT_CMap4 cmap )+ {+ FT_UInt charcode;+++ if ( cmap->cur_charcode >= 0xFFFFUL )+ goto Fail;++ charcode = (FT_UInt)cmap->cur_charcode + 1;++ if ( charcode < cmap->cur_start )+ charcode = cmap->cur_start;++ for ( ;; )+ {+ FT_Byte* values = cmap->cur_values;+ FT_UInt end = cmap->cur_end;+ FT_Int delta = cmap->cur_delta;+++ if ( charcode <= end )+ {+ if ( values )+ {+ FT_Byte* p = values + 2 * ( charcode - cmap->cur_start );+++ do+ {+ FT_UInt gindex = FT_NEXT_USHORT( p );+++ if ( gindex != 0 )+ {+ gindex = (FT_UInt)( ( gindex + delta ) & 0xFFFFU );+ if ( gindex != 0 )+ {+ cmap->cur_charcode = charcode;+ cmap->cur_gindex = gindex;+ return;+ }+ }+ } while ( ++charcode <= end );+ }+ else+ {+ do+ {+ FT_UInt gindex = (FT_UInt)( ( charcode + delta ) & 0xFFFFU );+++ if ( gindex != 0 )+ {+ cmap->cur_charcode = charcode;+ cmap->cur_gindex = gindex;+ return;+ }+ } while ( ++charcode <= end );+ }+ }++ /* we need to find another range */+ if ( tt_cmap4_set_range( cmap, cmap->cur_range + 1 ) < 0 )+ break;++ if ( charcode < cmap->cur_start )+ charcode = cmap->cur_start;+ }++ Fail:+ cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL;+ cmap->cur_gindex = 0;+ }+++ FT_CALLBACK_DEF( FT_Error )+ tt_cmap4_validate( FT_Byte* table,+ FT_Validator valid )+ {+ FT_Byte* p = table + 2; /* skip format */+ FT_UInt length = TT_NEXT_USHORT( p );+ FT_Byte *ends, *starts, *offsets, *deltas, *glyph_ids;+ FT_UInt num_segs;+ FT_Error error = SFNT_Err_Ok;+++ if ( length < 16 )+ FT_INVALID_TOO_SHORT;++ /* in certain fonts, the `length' field is invalid and goes */+ /* out of bound. We try to correct this here... */+ if ( table + length > valid->limit )+ {+ if ( valid->level >= FT_VALIDATE_TIGHT )+ FT_INVALID_TOO_SHORT;++ length = (FT_UInt)( valid->limit - table );+ }++ p = table + 6;+ num_segs = TT_NEXT_USHORT( p ); /* read segCountX2 */++ if ( valid->level >= FT_VALIDATE_PARANOID )+ {+ /* check that we have an even value here */+ if ( num_segs & 1 )+ FT_INVALID_DATA;+ }++ num_segs /= 2;++ if ( length < 16 + num_segs * 2 * 4 )+ FT_INVALID_TOO_SHORT;++ /* check the search parameters - even though we never use them */+ /* */+ if ( valid->level >= FT_VALIDATE_PARANOID )+ {+ /* check the values of `searchRange', `entrySelector', `rangeShift' */+ FT_UInt search_range = TT_NEXT_USHORT( p );+ FT_UInt entry_selector = TT_NEXT_USHORT( p );+ FT_UInt range_shift = TT_NEXT_USHORT( p );+++ if ( ( search_range | range_shift ) & 1 ) /* must be even values */+ FT_INVALID_DATA;++ search_range /= 2;+ range_shift /= 2;++ /* `search range' is the greatest power of 2 that is <= num_segs */++ if ( search_range > num_segs ||+ search_range * 2 < num_segs ||+ search_range + range_shift != num_segs ||+ search_range != ( 1U << entry_selector ) )+ FT_INVALID_DATA;+ }++ ends = table + 14;+ starts = table + 16 + num_segs * 2;+ deltas = starts + num_segs * 2;+ offsets = deltas + num_segs * 2;+ glyph_ids = offsets + num_segs * 2;++ /* check last segment; its end count value must be 0xFFFF */+ if ( valid->level >= FT_VALIDATE_PARANOID )+ {+ p = ends + ( num_segs - 1 ) * 2;+ if ( TT_PEEK_USHORT( p ) != 0xFFFFU )+ FT_INVALID_DATA;+ }++ {+ FT_UInt start, end, offset, n;+ FT_UInt last_start = 0, last_end = 0;+ FT_Int delta;+ FT_Byte* p_start = starts;+ FT_Byte* p_end = ends;+ FT_Byte* p_delta = deltas;+ FT_Byte* p_offset = offsets;+++ for ( n = 0; n < num_segs; n++ )+ {+ p = p_offset;+ start = TT_NEXT_USHORT( p_start );+ end = TT_NEXT_USHORT( p_end );+ delta = TT_NEXT_SHORT( p_delta );+ offset = TT_NEXT_USHORT( p_offset );++ if ( start > end )+ FT_INVALID_DATA;++ /* this test should be performed at default validation level; */+ /* unfortunately, some popular Asian fonts have overlapping */+ /* ranges in their charmaps */+ /* */+ if ( start <= last_end && n > 0 )+ {+ if ( valid->level >= FT_VALIDATE_TIGHT )+ FT_INVALID_DATA;+ else+ {+ /* allow overlapping segments, provided their start points */+ /* and end points, respectively, are in ascending order */+ /* */+ if ( last_start > start || last_end > end )+ error |= TT_CMAP_FLAG_UNSORTED;+ else+ error |= TT_CMAP_FLAG_OVERLAPPING;+ }+ }++ if ( offset && offset != 0xFFFFU )+ {+ p += offset; /* start of glyph ID array */++ /* check that we point within the glyph IDs table only */+ if ( valid->level >= FT_VALIDATE_TIGHT )+ {+ if ( p < glyph_ids ||+ p + ( end - start + 1 ) * 2 > table + length )+ FT_INVALID_DATA;+ }+ /* Some fonts handle the last segment incorrectly. In */+ /* theory, 0xFFFF might point to an ordinary glyph -- */+ /* a cmap 4 is versatile and could be used for any */+ /* encoding, not only Unicode. However, reality shows */+ /* that far too many fonts are sloppy and incorrectly */+ /* set all fields but `start' and `end' for the last */+ /* segment if it contains only a single character. */+ /* */+ /* We thus omit the test here, delaying it to the */+ /* routines which actually access the cmap. */+ else if ( n != num_segs - 1 ||+ !( start == 0xFFFFU && end == 0xFFFFU ) )+ {+ if ( p < glyph_ids ||+ p + ( end - start + 1 ) * 2 > valid->limit )+ FT_INVALID_DATA;+ }++ /* check glyph indices within the segment range */+ if ( valid->level >= FT_VALIDATE_TIGHT )+ {+ FT_UInt i, idx;+++ for ( i = start; i < end; i++ )+ {+ idx = FT_NEXT_USHORT( p );+ if ( idx != 0 )+ {+ idx = (FT_UInt)( idx + delta ) & 0xFFFFU;++ if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )+ FT_INVALID_GLYPH_ID;+ }+ }+ }+ }+ else if ( offset == 0xFFFFU )+ {+ /* some fonts (erroneously?) use a range offset of 0xFFFF */+ /* to mean missing glyph in cmap table */+ /* */+ if ( valid->level >= FT_VALIDATE_PARANOID ||+ n != num_segs - 1 ||+ !( start == 0xFFFFU && end == 0xFFFFU ) )+ FT_INVALID_DATA;+ }++ last_start = start;+ last_end = end;+ }+ }++ return error;+ }+++ static FT_UInt+ tt_cmap4_char_map_linear( TT_CMap cmap,+ FT_UInt32* pcharcode,+ FT_Bool next )+ {+ 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;+++ p = cmap->data + 6;+ num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 );++ num_segs = num_segs2 >> 1;++ if ( !num_segs )+ return 0;++ if ( next )+ charcode++;++ /* 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 );++ if ( charcode >= start && charcode <= end )+ {+ 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 )+ {+ TT_Face face = (TT_Face)cmap->cmap.charmap.face;+ FT_Byte* limit = face->cmap_table + face->cmap_size;+++ if ( offset && p + offset + 2 > limit )+ {+ delta = 1;+ offset = 0;+ }+ }++ if ( offset == 0xFFFFU )+ continue;++ if ( offset )+ {+ p += offset + ( charcode - start ) * 2;+ gindex = TT_PEEK_USHORT( p );+ if ( gindex != 0 )+ gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;+ }+ else+ gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU;++ break;+ }+ }++ if ( !next || gindex )+ break;+ }++ if ( next && gindex )+ *pcharcode = charcode;++ return gindex;+ }+++ static FT_UInt+ tt_cmap4_char_map_binary( TT_CMap cmap,+ FT_UInt32* pcharcode,+ FT_Bool next )+ {+ FT_UInt num_segs2, start, end, offset;+ FT_Int delta;+ FT_UInt max, min, mid, num_segs;+ FT_UInt charcode = (FT_UInt)*pcharcode;+ FT_UInt gindex = 0;+ FT_Byte* p;+++ p = cmap->data + 6;+ num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 );++ if ( !num_segs2 )+ return 0;++ num_segs = num_segs2 >> 1;++ /* make compiler happy */+ mid = num_segs;+ end = 0xFFFFU;++ if ( next )+ charcode++;++ min = 0;+ max = num_segs;++ /* binary search */+ while ( min < max )+ {+ mid = ( min + max ) >> 1;+ p = cmap->data + 14 + mid * 2;+ end = TT_PEEK_USHORT( p );+ p += 2 + num_segs2;+ start = TT_PEEK_USHORT( p );++ if ( charcode < start )+ max = mid;+ else if ( charcode > end )+ min = mid + 1;+ else+ {+ p += 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 ( mid >= num_segs - 1 &&+ start == 0xFFFFU && end == 0xFFFFU )+ {+ TT_Face face = (TT_Face)cmap->cmap.charmap.face;+ FT_Byte* limit = face->cmap_table + face->cmap_size;+++ if ( offset && p + offset + 2 > limit )+ {+ delta = 1;+ offset = 0;+ }+ }++ /* search the first segment containing `charcode' */+ if ( cmap->flags & TT_CMAP_FLAG_OVERLAPPING )+ {+ FT_UInt i;+++ /* call the current segment `max' */+ max = mid;++ if ( offset == 0xFFFFU )+ mid = max + 1;++ /* search in segments before the current segment */+ for ( i = max ; i > 0; i-- )+ {+ FT_UInt prev_end;+ FT_Byte* old_p;+++ old_p = p;+ p = cmap->data + 14 + ( i - 1 ) * 2;+ prev_end = TT_PEEK_USHORT( p );++ if ( charcode > prev_end )+ {+ p = old_p;+ break;+ }++ end = prev_end;+ p += 2 + num_segs2;+ start = TT_PEEK_USHORT( p );+ p += num_segs2;+ delta = TT_PEEK_SHORT( p );+ p += num_segs2;+ offset = TT_PEEK_USHORT( p );++ if ( offset != 0xFFFFU )+ mid = i - 1;+ }++ /* no luck */+ if ( mid == max + 1 )+ {+ if ( i != max )+ {+ p = cmap->data + 14 + max * 2;+ end = TT_PEEK_USHORT( p );+ p += 2 + num_segs2;+ start = TT_PEEK_USHORT( p );+ p += num_segs2;+ delta = TT_PEEK_SHORT( p );+ p += num_segs2;+ offset = TT_PEEK_USHORT( p );+ }++ mid = max;++ /* search in segments after the current segment */+ for ( i = max + 1; i < num_segs; i++ )+ {+ FT_UInt next_end, next_start;+++ p = cmap->data + 14 + i * 2;+ next_end = TT_PEEK_USHORT( p );+ p += 2 + num_segs2;+ next_start = TT_PEEK_USHORT( p );++ if ( charcode < next_start )+ break;++ end = next_end;+ start = next_start;+ p += num_segs2;+ delta = TT_PEEK_SHORT( p );+ p += num_segs2;+ offset = TT_PEEK_USHORT( p );++ if ( offset != 0xFFFFU )+ mid = i;+ }+ i--;++ /* still no luck */+ if ( mid == max )+ {+ mid = i;++ break;+ }+ }++ /* end, start, delta, and offset are for the i'th segment */+ if ( mid != i )+ {+ p = cmap->data + 14 + mid * 2;+ end = TT_PEEK_USHORT( p );+ p += 2 + num_segs2;+ start = TT_PEEK_USHORT( p );+ p += num_segs2;+ delta = TT_PEEK_SHORT( p );+ p += num_segs2;+ offset = TT_PEEK_USHORT( p );+ }+ }+ else+ {+ if ( offset == 0xFFFFU )+ break;+ }++ if ( offset )+ {+ p += offset + ( charcode - start ) * 2;+ gindex = TT_PEEK_USHORT( p );+ if ( gindex != 0 )+ gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;+ }+ else+ gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU;++ break;+ }+ }++ if ( next )+ {+ TT_CMap4 cmap4 = (TT_CMap4)cmap;+++ /* if `charcode' is not in any segment, then `mid' is */+ /* the segment nearest to `charcode' */+ /* */++ if ( charcode > end )+ {+ mid++;+ if ( mid == num_segs )+ return 0;+ }++ if ( tt_cmap4_set_range( cmap4, mid ) )+ {+ if ( gindex )+ *pcharcode = charcode;+ }+ else+ {+ cmap4->cur_charcode = charcode;++ if ( gindex )+ cmap4->cur_gindex = gindex;+ else+ {+ cmap4->cur_charcode = charcode;+ tt_cmap4_next( cmap4 );+ gindex = cmap4->cur_gindex;+ }++ if ( gindex )+ *pcharcode = cmap4->cur_charcode;+ }+ }++ return gindex;+ }+++ FT_CALLBACK_DEF( FT_UInt )+ tt_cmap4_char_index( TT_CMap cmap,+ FT_UInt32 char_code )+ {+ if ( char_code >= 0x10000UL )+ return 0;++ if ( cmap->flags & TT_CMAP_FLAG_UNSORTED )+ return tt_cmap4_char_map_linear( cmap, &char_code, 0 );+ else+ return tt_cmap4_char_map_binary( cmap, &char_code, 0 );+ }+++ FT_CALLBACK_DEF( FT_UInt32 )+ tt_cmap4_char_next( TT_CMap cmap,+ FT_UInt32 *pchar_code )+ {+ FT_UInt gindex;+++ if ( *pchar_code >= 0xFFFFU )+ return 0;++ if ( cmap->flags & TT_CMAP_FLAG_UNSORTED )+ gindex = tt_cmap4_char_map_linear( cmap, pchar_code, 1 );+ else+ {+ TT_CMap4 cmap4 = (TT_CMap4)cmap;+++ /* no need to search */+ if ( *pchar_code == cmap4->cur_charcode )+ {+ tt_cmap4_next( cmap4 );+ gindex = cmap4->cur_gindex;+ if ( gindex )+ *pchar_code = cmap4->cur_charcode;+ }+ else+ gindex = tt_cmap4_char_map_binary( cmap, pchar_code, 1 );+ }++ return gindex;+ }+++ FT_CALLBACK_DEF( FT_Error )+ tt_cmap4_get_info( TT_CMap cmap,+ TT_CMapInfo *cmap_info )+ {+ FT_Byte* p = cmap->data + 4;+++ cmap_info->format = 4;+ cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );++ return SFNT_Err_Ok;+ }+++ FT_DEFINE_TT_CMAP(tt_cmap4_class_rec,+ sizeof ( TT_CMap4Rec ),+ (FT_CMap_InitFunc) tt_cmap4_init,+ (FT_CMap_DoneFunc) NULL,+ (FT_CMap_CharIndexFunc)tt_cmap4_char_index,+ (FT_CMap_CharNextFunc) tt_cmap4_char_next,++ NULL, NULL, NULL, NULL, NULL+ ,+ 4,+ (TT_CMap_ValidateFunc) tt_cmap4_validate,+ (TT_CMap_Info_GetFunc) tt_cmap4_get_info+ )++#endif /* TT_CONFIG_CMAP_FORMAT_4 */+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** FORMAT 6 *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /*************************************************************************/+ /* */+ /* TABLE OVERVIEW */+ /* -------------- */+ /* */+ /* NAME OFFSET TYPE DESCRIPTION */+ /* */+ /* format 0 USHORT must be 4 */+ /* length 2 USHORT table length in bytes */+ /* language 4 USHORT Mac language code */+ /* */+ /* first 6 USHORT first segment code */+ /* count 8 USHORT segment size in chars */+ /* glyphIds 10 USHORT[count] glyph IDs */+ /* */+ /* A very simplified segment mapping. */+ /* */++#ifdef TT_CONFIG_CMAP_FORMAT_6++ FT_CALLBACK_DEF( FT_Error )+ tt_cmap6_validate( FT_Byte* table,+ FT_Validator valid )+ {+ FT_Byte* p;+ FT_UInt length, count;+++ if ( table + 10 > valid->limit )+ FT_INVALID_TOO_SHORT;++ p = table + 2;+ length = TT_NEXT_USHORT( p );++ p = table + 8; /* skip language and start index */+ count = TT_NEXT_USHORT( p );++ if ( table + length > valid->limit || length < 10 + count * 2 )+ FT_INVALID_TOO_SHORT;++ /* check glyph indices */+ if ( valid->level >= FT_VALIDATE_TIGHT )+ {+ FT_UInt gindex;+++ for ( ; count > 0; count-- )+ {+ gindex = TT_NEXT_USHORT( p );+ if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )+ FT_INVALID_GLYPH_ID;+ }+ }++ return SFNT_Err_Ok;+ }+++ FT_CALLBACK_DEF( FT_UInt )+ tt_cmap6_char_index( TT_CMap cmap,+ FT_UInt32 char_code )+ {+ FT_Byte* table = cmap->data;+ FT_UInt result = 0;+ FT_Byte* p = table + 6;+ FT_UInt start = TT_NEXT_USHORT( p );+ FT_UInt count = TT_NEXT_USHORT( p );+ FT_UInt idx = (FT_UInt)( char_code - start );+++ if ( idx < count )+ {+ p += 2 * idx;+ result = TT_PEEK_USHORT( p );+ }+ return result;+ }+++ FT_CALLBACK_DEF( FT_UInt32 )+ tt_cmap6_char_next( TT_CMap cmap,+ FT_UInt32 *pchar_code )+ {+ FT_Byte* table = cmap->data;+ FT_UInt32 result = 0;+ FT_UInt32 char_code = *pchar_code + 1;+ FT_UInt gindex = 0;++ FT_Byte* p = table + 6;+ FT_UInt start = TT_NEXT_USHORT( p );+ FT_UInt count = TT_NEXT_USHORT( p );+ FT_UInt idx;+++ if ( char_code >= 0x10000UL )+ goto Exit;++ if ( char_code < start )+ char_code = start;++ idx = (FT_UInt)( char_code - start );+ p += 2 * idx;++ for ( ; idx < count; idx++ )+ {+ gindex = TT_NEXT_USHORT( p );+ if ( gindex != 0 )+ {+ result = char_code;+ break;+ }+ char_code++;+ }++ Exit:+ *pchar_code = result;+ return gindex;+ }+++ FT_CALLBACK_DEF( FT_Error )+ tt_cmap6_get_info( TT_CMap cmap,+ TT_CMapInfo *cmap_info )+ {+ FT_Byte* p = cmap->data + 4;+++ cmap_info->format = 6;+ cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );++ return SFNT_Err_Ok;+ }+++ FT_DEFINE_TT_CMAP(tt_cmap6_class_rec,+ sizeof ( TT_CMapRec ),++ (FT_CMap_InitFunc) tt_cmap_init,+ (FT_CMap_DoneFunc) NULL,+ (FT_CMap_CharIndexFunc)tt_cmap6_char_index,+ (FT_CMap_CharNextFunc) tt_cmap6_char_next,++ NULL, NULL, NULL, NULL, NULL+ ,+ 6,+ (TT_CMap_ValidateFunc) tt_cmap6_validate,+ (TT_CMap_Info_GetFunc) tt_cmap6_get_info+ )++#endif /* TT_CONFIG_CMAP_FORMAT_6 */+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** FORMAT 8 *****/+ /***** *****/+ /***** It is hard to completely understand what the OpenType spec *****/+ /***** says about this format, but here is my conclusion. *****/+ /***** *****/+ /***** 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: *****/+ /***** *****/+ /***** - A 16-bit value that isn't part of the Unicode Surrogates *****/+ /***** Area (i.e. U+D800-U+DFFF). *****/+ /***** *****/+ /***** - A 32-bit value, made of two surrogate values, i.e.. if *****/+ /***** `char_code = (char_hi << 16) | char_lo', then both *****/+ /***** `char_hi' and `char_lo' must be in the Surrogates Area. *****/+ /***** Area. *****/+ /***** *****/+ /***** 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: *****/+ /***** *****/+ /***** If `char_hi == 0' then we must have `is32[char_lo] == 0'. *****/+ /***** *****/+ /***** If `char_hi != 0' then we must have both *****/+ /***** `is32[char_hi] != 0' and `is32[char_lo] != 0'. *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /*************************************************************************/+ /* */+ /* TABLE OVERVIEW */+ /* -------------- */+ /* */+ /* NAME OFFSET TYPE DESCRIPTION */+ /* */+ /* format 0 USHORT must be 8 */+ /* reserved 2 USHORT reserved */+ /* length 4 ULONG length in bytes */+ /* language 8 ULONG Mac language code */+ /* is32 12 BYTE[8192] 32-bitness bitmap */+ /* count 8204 ULONG number of groups */+ /* */+ /* This header is followed by `count' groups of the following format: */+ /* */+ /* start 0 ULONG first charcode */+ /* end 4 ULONG last charcode */+ /* startId 8 ULONG start glyph ID for the group */+ /* */++#ifdef TT_CONFIG_CMAP_FORMAT_8++ FT_CALLBACK_DEF( FT_Error )+ tt_cmap8_validate( FT_Byte* table,+ FT_Validator valid )+ {+ FT_Byte* p = table + 4;+ FT_Byte* is32;+ FT_UInt32 length;+ FT_UInt32 num_groups;+++ if ( table + 16 + 8192 > valid->limit )+ FT_INVALID_TOO_SHORT;++ length = TT_NEXT_ULONG( p );+ if ( length > (FT_UInt32)( valid->limit - table ) || length < 8192 + 16 )+ FT_INVALID_TOO_SHORT;++ is32 = table + 12;+ p = is32 + 8192; /* skip `is32' array */+ num_groups = TT_NEXT_ULONG( p );++ if ( p + num_groups * 12 > valid->limit )+ FT_INVALID_TOO_SHORT;++ /* check groups, they must be in increasing order */+ {+ FT_UInt32 n, start, end, start_id, count, last = 0;+++ for ( n = 0; n < num_groups; n++ )+ {+ FT_UInt hi, lo;+++ start = TT_NEXT_ULONG( p );+ end = TT_NEXT_ULONG( p );+ start_id = TT_NEXT_ULONG( p );++ if ( start > end )+ FT_INVALID_DATA;++ if ( n > 0 && start <= last )+ FT_INVALID_DATA;++ if ( valid->level >= FT_VALIDATE_TIGHT )+ {+ if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )+ FT_INVALID_GLYPH_ID;++ count = (FT_UInt32)( end - start + 1 );++ if ( start & ~0xFFFFU )+ {+ /* start_hi != 0; check that is32[i] is 1 for each i in */+ /* the `hi' and `lo' of the range [start..end] */+ for ( ; count > 0; count--, start++ )+ {+ hi = (FT_UInt)( start >> 16 );+ lo = (FT_UInt)( start & 0xFFFFU );++ if ( (is32[hi >> 3] & ( 0x80 >> ( hi & 7 ) ) ) == 0 )+ FT_INVALID_DATA;++ if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) == 0 )+ FT_INVALID_DATA;+ }+ }+ else+ {+ /* start_hi == 0; check that is32[i] is 0 for each i in */+ /* the range [start..end] */++ /* end_hi cannot be != 0! */+ if ( end & ~0xFFFFU )+ FT_INVALID_DATA;++ for ( ; count > 0; count--, start++ )+ {+ lo = (FT_UInt)( start & 0xFFFFU );++ if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) != 0 )+ FT_INVALID_DATA;+ }+ }+ }++ last = end;+ }+ }++ return SFNT_Err_Ok;+ }+++ FT_CALLBACK_DEF( FT_UInt )+ tt_cmap8_char_index( TT_CMap cmap,+ FT_UInt32 char_code )+ {+ FT_Byte* table = cmap->data;+ FT_UInt result = 0;+ FT_Byte* p = table + 8204;+ FT_UInt32 num_groups = TT_NEXT_ULONG( p );+ FT_UInt32 start, end, start_id;+++ for ( ; num_groups > 0; num_groups-- )+ {+ start = TT_NEXT_ULONG( p );+ end = TT_NEXT_ULONG( p );+ start_id = TT_NEXT_ULONG( p );++ if ( char_code < start )+ break;++ if ( char_code <= end )+ {+ result = (FT_UInt)( start_id + char_code - start );+ break;+ }+ }+ return result;+ }+++ FT_CALLBACK_DEF( FT_UInt32 )+ tt_cmap8_char_next( TT_CMap cmap,+ FT_UInt32 *pchar_code )+ {+ FT_UInt32 result = 0;+ FT_UInt32 char_code = *pchar_code + 1;+ FT_UInt gindex = 0;+ FT_Byte* table = cmap->data;+ FT_Byte* p = table + 8204;+ FT_UInt32 num_groups = TT_NEXT_ULONG( p );+ FT_UInt32 start, end, start_id;+++ p = table + 8208;++ for ( ; num_groups > 0; num_groups-- )+ {+ start = TT_NEXT_ULONG( p );+ end = TT_NEXT_ULONG( p );+ start_id = TT_NEXT_ULONG( p );++ if ( char_code < start )+ char_code = start;++ if ( char_code <= end )+ {+ gindex = (FT_UInt)( char_code - start + start_id );+ if ( gindex != 0 )+ {+ result = char_code;+ goto Exit;+ }+ }+ }++ Exit:+ *pchar_code = result;+ return gindex;+ }+++ FT_CALLBACK_DEF( FT_Error )+ tt_cmap8_get_info( TT_CMap cmap,+ TT_CMapInfo *cmap_info )+ {+ FT_Byte* p = cmap->data + 8;+++ cmap_info->format = 8;+ cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );++ return SFNT_Err_Ok;+ }+++ FT_DEFINE_TT_CMAP(tt_cmap8_class_rec,+ sizeof ( TT_CMapRec ),++ (FT_CMap_InitFunc) tt_cmap_init,+ (FT_CMap_DoneFunc) NULL,+ (FT_CMap_CharIndexFunc)tt_cmap8_char_index,+ (FT_CMap_CharNextFunc) tt_cmap8_char_next,++ NULL, NULL, NULL, NULL, NULL+ ,+ 8,+ (TT_CMap_ValidateFunc) tt_cmap8_validate,+ (TT_CMap_Info_GetFunc) tt_cmap8_get_info+ )++#endif /* TT_CONFIG_CMAP_FORMAT_8 */+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** FORMAT 10 *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /*************************************************************************/+ /* */+ /* TABLE OVERVIEW */+ /* -------------- */+ /* */+ /* NAME OFFSET TYPE DESCRIPTION */+ /* */+ /* format 0 USHORT must be 10 */+ /* reserved 2 USHORT reserved */+ /* length 4 ULONG length in bytes */+ /* language 8 ULONG Mac language code */+ /* */+ /* start 12 ULONG first char in range */+ /* count 16 ULONG number of chars in range */+ /* glyphIds 20 USHORT[count] glyph indices covered */+ /* */++#ifdef TT_CONFIG_CMAP_FORMAT_10++ FT_CALLBACK_DEF( FT_Error )+ tt_cmap10_validate( FT_Byte* table,+ FT_Validator valid )+ {+ FT_Byte* p = table + 4;+ FT_ULong length, count;+++ if ( table + 20 > valid->limit )+ FT_INVALID_TOO_SHORT;++ length = TT_NEXT_ULONG( p );+ p = table + 16;+ count = TT_NEXT_ULONG( p );++ if ( length > (FT_ULong)( valid->limit - table ) ||+ length < 20 + count * 2 )+ FT_INVALID_TOO_SHORT;++ /* check glyph indices */+ if ( valid->level >= FT_VALIDATE_TIGHT )+ {+ FT_UInt gindex;+++ for ( ; count > 0; count-- )+ {+ gindex = TT_NEXT_USHORT( p );+ if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )+ FT_INVALID_GLYPH_ID;+ }+ }++ return SFNT_Err_Ok;+ }+++ FT_CALLBACK_DEF( FT_UInt )+ tt_cmap10_char_index( TT_CMap cmap,+ FT_UInt32 char_code )+ {+ FT_Byte* table = cmap->data;+ FT_UInt result = 0;+ 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 );+++ if ( idx < count )+ {+ p += 2 * idx;+ result = TT_PEEK_USHORT( p );+ }+ return result;+ }+++ FT_CALLBACK_DEF( FT_UInt32 )+ tt_cmap10_char_next( TT_CMap cmap,+ FT_UInt32 *pchar_code )+ {+ FT_Byte* table = cmap->data;+ FT_UInt32 char_code = *pchar_code + 1;+ FT_UInt gindex = 0;+ FT_Byte* p = table + 12;+ FT_UInt32 start = TT_NEXT_ULONG( p );+ FT_UInt32 count = TT_NEXT_ULONG( p );+ FT_UInt32 idx;+++ if ( char_code < start )+ char_code = start;++ idx = (FT_UInt32)( char_code - start );+ p += 2 * idx;++ for ( ; idx < count; idx++ )+ {+ gindex = TT_NEXT_USHORT( p );+ if ( gindex != 0 )+ break;+ char_code++;+ }++ *pchar_code = char_code;+ return gindex;+ }+++ FT_CALLBACK_DEF( FT_Error )+ tt_cmap10_get_info( TT_CMap cmap,+ TT_CMapInfo *cmap_info )+ {+ FT_Byte* p = cmap->data + 8;+++ cmap_info->format = 10;+ cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );++ return SFNT_Err_Ok;+ }+++ FT_DEFINE_TT_CMAP(tt_cmap10_class_rec,+ sizeof ( TT_CMapRec ),++ (FT_CMap_InitFunc) tt_cmap_init,+ (FT_CMap_DoneFunc) NULL,+ (FT_CMap_CharIndexFunc)tt_cmap10_char_index,+ (FT_CMap_CharNextFunc) tt_cmap10_char_next,++ NULL, NULL, NULL, NULL, NULL+ ,+ 10,+ (TT_CMap_ValidateFunc) tt_cmap10_validate,+ (TT_CMap_Info_GetFunc) tt_cmap10_get_info+ )++#endif /* TT_CONFIG_CMAP_FORMAT_10 */+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** FORMAT 12 *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /*************************************************************************/+ /* */+ /* TABLE OVERVIEW */+ /* -------------- */+ /* */+ /* NAME OFFSET TYPE DESCRIPTION */+ /* */+ /* format 0 USHORT must be 12 */+ /* reserved 2 USHORT reserved */+ /* length 4 ULONG length in bytes */+ /* language 8 ULONG Mac language code */+ /* count 12 ULONG number of groups */+ /* 16 */+ /* */+ /* This header is followed by `count' groups of the following format: */+ /* */+ /* start 0 ULONG first charcode */+ /* end 4 ULONG last charcode */+ /* startId 8 ULONG start glyph ID for the group */+ /* */++#ifdef TT_CONFIG_CMAP_FORMAT_12++ typedef struct TT_CMap12Rec_+ {+ TT_CMapRec cmap;+ FT_Bool valid;+ FT_ULong cur_charcode;+ FT_UInt cur_gindex;+ FT_ULong cur_group;+ FT_ULong num_groups;++ } TT_CMap12Rec, *TT_CMap12;+++ FT_CALLBACK_DEF( FT_Error )+ tt_cmap12_init( TT_CMap12 cmap,+ FT_Byte* table )+ {+ cmap->cmap.data = table;++ table += 12;+ cmap->num_groups = FT_PEEK_ULONG( table );++ cmap->valid = 0;++ return SFNT_Err_Ok;+ }+++ FT_CALLBACK_DEF( FT_Error )+ tt_cmap12_validate( FT_Byte* table,+ FT_Validator valid )+ {+ FT_Byte* p;+ FT_ULong length;+ FT_ULong num_groups;+++ if ( table + 16 > valid->limit )+ FT_INVALID_TOO_SHORT;++ p = table + 4;+ length = TT_NEXT_ULONG( p );++ p = table + 12;+ num_groups = TT_NEXT_ULONG( p );++ if ( length > (FT_ULong)( valid->limit - table ) ||+ length < 16 + 12 * num_groups )+ FT_INVALID_TOO_SHORT;++ /* check groups, they must be in increasing order */+ {+ FT_ULong n, start, end, start_id, last = 0;+++ for ( n = 0; n < num_groups; n++ )+ {+ start = TT_NEXT_ULONG( p );+ end = TT_NEXT_ULONG( p );+ start_id = TT_NEXT_ULONG( p );++ if ( start > end )+ FT_INVALID_DATA;++ if ( n > 0 && start <= last )+ FT_INVALID_DATA;++ if ( valid->level >= FT_VALIDATE_TIGHT )+ {+ if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )+ FT_INVALID_GLYPH_ID;+ }++ last = end;+ }+ }++ return SFNT_Err_Ok;+ }+++ /* search the index of the charcode next to cmap->cur_charcode */+ /* cmap->cur_group should be set up properly by caller */+ /* */+ static void+ tt_cmap12_next( TT_CMap12 cmap )+ {+ FT_Byte* p;+ FT_ULong start, end, start_id, char_code;+ FT_ULong n;+ FT_UInt gindex;+++ if ( cmap->cur_charcode >= 0xFFFFFFFFUL )+ goto Fail;++ char_code = cmap->cur_charcode + 1;++ n = cmap->cur_group;++ for ( n = cmap->cur_group; n < cmap->num_groups; n++ )+ {+ p = cmap->cmap.data + 16 + 12 * n;+ start = TT_NEXT_ULONG( p );+ end = TT_NEXT_ULONG( p );+ start_id = TT_PEEK_ULONG( p );++ if ( char_code < start )+ char_code = start;++ for ( ; char_code <= end; char_code++ )+ {+ gindex = (FT_UInt)( start_id + char_code - start );++ if ( gindex )+ {+ cmap->cur_charcode = char_code;;+ cmap->cur_gindex = gindex;+ cmap->cur_group = n;++ return;+ }+ }+ }++ Fail:+ cmap->valid = 0;+ }+++ static FT_UInt+ tt_cmap12_char_map_binary( TT_CMap cmap,+ FT_UInt32* pchar_code,+ FT_Bool next )+ {+ FT_UInt gindex = 0;+ FT_Byte* p = cmap->data + 12;+ FT_UInt32 num_groups = TT_PEEK_ULONG( p );+ FT_UInt32 char_code = *pchar_code;+ FT_UInt32 start, end, start_id;+ FT_UInt32 max, min, mid;+++ if ( !num_groups )+ return 0;++ /* make compiler happy */+ mid = num_groups;+ end = 0xFFFFFFFFUL;++ if ( next )+ char_code++;++ min = 0;+ max = num_groups;++ /* binary search */+ while ( min < max )+ {+ mid = ( min + max ) >> 1;+ p = cmap->data + 16 + 12 * mid;++ start = TT_NEXT_ULONG( p );+ end = TT_NEXT_ULONG( p );++ if ( char_code < start )+ max = mid;+ else if ( char_code > end )+ min = mid + 1;+ else+ {+ start_id = TT_PEEK_ULONG( p );+ gindex = (FT_UInt)( start_id + char_code - start );++ break;+ }+ }++ if ( next )+ {+ 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 )+ {+ mid++;+ if ( mid == num_groups )+ return 0;+ }++ cmap12->valid = 1;+ cmap12->cur_charcode = char_code;+ cmap12->cur_group = mid;++ if ( !gindex )+ {+ tt_cmap12_next( cmap12 );++ if ( cmap12->valid )+ gindex = cmap12->cur_gindex;+ }+ else+ cmap12->cur_gindex = gindex;++ if ( gindex )+ *pchar_code = cmap12->cur_charcode;+ }++ return gindex;+ }+++ FT_CALLBACK_DEF( FT_UInt )+ tt_cmap12_char_index( TT_CMap cmap,+ FT_UInt32 char_code )+ {+ return tt_cmap12_char_map_binary( cmap, &char_code, 0 );+ }+++ FT_CALLBACK_DEF( FT_UInt32 )+ tt_cmap12_char_next( TT_CMap cmap,+ FT_UInt32 *pchar_code )+ {+ TT_CMap12 cmap12 = (TT_CMap12)cmap;+ FT_ULong gindex;+++ if ( cmap12->cur_charcode >= 0xFFFFFFFFUL )+ return 0;++ /* no need to search */+ if ( cmap12->valid && cmap12->cur_charcode == *pchar_code )+ {+ 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;+ }+ else+ gindex = 0;+ }+ else+ gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 );++ /* XXX: check gindex overflow is expected */+ return (FT_UInt32)gindex;+ }+++ FT_CALLBACK_DEF( FT_Error )+ tt_cmap12_get_info( TT_CMap cmap,+ TT_CMapInfo *cmap_info )+ {+ FT_Byte* p = cmap->data + 8;+++ cmap_info->format = 12;+ cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );++ return SFNT_Err_Ok;+ }+++ FT_DEFINE_TT_CMAP(tt_cmap12_class_rec,+ sizeof ( TT_CMap12Rec ),++ (FT_CMap_InitFunc) tt_cmap12_init,+ (FT_CMap_DoneFunc) NULL,+ (FT_CMap_CharIndexFunc)tt_cmap12_char_index,+ (FT_CMap_CharNextFunc) tt_cmap12_char_next,++ NULL, NULL, NULL, NULL, NULL+ ,+ 12,+ (TT_CMap_ValidateFunc) tt_cmap12_validate,+ (TT_CMap_Info_GetFunc) tt_cmap12_get_info+ )++#endif /* TT_CONFIG_CMAP_FORMAT_12 */+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** FORMAT 13 *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /*************************************************************************/+ /* */+ /* TABLE OVERVIEW */+ /* -------------- */+ /* */+ /* NAME OFFSET TYPE DESCRIPTION */+ /* */+ /* format 0 USHORT must be 13 */+ /* reserved 2 USHORT reserved */+ /* length 4 ULONG length in bytes */+ /* language 8 ULONG Mac language code */+ /* count 12 ULONG number of groups */+ /* 16 */+ /* */+ /* This header is followed by `count' groups of the following format: */+ /* */+ /* start 0 ULONG first charcode */+ /* end 4 ULONG last charcode */+ /* glyphId 8 ULONG glyph ID for the whole group */+ /* */++#ifdef TT_CONFIG_CMAP_FORMAT_13++ typedef struct TT_CMap13Rec_+ {+ TT_CMapRec cmap;+ FT_Bool valid;+ FT_ULong cur_charcode;+ FT_UInt cur_gindex;+ FT_ULong cur_group;+ FT_ULong num_groups;++ } TT_CMap13Rec, *TT_CMap13;+++ FT_CALLBACK_DEF( FT_Error )+ tt_cmap13_init( TT_CMap13 cmap,+ FT_Byte* table )+ {+ cmap->cmap.data = table;++ table += 12;+ cmap->num_groups = FT_PEEK_ULONG( table );++ cmap->valid = 0;++ return SFNT_Err_Ok;+ }+++ FT_CALLBACK_DEF( FT_Error )+ tt_cmap13_validate( FT_Byte* table,+ FT_Validator valid )+ {+ FT_Byte* p;+ FT_ULong length;+ FT_ULong num_groups;+++ if ( table + 16 > valid->limit )+ FT_INVALID_TOO_SHORT;++ p = table + 4;+ length = TT_NEXT_ULONG( p );++ p = table + 12;+ num_groups = TT_NEXT_ULONG( p );++ if ( length > (FT_ULong)( valid->limit - table ) ||+ length < 16 + 12 * num_groups )+ FT_INVALID_TOO_SHORT;++ /* check groups, they must be in increasing order */+ {+ FT_ULong n, start, end, glyph_id, last = 0;+++ for ( n = 0; n < num_groups; n++ )+ {+ start = TT_NEXT_ULONG( p );+ end = TT_NEXT_ULONG( p );+ glyph_id = TT_NEXT_ULONG( p );++ if ( start > end )+ FT_INVALID_DATA;++ if ( n > 0 && start <= last )+ FT_INVALID_DATA;++ if ( valid->level >= FT_VALIDATE_TIGHT )+ {+ if ( glyph_id >= TT_VALID_GLYPH_COUNT( valid ) )+ FT_INVALID_GLYPH_ID;+ }++ last = end;+ }+ }++ return SFNT_Err_Ok;+ }+++ /* search the index of the charcode next to cmap->cur_charcode */+ /* cmap->cur_group should be set up properly by caller */+ /* */+ static void+ tt_cmap13_next( TT_CMap13 cmap )+ {+ FT_Byte* p;+ FT_ULong start, end, glyph_id, char_code;+ FT_ULong n;+ FT_UInt gindex;+++ if ( cmap->cur_charcode >= 0xFFFFFFFFUL )+ goto Fail;++ char_code = cmap->cur_charcode + 1;++ n = cmap->cur_group;++ for ( n = cmap->cur_group; n < cmap->num_groups; n++ )+ {+ p = cmap->cmap.data + 16 + 12 * n;+ start = TT_NEXT_ULONG( p );+ end = TT_NEXT_ULONG( p );+ glyph_id = TT_PEEK_ULONG( p );++ if ( char_code < start )+ char_code = start;++ if ( char_code <= end )+ {+ gindex = (FT_UInt)glyph_id;++ if ( gindex )+ {+ cmap->cur_charcode = char_code;;+ cmap->cur_gindex = gindex;+ cmap->cur_group = n;++ return;+ }+ }+ }++ Fail:+ cmap->valid = 0;+ }+++ static FT_UInt+ tt_cmap13_char_map_binary( TT_CMap cmap,+ FT_UInt32* pchar_code,+ FT_Bool next )+ {+ FT_UInt gindex = 0;+ FT_Byte* p = cmap->data + 12;+ FT_UInt32 num_groups = TT_PEEK_ULONG( p );+ FT_UInt32 char_code = *pchar_code;+ FT_UInt32 start, end;+ FT_UInt32 max, min, mid;+++ if ( !num_groups )+ return 0;++ /* make compiler happy */+ mid = num_groups;+ end = 0xFFFFFFFFUL;++ if ( next )+ char_code++;++ min = 0;+ max = num_groups;++ /* binary search */+ while ( min < max )+ {+ mid = ( min + max ) >> 1;+ p = cmap->data + 16 + 12 * mid;++ start = TT_NEXT_ULONG( p );+ end = TT_NEXT_ULONG( p );++ if ( char_code < start )+ max = mid;+ else if ( char_code > end )+ min = mid + 1;+ else+ {+ gindex = (FT_UInt)TT_PEEK_ULONG( p );++ break;+ }+ }++ if ( next )+ {+ TT_CMap13 cmap13 = (TT_CMap13)cmap;+++ /* if `char_code' is not in any group, then `mid' is */+ /* the group nearest to `char_code' */+ /* */++ if ( char_code > end )+ {+ mid++;+ if ( mid == num_groups )+ return 0;+ }++ cmap13->valid = 1;+ cmap13->cur_charcode = char_code;+ cmap13->cur_group = mid;++ if ( !gindex )+ {+ tt_cmap13_next( cmap13 );++ if ( cmap13->valid )+ gindex = cmap13->cur_gindex;+ }+ else+ cmap13->cur_gindex = gindex;++ if ( gindex )+ *pchar_code = cmap13->cur_charcode;+ }++ return gindex;+ }+++ FT_CALLBACK_DEF( FT_UInt )+ tt_cmap13_char_index( TT_CMap cmap,+ FT_UInt32 char_code )+ {+ return tt_cmap13_char_map_binary( cmap, &char_code, 0 );+ }+++ FT_CALLBACK_DEF( FT_UInt32 )+ tt_cmap13_char_next( TT_CMap cmap,+ FT_UInt32 *pchar_code )+ {+ TT_CMap13 cmap13 = (TT_CMap13)cmap;+ 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;+ }+ else+ gindex = 0;+ }+ else+ gindex = tt_cmap13_char_map_binary( cmap, pchar_code, 1 );++ return gindex;+ }+++ FT_CALLBACK_DEF( FT_Error )+ tt_cmap13_get_info( TT_CMap cmap,+ TT_CMapInfo *cmap_info )+ {+ FT_Byte* p = cmap->data + 8;+++ cmap_info->format = 13;+ cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );++ return SFNT_Err_Ok;+ }+++ FT_DEFINE_TT_CMAP(tt_cmap13_class_rec,+ sizeof ( TT_CMap13Rec ),++ (FT_CMap_InitFunc) tt_cmap13_init,+ (FT_CMap_DoneFunc) NULL,+ (FT_CMap_CharIndexFunc)tt_cmap13_char_index,+ (FT_CMap_CharNextFunc) tt_cmap13_char_next,++ NULL, NULL, NULL, NULL, NULL+ ,+ 13,+ (TT_CMap_ValidateFunc) tt_cmap13_validate,+ (TT_CMap_Info_GetFunc) tt_cmap13_get_info+ )++#endif /* TT_CONFIG_CMAP_FORMAT_13 */+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** FORMAT 14 *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ /*************************************************************************/+ /* */+ /* TABLE OVERVIEW */+ /* -------------- */+ /* */+ /* NAME OFFSET TYPE DESCRIPTION */+ /* */+ /* format 0 USHORT must be 14 */+ /* length 2 ULONG table length in bytes */+ /* numSelector 6 ULONG number of variation sel. records */+ /* */+ /* Followed by numSelector records, each of which looks like */+ /* */+ /* varSelector 0 UINT24 Unicode codepoint of sel. */+ /* defaultOff 3 ULONG offset to a default UVS table */+ /* describing any variants to be found in */+ /* the normal Unicode subtable. */+ /* nonDefOff 7 ULONG offset to a non-default UVS table */+ /* describing any variants not in the */+ /* standard cmap, with GIDs here */+ /* (either offset may be 0 NULL) */+ /* */+ /* Selectors are sorted by code point. */+ /* */+ /* A default Unicode Variation Selector (UVS) subtable is just a list of */+ /* ranges of code points which are to be found in the standard cmap. No */+ /* glyph IDs (GIDs) here. */+ /* */+ /* numRanges 0 ULONG number of ranges following */+ /* */+ /* A range looks like */+ /* */+ /* uniStart 0 UINT24 code point of the first character in */+ /* this range */+ /* additionalCnt 3 UBYTE count of additional characters in this */+ /* range (zero means a range of a single */+ /* character) */+ /* */+ /* Ranges are sorted by `uniStart'. */+ /* */+ /* A non-default Unicode Variation Selector (UVS) subtable is a list of */+ /* mappings from codepoint to GID. */+ /* */+ /* numMappings 0 ULONG number of mappings */+ /* */+ /* A range looks like */+ /* */+ /* uniStart 0 UINT24 code point of the first character in */+ /* this range */+ /* GID 3 USHORT and its GID */+ /* */+ /* Ranges are sorted by `uniStart'. */++#ifdef TT_CONFIG_CMAP_FORMAT_14++ typedef struct TT_CMap14Rec_+ {+ TT_CMapRec cmap;+ FT_ULong num_selectors;++ /* This array is used to store the results of various+ * cmap 14 query functions. The data is overwritten+ * on each call to these functions.+ */+ FT_UInt32 max_results;+ FT_UInt32* results;+ FT_Memory memory;++ } TT_CMap14Rec, *TT_CMap14;+++ FT_CALLBACK_DEF( void )+ tt_cmap14_done( TT_CMap14 cmap )+ {+ FT_Memory memory = cmap->memory;+++ cmap->max_results = 0;+ if ( memory != NULL && cmap->results != NULL )+ FT_FREE( cmap->results );+ }+++ static FT_Error+ tt_cmap14_ensure( TT_CMap14 cmap,+ FT_UInt32 num_results,+ FT_Memory memory )+ {+ FT_UInt32 old_max = cmap->max_results;+ FT_Error error = SFNT_Err_Ok;+++ if ( num_results > cmap->max_results )+ {+ cmap->memory = memory;++ if ( FT_QRENEW_ARRAY( cmap->results, old_max, num_results ) )+ return error;++ cmap->max_results = num_results;+ }++ return error;+ }+++ FT_CALLBACK_DEF( FT_Error )+ tt_cmap14_init( TT_CMap14 cmap,+ FT_Byte* table )+ {+ cmap->cmap.data = table;++ table += 6;+ cmap->num_selectors = FT_PEEK_ULONG( table );+ cmap->max_results = 0;+ cmap->results = NULL;++ return SFNT_Err_Ok;+ }+++ FT_CALLBACK_DEF( FT_Error )+ tt_cmap14_validate( FT_Byte* table,+ FT_Validator valid )+ {+ FT_Byte* p = table + 2;+ FT_ULong length = TT_NEXT_ULONG( p );+ FT_ULong num_selectors = TT_NEXT_ULONG( p );+++ if ( length > (FT_ULong)( valid->limit - table ) ||+ length < 10 + 11 * num_selectors )+ FT_INVALID_TOO_SHORT;++ /* check selectors, they must be in increasing order */+ {+ /* we start lastVarSel at 1 because a variant selector value of 0+ * isn't valid.+ */+ FT_ULong n, lastVarSel = 1;+++ for ( n = 0; n < num_selectors; n++ )+ {+ FT_ULong varSel = TT_NEXT_UINT24( p );+ FT_ULong defOff = TT_NEXT_ULONG( p );+ FT_ULong nondefOff = TT_NEXT_ULONG( p );+++ if ( defOff >= length || nondefOff >= length )+ FT_INVALID_TOO_SHORT;++ if ( varSel < lastVarSel )+ FT_INVALID_DATA;++ lastVarSel = varSel + 1;++ /* check the default table (these glyphs should be reached */+ /* 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_ULong i;+ FT_ULong lastBase = 0;+++ if ( defp + numRanges * 4 > valid->limit )+ FT_INVALID_TOO_SHORT;++ for ( i = 0; i < numRanges; ++i )+ {+ FT_ULong base = TT_NEXT_UINT24( defp );+ FT_ULong cnt = FT_NEXT_BYTE( defp );+++ if ( base + cnt >= 0x110000UL ) /* end of Unicode */+ FT_INVALID_DATA;++ if ( base < lastBase )+ FT_INVALID_DATA;++ lastBase = base + cnt + 1U;+ }+ }++ /* 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;+++ if ( numMappings * 4 > (FT_ULong)( valid->limit - ndp ) )+ FT_INVALID_TOO_SHORT;++ for ( i = 0; i < numMappings; ++i )+ {+ FT_ULong uni = TT_NEXT_UINT24( ndp );+ FT_ULong gid = TT_NEXT_USHORT( ndp );+++ if ( uni >= 0x110000UL ) /* end of Unicode */+ FT_INVALID_DATA;++ if ( uni < lastUni )+ FT_INVALID_DATA;++ lastUni = uni + 1U;++ if ( valid->level >= FT_VALIDATE_TIGHT &&+ gid >= TT_VALID_GLYPH_COUNT( valid ) )+ FT_INVALID_GLYPH_ID;+ }+ }+ }+ }++ return SFNT_Err_Ok;+ }+++ FT_CALLBACK_DEF( FT_UInt )+ tt_cmap14_char_index( TT_CMap cmap,+ FT_UInt32 char_code )+ {+ FT_UNUSED( cmap );+ FT_UNUSED( char_code );++ /* This can't happen */+ return 0;+ }+++ FT_CALLBACK_DEF( FT_UInt32 )+ tt_cmap14_char_next( TT_CMap cmap,+ FT_UInt32 *pchar_code )+ {+ FT_UNUSED( cmap );++ /* This can't happen */+ *pchar_code = 0;+ return 0;+ }+++ FT_CALLBACK_DEF( FT_Error )+ tt_cmap14_get_info( TT_CMap cmap,+ TT_CMapInfo *cmap_info )+ {+ FT_UNUSED( cmap );++ cmap_info->format = 14;+ /* subtable 14 does not define a language field */+ cmap_info->language = 0xFFFFFFFFUL;++ return SFNT_Err_Ok;+ }+++ static FT_UInt+ tt_cmap14_char_map_def_binary( FT_Byte *base,+ FT_UInt32 char_code )+ {+ FT_UInt32 numRanges = TT_PEEK_ULONG( base );+ FT_UInt32 max, min;+++ min = 0;+ max = numRanges;++ base += 4;++ /* binary search */+ while ( min < max )+ {+ FT_UInt32 mid = ( min + max ) >> 1;+ FT_Byte* p = base + 4 * mid;+ FT_ULong start = TT_NEXT_UINT24( p );+ FT_UInt cnt = FT_NEXT_BYTE( p );+++ if ( char_code < start )+ max = mid;+ else if ( char_code > start+cnt )+ min = mid + 1;+ else+ return TRUE;+ }++ return FALSE;+ }+++ static FT_UInt+ tt_cmap14_char_map_nondef_binary( FT_Byte *base,+ FT_UInt32 char_code )+ {+ FT_UInt32 numMappings = TT_PEEK_ULONG( base );+ FT_UInt32 max, min;+++ min = 0;+ max = numMappings;++ base += 4;++ /* binary search */+ while ( min < max )+ {+ FT_UInt32 mid = ( min + max ) >> 1;+ FT_Byte* p = base + 5 * mid;+ FT_UInt32 uni = (FT_UInt32)TT_NEXT_UINT24( p );+++ if ( char_code < uni )+ max = mid;+ else if ( char_code > uni )+ min = mid + 1;+ else+ return TT_PEEK_USHORT( p );+ }++ return 0;+ }+++ static FT_Byte*+ tt_cmap14_find_variant( FT_Byte *base,+ FT_UInt32 variantCode )+ {+ FT_UInt32 numVar = TT_PEEK_ULONG( base );+ FT_UInt32 max, min;+++ min = 0;+ max = numVar;++ base += 4;++ /* binary search */+ while ( min < max )+ {+ FT_UInt32 mid = ( min + max ) >> 1;+ FT_Byte* p = base + 11 * mid;+ FT_ULong varSel = TT_NEXT_UINT24( p );+++ if ( variantCode < varSel )+ max = mid;+ else if ( variantCode > varSel )+ min = mid + 1;+ else+ return p;+ }++ return NULL;+ }+++ FT_CALLBACK_DEF( FT_UInt )+ tt_cmap14_char_var_index( TT_CMap cmap,+ TT_CMap ucmap,+ FT_UInt32 charcode,+ FT_UInt32 variantSelector)+ {+ FT_Byte* p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );+ FT_ULong defOff;+ FT_ULong nondefOff;+++ if ( !p )+ return 0;++ defOff = TT_NEXT_ULONG( p );+ nondefOff = TT_PEEK_ULONG( p );++ if ( defOff != 0 &&+ tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) )+ {+ /* This is the default variant of this charcode. GID not stored */+ /* here; stored in the normal Unicode charmap instead. */+ return ucmap->cmap.clazz->char_index( &ucmap->cmap, charcode );+ }++ if ( nondefOff != 0 )+ return tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,+ charcode );++ return 0;+ }+++ FT_CALLBACK_DEF( FT_Int )+ tt_cmap14_char_var_isdefault( TT_CMap cmap,+ FT_UInt32 charcode,+ FT_UInt32 variantSelector )+ {+ FT_Byte* p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );+ FT_ULong defOff;+ FT_ULong nondefOff;+++ if ( !p )+ return -1;++ defOff = TT_NEXT_ULONG( p );+ nondefOff = TT_NEXT_ULONG( p );++ if ( defOff != 0 &&+ tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) )+ return 1;++ if ( nondefOff != 0 &&+ tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,+ charcode ) != 0 )+ return 0;++ return -1;+ }+++ FT_CALLBACK_DEF( FT_UInt32* )+ tt_cmap14_variants( TT_CMap cmap,+ FT_Memory memory )+ {+ TT_CMap14 cmap14 = (TT_CMap14)cmap;+ FT_UInt32 count = cmap14->num_selectors;+ FT_Byte* p = cmap->data + 10;+ FT_UInt32* result;+ FT_UInt32 i;+++ if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) )+ return NULL;++ result = cmap14->results;+ for ( i = 0; i < count; ++i )+ {+ result[i] = (FT_UInt32)TT_NEXT_UINT24( p );+ p += 8;+ }+ result[i] = 0;++ return result;+ }+++ FT_CALLBACK_DEF( FT_UInt32 * )+ tt_cmap14_char_variants( TT_CMap cmap,+ FT_Memory memory,+ FT_UInt32 charCode )+ {+ TT_CMap14 cmap14 = (TT_CMap14) cmap;+ FT_UInt32 count = cmap14->num_selectors;+ FT_Byte* p = cmap->data + 10;+ FT_UInt32* q;+++ if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) )+ return NULL;++ for ( q = cmap14->results; count > 0; --count )+ {+ FT_UInt32 varSel = TT_NEXT_UINT24( p );+ FT_ULong defOff = TT_NEXT_ULONG( p );+ FT_ULong nondefOff = TT_NEXT_ULONG( p );+++ if ( ( defOff != 0 &&+ tt_cmap14_char_map_def_binary( cmap->data + defOff,+ charCode ) ) ||+ ( nondefOff != 0 &&+ tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,+ charCode ) != 0 ) )+ {+ q[0] = varSel;+ q++;+ }+ }+ q[0] = 0;++ return cmap14->results;+ }+++ static FT_UInt+ tt_cmap14_def_char_count( FT_Byte *p )+ {+ FT_UInt32 numRanges = (FT_UInt32)TT_NEXT_ULONG( p );+ FT_UInt tot = 0;+++ p += 3; /* point to the first `cnt' field */+ for ( ; numRanges > 0; numRanges-- )+ {+ tot += 1 + p[0];+ p += 4;+ }++ return tot;+ }+++ static FT_UInt32*+ tt_cmap14_get_def_chars( TT_CMap cmap,+ FT_Byte* p,+ FT_Memory memory )+ {+ TT_CMap14 cmap14 = (TT_CMap14) cmap;+ FT_UInt32 numRanges;+ FT_UInt cnt;+ FT_UInt32* q;+++ cnt = tt_cmap14_def_char_count( p );+ numRanges = (FT_UInt32)TT_NEXT_ULONG( p );++ if ( tt_cmap14_ensure( cmap14, ( cnt + 1 ), memory ) )+ return NULL;++ for ( q = cmap14->results; numRanges > 0; --numRanges )+ {+ FT_UInt32 uni = (FT_UInt32)TT_NEXT_UINT24( p );+++ cnt = FT_NEXT_BYTE( p ) + 1;+ do+ {+ q[0] = uni;+ uni += 1;+ q += 1;+ } while ( --cnt != 0 );+ }+ q[0] = 0;++ return cmap14->results;+ }+++ static FT_UInt32*+ tt_cmap14_get_nondef_chars( TT_CMap cmap,+ FT_Byte *p,+ FT_Memory memory )+ {+ TT_CMap14 cmap14 = (TT_CMap14) cmap;+ FT_UInt32 numMappings;+ FT_UInt i;+ FT_UInt32 *ret;+++ numMappings = (FT_UInt32)TT_NEXT_ULONG( p );++ if ( tt_cmap14_ensure( cmap14, ( numMappings + 1 ), memory ) )+ return NULL;++ ret = cmap14->results;+ for ( i = 0; i < numMappings; ++i )+ {+ ret[i] = (FT_UInt32)TT_NEXT_UINT24( p );+ p += 2;+ }+ ret[i] = 0;++ return ret;+ }+++ FT_CALLBACK_DEF( FT_UInt32 * )+ tt_cmap14_variant_chars( TT_CMap cmap,+ FT_Memory memory,+ FT_UInt32 variantSelector )+ {+ FT_Byte *p = tt_cmap14_find_variant( cmap->data + 6,+ variantSelector );+ FT_UInt32 *ret;+ FT_Int i;+ FT_ULong defOff;+ FT_ULong nondefOff;+++ if ( !p )+ return NULL;++ defOff = TT_NEXT_ULONG( p );+ nondefOff = TT_NEXT_ULONG( p );++ if ( defOff == 0 && nondefOff == 0 )+ return NULL;++ if ( defOff == 0 )+ return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff,+ memory );+ else if ( nondefOff == 0 )+ return tt_cmap14_get_def_chars( cmap, cmap->data + defOff,+ memory );+ else+ {+ /* Both a default and a non-default glyph set? That's probably not */+ /* good font design, but the spec allows for it... */+ TT_CMap14 cmap14 = (TT_CMap14) cmap;+ FT_UInt32 numRanges;+ FT_UInt32 numMappings;+ FT_UInt32 duni;+ FT_UInt32 dcnt;+ FT_UInt32 nuni;+ FT_Byte* dp;+ FT_UInt di, ni, k;+++ p = cmap->data + nondefOff;+ dp = cmap->data + defOff;++ numMappings = (FT_UInt32)TT_NEXT_ULONG( p );+ dcnt = tt_cmap14_def_char_count( dp );+ numRanges = (FT_UInt32)TT_NEXT_ULONG( dp );++ if ( numMappings == 0 )+ return tt_cmap14_get_def_chars( cmap, cmap->data + defOff,+ memory );+ if ( dcnt == 0 )+ return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff,+ memory );++ if ( tt_cmap14_ensure( cmap14, ( dcnt + numMappings + 1 ), memory ) )+ return NULL;++ ret = cmap14->results;+ duni = (FT_UInt32)TT_NEXT_UINT24( dp );+ dcnt = FT_NEXT_BYTE( dp );+ di = 1;+ nuni = (FT_UInt32)TT_NEXT_UINT24( p );+ p += 2;+ ni = 1;+ i = 0;++ for ( ;; )+ {+ if ( nuni > duni + dcnt )+ {+ for ( k = 0; k <= dcnt; ++k )+ ret[i++] = duni + k;++ ++di;++ if ( di > numRanges )+ break;++ duni = (FT_UInt32)TT_NEXT_UINT24( dp );+ dcnt = FT_NEXT_BYTE( dp );+ }+ else+ {+ if ( nuni < duni )+ ret[i++] = nuni;+ /* If it is within the default range then ignore it -- */+ /* that should not have happened */+ ++ni;+ if ( ni > numMappings )+ break;++ nuni = (FT_UInt32)TT_NEXT_UINT24( p );+ p += 2;+ }+ }++ if ( ni <= numMappings )+ {+ /* If we get here then we have run out of all default ranges. */+ /* We have read one non-default mapping which we haven't stored */+ /* and there may be others that need to be read. */+ ret[i++] = nuni;+ while ( ni < numMappings )+ {+ ret[i++] = (FT_UInt32)TT_NEXT_UINT24( p );+ p += 2;+ ++ni;+ }+ }+ else if ( di <= numRanges )+ {+ /* If we get here then we have run out of all non-default */+ /* mappings. We have read one default range which we haven't */+ /* stored and there may be others that need to be read. */+ for ( k = 0; k <= dcnt; ++k )+ ret[i++] = duni + k;++ while ( di < numRanges )+ {+ duni = (FT_UInt32)TT_NEXT_UINT24( dp );+ dcnt = FT_NEXT_BYTE( dp );++ for ( k = 0; k <= dcnt; ++k )+ ret[i++] = duni + k;+ ++di;+ }+ }++ ret[i] = 0;++ return ret;+ }+ }+++ FT_DEFINE_TT_CMAP(tt_cmap14_class_rec,+ sizeof ( TT_CMap14Rec ),++ (FT_CMap_InitFunc) tt_cmap14_init,+ (FT_CMap_DoneFunc) tt_cmap14_done,+ (FT_CMap_CharIndexFunc)tt_cmap14_char_index,+ (FT_CMap_CharNextFunc) tt_cmap14_char_next,++ /* Format 14 extension functions */+ (FT_CMap_CharVarIndexFunc) tt_cmap14_char_var_index,+ (FT_CMap_CharVarIsDefaultFunc)tt_cmap14_char_var_isdefault,+ (FT_CMap_VariantListFunc) tt_cmap14_variants,+ (FT_CMap_CharVariantListFunc) tt_cmap14_char_variants,+ (FT_CMap_VariantCharListFunc) tt_cmap14_variant_chars+ ,+ 14,+ (TT_CMap_ValidateFunc)tt_cmap14_validate,+ (TT_CMap_Info_GetFunc)tt_cmap14_get_info+ )++#endif /* TT_CONFIG_CMAP_FORMAT_14 */+++#ifndef FT_CONFIG_OPTION_PIC++ static const TT_CMap_Class tt_cmap_classes[] =+ {+#define TTCMAPCITEM(a) &a,+#include "ttcmapc.h"+ NULL,+ };++#else /*FT_CONFIG_OPTION_PIC*/++ void FT_Destroy_Class_tt_cmap_classes(FT_Library library, TT_CMap_Class* clazz)+ {+ FT_Memory memory = library->memory;+ if ( clazz )+ FT_FREE( clazz );+ }++ FT_Error FT_Create_Class_tt_cmap_classes(FT_Library library, TT_CMap_Class** output_class)+ {+ TT_CMap_Class* clazz;+ TT_CMap_ClassRec* recs;+ FT_Error error;+ FT_Memory memory = library->memory;+ int i = 0;++#define TTCMAPCITEM(a) i++;+#include "ttcmapc.h"++ /* allocate enough space for both the pointers +terminator and the class instances */+ if ( FT_ALLOC( clazz, sizeof(*clazz)*(i+1)+sizeof(TT_CMap_ClassRec)*i ) )+ return error;++ /* the location of the class instances follows the array of pointers */+ recs = (TT_CMap_ClassRec*) (((char*)clazz)+(sizeof(*clazz)*(i+1))); + i=0;++#undef TTCMAPCITEM+#define TTCMAPCITEM(a) \+ FT_Init_Class_##a(&recs[i]); \+ clazz[i] = &recs[i]; \+ i++;+#include "ttcmapc.h"++ clazz[i] = NULL;++ *output_class = clazz;+ return SFNT_Err_Ok;+ }++#endif /*FT_CONFIG_OPTION_PIC*/+++ /* parse the `cmap' table and build the corresponding TT_CMap objects */+ /* in the current face */+ /* */+ FT_LOCAL_DEF( FT_Error )+ tt_face_build_cmaps( TT_Face face )+ {+ FT_Byte* table = face->cmap_table;+ FT_Byte* limit = table + face->cmap_size;+ FT_UInt volatile num_cmaps;+ FT_Byte* volatile p = table;+ FT_Library library = FT_FACE_LIBRARY( face );++ FT_UNUSED( library );+++ if ( !p || p + 4 > limit )+ return SFNT_Err_Invalid_Table;++ /* only recognize format 0 */+ if ( TT_NEXT_USHORT( p ) != 0 )+ {+ p -= 2;+ FT_ERROR(( "tt_face_build_cmaps:"+ " unsupported `cmap' table format = %d\n",+ TT_PEEK_USHORT( p ) ));+ return SFNT_Err_Invalid_Table;+ }++ num_cmaps = TT_NEXT_USHORT( p );+#ifdef FT_MAX_CHARMAP_CACHEABLE+ if ( num_cmaps > FT_MAX_CHARMAP_CACHEABLE )+ FT_ERROR(( "tt_face_build_cmaps: too many cmap subtables(%d) "+ "subtable#%d and later are loaded but cannot be searched\n",+ num_cmaps, FT_MAX_CHARMAP_CACHEABLE + 1 ));+#endif++ for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- )+ {+ FT_CharMapRec charmap;+ FT_UInt32 offset;+++ charmap.platform_id = TT_NEXT_USHORT( p );+ charmap.encoding_id = TT_NEXT_USHORT( p );+ charmap.face = FT_FACE( face );+ charmap.encoding = FT_ENCODING_NONE; /* will be filled later */+ offset = TT_NEXT_ULONG( p );++ if ( offset && offset <= face->cmap_size - 2 )+ {+ FT_Byte* volatile cmap = table + offset;+ volatile FT_UInt format = TT_PEEK_USHORT( cmap );+ const TT_CMap_Class* volatile pclazz = FT_TT_CMAP_CLASSES_GET;+ TT_CMap_Class volatile clazz;+++ for ( ; *pclazz; pclazz++ )+ {+ clazz = *pclazz;+ if ( clazz->format == format )+ {+ volatile TT_ValidatorRec valid;+ volatile FT_Error error = SFNT_Err_Ok;+++ ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit,+ FT_VALIDATE_DEFAULT );++ valid.num_glyphs = (FT_UInt)face->max_profile.numGlyphs;++ if ( ft_setjmp(+ *((ft_jmp_buf*)&FT_VALIDATOR( &valid )->jump_buffer) ) == 0 )+ {+ /* validate this cmap sub-table */+ error = clazz->validate( cmap, FT_VALIDATOR( &valid ) );+ }++ if ( valid.validator.error == 0 )+ {+ FT_CMap ttcmap;+++ /* It might make sense to store the single variation selector */+ /* cmap somewhere special. But it would have to be in the */+ /* public FT_FaceRec, and we can't change that. */++ if ( !FT_CMap_New( (FT_CMap_Class)clazz,+ cmap, &charmap, &ttcmap ) )+ {+ /* it is simpler to directly set `flags' than adding */+ /* a parameter to FT_CMap_New */+ ((TT_CMap)ttcmap)->flags = (FT_Int)error;+ }+ }+ else+ {+ FT_TRACE0(( "tt_face_build_cmaps:"+ " broken cmap sub-table ignored\n" ));+ }+ break;+ }+ }++ if ( *pclazz == NULL )+ {+ FT_TRACE0(( "tt_face_build_cmaps:"+ " unsupported cmap sub-table ignored\n" ));+ }+ }+ }++ return SFNT_Err_Ok;+ }+++ FT_LOCAL( FT_Error )+ tt_get_cmap_info( FT_CharMap charmap,+ TT_CMapInfo *cmap_info )+ {+ FT_CMap cmap = (FT_CMap)charmap;+ TT_CMap_Class clazz = (TT_CMap_Class)cmap->clazz;+++ return clazz->get_cmap_info( charmap, cmap_info );+ }+++/* END */
+ src/sfnt/ttcmap.h view
@@ -0,0 +1,125 @@+/***************************************************************************/+/* */+/* ttcmap.h */+/* */+/* TrueType character mapping table (cmap) support (specification). */+/* */+/* Copyright 2002, 2003, 2004, 2005 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 __TTCMAP_H__+#define __TTCMAP_H__+++#include <ft2build.h>+#include FT_INTERNAL_TRUETYPE_TYPES_H+#include FT_INTERNAL_VALIDATE_H+#include FT_SERVICE_TT_CMAP_H++FT_BEGIN_HEADER+++#define TT_CMAP_FLAG_UNSORTED 1+#define TT_CMAP_FLAG_OVERLAPPING 2++ typedef struct TT_CMapRec_+ {+ FT_CMapRec cmap;+ FT_Byte* data; /* pointer to in-memory cmap table */+ FT_Int flags; /* for format 4 only */++ } TT_CMapRec, *TT_CMap;++ typedef const struct TT_CMap_ClassRec_* TT_CMap_Class;+++ typedef FT_Error+ (*TT_CMap_ValidateFunc)( FT_Byte* data,+ FT_Validator valid );++ typedef struct TT_CMap_ClassRec_+ {+ FT_CMap_ClassRec clazz;+ FT_UInt format;+ TT_CMap_ValidateFunc validate;+ TT_CMap_Info_GetFunc get_cmap_info;++ } TT_CMap_ClassRec;++#ifndef FT_CONFIG_OPTION_PIC++#define FT_DEFINE_TT_CMAP(class_, size_, init_, done_, char_index_, \+ char_next_, char_var_index_, char_var_default_, variant_list_, \+ charvariant_list_,variantchar_list_, \+ format_, validate_, get_cmap_info_) \+ FT_CALLBACK_TABLE_DEF \+ const TT_CMap_ClassRec class_ = \+ { \+ {size_, init_, done_, char_index_, \+ char_next_, char_var_index_, char_var_default_, variant_list_, \+ charvariant_list_, variantchar_list_}, \+ format_, validate_, get_cmap_info_ \+ };++#else /* FT_CONFIG_OPTION_PIC */ ++#define FT_DEFINE_TT_CMAP(class_, size_, init_, done_, char_index_, \+ char_next_, char_var_index_, char_var_default_, variant_list_, \+ charvariant_list_,variantchar_list_, \+ format_, validate_, get_cmap_info_) \+ void \+ FT_Init_Class_##class_( TT_CMap_ClassRec* clazz ) \+ { \+ clazz->clazz.size = size_; \+ clazz->clazz.init = init_; \+ clazz->clazz.done = done_; \+ clazz->clazz.char_index = char_index_; \+ clazz->clazz.char_next = char_next_; \+ clazz->clazz.char_var_index = char_var_index_; \+ clazz->clazz.char_var_default = char_var_default_; \+ clazz->clazz.variant_list = variant_list_; \+ clazz->clazz.charvariant_list = charvariant_list_; \+ clazz->clazz.variantchar_list = variantchar_list_; \+ clazz->format = format_; \+ clazz->validate = validate_; \+ clazz->get_cmap_info = get_cmap_info_; \+ } ++#endif /* FT_CONFIG_OPTION_PIC */ ++ typedef struct TT_ValidatorRec_+ {+ FT_ValidatorRec validator;+ FT_UInt num_glyphs;++ } TT_ValidatorRec, *TT_Validator;+++#define TT_VALIDATOR( x ) ((TT_Validator)( x ))+#define TT_VALID_GLYPH_COUNT( x ) TT_VALIDATOR( x )->num_glyphs+++ FT_LOCAL( FT_Error )+ tt_face_build_cmaps( TT_Face face );++ /* used in tt-cmaps service */+ FT_LOCAL( FT_Error )+ tt_get_cmap_info( FT_CharMap charmap,+ TT_CMapInfo *cmap_info );+++FT_END_HEADER++#endif /* __TTCMAP_H__ */+++/* END */
+ src/sfnt/ttcmapc.h view
@@ -0,0 +1,55 @@+/***************************************************************************/+/* */+/* ttcmapc.h */+/* */+/* TT CMAP classes definitions (specification only). */+/* */+/* Copyright 2009 by */+/* Oran Agra and Mickey Gabel. */+/* */+/* 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. */+/* */+/***************************************************************************/+++#ifdef TT_CONFIG_CMAP_FORMAT_0+ TTCMAPCITEM(tt_cmap0_class_rec)+#endif++#ifdef TT_CONFIG_CMAP_FORMAT_2+ TTCMAPCITEM(tt_cmap2_class_rec)+#endif++#ifdef TT_CONFIG_CMAP_FORMAT_4+ TTCMAPCITEM(tt_cmap4_class_rec)+#endif++#ifdef TT_CONFIG_CMAP_FORMAT_6+ TTCMAPCITEM(tt_cmap6_class_rec)+#endif++#ifdef TT_CONFIG_CMAP_FORMAT_8+ TTCMAPCITEM(tt_cmap8_class_rec)+#endif++#ifdef TT_CONFIG_CMAP_FORMAT_10+ TTCMAPCITEM(tt_cmap10_class_rec)+#endif++#ifdef TT_CONFIG_CMAP_FORMAT_12+ TTCMAPCITEM(tt_cmap12_class_rec)+#endif++#ifdef TT_CONFIG_CMAP_FORMAT_13+ TTCMAPCITEM(tt_cmap13_class_rec)+#endif++#ifdef TT_CONFIG_CMAP_FORMAT_14+ TTCMAPCITEM(tt_cmap14_class_rec)+#endif++ /* END */
+ src/sfnt/ttkern.c view
@@ -0,0 +1,306 @@+/***************************************************************************/+/* */+/* ttkern.c */+/* */+/* Load the basic TrueType kerning table. This doesn't handle */+/* kerning data within the GPOS table at the moment. */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 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_STREAM_H+#include FT_TRUETYPE_TAGS_H+#include "ttkern.h"++#include "sferrors.h"+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_ttkern+++#undef TT_KERN_INDEX+#define TT_KERN_INDEX( g1, g2 ) ( ( (FT_ULong)(g1) << 16 ) | (g2) )+++ FT_LOCAL_DEF( FT_Error )+ tt_face_load_kern( TT_Face face,+ FT_Stream stream )+ {+ FT_Error error;+ FT_ULong table_size;+ FT_Byte* p;+ FT_Byte* p_limit;+ FT_UInt nn, num_tables;+ FT_UInt32 avail = 0, ordered = 0;+++ /* the kern table is optional; exit silently if it is missing */+ error = face->goto_table( face, TTAG_kern, stream, &table_size );+ if ( error )+ goto Exit;++ if ( table_size < 4 ) /* the case of a malformed table */+ {+ FT_ERROR(( "tt_face_load_kern:"+ " kerning table is too small - ignored\n" ));+ error = SFNT_Err_Table_Missing;+ goto Exit;+ }++ if ( FT_FRAME_EXTRACT( table_size, face->kern_table ) )+ {+ FT_ERROR(( "tt_face_load_kern:"+ " could not extract kerning table\n" ));+ goto Exit;+ }++ face->kern_table_size = table_size;++ p = face->kern_table;+ p_limit = p + table_size;++ p += 2; /* skip version */+ num_tables = FT_NEXT_USHORT( p );++ if ( num_tables > 32 ) /* we only support up to 32 sub-tables */+ num_tables = 32;++ for ( nn = 0; nn < num_tables; nn++ )+ {+ FT_UInt num_pairs, length, coverage;+ FT_Byte* p_next;+ FT_UInt32 mask = (FT_UInt32)1UL << nn;+++ if ( p + 6 > p_limit )+ break;++ p_next = p;++ p += 2; /* skip version */+ length = FT_NEXT_USHORT( p );+ coverage = FT_NEXT_USHORT( p );++ if ( length <= 6 )+ break;++ p_next += length;++ if ( p_next > p_limit ) /* handle broken table */+ p_next = p_limit;++ /* only use horizontal kerning tables */+ if ( ( coverage & ~8 ) != 0x0001 ||+ p + 8 > p_limit )+ goto NextTable;++ num_pairs = FT_NEXT_USHORT( p );+ p += 6;++ if ( ( p_next - p ) < 6 * (int)num_pairs ) /* handle broken count */+ num_pairs = (FT_UInt)( ( p_next - p ) / 6 );++ avail |= mask;++ /*+ * Now check whether the pairs in this table are ordered.+ * We then can use binary search.+ */+ if ( num_pairs > 0 )+ {+ FT_ULong count;+ FT_ULong old_pair;+++ old_pair = FT_NEXT_ULONG( p );+ p += 2;++ for ( count = num_pairs - 1; count > 0; count-- )+ {+ FT_UInt32 cur_pair;+++ cur_pair = FT_NEXT_ULONG( p );+ if ( cur_pair <= old_pair )+ break;++ p += 2;+ old_pair = cur_pair;+ }++ if ( count == 0 )+ ordered |= mask;+ }++ NextTable:+ p = p_next;+ }++ face->num_kern_tables = nn;+ face->kern_avail_bits = avail;+ face->kern_order_bits = ordered;++ Exit:+ return error;+ }+++ FT_LOCAL_DEF( void )+ tt_face_done_kern( TT_Face face )+ {+ FT_Stream stream = face->root.stream;+++ FT_FRAME_RELEASE( face->kern_table );+ face->kern_table_size = 0;+ face->num_kern_tables = 0;+ face->kern_avail_bits = 0;+ face->kern_order_bits = 0;+ }+++ FT_LOCAL_DEF( FT_Int )+ tt_face_get_kerning( TT_Face face,+ FT_UInt left_glyph,+ FT_UInt right_glyph )+ {+ FT_Int result = 0;+ FT_UInt count, mask = 1;+ FT_Byte* p = face->kern_table;+ FT_Byte* p_limit = p + face->kern_table_size;+++ p += 4;+ mask = 0x0001;++ for ( count = face->num_kern_tables;+ count > 0 && p + 6 <= p_limit;+ count--, mask <<= 1 )+ {+ FT_Byte* base = p;+ FT_Byte* next = base;+ FT_UInt version = FT_NEXT_USHORT( p );+ FT_UInt length = FT_NEXT_USHORT( p );+ FT_UInt coverage = FT_NEXT_USHORT( p );+ FT_UInt num_pairs;+ FT_Int value = 0;++ FT_UNUSED( version );+++ next = base + length;++ if ( next > p_limit ) /* handle broken table */+ next = p_limit;++ if ( ( face->kern_avail_bits & mask ) == 0 )+ goto NextTable;++ if ( p + 8 > next )+ goto NextTable;++ num_pairs = FT_NEXT_USHORT( p );+ p += 6;++ if ( ( next - p ) < 6 * (int)num_pairs ) /* handle broken count */+ num_pairs = (FT_UInt)( ( next - p ) / 6 );++ switch ( coverage >> 8 )+ {+ case 0:+ {+ FT_ULong key0 = TT_KERN_INDEX( left_glyph, right_glyph );+++ if ( face->kern_order_bits & mask ) /* binary search */+ {+ FT_UInt min = 0;+ FT_UInt max = num_pairs;+++ while ( min < max )+ {+ FT_UInt mid = ( min + max ) >> 1;+ FT_Byte* q = p + 6 * mid;+ FT_ULong key;+++ key = FT_NEXT_ULONG( q );++ if ( key == key0 )+ {+ value = FT_PEEK_SHORT( q );+ goto Found;+ }+ if ( key < key0 )+ min = mid + 1;+ else+ max = mid;+ }+ }+ else /* linear search */+ {+ FT_UInt count2;+++ for ( count2 = num_pairs; count2 > 0; count2-- )+ {+ FT_ULong key = FT_NEXT_ULONG( p );+++ if ( key == key0 )+ {+ value = FT_PEEK_SHORT( p );+ goto Found;+ }+ p += 2;+ }+ }+ }+ break;++ /*+ * We don't support format 2 because we haven't seen a single font+ * using it in real life...+ */++ default:+ ;+ }++ goto NextTable;++ Found:+ if ( coverage & 8 ) /* override or add */+ result = value;+ else+ result += value;++ NextTable:+ p = next;+ }++ return result;+ }++#undef TT_KERN_INDEX++/* END */
+ src/sfnt/ttkern.h view
@@ -0,0 +1,52 @@+/***************************************************************************/+/* */+/* ttkern.h */+/* */+/* Load the basic TrueType kerning table. This doesn't handle */+/* kerning data within the GPOS table at the moment. */+/* */+/* Copyright 1996-2001, 2002, 2005, 2007 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 __TTKERN_H__+#define __TTKERN_H__+++#include <ft2build.h>+#include FT_INTERNAL_STREAM_H+#include FT_INTERNAL_TRUETYPE_TYPES_H+++FT_BEGIN_HEADER+++ FT_LOCAL( FT_Error )+ tt_face_load_kern( TT_Face face,+ FT_Stream stream );++ FT_LOCAL( void )+ tt_face_done_kern( TT_Face face );++ FT_LOCAL( FT_Int )+ tt_face_get_kerning( TT_Face face,+ FT_UInt left_glyph,+ FT_UInt right_glyph );++#define TT_FACE_HAS_KERNING( face ) ( (face)->kern_avail_bits != 0 )+++FT_END_HEADER++#endif /* __TTKERN_H__ */+++/* END */
+ src/sfnt/ttload.c view
@@ -0,0 +1,1267 @@+/***************************************************************************/+/* */+/* ttload.c */+/* */+/* Load the basic TrueType tables, i.e., tables that can be either in */+/* TTF or OTF fonts (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */+/* 2010 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_STREAM_H+#include FT_TRUETYPE_TAGS_H+#include "ttload.h"++#include "sferrors.h"+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_ttload+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_face_lookup_table */+ /* */+ /* <Description> */+ /* Looks for a TrueType table by name. */+ /* */+ /* <Input> */+ /* face :: A face object handle. */+ /* */+ /* tag :: The searched tag. */+ /* */+ /* <Return> */+ /* A pointer to the table directory entry. 0 if not found. */+ /* */+ FT_LOCAL_DEF( TT_Table )+ tt_face_lookup_table( TT_Face face,+ FT_ULong tag )+ {+ TT_Table entry;+ TT_Table limit;+#ifdef FT_DEBUG_LEVEL_TRACE+ FT_Bool zero_length = FALSE;+#endif+++ FT_TRACE4(( "tt_face_lookup_table: %08p, `%c%c%c%c' -- ",+ face,+ (FT_Char)( tag >> 24 ),+ (FT_Char)( tag >> 16 ),+ (FT_Char)( tag >> 8 ),+ (FT_Char)( tag ) ));++ entry = face->dir_tables;+ limit = entry + face->num_tables;++ for ( ; entry < limit; entry++ )+ {+ /* For compatibility with Windows, we consider */+ /* zero-length tables the same as missing tables. */+ if ( entry->Tag == tag )+ {+ if ( entry->Length != 0 )+ {+ FT_TRACE4(( "found table.\n" ));+ return entry;+ }+#ifdef FT_DEBUG_LEVEL_TRACE+ zero_length = TRUE;+#endif+ }+ }++#ifdef FT_DEBUG_LEVEL_TRACE+ if ( zero_length )+ FT_TRACE4(( "ignoring empty table\n" ));+ else+ FT_TRACE4(( "could not find table\n" ));+#endif++ return NULL;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_face_goto_table */+ /* */+ /* <Description> */+ /* Looks for a TrueType table by name, then seek a stream to it. */+ /* */+ /* <Input> */+ /* face :: A face object handle. */+ /* */+ /* tag :: The searched tag. */+ /* */+ /* stream :: The stream to seek when the table is found. */+ /* */+ /* <Output> */+ /* length :: The length of the table if found, undefined otherwise. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ tt_face_goto_table( TT_Face face,+ FT_ULong tag,+ FT_Stream stream,+ FT_ULong* length )+ {+ TT_Table table;+ FT_Error error;+++ table = tt_face_lookup_table( face, tag );+ if ( table )+ {+ if ( length )+ *length = table->Length;++ if ( FT_STREAM_SEEK( table->Offset ) )+ goto Exit;+ }+ else+ error = SFNT_Err_Table_Missing;++ Exit:+ return error;+ }+++ /* Here, we */+ /* */+ /* - check that `num_tables' is valid (and adjust it if necessary) */+ /* */+ /* - look for a `head' table, check its size, and parse it to check */+ /* whether its `magic' field is correctly set */+ /* */+ /* - errors (except errors returned by stream handling) */+ /* */+ /* SFNT_Err_Unknown_File_Format: */+ /* no table is defined in directory, it is not sfnt-wrapped */+ /* data */+ /* SFNT_Err_Table_Missing: */+ /* table directory is valid, but essential tables */+ /* (head/bhed/SING) are missing */+ /* */+ static FT_Error+ check_table_dir( SFNT_Header sfnt,+ FT_Stream stream )+ {+ FT_Error error;+ FT_UShort nn, valid_entries = 0;+ FT_UInt has_head = 0, has_sing = 0, has_meta = 0;+ FT_ULong offset = sfnt->offset + 12;++ static const FT_Frame_Field table_dir_entry_fields[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE TT_TableRec++ FT_FRAME_START( 16 ),+ FT_FRAME_ULONG( Tag ),+ FT_FRAME_ULONG( CheckSum ),+ FT_FRAME_ULONG( Offset ),+ FT_FRAME_ULONG( Length ),+ FT_FRAME_END+ };+++ if ( FT_STREAM_SEEK( offset ) )+ goto Exit;++ for ( nn = 0; nn < sfnt->num_tables; nn++ )+ {+ TT_TableRec table;+++ if ( FT_STREAM_READ_FIELDS( table_dir_entry_fields, &table ) )+ {+ nn--;+ FT_TRACE2(( "check_table_dir:"+ " can read only %d table%s in font (instead of %d)\n",+ nn, nn == 1 ? "" : "s", sfnt->num_tables ));+ sfnt->num_tables = nn;+ break;+ }++ /* we ignore invalid tables */+ if ( table.Offset + table.Length > stream->size )+ {+ FT_TRACE2(( "check_table_dir: table entry %d invalid\n", nn ));+ continue;+ }+ else+ valid_entries++;++ if ( table.Tag == TTAG_head || table.Tag == TTAG_bhed )+ {+ FT_UInt32 magic;+++#ifndef TT_CONFIG_OPTION_EMBEDDED_BITMAPS+ if ( table.Tag == TTAG_head )+#endif+ has_head = 1;++ /*+ * The table length should be 0x36, but certain font tools make it+ * 0x38, so we will just check that it is greater.+ *+ * Note that according to the specification, the table must be+ * padded to 32-bit lengths, but this doesn't apply to the value of+ * its `Length' field!+ *+ */+ if ( table.Length < 0x36 )+ {+ FT_TRACE2(( "check_table_dir: `head' table too small\n" ));+ error = SFNT_Err_Table_Missing;+ goto Exit;+ }++ if ( FT_STREAM_SEEK( table.Offset + 12 ) ||+ FT_READ_ULONG( magic ) )+ goto Exit;++ if ( magic != 0x5F0F3CF5UL )+ {+ FT_TRACE2(( "check_table_dir:"+ " no magic number found in `head' table\n"));+ error = SFNT_Err_Table_Missing;+ goto Exit;+ }++ if ( FT_STREAM_SEEK( offset + ( nn + 1 ) * 16 ) )+ goto Exit;+ }+ else if ( table.Tag == TTAG_SING )+ has_sing = 1;+ else if ( table.Tag == TTAG_META )+ has_meta = 1;+ }++ sfnt->num_tables = valid_entries;++ if ( sfnt->num_tables == 0 )+ {+ FT_TRACE2(( "check_table_dir: no tables found\n" ));+ error = SFNT_Err_Unknown_File_Format;+ goto Exit;+ }++ /* if `sing' and `meta' tables are present, there is no `head' table */+ if ( has_head || ( has_sing && has_meta ) )+ {+ error = SFNT_Err_Ok;+ goto Exit;+ }+ else+ {+ FT_TRACE2(( "check_table_dir:" ));+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS+ FT_TRACE2(( " neither `head', `bhed', nor `sing' table found\n" ));+#else+ FT_TRACE2(( " neither `head' nor `sing' table found\n" ));+#endif+ error = SFNT_Err_Table_Missing;+ }++ Exit:+ return error;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_face_load_font_dir */+ /* */+ /* <Description> */+ /* Loads the header of a SFNT font file. */+ /* */+ /* <Input> */+ /* face :: A handle to the target face object. */+ /* */+ /* stream :: The input stream. */+ /* */+ /* <Output> */+ /* sfnt :: The SFNT header. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ /* <Note> */+ /* The stream cursor must be at the beginning of the font directory. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ tt_face_load_font_dir( TT_Face face,+ FT_Stream stream )+ {+ SFNT_HeaderRec sfnt;+ FT_Error error;+ FT_Memory memory = stream->memory;+ TT_TableRec* entry;+ FT_Int nn;++ static const FT_Frame_Field offset_table_fields[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE SFNT_HeaderRec++ FT_FRAME_START( 8 ),+ FT_FRAME_USHORT( num_tables ),+ FT_FRAME_USHORT( search_range ),+ FT_FRAME_USHORT( entry_selector ),+ FT_FRAME_USHORT( range_shift ),+ FT_FRAME_END+ };+++ FT_TRACE2(( "tt_face_load_font_dir: %08p\n", face ));++ /* read the offset table */++ sfnt.offset = FT_STREAM_POS();++ if ( FT_READ_ULONG( sfnt.format_tag ) ||+ FT_STREAM_READ_FIELDS( offset_table_fields, &sfnt ) )+ goto Exit;++ /* many fonts don't have these fields set correctly */+#if 0+ if ( sfnt.search_range != 1 << ( sfnt.entry_selector + 4 ) ||+ sfnt.search_range + sfnt.range_shift != sfnt.num_tables << 4 )+ return SFNT_Err_Unknown_File_Format;+#endif++ /* load the table directory */++ FT_TRACE2(( "-- Number of tables: %10u\n", sfnt.num_tables ));+ FT_TRACE2(( "-- Format version: 0x%08lx\n", sfnt.format_tag ));++ /* check first */+ error = check_table_dir( &sfnt, stream );+ if ( error )+ {+ FT_TRACE2(( "tt_face_load_font_dir:"+ " invalid table directory for TrueType\n" ));++ goto Exit;+ }++ face->num_tables = sfnt.num_tables;+ 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 ) )+ goto Exit;++ entry = face->dir_tables;++ FT_TRACE2(( "\n"+ " tag offset length checksum\n"+ " ----------------------------------\n" ));++ for ( nn = 0; nn < sfnt.num_tables; nn++ )+ {+ entry->Tag = FT_GET_TAG4();+ entry->CheckSum = FT_GET_ULONG();+ entry->Offset = FT_GET_LONG();+ entry->Length = FT_GET_LONG();++ /* ignore invalid tables */+ if ( entry->Offset + entry->Length > stream->size )+ 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_FRAME_EXIT();++ FT_TRACE2(( "table directory loaded\n\n" ));++ Exit:+ return error;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_face_load_any */+ /* */+ /* <Description> */+ /* Loads any font table into client memory. */+ /* */+ /* <Input> */+ /* face :: The face object to look for. */+ /* */+ /* tag :: The tag of table to load. Use the value 0 if you want */+ /* to access the whole font file, else set this parameter */+ /* to a valid TrueType table tag that you can forge with */+ /* the MAKE_TT_TAG macro. */+ /* */+ /* offset :: The starting offset in the table (or the file if */+ /* tag == 0). */+ /* */+ /* length :: The address of the decision variable: */+ /* */+ /* If length == NULL: */+ /* Loads the whole table. Returns an error if */+ /* `offset' == 0! */+ /* */+ /* If *length == 0: */+ /* Exits immediately; returning the length of the given */+ /* table or of the font file, depending on the value of */+ /* `tag'. */+ /* */+ /* If *length != 0: */+ /* Loads the next `length' bytes of table or font, */+ /* starting at offset `offset' (in table or font too). */+ /* */+ /* <Output> */+ /* buffer :: The address of target buffer. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ tt_face_load_any( TT_Face face,+ FT_ULong tag,+ FT_Long offset,+ FT_Byte* buffer,+ FT_ULong* length )+ {+ FT_Error error;+ FT_Stream stream;+ TT_Table table;+ FT_ULong size;+++ if ( tag != 0 )+ {+ /* look for tag in font directory */+ table = tt_face_lookup_table( face, tag );+ if ( !table )+ {+ error = SFNT_Err_Table_Missing;+ goto Exit;+ }++ offset += table->Offset;+ size = table->Length;+ }+ else+ /* tag == 0 -- the user wants to access the font file directly */+ size = face->root.stream->size;++ if ( length && *length == 0 )+ {+ *length = size;++ return SFNT_Err_Ok;+ }++ if ( length )+ size = *length;++ stream = face->root.stream;+ /* the `if' is syntactic sugar for picky compilers */+ if ( FT_STREAM_READ_AT( offset, buffer, size ) )+ goto Exit;++ Exit:+ return error;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_face_load_generic_header */+ /* */+ /* <Description> */+ /* Loads the TrueType table `head' or `bhed'. */+ /* */+ /* <Input> */+ /* face :: A handle to the target face object. */+ /* */+ /* stream :: The input stream. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ static FT_Error+ tt_face_load_generic_header( TT_Face face,+ FT_Stream stream,+ FT_ULong tag )+ {+ FT_Error error;+ TT_Header* header;++ static const FT_Frame_Field header_fields[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE TT_Header++ FT_FRAME_START( 54 ),+ FT_FRAME_ULONG ( Table_Version ),+ FT_FRAME_ULONG ( Font_Revision ),+ FT_FRAME_LONG ( CheckSum_Adjust ),+ FT_FRAME_LONG ( Magic_Number ),+ FT_FRAME_USHORT( Flags ),+ FT_FRAME_USHORT( Units_Per_EM ),+ FT_FRAME_LONG ( Created[0] ),+ FT_FRAME_LONG ( Created[1] ),+ FT_FRAME_LONG ( Modified[0] ),+ FT_FRAME_LONG ( Modified[1] ),+ FT_FRAME_SHORT ( xMin ),+ FT_FRAME_SHORT ( yMin ),+ FT_FRAME_SHORT ( xMax ),+ FT_FRAME_SHORT ( yMax ),+ FT_FRAME_USHORT( Mac_Style ),+ FT_FRAME_USHORT( Lowest_Rec_PPEM ),+ FT_FRAME_SHORT ( Font_Direction ),+ FT_FRAME_SHORT ( Index_To_Loc_Format ),+ FT_FRAME_SHORT ( Glyph_Data_Format ),+ FT_FRAME_END+ };+++ error = face->goto_table( face, tag, stream, 0 );+ if ( error )+ goto Exit;++ header = &face->header;++ if ( FT_STREAM_READ_FIELDS( header_fields, header ) )+ goto Exit;++ FT_TRACE3(( "Units per EM: %4u\n", header->Units_Per_EM ));+ FT_TRACE3(( "IndexToLoc: %4d\n", header->Index_To_Loc_Format ));++ Exit:+ return error;+ }+++ FT_LOCAL_DEF( FT_Error )+ tt_face_load_head( TT_Face face,+ FT_Stream stream )+ {+ return tt_face_load_generic_header( face, stream, TTAG_head );+ }+++#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS++ FT_LOCAL_DEF( FT_Error )+ tt_face_load_bhed( TT_Face face,+ FT_Stream stream )+ {+ return tt_face_load_generic_header( face, stream, TTAG_bhed );+ }++#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_face_load_max_profile */+ /* */+ /* <Description> */+ /* Loads the maximum profile into a face object. */+ /* */+ /* <Input> */+ /* face :: A handle to the target face object. */+ /* */+ /* stream :: The input stream. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ tt_face_load_maxp( TT_Face face,+ FT_Stream stream )+ {+ FT_Error error;+ TT_MaxProfile* maxProfile = &face->max_profile;++ const FT_Frame_Field maxp_fields[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE TT_MaxProfile++ FT_FRAME_START( 6 ),+ FT_FRAME_LONG ( version ),+ FT_FRAME_USHORT( numGlyphs ),+ FT_FRAME_END+ };++ const FT_Frame_Field maxp_fields_extra[] =+ {+ FT_FRAME_START( 26 ),+ FT_FRAME_USHORT( maxPoints ),+ FT_FRAME_USHORT( maxContours ),+ FT_FRAME_USHORT( maxCompositePoints ),+ FT_FRAME_USHORT( maxCompositeContours ),+ FT_FRAME_USHORT( maxZones ),+ FT_FRAME_USHORT( maxTwilightPoints ),+ FT_FRAME_USHORT( maxStorage ),+ FT_FRAME_USHORT( maxFunctionDefs ),+ FT_FRAME_USHORT( maxInstructionDefs ),+ FT_FRAME_USHORT( maxStackElements ),+ FT_FRAME_USHORT( maxSizeOfInstructions ),+ FT_FRAME_USHORT( maxComponentElements ),+ FT_FRAME_USHORT( maxComponentDepth ),+ FT_FRAME_END+ };+++ error = face->goto_table( face, TTAG_maxp, stream, 0 );+ if ( error )+ goto Exit;++ if ( FT_STREAM_READ_FIELDS( maxp_fields, maxProfile ) )+ goto Exit;++ maxProfile->maxPoints = 0;+ maxProfile->maxContours = 0;+ maxProfile->maxCompositePoints = 0;+ maxProfile->maxCompositeContours = 0;+ maxProfile->maxZones = 0;+ maxProfile->maxTwilightPoints = 0;+ maxProfile->maxStorage = 0;+ maxProfile->maxFunctionDefs = 0;+ maxProfile->maxInstructionDefs = 0;+ maxProfile->maxStackElements = 0;+ maxProfile->maxSizeOfInstructions = 0;+ maxProfile->maxComponentElements = 0;+ maxProfile->maxComponentDepth = 0;++ if ( maxProfile->version >= 0x10000L )+ {+ if ( FT_STREAM_READ_FIELDS( maxp_fields_extra, maxProfile ) )+ goto Exit;++ /* XXX: an adjustment that is necessary to load certain */+ /* broken fonts like `Keystrokes MT' :-( */+ /* */+ /* We allocate 64 function entries by default when */+ /* the maxFunctionDefs value is smaller. */++ if ( maxProfile->maxFunctionDefs < 64 )+ maxProfile->maxFunctionDefs = 64;++ /* we add 4 phantom points later */+ if ( maxProfile->maxTwilightPoints > ( 0xFFFFU - 4 ) )+ {+ FT_TRACE0(( "tt_face_load_maxp:"+ " too much twilight points in `maxp' table;\n"+ " "+ " some glyphs might be rendered incorrectly\n" ));++ maxProfile->maxTwilightPoints = 0xFFFFU - 4;+ }++ /* we arbitrarily limit recursion to avoid stack exhaustion */+ if ( maxProfile->maxComponentDepth > 100 )+ {+ FT_TRACE0(( "tt_face_load_maxp:"+ " abnormally large component depth (%d) set to 100\n",+ maxProfile->maxComponentDepth ));+ maxProfile->maxComponentDepth = 100;+ }+ }++ FT_TRACE3(( "numGlyphs: %u\n", maxProfile->numGlyphs ));++ Exit:+ return error;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_face_load_names */+ /* */+ /* <Description> */+ /* Loads the name records. */+ /* */+ /* <Input> */+ /* face :: A handle to the target face object. */+ /* */+ /* stream :: The input stream. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ tt_face_load_name( TT_Face face,+ FT_Stream stream )+ {+ FT_Error error;+ FT_Memory memory = stream->memory;+ FT_ULong table_pos, table_len;+ FT_ULong storage_start, storage_limit;+ FT_UInt count;+ TT_NameTable table;++ static const FT_Frame_Field name_table_fields[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE TT_NameTableRec++ FT_FRAME_START( 6 ),+ FT_FRAME_USHORT( format ),+ FT_FRAME_USHORT( numNameRecords ),+ FT_FRAME_USHORT( storageOffset ),+ FT_FRAME_END+ };++ static const FT_Frame_Field name_record_fields[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE TT_NameEntryRec++ /* no FT_FRAME_START */+ FT_FRAME_USHORT( platformID ),+ FT_FRAME_USHORT( encodingID ),+ FT_FRAME_USHORT( languageID ),+ FT_FRAME_USHORT( nameID ),+ FT_FRAME_USHORT( stringLength ),+ FT_FRAME_USHORT( stringOffset ),+ FT_FRAME_END+ };+++ table = &face->name_table;+ table->stream = stream;++ error = face->goto_table( face, TTAG_name, stream, &table_len );+ if ( error )+ goto Exit;++ table_pos = FT_STREAM_POS();+++ if ( FT_STREAM_READ_FIELDS( name_table_fields, table ) )+ goto Exit;++ /* Some popular Asian fonts have an invalid `storageOffset' value */+ /* (it should be at least "6 + 12*num_names"). However, the string */+ /* offsets, computed as "storageOffset + entry->stringOffset", are */+ /* valid pointers within the name table... */+ /* */+ /* We thus can't check `storageOffset' right now. */+ /* */+ storage_start = table_pos + 6 + 12*table->numNameRecords;+ storage_limit = table_pos + table_len;++ if ( storage_start > storage_limit )+ {+ FT_ERROR(( "tt_face_load_name: invalid `name' table\n" ));+ error = SFNT_Err_Name_Table_Missing;+ goto Exit;+ }++ /* Allocate the array of name records. */+ count = table->numNameRecords;+ table->numNameRecords = 0;++ if ( FT_NEW_ARRAY( table->names, count ) ||+ FT_FRAME_ENTER( count * 12 ) )+ goto Exit;++ /* Load the name records and determine how much storage is needed */+ /* to hold the strings themselves. */+ {+ TT_NameEntryRec* entry = table->names;+++ for ( ; count > 0; count-- )+ {+ if ( FT_STREAM_READ_FIELDS( name_record_fields, entry ) )+ continue;++ /* check that the name is not empty */+ if ( entry->stringLength == 0 )+ continue;++ /* check that the name string is within the table */+ entry->stringOffset += table_pos + table->storageOffset;+ if ( entry->stringOffset < storage_start ||+ entry->stringOffset + entry->stringLength > storage_limit )+ {+ /* invalid entry - ignore it */+ entry->stringOffset = 0;+ entry->stringLength = 0;+ continue;+ }++ entry++;+ }++ table->numNameRecords = (FT_UInt)( entry - table->names );+ }++ FT_FRAME_EXIT();++ /* everything went well, update face->num_names */+ face->num_names = (FT_UShort) table->numNameRecords;++ Exit:+ return error;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_face_free_names */+ /* */+ /* <Description> */+ /* Frees the name records. */+ /* */+ /* <Input> */+ /* face :: A handle to the target face object. */+ /* */+ FT_LOCAL_DEF( void )+ tt_face_free_name( TT_Face face )+ {+ FT_Memory memory = face->root.driver->root.memory;+ TT_NameTable table = &face->name_table;+ TT_NameEntry entry = table->names;+ FT_UInt count = table->numNameRecords;+++ if ( table->names )+ {+ for ( ; count > 0; count--, entry++ )+ {+ FT_FREE( entry->string );+ entry->stringLength = 0;+ }++ /* free strings table */+ FT_FREE( table->names );+ }++ table->numNameRecords = 0;+ table->format = 0;+ table->storageOffset = 0;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_face_load_cmap */+ /* */+ /* <Description> */+ /* Loads the cmap directory in a face object. The cmaps themselves */+ /* are loaded on demand in the `ttcmap.c' module. */+ /* */+ /* <Input> */+ /* face :: A handle to the target face object. */+ /* */+ /* stream :: A handle to the input stream. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */++ FT_LOCAL_DEF( FT_Error )+ tt_face_load_cmap( TT_Face face,+ FT_Stream stream )+ {+ FT_Error error;+++ error = face->goto_table( face, TTAG_cmap, stream, &face->cmap_size );+ if ( error )+ goto Exit;++ if ( FT_FRAME_EXTRACT( face->cmap_size, face->cmap_table ) )+ face->cmap_size = 0;++ Exit:+ return error;+ }++++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_face_load_os2 */+ /* */+ /* <Description> */+ /* Loads the OS2 table. */+ /* */+ /* <Input> */+ /* face :: A handle to the target face object. */+ /* */+ /* stream :: A handle to the input stream. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ tt_face_load_os2( TT_Face face,+ FT_Stream stream )+ {+ FT_Error error;+ TT_OS2* os2;++ const FT_Frame_Field os2_fields[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE TT_OS2++ FT_FRAME_START( 78 ),+ FT_FRAME_USHORT( version ),+ FT_FRAME_SHORT ( xAvgCharWidth ),+ FT_FRAME_USHORT( usWeightClass ),+ FT_FRAME_USHORT( usWidthClass ),+ FT_FRAME_SHORT ( fsType ),+ FT_FRAME_SHORT ( ySubscriptXSize ),+ FT_FRAME_SHORT ( ySubscriptYSize ),+ FT_FRAME_SHORT ( ySubscriptXOffset ),+ FT_FRAME_SHORT ( ySubscriptYOffset ),+ FT_FRAME_SHORT ( ySuperscriptXSize ),+ FT_FRAME_SHORT ( ySuperscriptYSize ),+ FT_FRAME_SHORT ( ySuperscriptXOffset ),+ FT_FRAME_SHORT ( ySuperscriptYOffset ),+ FT_FRAME_SHORT ( yStrikeoutSize ),+ FT_FRAME_SHORT ( yStrikeoutPosition ),+ FT_FRAME_SHORT ( sFamilyClass ),+ FT_FRAME_BYTE ( panose[0] ),+ FT_FRAME_BYTE ( panose[1] ),+ FT_FRAME_BYTE ( panose[2] ),+ FT_FRAME_BYTE ( panose[3] ),+ FT_FRAME_BYTE ( panose[4] ),+ FT_FRAME_BYTE ( panose[5] ),+ FT_FRAME_BYTE ( panose[6] ),+ FT_FRAME_BYTE ( panose[7] ),+ FT_FRAME_BYTE ( panose[8] ),+ FT_FRAME_BYTE ( panose[9] ),+ FT_FRAME_ULONG ( ulUnicodeRange1 ),+ FT_FRAME_ULONG ( ulUnicodeRange2 ),+ FT_FRAME_ULONG ( ulUnicodeRange3 ),+ FT_FRAME_ULONG ( ulUnicodeRange4 ),+ FT_FRAME_BYTE ( achVendID[0] ),+ FT_FRAME_BYTE ( achVendID[1] ),+ FT_FRAME_BYTE ( achVendID[2] ),+ FT_FRAME_BYTE ( achVendID[3] ),++ FT_FRAME_USHORT( fsSelection ),+ FT_FRAME_USHORT( usFirstCharIndex ),+ FT_FRAME_USHORT( usLastCharIndex ),+ FT_FRAME_SHORT ( sTypoAscender ),+ FT_FRAME_SHORT ( sTypoDescender ),+ FT_FRAME_SHORT ( sTypoLineGap ),+ FT_FRAME_USHORT( usWinAscent ),+ FT_FRAME_USHORT( usWinDescent ),+ FT_FRAME_END+ };++ const FT_Frame_Field os2_fields_extra[] =+ {+ FT_FRAME_START( 8 ),+ FT_FRAME_ULONG( ulCodePageRange1 ),+ FT_FRAME_ULONG( ulCodePageRange2 ),+ FT_FRAME_END+ };++ const FT_Frame_Field os2_fields_extra2[] =+ {+ FT_FRAME_START( 10 ),+ FT_FRAME_SHORT ( sxHeight ),+ FT_FRAME_SHORT ( sCapHeight ),+ FT_FRAME_USHORT( usDefaultChar ),+ FT_FRAME_USHORT( usBreakChar ),+ FT_FRAME_USHORT( usMaxContext ),+ FT_FRAME_END+ };+++ /* We now support old Mac fonts where the OS/2 table doesn't */+ /* exist. Simply put, we set the `version' field to 0xFFFF */+ /* and test this value each time we need to access the table. */+ error = face->goto_table( face, TTAG_OS2, stream, 0 );+ if ( error )+ goto Exit;++ os2 = &face->os2;++ if ( FT_STREAM_READ_FIELDS( os2_fields, os2 ) )+ goto Exit;++ os2->ulCodePageRange1 = 0;+ os2->ulCodePageRange2 = 0;+ os2->sxHeight = 0;+ os2->sCapHeight = 0;+ os2->usDefaultChar = 0;+ os2->usBreakChar = 0;+ os2->usMaxContext = 0;++ if ( os2->version >= 0x0001 )+ {+ /* only version 1 tables */+ if ( FT_STREAM_READ_FIELDS( os2_fields_extra, os2 ) )+ goto Exit;++ if ( os2->version >= 0x0002 )+ {+ /* only version 2 tables */+ if ( FT_STREAM_READ_FIELDS( os2_fields_extra2, os2 ) )+ goto Exit;+ }+ }++ FT_TRACE3(( "sTypoAscender: %4d\n", os2->sTypoAscender ));+ FT_TRACE3(( "sTypoDescender: %4d\n", os2->sTypoDescender ));+ FT_TRACE3(( "usWinAscent: %4u\n", os2->usWinAscent ));+ FT_TRACE3(( "usWinDescent: %4u\n", os2->usWinDescent ));+ FT_TRACE3(( "fsSelection: 0x%2x\n", os2->fsSelection ));++ Exit:+ return error;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_face_load_postscript */+ /* */+ /* <Description> */+ /* Loads the Postscript table. */+ /* */+ /* <Input> */+ /* face :: A handle to the target face object. */+ /* */+ /* stream :: A handle to the input stream. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ tt_face_load_post( TT_Face face,+ FT_Stream stream )+ {+ FT_Error error;+ TT_Postscript* post = &face->postscript;++ static const FT_Frame_Field post_fields[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE TT_Postscript++ FT_FRAME_START( 32 ),+ FT_FRAME_ULONG( FormatType ),+ FT_FRAME_ULONG( italicAngle ),+ FT_FRAME_SHORT( underlinePosition ),+ FT_FRAME_SHORT( underlineThickness ),+ FT_FRAME_ULONG( isFixedPitch ),+ FT_FRAME_ULONG( minMemType42 ),+ FT_FRAME_ULONG( maxMemType42 ),+ FT_FRAME_ULONG( minMemType1 ),+ FT_FRAME_ULONG( maxMemType1 ),+ FT_FRAME_END+ };+++ error = face->goto_table( face, TTAG_post, stream, 0 );+ if ( error )+ return error;++ if ( FT_STREAM_READ_FIELDS( post_fields, post ) )+ return error;++ /* we don't load the glyph names, we do that in another */+ /* module (ttpost). */++ FT_TRACE3(( "FormatType: 0x%x\n", post->FormatType ));+ FT_TRACE3(( "isFixedPitch: %s\n", post->isFixedPitch+ ? " yes" : " no" ));++ return SFNT_Err_Ok;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_face_load_pclt */+ /* */+ /* <Description> */+ /* Loads the PCL 5 Table. */+ /* */+ /* <Input> */+ /* face :: A handle to the target face object. */+ /* */+ /* stream :: A handle to the input stream. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ tt_face_load_pclt( TT_Face face,+ FT_Stream stream )+ {+ static const FT_Frame_Field pclt_fields[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE TT_PCLT++ FT_FRAME_START( 54 ),+ FT_FRAME_ULONG ( Version ),+ FT_FRAME_ULONG ( FontNumber ),+ FT_FRAME_USHORT( Pitch ),+ FT_FRAME_USHORT( xHeight ),+ FT_FRAME_USHORT( Style ),+ FT_FRAME_USHORT( TypeFamily ),+ FT_FRAME_USHORT( CapHeight ),+ FT_FRAME_BYTES ( TypeFace, 16 ),+ FT_FRAME_BYTES ( CharacterComplement, 8 ),+ FT_FRAME_BYTES ( FileName, 6 ),+ FT_FRAME_CHAR ( StrokeWeight ),+ FT_FRAME_CHAR ( WidthType ),+ FT_FRAME_BYTE ( SerifStyle ),+ FT_FRAME_BYTE ( Reserved ),+ FT_FRAME_END+ };++ FT_Error error;+ TT_PCLT* pclt = &face->pclt;+++ /* optional table */+ error = face->goto_table( face, TTAG_PCLT, stream, 0 );+ if ( error )+ goto Exit;++ if ( FT_STREAM_READ_FIELDS( pclt_fields, pclt ) )+ goto Exit;++ Exit:+ return error;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_face_load_gasp */+ /* */+ /* <Description> */+ /* Loads the `gasp' table into a face object. */+ /* */+ /* <Input> */+ /* face :: A handle to the target face object. */+ /* */+ /* stream :: The input stream. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ tt_face_load_gasp( TT_Face face,+ FT_Stream stream )+ {+ FT_Error error;+ FT_Memory memory = stream->memory;++ FT_UInt j,num_ranges;+ TT_GaspRange gaspranges;+++ /* the gasp table is optional */+ error = face->goto_table( face, TTAG_gasp, stream, 0 );+ if ( error )+ goto Exit;++ if ( FT_FRAME_ENTER( 4L ) )+ goto Exit;++ face->gasp.version = FT_GET_USHORT();+ face->gasp.numRanges = FT_GET_USHORT();++ FT_FRAME_EXIT();++ /* only support versions 0 and 1 of the table */+ if ( face->gasp.version >= 2 )+ {+ face->gasp.numRanges = 0;+ error = SFNT_Err_Invalid_Table;+ goto Exit;+ }++ num_ranges = face->gasp.numRanges;+ FT_TRACE3(( "numRanges: %u\n", num_ranges ));++ if ( FT_QNEW_ARRAY( gaspranges, num_ranges ) ||+ FT_FRAME_ENTER( num_ranges * 4L ) )+ goto Exit;++ face->gasp.gaspRanges = gaspranges;++ for ( j = 0; j < num_ranges; j++ )+ {+ gaspranges[j].maxPPEM = FT_GET_USHORT();+ gaspranges[j].gaspFlag = FT_GET_USHORT();++ FT_TRACE3(( "gaspRange %d: rangeMaxPPEM %5d, rangeGaspBehavior 0x%x\n",+ j,+ gaspranges[j].maxPPEM,+ gaspranges[j].gaspFlag ));+ }++ FT_FRAME_EXIT();++ Exit:+ return error;+ }+++/* END */
+ src/sfnt/ttload.h view
@@ -0,0 +1,112 @@+/***************************************************************************/+/* */+/* ttload.h */+/* */+/* Load the basic TrueType tables, i.e., tables that can be either in */+/* TTF or OTF fonts (specification). */+/* */+/* Copyright 1996-2001, 2002, 2005, 2006 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 __TTLOAD_H__+#define __TTLOAD_H__+++#include <ft2build.h>+#include FT_INTERNAL_STREAM_H+#include FT_INTERNAL_TRUETYPE_TYPES_H+++FT_BEGIN_HEADER+++ FT_LOCAL( TT_Table )+ tt_face_lookup_table( TT_Face face,+ FT_ULong tag );++ FT_LOCAL( FT_Error )+ tt_face_goto_table( TT_Face face,+ FT_ULong tag,+ FT_Stream stream,+ FT_ULong* length );+++ FT_LOCAL( FT_Error )+ tt_face_load_font_dir( TT_Face face,+ FT_Stream stream );+++ FT_LOCAL( FT_Error )+ tt_face_load_any( TT_Face face,+ FT_ULong tag,+ FT_Long offset,+ FT_Byte* buffer,+ FT_ULong* length );+++ FT_LOCAL( FT_Error )+ tt_face_load_head( TT_Face face,+ FT_Stream stream );+++ FT_LOCAL( FT_Error )+ tt_face_load_cmap( TT_Face face,+ FT_Stream stream );+++ FT_LOCAL( FT_Error )+ tt_face_load_maxp( TT_Face face,+ FT_Stream stream );+++ FT_LOCAL( FT_Error )+ tt_face_load_name( TT_Face face,+ FT_Stream stream );+++ FT_LOCAL( FT_Error )+ tt_face_load_os2( TT_Face face,+ FT_Stream stream );+++ FT_LOCAL( FT_Error )+ tt_face_load_post( TT_Face face,+ FT_Stream stream );+++ FT_LOCAL( FT_Error )+ tt_face_load_pclt( TT_Face face,+ FT_Stream stream );++ FT_LOCAL( void )+ tt_face_free_name( TT_Face face );+++ FT_LOCAL( FT_Error )+ tt_face_load_gasp( TT_Face face,+ FT_Stream stream );++#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS++ FT_LOCAL( FT_Error )+ tt_face_load_bhed( TT_Face face,+ FT_Stream stream );++#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */+++FT_END_HEADER++#endif /* __TTLOAD_H__ */+++/* END */
+ src/sfnt/ttmtx.c view
@@ -0,0 +1,468 @@+/***************************************************************************/+/* */+/* ttmtx.c */+/* */+/* Load the metrics tables common to TTF and OTF fonts (body). */+/* */+/* Copyright 2006, 2007, 2008, 2009 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_STREAM_H+#include FT_TRUETYPE_TAGS_H+#include "ttmtx.h"++#include "sferrors.h"+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_ttmtx+++ /*+ * Unfortunately, we can't enable our memory optimizations if+ * FT_CONFIG_OPTION_OLD_INTERNALS is defined. This is because at least+ * one rogue client (libXfont in the X.Org XServer) is directly accessing+ * the metrics.+ */++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_face_load_hmtx */+ /* */+ /* <Description> */+ /* Load the `hmtx' or `vmtx' table into a face object. */+ /* */+ /* <Input> */+ /* face :: A handle to the target face object. */+ /* */+ /* stream :: The input stream. */+ /* */+ /* vertical :: A boolean flag. If set, load `vmtx'. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+#ifndef FT_CONFIG_OPTION_OLD_INTERNALS++ FT_LOCAL_DEF( FT_Error )+ tt_face_load_hmtx( TT_Face face,+ FT_Stream stream,+ FT_Bool vertical )+ {+ FT_Error error;+ FT_ULong tag, table_size;+ FT_ULong* ptable_offset;+ FT_ULong* ptable_size;+++ if ( vertical )+ {+ tag = TTAG_vmtx;+ ptable_offset = &face->vert_metrics_offset;+ ptable_size = &face->vert_metrics_size;+ }+ else+ {+ tag = TTAG_hmtx;+ ptable_offset = &face->horz_metrics_offset;+ ptable_size = &face->horz_metrics_size;+ }++ error = face->goto_table( face, tag, stream, &table_size );+ if ( error )+ goto Fail;++ *ptable_size = table_size;+ *ptable_offset = FT_STREAM_POS();++ Fail:+ return error;+ }++#else /* !FT_CONFIG_OPTION_OLD_INTERNALS */++ FT_LOCAL_DEF( FT_Error )+ tt_face_load_hmtx( TT_Face face,+ FT_Stream stream,+ FT_Bool vertical )+ {+ FT_Error error;+ FT_Memory memory = stream->memory;++ FT_ULong table_len;+ FT_Long num_shorts, num_longs, num_shorts_checked;++ TT_LongMetrics* longs;+ TT_ShortMetrics** shorts;+ FT_Byte* p;+++ if ( vertical )+ {+ void* lm = &face->vertical.long_metrics;+ void** sm = &face->vertical.short_metrics;+++ error = face->goto_table( face, TTAG_vmtx, stream, &table_len );+ if ( error )+ goto Fail;++ num_longs = face->vertical.number_Of_VMetrics;+ if ( (FT_ULong)num_longs > table_len / 4 )+ num_longs = (FT_Long)( table_len / 4 );++ face->vertical.number_Of_VMetrics = 0;++ longs = (TT_LongMetrics*)lm;+ shorts = (TT_ShortMetrics**)sm;+ }+ else+ {+ void* lm = &face->horizontal.long_metrics;+ void** sm = &face->horizontal.short_metrics;+++ error = face->goto_table( face, TTAG_hmtx, stream, &table_len );+ if ( error )+ goto Fail;++ num_longs = face->horizontal.number_Of_HMetrics;+ if ( (FT_ULong)num_longs > table_len / 4 )+ num_longs = (FT_Long)( table_len / 4 );++ face->horizontal.number_Of_HMetrics = 0;++ longs = (TT_LongMetrics*)lm;+ shorts = (TT_ShortMetrics**)sm;+ }++ /* never trust derived values */++ num_shorts = face->max_profile.numGlyphs - num_longs;+ num_shorts_checked = ( table_len - num_longs * 4L ) / 2;++ if ( num_shorts < 0 )+ {+ FT_TRACE0(( "tt_face_load_hmtx:"+ " %cmtx has more metrics than glyphs.\n",+ vertical ? "v" : "h" ));++ /* Adobe simply ignores this problem. So we shall do the same. */+#if 0+ error = vertical ? SFNT_Err_Invalid_Vert_Metrics+ : SFNT_Err_Invalid_Horiz_Metrics;+ goto Exit;+#else+ num_shorts = 0;+#endif+ }++ if ( FT_QNEW_ARRAY( *longs, num_longs ) ||+ FT_QNEW_ARRAY( *shorts, num_shorts ) )+ goto Fail;++ if ( FT_FRAME_ENTER( table_len ) )+ goto Fail;++ p = stream->cursor;++ {+ TT_LongMetrics cur = *longs;+ TT_LongMetrics limit = cur + num_longs;+++ for ( ; cur < limit; cur++ )+ {+ cur->advance = FT_NEXT_USHORT( p );+ cur->bearing = FT_NEXT_SHORT( p );+ }+ }++ /* do we have an inconsistent number of metric values? */+ {+ TT_ShortMetrics* cur = *shorts;+ TT_ShortMetrics* limit = cur ++ FT_MIN( num_shorts, num_shorts_checked );+++ for ( ; cur < limit; cur++ )+ *cur = FT_NEXT_SHORT( p );++ /* We fill up the missing left side bearings with the */+ /* last valid value. Since this will occur for buggy CJK */+ /* fonts usually only, nothing serious will happen. */+ if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 )+ {+ FT_Short val = (*shorts)[num_shorts_checked - 1];+++ limit = *shorts + num_shorts;+ for ( ; cur < limit; cur++ )+ *cur = val;+ }+ }++ FT_FRAME_EXIT();++ if ( vertical )+ face->vertical.number_Of_VMetrics = (FT_UShort)num_longs;+ else+ face->horizontal.number_Of_HMetrics = (FT_UShort)num_longs;++ Fail:+ return error;+ }++#endif /* !FT_CONFIG_OPTION_OLD_INTERNALS */+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_face_load_hhea */+ /* */+ /* <Description> */+ /* Load the `hhea' or 'vhea' table into a face object. */+ /* */+ /* <Input> */+ /* face :: A handle to the target face object. */+ /* */+ /* stream :: The input stream. */+ /* */+ /* vertical :: A boolean flag. If set, load `vhea'. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ tt_face_load_hhea( TT_Face face,+ FT_Stream stream,+ FT_Bool vertical )+ {+ FT_Error error;+ TT_HoriHeader* header;++ const FT_Frame_Field metrics_header_fields[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE TT_HoriHeader++ FT_FRAME_START( 36 ),+ FT_FRAME_ULONG ( Version ),+ FT_FRAME_SHORT ( Ascender ),+ FT_FRAME_SHORT ( Descender ),+ FT_FRAME_SHORT ( Line_Gap ),+ FT_FRAME_USHORT( advance_Width_Max ),+ FT_FRAME_SHORT ( min_Left_Side_Bearing ),+ FT_FRAME_SHORT ( min_Right_Side_Bearing ),+ FT_FRAME_SHORT ( xMax_Extent ),+ FT_FRAME_SHORT ( caret_Slope_Rise ),+ FT_FRAME_SHORT ( caret_Slope_Run ),+ FT_FRAME_SHORT ( caret_Offset ),+ FT_FRAME_SHORT ( Reserved[0] ),+ FT_FRAME_SHORT ( Reserved[1] ),+ FT_FRAME_SHORT ( Reserved[2] ),+ FT_FRAME_SHORT ( Reserved[3] ),+ FT_FRAME_SHORT ( metric_Data_Format ),+ FT_FRAME_USHORT( number_Of_HMetrics ),+ FT_FRAME_END+ };+++ if ( vertical )+ {+ void *v = &face->vertical;+++ error = face->goto_table( face, TTAG_vhea, stream, 0 );+ if ( error )+ goto Fail;++ header = (TT_HoriHeader*)v;+ }+ else+ {+ error = face->goto_table( face, TTAG_hhea, stream, 0 );+ if ( error )+ goto Fail;++ header = &face->horizontal;+ }++ if ( FT_STREAM_READ_FIELDS( metrics_header_fields, header ) )+ goto Fail;++ FT_TRACE3(( "Ascender: %5d\n", header->Ascender ));+ FT_TRACE3(( "Descender: %5d\n", header->Descender ));+ FT_TRACE3(( "number_Of_Metrics: %5u\n", header->number_Of_HMetrics ));++ header->long_metrics = NULL;+ header->short_metrics = NULL;++ Fail:+ return error;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_face_get_metrics */+ /* */+ /* <Description> */+ /* Returns the horizontal or vertical metrics in font units for a */+ /* given glyph. The metrics are the left side bearing (resp. top */+ /* side bearing) and advance width (resp. advance height). */+ /* */+ /* <Input> */+ /* header :: A pointer to either the horizontal or vertical metrics */+ /* structure. */+ /* */+ /* idx :: The glyph index. */+ /* */+ /* <Output> */+ /* bearing :: The bearing, either left side or top side. */+ /* */+ /* advance :: The advance width resp. advance height. */+ /* */+#ifndef FT_CONFIG_OPTION_OLD_INTERNALS++ FT_LOCAL_DEF( FT_Error )+ tt_face_get_metrics( TT_Face face,+ FT_Bool vertical,+ FT_UInt gindex,+ FT_Short *abearing,+ FT_UShort *aadvance )+ {+ FT_Error error;+ FT_Stream stream = face->root.stream;+ TT_HoriHeader* header;+ FT_ULong table_pos, table_size, table_end;+ FT_UShort k;+++ if ( vertical )+ {+ void* v = &face->vertical;+++ header = (TT_HoriHeader*)v;+ table_pos = face->vert_metrics_offset;+ table_size = face->vert_metrics_size;+ }+ else+ {+ header = &face->horizontal;+ table_pos = face->horz_metrics_offset;+ table_size = face->horz_metrics_size;+ }++ table_end = table_pos + table_size;++ k = header->number_Of_HMetrics;++ if ( k > 0 )+ {+ if ( gindex < (FT_UInt)k )+ {+ table_pos += 4 * gindex;+ if ( table_pos + 4 > table_end )+ goto NoData;++ if ( FT_STREAM_SEEK( table_pos ) ||+ FT_READ_USHORT( *aadvance ) ||+ FT_READ_SHORT( *abearing ) )+ goto NoData;+ }+ else+ {+ table_pos += 4 * ( k - 1 );+ if ( table_pos + 4 > table_end )+ goto NoData;++ if ( FT_STREAM_SEEK( table_pos ) ||+ FT_READ_USHORT( *aadvance ) )+ goto NoData;++ table_pos += 4 + 2 * ( gindex - k );+ if ( table_pos + 2 > table_end )+ *abearing = 0;+ else+ {+ if ( !FT_STREAM_SEEK( table_pos ) )+ (void)FT_READ_SHORT( *abearing );+ }+ }+ }+ else+ {+ NoData:+ *abearing = 0;+ *aadvance = 0;+ }++ return SFNT_Err_Ok;+ }++#else /* !FT_CONFIG_OPTION_OLD_INTERNALS */++ FT_LOCAL_DEF( FT_Error )+ tt_face_get_metrics( TT_Face face,+ FT_Bool vertical,+ FT_UInt gindex,+ FT_Short* abearing,+ FT_UShort* aadvance )+ {+ void* v = &face->vertical;+ void* h = &face->horizontal;+ TT_HoriHeader* header = vertical ? (TT_HoriHeader*)v+ : (TT_HoriHeader*)h;+ TT_LongMetrics longs_m;+ FT_UShort k = header->number_Of_HMetrics;+++ if ( k == 0 ||+ !header->long_metrics ||+ gindex >= (FT_UInt)face->max_profile.numGlyphs )+ {+ *abearing = *aadvance = 0;+ return SFNT_Err_Ok;+ }++ if ( gindex < (FT_UInt)k )+ {+ longs_m = (TT_LongMetrics)header->long_metrics + gindex;+ *abearing = longs_m->bearing;+ *aadvance = longs_m->advance;+ }+ else+ {+ *abearing = ((TT_ShortMetrics*)header->short_metrics)[gindex - k];+ *aadvance = ((TT_LongMetrics)header->long_metrics)[k - 1].advance;+ }++ return SFNT_Err_Ok;+ }++#endif /* !FT_CONFIG_OPTION_OLD_INTERNALS */+++/* END */
+ src/sfnt/ttmtx.h view
@@ -0,0 +1,55 @@+/***************************************************************************/+/* */+/* ttmtx.h */+/* */+/* Load the metrics tables common to TTF and OTF fonts (specification). */+/* */+/* Copyright 2006 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 __TTMTX_H__+#define __TTMTX_H__+++#include <ft2build.h>+#include FT_INTERNAL_STREAM_H+#include FT_INTERNAL_TRUETYPE_TYPES_H+++FT_BEGIN_HEADER+++ FT_LOCAL( FT_Error )+ tt_face_load_hhea( TT_Face face,+ FT_Stream stream,+ FT_Bool vertical );+++ FT_LOCAL( FT_Error )+ tt_face_load_hmtx( TT_Face face,+ FT_Stream stream,+ FT_Bool vertical );+++ FT_LOCAL( FT_Error )+ tt_face_get_metrics( TT_Face face,+ FT_Bool vertical,+ FT_UInt gindex,+ FT_Short* abearing,+ FT_UShort* aadvance );++FT_END_HEADER++#endif /* __TTMTX_H__ */+++/* END */
+ src/sfnt/ttpost.c view
@@ -0,0 +1,563 @@+/***************************************************************************/+/* */+/* ttpost.c */+/* */+/* Postcript name table processing for TrueType and OpenType fonts */+/* (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2006, 2007, 2008, 2009, 2010 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/++ /*************************************************************************/+ /* */+ /* The post table is not completely loaded by the core engine. This */+ /* file loads the missing PS glyph names and implements an API to access */+ /* them. */+ /* */+ /*************************************************************************/+++#include <ft2build.h>+#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_STREAM_H+#include FT_TRUETYPE_TAGS_H+#include "ttpost.h"++#include "sferrors.h"+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_ttpost+++ /* If this configuration macro is defined, we rely on the `PSNames' */+ /* module to grab the glyph names. */++#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES+++#include FT_SERVICE_POSTSCRIPT_CMAPS_H++#define MAC_NAME( x ) ( (FT_String*)psnames->macintosh_name( x ) )+++#else /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */+++ /* Otherwise, we ignore the `PSNames' module, and provide our own */+ /* table of Mac names. Thus, it is possible to build a version of */+ /* FreeType without the Type 1 driver & PSNames module. */++#define MAC_NAME( x ) ( (FT_String*)tt_post_default_names[x] )++ /* the 258 default Mac PS glyph names */++ static const FT_String* const tt_post_default_names[258] =+ {+ /* 0 */+ ".notdef", ".null", "CR", "space", "exclam",+ "quotedbl", "numbersign", "dollar", "percent", "ampersand",+ /* 10 */+ "quotesingle", "parenleft", "parenright", "asterisk", "plus",+ "comma", "hyphen", "period", "slash", "zero",+ /* 20 */+ "one", "two", "three", "four", "five",+ "six", "seven", "eight", "nine", "colon",+ /* 30 */+ "semicolon", "less", "equal", "greater", "question",+ "at", "A", "B", "C", "D",+ /* 40 */+ "E", "F", "G", "H", "I",+ "J", "K", "L", "M", "N",+ /* 50 */+ "O", "P", "Q", "R", "S",+ "T", "U", "V", "W", "X",+ /* 60 */+ "Y", "Z", "bracketleft", "backslash", "bracketright",+ "asciicircum", "underscore", "grave", "a", "b",+ /* 70 */+ "c", "d", "e", "f", "g",+ "h", "i", "j", "k", "l",+ /* 80 */+ "m", "n", "o", "p", "q",+ "r", "s", "t", "u", "v",+ /* 90 */+ "w", "x", "y", "z", "braceleft",+ "bar", "braceright", "asciitilde", "Adieresis", "Aring",+ /* 100 */+ "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",+ "aacute", "agrave", "acircumflex", "adieresis", "atilde",+ /* 110 */+ "aring", "ccedilla", "eacute", "egrave", "ecircumflex",+ "edieresis", "iacute", "igrave", "icircumflex", "idieresis",+ /* 120 */+ "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",+ "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",+ /* 130 */+ "dagger", "degree", "cent", "sterling", "section",+ "bullet", "paragraph", "germandbls", "registered", "copyright",+ /* 140 */+ "trademark", "acute", "dieresis", "notequal", "AE",+ "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",+ /* 150 */+ "yen", "mu", "partialdiff", "summation", "product",+ "pi", "integral", "ordfeminine", "ordmasculine", "Omega",+ /* 160 */+ "ae", "oslash", "questiondown", "exclamdown", "logicalnot",+ "radical", "florin", "approxequal", "Delta", "guillemotleft",+ /* 170 */+ "guillemotright", "ellipsis", "nbspace", "Agrave", "Atilde",+ "Otilde", "OE", "oe", "endash", "emdash",+ /* 180 */+ "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",+ "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",+ /* 190 */+ "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",+ "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",+ /* 200 */+ "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",+ "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",+ /* 210 */+ "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",+ "dotlessi", "circumflex", "tilde", "macron", "breve",+ /* 220 */+ "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",+ "caron", "Lslash", "lslash", "Scaron", "scaron",+ /* 230 */+ "Zcaron", "zcaron", "brokenbar", "Eth", "eth",+ "Yacute", "yacute", "Thorn", "thorn", "minus",+ /* 240 */+ "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",+ "onequarter", "threequarters", "franc", "Gbreve", "gbreve",+ /* 250 */+ "Idot", "Scedilla", "scedilla", "Cacute", "cacute",+ "Ccaron", "ccaron", "dmacron",+ };+++#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */+++ static FT_Error+ load_format_20( TT_Face face,+ FT_Stream stream,+ FT_Long post_limit )+ {+ FT_Memory memory = stream->memory;+ FT_Error error;++ FT_Int num_glyphs;+ FT_UShort num_names;++ FT_UShort* glyph_indices = 0;+ FT_Char** name_strings = 0;+++ if ( FT_READ_USHORT( num_glyphs ) )+ goto Exit;++ /* UNDOCUMENTED! The number of glyphs in this table can be smaller */+ /* than the value in the maxp table (cf. cyberbit.ttf). */++ /* There already exist fonts which have more than 32768 glyph names */+ /* in this table, so the test for this threshold has been dropped. */++ if ( num_glyphs > face->max_profile.numGlyphs )+ {+ error = SFNT_Err_Invalid_File_Format;+ goto Exit;+ }++ /* load the indices */+ {+ FT_Int n;+++ if ( FT_NEW_ARRAY ( glyph_indices, num_glyphs ) ||+ FT_FRAME_ENTER( num_glyphs * 2L ) )+ goto Fail;++ for ( n = 0; n < num_glyphs; n++ )+ glyph_indices[n] = FT_GET_USHORT();++ FT_FRAME_EXIT();+ }++ /* compute number of names stored in table */+ {+ FT_Int n;+++ num_names = 0;++ for ( n = 0; n < num_glyphs; n++ )+ {+ FT_Int idx;+++ idx = glyph_indices[n];+ if ( idx >= 258 )+ {+ idx -= 257;+ if ( idx > num_names )+ num_names = (FT_UShort)idx;+ }+ }+ }++ /* now load the name strings */+ {+ FT_UShort n;+++ if ( FT_NEW_ARRAY( name_strings, num_names ) )+ goto Fail;++ for ( n = 0; n < num_names; n++ )+ {+ FT_UInt len;+++ if ( FT_STREAM_POS() >= post_limit )+ break;+ else+ {+ FT_TRACE6(( "load_format_20: %d byte left in post table\n",+ post_limit - FT_STREAM_POS() ));++ if ( FT_READ_BYTE( len ) )+ goto Fail1;+ }++ if ( (FT_Int)len > post_limit ||+ FT_STREAM_POS() > post_limit - (FT_Int)len )+ {+ FT_ERROR(( "load_format_20:"+ " exceeding string length (%d),"+ " truncating at end of post table (%d byte left)\n",+ len, post_limit - FT_STREAM_POS() ));+ len = FT_MAX( 0, post_limit - FT_STREAM_POS() );+ }++ if ( FT_NEW_ARRAY( name_strings[n], len + 1 ) ||+ FT_STREAM_READ( name_strings[n], len ) )+ goto Fail1;++ name_strings[n][len] = '\0';+ }++ if ( n < num_names )+ {+ FT_ERROR(( "load_format_20:"+ " all entries in post table are already parsed,"+ " using NULL names for gid %d - %d\n",+ n, num_names - 1 ));+ for ( ; n < num_names; n++ )+ if ( FT_NEW_ARRAY( name_strings[n], 1 ) )+ goto Fail1;+ else+ name_strings[n][0] = '\0';+ }+ }++ /* all right, set table fields and exit successfully */+ {+ TT_Post_20 table = &face->postscript_names.names.format_20;+++ table->num_glyphs = (FT_UShort)num_glyphs;+ table->num_names = (FT_UShort)num_names;+ table->glyph_indices = glyph_indices;+ table->glyph_names = name_strings;+ }+ return SFNT_Err_Ok;++ Fail1:+ {+ FT_UShort n;+++ for ( n = 0; n < num_names; n++ )+ FT_FREE( name_strings[n] );+ }++ Fail:+ FT_FREE( name_strings );+ FT_FREE( glyph_indices );++ Exit:+ return error;+ }+++ static FT_Error+ load_format_25( TT_Face face,+ FT_Stream stream,+ FT_Long post_limit )+ {+ FT_Memory memory = stream->memory;+ FT_Error error;++ FT_Int num_glyphs;+ FT_Char* offset_table = 0;++ FT_UNUSED( post_limit );+++ /* UNDOCUMENTED! This value appears only in the Apple TT specs. */+ if ( FT_READ_USHORT( num_glyphs ) )+ goto Exit;++ /* check the number of glyphs */+ if ( num_glyphs > face->max_profile.numGlyphs || num_glyphs > 258 )+ {+ error = SFNT_Err_Invalid_File_Format;+ goto Exit;+ }++ if ( FT_NEW_ARRAY( offset_table, num_glyphs ) ||+ FT_STREAM_READ( offset_table, num_glyphs ) )+ goto Fail;++ /* now check the offset table */+ {+ FT_Int n;+++ for ( n = 0; n < num_glyphs; n++ )+ {+ FT_Long idx = (FT_Long)n + offset_table[n];+++ if ( idx < 0 || idx > num_glyphs )+ {+ error = SFNT_Err_Invalid_File_Format;+ goto Fail;+ }+ }+ }++ /* OK, set table fields and exit successfully */+ {+ TT_Post_25 table = &face->postscript_names.names.format_25;+++ table->num_glyphs = (FT_UShort)num_glyphs;+ table->offsets = offset_table;+ }++ return SFNT_Err_Ok;++ Fail:+ FT_FREE( offset_table );++ Exit:+ return error;+ }+++ static FT_Error+ load_post_names( TT_Face face )+ {+ FT_Stream stream;+ FT_Error error;+ FT_Fixed format;+ FT_ULong post_len;+ FT_Long post_limit;+++ /* get a stream for the face's resource */+ stream = face->root.stream;++ /* seek to the beginning of the PS names table */+ error = face->goto_table( face, TTAG_post, stream, &post_len );+ if ( error )+ goto Exit;++ post_limit = FT_STREAM_POS() + post_len;++ format = face->postscript.FormatType;++ /* go to beginning of subtable */+ if ( FT_STREAM_SKIP( 32 ) )+ goto Exit;++ /* now read postscript table */+ if ( format == 0x00020000L )+ error = load_format_20( face, stream, post_limit );+ else if ( format == 0x00028000L )+ error = load_format_25( face, stream, post_limit );+ else+ error = SFNT_Err_Invalid_File_Format;++ face->postscript_names.loaded = 1;++ Exit:+ return error;+ }+++ FT_LOCAL_DEF( void )+ tt_face_free_ps_names( TT_Face face )+ {+ FT_Memory memory = face->root.memory;+ TT_Post_Names names = &face->postscript_names;+ FT_Fixed format;+++ if ( names->loaded )+ {+ format = face->postscript.FormatType;++ if ( format == 0x00020000L )+ {+ TT_Post_20 table = &names->names.format_20;+ FT_UShort n;+++ FT_FREE( table->glyph_indices );+ table->num_glyphs = 0;++ for ( n = 0; n < table->num_names; n++ )+ FT_FREE( table->glyph_names[n] );++ FT_FREE( table->glyph_names );+ table->num_names = 0;+ }+ else if ( format == 0x00028000L )+ {+ TT_Post_25 table = &names->names.format_25;+++ FT_FREE( table->offsets );+ table->num_glyphs = 0;+ }+ }+ names->loaded = 0;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_face_get_ps_name */+ /* */+ /* <Description> */+ /* Get the PostScript glyph name of a glyph. */+ /* */+ /* <Input> */+ /* face :: A handle to the parent face. */+ /* */+ /* idx :: The glyph index. */+ /* */+ /* <InOut> */+ /* PSname :: The address of a string pointer. Will be NULL in case */+ /* of error, otherwise it is a pointer to the glyph name. */+ /* */+ /* You must not modify the returned string! */+ /* */+ /* <Output> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ tt_face_get_ps_name( TT_Face face,+ FT_UInt idx,+ FT_String** PSname )+ {+ FT_Error error;+ TT_Post_Names names;+ FT_Fixed format;++#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES+ FT_Service_PsCMaps psnames;+#endif+++ if ( !face )+ return SFNT_Err_Invalid_Face_Handle;++ if ( idx >= (FT_UInt)face->max_profile.numGlyphs )+ return SFNT_Err_Invalid_Glyph_Index;++#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES+ psnames = (FT_Service_PsCMaps)face->psnames;+ if ( !psnames )+ return SFNT_Err_Unimplemented_Feature;+#endif++ names = &face->postscript_names;++ /* `.notdef' by default */+ *PSname = MAC_NAME( 0 );++ format = face->postscript.FormatType;++ if ( format == 0x00010000L )+ {+ if ( idx < 258 ) /* paranoid checking */+ *PSname = MAC_NAME( idx );+ }+ else if ( format == 0x00020000L )+ {+ TT_Post_20 table = &names->names.format_20;+++ if ( !names->loaded )+ {+ error = load_post_names( face );+ if ( error )+ goto End;+ }++ if ( idx < (FT_UInt)table->num_glyphs )+ {+ FT_UShort name_index = table->glyph_indices[idx];+++ if ( name_index < 258 )+ *PSname = MAC_NAME( name_index );+ else+ *PSname = (FT_String*)table->glyph_names[name_index - 258];+ }+ }+ else if ( format == 0x00028000L )+ {+ TT_Post_25 table = &names->names.format_25;+++ if ( !names->loaded )+ {+ error = load_post_names( face );+ if ( error )+ goto End;+ }++ if ( idx < (FT_UInt)table->num_glyphs ) /* paranoid checking */+ {+ idx += table->offsets[idx];+ *PSname = MAC_NAME( idx );+ }+ }++ /* nothing to do for format == 0x00030000L */++ End:+ return SFNT_Err_Ok;+ }+++/* END */
+ src/sfnt/ttpost.h view
@@ -0,0 +1,46 @@+/***************************************************************************/+/* */+/* ttpost.h */+/* */+/* Postcript name table processing for TrueType and OpenType fonts */+/* (specification). */+/* */+/* Copyright 1996-2001, 2002 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 __TTPOST_H__+#define __TTPOST_H__+++#include <ft2build.h>+#include FT_CONFIG_CONFIG_H+#include FT_INTERNAL_TRUETYPE_TYPES_H+++FT_BEGIN_HEADER+++ FT_LOCAL( FT_Error )+ tt_face_get_ps_name( TT_Face face,+ FT_UInt idx,+ FT_String** PSname );++ FT_LOCAL( void )+ tt_face_free_ps_names( TT_Face face );+++FT_END_HEADER++#endif /* __TTPOST_H__ */+++/* END */
+ src/sfnt/ttsbit.c view
@@ -0,0 +1,1508 @@+/***************************************************************************/+/* */+/* ttsbit.c */+/* */+/* TrueType and OpenType embedded bitmap support (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */+/* 2010 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_STREAM_H+#include FT_TRUETYPE_TAGS_H++ /*+ * Alas, the memory-optimized sbit loader can't be used when implementing+ * the `old internals' hack+ */+#ifndef FT_CONFIG_OPTION_OLD_INTERNALS++#include "ttsbit0.c"++#else /* FT_CONFIG_OPTION_OLD_INTERNALS */++#include <ft2build.h>+#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_STREAM_H+#include FT_TRUETYPE_TAGS_H+#include "ttsbit.h"++#include "sferrors.h"+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_ttsbit+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* blit_sbit */+ /* */+ /* <Description> */+ /* Blits a bitmap from an input stream into a given target. Supports */+ /* x and y offsets as well as byte padded lines. */+ /* */+ /* <Input> */+ /* target :: The target bitmap/pixmap. */+ /* */+ /* source :: The input packed bitmap data. */+ /* */+ /* line_bits :: The number of bits per line. */+ /* */+ /* byte_padded :: A flag which is true if lines are byte-padded. */+ /* */+ /* x_offset :: The horizontal offset. */+ /* */+ /* y_offset :: The vertical offset. */+ /* */+ /* <Note> */+ /* IMPORTANT: The x and y offsets are relative to the top corner of */+ /* the target bitmap (unlike the normal TrueType */+ /* convention). A positive y offset indicates a downwards */+ /* direction! */+ /* */+ static void+ blit_sbit( FT_Bitmap* target,+ FT_Byte* source,+ FT_Int line_bits,+ FT_Bool byte_padded,+ FT_Int x_offset,+ FT_Int y_offset,+ FT_Int source_height )+ {+ FT_Byte* line_buff;+ FT_Int line_incr;+ FT_Int height;++ FT_UShort acc;+ FT_UInt loaded;+++ /* first of all, compute starting write position */+ line_incr = target->pitch;+ line_buff = target->buffer;++ if ( line_incr < 0 )+ line_buff -= line_incr * ( target->rows - 1 );++ line_buff += ( x_offset >> 3 ) + y_offset * line_incr;++ /***********************************************************************/+ /* */+ /* We use the extra-classic `accumulator' trick to extract the bits */+ /* from the source byte stream. */+ /* */+ /* Namely, the variable `acc' is a 16-bit accumulator containing the */+ /* last `loaded' bits from the input stream. The bits are shifted to */+ /* the upmost position in `acc'. */+ /* */+ /***********************************************************************/++ acc = 0; /* clear accumulator */+ loaded = 0; /* no bits were loaded */++ for ( height = source_height; height > 0; height-- )+ {+ FT_Byte* cur = line_buff; /* current write cursor */+ FT_Int count = line_bits; /* # of bits to extract per line */+ FT_Byte shift = (FT_Byte)( x_offset & 7 ); /* current write shift */+ FT_Byte space = (FT_Byte)( 8 - shift );+++ /* first of all, read individual source bytes */+ if ( count >= 8 )+ {+ count -= 8;+ {+ do+ {+ FT_Byte val;+++ /* ensure that there are at least 8 bits in the accumulator */+ if ( loaded < 8 )+ {+ acc |= (FT_UShort)((FT_UShort)*source++ << ( 8 - loaded ));+ loaded += 8;+ }++ /* now write one byte */+ val = (FT_Byte)( acc >> 8 );+ if ( shift )+ {+ cur[0] |= (FT_Byte)( val >> shift );+ cur[1] |= (FT_Byte)( val << space );+ }+ else+ cur[0] |= val;++ cur++;+ acc <<= 8; /* remove bits from accumulator */+ loaded -= 8;+ count -= 8;++ } while ( count >= 0 );+ }++ /* restore `count' to correct value */+ count += 8;+ }++ /* now write remaining bits (count < 8) */+ if ( count > 0 )+ {+ FT_Byte val;+++ /* ensure that there are at least `count' bits in the accumulator */+ if ( (FT_Int)loaded < count )+ {+ acc |= (FT_UShort)((FT_UShort)*source++ << ( 8 - loaded ));+ loaded += 8;+ }++ /* now write remaining bits */+ val = (FT_Byte)( ( (FT_Byte)( acc >> 8 ) ) & ~( 0xFF >> count ) );+ cur[0] |= (FT_Byte)( val >> shift );++ if ( count > space )+ cur[1] |= (FT_Byte)( val << space );++ acc <<= count;+ loaded -= count;+ }++ /* now, skip to next line */+ if ( byte_padded )+ {+ acc = 0;+ loaded = 0; /* clear accumulator on byte-padded lines */+ }++ line_buff += line_incr;+ }+ }+++ static const FT_Frame_Field sbit_metrics_fields[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE TT_SBit_MetricsRec++ FT_FRAME_START( 8 ),+ FT_FRAME_BYTE( height ),+ FT_FRAME_BYTE( width ),++ FT_FRAME_CHAR( horiBearingX ),+ FT_FRAME_CHAR( horiBearingY ),+ FT_FRAME_BYTE( horiAdvance ),++ FT_FRAME_CHAR( vertBearingX ),+ FT_FRAME_CHAR( vertBearingY ),+ FT_FRAME_BYTE( vertAdvance ),+ FT_FRAME_END+ };+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Load_SBit_Const_Metrics */+ /* */+ /* <Description> */+ /* Loads the metrics for `EBLC' index tables format 2 and 5. */+ /* */+ /* <Input> */+ /* range :: The target range. */+ /* */+ /* stream :: The input stream. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ static FT_Error+ Load_SBit_Const_Metrics( TT_SBit_Range range,+ FT_Stream stream )+ {+ FT_Error error;+++ if ( FT_READ_ULONG( range->image_size ) )+ return error;++ return FT_STREAM_READ_FIELDS( sbit_metrics_fields, &range->metrics );+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Load_SBit_Range_Codes */+ /* */+ /* <Description> */+ /* Loads the range codes for `EBLC' index tables format 4 and 5. */+ /* */+ /* <Input> */+ /* range :: The target range. */+ /* */+ /* stream :: The input stream. */+ /* */+ /* load_offsets :: A flag whether to load the glyph offset table. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ static FT_Error+ Load_SBit_Range_Codes( TT_SBit_Range range,+ FT_Stream stream,+ FT_Bool load_offsets )+ {+ FT_Error error;+ FT_ULong count, n, size;+ FT_Memory memory = stream->memory;+++ if ( FT_READ_ULONG( count ) )+ goto Exit;++ range->num_glyphs = count;++ /* Allocate glyph offsets table if needed */+ if ( load_offsets )+ {+ if ( FT_NEW_ARRAY( range->glyph_offsets, count ) )+ goto Exit;++ size = count * 4L;+ }+ else+ size = count * 2L;++ /* Allocate glyph codes table and access frame */+ if ( FT_NEW_ARRAY ( range->glyph_codes, count ) ||+ FT_FRAME_ENTER( size ) )+ goto Exit;++ for ( n = 0; n < count; n++ )+ {+ range->glyph_codes[n] = FT_GET_USHORT();++ if ( load_offsets )+ range->glyph_offsets[n] = (FT_ULong)range->image_offset ++ FT_GET_USHORT();+ }++ FT_FRAME_EXIT();++ Exit:+ return error;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Load_SBit_Range */+ /* */+ /* <Description> */+ /* Loads a given `EBLC' index/range table. */+ /* */+ /* <Input> */+ /* range :: The target range. */+ /* */+ /* stream :: The input stream. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ static FT_Error+ Load_SBit_Range( TT_SBit_Range range,+ FT_Stream stream )+ {+ FT_Error error;+ FT_Memory memory = stream->memory;+++ switch( range->index_format )+ {+ case 1: /* variable metrics with 4-byte offsets */+ case 3: /* variable metrics with 2-byte offsets */+ {+ FT_ULong num_glyphs, n;+ FT_Int size_elem;+ FT_Bool large = FT_BOOL( range->index_format == 1 );++++ if ( range->last_glyph < range->first_glyph )+ {+ error = SFNT_Err_Invalid_File_Format;+ goto Exit;+ }++ num_glyphs = range->last_glyph - range->first_glyph + 1L;+ range->num_glyphs = num_glyphs;+ num_glyphs++; /* XXX: BEWARE - see spec */++ size_elem = large ? 4 : 2;++ if ( FT_NEW_ARRAY( range->glyph_offsets, num_glyphs ) ||+ FT_FRAME_ENTER( num_glyphs * size_elem ) )+ goto Exit;++ for ( n = 0; n < num_glyphs; n++ )+ range->glyph_offsets[n] = (FT_ULong)( range->image_offset ++ ( large ? FT_GET_ULONG()+ : FT_GET_USHORT() ) );+ FT_FRAME_EXIT();+ }+ break;++ case 2: /* all glyphs have identical metrics */+ error = Load_SBit_Const_Metrics( range, stream );+ break;++ case 4:+ error = Load_SBit_Range_Codes( range, stream, 1 );+ break;++ case 5:+ error = Load_SBit_Const_Metrics( range, stream );+ if ( !error )+ error = Load_SBit_Range_Codes( range, stream, 0 );+ break;++ default:+ error = SFNT_Err_Invalid_File_Format;+ }++ Exit:+ return error;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_face_load_eblc */+ /* */+ /* <Description> */+ /* Loads the table of embedded bitmap sizes for this face. */+ /* */+ /* <Input> */+ /* face :: The target face object. */+ /* */+ /* stream :: The input stream. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ tt_face_load_eblc( TT_Face face,+ FT_Stream stream )+ {+ FT_Error error = SFNT_Err_Ok;+ FT_Memory memory = stream->memory;+ FT_Fixed version;+ FT_ULong num_strikes;+ FT_ULong table_base;++ static const FT_Frame_Field sbit_line_metrics_fields[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE TT_SBit_LineMetricsRec++ /* no FT_FRAME_START */+ FT_FRAME_CHAR( ascender ),+ FT_FRAME_CHAR( descender ),+ FT_FRAME_BYTE( max_width ),++ FT_FRAME_CHAR( caret_slope_numerator ),+ FT_FRAME_CHAR( caret_slope_denominator ),+ FT_FRAME_CHAR( caret_offset ),++ FT_FRAME_CHAR( min_origin_SB ),+ FT_FRAME_CHAR( min_advance_SB ),+ FT_FRAME_CHAR( max_before_BL ),+ FT_FRAME_CHAR( min_after_BL ),+ FT_FRAME_CHAR( pads[0] ),+ FT_FRAME_CHAR( pads[1] ),+ FT_FRAME_END+ };++ static const FT_Frame_Field strike_start_fields[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE TT_SBit_StrikeRec++ /* no FT_FRAME_START */+ FT_FRAME_ULONG( ranges_offset ),+ FT_FRAME_SKIP_LONG,+ FT_FRAME_ULONG( num_ranges ),+ FT_FRAME_ULONG( color_ref ),+ FT_FRAME_END+ };++ static const FT_Frame_Field strike_end_fields[] =+ {+ /* no FT_FRAME_START */+ FT_FRAME_USHORT( start_glyph ),+ FT_FRAME_USHORT( end_glyph ),+ FT_FRAME_BYTE ( x_ppem ),+ FT_FRAME_BYTE ( y_ppem ),+ FT_FRAME_BYTE ( bit_depth ),+ FT_FRAME_CHAR ( flags ),+ FT_FRAME_END+ };+++ face->num_sbit_strikes = 0;++ /* this table is optional */+ error = face->goto_table( face, TTAG_EBLC, stream, 0 );+ if ( error )+ error = face->goto_table( face, TTAG_bloc, stream, 0 );+ if ( error )+ goto Exit;++ table_base = FT_STREAM_POS();+ if ( FT_FRAME_ENTER( 8L ) )+ goto Exit;++ version = FT_GET_LONG();+ num_strikes = FT_GET_ULONG();++ FT_FRAME_EXIT();++ /* check version number and strike count */+ if ( version != 0x00020000L ||+ num_strikes >= 0x10000L )+ {+ FT_ERROR(( "tt_face_load_sbit_strikes: invalid table version\n" ));+ error = SFNT_Err_Invalid_File_Format;++ goto Exit;+ }++ /* allocate the strikes table */+ if ( FT_NEW_ARRAY( face->sbit_strikes, num_strikes ) )+ goto Exit;++ face->num_sbit_strikes = num_strikes;++ /* now read each strike table separately */+ {+ TT_SBit_Strike strike = face->sbit_strikes;+ FT_ULong count = num_strikes;+++ if ( FT_FRAME_ENTER( 48L * num_strikes ) )+ goto Exit;++ while ( count > 0 )+ {+ if ( FT_STREAM_READ_FIELDS( strike_start_fields, strike ) ||+ FT_STREAM_READ_FIELDS( sbit_line_metrics_fields, &strike->hori ) ||+ FT_STREAM_READ_FIELDS( sbit_line_metrics_fields, &strike->vert ) ||+ FT_STREAM_READ_FIELDS( strike_end_fields, strike ) )+ break;++ count--;+ strike++;+ }++ FT_FRAME_EXIT();+ }++ /* allocate the index ranges for each strike table */+ {+ TT_SBit_Strike strike = face->sbit_strikes;+ FT_ULong count = num_strikes;+++ while ( count > 0 )+ {+ TT_SBit_Range range;+ FT_ULong count2 = strike->num_ranges;+++ /* read each range */+ if ( FT_STREAM_SEEK( table_base + strike->ranges_offset ) ||+ FT_FRAME_ENTER( strike->num_ranges * 8L ) )+ goto Exit;++ if ( FT_NEW_ARRAY( strike->sbit_ranges, strike->num_ranges ) )+ goto Exit;++ range = strike->sbit_ranges;+ while ( count2 > 0 )+ {+ range->first_glyph = FT_GET_USHORT();+ range->last_glyph = FT_GET_USHORT();+ range->table_offset = table_base + strike->ranges_offset ++ FT_GET_ULONG();+ count2--;+ range++;+ }++ FT_FRAME_EXIT();++ /* Now, read each index table */+ count2 = strike->num_ranges;+ range = strike->sbit_ranges;+ while ( count2 > 0 )+ {+ /* Read the header */+ if ( FT_STREAM_SEEK( range->table_offset ) ||+ FT_FRAME_ENTER( 8L ) )+ goto Exit;++ range->index_format = FT_GET_USHORT();+ range->image_format = FT_GET_USHORT();+ range->image_offset = FT_GET_ULONG();++ FT_FRAME_EXIT();++ error = Load_SBit_Range( range, stream );+ if ( error )+ goto Exit;++ count2--;+ range++;+ }++ count--;+ strike++;+ }+ }++ Exit:+ return error;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_face_free_eblc */+ /* */+ /* <Description> */+ /* Releases the embedded bitmap tables. */+ /* */+ /* <Input> */+ /* face :: The target face object. */+ /* */+ FT_LOCAL_DEF( void )+ tt_face_free_eblc( TT_Face face )+ {+ FT_Memory memory = face->root.memory;+ TT_SBit_Strike strike = face->sbit_strikes;+ TT_SBit_Strike strike_limit = strike + face->num_sbit_strikes;+++ if ( strike )+ {+ for ( ; strike < strike_limit; strike++ )+ {+ TT_SBit_Range range = strike->sbit_ranges;+ TT_SBit_Range range_limit = range + strike->num_ranges;+++ if ( range )+ {+ for ( ; range < range_limit; range++ )+ {+ /* release the glyph offsets and codes tables */+ /* where appropriate */+ FT_FREE( range->glyph_offsets );+ FT_FREE( range->glyph_codes );+ }+ }+ FT_FREE( strike->sbit_ranges );+ strike->num_ranges = 0;+ }+ FT_FREE( face->sbit_strikes );+ }+ face->num_sbit_strikes = 0;+ }+++ FT_LOCAL_DEF( FT_Error )+ tt_face_set_sbit_strike( TT_Face face,+ FT_Size_Request req,+ FT_ULong* astrike_index )+ {+ return FT_Match_Size( (FT_Face)face, req, 0, astrike_index );+ }+++ FT_LOCAL_DEF( FT_Error )+ tt_face_load_strike_metrics( TT_Face face,+ FT_ULong strike_index,+ FT_Size_Metrics* metrics )+ {+ TT_SBit_Strike strike;+++ if ( strike_index >= face->num_sbit_strikes )+ return SFNT_Err_Invalid_Argument;++ strike = face->sbit_strikes + strike_index;++ metrics->x_ppem = strike->x_ppem;+ metrics->y_ppem = strike->y_ppem;++ metrics->ascender = strike->hori.ascender << 6;+ metrics->descender = strike->hori.descender << 6;++ /* XXX: Is this correct? */+ metrics->max_advance = ( strike->hori.min_origin_SB ++ strike->hori.max_width ++ strike->hori.min_advance_SB ) << 6;++ metrics->height = metrics->ascender - metrics->descender;++ return SFNT_Err_Ok;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* find_sbit_range */+ /* */+ /* <Description> */+ /* Scans a given strike's ranges and return, for a given glyph */+ /* index, the corresponding sbit range, and `EBDT' offset. */+ /* */+ /* <Input> */+ /* glyph_index :: The glyph index. */+ /* */+ /* strike :: The source/current sbit strike. */+ /* */+ /* <Output> */+ /* arange :: The sbit range containing the glyph index. */+ /* */+ /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means the glyph index was found. */+ /* */+ static FT_Error+ find_sbit_range( FT_UInt glyph_index,+ TT_SBit_Strike strike,+ TT_SBit_Range *arange,+ FT_ULong *aglyph_offset )+ {+ TT_SBit_RangeRec *range, *range_limit;+++ /* check whether the glyph index is within this strike's */+ /* glyph range */+ if ( glyph_index < (FT_UInt)strike->start_glyph ||+ glyph_index > (FT_UInt)strike->end_glyph )+ goto Fail;++ /* scan all ranges in strike */+ range = strike->sbit_ranges;+ range_limit = range + strike->num_ranges;+ if ( !range )+ goto Fail;++ for ( ; range < range_limit; range++ )+ {+ if ( glyph_index >= (FT_UInt)range->first_glyph &&+ glyph_index <= (FT_UInt)range->last_glyph )+ {+ FT_UShort delta = (FT_UShort)( glyph_index - range->first_glyph );+++ switch ( range->index_format )+ {+ case 1:+ case 3:+ *aglyph_offset = range->glyph_offsets[delta];+ break;++ case 2:+ *aglyph_offset = range->image_offset ++ range->image_size * delta;+ break;++ case 4:+ case 5:+ {+ FT_ULong n;+++ for ( n = 0; n < range->num_glyphs; n++ )+ {+ if ( (FT_UInt)range->glyph_codes[n] == glyph_index )+ {+ if ( range->index_format == 4 )+ *aglyph_offset = range->glyph_offsets[n];+ else+ *aglyph_offset = range->image_offset ++ n * range->image_size;+ goto Found;+ }+ }+ }++ /* fall-through */+ default:+ goto Fail;+ }++ Found:+ /* return successfully! */+ *arange = range;+ return SFNT_Err_Ok;+ }+ }++ Fail:+ *arange = 0;+ *aglyph_offset = 0;++ return SFNT_Err_Invalid_Argument;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_find_sbit_image */+ /* */+ /* <Description> */+ /* Checks whether an embedded bitmap (an `sbit') exists for a given */+ /* glyph, at a given strike. */+ /* */+ /* <Input> */+ /* face :: The target face object. */+ /* */+ /* glyph_index :: The glyph index. */+ /* */+ /* strike_index :: The current strike index. */+ /* */+ /* <Output> */+ /* arange :: The SBit range containing the glyph index. */+ /* */+ /* astrike :: The SBit strike containing the glyph index. */+ /* */+ /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. Returns */+ /* SFNT_Err_Invalid_Argument if no sbit exists for the requested */+ /* glyph. */+ /* */+ FT_LOCAL( FT_Error )+ tt_find_sbit_image( TT_Face face,+ FT_UInt glyph_index,+ FT_ULong strike_index,+ TT_SBit_Range *arange,+ TT_SBit_Strike *astrike,+ FT_ULong *aglyph_offset )+ {+ FT_Error error;+ TT_SBit_Strike strike;+++ if ( !face->sbit_strikes ||+ ( face->num_sbit_strikes <= strike_index ) )+ goto Fail;++ strike = &face->sbit_strikes[strike_index];++ error = find_sbit_range( glyph_index, strike,+ arange, aglyph_offset );+ if ( error )+ goto Fail;++ *astrike = strike;++ return SFNT_Err_Ok;++ Fail:+ /* no embedded bitmap for this glyph in face */+ *arange = 0;+ *astrike = 0;+ *aglyph_offset = 0;++ return SFNT_Err_Invalid_Argument;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_load_sbit_metrics */+ /* */+ /* <Description> */+ /* Gets the big metrics for a given SBit. */+ /* */+ /* <Input> */+ /* stream :: The input stream. */+ /* */+ /* range :: The SBit range containing the glyph. */+ /* */+ /* <Output> */+ /* big_metrics :: A big SBit metrics structure for the glyph. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ /* <Note> */+ /* The stream cursor must be positioned at the glyph's offset within */+ /* the `EBDT' table before the call. */+ /* */+ /* If the image format uses variable metrics, the stream cursor is */+ /* positioned just after the metrics header in the `EBDT' table on */+ /* function exit. */+ /* */+ FT_LOCAL( FT_Error )+ tt_load_sbit_metrics( FT_Stream stream,+ TT_SBit_Range range,+ TT_SBit_Metrics metrics )+ {+ FT_Error error = SFNT_Err_Ok;+++ switch ( range->image_format )+ {+ case 1:+ case 2:+ case 8:+ /* variable small metrics */+ {+ TT_SBit_SmallMetricsRec smetrics;++ static const FT_Frame_Field sbit_small_metrics_fields[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE TT_SBit_SmallMetricsRec++ FT_FRAME_START( 5 ),+ FT_FRAME_BYTE( height ),+ FT_FRAME_BYTE( width ),+ FT_FRAME_CHAR( bearingX ),+ FT_FRAME_CHAR( bearingY ),+ FT_FRAME_BYTE( advance ),+ FT_FRAME_END+ };+++ /* read small metrics */+ if ( FT_STREAM_READ_FIELDS( sbit_small_metrics_fields, &smetrics ) )+ goto Exit;++ /* convert it to a big metrics */+ metrics->height = smetrics.height;+ metrics->width = smetrics.width;+ metrics->horiBearingX = smetrics.bearingX;+ metrics->horiBearingY = smetrics.bearingY;+ metrics->horiAdvance = smetrics.advance;++ /* these metrics are made up at a higher level when */+ /* needed. */+ metrics->vertBearingX = 0;+ metrics->vertBearingY = 0;+ metrics->vertAdvance = 0;+ }+ break;++ case 6:+ case 7:+ case 9:+ /* variable big metrics */+ if ( FT_STREAM_READ_FIELDS( sbit_metrics_fields, metrics ) )+ goto Exit;+ break;++ case 5:+ default: /* constant metrics */+ if ( range->index_format == 2 || range->index_format == 5 )+ *metrics = range->metrics;+ else+ return SFNT_Err_Invalid_File_Format;+ }++ Exit:+ return error;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* crop_bitmap */+ /* */+ /* <Description> */+ /* Crops a bitmap to its tightest bounding box, and adjusts its */+ /* metrics. */+ /* */+ /* <InOut> */+ /* map :: The bitmap. */+ /* */+ /* metrics :: The corresponding metrics structure. */+ /* */+ static void+ crop_bitmap( FT_Bitmap* map,+ TT_SBit_Metrics metrics )+ {+ /***********************************************************************/+ /* */+ /* In this situation, some bounding boxes of embedded bitmaps are too */+ /* large. We need to crop it to a reasonable size. */+ /* */+ /* --------- */+ /* | | ----- */+ /* | *** | |***| */+ /* | * | | * | */+ /* | * | ------> | * | */+ /* | * | | * | */+ /* | * | | * | */+ /* | *** | |***| */+ /* --------- ----- */+ /* */+ /***********************************************************************/++ FT_Int rows, count;+ FT_Long line_len;+ FT_Byte* line;+++ /***********************************************************************/+ /* */+ /* first of all, check the top-most lines of the bitmap, and remove */+ /* them if they're empty. */+ /* */+ {+ line = (FT_Byte*)map->buffer;+ rows = map->rows;+ line_len = map->pitch;+++ for ( count = 0; count < rows; count++ )+ {+ FT_Byte* cur = line;+ FT_Byte* limit = line + line_len;+++ for ( ; cur < limit; cur++ )+ if ( cur[0] )+ goto Found_Top;++ /* the current line was empty - skip to next one */+ line = limit;+ }++ Found_Top:+ /* check that we have at least one filled line */+ if ( count >= rows )+ goto Empty_Bitmap;++ /* now, crop the empty upper lines */+ if ( count > 0 )+ {+ line = (FT_Byte*)map->buffer;++ FT_MEM_MOVE( line, line + count * line_len,+ ( rows - count ) * line_len );++ metrics->height = (FT_Byte)( metrics->height - count );+ metrics->horiBearingY = (FT_Char)( metrics->horiBearingY - count );+ metrics->vertBearingY = (FT_Char)( metrics->vertBearingY - count );++ map->rows -= count;+ rows -= count;+ }+ }++ /***********************************************************************/+ /* */+ /* second, crop the lower lines */+ /* */+ {+ line = (FT_Byte*)map->buffer + ( rows - 1 ) * line_len;++ for ( count = 0; count < rows; count++ )+ {+ FT_Byte* cur = line;+ FT_Byte* limit = line + line_len;+++ for ( ; cur < limit; cur++ )+ if ( cur[0] )+ goto Found_Bottom;++ /* the current line was empty - skip to previous one */+ line -= line_len;+ }++ Found_Bottom:+ if ( count > 0 )+ {+ metrics->height = (FT_Byte)( metrics->height - count );+ rows -= count;+ map->rows -= count;+ }+ }++ /***********************************************************************/+ /* */+ /* third, get rid of the space on the left side of the glyph */+ /* */+ do+ {+ FT_Byte* limit;+++ line = (FT_Byte*)map->buffer;+ limit = line + rows * line_len;++ for ( ; line < limit; line += line_len )+ if ( line[0] & 0x80 )+ goto Found_Left;++ /* shift the whole glyph one pixel to the left */+ line = (FT_Byte*)map->buffer;+ limit = line + rows * line_len;++ for ( ; line < limit; line += line_len )+ {+ FT_Int n, width = map->width;+ FT_Byte old;+ FT_Byte* cur = line;+++ old = (FT_Byte)(cur[0] << 1);+ for ( n = 8; n < width; n += 8 )+ {+ FT_Byte val;+++ val = cur[1];+ cur[0] = (FT_Byte)( old | ( val >> 7 ) );+ old = (FT_Byte)( val << 1 );+ cur++;+ }+ cur[0] = old;+ }++ map->width--;+ metrics->horiBearingX++;+ metrics->vertBearingX++;+ metrics->width--;++ } while ( map->width > 0 );++ Found_Left:++ /***********************************************************************/+ /* */+ /* finally, crop the bitmap width to get rid of the space on the right */+ /* side of the glyph. */+ /* */+ do+ {+ FT_Int right = map->width - 1;+ FT_Byte* limit;+ FT_Byte mask;+++ line = (FT_Byte*)map->buffer + ( right >> 3 );+ limit = line + rows * line_len;+ mask = (FT_Byte)( 0x80 >> ( right & 7 ) );++ for ( ; line < limit; line += line_len )+ if ( line[0] & mask )+ goto Found_Right;++ /* crop the whole glyph to the right */+ map->width--;+ metrics->width--;++ } while ( map->width > 0 );++ Found_Right:+ /* all right, the bitmap was cropped */+ return;++ Empty_Bitmap:+ map->width = 0;+ map->rows = 0;+ map->pitch = 0;+ map->pixel_mode = FT_PIXEL_MODE_MONO;+ }+++ static FT_Error+ Load_SBit_Single( FT_Bitmap* map,+ FT_Int x_offset,+ FT_Int y_offset,+ FT_Int pix_bits,+ FT_UShort image_format,+ TT_SBit_Metrics metrics,+ FT_Stream stream )+ {+ FT_Error error;+++ /* check that the source bitmap fits into the target pixmap */+ if ( x_offset < 0 || x_offset + metrics->width > map->width ||+ y_offset < 0 || y_offset + metrics->height > map->rows )+ {+ error = SFNT_Err_Invalid_Argument;++ goto Exit;+ }++ {+ FT_Int glyph_width = metrics->width;+ FT_Int glyph_height = metrics->height;+ FT_Int glyph_size;+ FT_Int line_bits = pix_bits * glyph_width;+ FT_Bool pad_bytes = 0;+++ /* compute size of glyph image */+ switch ( image_format )+ {+ case 1: /* byte-padded formats */+ case 6:+ {+ FT_Int line_length;+++ switch ( pix_bits )+ {+ case 1:+ line_length = ( glyph_width + 7 ) >> 3;+ break;+ case 2:+ line_length = ( glyph_width + 3 ) >> 2;+ break;+ case 4:+ line_length = ( glyph_width + 1 ) >> 1;+ break;+ default:+ line_length = glyph_width;+ }++ glyph_size = glyph_height * line_length;+ pad_bytes = 1;+ }+ break;++ case 2:+ case 5:+ case 7:+ line_bits = glyph_width * pix_bits;+ glyph_size = ( glyph_height * line_bits + 7 ) >> 3;+ break;++ default: /* invalid format */+ return SFNT_Err_Invalid_File_Format;+ }++ /* Now read data and draw glyph into target pixmap */+ if ( FT_FRAME_ENTER( glyph_size ) )+ goto Exit;++ /* don't forget to multiply `x_offset' by `map->pix_bits' as */+ /* the sbit blitter doesn't make a difference between pixmap */+ /* depths. */+ blit_sbit( map, (FT_Byte*)stream->cursor, line_bits, pad_bytes,+ x_offset * pix_bits, y_offset, metrics->height );++ FT_FRAME_EXIT();+ }++ Exit:+ return error;+ }+++ static FT_Error+ Load_SBit_Image( TT_SBit_Strike strike,+ TT_SBit_Range range,+ FT_ULong ebdt_pos,+ FT_ULong glyph_offset,+ FT_GlyphSlot slot,+ FT_Int x_offset,+ FT_Int y_offset,+ FT_Stream stream,+ TT_SBit_Metrics metrics,+ FT_Int depth )+ {+ FT_Memory memory = stream->memory;+ FT_Bitmap* map = &slot->bitmap;+ FT_Error error;+++ /* place stream at beginning of glyph data and read metrics */+ if ( FT_STREAM_SEEK( ebdt_pos + glyph_offset ) )+ goto Exit;++ error = tt_load_sbit_metrics( stream, range, metrics );+ if ( error )+ goto Exit;++ /* This function is recursive. At the top-level call, we */+ /* compute the dimensions of the higher-level glyph to */+ /* allocate the final pixmap buffer. */+ if ( depth == 0 )+ {+ FT_Long size;+++ map->width = metrics->width;+ map->rows = metrics->height;++ switch ( strike->bit_depth )+ {+ case 1:+ map->pixel_mode = FT_PIXEL_MODE_MONO;+ map->pitch = ( map->width + 7 ) >> 3;+ break;++ case 2:+ map->pixel_mode = FT_PIXEL_MODE_GRAY2;+ map->pitch = ( map->width + 3 ) >> 2;+ break;++ case 4:+ map->pixel_mode = FT_PIXEL_MODE_GRAY4;+ map->pitch = ( map->width + 1 ) >> 1;+ break;++ case 8:+ map->pixel_mode = FT_PIXEL_MODE_GRAY;+ map->pitch = map->width;+ break;++ default:+ return SFNT_Err_Invalid_File_Format;+ }++ size = map->rows * map->pitch;++ /* check that there is no empty image */+ if ( size == 0 )+ goto Exit; /* exit successfully! */++ error = ft_glyphslot_alloc_bitmap( slot, size );+ if (error)+ goto Exit;+ }++ switch ( range->image_format )+ {+ case 1: /* single sbit image - load it */+ case 2:+ case 5:+ case 6:+ case 7:+ return Load_SBit_Single( map, x_offset, y_offset, strike->bit_depth,+ range->image_format, metrics, stream );++ case 8: /* compound format */+ if ( FT_STREAM_SKIP( 1L ) )+ {+ error = SFNT_Err_Invalid_Stream_Skip;+ goto Exit;+ }+ /* fallthrough */++ case 9:+ break;++ default: /* invalid image format */+ return SFNT_Err_Invalid_File_Format;+ }++ /* All right, we have a compound format. First of all, read */+ /* the array of elements. */+ {+ TT_SBit_Component components;+ TT_SBit_Component comp;+ FT_UShort num_components, count;+++ if ( FT_READ_USHORT( num_components ) ||+ FT_NEW_ARRAY( components, num_components ) )+ goto Exit;++ count = num_components;++ if ( FT_FRAME_ENTER( 4L * num_components ) )+ goto Fail_Memory;++ for ( comp = components; count > 0; count--, comp++ )+ {+ comp->glyph_code = FT_GET_USHORT();+ comp->x_offset = FT_GET_CHAR();+ comp->y_offset = FT_GET_CHAR();+ }++ FT_FRAME_EXIT();++ /* Now recursively load each element glyph */+ count = num_components;+ comp = components;+ for ( ; count > 0; count--, comp++ )+ {+ TT_SBit_Range elem_range;+ TT_SBit_MetricsRec elem_metrics;+ FT_ULong elem_offset;+++ /* find the range for this element */+ error = find_sbit_range( comp->glyph_code,+ strike,+ &elem_range,+ &elem_offset );+ if ( error )+ goto Fail_Memory;++ /* now load the element, recursively */+ error = Load_SBit_Image( strike,+ elem_range,+ ebdt_pos,+ elem_offset,+ slot,+ x_offset + comp->x_offset,+ y_offset + comp->y_offset,+ stream,+ &elem_metrics,+ depth + 1 );+ if ( error )+ goto Fail_Memory;+ }++ Fail_Memory:+ FT_FREE( components );+ }++ Exit:+ return error;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_face_load_sbit_image */+ /* */+ /* <Description> */+ /* Loads a given glyph sbit image from the font resource. This also */+ /* returns its metrics. */+ /* */+ /* <Input> */+ /* face :: The target face object. */+ /* */+ /* strike_index :: The current strike index. */+ /* */+ /* glyph_index :: The current glyph index. */+ /* */+ /* load_flags :: The glyph load flags (the code checks for the flag */+ /* FT_LOAD_CROP_BITMAP). */+ /* */+ /* stream :: The input stream. */+ /* */+ /* <Output> */+ /* map :: The target pixmap. */+ /* */+ /* metrics :: A big sbit metrics structure for the glyph image. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. Returns an error if no */+ /* glyph sbit exists for the index. */+ /* */+ /* <Note> */+ /* The `map.buffer' field is always freed before the glyph is loaded. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ tt_face_load_sbit_image( TT_Face face,+ FT_ULong strike_index,+ FT_UInt glyph_index,+ FT_UInt load_flags,+ FT_Stream stream,+ FT_Bitmap *map,+ TT_SBit_MetricsRec *metrics )+ {+ FT_Error error;+ FT_ULong ebdt_pos, glyph_offset;++ TT_SBit_Strike strike;+ TT_SBit_Range range;+++ /* Check whether there is a glyph sbit for the current index */+ error = tt_find_sbit_image( face, glyph_index, strike_index,+ &range, &strike, &glyph_offset );+ if ( error )+ goto Exit;++ /* now, find the location of the `EBDT' table in */+ /* the font file */+ error = face->goto_table( face, TTAG_EBDT, stream, 0 );+ if ( error )+ error = face->goto_table( face, TTAG_bdat, stream, 0 );+ if ( error )+ goto Exit;++ ebdt_pos = FT_STREAM_POS();++ error = Load_SBit_Image( strike, range, ebdt_pos, glyph_offset,+ face->root.glyph, 0, 0, stream, metrics, 0 );+ if ( error )+ goto Exit;++ /* setup vertical metrics if needed */+ if ( strike->flags & 1 )+ {+ /* in case of a horizontal strike only */+ FT_Int advance;+++ advance = strike->hori.ascender - strike->hori.descender;++ /* some heuristic values */++ metrics->vertBearingX = (FT_Char)(-metrics->width / 2 );+ metrics->vertBearingY = (FT_Char)( ( advance - metrics->height ) / 2 );+ metrics->vertAdvance = (FT_Char)( advance * 12 / 10 );+ }++ /* Crop the bitmap now, unless specified otherwise */+ if ( load_flags & FT_LOAD_CROP_BITMAP )+ crop_bitmap( map, metrics );++ Exit:+ return error;+ }++#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */+++/* END */
+ src/sfnt/ttsbit.h view
@@ -0,0 +1,79 @@+/***************************************************************************/+/* */+/* ttsbit.h */+/* */+/* TrueType and OpenType embedded bitmap support (specification). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 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 __TTSBIT_H__+#define __TTSBIT_H__+++#include <ft2build.h>+#include "ttload.h"+++FT_BEGIN_HEADER+++ FT_LOCAL( FT_Error )+ tt_face_load_eblc( TT_Face face,+ FT_Stream stream );++ FT_LOCAL( void )+ tt_face_free_eblc( TT_Face face );+++ FT_LOCAL( FT_Error )+ tt_face_set_sbit_strike( TT_Face face,+ FT_Size_Request req,+ FT_ULong* astrike_index );++ FT_LOCAL( FT_Error )+ tt_face_load_strike_metrics( TT_Face face,+ FT_ULong strike_index,+ FT_Size_Metrics* metrics );++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS+ FT_LOCAL( FT_Error )+ tt_find_sbit_image( TT_Face face,+ FT_UInt glyph_index,+ FT_ULong strike_index,+ TT_SBit_Range *arange,+ TT_SBit_Strike *astrike,+ FT_ULong *aglyph_offset );++ FT_LOCAL( FT_Error )+ tt_load_sbit_metrics( FT_Stream stream,+ TT_SBit_Range range,+ TT_SBit_Metrics metrics );++#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */++ FT_LOCAL( FT_Error )+ tt_face_load_sbit_image( TT_Face face,+ FT_ULong strike_index,+ FT_UInt glyph_index,+ FT_UInt load_flags,+ FT_Stream stream,+ FT_Bitmap *map,+ TT_SBit_MetricsRec *metrics );+++FT_END_HEADER++#endif /* __TTSBIT_H__ */+++/* END */
+ src/sfnt/ttsbit0.c view
@@ -0,0 +1,1011 @@+/***************************************************************************/+/* */+/* ttsbit0.c */+/* */+/* TrueType and OpenType embedded bitmap support (body). */+/* This is a heap-optimized version. */+/* */+/* Copyright 2005, 2006, 2007, 2008, 2009 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 included by ttsbit.c */+++#include <ft2build.h>+#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_STREAM_H+#include FT_TRUETYPE_TAGS_H+#include "ttsbit.h"++#include "sferrors.h"+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_ttsbit+++ FT_LOCAL_DEF( FT_Error )+ tt_face_load_eblc( TT_Face face,+ FT_Stream stream )+ {+ FT_Error error = SFNT_Err_Ok;+ FT_Fixed version;+ FT_ULong num_strikes, table_size;+ FT_Byte* p;+ FT_Byte* p_limit;+ FT_UInt count;+++ face->sbit_num_strikes = 0;++ /* this table is optional */+ error = face->goto_table( face, TTAG_EBLC, stream, &table_size );+ if ( error )+ error = face->goto_table( face, TTAG_bloc, stream, &table_size );+ if ( error )+ goto Exit;++ if ( table_size < 8 )+ {+ FT_ERROR(( "tt_face_load_sbit_strikes: table too short\n" ));+ error = SFNT_Err_Invalid_File_Format;+ goto Exit;+ }++ if ( FT_FRAME_EXTRACT( table_size, face->sbit_table ) )+ goto Exit;++ face->sbit_table_size = table_size;++ p = face->sbit_table;+ p_limit = p + table_size;++ version = FT_NEXT_ULONG( p );+ num_strikes = FT_NEXT_ULONG( p );++ if ( version != 0x00020000UL || num_strikes >= 0x10000UL )+ {+ FT_ERROR(( "tt_face_load_sbit_strikes: invalid table version\n" ));+ error = SFNT_Err_Invalid_File_Format;+ goto Fail;+ }++ /*+ * Count the number of strikes available in the table. We are a bit+ * paranoid there and don't trust the data.+ */+ count = (FT_UInt)num_strikes;+ if ( 8 + 48UL * count > table_size )+ count = (FT_UInt)( ( p_limit - p ) / 48 );++ face->sbit_num_strikes = count;++ FT_TRACE3(( "sbit_num_strikes: %u\n", count ));+ Exit:+ return error;++ Fail:+ FT_FRAME_RELEASE( face->sbit_table );+ face->sbit_table_size = 0;+ goto Exit;+ }+++ FT_LOCAL_DEF( void )+ tt_face_free_eblc( TT_Face face )+ {+ FT_Stream stream = face->root.stream;+++ FT_FRAME_RELEASE( face->sbit_table );+ face->sbit_table_size = 0;+ face->sbit_num_strikes = 0;+ }+++ FT_LOCAL_DEF( FT_Error )+ tt_face_set_sbit_strike( TT_Face face,+ FT_Size_Request req,+ FT_ULong* astrike_index )+ {+ return FT_Match_Size( (FT_Face)face, req, 0, astrike_index );+ }+++ FT_LOCAL_DEF( FT_Error )+ tt_face_load_strike_metrics( TT_Face face,+ FT_ULong strike_index,+ FT_Size_Metrics* metrics )+ {+ FT_Byte* strike;+++ if ( strike_index >= (FT_ULong)face->sbit_num_strikes )+ return SFNT_Err_Invalid_Argument;++ strike = face->sbit_table + 8 + strike_index * 48;++ 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;++ /* XXX: 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;++ return SFNT_Err_Ok;+ }+++ typedef struct TT_SBitDecoderRec_+ {+ TT_Face face;+ FT_Stream stream;+ FT_Bitmap* bitmap;+ TT_SBit_Metrics metrics;+ FT_Bool metrics_loaded;+ FT_Bool bitmap_allocated;+ FT_Byte bit_depth;++ FT_ULong ebdt_start;+ FT_ULong ebdt_size;++ FT_ULong strike_index_array;+ FT_ULong strike_index_count;+ FT_Byte* eblc_base;+ FT_Byte* eblc_limit;++ } TT_SBitDecoderRec, *TT_SBitDecoder;+++ static FT_Error+ tt_sbit_decoder_init( TT_SBitDecoder decoder,+ TT_Face face,+ FT_ULong strike_index,+ TT_SBit_MetricsRec* metrics )+ {+ FT_Error error;+ FT_Stream stream = face->root.stream;+ FT_ULong ebdt_size;+++ error = face->goto_table( face, TTAG_EBDT, stream, &ebdt_size );+ if ( error )+ error = face->goto_table( face, TTAG_bdat, stream, &ebdt_size );+ if ( error )+ goto Exit;++ decoder->face = face;+ decoder->stream = stream;+ decoder->bitmap = &face->root.glyph->bitmap;+ decoder->metrics = metrics;++ decoder->metrics_loaded = 0;+ decoder->bitmap_allocated = 0;++ decoder->ebdt_start = FT_STREAM_POS();+ decoder->ebdt_size = ebdt_size;++ decoder->eblc_base = face->sbit_table;+ decoder->eblc_limit = face->sbit_table + face->sbit_table_size;++ /* now find the strike corresponding to the index */+ {+ FT_Byte* p;+++ if ( 8 + 48 * strike_index + 3 * 4 + 34 + 1 > face->sbit_table_size )+ {+ error = SFNT_Err_Invalid_File_Format;+ goto Exit;+ }++ p = decoder->eblc_base + 8 + 48 * strike_index;++ decoder->strike_index_array = FT_NEXT_ULONG( p );+ p += 4;+ decoder->strike_index_count = FT_NEXT_ULONG( p );+ p += 34;+ decoder->bit_depth = *p;++ if ( decoder->strike_index_array > face->sbit_table_size ||+ decoder->strike_index_array + 8 * decoder->strike_index_count >+ face->sbit_table_size )+ error = SFNT_Err_Invalid_File_Format;+ }++ Exit:+ return error;+ }+++ static void+ tt_sbit_decoder_done( TT_SBitDecoder decoder )+ {+ FT_UNUSED( decoder );+ }+++ static FT_Error+ tt_sbit_decoder_alloc_bitmap( TT_SBitDecoder decoder )+ {+ FT_Error error = SFNT_Err_Ok;+ FT_UInt width, height;+ FT_Bitmap* map = decoder->bitmap;+ FT_Long size;+++ if ( !decoder->metrics_loaded )+ {+ error = SFNT_Err_Invalid_Argument;+ goto Exit;+ }++ width = decoder->metrics->width;+ height = decoder->metrics->height;++ map->width = (int)width;+ map->rows = (int)height;++ switch ( decoder->bit_depth )+ {+ case 1:+ map->pixel_mode = FT_PIXEL_MODE_MONO;+ map->pitch = ( map->width + 7 ) >> 3;+ break;++ case 2:+ map->pixel_mode = FT_PIXEL_MODE_GRAY2;+ map->pitch = ( map->width + 3 ) >> 2;+ break;++ case 4:+ map->pixel_mode = FT_PIXEL_MODE_GRAY4;+ map->pitch = ( map->width + 1 ) >> 1;+ break;++ case 8:+ map->pixel_mode = FT_PIXEL_MODE_GRAY;+ map->pitch = map->width;+ break;++ default:+ error = SFNT_Err_Invalid_File_Format;+ goto Exit;+ }++ size = map->rows * map->pitch;++ /* check that there is no empty image */+ if ( size == 0 )+ goto Exit; /* exit successfully! */++ error = ft_glyphslot_alloc_bitmap( decoder->face->root.glyph, size );+ if ( error )+ goto Exit;++ decoder->bitmap_allocated = 1;++ Exit:+ return error;+ }+++ static FT_Error+ tt_sbit_decoder_load_metrics( TT_SBitDecoder decoder,+ FT_Byte* *pp,+ FT_Byte* limit,+ FT_Bool big )+ {+ FT_Byte* p = *pp;+ TT_SBit_Metrics metrics = decoder->metrics;+++ if ( p + 5 > limit )+ goto Fail;++ metrics->height = p[0];+ metrics->width = p[1];+ metrics->horiBearingX = (FT_Char)p[2];+ metrics->horiBearingY = (FT_Char)p[3];+ metrics->horiAdvance = p[4];++ p += 5;+ if ( big )+ {+ if ( p + 3 > limit )+ goto Fail;++ metrics->vertBearingX = (FT_Char)p[0];+ metrics->vertBearingY = (FT_Char)p[1];+ metrics->vertAdvance = p[2];++ p += 3;+ }++ decoder->metrics_loaded = 1;+ *pp = p;+ return SFNT_Err_Ok;++ Fail:+ return SFNT_Err_Invalid_Argument;+ }+++ /* forward declaration */+ static FT_Error+ tt_sbit_decoder_load_image( TT_SBitDecoder decoder,+ FT_UInt glyph_index,+ 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 );+++ static FT_Error+ tt_sbit_decoder_load_byte_aligned( TT_SBitDecoder decoder,+ FT_Byte* p,+ FT_Byte* limit,+ FT_Int x_pos,+ FT_Int y_pos )+ {+ FT_Error error = SFNT_Err_Ok;+ FT_Byte* line;+ FT_Int bit_height, bit_width, pitch, width, height, h;+ FT_Bitmap* bitmap;+++ if ( !decoder->bitmap_allocated )+ {+ error = tt_sbit_decoder_alloc_bitmap( decoder );+ if ( error )+ goto Exit;+ }++ /* check that we can write the glyph into the bitmap */+ bitmap = decoder->bitmap;+ bit_width = bitmap->width;+ bit_height = bitmap->rows;+ pitch = bitmap->pitch;+ line = bitmap->buffer;++ width = decoder->metrics->width;+ height = decoder->metrics->height;++ if ( x_pos < 0 || x_pos + width > bit_width ||+ y_pos < 0 || y_pos + height > bit_height )+ {+ error = SFNT_Err_Invalid_File_Format;+ goto Exit;+ }++ if ( p + ( ( width + 7 ) >> 3 ) * height > limit )+ {+ error = SFNT_Err_Invalid_File_Format;+ goto Exit;+ }++ /* now do the blit */+ line += y_pos * pitch + ( x_pos >> 3 );+ x_pos &= 7;++ if ( x_pos == 0 ) /* the easy one */+ {+ for ( h = height; h > 0; h--, line += pitch )+ {+ FT_Byte* write = line;+ FT_Int w;+++ for ( w = width; w >= 8; w -= 8 )+ {+ write[0] = (FT_Byte)( write[0] | *p++ );+ write += 1;+ }++ if ( w > 0 )+ write[0] = (FT_Byte)( write[0] | ( *p++ & ( 0xFF00U >> w ) ) );+ }+ }+ else /* x_pos > 0 */+ {+ for ( h = height; h > 0; h--, line += pitch )+ {+ FT_Byte* write = line;+ FT_Int w;+ FT_UInt wval = 0;+++ for ( w = width; w >= 8; w -= 8 )+ {+ wval = (FT_UInt)( wval | *p++ );+ write[0] = (FT_Byte)( write[0] | ( wval >> x_pos ) );+ write += 1;+ wval <<= 8;+ }++ if ( w > 0 )+ wval = (FT_UInt)( wval | ( *p++ & ( 0xFF00U >> w ) ) );++ /* all bits read and there are `x_pos + w' bits to be written */++ write[0] = (FT_Byte)( write[0] | ( wval >> x_pos ) );++ if ( x_pos + w > 8 )+ {+ write++;+ wval <<= 8;+ write[0] = (FT_Byte)( write[0] | ( wval >> x_pos ) );+ }+ }+ }++ Exit:+ return error;+ }+++ /*+ * Load a bit-aligned bitmap (with pointer `p') into a line-aligned bitmap+ * (with pointer `write'). In the example below, the width is 3 pixel,+ * and `x_pos' is 1 pixel.+ *+ * p p+1+ * | | |+ * | 7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0 |...+ * | | |+ * +-------+ +-------+ +-------+ ...+ * . . .+ * . . .+ * v . .+ * +-------+ . .+ * | | .+ * | 7 6 5 4 3 2 1 0 | .+ * | | .+ * write . .+ * . .+ * v .+ * +-------+ .+ * | |+ * | 7 6 5 4 3 2 1 0 |+ * | |+ * write+1 .+ * .+ * v+ * +-------++ * | |+ * | 7 6 5 4 3 2 1 0 |+ * | |+ * write+2+ *+ */++ static FT_Error+ tt_sbit_decoder_load_bit_aligned( TT_SBitDecoder decoder,+ FT_Byte* p,+ FT_Byte* limit,+ FT_Int x_pos,+ FT_Int y_pos )+ {+ FT_Error error = SFNT_Err_Ok;+ FT_Byte* line;+ FT_Int bit_height, bit_width, pitch, width, height, h, nbits;+ FT_Bitmap* bitmap;+ FT_UShort rval;+++ if ( !decoder->bitmap_allocated )+ {+ error = tt_sbit_decoder_alloc_bitmap( decoder );+ if ( error )+ goto Exit;+ }++ /* check that we can write the glyph into the bitmap */+ bitmap = decoder->bitmap;+ bit_width = bitmap->width;+ bit_height = bitmap->rows;+ pitch = bitmap->pitch;+ line = bitmap->buffer;++ width = decoder->metrics->width;+ height = decoder->metrics->height;++ if ( x_pos < 0 || x_pos + width > bit_width ||+ y_pos < 0 || y_pos + height > bit_height )+ {+ error = SFNT_Err_Invalid_File_Format;+ goto Exit;+ }++ if ( p + ( ( width * height + 7 ) >> 3 ) > limit )+ {+ error = SFNT_Err_Invalid_File_Format;+ goto Exit;+ }++ /* now do the blit */++ /* adjust `line' to point to the first byte of the bitmap */+ line += y_pos * pitch + ( x_pos >> 3 );+ x_pos &= 7;++ /* the higher byte of `rval' is used as a buffer */+ rval = 0;+ nbits = 0;++ for ( h = height; h > 0; h--, line += pitch )+ {+ FT_Byte* write = line;+ FT_Int w = width;+++ /* handle initial byte (in target bitmap) specially if necessary */+ if ( x_pos )+ {+ w = ( width < 8 - x_pos ) ? width : 8 - x_pos;++ if ( h == height )+ {+ rval = *p++;+ nbits = x_pos;+ }+ else if ( nbits < w )+ {+ if ( p < limit )+ rval |= *p++;+ nbits += 8 - w;+ }+ else+ {+ rval >>= 8;+ nbits -= w;+ }++ *write++ |= ( ( rval >> nbits ) & 0xFF ) &+ ( ~( 0xFF << w ) << ( 8 - w - x_pos ) );+ rval <<= 8;++ w = width - w;+ }++ /* handle medial bytes */+ for ( ; w >= 8; w -= 8 )+ {+ rval |= *p++;+ *write++ |= ( rval >> nbits ) & 0xFF;++ rval <<= 8;+ }++ /* handle final byte if necessary */+ if ( w > 0 )+ {+ if ( nbits < w )+ {+ if ( p < limit )+ rval |= *p++;+ *write |= ( ( rval >> nbits ) & 0xFF ) & ( 0xFF00U >> w );+ nbits += 8 - w;++ rval <<= 8;+ }+ else+ {+ *write |= ( ( rval >> nbits ) & 0xFF ) & ( 0xFF00U >> w );+ nbits -= w;+ }+ }+ }++ Exit:+ return error;+ }+++ static FT_Error+ tt_sbit_decoder_load_compound( TT_SBitDecoder decoder,+ FT_Byte* p,+ FT_Byte* limit,+ FT_Int x_pos,+ FT_Int y_pos )+ {+ FT_Error error = SFNT_Err_Ok;+ FT_UInt num_components, nn;++ FT_Char horiBearingX = decoder->metrics->horiBearingX;+ FT_Char horiBearingY = decoder->metrics->horiBearingY;+ FT_Byte horiAdvance = decoder->metrics->horiAdvance;+ FT_Char vertBearingX = decoder->metrics->vertBearingX;+ FT_Char vertBearingY = decoder->metrics->vertBearingY;+ FT_Byte vertAdvance = decoder->metrics->vertAdvance;+++ if ( p + 2 > limit )+ goto Fail;++ num_components = FT_NEXT_USHORT( p );+ if ( p + 4 * num_components > limit )+ goto Fail;++ if ( !decoder->bitmap_allocated )+ {+ error = tt_sbit_decoder_alloc_bitmap( decoder );+ if ( error )+ goto Exit;+ }++ for ( nn = 0; nn < num_components; nn++ )+ {+ FT_UInt gindex = FT_NEXT_USHORT( p );+ FT_Byte dx = FT_NEXT_BYTE( p );+ FT_Byte dy = FT_NEXT_BYTE( p );+++ /* NB: a recursive call */+ error = tt_sbit_decoder_load_image( decoder, gindex,+ x_pos + dx, y_pos + dy );+ if ( error )+ break;+ }++ decoder->metrics->horiBearingX = horiBearingX;+ decoder->metrics->horiBearingY = horiBearingY;+ decoder->metrics->horiAdvance = horiAdvance;+ decoder->metrics->vertBearingX = vertBearingX;+ decoder->metrics->vertBearingY = vertBearingY;+ decoder->metrics->vertAdvance = vertAdvance;+ decoder->metrics->width = (FT_UInt)decoder->bitmap->width;+ decoder->metrics->height = (FT_UInt)decoder->bitmap->rows;++ Exit:+ return error;++ Fail:+ error = SFNT_Err_Invalid_File_Format;+ goto Exit;+ }+++ static FT_Error+ tt_sbit_decoder_load_bitmap( TT_SBitDecoder decoder,+ FT_UInt glyph_format,+ FT_ULong glyph_start,+ FT_ULong glyph_size,+ FT_Int x_pos,+ FT_Int y_pos )+ {+ FT_Error error;+ FT_Stream stream = decoder->stream;+ FT_Byte* p;+ FT_Byte* p_limit;+ FT_Byte* data;+++ /* seek into the EBDT table now */+ if ( glyph_start + glyph_size > decoder->ebdt_size )+ {+ error = SFNT_Err_Invalid_Argument;+ goto Exit;+ }++ if ( FT_STREAM_SEEK( decoder->ebdt_start + glyph_start ) ||+ FT_FRAME_EXTRACT( glyph_size, data ) )+ goto Exit;++ p = data;+ p_limit = p + glyph_size;++ /* read the data, depending on the glyph format */+ switch ( glyph_format )+ {+ case 1:+ case 2:+ case 8:+ error = tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 0 );+ break;++ case 6:+ case 7:+ case 9:+ error = tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 );+ break;++ default:+ error = SFNT_Err_Ok;+ }++ if ( error )+ goto Fail;++ {+ TT_SBitDecoder_LoadFunc loader;+++ switch ( glyph_format )+ {+ case 1:+ case 6:+ loader = tt_sbit_decoder_load_byte_aligned;+ break;++ case 2:+ case 5:+ case 7:+ loader = tt_sbit_decoder_load_bit_aligned;+ break;++ case 8:+ if ( p + 1 > p_limit )+ goto Fail;++ p += 1; /* skip padding */+ /* fall-through */++ case 9:+ loader = tt_sbit_decoder_load_compound;+ break;++ default:+ goto Fail;+ }++ error = loader( decoder, p, p_limit, x_pos, y_pos );+ }++ Fail:+ FT_FRAME_RELEASE( data );++ Exit:+ return error;+ }+++ static FT_Error+ tt_sbit_decoder_load_image( TT_SBitDecoder decoder,+ FT_UInt glyph_index,+ FT_Int x_pos,+ FT_Int y_pos )+ {+ /*+ * 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;+ FT_UInt start, end, index_format, image_format;+ FT_ULong image_start = 0, image_end = 0, image_offset;+++ for ( ; num_ranges > 0; num_ranges-- )+ {+ start = FT_NEXT_USHORT( p );+ end = FT_NEXT_USHORT( p );++ if ( glyph_index >= start && glyph_index <= end )+ goto FoundRange;++ p += 4; /* ignore index offset */+ }+ goto NoBitmap;++ FoundRange:+ image_offset = FT_NEXT_ULONG( p );++ /* overflow check */+ if ( decoder->eblc_base + decoder->strike_index_array + image_offset <+ decoder->eblc_base )+ goto Failure;++ p = decoder->eblc_base + decoder->strike_index_array + image_offset;+ if ( p + 8 > p_limit )+ goto NoBitmap;++ /* now find the glyph's location and extend within the ebdt table */+ index_format = FT_NEXT_USHORT( p );+ image_format = FT_NEXT_USHORT( p );+ image_offset = FT_NEXT_ULONG ( p );++ switch ( index_format )+ {+ case 1: /* 4-byte offsets relative to `image_offset' */+ {+ p += 4 * ( glyph_index - start );+ if ( p + 8 > p_limit )+ goto NoBitmap;++ image_start = FT_NEXT_ULONG( p );+ image_end = FT_NEXT_ULONG( p );++ if ( image_start == image_end ) /* missing glyph */+ goto NoBitmap;+ }+ break;++ case 2: /* big metrics, constant image size */+ {+ FT_ULong image_size;+++ if ( p + 12 > p_limit )+ goto NoBitmap;++ image_size = FT_NEXT_ULONG( p );++ if ( tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 ) )+ goto NoBitmap;++ image_start = image_size * ( glyph_index - start );+ image_end = image_start + image_size;+ }+ break;++ case 3: /* 2-byte offsets relative to 'image_offset' */+ {+ p += 2 * ( glyph_index - start );+ if ( p + 4 > p_limit )+ goto NoBitmap;++ image_start = FT_NEXT_USHORT( p );+ image_end = FT_NEXT_USHORT( p );++ if ( image_start == image_end ) /* missing glyph */+ goto NoBitmap;+ }+ break;++ case 4: /* sparse glyph array with (glyph,offset) pairs */+ {+ FT_ULong mm, num_glyphs;+++ if ( p + 4 > p_limit )+ goto NoBitmap;++ num_glyphs = FT_NEXT_ULONG( p );++ /* overflow check */+ if ( p + ( num_glyphs + 1 ) * 4 < p )+ goto Failure;++ if ( p + ( num_glyphs + 1 ) * 4 > p_limit )+ goto NoBitmap;++ for ( mm = 0; mm < num_glyphs; mm++ )+ {+ FT_UInt gindex = FT_NEXT_USHORT( p );+++ if ( gindex == glyph_index )+ {+ image_start = FT_NEXT_USHORT( p );+ p += 2;+ image_end = FT_PEEK_USHORT( p );+ break;+ }+ p += 2;+ }++ if ( mm >= num_glyphs )+ goto NoBitmap;+ }+ break;++ case 5: /* constant metrics with sparse glyph codes */+ {+ FT_ULong image_size, mm, num_glyphs;+++ if ( p + 16 > p_limit )+ goto NoBitmap;++ image_size = FT_NEXT_ULONG( p );++ if ( tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 ) )+ goto NoBitmap;++ num_glyphs = FT_NEXT_ULONG( p );++ /* overflow check */+ if ( p + 2 * num_glyphs < p )+ goto Failure;++ if ( p + 2 * num_glyphs > p_limit )+ goto NoBitmap;++ for ( mm = 0; mm < num_glyphs; mm++ )+ {+ FT_UInt gindex = FT_NEXT_USHORT( p );+++ if ( gindex == glyph_index )+ break;+ }++ if ( mm >= num_glyphs )+ goto NoBitmap;++ image_start = image_size * mm;+ image_end = image_start + image_size;+ }+ break;++ default:+ goto NoBitmap;+ }++ if ( image_start > image_end )+ goto NoBitmap;++ image_end -= image_start;+ image_start = image_offset + image_start;++ return tt_sbit_decoder_load_bitmap( decoder,+ image_format,+ image_start,+ image_end,+ x_pos,+ y_pos );++ Failure:+ return SFNT_Err_Invalid_Table;++ NoBitmap:+ return SFNT_Err_Invalid_Argument;+ }+++ FT_LOCAL( FT_Error )+ tt_face_load_sbit_image( TT_Face face,+ FT_ULong strike_index,+ FT_UInt glyph_index,+ FT_UInt load_flags,+ FT_Stream stream,+ FT_Bitmap *map,+ TT_SBit_MetricsRec *metrics )+ {+ TT_SBitDecoderRec decoder[1];+ FT_Error error;++ FT_UNUSED( load_flags );+ FT_UNUSED( stream );+ FT_UNUSED( map );+++ error = tt_sbit_decoder_init( decoder, face, strike_index, metrics );+ if ( !error )+ {+ error = tt_sbit_decoder_load_image( decoder, glyph_index, 0, 0 );+ tt_sbit_decoder_done( decoder );+ }++ return error;+ }++/* EOF */
+ src/smooth/ftgrays.c view
@@ -0,0 +1,2062 @@+/***************************************************************************/+/* */+/* ftgrays.c */+/* */+/* A new `perfect' anti-aliasing renderer (body). */+/* */+/* Copyright 2000-2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009, 2010 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 can be compiled without the rest of the FreeType engine, by */+ /* defining the _STANDALONE_ macro when compiling it. You also need to */+ /* put the files `ftgrays.h' and `ftimage.h' into the current */+ /* compilation directory. Typically, you could do something like */+ /* */+ /* - copy `src/smooth/ftgrays.c' (this file) to your current directory */+ /* */+ /* - copy `include/freetype/ftimage.h' and `src/smooth/ftgrays.h' to the */+ /* same directory */+ /* */+ /* - compile `ftgrays' with the _STANDALONE_ macro defined, as in */+ /* */+ /* cc -c -D_STANDALONE_ ftgrays.c */+ /* */+ /* The renderer can be initialized with a call to */+ /* `ft_gray_raster.raster_new'; an anti-aliased bitmap can be generated */+ /* with a call to `ft_gray_raster.raster_render'. */+ /* */+ /* See the comments and documentation in the file `ftimage.h' for more */+ /* details on how the raster works. */+ /* */+ /*************************************************************************/++ /*************************************************************************/+ /* */+ /* This is a new anti-aliasing scan-converter for FreeType 2. The */+ /* algorithm used here is _very_ different from the one in the standard */+ /* `ftraster' module. Actually, `ftgrays' computes the _exact_ */+ /* coverage of the outline on each pixel cell. */+ /* */+ /* It is based on ideas that I initially found in Raph Levien's */+ /* excellent LibArt graphics library (see http://www.levien.com/libart */+ /* for more information, though the web pages do not tell anything */+ /* about the renderer; you'll have to dive into the source code to */+ /* understand how it works). */+ /* */+ /* Note, however, that this is a _very_ different implementation */+ /* compared to Raph's. Coverage information is stored in a very */+ /* different way, and I don't use sorted vector paths. Also, it doesn't */+ /* use floating point values. */+ /* */+ /* This renderer has the following advantages: */+ /* */+ /* - It doesn't need an intermediate bitmap. Instead, one can supply a */+ /* callback function that will be called by the renderer to draw gray */+ /* spans on any target surface. You can thus do direct composition on */+ /* any kind of bitmap, provided that you give the renderer the right */+ /* callback. */+ /* */+ /* - A perfect anti-aliaser, i.e., it computes the _exact_ coverage on */+ /* each pixel cell. */+ /* */+ /* - It performs a single pass on the outline (the `standard' FT2 */+ /* renderer makes two passes). */+ /* */+ /* - It can easily be modified to render to _any_ number of gray levels */+ /* cheaply. */+ /* */+ /* - For small (< 20) pixel sizes, it is faster than the standard */+ /* renderer. */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* 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_smooth+++#ifdef _STANDALONE_+++ /* define this to dump debugging information */+/* #define FT_DEBUG_LEVEL_TRACE */+++#ifdef FT_DEBUG_LEVEL_TRACE+#include <stdio.h>+#include <stdarg.h>+#endif++#include <stddef.h>+#include <string.h>+#include <setjmp.h>+#include <limits.h>+#define FT_UINT_MAX UINT_MAX+#define FT_INT_MAX INT_MAX++#define ft_memset memset++#define ft_setjmp setjmp+#define ft_longjmp longjmp+#define ft_jmp_buf jmp_buf++typedef ptrdiff_t FT_PtrDist;+++#define ErrRaster_Invalid_Mode -2+#define ErrRaster_Invalid_Outline -1+#define ErrRaster_Invalid_Argument -3+#define ErrRaster_Memory_Overflow -4++#define FT_BEGIN_HEADER+#define FT_END_HEADER++#include "ftimage.h"+#include "ftgrays.h"+++ /* This macro is used to indicate that a function parameter is unused. */+ /* Its purpose is simply to reduce compiler warnings. Note also that */+ /* simply defining it as `(void)x' doesn't avoid warnings with certain */+ /* ANSI compilers (e.g. LCC). */+#define FT_UNUSED( x ) (x) = (x)+++ /* we only use level 5 & 7 tracing messages; cf. ftdebug.h */++#ifdef FT_DEBUG_LEVEL_TRACE++ void+ FT_Message( const char* fmt,+ ... )+ {+ va_list ap;+++ va_start( ap, fmt );+ vfprintf( stderr, fmt, ap );+ va_end( ap );+ }++ /* we don't handle tracing levels in stand-alone mode; */+#ifndef FT_TRACE5+#define FT_TRACE5( varformat ) FT_Message varformat+#endif+#ifndef FT_TRACE7+#define FT_TRACE7( varformat ) FT_Message varformat+#endif+#ifndef FT_ERROR+#define FT_ERROR( varformat ) FT_Message varformat+#endif++#else /* !FT_DEBUG_LEVEL_TRACE */++#define FT_TRACE5( x ) do { } while ( 0 ) /* nothing */+#define FT_TRACE7( x ) do { } while ( 0 ) /* nothing */+#define FT_ERROR( x ) do { } while ( 0 ) /* nothing */++#endif /* !FT_DEBUG_LEVEL_TRACE */+++#define FT_DEFINE_OUTLINE_FUNCS( class_, \+ move_to_, line_to_, \+ conic_to_, cubic_to_, \+ shift_, delta_ ) \+ static const FT_Outline_Funcs class_ = \+ { \+ move_to_, \+ line_to_, \+ conic_to_, \+ cubic_to_, \+ shift_, \+ delta_ \+ };++#define FT_DEFINE_RASTER_FUNCS( class_, glyph_format_, \+ raster_new_, raster_reset_, \+ raster_set_mode_, raster_render_, \+ raster_done_ ) \+ const FT_Raster_Funcs class_ = \+ { \+ glyph_format_, \+ raster_new_, \+ raster_reset_, \+ raster_set_mode_, \+ raster_render_, \+ raster_done_ \+ };++#else /* !_STANDALONE_ */+++#include <ft2build.h>+#include "ftgrays.h"+#include FT_INTERNAL_OBJECTS_H+#include FT_INTERNAL_DEBUG_H+#include FT_OUTLINE_H++#include "ftsmerrs.h"++#include "ftspic.h"++#define ErrRaster_Invalid_Mode Smooth_Err_Cannot_Render_Glyph+#define ErrRaster_Invalid_Outline Smooth_Err_Invalid_Outline+#define ErrRaster_Memory_Overflow Smooth_Err_Out_Of_Memory+#define ErrRaster_Invalid_Argument Smooth_Err_Invalid_Argument++#endif /* !_STANDALONE_ */++#ifndef FT_MEM_SET+#define FT_MEM_SET( d, s, c ) ft_memset( d, s, c )+#endif++#ifndef FT_MEM_ZERO+#define FT_MEM_ZERO( dest, count ) FT_MEM_SET( dest, 0, count )+#endif++ /* as usual, for the speed hungry :-) */++#ifndef FT_STATIC_RASTER++#define RAS_ARG PWorker worker+#define RAS_ARG_ PWorker worker,++#define RAS_VAR worker+#define RAS_VAR_ worker,++#else /* FT_STATIC_RASTER */++#define RAS_ARG /* empty */+#define RAS_ARG_ /* empty */+#define RAS_VAR /* empty */+#define RAS_VAR_ /* empty */++#endif /* FT_STATIC_RASTER */+++ /* must be at least 6 bits! */+#define PIXEL_BITS 8++#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 )+#define CEILING( x ) ( ( (x) + ONE_PIXEL - 1 ) & -ONE_PIXEL )+#define ROUND( x ) ( ( (x) + ONE_PIXEL / 2 ) & -ONE_PIXEL )++#if PIXEL_BITS >= 6+#define UPSCALE( x ) ( (x) << ( PIXEL_BITS - 6 ) )+#define DOWNSCALE( x ) ( (x) >> ( PIXEL_BITS - 6 ) )+#else+#define UPSCALE( x ) ( (x) >> ( 6 - PIXEL_BITS ) )+#define DOWNSCALE( x ) ( (x) << ( 6 - PIXEL_BITS ) )+#endif+++ /*************************************************************************/+ /* */+ /* TYPE DEFINITIONS */+ /* */++ /* don't change the following types to FT_Int or FT_Pos, since we might */+ /* need to define them to "float" or "double" when experimenting with */+ /* new algorithms */++ typedef long TCoord; /* integer scanline/pixel coordinate */+ typedef long TPos; /* sub-pixel coordinate */++ /* determine the type used to store cell areas. This normally takes at */+ /* least PIXEL_BITS*2 + 1 bits. On 16-bit systems, we need to use */+ /* `long' instead of `int', otherwise bad things happen */++#if PIXEL_BITS <= 7++ typedef int TArea;++#else /* PIXEL_BITS >= 8 */++ /* approximately determine the size of integers using an ANSI-C header */+#if FT_UINT_MAX == 0xFFFFU+ typedef long TArea;+#else+ typedef int TArea;+#endif++#endif /* PIXEL_BITS >= 8 */+++ /* maximal number of gray spans in a call to the span callback */+#define FT_MAX_GRAY_SPANS 32+++ typedef struct TCell_* PCell;++ typedef struct TCell_+ {+ TPos x; /* same with TWorker.ex */+ TCoord cover; /* same with TWorker.cover */+ TArea area;+ PCell next;++ } TCell;+++ typedef struct TWorker_+ {+ TCoord ex, ey;+ TPos min_ex, max_ex;+ TPos min_ey, max_ey;+ TPos count_ex, count_ey;++ TArea area;+ TCoord cover;+ int invalid;++ PCell cells;+ 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];++ FT_Outline outline;+ FT_Bitmap target;+ FT_BBox clip_box;++ FT_Span gray_spans[FT_MAX_GRAY_SPANS];+ int num_gray_spans;++ FT_Raster_Span_Func render_span;+ void* render_span_data;+ int span_y;++ int band_size;+ int band_shoot;++ ft_jmp_buf jump_buffer;++ void* buffer;+ long buffer_size;++ PCell* ycells;+ TPos ycount;++ } TWorker, *PWorker;+++#ifndef FT_STATIC_RASTER+#define ras (*worker)+#else+ static TWorker ras;+#endif+++ typedef struct TRaster_+ {+ void* buffer;+ long buffer_size;+ int band_size;+ void* memory;+ PWorker worker;++ } TRaster, *PRaster;++++ /*************************************************************************/+ /* */+ /* Initialize the cells table. */+ /* */+ static void+ gray_init_cells( RAS_ARG_ void* buffer,+ long byte_size )+ {+ ras.buffer = buffer;+ ras.buffer_size = byte_size;++ ras.ycells = (PCell*) buffer;+ ras.cells = NULL;+ ras.max_cells = 0;+ ras.num_cells = 0;+ ras.area = 0;+ ras.cover = 0;+ ras.invalid = 1;+ }+++ /*************************************************************************/+ /* */+ /* Compute the outline bounding box. */+ /* */+ static void+ gray_compute_cbox( RAS_ARG )+ {+ FT_Outline* outline = &ras.outline;+ FT_Vector* vec = outline->points;+ FT_Vector* limit = vec + outline->n_points;+++ if ( outline->n_points <= 0 )+ {+ ras.min_ex = ras.max_ex = 0;+ ras.min_ey = ras.max_ey = 0;+ return;+ }++ ras.min_ex = ras.max_ex = vec->x;+ ras.min_ey = ras.max_ey = vec->y;++ vec++;++ for ( ; vec < limit; vec++ )+ {+ TPos x = vec->x;+ TPos y = vec->y;+++ if ( x < ras.min_ex ) ras.min_ex = x;+ if ( x > ras.max_ex ) ras.max_ex = x;+ if ( y < ras.min_ey ) ras.min_ey = y;+ if ( y > ras.max_ey ) ras.max_ey = y;+ }++ /* truncate the bounding box to integer pixels */+ ras.min_ex = ras.min_ex >> 6;+ ras.min_ey = ras.min_ey >> 6;+ ras.max_ex = ( ras.max_ex + 63 ) >> 6;+ ras.max_ey = ( ras.max_ey + 63 ) >> 6;+ }+++ /*************************************************************************/+ /* */+ /* Record the current cell in the table. */+ /* */+ static PCell+ gray_find_cell( RAS_ARG )+ {+ PCell *pcell, cell;+ TPos x = ras.ex;+++ if ( x > ras.count_ex )+ x = ras.count_ex;++ pcell = &ras.ycells[ras.ey];+ for (;;)+ {+ cell = *pcell;+ if ( cell == NULL || cell->x > x )+ break;++ if ( cell->x == x )+ goto Exit;++ pcell = &cell->next;+ }++ if ( ras.num_cells >= ras.max_cells )+ ft_longjmp( ras.jump_buffer, 1 );++ cell = ras.cells + ras.num_cells++;+ cell->x = x;+ cell->area = 0;+ cell->cover = 0;++ cell->next = *pcell;+ *pcell = cell;++ Exit:+ return cell;+ }+++ static void+ gray_record_cell( RAS_ARG )+ {+ if ( !ras.invalid && ( ras.area | ras.cover ) )+ {+ PCell cell = gray_find_cell( RAS_VAR );+++ cell->area += ras.area;+ cell->cover += ras.cover;+ }+ }+++ /*************************************************************************/+ /* */+ /* Set the current cell to a new position. */+ /* */+ static void+ gray_set_cell( RAS_ARG_ TCoord ex,+ TCoord ey )+ {+ /* Move the cell pointer to a new position. We set the `invalid' */+ /* flag to indicate that the cell isn't part of those we're interested */+ /* in during the render phase. This means that: */+ /* */+ /* . the new vertical position must be within min_ey..max_ey-1. */+ /* . the new horizontal position must be strictly less than max_ex */+ /* */+ /* Note that if a cell is to the left of the clipping region, it is */+ /* actually set to the (min_ex-1) horizontal position. */++ /* All cells that are on the left of the clipping region go to the */+ /* min_ex - 1 horizontal position. */+ ey -= ras.min_ey;++ if ( ex > ras.max_ex )+ ex = ras.max_ex;++ ex -= ras.min_ex;+ if ( ex < 0 )+ ex = -1;++ /* are we moving to a different cell ? */+ if ( ex != ras.ex || ey != ras.ey )+ {+ /* record the current one if it is valid */+ if ( !ras.invalid )+ gray_record_cell( RAS_VAR );++ ras.area = 0;+ ras.cover = 0;+ }++ ras.ex = ex;+ ras.ey = ey;+ ras.invalid = ( (unsigned)ey >= (unsigned)ras.count_ey ||+ ex >= ras.count_ex );+ }+++ /*************************************************************************/+ /* */+ /* Start a new contour at a given cell. */+ /* */+ static void+ gray_start_cell( RAS_ARG_ TCoord ex,+ TCoord ey )+ {+ if ( ex > ras.max_ex )+ ex = (TCoord)( ras.max_ex );++ if ( ex < ras.min_ex )+ ex = (TCoord)( ras.min_ex - 1 );++ ras.area = 0;+ 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 );+ }+++ /*************************************************************************/+ /* */+ /* Render a scanline as one or more cells. */+ /* */+ static void+ gray_render_scanline( RAS_ARG_ TCoord ey,+ TPos x1,+ TCoord y1,+ TPos x2,+ TCoord y2 )+ {+ TCoord ex1, ex2, fx1, fx2, delta, mod, lift, rem;+ long p, first, dx;+ int incr;+++ dx = x2 - x1;++ ex1 = TRUNC( x1 );+ ex2 = TRUNC( x2 );+ fx1 = (TCoord)( x1 - SUBPIXELS( ex1 ) );+ fx2 = (TCoord)( x2 - SUBPIXELS( ex2 ) );++ /* trivial case. Happens often */+ if ( y1 == y2 )+ {+ gray_set_cell( RAS_VAR_ ex2, ey );+ return;+ }++ /* everything is located in a single cell. That is easy! */+ /* */+ if ( ex1 == ex2 )+ {+ delta = y2 - y1;+ ras.area += (TArea)(( fx1 + fx2 ) * delta);+ ras.cover += delta;+ return;+ }++ /* ok, we'll have to render a run of adjacent cells on the same */+ /* scanline... */+ /* */+ p = ( ONE_PIXEL - fx1 ) * ( y2 - y1 );+ first = ONE_PIXEL;+ incr = 1;++ if ( dx < 0 )+ {+ p = fx1 * ( y2 - y1 );+ first = 0;+ incr = -1;+ dx = -dx;+ }++ delta = (TCoord)( p / dx );+ mod = (TCoord)( p % dx );+ if ( mod < 0 )+ {+ delta--;+ mod += (TCoord)dx;+ }++ ras.area += (TArea)(( fx1 + first ) * delta);+ ras.cover += delta;++ ex1 += incr;+ gray_set_cell( RAS_VAR_ ex1, ey );+ y1 += delta;++ if ( ex1 != ex2 )+ {+ p = ONE_PIXEL * ( y2 - y1 + delta );+ lift = (TCoord)( p / dx );+ rem = (TCoord)( p % dx );+ if ( rem < 0 )+ {+ lift--;+ rem += (TCoord)dx;+ }++ mod -= (int)dx;++ while ( ex1 != ex2 )+ {+ delta = lift;+ mod += rem;+ if ( mod >= 0 )+ {+ mod -= (TCoord)dx;+ delta++;+ }++ ras.area += (TArea)(ONE_PIXEL * delta);+ ras.cover += delta;+ y1 += delta;+ ex1 += incr;+ gray_set_cell( RAS_VAR_ ex1, ey );+ }+ }++ delta = y2 - y1;+ ras.area += (TArea)(( fx2 + ONE_PIXEL - first ) * delta);+ ras.cover += delta;+ }+++ /*************************************************************************/+ /* */+ /* Render a given line as a series of scanlines. */+ /* */+ static void+ gray_render_line( RAS_ARG_ TPos to_x,+ TPos to_y )+ {+ TCoord ey1, ey2, fy1, fy2, mod;+ TPos dx, dy, x, x2;+ long p, first;+ int delta, rem, lift, incr;+++ ey1 = TRUNC( ras.last_ey );+ ey2 = TRUNC( to_y ); /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */+ fy1 = (TCoord)( ras.y - ras.last_ey );+ fy2 = (TCoord)( to_y - SUBPIXELS( ey2 ) );++ dx = to_x - ras.x;+ dy = to_y - ras.y;++ /* XXX: we should do something about the trivial case where dx == 0, */+ /* as it happens very often! */++ /* 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;+ }++ /* everything is on a single scanline */+ if ( ey1 == ey2 )+ {+ gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, to_x, fy2 );+ goto End;+ }++ /* vertical line - avoid calling gray_render_scanline */+ incr = 1;++ if ( dx == 0 )+ {+ TCoord ex = TRUNC( ras.x );+ TCoord two_fx = (TCoord)( ( ras.x - SUBPIXELS( ex ) ) << 1 );+ TArea area;+++ first = ONE_PIXEL;+ if ( dy < 0 )+ {+ first = 0;+ incr = -1;+ }++ delta = (int)( first - fy1 );+ ras.area += (TArea)two_fx * delta;+ ras.cover += delta;+ ey1 += incr;++ gray_set_cell( RAS_VAR_ ex, ey1 );++ delta = (int)( first + first - ONE_PIXEL );+ area = (TArea)two_fx * delta;+ while ( ey1 != ey2 )+ {+ ras.area += area;+ ras.cover += delta;+ ey1 += incr;++ gray_set_cell( RAS_VAR_ ex, ey1 );+ }++ delta = (int)( fy2 - ONE_PIXEL + first );+ ras.area += (TArea)two_fx * delta;+ ras.cover += delta;++ goto End;+ }++ /* ok, we have to render several scanlines */+ p = ( ONE_PIXEL - fy1 ) * dx;+ first = ONE_PIXEL;+ incr = 1;++ if ( dy < 0 )+ {+ p = fy1 * dx;+ first = 0;+ incr = -1;+ dy = -dy;+ }++ delta = (int)( p / dy );+ mod = (int)( p % dy );+ if ( mod < 0 )+ {+ delta--;+ mod += (TCoord)dy;+ }++ x = ras.x + delta;+ gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, x, (TCoord)first );++ ey1 += incr;+ gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );++ if ( ey1 != ey2 )+ {+ p = ONE_PIXEL * dx;+ lift = (int)( p / dy );+ rem = (int)( p % dy );+ if ( rem < 0 )+ {+ lift--;+ rem += (int)dy;+ }+ mod -= (int)dy;++ while ( ey1 != ey2 )+ {+ delta = lift;+ mod += rem;+ if ( mod >= 0 )+ {+ mod -= (int)dy;+ delta++;+ }++ x2 = x + delta;+ gray_render_scanline( RAS_VAR_ ey1, x,+ (TCoord)( ONE_PIXEL - first ), x2,+ (TCoord)first );+ x = x2;++ ey1 += incr;+ gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );+ }+ }++ gray_render_scanline( RAS_VAR_ ey1, x,+ (TCoord)( ONE_PIXEL - first ), to_x,+ fy2 );++ End:+ ras.x = to_x;+ ras.y = to_y;+ ras.last_ey = SUBPIXELS( ey2 );+ }+++ static void+ gray_split_conic( FT_Vector* base )+ {+ TPos a, b;+++ base[4].x = base[2].x;+ b = base[1].x;+ a = base[3].x = ( base[2].x + b ) / 2;+ b = base[1].x = ( base[0].x + b ) / 2;+ base[2].x = ( a + b ) / 2;++ base[4].y = base[2].y;+ b = base[1].y;+ a = base[3].y = ( base[2].y + b ) / 2;+ b = base[1].y = ( base[0].y + b ) / 2;+ base[2].y = ( a + b ) / 2;+ }+++ static void+ gray_render_conic( RAS_ARG_ const FT_Vector* control,+ const FT_Vector* to )+ {+ TPos dx, dy;+ int top, level;+ int* levels;+ FT_Vector* arc;+++ arc = ras.bez_stack;+ arc[0].x = UPSCALE( to->x );+ arc[0].y = UPSCALE( to->y );+ arc[1].x = UPSCALE( control->x );+ arc[1].y = UPSCALE( control->y );+ arc[2].x = ras.x;+ arc[2].y = ras.y;++ dx = FT_ABS( arc[2].x + arc[0].x - 2 * arc[1].x );+ dy = FT_ABS( arc[2].y + arc[0].y - 2 * arc[1].y );+ if ( dx < dy )+ dx = dy;++ if ( dx <= ONE_PIXEL / 4 )+ {+ gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );+ return;+ }++ level = 0;+ while ( dx > ONE_PIXEL / 4 )+ {+ dx >>= 2;+ level++;+ }++ levels = ras.lev_stack;+ levels[0] = level;+ top = 0;++ while ( top >= 0 )+ {+ level = levels[top];+ if ( level > 1 )+ {+ /* check that the arc crosses the current band */+ TPos min, max, y;+++ min = max = arc[0].y;++ y = arc[1].y;+ if ( y < min ) min = y;+ if ( y > max ) max = y;++ y = arc[2].y;+ if ( y < min ) min = y;+ if ( y > max ) max = y;++ if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey )+ goto Draw;++ gray_split_conic( arc );+ arc += 2;+ top++;+ levels[top] = levels[top - 1] = level - 1;+ continue;+ }++ Draw:+ gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );+ top--;+ arc -= 2;+ }++ return;+ }+++ static void+ gray_split_cubic( FT_Vector* base )+ {+ TPos a, b, c, d;+++ base[6].x = base[3].x;+ c = base[1].x;+ d = base[2].x;+ base[1].x = a = ( base[0].x + c ) / 2;+ base[5].x = b = ( base[3].x + d ) / 2;+ c = ( c + d ) / 2;+ base[2].x = a = ( a + c ) / 2;+ base[4].x = b = ( b + c ) / 2;+ base[3].x = ( a + b ) / 2;++ base[6].y = base[3].y;+ c = base[1].y;+ d = base[2].y;+ base[1].y = a = ( base[0].y + c ) / 2;+ base[5].y = b = ( base[3].y + d ) / 2;+ c = ( c + d ) / 2;+ base[2].y = a = ( a + c ) / 2;+ base[4].y = b = ( b + c ) / 2;+ base[3].y = ( a + b ) / 2;+ }+++ static void+ gray_render_cubic( RAS_ARG_ const FT_Vector* control1,+ const FT_Vector* control2,+ const FT_Vector* to )+ {+ FT_Vector* arc;+++ arc = ras.bez_stack;+ arc[0].x = UPSCALE( to->x );+ arc[0].y = UPSCALE( to->y );+ arc[1].x = UPSCALE( control2->x );+ arc[1].y = UPSCALE( control2->y );+ arc[2].x = UPSCALE( control1->x );+ arc[2].y = UPSCALE( control1->y );+ arc[3].x = ras.x;+ arc[3].y = ras.y;++ for (;;)+ {+ /* Check that the arc crosses the current band. */+ TPos min, max, y;+++ min = max = arc[0].y;++ y = arc[1].y;+ if ( y < min )+ min = y;+ if ( y > max )+ max = y;++ y = arc[2].y;+ if ( y < min )+ min = y;+ if ( y > max )+ max = y;++ y = arc[3].y;+ if ( y < min )+ min = y;+ if ( y > max )+ max = y;++ if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey )+ goto Draw;++ /* Decide whether to split or draw. See `Rapid Termination */+ /* Evaluation for Recursive Subdivision of Bezier Curves' by Thomas */+ /* F. Hain, at */+ /* http://www.cis.southalabama.edu/~hain/general/Publications/Bezier/Camera-ready%20CISST02%202.pdf */++ {+ TPos dx, dy, dx_, dy_;+ TPos dx1, dy1, dx2, dy2;+ TPos L, s, s_limit;+++ /* dx and dy are x and y components of the P0-P3 chord vector. */+ dx = arc[3].x - arc[0].x;+ dy = arc[3].y - arc[0].y;++ /* L is an (under)estimate of the Euclidean distance P0-P3. */+ /* */+ /* If dx >= dy, then r = sqrt(dx^2 + dy^2) can be overestimated */+ /* with least maximum error by */+ /* */+ /* r_upperbound = dx + (sqrt(2) - 1) * dy , */+ /* */+ /* where sqrt(2) - 1 can be (over)estimated by 107/256, giving an */+ /* error of no more than 8.4%. */+ /* */+ /* Similarly, some elementary calculus shows that r can be */+ /* underestimated with least maximum error by */+ /* */+ /* r_lowerbound = sqrt(2 + sqrt(2)) / 2 * dx */+ /* + sqrt(2 - sqrt(2)) / 2 * dy . */+ /* */+ /* 236/256 and 97/256 are (under)estimates of the two algebraic */+ /* numbers, giving an error of no more than 8.1%. */++ dx_ = FT_ABS( dx );+ dy_ = FT_ABS( dy );++ /* This is the same as */+ /* */+ /* L = ( 236 * FT_MAX( dx_, dy_ ) */+ /* + 97 * FT_MIN( dx_, dy_ ) ) >> 8; */+ L = ( dx_ > dy_ ? 236 * dx_ + 97 * dy_+ : 97 * dx_ + 236 * dy_ ) >> 8;++ /* Avoid possible arithmetic overflow below by splitting. */+ if ( L > 32767 )+ goto Split;++ /* Max deviation may be as much as (s/L) * 3/4 (if Hain's v = 1). */+ s_limit = L * (TPos)( ONE_PIXEL / 6 );++ /* s is L * the perpendicular distance from P1 to the line P0-P3. */+ dx1 = arc[1].x - arc[0].x;+ dy1 = arc[1].y - arc[0].y;+ s = FT_ABS( dy * dx1 - dx * dy1 );++ if ( s > s_limit )+ goto Split;++ /* s is L * the perpendicular distance from P2 to the line P0-P3. */+ dx2 = arc[2].x - arc[0].x;+ dy2 = arc[2].y - arc[0].y;+ s = FT_ABS( dy * dx2 - dx * dy2 );++ if ( s > s_limit )+ goto Split;++ /* If P1 or P2 is outside P0-P3, split the curve. */+ if ( dy * dy1 + dx * dx1 < 0 ||+ dy * dy2 + dx * dx2 < 0 ||+ dy * (arc[3].y - arc[1].y) + dx * (arc[3].x - arc[1].x) < 0 ||+ dy * (arc[3].y - arc[2].y) + dx * (arc[3].x - arc[2].x) < 0 )+ goto Split;++ /* No reason to split. */+ goto Draw;+ }++ Split:+ gray_split_cubic( arc );+ arc += 3;+ continue;++ Draw:+ gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );++ if ( arc == ras.bez_stack )+ return;++ arc -= 3;+ }+ }+++ static int+ gray_move_to( const FT_Vector* to,+ PWorker worker )+ {+ TPos x, y;+++ /* record current cell, if any */+ gray_record_cell( RAS_VAR );++ /* start to a new position */+ x = UPSCALE( to->x );+ y = UPSCALE( to->y );++ gray_start_cell( RAS_VAR_ TRUNC( x ), TRUNC( y ) );++ worker->x = x;+ worker->y = y;+ return 0;+ }+++ static int+ gray_line_to( const FT_Vector* to,+ PWorker worker )+ {+ gray_render_line( RAS_VAR_ UPSCALE( to->x ), UPSCALE( to->y ) );+ return 0;+ }+++ static int+ gray_conic_to( const FT_Vector* control,+ const FT_Vector* to,+ PWorker worker )+ {+ gray_render_conic( RAS_VAR_ control, to );+ return 0;+ }+++ static int+ gray_cubic_to( const FT_Vector* control1,+ const FT_Vector* control2,+ const FT_Vector* to,+ PWorker worker )+ {+ gray_render_cubic( RAS_VAR_ control1, control2, to );+ return 0;+ }+++ static void+ gray_render_span( int y,+ int count,+ const FT_Span* spans,+ PWorker worker )+ {+ unsigned char* p;+ FT_Bitmap* map = &worker->target;+++ /* first of all, compute the scanline offset */+ p = (unsigned char*)map->buffer - y * map->pitch;+ if ( map->pitch >= 0 )+ p += (unsigned)( ( map->rows - 1 ) * map->pitch );++ for ( ; count > 0; count--, spans++ )+ {+ unsigned char coverage = spans->coverage;+++ if ( coverage )+ {+ /* For small-spans it is faster to do it by ourselves than+ * calling `memset'. This is mainly due to the cost of the+ * function call.+ */+ if ( spans->len >= 8 )+ FT_MEM_SET( p + spans->x, (unsigned char)coverage, spans->len );+ else+ {+ unsigned char* q = p + spans->x;+++ switch ( spans->len )+ {+ case 7: *q++ = (unsigned char)coverage;+ case 6: *q++ = (unsigned char)coverage;+ case 5: *q++ = (unsigned char)coverage;+ case 4: *q++ = (unsigned char)coverage;+ case 3: *q++ = (unsigned char)coverage;+ case 2: *q++ = (unsigned char)coverage;+ case 1: *q = (unsigned char)coverage;+ default:+ ;+ }+ }+ }+ }+ }+++ static void+ gray_hline( RAS_ARG_ TCoord x,+ TCoord y,+ TPos area,+ TCoord acount )+ {+ FT_Span* span;+ int count;+ int coverage;+++ /* compute the coverage line's coverage, depending on the */+ /* outline fill rule */+ /* */+ /* the coverage percentage is area/(PIXEL_BITS*PIXEL_BITS*2) */+ /* */+ coverage = (int)( area >> ( PIXEL_BITS * 2 + 1 - 8 ) );+ /* use range 0..256 */+ if ( coverage < 0 )+ coverage = -coverage;++ if ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL )+ {+ coverage &= 511;++ if ( coverage > 256 )+ coverage = 512 - coverage;+ else if ( coverage == 256 )+ coverage = 255;+ }+ else+ {+ /* normal non-zero winding rule */+ if ( coverage >= 256 )+ coverage = 255;+ }++ y += (TCoord)ras.min_ey;+ x += (TCoord)ras.min_ex;++ /* FT_Span.x is a 16-bit short, so limit our coordinates appropriately */+ if ( x >= 32767 )+ x = 32767;++ /* FT_Span.y is an integer, so limit our coordinates appropriately */+ if ( y >= FT_INT_MAX )+ y = FT_INT_MAX;++ if ( coverage )+ {+ /* see whether we can add this span to the current list */+ count = ras.num_gray_spans;+ span = ras.gray_spans + count - 1;+ if ( count > 0 &&+ ras.span_y == y &&+ (int)span->x + span->len == (int)x &&+ span->coverage == coverage )+ {+ span->len = (unsigned short)( span->len + acount );+ return;+ }++ if ( ras.span_y != y || count >= FT_MAX_GRAY_SPANS )+ {+ if ( ras.render_span && count > 0 )+ ras.render_span( ras.span_y, count, ras.gray_spans,+ ras.render_span_data );++#ifdef FT_DEBUG_LEVEL_TRACE++ if ( count > 0 )+ {+ int n;+++ FT_TRACE7(( "y = %3d ", ras.span_y ));+ span = ras.gray_spans;+ for ( n = 0; n < count; n++, span++ )+ FT_TRACE7(( "[%d..%d]:%02x ",+ span->x, span->x + span->len - 1, span->coverage ));+ FT_TRACE7(( "\n" ));+ }++#endif /* FT_DEBUG_LEVEL_TRACE */++ ras.num_gray_spans = 0;+ ras.span_y = (int)y;++ count = 0;+ span = ras.gray_spans;+ }+ else+ span++;++ /* add a gray span to the current list */+ span->x = (short)x;+ span->len = (unsigned short)acount;+ span->coverage = (unsigned char)coverage;++ ras.num_gray_spans++;+ }+ }+++#ifdef FT_DEBUG_LEVEL_TRACE++ /* to be called while in the debugger -- */+ /* this function causes a compiler warning since it is unused otherwise */+ static void+ gray_dump_cells( RAS_ARG )+ {+ int yindex;+++ for ( yindex = 0; yindex < ras.ycount; yindex++ )+ {+ PCell cell;+++ printf( "%3d:", yindex );++ for ( cell = ras.ycells[yindex]; cell != NULL; cell = cell->next )+ printf( " (%3ld, c:%4ld, a:%6d)", cell->x, cell->cover, cell->area );+ printf( "\n" );+ }+ }++#endif /* FT_DEBUG_LEVEL_TRACE */+++ static void+ gray_sweep( RAS_ARG_ const FT_Bitmap* target )+ {+ int yindex;++ FT_UNUSED( target );+++ if ( ras.num_cells == 0 )+ return;++ ras.num_gray_spans = 0;++ FT_TRACE7(( "gray_sweep: start\n" ));++ for ( yindex = 0; yindex < ras.ycount; yindex++ )+ {+ PCell cell = ras.ycells[yindex];+ TCoord cover = 0;+ TCoord x = 0;+++ for ( ; cell != NULL; cell = cell->next )+ {+ TPos area;+++ if ( cell->x > x && cover != 0 )+ gray_hline( RAS_VAR_ x, yindex, cover * ( ONE_PIXEL * 2 ),+ cell->x - x );++ cover += cell->cover;+ area = cover * ( ONE_PIXEL * 2 ) - cell->area;++ if ( area != 0 && cell->x >= 0 )+ gray_hline( RAS_VAR_ cell->x, yindex, area, 1 );++ x = cell->x + 1;+ }++ if ( cover != 0 )+ gray_hline( RAS_VAR_ x, yindex, cover * ( ONE_PIXEL * 2 ),+ ras.count_ex - x );+ }++ if ( ras.render_span && ras.num_gray_spans > 0 )+ ras.render_span( ras.span_y, ras.num_gray_spans,+ ras.gray_spans, ras.render_span_data );++ FT_TRACE7(( "gray_sweep: end\n" ));+ }+++#ifdef _STANDALONE_++ /*************************************************************************/+ /* */+ /* The following function should only compile in stand-alone mode, */+ /* i.e., when building this component without the rest of FreeType. */+ /* */+ /*************************************************************************/++ /*************************************************************************/+ /* */+ /* <Function> */+ /* FT_Outline_Decompose */+ /* */+ /* <Description> */+ /* Walk over an outline's structure to decompose it into individual */+ /* segments and Bézier arcs. This function is also able to emit */+ /* `move to' and `close to' operations to indicate the start and end */+ /* of new contours in the outline. */+ /* */+ /* <Input> */+ /* outline :: A pointer to the source target. */+ /* */+ /* func_interface :: A table of `emitters', i.e., function pointers */+ /* called during decomposition to indicate path */+ /* operations. */+ /* */+ /* <InOut> */+ /* user :: A typeless pointer which is passed to each */+ /* emitter during the decomposition. It can be */+ /* used to store the state during the */+ /* decomposition. */+ /* */+ /* <Return> */+ /* Error code. 0 means success. */+ /* */+ static int+ FT_Outline_Decompose( const FT_Outline* outline,+ const FT_Outline_Funcs* func_interface,+ void* user )+ {+#undef SCALED+#define SCALED( x ) ( ( (x) << shift ) - delta )++ FT_Vector v_last;+ FT_Vector v_control;+ FT_Vector v_start;++ FT_Vector* point;+ FT_Vector* limit;+ char* tags;++ int error;++ int n; /* index of contour in outline */+ int first; /* index of first point in contour */+ char tag; /* current point's state */++ int shift;+ TPos delta;+++ if ( !outline || !func_interface )+ return ErrRaster_Invalid_Argument;++ shift = func_interface->shift;+ delta = func_interface->delta;+ first = 0;++ for ( n = 0; n < outline->n_contours; n++ )+ {+ int last; /* index of last point in contour */+++ FT_TRACE5(( "FT_Outline_Decompose: Outline %d\n", n ));++ last = outline->contours[n];+ if ( last < 0 )+ goto Invalid_Outline;+ limit = outline->points + last;++ v_start = outline->points[first];+ v_start.x = SCALED( v_start.x );+ v_start.y = SCALED( v_start.y );++ v_last = outline->points[last];+ v_last.x = SCALED( v_last.x );+ v_last.y = SCALED( v_last.y );++ v_control = v_start;++ point = outline->points + first;+ tags = outline->tags + first;+ tag = FT_CURVE_TAG( tags[0] );++ /* A contour cannot start with a cubic control point! */+ if ( tag == FT_CURVE_TAG_CUBIC )+ goto Invalid_Outline;++ /* check first point to determine origin */+ if ( tag == FT_CURVE_TAG_CONIC )+ {+ /* first point is conic control. Yes, this happens. */+ if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON )+ {+ /* start at last point if it is on the curve */+ v_start = v_last;+ limit--;+ }+ else+ {+ /* if both first and last points are conic, */+ /* start at their middle and record its position */+ /* for closure */+ v_start.x = ( v_start.x + v_last.x ) / 2;+ v_start.y = ( v_start.y + v_last.y ) / 2;++ v_last = v_start;+ }+ point--;+ tags--;+ }++ FT_TRACE5(( " move to (%.2f, %.2f)\n",+ v_start.x / 64.0, v_start.y / 64.0 ));+ error = func_interface->move_to( &v_start, user );+ if ( error )+ goto Exit;++ while ( point < limit )+ {+ point++;+ tags++;++ tag = FT_CURVE_TAG( tags[0] );+ switch ( tag )+ {+ case FT_CURVE_TAG_ON: /* emit a single line_to */+ {+ FT_Vector vec;+++ vec.x = SCALED( point->x );+ vec.y = SCALED( point->y );++ FT_TRACE5(( " line to (%.2f, %.2f)\n",+ vec.x / 64.0, vec.y / 64.0 ));+ error = func_interface->line_to( &vec, user );+ if ( error )+ goto Exit;+ continue;+ }++ case FT_CURVE_TAG_CONIC: /* consume conic arcs */+ v_control.x = SCALED( point->x );+ v_control.y = SCALED( point->y );++ Do_Conic:+ if ( point < limit )+ {+ FT_Vector vec;+ FT_Vector v_middle;+++ point++;+ tags++;+ tag = FT_CURVE_TAG( tags[0] );++ vec.x = SCALED( point->x );+ vec.y = SCALED( point->y );++ if ( tag == FT_CURVE_TAG_ON )+ {+ FT_TRACE5(( " conic to (%.2f, %.2f)"+ " with control (%.2f, %.2f)\n",+ vec.x / 64.0, vec.y / 64.0,+ v_control.x / 64.0, v_control.y / 64.0 ));+ error = func_interface->conic_to( &v_control, &vec, user );+ if ( error )+ goto Exit;+ continue;+ }++ if ( tag != FT_CURVE_TAG_CONIC )+ goto Invalid_Outline;++ v_middle.x = ( v_control.x + vec.x ) / 2;+ v_middle.y = ( v_control.y + vec.y ) / 2;++ FT_TRACE5(( " conic to (%.2f, %.2f)"+ " with control (%.2f, %.2f)\n",+ v_middle.x / 64.0, v_middle.y / 64.0,+ v_control.x / 64.0, v_control.y / 64.0 ));+ error = func_interface->conic_to( &v_control, &v_middle, user );+ if ( error )+ goto Exit;++ v_control = vec;+ goto Do_Conic;+ }++ FT_TRACE5(( " conic to (%.2f, %.2f)"+ " with control (%.2f, %.2f)\n",+ v_start.x / 64.0, v_start.y / 64.0,+ v_control.x / 64.0, v_control.y / 64.0 ));+ error = func_interface->conic_to( &v_control, &v_start, user );+ goto Close;++ default: /* FT_CURVE_TAG_CUBIC */+ {+ FT_Vector vec1, vec2;+++ if ( point + 1 > limit ||+ FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )+ goto Invalid_Outline;++ point += 2;+ tags += 2;++ vec1.x = SCALED( point[-2].x );+ vec1.y = SCALED( point[-2].y );++ vec2.x = SCALED( point[-1].x );+ vec2.y = SCALED( point[-1].y );++ if ( point <= limit )+ {+ FT_Vector vec;+++ vec.x = SCALED( point->x );+ vec.y = SCALED( point->y );++ FT_TRACE5(( " cubic to (%.2f, %.2f)"+ " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",+ vec.x / 64.0, vec.y / 64.0,+ vec1.x / 64.0, vec1.y / 64.0,+ vec2.x / 64.0, vec2.y / 64.0 ));+ error = func_interface->cubic_to( &vec1, &vec2, &vec, user );+ if ( error )+ goto Exit;+ continue;+ }++ FT_TRACE5(( " cubic to (%.2f, %.2f)"+ " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",+ v_start.x / 64.0, v_start.y / 64.0,+ vec1.x / 64.0, vec1.y / 64.0,+ vec2.x / 64.0, vec2.y / 64.0 ));+ error = func_interface->cubic_to( &vec1, &vec2, &v_start, user );+ goto Close;+ }+ }+ }++ /* close the contour with a line segment */+ FT_TRACE5(( " line to (%.2f, %.2f)\n",+ v_start.x / 64.0, v_start.y / 64.0 ));+ error = func_interface->line_to( &v_start, user );++ Close:+ if ( error )+ goto Exit;++ first = last + 1;+ }++ FT_TRACE5(( "FT_Outline_Decompose: Done\n", n ));+ return 0;++ Exit:+ FT_TRACE5(( "FT_Outline_Decompose: Error %d\n", error ));+ return error;++ Invalid_Outline:+ return ErrRaster_Invalid_Outline;+ }++#endif /* _STANDALONE_ */+++ typedef struct TBand_+ {+ TPos min, max;++ } TBand;++ FT_DEFINE_OUTLINE_FUNCS(func_interface,+ (FT_Outline_MoveTo_Func) gray_move_to,+ (FT_Outline_LineTo_Func) gray_line_to,+ (FT_Outline_ConicTo_Func)gray_conic_to,+ (FT_Outline_CubicTo_Func)gray_cubic_to,+ 0,+ 0+ )++ static int+ gray_convert_glyph_inner( RAS_ARG )+ {++ volatile int error = 0;++#ifdef FT_CONFIG_OPTION_PIC+ FT_Outline_Funcs func_interface;+ Init_Class_func_interface(&func_interface);+#endif++ if ( ft_setjmp( ras.jump_buffer ) == 0 )+ {+ error = FT_Outline_Decompose( &ras.outline, &func_interface, &ras );+ gray_record_cell( RAS_VAR );+ }+ else+ error = ErrRaster_Memory_Overflow;++ return error;+ }+++ static int+ gray_convert_glyph( RAS_ARG )+ {+ TBand bands[40];+ TBand* volatile band;+ int volatile n, num_bands;+ TPos volatile min, max, max_y;+ FT_BBox* clip;+++ /* Set up state in the raster object */+ gray_compute_cbox( RAS_VAR );++ /* clip to target bitmap, exit if nothing to do */+ clip = &ras.clip_box;++ if ( ras.max_ex <= clip->xMin || ras.min_ex >= clip->xMax ||+ ras.max_ey <= clip->yMin || ras.min_ey >= clip->yMax )+ return 0;++ if ( ras.min_ex < clip->xMin ) ras.min_ex = clip->xMin;+ if ( ras.min_ey < clip->yMin ) ras.min_ey = clip->yMin;++ if ( ras.max_ex > clip->xMax ) ras.max_ex = clip->xMax;+ if ( ras.max_ey > clip->yMax ) ras.max_ey = clip->yMax;++ ras.count_ex = ras.max_ex - ras.min_ex;+ ras.count_ey = ras.max_ey - ras.min_ey;++ /* set up vertical bands */+ num_bands = (int)( ( ras.max_ey - ras.min_ey ) / ras.band_size );+ if ( num_bands == 0 )+ num_bands = 1;+ if ( num_bands >= 39 )+ num_bands = 39;++ ras.band_shoot = 0;++ min = ras.min_ey;+ max_y = ras.max_ey;++ for ( n = 0; n < num_bands; n++, min = max )+ {+ max = min + ras.band_size;+ if ( n == num_bands - 1 || max > max_y )+ max = max_y;++ bands[0].min = min;+ bands[0].max = max;+ band = bands;++ while ( band >= bands )+ {+ TPos bottom, top, middle;+ int error;++ {+ PCell cells_max;+ int yindex;+ long cell_start, cell_end, cell_mod;+++ ras.ycells = (PCell*)ras.buffer;+ ras.ycount = band->max - band->min;++ cell_start = sizeof ( PCell ) * ras.ycount;+ cell_mod = cell_start % sizeof ( TCell );+ if ( cell_mod > 0 )+ cell_start += sizeof ( TCell ) - cell_mod;++ cell_end = ras.buffer_size;+ cell_end -= cell_end % sizeof( TCell );++ cells_max = (PCell)( (char*)ras.buffer + cell_end );+ ras.cells = (PCell)( (char*)ras.buffer + cell_start );+ if ( ras.cells >= cells_max )+ goto ReduceBands;++ ras.max_cells = cells_max - ras.cells;+ if ( ras.max_cells < 2 )+ goto ReduceBands;++ for ( yindex = 0; yindex < ras.ycount; yindex++ )+ ras.ycells[yindex] = NULL;+ }++ ras.num_cells = 0;+ ras.invalid = 1;+ ras.min_ey = band->min;+ ras.max_ey = band->max;+ ras.count_ey = band->max - band->min;++ error = gray_convert_glyph_inner( RAS_VAR );++ if ( !error )+ {+ gray_sweep( RAS_VAR_ &ras.target );+ band--;+ continue;+ }+ else if ( error != ErrRaster_Memory_Overflow )+ return 1;++ ReduceBands:+ /* render pool overflow; we will reduce the render band by half */+ bottom = band->min;+ top = band->max;+ middle = bottom + ( ( top - bottom ) >> 1 );++ /* This is too complex for a single scanline; there must */+ /* be some problems. */+ if ( middle == bottom )+ {+#ifdef FT_DEBUG_LEVEL_TRACE+ FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" ));+#endif+ return 1;+ }++ if ( bottom-top >= ras.band_size )+ ras.band_shoot++;++ band[1].min = bottom;+ band[1].max = middle;+ band[0].min = middle;+ band[0].max = top;+ band++;+ }+ }++ if ( ras.band_shoot > 8 && ras.band_size > 16 )+ ras.band_size = ras.band_size / 2;++ return 0;+ }+++ static int+ gray_raster_render( PRaster raster,+ const FT_Raster_Params* params )+ {+ const FT_Outline* outline = (const FT_Outline*)params->source;+ const FT_Bitmap* target_map = params->target;+ PWorker worker;+++ if ( !raster || !raster->buffer || !raster->buffer_size )+ return ErrRaster_Invalid_Argument;++ if ( !outline )+ return ErrRaster_Invalid_Outline;++ /* return immediately if the outline is empty */+ if ( outline->n_points == 0 || outline->n_contours <= 0 )+ return 0;++ if ( !outline->contours || !outline->points )+ return ErrRaster_Invalid_Outline;++ if ( outline->n_points !=+ outline->contours[outline->n_contours - 1] + 1 )+ return ErrRaster_Invalid_Outline;++ worker = raster->worker;++ /* if direct mode is not set, we must have a target bitmap */+ if ( !( params->flags & FT_RASTER_FLAG_DIRECT ) )+ {+ if ( !target_map )+ return ErrRaster_Invalid_Argument;++ /* nothing to do */+ if ( !target_map->width || !target_map->rows )+ return 0;++ if ( !target_map->buffer )+ return ErrRaster_Invalid_Argument;+ }++ /* this version does not support monochrome rendering */+ if ( !( params->flags & FT_RASTER_FLAG_AA ) )+ return ErrRaster_Invalid_Mode;++ /* compute clipping box */+ if ( !( params->flags & FT_RASTER_FLAG_DIRECT ) )+ {+ /* compute clip box from target pixmap */+ ras.clip_box.xMin = 0;+ ras.clip_box.yMin = 0;+ ras.clip_box.xMax = target_map->width;+ ras.clip_box.yMax = target_map->rows;+ }+ else if ( params->flags & FT_RASTER_FLAG_CLIP )+ ras.clip_box = params->clip_box;+ else+ {+ ras.clip_box.xMin = -32768L;+ ras.clip_box.yMin = -32768L;+ ras.clip_box.xMax = 32767L;+ ras.clip_box.yMax = 32767L;+ }++ gray_init_cells( RAS_VAR_ raster->buffer, raster->buffer_size );++ ras.outline = *outline;+ ras.num_cells = 0;+ ras.invalid = 1;+ ras.band_size = raster->band_size;+ ras.num_gray_spans = 0;++ if ( params->flags & FT_RASTER_FLAG_DIRECT )+ {+ ras.render_span = (FT_Raster_Span_Func)params->gray_spans;+ ras.render_span_data = params->user;+ }+ else+ {+ ras.target = *target_map;+ ras.render_span = (FT_Raster_Span_Func)gray_render_span;+ ras.render_span_data = &ras;+ }++ return gray_convert_glyph( RAS_VAR );+ }+++ /**** RASTER OBJECT CREATION: In stand-alone mode, we simply use *****/+ /**** a static object. *****/++#ifdef _STANDALONE_++ static int+ gray_raster_new( void* memory,+ FT_Raster* araster )+ {+ static TRaster the_raster;++ FT_UNUSED( memory );+++ *araster = (FT_Raster)&the_raster;+ FT_MEM_ZERO( &the_raster, sizeof ( the_raster ) );++ return 0;+ }+++ static void+ gray_raster_done( FT_Raster raster )+ {+ /* nothing */+ FT_UNUSED( raster );+ }++#else /* !_STANDALONE_ */++ static int+ gray_raster_new( FT_Memory memory,+ FT_Raster* araster )+ {+ FT_Error error;+ PRaster raster = NULL;+++ *araster = 0;+ if ( !FT_ALLOC( raster, sizeof ( TRaster ) ) )+ {+ raster->memory = memory;+ *araster = (FT_Raster)raster;+ }++ return error;+ }+++ static void+ gray_raster_done( FT_Raster raster )+ {+ FT_Memory memory = (FT_Memory)((PRaster)raster)->memory;+++ FT_FREE( raster );+ }++#endif /* !_STANDALONE_ */+++ static void+ gray_raster_reset( FT_Raster raster,+ char* pool_base,+ long pool_size )+ {+ PRaster rast = (PRaster)raster;+++ if ( raster )+ {+ if ( pool_base && pool_size >= (long)sizeof ( TWorker ) + 2048 )+ {+ PWorker worker = (PWorker)pool_base;+++ rast->worker = worker;+ rast->buffer = pool_base ++ ( ( sizeof ( TWorker ) + sizeof ( TCell ) - 1 ) &+ ~( sizeof ( TCell ) - 1 ) );+ rast->buffer_size = (long)( ( pool_base + pool_size ) -+ (char*)rast->buffer ) &+ ~( sizeof ( TCell ) - 1 );+ rast->band_size = (int)( rast->buffer_size /+ ( sizeof ( TCell ) * 8 ) );+ }+ else+ {+ rast->buffer = NULL;+ rast->buffer_size = 0;+ rast->worker = NULL;+ }+ }+ }+++ FT_DEFINE_RASTER_FUNCS(ft_grays_raster,+ FT_GLYPH_FORMAT_OUTLINE,++ (FT_Raster_New_Func) gray_raster_new,+ (FT_Raster_Reset_Func) gray_raster_reset,+ (FT_Raster_Set_Mode_Func)0,+ (FT_Raster_Render_Func) gray_raster_render,+ (FT_Raster_Done_Func) gray_raster_done+ )+++/* END */+++/* Local Variables: */+/* coding: utf-8 */+/* End: */
+ src/smooth/ftgrays.h view
@@ -0,0 +1,58 @@+/***************************************************************************/+/* */+/* ftgrays.h */+/* */+/* FreeType smooth renderer declaration */+/* */+/* Copyright 1996-2001 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 __FTGRAYS_H__+#define __FTGRAYS_H__++#ifdef __cplusplus+ extern "C" {+#endif+++#ifdef _STANDALONE_+#include "ftimage.h"+#else+#include <ft2build.h>+#include FT_CONFIG_CONFIG_H /* for FT_CONFIG_OPTION_PIC */+#include FT_IMAGE_H+#endif+++ /*************************************************************************/+ /* */+ /* To make ftgrays.h independent from configuration files we check */+ /* whether FT_EXPORT_VAR has been defined already. */+ /* */+ /* On some systems and compilers (Win32 mostly), an extra keyword is */+ /* necessary to compile the library as a DLL. */+ /* */+#ifndef FT_EXPORT_VAR+#define FT_EXPORT_VAR( x ) extern x+#endif++ FT_EXPORT_VAR( const FT_Raster_Funcs ) ft_grays_raster;+++#ifdef __cplusplus+ }+#endif++#endif /* __FTGRAYS_H__ */+++/* END */
+ src/smooth/ftsmerrs.h view
@@ -0,0 +1,41 @@+/***************************************************************************/+/* */+/* ftsmerrs.h */+/* */+/* smooth renderer error codes (specification only). */+/* */+/* Copyright 2001 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 smooth renderer error enumeration */+ /* constants. */+ /* */+ /*************************************************************************/++#ifndef __FTSMERRS_H__+#define __FTSMERRS_H__++#include FT_MODULE_ERRORS_H++#undef __FTERRORS_H__++#define FT_ERR_PREFIX Smooth_Err_+#define FT_ERR_BASE FT_Mod_Err_Smooth++#include FT_ERRORS_H++#endif /* __FTSMERRS_H__ */+++/* END */
+ src/smooth/ftsmooth.c view
@@ -0,0 +1,499 @@+/***************************************************************************/+/* */+/* ftsmooth.c */+/* */+/* Anti-aliasing renderer interface (body). */+/* */+/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2009, 2010 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_OUTLINE_H+#include "ftsmooth.h"+#include "ftgrays.h"+#include "ftspic.h"++#include "ftsmerrs.h"+++ /* initialize renderer -- init its raster */+ static FT_Error+ ft_smooth_init( FT_Renderer render )+ {+ FT_Library library = FT_MODULE_LIBRARY( render );+++ render->clazz->raster_class->raster_reset( render->raster,+ library->raster_pool,+ library->raster_pool_size );++ return 0;+ }+++ /* sets render-specific mode */+ static FT_Error+ ft_smooth_set_mode( FT_Renderer render,+ FT_ULong mode_tag,+ FT_Pointer data )+ {+ /* we simply pass it to the raster */+ return render->clazz->raster_class->raster_set_mode( render->raster,+ mode_tag,+ data );+ }++ /* transform a given glyph image */+ static FT_Error+ ft_smooth_transform( FT_Renderer render,+ FT_GlyphSlot slot,+ const FT_Matrix* matrix,+ const FT_Vector* delta )+ {+ FT_Error error = Smooth_Err_Ok;+++ if ( slot->format != render->glyph_format )+ {+ error = Smooth_Err_Invalid_Argument;+ goto Exit;+ }++ if ( matrix )+ FT_Outline_Transform( &slot->outline, matrix );++ if ( delta )+ FT_Outline_Translate( &slot->outline, delta->x, delta->y );++ Exit:+ return error;+ }+++ /* return the glyph's control box */+ static void+ ft_smooth_get_cbox( FT_Renderer render,+ FT_GlyphSlot slot,+ FT_BBox* cbox )+ {+ FT_MEM_ZERO( cbox, sizeof ( *cbox ) );++ if ( slot->format == render->glyph_format )+ FT_Outline_Get_CBox( &slot->outline, cbox );+ }+++ /* convert a slot's glyph image into a bitmap */+ static FT_Error+ ft_smooth_render_generic( FT_Renderer render,+ FT_GlyphSlot slot,+ FT_Render_Mode mode,+ const FT_Vector* origin,+ FT_Render_Mode required_mode )+ {+ FT_Error error;+ FT_Outline* outline = NULL;+ FT_BBox cbox;+ FT_UInt width, height, height_org, width_org, pitch;+ FT_Bitmap* bitmap;+ FT_Memory memory;+ FT_Int hmul = mode == FT_RENDER_MODE_LCD;+ FT_Int vmul = mode == FT_RENDER_MODE_LCD_V;+ FT_Pos x_shift, y_shift, x_left, y_top;++ FT_Raster_Params params;+++ /* check glyph image format */+ if ( slot->format != render->glyph_format )+ {+ error = Smooth_Err_Invalid_Argument;+ goto Exit;+ }++ /* check mode */+ if ( mode != required_mode )+ return Smooth_Err_Cannot_Render_Glyph;++ outline = &slot->outline;++ /* translate the outline to the new origin if needed */+ if ( origin )+ FT_Outline_Translate( outline, origin->x, origin->y );++ /* compute the control box, and grid fit it */+ FT_Outline_Get_CBox( outline, &cbox );++ cbox.xMin = FT_PIX_FLOOR( cbox.xMin );+ cbox.yMin = FT_PIX_FLOOR( cbox.yMin );+ cbox.xMax = FT_PIX_CEIL( cbox.xMax );+ cbox.yMax = FT_PIX_CEIL( cbox.yMax );++ if ( cbox.xMin < 0 && cbox.xMax > FT_INT_MAX + cbox.xMin )+ {+ FT_ERROR(( "ft_smooth_render_generic: glyph too large:"+ " xMin = %d, xMax = %d\n",+ cbox.xMin >> 6, cbox.xMax >> 6 ));+ return Smooth_Err_Raster_Overflow;+ }+ else+ width = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 );++ if ( cbox.yMin < 0 && cbox.yMax > FT_INT_MAX + cbox.yMin )+ {+ FT_ERROR(( "ft_smooth_render_generic: glyph too large:"+ " yMin = %d, yMax = %d\n",+ cbox.yMin >> 6, cbox.yMax >> 6 ));+ return Smooth_Err_Raster_Overflow;+ }+ else+ height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 );++ bitmap = &slot->bitmap;+ memory = render->root.memory;++ width_org = width;+ height_org = height;++ /* release old bitmap buffer */+ if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )+ {+ FT_FREE( bitmap->buffer );+ slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;+ }++ /* allocate new one */+ pitch = width;+ if ( hmul )+ {+ width = width * 3;+ pitch = FT_PAD_CEIL( width, 4 );+ }++ if ( vmul )+ height *= 3;++ x_shift = (FT_Int) cbox.xMin;+ y_shift = (FT_Int) cbox.yMin;+ x_left = (FT_Int)( cbox.xMin >> 6 );+ y_top = (FT_Int)( cbox.yMax >> 6 );++#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING++ if ( slot->library->lcd_filter_func )+ {+ FT_Int extra = slot->library->lcd_extra;+++ if ( hmul )+ {+ x_shift -= 64 * ( extra >> 1 );+ width += 3 * extra;+ pitch = FT_PAD_CEIL( width, 4 );+ x_left -= extra >> 1;+ }++ if ( vmul )+ {+ y_shift -= 64 * ( extra >> 1 );+ height += 3 * extra;+ y_top += extra >> 1;+ }+ }++#endif++#if FT_UINT_MAX > 0xFFFFU++ /* Required check is ( pitch * height < FT_ULONG_MAX ), */+ /* but we care realistic cases only. Always pitch <= width. */+ if ( width > 0x7FFFU || height > 0x7FFFU )+ {+ FT_ERROR(( "ft_smooth_render_generic: glyph too large: %u x %u\n",+ width, height ));+ return Smooth_Err_Raster_Overflow;+ }++#endif++ bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;+ bitmap->num_grays = 256;+ bitmap->width = width;+ bitmap->rows = height;+ bitmap->pitch = pitch;++ /* translate outline to render it into the bitmap */+ FT_Outline_Translate( outline, -x_shift, -y_shift );++ if ( FT_ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) )+ goto Exit;++ slot->internal->flags |= FT_GLYPH_OWN_BITMAP;++ /* set up parameters */+ params.target = bitmap;+ params.source = outline;+ params.flags = FT_RASTER_FLAG_AA;++#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING++ /* implode outline if needed */+ {+ FT_Vector* points = outline->points;+ FT_Vector* points_end = points + outline->n_points;+ FT_Vector* vec;+++ if ( hmul )+ for ( vec = points; vec < points_end; vec++ )+ vec->x *= 3;++ if ( vmul )+ for ( vec = points; vec < points_end; vec++ )+ vec->y *= 3;+ }++ /* render outline into the bitmap */+ error = render->raster_render( render->raster, ¶ms );++ /* deflate outline if needed */+ {+ FT_Vector* points = outline->points;+ FT_Vector* points_end = points + outline->n_points;+ FT_Vector* vec;+++ if ( hmul )+ for ( vec = points; vec < points_end; vec++ )+ vec->x /= 3;++ if ( vmul )+ for ( vec = points; vec < points_end; vec++ )+ vec->y /= 3;+ }++ if ( slot->library->lcd_filter_func )+ slot->library->lcd_filter_func( bitmap, mode, slot->library );++#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */++ /* render outline into bitmap */+ error = render->raster_render( render->raster, ¶ms );++ /* expand it horizontally */+ if ( hmul )+ {+ FT_Byte* line = bitmap->buffer;+ FT_UInt hh;+++ for ( hh = height_org; hh > 0; hh--, line += pitch )+ {+ FT_UInt xx;+ FT_Byte* end = line + width;+++ for ( xx = width_org; xx > 0; xx-- )+ {+ FT_UInt pixel = line[xx-1];+++ end[-3] = (FT_Byte)pixel;+ end[-2] = (FT_Byte)pixel;+ end[-1] = (FT_Byte)pixel;+ end -= 3;+ }+ }+ }++ /* expand it vertically */+ if ( vmul )+ {+ FT_Byte* read = bitmap->buffer + ( height - height_org ) * pitch;+ FT_Byte* write = bitmap->buffer;+ FT_UInt hh;+++ for ( hh = height_org; hh > 0; hh-- )+ {+ ft_memcpy( write, read, pitch );+ write += pitch;++ ft_memcpy( write, read, pitch );+ write += pitch;++ ft_memcpy( write, read, pitch );+ write += pitch;+ read += pitch;+ }+ }++#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */++ FT_Outline_Translate( outline, x_shift, y_shift );++ /*+ * XXX: on 16bit system, we return an error for huge bitmap+ * to prevent an overflow.+ */+ if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX )+ return Smooth_Err_Invalid_Pixel_Size;++ if ( error )+ goto Exit;++ slot->format = FT_GLYPH_FORMAT_BITMAP;+ slot->bitmap_left = (FT_Int)x_left;+ slot->bitmap_top = (FT_Int)y_top;++ Exit:+ if ( outline && origin )+ FT_Outline_Translate( outline, -origin->x, -origin->y );++ return error;+ }+++ /* convert a slot's glyph image into a bitmap */+ static FT_Error+ ft_smooth_render( FT_Renderer render,+ FT_GlyphSlot slot,+ FT_Render_Mode mode,+ const FT_Vector* origin )+ {+ if ( mode == FT_RENDER_MODE_LIGHT )+ mode = FT_RENDER_MODE_NORMAL;++ return ft_smooth_render_generic( render, slot, mode, origin,+ FT_RENDER_MODE_NORMAL );+ }+++ /* convert a slot's glyph image into a horizontal LCD bitmap */+ static FT_Error+ ft_smooth_render_lcd( FT_Renderer render,+ FT_GlyphSlot slot,+ FT_Render_Mode mode,+ const FT_Vector* origin )+ {+ FT_Error error;++ error = ft_smooth_render_generic( render, slot, mode, origin,+ FT_RENDER_MODE_LCD );+ if ( !error )+ slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD;++ return error;+ }+++ /* convert a slot's glyph image into a vertical LCD bitmap */+ static FT_Error+ ft_smooth_render_lcd_v( FT_Renderer render,+ FT_GlyphSlot slot,+ FT_Render_Mode mode,+ const FT_Vector* origin )+ {+ FT_Error error;++ error = ft_smooth_render_generic( render, slot, mode, origin,+ FT_RENDER_MODE_LCD_V );+ if ( !error )+ slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD_V;++ return error;+ }+++ FT_DEFINE_RENDERER(ft_smooth_renderer_class,++ FT_MODULE_RENDERER,+ sizeof( FT_RendererRec ),++ "smooth",+ 0x10000L,+ 0x20000L,++ 0, /* module specific interface */++ (FT_Module_Constructor)ft_smooth_init,+ (FT_Module_Destructor) 0,+ (FT_Module_Requester) 0+ ,++ FT_GLYPH_FORMAT_OUTLINE,++ (FT_Renderer_RenderFunc) ft_smooth_render,+ (FT_Renderer_TransformFunc)ft_smooth_transform,+ (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox,+ (FT_Renderer_SetModeFunc) ft_smooth_set_mode,++ (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET+ )+++ FT_DEFINE_RENDERER(ft_smooth_lcd_renderer_class,+ + FT_MODULE_RENDERER,+ sizeof( FT_RendererRec ),++ "smooth-lcd",+ 0x10000L,+ 0x20000L,++ 0, /* module specific interface */++ (FT_Module_Constructor)ft_smooth_init,+ (FT_Module_Destructor) 0,+ (FT_Module_Requester) 0+ ,++ FT_GLYPH_FORMAT_OUTLINE,++ (FT_Renderer_RenderFunc) ft_smooth_render_lcd,+ (FT_Renderer_TransformFunc)ft_smooth_transform,+ (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox,+ (FT_Renderer_SetModeFunc) ft_smooth_set_mode,++ (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET+ )++ FT_DEFINE_RENDERER(ft_smooth_lcdv_renderer_class,++ FT_MODULE_RENDERER,+ sizeof( FT_RendererRec ),++ "smooth-lcdv",+ 0x10000L,+ 0x20000L,++ 0, /* module specific interface */++ (FT_Module_Constructor)ft_smooth_init,+ (FT_Module_Destructor) 0,+ (FT_Module_Requester) 0+ ,++ FT_GLYPH_FORMAT_OUTLINE,++ (FT_Renderer_RenderFunc) ft_smooth_render_lcd_v,+ (FT_Renderer_TransformFunc)ft_smooth_transform,+ (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox,+ (FT_Renderer_SetModeFunc) ft_smooth_set_mode,++ (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET+ )+++/* END */
+ src/smooth/ftsmooth.h view
@@ -0,0 +1,49 @@+/***************************************************************************/+/* */+/* ftsmooth.h */+/* */+/* Anti-aliasing renderer interface (specification). */+/* */+/* Copyright 1996-2001 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 __FTSMOOTH_H__+#define __FTSMOOTH_H__+++#include <ft2build.h>+#include FT_RENDER_H+++FT_BEGIN_HEADER+++#ifndef FT_CONFIG_OPTION_NO_STD_RASTER+ FT_DECLARE_RENDERER( ft_std_renderer_class )+#endif++#ifndef FT_CONFIG_OPTION_NO_SMOOTH_RASTER+ FT_DECLARE_RENDERER( ft_smooth_renderer_class )++ FT_DECLARE_RENDERER( ft_smooth_lcd_renderer_class )++ FT_DECLARE_RENDERER( ft_smooth_lcd_v_renderer_class )+#endif++++FT_END_HEADER++#endif /* __FTSMOOTH_H__ */+++/* END */
+ src/smooth/ftspic.c view
@@ -0,0 +1,98 @@+/***************************************************************************/+/* */+/* ftspic.c */+/* */+/* The FreeType position independent code services for smooth module. */+/* */+/* Copyright 2009, 2010 by */+/* Oran Agra and Mickey Gabel. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#include <ft2build.h>+#include FT_FREETYPE_H+#include FT_INTERNAL_OBJECTS_H+#include "ftspic.h"++#ifdef FT_CONFIG_OPTION_PIC++ /* forward declaration of PIC init functions from ftgrays.c */+ void FT_Init_Class_ft_grays_raster(FT_Raster_Funcs*);++ void+ ft_smooth_renderer_class_pic_free( FT_Library library )+ {+ FT_PIC_Container* pic_container = &library->pic_container;+ FT_Memory memory = library->memory;+ if ( pic_container->smooth )+ {+ SmoothPIC* container = (SmoothPIC*)pic_container->smooth;+ if(--container->ref_count)+ return;+ FT_FREE( container );+ pic_container->smooth = NULL;+ }+ }+++ FT_Error+ ft_smooth_renderer_class_pic_init( FT_Library library )+ {+ FT_PIC_Container* pic_container = &library->pic_container;+ FT_Error error = Smooth_Err_Ok;+ SmoothPIC* container;+ FT_Memory memory = library->memory;+++ /* since this function also serve smooth_lcd and smooth_lcdv renderers, + it implements reference counting */+ if(pic_container->smooth)+ {+ ((SmoothPIC*)pic_container->smooth)->ref_count++;+ return error;+ }++ /* allocate pointer, clear and set global container pointer */+ if ( FT_ALLOC ( container, sizeof ( *container ) ) )+ return error;+ FT_MEM_SET( container, 0, sizeof(*container) );+ pic_container->smooth = container;+ container->ref_count = 1;++ /* initialize pointer table - this is how the module usually expects this data */+ FT_Init_Class_ft_grays_raster(&container->ft_grays_raster);+/*Exit:*/+ if(error)+ ft_smooth_renderer_class_pic_free(library);+ return error;+ }++ /* re-route these init and free functions to the above functions */+ FT_Error ft_smooth_lcd_renderer_class_pic_init(FT_Library library)+ {+ return ft_smooth_renderer_class_pic_init(library);+ }+ void ft_smooth_lcd_renderer_class_pic_free(FT_Library library)+ {+ ft_smooth_renderer_class_pic_free(library);+ }+ FT_Error ft_smooth_lcdv_renderer_class_pic_init(FT_Library library)+ {+ return ft_smooth_renderer_class_pic_init(library);+ }+ void ft_smooth_lcdv_renderer_class_pic_free(FT_Library library)+ {+ ft_smooth_renderer_class_pic_free(library);+ }++#endif /* FT_CONFIG_OPTION_PIC */+++/* END */
+ src/smooth/ftspic.h view
@@ -0,0 +1,50 @@+/***************************************************************************/+/* */+/* ftspic.h */+/* */+/* The FreeType position independent code services for smooth module. */+/* */+/* Copyright 2009 by */+/* Oran Agra and Mickey Gabel. */+/* */+/* 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 __FTSPIC_H__+#define __FTSPIC_H__++ +FT_BEGIN_HEADER++#include FT_INTERNAL_PIC_H++#ifndef FT_CONFIG_OPTION_PIC+#define FT_GRAYS_RASTER_GET ft_grays_raster++#else /* FT_CONFIG_OPTION_PIC */++ typedef struct SmoothPIC_+ {+ int ref_count;+ FT_Raster_Funcs ft_grays_raster;+ } SmoothPIC;++#define GET_PIC(lib) ((SmoothPIC*)((lib)->pic_container.smooth))+#define FT_GRAYS_RASTER_GET (GET_PIC(library)->ft_grays_raster)++#endif /* FT_CONFIG_OPTION_PIC */++ /* */++FT_END_HEADER++#endif /* __FTSPIC_H__ */+++/* END */
+ src/smooth/smooth.c view
@@ -0,0 +1,27 @@+/***************************************************************************/+/* */+/* smooth.c */+/* */+/* FreeType anti-aliasing rasterer module component (body only). */+/* */+/* Copyright 1996-2001 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 "ftspic.c"+#include "ftgrays.c"+#include "ftsmooth.c"+++/* END */
+ src/truetype/truetype.c view
@@ -0,0 +1,37 @@+/***************************************************************************/+/* */+/* truetype.c */+/* */+/* FreeType TrueType driver component (body only). */+/* */+/* Copyright 1996-2001, 2004, 2006 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 "ttpic.c"+#include "ttdriver.c" /* driver interface */+#include "ttpload.c" /* tables loader */+#include "ttgload.c" /* glyph loader */+#include "ttobjs.c" /* object manager */++#ifdef TT_USE_BYTECODE_INTERPRETER+#include "ttinterp.c"+#endif++#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT+#include "ttgxvar.c" /* gx distortable font */+#endif+++/* END */
+ src/truetype/ttdriver.c view
@@ -0,0 +1,487 @@+/***************************************************************************/+/* */+/* ttdriver.c */+/* */+/* TrueType font driver implementation (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 */+/* 2010 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_STREAM_H+#include FT_INTERNAL_SFNT_H+#include FT_SERVICE_XFREE86_NAME_H++#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT+#include FT_MULTIPLE_MASTERS_H+#include FT_SERVICE_MULTIPLE_MASTERS_H+#endif++#include FT_SERVICE_TRUETYPE_ENGINE_H+#include FT_SERVICE_TRUETYPE_GLYF_H++#include "ttdriver.h"+#include "ttgload.h"+#include "ttpload.h"++#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT+#include "ttgxvar.h"+#endif++#include "tterrors.h"++#include "ttpic.h"++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_ttdriver+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** ****/+ /**** F A C E S ****/+ /**** ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++#undef PAIR_TAG+#define PAIR_TAG( left, right ) ( ( (FT_ULong)left << 16 ) | \+ (FT_ULong)right )+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_get_kerning */+ /* */+ /* <Description> */+ /* A driver method used to return the kerning vector between two */+ /* glyphs of the same face. */+ /* */+ /* <Input> */+ /* face :: A handle to the source face object. */+ /* */+ /* left_glyph :: The index of the left glyph in the kern pair. */+ /* */+ /* right_glyph :: The index of the right glyph in the kern pair. */+ /* */+ /* <Output> */+ /* kerning :: The kerning vector. This is in font units for */+ /* scalable formats, and in pixels for fixed-sizes */+ /* formats. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ /* <Note> */+ /* Only horizontal layouts (left-to-right & right-to-left) are */+ /* supported by this function. Other layouts, or more sophisticated */+ /* kernings, are out of scope of this method (the basic driver */+ /* interface is meant to be simple). */+ /* */+ /* They can be implemented by format-specific interfaces. */+ /* */+ static FT_Error+ tt_get_kerning( FT_Face ttface, /* TT_Face */+ FT_UInt left_glyph,+ FT_UInt right_glyph,+ FT_Vector* kerning )+ {+ TT_Face face = (TT_Face)ttface;+ SFNT_Service sfnt = (SFNT_Service)face->sfnt;+++ kerning->x = 0;+ kerning->y = 0;++ if ( sfnt )+ kerning->x = sfnt->get_kerning( face, left_glyph, right_glyph );++ return 0;+ }+++#undef PAIR_TAG+++ static FT_Error+ tt_get_advances( FT_Face ttface,+ FT_UInt start,+ FT_UInt count,+ FT_Int32 flags,+ FT_Fixed *advances )+ {+ FT_UInt nn;+ TT_Face face = (TT_Face) ttface;+ FT_Bool check = FT_BOOL(+ !( flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) );+++ /* XXX: TODO: check for sbits */++ if ( flags & FT_LOAD_VERTICAL_LAYOUT )+ {+ for ( nn = 0; nn < count; nn++ )+ {+ FT_Short tsb;+ FT_UShort ah;+++ TT_Get_VMetrics( face, start + nn, check, &tsb, &ah );+ advances[nn] = ah;+ }+ }+ else+ {+ for ( nn = 0; nn < count; nn++ )+ {+ FT_Short lsb;+ FT_UShort aw;+++ TT_Get_HMetrics( face, start + nn, check, &lsb, &aw );+ advances[nn] = aw;+ }+ }++ return TT_Err_Ok;+ }++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** ****/+ /**** S I Z E S ****/+ /**** ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS++ static FT_Error+ tt_size_select( FT_Size size,+ FT_ULong strike_index )+ {+ TT_Face ttface = (TT_Face)size->face;+ TT_Size ttsize = (TT_Size)size;+ FT_Error error = TT_Err_Ok;+++ ttsize->strike_index = strike_index;++ if ( FT_IS_SCALABLE( size->face ) )+ {+ /* use the scaled metrics, even when tt_size_reset fails */+ FT_Select_Metrics( size->face, strike_index );++ tt_size_reset( ttsize );+ }+ else+ {+ SFNT_Service sfnt = (SFNT_Service) ttface->sfnt;+ FT_Size_Metrics* metrics = &size->metrics;+++ error = sfnt->load_strike_metrics( ttface, strike_index, metrics );+ if ( error )+ ttsize->strike_index = 0xFFFFFFFFUL;+ }++ return error;+ }++#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */+++ static FT_Error+ tt_size_request( FT_Size size,+ FT_Size_Request req )+ {+ TT_Size ttsize = (TT_Size)size;+ FT_Error error = TT_Err_Ok;+++#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS++ if ( FT_HAS_FIXED_SIZES( size->face ) )+ {+ TT_Face ttface = (TT_Face)size->face;+ SFNT_Service sfnt = (SFNT_Service) ttface->sfnt;+ FT_ULong strike_index;+++ error = sfnt->set_sbit_strike( ttface, req, &strike_index );++ if ( error )+ ttsize->strike_index = 0xFFFFFFFFUL;+ else+ return tt_size_select( size, strike_index );+ }++#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */++ FT_Request_Metrics( size->face, req );++ if ( FT_IS_SCALABLE( size->face ) )+ error = tt_size_reset( ttsize );++ return error;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Load_Glyph */+ /* */+ /* <Description> */+ /* A driver method used to load a glyph within a given glyph slot. */+ /* */+ /* <Input> */+ /* slot :: A handle to the target slot object where the glyph */+ /* will be loaded. */+ /* */+ /* size :: A handle to the source face size at which the glyph */+ /* must be scaled, loaded, etc. */+ /* */+ /* glyph_index :: The index of the glyph in the font file. */+ /* */+ /* load_flags :: A flag indicating what to load for this glyph. The */+ /* FT_LOAD_XXX constants can be used to control the */+ /* glyph loading process (e.g., whether the outline */+ /* should be scaled, whether to load bitmaps or not, */+ /* whether to hint the outline, etc). */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ static FT_Error+ Load_Glyph( FT_GlyphSlot ttslot, /* TT_GlyphSlot */+ FT_Size ttsize, /* TT_Size */+ FT_UInt glyph_index,+ FT_Int32 load_flags )+ {+ TT_GlyphSlot slot = (TT_GlyphSlot)ttslot;+ TT_Size size = (TT_Size)ttsize;+ FT_Face face = ttslot->face;+ FT_Error error;+++ if ( !slot )+ return TT_Err_Invalid_Slot_Handle;++ if ( !size )+ return TT_Err_Invalid_Size_Handle;++ if ( !face )+ return TT_Err_Invalid_Argument;++#ifdef FT_CONFIG_OPTION_INCREMENTAL+ if ( glyph_index >= (FT_UInt)face->num_glyphs &&+ !face->internal->incremental_interface )+#else+ if ( glyph_index >= (FT_UInt)face->num_glyphs )+#endif+ return TT_Err_Invalid_Argument;++ if ( load_flags & FT_LOAD_NO_HINTING )+ {+ /* both FT_LOAD_NO_HINTING and FT_LOAD_NO_AUTOHINT */+ /* are necessary to disable hinting for tricky fonts */ ++ if ( FT_IS_TRICKY( face ) )+ load_flags &= ~FT_LOAD_NO_HINTING;++ if ( load_flags & FT_LOAD_NO_AUTOHINT )+ load_flags |= FT_LOAD_NO_HINTING;+ }++ if ( load_flags & ( FT_LOAD_NO_RECURSE | FT_LOAD_NO_SCALE ) )+ {+ load_flags |= FT_LOAD_NO_BITMAP | FT_LOAD_NO_SCALE;++ if ( !FT_IS_TRICKY( face ) )+ load_flags |= FT_LOAD_NO_HINTING;+ }++ /* now load the glyph outline if necessary */+ error = TT_Load_Glyph( size, slot, glyph_index, load_flags );++ /* force drop-out mode to 2 - irrelevant now */+ /* slot->outline.dropout_mode = 2; */++ return error;+ }+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /**** ****/+ /**** ****/+ /**** D R I V E R I N T E R F A C E ****/+ /**** ****/+ /**** ****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/++#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+ )+#endif++ static const FT_Service_TrueTypeEngineRec tt_service_truetype_engine =+ {+#ifdef TT_USE_BYTECODE_INTERPRETER++#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING+ FT_TRUETYPE_ENGINE_TYPE_UNPATENTED+#else+ FT_TRUETYPE_ENGINE_TYPE_PATENTED+#endif++#else /* !TT_USE_BYTECODE_INTERPRETER */++ FT_TRUETYPE_ENGINE_TYPE_NONE++#endif /* TT_USE_BYTECODE_INTERPRETER */+ };++ FT_DEFINE_SERVICE_TTGLYFREC(tt_service_truetype_glyf,+ (TT_Glyf_GetLocationFunc)tt_face_get_location+ )++#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT+ FT_DEFINE_SERVICEDESCREC4(tt_services,+ FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_TRUETYPE,+ FT_SERVICE_ID_MULTI_MASTERS, &FT_TT_SERVICE_GX_MULTI_MASTERS_GET,+ FT_SERVICE_ID_TRUETYPE_ENGINE, &tt_service_truetype_engine,+ FT_SERVICE_ID_TT_GLYF, &FT_TT_SERVICE_TRUETYPE_GLYF_GET+ )+#else+ FT_DEFINE_SERVICEDESCREC3(tt_services,+ FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_TRUETYPE,+ FT_SERVICE_ID_TRUETYPE_ENGINE, &tt_service_truetype_engine,+ FT_SERVICE_ID_TT_GLYF, &FT_TT_SERVICE_TRUETYPE_GLYF_GET+ )+#endif++ FT_CALLBACK_DEF( FT_Module_Interface )+ tt_get_interface( FT_Module driver, /* TT_Driver */+ const char* tt_interface )+ {+ FT_Module_Interface result;+ FT_Module sfntd;+ SFNT_Service sfnt;++ result = ft_service_list_lookup( FT_TT_SERVICES_GET, tt_interface );+ if ( result != NULL )+ return result;++ if ( !driver )+ return NULL;++ /* only return the default interface from the SFNT module */+ sfntd = FT_Get_Module( driver->library, "sfnt" );+ if ( sfntd )+ {+ sfnt = (SFNT_Service)( sfntd->clazz->module_interface );+ if ( sfnt )+ return sfnt->get_interface( driver, tt_interface );+ }++ return 0;+ }+++ /* The FT_DriverInterface structure is defined in ftdriver.h. */++#ifdef TT_USE_BYTECODE_INTERPRETER+#define TT_HINTER_FLAG FT_MODULE_DRIVER_HAS_HINTER+#else+#define TT_HINTER_FLAG 0+#endif++#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS+#define TT_SIZE_SELECT tt_size_select+#else+#define TT_SIZE_SELECT 0+#endif++ FT_DEFINE_DRIVER(tt_driver_class,+ + + FT_MODULE_FONT_DRIVER |+ FT_MODULE_DRIVER_SCALABLE |+ TT_HINTER_FLAG,++ sizeof ( TT_DriverRec ),++ "truetype", /* driver name */+ 0x10000L, /* driver version == 1.0 */+ 0x20000L, /* driver requires FreeType 2.0 or above */++ (void*)0, /* driver specific interface */++ tt_driver_init,+ tt_driver_done,+ tt_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 */++ ft_stub_set_char_sizes, /* FT_CONFIG_OPTION_OLD_INTERNALS */+ ft_stub_set_pixel_sizes, /* FT_CONFIG_OPTION_OLD_INTERNALS */++ Load_Glyph,++ tt_get_kerning,+ 0, /* FT_Face_AttachFunc */+ tt_get_advances,++ tt_size_request,+ TT_SIZE_SELECT+ )+++/* END */
+ src/truetype/ttdriver.h view
@@ -0,0 +1,38 @@+/***************************************************************************/+/* */+/* ttdriver.h */+/* */+/* High-level TrueType driver interface (specification). */+/* */+/* Copyright 1996-2001, 2002 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 __TTDRIVER_H__+#define __TTDRIVER_H__+++#include <ft2build.h>+#include FT_INTERNAL_DRIVER_H+++FT_BEGIN_HEADER+++ FT_DECLARE_DRIVER( tt_driver_class )+++FT_END_HEADER++#endif /* __TTDRIVER_H__ */+++/* END */
+ src/truetype/tterrors.h view
@@ -0,0 +1,40 @@+/***************************************************************************/+/* */+/* tterrors.h */+/* */+/* TrueType error codes (specification only). */+/* */+/* Copyright 2001 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 TrueType error enumeration */+ /* constants. */+ /* */+ /*************************************************************************/++#ifndef __TTERRORS_H__+#define __TTERRORS_H__++#include FT_MODULE_ERRORS_H++#undef __FTERRORS_H__++#define FT_ERR_PREFIX TT_Err_+#define FT_ERR_BASE FT_Mod_Err_TrueType++#include FT_ERRORS_H++#endif /* __TTERRORS_H__ */++/* END */
+ src/truetype/ttgload.c view
@@ -0,0 +1,2147 @@+/***************************************************************************/+/* */+/* ttgload.c */+/* */+/* TrueType Glyph Loader (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */+/* 2010 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_CALC_H+#include FT_INTERNAL_STREAM_H+#include FT_INTERNAL_SFNT_H+#include FT_TRUETYPE_TAGS_H+#include FT_OUTLINE_H++#include "ttgload.h"+#include "ttpload.h"++#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT+#include "ttgxvar.h"+#endif++#include "tterrors.h"+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_ttgload+++ /*************************************************************************/+ /* */+ /* Composite font flags. */+ /* */+#define ARGS_ARE_WORDS 0x0001+#define ARGS_ARE_XY_VALUES 0x0002+#define ROUND_XY_TO_GRID 0x0004+#define WE_HAVE_A_SCALE 0x0008+/* reserved 0x0010 */+#define MORE_COMPONENTS 0x0020+#define WE_HAVE_AN_XY_SCALE 0x0040+#define WE_HAVE_A_2X2 0x0080+#define WE_HAVE_INSTR 0x0100+#define USE_MY_METRICS 0x0200+#define OVERLAP_COMPOUND 0x0400+#define SCALED_COMPONENT_OFFSET 0x0800+#define UNSCALED_COMPONENT_OFFSET 0x1000+++ /*************************************************************************/+ /* */+ /* Returns the horizontal metrics in font units for a given glyph. If */+ /* `check' is true, take care of monospaced fonts by returning the */+ /* advance width maximum. */+ /* */+ FT_LOCAL_DEF( void )+ TT_Get_HMetrics( TT_Face face,+ FT_UInt idx,+ FT_Bool check,+ FT_Short* lsb,+ FT_UShort* aw )+ {+ ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, idx, lsb, aw );++ if ( check && face->postscript.isFixedPitch )+ *aw = face->horizontal.advance_Width_Max;++ FT_TRACE5(( " advance width (font units): %d\n", *aw ));+ FT_TRACE5(( " left side bearing (font units): %d\n", *lsb ));+ }+++ /*************************************************************************/+ /* */+ /* Returns the vertical metrics in font units for a given glyph. */+ /* Greg Hitchcock from Microsoft told us that if there were no `vmtx' */+ /* table, typoAscender/Descender from the `OS/2' table would be used */+ /* instead, and if there were no `OS/2' table, use ascender/descender */+ /* from the `hhea' table. But that is not what Microsoft's rasterizer */+ /* apparently does: It uses the ppem value as the advance height, and */+ /* sets the top side bearing to be zero. */+ /* */+ /* The monospace `check' is probably not meaningful here, but we leave */+ /* it in for a consistent interface. */+ /* */+ FT_LOCAL_DEF( void )+ TT_Get_VMetrics( TT_Face face,+ FT_UInt idx,+ FT_Bool check,+ FT_Short* tsb,+ FT_UShort* ah )+ {+ FT_UNUSED( check );++ if ( face->vertical_info )+ ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah );++#if 1 /* Empirically determined, at variance with what MS said */++ else+ {+ *tsb = 0;+ *ah = face->root.units_per_EM;+ }++#else /* This is what MS said to do. It isn't what they do, however. */++ else if ( face->os2.version != 0xFFFFU )+ {+ *tsb = face->os2.sTypoAscender;+ *ah = face->os2.sTypoAscender - face->os2.sTypoDescender;+ }+ else+ {+ *tsb = face->horizontal.Ascender;+ *ah = face->horizontal.Ascender - face->horizontal.Descender;+ }++#endif++ FT_TRACE5(( " advance height (font units): %d\n", *ah ));+ FT_TRACE5(( " top side bearing (font units): %d\n", *tsb ));+ }+++ static void+ tt_get_metrics( TT_Loader loader,+ FT_UInt glyph_index )+ {+ TT_Face face = (TT_Face)loader->face;++ FT_Short left_bearing = 0, top_bearing = 0;+ FT_UShort advance_width = 0, advance_height = 0;+++ TT_Get_HMetrics( face, glyph_index,+ (FT_Bool)!( loader->load_flags &+ FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),+ &left_bearing,+ &advance_width );+ TT_Get_VMetrics( face, glyph_index,+ (FT_Bool)!( loader->load_flags &+ FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),+ &top_bearing,+ &advance_height );++ loader->left_bearing = left_bearing;+ loader->advance = advance_width;+ loader->top_bearing = top_bearing;+ loader->vadvance = advance_height;++ if ( !loader->linear_def )+ {+ loader->linear_def = 1;+ loader->linear = advance_width;+ }+ }+++#ifdef FT_CONFIG_OPTION_INCREMENTAL++ static void+ tt_get_metrics_incr_overrides( TT_Loader loader,+ FT_UInt glyph_index )+ {+ TT_Face face = (TT_Face)loader->face;++ FT_Short left_bearing = 0, top_bearing = 0;+ FT_UShort advance_width = 0, advance_height = 0;+++ /* If this is an incrementally loaded font check whether there are */+ /* overriding metrics for this glyph. */+ if ( face->root.internal->incremental_interface &&+ face->root.internal->incremental_interface->funcs->get_glyph_metrics )+ {+ FT_Incremental_MetricsRec metrics;+ FT_Error error;+++ metrics.bearing_x = loader->left_bearing;+ metrics.bearing_y = 0;+ metrics.advance = loader->advance;+ metrics.advance_v = 0;++ error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(+ face->root.internal->incremental_interface->object,+ glyph_index, FALSE, &metrics );+ if ( error )+ goto Exit;++ left_bearing = (FT_Short)metrics.bearing_x;+ advance_width = (FT_UShort)metrics.advance;++#if 0++ /* GWW: Do I do the same for vertical metrics? */+ metrics.bearing_x = 0;+ metrics.bearing_y = loader->top_bearing;+ metrics.advance = loader->vadvance;++ error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(+ face->root.internal->incremental_interface->object,+ glyph_index, TRUE, &metrics );+ if ( error )+ goto Exit;++ top_bearing = (FT_Short)metrics.bearing_y;+ advance_height = (FT_UShort)metrics.advance;++#endif /* 0 */++ loader->left_bearing = left_bearing;+ loader->advance = advance_width;+ loader->top_bearing = top_bearing;+ loader->vadvance = advance_height;++ if ( !loader->linear_def )+ {+ loader->linear_def = 1;+ loader->linear = advance_width;+ }+ }++ Exit:+ return;+ }++#endif /* FT_CONFIG_OPTION_INCREMENTAL */+++ /*************************************************************************/+ /* */+ /* 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;+ }+++#undef IS_HINTED+#define IS_HINTED( flags ) ( ( flags & FT_LOAD_NO_HINTING ) == 0 )+++ /*************************************************************************/+ /* */+ /* 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. */+ /* */+ /*************************************************************************/++ FT_CALLBACK_DEF( FT_Error )+ TT_Access_Glyph_Frame( TT_Loader loader,+ FT_UInt glyph_index,+ FT_ULong offset,+ FT_UInt byte_count )+ {+ FT_Error error;+ FT_Stream stream = loader->stream;++ /* for non-debug mode */+ FT_UNUSED( glyph_index );+++ FT_TRACE4(( "Glyph %ld\n", glyph_index ));++ /* the following line sets the `error' variable through macros! */+ if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) )+ return error;++ loader->cursor = stream->cursor;+ loader->limit = stream->limit;++ return TT_Err_Ok;+ }+++ FT_CALLBACK_DEF( void )+ TT_Forget_Glyph_Frame( TT_Loader loader )+ {+ FT_Stream stream = loader->stream;+++ FT_FRAME_EXIT();+ }+++ FT_CALLBACK_DEF( FT_Error )+ TT_Load_Glyph_Header( TT_Loader loader )+ {+ FT_Byte* p = loader->cursor;+ FT_Byte* limit = loader->limit;+++ if ( p + 10 > limit )+ return TT_Err_Invalid_Outline;++ loader->n_contours = FT_NEXT_SHORT( p );++ loader->bbox.xMin = FT_NEXT_SHORT( p );+ loader->bbox.yMin = FT_NEXT_SHORT( p );+ loader->bbox.xMax = FT_NEXT_SHORT( p );+ loader->bbox.yMax = FT_NEXT_SHORT( p );++ FT_TRACE5(( " # of contours: %d\n", loader->n_contours ));+ FT_TRACE5(( " xMin: %4d xMax: %4d\n", loader->bbox.xMin,+ loader->bbox.xMax ));+ FT_TRACE5(( " yMin: %4d yMax: %4d\n", loader->bbox.yMin,+ loader->bbox.yMax ));+ loader->cursor = p;++ return TT_Err_Ok;+ }+++ FT_CALLBACK_DEF( FT_Error )+ TT_Load_Simple_Glyph( TT_Loader load )+ {+ FT_Error error;+ FT_Byte* p = load->cursor;+ FT_Byte* limit = load->limit;+ FT_GlyphLoader gloader = load->gloader;+ FT_Int n_contours = load->n_contours;+ FT_Outline* outline;+ TT_Face face = (TT_Face)load->face;+ FT_UShort n_ins;+ FT_Int n_points;++ FT_Byte *flag, *flag_limit;+ FT_Byte c, count;+ FT_Vector *vec, *vec_limit;+ FT_Pos x;+ FT_Short *cont, *cont_limit, prev_cont;+ FT_Int xy_size = 0;+++ /* check that we can add the contours to the glyph */+ error = FT_GLYPHLOADER_CHECK_POINTS( gloader, 0, n_contours );+ if ( error )+ goto Fail;++ /* reading the contours' endpoints & number of points */+ cont = gloader->current.outline.contours;+ cont_limit = cont + n_contours;++ /* check space for contours array + instructions count */+ if ( n_contours >= 0xFFF || p + ( n_contours + 1 ) * 2 > limit )+ goto Invalid_Outline;++ prev_cont = FT_NEXT_USHORT( p );++ if ( n_contours > 0 )+ cont[0] = prev_cont;++ for ( cont++; cont < cont_limit; cont++ )+ {+ cont[0] = FT_NEXT_USHORT( p );+ if ( cont[0] <= prev_cont )+ {+ /* unordered contours: this is invalid */+ error = TT_Err_Invalid_Table;+ goto Fail;+ }+ prev_cont = cont[0];+ }++ n_points = 0;+ if ( n_contours > 0 )+ {+ n_points = cont[-1] + 1;+ if ( n_points < 0 )+ goto Invalid_Outline;+ }++ /* note that we will add four phantom points later */+ error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 );+ if ( error )+ goto Fail;++ /* we'd better check the contours table right now */+ outline = &gloader->current.outline;++ for ( cont = outline->contours + 1; cont < cont_limit; cont++ )+ if ( cont[-1] >= cont[0] )+ goto Invalid_Outline;++ /* reading the bytecode instructions */+ load->glyph->control_len = 0;+ load->glyph->control_data = 0;++ if ( p + 2 > limit )+ goto Invalid_Outline;++ n_ins = FT_NEXT_USHORT( p );++ FT_TRACE5(( " Instructions size: %u\n", n_ins ));++ if ( n_ins > face->max_profile.maxSizeOfInstructions )+ {+ FT_TRACE0(( "TT_Load_Simple_Glyph: too many instructions (%d)\n",+ n_ins ));+ error = TT_Err_Too_Many_Hints;+ goto Fail;+ }++ if ( ( limit - p ) < n_ins )+ {+ FT_TRACE0(( "TT_Load_Simple_Glyph: instruction count mismatch\n" ));+ error = TT_Err_Too_Many_Hints;+ goto Fail;+ }++#ifdef TT_USE_BYTECODE_INTERPRETER++ if ( IS_HINTED( load->load_flags ) )+ {+ load->glyph->control_len = n_ins;+ load->glyph->control_data = load->exec->glyphIns;++ FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins );+ }++#endif /* TT_USE_BYTECODE_INTERPRETER */++ p += n_ins;++ /* reading the point tags */+ flag = (FT_Byte*)outline->tags;+ flag_limit = flag + n_points;++ FT_ASSERT( flag != NULL );++ while ( flag < flag_limit )+ {+ if ( p + 1 > limit )+ goto Invalid_Outline;++ *flag++ = c = FT_NEXT_BYTE( p );+ if ( c & 8 )+ {+ if ( p + 1 > limit )+ goto Invalid_Outline;++ count = FT_NEXT_BYTE( p );+ if ( flag + (FT_Int)count > flag_limit )+ goto Invalid_Outline;++ for ( ; count > 0; count-- )+ *flag++ = c;+ }+ }++ /* reading the X coordinates */++ vec = outline->points;+ vec_limit = vec + n_points;+ flag = (FT_Byte*)outline->tags;+ x = 0;++ if ( p + xy_size > limit )+ goto Invalid_Outline;++ for ( ; vec < vec_limit; vec++, flag++ )+ {+ FT_Pos y = 0;+ FT_Byte f = *flag;+++ if ( f & 2 )+ {+ if ( p + 1 > limit )+ goto Invalid_Outline;++ y = (FT_Pos)FT_NEXT_BYTE( p );+ if ( ( f & 16 ) == 0 )+ y = -y;+ }+ else if ( ( f & 16 ) == 0 )+ {+ if ( p + 2 > limit )+ goto Invalid_Outline;++ y = (FT_Pos)FT_NEXT_SHORT( p );+ }++ x += y;+ vec->x = x;+ /* the cast is for stupid compilers */+ *flag = (FT_Byte)( f & ~( 2 | 16 ) );+ }++ /* reading the Y coordinates */++ vec = gloader->current.outline.points;+ vec_limit = vec + n_points;+ flag = (FT_Byte*)outline->tags;+ x = 0;++ for ( ; vec < vec_limit; vec++, flag++ )+ {+ FT_Pos y = 0;+ FT_Byte f = *flag;+++ if ( f & 4 )+ {+ if ( p + 1 > limit )+ goto Invalid_Outline;++ y = (FT_Pos)FT_NEXT_BYTE( p );+ if ( ( f & 32 ) == 0 )+ y = -y;+ }+ else if ( ( f & 32 ) == 0 )+ {+ if ( p + 2 > limit )+ goto Invalid_Outline;++ y = (FT_Pos)FT_NEXT_SHORT( p );+ }++ x += y;+ vec->y = x;+ /* the cast is for stupid compilers */+ *flag = (FT_Byte)( f & FT_CURVE_TAG_ON );+ }++ outline->n_points = (FT_UShort)n_points;+ outline->n_contours = (FT_Short) n_contours;++ load->cursor = p;++ Fail:+ return error;++ Invalid_Outline:+ error = TT_Err_Invalid_Outline;+ goto Fail;+ }+++ FT_CALLBACK_DEF( FT_Error )+ TT_Load_Composite_Glyph( TT_Loader loader )+ {+ FT_Error error;+ FT_Byte* p = loader->cursor;+ FT_Byte* limit = loader->limit;+ FT_GlyphLoader gloader = loader->gloader;+ FT_SubGlyph subglyph;+ FT_UInt num_subglyphs;+++ num_subglyphs = 0;++ do+ {+ FT_Fixed xx, xy, yy, yx;+ FT_UInt count;+++ /* check that we can load a new subglyph */+ error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs + 1 );+ if ( error )+ goto Fail;++ /* check space */+ if ( p + 4 > limit )+ goto Invalid_Composite;++ subglyph = gloader->current.subglyphs + num_subglyphs;++ subglyph->arg1 = subglyph->arg2 = 0;++ subglyph->flags = FT_NEXT_USHORT( p );+ subglyph->index = FT_NEXT_USHORT( p );++ /* check space */+ count = 2;+ if ( subglyph->flags & ARGS_ARE_WORDS )+ count += 2;+ if ( subglyph->flags & WE_HAVE_A_SCALE )+ count += 2;+ else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )+ count += 4;+ else if ( subglyph->flags & WE_HAVE_A_2X2 )+ count += 8;++ if ( p + count > limit )+ goto Invalid_Composite;++ /* read arguments */+ if ( subglyph->flags & ARGS_ARE_WORDS )+ {+ subglyph->arg1 = FT_NEXT_SHORT( p );+ subglyph->arg2 = FT_NEXT_SHORT( p );+ }+ else+ {+ subglyph->arg1 = FT_NEXT_CHAR( p );+ subglyph->arg2 = FT_NEXT_CHAR( p );+ }++ /* read transform */+ xx = yy = 0x10000L;+ xy = yx = 0;++ if ( subglyph->flags & WE_HAVE_A_SCALE )+ {+ xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;+ 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;+ }+ 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;+ }++ subglyph->transform.xx = xx;+ subglyph->transform.xy = xy;+ subglyph->transform.yx = yx;+ subglyph->transform.yy = yy;++ num_subglyphs++;++ } while ( subglyph->flags & MORE_COMPONENTS );++ gloader->current.num_subglyphs = num_subglyphs;++#ifdef TT_USE_BYTECODE_INTERPRETER++ {+ FT_Stream stream = loader->stream;+++ /* we must undo the FT_FRAME_ENTER in order to point */+ /* to the composite instructions, if we find some. */+ /* We will process them later. */+ /* */+ loader->ins_pos = (FT_ULong)( FT_STREAM_POS() ++ p - limit );+ }++#endif++ loader->cursor = p;++ Fail:+ return error;++ Invalid_Composite:+ error = TT_Err_Invalid_Composite;+ goto Fail;+ }+++ FT_LOCAL_DEF( void )+ TT_Init_Glyph_Loading( TT_Face face )+ {+ face->access_glyph_frame = TT_Access_Glyph_Frame;+ face->read_glyph_header = TT_Load_Glyph_Header;+ face->read_simple_glyph = TT_Load_Simple_Glyph;+ face->read_composite_glyph = TT_Load_Composite_Glyph;+ face->forget_glyph_frame = TT_Forget_Glyph_Frame;+ }+++ static void+ tt_prepare_zone( TT_GlyphZone zone,+ FT_GlyphLoad load,+ FT_UInt start_point,+ FT_UInt start_contour )+ {+ zone->n_points = (FT_UShort)( load->outline.n_points - start_point );+ zone->n_contours = (FT_Short) ( load->outline.n_contours -+ start_contour );+ zone->org = load->extra_points + start_point;+ zone->cur = load->outline.points + start_point;+ zone->orus = load->extra_points2 + start_point;+ zone->tags = (FT_Byte*)load->outline.tags + start_point;+ zone->contours = (FT_UShort*)load->outline.contours + start_contour;+ zone->first_point = (FT_UShort)start_point;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* TT_Hint_Glyph */+ /* */+ /* <Description> */+ /* Hint the glyph using the zone prepared by the caller. Note that */+ /* the zone is supposed to include four phantom points. */+ /* */+ static FT_Error+ TT_Hint_Glyph( TT_Loader loader,+ FT_Bool is_composite )+ {+ TT_GlyphZone zone = &loader->zone;+ FT_Pos origin;++#ifdef TT_USE_BYTECODE_INTERPRETER+ FT_UInt n_ins;+#else+ FT_UNUSED( is_composite );+#endif+++#ifdef TT_USE_BYTECODE_INTERPRETER+ if ( loader->glyph->control_len > 0xFFFFL )+ {+ FT_TRACE1(( "TT_Hint_Glyph: too long instructions " ));+ FT_TRACE1(( "(0x%lx byte) is truncated\n",+ loader->glyph->control_len ));+ }+ n_ins = (FT_UInt)( loader->glyph->control_len );+#endif++ origin = zone->cur[zone->n_points - 4].x;+ origin = FT_PIX_ROUND( origin ) - origin;+ if ( origin )+ translate_array( zone->n_points, zone->cur, origin, 0 );++#ifdef TT_USE_BYTECODE_INTERPRETER+ /* save original point position in org */+ if ( n_ins > 0 )+ FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points );++ /* Reset graphics state. */+ loader->exec->GS = ((TT_Size)loader->size)->GS;++ /* XXX: UNDOCUMENTED! Hinting instructions of a composite glyph */+ /* completely refer to the (already) hinted subglyphs. */+ if ( is_composite )+ {+ loader->exec->metrics.x_scale = 1 << 16;+ loader->exec->metrics.y_scale = 1 << 16;++ FT_ARRAY_COPY( zone->orus, zone->cur, zone->n_points );+ }+ 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;+ }+#endif++ /* round pp2 and pp4 */+ zone->cur[zone->n_points - 3].x =+ FT_PIX_ROUND( zone->cur[zone->n_points - 3].x );+ zone->cur[zone->n_points - 1].y =+ FT_PIX_ROUND( zone->cur[zone->n_points - 1].y );++#ifdef TT_USE_BYTECODE_INTERPRETER++ if ( n_ins > 0 )+ {+ FT_Bool debug;+ FT_Error error;++ FT_GlyphLoader gloader = loader->gloader;+ FT_Outline current_outline = gloader->current.outline;+++ error = TT_Set_CodeRange( loader->exec, tt_coderange_glyph,+ loader->exec->glyphIns, n_ins );+ if ( error )+ return error;++ loader->exec->is_composite = is_composite;+ loader->exec->pts = *zone;++ debug = FT_BOOL( !( loader->load_flags & FT_LOAD_NO_SCALE ) &&+ ((TT_Size)loader->size)->debug );++ error = TT_Run_Context( loader->exec, debug );+ if ( error && loader->exec->pedantic_hinting )+ return error;++ /* store drop-out mode in bits 5-7; set bit 2 also as a marker */+ current_outline.tags[0] |=+ ( loader->exec->GS.scan_type << 5 ) | FT_CURVE_TAG_HAS_SCANMODE;+ }++#endif++ /* save glyph phantom points */+ if ( !loader->preserve_pps )+ {+ loader->pp1 = zone->cur[zone->n_points - 4];+ loader->pp2 = zone->cur[zone->n_points - 3];+ loader->pp3 = zone->cur[zone->n_points - 2];+ loader->pp4 = zone->cur[zone->n_points - 1];+ }++ return TT_Err_Ok;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* TT_Process_Simple_Glyph */+ /* */+ /* <Description> */+ /* Once a simple glyph has been loaded, it needs to be processed. */+ /* Usually, this means scaling and hinting through bytecode */+ /* interpretation. */+ /* */+ static FT_Error+ TT_Process_Simple_Glyph( TT_Loader loader )+ {+ FT_GlyphLoader gloader = loader->gloader;+ FT_Error error = TT_Err_Ok;+ FT_Outline* outline;+ FT_Int n_points;+++ outline = &gloader->current.outline;+ n_points = outline->n_points;++ /* set phantom points */++ outline->points[n_points ] = loader->pp1;+ outline->points[n_points + 1] = loader->pp2;+ outline->points[n_points + 2] = loader->pp3;+ outline->points[n_points + 3] = loader->pp4;++ outline->tags[n_points ] = 0;+ outline->tags[n_points + 1] = 0;+ outline->tags[n_points + 2] = 0;+ outline->tags[n_points + 3] = 0;++ n_points += 4;++#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT++ if ( ((TT_Face)loader->face)->doblend )+ {+ /* Deltas apply to the unscaled data. */+ FT_Vector* deltas;+ FT_Memory memory = loader->face->memory;+ FT_Int i;+++ error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),+ loader->glyph_index,+ &deltas,+ n_points );+ if ( error )+ return error;++ for ( i = 0; i < n_points; ++i )+ {+ outline->points[i].x += deltas[i].x;+ outline->points[i].y += deltas[i].y;+ }++ FT_FREE( deltas );+ }++#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */++ if ( IS_HINTED( loader->load_flags ) )+ {+ tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 );++ FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur,+ loader->zone.n_points + 4 );+ }++ /* scale the glyph */+ if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )+ {+ FT_Vector* vec = outline->points;+ FT_Vector* limit = outline->points + n_points;+ FT_Fixed x_scale = ((TT_Size)loader->size)->metrics.x_scale;+ FT_Fixed y_scale = ((TT_Size)loader->size)->metrics.y_scale;+++ for ( ; vec < limit; vec++ )+ {+ vec->x = FT_MulFix( vec->x, x_scale );+ vec->y = FT_MulFix( vec->y, y_scale );+ }++ loader->pp1 = outline->points[n_points - 4];+ loader->pp2 = outline->points[n_points - 3];+ loader->pp3 = outline->points[n_points - 2];+ loader->pp4 = outline->points[n_points - 1];+ }++ if ( IS_HINTED( loader->load_flags ) )+ {+ loader->zone.n_points += 4;++ error = TT_Hint_Glyph( loader, 0 );+ }++ return error;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* TT_Process_Composite_Component */+ /* */+ /* <Description> */+ /* Once a composite component has been loaded, it needs to be */+ /* processed. Usually, this means transforming and translating. */+ /* */+ static FT_Error+ TT_Process_Composite_Component( TT_Loader loader,+ FT_SubGlyph subglyph,+ 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 = gloader->base.outline.n_points;+ FT_Bool have_scale;+ FT_Pos x, y;+++ 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 );+ }++ /* get offset */+ if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )+ {+ FT_UInt k = subglyph->arg1;+ FT_UInt l = subglyph->arg2;+ FT_Vector* p1;+ FT_Vector* p2;+++ /* match l-th point of the newly loaded component to the k-th point */+ /* of the previously loaded components. */++ /* change to the point numbers used by our outline */+ k += start_point;+ l += num_base_points;+ if ( k >= num_base_points ||+ l >= num_points )+ return TT_Err_Invalid_Composite;++ p1 = gloader->base.outline.points + k;+ p2 = gloader->base.outline.points + l;++ x = p1->x - p2->x;+ y = p1->y - p2->y;+ }+ else+ {+ x = subglyph->arg1;+ y = subglyph->arg2;++ if ( !x && !y )+ return TT_Err_Ok;++ /* Use a default value dependent on */+ /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED. This is useful for old TT */+ /* fonts which don't set the xxx_COMPONENT_OFFSET bit. */++ if ( have_scale &&+#ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED+ !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) )+#else+ ( subglyph->flags & SCALED_COMPONENT_OFFSET ) )+#endif+ {++#if 0++ /*************************************************************************/+ /* */+ /* This algorithm is what Apple documents. But it doesn't work. */+ /* */+ int a = subglyph->transform.xx > 0 ? subglyph->transform.xx+ : -subglyph->transform.xx;+ int b = subglyph->transform.yx > 0 ? subglyph->transform.yx+ : -subglyph->transform.yx;+ int c = subglyph->transform.xy > 0 ? subglyph->transform.xy+ : -subglyph->transform.xy;+ int d = subglyph->transform.yy > 0 ? subglyph->transform.yy+ : -subglyph->transform.yy;+ int m = a > b ? a : b;+ int n = c > d ? c : d;+++ if ( a - b <= 33 && a - b >= -33 )+ m *= 2;+ if ( c - d <= 33 && c - d >= -33 )+ n *= 2;+ x = FT_MulFix( x, m );+ y = FT_MulFix( y, n );++#else /* 0 */++ /*************************************************************************/+ /* */+ /* This algorithm is a guess and works much better than the above. */+ /* */+ FT_Fixed mac_xscale = FT_SqrtFixed(+ (FT_Int32)FT_MulFix( subglyph->transform.xx,+ subglyph->transform.xx ) ++ (FT_Int32)FT_MulFix( subglyph->transform.xy,+ subglyph->transform.xy ) );+ FT_Fixed mac_yscale = FT_SqrtFixed(+ (FT_Int32)FT_MulFix( subglyph->transform.yy,+ subglyph->transform.yy ) ++ (FT_Int32)FT_MulFix( subglyph->transform.yx,+ subglyph->transform.yx ) );+++ x = FT_MulFix( x, mac_xscale );+ y = FT_MulFix( y, mac_yscale );++#endif /* 0 */++ }++ 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;+++ x = FT_MulFix( x, x_scale );+ y = FT_MulFix( y, y_scale );++ if ( subglyph->flags & ROUND_XY_TO_GRID )+ {+ x = FT_PIX_ROUND( x );+ y = FT_PIX_ROUND( y );+ }+ }+ }++ if ( x || y )+ translate_array( num_points - num_base_points,+ base_vec + num_base_points,+ x, y );++ return TT_Err_Ok;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* TT_Process_Composite_Glyph */+ /* */+ /* <Description> */+ /* This is slightly different from TT_Process_Simple_Glyph, in that */+ /* its sole purpose is to hint the glyph. Thus this function is */+ /* only available when bytecode interpreter is enabled. */+ /* */+ static FT_Error+ TT_Process_Composite_Glyph( TT_Loader loader,+ FT_UInt start_point,+ FT_UInt start_contour )+ {+ FT_Error error;+ FT_Outline* outline;+ FT_UInt i;+++ outline = &loader->gloader->base.outline;++ /* make room for phantom points */+ error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader,+ outline->n_points + 4,+ 0 );+ if ( error )+ return error;++ outline->points[outline->n_points ] = loader->pp1;+ outline->points[outline->n_points + 1] = loader->pp2;+ outline->points[outline->n_points + 2] = loader->pp3;+ outline->points[outline->n_points + 3] = loader->pp4;++ outline->tags[outline->n_points ] = 0;+ outline->tags[outline->n_points + 1] = 0;+ outline->tags[outline->n_points + 2] = 0;+ outline->tags[outline->n_points + 3] = 0;++#ifdef TT_USE_BYTECODE_INTERPRETER++ {+ FT_Stream stream = loader->stream;+ FT_UShort n_ins, max_ins;+ FT_ULong tmp;+++ /* TT_Load_Composite_Glyph only gives us the offset of instructions */+ /* so we read them here */+ if ( FT_STREAM_SEEK( loader->ins_pos ) ||+ FT_READ_USHORT( n_ins ) )+ return error;++ FT_TRACE5(( " Instructions size = %d\n", n_ins ));++ /* check it */+ max_ins = ((TT_Face)loader->face)->max_profile.maxSizeOfInstructions;+ if ( n_ins > max_ins )+ {+ /* acroread ignores this field, so we only do a rough safety check */+ if ( (FT_Int)n_ins > loader->byte_len )+ {+ FT_TRACE1(( "TT_Process_Composite_Glyph: "+ "too many instructions (%d) for glyph with length %d\n",+ n_ins, loader->byte_len ));+ return TT_Err_Too_Many_Hints;+ }++ tmp = loader->exec->glyphSize;+ error = Update_Max( loader->exec->memory,+ &tmp,+ sizeof ( FT_Byte ),+ (void*)&loader->exec->glyphIns,+ n_ins );+ loader->exec->glyphSize = (FT_UShort)tmp;+ if ( error )+ return error;+ }+ else if ( n_ins == 0 )+ return TT_Err_Ok;++ if ( FT_STREAM_READ( loader->exec->glyphIns, n_ins ) )+ return error;++ loader->glyph->control_data = loader->exec->glyphIns;+ loader->glyph->control_len = n_ins;+ }++#endif++ tt_prepare_zone( &loader->zone, &loader->gloader->base,+ start_point, start_contour );++ /* Some points are likely touched during execution of */+ /* instructions on components. So let's untouch them. */+ for ( i = start_point; i < loader->zone.n_points; i++ )+ loader->zone.tags[i] &= ~FT_CURVE_TAG_TOUCH_BOTH;++ loader->zone.n_points += 4;++ return TT_Hint_Glyph( loader, 1 );+ }+++ /* Calculate the four phantom points. */+ /* The first two stand for horizontal origin and advance. */+ /* The last two stand for vertical origin and advance. */+#define TT_LOADER_SET_PP( loader ) \+ do { \+ (loader)->pp1.x = (loader)->bbox.xMin - (loader)->left_bearing; \+ (loader)->pp1.y = 0; \+ (loader)->pp2.x = (loader)->pp1.x + (loader)->advance; \+ (loader)->pp2.y = 0; \+ (loader)->pp3.x = 0; \+ (loader)->pp3.y = (loader)->top_bearing + (loader)->bbox.yMax; \+ (loader)->pp4.x = 0; \+ (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance; \+ } while ( 0 )+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* load_truetype_glyph */+ /* */+ /* <Description> */+ /* Loads a given truetype glyph. Handles composites and uses a */+ /* TT_Loader object. */+ /* */+ static FT_Error+ load_truetype_glyph( TT_Loader loader,+ FT_UInt glyph_index,+ FT_UInt recurse_count,+ FT_Bool header_only )+ {+ FT_Error error = TT_Err_Ok;+ FT_Fixed x_scale, y_scale;+ FT_ULong offset;+ TT_Face face = (TT_Face)loader->face;+ FT_GlyphLoader gloader = loader->gloader;+ FT_Bool opened_frame = 0;++#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT+ FT_Vector* deltas = NULL;+#endif++#ifdef FT_CONFIG_OPTION_INCREMENTAL+ FT_StreamRec inc_stream;+ FT_Data glyph_data;+ FT_Bool glyph_data_loaded = 0;+#endif+++ /* some fonts have an incorrect value of `maxComponentDepth', */+ /* thus we allow depth 1 to catch the majority of them */+ if ( recurse_count > 1 &&+ recurse_count > face->max_profile.maxComponentDepth )+ {+ error = TT_Err_Invalid_Composite;+ goto Exit;+ }++ /* check glyph index */+ if ( glyph_index >= (FT_UInt)face->root.num_glyphs )+ {+ error = TT_Err_Invalid_Glyph_Index;+ goto Exit;+ }++ loader->glyph_index = glyph_index;++ 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;+ }+ else+ {+ x_scale = 0x10000L;+ y_scale = 0x10000L;+ }++ tt_get_metrics( loader, glyph_index );++ /* Set `offset' to the start of the glyph relative to the start of */+ /* the `glyf' table, and `byte_len' to the length of the glyph in */+ /* bytes. */++#ifdef FT_CONFIG_OPTION_INCREMENTAL++ /* If we are loading glyph data via the incremental interface, set */+ /* the loader stream to a memory stream reading the data returned */+ /* by the interface. */+ if ( face->root.internal->incremental_interface )+ {+ error = face->root.internal->incremental_interface->funcs->get_glyph_data(+ face->root.internal->incremental_interface->object,+ glyph_index, &glyph_data );+ if ( error )+ goto Exit;++ glyph_data_loaded = 1;+ offset = 0;+ loader->byte_len = glyph_data.length;++ FT_MEM_ZERO( &inc_stream, sizeof ( inc_stream ) );+ FT_Stream_OpenMemory( &inc_stream,+ glyph_data.pointer, glyph_data.length );++ loader->stream = &inc_stream;+ }+ else++#endif /* FT_CONFIG_OPTION_INCREMENTAL */++ offset = tt_face_get_location( face, glyph_index,+ (FT_UInt*)&loader->byte_len );++ if ( loader->byte_len > 0 )+ {+#ifdef FT_CONFIG_OPTION_INCREMENTAL+ /* for the incremental interface, `glyf_offset' is always zero */+ if ( !loader->glyf_offset &&+ !face->root.internal->incremental_interface )+#else+ if ( !loader->glyf_offset )+#endif /* FT_CONFIG_OPTION_INCREMENTAL */+ {+ FT_TRACE2(( "no `glyf' table but non-zero `loca' entry\n" ));+ error = TT_Err_Invalid_Table;+ goto Exit;+ }++ error = face->access_glyph_frame( loader, glyph_index,+ loader->glyf_offset + offset,+ loader->byte_len );+ if ( error )+ goto Exit;++ opened_frame = 1;++ /* read glyph header first */+ error = face->read_glyph_header( loader );+ if ( error || header_only )+ goto Exit;+ }++ if ( loader->byte_len == 0 || loader->n_contours == 0 )+ {+ loader->bbox.xMin = 0;+ loader->bbox.xMax = 0;+ loader->bbox.yMin = 0;+ loader->bbox.yMax = 0;++ if ( header_only )+ goto Exit;++ /* must initialize points before (possibly) overriding */+ /* glyph metrics from the incremental interface */+ TT_LOADER_SET_PP( loader );++#ifdef FT_CONFIG_OPTION_INCREMENTAL+ tt_get_metrics_incr_overrides( loader, glyph_index );+#endif++#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT++ if ( ((TT_Face)(loader->face))->doblend )+ {+ /* this must be done before scaling */+ FT_Memory memory = loader->face->memory;+++ error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),+ glyph_index, &deltas, 4 );+ if ( error )+ goto Exit;++ loader->pp1.x += deltas[0].x; loader->pp1.y += deltas[0].y;+ loader->pp2.x += deltas[1].x; loader->pp2.y += deltas[1].y;+ loader->pp3.x += deltas[2].x; loader->pp3.y += deltas[2].y;+ loader->pp4.x += deltas[3].x; loader->pp4.y += deltas[3].y;++ FT_FREE( deltas );+ }++#endif++ if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )+ {+ loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );+ loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );+ loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );+ loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );+ }++ error = TT_Err_Ok;+ goto Exit;+ }++ /* must initialize points before (possibly) overriding */+ /* glyph metrics from the incremental interface */+ TT_LOADER_SET_PP( loader );++#ifdef FT_CONFIG_OPTION_INCREMENTAL+ tt_get_metrics_incr_overrides( loader, glyph_index );+#endif++ /***********************************************************************/+ /***********************************************************************/+ /***********************************************************************/++ /* if it is a simple glyph, load it */++ if ( loader->n_contours > 0 )+ {+ error = face->read_simple_glyph( loader );+ if ( error )+ goto Exit;++ /* all data have been read */+ face->forget_glyph_frame( loader );+ opened_frame = 0;++ error = TT_Process_Simple_Glyph( loader );+ if ( error )+ goto Exit;++ FT_GlyphLoader_Add( gloader );+ }++ /***********************************************************************/+ /***********************************************************************/+ /***********************************************************************/++ /* otherwise, load a composite! */+ else if ( loader->n_contours == -1 )+ {+ FT_UInt start_point;+ FT_UInt start_contour;+ FT_ULong ins_pos; /* position of composite instructions, if any */+++ start_point = gloader->base.outline.n_points;+ start_contour = gloader->base.outline.n_contours;++ /* for each subglyph, read composite header */+ error = face->read_composite_glyph( loader );+ if ( error )+ goto Exit;++ /* store the offset of instructions */+ ins_pos = loader->ins_pos;++ /* all data we need are read */+ face->forget_glyph_frame( loader );+ opened_frame = 0;++#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT++ if ( face->doblend )+ {+ FT_Int i, limit;+ FT_SubGlyph subglyph;+ FT_Memory memory = face->root.memory;+++ /* this provides additional offsets */+ /* for each component's translation */++ if ( ( error = TT_Vary_Get_Glyph_Deltas(+ face,+ glyph_index,+ &deltas,+ gloader->current.num_subglyphs + 4 )) != 0 )+ goto Exit;++ subglyph = gloader->current.subglyphs + gloader->base.num_subglyphs;+ limit = gloader->current.num_subglyphs;++ for ( i = 0; i < limit; ++i, ++subglyph )+ {+ if ( subglyph->flags & ARGS_ARE_XY_VALUES )+ {+ /* XXX: overflow check for subglyph->{arg1,arg2}. */+ /* deltas[i].{x,y} must be within signed 16-bit, */+ /* but the restriction of summed delta is not clear */+ subglyph->arg1 += (FT_Int16)deltas[i].x;+ subglyph->arg2 += (FT_Int16)deltas[i].y;+ }+ }++ loader->pp1.x += deltas[i + 0].x; loader->pp1.y += deltas[i + 0].y;+ loader->pp2.x += deltas[i + 1].x; loader->pp2.y += deltas[i + 1].y;+ loader->pp3.x += deltas[i + 2].x; loader->pp3.y += deltas[i + 2].y;+ loader->pp4.x += deltas[i + 3].x; loader->pp4.y += deltas[i + 3].y;++ FT_FREE( deltas );+ }++#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */++ if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )+ {+ loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );+ loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );+ loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );+ loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );+ }++ /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */+ /* `as is' in the glyph slot (the client application will be */+ /* responsible for interpreting these data)... */+ if ( loader->load_flags & FT_LOAD_NO_RECURSE )+ {+ FT_GlyphLoader_Add( gloader );+ loader->glyph->format = FT_GLYPH_FORMAT_COMPOSITE;++ goto Exit;+ }++ /*********************************************************************/+ /*********************************************************************/+ /*********************************************************************/++ {+ FT_UInt n, num_base_points;+ FT_SubGlyph subglyph = 0;++ FT_UInt num_points = start_point;+ FT_UInt num_subglyphs = gloader->current.num_subglyphs;+ FT_UInt num_base_subgs = gloader->base.num_subglyphs;++ FT_Stream old_stream = loader->stream;+ FT_Int old_byte_len = loader->byte_len;+++ FT_GlyphLoader_Add( gloader );++ /* read each subglyph independently */+ for ( n = 0; n < num_subglyphs; n++ )+ {+ FT_Vector pp[4];+++ /* Each time we call load_truetype_glyph in this loop, the */+ /* value of `gloader.base.subglyphs' can change due to table */+ /* reallocations. We thus need to recompute the subglyph */+ /* pointer on each iteration. */+ subglyph = gloader->base.subglyphs + num_base_subgs + n;++ pp[0] = loader->pp1;+ pp[1] = loader->pp2;+ pp[2] = loader->pp3;+ pp[3] = loader->pp4;++ num_base_points = gloader->base.outline.n_points;++ error = load_truetype_glyph( loader, subglyph->index,+ recurse_count + 1, FALSE );+ if ( error )+ goto Exit;++ /* restore subglyph pointer */+ subglyph = gloader->base.subglyphs + num_base_subgs + n;++ if ( !( subglyph->flags & USE_MY_METRICS ) )+ {+ loader->pp1 = pp[0];+ loader->pp2 = pp[1];+ loader->pp3 = pp[2];+ loader->pp4 = pp[3];+ }++ num_points = gloader->base.outline.n_points;++ if ( num_points == num_base_points )+ continue;++ /* gloader->base.outline consists of three parts: */+ /* 0 -(1)-> start_point -(2)-> num_base_points -(3)-> n_points. */+ /* */+ /* (1): exists from the beginning */+ /* (2): components that have been loaded so far */+ /* (3): the newly loaded component */+ TT_Process_Composite_Component( loader, subglyph, start_point,+ num_base_points );+ }++ loader->stream = old_stream;+ loader->byte_len = old_byte_len;++ /* process the glyph */+ loader->ins_pos = ins_pos;+ if ( IS_HINTED( loader->load_flags ) &&++#ifdef TT_USE_BYTECODE_INTERPRETER++ subglyph->flags & WE_HAVE_INSTR &&++#endif++ num_points > start_point )+ TT_Process_Composite_Glyph( loader, start_point, start_contour );++ }+ }+ else+ {+ /* invalid composite count (negative but not -1) */+ error = TT_Err_Invalid_Outline;+ goto Exit;+ }++ /***********************************************************************/+ /***********************************************************************/+ /***********************************************************************/++ Exit:++ if ( opened_frame )+ face->forget_glyph_frame( loader );++#ifdef FT_CONFIG_OPTION_INCREMENTAL++ if ( glyph_data_loaded )+ face->root.internal->incremental_interface->funcs->free_glyph_data(+ face->root.internal->incremental_interface->object,+ &glyph_data );++#endif++ return error;+ }+++ static FT_Error+ compute_glyph_metrics( TT_Loader loader,+ FT_UInt glyph_index )+ {+ FT_BBox bbox;+ TT_Face face = (TT_Face)loader->face;+ FT_Fixed y_scale;+ TT_GlyphSlot glyph = loader->glyph;+ TT_Size size = (TT_Size)loader->size;+++ y_scale = 0x10000L;+ if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )+ y_scale = size->root.metrics.y_scale;++ if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE )+ FT_Outline_Get_CBox( &glyph->outline, &bbox );+ else+ bbox = loader->bbox;++ /* get the device-independent horizontal advance; it is scaled later */+ /* by the base layer. */+ {+ FT_Pos advance = loader->linear;+++ /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */+ /* correctly support DynaLab fonts, which have an incorrect */+ /* `advance_Width_Max' field! It is used, to my knowledge, */+ /* exclusively in the X-TrueType font server. */+ /* */+ if ( face->postscript.isFixedPitch &&+ ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )+ advance = face->horizontal.advance_Width_Max;++ /* we need to return the advance in font units in linearHoriAdvance, */+ /* it will be scaled later by the base layer. */+ glyph->linearHoriAdvance = advance;+ }++ glyph->metrics.horiBearingX = bbox.xMin;+ glyph->metrics.horiBearingY = bbox.yMax;+ glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;++ /* adjust advance width to the value contained in the hdmx table */+ if ( !face->postscript.isFixedPitch &&+ IS_HINTED( loader->load_flags ) )+ {+ FT_Byte* widthp;+++ widthp = tt_face_get_device_metrics( face,+ size->root.metrics.x_ppem,+ glyph_index );++ if ( widthp )+ glyph->metrics.horiAdvance = *widthp << 6;+ }++ /* set glyph dimensions */+ glyph->metrics.width = bbox.xMax - bbox.xMin;+ glyph->metrics.height = bbox.yMax - bbox.yMin;++ /* Now take care of vertical metrics. In the case where there is */+ /* no vertical information within the font (relatively common), */+ /* create some metrics manually */+ {+ FT_Pos top; /* scaled vertical top side bearing */+ FT_Pos advance; /* scaled vertical advance height */+++ /* Get the unscaled top bearing and advance height. */+ if ( face->vertical_info &&+ face->vertical.number_Of_VMetrics > 0 )+ {+ top = (FT_Short)FT_DivFix( loader->pp3.y - bbox.yMax,+ y_scale );++ if ( loader->pp3.y <= loader->pp4.y )+ advance = 0;+ else+ advance = (FT_UShort)FT_DivFix( loader->pp3.y - loader->pp4.y,+ y_scale );+ }+ else+ {+ FT_Pos height;+++ /* XXX Compute top side bearing and advance height in */+ /* Get_VMetrics instead of here. */++ /* NOTE: The OS/2 values are the only `portable' ones, */+ /* which is why we use them, if there is an OS/2 */+ /* table in the font. Otherwise, we use the */+ /* values defined in the horizontal header. */++ height = (FT_Short)FT_DivFix( bbox.yMax - bbox.yMin,+ y_scale );+ if ( face->os2.version != 0xFFFFU )+ advance = (FT_Pos)( face->os2.sTypoAscender -+ face->os2.sTypoDescender );+ else+ advance = (FT_Pos)( face->horizontal.Ascender -+ face->horizontal.Descender );++ top = ( advance - height ) / 2;+ }++#ifdef FT_CONFIG_OPTION_INCREMENTAL+ {+ FT_Incremental_InterfaceRec* incr;+ FT_Incremental_MetricsRec metrics;+ FT_Error error;+++ incr = face->root.internal->incremental_interface;++ /* If this is an incrementally loaded font see if there are */+ /* overriding metrics for this glyph. */+ if ( incr && incr->funcs->get_glyph_metrics )+ {+ metrics.bearing_x = 0;+ metrics.bearing_y = top;+ metrics.advance = advance;++ error = incr->funcs->get_glyph_metrics( incr->object,+ glyph_index,+ TRUE,+ &metrics );+ if ( error )+ return error;++ top = metrics.bearing_y;+ advance = metrics.advance;+ }+ }++ /* GWW: Do vertical metrics get loaded incrementally too? */++#endif /* FT_CONFIG_OPTION_INCREMENTAL */++ glyph->linearVertAdvance = advance;++ /* scale the metrics */+ if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )+ {+ top = FT_MulFix( top, y_scale );+ advance = FT_MulFix( advance, y_scale );+ }++ /* XXX: for now, we have no better algorithm for the lsb, but it */+ /* should work fine. */+ /* */+ glyph->metrics.vertBearingX = glyph->metrics.horiBearingX -+ glyph->metrics.horiAdvance / 2;+ glyph->metrics.vertBearingY = top;+ glyph->metrics.vertAdvance = advance;+ }++ return 0;+ }+++#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS++ static FT_Error+ load_sbit_image( TT_Size size,+ TT_GlyphSlot glyph,+ FT_UInt glyph_index,+ FT_Int32 load_flags )+ {+ TT_Face face;+ SFNT_Service sfnt;+ FT_Stream stream;+ FT_Error error;+ TT_SBit_MetricsRec metrics;+++ face = (TT_Face)glyph->face;+ sfnt = (SFNT_Service)face->sfnt;+ stream = face->root.stream;++ error = sfnt->load_sbit_image( face,+ size->strike_index,+ glyph_index,+ (FT_Int)load_flags,+ stream,+ &glyph->bitmap,+ &metrics );+ if ( !error )+ {+ 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.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;+ glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;+ glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6;++ 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->format = FT_GLYPH_FORMAT_BITMAP;++ if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )+ {+ glyph->bitmap_left = metrics.vertBearingX;+ glyph->bitmap_top = metrics.vertBearingY;+ }+ else+ {+ glyph->bitmap_left = metrics.horiBearingX;+ glyph->bitmap_top = metrics.horiBearingY;+ }+ }++ return error;+ }++#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */+++ static FT_Error+ tt_loader_init( TT_Loader loader,+ TT_Size size,+ TT_GlyphSlot glyph,+ FT_Int32 load_flags,+ FT_Bool glyf_table_only )+ {+ TT_Face face;+ FT_Stream stream;+++ face = (TT_Face)glyph->face;+ stream = face->root.stream;++ FT_MEM_ZERO( loader, sizeof ( TT_LoaderRec ) );++#ifdef TT_USE_BYTECODE_INTERPRETER++ /* load execution context */+ if ( IS_HINTED( load_flags ) && !glyf_table_only )+ {+ TT_ExecContext exec;+ FT_Bool grayscale;+++ if ( !size->cvt_ready )+ {+ FT_Error error = tt_size_ready_bytecode( size );+ if ( error )+ return error;+ }++ /* query new execution context */+ exec = size->debug ? size->context+ : ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;+ if ( !exec )+ return TT_Err_Could_Not_Find_Context;++ grayscale =+ FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != FT_RENDER_MODE_MONO );++ TT_Load_Context( exec, face, size );++ /* a change from mono to grayscale rendering (and vice versa) */+ /* requires a re-execution of the CVT program */+ if ( grayscale != exec->grayscale )+ {+ FT_UInt i;+++ FT_TRACE4(( "tt_loader_init: grayscale change,"+ " re-executing `prep' table\n" ));++ exec->grayscale = grayscale;++ for ( i = 0; i < size->cvt_size; i++ )+ size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );+ tt_size_run_prep( size );+ }++ /* see whether the cvt program has disabled hinting */+ if ( exec->GS.instruct_control & 1 )+ load_flags |= FT_LOAD_NO_HINTING;++ /* load default graphics state -- if needed */+ if ( exec->GS.instruct_control & 2 )+ exec->GS = tt_default_graphics_state;++ exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );+ loader->exec = exec;+ loader->instructions = exec->glyphIns;+ }++#endif /* TT_USE_BYTECODE_INTERPRETER */++ /* seek to the beginning of the glyph table -- for Type 42 fonts */+ /* the table might be accessed from a Postscript stream or something */+ /* else... */++#ifdef FT_CONFIG_OPTION_INCREMENTAL++ if ( face->root.internal->incremental_interface )+ loader->glyf_offset = 0;+ else++#endif++ {+ FT_Error error = face->goto_table( face, TTAG_glyf, stream, 0 );+++ if ( error == TT_Err_Table_Missing )+ loader->glyf_offset = 0;+ else if ( error )+ {+ FT_ERROR(( "tt_loader_init: could not access glyph table\n" ));+ return error;+ }+ else+ loader->glyf_offset = FT_STREAM_POS();+ }++ /* get face's glyph loader */+ if ( !glyf_table_only )+ {+ FT_GlyphLoader gloader = glyph->internal->loader;+++ FT_GlyphLoader_Rewind( gloader );+ loader->gloader = gloader;+ }++ loader->load_flags = load_flags;++ loader->face = (FT_Face)face;+ loader->size = (FT_Size)size;+ loader->glyph = (FT_GlyphSlot)glyph;+ loader->stream = stream;++ return TT_Err_Ok;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* TT_Load_Glyph */+ /* */+ /* <Description> */+ /* A function used to load a single glyph within a given glyph slot, */+ /* for a given size. */+ /* */+ /* <Input> */+ /* glyph :: A handle to a target slot object where the glyph */+ /* will be loaded. */+ /* */+ /* size :: A handle to the source face size at which the glyph */+ /* must be scaled/loaded. */+ /* */+ /* glyph_index :: The index of the glyph in the font file. */+ /* */+ /* load_flags :: A flag indicating what to load for this glyph. The */+ /* FT_LOAD_XXX constants can be used to control the */+ /* glyph loading process (e.g., whether the outline */+ /* should be scaled, whether to load bitmaps or not, */+ /* whether to hint the outline, etc). */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ TT_Load_Glyph( TT_Size size,+ TT_GlyphSlot glyph,+ FT_UInt glyph_index,+ FT_Int32 load_flags )+ {+ TT_Face face;+ FT_Error error;+ TT_LoaderRec loader;+++ face = (TT_Face)glyph->face;+ error = TT_Err_Ok;++#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS++ /* try to load embedded bitmap if any */+ /* */+ /* XXX: The convention should be emphasized in */+ /* the documents because it can be confusing. */+ if ( size->strike_index != 0xFFFFFFFFUL &&+ ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )+ {+ error = load_sbit_image( size, glyph, glyph_index, load_flags );+ if ( !error )+ {+ FT_Face root = &face->root;+++ if ( FT_IS_SCALABLE( root ) )+ {+ /* 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 );+ glyph->linearHoriAdvance = loader.linear;+ glyph->linearVertAdvance = loader.top_bearing + loader.bbox.yMax -+ loader.vadvance;+ if ( face->postscript.isFixedPitch &&+ ( load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )+ glyph->linearHoriAdvance = face->horizontal.advance_Width_Max;+ }++ return TT_Err_Ok;+ }+ }++#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */++ /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */+ if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid )+ return TT_Err_Invalid_Size_Handle;++ if ( load_flags & FT_LOAD_SBITS_ONLY )+ return TT_Err_Invalid_Argument;++ error = tt_loader_init( &loader, size, glyph, load_flags, FALSE );+ if ( error )+ return error;++ glyph->format = FT_GLYPH_FORMAT_OUTLINE;+ glyph->num_subglyphs = 0;+ glyph->outline.flags = 0;++ /* main loading loop */+ error = load_truetype_glyph( &loader, glyph_index, 0, FALSE );+ if ( !error )+ {+ if ( glyph->format == FT_GLYPH_FORMAT_COMPOSITE )+ {+ glyph->num_subglyphs = loader.gloader->base.num_subglyphs;+ glyph->subglyphs = loader.gloader->base.subglyphs;+ }+ else+ {+ glyph->outline = loader.gloader->base.outline;+ glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS;++ /* Translate array so that (0,0) is the glyph's origin. Note */+ /* that this behaviour is independent on the value of bit 1 of */+ /* the `flags' field in the `head' table -- at least major */+ /* applications like Acroread indicate that. */+ if ( loader.pp1.x )+ FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 );+ }++#ifdef TT_USE_BYTECODE_INTERPRETER++ if ( IS_HINTED( load_flags ) )+ {+ if ( loader.exec->GS.scan_control )+ {+ /* convert scan conversion mode to FT_OUTLINE_XXX flags */+ switch ( loader.exec->GS.scan_type )+ {+ case 0: /* simple drop-outs including stubs */+ glyph->outline.flags |= FT_OUTLINE_INCLUDE_STUBS;+ break;+ case 1: /* simple drop-outs excluding stubs */+ /* nothing; it's the default rendering mode */+ break;+ case 4: /* smart drop-outs including stubs */+ glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS |+ FT_OUTLINE_INCLUDE_STUBS;+ break;+ case 5: /* smart drop-outs excluding stubs */+ glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS;+ break;++ default: /* no drop-out control */+ glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;+ break;+ }+ }+ else+ glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;+ }++#endif /* TT_USE_BYTECODE_INTERPRETER */++ compute_glyph_metrics( &loader, glyph_index );+ }++ /* Set the `high precision' bit flag. */+ /* This is _critical_ to get correct output for monochrome */+ /* TrueType glyphs at all sizes using the bytecode interpreter. */+ /* */+ if ( !( load_flags & FT_LOAD_NO_SCALE ) &&+ size->root.metrics.y_ppem < 24 )+ glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;++ return error;+ }+++/* END */
+ src/truetype/ttgload.h view
@@ -0,0 +1,63 @@+/***************************************************************************/+/* */+/* ttgload.h */+/* */+/* TrueType Glyph Loader (specification). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2008 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 __TTGLOAD_H__+#define __TTGLOAD_H__+++#include <ft2build.h>+#include "ttobjs.h"++#ifdef TT_USE_BYTECODE_INTERPRETER+#include "ttinterp.h"+#endif+++FT_BEGIN_HEADER+++ FT_LOCAL( void )+ TT_Init_Glyph_Loading( TT_Face face );++ FT_LOCAL( void )+ TT_Get_HMetrics( TT_Face face,+ FT_UInt idx,+ FT_Bool check,+ FT_Short* lsb,+ FT_UShort* aw );++ FT_LOCAL( void )+ TT_Get_VMetrics( TT_Face face,+ FT_UInt idx,+ FT_Bool check,+ FT_Short* tsb,+ FT_UShort* ah );++ FT_LOCAL( FT_Error )+ TT_Load_Glyph( TT_Size size,+ TT_GlyphSlot glyph,+ FT_UInt glyph_index,+ FT_Int32 load_flags );+++FT_END_HEADER++#endif /* __TTGLOAD_H__ */+++/* END */
+ src/truetype/ttgxvar.c view
@@ -0,0 +1,1548 @@+/***************************************************************************/+/* */+/* ttgxvar.c */+/* */+/* TrueType GX Font Variation loader */+/* */+/* Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010 by */+/* David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. */+/* */+/* 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. */+/* */+/***************************************************************************/+++ /*************************************************************************/+ /* */+ /* Apple documents the `fvar', `gvar', `cvar', and `avar' tables at */+ /* */+ /* http://developer.apple.com/fonts/TTRefMan/RM06/Chap6[fgca]var.html */+ /* */+ /* The documentation for `fvar' is inconsistent. At one point it says */+ /* that `countSizePairs' should be 3, at another point 2. It should */+ /* be 2. */+ /* */+ /* The documentation for `gvar' is not intelligible; `cvar' refers you */+ /* to `gvar' and is thus also incomprehensible. */+ /* */+ /* The documentation for `avar' appears correct, but Apple has no fonts */+ /* with an `avar' table, so it is hard to test. */+ /* */+ /* Many thanks to John Jenkins (at Apple) in figuring this out. */+ /* */+ /* */+ /* Apple's `kern' table has some references to tuple indices, but as */+ /* there is no indication where these indices are defined, nor how to */+ /* interpolate the kerning values (different tuples have different */+ /* classes) this issue is ignored. */+ /* */+ /*************************************************************************/+++#include <ft2build.h>+#include FT_INTERNAL_DEBUG_H+#include FT_CONFIG_CONFIG_H+#include FT_INTERNAL_STREAM_H+#include FT_INTERNAL_SFNT_H+#include FT_TRUETYPE_TAGS_H+#include FT_MULTIPLE_MASTERS_H++#include "ttpload.h"+#include "ttgxvar.h"++#include "tterrors.h"+++#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT+++#define FT_Stream_FTell( stream ) \+ ( (stream)->cursor - (stream)->base )+#define FT_Stream_SeekSet( stream, off ) \+ ( (stream)->cursor = (stream)->base+(off) )+++ /*************************************************************************/+ /* */+ /* 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_ttgxvar+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** Internal Routines *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* The macro ALL_POINTS is used in `ft_var_readpackedpoints'. It */+ /* indicates that there is a delta for every point without needing to */+ /* enumerate all of them. */+ /* */+#define ALL_POINTS (FT_UShort*)( -1 )+++#define GX_PT_POINTS_ARE_WORDS 0x80+#define GX_PT_POINT_RUN_COUNT_MASK 0x7F+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* ft_var_readpackedpoints */+ /* */+ /* <Description> */+ /* Read a set of points to which the following deltas will apply. */+ /* Points are packed with a run length encoding. */+ /* */+ /* <Input> */+ /* stream :: The data stream. */+ /* */+ /* <Output> */+ /* point_cnt :: The number of points read. A zero value means that */+ /* all points in the glyph will be affected, without */+ /* enumerating them individually. */+ /* */+ /* <Return> */+ /* An array of FT_UShort containing the affected points or the */+ /* special value ALL_POINTS. */+ /* */+ static FT_UShort*+ ft_var_readpackedpoints( FT_Stream stream,+ FT_UInt *point_cnt )+ {+ FT_UShort *points;+ FT_Int n;+ FT_Int runcnt;+ FT_Int i;+ FT_Int j;+ FT_Int first;+ FT_Memory memory = stream->memory;+ FT_Error error = TT_Err_Ok;++ FT_UNUSED( error );+++ *point_cnt = n = FT_GET_BYTE();+ if ( n == 0 )+ return ALL_POINTS;++ if ( n & GX_PT_POINTS_ARE_WORDS )+ n = FT_GET_BYTE() | ( ( n & GX_PT_POINT_RUN_COUNT_MASK ) << 8 );++ if ( FT_NEW_ARRAY( points, n ) )+ return NULL;++ i = 0;+ while ( i < n )+ {+ runcnt = FT_GET_BYTE();+ if ( runcnt & GX_PT_POINTS_ARE_WORDS )+ {+ runcnt = runcnt & GX_PT_POINT_RUN_COUNT_MASK;+ first = points[i++] = FT_GET_USHORT();++ if ( runcnt < 1 || i + runcnt >= n )+ goto Exit;++ /* first point not included in runcount */+ for ( j = 0; j < runcnt; ++j )+ points[i++] = (FT_UShort)( first += FT_GET_USHORT() );+ }+ else+ {+ first = points[i++] = FT_GET_BYTE();++ if ( runcnt < 1 || i + runcnt >= n )+ goto Exit;++ for ( j = 0; j < runcnt; ++j )+ points[i++] = (FT_UShort)( first += FT_GET_BYTE() );+ }+ }++ Exit:+ return points;+ }+++ enum+ {+ GX_DT_DELTAS_ARE_ZERO = 0x80,+ GX_DT_DELTAS_ARE_WORDS = 0x40,+ GX_DT_DELTA_RUN_COUNT_MASK = 0x3F+ };+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* ft_var_readpackeddeltas */+ /* */+ /* <Description> */+ /* Read a set of deltas. These are packed slightly differently than */+ /* points. In particular there is no overall count. */+ /* */+ /* <Input> */+ /* stream :: The data stream. */+ /* */+ /* delta_cnt :: The number of to be read. */+ /* */+ /* <Return> */+ /* An array of FT_Short containing the deltas for the affected */+ /* points. (This only gets the deltas for one dimension. It will */+ /* generally be called twice, once for x, once for y. When used in */+ /* cvt table, it will only be called once.) */+ /* */+ static FT_Short*+ ft_var_readpackeddeltas( FT_Stream stream,+ FT_Offset delta_cnt )+ {+ FT_Short *deltas = NULL;+ FT_UInt runcnt;+ FT_Offset i;+ FT_UInt j;+ FT_Memory memory = stream->memory;+ FT_Error error = TT_Err_Ok;++ FT_UNUSED( error );+++ if ( FT_NEW_ARRAY( deltas, delta_cnt ) )+ return NULL;++ i = 0;+ while ( i < delta_cnt )+ {+ runcnt = FT_GET_BYTE();+ if ( runcnt & GX_DT_DELTAS_ARE_ZERO )+ {+ /* runcnt zeroes get added */+ for ( j = 0;+ j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt;+ ++j )+ deltas[i++] = 0;+ }+ else if ( runcnt & GX_DT_DELTAS_ARE_WORDS )+ {+ /* runcnt shorts from the stack */+ for ( j = 0;+ j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt;+ ++j )+ deltas[i++] = FT_GET_SHORT();+ }+ else+ {+ /* runcnt signed bytes from the stack */+ for ( j = 0;+ j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt;+ ++j )+ deltas[i++] = FT_GET_CHAR();+ }++ if ( j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) )+ {+ /* Bad format */+ FT_FREE( deltas );+ return NULL;+ }+ }++ return deltas;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* ft_var_load_avar */+ /* */+ /* <Description> */+ /* Parse the `avar' table if present. It need not be, so we return */+ /* nothing. */+ /* */+ /* <InOut> */+ /* face :: The font face. */+ /* */+ static void+ ft_var_load_avar( TT_Face face )+ {+ FT_Stream stream = FT_FACE_STREAM(face);+ FT_Memory memory = stream->memory;+ GX_Blend blend = face->blend;+ GX_AVarSegment segment;+ FT_Error error = TT_Err_Ok;+ FT_ULong version;+ FT_Long axisCount;+ FT_Int i, j;+ FT_ULong table_len;++ FT_UNUSED( error );+++ blend->avar_checked = TRUE;+ if ( (error = face->goto_table( face, TTAG_avar, stream, &table_len )) != 0 )+ return;++ if ( FT_FRAME_ENTER( table_len ) )+ return;++ version = FT_GET_LONG();+ axisCount = FT_GET_LONG();++ if ( version != 0x00010000L ||+ axisCount != (FT_Long)blend->mmvar->num_axis )+ goto Exit;++ if ( FT_NEW_ARRAY( blend->avar_segment, axisCount ) )+ goto Exit;++ segment = &blend->avar_segment[0];+ for ( i = 0; i < axisCount; ++i, ++segment )+ {+ segment->pairCount = FT_GET_USHORT();+ if ( 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. */++ for ( j = i - 1; j >= 0; --j )+ FT_FREE( blend->avar_segment[j].correspondence );++ FT_FREE( blend->avar_segment );+ blend->avar_segment = NULL;+ goto Exit;+ }++ for ( j = 0; j < segment->pairCount; ++j )+ {+ segment->correspondence[j].fromCoord =+ FT_GET_SHORT() << 2; /* convert to Fixed */+ segment->correspondence[j].toCoord =+ FT_GET_SHORT()<<2; /* convert to Fixed */+ }+ }++ Exit:+ FT_FRAME_EXIT();+ }+++ typedef struct GX_GVar_Head_+ {+ FT_Long version;+ FT_UShort axisCount;+ FT_UShort globalCoordCount;+ FT_ULong offsetToCoord;+ FT_UShort glyphCount;+ FT_UShort flags;+ FT_ULong offsetToData;++ } GX_GVar_Head;+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* ft_var_load_gvar */+ /* */+ /* <Description> */+ /* Parses the `gvar' table if present. If `fvar' is there, `gvar' */+ /* had better be there too. */+ /* */+ /* <InOut> */+ /* face :: The font face. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ static FT_Error+ ft_var_load_gvar( TT_Face face )+ {+ FT_Stream stream = FT_FACE_STREAM(face);+ FT_Memory memory = stream->memory;+ GX_Blend blend = face->blend;+ FT_Error error;+ FT_UInt i, j;+ FT_ULong table_len;+ FT_ULong gvar_start;+ FT_ULong offsetToData;+ GX_GVar_Head gvar_head;++ static const FT_Frame_Field gvar_fields[] =+ {++#undef FT_STRUCTURE+#define FT_STRUCTURE GX_GVar_Head++ FT_FRAME_START( 20 ),+ FT_FRAME_LONG ( version ),+ FT_FRAME_USHORT( axisCount ),+ FT_FRAME_USHORT( globalCoordCount ),+ FT_FRAME_ULONG ( offsetToCoord ),+ FT_FRAME_USHORT( glyphCount ),+ FT_FRAME_USHORT( flags ),+ FT_FRAME_ULONG ( offsetToData ),+ FT_FRAME_END+ };++ if ( (error = face->goto_table( face, TTAG_gvar, stream, &table_len )) != 0 )+ goto Exit;++ gvar_start = FT_STREAM_POS( );+ 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 != (FT_Long)0x00010000L ||+ gvar_head.axisCount != (FT_UShort)blend->mmvar->num_axis )+ {+ error = TT_Err_Invalid_Table;+ goto Exit;+ }++ if ( FT_NEW_ARRAY( blend->glyphoffsets, blend->gv_glyphcnt + 1 ) )+ goto Exit;++ if ( gvar_head.flags & 1 )+ {+ /* long offsets (one more offset than glyphs, to mark size of last) */+ if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 4L ) )+ goto Exit;++ for ( i = 0; i <= blend->gv_glyphcnt; ++i )+ blend->glyphoffsets[i] = offsetToData + FT_GET_LONG();++ FT_FRAME_EXIT();+ }+ else+ {+ /* short offsets (one more offset than glyphs, to mark size of last) */+ if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 2L ) )+ goto Exit;++ for ( i = 0; i <= blend->gv_glyphcnt; ++i )+ blend->glyphoffsets[i] = offsetToData + FT_GET_USHORT() * 2;+ /* XXX: Undocumented: `*2'! */++ FT_FRAME_EXIT();+ }++ if ( blend->tuplecount != 0 )+ {+ if ( FT_NEW_ARRAY( blend->tuplecoords,+ gvar_head.axisCount * blend->tuplecount ) )+ goto Exit;++ if ( FT_STREAM_SEEK( gvar_start + gvar_head.offsetToCoord ) ||+ FT_FRAME_ENTER( blend->tuplecount * gvar_head.axisCount * 2L ) )+ goto Exit;++ for ( i = 0; i < blend->tuplecount; ++i )+ 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_FRAME_EXIT();+ }++ Exit:+ return error;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* ft_var_apply_tuple */+ /* */+ /* <Description> */+ /* Figure out whether a given tuple (design) applies to the current */+ /* blend, and if so, what is the scaling factor. */+ /* */+ /* <Input> */+ /* blend :: The current blend of the font. */+ /* */+ /* tupleIndex :: A flag saying whether this is an intermediate */+ /* tuple or not. */+ /* */+ /* tuple_coords :: The coordinates of the tuple in normalized axis */+ /* units. */+ /* */+ /* im_start_coords :: The initial coordinates where this tuple starts */+ /* to apply (for intermediate coordinates). */+ /* */+ /* im_end_coords :: The final coordinates after which this tuple no */+ /* longer applies (for intermediate coordinates). */+ /* */+ /* <Return> */+ /* An FT_Fixed value containing the scaling factor. */+ /* */+ static FT_Fixed+ ft_var_apply_tuple( GX_Blend blend,+ FT_UShort tupleIndex,+ FT_Fixed* tuple_coords,+ FT_Fixed* im_start_coords,+ FT_Fixed* im_end_coords )+ {+ FT_UInt i;+ FT_Fixed apply;+ FT_Fixed temp;+++ apply = 0x10000L;+ for ( i = 0; i < blend->num_axis; ++i )+ {+ if ( tuple_coords[i] == 0 )+ /* It's not clear why (for intermediate tuples) we don't need */+ /* to check against start/end -- the documentation says we don't. */+ /* Similarly, it's unclear why we don't need to scale along the */+ /* axis. */+ continue;++ else if ( blend->normalizedcoords[i] == 0 ||+ ( blend->normalizedcoords[i] < 0 && tuple_coords[i] > 0 ) ||+ ( blend->normalizedcoords[i] > 0 && tuple_coords[i] < 0 ) )+ {+ apply = 0;+ break;+ }++ else if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) )+ /* not an intermediate tuple */+ apply = FT_MulDiv( apply,+ blend->normalizedcoords[i] > 0+ ? blend->normalizedcoords[i]+ : -blend->normalizedcoords[i],+ 0x10000L );++ else if ( blend->normalizedcoords[i] <= im_start_coords[i] ||+ blend->normalizedcoords[i] >= im_end_coords[i] )+ {+ apply = 0;+ break;+ }++ else if ( blend->normalizedcoords[i] < tuple_coords[i] )+ {+ temp = FT_MulDiv( blend->normalizedcoords[i] - im_start_coords[i],+ 0x10000L,+ tuple_coords[i] - im_start_coords[i]);+ apply = FT_MulDiv( apply, temp, 0x10000L );+ }++ else+ {+ temp = FT_MulDiv( im_end_coords[i] - blend->normalizedcoords[i],+ 0x10000L,+ im_end_coords[i] - tuple_coords[i] );+ apply = FT_MulDiv( apply, temp, 0x10000L );+ }+ }++ return apply;+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** MULTIPLE MASTERS SERVICE FUNCTIONS *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+++ typedef struct GX_FVar_Head_+ {+ FT_Long version;+ FT_UShort offsetToData;+ FT_UShort countSizePairs;+ FT_UShort axisCount;+ FT_UShort axisSize;+ FT_UShort instanceCount;+ FT_UShort instanceSize;++ } GX_FVar_Head;+++ typedef struct fvar_axis_+ {+ FT_ULong axisTag;+ FT_ULong minValue;+ FT_ULong defaultValue;+ FT_ULong maxValue;+ FT_UShort flags;+ FT_UShort nameID;++ } GX_FVar_Axis;+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* TT_Get_MM_Var */+ /* */+ /* <Description> */+ /* Check that the font's `fvar' table is valid, parse it, and return */+ /* those data. */+ /* */+ /* <InOut> */+ /* face :: The font face. */+ /* TT_Get_MM_Var initializes the blend structure. */+ /* */+ /* <Output> */+ /* master :: The `fvar' data (must be freed by caller). */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ TT_Get_MM_Var( TT_Face face,+ FT_MM_Var* *master )+ {+ FT_Stream stream = face->root.stream;+ FT_Memory memory = face->root.memory;+ FT_ULong table_len;+ FT_Error error = TT_Err_Ok;+ FT_ULong fvar_start;+ FT_Int i, j;+ FT_MM_Var* mmvar;+ FT_Fixed* next_coords;+ FT_String* next_name;+ FT_Var_Axis* a;+ FT_Var_Named_Style* ns;+ GX_FVar_Head fvar_head;++ static const FT_Frame_Field fvar_fields[] =+ {++#undef FT_STRUCTURE+#define FT_STRUCTURE GX_FVar_Head++ FT_FRAME_START( 16 ),+ FT_FRAME_LONG ( version ),+ FT_FRAME_USHORT( offsetToData ),+ FT_FRAME_USHORT( countSizePairs ),+ FT_FRAME_USHORT( axisCount ),+ FT_FRAME_USHORT( axisSize ),+ FT_FRAME_USHORT( instanceCount ),+ FT_FRAME_USHORT( instanceSize ),+ FT_FRAME_END+ };++ static const FT_Frame_Field fvaraxis_fields[] =+ {++#undef FT_STRUCTURE+#define FT_STRUCTURE GX_FVar_Axis++ FT_FRAME_START( 20 ),+ FT_FRAME_ULONG ( axisTag ),+ FT_FRAME_ULONG ( minValue ),+ FT_FRAME_ULONG ( defaultValue ),+ FT_FRAME_ULONG ( maxValue ),+ FT_FRAME_USHORT( flags ),+ FT_FRAME_USHORT( nameID ),+ FT_FRAME_END+ };+++ if ( face->blend == NULL )+ {+ /* both `fvar' and `gvar' must be present */+ if ( (error = face->goto_table( face, TTAG_gvar,+ stream, &table_len )) != 0 )+ goto Exit;++ if ( (error = face->goto_table( face, TTAG_fvar,+ stream, &table_len )) != 0 )+ goto Exit;++ fvar_start = FT_STREAM_POS( );++ if ( FT_STREAM_READ_FIELDS( fvar_fields, &fvar_head ) )+ goto Exit;++ if ( fvar_head.version != (FT_Long)0x00010000L ||+ fvar_head.countSizePairs != 2 ||+ fvar_head.axisSize != 20 ||+ /* axisCount limit implied by 16-bit instanceSize */+ fvar_head.axisCount > 0x3FFE ||+ fvar_head.instanceSize != 4 + 4 * fvar_head.axisCount ||+ /* instanceCount limit implied by limited range of name IDs */+ fvar_head.instanceCount > 0x7EFF ||+ fvar_head.offsetToData + fvar_head.axisCount * 20U ++ fvar_head.instanceCount * fvar_head.instanceSize > table_len )+ {+ error = TT_Err_Invalid_Table;+ goto Exit;+ }++ if ( FT_NEW( face->blend ) )+ goto Exit;++ /* cannot overflow 32-bit arithmetic because of limits above */+ face->blend->mmvar_len =+ sizeof ( FT_MM_Var ) ++ fvar_head.axisCount * sizeof ( FT_Var_Axis ) ++ fvar_head.instanceCount * sizeof ( FT_Var_Named_Style ) ++ fvar_head.instanceCount * fvar_head.axisCount * sizeof ( FT_Fixed ) ++ 5 * fvar_head.axisCount;++ if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) )+ goto Exit;+ face->blend->mmvar = mmvar;++ mmvar->num_axis =+ fvar_head.axisCount;+ mmvar->num_designs =+ (FT_UInt)-1; /* meaningless in this context; each glyph */+ /* may have a different number of designs */+ /* (or tuples, as called by Apple) */+ mmvar->num_namedstyles =+ fvar_head.instanceCount;+ mmvar->axis =+ (FT_Var_Axis*)&(mmvar[1]);+ mmvar->namedstyle =+ (FT_Var_Named_Style*)&(mmvar->axis[fvar_head.axisCount]);++ next_coords =+ (FT_Fixed*)&(mmvar->namedstyle[fvar_head.instanceCount]);+ for ( i = 0; i < fvar_head.instanceCount; ++i )+ {+ mmvar->namedstyle[i].coords = next_coords;+ next_coords += fvar_head.axisCount;+ }++ next_name = (FT_String*)next_coords;+ for ( i = 0; i < fvar_head.axisCount; ++i )+ {+ mmvar->axis[i].name = next_name;+ next_name += 5;+ }++ if ( FT_STREAM_SEEK( fvar_start + fvar_head.offsetToData ) )+ goto Exit;++ a = mmvar->axis;+ for ( i = 0; i < fvar_head.axisCount; ++i )+ {+ GX_FVar_Axis axis_rec;+++ if ( FT_STREAM_READ_FIELDS( fvaraxis_fields, &axis_rec ) )+ goto Exit;+ a->tag = axis_rec.axisTag;+ a->minimum = axis_rec.minValue; /* A Fixed */+ a->def = axis_rec.defaultValue; /* A Fixed */+ a->maximum = axis_rec.maxValue; /* A Fixed */+ a->strid = axis_rec.nameID;++ a->name[0] = (FT_String)( a->tag >> 24 );+ a->name[1] = (FT_String)( ( a->tag >> 16 ) & 0xFF );+ a->name[2] = (FT_String)( ( a->tag >> 8 ) & 0xFF );+ a->name[3] = (FT_String)( ( a->tag ) & 0xFF );+ a->name[4] = 0;++ ++a;+ }++ ns = mmvar->namedstyle;+ for ( i = 0; i < fvar_head.instanceCount; ++i, ++ns )+ {+ if ( FT_FRAME_ENTER( 4L + 4L * fvar_head.axisCount ) )+ goto Exit;++ ns->strid = FT_GET_USHORT();+ (void) /* flags = */ FT_GET_USHORT();++ for ( j = 0; j < fvar_head.axisCount; ++j )+ ns->coords[j] = FT_GET_ULONG(); /* A Fixed */++ FT_FRAME_EXIT();+ }+ }++ if ( master != NULL )+ {+ FT_UInt n;+++ if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) )+ goto Exit;+ FT_MEM_COPY( mmvar, face->blend->mmvar, face->blend->mmvar_len );++ mmvar->axis =+ (FT_Var_Axis*)&(mmvar[1]);+ mmvar->namedstyle =+ (FT_Var_Named_Style*)&(mmvar->axis[mmvar->num_axis]);+ next_coords =+ (FT_Fixed*)&(mmvar->namedstyle[mmvar->num_namedstyles]);++ for ( n = 0; n < mmvar->num_namedstyles; ++n )+ {+ mmvar->namedstyle[n].coords = next_coords;+ next_coords += mmvar->num_axis;+ }++ a = mmvar->axis;+ next_name = (FT_String*)next_coords;+ for ( n = 0; n < mmvar->num_axis; ++n )+ {+ a->name = next_name;++ /* standard PostScript names for some standard apple tags */+ if ( a->tag == TTAG_wght )+ a->name = (char *)"Weight";+ else if ( a->tag == TTAG_wdth )+ a->name = (char *)"Width";+ else if ( a->tag == TTAG_opsz )+ a->name = (char *)"OpticalSize";+ else if ( a->tag == TTAG_slnt )+ a->name = (char *)"Slant";++ next_name += 5;+ ++a;+ }++ *master = mmvar;+ }++ Exit:+ return error;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* TT_Set_MM_Blend */+ /* */+ /* <Description> */+ /* Set the blend (normalized) coordinates for this instance of the */+ /* font. Check that the `gvar' table is reasonable and does some */+ /* initial preparation. */+ /* */+ /* <InOut> */+ /* face :: The font. */+ /* Initialize the blend structure with `gvar' data. */+ /* */+ /* <Input> */+ /* num_coords :: Must be the axis count of the font. */+ /* */+ /* coords :: An array of num_coords, each between [-1,1]. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ TT_Set_MM_Blend( TT_Face face,+ FT_UInt num_coords,+ FT_Fixed* coords )+ {+ FT_Error error = TT_Err_Ok;+ GX_Blend blend;+ FT_MM_Var* mmvar;+ FT_UInt i;+ FT_Memory memory = face->root.memory;++ enum+ {+ mcvt_retain,+ mcvt_modify,+ mcvt_load++ } manageCvt;+++ face->doblend = FALSE;++ if ( face->blend == NULL )+ {+ if ( (error = TT_Get_MM_Var( face, NULL)) != 0 )+ goto Exit;+ }++ blend = face->blend;+ mmvar = blend->mmvar;++ if ( num_coords != mmvar->num_axis )+ {+ error = TT_Err_Invalid_Argument;+ goto Exit;+ }++ for ( i = 0; i < num_coords; ++i )+ if ( coords[i] < -0x00010000L || coords[i] > 0x00010000L )+ {+ error = TT_Err_Invalid_Argument;+ goto Exit;+ }++ if ( blend->glyphoffsets == NULL )+ if ( (error = ft_var_load_gvar( face )) != 0 )+ goto Exit;++ if ( blend->normalizedcoords == NULL )+ {+ if ( FT_NEW_ARRAY( blend->normalizedcoords, num_coords ) )+ goto Exit;++ manageCvt = mcvt_modify;++ /* If we have not set the blend coordinates before this, then the */+ /* cvt table will still be what we read from the `cvt ' table and */+ /* we don't need to reload it. We may need to change it though... */+ }+ else+ {+ manageCvt = mcvt_retain;+ for ( i = 0; i < num_coords; ++i )+ {+ if ( blend->normalizedcoords[i] != coords[i] )+ {+ manageCvt = mcvt_load;+ break;+ }+ }++ /* If we don't change the blend coords then we don't need to do */+ /* anything to the cvt table. It will be correct. Otherwise we */+ /* no longer have the original cvt (it was modified when we set */+ /* the blend last time), so we must reload and then modify it. */+ }++ blend->num_axis = num_coords;+ FT_MEM_COPY( blend->normalizedcoords,+ coords,+ num_coords * sizeof ( FT_Fixed ) );++ face->doblend = TRUE;++ if ( face->cvt != NULL )+ {+ switch ( manageCvt )+ {+ case mcvt_load:+ /* The cvt table has been loaded already; every time we change the */+ /* blend we may need to reload and remodify the cvt table. */+ FT_FREE( face->cvt );+ face->cvt = NULL;++ tt_face_load_cvt( face, face->root.stream );+ break;++ case mcvt_modify:+ /* The original cvt table is in memory. All we need to do is */+ /* apply the `cvar' table (if any). */+ tt_face_vary_cvt( face, face->root.stream );+ break;++ case mcvt_retain:+ /* The cvt table is correct for this set of coordinates. */+ break;+ }+ }++ Exit:+ return error;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* TT_Set_Var_Design */+ /* */+ /* <Description> */+ /* Set the coordinates for the instance, measured in the user */+ /* coordinate system. Parse the `avar' table (if present) to convert */+ /* from user to normalized coordinates. */+ /* */+ /* <InOut> */+ /* face :: The font face. */+ /* Initialize the blend struct with `gvar' data. */+ /* */+ /* <Input> */+ /* num_coords :: This must be the axis count of the font. */+ /* */+ /* coords :: A coordinate array with `num_coords' elements. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ TT_Set_Var_Design( TT_Face face,+ FT_UInt num_coords,+ FT_Fixed* coords )+ {+ FT_Error error = TT_Err_Ok;+ FT_Fixed* normalized = NULL;+ GX_Blend blend;+ FT_MM_Var* mmvar;+ FT_UInt i, j;+ FT_Var_Axis* a;+ GX_AVarSegment av;+ FT_Memory memory = face->root.memory;+++ if ( face->blend == NULL )+ {+ if ( (error = TT_Get_MM_Var( face, NULL )) != 0 )+ goto Exit;+ }++ blend = face->blend;+ mmvar = blend->mmvar;++ if ( num_coords != mmvar->num_axis )+ {+ error = TT_Err_Invalid_Argument;+ goto Exit;+ }++ /* Axis normalization is a two stage process. First we normalize */+ /* based on the [min,def,max] values for the axis to be [-1,0,1]. */+ /* Then, if there's an `avar' table, we renormalize this range. */++ if ( FT_NEW_ARRAY( normalized, mmvar->num_axis ) )+ goto Exit;++ a = mmvar->axis;+ for ( i = 0; i < mmvar->num_axis; ++i, ++a )+ {+ if ( coords[i] > a->maximum || coords[i] < a->minimum )+ {+ error = TT_Err_Invalid_Argument;+ goto Exit;+ }++ if ( coords[i] < a->def )+ {+ normalized[i] = -FT_MulDiv( coords[i] - a->def,+ 0x10000L,+ a->minimum - a->def );+ }+ else if ( a->maximum == a->def )+ normalized[i] = 0;+ else+ {+ normalized[i] = FT_MulDiv( coords[i] - a->def,+ 0x10000L,+ a->maximum - a->def );+ }+ }++ if ( !blend->avar_checked )+ ft_var_load_avar( face );++ if ( blend->avar_segment != NULL )+ {+ av = blend->avar_segment;+ for ( i = 0; i < mmvar->num_axis; ++i, ++av )+ {+ for ( j = 1; j < (FT_UInt)av->pairCount; ++j )+ if ( normalized[i] < av->correspondence[j].fromCoord )+ {+ normalized[i] =+ FT_MulDiv(+ FT_MulDiv(+ normalized[i] - av->correspondence[j - 1].fromCoord,+ 0x10000L,+ av->correspondence[j].fromCoord -+ av->correspondence[j - 1].fromCoord ),+ av->correspondence[j].toCoord -+ av->correspondence[j - 1].toCoord,+ 0x10000L ) ++ av->correspondence[j - 1].toCoord;+ break;+ }+ }+ }++ error = TT_Set_MM_Blend( face, num_coords, normalized );++ Exit:+ FT_FREE( normalized );+ return error;+ }+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** GX VAR PARSING ROUTINES *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_face_vary_cvt */+ /* */+ /* <Description> */+ /* Modify the loaded cvt table according to the `cvar' table and the */+ /* font's blend. */+ /* */+ /* <InOut> */+ /* face :: A handle to the target face object. */+ /* */+ /* <Input> */+ /* stream :: A handle to the input stream. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ /* Most errors are ignored. It is perfectly valid not to have a */+ /* `cvar' table even if there is a `gvar' and `fvar' table. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ tt_face_vary_cvt( TT_Face face,+ FT_Stream stream )+ {+ FT_Error error;+ FT_Memory memory = stream->memory;+ FT_ULong table_start;+ FT_ULong table_len;+ FT_UInt tupleCount;+ FT_ULong offsetToData;+ FT_ULong here;+ FT_UInt i, j;+ FT_Fixed* tuple_coords = NULL;+ FT_Fixed* im_start_coords = NULL;+ FT_Fixed* im_end_coords = NULL;+ GX_Blend blend = face->blend;+ FT_UInt point_count;+ FT_UShort* localpoints;+ FT_Short* deltas;+++ FT_TRACE2(( "CVAR " ));++ if ( blend == NULL )+ {+ FT_TRACE2(( "tt_face_vary_cvt: no blend specified\n" ));++ error = TT_Err_Ok;+ goto Exit;+ }++ if ( face->cvt == NULL )+ {+ FT_TRACE2(( "tt_face_vary_cvt: no `cvt ' table\n" ));++ error = TT_Err_Ok;+ goto Exit;+ }++ error = face->goto_table( face, TTAG_cvar, stream, &table_len );+ if ( error )+ {+ FT_TRACE2(( "is missing\n" ));++ error = TT_Err_Ok;+ goto Exit;+ }++ if ( FT_FRAME_ENTER( table_len ) )+ {+ error = TT_Err_Ok;+ goto Exit;+ }++ table_start = FT_Stream_FTell( stream );+ if ( FT_GET_LONG() != 0x00010000L )+ {+ FT_TRACE2(( "bad table version\n" ));++ error = TT_Err_Ok;+ goto FExit;+ }++ if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis ) ||+ FT_NEW_ARRAY( im_start_coords, blend->num_axis ) ||+ FT_NEW_ARRAY( im_end_coords, blend->num_axis ) )+ goto FExit;++ tupleCount = FT_GET_USHORT();+ offsetToData = table_start + FT_GET_USHORT();++ /* 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. */++ for ( i = 0; i < ( tupleCount & 0xFFF ); ++i )+ {+ FT_UInt tupleDataSize;+ FT_UInt tupleIndex;+ FT_Fixed apply;+++ tupleDataSize = FT_GET_USHORT();+ tupleIndex = FT_GET_USHORT();++ /* There is no provision here for a global tuple coordinate section, */+ /* so John says. There are no tuple indices, just embedded tuples. */++ if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )+ {+ for ( j = 0; j < blend->num_axis; ++j )+ tuple_coords[j] = FT_GET_SHORT() << 2; /* convert from */+ /* short frac to fixed */+ }+ else+ {+ /* skip this tuple; it makes no sense */++ if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )+ for ( j = 0; j < 2 * blend->num_axis; ++j )+ (void)FT_GET_SHORT();++ offsetToData += tupleDataSize;+ continue;+ }++ if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )+ {+ for ( j = 0; j < blend->num_axis; ++j )+ im_start_coords[j] = FT_GET_SHORT() << 2;+ for ( j = 0; j < blend->num_axis; ++j )+ im_end_coords[j] = FT_GET_SHORT() << 2;+ }++ apply = ft_var_apply_tuple( blend,+ (FT_UShort)tupleIndex,+ tuple_coords,+ im_start_coords,+ im_end_coords );+ if ( /* tuple isn't active for our blend */+ apply == 0 ||+ /* global points not allowed, */+ /* if they aren't local, makes no sense */+ !( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS ) )+ {+ offsetToData += tupleDataSize;+ continue;+ }++ here = FT_Stream_FTell( stream );++ FT_Stream_SeekSet( stream, offsetToData );++ localpoints = ft_var_readpackedpoints( stream, &point_count );+ deltas = ft_var_readpackeddeltas( stream,+ point_count == 0 ? face->cvt_size+ : point_count );+ if ( localpoints == NULL || deltas == NULL )+ /* failure, ignore it */;++ else if ( localpoints == ALL_POINTS )+ {+ /* this means that there are deltas for every entry in cvt */+ for ( j = 0; j < face->cvt_size; ++j )+ face->cvt[j] = (FT_Short)( face->cvt[j] ++ FT_MulFix( deltas[j], apply ) );+ }++ else+ {+ for ( j = 0; j < point_count; ++j )+ {+ int pindex = localpoints[j];++ face->cvt[pindex] = (FT_Short)( face->cvt[pindex] ++ FT_MulFix( deltas[j], apply ) );+ }+ }++ if ( localpoints != ALL_POINTS )+ FT_FREE( localpoints );+ FT_FREE( deltas );++ offsetToData += tupleDataSize;++ FT_Stream_SeekSet( stream, here );+ }++ FExit:+ FT_FRAME_EXIT();++ Exit:+ FT_FREE( tuple_coords );+ FT_FREE( im_start_coords );+ FT_FREE( im_end_coords );++ return error;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* TT_Vary_Get_Glyph_Deltas */+ /* */+ /* <Description> */+ /* Load the appropriate deltas for the current glyph. */+ /* */+ /* <Input> */+ /* face :: A handle to the target face object. */+ /* */+ /* glyph_index :: The index of the glyph being modified. */+ /* */+ /* n_points :: The number of the points in the glyph, including */+ /* phantom points. */+ /* */+ /* <Output> */+ /* deltas :: The array of points to change. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ TT_Vary_Get_Glyph_Deltas( TT_Face face,+ FT_UInt glyph_index,+ FT_Vector* *deltas,+ FT_UInt n_points )+ {+ FT_Stream stream = face->root.stream;+ FT_Memory memory = stream->memory;+ GX_Blend blend = face->blend;+ FT_Vector* delta_xy;++ FT_Error error;+ FT_ULong glyph_start;+ FT_UInt tupleCount;+ FT_ULong offsetToData;+ FT_ULong here;+ FT_UInt i, j;+ FT_Fixed* tuple_coords = NULL;+ FT_Fixed* im_start_coords = NULL;+ FT_Fixed* im_end_coords = NULL;+ FT_UInt point_count, spoint_count = 0;+ FT_UShort* sharedpoints = NULL;+ FT_UShort* localpoints = NULL;+ FT_UShort* points;+ FT_Short *deltas_x, *deltas_y;+++ if ( !face->doblend || blend == NULL )+ return TT_Err_Invalid_Argument;++ /* to be freed by the caller */+ if ( FT_NEW_ARRAY( delta_xy, n_points ) )+ goto Exit;+ *deltas = delta_xy;++ if ( glyph_index >= blend->gv_glyphcnt ||+ blend->glyphoffsets[glyph_index] ==+ blend->glyphoffsets[glyph_index + 1] )+ return TT_Err_Ok; /* no variation data for this glyph */++ if ( FT_STREAM_SEEK( blend->glyphoffsets[glyph_index] ) ||+ FT_FRAME_ENTER( blend->glyphoffsets[glyph_index + 1] -+ blend->glyphoffsets[glyph_index] ) )+ goto Fail1;++ glyph_start = FT_Stream_FTell( stream );++ /* each set of glyph variation data is formatted similarly to `cvar' */+ /* (except we get shared points and global tuples) */++ if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis ) ||+ FT_NEW_ARRAY( im_start_coords, blend->num_axis ) ||+ FT_NEW_ARRAY( im_end_coords, blend->num_axis ) )+ goto Fail2;++ tupleCount = FT_GET_USHORT();+ offsetToData = glyph_start + FT_GET_USHORT();++ if ( tupleCount & GX_TC_TUPLES_SHARE_POINT_NUMBERS )+ {+ here = FT_Stream_FTell( stream );++ FT_Stream_SeekSet( stream, offsetToData );++ sharedpoints = ft_var_readpackedpoints( stream, &spoint_count );+ offsetToData = FT_Stream_FTell( stream );++ FT_Stream_SeekSet( stream, here );+ }++ for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); ++i )+ {+ FT_UInt tupleDataSize;+ FT_UInt tupleIndex;+ FT_Fixed apply;+++ tupleDataSize = FT_GET_USHORT();+ tupleIndex = FT_GET_USHORT();++ if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )+ {+ for ( j = 0; j < blend->num_axis; ++j )+ tuple_coords[j] = FT_GET_SHORT() << 2; /* convert from */+ /* short frac to fixed */+ }+ else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount )+ {+ error = TT_Err_Invalid_Table;+ goto Fail3;+ }+ else+ {+ FT_MEM_COPY(+ tuple_coords,+ &blend->tuplecoords[(tupleIndex & 0xFFF) * blend->num_axis],+ blend->num_axis * sizeof ( FT_Fixed ) );+ }++ if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )+ {+ for ( j = 0; j < blend->num_axis; ++j )+ im_start_coords[j] = FT_GET_SHORT() << 2;+ for ( j = 0; j < blend->num_axis; ++j )+ im_end_coords[j] = FT_GET_SHORT() << 2;+ }++ apply = ft_var_apply_tuple( blend,+ (FT_UShort)tupleIndex,+ tuple_coords,+ im_start_coords,+ im_end_coords );++ if ( apply == 0 ) /* tuple isn't active for our blend */+ {+ offsetToData += tupleDataSize;+ continue;+ }++ here = FT_Stream_FTell( stream );++ if ( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS )+ {+ FT_Stream_SeekSet( stream, offsetToData );++ localpoints = ft_var_readpackedpoints( stream, &point_count );+ points = localpoints;+ }+ else+ {+ points = sharedpoints;+ point_count = spoint_count;+ }++ deltas_x = ft_var_readpackeddeltas( stream,+ point_count == 0 ? n_points+ : point_count );+ deltas_y = ft_var_readpackeddeltas( stream,+ point_count == 0 ? n_points+ : point_count );++ if ( points == NULL || deltas_y == NULL || deltas_x == NULL )+ ; /* failure, ignore it */++ else if ( points == ALL_POINTS )+ {+ /* this means that there are deltas for every point in the glyph */+ for ( j = 0; j < n_points; ++j )+ {+ delta_xy[j].x += FT_MulFix( deltas_x[j], apply );+ delta_xy[j].y += FT_MulFix( deltas_y[j], apply );+ }+ }++ else+ {+ for ( j = 0; j < point_count; ++j )+ {+ delta_xy[localpoints[j]].x += FT_MulFix( deltas_x[j], apply );+ delta_xy[localpoints[j]].y += FT_MulFix( deltas_y[j], apply );+ }+ }++ if ( localpoints != ALL_POINTS )+ FT_FREE( localpoints );+ FT_FREE( deltas_x );+ FT_FREE( deltas_y );++ offsetToData += tupleDataSize;++ FT_Stream_SeekSet( stream, here );+ }++ Fail3:+ FT_FREE( tuple_coords );+ FT_FREE( im_start_coords );+ FT_FREE( im_end_coords );++ Fail2:+ FT_FRAME_EXIT();++ Fail1:+ if ( error )+ {+ FT_FREE( delta_xy );+ *deltas = NULL;+ }++ Exit:+ return error;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_done_blend */+ /* */+ /* <Description> */+ /* Frees the blend internal data structure. */+ /* */+ FT_LOCAL_DEF( void )+ tt_done_blend( FT_Memory memory,+ GX_Blend blend )+ {+ if ( blend != NULL )+ {+ FT_UInt i;+++ FT_FREE( blend->normalizedcoords );+ FT_FREE( blend->mmvar );++ if ( blend->avar_segment != NULL )+ {+ for ( i = 0; i < blend->num_axis; ++i )+ FT_FREE( blend->avar_segment[i].correspondence );+ FT_FREE( blend->avar_segment );+ }++ FT_FREE( blend->tuplecoords );+ FT_FREE( blend->glyphoffsets );+ FT_FREE( blend );+ }+ }++#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */+++/* END */
+ src/truetype/ttgxvar.h view
@@ -0,0 +1,182 @@+/***************************************************************************/+/* */+/* ttgxvar.h */+/* */+/* TrueType GX Font Variation loader (specification) */+/* */+/* Copyright 2004 by */+/* David Turner, Robert Wilhelm, Werner Lemberg and George Williams. */+/* */+/* 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 __TTGXVAR_H__+#define __TTGXVAR_H__+++#include <ft2build.h>+#include "ttobjs.h"+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* GX_AVarCorrespondenceRec */+ /* */+ /* <Description> */+ /* A data structure representing `shortFracCorrespondence' in `avar' */+ /* table according to the specifications from Apple. */+ /* */+ typedef struct GX_AVarCorrespondenceRec_+ {+ FT_Fixed fromCoord;+ FT_Fixed toCoord;++ } GX_AVarCorrespondenceRec_, *GX_AVarCorrespondence;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* GX_AVarRec */+ /* */+ /* <Description> */+ /* Data from the segment field of `avar' table. */+ /* There is one of these for each axis. */+ /* */+ typedef struct GX_AVarSegmentRec_+ {+ FT_UShort pairCount;+ GX_AVarCorrespondence correspondence; /* array with pairCount entries */++ } GX_AVarSegmentRec, *GX_AVarSegment;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* GX_BlendRec */+ /* */+ /* <Description> */+ /* Data for interpolating a font from a distortable font specified */+ /* by the GX *var tables ([fgca]var). */+ /* */+ /* <Fields> */+ /* num_axis :: The number of axes along which interpolation */+ /* may happen */+ /* */+ /* normalizedcoords :: A normalized value (between [-1,1]) indicating */+ /* the contribution along each axis to the final */+ /* interpolated font. */+ /* */+ typedef struct GX_BlendRec_+ {+ FT_UInt num_axis;+ FT_Fixed* normalizedcoords;++ FT_MM_Var* mmvar;+ FT_Offset mmvar_len;++ FT_Bool avar_checked;+ GX_AVarSegment avar_segment;++ FT_UInt tuplecount; /* shared tuples in `gvar' */+ FT_Fixed* tuplecoords; /* tuplecoords[tuplecount][num_axis] */++ FT_UInt gv_glyphcnt;+ FT_ULong* glyphoffsets;++ } GX_BlendRec;+++ /*************************************************************************/+ /* */+ /* <enum> */+ /* GX_TupleCountFlags */+ /* */+ /* <Description> */+ /* Flags used within the `TupleCount' field of the `gvar' table. */+ /* */+ typedef enum GX_TupleCountFlags_+ {+ GX_TC_TUPLES_SHARE_POINT_NUMBERS = 0x8000,+ GX_TC_RESERVED_TUPLE_FLAGS = 0x7000,+ GX_TC_TUPLE_COUNT_MASK = 0x0FFF++ } GX_TupleCountFlags;+++ /*************************************************************************/+ /* */+ /* <enum> */+ /* GX_TupleIndexFlags */+ /* */+ /* <Description> */+ /* Flags used within the `TupleIndex' field of the `gvar' and `cvar' */+ /* tables. */+ /* */+ typedef enum GX_TupleIndexFlags_+ {+ GX_TI_EMBEDDED_TUPLE_COORD = 0x8000,+ GX_TI_INTERMEDIATE_TUPLE = 0x4000,+ GX_TI_PRIVATE_POINT_NUMBERS = 0x2000,+ GX_TI_RESERVED_TUPLE_FLAG = 0x1000,+ GX_TI_TUPLE_INDEX_MASK = 0x0FFF++ } GX_TupleIndexFlags;+++#define TTAG_wght FT_MAKE_TAG( 'w', 'g', 'h', 't' )+#define TTAG_wdth FT_MAKE_TAG( 'w', 'd', 't', 'h' )+#define TTAG_opsz FT_MAKE_TAG( 'o', 'p', 's', 'z' )+#define TTAG_slnt FT_MAKE_TAG( 's', 'l', 'n', 't' )+++ FT_LOCAL( FT_Error )+ TT_Set_MM_Blend( TT_Face face,+ FT_UInt num_coords,+ FT_Fixed* coords );++ FT_LOCAL( FT_Error )+ TT_Set_Var_Design( TT_Face face,+ FT_UInt num_coords,+ FT_Fixed* coords );++ FT_LOCAL( FT_Error )+ TT_Get_MM_Var( TT_Face face,+ FT_MM_Var* *master );+++ FT_LOCAL( FT_Error )+ tt_face_vary_cvt( TT_Face face,+ FT_Stream stream );+++ FT_LOCAL( FT_Error )+ TT_Vary_Get_Glyph_Deltas( TT_Face face,+ FT_UInt glyph_index,+ FT_Vector* *deltas,+ FT_UInt n_points );+++ FT_LOCAL( void )+ tt_done_blend( FT_Memory memory,+ GX_Blend blend );+++FT_END_HEADER+++#endif /* __TTGXVAR_H__ */+++/* END */
+ src/truetype/ttinterp.c view
@@ -0,0 +1,8160 @@+/***************************************************************************/+/* */+/* ttinterp.c */+/* */+/* TrueType bytecode interpreter (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */+/* 2010 */+/* 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_CALC_H+#include FT_TRIGONOMETRY_H+#include FT_SYSTEM_H++#include "ttinterp.h"++#include "tterrors.h"+++#ifdef TT_USE_BYTECODE_INTERPRETER+++#define TT_MULFIX FT_MulFix+#define TT_MULDIV FT_MulDiv+#define TT_MULDIV_NO_ROUND FT_MulDiv_No_Round+++ /*************************************************************************/+ /* */+ /* 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_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 maximal number of opcodes defined below. */+ /* */+#define MAX_RUNNABLE_OPCODES 1000000L+++ /*************************************************************************/+ /* */+ /* There are two kinds of implementations: */+ /* */+ /* a. static implementation */+ /* */+ /* The current execution context is a static variable, which fields */+ /* are accessed directly by the interpreter during execution. The */+ /* context is named `cur'. */+ /* */+ /* This version is non-reentrant, of course. */+ /* */+ /* b. indirect implementation */+ /* */+ /* The current execution context is passed to _each_ function as its */+ /* first argument, and each field is thus accessed indirectly. */+ /* */+ /* This version is fully re-entrant. */+ /* */+ /* The idea is that an indirect implementation may be slower to execute */+ /* on low-end processors that are used in some systems (like 386s or */+ /* even 486s). */+ /* */+ /* As a consequence, the indirect implementation is now the default, as */+ /* its performance costs can be considered negligible in our context. */+ /* Note, however, that we kept the same source with macros because: */+ /* */+ /* - The code is kept very close in design to the Pascal code used for */+ /* development. */+ /* */+ /* - It's much more readable that way! */+ /* */+ /* - It's still open to experimentation and tuning. */+ /* */+ /*************************************************************************/+++#ifndef TT_CONFIG_OPTION_STATIC_INTERPRETER /* indirect implementation */++#define CUR (*exc) /* see ttobjs.h */++ /*************************************************************************/+ /* */+ /* This macro is used whenever `exec' is unused in a function, to avoid */+ /* stupid warnings from pedantic compilers. */+ /* */+#define FT_UNUSED_EXEC FT_UNUSED( exc )++#else /* static implementation */++#define CUR cur++#define FT_UNUSED_EXEC int __dummy = __dummy++ static+ TT_ExecContextRec cur; /* static exec. context variable */++ /* apparently, we have a _lot_ of direct indexing when accessing */+ /* the static `cur', which makes the code bigger (due to all the */+ /* four bytes addresses). */++#endif /* TT_CONFIG_OPTION_STATIC_INTERPRETER */+++ /*************************************************************************/+ /* */+ /* The instruction argument stack. */+ /* */+#define INS_ARG EXEC_OP_ FT_Long* args /* see ttobjs.h for EXEC_OP_ */+++ /*************************************************************************/+ /* */+ /* This macro is used whenever `args' is unused in a function, to avoid */+ /* stupid warnings from pedantic compilers. */+ /* */+#define FT_UNUSED_ARG FT_UNUSED_EXEC; FT_UNUSED( args )+++ /*************************************************************************/+ /* */+ /* The following macros hide the use of EXEC_ARG and EXEC_ARG_ to */+ /* increase readability of the code. */+ /* */+ /*************************************************************************/+++#define SKIP_Code() \+ SkipCode( EXEC_ARG )++#define GET_ShortIns() \+ GetShortIns( EXEC_ARG )++#define NORMalize( x, y, v ) \+ Normalize( EXEC_ARG_ x, y, v )++#define SET_SuperRound( scale, flags ) \+ SetSuperRound( EXEC_ARG_ scale, flags )++#define ROUND_None( d, c ) \+ Round_None( EXEC_ARG_ d, c )++#define INS_Goto_CodeRange( range, ip ) \+ Ins_Goto_CodeRange( EXEC_ARG_ range, ip )++#define CUR_Func_move( z, p, d ) \+ CUR.func_move( EXEC_ARG_ z, p, d )++#define CUR_Func_move_orig( z, p, d ) \+ CUR.func_move_orig( EXEC_ARG_ z, p, d )++#define CUR_Func_round( d, c ) \+ CUR.func_round( EXEC_ARG_ d, c )++#define CUR_Func_read_cvt( index ) \+ CUR.func_read_cvt( EXEC_ARG_ index )++#define CUR_Func_write_cvt( index, val ) \+ CUR.func_write_cvt( EXEC_ARG_ index, val )++#define CUR_Func_move_cvt( index, val ) \+ CUR.func_move_cvt( EXEC_ARG_ index, val )++#define CURRENT_Ratio() \+ Current_Ratio( EXEC_ARG )++#define CURRENT_Ppem() \+ Current_Ppem( EXEC_ARG )++#define CUR_Ppem() \+ Cur_PPEM( EXEC_ARG )++#define INS_SxVTL( a, b, c, d ) \+ Ins_SxVTL( EXEC_ARG_ a, b, c, d )++#define COMPUTE_Funcs() \+ Compute_Funcs( EXEC_ARG )++#define COMPUTE_Round( a ) \+ Compute_Round( EXEC_ARG_ a )++#define COMPUTE_Point_Displacement( a, b, c, d ) \+ Compute_Point_Displacement( EXEC_ARG_ a, b, c, d )++#define MOVE_Zp2_Point( a, b, c, t ) \+ Move_Zp2_Point( EXEC_ARG_ a, b, c, t )+++#define CUR_Func_project( v1, v2 ) \+ CUR.func_project( EXEC_ARG_ (v1)->x - (v2)->x, (v1)->y - (v2)->y )++#define CUR_Func_dualproj( v1, v2 ) \+ CUR.func_dualproj( EXEC_ARG_ (v1)->x - (v2)->x, (v1)->y - (v2)->y )++#define CUR_fast_project( v ) \+ CUR.func_project( EXEC_ARG_ (v)->x, (v)->y )++#define CUR_fast_dualproj( v ) \+ CUR.func_dualproj( EXEC_ARG_ (v)->x, (v)->y )+++ /*************************************************************************/+ /* */+ /* Instruction dispatch function, as used by the interpreter. */+ /* */+ typedef void (*TInstruction_Function)( INS_ARG );+++ /*************************************************************************/+ /* */+ /* Two simple bounds-checking macros. */+ /* */+#define BOUNDS( x, n ) ( (FT_UInt)(x) >= (FT_UInt)(n) )+#define BOUNDSL( x, n ) ( (FT_ULong)(x) >= (FT_ULong)(n) )++#undef SUCCESS+#define SUCCESS 0++#undef FAILURE+#define FAILURE 1++#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING+#define GUESS_VECTOR( V ) \+ if ( CUR.face->unpatented_hinting ) \+ { \+ CUR.GS.V.x = (FT_F2Dot14)( CUR.GS.both_x_axis ? 0x4000 : 0 ); \+ CUR.GS.V.y = (FT_F2Dot14)( CUR.GS.both_x_axis ? 0 : 0x4000 ); \+ }+#else+#define GUESS_VECTOR( V )+#endif++ /*************************************************************************/+ /* */+ /* CODERANGE FUNCTIONS */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* TT_Goto_CodeRange */+ /* */+ /* <Description> */+ /* Switches to a new code range (updates the code related elements in */+ /* `exec', and `IP'). */+ /* */+ /* <Input> */+ /* range :: The new execution code range. */+ /* */+ /* IP :: The new IP in the new code range. */+ /* */+ /* <InOut> */+ /* exec :: The target execution context. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ TT_Goto_CodeRange( TT_ExecContext exec,+ FT_Int range,+ FT_Long IP )+ {+ TT_CodeRange* coderange;+++ FT_ASSERT( range >= 1 && range <= 3 );++ coderange = &exec->codeRangeTable[range - 1];++ FT_ASSERT( coderange->base != NULL );++ /* NOTE: Because the last instruction of a program may be a CALL */+ /* which will return to the first byte *after* the code */+ /* range, we test for IP <= Size instead of IP < Size. */+ /* */+ FT_ASSERT( (FT_ULong)IP <= coderange->size );++ exec->code = coderange->base;+ exec->codeSize = coderange->size;+ exec->IP = IP;+ exec->curRange = range;++ return TT_Err_Ok;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* TT_Set_CodeRange */+ /* */+ /* <Description> */+ /* Sets a code range. */+ /* */+ /* <Input> */+ /* range :: The code range index. */+ /* */+ /* base :: The new code base. */+ /* */+ /* length :: The range size in bytes. */+ /* */+ /* <InOut> */+ /* exec :: The target execution context. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ TT_Set_CodeRange( TT_ExecContext exec,+ FT_Int range,+ void* base,+ FT_Long length )+ {+ FT_ASSERT( range >= 1 && range <= 3 );++ exec->codeRangeTable[range - 1].base = (FT_Byte*)base;+ exec->codeRangeTable[range - 1].size = length;++ return TT_Err_Ok;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* TT_Clear_CodeRange */+ /* */+ /* <Description> */+ /* Clears a code range. */+ /* */+ /* <Input> */+ /* range :: The code range index. */+ /* */+ /* <InOut> */+ /* exec :: The target execution context. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ /* <Note> */+ /* Does not set the Error variable. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ TT_Clear_CodeRange( TT_ExecContext exec,+ FT_Int range )+ {+ FT_ASSERT( range >= 1 && range <= 3 );++ exec->codeRangeTable[range - 1].base = NULL;+ exec->codeRangeTable[range - 1].size = 0;++ return TT_Err_Ok;+ }+++ /*************************************************************************/+ /* */+ /* EXECUTION CONTEXT ROUTINES */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* TT_Done_Context */+ /* */+ /* <Description> */+ /* Destroys a given context. */+ /* */+ /* <Input> */+ /* exec :: A handle to the target execution context. */+ /* */+ /* memory :: A handle to the parent memory object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ /* <Note> */+ /* Only the glyph loader and debugger should call this function. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ TT_Done_Context( TT_ExecContext exec )+ {+ FT_Memory memory = exec->memory;+++ /* points zone */+ exec->maxPoints = 0;+ exec->maxContours = 0;++ /* free stack */+ FT_FREE( exec->stack );+ exec->stackSize = 0;++ /* free call stack */+ FT_FREE( exec->callStack );+ exec->callSize = 0;+ exec->callTop = 0;++ /* free glyph code range */+ FT_FREE( exec->glyphIns );+ exec->glyphSize = 0;++ exec->size = NULL;+ exec->face = NULL;++ FT_FREE( exec );++ return TT_Err_Ok;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Init_Context */+ /* */+ /* <Description> */+ /* Initializes a context object. */+ /* */+ /* <Input> */+ /* memory :: A handle to the parent memory object. */+ /* */+ /* <InOut> */+ /* exec :: A handle to the target execution context. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ static FT_Error+ Init_Context( TT_ExecContext exec,+ FT_Memory memory )+ {+ FT_Error error;+++ FT_TRACE1(( "Init_Context: new object at 0x%08p\n", exec ));++ exec->memory = memory;+ exec->callSize = 32;++ if ( FT_NEW_ARRAY( exec->callStack, exec->callSize ) )+ goto Fail_Memory;++ /* all values in the context are set to 0 already, but this is */+ /* here as a remainder */+ exec->maxPoints = 0;+ exec->maxContours = 0;++ exec->stackSize = 0;+ exec->glyphSize = 0;++ exec->stack = NULL;+ exec->glyphIns = NULL;++ exec->face = NULL;+ exec->size = NULL;++ return TT_Err_Ok;++ Fail_Memory:+ FT_ERROR(( "Init_Context: not enough memory for %p\n", exec ));+ TT_Done_Context( exec );++ return error;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Update_Max */+ /* */+ /* <Description> */+ /* Checks the size of a buffer and reallocates it if necessary. */+ /* */+ /* <Input> */+ /* memory :: A handle to the parent memory object. */+ /* */+ /* multiplier :: The size in bytes of each element in the buffer. */+ /* */+ /* new_max :: The new capacity (size) of the buffer. */+ /* */+ /* <InOut> */+ /* size :: The address of the buffer's current size expressed */+ /* in elements. */+ /* */+ /* buff :: The address of the buffer base pointer. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ Update_Max( FT_Memory memory,+ FT_ULong* size,+ FT_Long multiplier,+ void* _pbuff,+ FT_ULong new_max )+ {+ FT_Error error;+ void** pbuff = (void**)_pbuff;+++ if ( *size < new_max )+ {+ if ( FT_REALLOC( *pbuff, *size * multiplier, new_max * multiplier ) )+ return error;+ *size = new_max;+ }++ return TT_Err_Ok;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* TT_Load_Context */+ /* */+ /* <Description> */+ /* Prepare an execution context for glyph hinting. */+ /* */+ /* <Input> */+ /* face :: A handle to the source face object. */+ /* */+ /* size :: A handle to the source size object. */+ /* */+ /* <InOut> */+ /* exec :: A handle to the target execution context. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ /* <Note> */+ /* Only the glyph loader and debugger should call this function. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ TT_Load_Context( TT_ExecContext exec,+ TT_Face face,+ TT_Size size )+ {+ FT_Int i;+ FT_ULong tmp;+ TT_MaxProfile* maxp;+ FT_Error error;+++ exec->face = face;+ maxp = &face->max_profile;+ exec->size = size;++ if ( size )+ {+ exec->numFDefs = size->num_function_defs;+ exec->maxFDefs = size->max_function_defs;+ exec->numIDefs = size->num_instruction_defs;+ exec->maxIDefs = size->max_instruction_defs;+ exec->FDefs = size->function_defs;+ exec->IDefs = size->instruction_defs;+ exec->tt_metrics = size->ttmetrics;+ exec->metrics = size->metrics;++ exec->maxFunc = size->max_func;+ exec->maxIns = size->max_ins;++ for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )+ exec->codeRangeTable[i] = size->codeRangeTable[i];++ /* set graphics state */+ exec->GS = size->GS;++ exec->cvtSize = size->cvt_size;+ exec->cvt = size->cvt;++ exec->storeSize = size->storage_size;+ exec->storage = size->storage;++ exec->twilight = size->twilight;++ /* In case of multi-threading it can happen that the old size object */+ /* no longer exists, thus we must clear all glyph zone references. */+ ft_memset( &exec->zp0, 0, sizeof ( exec->zp0 ) );+ exec->zp1 = exec->zp0;+ exec->zp2 = exec->zp0;+ }++ /* XXX: We reserve a little more elements on the stack to deal safely */+ /* with broken fonts like arialbs, courbs, timesbs, etc. */+ tmp = exec->stackSize;+ error = Update_Max( exec->memory,+ &tmp,+ sizeof ( FT_F26Dot6 ),+ (void*)&exec->stack,+ maxp->maxStackElements + 32 );+ exec->stackSize = (FT_UInt)tmp;+ if ( error )+ return error;++ tmp = exec->glyphSize;+ error = Update_Max( exec->memory,+ &tmp,+ sizeof ( FT_Byte ),+ (void*)&exec->glyphIns,+ maxp->maxSizeOfInstructions );+ exec->glyphSize = (FT_UShort)tmp;+ if ( error )+ return error;++ exec->pts.n_points = 0;+ exec->pts.n_contours = 0;++ exec->zp1 = exec->pts;+ exec->zp2 = exec->pts;+ exec->zp0 = exec->pts;++ exec->instruction_trap = FALSE;++ return TT_Err_Ok;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* TT_Save_Context */+ /* */+ /* <Description> */+ /* Saves the code ranges in a `size' object. */+ /* */+ /* <Input> */+ /* exec :: A handle to the source execution context. */+ /* */+ /* <InOut> */+ /* size :: A handle to the target size object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ /* <Note> */+ /* Only the glyph loader and debugger should call this function. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ TT_Save_Context( TT_ExecContext exec,+ TT_Size size )+ {+ FT_Int i;+++ /* XXXX: Will probably disappear soon with all the code range */+ /* management, which is now rather obsolete. */+ /* */+ size->num_function_defs = exec->numFDefs;+ size->num_instruction_defs = exec->numIDefs;++ size->max_func = exec->maxFunc;+ size->max_ins = exec->maxIns;++ for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )+ size->codeRangeTable[i] = exec->codeRangeTable[i];++ return TT_Err_Ok;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* TT_Run_Context */+ /* */+ /* <Description> */+ /* Executes one or more instructions in the execution context. */+ /* */+ /* <Input> */+ /* debug :: A Boolean flag. If set, the function sets some internal */+ /* variables and returns immediately, otherwise TT_RunIns() */+ /* is called. */+ /* */+ /* This is commented out currently. */+ /* */+ /* <Input> */+ /* exec :: A handle to the target execution context. */+ /* */+ /* <Return> */+ /* TrueType error code. 0 means success. */+ /* */+ /* <Note> */+ /* Only the glyph loader and debugger should call this function. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ TT_Run_Context( TT_ExecContext exec,+ FT_Bool debug )+ {+ FT_Error error;+++ if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 ) )+ != TT_Err_Ok )+ return error;++ exec->zp0 = exec->pts;+ exec->zp1 = exec->pts;+ exec->zp2 = exec->pts;++ exec->GS.gep0 = 1;+ exec->GS.gep1 = 1;+ exec->GS.gep2 = 1;++ exec->GS.projVector.x = 0x4000;+ exec->GS.projVector.y = 0x0000;++ exec->GS.freeVector = exec->GS.projVector;+ exec->GS.dualVector = exec->GS.projVector;++#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING+ exec->GS.both_x_axis = TRUE;+#endif++ exec->GS.round_state = 1;+ exec->GS.loop = 1;++ /* some glyphs leave something on the stack. so we clean it */+ /* before a new execution. */+ exec->top = 0;+ exec->callTop = 0;++#if 1+ FT_UNUSED( debug );++ return exec->face->interpreter( exec );+#else+ if ( !debug )+ return TT_RunIns( exec );+ else+ return TT_Err_Ok;+#endif+ }+++ /* The default value for `scan_control' is documented as FALSE in the */+ /* TrueType specification. This is confusing since it implies a */+ /* Boolean value. However, this is not the case, thus both the */+ /* default values of our `scan_type' and `scan_control' fields (which */+ /* the documentation's `scan_control' variable is split into) are */+ /* zero. */++ const TT_GraphicsState tt_default_graphics_state =+ {+ 0, 0, 0,+ { 0x4000, 0 },+ { 0x4000, 0 },+ { 0x4000, 0 },++#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING+ TRUE,+#endif++ 1, 64, 1,+ TRUE, 68, 0, 0, 9, 3,+ 0, FALSE, 0, 1, 1, 1+ };+++ /* documentation is in ttinterp.h */++ FT_EXPORT_DEF( TT_ExecContext )+ TT_New_Context( TT_Driver driver )+ {+ TT_ExecContext exec;+ FT_Memory memory;+++ memory = driver->root.root.memory;+ exec = driver->context;++ if ( !driver->context )+ {+ FT_Error error;+++ /* allocate object */+ if ( FT_NEW( exec ) )+ goto Fail;++ /* initialize it; in case of error this deallocates `exec' too */+ error = Init_Context( exec, memory );+ if ( error )+ goto Fail;++ /* store it into the driver */+ driver->context = exec;+ }++ return driver->context;++ Fail:+ return NULL;+ }+++ /*************************************************************************/+ /* */+ /* Before an opcode is executed, the interpreter verifies that there are */+ /* enough arguments on the stack, with the help of the `Pop_Push_Count' */+ /* table. */+ /* */+ /* For each opcode, the first column gives the number of arguments that */+ /* are popped from the stack; the second one gives the number of those */+ /* that are pushed in result. */+ /* */+ /* Opcodes which have a varying number of parameters in the data stream */+ /* (NPUSHB, NPUSHW) are handled specially; they have a negative value in */+ /* the `opcode_length' table, and the value in `Pop_Push_Count' is set */+ /* to zero. */+ /* */+ /*************************************************************************/+++#undef PACK+#define PACK( x, y ) ( ( x << 4 ) | y )+++ static+ const FT_Byte Pop_Push_Count[256] =+ {+ /* opcodes are gathered in groups of 16 */+ /* please keep the spaces as they are */++ /* SVTCA y */ PACK( 0, 0 ),+ /* SVTCA x */ PACK( 0, 0 ),+ /* SPvTCA y */ PACK( 0, 0 ),+ /* SPvTCA x */ PACK( 0, 0 ),+ /* SFvTCA y */ PACK( 0, 0 ),+ /* SFvTCA x */ PACK( 0, 0 ),+ /* SPvTL // */ PACK( 2, 0 ),+ /* SPvTL + */ PACK( 2, 0 ),+ /* SFvTL // */ PACK( 2, 0 ),+ /* SFvTL + */ PACK( 2, 0 ),+ /* SPvFS */ PACK( 2, 0 ),+ /* SFvFS */ PACK( 2, 0 ),+ /* GPV */ PACK( 0, 2 ),+ /* GFV */ PACK( 0, 2 ),+ /* SFvTPv */ PACK( 0, 0 ),+ /* ISECT */ PACK( 5, 0 ),++ /* SRP0 */ PACK( 1, 0 ),+ /* SRP1 */ PACK( 1, 0 ),+ /* SRP2 */ PACK( 1, 0 ),+ /* SZP0 */ PACK( 1, 0 ),+ /* SZP1 */ PACK( 1, 0 ),+ /* SZP2 */ PACK( 1, 0 ),+ /* SZPS */ PACK( 1, 0 ),+ /* SLOOP */ PACK( 1, 0 ),+ /* RTG */ PACK( 0, 0 ),+ /* RTHG */ PACK( 0, 0 ),+ /* SMD */ PACK( 1, 0 ),+ /* ELSE */ PACK( 0, 0 ),+ /* JMPR */ PACK( 1, 0 ),+ /* SCvTCi */ PACK( 1, 0 ),+ /* SSwCi */ PACK( 1, 0 ),+ /* SSW */ PACK( 1, 0 ),++ /* DUP */ PACK( 1, 2 ),+ /* POP */ PACK( 1, 0 ),+ /* CLEAR */ PACK( 0, 0 ),+ /* SWAP */ PACK( 2, 2 ),+ /* DEPTH */ PACK( 0, 1 ),+ /* CINDEX */ PACK( 1, 1 ),+ /* MINDEX */ PACK( 1, 0 ),+ /* AlignPTS */ PACK( 2, 0 ),+ /* INS_$28 */ PACK( 0, 0 ),+ /* UTP */ PACK( 1, 0 ),+ /* LOOPCALL */ PACK( 2, 0 ),+ /* CALL */ PACK( 1, 0 ),+ /* FDEF */ PACK( 1, 0 ),+ /* ENDF */ PACK( 0, 0 ),+ /* MDAP[0] */ PACK( 1, 0 ),+ /* MDAP[1] */ PACK( 1, 0 ),++ /* IUP[0] */ PACK( 0, 0 ),+ /* IUP[1] */ PACK( 0, 0 ),+ /* SHP[0] */ PACK( 0, 0 ),+ /* SHP[1] */ PACK( 0, 0 ),+ /* SHC[0] */ PACK( 1, 0 ),+ /* SHC[1] */ PACK( 1, 0 ),+ /* SHZ[0] */ PACK( 1, 0 ),+ /* SHZ[1] */ PACK( 1, 0 ),+ /* SHPIX */ PACK( 1, 0 ),+ /* IP */ PACK( 0, 0 ),+ /* MSIRP[0] */ PACK( 2, 0 ),+ /* MSIRP[1] */ PACK( 2, 0 ),+ /* AlignRP */ PACK( 0, 0 ),+ /* RTDG */ PACK( 0, 0 ),+ /* MIAP[0] */ PACK( 2, 0 ),+ /* MIAP[1] */ PACK( 2, 0 ),++ /* NPushB */ PACK( 0, 0 ),+ /* NPushW */ PACK( 0, 0 ),+ /* WS */ PACK( 2, 0 ),+ /* RS */ PACK( 1, 1 ),+ /* WCvtP */ PACK( 2, 0 ),+ /* RCvt */ PACK( 1, 1 ),+ /* GC[0] */ PACK( 1, 1 ),+ /* GC[1] */ PACK( 1, 1 ),+ /* SCFS */ PACK( 2, 0 ),+ /* MD[0] */ PACK( 2, 1 ),+ /* MD[1] */ PACK( 2, 1 ),+ /* MPPEM */ PACK( 0, 1 ),+ /* MPS */ PACK( 0, 1 ),+ /* FlipON */ PACK( 0, 0 ),+ /* FlipOFF */ PACK( 0, 0 ),+ /* DEBUG */ PACK( 1, 0 ),++ /* LT */ PACK( 2, 1 ),+ /* LTEQ */ PACK( 2, 1 ),+ /* GT */ PACK( 2, 1 ),+ /* GTEQ */ PACK( 2, 1 ),+ /* EQ */ PACK( 2, 1 ),+ /* NEQ */ PACK( 2, 1 ),+ /* ODD */ PACK( 1, 1 ),+ /* EVEN */ PACK( 1, 1 ),+ /* IF */ PACK( 1, 0 ),+ /* EIF */ PACK( 0, 0 ),+ /* AND */ PACK( 2, 1 ),+ /* OR */ PACK( 2, 1 ),+ /* NOT */ PACK( 1, 1 ),+ /* DeltaP1 */ PACK( 1, 0 ),+ /* SDB */ PACK( 1, 0 ),+ /* SDS */ PACK( 1, 0 ),++ /* ADD */ PACK( 2, 1 ),+ /* SUB */ PACK( 2, 1 ),+ /* DIV */ PACK( 2, 1 ),+ /* MUL */ PACK( 2, 1 ),+ /* ABS */ PACK( 1, 1 ),+ /* NEG */ PACK( 1, 1 ),+ /* FLOOR */ PACK( 1, 1 ),+ /* CEILING */ PACK( 1, 1 ),+ /* ROUND[0] */ PACK( 1, 1 ),+ /* ROUND[1] */ PACK( 1, 1 ),+ /* ROUND[2] */ PACK( 1, 1 ),+ /* ROUND[3] */ PACK( 1, 1 ),+ /* NROUND[0] */ PACK( 1, 1 ),+ /* NROUND[1] */ PACK( 1, 1 ),+ /* NROUND[2] */ PACK( 1, 1 ),+ /* NROUND[3] */ PACK( 1, 1 ),++ /* WCvtF */ PACK( 2, 0 ),+ /* DeltaP2 */ PACK( 1, 0 ),+ /* DeltaP3 */ PACK( 1, 0 ),+ /* DeltaCn[0] */ PACK( 1, 0 ),+ /* DeltaCn[1] */ PACK( 1, 0 ),+ /* DeltaCn[2] */ PACK( 1, 0 ),+ /* SROUND */ PACK( 1, 0 ),+ /* S45Round */ PACK( 1, 0 ),+ /* JROT */ PACK( 2, 0 ),+ /* JROF */ PACK( 2, 0 ),+ /* ROFF */ PACK( 0, 0 ),+ /* INS_$7B */ PACK( 0, 0 ),+ /* RUTG */ PACK( 0, 0 ),+ /* RDTG */ PACK( 0, 0 ),+ /* SANGW */ PACK( 1, 0 ),+ /* AA */ PACK( 1, 0 ),++ /* FlipPT */ PACK( 0, 0 ),+ /* FlipRgON */ PACK( 2, 0 ),+ /* FlipRgOFF */ PACK( 2, 0 ),+ /* INS_$83 */ PACK( 0, 0 ),+ /* INS_$84 */ PACK( 0, 0 ),+ /* ScanCTRL */ PACK( 1, 0 ),+ /* SDVPTL[0] */ PACK( 2, 0 ),+ /* SDVPTL[1] */ PACK( 2, 0 ),+ /* GetINFO */ PACK( 1, 1 ),+ /* IDEF */ PACK( 1, 0 ),+ /* ROLL */ PACK( 3, 3 ),+ /* MAX */ PACK( 2, 1 ),+ /* MIN */ PACK( 2, 1 ),+ /* ScanTYPE */ PACK( 1, 0 ),+ /* InstCTRL */ PACK( 2, 0 ),+ /* INS_$8F */ PACK( 0, 0 ),++ /* INS_$90 */ PACK( 0, 0 ),+ /* INS_$91 */ PACK( 0, 0 ),+ /* INS_$92 */ PACK( 0, 0 ),+ /* INS_$93 */ PACK( 0, 0 ),+ /* INS_$94 */ PACK( 0, 0 ),+ /* INS_$95 */ PACK( 0, 0 ),+ /* INS_$96 */ PACK( 0, 0 ),+ /* INS_$97 */ PACK( 0, 0 ),+ /* INS_$98 */ PACK( 0, 0 ),+ /* INS_$99 */ PACK( 0, 0 ),+ /* INS_$9A */ PACK( 0, 0 ),+ /* INS_$9B */ PACK( 0, 0 ),+ /* INS_$9C */ PACK( 0, 0 ),+ /* INS_$9D */ PACK( 0, 0 ),+ /* INS_$9E */ PACK( 0, 0 ),+ /* INS_$9F */ PACK( 0, 0 ),++ /* INS_$A0 */ PACK( 0, 0 ),+ /* INS_$A1 */ PACK( 0, 0 ),+ /* INS_$A2 */ PACK( 0, 0 ),+ /* INS_$A3 */ PACK( 0, 0 ),+ /* INS_$A4 */ PACK( 0, 0 ),+ /* INS_$A5 */ PACK( 0, 0 ),+ /* INS_$A6 */ PACK( 0, 0 ),+ /* INS_$A7 */ PACK( 0, 0 ),+ /* INS_$A8 */ PACK( 0, 0 ),+ /* INS_$A9 */ PACK( 0, 0 ),+ /* INS_$AA */ PACK( 0, 0 ),+ /* INS_$AB */ PACK( 0, 0 ),+ /* INS_$AC */ PACK( 0, 0 ),+ /* INS_$AD */ PACK( 0, 0 ),+ /* INS_$AE */ PACK( 0, 0 ),+ /* INS_$AF */ PACK( 0, 0 ),++ /* PushB[0] */ PACK( 0, 1 ),+ /* PushB[1] */ PACK( 0, 2 ),+ /* PushB[2] */ PACK( 0, 3 ),+ /* PushB[3] */ PACK( 0, 4 ),+ /* PushB[4] */ PACK( 0, 5 ),+ /* PushB[5] */ PACK( 0, 6 ),+ /* PushB[6] */ PACK( 0, 7 ),+ /* PushB[7] */ PACK( 0, 8 ),+ /* PushW[0] */ PACK( 0, 1 ),+ /* PushW[1] */ PACK( 0, 2 ),+ /* PushW[2] */ PACK( 0, 3 ),+ /* PushW[3] */ PACK( 0, 4 ),+ /* PushW[4] */ PACK( 0, 5 ),+ /* PushW[5] */ PACK( 0, 6 ),+ /* PushW[6] */ PACK( 0, 7 ),+ /* PushW[7] */ PACK( 0, 8 ),++ /* MDRP[00] */ PACK( 1, 0 ),+ /* MDRP[01] */ PACK( 1, 0 ),+ /* MDRP[02] */ PACK( 1, 0 ),+ /* MDRP[03] */ PACK( 1, 0 ),+ /* MDRP[04] */ PACK( 1, 0 ),+ /* MDRP[05] */ PACK( 1, 0 ),+ /* MDRP[06] */ PACK( 1, 0 ),+ /* MDRP[07] */ PACK( 1, 0 ),+ /* MDRP[08] */ PACK( 1, 0 ),+ /* MDRP[09] */ PACK( 1, 0 ),+ /* MDRP[10] */ PACK( 1, 0 ),+ /* MDRP[11] */ PACK( 1, 0 ),+ /* MDRP[12] */ PACK( 1, 0 ),+ /* MDRP[13] */ PACK( 1, 0 ),+ /* MDRP[14] */ PACK( 1, 0 ),+ /* MDRP[15] */ PACK( 1, 0 ),++ /* MDRP[16] */ PACK( 1, 0 ),+ /* MDRP[17] */ PACK( 1, 0 ),+ /* MDRP[18] */ PACK( 1, 0 ),+ /* MDRP[19] */ PACK( 1, 0 ),+ /* MDRP[20] */ PACK( 1, 0 ),+ /* MDRP[21] */ PACK( 1, 0 ),+ /* MDRP[22] */ PACK( 1, 0 ),+ /* MDRP[23] */ PACK( 1, 0 ),+ /* MDRP[24] */ PACK( 1, 0 ),+ /* MDRP[25] */ PACK( 1, 0 ),+ /* MDRP[26] */ PACK( 1, 0 ),+ /* MDRP[27] */ PACK( 1, 0 ),+ /* MDRP[28] */ PACK( 1, 0 ),+ /* MDRP[29] */ PACK( 1, 0 ),+ /* MDRP[30] */ PACK( 1, 0 ),+ /* MDRP[31] */ PACK( 1, 0 ),++ /* MIRP[00] */ PACK( 2, 0 ),+ /* MIRP[01] */ PACK( 2, 0 ),+ /* MIRP[02] */ PACK( 2, 0 ),+ /* MIRP[03] */ PACK( 2, 0 ),+ /* MIRP[04] */ PACK( 2, 0 ),+ /* MIRP[05] */ PACK( 2, 0 ),+ /* MIRP[06] */ PACK( 2, 0 ),+ /* MIRP[07] */ PACK( 2, 0 ),+ /* MIRP[08] */ PACK( 2, 0 ),+ /* MIRP[09] */ PACK( 2, 0 ),+ /* MIRP[10] */ PACK( 2, 0 ),+ /* MIRP[11] */ PACK( 2, 0 ),+ /* MIRP[12] */ PACK( 2, 0 ),+ /* MIRP[13] */ PACK( 2, 0 ),+ /* MIRP[14] */ PACK( 2, 0 ),+ /* MIRP[15] */ PACK( 2, 0 ),++ /* MIRP[16] */ PACK( 2, 0 ),+ /* MIRP[17] */ PACK( 2, 0 ),+ /* MIRP[18] */ PACK( 2, 0 ),+ /* MIRP[19] */ PACK( 2, 0 ),+ /* MIRP[20] */ PACK( 2, 0 ),+ /* MIRP[21] */ PACK( 2, 0 ),+ /* MIRP[22] */ PACK( 2, 0 ),+ /* MIRP[23] */ PACK( 2, 0 ),+ /* MIRP[24] */ PACK( 2, 0 ),+ /* MIRP[25] */ PACK( 2, 0 ),+ /* MIRP[26] */ PACK( 2, 0 ),+ /* MIRP[27] */ PACK( 2, 0 ),+ /* MIRP[28] */ PACK( 2, 0 ),+ /* MIRP[29] */ PACK( 2, 0 ),+ /* MIRP[30] */ PACK( 2, 0 ),+ /* MIRP[31] */ PACK( 2, 0 )+ };+++#ifdef FT_DEBUG_LEVEL_TRACE++ static+ const char* const opcode_name[256] =+ {+ "SVTCA y",+ "SVTCA x",+ "SPvTCA y",+ "SPvTCA x",+ "SFvTCA y",+ "SFvTCA x",+ "SPvTL ||",+ "SPvTL +",+ "SFvTL ||",+ "SFvTL +",+ "SPvFS",+ "SFvFS",+ "GPV",+ "GFV",+ "SFvTPv",+ "ISECT",++ "SRP0",+ "SRP1",+ "SRP2",+ "SZP0",+ "SZP1",+ "SZP2",+ "SZPS",+ "SLOOP",+ "RTG",+ "RTHG",+ "SMD",+ "ELSE",+ "JMPR",+ "SCvTCi",+ "SSwCi",+ "SSW",++ "DUP",+ "POP",+ "CLEAR",+ "SWAP",+ "DEPTH",+ "CINDEX",+ "MINDEX",+ "AlignPTS",+ "INS_$28",+ "UTP",+ "LOOPCALL",+ "CALL",+ "FDEF",+ "ENDF",+ "MDAP[0]",+ "MDAP[1]",++ "IUP[0]",+ "IUP[1]",+ "SHP[0]",+ "SHP[1]",+ "SHC[0]",+ "SHC[1]",+ "SHZ[0]",+ "SHZ[1]",+ "SHPIX",+ "IP",+ "MSIRP[0]",+ "MSIRP[1]",+ "AlignRP",+ "RTDG",+ "MIAP[0]",+ "MIAP[1]",++ "NPushB",+ "NPushW",+ "WS",+ "RS",+ "WCvtP",+ "RCvt",+ "GC[0]",+ "GC[1]",+ "SCFS",+ "MD[0]",+ "MD[1]",+ "MPPEM",+ "MPS",+ "FlipON",+ "FlipOFF",+ "DEBUG",++ "LT",+ "LTEQ",+ "GT",+ "GTEQ",+ "EQ",+ "NEQ",+ "ODD",+ "EVEN",+ "IF",+ "EIF",+ "AND",+ "OR",+ "NOT",+ "DeltaP1",+ "SDB",+ "SDS",++ "ADD",+ "SUB",+ "DIV",+ "MUL",+ "ABS",+ "NEG",+ "FLOOR",+ "CEILING",+ "ROUND[0]",+ "ROUND[1]",+ "ROUND[2]",+ "ROUND[3]",+ "NROUND[0]",+ "NROUND[1]",+ "NROUND[2]",+ "NROUND[3]",++ "WCvtF",+ "DeltaP2",+ "DeltaP3",+ "DeltaCn[0]",+ "DeltaCn[1]",+ "DeltaCn[2]",+ "SROUND",+ "S45Round",+ "JROT",+ "JROF",+ "ROFF",+ "INS_$7B",+ "RUTG",+ "RDTG",+ "SANGW",+ "AA",++ "FlipPT",+ "FlipRgON",+ "FlipRgOFF",+ "INS_$83",+ "INS_$84",+ "ScanCTRL",+ "SDVPTL[0]",+ "SDVPTL[1]",+ "GetINFO",+ "IDEF",+ "ROLL",+ "MAX",+ "MIN",+ "ScanTYPE",+ "InstCTRL",+ "INS_$8F",++ "INS_$90",+ "INS_$91",+ "INS_$92",+ "INS_$93",+ "INS_$94",+ "INS_$95",+ "INS_$96",+ "INS_$97",+ "INS_$98",+ "INS_$99",+ "INS_$9A",+ "INS_$9B",+ "INS_$9C",+ "INS_$9D",+ "INS_$9E",+ "INS_$9F",++ "INS_$A0",+ "INS_$A1",+ "INS_$A2",+ "INS_$A3",+ "INS_$A4",+ "INS_$A5",+ "INS_$A6",+ "INS_$A7",+ "INS_$A8",+ "INS_$A9",+ "INS_$AA",+ "INS_$AB",+ "INS_$AC",+ "INS_$AD",+ "INS_$AE",+ "INS_$AF",++ "PushB[0]",+ "PushB[1]",+ "PushB[2]",+ "PushB[3]",+ "PushB[4]",+ "PushB[5]",+ "PushB[6]",+ "PushB[7]",+ "PushW[0]",+ "PushW[1]",+ "PushW[2]",+ "PushW[3]",+ "PushW[4]",+ "PushW[5]",+ "PushW[6]",+ "PushW[7]",++ "MDRP[00]",+ "MDRP[01]",+ "MDRP[02]",+ "MDRP[03]",+ "MDRP[04]",+ "MDRP[05]",+ "MDRP[06]",+ "MDRP[07]",+ "MDRP[08]",+ "MDRP[09]",+ "MDRP[10]",+ "MDRP[11]",+ "MDRP[12]",+ "MDRP[13]",+ "MDRP[14]",+ "MDRP[15]",++ "MDRP[16]",+ "MDRP[17]",+ "MDRP[18]",+ "MDRP[19]",+ "MDRP[20]",+ "MDRP[21]",+ "MDRP[22]",+ "MDRP[23]",+ "MDRP[24]",+ "MDRP[25]",+ "MDRP[26]",+ "MDRP[27]",+ "MDRP[28]",+ "MDRP[29]",+ "MDRP[30]",+ "MDRP[31]",++ "MIRP[00]",+ "MIRP[01]",+ "MIRP[02]",+ "MIRP[03]",+ "MIRP[04]",+ "MIRP[05]",+ "MIRP[06]",+ "MIRP[07]",+ "MIRP[08]",+ "MIRP[09]",+ "MIRP[10]",+ "MIRP[11]",+ "MIRP[12]",+ "MIRP[13]",+ "MIRP[14]",+ "MIRP[15]",++ "MIRP[16]",+ "MIRP[17]",+ "MIRP[18]",+ "MIRP[19]",+ "MIRP[20]",+ "MIRP[21]",+ "MIRP[22]",+ "MIRP[23]",+ "MIRP[24]",+ "MIRP[25]",+ "MIRP[26]",+ "MIRP[27]",+ "MIRP[28]",+ "MIRP[29]",+ "MIRP[30]",+ "MIRP[31]"+ };++#endif /* FT_DEBUG_LEVEL_TRACE */+++ static+ const FT_Char opcode_length[256] =+ {+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,++ -1,-2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,++ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,+ 2, 3, 4, 5, 6, 7, 8, 9, 3, 5, 7, 9, 11,13,15,17,++ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1+ };++#undef PACK++#if 1++ static FT_Int32+ TT_MulFix14( FT_Int32 a,+ FT_Int b )+ {+ FT_Int32 sign;+ FT_UInt32 ah, al, mid, lo, hi;+++ sign = a ^ b;++ if ( a < 0 )+ a = -a;+ if ( b < 0 )+ b = -b;++ ah = (FT_UInt32)( ( a >> 16 ) & 0xFFFFU );+ al = (FT_UInt32)( a & 0xFFFFU );++ lo = al * b;+ mid = ah * b;+ hi = mid >> 16;+ mid = ( mid << 16 ) + ( 1 << 13 ); /* rounding */+ lo += mid;+ if ( lo < mid )+ hi += 1;++ mid = ( lo >> 14 ) | ( hi << 18 );++ return sign >= 0 ? (FT_Int32)mid : -(FT_Int32)mid;+ }++#else++ /* compute (a*b)/2^14 with maximal accuracy and rounding */+ static FT_Int32+ TT_MulFix14( FT_Int32 a,+ FT_Int b )+ {+ FT_Int32 m, s, hi;+ FT_UInt32 l, lo;+++ /* compute ax*bx as 64-bit value */+ l = (FT_UInt32)( ( a & 0xFFFFU ) * b );+ m = ( a >> 16 ) * b;++ lo = l + (FT_UInt32)( m << 16 );+ hi = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo < l );++ /* divide the result by 2^14 with rounding */+ s = hi >> 31;+ l = lo + (FT_UInt32)s;+ hi += s + ( l < lo );+ lo = l;++ l = lo + 0x2000U;+ hi += l < lo;++ return ( hi << 18 ) | ( l >> 14 );+ }+#endif+++ /* compute (ax*bx+ay*by)/2^14 with maximal accuracy and rounding */+ static FT_Int32+ TT_DotFix14( FT_Int32 ax,+ FT_Int32 ay,+ FT_Int bx,+ FT_Int by )+ {+ FT_Int32 m, s, hi1, hi2, hi;+ FT_UInt32 l, lo1, lo2, lo;+++ /* compute ax*bx as 64-bit value */+ l = (FT_UInt32)( ( ax & 0xFFFFU ) * bx );+ m = ( ax >> 16 ) * bx;++ lo1 = l + (FT_UInt32)( m << 16 );+ hi1 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo1 < l );++ /* compute ay*by as 64-bit value */+ l = (FT_UInt32)( ( ay & 0xFFFFU ) * by );+ m = ( ay >> 16 ) * by;++ lo2 = l + (FT_UInt32)( m << 16 );+ hi2 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo2 < l );++ /* add them */+ lo = lo1 + lo2;+ hi = hi1 + hi2 + ( lo < lo1 );++ /* divide the result by 2^14 with rounding */+ s = hi >> 31;+ l = lo + (FT_UInt32)s;+ hi += s + ( l < lo );+ lo = l;++ l = lo + 0x2000U;+ hi += ( l < lo );++ return ( hi << 18 ) | ( l >> 14 );+ }+++ /* return length of given vector */++#if 0++ static FT_Int32+ TT_VecLen( FT_Int32 x,+ FT_Int32 y )+ {+ FT_Int32 m, hi1, hi2, hi;+ FT_UInt32 l, lo1, lo2, lo;+++ /* compute x*x as 64-bit value */+ lo = (FT_UInt32)( x & 0xFFFFU );+ hi = x >> 16;++ l = lo * lo;+ m = hi * lo;+ hi = hi * hi;++ lo1 = l + (FT_UInt32)( m << 17 );+ hi1 = hi + ( m >> 15 ) + ( lo1 < l );++ /* compute y*y as 64-bit value */+ lo = (FT_UInt32)( y & 0xFFFFU );+ hi = y >> 16;++ l = lo * lo;+ m = hi * lo;+ hi = hi * hi;++ lo2 = l + (FT_UInt32)( m << 17 );+ hi2 = hi + ( m >> 15 ) + ( lo2 < l );++ /* add them to get 'x*x+y*y' as 64-bit value */+ lo = lo1 + lo2;+ hi = hi1 + hi2 + ( lo < lo1 );++ /* compute the square root of this value */+ {+ FT_UInt32 root, rem, test_div;+ FT_Int count;+++ root = 0;++ {+ rem = 0;+ count = 32;+ do+ {+ rem = ( rem << 2 ) | ( (FT_UInt32)hi >> 30 );+ hi = ( hi << 2 ) | ( lo >> 30 );+ lo <<= 2;+ root <<= 1;+ test_div = ( root << 1 ) + 1;++ if ( rem >= test_div )+ {+ rem -= test_div;+ root += 1;+ }+ } while ( --count );+ }++ return (FT_Int32)root;+ }+ }++#else++ /* this version uses FT_Vector_Length which computes the same value */+ /* much, much faster.. */+ /* */+ static FT_F26Dot6+ TT_VecLen( FT_F26Dot6 X,+ FT_F26Dot6 Y )+ {+ FT_Vector v;+++ v.x = X;+ v.y = Y;++ return FT_Vector_Length( &v );+ }++#endif+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Current_Ratio */+ /* */+ /* <Description> */+ /* Returns the current aspect ratio scaling factor depending on the */+ /* projection vector's state and device resolutions. */+ /* */+ /* <Return> */+ /* The aspect ratio in 16.16 format, always <= 1.0 . */+ /* */+ static FT_Long+ Current_Ratio( EXEC_OP )+ {+ if ( !CUR.tt_metrics.ratio )+ {+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING+ if ( CUR.face->unpatented_hinting )+ {+ if ( CUR.GS.both_x_axis )+ CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;+ else+ CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;+ }+ else+#endif+ {+ if ( CUR.GS.projVector.y == 0 )+ CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;++ else if ( CUR.GS.projVector.x == 0 )+ CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;++ else+ {+ FT_Long x, y;+++ x = TT_MULDIV( CUR.GS.projVector.x,+ CUR.tt_metrics.x_ratio, 0x4000 );+ y = TT_MULDIV( CUR.GS.projVector.y,+ CUR.tt_metrics.y_ratio, 0x4000 );+ CUR.tt_metrics.ratio = TT_VecLen( x, y );+ }+ }+ }+ return CUR.tt_metrics.ratio;+ }+++ static FT_Long+ Current_Ppem( EXEC_OP )+ {+ return TT_MULFIX( CUR.tt_metrics.ppem, CURRENT_Ratio() );+ }+++ /*************************************************************************/+ /* */+ /* Functions related to the control value table (CVT). */+ /* */+ /*************************************************************************/+++ FT_CALLBACK_DEF( FT_F26Dot6 )+ Read_CVT( EXEC_OP_ FT_ULong idx )+ {+ return CUR.cvt[idx];+ }+++ FT_CALLBACK_DEF( FT_F26Dot6 )+ Read_CVT_Stretched( EXEC_OP_ FT_ULong idx )+ {+ return TT_MULFIX( CUR.cvt[idx], CURRENT_Ratio() );+ }+++ FT_CALLBACK_DEF( void )+ Write_CVT( EXEC_OP_ FT_ULong idx,+ FT_F26Dot6 value )+ {+ CUR.cvt[idx] = value;+ }+++ FT_CALLBACK_DEF( void )+ Write_CVT_Stretched( EXEC_OP_ FT_ULong idx,+ FT_F26Dot6 value )+ {+ CUR.cvt[idx] = FT_DivFix( value, CURRENT_Ratio() );+ }+++ FT_CALLBACK_DEF( void )+ Move_CVT( EXEC_OP_ FT_ULong idx,+ FT_F26Dot6 value )+ {+ CUR.cvt[idx] += value;+ }+++ FT_CALLBACK_DEF( void )+ Move_CVT_Stretched( EXEC_OP_ FT_ULong idx,+ FT_F26Dot6 value )+ {+ CUR.cvt[idx] += FT_DivFix( value, CURRENT_Ratio() );+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* GetShortIns */+ /* */+ /* <Description> */+ /* Returns a short integer taken from the instruction stream at */+ /* address IP. */+ /* */+ /* <Return> */+ /* Short read at code[IP]. */+ /* */+ /* <Note> */+ /* This one could become a macro. */+ /* */+ static FT_Short+ GetShortIns( EXEC_OP )+ {+ /* Reading a byte stream so there is no endianess (DaveP) */+ CUR.IP += 2;+ return (FT_Short)( ( CUR.code[CUR.IP - 2] << 8 ) ++ CUR.code[CUR.IP - 1] );+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Ins_Goto_CodeRange */+ /* */+ /* <Description> */+ /* Goes to a certain code range in the instruction stream. */+ /* */+ /* <Input> */+ /* aRange :: The index of the code range. */+ /* */+ /* aIP :: The new IP address in the code range. */+ /* */+ /* <Return> */+ /* SUCCESS or FAILURE. */+ /* */+ static FT_Bool+ Ins_Goto_CodeRange( EXEC_OP_ FT_Int aRange,+ FT_ULong aIP )+ {+ TT_CodeRange* range;+++ if ( aRange < 1 || aRange > 3 )+ {+ CUR.error = TT_Err_Bad_Argument;+ return FAILURE;+ }++ range = &CUR.codeRangeTable[aRange - 1];++ if ( range->base == NULL ) /* invalid coderange */+ {+ CUR.error = TT_Err_Invalid_CodeRange;+ return FAILURE;+ }++ /* NOTE: Because the last instruction of a program may be a CALL */+ /* which will return to the first byte *after* the code */+ /* range, we test for AIP <= Size, instead of AIP < Size. */++ if ( aIP > range->size )+ {+ CUR.error = TT_Err_Code_Overflow;+ return FAILURE;+ }++ CUR.code = range->base;+ CUR.codeSize = range->size;+ CUR.IP = aIP;+ CUR.curRange = aRange;++ return SUCCESS;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Direct_Move */+ /* */+ /* <Description> */+ /* Moves a point by a given distance along the freedom vector. The */+ /* point will be `touched'. */+ /* */+ /* <Input> */+ /* point :: The index of the point to move. */+ /* */+ /* distance :: The distance to apply. */+ /* */+ /* <InOut> */+ /* zone :: The affected glyph zone. */+ /* */+ static void+ Direct_Move( EXEC_OP_ TT_GlyphZone zone,+ FT_UShort point,+ FT_F26Dot6 distance )+ {+ FT_F26Dot6 v;+++#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING+ FT_ASSERT( !CUR.face->unpatented_hinting );+#endif++ v = CUR.GS.freeVector.x;++ if ( v != 0 )+ {+ zone->cur[point].x += TT_MULDIV( distance,+ v * 0x10000L,+ CUR.F_dot_P );++ zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;+ }++ v = CUR.GS.freeVector.y;++ if ( v != 0 )+ {+ zone->cur[point].y += TT_MULDIV( distance,+ v * 0x10000L,+ CUR.F_dot_P );++ zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;+ }+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Direct_Move_Orig */+ /* */+ /* <Description> */+ /* Moves the *original* position of a point by a given distance along */+ /* the freedom vector. Obviously, the point will not be `touched'. */+ /* */+ /* <Input> */+ /* point :: The index of the point to move. */+ /* */+ /* distance :: The distance to apply. */+ /* */+ /* <InOut> */+ /* zone :: The affected glyph zone. */+ /* */+ static void+ Direct_Move_Orig( EXEC_OP_ TT_GlyphZone zone,+ FT_UShort point,+ FT_F26Dot6 distance )+ {+ FT_F26Dot6 v;+++#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING+ FT_ASSERT( !CUR.face->unpatented_hinting );+#endif++ v = CUR.GS.freeVector.x;++ if ( v != 0 )+ zone->org[point].x += TT_MULDIV( distance,+ v * 0x10000L,+ CUR.F_dot_P );++ v = CUR.GS.freeVector.y;++ if ( v != 0 )+ zone->org[point].y += TT_MULDIV( distance,+ v * 0x10000L,+ CUR.F_dot_P );+ }+++ /*************************************************************************/+ /* */+ /* Special versions of Direct_Move() */+ /* */+ /* The following versions are used whenever both vectors are both */+ /* along one of the coordinate unit vectors, i.e. in 90% of the cases. */+ /* */+ /*************************************************************************/+++ static void+ Direct_Move_X( EXEC_OP_ TT_GlyphZone zone,+ FT_UShort point,+ FT_F26Dot6 distance )+ {+ FT_UNUSED_EXEC;++ zone->cur[point].x += distance;+ zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;+ }+++ static void+ Direct_Move_Y( EXEC_OP_ TT_GlyphZone zone,+ FT_UShort point,+ FT_F26Dot6 distance )+ {+ FT_UNUSED_EXEC;++ zone->cur[point].y += distance;+ zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;+ }+++ /*************************************************************************/+ /* */+ /* Special versions of Direct_Move_Orig() */+ /* */+ /* The following versions are used whenever both vectors are both */+ /* along one of the coordinate unit vectors, i.e. in 90% of the cases. */+ /* */+ /*************************************************************************/+++ static void+ Direct_Move_Orig_X( EXEC_OP_ TT_GlyphZone zone,+ FT_UShort point,+ FT_F26Dot6 distance )+ {+ FT_UNUSED_EXEC;++ zone->org[point].x += distance;+ }+++ static void+ Direct_Move_Orig_Y( EXEC_OP_ TT_GlyphZone zone,+ FT_UShort point,+ FT_F26Dot6 distance )+ {+ FT_UNUSED_EXEC;++ zone->org[point].y += distance;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Round_None */+ /* */+ /* <Description> */+ /* Does not round, but adds engine compensation. */+ /* */+ /* <Input> */+ /* distance :: The distance (not) to round. */+ /* */+ /* compensation :: The engine compensation. */+ /* */+ /* <Return> */+ /* The compensated distance. */+ /* */+ /* <Note> */+ /* The TrueType specification says very few about the relationship */+ /* between rounding and engine compensation. However, it seems from */+ /* the description of super round that we should add the compensation */+ /* before rounding. */+ /* */+ static FT_F26Dot6+ Round_None( EXEC_OP_ FT_F26Dot6 distance,+ FT_F26Dot6 compensation )+ {+ FT_F26Dot6 val;++ FT_UNUSED_EXEC;+++ if ( distance >= 0 )+ {+ val = distance + compensation;+ if ( distance && val < 0 )+ val = 0;+ }+ else+ {+ val = distance - compensation;+ if ( val > 0 )+ val = 0;+ }+ return val;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Round_To_Grid */+ /* */+ /* <Description> */+ /* Rounds value to grid after adding engine compensation. */+ /* */+ /* <Input> */+ /* distance :: The distance to round. */+ /* */+ /* compensation :: The engine compensation. */+ /* */+ /* <Return> */+ /* Rounded distance. */+ /* */+ static FT_F26Dot6+ Round_To_Grid( EXEC_OP_ FT_F26Dot6 distance,+ FT_F26Dot6 compensation )+ {+ FT_F26Dot6 val;++ FT_UNUSED_EXEC;+++ if ( distance >= 0 )+ {+ val = distance + compensation + 32;+ if ( distance && val > 0 )+ val &= ~63;+ else+ val = 0;+ }+ else+ {+ val = -FT_PIX_ROUND( compensation - distance );+ if ( val > 0 )+ val = 0;+ }++ return val;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Round_To_Half_Grid */+ /* */+ /* <Description> */+ /* Rounds value to half grid after adding engine compensation. */+ /* */+ /* <Input> */+ /* distance :: The distance to round. */+ /* */+ /* compensation :: The engine compensation. */+ /* */+ /* <Return> */+ /* Rounded distance. */+ /* */+ static FT_F26Dot6+ Round_To_Half_Grid( EXEC_OP_ FT_F26Dot6 distance,+ FT_F26Dot6 compensation )+ {+ FT_F26Dot6 val;++ FT_UNUSED_EXEC;+++ if ( distance >= 0 )+ {+ val = FT_PIX_FLOOR( distance + compensation ) + 32;+ if ( distance && val < 0 )+ val = 0;+ }+ else+ {+ val = -( FT_PIX_FLOOR( compensation - distance ) + 32 );+ if ( val > 0 )+ val = 0;+ }++ return val;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Round_Down_To_Grid */+ /* */+ /* <Description> */+ /* Rounds value down to grid after adding engine compensation. */+ /* */+ /* <Input> */+ /* distance :: The distance to round. */+ /* */+ /* compensation :: The engine compensation. */+ /* */+ /* <Return> */+ /* Rounded distance. */+ /* */+ static FT_F26Dot6+ Round_Down_To_Grid( EXEC_OP_ FT_F26Dot6 distance,+ FT_F26Dot6 compensation )+ {+ FT_F26Dot6 val;++ FT_UNUSED_EXEC;+++ if ( distance >= 0 )+ {+ val = distance + compensation;+ if ( distance && val > 0 )+ val &= ~63;+ else+ val = 0;+ }+ else+ {+ val = -( ( compensation - distance ) & -64 );+ if ( val > 0 )+ val = 0;+ }++ return val;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Round_Up_To_Grid */+ /* */+ /* <Description> */+ /* Rounds value up to grid after adding engine compensation. */+ /* */+ /* <Input> */+ /* distance :: The distance to round. */+ /* */+ /* compensation :: The engine compensation. */+ /* */+ /* <Return> */+ /* Rounded distance. */+ /* */+ static FT_F26Dot6+ Round_Up_To_Grid( EXEC_OP_ FT_F26Dot6 distance,+ FT_F26Dot6 compensation )+ {+ FT_F26Dot6 val;++ FT_UNUSED_EXEC;+++ if ( distance >= 0 )+ {+ val = distance + compensation + 63;+ if ( distance && val > 0 )+ val &= ~63;+ else+ val = 0;+ }+ else+ {+ val = - FT_PIX_CEIL( compensation - distance );+ if ( val > 0 )+ val = 0;+ }++ return val;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Round_To_Double_Grid */+ /* */+ /* <Description> */+ /* Rounds value to double grid after adding engine compensation. */+ /* */+ /* <Input> */+ /* distance :: The distance to round. */+ /* */+ /* compensation :: The engine compensation. */+ /* */+ /* <Return> */+ /* Rounded distance. */+ /* */+ static FT_F26Dot6+ Round_To_Double_Grid( EXEC_OP_ FT_F26Dot6 distance,+ FT_F26Dot6 compensation )+ {+ FT_F26Dot6 val;++ FT_UNUSED_EXEC;+++ if ( distance >= 0 )+ {+ val = distance + compensation + 16;+ if ( distance && val > 0 )+ val &= ~31;+ else+ val = 0;+ }+ else+ {+ val = -FT_PAD_ROUND( compensation - distance, 32 );+ if ( val > 0 )+ val = 0;+ }++ return val;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Round_Super */+ /* */+ /* <Description> */+ /* Super-rounds value to grid after adding engine compensation. */+ /* */+ /* <Input> */+ /* distance :: The distance to round. */+ /* */+ /* compensation :: The engine compensation. */+ /* */+ /* <Return> */+ /* Rounded distance. */+ /* */+ /* <Note> */+ /* The TrueType specification says very few about the relationship */+ /* between rounding and engine compensation. However, it seems from */+ /* the description of super round that we should add the compensation */+ /* before rounding. */+ /* */+ static FT_F26Dot6+ Round_Super( EXEC_OP_ FT_F26Dot6 distance,+ FT_F26Dot6 compensation )+ {+ FT_F26Dot6 val;+++ if ( distance >= 0 )+ {+ val = ( distance - CUR.phase + CUR.threshold + compensation ) &+ -CUR.period;+ if ( distance && val < 0 )+ val = 0;+ val += CUR.phase;+ }+ else+ {+ val = -( ( CUR.threshold - CUR.phase - distance + compensation ) &+ -CUR.period );+ if ( val > 0 )+ val = 0;+ val -= CUR.phase;+ }++ return val;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Round_Super_45 */+ /* */+ /* <Description> */+ /* Super-rounds value to grid after adding engine compensation. */+ /* */+ /* <Input> */+ /* distance :: The distance to round. */+ /* */+ /* compensation :: The engine compensation. */+ /* */+ /* <Return> */+ /* Rounded distance. */+ /* */+ /* <Note> */+ /* There is a separate function for Round_Super_45() as we may need */+ /* greater precision. */+ /* */+ static FT_F26Dot6+ Round_Super_45( EXEC_OP_ FT_F26Dot6 distance,+ FT_F26Dot6 compensation )+ {+ FT_F26Dot6 val;+++ if ( distance >= 0 )+ {+ val = ( ( distance - CUR.phase + CUR.threshold + compensation ) /+ CUR.period ) * CUR.period;+ if ( distance && val < 0 )+ val = 0;+ val += CUR.phase;+ }+ else+ {+ val = -( ( ( CUR.threshold - CUR.phase - distance + compensation ) /+ CUR.period ) * CUR.period );+ if ( val > 0 )+ val = 0;+ val -= CUR.phase;+ }++ return val;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Compute_Round */+ /* */+ /* <Description> */+ /* Sets the rounding mode. */+ /* */+ /* <Input> */+ /* round_mode :: The rounding mode to be used. */+ /* */+ static void+ Compute_Round( EXEC_OP_ FT_Byte round_mode )+ {+ switch ( round_mode )+ {+ case TT_Round_Off:+ CUR.func_round = (TT_Round_Func)Round_None;+ break;++ case TT_Round_To_Grid:+ CUR.func_round = (TT_Round_Func)Round_To_Grid;+ break;++ case TT_Round_Up_To_Grid:+ CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;+ break;++ case TT_Round_Down_To_Grid:+ CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;+ break;++ case TT_Round_To_Half_Grid:+ CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;+ break;++ case TT_Round_To_Double_Grid:+ CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;+ break;++ case TT_Round_Super:+ CUR.func_round = (TT_Round_Func)Round_Super;+ break;++ case TT_Round_Super_45:+ CUR.func_round = (TT_Round_Func)Round_Super_45;+ break;+ }+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* SetSuperRound */+ /* */+ /* <Description> */+ /* Sets Super Round parameters. */+ /* */+ /* <Input> */+ /* GridPeriod :: Grid period */+ /* selector :: SROUND opcode */+ /* */+ static void+ SetSuperRound( EXEC_OP_ FT_F26Dot6 GridPeriod,+ FT_Long selector )+ {+ switch ( (FT_Int)( selector & 0xC0 ) )+ {+ case 0:+ CUR.period = GridPeriod / 2;+ break;++ case 0x40:+ CUR.period = GridPeriod;+ break;++ case 0x80:+ CUR.period = GridPeriod * 2;+ break;++ /* This opcode is reserved, but... */++ case 0xC0:+ CUR.period = GridPeriod;+ break;+ }++ switch ( (FT_Int)( selector & 0x30 ) )+ {+ case 0:+ CUR.phase = 0;+ break;++ case 0x10:+ CUR.phase = CUR.period / 4;+ break;++ case 0x20:+ CUR.phase = CUR.period / 2;+ break;++ case 0x30:+ CUR.phase = CUR.period * 3 / 4;+ break;+ }++ if ( ( selector & 0x0F ) == 0 )+ CUR.threshold = CUR.period - 1;+ else+ CUR.threshold = ( (FT_Int)( selector & 0x0F ) - 4 ) * CUR.period / 8;++ CUR.period /= 256;+ CUR.phase /= 256;+ CUR.threshold /= 256;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Project */+ /* */+ /* <Description> */+ /* Computes the projection of vector given by (v2-v1) along the */+ /* current projection vector. */+ /* */+ /* <Input> */+ /* v1 :: First input vector. */+ /* v2 :: Second input vector. */+ /* */+ /* <Return> */+ /* The distance in F26dot6 format. */+ /* */+ static FT_F26Dot6+ Project( EXEC_OP_ FT_Pos dx,+ FT_Pos dy )+ {+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING+ FT_ASSERT( !CUR.face->unpatented_hinting );+#endif++ return TT_DotFix14( (FT_UInt32)dx, (FT_UInt32)dy,+ CUR.GS.projVector.x,+ CUR.GS.projVector.y );+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Dual_Project */+ /* */+ /* <Description> */+ /* Computes the projection of the vector given by (v2-v1) along the */+ /* current dual vector. */+ /* */+ /* <Input> */+ /* v1 :: First input vector. */+ /* v2 :: Second input vector. */+ /* */+ /* <Return> */+ /* The distance in F26dot6 format. */+ /* */+ static FT_F26Dot6+ Dual_Project( EXEC_OP_ FT_Pos dx,+ FT_Pos dy )+ {+ return TT_DotFix14( (FT_UInt32)dx, (FT_UInt32)dy,+ CUR.GS.dualVector.x,+ CUR.GS.dualVector.y );+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Project_x */+ /* */+ /* <Description> */+ /* Computes the projection of the vector given by (v2-v1) along the */+ /* horizontal axis. */+ /* */+ /* <Input> */+ /* v1 :: First input vector. */+ /* v2 :: Second input vector. */+ /* */+ /* <Return> */+ /* The distance in F26dot6 format. */+ /* */+ static FT_F26Dot6+ Project_x( EXEC_OP_ FT_Pos dx,+ FT_Pos dy )+ {+ FT_UNUSED_EXEC;+ FT_UNUSED( dy );++ return dx;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Project_y */+ /* */+ /* <Description> */+ /* Computes the projection of the vector given by (v2-v1) along the */+ /* vertical axis. */+ /* */+ /* <Input> */+ /* v1 :: First input vector. */+ /* v2 :: Second input vector. */+ /* */+ /* <Return> */+ /* The distance in F26dot6 format. */+ /* */+ static FT_F26Dot6+ Project_y( EXEC_OP_ FT_Pos dx,+ FT_Pos dy )+ {+ FT_UNUSED_EXEC;+ FT_UNUSED( dx );++ return dy;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Compute_Funcs */+ /* */+ /* <Description> */+ /* Computes the projection and movement function pointers according */+ /* to the current graphics state. */+ /* */+ static void+ Compute_Funcs( EXEC_OP )+ {+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING+ if ( CUR.face->unpatented_hinting )+ {+ /* If both vectors point rightwards along the x axis, set */+ /* `both-x-axis' true, otherwise set it false. The x values only */+ /* need be tested because the vector has been normalised to a unit */+ /* vector of length 0x4000 = unity. */+ CUR.GS.both_x_axis = (FT_Bool)( CUR.GS.projVector.x == 0x4000 &&+ CUR.GS.freeVector.x == 0x4000 );++ /* Throw away projection and freedom vector information */+ /* because the patents don't allow them to be stored. */+ /* The relevant US Patents are 5155805 and 5325479. */+ CUR.GS.projVector.x = 0;+ CUR.GS.projVector.y = 0;+ CUR.GS.freeVector.x = 0;+ CUR.GS.freeVector.y = 0;++ if ( CUR.GS.both_x_axis )+ {+ CUR.func_project = Project_x;+ CUR.func_move = Direct_Move_X;+ CUR.func_move_orig = Direct_Move_Orig_X;+ }+ else+ {+ CUR.func_project = Project_y;+ CUR.func_move = Direct_Move_Y;+ CUR.func_move_orig = Direct_Move_Orig_Y;+ }++ if ( CUR.GS.dualVector.x == 0x4000 )+ CUR.func_dualproj = Project_x;+ else+ {+ if ( CUR.GS.dualVector.y == 0x4000 )+ CUR.func_dualproj = Project_y;+ else+ CUR.func_dualproj = Dual_Project;+ }++ /* Force recalculation of cached aspect ratio */+ CUR.tt_metrics.ratio = 0;++ return;+ }+#endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING */++ if ( CUR.GS.freeVector.x == 0x4000 )+ CUR.F_dot_P = CUR.GS.projVector.x * 0x10000L;+ else+ {+ if ( CUR.GS.freeVector.y == 0x4000 )+ CUR.F_dot_P = CUR.GS.projVector.y * 0x10000L;+ else+ CUR.F_dot_P = (FT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x * 4 ++ (FT_Long)CUR.GS.projVector.y * CUR.GS.freeVector.y * 4;+ }++ if ( CUR.GS.projVector.x == 0x4000 )+ CUR.func_project = (TT_Project_Func)Project_x;+ else+ {+ if ( CUR.GS.projVector.y == 0x4000 )+ CUR.func_project = (TT_Project_Func)Project_y;+ else+ CUR.func_project = (TT_Project_Func)Project;+ }++ if ( CUR.GS.dualVector.x == 0x4000 )+ CUR.func_dualproj = (TT_Project_Func)Project_x;+ else+ {+ if ( CUR.GS.dualVector.y == 0x4000 )+ CUR.func_dualproj = (TT_Project_Func)Project_y;+ else+ CUR.func_dualproj = (TT_Project_Func)Dual_Project;+ }++ CUR.func_move = (TT_Move_Func)Direct_Move;+ CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig;++ if ( CUR.F_dot_P == 0x40000000L )+ {+ if ( CUR.GS.freeVector.x == 0x4000 )+ {+ CUR.func_move = (TT_Move_Func)Direct_Move_X;+ CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_X;+ }+ else+ {+ if ( CUR.GS.freeVector.y == 0x4000 )+ {+ CUR.func_move = (TT_Move_Func)Direct_Move_Y;+ CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y;+ }+ }+ }++ /* at small sizes, F_dot_P can become too small, resulting */+ /* in overflows and `spikes' in a number of glyphs like `w'. */++ if ( FT_ABS( CUR.F_dot_P ) < 0x4000000L )+ CUR.F_dot_P = 0x40000000L;++ /* Disable cached aspect ratio */+ CUR.tt_metrics.ratio = 0;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Normalize */+ /* */+ /* <Description> */+ /* Norms a vector. */+ /* */+ /* <Input> */+ /* Vx :: The horizontal input vector coordinate. */+ /* Vy :: The vertical input vector coordinate. */+ /* */+ /* <Output> */+ /* R :: The normed unit vector. */+ /* */+ /* <Return> */+ /* Returns FAILURE if a vector parameter is zero. */+ /* */+ /* <Note> */+ /* In case Vx and Vy are both zero, Normalize() returns SUCCESS, and */+ /* R is undefined. */+ /* */+++ static FT_Bool+ Normalize( EXEC_OP_ FT_F26Dot6 Vx,+ FT_F26Dot6 Vy,+ FT_UnitVector* R )+ {+ FT_F26Dot6 W;+ FT_Bool S1, S2;++ FT_UNUSED_EXEC;+++ if ( FT_ABS( Vx ) < 0x10000L && FT_ABS( Vy ) < 0x10000L )+ {+ Vx *= 0x100;+ Vy *= 0x100;++ W = TT_VecLen( Vx, Vy );++ if ( W == 0 )+ {+ /* XXX: UNDOCUMENTED! It seems that it is possible to try */+ /* to normalize the vector (0,0). Return immediately. */+ return SUCCESS;+ }++ R->x = (FT_F2Dot14)FT_MulDiv( Vx, 0x4000L, W );+ R->y = (FT_F2Dot14)FT_MulDiv( Vy, 0x4000L, W );++ return SUCCESS;+ }++ W = TT_VecLen( Vx, Vy );++ Vx = FT_MulDiv( Vx, 0x4000L, W );+ Vy = FT_MulDiv( Vy, 0x4000L, W );++ W = Vx * Vx + Vy * Vy;++ /* Now, we want that Sqrt( W ) = 0x4000 */+ /* Or 0x10000000 <= W < 0x10004000 */++ if ( Vx < 0 )+ {+ Vx = -Vx;+ S1 = TRUE;+ }+ else+ S1 = FALSE;++ if ( Vy < 0 )+ {+ Vy = -Vy;+ S2 = TRUE;+ }+ else+ S2 = FALSE;++ while ( W < 0x10000000L )+ {+ /* We need to increase W by a minimal amount */+ if ( Vx < Vy )+ Vx++;+ else+ Vy++;++ W = Vx * Vx + Vy * Vy;+ }++ while ( W >= 0x10004000L )+ {+ /* We need to decrease W by a minimal amount */+ if ( Vx < Vy )+ Vx--;+ else+ Vy--;++ W = Vx * Vx + Vy * Vy;+ }++ /* Note that in various cases, we can only */+ /* compute a Sqrt(W) of 0x3FFF, eg. Vx = Vy */++ if ( S1 )+ Vx = -Vx;++ if ( S2 )+ Vy = -Vy;++ R->x = (FT_F2Dot14)Vx; /* Type conversion */+ R->y = (FT_F2Dot14)Vy; /* Type conversion */++ return SUCCESS;+ }+++ /*************************************************************************/+ /* */+ /* Here we start with the implementation of the various opcodes. */+ /* */+ /*************************************************************************/+++ static FT_Bool+ Ins_SxVTL( EXEC_OP_ FT_UShort aIdx1,+ FT_UShort aIdx2,+ FT_Int aOpc,+ FT_UnitVector* Vec )+ {+ FT_Long A, B, C;+ FT_Vector* p1;+ FT_Vector* p2;+++ if ( BOUNDS( aIdx1, CUR.zp2.n_points ) ||+ BOUNDS( aIdx2, CUR.zp1.n_points ) )+ {+ if ( CUR.pedantic_hinting )+ CUR.error = TT_Err_Invalid_Reference;+ return FAILURE;+ }++ p1 = CUR.zp1.cur + aIdx2;+ p2 = CUR.zp2.cur + aIdx1;++ A = p1->x - p2->x;+ B = p1->y - p2->y;++ if ( ( aOpc & 1 ) != 0 )+ {+ C = B; /* counter clockwise rotation */+ B = A;+ A = -C;+ }++ NORMalize( A, B, Vec );++ return SUCCESS;+ }+++ /* When not using the big switch statements, the interpreter uses a */+ /* call table defined later below in this source. Each opcode must */+ /* thus have a corresponding function, even trivial ones. */+ /* */+ /* They are all defined there. */++#define DO_SVTCA \+ { \+ FT_Short A, B; \+ \+ \+ A = (FT_Short)( CUR.opcode & 1 ) << 14; \+ B = A ^ (FT_Short)0x4000; \+ \+ CUR.GS.freeVector.x = A; \+ CUR.GS.projVector.x = A; \+ CUR.GS.dualVector.x = A; \+ \+ CUR.GS.freeVector.y = B; \+ CUR.GS.projVector.y = B; \+ CUR.GS.dualVector.y = B; \+ \+ COMPUTE_Funcs(); \+ }+++#define DO_SPVTCA \+ { \+ FT_Short A, B; \+ \+ \+ A = (FT_Short)( CUR.opcode & 1 ) << 14; \+ B = A ^ (FT_Short)0x4000; \+ \+ CUR.GS.projVector.x = A; \+ CUR.GS.dualVector.x = A; \+ \+ CUR.GS.projVector.y = B; \+ CUR.GS.dualVector.y = B; \+ \+ GUESS_VECTOR( freeVector ); \+ \+ COMPUTE_Funcs(); \+ }+++#define DO_SFVTCA \+ { \+ FT_Short A, B; \+ \+ \+ A = (FT_Short)( CUR.opcode & 1 ) << 14; \+ B = A ^ (FT_Short)0x4000; \+ \+ CUR.GS.freeVector.x = A; \+ CUR.GS.freeVector.y = B; \+ \+ GUESS_VECTOR( projVector ); \+ \+ COMPUTE_Funcs(); \+ }+++#define DO_SPVTL \+ if ( INS_SxVTL( (FT_UShort)args[1], \+ (FT_UShort)args[0], \+ CUR.opcode, \+ &CUR.GS.projVector ) == SUCCESS ) \+ { \+ CUR.GS.dualVector = CUR.GS.projVector; \+ GUESS_VECTOR( freeVector ); \+ COMPUTE_Funcs(); \+ }+++#define DO_SFVTL \+ if ( INS_SxVTL( (FT_UShort)args[1], \+ (FT_UShort)args[0], \+ CUR.opcode, \+ &CUR.GS.freeVector ) == SUCCESS ) \+ { \+ GUESS_VECTOR( projVector ); \+ COMPUTE_Funcs(); \+ }+++#define DO_SFVTPV \+ GUESS_VECTOR( projVector ); \+ CUR.GS.freeVector = CUR.GS.projVector; \+ COMPUTE_Funcs();+++#define DO_SPVFS \+ { \+ FT_Short S; \+ FT_Long X, Y; \+ \+ \+ /* Only use low 16bits, then sign extend */ \+ S = (FT_Short)args[1]; \+ Y = (FT_Long)S; \+ S = (FT_Short)args[0]; \+ X = (FT_Long)S; \+ \+ NORMalize( X, Y, &CUR.GS.projVector ); \+ \+ CUR.GS.dualVector = CUR.GS.projVector; \+ GUESS_VECTOR( freeVector ); \+ COMPUTE_Funcs(); \+ }+++#define DO_SFVFS \+ { \+ FT_Short S; \+ FT_Long X, Y; \+ \+ \+ /* Only use low 16bits, then sign extend */ \+ S = (FT_Short)args[1]; \+ Y = (FT_Long)S; \+ S = (FT_Short)args[0]; \+ X = S; \+ \+ NORMalize( X, Y, &CUR.GS.freeVector ); \+ GUESS_VECTOR( projVector ); \+ COMPUTE_Funcs(); \+ }+++#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING+#define DO_GPV \+ if ( CUR.face->unpatented_hinting ) \+ { \+ args[0] = CUR.GS.both_x_axis ? 0x4000 : 0; \+ args[1] = CUR.GS.both_x_axis ? 0 : 0x4000; \+ } \+ else \+ { \+ args[0] = CUR.GS.projVector.x; \+ args[1] = CUR.GS.projVector.y; \+ }+#else+#define DO_GPV \+ args[0] = CUR.GS.projVector.x; \+ args[1] = CUR.GS.projVector.y;+#endif+++#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING+#define DO_GFV \+ if ( CUR.face->unpatented_hinting ) \+ { \+ args[0] = CUR.GS.both_x_axis ? 0x4000 : 0; \+ args[1] = CUR.GS.both_x_axis ? 0 : 0x4000; \+ } \+ else \+ { \+ args[0] = CUR.GS.freeVector.x; \+ args[1] = CUR.GS.freeVector.y; \+ }+#else+#define DO_GFV \+ args[0] = CUR.GS.freeVector.x; \+ args[1] = CUR.GS.freeVector.y;+#endif+++#define DO_SRP0 \+ CUR.GS.rp0 = (FT_UShort)args[0];+++#define DO_SRP1 \+ CUR.GS.rp1 = (FT_UShort)args[0];+++#define DO_SRP2 \+ CUR.GS.rp2 = (FT_UShort)args[0];+++#define DO_RTHG \+ CUR.GS.round_state = TT_Round_To_Half_Grid; \+ CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;+++#define DO_RTG \+ CUR.GS.round_state = TT_Round_To_Grid; \+ CUR.func_round = (TT_Round_Func)Round_To_Grid;+++#define DO_RTDG \+ CUR.GS.round_state = TT_Round_To_Double_Grid; \+ CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;+++#define DO_RUTG \+ CUR.GS.round_state = TT_Round_Up_To_Grid; \+ CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;+++#define DO_RDTG \+ CUR.GS.round_state = TT_Round_Down_To_Grid; \+ CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;+++#define DO_ROFF \+ CUR.GS.round_state = TT_Round_Off; \+ CUR.func_round = (TT_Round_Func)Round_None;+++#define DO_SROUND \+ SET_SuperRound( 0x4000, args[0] ); \+ CUR.GS.round_state = TT_Round_Super; \+ CUR.func_round = (TT_Round_Func)Round_Super;+++#define DO_S45ROUND \+ SET_SuperRound( 0x2D41, args[0] ); \+ CUR.GS.round_state = TT_Round_Super_45; \+ CUR.func_round = (TT_Round_Func)Round_Super_45;+++#define DO_SLOOP \+ if ( args[0] < 0 ) \+ CUR.error = TT_Err_Bad_Argument; \+ else \+ CUR.GS.loop = args[0];+++#define DO_SMD \+ CUR.GS.minimum_distance = args[0];+++#define DO_SCVTCI \+ CUR.GS.control_value_cutin = (FT_F26Dot6)args[0];+++#define DO_SSWCI \+ CUR.GS.single_width_cutin = (FT_F26Dot6)args[0];+++ /* XXX: UNDOCUMENTED! or bug in the Windows engine? */+ /* */+ /* It seems that the value that is read here is */+ /* expressed in 16.16 format rather than in font */+ /* units. */+ /* */+#define DO_SSW \+ CUR.GS.single_width_value = (FT_F26Dot6)( args[0] >> 10 );+++#define DO_FLIPON \+ CUR.GS.auto_flip = TRUE;+++#define DO_FLIPOFF \+ CUR.GS.auto_flip = FALSE;+++#define DO_SDB \+ CUR.GS.delta_base = (FT_Short)args[0];+++#define DO_SDS \+ CUR.GS.delta_shift = (FT_Short)args[0];+++#define DO_MD /* nothing */+++#define DO_MPPEM \+ args[0] = CURRENT_Ppem();+++ /* Note: The pointSize should be irrelevant in a given font program; */+ /* we thus decide to return only the ppem. */+#if 0++#define DO_MPS \+ args[0] = CUR.metrics.pointSize;++#else++#define DO_MPS \+ args[0] = CURRENT_Ppem();++#endif /* 0 */+++#define DO_DUP \+ args[1] = args[0];+++#define DO_CLEAR \+ CUR.new_top = 0;+++#define DO_SWAP \+ { \+ FT_Long L; \+ \+ \+ L = args[0]; \+ args[0] = args[1]; \+ args[1] = L; \+ }+++#define DO_DEPTH \+ args[0] = CUR.top;+++#define DO_CINDEX \+ { \+ FT_Long L; \+ \+ \+ L = args[0]; \+ \+ if ( L <= 0 || L > CUR.args ) \+ CUR.error = TT_Err_Invalid_Reference; \+ else \+ args[0] = CUR.stack[CUR.args - L]; \+ }+++#define DO_JROT \+ if ( args[1] != 0 ) \+ { \+ CUR.IP += args[0]; \+ if ( CUR.IP < 0 ) \+ CUR.error = TT_Err_Bad_Argument; \+ CUR.step_ins = FALSE; \+ }+++#define DO_JMPR \+ CUR.IP += args[0]; \+ if ( CUR.IP < 0 ) \+ CUR.error = TT_Err_Bad_Argument; \+ CUR.step_ins = FALSE;+++#define DO_JROF \+ if ( args[1] == 0 ) \+ { \+ CUR.IP += args[0]; \+ if ( CUR.IP < 0 ) \+ CUR.error = TT_Err_Bad_Argument; \+ CUR.step_ins = FALSE; \+ }+++#define DO_LT \+ args[0] = ( args[0] < args[1] );+++#define DO_LTEQ \+ args[0] = ( args[0] <= args[1] );+++#define DO_GT \+ args[0] = ( args[0] > args[1] );+++#define DO_GTEQ \+ args[0] = ( args[0] >= args[1] );+++#define DO_EQ \+ args[0] = ( args[0] == args[1] );+++#define DO_NEQ \+ args[0] = ( args[0] != args[1] );+++#define DO_ODD \+ args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 64 );+++#define DO_EVEN \+ args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 0 );+++#define DO_AND \+ args[0] = ( args[0] && args[1] );+++#define DO_OR \+ args[0] = ( args[0] || args[1] );+++#define DO_NOT \+ args[0] = !args[0];+++#define DO_ADD \+ args[0] += args[1];+++#define DO_SUB \+ args[0] -= args[1];+++#define DO_DIV \+ if ( args[1] == 0 ) \+ CUR.error = TT_Err_Divide_By_Zero; \+ else \+ args[0] = TT_MULDIV_NO_ROUND( args[0], 64L, args[1] );+++#define DO_MUL \+ args[0] = TT_MULDIV( args[0], args[1], 64L );+++#define DO_ABS \+ args[0] = FT_ABS( args[0] );+++#define DO_NEG \+ args[0] = -args[0];+++#define DO_FLOOR \+ args[0] = FT_PIX_FLOOR( args[0] );+++#define DO_CEILING \+ args[0] = FT_PIX_CEIL( args[0] );+++#define DO_RS \+ { \+ FT_ULong I = (FT_ULong)args[0]; \+ \+ \+ if ( BOUNDSL( I, CUR.storeSize ) ) \+ { \+ if ( CUR.pedantic_hinting ) \+ { \+ ARRAY_BOUND_ERROR; \+ } \+ else \+ args[0] = 0; \+ } \+ else \+ args[0] = CUR.storage[I]; \+ }+++#define DO_WS \+ { \+ FT_ULong I = (FT_ULong)args[0]; \+ \+ \+ if ( BOUNDSL( I, CUR.storeSize ) ) \+ { \+ if ( CUR.pedantic_hinting ) \+ { \+ ARRAY_BOUND_ERROR; \+ } \+ } \+ else \+ CUR.storage[I] = args[1]; \+ }+++#define DO_RCVT \+ { \+ FT_ULong I = (FT_ULong)args[0]; \+ \+ \+ if ( BOUNDSL( I, CUR.cvtSize ) ) \+ { \+ if ( CUR.pedantic_hinting ) \+ { \+ ARRAY_BOUND_ERROR; \+ } \+ else \+ args[0] = 0; \+ } \+ else \+ args[0] = CUR_Func_read_cvt( I ); \+ }+++#define DO_WCVTP \+ { \+ FT_ULong I = (FT_ULong)args[0]; \+ \+ \+ if ( BOUNDSL( I, CUR.cvtSize ) ) \+ { \+ if ( CUR.pedantic_hinting ) \+ { \+ ARRAY_BOUND_ERROR; \+ } \+ } \+ else \+ CUR_Func_write_cvt( I, args[1] ); \+ }+++#define DO_WCVTF \+ { \+ FT_ULong I = (FT_ULong)args[0]; \+ \+ \+ if ( BOUNDSL( I, CUR.cvtSize ) ) \+ { \+ if ( CUR.pedantic_hinting ) \+ { \+ ARRAY_BOUND_ERROR; \+ } \+ } \+ else \+ CUR.cvt[I] = TT_MULFIX( args[1], CUR.tt_metrics.scale ); \+ }+++#define DO_DEBUG \+ CUR.error = TT_Err_Debug_OpCode;+++#define DO_ROUND \+ args[0] = CUR_Func_round( \+ args[0], \+ CUR.tt_metrics.compensations[CUR.opcode - 0x68] );+++#define DO_NROUND \+ args[0] = ROUND_None( args[0], \+ CUR.tt_metrics.compensations[CUR.opcode - 0x6C] );+++#define DO_MAX \+ if ( args[1] > args[0] ) \+ args[0] = args[1];+++#define DO_MIN \+ if ( args[1] < args[0] ) \+ args[0] = args[1];+++#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH+++#undef ARRAY_BOUND_ERROR+#define ARRAY_BOUND_ERROR \+ { \+ CUR.error = TT_Err_Invalid_Reference; \+ return; \+ }+++ /*************************************************************************/+ /* */+ /* SVTCA[a]: Set (F and P) Vectors to Coordinate Axis */+ /* Opcode range: 0x00-0x01 */+ /* Stack: --> */+ /* */+ static void+ Ins_SVTCA( INS_ARG )+ {+ DO_SVTCA+ }+++ /*************************************************************************/+ /* */+ /* SPVTCA[a]: Set PVector to Coordinate Axis */+ /* Opcode range: 0x02-0x03 */+ /* Stack: --> */+ /* */+ static void+ Ins_SPVTCA( INS_ARG )+ {+ DO_SPVTCA+ }+++ /*************************************************************************/+ /* */+ /* SFVTCA[a]: Set FVector to Coordinate Axis */+ /* Opcode range: 0x04-0x05 */+ /* Stack: --> */+ /* */+ static void+ Ins_SFVTCA( INS_ARG )+ {+ DO_SFVTCA+ }+++ /*************************************************************************/+ /* */+ /* SPVTL[a]: Set PVector To Line */+ /* Opcode range: 0x06-0x07 */+ /* Stack: uint32 uint32 --> */+ /* */+ static void+ Ins_SPVTL( INS_ARG )+ {+ DO_SPVTL+ }+++ /*************************************************************************/+ /* */+ /* SFVTL[a]: Set FVector To Line */+ /* Opcode range: 0x08-0x09 */+ /* Stack: uint32 uint32 --> */+ /* */+ static void+ Ins_SFVTL( INS_ARG )+ {+ DO_SFVTL+ }+++ /*************************************************************************/+ /* */+ /* SFVTPV[]: Set FVector To PVector */+ /* Opcode range: 0x0E */+ /* Stack: --> */+ /* */+ static void+ Ins_SFVTPV( INS_ARG )+ {+ DO_SFVTPV+ }+++ /*************************************************************************/+ /* */+ /* SPVFS[]: Set PVector From Stack */+ /* Opcode range: 0x0A */+ /* Stack: f2.14 f2.14 --> */+ /* */+ static void+ Ins_SPVFS( INS_ARG )+ {+ DO_SPVFS+ }+++ /*************************************************************************/+ /* */+ /* SFVFS[]: Set FVector From Stack */+ /* Opcode range: 0x0B */+ /* Stack: f2.14 f2.14 --> */+ /* */+ static void+ Ins_SFVFS( INS_ARG )+ {+ DO_SFVFS+ }+++ /*************************************************************************/+ /* */+ /* GPV[]: Get Projection Vector */+ /* Opcode range: 0x0C */+ /* Stack: ef2.14 --> ef2.14 */+ /* */+ static void+ Ins_GPV( INS_ARG )+ {+ DO_GPV+ }+++ /*************************************************************************/+ /* GFV[]: Get Freedom Vector */+ /* Opcode range: 0x0D */+ /* Stack: ef2.14 --> ef2.14 */+ /* */+ static void+ Ins_GFV( INS_ARG )+ {+ DO_GFV+ }+++ /*************************************************************************/+ /* */+ /* SRP0[]: Set Reference Point 0 */+ /* Opcode range: 0x10 */+ /* Stack: uint32 --> */+ /* */+ static void+ Ins_SRP0( INS_ARG )+ {+ DO_SRP0+ }+++ /*************************************************************************/+ /* */+ /* SRP1[]: Set Reference Point 1 */+ /* Opcode range: 0x11 */+ /* Stack: uint32 --> */+ /* */+ static void+ Ins_SRP1( INS_ARG )+ {+ DO_SRP1+ }+++ /*************************************************************************/+ /* */+ /* SRP2[]: Set Reference Point 2 */+ /* Opcode range: 0x12 */+ /* Stack: uint32 --> */+ /* */+ static void+ Ins_SRP2( INS_ARG )+ {+ DO_SRP2+ }+++ /*************************************************************************/+ /* */+ /* RTHG[]: Round To Half Grid */+ /* Opcode range: 0x19 */+ /* Stack: --> */+ /* */+ static void+ Ins_RTHG( INS_ARG )+ {+ DO_RTHG+ }+++ /*************************************************************************/+ /* */+ /* RTG[]: Round To Grid */+ /* Opcode range: 0x18 */+ /* Stack: --> */+ /* */+ static void+ Ins_RTG( INS_ARG )+ {+ DO_RTG+ }+++ /*************************************************************************/+ /* RTDG[]: Round To Double Grid */+ /* Opcode range: 0x3D */+ /* Stack: --> */+ /* */+ static void+ Ins_RTDG( INS_ARG )+ {+ DO_RTDG+ }+++ /*************************************************************************/+ /* RUTG[]: Round Up To Grid */+ /* Opcode range: 0x7C */+ /* Stack: --> */+ /* */+ static void+ Ins_RUTG( INS_ARG )+ {+ DO_RUTG+ }+++ /*************************************************************************/+ /* */+ /* RDTG[]: Round Down To Grid */+ /* Opcode range: 0x7D */+ /* Stack: --> */+ /* */+ static void+ Ins_RDTG( INS_ARG )+ {+ DO_RDTG+ }+++ /*************************************************************************/+ /* */+ /* ROFF[]: Round OFF */+ /* Opcode range: 0x7A */+ /* Stack: --> */+ /* */+ static void+ Ins_ROFF( INS_ARG )+ {+ DO_ROFF+ }+++ /*************************************************************************/+ /* */+ /* SROUND[]: Super ROUND */+ /* Opcode range: 0x76 */+ /* Stack: Eint8 --> */+ /* */+ static void+ Ins_SROUND( INS_ARG )+ {+ DO_SROUND+ }+++ /*************************************************************************/+ /* */+ /* S45ROUND[]: Super ROUND 45 degrees */+ /* Opcode range: 0x77 */+ /* Stack: uint32 --> */+ /* */+ static void+ Ins_S45ROUND( INS_ARG )+ {+ DO_S45ROUND+ }+++ /*************************************************************************/+ /* */+ /* SLOOP[]: Set LOOP variable */+ /* Opcode range: 0x17 */+ /* Stack: int32? --> */+ /* */+ static void+ Ins_SLOOP( INS_ARG )+ {+ DO_SLOOP+ }+++ /*************************************************************************/+ /* */+ /* SMD[]: Set Minimum Distance */+ /* Opcode range: 0x1A */+ /* Stack: f26.6 --> */+ /* */+ static void+ Ins_SMD( INS_ARG )+ {+ DO_SMD+ }+++ /*************************************************************************/+ /* */+ /* SCVTCI[]: Set Control Value Table Cut In */+ /* Opcode range: 0x1D */+ /* Stack: f26.6 --> */+ /* */+ static void+ Ins_SCVTCI( INS_ARG )+ {+ DO_SCVTCI+ }+++ /*************************************************************************/+ /* */+ /* SSWCI[]: Set Single Width Cut In */+ /* Opcode range: 0x1E */+ /* Stack: f26.6 --> */+ /* */+ static void+ Ins_SSWCI( INS_ARG )+ {+ DO_SSWCI+ }+++ /*************************************************************************/+ /* */+ /* SSW[]: Set Single Width */+ /* Opcode range: 0x1F */+ /* Stack: int32? --> */+ /* */+ static void+ Ins_SSW( INS_ARG )+ {+ DO_SSW+ }+++ /*************************************************************************/+ /* */+ /* FLIPON[]: Set auto-FLIP to ON */+ /* Opcode range: 0x4D */+ /* Stack: --> */+ /* */+ static void+ Ins_FLIPON( INS_ARG )+ {+ DO_FLIPON+ }+++ /*************************************************************************/+ /* */+ /* FLIPOFF[]: Set auto-FLIP to OFF */+ /* Opcode range: 0x4E */+ /* Stack: --> */+ /* */+ static void+ Ins_FLIPOFF( INS_ARG )+ {+ DO_FLIPOFF+ }+++ /*************************************************************************/+ /* */+ /* SANGW[]: Set ANGle Weight */+ /* Opcode range: 0x7E */+ /* Stack: uint32 --> */+ /* */+ static void+ Ins_SANGW( INS_ARG )+ {+ /* instruction not supported anymore */+ }+++ /*************************************************************************/+ /* */+ /* SDB[]: Set Delta Base */+ /* Opcode range: 0x5E */+ /* Stack: uint32 --> */+ /* */+ static void+ Ins_SDB( INS_ARG )+ {+ DO_SDB+ }+++ /*************************************************************************/+ /* */+ /* SDS[]: Set Delta Shift */+ /* Opcode range: 0x5F */+ /* Stack: uint32 --> */+ /* */+ static void+ Ins_SDS( INS_ARG )+ {+ DO_SDS+ }+++ /*************************************************************************/+ /* */+ /* MPPEM[]: Measure Pixel Per EM */+ /* Opcode range: 0x4B */+ /* Stack: --> Euint16 */+ /* */+ static void+ Ins_MPPEM( INS_ARG )+ {+ DO_MPPEM+ }+++ /*************************************************************************/+ /* */+ /* MPS[]: Measure Point Size */+ /* Opcode range: 0x4C */+ /* Stack: --> Euint16 */+ /* */+ static void+ Ins_MPS( INS_ARG )+ {+ DO_MPS+ }+++ /*************************************************************************/+ /* */+ /* DUP[]: DUPlicate the top stack's element */+ /* Opcode range: 0x20 */+ /* Stack: StkElt --> StkElt StkElt */+ /* */+ static void+ Ins_DUP( INS_ARG )+ {+ DO_DUP+ }+++ /*************************************************************************/+ /* */+ /* POP[]: POP the stack's top element */+ /* Opcode range: 0x21 */+ /* Stack: StkElt --> */+ /* */+ static void+ Ins_POP( INS_ARG )+ {+ /* nothing to do */+ }+++ /*************************************************************************/+ /* */+ /* CLEAR[]: CLEAR the entire stack */+ /* Opcode range: 0x22 */+ /* Stack: StkElt... --> */+ /* */+ static void+ Ins_CLEAR( INS_ARG )+ {+ DO_CLEAR+ }+++ /*************************************************************************/+ /* */+ /* SWAP[]: SWAP the stack's top two elements */+ /* Opcode range: 0x23 */+ /* Stack: 2 * StkElt --> 2 * StkElt */+ /* */+ static void+ Ins_SWAP( INS_ARG )+ {+ DO_SWAP+ }+++ /*************************************************************************/+ /* */+ /* DEPTH[]: return the stack DEPTH */+ /* Opcode range: 0x24 */+ /* Stack: --> uint32 */+ /* */+ static void+ Ins_DEPTH( INS_ARG )+ {+ DO_DEPTH+ }+++ /*************************************************************************/+ /* */+ /* CINDEX[]: Copy INDEXed element */+ /* Opcode range: 0x25 */+ /* Stack: int32 --> StkElt */+ /* */+ static void+ Ins_CINDEX( INS_ARG )+ {+ DO_CINDEX+ }+++ /*************************************************************************/+ /* */+ /* EIF[]: End IF */+ /* Opcode range: 0x59 */+ /* Stack: --> */+ /* */+ static void+ Ins_EIF( INS_ARG )+ {+ /* nothing to do */+ }+++ /*************************************************************************/+ /* */+ /* JROT[]: Jump Relative On True */+ /* Opcode range: 0x78 */+ /* Stack: StkElt int32 --> */+ /* */+ static void+ Ins_JROT( INS_ARG )+ {+ DO_JROT+ }+++ /*************************************************************************/+ /* */+ /* JMPR[]: JuMP Relative */+ /* Opcode range: 0x1C */+ /* Stack: int32 --> */+ /* */+ static void+ Ins_JMPR( INS_ARG )+ {+ DO_JMPR+ }+++ /*************************************************************************/+ /* */+ /* JROF[]: Jump Relative On False */+ /* Opcode range: 0x79 */+ /* Stack: StkElt int32 --> */+ /* */+ static void+ Ins_JROF( INS_ARG )+ {+ DO_JROF+ }+++ /*************************************************************************/+ /* */+ /* LT[]: Less Than */+ /* Opcode range: 0x50 */+ /* Stack: int32? int32? --> bool */+ /* */+ static void+ Ins_LT( INS_ARG )+ {+ DO_LT+ }+++ /*************************************************************************/+ /* */+ /* LTEQ[]: Less Than or EQual */+ /* Opcode range: 0x51 */+ /* Stack: int32? int32? --> bool */+ /* */+ static void+ Ins_LTEQ( INS_ARG )+ {+ DO_LTEQ+ }+++ /*************************************************************************/+ /* */+ /* GT[]: Greater Than */+ /* Opcode range: 0x52 */+ /* Stack: int32? int32? --> bool */+ /* */+ static void+ Ins_GT( INS_ARG )+ {+ DO_GT+ }+++ /*************************************************************************/+ /* */+ /* GTEQ[]: Greater Than or EQual */+ /* Opcode range: 0x53 */+ /* Stack: int32? int32? --> bool */+ /* */+ static void+ Ins_GTEQ( INS_ARG )+ {+ DO_GTEQ+ }+++ /*************************************************************************/+ /* */+ /* EQ[]: EQual */+ /* Opcode range: 0x54 */+ /* Stack: StkElt StkElt --> bool */+ /* */+ static void+ Ins_EQ( INS_ARG )+ {+ DO_EQ+ }+++ /*************************************************************************/+ /* */+ /* NEQ[]: Not EQual */+ /* Opcode range: 0x55 */+ /* Stack: StkElt StkElt --> bool */+ /* */+ static void+ Ins_NEQ( INS_ARG )+ {+ DO_NEQ+ }+++ /*************************************************************************/+ /* */+ /* ODD[]: Is ODD */+ /* Opcode range: 0x56 */+ /* Stack: f26.6 --> bool */+ /* */+ static void+ Ins_ODD( INS_ARG )+ {+ DO_ODD+ }+++ /*************************************************************************/+ /* */+ /* EVEN[]: Is EVEN */+ /* Opcode range: 0x57 */+ /* Stack: f26.6 --> bool */+ /* */+ static void+ Ins_EVEN( INS_ARG )+ {+ DO_EVEN+ }+++ /*************************************************************************/+ /* */+ /* AND[]: logical AND */+ /* Opcode range: 0x5A */+ /* Stack: uint32 uint32 --> uint32 */+ /* */+ static void+ Ins_AND( INS_ARG )+ {+ DO_AND+ }+++ /*************************************************************************/+ /* */+ /* OR[]: logical OR */+ /* Opcode range: 0x5B */+ /* Stack: uint32 uint32 --> uint32 */+ /* */+ static void+ Ins_OR( INS_ARG )+ {+ DO_OR+ }+++ /*************************************************************************/+ /* */+ /* NOT[]: logical NOT */+ /* Opcode range: 0x5C */+ /* Stack: StkElt --> uint32 */+ /* */+ static void+ Ins_NOT( INS_ARG )+ {+ DO_NOT+ }+++ /*************************************************************************/+ /* */+ /* ADD[]: ADD */+ /* Opcode range: 0x60 */+ /* Stack: f26.6 f26.6 --> f26.6 */+ /* */+ static void+ Ins_ADD( INS_ARG )+ {+ DO_ADD+ }+++ /*************************************************************************/+ /* */+ /* SUB[]: SUBtract */+ /* Opcode range: 0x61 */+ /* Stack: f26.6 f26.6 --> f26.6 */+ /* */+ static void+ Ins_SUB( INS_ARG )+ {+ DO_SUB+ }+++ /*************************************************************************/+ /* */+ /* DIV[]: DIVide */+ /* Opcode range: 0x62 */+ /* Stack: f26.6 f26.6 --> f26.6 */+ /* */+ static void+ Ins_DIV( INS_ARG )+ {+ DO_DIV+ }+++ /*************************************************************************/+ /* */+ /* MUL[]: MULtiply */+ /* Opcode range: 0x63 */+ /* Stack: f26.6 f26.6 --> f26.6 */+ /* */+ static void+ Ins_MUL( INS_ARG )+ {+ DO_MUL+ }+++ /*************************************************************************/+ /* */+ /* ABS[]: ABSolute value */+ /* Opcode range: 0x64 */+ /* Stack: f26.6 --> f26.6 */+ /* */+ static void+ Ins_ABS( INS_ARG )+ {+ DO_ABS+ }+++ /*************************************************************************/+ /* */+ /* NEG[]: NEGate */+ /* Opcode range: 0x65 */+ /* Stack: f26.6 --> f26.6 */+ /* */+ static void+ Ins_NEG( INS_ARG )+ {+ DO_NEG+ }+++ /*************************************************************************/+ /* */+ /* FLOOR[]: FLOOR */+ /* Opcode range: 0x66 */+ /* Stack: f26.6 --> f26.6 */+ /* */+ static void+ Ins_FLOOR( INS_ARG )+ {+ DO_FLOOR+ }+++ /*************************************************************************/+ /* */+ /* CEILING[]: CEILING */+ /* Opcode range: 0x67 */+ /* Stack: f26.6 --> f26.6 */+ /* */+ static void+ Ins_CEILING( INS_ARG )+ {+ DO_CEILING+ }+++ /*************************************************************************/+ /* */+ /* RS[]: Read Store */+ /* Opcode range: 0x43 */+ /* Stack: uint32 --> uint32 */+ /* */+ static void+ Ins_RS( INS_ARG )+ {+ DO_RS+ }+++ /*************************************************************************/+ /* */+ /* WS[]: Write Store */+ /* Opcode range: 0x42 */+ /* Stack: uint32 uint32 --> */+ /* */+ static void+ Ins_WS( INS_ARG )+ {+ DO_WS+ }+++ /*************************************************************************/+ /* */+ /* WCVTP[]: Write CVT in Pixel units */+ /* Opcode range: 0x44 */+ /* Stack: f26.6 uint32 --> */+ /* */+ static void+ Ins_WCVTP( INS_ARG )+ {+ DO_WCVTP+ }+++ /*************************************************************************/+ /* */+ /* WCVTF[]: Write CVT in Funits */+ /* Opcode range: 0x70 */+ /* Stack: uint32 uint32 --> */+ /* */+ static void+ Ins_WCVTF( INS_ARG )+ {+ DO_WCVTF+ }+++ /*************************************************************************/+ /* */+ /* RCVT[]: Read CVT */+ /* Opcode range: 0x45 */+ /* Stack: uint32 --> f26.6 */+ /* */+ static void+ Ins_RCVT( INS_ARG )+ {+ DO_RCVT+ }+++ /*************************************************************************/+ /* */+ /* AA[]: Adjust Angle */+ /* Opcode range: 0x7F */+ /* Stack: uint32 --> */+ /* */+ static void+ Ins_AA( INS_ARG )+ {+ /* intentionally no longer supported */+ }+++ /*************************************************************************/+ /* */+ /* DEBUG[]: DEBUG. Unsupported. */+ /* Opcode range: 0x4F */+ /* Stack: uint32 --> */+ /* */+ /* Note: The original instruction pops a value from the stack. */+ /* */+ static void+ Ins_DEBUG( INS_ARG )+ {+ DO_DEBUG+ }+++ /*************************************************************************/+ /* */+ /* ROUND[ab]: ROUND value */+ /* Opcode range: 0x68-0x6B */+ /* Stack: f26.6 --> f26.6 */+ /* */+ static void+ Ins_ROUND( INS_ARG )+ {+ DO_ROUND+ }+++ /*************************************************************************/+ /* */+ /* NROUND[ab]: No ROUNDing of value */+ /* Opcode range: 0x6C-0x6F */+ /* Stack: f26.6 --> f26.6 */+ /* */+ static void+ Ins_NROUND( INS_ARG )+ {+ DO_NROUND+ }+++ /*************************************************************************/+ /* */+ /* MAX[]: MAXimum */+ /* Opcode range: 0x68 */+ /* Stack: int32? int32? --> int32 */+ /* */+ static void+ Ins_MAX( INS_ARG )+ {+ DO_MAX+ }+++ /*************************************************************************/+ /* */+ /* MIN[]: MINimum */+ /* Opcode range: 0x69 */+ /* Stack: int32? int32? --> int32 */+ /* */+ static void+ Ins_MIN( INS_ARG )+ {+ DO_MIN+ }+++#endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */+++ /*************************************************************************/+ /* */+ /* The following functions are called as is within the switch statement. */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* MINDEX[]: Move INDEXed element */+ /* Opcode range: 0x26 */+ /* Stack: int32? --> StkElt */+ /* */+ static void+ Ins_MINDEX( INS_ARG )+ {+ FT_Long L, K;+++ L = args[0];++ if ( L <= 0 || L > CUR.args )+ {+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }++ K = CUR.stack[CUR.args - L];++ FT_ARRAY_MOVE( &CUR.stack[CUR.args - L ],+ &CUR.stack[CUR.args - L + 1],+ ( L - 1 ) );++ CUR.stack[CUR.args - 1] = K;+ }+++ /*************************************************************************/+ /* */+ /* ROLL[]: ROLL top three elements */+ /* Opcode range: 0x8A */+ /* Stack: 3 * StkElt --> 3 * StkElt */+ /* */+ static void+ Ins_ROLL( INS_ARG )+ {+ FT_Long A, B, C;++ FT_UNUSED_EXEC;+++ A = args[2];+ B = args[1];+ C = args[0];++ args[2] = C;+ args[1] = A;+ args[0] = B;+ }+++ /*************************************************************************/+ /* */+ /* MANAGING THE FLOW OF CONTROL */+ /* */+ /* Instructions appear in the specification's order. */+ /* */+ /*************************************************************************/+++ static FT_Bool+ SkipCode( EXEC_OP )+ {+ CUR.IP += CUR.length;++ if ( CUR.IP < CUR.codeSize )+ {+ CUR.opcode = CUR.code[CUR.IP];++ CUR.length = opcode_length[CUR.opcode];+ if ( CUR.length < 0 )+ {+ if ( CUR.IP + 1 > CUR.codeSize )+ goto Fail_Overflow;+ CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];+ }++ if ( CUR.IP + CUR.length <= CUR.codeSize )+ return SUCCESS;+ }++ Fail_Overflow:+ CUR.error = TT_Err_Code_Overflow;+ return FAILURE;+ }+++ /*************************************************************************/+ /* */+ /* IF[]: IF test */+ /* Opcode range: 0x58 */+ /* Stack: StkElt --> */+ /* */+ static void+ Ins_IF( INS_ARG )+ {+ FT_Int nIfs;+ FT_Bool Out;+++ if ( args[0] != 0 )+ return;++ nIfs = 1;+ Out = 0;++ do+ {+ if ( SKIP_Code() == FAILURE )+ return;++ switch ( CUR.opcode )+ {+ case 0x58: /* IF */+ nIfs++;+ break;++ case 0x1B: /* ELSE */+ Out = FT_BOOL( nIfs == 1 );+ break;++ case 0x59: /* EIF */+ nIfs--;+ Out = FT_BOOL( nIfs == 0 );+ break;+ }+ } while ( Out == 0 );+ }+++ /*************************************************************************/+ /* */+ /* ELSE[]: ELSE */+ /* Opcode range: 0x1B */+ /* Stack: --> */+ /* */+ static void+ Ins_ELSE( INS_ARG )+ {+ FT_Int nIfs;++ FT_UNUSED_ARG;+++ nIfs = 1;++ do+ {+ if ( SKIP_Code() == FAILURE )+ return;++ switch ( CUR.opcode )+ {+ case 0x58: /* IF */+ nIfs++;+ break;++ case 0x59: /* EIF */+ nIfs--;+ break;+ }+ } while ( nIfs != 0 );+ }+++ /*************************************************************************/+ /* */+ /* DEFINING AND USING FUNCTIONS AND INSTRUCTIONS */+ /* */+ /* Instructions appear in the specification's order. */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* FDEF[]: Function DEFinition */+ /* Opcode range: 0x2C */+ /* Stack: uint32 --> */+ /* */+ static void+ Ins_FDEF( INS_ARG )+ {+ FT_ULong n;+ TT_DefRecord* rec;+ TT_DefRecord* limit;+++ /* some font programs are broken enough to redefine functions! */+ /* We will then parse the current table. */++ rec = CUR.FDefs;+ limit = rec + CUR.numFDefs;+ n = args[0];++ for ( ; rec < limit; rec++ )+ {+ if ( rec->opc == n )+ break;+ }++ if ( rec == limit )+ {+ /* check that there is enough room for new functions */+ if ( CUR.numFDefs >= CUR.maxFDefs )+ {+ CUR.error = TT_Err_Too_Many_Function_Defs;+ return;+ }+ CUR.numFDefs++;+ }++ /* Although FDEF takes unsigned 32-bit integer, */+ /* func # must be within unsigned 16-bit integer */+ if ( n > 0xFFFFU )+ {+ CUR.error = TT_Err_Too_Many_Function_Defs;+ return;+ }++ rec->range = CUR.curRange;+ rec->opc = (FT_UInt16)n;+ rec->start = CUR.IP + 1;+ rec->active = TRUE;++ if ( n > CUR.maxFunc )+ CUR.maxFunc = (FT_UInt16)n;++ /* Now skip the whole function definition. */+ /* We don't allow nested IDEFS & FDEFs. */++ while ( SKIP_Code() == SUCCESS )+ {+ switch ( CUR.opcode )+ {+ case 0x89: /* IDEF */+ case 0x2C: /* FDEF */+ CUR.error = TT_Err_Nested_DEFS;+ return;++ case 0x2D: /* ENDF */+ return;+ }+ }+ }+++ /*************************************************************************/+ /* */+ /* ENDF[]: END Function definition */+ /* Opcode range: 0x2D */+ /* Stack: --> */+ /* */+ static void+ Ins_ENDF( INS_ARG )+ {+ TT_CallRec* pRec;++ FT_UNUSED_ARG;+++ if ( CUR.callTop <= 0 ) /* We encountered an ENDF without a call */+ {+ CUR.error = TT_Err_ENDF_In_Exec_Stream;+ return;+ }++ CUR.callTop--;++ pRec = &CUR.callStack[CUR.callTop];++ pRec->Cur_Count--;++ CUR.step_ins = FALSE;++ if ( pRec->Cur_Count > 0 )+ {+ CUR.callTop++;+ CUR.IP = pRec->Cur_Restart;+ }+ else+ /* Loop through the current function */+ INS_Goto_CodeRange( pRec->Caller_Range,+ pRec->Caller_IP );++ /* Exit the current call frame. */++ /* NOTE: If the last instruction of a program is a */+ /* CALL or LOOPCALL, the return address is */+ /* always out of the code range. This is a */+ /* valid address, and it is why we do not test */+ /* the result of Ins_Goto_CodeRange() here! */+ }+++ /*************************************************************************/+ /* */+ /* CALL[]: CALL function */+ /* Opcode range: 0x2B */+ /* Stack: uint32? --> */+ /* */+ static void+ Ins_CALL( INS_ARG )+ {+ FT_ULong F;+ TT_CallRec* pCrec;+ TT_DefRecord* def;+++ /* first of all, check the index */++ F = args[0];+ if ( BOUNDSL( F, CUR.maxFunc + 1 ) )+ goto Fail;++ /* Except for some old Apple fonts, all functions in a TrueType */+ /* font are defined in increasing order, starting from 0. This */+ /* means that we normally have */+ /* */+ /* CUR.maxFunc+1 == CUR.numFDefs */+ /* CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc */+ /* */+ /* If this isn't true, we need to look up the function table. */++ def = CUR.FDefs + F;+ if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )+ {+ /* look up the FDefs table */+ TT_DefRecord* limit;+++ def = CUR.FDefs;+ limit = def + CUR.numFDefs;++ while ( def < limit && def->opc != F )+ def++;++ if ( def == limit )+ goto Fail;+ }++ /* check that the function is active */+ if ( !def->active )+ goto Fail;++ /* check the call stack */+ if ( CUR.callTop >= CUR.callSize )+ {+ CUR.error = TT_Err_Stack_Overflow;+ return;+ }++ pCrec = CUR.callStack + CUR.callTop;++ pCrec->Caller_Range = CUR.curRange;+ pCrec->Caller_IP = CUR.IP + 1;+ pCrec->Cur_Count = 1;+ pCrec->Cur_Restart = def->start;++ CUR.callTop++;++ INS_Goto_CodeRange( def->range,+ def->start );++ CUR.step_ins = FALSE;+ return;++ Fail:+ CUR.error = TT_Err_Invalid_Reference;+ }+++ /*************************************************************************/+ /* */+ /* LOOPCALL[]: LOOP and CALL function */+ /* Opcode range: 0x2A */+ /* Stack: uint32? Eint16? --> */+ /* */+ static void+ Ins_LOOPCALL( INS_ARG )+ {+ FT_ULong F;+ TT_CallRec* pCrec;+ TT_DefRecord* def;+++ /* first of all, check the index */+ F = args[1];+ if ( BOUNDSL( F, CUR.maxFunc + 1 ) )+ goto Fail;++ /* Except for some old Apple fonts, all functions in a TrueType */+ /* font are defined in increasing order, starting from 0. This */+ /* means that we normally have */+ /* */+ /* CUR.maxFunc+1 == CUR.numFDefs */+ /* CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc */+ /* */+ /* If this isn't true, we need to look up the function table. */++ def = CUR.FDefs + F;+ if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )+ {+ /* look up the FDefs table */+ TT_DefRecord* limit;+++ def = CUR.FDefs;+ limit = def + CUR.numFDefs;++ while ( def < limit && def->opc != F )+ def++;++ if ( def == limit )+ goto Fail;+ }++ /* check that the function is active */+ if ( !def->active )+ goto Fail;++ /* check stack */+ if ( CUR.callTop >= CUR.callSize )+ {+ CUR.error = TT_Err_Stack_Overflow;+ return;+ }++ if ( args[0] > 0 )+ {+ pCrec = CUR.callStack + CUR.callTop;++ pCrec->Caller_Range = CUR.curRange;+ pCrec->Caller_IP = CUR.IP + 1;+ pCrec->Cur_Count = (FT_Int)args[0];+ pCrec->Cur_Restart = def->start;++ CUR.callTop++;++ INS_Goto_CodeRange( def->range, def->start );++ CUR.step_ins = FALSE;+ }+ return;++ Fail:+ CUR.error = TT_Err_Invalid_Reference;+ }+++ /*************************************************************************/+ /* */+ /* IDEF[]: Instruction DEFinition */+ /* Opcode range: 0x89 */+ /* Stack: Eint8 --> */+ /* */+ static void+ Ins_IDEF( INS_ARG )+ {+ TT_DefRecord* def;+ TT_DefRecord* limit;+++ /* First of all, look for the same function in our table */++ def = CUR.IDefs;+ limit = def + CUR.numIDefs;++ for ( ; def < limit; def++ )+ if ( def->opc == (FT_ULong)args[0] )+ break;++ if ( def == limit )+ {+ /* check that there is enough room for a new instruction */+ if ( CUR.numIDefs >= CUR.maxIDefs )+ {+ CUR.error = TT_Err_Too_Many_Instruction_Defs;+ return;+ }+ CUR.numIDefs++;+ }++ /* opcode must be unsigned 8-bit integer */+ if ( 0 > args[0] || args[0] > 0x00FF )+ {+ CUR.error = TT_Err_Too_Many_Instruction_Defs;+ return;+ }++ def->opc = (FT_Byte)args[0];+ def->start = CUR.IP + 1;+ def->range = CUR.curRange;+ def->active = TRUE;++ if ( (FT_ULong)args[0] > CUR.maxIns )+ CUR.maxIns = (FT_Byte)args[0];++ /* Now skip the whole function definition. */+ /* We don't allow nested IDEFs & FDEFs. */++ while ( SKIP_Code() == SUCCESS )+ {+ switch ( CUR.opcode )+ {+ case 0x89: /* IDEF */+ case 0x2C: /* FDEF */+ CUR.error = TT_Err_Nested_DEFS;+ return;+ case 0x2D: /* ENDF */+ return;+ }+ }+ }+++ /*************************************************************************/+ /* */+ /* PUSHING DATA ONTO THE INTERPRETER STACK */+ /* */+ /* Instructions appear in the specification's order. */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* NPUSHB[]: PUSH N Bytes */+ /* Opcode range: 0x40 */+ /* Stack: --> uint32... */+ /* */+ static void+ Ins_NPUSHB( INS_ARG )+ {+ FT_UShort L, K;+++ L = (FT_UShort)CUR.code[CUR.IP + 1];++ if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )+ {+ CUR.error = TT_Err_Stack_Overflow;+ return;+ }++ for ( K = 1; K <= L; K++ )+ args[K - 1] = CUR.code[CUR.IP + K + 1];++ CUR.new_top += L;+ }+++ /*************************************************************************/+ /* */+ /* NPUSHW[]: PUSH N Words */+ /* Opcode range: 0x41 */+ /* Stack: --> int32... */+ /* */+ static void+ Ins_NPUSHW( INS_ARG )+ {+ FT_UShort L, K;+++ L = (FT_UShort)CUR.code[CUR.IP + 1];++ if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )+ {+ CUR.error = TT_Err_Stack_Overflow;+ return;+ }++ CUR.IP += 2;++ for ( K = 0; K < L; K++ )+ args[K] = GET_ShortIns();++ CUR.step_ins = FALSE;+ CUR.new_top += L;+ }+++ /*************************************************************************/+ /* */+ /* PUSHB[abc]: PUSH Bytes */+ /* Opcode range: 0xB0-0xB7 */+ /* Stack: --> uint32... */+ /* */+ static void+ Ins_PUSHB( INS_ARG )+ {+ FT_UShort L, K;+++ L = (FT_UShort)( CUR.opcode - 0xB0 + 1 );++ if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )+ {+ CUR.error = TT_Err_Stack_Overflow;+ return;+ }++ for ( K = 1; K <= L; K++ )+ args[K - 1] = CUR.code[CUR.IP + K];+ }+++ /*************************************************************************/+ /* */+ /* PUSHW[abc]: PUSH Words */+ /* Opcode range: 0xB8-0xBF */+ /* Stack: --> int32... */+ /* */+ static void+ Ins_PUSHW( INS_ARG )+ {+ FT_UShort L, K;+++ L = (FT_UShort)( CUR.opcode - 0xB8 + 1 );++ if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )+ {+ CUR.error = TT_Err_Stack_Overflow;+ return;+ }++ CUR.IP++;++ for ( K = 0; K < L; K++ )+ args[K] = GET_ShortIns();++ CUR.step_ins = FALSE;+ }+++ /*************************************************************************/+ /* */+ /* MANAGING THE GRAPHICS STATE */+ /* */+ /* Instructions appear in the specs' order. */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* GC[a]: Get Coordinate projected onto */+ /* Opcode range: 0x46-0x47 */+ /* Stack: uint32 --> f26.6 */+ /* */+ /* BULLSHIT: Measures from the original glyph must be taken along the */+ /* dual projection vector! */+ /* */+ static void+ Ins_GC( INS_ARG )+ {+ FT_ULong L;+ FT_F26Dot6 R;+++ L = (FT_ULong)args[0];++ if ( BOUNDSL( L, CUR.zp2.n_points ) )+ {+ if ( CUR.pedantic_hinting )+ {+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }+ else+ R = 0;+ }+ else+ {+ if ( CUR.opcode & 1 )+ R = CUR_fast_dualproj( &CUR.zp2.org[L] );+ else+ R = CUR_fast_project( &CUR.zp2.cur[L] );+ }++ args[0] = R;+ }+++ /*************************************************************************/+ /* */+ /* SCFS[]: Set Coordinate From Stack */+ /* Opcode range: 0x48 */+ /* Stack: f26.6 uint32 --> */+ /* */+ /* Formula: */+ /* */+ /* OA := OA + ( value - OA.p )/( f.p ) * f */+ /* */+ static void+ Ins_SCFS( INS_ARG )+ {+ FT_Long K;+ FT_UShort L;+++ L = (FT_UShort)args[0];++ if ( BOUNDS( L, CUR.zp2.n_points ) )+ {+ if ( CUR.pedantic_hinting )+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }++ K = CUR_fast_project( &CUR.zp2.cur[L] );++ CUR_Func_move( &CUR.zp2, L, args[1] - K );++ /* not part of the specs, but here for safety */++ if ( CUR.GS.gep2 == 0 )+ CUR.zp2.org[L] = CUR.zp2.cur[L];+ }+++ /*************************************************************************/+ /* */+ /* MD[a]: Measure Distance */+ /* Opcode range: 0x49-0x4A */+ /* Stack: uint32 uint32 --> f26.6 */+ /* */+ /* BULLSHIT: Measure taken in the original glyph must be along the dual */+ /* projection vector. */+ /* */+ /* Second BULLSHIT: Flag attributes are inverted! */+ /* 0 => measure distance in original outline */+ /* 1 => measure distance in grid-fitted outline */+ /* */+ /* Third one: `zp0 - zp1', and not `zp2 - zp1! */+ /* */+ static void+ Ins_MD( INS_ARG )+ {+ FT_UShort K, L;+ FT_F26Dot6 D;+++ K = (FT_UShort)args[1];+ L = (FT_UShort)args[0];++ if ( BOUNDS( L, CUR.zp0.n_points ) ||+ BOUNDS( K, CUR.zp1.n_points ) )+ {+ if ( CUR.pedantic_hinting )+ {+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }+ D = 0;+ }+ else+ {+ if ( CUR.opcode & 1 )+ D = CUR_Func_project( CUR.zp0.cur + L, CUR.zp1.cur + K );+ else+ {+ FT_Vector* vec1 = CUR.zp0.orus + L;+ FT_Vector* vec2 = CUR.zp1.orus + K;+++ if ( CUR.metrics.x_scale == CUR.metrics.y_scale )+ {+ /* this should be faster */+ D = CUR_Func_dualproj( vec1, vec2 );+ D = TT_MULFIX( D, CUR.metrics.x_scale );+ }+ else+ {+ FT_Vector vec;+++ vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale );+ vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale );++ D = CUR_fast_dualproj( &vec );+ }+ }+ }++ args[0] = D;+ }+++ /*************************************************************************/+ /* */+ /* SDPVTL[a]: Set Dual PVector to Line */+ /* Opcode range: 0x86-0x87 */+ /* Stack: uint32 uint32 --> */+ /* */+ static void+ Ins_SDPVTL( INS_ARG )+ {+ FT_Long A, B, C;+ FT_UShort p1, p2; /* was FT_Int in pas type ERROR */+++ p1 = (FT_UShort)args[1];+ p2 = (FT_UShort)args[0];++ if ( BOUNDS( p2, CUR.zp1.n_points ) ||+ BOUNDS( p1, CUR.zp2.n_points ) )+ {+ if ( CUR.pedantic_hinting )+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }++ {+ FT_Vector* v1 = CUR.zp1.org + p2;+ FT_Vector* v2 = CUR.zp2.org + p1;+++ A = v1->x - v2->x;+ B = v1->y - v2->y;+ }++ if ( ( CUR.opcode & 1 ) != 0 )+ {+ C = B; /* counter clockwise rotation */+ B = A;+ A = -C;+ }++ NORMalize( A, B, &CUR.GS.dualVector );++ {+ FT_Vector* v1 = CUR.zp1.cur + p2;+ FT_Vector* v2 = CUR.zp2.cur + p1;+++ A = v1->x - v2->x;+ B = v1->y - v2->y;+ }++ if ( ( CUR.opcode & 1 ) != 0 )+ {+ C = B; /* counter clockwise rotation */+ B = A;+ A = -C;+ }++ NORMalize( A, B, &CUR.GS.projVector );++ GUESS_VECTOR( freeVector );++ COMPUTE_Funcs();+ }+++ /*************************************************************************/+ /* */+ /* SZP0[]: Set Zone Pointer 0 */+ /* Opcode range: 0x13 */+ /* Stack: uint32 --> */+ /* */+ static void+ Ins_SZP0( INS_ARG )+ {+ switch ( (FT_Int)args[0] )+ {+ case 0:+ CUR.zp0 = CUR.twilight;+ break;++ case 1:+ CUR.zp0 = CUR.pts;+ break;++ default:+ if ( CUR.pedantic_hinting )+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }++ CUR.GS.gep0 = (FT_UShort)args[0];+ }+++ /*************************************************************************/+ /* */+ /* SZP1[]: Set Zone Pointer 1 */+ /* Opcode range: 0x14 */+ /* Stack: uint32 --> */+ /* */+ static void+ Ins_SZP1( INS_ARG )+ {+ switch ( (FT_Int)args[0] )+ {+ case 0:+ CUR.zp1 = CUR.twilight;+ break;++ case 1:+ CUR.zp1 = CUR.pts;+ break;++ default:+ if ( CUR.pedantic_hinting )+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }++ CUR.GS.gep1 = (FT_UShort)args[0];+ }+++ /*************************************************************************/+ /* */+ /* SZP2[]: Set Zone Pointer 2 */+ /* Opcode range: 0x15 */+ /* Stack: uint32 --> */+ /* */+ static void+ Ins_SZP2( INS_ARG )+ {+ switch ( (FT_Int)args[0] )+ {+ case 0:+ CUR.zp2 = CUR.twilight;+ break;++ case 1:+ CUR.zp2 = CUR.pts;+ break;++ default:+ if ( CUR.pedantic_hinting )+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }++ CUR.GS.gep2 = (FT_UShort)args[0];+ }+++ /*************************************************************************/+ /* */+ /* SZPS[]: Set Zone PointerS */+ /* Opcode range: 0x16 */+ /* Stack: uint32 --> */+ /* */+ static void+ Ins_SZPS( INS_ARG )+ {+ switch ( (FT_Int)args[0] )+ {+ case 0:+ CUR.zp0 = CUR.twilight;+ break;++ case 1:+ CUR.zp0 = CUR.pts;+ break;++ default:+ if ( CUR.pedantic_hinting )+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }++ CUR.zp1 = CUR.zp0;+ CUR.zp2 = CUR.zp0;++ CUR.GS.gep0 = (FT_UShort)args[0];+ CUR.GS.gep1 = (FT_UShort)args[0];+ CUR.GS.gep2 = (FT_UShort)args[0];+ }+++ /*************************************************************************/+ /* */+ /* INSTCTRL[]: INSTruction ConTRoL */+ /* Opcode range: 0x8e */+ /* Stack: int32 int32 --> */+ /* */+ static void+ Ins_INSTCTRL( INS_ARG )+ {+ FT_Long K, L;+++ K = args[1];+ L = args[0];++ if ( K < 1 || K > 2 )+ {+ if ( CUR.pedantic_hinting )+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }++ if ( L != 0 )+ L = K;++ CUR.GS.instruct_control = FT_BOOL(+ ( (FT_Byte)CUR.GS.instruct_control & ~(FT_Byte)K ) | (FT_Byte)L );+ }+++ /*************************************************************************/+ /* */+ /* SCANCTRL[]: SCAN ConTRoL */+ /* Opcode range: 0x85 */+ /* Stack: uint32? --> */+ /* */+ static void+ Ins_SCANCTRL( INS_ARG )+ {+ FT_Int A;+++ /* Get Threshold */+ A = (FT_Int)( args[0] & 0xFF );++ if ( A == 0xFF )+ {+ CUR.GS.scan_control = TRUE;+ return;+ }+ else if ( A == 0 )+ {+ CUR.GS.scan_control = FALSE;+ return;+ }++ if ( ( args[0] & 0x100 ) != 0 && CUR.tt_metrics.ppem <= A )+ CUR.GS.scan_control = TRUE;++ if ( ( args[0] & 0x200 ) != 0 && CUR.tt_metrics.rotated )+ CUR.GS.scan_control = TRUE;++ if ( ( args[0] & 0x400 ) != 0 && CUR.tt_metrics.stretched )+ CUR.GS.scan_control = TRUE;++ if ( ( args[0] & 0x800 ) != 0 && CUR.tt_metrics.ppem > A )+ CUR.GS.scan_control = FALSE;++ if ( ( args[0] & 0x1000 ) != 0 && CUR.tt_metrics.rotated )+ CUR.GS.scan_control = FALSE;++ if ( ( args[0] & 0x2000 ) != 0 && CUR.tt_metrics.stretched )+ CUR.GS.scan_control = FALSE;+ }+++ /*************************************************************************/+ /* */+ /* SCANTYPE[]: SCAN TYPE */+ /* Opcode range: 0x8D */+ /* Stack: uint32? --> */+ /* */+ static void+ Ins_SCANTYPE( INS_ARG )+ {+ if ( args[0] >= 0 )+ CUR.GS.scan_type = (FT_Int)args[0];+ }+++ /*************************************************************************/+ /* */+ /* MANAGING OUTLINES */+ /* */+ /* Instructions appear in the specification's order. */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* FLIPPT[]: FLIP PoinT */+ /* Opcode range: 0x80 */+ /* Stack: uint32... --> */+ /* */+ static void+ Ins_FLIPPT( INS_ARG )+ {+ FT_UShort point;++ FT_UNUSED_ARG;+++ if ( CUR.top < CUR.GS.loop )+ {+ CUR.error = TT_Err_Too_Few_Arguments;+ return;+ }++ while ( CUR.GS.loop > 0 )+ {+ CUR.args--;++ point = (FT_UShort)CUR.stack[CUR.args];++ if ( BOUNDS( point, CUR.pts.n_points ) )+ {+ if ( CUR.pedantic_hinting )+ {+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }+ }+ else+ CUR.pts.tags[point] ^= FT_CURVE_TAG_ON;++ CUR.GS.loop--;+ }++ CUR.GS.loop = 1;+ CUR.new_top = CUR.args;+ }+++ /*************************************************************************/+ /* */+ /* FLIPRGON[]: FLIP RanGe ON */+ /* Opcode range: 0x81 */+ /* Stack: uint32 uint32 --> */+ /* */+ static void+ Ins_FLIPRGON( INS_ARG )+ {+ FT_UShort I, K, L;+++ K = (FT_UShort)args[1];+ L = (FT_UShort)args[0];++ if ( BOUNDS( K, CUR.pts.n_points ) ||+ BOUNDS( L, CUR.pts.n_points ) )+ {+ if ( CUR.pedantic_hinting )+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }++ for ( I = L; I <= K; I++ )+ CUR.pts.tags[I] |= FT_CURVE_TAG_ON;+ }+++ /*************************************************************************/+ /* */+ /* FLIPRGOFF: FLIP RanGe OFF */+ /* Opcode range: 0x82 */+ /* Stack: uint32 uint32 --> */+ /* */+ static void+ Ins_FLIPRGOFF( INS_ARG )+ {+ FT_UShort I, K, L;+++ K = (FT_UShort)args[1];+ L = (FT_UShort)args[0];++ if ( BOUNDS( K, CUR.pts.n_points ) ||+ BOUNDS( L, CUR.pts.n_points ) )+ {+ if ( CUR.pedantic_hinting )+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }++ for ( I = L; I <= K; I++ )+ CUR.pts.tags[I] &= ~FT_CURVE_TAG_ON;+ }+++ static FT_Bool+ Compute_Point_Displacement( EXEC_OP_ FT_F26Dot6* x,+ FT_F26Dot6* y,+ TT_GlyphZone zone,+ FT_UShort* refp )+ {+ TT_GlyphZoneRec zp;+ FT_UShort p;+ FT_F26Dot6 d;+++ if ( CUR.opcode & 1 )+ {+ zp = CUR.zp0;+ p = CUR.GS.rp1;+ }+ else+ {+ zp = CUR.zp1;+ p = CUR.GS.rp2;+ }++ if ( BOUNDS( p, zp.n_points ) )+ {+ if ( CUR.pedantic_hinting )+ CUR.error = TT_Err_Invalid_Reference;+ *refp = 0;+ return FAILURE;+ }++ *zone = zp;+ *refp = p;++ d = CUR_Func_project( zp.cur + p, zp.org + p );++#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING+ if ( CUR.face->unpatented_hinting )+ {+ if ( CUR.GS.both_x_axis )+ {+ *x = d;+ *y = 0;+ }+ else+ {+ *x = 0;+ *y = d;+ }+ }+ else+#endif+ {+ *x = TT_MULDIV( d,+ (FT_Long)CUR.GS.freeVector.x * 0x10000L,+ CUR.F_dot_P );+ *y = TT_MULDIV( d,+ (FT_Long)CUR.GS.freeVector.y * 0x10000L,+ CUR.F_dot_P );+ }++ return SUCCESS;+ }+++ static void+ Move_Zp2_Point( EXEC_OP_ FT_UShort point,+ FT_F26Dot6 dx,+ FT_F26Dot6 dy,+ FT_Bool touch )+ {+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING+ if ( CUR.face->unpatented_hinting )+ {+ if ( CUR.GS.both_x_axis )+ {+ CUR.zp2.cur[point].x += dx;+ if ( touch )+ CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;+ }+ else+ {+ CUR.zp2.cur[point].y += dy;+ if ( touch )+ CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;+ }+ return;+ }+#endif++ if ( CUR.GS.freeVector.x != 0 )+ {+ CUR.zp2.cur[point].x += dx;+ if ( touch )+ CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;+ }++ if ( CUR.GS.freeVector.y != 0 )+ {+ CUR.zp2.cur[point].y += dy;+ if ( touch )+ CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;+ }+ }+++ /*************************************************************************/+ /* */+ /* SHP[a]: SHift Point by the last point */+ /* Opcode range: 0x32-0x33 */+ /* Stack: uint32... --> */+ /* */+ static void+ Ins_SHP( INS_ARG )+ {+ TT_GlyphZoneRec zp;+ FT_UShort refp;++ FT_F26Dot6 dx,+ dy;+ FT_UShort point;++ FT_UNUSED_ARG;+++ if ( CUR.top < CUR.GS.loop )+ {+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }++ if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )+ return;++ while ( CUR.GS.loop > 0 )+ {+ CUR.args--;+ point = (FT_UShort)CUR.stack[CUR.args];++ if ( BOUNDS( point, CUR.zp2.n_points ) )+ {+ if ( CUR.pedantic_hinting )+ {+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }+ }+ else+ /* XXX: UNDOCUMENTED! SHP touches the points */+ MOVE_Zp2_Point( point, dx, dy, TRUE );++ CUR.GS.loop--;+ }++ CUR.GS.loop = 1;+ CUR.new_top = CUR.args;+ }+++ /*************************************************************************/+ /* */+ /* SHC[a]: SHift Contour */+ /* Opcode range: 0x34-35 */+ /* Stack: uint32 --> */+ /* */+ static void+ Ins_SHC( INS_ARG )+ {+ TT_GlyphZoneRec zp;+ FT_UShort refp;+ FT_F26Dot6 dx,+ dy;++ FT_Short contour;+ FT_UShort first_point, last_point, i;+++ contour = (FT_UShort)args[0];++ if ( BOUNDS( contour, CUR.pts.n_contours ) )+ {+ if ( CUR.pedantic_hinting )+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }++ if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )+ return;++ if ( contour == 0 )+ first_point = 0;+ else+ first_point = (FT_UShort)( CUR.pts.contours[contour - 1] + 1 -+ CUR.pts.first_point );++ last_point = (FT_UShort)( CUR.pts.contours[contour] -+ CUR.pts.first_point );++ /* XXX: this is probably wrong... at least it prevents memory */+ /* corruption when zp2 is the twilight zone */+ if ( BOUNDS( last_point, CUR.zp2.n_points ) )+ {+ if ( CUR.zp2.n_points > 0 )+ last_point = (FT_UShort)(CUR.zp2.n_points - 1);+ else+ last_point = 0;+ }++ /* XXX: UNDOCUMENTED! SHC touches the points */+ for ( i = first_point; i <= last_point; i++ )+ {+ if ( zp.cur != CUR.zp2.cur || refp != i )+ MOVE_Zp2_Point( i, dx, dy, TRUE );+ }+ }+++ /*************************************************************************/+ /* */+ /* SHZ[a]: SHift Zone */+ /* Opcode range: 0x36-37 */+ /* Stack: uint32 --> */+ /* */+ static void+ Ins_SHZ( INS_ARG )+ {+ TT_GlyphZoneRec zp;+ FT_UShort refp;+ FT_F26Dot6 dx,+ dy;++ FT_UShort last_point, i;+++ if ( BOUNDS( args[0], 2 ) )+ {+ if ( CUR.pedantic_hinting )+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }++ if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )+ return;++ /* XXX: UNDOCUMENTED! SHZ doesn't move the phantom points. */+ /* Twilight zone has no contours, so use `n_points'. */+ /* Normal zone's `n_points' includes phantoms, so must */+ /* use end of last contour. */+ if ( CUR.GS.gep2 == 0 && CUR.zp2.n_points > 0 )+ last_point = (FT_UShort)( CUR.zp2.n_points - 1 );+ else if ( CUR.GS.gep2 == 1 && CUR.zp2.n_contours > 0 )+ {+ last_point = (FT_UShort)( CUR.zp2.contours[CUR.zp2.n_contours - 1] );++ if ( BOUNDS( last_point, CUR.zp2.n_points ) )+ {+ if ( CUR.pedantic_hinting )+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }+ }+ else+ last_point = 0;++ /* XXX: UNDOCUMENTED! SHZ doesn't touch the points */+ for ( i = 0; i <= last_point; i++ )+ {+ if ( zp.cur != CUR.zp2.cur || refp != i )+ MOVE_Zp2_Point( i, dx, dy, FALSE );+ }+ }+++ /*************************************************************************/+ /* */+ /* SHPIX[]: SHift points by a PIXel amount */+ /* Opcode range: 0x38 */+ /* Stack: f26.6 uint32... --> */+ /* */+ static void+ Ins_SHPIX( INS_ARG )+ {+ FT_F26Dot6 dx, dy;+ FT_UShort point;+++ if ( CUR.top < CUR.GS.loop + 1 )+ {+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }++#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING+ if ( CUR.face->unpatented_hinting )+ {+ if ( CUR.GS.both_x_axis )+ {+ dx = TT_MulFix14( (FT_UInt32)args[0], 0x4000 );+ dy = 0;+ }+ else+ {+ dx = 0;+ dy = TT_MulFix14( (FT_UInt32)args[0], 0x4000 );+ }+ }+ else+#endif+ {+ dx = TT_MulFix14( (FT_UInt32)args[0], CUR.GS.freeVector.x );+ dy = TT_MulFix14( (FT_UInt32)args[0], CUR.GS.freeVector.y );+ }++ while ( CUR.GS.loop > 0 )+ {+ CUR.args--;++ point = (FT_UShort)CUR.stack[CUR.args];++ if ( BOUNDS( point, CUR.zp2.n_points ) )+ {+ if ( CUR.pedantic_hinting )+ {+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }+ }+ else+ MOVE_Zp2_Point( point, dx, dy, TRUE );++ CUR.GS.loop--;+ }++ CUR.GS.loop = 1;+ CUR.new_top = CUR.args;+ }+++ /*************************************************************************/+ /* */+ /* MSIRP[a]: Move Stack Indirect Relative Position */+ /* Opcode range: 0x3A-0x3B */+ /* Stack: f26.6 uint32 --> */+ /* */+ static void+ Ins_MSIRP( INS_ARG )+ {+ FT_UShort point;+ FT_F26Dot6 distance;+++ point = (FT_UShort)args[0];++ if ( BOUNDS( point, CUR.zp1.n_points ) ||+ BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )+ {+ if ( CUR.pedantic_hinting )+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }++ /* XXX: UNDOCUMENTED! behaviour */+ if ( CUR.GS.gep1 == 0 ) /* if the point that is to be moved */+ /* is in twilight zone */+ {+ CUR.zp1.org[point] = CUR.zp0.org[CUR.GS.rp0];+ CUR_Func_move_orig( &CUR.zp1, point, args[1] );+ CUR.zp1.cur[point] = CUR.zp1.org[point];+ }++ distance = CUR_Func_project( CUR.zp1.cur + point,+ CUR.zp0.cur + CUR.GS.rp0 );++ CUR_Func_move( &CUR.zp1, point, args[1] - distance );++ CUR.GS.rp1 = CUR.GS.rp0;+ CUR.GS.rp2 = point;++ if ( ( CUR.opcode & 1 ) != 0 )+ CUR.GS.rp0 = point;+ }+++ /*************************************************************************/+ /* */+ /* MDAP[a]: Move Direct Absolute Point */+ /* Opcode range: 0x2E-0x2F */+ /* Stack: uint32 --> */+ /* */+ static void+ Ins_MDAP( INS_ARG )+ {+ FT_UShort point;+ FT_F26Dot6 cur_dist,+ distance;+++ point = (FT_UShort)args[0];++ if ( BOUNDS( point, CUR.zp0.n_points ) )+ {+ if ( CUR.pedantic_hinting )+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }++ /* XXX: Is there some undocumented feature while in the */+ /* twilight zone? ? */+ if ( ( CUR.opcode & 1 ) != 0 )+ {+ cur_dist = CUR_fast_project( &CUR.zp0.cur[point] );+ distance = CUR_Func_round( cur_dist,+ CUR.tt_metrics.compensations[0] ) - cur_dist;+ }+ else+ distance = 0;++ CUR_Func_move( &CUR.zp0, point, distance );++ CUR.GS.rp0 = point;+ CUR.GS.rp1 = point;+ }+++ /*************************************************************************/+ /* */+ /* MIAP[a]: Move Indirect Absolute Point */+ /* Opcode range: 0x3E-0x3F */+ /* Stack: uint32 uint32 --> */+ /* */+ static void+ Ins_MIAP( INS_ARG )+ {+ FT_ULong cvtEntry;+ FT_UShort point;+ FT_F26Dot6 distance,+ org_dist;+++ cvtEntry = (FT_ULong)args[1];+ point = (FT_UShort)args[0];++ if ( BOUNDS( point, CUR.zp0.n_points ) ||+ BOUNDSL( cvtEntry, CUR.cvtSize ) )+ {+ if ( CUR.pedantic_hinting )+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }++ /* XXX: UNDOCUMENTED! */+ /* */+ /* The behaviour of an MIAP instruction is quite */+ /* different when used in the twilight zone. */+ /* */+ /* First, no control value cut-in test is performed */+ /* as it would fail anyway. Second, the original */+ /* point, i.e. (org_x,org_y) of zp0.point, is set */+ /* to the absolute, unrounded distance found in */+ /* the CVT. */+ /* */+ /* This is used in the CVT programs of the Microsoft */+ /* fonts Arial, Times, etc., in order to re-adjust */+ /* some key font heights. It allows the use of the */+ /* IP instruction in the twilight zone, which */+ /* otherwise would be `illegal' according to the */+ /* specification. */+ /* */+ /* We implement it with a special sequence for the */+ /* twilight zone. This is a bad hack, but it seems */+ /* to work. */++ distance = CUR_Func_read_cvt( cvtEntry );++ if ( CUR.GS.gep0 == 0 ) /* If in twilight zone */+ {+ CUR.zp0.org[point].x = TT_MulFix14( (FT_UInt32)distance, CUR.GS.freeVector.x );+ CUR.zp0.org[point].y = TT_MulFix14( (FT_UInt32)distance, CUR.GS.freeVector.y ),+ CUR.zp0.cur[point] = CUR.zp0.org[point];+ }++ org_dist = CUR_fast_project( &CUR.zp0.cur[point] );++ if ( ( CUR.opcode & 1 ) != 0 ) /* rounding and control cutin flag */+ {+ if ( FT_ABS( distance - org_dist ) > CUR.GS.control_value_cutin )+ distance = org_dist;++ distance = CUR_Func_round( distance, CUR.tt_metrics.compensations[0] );+ }++ CUR_Func_move( &CUR.zp0, point, distance - org_dist );++ CUR.GS.rp0 = point;+ CUR.GS.rp1 = point;+ }+++ /*************************************************************************/+ /* */+ /* MDRP[abcde]: Move Direct Relative Point */+ /* Opcode range: 0xC0-0xDF */+ /* Stack: uint32 --> */+ /* */+ static void+ Ins_MDRP( INS_ARG )+ {+ FT_UShort point;+ FT_F26Dot6 org_dist, distance;+++ point = (FT_UShort)args[0];++ if ( BOUNDS( point, CUR.zp1.n_points ) ||+ BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )+ {+ if ( CUR.pedantic_hinting )+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }++ /* XXX: Is there some undocumented feature while in the */+ /* twilight zone? */++ /* XXX: UNDOCUMENTED: twilight zone special case */++ if ( CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 )+ {+ FT_Vector* vec1 = &CUR.zp1.org[point];+ FT_Vector* vec2 = &CUR.zp0.org[CUR.GS.rp0];+++ org_dist = CUR_Func_dualproj( vec1, vec2 );+ }+ else+ {+ FT_Vector* vec1 = &CUR.zp1.orus[point];+ FT_Vector* vec2 = &CUR.zp0.orus[CUR.GS.rp0];+++ if ( CUR.metrics.x_scale == CUR.metrics.y_scale )+ {+ /* this should be faster */+ org_dist = CUR_Func_dualproj( vec1, vec2 );+ org_dist = TT_MULFIX( org_dist, CUR.metrics.x_scale );+ }+ else+ {+ FT_Vector vec;+++ vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale );+ vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale );++ org_dist = CUR_fast_dualproj( &vec );+ }+ }++ /* single width cut-in test */++ if ( FT_ABS( org_dist - CUR.GS.single_width_value ) <+ CUR.GS.single_width_cutin )+ {+ if ( org_dist >= 0 )+ org_dist = CUR.GS.single_width_value;+ else+ org_dist = -CUR.GS.single_width_value;+ }++ /* round flag */++ if ( ( CUR.opcode & 4 ) != 0 )+ distance = CUR_Func_round(+ org_dist,+ CUR.tt_metrics.compensations[CUR.opcode & 3] );+ else+ distance = ROUND_None(+ org_dist,+ CUR.tt_metrics.compensations[CUR.opcode & 3] );++ /* minimum distance flag */++ if ( ( CUR.opcode & 8 ) != 0 )+ {+ if ( org_dist >= 0 )+ {+ if ( distance < CUR.GS.minimum_distance )+ distance = CUR.GS.minimum_distance;+ }+ else+ {+ if ( distance > -CUR.GS.minimum_distance )+ distance = -CUR.GS.minimum_distance;+ }+ }++ /* now move the point */++ org_dist = CUR_Func_project( CUR.zp1.cur + point,+ CUR.zp0.cur + CUR.GS.rp0 );++ CUR_Func_move( &CUR.zp1, point, distance - org_dist );++ CUR.GS.rp1 = CUR.GS.rp0;+ CUR.GS.rp2 = point;++ if ( ( CUR.opcode & 16 ) != 0 )+ CUR.GS.rp0 = point;+ }+++ /*************************************************************************/+ /* */+ /* MIRP[abcde]: Move Indirect Relative Point */+ /* Opcode range: 0xE0-0xFF */+ /* Stack: int32? uint32 --> */+ /* */+ static void+ Ins_MIRP( INS_ARG )+ {+ FT_UShort point;+ FT_ULong cvtEntry;++ FT_F26Dot6 cvt_dist,+ distance,+ cur_dist,+ org_dist;+++ point = (FT_UShort)args[0];+ cvtEntry = (FT_ULong)( args[1] + 1 );++ /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */++ if ( BOUNDS( point, CUR.zp1.n_points ) ||+ BOUNDSL( cvtEntry, CUR.cvtSize + 1 ) ||+ BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )+ {+ if ( CUR.pedantic_hinting )+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }++ if ( !cvtEntry )+ cvt_dist = 0;+ else+ cvt_dist = CUR_Func_read_cvt( cvtEntry - 1 );++ /* single width test */++ if ( FT_ABS( cvt_dist - CUR.GS.single_width_value ) <+ CUR.GS.single_width_cutin )+ {+ if ( cvt_dist >= 0 )+ cvt_dist = CUR.GS.single_width_value;+ else+ cvt_dist = -CUR.GS.single_width_value;+ }++ /* XXX: UNDOCUMENTED! -- twilight zone */++ if ( CUR.GS.gep1 == 0 )+ {+ CUR.zp1.org[point].x = CUR.zp0.org[CUR.GS.rp0].x ++ TT_MulFix14( (FT_UInt32)cvt_dist,+ CUR.GS.freeVector.x );++ CUR.zp1.org[point].y = CUR.zp0.org[CUR.GS.rp0].y ++ TT_MulFix14( (FT_UInt32)cvt_dist,+ CUR.GS.freeVector.y );++ CUR.zp1.cur[point] = CUR.zp0.cur[point];+ }++ org_dist = CUR_Func_dualproj( &CUR.zp1.org[point],+ &CUR.zp0.org[CUR.GS.rp0] );+ cur_dist = CUR_Func_project ( &CUR.zp1.cur[point],+ &CUR.zp0.cur[CUR.GS.rp0] );++ /* auto-flip test */++ if ( CUR.GS.auto_flip )+ {+ if ( ( org_dist ^ cvt_dist ) < 0 )+ cvt_dist = -cvt_dist;+ }++ /* control value cutin and round */++ if ( ( CUR.opcode & 4 ) != 0 )+ {+ /* XXX: UNDOCUMENTED! Only perform cut-in test when both points */+ /* refer to the same zone. */++ if ( CUR.GS.gep0 == CUR.GS.gep1 )+ if ( FT_ABS( cvt_dist - org_dist ) >= CUR.GS.control_value_cutin )+ cvt_dist = org_dist;++ distance = CUR_Func_round(+ cvt_dist,+ CUR.tt_metrics.compensations[CUR.opcode & 3] );+ }+ else+ distance = ROUND_None(+ cvt_dist,+ CUR.tt_metrics.compensations[CUR.opcode & 3] );++ /* minimum distance test */++ if ( ( CUR.opcode & 8 ) != 0 )+ {+ if ( org_dist >= 0 )+ {+ if ( distance < CUR.GS.minimum_distance )+ distance = CUR.GS.minimum_distance;+ }+ else+ {+ if ( distance > -CUR.GS.minimum_distance )+ distance = -CUR.GS.minimum_distance;+ }+ }++ CUR_Func_move( &CUR.zp1, point, distance - cur_dist );++ CUR.GS.rp1 = CUR.GS.rp0;++ if ( ( CUR.opcode & 16 ) != 0 )+ CUR.GS.rp0 = point;++ /* XXX: UNDOCUMENTED! */+ CUR.GS.rp2 = point;+ }+++ /*************************************************************************/+ /* */+ /* ALIGNRP[]: ALIGN Relative Point */+ /* Opcode range: 0x3C */+ /* Stack: uint32 uint32... --> */+ /* */+ static void+ Ins_ALIGNRP( INS_ARG )+ {+ FT_UShort point;+ FT_F26Dot6 distance;++ FT_UNUSED_ARG;+++ if ( CUR.top < CUR.GS.loop ||+ BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )+ {+ if ( CUR.pedantic_hinting )+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }++ while ( CUR.GS.loop > 0 )+ {+ CUR.args--;++ point = (FT_UShort)CUR.stack[CUR.args];++ if ( BOUNDS( point, CUR.zp1.n_points ) )+ {+ if ( CUR.pedantic_hinting )+ {+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }+ }+ else+ {+ distance = CUR_Func_project( CUR.zp1.cur + point,+ CUR.zp0.cur + CUR.GS.rp0 );++ CUR_Func_move( &CUR.zp1, point, -distance );+ }++ CUR.GS.loop--;+ }++ CUR.GS.loop = 1;+ CUR.new_top = CUR.args;+ }+++ /*************************************************************************/+ /* */+ /* ISECT[]: moves point to InterSECTion */+ /* Opcode range: 0x0F */+ /* Stack: 5 * uint32 --> */+ /* */+ static void+ Ins_ISECT( INS_ARG )+ {+ FT_UShort point,+ a0, a1,+ b0, b1;++ FT_F26Dot6 discriminant;++ FT_F26Dot6 dx, dy,+ dax, day,+ dbx, dby;++ FT_F26Dot6 val;++ FT_Vector R;+++ point = (FT_UShort)args[0];++ a0 = (FT_UShort)args[1];+ a1 = (FT_UShort)args[2];+ b0 = (FT_UShort)args[3];+ b1 = (FT_UShort)args[4];++ if ( BOUNDS( b0, CUR.zp0.n_points ) ||+ BOUNDS( b1, CUR.zp0.n_points ) ||+ BOUNDS( a0, CUR.zp1.n_points ) ||+ BOUNDS( a1, CUR.zp1.n_points ) ||+ BOUNDS( point, CUR.zp2.n_points ) )+ {+ if ( CUR.pedantic_hinting )+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }++ dbx = CUR.zp0.cur[b1].x - CUR.zp0.cur[b0].x;+ dby = CUR.zp0.cur[b1].y - CUR.zp0.cur[b0].y;++ dax = CUR.zp1.cur[a1].x - CUR.zp1.cur[a0].x;+ day = CUR.zp1.cur[a1].y - CUR.zp1.cur[a0].y;++ dx = CUR.zp0.cur[b0].x - CUR.zp1.cur[a0].x;+ dy = CUR.zp0.cur[b0].y - CUR.zp1.cur[a0].y;++ CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH;++ discriminant = TT_MULDIV( dax, -dby, 0x40 ) ++ TT_MULDIV( day, dbx, 0x40 );++ if ( FT_ABS( discriminant ) >= 0x40 )+ {+ val = TT_MULDIV( dx, -dby, 0x40 ) + TT_MULDIV( dy, dbx, 0x40 );++ R.x = TT_MULDIV( val, dax, discriminant );+ R.y = TT_MULDIV( val, day, discriminant );++ CUR.zp2.cur[point].x = CUR.zp1.cur[a0].x + R.x;+ CUR.zp2.cur[point].y = CUR.zp1.cur[a0].y + R.y;+ }+ else+ {+ /* else, take the middle of the middles of A and B */++ CUR.zp2.cur[point].x = ( CUR.zp1.cur[a0].x ++ CUR.zp1.cur[a1].x ++ CUR.zp0.cur[b0].x ++ CUR.zp0.cur[b1].x ) / 4;+ CUR.zp2.cur[point].y = ( CUR.zp1.cur[a0].y ++ CUR.zp1.cur[a1].y ++ CUR.zp0.cur[b0].y ++ CUR.zp0.cur[b1].y ) / 4;+ }+ }+++ /*************************************************************************/+ /* */+ /* ALIGNPTS[]: ALIGN PoinTS */+ /* Opcode range: 0x27 */+ /* Stack: uint32 uint32 --> */+ /* */+ static void+ Ins_ALIGNPTS( INS_ARG )+ {+ FT_UShort p1, p2;+ FT_F26Dot6 distance;+++ p1 = (FT_UShort)args[0];+ p2 = (FT_UShort)args[1];++ if ( BOUNDS( p1, CUR.zp1.n_points ) ||+ BOUNDS( p2, CUR.zp0.n_points ) )+ {+ if ( CUR.pedantic_hinting )+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }++ distance = CUR_Func_project( CUR.zp0.cur + p2,+ CUR.zp1.cur + p1 ) / 2;++ CUR_Func_move( &CUR.zp1, p1, distance );+ CUR_Func_move( &CUR.zp0, p2, -distance );+ }+++ /*************************************************************************/+ /* */+ /* IP[]: Interpolate Point */+ /* Opcode range: 0x39 */+ /* Stack: uint32... --> */+ /* */++ /* SOMETIMES, DUMBER CODE IS BETTER CODE */++ static void+ Ins_IP( INS_ARG )+ {+ FT_F26Dot6 old_range, cur_range;+ FT_Vector* orus_base;+ FT_Vector* cur_base;+ FT_Int twilight;++ FT_UNUSED_ARG;+++ if ( CUR.top < CUR.GS.loop )+ {+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }++ /*+ * We need to deal in a special way with the twilight zone.+ * Otherwise, by definition, the value of CUR.twilight.orus[n] is (0,0),+ * for every n.+ */+ twilight = CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 || CUR.GS.gep2 == 0;++ if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) )+ {+ if ( CUR.pedantic_hinting )+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }++ if ( twilight )+ orus_base = &CUR.zp0.org[CUR.GS.rp1];+ else+ orus_base = &CUR.zp0.orus[CUR.GS.rp1];++ cur_base = &CUR.zp0.cur[CUR.GS.rp1];++ /* XXX: There are some glyphs in some braindead but popular */+ /* fonts out there (e.g. [aeu]grave in monotype.ttf) */+ /* calling IP[] with bad values of rp[12]. */+ /* Do something sane when this odd thing happens. */+ if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) ||+ BOUNDS( CUR.GS.rp2, CUR.zp1.n_points ) )+ {+ old_range = 0;+ cur_range = 0;+ }+ else+ {+ if ( twilight )+ old_range = CUR_Func_dualproj( &CUR.zp1.org[CUR.GS.rp2],+ orus_base );+ else+ old_range = CUR_Func_dualproj( &CUR.zp1.orus[CUR.GS.rp2],+ orus_base );++ cur_range = CUR_Func_project ( &CUR.zp1.cur[CUR.GS.rp2], cur_base );+ }++ for ( ; CUR.GS.loop > 0; --CUR.GS.loop )+ {+ FT_UInt point = (FT_UInt)CUR.stack[--CUR.args];+ FT_F26Dot6 org_dist, cur_dist, new_dist;+++ /* check point bounds */+ if ( BOUNDS( point, CUR.zp2.n_points ) )+ {+ if ( CUR.pedantic_hinting )+ {+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }+ continue;+ }++ if ( twilight )+ org_dist = CUR_Func_dualproj( &CUR.zp2.org[point], orus_base );+ else+ org_dist = CUR_Func_dualproj( &CUR.zp2.orus[point], orus_base );++ cur_dist = CUR_Func_project ( &CUR.zp2.cur[point], cur_base );++ if ( org_dist )+ new_dist = ( old_range != 0 )+ ? TT_MULDIV( org_dist, cur_range, old_range )+ : cur_dist;+ else+ new_dist = 0;++ CUR_Func_move( &CUR.zp2, (FT_UShort)point, new_dist - cur_dist );+ }+ CUR.GS.loop = 1;+ CUR.new_top = CUR.args;+ }+++ /*************************************************************************/+ /* */+ /* UTP[a]: UnTouch Point */+ /* Opcode range: 0x29 */+ /* Stack: uint32 --> */+ /* */+ static void+ Ins_UTP( INS_ARG )+ {+ FT_UShort point;+ FT_Byte mask;+++ point = (FT_UShort)args[0];++ if ( BOUNDS( point, CUR.zp0.n_points ) )+ {+ if ( CUR.pedantic_hinting )+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }++ mask = 0xFF;++ if ( CUR.GS.freeVector.x != 0 )+ mask &= ~FT_CURVE_TAG_TOUCH_X;++ if ( CUR.GS.freeVector.y != 0 )+ mask &= ~FT_CURVE_TAG_TOUCH_Y;++ CUR.zp0.tags[point] &= mask;+ }+++ /* Local variables for Ins_IUP: */+ typedef struct IUP_WorkerRec_+ {+ FT_Vector* orgs; /* original and current coordinate */+ FT_Vector* curs; /* arrays */+ FT_Vector* orus;+ FT_UInt max_points;++ } IUP_WorkerRec, *IUP_Worker;+++ static void+ _iup_worker_shift( IUP_Worker worker,+ FT_UInt p1,+ FT_UInt p2,+ FT_UInt p )+ {+ FT_UInt i;+ FT_F26Dot6 dx;+++ dx = worker->curs[p].x - worker->orgs[p].x;+ if ( dx != 0 )+ {+ for ( i = p1; i < p; i++ )+ worker->curs[i].x += dx;++ for ( i = p + 1; i <= p2; i++ )+ worker->curs[i].x += dx;+ }+ }+++ static void+ _iup_worker_interpolate( IUP_Worker worker,+ FT_UInt p1,+ FT_UInt p2,+ FT_UInt ref1,+ FT_UInt ref2 )+ {+ FT_UInt i;+ FT_F26Dot6 orus1, orus2, org1, org2, delta1, delta2;+++ if ( p1 > p2 )+ return;++ if ( BOUNDS( ref1, worker->max_points ) ||+ BOUNDS( ref2, worker->max_points ) )+ return;++ orus1 = worker->orus[ref1].x;+ orus2 = worker->orus[ref2].x;++ if ( orus1 > orus2 )+ {+ FT_F26Dot6 tmp_o;+ FT_UInt tmp_r;+++ tmp_o = orus1;+ orus1 = orus2;+ orus2 = tmp_o;++ tmp_r = ref1;+ ref1 = ref2;+ ref2 = tmp_r;+ }++ org1 = worker->orgs[ref1].x;+ org2 = worker->orgs[ref2].x;+ delta1 = worker->curs[ref1].x - org1;+ delta2 = worker->curs[ref2].x - org2;++ if ( orus1 == orus2 )+ {+ /* simple shift of untouched points */+ for ( i = p1; i <= p2; i++ )+ {+ FT_F26Dot6 x = worker->orgs[i].x;+++ if ( x <= org1 )+ x += delta1;+ else+ x += delta2;++ worker->curs[i].x = x;+ }+ }+ else+ {+ FT_Fixed scale = 0;+ FT_Bool scale_valid = 0;+++ /* interpolation */+ for ( i = p1; i <= p2; i++ )+ {+ FT_F26Dot6 x = worker->orgs[i].x;+++ if ( x <= org1 )+ x += delta1;++ else if ( x >= org2 )+ x += delta2;++ else+ {+ if ( !scale_valid )+ {+ scale_valid = 1;+ scale = TT_MULDIV( org2 + delta2 - ( org1 + delta1 ),+ 0x10000L, orus2 - orus1 );+ }++ x = ( org1 + delta1 ) ++ TT_MULFIX( worker->orus[i].x - orus1, scale );+ }+ worker->curs[i].x = x;+ }+ }+ }+++ /*************************************************************************/+ /* */+ /* IUP[a]: Interpolate Untouched Points */+ /* Opcode range: 0x30-0x31 */+ /* Stack: --> */+ /* */+ static void+ Ins_IUP( INS_ARG )+ {+ IUP_WorkerRec V;+ FT_Byte mask;++ FT_UInt first_point; /* first point of contour */+ FT_UInt end_point; /* end point (last+1) of contour */++ FT_UInt first_touched; /* first touched point in contour */+ FT_UInt cur_touched; /* current touched point in contour */++ FT_UInt point; /* current point */+ FT_Short contour; /* current contour */++ FT_UNUSED_ARG;+++ /* ignore empty outlines */+ if ( CUR.pts.n_contours == 0 )+ return;++ if ( CUR.opcode & 1 )+ {+ mask = FT_CURVE_TAG_TOUCH_X;+ V.orgs = CUR.pts.org;+ V.curs = CUR.pts.cur;+ V.orus = CUR.pts.orus;+ }+ else+ {+ mask = FT_CURVE_TAG_TOUCH_Y;+ V.orgs = (FT_Vector*)( (FT_Pos*)CUR.pts.org + 1 );+ V.curs = (FT_Vector*)( (FT_Pos*)CUR.pts.cur + 1 );+ V.orus = (FT_Vector*)( (FT_Pos*)CUR.pts.orus + 1 );+ }+ V.max_points = CUR.pts.n_points;++ contour = 0;+ point = 0;++ do+ {+ end_point = CUR.pts.contours[contour] - CUR.pts.first_point;+ first_point = point;++ if ( BOUNDS ( end_point, CUR.pts.n_points ) )+ end_point = CUR.pts.n_points - 1;++ while ( point <= end_point && ( CUR.pts.tags[point] & mask ) == 0 )+ point++;++ if ( point <= end_point )+ {+ first_touched = point;+ cur_touched = point;++ point++;++ while ( point <= end_point )+ {+ if ( ( CUR.pts.tags[point] & mask ) != 0 )+ {+ _iup_worker_interpolate( &V,+ cur_touched + 1,+ point - 1,+ cur_touched,+ point );+ cur_touched = point;+ }++ point++;+ }++ if ( cur_touched == first_touched )+ _iup_worker_shift( &V, first_point, end_point, cur_touched );+ else+ {+ _iup_worker_interpolate( &V,+ (FT_UShort)( cur_touched + 1 ),+ end_point,+ cur_touched,+ first_touched );++ if ( first_touched > 0 )+ _iup_worker_interpolate( &V,+ first_point,+ first_touched - 1,+ cur_touched,+ first_touched );+ }+ }+ contour++;+ } while ( contour < CUR.pts.n_contours );+ }+++ /*************************************************************************/+ /* */+ /* DELTAPn[]: DELTA exceptions P1, P2, P3 */+ /* Opcode range: 0x5D,0x71,0x72 */+ /* Stack: uint32 (2 * uint32)... --> */+ /* */+ static void+ Ins_DELTAP( INS_ARG )+ {+ FT_ULong k, nump;+ FT_UShort A;+ FT_ULong C;+ FT_Long B;+++#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING+ /* Delta hinting is covered by US Patent 5159668. */+ if ( CUR.face->unpatented_hinting )+ {+ FT_Long n = args[0] * 2;+++ if ( CUR.args < n )+ {+ CUR.error = TT_Err_Too_Few_Arguments;+ return;+ }++ CUR.args -= n;+ CUR.new_top = CUR.args;+ return;+ }+#endif++ nump = (FT_ULong)args[0]; /* some points theoretically may occur more+ than once, thus UShort isn't enough */++ for ( k = 1; k <= nump; k++ )+ {+ if ( CUR.args < 2 )+ {+ CUR.error = TT_Err_Too_Few_Arguments;+ return;+ }++ CUR.args -= 2;++ A = (FT_UShort)CUR.stack[CUR.args + 1];+ B = CUR.stack[CUR.args];++ /* XXX: Because some popular fonts contain some invalid DeltaP */+ /* instructions, we simply ignore them when the stacked */+ /* point reference is off limit, rather than returning an */+ /* error. As a delta instruction doesn't change a glyph */+ /* in great ways, this shouldn't be a problem. */++ if ( !BOUNDS( A, CUR.zp0.n_points ) )+ {+ C = ( (FT_ULong)B & 0xF0 ) >> 4;++ switch ( CUR.opcode )+ {+ case 0x5D:+ break;++ case 0x71:+ C += 16;+ break;++ case 0x72:+ C += 32;+ break;+ }++ C += CUR.GS.delta_base;++ if ( CURRENT_Ppem() == (FT_Long)C )+ {+ B = ( (FT_ULong)B & 0xF ) - 8;+ if ( B >= 0 )+ B++;+ B = B * 64 / ( 1L << CUR.GS.delta_shift );++ CUR_Func_move( &CUR.zp0, A, B );+ }+ }+ else+ if ( CUR.pedantic_hinting )+ CUR.error = TT_Err_Invalid_Reference;+ }++ CUR.new_top = CUR.args;+ }+++ /*************************************************************************/+ /* */+ /* DELTACn[]: DELTA exceptions C1, C2, C3 */+ /* Opcode range: 0x73,0x74,0x75 */+ /* Stack: uint32 (2 * uint32)... --> */+ /* */+ static void+ Ins_DELTAC( INS_ARG )+ {+ FT_ULong nump, k;+ FT_ULong A, C;+ FT_Long B;+++#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING+ /* Delta hinting is covered by US Patent 5159668. */+ if ( CUR.face->unpatented_hinting )+ {+ FT_Long n = args[0] * 2;+++ if ( CUR.args < n )+ {+ CUR.error = TT_Err_Too_Few_Arguments;+ return;+ }++ CUR.args -= n;+ CUR.new_top = CUR.args;+ return;+ }+#endif++ nump = (FT_ULong)args[0];++ for ( k = 1; k <= nump; k++ )+ {+ if ( CUR.args < 2 )+ {+ CUR.error = TT_Err_Too_Few_Arguments;+ return;+ }++ CUR.args -= 2;++ A = (FT_ULong)CUR.stack[CUR.args + 1];+ B = CUR.stack[CUR.args];++ if ( BOUNDSL( A, CUR.cvtSize ) )+ {+ if ( CUR.pedantic_hinting )+ {+ CUR.error = TT_Err_Invalid_Reference;+ return;+ }+ }+ else+ {+ C = ( (FT_ULong)B & 0xF0 ) >> 4;++ switch ( CUR.opcode )+ {+ case 0x73:+ break;++ case 0x74:+ C += 16;+ break;++ case 0x75:+ C += 32;+ break;+ }++ C += CUR.GS.delta_base;++ if ( CURRENT_Ppem() == (FT_Long)C )+ {+ B = ( (FT_ULong)B & 0xF ) - 8;+ if ( B >= 0 )+ B++;+ B = B * 64 / ( 1L << CUR.GS.delta_shift );++ CUR_Func_move_cvt( A, B );+ }+ }+ }++ CUR.new_top = CUR.args;+ }+++ /*************************************************************************/+ /* */+ /* MISC. INSTRUCTIONS */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* GETINFO[]: GET INFOrmation */+ /* Opcode range: 0x88 */+ /* Stack: uint32 --> uint32 */+ /* */+ static void+ Ins_GETINFO( INS_ARG )+ {+ FT_Long K;+++ K = 0;++ /* We return MS rasterizer version 1.7 for the font scaler. */+ if ( ( args[0] & 1 ) != 0 )+ K = 35;++ /* Has the glyph been rotated? */+ if ( ( args[0] & 2 ) != 0 && CUR.tt_metrics.rotated )+ K |= 0x80;++ /* Has the glyph been stretched? */+ if ( ( args[0] & 4 ) != 0 && CUR.tt_metrics.stretched )+ K |= 1 << 8;++ /* Are we hinting for grayscale? */+ if ( ( args[0] & 32 ) != 0 && CUR.grayscale )+ K |= 1 << 12;++ args[0] = K;+ }+++ static void+ Ins_UNKNOWN( INS_ARG )+ {+ TT_DefRecord* def = CUR.IDefs;+ TT_DefRecord* limit = def + CUR.numIDefs;++ FT_UNUSED_ARG;+++ for ( ; def < limit; def++ )+ {+ if ( (FT_Byte)def->opc == CUR.opcode && def->active )+ {+ TT_CallRec* call;+++ if ( CUR.callTop >= CUR.callSize )+ {+ CUR.error = TT_Err_Stack_Overflow;+ return;+ }++ call = CUR.callStack + CUR.callTop++;++ call->Caller_Range = CUR.curRange;+ call->Caller_IP = CUR.IP + 1;+ call->Cur_Count = 1;+ call->Cur_Restart = def->start;++ INS_Goto_CodeRange( def->range, def->start );++ CUR.step_ins = FALSE;+ return;+ }+ }++ CUR.error = TT_Err_Invalid_Opcode;+ }+++#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH+++ static+ TInstruction_Function Instruct_Dispatch[256] =+ {+ /* Opcodes are gathered in groups of 16. */+ /* Please keep the spaces as they are. */++ /* SVTCA y */ Ins_SVTCA,+ /* SVTCA x */ Ins_SVTCA,+ /* SPvTCA y */ Ins_SPVTCA,+ /* SPvTCA x */ Ins_SPVTCA,+ /* SFvTCA y */ Ins_SFVTCA,+ /* SFvTCA x */ Ins_SFVTCA,+ /* SPvTL // */ Ins_SPVTL,+ /* SPvTL + */ Ins_SPVTL,+ /* SFvTL // */ Ins_SFVTL,+ /* SFvTL + */ Ins_SFVTL,+ /* SPvFS */ Ins_SPVFS,+ /* SFvFS */ Ins_SFVFS,+ /* GPV */ Ins_GPV,+ /* GFV */ Ins_GFV,+ /* SFvTPv */ Ins_SFVTPV,+ /* ISECT */ Ins_ISECT,++ /* SRP0 */ Ins_SRP0,+ /* SRP1 */ Ins_SRP1,+ /* SRP2 */ Ins_SRP2,+ /* SZP0 */ Ins_SZP0,+ /* SZP1 */ Ins_SZP1,+ /* SZP2 */ Ins_SZP2,+ /* SZPS */ Ins_SZPS,+ /* SLOOP */ Ins_SLOOP,+ /* RTG */ Ins_RTG,+ /* RTHG */ Ins_RTHG,+ /* SMD */ Ins_SMD,+ /* ELSE */ Ins_ELSE,+ /* JMPR */ Ins_JMPR,+ /* SCvTCi */ Ins_SCVTCI,+ /* SSwCi */ Ins_SSWCI,+ /* SSW */ Ins_SSW,++ /* DUP */ Ins_DUP,+ /* POP */ Ins_POP,+ /* CLEAR */ Ins_CLEAR,+ /* SWAP */ Ins_SWAP,+ /* DEPTH */ Ins_DEPTH,+ /* CINDEX */ Ins_CINDEX,+ /* MINDEX */ Ins_MINDEX,+ /* AlignPTS */ Ins_ALIGNPTS,+ /* INS_0x28 */ Ins_UNKNOWN,+ /* UTP */ Ins_UTP,+ /* LOOPCALL */ Ins_LOOPCALL,+ /* CALL */ Ins_CALL,+ /* FDEF */ Ins_FDEF,+ /* ENDF */ Ins_ENDF,+ /* MDAP[0] */ Ins_MDAP,+ /* MDAP[1] */ Ins_MDAP,++ /* IUP[0] */ Ins_IUP,+ /* IUP[1] */ Ins_IUP,+ /* SHP[0] */ Ins_SHP,+ /* SHP[1] */ Ins_SHP,+ /* SHC[0] */ Ins_SHC,+ /* SHC[1] */ Ins_SHC,+ /* SHZ[0] */ Ins_SHZ,+ /* SHZ[1] */ Ins_SHZ,+ /* SHPIX */ Ins_SHPIX,+ /* IP */ Ins_IP,+ /* MSIRP[0] */ Ins_MSIRP,+ /* MSIRP[1] */ Ins_MSIRP,+ /* AlignRP */ Ins_ALIGNRP,+ /* RTDG */ Ins_RTDG,+ /* MIAP[0] */ Ins_MIAP,+ /* MIAP[1] */ Ins_MIAP,++ /* NPushB */ Ins_NPUSHB,+ /* NPushW */ Ins_NPUSHW,+ /* WS */ Ins_WS,+ /* RS */ Ins_RS,+ /* WCvtP */ Ins_WCVTP,+ /* RCvt */ Ins_RCVT,+ /* GC[0] */ Ins_GC,+ /* GC[1] */ Ins_GC,+ /* SCFS */ Ins_SCFS,+ /* MD[0] */ Ins_MD,+ /* MD[1] */ Ins_MD,+ /* MPPEM */ Ins_MPPEM,+ /* MPS */ Ins_MPS,+ /* FlipON */ Ins_FLIPON,+ /* FlipOFF */ Ins_FLIPOFF,+ /* DEBUG */ Ins_DEBUG,++ /* LT */ Ins_LT,+ /* LTEQ */ Ins_LTEQ,+ /* GT */ Ins_GT,+ /* GTEQ */ Ins_GTEQ,+ /* EQ */ Ins_EQ,+ /* NEQ */ Ins_NEQ,+ /* ODD */ Ins_ODD,+ /* EVEN */ Ins_EVEN,+ /* IF */ Ins_IF,+ /* EIF */ Ins_EIF,+ /* AND */ Ins_AND,+ /* OR */ Ins_OR,+ /* NOT */ Ins_NOT,+ /* DeltaP1 */ Ins_DELTAP,+ /* SDB */ Ins_SDB,+ /* SDS */ Ins_SDS,++ /* ADD */ Ins_ADD,+ /* SUB */ Ins_SUB,+ /* DIV */ Ins_DIV,+ /* MUL */ Ins_MUL,+ /* ABS */ Ins_ABS,+ /* NEG */ Ins_NEG,+ /* FLOOR */ Ins_FLOOR,+ /* CEILING */ Ins_CEILING,+ /* ROUND[0] */ Ins_ROUND,+ /* ROUND[1] */ Ins_ROUND,+ /* ROUND[2] */ Ins_ROUND,+ /* ROUND[3] */ Ins_ROUND,+ /* NROUND[0] */ Ins_NROUND,+ /* NROUND[1] */ Ins_NROUND,+ /* NROUND[2] */ Ins_NROUND,+ /* NROUND[3] */ Ins_NROUND,++ /* WCvtF */ Ins_WCVTF,+ /* DeltaP2 */ Ins_DELTAP,+ /* DeltaP3 */ Ins_DELTAP,+ /* DeltaCn[0] */ Ins_DELTAC,+ /* DeltaCn[1] */ Ins_DELTAC,+ /* DeltaCn[2] */ Ins_DELTAC,+ /* SROUND */ Ins_SROUND,+ /* S45Round */ Ins_S45ROUND,+ /* JROT */ Ins_JROT,+ /* JROF */ Ins_JROF,+ /* ROFF */ Ins_ROFF,+ /* INS_0x7B */ Ins_UNKNOWN,+ /* RUTG */ Ins_RUTG,+ /* RDTG */ Ins_RDTG,+ /* SANGW */ Ins_SANGW,+ /* AA */ Ins_AA,++ /* FlipPT */ Ins_FLIPPT,+ /* FlipRgON */ Ins_FLIPRGON,+ /* FlipRgOFF */ Ins_FLIPRGOFF,+ /* INS_0x83 */ Ins_UNKNOWN,+ /* INS_0x84 */ Ins_UNKNOWN,+ /* ScanCTRL */ Ins_SCANCTRL,+ /* SDPVTL[0] */ Ins_SDPVTL,+ /* SDPVTL[1] */ Ins_SDPVTL,+ /* GetINFO */ Ins_GETINFO,+ /* IDEF */ Ins_IDEF,+ /* ROLL */ Ins_ROLL,+ /* MAX */ Ins_MAX,+ /* MIN */ Ins_MIN,+ /* ScanTYPE */ Ins_SCANTYPE,+ /* InstCTRL */ Ins_INSTCTRL,+ /* INS_0x8F */ Ins_UNKNOWN,++ /* INS_0x90 */ Ins_UNKNOWN,+ /* INS_0x91 */ Ins_UNKNOWN,+ /* INS_0x92 */ Ins_UNKNOWN,+ /* INS_0x93 */ Ins_UNKNOWN,+ /* INS_0x94 */ Ins_UNKNOWN,+ /* INS_0x95 */ Ins_UNKNOWN,+ /* INS_0x96 */ Ins_UNKNOWN,+ /* INS_0x97 */ Ins_UNKNOWN,+ /* INS_0x98 */ Ins_UNKNOWN,+ /* INS_0x99 */ Ins_UNKNOWN,+ /* INS_0x9A */ Ins_UNKNOWN,+ /* INS_0x9B */ Ins_UNKNOWN,+ /* INS_0x9C */ Ins_UNKNOWN,+ /* INS_0x9D */ Ins_UNKNOWN,+ /* INS_0x9E */ Ins_UNKNOWN,+ /* INS_0x9F */ Ins_UNKNOWN,++ /* INS_0xA0 */ Ins_UNKNOWN,+ /* INS_0xA1 */ Ins_UNKNOWN,+ /* INS_0xA2 */ Ins_UNKNOWN,+ /* INS_0xA3 */ Ins_UNKNOWN,+ /* INS_0xA4 */ Ins_UNKNOWN,+ /* INS_0xA5 */ Ins_UNKNOWN,+ /* INS_0xA6 */ Ins_UNKNOWN,+ /* INS_0xA7 */ Ins_UNKNOWN,+ /* INS_0xA8 */ Ins_UNKNOWN,+ /* INS_0xA9 */ Ins_UNKNOWN,+ /* INS_0xAA */ Ins_UNKNOWN,+ /* INS_0xAB */ Ins_UNKNOWN,+ /* INS_0xAC */ Ins_UNKNOWN,+ /* INS_0xAD */ Ins_UNKNOWN,+ /* INS_0xAE */ Ins_UNKNOWN,+ /* INS_0xAF */ Ins_UNKNOWN,++ /* PushB[0] */ Ins_PUSHB,+ /* PushB[1] */ Ins_PUSHB,+ /* PushB[2] */ Ins_PUSHB,+ /* PushB[3] */ Ins_PUSHB,+ /* PushB[4] */ Ins_PUSHB,+ /* PushB[5] */ Ins_PUSHB,+ /* PushB[6] */ Ins_PUSHB,+ /* PushB[7] */ Ins_PUSHB,+ /* PushW[0] */ Ins_PUSHW,+ /* PushW[1] */ Ins_PUSHW,+ /* PushW[2] */ Ins_PUSHW,+ /* PushW[3] */ Ins_PUSHW,+ /* PushW[4] */ Ins_PUSHW,+ /* PushW[5] */ Ins_PUSHW,+ /* PushW[6] */ Ins_PUSHW,+ /* PushW[7] */ Ins_PUSHW,++ /* MDRP[00] */ Ins_MDRP,+ /* MDRP[01] */ Ins_MDRP,+ /* MDRP[02] */ Ins_MDRP,+ /* MDRP[03] */ Ins_MDRP,+ /* MDRP[04] */ Ins_MDRP,+ /* MDRP[05] */ Ins_MDRP,+ /* MDRP[06] */ Ins_MDRP,+ /* MDRP[07] */ Ins_MDRP,+ /* MDRP[08] */ Ins_MDRP,+ /* MDRP[09] */ Ins_MDRP,+ /* MDRP[10] */ Ins_MDRP,+ /* MDRP[11] */ Ins_MDRP,+ /* MDRP[12] */ Ins_MDRP,+ /* MDRP[13] */ Ins_MDRP,+ /* MDRP[14] */ Ins_MDRP,+ /* MDRP[15] */ Ins_MDRP,++ /* MDRP[16] */ Ins_MDRP,+ /* MDRP[17] */ Ins_MDRP,+ /* MDRP[18] */ Ins_MDRP,+ /* MDRP[19] */ Ins_MDRP,+ /* MDRP[20] */ Ins_MDRP,+ /* MDRP[21] */ Ins_MDRP,+ /* MDRP[22] */ Ins_MDRP,+ /* MDRP[23] */ Ins_MDRP,+ /* MDRP[24] */ Ins_MDRP,+ /* MDRP[25] */ Ins_MDRP,+ /* MDRP[26] */ Ins_MDRP,+ /* MDRP[27] */ Ins_MDRP,+ /* MDRP[28] */ Ins_MDRP,+ /* MDRP[29] */ Ins_MDRP,+ /* MDRP[30] */ Ins_MDRP,+ /* MDRP[31] */ Ins_MDRP,++ /* MIRP[00] */ Ins_MIRP,+ /* MIRP[01] */ Ins_MIRP,+ /* MIRP[02] */ Ins_MIRP,+ /* MIRP[03] */ Ins_MIRP,+ /* MIRP[04] */ Ins_MIRP,+ /* MIRP[05] */ Ins_MIRP,+ /* MIRP[06] */ Ins_MIRP,+ /* MIRP[07] */ Ins_MIRP,+ /* MIRP[08] */ Ins_MIRP,+ /* MIRP[09] */ Ins_MIRP,+ /* MIRP[10] */ Ins_MIRP,+ /* MIRP[11] */ Ins_MIRP,+ /* MIRP[12] */ Ins_MIRP,+ /* MIRP[13] */ Ins_MIRP,+ /* MIRP[14] */ Ins_MIRP,+ /* MIRP[15] */ Ins_MIRP,++ /* MIRP[16] */ Ins_MIRP,+ /* MIRP[17] */ Ins_MIRP,+ /* MIRP[18] */ Ins_MIRP,+ /* MIRP[19] */ Ins_MIRP,+ /* MIRP[20] */ Ins_MIRP,+ /* MIRP[21] */ Ins_MIRP,+ /* MIRP[22] */ Ins_MIRP,+ /* MIRP[23] */ Ins_MIRP,+ /* MIRP[24] */ Ins_MIRP,+ /* MIRP[25] */ Ins_MIRP,+ /* MIRP[26] */ Ins_MIRP,+ /* MIRP[27] */ Ins_MIRP,+ /* MIRP[28] */ Ins_MIRP,+ /* MIRP[29] */ Ins_MIRP,+ /* MIRP[30] */ Ins_MIRP,+ /* MIRP[31] */ Ins_MIRP+ };+++#endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */+++ /*************************************************************************/+ /* */+ /* RUN */+ /* */+ /* This function executes a run of opcodes. It will exit in the */+ /* following cases: */+ /* */+ /* - Errors (in which case it returns FALSE). */+ /* */+ /* - Reaching the end of the main code range (returns TRUE). */+ /* Reaching the end of a code range within a function call is an */+ /* error. */+ /* */+ /* - After executing one single opcode, if the flag `Instruction_Trap' */+ /* is set to TRUE (returns TRUE). */+ /* */+ /* On exit with TRUE, test IP < CodeSize to know whether it comes from */+ /* an instruction trap or a normal termination. */+ /* */+ /* */+ /* Note: The documented DEBUG opcode pops a value from the stack. This */+ /* behaviour is unsupported; here a DEBUG opcode is always an */+ /* error. */+ /* */+ /* */+ /* THIS IS THE INTERPRETER'S MAIN LOOP. */+ /* */+ /* Instructions appear in the specification's order. */+ /* */+ /*************************************************************************/+++ /* documentation is in ttinterp.h */++ FT_EXPORT_DEF( FT_Error )+ TT_RunIns( TT_ExecContext exc )+ {+ FT_Long ins_counter = 0; /* executed instructions counter */+++#ifdef TT_CONFIG_OPTION_STATIC_RASTER+ cur = *exc;+#endif++ /* set CVT functions */+ CUR.tt_metrics.ratio = 0;+ if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem )+ {+ /* non-square pixels, use the stretched routines */+ CUR.func_read_cvt = Read_CVT_Stretched;+ CUR.func_write_cvt = Write_CVT_Stretched;+ CUR.func_move_cvt = Move_CVT_Stretched;+ }+ else+ {+ /* square pixels, use normal routines */+ CUR.func_read_cvt = Read_CVT;+ CUR.func_write_cvt = Write_CVT;+ CUR.func_move_cvt = Move_CVT;+ }++ COMPUTE_Funcs();+ COMPUTE_Round( (FT_Byte)exc->GS.round_state );++ do+ {+ CUR.opcode = CUR.code[CUR.IP];++ FT_TRACE7(( " " ));+ FT_TRACE7(( opcode_name[CUR.opcode] ));+ FT_TRACE7(( "\n" ));++ if ( ( CUR.length = opcode_length[CUR.opcode] ) < 0 )+ {+ if ( CUR.IP + 1 > CUR.codeSize )+ goto LErrorCodeOverflow_;++ CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];+ }++ if ( CUR.IP + CUR.length > CUR.codeSize )+ goto LErrorCodeOverflow_;++ /* First, let's check for empty stack and overflow */+ CUR.args = CUR.top - ( Pop_Push_Count[CUR.opcode] >> 4 );++ /* `args' is the top of the stack once arguments have been popped. */+ /* One can also interpret it as the index of the last argument. */+ if ( CUR.args < 0 )+ {+ CUR.error = TT_Err_Too_Few_Arguments;+ goto LErrorLabel_;+ }++ CUR.new_top = CUR.args + ( Pop_Push_Count[CUR.opcode] & 15 );++ /* `new_top' is the new top of the stack, after the instruction's */+ /* execution. `top' will be set to `new_top' after the `switch' */+ /* statement. */+ if ( CUR.new_top > CUR.stackSize )+ {+ CUR.error = TT_Err_Stack_Overflow;+ goto LErrorLabel_;+ }++ CUR.step_ins = TRUE;+ CUR.error = TT_Err_Ok;++#ifdef TT_CONFIG_OPTION_INTERPRETER_SWITCH++ {+ FT_Long* args = CUR.stack + CUR.args;+ FT_Byte opcode = CUR.opcode;+++#undef ARRAY_BOUND_ERROR+#define ARRAY_BOUND_ERROR goto Set_Invalid_Ref+++ switch ( opcode )+ {+ case 0x00: /* SVTCA y */+ case 0x01: /* SVTCA x */+ case 0x02: /* SPvTCA y */+ case 0x03: /* SPvTCA x */+ case 0x04: /* SFvTCA y */+ case 0x05: /* SFvTCA x */+ {+ FT_Short AA, BB;+++ AA = (FT_Short)( ( opcode & 1 ) << 14 );+ BB = (FT_Short)( AA ^ 0x4000 );++ if ( opcode < 4 )+ {+ CUR.GS.projVector.x = AA;+ CUR.GS.projVector.y = BB;++ CUR.GS.dualVector.x = AA;+ CUR.GS.dualVector.y = BB;+ }+ else+ {+ GUESS_VECTOR( projVector );+ }++ if ( ( opcode & 2 ) == 0 )+ {+ CUR.GS.freeVector.x = AA;+ CUR.GS.freeVector.y = BB;+ }+ else+ {+ GUESS_VECTOR( freeVector );+ }++ COMPUTE_Funcs();+ }+ break;++ case 0x06: /* SPvTL // */+ case 0x07: /* SPvTL + */+ DO_SPVTL+ break;++ case 0x08: /* SFvTL // */+ case 0x09: /* SFvTL + */+ DO_SFVTL+ break;++ case 0x0A: /* SPvFS */+ DO_SPVFS+ break;++ case 0x0B: /* SFvFS */+ DO_SFVFS+ break;++ case 0x0C: /* GPV */+ DO_GPV+ break;++ case 0x0D: /* GFV */+ DO_GFV+ break;++ case 0x0E: /* SFvTPv */+ DO_SFVTPV+ break;++ case 0x0F: /* ISECT */+ Ins_ISECT( EXEC_ARG_ args );+ break;++ case 0x10: /* SRP0 */+ DO_SRP0+ break;++ case 0x11: /* SRP1 */+ DO_SRP1+ break;++ case 0x12: /* SRP2 */+ DO_SRP2+ break;++ case 0x13: /* SZP0 */+ Ins_SZP0( EXEC_ARG_ args );+ break;++ case 0x14: /* SZP1 */+ Ins_SZP1( EXEC_ARG_ args );+ break;++ case 0x15: /* SZP2 */+ Ins_SZP2( EXEC_ARG_ args );+ break;++ case 0x16: /* SZPS */+ Ins_SZPS( EXEC_ARG_ args );+ break;++ case 0x17: /* SLOOP */+ DO_SLOOP+ break;++ case 0x18: /* RTG */+ DO_RTG+ break;++ case 0x19: /* RTHG */+ DO_RTHG+ break;++ case 0x1A: /* SMD */+ DO_SMD+ break;++ case 0x1B: /* ELSE */+ Ins_ELSE( EXEC_ARG_ args );+ break;++ case 0x1C: /* JMPR */+ DO_JMPR+ break;++ case 0x1D: /* SCVTCI */+ DO_SCVTCI+ break;++ case 0x1E: /* SSWCI */+ DO_SSWCI+ break;++ case 0x1F: /* SSW */+ DO_SSW+ break;++ case 0x20: /* DUP */+ DO_DUP+ break;++ case 0x21: /* POP */+ /* nothing :-) */+ break;++ case 0x22: /* CLEAR */+ DO_CLEAR+ break;++ case 0x23: /* SWAP */+ DO_SWAP+ break;++ case 0x24: /* DEPTH */+ DO_DEPTH+ break;++ case 0x25: /* CINDEX */+ DO_CINDEX+ break;++ case 0x26: /* MINDEX */+ Ins_MINDEX( EXEC_ARG_ args );+ break;++ case 0x27: /* ALIGNPTS */+ Ins_ALIGNPTS( EXEC_ARG_ args );+ break;++ case 0x28: /* ???? */+ Ins_UNKNOWN( EXEC_ARG_ args );+ break;++ case 0x29: /* UTP */+ Ins_UTP( EXEC_ARG_ args );+ break;++ case 0x2A: /* LOOPCALL */+ Ins_LOOPCALL( EXEC_ARG_ args );+ break;++ case 0x2B: /* CALL */+ Ins_CALL( EXEC_ARG_ args );+ break;++ case 0x2C: /* FDEF */+ Ins_FDEF( EXEC_ARG_ args );+ break;++ case 0x2D: /* ENDF */+ Ins_ENDF( EXEC_ARG_ args );+ break;++ case 0x2E: /* MDAP */+ case 0x2F: /* MDAP */+ Ins_MDAP( EXEC_ARG_ args );+ break;+++ case 0x30: /* IUP */+ case 0x31: /* IUP */+ Ins_IUP( EXEC_ARG_ args );+ break;++ case 0x32: /* SHP */+ case 0x33: /* SHP */+ Ins_SHP( EXEC_ARG_ args );+ break;++ case 0x34: /* SHC */+ case 0x35: /* SHC */+ Ins_SHC( EXEC_ARG_ args );+ break;++ case 0x36: /* SHZ */+ case 0x37: /* SHZ */+ Ins_SHZ( EXEC_ARG_ args );+ break;++ case 0x38: /* SHPIX */+ Ins_SHPIX( EXEC_ARG_ args );+ break;++ case 0x39: /* IP */+ Ins_IP( EXEC_ARG_ args );+ break;++ case 0x3A: /* MSIRP */+ case 0x3B: /* MSIRP */+ Ins_MSIRP( EXEC_ARG_ args );+ break;++ case 0x3C: /* AlignRP */+ Ins_ALIGNRP( EXEC_ARG_ args );+ break;++ case 0x3D: /* RTDG */+ DO_RTDG+ break;++ case 0x3E: /* MIAP */+ case 0x3F: /* MIAP */+ Ins_MIAP( EXEC_ARG_ args );+ break;++ case 0x40: /* NPUSHB */+ Ins_NPUSHB( EXEC_ARG_ args );+ break;++ case 0x41: /* NPUSHW */+ Ins_NPUSHW( EXEC_ARG_ args );+ break;++ case 0x42: /* WS */+ DO_WS+ break;++ Set_Invalid_Ref:+ CUR.error = TT_Err_Invalid_Reference;+ break;++ case 0x43: /* RS */+ DO_RS+ break;++ case 0x44: /* WCVTP */+ DO_WCVTP+ break;++ case 0x45: /* RCVT */+ DO_RCVT+ break;++ case 0x46: /* GC */+ case 0x47: /* GC */+ Ins_GC( EXEC_ARG_ args );+ break;++ case 0x48: /* SCFS */+ Ins_SCFS( EXEC_ARG_ args );+ break;++ case 0x49: /* MD */+ case 0x4A: /* MD */+ Ins_MD( EXEC_ARG_ args );+ break;++ case 0x4B: /* MPPEM */+ DO_MPPEM+ break;++ case 0x4C: /* MPS */+ DO_MPS+ break;++ case 0x4D: /* FLIPON */+ DO_FLIPON+ break;++ case 0x4E: /* FLIPOFF */+ DO_FLIPOFF+ break;++ case 0x4F: /* DEBUG */+ DO_DEBUG+ break;++ case 0x50: /* LT */+ DO_LT+ break;++ case 0x51: /* LTEQ */+ DO_LTEQ+ break;++ case 0x52: /* GT */+ DO_GT+ break;++ case 0x53: /* GTEQ */+ DO_GTEQ+ break;++ case 0x54: /* EQ */+ DO_EQ+ break;++ case 0x55: /* NEQ */+ DO_NEQ+ break;++ case 0x56: /* ODD */+ DO_ODD+ break;++ case 0x57: /* EVEN */+ DO_EVEN+ break;++ case 0x58: /* IF */+ Ins_IF( EXEC_ARG_ args );+ break;++ case 0x59: /* EIF */+ /* do nothing */+ break;++ case 0x5A: /* AND */+ DO_AND+ break;++ case 0x5B: /* OR */+ DO_OR+ break;++ case 0x5C: /* NOT */+ DO_NOT+ break;++ case 0x5D: /* DELTAP1 */+ Ins_DELTAP( EXEC_ARG_ args );+ break;++ case 0x5E: /* SDB */+ DO_SDB+ break;++ case 0x5F: /* SDS */+ DO_SDS+ break;++ case 0x60: /* ADD */+ DO_ADD+ break;++ case 0x61: /* SUB */+ DO_SUB+ break;++ case 0x62: /* DIV */+ DO_DIV+ break;++ case 0x63: /* MUL */+ DO_MUL+ break;++ case 0x64: /* ABS */+ DO_ABS+ break;++ case 0x65: /* NEG */+ DO_NEG+ break;++ case 0x66: /* FLOOR */+ DO_FLOOR+ break;++ case 0x67: /* CEILING */+ DO_CEILING+ break;++ case 0x68: /* ROUND */+ case 0x69: /* ROUND */+ case 0x6A: /* ROUND */+ case 0x6B: /* ROUND */+ DO_ROUND+ break;++ case 0x6C: /* NROUND */+ case 0x6D: /* NROUND */+ case 0x6E: /* NRRUND */+ case 0x6F: /* NROUND */+ DO_NROUND+ break;++ case 0x70: /* WCVTF */+ DO_WCVTF+ break;++ case 0x71: /* DELTAP2 */+ case 0x72: /* DELTAP3 */+ Ins_DELTAP( EXEC_ARG_ args );+ break;++ case 0x73: /* DELTAC0 */+ case 0x74: /* DELTAC1 */+ case 0x75: /* DELTAC2 */+ Ins_DELTAC( EXEC_ARG_ args );+ break;++ case 0x76: /* SROUND */+ DO_SROUND+ break;++ case 0x77: /* S45Round */+ DO_S45ROUND+ break;++ case 0x78: /* JROT */+ DO_JROT+ break;++ case 0x79: /* JROF */+ DO_JROF+ break;++ case 0x7A: /* ROFF */+ DO_ROFF+ break;++ case 0x7B: /* ???? */+ Ins_UNKNOWN( EXEC_ARG_ args );+ break;++ case 0x7C: /* RUTG */+ DO_RUTG+ break;++ case 0x7D: /* RDTG */+ DO_RDTG+ break;++ case 0x7E: /* SANGW */+ case 0x7F: /* AA */+ /* nothing - obsolete */+ break;++ case 0x80: /* FLIPPT */+ Ins_FLIPPT( EXEC_ARG_ args );+ break;++ case 0x81: /* FLIPRGON */+ Ins_FLIPRGON( EXEC_ARG_ args );+ break;++ case 0x82: /* FLIPRGOFF */+ Ins_FLIPRGOFF( EXEC_ARG_ args );+ break;++ case 0x83: /* UNKNOWN */+ case 0x84: /* UNKNOWN */+ Ins_UNKNOWN( EXEC_ARG_ args );+ break;++ case 0x85: /* SCANCTRL */+ Ins_SCANCTRL( EXEC_ARG_ args );+ break;++ case 0x86: /* SDPVTL */+ case 0x87: /* SDPVTL */+ Ins_SDPVTL( EXEC_ARG_ args );+ break;++ case 0x88: /* GETINFO */+ Ins_GETINFO( EXEC_ARG_ args );+ break;++ case 0x89: /* IDEF */+ Ins_IDEF( EXEC_ARG_ args );+ break;++ case 0x8A: /* ROLL */+ Ins_ROLL( EXEC_ARG_ args );+ break;++ case 0x8B: /* MAX */+ DO_MAX+ break;++ case 0x8C: /* MIN */+ DO_MIN+ break;++ case 0x8D: /* SCANTYPE */+ Ins_SCANTYPE( EXEC_ARG_ args );+ break;++ case 0x8E: /* INSTCTRL */+ Ins_INSTCTRL( EXEC_ARG_ args );+ break;++ case 0x8F:+ Ins_UNKNOWN( EXEC_ARG_ args );+ break;++ default:+ if ( opcode >= 0xE0 )+ Ins_MIRP( EXEC_ARG_ args );+ else if ( opcode >= 0xC0 )+ Ins_MDRP( EXEC_ARG_ args );+ else if ( opcode >= 0xB8 )+ Ins_PUSHW( EXEC_ARG_ args );+ else if ( opcode >= 0xB0 )+ Ins_PUSHB( EXEC_ARG_ args );+ else+ Ins_UNKNOWN( EXEC_ARG_ args );+ }++ }++#else++ Instruct_Dispatch[CUR.opcode]( EXEC_ARG_ &CUR.stack[CUR.args] );++#endif /* TT_CONFIG_OPTION_INTERPRETER_SWITCH */++ if ( CUR.error != TT_Err_Ok )+ {+ switch ( CUR.error )+ {+ case TT_Err_Invalid_Opcode: /* looking for redefined instructions */+ {+ TT_DefRecord* def = CUR.IDefs;+ TT_DefRecord* limit = def + CUR.numIDefs;+++ for ( ; def < limit; def++ )+ {+ if ( def->active && CUR.opcode == (FT_Byte)def->opc )+ {+ TT_CallRec* callrec;+++ if ( CUR.callTop >= CUR.callSize )+ {+ CUR.error = TT_Err_Invalid_Reference;+ goto LErrorLabel_;+ }++ callrec = &CUR.callStack[CUR.callTop];++ callrec->Caller_Range = CUR.curRange;+ callrec->Caller_IP = CUR.IP + 1;+ callrec->Cur_Count = 1;+ callrec->Cur_Restart = def->start;++ if ( INS_Goto_CodeRange( def->range, def->start ) == FAILURE )+ goto LErrorLabel_;++ goto LSuiteLabel_;+ }+ }+ }++ CUR.error = TT_Err_Invalid_Opcode;+ goto LErrorLabel_;++#if 0+ break; /* Unreachable code warning suppression. */+ /* Leave to remind in case a later change the editor */+ /* to consider break; */+#endif++ default:+ goto LErrorLabel_;++#if 0+ break;+#endif+ }+ }++ CUR.top = CUR.new_top;++ if ( CUR.step_ins )+ CUR.IP += CUR.length;++ /* 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 )+ return TT_Err_Execution_Too_Long;++ LSuiteLabel_:+ if ( CUR.IP >= CUR.codeSize )+ {+ if ( CUR.callTop > 0 )+ {+ CUR.error = TT_Err_Code_Overflow;+ goto LErrorLabel_;+ }+ else+ goto LNo_Error_;+ }+ } while ( !CUR.instruction_trap );++ LNo_Error_:++#ifdef TT_CONFIG_OPTION_STATIC_RASTER+ *exc = cur;+#endif++ return TT_Err_Ok;++ LErrorCodeOverflow_:+ CUR.error = TT_Err_Code_Overflow;++ LErrorLabel_:++#ifdef TT_CONFIG_OPTION_STATIC_RASTER+ *exc = cur;+#endif++ /* If any errors have occurred, function tables may be broken. */+ /* Force a re-execution of `prep' and `fpgm' tables if no */+ /* bytecode debugger is run. */+ if ( CUR.error && !CUR.instruction_trap )+ {+ FT_TRACE1(( " The interpreter returned error 0x%x\n", CUR.error ));+ exc->size->cvt_ready = FALSE; + }++ return CUR.error;+ }+++#endif /* TT_USE_BYTECODE_INTERPRETER */+++/* END */
+ src/truetype/ttinterp.h view
@@ -0,0 +1,319 @@+/***************************************************************************/+/* */+/* ttinterp.h */+/* */+/* TrueType bytecode interpreter (specification). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2010 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 __TTINTERP_H__+#define __TTINTERP_H__++#include <ft2build.h>+#include "ttobjs.h"+++FT_BEGIN_HEADER+++#ifndef TT_CONFIG_OPTION_STATIC_INTERPRETER /* indirect implementation */++#define EXEC_OP_ TT_ExecContext exc,+#define EXEC_OP TT_ExecContext exc+#define EXEC_ARG_ exc,+#define EXEC_ARG exc++#else /* static implementation */++#define EXEC_OP_ /* void */+#define EXEC_OP /* void */+#define EXEC_ARG_ /* void */+#define EXEC_ARG /* void */++#endif /* TT_CONFIG_OPTION_STATIC_INTERPRETER */+++ /*************************************************************************/+ /* */+ /* Rounding mode constants. */+ /* */+#define TT_Round_Off 5+#define TT_Round_To_Half_Grid 0+#define TT_Round_To_Grid 1+#define TT_Round_To_Double_Grid 2+#define TT_Round_Up_To_Grid 4+#define TT_Round_Down_To_Grid 3+#define TT_Round_Super 6+#define TT_Round_Super_45 7+++ /*************************************************************************/+ /* */+ /* Function types used by the interpreter, depending on various modes */+ /* (e.g. the rounding mode, whether to render a vertical or horizontal */+ /* line etc). */+ /* */+ /*************************************************************************/++ /* Rounding function */+ typedef FT_F26Dot6+ (*TT_Round_Func)( EXEC_OP_ FT_F26Dot6 distance,+ FT_F26Dot6 compensation );++ /* Point displacement along the freedom vector routine */+ typedef void+ (*TT_Move_Func)( EXEC_OP_ TT_GlyphZone zone,+ FT_UShort point,+ FT_F26Dot6 distance );++ /* Distance projection along one of the projection vectors */+ typedef FT_F26Dot6+ (*TT_Project_Func)( EXEC_OP_ FT_Pos dx,+ FT_Pos dy );++ /* reading a cvt value. Take care of non-square pixels if necessary */+ typedef FT_F26Dot6+ (*TT_Get_CVT_Func)( EXEC_OP_ FT_ULong idx );++ /* setting or moving a cvt value. Take care of non-square pixels */+ /* if necessary */+ typedef void+ (*TT_Set_CVT_Func)( EXEC_OP_ FT_ULong idx,+ FT_F26Dot6 value );+++ /*************************************************************************/+ /* */+ /* This structure defines a call record, used to manage function calls. */+ /* */+ typedef struct TT_CallRec_+ {+ FT_Int Caller_Range;+ FT_Long Caller_IP;+ FT_Long Cur_Count;+ FT_Long Cur_Restart;++ } TT_CallRec, *TT_CallStack;+++ /*************************************************************************/+ /* */+ /* The main structure for the interpreter which collects all necessary */+ /* variables and states. */+ /* */+ typedef struct TT_ExecContextRec_+ {+ TT_Face face;+ TT_Size size;+ FT_Memory memory;++ /* instructions state */++ FT_Error error; /* last execution error */++ FT_Long top; /* top of exec. stack */++ FT_UInt stackSize; /* size of exec. stack */+ FT_Long* stack; /* current exec. stack */++ FT_Long args;+ FT_UInt new_top; /* new top after exec. */++ TT_GlyphZoneRec zp0, /* zone records */+ zp1,+ zp2,+ pts,+ twilight;++ FT_Size_Metrics metrics;+ TT_Size_Metrics tt_metrics; /* size metrics */++ TT_GraphicsState GS; /* current graphics state */++ FT_Int curRange; /* current code range number */+ FT_Byte* code; /* current code range */+ FT_Long IP; /* current instruction pointer */+ FT_Long codeSize; /* size of current range */++ FT_Byte opcode; /* current opcode */+ FT_Int length; /* length of current opcode */++ FT_Bool step_ins; /* true if the interpreter must */+ /* increment IP after ins. exec */+ FT_ULong cvtSize;+ FT_Long* cvt;++ FT_UInt glyphSize; /* glyph instructions buffer size */+ FT_Byte* glyphIns; /* glyph instructions buffer */++ FT_UInt numFDefs; /* number of function defs */+ FT_UInt maxFDefs; /* maximum number of function defs */+ TT_DefArray FDefs; /* table of FDefs entries */++ FT_UInt numIDefs; /* number of instruction defs */+ FT_UInt maxIDefs; /* maximum number of ins defs */+ TT_DefArray IDefs; /* table of IDefs entries */++ FT_UInt maxFunc; /* maximum function index */+ FT_UInt maxIns; /* maximum instruction index */++ FT_Int callTop, /* top of call stack during execution */+ callSize; /* size of call stack */+ TT_CallStack callStack; /* call stack */++ FT_UShort maxPoints; /* capacity of this context's `pts' */+ FT_Short maxContours; /* record, expressed in points and */+ /* contours. */++ TT_CodeRangeTable codeRangeTable; /* table of valid code ranges */+ /* useful for the debugger */++ FT_UShort storeSize; /* size of current storage */+ FT_Long* storage; /* storage area */++ FT_F26Dot6 period; /* values used for the */+ FT_F26Dot6 phase; /* `SuperRounding' */+ FT_F26Dot6 threshold;++#if 0+ /* this seems to be unused */+ FT_Int cur_ppem; /* ppem along the current proj vector */+#endif++ FT_Bool instruction_trap; /* If `True', the interpreter will */+ /* exit after each instruction */++ TT_GraphicsState default_GS; /* graphics state resulting from */+ /* the prep program */+ FT_Bool is_composite; /* true if the glyph is composite */+ FT_Bool pedantic_hinting; /* true if pedantic interpretation */++ /* latest interpreter additions */++ FT_Long F_dot_P; /* dot product of freedom and projection */+ /* vectors */+ TT_Round_Func func_round; /* current rounding function */++ TT_Project_Func func_project, /* current projection function */+ func_dualproj, /* current dual proj. function */+ func_freeProj; /* current freedom proj. func */++ TT_Move_Func func_move; /* current point move function */+ TT_Move_Func func_move_orig; /* move original position function */++ TT_Get_CVT_Func func_read_cvt; /* read a cvt entry */+ TT_Set_CVT_Func func_write_cvt; /* write a cvt entry (in pixels) */+ TT_Set_CVT_Func func_move_cvt; /* incr a cvt entry (in pixels) */++ FT_Bool grayscale; /* are we hinting for grayscale? */++ } TT_ExecContextRec;+++ extern const TT_GraphicsState tt_default_graphics_state;+++ FT_LOCAL( FT_Error )+ TT_Goto_CodeRange( TT_ExecContext exec,+ FT_Int range,+ FT_Long IP );++ FT_LOCAL( FT_Error )+ TT_Set_CodeRange( TT_ExecContext exec,+ FT_Int range,+ void* base,+ FT_Long length );++ FT_LOCAL( FT_Error )+ TT_Clear_CodeRange( TT_ExecContext exec,+ FT_Int range );+++ FT_LOCAL( FT_Error )+ Update_Max( FT_Memory memory,+ FT_ULong* size,+ FT_Long multiplier,+ void* _pbuff,+ FT_ULong new_max );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* TT_New_Context */+ /* */+ /* <Description> */+ /* Queries the face context for a given font. Note that there is */+ /* now a _single_ execution context in the TrueType driver which is */+ /* shared among faces. */+ /* */+ /* <Input> */+ /* face :: A handle to the source face object. */+ /* */+ /* <Return> */+ /* A handle to the execution context. Initialized for `face'. */+ /* */+ /* <Note> */+ /* Only the glyph loader and debugger should call this function. */+ /* */+ FT_EXPORT( TT_ExecContext )+ TT_New_Context( TT_Driver driver );++ FT_LOCAL( FT_Error )+ TT_Done_Context( TT_ExecContext exec );++ FT_LOCAL( FT_Error )+ TT_Load_Context( TT_ExecContext exec,+ TT_Face face,+ TT_Size size );++ FT_LOCAL( FT_Error )+ TT_Save_Context( TT_ExecContext exec,+ TT_Size ins );++ FT_LOCAL( FT_Error )+ TT_Run_Context( TT_ExecContext exec,+ FT_Bool debug );+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* TT_RunIns */+ /* */+ /* <Description> */+ /* Executes one or more instruction in the execution context. This */+ /* is the main function of the TrueType opcode interpreter. */+ /* */+ /* <Input> */+ /* exec :: A handle to the target execution context. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ /* <Note> */+ /* Only the object manager and debugger should call this function. */+ /* */+ /* This function is publicly exported because it is directly */+ /* invoked by the TrueType debugger. */+ /* */+ FT_EXPORT( FT_Error )+ TT_RunIns( TT_ExecContext exec );+++FT_END_HEADER++#endif /* __TTINTERP_H__ */+++/* END */
+ src/truetype/ttobjs.c view
@@ -0,0 +1,1135 @@+/***************************************************************************/+/* */+/* ttobjs.c */+/* */+/* Objects manager (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */+/* 2010 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_STREAM_H+#include FT_TRUETYPE_TAGS_H+#include FT_INTERNAL_SFNT_H++#include "ttgload.h"+#include "ttpload.h"++#include "tterrors.h"++#ifdef TT_USE_BYTECODE_INTERPRETER+#include "ttinterp.h"+#endif++#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING+#include FT_TRUETYPE_UNPATENTED_H+#endif++#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT+#include "ttgxvar.h"+#endif++ /*************************************************************************/+ /* */+ /* 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_ttobjs+++#ifdef TT_USE_BYTECODE_INTERPRETER++ /*************************************************************************/+ /* */+ /* GLYPH ZONE FUNCTIONS */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_glyphzone_done */+ /* */+ /* <Description> */+ /* Deallocate a glyph zone. */+ /* */+ /* <Input> */+ /* zone :: A pointer to the target glyph zone. */+ /* */+ FT_LOCAL_DEF( void )+ tt_glyphzone_done( TT_GlyphZone zone )+ {+ FT_Memory memory = zone->memory;+++ if ( memory )+ {+ FT_FREE( zone->contours );+ FT_FREE( zone->tags );+ FT_FREE( zone->cur );+ FT_FREE( zone->org );+ FT_FREE( zone->orus );++ zone->max_points = zone->n_points = 0;+ zone->max_contours = zone->n_contours = 0;+ zone->memory = NULL;+ }+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_glyphzone_new */+ /* */+ /* <Description> */+ /* Allocate a new glyph zone. */+ /* */+ /* <Input> */+ /* memory :: A handle to the current memory object. */+ /* */+ /* maxPoints :: The capacity of glyph zone in points. */+ /* */+ /* maxContours :: The capacity of glyph zone in contours. */+ /* */+ /* <Output> */+ /* zone :: A pointer to the target glyph zone record. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ tt_glyphzone_new( FT_Memory memory,+ FT_UShort maxPoints,+ FT_Short maxContours,+ TT_GlyphZone zone )+ {+ FT_Error error;+++ FT_MEM_ZERO( zone, sizeof ( *zone ) );+ zone->memory = memory;++ if ( FT_NEW_ARRAY( zone->org, maxPoints ) ||+ FT_NEW_ARRAY( zone->cur, maxPoints ) ||+ FT_NEW_ARRAY( zone->orus, maxPoints ) ||+ FT_NEW_ARRAY( zone->tags, maxPoints ) ||+ FT_NEW_ARRAY( zone->contours, maxContours ) )+ {+ tt_glyphzone_done( zone );+ }+ else+ {+ zone->max_points = maxPoints;+ zone->max_contours = maxContours;+ }++ return error;+ }+#endif /* TT_USE_BYTECODE_INTERPRETER */+++ /* Compare the face with a list of well-known `tricky' fonts. */+ /* This list shall be expanded as we find more of them. */++ static FT_Bool+ tt_check_trickyness_family( FT_String* name )+ {++#define TRICK_NAMES_MAX_CHARACTERS 16+#define TRICK_NAMES_COUNT 8++ static const char trick_names[TRICK_NAMES_COUNT]+ [TRICK_NAMES_MAX_CHARACTERS + 1] =+ {+ "DFKaiSho-SB", /* dfkaisb.ttf */+ "DFKaiShu",+ "DFKai-SB", /* kaiu.ttf */+ "HuaTianKaiTi?", /* htkt2.ttf */+ "HuaTianSongTi?", /* htst3.ttf */+ "MingLiU", /* mingliu.ttf & mingliu.ttc */+ "PMingLiU", /* mingliu.ttc */+ "MingLi43", /* mingli.ttf */+ };++ int nn;+++ for ( nn = 0; nn < TRICK_NAMES_COUNT; nn++ )+ if ( ft_strstr( name, trick_names[nn] ) )+ return TRUE;++ return FALSE;+ }+++ /* XXX: This function should be in the `sfnt' module. */++ /* Some PDF generators clear the checksums in the TrueType header table. */+ /* For example, Quartz ContextPDF clears all entries, or Bullzip PDF */+ /* Printer clears the entries for subsetted subtables. We thus have to */+ /* recalculate the checksums where necessary. */++ static FT_UInt32+ tt_synth_sfnt_checksum( FT_Stream stream,+ FT_ULong length )+ {+ FT_Error error;+ FT_UInt32 checksum = 0;+ int i;+++ if ( FT_FRAME_ENTER( length ) )+ return 0;++ 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 ) );++ FT_FRAME_EXIT();++ return checksum;+ }+++ /* XXX: This function should be in the `sfnt' module. */++ static FT_ULong+ tt_get_sfnt_checksum( TT_Face face,+ FT_UShort i )+ {+ if ( face->dir_tables[i].CheckSum )+ return face->dir_tables[i].CheckSum;++ else if ( !face->goto_table )+ return 0;++ else if ( !face->goto_table( face,+ face->dir_tables[i].Tag,+ face->root.stream,+ NULL ) )+ return 0;++ return (FT_ULong)tt_synth_sfnt_checksum( face->root.stream,+ face->dir_tables[i].Length );+ }+++ typedef struct tt_sfnt_id_rec_+ {+ FT_ULong CheckSum;+ FT_ULong Length;++ } tt_sfnt_id_rec;+++ static FT_Bool+ tt_check_trickyness_sfnt_ids( TT_Face face )+ {+#define TRICK_SFNT_IDS_PER_FACE 3+#define TRICK_SFNT_IDS_NUM_FACES 5++ static const tt_sfnt_id_rec sfnt_id[TRICK_SFNT_IDS_NUM_FACES]+ [TRICK_SFNT_IDS_PER_FACE] = {++#define TRICK_SFNT_ID_cvt 0+#define TRICK_SFNT_ID_fpgm 1+#define TRICK_SFNT_ID_prep 2++ { /* MingLiU 1995 */+ { 0x05bcf058, 0x000002e4 }, /* cvt */+ { 0x28233bf1, 0x000087c4 }, /* fpgm */+ { 0xa344a1ea, 0x000001e1 } /* prep */+ },+ { /* MingLiU 1996- */+ { 0x05bcf058, 0x000002e4 }, /* cvt */+ { 0x28233bf1, 0x000087c4 }, /* fpgm */+ { 0xa344a1eb, 0x000001e1 } /* prep */+ },+ { /* DFKaiShu */+ { 0x11e5ead4, 0x00000350 }, /* cvt */+ { 0x5a30ca3b, 0x00009063 }, /* fpgm */+ { 0x13a42602, 0x0000007e } /* prep */+ },+ { /* HuaTianKaiTi */+ { 0xfffbfffc, 0x00000008 }, /* cvt */+ { 0x9c9e48b8, 0x0000bea2 }, /* fpgm */+ { 0x70020112, 0x00000008 } /* prep */+ },+ { /* HuaTianSongTi */+ { 0xfffbfffc, 0x00000008 }, /* cvt */+ { 0x0a5a0483, 0x00017c39 }, /* fpgm */+ { 0x70020112, 0x00000008 } /* prep */+ }+ };++ FT_ULong checksum;+ int num_matched_ids[TRICK_SFNT_IDS_NUM_FACES];+ int i, j, k;+++ FT_MEM_SET( num_matched_ids, 0,+ sizeof( int ) * TRICK_SFNT_IDS_NUM_FACES );++ for ( i = 0; i < face->num_tables; i++ )+ {+ checksum = 0;++ switch( face->dir_tables[i].Tag )+ {+ case TTAG_cvt:+ k = TRICK_SFNT_ID_cvt;+ break;++ case TTAG_fpgm:+ k = TRICK_SFNT_ID_fpgm;+ break;++ case TTAG_prep:+ k = TRICK_SFNT_ID_prep;+ break;++ default:+ continue;+ }++ for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ )+ if ( face->dir_tables[i].Length == sfnt_id[j][k].Length )+ {+ if ( !checksum )+ checksum = tt_get_sfnt_checksum( face, i );++ if ( sfnt_id[j][k].CheckSum == checksum )+ num_matched_ids[j]++;++ if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE )+ return TRUE;+ }+ }++ return FALSE;+ }+++ static FT_Bool+ tt_check_trickyness( FT_Face face )+ {+ if ( !face )+ return FALSE;++ /* First, check the face name. */+ if ( face->family_name )+ {+ if ( tt_check_trickyness_family( face->family_name ) )+ return TRUE;+ else+ return FALSE;+ }++ /* Type42 fonts may lack `name' tables, we thus try to identify */+ /* tricky fonts by checking the checksums of Type42-persistent */+ /* sfnt tables (`cvt', `fpgm', and `prep'). */+ if ( tt_check_trickyness_sfnt_ids( (TT_Face)face ) )+ return TRUE;++ return FALSE;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_face_init */+ /* */+ /* <Description> */+ /* Initialize a given TrueType face object. */+ /* */+ /* <Input> */+ /* stream :: The source font stream. */+ /* */+ /* face_index :: The index of the font face in the resource. */+ /* */+ /* num_params :: Number of additional generic parameters. Ignored. */+ /* */+ /* params :: Additional generic parameters. Ignored. */+ /* */+ /* <InOut> */+ /* face :: The newly built face object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ tt_face_init( FT_Stream stream,+ FT_Face ttface, /* TT_Face */+ FT_Int face_index,+ FT_Int num_params,+ FT_Parameter* params )+ {+ FT_Error error;+ FT_Library library;+ SFNT_Service sfnt;+ TT_Face face = (TT_Face)ttface;+++ library = ttface->driver->root.library;+ sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" );+ if ( !sfnt )+ goto Bad_Format;++ /* create input stream from resource */+ if ( FT_STREAM_SEEK( 0 ) )+ goto Exit;++ /* check that we have a valid TrueType file */+ error = sfnt->init_face( stream, face, face_index, num_params, params );+ if ( error )+ goto Exit;++ /* We must also be able to accept Mac/GX fonts, as well as OT ones. */+ /* The 0x00020000 tag is completely undocumented; some fonts from */+ /* Arphic made for Chinese Windows 3.1 have this. */+ if ( face->format_tag != 0x00010000L && /* MS fonts */+ face->format_tag != 0x00020000L && /* CJK fonts for Win 3.1 */+ face->format_tag != TTAG_true ) /* Mac fonts */+ {+ FT_TRACE2(( "[not a valid TTF font]\n" ));+ goto Bad_Format;+ }++#ifdef TT_USE_BYTECODE_INTERPRETER+ ttface->face_flags |= FT_FACE_FLAG_HINTER;+#endif++ /* If we are performing a simple font format check, exit immediately. */+ if ( face_index < 0 )+ return TT_Err_Ok;++ /* Load font directory */+ error = sfnt->load_face( stream, face, face_index, num_params, params );+ if ( error )+ goto Exit;++ if ( tt_check_trickyness( ttface ) )+ ttface->face_flags |= FT_FACE_FLAG_TRICKY;++ error = tt_face_load_hdmx( face, stream );+ if ( error )+ goto Exit;++ if ( FT_IS_SCALABLE( ttface ) )+ {++#ifdef FT_CONFIG_OPTION_INCREMENTAL++ if ( !ttface->internal->incremental_interface )+ error = tt_face_load_loca( face, stream );+ if ( !error )+ error = tt_face_load_cvt( face, stream );+ if ( !error )+ error = tt_face_load_fpgm( face, stream );+ if ( !error )+ error = tt_face_load_prep( face, stream );++#else++ if ( !error )+ error = tt_face_load_loca( face, stream );+ if ( !error )+ error = tt_face_load_cvt( face, stream );+ if ( !error )+ error = tt_face_load_fpgm( face, stream );+ if ( !error )+ error = tt_face_load_prep( face, stream );++#endif++ }++#if defined( TT_CONFIG_OPTION_UNPATENTED_HINTING ) && \+ !defined( TT_CONFIG_OPTION_BYTECODE_INTERPRETER )++ {+ FT_Bool unpatented_hinting;+ int i;+++ /* Determine whether unpatented hinting is to be used for this face. */+ unpatented_hinting = FT_BOOL+ ( library->debug_hooks[FT_DEBUG_HOOK_UNPATENTED_HINTING] != NULL );++ for ( i = 0; i < num_params && !face->unpatented_hinting; i++ )+ if ( params[i].tag == FT_PARAM_TAG_UNPATENTED_HINTING )+ unpatented_hinting = TRUE;++ if ( !unpatented_hinting )+ ttface->internal->ignore_unpatented_hinter = TRUE;+ }++#endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING &&+ !TT_CONFIG_OPTION_BYTECODE_INTERPRETER */++ /* initialize standard glyph loading routines */+ TT_Init_Glyph_Loading( face );++ Exit:+ return error;++ Bad_Format:+ error = TT_Err_Unknown_File_Format;+ goto Exit;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_face_done */+ /* */+ /* <Description> */+ /* Finalize a given face object. */+ /* */+ /* <Input> */+ /* face :: A pointer to the face object to destroy. */+ /* */+ FT_LOCAL_DEF( void )+ tt_face_done( FT_Face ttface ) /* TT_Face */+ {+ TT_Face face = (TT_Face)ttface;+ FT_Memory memory;+ FT_Stream stream;+ SFNT_Service sfnt;+++ if ( !face )+ return;++ memory = ttface->memory;+ stream = ttface->stream;+ sfnt = (SFNT_Service)face->sfnt;++ /* for `extended TrueType formats' (i.e. compressed versions) */+ if ( face->extra.finalizer )+ face->extra.finalizer( face->extra.data );++ if ( sfnt )+ sfnt->done_face( face );++ /* freeing the locations table */+ tt_face_done_loca( face );++ tt_face_free_hdmx( face );++ /* freeing the CVT */+ FT_FREE( face->cvt );+ face->cvt_size = 0;++ /* freeing the programs */+ FT_FRAME_RELEASE( face->font_program );+ FT_FRAME_RELEASE( face->cvt_program );+ face->font_program_size = 0;+ face->cvt_program_size = 0;++#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT+ tt_done_blend( memory, face->blend );+ face->blend = NULL;+#endif+ }+++ /*************************************************************************/+ /* */+ /* SIZE FUNCTIONS */+ /* */+ /*************************************************************************/++#ifdef TT_USE_BYTECODE_INTERPRETER++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_size_run_fpgm */+ /* */+ /* <Description> */+ /* Run the font program. */+ /* */+ /* <Input> */+ /* size :: A handle to the size object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ tt_size_run_fpgm( TT_Size size )+ {+ TT_Face face = (TT_Face)size->root.face;+ TT_ExecContext exec;+ FT_Error error;+++ /* debugging instances have their own context */+ if ( size->debug )+ exec = size->context;+ else+ exec = ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;++ if ( !exec )+ return TT_Err_Could_Not_Find_Context;++ TT_Load_Context( exec, face, size );++ exec->callTop = 0;+ exec->top = 0;++ exec->period = 64;+ exec->phase = 0;+ exec->threshold = 0;++ exec->instruction_trap = FALSE;+ exec->F_dot_P = 0x10000L;++ {+ FT_Size_Metrics* metrics = &exec->metrics;+ TT_Size_Metrics* tt_metrics = &exec->tt_metrics;+++ metrics->x_ppem = 0;+ metrics->y_ppem = 0;+ metrics->x_scale = 0;+ metrics->y_scale = 0;++ tt_metrics->ppem = 0;+ tt_metrics->scale = 0;+ tt_metrics->ratio = 0x10000L;+ }++ /* allow font program execution */+ TT_Set_CodeRange( exec,+ tt_coderange_font,+ face->font_program,+ face->font_program_size );++ /* disable CVT and glyph programs coderange */+ TT_Clear_CodeRange( exec, tt_coderange_cvt );+ TT_Clear_CodeRange( exec, tt_coderange_glyph );++ if ( face->font_program_size > 0 )+ {+ error = TT_Goto_CodeRange( exec, tt_coderange_font, 0 );++ if ( !error )+ {+ FT_TRACE4(( "Executing `fpgm' table.\n" ));++ error = face->interpreter( exec );+ }+ }+ else+ error = TT_Err_Ok;++ if ( !error )+ TT_Save_Context( exec, size );++ return error;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_size_run_prep */+ /* */+ /* <Description> */+ /* Run the control value program. */+ /* */+ /* <Input> */+ /* size :: A handle to the size object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ tt_size_run_prep( TT_Size size )+ {+ TT_Face face = (TT_Face)size->root.face;+ TT_ExecContext exec;+ FT_Error error;+++ /* debugging instances have their own context */+ if ( size->debug )+ exec = size->context;+ else+ exec = ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;++ if ( !exec )+ return TT_Err_Could_Not_Find_Context;++ TT_Load_Context( exec, face, size );++ exec->callTop = 0;+ exec->top = 0;++ exec->instruction_trap = FALSE;++ TT_Set_CodeRange( exec,+ tt_coderange_cvt,+ face->cvt_program,+ face->cvt_program_size );++ TT_Clear_CodeRange( exec, tt_coderange_glyph );++ if ( face->cvt_program_size > 0 )+ {+ error = TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 );++ if ( !error && !size->debug )+ {+ FT_TRACE4(( "Executing `prep' table.\n" ));++ error = face->interpreter( exec );+ }+ }+ else+ error = TT_Err_Ok;++ /* save as default graphics state */+ size->GS = exec->GS;++ TT_Save_Context( exec, size );++ return error;+ }++#endif /* TT_USE_BYTECODE_INTERPRETER */+++#ifdef TT_USE_BYTECODE_INTERPRETER++ static void+ tt_size_done_bytecode( FT_Size ftsize )+ {+ TT_Size size = (TT_Size)ftsize;+ TT_Face face = (TT_Face)ftsize->face;+ FT_Memory memory = face->root.memory;+++ if ( size->debug )+ {+ /* the debug context must be deleted by the debugger itself */+ size->context = NULL;+ size->debug = FALSE;+ }++ FT_FREE( size->cvt );+ size->cvt_size = 0;++ /* free storage area */+ FT_FREE( size->storage );+ size->storage_size = 0;++ /* twilight zone */+ tt_glyphzone_done( &size->twilight );++ FT_FREE( size->function_defs );+ FT_FREE( size->instruction_defs );++ size->num_function_defs = 0;+ size->max_function_defs = 0;+ size->num_instruction_defs = 0;+ size->max_instruction_defs = 0;++ size->max_func = 0;+ size->max_ins = 0;++ size->bytecode_ready = 0;+ size->cvt_ready = 0;+ }+++ /* Initialize bytecode-related fields in the size object. */+ /* We do this only if bytecode interpretation is really needed. */+ static FT_Error+ tt_size_init_bytecode( FT_Size ftsize )+ {+ FT_Error error;+ TT_Size size = (TT_Size)ftsize;+ TT_Face face = (TT_Face)ftsize->face;+ FT_Memory memory = face->root.memory;+ FT_Int i;++ FT_UShort n_twilight;+ TT_MaxProfile* maxp = &face->max_profile;+++ size->bytecode_ready = 1;+ size->cvt_ready = 0;++ size->max_function_defs = maxp->maxFunctionDefs;+ size->max_instruction_defs = maxp->maxInstructionDefs;++ size->num_function_defs = 0;+ size->num_instruction_defs = 0;++ size->max_func = 0;+ size->max_ins = 0;++ size->cvt_size = face->cvt_size;+ size->storage_size = maxp->maxStorage;++ /* Set default metrics */+ {+ TT_Size_Metrics* metrics = &size->ttmetrics;+++ metrics->rotated = FALSE;+ metrics->stretched = FALSE;++ /* set default compensation (all 0) */+ for ( i = 0; i < 4; i++ )+ metrics->compensations[i] = 0;+ }++ /* allocate function defs, instruction defs, cvt, and storage area */+ if ( FT_NEW_ARRAY( size->function_defs, size->max_function_defs ) ||+ FT_NEW_ARRAY( size->instruction_defs, size->max_instruction_defs ) ||+ FT_NEW_ARRAY( size->cvt, size->cvt_size ) ||+ FT_NEW_ARRAY( size->storage, size->storage_size ) )+ goto Exit;++ /* reserve twilight zone */+ n_twilight = maxp->maxTwilightPoints;++ /* there are 4 phantom points (do we need this?) */+ n_twilight += 4;++ error = tt_glyphzone_new( memory, n_twilight, 0, &size->twilight );+ if ( error )+ goto Exit;++ size->twilight.n_points = n_twilight;++ size->GS = tt_default_graphics_state;++ /* set `face->interpreter' according to the debug hook present */+ {+ FT_Library library = face->root.driver->root.library;+++ face->interpreter = (TT_Interpreter)+ library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE];+ if ( !face->interpreter )+ face->interpreter = (TT_Interpreter)TT_RunIns;+ }++ /* Fine, now run the font program! */+ error = tt_size_run_fpgm( size );++ Exit:+ if ( error )+ tt_size_done_bytecode( ftsize );++ return error;+ }+++ FT_LOCAL_DEF( FT_Error )+ tt_size_ready_bytecode( TT_Size size )+ {+ FT_Error error = TT_Err_Ok;+++ if ( !size->bytecode_ready )+ {+ error = tt_size_init_bytecode( (FT_Size)size );+ if ( error )+ goto Exit;+ }++ /* rescale CVT when needed */+ if ( !size->cvt_ready )+ {+ FT_UInt i;+ TT_Face face = (TT_Face)size->root.face;+++ /* Scale the cvt values to the new ppem. */+ /* We use by default the y ppem to scale the CVT. */+ for ( i = 0; i < size->cvt_size; i++ )+ size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );++ /* all twilight points are originally zero */+ for ( i = 0; i < (FT_UInt)size->twilight.n_points; i++ )+ {+ size->twilight.org[i].x = 0;+ size->twilight.org[i].y = 0;+ size->twilight.cur[i].x = 0;+ size->twilight.cur[i].y = 0;+ }++ /* clear storage area */+ for ( i = 0; i < (FT_UInt)size->storage_size; i++ )+ size->storage[i] = 0;++ size->GS = tt_default_graphics_state;++ error = tt_size_run_prep( size );+ if ( !error )+ size->cvt_ready = 1;+ }++ Exit:+ return error;+ }++#endif /* TT_USE_BYTECODE_INTERPRETER */+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_size_init */+ /* */+ /* <Description> */+ /* Initialize a new TrueType size object. */+ /* */+ /* <InOut> */+ /* size :: A handle to the size object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ tt_size_init( FT_Size ttsize ) /* TT_Size */+ {+ TT_Size size = (TT_Size)ttsize;+ FT_Error error = TT_Err_Ok;++#ifdef TT_USE_BYTECODE_INTERPRETER+ size->bytecode_ready = 0;+ size->cvt_ready = 0;+#endif++ size->ttmetrics.valid = FALSE;+ size->strike_index = 0xFFFFFFFFUL;++ return error;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_size_done */+ /* */+ /* <Description> */+ /* The TrueType size object finalizer. */+ /* */+ /* <Input> */+ /* size :: A handle to the target size object. */+ /* */+ FT_LOCAL_DEF( void )+ tt_size_done( FT_Size ttsize ) /* TT_Size */+ {+ TT_Size size = (TT_Size)ttsize;+++#ifdef TT_USE_BYTECODE_INTERPRETER+ if ( size->bytecode_ready )+ tt_size_done_bytecode( ttsize );+#endif++ size->ttmetrics.valid = FALSE;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_size_reset */+ /* */+ /* <Description> */+ /* Reset a TrueType size when resolutions and character dimensions */+ /* have been changed. */+ /* */+ /* <Input> */+ /* size :: A handle to the target size object. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ tt_size_reset( TT_Size size )+ {+ TT_Face face;+ FT_Error error = TT_Err_Ok;+ FT_Size_Metrics* metrics;+++ size->ttmetrics.valid = FALSE;++ face = (TT_Face)size->root.face;++ metrics = &size->metrics;++ /* copy the result from base layer */+ *metrics = size->root.metrics;++ if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 )+ return TT_Err_Invalid_PPem;++ /* This bit flag, if set, indicates that the ppems must be */+ /* rounded to integers. Nearly all TrueType fonts have this bit */+ /* set, as hinting won't work really well otherwise. */+ /* */+ if ( face->header.Flags & 8 )+ {+ metrics->x_scale = FT_DivFix( metrics->x_ppem << 6,+ face->root.units_per_EM );+ metrics->y_scale = FT_DivFix( metrics->y_ppem << 6,+ face->root.units_per_EM );++ metrics->ascender =+ FT_PIX_ROUND( FT_MulFix( face->root.ascender, metrics->y_scale ) );+ metrics->descender =+ FT_PIX_ROUND( FT_MulFix( face->root.descender, metrics->y_scale ) );+ metrics->height =+ FT_PIX_ROUND( FT_MulFix( face->root.height, metrics->y_scale ) );+ metrics->max_advance =+ FT_PIX_ROUND( FT_MulFix( face->root.max_advance_width,+ metrics->x_scale ) );+ }++ /* compute new transformation */+ if ( metrics->x_ppem >= metrics->y_ppem )+ {+ size->ttmetrics.scale = metrics->x_scale;+ size->ttmetrics.ppem = metrics->x_ppem;+ size->ttmetrics.x_ratio = 0x10000L;+ size->ttmetrics.y_ratio = FT_MulDiv( metrics->y_ppem,+ 0x10000L,+ metrics->x_ppem );+ }+ else+ {+ size->ttmetrics.scale = metrics->y_scale;+ size->ttmetrics.ppem = metrics->y_ppem;+ size->ttmetrics.x_ratio = FT_MulDiv( metrics->x_ppem,+ 0x10000L,+ metrics->y_ppem );+ size->ttmetrics.y_ratio = 0x10000L;+ }++#ifdef TT_USE_BYTECODE_INTERPRETER+ size->cvt_ready = 0;+#endif /* TT_USE_BYTECODE_INTERPRETER */++ if ( !error )+ size->ttmetrics.valid = TRUE;++ return error;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_driver_init */+ /* */+ /* <Description> */+ /* Initialize a given TrueType driver object. */+ /* */+ /* <Input> */+ /* driver :: A handle to the target driver object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ tt_driver_init( FT_Module ttdriver ) /* TT_Driver */+ {++#ifdef TT_USE_BYTECODE_INTERPRETER++ TT_Driver driver = (TT_Driver)ttdriver;+++ if ( !TT_New_Context( driver ) )+ return TT_Err_Could_Not_Find_Context;++#else++ FT_UNUSED( ttdriver );++#endif++ return TT_Err_Ok;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_driver_done */+ /* */+ /* <Description> */+ /* Finalize a given TrueType driver. */+ /* */+ /* <Input> */+ /* driver :: A handle to the target TrueType driver. */+ /* */+ FT_LOCAL_DEF( void )+ tt_driver_done( FT_Module ttdriver ) /* TT_Driver */+ {+#ifdef TT_USE_BYTECODE_INTERPRETER+ TT_Driver driver = (TT_Driver)ttdriver;+++ /* destroy the execution context */+ if ( driver->context )+ {+ TT_Done_Context( driver->context );+ driver->context = NULL;+ }+#else+ FT_UNUSED( ttdriver );+#endif++ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_slot_init */+ /* */+ /* <Description> */+ /* Initialize a new slot object. */+ /* */+ /* <InOut> */+ /* slot :: A handle to the slot object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ tt_slot_init( FT_GlyphSlot slot )+ {+ return FT_GlyphLoader_CreateExtra( slot->internal->loader );+ }+++/* END */
+ src/truetype/ttobjs.h view
@@ -0,0 +1,431 @@+/***************************************************************************/+/* */+/* ttobjs.h */+/* */+/* Objects manager (specification). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 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 __TTOBJS_H__+#define __TTOBJS_H__+++#include <ft2build.h>+#include FT_INTERNAL_OBJECTS_H+#include FT_INTERNAL_TRUETYPE_TYPES_H+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* TT_Driver */+ /* */+ /* <Description> */+ /* A handle to a TrueType driver object. */+ /* */+ typedef struct TT_DriverRec_* TT_Driver;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* TT_Instance */+ /* */+ /* <Description> */+ /* A handle to a TrueType size object. */+ /* */+ typedef struct TT_SizeRec_* TT_Size;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* TT_GlyphSlot */+ /* */+ /* <Description> */+ /* A handle to a TrueType glyph slot object. */+ /* */+ /* <Note> */+ /* This is a direct typedef of FT_GlyphSlot, as there is nothing */+ /* specific about the TrueType glyph slot. */+ /* */+ typedef FT_GlyphSlot TT_GlyphSlot;+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* TT_GraphicsState */+ /* */+ /* <Description> */+ /* The TrueType graphics state used during bytecode interpretation. */+ /* */+ typedef struct TT_GraphicsState_+ {+ FT_UShort rp0;+ FT_UShort rp1;+ FT_UShort rp2;++ FT_UnitVector dualVector;+ FT_UnitVector projVector;+ FT_UnitVector freeVector;++#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING+ FT_Bool both_x_axis;+#endif++ FT_Long loop;+ FT_F26Dot6 minimum_distance;+ FT_Int round_state;++ FT_Bool auto_flip;+ FT_F26Dot6 control_value_cutin;+ FT_F26Dot6 single_width_cutin;+ FT_F26Dot6 single_width_value;+ FT_Short delta_base;+ FT_Short delta_shift;++ FT_Byte instruct_control;+ /* According to Greg Hitchcock from Microsoft, the `scan_control' */+ /* variable as documented in the TrueType specification is a 32-bit */+ /* integer; the high-word part holds the SCANTYPE value, the low-word */+ /* part the SCANCTRL value. We separate it into two fields. */+ FT_Bool scan_control;+ FT_Int scan_type;++ FT_UShort gep0;+ FT_UShort gep1;+ FT_UShort gep2;++ } TT_GraphicsState;+++#ifdef TT_USE_BYTECODE_INTERPRETER++ FT_LOCAL( void )+ tt_glyphzone_done( TT_GlyphZone zone );++ FT_LOCAL( FT_Error )+ tt_glyphzone_new( FT_Memory memory,+ FT_UShort maxPoints,+ FT_Short maxContours,+ TT_GlyphZone zone );++#endif /* TT_USE_BYTECODE_INTERPRETER */++++ /*************************************************************************/+ /* */+ /* EXECUTION SUBTABLES */+ /* */+ /* These sub-tables relate to instruction execution. */+ /* */+ /*************************************************************************/+++#define TT_MAX_CODE_RANGES 3+++ /*************************************************************************/+ /* */+ /* There can only be 3 active code ranges at once: */+ /* - the Font Program */+ /* - the CVT Program */+ /* - a glyph's instructions set */+ /* */+ typedef enum TT_CodeRange_Tag_+ {+ tt_coderange_none = 0,+ tt_coderange_font,+ tt_coderange_cvt,+ tt_coderange_glyph++ } TT_CodeRange_Tag;+++ typedef struct TT_CodeRange_+ {+ FT_Byte* base;+ FT_ULong size;++ } TT_CodeRange;++ typedef TT_CodeRange TT_CodeRangeTable[TT_MAX_CODE_RANGES];+++ /*************************************************************************/+ /* */+ /* Defines a function/instruction definition record. */+ /* */+ typedef struct TT_DefRecord_+ {+ FT_Int range; /* in which code range is it located? */+ FT_Long start; /* where does it start? */+ FT_UInt opc; /* function #, or instruction code */+ FT_Bool active; /* is it active? */++ } TT_DefRecord, *TT_DefArray;+++ /*************************************************************************/+ /* */+ /* Subglyph transformation record. */+ /* */+ typedef struct TT_Transform_+ {+ FT_Fixed xx, xy; /* transformation matrix coefficients */+ FT_Fixed yx, yy;+ FT_F26Dot6 ox, oy; /* offsets */++ } TT_Transform;+++ /*************************************************************************/+ /* */+ /* A note regarding non-squared pixels: */+ /* */+ /* (This text will probably go into some docs at some time; for now, it */+ /* is kept here to explain some definitions in the TT_Size_Metrics */+ /* record). */+ /* */+ /* The CVT is a one-dimensional array containing values that control */+ /* certain important characteristics in a font, like the height of all */+ /* capitals, all lowercase letter, default spacing or stem width/height. */+ /* */+ /* These values are found in FUnits in the font file, and must be scaled */+ /* to pixel coordinates before being used by the CVT and glyph programs. */+ /* Unfortunately, when using distinct x and y resolutions (or distinct x */+ /* and y pointsizes), there are two possible scalings. */+ /* */+ /* A first try was to implement a `lazy' scheme where all values were */+ /* scaled when first used. However, while some values are always used */+ /* in the same direction, some others are used under many different */+ /* circumstances and orientations. */+ /* */+ /* I have found a simpler way to do the same, and it even seems to work */+ /* in most of the cases: */+ /* */+ /* - All CVT values are scaled to the maximum ppem size. */+ /* */+ /* - When performing a read or write in the CVT, a ratio factor is used */+ /* to perform adequate scaling. Example: */+ /* */+ /* x_ppem = 14 */+ /* y_ppem = 10 */+ /* */+ /* We choose ppem = x_ppem = 14 as the CVT scaling size. All cvt */+ /* entries are scaled to it. */+ /* */+ /* x_ratio = 1.0 */+ /* y_ratio = y_ppem/ppem (< 1.0) */+ /* */+ /* We compute the current ratio like: */+ /* */+ /* - If projVector is horizontal, */+ /* ratio = x_ratio = 1.0 */+ /* */+ /* - if projVector is vertical, */+ /* ratio = y_ratio */+ /* */+ /* - else, */+ /* ratio = sqrt( (proj.x * x_ratio) ^ 2 + (proj.y * y_ratio) ^ 2 ) */+ /* */+ /* Reading a cvt value returns */+ /* ratio * cvt[index] */+ /* */+ /* Writing a cvt value in pixels: */+ /* cvt[index] / ratio */+ /* */+ /* The current ppem is simply */+ /* ratio * ppem */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* Metrics used by the TrueType size and context objects. */+ /* */+ typedef struct TT_Size_Metrics_+ {+ /* for non-square pixels */+ FT_Long x_ratio;+ FT_Long y_ratio;++ FT_UShort ppem; /* maximum ppem size */+ FT_Long ratio; /* current ratio */+ FT_Fixed scale;++ FT_F26Dot6 compensations[4]; /* device-specific compensations */++ FT_Bool valid;++ FT_Bool rotated; /* `is the glyph rotated?'-flag */+ FT_Bool stretched; /* `is the glyph stretched?'-flag */++ } TT_Size_Metrics;+++ /*************************************************************************/+ /* */+ /* TrueType size class. */+ /* */+ typedef struct TT_SizeRec_+ {+ FT_SizeRec root;++ /* we have our own copy of metrics so that we can modify */+ /* it without affecting auto-hinting (when used) */+ FT_Size_Metrics metrics;++ TT_Size_Metrics ttmetrics;++ FT_ULong strike_index; /* 0xFFFFFFFF to indicate invalid */++#ifdef TT_USE_BYTECODE_INTERPRETER++ FT_UInt num_function_defs; /* number of function definitions */+ FT_UInt max_function_defs;+ TT_DefArray function_defs; /* table of function definitions */++ FT_UInt num_instruction_defs; /* number of ins. definitions */+ FT_UInt max_instruction_defs;+ TT_DefArray instruction_defs; /* table of ins. definitions */++ FT_UInt max_func;+ FT_UInt max_ins;++ TT_CodeRangeTable codeRangeTable;++ TT_GraphicsState GS;++ FT_ULong cvt_size; /* the scaled control value table */+ FT_Long* cvt;++ FT_UShort storage_size; /* The storage area is now part of */+ FT_Long* storage; /* the instance */++ TT_GlyphZoneRec twilight; /* The instance's twilight zone */++ /* debugging variables */++ /* When using the debugger, we must keep the */+ /* execution context tied to the instance */+ /* object rather than asking it on demand. */++ FT_Bool debug;+ TT_ExecContext context;++ FT_Bool bytecode_ready;+ FT_Bool cvt_ready;++#endif /* TT_USE_BYTECODE_INTERPRETER */++ } TT_SizeRec;+++ /*************************************************************************/+ /* */+ /* TrueType driver class. */+ /* */+ typedef struct TT_DriverRec_+ {+ FT_DriverRec root;+ TT_ExecContext context; /* execution context */+ TT_GlyphZoneRec zone; /* glyph loader points zone */++ void* extension_component;++ } TT_DriverRec;+++ /* Note: All of the functions below (except tt_size_reset()) are used */+ /* as function pointers in a FT_Driver_ClassRec. Therefore their */+ /* parameters are of types FT_Face, FT_Size, etc., rather than TT_Face, */+ /* TT_Size, etc., so that the compiler can confirm that the types and */+ /* number of parameters are correct. In all cases the FT_xxx types are */+ /* cast to their TT_xxx counterparts inside the functions since FreeType */+ /* will always use the TT driver to create them. */+++ /*************************************************************************/+ /* */+ /* Face functions */+ /* */+ FT_LOCAL( FT_Error )+ tt_face_init( FT_Stream stream,+ FT_Face ttface, /* TT_Face */+ FT_Int face_index,+ FT_Int num_params,+ FT_Parameter* params );++ FT_LOCAL( void )+ tt_face_done( FT_Face ttface ); /* TT_Face */+++ /*************************************************************************/+ /* */+ /* Size functions */+ /* */+ FT_LOCAL( FT_Error )+ tt_size_init( FT_Size ttsize ); /* TT_Size */++ FT_LOCAL( void )+ tt_size_done( FT_Size ttsize ); /* TT_Size */++#ifdef TT_USE_BYTECODE_INTERPRETER++ FT_LOCAL( FT_Error )+ tt_size_run_fpgm( TT_Size size );++ FT_LOCAL( FT_Error )+ tt_size_run_prep( TT_Size size );++ FT_LOCAL( FT_Error )+ tt_size_ready_bytecode( TT_Size size );++#endif /* TT_USE_BYTECODE_INTERPRETER */++ FT_LOCAL( FT_Error )+ tt_size_reset( TT_Size size );+++ /*************************************************************************/+ /* */+ /* Driver functions */+ /* */+ FT_LOCAL( FT_Error )+ tt_driver_init( FT_Module ttdriver ); /* TT_Driver */++ FT_LOCAL( void )+ tt_driver_done( FT_Module ttdriver ); /* TT_Driver */+++ /*************************************************************************/+ /* */+ /* Slot functions */+ /* */+ FT_LOCAL( FT_Error )+ tt_slot_init( FT_GlyphSlot slot );+++FT_END_HEADER++#endif /* __TTOBJS_H__ */+++/* END */
+ src/truetype/ttpic.c view
@@ -0,0 +1,81 @@+/***************************************************************************/+/* */+/* ttpic.c */+/* */+/* The FreeType position independent code services for truetype module. */+/* */+/* Copyright 2009, 2010 by */+/* Oran Agra and Mickey Gabel. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++#include <ft2build.h>+#include FT_FREETYPE_H+#include FT_INTERNAL_OBJECTS_H+#include "ttpic.h"++#ifdef FT_CONFIG_OPTION_PIC++ /* forward declaration of PIC init functions from ttdriver.c */+ FT_Error FT_Create_Class_tt_services( FT_Library, FT_ServiceDescRec**);+ void FT_Destroy_Class_tt_services( FT_Library, FT_ServiceDescRec*);+ void FT_Init_Class_tt_service_gx_multi_masters(FT_Service_MultiMastersRec*);+ void FT_Init_Class_tt_service_truetype_glyf(FT_Service_TTGlyfRec*);++ void+ tt_driver_class_pic_free( FT_Library library )+ {+ FT_PIC_Container* pic_container = &library->pic_container;+ FT_Memory memory = library->memory;+ if ( pic_container->truetype )+ {+ TTModulePIC* container = (TTModulePIC*)pic_container->truetype;+ if(container->tt_services)+ FT_Destroy_Class_tt_services(library, container->tt_services);+ container->tt_services = NULL;+ FT_FREE( container );+ pic_container->truetype = NULL;+ }+ }+++ FT_Error+ tt_driver_class_pic_init( FT_Library library )+ {+ FT_PIC_Container* pic_container = &library->pic_container;+ FT_Error error = TT_Err_Ok;+ TTModulePIC* container;+ FT_Memory memory = library->memory;+++ /* allocate pointer, clear and set global container pointer */+ if ( FT_ALLOC ( container, sizeof ( *container ) ) )+ return error;+ FT_MEM_SET( container, 0, sizeof(*container) );+ pic_container->truetype = container;++ /* initialize pointer table - this is how the module usually expects this data */+ error = FT_Create_Class_tt_services(library, &container->tt_services);+ if(error) + goto Exit;+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT+ FT_Init_Class_tt_service_gx_multi_masters(&container->tt_service_gx_multi_masters);+#endif+ FT_Init_Class_tt_service_truetype_glyf(&container->tt_service_truetype_glyf);+Exit:+ if(error)+ tt_driver_class_pic_free(library);+ return error;+ }++#endif /* FT_CONFIG_OPTION_PIC */+++/* END */
+ src/truetype/ttpic.h view
@@ -0,0 +1,59 @@+/***************************************************************************/+/* */+/* ttpic.h */+/* */+/* The FreeType position independent code services for truetype module. */+/* */+/* Copyright 2009 by */+/* Oran Agra and Mickey Gabel. */+/* */+/* 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 __TTPIC_H__+#define __TTPIC_H__++ +FT_BEGIN_HEADER++#ifndef FT_CONFIG_OPTION_PIC+#define FT_TT_SERVICES_GET tt_services+#define FT_TT_SERVICE_GX_MULTI_MASTERS_GET tt_service_gx_multi_masters+#define FT_TT_SERVICE_TRUETYPE_GLYF_GET tt_service_truetype_glyf++#else /* FT_CONFIG_OPTION_PIC */++#include FT_MULTIPLE_MASTERS_H+#include FT_SERVICE_MULTIPLE_MASTERS_H+#include FT_SERVICE_TRUETYPE_GLYF_H++ typedef struct TTModulePIC_+ {+ FT_ServiceDescRec* tt_services;+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT+ FT_Service_MultiMastersRec tt_service_gx_multi_masters;+#endif+ FT_Service_TTGlyfRec tt_service_truetype_glyf;+ } TTModulePIC;++#define GET_PIC(lib) ((TTModulePIC*)((lib)->pic_container.truetype))+#define FT_TT_SERVICES_GET (GET_PIC(library)->tt_services)+#define FT_TT_SERVICE_GX_MULTI_MASTERS_GET (GET_PIC(library)->tt_service_gx_multi_masters)+#define FT_TT_SERVICE_TRUETYPE_GLYF_GET (GET_PIC(library)->tt_service_truetype_glyf)++#endif /* FT_CONFIG_OPTION_PIC */++ /* */++FT_END_HEADER++#endif /* __TTPIC_H__ */+++/* END */
+ src/truetype/ttpload.c view
@@ -0,0 +1,598 @@+/***************************************************************************/+/* */+/* ttpload.c */+/* */+/* TrueType-specific tables loader (body). */+/* */+/* Copyright 1996-2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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_INTERNAL_STREAM_H+#include FT_TRUETYPE_TAGS_H++#include "ttpload.h"++#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT+#include "ttgxvar.h"+#endif++#include "tterrors.h"+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_ttpload+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_face_load_loca */+ /* */+ /* <Description> */+ /* Load the locations table. */+ /* */+ /* <InOut> */+ /* face :: A handle to the target face object. */+ /* */+ /* <Input> */+ /* stream :: The input stream. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ tt_face_load_loca( TT_Face face,+ FT_Stream stream )+ {+ FT_Error error;+ FT_ULong table_len;+ FT_Int shift;+++ /* we need the size of the `glyf' table for malformed `loca' tables */+ error = face->goto_table( face, TTAG_glyf, stream, &face->glyf_len );++ /* it is possible that a font doesn't have a glyf table at all */+ /* or its size is zero */+ if ( error == TT_Err_Table_Missing )+ face->glyf_len = 0;+ else if ( error )+ goto Exit;++ FT_TRACE2(( "Locations " ));+ error = face->goto_table( face, TTAG_loca, stream, &table_len );+ if ( error )+ {+ error = TT_Err_Locations_Missing;+ goto Exit;+ }++ if ( face->header.Index_To_Loc_Format != 0 )+ {+ shift = 2;++ if ( table_len >= 0x40000L )+ {+ FT_TRACE2(( "table too large\n" ));+ error = TT_Err_Invalid_Table;+ goto Exit;+ }+ face->num_locations = table_len >> shift;+ }+ else+ {+ shift = 1;++ if ( table_len >= 0x20000L )+ {+ FT_TRACE2(( "table too large\n" ));+ error = TT_Err_Invalid_Table;+ goto Exit;+ }+ face->num_locations = table_len >> shift;+ }++ if ( face->num_locations != (FT_ULong)face->root.num_glyphs )+ {+ FT_TRACE2(( "glyph count mismatch! loca: %d, maxp: %d\n",+ face->num_locations, face->root.num_glyphs ));++ /* we only handle the case where `maxp' gives a larger value */+ if ( face->num_locations < (FT_ULong)face->root.num_glyphs )+ {+ FT_Long new_loca_len = (FT_Long)face->root.num_glyphs << shift;++ TT_Table entry = face->dir_tables;+ TT_Table limit = entry + face->num_tables;++ FT_Long pos = FT_Stream_Pos( stream );+ FT_Long dist = 0x7FFFFFFFL;+++ /* compute the distance to next table in font file */+ for ( ; entry < limit; entry++ )+ {+ FT_Long diff = entry->Offset - pos;+++ if ( diff > 0 && diff < dist )+ dist = diff;+ }++ if ( entry == limit )+ {+ /* `loca' is the last table */+ dist = stream->size - pos;+ }++ if ( new_loca_len <= dist )+ {+ face->num_locations = face->root.num_glyphs;+ table_len = new_loca_len;++ FT_TRACE2(( "adjusting num_locations to %d\n",+ face->num_locations ));+ }+ }+ }++ /*+ * Extract the frame. We don't need to decompress it since+ * we are able to parse it directly.+ */+ if ( FT_FRAME_EXTRACT( table_len, face->glyph_locations ) )+ goto Exit;++ FT_TRACE2(( "loaded\n" ));++ Exit:+ return error;+ }+++ FT_LOCAL_DEF( FT_ULong )+ tt_face_get_location( TT_Face face,+ FT_UInt gindex,+ FT_UInt *asize )+ {+ FT_ULong pos1, pos2;+ FT_Byte* p;+ FT_Byte* p_limit;+++ pos1 = pos2 = 0;++ if ( gindex < face->num_locations )+ {+ if ( face->header.Index_To_Loc_Format != 0 )+ {+ p = face->glyph_locations + gindex * 4;+ p_limit = face->glyph_locations + face->num_locations * 4;++ pos1 = FT_NEXT_ULONG( p );+ pos2 = pos1;++ if ( p + 4 <= p_limit )+ pos2 = FT_NEXT_ULONG( p );+ }+ else+ {+ p = face->glyph_locations + gindex * 2;+ p_limit = face->glyph_locations + face->num_locations * 2;++ pos1 = FT_NEXT_USHORT( p );+ pos2 = pos1;++ if ( p + 2 <= p_limit )+ pos2 = FT_NEXT_USHORT( p );++ pos1 <<= 1;+ pos2 <<= 1;+ }+ }++ /* Check broken location data */+ if ( pos1 >= face->glyf_len )+ {+ FT_TRACE1(( "tt_face_get_location:"+ " too large offset=0x%08lx found for gid=0x%04lx,"+ " exceeding the end of glyf table (0x%08lx)\n",+ pos1, gindex, face->glyf_len ));+ *asize = 0;+ return 0;+ }++ if ( pos2 >= face->glyf_len )+ {+ FT_TRACE1(( "tt_face_get_location:"+ " too large offset=0x%08lx found for gid=0x%04lx,"+ " truncate at the end of glyf table (0x%08lx)\n",+ pos2, gindex + 1, face->glyf_len ));+ pos2 = face->glyf_len;+ }++ /* The `loca' table must be ordered; it refers to the length of */+ /* an entry as the difference between the current and the next */+ /* position. However, there do exist (malformed) fonts which */+ /* don't obey this rule, so we are only able to provide an */+ /* upper bound for the size. */+ /* */+ /* We get (intentionally) a wrong, non-zero result in case the */+ /* `glyf' table is missing. */+ if ( pos2 >= pos1 )+ *asize = (FT_UInt)( pos2 - pos1 );+ else+ *asize = (FT_UInt)( face->glyf_len - pos1 );++ return pos1;+ }+++ FT_LOCAL_DEF( void )+ tt_face_done_loca( TT_Face face )+ {+ FT_Stream stream = face->root.stream;+++ FT_FRAME_RELEASE( face->glyph_locations );+ face->num_locations = 0;+ }++++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_face_load_cvt */+ /* */+ /* <Description> */+ /* Load the control value table into a face object. */+ /* */+ /* <InOut> */+ /* face :: A handle to the target face object. */+ /* */+ /* <Input> */+ /* stream :: A handle to the input stream. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ tt_face_load_cvt( TT_Face face,+ FT_Stream stream )+ {+#ifdef TT_USE_BYTECODE_INTERPRETER++ FT_Error error;+ FT_Memory memory = stream->memory;+ FT_ULong table_len;+++ FT_TRACE2(( "CVT " ));++ error = face->goto_table( face, TTAG_cvt, stream, &table_len );+ if ( error )+ {+ FT_TRACE2(( "is missing\n" ));++ face->cvt_size = 0;+ face->cvt = NULL;+ error = TT_Err_Ok;++ goto Exit;+ }++ face->cvt_size = table_len / 2;++ if ( FT_NEW_ARRAY( face->cvt, face->cvt_size ) )+ goto Exit;++ if ( FT_FRAME_ENTER( face->cvt_size * 2L ) )+ goto Exit;++ {+ FT_Short* cur = face->cvt;+ FT_Short* limit = cur + face->cvt_size;+++ for ( ; cur < limit; cur++ )+ *cur = FT_GET_SHORT();+ }++ FT_FRAME_EXIT();+ FT_TRACE2(( "loaded\n" ));++#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT+ if ( face->doblend )+ error = tt_face_vary_cvt( face, stream );+#endif++ Exit:+ return error;++#else /* !TT_USE_BYTECODE_INTERPRETER */++ FT_UNUSED( face );+ FT_UNUSED( stream );++ return TT_Err_Ok;++#endif+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_face_load_fpgm */+ /* */+ /* <Description> */+ /* Load the font program. */+ /* */+ /* <InOut> */+ /* face :: A handle to the target face object. */+ /* */+ /* <Input> */+ /* stream :: A handle to the input stream. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ tt_face_load_fpgm( TT_Face face,+ FT_Stream stream )+ {+#ifdef TT_USE_BYTECODE_INTERPRETER++ FT_Error error;+ FT_ULong table_len;+++ FT_TRACE2(( "Font program " ));++ /* The font program is optional */+ error = face->goto_table( face, TTAG_fpgm, stream, &table_len );+ if ( error )+ {+ face->font_program = NULL;+ face->font_program_size = 0;+ error = TT_Err_Ok;++ FT_TRACE2(( "is missing\n" ));+ }+ else+ {+ face->font_program_size = table_len;+ if ( FT_FRAME_EXTRACT( table_len, face->font_program ) )+ goto Exit;++ FT_TRACE2(( "loaded, %12d bytes\n", face->font_program_size ));+ }++ Exit:+ return error;++#else /* !TT_USE_BYTECODE_INTERPRETER */++ FT_UNUSED( face );+ FT_UNUSED( stream );++ return TT_Err_Ok;++#endif+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_face_load_prep */+ /* */+ /* <Description> */+ /* Load the cvt program. */+ /* */+ /* <InOut> */+ /* face :: A handle to the target face object. */+ /* */+ /* <Input> */+ /* stream :: A handle to the input stream. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ tt_face_load_prep( TT_Face face,+ FT_Stream stream )+ {+#ifdef TT_USE_BYTECODE_INTERPRETER++ FT_Error error;+ FT_ULong table_len;+++ FT_TRACE2(( "Prep program " ));++ error = face->goto_table( face, TTAG_prep, stream, &table_len );+ if ( error )+ {+ face->cvt_program = NULL;+ face->cvt_program_size = 0;+ error = TT_Err_Ok;++ FT_TRACE2(( "is missing\n" ));+ }+ else+ {+ face->cvt_program_size = table_len;+ if ( FT_FRAME_EXTRACT( table_len, face->cvt_program ) )+ goto Exit;++ FT_TRACE2(( "loaded, %12d bytes\n", face->cvt_program_size ));+ }++ Exit:+ return error;++#else /* !TT_USE_BYTECODE_INTERPRETER */++ FT_UNUSED( face );+ FT_UNUSED( stream );++ return TT_Err_Ok;++#endif+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* tt_face_load_hdmx */+ /* */+ /* <Description> */+ /* Load the `hdmx' table into the face object. */+ /* */+ /* <Input> */+ /* face :: A handle to the target face object. */+ /* */+ /* stream :: A handle to the input stream. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */++ FT_LOCAL_DEF( FT_Error )+ tt_face_load_hdmx( TT_Face face,+ FT_Stream stream )+ {+ FT_Error error;+ FT_Memory memory = stream->memory;+ FT_UInt version, nn, num_records;+ FT_ULong table_size, record_size;+ FT_Byte* p;+ FT_Byte* limit;+++ /* this table is optional */+ error = face->goto_table( face, TTAG_hdmx, stream, &table_size );+ if ( error || table_size < 8 )+ return TT_Err_Ok;++ if ( FT_FRAME_EXTRACT( table_size, face->hdmx_table ) )+ goto Exit;++ p = face->hdmx_table;+ limit = p + table_size;++ version = FT_NEXT_USHORT( p );+ num_records = FT_NEXT_USHORT( p );+ record_size = FT_NEXT_ULONG( p );++ /* The maximum number of bytes in an hdmx device record is the */+ /* maximum number of glyphs + 2; this is 0xFFFF + 2; this is */+ /* the reason why `record_size' is a long (which we read as */+ /* unsigned long for convenience). In practice, two bytes */+ /* sufficient to hold the size value. */+ /* */+ /* There are at least two fonts, HANNOM-A and HANNOM-B version */+ /* 2.0 (2005), which get this wrong: The upper two bytes of */+ /* the size value are set to 0xFF instead of 0x00. We catch */+ /* and fix this. */++ if ( record_size >= 0xFFFF0000UL )+ record_size &= 0xFFFFU;++ /* The limit for `num_records' is a heuristic value. */++ if ( version != 0 || num_records > 255 || record_size > 0x10001L )+ {+ error = TT_Err_Invalid_File_Format;+ goto Fail;+ }++ if ( FT_NEW_ARRAY( face->hdmx_record_sizes, num_records ) )+ goto Fail;++ for ( nn = 0; nn < num_records; nn++ )+ {+ if ( p + record_size > limit )+ break;++ face->hdmx_record_sizes[nn] = p[0];+ p += record_size;+ }++ face->hdmx_record_count = nn;+ face->hdmx_table_size = table_size;+ face->hdmx_record_size = record_size;++ Exit:+ return error;++ Fail:+ FT_FRAME_RELEASE( face->hdmx_table );+ face->hdmx_table_size = 0;+ goto Exit;+ }+++ FT_LOCAL_DEF( void )+ tt_face_free_hdmx( TT_Face face )+ {+ FT_Stream stream = face->root.stream;+ FT_Memory memory = stream->memory;+++ FT_FREE( face->hdmx_record_sizes );+ FT_FRAME_RELEASE( face->hdmx_table );+ }+++ /*************************************************************************/+ /* */+ /* Return the advance width table for a given pixel size if it is found */+ /* in the font's `hdmx' table (if any). */+ /* */+ FT_LOCAL_DEF( FT_Byte* )+ tt_face_get_device_metrics( TT_Face face,+ FT_UInt ppem,+ FT_UInt gindex )+ {+ FT_UInt nn;+ FT_Byte* result = NULL;+ FT_ULong record_size = face->hdmx_record_size;+ FT_Byte* record = face->hdmx_table + 8;+++ for ( nn = 0; nn < face->hdmx_record_count; nn++ )+ if ( face->hdmx_record_sizes[nn] == ppem )+ {+ gindex += 2;+ if ( gindex < record_size )+ result = record + nn * record_size + gindex;+ break;+ }++ return result;+ }+++/* END */
+ src/truetype/ttpload.h view
@@ -0,0 +1,75 @@+/***************************************************************************/+/* */+/* ttpload.h */+/* */+/* TrueType-specific tables loader (specification). */+/* */+/* Copyright 1996-2001, 2002, 2005, 2006 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 __TTPLOAD_H__+#define __TTPLOAD_H__+++#include <ft2build.h>+#include FT_INTERNAL_TRUETYPE_TYPES_H+++FT_BEGIN_HEADER+++ FT_LOCAL( FT_Error )+ tt_face_load_loca( TT_Face face,+ FT_Stream stream );++ FT_LOCAL( FT_ULong )+ tt_face_get_location( TT_Face face,+ FT_UInt gindex,+ FT_UInt *asize );++ FT_LOCAL( void )+ tt_face_done_loca( TT_Face face );++ FT_LOCAL( FT_Error )+ tt_face_load_cvt( TT_Face face,+ FT_Stream stream );++ FT_LOCAL( FT_Error )+ tt_face_load_fpgm( TT_Face face,+ FT_Stream stream );+++ FT_LOCAL( FT_Error )+ tt_face_load_prep( TT_Face face,+ FT_Stream stream );+++ FT_LOCAL( FT_Error )+ tt_face_load_hdmx( TT_Face face,+ FT_Stream stream );+++ FT_LOCAL( void )+ tt_face_free_hdmx( TT_Face face );+++ FT_LOCAL( FT_Byte* )+ tt_face_get_device_metrics( TT_Face face,+ FT_UInt ppem,+ FT_UInt gindex );++FT_END_HEADER++#endif /* __TTPLOAD_H__ */+++/* END */
+ src/type1/t1afm.c view
@@ -0,0 +1,397 @@+/***************************************************************************/+/* */+/* t1afm.c */+/* */+/* AFM support for Type 1 fonts (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */+/* 2010 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 "t1afm.h"+#include "t1errors.h"+#include FT_INTERNAL_STREAM_H+#include FT_INTERNAL_POSTSCRIPT_AUX_H+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_t1afm+++ FT_LOCAL_DEF( void )+ T1_Done_Metrics( FT_Memory memory,+ AFM_FontInfo fi )+ {+ FT_FREE( fi->KernPairs );+ fi->NumKernPair = 0;++ FT_FREE( fi->TrackKerns );+ fi->NumTrackKern = 0;++ FT_FREE( fi );+ }+++ /* read a glyph name and return the equivalent glyph index */+ static FT_Int+ t1_get_index( const char* name,+ FT_Offset len,+ void* user_data )+ {+ T1_Font type1 = (T1_Font)user_data;+ FT_Int n;+++ /* PS string/name length must be < 16-bit */+ if ( len > 0xFFFFU )+ return 0;++ for ( n = 0; n < type1->num_glyphs; n++ )+ {+ char* gname = (char*)type1->glyph_names[n];+++ if ( gname && gname[0] == name[0] &&+ ft_strlen( gname ) == len &&+ ft_strncmp( gname, name, len ) == 0 )+ return n;+ }++ return 0;+ }+++#undef KERN_INDEX+#define KERN_INDEX( g1, g2 ) ( ( (FT_ULong)(g1) << 16 ) | (g2) )+++ /* compare two kerning pairs */+ FT_CALLBACK_DEF( int )+ compare_kern_pairs( const void* a,+ const void* b )+ {+ AFM_KernPair pair1 = (AFM_KernPair)a;+ AFM_KernPair pair2 = (AFM_KernPair)b;++ FT_ULong index1 = KERN_INDEX( pair1->index1, pair1->index2 );+ FT_ULong index2 = KERN_INDEX( pair2->index1, pair2->index2 );+++ if ( index1 > index2 )+ return 1;+ else if ( index1 < index2 )+ return -1;+ else+ return 0;+ }+++ /* parse a PFM file -- for now, only read the kerning pairs */+ static FT_Error+ T1_Read_PFM( FT_Face t1_face,+ FT_Stream stream,+ AFM_FontInfo fi )+ {+ FT_Error error = T1_Err_Ok;+ FT_Memory memory = stream->memory;+ FT_Byte* start;+ FT_Byte* limit;+ FT_Byte* p;+ AFM_KernPair kp;+ FT_Int width_table_length;+ FT_CharMap oldcharmap;+ FT_CharMap charmap;+ FT_Int n;+++ start = (FT_Byte*)stream->cursor;+ limit = (FT_Byte*)stream->limit;+ p = start;++ /* Figure out how long the width table is. */+ /* This info is a little-endian short at offset 99. */+ p = start + 99;+ if ( p + 2 > limit )+ {+ error = T1_Err_Unknown_File_Format;+ goto Exit;+ }+ width_table_length = FT_PEEK_USHORT_LE( p );++ p += 18 + width_table_length;+ if ( p + 0x12 > limit || FT_PEEK_USHORT_LE( p ) < 0x12 )+ /* extension table is probably optional */+ goto Exit;++ /* Kerning offset is 14 bytes from start of extensions table. */+ p += 14;+ p = start + FT_PEEK_ULONG_LE( p );++ if ( p == start )+ /* zero offset means no table */+ goto Exit;++ if ( p + 2 > limit )+ {+ error = T1_Err_Unknown_File_Format;+ goto Exit;+ }++ fi->NumKernPair = FT_PEEK_USHORT_LE( p );+ p += 2;+ if ( p + 4 * fi->NumKernPair > limit )+ {+ error = T1_Err_Unknown_File_Format;+ goto Exit;+ }++ /* Actually, kerning pairs are simply optional! */+ if ( fi->NumKernPair == 0 )+ goto Exit;++ /* allocate the pairs */+ if ( FT_QNEW_ARRAY( fi->KernPairs, fi->NumKernPair ) )+ goto Exit;++ /* now, read each kern pair */+ kp = fi->KernPairs;+ limit = p + 4 * fi->NumKernPair;++ /* PFM kerning data are stored by encoding rather than glyph index, */+ /* so find the PostScript charmap of this font and install it */+ /* temporarily. If we find no PostScript charmap, then just use */+ /* the default and hope it is the right one. */+ oldcharmap = t1_face->charmap;+ charmap = NULL;++ for ( n = 0; n < t1_face->num_charmaps; n++ )+ {+ charmap = t1_face->charmaps[n];+ /* check against PostScript pseudo platform */+ if ( charmap->platform_id == 7 )+ {+ error = FT_Set_Charmap( t1_face, charmap );+ if ( error )+ goto Exit;+ break;+ }+ }++ /* Kerning info is stored as: */+ /* */+ /* encoding of first glyph (1 byte) */+ /* encoding of second glyph (1 byte) */+ /* offset (little-endian short) */+ for ( ; p < limit ; p += 4 )+ {+ kp->index1 = FT_Get_Char_Index( t1_face, p[0] );+ kp->index2 = FT_Get_Char_Index( t1_face, p[1] );++ kp->x = (FT_Int)FT_PEEK_SHORT_LE(p + 2);+ kp->y = 0;++ kp++;+ }++ if ( oldcharmap != NULL )+ error = FT_Set_Charmap( t1_face, oldcharmap );+ if ( error )+ goto Exit;++ /* now, sort the kern pairs according to their glyph indices */+ ft_qsort( fi->KernPairs, fi->NumKernPair, sizeof ( AFM_KernPairRec ),+ compare_kern_pairs );++ Exit:+ if ( error )+ {+ FT_FREE( fi->KernPairs );+ fi->NumKernPair = 0;+ }++ return error;+ }+++ /* parse a metrics file -- either AFM or PFM depending on what */+ /* it turns out to be */+ FT_LOCAL_DEF( FT_Error )+ T1_Read_Metrics( FT_Face t1_face,+ FT_Stream stream )+ {+ PSAux_Service psaux;+ FT_Memory memory = stream->memory;+ AFM_ParserRec parser;+ AFM_FontInfo fi = NULL;+ FT_Error error = T1_Err_Unknown_File_Format;+ T1_Font t1_font = &( (T1_Face)t1_face )->type1;+++ if ( FT_NEW( fi ) ||+ FT_FRAME_ENTER( stream->size ) )+ goto Exit;++ fi->FontBBox = t1_font->font_bbox;+ fi->Ascender = t1_font->font_bbox.yMax;+ fi->Descender = t1_font->font_bbox.yMin;++ psaux = (PSAux_Service)( (T1_Face)t1_face )->psaux;+ if ( psaux && psaux->afm_parser_funcs )+ {+ error = psaux->afm_parser_funcs->init( &parser,+ stream->memory,+ stream->cursor,+ stream->limit );++ if ( !error )+ {+ parser.FontInfo = fi;+ parser.get_index = t1_get_index;+ parser.user_data = t1_font;++ error = psaux->afm_parser_funcs->parse( &parser );+ psaux->afm_parser_funcs->done( &parser );+ }+ }++ if ( error == T1_Err_Unknown_File_Format )+ {+ FT_Byte* start = stream->cursor;+++ /* MS Windows allows versions up to 0x3FF without complaining */+ if ( stream->size > 6 &&+ start[1] < 4 &&+ FT_PEEK_ULONG_LE( start + 2 ) == stream->size )+ error = T1_Read_PFM( t1_face, stream, fi );+ }++ if ( !error )+ {+ t1_font->font_bbox = fi->FontBBox;++ t1_face->bbox.xMin = fi->FontBBox.xMin >> 16;+ t1_face->bbox.yMin = fi->FontBBox.yMin >> 16;+ /* no `U' suffix here to 0xFFFF! */+ t1_face->bbox.xMax = ( fi->FontBBox.xMax + 0xFFFF ) >> 16;+ t1_face->bbox.yMax = ( fi->FontBBox.yMax + 0xFFFF ) >> 16;++ /* no `U' suffix here to 0x8000! */+ t1_face->ascender = (FT_Short)( ( fi->Ascender + 0x8000 ) >> 16 );+ t1_face->descender = (FT_Short)( ( fi->Descender + 0x8000 ) >> 16 );++ if ( fi->NumKernPair )+ {+ t1_face->face_flags |= FT_FACE_FLAG_KERNING;+ ( (T1_Face)t1_face )->afm_data = fi;+ fi = NULL;+ }+ }++ FT_FRAME_EXIT();++ Exit:+ if ( fi != NULL )+ T1_Done_Metrics( memory, fi );++ return error;+ }+++ /* find the kerning for a given glyph pair */+ FT_LOCAL_DEF( void )+ T1_Get_Kerning( AFM_FontInfo fi,+ FT_UInt glyph1,+ FT_UInt glyph2,+ FT_Vector* kerning )+ {+ AFM_KernPair min, mid, max;+ FT_ULong idx = KERN_INDEX( glyph1, glyph2 );+++ /* simple binary search */+ min = fi->KernPairs;+ max = min + fi->NumKernPair - 1;++ while ( min <= max )+ {+ FT_ULong midi;+++ mid = min + ( max - min ) / 2;+ midi = KERN_INDEX( mid->index1, mid->index2 );++ if ( midi == idx )+ {+ kerning->x = mid->x;+ kerning->y = mid->y;++ return;+ }++ if ( midi < idx )+ min = mid + 1;+ else+ max = mid - 1;+ }++ kerning->x = 0;+ kerning->y = 0;+ }+++ FT_LOCAL_DEF( FT_Error )+ T1_Get_Track_Kerning( FT_Face face,+ FT_Fixed ptsize,+ FT_Int degree,+ FT_Fixed* kerning )+ {+ AFM_FontInfo fi = (AFM_FontInfo)( (T1_Face)face )->afm_data;+ FT_Int i;+++ if ( !fi )+ return T1_Err_Invalid_Argument;++ for ( i = 0; i < fi->NumTrackKern; i++ )+ {+ AFM_TrackKern tk = fi->TrackKerns + i;+++ if ( tk->degree != degree )+ continue;++ if ( ptsize < tk->min_ptsize )+ *kerning = tk->min_kern;+ else if ( ptsize > tk->max_ptsize )+ *kerning = tk->max_kern;+ else+ {+ *kerning = FT_MulDiv( ptsize - tk->min_ptsize,+ tk->max_kern - tk->min_kern,+ tk->max_ptsize - tk->min_ptsize ) ++ tk->min_kern;+ }+ }++ return T1_Err_Ok;+ }+++/* END */
+ src/type1/t1afm.h view
@@ -0,0 +1,54 @@+/***************************************************************************/+/* */+/* t1afm.h */+/* */+/* AFM support for Type 1 fonts (specification). */+/* */+/* Copyright 1996-2001, 2002, 2006 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 __T1AFM_H__+#define __T1AFM_H__++#include <ft2build.h>+#include "t1objs.h"+#include FT_INTERNAL_TYPE1_TYPES_H++FT_BEGIN_HEADER+++ FT_LOCAL( FT_Error )+ T1_Read_Metrics( FT_Face face,+ FT_Stream stream );++ FT_LOCAL( void )+ T1_Done_Metrics( FT_Memory memory,+ AFM_FontInfo fi );++ FT_LOCAL( void )+ T1_Get_Kerning( AFM_FontInfo fi,+ FT_UInt glyph1,+ FT_UInt glyph2,+ FT_Vector* kerning );++ FT_LOCAL( FT_Error )+ T1_Get_Track_Kerning( FT_Face face,+ FT_Fixed ptsize,+ FT_Int degree,+ FT_Fixed* kerning );++FT_END_HEADER++#endif /* __T1AFM_H__ */+++/* END */
+ src/type1/t1driver.c view
@@ -0,0 +1,331 @@+/***************************************************************************/+/* */+/* t1driver.c */+/* */+/* Type 1 driver interface (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007, 2009 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 "t1driver.h"+#include "t1gload.h"+#include "t1load.h"++#include "t1errors.h"++#ifndef T1_CONFIG_OPTION_NO_AFM+#include "t1afm.h"+#endif++#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_STREAM_H++#include FT_SERVICE_MULTIPLE_MASTERS_H+#include FT_SERVICE_GLYPH_DICT_H+#include FT_SERVICE_XFREE86_NAME_H+#include FT_SERVICE_POSTSCRIPT_NAME_H+#include FT_SERVICE_POSTSCRIPT_CMAPS_H+#include FT_SERVICE_POSTSCRIPT_INFO_H+#include FT_SERVICE_KERNING_H+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_t1driver++ /*+ * GLYPH DICT SERVICE+ *+ */++ static FT_Error+ t1_get_glyph_name( T1_Face face,+ FT_UInt glyph_index,+ FT_Pointer buffer,+ FT_UInt buffer_max )+ {+ FT_STRCPYN( buffer, face->type1.glyph_names[glyph_index], buffer_max );++ return T1_Err_Ok;+ }+++ static FT_UInt+ t1_get_name_index( T1_Face face,+ FT_String* glyph_name )+ {+ FT_Int i;+ FT_String* gname;+++ for ( i = 0; i < face->type1.num_glyphs; i++ )+ {+ gname = face->type1.glyph_names[i];++ if ( !ft_strcmp( glyph_name, gname ) )+ return (FT_UInt)i;+ }++ return 0;+ }+++ static const FT_Service_GlyphDictRec t1_service_glyph_dict =+ {+ (FT_GlyphDict_GetNameFunc) t1_get_glyph_name,+ (FT_GlyphDict_NameIndexFunc)t1_get_name_index+ };+++ /*+ * POSTSCRIPT NAME SERVICE+ *+ */++ static const char*+ t1_get_ps_name( T1_Face face )+ {+ return (const char*) face->type1.font_name;+ }+++ static const FT_Service_PsFontNameRec t1_service_ps_name =+ {+ (FT_PsName_GetFunc)t1_get_ps_name+ };+++ /*+ * MULTIPLE MASTERS SERVICE+ *+ */++#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT+ static const FT_Service_MultiMastersRec t1_service_multi_masters =+ {+ (FT_Get_MM_Func) T1_Get_Multi_Master,+ (FT_Set_MM_Design_Func) T1_Set_MM_Design,+ (FT_Set_MM_Blend_Func) T1_Set_MM_Blend,+ (FT_Get_MM_Var_Func) T1_Get_MM_Var,+ (FT_Set_Var_Design_Func)T1_Set_Var_Design+ };+#endif+++ /*+ * POSTSCRIPT INFO SERVICE+ *+ */++ static FT_Error+ t1_ps_get_font_info( FT_Face face,+ PS_FontInfoRec* afont_info )+ {+ *afont_info = ((T1_Face)face)->type1.font_info;++ return T1_Err_Ok;+ }+++ static FT_Error+ t1_ps_get_font_extra( FT_Face face,+ PS_FontExtraRec* afont_extra )+ {+ *afont_extra = ((T1_Face)face)->type1.font_extra;++ return T1_Err_Ok;+ }+++ static FT_Int+ t1_ps_has_glyph_names( FT_Face face )+ {+ FT_UNUSED( face );++ return 1;+ }+++ static FT_Error+ t1_ps_get_font_private( FT_Face face,+ PS_PrivateRec* afont_private )+ {+ *afont_private = ((T1_Face)face)->type1.private_dict;++ return T1_Err_Ok;+ }+++ static const FT_Service_PsInfoRec t1_service_ps_info =+ {+ (PS_GetFontInfoFunc) t1_ps_get_font_info,+ (PS_GetFontExtraFunc) t1_ps_get_font_extra,+ (PS_HasGlyphNamesFunc) t1_ps_has_glyph_names,+ (PS_GetFontPrivateFunc)t1_ps_get_font_private,+ };+++#ifndef T1_CONFIG_OPTION_NO_AFM+ static const FT_Service_KerningRec t1_service_kerning =+ {+ T1_Get_Track_Kerning,+ };+#endif+++ /*+ * SERVICE LIST+ *+ */++ static const FT_ServiceDescRec t1_services[] =+ {+ { FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &t1_service_ps_name },+ { FT_SERVICE_ID_GLYPH_DICT, &t1_service_glyph_dict },+ { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_TYPE_1 },+ { FT_SERVICE_ID_POSTSCRIPT_INFO, &t1_service_ps_info },++#ifndef T1_CONFIG_OPTION_NO_AFM+ { FT_SERVICE_ID_KERNING, &t1_service_kerning },+#endif++#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT+ { FT_SERVICE_ID_MULTI_MASTERS, &t1_service_multi_masters },+#endif+ { NULL, NULL }+ };+++ static FT_Module_Interface+ Get_Interface( FT_Driver driver,+ const FT_String* t1_interface )+ {+ FT_UNUSED( driver );++ return ft_service_list_lookup( t1_services, t1_interface );+ }+++#ifndef T1_CONFIG_OPTION_NO_AFM++ /*************************************************************************/+ /* */+ /* <Function> */+ /* Get_Kerning */+ /* */+ /* <Description> */+ /* A driver method used to return the kerning vector between two */+ /* glyphs of the same face. */+ /* */+ /* <Input> */+ /* face :: A handle to the source face object. */+ /* */+ /* left_glyph :: The index of the left glyph in the kern pair. */+ /* */+ /* right_glyph :: The index of the right glyph in the kern pair. */+ /* */+ /* <Output> */+ /* kerning :: The kerning vector. This is in font units for */+ /* scalable formats, and in pixels for fixed-sizes */+ /* formats. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ /* <Note> */+ /* Only horizontal layouts (left-to-right & right-to-left) are */+ /* supported by this function. Other layouts, or more sophisticated */+ /* kernings are out of scope of this method (the basic driver */+ /* interface is meant to be simple). */+ /* */+ /* They can be implemented by format-specific interfaces. */+ /* */+ static FT_Error+ Get_Kerning( T1_Face face,+ FT_UInt left_glyph,+ FT_UInt right_glyph,+ FT_Vector* kerning )+ {+ kerning->x = 0;+ kerning->y = 0;++ if ( face->afm_data )+ T1_Get_Kerning( (AFM_FontInfo)face->afm_data,+ left_glyph,+ right_glyph,+ kerning );++ return T1_Err_Ok;+ }+++#endif /* T1_CONFIG_OPTION_NO_AFM */+++ FT_CALLBACK_TABLE_DEF+ const FT_Driver_ClassRec t1_driver_class =+ {+ {+ FT_MODULE_FONT_DRIVER |+ FT_MODULE_DRIVER_SCALABLE |+ FT_MODULE_DRIVER_HAS_HINTER,++ sizeof( FT_DriverRec ),++ "type1",+ 0x10000L,+ 0x20000L,++ 0, /* format interface */++ (FT_Module_Constructor)T1_Driver_Init,+ (FT_Module_Destructor) T1_Driver_Done,+ (FT_Module_Requester) Get_Interface,+ },++ sizeof( T1_FaceRec ),+ sizeof( T1_SizeRec ),+ sizeof( T1_GlyphSlotRec ),++ (FT_Face_InitFunc) T1_Face_Init,+ (FT_Face_DoneFunc) T1_Face_Done,+ (FT_Size_InitFunc) T1_Size_Init,+ (FT_Size_DoneFunc) T1_Size_Done,+ (FT_Slot_InitFunc) T1_GlyphSlot_Init,+ (FT_Slot_DoneFunc) T1_GlyphSlot_Done,++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS+ ft_stub_set_char_sizes,+ ft_stub_set_pixel_sizes,+#endif+ (FT_Slot_LoadFunc) T1_Load_Glyph,++#ifdef T1_CONFIG_OPTION_NO_AFM+ (FT_Face_GetKerningFunc) 0,+ (FT_Face_AttachFunc) 0,+#else+ (FT_Face_GetKerningFunc) Get_Kerning,+ (FT_Face_AttachFunc) T1_Read_Metrics,+#endif+ (FT_Face_GetAdvancesFunc) T1_Get_Advances,+ (FT_Size_RequestFunc) T1_Size_Request,+ (FT_Size_SelectFunc) 0+ };+++/* END */
+ src/type1/t1driver.h view
@@ -0,0 +1,42 @@+/***************************************************************************/+/* */+/* t1driver.h */+/* */+/* High-level Type 1 driver interface (specification). */+/* */+/* Copyright 1996-2001, 2002 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 __T1DRIVER_H__+#define __T1DRIVER_H__+++#include <ft2build.h>+#include FT_INTERNAL_DRIVER_H+++FT_BEGIN_HEADER++#ifdef FT_CONFIG_OPTION_PIC+#error "this module does not support PIC yet"+#endif +++ FT_EXPORT_VAR( const FT_Driver_ClassRec ) t1_driver_class;+++FT_END_HEADER++#endif /* __T1DRIVER_H__ */+++/* END */
+ src/type1/t1errors.h view
@@ -0,0 +1,40 @@+/***************************************************************************/+/* */+/* t1errors.h */+/* */+/* Type 1 error codes (specification only). */+/* */+/* Copyright 2001 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 Type 1 error enumeration constants. */+ /* */+ /*************************************************************************/++#ifndef __T1ERRORS_H__+#define __T1ERRORS_H__++#include FT_MODULE_ERRORS_H++#undef __FTERRORS_H__++#define FT_ERR_PREFIX T1_Err_+#define FT_ERR_BASE FT_Mod_Err_Type1++#include FT_ERRORS_H++#endif /* __T1ERRORS_H__ */+++/* END */
+ src/type1/t1gload.c view
@@ -0,0 +1,515 @@+/***************************************************************************/+/* */+/* t1gload.c */+/* */+/* Type 1 Glyph Loader (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009, 2010 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 "t1gload.h"+#include FT_INTERNAL_CALC_H+#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_STREAM_H+#include FT_OUTLINE_H+#include FT_INTERNAL_POSTSCRIPT_AUX_H++#include "t1errors.h"+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_t1gload+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /********** *********/+ /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/+ /********** *********/+ /********** The following code is in charge of computing *********/+ /********** the maximum advance width of the font. It *********/+ /********** quickly processes each glyph charstring to *********/+ /********** extract the value from either a `sbw' or `seac' *********/+ /********** operator. *********/+ /********** *********/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ FT_LOCAL_DEF( FT_Error )+ T1_Parse_Glyph_And_Get_Char_String( T1_Decoder decoder,+ FT_UInt glyph_index,+ FT_Data* char_string )+ {+ T1_Face face = (T1_Face)decoder->builder.face;+ T1_Font type1 = &face->type1;+ FT_Error error = T1_Err_Ok;++#ifdef FT_CONFIG_OPTION_INCREMENTAL+ FT_Incremental_InterfaceRec *inc =+ face->root.internal->incremental_interface;+#endif+++ decoder->font_matrix = type1->font_matrix;+ decoder->font_offset = type1->font_offset;++#ifdef FT_CONFIG_OPTION_INCREMENTAL++ /* For incremental fonts get the character data using the */+ /* callback function. */+ if ( inc )+ error = inc->funcs->get_glyph_data( inc->object,+ glyph_index, char_string );+ else++#endif /* FT_CONFIG_OPTION_INCREMENTAL */++ /* For ordinary fonts get the character data stored in the face record. */+ {+ char_string->pointer = type1->charstrings[glyph_index];+ char_string->length = (FT_Int)type1->charstrings_len[glyph_index];+ }++ if ( !error )+ error = decoder->funcs.parse_charstrings(+ decoder, (FT_Byte*)char_string->pointer,+ char_string->length );++#ifdef FT_CONFIG_OPTION_INCREMENTAL++ /* Incremental fonts can optionally override the metrics. */+ if ( !error && inc && inc->funcs->get_glyph_metrics )+ {+ FT_Incremental_MetricsRec metrics;+++ metrics.bearing_x = FIXED_TO_INT( decoder->builder.left_bearing.x );+ metrics.bearing_y = 0;+ metrics.advance = FIXED_TO_INT( decoder->builder.advance.x );+ metrics.advance_v = FIXED_TO_INT( decoder->builder.advance.y );++ error = inc->funcs->get_glyph_metrics( inc->object,+ glyph_index, FALSE, &metrics );++ decoder->builder.left_bearing.x = INT_TO_FIXED( metrics.bearing_x );+ decoder->builder.advance.x = INT_TO_FIXED( metrics.advance );+ decoder->builder.advance.y = INT_TO_FIXED( metrics.advance_v );+ }++#endif /* FT_CONFIG_OPTION_INCREMENTAL */++ return error;+ }+++ FT_CALLBACK_DEF( FT_Error )+ T1_Parse_Glyph( T1_Decoder decoder,+ FT_UInt glyph_index )+ {+ FT_Data glyph_data;+ FT_Error error = T1_Parse_Glyph_And_Get_Char_String(+ decoder, glyph_index, &glyph_data );+++#ifdef FT_CONFIG_OPTION_INCREMENTAL++ if ( !error )+ {+ T1_Face face = (T1_Face)decoder->builder.face;+++ if ( face->root.internal->incremental_interface )+ face->root.internal->incremental_interface->funcs->free_glyph_data(+ face->root.internal->incremental_interface->object,+ &glyph_data );+ }++#endif /* FT_CONFIG_OPTION_INCREMENTAL */++ return error;+ }+++ FT_LOCAL_DEF( FT_Error )+ T1_Compute_Max_Advance( T1_Face face,+ FT_Pos* max_advance )+ {+ FT_Error error;+ T1_DecoderRec decoder;+ FT_Int glyph_index;+ T1_Font type1 = &face->type1;+ PSAux_Service psaux = (PSAux_Service)face->psaux;+++ FT_ASSERT( ( face->len_buildchar == 0 ) == ( face->buildchar == NULL ) );++ *max_advance = 0;++ /* initialize load decoder */+ error = psaux->t1_decoder_funcs->init( &decoder,+ (FT_Face)face,+ 0, /* size */+ 0, /* glyph slot */+ (FT_Byte**)type1->glyph_names,+ face->blend,+ 0,+ FT_RENDER_MODE_NORMAL,+ T1_Parse_Glyph );+ if ( error )+ return error;++ decoder.builder.metrics_only = 1;+ decoder.builder.load_points = 0;++ decoder.num_subrs = type1->num_subrs;+ decoder.subrs = type1->subrs;+ decoder.subrs_len = type1->subrs_len;++ decoder.buildchar = face->buildchar;+ decoder.len_buildchar = face->len_buildchar;++ *max_advance = 0;++ /* for each glyph, parse the glyph charstring and extract */+ /* the advance width */+ for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ )+ {+ /* now get load the unscaled outline */+ error = T1_Parse_Glyph( &decoder, glyph_index );+ if ( glyph_index == 0 || decoder.builder.advance.x > *max_advance )+ *max_advance = decoder.builder.advance.x;++ /* ignore the error if one occurred - skip to next glyph */+ }++ psaux->t1_decoder_funcs->done( &decoder );++ return T1_Err_Ok;+ }+++ FT_LOCAL_DEF( FT_Error )+ T1_Get_Advances( T1_Face face,+ FT_UInt first,+ FT_UInt count,+ FT_ULong load_flags,+ FT_Fixed* advances )+ {+ T1_DecoderRec decoder;+ T1_Font type1 = &face->type1;+ PSAux_Service psaux = (PSAux_Service)face->psaux;+ FT_UInt nn;+ FT_Error error;+++ if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )+ {+ for ( nn = 0; nn < count; nn++ )+ advances[nn] = 0;++ return T1_Err_Ok;+ }++ error = psaux->t1_decoder_funcs->init( &decoder,+ (FT_Face)face,+ 0, /* size */+ 0, /* glyph slot */+ (FT_Byte**)type1->glyph_names,+ face->blend,+ 0,+ FT_RENDER_MODE_NORMAL,+ T1_Parse_Glyph );+ if ( error )+ return error;++ decoder.builder.metrics_only = 1;+ decoder.builder.load_points = 0;++ decoder.num_subrs = type1->num_subrs;+ decoder.subrs = type1->subrs;+ decoder.subrs_len = type1->subrs_len;++ decoder.buildchar = face->buildchar;+ decoder.len_buildchar = face->len_buildchar;++ for ( nn = 0; nn < count; nn++ )+ {+ error = T1_Parse_Glyph( &decoder, first + nn );+ if ( !error )+ advances[nn] = FIXED_TO_INT( decoder.builder.advance.x );+ else+ advances[nn] = 0;+ }++ return T1_Err_Ok;+ }+++ FT_LOCAL_DEF( FT_Error )+ T1_Load_Glyph( T1_GlyphSlot glyph,+ T1_Size size,+ FT_UInt glyph_index,+ FT_Int32 load_flags )+ {+ FT_Error error;+ T1_DecoderRec decoder;+ T1_Face face = (T1_Face)glyph->root.face;+ FT_Bool hinting;+ T1_Font type1 = &face->type1;+ PSAux_Service psaux = (PSAux_Service)face->psaux;+ const T1_Decoder_Funcs decoder_funcs = psaux->t1_decoder_funcs;++ FT_Matrix font_matrix;+ FT_Vector font_offset;+ FT_Data glyph_data;+ FT_Bool must_finish_decoder = FALSE;+#ifdef FT_CONFIG_OPTION_INCREMENTAL+ FT_Bool glyph_data_loaded = 0;+#endif+++#ifdef FT_CONFIG_OPTION_INCREMENTAL+ if ( glyph_index >= (FT_UInt)face->root.num_glyphs &&+ !face->root.internal->incremental_interface )+#else+ if ( glyph_index >= (FT_UInt)face->root.num_glyphs )+#endif /* FT_CONFIG_OPTION_INCREMENTAL */+ {+ error = T1_Err_Invalid_Argument;+ goto Exit;+ }++ FT_ASSERT( ( face->len_buildchar == 0 ) == ( face->buildchar == NULL ) );++ if ( load_flags & FT_LOAD_NO_RECURSE )+ load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;++ if ( size )+ {+ glyph->x_scale = size->root.metrics.x_scale;+ glyph->y_scale = size->root.metrics.y_scale;+ }+ else+ {+ glyph->x_scale = 0x10000L;+ glyph->y_scale = 0x10000L;+ }++ glyph->root.outline.n_points = 0;+ glyph->root.outline.n_contours = 0;++ hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 &&+ ( load_flags & FT_LOAD_NO_HINTING ) == 0 );++ glyph->root.format = FT_GLYPH_FORMAT_OUTLINE;++ error = decoder_funcs->init( &decoder,+ (FT_Face)face,+ (FT_Size)size,+ (FT_GlyphSlot)glyph,+ (FT_Byte**)type1->glyph_names,+ face->blend,+ FT_BOOL( hinting ),+ FT_LOAD_TARGET_MODE( load_flags ),+ T1_Parse_Glyph );+ if ( error )+ goto Exit;++ must_finish_decoder = TRUE;++ decoder.builder.no_recurse = FT_BOOL(+ ( load_flags & FT_LOAD_NO_RECURSE ) != 0 );++ decoder.num_subrs = type1->num_subrs;+ decoder.subrs = type1->subrs;+ decoder.subrs_len = type1->subrs_len;++ decoder.buildchar = face->buildchar;+ decoder.len_buildchar = face->len_buildchar;++ /* now load the unscaled outline */+ error = T1_Parse_Glyph_And_Get_Char_String( &decoder, glyph_index,+ &glyph_data );+ if ( error )+ goto Exit;+#ifdef FT_CONFIG_OPTION_INCREMENTAL+ glyph_data_loaded = 1;+#endif++ font_matrix = decoder.font_matrix;+ font_offset = decoder.font_offset;++ /* save new glyph tables */+ decoder_funcs->done( &decoder );++ must_finish_decoder = FALSE;++ /* now, set the metrics -- this is rather simple, as */+ /* the left side bearing is the xMin, and the top side */+ /* bearing the yMax */+ if ( !error )+ {+ glyph->root.outline.flags &= FT_OUTLINE_OWNER;+ glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL;++ /* for composite glyphs, return only left side bearing and */+ /* advance width */+ if ( load_flags & FT_LOAD_NO_RECURSE )+ {+ FT_Slot_Internal internal = glyph->root.internal;+++ glyph->root.metrics.horiBearingX =+ FIXED_TO_INT( decoder.builder.left_bearing.x );+ glyph->root.metrics.horiAdvance =+ FIXED_TO_INT( decoder.builder.advance.x );++ internal->glyph_matrix = font_matrix;+ internal->glyph_delta = font_offset;+ internal->glyph_transformed = 1;+ }+ else+ {+ FT_BBox cbox;+ FT_Glyph_Metrics* metrics = &glyph->root.metrics;+ FT_Vector advance;+++ /* copy the _unscaled_ advance width */+ metrics->horiAdvance =+ FIXED_TO_INT( decoder.builder.advance.x );+ glyph->root.linearHoriAdvance =+ FIXED_TO_INT( decoder.builder.advance.x );+ glyph->root.internal->glyph_transformed = 0;++ if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) + {+ /* make up vertical ones */+ metrics->vertAdvance = ( face->type1.font_bbox.yMax -+ face->type1.font_bbox.yMin ) >> 16;+ glyph->root.linearVertAdvance = metrics->vertAdvance;+ }+ else+ {+ metrics->vertAdvance =+ FIXED_TO_INT( decoder.builder.advance.y );+ glyph->root.linearVertAdvance =+ FIXED_TO_INT( decoder.builder.advance.y );+ }++ glyph->root.format = FT_GLYPH_FORMAT_OUTLINE;++ if ( size && size->root.metrics.y_ppem < 24 )+ glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION;++#if 1+ /* apply the font matrix, if any */+ if ( font_matrix.xx != 0x10000L || font_matrix.yy != font_matrix.xx ||+ font_matrix.xy != 0 || font_matrix.yx != 0 )+ FT_Outline_Transform( &glyph->root.outline, &font_matrix );++ if ( font_offset.x || font_offset.y )+ FT_Outline_Translate( &glyph->root.outline,+ font_offset.x,+ font_offset.y );++ advance.x = metrics->horiAdvance;+ advance.y = 0;+ FT_Vector_Transform( &advance, &font_matrix );+ metrics->horiAdvance = advance.x + font_offset.x;+ advance.x = 0;+ advance.y = metrics->vertAdvance;+ FT_Vector_Transform( &advance, &font_matrix );+ metrics->vertAdvance = advance.y + font_offset.y;+#endif++ if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )+ {+ /* scale the outline and the metrics */+ FT_Int n;+ FT_Outline* cur = decoder.builder.base;+ FT_Vector* vec = cur->points;+ FT_Fixed x_scale = glyph->x_scale;+ FT_Fixed y_scale = glyph->y_scale;+++ /* First of all, scale the points, if we are not hinting */+ if ( !hinting || ! decoder.builder.hints_funcs )+ for ( n = cur->n_points; n > 0; n--, vec++ )+ {+ vec->x = FT_MulFix( vec->x, x_scale );+ vec->y = FT_MulFix( vec->y, y_scale );+ }++ /* Then scale the metrics */+ metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );+ metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );+ }++ /* compute the other metrics */+ FT_Outline_Get_CBox( &glyph->root.outline, &cbox );++ metrics->width = cbox.xMax - cbox.xMin;+ metrics->height = cbox.yMax - cbox.yMin;++ metrics->horiBearingX = cbox.xMin;+ metrics->horiBearingY = cbox.yMax;++ if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) + {+ /* make up vertical ones */+ ft_synthesize_vertical_metrics( metrics,+ metrics->vertAdvance );+ }+ }++ /* Set control data to the glyph charstrings. Note that this is */+ /* _not_ zero-terminated. */+ glyph->root.control_data = (FT_Byte*)glyph_data.pointer;+ glyph->root.control_len = glyph_data.length;+ }+++ Exit:++#ifdef FT_CONFIG_OPTION_INCREMENTAL+ if ( glyph_data_loaded && face->root.internal->incremental_interface )+ {+ face->root.internal->incremental_interface->funcs->free_glyph_data(+ face->root.internal->incremental_interface->object,+ &glyph_data );++ /* Set the control data to null - it is no longer available if */+ /* loaded incrementally. */+ glyph->root.control_data = 0;+ glyph->root.control_len = 0;+ }+#endif++ if ( must_finish_decoder )+ decoder_funcs->done( &decoder );++ return error;+ }+++/* END */
+ src/type1/t1gload.h view
@@ -0,0 +1,53 @@+/***************************************************************************/+/* */+/* t1gload.h */+/* */+/* Type 1 Glyph Loader (specification). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2008 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 __T1GLOAD_H__+#define __T1GLOAD_H__+++#include <ft2build.h>+#include "t1objs.h"+++FT_BEGIN_HEADER+++ FT_LOCAL( FT_Error )+ T1_Compute_Max_Advance( T1_Face face,+ FT_Pos* max_advance );++ FT_LOCAL( FT_Error )+ T1_Get_Advances( T1_Face face,+ FT_UInt first,+ FT_UInt count,+ FT_ULong load_flags,+ FT_Fixed* advances );++ FT_LOCAL( FT_Error )+ T1_Load_Glyph( T1_GlyphSlot glyph,+ T1_Size size,+ FT_UInt glyph_index,+ FT_Int32 load_flags );+++FT_END_HEADER++#endif /* __T1GLOAD_H__ */+++/* END */
+ src/type1/t1load.c view
@@ -0,0 +1,2237 @@+/***************************************************************************/+/* */+/* t1load.c */+/* */+/* Type 1 font loader (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */+/* 2010 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++ /*************************************************************************/+ /* */+ /* This is the new and improved Type 1 data loader for FreeType 2. The */+ /* old loader has several problems: it is slow, complex, difficult to */+ /* maintain, and contains incredible hacks to make it accept some */+ /* ill-formed Type 1 fonts without hiccup-ing. Moreover, about 5% of */+ /* the Type 1 fonts on my machine still aren't loaded correctly by it. */+ /* */+ /* This version is much simpler, much faster and also easier to read and */+ /* maintain by a great order of magnitude. The idea behind it is to */+ /* _not_ try to read the Type 1 token stream with a state machine (i.e. */+ /* a Postscript-like interpreter) but rather to perform simple pattern */+ /* matching. */+ /* */+ /* Indeed, nearly all data definitions follow a simple pattern like */+ /* */+ /* ... /Field <data> ... */+ /* */+ /* where <data> can be a number, a boolean, a string, or an array of */+ /* numbers. There are a few exceptions, namely the encoding, font name, */+ /* charstrings, and subrs; they are handled with a special pattern */+ /* matching routine. */+ /* */+ /* All other common cases are handled very simply. The matching rules */+ /* are defined in the file `t1tokens.h' through the use of several */+ /* macros calls PARSE_XXX. This file is included twice here; the first */+ /* time to generate parsing callback functions, the second time to */+ /* generate a table of keywords (with pointers to the associated */+ /* callback functions). */+ /* */+ /* The function `parse_dict' simply scans *linearly* a given dictionary */+ /* (either the top-level or private one) and calls the appropriate */+ /* callback when it encounters an immediate keyword. */+ /* */+ /* This is by far the fastest way one can find to parse and read all */+ /* data. */+ /* */+ /* This led to tremendous code size reduction. Note that later, the */+ /* glyph loader will also be _greatly_ simplified, and the automatic */+ /* hinter will replace the clumsy `t1hinter'. */+ /* */+ /*************************************************************************/+++#include <ft2build.h>+#include FT_INTERNAL_DEBUG_H+#include FT_CONFIG_CONFIG_H+#include FT_MULTIPLE_MASTERS_H+#include FT_INTERNAL_TYPE1_TYPES_H+#include FT_INTERNAL_CALC_H++#include "t1load.h"+#include "t1errors.h"+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_t1load+++#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT+++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** MULTIPLE MASTERS SUPPORT *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ static FT_Error+ t1_allocate_blend( T1_Face face,+ FT_UInt num_designs,+ FT_UInt num_axis )+ {+ PS_Blend blend;+ FT_Memory memory = face->root.memory;+ FT_Error error = T1_Err_Ok;+++ blend = face->blend;+ if ( !blend )+ {+ if ( FT_NEW( blend ) )+ goto Exit;++ blend->num_default_design_vector = 0;++ face->blend = blend;+ }++ /* allocate design data if needed */+ if ( num_designs > 0 )+ {+ if ( blend->num_designs == 0 )+ {+ FT_UInt nn;+++ /* allocate the blend `private' and `font_info' dictionaries */+ if ( FT_NEW_ARRAY( blend->font_infos[1], num_designs ) ||+ FT_NEW_ARRAY( blend->privates[1], num_designs ) ||+ FT_NEW_ARRAY( blend->bboxes[1], num_designs ) ||+ FT_NEW_ARRAY( blend->weight_vector, num_designs * 2 ) )+ goto Exit;++ blend->default_weight_vector = blend->weight_vector + num_designs;++ blend->font_infos[0] = &face->type1.font_info;+ blend->privates [0] = &face->type1.private_dict;+ blend->bboxes [0] = &face->type1.font_bbox;++ for ( nn = 2; nn <= num_designs; nn++ )+ {+ blend->privates[nn] = blend->privates [nn - 1] + 1;+ blend->font_infos[nn] = blend->font_infos[nn - 1] + 1;+ blend->bboxes[nn] = blend->bboxes [nn - 1] + 1;+ }++ blend->num_designs = num_designs;+ }+ else if ( blend->num_designs != num_designs )+ goto Fail;+ }++ /* allocate axis data if needed */+ if ( num_axis > 0 )+ {+ if ( blend->num_axis != 0 && blend->num_axis != num_axis )+ goto Fail;++ blend->num_axis = num_axis;+ }++ /* allocate the blend design pos table if needed */+ num_designs = blend->num_designs;+ num_axis = blend->num_axis;+ if ( num_designs && num_axis && blend->design_pos[0] == 0 )+ {+ FT_UInt n;+++ if ( FT_NEW_ARRAY( blend->design_pos[0], num_designs * num_axis ) )+ goto Exit;++ for ( n = 1; n < num_designs; n++ )+ blend->design_pos[n] = blend->design_pos[0] + num_axis * n;+ }++ Exit:+ return error;++ Fail:+ error = T1_Err_Invalid_File_Format;+ goto Exit;+ }+++ FT_LOCAL_DEF( FT_Error )+ T1_Get_Multi_Master( T1_Face face,+ FT_Multi_Master* master )+ {+ PS_Blend blend = face->blend;+ FT_UInt n;+ FT_Error error;+++ error = T1_Err_Invalid_Argument;++ if ( blend )+ {+ master->num_axis = blend->num_axis;+ master->num_designs = blend->num_designs;++ for ( n = 0; n < blend->num_axis; n++ )+ {+ FT_MM_Axis* axis = master->axis + n;+ PS_DesignMap map = blend->design_map + n;+++ axis->name = blend->axis_names[n];+ axis->minimum = map->design_points[0];+ axis->maximum = map->design_points[map->num_points - 1];+ }++ error = T1_Err_Ok;+ }++ return error;+ }+++ /*************************************************************************/+ /* */+ /* Given a normalized (blend) coordinate, figure out the design */+ /* coordinate appropriate for that value. */+ /* */+ FT_LOCAL_DEF( FT_Fixed )+ mm_axis_unmap( PS_DesignMap axismap,+ FT_Fixed ncv )+ {+ int j;+++ if ( ncv <= axismap->blend_points[0] )+ return INT_TO_FIXED( axismap->design_points[0] );++ for ( j = 1; j < axismap->num_points; ++j )+ {+ if ( ncv <= axismap->blend_points[j] )+ {+ FT_Fixed t = FT_MulDiv( ncv - axismap->blend_points[j - 1],+ 0x10000L,+ axismap->blend_points[j] -+ axismap->blend_points[j - 1] );++ return INT_TO_FIXED( axismap->design_points[j - 1] ) ++ FT_MulDiv( t,+ axismap->design_points[j] -+ axismap->design_points[j - 1],+ 1L );+ }+ }++ return INT_TO_FIXED( axismap->design_points[axismap->num_points - 1] );+ }+++ /*************************************************************************/+ /* */+ /* Given a vector of weights, one for each design, figure out the */+ /* normalized axis coordinates which gave rise to those weights. */+ /* */+ FT_LOCAL_DEF( void )+ mm_weights_unmap( FT_Fixed* weights,+ FT_Fixed* axiscoords,+ FT_UInt axis_count )+ {+ FT_ASSERT( axis_count <= T1_MAX_MM_AXIS );++ if ( axis_count == 1 )+ axiscoords[0] = weights[1];++ else if ( axis_count == 2 )+ {+ axiscoords[0] = weights[3] + weights[1];+ axiscoords[1] = weights[3] + weights[2];+ }++ else if ( axis_count == 3 )+ {+ axiscoords[0] = weights[7] + weights[5] + weights[3] + weights[1];+ axiscoords[1] = weights[7] + weights[6] + weights[3] + weights[2];+ axiscoords[2] = weights[7] + weights[6] + weights[5] + weights[4];+ }++ else+ {+ axiscoords[0] = weights[15] + weights[13] + weights[11] + weights[9] ++ weights[7] + weights[5] + weights[3] + weights[1];+ axiscoords[1] = weights[15] + weights[14] + weights[11] + weights[10] ++ weights[7] + weights[6] + weights[3] + weights[2];+ axiscoords[2] = weights[15] + weights[14] + weights[13] + weights[12] ++ weights[7] + weights[6] + weights[5] + weights[4];+ axiscoords[3] = weights[15] + weights[14] + weights[13] + weights[12] ++ weights[11] + weights[10] + weights[9] + weights[8];+ }+ }+++ /*************************************************************************/+ /* */+ /* Just a wrapper around T1_Get_Multi_Master to support the different */+ /* arguments needed by the GX var distortable fonts. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ T1_Get_MM_Var( T1_Face face,+ FT_MM_Var* *master )+ {+ FT_Memory memory = face->root.memory;+ FT_MM_Var *mmvar;+ FT_Multi_Master mmaster;+ FT_Error error;+ FT_UInt i;+ FT_Fixed axiscoords[T1_MAX_MM_AXIS];+ PS_Blend blend = face->blend;+++ error = T1_Get_Multi_Master( face, &mmaster );+ if ( error )+ goto Exit;+ if ( FT_ALLOC( mmvar,+ sizeof ( FT_MM_Var ) ++ mmaster.num_axis * sizeof ( FT_Var_Axis ) ) )+ goto Exit;++ mmvar->num_axis = mmaster.num_axis;+ mmvar->num_designs = mmaster.num_designs;+ mmvar->num_namedstyles = (FT_UInt)-1; /* Does not apply */+ mmvar->axis = (FT_Var_Axis*)&mmvar[1];+ /* Point to axes after MM_Var struct */+ mmvar->namedstyle = NULL;++ for ( i = 0 ; i < mmaster.num_axis; ++i )+ {+ mmvar->axis[i].name = mmaster.axis[i].name;+ mmvar->axis[i].minimum = INT_TO_FIXED( mmaster.axis[i].minimum);+ mmvar->axis[i].maximum = INT_TO_FIXED( mmaster.axis[i].maximum);+ mmvar->axis[i].def = ( mmvar->axis[i].minimum ++ mmvar->axis[i].maximum ) / 2;+ /* Does not apply. But this value is in range */+ mmvar->axis[i].strid = (FT_UInt)-1; /* Does not apply */+ mmvar->axis[i].tag = (FT_ULong)-1; /* Does not apply */++ if ( ft_strcmp( mmvar->axis[i].name, "Weight" ) == 0 )+ mmvar->axis[i].tag = FT_MAKE_TAG( 'w', 'g', 'h', 't' );+ else if ( ft_strcmp( mmvar->axis[i].name, "Width" ) == 0 )+ mmvar->axis[i].tag = FT_MAKE_TAG( 'w', 'd', 't', 'h' );+ else if ( ft_strcmp( mmvar->axis[i].name, "OpticalSize" ) == 0 )+ mmvar->axis[i].tag = FT_MAKE_TAG( 'o', 'p', 's', 'z' );+ }++ if ( blend->num_designs == ( 1U << blend->num_axis ) )+ {+ mm_weights_unmap( blend->default_weight_vector,+ axiscoords,+ blend->num_axis );++ for ( i = 0; i < mmaster.num_axis; ++i )+ mmvar->axis[i].def = mm_axis_unmap( &blend->design_map[i],+ axiscoords[i] );+ }++ *master = mmvar;++ Exit:+ return error;+ }+++ FT_LOCAL_DEF( FT_Error )+ T1_Set_MM_Blend( T1_Face face,+ FT_UInt num_coords,+ FT_Fixed* coords )+ {+ PS_Blend blend = face->blend;+ FT_Error error;+ FT_UInt n, m;+++ error = T1_Err_Invalid_Argument;++ if ( blend && blend->num_axis == num_coords )+ {+ /* recompute the weight vector from the blend coordinates */+ error = T1_Err_Ok;++ for ( n = 0; n < blend->num_designs; n++ )+ {+ FT_Fixed result = 0x10000L; /* 1.0 fixed */+++ for ( m = 0; m < blend->num_axis; m++ )+ {+ FT_Fixed factor;+++ /* get current blend axis position */+ factor = coords[m];+ if ( factor < 0 ) factor = 0;+ if ( factor > 0x10000L ) factor = 0x10000L;++ if ( ( n & ( 1 << m ) ) == 0 )+ factor = 0x10000L - factor;++ result = FT_MulFix( result, factor );+ }+ blend->weight_vector[n] = result;+ }++ error = T1_Err_Ok;+ }++ return error;+ }+++ FT_LOCAL_DEF( FT_Error )+ T1_Set_MM_Design( T1_Face face,+ FT_UInt num_coords,+ FT_Long* coords )+ {+ PS_Blend blend = face->blend;+ FT_Error error;+ FT_UInt n, p;+++ error = T1_Err_Invalid_Argument;+ if ( blend && blend->num_axis == num_coords )+ {+ /* compute the blend coordinates through the blend design map */+ FT_Fixed final_blends[T1_MAX_MM_DESIGNS];+++ for ( n = 0; n < blend->num_axis; n++ )+ {+ FT_Long design = coords[n];+ FT_Fixed the_blend;+ PS_DesignMap map = blend->design_map + n;+ FT_Long* designs = map->design_points;+ FT_Fixed* blends = map->blend_points;+ FT_Int before = -1, after = -1;+++ for ( p = 0; p < (FT_UInt)map->num_points; p++ )+ {+ FT_Long p_design = designs[p];+++ /* exact match? */+ if ( design == p_design )+ {+ the_blend = blends[p];+ goto Found;+ }++ if ( design < p_design )+ {+ after = p;+ break;+ }++ before = p;+ }++ /* now interpolate if necessary */+ if ( before < 0 )+ the_blend = blends[0];++ else if ( after < 0 )+ the_blend = blends[map->num_points - 1];++ else+ the_blend = FT_MulDiv( design - designs[before],+ blends [after] - blends [before],+ designs[after] - designs[before] );++ Found:+ final_blends[n] = the_blend;+ }++ error = T1_Set_MM_Blend( face, num_coords, final_blends );+ }++ return error;+ }+++ /*************************************************************************/+ /* */+ /* Just a wrapper around T1_Set_MM_Design to support the different */+ /* arguments needed by the GX var distortable fonts. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ T1_Set_Var_Design( T1_Face face,+ FT_UInt num_coords,+ FT_Fixed* coords )+ {+ FT_Long lcoords[4]; /* maximum axis count is 4 */+ FT_UInt i;+ FT_Error error;+++ error = T1_Err_Invalid_Argument;+ if ( num_coords <= 4 && num_coords > 0 )+ {+ for ( i = 0; i < num_coords; ++i )+ lcoords[i] = FIXED_TO_INT( coords[i] );+ error = T1_Set_MM_Design( face, num_coords, lcoords );+ }++ return error;+ }+++ FT_LOCAL_DEF( void )+ T1_Done_Blend( T1_Face face )+ {+ FT_Memory memory = face->root.memory;+ PS_Blend blend = face->blend;+++ if ( blend )+ {+ FT_UInt num_designs = blend->num_designs;+ FT_UInt num_axis = blend->num_axis;+ FT_UInt n;+++ /* release design pos table */+ FT_FREE( blend->design_pos[0] );+ for ( n = 1; n < num_designs; n++ )+ blend->design_pos[n] = 0;++ /* release blend `private' and `font info' dictionaries */+ FT_FREE( blend->privates[1] );+ FT_FREE( blend->font_infos[1] );+ FT_FREE( blend->bboxes[1] );++ for ( n = 0; n < num_designs; n++ )+ {+ blend->privates [n] = 0;+ blend->font_infos[n] = 0;+ blend->bboxes [n] = 0;+ }++ /* release weight vectors */+ FT_FREE( blend->weight_vector );+ blend->default_weight_vector = 0;++ /* release axis names */+ for ( n = 0; n < num_axis; n++ )+ FT_FREE( blend->axis_names[n] );++ /* release design map */+ for ( n = 0; n < num_axis; n++ )+ {+ PS_DesignMap dmap = blend->design_map + n;+++ FT_FREE( dmap->design_points );+ dmap->num_points = 0;+ }++ FT_FREE( face->blend );+ }+ }+++ static void+ parse_blend_axis_types( T1_Face face,+ T1_Loader loader )+ {+ T1_TokenRec axis_tokens[T1_MAX_MM_AXIS];+ FT_Int n, num_axis;+ FT_Error error = T1_Err_Ok;+ PS_Blend blend;+ FT_Memory memory;+++ /* take an array of objects */+ T1_ToTokenArray( &loader->parser, axis_tokens,+ T1_MAX_MM_AXIS, &num_axis );+ if ( num_axis < 0 )+ {+ error = T1_Err_Ignore;+ goto Exit;+ }+ if ( num_axis == 0 || num_axis > T1_MAX_MM_AXIS )+ {+ FT_ERROR(( "parse_blend_axis_types: incorrect number of axes: %d\n",+ num_axis ));+ error = T1_Err_Invalid_File_Format;+ goto Exit;+ }++ /* allocate blend if necessary */+ error = t1_allocate_blend( face, 0, (FT_UInt)num_axis );+ if ( error )+ goto Exit;++ blend = face->blend;+ memory = face->root.memory;++ /* each token is an immediate containing the name of the axis */+ for ( n = 0; n < num_axis; n++ )+ {+ T1_Token token = axis_tokens + n;+ FT_Byte* name;+ FT_PtrDist len;+++ /* skip first slash, if any */+ if ( token->start[0] == '/' )+ token->start++;++ len = token->limit - token->start;+ if ( len == 0 )+ {+ error = T1_Err_Invalid_File_Format;+ goto Exit;+ }++ if ( FT_ALLOC( blend->axis_names[n], len + 1 ) )+ goto Exit;++ name = (FT_Byte*)blend->axis_names[n];+ FT_MEM_COPY( name, token->start, len );+ name[len] = 0;+ }++ Exit:+ loader->parser.root.error = error;+ }+++ static void+ parse_blend_design_positions( T1_Face face,+ T1_Loader loader )+ {+ T1_TokenRec design_tokens[T1_MAX_MM_DESIGNS];+ FT_Int num_designs;+ FT_Int num_axis;+ T1_Parser parser = &loader->parser;++ FT_Error error = T1_Err_Ok;+ PS_Blend blend;+++ /* get the array of design tokens -- compute number of designs */+ T1_ToTokenArray( parser, design_tokens,+ T1_MAX_MM_DESIGNS, &num_designs );+ if ( num_designs < 0 )+ {+ error = T1_Err_Ignore;+ goto Exit;+ }+ if ( num_designs == 0 || num_designs > T1_MAX_MM_DESIGNS )+ {+ FT_ERROR(( "parse_blend_design_positions:"+ " incorrect number of designs: %d\n",+ num_designs ));+ error = T1_Err_Invalid_File_Format;+ goto Exit;+ }++ {+ FT_Byte* old_cursor = parser->root.cursor;+ FT_Byte* old_limit = parser->root.limit;+ FT_Int n;+++ blend = face->blend;+ num_axis = 0; /* make compiler happy */++ for ( n = 0; n < num_designs; n++ )+ {+ T1_TokenRec axis_tokens[T1_MAX_MM_AXIS];+ T1_Token token;+ FT_Int axis, n_axis;+++ /* read axis/coordinates tokens */+ token = design_tokens + n;+ parser->root.cursor = token->start;+ parser->root.limit = token->limit;+ T1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &n_axis );++ if ( n == 0 )+ {+ if ( n_axis <= 0 || n_axis > T1_MAX_MM_AXIS )+ {+ FT_ERROR(( "parse_blend_design_positions:"+ " invalid number of axes: %d\n",+ n_axis ));+ error = T1_Err_Invalid_File_Format;+ goto Exit;+ }++ num_axis = n_axis;+ error = t1_allocate_blend( face, num_designs, num_axis );+ if ( error )+ goto Exit;+ blend = face->blend;+ }+ else if ( n_axis != num_axis )+ {+ FT_ERROR(( "parse_blend_design_positions: incorrect table\n" ));+ error = T1_Err_Invalid_File_Format;+ goto Exit;+ }++ /* now read each axis token into the design position */+ for ( axis = 0; axis < n_axis; axis++ )+ {+ T1_Token token2 = axis_tokens + axis;+++ parser->root.cursor = token2->start;+ parser->root.limit = token2->limit;+ blend->design_pos[n][axis] = T1_ToFixed( parser, 0 );+ }+ }++ loader->parser.root.cursor = old_cursor;+ loader->parser.root.limit = old_limit;+ }++ Exit:+ loader->parser.root.error = error;+ }+++ static void+ parse_blend_design_map( T1_Face face,+ T1_Loader loader )+ {+ FT_Error error = T1_Err_Ok;+ T1_Parser parser = &loader->parser;+ PS_Blend blend;+ T1_TokenRec axis_tokens[T1_MAX_MM_AXIS];+ FT_Int n, num_axis;+ FT_Byte* old_cursor;+ FT_Byte* old_limit;+ FT_Memory memory = face->root.memory;+++ T1_ToTokenArray( parser, axis_tokens,+ T1_MAX_MM_AXIS, &num_axis );+ if ( num_axis < 0 )+ {+ error = T1_Err_Ignore;+ goto Exit;+ }+ if ( num_axis == 0 || num_axis > T1_MAX_MM_AXIS )+ {+ FT_ERROR(( "parse_blend_design_map: incorrect number of axes: %d\n",+ num_axis ));+ error = T1_Err_Invalid_File_Format;+ goto Exit;+ }++ old_cursor = parser->root.cursor;+ old_limit = parser->root.limit;++ error = t1_allocate_blend( face, 0, num_axis );+ if ( error )+ goto Exit;+ blend = face->blend;++ /* now read each axis design map */+ for ( n = 0; n < num_axis; n++ )+ {+ PS_DesignMap map = blend->design_map + n;+ T1_Token axis_token;+ T1_TokenRec point_tokens[T1_MAX_MM_MAP_POINTS];+ FT_Int p, num_points;+++ axis_token = axis_tokens + n;++ parser->root.cursor = axis_token->start;+ parser->root.limit = axis_token->limit;+ T1_ToTokenArray( parser, point_tokens,+ T1_MAX_MM_MAP_POINTS, &num_points );++ if ( num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS )+ {+ FT_ERROR(( "parse_blend_design_map: incorrect table\n" ));+ error = T1_Err_Invalid_File_Format;+ goto Exit;+ }++ /* allocate design map data */+ if ( FT_NEW_ARRAY( map->design_points, num_points * 2 ) )+ goto Exit;+ map->blend_points = map->design_points + num_points;+ map->num_points = (FT_Byte)num_points;++ for ( p = 0; p < num_points; p++ )+ {+ T1_Token point_token;+++ point_token = point_tokens + p;++ /* don't include delimiting brackets */+ parser->root.cursor = point_token->start + 1;+ parser->root.limit = point_token->limit - 1;++ map->design_points[p] = T1_ToInt( parser );+ map->blend_points [p] = T1_ToFixed( parser, 0 );+ }+ }++ parser->root.cursor = old_cursor;+ parser->root.limit = old_limit;++ Exit:+ parser->root.error = error;+ }+++ static void+ parse_weight_vector( T1_Face face,+ T1_Loader loader )+ {+ T1_TokenRec design_tokens[T1_MAX_MM_DESIGNS];+ FT_Int num_designs;+ FT_Error error = T1_Err_Ok;+ T1_Parser parser = &loader->parser;+ PS_Blend blend = face->blend;+ T1_Token token;+ FT_Int n;+ FT_Byte* old_cursor;+ FT_Byte* old_limit;+++ T1_ToTokenArray( parser, design_tokens,+ T1_MAX_MM_DESIGNS, &num_designs );+ if ( num_designs < 0 )+ {+ error = T1_Err_Ignore;+ goto Exit;+ }+ if ( num_designs == 0 || num_designs > T1_MAX_MM_DESIGNS )+ {+ FT_ERROR(( "parse_weight_vector:"+ " incorrect number of designs: %d\n",+ num_designs ));+ error = T1_Err_Invalid_File_Format;+ goto Exit;+ }++ if ( !blend || !blend->num_designs )+ {+ error = t1_allocate_blend( face, num_designs, 0 );+ if ( error )+ goto Exit;+ blend = face->blend;+ }+ else if ( blend->num_designs != (FT_UInt)num_designs )+ {+ FT_ERROR(( "parse_weight_vector:"+ " /BlendDesignPosition and /WeightVector have\n"+ " "+ " different number of elements\n" ));+ error = T1_Err_Invalid_File_Format;+ goto Exit;+ }++ old_cursor = parser->root.cursor;+ old_limit = parser->root.limit;++ for ( n = 0; n < num_designs; n++ )+ {+ token = design_tokens + n;+ parser->root.cursor = token->start;+ parser->root.limit = token->limit;++ blend->default_weight_vector[n] =+ blend->weight_vector[n] = T1_ToFixed( parser, 0 );+ }++ parser->root.cursor = old_cursor;+ parser->root.limit = old_limit;++ Exit:+ parser->root.error = error;+ }+++ /* e.g., /BuildCharArray [0 0 0 0 0 0 0 0] def */+ /* we're only interested in the number of array elements */+ static void+ parse_buildchar( T1_Face face,+ T1_Loader loader )+ {+ face->len_buildchar = T1_ToFixedArray( &loader->parser, 0, NULL, 0 );++ return;+ }+++#endif /* T1_CONFIG_OPTION_NO_MM_SUPPORT */+++++ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** TYPE 1 SYMBOL PARSING *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/++ static FT_Error+ t1_load_keyword( T1_Face face,+ T1_Loader loader,+ const T1_Field field )+ {+ FT_Error error;+ void* dummy_object;+ void** objects;+ FT_UInt max_objects;+ PS_Blend blend = face->blend;+++ /* if the keyword has a dedicated callback, call it */+ if ( field->type == T1_FIELD_TYPE_CALLBACK )+ {+ field->reader( (FT_Face)face, loader );+ error = loader->parser.root.error;+ goto Exit;+ }++ /* now, the keyword is either a simple field, or a table of fields; */+ /* we are now going to take care of it */+ switch ( field->location )+ {+ case T1_FIELD_LOCATION_FONT_INFO:+ dummy_object = &face->type1.font_info;+ objects = &dummy_object;+ max_objects = 0;++ if ( blend )+ {+ objects = (void**)blend->font_infos;+ max_objects = blend->num_designs;+ }+ break;++ case T1_FIELD_LOCATION_FONT_EXTRA:+ dummy_object = &face->type1.font_extra;+ objects = &dummy_object;+ max_objects = 0;+ break;++ case T1_FIELD_LOCATION_PRIVATE:+ dummy_object = &face->type1.private_dict;+ objects = &dummy_object;+ max_objects = 0;++ if ( blend )+ {+ objects = (void**)blend->privates;+ max_objects = blend->num_designs;+ }+ break;++ case T1_FIELD_LOCATION_BBOX:+ dummy_object = &face->type1.font_bbox;+ objects = &dummy_object;+ max_objects = 0;++ if ( blend )+ {+ objects = (void**)blend->bboxes;+ max_objects = blend->num_designs;+ }+ break;++ case T1_FIELD_LOCATION_LOADER:+ dummy_object = loader;+ objects = &dummy_object;+ max_objects = 0;+ break;++ case T1_FIELD_LOCATION_FACE:+ dummy_object = face;+ objects = &dummy_object;+ max_objects = 0;+ break;++#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT+ case T1_FIELD_LOCATION_BLEND:+ dummy_object = face->blend;+ objects = &dummy_object;+ max_objects = 0;+ break;+#endif++ default:+ dummy_object = &face->type1;+ objects = &dummy_object;+ max_objects = 0;+ }++ if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY ||+ field->type == T1_FIELD_TYPE_FIXED_ARRAY )+ error = T1_Load_Field_Table( &loader->parser, field,+ objects, max_objects, 0 );+ else+ error = T1_Load_Field( &loader->parser, field,+ objects, max_objects, 0 );++ Exit:+ return error;+ }+++ static void+ parse_private( T1_Face face,+ T1_Loader loader )+ {+ FT_UNUSED( face );++ loader->keywords_encountered |= T1_PRIVATE;+ }+++ static int+ read_binary_data( T1_Parser parser,+ FT_Long* size,+ FT_Byte** base )+ {+ FT_Byte* cur;+ FT_Byte* limit = parser->root.limit;+++ /* the binary data has one of the following formats */+ /* */+ /* `size' [white*] RD white ....... ND */+ /* `size' [white*] -| white ....... |- */+ /* */++ T1_Skip_Spaces( parser );++ cur = parser->root.cursor;++ if ( cur < limit && ft_isdigit( *cur ) )+ {+ FT_Long s = T1_ToInt( parser );+++ T1_Skip_PS_Token( parser ); /* `RD' or `-|' or something else */++ /* there is only one whitespace char after the */+ /* `RD' or `-|' token */+ *base = parser->root.cursor + 1;++ if ( s >= 0 && s < limit - *base )+ {+ parser->root.cursor += s + 1;+ *size = s;+ return !parser->root.error;+ }+ }++ FT_ERROR(( "read_binary_data: invalid size field\n" ));+ parser->root.error = T1_Err_Invalid_File_Format;+ return 0;+ }+++ /* We now define the routines to handle the `/Encoding', `/Subrs', */+ /* and `/CharStrings' dictionaries. */++ static void+ parse_font_matrix( T1_Face face,+ T1_Loader loader )+ {+ T1_Parser parser = &loader->parser;+ FT_Matrix* matrix = &face->type1.font_matrix;+ FT_Vector* offset = &face->type1.font_offset;+ FT_Face root = (FT_Face)&face->root;+ FT_Fixed temp[6];+ FT_Fixed temp_scale;+ FT_Int result;+++ result = T1_ToFixedArray( parser, 6, temp, 3 );++ if ( result < 0 )+ {+ parser->root.error = T1_Err_Invalid_File_Format;+ return;+ }++ temp_scale = FT_ABS( temp[3] );++ if ( temp_scale == 0 )+ {+ FT_ERROR(( "parse_font_matrix: invalid font matrix\n" ));+ parser->root.error = T1_Err_Invalid_File_Format;+ return;+ }++ /* Set Units per EM based on FontMatrix values. We set the value to */+ /* 1000 / temp_scale, because temp_scale was already multiplied by */+ /* 1000 (in t1_tofixed, from psobjs.c). */++ root->units_per_EM = (FT_UShort)( FT_DivFix( 1000 * 0x10000L,+ temp_scale ) >> 16 );++ /* we need to scale the values by 1.0/temp_scale */+ if ( temp_scale != 0x10000L )+ {+ temp[0] = FT_DivFix( temp[0], temp_scale );+ temp[1] = FT_DivFix( temp[1], temp_scale );+ temp[2] = FT_DivFix( temp[2], temp_scale );+ temp[4] = FT_DivFix( temp[4], temp_scale );+ temp[5] = FT_DivFix( temp[5], temp_scale );+ temp[3] = temp[3] < 0 ? -0x10000L : 0x10000L;+ }++ matrix->xx = temp[0];+ matrix->yx = temp[1];+ matrix->xy = temp[2];+ matrix->yy = temp[3];++ /* note that the offsets must be expressed in integer font units */+ offset->x = temp[4] >> 16;+ offset->y = temp[5] >> 16;+ }+++ static void+ parse_encoding( T1_Face face,+ T1_Loader loader )+ {+ T1_Parser parser = &loader->parser;+ FT_Byte* cur;+ FT_Byte* limit = parser->root.limit;++ PSAux_Service psaux = (PSAux_Service)face->psaux;+++ T1_Skip_Spaces( parser );+ cur = parser->root.cursor;+ if ( cur >= limit )+ {+ FT_ERROR(( "parse_encoding: out of bounds\n" ));+ parser->root.error = T1_Err_Invalid_File_Format;+ return;+ }++ /* if we have a number or `[', the encoding is an array, */+ /* and we must load it now */+ if ( ft_isdigit( *cur ) || *cur == '[' )+ {+ T1_Encoding encode = &face->type1.encoding;+ FT_Int count, n;+ PS_Table char_table = &loader->encoding_table;+ FT_Memory memory = parser->root.memory;+ FT_Error error;+ FT_Bool only_immediates = 0;+++ /* read the number of entries in the encoding; should be 256 */+ if ( *cur == '[' )+ {+ count = 256;+ only_immediates = 1;+ parser->root.cursor++;+ }+ else+ count = (FT_Int)T1_ToInt( parser );++ T1_Skip_Spaces( parser );+ if ( parser->root.cursor >= limit )+ return;++ /* we use a T1_Table to store our charnames */+ loader->num_chars = encode->num_chars = count;+ if ( FT_NEW_ARRAY( encode->char_index, count ) ||+ FT_NEW_ARRAY( encode->char_name, count ) ||+ FT_SET_ERROR( psaux->ps_table_funcs->init(+ char_table, count, memory ) ) )+ {+ parser->root.error = error;+ return;+ }++ /* We need to `zero' out encoding_table.elements */+ for ( n = 0; n < count; n++ )+ {+ char* notdef = (char *)".notdef";+++ T1_Add_Table( char_table, n, notdef, 8 );+ }++ /* Now we need to read records of the form */+ /* */+ /* ... charcode /charname ... */+ /* */+ /* for each entry in our table. */+ /* */+ /* We simply look for a number followed by an immediate */+ /* name. Note that this ignores correctly the sequence */+ /* that is often seen in type1 fonts: */+ /* */+ /* 0 1 255 { 1 index exch /.notdef put } for dup */+ /* */+ /* used to clean the encoding array before anything else. */+ /* */+ /* Alternatively, if the array is directly given as */+ /* */+ /* /Encoding [ ... ] */+ /* */+ /* we only read immediates. */++ n = 0;+ T1_Skip_Spaces( parser );++ while ( parser->root.cursor < limit )+ {+ cur = parser->root.cursor;++ /* we stop when we encounter a `def' or `]' */+ if ( *cur == 'd' && cur + 3 < limit )+ {+ if ( cur[1] == 'e' &&+ cur[2] == 'f' &&+ IS_PS_DELIM( cur[3] ) )+ {+ FT_TRACE6(( "encoding end\n" ));+ cur += 3;+ break;+ }+ }+ if ( *cur == ']' )+ {+ FT_TRACE6(( "encoding end\n" ));+ cur++;+ break;+ }++ /* check whether we've found an entry */+ if ( ft_isdigit( *cur ) || only_immediates )+ {+ FT_Int charcode;+++ if ( only_immediates )+ charcode = n;+ else+ {+ charcode = (FT_Int)T1_ToInt( parser );+ T1_Skip_Spaces( parser );+ }++ cur = parser->root.cursor;++ if ( *cur == '/' && cur + 2 < limit && n < count )+ {+ FT_PtrDist len;+++ cur++;++ parser->root.cursor = cur;+ T1_Skip_PS_Token( parser );+ if ( parser->root.error )+ return;++ len = parser->root.cursor - cur;++ parser->root.error = T1_Add_Table( char_table, charcode,+ cur, len + 1 );+ if ( parser->root.error )+ return;+ char_table->elements[charcode][len] = '\0';++ n++;+ }+ else if ( only_immediates )+ {+ /* Since the current position is not updated for */+ /* immediates-only mode we would get an infinite loop if */+ /* we don't do anything here. */+ /* */+ /* This encoding array is not valid according to the type1 */+ /* specification (it might be an encoding for a CID type1 */+ /* font, however), so we conclude that this font is NOT a */+ /* type1 font. */+ parser->root.error = FT_Err_Unknown_File_Format;+ return;+ }+ }+ else+ {+ T1_Skip_PS_Token( parser );+ if ( parser->root.error )+ return;+ }++ T1_Skip_Spaces( parser );+ }++ face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY;+ parser->root.cursor = cur;+ }++ /* Otherwise, we should have either `StandardEncoding', */+ /* `ExpertEncoding', or `ISOLatin1Encoding' */+ else+ {+ if ( cur + 17 < limit &&+ ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )+ face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD;++ else if ( cur + 15 < limit &&+ ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )+ face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT;++ else if ( cur + 18 < limit &&+ ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 )+ face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1;++ else+ parser->root.error = T1_Err_Ignore;+ }+ }+++ static void+ parse_subrs( T1_Face face,+ T1_Loader loader )+ {+ T1_Parser parser = &loader->parser;+ PS_Table table = &loader->subrs;+ FT_Memory memory = parser->root.memory;+ FT_Error error;+ FT_Int num_subrs;++ PSAux_Service psaux = (PSAux_Service)face->psaux;+++ T1_Skip_Spaces( parser );++ /* test for empty array */+ if ( parser->root.cursor < parser->root.limit &&+ *parser->root.cursor == '[' )+ {+ T1_Skip_PS_Token( parser );+ T1_Skip_Spaces ( parser );+ if ( parser->root.cursor >= parser->root.limit ||+ *parser->root.cursor != ']' )+ parser->root.error = T1_Err_Invalid_File_Format;+ return;+ }++ num_subrs = (FT_Int)T1_ToInt( parser );++ /* position the parser right before the `dup' of the first subr */+ T1_Skip_PS_Token( parser ); /* `array' */+ if ( parser->root.error )+ return;+ T1_Skip_Spaces( parser );++ /* initialize subrs array -- with synthetic fonts it is possible */+ /* we get here twice */+ if ( !loader->num_subrs )+ {+ error = psaux->ps_table_funcs->init( table, num_subrs, memory );+ if ( error )+ goto Fail;+ }++ /* the format is simple: */+ /* */+ /* `index' + binary data */+ /* */+ for (;;)+ {+ FT_Long idx, size;+ FT_Byte* base;+++ /* If the next token isn't `dup' we are done. */+ if ( ft_strncmp( (char*)parser->root.cursor, "dup", 3 ) != 0 )+ break;++ T1_Skip_PS_Token( parser ); /* `dup' */++ idx = T1_ToInt( parser );++ if ( !read_binary_data( parser, &size, &base ) )+ return;++ /* The binary string is followed by one token, e.g. `NP' */+ /* (bound to `noaccess put') or by two separate tokens: */+ /* `noaccess' & `put'. We position the parser right */+ /* before the next `dup', if any. */+ T1_Skip_PS_Token( parser ); /* `NP' or `|' or `noaccess' */+ if ( parser->root.error )+ return;+ T1_Skip_Spaces ( parser );++ if ( ft_strncmp( (char*)parser->root.cursor, "put", 3 ) == 0 )+ {+ T1_Skip_PS_Token( parser ); /* skip `put' */+ T1_Skip_Spaces ( parser );+ }++ /* with synthetic fonts it is possible we get here twice */+ if ( loader->num_subrs )+ continue;++ /* some fonts use a value of -1 for lenIV to indicate that */+ /* the charstrings are unencoded */+ /* */+ /* thanks to Tom Kacvinsky for pointing this out */+ /* */+ if ( face->type1.private_dict.lenIV >= 0 )+ {+ FT_Byte* temp;+++ /* some fonts define empty subr records -- this is not totally */+ /* compliant to the specification (which says they should at */+ /* least contain a `return'), but we support them anyway */+ if ( size < face->type1.private_dict.lenIV )+ {+ error = T1_Err_Invalid_File_Format;+ goto Fail;+ }++ /* t1_decrypt() shouldn't write to base -- make temporary copy */+ if ( FT_ALLOC( temp, size ) )+ goto Fail;+ FT_MEM_COPY( temp, base, size );+ psaux->t1_decrypt( temp, size, 4330 );+ size -= face->type1.private_dict.lenIV;+ error = T1_Add_Table( table, (FT_Int)idx,+ temp + face->type1.private_dict.lenIV, size );+ FT_FREE( temp );+ }+ else+ error = T1_Add_Table( table, (FT_Int)idx, base, size );+ if ( error )+ goto Fail;+ }++ if ( !loader->num_subrs )+ loader->num_subrs = num_subrs;++ return;++ Fail:+ parser->root.error = error;+ }+++#define TABLE_EXTEND 5+++ static void+ parse_charstrings( T1_Face face,+ T1_Loader loader )+ {+ T1_Parser parser = &loader->parser;+ PS_Table code_table = &loader->charstrings;+ PS_Table name_table = &loader->glyph_names;+ PS_Table swap_table = &loader->swap_table;+ FT_Memory memory = parser->root.memory;+ FT_Error error;++ PSAux_Service psaux = (PSAux_Service)face->psaux;++ FT_Byte* cur;+ FT_Byte* limit = parser->root.limit;+ FT_Int n, num_glyphs;+ FT_UInt notdef_index = 0;+ FT_Byte notdef_found = 0;+++ num_glyphs = (FT_Int)T1_ToInt( parser );+ /* some fonts like Optima-Oblique not only define the /CharStrings */+ /* array but access it also */+ if ( num_glyphs == 0 || parser->root.error )+ return;++ /* initialize tables, leaving space for addition of .notdef, */+ /* if necessary, and a few other glyphs to handle buggy */+ /* fonts which have more glyphs than specified. */++ /* for some non-standard fonts like `Optima' which provides */+ /* different outlines depending on the resolution it is */+ /* possible to get here twice */+ if ( !loader->num_glyphs )+ {+ error = psaux->ps_table_funcs->init(+ code_table, num_glyphs + 1 + TABLE_EXTEND, memory );+ if ( error )+ goto Fail;++ error = psaux->ps_table_funcs->init(+ name_table, num_glyphs + 1 + TABLE_EXTEND, memory );+ if ( error )+ goto Fail;++ /* Initialize table for swapping index notdef_index and */+ /* index 0 names and codes (if necessary). */++ error = psaux->ps_table_funcs->init( swap_table, 4, memory );+ if ( error )+ goto Fail;+ }++ n = 0;++ for (;;)+ {+ FT_Long size;+ FT_Byte* base;+++ /* the format is simple: */+ /* `/glyphname' + binary data */++ T1_Skip_Spaces( parser );++ cur = parser->root.cursor;+ if ( cur >= limit )+ break;++ /* we stop when we find a `def' or `end' keyword */+ if ( cur + 3 < limit && IS_PS_DELIM( cur[3] ) )+ {+ if ( cur[0] == 'd' &&+ cur[1] == 'e' &&+ cur[2] == 'f' )+ {+ /* There are fonts which have this: */+ /* */+ /* /CharStrings 118 dict def */+ /* Private begin */+ /* CharStrings begin */+ /* ... */+ /* */+ /* To catch this we ignore `def' if */+ /* no charstring has actually been */+ /* seen. */+ if ( n )+ break;+ }++ if ( cur[0] == 'e' &&+ cur[1] == 'n' &&+ cur[2] == 'd' )+ break;+ }++ T1_Skip_PS_Token( parser );+ if ( parser->root.error )+ return;++ if ( *cur == '/' )+ {+ FT_PtrDist len;+++ if ( cur + 1 >= limit )+ {+ error = T1_Err_Invalid_File_Format;+ goto Fail;+ }++ cur++; /* skip `/' */+ len = parser->root.cursor - cur;++ if ( !read_binary_data( parser, &size, &base ) )+ return;++ /* for some non-standard fonts like `Optima' which provides */+ /* different outlines depending on the resolution it is */+ /* possible to get here twice */+ if ( loader->num_glyphs )+ continue;++ error = T1_Add_Table( name_table, n, cur, len + 1 );+ if ( error )+ goto Fail;++ /* add a trailing zero to the name table */+ name_table->elements[n][len] = '\0';++ /* record index of /.notdef */+ if ( *cur == '.' &&+ ft_strcmp( ".notdef",+ (const char*)(name_table->elements[n]) ) == 0 )+ {+ notdef_index = n;+ notdef_found = 1;+ }++ if ( face->type1.private_dict.lenIV >= 0 &&+ n < num_glyphs + TABLE_EXTEND )+ {+ FT_Byte* temp;+++ if ( size <= face->type1.private_dict.lenIV )+ {+ error = T1_Err_Invalid_File_Format;+ goto Fail;+ }++ /* t1_decrypt() shouldn't write to base -- make temporary copy */+ if ( FT_ALLOC( temp, size ) )+ goto Fail;+ FT_MEM_COPY( temp, base, size );+ psaux->t1_decrypt( temp, size, 4330 );+ size -= face->type1.private_dict.lenIV;+ error = T1_Add_Table( code_table, n,+ temp + face->type1.private_dict.lenIV, size );+ FT_FREE( temp );+ }+ else+ error = T1_Add_Table( code_table, n, base, size );+ if ( error )+ goto Fail;++ n++;+ }+ }++ loader->num_glyphs = n;++ /* if /.notdef is found but does not occupy index 0, do our magic. */+ if ( notdef_found &&+ ft_strcmp( ".notdef", (const char*)name_table->elements[0] ) )+ {+ /* Swap glyph in index 0 with /.notdef glyph. First, add index 0 */+ /* name and code entries to swap_table. Then place notdef_index */+ /* name and code entries into swap_table. Then swap name and code */+ /* entries at indices notdef_index and 0 using values stored in */+ /* swap_table. */++ /* Index 0 name */+ error = T1_Add_Table( swap_table, 0,+ name_table->elements[0],+ name_table->lengths [0] );+ if ( error )+ goto Fail;++ /* Index 0 code */+ error = T1_Add_Table( swap_table, 1,+ code_table->elements[0],+ code_table->lengths [0] );+ if ( error )+ goto Fail;++ /* Index notdef_index name */+ error = T1_Add_Table( swap_table, 2,+ name_table->elements[notdef_index],+ name_table->lengths [notdef_index] );+ if ( error )+ goto Fail;++ /* Index notdef_index code */+ error = T1_Add_Table( swap_table, 3,+ code_table->elements[notdef_index],+ code_table->lengths [notdef_index] );+ if ( error )+ goto Fail;++ error = T1_Add_Table( name_table, notdef_index,+ swap_table->elements[0],+ swap_table->lengths [0] );+ if ( error )+ goto Fail;++ error = T1_Add_Table( code_table, notdef_index,+ swap_table->elements[1],+ swap_table->lengths [1] );+ if ( error )+ goto Fail;++ error = T1_Add_Table( name_table, 0,+ swap_table->elements[2],+ swap_table->lengths [2] );+ if ( error )+ goto Fail;++ error = T1_Add_Table( code_table, 0,+ swap_table->elements[3],+ swap_table->lengths [3] );+ if ( error )+ goto Fail;++ }+ else if ( !notdef_found )+ {+ /* notdef_index is already 0, or /.notdef is undefined in */+ /* charstrings dictionary. Worry about /.notdef undefined. */+ /* We take index 0 and add it to the end of the table(s) */+ /* and add our own /.notdef glyph to index 0. */++ /* 0 333 hsbw endchar */+ FT_Byte notdef_glyph[] = { 0x8B, 0xF7, 0xE1, 0x0D, 0x0E };+ char* notdef_name = (char *)".notdef";+++ error = T1_Add_Table( swap_table, 0,+ name_table->elements[0],+ name_table->lengths [0] );+ if ( error )+ goto Fail;++ error = T1_Add_Table( swap_table, 1,+ code_table->elements[0],+ code_table->lengths [0] );+ if ( error )+ goto Fail;++ error = T1_Add_Table( name_table, 0, notdef_name, 8 );+ if ( error )+ goto Fail;++ error = T1_Add_Table( code_table, 0, notdef_glyph, 5 );++ if ( error )+ goto Fail;++ error = T1_Add_Table( name_table, n,+ swap_table->elements[0],+ swap_table->lengths [0] );+ if ( error )+ goto Fail;++ error = T1_Add_Table( code_table, n,+ swap_table->elements[1],+ swap_table->lengths [1] );+ if ( error )+ goto Fail;++ /* we added a glyph. */+ loader->num_glyphs += 1;+ }++ return;++ Fail:+ parser->root.error = error;+ }+++ /*************************************************************************/+ /* */+ /* Define the token field static variables. This is a set of */+ /* T1_FieldRec variables. */+ /* */+ /*************************************************************************/+++ static+ const T1_FieldRec t1_keywords[] =+ {++#include "t1tokens.h"++ /* now add the special functions... */+ T1_FIELD_CALLBACK( "FontMatrix", parse_font_matrix,+ T1_FIELD_DICT_FONTDICT )+ T1_FIELD_CALLBACK( "Encoding", parse_encoding,+ T1_FIELD_DICT_FONTDICT )+ T1_FIELD_CALLBACK( "Subrs", parse_subrs,+ T1_FIELD_DICT_PRIVATE )+ T1_FIELD_CALLBACK( "CharStrings", parse_charstrings,+ T1_FIELD_DICT_PRIVATE )+ T1_FIELD_CALLBACK( "Private", parse_private,+ T1_FIELD_DICT_FONTDICT )++#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT+ T1_FIELD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions,+ T1_FIELD_DICT_FONTDICT )+ T1_FIELD_CALLBACK( "BlendDesignMap", parse_blend_design_map,+ T1_FIELD_DICT_FONTDICT )+ T1_FIELD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types,+ T1_FIELD_DICT_FONTDICT )+ T1_FIELD_CALLBACK( "WeightVector", parse_weight_vector,+ T1_FIELD_DICT_FONTDICT )+ T1_FIELD_CALLBACK( "BuildCharArray", parse_buildchar,+ T1_FIELD_DICT_PRIVATE )+#endif++ { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 }+ };+++#define T1_FIELD_COUNT \+ ( sizeof ( t1_keywords ) / sizeof ( t1_keywords[0] ) )+++ static FT_Error+ parse_dict( T1_Face face,+ T1_Loader loader,+ FT_Byte* base,+ FT_Long size )+ {+ T1_Parser parser = &loader->parser;+ FT_Byte *limit, *start_binary = NULL;+ FT_Bool have_integer = 0;+++ parser->root.cursor = base;+ parser->root.limit = base + size;+ parser->root.error = T1_Err_Ok;++ limit = parser->root.limit;++ T1_Skip_Spaces( parser );++ while ( parser->root.cursor < limit )+ {+ FT_Byte* cur;+++ cur = parser->root.cursor;++ /* look for `eexec' */+ if ( IS_PS_TOKEN( cur, limit, "eexec" ) )+ break;++ /* look for `closefile' which ends the eexec section */+ else if ( IS_PS_TOKEN( cur, limit, "closefile" ) )+ break;++ /* in a synthetic font the base font starts after a */+ /* `FontDictionary' token that is placed after a Private dict */+ else if ( IS_PS_TOKEN( cur, limit, "FontDirectory" ) )+ {+ if ( loader->keywords_encountered & T1_PRIVATE )+ loader->keywords_encountered |=+ T1_FONTDIR_AFTER_PRIVATE;+ parser->root.cursor += 13;+ }++ /* check whether we have an integer */+ else if ( ft_isdigit( *cur ) )+ {+ start_binary = cur;+ T1_Skip_PS_Token( parser );+ if ( parser->root.error )+ goto Exit;+ have_integer = 1;+ }++ /* in valid Type 1 fonts we don't see `RD' or `-|' directly */+ /* since those tokens are handled by parse_subrs and */+ /* parse_charstrings */+ else if ( *cur == 'R' && cur + 6 < limit && *(cur + 1) == 'D' &&+ have_integer )+ {+ FT_Long s;+ FT_Byte* b;+++ parser->root.cursor = start_binary;+ if ( !read_binary_data( parser, &s, &b ) )+ return T1_Err_Invalid_File_Format;+ have_integer = 0;+ }++ else if ( *cur == '-' && cur + 6 < limit && *(cur + 1) == '|' &&+ have_integer )+ {+ FT_Long s;+ FT_Byte* b;+++ parser->root.cursor = start_binary;+ if ( !read_binary_data( parser, &s, &b ) )+ return T1_Err_Invalid_File_Format;+ have_integer = 0;+ }++ /* look for immediates */+ else if ( *cur == '/' && cur + 2 < limit )+ {+ FT_PtrDist len;+++ cur++;++ parser->root.cursor = cur;+ T1_Skip_PS_Token( parser );+ if ( parser->root.error )+ goto Exit;++ len = parser->root.cursor - cur;++ if ( len > 0 && len < 22 && parser->root.cursor < limit )+ {+ /* now compare the immediate name to the keyword table */+ T1_Field keyword = (T1_Field)t1_keywords;+++ for (;;)+ {+ FT_Byte* name;+++ name = (FT_Byte*)keyword->ident;+ if ( !name )+ break;++ if ( cur[0] == name[0] &&+ len == (FT_PtrDist)ft_strlen( (const char *)name ) &&+ ft_memcmp( cur, name, len ) == 0 )+ {+ /* We found it -- run the parsing callback! */+ /* We record every instance of every field */+ /* (until we reach the base font of a */+ /* synthetic font) to deal adequately with */+ /* multiple master fonts; this is also */+ /* necessary because later PostScript */+ /* definitions override earlier ones. */++ /* Once we encounter `FontDirectory' after */+ /* `/Private', we know that this is a synthetic */+ /* font; except for `/CharStrings' we are not */+ /* interested in anything that follows this */+ /* `FontDirectory'. */++ /* MM fonts have more than one /Private token at */+ /* the top level; let's hope that all the junk */+ /* that follows the first /Private token is not */+ /* interesting to us. */++ /* According to Adobe Tech Note #5175 (CID-Keyed */+ /* Font Installation for ATM Software) a `begin' */+ /* must be followed by exactly one `end', and */+ /* `begin' -- `end' pairs must be accurately */+ /* paired. We could use this to distinguish */+ /* between the global Private and the Private */+ /* dict that is a member of the Blend dict. */++ const FT_UInt dict =+ ( loader->keywords_encountered & T1_PRIVATE )+ ? T1_FIELD_DICT_PRIVATE+ : T1_FIELD_DICT_FONTDICT;++ if ( !( dict & keyword->dict ) )+ {+ FT_TRACE1(( "parse_dict: found %s but ignoring it "+ "since it is in the wrong dictionary\n",+ keyword->ident ));+ break;+ }++ if ( !( loader->keywords_encountered &+ T1_FONTDIR_AFTER_PRIVATE ) ||+ ft_strcmp( (const char*)name, "CharStrings" ) == 0 )+ {+ parser->root.error = t1_load_keyword( face,+ loader,+ keyword );+ if ( parser->root.error != T1_Err_Ok )+ {+ if ( FT_ERROR_BASE( parser->root.error ) == FT_Err_Ignore )+ parser->root.error = T1_Err_Ok;+ else+ return parser->root.error;+ }+ }+ break;+ }++ keyword++;+ }+ }++ have_integer = 0;+ }+ else+ {+ T1_Skip_PS_Token( parser );+ if ( parser->root.error )+ goto Exit;+ have_integer = 0;+ }++ T1_Skip_Spaces( parser );+ }++ Exit:+ return parser->root.error;+ }+++ static void+ t1_init_loader( T1_Loader loader,+ T1_Face face )+ {+ FT_UNUSED( face );++ FT_MEM_ZERO( loader, sizeof ( *loader ) );+ loader->num_glyphs = 0;+ loader->num_chars = 0;++ /* initialize the tables -- simply set their `init' field to 0 */+ loader->encoding_table.init = 0;+ loader->charstrings.init = 0;+ loader->glyph_names.init = 0;+ loader->subrs.init = 0;+ loader->swap_table.init = 0;+ loader->fontdata = 0;+ loader->keywords_encountered = 0;+ }+++ static void+ t1_done_loader( T1_Loader loader )+ {+ T1_Parser parser = &loader->parser;+++ /* finalize tables */+ T1_Release_Table( &loader->encoding_table );+ T1_Release_Table( &loader->charstrings );+ T1_Release_Table( &loader->glyph_names );+ T1_Release_Table( &loader->swap_table );+ T1_Release_Table( &loader->subrs );++ /* finalize parser */+ T1_Finalize_Parser( parser );+ }+++ FT_LOCAL_DEF( FT_Error )+ T1_Open_Face( T1_Face face )+ {+ T1_LoaderRec loader;+ T1_Parser parser;+ T1_Font type1 = &face->type1;+ PS_Private priv = &type1->private_dict;+ FT_Error error;++ PSAux_Service psaux = (PSAux_Service)face->psaux;+++ t1_init_loader( &loader, face );++ /* default values */+ face->ndv_idx = -1;+ face->cdv_idx = -1;+ face->len_buildchar = 0;++ priv->blue_shift = 7;+ priv->blue_fuzz = 1;+ priv->lenIV = 4;+ priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L );+ priv->blue_scale = (FT_Fixed)( 0.039625 * 0x10000L * 1000 );++ parser = &loader.parser;+ error = T1_New_Parser( parser,+ face->root.stream,+ face->root.memory,+ psaux );+ if ( error )+ goto Exit;++ error = parse_dict( face, &loader,+ parser->base_dict, parser->base_len );+ if ( error )+ goto Exit;++ error = T1_Get_Private_Dict( parser, psaux );+ if ( error )+ goto Exit;++ error = parse_dict( face, &loader,+ parser->private_dict, parser->private_len );+ if ( error )+ goto Exit;++ /* ensure even-ness of `num_blue_values' */+ priv->num_blue_values &= ~1;++#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT++ if ( face->blend &&+ face->blend->num_default_design_vector != 0 &&+ face->blend->num_default_design_vector != face->blend->num_axis )+ {+ /* we don't use it currently so just warn, reset, and ignore */+ FT_ERROR(( "T1_Open_Face(): /DesignVector contains %u entries "+ "while there are %u axes.\n",+ face->blend->num_default_design_vector,+ face->blend->num_axis ));++ face->blend->num_default_design_vector = 0;+ }++ /* the following can happen for MM instances; we then treat the */+ /* font as a normal PS font */+ if ( face->blend &&+ ( !face->blend->num_designs || !face->blend->num_axis ) )+ T1_Done_Blend( face );++ /* another safety check */+ if ( face->blend )+ {+ FT_UInt i;+++ for ( i = 0; i < face->blend->num_axis; i++ )+ if ( !face->blend->design_map[i].num_points )+ {+ T1_Done_Blend( face );+ break;+ }+ }++ if ( face->blend )+ {+ if ( face->len_buildchar > 0 )+ {+ FT_Memory memory = face->root.memory;+++ if ( FT_NEW_ARRAY( face->buildchar, face->len_buildchar ) )+ {+ FT_ERROR(( "T1_Open_Face: cannot allocate BuildCharArray\n" ));+ face->len_buildchar = 0;+ goto Exit;+ }+ }+ }++#endif /* T1_CONFIG_OPTION_NO_MM_SUPPORT */++ /* now, propagate the subrs, charstrings, and glyphnames tables */+ /* to the Type1 data */+ type1->num_glyphs = loader.num_glyphs;++ if ( loader.subrs.init )+ {+ loader.subrs.init = 0;+ type1->num_subrs = loader.num_subrs;+ type1->subrs_block = loader.subrs.block;+ type1->subrs = loader.subrs.elements;+ type1->subrs_len = loader.subrs.lengths;+ }++#ifdef FT_CONFIG_OPTION_INCREMENTAL+ if ( !face->root.internal->incremental_interface )+#endif+ if ( !loader.charstrings.init )+ {+ FT_ERROR(( "T1_Open_Face: no `/CharStrings' array in face\n" ));+ error = T1_Err_Invalid_File_Format;+ }++ loader.charstrings.init = 0;+ type1->charstrings_block = loader.charstrings.block;+ type1->charstrings = loader.charstrings.elements;+ type1->charstrings_len = loader.charstrings.lengths;++ /* we copy the glyph names `block' and `elements' fields; */+ /* the `lengths' field must be released later */+ type1->glyph_names_block = loader.glyph_names.block;+ type1->glyph_names = (FT_String**)loader.glyph_names.elements;+ loader.glyph_names.block = 0;+ loader.glyph_names.elements = 0;++ /* we must now build type1.encoding when we have a custom array */+ if ( type1->encoding_type == T1_ENCODING_TYPE_ARRAY )+ {+ FT_Int charcode, idx, min_char, max_char;+ FT_Byte* char_name;+ FT_Byte* glyph_name;+++ /* OK, we do the following: for each element in the encoding */+ /* table, look up the index of the glyph having the same name */+ /* the index is then stored in type1.encoding.char_index, and */+ /* the name to type1.encoding.char_name */++ min_char = 0;+ max_char = 0;++ charcode = 0;+ for ( ; charcode < loader.encoding_table.max_elems; charcode++ )+ {+ type1->encoding.char_index[charcode] = 0;+ type1->encoding.char_name [charcode] = (char *)".notdef";++ char_name = loader.encoding_table.elements[charcode];+ if ( char_name )+ for ( idx = 0; idx < type1->num_glyphs; idx++ )+ {+ glyph_name = (FT_Byte*)type1->glyph_names[idx];+ if ( ft_strcmp( (const char*)char_name,+ (const char*)glyph_name ) == 0 )+ {+ type1->encoding.char_index[charcode] = (FT_UShort)idx;+ type1->encoding.char_name [charcode] = (char*)glyph_name;++ /* Change min/max encoded char only if glyph name is */+ /* not /.notdef */+ if ( ft_strcmp( (const char*)".notdef",+ (const char*)glyph_name ) != 0 )+ {+ if ( charcode < min_char )+ min_char = charcode;+ if ( charcode >= max_char )+ max_char = charcode + 1;+ }+ break;+ }+ }+ }++ type1->encoding.code_first = min_char;+ type1->encoding.code_last = max_char;+ type1->encoding.num_chars = loader.num_chars;+ }++ Exit:+ t1_done_loader( &loader );+ return error;+ }+++/* END */
+ src/type1/t1load.h view
@@ -0,0 +1,102 @@+/***************************************************************************/+/* */+/* t1load.h */+/* */+/* Type 1 font loader (specification). */+/* */+/* Copyright 1996-2001, 2002, 2004, 2006, 2007 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 __T1LOAD_H__+#define __T1LOAD_H__+++#include <ft2build.h>+#include FT_INTERNAL_STREAM_H+#include FT_INTERNAL_POSTSCRIPT_AUX_H+#include FT_MULTIPLE_MASTERS_H++#include "t1parse.h"+++FT_BEGIN_HEADER+++ typedef struct T1_Loader_+ {+ T1_ParserRec parser; /* parser used to read the stream */++ FT_Int num_chars; /* number of characters in encoding */+ PS_TableRec encoding_table; /* PS_Table used to store the */+ /* encoding character names */++ FT_Int num_glyphs;+ PS_TableRec glyph_names;+ PS_TableRec charstrings;+ PS_TableRec swap_table; /* For moving .notdef glyph to index 0. */++ FT_Int num_subrs;+ PS_TableRec subrs;+ FT_Bool fontdata;++ FT_UInt keywords_encountered; /* T1_LOADER_ENCOUNTERED_XXX */++ } T1_LoaderRec, *T1_Loader;+++ /* treatment of some keywords differs depending on whether */+ /* they precede or follow certain other keywords */++#define T1_PRIVATE ( 1 << 0 )+#define T1_FONTDIR_AFTER_PRIVATE ( 1 << 1 )+++ FT_LOCAL( FT_Error )+ T1_Open_Face( T1_Face face );++#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT++ FT_LOCAL( FT_Error )+ T1_Get_Multi_Master( T1_Face face,+ FT_Multi_Master* master );++ FT_LOCAL_DEF( FT_Error )+ T1_Get_MM_Var( T1_Face face,+ FT_MM_Var* *master );++ FT_LOCAL( FT_Error )+ T1_Set_MM_Blend( T1_Face face,+ FT_UInt num_coords,+ FT_Fixed* coords );++ FT_LOCAL( FT_Error )+ T1_Set_MM_Design( T1_Face face,+ FT_UInt num_coords,+ FT_Long* coords );++ FT_LOCAL_DEF( FT_Error )+ T1_Set_Var_Design( T1_Face face,+ FT_UInt num_coords,+ FT_Fixed* coords );++ FT_LOCAL( void )+ T1_Done_Blend( T1_Face face );++#endif /* !T1_CONFIG_OPTION_NO_MM_SUPPORT */+++FT_END_HEADER++#endif /* __T1LOAD_H__ */+++/* END */
+ src/type1/t1objs.c view
@@ -0,0 +1,597 @@+/***************************************************************************/+/* */+/* t1objs.c */+/* */+/* Type 1 objects manager (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 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_CALC_H+#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_STREAM_H+#include FT_TRUETYPE_IDS_H++#include "t1gload.h"+#include "t1load.h"++#include "t1errors.h"++#ifndef T1_CONFIG_OPTION_NO_AFM+#include "t1afm.h"+#endif++#include FT_SERVICE_POSTSCRIPT_CMAPS_H+#include FT_INTERNAL_POSTSCRIPT_AUX_H+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_t1objs+++ /*************************************************************************/+ /* */+ /* SIZE FUNCTIONS */+ /* */+ /* note that we store the global hints in the size's "internal" root */+ /* field */+ /* */+ /*************************************************************************/+++ static PSH_Globals_Funcs+ T1_Size_Get_Globals_Funcs( T1_Size size )+ {+ T1_Face face = (T1_Face)size->root.face;+ PSHinter_Service pshinter = (PSHinter_Service)face->pshinter;+ FT_Module module;+++ module = FT_Get_Module( size->root.face->driver->root.library,+ "pshinter" );+ return ( module && pshinter && pshinter->get_globals_funcs )+ ? pshinter->get_globals_funcs( module )+ : 0 ;+ }+++ FT_LOCAL_DEF( void )+ T1_Size_Done( T1_Size size )+ {+ if ( size->root.internal )+ {+ PSH_Globals_Funcs funcs;+++ funcs = T1_Size_Get_Globals_Funcs( size );+ if ( funcs )+ funcs->destroy( (PSH_Globals)size->root.internal );++ size->root.internal = 0;+ }+ }+++ FT_LOCAL_DEF( FT_Error )+ T1_Size_Init( T1_Size size )+ {+ FT_Error error = T1_Err_Ok;+ PSH_Globals_Funcs funcs = T1_Size_Get_Globals_Funcs( size );+++ if ( funcs )+ {+ PSH_Globals globals;+ T1_Face face = (T1_Face)size->root.face;+++ error = funcs->create( size->root.face->memory,+ &face->type1.private_dict, &globals );+ if ( !error )+ size->root.internal = (FT_Size_Internal)(void*)globals;+ }++ return error;+ }+++ FT_LOCAL_DEF( FT_Error )+ T1_Size_Request( T1_Size size,+ FT_Size_Request req )+ {+ PSH_Globals_Funcs funcs = T1_Size_Get_Globals_Funcs( size );+++ FT_Request_Metrics( size->root.face, req );++ if ( funcs )+ funcs->set_scale( (PSH_Globals)size->root.internal,+ size->root.metrics.x_scale,+ size->root.metrics.y_scale,+ 0, 0 );++ return T1_Err_Ok;+ }+++ /*************************************************************************/+ /* */+ /* SLOT FUNCTIONS */+ /* */+ /*************************************************************************/++ FT_LOCAL_DEF( void )+ T1_GlyphSlot_Done( T1_GlyphSlot slot )+ {+ slot->root.internal->glyph_hints = 0;+ }+++ FT_LOCAL_DEF( FT_Error )+ T1_GlyphSlot_Init( T1_GlyphSlot slot )+ {+ T1_Face face;+ PSHinter_Service pshinter;+++ face = (T1_Face)slot->root.face;+ pshinter = (PSHinter_Service)face->pshinter;++ if ( pshinter )+ {+ FT_Module module;+++ module = FT_Get_Module( slot->root.face->driver->root.library, "pshinter" );+ if (module)+ {+ T1_Hints_Funcs funcs;++ funcs = pshinter->get_t1_funcs( module );+ slot->root.internal->glyph_hints = (void*)funcs;+ }+ }+ return 0;+ }+++ /*************************************************************************/+ /* */+ /* FACE FUNCTIONS */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* T1_Face_Done */+ /* */+ /* <Description> */+ /* The face object destructor. */+ /* */+ /* <Input> */+ /* face :: A typeless pointer to the face object to destroy. */+ /* */+ FT_LOCAL_DEF( void )+ T1_Face_Done( T1_Face face )+ {+ FT_Memory memory;+ T1_Font type1;+++ if ( !face )+ return;++ memory = face->root.memory;+ type1 = &face->type1;++#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT+ /* release multiple masters information */+ FT_ASSERT( ( face->len_buildchar == 0 ) == ( face->buildchar == NULL ) );++ if ( face->buildchar )+ {+ FT_FREE( face->buildchar );++ face->buildchar = NULL;+ face->len_buildchar = 0;+ }++ T1_Done_Blend( face );+ face->blend = 0;+#endif++ /* release font info strings */+ {+ PS_FontInfo info = &type1->font_info;+++ FT_FREE( info->version );+ FT_FREE( info->notice );+ FT_FREE( info->full_name );+ FT_FREE( info->family_name );+ FT_FREE( info->weight );+ }++ /* release top dictionary */+ FT_FREE( type1->charstrings_len );+ FT_FREE( type1->charstrings );+ FT_FREE( type1->glyph_names );++ FT_FREE( type1->subrs );+ FT_FREE( type1->subrs_len );++ FT_FREE( type1->subrs_block );+ FT_FREE( type1->charstrings_block );+ FT_FREE( type1->glyph_names_block );++ FT_FREE( type1->encoding.char_index );+ FT_FREE( type1->encoding.char_name );+ FT_FREE( type1->font_name );++#ifndef T1_CONFIG_OPTION_NO_AFM+ /* release afm data if present */+ if ( face->afm_data )+ T1_Done_Metrics( memory, (AFM_FontInfo)face->afm_data );+#endif++ /* release unicode map, if any */+#if 0+ FT_FREE( face->unicode_map_rec.maps );+ face->unicode_map_rec.num_maps = 0;+ face->unicode_map = NULL;+#endif++ face->root.family_name = NULL;+ face->root.style_name = NULL;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* T1_Face_Init */+ /* */+ /* <Description> */+ /* The face object constructor. */+ /* */+ /* <Input> */+ /* stream :: input stream where to load font data. */+ /* */+ /* face_index :: The index of the font face in the resource. */+ /* */+ /* num_params :: Number of additional generic parameters. Ignored. */+ /* */+ /* params :: Additional generic parameters. Ignored. */+ /* */+ /* <InOut> */+ /* face :: The face record to build. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ T1_Face_Init( FT_Stream stream,+ T1_Face face,+ FT_Int face_index,+ FT_Int num_params,+ FT_Parameter* params )+ {+ FT_Error error;+ FT_Service_PsCMaps psnames;+ PSAux_Service psaux;+ T1_Font type1 = &face->type1;+ PS_FontInfo info = &type1->font_info;++ FT_UNUSED( num_params );+ FT_UNUSED( params );+ FT_UNUSED( stream );+++ face->root.num_faces = 1;++ FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );+ face->psnames = psnames;++ face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),+ "psaux" );+ psaux = (PSAux_Service)face->psaux;++ face->pshinter = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),+ "pshinter" );++ /* open the tokenizer; this will also check the font format */+ error = T1_Open_Face( face );+ if ( error )+ goto Exit;++ /* if we just wanted to check the format, leave successfully now */+ if ( face_index < 0 )+ goto Exit;++ /* check the face index */+ if ( face_index > 0 )+ {+ FT_ERROR(( "T1_Face_Init: invalid face index\n" ));+ error = T1_Err_Invalid_Argument;+ goto Exit;+ }++ /* now load the font program into the face object */++ /* initialize the face object fields */++ /* set up root face fields */+ {+ FT_Face root = (FT_Face)&face->root;+++ root->num_glyphs = type1->num_glyphs;+ root->face_index = 0;++ root->face_flags = FT_FACE_FLAG_SCALABLE |+ FT_FACE_FLAG_HORIZONTAL |+ FT_FACE_FLAG_GLYPH_NAMES |+ FT_FACE_FLAG_HINTER;++ if ( info->is_fixed_pitch )+ root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;++ if ( face->blend )+ root->face_flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;++ /* XXX: TODO -- add kerning with .afm support */+++ /* The following code to extract the family and the style is very */+ /* simplistic and might get some things wrong. For a full-featured */+ /* algorithm you might have a look at the whitepaper given at */+ /* */+ /* http://blogs.msdn.com/text/archive/2007/04/23/wpf-font-selection-model.aspx */++ /* get style name -- be careful, some broken fonts only */+ /* have a `/FontName' dictionary entry! */+ root->family_name = info->family_name;+ root->style_name = NULL;++ if ( root->family_name )+ {+ char* full = info->full_name;+ char* family = root->family_name;+++ if ( full )+ {+ FT_Bool the_same = TRUE;+++ while ( *full )+ {+ if ( *full == *family )+ {+ family++;+ full++;+ }+ else+ {+ if ( *full == ' ' || *full == '-' )+ full++;+ else if ( *family == ' ' || *family == '-' )+ family++;+ else+ {+ the_same = FALSE;++ if ( !*family )+ root->style_name = full;+ break;+ }+ }+ }++ if ( the_same )+ root->style_name = (char *)"Regular";+ }+ }+ else+ {+ /* do we have a `/FontName'? */+ if ( type1->font_name )+ root->family_name = type1->font_name;+ }++ if ( !root->style_name )+ {+ if ( info->weight )+ root->style_name = info->weight;+ else+ /* assume `Regular' style because we don't know better */+ root->style_name = (char *)"Regular";+ }++ /* compute style flags */+ root->style_flags = 0;+ if ( info->italic_angle )+ root->style_flags |= FT_STYLE_FLAG_ITALIC;+ if ( info->weight )+ {+ if ( !ft_strcmp( info->weight, "Bold" ) ||+ !ft_strcmp( info->weight, "Black" ) )+ root->style_flags |= FT_STYLE_FLAG_BOLD;+ }++ /* no embedded bitmap support */+ root->num_fixed_sizes = 0;+ root->available_sizes = 0;++ root->bbox.xMin = type1->font_bbox.xMin >> 16;+ root->bbox.yMin = type1->font_bbox.yMin >> 16;+ /* no `U' suffix here to 0xFFFF! */+ root->bbox.xMax = ( type1->font_bbox.xMax + 0xFFFF ) >> 16;+ root->bbox.yMax = ( type1->font_bbox.yMax + 0xFFFF ) >> 16;++ /* Set units_per_EM if we didn't set it in parse_font_matrix. */+ if ( !root->units_per_EM )+ root->units_per_EM = 1000;++ root->ascender = (FT_Short)( root->bbox.yMax );+ root->descender = (FT_Short)( root->bbox.yMin );++ root->height = (FT_Short)( ( root->units_per_EM * 12 ) / 10 );+ if ( root->height < root->ascender - root->descender )+ root->height = (FT_Short)( root->ascender - root->descender );++ /* now compute the maximum advance width */+ root->max_advance_width =+ (FT_Short)( root->bbox.xMax );+ {+ FT_Pos max_advance;+++ error = T1_Compute_Max_Advance( face, &max_advance );++ /* in case of error, keep the standard width */+ if ( !error )+ root->max_advance_width = (FT_Short)FIXED_TO_INT( max_advance );+ else+ error = T1_Err_Ok; /* clear error */+ }++ root->max_advance_height = root->height;++ root->underline_position = (FT_Short)info->underline_position;+ root->underline_thickness = (FT_Short)info->underline_thickness;+ }++ {+ FT_Face root = &face->root;+++ if ( psnames && psaux )+ {+ FT_CharMapRec charmap;+ T1_CMap_Classes cmap_classes = psaux->t1_cmap_classes;+ FT_CMap_Class clazz;+++ charmap.face = root;++ /* first of all, try to synthesize a Unicode charmap */+ charmap.platform_id = TT_PLATFORM_MICROSOFT;+ charmap.encoding_id = TT_MS_ID_UNICODE_CS;+ charmap.encoding = FT_ENCODING_UNICODE;++ error = FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL );+ if ( error && FT_Err_No_Unicode_Glyph_Name != error )+ goto Exit;+ error = FT_Err_Ok;++ /* now, generate an Adobe Standard encoding when appropriate */+ charmap.platform_id = TT_PLATFORM_ADOBE;+ clazz = NULL;++ switch ( type1->encoding_type )+ {+ case T1_ENCODING_TYPE_STANDARD:+ charmap.encoding = FT_ENCODING_ADOBE_STANDARD;+ charmap.encoding_id = TT_ADOBE_ID_STANDARD;+ clazz = cmap_classes->standard;+ break;++ case T1_ENCODING_TYPE_EXPERT:+ charmap.encoding = FT_ENCODING_ADOBE_EXPERT;+ charmap.encoding_id = TT_ADOBE_ID_EXPERT;+ clazz = cmap_classes->expert;+ break;++ case T1_ENCODING_TYPE_ARRAY:+ charmap.encoding = FT_ENCODING_ADOBE_CUSTOM;+ charmap.encoding_id = TT_ADOBE_ID_CUSTOM;+ clazz = cmap_classes->custom;+ break;++ case T1_ENCODING_TYPE_ISOLATIN1:+ charmap.encoding = FT_ENCODING_ADOBE_LATIN_1;+ charmap.encoding_id = TT_ADOBE_ID_LATIN_1;+ clazz = cmap_classes->unicode;+ break;++ default:+ ;+ }++ if ( clazz )+ error = FT_CMap_New( clazz, NULL, &charmap, NULL );++#if 0+ /* Select default charmap */+ if (root->num_charmaps)+ root->charmap = root->charmaps[0];+#endif+ }+ }++ Exit:+ return error;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* T1_Driver_Init */+ /* */+ /* <Description> */+ /* Initializes a given Type 1 driver object. */+ /* */+ /* <Input> */+ /* driver :: A handle to the target driver object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ T1_Driver_Init( T1_Driver driver )+ {+ FT_UNUSED( driver );++ return T1_Err_Ok;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* T1_Driver_Done */+ /* */+ /* <Description> */+ /* Finalizes a given Type 1 driver. */+ /* */+ /* <Input> */+ /* driver :: A handle to the target Type 1 driver. */+ /* */+ FT_LOCAL_DEF( void )+ T1_Driver_Done( T1_Driver driver )+ {+ FT_UNUSED( driver );+ }+++/* END */
+ src/type1/t1objs.h view
@@ -0,0 +1,171 @@+/***************************************************************************/+/* */+/* t1objs.h */+/* */+/* Type 1 objects manager (specification). */+/* */+/* Copyright 1996-2001, 2002, 2006 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 __T1OBJS_H__+#define __T1OBJS_H__+++#include <ft2build.h>+#include FT_INTERNAL_OBJECTS_H+#include FT_CONFIG_CONFIG_H+#include FT_INTERNAL_TYPE1_TYPES_H+++FT_BEGIN_HEADER+++ /* The following structures must be defined by the hinter */+ typedef struct T1_Size_Hints_ T1_Size_Hints;+ typedef struct T1_Glyph_Hints_ T1_Glyph_Hints;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* T1_Driver */+ /* */+ /* <Description> */+ /* A handle to a Type 1 driver object. */+ /* */+ typedef struct T1_DriverRec_ *T1_Driver;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* T1_Size */+ /* */+ /* <Description> */+ /* A handle to a Type 1 size object. */+ /* */+ typedef struct T1_SizeRec_* T1_Size;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* T1_GlyphSlot */+ /* */+ /* <Description> */+ /* A handle to a Type 1 glyph slot object. */+ /* */+ typedef struct T1_GlyphSlotRec_* T1_GlyphSlot;+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* T1_CharMap */+ /* */+ /* <Description> */+ /* A handle to a Type 1 character mapping object. */+ /* */+ /* <Note> */+ /* The Type 1 format doesn't use a charmap but an encoding table. */+ /* The driver is responsible for making up charmap objects */+ /* corresponding to these tables. */+ /* */+ typedef struct T1_CharMapRec_* T1_CharMap;+++ /*************************************************************************/+ /* */+ /* HERE BEGINS THE TYPE1 SPECIFIC STUFF */+ /* */+ /*************************************************************************/+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* T1_SizeRec */+ /* */+ /* <Description> */+ /* Type 1 size record. */+ /* */+ typedef struct T1_SizeRec_+ {+ FT_SizeRec root;++ } T1_SizeRec;+++ FT_LOCAL( void )+ T1_Size_Done( T1_Size size );++ FT_LOCAL( FT_Error )+ T1_Size_Request( T1_Size size,+ FT_Size_Request req );++ FT_LOCAL( FT_Error )+ T1_Size_Init( T1_Size size );+++ /*************************************************************************/+ /* */+ /* <Type> */+ /* T1_GlyphSlotRec */+ /* */+ /* <Description> */+ /* Type 1 glyph slot record. */+ /* */+ typedef struct T1_GlyphSlotRec_+ {+ FT_GlyphSlotRec root;++ FT_Bool hint;+ FT_Bool scaled;++ FT_Int max_points;+ FT_Int max_contours;++ FT_Fixed x_scale;+ FT_Fixed y_scale;++ } T1_GlyphSlotRec;+++ FT_LOCAL( FT_Error )+ T1_Face_Init( FT_Stream stream,+ T1_Face face,+ FT_Int face_index,+ FT_Int num_params,+ FT_Parameter* params );++ FT_LOCAL( void )+ T1_Face_Done( T1_Face face );++ FT_LOCAL( FT_Error )+ T1_GlyphSlot_Init( T1_GlyphSlot slot );++ FT_LOCAL( void )+ T1_GlyphSlot_Done( T1_GlyphSlot slot );++ FT_LOCAL( FT_Error )+ T1_Driver_Init( T1_Driver driver );++ FT_LOCAL( void )+ T1_Driver_Done( T1_Driver driver );+++FT_END_HEADER++#endif /* __T1OBJS_H__ */+++/* END */
+ src/type1/t1parse.c view
@@ -0,0 +1,486 @@+/***************************************************************************/+/* */+/* t1parse.c */+/* */+/* Type 1 parser (body). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2008, 2009 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* */+/* This file is part of the FreeType project, and may only be used, */+/* modified, and distributed under the terms of the FreeType project */+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */+/* this file you indicate that you have read the license and */+/* understand and accept it fully. */+/* */+/***************************************************************************/+++ /*************************************************************************/+ /* */+ /* The Type 1 parser is in charge of the following: */+ /* */+ /* - provide an implementation of a growing sequence of objects called */+ /* a `T1_Table' (used to build various tables needed by the loader). */+ /* */+ /* - opening .pfb and .pfa files to extract their top-level and private */+ /* dictionaries. */+ /* */+ /* - read numbers, arrays & strings from any dictionary. */+ /* */+ /* See `t1load.c' to see how data is loaded from the font file. */+ /* */+ /*************************************************************************/+++#include <ft2build.h>+#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_STREAM_H+#include FT_INTERNAL_POSTSCRIPT_AUX_H++#include "t1parse.h"++#include "t1errors.h"+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_t1parse+++ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+ /***** *****/+ /***** INPUT STREAM PARSER *****/+ /***** *****/+ /*************************************************************************/+ /*************************************************************************/+ /*************************************************************************/+++ /* see Adobe Technical Note 5040.Download_Fonts.pdf */++ static FT_Error+ read_pfb_tag( FT_Stream stream,+ FT_UShort *atag,+ FT_ULong *asize )+ {+ FT_Error error;+ FT_UShort tag;+ FT_ULong size;+++ *atag = 0;+ *asize = 0;++ if ( !FT_READ_USHORT( tag ) )+ {+ if ( tag == 0x8001U || tag == 0x8002U )+ {+ if ( !FT_READ_ULONG_LE( size ) )+ *asize = size;+ }++ *atag = tag;+ }++ return error;+ }+++ static FT_Error+ check_type1_format( FT_Stream stream,+ const char* header_string,+ size_t header_length )+ {+ FT_Error error;+ FT_UShort tag;+ FT_ULong dummy;+++ if ( FT_STREAM_SEEK( 0 ) )+ goto Exit;++ error = read_pfb_tag( stream, &tag, &dummy );+ if ( error )+ goto Exit;++ /* We assume that the first segment in a PFB is always encoded as */+ /* text. This might be wrong (and the specification doesn't insist */+ /* on that), but we have never seen a counterexample. */+ if ( tag != 0x8001U && FT_STREAM_SEEK( 0 ) )+ goto Exit;++ if ( !FT_FRAME_ENTER( header_length ) )+ {+ error = T1_Err_Ok;++ if ( ft_memcmp( stream->cursor, header_string, header_length ) != 0 )+ error = T1_Err_Unknown_File_Format;++ FT_FRAME_EXIT();+ }++ Exit:+ return error;+ }+++ FT_LOCAL_DEF( FT_Error )+ T1_New_Parser( T1_Parser parser,+ FT_Stream stream,+ FT_Memory memory,+ PSAux_Service psaux )+ {+ FT_Error error;+ FT_UShort tag;+ FT_ULong size;+++ psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );++ parser->stream = stream;+ parser->base_len = 0;+ parser->base_dict = 0;+ parser->private_len = 0;+ parser->private_dict = 0;+ parser->in_pfb = 0;+ parser->in_memory = 0;+ parser->single_block = 0;++ /* check the header format */+ error = check_type1_format( stream, "%!PS-AdobeFont", 14 );+ if ( error )+ {+ if ( error != T1_Err_Unknown_File_Format )+ goto Exit;++ error = check_type1_format( stream, "%!FontType", 10 );+ if ( error )+ {+ FT_TRACE2(( "[not a Type1 font]\n" ));+ goto Exit;+ }+ }++ /******************************************************************/+ /* */+ /* Here a short summary of what is going on: */+ /* */+ /* When creating a new Type 1 parser, we try to locate and load */+ /* the base dictionary if this is possible (i.e., for PFB */+ /* files). Otherwise, we load the whole font into memory. */+ /* */+ /* When `loading' the base dictionary, we only setup pointers */+ /* in the case of a memory-based stream. Otherwise, we */+ /* allocate and load the base dictionary in it. */+ /* */+ /* parser->in_pfb is set if we are in a binary (`.pfb') font. */+ /* parser->in_memory is set if we have a memory stream. */+ /* */++ /* try to compute the size of the base dictionary; */+ /* look for a Postscript binary file tag, i.e., 0x8001 */+ if ( FT_STREAM_SEEK( 0L ) )+ goto Exit;++ error = read_pfb_tag( stream, &tag, &size );+ if ( error )+ goto Exit;++ if ( tag != 0x8001U )+ {+ /* assume that this is a PFA file for now; an error will */+ /* be produced later when more things are checked */+ if ( FT_STREAM_SEEK( 0L ) )+ goto Exit;+ size = stream->size;+ }+ else+ parser->in_pfb = 1;++ /* now, try to load `size' bytes of the `base' dictionary we */+ /* found previously */++ /* if it is a memory-based resource, set up pointers */+ if ( !stream->read )+ {+ parser->base_dict = (FT_Byte*)stream->base + stream->pos;+ parser->base_len = size;+ parser->in_memory = 1;++ /* check that the `size' field is valid */+ if ( FT_STREAM_SKIP( size ) )+ goto Exit;+ }+ else+ {+ /* read segment in memory -- this is clumsy, but so does the format */+ if ( FT_ALLOC( parser->base_dict, size ) ||+ FT_STREAM_READ( parser->base_dict, size ) )+ goto Exit;+ parser->base_len = size;+ }++ parser->root.base = parser->base_dict;+ parser->root.cursor = parser->base_dict;+ parser->root.limit = parser->root.cursor + parser->base_len;++ Exit:+ if ( error && !parser->in_memory )+ FT_FREE( parser->base_dict );++ return error;+ }+++ FT_LOCAL_DEF( void )+ T1_Finalize_Parser( T1_Parser parser )+ {+ FT_Memory memory = parser->root.memory;+++ /* always free the private dictionary */+ FT_FREE( parser->private_dict );++ /* free the base dictionary only when we have a disk stream */+ if ( !parser->in_memory )+ FT_FREE( parser->base_dict );++ parser->root.funcs.done( &parser->root );+ }+++ FT_LOCAL_DEF( FT_Error )+ T1_Get_Private_Dict( T1_Parser parser,+ PSAux_Service psaux )+ {+ FT_Stream stream = parser->stream;+ FT_Memory memory = parser->root.memory;+ FT_Error error = T1_Err_Ok;+ FT_ULong size;+++ if ( parser->in_pfb )+ {+ /* in the case of the PFB format, the private dictionary can be */+ /* made of several segments. We thus first read the number of */+ /* segments to compute the total size of the private dictionary */+ /* then re-read them into memory. */+ FT_Long start_pos = FT_STREAM_POS();+ FT_UShort tag;+++ parser->private_len = 0;+ for (;;)+ {+ error = read_pfb_tag( stream, &tag, &size );+ if ( error )+ goto Fail;++ if ( tag != 0x8002U )+ break;++ parser->private_len += size;++ if ( FT_STREAM_SKIP( size ) )+ goto Fail;+ }++ /* Check that we have a private dictionary there */+ /* and allocate private dictionary buffer */+ if ( parser->private_len == 0 )+ {+ FT_ERROR(( "T1_Get_Private_Dict:"+ " invalid private dictionary section\n" ));+ error = T1_Err_Invalid_File_Format;+ goto Fail;+ }++ if ( FT_STREAM_SEEK( start_pos ) ||+ FT_ALLOC( parser->private_dict, parser->private_len ) )+ goto Fail;++ parser->private_len = 0;+ for (;;)+ {+ error = read_pfb_tag( stream, &tag, &size );+ if ( error || tag != 0x8002U )+ {+ error = T1_Err_Ok;+ break;+ }++ if ( FT_STREAM_READ( parser->private_dict + parser->private_len,+ size ) )+ goto Fail;++ parser->private_len += size;+ }+ }+ else+ {+ /* We have already `loaded' the whole PFA font file into memory; */+ /* if this is a memory resource, allocate a new block to hold */+ /* the private dict. Otherwise, simply overwrite into the base */+ /* dictionary block in the heap. */++ /* first of all, look at the `eexec' keyword */+ FT_Byte* cur = parser->base_dict;+ FT_Byte* limit = cur + parser->base_len;+ FT_Byte c;+++ Again:+ for (;;)+ {+ c = cur[0];+ if ( c == 'e' && cur + 9 < limit ) /* 9 = 5 letters for `eexec' + */+ /* newline + 4 chars */+ {+ if ( cur[1] == 'e' &&+ cur[2] == 'x' &&+ cur[3] == 'e' &&+ cur[4] == 'c' )+ break;+ }+ cur++;+ if ( cur >= limit )+ {+ FT_ERROR(( "T1_Get_Private_Dict:"+ " could not find `eexec' keyword\n" ));+ error = T1_Err_Invalid_File_Format;+ goto Exit;+ }+ }++ /* check whether `eexec' was real -- it could be in a comment */+ /* or string (as e.g. in u003043t.gsf from ghostscript) */++ parser->root.cursor = parser->base_dict;+ parser->root.limit = cur + 9;++ cur = parser->root.cursor;+ limit = parser->root.limit;++ while ( cur < limit )+ {+ if ( *cur == 'e' && ft_strncmp( (char*)cur, "eexec", 5 ) == 0 )+ goto Found;++ T1_Skip_PS_Token( parser );+ if ( parser->root.error )+ break;+ T1_Skip_Spaces ( parser );+ cur = parser->root.cursor;+ }++ /* we haven't found the correct `eexec'; go back and continue */+ /* searching */++ cur = limit;+ limit = parser->base_dict + parser->base_len;+ goto Again;++ /* now determine where to write the _encrypted_ binary private */+ /* dictionary. We overwrite the base dictionary for disk-based */+ /* resources and allocate a new block otherwise */++ Found:+ parser->root.limit = parser->base_dict + parser->base_len;++ T1_Skip_PS_Token( parser );+ cur = parser->root.cursor;++ /* according to the Type1 spec, the first cipher byte must not be */+ /* an ASCII whitespace character code (blank, tab, carriage return */+ /* or line feed). We have seen Type 1 fonts with two line feed */+ /* characters... So skip now all whitespace character codes. */+ while ( cur < limit &&+ ( *cur == ' ' ||+ *cur == '\t' || + *cur == '\r' ||+ *cur == '\n' ) )+ ++cur;+ if ( cur >= limit )+ {+ FT_ERROR(( "T1_Get_Private_Dict:"+ " `eexec' not properly terminated\n" ));+ error = T1_Err_Invalid_File_Format;+ goto Exit;+ }++ size = parser->base_len - ( cur - parser->base_dict );++ if ( parser->in_memory )+ {+ /* note that we allocate one more byte to put a terminating `0' */+ if ( FT_ALLOC( parser->private_dict, size + 1 ) )+ goto Fail;+ parser->private_len = size;+ }+ else+ {+ parser->single_block = 1;+ parser->private_dict = parser->base_dict;+ parser->private_len = size;+ parser->base_dict = 0;+ parser->base_len = 0;+ }++ /* now determine whether the private dictionary is encoded in binary */+ /* or hexadecimal ASCII format -- decode it accordingly */++ /* we need to access the next 4 bytes (after the final \r following */+ /* the `eexec' keyword); if they all are hexadecimal digits, then */+ /* we have a case of ASCII storage */++ if ( ft_isxdigit( cur[0] ) && ft_isxdigit( cur[1] ) &&+ ft_isxdigit( cur[2] ) && ft_isxdigit( cur[3] ) )+ {+ /* ASCII hexadecimal encoding */+ FT_Long len;+++ parser->root.cursor = cur;+ (void)psaux->ps_parser_funcs->to_bytes( &parser->root,+ parser->private_dict,+ parser->private_len,+ &len,+ 0 );+ parser->private_len = len;++ /* put a safeguard */+ parser->private_dict[len] = '\0';+ }+ else+ /* binary encoding -- copy the private dict */+ FT_MEM_MOVE( parser->private_dict, cur, size );+ }++ /* we now decrypt the encoded binary private dictionary */+ psaux->t1_decrypt( parser->private_dict, parser->private_len, 55665U );++ /* replace the four random bytes at the beginning with whitespace */+ parser->private_dict[0] = ' ';+ parser->private_dict[1] = ' ';+ parser->private_dict[2] = ' ';+ parser->private_dict[3] = ' ';++ parser->root.base = parser->private_dict;+ parser->root.cursor = parser->private_dict;+ parser->root.limit = parser->root.cursor + parser->private_len;++ Fail:+ Exit:+ return error;+ }+++/* END */
+ src/type1/t1parse.h view
@@ -0,0 +1,135 @@+/***************************************************************************/+/* */+/* t1parse.h */+/* */+/* Type 1 parser (specification). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2008 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 __T1PARSE_H__+#define __T1PARSE_H__+++#include <ft2build.h>+#include FT_INTERNAL_TYPE1_TYPES_H+#include FT_INTERNAL_STREAM_H+++FT_BEGIN_HEADER+++ /*************************************************************************/+ /* */+ /* <Struct> */+ /* T1_ParserRec */+ /* */+ /* <Description> */+ /* A PS_ParserRec is an object used to parse a Type 1 fonts very */+ /* quickly. */+ /* */+ /* <Fields> */+ /* root :: The root parser. */+ /* */+ /* stream :: The current input stream. */+ /* */+ /* base_dict :: A pointer to the top-level dictionary. */+ /* */+ /* base_len :: The length in bytes of the top dictionary. */+ /* */+ /* private_dict :: A pointer to the private dictionary. */+ /* */+ /* private_len :: The length in bytes of the private dictionary. */+ /* */+ /* in_pfb :: A boolean. Indicates that we are handling a PFB */+ /* file. */+ /* */+ /* in_memory :: A boolean. Indicates a memory-based stream. */+ /* */+ /* single_block :: A boolean. Indicates that the private dictionary */+ /* is stored in lieu of the base dictionary. */+ /* */+ typedef struct T1_ParserRec_+ {+ PS_ParserRec root;+ FT_Stream stream;++ FT_Byte* base_dict;+ FT_ULong base_len;++ FT_Byte* private_dict;+ FT_ULong private_len;++ FT_Bool in_pfb;+ FT_Bool in_memory;+ FT_Bool single_block;++ } T1_ParserRec, *T1_Parser;+++#define T1_Add_Table( p, i, o, l ) (p)->funcs.add( (p), i, o, l )+#define T1_Done_Table( p ) \+ do \+ { \+ if ( (p)->funcs.done ) \+ (p)->funcs.done( p ); \+ } while ( 0 )+#define T1_Release_Table( p ) \+ do \+ { \+ if ( (p)->funcs.release ) \+ (p)->funcs.release( p ); \+ } while ( 0 )+++#define T1_Skip_Spaces( p ) (p)->root.funcs.skip_spaces( &(p)->root )+#define T1_Skip_PS_Token( p ) (p)->root.funcs.skip_PS_token( &(p)->root )++#define T1_ToInt( p ) (p)->root.funcs.to_int( &(p)->root )+#define T1_ToFixed( p, t ) (p)->root.funcs.to_fixed( &(p)->root, t )++#define T1_ToCoordArray( p, m, c ) \+ (p)->root.funcs.to_coord_array( &(p)->root, m, c )+#define T1_ToFixedArray( p, m, f, t ) \+ (p)->root.funcs.to_fixed_array( &(p)->root, m, f, t )+#define T1_ToToken( p, t ) \+ (p)->root.funcs.to_token( &(p)->root, t )+#define T1_ToTokenArray( p, t, m, c ) \+ (p)->root.funcs.to_token_array( &(p)->root, t, m, c )++#define T1_Load_Field( p, f, o, m, pf ) \+ (p)->root.funcs.load_field( &(p)->root, f, o, m, pf )++#define T1_Load_Field_Table( p, f, o, m, pf ) \+ (p)->root.funcs.load_field_table( &(p)->root, f, o, m, pf )+++ FT_LOCAL( FT_Error )+ T1_New_Parser( T1_Parser parser,+ FT_Stream stream,+ FT_Memory memory,+ PSAux_Service psaux );++ FT_LOCAL( FT_Error )+ T1_Get_Private_Dict( T1_Parser parser,+ PSAux_Service psaux );++ FT_LOCAL( void )+ T1_Finalize_Parser( T1_Parser parser );+++FT_END_HEADER++#endif /* __T1PARSE_H__ */+++/* END */
+ src/type1/t1tokens.h view
@@ -0,0 +1,143 @@+/***************************************************************************/+/* */+/* t1tokens.h */+/* */+/* Type 1 tokenizer (specification). */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2008, 2009 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. */+/* */+/***************************************************************************/+++#undef FT_STRUCTURE+#define FT_STRUCTURE PS_FontInfoRec+#undef T1CODE+#define T1CODE T1_FIELD_LOCATION_FONT_INFO++ T1_FIELD_STRING( "version", version,+ T1_FIELD_DICT_FONTDICT )+ T1_FIELD_STRING( "Notice", notice,+ T1_FIELD_DICT_FONTDICT )+ T1_FIELD_STRING( "FullName", full_name,+ T1_FIELD_DICT_FONTDICT )+ T1_FIELD_STRING( "FamilyName", family_name,+ T1_FIELD_DICT_FONTDICT )+ T1_FIELD_STRING( "Weight", weight,+ T1_FIELD_DICT_FONTDICT )++ /* we use pointers to detect modifications made by synthetic fonts */+ T1_FIELD_NUM ( "ItalicAngle", italic_angle,+ T1_FIELD_DICT_FONTDICT )+ T1_FIELD_BOOL ( "isFixedPitch", is_fixed_pitch,+ T1_FIELD_DICT_FONTDICT )+ T1_FIELD_NUM ( "UnderlinePosition", underline_position,+ T1_FIELD_DICT_FONTDICT )+ T1_FIELD_NUM ( "UnderlineThickness", underline_thickness,+ T1_FIELD_DICT_FONTDICT )++#undef FT_STRUCTURE+#define FT_STRUCTURE PS_FontExtraRec+#undef T1CODE+#define T1CODE T1_FIELD_LOCATION_FONT_EXTRA++ T1_FIELD_NUM ( "FSType", fs_type,+ T1_FIELD_DICT_FONTDICT )++#undef FT_STRUCTURE+#define FT_STRUCTURE PS_PrivateRec+#undef T1CODE+#define T1CODE T1_FIELD_LOCATION_PRIVATE++ T1_FIELD_NUM ( "UniqueID", unique_id,+ T1_FIELD_DICT_FONTDICT | T1_FIELD_DICT_PRIVATE )+ T1_FIELD_NUM ( "lenIV", lenIV,+ T1_FIELD_DICT_PRIVATE )+ T1_FIELD_NUM ( "LanguageGroup", language_group,+ T1_FIELD_DICT_PRIVATE )+ T1_FIELD_NUM ( "password", password,+ T1_FIELD_DICT_PRIVATE )++ T1_FIELD_FIXED_1000( "BlueScale", blue_scale,+ T1_FIELD_DICT_PRIVATE )+ T1_FIELD_NUM ( "BlueShift", blue_shift,+ T1_FIELD_DICT_PRIVATE )+ T1_FIELD_NUM ( "BlueFuzz", blue_fuzz,+ T1_FIELD_DICT_PRIVATE )++ T1_FIELD_NUM_TABLE ( "BlueValues", blue_values, 14,+ T1_FIELD_DICT_PRIVATE )+ T1_FIELD_NUM_TABLE ( "OtherBlues", other_blues, 10,+ T1_FIELD_DICT_PRIVATE )+ T1_FIELD_NUM_TABLE ( "FamilyBlues", family_blues, 14,+ T1_FIELD_DICT_PRIVATE )+ T1_FIELD_NUM_TABLE ( "FamilyOtherBlues", family_other_blues, 10,+ T1_FIELD_DICT_PRIVATE )++ T1_FIELD_NUM_TABLE2( "StdHW", standard_width, 1,+ T1_FIELD_DICT_PRIVATE )+ T1_FIELD_NUM_TABLE2( "StdVW", standard_height, 1,+ T1_FIELD_DICT_PRIVATE )+ T1_FIELD_NUM_TABLE2( "MinFeature", min_feature, 2,+ T1_FIELD_DICT_PRIVATE )++ T1_FIELD_NUM_TABLE ( "StemSnapH", snap_widths, 12,+ T1_FIELD_DICT_PRIVATE )+ T1_FIELD_NUM_TABLE ( "StemSnapV", snap_heights, 12,+ T1_FIELD_DICT_PRIVATE )++ T1_FIELD_FIXED ( "ExpansionFactor", expansion_factor,+ T1_FIELD_DICT_PRIVATE )+ T1_FIELD_BOOL ( "ForceBold", force_bold,+ T1_FIELD_DICT_PRIVATE )+ ++#undef FT_STRUCTURE+#define FT_STRUCTURE T1_FontRec+#undef T1CODE+#define T1CODE T1_FIELD_LOCATION_FONT_DICT++ T1_FIELD_KEY ( "FontName", font_name, T1_FIELD_DICT_FONTDICT )+ T1_FIELD_NUM ( "PaintType", paint_type, T1_FIELD_DICT_FONTDICT )+ T1_FIELD_NUM ( "FontType", font_type, T1_FIELD_DICT_FONTDICT )+ T1_FIELD_FIXED( "StrokeWidth", stroke_width, T1_FIELD_DICT_FONTDICT )+++#undef FT_STRUCTURE+#define FT_STRUCTURE FT_BBox+#undef T1CODE+#define T1CODE T1_FIELD_LOCATION_BBOX++ T1_FIELD_BBOX( "FontBBox", xMin, T1_FIELD_DICT_FONTDICT )+++#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT++#undef FT_STRUCTURE+#define FT_STRUCTURE T1_FaceRec+#undef T1CODE+#define T1CODE T1_FIELD_LOCATION_FACE++ T1_FIELD_NUM( "NDV", ndv_idx, T1_FIELD_DICT_PRIVATE )+ T1_FIELD_NUM( "CDV", cdv_idx, T1_FIELD_DICT_PRIVATE )+++#undef FT_STRUCTURE+#define FT_STRUCTURE PS_BlendRec+#undef T1CODE+#define T1CODE T1_FIELD_LOCATION_BLEND++ T1_FIELD_NUM_TABLE( "DesignVector", default_design_vector,+ T1_MAX_MM_DESIGNS, T1_FIELD_DICT_FONTDICT )+++#endif /* T1_CONFIG_OPTION_NO_MM_SUPPORT */+++/* END */
+ src/type1/type1.c view
@@ -0,0 +1,33 @@+/***************************************************************************/+/* */+/* type1.c */+/* */+/* FreeType Type 1 driver component (body only). */+/* */+/* Copyright 1996-2001 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 "t1parse.c"+#include "t1load.c"+#include "t1objs.c"+#include "t1driver.c"+#include "t1gload.c"++#ifndef T1_CONFIG_OPTION_NO_AFM+#include "t1afm.c"+#endif+++/* END */
+ src/type42/t42drivr.c view
@@ -0,0 +1,246 @@+/***************************************************************************/+/* */+/* t42drivr.c */+/* */+/* High-level Type 42 driver interface (body). */+/* */+/* Copyright 2002, 2003, 2004, 2006, 2007, 2009 by Roberto Alameda. */+/* */+/* 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 driver implements Type42 fonts as described in the */+ /* Technical Note #5012 from Adobe, with these limitations: */+ /* */+ /* 1) CID Fonts are not currently supported. */+ /* 2) Incremental fonts making use of the GlyphDirectory keyword */+ /* will be loaded, but the rendering will be using the TrueType */+ /* tables. */+ /* 3) As for Type1 fonts, CDevProc is not supported. */+ /* 4) The Metrics dictionary is not supported. */+ /* 5) AFM metrics are not supported. */+ /* */+ /* In other words, this driver supports Type42 fonts derived from */+ /* TrueType fonts in a non-CID manner, as done by usual conversion */+ /* programs. */+ /* */+ /*************************************************************************/+++#include "t42drivr.h"+#include "t42objs.h"+#include "t42error.h"+#include FT_INTERNAL_DEBUG_H++#include FT_SERVICE_XFREE86_NAME_H+#include FT_SERVICE_GLYPH_DICT_H+#include FT_SERVICE_POSTSCRIPT_NAME_H+#include FT_SERVICE_POSTSCRIPT_INFO_H++#undef FT_COMPONENT+#define FT_COMPONENT trace_t42+++ /*+ *+ * GLYPH DICT SERVICE+ *+ */++ static FT_Error+ t42_get_glyph_name( T42_Face face,+ FT_UInt glyph_index,+ FT_Pointer buffer,+ FT_UInt buffer_max )+ {+ FT_STRCPYN( buffer, face->type1.glyph_names[glyph_index], buffer_max );++ return T42_Err_Ok;+ }+++ static FT_UInt+ t42_get_name_index( T42_Face face,+ FT_String* glyph_name )+ {+ FT_Int i;+ FT_String* gname;+++ for ( i = 0; i < face->type1.num_glyphs; i++ )+ {+ gname = face->type1.glyph_names[i];++ if ( glyph_name[0] == gname[0] && !ft_strcmp( glyph_name, gname ) )+ return (FT_UInt)ft_atol( (const char *)face->type1.charstrings[i] );+ }++ return 0;+ }+++ static const FT_Service_GlyphDictRec t42_service_glyph_dict =+ {+ (FT_GlyphDict_GetNameFunc) t42_get_glyph_name,+ (FT_GlyphDict_NameIndexFunc)t42_get_name_index+ };+++ /*+ *+ * POSTSCRIPT NAME SERVICE+ *+ */++ static const char*+ t42_get_ps_font_name( T42_Face face )+ {+ return (const char*)face->type1.font_name;+ }+++ static const FT_Service_PsFontNameRec t42_service_ps_font_name =+ {+ (FT_PsName_GetFunc)t42_get_ps_font_name+ };+++ /*+ *+ * POSTSCRIPT INFO SERVICE+ *+ */++ static FT_Error+ t42_ps_get_font_info( FT_Face face,+ PS_FontInfoRec* afont_info )+ {+ *afont_info = ((T42_Face)face)->type1.font_info;++ return T42_Err_Ok;+ }+++ static FT_Error+ t42_ps_get_font_extra( FT_Face face,+ PS_FontExtraRec* afont_extra )+ {+ *afont_extra = ((T42_Face)face)->type1.font_extra;++ return T42_Err_Ok;+ }+++ static FT_Int+ t42_ps_has_glyph_names( FT_Face face )+ {+ FT_UNUSED( face );++ return 1;+ }+++ static FT_Error+ t42_ps_get_font_private( FT_Face face,+ PS_PrivateRec* afont_private )+ {+ *afont_private = ((T42_Face)face)->type1.private_dict;++ return T42_Err_Ok;+ }+++ static const FT_Service_PsInfoRec t42_service_ps_info =+ {+ (PS_GetFontInfoFunc) t42_ps_get_font_info,+ (PS_GetFontExtraFunc) t42_ps_get_font_extra,+ (PS_HasGlyphNamesFunc) t42_ps_has_glyph_names,+ (PS_GetFontPrivateFunc)t42_ps_get_font_private+ };+++ /*+ *+ * SERVICE LIST+ *+ */++ static const FT_ServiceDescRec t42_services[] =+ {+ { FT_SERVICE_ID_GLYPH_DICT, &t42_service_glyph_dict },+ { FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &t42_service_ps_font_name },+ { FT_SERVICE_ID_POSTSCRIPT_INFO, &t42_service_ps_info },+ { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_TYPE_42 },+ { NULL, NULL }+ };+++ static FT_Module_Interface+ T42_Get_Interface( FT_Driver driver,+ const FT_String* t42_interface )+ {+ FT_UNUSED( driver );++ return ft_service_list_lookup( t42_services, t42_interface );+ }+++ const FT_Driver_ClassRec t42_driver_class =+ {+ {+ FT_MODULE_FONT_DRIVER |+ FT_MODULE_DRIVER_SCALABLE |+#ifdef TT_USE_BYTECODE_INTERPRETER+ FT_MODULE_DRIVER_HAS_HINTER,+#else+ 0,+#endif++ sizeof ( T42_DriverRec ),++ "type42",+ 0x10000L,+ 0x20000L,++ 0, /* format interface */++ (FT_Module_Constructor)T42_Driver_Init,+ (FT_Module_Destructor) T42_Driver_Done,+ (FT_Module_Requester) T42_Get_Interface,+ },++ sizeof ( T42_FaceRec ),+ sizeof ( T42_SizeRec ),+ sizeof ( T42_GlyphSlotRec ),++ (FT_Face_InitFunc) T42_Face_Init,+ (FT_Face_DoneFunc) T42_Face_Done,+ (FT_Size_InitFunc) T42_Size_Init,+ (FT_Size_DoneFunc) T42_Size_Done,+ (FT_Slot_InitFunc) T42_GlyphSlot_Init,+ (FT_Slot_DoneFunc) T42_GlyphSlot_Done,++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS+ ft_stub_set_char_sizes,+ ft_stub_set_pixel_sizes,+#endif+ (FT_Slot_LoadFunc) T42_GlyphSlot_Load,++ (FT_Face_GetKerningFunc) 0,+ (FT_Face_AttachFunc) 0,++ (FT_Face_GetAdvancesFunc) 0,+ (FT_Size_RequestFunc) T42_Size_Request,+ (FT_Size_SelectFunc) T42_Size_Select+ };+++/* END */
+ src/type42/t42drivr.h view
@@ -0,0 +1,42 @@+/***************************************************************************/+/* */+/* t42drivr.h */+/* */+/* High-level Type 42 driver interface (specification). */+/* */+/* Copyright 2002 by Roberto Alameda. */+/* */+/* 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 __T42DRIVR_H__+#define __T42DRIVR_H__+++#include <ft2build.h>+#include FT_INTERNAL_DRIVER_H+++FT_BEGIN_HEADER++#ifdef FT_CONFIG_OPTION_PIC+#error "this module does not support PIC yet"+#endif +++ FT_EXPORT_VAR( const FT_Driver_ClassRec ) t42_driver_class;+++FT_END_HEADER+++#endif /* __T42DRIVR_H__ */+++/* END */
+ src/type42/t42error.h view
@@ -0,0 +1,40 @@+/***************************************************************************/+/* */+/* t42error.h */+/* */+/* Type 42 error codes (specification only). */+/* */+/* Copyright 2002, 2003 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 Type 42 error enumeration constants. */+ /* */+ /*************************************************************************/++#ifndef __T42ERROR_H__+#define __T42ERROR_H__++#include FT_MODULE_ERRORS_H++#undef __FTERRORS_H__++#define FT_ERR_PREFIX T42_Err_+#define FT_ERR_BASE FT_Mod_Err_Type42++#include FT_ERRORS_H++#endif /* __T42ERROR_H__ */+++/* END */
+ src/type42/t42objs.c view
@@ -0,0 +1,652 @@+/***************************************************************************/+/* */+/* t42objs.c */+/* */+/* Type 42 objects manager (body). */+/* */+/* Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 */+/* by Roberto Alameda. */+/* */+/* 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 "t42objs.h"+#include "t42parse.h"+#include "t42error.h"+#include FT_INTERNAL_DEBUG_H+#include FT_LIST_H+#include FT_TRUETYPE_IDS_H +++#undef FT_COMPONENT+#define FT_COMPONENT trace_t42+++ static FT_Error+ T42_Open_Face( T42_Face face )+ {+ T42_LoaderRec loader;+ T42_Parser parser;+ T1_Font type1 = &face->type1;+ FT_Memory memory = face->root.memory;+ FT_Error error;++ PSAux_Service psaux = (PSAux_Service)face->psaux;+++ t42_loader_init( &loader, face );++ parser = &loader.parser;++ if ( FT_ALLOC( face->ttf_data, 12 ) )+ goto Exit;++ error = t42_parser_init( parser,+ face->root.stream,+ memory,+ psaux);+ if ( error )+ goto Exit;++ error = t42_parse_dict( face, &loader,+ parser->base_dict, parser->base_len );+ if ( error )+ goto Exit;++ if ( type1->font_type != 42 )+ {+ error = T42_Err_Unknown_File_Format;+ goto Exit;+ }++ /* now, propagate the charstrings and glyphnames tables */+ /* to the Type1 data */+ type1->num_glyphs = loader.num_glyphs;++ if ( !loader.charstrings.init )+ {+ FT_ERROR(( "T42_Open_Face: no charstrings array in face\n" ));+ error = T42_Err_Invalid_File_Format;+ }++ loader.charstrings.init = 0;+ type1->charstrings_block = loader.charstrings.block;+ type1->charstrings = loader.charstrings.elements;+ type1->charstrings_len = loader.charstrings.lengths;++ /* we copy the glyph names `block' and `elements' fields; */+ /* the `lengths' field must be released later */+ type1->glyph_names_block = loader.glyph_names.block;+ type1->glyph_names = (FT_String**)loader.glyph_names.elements;+ loader.glyph_names.block = 0;+ loader.glyph_names.elements = 0;++ /* we must now build type1.encoding when we have a custom array */+ if ( type1->encoding_type == T1_ENCODING_TYPE_ARRAY )+ {+ FT_Int charcode, idx, min_char, max_char;+ FT_Byte* char_name;+ FT_Byte* glyph_name;+++ /* OK, we do the following: for each element in the encoding */+ /* table, look up the index of the glyph having the same name */+ /* as defined in the CharStrings array. */+ /* The index is then stored in type1.encoding.char_index, and */+ /* the name in type1.encoding.char_name */++ min_char = 0;+ max_char = 0;++ charcode = 0;+ for ( ; charcode < loader.encoding_table.max_elems; charcode++ )+ {+ type1->encoding.char_index[charcode] = 0;+ type1->encoding.char_name [charcode] = (char *)".notdef";++ char_name = loader.encoding_table.elements[charcode];+ if ( char_name )+ for ( idx = 0; idx < type1->num_glyphs; idx++ )+ {+ glyph_name = (FT_Byte*)type1->glyph_names[idx];+ if ( ft_strcmp( (const char*)char_name,+ (const char*)glyph_name ) == 0 )+ {+ type1->encoding.char_index[charcode] = (FT_UShort)idx;+ type1->encoding.char_name [charcode] = (char*)glyph_name;++ /* Change min/max encoded char only if glyph name is */+ /* not /.notdef */+ if ( ft_strcmp( (const char*)".notdef",+ (const char*)glyph_name ) != 0 )+ {+ if ( charcode < min_char )+ min_char = charcode;+ if ( charcode >= max_char )+ max_char = charcode + 1;+ }+ break;+ }+ }+ }++ type1->encoding.code_first = min_char;+ type1->encoding.code_last = max_char;+ type1->encoding.num_chars = loader.num_chars;+ }++ Exit:+ t42_loader_done( &loader );+ return error;+ }+++ /***************** Driver Functions *************/+++ FT_LOCAL_DEF( FT_Error )+ T42_Face_Init( FT_Stream stream,+ T42_Face face,+ FT_Int face_index,+ FT_Int num_params,+ FT_Parameter* params )+ {+ FT_Error error;+ FT_Service_PsCMaps psnames;+ PSAux_Service psaux;+ FT_Face root = (FT_Face)&face->root;+ T1_Font type1 = &face->type1;+ PS_FontInfo info = &type1->font_info;++ FT_UNUSED( num_params );+ FT_UNUSED( params );+ FT_UNUSED( face_index );+ FT_UNUSED( stream );+++ face->ttf_face = NULL;+ face->root.num_faces = 1;++ FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );+ face->psnames = psnames;++ face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),+ "psaux" );+ psaux = (PSAux_Service)face->psaux;++ /* open the tokenizer, this will also check the font format */+ error = T42_Open_Face( face );+ if ( error )+ goto Exit;++ /* if we just wanted to check the format, leave successfully now */+ if ( face_index < 0 )+ goto Exit;++ /* check the face index */+ if ( face_index > 0 )+ {+ FT_ERROR(( "T42_Face_Init: invalid face index\n" ));+ error = T42_Err_Invalid_Argument;+ goto Exit;+ }++ /* Now load the font program into the face object */++ /* Init the face object fields */+ /* Now set up root face fields */++ root->num_glyphs = type1->num_glyphs;+ root->num_charmaps = 0;+ root->face_index = 0;++ root->face_flags = FT_FACE_FLAG_SCALABLE |+ FT_FACE_FLAG_HORIZONTAL |+ FT_FACE_FLAG_GLYPH_NAMES;++ if ( info->is_fixed_pitch )+ root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;++ /* We only set this flag if we have the patented bytecode interpreter. */+ /* There are no known `tricky' Type42 fonts that could be loaded with */+ /* the unpatented interpreter. */+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER+ root->face_flags |= FT_FACE_FLAG_HINTER;+#endif++ /* XXX: TODO -- add kerning with .afm support */++ /* get style name -- be careful, some broken fonts only */+ /* have a `/FontName' dictionary entry! */+ root->family_name = info->family_name;+ /* assume "Regular" style if we don't know better */+ root->style_name = (char *)"Regular";+ if ( root->family_name )+ {+ char* full = info->full_name;+ char* family = root->family_name;+++ if ( full )+ {+ while ( *full )+ {+ if ( *full == *family )+ {+ family++;+ full++;+ }+ else+ {+ if ( *full == ' ' || *full == '-' )+ full++;+ else if ( *family == ' ' || *family == '-' )+ family++;+ else+ {+ if ( !*family )+ root->style_name = full;+ break;+ }+ }+ }+ }+ }+ else+ {+ /* do we have a `/FontName'? */+ if ( type1->font_name )+ root->family_name = type1->font_name;+ }++ /* no embedded bitmap support */+ root->num_fixed_sizes = 0;+ root->available_sizes = 0;++ /* Load the TTF font embedded in the T42 font */+ {+ FT_Open_Args args;+++ args.flags = FT_OPEN_MEMORY;+ args.memory_base = face->ttf_data;+ args.memory_size = face->ttf_size;++ if ( num_params )+ {+ args.flags |= FT_OPEN_PARAMS;+ args.num_params = num_params;+ args.params = params;+ }++ error = FT_Open_Face( FT_FACE_LIBRARY( face ),+ &args, 0, &face->ttf_face );+ }++ if ( error )+ goto Exit;++ FT_Done_Size( face->ttf_face->size );++ /* Ignore info in FontInfo dictionary and use the info from the */+ /* loaded TTF font. The PostScript interpreter also ignores it. */+ root->bbox = face->ttf_face->bbox;+ root->units_per_EM = face->ttf_face->units_per_EM;++ root->ascender = face->ttf_face->ascender;+ root->descender = face->ttf_face->descender;+ root->height = face->ttf_face->height;++ root->max_advance_width = face->ttf_face->max_advance_width;+ root->max_advance_height = face->ttf_face->max_advance_height;++ root->underline_position = (FT_Short)info->underline_position;+ root->underline_thickness = (FT_Short)info->underline_thickness;++ /* compute style flags */+ root->style_flags = 0;+ if ( info->italic_angle )+ root->style_flags |= FT_STYLE_FLAG_ITALIC;++ if ( face->ttf_face->style_flags & FT_STYLE_FLAG_BOLD )+ root->style_flags |= FT_STYLE_FLAG_BOLD;++ if ( face->ttf_face->face_flags & FT_FACE_FLAG_VERTICAL )+ root->face_flags |= FT_FACE_FLAG_VERTICAL;++ {+ if ( psnames && psaux )+ {+ FT_CharMapRec charmap;+ T1_CMap_Classes cmap_classes = psaux->t1_cmap_classes;+ FT_CMap_Class clazz;+++ charmap.face = root;++ /* first of all, try to synthesize a Unicode charmap */+ charmap.platform_id = TT_PLATFORM_MICROSOFT;+ charmap.encoding_id = TT_MS_ID_UNICODE_CS;+ charmap.encoding = FT_ENCODING_UNICODE;++ error = FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL );+ if ( error && FT_Err_No_Unicode_Glyph_Name != error )+ goto Exit;+ error = FT_Err_Ok;++ /* now, generate an Adobe Standard encoding when appropriate */+ charmap.platform_id = TT_PLATFORM_ADOBE;+ clazz = NULL;++ switch ( type1->encoding_type )+ {+ case T1_ENCODING_TYPE_STANDARD:+ charmap.encoding = FT_ENCODING_ADOBE_STANDARD;+ charmap.encoding_id = TT_ADOBE_ID_STANDARD;+ clazz = cmap_classes->standard;+ break;++ case T1_ENCODING_TYPE_EXPERT:+ charmap.encoding = FT_ENCODING_ADOBE_EXPERT;+ charmap.encoding_id = TT_ADOBE_ID_EXPERT;+ clazz = cmap_classes->expert;+ break;++ case T1_ENCODING_TYPE_ARRAY:+ charmap.encoding = FT_ENCODING_ADOBE_CUSTOM;+ charmap.encoding_id = TT_ADOBE_ID_CUSTOM;+ clazz = cmap_classes->custom;+ break;++ case T1_ENCODING_TYPE_ISOLATIN1:+ charmap.encoding = FT_ENCODING_ADOBE_LATIN_1;+ charmap.encoding_id = TT_ADOBE_ID_LATIN_1;+ clazz = cmap_classes->unicode;+ break;++ default:+ ;+ }++ if ( clazz )+ error = FT_CMap_New( clazz, NULL, &charmap, NULL );++#if 0+ /* Select default charmap */+ if ( root->num_charmaps )+ root->charmap = root->charmaps[0];+#endif+ }+ }+ Exit:+ return error;+ }+++ FT_LOCAL_DEF( void )+ T42_Face_Done( T42_Face face )+ {+ T1_Font type1;+ PS_FontInfo info;+ FT_Memory memory;+++ if ( !face )+ return;++ type1 = &face->type1;+ info = &type1->font_info;+ memory = face->root.memory;++ /* delete internal ttf face prior to freeing face->ttf_data */+ if ( face->ttf_face )+ FT_Done_Face( face->ttf_face );++ /* release font info strings */+ FT_FREE( info->version );+ FT_FREE( info->notice );+ FT_FREE( info->full_name );+ FT_FREE( info->family_name );+ FT_FREE( info->weight );++ /* release top dictionary */+ FT_FREE( type1->charstrings_len );+ FT_FREE( type1->charstrings );+ FT_FREE( type1->glyph_names );++ FT_FREE( type1->charstrings_block );+ FT_FREE( type1->glyph_names_block );++ FT_FREE( type1->encoding.char_index );+ FT_FREE( type1->encoding.char_name );+ FT_FREE( type1->font_name );++ FT_FREE( face->ttf_data );++#if 0+ /* release afm data if present */+ if ( face->afm_data )+ T1_Done_AFM( memory, (T1_AFM*)face->afm_data );+#endif++ /* release unicode map, if any */+ FT_FREE( face->unicode_map.maps );+ face->unicode_map.num_maps = 0;++ face->root.family_name = 0;+ face->root.style_name = 0;+ }+++ /*************************************************************************/+ /* */+ /* <Function> */+ /* T42_Driver_Init */+ /* */+ /* <Description> */+ /* Initializes a given Type 42 driver object. */+ /* */+ /* <Input> */+ /* driver :: A handle to the target driver object. */+ /* */+ /* <Return> */+ /* FreeType error code. 0 means success. */+ /* */+ FT_LOCAL_DEF( FT_Error )+ T42_Driver_Init( T42_Driver driver )+ {+ FT_Module ttmodule;+++ ttmodule = FT_Get_Module( FT_MODULE(driver)->library, "truetype" );+ driver->ttclazz = (FT_Driver_Class)ttmodule->clazz;++ return T42_Err_Ok;+ }+++ FT_LOCAL_DEF( void )+ T42_Driver_Done( T42_Driver driver )+ {+ FT_UNUSED( driver );+ }+++ FT_LOCAL_DEF( FT_Error )+ T42_Size_Init( T42_Size size )+ {+ FT_Face face = size->root.face;+ T42_Face t42face = (T42_Face)face;+ FT_Size ttsize;+ FT_Error error = T42_Err_Ok;+++ error = FT_New_Size( t42face->ttf_face, &ttsize );+ size->ttsize = ttsize;++ FT_Activate_Size( ttsize );++ return error;+ }+++ FT_LOCAL_DEF( FT_Error )+ T42_Size_Request( T42_Size size,+ FT_Size_Request req )+ {+ T42_Face face = (T42_Face)size->root.face;+ FT_Error error;+++ FT_Activate_Size( size->ttsize );++ error = FT_Request_Size( face->ttf_face, req );+ if ( !error )+ ( (FT_Size)size )->metrics = face->ttf_face->size->metrics;++ return error;+ }+++ FT_LOCAL_DEF( FT_Error )+ T42_Size_Select( T42_Size size,+ FT_ULong strike_index )+ {+ T42_Face face = (T42_Face)size->root.face;+ FT_Error error;+++ FT_Activate_Size( size->ttsize );++ error = FT_Select_Size( face->ttf_face, (FT_Int)strike_index );+ if ( !error )+ ( (FT_Size)size )->metrics = face->ttf_face->size->metrics;++ return error;++ }+++ FT_LOCAL_DEF( void )+ T42_Size_Done( T42_Size size )+ {+ FT_Face face = size->root.face;+ T42_Face t42face = (T42_Face)face;+ FT_ListNode node;+++ node = FT_List_Find( &t42face->ttf_face->sizes_list, size->ttsize );+ if ( node )+ {+ FT_Done_Size( size->ttsize );+ size->ttsize = NULL;+ }+ }+++ FT_LOCAL_DEF( FT_Error )+ T42_GlyphSlot_Init( T42_GlyphSlot slot )+ {+ FT_Face face = slot->root.face;+ T42_Face t42face = (T42_Face)face;+ FT_GlyphSlot ttslot;+ FT_Error error = T42_Err_Ok;+++ if ( face->glyph == NULL )+ {+ /* First glyph slot for this face */+ slot->ttslot = t42face->ttf_face->glyph;+ }+ else+ {+ error = FT_New_GlyphSlot( t42face->ttf_face, &ttslot );+ slot->ttslot = ttslot;+ }++ return error;+ }+++ FT_LOCAL_DEF( void )+ T42_GlyphSlot_Done( T42_GlyphSlot slot )+ {+ FT_Done_GlyphSlot( slot->ttslot );+ }+++ static void+ t42_glyphslot_clear( FT_GlyphSlot slot )+ {+ /* free bitmap if needed */+ ft_glyphslot_free_bitmap( slot );++ /* clear all public fields in the glyph slot */+ FT_ZERO( &slot->metrics );+ FT_ZERO( &slot->outline );+ FT_ZERO( &slot->bitmap );++ slot->bitmap_left = 0;+ slot->bitmap_top = 0;+ slot->num_subglyphs = 0;+ slot->subglyphs = 0;+ slot->control_data = 0;+ slot->control_len = 0;+ slot->other = 0;+ slot->format = FT_GLYPH_FORMAT_NONE;++ slot->linearHoriAdvance = 0;+ slot->linearVertAdvance = 0;+ }+++ FT_LOCAL_DEF( FT_Error )+ T42_GlyphSlot_Load( FT_GlyphSlot glyph,+ FT_Size size,+ FT_UInt glyph_index,+ FT_Int32 load_flags )+ {+ FT_Error error;+ T42_GlyphSlot t42slot = (T42_GlyphSlot)glyph;+ T42_Size t42size = (T42_Size)size;+ FT_Driver_Class ttclazz = ((T42_Driver)glyph->face->driver)->ttclazz;+++ t42_glyphslot_clear( t42slot->ttslot );+ error = ttclazz->load_glyph( t42slot->ttslot,+ t42size->ttsize,+ glyph_index,+ load_flags | FT_LOAD_NO_BITMAP );++ if ( !error )+ {+ glyph->metrics = t42slot->ttslot->metrics;++ glyph->linearHoriAdvance = t42slot->ttslot->linearHoriAdvance;+ glyph->linearVertAdvance = t42slot->ttslot->linearVertAdvance;++ glyph->format = t42slot->ttslot->format;+ glyph->outline = t42slot->ttslot->outline;++ glyph->bitmap = t42slot->ttslot->bitmap;+ glyph->bitmap_left = t42slot->ttslot->bitmap_left;+ glyph->bitmap_top = t42slot->ttslot->bitmap_top;++ glyph->num_subglyphs = t42slot->ttslot->num_subglyphs;+ glyph->subglyphs = t42slot->ttslot->subglyphs;++ glyph->control_data = t42slot->ttslot->control_data;+ glyph->control_len = t42slot->ttslot->control_len;+ }++ return error;+ }+++/* END */
+ src/type42/t42objs.h view
@@ -0,0 +1,124 @@+/***************************************************************************/+/* */+/* t42objs.h */+/* */+/* Type 42 objects manager (specification). */+/* */+/* Copyright 2002, 2003, 2006, 2007 by Roberto Alameda. */+/* */+/* 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 __T42OBJS_H__+#define __T42OBJS_H__++#include <ft2build.h>+#include FT_FREETYPE_H+#include FT_TYPE1_TABLES_H+#include FT_INTERNAL_TYPE1_TYPES_H+#include "t42types.h"+#include FT_INTERNAL_OBJECTS_H+#include FT_INTERNAL_DRIVER_H+#include FT_SERVICE_POSTSCRIPT_CMAPS_H+#include FT_INTERNAL_POSTSCRIPT_HINTS_H+++FT_BEGIN_HEADER+++ /* Type42 size */+ typedef struct T42_SizeRec_+ {+ FT_SizeRec root;+ FT_Size ttsize;++ } T42_SizeRec, *T42_Size;+++ /* Type42 slot */+ typedef struct T42_GlyphSlotRec_+ {+ FT_GlyphSlotRec root;+ FT_GlyphSlot ttslot;++ } T42_GlyphSlotRec, *T42_GlyphSlot;+++ /* Type 42 driver */+ typedef struct T42_DriverRec_+ {+ FT_DriverRec root;+ FT_Driver_Class ttclazz;+ void* extension_component;++ } T42_DriverRec, *T42_Driver;+++ /* */+++ FT_LOCAL( FT_Error )+ T42_Face_Init( FT_Stream stream,+ T42_Face face,+ FT_Int face_index,+ FT_Int num_params,+ FT_Parameter* params );+++ FT_LOCAL( void )+ T42_Face_Done( T42_Face face );+++ FT_LOCAL( FT_Error )+ T42_Size_Init( T42_Size size );+++ FT_LOCAL( FT_Error )+ T42_Size_Request( T42_Size size,+ FT_Size_Request req );+++ FT_LOCAL( FT_Error )+ T42_Size_Select( T42_Size size,+ FT_ULong strike_index );+++ FT_LOCAL( void )+ T42_Size_Done( T42_Size size );+++ FT_LOCAL( FT_Error )+ T42_GlyphSlot_Init( T42_GlyphSlot slot );+++ FT_LOCAL( FT_Error )+ T42_GlyphSlot_Load( FT_GlyphSlot glyph,+ FT_Size size,+ FT_UInt glyph_index,+ FT_Int32 load_flags );++ FT_LOCAL( void )+ T42_GlyphSlot_Done( T42_GlyphSlot slot );+++ FT_LOCAL( FT_Error )+ T42_Driver_Init( T42_Driver driver );++ FT_LOCAL( void )+ T42_Driver_Done( T42_Driver driver );++ /* */++FT_END_HEADER+++#endif /* __T42OBJS_H__ */+++/* END */
+ src/type42/t42parse.c view
@@ -0,0 +1,1187 @@+/***************************************************************************/+/* */+/* t42parse.c */+/* */+/* Type 42 font parser (body). */+/* */+/* Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by */+/* Roberto Alameda. */+/* */+/* 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 "t42parse.h"+#include "t42error.h"+#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_STREAM_H+#include FT_INTERNAL_POSTSCRIPT_AUX_H+++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_t42+++ static void+ t42_parse_font_matrix( T42_Face face,+ T42_Loader loader );+ static void+ t42_parse_encoding( T42_Face face,+ T42_Loader loader );++ static void+ t42_parse_charstrings( T42_Face face,+ T42_Loader loader );++ static void+ t42_parse_sfnts( T42_Face face,+ T42_Loader loader );+++ /* as Type42 fonts have no Private dict, */+ /* we set the last argument of T1_FIELD_XXX to 0 */+ static const+ T1_FieldRec t42_keywords[] =+ {++#undef FT_STRUCTURE+#define FT_STRUCTURE T1_FontInfo+#undef T1CODE+#define T1CODE T1_FIELD_LOCATION_FONT_INFO++ T1_FIELD_STRING( "version", version, 0 )+ T1_FIELD_STRING( "Notice", notice, 0 )+ T1_FIELD_STRING( "FullName", full_name, 0 )+ T1_FIELD_STRING( "FamilyName", family_name, 0 )+ T1_FIELD_STRING( "Weight", weight, 0 )+ T1_FIELD_NUM ( "ItalicAngle", italic_angle, 0 )+ T1_FIELD_BOOL ( "isFixedPitch", is_fixed_pitch, 0 )+ T1_FIELD_NUM ( "UnderlinePosition", underline_position, 0 )+ T1_FIELD_NUM ( "UnderlineThickness", underline_thickness, 0 )++#undef FT_STRUCTURE+#define FT_STRUCTURE PS_FontExtraRec+#undef T1CODE+#define T1CODE T1_FIELD_LOCATION_FONT_EXTRA++ T1_FIELD_NUM ( "FSType", fs_type, 0 )++#undef FT_STRUCTURE+#define FT_STRUCTURE T1_FontRec+#undef T1CODE+#define T1CODE T1_FIELD_LOCATION_FONT_DICT++ T1_FIELD_KEY ( "FontName", font_name, 0 )+ T1_FIELD_NUM ( "PaintType", paint_type, 0 )+ T1_FIELD_NUM ( "FontType", font_type, 0 )+ T1_FIELD_FIXED( "StrokeWidth", stroke_width, 0 )++#undef FT_STRUCTURE+#define FT_STRUCTURE FT_BBox+#undef T1CODE+#define T1CODE T1_FIELD_LOCATION_BBOX++ T1_FIELD_BBOX("FontBBox", xMin, 0 )++ T1_FIELD_CALLBACK( "FontMatrix", t42_parse_font_matrix, 0 )+ T1_FIELD_CALLBACK( "Encoding", t42_parse_encoding, 0 )+ T1_FIELD_CALLBACK( "CharStrings", t42_parse_charstrings, 0 )+ T1_FIELD_CALLBACK( "sfnts", t42_parse_sfnts, 0 )++ { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 }+ };+++#define T1_Add_Table( p, i, o, l ) (p)->funcs.add( (p), i, o, l )+#define T1_Done_Table( p ) \+ do \+ { \+ if ( (p)->funcs.done ) \+ (p)->funcs.done( p ); \+ } while ( 0 )+#define T1_Release_Table( p ) \+ do \+ { \+ if ( (p)->funcs.release ) \+ (p)->funcs.release( p ); \+ } while ( 0 )++#define T1_Skip_Spaces( p ) (p)->root.funcs.skip_spaces( &(p)->root )+#define T1_Skip_PS_Token( p ) (p)->root.funcs.skip_PS_token( &(p)->root )++#define T1_ToInt( p ) \+ (p)->root.funcs.to_int( &(p)->root )+#define T1_ToBytes( p, b, m, n, d ) \+ (p)->root.funcs.to_bytes( &(p)->root, b, m, n, d )++#define T1_ToFixedArray( p, m, f, t ) \+ (p)->root.funcs.to_fixed_array( &(p)->root, m, f, t )+#define T1_ToToken( p, t ) \+ (p)->root.funcs.to_token( &(p)->root, t )++#define T1_Load_Field( p, f, o, m, pf ) \+ (p)->root.funcs.load_field( &(p)->root, f, o, m, pf )+#define T1_Load_Field_Table( p, f, o, m, pf ) \+ (p)->root.funcs.load_field_table( &(p)->root, f, o, m, pf )+++ /********************* Parsing Functions ******************/++ FT_LOCAL_DEF( FT_Error )+ t42_parser_init( T42_Parser parser,+ FT_Stream stream,+ FT_Memory memory,+ PSAux_Service psaux )+ {+ FT_Error error = T42_Err_Ok;+ FT_Long size;+++ psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );++ parser->stream = stream;+ parser->base_len = 0;+ parser->base_dict = 0;+ parser->in_memory = 0;++ /*******************************************************************/+ /* */+ /* Here a short summary of what is going on: */+ /* */+ /* When creating a new Type 42 parser, we try to locate and load */+ /* the base dictionary, loading the whole font into memory. */+ /* */+ /* When `loading' the base dictionary, we only set up pointers */+ /* in the case of a memory-based stream. Otherwise, we allocate */+ /* and load the base dictionary in it. */+ /* */+ /* parser->in_memory is set if we have a memory stream. */+ /* */++ if ( FT_STREAM_SEEK( 0L ) ||+ FT_FRAME_ENTER( 17 ) )+ goto Exit;++ if ( ft_memcmp( stream->cursor, "%!PS-TrueTypeFont", 17 ) != 0 )+ {+ FT_TRACE2(( "not a Type42 font\n" ));+ error = T42_Err_Unknown_File_Format;+ }++ FT_FRAME_EXIT();++ if ( error || FT_STREAM_SEEK( 0 ) )+ goto Exit;++ size = stream->size;++ /* now, try to load `size' bytes of the `base' dictionary we */+ /* found previously */++ /* if it is a memory-based resource, set up pointers */+ if ( !stream->read )+ {+ parser->base_dict = (FT_Byte*)stream->base + stream->pos;+ parser->base_len = size;+ parser->in_memory = 1;++ /* check that the `size' field is valid */+ if ( FT_STREAM_SKIP( size ) )+ goto Exit;+ }+ else+ {+ /* read segment in memory */+ if ( FT_ALLOC( parser->base_dict, size ) ||+ FT_STREAM_READ( parser->base_dict, size ) )+ goto Exit;++ parser->base_len = size;+ }++ parser->root.base = parser->base_dict;+ parser->root.cursor = parser->base_dict;+ parser->root.limit = parser->root.cursor + parser->base_len;++ Exit:+ if ( error && !parser->in_memory )+ FT_FREE( parser->base_dict );++ return error;+ }+++ FT_LOCAL_DEF( void )+ t42_parser_done( T42_Parser parser )+ {+ FT_Memory memory = parser->root.memory;+++ /* free the base dictionary only when we have a disk stream */+ if ( !parser->in_memory )+ FT_FREE( parser->base_dict );++ parser->root.funcs.done( &parser->root );+ }+++ static int+ t42_is_space( FT_Byte c )+ {+ return ( c == ' ' || c == '\t' ||+ c == '\r' || c == '\n' || c == '\f' ||+ c == '\0' );+ }+++ static void+ t42_parse_font_matrix( T42_Face face,+ T42_Loader loader )+ {+ T42_Parser parser = &loader->parser;+ FT_Matrix* matrix = &face->type1.font_matrix;+ FT_Vector* offset = &face->type1.font_offset;+ FT_Face root = (FT_Face)&face->root;+ FT_Fixed temp[6];+ FT_Fixed temp_scale;+++ (void)T1_ToFixedArray( parser, 6, temp, 3 );++ temp_scale = FT_ABS( temp[3] );++ /* Set Units per EM based on FontMatrix values. We set the value to */+ /* 1000 / temp_scale, because temp_scale was already multiplied by */+ /* 1000 (in t1_tofixed, from psobjs.c). */++ root->units_per_EM = (FT_UShort)( FT_DivFix( 1000 * 0x10000L,+ temp_scale ) >> 16 );++ /* we need to scale the values by 1.0/temp_scale */+ if ( temp_scale != 0x10000L )+ {+ temp[0] = FT_DivFix( temp[0], temp_scale );+ temp[1] = FT_DivFix( temp[1], temp_scale );+ temp[2] = FT_DivFix( temp[2], temp_scale );+ temp[4] = FT_DivFix( temp[4], temp_scale );+ temp[5] = FT_DivFix( temp[5], temp_scale );+ temp[3] = 0x10000L;+ }++ matrix->xx = temp[0];+ matrix->yx = temp[1];+ matrix->xy = temp[2];+ matrix->yy = temp[3];++ /* note that the offsets must be expressed in integer font units */+ offset->x = temp[4] >> 16;+ offset->y = temp[5] >> 16;+ }+++ static void+ t42_parse_encoding( T42_Face face,+ T42_Loader loader )+ {+ T42_Parser parser = &loader->parser;+ FT_Byte* cur;+ FT_Byte* limit = parser->root.limit;++ PSAux_Service psaux = (PSAux_Service)face->psaux;+++ T1_Skip_Spaces( parser );+ cur = parser->root.cursor;+ if ( cur >= limit )+ {+ FT_ERROR(( "t42_parse_encoding: out of bounds\n" ));+ parser->root.error = T42_Err_Invalid_File_Format;+ return;+ }++ /* if we have a number or `[', the encoding is an array, */+ /* and we must load it now */+ if ( ft_isdigit( *cur ) || *cur == '[' )+ {+ T1_Encoding encode = &face->type1.encoding;+ FT_UInt count, n;+ PS_Table char_table = &loader->encoding_table;+ FT_Memory memory = parser->root.memory;+ FT_Error error;+ FT_Bool only_immediates = 0;+++ /* read the number of entries in the encoding; should be 256 */+ if ( *cur == '[' )+ {+ count = 256;+ only_immediates = 1;+ parser->root.cursor++;+ }+ else+ count = (FT_UInt)T1_ToInt( parser );++ T1_Skip_Spaces( parser );+ if ( parser->root.cursor >= limit )+ return;++ /* we use a T1_Table to store our charnames */+ loader->num_chars = encode->num_chars = count;+ if ( FT_NEW_ARRAY( encode->char_index, count ) ||+ FT_NEW_ARRAY( encode->char_name, count ) ||+ FT_SET_ERROR( psaux->ps_table_funcs->init(+ char_table, count, memory ) ) )+ {+ parser->root.error = error;+ return;+ }++ /* We need to `zero' out encoding_table.elements */+ for ( n = 0; n < count; n++ )+ {+ char* notdef = (char *)".notdef";+++ T1_Add_Table( char_table, n, notdef, 8 );+ }++ /* Now we need to read records of the form */+ /* */+ /* ... charcode /charname ... */+ /* */+ /* for each entry in our table. */+ /* */+ /* We simply look for a number followed by an immediate */+ /* name. Note that this ignores correctly the sequence */+ /* that is often seen in type42 fonts: */+ /* */+ /* 0 1 255 { 1 index exch /.notdef put } for dup */+ /* */+ /* used to clean the encoding array before anything else. */+ /* */+ /* Alternatively, if the array is directly given as */+ /* */+ /* /Encoding [ ... ] */+ /* */+ /* we only read immediates. */++ n = 0;+ T1_Skip_Spaces( parser );++ while ( parser->root.cursor < limit )+ {+ cur = parser->root.cursor;++ /* we stop when we encounter `def' or `]' */+ if ( *cur == 'd' && cur + 3 < limit )+ {+ if ( cur[1] == 'e' &&+ cur[2] == 'f' &&+ t42_is_space( cur[3] ) )+ {+ FT_TRACE6(( "encoding end\n" ));+ cur += 3;+ break;+ }+ }+ if ( *cur == ']' )+ {+ FT_TRACE6(( "encoding end\n" ));+ cur++;+ break;+ }++ /* check whether we have found an entry */+ if ( ft_isdigit( *cur ) || only_immediates )+ {+ FT_Int charcode;+++ if ( only_immediates )+ charcode = n;+ else+ {+ charcode = (FT_Int)T1_ToInt( parser );+ T1_Skip_Spaces( parser );+ }++ cur = parser->root.cursor;++ if ( *cur == '/' && cur + 2 < limit && n < count )+ {+ FT_PtrDist len;+++ cur++;++ parser->root.cursor = cur;+ T1_Skip_PS_Token( parser );+ if ( parser->root.error )+ return;++ len = parser->root.cursor - cur;++ parser->root.error = T1_Add_Table( char_table, charcode,+ cur, len + 1 );+ if ( parser->root.error )+ return;+ char_table->elements[charcode][len] = '\0';++ n++;+ }+ }+ else+ {+ T1_Skip_PS_Token( parser );+ if ( parser->root.error )+ return;+ }++ T1_Skip_Spaces( parser );+ }++ face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY;+ parser->root.cursor = cur;+ }++ /* Otherwise, we should have either `StandardEncoding', */+ /* `ExpertEncoding', or `ISOLatin1Encoding' */+ else+ {+ if ( cur + 17 < limit &&+ ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )+ face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD;++ else if ( cur + 15 < limit &&+ ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )+ face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT;++ else if ( cur + 18 < limit &&+ ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 )+ face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1;++ else+ {+ FT_ERROR(( "t42_parse_encoding: invalid token\n" ));+ parser->root.error = T42_Err_Invalid_File_Format;+ }+ }+ }+++ typedef enum T42_Load_Status_+ {+ BEFORE_START,+ BEFORE_TABLE_DIR,+ OTHER_TABLES++ } T42_Load_Status;+++ static void+ t42_parse_sfnts( T42_Face face,+ T42_Loader loader )+ {+ T42_Parser parser = &loader->parser;+ FT_Memory memory = parser->root.memory;+ FT_Byte* cur;+ FT_Byte* limit = parser->root.limit;+ FT_Error error;+ FT_Int num_tables = 0;+ FT_ULong count, ttf_size = 0;++ FT_Long n, string_size, old_string_size, real_size;+ FT_Byte* string_buf = NULL;+ FT_Bool allocated = 0;++ T42_Load_Status status;+++ /* The format is */+ /* */+ /* /sfnts [ <hexstring> <hexstring> ... ] def */+ /* */+ /* or */+ /* */+ /* /sfnts [ */+ /* <num_bin_bytes> RD <binary data> */+ /* <num_bin_bytes> RD <binary data> */+ /* ... */+ /* ] def */+ /* */+ /* with exactly one space after the `RD' token. */++ T1_Skip_Spaces( parser );++ if ( parser->root.cursor >= limit || *parser->root.cursor++ != '[' )+ {+ FT_ERROR(( "t42_parse_sfnts: can't find begin of sfnts vector\n" ));+ error = T42_Err_Invalid_File_Format;+ goto Fail;+ }++ T1_Skip_Spaces( parser );+ status = BEFORE_START;+ string_size = 0;+ old_string_size = 0;+ count = 0;++ while ( parser->root.cursor < limit )+ {+ cur = parser->root.cursor;++ if ( *cur == ']' )+ {+ parser->root.cursor++;+ goto Exit;+ }++ else if ( *cur == '<' )+ {+ T1_Skip_PS_Token( parser );+ if ( parser->root.error )+ goto Exit;++ /* don't include delimiters */+ string_size = (FT_Long)( ( parser->root.cursor - cur - 2 + 1 ) / 2 );+ if ( FT_REALLOC( string_buf, old_string_size, string_size ) )+ goto Fail;++ allocated = 1;++ parser->root.cursor = cur;+ (void)T1_ToBytes( parser, string_buf, string_size, &real_size, 1 );+ old_string_size = string_size;+ string_size = real_size;+ }++ else if ( ft_isdigit( *cur ) )+ {+ if ( allocated )+ {+ FT_ERROR(( "t42_parse_sfnts: "+ "can't handle mixed binary and hex strings\n" ));+ error = T42_Err_Invalid_File_Format;+ goto Fail;+ }++ string_size = T1_ToInt( parser );+ if ( string_size < 0 )+ {+ FT_ERROR(( "t42_parse_sfnts: invalid string size\n" ));+ error = T42_Err_Invalid_File_Format;+ goto Fail;+ }++ T1_Skip_PS_Token( parser ); /* `RD' */+ if ( parser->root.error )+ return;++ string_buf = parser->root.cursor + 1; /* one space after `RD' */++ if ( limit - parser->root.cursor < string_size )+ {+ FT_ERROR(( "t42_parse_sfnts: too many binary data\n" ));+ error = T42_Err_Invalid_File_Format;+ goto Fail;+ }+ else+ parser->root.cursor += string_size + 1;+ }++ if ( !string_buf )+ {+ FT_ERROR(( "t42_parse_sfnts: invalid data in sfnts array\n" ));+ error = T42_Err_Invalid_File_Format;+ goto Fail;+ }++ /* A string can have a trailing zero byte for padding. Ignore it. */+ if ( string_buf[string_size - 1] == 0 && ( string_size % 2 == 1 ) )+ string_size--;++ if ( !string_size )+ {+ FT_ERROR(( "t42_parse_sfnts: invalid string\n" ));+ error = T42_Err_Invalid_File_Format;+ goto Fail;+ }++ for ( n = 0; n < string_size; n++ )+ {+ switch ( status )+ {+ case BEFORE_START:+ /* load offset table, 12 bytes */+ if ( count < 12 )+ {+ face->ttf_data[count++] = string_buf[n];+ continue;+ }+ else+ {+ num_tables = 16 * face->ttf_data[4] + face->ttf_data[5];+ status = BEFORE_TABLE_DIR;+ ttf_size = 12 + 16 * num_tables;++ if ( FT_REALLOC( face->ttf_data, 12, ttf_size ) )+ goto Fail;+ }+ /* fall through */++ case BEFORE_TABLE_DIR:+ /* the offset table is read; read the table directory */+ if ( count < ttf_size )+ {+ face->ttf_data[count++] = string_buf[n];+ continue;+ }+ else+ {+ int i;+ FT_ULong len;+++ for ( i = 0; i < num_tables; i++ )+ {+ FT_Byte* p = face->ttf_data + 12 + 16 * i + 12;+++ len = FT_PEEK_ULONG( p );++ /* Pad to a 4-byte boundary length */+ ttf_size += ( len + 3 ) & ~3;+ }++ status = OTHER_TABLES;+ face->ttf_size = ttf_size;++ /* there are no more than 256 tables, so no size check here */+ if ( FT_REALLOC( face->ttf_data, 12 + 16 * num_tables,+ ttf_size + 1 ) )+ goto Fail;+ }+ /* fall through */++ case OTHER_TABLES:+ /* all other tables are just copied */+ if ( count >= ttf_size )+ {+ FT_ERROR(( "t42_parse_sfnts: too many binary data\n" ));+ error = T42_Err_Invalid_File_Format;+ goto Fail;+ }+ face->ttf_data[count++] = string_buf[n];+ }+ }++ T1_Skip_Spaces( parser );+ }++ /* if control reaches this point, the format was not valid */+ error = T42_Err_Invalid_File_Format;++ Fail:+ parser->root.error = error;++ Exit:+ if ( allocated )+ FT_FREE( string_buf );+ }+++ static void+ t42_parse_charstrings( T42_Face face,+ T42_Loader loader )+ {+ T42_Parser parser = &loader->parser;+ PS_Table code_table = &loader->charstrings;+ PS_Table name_table = &loader->glyph_names;+ PS_Table swap_table = &loader->swap_table;+ FT_Memory memory = parser->root.memory;+ FT_Error error;++ PSAux_Service psaux = (PSAux_Service)face->psaux;++ FT_Byte* cur;+ FT_Byte* limit = parser->root.limit;+ FT_UInt n;+ FT_UInt notdef_index = 0;+ FT_Byte notdef_found = 0;+++ T1_Skip_Spaces( parser );++ if ( parser->root.cursor >= limit )+ {+ FT_ERROR(( "t42_parse_charstrings: out of bounds\n" ));+ error = T42_Err_Invalid_File_Format;+ goto Fail;+ }++ if ( ft_isdigit( *parser->root.cursor ) )+ {+ loader->num_glyphs = (FT_UInt)T1_ToInt( parser );+ if ( parser->root.error )+ return;+ }+ else if ( *parser->root.cursor == '<' )+ {+ /* We have `<< ... >>'. Count the number of `/' in the dictionary */+ /* to get its size. */+ FT_UInt count = 0;+++ T1_Skip_PS_Token( parser );+ if ( parser->root.error )+ return;+ T1_Skip_Spaces( parser );+ cur = parser->root.cursor;++ while ( parser->root.cursor < limit )+ {+ if ( *parser->root.cursor == '/' )+ count++;+ else if ( *parser->root.cursor == '>' )+ {+ loader->num_glyphs = count;+ parser->root.cursor = cur; /* rewind */+ break;+ }+ T1_Skip_PS_Token( parser );+ if ( parser->root.error )+ return;+ T1_Skip_Spaces( parser );+ }+ }+ else+ {+ FT_ERROR(( "t42_parse_charstrings: invalid token\n" ));+ error = T42_Err_Invalid_File_Format;+ goto Fail;+ }++ if ( parser->root.cursor >= limit )+ {+ FT_ERROR(( "t42_parse_charstrings: out of bounds\n" ));+ error = T42_Err_Invalid_File_Format;+ goto Fail;+ }++ /* initialize tables */++ error = psaux->ps_table_funcs->init( code_table,+ loader->num_glyphs,+ memory );+ if ( error )+ goto Fail;++ error = psaux->ps_table_funcs->init( name_table,+ loader->num_glyphs,+ memory );+ if ( error )+ goto Fail;++ /* Initialize table for swapping index notdef_index and */+ /* index 0 names and codes (if necessary). */++ error = psaux->ps_table_funcs->init( swap_table, 4, memory );+ if ( error )+ goto Fail;++ n = 0;++ for (;;)+ {+ /* The format is simple: */+ /* `/glyphname' + index [+ def] */++ T1_Skip_Spaces( parser );++ cur = parser->root.cursor;+ if ( cur >= limit )+ break;++ /* We stop when we find an `end' keyword or '>' */+ if ( *cur == 'e' &&+ cur + 3 < limit &&+ cur[1] == 'n' &&+ cur[2] == 'd' &&+ t42_is_space( cur[3] ) )+ break;+ if ( *cur == '>' )+ break;++ T1_Skip_PS_Token( parser );+ if ( parser->root.error )+ return;++ if ( *cur == '/' )+ {+ FT_PtrDist len;+++ if ( cur + 1 >= limit )+ {+ FT_ERROR(( "t42_parse_charstrings: out of bounds\n" ));+ error = T42_Err_Invalid_File_Format;+ goto Fail;+ }++ cur++; /* skip `/' */+ len = parser->root.cursor - cur;++ error = T1_Add_Table( name_table, n, cur, len + 1 );+ if ( error )+ goto Fail;++ /* add a trailing zero to the name table */+ name_table->elements[n][len] = '\0';++ /* record index of /.notdef */+ if ( *cur == '.' &&+ ft_strcmp( ".notdef",+ (const char*)(name_table->elements[n]) ) == 0 )+ {+ notdef_index = n;+ notdef_found = 1;+ }++ T1_Skip_Spaces( parser );++ cur = parser->root.cursor;++ (void)T1_ToInt( parser );+ if ( parser->root.cursor >= limit )+ {+ FT_ERROR(( "t42_parse_charstrings: out of bounds\n" ));+ error = T42_Err_Invalid_File_Format;+ goto Fail;+ }++ len = parser->root.cursor - cur;++ error = T1_Add_Table( code_table, n, cur, len + 1 );+ if ( error )+ goto Fail;++ code_table->elements[n][len] = '\0';++ n++;+ if ( n >= loader->num_glyphs )+ break;+ }+ }++ loader->num_glyphs = n;++ if ( !notdef_found )+ {+ FT_ERROR(( "t42_parse_charstrings: no /.notdef glyph\n" ));+ error = T42_Err_Invalid_File_Format;+ goto Fail;+ }++ /* if /.notdef does not occupy index 0, do our magic. */+ if ( ft_strcmp( (const char*)".notdef",+ (const char*)name_table->elements[0] ) )+ {+ /* Swap glyph in index 0 with /.notdef glyph. First, add index 0 */+ /* name and code entries to swap_table. Then place notdef_index */+ /* name and code entries into swap_table. Then swap name and code */+ /* entries at indices notdef_index and 0 using values stored in */+ /* swap_table. */++ /* Index 0 name */+ error = T1_Add_Table( swap_table, 0,+ name_table->elements[0],+ name_table->lengths [0] );+ if ( error )+ goto Fail;++ /* Index 0 code */+ error = T1_Add_Table( swap_table, 1,+ code_table->elements[0],+ code_table->lengths [0] );+ if ( error )+ goto Fail;++ /* Index notdef_index name */+ error = T1_Add_Table( swap_table, 2,+ name_table->elements[notdef_index],+ name_table->lengths [notdef_index] );+ if ( error )+ goto Fail;++ /* Index notdef_index code */+ error = T1_Add_Table( swap_table, 3,+ code_table->elements[notdef_index],+ code_table->lengths [notdef_index] );+ if ( error )+ goto Fail;++ error = T1_Add_Table( name_table, notdef_index,+ swap_table->elements[0],+ swap_table->lengths [0] );+ if ( error )+ goto Fail;++ error = T1_Add_Table( code_table, notdef_index,+ swap_table->elements[1],+ swap_table->lengths [1] );+ if ( error )+ goto Fail;++ error = T1_Add_Table( name_table, 0,+ swap_table->elements[2],+ swap_table->lengths [2] );+ if ( error )+ goto Fail;++ error = T1_Add_Table( code_table, 0,+ swap_table->elements[3],+ swap_table->lengths [3] );+ if ( error )+ goto Fail;++ }++ return;++ Fail:+ parser->root.error = error;+ }+++ static FT_Error+ t42_load_keyword( T42_Face face,+ T42_Loader loader,+ T1_Field field )+ {+ FT_Error error;+ void* dummy_object;+ void** objects;+ FT_UInt max_objects = 0;+++ /* if the keyword has a dedicated callback, call it */+ if ( field->type == T1_FIELD_TYPE_CALLBACK )+ {+ field->reader( (FT_Face)face, loader );+ error = loader->parser.root.error;+ goto Exit;+ }++ /* now the keyword is either a simple field or a table of fields; */+ /* we are now going to take care of it */++ switch ( field->location )+ {+ case T1_FIELD_LOCATION_FONT_INFO:+ dummy_object = &face->type1.font_info;+ break;++ case T1_FIELD_LOCATION_FONT_EXTRA:+ dummy_object = &face->type1.font_extra;+ break;++ case T1_FIELD_LOCATION_BBOX:+ dummy_object = &face->type1.font_bbox;+ break;++ default:+ dummy_object = &face->type1;+ }++ objects = &dummy_object;++ if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY ||+ field->type == T1_FIELD_TYPE_FIXED_ARRAY )+ error = T1_Load_Field_Table( &loader->parser, field,+ objects, max_objects, 0 );+ else+ error = T1_Load_Field( &loader->parser, field,+ objects, max_objects, 0 );++ Exit:+ return error;+ }+++ FT_LOCAL_DEF( FT_Error )+ t42_parse_dict( T42_Face face,+ T42_Loader loader,+ FT_Byte* base,+ FT_Long size )+ {+ T42_Parser parser = &loader->parser;+ FT_Byte* limit;+ FT_Int n_keywords = (FT_Int)( sizeof ( t42_keywords ) /+ sizeof ( t42_keywords[0] ) );+++ parser->root.cursor = base;+ parser->root.limit = base + size;+ parser->root.error = T42_Err_Ok;++ limit = parser->root.limit;++ T1_Skip_Spaces( parser );++ while ( parser->root.cursor < limit )+ {+ FT_Byte* cur;+++ cur = parser->root.cursor;++ /* look for `FontDirectory' which causes problems for some fonts */+ if ( *cur == 'F' && cur + 25 < limit &&+ ft_strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )+ {+ FT_Byte* cur2;+++ /* skip the `FontDirectory' keyword */+ T1_Skip_PS_Token( parser );+ T1_Skip_Spaces ( parser );+ cur = cur2 = parser->root.cursor;++ /* look up the `known' keyword */+ while ( cur < limit )+ {+ if ( *cur == 'k' && cur + 5 < limit &&+ ft_strncmp( (char*)cur, "known", 5 ) == 0 )+ break;++ T1_Skip_PS_Token( parser );+ if ( parser->root.error )+ goto Exit;+ T1_Skip_Spaces ( parser );+ cur = parser->root.cursor;+ }++ if ( cur < limit )+ {+ T1_TokenRec token;+++ /* skip the `known' keyword and the token following it */+ T1_Skip_PS_Token( parser );+ T1_ToToken( parser, &token );++ /* if the last token was an array, skip it! */+ if ( token.type == T1_TOKEN_TYPE_ARRAY )+ cur2 = parser->root.cursor;+ }+ parser->root.cursor = cur2;+ }++ /* look for immediates */+ else if ( *cur == '/' && cur + 2 < limit )+ {+ FT_PtrDist len;+++ cur++;++ parser->root.cursor = cur;+ T1_Skip_PS_Token( parser );+ if ( parser->root.error )+ goto Exit;++ len = parser->root.cursor - cur;++ if ( len > 0 && len < 22 && parser->root.cursor < limit )+ {+ int i;+++ /* now compare the immediate name to the keyword table */++ /* loop through all known keywords */+ for ( i = 0; i < n_keywords; i++ )+ {+ T1_Field keyword = (T1_Field)&t42_keywords[i];+ FT_Byte *name = (FT_Byte*)keyword->ident;+++ if ( !name )+ continue;++ if ( cur[0] == name[0] &&+ len == (FT_PtrDist)ft_strlen( (const char *)name ) &&+ ft_memcmp( cur, name, len ) == 0 )+ {+ /* we found it -- run the parsing callback! */+ parser->root.error = t42_load_keyword( face,+ loader,+ keyword );+ if ( parser->root.error )+ return parser->root.error;+ break;+ }+ }+ }+ }+ else+ {+ T1_Skip_PS_Token( parser );+ if ( parser->root.error )+ goto Exit;+ }++ T1_Skip_Spaces( parser );+ }++ Exit:+ return parser->root.error;+ }+++ FT_LOCAL_DEF( void )+ t42_loader_init( T42_Loader loader,+ T42_Face face )+ {+ FT_UNUSED( face );++ FT_MEM_ZERO( loader, sizeof ( *loader ) );+ loader->num_glyphs = 0;+ loader->num_chars = 0;++ /* initialize the tables -- simply set their `init' field to 0 */+ loader->encoding_table.init = 0;+ loader->charstrings.init = 0;+ loader->glyph_names.init = 0;+ }+++ FT_LOCAL_DEF( void )+ t42_loader_done( T42_Loader loader )+ {+ T42_Parser parser = &loader->parser;+++ /* finalize tables */+ T1_Release_Table( &loader->encoding_table );+ T1_Release_Table( &loader->charstrings );+ T1_Release_Table( &loader->glyph_names );+ T1_Release_Table( &loader->swap_table );++ /* finalize parser */+ t42_parser_done( parser );+ }+++/* END */
+ src/type42/t42parse.h view
@@ -0,0 +1,90 @@+/***************************************************************************/+/* */+/* t42parse.h */+/* */+/* Type 42 font parser (specification). */+/* */+/* Copyright 2002, 2003 by Roberto Alameda. */+/* */+/* 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 __T42PARSE_H__+#define __T42PARSE_H__+++#include "t42objs.h"+#include FT_INTERNAL_POSTSCRIPT_AUX_H+++FT_BEGIN_HEADER++ typedef struct T42_ParserRec_+ {+ PS_ParserRec root;+ FT_Stream stream;++ FT_Byte* base_dict;+ FT_Long base_len;++ FT_Bool in_memory;++ } T42_ParserRec, *T42_Parser;+++ typedef struct T42_Loader_+ {+ T42_ParserRec parser; /* parser used to read the stream */++ FT_UInt num_chars; /* number of characters in encoding */+ PS_TableRec encoding_table; /* PS_Table used to store the */+ /* encoding character names */++ FT_UInt num_glyphs;+ PS_TableRec glyph_names;+ PS_TableRec charstrings;+ PS_TableRec swap_table; /* For moving .notdef glyph to index 0. */++ } T42_LoaderRec, *T42_Loader;+++ FT_LOCAL( FT_Error )+ t42_parser_init( T42_Parser parser,+ FT_Stream stream,+ FT_Memory memory,+ PSAux_Service psaux );++ FT_LOCAL( void )+ t42_parser_done( T42_Parser parser );+++ FT_LOCAL( FT_Error )+ t42_parse_dict( T42_Face face,+ T42_Loader loader,+ FT_Byte* base,+ FT_Long size );+++ FT_LOCAL( void )+ t42_loader_init( T42_Loader loader,+ T42_Face face );++ FT_LOCAL( void )+ t42_loader_done( T42_Loader loader );+++ /* */++FT_END_HEADER+++#endif /* __T42PARSE_H__ */+++/* END */
+ src/type42/t42types.h view
@@ -0,0 +1,56 @@+/***************************************************************************/+/* */+/* t42types.h */+/* */+/* Type 42 font data types (specification only). */+/* */+/* Copyright 2002, 2003, 2006, 2008 by Roberto Alameda. */+/* */+/* 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 __T42TYPES_H__+#define __T42TYPES_H__+++#include <ft2build.h>+#include FT_FREETYPE_H+#include FT_TYPE1_TABLES_H+#include FT_INTERNAL_TYPE1_TYPES_H+#include FT_INTERNAL_POSTSCRIPT_HINTS_H+++FT_BEGIN_HEADER+++ typedef struct T42_FaceRec_+ {+ FT_FaceRec root;+ T1_FontRec type1;+ const void* psnames;+ const void* psaux;+#if 0+ const void* afm_data;+#endif+ FT_Byte* ttf_data;+ FT_ULong ttf_size;+ FT_Face ttf_face;+ FT_CharMapRec charmaprecs[2];+ FT_CharMap charmaps[2];+ PS_UnicodesRec unicode_map;++ } T42_FaceRec, *T42_Face;+++FT_END_HEADER++#endif /* __T42TYPES_H__ */+++/* END */
+ src/type42/type42.c view
@@ -0,0 +1,25 @@+/***************************************************************************/+/* */+/* type42.c */+/* */+/* FreeType Type 42 driver component. */+/* */+/* Copyright 2002 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 "t42objs.c"+#include "t42parse.c"+#include "t42drivr.c"++/* END */
+ src/winfonts/fnterrs.h view
@@ -0,0 +1,41 @@+/***************************************************************************/+/* */+/* fnterrs.h */+/* */+/* Win FNT/FON error codes (specification only). */+/* */+/* Copyright 2001 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 Windows FNT/FON error enumeration */+ /* constants. */+ /* */+ /*************************************************************************/++#ifndef __FNTERRS_H__+#define __FNTERRS_H__++#include FT_MODULE_ERRORS_H++#undef __FTERRORS_H__++#define FT_ERR_PREFIX FNT_Err_+#define FT_ERR_BASE FT_Mod_Err_Winfonts++#include FT_ERRORS_H++#endif /* __FNTERRS_H__ */+++/* END */
+ src/winfonts/winfnt.c view
@@ -0,0 +1,1145 @@+/***************************************************************************/+/* */+/* winfnt.c */+/* */+/* FreeType font driver for Windows FNT/FON files */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* Copyright 2003 Huw D M Davies for Codeweavers */+/* Copyright 2007 Dmitry Timoshkov for Codeweavers */+/* */+/* 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_WINFONTS_H+#include FT_INTERNAL_DEBUG_H+#include FT_INTERNAL_STREAM_H+#include FT_INTERNAL_OBJECTS_H+#include FT_TRUETYPE_IDS_H ++#include "winfnt.h"+#include "fnterrs.h"+#include FT_SERVICE_WINFNT_H+#include FT_SERVICE_XFREE86_NAME_H++ /*************************************************************************/+ /* */+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */+ /* messages during execution. */+ /* */+#undef FT_COMPONENT+#define FT_COMPONENT trace_winfnt+++ static const FT_Frame_Field winmz_header_fields[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE WinMZ_HeaderRec++ FT_FRAME_START( 64 ),+ FT_FRAME_USHORT_LE ( magic ),+ FT_FRAME_SKIP_BYTES( 29 * 2 ),+ FT_FRAME_ULONG_LE ( lfanew ),+ FT_FRAME_END+ };++ static const FT_Frame_Field winne_header_fields[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE WinNE_HeaderRec++ FT_FRAME_START( 40 ),+ FT_FRAME_USHORT_LE ( magic ),+ FT_FRAME_SKIP_BYTES( 34 ),+ FT_FRAME_USHORT_LE ( resource_tab_offset ),+ FT_FRAME_USHORT_LE ( rname_tab_offset ),+ FT_FRAME_END+ };++ static const FT_Frame_Field winpe32_header_fields[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE WinPE32_HeaderRec++ FT_FRAME_START( 248 ),+ FT_FRAME_ULONG_LE ( magic ), /* PE00 */+ FT_FRAME_USHORT_LE ( machine ), /* 0x014c - i386 */+ FT_FRAME_USHORT_LE ( number_of_sections ),+ FT_FRAME_SKIP_BYTES( 12 ),+ FT_FRAME_USHORT_LE ( size_of_optional_header ),+ FT_FRAME_SKIP_BYTES( 2 ),+ FT_FRAME_USHORT_LE ( magic32 ), /* 0x10b */+ FT_FRAME_SKIP_BYTES( 110 ),+ FT_FRAME_ULONG_LE ( rsrc_virtual_address ),+ FT_FRAME_ULONG_LE ( rsrc_size ),+ FT_FRAME_SKIP_BYTES( 104 ),+ FT_FRAME_END+ };++ static const FT_Frame_Field winpe32_section_fields[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE WinPE32_SectionRec++ FT_FRAME_START( 40 ),+ FT_FRAME_BYTES ( name, 8 ),+ FT_FRAME_SKIP_BYTES( 4 ),+ FT_FRAME_ULONG_LE ( virtual_address ),+ FT_FRAME_ULONG_LE ( size_of_raw_data ),+ FT_FRAME_ULONG_LE ( pointer_to_raw_data ),+ FT_FRAME_SKIP_BYTES( 16 ),+ FT_FRAME_END+ };++ static const FT_Frame_Field winpe_rsrc_dir_fields[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE WinPE_RsrcDirRec++ FT_FRAME_START( 16 ),+ FT_FRAME_ULONG_LE ( characteristics ),+ FT_FRAME_ULONG_LE ( time_date_stamp ),+ FT_FRAME_USHORT_LE( major_version ),+ FT_FRAME_USHORT_LE( minor_version ),+ FT_FRAME_USHORT_LE( number_of_named_entries ),+ FT_FRAME_USHORT_LE( number_of_id_entries ),+ FT_FRAME_END+ };++ static const FT_Frame_Field winpe_rsrc_dir_entry_fields[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE WinPE_RsrcDirEntryRec++ FT_FRAME_START( 8 ),+ FT_FRAME_ULONG_LE( name ),+ FT_FRAME_ULONG_LE( offset ),+ FT_FRAME_END+ };++ static const FT_Frame_Field winpe_rsrc_data_entry_fields[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE WinPE_RsrcDataEntryRec++ FT_FRAME_START( 16 ),+ FT_FRAME_ULONG_LE( offset_to_data ),+ FT_FRAME_ULONG_LE( size ),+ FT_FRAME_ULONG_LE( code_page ),+ FT_FRAME_ULONG_LE( reserved ),+ FT_FRAME_END+ };++ static const FT_Frame_Field winfnt_header_fields[] =+ {+#undef FT_STRUCTURE+#define FT_STRUCTURE FT_WinFNT_HeaderRec++ FT_FRAME_START( 148 ),+ FT_FRAME_USHORT_LE( version ),+ FT_FRAME_ULONG_LE ( file_size ),+ FT_FRAME_BYTES ( copyright, 60 ),+ FT_FRAME_USHORT_LE( file_type ),+ FT_FRAME_USHORT_LE( nominal_point_size ),+ FT_FRAME_USHORT_LE( vertical_resolution ),+ FT_FRAME_USHORT_LE( horizontal_resolution ),+ FT_FRAME_USHORT_LE( ascent ),+ FT_FRAME_USHORT_LE( internal_leading ),+ FT_FRAME_USHORT_LE( external_leading ),+ FT_FRAME_BYTE ( italic ),+ FT_FRAME_BYTE ( underline ),+ FT_FRAME_BYTE ( strike_out ),+ FT_FRAME_USHORT_LE( weight ),+ FT_FRAME_BYTE ( charset ),+ FT_FRAME_USHORT_LE( pixel_width ),+ FT_FRAME_USHORT_LE( pixel_height ),+ FT_FRAME_BYTE ( pitch_and_family ),+ FT_FRAME_USHORT_LE( avg_width ),+ FT_FRAME_USHORT_LE( max_width ),+ FT_FRAME_BYTE ( first_char ),+ FT_FRAME_BYTE ( last_char ),+ FT_FRAME_BYTE ( default_char ),+ FT_FRAME_BYTE ( break_char ),+ FT_FRAME_USHORT_LE( bytes_per_row ),+ FT_FRAME_ULONG_LE ( device_offset ),+ FT_FRAME_ULONG_LE ( face_name_offset ),+ FT_FRAME_ULONG_LE ( bits_pointer ),+ FT_FRAME_ULONG_LE ( bits_offset ),+ FT_FRAME_BYTE ( reserved ),+ FT_FRAME_ULONG_LE ( flags ),+ FT_FRAME_USHORT_LE( A_space ),+ FT_FRAME_USHORT_LE( B_space ),+ FT_FRAME_USHORT_LE( C_space ),+ FT_FRAME_ULONG_LE ( color_table_offset ),+ FT_FRAME_BYTES ( reserved1, 16 ),+ FT_FRAME_END+ };+++ static void+ fnt_font_done( FNT_Face face )+ {+ FT_Memory memory = FT_FACE( face )->memory;+ FT_Stream stream = FT_FACE( face )->stream;+ FNT_Font font = face->font;+++ if ( !font )+ return;++ if ( font->fnt_frame )+ FT_FRAME_RELEASE( font->fnt_frame );+ FT_FREE( font->family_name );++ FT_FREE( font );+ face->font = 0;+ }+++ static FT_Error+ fnt_font_load( FNT_Font font,+ FT_Stream stream )+ {+ FT_Error error;+ FT_WinFNT_Header header = &font->header;+ FT_Bool new_format;+ FT_UInt size;+++ /* first of all, read the FNT header */+ if ( FT_STREAM_SEEK( font->offset ) ||+ FT_STREAM_READ_FIELDS( winfnt_header_fields, header ) )+ goto Exit;++ /* check header */+ if ( header->version != 0x200 &&+ header->version != 0x300 )+ {+ FT_TRACE2(( "[not a valid FNT file]\n" ));+ error = FNT_Err_Unknown_File_Format;+ goto Exit;+ }++ new_format = FT_BOOL( font->header.version == 0x300 );+ size = new_format ? 148 : 118;++ if ( header->file_size < size )+ {+ FT_TRACE2(( "[not a valid FNT file]\n" ));+ error = FNT_Err_Unknown_File_Format;+ goto Exit;+ }++ /* Version 2 doesn't have these fields */+ if ( header->version == 0x200 )+ {+ header->flags = 0;+ header->A_space = 0;+ header->B_space = 0;+ header->C_space = 0;++ header->color_table_offset = 0;+ }++ if ( header->file_type & 1 )+ {+ FT_TRACE2(( "[can't handle vector FNT fonts]\n" ));+ error = FNT_Err_Unknown_File_Format;+ goto Exit;+ }++ /* this is a FNT file/table; extract its frame */+ if ( FT_STREAM_SEEK( font->offset ) ||+ FT_FRAME_EXTRACT( header->file_size, font->fnt_frame ) )+ goto Exit;++ Exit:+ return error;+ }+++ static FT_Error+ fnt_face_get_dll_font( FNT_Face face,+ FT_Int face_index )+ {+ FT_Error error;+ FT_Stream stream = FT_FACE( face )->stream;+ FT_Memory memory = FT_FACE( face )->memory;+ WinMZ_HeaderRec mz_header;+++ face->font = 0;++ /* does it begin with an MZ header? */+ if ( FT_STREAM_SEEK( 0 ) ||+ FT_STREAM_READ_FIELDS( winmz_header_fields, &mz_header ) )+ goto Exit;++ error = FNT_Err_Unknown_File_Format;+ if ( mz_header.magic == WINFNT_MZ_MAGIC )+ {+ /* yes, now look for an NE header in the file */+ WinNE_HeaderRec ne_header;+++ FT_TRACE2(( "MZ signature found\n" ));++ if ( FT_STREAM_SEEK( mz_header.lfanew ) ||+ FT_STREAM_READ_FIELDS( winne_header_fields, &ne_header ) )+ goto Exit;++ error = FNT_Err_Unknown_File_Format;+ if ( ne_header.magic == WINFNT_NE_MAGIC )+ {+ /* good, now look into the resource table for each FNT resource */+ FT_ULong res_offset = mz_header.lfanew ++ ne_header.resource_tab_offset;+ FT_UShort size_shift;+ FT_UShort font_count = 0;+ FT_ULong font_offset = 0;+++ FT_TRACE2(( "NE signature found\n" ));++ if ( FT_STREAM_SEEK( res_offset ) ||+ FT_FRAME_ENTER( ne_header.rname_tab_offset -+ ne_header.resource_tab_offset ) )+ goto Exit;++ size_shift = FT_GET_USHORT_LE();++ for (;;)+ {+ FT_UShort type_id, count;+++ type_id = FT_GET_USHORT_LE();+ if ( !type_id )+ break;++ count = FT_GET_USHORT_LE();++ if ( type_id == 0x8008U )+ {+ font_count = count;+ font_offset = (FT_ULong)( FT_STREAM_POS() + 4 ++ ( stream->cursor - stream->limit ) );+ break;+ }++ stream->cursor += 4 + count * 12;+ }++ FT_FRAME_EXIT();++ if ( !font_count || !font_offset )+ {+ FT_TRACE2(( "this file doesn't contain any FNT resources\n" ));+ error = FNT_Err_Invalid_File_Format;+ goto Exit;+ }++ /* loading `winfnt_header_fields' needs at least 118 bytes; */+ /* use this as a rough measure to check the expected font size */+ if ( font_count * 118UL > stream->size )+ {+ FT_TRACE2(( "invalid number of faces\n" ));+ error = FNT_Err_Invalid_File_Format;+ goto Exit;+ }++ face->root.num_faces = font_count;++ if ( face_index >= font_count )+ {+ error = FNT_Err_Invalid_Argument;+ goto Exit;+ }+ else if ( face_index < 0 )+ goto Exit;++ if ( FT_NEW( face->font ) )+ goto Exit;++ if ( FT_STREAM_SEEK( font_offset + face_index * 12 ) ||+ FT_FRAME_ENTER( 12 ) )+ goto Fail;++ face->font->offset = (FT_ULong)FT_GET_USHORT_LE() << size_shift;+ face->font->fnt_size = (FT_ULong)FT_GET_USHORT_LE() << size_shift;++ stream->cursor += 8;++ FT_FRAME_EXIT();++ error = fnt_font_load( face->font, stream );+ }+ else if ( ne_header.magic == WINFNT_PE_MAGIC )+ {+ WinPE32_HeaderRec pe32_header;+ WinPE32_SectionRec pe32_section;+ WinPE_RsrcDirRec root_dir, name_dir, lang_dir;+ WinPE_RsrcDirEntryRec dir_entry1, dir_entry2, dir_entry3;+ WinPE_RsrcDataEntryRec data_entry;++ FT_Long root_dir_offset, name_dir_offset, lang_dir_offset;+ FT_UShort i, j, k;+++ FT_TRACE2(( "PE signature found\n" ));++ if ( FT_STREAM_SEEK( mz_header.lfanew ) ||+ FT_STREAM_READ_FIELDS( winpe32_header_fields, &pe32_header ) )+ goto Exit;++ FT_TRACE2(( "magic %04lx, machine %02x, number_of_sections %u, "+ "size_of_optional_header %02x\n"+ "magic32 %02x, rsrc_virtual_address %04lx, "+ "rsrc_size %04lx\n",+ pe32_header.magic, pe32_header.machine,+ pe32_header.number_of_sections,+ pe32_header.size_of_optional_header,+ pe32_header.magic32, pe32_header.rsrc_virtual_address,+ pe32_header.rsrc_size ));++ if ( pe32_header.magic != WINFNT_PE_MAGIC /* check full signature */ ||+ pe32_header.machine != 0x014c /* i386 */ ||+ pe32_header.size_of_optional_header != 0xe0 /* FIXME */ ||+ pe32_header.magic32 != 0x10b )+ {+ FT_TRACE2(( "this file has an invalid PE header\n" ));+ error = FNT_Err_Invalid_File_Format;+ goto Exit;+ }++ face->root.num_faces = 0;++ for ( i = 0; i < pe32_header.number_of_sections; i++ )+ {+ if ( FT_STREAM_READ_FIELDS( winpe32_section_fields,+ &pe32_section ) )+ goto Exit;++ FT_TRACE2(( "name %.8s, va %04lx, size %04lx, offset %04lx\n",+ pe32_section.name, pe32_section.virtual_address,+ pe32_section.size_of_raw_data,+ pe32_section.pointer_to_raw_data ));++ if ( pe32_header.rsrc_virtual_address ==+ pe32_section.virtual_address )+ goto Found_rsrc_section;+ }++ FT_TRACE2(( "this file doesn't contain any resources\n" ));+ error = FNT_Err_Invalid_File_Format;+ goto Exit;++ Found_rsrc_section:+ FT_TRACE2(( "found resources section %.8s\n", pe32_section.name ));++ if ( FT_STREAM_SEEK( pe32_section.pointer_to_raw_data ) ||+ FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields, &root_dir ) )+ goto Exit;++ root_dir_offset = pe32_section.pointer_to_raw_data;++ for ( i = 0; i < root_dir.number_of_named_entries ++ root_dir.number_of_id_entries; i++ )+ {+ if ( FT_STREAM_SEEK( root_dir_offset + 16 + i * 8 ) ||+ FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields,+ &dir_entry1 ) )+ goto Exit;++ if ( !(dir_entry1.offset & 0x80000000UL ) /* DataIsDirectory */ )+ {+ error = FNT_Err_Invalid_File_Format;+ goto Exit;+ }++ dir_entry1.offset &= ~0x80000000UL;++ name_dir_offset = pe32_section.pointer_to_raw_data ++ dir_entry1.offset;++ if ( FT_STREAM_SEEK( pe32_section.pointer_to_raw_data ++ dir_entry1.offset ) ||+ FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields, &name_dir ) )+ goto Exit;++ for ( j = 0; j < name_dir.number_of_named_entries ++ name_dir.number_of_id_entries; j++ )+ {+ if ( FT_STREAM_SEEK( name_dir_offset + 16 + j * 8 ) ||+ FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields,+ &dir_entry2 ) )+ goto Exit;++ if ( !(dir_entry2.offset & 0x80000000UL ) /* DataIsDirectory */ )+ {+ error = FNT_Err_Invalid_File_Format;+ goto Exit;+ }++ dir_entry2.offset &= ~0x80000000UL;++ lang_dir_offset = pe32_section.pointer_to_raw_data ++ dir_entry2.offset;++ if ( FT_STREAM_SEEK( pe32_section.pointer_to_raw_data ++ dir_entry2.offset ) ||+ FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields, &lang_dir ) )+ goto Exit;++ for ( k = 0; k < lang_dir.number_of_named_entries ++ lang_dir.number_of_id_entries; k++ )+ {+ if ( FT_STREAM_SEEK( lang_dir_offset + 16 + k * 8 ) ||+ FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields,+ &dir_entry3 ) )+ goto Exit;++ if ( dir_entry2.offset & 0x80000000UL /* DataIsDirectory */ )+ {+ error = FNT_Err_Invalid_File_Format;+ goto Exit;+ }++ if ( dir_entry1.name == 8 /* RT_FONT */ )+ {+ if ( FT_STREAM_SEEK( root_dir_offset + dir_entry3.offset ) ||+ FT_STREAM_READ_FIELDS( winpe_rsrc_data_entry_fields,+ &data_entry ) )+ goto Exit;++ FT_TRACE2(( "found font #%lu, offset %04lx, "+ "size %04lx, cp %lu\n",+ dir_entry2.name,+ pe32_section.pointer_to_raw_data ++ data_entry.offset_to_data -+ pe32_section.virtual_address,+ data_entry.size, data_entry.code_page ));++ if ( face_index == face->root.num_faces )+ {+ if ( FT_NEW( face->font ) )+ goto Exit;++ face->font->offset = pe32_section.pointer_to_raw_data ++ data_entry.offset_to_data -+ pe32_section.virtual_address;+ face->font->fnt_size = data_entry.size;++ error = fnt_font_load( face->font, stream );+ if ( error )+ {+ FT_TRACE2(( "font #%lu load error %d\n",+ dir_entry2.name, error ));+ goto Fail;+ }+ else+ FT_TRACE2(( "font #%lu successfully loaded\n",+ dir_entry2.name ));+ }++ face->root.num_faces++;+ }+ }+ }+ }+ }++ if ( !face->root.num_faces )+ {+ FT_TRACE2(( "this file doesn't contain any RT_FONT resources\n" ));+ error = FNT_Err_Invalid_File_Format;+ goto Exit;+ }++ if ( face_index >= face->root.num_faces )+ {+ error = FNT_Err_Invalid_Argument;+ goto Exit;+ }+ }++ Fail:+ if ( error )+ fnt_font_done( face );++ Exit:+ return error;+ }+++ typedef struct FNT_CMapRec_+ {+ FT_CMapRec cmap;+ FT_UInt32 first;+ FT_UInt32 count;++ } FNT_CMapRec, *FNT_CMap;+++ static FT_Error+ fnt_cmap_init( FNT_CMap cmap )+ {+ FNT_Face face = (FNT_Face)FT_CMAP_FACE( cmap );+ FNT_Font font = face->font;+++ cmap->first = (FT_UInt32) font->header.first_char;+ cmap->count = (FT_UInt32)( font->header.last_char - cmap->first + 1 );++ return 0;+ }+++ static FT_UInt+ fnt_cmap_char_index( FNT_CMap cmap,+ FT_UInt32 char_code )+ {+ FT_UInt gindex = 0;+++ char_code -= cmap->first;+ if ( char_code < cmap->count )+ /* we artificially increase the glyph index; */+ /* FNT_Load_Glyph reverts to the right one */+ gindex = (FT_UInt)( char_code + 1 );+ return gindex;+ }+++ static FT_UInt32+ fnt_cmap_char_next( FNT_CMap cmap,+ FT_UInt32 *pchar_code )+ {+ FT_UInt gindex = 0;+ FT_UInt32 result = 0;+ FT_UInt32 char_code = *pchar_code + 1;+++ if ( char_code <= cmap->first )+ {+ result = cmap->first;+ gindex = 1;+ }+ else+ {+ char_code -= cmap->first;+ if ( char_code < cmap->count )+ {+ result = cmap->first + char_code;+ gindex = (FT_UInt)( char_code + 1 );+ }+ }++ *pchar_code = result;+ return gindex;+ }+++ static const FT_CMap_ClassRec fnt_cmap_class_rec =+ {+ sizeof ( FNT_CMapRec ),++ (FT_CMap_InitFunc) fnt_cmap_init,+ (FT_CMap_DoneFunc) NULL,+ (FT_CMap_CharIndexFunc)fnt_cmap_char_index,+ (FT_CMap_CharNextFunc) fnt_cmap_char_next,++ NULL, NULL, NULL, NULL, NULL+ };++ static FT_CMap_Class const fnt_cmap_class = &fnt_cmap_class_rec;+++ static void+ FNT_Face_Done( FNT_Face face )+ {+ FT_Memory memory;+++ if ( !face )+ return;++ memory = FT_FACE_MEMORY( face );++ fnt_font_done( face );++ FT_FREE( face->root.available_sizes );+ face->root.num_fixed_sizes = 0;+ }+++ static FT_Error+ FNT_Face_Init( FT_Stream stream,+ FNT_Face face,+ FT_Int face_index,+ FT_Int num_params,+ FT_Parameter* params )+ {+ FT_Error error;+ FT_Memory memory = FT_FACE_MEMORY( face );++ FT_UNUSED( num_params );+ FT_UNUSED( params );+++ /* try to load font from a DLL */+ error = fnt_face_get_dll_font( face, face_index );+ if ( !error && face_index < 0 )+ goto Exit;++ if ( error == FNT_Err_Unknown_File_Format )+ {+ /* this didn't work; try to load a single FNT font */+ FNT_Font font;++ if ( FT_NEW( face->font ) )+ goto Exit;++ face->root.num_faces = 1;++ font = face->font;+ font->offset = 0;+ font->fnt_size = stream->size;++ error = fnt_font_load( font, stream );++ if ( !error )+ {+ if ( face_index > 0 )+ error = FNT_Err_Invalid_Argument;+ else if ( face_index < 0 )+ goto Exit;+ }+ }++ if ( error )+ goto Fail;++ /* we now need to fill the root FT_Face fields */+ /* with relevant information */+ {+ FT_Face root = FT_FACE( face );+ FNT_Font font = face->font;+ FT_PtrDist family_size;+++ root->face_index = face_index;++ root->face_flags = FT_FACE_FLAG_FIXED_SIZES |+ FT_FACE_FLAG_HORIZONTAL;++ if ( font->header.avg_width == font->header.max_width )+ root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;++ if ( font->header.italic )+ root->style_flags |= FT_STYLE_FLAG_ITALIC;++ if ( font->header.weight >= 800 )+ root->style_flags |= FT_STYLE_FLAG_BOLD;++ /* set up the `fixed_sizes' array */+ if ( FT_NEW_ARRAY( root->available_sizes, 1 ) )+ goto Fail;++ root->num_fixed_sizes = 1;++ {+ FT_Bitmap_Size* bsize = root->available_sizes;+ FT_UShort x_res, y_res;+++ bsize->width = font->header.avg_width;+ bsize->height = (FT_Short)(+ font->header.pixel_height + font->header.external_leading );+ bsize->size = font->header.nominal_point_size << 6;++ x_res = font->header.horizontal_resolution;+ if ( !x_res )+ x_res = 72;++ y_res = font->header.vertical_resolution;+ if ( !y_res )+ y_res = 72;++ bsize->y_ppem = FT_MulDiv( bsize->size, y_res, 72 );+ bsize->y_ppem = FT_PIX_ROUND( bsize->y_ppem );++ /*+ * this reads:+ *+ * the nominal height is larger than the bbox's height+ *+ * => nominal_point_size contains incorrect value;+ * use pixel_height as the nominal height+ */+ if ( bsize->y_ppem > ( font->header.pixel_height << 6 ) )+ {+ FT_TRACE2(( "use pixel_height as the nominal height\n" ));++ bsize->y_ppem = font->header.pixel_height << 6;+ bsize->size = FT_MulDiv( bsize->y_ppem, 72, y_res );+ }++ bsize->x_ppem = FT_MulDiv( bsize->size, x_res, 72 );+ bsize->x_ppem = FT_PIX_ROUND( bsize->x_ppem );+ }++ {+ FT_CharMapRec charmap;+++ charmap.encoding = FT_ENCODING_NONE;+ /* initial platform/encoding should indicate unset status? */+ charmap.platform_id = TT_PLATFORM_APPLE_UNICODE;+ charmap.encoding_id = TT_APPLE_ID_DEFAULT;+ charmap.face = root;++ if ( font->header.charset == FT_WinFNT_ID_MAC )+ {+ charmap.encoding = FT_ENCODING_APPLE_ROMAN;+ charmap.platform_id = TT_PLATFORM_MACINTOSH;+/* charmap.encoding_id = TT_MAC_ID_ROMAN; */+ }++ error = FT_CMap_New( fnt_cmap_class,+ NULL,+ &charmap,+ NULL );+ if ( error )+ goto Fail;++ /* Select default charmap */+ if ( root->num_charmaps )+ root->charmap = root->charmaps[0];+ }++ /* setup remaining flags */++ /* reserve one slot for the .notdef glyph at index 0 */+ root->num_glyphs = font->header.last_char -+ font->header.first_char + 1 + 1;++ if ( font->header.face_name_offset >= font->header.file_size )+ {+ FT_TRACE2(( "invalid family name offset\n" ));+ error = FNT_Err_Invalid_File_Format;+ goto Fail;+ }+ family_size = font->header.file_size - font->header.face_name_offset;+ /* Some broken fonts don't delimit the face name with a final */+ /* NULL byte -- the frame is erroneously one byte too small. */+ /* We thus allocate one more byte, setting it explicitly to */+ /* zero. */+ if ( FT_ALLOC( font->family_name, family_size + 1 ) )+ goto Fail;++ FT_MEM_COPY( font->family_name,+ font->fnt_frame + font->header.face_name_offset,+ family_size );++ font->family_name[family_size] = '\0';++ if ( FT_REALLOC( font->family_name,+ family_size,+ ft_strlen( font->family_name ) + 1 ) )+ goto Fail;++ root->family_name = font->family_name;+ root->style_name = (char *)"Regular";++ if ( root->style_flags & FT_STYLE_FLAG_BOLD )+ {+ if ( root->style_flags & FT_STYLE_FLAG_ITALIC )+ root->style_name = (char *)"Bold Italic";+ else+ root->style_name = (char *)"Bold";+ }+ else if ( root->style_flags & FT_STYLE_FLAG_ITALIC )+ root->style_name = (char *)"Italic";+ }+ goto Exit;++ Fail:+ FNT_Face_Done( face );++ Exit:+ return error;+ }+++ static FT_Error+ FNT_Size_Select( FT_Size size )+ {+ FNT_Face face = (FNT_Face)size->face;+ FT_WinFNT_Header header = &face->font->header;+++ FT_Select_Metrics( size->face, 0 );++ size->metrics.ascender = header->ascent * 64;+ size->metrics.descender = -( header->pixel_height -+ header->ascent ) * 64;+ size->metrics.max_advance = header->max_width * 64;++ return FNT_Err_Ok;+ }+++ static FT_Error+ FNT_Size_Request( FT_Size size,+ FT_Size_Request req )+ {+ FNT_Face face = (FNT_Face)size->face;+ FT_WinFNT_Header header = &face->font->header;+ FT_Bitmap_Size* bsize = size->face->available_sizes;+ FT_Error error = FNT_Err_Invalid_Pixel_Size;+ FT_Long height;+++ height = FT_REQUEST_HEIGHT( req );+ height = ( height + 32 ) >> 6;++ switch ( req->type )+ {+ case FT_SIZE_REQUEST_TYPE_NOMINAL:+ if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) )+ error = FNT_Err_Ok;+ break;++ case FT_SIZE_REQUEST_TYPE_REAL_DIM:+ if ( height == header->pixel_height )+ error = FNT_Err_Ok;+ break;++ default:+ error = FNT_Err_Unimplemented_Feature;+ break;+ }++ if ( error )+ return error;+ else+ return FNT_Size_Select( size );+ }+++ static FT_Error+ FNT_Load_Glyph( FT_GlyphSlot slot,+ FT_Size size,+ FT_UInt glyph_index,+ FT_Int32 load_flags )+ {+ FNT_Face face = (FNT_Face)FT_SIZE_FACE( size );+ FNT_Font font;+ FT_Error error = FNT_Err_Ok;+ FT_Byte* p;+ FT_Int len;+ FT_Bitmap* bitmap = &slot->bitmap;+ FT_ULong offset;+ FT_Bool new_format;++ FT_UNUSED( load_flags );+++ if ( !face )+ {+ error = FNT_Err_Invalid_Argument;+ goto Exit;+ }++ font = face->font;++ if ( !font ||+ glyph_index >= (FT_UInt)( FT_FACE( face )->num_glyphs ) )+ {+ error = FNT_Err_Invalid_Argument;+ goto Exit;+ }++ if ( glyph_index > 0 )+ glyph_index--; /* revert to real index */+ else+ glyph_index = font->header.default_char; /* the .notdef glyph */++ new_format = FT_BOOL( font->header.version == 0x300 );+ len = new_format ? 6 : 4;++ /* jump to glyph entry */+ p = font->fnt_frame + ( new_format ? 148 : 118 ) + len * glyph_index;++ bitmap->width = FT_NEXT_SHORT_LE( p );++ if ( new_format )+ offset = FT_NEXT_ULONG_LE( p );+ else+ offset = FT_NEXT_USHORT_LE( p );++ if ( offset >= font->header.file_size )+ {+ FT_TRACE2(( "invalid FNT offset\n" ));+ error = FNT_Err_Invalid_File_Format;+ goto Exit;+ }++ /* jump to glyph data */+ p = font->fnt_frame + /* font->header.bits_offset */ + offset;++ /* allocate and build bitmap */+ {+ FT_Memory memory = FT_FACE_MEMORY( slot->face );+ FT_Int pitch = ( bitmap->width + 7 ) >> 3;+ FT_Byte* column;+ FT_Byte* write;+++ bitmap->pitch = pitch;+ bitmap->rows = font->header.pixel_height;+ bitmap->pixel_mode = FT_PIXEL_MODE_MONO;++ if ( offset + pitch * bitmap->rows >= font->header.file_size )+ {+ FT_TRACE2(( "invalid bitmap width\n" ));+ error = FNT_Err_Invalid_File_Format;+ goto Exit;+ }++ /* note: since glyphs are stored in columns and not in rows we */+ /* can't use ft_glyphslot_set_bitmap */+ if ( FT_ALLOC_MULT( bitmap->buffer, pitch, bitmap->rows ) )+ goto Exit;++ column = (FT_Byte*)bitmap->buffer;++ for ( ; pitch > 0; pitch--, column++ )+ {+ FT_Byte* limit = p + bitmap->rows;+++ for ( write = column; p < limit; p++, write += bitmap->pitch )+ *write = *p;+ }+ }++ slot->internal->flags = FT_GLYPH_OWN_BITMAP;+ slot->bitmap_left = 0;+ slot->bitmap_top = font->header.ascent;+ slot->format = FT_GLYPH_FORMAT_BITMAP;++ /* now set up metrics */+ slot->metrics.width = bitmap->width << 6;+ slot->metrics.height = bitmap->rows << 6;+ slot->metrics.horiAdvance = bitmap->width << 6;+ slot->metrics.horiBearingX = 0;+ slot->metrics.horiBearingY = slot->bitmap_top << 6;++ ft_synthesize_vertical_metrics( &slot->metrics,+ bitmap->rows << 6 );++ Exit:+ return error;+ }+++ static FT_Error+ winfnt_get_header( FT_Face face,+ FT_WinFNT_HeaderRec *aheader )+ {+ FNT_Font font = ((FNT_Face)face)->font;+++ *aheader = font->header;++ return 0;+ }+++ static const FT_Service_WinFntRec winfnt_service_rec =+ {+ winfnt_get_header+ };++ /*+ * SERVICE LIST+ *+ */++ static const FT_ServiceDescRec winfnt_services[] =+ {+ { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_WINFNT },+ { FT_SERVICE_ID_WINFNT, &winfnt_service_rec },+ { NULL, NULL }+ };+++ static FT_Module_Interface+ winfnt_get_service( FT_Driver driver,+ const FT_String* service_id )+ {+ FT_UNUSED( driver );++ return ft_service_list_lookup( winfnt_services, service_id );+ }+++++ FT_CALLBACK_TABLE_DEF+ const FT_Driver_ClassRec winfnt_driver_class =+ {+ {+ FT_MODULE_FONT_DRIVER |+ FT_MODULE_DRIVER_NO_OUTLINES,+ sizeof ( FT_DriverRec ),++ "winfonts",+ 0x10000L,+ 0x20000L,++ 0,++ (FT_Module_Constructor)0,+ (FT_Module_Destructor) 0,+ (FT_Module_Requester) winfnt_get_service+ },++ sizeof( FNT_FaceRec ),+ sizeof( FT_SizeRec ),+ sizeof( FT_GlyphSlotRec ),++ (FT_Face_InitFunc) FNT_Face_Init,+ (FT_Face_DoneFunc) FNT_Face_Done,+ (FT_Size_InitFunc) 0,+ (FT_Size_DoneFunc) 0,+ (FT_Slot_InitFunc) 0,+ (FT_Slot_DoneFunc) 0,++#ifdef FT_CONFIG_OPTION_OLD_INTERNALS+ ft_stub_set_char_sizes,+ ft_stub_set_pixel_sizes,+#endif+ (FT_Slot_LoadFunc) FNT_Load_Glyph,++ (FT_Face_GetKerningFunc) 0,+ (FT_Face_AttachFunc) 0,+ (FT_Face_GetAdvancesFunc) 0,++ (FT_Size_RequestFunc) FNT_Size_Request,+ (FT_Size_SelectFunc) FNT_Size_Select+ };+++/* END */
+ src/winfonts/winfnt.h view
@@ -0,0 +1,171 @@+/***************************************************************************/+/* */+/* winfnt.h */+/* */+/* FreeType font driver for Windows FNT/FON files */+/* */+/* Copyright 1996-2001, 2002, 2003, 2004, 2007 by */+/* David Turner, Robert Wilhelm, and Werner Lemberg. */+/* Copyright 2007 Dmitry Timoshkov for Codeweavers */+/* */+/* 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 __WINFNT_H__+#define __WINFNT_H__+++#include <ft2build.h>+#include FT_WINFONTS_H+#include FT_INTERNAL_DRIVER_H+++FT_BEGIN_HEADER++#ifdef FT_CONFIG_OPTION_PIC+#error "this module does not support PIC yet"+#endif ++ typedef struct WinMZ_HeaderRec_+ {+ FT_UShort magic;+ /* skipped content */+ FT_UShort lfanew;++ } WinMZ_HeaderRec;+++ typedef struct WinNE_HeaderRec_+ {+ FT_UShort magic;+ /* skipped content */+ FT_UShort resource_tab_offset;+ FT_UShort rname_tab_offset;++ } WinNE_HeaderRec;+++ typedef struct WinPE32_HeaderRec_+ {+ FT_ULong magic;+ FT_UShort machine;+ FT_UShort number_of_sections;+ /* skipped content */+ FT_UShort size_of_optional_header;+ /* skipped content */+ FT_UShort magic32;+ /* skipped content */+ FT_ULong rsrc_virtual_address;+ FT_ULong rsrc_size;+ /* skipped content */++ } WinPE32_HeaderRec;+++ typedef struct WinPE32_SectionRec_+ {+ FT_Byte name[8];+ /* skipped content */+ FT_ULong virtual_address;+ FT_ULong size_of_raw_data;+ FT_ULong pointer_to_raw_data;+ /* skipped content */++ } WinPE32_SectionRec;+++ typedef struct WinPE_RsrcDirRec_+ {+ FT_ULong characteristics;+ FT_ULong time_date_stamp;+ FT_UShort major_version;+ FT_UShort minor_version;+ FT_UShort number_of_named_entries;+ FT_UShort number_of_id_entries;++ } WinPE_RsrcDirRec;+++ typedef struct WinPE_RsrcDirEntryRec_+ {+ FT_ULong name;+ FT_ULong offset;++ } WinPE_RsrcDirEntryRec;+++ typedef struct WinPE_RsrcDataEntryRec_+ {+ FT_ULong offset_to_data;+ FT_ULong size;+ FT_ULong code_page;+ FT_ULong reserved;++ } WinPE_RsrcDataEntryRec;+++ typedef struct WinNameInfoRec_+ {+ FT_UShort offset;+ FT_UShort length;+ FT_UShort flags;+ FT_UShort id;+ FT_UShort handle;+ FT_UShort usage;++ } WinNameInfoRec;+++ typedef struct WinResourceInfoRec_+ {+ FT_UShort type_id;+ FT_UShort count;++ } WinResourceInfoRec;+++#define WINFNT_MZ_MAGIC 0x5A4D+#define WINFNT_NE_MAGIC 0x454E+#define WINFNT_PE_MAGIC 0x4550+++ typedef struct FNT_FontRec_+ {+ FT_ULong offset;++ FT_WinFNT_HeaderRec header;++ FT_Byte* fnt_frame;+ FT_ULong fnt_size;+ FT_String* family_name;++ } FNT_FontRec, *FNT_Font;+++ typedef struct FNT_FaceRec_+ {+ FT_FaceRec root;+ FNT_Font font;++ FT_CharMap charmap_handle;+ FT_CharMapRec charmap; /* a single charmap per face */++ } FNT_FaceRec, *FNT_Face;+++ FT_EXPORT_VAR( const FT_Driver_ClassRec ) winfnt_driver_class;+++FT_END_HEADER+++#endif /* __WINFNT_H__ */+++/* END */