summaryrefslogtreecommitdiff
path: root/thirdparty
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty')
-rw-r--r--thirdparty/README.md14
-rw-r--r--thirdparty/freetype/FTL.TXT2
-rw-r--r--thirdparty/freetype/include/freetype/config/ftconfig.h108
-rw-r--r--thirdparty/freetype/include/freetype/config/ftheader.h128
-rw-r--r--thirdparty/freetype/include/freetype/config/ftoption.h93
-rw-r--r--thirdparty/freetype/include/freetype/config/ftstdlib.h2
-rw-r--r--thirdparty/freetype/include/freetype/freetype.h270
-rw-r--r--thirdparty/freetype/include/freetype/ftadvanc.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftbbox.h4
-rw-r--r--thirdparty/freetype/include/freetype/ftbdf.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftbitmap.h4
-rw-r--r--thirdparty/freetype/include/freetype/ftbzip2.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftcache.h17
-rw-r--r--thirdparty/freetype/include/freetype/ftchapters.h3
-rw-r--r--thirdparty/freetype/include/freetype/ftcid.h4
-rw-r--r--thirdparty/freetype/include/freetype/ftdriver.h1225
-rw-r--r--thirdparty/freetype/include/freetype/fterrdef.h2
-rw-r--r--thirdparty/freetype/include/freetype/fterrors.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftfntfmt.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftgasp.h7
-rw-r--r--thirdparty/freetype/include/freetype/ftglyph.h6
-rw-r--r--thirdparty/freetype/include/freetype/ftgxval.h10
-rw-r--r--thirdparty/freetype/include/freetype/ftgzip.h5
-rw-r--r--thirdparty/freetype/include/freetype/ftimage.h36
-rw-r--r--thirdparty/freetype/include/freetype/ftincrem.h15
-rw-r--r--thirdparty/freetype/include/freetype/ftlcdfil.h23
-rw-r--r--thirdparty/freetype/include/freetype/ftlist.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftlzw.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftmac.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftmm.h110
-rw-r--r--thirdparty/freetype/include/freetype/ftmodapi.h23
-rw-r--r--thirdparty/freetype/include/freetype/ftmoderr.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftotval.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftoutln.h11
-rw-r--r--thirdparty/freetype/include/freetype/ftparams.h205
-rw-r--r--thirdparty/freetype/include/freetype/ftpfr.h8
-rw-r--r--thirdparty/freetype/include/freetype/ftrender.h4
-rw-r--r--thirdparty/freetype/include/freetype/ftsizes.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftsnames.h50
-rw-r--r--thirdparty/freetype/include/freetype/ftstroke.h12
-rw-r--r--thirdparty/freetype/include/freetype/ftsynth.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftsystem.h2
-rw-r--r--thirdparty/freetype/include/freetype/fttrigon.h2
-rw-r--r--thirdparty/freetype/include/freetype/fttypes.h4
-rw-r--r--thirdparty/freetype/include/freetype/ftwinfnt.h4
-rw-r--r--thirdparty/freetype/include/freetype/internal/autohint.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/cffotypes.h108
-rw-r--r--thirdparty/freetype/include/freetype/internal/cfftypes.h412
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftcalc.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftdebug.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftdrv.h400
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftgloadr.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftmemory.h4
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftobjs.h85
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftpic.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftpsprop.h48
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftrfork.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftserv.h103
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftstream.h6
-rw-r--r--thirdparty/freetype/include/freetype/internal/fttrace.h9
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftvalid.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/internal.h8
-rw-r--r--thirdparty/freetype/include/freetype/internal/psaux.h501
-rw-r--r--thirdparty/freetype/include/freetype/internal/pshints.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svbdf.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svcfftl.h112
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svcid.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svfntfmt.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svgldict.h6
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svgxval.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svkern.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svmetric.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svmm.h57
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svotval.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svpfr.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svpostnm.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svprop.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svpscmap.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svpsinfo.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svsfnt.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svttcmap.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svtteng.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svttglyf.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svwinfnt.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/sfnt.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/t1types.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/tttypes.h12
-rw-r--r--thirdparty/freetype/include/freetype/t1tables.h11
-rw-r--r--thirdparty/freetype/include/freetype/ttnameid.h4
-rw-r--r--thirdparty/freetype/include/freetype/tttables.h2
-rw-r--r--thirdparty/freetype/include/freetype/tttags.h2
-rw-r--r--thirdparty/freetype/include/ft2build.h2
-rw-r--r--thirdparty/freetype/src/autofit/afangles.c2
-rw-r--r--thirdparty/freetype/src/autofit/afblue.c8
-rw-r--r--thirdparty/freetype/src/autofit/afblue.cin2
-rw-r--r--thirdparty/freetype/src/autofit/afblue.dat10
-rw-r--r--thirdparty/freetype/src/autofit/afblue.h300
-rw-r--r--thirdparty/freetype/src/autofit/afblue.hin2
-rw-r--r--thirdparty/freetype/src/autofit/afcjk.c6
-rw-r--r--thirdparty/freetype/src/autofit/afcjk.h2
-rw-r--r--thirdparty/freetype/src/autofit/afcover.h2
-rw-r--r--thirdparty/freetype/src/autofit/afdummy.c2
-rw-r--r--thirdparty/freetype/src/autofit/afdummy.h2
-rw-r--r--thirdparty/freetype/src/autofit/aferrors.h2
-rw-r--r--thirdparty/freetype/src/autofit/afglobal.c2
-rw-r--r--thirdparty/freetype/src/autofit/afglobal.h2
-rw-r--r--thirdparty/freetype/src/autofit/afhints.c15
-rw-r--r--thirdparty/freetype/src/autofit/afhints.h4
-rw-r--r--thirdparty/freetype/src/autofit/afindic.c2
-rw-r--r--thirdparty/freetype/src/autofit/afindic.h2
-rw-r--r--thirdparty/freetype/src/autofit/aflatin.c2
-rw-r--r--thirdparty/freetype/src/autofit/aflatin.h2
-rw-r--r--thirdparty/freetype/src/autofit/aflatin2.c2
-rw-r--r--thirdparty/freetype/src/autofit/aflatin2.h2
-rw-r--r--thirdparty/freetype/src/autofit/afloader.c2
-rw-r--r--thirdparty/freetype/src/autofit/afloader.h2
-rw-r--r--thirdparty/freetype/src/autofit/afmodule.c4
-rw-r--r--thirdparty/freetype/src/autofit/afmodule.h2
-rw-r--r--thirdparty/freetype/src/autofit/afpic.c2
-rw-r--r--thirdparty/freetype/src/autofit/afpic.h2
-rw-r--r--thirdparty/freetype/src/autofit/afranges.c27
-rw-r--r--thirdparty/freetype/src/autofit/afranges.h2
-rw-r--r--thirdparty/freetype/src/autofit/afscript.h4
-rw-r--r--thirdparty/freetype/src/autofit/afshaper.c33
-rw-r--r--thirdparty/freetype/src/autofit/afshaper.h2
-rw-r--r--thirdparty/freetype/src/autofit/afstyles.h2
-rw-r--r--thirdparty/freetype/src/autofit/aftypes.h8
-rw-r--r--thirdparty/freetype/src/autofit/afwarp.c2
-rw-r--r--thirdparty/freetype/src/autofit/afwarp.h2
-rw-r--r--thirdparty/freetype/src/autofit/afwrtsys.h2
-rw-r--r--thirdparty/freetype/src/autofit/autofit.c2
-rw-r--r--thirdparty/freetype/src/autofit/module.mk2
-rw-r--r--thirdparty/freetype/src/autofit/rules.mk2
-rw-r--r--thirdparty/freetype/src/base/basepic.c2
-rw-r--r--thirdparty/freetype/src/base/basepic.h2
-rw-r--r--thirdparty/freetype/src/base/ftadvanc.c16
-rw-r--r--thirdparty/freetype/src/base/ftapi.c2
-rw-r--r--thirdparty/freetype/src/base/ftbase.c5
-rw-r--r--thirdparty/freetype/src/base/ftbase.h8
-rw-r--r--thirdparty/freetype/src/base/ftbbox.c2
-rw-r--r--thirdparty/freetype/src/base/ftbdf.c2
-rw-r--r--thirdparty/freetype/src/base/ftbitmap.c77
-rw-r--r--thirdparty/freetype/src/base/ftcalc.c2
-rw-r--r--thirdparty/freetype/src/base/ftcid.c2
-rw-r--r--thirdparty/freetype/src/base/ftdbgmem.c10
-rw-r--r--thirdparty/freetype/src/base/ftdebug.c4
-rw-r--r--thirdparty/freetype/src/base/ftfntfmt.c2
-rw-r--r--thirdparty/freetype/src/base/ftfstype.c2
-rw-r--r--thirdparty/freetype/src/base/ftgasp.c2
-rw-r--r--thirdparty/freetype/src/base/ftgloadr.c2
-rw-r--r--thirdparty/freetype/src/base/ftglyph.c2
-rw-r--r--thirdparty/freetype/src/base/ftgxval.c2
-rw-r--r--thirdparty/freetype/src/base/ftinit.c2
-rw-r--r--thirdparty/freetype/src/base/ftlcdfil.c59
-rw-r--r--thirdparty/freetype/src/base/ftmac.c2
-rw-r--r--thirdparty/freetype/src/base/ftmm.c81
-rw-r--r--thirdparty/freetype/src/base/ftobjs.c470
-rw-r--r--thirdparty/freetype/src/base/ftotval.c2
-rw-r--r--thirdparty/freetype/src/base/ftoutln.c13
-rw-r--r--thirdparty/freetype/src/base/ftpatent.c2
-rw-r--r--thirdparty/freetype/src/base/ftpfr.c2
-rw-r--r--thirdparty/freetype/src/base/ftpic.c2
-rw-r--r--thirdparty/freetype/src/base/ftpsprop.c285
-rw-r--r--thirdparty/freetype/src/base/ftrfork.c4
-rw-r--r--thirdparty/freetype/src/base/ftsnames.c2
-rw-r--r--thirdparty/freetype/src/base/ftstream.c2
-rw-r--r--thirdparty/freetype/src/base/ftstroke.c2
-rw-r--r--thirdparty/freetype/src/base/ftsynth.c2
-rw-r--r--thirdparty/freetype/src/base/ftsystem.c2
-rw-r--r--thirdparty/freetype/src/base/fttrigon.c2
-rw-r--r--thirdparty/freetype/src/base/fttype1.c2
-rw-r--r--thirdparty/freetype/src/base/ftutil.c2
-rw-r--r--thirdparty/freetype/src/base/ftver.rc61
-rw-r--r--thirdparty/freetype/src/base/ftwinfnt.c2
-rw-r--r--thirdparty/freetype/src/base/rules.mk5
-rw-r--r--thirdparty/freetype/src/bdf/README2
-rw-r--r--thirdparty/freetype/src/bdf/bdfdrivr.c2
-rw-r--r--thirdparty/freetype/src/bdf/bdflib.c12
-rw-r--r--thirdparty/freetype/src/bzip2/ftbzip2.c2
-rw-r--r--thirdparty/freetype/src/bzip2/rules.mk2
-rw-r--r--thirdparty/freetype/src/cache/ftcache.c2
-rw-r--r--thirdparty/freetype/src/cache/ftcbasic.c2
-rw-r--r--thirdparty/freetype/src/cache/ftccache.c2
-rw-r--r--thirdparty/freetype/src/cache/ftccache.h2
-rw-r--r--thirdparty/freetype/src/cache/ftccback.h2
-rw-r--r--thirdparty/freetype/src/cache/ftccmap.c2
-rw-r--r--thirdparty/freetype/src/cache/ftcerror.h2
-rw-r--r--thirdparty/freetype/src/cache/ftcglyph.c2
-rw-r--r--thirdparty/freetype/src/cache/ftcglyph.h2
-rw-r--r--thirdparty/freetype/src/cache/ftcimage.c2
-rw-r--r--thirdparty/freetype/src/cache/ftcimage.h2
-rw-r--r--thirdparty/freetype/src/cache/ftcmanag.c2
-rw-r--r--thirdparty/freetype/src/cache/ftcmanag.h2
-rw-r--r--thirdparty/freetype/src/cache/ftcmru.c2
-rw-r--r--thirdparty/freetype/src/cache/ftcmru.h2
-rw-r--r--thirdparty/freetype/src/cache/ftcsbits.c2
-rw-r--r--thirdparty/freetype/src/cache/ftcsbits.h2
-rw-r--r--thirdparty/freetype/src/cache/rules.mk2
-rw-r--r--thirdparty/freetype/src/cff/cff.c13
-rw-r--r--thirdparty/freetype/src/cff/cffcmap.c2
-rw-r--r--thirdparty/freetype/src/cff/cffcmap.h4
-rw-r--r--thirdparty/freetype/src/cff/cffdrivr.c381
-rw-r--r--thirdparty/freetype/src/cff/cffdrivr.h2
-rw-r--r--thirdparty/freetype/src/cff/cfferrs.h2
-rw-r--r--thirdparty/freetype/src/cff/cffgload.c2623
-rw-r--r--thirdparty/freetype/src/cff/cffgload.h187
-rw-r--r--thirdparty/freetype/src/cff/cffload.c84
-rw-r--r--thirdparty/freetype/src/cff/cffload.h9
-rw-r--r--thirdparty/freetype/src/cff/cffobjs.c120
-rw-r--r--thirdparty/freetype/src/cff/cffobjs.h106
-rw-r--r--thirdparty/freetype/src/cff/cffparse.c27
-rw-r--r--thirdparty/freetype/src/cff/cffparse.h4
-rw-r--r--thirdparty/freetype/src/cff/cffpic.c2
-rw-r--r--thirdparty/freetype/src/cff/cffpic.h7
-rw-r--r--thirdparty/freetype/src/cff/cfftoken.h2
-rw-r--r--thirdparty/freetype/src/cff/module.mk2
-rw-r--r--thirdparty/freetype/src/cff/rules.mk19
-rw-r--r--thirdparty/freetype/src/cid/ciderrs.h2
-rw-r--r--thirdparty/freetype/src/cid/cidgload.c87
-rw-r--r--thirdparty/freetype/src/cid/cidgload.h2
-rw-r--r--thirdparty/freetype/src/cid/cidload.c2
-rw-r--r--thirdparty/freetype/src/cid/cidload.h2
-rw-r--r--thirdparty/freetype/src/cid/cidobjs.c40
-rw-r--r--thirdparty/freetype/src/cid/cidobjs.h2
-rw-r--r--thirdparty/freetype/src/cid/cidparse.c2
-rw-r--r--thirdparty/freetype/src/cid/cidparse.h2
-rw-r--r--thirdparty/freetype/src/cid/cidriver.c22
-rw-r--r--thirdparty/freetype/src/cid/cidriver.h2
-rw-r--r--thirdparty/freetype/src/cid/cidtoken.h2
-rw-r--r--thirdparty/freetype/src/cid/module.mk2
-rw-r--r--thirdparty/freetype/src/cid/rules.mk2
-rw-r--r--thirdparty/freetype/src/cid/type1cid.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/README12
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvalid.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvalid.h2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvbsln.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvcommn.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvcommn.h2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxverror.h2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvfeat.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvfeat.h2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvfgen.c4
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvjust.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvkern.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvlcar.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmod.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmod.h2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmort.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmort.h2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmort0.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmort1.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmort2.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmort4.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmort5.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmorx.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmorx.h2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmorx0.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmorx1.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmorx2.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmorx4.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmorx5.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvopbd.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvprop.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvtrak.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/module.mk2
-rw-r--r--thirdparty/freetype/src/gxvalid/rules.mk2
-rw-r--r--thirdparty/freetype/src/gzip/ftgzip.c2
-rw-r--r--thirdparty/freetype/src/gzip/rules.mk2
-rw-r--r--thirdparty/freetype/src/lzw/ftlzw.c2
-rw-r--r--thirdparty/freetype/src/lzw/ftzopen.c2
-rw-r--r--thirdparty/freetype/src/lzw/ftzopen.h2
-rw-r--r--thirdparty/freetype/src/lzw/rules.mk2
-rw-r--r--thirdparty/freetype/src/otvalid/module.mk2
-rw-r--r--thirdparty/freetype/src/otvalid/otvalid.c2
-rw-r--r--thirdparty/freetype/src/otvalid/otvalid.h2
-rw-r--r--thirdparty/freetype/src/otvalid/otvbase.c35
-rw-r--r--thirdparty/freetype/src/otvalid/otvcommn.c30
-rw-r--r--thirdparty/freetype/src/otvalid/otvcommn.h54
-rw-r--r--thirdparty/freetype/src/otvalid/otverror.h2
-rw-r--r--thirdparty/freetype/src/otvalid/otvgdef.c113
-rw-r--r--thirdparty/freetype/src/otvalid/otvgpos.c56
-rw-r--r--thirdparty/freetype/src/otvalid/otvgpos.h2
-rw-r--r--thirdparty/freetype/src/otvalid/otvgsub.c36
-rw-r--r--thirdparty/freetype/src/otvalid/otvjstf.c2
-rw-r--r--thirdparty/freetype/src/otvalid/otvmath.c2
-rw-r--r--thirdparty/freetype/src/otvalid/otvmod.c2
-rw-r--r--thirdparty/freetype/src/otvalid/otvmod.h2
-rw-r--r--thirdparty/freetype/src/otvalid/rules.mk2
-rw-r--r--thirdparty/freetype/src/pcf/pcfdrivr.c2
-rw-r--r--thirdparty/freetype/src/pcf/pcfread.c6
-rw-r--r--thirdparty/freetype/src/pfr/module.mk2
-rw-r--r--thirdparty/freetype/src/pfr/pfr.c2
-rw-r--r--thirdparty/freetype/src/pfr/pfrcmap.c2
-rw-r--r--thirdparty/freetype/src/pfr/pfrcmap.h2
-rw-r--r--thirdparty/freetype/src/pfr/pfrdrivr.c2
-rw-r--r--thirdparty/freetype/src/pfr/pfrdrivr.h2
-rw-r--r--thirdparty/freetype/src/pfr/pfrerror.h2
-rw-r--r--thirdparty/freetype/src/pfr/pfrgload.c12
-rw-r--r--thirdparty/freetype/src/pfr/pfrgload.h2
-rw-r--r--thirdparty/freetype/src/pfr/pfrload.c2
-rw-r--r--thirdparty/freetype/src/pfr/pfrload.h2
-rw-r--r--thirdparty/freetype/src/pfr/pfrobjs.c2
-rw-r--r--thirdparty/freetype/src/pfr/pfrobjs.h2
-rw-r--r--thirdparty/freetype/src/pfr/pfrsbit.c2
-rw-r--r--thirdparty/freetype/src/pfr/pfrsbit.h2
-rw-r--r--thirdparty/freetype/src/pfr/pfrtypes.h2
-rw-r--r--thirdparty/freetype/src/pfr/rules.mk2
-rw-r--r--thirdparty/freetype/src/psaux/afmparse.c2
-rw-r--r--thirdparty/freetype/src/psaux/afmparse.h2
-rw-r--r--thirdparty/freetype/src/psaux/cffdecode.c2370
-rw-r--r--thirdparty/freetype/src/psaux/cffdecode.h64
-rw-r--r--thirdparty/freetype/src/psaux/module.mk2
-rw-r--r--thirdparty/freetype/src/psaux/psarrst.c241
-rw-r--r--thirdparty/freetype/src/psaux/psarrst.h100
-rw-r--r--thirdparty/freetype/src/psaux/psaux.c13
-rw-r--r--thirdparty/freetype/src/psaux/psauxerr.h2
-rw-r--r--thirdparty/freetype/src/psaux/psauxmod.c56
-rw-r--r--thirdparty/freetype/src/psaux/psauxmod.h11
-rw-r--r--thirdparty/freetype/src/psaux/psblues.c582
-rw-r--r--thirdparty/freetype/src/psaux/psblues.h185
-rw-r--r--thirdparty/freetype/src/psaux/psconv.c2
-rw-r--r--thirdparty/freetype/src/psaux/psconv.h2
-rw-r--r--thirdparty/freetype/src/psaux/pserror.c52
-rw-r--r--thirdparty/freetype/src/psaux/pserror.h119
-rw-r--r--thirdparty/freetype/src/psaux/psfixed.h95
-rw-r--r--thirdparty/freetype/src/psaux/psfont.c567
-rw-r--r--thirdparty/freetype/src/psaux/psfont.h134
-rw-r--r--thirdparty/freetype/src/psaux/psft.c890
-rw-r--r--thirdparty/freetype/src/psaux/psft.h167
-rw-r--r--thirdparty/freetype/src/psaux/psglue.h144
-rw-r--r--thirdparty/freetype/src/psaux/pshints.c1939
-rw-r--r--thirdparty/freetype/src/psaux/pshints.h288
-rw-r--r--thirdparty/freetype/src/psaux/psintrp.c3040
-rw-r--r--thirdparty/freetype/src/psaux/psintrp.h83
-rw-r--r--thirdparty/freetype/src/psaux/psobjs.c753
-rw-r--r--thirdparty/freetype/src/psaux/psobjs.h103
-rw-r--r--thirdparty/freetype/src/psaux/psread.c112
-rw-r--r--thirdparty/freetype/src/psaux/psread.h68
-rw-r--r--thirdparty/freetype/src/psaux/psstack.c328
-rw-r--r--thirdparty/freetype/src/psaux/psstack.h121
-rw-r--r--thirdparty/freetype/src/psaux/pstypes.h78
-rw-r--r--thirdparty/freetype/src/psaux/rules.mk19
-rw-r--r--thirdparty/freetype/src/psaux/t1cmap.c2
-rw-r--r--thirdparty/freetype/src/psaux/t1cmap.h2
-rw-r--r--thirdparty/freetype/src/psaux/t1decode.c350
-rw-r--r--thirdparty/freetype/src/psaux/t1decode.h12
-rw-r--r--thirdparty/freetype/src/pshinter/module.mk2
-rw-r--r--thirdparty/freetype/src/pshinter/pshalgo.c4
-rw-r--r--thirdparty/freetype/src/pshinter/pshalgo.h2
-rw-r--r--thirdparty/freetype/src/pshinter/pshglob.c6
-rw-r--r--thirdparty/freetype/src/pshinter/pshglob.h2
-rw-r--r--thirdparty/freetype/src/pshinter/pshinter.c2
-rw-r--r--thirdparty/freetype/src/pshinter/pshmod.c2
-rw-r--r--thirdparty/freetype/src/pshinter/pshmod.h2
-rw-r--r--thirdparty/freetype/src/pshinter/pshnterr.h2
-rw-r--r--thirdparty/freetype/src/pshinter/pshpic.c2
-rw-r--r--thirdparty/freetype/src/pshinter/pshpic.h2
-rw-r--r--thirdparty/freetype/src/pshinter/pshrec.c2
-rw-r--r--thirdparty/freetype/src/pshinter/pshrec.h2
-rw-r--r--thirdparty/freetype/src/pshinter/rules.mk2
-rw-r--r--thirdparty/freetype/src/psnames/module.mk2
-rw-r--r--thirdparty/freetype/src/psnames/psmodule.c2
-rw-r--r--thirdparty/freetype/src/psnames/psmodule.h2
-rw-r--r--thirdparty/freetype/src/psnames/psnamerr.h2
-rw-r--r--thirdparty/freetype/src/psnames/psnames.c2
-rw-r--r--thirdparty/freetype/src/psnames/pspic.c2
-rw-r--r--thirdparty/freetype/src/psnames/pspic.h2
-rw-r--r--thirdparty/freetype/src/psnames/pstables.h2
-rw-r--r--thirdparty/freetype/src/psnames/rules.mk2
-rw-r--r--thirdparty/freetype/src/raster/ftmisc.h2
-rw-r--r--thirdparty/freetype/src/raster/ftraster.c2
-rw-r--r--thirdparty/freetype/src/raster/ftraster.h2
-rw-r--r--thirdparty/freetype/src/raster/ftrend1.c111
-rw-r--r--thirdparty/freetype/src/raster/ftrend1.h2
-rw-r--r--thirdparty/freetype/src/raster/module.mk2
-rw-r--r--thirdparty/freetype/src/raster/raster.c2
-rw-r--r--thirdparty/freetype/src/raster/rasterrs.h2
-rw-r--r--thirdparty/freetype/src/raster/rastpic.c2
-rw-r--r--thirdparty/freetype/src/raster/rastpic.h2
-rw-r--r--thirdparty/freetype/src/raster/rules.mk2
-rw-r--r--thirdparty/freetype/src/sfnt/module.mk2
-rw-r--r--thirdparty/freetype/src/sfnt/pngshim.c61
-rw-r--r--thirdparty/freetype/src/sfnt/pngshim.h2
-rw-r--r--thirdparty/freetype/src/sfnt/rules.mk2
-rw-r--r--thirdparty/freetype/src/sfnt/sfdriver.c9
-rw-r--r--thirdparty/freetype/src/sfnt/sfdriver.h2
-rw-r--r--thirdparty/freetype/src/sfnt/sferrors.h2
-rw-r--r--thirdparty/freetype/src/sfnt/sfnt.c2
-rw-r--r--thirdparty/freetype/src/sfnt/sfntpic.c2
-rw-r--r--thirdparty/freetype/src/sfnt/sfntpic.h2
-rw-r--r--thirdparty/freetype/src/sfnt/sfobjs.c19
-rw-r--r--thirdparty/freetype/src/sfnt/sfobjs.h2
-rw-r--r--thirdparty/freetype/src/sfnt/ttbdf.c2
-rw-r--r--thirdparty/freetype/src/sfnt/ttbdf.h6
-rw-r--r--thirdparty/freetype/src/sfnt/ttcmap.c47
-rw-r--r--thirdparty/freetype/src/sfnt/ttcmap.h2
-rw-r--r--thirdparty/freetype/src/sfnt/ttcmapc.h2
-rw-r--r--thirdparty/freetype/src/sfnt/ttkern.c2
-rw-r--r--thirdparty/freetype/src/sfnt/ttkern.h2
-rw-r--r--thirdparty/freetype/src/sfnt/ttload.c4
-rw-r--r--thirdparty/freetype/src/sfnt/ttload.h2
-rw-r--r--thirdparty/freetype/src/sfnt/ttmtx.c2
-rw-r--r--thirdparty/freetype/src/sfnt/ttmtx.h2
-rw-r--r--thirdparty/freetype/src/sfnt/ttpost.c6
-rw-r--r--thirdparty/freetype/src/sfnt/ttpost.h2
-rw-r--r--thirdparty/freetype/src/sfnt/ttsbit.c9
-rw-r--r--thirdparty/freetype/src/sfnt/ttsbit.h2
-rw-r--r--thirdparty/freetype/src/smooth/ftgrays.c85
-rw-r--r--thirdparty/freetype/src/smooth/ftgrays.h2
-rw-r--r--thirdparty/freetype/src/smooth/ftsmerrs.h2
-rw-r--r--thirdparty/freetype/src/smooth/ftsmooth.c287
-rw-r--r--thirdparty/freetype/src/smooth/ftsmooth.h2
-rw-r--r--thirdparty/freetype/src/smooth/ftspic.c2
-rw-r--r--thirdparty/freetype/src/smooth/ftspic.h2
-rw-r--r--thirdparty/freetype/src/smooth/module.mk2
-rw-r--r--thirdparty/freetype/src/smooth/rules.mk2
-rw-r--r--thirdparty/freetype/src/smooth/smooth.c2
-rw-r--r--thirdparty/freetype/src/truetype/module.mk2
-rw-r--r--thirdparty/freetype/src/truetype/rules.mk2
-rw-r--r--thirdparty/freetype/src/truetype/truetype.c2
-rw-r--r--thirdparty/freetype/src/truetype/ttdriver.c13
-rw-r--r--thirdparty/freetype/src/truetype/ttdriver.h2
-rw-r--r--thirdparty/freetype/src/truetype/tterrors.h2
-rw-r--r--thirdparty/freetype/src/truetype/ttgload.c139
-rw-r--r--thirdparty/freetype/src/truetype/ttgload.h2
-rw-r--r--thirdparty/freetype/src/truetype/ttgxvar.c646
-rw-r--r--thirdparty/freetype/src/truetype/ttgxvar.h10
-rw-r--r--thirdparty/freetype/src/truetype/ttinterp.c115
-rw-r--r--thirdparty/freetype/src/truetype/ttinterp.h2
-rw-r--r--thirdparty/freetype/src/truetype/ttobjs.c101
-rw-r--r--thirdparty/freetype/src/truetype/ttobjs.h2
-rw-r--r--thirdparty/freetype/src/truetype/ttpic.c2
-rw-r--r--thirdparty/freetype/src/truetype/ttpic.h2
-rw-r--r--thirdparty/freetype/src/truetype/ttpload.c2
-rw-r--r--thirdparty/freetype/src/truetype/ttpload.h2
-rw-r--r--thirdparty/freetype/src/truetype/ttsubpix.c28
-rw-r--r--thirdparty/freetype/src/truetype/ttsubpix.h2
-rw-r--r--thirdparty/freetype/src/type1/module.mk2
-rw-r--r--thirdparty/freetype/src/type1/rules.mk2
-rw-r--r--thirdparty/freetype/src/type1/t1afm.c2
-rw-r--r--thirdparty/freetype/src/type1/t1afm.h2
-rw-r--r--thirdparty/freetype/src/type1/t1driver.c21
-rw-r--r--thirdparty/freetype/src/type1/t1driver.h2
-rw-r--r--thirdparty/freetype/src/type1/t1errors.h2
-rw-r--r--thirdparty/freetype/src/type1/t1gload.c118
-rw-r--r--thirdparty/freetype/src/type1/t1gload.h2
-rw-r--r--thirdparty/freetype/src/type1/t1load.c113
-rw-r--r--thirdparty/freetype/src/type1/t1load.h6
-rw-r--r--thirdparty/freetype/src/type1/t1objs.c42
-rw-r--r--thirdparty/freetype/src/type1/t1objs.h8
-rw-r--r--thirdparty/freetype/src/type1/t1parse.c2
-rw-r--r--thirdparty/freetype/src/type1/t1parse.h2
-rw-r--r--thirdparty/freetype/src/type1/t1tokens.h2
-rw-r--r--thirdparty/freetype/src/type1/type1.c2
-rw-r--r--thirdparty/freetype/src/type42/module.mk2
-rw-r--r--thirdparty/freetype/src/type42/rules.mk2
-rw-r--r--thirdparty/freetype/src/type42/t42drivr.c2
-rw-r--r--thirdparty/freetype/src/type42/t42drivr.h2
-rw-r--r--thirdparty/freetype/src/type42/t42error.h2
-rw-r--r--thirdparty/freetype/src/type42/t42objs.c2
-rw-r--r--thirdparty/freetype/src/type42/t42objs.h2
-rw-r--r--thirdparty/freetype/src/type42/t42parse.c2
-rw-r--r--thirdparty/freetype/src/type42/t42parse.h2
-rw-r--r--thirdparty/freetype/src/type42/t42types.h2
-rw-r--r--thirdparty/freetype/src/type42/type42.c2
-rw-r--r--thirdparty/freetype/src/winfonts/fnterrs.h2
-rw-r--r--thirdparty/freetype/src/winfonts/module.mk2
-rw-r--r--thirdparty/freetype/src/winfonts/rules.mk2
-rw-r--r--thirdparty/freetype/src/winfonts/winfnt.c2
-rw-r--r--thirdparty/freetype/src/winfonts/winfnt.h2
-rw-r--r--thirdparty/libvorbis/COPYING2
-rw-r--r--thirdparty/libvorbis/analysis.c1
-rw-r--r--thirdparty/libvorbis/backends.h1
-rw-r--r--thirdparty/libvorbis/barkmel.c1
-rw-r--r--thirdparty/libvorbis/bitrate.c1
-rw-r--r--thirdparty/libvorbis/bitrate.h1
-rw-r--r--thirdparty/libvorbis/block.c1
-rw-r--r--thirdparty/libvorbis/books/coupled/res_books_51.h1
-rw-r--r--thirdparty/libvorbis/books/coupled/res_books_stereo.h1
-rw-r--r--thirdparty/libvorbis/books/floor/floor_books.h1
-rw-r--r--thirdparty/libvorbis/books/uncoupled/res_books_uncoupled.h1
-rw-r--r--thirdparty/libvorbis/codebook.c49
-rw-r--r--thirdparty/libvorbis/codebook.h1
-rw-r--r--thirdparty/libvorbis/codec_internal.h1
-rw-r--r--thirdparty/libvorbis/envelope.c1
-rw-r--r--thirdparty/libvorbis/envelope.h1
-rw-r--r--thirdparty/libvorbis/floor0.c1
-rw-r--r--thirdparty/libvorbis/floor1.c1
-rw-r--r--thirdparty/libvorbis/highlevel.h1
-rw-r--r--thirdparty/libvorbis/info.c34
-rw-r--r--thirdparty/libvorbis/lookup.c1
-rw-r--r--thirdparty/libvorbis/lookup.h1
-rw-r--r--thirdparty/libvorbis/lookup_data.h1
-rw-r--r--thirdparty/libvorbis/lpc.c1
-rw-r--r--thirdparty/libvorbis/lpc.h1
-rw-r--r--thirdparty/libvorbis/lsp.c1
-rw-r--r--thirdparty/libvorbis/lsp.h1
-rw-r--r--thirdparty/libvorbis/mapping0.c2
-rw-r--r--thirdparty/libvorbis/masking.h1
-rw-r--r--thirdparty/libvorbis/mdct.c1
-rw-r--r--thirdparty/libvorbis/mdct.h1
-rw-r--r--thirdparty/libvorbis/misc.h1
-rw-r--r--thirdparty/libvorbis/modes/floor_all.h1
-rw-r--r--thirdparty/libvorbis/modes/psych_11.h1
-rw-r--r--thirdparty/libvorbis/modes/psych_16.h1
-rw-r--r--thirdparty/libvorbis/modes/psych_44.h1
-rw-r--r--thirdparty/libvorbis/modes/psych_8.h1
-rw-r--r--thirdparty/libvorbis/modes/residue_16.h1
-rw-r--r--thirdparty/libvorbis/modes/residue_44.h1
-rw-r--r--thirdparty/libvorbis/modes/residue_44p51.h1
-rw-r--r--thirdparty/libvorbis/modes/residue_44u.h1
-rw-r--r--thirdparty/libvorbis/modes/residue_8.h1
-rw-r--r--thirdparty/libvorbis/modes/setup_11.h1
-rw-r--r--thirdparty/libvorbis/modes/setup_16.h1
-rw-r--r--thirdparty/libvorbis/modes/setup_22.h1
-rw-r--r--thirdparty/libvorbis/modes/setup_32.h1
-rw-r--r--thirdparty/libvorbis/modes/setup_44.h1
-rw-r--r--thirdparty/libvorbis/modes/setup_44p51.h1
-rw-r--r--thirdparty/libvorbis/modes/setup_44u.h1
-rw-r--r--thirdparty/libvorbis/modes/setup_8.h1
-rw-r--r--thirdparty/libvorbis/modes/setup_X.h1
-rw-r--r--thirdparty/libvorbis/os.h3
-rw-r--r--thirdparty/libvorbis/psy.c1
-rw-r--r--thirdparty/libvorbis/psy.h1
-rw-r--r--thirdparty/libvorbis/psytune.c65
-rw-r--r--thirdparty/libvorbis/registry.c1
-rw-r--r--thirdparty/libvorbis/registry.h1
-rw-r--r--thirdparty/libvorbis/res0.c1
-rw-r--r--thirdparty/libvorbis/scales.h1
-rw-r--r--thirdparty/libvorbis/sharedbook.c19
-rw-r--r--thirdparty/libvorbis/smallft.c1
-rw-r--r--thirdparty/libvorbis/smallft.h1
-rw-r--r--thirdparty/libvorbis/synthesis.c3
-rw-r--r--thirdparty/libvorbis/tone.c4
-rw-r--r--thirdparty/libvorbis/vorbis/codec.h1
-rw-r--r--thirdparty/libvorbis/vorbis/vorbisenc.h1
-rw-r--r--thirdparty/libvorbis/vorbis/vorbisfile.h1
-rw-r--r--thirdparty/libvorbis/vorbisenc.c1
-rw-r--r--thirdparty/libvorbis/vorbisfile.c1
-rw-r--r--thirdparty/libvorbis/window.c1
-rw-r--r--thirdparty/libvorbis/window.h1
-rw-r--r--thirdparty/libwebp/AUTHORS15
-rw-r--r--thirdparty/libwebp/src/dec/frame_dec.c12
-rw-r--r--thirdparty/libwebp/src/dec/vp8_dec.c2
-rw-r--r--thirdparty/libwebp/src/dec/vp8i_dec.h6
-rw-r--r--thirdparty/libwebp/src/dec/vp8l_dec.c10
-rw-r--r--thirdparty/libwebp/src/demux/demux.c6
-rw-r--r--thirdparty/libwebp/src/dsp/alpha_processing.c29
-rw-r--r--thirdparty/libwebp/src/dsp/alpha_processing_mips_dsp_r2.c46
-rw-r--r--thirdparty/libwebp/src/dsp/common_sse2.h14
-rw-r--r--thirdparty/libwebp/src/dsp/common_sse41.h132
-rw-r--r--thirdparty/libwebp/src/dsp/cost.c9
-rw-r--r--thirdparty/libwebp/src/dsp/dec.c9
-rw-r--r--thirdparty/libwebp/src/dsp/dsp.h52
-rw-r--r--thirdparty/libwebp/src/dsp/enc.c9
-rw-r--r--thirdparty/libwebp/src/dsp/filters.c9
-rw-r--r--thirdparty/libwebp/src/dsp/lossless.c9
-rw-r--r--thirdparty/libwebp/src/dsp/lossless.h4
-rw-r--r--thirdparty/libwebp/src/dsp/lossless_enc.c9
-rw-r--r--thirdparty/libwebp/src/dsp/lossless_enc_sse2.c27
-rw-r--r--thirdparty/libwebp/src/dsp/lossless_enc_sse41.c94
-rw-r--r--thirdparty/libwebp/src/dsp/lossless_sse2.c19
-rw-r--r--thirdparty/libwebp/src/dsp/rescaler.c7
-rw-r--r--thirdparty/libwebp/src/dsp/rescaler_sse2.c20
-rw-r--r--thirdparty/libwebp/src/dsp/ssim.c9
-rw-r--r--thirdparty/libwebp/src/dsp/upsampling.c30
-rw-r--r--thirdparty/libwebp/src/dsp/upsampling_msa.c6
-rw-r--r--thirdparty/libwebp/src/dsp/upsampling_sse2.c32
-rw-r--r--thirdparty/libwebp/src/dsp/upsampling_sse41.c239
-rw-r--r--thirdparty/libwebp/src/dsp/yuv.c29
-rw-r--r--thirdparty/libwebp/src/dsp/yuv.h13
-rw-r--r--thirdparty/libwebp/src/dsp/yuv_sse2.c4
-rw-r--r--thirdparty/libwebp/src/dsp/yuv_sse41.c613
-rw-r--r--thirdparty/libwebp/src/enc/alpha_enc.c5
-rw-r--r--thirdparty/libwebp/src/enc/analysis_enc.c6
-rw-r--r--thirdparty/libwebp/src/enc/frame_enc.c26
-rw-r--r--thirdparty/libwebp/src/enc/histogram_enc.c11
-rw-r--r--thirdparty/libwebp/src/enc/histogram_enc.h5
-rw-r--r--thirdparty/libwebp/src/enc/iterator_enc.c8
-rw-r--r--thirdparty/libwebp/src/enc/near_lossless_enc.c2
-rw-r--r--thirdparty/libwebp/src/enc/picture_csp_enc.c148
-rw-r--r--thirdparty/libwebp/src/enc/picture_psnr_enc.c15
-rw-r--r--thirdparty/libwebp/src/enc/quant_enc.c87
-rw-r--r--thirdparty/libwebp/src/enc/vp8i_enc.h16
-rw-r--r--thirdparty/libwebp/src/enc/vp8l_enc.c79
-rw-r--r--thirdparty/libwebp/src/enc/webp_enc.c9
-rw-r--r--thirdparty/libwebp/src/mux/muxi.h6
-rw-r--r--thirdparty/libwebp/src/utils/endian_inl_utils.h7
-rw-r--r--thirdparty/minizip/crypt.h8
-rw-r--r--thirdparty/minizip/godot-zlib-1.2.4-minizip-seek.patch6
-rw-r--r--thirdparty/minizip/ioapi.c22
-rw-r--r--thirdparty/minizip/ioapi.h10
-rw-r--r--thirdparty/minizip/unzip.c26
-rw-r--r--thirdparty/minizip/unzip.h4
-rw-r--r--thirdparty/minizip/zip.c35
-rw-r--r--thirdparty/misc/stb_truetype.h487
-rw-r--r--thirdparty/misc/stb_vorbis.c293
-rw-r--r--thirdparty/zstd/common/bitstream.h2
-rw-r--r--thirdparty/zstd/common/compiler.h25
-rw-r--r--thirdparty/zstd/common/cpu.h216
-rw-r--r--thirdparty/zstd/common/error_private.c1
-rw-r--r--thirdparty/zstd/common/fse.h2
-rw-r--r--thirdparty/zstd/common/fse_decompress.c4
-rw-r--r--thirdparty/zstd/common/huf.h203
-rw-r--r--thirdparty/zstd/common/pool.c63
-rw-r--r--thirdparty/zstd/common/pool.h27
-rw-r--r--thirdparty/zstd/common/threading.h24
-rw-r--r--thirdparty/zstd/common/zstd_errors.h23
-rw-r--r--thirdparty/zstd/common/zstd_internal.h9
-rw-r--r--thirdparty/zstd/compress/fse_compress.c30
-rw-r--r--thirdparty/zstd/compress/huf_compress.c222
-rw-r--r--thirdparty/zstd/compress/zstd_compress.c1617
-rw-r--r--thirdparty/zstd/compress/zstd_compress_internal.h315
-rw-r--r--thirdparty/zstd/compress/zstd_double_fast.c142
-rw-r--r--thirdparty/zstd/compress/zstd_double_fast.h15
-rw-r--r--thirdparty/zstd/compress/zstd_fast.c158
-rw-r--r--thirdparty/zstd/compress/zstd_fast.h16
-rw-r--r--thirdparty/zstd/compress/zstd_lazy.c607
-rw-r--r--thirdparty/zstd/compress/zstd_lazy.h49
-rw-r--r--thirdparty/zstd/compress/zstd_ldm.c664
-rw-r--r--thirdparty/zstd/compress/zstd_ldm.h85
-rw-r--r--thirdparty/zstd/compress/zstd_opt.c250
-rw-r--r--thirdparty/zstd/compress/zstd_opt.h22
-rw-r--r--thirdparty/zstd/compress/zstdmt_compress.c1580
-rw-r--r--thirdparty/zstd/compress/zstdmt_compress.h48
-rw-r--r--thirdparty/zstd/decompress/huf_decompress.c680
-rw-r--r--thirdparty/zstd/decompress/zstd_decompress.c1216
-rw-r--r--thirdparty/zstd/zstd.h508
628 files changed, 28182 insertions, 9368 deletions
diff --git a/thirdparty/README.md b/thirdparty/README.md
index 06084641cc..25d6e3df9a 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -102,7 +102,7 @@ Use UI font variant if available, because it has tight vertical metrics and good
## freetype
- Upstream: https://www.freetype.org
-- Version: 2.8.1
+- Version: 2.9.1
- License: FreeType License (BSD-like)
Files extracted from upstream source:
@@ -191,7 +191,7 @@ Files extracted from upstream source:
## libvorbis
- Upstream: https://www.xiph.org/vorbis
-- Version: 1.3.5
+- Version: 1.3.6
- License: BSD-3-Clause
Files extracted from upstream source:
@@ -218,7 +218,7 @@ Godot-made change marked with `// -- GODOT --` comments.
## libwebp
- Upstream: https://chromium.googlesource.com/webm/libwebp/
-- Version: 0.6.1
+- Version: 1.0.0
- License: BSD-3-Clause
Files extracted from upstream source:
@@ -267,7 +267,7 @@ File extracted from upstream release tarball `mbedtls-2.8.0-apache.tgz`:
## minizip
- Upstream: http://www.zlib.net
-- Version: 1.2.4 (zlib contrib)
+- Version: 1.2.11 (zlib contrib)
- License: zlib
Files extracted from the upstream source:
@@ -342,11 +342,11 @@ Collection of single-file libraries used in Godot components.
* License: zlib
- `stb_truetype.h`
* Upstream: https://github.com/nothings/stb
- * Version: 1.17
+ * Version: 1.19
* License: Public Domain (Unlicense) or MIT
- `stb_vorbis.c`
* Upstream: https://github.com/nothings/stb
- * Version: 1.11
+ * Version: 1.14
* License: Public Domain (Unlicense) or MIT
@@ -480,7 +480,7 @@ Files extracted from upstream source:
## zstd
- Upstream: https://github.com/facebook/zstd
-- Version: 1.3.3
+- Version: 1.3.4
- License: BSD-3-Clause
Files extracted from upstream source:
diff --git a/thirdparty/freetype/FTL.TXT b/thirdparty/freetype/FTL.TXT
index 433ab060e3..c406d150fa 100644
--- a/thirdparty/freetype/FTL.TXT
+++ b/thirdparty/freetype/FTL.TXT
@@ -163,7 +163,7 @@ Legal Terms
Our home page can be found at
- http://www.freetype.org
+ https://www.freetype.org
--- end of FTL.TXT ---
diff --git a/thirdparty/freetype/include/freetype/config/ftconfig.h b/thirdparty/freetype/include/freetype/config/ftconfig.h
index 889aebf5ab..eedebf4082 100644
--- a/thirdparty/freetype/include/freetype/config/ftconfig.h
+++ b/thirdparty/freetype/include/freetype/config/ftconfig.h
@@ -4,7 +4,7 @@
/* */
/* ANSI-specific configuration file (specification only). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -73,11 +73,11 @@ FT_BEGIN_HEADER
/* The size of an `int' type. */
#if FT_UINT_MAX == 0xFFFFUL
-#define FT_SIZEOF_INT (16 / FT_CHAR_BIT)
+#define FT_SIZEOF_INT ( 16 / FT_CHAR_BIT )
#elif FT_UINT_MAX == 0xFFFFFFFFUL
-#define FT_SIZEOF_INT (32 / FT_CHAR_BIT)
+#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)
+#define FT_SIZEOF_INT ( 64 / FT_CHAR_BIT )
#else
#error "Unsupported size of `int' type!"
#endif
@@ -85,11 +85,11 @@ FT_BEGIN_HEADER
/* 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)
+#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)
+#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)
+#define FT_SIZEOF_LONG ( 64 / FT_CHAR_BIT )
#else
#error "Unsupported size of `long' type!"
#endif
@@ -236,12 +236,12 @@ FT_BEGIN_HEADER
#endif
-#if FT_SIZEOF_INT == (32 / FT_CHAR_BIT)
+#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)
+#elif FT_SIZEOF_LONG == ( 32 / FT_CHAR_BIT )
typedef signed long FT_Int32;
typedef unsigned long FT_UInt32;
@@ -252,12 +252,12 @@ FT_BEGIN_HEADER
/* look up an integer type that is at least 32 bits */
-#if FT_SIZEOF_INT >= (32 / FT_CHAR_BIT)
+#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)
+#elif FT_SIZEOF_LONG >= ( 32 / FT_CHAR_BIT )
typedef long FT_Fast;
typedef unsigned long FT_UFast;
@@ -267,7 +267,7 @@ FT_BEGIN_HEADER
/* determine whether we have a 64-bit int type for platforms without */
/* Autoconf */
-#if FT_SIZEOF_LONG == (64 / FT_CHAR_BIT)
+#if FT_SIZEOF_LONG == ( 64 / FT_CHAR_BIT )
/* FT_LONG64 must be defined if a 64-bit type is available */
#define FT_LONG64
@@ -365,6 +365,14 @@ FT_BEGIN_HEADER
#endif
+ /* Use FT_LOCAL and FT_LOCAL_DEF to declare and define, respectively, */
+ /* a function that gets used only within the scope of a module. */
+ /* Normally, both the header and source code files for such a */
+ /* function are within a single module directory. */
+ /* */
+ /* Intra-module arrays should be tagged with FT_LOCAL_ARRAY and */
+ /* FT_LOCAL_ARRAY_DEF. */
+ /* */
#ifdef FT_MAKE_OPTION_SINGLE_OBJECT
#define FT_LOCAL( x ) static x
@@ -386,6 +394,12 @@ FT_BEGIN_HEADER
#define FT_LOCAL_ARRAY_DEF( x ) const x
+ /* Use FT_BASE and FT_BASE_DEF to declare and define, respectively, */
+ /* functions that are used in more than a single module. In the */
+ /* current setup this implies that the declaration is in a header */
+ /* file in the `include/freetype/internal' directory, and the */
+ /* function body is in a file in `src/base'. */
+ /* */
#ifndef FT_BASE
#ifdef __cplusplus
@@ -408,14 +422,63 @@ FT_BEGIN_HEADER
#endif /* !FT_BASE_DEF */
+ /* When compiling FreeType as a DLL or DSO with hidden visibility */
+ /* some systems/compilers need a special attribute 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. */
+ /* */
+ /* To export a variable, use FT_EXPORT_VAR. */
+ /* */
#ifndef FT_EXPORT
-#ifdef __cplusplus
+#ifdef FT2_BUILD_LIBRARY
+
+#if defined( _WIN32 ) && ( defined( _DLL ) || defined( DLL_EXPORT ) )
+#define FT_EXPORT( x ) __declspec( dllexport ) x
+#elif defined( __GNUC__ ) && __GNUC__ >= 4
+#define FT_EXPORT( x ) __attribute__(( visibility( "default" ) )) x
+#elif defined( __cplusplus )
+#define FT_EXPORT( x ) extern "C" x
+#else
+#define FT_EXPORT( x ) extern x
+#endif
+
+#else
+
+#if defined( FT2_DLLIMPORT )
+#define FT_EXPORT( x ) __declspec( dllimport ) x
+#elif defined( __cplusplus )
#define FT_EXPORT( x ) extern "C" x
#else
#define FT_EXPORT( x ) extern x
#endif
+#endif
+
#endif /* !FT_EXPORT */
@@ -440,6 +503,7 @@ FT_BEGIN_HEADER
#endif /* !FT_EXPORT_VAR */
+
/* The following macros are needed to compile the library with a */
/* C++ compiler and with 16bit compilers. */
/* */
@@ -451,7 +515,13 @@ FT_BEGIN_HEADER
/* functions which are accessed by (global) function pointers. */
/* */
/* */
- /* FT_CALLBACK_DEF is used to _define_ a callback function. */
+ /* FT_CALLBACK_DEF is used to _define_ a callback function, */
+ /* located in the same source code file as the structure that uses */
+ /* it. */
+ /* */
+ /* FT_BASE_CALLBACK and FT_BASE_CALLBACK_DEF are used to declare */
+ /* and define a callback function, respectively, in a similar way */
+ /* as FT_BASE and FT_BASE_DEF work. */
/* */
/* FT_CALLBACK_TABLE is used to _declare_ a constant variable that */
/* contains pointers to callback functions. */
@@ -471,6 +541,16 @@ FT_BEGIN_HEADER
#endif
#endif /* FT_CALLBACK_DEF */
+#ifndef FT_BASE_CALLBACK
+#ifdef __cplusplus
+#define FT_BASE_CALLBACK( x ) extern "C" x
+#define FT_BASE_CALLBACK_DEF( x ) extern "C" x
+#else
+#define FT_BASE_CALLBACK( x ) extern x
+#define FT_BASE_CALLBACK_DEF( x ) x
+#endif
+#endif /* FT_BASE_CALLBACK */
+
#ifndef FT_CALLBACK_TABLE
#ifdef __cplusplus
#define FT_CALLBACK_TABLE extern "C"
diff --git a/thirdparty/freetype/include/freetype/config/ftheader.h b/thirdparty/freetype/include/freetype/config/ftheader.h
index d491af57c3..702f77cc42 100644
--- a/thirdparty/freetype/include/freetype/config/ftheader.h
+++ b/thirdparty/freetype/include/freetype/config/ftheader.h
@@ -4,7 +4,7 @@
/* */
/* Build macros of the FreeType 2 library. */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -318,14 +318,29 @@
/*************************************************************************
*
* @macro:
+ * FT_DRIVER_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing
+ * structures and macros related to the driver modules.
+ *
+ */
+#define FT_DRIVER_H <freetype/ftdriver.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
* FT_AUTOHINTER_H
*
* @description:
* A macro used in #include statements to name the file containing
* structures and macros related to the auto-hinting module.
*
+ * Deprecated since version 2.9; use @FT_DRIVER_H instead.
+ *
*/
-#define FT_AUTOHINTER_H <freetype/ftautoh.h>
+#define FT_AUTOHINTER_H FT_DRIVER_H
/*************************************************************************
@@ -337,8 +352,10 @@
* A macro used in #include statements to name the file containing
* structures and macros related to the CFF driver module.
*
+ * Deprecated since version 2.9; use @FT_DRIVER_H instead.
+ *
*/
-#define FT_CFF_DRIVER_H <freetype/ftcffdrv.h>
+#define FT_CFF_DRIVER_H FT_DRIVER_H
/*************************************************************************
@@ -350,8 +367,10 @@
* A macro used in #include statements to name the file containing
* structures and macros related to the TrueType driver module.
*
+ * Deprecated since version 2.9; use @FT_DRIVER_H instead.
+ *
*/
-#define FT_TRUETYPE_DRIVER_H <freetype/ftttdrv.h>
+#define FT_TRUETYPE_DRIVER_H FT_DRIVER_H
/*************************************************************************
@@ -363,8 +382,10 @@
* A macro used in #include statements to name the file containing
* structures and macros related to the PCF driver module.
*
+ * Deprecated since version 2.9; use @FT_DRIVER_H instead.
+ *
*/
-#define FT_PCF_DRIVER_H <freetype/ftpcfdrv.h>
+#define FT_PCF_DRIVER_H FT_DRIVER_H
/*************************************************************************
@@ -557,63 +578,6 @@
/*************************************************************************
*
* @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:
@@ -763,17 +727,6 @@
/*************************************************************************
*
* @macro:
- * FT_UNPATENTED_HINTING_H
- *
- * @description:
- * Deprecated.
- */
-#define FT_UNPATENTED_HINTING_H <freetype/ttunpat.h>
-
-
- /*************************************************************************
- *
- * @macro:
* FT_INCREMENTAL_H
*
* @description:
@@ -809,25 +762,30 @@
/* */
+ /* These header files don't need to be included by the user. */
#define FT_ERROR_DEFINITIONS_H <freetype/fterrdef.h>
+#define FT_PARAMETER_TAGS_H <freetype/ftparams.h>
+ /* Deprecated macros. */
+#define FT_UNPATENTED_HINTING_H <freetype/ftparams.h>
+#define FT_TRUETYPE_UNPATENTED_H <freetype/ftparams.h>
+
+ /* FT_CACHE_H is the only header file needed for the cache subsystem. */
+#define FT_CACHE_IMAGE_H FT_CACHE_H
+#define FT_CACHE_SMALL_BITMAPS_H FT_CACHE_H
+#define FT_CACHE_CHARMAP_H FT_CACHE_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>
+#define FT_CACHE_MANAGER_H FT_CACHE_H
+#define FT_CACHE_INTERNAL_MRU_H FT_CACHE_H
+#define FT_CACHE_INTERNAL_MANAGER_H FT_CACHE_H
+#define FT_CACHE_INTERNAL_CACHE_H FT_CACHE_H
+#define FT_CACHE_INTERNAL_GLYPH_H FT_CACHE_H
+#define FT_CACHE_INTERNAL_IMAGE_H FT_CACHE_H
+#define FT_CACHE_INTERNAL_SBITS_H FT_CACHE_H
/*
diff --git a/thirdparty/freetype/include/freetype/config/ftoption.h b/thirdparty/freetype/include/freetype/config/ftoption.h
index 2fbe80b9b4..4bcab2af5c 100644
--- a/thirdparty/freetype/include/freetype/config/ftoption.h
+++ b/thirdparty/freetype/include/freetype/config/ftoption.h
@@ -4,7 +4,7 @@
/* */
/* User-selectable configuration macros (specification only). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -75,19 +75,21 @@ FT_BEGIN_HEADER
/*************************************************************************/
- /*************************************************************************/
+ /*#***********************************************************************/
/* */
/* If you enable this configuration option, FreeType recognizes an */
/* environment variable called `FREETYPE_PROPERTIES', which can be used */
/* to control the various font drivers and modules. The controllable */
- /* properties are listed in the section `Controlling FreeType Modules' */
- /* in the reference's table of contents; currently there are properties */
- /* for the auto-hinter (file `ftautoh.h'), CFF (file `ftcffdrv.h'), */
- /* TrueType (file `ftttdrv.h'), and PCF (file `ftpcfdrv.h'). */
+ /* properties are listed in the section @properties. */
+ /* */
+ /* You have to undefine this configuration option on platforms that lack */
+ /* the concept of environment variables (and thus don't have the */
+ /* `getenv' function), for example Windows CE. */
/* */
/* `FREETYPE_PROPERTIES' has the following syntax form (broken here into */
/* multiple lines for better readability). */
/* */
+ /* { */
/* <optional whitespace> */
/* <module-name1> ':' */
/* <property-name1> '=' <property-value1> */
@@ -95,6 +97,7 @@ FT_BEGIN_HEADER
/* <module-name2> ':' */
/* <property-name2> '=' <property-value2> */
/* ... */
+ /* } */
/* */
/* Example: */
/* */
@@ -211,6 +214,10 @@ FT_BEGIN_HEADER
/* Do not #undef this macro here since the build system might define */
/* it for certain configurations only. */
/* */
+ /* If you use a build system like cmake or the `configure' script, */
+ /* options set by those programs have precendence, overwriting the */
+ /* value here with the configured one. */
+ /* */
/* #define FT_CONFIG_OPTION_SYSTEM_ZLIB */
@@ -227,6 +234,10 @@ FT_BEGIN_HEADER
/* */
/* Define this macro if you want to enable this `feature'. */
/* */
+ /* If you use a build system like cmake or the `configure' script, */
+ /* options set by those programs have precendence, overwriting the */
+ /* value here with the configured one. */
+ /* */
/* #define FT_CONFIG_OPTION_USE_BZIP2 */
@@ -252,6 +263,10 @@ FT_BEGIN_HEADER
/* */
/* Define this macro if you want to enable this `feature'. */
/* */
+ /* If you use a build system like cmake or the `configure' script, */
+ /* options set by those programs have precendence, overwriting the */
+ /* value here with the configured one. */
+ /* */
/* #define FT_CONFIG_OPTION_USE_PNG */
@@ -265,49 +280,11 @@ FT_BEGIN_HEADER
/* */
/* Define this macro if you want to enable this `feature'. */
/* */
-/* #define FT_CONFIG_OPTION_USE_HARFBUZZ */
-
-
- /*************************************************************************/
- /* */
- /* 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 ); */
- /* */
+ /* If you use a build system like cmake or the `configure' script, */
+ /* options set by those programs have precendence, overwriting the */
+ /* value here with the configured one. */
/* */
- /* 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 */
+/* #define FT_CONFIG_OPTION_USE_HARFBUZZ */
/*************************************************************************/
@@ -678,7 +655,7 @@ FT_BEGIN_HEADER
/* This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be */
/* defined. */
/* */
- /* [1] http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx */
+ /* [1] https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx */
/* */
/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING 1 */
#define TT_CONFIG_OPTION_SUBPIXEL_HINTING 2
@@ -698,7 +675,7 @@ FT_BEGIN_HEADER
/* composite flags array which can be used to disambiguate, but old */
/* fonts will not have them. */
/* */
- /* http://www.microsoft.com/typography/otspec/glyf.htm */
+ /* https://www.microsoft.com/typography/otspec/glyf.htm */
/* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6glyf.html */
/* */
#undef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
@@ -796,6 +773,16 @@ FT_BEGIN_HEADER
/*************************************************************************/
+ /* */
+ /* T1_CONFIG_OPTION_OLD_ENGINE controls whether the pre-Adobe Type 1 */
+ /* engine gets compiled into FreeType. If defined, it is possible to */
+ /* switch between the two engines using the `hinting-engine' property of */
+ /* the type1 driver module. */
+ /* */
+/* #define T1_CONFIG_OPTION_OLD_ENGINE */
+
+
+ /*************************************************************************/
/*************************************************************************/
/**** ****/
/**** C F F D R I V E R C O N F I G U R A T I O N ****/
@@ -810,8 +797,8 @@ FT_BEGIN_HEADER
/* possible to set up the default values of the four control points that */
/* define the stem darkening behaviour of the (new) CFF engine. For */
/* more details please read the documentation of the */
- /* `darkening-parameters' property of the cff driver module (file */
- /* `ftcffdrv.h'), which allows the control at run-time. */
+ /* `darkening-parameters' property (file `ftdriver.h'), which allows the */
+ /* control at run-time. */
/* */
/* Do *not* undefine these macros! */
/* */
@@ -899,7 +886,7 @@ FT_BEGIN_HEADER
/* */
/* This experimental option is active only if the rendering mode is */
/* FT_RENDER_MODE_LIGHT; you can switch warping on and off with the */
- /* `warping' property of the auto-hinter (see file `ftautoh.h' for more */
+ /* `warping' property of the auto-hinter (see file `ftdriver.h' for more */
/* information; by default it is switched off). */
/* */
#define AF_CONFIG_OPTION_USE_WARPER
diff --git a/thirdparty/freetype/include/freetype/config/ftstdlib.h b/thirdparty/freetype/include/freetype/config/ftstdlib.h
index 05a4845fd5..42f9a06e43 100644
--- a/thirdparty/freetype/include/freetype/config/ftstdlib.h
+++ b/thirdparty/freetype/include/freetype/config/ftstdlib.h
@@ -5,7 +5,7 @@
/* ANSI-specific library and header configuration file (specification */
/* only). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/freetype.h b/thirdparty/freetype/include/freetype/freetype.h
index b0c261799a..96644046e4 100644
--- a/thirdparty/freetype/include/freetype/freetype.h
+++ b/thirdparty/freetype/include/freetype/freetype.h
@@ -4,7 +4,7 @@
/* */
/* FreeType high-level API and common types (specification only). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -138,6 +138,7 @@ FT_BEGIN_HEADER
/* FT_FACE_FLAG_TRICKY */
/* FT_FACE_FLAG_KERNING */
/* FT_FACE_FLAG_MULTIPLE_MASTERS */
+ /* FT_FACE_FLAG_VARIATION */
/* FT_FACE_FLAG_GLYPH_NAMES */
/* FT_FACE_FLAG_EXTERNAL_STREAM */
/* FT_FACE_FLAG_HINTER */
@@ -147,14 +148,16 @@ FT_BEGIN_HEADER
/* FT_HAS_KERNING */
/* FT_HAS_FIXED_SIZES */
/* FT_HAS_GLYPH_NAMES */
- /* FT_HAS_MULTIPLE_MASTERS */
/* FT_HAS_COLOR */
+ /* FT_HAS_MULTIPLE_MASTERS */
/* */
/* FT_IS_SFNT */
/* FT_IS_SCALABLE */
/* FT_IS_FIXED_WIDTH */
/* FT_IS_CID_KEYED */
/* FT_IS_TRICKY */
+ /* FT_IS_NAMED_INSTANCE */
+ /* FT_IS_VARIATION */
/* */
/* FT_STYLE_FLAG_BOLD */
/* FT_STYLE_FLAG_ITALIC */
@@ -648,7 +651,7 @@ FT_BEGIN_HEADER
/* FT_ENCODING_MS_SYMBOL :: */
/* Microsoft Symbol encoding, used to encode mathematical symbols */
/* and wingdings. For more information, see */
- /* `http://www.microsoft.com/typography/otspec/recom.htm', */
+ /* `https://www.microsoft.com/typography/otspec/recom.htm', */
/* `http://www.kostis.net/charsets/symbol.htm', and */
/* `http://www.kostis.net/charsets/wingding.htm'. */
/* */
@@ -657,7 +660,7 @@ FT_BEGIN_HEADER
/* */
/* FT_ENCODING_SJIS :: */
/* Shift JIS encoding for Japanese. More info at */
- /* `http://en.wikipedia.org/wiki/Shift_JIS'. See note on */
+ /* `https://en.wikipedia.org/wiki/Shift_JIS'. See note on */
/* multi-byte encodings below. */
/* */
/* FT_ENCODING_PRC :: */
@@ -673,7 +676,7 @@ FT_BEGIN_HEADER
/* Corresponds to the Korean encoding system known as Extended */
/* Wansung (MS Windows code page 949). */
/* For more information see */
- /* `http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/bestfit949.txt'. */
+ /* `https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/bestfit949.txt'. */
/* */
/* FT_ENCODING_JOHAB :: */
/* The Korean standard character set (KS~C 5601-1992), which */
@@ -721,11 +724,12 @@ FT_BEGIN_HEADER
/* Same as FT_ENCODING_JOHAB. Deprecated. */
/* */
/* <Note> */
- /* By default, FreeType automatically synthesizes a Unicode charmap */
- /* for PostScript fonts, using their glyph name 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. */
+ /* By default, FreeType enables a Unicode charmap and tags it with */
+ /* FT_ENCODING_UNICODE when it is either provided or can be generated */
+ /* from PostScript glyph name dictionaries in the font file. */
+ /* All other encodings are considered legacy and tagged only if */
+ /* explicitly defined in the font file. Otherwise, FT_ENCODING_NONE */
+ /* is used. */
/* */
/* 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 */
@@ -749,7 +753,7 @@ FT_BEGIN_HEADER
/* @FT_Get_CMap_Language_ID to query the Mac language ID that may */
/* be needed to be able to distinguish Apple encoding variants. See */
/* */
- /* http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/Readme.txt */
+ /* https://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. */
@@ -888,34 +892,41 @@ FT_BEGIN_HEADER
/* are set to~0 if there is only one face in */
/* the font file. */
/* */
- /* Bits 16-30 are relevant to GX and OpenType */
- /* variation fonts only, holding the named */
- /* instance index for the current face index */
- /* (starting with value~1; value~0 indicates */
- /* font access without a named instance). For */
- /* non-variation fonts, bits 16-30 are */
- /* ignored. If we have the third named */
- /* instance of face~4, say, `face_index' is */
- /* set to 0x00030004. */
+ /* [Since 2.6.1] Bits 16-30 are relevant to GX */
+ /* and OpenType variation fonts only, holding */
+ /* the named instance index for the current */
+ /* face index (starting with value~1; value~0 */
+ /* indicates font access without a named */
+ /* instance). For non-variation fonts, bits */
+ /* 16-30 are ignored. If we have the third */
+ /* named instance of face~4, say, `face_index' */
+ /* is set to 0x00030004. */
/* */
/* Bit 31 is always zero (this is, */
/* `face_index' is always a positive value). */
/* */
+ /* [Since 2.9] Changing the design coordinates */
+ /* with @FT_Set_Var_Design_Coordinates or */
+ /* @FT_Set_Var_Blend_Coordinates does not */
+ /* influence the named instance index value */
+ /* (only @FT_Set_Named_Instance does that). */
+ /* */
/* face_flags :: A set of bit flags that give important */
/* information about the face; see */
/* @FT_FACE_FLAG_XXX for the details. */
/* */
/* style_flags :: The lower 16~bits contain a set of bit */
/* flags indicating the style of the face; see */
- /* @FT_STYLE_FLAG_XXX for the details. Bits */
- /* 16-30 hold the number of named instances */
- /* available for the current face if we have a */
- /* GX or OpenType variation (sub)font. Bit 31 */
- /* is always zero (this is, `style_flags' is */
- /* always a positive value). Note that a */
- /* variation font has always at least one */
- /* named instance, namely the default */
- /* instance. */
+ /* @FT_STYLE_FLAG_XXX for the details. */
+ /* */
+ /* [Since 2.6.1] Bits 16-30 hold the number */
+ /* of named instances available for the */
+ /* current face if we have a GX or OpenType */
+ /* variation (sub)font. Bit 31 is always zero */
+ /* (this is, `style_flags' is always a */
+ /* positive value). Note that a variation */
+ /* font has always at least one named */
+ /* instance, namely the default instance. */
/* */
/* num_glyphs :: The number of glyphs in the face. If the */
/* face is scalable and has sbits (see */
@@ -1052,6 +1063,9 @@ FT_BEGIN_HEADER
/* `descender', `height', `underline_position', and */
/* `underline_thickness'. */
/* */
+ /* Especially for TrueType fonts see also the documentation for */
+ /* @FT_Size_Metrics. */
+ /* */
typedef struct FT_FaceRec_
{
FT_Long num_faces;
@@ -1162,7 +1176,7 @@ FT_BEGIN_HEADER
/* interpolating between them. Supported formats are Adobe MM, */
/* TrueType GX, and OpenType variation fonts. */
/* */
- /* See the multiple-masters specific API for details. */
+ /* See section @multiple_masters for API details. */
/* */
/* FT_FACE_FLAG_GLYPH_NAMES :: */
/* The face contains glyph names, which can be retrieved using */
@@ -1212,8 +1226,15 @@ FT_BEGIN_HEADER
/* tricky fonts; they are hard-coded in file `ttobjs.c'. */
/* */
/* FT_FACE_FLAG_COLOR :: */
- /* The face has color glyph tables. To access color glyphs use */
- /* @FT_LOAD_COLOR. */
+ /* [Since 2.5.1] The face has color glyph tables. To access color */
+ /* glyphs use @FT_LOAD_COLOR. */
+ /* */
+ /* FT_FACE_FLAG_VARIATION :: */
+ /* [Since 2.9] Set if the current face (or named instance) has been */
+ /* altered with @FT_Set_MM_Design_Coordinates, */
+ /* @FT_Set_Var_Design_Coordinates, or */
+ /* @FT_Set_Var_Blend_Coordinates. This flag is unset by a call to */
+ /* @FT_Set_Named_Instance. */
/* */
#define FT_FACE_FLAG_SCALABLE ( 1L << 0 )
#define FT_FACE_FLAG_FIXED_SIZES ( 1L << 1 )
@@ -1230,6 +1251,7 @@ FT_BEGIN_HEADER
#define FT_FACE_FLAG_CID_KEYED ( 1L << 12 )
#define FT_FACE_FLAG_TRICKY ( 1L << 13 )
#define FT_FACE_FLAG_COLOR ( 1L << 14 )
+#define FT_FACE_FLAG_VARIATION ( 1L << 15 )
/*************************************************************************
@@ -1391,6 +1413,14 @@ FT_BEGIN_HEADER
* A macro that returns true whenever a face object is a named instance
* of a GX or OpenType variation font.
*
+ * [Since 2.9] Changing the design coordinates with
+ * @FT_Set_Var_Design_Coordinates or @FT_Set_Var_Blend_Coordinates does
+ * not influence the return value of this macro (only
+ * @FT_Set_Named_Instance does that).
+ *
+ * @since:
+ * 2.7
+ *
*/
#define FT_IS_NAMED_INSTANCE( face ) \
( (face)->face_index & 0x7FFF0000L )
@@ -1399,6 +1429,24 @@ FT_BEGIN_HEADER
/*************************************************************************
*
* @macro:
+ * FT_IS_VARIATION( face )
+ *
+ * @description:
+ * A macro that returns true whenever a face object has been altered
+ * by @FT_Set_MM_Design_Coordinates, @FT_Set_Var_Design_Coordinates, or
+ * @FT_Set_Var_Blend_Coordinates.
+ *
+ * @since:
+ * 2.9
+ *
+ */
+#define FT_IS_VARIATION( face ) \
+ ( (face)->face_flags & FT_FACE_FLAG_VARIATION )
+
+
+ /*************************************************************************
+ *
+ * @macro:
* FT_IS_CID_KEYED( face )
*
* @description:
@@ -1437,6 +1485,9 @@ FT_BEGIN_HEADER
* A macro that returns true whenever a face object contains
* tables for color glyphs.
*
+ * @since:
+ * 2.5.1
+ *
*/
#define FT_HAS_COLOR( face ) \
( (face)->face_flags & FT_FACE_FLAG_COLOR )
@@ -1534,7 +1585,7 @@ FT_BEGIN_HEADER
/* to the following. */
/* */
/* { */
- /* scaled_ascender = FT_MulFix( face->root.ascender, */
+ /* scaled_ascender = FT_MulFix( face->ascender, */
/* size_metrics->y_scale ); */
/* } */
/* */
@@ -1548,6 +1599,43 @@ FT_BEGIN_HEADER
/* */
/* The `FT_Size_Metrics' structure is valid for bitmap fonts also. */
/* */
+ /* */
+ /* *TrueType* *fonts* *with* *native* *bytecode* *hinting* */
+ /* */
+ /* All applications that handle TrueType fonts with native hinting */
+ /* must be aware that TTFs expect different rounding of vertical font */
+ /* dimensions. The application has to cater for this, especially if */
+ /* it wants to rely on a TTF's vertical data (for example, to */
+ /* properly align box characters vertically). */
+ /* */
+ /* Only the application knows _in_ _advance_ that it is going to use */
+ /* native hinting for TTFs! FreeType, on the other hand, selects the */
+ /* hinting mode not at the time of creating an @FT_Size object but */
+ /* much later, namely while calling @FT_Load_Glyph. */
+ /* */
+ /* Here is some pseudo code that illustrates a possible solution. */
+ /* */
+ /* { */
+ /* font_format = FT_Get_Font_Format( face ); */
+ /* */
+ /* if ( !strcmp( font_format, "TrueType" ) && */
+ /* do_native_bytecode_hinting ) */
+ /* { */
+ /* ascender = ROUND( FT_MulFix( face->ascender, */
+ /* size_metrics->y_scale ) ); */
+ /* descender = ROUND( FT_MulFix( face->descender, */
+ /* size_metrics->y_scale ) ); */
+ /* } */
+ /* else */
+ /* { */
+ /* ascender = size_metrics->ascender; */
+ /* descender = size_metrics->descender; */
+ /* } */
+ /* */
+ /* height = size_metrics->height; */
+ /* max_advance = size_metrics->max_advance; */
+ /* } */
+ /* */
typedef struct FT_Size_Metrics_
{
FT_UShort x_ppem; /* horizontal pixels per EM */
@@ -1689,17 +1777,13 @@ FT_BEGIN_HEADER
/* @FT_GLYPH_FORMAT_COMPOSITE, but other values */
/* 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 :: This field is used as a bitmap descriptor. */
+ /* 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 :: The bitmap's left bearing expressed in */
- /* integer pixels. Only valid if the format is */
- /* @FT_GLYPH_FORMAT_BITMAP, this is, if the */
- /* glyph slot contains a bitmap. */
+ /* integer pixels. */
/* */
/* bitmap_top :: The bitmap's top bearing expressed in integer */
/* pixels. This is the distance from the */
@@ -1746,7 +1830,9 @@ FT_BEGIN_HEADER
/* 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). */
+ /* formats). [Since 2.9] The prospective bitmap metrics are */
+ /* calculated according to @FT_LOAD_TARGET_XXX and other flags even */
+ /* for the outline glyph, even if @FT_LOAD_RENDER is not set. */
/* */
/* This image can later be converted into a bitmap by calling */
/* @FT_Render_Glyph. This function searches the current renderer for */
@@ -1895,8 +1981,8 @@ FT_BEGIN_HEADER
/* */
/* If compilation option FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES is */
/* set, this function reads the `FREETYPE_PROPERTIES' environment */
- /* variable to control driver properties. See sections @auto_hinter, */
- /* @cff_driver, @pcf_driver, and @tt_driver for more. */
+ /* variable to control driver properties. See section @properties */
+ /* for more. */
/* */
FT_EXPORT( FT_Error )
FT_Init_FreeType( FT_Library *alibrary );
@@ -1977,8 +2063,8 @@ FT_BEGIN_HEADER
/* 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. */
+ /* The ID and function of parameters are driver-specific. See */
+ /* section @parameter_tags for more information. */
/* */
typedef struct FT_Parameter_
{
@@ -2155,14 +2241,14 @@ FT_BEGIN_HEADER
/* with value~0). Set it to~0 if there is only one */
/* face in the font file. */
/* */
- /* Bits 16-30 are relevant to GX and OpenType variation */
- /* fonts only, specifying the named instance index for */
- /* the current face index (starting with value~1; */
- /* value~0 makes FreeType ignore named instances). For */
- /* non-variation fonts, bits 16-30 are ignored. */
- /* Assuming that you want to access the third named */
- /* instance in face~4, `face_index' should be set to */
- /* 0x00030004. If you want to access face~4 without */
+ /* [Since 2.6.1] Bits 16-30 are relevant to GX and */
+ /* OpenType variation fonts only, specifying the named */
+ /* instance index for the current face index (starting */
+ /* with value~1; value~0 makes FreeType ignore named */
+ /* instances). For non-variation fonts, bits 16-30 are */
+ /* ignored. Assuming that you want to access the third */
+ /* named instance in face~4, `face_index' should be set */
+ /* to 0x00030004. If you want to access face~4 without */
/* variation handling, simply set `face_index' to */
/* value~4. */
/* */
@@ -2748,6 +2834,10 @@ FT_BEGIN_HEADER
/* since its glyph indices are not listed in any of the font's */
/* charmaps. */
/* */
+ /* If no active cmap is set up (i.e., `face->charmap' is zero), the */
+ /* call to @FT_Get_Char_Index is omitted, and the function behaves */
+ /* identically to @FT_Load_Glyph. */
+ /* */
FT_EXPORT( FT_Error )
FT_Load_Char( FT_Face face,
FT_ULong char_code,
@@ -2869,26 +2959,26 @@ FT_BEGIN_HEADER
* Disable the auto-hinter. See also the note below.
*
* FT_LOAD_COLOR ::
- * Load embedded color bitmap images. The resulting color bitmaps,
- * if available, will have the @FT_PIXEL_MODE_BGRA format. If the
- * flag is not set and color bitmaps are found, they are converted
- * to 256-level gray bitmaps transparently, using the
+ * [Since 2.5] Load embedded color bitmap images. The resulting color
+ * bitmaps, if available, will have the @FT_PIXEL_MODE_BGRA format.
+ * If the flag is not set and color bitmaps are found, they are
+ * converted to 256-level gray bitmaps transparently, using the
* @FT_PIXEL_MODE_GRAY format.
*
* FT_LOAD_COMPUTE_METRICS ::
- * Compute glyph metrics from the glyph data, without the use of
- * bundled metrics tables (for example, the `hdmx' table in TrueType
- * fonts). This flag is mainly used by font validating or font
- * editing applications, which need to ignore, verify, or edit those
- * tables.
+ * [Since 2.6.1] Compute glyph metrics from the glyph data, without
+ * the use of bundled metrics tables (for example, the `hdmx' table in
+ * TrueType fonts). This flag is mainly used by font validating or
+ * font editing applications, which need to ignore, verify, or edit
+ * those tables.
*
* Currently, this flag is only implemented for TrueType fonts.
*
* FT_LOAD_BITMAP_METRICS_ONLY ::
- * Request loading of the metrics and bitmap image information of a
- * (possibly embedded) bitmap glyph without allocating or copying
- * the bitmap image data itself. No effect if the target glyph is
- * not a bitmap image.
+ * [Since 2.7.1] Request loading of the metrics and bitmap image
+ * information of a (possibly embedded) bitmap glyph without
+ * allocating or copying the bitmap image data itself. No effect if
+ * the target glyph is not a bitmap image.
*
* This flag unsets @FT_LOAD_RENDER.
*
@@ -2980,7 +3070,7 @@ FT_BEGIN_HEADER
*
* Advance widths are rounded to integer values; however, using the
* `lsb_delta' and `rsb_delta' fields of @FT_GlyphSlotRec, it is
- * possible to get fractional advance widths for sub-pixel positioning
+ * possible to get fractional advance widths for subpixel positioning
* (which is recommended to use).
*
* If configuration option AF_CONFIG_OPTION_TT_SIZE_METRICS is active,
@@ -3119,13 +3209,13 @@ FT_BEGIN_HEADER
/* opacity). */
/* */
/* FT_RENDER_MODE_LCD :: */
- /* This mode corresponds to horizontal RGB and BGR sub-pixel */
+ /* This mode corresponds to horizontal RGB and BGR subpixel */
/* 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 */
+ /* This mode corresponds to vertical RGB and BGR subpixel 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. */
@@ -3471,7 +3561,14 @@ FT_BEGIN_HEADER
/* retrieve it. FreeType follows Adobe TechNote #5902, `Generating */
/* PostScript Names for Fonts Using OpenType Font Variations'. */
/* */
- /* http://wwwimages.adobe.com/content/dam/Adobe/en/devnet/font/pdfs/5902.AdobePSNameGeneration.html */
+ /* https://download.macromedia.com/pub/developer/opentype/tech-notes/5902.AdobePSNameGeneration.html */
+ /* */
+ /* [Since 2.9] Special PostScript names for named instances are only */
+ /* returned if the named instance is set with @FT_Set_Named_Instance */
+ /* (and the font has corresponding entries in its `fvar' table). If */
+ /* @FT_IS_VARIATION returns true, the algorithmically derived */
+ /* PostScript name is provided, not looking up special entries for */
+ /* named instances. */
/* */
FT_EXPORT( const char* )
FT_Get_Postscript_Name( FT_Face face );
@@ -3702,17 +3799,17 @@ FT_BEGIN_HEADER
* Note that only a subset of the available properties can be
* controlled.
*
- * * Stem darkening (@FT_PARAM_TAG_STEM_DARKENING, corresponding to the
- * property `no-stem-darkening' provided by the `autofit' and `cff'
- * modules; see @no-stem-darkening[autofit] and
- * @no-stem-darkening[cff]).
+ * * @FT_PARAM_TAG_STEM_DARKENING (stem darkening, corresponding to the
+ * property `no-stem-darkening' provided by the `autofit', `cff',
+ * `type1', and `t1cid' modules; see @no-stem-darkening).
*
- * * LCD filter weights (@FT_PARAM_TAG_LCD_FILTER_WEIGHTS, corresponding
+ * * @FT_PARAM_TAG_LCD_FILTER_WEIGHTS (LCD filter weights, corresponding
* to function @FT_Library_SetLcdFilterWeights).
*
- * * Seed value for the CFF `random' operator
- * (@FT_PARAM_TAG_RANDOM_SEED, corresponding to the `random-seed'
- * property provided by the `cff' module; see @random-seed).
+ * * @FT_PARAM_TAG_RANDOM_SEED (seed value for the CFF, Type~1, and CID
+ * `random' operator, corresponding to the `random-seed' property
+ * provided by the `cff', `type1', and `t1cid' modules; see
+ * @random-seed).
*
* Pass NULL as `data' in @FT_Parameter for a given tag to reset the
* option and use the library or module default again.
@@ -3775,6 +3872,9 @@ FT_BEGIN_HEADER
* FT_Face_Properties( face, 1, &property );
* }
*
+ * @since:
+ * 2.8
+ *
*/
FT_EXPORT( FT_Error )
FT_Face_Properties( FT_Face face,
@@ -3899,7 +3999,7 @@ FT_BEGIN_HEADER
/* and subsetting restrictions associated with a font. */
/* */
/* See */
- /* http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/FontPolicies.pdf */
+ /* https://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/FontPolicies.pdf */
/* for more details. */
/* */
/* <Values> */
@@ -3999,9 +4099,9 @@ FT_BEGIN_HEADER
/* Sequences' (IVS), collected in the `Ideographic Variation */
/* Database' (IVD). */
/* */
- /* http://unicode.org/Public/UCD/latest/ucd/StandardizedVariants.txt */
- /* http://unicode.org/reports/tr37/ */
- /* http://unicode.org/ivd/ */
+ /* https://unicode.org/Public/UCD/latest/ucd/StandardizedVariants.txt */
+ /* https://unicode.org/reports/tr37/ */
+ /* https://unicode.org/ivd/ */
/* */
/* To date (January 2017), the character with the most ideographic */
/* variations is U+9089, having 32 such IVS. */
@@ -4456,7 +4556,7 @@ FT_BEGIN_HEADER
*
*/
#define FREETYPE_MAJOR 2
-#define FREETYPE_MINOR 8
+#define FREETYPE_MINOR 9
#define FREETYPE_PATCH 1
diff --git a/thirdparty/freetype/include/freetype/ftadvanc.h b/thirdparty/freetype/include/freetype/ftadvanc.h
index dea96e0db4..f78e8b1a9d 100644
--- a/thirdparty/freetype/include/freetype/ftadvanc.h
+++ b/thirdparty/freetype/include/freetype/ftadvanc.h
@@ -4,7 +4,7 @@
/* */
/* Quick computation of advance widths (specification only). */
/* */
-/* Copyright 2008-2017 by */
+/* Copyright 2008-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/ftbbox.h b/thirdparty/freetype/include/freetype/ftbbox.h
index f03bdc1e1e..f9eb70b137 100644
--- a/thirdparty/freetype/include/freetype/ftbbox.h
+++ b/thirdparty/freetype/include/freetype/ftbbox.h
@@ -4,7 +4,7 @@
/* */
/* FreeType exact bbox computation (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -61,7 +61,7 @@ FT_BEGIN_HEADER
/* Compute the exact bounding box of an outline. This is slower */
/* than computing the control box. However, it uses an advanced */
/* algorithm that returns _very_ quickly when the two boxes */
- /* coincide. Otherwise, the outline Bézier arcs are traversed to */
+ /* coincide. Otherwise, the outline Bezier arcs are traversed to */
/* extract their extrema. */
/* */
/* <Input> */
diff --git a/thirdparty/freetype/include/freetype/ftbdf.h b/thirdparty/freetype/include/freetype/ftbdf.h
index 3d3106bad0..1b6dea6586 100644
--- a/thirdparty/freetype/include/freetype/ftbdf.h
+++ b/thirdparty/freetype/include/freetype/ftbdf.h
@@ -4,7 +4,7 @@
/* */
/* FreeType API for accessing BDF-specific strings (specification). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/ftbitmap.h b/thirdparty/freetype/include/freetype/ftbitmap.h
index 04b2402ad0..a43187cad4 100644
--- a/thirdparty/freetype/include/freetype/ftbitmap.h
+++ b/thirdparty/freetype/include/freetype/ftbitmap.h
@@ -4,7 +4,7 @@
/* */
/* FreeType utility functions for bitmaps (specification). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -97,7 +97,7 @@ FT_BEGIN_HEADER
FT_EXPORT( FT_Error )
FT_Bitmap_Copy( FT_Library library,
const FT_Bitmap *source,
- FT_Bitmap *target);
+ FT_Bitmap *target );
/*************************************************************************/
diff --git a/thirdparty/freetype/include/freetype/ftbzip2.h b/thirdparty/freetype/include/freetype/ftbzip2.h
index 9147a790a4..6edfa031b5 100644
--- a/thirdparty/freetype/include/freetype/ftbzip2.h
+++ b/thirdparty/freetype/include/freetype/ftbzip2.h
@@ -4,7 +4,7 @@
/* */
/* Bzip2-compressed stream support. */
/* */
-/* Copyright 2010-2017 by */
+/* Copyright 2010-2018 by */
/* Joel Klinghed. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/ftcache.h b/thirdparty/freetype/include/freetype/ftcache.h
index 5ff3ccf404..52d5f00e06 100644
--- a/thirdparty/freetype/include/freetype/ftcache.h
+++ b/thirdparty/freetype/include/freetype/ftcache.h
@@ -4,7 +4,7 @@
/* */
/* FreeType Cache subsystem (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -540,13 +540,6 @@ FT_BEGIN_HEADER
FTC_FaceID face_id );
- /*************************************************************************/
- /* */
- /* <Section> */
- /* cache_subsystem */
- /* */
- /*************************************************************************/
-
/*************************************************************************
*
* @type:
@@ -624,14 +617,6 @@ FT_BEGIN_HEADER
/*************************************************************************/
- /* */
- /* <Section> */
- /* cache_subsystem */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/***** *****/
diff --git a/thirdparty/freetype/include/freetype/ftchapters.h b/thirdparty/freetype/include/freetype/ftchapters.h
index a0a121b0a1..51257bb7ca 100644
--- a/thirdparty/freetype/include/freetype/ftchapters.h
+++ b/thirdparty/freetype/include/freetype/ftchapters.h
@@ -76,8 +76,11 @@
/* <Sections> */
/* auto_hinter */
/* cff_driver */
+/* t1_cid_driver */
/* tt_driver */
/* pcf_driver */
+/* properties */
+/* parameter_tags */
/* */
/***************************************************************************/
diff --git a/thirdparty/freetype/include/freetype/ftcid.h b/thirdparty/freetype/include/freetype/ftcid.h
index 4adcbeeda9..5e9100a67c 100644
--- a/thirdparty/freetype/include/freetype/ftcid.h
+++ b/thirdparty/freetype/include/freetype/ftcid.h
@@ -4,7 +4,7 @@
/* */
/* FreeType API for accessing CID font information (specification). */
/* */
-/* Copyright 2007-2017 by */
+/* Copyright 2007-2018 by */
/* Dereg Clegg and Michael Toftdal. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -87,7 +87,7 @@ FT_BEGIN_HEADER
FT_Get_CID_Registry_Ordering_Supplement( FT_Face face,
const char* *registry,
const char* *ordering,
- FT_Int *supplement);
+ FT_Int *supplement );
/**********************************************************************
diff --git a/thirdparty/freetype/include/freetype/ftdriver.h b/thirdparty/freetype/include/freetype/ftdriver.h
new file mode 100644
index 0000000000..e90475b2af
--- /dev/null
+++ b/thirdparty/freetype/include/freetype/ftdriver.h
@@ -0,0 +1,1225 @@
+/***************************************************************************/
+/* */
+/* ftdriver.h */
+/* */
+/* FreeType API for controlling driver modules (specification only). */
+/* */
+/* Copyright 2017-2018 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef FTDRIVER_H_
+#define FTDRIVER_H_
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_PARAMETER_TAGS_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:
+ * auto_hinter
+ *
+ * @title:
+ * The auto-hinter
+ *
+ * @abstract:
+ * Controlling the auto-hinting module.
+ *
+ * @description:
+ * While FreeType's auto-hinter doesn't expose API functions by itself,
+ * it is possible to control its behaviour with @FT_Property_Set and
+ * @FT_Property_Get. The following lists the available properties
+ * together with the necessary macros and structures.
+ *
+ * Note that the auto-hinter's module name is `autofitter' for
+ * historical reasons.
+ *
+ * Available properties are @increase-x-height, @no-stem-darkening
+ * (experimental), @darkening-parameters (experimental), @warping
+ * (experimental), @glyph-to-script-map (experimental), @fallback-script
+ * (experimental), and @default-script (experimental), as documented in
+ * the @properties section.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * cff_driver
+ *
+ * @title:
+ * The CFF driver
+ *
+ * @abstract:
+ * Controlling the CFF driver module.
+ *
+ * @description:
+ * While FreeType's CFF driver doesn't expose API functions by itself,
+ * it is possible to control its behaviour with @FT_Property_Set and
+ * @FT_Property_Get.
+ *
+ * The CFF driver's module name is `cff'.
+ *
+ * Available properties are @hinting-engine, @no-stem-darkening,
+ * @darkening-parameters, and @random-seed, as documented in the
+ * @properties section.
+ *
+ *
+ * *Hinting* *and* *antialiasing* *principles* *of* *the* *new* *engine*
+ *
+ * The rasterizer is positioning horizontal features (e.g., ascender
+ * height & x-height, or crossbars) on the pixel grid and minimizing the
+ * amount of antialiasing applied to them, while placing vertical
+ * features (vertical stems) on the pixel grid without hinting, thus
+ * representing the stem position and weight accurately. Sometimes the
+ * vertical stems may be only partially black. In this context,
+ * `antialiasing' means that stems are not positioned exactly on pixel
+ * borders, causing a fuzzy appearance.
+ *
+ * There are two principles behind this approach.
+ *
+ * 1) No hinting in the horizontal direction: Unlike `superhinted'
+ * TrueType, which changes glyph widths to accommodate regular
+ * inter-glyph spacing, Adobe's approach is `faithful to the design' in
+ * representing both the glyph width and the inter-glyph spacing
+ * designed for the font. This makes the screen display as close as it
+ * can be to the result one would get with infinite resolution, while
+ * preserving what is considered the key characteristics of each glyph.
+ * Note that the distances between unhinted and grid-fitted positions at
+ * small sizes are comparable to kerning values and thus would be
+ * noticeable (and distracting) while reading if hinting were applied.
+ *
+ * One of the reasons to not hint horizontally is antialiasing for LCD
+ * screens: The pixel geometry of modern displays supplies three
+ * vertical subpixels as the eye moves horizontally across each visible
+ * pixel. On devices where we can be certain this characteristic is
+ * present a rasterizer can take advantage of the subpixels to add
+ * increments of weight. In Western writing systems this turns out to
+ * be the more critical direction anyway; the weights and spacing of
+ * vertical stems (see above) are central to Armenian, Cyrillic, Greek,
+ * and Latin type designs. Even when the rasterizer uses greyscale
+ * antialiasing instead of color (a necessary compromise when one
+ * doesn't know the screen characteristics), the unhinted vertical
+ * features preserve the design's weight and spacing much better than
+ * aliased type would.
+ *
+ * 2) Alignment in the vertical direction: Weights and spacing along the
+ * y~axis are less critical; what is much more important is the visual
+ * alignment of related features (like cap-height and x-height). The
+ * sense of alignment for these is enhanced by the sharpness of grid-fit
+ * edges, while the cruder vertical resolution (full pixels instead of
+ * 1/3 pixels) is less of a problem.
+ *
+ * On the technical side, horizontal alignment zones for ascender,
+ * x-height, and other important height values (traditionally called
+ * `blue zones') as defined in the font are positioned independently,
+ * each being rounded to the nearest pixel edge, taking care of
+ * overshoot suppression at small sizes, stem darkening, and scaling.
+ *
+ * Hstems (this is, hint values defined in the font to help align
+ * horizontal features) that fall within a blue zone are said to be
+ * `captured' and are aligned to that zone. Uncaptured stems are moved
+ * in one of four ways, top edge up or down, bottom edge up or down.
+ * Unless there are conflicting hstems, the smallest movement is taken
+ * to minimize distortion.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * pcf_driver
+ *
+ * @title:
+ * The PCF driver
+ *
+ * @abstract:
+ * Controlling the PCF driver module.
+ *
+ * @description:
+ * While FreeType's PCF driver doesn't expose API functions by itself,
+ * it is possible to control its behaviour with @FT_Property_Set and
+ * @FT_Property_Get. Right now, there is a single property
+ * @no-long-family-names available if FreeType is compiled with
+ * PCF_CONFIG_OPTION_LONG_FAMILY_NAMES.
+ *
+ * The PCF driver's module name is `pcf'.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * t1_cid_driver
+ *
+ * @title:
+ * The Type 1 and CID drivers
+ *
+ * @abstract:
+ * Controlling the Type~1 and CID driver modules.
+ *
+ * @description:
+ * It is possible to control the behaviour of FreeType's Type~1 and
+ * Type~1 CID drivers with @FT_Property_Set and @FT_Property_Get.
+ *
+ * Behind the scenes, both drivers use the Adobe CFF engine for hinting;
+ * however, the used properties must be specified separately.
+ *
+ * The Type~1 driver's module name is `type1'; the CID driver's module
+ * name is `t1cid'.
+ *
+ * Available properties are @hinting-engine, @no-stem-darkening,
+ * @darkening-parameters, and @random-seed, as documented in the
+ * @properties section.
+ *
+ * Please see the @cff_driver section for more details on the new
+ * hinting engine.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * tt_driver
+ *
+ * @title:
+ * The TrueType driver
+ *
+ * @abstract:
+ * Controlling the TrueType driver module.
+ *
+ * @description:
+ * While FreeType's TrueType driver doesn't expose API functions by
+ * itself, it is possible to control its behaviour with @FT_Property_Set
+ * and @FT_Property_Get. The following lists the available properties
+ * together with the necessary macros and structures.
+ *
+ * The TrueType driver's module name is `truetype'.
+ *
+ * A single property @interpreter-version is available, as documented in
+ * the @properties section.
+ *
+ * We start with a list of definitions, kindly provided by Greg
+ * Hitchcock.
+ *
+ * _Bi-Level_ _Rendering_
+ *
+ * Monochromatic rendering, exclusively used in the early days of
+ * TrueType by both Apple and Microsoft. Microsoft's GDI interface
+ * supported hinting of the right-side bearing point, such that the
+ * advance width could be non-linear. Most often this was done to
+ * achieve some level of glyph symmetry. To enable reasonable
+ * performance (e.g., not having to run hinting on all glyphs just to
+ * get the widths) there was a bit in the head table indicating if the
+ * side bearing was hinted, and additional tables, `hdmx' and `LTSH', to
+ * cache hinting widths across multiple sizes and device aspect ratios.
+ *
+ * _Font_ _Smoothing_
+ *
+ * Microsoft's GDI implementation of anti-aliasing. Not traditional
+ * anti-aliasing as the outlines were hinted before the sampling. The
+ * widths matched the bi-level rendering.
+ *
+ * _ClearType_ _Rendering_
+ *
+ * Technique that uses physical subpixels to improve rendering on LCD
+ * (and other) displays. Because of the higher resolution, many methods
+ * of improving symmetry in glyphs through hinting the right-side
+ * bearing were no longer necessary. This lead to what GDI calls
+ * `natural widths' ClearType, see
+ * http://www.beatstamm.com/typography/RTRCh4.htm#Sec21. Since hinting
+ * has extra resolution, most non-linearity went away, but it is still
+ * possible for hints to change the advance widths in this mode.
+ *
+ * _ClearType_ _Compatible_ _Widths_
+ *
+ * One of the earliest challenges with ClearType was allowing the
+ * implementation in GDI to be selected without requiring all UI and
+ * documents to reflow. To address this, a compatible method of
+ * rendering ClearType was added where the font hints are executed once
+ * to determine the width in bi-level rendering, and then re-run in
+ * ClearType, with the difference in widths being absorbed in the font
+ * hints for ClearType (mostly in the white space of hints); see
+ * http://www.beatstamm.com/typography/RTRCh4.htm#Sec20. Somewhat by
+ * definition, compatible width ClearType allows for non-linear widths,
+ * but only when the bi-level version has non-linear widths.
+ *
+ * _ClearType_ _Subpixel_ _Positioning_
+ *
+ * One of the nice benefits of ClearType is the ability to more crisply
+ * display fractional widths; unfortunately, the GDI model of integer
+ * bitmaps did not support this. However, the WPF and Direct Write
+ * frameworks do support fractional widths. DWrite calls this `natural
+ * mode', not to be confused with GDI's `natural widths'. Subpixel
+ * positioning, in the current implementation of Direct Write,
+ * unfortunately does not support hinted advance widths, see
+ * http://www.beatstamm.com/typography/RTRCh4.htm#Sec22. Note that the
+ * TrueType interpreter fully allows the advance width to be adjusted in
+ * this mode, just the DWrite client will ignore those changes.
+ *
+ * _ClearType_ _Backward_ _Compatibility_
+ *
+ * This is a set of exceptions made in the TrueType interpreter to
+ * minimize hinting techniques that were problematic with the extra
+ * resolution of ClearType; see
+ * http://www.beatstamm.com/typography/RTRCh4.htm#Sec1 and
+ * https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx.
+ * This technique is not to be confused with ClearType compatible
+ * widths. ClearType backward compatibility has no direct impact on
+ * changing advance widths, but there might be an indirect impact on
+ * disabling some deltas. This could be worked around in backward
+ * compatibility mode.
+ *
+ * _Native_ _ClearType_ _Mode_
+ *
+ * (Not to be confused with `natural widths'.) This mode removes all
+ * the exceptions in the TrueType interpreter when running with
+ * ClearType. Any issues on widths would still apply, though.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * properties
+ *
+ * @title:
+ * Driver properties
+ *
+ * @abstract:
+ * Controlling driver modules.
+ *
+ * @description:
+ * Driver modules can be controlled by setting and unsetting properties,
+ * using the functions @FT_Property_Set and @FT_Property_Get. This
+ * section documents the available properties, together with auxiliary
+ * macros and structures.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_HINTING_XXX
+ *
+ * @description:
+ * A list of constants used for the @hinting-engine property to
+ * select the hinting engine for CFF, Type~1, and CID fonts.
+ *
+ * @values:
+ * FT_HINTING_FREETYPE ::
+ * Use the old FreeType hinting engine.
+ *
+ * FT_HINTING_ADOBE ::
+ * Use the hinting engine contributed by Adobe.
+ *
+ * @since:
+ * 2.9
+ *
+ */
+#define FT_HINTING_FREETYPE 0
+#define FT_HINTING_ADOBE 1
+
+ /* these constants (introduced in 2.4.12) are deprecated */
+#define FT_CFF_HINTING_FREETYPE FT_HINTING_FREETYPE
+#define FT_CFF_HINTING_ADOBE FT_HINTING_ADOBE
+
+
+ /**************************************************************************
+ *
+ * @property:
+ * hinting-engine
+ *
+ * @description:
+ * Thanks to Adobe, which contributed a new hinting (and parsing)
+ * engine, an application can select between `freetype' and `adobe' if
+ * compiled with CFF_CONFIG_OPTION_OLD_ENGINE. If this configuration
+ * macro isn't defined, `hinting-engine' does nothing.
+ *
+ * The same holds for the Type~1 and CID modules if compiled with
+ * T1_CONFIG_OPTION_OLD_ENGINE.
+ *
+ * For the `cff' module, the default engine is `freetype' if
+ * CFF_CONFIG_OPTION_OLD_ENGINE is defined, and `adobe' otherwise.
+ *
+ * For both the `type1' and `t1cid' modules, the default engine is
+ * `freetype' if T1_CONFIG_OPTION_OLD_ENGINE is defined, and `adobe'
+ * otherwise.
+ *
+ * The following example code demonstrates how to select Adobe's hinting
+ * engine for the `cff' module (omitting the error handling).
+ *
+ * {
+ * FT_Library library;
+ * FT_UInt hinting_engine = FT_CFF_HINTING_ADOBE;
+ *
+ *
+ * FT_Init_FreeType( &library );
+ *
+ * FT_Property_Set( library, "cff",
+ * "hinting-engine", &hinting_engine );
+ * }
+ *
+ * @note:
+ * This property can be used with @FT_Property_Get also.
+ *
+ * This property can be set via the `FREETYPE_PROPERTIES' environment
+ * variable (using values `adobe' or `freetype').
+ *
+ * @since:
+ * 2.4.12 (for `cff' module)
+ *
+ * 2.9 (for `type1' and `t1cid' modules)
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @property:
+ * no-stem-darkening
+ *
+ * @description:
+ * All glyphs that pass through the auto-hinter will be emboldened
+ * unless this property is set to TRUE. The same is true for the CFF,
+ * Type~1, and CID font modules if the `Adobe' engine is selected (which
+ * is the default).
+ *
+ * Stem darkening emboldens glyphs at smaller sizes to make them more
+ * readable on common low-DPI screens when using linear alpha blending
+ * and gamma correction, see @FT_Render_Glyph. When not using linear
+ * alpha blending and gamma correction, glyphs will appear heavy and
+ * fuzzy!
+ *
+ * Gamma correction essentially lightens fonts since shades of grey are
+ * shifted to higher pixel values (=~higher brightness) to match the
+ * original intention to the reality of our screens. The side-effect is
+ * that glyphs `thin out'. Mac OS~X and Adobe's proprietary font
+ * rendering library implement a counter-measure: stem darkening at
+ * smaller sizes where shades of gray dominate. By emboldening a glyph
+ * slightly in relation to its pixel size, individual pixels get higher
+ * coverage of filled-in outlines and are therefore `blacker'. This
+ * counteracts the `thinning out' of glyphs, making text remain readable
+ * at smaller sizes.
+ *
+ * By default, the Adobe engines for CFF, Type~1, and CID fonts darken
+ * stems at smaller sizes, regardless of hinting, to enhance contrast.
+ * Setting this property, stem darkening gets switched off.
+ *
+ * For the auto-hinter, stem-darkening is experimental currently and
+ * thus switched off by default (this is, `no-stem-darkening' is set to
+ * TRUE by default). Total consistency with the CFF driver is not
+ * achieved right now because the emboldening method differs and glyphs
+ * must be scaled down on the Y-axis to keep outline points inside their
+ * precomputed blue zones. The smaller the size (especially 9ppem and
+ * down), the higher the loss of emboldening versus the CFF driver.
+ *
+ * Note that stem darkening is never applied if @FT_LOAD_NO_SCALE is
+ * set.
+ *
+ * {
+ * FT_Library library;
+ * FT_Bool no_stem_darkening = TRUE;
+ *
+ *
+ * FT_Init_FreeType( &library );
+ *
+ * FT_Property_Set( library, "cff",
+ * "no-stem-darkening", &no_stem_darkening );
+ * }
+ *
+ * @note:
+ * This property can be used with @FT_Property_Get also.
+ *
+ * This property can be set via the `FREETYPE_PROPERTIES' environment
+ * variable (using values 1 and 0 for `on' and `off', respectively).
+ * It can also be set per face using @FT_Face_Properties with
+ * @FT_PARAM_TAG_STEM_DARKENING.
+ *
+ * @since:
+ * 2.4.12 (for `cff' module)
+ *
+ * 2.6.2 (for `autofitter' module)
+ *
+ * 2.9 (for `type1' and `t1cid' modules)
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @property:
+ * darkening-parameters
+ *
+ * @description:
+ * By default, the Adobe hinting engine, as used by the CFF, Type~1, and
+ * CID font drivers, darkens stems as follows (if the
+ * `no-stem-darkening' property isn't set):
+ *
+ * {
+ * stem width <= 0.5px: darkening amount = 0.4px
+ * stem width = 1px: darkening amount = 0.275px
+ * stem width = 1.667px: darkening amount = 0.275px
+ * stem width >= 2.333px: darkening amount = 0px
+ * }
+ *
+ * and piecewise linear in-between. At configuration time, these four
+ * control points can be set with the macro
+ * `CFF_CONFIG_OPTION_DARKENING_PARAMETERS'; the CFF, Type~1, and CID
+ * drivers share these values. At runtime, the control points can be
+ * changed using the `darkening-parameters' property, as the following
+ * example demonstrates for the Type~1 driver.
+ *
+ * {
+ * FT_Library library;
+ * FT_Int darken_params[8] = { 500, 300, // x1, y1
+ * 1000, 200, // x2, y2
+ * 1500, 100, // x3, y3
+ * 2000, 0 }; // x4, y4
+ *
+ *
+ * FT_Init_FreeType( &library );
+ *
+ * FT_Property_Set( library, "type1",
+ * "darkening-parameters", darken_params );
+ * }
+ *
+ * The x~values give the stem width, and the y~values the darkening
+ * amount. The unit is 1000th of pixels. All coordinate values must be
+ * positive; the x~values must be monotonically increasing; the
+ * y~values must be monotonically decreasing and smaller than or
+ * equal to 500 (corresponding to half a pixel); the slope of each
+ * linear piece must be shallower than -1 (e.g., -.4).
+ *
+ * The auto-hinter provides this property, too, as an experimental
+ * feature. See @no-stem-darkening for more.
+ *
+ * @note:
+ * This property can be used with @FT_Property_Get also.
+ *
+ * This property can be set via the `FREETYPE_PROPERTIES' environment
+ * variable, using eight comma-separated integers without spaces. Here
+ * the above example, using `\' to break the line for readability.
+ *
+ * {
+ * FREETYPE_PROPERTIES=\
+ * type1:darkening-parameters=500,300,1000,200,1500,100,2000,0
+ * }
+ *
+ * @since:
+ * 2.5.1 (for `cff' module)
+ *
+ * 2.6.2 (for `autofitter' module)
+ *
+ * 2.9 (for `type1' and `t1cid' modules)
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @property:
+ * random-seed
+ *
+ * @description:
+ * By default, the seed value for the CFF `random' operator and the
+ * similar `0 28 callothersubr pop' command for the Type~1 and CID
+ * drivers is set to a random value. However, mainly for debugging
+ * purposes, it is often necessary to use a known value as a seed so
+ * that the pseudo-random number sequences generated by `random' are
+ * repeatable.
+ *
+ * The `random-seed' property does that. Its argument is a signed 32bit
+ * integer; if the value is zero or negative, the seed given by the
+ * `intitialRandomSeed' private DICT operator in a CFF file gets used
+ * (or a default value if there is no such operator). If the value is
+ * positive, use it instead of `initialRandomSeed', which is
+ * consequently ignored.
+ *
+ * @note:
+ * This property can be set via the `FREETYPE_PROPERTIES' environment
+ * variable. It can also be set per face using @FT_Face_Properties with
+ * @FT_PARAM_TAG_RANDOM_SEED.
+ *
+ * @since:
+ * 2.8 (for `cff' module)
+ *
+ * 2.9 (for `type1' and `t1cid' modules)
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @property:
+ * no-long-family-names
+ *
+ * @description:
+ * If PCF_CONFIG_OPTION_LONG_FAMILY_NAMES is active while compiling
+ * FreeType, the PCF driver constructs long family names.
+ *
+ * There are many PCF fonts just called `Fixed' which look completely
+ * different, and which have nothing to do with each other. When
+ * selecting `Fixed' in KDE or Gnome one gets results that appear rather
+ * random, the style changes often if one changes the size and one
+ * cannot select some fonts at all. The improve this situation, the PCF
+ * module prepends the foundry name (plus a space) to the family name.
+ * It also checks whether there are `wide' characters; all put together,
+ * family names like `Sony Fixed' or `Misc Fixed Wide' are constructed.
+ *
+ * If `no-long-family-names' is set, this feature gets switched off.
+ *
+ * {
+ * FT_Library library;
+ * FT_Bool no_long_family_names = TRUE;
+ *
+ *
+ * FT_Init_FreeType( &library );
+ *
+ * FT_Property_Set( library, "pcf",
+ * "no-long-family-names",
+ * &no_long_family_names );
+ * }
+ *
+ * @note:
+ * This property can be used with @FT_Property_Get also.
+ *
+ * This property can be set via the `FREETYPE_PROPERTIES' environment
+ * variable (using values 1 and 0 for `on' and `off', respectively).
+ *
+ * @since:
+ * 2.8
+ */
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * TT_INTERPRETER_VERSION_XXX
+ *
+ * @description:
+ * A list of constants used for the @interpreter-version property to
+ * select the hinting engine for Truetype fonts.
+ *
+ * The numeric value in the constant names represents the version
+ * number as returned by the `GETINFO' bytecode instruction.
+ *
+ * @values:
+ * TT_INTERPRETER_VERSION_35 ::
+ * Version~35 corresponds to MS rasterizer v.1.7 as used e.g. in
+ * Windows~98; only grayscale and B/W rasterizing is supported.
+ *
+ * TT_INTERPRETER_VERSION_38 ::
+ * Version~38 corresponds to MS rasterizer v.1.9; it is roughly
+ * equivalent to the hinting provided by DirectWrite ClearType (as can
+ * be found, for example, in the Internet Explorer~9 running on
+ * Windows~7). It is used in FreeType to select the `Infinality'
+ * subpixel hinting code. The code may be removed in a future
+ * version.
+ *
+ * TT_INTERPRETER_VERSION_40 ::
+ * Version~40 corresponds to MS rasterizer v.2.1; it is roughly
+ * equivalent to the hinting provided by DirectWrite ClearType (as can
+ * be found, for example, in Microsoft's Edge Browser on Windows~10).
+ * It is used in FreeType to select the `minimal' subpixel hinting
+ * code, a stripped-down and higher performance version of the
+ * `Infinality' code.
+ *
+ * @note:
+ * This property controls the behaviour of the bytecode interpreter
+ * and thus how outlines get hinted. It does *not* control how glyph
+ * get rasterized! In particular, it does not control subpixel color
+ * filtering.
+ *
+ * If FreeType has not been compiled with the configuration option
+ * TT_CONFIG_OPTION_SUBPIXEL_HINTING, selecting version~38 or~40 causes
+ * an `FT_Err_Unimplemented_Feature' error.
+ *
+ * Depending on the graphics framework, Microsoft uses different
+ * bytecode and rendering engines. As a consequence, the version
+ * numbers returned by a call to the `GETINFO' bytecode instruction are
+ * more convoluted than desired.
+ *
+ * Here are two tables that try to shed some light on the possible
+ * values for the MS rasterizer engine, together with the additional
+ * features introduced by it.
+ *
+ * {
+ * GETINFO framework version feature
+ * -------------------------------------------------------------------
+ * 3 GDI (Win 3.1), v1.0 16-bit, first version
+ * TrueImage
+ * 33 GDI (Win NT 3.1), v1.5 32-bit
+ * HP Laserjet
+ * 34 GDI (Win 95) v1.6 font smoothing,
+ * new SCANTYPE opcode
+ * 35 GDI (Win 98/2000) v1.7 (UN)SCALED_COMPONENT_OFFSET
+ * bits in composite glyphs
+ * 36 MGDI (Win CE 2) v1.6+ classic ClearType
+ * 37 GDI (XP and later), v1.8 ClearType
+ * GDI+ old (before Vista)
+ * 38 GDI+ old (Vista, Win 7), v1.9 subpixel ClearType,
+ * WPF Y-direction ClearType,
+ * additional error checking
+ * 39 DWrite (before Win 8) v2.0 subpixel ClearType flags
+ * in GETINFO opcode,
+ * bug fixes
+ * 40 GDI+ (after Win 7), v2.1 Y-direction ClearType flag
+ * DWrite (Win 8) in GETINFO opcode,
+ * Gray ClearType
+ * }
+ *
+ * The `version' field gives a rough orientation only, since some
+ * applications provided certain features much earlier (as an example,
+ * Microsoft Reader used subpixel and Y-direction ClearType already in
+ * Windows 2000). Similarly, updates to a given framework might include
+ * improved hinting support.
+ *
+ * {
+ * version sampling rendering comment
+ * x y x y
+ * --------------------------------------------------------------
+ * v1.0 normal normal B/W B/W bi-level
+ * v1.6 high high gray gray grayscale
+ * v1.8 high normal color-filter B/W (GDI) ClearType
+ * v1.9 high high color-filter gray Color ClearType
+ * v2.1 high normal gray B/W Gray ClearType
+ * v2.1 high high gray gray Gray ClearType
+ * }
+ *
+ * Color and Gray ClearType are the two available variants of
+ * `Y-direction ClearType', meaning grayscale rasterization along the
+ * Y-direction; the name used in the TrueType specification for this
+ * feature is `symmetric smoothing'. `Classic ClearType' is the
+ * original algorithm used before introducing a modified version in
+ * Win~XP. Another name for v1.6's grayscale rendering is `font
+ * smoothing', and `Color ClearType' is sometimes also called `DWrite
+ * ClearType'. To differentiate between today's Color ClearType and the
+ * earlier ClearType variant with B/W rendering along the vertical axis,
+ * the latter is sometimes called `GDI ClearType'.
+ *
+ * `Normal' and `high' sampling describe the (virtual) resolution to
+ * access the rasterized outline after the hinting process. `Normal'
+ * means 1 sample per grid line (i.e., B/W). In the current Microsoft
+ * implementation, `high' means an extra virtual resolution of 16x16 (or
+ * 16x1) grid lines per pixel for bytecode instructions like `MIRP'.
+ * After hinting, these 16 grid lines are mapped to 6x5 (or 6x1) grid
+ * lines for color filtering if Color ClearType is activated.
+ *
+ * Note that `Gray ClearType' is essentially the same as v1.6's
+ * grayscale rendering. However, the GETINFO instruction handles it
+ * differently: v1.6 returns bit~12 (hinting for grayscale), while v2.1
+ * returns bits~13 (hinting for ClearType), 18 (symmetrical smoothing),
+ * and~19 (Gray ClearType). Also, this mode respects bits 2 and~3 for
+ * the version~1 gasp table exclusively (like Color ClearType), while
+ * v1.6 only respects the values of version~0 (bits 0 and~1).
+ *
+ * Keep in mind that the features of the above interpreter versions
+ * might not map exactly to FreeType features or behavior because it is
+ * a fundamentally different library with different internals.
+ *
+ */
+#define TT_INTERPRETER_VERSION_35 35
+#define TT_INTERPRETER_VERSION_38 38
+#define TT_INTERPRETER_VERSION_40 40
+
+
+ /**************************************************************************
+ *
+ * @property:
+ * interpreter-version
+ *
+ * @description:
+ * Currently, three versions are available, two representing the
+ * bytecode interpreter with subpixel hinting support (old `Infinality'
+ * code and new stripped-down and higher performance `minimal' code) and
+ * one without, respectively. The default is subpixel support if
+ * TT_CONFIG_OPTION_SUBPIXEL_HINTING is defined, and no subpixel support
+ * otherwise (since it isn't available then).
+ *
+ * If subpixel hinting is on, many TrueType bytecode instructions behave
+ * differently compared to B/W or grayscale rendering (except if `native
+ * ClearType' is selected by the font). Microsoft's main idea is to
+ * render at a much increased horizontal resolution, then sampling down
+ * the created output to subpixel precision. However, many older fonts
+ * are not suited to this and must be specially taken care of by
+ * applying (hardcoded) tweaks in Microsoft's interpreter.
+ *
+ * Details on subpixel hinting and some of the necessary tweaks can be
+ * found in Greg Hitchcock's whitepaper at
+ * `https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx'.
+ * Note that FreeType currently doesn't really `subpixel hint' (6x1, 6x2,
+ * or 6x5 supersampling) like discussed in the paper. Depending on the
+ * chosen interpreter, it simply ignores instructions on vertical stems
+ * to arrive at very similar results.
+ *
+ * The following example code demonstrates how to deactivate subpixel
+ * hinting (omitting the error handling).
+ *
+ * {
+ * FT_Library library;
+ * FT_Face face;
+ * FT_UInt interpreter_version = TT_INTERPRETER_VERSION_35;
+ *
+ *
+ * FT_Init_FreeType( &library );
+ *
+ * FT_Property_Set( library, "truetype",
+ * "interpreter-version",
+ * &interpreter_version );
+ * }
+ *
+ * @note:
+ * This property can be used with @FT_Property_Get also.
+ *
+ * This property can be set via the `FREETYPE_PROPERTIES' environment
+ * variable (using values `35', `38', or `40').
+ *
+ * @since:
+ * 2.5
+ */
+
+
+ /**************************************************************************
+ *
+ * @property:
+ * glyph-to-script-map
+ *
+ * @description:
+ * *Experimental* *only*
+ *
+ * The auto-hinter provides various script modules to hint glyphs.
+ * Examples of supported scripts are Latin or CJK. Before a glyph is
+ * auto-hinted, the Unicode character map of the font gets examined, and
+ * the script is then determined based on Unicode character ranges, see
+ * below.
+ *
+ * OpenType fonts, however, often provide much more glyphs than
+ * character codes (small caps, superscripts, ligatures, swashes, etc.),
+ * to be controlled by so-called `features'. Handling OpenType features
+ * can be quite complicated and thus needs a separate library on top of
+ * FreeType.
+ *
+ * The mapping between glyph indices and scripts (in the auto-hinter
+ * sense, see the @FT_AUTOHINTER_SCRIPT_XXX values) is stored as an
+ * array with `num_glyphs' elements, as found in the font's @FT_Face
+ * structure. The `glyph-to-script-map' property returns a pointer to
+ * this array, which can be modified as needed. Note that the
+ * modification should happen before the first glyph gets processed by
+ * the auto-hinter so that the global analysis of the font shapes
+ * actually uses the modified mapping.
+ *
+ * The following example code demonstrates how to access it (omitting
+ * the error handling).
+ *
+ * {
+ * FT_Library library;
+ * FT_Face face;
+ * FT_Prop_GlyphToScriptMap prop;
+ *
+ *
+ * FT_Init_FreeType( &library );
+ * FT_New_Face( library, "foo.ttf", 0, &face );
+ *
+ * prop.face = face;
+ *
+ * FT_Property_Get( library, "autofitter",
+ * "glyph-to-script-map", &prop );
+ *
+ * // adjust `prop.map' as needed right here
+ *
+ * FT_Load_Glyph( face, ..., FT_LOAD_FORCE_AUTOHINT );
+ * }
+ *
+ * @since:
+ * 2.4.11
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_AUTOHINTER_SCRIPT_XXX
+ *
+ * @description:
+ * *Experimental* *only*
+ *
+ * A list of constants used for the @glyph-to-script-map property to
+ * specify the script submodule the auto-hinter should use for hinting a
+ * particular glyph.
+ *
+ * @values:
+ * FT_AUTOHINTER_SCRIPT_NONE ::
+ * Don't auto-hint this glyph.
+ *
+ * FT_AUTOHINTER_SCRIPT_LATIN ::
+ * Apply the latin auto-hinter. For the auto-hinter, `latin' is a
+ * very broad term, including Cyrillic and Greek also since characters
+ * from those scripts share the same design constraints.
+ *
+ * By default, characters from the following Unicode ranges are
+ * assigned to this submodule.
+ *
+ * {
+ * U+0020 - U+007F // Basic Latin (no control characters)
+ * U+00A0 - U+00FF // Latin-1 Supplement (no control characters)
+ * U+0100 - U+017F // Latin Extended-A
+ * U+0180 - U+024F // Latin Extended-B
+ * U+0250 - U+02AF // IPA Extensions
+ * U+02B0 - U+02FF // Spacing Modifier Letters
+ * U+0300 - U+036F // Combining Diacritical Marks
+ * U+0370 - U+03FF // Greek and Coptic
+ * U+0400 - U+04FF // Cyrillic
+ * U+0500 - U+052F // Cyrillic Supplement
+ * U+1D00 - U+1D7F // Phonetic Extensions
+ * U+1D80 - U+1DBF // Phonetic Extensions Supplement
+ * U+1DC0 - U+1DFF // Combining Diacritical Marks Supplement
+ * U+1E00 - U+1EFF // Latin Extended Additional
+ * U+1F00 - U+1FFF // Greek Extended
+ * U+2000 - U+206F // General Punctuation
+ * U+2070 - U+209F // Superscripts and Subscripts
+ * U+20A0 - U+20CF // Currency Symbols
+ * U+2150 - U+218F // Number Forms
+ * U+2460 - U+24FF // Enclosed Alphanumerics
+ * U+2C60 - U+2C7F // Latin Extended-C
+ * U+2DE0 - U+2DFF // Cyrillic Extended-A
+ * U+2E00 - U+2E7F // Supplemental Punctuation
+ * U+A640 - U+A69F // Cyrillic Extended-B
+ * U+A720 - U+A7FF // Latin Extended-D
+ * U+FB00 - U+FB06 // Alphab. Present. Forms (Latin Ligatures)
+ * U+1D400 - U+1D7FF // Mathematical Alphanumeric Symbols
+ * U+1F100 - U+1F1FF // Enclosed Alphanumeric Supplement
+ * }
+ *
+ * FT_AUTOHINTER_SCRIPT_CJK ::
+ * Apply the CJK auto-hinter, covering Chinese, Japanese, Korean, old
+ * Vietnamese, and some other scripts.
+ *
+ * By default, characters from the following Unicode ranges are
+ * assigned to this submodule.
+ *
+ * {
+ * U+1100 - U+11FF // Hangul Jamo
+ * U+2E80 - U+2EFF // CJK Radicals Supplement
+ * U+2F00 - U+2FDF // Kangxi Radicals
+ * U+2FF0 - U+2FFF // Ideographic Description Characters
+ * U+3000 - U+303F // CJK Symbols and Punctuation
+ * U+3040 - U+309F // Hiragana
+ * U+30A0 - U+30FF // Katakana
+ * U+3100 - U+312F // Bopomofo
+ * U+3130 - U+318F // Hangul Compatibility Jamo
+ * U+3190 - U+319F // Kanbun
+ * U+31A0 - U+31BF // Bopomofo Extended
+ * U+31C0 - U+31EF // CJK Strokes
+ * U+31F0 - U+31FF // Katakana Phonetic Extensions
+ * U+3200 - U+32FF // Enclosed CJK Letters and Months
+ * U+3300 - U+33FF // CJK Compatibility
+ * U+3400 - U+4DBF // CJK Unified Ideographs Extension A
+ * U+4DC0 - U+4DFF // Yijing Hexagram Symbols
+ * U+4E00 - U+9FFF // CJK Unified Ideographs
+ * U+A960 - U+A97F // Hangul Jamo Extended-A
+ * U+AC00 - U+D7AF // Hangul Syllables
+ * U+D7B0 - U+D7FF // Hangul Jamo Extended-B
+ * U+F900 - U+FAFF // CJK Compatibility Ideographs
+ * U+FE10 - U+FE1F // Vertical forms
+ * U+FE30 - U+FE4F // CJK Compatibility Forms
+ * U+FF00 - U+FFEF // Halfwidth and Fullwidth Forms
+ * U+1B000 - U+1B0FF // Kana Supplement
+ * U+1D300 - U+1D35F // Tai Xuan Hing Symbols
+ * U+1F200 - U+1F2FF // Enclosed Ideographic Supplement
+ * U+20000 - U+2A6DF // CJK Unified Ideographs Extension B
+ * U+2A700 - U+2B73F // CJK Unified Ideographs Extension C
+ * U+2B740 - U+2B81F // CJK Unified Ideographs Extension D
+ * U+2F800 - U+2FA1F // CJK Compatibility Ideographs Supplement
+ * }
+ *
+ * FT_AUTOHINTER_SCRIPT_INDIC ::
+ * Apply the indic auto-hinter, covering all major scripts from the
+ * Indian sub-continent and some other related scripts like Thai, Lao,
+ * or Tibetan.
+ *
+ * By default, characters from the following Unicode ranges are
+ * assigned to this submodule.
+ *
+ * {
+ * U+0900 - U+0DFF // Indic Range
+ * U+0F00 - U+0FFF // Tibetan
+ * U+1900 - U+194F // Limbu
+ * U+1B80 - U+1BBF // Sundanese
+ * U+A800 - U+A82F // Syloti Nagri
+ * U+ABC0 - U+ABFF // Meetei Mayek
+ * U+11800 - U+118DF // Sharada
+ * }
+ *
+ * Note that currently Indic support is rudimentary only, missing blue
+ * zone support.
+ *
+ * @since:
+ * 2.4.11
+ *
+ */
+#define FT_AUTOHINTER_SCRIPT_NONE 0
+#define FT_AUTOHINTER_SCRIPT_LATIN 1
+#define FT_AUTOHINTER_SCRIPT_CJK 2
+#define FT_AUTOHINTER_SCRIPT_INDIC 3
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Prop_GlyphToScriptMap
+ *
+ * @description:
+ * *Experimental* *only*
+ *
+ * The data exchange structure for the @glyph-to-script-map property.
+ *
+ * @since:
+ * 2.4.11
+ *
+ */
+ typedef struct FT_Prop_GlyphToScriptMap_
+ {
+ FT_Face face;
+ FT_UShort* map;
+
+ } FT_Prop_GlyphToScriptMap;
+
+
+ /**************************************************************************
+ *
+ * @property:
+ * fallback-script
+ *
+ * @description:
+ * *Experimental* *only*
+ *
+ * If no auto-hinter script module can be assigned to a glyph, a
+ * fallback script gets assigned to it (see also the
+ * @glyph-to-script-map property). By default, this is
+ * @FT_AUTOHINTER_SCRIPT_CJK. Using the `fallback-script' property,
+ * this fallback value can be changed.
+ *
+ * {
+ * FT_Library library;
+ * FT_UInt fallback_script = FT_AUTOHINTER_SCRIPT_NONE;
+ *
+ *
+ * FT_Init_FreeType( &library );
+ *
+ * FT_Property_Set( library, "autofitter",
+ * "fallback-script", &fallback_script );
+ * }
+ *
+ * @note:
+ * This property can be used with @FT_Property_Get also.
+ *
+ * It's important to use the right timing for changing this value: The
+ * creation of the glyph-to-script map that eventually uses the
+ * fallback script value gets triggered either by setting or reading a
+ * face-specific property like @glyph-to-script-map, or by auto-hinting
+ * any glyph from that face. In particular, if you have already created
+ * an @FT_Face structure but not loaded any glyph (using the
+ * auto-hinter), a change of the fallback script will affect this face.
+ *
+ * @since:
+ * 2.4.11
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @property:
+ * default-script
+ *
+ * @description:
+ * *Experimental* *only*
+ *
+ * If FreeType gets compiled with FT_CONFIG_OPTION_USE_HARFBUZZ to make
+ * the HarfBuzz library access OpenType features for getting better
+ * glyph coverages, this property sets the (auto-fitter) script to be
+ * used for the default (OpenType) script data of a font's GSUB table.
+ * Features for the default script are intended for all scripts not
+ * explicitly handled in GSUB; an example is a `dlig' feature,
+ * containing the combination of the characters `T', `E', and `L' to
+ * form a `TEL' ligature.
+ *
+ * By default, this is @FT_AUTOHINTER_SCRIPT_LATIN. Using the
+ * `default-script' property, this default value can be changed.
+ *
+ * {
+ * FT_Library library;
+ * FT_UInt default_script = FT_AUTOHINTER_SCRIPT_NONE;
+ *
+ *
+ * FT_Init_FreeType( &library );
+ *
+ * FT_Property_Set( library, "autofitter",
+ * "default-script", &default_script );
+ * }
+ *
+ * @note:
+ * This property can be used with @FT_Property_Get also.
+ *
+ * It's important to use the right timing for changing this value: The
+ * creation of the glyph-to-script map that eventually uses the
+ * default script value gets triggered either by setting or reading a
+ * face-specific property like @glyph-to-script-map, or by auto-hinting
+ * any glyph from that face. In particular, if you have already created
+ * an @FT_Face structure but not loaded any glyph (using the
+ * auto-hinter), a change of the default script will affect this face.
+ *
+ * @since:
+ * 2.5.3
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @property:
+ * increase-x-height
+ *
+ * @description:
+ * For ppem values in the range 6~<= ppem <= `increase-x-height', round
+ * up the font's x~height much more often than normally. If the value
+ * is set to~0, which is the default, this feature is switched off. Use
+ * this property to improve the legibility of small font sizes if
+ * necessary.
+ *
+ * {
+ * FT_Library library;
+ * FT_Face face;
+ * FT_Prop_IncreaseXHeight prop;
+ *
+ *
+ * FT_Init_FreeType( &library );
+ * FT_New_Face( library, "foo.ttf", 0, &face );
+ * FT_Set_Char_Size( face, 10 * 64, 0, 72, 0 );
+ *
+ * prop.face = face;
+ * prop.limit = 14;
+ *
+ * FT_Property_Set( library, "autofitter",
+ * "increase-x-height", &prop );
+ * }
+ *
+ * @note:
+ * This property can be used with @FT_Property_Get also.
+ *
+ * Set this value right after calling @FT_Set_Char_Size, but before
+ * loading any glyph (using the auto-hinter).
+ *
+ * @since:
+ * 2.4.11
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Prop_IncreaseXHeight
+ *
+ * @description:
+ * The data exchange structure for the @increase-x-height property.
+ *
+ */
+ typedef struct FT_Prop_IncreaseXHeight_
+ {
+ FT_Face face;
+ FT_UInt limit;
+
+ } FT_Prop_IncreaseXHeight;
+
+
+ /**************************************************************************
+ *
+ * @property:
+ * warping
+ *
+ * @description:
+ * *Experimental* *only*
+ *
+ * If FreeType gets compiled with option AF_CONFIG_OPTION_USE_WARPER to
+ * activate the warp hinting code in the auto-hinter, this property
+ * switches warping on and off.
+ *
+ * Warping only works in `normal' auto-hinting mode replacing it.
+ * The idea of the code is to slightly scale and shift a glyph along
+ * the non-hinted dimension (which is usually the horizontal axis) so
+ * that as much of its segments are aligned (more or less) to the grid.
+ * To find out a glyph's optimal scaling and shifting value, various
+ * parameter combinations are tried and scored.
+ *
+ * By default, warping is off. The example below shows how to switch on
+ * warping (omitting the error handling).
+ *
+ * {
+ * FT_Library library;
+ * FT_Bool warping = 1;
+ *
+ *
+ * FT_Init_FreeType( &library );
+ *
+ * FT_Property_Set( library, "autofitter",
+ * "warping", &warping );
+ * }
+ *
+ * @note:
+ * This property can be used with @FT_Property_Get also.
+ *
+ * This property can be set via the `FREETYPE_PROPERTIES' environment
+ * variable (using values 1 and 0 for `on' and `off', respectively).
+ *
+ * The warping code can also change advance widths. Have a look at the
+ * `lsb_delta' and `rsb_delta' fields in the @FT_GlyphSlotRec structure
+ * for details on improving inter-glyph distances while rendering.
+ *
+ * Since warping is a global property of the auto-hinter it is best to
+ * change its value before rendering any face. Otherwise, you should
+ * reload all faces that get auto-hinted in `normal' hinting mode.
+ *
+ * @since:
+ * 2.6
+ *
+ */
+
+
+ /* */
+
+
+FT_END_HEADER
+
+
+#endif /* FTDRIVER_H_ */
+
+
+/* END */
diff --git a/thirdparty/freetype/include/freetype/fterrdef.h b/thirdparty/freetype/include/freetype/fterrdef.h
index 6a6dc85b87..8ffd346ca8 100644
--- a/thirdparty/freetype/include/freetype/fterrdef.h
+++ b/thirdparty/freetype/include/freetype/fterrdef.h
@@ -4,7 +4,7 @@
/* */
/* FreeType error codes (specification). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/fterrors.h b/thirdparty/freetype/include/freetype/fterrors.h
index ae382c419f..f6ee5c24e2 100644
--- a/thirdparty/freetype/include/freetype/fterrors.h
+++ b/thirdparty/freetype/include/freetype/fterrors.h
@@ -4,7 +4,7 @@
/* */
/* FreeType error code handling (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/ftfntfmt.h b/thirdparty/freetype/include/freetype/ftfntfmt.h
index 337758328a..cc86efac23 100644
--- a/thirdparty/freetype/include/freetype/ftfntfmt.h
+++ b/thirdparty/freetype/include/freetype/ftfntfmt.h
@@ -4,7 +4,7 @@
/* */
/* Support functions for font formats. */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/ftgasp.h b/thirdparty/freetype/include/freetype/ftgasp.h
index ce18d64784..fc1248ff48 100644
--- a/thirdparty/freetype/include/freetype/ftgasp.h
+++ b/thirdparty/freetype/include/freetype/ftgasp.h
@@ -4,7 +4,7 @@
/* */
/* Access of TrueType's `gasp' table (specification). */
/* */
-/* Copyright 2007-2017 by */
+/* Copyright 2007-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -29,6 +29,9 @@
#endif
+FT_BEGIN_HEADER
+
+
/***************************************************************************
*
* @section:
@@ -131,6 +134,8 @@
/* */
+FT_END_HEADER
+
#endif /* FTGASP_H_ */
diff --git a/thirdparty/freetype/include/freetype/ftglyph.h b/thirdparty/freetype/include/freetype/ftglyph.h
index db1a2c8ba5..5f3fc009cd 100644
--- a/thirdparty/freetype/include/freetype/ftglyph.h
+++ b/thirdparty/freetype/include/freetype/ftglyph.h
@@ -4,7 +4,7 @@
/* */
/* FreeType convenience functions to handle glyphs (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -347,10 +347,10 @@ FT_BEGIN_HEADER
/* */
/* <Description> */
/* Return a glyph's `control box'. The control box encloses all the */
- /* outline's points, including Bézier control points. Though it */
+ /* outline's points, including Bezier 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 */
- /* that contains Bézier outside arcs). */
+ /* that contains Bezier 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 */
diff --git a/thirdparty/freetype/include/freetype/ftgxval.h b/thirdparty/freetype/include/freetype/ftgxval.h
index f239c71eb1..8382d59954 100644
--- a/thirdparty/freetype/include/freetype/ftgxval.h
+++ b/thirdparty/freetype/include/freetype/ftgxval.h
@@ -4,7 +4,7 @@
/* */
/* FreeType API for validating TrueTypeGX/AAT tables (specification). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* Masatake YAMATO, Redhat K.K, */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
@@ -101,15 +101,15 @@ FT_BEGIN_HEADER
* 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)
+#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 )
+#define FT_VALIDATE_GX_START 0x4000
+#define FT_VALIDATE_GX_BITFIELD( tag ) \
+ ( FT_VALIDATE_GX_START << FT_VALIDATE_##tag##_INDEX )
/**********************************************************************
diff --git a/thirdparty/freetype/include/freetype/ftgzip.h b/thirdparty/freetype/include/freetype/ftgzip.h
index bd5ceaab9f..db033da0ed 100644
--- a/thirdparty/freetype/include/freetype/ftgzip.h
+++ b/thirdparty/freetype/include/freetype/ftgzip.h
@@ -4,7 +4,7 @@
/* */
/* Gzip-compressed stream support. */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -129,6 +129,9 @@ FT_BEGIN_HEADER
* @note:
* This function may return `FT_Err_Unimplemented_Feature' if your build
* of FreeType was not compiled with zlib support.
+ *
+ * @since:
+ * 2.5.1
*/
FT_EXPORT( FT_Error )
FT_Gzip_Uncompress( FT_Memory memory,
diff --git a/thirdparty/freetype/include/freetype/ftimage.h b/thirdparty/freetype/include/freetype/ftimage.h
index 1c789e5a44..79ede1959d 100644
--- a/thirdparty/freetype/include/freetype/ftimage.h
+++ b/thirdparty/freetype/include/freetype/ftimage.h
@@ -5,7 +5,7 @@
/* FreeType glyph image formats and default raster interface */
/* (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -169,13 +169,13 @@ FT_BEGIN_HEADER
/* @FT_RENDER_MODE_LCD_V. */
/* */
/* FT_PIXEL_MODE_BGRA :: */
- /* An image with four 8-bit channels per pixel, representing a */
- /* color image (such as emoticons) with alpha channel. For each */
- /* pixel, the format is BGRA, which means, the blue channel comes */
- /* first in memory. The color channels are pre-multiplied and in */
- /* the sRGB colorspace. For example, full red at half-translucent */
- /* opacity will be represented as `00,00,80,80', not `00,00,FF,80'. */
- /* See also @FT_LOAD_COLOR. */
+ /* [Since 2.5] An image with four 8-bit channels per pixel, */
+ /* representing a color image (such as emoticons) with alpha */
+ /* channel. For each pixel, the format is BGRA, which means, the */
+ /* blue channel comes first in memory. The color channels are */
+ /* pre-multiplied and in the sRGB colorspace. For example, full */
+ /* red at half-translucent opacity will be represented as */
+ /* `00,00,80,80', not `00,00,FF,80'. See also @FT_LOAD_COLOR. */
/* */
typedef enum FT_Pixel_Mode_
{
@@ -301,11 +301,11 @@ FT_BEGIN_HEADER
/* 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 */
+ /* i.e., a Bezier 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; */
+ /* it indicates a third-order Bezier arc control point; */
/* and a second-order control point if unset. */
/* */
/* If bit~2 is set, bits 5-7 contain the drop-out mode */
@@ -532,7 +532,7 @@ FT_BEGIN_HEADER
/* 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 */
+ /* A `conic to' is emitted to indicate a second-order Bezier arc in */
/* the outline. */
/* */
/* <Input> */
@@ -564,12 +564,12 @@ FT_BEGIN_HEADER
/* 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. */
+ /* A `cubic to' is emitted to indicate a third-order Bezier arc. */
/* */
/* <Input> */
- /* control1 :: A pointer to the first Bézier control point. */
+ /* control1 :: A pointer to the first Bezier control point. */
/* */
- /* control2 :: A pointer to the second Bézier control point. */
+ /* control2 :: A pointer to the second Bezier control point. */
/* */
/* to :: A pointer to the target end point. */
/* */
@@ -595,16 +595,16 @@ FT_BEGIN_HEADER
/* */
/* <Description> */
/* A structure to hold various function pointers used during outline */
- /* decomposition in order to emit segments, conic, and cubic Béziers. */
+ /* decomposition in order to emit segments, conic, and cubic Beziers. */
/* */
/* <Fields> */
/* move_to :: The `move to' emitter. */
/* */
/* line_to :: The segment emitter. */
/* */
- /* conic_to :: The second-order Bézier arc emitter. */
+ /* conic_to :: The second-order Bezier arc emitter. */
/* */
- /* cubic_to :: The third-order Bézier arc emitter. */
+ /* cubic_to :: The third-order Bezier arc emitter. */
/* */
/* shift :: The shift that is applied to coordinates before they */
/* are sent to the emitter. */
@@ -701,7 +701,7 @@ FT_BEGIN_HEADER
/* */
/* 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 */
+ /* and Bezier 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. */
/* */
diff --git a/thirdparty/freetype/include/freetype/ftincrem.h b/thirdparty/freetype/include/freetype/ftincrem.h
index f6ae2baed6..44619f941e 100644
--- a/thirdparty/freetype/include/freetype/ftincrem.h
+++ b/thirdparty/freetype/include/freetype/ftincrem.h
@@ -4,7 +4,7 @@
/* */
/* FreeType incremental loading (specification). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -21,6 +21,7 @@
#include <ft2build.h>
#include FT_FREETYPE_H
+#include FT_PARAMETER_TAGS_H
#ifdef FREETYPE_H
#error "freetype.h of FreeType 1 has been loaded!"
@@ -331,18 +332,6 @@ FT_BEGIN_HEADER
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' )
-
/* */
diff --git a/thirdparty/freetype/include/freetype/ftlcdfil.h b/thirdparty/freetype/include/freetype/ftlcdfil.h
index bdaf9af906..2a27196cbb 100644
--- a/thirdparty/freetype/include/freetype/ftlcdfil.h
+++ b/thirdparty/freetype/include/freetype/ftlcdfil.h
@@ -5,7 +5,7 @@
/* FreeType API for color filtering of subpixel bitmap glyphs */
/* (specification). */
/* */
-/* Copyright 2006-2017 by */
+/* Copyright 2006-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -22,6 +22,7 @@
#include <ft2build.h>
#include FT_FREETYPE_H
+#include FT_PARAMETER_TAGS_H
#ifdef FREETYPE_H
#error "freetype.h of FreeType 1 has been loaded!"
@@ -280,23 +281,6 @@ FT_BEGIN_HEADER
unsigned char *weights );
- /**************************************************************************
- *
- * @constant:
- * FT_PARAM_TAG_LCD_FILTER_WEIGHTS
- *
- * @description:
- * An @FT_Parameter tag to be used with @FT_Face_Properties. The
- * corresponding argument specifies the five LCD filter weights for a
- * given face (if using @FT_LOAD_TARGET_LCD, for example), overriding
- * the global default values or the values set up with
- * @FT_Library_SetLcdFilterWeights.
- *
- */
-#define FT_PARAM_TAG_LCD_FILTER_WEIGHTS \
- FT_MAKE_TAG( 'l', 'c', 'd', 'f' )
-
-
/*
* @type:
* FT_LcdFiveTapFilter
@@ -305,6 +289,9 @@ FT_BEGIN_HEADER
* A typedef for passing the five LCD filter weights to
* @FT_Face_Properties within an @FT_Parameter structure.
*
+ * @since:
+ * 2.8
+ *
*/
#define FT_LCD_FILTER_FIVE_TAPS 5
diff --git a/thirdparty/freetype/include/freetype/ftlist.h b/thirdparty/freetype/include/freetype/ftlist.h
index 5309cb18ba..117473b96a 100644
--- a/thirdparty/freetype/include/freetype/ftlist.h
+++ b/thirdparty/freetype/include/freetype/ftlist.h
@@ -4,7 +4,7 @@
/* */
/* Generic list support for FreeType (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/ftlzw.h b/thirdparty/freetype/include/freetype/ftlzw.h
index a82c95e7c9..1615912d62 100644
--- a/thirdparty/freetype/include/freetype/ftlzw.h
+++ b/thirdparty/freetype/include/freetype/ftlzw.h
@@ -4,7 +4,7 @@
/* */
/* LZW-compressed stream support. */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/ftmac.h b/thirdparty/freetype/include/freetype/ftmac.h
index a1656eec0e..c1e497ca2d 100644
--- a/thirdparty/freetype/include/freetype/ftmac.h
+++ b/thirdparty/freetype/include/freetype/ftmac.h
@@ -4,7 +4,7 @@
/* */
/* Additional Mac-specific API. */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/ftmm.h b/thirdparty/freetype/include/freetype/ftmm.h
index 80ac98d612..9948102c14 100644
--- a/thirdparty/freetype/include/freetype/ftmm.h
+++ b/thirdparty/freetype/include/freetype/ftmm.h
@@ -4,7 +4,7 @@
/* */
/* FreeType Multiple Master font interface (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -286,7 +286,7 @@ FT_BEGIN_HEADER
/* <Output> */
/* amaster :: The variation descriptor. */
/* Allocates a data structure, which the user must */
- /* deallocate with `free' after use. */
+ /* deallocate with a call to @FT_Done_MM_Var after use. */
/* */
/* <Return> */
/* FreeType error code. 0~means success. */
@@ -299,6 +299,26 @@ FT_BEGIN_HEADER
/*************************************************************************/
/* */
/* <Function> */
+ /* FT_Done_MM_Var */
+ /* */
+ /* <Description> */
+ /* Free the memory allocated by @FT_Get_MM_Var. */
+ /* */
+ /* <Input> */
+ /* library :: A handle of the face's parent library object that was */
+ /* used in the call to @FT_Get_MM_Var to create `amaster'. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0~means success. */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Done_MM_Var( FT_Library library,
+ FT_MM_Var *amaster );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
/* FT_Set_MM_Design_Coordinates */
/* */
/* <Description> */
@@ -323,9 +343,13 @@ FT_BEGIN_HEADER
/* FreeType error code. 0~means success. */
/* */
/* <Note> */
- /* To reset all axes to the default values, call the function with */
- /* `num_coords' set to zero and `coords' set to NULL (new feature in */
- /* FreeType version 2.8.1). */
+ /* [Since 2.8.1] To reset all axes to the default values, call the */
+ /* function with `num_coords' set to zero and `coords' set to NULL. */
+ /* */
+ /* [Since 2.9] If `num_coords' is larger than zero, this function */
+ /* sets the @FT_FACE_FLAG_VARIATION bit in @FT_Face's `face_flags' */
+ /* field (i.e., @FT_IS_VARIATION will return true). If `num_coords' */
+ /* is zero, this bit flag gets unset. */
/* */
FT_EXPORT( FT_Error )
FT_Set_MM_Design_Coordinates( FT_Face face,
@@ -358,9 +382,15 @@ FT_BEGIN_HEADER
/* FreeType error code. 0~means success. */
/* */
/* <Note> */
- /* To reset all axes to the default values, call the function with */
- /* `num_coords' set to zero and `coords' set to NULL (new feature in */
- /* FreeType version 2.8.1). */
+ /* [Since 2.8.1] To reset all axes to the default values, call the */
+ /* function with `num_coords' set to zero and `coords' set to NULL. */
+ /* [Since 2.9] `Default values' means the currently selected named */
+ /* instance (or the base font if no named instance is selected). */
+ /* */
+ /* [Since 2.9] If `num_coords' is larger than zero, this function */
+ /* sets the @FT_FACE_FLAG_VARIATION bit in @FT_Face's `face_flags' */
+ /* field (i.e., @FT_IS_VARIATION will return true). If `num_coords' */
+ /* is zero, this bit flag gets unset. */
/* */
FT_EXPORT( FT_Error )
FT_Set_Var_Design_Coordinates( FT_Face face,
@@ -392,6 +422,9 @@ FT_BEGIN_HEADER
/* <Return> */
/* FreeType error code. 0~means success. */
/* */
+ /* <Since> */
+ /* 2.7.1 */
+ /* */
FT_EXPORT( FT_Error )
FT_Get_Var_Design_Coordinates( FT_Face face,
FT_UInt num_coords,
@@ -427,9 +460,15 @@ FT_BEGIN_HEADER
/* FreeType error code. 0~means success. */
/* */
/* <Note> */
- /* To reset all axes to the default values, call the function with */
- /* `num_coords' set to zero and `coords' set to NULL (new feature in */
- /* FreeType version 2.8.1). */
+ /* [Since 2.8.1] To reset all axes to the default values, call the */
+ /* function with `num_coords' set to zero and `coords' set to NULL. */
+ /* [Since 2.9] `Default values' means the currently selected named */
+ /* instance (or the base font if no named instance is selected). */
+ /* */
+ /* [Since 2.9] If `num_coords' is larger than zero, this function */
+ /* sets the @FT_FACE_FLAG_VARIATION bit in @FT_Face's `face_flags' */
+ /* field (i.e., @FT_IS_VARIATION will return true). If `num_coords' */
+ /* is zero, this bit flag gets unset. */
/* */
FT_EXPORT( FT_Error )
FT_Set_MM_Blend_Coordinates( FT_Face face,
@@ -462,6 +501,9 @@ FT_BEGIN_HEADER
/* <Return> */
/* FreeType error code. 0~means success. */
/* */
+ /* <Since> */
+ /* 2.7.1 */
+ /* */
FT_EXPORT( FT_Error )
FT_Get_MM_Blend_Coordinates( FT_Face face,
FT_UInt num_coords,
@@ -490,6 +532,9 @@ FT_BEGIN_HEADER
/* <Description> */
/* This is another name of @FT_Get_MM_Blend_Coordinates. */
/* */
+ /* <Since> */
+ /* 2.7.1 */
+ /* */
FT_EXPORT( FT_Error )
FT_Get_Var_Blend_Coordinates( FT_Face face,
FT_UInt num_coords,
@@ -509,6 +554,9 @@ FT_BEGIN_HEADER
/* FT_VAR_AXIS_FLAG_HIDDEN :: */
/* The variation axis should not be exposed to user interfaces. */
/* */
+ /* <Since> */
+ /* 2.8.1 */
+ /* */
#define FT_VAR_AXIS_FLAG_HIDDEN 1
@@ -534,11 +582,51 @@ FT_BEGIN_HEADER
/* <Return> */
/* FreeType error code. 0~means success. */
/* */
+ /* <Since> */
+ /* 2.8.1 */
+ /* */
FT_EXPORT( FT_Error )
FT_Get_Var_Axis_Flags( FT_MM_Var* master,
FT_UInt axis_index,
FT_UInt* flags );
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Set_Named_Instance */
+ /* */
+ /* <Description> */
+ /* Set or change the current named instance. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face. */
+ /* */
+ /* instance_index :: The index of the requested instance, starting */
+ /* with value 1. If set to value 0, FreeType */
+ /* switches to font access without a named */
+ /* instance. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0~means success. */
+ /* */
+ /* <Note> */
+ /* The function uses the value of `instance_index' to set bits 16-30 */
+ /* of the face's `face_index' field. It also resets any variation */
+ /* applied to the font, and the @FT_FACE_FLAG_VARIATION bit of the */
+ /* face's `face_flags' field gets reset to zero (i.e., */
+ /* @FT_IS_VARIATION will return false). */
+ /* */
+ /* For Adobe MM fonts (which don't have named instances) this */
+ /* function simply resets the current face to the default instance. */
+ /* */
+ /* <Since> */
+ /* 2.9 */
+ /* */
+ FT_EXPORT( FT_Error )
+ FT_Set_Named_Instance( FT_Face face,
+ FT_UInt instance_index );
+
/* */
diff --git a/thirdparty/freetype/include/freetype/ftmodapi.h b/thirdparty/freetype/include/freetype/ftmodapi.h
index 4147aadf8b..a6eb876ebe 100644
--- a/thirdparty/freetype/include/freetype/ftmodapi.h
+++ b/thirdparty/freetype/include/freetype/ftmodapi.h
@@ -4,7 +4,7 @@
/* */
/* FreeType modules public interface (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -323,16 +323,15 @@ FT_BEGIN_HEADER
* The module name.
*
* property_name ::
- * The property name. Properties are described in the `Synopsis'
- * subsection of the module's documentation.
+ * The property name. Properties are described in section
+ * @properties.
*
* Note that only a few modules have properties.
*
* value ::
* A generic pointer to a variable or structure that gives the new
* value of the property. The exact definition of `value' is
- * dependent on the property; see the `Synopsis' subsection of the
- * module's documentation.
+ * dependent on the property; see section @properties.
*
* @return:
* FreeType error code. 0~means success.
@@ -390,15 +389,14 @@ FT_BEGIN_HEADER
* The module name.
*
* property_name ::
- * The property name. Properties are described in the `Synopsis'
- * subsection of the module's documentation.
+ * The property name. Properties are described in section
+ * @properties.
*
* @inout:
* value ::
* A generic pointer to a variable or structure that gives the
* value of the property. The exact definition of `value' is
- * dependent on the property; see the `Synopsis' subsection of the
- * module's documentation.
+ * dependent on the property; see section @properties.
*
* @return:
* FreeType error code. 0~means success.
@@ -446,8 +444,8 @@ FT_BEGIN_HEADER
/* <Description> */
/* If compilation option FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES is */
/* set, this function reads the `FREETYPE_PROPERTIES' environment */
- /* variable to control driver properties. See sections @auto_hinter, */
- /* @cff_driver, @pcf_driver, and @tt_driver for more. */
+ /* variable to control driver properties. See section @properties */
+ /* for more. */
/* */
/* If the compilation option is not set, this function does nothing. */
/* */
@@ -475,6 +473,9 @@ FT_BEGIN_HEADER
/* <InOut> */
/* library :: A handle to a new library object. */
/* */
+ /* <Since> */
+ /* 2.8 */
+ /* */
FT_EXPORT( void )
FT_Set_Default_Properties( FT_Library library );
diff --git a/thirdparty/freetype/include/freetype/ftmoderr.h b/thirdparty/freetype/include/freetype/ftmoderr.h
index 7f608375e8..e0fc1312bd 100644
--- a/thirdparty/freetype/include/freetype/ftmoderr.h
+++ b/thirdparty/freetype/include/freetype/ftmoderr.h
@@ -4,7 +4,7 @@
/* */
/* FreeType module error offsets (specification). */
/* */
-/* Copyright 2001-2017 by */
+/* Copyright 2001-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/ftotval.h b/thirdparty/freetype/include/freetype/ftotval.h
index b5d27cfe74..26731c2b9f 100644
--- a/thirdparty/freetype/include/freetype/ftotval.h
+++ b/thirdparty/freetype/include/freetype/ftotval.h
@@ -4,7 +4,7 @@
/* */
/* FreeType API for validating OpenType tables (specification). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/ftoutln.h b/thirdparty/freetype/include/freetype/ftoutln.h
index 56f56a9603..89389a49b7 100644
--- a/thirdparty/freetype/include/freetype/ftoutln.h
+++ b/thirdparty/freetype/include/freetype/ftoutln.h
@@ -5,7 +5,7 @@
/* Support for the FT_Outline type used to store glyph shapes of */
/* most scalable font formats (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -89,7 +89,7 @@ FT_BEGIN_HEADER
/* */
/* <Description> */
/* Walk over an outline's structure to decompose it into individual */
- /* segments and Bézier arcs. This function also emits `move to' */
+ /* segments and Bezier arcs. This function also emits `move to' */
/* operations to indicate the start of new contours in the outline. */
/* */
/* <Input> */
@@ -190,9 +190,6 @@ FT_BEGIN_HEADER
/* 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 );
@@ -232,10 +229,10 @@ FT_BEGIN_HEADER
/* */
/* <Description> */
/* Return an outline's `control box'. The control box encloses all */
- /* the outline's points, including Bézier control points. Though it */
+ /* the outline's points, including Bezier 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 */
- /* that contains Bézier outside arcs). */
+ /* that contains Bezier 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 */
diff --git a/thirdparty/freetype/include/freetype/ftparams.h b/thirdparty/freetype/include/freetype/ftparams.h
new file mode 100644
index 0000000000..5a9006c505
--- /dev/null
+++ b/thirdparty/freetype/include/freetype/ftparams.h
@@ -0,0 +1,205 @@
+/***************************************************************************/
+/* */
+/* ftparams.h */
+/* */
+/* FreeType API for possible FT_Parameter tags (specification only). */
+/* */
+/* Copyright 2017-2018 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef FTPARAMS_H_
+#define FTPARAMS_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:
+ * parameter_tags
+ *
+ * @title:
+ * Parameter Tags
+ *
+ * @abstract:
+ * Macros for driver property and font loading parameter tags.
+ *
+ * @description:
+ * This section contains macros for the @FT_Parameter structure that are
+ * used with various functions to activate some special functionality or
+ * different behaviour of various components of FreeType.
+ *
+ */
+
+
+ /***************************************************************************
+ *
+ * @constant:
+ * FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY
+ *
+ * @description:
+ * A tag for @FT_Parameter to make @FT_Open_Face ignore typographic
+ * family names in the `name' table (introduced in OpenType version
+ * 1.4). Use this for backward compatibility with legacy systems that
+ * have a four-faces-per-family restriction.
+ *
+ * @since:
+ * 2.8
+ *
+ */
+#define FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY \
+ FT_MAKE_TAG( 'i', 'g', 'p', 'f' )
+
+
+ /* this constant is deprecated */
+#define FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY \
+ FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY
+
+
+ /***************************************************************************
+ *
+ * @constant:
+ * FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY
+ *
+ * @description:
+ * A tag for @FT_Parameter to make @FT_Open_Face ignore typographic
+ * subfamily names in the `name' table (introduced in OpenType version
+ * 1.4). Use this for backward compatibility with legacy systems that
+ * have a four-faces-per-family restriction.
+ *
+ * @since:
+ * 2.8
+ *
+ */
+#define FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY \
+ FT_MAKE_TAG( 'i', 'g', 'p', 's' )
+
+
+ /* this constant is deprecated */
+#define FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY \
+ FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY
+
+
+ /***************************************************************************
+ *
+ * @constant:
+ * FT_PARAM_TAG_INCREMENTAL
+ *
+ * @description:
+ * An @FT_Parameter tag to be used with @FT_Open_Face to indicate
+ * incremental glyph loading.
+ *
+ */
+#define FT_PARAM_TAG_INCREMENTAL \
+ FT_MAKE_TAG( 'i', 'n', 'c', 'r' )
+
+
+ /**************************************************************************
+ *
+ * @constant:
+ * FT_PARAM_TAG_LCD_FILTER_WEIGHTS
+ *
+ * @description:
+ * An @FT_Parameter tag to be used with @FT_Face_Properties. The
+ * corresponding argument specifies the five LCD filter weights for a
+ * given face (if using @FT_LOAD_TARGET_LCD, for example), overriding
+ * the global default values or the values set up with
+ * @FT_Library_SetLcdFilterWeights.
+ *
+ * @since:
+ * 2.8
+ *
+ */
+#define FT_PARAM_TAG_LCD_FILTER_WEIGHTS \
+ FT_MAKE_TAG( 'l', 'c', 'd', 'f' )
+
+
+ /**************************************************************************
+ *
+ * @constant:
+ * FT_PARAM_TAG_RANDOM_SEED
+ *
+ * @description:
+ * An @FT_Parameter tag to be used with @FT_Face_Properties. The
+ * corresponding 32bit signed integer argument overrides the font
+ * driver's random seed value with a face-specific one; see
+ * @random-seed.
+ *
+ * @since:
+ * 2.8
+ *
+ */
+#define FT_PARAM_TAG_RANDOM_SEED \
+ FT_MAKE_TAG( 's', 'e', 'e', 'd' )
+
+
+ /**************************************************************************
+ *
+ * @constant:
+ * FT_PARAM_TAG_STEM_DARKENING
+ *
+ * @description:
+ * An @FT_Parameter tag to be used with @FT_Face_Properties. The
+ * corresponding Boolean argument specifies whether to apply stem
+ * darkening, overriding the global default values or the values set up
+ * with @FT_Property_Set (see @no-stem-darkening).
+ *
+ * This is a passive setting that only takes effect if the font driver
+ * or autohinter honors it, which the CFF, Type~1, and CID drivers
+ * always do, but the autohinter only in `light' hinting mode (as of
+ * version 2.9).
+ *
+ * @since:
+ * 2.8
+ *
+ */
+#define FT_PARAM_TAG_STEM_DARKENING \
+ FT_MAKE_TAG( 'd', 'a', 'r', 'k' )
+
+
+ /***************************************************************************
+ *
+ * @constant:
+ * FT_PARAM_TAG_UNPATENTED_HINTING
+ *
+ * @description:
+ * Deprecated, no effect.
+ *
+ * Previously: 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 /* FTPARAMS_H_ */
+
+
+/* END */
diff --git a/thirdparty/freetype/include/freetype/ftpfr.h b/thirdparty/freetype/include/freetype/ftpfr.h
index f2a6ae9349..a69cc482dc 100644
--- a/thirdparty/freetype/include/freetype/ftpfr.h
+++ b/thirdparty/freetype/include/freetype/ftpfr.h
@@ -4,7 +4,7 @@
/* */
/* FreeType API for accessing PFR-specific data (specification only). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -71,7 +71,7 @@ FT_BEGIN_HEADER
*
* 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
+ * in metrics units to device subpixels. This is equivalent to
* `face->size->x_scale', but for metrics only. Optional (parameter
* can be NULL).
*
@@ -123,7 +123,7 @@ FT_BEGIN_HEADER
* 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.
+ * returned by @FT_Get_PFR_Metrics to scale these to device subpixels.
*/
FT_EXPORT( FT_Error )
FT_Get_PFR_Kerning( FT_Face face,
@@ -154,7 +154,7 @@ FT_BEGIN_HEADER
*
* @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).
+ * to convert the advance to device subpixels (i.e., 1/64th of pixels).
*/
FT_EXPORT( FT_Error )
FT_Get_PFR_Advance( FT_Face face,
diff --git a/thirdparty/freetype/include/freetype/ftrender.h b/thirdparty/freetype/include/freetype/ftrender.h
index 960837580a..fa8ad22b98 100644
--- a/thirdparty/freetype/include/freetype/ftrender.h
+++ b/thirdparty/freetype/include/freetype/ftrender.h
@@ -4,7 +4,7 @@
/* */
/* FreeType renderer modules public interface (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -88,7 +88,7 @@ FT_BEGIN_HEADER
typedef FT_Error
(*FT_Renderer_RenderFunc)( FT_Renderer renderer,
FT_GlyphSlot slot,
- FT_UInt mode,
+ FT_Render_Mode mode,
const FT_Vector* origin );
typedef FT_Error
diff --git a/thirdparty/freetype/include/freetype/ftsizes.h b/thirdparty/freetype/include/freetype/ftsizes.h
index 2f3958a857..72cb08bf2a 100644
--- a/thirdparty/freetype/include/freetype/ftsizes.h
+++ b/thirdparty/freetype/include/freetype/ftsizes.h
@@ -4,7 +4,7 @@
/* */
/* FreeType size objects management (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/ftsnames.h b/thirdparty/freetype/include/freetype/ftsnames.h
index a316540576..8eb8d70ff7 100644
--- a/thirdparty/freetype/include/freetype/ftsnames.h
+++ b/thirdparty/freetype/include/freetype/ftsnames.h
@@ -7,7 +7,7 @@
/* */
/* This is _not_ used to retrieve glyph names! */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -25,6 +25,7 @@
#include <ft2build.h>
#include FT_FREETYPE_H
+#include FT_PARAMETER_TAGS_H
#ifdef FREETYPE_H
#error "freetype.h of FreeType 1 has been loaded!"
@@ -189,6 +190,9 @@ FT_BEGIN_HEADER
/* Please refer to the TrueType or OpenType specification for more */
/* details. */
/* */
+ /* <Since> */
+ /* 2.8 */
+ /* */
typedef struct FT_SfntLangTag_
{
FT_Byte* string; /* this string is *not* null-terminated! */
@@ -229,53 +233,15 @@ FT_BEGIN_HEADER
/* invalid format~1 language ID values, FT_Err_Invalid_Argument is */
/* returned. */
/* */
+ /* <Since> */
+ /* 2.8 */
+ /* */
FT_EXPORT( FT_Error )
FT_Get_Sfnt_LangTag( FT_Face face,
FT_UInt langID,
FT_SfntLangTag *alangTag );
- /***************************************************************************
- *
- * @constant:
- * FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY
- *
- * @description:
- * A tag for @FT_Parameter to make @FT_Open_Face ignore typographic
- * family names in the `name' table (introduced in OpenType version
- * 1.4). Use this for backward compatibility with legacy systems that
- * have a four-faces-per-family restriction.
- *
- */
-#define FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY \
- FT_MAKE_TAG( 'i', 'g', 'p', 'f' )
-
-
- /* this constant is deprecated */
-#define FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY \
- FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY
-
-
- /***************************************************************************
- *
- * @constant:
- * FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY
- *
- * @description:
- * A tag for @FT_Parameter to make @FT_Open_Face ignore typographic
- * subfamily names in the `name' table (introduced in OpenType version
- * 1.4). Use this for backward compatibility with legacy systems that
- * have a four-faces-per-family restriction.
- *
- */
-#define FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY \
- FT_MAKE_TAG( 'i', 'g', 'p', 's' )
-
-
- /* this constant is deprecated */
-#define FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY \
- FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY
-
/* */
diff --git a/thirdparty/freetype/include/freetype/ftstroke.h b/thirdparty/freetype/include/freetype/ftstroke.h
index 4a20667c5e..44b6fbe19f 100644
--- a/thirdparty/freetype/include/freetype/ftstroke.h
+++ b/thirdparty/freetype/include/freetype/ftstroke.h
@@ -4,7 +4,7 @@
/* */
/* FreeType path stroker (specification). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -466,7 +466,7 @@ FT_BEGIN_HEADER
* FT_Stroker_ConicTo
*
* @description:
- * `Draw' a single quadratic Bézier in the stroker's current sub-path,
+ * `Draw' a single quadratic Bezier in the stroker's current sub-path,
* from the last position.
*
* @input:
@@ -474,7 +474,7 @@ FT_BEGIN_HEADER
* The target stroker handle.
*
* control ::
- * A pointer to a Bézier control point.
+ * A pointer to a Bezier control point.
*
* to ::
* A pointer to the destination point.
@@ -498,7 +498,7 @@ FT_BEGIN_HEADER
* FT_Stroker_CubicTo
*
* @description:
- * `Draw' a single cubic Bézier in the stroker's current sub-path,
+ * `Draw' a single cubic Bezier in the stroker's current sub-path,
* from the last position.
*
* @input:
@@ -506,10 +506,10 @@ FT_BEGIN_HEADER
* The target stroker handle.
*
* control1 ::
- * A pointer to the first Bézier control point.
+ * A pointer to the first Bezier control point.
*
* control2 ::
- * A pointer to second Bézier control point.
+ * A pointer to second Bezier control point.
*
* to ::
* A pointer to the destination point.
diff --git a/thirdparty/freetype/include/freetype/ftsynth.h b/thirdparty/freetype/include/freetype/ftsynth.h
index 1863fa2383..ff9fb43d96 100644
--- a/thirdparty/freetype/include/freetype/ftsynth.h
+++ b/thirdparty/freetype/include/freetype/ftsynth.h
@@ -5,7 +5,7 @@
/* FreeType synthesizing code for emboldening and slanting */
/* (specification). */
/* */
-/* Copyright 2000-2017 by */
+/* Copyright 2000-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/ftsystem.h b/thirdparty/freetype/include/freetype/ftsystem.h
index 1aa4762ad6..f6b1629ef2 100644
--- a/thirdparty/freetype/include/freetype/ftsystem.h
+++ b/thirdparty/freetype/include/freetype/ftsystem.h
@@ -4,7 +4,7 @@
/* */
/* FreeType low-level system interface definition (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/fttrigon.h b/thirdparty/freetype/include/freetype/fttrigon.h
index 89f0350675..2e3f3f1f73 100644
--- a/thirdparty/freetype/include/freetype/fttrigon.h
+++ b/thirdparty/freetype/include/freetype/fttrigon.h
@@ -4,7 +4,7 @@
/* */
/* FreeType trigonometric functions (specification). */
/* */
-/* Copyright 2001-2017 by */
+/* Copyright 2001-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/fttypes.h b/thirdparty/freetype/include/freetype/fttypes.h
index eab8adaad4..f638c2e54f 100644
--- a/thirdparty/freetype/include/freetype/fttypes.h
+++ b/thirdparty/freetype/include/freetype/fttypes.h
@@ -4,7 +4,7 @@
/* */
/* FreeType simple types definitions (specification only). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -425,7 +425,7 @@ FT_BEGIN_HEADER
/* The address of the FreeType object that is under finalization. */
/* Its client data is accessed through its `generic' field. */
/* */
- typedef void (*FT_Generic_Finalizer)(void* object);
+ typedef void (*FT_Generic_Finalizer)( void* object );
/*************************************************************************/
diff --git a/thirdparty/freetype/include/freetype/ftwinfnt.h b/thirdparty/freetype/include/freetype/ftwinfnt.h
index 1eeef6c8ba..461c65b779 100644
--- a/thirdparty/freetype/include/freetype/ftwinfnt.h
+++ b/thirdparty/freetype/include/freetype/ftwinfnt.h
@@ -4,7 +4,7 @@
/* */
/* FreeType API for accessing Windows fnt-specific data. */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -78,7 +78,7 @@ FT_BEGIN_HEADER
* Mac Roman encoding.
*
* FT_WinFNT_ID_OEM ::
- * From Michael Pöttgen <michael@poettgen.de>:
+ * From Michael Poettgen <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',
diff --git a/thirdparty/freetype/include/freetype/internal/autohint.h b/thirdparty/freetype/include/freetype/internal/autohint.h
index bae83e7384..f4d308f68c 100644
--- a/thirdparty/freetype/include/freetype/internal/autohint.h
+++ b/thirdparty/freetype/include/freetype/internal/autohint.h
@@ -4,7 +4,7 @@
/* */
/* High-level `autohint' module-specific interface (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/internal/cffotypes.h b/thirdparty/freetype/include/freetype/internal/cffotypes.h
new file mode 100644
index 0000000000..57e7591d41
--- /dev/null
+++ b/thirdparty/freetype/include/freetype/internal/cffotypes.h
@@ -0,0 +1,108 @@
+/***************************************************************************/
+/* */
+/* cffotypes.h */
+/* */
+/* Basic OpenType/CFF object type definitions (specification). */
+/* */
+/* Copyright 2017-2018 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef CFFOTYPES_H_
+#define CFFOTYPES_H_
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_CFF_TYPES_H
+#include FT_INTERNAL_TRUETYPE_TYPES_H
+#include FT_SERVICE_POSTSCRIPT_CMAPS_H
+#include FT_INTERNAL_POSTSCRIPT_HINTS_H
+
+
+FT_BEGIN_HEADER
+
+
+ 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;
+
+
+FT_END_HEADER
+
+
+#endif /* CFFOTYPES_H_ */
+
+
+/* END */
diff --git a/thirdparty/freetype/include/freetype/internal/cfftypes.h b/thirdparty/freetype/include/freetype/internal/cfftypes.h
new file mode 100644
index 0000000000..7c07e1a376
--- /dev/null
+++ b/thirdparty/freetype/include/freetype/internal/cfftypes.h
@@ -0,0 +1,412 @@
+/***************************************************************************/
+/* */
+/* cfftypes.h */
+/* */
+/* Basic OpenType/CFF type definitions and interface (specification */
+/* only). */
+/* */
+/* Copyright 1996-2018 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.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
+#include FT_INTERNAL_TYPE1_TYPES_H
+
+
+FT_BEGIN_HEADER
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* CFF_IndexRec */
+ /* */
+ /* <Description> */
+ /* A structure used to model a CFF Index table. */
+ /* */
+ /* <Fields> */
+ /* stream :: The source input stream. */
+ /* */
+ /* start :: The position of the first index byte in the */
+ /* input stream. */
+ /* */
+ /* count :: The number of elements in the index. */
+ /* */
+ /* off_size :: The size in bytes of object offsets in index. */
+ /* */
+ /* data_offset :: The position of first data byte in the index's */
+ /* bytes. */
+ /* */
+ /* data_size :: The size of the data table in this index. */
+ /* */
+ /* offsets :: A table of element offsets in the index. Must be */
+ /* loaded explicitly. */
+ /* */
+ /* bytes :: If the index is loaded in memory, its bytes. */
+ /* */
+ typedef struct CFF_IndexRec_
+ {
+ FT_Stream stream;
+ FT_ULong start;
+ FT_UInt hdr_size;
+ FT_UInt count;
+ FT_Byte off_size;
+ FT_ULong data_offset;
+ FT_ULong data_size;
+
+ FT_ULong* offsets;
+ FT_Byte* bytes;
+
+ } CFF_IndexRec, *CFF_Index;
+
+
+ typedef struct CFF_EncodingRec_
+ {
+ FT_UInt format;
+ FT_ULong offset;
+
+ FT_UInt count;
+ FT_UShort sids [256]; /* avoid dynamic allocations */
+ FT_UShort codes[256];
+
+ } CFF_EncodingRec, *CFF_Encoding;
+
+
+ typedef struct CFF_CharsetRec_
+ {
+
+ FT_UInt format;
+ FT_ULong offset;
+
+ FT_UShort* sids;
+ FT_UShort* cids; /* the inverse mapping of `sids'; only needed */
+ /* for CID-keyed fonts */
+ FT_UInt max_cid;
+ FT_UInt num_glyphs;
+
+ } CFF_CharsetRec, *CFF_Charset;
+
+
+ /* cf. similar fields in file `ttgxvar.h' from the `truetype' module */
+
+ typedef struct CFF_VarData_
+ {
+#if 0
+ FT_UInt itemCount; /* not used; always zero */
+ FT_UInt shortDeltaCount; /* not used; always zero */
+#endif
+
+ FT_UInt regionIdxCount; /* number of region indexes */
+ FT_UInt* regionIndices; /* array of `regionIdxCount' indices; */
+ /* these index `varRegionList' */
+ } CFF_VarData;
+
+
+ /* contribution of one axis to a region */
+ typedef struct CFF_AxisCoords_
+ {
+ FT_Fixed startCoord;
+ FT_Fixed peakCoord; /* zero peak means no effect (factor = 1) */
+ FT_Fixed endCoord;
+
+ } CFF_AxisCoords;
+
+
+ typedef struct CFF_VarRegion_
+ {
+ CFF_AxisCoords* axisList; /* array of axisCount records */
+
+ } CFF_VarRegion;
+
+
+ typedef struct CFF_VStoreRec_
+ {
+ FT_UInt dataCount;
+ CFF_VarData* varData; /* array of dataCount records */
+ /* vsindex indexes this array */
+ FT_UShort axisCount;
+ FT_UInt regionCount; /* total number of regions defined */
+ CFF_VarRegion* varRegionList;
+
+ } CFF_VStoreRec, *CFF_VStore;
+
+
+ /* forward reference */
+ typedef struct CFF_FontRec_* CFF_Font;
+
+
+ /* This object manages one cached blend vector. */
+ /* */
+ /* There is a BlendRec for Private DICT parsing in each subfont */
+ /* and a BlendRec for charstrings in CF2_Font instance data. */
+ /* A cached BV may be used across DICTs or Charstrings if inputs */
+ /* have not changed. */
+ /* */
+ /* `usedBV' is reset at the start of each parse or charstring. */
+ /* vsindex cannot be changed after a BV is used. */
+ /* */
+ /* Note: NDV is long (32/64 bit), while BV is 16.16 (FT_Int32). */
+ typedef struct CFF_BlendRec_
+ {
+ FT_Bool builtBV; /* blendV has been built */
+ FT_Bool usedBV; /* blendV has been used */
+ CFF_Font font; /* top level font struct */
+ FT_UInt lastVsindex; /* last vsindex used */
+ FT_UInt lenNDV; /* normDV length (aka numAxes) */
+ FT_Fixed* lastNDV; /* last NDV used */
+ FT_UInt lenBV; /* BlendV length (aka numMasters) */
+ FT_Int32* BV; /* current blendV (per DICT/glyph) */
+
+ } CFF_BlendRec, *CFF_Blend;
+
+
+ typedef struct CFF_FontRecDictRec_
+ {
+ FT_UInt version;
+ FT_UInt notice;
+ FT_UInt copyright;
+ FT_UInt full_name;
+ FT_UInt family_name;
+ FT_UInt weight;
+ FT_Bool is_fixed_pitch;
+ FT_Fixed italic_angle;
+ FT_Fixed underline_position;
+ FT_Fixed underline_thickness;
+ FT_Int paint_type;
+ FT_Int charstring_type;
+ FT_Matrix font_matrix;
+ FT_Bool has_font_matrix;
+ FT_ULong units_per_em; /* temporarily used as scaling value also */
+ FT_Vector font_offset;
+ FT_ULong unique_id;
+ FT_BBox font_bbox;
+ FT_Pos stroke_width;
+ FT_ULong charset_offset;
+ FT_ULong encoding_offset;
+ FT_ULong charstrings_offset;
+ FT_ULong private_offset;
+ FT_ULong private_size;
+ FT_Long synthetic_base;
+ FT_UInt embedded_postscript;
+
+ /* these should only be used for the top-level font dictionary */
+ FT_UInt cid_registry;
+ FT_UInt cid_ordering;
+ FT_Long cid_supplement;
+
+ FT_Long cid_font_version;
+ FT_Long cid_font_revision;
+ FT_Long cid_font_type;
+ FT_ULong cid_count;
+ FT_ULong cid_uid_base;
+ FT_ULong cid_fd_array_offset;
+ FT_ULong cid_fd_select_offset;
+ FT_UInt cid_font_name;
+
+ /* the next fields come from the data of the deprecated */
+ /* `MultipleMaster' operator; they are needed to parse the (also */
+ /* deprecated) `blend' operator in Type 2 charstrings */
+ FT_UShort num_designs;
+ FT_UShort num_axes;
+
+ /* fields for CFF2 */
+ FT_ULong vstore_offset;
+ FT_UInt maxstack;
+
+ } CFF_FontRecDictRec, *CFF_FontRecDict;
+
+
+ /* forward reference */
+ typedef struct CFF_SubFontRec_* CFF_SubFont;
+
+
+ typedef struct CFF_PrivateRec_
+ {
+ FT_Byte num_blue_values;
+ FT_Byte num_other_blues;
+ FT_Byte num_family_blues;
+ FT_Byte num_family_other_blues;
+
+ FT_Pos blue_values[14];
+ FT_Pos other_blues[10];
+ FT_Pos family_blues[14];
+ FT_Pos family_other_blues[10];
+
+ FT_Fixed blue_scale;
+ FT_Pos blue_shift;
+ FT_Pos blue_fuzz;
+ FT_Pos standard_width;
+ FT_Pos standard_height;
+
+ FT_Byte num_snap_widths;
+ FT_Byte num_snap_heights;
+ FT_Pos snap_widths[13];
+ FT_Pos snap_heights[13];
+ FT_Bool force_bold;
+ FT_Fixed force_bold_threshold;
+ FT_Int lenIV;
+ FT_Int language_group;
+ FT_Fixed expansion_factor;
+ FT_Long initial_random_seed;
+ FT_ULong local_subrs_offset;
+ FT_Pos default_width;
+ FT_Pos nominal_width;
+
+ /* fields for CFF2 */
+ FT_UInt vsindex;
+ CFF_SubFont subfont;
+
+ } CFF_PrivateRec, *CFF_Private;
+
+
+ typedef struct CFF_FDSelectRec_
+ {
+ FT_Byte format;
+ FT_UInt range_count;
+
+ /* that's the table, taken from the file `as is' */
+ FT_Byte* data;
+ FT_UInt data_size;
+
+ /* small cache for format 3 only */
+ FT_UInt cache_first;
+ FT_UInt cache_count;
+ FT_Byte cache_fd;
+
+ } CFF_FDSelectRec, *CFF_FDSelect;
+
+
+ /* A SubFont packs a font dict and a private dict together. They are */
+ /* needed to support CID-keyed CFF fonts. */
+ typedef struct CFF_SubFontRec_
+ {
+ CFF_FontRecDictRec font_dict;
+ CFF_PrivateRec private_dict;
+
+ /* fields for CFF2 */
+ CFF_BlendRec blend; /* current blend vector */
+ FT_UInt lenNDV; /* current length NDV or zero */
+ FT_Fixed* NDV; /* ptr to current NDV or NULL */
+
+ /* `blend_stack' is a writable buffer to hold blend results. */
+ /* This buffer is to the side of the normal cff parser stack; */
+ /* `cff_parse_blend' and `cff_blend_doBlend' push blend results here. */
+ /* The normal stack then points to these values instead of the DICT */
+ /* because all other operators in Private DICT clear the stack. */
+ /* `blend_stack' could be cleared at each operator other than blend. */
+ /* Blended values are stored as 5-byte fixed point values. */
+
+ FT_Byte* blend_stack; /* base of stack allocation */
+ FT_Byte* blend_top; /* first empty slot */
+ FT_UInt blend_used; /* number of bytes in use */
+ FT_UInt blend_alloc; /* number of bytes allocated */
+
+ CFF_IndexRec local_subrs_index;
+ FT_Byte** local_subrs; /* array of pointers */
+ /* into Local Subrs INDEX data */
+
+ FT_UInt32 random;
+
+ } CFF_SubFontRec;
+
+
+#define CFF_MAX_CID_FONTS 256
+
+
+ typedef struct CFF_FontRec_
+ {
+ FT_Library library;
+ FT_Stream stream;
+ FT_Memory memory; /* TODO: take this from stream->memory? */
+ FT_ULong base_offset; /* offset to start of CFF */
+ FT_UInt num_faces;
+ FT_UInt num_glyphs;
+
+ FT_Byte version_major;
+ FT_Byte version_minor;
+ FT_Byte header_size;
+
+ FT_UInt top_dict_length; /* cff2 only */
+
+ FT_Bool cff2;
+
+ CFF_IndexRec name_index;
+ CFF_IndexRec top_dict_index;
+ CFF_IndexRec global_subrs_index;
+
+ CFF_EncodingRec encoding;
+ CFF_CharsetRec charset;
+
+ CFF_IndexRec charstrings_index;
+ CFF_IndexRec font_dict_index;
+ CFF_IndexRec private_index;
+ CFF_IndexRec local_subrs_index;
+
+ FT_String* font_name;
+
+ /* array of pointers into Global Subrs INDEX data */
+ FT_Byte** global_subrs;
+
+ /* array of pointers into String INDEX data stored at string_pool */
+ FT_UInt num_strings;
+ FT_Byte** strings;
+ FT_Byte* string_pool;
+ FT_ULong string_pool_size;
+
+ CFF_SubFontRec top_font;
+ FT_UInt num_subfonts;
+ CFF_SubFont subfonts[CFF_MAX_CID_FONTS];
+
+ CFF_FDSelectRec fd_select;
+
+ /* interface to PostScript hinter */
+ PSHinter_Service pshinter;
+
+ /* interface to Postscript Names service */
+ FT_Service_PsCMaps psnames;
+
+ /* interface to CFFLoad service */
+ const void* cffload;
+
+ /* since version 2.3.0 */
+ PS_FontInfoRec* font_info; /* font info dictionary */
+
+ /* since version 2.3.6 */
+ FT_String* registry;
+ FT_String* ordering;
+
+ /* since version 2.4.12 */
+ FT_Generic cf2_instance;
+
+ /* since version 2.7.1 */
+ CFF_VStoreRec vstore; /* parsed vstore structure */
+
+ /* since version 2.9 */
+ PS_FontExtraRec* font_extra;
+
+ } CFF_FontRec;
+
+
+FT_END_HEADER
+
+#endif /* CFFTYPES_H_ */
+
+
+/* END */
diff --git a/thirdparty/freetype/include/freetype/internal/ftcalc.h b/thirdparty/freetype/include/freetype/internal/ftcalc.h
index 8b35f03d88..818a812359 100644
--- a/thirdparty/freetype/include/freetype/internal/ftcalc.h
+++ b/thirdparty/freetype/include/freetype/internal/ftcalc.h
@@ -4,7 +4,7 @@
/* */
/* Arithmetic computations (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/internal/ftdebug.h b/thirdparty/freetype/include/freetype/internal/ftdebug.h
index 5dcd2b1740..292a4eedb8 100644
--- a/thirdparty/freetype/include/freetype/internal/ftdebug.h
+++ b/thirdparty/freetype/include/freetype/internal/ftdebug.h
@@ -4,7 +4,7 @@
/* */
/* Debugging and logging component (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/internal/ftdrv.h b/thirdparty/freetype/include/freetype/internal/ftdrv.h
new file mode 100644
index 0000000000..58dd35a933
--- /dev/null
+++ b/thirdparty/freetype/include/freetype/internal/ftdrv.h
@@ -0,0 +1,400 @@
+/***************************************************************************/
+/* */
+/* ftdrv.h */
+/* */
+/* FreeType internal font driver interface (specification). */
+/* */
+/* Copyright 1996-2018 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.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 FTDRV_H_
+#define FTDRV_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 );
+
+ typedef FT_Error
+ (*FT_Slot_LoadFunc)( FT_GlyphSlot slot,
+ FT_Size size,
+ FT_UInt glyph_index,
+ FT_Int32 load_flags );
+
+
+ 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. */
+ /* 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;
+
+ 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;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Macro> */
+ /* FT_DECLARE_DRIVER */
+ /* */
+ /* <Description> */
+ /* Used to create a forward declaration of an FT_Driver_ClassRec */
+ /* struct 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' function has to be */
+ /* called with a pointer where the allocated structure is returned. */
+ /* And when it is no longer needed a `destroy' function needs to be */
+ /* called to release that allocation. */
+ /* */
+ /* `ftinit.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' to allow you to manually allocate and */
+ /* initialize any additional global data, like a 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. Also the `pic_init' and */
+ /* `pic_free' functions should be declared in `pic.h', to be referred */
+ /* by driver definition calling `FT_DEFINE_DRIVER' in following. */
+ /* */
+ /* 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_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_, \
+ 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_, \
+ \
+ load_glyph_, \
+ \
+ get_kerning_, \
+ attach_file_, \
+ get_advances_, \
+ \
+ request_size_, \
+ select_size_ \
+ };
+
+#else /* FT_CONFIG_OPTION_PIC */
+
+#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_, \
+ load_glyph_, \
+ get_kerning_, \
+ attach_file_, \
+ get_advances_, \
+ request_size_, \
+ select_size_ ) \
+ 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 = NULL; \
+ 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_; \
+ \
+ 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 /* FTDRV_H_ */
+
+
+/* END */
diff --git a/thirdparty/freetype/include/freetype/internal/ftgloadr.h b/thirdparty/freetype/include/freetype/internal/ftgloadr.h
index f41c3df554..a002fdbfca 100644
--- a/thirdparty/freetype/include/freetype/internal/ftgloadr.h
+++ b/thirdparty/freetype/include/freetype/internal/ftgloadr.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType glyph loader (specification). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/internal/ftmemory.h b/thirdparty/freetype/include/freetype/internal/ftmemory.h
index 59e5b58a57..054eaec31f 100644
--- a/thirdparty/freetype/include/freetype/internal/ftmemory.h
+++ b/thirdparty/freetype/include/freetype/internal/ftmemory.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType memory management macros (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -210,7 +210,7 @@ extern "C++"
NULL, \
&error ) )
-#define FT_MEM_QREALLOC_MULT( ptr, oldcnt, newcnt, itmsz) \
+#define FT_MEM_QREALLOC_MULT( ptr, oldcnt, newcnt, itmsz ) \
FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory, \
(FT_Long)(itmsz), \
(FT_Long)(oldcnt), \
diff --git a/thirdparty/freetype/include/freetype/internal/ftobjs.h b/thirdparty/freetype/include/freetype/internal/ftobjs.h
index 4231be238a..1c3c6ad456 100644
--- a/thirdparty/freetype/include/freetype/internal/ftobjs.h
+++ b/thirdparty/freetype/include/freetype/internal/ftobjs.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType private base classes (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -85,9 +85,9 @@ FT_BEGIN_HEADER
: y + ( 3 * x >> 3 ) )
/* we use FT_TYPEOF to suppress signedness compilation warnings */
-#define FT_PAD_FLOOR( x, n ) ( (x) & ~FT_TYPEOF( x )( (n)-1 ) )
-#define FT_PAD_ROUND( x, n ) FT_PAD_FLOOR( (x) + (n)/2, n )
-#define FT_PAD_CEIL( x, n ) FT_PAD_FLOOR( (x) + (n)-1, n )
+#define FT_PAD_FLOOR( x, n ) ( (x) & ~FT_TYPEOF( x )( (n) - 1 ) )
+#define FT_PAD_ROUND( x, n ) FT_PAD_FLOOR( (x) + (n) / 2, n )
+#define FT_PAD_CEIL( x, n ) FT_PAD_FLOOR( (x) + (n) - 1, n )
#define FT_PIX_FLOOR( x ) ( (x) & ~FT_TYPEOF( x )63 )
#define FT_PIX_ROUND( x ) FT_PIX_FLOOR( (x) + 32 )
@@ -155,8 +155,8 @@ FT_BEGIN_HEADER
} FT_CMapRec;
- /* typecase any pointer to a charmap handle */
-#define FT_CMAP( x ) ((FT_CMap)( x ))
+ /* typecast 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
@@ -312,6 +312,27 @@ FT_BEGIN_HEADER
FT_CMap_Done( FT_CMap cmap );
+ /* adds LCD padding to Min and Max boundaries */
+ FT_BASE( void )
+ ft_lcd_padding( FT_Pos* Min,
+ FT_Pos* Max,
+ FT_GlyphSlot slot );
+
+#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
+
+ typedef void (*FT_Bitmap_LcdFilterFunc)( FT_Bitmap* bitmap,
+ FT_Render_Mode render_mode,
+ FT_Byte* weights );
+
+
+ /* This is the default LCD filter, an in-place, 5-tap FIR filter. */
+ FT_BASE( void )
+ ft_lcd_filter_fir( FT_Bitmap* bitmap,
+ FT_Render_Mode mode,
+ FT_LcdFiveTapFilter weights );
+
+#endif /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
+
/*************************************************************************/
/* */
/* <Struct> */
@@ -369,9 +390,10 @@ FT_BEGIN_HEADER
/* operator. Value~0 means to use the font's value. Value~-1 */
/* means to use the CFF driver's default. */
/* */
- /* lcd_weights :: */
- /* Overrides the library default with custom weights for the 5-tap */
- /* FIR filter. `{0, 0, 0, 0, 0}' means to use the library default. */
+ /* lcd_weights :: */
+ /* lcd_filter_func :: */
+ /* If subpixel rendering is activated, the LCD filtering weights */
+ /* and callback function. */
/* */
/* refcount :: */
/* A counter initialized to~1 at the time an @FT_Face structure is */
@@ -393,8 +415,10 @@ FT_BEGIN_HEADER
FT_Char no_stem_darkening;
FT_Int32 random_seed;
+
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
- FT_LcdFiveTapFilter lcd_weights; /* preset or custom filter weights */
+ FT_LcdFiveTapFilter lcd_weights; /* filter weights, if any */
+ FT_Bitmap_LcdFilterFunc lcd_filter_func; /* filtering callback */
#endif
FT_Int refcount;
@@ -516,7 +540,8 @@ FT_BEGIN_HEADER
/* typecast an object to an FT_Module */
-#define FT_MODULE( x ) ((FT_Module)( x ))
+#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
@@ -602,9 +627,9 @@ FT_BEGIN_HEADER
/* 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( 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
@@ -705,6 +730,12 @@ FT_BEGIN_HEADER
ft_glyphslot_free_bitmap( FT_GlyphSlot slot );
+ /* Preset bitmap metrics of an outline glyphslot prior to rendering. */
+ FT_BASE( void )
+ ft_glyphslot_preset_bitmap( FT_GlyphSlot slot,
+ FT_Render_Mode mode,
+ const FT_Vector* origin );
+
/* Allocate a new bitmap buffer in a glyph slot. */
FT_BASE( FT_Error )
ft_glyphslot_alloc_bitmap( FT_GlyphSlot slot,
@@ -731,10 +762,10 @@ FT_BEGIN_HEADER
/*************************************************************************/
-#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 ))
+#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_
@@ -765,7 +796,7 @@ FT_BEGIN_HEADER
/* typecast a module into a driver easily */
-#define FT_DRIVER( x ) ((FT_Driver)(x))
+#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
@@ -821,18 +852,6 @@ FT_BEGIN_HEADER
#define FT_DEBUG_HOOK_TRUETYPE 0
- typedef void (*FT_Bitmap_LcdFilterFunc)( FT_Bitmap* bitmap,
- FT_Render_Mode render_mode,
- FT_Byte* weights );
-
-
- /* This is the default LCD filter, an in-place, 5-tap FIR filter. */
- FT_BASE( void )
- ft_lcd_filter_fir( FT_Bitmap* bitmap,
- FT_Render_Mode mode,
- FT_LcdFiveTapFilter weights );
-
-
/*************************************************************************/
/* */
/* <Struct> */
@@ -878,9 +897,6 @@ FT_BEGIN_HEADER
/* interpreter. Currently, only the TrueType */
/* bytecode debugger uses this. */
/* */
- /* lcd_filter :: If subpixel rendering is activated, the */
- /* selected LCD filter mode. */
- /* */
/* lcd_weights :: If subpixel rendering is activated, the LCD */
/* filter weights, if any. */
/* */
@@ -915,7 +931,6 @@ FT_BEGIN_HEADER
FT_DebugHook_Func debug_hooks[4];
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
- FT_LcdFilter lcd_filter;
FT_LcdFiveTapFilter lcd_weights; /* filter weights, if any */
FT_Bitmap_LcdFilterFunc lcd_filter_func; /* filtering callback */
#endif
diff --git a/thirdparty/freetype/include/freetype/internal/ftpic.h b/thirdparty/freetype/include/freetype/internal/ftpic.h
index 0d43ed20f7..5214f05989 100644
--- a/thirdparty/freetype/include/freetype/internal/ftpic.h
+++ b/thirdparty/freetype/include/freetype/internal/ftpic.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services (declaration). */
/* */
-/* Copyright 2009-2017 by */
+/* Copyright 2009-2018 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/internal/ftpsprop.h b/thirdparty/freetype/include/freetype/internal/ftpsprop.h
new file mode 100644
index 0000000000..abbb62862b
--- /dev/null
+++ b/thirdparty/freetype/include/freetype/internal/ftpsprop.h
@@ -0,0 +1,48 @@
+/***************************************************************************/
+/* */
+/* ftpsprop.h */
+/* */
+/* Get and set properties of PostScript drivers (specification). */
+/* */
+/* Copyright 2017-2018 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef FTPSPROP_H_
+#define FTPSPROP_H_
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+
+ FT_BASE_CALLBACK( FT_Error )
+ ps_property_set( FT_Module module, /* PS_Driver */
+ const char* property_name,
+ const void* value,
+ FT_Bool value_is_string );
+
+ FT_BASE_CALLBACK( FT_Error )
+ ps_property_get( FT_Module module, /* PS_Driver */
+ const char* property_name,
+ void* value );
+
+
+FT_END_HEADER
+
+
+#endif /* FTPSPROP_H_ */
+
+
+/* END */
diff --git a/thirdparty/freetype/include/freetype/internal/ftrfork.h b/thirdparty/freetype/include/freetype/internal/ftrfork.h
index 25a44a4487..1aca48a0e7 100644
--- a/thirdparty/freetype/include/freetype/internal/ftrfork.h
+++ b/thirdparty/freetype/include/freetype/internal/ftrfork.h
@@ -4,7 +4,7 @@
/* */
/* Embedded resource forks accessor (specification). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* Masatake YAMATO and Redhat K.K. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/internal/ftserv.h b/thirdparty/freetype/include/freetype/internal/ftserv.h
index 71ef9cac3a..e01c1679b5 100644
--- a/thirdparty/freetype/include/freetype/internal/ftserv.h
+++ b/thirdparty/freetype/include/freetype/internal/ftserv.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType services (specification only). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -330,6 +330,32 @@ FT_BEGIN_HEADER
{ NULL, NULL } \
};
+#define FT_DEFINE_SERVICEDESCREC10( 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, \
+ serv_id_7, serv_data_7, \
+ serv_id_8, serv_data_8, \
+ serv_id_9, serv_data_9, \
+ serv_id_10, serv_data_10 ) \
+ 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 }, \
+ { serv_id_7, serv_data_7 }, \
+ { serv_id_8, serv_data_8 }, \
+ { serv_id_9, serv_data_9 }, \
+ { serv_id_10, serv_data_10 }, \
+ { NULL, NULL } \
+ };
+
#else /* FT_CONFIG_OPTION_PIC */
#define FT_DEFINE_SERVICEDESCREC1( class_, \
@@ -557,7 +583,7 @@ FT_BEGIN_HEADER
\
FT_Error \
FT_Create_Class_ ## class_( FT_Library library, \
- FT_ServiceDescRec** output_class) \
+ FT_ServiceDescRec** output_class ) \
{ \
FT_ServiceDescRec* clazz = NULL; \
FT_Error error; \
@@ -608,7 +634,7 @@ FT_BEGIN_HEADER
\
FT_Error \
FT_Create_Class_ ## class_( FT_Library library, \
- FT_ServiceDescRec** output_class) \
+ FT_ServiceDescRec** output_class ) \
{ \
FT_ServiceDescRec* clazz = NULL; \
FT_Error error; \
@@ -662,7 +688,7 @@ FT_BEGIN_HEADER
\
FT_Error \
FT_Create_Class_ ## class_( FT_Library library, \
- FT_ServiceDescRec** output_class) \
+ FT_ServiceDescRec** output_class ) \
{ \
FT_ServiceDescRec* clazz = NULL; \
FT_Error error; \
@@ -719,7 +745,7 @@ FT_BEGIN_HEADER
\
FT_Error \
FT_Create_Class_ ## class_( FT_Library library, \
- FT_ServiceDescRec** output_class) \
+ FT_ServiceDescRec** output_class ) \
{ \
FT_ServiceDescRec* clazz = NULL; \
FT_Error error; \
@@ -755,6 +781,68 @@ FT_BEGIN_HEADER
return FT_Err_Ok; \
}
+#define FT_DEFINE_SERVICEDESCREC10( 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, \
+ serv_id_7, serv_data_7, \
+ serv_id_8, serv_data_8, \
+ serv_id_9, serv_data_9, \
+ serv_id_10, serv_data_10 ) \
+ 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 = NULL; \
+ FT_Error error; \
+ FT_Memory memory = library->memory; \
+ \
+ \
+ if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 11 ) ) \
+ 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 = serv_id_7; \
+ clazz[ 6].serv_data = serv_data_7; \
+ clazz[ 7].serv_id = serv_id_8; \
+ clazz[ 7].serv_data = serv_data_8; \
+ clazz[ 8].serv_id = serv_id_9; \
+ clazz[ 8].serv_data = serv_data_9; \
+ clazz[ 9].serv_id = serv_id_10; \
+ clazz[ 9].serv_data = serv_data_10; \
+ clazz[10].serv_id = NULL; \
+ clazz[10].serv_data = NULL; \
+ \
+ *output_class = clazz; \
+ \
+ return FT_Err_Ok; \
+ }
+
#endif /* FT_CONFIG_OPTION_PIC */
@@ -898,7 +986,9 @@ FT_BEGIN_HEADER
*/
#define FT_SERVICE_BDF_H <freetype/internal/services/svbdf.h>
+#define FT_SERVICE_CFF_TABLE_LOAD_H <freetype/internal/services/svcfftl.h>
#define FT_SERVICE_CID_H <freetype/internal/services/svcid.h>
+#define FT_SERVICE_FONT_FORMAT_H <freetype/internal/services/svfntfmt.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>
@@ -912,10 +1002,9 @@ FT_BEGIN_HEADER
#define FT_SERVICE_PROPERTIES_H <freetype/internal/services/svprop.h>
#define FT_SERVICE_SFNT_H <freetype/internal/services/svsfnt.h>
#define FT_SERVICE_TRUETYPE_ENGINE_H <freetype/internal/services/svtteng.h>
+#define FT_SERVICE_TRUETYPE_GLYF_H <freetype/internal/services/svttglyf.h>
#define FT_SERVICE_TT_CMAP_H <freetype/internal/services/svttcmap.h>
#define FT_SERVICE_WINFNT_H <freetype/internal/services/svwinfnt.h>
-#define FT_SERVICE_FONT_FORMAT_H <freetype/internal/services/svfntfmt.h>
-#define FT_SERVICE_TRUETYPE_GLYF_H <freetype/internal/services/svttglyf.h>
/* */
diff --git a/thirdparty/freetype/include/freetype/internal/ftstream.h b/thirdparty/freetype/include/freetype/internal/ftstream.h
index 3e2c07b269..f90002fe77 100644
--- a/thirdparty/freetype/include/freetype/internal/ftstream.h
+++ b/thirdparty/freetype/include/freetype/internal/ftstream.h
@@ -4,7 +4,7 @@
/* */
/* Stream handling (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -165,8 +165,8 @@ FT_BEGIN_HEADER
#define FT_BYTE_U32( p, i, s ) ( FT_UINT32( FT_BYTE_( p, i ) ) << (s) )
-#define FT_PEEK_SHORT( p ) FT_INT16( FT_BYTE_U16( p, 0, 8) | \
- FT_BYTE_U16( p, 1, 0) )
+#define FT_PEEK_SHORT( p ) FT_INT16( FT_BYTE_U16( p, 0, 8 ) | \
+ FT_BYTE_U16( p, 1, 0 ) )
#define FT_PEEK_USHORT( p ) FT_UINT16( FT_BYTE_U16( p, 0, 8 ) | \
FT_BYTE_U16( p, 1, 0 ) )
diff --git a/thirdparty/freetype/include/freetype/internal/fttrace.h b/thirdparty/freetype/include/freetype/internal/fttrace.h
index caf5fc9460..8092e41fd7 100644
--- a/thirdparty/freetype/include/freetype/internal/fttrace.h
+++ b/thirdparty/freetype/include/freetype/internal/fttrace.h
@@ -4,7 +4,7 @@
/* */
/* Tracing handling (specification only). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -39,6 +39,7 @@ 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) */
FT_TRACE_DEF( bitmap ) /* bitmap checksum (ftobjs.c) */
+FT_TRACE_DEF( psprops ) /* PS driver properties (ftpsprop.c) */
/* Cache sub-system */
FT_TRACE_DEF( cache ) /* cache sub-system (ftcache.c, etc.) */
@@ -66,20 +67,19 @@ FT_TRACE_DEF( ttgxvar ) /* TrueType GX var handler (ttgxvar.c) */
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( cffdecode )
FT_TRACE_DEF( psobjs )
FT_TRACE_DEF( psconv )
/* PostScript hinting module `pshinter' */
FT_TRACE_DEF( pshrec )
-FT_TRACE_DEF( pshalgo1 )
-FT_TRACE_DEF( pshalgo2 )
+FT_TRACE_DEF( pshalgo )
/* Type 2 driver components */
FT_TRACE_DEF( cffdriver )
@@ -96,7 +96,6 @@ FT_TRACE_DEF( cf2interp )
FT_TRACE_DEF( t42 )
/* CID driver components */
-FT_TRACE_DEF( cidafm )
FT_TRACE_DEF( ciddriver )
FT_TRACE_DEF( cidgload )
FT_TRACE_DEF( cidload )
diff --git a/thirdparty/freetype/include/freetype/internal/ftvalid.h b/thirdparty/freetype/include/freetype/internal/ftvalid.h
index df6f7c5778..cad47a556d 100644
--- a/thirdparty/freetype/include/freetype/internal/ftvalid.h
+++ b/thirdparty/freetype/include/freetype/internal/ftvalid.h
@@ -4,7 +4,7 @@
/* */
/* FreeType validation support (specification). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/internal/internal.h b/thirdparty/freetype/include/freetype/internal/internal.h
index 02046813a3..8f546e443b 100644
--- a/thirdparty/freetype/include/freetype/internal/internal.h
+++ b/thirdparty/freetype/include/freetype/internal/internal.h
@@ -4,7 +4,7 @@
/* */
/* Internal header files (specification only). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -31,7 +31,7 @@
#define FT_INTERNAL_DEBUG_H <freetype/internal/ftdebug.h>
#define FT_INTERNAL_CALC_H <freetype/internal/ftcalc.h>
#define FT_INTERNAL_HASH_H <freetype/internal/fthash.h>
-#define FT_INTERNAL_DRIVER_H <freetype/internal/ftdriver.h>
+#define FT_INTERNAL_DRIVER_H <freetype/internal/ftdrv.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>
@@ -44,9 +44,13 @@
#define FT_INTERNAL_POSTSCRIPT_AUX_H <freetype/internal/psaux.h>
#define FT_INTERNAL_POSTSCRIPT_HINTS_H <freetype/internal/pshints.h>
+#define FT_INTERNAL_POSTSCRIPT_PROPS_H <freetype/internal/ftpsprop.h>
#define FT_INTERNAL_AUTOHINT_H <freetype/internal/autohint.h>
+#define FT_INTERNAL_CFF_TYPES_H <freetype/internal/cfftypes.h>
+#define FT_INTERNAL_CFF_OBJECTS_TYPES_H <freetype/internal/cffotypes.h>
+
#if defined( _MSC_VER ) /* Visual C++ (and Intel C++) */
diff --git a/thirdparty/freetype/include/freetype/internal/psaux.h b/thirdparty/freetype/include/freetype/internal/psaux.h
index 935eb1a9c7..f77380d25f 100644
--- a/thirdparty/freetype/include/freetype/internal/psaux.h
+++ b/thirdparty/freetype/include/freetype/internal/psaux.h
@@ -5,7 +5,7 @@
/* Auxiliary functions and data structures related to PostScript fonts */
/* (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -25,12 +25,32 @@
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_TYPE1_TYPES_H
#include FT_INTERNAL_HASH_H
+#include FT_INTERNAL_TRUETYPE_TYPES_H
#include FT_SERVICE_POSTSCRIPT_CMAPS_H
+#include FT_INTERNAL_CFF_TYPES_H
+#include FT_INTERNAL_CFF_OBJECTS_TYPES_H
+
FT_BEGIN_HEADER
+ /***********************************************************************/
+ /* */
+ /* PostScript modules driver class. */
+ /* */
+ typedef struct PS_DriverRec_
+ {
+ FT_DriverRec root;
+
+ FT_UInt hinting_engine;
+ FT_Bool no_stem_darkening;
+ FT_Int darken_params[8];
+ FT_Int32 random_seed;
+
+ } PS_DriverRec, *PS_Driver;
+
+
/*************************************************************************/
/*************************************************************************/
/***** *****/
@@ -442,6 +462,202 @@ FT_BEGIN_HEADER
/*************************************************************************/
/*************************************************************************/
/***** *****/
+ /***** PS BUILDER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ typedef struct PS_Builder_ PS_Builder;
+ typedef const struct PS_Builder_FuncsRec_* PS_Builder_Funcs;
+
+ typedef struct PS_Builder_FuncsRec_
+ {
+ void
+ (*init)( PS_Builder* ps_builder,
+ void* builder,
+ FT_Bool is_t1 );
+
+ void
+ (*done)( PS_Builder* builder );
+
+ } PS_Builder_FuncsRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Structure> */
+ /* PS_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 :: XXX */
+ /* */
+ /* 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. */
+ /* */
+ /* is_t1 :: Set if current font type is Type 1. */
+ /* */
+ /* funcs :: An array of function pointers for the builder. */
+ /* */
+ struct PS_Builder_
+ {
+ FT_Memory memory;
+ FT_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;
+ FT_Bool is_t1;
+
+ PS_Builder_FuncsRec funcs;
+
+ };
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** PS DECODER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+#define PS_MAX_OPERANDS 48
+#define PS_MAX_SUBRS_CALLS 16 /* maximum subroutine nesting; */
+ /* only 10 are allowed but there exist */
+ /* fonts like `HiraKakuProN-W3.ttf' */
+ /* (Hiragino Kaku Gothic ProN W3; */
+ /* 8.2d6e1; 2014-12-19) that exceed */
+ /* this limit */
+
+ /* execution context charstring zone */
+
+ typedef struct PS_Decoder_Zone_
+ {
+ FT_Byte* base;
+ FT_Byte* limit;
+ FT_Byte* cursor;
+
+ } PS_Decoder_Zone;
+
+
+ typedef FT_Error
+ (*CFF_Decoder_Get_Glyph_Callback)( TT_Face face,
+ FT_UInt glyph_index,
+ FT_Byte** pointer,
+ FT_ULong* length );
+
+ typedef void
+ (*CFF_Decoder_Free_Glyph_Callback)( TT_Face face,
+ FT_Byte** pointer,
+ FT_ULong length );
+
+
+ typedef struct PS_Decoder_
+ {
+ PS_Builder builder;
+
+ FT_Fixed stack[PS_MAX_OPERANDS + 1];
+ FT_Fixed* top;
+
+ PS_Decoder_Zone zones[PS_MAX_SUBRS_CALLS + 1];
+ PS_Decoder_Zone* zone;
+
+ FT_Int flex_state;
+ FT_Int num_flex_vectors;
+ FT_Vector flex_vectors[7];
+
+ CFF_Font cff;
+ CFF_SubFont current_subfont; /* for current glyph_index */
+ FT_Generic* cf2_instance;
+
+ FT_Pos* glyph_width;
+ FT_Bool width_only;
+ FT_Int num_hints;
+
+ 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_Get_Glyph_Callback get_glyph_callback;
+ CFF_Decoder_Free_Glyph_Callback free_glyph_callback;
+
+ /* Type 1 stuff */
+ FT_Service_PsCMaps psnames; /* for seac */
+
+ FT_Int lenIV; /* internal for sub routine calls */
+ FT_UInt* locals_len; /* array of subrs length (optional) */
+ FT_Hash locals_hash; /* used if `num_subrs' was massaged */
+
+ FT_Matrix font_matrix;
+ FT_Vector font_offset;
+
+ PS_Blend blend; /* for multiple master support */
+
+ FT_Long* buildchar;
+ FT_UInt len_buildchar;
+
+ } PS_Decoder;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
/***** T1 BUILDER *****/
/***** *****/
/*************************************************************************/
@@ -653,10 +869,23 @@ FT_BEGIN_HEADER
void
(*done)( T1_Decoder decoder );
+#ifdef T1_CONFIG_OPTION_OLD_ENGINE
+ FT_Error
+ (*parse_charstrings_old)( T1_Decoder decoder,
+ FT_Byte* base,
+ FT_UInt len );
+#else
+ FT_Error
+ (*parse_metrics)( T1_Decoder decoder,
+ FT_Byte* base,
+ FT_UInt len );
+#endif
+
FT_Error
- (*parse_charstrings)( T1_Decoder decoder,
- FT_Byte* base,
- FT_UInt len );
+ (*parse_charstrings)( PS_Decoder* decoder,
+ FT_Byte* charstring_base,
+ FT_ULong charstring_len );
+
} T1_Decoder_FuncsRec;
@@ -700,12 +929,261 @@ FT_BEGIN_HEADER
FT_Bool seac;
+ FT_Generic cf2_instance;
+
} T1_DecoderRec;
/*************************************************************************/
/*************************************************************************/
/***** *****/
+ /***** CFF BUILDER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ typedef struct CFF_Builder_ CFF_Builder;
+
+
+ typedef FT_Error
+ (*CFF_Builder_Check_Points_Func)( CFF_Builder* builder,
+ FT_Int count );
+
+ typedef void
+ (*CFF_Builder_Add_Point_Func)( CFF_Builder* builder,
+ FT_Pos x,
+ FT_Pos y,
+ FT_Byte flag );
+ typedef FT_Error
+ (*CFF_Builder_Add_Point1_Func)( CFF_Builder* builder,
+ FT_Pos x,
+ FT_Pos y );
+ typedef FT_Error
+ (*CFF_Builder_Start_Point_Func)( CFF_Builder* builder,
+ FT_Pos x,
+ FT_Pos y );
+ typedef void
+ (*CFF_Builder_Close_Contour_Func)( CFF_Builder* builder );
+
+ typedef FT_Error
+ (*CFF_Builder_Add_Contour_Func)( CFF_Builder* builder );
+
+ typedef const struct CFF_Builder_FuncsRec_* CFF_Builder_Funcs;
+
+ typedef struct CFF_Builder_FuncsRec_
+ {
+ void
+ (*init)( CFF_Builder* builder,
+ TT_Face face,
+ CFF_Size size,
+ CFF_GlyphSlot glyph,
+ FT_Bool hinting );
+
+ void
+ (*done)( CFF_Builder* builder );
+
+ CFF_Builder_Check_Points_Func check_points;
+ CFF_Builder_Add_Point_Func add_point;
+ CFF_Builder_Add_Point1_Func add_point1;
+ CFF_Builder_Add_Contour_Func add_contour;
+ CFF_Builder_Start_Point_Func start_point;
+ CFF_Builder_Close_Contour_Func close_contour;
+
+ } CFF_Builder_FuncsRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* <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. */
+ /* */
+ /* funcs :: A table of method pointers for this object. */
+ /* */
+ 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_FuncsRec funcs;
+ };
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** CFF DECODER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+#define CFF_MAX_OPERANDS 48
+#define CFF_MAX_SUBRS_CALLS 16 /* maximum subroutine nesting; */
+ /* only 10 are allowed but there exist */
+ /* fonts like `HiraKakuProN-W3.ttf' */
+ /* (Hiragino Kaku Gothic ProN W3; */
+ /* 8.2d6e1; 2014-12-19) that exceed */
+ /* this limit */
+#define CFF_MAX_TRANS_ELEMENTS 32
+
+ /* execution context charstring zone */
+
+ typedef struct CFF_Decoder_Zone_
+ {
+ FT_Byte* base;
+ FT_Byte* limit;
+ FT_Byte* cursor;
+
+ } CFF_Decoder_Zone;
+
+
+ typedef struct CFF_Decoder_
+ {
+ CFF_Builder builder;
+ CFF_Font cff;
+
+ FT_Fixed stack[CFF_MAX_OPERANDS + 1];
+ FT_Fixed* top;
+
+ CFF_Decoder_Zone zones[CFF_MAX_SUBRS_CALLS + 1];
+ CFF_Decoder_Zone* zone;
+
+ FT_Int flex_state;
+ FT_Int num_flex_vectors;
+ FT_Vector flex_vectors[7];
+
+ FT_Pos glyph_width;
+ FT_Pos nominal_width;
+
+ FT_Bool read_width;
+ FT_Bool width_only;
+ FT_Int num_hints;
+ FT_Fixed buildchar[CFF_MAX_TRANS_ELEMENTS];
+
+ FT_UInt num_locals;
+ FT_UInt num_globals;
+
+ FT_Int locals_bias;
+ FT_Int globals_bias;
+
+ FT_Byte** locals;
+ FT_Byte** globals;
+
+ FT_Byte** glyph_names; /* for pure CFF fonts only */
+ FT_UInt num_glyphs; /* number of glyphs in font */
+
+ FT_Render_Mode hint_mode;
+
+ FT_Bool seac;
+
+ CFF_SubFont current_subfont; /* for current glyph_index */
+
+ CFF_Decoder_Get_Glyph_Callback get_glyph_callback;
+ CFF_Decoder_Free_Glyph_Callback free_glyph_callback;
+
+ } CFF_Decoder;
+
+
+ typedef const struct CFF_Decoder_FuncsRec_* CFF_Decoder_Funcs;
+
+ typedef struct CFF_Decoder_FuncsRec_
+ {
+ void
+ (*init)( CFF_Decoder* decoder,
+ TT_Face face,
+ CFF_Size size,
+ CFF_GlyphSlot slot,
+ FT_Bool hinting,
+ FT_Render_Mode hint_mode,
+ CFF_Decoder_Get_Glyph_Callback get_callback,
+ CFF_Decoder_Free_Glyph_Callback free_callback );
+
+ FT_Error
+ (*prepare)( CFF_Decoder* decoder,
+ CFF_Size size,
+ FT_UInt glyph_index );
+
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+ FT_Error
+ (*parse_charstrings_old)( CFF_Decoder* decoder,
+ FT_Byte* charstring_base,
+ FT_ULong charstring_len,
+ FT_Bool in_dict );
+#endif
+
+ FT_Error
+ (*parse_charstrings)( PS_Decoder* decoder,
+ FT_Byte* charstring_base,
+ FT_ULong charstring_len );
+
+ } CFF_Decoder_FuncsRec;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
/***** AFM PARSER *****/
/***** *****/
/*************************************************************************/
@@ -810,11 +1288,26 @@ FT_BEGIN_HEADER
FT_Offset length,
FT_UShort seed );
+ FT_UInt32
+ (*cff_random)( FT_UInt32 r );
+
+ void
+ (*ps_decoder_init)( PS_Decoder* ps_decoder,
+ void* decoder,
+ FT_Bool is_t1 );
+
+ void
+ (*t1_make_subfont)( FT_Face face,
+ PS_Private priv,
+ CFF_SubFont subfont );
+
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;
+ const CFF_Decoder_FuncsRec* cff_decoder_funcs;
+
} PSAux_ServiceRec, *PSAux_Service;
/* backward compatible type definition */
diff --git a/thirdparty/freetype/include/freetype/internal/pshints.h b/thirdparty/freetype/include/freetype/internal/pshints.h
index 49116eb443..d29314ec2e 100644
--- a/thirdparty/freetype/include/freetype/internal/pshints.h
+++ b/thirdparty/freetype/include/freetype/internal/pshints.h
@@ -6,7 +6,7 @@
/* recorders (specification only). These are used to support native */
/* T1/T2 hints in the `type1', `cid', and `cff' font drivers. */
/* */
-/* Copyright 2001-2017 by */
+/* Copyright 2001-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svbdf.h b/thirdparty/freetype/include/freetype/internal/services/svbdf.h
index eeebf67da1..4a9ec20075 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svbdf.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svbdf.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType BDF services (specification). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svcfftl.h b/thirdparty/freetype/include/freetype/internal/services/svcfftl.h
new file mode 100644
index 0000000000..db623e6840
--- /dev/null
+++ b/thirdparty/freetype/include/freetype/internal/services/svcfftl.h
@@ -0,0 +1,112 @@
+/***************************************************************************/
+/* */
+/* svcfftl.h */
+/* */
+/* The FreeType CFF tables loader service (specification). */
+/* */
+/* Copyright 2017-2018 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef SVCFFTL_H_
+#define SVCFFTL_H_
+
+#include FT_INTERNAL_SERVICE_H
+#include FT_INTERNAL_CFF_TYPES_H
+
+
+FT_BEGIN_HEADER
+
+
+#define FT_SERVICE_ID_CFF_LOAD "cff-load"
+
+
+ typedef FT_UShort
+ (*FT_Get_Standard_Encoding_Func)( FT_UInt charcode );
+
+ typedef FT_Error
+ (*FT_Load_Private_Dict_Func)( CFF_Font font,
+ CFF_SubFont subfont,
+ FT_UInt lenNDV,
+ FT_Fixed* NDV );
+
+ typedef FT_Byte
+ (*FT_FD_Select_Get_Func)( CFF_FDSelect fdselect,
+ FT_UInt glyph_index );
+
+ typedef FT_Bool
+ (*FT_Blend_Check_Vector_Func)( CFF_Blend blend,
+ FT_UInt vsindex,
+ FT_UInt lenNDV,
+ FT_Fixed* NDV );
+
+ typedef FT_Error
+ (*FT_Blend_Build_Vector_Func)( CFF_Blend blend,
+ FT_UInt vsindex,
+ FT_UInt lenNDV,
+ FT_Fixed* NDV );
+
+
+ FT_DEFINE_SERVICE( CFFLoad )
+ {
+ FT_Get_Standard_Encoding_Func get_standard_encoding;
+ FT_Load_Private_Dict_Func load_private_dict;
+ FT_FD_Select_Get_Func fd_select_get;
+ FT_Blend_Check_Vector_Func blend_check_vector;
+ FT_Blend_Build_Vector_Func blend_build_vector;
+ };
+
+
+#ifndef FT_CONFIG_OPTION_PIC
+
+#define FT_DEFINE_SERVICE_CFFLOADREC( class_, \
+ get_standard_encoding_, \
+ load_private_dict_, \
+ fd_select_get_, \
+ blend_check_vector_, \
+ blend_build_vector_ ) \
+ static const FT_Service_CFFLoadRec class_ = \
+ { \
+ get_standard_encoding_, \
+ load_private_dict_, \
+ fd_select_get_, \
+ blend_check_vector_, \
+ blend_build_vector_ \
+ };
+
+#else /* FT_CONFIG_OPTION_PIC */
+
+#define FT_DEFINE_SERVICE_CFFLOADREC( class_, \
+ get_standard_encoding_, \
+ load_private_dict_, \
+ fd_select_get_, \
+ blend_check_vector_, \
+ blend_build_vector_ ) \
+ void \
+ FT_Init_Class_ ## class_( FT_Service_CFFLoadRec* clazz ) \
+ { \
+ clazz->get_standard_encoding = get_standard_encoding_; \
+ clazz->load_private_dict = load_private_dict_; \
+ clazz->fd_select_get = fd_select_get_; \
+ clazz->blend_check_vector = blend_check_vector_; \
+ clazz->blend_build_vector = blend_build_vector_; \
+ }
+
+#endif /* FT_CONFIG_OPTION_PIC */
+
+
+FT_END_HEADER
+
+
+#endif
+
+
+/* END */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svcid.h b/thirdparty/freetype/include/freetype/internal/services/svcid.h
index cce94d8df6..cb59ac6a29 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svcid.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svcid.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType CID font services (specification). */
/* */
-/* Copyright 2007-2017 by */
+/* Copyright 2007-2018 by */
/* Derek Clegg and Michael Toftdal. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svfntfmt.h b/thirdparty/freetype/include/freetype/internal/services/svfntfmt.h
index 376d9255bb..3b732be1a1 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svfntfmt.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svfntfmt.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType font format service (specification only). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svgldict.h b/thirdparty/freetype/include/freetype/internal/services/svgldict.h
index 0cd13618d8..f1a68e3110 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svgldict.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svgldict.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType glyph dictionary services (specification). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -56,7 +56,7 @@ FT_BEGIN_HEADER
#define FT_DEFINE_SERVICE_GLYPHDICTREC( class_, \
get_name_, \
- name_index_) \
+ name_index_ ) \
static const FT_Service_GlyphDictRec class_ = \
{ \
get_name_, name_index_ \
@@ -66,7 +66,7 @@ FT_BEGIN_HEADER
#define FT_DEFINE_SERVICE_GLYPHDICTREC( class_, \
get_name_, \
- name_index_) \
+ name_index_ ) \
void \
FT_Init_Class_ ## class_( FT_Library library, \
FT_Service_GlyphDictRec* clazz ) \
diff --git a/thirdparty/freetype/include/freetype/internal/services/svgxval.h b/thirdparty/freetype/include/freetype/internal/services/svgxval.h
index 71bfa97af8..ed79ebeaa8 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svgxval.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svgxval.h
@@ -4,7 +4,7 @@
/* */
/* FreeType API for validating TrueTypeGX/AAT tables (specification). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svkern.h b/thirdparty/freetype/include/freetype/internal/services/svkern.h
index b8344e96e9..c7e8f6ef27 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svkern.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svkern.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType Kerning service (specification). */
/* */
-/* Copyright 2006-2017 by */
+/* Copyright 2006-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svmetric.h b/thirdparty/freetype/include/freetype/internal/services/svmetric.h
index 1f7d5ddd0c..abaacddbbe 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svmetric.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svmetric.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType services for metrics variations (specification). */
/* */
-/* Copyright 2016-2017 by */
+/* Copyright 2016-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svmm.h b/thirdparty/freetype/include/freetype/internal/services/svmm.h
index 1d51cd9090..bcbb38e2ce 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svmm.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svmm.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType Multiple Masters and GX var services (specification). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -48,11 +48,15 @@ FT_BEGIN_HEADER
FT_UInt num_coords,
FT_Long* coords );
+ /* use return value -1 to indicate that the new coordinates */
+ /* are equal to the current ones; no changes are thus needed */
typedef FT_Error
(*FT_Set_Var_Design_Func)( FT_Face face,
FT_UInt num_coords,
FT_Fixed* coords );
+ /* use return value -1 to indicate that the new coordinates */
+ /* are equal to the current ones; no changes are thus needed */
typedef FT_Error
(*FT_Set_MM_Blend_Func)( FT_Face face,
FT_UInt num_coords,
@@ -64,6 +68,10 @@ FT_BEGIN_HEADER
FT_Fixed* coords );
typedef FT_Error
+ (*FT_Set_Instance_Func)( FT_Face face,
+ FT_UInt instance_index );
+
+ typedef FT_Error
(*FT_Get_MM_Blend_Func)( FT_Face face,
FT_UInt num_coords,
FT_Long* coords );
@@ -88,6 +96,7 @@ FT_BEGIN_HEADER
FT_Get_MM_Var_Func get_mm_var;
FT_Set_Var_Design_Func set_var_design;
FT_Get_Var_Design_Func get_var_design;
+ FT_Set_Instance_Func set_instance;
/* for internal use; only needed for code sharing between modules */
FT_Get_Var_Blend_Func get_var_blend;
@@ -97,27 +106,29 @@ FT_BEGIN_HEADER
#ifndef FT_CONFIG_OPTION_PIC
-#define FT_DEFINE_SERVICE_MULTIMASTERSREC( class_, \
- get_mm_, \
- set_mm_design_, \
- set_mm_blend_, \
- get_mm_blend_, \
- get_mm_var_, \
- set_var_design_, \
- get_var_design_, \
- get_var_blend_, \
- done_blend_ ) \
- static const FT_Service_MultiMastersRec class_ = \
- { \
- get_mm_, \
- set_mm_design_, \
- set_mm_blend_, \
- get_mm_blend_, \
- get_mm_var_, \
- set_var_design_, \
- get_var_design_, \
- get_var_blend_, \
- done_blend_ \
+#define FT_DEFINE_SERVICE_MULTIMASTERSREC( class_, \
+ get_mm_, \
+ set_mm_design_, \
+ set_mm_blend_, \
+ get_mm_blend_, \
+ get_mm_var_, \
+ set_var_design_, \
+ get_var_design_, \
+ set_instance_, \
+ get_var_blend_, \
+ done_blend_ ) \
+ static const FT_Service_MultiMastersRec class_ = \
+ { \
+ get_mm_, \
+ set_mm_design_, \
+ set_mm_blend_, \
+ get_mm_blend_, \
+ get_mm_var_, \
+ set_var_design_, \
+ get_var_design_, \
+ set_instance_, \
+ get_var_blend_, \
+ done_blend_ \
};
#else /* FT_CONFIG_OPTION_PIC */
@@ -130,6 +141,7 @@ FT_BEGIN_HEADER
get_mm_var_, \
set_var_design_, \
get_var_design_, \
+ set_instance_, \
get_var_blend_, \
done_blend_ ) \
void \
@@ -142,6 +154,7 @@ FT_BEGIN_HEADER
clazz->get_mm_var = get_mm_var_; \
clazz->set_var_design = set_var_design_; \
clazz->get_var_design = get_var_design_; \
+ clazz->set_instance = set_instance_; \
clazz->get_var_blend = get_var_blend_; \
clazz->done_blend = done_blend_; \
}
diff --git a/thirdparty/freetype/include/freetype/internal/services/svotval.h b/thirdparty/freetype/include/freetype/internal/services/svotval.h
index ac84abee46..31294296a6 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svotval.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svotval.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType OpenType validation service (specification). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svpfr.h b/thirdparty/freetype/include/freetype/internal/services/svpfr.h
index c9a182fe39..e65d57e91b 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svpfr.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svpfr.h
@@ -4,7 +4,7 @@
/* */
/* Internal PFR service functions (specification). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svpostnm.h b/thirdparty/freetype/include/freetype/internal/services/svpostnm.h
index 022cdec195..4a49d8b053 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svpostnm.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svpostnm.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType PostScript name services (specification). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svprop.h b/thirdparty/freetype/include/freetype/internal/services/svprop.h
index eb2d4eed15..adc0bcf439 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svprop.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svprop.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType property service (specification). */
/* */
-/* Copyright 2012-2017 by */
+/* Copyright 2012-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svpscmap.h b/thirdparty/freetype/include/freetype/internal/services/svpscmap.h
index b32122e5d6..5589575b92 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svpscmap.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svpscmap.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType PostScript charmap service (specification). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svpsinfo.h b/thirdparty/freetype/include/freetype/internal/services/svpsinfo.h
index 0220ce529c..408f406dfa 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svpsinfo.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svpsinfo.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType PostScript info service (specification). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svsfnt.h b/thirdparty/freetype/include/freetype/internal/services/svsfnt.h
index 49d18e43e0..e8b37bc47f 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svsfnt.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svsfnt.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType SFNT table loading service (specification). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svttcmap.h b/thirdparty/freetype/include/freetype/internal/services/svttcmap.h
index 30f7feec71..cd0e6fda6f 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svttcmap.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svttcmap.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType TrueType/sfnt cmap extra information service. */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* Masatake YAMATO, Redhat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svtteng.h b/thirdparty/freetype/include/freetype/internal/services/svtteng.h
index e4b368ad40..92e3c541f5 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svtteng.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svtteng.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType TrueType engine query service (specification). */
/* */
-/* Copyright 2006-2017 by */
+/* Copyright 2006-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svttglyf.h b/thirdparty/freetype/include/freetype/internal/services/svttglyf.h
index b7793059fd..16fac1ca18 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svttglyf.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svttglyf.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType TrueType glyph service. */
/* */
-/* Copyright 2007-2017 by */
+/* Copyright 2007-2018 by */
/* David Turner. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/internal/services/svwinfnt.h b/thirdparty/freetype/include/freetype/internal/services/svwinfnt.h
index c94b7e1073..80d481cbd1 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svwinfnt.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svwinfnt.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType Windows FNT/FONT service (specification). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/internal/sfnt.h b/thirdparty/freetype/include/freetype/internal/sfnt.h
index b8667a003a..fb1e327aeb 100644
--- a/thirdparty/freetype/include/freetype/internal/sfnt.h
+++ b/thirdparty/freetype/include/freetype/internal/sfnt.h
@@ -4,7 +4,7 @@
/* */
/* High-level `sfnt' driver interface (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/internal/t1types.h b/thirdparty/freetype/include/freetype/internal/t1types.h
index b2e35d42d1..2118e33674 100644
--- a/thirdparty/freetype/include/freetype/internal/t1types.h
+++ b/thirdparty/freetype/include/freetype/internal/t1types.h
@@ -5,7 +5,7 @@
/* Basic Type1/Type2 type definitions and interface (specification */
/* only). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/internal/tttypes.h b/thirdparty/freetype/include/freetype/internal/tttypes.h
index c0758e25fc..10dd336a89 100644
--- a/thirdparty/freetype/include/freetype/internal/tttypes.h
+++ b/thirdparty/freetype/include/freetype/internal/tttypes.h
@@ -5,7 +5,7 @@
/* Basic SFNT/TrueType type definitions and interface (specification */
/* only). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -148,7 +148,7 @@ FT_BEGIN_HEADER
/* <Fields> */
/* See */
/* */
- /* http://www.w3.org/TR/WOFF/#WOFFHeader */
+ /* https://www.w3.org/TR/WOFF/#WOFFHeader */
/* */
typedef struct WOFF_HeaderRec_
{
@@ -1299,10 +1299,6 @@ FT_BEGIN_HEADER
/* variation tables (rather like Multiple */
/* Master data). */
/* */
- /* is_default_instance :: Set if the glyph outlines can be used */
- /* unmodified (i.e., without applying glyph */
- /* variation deltas). */
- /* */
/* variation_support :: Flags that indicate which OpenType */
/* functionality related to font variation */
/* support is present, valid, and usable. */
@@ -1445,6 +1441,9 @@ FT_BEGIN_HEADER
void* var;
#endif
+ /* a typeless pointer to the PostScript Aux service */
+ void* psaux;
+
/***********************************************************************/
/* */
@@ -1509,7 +1508,6 @@ FT_BEGIN_HEADER
FT_Bool doblend;
GX_Blend blend;
- FT_Bool is_default_instance; /* since 2.7.1 */
FT_UInt32 variation_support; /* since 2.7.1 */
const char* var_postscript_prefix; /* since 2.7.2 */
diff --git a/thirdparty/freetype/include/freetype/t1tables.h b/thirdparty/freetype/include/freetype/t1tables.h
index 3f6b36e108..3503c2616b 100644
--- a/thirdparty/freetype/include/freetype/t1tables.h
+++ b/thirdparty/freetype/include/freetype/t1tables.h
@@ -5,7 +5,7 @@
/* Basic Type 1/Type 2 tables definitions and interface (specification */
/* only). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -554,6 +554,9 @@ FT_BEGIN_HEADER
/* T1_ENCODING_TYPE_ISOLATIN1 :: */
/* T1_ENCODING_TYPE_EXPERT :: */
/* */
+ /* <Since> */
+ /* 2.4.8 */
+ /* */
typedef enum T1_EncodingType_
{
T1_ENCODING_TYPE_NONE = 0,
@@ -622,6 +625,9 @@ FT_BEGIN_HEADER
/* PS_DICT_FS_TYPE :: */
/* PS_DICT_ITALIC_ANGLE :: */
/* */
+ /* <Since> */
+ /* 2.4.8 */
+ /* */
typedef enum PS_Dict_Keys_
{
/* conventionally in the font dictionary */
@@ -743,6 +749,9 @@ FT_BEGIN_HEADER
* If the font's format is not PostScript-based, this function returns
* the `FT_Err_Invalid_Argument' error code.
*
+ * @since:
+ * 2.4.8
+ *
*/
FT_EXPORT( FT_Long )
FT_Get_PS_Font_Value( FT_Face face,
diff --git a/thirdparty/freetype/include/freetype/ttnameid.h b/thirdparty/freetype/include/freetype/ttnameid.h
index 494d677186..8605183dc7 100644
--- a/thirdparty/freetype/include/freetype/ttnameid.h
+++ b/thirdparty/freetype/include/freetype/ttnameid.h
@@ -4,7 +4,7 @@
/* */
/* TrueType name ID definitions (specification only). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -437,7 +437,7 @@ FT_BEGIN_HEADER
*
* The canonical source for Microsoft's IDs is
*
- * http://www.microsoft.com/globaldev/reference/lcid-all.mspx ,
+ * https://www.microsoft.com/globaldev/reference/lcid-all.mspx ,
*
* however, we only provide macros for language identifiers present in
* the OpenType specification: Microsoft has abandoned the concept of
diff --git a/thirdparty/freetype/include/freetype/tttables.h b/thirdparty/freetype/include/freetype/tttables.h
index 58312044ca..ce6a61779c 100644
--- a/thirdparty/freetype/include/freetype/tttables.h
+++ b/thirdparty/freetype/include/freetype/tttables.h
@@ -5,7 +5,7 @@
/* Basic SFNT/TrueType tables definitions and interface */
/* (specification only). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/freetype/tttags.h b/thirdparty/freetype/include/freetype/tttags.h
index b7d3bac0f1..e5cee68a15 100644
--- a/thirdparty/freetype/include/freetype/tttags.h
+++ b/thirdparty/freetype/include/freetype/tttags.h
@@ -4,7 +4,7 @@
/* */
/* Tags for TrueType and OpenType tables (specification only). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/include/ft2build.h b/thirdparty/freetype/include/ft2build.h
index e7d808f3f4..e7ce99bc94 100644
--- a/thirdparty/freetype/include/ft2build.h
+++ b/thirdparty/freetype/include/ft2build.h
@@ -4,7 +4,7 @@
/* */
/* FreeType 2 build and setup macros. */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/afangles.c b/thirdparty/freetype/src/autofit/afangles.c
index ccdae84136..c65a3ae23e 100644
--- a/thirdparty/freetype/src/autofit/afangles.c
+++ b/thirdparty/freetype/src/autofit/afangles.c
@@ -5,7 +5,7 @@
/* Routines used to compute vector angles with limited accuracy */
/* and very high speed. It also contains sorting routines (body). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/afblue.c b/thirdparty/freetype/src/autofit/afblue.c
index fedeacf797..e4078fd044 100644
--- a/thirdparty/freetype/src/autofit/afblue.c
+++ b/thirdparty/freetype/src/autofit/afblue.c
@@ -7,7 +7,7 @@
/* */
/* Auto-fitter data for blue strings (body). */
/* */
-/* Copyright 2013-2017 by */
+/* Copyright 2013-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -166,6 +166,10 @@
'\0',
'\xE2', '\xB4', '\x84', ' ', '\xE2', '\xB4', '\x85', ' ', '\xE2', '\xB4', '\x94', ' ', '\xE2', '\xB4', '\x95', ' ', '\xE2', '\xB4', '\x81', ' ', '\xE2', '\xB4', '\x82', ' ', '\xE2', '\xB4', '\x98', ' ', '\xE2', '\xB4', '\x9D', /* ⴄ ⴅ ⴔ ⴕ ⴁ ⴂ ⴘ ⴝ */
'\0',
+ '\xE1', '\xB2', '\x9C', ' ', '\xE1', '\xB2', '\x9F', ' ', '\xE1', '\xB2', '\xB3', ' ', '\xE1', '\xB2', '\xB8', ' ', '\xE1', '\xB2', '\x92', ' ', '\xE1', '\xB2', '\x94', ' ', '\xE1', '\xB2', '\x9D', ' ', '\xE1', '\xB2', '\xB4', /* Ნ Ჟ Ჳ Ჸ Გ Ე Ო Ჴ */
+ '\0',
+ '\xE1', '\xB2', '\x98', ' ', '\xE1', '\xB2', '\xB2', ' ', '\xE1', '\xB2', '\x9D', ' ', '\xE1', '\xB2', '\xA9', ' ', '\xE1', '\xB2', '\x9B', ' ', '\xE1', '\xB2', '\xA8', ' ', '\xE1', '\xB2', '\xAF', ' ', '\xE1', '\xB2', '\xBD', /* Ი Ჲ Ო Ჩ Მ Შ Ჯ Ჽ */
+ '\0',
'\xE2', '\xB0', '\x85', ' ', '\xE2', '\xB0', '\x94', ' ', '\xE2', '\xB0', '\xAA', ' ', '\xE2', '\xB0', '\x84', ' ', '\xE2', '\xB0', '\x82', ' ', '\xE2', '\xB0', '\x8A', ' ', '\xE2', '\xB0', '\xAB', ' ', '\xE2', '\xB0', '\x8B', /* Ⰵ Ⱄ Ⱚ Ⰴ Ⰲ Ⰺ Ⱛ Ⰻ */
'\0',
'\xE2', '\xB0', '\x85', ' ', '\xE2', '\xB0', '\x84', ' ', '\xE2', '\xB0', '\x82', ' ', '\xE2', '\xB0', '\xAA', ' ', '\xE2', '\xB0', '\x9E', ' ', '\xE2', '\xB0', '\xA1', ' ', '\xE2', '\xB0', '\x8A', ' ', '\xE2', '\xB0', '\x94', /* Ⰵ Ⰴ Ⰲ Ⱚ Ⱎ Ⱑ Ⰺ Ⱄ */
@@ -539,6 +543,8 @@
{ AF_BLUE_STRING_GEORGIAN_MKHEDRULI_BOTTOM, 0 },
{ AF_BLUE_STRING_GEORGIAN_MKHEDRULI_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_GEORGIAN_MKHEDRULI_DESCENDER, 0 },
+ { AF_BLUE_STRING_GEORGIAN_MTAVRULI_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_GEORGIAN_MTAVRULI_BOTTOM, 0 },
{ AF_BLUE_STRING_MAX, 0 },
{ AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
{ AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_BOTTOM, 0 },
diff --git a/thirdparty/freetype/src/autofit/afblue.cin b/thirdparty/freetype/src/autofit/afblue.cin
index f9080c54d4..4913e2eb6f 100644
--- a/thirdparty/freetype/src/autofit/afblue.cin
+++ b/thirdparty/freetype/src/autofit/afblue.cin
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter data for blue strings (body). */
/* */
-/* Copyright 2013-2017 by */
+/* Copyright 2013-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/afblue.dat b/thirdparty/freetype/src/autofit/afblue.dat
index f62eb82a1a..bc2f0d2754 100644
--- a/thirdparty/freetype/src/autofit/afblue.dat
+++ b/thirdparty/freetype/src/autofit/afblue.dat
@@ -2,7 +2,7 @@
//
// Auto-fitter data for blue strings.
//
-// Copyright 2013-2017 by
+// Copyright 2013-2018 by
// David Turner, Robert Wilhelm, and Werner Lemberg.
//
// This file is part of the FreeType project, and may only be used,
@@ -242,6 +242,11 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN:
AF_BLUE_STRING_GEORGIAN_NUSKHURI_DESCENDER
"ⴄ ⴅ ⴔ ⴕ ⴁ ⴂ ⴘ ⴝ"
+ AF_BLUE_STRING_GEORGIAN_MTAVRULI_TOP
+ "Ნ Ჟ Ჳ Ჸ Გ Ე Ო Ჴ"
+ AF_BLUE_STRING_GEORGIAN_MTAVRULI_BOTTOM
+ "Ი Ჲ Ო Ჩ Მ Შ Ჯ Ჽ"
+
AF_BLUE_STRING_GLAGOLITIC_CAPITAL_TOP
"Ⰵ Ⱄ Ⱚ Ⰴ Ⰲ Ⰺ Ⱛ Ⰻ"
AF_BLUE_STRING_GLAGOLITIC_CAPITAL_BOTTOM
@@ -795,13 +800,14 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN:
{ AF_BLUE_STRING_ETHIOPIC_BOTTOM, 0 }
{ AF_BLUE_STRING_MAX, 0 }
- // blue zones for Mtavruli are missing (not yet defined in Unicode)
AF_BLUE_STRINGSET_GEOR
{ AF_BLUE_STRING_GEORGIAN_MKHEDRULI_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
{ AF_BLUE_STRING_GEORGIAN_MKHEDRULI_BOTTOM, 0 }
{ AF_BLUE_STRING_GEORGIAN_MKHEDRULI_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }
{ AF_BLUE_STRING_GEORGIAN_MKHEDRULI_DESCENDER, 0 }
+ { AF_BLUE_STRING_GEORGIAN_MTAVRULI_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_GEORGIAN_MTAVRULI_BOTTOM, 0 }
{ AF_BLUE_STRING_MAX, 0 }
AF_BLUE_STRINGSET_GEOK
diff --git a/thirdparty/freetype/src/autofit/afblue.h b/thirdparty/freetype/src/autofit/afblue.h
index 99ef51cd4a..de31e259c3 100644
--- a/thirdparty/freetype/src/autofit/afblue.h
+++ b/thirdparty/freetype/src/autofit/afblue.h
@@ -7,7 +7,7 @@
/* */
/* Auto-fitter data for blue strings (specification). */
/* */
-/* Copyright 2013-2017 by */
+/* Copyright 2013-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -147,119 +147,121 @@ FT_BEGIN_HEADER
AF_BLUE_STRING_GEORGIAN_NUSKHURI_BOTTOM = 1813,
AF_BLUE_STRING_GEORGIAN_NUSKHURI_ASCENDER = 1845,
AF_BLUE_STRING_GEORGIAN_NUSKHURI_DESCENDER = 1877,
- AF_BLUE_STRING_GLAGOLITIC_CAPITAL_TOP = 1909,
- AF_BLUE_STRING_GLAGOLITIC_CAPITAL_BOTTOM = 1941,
- AF_BLUE_STRING_GLAGOLITIC_SMALL_TOP = 1973,
- AF_BLUE_STRING_GLAGOLITIC_SMALL_BOTTOM = 2005,
- AF_BLUE_STRING_GOTHIC_TOP = 2037,
- AF_BLUE_STRING_GOTHIC_BOTTOM = 2077,
- AF_BLUE_STRING_GREEK_CAPITAL_TOP = 2097,
- AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM = 2118,
- AF_BLUE_STRING_GREEK_SMALL_BETA_TOP = 2136,
- AF_BLUE_STRING_GREEK_SMALL = 2154,
- AF_BLUE_STRING_GREEK_SMALL_DESCENDER = 2178,
- AF_BLUE_STRING_GUJARATI_TOP = 2202,
- AF_BLUE_STRING_GUJARATI_BOTTOM = 2234,
- AF_BLUE_STRING_GUJARATI_ASCENDER = 2266,
- AF_BLUE_STRING_GUJARATI_DESCENDER = 2316,
- AF_BLUE_STRING_GUJARATI_DIGIT_TOP = 2349,
- AF_BLUE_STRING_GURMUKHI_BASE = 2369,
- AF_BLUE_STRING_GURMUKHI_HEAD = 2401,
- AF_BLUE_STRING_GURMUKHI_TOP = 2433,
- AF_BLUE_STRING_GURMUKHI_BOTTOM = 2465,
- AF_BLUE_STRING_GURMUKHI_DIGIT_TOP = 2497,
- AF_BLUE_STRING_HEBREW_TOP = 2517,
- AF_BLUE_STRING_HEBREW_BOTTOM = 2541,
- AF_BLUE_STRING_HEBREW_DESCENDER = 2559,
- AF_BLUE_STRING_KANNADA_TOP = 2574,
- AF_BLUE_STRING_KANNADA_BOTTOM = 2618,
- AF_BLUE_STRING_KAYAH_LI_TOP = 2650,
- AF_BLUE_STRING_KAYAH_LI_BOTTOM = 2674,
- AF_BLUE_STRING_KAYAH_LI_ASCENDER = 2694,
- AF_BLUE_STRING_KAYAH_LI_DESCENDER = 2702,
- AF_BLUE_STRING_KAYAH_LI_LARGE_DESCENDER = 2714,
- AF_BLUE_STRING_KHMER_TOP = 2735,
- AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP = 2759,
- AF_BLUE_STRING_KHMER_BOTTOM = 2799,
- AF_BLUE_STRING_KHMER_DESCENDER = 2831,
- AF_BLUE_STRING_KHMER_LARGE_DESCENDER = 2865,
- AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP = 2952,
- AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM = 2960,
- AF_BLUE_STRING_LAO_TOP = 2968,
- AF_BLUE_STRING_LAO_BOTTOM = 3000,
- AF_BLUE_STRING_LAO_ASCENDER = 3032,
- AF_BLUE_STRING_LAO_LARGE_ASCENDER = 3048,
- AF_BLUE_STRING_LAO_DESCENDER = 3060,
- AF_BLUE_STRING_LATIN_CAPITAL_TOP = 3084,
- AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM = 3100,
- AF_BLUE_STRING_LATIN_SMALL_F_TOP = 3116,
- AF_BLUE_STRING_LATIN_SMALL_TOP = 3130,
- AF_BLUE_STRING_LATIN_SMALL_BOTTOM = 3146,
- AF_BLUE_STRING_LATIN_SMALL_DESCENDER = 3162,
- AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP = 3172,
- AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM = 3192,
- AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP = 3212,
- AF_BLUE_STRING_LATIN_SUBS_SMALL = 3232,
- AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER = 3268,
- AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP = 3288,
- AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM = 3319,
- AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP = 3348,
- AF_BLUE_STRING_LATIN_SUPS_SMALL = 3374,
- AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER = 3399,
- AF_BLUE_STRING_LISU_TOP = 3410,
- AF_BLUE_STRING_LISU_BOTTOM = 3442,
- AF_BLUE_STRING_MALAYALAM_TOP = 3474,
- AF_BLUE_STRING_MALAYALAM_BOTTOM = 3518,
- AF_BLUE_STRING_MYANMAR_TOP = 3550,
- AF_BLUE_STRING_MYANMAR_BOTTOM = 3582,
- AF_BLUE_STRING_MYANMAR_ASCENDER = 3614,
- AF_BLUE_STRING_MYANMAR_DESCENDER = 3642,
- AF_BLUE_STRING_NKO_TOP = 3674,
- AF_BLUE_STRING_NKO_BOTTOM = 3698,
- AF_BLUE_STRING_NKO_SMALL_TOP = 3713,
- AF_BLUE_STRING_NKO_SMALL_BOTTOM = 3722,
- AF_BLUE_STRING_OL_CHIKI = 3734,
- AF_BLUE_STRING_OLD_TURKIC_TOP = 3758,
- AF_BLUE_STRING_OLD_TURKIC_BOTTOM = 3773,
- AF_BLUE_STRING_OSAGE_CAPITAL_TOP = 3793,
- AF_BLUE_STRING_OSAGE_CAPITAL_BOTTOM = 3833,
- AF_BLUE_STRING_OSAGE_CAPITAL_DESCENDER = 3863,
- AF_BLUE_STRING_OSAGE_SMALL_TOP = 3878,
- AF_BLUE_STRING_OSAGE_SMALL_BOTTOM = 3918,
- AF_BLUE_STRING_OSAGE_SMALL_ASCENDER = 3958,
- AF_BLUE_STRING_OSAGE_SMALL_DESCENDER = 3983,
- AF_BLUE_STRING_OSMANYA_TOP = 3998,
- AF_BLUE_STRING_OSMANYA_BOTTOM = 4038,
- AF_BLUE_STRING_SAURASHTRA_TOP = 4078,
- AF_BLUE_STRING_SAURASHTRA_BOTTOM = 4110,
- AF_BLUE_STRING_SHAVIAN_TOP = 4130,
- AF_BLUE_STRING_SHAVIAN_BOTTOM = 4140,
- AF_BLUE_STRING_SHAVIAN_DESCENDER = 4165,
- AF_BLUE_STRING_SHAVIAN_SMALL_TOP = 4175,
- AF_BLUE_STRING_SHAVIAN_SMALL_BOTTOM = 4210,
- AF_BLUE_STRING_SINHALA_TOP = 4225,
- AF_BLUE_STRING_SINHALA_BOTTOM = 4257,
- AF_BLUE_STRING_SINHALA_DESCENDER = 4289,
- AF_BLUE_STRING_SUNDANESE_TOP = 4333,
- AF_BLUE_STRING_SUNDANESE_BOTTOM = 4357,
- AF_BLUE_STRING_SUNDANESE_DESCENDER = 4389,
- AF_BLUE_STRING_TAI_VIET_TOP = 4397,
- AF_BLUE_STRING_TAI_VIET_BOTTOM = 4417,
- AF_BLUE_STRING_TAMIL_TOP = 4429,
- AF_BLUE_STRING_TAMIL_BOTTOM = 4461,
- AF_BLUE_STRING_TELUGU_TOP = 4493,
- AF_BLUE_STRING_TELUGU_BOTTOM = 4521,
- AF_BLUE_STRING_THAI_TOP = 4549,
- AF_BLUE_STRING_THAI_BOTTOM = 4573,
- AF_BLUE_STRING_THAI_ASCENDER = 4601,
- AF_BLUE_STRING_THAI_LARGE_ASCENDER = 4613,
- AF_BLUE_STRING_THAI_DESCENDER = 4625,
- AF_BLUE_STRING_THAI_LARGE_DESCENDER = 4641,
- AF_BLUE_STRING_THAI_DIGIT_TOP = 4649,
- AF_BLUE_STRING_TIFINAGH = 4661,
- AF_BLUE_STRING_VAI_TOP = 4693,
- AF_BLUE_STRING_VAI_BOTTOM = 4725,
- af_blue_1_1 = 4756,
+ AF_BLUE_STRING_GEORGIAN_MTAVRULI_TOP = 1909,
+ AF_BLUE_STRING_GEORGIAN_MTAVRULI_BOTTOM = 1941,
+ AF_BLUE_STRING_GLAGOLITIC_CAPITAL_TOP = 1973,
+ AF_BLUE_STRING_GLAGOLITIC_CAPITAL_BOTTOM = 2005,
+ AF_BLUE_STRING_GLAGOLITIC_SMALL_TOP = 2037,
+ AF_BLUE_STRING_GLAGOLITIC_SMALL_BOTTOM = 2069,
+ AF_BLUE_STRING_GOTHIC_TOP = 2101,
+ AF_BLUE_STRING_GOTHIC_BOTTOM = 2141,
+ AF_BLUE_STRING_GREEK_CAPITAL_TOP = 2161,
+ AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM = 2182,
+ AF_BLUE_STRING_GREEK_SMALL_BETA_TOP = 2200,
+ AF_BLUE_STRING_GREEK_SMALL = 2218,
+ AF_BLUE_STRING_GREEK_SMALL_DESCENDER = 2242,
+ AF_BLUE_STRING_GUJARATI_TOP = 2266,
+ AF_BLUE_STRING_GUJARATI_BOTTOM = 2298,
+ AF_BLUE_STRING_GUJARATI_ASCENDER = 2330,
+ AF_BLUE_STRING_GUJARATI_DESCENDER = 2380,
+ AF_BLUE_STRING_GUJARATI_DIGIT_TOP = 2413,
+ AF_BLUE_STRING_GURMUKHI_BASE = 2433,
+ AF_BLUE_STRING_GURMUKHI_HEAD = 2465,
+ AF_BLUE_STRING_GURMUKHI_TOP = 2497,
+ AF_BLUE_STRING_GURMUKHI_BOTTOM = 2529,
+ AF_BLUE_STRING_GURMUKHI_DIGIT_TOP = 2561,
+ AF_BLUE_STRING_HEBREW_TOP = 2581,
+ AF_BLUE_STRING_HEBREW_BOTTOM = 2605,
+ AF_BLUE_STRING_HEBREW_DESCENDER = 2623,
+ AF_BLUE_STRING_KANNADA_TOP = 2638,
+ AF_BLUE_STRING_KANNADA_BOTTOM = 2682,
+ AF_BLUE_STRING_KAYAH_LI_TOP = 2714,
+ AF_BLUE_STRING_KAYAH_LI_BOTTOM = 2738,
+ AF_BLUE_STRING_KAYAH_LI_ASCENDER = 2758,
+ AF_BLUE_STRING_KAYAH_LI_DESCENDER = 2766,
+ AF_BLUE_STRING_KAYAH_LI_LARGE_DESCENDER = 2778,
+ AF_BLUE_STRING_KHMER_TOP = 2799,
+ AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP = 2823,
+ AF_BLUE_STRING_KHMER_BOTTOM = 2863,
+ AF_BLUE_STRING_KHMER_DESCENDER = 2895,
+ AF_BLUE_STRING_KHMER_LARGE_DESCENDER = 2929,
+ AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP = 3016,
+ AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM = 3024,
+ AF_BLUE_STRING_LAO_TOP = 3032,
+ AF_BLUE_STRING_LAO_BOTTOM = 3064,
+ AF_BLUE_STRING_LAO_ASCENDER = 3096,
+ AF_BLUE_STRING_LAO_LARGE_ASCENDER = 3112,
+ AF_BLUE_STRING_LAO_DESCENDER = 3124,
+ AF_BLUE_STRING_LATIN_CAPITAL_TOP = 3148,
+ AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM = 3164,
+ AF_BLUE_STRING_LATIN_SMALL_F_TOP = 3180,
+ AF_BLUE_STRING_LATIN_SMALL_TOP = 3194,
+ AF_BLUE_STRING_LATIN_SMALL_BOTTOM = 3210,
+ AF_BLUE_STRING_LATIN_SMALL_DESCENDER = 3226,
+ AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP = 3236,
+ AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM = 3256,
+ AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP = 3276,
+ AF_BLUE_STRING_LATIN_SUBS_SMALL = 3296,
+ AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER = 3332,
+ AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP = 3352,
+ AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM = 3383,
+ AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP = 3412,
+ AF_BLUE_STRING_LATIN_SUPS_SMALL = 3438,
+ AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER = 3463,
+ AF_BLUE_STRING_LISU_TOP = 3474,
+ AF_BLUE_STRING_LISU_BOTTOM = 3506,
+ AF_BLUE_STRING_MALAYALAM_TOP = 3538,
+ AF_BLUE_STRING_MALAYALAM_BOTTOM = 3582,
+ AF_BLUE_STRING_MYANMAR_TOP = 3614,
+ AF_BLUE_STRING_MYANMAR_BOTTOM = 3646,
+ AF_BLUE_STRING_MYANMAR_ASCENDER = 3678,
+ AF_BLUE_STRING_MYANMAR_DESCENDER = 3706,
+ AF_BLUE_STRING_NKO_TOP = 3738,
+ AF_BLUE_STRING_NKO_BOTTOM = 3762,
+ AF_BLUE_STRING_NKO_SMALL_TOP = 3777,
+ AF_BLUE_STRING_NKO_SMALL_BOTTOM = 3786,
+ AF_BLUE_STRING_OL_CHIKI = 3798,
+ AF_BLUE_STRING_OLD_TURKIC_TOP = 3822,
+ AF_BLUE_STRING_OLD_TURKIC_BOTTOM = 3837,
+ AF_BLUE_STRING_OSAGE_CAPITAL_TOP = 3857,
+ AF_BLUE_STRING_OSAGE_CAPITAL_BOTTOM = 3897,
+ AF_BLUE_STRING_OSAGE_CAPITAL_DESCENDER = 3927,
+ AF_BLUE_STRING_OSAGE_SMALL_TOP = 3942,
+ AF_BLUE_STRING_OSAGE_SMALL_BOTTOM = 3982,
+ AF_BLUE_STRING_OSAGE_SMALL_ASCENDER = 4022,
+ AF_BLUE_STRING_OSAGE_SMALL_DESCENDER = 4047,
+ AF_BLUE_STRING_OSMANYA_TOP = 4062,
+ AF_BLUE_STRING_OSMANYA_BOTTOM = 4102,
+ AF_BLUE_STRING_SAURASHTRA_TOP = 4142,
+ AF_BLUE_STRING_SAURASHTRA_BOTTOM = 4174,
+ AF_BLUE_STRING_SHAVIAN_TOP = 4194,
+ AF_BLUE_STRING_SHAVIAN_BOTTOM = 4204,
+ AF_BLUE_STRING_SHAVIAN_DESCENDER = 4229,
+ AF_BLUE_STRING_SHAVIAN_SMALL_TOP = 4239,
+ AF_BLUE_STRING_SHAVIAN_SMALL_BOTTOM = 4274,
+ AF_BLUE_STRING_SINHALA_TOP = 4289,
+ AF_BLUE_STRING_SINHALA_BOTTOM = 4321,
+ AF_BLUE_STRING_SINHALA_DESCENDER = 4353,
+ AF_BLUE_STRING_SUNDANESE_TOP = 4397,
+ AF_BLUE_STRING_SUNDANESE_BOTTOM = 4421,
+ AF_BLUE_STRING_SUNDANESE_DESCENDER = 4453,
+ AF_BLUE_STRING_TAI_VIET_TOP = 4461,
+ AF_BLUE_STRING_TAI_VIET_BOTTOM = 4481,
+ AF_BLUE_STRING_TAMIL_TOP = 4493,
+ AF_BLUE_STRING_TAMIL_BOTTOM = 4525,
+ AF_BLUE_STRING_TELUGU_TOP = 4557,
+ AF_BLUE_STRING_TELUGU_BOTTOM = 4585,
+ AF_BLUE_STRING_THAI_TOP = 4613,
+ AF_BLUE_STRING_THAI_BOTTOM = 4637,
+ AF_BLUE_STRING_THAI_ASCENDER = 4665,
+ AF_BLUE_STRING_THAI_LARGE_ASCENDER = 4677,
+ AF_BLUE_STRING_THAI_DESCENDER = 4689,
+ AF_BLUE_STRING_THAI_LARGE_DESCENDER = 4705,
+ AF_BLUE_STRING_THAI_DIGIT_TOP = 4713,
+ AF_BLUE_STRING_TIFINAGH = 4725,
+ AF_BLUE_STRING_VAI_TOP = 4757,
+ AF_BLUE_STRING_VAI_BOTTOM = 4789,
+ af_blue_1_1 = 4820,
#ifdef AF_CONFIG_OPTION_CJK
AF_BLUE_STRING_CJK_TOP = af_blue_1_1 + 1,
AF_BLUE_STRING_CJK_BOTTOM = af_blue_1_1 + 203,
@@ -336,41 +338,41 @@ FT_BEGIN_HEADER
AF_BLUE_STRINGSET_DSRT = 75,
AF_BLUE_STRINGSET_ETHI = 80,
AF_BLUE_STRINGSET_GEOR = 83,
- AF_BLUE_STRINGSET_GEOK = 88,
- AF_BLUE_STRINGSET_GLAG = 95,
- AF_BLUE_STRINGSET_GOTH = 100,
- AF_BLUE_STRINGSET_GREK = 103,
- AF_BLUE_STRINGSET_GUJR = 110,
- AF_BLUE_STRINGSET_GURU = 116,
- AF_BLUE_STRINGSET_HEBR = 122,
- AF_BLUE_STRINGSET_KALI = 126,
- AF_BLUE_STRINGSET_KHMR = 132,
- AF_BLUE_STRINGSET_KHMS = 138,
- AF_BLUE_STRINGSET_KNDA = 141,
- AF_BLUE_STRINGSET_LAO = 144,
- AF_BLUE_STRINGSET_LATN = 150,
- AF_BLUE_STRINGSET_LATB = 157,
- AF_BLUE_STRINGSET_LATP = 164,
- AF_BLUE_STRINGSET_LISU = 171,
- AF_BLUE_STRINGSET_MLYM = 174,
- AF_BLUE_STRINGSET_MYMR = 177,
- AF_BLUE_STRINGSET_NKOO = 182,
- AF_BLUE_STRINGSET_NONE = 187,
- AF_BLUE_STRINGSET_OLCK = 188,
- AF_BLUE_STRINGSET_ORKH = 191,
- AF_BLUE_STRINGSET_OSGE = 194,
- AF_BLUE_STRINGSET_OSMA = 202,
- AF_BLUE_STRINGSET_SAUR = 205,
- AF_BLUE_STRINGSET_SHAW = 208,
- AF_BLUE_STRINGSET_SINH = 214,
- AF_BLUE_STRINGSET_SUND = 218,
- AF_BLUE_STRINGSET_TAML = 222,
- AF_BLUE_STRINGSET_TAVT = 225,
- AF_BLUE_STRINGSET_TELU = 228,
- AF_BLUE_STRINGSET_TFNG = 231,
- AF_BLUE_STRINGSET_THAI = 234,
- AF_BLUE_STRINGSET_VAII = 242,
- af_blue_2_1 = 245,
+ AF_BLUE_STRINGSET_GEOK = 90,
+ AF_BLUE_STRINGSET_GLAG = 97,
+ AF_BLUE_STRINGSET_GOTH = 102,
+ AF_BLUE_STRINGSET_GREK = 105,
+ AF_BLUE_STRINGSET_GUJR = 112,
+ AF_BLUE_STRINGSET_GURU = 118,
+ AF_BLUE_STRINGSET_HEBR = 124,
+ AF_BLUE_STRINGSET_KALI = 128,
+ AF_BLUE_STRINGSET_KHMR = 134,
+ AF_BLUE_STRINGSET_KHMS = 140,
+ AF_BLUE_STRINGSET_KNDA = 143,
+ AF_BLUE_STRINGSET_LAO = 146,
+ AF_BLUE_STRINGSET_LATN = 152,
+ AF_BLUE_STRINGSET_LATB = 159,
+ AF_BLUE_STRINGSET_LATP = 166,
+ AF_BLUE_STRINGSET_LISU = 173,
+ AF_BLUE_STRINGSET_MLYM = 176,
+ AF_BLUE_STRINGSET_MYMR = 179,
+ AF_BLUE_STRINGSET_NKOO = 184,
+ AF_BLUE_STRINGSET_NONE = 189,
+ AF_BLUE_STRINGSET_OLCK = 190,
+ AF_BLUE_STRINGSET_ORKH = 193,
+ AF_BLUE_STRINGSET_OSGE = 196,
+ AF_BLUE_STRINGSET_OSMA = 204,
+ AF_BLUE_STRINGSET_SAUR = 207,
+ AF_BLUE_STRINGSET_SHAW = 210,
+ AF_BLUE_STRINGSET_SINH = 216,
+ AF_BLUE_STRINGSET_SUND = 220,
+ AF_BLUE_STRINGSET_TAML = 224,
+ AF_BLUE_STRINGSET_TAVT = 227,
+ AF_BLUE_STRINGSET_TELU = 230,
+ AF_BLUE_STRINGSET_TFNG = 233,
+ AF_BLUE_STRINGSET_THAI = 236,
+ AF_BLUE_STRINGSET_VAII = 244,
+ af_blue_2_1 = 247,
#ifdef AF_CONFIG_OPTION_CJK
AF_BLUE_STRINGSET_HANI = af_blue_2_1 + 0,
af_blue_2_1_1 = af_blue_2_1 + 2,
diff --git a/thirdparty/freetype/src/autofit/afblue.hin b/thirdparty/freetype/src/autofit/afblue.hin
index 268bcbc531..682147cb30 100644
--- a/thirdparty/freetype/src/autofit/afblue.hin
+++ b/thirdparty/freetype/src/autofit/afblue.hin
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter data for blue strings (specification). */
/* */
-/* Copyright 2013-2017 by */
+/* Copyright 2013-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/afcjk.c b/thirdparty/freetype/src/autofit/afcjk.c
index 897533d148..21b6bffa33 100644
--- a/thirdparty/freetype/src/autofit/afcjk.c
+++ b/thirdparty/freetype/src/autofit/afcjk.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter hinting routines for CJK writing system (body). */
/* */
-/* Copyright 2006-2017 by */
+/* Copyright 2006-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -16,9 +16,9 @@
/***************************************************************************/
/*
- * The algorithm is based on akito's autohint patch, available here:
+ * The algorithm is based on akito's autohint patch, archived at
*
- * http://www.kde.gr.jp/~akito/patch/freetype2/
+ * https://web.archive.org/web/20051219160454/http://www.kde.gr.jp:80/~akito/patch/freetype2/2.1.7/
*
*/
diff --git a/thirdparty/freetype/src/autofit/afcjk.h b/thirdparty/freetype/src/autofit/afcjk.h
index 84f892f909..d229c0c9cf 100644
--- a/thirdparty/freetype/src/autofit/afcjk.h
+++ b/thirdparty/freetype/src/autofit/afcjk.h
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter hinting routines for CJK writing system (specification). */
/* */
-/* Copyright 2006-2017 by */
+/* Copyright 2006-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/afcover.h b/thirdparty/freetype/src/autofit/afcover.h
index 1b18c666ab..6eeb8fc9fb 100644
--- a/thirdparty/freetype/src/autofit/afcover.h
+++ b/thirdparty/freetype/src/autofit/afcover.h
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter coverages (specification only). */
/* */
-/* Copyright 2013-2017 by */
+/* Copyright 2013-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/afdummy.c b/thirdparty/freetype/src/autofit/afdummy.c
index 61c32db5bf..f30c517cbb 100644
--- a/thirdparty/freetype/src/autofit/afdummy.c
+++ b/thirdparty/freetype/src/autofit/afdummy.c
@@ -5,7 +5,7 @@
/* Auto-fitter dummy routines to be used if no hinting should be */
/* performed (body). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/afdummy.h b/thirdparty/freetype/src/autofit/afdummy.h
index ebaa7d76ea..b382acd92a 100644
--- a/thirdparty/freetype/src/autofit/afdummy.h
+++ b/thirdparty/freetype/src/autofit/afdummy.h
@@ -5,7 +5,7 @@
/* Auto-fitter dummy routines to be used if no hinting should be */
/* performed (specification). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/aferrors.h b/thirdparty/freetype/src/autofit/aferrors.h
index dde182f3c8..e5de54360f 100644
--- a/thirdparty/freetype/src/autofit/aferrors.h
+++ b/thirdparty/freetype/src/autofit/aferrors.h
@@ -4,7 +4,7 @@
/* */
/* Autofitter error codes (specification only). */
/* */
-/* Copyright 2005-2017 by */
+/* Copyright 2005-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/afglobal.c b/thirdparty/freetype/src/autofit/afglobal.c
index 85bef001f7..3d09c53e8a 100644
--- a/thirdparty/freetype/src/autofit/afglobal.c
+++ b/thirdparty/freetype/src/autofit/afglobal.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter routines to compute global hinting values (body). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/afglobal.h b/thirdparty/freetype/src/autofit/afglobal.h
index de6142ea26..489ed46d9e 100644
--- a/thirdparty/freetype/src/autofit/afglobal.h
+++ b/thirdparty/freetype/src/autofit/afglobal.h
@@ -5,7 +5,7 @@
/* Auto-fitter routines to compute global hinting values */
/* (specification). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/afhints.c b/thirdparty/freetype/src/autofit/afhints.c
index 1b21c06c2c..0666dbc8e2 100644
--- a/thirdparty/freetype/src/autofit/afhints.c
+++ b/thirdparty/freetype/src/autofit/afhints.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter hinting routines (body). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -314,8 +314,12 @@
AF_DUMP(( "Table of points:\n" ));
if ( hints->num_points )
+ {
AF_DUMP(( " index hedge hseg vedge vseg flags "
+ /* " XXXXX XXXXX XXXXX XXXXX XXXXX XXXXXX" */
" xorg yorg xscale yscale xfit yfit" ));
+ /* " XXXXX XXXXX XXXX.XX XXXX.XX XXXX.XX XXXX.XX" */
+ }
else
AF_DUMP(( " (none)\n" ));
@@ -420,9 +424,14 @@
dimension == AF_DIMENSION_HORZ ? "vertical"
: "horizontal" ));
if ( axis->num_segments )
+ {
AF_DUMP(( " index pos delta dir from to "
+ /* " XXXXX XXXXX XXXXX XXXXX XXXX XXXX" */
" link serif edge"
+ /* " XXXX XXXXX XXXX" */
" height extra flags\n" ));
+ /* " XXXXXX XXXXX XXXXXXXXXXX" */
+ }
else
AF_DUMP(( " (none)\n" ));
@@ -564,8 +573,12 @@
10.0 * hints->y_scale / 65536.0 / 64.0 ));
if ( axis->num_edges )
+ {
AF_DUMP(( " index pos dir link serif"
+ /* " XXXXX XXXX.XX XXXXX XXXX XXXXX" */
" blue opos pos flags\n" ));
+ /* " X XXXX.XX XXXX.XX XXXXXXXXXXX" */
+ }
else
AF_DUMP(( " (none)\n" ));
diff --git a/thirdparty/freetype/src/autofit/afhints.h b/thirdparty/freetype/src/autofit/afhints.h
index 16638b1030..3326ebc44e 100644
--- a/thirdparty/freetype/src/autofit/afhints.h
+++ b/thirdparty/freetype/src/autofit/afhints.h
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter hinting routines (specification). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -62,7 +62,7 @@ FT_BEGIN_HEADER
*
* by David Turner and Werner Lemberg
*
- * http://www.tug.org/TUGboat/Articles/tb24-3/lemberg.pdf
+ * https://www.tug.org/TUGboat/Articles/tb24-3/lemberg.pdf
*
* with appropriate updates.
*
diff --git a/thirdparty/freetype/src/autofit/afindic.c b/thirdparty/freetype/src/autofit/afindic.c
index 23be46ed51..dfbea5f34c 100644
--- a/thirdparty/freetype/src/autofit/afindic.c
+++ b/thirdparty/freetype/src/autofit/afindic.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter hinting routines for Indic writing system (body). */
/* */
-/* Copyright 2007-2017 by */
+/* Copyright 2007-2018 by */
/* Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/afindic.h b/thirdparty/freetype/src/autofit/afindic.h
index ec9e263161..5688738e6e 100644
--- a/thirdparty/freetype/src/autofit/afindic.h
+++ b/thirdparty/freetype/src/autofit/afindic.h
@@ -5,7 +5,7 @@
/* Auto-fitter hinting routines for Indic writing system */
/* (specification). */
/* */
-/* Copyright 2007-2017 by */
+/* Copyright 2007-2018 by */
/* Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/aflatin.c b/thirdparty/freetype/src/autofit/aflatin.c
index 02b3b8bbd3..9f1b54056f 100644
--- a/thirdparty/freetype/src/autofit/aflatin.c
+++ b/thirdparty/freetype/src/autofit/aflatin.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter hinting routines for latin writing system (body). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/aflatin.h b/thirdparty/freetype/src/autofit/aflatin.h
index d80e125ddc..432cccce4e 100644
--- a/thirdparty/freetype/src/autofit/aflatin.h
+++ b/thirdparty/freetype/src/autofit/aflatin.h
@@ -5,7 +5,7 @@
/* Auto-fitter hinting routines for latin writing system */
/* (specification). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/aflatin2.c b/thirdparty/freetype/src/autofit/aflatin2.c
index fb42445116..5c71378118 100644
--- a/thirdparty/freetype/src/autofit/aflatin2.c
+++ b/thirdparty/freetype/src/autofit/aflatin2.c
@@ -9,7 +9,7 @@
/* */
/* Auto-fitter hinting routines for latin writing system (body). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/aflatin2.h b/thirdparty/freetype/src/autofit/aflatin2.h
index 2d0b154f58..0129dc707e 100644
--- a/thirdparty/freetype/src/autofit/aflatin2.h
+++ b/thirdparty/freetype/src/autofit/aflatin2.h
@@ -10,7 +10,7 @@
/* Auto-fitter hinting routines for latin writing system */
/* (specification). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/afloader.c b/thirdparty/freetype/src/autofit/afloader.c
index 067ebd17f6..a55550b338 100644
--- a/thirdparty/freetype/src/autofit/afloader.c
+++ b/thirdparty/freetype/src/autofit/afloader.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter glyph loading routines (body). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/afloader.h b/thirdparty/freetype/src/autofit/afloader.h
index 2578abed16..d4d72d1583 100644
--- a/thirdparty/freetype/src/autofit/afloader.h
+++ b/thirdparty/freetype/src/autofit/afloader.h
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter glyph loading routines (specification). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/afmodule.c b/thirdparty/freetype/src/autofit/afmodule.c
index 9d7ba224da..dcaa17a27e 100644
--- a/thirdparty/freetype/src/autofit/afmodule.c
+++ b/thirdparty/freetype/src/autofit/afmodule.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter module implementation (body). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -56,7 +56,7 @@
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_DEBUG_H
-#include FT_AUTOHINTER_H
+#include FT_DRIVER_H
#include FT_SERVICE_PROPERTIES_H
diff --git a/thirdparty/freetype/src/autofit/afmodule.h b/thirdparty/freetype/src/autofit/afmodule.h
index 0571d14d59..56f64eaf23 100644
--- a/thirdparty/freetype/src/autofit/afmodule.h
+++ b/thirdparty/freetype/src/autofit/afmodule.h
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter module implementation (specification). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/afpic.c b/thirdparty/freetype/src/autofit/afpic.c
index 3125e03e27..d48d016a0e 100644
--- a/thirdparty/freetype/src/autofit/afpic.c
+++ b/thirdparty/freetype/src/autofit/afpic.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for autofit module. */
/* */
-/* Copyright 2009-2017 by */
+/* Copyright 2009-2018 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/afpic.h b/thirdparty/freetype/src/autofit/afpic.h
index 8cd3392123..0c73456785 100644
--- a/thirdparty/freetype/src/autofit/afpic.h
+++ b/thirdparty/freetype/src/autofit/afpic.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for autofit module. */
/* */
-/* Copyright 2009-2017 by */
+/* Copyright 2009-2018 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/afranges.c b/thirdparty/freetype/src/autofit/afranges.c
index 7f37eea1e0..cf67fafb11 100644
--- a/thirdparty/freetype/src/autofit/afranges.c
+++ b/thirdparty/freetype/src/autofit/afranges.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter Unicode script ranges (body). */
/* */
-/* Copyright 2013-2017 by */
+/* Copyright 2013-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -91,7 +91,7 @@
AF_UNIRANGE_REC( 0x06E7, 0x06E8 ),
AF_UNIRANGE_REC( 0x06EA, 0x06ED ),
AF_UNIRANGE_REC( 0x08D4, 0x08E1 ),
- AF_UNIRANGE_REC( 0x08E3, 0x08FF ),
+ AF_UNIRANGE_REC( 0x08D3, 0x08FF ),
AF_UNIRANGE_REC( 0xFBB2, 0xFBC1 ),
AF_UNIRANGE_REC( 0xFE70, 0xFE70 ),
AF_UNIRANGE_REC( 0xFE72, 0xFE72 ),
@@ -163,6 +163,7 @@
AF_UNIRANGE_REC( 0x09C1, 0x09C4 ),
AF_UNIRANGE_REC( 0x09CD, 0x09CD ),
AF_UNIRANGE_REC( 0x09E2, 0x09E3 ),
+ AF_UNIRANGE_REC( 0x09FE, 0x09FE ),
AF_UNIRANGE_REC( 0, 0 )
};
@@ -190,6 +191,7 @@
{
AF_UNIRANGE_REC( 0x11100, 0x11102 ),
AF_UNIRANGE_REC( 0x11127, 0x11134 ),
+ AF_UNIRANGE_REC( 0x11146, 0x11146 ),
AF_UNIRANGE_REC( 0, 0 )
};
@@ -304,6 +306,7 @@
AF_UNIRANGE_REC( 0x0953, 0x0957 ),
AF_UNIRANGE_REC( 0x0962, 0x0963 ),
AF_UNIRANGE_REC( 0xA8E0, 0xA8F1 ),
+ AF_UNIRANGE_REC( 0xA8FF, 0xA8FF ),
AF_UNIRANGE_REC( 0, 0 )
};
@@ -338,11 +341,8 @@
const AF_Script_UniRangeRec af_geor_uniranges[] =
{
- AF_UNIRANGE_REC( 0x10D0, 0x10FF ), /* Georgian (Mkhedruli) */
-#if 0
- /* the following range is proposed for inclusion in Unicode */
- AF_UNIRANGE_REC( 0x1C90, 0x1CBF ), /* Georgian (Mtavruli) */
-#endif
+ AF_UNIRANGE_REC( 0x10D0, 0x10FF ), /* Georgian (Mkhedruli) */
+ AF_UNIRANGE_REC( 0x1C90, 0x1CBF ), /* Georgian Extended (Mtavruli) */
AF_UNIRANGE_REC( 0, 0 )
};
@@ -355,8 +355,8 @@
const AF_Script_UniRangeRec af_geok_uniranges[] =
{
/* Khutsuri */
- AF_UNIRANGE_REC( 0x10A0, 0x10CD ), /* Georgian (Asomtavruli) */
- AF_UNIRANGE_REC( 0x2D00, 0x2D2D ), /* Georgian (Nuskhuri) */
+ AF_UNIRANGE_REC( 0x10A0, 0x10CD ), /* Georgian (Asomtavruli) */
+ AF_UNIRANGE_REC( 0x2D00, 0x2D2D ), /* Georgian Supplement (Nuskhuri) */
AF_UNIRANGE_REC( 0, 0 )
};
@@ -425,6 +425,7 @@
AF_UNIRANGE_REC( 0x0AC1, 0x0AC8 ),
AF_UNIRANGE_REC( 0x0ACD, 0x0ACD ),
AF_UNIRANGE_REC( 0x0AE2, 0x0AE3 ),
+ AF_UNIRANGE_REC( 0x0AFA, 0x0AFF ),
AF_UNIRANGE_REC( 0, 0 )
};
@@ -655,7 +656,8 @@
const AF_Script_UniRangeRec af_mlym_nonbase_uniranges[] =
{
- AF_UNIRANGE_REC( 0x0D01, 0x0D01 ),
+ AF_UNIRANGE_REC( 0x0D00, 0x0D01 ),
+ AF_UNIRANGE_REC( 0x0D3B, 0x0D3C ),
AF_UNIRANGE_REC( 0x0D4D, 0x0D4E ),
AF_UNIRANGE_REC( 0x0D62, 0x0D63 ),
AF_UNIRANGE_REC( 0, 0 )
@@ -697,6 +699,7 @@
const AF_Script_UniRangeRec af_nkoo_nonbase_uniranges[] =
{
AF_UNIRANGE_REC( 0x07EB, 0x07F5 ),
+ AF_UNIRANGE_REC( 0x07FD, 0x07FD ),
AF_UNIRANGE_REC( 0, 0 )
};
@@ -856,6 +859,7 @@
const AF_Script_UniRangeRec af_telu_nonbase_uniranges[] =
{
AF_UNIRANGE_REC( 0x0C00, 0x0C00 ),
+ AF_UNIRANGE_REC( 0x0C04, 0x0C04 ),
AF_UNIRANGE_REC( 0x0C3E, 0x0C40 ),
AF_UNIRANGE_REC( 0x0C46, 0x0C56 ),
AF_UNIRANGE_REC( 0x0C62, 0x0C63 ),
@@ -1006,10 +1010,13 @@
AF_UNIRANGE_REC( 0xFE30, 0xFE4F ), /* CJK Compatibility Forms */
AF_UNIRANGE_REC( 0xFF00, 0xFFEF ), /* Halfwidth and Fullwidth Forms */
AF_UNIRANGE_REC( 0x1B000, 0x1B0FF ), /* Kana Supplement */
+ AF_UNIRANGE_REC( 0x1B100, 0x1B12F ), /* Kana Extended-A */
AF_UNIRANGE_REC( 0x1D300, 0x1D35F ), /* Tai Xuan Hing Symbols */
AF_UNIRANGE_REC( 0x20000, 0x2A6DF ), /* CJK Unified Ideographs Extension B */
AF_UNIRANGE_REC( 0x2A700, 0x2B73F ), /* CJK Unified Ideographs Extension C */
AF_UNIRANGE_REC( 0x2B740, 0x2B81F ), /* CJK Unified Ideographs Extension D */
+ AF_UNIRANGE_REC( 0x2B820, 0x2CEAF ), /* CJK Unified Ideographs Extension E */
+ AF_UNIRANGE_REC( 0x2CEB0, 0x2EBEF ), /* CJK Unified Ideographs Extension F */
AF_UNIRANGE_REC( 0x2F800, 0x2FA1F ), /* CJK Compatibility Ideographs Supplement */
AF_UNIRANGE_REC( 0, 0 )
};
diff --git a/thirdparty/freetype/src/autofit/afranges.h b/thirdparty/freetype/src/autofit/afranges.h
index 72d9eaad2c..ba3b5e7ccb 100644
--- a/thirdparty/freetype/src/autofit/afranges.h
+++ b/thirdparty/freetype/src/autofit/afranges.h
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter Unicode script ranges (specification). */
/* */
-/* Copyright 2013-2017 by */
+/* Copyright 2013-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/afscript.h b/thirdparty/freetype/src/autofit/afscript.h
index cb815dbb40..623a1734a6 100644
--- a/thirdparty/freetype/src/autofit/afscript.h
+++ b/thirdparty/freetype/src/autofit/afscript.h
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter scripts (specification only). */
/* */
-/* Copyright 2013-2017 by */
+/* Copyright 2013-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -137,7 +137,7 @@
"Georgian (Mkhedruli)",
HB_SCRIPT_GEORGIAN,
HINTING_BOTTOM_TO_TOP,
- "\xE1\x83\x98 \xE1\x83\x94 \xE1\x83\x90" ) /* ი ე ა */
+ "\xE1\x83\x98 \xE1\x83\x94 \xE1\x83\x90 \xE1\xB2\xBF" ) /* ი ე ა Ი */
SCRIPT( geok, GEOK,
"Georgian (Khutsuri)",
diff --git a/thirdparty/freetype/src/autofit/afshaper.c b/thirdparty/freetype/src/autofit/afshaper.c
index d259964217..f30828173c 100644
--- a/thirdparty/freetype/src/autofit/afshaper.c
+++ b/thirdparty/freetype/src/autofit/afshaper.c
@@ -4,7 +4,7 @@
/* */
/* HarfBuzz interface for accessing OpenType features (body). */
/* */
-/* Copyright 2013-2017 by */
+/* Copyright 2013-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -104,10 +104,10 @@
{
hb_face_t* face;
- hb_set_t* gsub_lookups; /* GSUB lookups for a given script */
- hb_set_t* gsub_glyphs; /* glyphs covered by GSUB lookups */
- hb_set_t* gpos_lookups; /* GPOS lookups for a given script */
- hb_set_t* gpos_glyphs; /* glyphs covered by GPOS lookups */
+ hb_set_t* gsub_lookups = NULL; /* GSUB lookups for a given script */
+ hb_set_t* gsub_glyphs = NULL; /* glyphs covered by GSUB lookups */
+ hb_set_t* gpos_lookups = NULL; /* GPOS lookups for a given script */
+ hb_set_t* gpos_glyphs = NULL; /* glyphs covered by GPOS lookups */
hb_script_t script;
const hb_tag_t* coverage_tags;
@@ -127,11 +127,6 @@
face = hb_font_get_face( globals->hb_font );
- gsub_lookups = hb_set_create();
- gsub_glyphs = hb_set_create();
- gpos_lookups = hb_set_create();
- gpos_glyphs = hb_set_create();
-
coverage_tags = coverages[style_class->coverage];
script = scripts[style_class->script];
@@ -168,6 +163,7 @@
script_tags[1] = HB_TAG_NONE;
}
+ gsub_lookups = hb_set_create();
hb_ot_layout_collect_lookups( face,
HB_OT_TAG_GSUB,
script_tags,
@@ -178,13 +174,6 @@
if ( hb_set_is_empty( gsub_lookups ) )
goto Exit; /* nothing to do */
- hb_ot_layout_collect_lookups( face,
- HB_OT_TAG_GPOS,
- script_tags,
- NULL,
- coverage_tags,
- gpos_lookups );
-
FT_TRACE4(( "GSUB lookups (style `%s'):\n"
" ",
af_style_names[style_class->style] ));
@@ -193,6 +182,7 @@
count = 0;
#endif
+ gsub_glyphs = hb_set_create();
for ( idx = HB_SET_VALUE_INVALID; hb_set_next( gsub_lookups, &idx ); )
{
#ifdef FT_DEBUG_LEVEL_TRACE
@@ -220,10 +210,19 @@
" ",
af_style_names[style_class->style] ));
+ gpos_lookups = hb_set_create();
+ hb_ot_layout_collect_lookups( face,
+ HB_OT_TAG_GPOS,
+ script_tags,
+ NULL,
+ coverage_tags,
+ gpos_lookups );
+
#ifdef FT_DEBUG_LEVEL_TRACE
count = 0;
#endif
+ gpos_glyphs = hb_set_create();
for ( idx = HB_SET_VALUE_INVALID; hb_set_next( gpos_lookups, &idx ); )
{
#ifdef FT_DEBUG_LEVEL_TRACE
diff --git a/thirdparty/freetype/src/autofit/afshaper.h b/thirdparty/freetype/src/autofit/afshaper.h
index 9185d19003..7efd9f6a4e 100644
--- a/thirdparty/freetype/src/autofit/afshaper.h
+++ b/thirdparty/freetype/src/autofit/afshaper.h
@@ -4,7 +4,7 @@
/* */
/* HarfBuzz interface for accessing OpenType features (specification). */
/* */
-/* Copyright 2013-2017 by */
+/* Copyright 2013-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/afstyles.h b/thirdparty/freetype/src/autofit/afstyles.h
index 281559eea2..e2688b3fc2 100644
--- a/thirdparty/freetype/src/autofit/afstyles.h
+++ b/thirdparty/freetype/src/autofit/afstyles.h
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter styles (specification only). */
/* */
-/* Copyright 2013-2017 by */
+/* Copyright 2013-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/aftypes.h b/thirdparty/freetype/src/autofit/aftypes.h
index 718dab70b6..6bd8c895b2 100644
--- a/thirdparty/freetype/src/autofit/aftypes.h
+++ b/thirdparty/freetype/src/autofit/aftypes.h
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter types (specification only). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -76,9 +76,9 @@ extern void* _af_debug_hints;
typedef struct AF_WidthRec_
{
- FT_Pos org; /* original position/width in font units */
- FT_Pos cur; /* current/scaled position/width in device sub-pixels */
- FT_Pos fit; /* current/fitted position/width in device sub-pixels */
+ FT_Pos org; /* original position/width in font units */
+ FT_Pos cur; /* current/scaled position/width in device subpixels */
+ FT_Pos fit; /* current/fitted position/width in device subpixels */
} AF_WidthRec, *AF_Width;
diff --git a/thirdparty/freetype/src/autofit/afwarp.c b/thirdparty/freetype/src/autofit/afwarp.c
index f99aa6d987..2a75ea7b35 100644
--- a/thirdparty/freetype/src/autofit/afwarp.c
+++ b/thirdparty/freetype/src/autofit/afwarp.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter warping algorithm (body). */
/* */
-/* Copyright 2006-2017 by */
+/* Copyright 2006-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/afwarp.h b/thirdparty/freetype/src/autofit/afwarp.h
index 2e85cbd851..520b1be907 100644
--- a/thirdparty/freetype/src/autofit/afwarp.h
+++ b/thirdparty/freetype/src/autofit/afwarp.h
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter warping algorithm (specification). */
/* */
-/* Copyright 2006-2017 by */
+/* Copyright 2006-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/afwrtsys.h b/thirdparty/freetype/src/autofit/afwrtsys.h
index 86749a2a83..4675f3242d 100644
--- a/thirdparty/freetype/src/autofit/afwrtsys.h
+++ b/thirdparty/freetype/src/autofit/afwrtsys.h
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter writing systems (specification only). */
/* */
-/* Copyright 2013-2017 by */
+/* Copyright 2013-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/autofit.c b/thirdparty/freetype/src/autofit/autofit.c
index bbedad7b5f..c1605160a1 100644
--- a/thirdparty/freetype/src/autofit/autofit.c
+++ b/thirdparty/freetype/src/autofit/autofit.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter module (body). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/autofit/module.mk b/thirdparty/freetype/src/autofit/module.mk
index c4e249b6f1..ff05f83e7e 100644
--- a/thirdparty/freetype/src/autofit/module.mk
+++ b/thirdparty/freetype/src/autofit/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 2003-2017 by
+# Copyright 2003-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/autofit/rules.mk b/thirdparty/freetype/src/autofit/rules.mk
index ec4e1302d1..75171b412c 100644
--- a/thirdparty/freetype/src/autofit/rules.mk
+++ b/thirdparty/freetype/src/autofit/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 2003-2017 by
+# Copyright 2003-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/base/basepic.c b/thirdparty/freetype/src/base/basepic.c
index 57fb8169ad..bc80406441 100644
--- a/thirdparty/freetype/src/base/basepic.c
+++ b/thirdparty/freetype/src/base/basepic.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for base. */
/* */
-/* Copyright 2009-2017 by */
+/* Copyright 2009-2018 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/base/basepic.h b/thirdparty/freetype/src/base/basepic.h
index 258d4ce2ba..492d1ede56 100644
--- a/thirdparty/freetype/src/base/basepic.h
+++ b/thirdparty/freetype/src/base/basepic.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for base. */
/* */
-/* Copyright 2009-2017 by */
+/* Copyright 2009-2018 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/base/ftadvanc.c b/thirdparty/freetype/src/base/ftadvanc.c
index 1557607fc5..230c84d6ad 100644
--- a/thirdparty/freetype/src/base/ftadvanc.c
+++ b/thirdparty/freetype/src/base/ftadvanc.c
@@ -4,7 +4,7 @@
/* */
/* Quick computation of advance widths (body). */
/* */
-/* Copyright 2008-2017 by */
+/* Copyright 2008-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -116,9 +116,12 @@
FT_Int32 flags,
FT_Fixed *padvances )
{
+ FT_Error error = FT_Err_Ok;
+
FT_Face_GetAdvancesFunc func;
- FT_UInt num, end, nn;
- FT_Error error = FT_Err_Ok;
+
+ FT_UInt num, end, nn;
+ FT_Int factor;
if ( !face )
@@ -152,16 +155,17 @@
return FT_THROW( Unimplemented_Feature );
flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY;
+ factor = ( flags & FT_LOAD_NO_SCALE ) ? 1 : 1024;
for ( nn = 0; nn < count; nn++ )
{
error = FT_Load_Glyph( face, start + nn, flags );
if ( error )
break;
- /* scale from 26.6 to 16.16 */
+ /* scale from 26.6 to 16.16, unless NO_SCALE was requested */
padvances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT )
- ? face->glyph->advance.y * 1024
- : face->glyph->advance.x * 1024;
+ ? face->glyph->advance.y * factor
+ : face->glyph->advance.x * factor;
}
return error;
diff --git a/thirdparty/freetype/src/base/ftapi.c b/thirdparty/freetype/src/base/ftapi.c
index 4262d37e39..32d6e95d19 100644
--- a/thirdparty/freetype/src/base/ftapi.c
+++ b/thirdparty/freetype/src/base/ftapi.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType compatibility functions (body). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/base/ftbase.c b/thirdparty/freetype/src/base/ftbase.c
index 55f7359942..f914b9b247 100644
--- a/thirdparty/freetype/src/base/ftbase.c
+++ b/thirdparty/freetype/src/base/ftbase.c
@@ -4,7 +4,7 @@
/* */
/* Single object library component (body only). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -23,12 +23,15 @@
#include "ftadvanc.c"
#include "ftcalc.c"
#include "ftdbgmem.c"
+#include "ftfntfmt.c"
#include "ftgloadr.c"
#include "fthash.c"
+#include "ftlcdfil.c"
#include "ftmac.c"
#include "ftobjs.c"
#include "ftoutln.c"
#include "ftpic.c"
+#include "ftpsprop.c"
#include "ftrfork.c"
#include "ftsnames.c"
#include "ftstream.c"
diff --git a/thirdparty/freetype/src/base/ftbase.h b/thirdparty/freetype/src/base/ftbase.h
index 2072284f06..7e8cfad959 100644
--- a/thirdparty/freetype/src/base/ftbase.h
+++ b/thirdparty/freetype/src/base/ftbase.h
@@ -2,9 +2,9 @@
/* */
/* ftbase.h */
/* */
-/* The FreeType private functions used in base module (specification). */
+/* Private functions used in the `base' module (specification). */
/* */
-/* Copyright 2008-2017 by */
+/* Copyright 2008-2018 by */
/* David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -27,6 +27,8 @@
FT_BEGIN_HEADER
+#ifdef FT_CONFIG_OPTION_MAC_FONTS
+
/* MacOS resource fork cannot exceed 16MB at least for Carbon code; */
/* see https://support.microsoft.com/en-us/kb/130437 */
#define FT_MAC_RFORK_MAX_LEN 0x00FFFFFFUL
@@ -65,6 +67,8 @@ FT_BEGIN_HEADER
ft_raccess_rule_by_darwin_vfs( FT_Library library, FT_UInt rule_index );
#endif
+#endif /* FT_CONFIG_OPTION_MAC_FONTS */
+
FT_END_HEADER
diff --git a/thirdparty/freetype/src/base/ftbbox.c b/thirdparty/freetype/src/base/ftbbox.c
index 6e19da63cb..151e85c97a 100644
--- a/thirdparty/freetype/src/base/ftbbox.c
+++ b/thirdparty/freetype/src/base/ftbbox.c
@@ -4,7 +4,7 @@
/* */
/* FreeType bbox computation (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used */
diff --git a/thirdparty/freetype/src/base/ftbdf.c b/thirdparty/freetype/src/base/ftbdf.c
index 40f0ca2bb8..c4ea502fbc 100644
--- a/thirdparty/freetype/src/base/ftbdf.c
+++ b/thirdparty/freetype/src/base/ftbdf.c
@@ -4,7 +4,7 @@
/* */
/* FreeType API for accessing BDF-specific strings (body). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/base/ftbitmap.c b/thirdparty/freetype/src/base/ftbitmap.c
index e567a0453e..a9746663fa 100644
--- a/thirdparty/freetype/src/base/ftbitmap.c
+++ b/thirdparty/freetype/src/base/ftbitmap.c
@@ -4,7 +4,7 @@
/* */
/* FreeType utility functions for bitmaps (body). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -153,38 +153,36 @@
FT_UInt ypixels )
{
FT_Error error;
- int pitch;
- int new_pitch;
+ unsigned int pitch;
+ unsigned int new_pitch;
FT_UInt bpp;
- FT_UInt i, width, height;
+ FT_UInt width, height;
unsigned char* buffer = NULL;
width = bitmap->width;
height = bitmap->rows;
- pitch = bitmap->pitch;
- if ( pitch < 0 )
- pitch = -pitch;
+ pitch = (unsigned int)FT_ABS( bitmap->pitch );
switch ( bitmap->pixel_mode )
{
case FT_PIXEL_MODE_MONO:
bpp = 1;
- new_pitch = (int)( ( width + xpixels + 7 ) >> 3 );
+ new_pitch = ( width + xpixels + 7 ) >> 3;
break;
case FT_PIXEL_MODE_GRAY2:
bpp = 2;
- new_pitch = (int)( ( width + xpixels + 3 ) >> 2 );
+ new_pitch = ( width + xpixels + 3 ) >> 2;
break;
case FT_PIXEL_MODE_GRAY4:
bpp = 4;
- new_pitch = (int)( ( width + xpixels + 1 ) >> 1 );
+ new_pitch = ( width + xpixels + 1 ) >> 1;
break;
case FT_PIXEL_MODE_GRAY:
case FT_PIXEL_MODE_LCD:
case FT_PIXEL_MODE_LCD_V:
bpp = 8;
- new_pitch = (int)( width + xpixels );
+ new_pitch = width + xpixels;
break;
default:
return FT_THROW( Invalid_Glyph_Format );
@@ -194,7 +192,7 @@
if ( ypixels == 0 && new_pitch <= pitch )
{
/* zero the padding */
- FT_UInt bit_width = (FT_UInt)pitch * 8;
+ FT_UInt bit_width = pitch * 8;
FT_UInt bit_last = ( width + xpixels ) * bpp;
@@ -235,31 +233,60 @@
{
FT_UInt len = ( width * bpp + 7 ) >> 3;
+ unsigned char* in = bitmap->buffer;
+ unsigned char* out = buffer;
+
+ unsigned char* limit = bitmap->buffer + pitch * bitmap->rows;
+ unsigned int delta = new_pitch - len;
+
+
+ FT_MEM_ZERO( out, new_pitch * ypixels );
+ out += new_pitch * ypixels;
- for ( i = 0; i < bitmap->rows; i++ )
- FT_MEM_COPY( buffer + (FT_UInt)new_pitch * ( ypixels + i ),
- bitmap->buffer + (FT_UInt)pitch * i,
- len );
+ while ( in < limit )
+ {
+ FT_MEM_COPY( out, in, len );
+ in += pitch;
+ out += len;
+
+ /* we use FT_QALLOC_MULT, which doesn't zero out the buffer; */
+ /* consequently, we have to manually zero out the remaining bytes */
+ FT_MEM_ZERO( out, delta );
+ out += delta;
+ }
}
else
{
FT_UInt len = ( width * bpp + 7 ) >> 3;
+ unsigned char* in = bitmap->buffer;
+ unsigned char* out = buffer;
+
+ unsigned char* limit = bitmap->buffer + pitch * bitmap->rows;
+ unsigned int delta = new_pitch - len;
+
- for ( i = 0; i < bitmap->rows; i++ )
- FT_MEM_COPY( buffer + (FT_UInt)new_pitch * i,
- bitmap->buffer + (FT_UInt)pitch * i,
- len );
+ while ( in < limit )
+ {
+ FT_MEM_COPY( out, in, len );
+ in += pitch;
+ out += len;
+
+ FT_MEM_ZERO( out, delta );
+ out += delta;
+ }
+
+ FT_MEM_ZERO( out, new_pitch * ypixels );
}
FT_FREE( bitmap->buffer );
bitmap->buffer = buffer;
- if ( bitmap->pitch < 0 )
- new_pitch = -new_pitch;
-
/* set pitch only, width and height are left untouched */
- bitmap->pitch = new_pitch;
+ if ( bitmap->pitch < 0 )
+ bitmap->pitch = -(int)new_pitch;
+ else
+ bitmap->pitch = (int)new_pitch;
return FT_Err_Ok;
}
@@ -444,7 +471,7 @@
* A gamma of 2.2 is fair to assume. And then, we need to
* undo the premultiplication too.
*
- * http://accessibility.kde.org/hsl-adjusted.php
+ * https://accessibility.kde.org/hsl-adjusted.php
*
* We do the computation with integers only, applying a gamma of 2.0.
* We guarantee 32-bit arithmetic to avoid overflow but the resulting
diff --git a/thirdparty/freetype/src/base/ftcalc.c b/thirdparty/freetype/src/base/ftcalc.c
index 00d63c6e6b..f4ff45f8ef 100644
--- a/thirdparty/freetype/src/base/ftcalc.c
+++ b/thirdparty/freetype/src/base/ftcalc.c
@@ -4,7 +4,7 @@
/* */
/* Arithmetic computations (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/base/ftcid.c b/thirdparty/freetype/src/base/ftcid.c
index 398396b845..f5184649bf 100644
--- a/thirdparty/freetype/src/base/ftcid.c
+++ b/thirdparty/freetype/src/base/ftcid.c
@@ -4,7 +4,7 @@
/* */
/* FreeType API for accessing CID font information. */
/* */
-/* Copyright 2007-2017 by */
+/* Copyright 2007-2018 by */
/* Derek Clegg and Michael Toftdal. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/base/ftdbgmem.c b/thirdparty/freetype/src/base/ftdbgmem.c
index 242246bfd1..c33d8acb4e 100644
--- a/thirdparty/freetype/src/base/ftdbgmem.c
+++ b/thirdparty/freetype/src/base/ftdbgmem.c
@@ -4,7 +4,7 @@
/* */
/* Memory debugger (body). */
/* */
-/* Copyright 2001-2017 by */
+/* Copyright 2001-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -826,7 +826,7 @@
FT_Int result = 0;
- if ( getenv( "FT2_DEBUG_MEMORY" ) )
+ if ( ft_getenv( "FT2_DEBUG_MEMORY" ) )
{
table = ft_mem_table_new( memory );
if ( table )
@@ -839,7 +839,7 @@
memory->realloc = ft_mem_debug_realloc;
memory->free = ft_mem_debug_free;
- p = getenv( "FT2_ALLOC_TOTAL_MAX" );
+ p = ft_getenv( "FT2_ALLOC_TOTAL_MAX" );
if ( p )
{
FT_Long total_max = ft_strtol( p, NULL, 10 );
@@ -852,7 +852,7 @@
}
}
- p = getenv( "FT2_ALLOC_COUNT_MAX" );
+ p = ft_getenv( "FT2_ALLOC_COUNT_MAX" );
if ( p )
{
FT_Long total_count = ft_strtol( p, NULL, 10 );
@@ -865,7 +865,7 @@
}
}
- p = getenv( "FT2_KEEP_ALIVE" );
+ p = ft_getenv( "FT2_KEEP_ALIVE" );
if ( p )
{
FT_Long keep_alive = ft_strtol( p, NULL, 10 );
diff --git a/thirdparty/freetype/src/base/ftdebug.c b/thirdparty/freetype/src/base/ftdebug.c
index 20c617089f..fe26309101 100644
--- a/thirdparty/freetype/src/base/ftdebug.c
+++ b/thirdparty/freetype/src/base/ftdebug.c
@@ -4,7 +4,7 @@
/* */
/* Debugging and logging component (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -161,7 +161,7 @@
FT_BASE_DEF( void )
ft_debug_init( void )
{
- const char* ft2_debug = getenv( "FT2_DEBUG" );
+ const char* ft2_debug = ft_getenv( "FT2_DEBUG" );
if ( ft2_debug )
diff --git a/thirdparty/freetype/src/base/ftfntfmt.c b/thirdparty/freetype/src/base/ftfntfmt.c
index dcbeba0053..a2900ceb09 100644
--- a/thirdparty/freetype/src/base/ftfntfmt.c
+++ b/thirdparty/freetype/src/base/ftfntfmt.c
@@ -4,7 +4,7 @@
/* */
/* FreeType utility file for font formats (body). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/base/ftfstype.c b/thirdparty/freetype/src/base/ftfstype.c
index cec4fb3025..e6cdf6e2ec 100644
--- a/thirdparty/freetype/src/base/ftfstype.c
+++ b/thirdparty/freetype/src/base/ftfstype.c
@@ -4,7 +4,7 @@
/* */
/* FreeType utility file to access FSType data (body). */
/* */
-/* Copyright 2008-2017 by */
+/* Copyright 2008-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/base/ftgasp.c b/thirdparty/freetype/src/base/ftgasp.c
index 477b72558c..4f80bba630 100644
--- a/thirdparty/freetype/src/base/ftgasp.c
+++ b/thirdparty/freetype/src/base/ftgasp.c
@@ -4,7 +4,7 @@
/* */
/* Access of TrueType's `gasp' table (body). */
/* */
-/* Copyright 2007-2017 by */
+/* Copyright 2007-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/base/ftgloadr.c b/thirdparty/freetype/src/base/ftgloadr.c
index 8134003b4b..47202496b9 100644
--- a/thirdparty/freetype/src/base/ftgloadr.c
+++ b/thirdparty/freetype/src/base/ftgloadr.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType glyph loader (body). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/base/ftglyph.c b/thirdparty/freetype/src/base/ftglyph.c
index 3f78a8c36b..6759aa25d0 100644
--- a/thirdparty/freetype/src/base/ftglyph.c
+++ b/thirdparty/freetype/src/base/ftglyph.c
@@ -4,7 +4,7 @@
/* */
/* FreeType convenience functions to handle glyphs (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/base/ftgxval.c b/thirdparty/freetype/src/base/ftgxval.c
index ff24d336df..19e2d6acb5 100644
--- a/thirdparty/freetype/src/base/ftgxval.c
+++ b/thirdparty/freetype/src/base/ftgxval.c
@@ -4,7 +4,7 @@
/* */
/* FreeType API for validating TrueTypeGX/AAT tables (body). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* Masatake YAMATO, Redhat K.K, */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/base/ftinit.c b/thirdparty/freetype/src/base/ftinit.c
index b3b08fa541..1fa4721094 100644
--- a/thirdparty/freetype/src/base/ftinit.c
+++ b/thirdparty/freetype/src/base/ftinit.c
@@ -4,7 +4,7 @@
/* */
/* FreeType initialization layer (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/base/ftlcdfil.c b/thirdparty/freetype/src/base/ftlcdfil.c
index 60c813fd9e..8d314df080 100644
--- a/thirdparty/freetype/src/base/ftlcdfil.c
+++ b/thirdparty/freetype/src/base/ftlcdfil.c
@@ -4,7 +4,7 @@
/* */
/* FreeType API for color filtering of subpixel bitmap glyphs (body). */
/* */
-/* Copyright 2006-2017 by */
+/* Copyright 2006-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -31,8 +31,41 @@
#define FT_SHIFTCLAMP( x ) ( x >>= 8, (FT_Byte)( x > 255 ? 255 : x ) )
+
+ /* add padding according to filter weights */
+ FT_BASE_DEF (void)
+ ft_lcd_padding( FT_Pos* Min,
+ FT_Pos* Max,
+ FT_GlyphSlot slot )
+ {
+ FT_Byte* lcd_weights;
+ FT_Bitmap_LcdFilterFunc lcd_filter_func;
+
+
+ /* Per-face LCD filtering takes priority if set up. */
+ if ( slot->face && slot->face->internal->lcd_filter_func )
+ {
+ lcd_weights = slot->face->internal->lcd_weights;
+ lcd_filter_func = slot->face->internal->lcd_filter_func;
+ }
+ else
+ {
+ lcd_weights = slot->library->lcd_weights;
+ lcd_filter_func = slot->library->lcd_filter_func;
+ }
+
+ if ( lcd_filter_func == ft_lcd_filter_fir )
+ {
+ *Min -= lcd_weights[0] ? 43 :
+ lcd_weights[1] ? 22 : 0;
+ *Max += lcd_weights[4] ? 43 :
+ lcd_weights[3] ? 22 : 0;
+ }
+ }
+
+
/* FIR filter used by the default and light filters */
- FT_BASE( void )
+ FT_BASE_DEF( void )
ft_lcd_filter_fir( FT_Bitmap* bitmap,
FT_Render_Mode mode,
FT_LcdFiveTapFilter weights )
@@ -44,7 +77,7 @@
/* take care of bitmap flow */
- if ( pitch > 0 )
+ if ( pitch > 0 && height > 0 )
origin += pitch * (FT_Int)( height - 1 );
/* horizontal in-place FIR filter */
@@ -159,7 +192,7 @@
/* take care of bitmap flow */
- if ( pitch > 0 )
+ if ( pitch > 0 && height > 0 )
origin += pitch * (FT_Int)( height - 1 );
/* horizontal in-place intra-pixel filter */
@@ -305,21 +338,21 @@
return FT_THROW( Invalid_Argument );
}
- library->lcd_filter = filter;
-
return FT_Err_Ok;
}
#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
- FT_BASE( void )
- ft_lcd_filter_fir( FT_Bitmap* bitmap,
- FT_Render_Mode mode,
- FT_LcdFiveTapFilter weights )
+ /* add padding according to accommodate outline shifts */
+ FT_BASE_DEF (void)
+ ft_lcd_padding( FT_Pos* Min,
+ FT_Pos* Max,
+ FT_GlyphSlot slot )
{
- FT_UNUSED( bitmap );
- FT_UNUSED( mode );
- FT_UNUSED( weights );
+ FT_UNUSED( slot );
+
+ *Min -= 21;
+ *Max += 21;
}
diff --git a/thirdparty/freetype/src/base/ftmac.c b/thirdparty/freetype/src/base/ftmac.c
index 4e76585e5f..fd4c0cc274 100644
--- a/thirdparty/freetype/src/base/ftmac.c
+++ b/thirdparty/freetype/src/base/ftmac.c
@@ -8,7 +8,7 @@
/* This file is for Mac OS X only; see builds/mac/ftoldmac.c for */
/* classic platforms built by MPW. */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/base/ftmm.c b/thirdparty/freetype/src/base/ftmm.c
index 43877ece45..800441bcac 100644
--- a/thirdparty/freetype/src/base/ftmm.c
+++ b/thirdparty/freetype/src/base/ftmm.c
@@ -4,7 +4,7 @@
/* */
/* Multiple Master font support (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -148,6 +148,25 @@
/* documentation is in ftmm.h */
FT_EXPORT_DEF( FT_Error )
+ FT_Done_MM_Var( FT_Library library,
+ FT_MM_Var* amaster )
+ {
+ FT_Memory memory;
+
+
+ if ( !library )
+ return FT_THROW( Invalid_Library_Handle );
+
+ memory = library->memory;
+ FT_FREE( amaster );
+
+ return FT_Err_Ok;
+ }
+
+
+ /* documentation is in ftmm.h */
+
+ FT_EXPORT_DEF( FT_Error )
FT_Set_MM_Design_Coordinates( FT_Face face,
FT_UInt num_coords,
FT_Long* coords )
@@ -203,6 +222,10 @@
error = FT_ERR( Invalid_Argument );
if ( service_mm->set_var_design )
error = service_mm->set_var_design( face, num_coords, coords );
+
+ /* internal error code -1 means `no change'; we can exit immediately */
+ if ( error == -1 )
+ return FT_Err_Ok;
}
if ( !error )
@@ -275,6 +298,10 @@
error = FT_ERR( Invalid_Argument );
if ( service_mm->set_mm_blend )
error = service_mm->set_mm_blend( face, num_coords, coords );
+
+ /* internal error code -1 means `no change'; we can exit immediately */
+ if ( error == -1 )
+ return FT_Err_Ok;
}
if ( !error )
@@ -322,6 +349,10 @@
error = FT_ERR( Invalid_Argument );
if ( service_mm->set_mm_blend )
error = service_mm->set_mm_blend( face, num_coords, coords );
+
+ /* internal error code -1 means `no change'; we can exit immediately */
+ if ( error == -1 )
+ return FT_Err_Ok;
}
if ( !error )
@@ -426,4 +457,52 @@
}
+ /* documentation is in ftmm.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Set_Named_Instance( FT_Face face,
+ FT_UInt instance_index )
+ {
+ FT_Error error;
+
+ FT_Service_MultiMasters service_mm = NULL;
+ FT_Service_MetricsVariations service_mvar = NULL;
+
+
+ /* check of `face' delayed to `ft_face_get_mm_service' */
+
+ error = ft_face_get_mm_service( face, &service_mm );
+ if ( !error )
+ {
+ error = FT_ERR( Invalid_Argument );
+ if ( service_mm->set_instance )
+ error = service_mm->set_instance( face, instance_index );
+ }
+
+ if ( !error )
+ {
+ (void)ft_face_get_mvar_service( face, &service_mvar );
+
+ if ( service_mvar && service_mvar->metrics_adjust )
+ service_mvar->metrics_adjust( face );
+ }
+
+ /* enforce recomputation of auto-hinting data */
+ if ( !error && face->autohint.finalizer )
+ {
+ face->autohint.finalizer( face->autohint.data );
+ face->autohint.data = NULL;
+ }
+
+ if ( !error )
+ {
+ face->face_index = ( instance_index << 16 ) |
+ ( face->face_index & 0xFFFFL );
+ face->face_flags &= ~FT_FACE_FLAG_VARIATION;
+ }
+
+ return error;
+ }
+
+
/* END */
diff --git a/thirdparty/freetype/src/base/ftobjs.c b/thirdparty/freetype/src/base/ftobjs.c
index 6db8136cfc..8d07e35ae3 100644
--- a/thirdparty/freetype/src/base/ftobjs.c
+++ b/thirdparty/freetype/src/base/ftobjs.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType private base classes (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -19,12 +19,16 @@
#include <ft2build.h>
#include FT_LIST_H
#include FT_OUTLINE_H
+#include FT_FONT_FORMATS_H
+
#include FT_INTERNAL_VALIDATE_H
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_RFORK_H
#include FT_INTERNAL_STREAM_H
-#include FT_INTERNAL_SFNT_H /* for SFNT_Load_Table_Func */
+#include FT_INTERNAL_SFNT_H /* for SFNT_Load_Table_Func */
+#include FT_INTERNAL_POSTSCRIPT_AUX_H /* for PS_Driver */
+
#include FT_TRUETYPE_TABLES_H
#include FT_TRUETYPE_TAGS_H
#include FT_TRUETYPE_IDS_H
@@ -37,8 +41,7 @@
#include FT_SERVICE_KERNING_H
#include FT_SERVICE_TRUETYPE_ENGINE_H
-#include FT_AUTOHINTER_H
-#include FT_CFF_DRIVER_H
+#include FT_DRIVER_H
#ifdef FT_CONFIG_OPTION_MAC_FONTS
#include "ftbase.h"
@@ -328,6 +331,138 @@
FT_BASE_DEF( void )
+ ft_glyphslot_preset_bitmap( FT_GlyphSlot slot,
+ FT_Render_Mode mode,
+ const FT_Vector* origin )
+ {
+ FT_Outline* outline = &slot->outline;
+ FT_Bitmap* bitmap = &slot->bitmap;
+
+ FT_Pixel_Mode pixel_mode;
+
+ FT_BBox cbox;
+ FT_Pos x_shift = 0;
+ FT_Pos y_shift = 0;
+ FT_Pos x_left, y_top;
+ FT_Pos width, height, pitch;
+
+
+ if ( slot->internal && ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) )
+ return;
+
+ if ( origin )
+ {
+ x_shift = origin->x;
+ y_shift = origin->y;
+ }
+
+ /* compute the control box, and grid-fit it, */
+ /* taking into account the origin shift */
+ FT_Outline_Get_CBox( outline, &cbox );
+
+ cbox.xMin += x_shift;
+ cbox.yMin += y_shift;
+ cbox.xMax += x_shift;
+ cbox.yMax += y_shift;
+
+ switch ( mode )
+ {
+ case FT_RENDER_MODE_MONO:
+ pixel_mode = FT_PIXEL_MODE_MONO;
+#if 1
+ /* undocumented but confirmed: bbox values get rounded */
+ /* unless the rounded box can collapse for a narrow glyph */
+ if ( cbox.xMax - cbox.xMin < 64 )
+ {
+ cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
+ cbox.xMax = FT_PIX_CEIL_LONG( cbox.xMax );
+ }
+ else
+ {
+ cbox.xMin = FT_PIX_ROUND_LONG( cbox.xMin );
+ cbox.xMax = FT_PIX_ROUND_LONG( cbox.xMax );
+ }
+
+ if ( cbox.yMax - cbox.yMin < 64 )
+ {
+ cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
+ cbox.yMax = FT_PIX_CEIL_LONG( cbox.yMax );
+ }
+ else
+ {
+ cbox.yMin = FT_PIX_ROUND_LONG( cbox.yMin );
+ cbox.yMax = FT_PIX_ROUND_LONG( cbox.yMax );
+ }
+#else
+ cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
+ cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
+ cbox.xMax = FT_PIX_CEIL_LONG( cbox.xMax );
+ cbox.yMax = FT_PIX_CEIL_LONG( cbox.yMax );
+#endif
+ break;
+
+ case FT_RENDER_MODE_LCD:
+ pixel_mode = FT_PIXEL_MODE_LCD;
+ ft_lcd_padding( &cbox.xMin, &cbox.xMax, slot );
+ goto Round;
+
+ case FT_RENDER_MODE_LCD_V:
+ pixel_mode = FT_PIXEL_MODE_LCD_V;
+ ft_lcd_padding( &cbox.yMin, &cbox.yMax, slot );
+ goto Round;
+
+ case FT_RENDER_MODE_NORMAL:
+ case FT_RENDER_MODE_LIGHT:
+ default:
+ pixel_mode = FT_PIXEL_MODE_GRAY;
+ Round:
+ cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
+ cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
+ cbox.xMax = FT_PIX_CEIL_LONG( cbox.xMax );
+ cbox.yMax = FT_PIX_CEIL_LONG( cbox.yMax );
+ }
+
+ x_shift = SUB_LONG( x_shift, cbox.xMin );
+ y_shift = SUB_LONG( y_shift, cbox.yMin );
+
+ x_left = cbox.xMin >> 6;
+ y_top = cbox.yMax >> 6;
+
+ width = ( (FT_ULong)cbox.xMax - (FT_ULong)cbox.xMin ) >> 6;
+ height = ( (FT_ULong)cbox.yMax - (FT_ULong)cbox.yMin ) >> 6;
+
+ switch ( pixel_mode )
+ {
+ case FT_PIXEL_MODE_MONO:
+ pitch = ( ( width + 15 ) >> 4 ) << 1;
+ break;
+
+ case FT_PIXEL_MODE_LCD:
+ width *= 3;
+ pitch = FT_PAD_CEIL( width, 4 );
+ break;
+
+ case FT_PIXEL_MODE_LCD_V:
+ height *= 3;
+ /* fall through */
+
+ case FT_PIXEL_MODE_GRAY:
+ default:
+ pitch = width;
+ }
+
+ slot->bitmap_left = (FT_Int)x_left;
+ slot->bitmap_top = (FT_Int)y_top;
+
+ bitmap->pixel_mode = (unsigned char)pixel_mode;
+ bitmap->num_grays = 256;
+ bitmap->width = (unsigned int)width;
+ bitmap->rows = (unsigned int)height;
+ bitmap->pitch = pitch;
+ }
+
+
+ FT_BASE_DEF( void )
ft_glyphslot_set_bitmap( FT_GlyphSlot slot,
FT_Byte* buffer )
{
@@ -669,9 +804,13 @@
* Determine whether we need to auto-hint or not.
* The general rules are:
*
- * - Do only auto-hinting if we have a hinter module, a scalable font
- * format dealing with outlines, and no transforms except simple
- * slants and/or rotations by integer multiples of 90 degrees.
+ * - Do only auto-hinting if we have
+ *
+ * - a hinter module,
+ * - a scalable font format dealing with outlines,
+ * - not a tricky font, and
+ * - no transforms except simple slants and/or rotations by
+ * integer multiples of 90 degrees.
*
* - Then, auto-hint if FT_LOAD_FORCE_AUTOHINT is set or if we don't
* have a native font hinter.
@@ -701,8 +840,15 @@
else
{
FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags );
+ FT_Bool is_light_type1;
+ /* only the new Adobe engine (for both CFF and Type 1) is `light'; */
+ /* we use `strstr' to catch both `Type 1' and `CID Type 1' */
+ is_light_type1 =
+ ft_strstr( FT_Get_Font_Format( face ), "Type 1" ) != NULL &&
+ ((PS_Driver)driver)->hinting_engine == FT_HINTING_ADOBE;
+
/* the check for `num_locations' assures that we actually */
/* test for instructions in a TTF and not in a CFF-based OTF */
/* */
@@ -710,8 +856,9 @@
/* check the size of the `fpgm' and `prep' tables, too -- */
/* the assumption is that there don't exist real TTFs where */
/* both `fpgm' and `prep' tables are missing */
- if ( ( mode == FT_RENDER_MODE_LIGHT &&
- !FT_DRIVER_HINTS_LIGHTLY( driver ) ) ||
+ if ( ( mode == FT_RENDER_MODE_LIGHT &&
+ ( !FT_DRIVER_HINTS_LIGHTLY( driver ) &&
+ !is_light_type1 ) ) ||
( FT_IS_SFNT( face ) &&
ttface->num_locations &&
ttface->max_profile.maxSizeOfInstructions == 0 &&
@@ -731,8 +878,8 @@
/* XXX: This is really a temporary hack that should disappear */
/* promptly with FreeType 2.1! */
/* */
- if ( FT_HAS_FIXED_SIZES( face ) &&
- ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
+ if ( FT_HAS_FIXED_SIZES( face ) &&
+ ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
{
error = driver->clazz->load_glyph( slot, face->size,
glyph_index,
@@ -800,7 +947,7 @@
/* compute the linear advance in 16.16 pixels */
if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 &&
- ( FT_IS_SCALABLE( face ) ) )
+ FT_IS_SCALABLE( face ) )
{
FT_Size_Metrics* metrics = &face->size->metrics;
@@ -848,28 +995,37 @@
}
}
- FT_TRACE5(( " x advance: %d\n" , slot->advance.x ));
- FT_TRACE5(( " y advance: %d\n" , slot->advance.y ));
-
- FT_TRACE5(( " linear x advance: %d\n" , slot->linearHoriAdvance ));
- FT_TRACE5(( " linear y advance: %d\n" , slot->linearVertAdvance ));
-
- /* do we need to render the image now? */
+ /* do we need to render the image or preset the bitmap now? */
if ( !error &&
+ ( load_flags & FT_LOAD_NO_SCALE ) == 0 &&
slot->format != FT_GLYPH_FORMAT_BITMAP &&
- slot->format != FT_GLYPH_FORMAT_COMPOSITE &&
- load_flags & FT_LOAD_RENDER )
+ slot->format != FT_GLYPH_FORMAT_COMPOSITE )
{
FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags );
- if ( mode == FT_RENDER_MODE_NORMAL &&
- (load_flags & FT_LOAD_MONOCHROME ) )
+ if ( mode == FT_RENDER_MODE_NORMAL &&
+ load_flags & FT_LOAD_MONOCHROME )
mode = FT_RENDER_MODE_MONO;
- error = FT_Render_Glyph( slot, mode );
+ if ( load_flags & FT_LOAD_RENDER )
+ error = FT_Render_Glyph( slot, mode );
+ else
+ ft_glyphslot_preset_bitmap( slot, mode, NULL );
}
+ FT_TRACE5(( "FT_Load_Glyph: index %d, flags %x\n",
+ glyph_index, load_flags ));
+ FT_TRACE5(( " x advance: %f\n", slot->advance.x / 64.0 ));
+ FT_TRACE5(( " y advance: %f\n", slot->advance.y / 64.0 ));
+ FT_TRACE5(( " linear x advance: %f\n",
+ slot->linearHoriAdvance / 65536.0 ));
+ FT_TRACE5(( " linear y advance: %f\n",
+ slot->linearVertAdvance / 65536.0 ));
+ FT_TRACE5(( " bitmap %dx%d, mode %d\n",
+ slot->bitmap.width, slot->bitmap.rows,
+ slot->bitmap.pixel_mode ));
+
Exit:
return error;
}
@@ -2441,7 +2597,8 @@
internal->no_stem_darkening = -1;
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
- ft_memset( internal->lcd_weights, 0, FT_LCD_FILTER_FIVE_TAPS );
+ /* Per-face filtering can only be set up by FT_Face_Properties */
+ internal->lcd_filter_func = NULL;
#endif
}
@@ -2864,18 +3021,6 @@
metrics->height = bsize->height << 6;
metrics->max_advance = bsize->x_ppem;
}
-
- FT_TRACE5(( "FT_Select_Metrics:\n" ));
- FT_TRACE5(( " x scale: %d (%f)\n",
- metrics->x_scale, metrics->x_scale / 65536.0 ));
- FT_TRACE5(( " y scale: %d (%f)\n",
- metrics->y_scale, metrics->y_scale / 65536.0 ));
- FT_TRACE5(( " ascender: %f\n", metrics->ascender / 64.0 ));
- FT_TRACE5(( " descender: %f\n", metrics->descender / 64.0 ));
- FT_TRACE5(( " height: %f\n", metrics->height / 64.0 ));
- FT_TRACE5(( " max advance: %f\n", metrics->max_advance / 64.0 ));
- FT_TRACE5(( " x ppem: %d\n", metrics->x_ppem ));
- FT_TRACE5(( " y ppem: %d\n", metrics->y_ppem ));
}
@@ -2984,18 +3129,6 @@
metrics->x_scale = 1L << 16;
metrics->y_scale = 1L << 16;
}
-
- FT_TRACE5(( "FT_Request_Metrics:\n" ));
- FT_TRACE5(( " x scale: %d (%f)\n",
- metrics->x_scale, metrics->x_scale / 65536.0 ));
- FT_TRACE5(( " y scale: %d (%f)\n",
- metrics->y_scale, metrics->y_scale / 65536.0 ));
- FT_TRACE5(( " ascender: %f\n", metrics->ascender / 64.0 ));
- FT_TRACE5(( " descender: %f\n", metrics->descender / 64.0 ));
- FT_TRACE5(( " height: %f\n", metrics->height / 64.0 ));
- FT_TRACE5(( " max advance: %f\n", metrics->max_advance / 64.0 ));
- FT_TRACE5(( " x ppem: %d\n", metrics->x_ppem ));
- FT_TRACE5(( " y ppem: %d\n", metrics->y_ppem ));
}
@@ -3005,6 +3138,7 @@
FT_Select_Size( FT_Face face,
FT_Int strike_index )
{
+ FT_Error error = FT_Err_Ok;
FT_Driver_Class clazz;
@@ -3018,36 +3152,37 @@
if ( clazz->select_size )
{
- FT_Error error;
+ error = clazz->select_size( face->size, (FT_ULong)strike_index );
+ FT_TRACE5(( "FT_Select_Size (%s driver):\n",
+ face->driver->root.clazz->module_name ));
+ }
+ else
+ {
+ FT_Select_Metrics( face, (FT_ULong)strike_index );
- error = clazz->select_size( face->size, (FT_ULong)strike_index );
+ FT_TRACE5(( "FT_Select_Size:\n" ));
+ }
#ifdef FT_DEBUG_LEVEL_TRACE
- {
- FT_Size_Metrics* metrics = &face->size->metrics;
-
-
- FT_TRACE5(( "FT_Select_Size (font driver's `select_size'):\n" ));
- FT_TRACE5(( " x scale: %d (%f)\n",
- metrics->x_scale, metrics->x_scale / 65536.0 ));
- FT_TRACE5(( " y scale: %d (%f)\n",
- metrics->y_scale, metrics->y_scale / 65536.0 ));
- FT_TRACE5(( " ascender: %f\n", metrics->ascender / 64.0 ));
- FT_TRACE5(( " descender: %f\n", metrics->descender / 64.0 ));
- FT_TRACE5(( " height: %f\n", metrics->height / 64.0 ));
- FT_TRACE5(( " max advance: %f\n", metrics->max_advance / 64.0 ));
- FT_TRACE5(( " x ppem: %d\n", metrics->x_ppem ));
- FT_TRACE5(( " y ppem: %d\n", metrics->y_ppem ));
- }
-#endif
+ {
+ FT_Size_Metrics* metrics = &face->size->metrics;
- return error;
- }
- FT_Select_Metrics( face, (FT_ULong)strike_index );
+ FT_TRACE5(( " x scale: %d (%f)\n",
+ metrics->x_scale, metrics->x_scale / 65536.0 ));
+ FT_TRACE5(( " y scale: %d (%f)\n",
+ metrics->y_scale, metrics->y_scale / 65536.0 ));
+ FT_TRACE5(( " ascender: %f\n", metrics->ascender / 64.0 ));
+ FT_TRACE5(( " descender: %f\n", metrics->descender / 64.0 ));
+ FT_TRACE5(( " height: %f\n", metrics->height / 64.0 ));
+ FT_TRACE5(( " max advance: %f\n", metrics->max_advance / 64.0 ));
+ FT_TRACE5(( " x ppem: %d\n", metrics->x_ppem ));
+ FT_TRACE5(( " y ppem: %d\n", metrics->y_ppem ));
+ }
+#endif
- return FT_Err_Ok;
+ return error;
}
@@ -3057,6 +3192,7 @@
FT_Request_Size( FT_Face face,
FT_Size_Request req )
{
+ FT_Error error = FT_Err_Ok;
FT_Driver_Class clazz;
FT_ULong strike_index;
@@ -3076,55 +3212,52 @@
if ( clazz->request_size )
{
- FT_Error error;
-
-
error = clazz->request_size( face->size, req );
-#ifdef FT_DEBUG_LEVEL_TRACE
- {
- FT_Size_Metrics* metrics = &face->size->metrics;
-
-
- FT_TRACE5(( "FT_Request_Size (font driver's `request_size'):\n" ));
- FT_TRACE5(( " x scale: %d (%f)\n",
- metrics->x_scale, metrics->x_scale / 65536.0 ));
- FT_TRACE5(( " y scale: %d (%f)\n",
- metrics->y_scale, metrics->y_scale / 65536.0 ));
- FT_TRACE5(( " ascender: %f\n", metrics->ascender / 64.0 ));
- FT_TRACE5(( " descender: %f\n", metrics->descender / 64.0 ));
- FT_TRACE5(( " height: %f\n", metrics->height / 64.0 ));
- FT_TRACE5(( " max advance: %f\n", metrics->max_advance / 64.0 ));
- FT_TRACE5(( " x ppem: %d\n", metrics->x_ppem ));
- FT_TRACE5(( " y ppem: %d\n", metrics->y_ppem ));
- }
-#endif
-
- return error;
+ FT_TRACE5(( "FT_Request_Size (%s driver):\n",
+ face->driver->root.clazz->module_name ));
}
-
- /*
- * The reason that a driver doesn't have `request_size' defined is
- * either that the scaling here suffices or that the supported formats
- * are bitmap-only and size matching is not implemented.
- *
- * In the latter case, a simple size matching is done.
- */
- if ( !FT_IS_SCALABLE( face ) && FT_HAS_FIXED_SIZES( face ) )
+ else if ( !FT_IS_SCALABLE( face ) && FT_HAS_FIXED_SIZES( face ) )
{
- FT_Error error;
-
-
+ /*
+ * The reason that a driver doesn't have `request_size' defined is
+ * either that the scaling here suffices or that the supported formats
+ * are bitmap-only and size matching is not implemented.
+ *
+ * In the latter case, a simple size matching is done.
+ */
error = FT_Match_Size( face, req, 0, &strike_index );
if ( error )
return error;
return FT_Select_Size( face, (FT_Int)strike_index );
}
+ else
+ {
+ FT_Request_Metrics( face, req );
- FT_Request_Metrics( face, req );
+ FT_TRACE5(( "FT_Request_Size:\n" ));
+ }
- return FT_Err_Ok;
+#ifdef FT_DEBUG_LEVEL_TRACE
+ {
+ FT_Size_Metrics* metrics = &face->size->metrics;
+
+
+ FT_TRACE5(( " x scale: %d (%f)\n",
+ metrics->x_scale, metrics->x_scale / 65536.0 ));
+ FT_TRACE5(( " y scale: %d (%f)\n",
+ metrics->y_scale, metrics->y_scale / 65536.0 ));
+ FT_TRACE5(( " ascender: %f\n", metrics->ascender / 64.0 ));
+ FT_TRACE5(( " descender: %f\n", metrics->descender / 64.0 ));
+ FT_TRACE5(( " height: %f\n", metrics->height / 64.0 ));
+ FT_TRACE5(( " max advance: %f\n", metrics->max_advance / 64.0 ));
+ FT_TRACE5(( " x ppem: %d\n", metrics->x_ppem ));
+ FT_TRACE5(( " y ppem: %d\n", metrics->y_ppem ));
+ }
+#endif
+
+ return error;
}
@@ -3653,16 +3786,11 @@
{
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
if ( properties->data )
+ {
ft_memcpy( face->internal->lcd_weights,
properties->data,
FT_LCD_FILTER_FIVE_TAPS );
- else
- {
- /* Value NULL indicates `no custom weights, use library */
- /* defaults', signaled by filling the weight field with zeros. */
- ft_memset( face->internal->lcd_weights,
- 0,
- FT_LCD_FILTER_FIVE_TAPS );
+ face->internal->lcd_filter_func = ft_lcd_filter_fir;
}
#else
error = FT_THROW( Unimplemented_Feature );
@@ -4414,43 +4542,97 @@
*/
/* we use FT_TRACE3 in this block */
- if ( ft_trace_levels[trace_bitmap] >= 3 )
+ if ( !error &&
+ ft_trace_levels[trace_bitmap] >= 3 &&
+ slot->bitmap.buffer )
{
+ FT_Bitmap bitmap;
+ FT_Error err;
+
+
+ FT_Bitmap_Init( &bitmap );
+
/* we convert to a single bitmap format for computing the checksum */
- if ( !error && slot->bitmap.buffer )
+ /* this also converts the bitmap flow to `down' (i.e., pitch > 0) */
+ err = FT_Bitmap_Convert( library, &slot->bitmap, &bitmap, 1 );
+ if ( !err )
{
- FT_Bitmap bitmap;
- FT_Error err;
+ MD5_CTX ctx;
+ unsigned char md5[16];
+ unsigned long coverage = 0;
+ int i, j;
+ int rows = (int)bitmap.rows;
+ int pitch = bitmap.pitch;
+
+
+ FT_TRACE3(( "FT_Render_Glyph: bitmap %dx%d, mode %d\n",
+ rows, pitch, slot->bitmap.pixel_mode ));
+
+ for ( i = 0; i < rows; i++ )
+ for ( j = 0; j < pitch; j++ )
+ coverage += bitmap.buffer[i * pitch + j];
+ FT_TRACE3(( " Total coverage: %lu\n", coverage ));
- FT_Bitmap_Init( &bitmap );
+ MD5_Init( &ctx );
+ if ( bitmap.buffer )
+ MD5_Update( &ctx, bitmap.buffer,
+ (unsigned long)rows * (unsigned long)pitch );
+ MD5_Final( md5, &ctx );
- /* this also converts the bitmap flow to `down' (i.e., pitch > 0) */
- err = FT_Bitmap_Convert( library, &slot->bitmap, &bitmap, 1 );
- if ( !err )
+ FT_TRACE3(( " MD5 checksum: " ));
+ for ( i = 0; i < 16; i++ )
+ FT_TRACE3(( "%02X", md5[i] ));
+ FT_TRACE3(( "\n" ));
+ }
+
+ FT_Bitmap_Done( library, &bitmap );
+ }
+
+ /*
+ * Dump bitmap in Netpbm format (PBM or PGM).
+ */
+
+ /* we use FT_TRACE7 in this block */
+ if ( !error &&
+ ft_trace_levels[trace_bitmap] >= 7 &&
+ slot->bitmap.rows < 128U &&
+ slot->bitmap.width < 128U &&
+ slot->bitmap.buffer )
+ {
+ int rows = (int)slot->bitmap.rows;
+ int width = (int)slot->bitmap.width;
+ int pitch = slot->bitmap.pitch;
+ int i, j, m;
+ unsigned char* topleft = slot->bitmap.buffer;
+
+ if ( pitch < 0 )
+ topleft -= pitch * ( rows - 1 );
+
+ FT_TRACE7(( "Netpbm image: start\n" ));
+ switch ( slot->bitmap.pixel_mode )
+ {
+ case FT_PIXEL_MODE_MONO:
+ FT_TRACE7(( "P1 %d %d\n", width, rows ));
+ for ( i = 0; i < rows; i++ )
{
- MD5_CTX ctx;
- unsigned char md5[16];
- int i;
- unsigned int rows = bitmap.rows;
- unsigned int pitch = (unsigned int)bitmap.pitch;
-
-
- MD5_Init( &ctx );
- if ( bitmap.buffer )
- MD5_Update( &ctx, bitmap.buffer, rows * pitch );
- MD5_Final( md5, &ctx );
-
- FT_TRACE3(( "MD5 checksum for %dx%d bitmap:\n"
- " ",
- rows, pitch ));
- for ( i = 0; i < 16; i++ )
- FT_TRACE3(( "%02X", md5[i] ));
- FT_TRACE3(( "\n" ));
+ for ( j = 0; j < width; )
+ for ( m = 128; m > 0 && j < width; m >>= 1, j++ )
+ FT_TRACE7(( " %d", ( topleft[i * pitch + j / 8] & m ) != 0 ));
+ FT_TRACE7(( "\n" ));
}
+ break;
- FT_Bitmap_Done( library, &bitmap );
+ default:
+ FT_TRACE7(( "P2 %d %d 255\n", width, rows ));
+ for ( i = 0; i < rows; i++ )
+ {
+ for ( j = 0; j < width; j += 1 )
+ FT_TRACE7(( " %3u", topleft[i * pitch + j] ));
+ FT_TRACE7(( "\n" ));
+ }
}
+ FT_TRACE7(( "Netpbm image: end\n" ));
}
#undef FT_COMPONENT
@@ -4995,9 +5177,9 @@
#ifdef FT_CONFIG_OPTION_PIC
Fail:
ft_pic_container_destroy( library );
-#endif
FT_FREE( library );
return error;
+#endif
}
diff --git a/thirdparty/freetype/src/base/ftotval.c b/thirdparty/freetype/src/base/ftotval.c
index 5fa098691e..a2944a7950 100644
--- a/thirdparty/freetype/src/base/ftotval.c
+++ b/thirdparty/freetype/src/base/ftotval.c
@@ -4,7 +4,7 @@
/* */
/* FreeType API for validating OpenType tables (body). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/base/ftoutln.c b/thirdparty/freetype/src/base/ftoutln.c
index 9ceb9cf1ba..cb91321deb 100644
--- a/thirdparty/freetype/src/base/ftoutln.c
+++ b/thirdparty/freetype/src/base/ftoutln.c
@@ -4,7 +4,7 @@
/* */
/* FreeType outline management (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -286,12 +286,13 @@
FT_TRACE5(( "FT_Outline_Decompose: Done\n", n ));
return FT_Err_Ok;
+ Invalid_Outline:
+ error = FT_THROW( Invalid_Outline );
+ /* fall through */
+
Exit:
FT_TRACE5(( "FT_Outline_Decompose: Error 0x%x\n", error ));
return error;
-
- Invalid_Outline:
- return FT_THROW( Invalid_Outline );
}
@@ -540,8 +541,8 @@
for ( n = 0; n < outline->n_points; n++ )
{
- vec->x += xOffset;
- vec->y += yOffset;
+ vec->x = ADD_LONG( vec->x, xOffset );
+ vec->y = ADD_LONG( vec->y, yOffset );
vec++;
}
}
diff --git a/thirdparty/freetype/src/base/ftpatent.c b/thirdparty/freetype/src/base/ftpatent.c
index 9900f99bfc..e23ee2e3f4 100644
--- a/thirdparty/freetype/src/base/ftpatent.c
+++ b/thirdparty/freetype/src/base/ftpatent.c
@@ -5,7 +5,7 @@
/* FreeType API for checking patented TrueType bytecode instructions */
/* (body). Obsolete, retained for backward compatibility. */
/* */
-/* Copyright 2007-2017 by */
+/* Copyright 2007-2018 by */
/* David Turner. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/base/ftpfr.c b/thirdparty/freetype/src/base/ftpfr.c
index 5cc0b70726..bfe13520eb 100644
--- a/thirdparty/freetype/src/base/ftpfr.c
+++ b/thirdparty/freetype/src/base/ftpfr.c
@@ -4,7 +4,7 @@
/* */
/* FreeType API for accessing PFR-specific data (body). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/base/ftpic.c b/thirdparty/freetype/src/base/ftpic.c
index 0f84fddc98..1492e1809a 100644
--- a/thirdparty/freetype/src/base/ftpic.c
+++ b/thirdparty/freetype/src/base/ftpic.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services (body). */
/* */
-/* Copyright 2009-2017 by */
+/* Copyright 2009-2018 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/base/ftpsprop.c b/thirdparty/freetype/src/base/ftpsprop.c
new file mode 100644
index 0000000000..459b5e6054
--- /dev/null
+++ b/thirdparty/freetype/src/base/ftpsprop.c
@@ -0,0 +1,285 @@
+/***************************************************************************/
+/* */
+/* ftpsprop.c */
+/* */
+/* Get and set properties of PostScript drivers (body). */
+/* See `ftdriver.h' for available properties. */
+/* */
+/* Copyright 2017-2018 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_DRIVER_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_POSTSCRIPT_PROPS_H
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_psprops
+
+
+ FT_BASE_CALLBACK_DEF( FT_Error )
+ ps_property_set( FT_Module module, /* PS_Driver */
+ const char* property_name,
+ const void* value,
+ FT_Bool value_is_string )
+ {
+ FT_Error error = FT_Err_Ok;
+ PS_Driver driver = (PS_Driver)module;
+
+#ifndef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+ FT_UNUSED( value_is_string );
+#endif
+
+
+ if ( !ft_strcmp( property_name, "darkening-parameters" ) )
+ {
+ FT_Int* darken_params;
+ FT_Int x1, y1, x2, y2, x3, y3, x4, y4;
+
+#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+ FT_Int dp[8];
+
+
+ if ( value_is_string )
+ {
+ const char* s = (const char*)value;
+ char* ep;
+ int i;
+
+
+ /* eight comma-separated numbers */
+ for ( i = 0; i < 7; i++ )
+ {
+ dp[i] = (FT_Int)ft_strtol( s, &ep, 10 );
+ if ( *ep != ',' || s == ep )
+ return FT_THROW( Invalid_Argument );
+
+ s = ep + 1;
+ }
+
+ dp[7] = (FT_Int)ft_strtol( s, &ep, 10 );
+ if ( !( *ep == '\0' || *ep == ' ' ) || s == ep )
+ return FT_THROW( Invalid_Argument );
+
+ darken_params = dp;
+ }
+ else
+#endif
+ darken_params = (FT_Int*)value;
+
+ x1 = darken_params[0];
+ y1 = darken_params[1];
+ x2 = darken_params[2];
+ y2 = darken_params[3];
+ x3 = darken_params[4];
+ y3 = darken_params[5];
+ x4 = darken_params[6];
+ y4 = darken_params[7];
+
+ if ( x1 < 0 || x2 < 0 || x3 < 0 || x4 < 0 ||
+ y1 < 0 || y2 < 0 || y3 < 0 || y4 < 0 ||
+ x1 > x2 || x2 > x3 || x3 > x4 ||
+ y1 > 500 || y2 > 500 || y3 > 500 || y4 > 500 )
+ return FT_THROW( Invalid_Argument );
+
+ driver->darken_params[0] = x1;
+ driver->darken_params[1] = y1;
+ driver->darken_params[2] = x2;
+ driver->darken_params[3] = y2;
+ driver->darken_params[4] = x3;
+ driver->darken_params[5] = y3;
+ driver->darken_params[6] = x4;
+ driver->darken_params[7] = y4;
+
+ return error;
+ }
+
+ else if ( !ft_strcmp( property_name, "hinting-engine" ) )
+ {
+#if defined( CFF_CONFIG_OPTION_OLD_ENGINE ) || \
+ defined( T1_CONFIG_OPTION_OLD_ENGINE )
+ const char* module_name = module->clazz->module_name;
+#endif
+
+
+#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+ if ( value_is_string )
+ {
+ const char* s = (const char*)value;
+
+
+ if ( !ft_strcmp( s, "adobe" ) )
+ driver->hinting_engine = FT_HINTING_ADOBE;
+
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+ else if ( !ft_strcmp( module_name, "cff" ) &&
+ !ft_strcmp( s, "freetype" ) )
+ driver->hinting_engine = FT_HINTING_FREETYPE;
+#endif
+
+#ifdef T1_CONFIG_OPTION_OLD_ENGINE
+ else if ( ( !ft_strcmp( module_name, "type1" ) ||
+ !ft_strcmp( module_name, "t1cid" ) ) &&
+ !ft_strcmp( s, "freetype" ) )
+ driver->hinting_engine = FT_HINTING_FREETYPE;
+#endif
+
+ else
+ return FT_THROW( Invalid_Argument );
+ }
+ else
+#endif /* FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES */
+ {
+ FT_UInt* hinting_engine = (FT_UInt*)value;
+
+
+ if ( *hinting_engine == FT_HINTING_ADOBE
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+ || ( *hinting_engine == FT_HINTING_FREETYPE &&
+ !ft_strcmp( module_name, "cff" ) )
+#endif
+#ifdef T1_CONFIG_OPTION_OLD_ENGINE
+ || ( *hinting_engine == FT_HINTING_FREETYPE &&
+ ( !ft_strcmp( module_name, "type1" ) ||
+ !ft_strcmp( module_name, "t1cid" ) ) )
+#endif
+ )
+ driver->hinting_engine = *hinting_engine;
+ else
+ error = FT_ERR( Unimplemented_Feature );
+
+ return error;
+ }
+ }
+
+ else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
+ {
+#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+ if ( value_is_string )
+ {
+ const char* s = (const char*)value;
+ long nsd = ft_strtol( s, NULL, 10 );
+
+
+ if ( !nsd )
+ driver->no_stem_darkening = FALSE;
+ else
+ driver->no_stem_darkening = TRUE;
+ }
+ else
+#endif
+ {
+ FT_Bool* no_stem_darkening = (FT_Bool*)value;
+
+
+ driver->no_stem_darkening = *no_stem_darkening;
+ }
+
+ return error;
+ }
+
+ else if ( !ft_strcmp( property_name, "random-seed" ) )
+ {
+ FT_Int32 random_seed;
+
+
+#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+ if ( value_is_string )
+ {
+ const char* s = (const char*)value;
+
+
+ random_seed = (FT_Int32)ft_strtol( s, NULL, 10 );
+ }
+ else
+#endif
+ random_seed = *(FT_Int32*)value;
+
+ if ( random_seed < 0 )
+ random_seed = 0;
+
+ driver->random_seed = random_seed;
+
+ return error;
+ }
+
+ FT_TRACE0(( "ps_property_set: missing property `%s'\n",
+ property_name ));
+ return FT_THROW( Missing_Property );
+ }
+
+
+ FT_BASE_CALLBACK_DEF( FT_Error )
+ ps_property_get( FT_Module module, /* PS_Driver */
+ const char* property_name,
+ void* value )
+ {
+ FT_Error error = FT_Err_Ok;
+ PS_Driver driver = (PS_Driver)module;
+
+
+ if ( !ft_strcmp( property_name, "darkening-parameters" ) )
+ {
+ FT_Int* darken_params = driver->darken_params;
+ FT_Int* val = (FT_Int*)value;
+
+
+ val[0] = darken_params[0];
+ val[1] = darken_params[1];
+ val[2] = darken_params[2];
+ val[3] = darken_params[3];
+ val[4] = darken_params[4];
+ val[5] = darken_params[5];
+ val[6] = darken_params[6];
+ val[7] = darken_params[7];
+
+ return error;
+ }
+
+ else if ( !ft_strcmp( property_name, "hinting-engine" ) )
+ {
+ FT_UInt hinting_engine = driver->hinting_engine;
+ FT_UInt* val = (FT_UInt*)value;
+
+
+ *val = hinting_engine;
+
+ return error;
+ }
+
+ else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
+ {
+ FT_Bool no_stem_darkening = driver->no_stem_darkening;
+ FT_Bool* val = (FT_Bool*)value;
+
+
+ *val = no_stem_darkening;
+
+ return error;
+ }
+
+ FT_TRACE0(( "ps_property_get: missing property `%s'\n",
+ property_name ));
+ return FT_THROW( Missing_Property );
+ }
+
+
+/* END */
diff --git a/thirdparty/freetype/src/base/ftrfork.c b/thirdparty/freetype/src/base/ftrfork.c
index f5ad2874d8..c3a2b9151a 100644
--- a/thirdparty/freetype/src/base/ftrfork.c
+++ b/thirdparty/freetype/src/base/ftrfork.c
@@ -4,7 +4,7 @@
/* */
/* Embedded resource forks accessor (body). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* Masatake YAMATO and Redhat K.K. */
/* */
/* FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are */
@@ -478,7 +478,7 @@
}
-#ifndef FT_MACINTOSH
+#if defined( FT_CONFIG_OPTION_MAC_FONTS ) && !defined( FT_MACINTOSH )
static FT_RFork_Rule
raccess_get_rule_type_from_rule_index( FT_Library library,
FT_UInt rule_index )
diff --git a/thirdparty/freetype/src/base/ftsnames.c b/thirdparty/freetype/src/base/ftsnames.c
index 3609450088..90ea1e2be7 100644
--- a/thirdparty/freetype/src/base/ftsnames.c
+++ b/thirdparty/freetype/src/base/ftsnames.c
@@ -7,7 +7,7 @@
/* */
/* This is _not_ used to retrieve glyph names! */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/base/ftstream.c b/thirdparty/freetype/src/base/ftstream.c
index a3f8c8b3c9..18df7dcfef 100644
--- a/thirdparty/freetype/src/base/ftstream.c
+++ b/thirdparty/freetype/src/base/ftstream.c
@@ -4,7 +4,7 @@
/* */
/* I/O stream support (body). */
/* */
-/* Copyright 2000-2017 by */
+/* Copyright 2000-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/base/ftstroke.c b/thirdparty/freetype/src/base/ftstroke.c
index d32de0d62b..6ae1819067 100644
--- a/thirdparty/freetype/src/base/ftstroke.c
+++ b/thirdparty/freetype/src/base/ftstroke.c
@@ -4,7 +4,7 @@
/* */
/* FreeType path stroker (body). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/base/ftsynth.c b/thirdparty/freetype/src/base/ftsynth.c
index 5cf386f48d..c28346707b 100644
--- a/thirdparty/freetype/src/base/ftsynth.c
+++ b/thirdparty/freetype/src/base/ftsynth.c
@@ -4,7 +4,7 @@
/* */
/* FreeType synthesizing code for emboldening and slanting (body). */
/* */
-/* Copyright 2000-2017 by */
+/* Copyright 2000-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/base/ftsystem.c b/thirdparty/freetype/src/base/ftsystem.c
index 324f949a49..6adebdb938 100644
--- a/thirdparty/freetype/src/base/ftsystem.c
+++ b/thirdparty/freetype/src/base/ftsystem.c
@@ -4,7 +4,7 @@
/* */
/* ANSI-specific FreeType low-level system interface (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/base/fttrigon.c b/thirdparty/freetype/src/base/fttrigon.c
index 7a4d17c829..d6dd098c42 100644
--- a/thirdparty/freetype/src/base/fttrigon.c
+++ b/thirdparty/freetype/src/base/fttrigon.c
@@ -4,7 +4,7 @@
/* */
/* FreeType trigonometric functions (body). */
/* */
-/* Copyright 2001-2017 by */
+/* Copyright 2001-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/base/fttype1.c b/thirdparty/freetype/src/base/fttype1.c
index 4d16a6371a..aa8f8ccbbb 100644
--- a/thirdparty/freetype/src/base/fttype1.c
+++ b/thirdparty/freetype/src/base/fttype1.c
@@ -4,7 +4,7 @@
/* */
/* FreeType utility file for PS names support (body). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/base/ftutil.c b/thirdparty/freetype/src/base/ftutil.c
index 7bd5bee87c..4de5f2c145 100644
--- a/thirdparty/freetype/src/base/ftutil.c
+++ b/thirdparty/freetype/src/base/ftutil.c
@@ -4,7 +4,7 @@
/* */
/* FreeType utility file for memory and list management (body). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/base/ftver.rc b/thirdparty/freetype/src/base/ftver.rc
new file mode 100644
index 0000000000..a2903d5883
--- /dev/null
+++ b/thirdparty/freetype/src/base/ftver.rc
@@ -0,0 +1,61 @@
+/***************************************************************************/
+/* */
+/* ftver.rc */
+/* */
+/* FreeType VERSIONINFO resource for Windows DLLs. */
+/* */
+/* Copyright 2018 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include<windows.h>
+
+#define FT_VERSION 2,9,1,0
+#define FT_VERSION_STR "2.9.1"
+
+VS_VERSION_INFO VERSIONINFO
+FILEVERSION FT_VERSION
+PRODUCTVERSION FT_VERSION
+FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+#ifdef _DEBUG
+FILEFLAGS VS_FF_DEBUG
+#endif
+#ifdef _DLL
+FILETYPE VFT_DLL
+#define FT_FILENAME "freetype.dll"
+#else
+FILETYPE VFT_STATIC_LIB
+#define FT_FILENAME "freetype.lib"
+#endif
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904E4"
+ BEGIN
+ VALUE "CompanyName", "The FreeType Project"
+ VALUE "FileDescription", "Font Rendering Library"
+ VALUE "FileVersion", FT_VERSION_STR
+ VALUE "ProductName", "FreeType"
+ VALUE "ProductVersion", FT_VERSION_STR
+ VALUE "LegalCopyright", "\251 2018 The FreeType Project www.freetype.org. All rights reserved."
+ VALUE "InternalName", "freetype"
+ VALUE "OriginalFilename", FT_FILENAME
+ END
+ END
+
+ BLOCK "VarFileInfo"
+ BEGIN
+ /* The following line should only be modified for localized versions. */
+ /* It consists of any number of WORD,WORD pairs, with each pair */
+ /* describing a "language,codepage" combination supported by the file. */
+ VALUE "Translation", 0x409, 1252
+ END
+END
diff --git a/thirdparty/freetype/src/base/ftwinfnt.c b/thirdparty/freetype/src/base/ftwinfnt.c
index 05baa02da6..11bd28afb7 100644
--- a/thirdparty/freetype/src/base/ftwinfnt.c
+++ b/thirdparty/freetype/src/base/ftwinfnt.c
@@ -4,7 +4,7 @@
/* */
/* FreeType API for accessing Windows FNT specific info (body). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/base/rules.mk b/thirdparty/freetype/src/base/rules.mk
index 2a1e93cb00..e9805bd068 100644
--- a/thirdparty/freetype/src/base/rules.mk
+++ b/thirdparty/freetype/src/base/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2017 by
+# Copyright 1996-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
@@ -40,11 +40,14 @@ BASE_SRC := $(BASE_DIR)/basepic.c \
$(BASE_DIR)/ftadvanc.c \
$(BASE_DIR)/ftcalc.c \
$(BASE_DIR)/ftdbgmem.c \
+ $(BASE_DIR)/ftfntfmt.c \
$(BASE_DIR)/ftgloadr.c \
$(BASE_DIR)/fthash.c \
+ $(BASE_DIR)/ftlcdfil.c \
$(BASE_DIR)/ftobjs.c \
$(BASE_DIR)/ftoutln.c \
$(BASE_DIR)/ftpic.c \
+ $(BASE_DIR)/ftpsprop.c \
$(BASE_DIR)/ftrfork.c \
$(BASE_DIR)/ftsnames.c \
$(BASE_DIR)/ftstream.c \
diff --git a/thirdparty/freetype/src/bdf/README b/thirdparty/freetype/src/bdf/README
index b761aba2b2..996ac2d2aa 100644
--- a/thirdparty/freetype/src/bdf/README
+++ b/thirdparty/freetype/src/bdf/README
@@ -13,7 +13,7 @@ This code implements a BDF driver for the FreeType library, following the
Adobe Specification V 2.2. The specification of the BDF font format is
available from Adobe's web site:
- http://partners.adobe.com/public/developer/en/font/5005.BDF_Spec.pdf
+ https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5005.BDF_Spec.pdf
Many good bitmap fonts in bdf format come with XFree86 (www.XFree86.org).
They do not define vertical metrics, because the X Consortium BDF
diff --git a/thirdparty/freetype/src/bdf/bdfdrivr.c b/thirdparty/freetype/src/bdf/bdfdrivr.c
index fb77810007..ca937f89ce 100644
--- a/thirdparty/freetype/src/bdf/bdfdrivr.c
+++ b/thirdparty/freetype/src/bdf/bdfdrivr.c
@@ -813,7 +813,7 @@ THE SOFTWARE.
bitmap->rows = glyph.bbx.height;
bitmap->width = glyph.bbx.width;
- if ( glyph.bpr > INT_MAX )
+ if ( glyph.bpr > FT_INT_MAX )
FT_TRACE1(( "BDF_Glyph_Load: too large pitch %d is truncated\n",
glyph.bpr ));
bitmap->pitch = (int)glyph.bpr; /* same as FT_Bitmap.pitch */
diff --git a/thirdparty/freetype/src/bdf/bdflib.c b/thirdparty/freetype/src/bdf/bdflib.c
index bf10887fd4..2f5c99d544 100644
--- a/thirdparty/freetype/src/bdf/bdflib.c
+++ b/thirdparty/freetype/src/bdf/bdflib.c
@@ -705,11 +705,11 @@
for ( v = 0; sbitset( ddigits, *s ); s++ )
{
- if ( v < ( ULONG_MAX - 9 ) / 10 )
+ if ( v < ( FT_ULONG_MAX - 9 ) / 10 )
v = v * 10 + a2i[(int)*s];
else
{
- v = ULONG_MAX;
+ v = FT_ULONG_MAX;
break;
}
}
@@ -738,11 +738,11 @@
for ( v = 0; sbitset( ddigits, *s ); s++ )
{
- if ( v < ( LONG_MAX - 9 ) / 10 )
+ if ( v < ( FT_LONG_MAX - 9 ) / 10 )
v = v * 10 + a2i[(int)*s];
else
{
- v = LONG_MAX;
+ v = FT_LONG_MAX;
break;
}
}
@@ -763,11 +763,11 @@
for ( v = 0; sbitset( ddigits, *s ); s++ )
{
- if ( v < ( USHRT_MAX - 9 ) / 10 )
+ if ( v < ( FT_USHORT_MAX - 9 ) / 10 )
v = (unsigned short)( v * 10 + a2i[(int)*s] );
else
{
- v = USHRT_MAX;
+ v = FT_USHORT_MAX;
break;
}
}
diff --git a/thirdparty/freetype/src/bzip2/ftbzip2.c b/thirdparty/freetype/src/bzip2/ftbzip2.c
index 7fc71e7079..16019485a9 100644
--- a/thirdparty/freetype/src/bzip2/ftbzip2.c
+++ b/thirdparty/freetype/src/bzip2/ftbzip2.c
@@ -8,7 +8,7 @@
/* parse compressed PCF fonts, as found with many X11 server */
/* distributions. */
/* */
-/* Copyright 2010-2017 by */
+/* Copyright 2010-2018 by */
/* Joel Klinghed. */
/* */
/* based on `src/gzip/ftgzip.c' */
diff --git a/thirdparty/freetype/src/bzip2/rules.mk b/thirdparty/freetype/src/bzip2/rules.mk
index f63ddc4d34..95954d7520 100644
--- a/thirdparty/freetype/src/bzip2/rules.mk
+++ b/thirdparty/freetype/src/bzip2/rules.mk
@@ -2,7 +2,7 @@
# FreeType 2 BZIP2 support configuration rules
#
-# Copyright 2010-2017 by
+# Copyright 2010-2018 by
# Joel Klinghed.
#
# based on `src/lzw/rules.mk'
diff --git a/thirdparty/freetype/src/cache/ftcache.c b/thirdparty/freetype/src/cache/ftcache.c
index 8226188314..1b425af911 100644
--- a/thirdparty/freetype/src/cache/ftcache.c
+++ b/thirdparty/freetype/src/cache/ftcache.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType Caching sub-system (body only). */
/* */
-/* Copyright 2000-2017 by */
+/* Copyright 2000-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cache/ftcbasic.c b/thirdparty/freetype/src/cache/ftcbasic.c
index e804776ab4..994aa12286 100644
--- a/thirdparty/freetype/src/cache/ftcbasic.c
+++ b/thirdparty/freetype/src/cache/ftcbasic.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType basic cache interface (body). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cache/ftccache.c b/thirdparty/freetype/src/cache/ftccache.c
index 37dc3abb1d..12ec585a25 100644
--- a/thirdparty/freetype/src/cache/ftccache.c
+++ b/thirdparty/freetype/src/cache/ftccache.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType internal cache interface (body). */
/* */
-/* Copyright 2000-2017 by */
+/* Copyright 2000-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cache/ftccache.h b/thirdparty/freetype/src/cache/ftccache.h
index d3c11ce082..859c547e46 100644
--- a/thirdparty/freetype/src/cache/ftccache.h
+++ b/thirdparty/freetype/src/cache/ftccache.h
@@ -4,7 +4,7 @@
/* */
/* FreeType internal cache interface (specification). */
/* */
-/* Copyright 2000-2017 by */
+/* Copyright 2000-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cache/ftccback.h b/thirdparty/freetype/src/cache/ftccback.h
index 2681e8c022..e51d8d6e55 100644
--- a/thirdparty/freetype/src/cache/ftccback.h
+++ b/thirdparty/freetype/src/cache/ftccback.h
@@ -4,7 +4,7 @@
/* */
/* Callback functions of the caching sub-system (specification only). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cache/ftccmap.c b/thirdparty/freetype/src/cache/ftccmap.c
index 2fa84979c8..d20b0f48fe 100644
--- a/thirdparty/freetype/src/cache/ftccmap.c
+++ b/thirdparty/freetype/src/cache/ftccmap.c
@@ -4,7 +4,7 @@
/* */
/* FreeType CharMap cache (body) */
/* */
-/* Copyright 2000-2017 by */
+/* Copyright 2000-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cache/ftcerror.h b/thirdparty/freetype/src/cache/ftcerror.h
index 84fe52f546..a26cd5935b 100644
--- a/thirdparty/freetype/src/cache/ftcerror.h
+++ b/thirdparty/freetype/src/cache/ftcerror.h
@@ -4,7 +4,7 @@
/* */
/* Caching sub-system error codes (specification only). */
/* */
-/* Copyright 2001-2017 by */
+/* Copyright 2001-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cache/ftcglyph.c b/thirdparty/freetype/src/cache/ftcglyph.c
index d2468f2f43..782cc0ed09 100644
--- a/thirdparty/freetype/src/cache/ftcglyph.c
+++ b/thirdparty/freetype/src/cache/ftcglyph.c
@@ -4,7 +4,7 @@
/* */
/* FreeType Glyph Image (FT_Glyph) cache (body). */
/* */
-/* Copyright 2000-2017 by */
+/* Copyright 2000-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cache/ftcglyph.h b/thirdparty/freetype/src/cache/ftcglyph.h
index cab58ed311..23c24d223f 100644
--- a/thirdparty/freetype/src/cache/ftcglyph.h
+++ b/thirdparty/freetype/src/cache/ftcglyph.h
@@ -4,7 +4,7 @@
/* */
/* FreeType abstract glyph cache (specification). */
/* */
-/* Copyright 2000-2017 by */
+/* Copyright 2000-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cache/ftcimage.c b/thirdparty/freetype/src/cache/ftcimage.c
index 359f818cce..77a100153e 100644
--- a/thirdparty/freetype/src/cache/ftcimage.c
+++ b/thirdparty/freetype/src/cache/ftcimage.c
@@ -4,7 +4,7 @@
/* */
/* FreeType Image cache (body). */
/* */
-/* Copyright 2000-2017 by */
+/* Copyright 2000-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cache/ftcimage.h b/thirdparty/freetype/src/cache/ftcimage.h
index 14049af9d2..24a221053b 100644
--- a/thirdparty/freetype/src/cache/ftcimage.h
+++ b/thirdparty/freetype/src/cache/ftcimage.h
@@ -4,7 +4,7 @@
/* */
/* FreeType Generic Image cache (specification) */
/* */
-/* Copyright 2000-2017 by */
+/* Copyright 2000-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cache/ftcmanag.c b/thirdparty/freetype/src/cache/ftcmanag.c
index edec2b6b5b..2bcd9df502 100644
--- a/thirdparty/freetype/src/cache/ftcmanag.c
+++ b/thirdparty/freetype/src/cache/ftcmanag.c
@@ -4,7 +4,7 @@
/* */
/* FreeType Cache Manager (body). */
/* */
-/* Copyright 2000-2017 by */
+/* Copyright 2000-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cache/ftcmanag.h b/thirdparty/freetype/src/cache/ftcmanag.h
index 556842e131..b4b4755356 100644
--- a/thirdparty/freetype/src/cache/ftcmanag.h
+++ b/thirdparty/freetype/src/cache/ftcmanag.h
@@ -4,7 +4,7 @@
/* */
/* FreeType Cache Manager (specification). */
/* */
-/* Copyright 2000-2017 by */
+/* Copyright 2000-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cache/ftcmru.c b/thirdparty/freetype/src/cache/ftcmru.c
index e293269f2f..1087be4d89 100644
--- a/thirdparty/freetype/src/cache/ftcmru.c
+++ b/thirdparty/freetype/src/cache/ftcmru.c
@@ -4,7 +4,7 @@
/* */
/* FreeType MRU support (body). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cache/ftcmru.h b/thirdparty/freetype/src/cache/ftcmru.h
index c4c330d558..82396b917d 100644
--- a/thirdparty/freetype/src/cache/ftcmru.h
+++ b/thirdparty/freetype/src/cache/ftcmru.h
@@ -4,7 +4,7 @@
/* */
/* Simple MRU list-cache (specification). */
/* */
-/* Copyright 2000-2017 by */
+/* Copyright 2000-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cache/ftcsbits.c b/thirdparty/freetype/src/cache/ftcsbits.c
index 2f9336decd..018f1ecdb7 100644
--- a/thirdparty/freetype/src/cache/ftcsbits.c
+++ b/thirdparty/freetype/src/cache/ftcsbits.c
@@ -4,7 +4,7 @@
/* */
/* FreeType sbits manager (body). */
/* */
-/* Copyright 2000-2017 by */
+/* Copyright 2000-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cache/ftcsbits.h b/thirdparty/freetype/src/cache/ftcsbits.h
index 1e15ce9764..206a1bb3fc 100644
--- a/thirdparty/freetype/src/cache/ftcsbits.h
+++ b/thirdparty/freetype/src/cache/ftcsbits.h
@@ -4,7 +4,7 @@
/* */
/* A small-bitmap cache (specification). */
/* */
-/* Copyright 2000-2017 by */
+/* Copyright 2000-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cache/rules.mk b/thirdparty/freetype/src/cache/rules.mk
index 6204689505..558935976d 100644
--- a/thirdparty/freetype/src/cache/rules.mk
+++ b/thirdparty/freetype/src/cache/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 2000-2017 by
+# Copyright 2000-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/cff/cff.c b/thirdparty/freetype/src/cff/cff.c
index 397f6dfafe..1a755d5dad 100644
--- a/thirdparty/freetype/src/cff/cff.c
+++ b/thirdparty/freetype/src/cff/cff.c
@@ -4,7 +4,7 @@
/* */
/* FreeType OpenType driver component (body only). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -27,15 +27,4 @@
#include "cffload.c"
#include "cffobjs.c"
-#include "cf2arrst.c"
-#include "cf2blues.c"
-#include "cf2error.c"
-#include "cf2font.c"
-#include "cf2ft.c"
-#include "cf2hints.c"
-#include "cf2intrp.c"
-#include "cf2read.c"
-#include "cf2stack.c"
-
-
/* END */
diff --git a/thirdparty/freetype/src/cff/cffcmap.c b/thirdparty/freetype/src/cff/cffcmap.c
index 4adce7a54d..e45ae1127b 100644
--- a/thirdparty/freetype/src/cff/cffcmap.c
+++ b/thirdparty/freetype/src/cff/cffcmap.c
@@ -4,7 +4,7 @@
/* */
/* CFF character mapping table (cmap) support (body). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cff/cffcmap.h b/thirdparty/freetype/src/cff/cffcmap.h
index 7792e04248..856a43dd1b 100644
--- a/thirdparty/freetype/src/cff/cffcmap.h
+++ b/thirdparty/freetype/src/cff/cffcmap.h
@@ -4,7 +4,7 @@
/* */
/* CFF character mapping table (cmap) support (specification). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -19,7 +19,7 @@
#ifndef CFFCMAP_H_
#define CFFCMAP_H_
-#include "cffobjs.h"
+#include FT_INTERNAL_CFF_OBJECTS_TYPES_H
FT_BEGIN_HEADER
diff --git a/thirdparty/freetype/src/cff/cffdrivr.c b/thirdparty/freetype/src/cff/cffdrivr.c
index 38bfc2ca3d..df896848da 100644
--- a/thirdparty/freetype/src/cff/cffdrivr.c
+++ b/thirdparty/freetype/src/cff/cffdrivr.c
@@ -4,7 +4,7 @@
/* */
/* OpenType font driver implementation (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -21,16 +21,20 @@
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_SFNT_H
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+#include FT_INTERNAL_POSTSCRIPT_PROPS_H
#include FT_SERVICE_CID_H
#include FT_SERVICE_POSTSCRIPT_INFO_H
#include FT_SERVICE_POSTSCRIPT_NAME_H
#include FT_SERVICE_TT_CMAP_H
+#include FT_SERVICE_CFF_TABLE_LOAD_H
#include "cffdrivr.h"
#include "cffgload.h"
#include "cffload.h"
#include "cffcmap.h"
#include "cffparse.h"
+#include "cffobjs.h"
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
#include FT_SERVICE_MULTIPLE_MASTERS_H
@@ -43,7 +47,7 @@
#include FT_SERVICE_FONT_FORMAT_H
#include FT_SERVICE_GLYPH_DICT_H
#include FT_SERVICE_PROPERTIES_H
-#include FT_CFF_DRIVER_H
+#include FT_DRIVER_H
/*************************************************************************/
@@ -214,8 +218,8 @@
{
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
/* no fast retrieval for blended MM fonts without VVAR table */
- if ( !ttface->is_default_instance &&
- !( ttface->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
+ if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) &&
+ !( ttface->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
return FT_THROW( Unimplemented_Feature );
#endif
@@ -237,8 +241,10 @@
&dummy,
&ah );
- FT_TRACE5(( " idx %d: advance height %d font units\n",
- start + nn, ah ));
+ FT_TRACE5(( " idx %d: advance height %d font unit%s\n",
+ start + nn,
+ ah,
+ ah == 1 ? "" : "s" ));
advances[nn] = ah;
}
}
@@ -246,8 +252,8 @@
{
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
/* no fast retrieval for blended MM fonts without HVAR table */
- if ( !ttface->is_default_instance &&
- !( ttface->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
+ if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) &&
+ !( ttface->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
return FT_THROW( Unimplemented_Feature );
#endif
@@ -266,8 +272,10 @@
&dummy,
&aw );
- FT_TRACE5(( " idx %d: advance width %d font units\n",
- start + nn, aw ));
+ FT_TRACE5(( " idx %d: advance width %d font unit%s\n",
+ start + nn,
+ aw,
+ aw == 1 ? "" : "s" ));
advances[nn] = aw;
}
}
@@ -493,11 +501,89 @@
}
+ static FT_Error
+ cff_ps_get_font_extra( CFF_Face face,
+ PS_FontExtraRec* afont_extra )
+ {
+ CFF_Font cff = (CFF_Font)face->extra.data;
+ FT_Error error = FT_Err_Ok;
+
+
+ if ( cff && cff->font_extra == NULL )
+ {
+ CFF_FontRecDict dict = &cff->top_font.font_dict;
+ PS_FontExtraRec* font_extra = NULL;
+ FT_Memory memory = face->root.memory;
+ FT_String* embedded_postscript;
+
+
+ if ( FT_ALLOC( font_extra, sizeof ( *font_extra ) ) )
+ goto Fail;
+
+ font_extra->fs_type = 0U;
+
+ embedded_postscript = cff_index_get_sid_string(
+ cff,
+ dict->embedded_postscript );
+ if ( embedded_postscript )
+ {
+ FT_String* start_fstype;
+ FT_String* start_def;
+
+
+ /* Identify the XYZ integer in `/FSType XYZ def' substring. */
+ if ( ( start_fstype = ft_strstr( embedded_postscript,
+ "/FSType" ) ) != NULL &&
+ ( start_def = ft_strstr( start_fstype +
+ sizeof ( "/FSType" ) - 1,
+ "def" ) ) != NULL )
+ {
+ FT_String* s;
+
+
+ for ( s = start_fstype + sizeof ( "/FSType" ) - 1;
+ s != start_def;
+ s++ )
+ {
+ if ( *s >= '0' && *s <= '9' )
+ {
+ if ( font_extra->fs_type >= ( FT_USHORT_MAX - 9 ) / 10 )
+ {
+ /* Overflow - ignore the FSType value. */
+ font_extra->fs_type = 0U;
+ break;
+ }
+
+ font_extra->fs_type *= 10;
+ font_extra->fs_type += (FT_UShort)( *s - '0' );
+ }
+ else if ( *s != ' ' && *s != '\n' && *s != '\r' )
+ {
+ /* Non-whitespace character between `/FSType' and next `def' */
+ /* - ignore the FSType value. */
+ font_extra->fs_type = 0U;
+ break;
+ }
+ }
+ }
+ }
+
+ cff->font_extra = font_extra;
+ }
+
+ if ( cff )
+ *afont_extra = *cff->font_extra;
+
+ Fail:
+ return error;
+ }
+
+
FT_DEFINE_SERVICE_PSINFOREC(
cff_service_ps_info,
(PS_GetFontInfoFunc) cff_ps_get_font_info, /* ps_get_font_info */
- (PS_GetFontExtraFunc) NULL, /* ps_get_font_extra */
+ (PS_GetFontExtraFunc) cff_ps_get_font_extra, /* ps_get_font_extra */
(PS_HasGlyphNamesFunc) cff_ps_has_glyph_names, /* ps_has_glyph_names */
/* unsupported with CFF fonts */
(PS_GetFontPrivateFunc)NULL, /* ps_get_font_private */
@@ -735,231 +821,12 @@
* PROPERTY SERVICE
*
*/
- static FT_Error
- cff_property_set( FT_Module module, /* CFF_Driver */
- const char* property_name,
- const void* value,
- FT_Bool value_is_string )
- {
- FT_Error error = FT_Err_Ok;
- CFF_Driver driver = (CFF_Driver)module;
-
-#ifndef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
- FT_UNUSED( value_is_string );
-#endif
-
-
- if ( !ft_strcmp( property_name, "darkening-parameters" ) )
- {
- FT_Int* darken_params;
- FT_Int x1, y1, x2, y2, x3, y3, x4, y4;
-
-#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
- FT_Int dp[8];
-
-
- if ( value_is_string )
- {
- const char* s = (const char*)value;
- char* ep;
- int i;
-
-
- /* eight comma-separated numbers */
- for ( i = 0; i < 7; i++ )
- {
- dp[i] = (FT_Int)ft_strtol( s, &ep, 10 );
- if ( *ep != ',' || s == ep )
- return FT_THROW( Invalid_Argument );
-
- s = ep + 1;
- }
-
- dp[7] = (FT_Int)ft_strtol( s, &ep, 10 );
- if ( !( *ep == '\0' || *ep == ' ' ) || s == ep )
- return FT_THROW( Invalid_Argument );
-
- darken_params = dp;
- }
- else
-#endif
- darken_params = (FT_Int*)value;
-
- x1 = darken_params[0];
- y1 = darken_params[1];
- x2 = darken_params[2];
- y2 = darken_params[3];
- x3 = darken_params[4];
- y3 = darken_params[5];
- x4 = darken_params[6];
- y4 = darken_params[7];
-
- if ( x1 < 0 || x2 < 0 || x3 < 0 || x4 < 0 ||
- y1 < 0 || y2 < 0 || y3 < 0 || y4 < 0 ||
- x1 > x2 || x2 > x3 || x3 > x4 ||
- y1 > 500 || y2 > 500 || y3 > 500 || y4 > 500 )
- return FT_THROW( Invalid_Argument );
-
- driver->darken_params[0] = x1;
- driver->darken_params[1] = y1;
- driver->darken_params[2] = x2;
- driver->darken_params[3] = y2;
- driver->darken_params[4] = x3;
- driver->darken_params[5] = y3;
- driver->darken_params[6] = x4;
- driver->darken_params[7] = y4;
-
- return error;
- }
- else if ( !ft_strcmp( property_name, "hinting-engine" ) )
- {
-#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
- if ( value_is_string )
- {
- const char* s = (const char*)value;
-
-
- if ( !ft_strcmp( s, "adobe" ) )
- driver->hinting_engine = FT_CFF_HINTING_ADOBE;
-#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
- else if ( !ft_strcmp( s, "freetype" ) )
- driver->hinting_engine = FT_CFF_HINTING_FREETYPE;
-#endif
- else
- return FT_THROW( Invalid_Argument );
- }
- else
-#endif
- {
- FT_UInt* hinting_engine = (FT_UInt*)value;
-
-
- if ( *hinting_engine == FT_CFF_HINTING_ADOBE
-#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
- || *hinting_engine == FT_CFF_HINTING_FREETYPE
-#endif
- )
- driver->hinting_engine = *hinting_engine;
- else
- error = FT_ERR( Unimplemented_Feature );
-
- return error;
- }
- }
- else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
- {
-#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
- if ( value_is_string )
- {
- const char* s = (const char*)value;
- long nsd = ft_strtol( s, NULL, 10 );
-
-
- if ( !nsd )
- driver->no_stem_darkening = FALSE;
- else
- driver->no_stem_darkening = TRUE;
- }
- else
-#endif
- {
- FT_Bool* no_stem_darkening = (FT_Bool*)value;
-
-
- driver->no_stem_darkening = *no_stem_darkening;
- }
-
- return error;
- }
- else if ( !ft_strcmp( property_name, "random-seed" ) )
- {
- FT_Int32 random_seed;
-
-
-#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
- if ( value_is_string )
- {
- const char* s = (const char*)value;
-
-
- random_seed = (FT_Int32)ft_strtol( s, NULL, 10 );
- }
- else
-#endif
- random_seed = *(FT_Int32*)value;
-
- if ( random_seed < 0 )
- random_seed = 0;
-
- driver->random_seed = random_seed;
-
- return error;
- }
-
- FT_TRACE0(( "cff_property_set: missing property `%s'\n",
- property_name ));
- return FT_THROW( Missing_Property );
- }
-
-
- static FT_Error
- cff_property_get( FT_Module module, /* CFF_Driver */
- const char* property_name,
- const void* value )
- {
- FT_Error error = FT_Err_Ok;
- CFF_Driver driver = (CFF_Driver)module;
-
-
- if ( !ft_strcmp( property_name, "darkening-parameters" ) )
- {
- FT_Int* darken_params = driver->darken_params;
- FT_Int* val = (FT_Int*)value;
-
-
- val[0] = darken_params[0];
- val[1] = darken_params[1];
- val[2] = darken_params[2];
- val[3] = darken_params[3];
- val[4] = darken_params[4];
- val[5] = darken_params[5];
- val[6] = darken_params[6];
- val[7] = darken_params[7];
-
- return error;
- }
- else if ( !ft_strcmp( property_name, "hinting-engine" ) )
- {
- FT_UInt hinting_engine = driver->hinting_engine;
- FT_UInt* val = (FT_UInt*)value;
-
-
- *val = hinting_engine;
-
- return error;
- }
- else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
- {
- FT_Bool no_stem_darkening = driver->no_stem_darkening;
- FT_Bool* val = (FT_Bool*)value;
-
-
- *val = no_stem_darkening;
-
- return error;
- }
-
- FT_TRACE0(( "cff_property_get: missing property `%s'\n",
- property_name ));
- return FT_THROW( Missing_Property );
- }
-
FT_DEFINE_SERVICE_PROPERTIESREC(
cff_service_properties,
- (FT_Properties_SetFunc)cff_property_set, /* set_property */
- (FT_Properties_GetFunc)cff_property_get ) /* get_property */
+ (FT_Properties_SetFunc)ps_property_set, /* set_property */
+ (FT_Properties_GetFunc)ps_property_get ) /* get_property */
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
@@ -1028,6 +895,17 @@
}
+ static FT_Error
+ cff_set_instance( CFF_Face face,
+ FT_UInt instance_index )
+ {
+ FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm;
+
+
+ return mm->set_instance( FT_FACE( face ), instance_index );
+ }
+
+
FT_DEFINE_SERVICE_MULTIMASTERSREC(
cff_service_multi_masters,
@@ -1038,6 +916,7 @@
(FT_Get_MM_Var_Func) cff_get_mm_var, /* get_mm_var */
(FT_Set_Var_Design_Func)cff_set_var_design, /* set_var_design */
(FT_Get_Var_Design_Func)cff_get_var_design, /* get_var_design */
+ (FT_Set_Instance_Func) cff_set_instance, /* set_instance */
(FT_Get_Var_Blend_Func) cff_get_var_blend, /* get_var_blend */
(FT_Done_Blend_Func) cff_done_blend /* done_blend */
@@ -1088,6 +967,22 @@
#endif
+ /*
+ * CFFLOAD SERVICE
+ *
+ */
+
+ FT_DEFINE_SERVICE_CFFLOADREC(
+ cff_service_cff_load,
+
+ (FT_Get_Standard_Encoding_Func)cff_get_standard_encoding,
+ (FT_Load_Private_Dict_Func) cff_load_private_dict,
+ (FT_FD_Select_Get_Func) cff_fd_select_get,
+ (FT_Blend_Check_Vector_Func) cff_blend_check_vector,
+ (FT_Blend_Build_Vector_Func) cff_blend_build_vector
+ )
+
+
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
@@ -1102,7 +997,7 @@
#if !defined FT_CONFIG_OPTION_NO_GLYPH_NAMES && \
defined TT_CONFIG_OPTION_GX_VAR_SUPPORT
- FT_DEFINE_SERVICEDESCREC9(
+ FT_DEFINE_SERVICEDESCREC10(
cff_services,
FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF,
@@ -1113,10 +1008,11 @@
FT_SERVICE_ID_GLYPH_DICT, &CFF_SERVICE_GLYPH_DICT_GET,
FT_SERVICE_ID_TT_CMAP, &CFF_SERVICE_GET_CMAP_INFO_GET,
FT_SERVICE_ID_CID, &CFF_SERVICE_CID_INFO_GET,
- FT_SERVICE_ID_PROPERTIES, &CFF_SERVICE_PROPERTIES_GET
+ FT_SERVICE_ID_PROPERTIES, &CFF_SERVICE_PROPERTIES_GET,
+ FT_SERVICE_ID_CFF_LOAD, &CFF_SERVICE_CFF_LOAD_GET
)
#elif !defined FT_CONFIG_OPTION_NO_GLYPH_NAMES
- FT_DEFINE_SERVICEDESCREC7(
+ FT_DEFINE_SERVICEDESCREC8(
cff_services,
FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF,
@@ -1125,10 +1021,11 @@
FT_SERVICE_ID_GLYPH_DICT, &CFF_SERVICE_GLYPH_DICT_GET,
FT_SERVICE_ID_TT_CMAP, &CFF_SERVICE_GET_CMAP_INFO_GET,
FT_SERVICE_ID_CID, &CFF_SERVICE_CID_INFO_GET,
- FT_SERVICE_ID_PROPERTIES, &CFF_SERVICE_PROPERTIES_GET
+ FT_SERVICE_ID_PROPERTIES, &CFF_SERVICE_PROPERTIES_GET,
+ FT_SERVICE_ID_CFF_LOAD, &CFF_SERVICE_CFF_LOAD_GET
)
#elif defined TT_CONFIG_OPTION_GX_VAR_SUPPORT
- FT_DEFINE_SERVICEDESCREC8(
+ FT_DEFINE_SERVICEDESCREC9(
cff_services,
FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF,
@@ -1138,10 +1035,11 @@
FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
FT_SERVICE_ID_TT_CMAP, &CFF_SERVICE_GET_CMAP_INFO_GET,
FT_SERVICE_ID_CID, &CFF_SERVICE_CID_INFO_GET,
- FT_SERVICE_ID_PROPERTIES, &CFF_SERVICE_PROPERTIES_GET
+ FT_SERVICE_ID_PROPERTIES, &CFF_SERVICE_PROPERTIES_GET,
+ FT_SERVICE_ID_CFF_LOAD, &CFF_SERVICE_CFF_LOAD_GET
)
#else
- FT_DEFINE_SERVICEDESCREC6(
+ FT_DEFINE_SERVICEDESCREC7(
cff_services,
FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF,
@@ -1149,7 +1047,8 @@
FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
FT_SERVICE_ID_TT_CMAP, &CFF_SERVICE_GET_CMAP_INFO_GET,
FT_SERVICE_ID_CID, &CFF_SERVICE_CID_INFO_GET,
- FT_SERVICE_ID_PROPERTIES, &CFF_SERVICE_PROPERTIES_GET
+ FT_SERVICE_ID_PROPERTIES, &CFF_SERVICE_PROPERTIES_GET,
+ FT_SERVICE_ID_CFF_LOAD, &CFF_SERVICE_CFF_LOAD_GET
)
#endif
@@ -1208,7 +1107,7 @@
FT_MODULE_DRIVER_HAS_HINTER |
FT_MODULE_DRIVER_HINTS_LIGHTLY,
- sizeof ( CFF_DriverRec ),
+ sizeof ( PS_DriverRec ),
"cff",
0x10000L,
0x20000L,
diff --git a/thirdparty/freetype/src/cff/cffdrivr.h b/thirdparty/freetype/src/cff/cffdrivr.h
index 05381e66db..ad7c3ad70a 100644
--- a/thirdparty/freetype/src/cff/cffdrivr.h
+++ b/thirdparty/freetype/src/cff/cffdrivr.h
@@ -4,7 +4,7 @@
/* */
/* High-level OpenType driver interface (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cff/cfferrs.h b/thirdparty/freetype/src/cff/cfferrs.h
index 40808c1051..b2e1bfaf9d 100644
--- a/thirdparty/freetype/src/cff/cfferrs.h
+++ b/thirdparty/freetype/src/cff/cfferrs.h
@@ -4,7 +4,7 @@
/* */
/* CFF error codes (specification only). */
/* */
-/* Copyright 2001-2017 by */
+/* Copyright 2001-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cff/cffgload.c b/thirdparty/freetype/src/cff/cffgload.c
index 20f3a2c28e..c58471ce86 100644
--- a/thirdparty/freetype/src/cff/cffgload.c
+++ b/thirdparty/freetype/src/cff/cffgload.c
@@ -4,7 +4,7 @@
/* */
/* OpenType Glyph Loader (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -21,13 +21,12 @@
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_SFNT_H
#include FT_INTERNAL_CALC_H
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
#include FT_OUTLINE_H
-#include FT_CFF_DRIVER_H
+#include FT_DRIVER_H
-#include "cffobjs.h"
#include "cffload.h"
#include "cffgload.h"
-#include "cf2ft.h" /* for cf2_decoder_parse_charstrings */
#include "cfferrs.h"
@@ -42,623 +41,6 @@
#define FT_COMPONENT trace_cffgload
-#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
-
- typedef enum CFF_Operator_
- {
- cff_op_unknown = 0,
-
- cff_op_rmoveto,
- cff_op_hmoveto,
- cff_op_vmoveto,
-
- cff_op_rlineto,
- cff_op_hlineto,
- cff_op_vlineto,
-
- cff_op_rrcurveto,
- cff_op_hhcurveto,
- cff_op_hvcurveto,
- cff_op_rcurveline,
- cff_op_rlinecurve,
- cff_op_vhcurveto,
- cff_op_vvcurveto,
-
- cff_op_flex,
- cff_op_hflex,
- cff_op_hflex1,
- cff_op_flex1,
-
- cff_op_endchar,
-
- cff_op_hstem,
- cff_op_vstem,
- cff_op_hstemhm,
- cff_op_vstemhm,
-
- cff_op_hintmask,
- cff_op_cntrmask,
- cff_op_dotsection, /* deprecated, acts as no-op */
-
- cff_op_abs,
- cff_op_add,
- cff_op_sub,
- cff_op_div,
- cff_op_neg,
- cff_op_random,
- cff_op_mul,
- cff_op_sqrt,
-
- cff_op_blend,
-
- cff_op_drop,
- cff_op_exch,
- cff_op_index,
- cff_op_roll,
- cff_op_dup,
-
- cff_op_put,
- cff_op_get,
- cff_op_store,
- cff_op_load,
-
- cff_op_and,
- cff_op_or,
- cff_op_not,
- cff_op_eq,
- cff_op_ifelse,
-
- cff_op_callsubr,
- cff_op_callgsubr,
- cff_op_return,
-
- /* Type 1 opcodes: invalid but seen in real life */
- cff_op_hsbw,
- cff_op_closepath,
- cff_op_callothersubr,
- cff_op_pop,
- cff_op_seac,
- cff_op_sbw,
- cff_op_setcurrentpoint,
-
- /* do not remove */
- cff_op_max
-
- } CFF_Operator;
-
-
-#define CFF_COUNT_CHECK_WIDTH 0x80
-#define CFF_COUNT_EXACT 0x40
-#define CFF_COUNT_CLEAR_STACK 0x20
-
- /* count values which have the `CFF_COUNT_CHECK_WIDTH' flag set are */
- /* used for checking the width and requested numbers of arguments */
- /* only; they are set to zero afterwards */
-
- /* the other two flags are informative only and unused currently */
-
- static const FT_Byte cff_argument_counts[] =
- {
- 0, /* unknown */
-
- 2 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, /* rmoveto */
- 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,
- 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,
-
- 0 | CFF_COUNT_CLEAR_STACK, /* rlineto */
- 0 | CFF_COUNT_CLEAR_STACK,
- 0 | CFF_COUNT_CLEAR_STACK,
-
- 0 | CFF_COUNT_CLEAR_STACK, /* rrcurveto */
- 0 | CFF_COUNT_CLEAR_STACK,
- 0 | CFF_COUNT_CLEAR_STACK,
- 0 | CFF_COUNT_CLEAR_STACK,
- 0 | CFF_COUNT_CLEAR_STACK,
- 0 | CFF_COUNT_CLEAR_STACK,
- 0 | CFF_COUNT_CLEAR_STACK,
-
- 13, /* flex */
- 7,
- 9,
- 11,
-
- 0 | CFF_COUNT_CHECK_WIDTH, /* endchar */
-
- 2 | CFF_COUNT_CHECK_WIDTH, /* hstem */
- 2 | CFF_COUNT_CHECK_WIDTH,
- 2 | CFF_COUNT_CHECK_WIDTH,
- 2 | CFF_COUNT_CHECK_WIDTH,
-
- 0 | CFF_COUNT_CHECK_WIDTH, /* hintmask */
- 0 | CFF_COUNT_CHECK_WIDTH, /* cntrmask */
- 0, /* dotsection */
-
- 1, /* abs */
- 2,
- 2,
- 2,
- 1,
- 0,
- 2,
- 1,
-
- 1, /* blend */
-
- 1, /* drop */
- 2,
- 1,
- 2,
- 1,
-
- 2, /* put */
- 1,
- 4,
- 3,
-
- 2, /* and */
- 2,
- 1,
- 2,
- 4,
-
- 1, /* callsubr */
- 1,
- 0,
-
- 2, /* hsbw */
- 0,
- 0,
- 0,
- 5, /* seac */
- 4, /* sbw */
- 2 /* setcurrentpoint */
- };
-
-#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */
-
-
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
- /********** *********/
- /********** *********/
- /********** GENERIC CHARSTRING PARSING *********/
- /********** *********/
- /********** *********/
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* cff_builder_init */
- /* */
- /* <Description> */
- /* Initializes a given glyph builder. */
- /* */
- /* <InOut> */
- /* builder :: A pointer to the glyph builder to initialize. */
- /* */
- /* <Input> */
- /* face :: The current face object. */
- /* */
- /* size :: The current size object. */
- /* */
- /* glyph :: The current glyph object. */
- /* */
- /* hinting :: Whether hinting is active. */
- /* */
- static void
- cff_builder_init( CFF_Builder* builder,
- TT_Face face,
- CFF_Size size,
- CFF_GlyphSlot glyph,
- FT_Bool hinting )
- {
- builder->path_begun = 0;
- builder->load_points = 1;
-
- builder->face = face;
- builder->glyph = glyph;
- builder->memory = face->root.memory;
-
- if ( glyph )
- {
- FT_GlyphLoader loader = glyph->root.internal->loader;
-
-
- builder->loader = loader;
- builder->base = &loader->base.outline;
- builder->current = &loader->current.outline;
- FT_GlyphLoader_Rewind( loader );
-
- builder->hints_globals = NULL;
- builder->hints_funcs = NULL;
-
- if ( hinting && size )
- {
- FT_Size ftsize = FT_SIZE( size );
- CFF_Internal internal = (CFF_Internal)ftsize->internal->module_data;
-
-
- if ( internal )
- {
- builder->hints_globals = (void *)internal->topfont;
- builder->hints_funcs = glyph->root.internal->glyph_hints;
- }
- }
- }
-
- builder->pos_x = 0;
- builder->pos_y = 0;
-
- builder->left_bearing.x = 0;
- builder->left_bearing.y = 0;
- builder->advance.x = 0;
- builder->advance.y = 0;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* cff_builder_done */
- /* */
- /* <Description> */
- /* Finalizes a given glyph builder. Its contents can still be used */
- /* after the call, but the function saves important information */
- /* within the corresponding glyph slot. */
- /* */
- /* <Input> */
- /* builder :: A pointer to the glyph builder to finalize. */
- /* */
- static void
- cff_builder_done( CFF_Builder* builder )
- {
- CFF_GlyphSlot glyph = builder->glyph;
-
-
- if ( glyph )
- glyph->root.outline = *builder->base;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* cff_compute_bias */
- /* */
- /* <Description> */
- /* Computes the bias value in dependence of the number of glyph */
- /* subroutines. */
- /* */
- /* <Input> */
- /* in_charstring_type :: The `CharstringType' value of the top DICT */
- /* dictionary. */
- /* */
- /* num_subrs :: The number of glyph subroutines. */
- /* */
- /* <Return> */
- /* The bias value. */
- static FT_Int
- cff_compute_bias( FT_Int in_charstring_type,
- FT_UInt num_subrs )
- {
- FT_Int result;
-
-
- if ( in_charstring_type == 1 )
- result = 0;
- else if ( num_subrs < 1240 )
- result = 107;
- else if ( num_subrs < 33900U )
- result = 1131;
- else
- result = 32768U;
-
- return result;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* cff_decoder_init */
- /* */
- /* <Description> */
- /* Initializes a given glyph decoder. */
- /* */
- /* <InOut> */
- /* decoder :: A pointer to the glyph builder to initialize. */
- /* */
- /* <Input> */
- /* face :: The current face object. */
- /* */
- /* size :: The current size object. */
- /* */
- /* slot :: The current glyph object. */
- /* */
- /* hinting :: Whether hinting is active. */
- /* */
- /* hint_mode :: The hinting mode. */
- /* */
- FT_LOCAL_DEF( void )
- cff_decoder_init( CFF_Decoder* decoder,
- TT_Face face,
- CFF_Size size,
- CFF_GlyphSlot slot,
- FT_Bool hinting,
- FT_Render_Mode hint_mode )
- {
- CFF_Font cff = (CFF_Font)face->extra.data;
-
-
- /* clear everything */
- FT_ZERO( decoder );
-
- /* initialize builder */
- cff_builder_init( &decoder->builder, face, size, slot, hinting );
-
- /* initialize Type2 decoder */
- decoder->cff = cff;
- decoder->num_globals = cff->global_subrs_index.count;
- decoder->globals = cff->global_subrs;
- decoder->globals_bias = cff_compute_bias(
- cff->top_font.font_dict.charstring_type,
- decoder->num_globals );
-
- decoder->hint_mode = hint_mode;
- }
-
-
- /* this function is used to select the subfont */
- /* and the locals subrs array */
- FT_LOCAL_DEF( FT_Error )
- cff_decoder_prepare( CFF_Decoder* decoder,
- CFF_Size size,
- FT_UInt glyph_index )
- {
- CFF_Builder *builder = &decoder->builder;
- CFF_Font cff = (CFF_Font)builder->face->extra.data;
- CFF_SubFont sub = &cff->top_font;
- FT_Error error = FT_Err_Ok;
-
-
- /* manage CID fonts */
- if ( cff->num_subfonts )
- {
- FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, glyph_index );
-
-
- if ( fd_index >= cff->num_subfonts )
- {
- FT_TRACE4(( "cff_decoder_prepare: invalid CID subfont index\n" ));
- error = FT_THROW( Invalid_File_Format );
- goto Exit;
- }
-
- FT_TRACE3(( " in subfont %d:\n", fd_index ));
-
- sub = cff->subfonts[fd_index];
-
- if ( builder->hints_funcs && size )
- {
- FT_Size ftsize = FT_SIZE( size );
- CFF_Internal internal = (CFF_Internal)ftsize->internal->module_data;
-
-
- /* for CFFs without subfonts, this value has already been set */
- builder->hints_globals = (void *)internal->subfonts[fd_index];
- }
- }
-
- decoder->num_locals = sub->local_subrs_index.count;
- decoder->locals = sub->local_subrs;
- decoder->locals_bias = cff_compute_bias(
- decoder->cff->top_font.font_dict.charstring_type,
- decoder->num_locals );
-
- decoder->glyph_width = sub->private_dict.default_width;
- decoder->nominal_width = sub->private_dict.nominal_width;
-
- decoder->current_subfont = sub;
-
- Exit:
- return error;
- }
-
-
- /* check that there is enough space for `count' more points */
- FT_LOCAL_DEF( FT_Error )
- cff_check_points( CFF_Builder* builder,
- FT_Int count )
- {
- return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );
- }
-
-
- /* add a new point, do not check space */
- FT_LOCAL_DEF( void )
- cff_builder_add_point( CFF_Builder* builder,
- FT_Pos x,
- FT_Pos y,
- FT_Byte flag )
- {
- FT_Outline* outline = builder->current;
-
-
- if ( builder->load_points )
- {
- FT_Vector* point = outline->points + outline->n_points;
- FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
-
-#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
- CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( builder->face );
-
-
- if ( driver->hinting_engine == FT_CFF_HINTING_FREETYPE )
- {
- point->x = x >> 16;
- point->y = y >> 16;
- }
- else
-#endif
- {
- /* cf2_decoder_parse_charstrings uses 16.16 coordinates */
- point->x = x >> 10;
- point->y = y >> 10;
- }
- *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
- }
-
- outline->n_points++;
- }
-
-
- /* check space for a new on-curve point, then add it */
- FT_LOCAL_DEF( FT_Error )
- cff_builder_add_point1( CFF_Builder* builder,
- FT_Pos x,
- FT_Pos y )
- {
- FT_Error error;
-
-
- error = cff_check_points( builder, 1 );
- if ( !error )
- cff_builder_add_point( builder, x, y, 1 );
-
- return error;
- }
-
-
- /* check space for a new contour, then add it */
- static FT_Error
- cff_builder_add_contour( CFF_Builder* builder )
- {
- FT_Outline* outline = builder->current;
- FT_Error error;
-
-
- if ( !builder->load_points )
- {
- outline->n_contours++;
- return FT_Err_Ok;
- }
-
- error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );
- if ( !error )
- {
- if ( outline->n_contours > 0 )
- outline->contours[outline->n_contours - 1] =
- (short)( outline->n_points - 1 );
-
- outline->n_contours++;
- }
-
- return error;
- }
-
-
- /* if a path was begun, add its first on-curve point */
- FT_LOCAL_DEF( FT_Error )
- cff_builder_start_point( CFF_Builder* builder,
- FT_Pos x,
- FT_Pos y )
- {
- FT_Error error = FT_Err_Ok;
-
-
- /* test whether we are building a new contour */
- if ( !builder->path_begun )
- {
- builder->path_begun = 1;
- error = cff_builder_add_contour( builder );
- if ( !error )
- error = cff_builder_add_point1( builder, x, y );
- }
-
- return error;
- }
-
-
- /* close the current contour */
- FT_LOCAL_DEF( void )
- cff_builder_close_contour( CFF_Builder* builder )
- {
- FT_Outline* outline = builder->current;
- FT_Int first;
-
-
- if ( !outline )
- return;
-
- first = outline->n_contours <= 1
- ? 0 : outline->contours[outline->n_contours - 2] + 1;
-
- /* We must not include the last point in the path if it */
- /* is located on the first point. */
- if ( outline->n_points > 1 )
- {
- FT_Vector* p1 = outline->points + first;
- FT_Vector* p2 = outline->points + outline->n_points - 1;
- FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1;
-
-
- /* `delete' last point only if it coincides with the first */
- /* point and if it is not a control point (which can happen). */
- if ( p1->x == p2->x && p1->y == p2->y )
- if ( *control == FT_CURVE_TAG_ON )
- outline->n_points--;
- }
-
- if ( outline->n_contours > 0 )
- {
- /* Don't add contours only consisting of one point, i.e., */
- /* check whether begin point and last point are the same. */
- if ( first == outline->n_points - 1 )
- {
- outline->n_contours--;
- outline->n_points--;
- }
- else
- outline->contours[outline->n_contours - 1] =
- (short)( outline->n_points - 1 );
- }
- }
-
-
- FT_LOCAL_DEF( FT_Int )
- cff_lookup_glyph_by_stdcharcode( CFF_Font cff,
- FT_Int charcode )
- {
- FT_UInt n;
- FT_UShort glyph_sid;
-
-
- /* CID-keyed fonts don't have glyph names */
- if ( !cff->charset.sids )
- return -1;
-
- /* check range of standard char code */
- if ( charcode < 0 || charcode > 255 )
- return -1;
-
- /* Get code to SID mapping from `cff_standard_encoding'. */
- glyph_sid = cff_get_standard_encoding( (FT_UInt)charcode );
-
- for ( n = 0; n < cff->num_glyphs; n++ )
- {
- if ( cff->charset.sids[n] == glyph_sid )
- return (FT_Int)n;
- }
-
- return -1;
- }
-
-
FT_LOCAL_DEF( FT_Error )
cff_get_glyph_data( TT_Face face,
FT_UInt glyph_index,
@@ -730,1950 +112,6 @@
}
-#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
-
- static FT_Error
- cff_operator_seac( CFF_Decoder* decoder,
- FT_Pos asb,
- FT_Pos adx,
- FT_Pos ady,
- FT_Int bchar,
- FT_Int achar )
- {
- FT_Error error;
- CFF_Builder* builder = &decoder->builder;
- FT_Int bchar_index, achar_index;
- TT_Face face = decoder->builder.face;
- FT_Vector left_bearing, advance;
- FT_Byte* charstring;
- FT_ULong charstring_len;
- FT_Pos glyph_width;
-
-
- if ( decoder->seac )
- {
- FT_ERROR(( "cff_operator_seac: invalid nested seac\n" ));
- return FT_THROW( Syntax_Error );
- }
-
- adx += decoder->builder.left_bearing.x;
- ady += decoder->builder.left_bearing.y;
-
-#ifdef FT_CONFIG_OPTION_INCREMENTAL
- /* Incremental fonts don't necessarily have valid charsets. */
- /* They use the character code, not the glyph index, in this case. */
- if ( face->root.internal->incremental_interface )
- {
- bchar_index = bchar;
- achar_index = achar;
- }
- else
-#endif /* FT_CONFIG_OPTION_INCREMENTAL */
- {
- CFF_Font cff = (CFF_Font)(face->extra.data);
-
-
- bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar );
- achar_index = cff_lookup_glyph_by_stdcharcode( cff, achar );
- }
-
- if ( bchar_index < 0 || achar_index < 0 )
- {
- FT_ERROR(( "cff_operator_seac:"
- " invalid seac character code arguments\n" ));
- return FT_THROW( Syntax_Error );
- }
-
- /* If we are trying to load a composite glyph, do not load the */
- /* accent character and return the array of subglyphs. */
- if ( builder->no_recurse )
- {
- FT_GlyphSlot glyph = (FT_GlyphSlot)builder->glyph;
- FT_GlyphLoader loader = glyph->internal->loader;
- FT_SubGlyph subg;
-
-
- /* reallocate subglyph array if necessary */
- error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );
- if ( error )
- goto Exit;
-
- subg = loader->current.subglyphs;
-
- /* subglyph 0 = base character */
- subg->index = bchar_index;
- subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
- FT_SUBGLYPH_FLAG_USE_MY_METRICS;
- subg->arg1 = 0;
- subg->arg2 = 0;
- subg++;
-
- /* subglyph 1 = accent character */
- subg->index = achar_index;
- subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
- subg->arg1 = (FT_Int)( adx >> 16 );
- subg->arg2 = (FT_Int)( ady >> 16 );
-
- /* set up remaining glyph fields */
- glyph->num_subglyphs = 2;
- glyph->subglyphs = loader->base.subglyphs;
- glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
-
- loader->current.num_subglyphs = 2;
- }
-
- FT_GlyphLoader_Prepare( builder->loader );
-
- /* First load `bchar' in builder */
- error = cff_get_glyph_data( face, (FT_UInt)bchar_index,
- &charstring, &charstring_len );
- if ( !error )
- {
- /* the seac operator must not be nested */
- decoder->seac = TRUE;
- error = cff_decoder_parse_charstrings( decoder, charstring,
- charstring_len, 0 );
- decoder->seac = FALSE;
-
- cff_free_glyph_data( face, &charstring, charstring_len );
-
- if ( error )
- goto Exit;
- }
-
- /* Save the left bearing, advance and glyph width of the base */
- /* character as they will be erased by the next load. */
-
- left_bearing = builder->left_bearing;
- advance = builder->advance;
- glyph_width = decoder->glyph_width;
-
- builder->left_bearing.x = 0;
- builder->left_bearing.y = 0;
-
- builder->pos_x = adx - asb;
- builder->pos_y = ady;
-
- /* Now load `achar' on top of the base outline. */
- error = cff_get_glyph_data( face, (FT_UInt)achar_index,
- &charstring, &charstring_len );
- if ( !error )
- {
- /* the seac operator must not be nested */
- decoder->seac = TRUE;
- error = cff_decoder_parse_charstrings( decoder, charstring,
- charstring_len, 0 );
- decoder->seac = FALSE;
-
- cff_free_glyph_data( face, &charstring, charstring_len );
-
- if ( error )
- goto Exit;
- }
-
- /* Restore the left side bearing, advance and glyph width */
- /* of the base character. */
- builder->left_bearing = left_bearing;
- builder->advance = advance;
- decoder->glyph_width = glyph_width;
-
- builder->pos_x = 0;
- builder->pos_y = 0;
-
- Exit:
- return error;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* cff_decoder_parse_charstrings */
- /* */
- /* <Description> */
- /* Parses a given Type 2 charstrings program. */
- /* */
- /* <InOut> */
- /* decoder :: The current Type 1 decoder. */
- /* */
- /* <Input> */
- /* charstring_base :: The base of the charstring stream. */
- /* */
- /* charstring_len :: The length in bytes of the charstring stream. */
- /* */
- /* in_dict :: Set to 1 if function is called from top or */
- /* private DICT (needed for Multiple Master CFFs). */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- cff_decoder_parse_charstrings( CFF_Decoder* decoder,
- FT_Byte* charstring_base,
- FT_ULong charstring_len,
- FT_Bool in_dict )
- {
- FT_Error error;
- CFF_Decoder_Zone* zone;
- FT_Byte* ip;
- FT_Byte* limit;
- CFF_Builder* builder = &decoder->builder;
- FT_Pos x, y;
- FT_Fixed* stack;
- FT_Int charstring_type =
- decoder->cff->top_font.font_dict.charstring_type;
- FT_UShort num_designs =
- decoder->cff->top_font.font_dict.num_designs;
- FT_UShort num_axes =
- decoder->cff->top_font.font_dict.num_axes;
-
- T2_Hints_Funcs hinter;
-
-
- /* set default width */
- decoder->num_hints = 0;
- decoder->read_width = 1;
-
- /* initialize the decoder */
- decoder->top = decoder->stack;
- decoder->zone = decoder->zones;
- zone = decoder->zones;
- stack = decoder->top;
-
- hinter = (T2_Hints_Funcs)builder->hints_funcs;
-
- builder->path_begun = 0;
-
- zone->base = charstring_base;
- limit = zone->limit = charstring_base + charstring_len;
- ip = zone->cursor = zone->base;
-
- error = FT_Err_Ok;
-
- x = builder->pos_x;
- y = builder->pos_y;
-
- /* begin hints recording session, if any */
- if ( hinter )
- hinter->open( hinter->hints );
-
- /* now execute loop */
- while ( ip < limit )
- {
- CFF_Operator op;
- FT_Byte v;
-
-
- /********************************************************************/
- /* */
- /* Decode operator or operand */
- /* */
- v = *ip++;
- if ( v >= 32 || v == 28 )
- {
- FT_Int shift = 16;
- FT_Int32 val;
-
-
- /* this is an operand, push it on the stack */
-
- /* if we use shifts, all computations are done with unsigned */
- /* values; the conversion to a signed value is the last step */
- if ( v == 28 )
- {
- if ( ip + 1 >= limit )
- goto Syntax_Error;
- val = (FT_Short)( ( (FT_UShort)ip[0] << 8 ) | ip[1] );
- ip += 2;
- }
- else if ( v < 247 )
- val = (FT_Int32)v - 139;
- else if ( v < 251 )
- {
- if ( ip >= limit )
- goto Syntax_Error;
- val = ( (FT_Int32)v - 247 ) * 256 + *ip++ + 108;
- }
- else if ( v < 255 )
- {
- if ( ip >= limit )
- goto Syntax_Error;
- val = -( (FT_Int32)v - 251 ) * 256 - *ip++ - 108;
- }
- else
- {
- if ( ip + 3 >= limit )
- goto Syntax_Error;
- val = (FT_Int32)( ( (FT_UInt32)ip[0] << 24 ) |
- ( (FT_UInt32)ip[1] << 16 ) |
- ( (FT_UInt32)ip[2] << 8 ) |
- (FT_UInt32)ip[3] );
- ip += 4;
- if ( charstring_type == 2 )
- shift = 0;
- }
- if ( decoder->top - stack >= CFF_MAX_OPERANDS )
- goto Stack_Overflow;
-
- val = (FT_Int32)( (FT_UInt32)val << shift );
- *decoder->top++ = val;
-
-#ifdef FT_DEBUG_LEVEL_TRACE
- if ( !( val & 0xFFFFL ) )
- FT_TRACE4(( " %hd", (FT_Short)( (FT_UInt32)val >> 16 ) ));
- else
- FT_TRACE4(( " %.5f", val / 65536.0 ));
-#endif
-
- }
- else
- {
- /* The specification says that normally arguments are to be taken */
- /* from the bottom of the stack. However, this seems not to be */
- /* correct, at least for Acroread 7.0.8 on GNU/Linux: It pops the */
- /* arguments similar to a PS interpreter. */
-
- FT_Fixed* args = decoder->top;
- FT_Int num_args = (FT_Int)( args - decoder->stack );
- FT_Int req_args;
-
-
- /* find operator */
- op = cff_op_unknown;
-
- switch ( v )
- {
- case 1:
- op = cff_op_hstem;
- break;
- case 3:
- op = cff_op_vstem;
- break;
- case 4:
- op = cff_op_vmoveto;
- break;
- case 5:
- op = cff_op_rlineto;
- break;
- case 6:
- op = cff_op_hlineto;
- break;
- case 7:
- op = cff_op_vlineto;
- break;
- case 8:
- op = cff_op_rrcurveto;
- break;
- case 9:
- op = cff_op_closepath;
- break;
- case 10:
- op = cff_op_callsubr;
- break;
- case 11:
- op = cff_op_return;
- break;
- case 12:
- {
- if ( ip >= limit )
- goto Syntax_Error;
- v = *ip++;
-
- switch ( v )
- {
- case 0:
- op = cff_op_dotsection;
- break;
- case 1: /* this is actually the Type1 vstem3 operator */
- op = cff_op_vstem;
- break;
- case 2: /* this is actually the Type1 hstem3 operator */
- op = cff_op_hstem;
- break;
- case 3:
- op = cff_op_and;
- break;
- case 4:
- op = cff_op_or;
- break;
- case 5:
- op = cff_op_not;
- break;
- case 6:
- op = cff_op_seac;
- break;
- case 7:
- op = cff_op_sbw;
- break;
- case 8:
- op = cff_op_store;
- break;
- case 9:
- op = cff_op_abs;
- break;
- case 10:
- op = cff_op_add;
- break;
- case 11:
- op = cff_op_sub;
- break;
- case 12:
- op = cff_op_div;
- break;
- case 13:
- op = cff_op_load;
- break;
- case 14:
- op = cff_op_neg;
- break;
- case 15:
- op = cff_op_eq;
- break;
- case 16:
- op = cff_op_callothersubr;
- break;
- case 17:
- op = cff_op_pop;
- break;
- case 18:
- op = cff_op_drop;
- break;
- case 20:
- op = cff_op_put;
- break;
- case 21:
- op = cff_op_get;
- break;
- case 22:
- op = cff_op_ifelse;
- break;
- case 23:
- op = cff_op_random;
- break;
- case 24:
- op = cff_op_mul;
- break;
- case 26:
- op = cff_op_sqrt;
- break;
- case 27:
- op = cff_op_dup;
- break;
- case 28:
- op = cff_op_exch;
- break;
- case 29:
- op = cff_op_index;
- break;
- case 30:
- op = cff_op_roll;
- break;
- case 33:
- op = cff_op_setcurrentpoint;
- break;
- case 34:
- op = cff_op_hflex;
- break;
- case 35:
- op = cff_op_flex;
- break;
- case 36:
- op = cff_op_hflex1;
- break;
- case 37:
- op = cff_op_flex1;
- break;
- default:
- FT_TRACE4(( " unknown op (12, %d)\n", v ));
- break;
- }
- }
- break;
- case 13:
- op = cff_op_hsbw;
- break;
- case 14:
- op = cff_op_endchar;
- break;
- case 16:
- op = cff_op_blend;
- break;
- case 18:
- op = cff_op_hstemhm;
- break;
- case 19:
- op = cff_op_hintmask;
- break;
- case 20:
- op = cff_op_cntrmask;
- break;
- case 21:
- op = cff_op_rmoveto;
- break;
- case 22:
- op = cff_op_hmoveto;
- break;
- case 23:
- op = cff_op_vstemhm;
- break;
- case 24:
- op = cff_op_rcurveline;
- break;
- case 25:
- op = cff_op_rlinecurve;
- break;
- case 26:
- op = cff_op_vvcurveto;
- break;
- case 27:
- op = cff_op_hhcurveto;
- break;
- case 29:
- op = cff_op_callgsubr;
- break;
- case 30:
- op = cff_op_vhcurveto;
- break;
- case 31:
- op = cff_op_hvcurveto;
- break;
- default:
- FT_TRACE4(( " unknown op (%d)\n", v ));
- break;
- }
-
- if ( op == cff_op_unknown )
- continue;
-
- /* in Multiple Master CFFs, T2 charstrings can appear in */
- /* dictionaries, but some operators are prohibited */
- if ( in_dict )
- {
- switch ( op )
- {
- case cff_op_hstem:
- case cff_op_vstem:
- case cff_op_vmoveto:
- case cff_op_rlineto:
- case cff_op_hlineto:
- case cff_op_vlineto:
- case cff_op_rrcurveto:
- case cff_op_hstemhm:
- case cff_op_hintmask:
- case cff_op_cntrmask:
- case cff_op_rmoveto:
- case cff_op_hmoveto:
- case cff_op_vstemhm:
- case cff_op_rcurveline:
- case cff_op_rlinecurve:
- case cff_op_vvcurveto:
- case cff_op_hhcurveto:
- case cff_op_vhcurveto:
- case cff_op_hvcurveto:
- case cff_op_hflex:
- case cff_op_flex:
- case cff_op_hflex1:
- case cff_op_flex1:
- case cff_op_callsubr:
- case cff_op_callgsubr:
- goto MM_Error;
-
- default:
- break;
- }
- }
-
- /* check arguments */
- req_args = cff_argument_counts[op];
- if ( req_args & CFF_COUNT_CHECK_WIDTH )
- {
- if ( num_args > 0 && decoder->read_width )
- {
- /* If `nominal_width' is non-zero, the number is really a */
- /* difference against `nominal_width'. Else, the number here */
- /* is truly a width, not a difference against `nominal_width'. */
- /* If the font does not set `nominal_width', then */
- /* `nominal_width' defaults to zero, and so we can set */
- /* `glyph_width' to `nominal_width' plus number on the stack */
- /* -- for either case. */
-
- FT_Int set_width_ok;
-
-
- switch ( op )
- {
- case cff_op_hmoveto:
- case cff_op_vmoveto:
- set_width_ok = num_args & 2;
- break;
-
- case cff_op_hstem:
- case cff_op_vstem:
- case cff_op_hstemhm:
- case cff_op_vstemhm:
- case cff_op_rmoveto:
- case cff_op_hintmask:
- case cff_op_cntrmask:
- set_width_ok = num_args & 1;
- break;
-
- case cff_op_endchar:
- /* If there is a width specified for endchar, we either have */
- /* 1 argument or 5 arguments. We like to argue. */
- set_width_ok = in_dict
- ? 0
- : ( ( num_args == 5 ) || ( num_args == 1 ) );
- break;
-
- default:
- set_width_ok = 0;
- break;
- }
-
- if ( set_width_ok )
- {
- decoder->glyph_width = decoder->nominal_width +
- ( stack[0] >> 16 );
-
- if ( decoder->width_only )
- {
- /* we only want the advance width; stop here */
- break;
- }
-
- /* Consumed an argument. */
- num_args--;
- }
- }
-
- decoder->read_width = 0;
- req_args = 0;
- }
-
- req_args &= 0x000F;
- if ( num_args < req_args )
- goto Stack_Underflow;
- args -= req_args;
- num_args -= req_args;
-
- /* At this point, `args' points to the first argument of the */
- /* operand in case `req_args' isn't zero. Otherwise, we have */
- /* to adjust `args' manually. */
-
- /* Note that we only pop arguments from the stack which we */
- /* really need and can digest so that we can continue in case */
- /* of superfluous stack elements. */
-
- switch ( op )
- {
- case cff_op_hstem:
- case cff_op_vstem:
- case cff_op_hstemhm:
- case cff_op_vstemhm:
- /* the number of arguments is always even here */
- FT_TRACE4((
- op == cff_op_hstem ? " hstem\n" :
- ( op == cff_op_vstem ? " vstem\n" :
- ( op == cff_op_hstemhm ? " hstemhm\n" : " vstemhm\n" ) ) ));
-
- if ( hinter )
- hinter->stems( hinter->hints,
- ( op == cff_op_hstem || op == cff_op_hstemhm ),
- num_args / 2,
- args - ( num_args & ~1 ) );
-
- decoder->num_hints += num_args / 2;
- args = stack;
- break;
-
- case cff_op_hintmask:
- case cff_op_cntrmask:
- FT_TRACE4(( op == cff_op_hintmask ? " hintmask" : " cntrmask" ));
-
- /* implement vstem when needed -- */
- /* the specification doesn't say it, but this also works */
- /* with the 'cntrmask' operator */
- /* */
- if ( num_args > 0 )
- {
- if ( hinter )
- hinter->stems( hinter->hints,
- 0,
- num_args / 2,
- args - ( num_args & ~1 ) );
-
- decoder->num_hints += num_args / 2;
- }
-
- /* In a valid charstring there must be at least one byte */
- /* after `hintmask' or `cntrmask' (e.g., for a `return' */
- /* instruction). Additionally, there must be space for */
- /* `num_hints' bits. */
-
- if ( ( ip + ( ( decoder->num_hints + 7 ) >> 3 ) ) >= limit )
- goto Syntax_Error;
-
- if ( hinter )
- {
- if ( op == cff_op_hintmask )
- hinter->hintmask( hinter->hints,
- (FT_UInt)builder->current->n_points,
- (FT_UInt)decoder->num_hints,
- ip );
- else
- hinter->counter( hinter->hints,
- (FT_UInt)decoder->num_hints,
- ip );
- }
-
-#ifdef FT_DEBUG_LEVEL_TRACE
- {
- FT_UInt maskbyte;
-
-
- FT_TRACE4(( " (maskbytes:" ));
-
- for ( maskbyte = 0;
- maskbyte < (FT_UInt)( ( decoder->num_hints + 7 ) >> 3 );
- maskbyte++, ip++ )
- FT_TRACE4(( " 0x%02X", *ip ));
-
- FT_TRACE4(( ")\n" ));
- }
-#else
- ip += ( decoder->num_hints + 7 ) >> 3;
-#endif
- args = stack;
- break;
-
- case cff_op_rmoveto:
- FT_TRACE4(( " rmoveto\n" ));
-
- cff_builder_close_contour( builder );
- builder->path_begun = 0;
- x = ADD_LONG( x, args[-2] );
- y = ADD_LONG( y, args[-1] );
- args = stack;
- break;
-
- case cff_op_vmoveto:
- FT_TRACE4(( " vmoveto\n" ));
-
- cff_builder_close_contour( builder );
- builder->path_begun = 0;
- y = ADD_LONG( y, args[-1] );
- args = stack;
- break;
-
- case cff_op_hmoveto:
- FT_TRACE4(( " hmoveto\n" ));
-
- cff_builder_close_contour( builder );
- builder->path_begun = 0;
- x = ADD_LONG( x, args[-1] );
- args = stack;
- break;
-
- case cff_op_rlineto:
- FT_TRACE4(( " rlineto\n" ));
-
- if ( cff_builder_start_point( builder, x, y ) ||
- cff_check_points( builder, num_args / 2 ) )
- goto Fail;
-
- if ( num_args < 2 )
- goto Stack_Underflow;
-
- args -= num_args & ~1;
- while ( args < decoder->top )
- {
- x = ADD_LONG( x, args[0] );
- y = ADD_LONG( y, args[1] );
- cff_builder_add_point( builder, x, y, 1 );
- args += 2;
- }
- args = stack;
- break;
-
- case cff_op_hlineto:
- case cff_op_vlineto:
- {
- FT_Int phase = ( op == cff_op_hlineto );
-
-
- FT_TRACE4(( op == cff_op_hlineto ? " hlineto\n"
- : " vlineto\n" ));
-
- if ( num_args < 0 )
- goto Stack_Underflow;
-
- /* there exist subsetted fonts (found in PDFs) */
- /* which call `hlineto' without arguments */
- if ( num_args == 0 )
- break;
-
- if ( cff_builder_start_point( builder, x, y ) ||
- cff_check_points( builder, num_args ) )
- goto Fail;
-
- args = stack;
- while ( args < decoder->top )
- {
- if ( phase )
- x = ADD_LONG( x, args[0] );
- else
- y = ADD_LONG( y, args[0] );
-
- if ( cff_builder_add_point1( builder, x, y ) )
- goto Fail;
-
- args++;
- phase ^= 1;
- }
- args = stack;
- }
- break;
-
- case cff_op_rrcurveto:
- {
- FT_Int nargs;
-
-
- FT_TRACE4(( " rrcurveto\n" ));
-
- if ( num_args < 6 )
- goto Stack_Underflow;
-
- nargs = num_args - num_args % 6;
-
- if ( cff_builder_start_point( builder, x, y ) ||
- cff_check_points( builder, nargs / 2 ) )
- goto Fail;
-
- args -= nargs;
- while ( args < decoder->top )
- {
- x = ADD_LONG( x, args[0] );
- y = ADD_LONG( y, args[1] );
- cff_builder_add_point( builder, x, y, 0 );
-
- x = ADD_LONG( x, args[2] );
- y = ADD_LONG( y, args[3] );
- cff_builder_add_point( builder, x, y, 0 );
-
- x = ADD_LONG( x, args[4] );
- y = ADD_LONG( y, args[5] );
- cff_builder_add_point( builder, x, y, 1 );
-
- args += 6;
- }
- args = stack;
- }
- break;
-
- case cff_op_vvcurveto:
- {
- FT_Int nargs;
-
-
- FT_TRACE4(( " vvcurveto\n" ));
-
- if ( num_args < 4 )
- goto Stack_Underflow;
-
- /* if num_args isn't of the form 4n or 4n+1, */
- /* we enforce it by clearing the second bit */
-
- nargs = num_args & ~2;
-
- if ( cff_builder_start_point( builder, x, y ) )
- goto Fail;
-
- args -= nargs;
-
- if ( nargs & 1 )
- {
- x = ADD_LONG( x, args[0] );
- args++;
- nargs--;
- }
-
- if ( cff_check_points( builder, 3 * ( nargs / 4 ) ) )
- goto Fail;
-
- while ( args < decoder->top )
- {
- y = ADD_LONG( y, args[0] );
- cff_builder_add_point( builder, x, y, 0 );
-
- x = ADD_LONG( x, args[1] );
- y = ADD_LONG( y, args[2] );
- cff_builder_add_point( builder, x, y, 0 );
-
- y = ADD_LONG( y, args[3] );
- cff_builder_add_point( builder, x, y, 1 );
-
- args += 4;
- }
- args = stack;
- }
- break;
-
- case cff_op_hhcurveto:
- {
- FT_Int nargs;
-
-
- FT_TRACE4(( " hhcurveto\n" ));
-
- if ( num_args < 4 )
- goto Stack_Underflow;
-
- /* if num_args isn't of the form 4n or 4n+1, */
- /* we enforce it by clearing the second bit */
-
- nargs = num_args & ~2;
-
- if ( cff_builder_start_point( builder, x, y ) )
- goto Fail;
-
- args -= nargs;
- if ( nargs & 1 )
- {
- y = ADD_LONG( y, args[0] );
- args++;
- nargs--;
- }
-
- if ( cff_check_points( builder, 3 * ( nargs / 4 ) ) )
- goto Fail;
-
- while ( args < decoder->top )
- {
- x = ADD_LONG( x, args[0] );
- cff_builder_add_point( builder, x, y, 0 );
-
- x = ADD_LONG( x, args[1] );
- y = ADD_LONG( y, args[2] );
- cff_builder_add_point( builder, x, y, 0 );
-
- x = ADD_LONG( x, args[3] );
- cff_builder_add_point( builder, x, y, 1 );
-
- args += 4;
- }
- args = stack;
- }
- break;
-
- case cff_op_vhcurveto:
- case cff_op_hvcurveto:
- {
- FT_Int phase;
- FT_Int nargs;
-
-
- FT_TRACE4(( op == cff_op_vhcurveto ? " vhcurveto\n"
- : " hvcurveto\n" ));
-
- if ( cff_builder_start_point( builder, x, y ) )
- goto Fail;
-
- if ( num_args < 4 )
- goto Stack_Underflow;
-
- /* if num_args isn't of the form 8n, 8n+1, 8n+4, or 8n+5, */
- /* we enforce it by clearing the second bit */
-
- nargs = num_args & ~2;
-
- args -= nargs;
- if ( cff_check_points( builder, ( nargs / 4 ) * 3 ) )
- goto Stack_Underflow;
-
- phase = ( op == cff_op_hvcurveto );
-
- while ( nargs >= 4 )
- {
- nargs -= 4;
- if ( phase )
- {
- x = ADD_LONG( x, args[0] );
- cff_builder_add_point( builder, x, y, 0 );
-
- x = ADD_LONG( x, args[1] );
- y = ADD_LONG( y, args[2] );
- cff_builder_add_point( builder, x, y, 0 );
-
- y = ADD_LONG( y, args[3] );
- if ( nargs == 1 )
- x = ADD_LONG( x, args[4] );
- cff_builder_add_point( builder, x, y, 1 );
- }
- else
- {
- y = ADD_LONG( y, args[0] );
- cff_builder_add_point( builder, x, y, 0 );
-
- x = ADD_LONG( x, args[1] );
- y = ADD_LONG( y, args[2] );
- cff_builder_add_point( builder, x, y, 0 );
-
- x = ADD_LONG( x, args[3] );
- if ( nargs == 1 )
- y = ADD_LONG( y, args[4] );
- cff_builder_add_point( builder, x, y, 1 );
- }
- args += 4;
- phase ^= 1;
- }
- args = stack;
- }
- break;
-
- case cff_op_rlinecurve:
- {
- FT_Int num_lines;
- FT_Int nargs;
-
-
- FT_TRACE4(( " rlinecurve\n" ));
-
- if ( num_args < 8 )
- goto Stack_Underflow;
-
- nargs = num_args & ~1;
- num_lines = ( nargs - 6 ) / 2;
-
- if ( cff_builder_start_point( builder, x, y ) ||
- cff_check_points( builder, num_lines + 3 ) )
- goto Fail;
-
- args -= nargs;
-
- /* first, add the line segments */
- while ( num_lines > 0 )
- {
- x = ADD_LONG( x, args[0] );
- y = ADD_LONG( y, args[1] );
- cff_builder_add_point( builder, x, y, 1 );
-
- args += 2;
- num_lines--;
- }
-
- /* then the curve */
- x = ADD_LONG( x, args[0] );
- y = ADD_LONG( y, args[1] );
- cff_builder_add_point( builder, x, y, 0 );
-
- x = ADD_LONG( x, args[2] );
- y = ADD_LONG( y, args[3] );
- cff_builder_add_point( builder, x, y, 0 );
-
- x = ADD_LONG( x, args[4] );
- y = ADD_LONG( y, args[5] );
- cff_builder_add_point( builder, x, y, 1 );
-
- args = stack;
- }
- break;
-
- case cff_op_rcurveline:
- {
- FT_Int num_curves;
- FT_Int nargs;
-
-
- FT_TRACE4(( " rcurveline\n" ));
-
- if ( num_args < 8 )
- goto Stack_Underflow;
-
- nargs = num_args - 2;
- nargs = nargs - nargs % 6 + 2;
- num_curves = ( nargs - 2 ) / 6;
-
- if ( cff_builder_start_point( builder, x, y ) ||
- cff_check_points( builder, num_curves * 3 + 2 ) )
- goto Fail;
-
- args -= nargs;
-
- /* first, add the curves */
- while ( num_curves > 0 )
- {
- x = ADD_LONG( x, args[0] );
- y = ADD_LONG( y, args[1] );
- cff_builder_add_point( builder, x, y, 0 );
-
- x = ADD_LONG( x, args[2] );
- y = ADD_LONG( y, args[3] );
- cff_builder_add_point( builder, x, y, 0 );
-
- x = ADD_LONG( x, args[4] );
- y = ADD_LONG( y, args[5] );
- cff_builder_add_point( builder, x, y, 1 );
-
- args += 6;
- num_curves--;
- }
-
- /* then the final line */
- x = ADD_LONG( x, args[0] );
- y = ADD_LONG( y, args[1] );
- cff_builder_add_point( builder, x, y, 1 );
-
- args = stack;
- }
- break;
-
- case cff_op_hflex1:
- {
- FT_Pos start_y;
-
-
- FT_TRACE4(( " hflex1\n" ));
-
- /* adding five more points: 4 control points, 1 on-curve point */
- /* -- make sure we have enough space for the start point if it */
- /* needs to be added */
- if ( cff_builder_start_point( builder, x, y ) ||
- cff_check_points( builder, 6 ) )
- goto Fail;
-
- /* record the starting point's y position for later use */
- start_y = y;
-
- /* first control point */
- x = ADD_LONG( x, args[0] );
- y = ADD_LONG( y, args[1] );
- cff_builder_add_point( builder, x, y, 0 );
-
- /* second control point */
- x = ADD_LONG( x, args[2] );
- y = ADD_LONG( y, args[3] );
- cff_builder_add_point( builder, x, y, 0 );
-
- /* join point; on curve, with y-value the same as the last */
- /* control point's y-value */
- x = ADD_LONG( x, args[4] );
- cff_builder_add_point( builder, x, y, 1 );
-
- /* third control point, with y-value the same as the join */
- /* point's y-value */
- x = ADD_LONG( x, args[5] );
- cff_builder_add_point( builder, x, y, 0 );
-
- /* fourth control point */
- x = ADD_LONG( x, args[6] );
- y = ADD_LONG( y, args[7] );
- cff_builder_add_point( builder, x, y, 0 );
-
- /* ending point, with y-value the same as the start */
- x = ADD_LONG( x, args[8] );
- y = start_y;
- cff_builder_add_point( builder, x, y, 1 );
-
- args = stack;
- break;
- }
-
- case cff_op_hflex:
- {
- FT_Pos start_y;
-
-
- FT_TRACE4(( " hflex\n" ));
-
- /* adding six more points; 4 control points, 2 on-curve points */
- if ( cff_builder_start_point( builder, x, y ) ||
- cff_check_points( builder, 6 ) )
- goto Fail;
-
- /* record the starting point's y-position for later use */
- start_y = y;
-
- /* first control point */
- x = ADD_LONG( x, args[0] );
- cff_builder_add_point( builder, x, y, 0 );
-
- /* second control point */
- x = ADD_LONG( x, args[1] );
- y = ADD_LONG( y, args[2] );
- cff_builder_add_point( builder, x, y, 0 );
-
- /* join point; on curve, with y-value the same as the last */
- /* control point's y-value */
- x = ADD_LONG( x, args[3] );
- cff_builder_add_point( builder, x, y, 1 );
-
- /* third control point, with y-value the same as the join */
- /* point's y-value */
- x = ADD_LONG( x, args[4] );
- cff_builder_add_point( builder, x, y, 0 );
-
- /* fourth control point */
- x = ADD_LONG( x, args[5] );
- y = start_y;
- cff_builder_add_point( builder, x, y, 0 );
-
- /* ending point, with y-value the same as the start point's */
- /* y-value -- we don't add this point, though */
- x = ADD_LONG( x, args[6] );
- cff_builder_add_point( builder, x, y, 1 );
-
- args = stack;
- break;
- }
-
- case cff_op_flex1:
- {
- FT_Pos start_x, start_y; /* record start x, y values for */
- /* alter use */
- FT_Fixed dx = 0, dy = 0; /* used in horizontal/vertical */
- /* algorithm below */
- FT_Int horizontal, count;
- FT_Fixed* temp;
-
-
- FT_TRACE4(( " flex1\n" ));
-
- /* adding six more points; 4 control points, 2 on-curve points */
- if ( cff_builder_start_point( builder, x, y ) ||
- cff_check_points( builder, 6 ) )
- goto Fail;
-
- /* record the starting point's x, y position for later use */
- start_x = x;
- start_y = y;
-
- /* XXX: figure out whether this is supposed to be a horizontal */
- /* or vertical flex; the Type 2 specification is vague... */
-
- temp = args;
-
- /* grab up to the last argument */
- for ( count = 5; count > 0; count-- )
- {
- dx = ADD_LONG( dx, temp[0] );
- dy = ADD_LONG( dy, temp[1] );
- temp += 2;
- }
-
- if ( dx < 0 )
- dx = -dx;
- if ( dy < 0 )
- dy = -dy;
-
- /* strange test, but here it is... */
- horizontal = ( dx > dy );
-
- for ( count = 5; count > 0; count-- )
- {
- x = ADD_LONG( x, args[0] );
- y = ADD_LONG( y, args[1] );
- cff_builder_add_point( builder, x, y,
- (FT_Bool)( count == 3 ) );
- args += 2;
- }
-
- /* is last operand an x- or y-delta? */
- if ( horizontal )
- {
- x = ADD_LONG( x, args[0] );
- y = start_y;
- }
- else
- {
- x = start_x;
- y = ADD_LONG( y, args[0] );
- }
-
- cff_builder_add_point( builder, x, y, 1 );
-
- args = stack;
- break;
- }
-
- case cff_op_flex:
- {
- FT_UInt count;
-
-
- FT_TRACE4(( " flex\n" ));
-
- if ( cff_builder_start_point( builder, x, y ) ||
- cff_check_points( builder, 6 ) )
- goto Fail;
-
- for ( count = 6; count > 0; count-- )
- {
- x = ADD_LONG( x, args[0] );
- y = ADD_LONG( y, args[1] );
- cff_builder_add_point( builder, x, y,
- (FT_Bool)( count == 4 || count == 1 ) );
- args += 2;
- }
-
- args = stack;
- }
- break;
-
- case cff_op_seac:
- FT_TRACE4(( " seac\n" ));
-
- error = cff_operator_seac( decoder,
- args[0], args[1], args[2],
- (FT_Int)( args[3] >> 16 ),
- (FT_Int)( args[4] >> 16 ) );
-
- /* add current outline to the glyph slot */
- FT_GlyphLoader_Add( builder->loader );
-
- /* return now! */
- FT_TRACE4(( "\n" ));
- return error;
-
- case cff_op_endchar:
- /* in dictionaries, `endchar' simply indicates end of data */
- if ( in_dict )
- return error;
-
- FT_TRACE4(( " endchar\n" ));
-
- /* We are going to emulate the seac operator. */
- if ( num_args >= 4 )
- {
- /* Save glyph width so that the subglyphs don't overwrite it. */
- FT_Pos glyph_width = decoder->glyph_width;
-
-
- error = cff_operator_seac( decoder,
- 0L, args[-4], args[-3],
- (FT_Int)( args[-2] >> 16 ),
- (FT_Int)( args[-1] >> 16 ) );
-
- decoder->glyph_width = glyph_width;
- }
- else
- {
- cff_builder_close_contour( builder );
-
- /* close hints recording session */
- if ( hinter )
- {
- if ( hinter->close( hinter->hints,
- (FT_UInt)builder->current->n_points ) )
- goto Syntax_Error;
-
- /* apply hints to the loaded glyph outline now */
- error = hinter->apply( hinter->hints,
- builder->current,
- (PSH_Globals)builder->hints_globals,
- decoder->hint_mode );
- if ( error )
- goto Fail;
- }
-
- /* add current outline to the glyph slot */
- FT_GlyphLoader_Add( builder->loader );
- }
-
- /* return now! */
- FT_TRACE4(( "\n" ));
- return error;
-
- case cff_op_abs:
- FT_TRACE4(( " abs\n" ));
-
- if ( args[0] < 0 )
- {
- if ( args[0] == FT_LONG_MIN )
- args[0] = FT_LONG_MAX;
- else
- args[0] = -args[0];
- }
- args++;
- break;
-
- case cff_op_add:
- FT_TRACE4(( " add\n" ));
-
- args[0] = ADD_LONG( args[0], args[1] );
- args++;
- break;
-
- case cff_op_sub:
- FT_TRACE4(( " sub\n" ));
-
- args[0] = SUB_LONG( args[0], args[1] );
- args++;
- break;
-
- case cff_op_div:
- FT_TRACE4(( " div\n" ));
-
- args[0] = FT_DivFix( args[0], args[1] );
- args++;
- break;
-
- case cff_op_neg:
- FT_TRACE4(( " neg\n" ));
-
- if ( args[0] == FT_LONG_MIN )
- args[0] = FT_LONG_MAX;
- args[0] = -args[0];
- args++;
- break;
-
- case cff_op_random:
- FT_TRACE4(( " random\n" ));
-
- /* only use the lower 16 bits of `random' */
- /* to generate a number in the range (0;1] */
- args[0] = (FT_Fixed)
- ( ( decoder->current_subfont->random & 0xFFFF ) + 1 );
- args++;
-
- decoder->current_subfont->random =
- cff_random( decoder->current_subfont->random );
- break;
-
- case cff_op_mul:
- FT_TRACE4(( " mul\n" ));
-
- args[0] = FT_MulFix( args[0], args[1] );
- args++;
- break;
-
- case cff_op_sqrt:
- FT_TRACE4(( " sqrt\n" ));
-
- if ( args[0] > 0 )
- {
- FT_Fixed root = args[0];
- FT_Fixed new_root;
-
-
- for (;;)
- {
- new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1;
- if ( new_root == root )
- break;
- root = new_root;
- }
- args[0] = new_root;
- }
- else
- args[0] = 0;
- args++;
- break;
-
- case cff_op_drop:
- /* nothing */
- FT_TRACE4(( " drop\n" ));
-
- break;
-
- case cff_op_exch:
- {
- FT_Fixed tmp;
-
-
- FT_TRACE4(( " exch\n" ));
-
- tmp = args[0];
- args[0] = args[1];
- args[1] = tmp;
- args += 2;
- }
- break;
-
- case cff_op_index:
- {
- FT_Int idx = (FT_Int)( args[0] >> 16 );
-
-
- FT_TRACE4(( " index\n" ));
-
- if ( idx < 0 )
- idx = 0;
- else if ( idx > num_args - 2 )
- idx = num_args - 2;
- args[0] = args[-( idx + 1 )];
- args++;
- }
- break;
-
- case cff_op_roll:
- {
- FT_Int count = (FT_Int)( args[0] >> 16 );
- FT_Int idx = (FT_Int)( args[1] >> 16 );
-
-
- FT_TRACE4(( " roll\n" ));
-
- if ( count <= 0 )
- count = 1;
-
- args -= count;
- if ( args < stack )
- goto Stack_Underflow;
-
- if ( idx >= 0 )
- {
- while ( idx > 0 )
- {
- FT_Fixed tmp = args[count - 1];
- FT_Int i;
-
-
- for ( i = count - 2; i >= 0; i-- )
- args[i + 1] = args[i];
- args[0] = tmp;
- idx--;
- }
- }
- else
- {
- while ( idx < 0 )
- {
- FT_Fixed tmp = args[0];
- FT_Int i;
-
-
- for ( i = 0; i < count - 1; i++ )
- args[i] = args[i + 1];
- args[count - 1] = tmp;
- idx++;
- }
- }
- args += count;
- }
- break;
-
- case cff_op_dup:
- FT_TRACE4(( " dup\n" ));
-
- args[1] = args[0];
- args += 2;
- break;
-
- case cff_op_put:
- {
- FT_Fixed val = args[0];
- FT_Int idx = (FT_Int)( args[1] >> 16 );
-
-
- FT_TRACE4(( " put\n" ));
-
- /* the Type2 specification before version 16-March-2000 */
- /* didn't give a hard-coded size limit of the temporary */
- /* storage array; instead, an argument of the */
- /* `MultipleMaster' operator set the size */
- if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS )
- decoder->buildchar[idx] = val;
- }
- break;
-
- case cff_op_get:
- {
- FT_Int idx = (FT_Int)( args[0] >> 16 );
- FT_Fixed val = 0;
-
-
- FT_TRACE4(( " get\n" ));
-
- if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS )
- val = decoder->buildchar[idx];
-
- args[0] = val;
- args++;
- }
- break;
-
- case cff_op_store:
- /* this operator was removed from the Type2 specification */
- /* in version 16-March-2000 */
-
- /* since we currently don't handle interpolation of multiple */
- /* master fonts, this is a no-op */
- FT_TRACE4(( " store\n"));
- break;
-
- case cff_op_load:
- /* this operator was removed from the Type2 specification */
- /* in version 16-March-2000 */
- {
- FT_Int reg_idx = (FT_Int)args[0];
- FT_Int idx = (FT_Int)args[1];
- FT_Int count = (FT_Int)args[2];
-
-
- FT_TRACE4(( " load\n" ));
-
- /* since we currently don't handle interpolation of multiple */
- /* master fonts, we store a vector [1 0 0 ...] in the */
- /* temporary storage array regardless of the Registry index */
- if ( reg_idx >= 0 && reg_idx <= 2 &&
- idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS &&
- count >= 0 && count <= num_axes )
- {
- FT_Int end, i;
-
-
- end = FT_MIN( idx + count, CFF_MAX_TRANS_ELEMENTS );
-
- if ( idx < end )
- decoder->buildchar[idx] = 1 << 16;
-
- for ( i = idx + 1; i < end; i++ )
- decoder->buildchar[i] = 0;
- }
- }
- break;
-
- case cff_op_blend:
- /* this operator was removed from the Type2 specification */
- /* in version 16-March-2000 */
- {
- FT_Int num_results = (FT_Int)( args[0] >> 16 );
-
-
- FT_TRACE4(( " blend\n" ));
-
- if ( num_results < 0 )
- goto Syntax_Error;
-
- if ( num_results * (FT_Int)num_designs > num_args )
- goto Stack_Underflow;
-
- /* since we currently don't handle interpolation of multiple */
- /* master fonts, return the `num_results' values of the */
- /* first master */
- args -= num_results * ( num_designs - 1 );
- num_args -= num_results * ( num_designs - 1 );
- }
- break;
-
- case cff_op_dotsection:
- /* this operator is deprecated and ignored by the parser */
- FT_TRACE4(( " dotsection\n" ));
- break;
-
- case cff_op_closepath:
- /* this is an invalid Type 2 operator; however, there */
- /* exist fonts which are incorrectly converted from probably */
- /* Type 1 to CFF, and some parsers seem to accept it */
-
- FT_TRACE4(( " closepath (invalid op)\n" ));
-
- args = stack;
- break;
-
- case cff_op_hsbw:
- /* this is an invalid Type 2 operator; however, there */
- /* exist fonts which are incorrectly converted from probably */
- /* Type 1 to CFF, and some parsers seem to accept it */
-
- FT_TRACE4(( " hsbw (invalid op)\n" ));
-
- decoder->glyph_width =
- ADD_LONG( decoder->nominal_width, ( args[1] >> 16 ) );
-
- decoder->builder.left_bearing.x = args[0];
- decoder->builder.left_bearing.y = 0;
-
- x = ADD_LONG( decoder->builder.pos_x, args[0] );
- y = decoder->builder.pos_y;
- args = stack;
- break;
-
- case cff_op_sbw:
- /* this is an invalid Type 2 operator; however, there */
- /* exist fonts which are incorrectly converted from probably */
- /* Type 1 to CFF, and some parsers seem to accept it */
-
- FT_TRACE4(( " sbw (invalid op)\n" ));
-
- decoder->glyph_width =
- ADD_LONG( decoder->nominal_width, ( args[2] >> 16 ) );
-
- decoder->builder.left_bearing.x = args[0];
- decoder->builder.left_bearing.y = args[1];
-
- x = ADD_LONG( decoder->builder.pos_x, args[0] );
- y = ADD_LONG( decoder->builder.pos_y, args[1] );
- args = stack;
- break;
-
- case cff_op_setcurrentpoint:
- /* this is an invalid Type 2 operator; however, there */
- /* exist fonts which are incorrectly converted from probably */
- /* Type 1 to CFF, and some parsers seem to accept it */
-
- FT_TRACE4(( " setcurrentpoint (invalid op)\n" ));
-
- x = ADD_LONG( decoder->builder.pos_x, args[0] );
- y = ADD_LONG( decoder->builder.pos_y, args[1] );
- args = stack;
- break;
-
- case cff_op_callothersubr:
- /* this is an invalid Type 2 operator; however, there */
- /* exist fonts which are incorrectly converted from probably */
- /* Type 1 to CFF, and some parsers seem to accept it */
-
- FT_TRACE4(( " callothersubr (invalid op)\n" ));
-
- /* subsequent `pop' operands should add the arguments, */
- /* this is the implementation described for `unknown' other */
- /* subroutines in the Type1 spec. */
- /* */
- /* XXX Fix return arguments (see discussion below). */
- args -= 2 + ( args[-2] >> 16 );
- if ( args < stack )
- goto Stack_Underflow;
- break;
-
- case cff_op_pop:
- /* this is an invalid Type 2 operator; however, there */
- /* exist fonts which are incorrectly converted from probably */
- /* Type 1 to CFF, and some parsers seem to accept it */
-
- FT_TRACE4(( " pop (invalid op)\n" ));
-
- /* XXX Increasing `args' is wrong: After a certain number of */
- /* `pop's we get a stack overflow. Reason for doing it is */
- /* code like this (actually found in a CFF font): */
- /* */
- /* 17 1 3 callothersubr */
- /* pop */
- /* callsubr */
- /* */
- /* Since we handle `callothersubr' as a no-op, and */
- /* `callsubr' needs at least one argument, `pop' can't be a */
- /* no-op too as it basically should be. */
- /* */
- /* The right solution would be to provide real support for */
- /* `callothersubr' as done in `t1decode.c', however, given */
- /* the fact that CFF fonts with `pop' are invalid, it is */
- /* questionable whether it is worth the time. */
- args++;
- break;
-
- case cff_op_and:
- {
- FT_Fixed cond = ( args[0] && args[1] );
-
-
- FT_TRACE4(( " and\n" ));
-
- args[0] = cond ? 0x10000L : 0;
- args++;
- }
- break;
-
- case cff_op_or:
- {
- FT_Fixed cond = ( args[0] || args[1] );
-
-
- FT_TRACE4(( " or\n" ));
-
- args[0] = cond ? 0x10000L : 0;
- args++;
- }
- break;
-
- case cff_op_not:
- {
- FT_Fixed cond = !args[0];
-
-
- FT_TRACE4(( " not\n" ));
-
- args[0] = cond ? 0x10000L : 0;
- args++;
- }
- break;
-
- case cff_op_eq:
- {
- FT_Fixed cond = ( args[0] == args[1] );
-
-
- FT_TRACE4(( " eq\n" ));
-
- args[0] = cond ? 0x10000L : 0;
- args++;
- }
- break;
-
- case cff_op_ifelse:
- {
- FT_Fixed cond = ( args[2] <= args[3] );
-
-
- FT_TRACE4(( " ifelse\n" ));
-
- if ( !cond )
- args[0] = args[1];
- args++;
- }
- break;
-
- case cff_op_callsubr:
- {
- FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) +
- decoder->locals_bias );
-
-
- FT_TRACE4(( " callsubr (idx %d, entering level %d)\n",
- idx,
- zone - decoder->zones + 1 ));
-
- if ( idx >= decoder->num_locals )
- {
- FT_ERROR(( "cff_decoder_parse_charstrings:"
- " invalid local subr index\n" ));
- goto Syntax_Error;
- }
-
- if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
- {
- FT_ERROR(( "cff_decoder_parse_charstrings:"
- " too many nested subrs\n" ));
- goto Syntax_Error;
- }
-
- zone->cursor = ip; /* save current instruction pointer */
-
- zone++;
- zone->base = decoder->locals[idx];
- zone->limit = decoder->locals[idx + 1];
- zone->cursor = zone->base;
-
- if ( !zone->base || zone->limit == zone->base )
- {
- FT_ERROR(( "cff_decoder_parse_charstrings:"
- " invoking empty subrs\n" ));
- goto Syntax_Error;
- }
-
- decoder->zone = zone;
- ip = zone->base;
- limit = zone->limit;
- }
- break;
-
- case cff_op_callgsubr:
- {
- FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) +
- decoder->globals_bias );
-
-
- FT_TRACE4(( " callgsubr (idx %d, entering level %d)\n",
- idx,
- zone - decoder->zones + 1 ));
-
- if ( idx >= decoder->num_globals )
- {
- FT_ERROR(( "cff_decoder_parse_charstrings:"
- " invalid global subr index\n" ));
- goto Syntax_Error;
- }
-
- if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
- {
- FT_ERROR(( "cff_decoder_parse_charstrings:"
- " too many nested subrs\n" ));
- goto Syntax_Error;
- }
-
- zone->cursor = ip; /* save current instruction pointer */
-
- zone++;
- zone->base = decoder->globals[idx];
- zone->limit = decoder->globals[idx + 1];
- zone->cursor = zone->base;
-
- if ( !zone->base || zone->limit == zone->base )
- {
- FT_ERROR(( "cff_decoder_parse_charstrings:"
- " invoking empty subrs\n" ));
- goto Syntax_Error;
- }
-
- decoder->zone = zone;
- ip = zone->base;
- limit = zone->limit;
- }
- break;
-
- case cff_op_return:
- FT_TRACE4(( " return (leaving level %d)\n",
- decoder->zone - decoder->zones ));
-
- if ( decoder->zone <= decoder->zones )
- {
- FT_ERROR(( "cff_decoder_parse_charstrings:"
- " unexpected return\n" ));
- goto Syntax_Error;
- }
-
- decoder->zone--;
- zone = decoder->zone;
- ip = zone->cursor;
- limit = zone->limit;
- break;
-
- default:
- FT_ERROR(( "Unimplemented opcode: %d", ip[-1] ));
-
- if ( ip[-1] == 12 )
- FT_ERROR(( " %d", ip[0] ));
- FT_ERROR(( "\n" ));
-
- return FT_THROW( Unimplemented_Feature );
- }
-
- decoder->top = args;
-
- if ( decoder->top - stack >= CFF_MAX_OPERANDS )
- goto Stack_Overflow;
-
- } /* general operator processing */
-
- } /* while ip < limit */
-
- FT_TRACE4(( "..end..\n\n" ));
-
- Fail:
- return error;
-
- MM_Error:
- FT_TRACE4(( "cff_decoder_parse_charstrings:"
- " invalid opcode found in top DICT charstring\n"));
- return FT_THROW( Invalid_File_Format );
-
- Syntax_Error:
- FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error\n" ));
- return FT_THROW( Invalid_File_Format );
-
- Stack_Underflow:
- FT_TRACE4(( "cff_decoder_parse_charstrings: stack underflow\n" ));
- return FT_THROW( Too_Few_Arguments );
-
- Stack_Overflow:
- FT_TRACE4(( "cff_decoder_parse_charstrings: stack overflow\n" ));
- return FT_THROW( Stack_Overflow );
- }
-
-#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */
-
-
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
@@ -2704,11 +142,14 @@
FT_Int glyph_index;
CFF_Font cff = (CFF_Font)face->other;
+ PSAux_Service psaux = (PSAux_Service)face->psaux;
+ const CFF_Decoder_Funcs decoder_funcs = psaux->cff_decoder_funcs;
+
*max_advance = 0;
/* Initialize load decoder */
- cff_decoder_init( &decoder, face, 0, 0, 0, 0 );
+ decoder_funcs->init( &decoder, face, 0, 0, 0, 0, 0, 0 );
decoder.builder.metrics_only = 1;
decoder.builder.load_points = 0;
@@ -2727,12 +168,12 @@
&charstring, &charstring_len );
if ( !error )
{
- error = cff_decoder_prepare( &decoder, size, glyph_index );
+ error = decoder_funcs->prepare( &decoder, size, glyph_index );
if ( !error )
- error = cff_decoder_parse_charstrings( &decoder,
- charstring,
- charstring_len,
- 0 );
+ error = decoder_funcs->parse_charstrings_old( &decoder,
+ charstring,
+ charstring_len,
+ 0 );
cff_free_glyph_data( face, &charstring, &charstring_len );
}
@@ -2758,10 +199,14 @@
{
FT_Error error;
CFF_Decoder decoder;
+ PS_Decoder psdecoder;
TT_Face face = (TT_Face)glyph->root.face;
FT_Bool hinting, scaled, force_scaling;
CFF_Font cff = (CFF_Font)face->extra.data;
+ PSAux_Service psaux = (PSAux_Service)face->psaux;
+ const CFF_Decoder_Funcs decoder_funcs = psaux->cff_decoder_funcs;
+
FT_Matrix font_matrix;
FT_Vector font_offset;
@@ -2951,7 +396,7 @@
{
#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
- CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( face );
+ PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( face );
#endif
@@ -2959,8 +404,10 @@
FT_ULong charstring_len;
- cff_decoder_init( &decoder, face, size, glyph, hinting,
- FT_LOAD_TARGET_MODE( load_flags ) );
+ decoder_funcs->init( &decoder, face, size, glyph, hinting,
+ FT_LOAD_TARGET_MODE( load_flags ),
+ cff_get_glyph_data,
+ cff_free_glyph_data );
/* this is for pure CFFs */
if ( load_flags & FT_LOAD_ADVANCE_ONLY )
@@ -2975,23 +422,25 @@
if ( error )
goto Glyph_Build_Finished;
- error = cff_decoder_prepare( &decoder, size, glyph_index );
+ error = decoder_funcs->prepare( &decoder, size, glyph_index );
if ( error )
goto Glyph_Build_Finished;
#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
/* choose which CFF renderer to use */
- if ( driver->hinting_engine == FT_CFF_HINTING_FREETYPE )
- error = cff_decoder_parse_charstrings( &decoder,
- charstring,
- charstring_len,
- 0 );
+ if ( driver->hinting_engine == FT_HINTING_FREETYPE )
+ error = decoder_funcs->parse_charstrings_old( &decoder,
+ charstring,
+ charstring_len,
+ 0 );
else
#endif
{
- error = cf2_decoder_parse_charstrings( &decoder,
- charstring,
- charstring_len );
+ psaux->ps_decoder_init( &psdecoder, &decoder, FALSE );
+
+ error = decoder_funcs->parse_charstrings( &psdecoder,
+ charstring,
+ charstring_len );
/* Adobe's engine uses 16.16 numbers everywhere; */
/* as a consequence, glyphs larger than 2000ppem get rejected */
@@ -3004,9 +453,9 @@
force_scaling = TRUE;
glyph->hint = hinting;
- error = cf2_decoder_parse_charstrings( &decoder,
- charstring,
- charstring_len );
+ error = decoder_funcs->parse_charstrings( &psdecoder,
+ charstring,
+ charstring_len );
}
}
@@ -3044,7 +493,7 @@
Glyph_Build_Finished:
/* save new glyph tables, if no error */
if ( !error )
- cff_builder_done( &decoder.builder );
+ decoder.builder.funcs.done( &decoder.builder );
/* XXX: anything to do for broken glyph entry? */
}
diff --git a/thirdparty/freetype/src/cff/cffgload.h b/thirdparty/freetype/src/cff/cffgload.h
index 0fa93b4398..803f3974fc 100644
--- a/thirdparty/freetype/src/cff/cffgload.h
+++ b/thirdparty/freetype/src/cff/cffgload.h
@@ -4,7 +4,7 @@
/* */
/* OpenType Glyph Loader (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -22,119 +22,11 @@
#include <ft2build.h>
#include FT_FREETYPE_H
-#include "cffobjs.h"
+#include FT_INTERNAL_CFF_OBJECTS_TYPES_H
FT_BEGIN_HEADER
-
-#define CFF_MAX_OPERANDS 48
-#define CFF_MAX_SUBRS_CALLS 16 /* maximum subroutine nesting; */
- /* only 10 are allowed but there exist */
- /* fonts like `HiraKakuProN-W3.ttf' */
- /* (Hiragino Kaku Gothic ProN W3; */
- /* 8.2d6e1; 2014-12-19) that exceed */
- /* this limit */
-#define CFF_MAX_TRANS_ELEMENTS 32
-
-
- /*************************************************************************/
- /* */
- /* <Structure> */
- /* CFF_Builder */
- /* */
- /* <Description> */
- /* A structure used during glyph loading to store its outline. */
- /* */
- /* <Fields> */
- /* memory :: The current memory object. */
- /* */
- /* face :: The current face object. */
- /* */
- /* glyph :: The current glyph slot. */
- /* */
- /* loader :: The current glyph loader. */
- /* */
- /* base :: The base glyph outline. */
- /* */
- /* current :: The current glyph outline. */
- /* */
- /* pos_x :: The horizontal translation (if composite glyph). */
- /* */
- /* pos_y :: The vertical translation (if composite glyph). */
- /* */
- /* left_bearing :: The left side bearing point. */
- /* */
- /* advance :: The horizontal advance vector. */
- /* */
- /* bbox :: Unused. */
- /* */
- /* path_begun :: A flag which indicates that a new path has begun. */
- /* */
- /* load_points :: If this flag is not set, no points are loaded. */
- /* */
- /* no_recurse :: Set but not used. */
- /* */
- /* metrics_only :: A boolean indicating that we only want to compute */
- /* the metrics of a given glyph, not load all of its */
- /* points. */
- /* */
- /* hints_funcs :: Auxiliary pointer for hinting. */
- /* */
- /* hints_globals :: Auxiliary pointer for hinting. */
- /* */
- typedef struct CFF_Builder_
- {
- FT_Memory memory;
- TT_Face face;
- CFF_GlyphSlot glyph;
- FT_GlyphLoader loader;
- FT_Outline* base;
- FT_Outline* current;
-
- FT_Pos pos_x;
- FT_Pos pos_y;
-
- FT_Vector left_bearing;
- FT_Vector advance;
-
- FT_BBox bbox; /* bounding box */
- FT_Bool path_begun;
- FT_Bool load_points;
- FT_Bool no_recurse;
-
- FT_Bool metrics_only;
-
- void* hints_funcs; /* hinter-specific */
- void* hints_globals; /* hinter-specific */
-
- } CFF_Builder;
-
-
- FT_LOCAL( FT_Error )
- cff_check_points( CFF_Builder* builder,
- FT_Int count );
-
- FT_LOCAL( void )
- cff_builder_add_point( CFF_Builder* builder,
- FT_Pos x,
- FT_Pos y,
- FT_Byte flag );
- FT_LOCAL( FT_Error )
- cff_builder_add_point1( CFF_Builder* builder,
- FT_Pos x,
- FT_Pos y );
- FT_LOCAL( FT_Error )
- cff_builder_start_point( CFF_Builder* builder,
- FT_Pos x,
- FT_Pos y );
- FT_LOCAL( void )
- cff_builder_close_contour( CFF_Builder* builder );
-
-
- FT_LOCAL( FT_Int )
- cff_lookup_glyph_by_stdcharcode( CFF_Font cff,
- FT_Int charcode );
FT_LOCAL( FT_Error )
cff_get_glyph_data( TT_Face face,
FT_UInt glyph_index,
@@ -146,74 +38,6 @@ FT_BEGIN_HEADER
FT_ULong length );
- /* execution context charstring zone */
-
- typedef struct CFF_Decoder_Zone_
- {
- FT_Byte* base;
- FT_Byte* limit;
- FT_Byte* cursor;
-
- } CFF_Decoder_Zone;
-
-
- typedef struct CFF_Decoder_
- {
- CFF_Builder builder;
- CFF_Font cff;
-
- FT_Fixed stack[CFF_MAX_OPERANDS + 1];
- FT_Fixed* top;
-
- CFF_Decoder_Zone zones[CFF_MAX_SUBRS_CALLS + 1];
- CFF_Decoder_Zone* zone;
-
- FT_Int flex_state;
- FT_Int num_flex_vectors;
- FT_Vector flex_vectors[7];
-
- FT_Pos glyph_width;
- FT_Pos nominal_width;
-
- FT_Bool read_width;
- FT_Bool width_only;
- FT_Int num_hints;
- FT_Fixed buildchar[CFF_MAX_TRANS_ELEMENTS];
-
- FT_UInt num_locals;
- FT_UInt num_globals;
-
- FT_Int locals_bias;
- FT_Int globals_bias;
-
- FT_Byte** locals;
- FT_Byte** globals;
-
- FT_Byte** glyph_names; /* for pure CFF fonts only */
- FT_UInt num_glyphs; /* number of glyphs in font */
-
- FT_Render_Mode hint_mode;
-
- FT_Bool seac;
-
- CFF_SubFont current_subfont; /* for current glyph_index */
-
- } CFF_Decoder;
-
-
- FT_LOCAL( void )
- cff_decoder_init( CFF_Decoder* decoder,
- TT_Face face,
- CFF_Size size,
- CFF_GlyphSlot slot,
- FT_Bool hinting,
- FT_Render_Mode hint_mode );
-
- FT_LOCAL( FT_Error )
- cff_decoder_prepare( CFF_Decoder* decoder,
- CFF_Size size,
- FT_UInt glyph_index );
-
#if 0 /* unused until we support pure CFF fonts */
/* Compute the maximum advance width of a font through quick parsing */
@@ -223,13 +47,6 @@ FT_BEGIN_HEADER
#endif /* 0 */
-#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
- FT_LOCAL( FT_Error )
- cff_decoder_parse_charstrings( CFF_Decoder* decoder,
- FT_Byte* charstring_base,
- FT_ULong charstring_len,
- FT_Bool in_dict );
-#endif
FT_LOCAL( FT_Error )
cff_slot_load( CFF_GlyphSlot glyph,
diff --git a/thirdparty/freetype/src/cff/cffload.c b/thirdparty/freetype/src/cff/cffload.c
index 12420384af..1c6fe51566 100644
--- a/thirdparty/freetype/src/cff/cffload.c
+++ b/thirdparty/freetype/src/cff/cffload.c
@@ -4,7 +4,7 @@
/* */
/* OpenType and CFF data/program tables loader (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -22,6 +22,7 @@
#include FT_INTERNAL_STREAM_H
#include FT_TRUETYPE_TAGS_H
#include FT_TYPE1_TABLES_H
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
#include FT_MULTIPLE_MASTERS_H
@@ -1297,7 +1298,9 @@
if ( numOperands > count )
{
- FT_TRACE4(( " cff_blend_doBlend: Stack underflow %d args\n", count ));
+ FT_TRACE4(( " cff_blend_doBlend: Stack underflow %d argument%s\n",
+ count,
+ count == 1 ? "" : "s" ));
error = FT_THROW( Stack_Underflow );
goto Exit;
@@ -1345,19 +1348,14 @@
for ( i = 0; i < numBlends; i++ )
{
const FT_Int32* weight = &blend->BV[1];
- FT_Int32 sum;
+ FT_UInt32 sum;
/* convert inputs to 16.16 fixed point */
- sum = cff_parse_num( parser, &parser->stack[i + base] ) * 65536;
+ sum = cff_parse_num( parser, &parser->stack[i + base] ) * 0x10000;
for ( j = 1; j < blend->lenBV; j++ )
- sum = ADD_INT32(
- sum,
- FT_MulFix(
- *weight++,
- cff_parse_num( parser,
- &parser->stack[delta++] ) * 65536 ) );
+ sum += cff_parse_num( parser, &parser->stack[delta++] ) * *weight++;
/* point parser stack to new value on blend_stack */
parser->stack[i + base] = subFont->blend_top;
@@ -1367,10 +1365,10 @@
/* opcode in both CFF and CFF2 DICTs. See `cff_parse_num' for */
/* decode of this, which rounds to an integer. */
*subFont->blend_top++ = 255;
- *subFont->blend_top++ = ( (FT_UInt32)sum & 0xFF000000U ) >> 24;
- *subFont->blend_top++ = ( (FT_UInt32)sum & 0x00FF0000U ) >> 16;
- *subFont->blend_top++ = ( (FT_UInt32)sum & 0x0000FF00U ) >> 8;
- *subFont->blend_top++ = (FT_UInt32)sum & 0x000000FFU;
+ *subFont->blend_top++ = (FT_Byte)( sum >> 24 );
+ *subFont->blend_top++ = (FT_Byte)( sum >> 16 );
+ *subFont->blend_top++ = (FT_Byte)( sum >> 8 );
+ *subFont->blend_top++ = (FT_Byte)sum;
}
/* leave only numBlends results on parser stack */
@@ -1558,13 +1556,13 @@
FT_UInt lenNDV,
FT_Fixed* NDV )
{
- if ( !blend->builtBV ||
- blend->lastVsindex != vsindex ||
- blend->lenNDV != lenNDV ||
- ( lenNDV &&
- memcmp( NDV,
- blend->lastNDV,
- lenNDV * sizeof ( *NDV ) ) != 0 ) )
+ if ( !blend->builtBV ||
+ blend->lastVsindex != vsindex ||
+ blend->lenNDV != lenNDV ||
+ ( lenNDV &&
+ ft_memcmp( NDV,
+ blend->lastNDV,
+ lenNDV * sizeof ( *NDV ) ) != 0 ) )
{
/* need to build blend vector */
return TRUE;
@@ -1600,7 +1598,8 @@
FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm;
- mm->done_blend( FT_FACE( face ) );
+ if (mm)
+ mm->done_blend( FT_FACE( face ) );
}
#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
@@ -1934,6 +1933,24 @@
else if ( priv->initial_random_seed == 0 )
priv->initial_random_seed = 987654321;
+ /* some sanitizing to avoid overflows later on; */
+ /* the upper limits are ad-hoc values */
+ if ( priv->blue_shift > 1000 || priv->blue_shift < 0 )
+ {
+ FT_TRACE2(( "cff_load_private_dict:"
+ " setting unlikely BlueShift value %d to default (7)\n",
+ priv->blue_shift ));
+ priv->blue_shift = 7;
+ }
+
+ if ( priv->blue_fuzz > 1000 || priv->blue_fuzz < 0 )
+ {
+ FT_TRACE2(( "cff_load_private_dict:"
+ " setting unlikely BlueFuzz value %d to default (1)\n",
+ priv->blue_fuzz ));
+ priv->blue_fuzz = 1;
+ }
+
Exit:
/* clean up */
cff_blend_clear( subfont ); /* clear blend stack */
@@ -1945,18 +1962,6 @@
}
- FT_LOCAL_DEF( FT_UInt32 )
- cff_random( FT_UInt32 r )
- {
- /* a 32bit version of the `xorshift' algorithm */
- r ^= r << 13;
- r ^= r >> 17;
- r ^= r << 5;
-
- return r;
- }
-
-
/* There are 3 ways to call this function, distinguished by code. */
/* */
/* . CFF_CODE_TOPDICT for either a CFF Top DICT or a CFF Font DICT */
@@ -1980,6 +1985,8 @@
CFF_FontRecDict top = &subfont->font_dict;
CFF_Private priv = &subfont->private_dict;
+ PSAux_Service psaux = (PSAux_Service)face->psaux;
+
FT_Bool cff2 = FT_BOOL( code == CFF2_CODE_TOPDICT ||
code == CFF2_CODE_FONTDICT );
FT_UInt stackSize = cff2 ? CFF2_DEFAULT_STACK
@@ -2085,7 +2092,7 @@
*/
if ( face->root.internal->random_seed == -1 )
{
- CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( face );
+ PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( face );
subfont->random = (FT_UInt32)driver->random_seed;
@@ -2094,7 +2101,7 @@
do
{
driver->random_seed =
- (FT_Int32)cff_random( (FT_UInt32)driver->random_seed );
+ (FT_Int32)psaux->cff_random( (FT_UInt32)driver->random_seed );
} while ( driver->random_seed < 0 );
}
@@ -2107,7 +2114,8 @@
do
{
face->root.internal->random_seed =
- (FT_Int32)cff_random( (FT_UInt32)face->root.internal->random_seed );
+ (FT_Int32)psaux->cff_random(
+ (FT_UInt32)face->root.internal->random_seed );
} while ( face->root.internal->random_seed < 0 );
}
@@ -2548,6 +2556,8 @@
font->cf2_instance.finalizer( font->cf2_instance.data );
FT_FREE( font->cf2_instance.data );
}
+
+ FT_FREE( font->font_extra );
}
diff --git a/thirdparty/freetype/src/cff/cffload.h b/thirdparty/freetype/src/cff/cffload.h
index c745e8127b..14d14e2112 100644
--- a/thirdparty/freetype/src/cff/cffload.h
+++ b/thirdparty/freetype/src/cff/cffload.h
@@ -4,7 +4,7 @@
/* */
/* OpenType & CFF data/program tables loader (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -21,9 +21,9 @@
#include <ft2build.h>
-#include "cfftypes.h"
+#include FT_INTERNAL_CFF_TYPES_H
#include "cffparse.h"
-#include "cffobjs.h" /* for CFF_Face */
+#include FT_INTERNAL_CFF_OBJECTS_TYPES_H /* for CFF_Face */
FT_BEGIN_HEADER
@@ -61,9 +61,6 @@ FT_BEGIN_HEADER
FT_UInt cid );
- FT_LOCAL( FT_UInt32 )
- cff_random( FT_UInt32 r );
-
FT_LOCAL( FT_Error )
cff_font_load( FT_Library library,
FT_Stream stream,
diff --git a/thirdparty/freetype/src/cff/cffobjs.c b/thirdparty/freetype/src/cff/cffobjs.c
index 61613933ff..a2d7aec65e 100644
--- a/thirdparty/freetype/src/cff/cffobjs.c
+++ b/thirdparty/freetype/src/cff/cffobjs.c
@@ -4,7 +4,7 @@
/* */
/* OpenType objects manager (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -25,13 +25,15 @@
#include FT_TRUETYPE_IDS_H
#include FT_TRUETYPE_TAGS_H
#include FT_INTERNAL_SFNT_H
-#include FT_CFF_DRIVER_H
+#include FT_DRIVER_H
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
#include FT_MULTIPLE_MASTERS_H
#include FT_SERVICE_MULTIPLE_MASTERS_H
+#include FT_SERVICE_METRICS_VARIATIONS_H
#endif
+#include FT_INTERNAL_CFF_OBJECTS_TYPES_H
#include "cffobjs.h"
#include "cffload.h"
#include "cffcmap.h"
@@ -39,6 +41,9 @@
#include "cfferrs.h"
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+#include FT_SERVICE_CFF_TABLE_LOAD_H
+
/*************************************************************************/
/* */
@@ -408,7 +413,7 @@
remove_subset_prefix( FT_String* name )
{
FT_Int32 idx = 0;
- FT_Int32 length = (FT_Int32)strlen( name ) + 1;
+ FT_Int32 length = (FT_Int32)ft_strlen( name ) + 1;
FT_Bool continue_search = 1;
@@ -445,8 +450,8 @@
FT_Int32 family_name_length, style_name_length;
- family_name_length = (FT_Int32)strlen( family_name );
- style_name_length = (FT_Int32)strlen( style_name );
+ family_name_length = (FT_Int32)ft_strlen( family_name );
+ style_name_length = (FT_Int32)ft_strlen( style_name );
if ( family_name_length > style_name_length )
{
@@ -493,14 +498,16 @@
SFNT_Service sfnt;
FT_Service_PsCMaps psnames;
PSHinter_Service pshinter;
+ PSAux_Service psaux;
+ FT_Service_CFFLoad cffload;
FT_Bool pure_cff = 1;
FT_Bool cff2 = 0;
FT_Bool sfnt_format = 0;
FT_Library library = cffface->driver->root.library;
- sfnt = (SFNT_Service)FT_Get_Module_Interface(
- library, "sfnt" );
+ sfnt = (SFNT_Service)FT_Get_Module_Interface( library,
+ "sfnt" );
if ( !sfnt )
{
FT_ERROR(( "cff_face_init: cannot access `sfnt' module\n" ));
@@ -510,8 +517,20 @@
FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
- pshinter = (PSHinter_Service)FT_Get_Module_Interface(
- library, "pshinter" );
+ pshinter = (PSHinter_Service)FT_Get_Module_Interface( library,
+ "pshinter" );
+
+ psaux = (PSAux_Service)FT_Get_Module_Interface( library,
+ "psaux" );
+ if ( !psaux )
+ {
+ FT_ERROR(( "cff_face_init: cannot access `psaux' module\n" ));
+ error = FT_THROW( Missing_Module );
+ goto Exit;
+ }
+ face->psaux = psaux;
+
+ FT_FACE_FIND_GLOBAL_SERVICE( face, cffload, CFF_LOAD );
FT_TRACE2(( "CFF driver\n" ));
@@ -614,6 +633,7 @@
cff->pshinter = pshinter;
cff->psnames = psnames;
+ cff->cffload = cffload;
cffface->face_index = face_index & 0xFFFF;
@@ -690,50 +710,22 @@
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
{
- FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm;
+ FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm;
+ FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var;
- FT_Int instance_index = face_index >> 16;
+ FT_UInt instance_index = (FT_UInt)face_index >> 16;
if ( FT_HAS_MULTIPLE_MASTERS( cffface ) &&
mm &&
instance_index > 0 )
{
- FT_MM_Var* mm_var;
-
-
- error = mm->get_mm_var( cffface, NULL );
+ error = mm->set_instance( cffface, instance_index );
if ( error )
goto Exit;
- mm->get_var_blend( cffface, NULL, NULL, NULL, &mm_var );
-
- if ( mm_var->namedstyle )
- {
- FT_Var_Named_Style* named_style;
- FT_String* style_name;
-
-
- /* in `face_index', the instance index starts with value 1 */
- named_style = mm_var->namedstyle + instance_index - 1;
- error = sfnt->get_name( face,
- (FT_UShort)named_style->strid,
- &style_name );
- if ( error )
- goto Exit;
-
- /* set style name; if already set, replace it */
- if ( face->root.style_name )
- FT_FREE( face->root.style_name );
- face->root.style_name = style_name;
-
- /* finally, select the named instance */
- error = mm->set_var_design( cffface,
- mm_var->num_axis,
- named_style->coords );
- if ( error )
- goto Exit;
- }
+ if ( var )
+ var->metrics_adjust( cffface );
}
}
#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
@@ -876,7 +868,8 @@
cffface->height = (FT_Short)( ( cffface->units_per_EM * 12 ) / 10 );
if ( cffface->height < cffface->ascender - cffface->descender )
- cffface->height = (FT_Short)( cffface->ascender - cffface->descender );
+ cffface->height = (FT_Short)( cffface->ascender -
+ cffface->descender );
cffface->underline_position =
(FT_Short)( dict->underline_position >> 16 );
@@ -884,27 +877,32 @@
(FT_Short)( dict->underline_thickness >> 16 );
/* retrieve font family & style name */
- cffface->family_name = cff_index_get_name(
- cff,
- (FT_UInt)( face_index & 0xFFFF ) );
+ if ( dict->family_name )
+ {
+ char* family_name;
+
+
+ family_name = cff_index_get_sid_string( cff, dict->family_name );
+ if ( family_name )
+ cffface->family_name = cff_strcpy( memory, family_name );
+ }
+
+ if ( !cffface->family_name )
+ {
+ cffface->family_name = cff_index_get_name(
+ cff,
+ (FT_UInt)( face_index & 0xFFFF ) );
+ if ( cffface->family_name )
+ remove_subset_prefix( cffface->family_name );
+ }
+
if ( cffface->family_name )
{
char* full = cff_index_get_sid_string( cff,
dict->full_name );
char* fullp = full;
char* family = cffface->family_name;
- char* family_name = NULL;
-
- remove_subset_prefix( cffface->family_name );
-
- if ( dict->family_name )
- {
- family_name = cff_index_get_sid_string( cff,
- dict->family_name );
- if ( family_name )
- family = family_name;
- }
/* We try to extract the style name from the full name. */
/* We need to ignore spaces and dashes during the search. */
@@ -1159,16 +1157,16 @@
FT_LOCAL_DEF( FT_Error )
cff_driver_init( FT_Module module ) /* CFF_Driver */
{
- CFF_Driver driver = (CFF_Driver)module;
+ PS_Driver driver = (PS_Driver)module;
FT_UInt32 seed;
/* set default property values, cf. `ftcffdrv.h' */
#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
- driver->hinting_engine = FT_CFF_HINTING_FREETYPE;
+ driver->hinting_engine = FT_HINTING_FREETYPE;
#else
- driver->hinting_engine = FT_CFF_HINTING_ADOBE;
+ driver->hinting_engine = FT_HINTING_ADOBE;
#endif
driver->no_stem_darkening = TRUE;
diff --git a/thirdparty/freetype/src/cff/cffobjs.h b/thirdparty/freetype/src/cff/cffobjs.h
index 1dba694c53..616a25b3b5 100644
--- a/thirdparty/freetype/src/cff/cffobjs.h
+++ b/thirdparty/freetype/src/cff/cffobjs.h
@@ -4,7 +4,7 @@
/* */
/* OpenType objects manager (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -21,111 +21,11 @@
#include <ft2build.h>
-#include FT_INTERNAL_OBJECTS_H
-#include "cfftypes.h"
-#include FT_INTERNAL_TRUETYPE_TYPES_H
-#include FT_SERVICE_POSTSCRIPT_CMAPS_H
-#include FT_INTERNAL_POSTSCRIPT_HINTS_H
FT_BEGIN_HEADER
- /*************************************************************************/
- /* */
- /* <Type> */
- /* CFF_Driver */
- /* */
- /* <Description> */
- /* A handle to an OpenType driver object. */
- /* */
- typedef struct CFF_DriverRec_* CFF_Driver;
-
- typedef TT_Face CFF_Face;
-
-
- /*************************************************************************/
- /* */
- /* <Type> */
- /* CFF_Size */
- /* */
- /* <Description> */
- /* A handle to an OpenType size object. */
- /* */
- typedef struct CFF_SizeRec_
- {
- FT_SizeRec root;
- FT_ULong strike_index; /* 0xFFFFFFFF to indicate invalid */
-
- } CFF_SizeRec, *CFF_Size;
-
-
- /*************************************************************************/
- /* */
- /* <Type> */
- /* CFF_GlyphSlot */
- /* */
- /* <Description> */
- /* A handle to an OpenType glyph slot object. */
- /* */
- typedef struct CFF_GlyphSlotRec_
- {
- FT_GlyphSlotRec root;
-
- FT_Bool hint;
- FT_Bool scaled;
-
- FT_Fixed x_scale;
- FT_Fixed y_scale;
-
- } CFF_GlyphSlotRec, *CFF_GlyphSlot;
-
-
- /*************************************************************************/
- /* */
- /* <Type> */
- /* CFF_Internal */
- /* */
- /* <Description> */
- /* The interface to the `internal' field of `FT_Size'. */
- /* */
- typedef struct CFF_InternalRec_
- {
- PSH_Globals topfont;
- PSH_Globals subfonts[CFF_MAX_CID_FONTS];
-
- } CFF_InternalRec, *CFF_Internal;
-
-
- /*************************************************************************/
- /* */
- /* Subglyph transformation record. */
- /* */
- typedef struct CFF_Transform_
- {
- FT_Fixed xx, xy; /* transformation matrix coefficients */
- FT_Fixed yx, yy;
- FT_F26Dot6 ox, oy; /* offsets */
-
- } CFF_Transform;
-
-
- /***********************************************************************/
- /* */
- /* CFF driver class. */
- /* */
- typedef struct CFF_DriverRec_
- {
- FT_DriverRec root;
-
- FT_UInt hinting_engine;
- FT_Bool no_stem_darkening;
- FT_Int darken_params[8];
- FT_Int32 random_seed;
-
- } CFF_DriverRec;
-
-
FT_LOCAL( FT_Error )
cff_size_init( FT_Size size ); /* CFF_Size */
@@ -171,10 +71,10 @@ FT_BEGIN_HEADER
/* Driver functions */
/* */
FT_LOCAL( FT_Error )
- cff_driver_init( FT_Module module ); /* CFF_Driver */
+ cff_driver_init( FT_Module module ); /* PS_Driver */
FT_LOCAL( void )
- cff_driver_done( FT_Module module ); /* CFF_Driver */
+ cff_driver_done( FT_Module module ); /* PS_Driver */
FT_END_HEADER
diff --git a/thirdparty/freetype/src/cff/cffparse.c b/thirdparty/freetype/src/cff/cffparse.c
index 9d7bf6d22c..b9611cf548 100644
--- a/thirdparty/freetype/src/cff/cffparse.c
+++ b/thirdparty/freetype/src/cff/cffparse.c
@@ -4,7 +4,7 @@
/* */
/* CFF token stream parser (body) */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -21,10 +21,10 @@
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_CALC_H
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
#include "cfferrs.h"
#include "cffpic.h"
-#include "cffgload.h"
#include "cffload.h"
@@ -949,7 +949,9 @@
goto Exit;
}
- FT_TRACE4(( " %d values blended\n", numBlends ));
+ FT_TRACE4(( " %d value%s blended\n",
+ numBlends,
+ numBlends == 1 ? "" : "s" ));
error = cff_blend_doBlend( subFont, parser, numBlends );
@@ -1299,9 +1301,14 @@
FT_Byte* start,
FT_Byte* limit )
{
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+ PSAux_Service psaux;
+#endif
+
FT_Byte* p = start;
FT_Error error = FT_Err_Ok;
FT_Library library = parser->library;
+
FT_UNUSED( library );
@@ -1388,10 +1395,16 @@
cff_rec.top_font.font_dict.num_axes = parser->num_axes;
decoder.cff = &cff_rec;
- error = cff_decoder_parse_charstrings( &decoder,
- charstring_base,
- charstring_len,
- 1 );
+ psaux = (PSAux_Service)FT_Get_Module_Interface( library, "psaux" );
+ if ( !psaux )
+ {
+ FT_ERROR(( "cff_parser_run: cannot access `psaux' module\n" ));
+ error = FT_THROW( Missing_Module );
+ goto Exit;
+ }
+
+ error = psaux->cff_decoder_funcs->parse_charstrings_old(
+ &decoder, charstring_base, charstring_len, 1 );
/* Now copy the stack data in the temporary decoder object, */
/* converting it back to charstring number representations */
diff --git a/thirdparty/freetype/src/cff/cffparse.h b/thirdparty/freetype/src/cff/cffparse.h
index 83d1bba45f..8a8caeca44 100644
--- a/thirdparty/freetype/src/cff/cffparse.h
+++ b/thirdparty/freetype/src/cff/cffparse.h
@@ -4,7 +4,7 @@
/* */
/* CFF token stream parser (specification) */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -21,7 +21,7 @@
#include <ft2build.h>
-#include "cfftypes.h"
+#include FT_INTERNAL_CFF_TYPES_H
#include FT_INTERNAL_OBJECTS_H
diff --git a/thirdparty/freetype/src/cff/cffpic.c b/thirdparty/freetype/src/cff/cffpic.c
index 4e9ba12b3f..08b74c7cf2 100644
--- a/thirdparty/freetype/src/cff/cffpic.c
+++ b/thirdparty/freetype/src/cff/cffpic.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for cff module. */
/* */
-/* Copyright 2009-2017 by */
+/* Copyright 2009-2018 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cff/cffpic.h b/thirdparty/freetype/src/cff/cffpic.h
index 5db39cd627..8ba4203a8d 100644
--- a/thirdparty/freetype/src/cff/cffpic.h
+++ b/thirdparty/freetype/src/cff/cffpic.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for cff module. */
/* */
-/* Copyright 2009-2017 by */
+/* Copyright 2009-2018 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -22,7 +22,6 @@
#include FT_INTERNAL_PIC_H
-
#ifndef FT_CONFIG_OPTION_PIC
#define CFF_SERVICE_PS_INFO_GET cff_service_ps_info
@@ -34,6 +33,7 @@
#define CFF_SERVICES_GET cff_services
#define CFF_SERVICE_MULTI_MASTERS_GET cff_service_multi_masters
#define CFF_SERVICE_METRICS_VAR_GET cff_service_metrics_variations
+#define CFF_SERVICE_CFF_LOAD_GET cff_service_cff_load
#define CFF_CMAP_ENCODING_CLASS_REC_GET cff_cmap_encoding_class_rec
#define CFF_CMAP_UNICODE_CLASS_REC_GET cff_cmap_unicode_class_rec
#define CFF_FIELD_HANDLERS_GET cff_field_handlers
@@ -65,6 +65,7 @@ FT_BEGIN_HEADER
FT_Service_PropertiesRec cff_service_properties;
FT_Service_MultiMastersRec cff_service_multi_masters;
FT_Service_MetricsVariationsRec cff_service_metrics_variations;
+ FT_Service_CFFLoadRec cff_service_cff_load;
FT_CMap_ClassRec cff_cmap_encoding_class_rec;
FT_CMap_ClassRec cff_cmap_unicode_class_rec;
@@ -92,6 +93,8 @@ FT_BEGIN_HEADER
( GET_PIC( library )->cff_service_multi_masters )
#define CFF_SERVICE_METRICS_VAR_GET \
( GET_PIC( library )->cff_service_metrics_variations )
+#define CFF_SERVICE_CFF_LOAD_GET \
+ ( GET_PIC( library )->cff_service_cff_load )
#define CFF_CMAP_ENCODING_CLASS_REC_GET \
( GET_PIC( library )->cff_cmap_encoding_class_rec )
#define CFF_CMAP_UNICODE_CLASS_REC_GET \
diff --git a/thirdparty/freetype/src/cff/cfftoken.h b/thirdparty/freetype/src/cff/cfftoken.h
index 3222e933f1..fec1ca20bd 100644
--- a/thirdparty/freetype/src/cff/cfftoken.h
+++ b/thirdparty/freetype/src/cff/cfftoken.h
@@ -4,7 +4,7 @@
/* */
/* CFF token definitions (specification only). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cff/module.mk b/thirdparty/freetype/src/cff/module.mk
index 2975aeed8c..8013d5dcab 100644
--- a/thirdparty/freetype/src/cff/module.mk
+++ b/thirdparty/freetype/src/cff/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2017 by
+# Copyright 1996-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/cff/rules.mk b/thirdparty/freetype/src/cff/rules.mk
index 86840bfe3c..bce672927e 100644
--- a/thirdparty/freetype/src/cff/rules.mk
+++ b/thirdparty/freetype/src/cff/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2017 by
+# Copyright 1996-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
@@ -32,27 +32,14 @@ CFF_DRV_SRC := $(CFF_DIR)/cffcmap.c \
$(CFF_DIR)/cffload.c \
$(CFF_DIR)/cffobjs.c \
$(CFF_DIR)/cffparse.c \
- $(CFF_DIR)/cffpic.c \
- $(CFF_DIR)/cf2arrst.c \
- $(CFF_DIR)/cf2blues.c \
- $(CFF_DIR)/cf2error.c \
- $(CFF_DIR)/cf2font.c \
- $(CFF_DIR)/cf2ft.c \
- $(CFF_DIR)/cf2hints.c \
- $(CFF_DIR)/cf2intrp.c \
- $(CFF_DIR)/cf2read.c \
- $(CFF_DIR)/cf2stack.c
+ $(CFF_DIR)/cffpic.c
# CFF driver headers
#
CFF_DRV_H := $(CFF_DRV_SRC:%.c=%.h) \
$(CFF_DIR)/cfferrs.h \
- $(CFF_DIR)/cfftoken.h \
- $(CFF_DIR)/cfftypes.h \
- $(CFF_DIR)/cf2fixed.h \
- $(CFF_DIR)/cf2glue.h \
- $(CFF_DIR)/cf2types.h
+ $(CFF_DIR)/cfftoken.h
# CFF driver object(s)
diff --git a/thirdparty/freetype/src/cid/ciderrs.h b/thirdparty/freetype/src/cid/ciderrs.h
index 709dc8cd1e..a5a86e3fc6 100644
--- a/thirdparty/freetype/src/cid/ciderrs.h
+++ b/thirdparty/freetype/src/cid/ciderrs.h
@@ -4,7 +4,7 @@
/* */
/* CID error codes (specification only). */
/* */
-/* Copyright 2001-2017 by */
+/* Copyright 2001-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cid/cidgload.c b/thirdparty/freetype/src/cid/cidgload.c
index b96c33334d..d14f9a2cc9 100644
--- a/thirdparty/freetype/src/cid/cidgload.c
+++ b/thirdparty/freetype/src/cid/cidgload.c
@@ -4,7 +4,7 @@
/* */
/* CID-keyed Type1 Glyph Loader (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -24,6 +24,10 @@
#include FT_OUTLINE_H
#include FT_INTERNAL_CALC_H
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+#include FT_INTERNAL_CFF_TYPES_H
+#include FT_DRIVER_H
+
#include "ciderrs.h"
@@ -52,9 +56,11 @@
FT_ULong glyph_length = 0;
PSAux_Service psaux = (PSAux_Service)face->psaux;
+ FT_Bool force_scaling = FALSE;
+
#ifdef FT_CONFIG_OPTION_INCREMENTAL
- FT_Incremental_InterfaceRec *inc =
- face->root.internal->incremental_interface;
+ FT_Incremental_InterfaceRec *inc =
+ face->root.internal->incremental_interface;
#endif
@@ -169,9 +175,57 @@
if ( decoder->lenIV >= 0 )
psaux->t1_decrypt( charstring, glyph_length, 4330 );
- error = decoder->funcs.parse_charstrings(
- decoder, charstring + cs_offset,
- glyph_length - cs_offset );
+ /* choose which renderer to use */
+#ifdef T1_CONFIG_OPTION_OLD_ENGINE
+ if ( ( (PS_Driver)FT_FACE_DRIVER( face ) )->hinting_engine ==
+ FT_HINTING_FREETYPE ||
+ decoder->builder.metrics_only )
+ error = psaux->t1_decoder_funcs->parse_charstrings_old(
+ decoder,
+ charstring + cs_offset,
+ glyph_length - cs_offset );
+#else
+ if ( decoder->builder.metrics_only )
+ error = psaux->t1_decoder_funcs->parse_metrics(
+ decoder,
+ charstring + cs_offset,
+ glyph_length - cs_offset );
+#endif
+ else
+ {
+ PS_Decoder psdecoder;
+ CFF_SubFontRec subfont;
+
+
+ psaux->ps_decoder_init( &psdecoder, decoder, TRUE );
+
+ psaux->t1_make_subfont( FT_FACE( face ),
+ &dict->private_dict,
+ &subfont );
+ psdecoder.current_subfont = &subfont;
+
+ error = psaux->t1_decoder_funcs->parse_charstrings(
+ &psdecoder,
+ charstring + cs_offset,
+ glyph_length - cs_offset );
+
+ /* Adobe's engine uses 16.16 numbers everywhere; */
+ /* as a consequence, glyphs larger than 2000ppem get rejected */
+ if ( FT_ERR_EQ( error, Glyph_Too_Big ) )
+ {
+ /* this time, we retry unhinted and scale up the glyph later on */
+ /* (the engine uses and sets the hardcoded value 0x10000 / 64 = */
+ /* 0x400 for both `x_scale' and `y_scale' in this case) */
+ ((CID_GlyphSlot)decoder->builder.glyph)->hint = FALSE;
+
+ force_scaling = TRUE;
+
+ error = psaux->t1_decoder_funcs->parse_charstrings(
+ &psdecoder,
+ charstring + cs_offset,
+ glyph_length - cs_offset );
+ }
+ }
}
#ifdef FT_CONFIG_OPTION_INCREMENTAL
@@ -200,6 +254,8 @@
Exit:
FT_FREE( charstring );
+ ((CID_GlyphSlot)decoder->builder.glyph)->scaled = force_scaling;
+
return error;
}
@@ -288,10 +344,12 @@
T1_DecoderRec decoder;
CID_Face face = (CID_Face)cidglyph->face;
FT_Bool hinting;
+ FT_Bool scaled;
PSAux_Service psaux = (PSAux_Service)face->psaux;
FT_Matrix font_matrix;
FT_Vector font_offset;
+ FT_Bool must_finish_decoder = FALSE;
if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
@@ -311,7 +369,10 @@
hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 &&
( load_flags & FT_LOAD_NO_HINTING ) == 0 );
+ scaled = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 );
+ glyph->hint = hinting;
+ glyph->scaled = scaled;
cidglyph->format = FT_GLYPH_FORMAT_OUTLINE;
error = psaux->t1_decoder_funcs->init( &decoder,
@@ -329,6 +390,8 @@
/* TODO: initialize decoder.len_buildchar and decoder.buildchar */
/* if we ever support CID-keyed multiple master fonts */
+ must_finish_decoder = TRUE;
+
/* set up the decoder */
decoder.builder.no_recurse = FT_BOOL(
( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 ) );
@@ -337,12 +400,18 @@
if ( error )
goto Exit;
+ /* copy flags back for forced scaling */
+ hinting = glyph->hint;
+ scaled = glyph->scaled;
+
font_matrix = decoder.font_matrix;
font_offset = decoder.font_offset;
/* save new glyph tables */
psaux->t1_decoder_funcs->done( &decoder );
+ must_finish_decoder = FALSE;
+
/* now set the metrics -- this is rather simple, as */
/* the left side bearing is the xMin, and the top side */
/* bearing the yMax */
@@ -410,7 +479,7 @@
metrics->vertAdvance += font_offset.y;
}
- if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
+ if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || scaled )
{
/* scale the outline and the metrics */
FT_Int n;
@@ -451,6 +520,10 @@
}
Exit:
+
+ if ( must_finish_decoder )
+ psaux->t1_decoder_funcs->done( &decoder );
+
return error;
}
diff --git a/thirdparty/freetype/src/cid/cidgload.h b/thirdparty/freetype/src/cid/cidgload.h
index 7f816b5bc7..4811852ae4 100644
--- a/thirdparty/freetype/src/cid/cidgload.h
+++ b/thirdparty/freetype/src/cid/cidgload.h
@@ -4,7 +4,7 @@
/* */
/* OpenType Glyph Loader (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cid/cidload.c b/thirdparty/freetype/src/cid/cidload.c
index ff0722110d..27cd09b3c3 100644
--- a/thirdparty/freetype/src/cid/cidload.c
+++ b/thirdparty/freetype/src/cid/cidload.c
@@ -4,7 +4,7 @@
/* */
/* CID-keyed Type1 font loader (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cid/cidload.h b/thirdparty/freetype/src/cid/cidload.h
index 45a0e6df25..3f8bd08620 100644
--- a/thirdparty/freetype/src/cid/cidload.h
+++ b/thirdparty/freetype/src/cid/cidload.h
@@ -4,7 +4,7 @@
/* */
/* CID-keyed Type1 font loader (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cid/cidobjs.c b/thirdparty/freetype/src/cid/cidobjs.c
index ceda8ff97f..77afe1c875 100644
--- a/thirdparty/freetype/src/cid/cidobjs.c
+++ b/thirdparty/freetype/src/cid/cidobjs.c
@@ -4,7 +4,7 @@
/* */
/* CID objects manager (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -26,6 +26,7 @@
#include FT_SERVICE_POSTSCRIPT_CMAPS_H
#include FT_INTERNAL_POSTSCRIPT_AUX_H
#include FT_INTERNAL_POSTSCRIPT_HINTS_H
+#include FT_DRIVER_H
#include "ciderrs.h"
@@ -463,9 +464,42 @@
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
- cid_driver_init( FT_Module driver )
+ cid_driver_init( FT_Module module )
{
- FT_UNUSED( driver );
+ PS_Driver driver = (PS_Driver)module;
+
+ FT_UInt32 seed;
+
+
+ /* set default property values, cf. `ftt1drv.h' */
+#ifdef T1_CONFIG_OPTION_OLD_ENGINE
+ driver->hinting_engine = FT_HINTING_FREETYPE;
+#else
+ driver->hinting_engine = FT_HINTING_ADOBE;
+#endif
+
+ driver->no_stem_darkening = TRUE;
+
+ driver->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1;
+ driver->darken_params[1] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1;
+ driver->darken_params[2] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2;
+ driver->darken_params[3] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2;
+ driver->darken_params[4] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3;
+ driver->darken_params[5] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3;
+ driver->darken_params[6] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4;
+ driver->darken_params[7] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4;
+
+ /* compute random seed from some memory addresses */
+ seed = (FT_UInt32)( (FT_Offset)(char*)&seed ^
+ (FT_Offset)(char*)&module ^
+ (FT_Offset)(char*)module->memory );
+ seed = seed ^ ( seed >> 10 ) ^ ( seed >> 20 );
+
+ driver->random_seed = (FT_Int32)seed;
+ if ( driver->random_seed < 0 )
+ driver->random_seed = -driver->random_seed;
+ else if ( driver->random_seed == 0 )
+ driver->random_seed = 123456789;
return FT_Err_Ok;
}
diff --git a/thirdparty/freetype/src/cid/cidobjs.h b/thirdparty/freetype/src/cid/cidobjs.h
index 8bcf886e10..0221f017dd 100644
--- a/thirdparty/freetype/src/cid/cidobjs.h
+++ b/thirdparty/freetype/src/cid/cidobjs.h
@@ -4,7 +4,7 @@
/* */
/* CID objects manager (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cid/cidparse.c b/thirdparty/freetype/src/cid/cidparse.c
index 007609bbdf..b1c7f3cb2c 100644
--- a/thirdparty/freetype/src/cid/cidparse.c
+++ b/thirdparty/freetype/src/cid/cidparse.c
@@ -4,7 +4,7 @@
/* */
/* CID-keyed Type1 parser (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cid/cidparse.h b/thirdparty/freetype/src/cid/cidparse.h
index 20bebb942b..61602f7674 100644
--- a/thirdparty/freetype/src/cid/cidparse.h
+++ b/thirdparty/freetype/src/cid/cidparse.h
@@ -4,7 +4,7 @@
/* */
/* CID-keyed Type1 parser (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cid/cidriver.c b/thirdparty/freetype/src/cid/cidriver.c
index bb611a961e..d9faf353ea 100644
--- a/thirdparty/freetype/src/cid/cidriver.c
+++ b/thirdparty/freetype/src/cid/cidriver.c
@@ -4,7 +4,7 @@
/* */
/* CID driver interface (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -20,6 +20,7 @@
#include "cidriver.h"
#include "cidgload.h"
#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_POSTSCRIPT_PROPS_H
#include "ciderrs.h"
@@ -27,6 +28,10 @@
#include FT_SERVICE_FONT_FORMAT_H
#include FT_SERVICE_POSTSCRIPT_INFO_H
#include FT_SERVICE_CID_H
+#include FT_SERVICE_PROPERTIES_H
+#include FT_DRIVER_H
+
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
/*************************************************************************/
@@ -168,6 +173,18 @@
/*
+ * PROPERTY SERVICE
+ *
+ */
+
+ FT_DEFINE_SERVICE_PROPERTIESREC(
+ cid_service_properties,
+
+ (FT_Properties_SetFunc)ps_property_set, /* set_property */
+ (FT_Properties_GetFunc)ps_property_get ) /* get_property */
+
+
+ /*
* SERVICE LIST
*
*/
@@ -178,6 +195,7 @@
{ FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cid_service_ps_name },
{ FT_SERVICE_ID_POSTSCRIPT_INFO, &cid_service_ps_info },
{ FT_SERVICE_ID_CID, &cid_service_cid_info },
+ { FT_SERVICE_ID_PROPERTIES, &cid_service_properties },
{ NULL, NULL }
};
@@ -200,7 +218,7 @@
FT_MODULE_FONT_DRIVER |
FT_MODULE_DRIVER_SCALABLE |
FT_MODULE_DRIVER_HAS_HINTER,
- sizeof ( FT_DriverRec ),
+ sizeof ( PS_DriverRec ),
"t1cid", /* module name */
0x10000L, /* version 1.0 of driver */
diff --git a/thirdparty/freetype/src/cid/cidriver.h b/thirdparty/freetype/src/cid/cidriver.h
index 76640c57ba..59d9ded901 100644
--- a/thirdparty/freetype/src/cid/cidriver.h
+++ b/thirdparty/freetype/src/cid/cidriver.h
@@ -4,7 +4,7 @@
/* */
/* High-level CID driver interface (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cid/cidtoken.h b/thirdparty/freetype/src/cid/cidtoken.h
index 653cc5586e..b0e2dac6aa 100644
--- a/thirdparty/freetype/src/cid/cidtoken.h
+++ b/thirdparty/freetype/src/cid/cidtoken.h
@@ -4,7 +4,7 @@
/* */
/* CID token definitions (specification only). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/cid/module.mk b/thirdparty/freetype/src/cid/module.mk
index b30b8679b9..9010e339a4 100644
--- a/thirdparty/freetype/src/cid/module.mk
+++ b/thirdparty/freetype/src/cid/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2017 by
+# Copyright 1996-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/cid/rules.mk b/thirdparty/freetype/src/cid/rules.mk
index fcddd92eca..94333bda06 100644
--- a/thirdparty/freetype/src/cid/rules.mk
+++ b/thirdparty/freetype/src/cid/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2017 by
+# Copyright 1996-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/cid/type1cid.c b/thirdparty/freetype/src/cid/type1cid.c
index 93e6f810db..61770e3f1e 100644
--- a/thirdparty/freetype/src/cid/type1cid.c
+++ b/thirdparty/freetype/src/cid/type1cid.c
@@ -4,7 +4,7 @@
/* */
/* FreeType OpenType driver component (body only). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/gxvalid/README b/thirdparty/freetype/src/gxvalid/README
index 200f66cb12..af8128e0e7 100644
--- a/thirdparty/freetype/src/gxvalid/README
+++ b/thirdparty/freetype/src/gxvalid/README
@@ -287,11 +287,11 @@ gxvalid: TrueType GX validator
4-5. invalid feature number (117/183)
-------------------------------------
- The GX/AAT extension can include 255 different layout features, but
- popular layout features are predefined (see
- http://developer.apple.com/fonts/Registry/index.html). Some fonts
- include feature numbers which are incompatible with the predefined
- feature registry.
+ The GX/AAT extension can include 255 different layout features,
+ but popular layout features are predefined (see
+ https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html).
+ Some fonts include feature numbers which are incompatible with the
+ predefined feature registry.
In our survey, there are 140 fonts including `feat' table.
@@ -518,7 +518,7 @@ gxvalid: TrueType GX validator
------------------------------------------------------------------------
-Copyright 2004-2017 by
+Copyright 2004-2018 by
suzuki toshiya, Masatake YAMATO, Red hat K.K.,
David Turner, Robert Wilhelm, and Werner Lemberg.
diff --git a/thirdparty/freetype/src/gxvalid/gxvalid.c b/thirdparty/freetype/src/gxvalid/gxvalid.c
index da485141d3..d0577a247e 100644
--- a/thirdparty/freetype/src/gxvalid/gxvalid.c
+++ b/thirdparty/freetype/src/gxvalid/gxvalid.c
@@ -4,7 +4,7 @@
/* */
/* FreeType validator for TrueTypeGX/AAT tables (body only). */
/* */
-/* Copyright 2005-2017 by */
+/* Copyright 2005-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxvalid.h b/thirdparty/freetype/src/gxvalid/gxvalid.h
index 78116ef85a..19f0379982 100644
--- a/thirdparty/freetype/src/gxvalid/gxvalid.h
+++ b/thirdparty/freetype/src/gxvalid/gxvalid.h
@@ -4,7 +4,7 @@
/* */
/* TrueTypeGX/AAT table validation (specification only). */
/* */
-/* Copyright 2005-2017 by */
+/* Copyright 2005-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxvbsln.c b/thirdparty/freetype/src/gxvalid/gxvbsln.c
index 81dff7304d..c367d38483 100644
--- a/thirdparty/freetype/src/gxvalid/gxvbsln.c
+++ b/thirdparty/freetype/src/gxvalid/gxvbsln.c
@@ -4,7 +4,7 @@
/* */
/* TrueTypeGX/AAT bsln table validation (body). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxvcommn.c b/thirdparty/freetype/src/gxvalid/gxvcommn.c
index db0a91ea74..b96601108b 100644
--- a/thirdparty/freetype/src/gxvalid/gxvcommn.c
+++ b/thirdparty/freetype/src/gxvalid/gxvcommn.c
@@ -4,7 +4,7 @@
/* */
/* TrueTypeGX/AAT common tables validation (body). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxvcommn.h b/thirdparty/freetype/src/gxvalid/gxvcommn.h
index 10b1c800f0..8e4ff9cafc 100644
--- a/thirdparty/freetype/src/gxvalid/gxvcommn.h
+++ b/thirdparty/freetype/src/gxvalid/gxvcommn.h
@@ -4,7 +4,7 @@
/* */
/* TrueTypeGX/AAT common tables validation (specification). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxverror.h b/thirdparty/freetype/src/gxvalid/gxverror.h
index 80a2b8a262..d1151258a9 100644
--- a/thirdparty/freetype/src/gxvalid/gxverror.h
+++ b/thirdparty/freetype/src/gxvalid/gxverror.h
@@ -4,7 +4,7 @@
/* */
/* TrueTypeGX/AAT validation module error codes (specification only). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxvfeat.c b/thirdparty/freetype/src/gxvalid/gxvfeat.c
index 2e3ec6f9be..2c805d1d11 100644
--- a/thirdparty/freetype/src/gxvalid/gxvfeat.c
+++ b/thirdparty/freetype/src/gxvalid/gxvfeat.c
@@ -4,7 +4,7 @@
/* */
/* TrueTypeGX/AAT feat table validation (body). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxvfeat.h b/thirdparty/freetype/src/gxvalid/gxvfeat.h
index 8c0e847eb7..2d943806c1 100644
--- a/thirdparty/freetype/src/gxvalid/gxvfeat.h
+++ b/thirdparty/freetype/src/gxvalid/gxvfeat.h
@@ -4,7 +4,7 @@
/* */
/* TrueTypeGX/AAT feat table validation (specification). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxvfgen.c b/thirdparty/freetype/src/gxvalid/gxvfgen.c
index 8cc08cd9c3..840c0f3524 100644
--- a/thirdparty/freetype/src/gxvalid/gxvfgen.c
+++ b/thirdparty/freetype/src/gxvalid/gxvfgen.c
@@ -5,7 +5,7 @@
/* Generate feature registry data for gxv `feat' validator. */
/* This program is derived from gxfeatreg.c in gxlayout. */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* Masatake YAMATO and Redhat K.K. */
/* */
/* This file may only be used, */
@@ -21,7 +21,7 @@
/* gxfeatreg.c */
/* */
/* Database of font features pre-defined by Apple Computer, Inc. */
-/* http://developer.apple.com/fonts/Registry/ */
+/* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html */
/* (body). */
/* */
/* Copyright 2003 by */
diff --git a/thirdparty/freetype/src/gxvalid/gxvjust.c b/thirdparty/freetype/src/gxvalid/gxvjust.c
index c8cfd83eac..00c4293195 100644
--- a/thirdparty/freetype/src/gxvalid/gxvjust.c
+++ b/thirdparty/freetype/src/gxvalid/gxvjust.c
@@ -4,7 +4,7 @@
/* */
/* TrueTypeGX/AAT just table validation (body). */
/* */
-/* Copyright 2005-2017 by */
+/* Copyright 2005-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxvkern.c b/thirdparty/freetype/src/gxvalid/gxvkern.c
index 9f9037387d..9c0efd7a4f 100644
--- a/thirdparty/freetype/src/gxvalid/gxvkern.c
+++ b/thirdparty/freetype/src/gxvalid/gxvkern.c
@@ -4,7 +4,7 @@
/* */
/* TrueTypeGX/AAT kern table validation (body). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxvlcar.c b/thirdparty/freetype/src/gxvalid/gxvlcar.c
index 775d5229f2..0f261a9ace 100644
--- a/thirdparty/freetype/src/gxvalid/gxvlcar.c
+++ b/thirdparty/freetype/src/gxvalid/gxvlcar.c
@@ -4,7 +4,7 @@
/* */
/* TrueTypeGX/AAT lcar table validation (body). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxvmod.c b/thirdparty/freetype/src/gxvalid/gxvmod.c
index 84e9275baf..1a3c862927 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmod.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmod.c
@@ -4,7 +4,7 @@
/* */
/* FreeType's TrueTypeGX/AAT validation module implementation (body). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxvmod.h b/thirdparty/freetype/src/gxvalid/gxvmod.h
index df25e60cb2..745c62e105 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmod.h
+++ b/thirdparty/freetype/src/gxvalid/gxvmod.h
@@ -5,7 +5,7 @@
/* FreeType's TrueTypeGX/AAT validation module implementation */
/* (specification). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxvmort.c b/thirdparty/freetype/src/gxvalid/gxvmort.c
index 184a6317c0..b361cb2b9d 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmort.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmort.c
@@ -4,7 +4,7 @@
/* */
/* TrueTypeGX/AAT mort table validation (body). */
/* */
-/* Copyright 2005-2017 by */
+/* Copyright 2005-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxvmort.h b/thirdparty/freetype/src/gxvalid/gxvmort.h
index d0543adcc5..d8030645e9 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmort.h
+++ b/thirdparty/freetype/src/gxvalid/gxvmort.h
@@ -4,7 +4,7 @@
/* */
/* TrueTypeGX/AAT common definition for mort table (specification). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxvmort0.c b/thirdparty/freetype/src/gxvalid/gxvmort0.c
index a75fad7768..95cf53d5eb 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmort0.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmort0.c
@@ -5,7 +5,7 @@
/* TrueTypeGX/AAT mort table validation */
/* body for type0 (Indic Script Rearrangement) subtable. */
/* */
-/* Copyright 2005-2017 by */
+/* Copyright 2005-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxvmort1.c b/thirdparty/freetype/src/gxvalid/gxvmort1.c
index 361ef2262d..a7683a17b0 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmort1.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmort1.c
@@ -5,7 +5,7 @@
/* TrueTypeGX/AAT mort table validation */
/* body for type1 (Contextual Substitution) subtable. */
/* */
-/* Copyright 2005-2017 by */
+/* Copyright 2005-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxvmort2.c b/thirdparty/freetype/src/gxvalid/gxvmort2.c
index c17e51e323..c23c2775a1 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmort2.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmort2.c
@@ -5,7 +5,7 @@
/* TrueTypeGX/AAT mort table validation */
/* body for type2 (Ligature Substitution) subtable. */
/* */
-/* Copyright 2005-2017 by */
+/* Copyright 2005-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxvmort4.c b/thirdparty/freetype/src/gxvalid/gxvmort4.c
index 041bab369f..9d21a5fc29 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmort4.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmort4.c
@@ -5,7 +5,7 @@
/* TrueTypeGX/AAT mort table validation */
/* body for type4 (Non-Contextual Glyph Substitution) subtable. */
/* */
-/* Copyright 2005-2017 by */
+/* Copyright 2005-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxvmort5.c b/thirdparty/freetype/src/gxvalid/gxvmort5.c
index 4751eceaa0..42cb428aa8 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmort5.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmort5.c
@@ -5,7 +5,7 @@
/* TrueTypeGX/AAT mort table validation */
/* body for type5 (Contextual Glyph Insertion) subtable. */
/* */
-/* Copyright 2005-2017 by */
+/* Copyright 2005-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx.c b/thirdparty/freetype/src/gxvalid/gxvmorx.c
index 2bb4f3b8b1..9fd6e6b971 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmorx.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmorx.c
@@ -4,7 +4,7 @@
/* */
/* TrueTypeGX/AAT morx table validation (body). */
/* */
-/* Copyright 2005-2017 by */
+/* Copyright 2005-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx.h b/thirdparty/freetype/src/gxvalid/gxvmorx.h
index 20cec58672..6d9925e92b 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmorx.h
+++ b/thirdparty/freetype/src/gxvalid/gxvmorx.h
@@ -4,7 +4,7 @@
/* */
/* TrueTypeGX/AAT common definition for morx table (specification). */
/* */
-/* Copyright 2005-2017 by */
+/* Copyright 2005-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx0.c b/thirdparty/freetype/src/gxvalid/gxvmorx0.c
index e0a0a92438..302261b7fa 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmorx0.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmorx0.c
@@ -5,7 +5,7 @@
/* TrueTypeGX/AAT morx table validation */
/* body for type0 (Indic Script Rearrangement) subtable. */
/* */
-/* Copyright 2005-2017 by */
+/* Copyright 2005-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx1.c b/thirdparty/freetype/src/gxvalid/gxvmorx1.c
index 9afebdbfa8..890ca74b1d 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmorx1.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmorx1.c
@@ -5,7 +5,7 @@
/* TrueTypeGX/AAT morx table validation */
/* body for type1 (Contextual Substitution) subtable. */
/* */
-/* Copyright 2005-2017 by */
+/* Copyright 2005-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx2.c b/thirdparty/freetype/src/gxvalid/gxvmorx2.c
index 3a60cf68a4..3135031d45 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmorx2.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmorx2.c
@@ -5,7 +5,7 @@
/* TrueTypeGX/AAT morx table validation */
/* body for type2 (Ligature Substitution) subtable. */
/* */
-/* Copyright 2005-2017 by */
+/* Copyright 2005-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx4.c b/thirdparty/freetype/src/gxvalid/gxvmorx4.c
index 29555685af..1e2397b0c5 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmorx4.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmorx4.c
@@ -5,7 +5,7 @@
/* TrueTypeGX/AAT morx table validation */
/* body for "morx" type4 (Non-Contextual Glyph Substitution) subtable. */
/* */
-/* Copyright 2005-2017 by */
+/* Copyright 2005-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx5.c b/thirdparty/freetype/src/gxvalid/gxvmorx5.c
index 05c11417ef..db4f9290c8 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmorx5.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmorx5.c
@@ -5,7 +5,7 @@
/* TrueTypeGX/AAT morx table validation */
/* body for type5 (Contextual Glyph Insertion) subtable. */
/* */
-/* Copyright 2005-2017 by */
+/* Copyright 2005-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxvopbd.c b/thirdparty/freetype/src/gxvalid/gxvopbd.c
index 11580d8b2a..e2c167ea59 100644
--- a/thirdparty/freetype/src/gxvalid/gxvopbd.c
+++ b/thirdparty/freetype/src/gxvalid/gxvopbd.c
@@ -4,7 +4,7 @@
/* */
/* TrueTypeGX/AAT opbd table validation (body). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxvprop.c b/thirdparty/freetype/src/gxvalid/gxvprop.c
index 7d398b7e66..a67b6bdd00 100644
--- a/thirdparty/freetype/src/gxvalid/gxvprop.c
+++ b/thirdparty/freetype/src/gxvalid/gxvprop.c
@@ -4,7 +4,7 @@
/* */
/* TrueTypeGX/AAT prop table validation (body). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/gxvtrak.c b/thirdparty/freetype/src/gxvalid/gxvtrak.c
index dd49825565..d501b5014b 100644
--- a/thirdparty/freetype/src/gxvalid/gxvtrak.c
+++ b/thirdparty/freetype/src/gxvalid/gxvtrak.c
@@ -4,7 +4,7 @@
/* */
/* TrueTypeGX/AAT trak table validation (body). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/thirdparty/freetype/src/gxvalid/module.mk b/thirdparty/freetype/src/gxvalid/module.mk
index 7f87e10812..b64879dcee 100644
--- a/thirdparty/freetype/src/gxvalid/module.mk
+++ b/thirdparty/freetype/src/gxvalid/module.mk
@@ -2,7 +2,7 @@
# FreeType 2 gxvalid module definition
#
-# Copyright 2004-2017 by
+# Copyright 2004-2018 by
# suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
diff --git a/thirdparty/freetype/src/gxvalid/rules.mk b/thirdparty/freetype/src/gxvalid/rules.mk
index 10ec08c5b0..3a17c030a6 100644
--- a/thirdparty/freetype/src/gxvalid/rules.mk
+++ b/thirdparty/freetype/src/gxvalid/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 2004-2017 by
+# Copyright 2004-2018 by
# suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
diff --git a/thirdparty/freetype/src/gzip/ftgzip.c b/thirdparty/freetype/src/gzip/ftgzip.c
index c487786d99..f8011c2dd8 100644
--- a/thirdparty/freetype/src/gzip/ftgzip.c
+++ b/thirdparty/freetype/src/gzip/ftgzip.c
@@ -8,7 +8,7 @@
/* parse compressed PCF fonts, as found with many X11 server */
/* distributions. */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/gzip/rules.mk b/thirdparty/freetype/src/gzip/rules.mk
index bc7d5fa631..1a2e48bebd 100644
--- a/thirdparty/freetype/src/gzip/rules.mk
+++ b/thirdparty/freetype/src/gzip/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 2002-2017 by
+# Copyright 2002-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/lzw/ftlzw.c b/thirdparty/freetype/src/lzw/ftlzw.c
index 941f6cef4c..cb46f93c68 100644
--- a/thirdparty/freetype/src/lzw/ftlzw.c
+++ b/thirdparty/freetype/src/lzw/ftlzw.c
@@ -8,7 +8,7 @@
/* be used to parse compressed PCF fonts, as found with many X11 server */
/* distributions. */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* Albert Chin-A-Young. */
/* */
/* based on code in `src/gzip/ftgzip.c' */
diff --git a/thirdparty/freetype/src/lzw/ftzopen.c b/thirdparty/freetype/src/lzw/ftzopen.c
index 486c546c14..2b868ba9f2 100644
--- a/thirdparty/freetype/src/lzw/ftzopen.c
+++ b/thirdparty/freetype/src/lzw/ftzopen.c
@@ -8,7 +8,7 @@
/* be used to parse compressed PCF fonts, as found with many X11 server */
/* distributions. */
/* */
-/* Copyright 2005-2017 by */
+/* Copyright 2005-2018 by */
/* David Turner. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/lzw/ftzopen.h b/thirdparty/freetype/src/lzw/ftzopen.h
index a108862c0a..4fd267eb90 100644
--- a/thirdparty/freetype/src/lzw/ftzopen.h
+++ b/thirdparty/freetype/src/lzw/ftzopen.h
@@ -8,7 +8,7 @@
/* be used to parse compressed PCF fonts, as found with many X11 server */
/* distributions. */
/* */
-/* Copyright 2005-2017 by */
+/* Copyright 2005-2018 by */
/* David Turner. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/lzw/rules.mk b/thirdparty/freetype/src/lzw/rules.mk
index e7bf68a065..18933c41c2 100644
--- a/thirdparty/freetype/src/lzw/rules.mk
+++ b/thirdparty/freetype/src/lzw/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 2004-2017 by
+# Copyright 2004-2018 by
# Albert Chin-A-Young.
#
# based on `src/lzw/rules.mk'
diff --git a/thirdparty/freetype/src/otvalid/module.mk b/thirdparty/freetype/src/otvalid/module.mk
index 5ee1265db8..34f3dab32f 100644
--- a/thirdparty/freetype/src/otvalid/module.mk
+++ b/thirdparty/freetype/src/otvalid/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 2004-2017 by
+# Copyright 2004-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/otvalid/otvalid.c b/thirdparty/freetype/src/otvalid/otvalid.c
index 312751a1f4..4423ca1012 100644
--- a/thirdparty/freetype/src/otvalid/otvalid.c
+++ b/thirdparty/freetype/src/otvalid/otvalid.c
@@ -4,7 +4,7 @@
/* */
/* FreeType validator for OpenType tables (body only). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/otvalid/otvalid.h b/thirdparty/freetype/src/otvalid/otvalid.h
index f2969ccccc..d7801abae5 100644
--- a/thirdparty/freetype/src/otvalid/otvalid.h
+++ b/thirdparty/freetype/src/otvalid/otvalid.h
@@ -4,7 +4,7 @@
/* */
/* OpenType table validation (specification only). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/otvalid/otvbase.c b/thirdparty/freetype/src/otvalid/otvbase.c
index 3adad8439c..a01d45c707 100644
--- a/thirdparty/freetype/src/otvalid/otvbase.c
+++ b/thirdparty/freetype/src/otvalid/otvbase.c
@@ -4,7 +4,7 @@
/* */
/* OpenType BASE table validation (body). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -284,22 +284,41 @@
OTV_Validator otvalid = &otvalidrec;
FT_Bytes p = table;
FT_UInt table_size;
+ FT_UShort version;
OTV_OPTIONAL_TABLE( HorizAxis );
OTV_OPTIONAL_TABLE( VertAxis );
+ OTV_OPTIONAL_TABLE32( itemVarStore );
+
otvalid->root = ftvalid;
FT_TRACE3(( "validating BASE table\n" ));
OTV_INIT;
- OTV_LIMIT_CHECK( 6 );
+ OTV_LIMIT_CHECK( 4 );
- if ( FT_NEXT_ULONG( p ) != 0x10000UL ) /* Version */
+ if ( FT_NEXT_USHORT( p ) != 1 ) /* majorVersion */
FT_INVALID_FORMAT;
- table_size = 6;
+ version = FT_NEXT_USHORT( p ); /* minorVersion */
+
+ table_size = 8;
+ switch ( version )
+ {
+ case 0:
+ OTV_LIMIT_CHECK( 4 );
+ break;
+
+ case 1:
+ OTV_LIMIT_CHECK( 8 );
+ table_size += 4;
+ break;
+
+ default:
+ FT_INVALID_FORMAT;
+ }
OTV_OPTIONAL_OFFSET( HorizAxis );
OTV_SIZE_CHECK( HorizAxis );
@@ -311,6 +330,14 @@
if ( VertAxis )
otv_Axis_validate( table + VertAxis, otvalid );
+ if ( version > 0 )
+ {
+ OTV_OPTIONAL_OFFSET32( itemVarStore );
+ OTV_SIZE_CHECK32( itemVarStore );
+ if ( itemVarStore )
+ OTV_TRACE(( " [omitting itemVarStore validation]\n" )); /* XXX */
+ }
+
FT_TRACE4(( "\n" ));
}
diff --git a/thirdparty/freetype/src/otvalid/otvcommn.c b/thirdparty/freetype/src/otvalid/otvcommn.c
index 3407d2ad4a..0ccfb03c08 100644
--- a/thirdparty/freetype/src/otvalid/otvcommn.c
+++ b/thirdparty/freetype/src/otvalid/otvcommn.c
@@ -4,7 +4,7 @@
/* */
/* OpenType common tables validation (body). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -313,19 +313,26 @@
OTV_NAME_ENTER( "Device" );
- OTV_LIMIT_CHECK( 8 );
+ OTV_LIMIT_CHECK( 6 );
StartSize = FT_NEXT_USHORT( p );
EndSize = FT_NEXT_USHORT( p );
DeltaFormat = FT_NEXT_USHORT( p );
- if ( DeltaFormat < 1 || DeltaFormat > 3 )
- FT_INVALID_FORMAT;
+ if ( DeltaFormat == 0x8000U )
+ {
+ /* VariationIndex, nothing to do */
+ }
+ else
+ {
+ if ( DeltaFormat < 1 || DeltaFormat > 3 )
+ FT_INVALID_FORMAT;
- if ( EndSize < StartSize )
- FT_INVALID_DATA;
+ if ( EndSize < StartSize )
+ FT_INVALID_DATA;
- count = EndSize - StartSize + 1;
- OTV_LIMIT_CHECK( ( 1 << DeltaFormat ) * count / 8 ); /* DeltaValue */
+ count = EndSize - StartSize + 1;
+ OTV_LIMIT_CHECK( ( 1 << DeltaFormat ) * count / 8 ); /* DeltaValue */
+ }
OTV_EXIT;
}
@@ -347,7 +354,7 @@
OTV_Validator otvalid )
{
FT_Bytes p = table;
- FT_UInt LookupType, SubTableCount;
+ FT_UInt LookupType, LookupFlag, SubTableCount;
OTV_Validate_Func validate;
@@ -355,7 +362,7 @@
OTV_LIMIT_CHECK( 6 );
LookupType = FT_NEXT_USHORT( p );
- p += 2; /* skip LookupFlag */
+ LookupFlag = FT_NEXT_USHORT( p );
SubTableCount = FT_NEXT_USHORT( p );
OTV_TRACE(( " (type %d)\n", LookupType ));
@@ -373,6 +380,9 @@
for ( ; SubTableCount > 0; SubTableCount-- )
validate( table + FT_NEXT_USHORT( p ), otvalid );
+ if ( LookupFlag & 0x10 )
+ OTV_LIMIT_CHECK( 2 ); /* MarkFilteringSet */
+
OTV_EXIT;
}
diff --git a/thirdparty/freetype/src/otvalid/otvcommn.h b/thirdparty/freetype/src/otvalid/otvcommn.h
index 10a603ebb9..a392784cf1 100644
--- a/thirdparty/freetype/src/otvalid/otvcommn.h
+++ b/thirdparty/freetype/src/otvalid/otvcommn.h
@@ -4,7 +4,7 @@
/* */
/* OpenType common tables validation (specification). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -67,29 +67,38 @@ FT_BEGIN_HEADER
#undef FT_INVALID_
-#define FT_INVALID_( _error ) \
+#define FT_INVALID_( _error ) \
ft_validator_error( otvalid->root, FT_THROW( _error ) )
#define OTV_OPTIONAL_TABLE( _table ) FT_UShort _table; \
FT_Bytes _table ## _p
+#define OTV_OPTIONAL_TABLE32( _table ) FT_ULong _table; \
+ FT_Bytes _table ## _p
+
#define OTV_OPTIONAL_OFFSET( _offset ) \
FT_BEGIN_STMNT \
_offset ## _p = p; \
_offset = FT_NEXT_USHORT( p ); \
FT_END_STMNT
-#define OTV_LIMIT_CHECK( _count ) \
- FT_BEGIN_STMNT \
+#define OTV_OPTIONAL_OFFSET32( _offset ) \
+ FT_BEGIN_STMNT \
+ _offset ## _p = p; \
+ _offset = FT_NEXT_ULONG( p ); \
+ FT_END_STMNT
+
+#define OTV_LIMIT_CHECK( _count ) \
+ FT_BEGIN_STMNT \
if ( p + (_count) > otvalid->root->limit ) \
- FT_INVALID_TOO_SHORT; \
+ FT_INVALID_TOO_SHORT; \
FT_END_STMNT
#define OTV_SIZE_CHECK( _size ) \
FT_BEGIN_STMNT \
if ( _size > 0 && _size < table_size ) \
{ \
- if ( otvalid->root->level == FT_VALIDATE_PARANOID ) \
+ if ( otvalid->root->level == FT_VALIDATE_PARANOID ) \
FT_INVALID_OFFSET; \
else \
{ \
@@ -102,12 +111,33 @@ FT_BEGIN_HEADER
" set to zero.\n" \
"\n", #_size )); \
\
- /* always assume 16bit entities */ \
_size = pp[0] = pp[1] = 0; \
} \
} \
FT_END_STMNT
+#define OTV_SIZE_CHECK32( _size ) \
+ FT_BEGIN_STMNT \
+ if ( _size > 0 && _size < table_size ) \
+ { \
+ if ( otvalid->root->level == FT_VALIDATE_PARANOID ) \
+ FT_INVALID_OFFSET; \
+ else \
+ { \
+ /* strip off `const' */ \
+ FT_Byte* pp = (FT_Byte*)_size ## _p; \
+ \
+ \
+ FT_TRACE3(( "\n" \
+ "Invalid offset to optional table `%s'" \
+ " set to zero.\n" \
+ "\n", #_size )); \
+ \
+ _size = pp[0] = pp[1] = pp[2] = pp[3] = 0; \
+ } \
+ } \
+ FT_END_STMNT
+
#define OTV_NAME_(x) #x
#define OTV_NAME(x) OTV_NAME_(x)
@@ -146,11 +176,11 @@ FT_BEGIN_HEADER
#define OTV_INIT otvalid->debug_indent = 0
-#define OTV_ENTER \
- FT_BEGIN_STMNT \
- otvalid->debug_indent += 2; \
- FT_TRACE4(( "%*.s", otvalid->debug_indent, 0 )); \
- FT_TRACE4(( "%s table\n", \
+#define OTV_ENTER \
+ FT_BEGIN_STMNT \
+ otvalid->debug_indent += 2; \
+ FT_TRACE4(( "%*.s", otvalid->debug_indent, 0 )); \
+ FT_TRACE4(( "%s table\n", \
otvalid->debug_function_name[otvalid->nesting_level] )); \
FT_END_STMNT
diff --git a/thirdparty/freetype/src/otvalid/otverror.h b/thirdparty/freetype/src/otvalid/otverror.h
index 699903987c..2fcf42e387 100644
--- a/thirdparty/freetype/src/otvalid/otverror.h
+++ b/thirdparty/freetype/src/otvalid/otverror.h
@@ -4,7 +4,7 @@
/* */
/* OpenType validation module error codes (specification only). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/otvalid/otvgdef.c b/thirdparty/freetype/src/otvalid/otvgdef.c
index 27b9a69ca8..08f3171541 100644
--- a/thirdparty/freetype/src/otvalid/otvgdef.c
+++ b/thirdparty/freetype/src/otvalid/otvgdef.c
@@ -4,7 +4,7 @@
/* */
/* OpenType GDEF table validation (body). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -68,7 +68,7 @@
OTV_LIMIT_CHECK( GlyphCount * 2 );
otvalid->nesting_level++;
- func = otvalid->func[otvalid->nesting_level];
+ func = otvalid->func[otvalid->nesting_level];
otvalid->extra1 = 0;
for ( ; GlyphCount > 0; GlyphCount-- )
@@ -136,6 +136,40 @@
/*************************************************************************/
/*************************************************************************/
/***** *****/
+ /***** MARK GLYPH SETS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static void
+ otv_MarkGlyphSets_validate( FT_Bytes table,
+ OTV_Validator otvalid )
+ {
+ FT_Bytes p = table;
+ FT_UInt MarkGlyphSetCount;
+
+
+ OTV_NAME_ENTER( "MarkGlyphSets" );
+
+ p += 2; /* skip Format */
+
+ OTV_LIMIT_CHECK( 2 );
+ MarkGlyphSetCount = FT_NEXT_USHORT( p );
+
+ OTV_TRACE(( " (MarkGlyphSetCount = %d)\n", MarkGlyphSetCount ));
+
+ OTV_LIMIT_CHECK( MarkGlyphSetCount * 4 ); /* CoverageOffsets */
+
+ for ( ; MarkGlyphSetCount > 0; MarkGlyphSetCount-- )
+ otv_Coverage_validate( table + FT_NEXT_ULONG( p ), otvalid, -1 );
+
+ OTV_EXIT;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
/***** GDEF TABLE *****/
/***** *****/
/*************************************************************************/
@@ -152,14 +186,18 @@
{
OTV_ValidatorRec otvalidrec;
OTV_Validator otvalid = &otvalidrec;
- FT_Bytes p = table;
+ FT_Bytes p = table;
FT_UInt table_size;
- FT_Bool need_MarkAttachClassDef;
+ FT_UShort version;
+ FT_Bool need_MarkAttachClassDef = 1;
OTV_OPTIONAL_TABLE( GlyphClassDef );
OTV_OPTIONAL_TABLE( AttachListOffset );
OTV_OPTIONAL_TABLE( LigCaretListOffset );
OTV_OPTIONAL_TABLE( MarkAttachClassDef );
+ OTV_OPTIONAL_TABLE( MarkGlyphSetsDef );
+
+ OTV_OPTIONAL_TABLE32( itemVarStore );
otvalid->root = ftvalid;
@@ -167,24 +205,49 @@
FT_TRACE3(( "validating GDEF table\n" ));
OTV_INIT;
- OTV_LIMIT_CHECK( 12 );
+ OTV_LIMIT_CHECK( 4 );
- if ( FT_NEXT_ULONG( p ) != 0x10000UL ) /* Version */
+ if ( FT_NEXT_USHORT( p ) != 1 ) /* majorVersion */
FT_INVALID_FORMAT;
- /* MarkAttachClassDef has been added to the OpenType */
- /* specification without increasing GDEF's version, */
- /* so we use this ugly hack to find out whether the */
- /* table is needed actually. */
+ version = FT_NEXT_USHORT( p ); /* minorVersion */
- need_MarkAttachClassDef = FT_BOOL(
- otv_GSUBGPOS_have_MarkAttachmentType_flag( gsub ) ||
- otv_GSUBGPOS_have_MarkAttachmentType_flag( gpos ) );
+ table_size = 10;
+ switch ( version )
+ {
+ case 0:
+ /* MarkAttachClassDef has been added to the OpenType */
+ /* specification without increasing GDEF's version, */
+ /* so we use this ugly hack to find out whether the */
+ /* table is needed actually. */
+
+ need_MarkAttachClassDef = FT_BOOL(
+ otv_GSUBGPOS_have_MarkAttachmentType_flag( gsub ) ||
+ otv_GSUBGPOS_have_MarkAttachmentType_flag( gpos ) );
+
+ if ( need_MarkAttachClassDef )
+ {
+ OTV_LIMIT_CHECK( 8 );
+ table_size += 2;
+ }
+ else
+ OTV_LIMIT_CHECK( 6 ); /* OpenType < 1.2 */
- if ( need_MarkAttachClassDef )
- table_size = 12; /* OpenType >= 1.2 */
- else
- table_size = 10; /* OpenType < 1.2 */
+ break;
+
+ case 2:
+ OTV_LIMIT_CHECK( 10 );
+ table_size += 4;
+ break;
+
+ case 3:
+ OTV_LIMIT_CHECK( 14 );
+ table_size += 8;
+ break;
+
+ default:
+ FT_INVALID_FORMAT;
+ }
otvalid->glyph_count = glyph_count;
@@ -217,6 +280,22 @@
otv_ClassDef_validate( table + MarkAttachClassDef, otvalid );
}
+ if ( version > 0 )
+ {
+ OTV_OPTIONAL_OFFSET( MarkGlyphSetsDef );
+ OTV_SIZE_CHECK( MarkGlyphSetsDef );
+ if ( MarkGlyphSetsDef )
+ otv_MarkGlyphSets_validate( table + MarkGlyphSetsDef, otvalid );
+ }
+
+ if ( version > 2 )
+ {
+ OTV_OPTIONAL_OFFSET32( itemVarStore );
+ OTV_SIZE_CHECK32( itemVarStore );
+ if ( itemVarStore )
+ OTV_TRACE(( " [omitting itemVarStore validation]\n" )); /* XXX */
+ }
+
FT_TRACE4(( "\n" ));
}
diff --git a/thirdparty/freetype/src/otvalid/otvgpos.c b/thirdparty/freetype/src/otvalid/otvgpos.c
index 0fbcc2077c..696b35cae6 100644
--- a/thirdparty/freetype/src/otvalid/otvgpos.c
+++ b/thirdparty/freetype/src/otvalid/otvgpos.c
@@ -4,7 +4,7 @@
/* */
/* OpenType GPOS table validation (body). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -130,7 +130,7 @@
otv_MarkArray_validate( table + Array1, otvalid );
otvalid->nesting_level++;
- func = otvalid->func[otvalid->nesting_level];
+ func = otvalid->func[otvalid->nesting_level];
otvalid->extra1 = ClassCount;
func( table + Array2, otvalid );
@@ -218,10 +218,6 @@
OTV_LIMIT_CHECK( 2 );
OTV_OPTIONAL_OFFSET( device );
- /* XXX: this value is usually too small, especially if the current */
- /* ValueRecord is part of an array -- getting the correct table */
- /* size is probably not worth the trouble */
-
table_size = p - otvalid->extra3;
OTV_SIZE_CHECK( device );
@@ -271,7 +267,7 @@
case 3:
{
- FT_UInt table_size;
+ FT_UInt table_size;
OTV_OPTIONAL_TABLE( XDeviceTable );
OTV_OPTIONAL_TABLE( YDeviceTable );
@@ -426,6 +422,8 @@
/*************************************************************************/
/*************************************************************************/
+ /* sets otvalid->extra3 (pointer to base table) */
+
static void
otv_PairSet_validate( FT_Bytes table,
FT_UInt format1,
@@ -438,6 +436,8 @@
OTV_NAME_ENTER( "PairSet" );
+ otvalid->extra3 = table;
+
OTV_LIMIT_CHECK( 2 );
PairValueCount = FT_NEXT_USHORT( p );
@@ -483,8 +483,6 @@
OTV_TRACE(( " (format %d)\n", PosFormat ));
- otvalid->extra3 = table;
-
switch ( PosFormat )
{
case 1: /* PairPosFormat1 */
@@ -537,7 +535,9 @@
otv_ClassDef_validate( table + ClassDef2, otvalid );
OTV_LIMIT_CHECK( ClassCount1 * ClassCount2 *
- ( len_value1 + len_value2 ) );
+ ( len_value1 + len_value2 ) );
+
+ otvalid->extra3 = table;
/* Class1Record */
for ( ; ClassCount1 > 0; ClassCount1-- )
@@ -985,20 +985,42 @@
{
OTV_ValidatorRec validrec;
OTV_Validator otvalid = &validrec;
- FT_Bytes p = table;
+ FT_Bytes p = table;
+ FT_UInt table_size;
+ FT_UShort version;
FT_UInt ScriptList, FeatureList, LookupList;
+ OTV_OPTIONAL_TABLE32( featureVariations );
+
otvalid->root = ftvalid;
FT_TRACE3(( "validating GPOS table\n" ));
OTV_INIT;
- OTV_LIMIT_CHECK( 10 );
+ OTV_LIMIT_CHECK( 4 );
- if ( FT_NEXT_ULONG( p ) != 0x10000UL ) /* Version */
+ if ( FT_NEXT_USHORT( p ) != 1 ) /* majorVersion */
FT_INVALID_FORMAT;
+ version = FT_NEXT_USHORT( p ); /* minorVersion */
+
+ table_size = 10;
+ switch ( version )
+ {
+ case 0:
+ OTV_LIMIT_CHECK( 6 );
+ break;
+
+ case 1:
+ OTV_LIMIT_CHECK( 10 );
+ table_size += 4;
+ break;
+
+ default:
+ FT_INVALID_FORMAT;
+ }
+
ScriptList = FT_NEXT_USHORT( p );
FeatureList = FT_NEXT_USHORT( p );
LookupList = FT_NEXT_USHORT( p );
@@ -1014,6 +1036,14 @@
otv_ScriptList_validate( table + ScriptList, table + FeatureList,
otvalid );
+ if ( version > 0 )
+ {
+ OTV_OPTIONAL_OFFSET32( featureVariations );
+ OTV_SIZE_CHECK32( featureVariations );
+ if ( featureVariations )
+ OTV_TRACE(( " [omitting featureVariations validation]\n" )); /* XXX */
+ }
+
FT_TRACE4(( "\n" ));
}
diff --git a/thirdparty/freetype/src/otvalid/otvgpos.h b/thirdparty/freetype/src/otvalid/otvgpos.h
index 99b0ad3915..95f9ac3ee8 100644
--- a/thirdparty/freetype/src/otvalid/otvgpos.h
+++ b/thirdparty/freetype/src/otvalid/otvgpos.h
@@ -4,7 +4,7 @@
/* */
/* OpenType GPOS table validator (specification). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/otvalid/otvgsub.c b/thirdparty/freetype/src/otvalid/otvgsub.c
index f9bd8dc5d8..d35ea67f30 100644
--- a/thirdparty/freetype/src/otvalid/otvgsub.c
+++ b/thirdparty/freetype/src/otvalid/otvgsub.c
@@ -4,7 +4,7 @@
/* */
/* OpenType GSUB table validation (body). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -552,18 +552,40 @@
OTV_ValidatorRec otvalidrec;
OTV_Validator otvalid = &otvalidrec;
FT_Bytes p = table;
+ FT_UInt table_size;
+ FT_UShort version;
FT_UInt ScriptList, FeatureList, LookupList;
+ OTV_OPTIONAL_TABLE32( featureVariations );
+
otvalid->root = ftvalid;
FT_TRACE3(( "validating GSUB table\n" ));
OTV_INIT;
- OTV_LIMIT_CHECK( 10 );
+ OTV_LIMIT_CHECK( 4 );
+
+ if ( FT_NEXT_USHORT( p ) != 1 ) /* majorVersion */
+ FT_INVALID_FORMAT;
+
+ version = FT_NEXT_USHORT( p ); /* minorVersion */
+
+ table_size = 10;
+ switch ( version )
+ {
+ case 0:
+ OTV_LIMIT_CHECK( 6 );
+ break;
+
+ case 1:
+ OTV_LIMIT_CHECK( 10 );
+ table_size += 4;
+ break;
- if ( FT_NEXT_ULONG( p ) != 0x10000UL ) /* Version */
+ default:
FT_INVALID_FORMAT;
+ }
ScriptList = FT_NEXT_USHORT( p );
FeatureList = FT_NEXT_USHORT( p );
@@ -580,6 +602,14 @@
otv_ScriptList_validate( table + ScriptList, table + FeatureList,
otvalid );
+ if ( version > 0 )
+ {
+ OTV_OPTIONAL_OFFSET32( featureVariations );
+ OTV_SIZE_CHECK32( featureVariations );
+ if ( featureVariations )
+ OTV_TRACE(( " [omitting featureVariations validation]\n" )); /* XXX */
+ }
+
FT_TRACE4(( "\n" ));
}
diff --git a/thirdparty/freetype/src/otvalid/otvjstf.c b/thirdparty/freetype/src/otvalid/otvjstf.c
index 57a38f95c9..94d4af90f6 100644
--- a/thirdparty/freetype/src/otvalid/otvjstf.c
+++ b/thirdparty/freetype/src/otvalid/otvjstf.c
@@ -4,7 +4,7 @@
/* */
/* OpenType JSTF table validation (body). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/otvalid/otvmath.c b/thirdparty/freetype/src/otvalid/otvmath.c
index a14d369700..b9800f60a2 100644
--- a/thirdparty/freetype/src/otvalid/otvmath.c
+++ b/thirdparty/freetype/src/otvalid/otvmath.c
@@ -4,7 +4,7 @@
/* */
/* OpenType MATH table validation (body). */
/* */
-/* Copyright 2007-2017 by */
+/* Copyright 2007-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* Written by George Williams. */
diff --git a/thirdparty/freetype/src/otvalid/otvmod.c b/thirdparty/freetype/src/otvalid/otvmod.c
index 35ffc43d3a..89ee449d16 100644
--- a/thirdparty/freetype/src/otvalid/otvmod.c
+++ b/thirdparty/freetype/src/otvalid/otvmod.c
@@ -4,7 +4,7 @@
/* */
/* FreeType's OpenType validation module implementation (body). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/otvalid/otvmod.h b/thirdparty/freetype/src/otvalid/otvmod.h
index 30d401ddca..6917bccee5 100644
--- a/thirdparty/freetype/src/otvalid/otvmod.h
+++ b/thirdparty/freetype/src/otvalid/otvmod.h
@@ -5,7 +5,7 @@
/* FreeType's OpenType validation module implementation */
/* (specification). */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/otvalid/rules.mk b/thirdparty/freetype/src/otvalid/rules.mk
index 10329a96ea..d4fc723740 100644
--- a/thirdparty/freetype/src/otvalid/rules.mk
+++ b/thirdparty/freetype/src/otvalid/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 2004-2017 by
+# Copyright 2004-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/pcf/pcfdrivr.c b/thirdparty/freetype/src/pcf/pcfdrivr.c
index 169f75e950..0119d94853 100644
--- a/thirdparty/freetype/src/pcf/pcfdrivr.c
+++ b/thirdparty/freetype/src/pcf/pcfdrivr.c
@@ -50,7 +50,7 @@ THE SOFTWARE.
#include FT_SERVICE_BDF_H
#include FT_SERVICE_FONT_FORMAT_H
#include FT_SERVICE_PROPERTIES_H
-#include FT_PCF_DRIVER_H
+#include FT_DRIVER_H
/*************************************************************************/
diff --git a/thirdparty/freetype/src/pcf/pcfread.c b/thirdparty/freetype/src/pcf/pcfread.c
index da216b05f4..537da0dc79 100644
--- a/thirdparty/freetype/src/pcf/pcfread.c
+++ b/thirdparty/freetype/src/pcf/pcfread.c
@@ -840,7 +840,7 @@ THE SOFTWARE.
FT_TRACE4(( "pcf_get_bitmaps:\n"
" format: 0x%lX\n"
" (%s, %s,\n"
- " padding=%d bits, scanning=%d bits)\n",
+ " padding=%d bit%s, scanning=%d bit%s)\n",
format,
PCF_BYTE_ORDER( format ) == MSBFirst
? "most significant byte first"
@@ -849,7 +849,9 @@ THE SOFTWARE.
? "most significant bit first"
: "least significant bit first",
8 << PCF_GLYPH_PAD_INDEX( format ),
- 8 << PCF_SCAN_UNIT_INDEX( format ) ));
+ ( 8 << PCF_GLYPH_PAD_INDEX( format ) ) == 1 ? "" : "s",
+ 8 << PCF_SCAN_UNIT_INDEX( format ),
+ ( 8 << PCF_SCAN_UNIT_INDEX( format ) ) == 1 ? "" : "s" ));
if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
return FT_THROW( Invalid_File_Format );
diff --git a/thirdparty/freetype/src/pfr/module.mk b/thirdparty/freetype/src/pfr/module.mk
index 7b84da9708..27fec8e5f6 100644
--- a/thirdparty/freetype/src/pfr/module.mk
+++ b/thirdparty/freetype/src/pfr/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 2002-2017 by
+# Copyright 2002-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/pfr/pfr.c b/thirdparty/freetype/src/pfr/pfr.c
index 4f31f5d9bc..1760882fcd 100644
--- a/thirdparty/freetype/src/pfr/pfr.c
+++ b/thirdparty/freetype/src/pfr/pfr.c
@@ -4,7 +4,7 @@
/* */
/* FreeType PFR driver component. */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/pfr/pfrcmap.c b/thirdparty/freetype/src/pfr/pfrcmap.c
index 1d6b15be48..60643780a1 100644
--- a/thirdparty/freetype/src/pfr/pfrcmap.c
+++ b/thirdparty/freetype/src/pfr/pfrcmap.c
@@ -4,7 +4,7 @@
/* */
/* FreeType PFR cmap handling (body). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/pfr/pfrcmap.h b/thirdparty/freetype/src/pfr/pfrcmap.h
index 957bf65b4c..c70a0c83c5 100644
--- a/thirdparty/freetype/src/pfr/pfrcmap.h
+++ b/thirdparty/freetype/src/pfr/pfrcmap.h
@@ -4,7 +4,7 @@
/* */
/* FreeType PFR cmap handling (specification). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/pfr/pfrdrivr.c b/thirdparty/freetype/src/pfr/pfrdrivr.c
index 195cdb76ac..6c7e50128a 100644
--- a/thirdparty/freetype/src/pfr/pfrdrivr.c
+++ b/thirdparty/freetype/src/pfr/pfrdrivr.c
@@ -4,7 +4,7 @@
/* */
/* FreeType PFR driver interface (body). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/pfr/pfrdrivr.h b/thirdparty/freetype/src/pfr/pfrdrivr.h
index b81d56017e..cab852789b 100644
--- a/thirdparty/freetype/src/pfr/pfrdrivr.h
+++ b/thirdparty/freetype/src/pfr/pfrdrivr.h
@@ -4,7 +4,7 @@
/* */
/* High-level Type PFR driver interface (specification). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/pfr/pfrerror.h b/thirdparty/freetype/src/pfr/pfrerror.h
index ef044e32c9..7027c818e8 100644
--- a/thirdparty/freetype/src/pfr/pfrerror.h
+++ b/thirdparty/freetype/src/pfr/pfrerror.h
@@ -4,7 +4,7 @@
/* */
/* PFR error codes (specification only). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/pfr/pfrgload.c b/thirdparty/freetype/src/pfr/pfrgload.c
index 93f5fc7090..b7990196b6 100644
--- a/thirdparty/freetype/src/pfr/pfrgload.c
+++ b/thirdparty/freetype/src/pfr/pfrgload.c
@@ -4,7 +4,7 @@
/* */
/* FreeType PFR glyph loader (body). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -756,8 +756,10 @@
count = glyph->num_subs - old_count;
- FT_TRACE4(( "compound glyph with %d elements (offset %lu):\n",
- count, offset ));
+ FT_TRACE4(( "compound glyph with %d element%s (offset %lu):\n",
+ count,
+ count == 1 ? "" : "s",
+ offset ));
/* now, load each individual glyph */
for ( n = 0; n < count; n++ )
@@ -810,7 +812,9 @@
/* proceed to next sub-glyph */
}
- FT_TRACE4(( "end compound glyph with %d elements\n", count ));
+ FT_TRACE4(( "end compound glyph with %d element%s\n",
+ count,
+ count == 1 ? "" : "s" ));
}
else
{
diff --git a/thirdparty/freetype/src/pfr/pfrgload.h b/thirdparty/freetype/src/pfr/pfrgload.h
index 6612323871..01f48d7706 100644
--- a/thirdparty/freetype/src/pfr/pfrgload.h
+++ b/thirdparty/freetype/src/pfr/pfrgload.h
@@ -4,7 +4,7 @@
/* */
/* FreeType PFR glyph loader (specification). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/pfr/pfrload.c b/thirdparty/freetype/src/pfr/pfrload.c
index 4f84165828..2776da462a 100644
--- a/thirdparty/freetype/src/pfr/pfrload.c
+++ b/thirdparty/freetype/src/pfr/pfrload.c
@@ -4,7 +4,7 @@
/* */
/* FreeType PFR loader (body). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/pfr/pfrload.h b/thirdparty/freetype/src/pfr/pfrload.h
index f9475ae062..36e809a762 100644
--- a/thirdparty/freetype/src/pfr/pfrload.h
+++ b/thirdparty/freetype/src/pfr/pfrload.h
@@ -4,7 +4,7 @@
/* */
/* FreeType PFR loader (specification). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/pfr/pfrobjs.c b/thirdparty/freetype/src/pfr/pfrobjs.c
index 514af8050d..737b97b5ff 100644
--- a/thirdparty/freetype/src/pfr/pfrobjs.c
+++ b/thirdparty/freetype/src/pfr/pfrobjs.c
@@ -4,7 +4,7 @@
/* */
/* FreeType PFR object methods (body). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/pfr/pfrobjs.h b/thirdparty/freetype/src/pfr/pfrobjs.h
index d6ad6562df..59c709f58d 100644
--- a/thirdparty/freetype/src/pfr/pfrobjs.h
+++ b/thirdparty/freetype/src/pfr/pfrobjs.h
@@ -4,7 +4,7 @@
/* */
/* FreeType PFR object methods (specification). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/pfr/pfrsbit.c b/thirdparty/freetype/src/pfr/pfrsbit.c
index 54e7d0e6cc..ba909ddca7 100644
--- a/thirdparty/freetype/src/pfr/pfrsbit.c
+++ b/thirdparty/freetype/src/pfr/pfrsbit.c
@@ -4,7 +4,7 @@
/* */
/* FreeType PFR bitmap loader (body). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/pfr/pfrsbit.h b/thirdparty/freetype/src/pfr/pfrsbit.h
index fc270f50a8..07b27bc06c 100644
--- a/thirdparty/freetype/src/pfr/pfrsbit.h
+++ b/thirdparty/freetype/src/pfr/pfrsbit.h
@@ -4,7 +4,7 @@
/* */
/* FreeType PFR bitmap loader (specification). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/pfr/pfrtypes.h b/thirdparty/freetype/src/pfr/pfrtypes.h
index c3d542c209..058d6aadc9 100644
--- a/thirdparty/freetype/src/pfr/pfrtypes.h
+++ b/thirdparty/freetype/src/pfr/pfrtypes.h
@@ -4,7 +4,7 @@
/* */
/* FreeType PFR data structures (specification only). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/pfr/rules.mk b/thirdparty/freetype/src/pfr/rules.mk
index 9940f62286..3acb795696 100644
--- a/thirdparty/freetype/src/pfr/rules.mk
+++ b/thirdparty/freetype/src/pfr/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 2002-2017 by
+# Copyright 2002-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/psaux/afmparse.c b/thirdparty/freetype/src/psaux/afmparse.c
index ff2cc8cf08..0c33d5949b 100644
--- a/thirdparty/freetype/src/psaux/afmparse.c
+++ b/thirdparty/freetype/src/psaux/afmparse.c
@@ -4,7 +4,7 @@
/* */
/* AFM parser (body). */
/* */
-/* Copyright 2006-2017 by */
+/* Copyright 2006-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/psaux/afmparse.h b/thirdparty/freetype/src/psaux/afmparse.h
index cd2beb7804..86f852a247 100644
--- a/thirdparty/freetype/src/psaux/afmparse.h
+++ b/thirdparty/freetype/src/psaux/afmparse.h
@@ -4,7 +4,7 @@
/* */
/* AFM parser (specification). */
/* */
-/* Copyright 2006-2017 by */
+/* Copyright 2006-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/psaux/cffdecode.c b/thirdparty/freetype/src/psaux/cffdecode.c
new file mode 100644
index 0000000000..80d622c0e1
--- /dev/null
+++ b/thirdparty/freetype/src/psaux/cffdecode.c
@@ -0,0 +1,2370 @@
+/***************************************************************************/
+/* */
+/* cffdecode.c */
+/* */
+/* PostScript CFF (Type 2) decoding routines (body). */
+/* */
+/* Copyright 2017-2018 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_SERVICE_H
+#include FT_SERVICE_CFF_TABLE_LOAD_H
+
+#include "cffdecode.h"
+#include "psobjs.h"
+
+#include "psauxerr.h"
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_cffdecode
+
+
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+
+ typedef enum CFF_Operator_
+ {
+ cff_op_unknown = 0,
+
+ cff_op_rmoveto,
+ cff_op_hmoveto,
+ cff_op_vmoveto,
+
+ cff_op_rlineto,
+ cff_op_hlineto,
+ cff_op_vlineto,
+
+ cff_op_rrcurveto,
+ cff_op_hhcurveto,
+ cff_op_hvcurveto,
+ cff_op_rcurveline,
+ cff_op_rlinecurve,
+ cff_op_vhcurveto,
+ cff_op_vvcurveto,
+
+ cff_op_flex,
+ cff_op_hflex,
+ cff_op_hflex1,
+ cff_op_flex1,
+
+ cff_op_endchar,
+
+ cff_op_hstem,
+ cff_op_vstem,
+ cff_op_hstemhm,
+ cff_op_vstemhm,
+
+ cff_op_hintmask,
+ cff_op_cntrmask,
+ cff_op_dotsection, /* deprecated, acts as no-op */
+
+ cff_op_abs,
+ cff_op_add,
+ cff_op_sub,
+ cff_op_div,
+ cff_op_neg,
+ cff_op_random,
+ cff_op_mul,
+ cff_op_sqrt,
+
+ cff_op_blend,
+
+ cff_op_drop,
+ cff_op_exch,
+ cff_op_index,
+ cff_op_roll,
+ cff_op_dup,
+
+ cff_op_put,
+ cff_op_get,
+ cff_op_store,
+ cff_op_load,
+
+ cff_op_and,
+ cff_op_or,
+ cff_op_not,
+ cff_op_eq,
+ cff_op_ifelse,
+
+ cff_op_callsubr,
+ cff_op_callgsubr,
+ cff_op_return,
+
+ /* Type 1 opcodes: invalid but seen in real life */
+ cff_op_hsbw,
+ cff_op_closepath,
+ cff_op_callothersubr,
+ cff_op_pop,
+ cff_op_seac,
+ cff_op_sbw,
+ cff_op_setcurrentpoint,
+
+ /* do not remove */
+ cff_op_max
+
+ } CFF_Operator;
+
+
+#define CFF_COUNT_CHECK_WIDTH 0x80
+#define CFF_COUNT_EXACT 0x40
+#define CFF_COUNT_CLEAR_STACK 0x20
+
+ /* count values which have the `CFF_COUNT_CHECK_WIDTH' flag set are */
+ /* used for checking the width and requested numbers of arguments */
+ /* only; they are set to zero afterwards */
+
+ /* the other two flags are informative only and unused currently */
+
+ static const FT_Byte cff_argument_counts[] =
+ {
+ 0, /* unknown */
+
+ 2 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, /* rmoveto */
+ 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,
+ 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,
+
+ 0 | CFF_COUNT_CLEAR_STACK, /* rlineto */
+ 0 | CFF_COUNT_CLEAR_STACK,
+ 0 | CFF_COUNT_CLEAR_STACK,
+
+ 0 | CFF_COUNT_CLEAR_STACK, /* rrcurveto */
+ 0 | CFF_COUNT_CLEAR_STACK,
+ 0 | CFF_COUNT_CLEAR_STACK,
+ 0 | CFF_COUNT_CLEAR_STACK,
+ 0 | CFF_COUNT_CLEAR_STACK,
+ 0 | CFF_COUNT_CLEAR_STACK,
+ 0 | CFF_COUNT_CLEAR_STACK,
+
+ 13, /* flex */
+ 7,
+ 9,
+ 11,
+
+ 0 | CFF_COUNT_CHECK_WIDTH, /* endchar */
+
+ 2 | CFF_COUNT_CHECK_WIDTH, /* hstem */
+ 2 | CFF_COUNT_CHECK_WIDTH,
+ 2 | CFF_COUNT_CHECK_WIDTH,
+ 2 | CFF_COUNT_CHECK_WIDTH,
+
+ 0 | CFF_COUNT_CHECK_WIDTH, /* hintmask */
+ 0 | CFF_COUNT_CHECK_WIDTH, /* cntrmask */
+ 0, /* dotsection */
+
+ 1, /* abs */
+ 2,
+ 2,
+ 2,
+ 1,
+ 0,
+ 2,
+ 1,
+
+ 1, /* blend */
+
+ 1, /* drop */
+ 2,
+ 1,
+ 2,
+ 1,
+
+ 2, /* put */
+ 1,
+ 4,
+ 3,
+
+ 2, /* and */
+ 2,
+ 1,
+ 2,
+ 4,
+
+ 1, /* callsubr */
+ 1,
+ 0,
+
+ 2, /* hsbw */
+ 0,
+ 0,
+ 0,
+ 5, /* seac */
+ 4, /* sbw */
+ 2 /* setcurrentpoint */
+ };
+
+
+ static FT_Error
+ cff_operator_seac( CFF_Decoder* decoder,
+ FT_Pos asb,
+ FT_Pos adx,
+ FT_Pos ady,
+ FT_Int bchar,
+ FT_Int achar )
+ {
+ FT_Error error;
+ CFF_Builder* builder = &decoder->builder;
+ FT_Int bchar_index, achar_index;
+ TT_Face face = decoder->builder.face;
+ FT_Vector left_bearing, advance;
+ FT_Byte* charstring;
+ FT_ULong charstring_len;
+ FT_Pos glyph_width;
+
+
+ if ( decoder->seac )
+ {
+ FT_ERROR(( "cff_operator_seac: invalid nested seac\n" ));
+ return FT_THROW( Syntax_Error );
+ }
+
+ adx += decoder->builder.left_bearing.x;
+ ady += decoder->builder.left_bearing.y;
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+ /* Incremental fonts don't necessarily have valid charsets. */
+ /* They use the character code, not the glyph index, in this case. */
+ if ( face->root.internal->incremental_interface )
+ {
+ bchar_index = bchar;
+ achar_index = achar;
+ }
+ else
+#endif /* FT_CONFIG_OPTION_INCREMENTAL */
+ {
+ CFF_Font cff = (CFF_Font)(face->extra.data);
+
+
+ bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar );
+ achar_index = cff_lookup_glyph_by_stdcharcode( cff, achar );
+ }
+
+ if ( bchar_index < 0 || achar_index < 0 )
+ {
+ FT_ERROR(( "cff_operator_seac:"
+ " invalid seac character code arguments\n" ));
+ return FT_THROW( Syntax_Error );
+ }
+
+ /* If we are trying to load a composite glyph, do not load the */
+ /* accent character and return the array of subglyphs. */
+ if ( builder->no_recurse )
+ {
+ FT_GlyphSlot glyph = (FT_GlyphSlot)builder->glyph;
+ FT_GlyphLoader loader = glyph->internal->loader;
+ FT_SubGlyph subg;
+
+
+ /* reallocate subglyph array if necessary */
+ error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );
+ if ( error )
+ goto Exit;
+
+ subg = loader->current.subglyphs;
+
+ /* subglyph 0 = base character */
+ subg->index = bchar_index;
+ subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
+ FT_SUBGLYPH_FLAG_USE_MY_METRICS;
+ subg->arg1 = 0;
+ subg->arg2 = 0;
+ subg++;
+
+ /* subglyph 1 = accent character */
+ subg->index = achar_index;
+ subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
+ subg->arg1 = (FT_Int)( adx >> 16 );
+ subg->arg2 = (FT_Int)( ady >> 16 );
+
+ /* set up remaining glyph fields */
+ glyph->num_subglyphs = 2;
+ glyph->subglyphs = loader->base.subglyphs;
+ glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
+
+ loader->current.num_subglyphs = 2;
+ }
+
+ FT_GlyphLoader_Prepare( builder->loader );
+
+ /* First load `bchar' in builder */
+ error = decoder->get_glyph_callback( face, (FT_UInt)bchar_index,
+ &charstring, &charstring_len );
+ if ( !error )
+ {
+ /* the seac operator must not be nested */
+ decoder->seac = TRUE;
+ error = cff_decoder_parse_charstrings( decoder, charstring,
+ charstring_len, 0 );
+ decoder->seac = FALSE;
+
+ decoder->free_glyph_callback( face, &charstring, charstring_len );
+
+ if ( error )
+ goto Exit;
+ }
+
+ /* Save the left bearing, advance and glyph width of the base */
+ /* character as they will be erased by the next load. */
+
+ left_bearing = builder->left_bearing;
+ advance = builder->advance;
+ glyph_width = decoder->glyph_width;
+
+ builder->left_bearing.x = 0;
+ builder->left_bearing.y = 0;
+
+ builder->pos_x = adx - asb;
+ builder->pos_y = ady;
+
+ /* Now load `achar' on top of the base outline. */
+ error = decoder->get_glyph_callback( face, (FT_UInt)achar_index,
+ &charstring, &charstring_len );
+ if ( !error )
+ {
+ /* the seac operator must not be nested */
+ decoder->seac = TRUE;
+ error = cff_decoder_parse_charstrings( decoder, charstring,
+ charstring_len, 0 );
+ decoder->seac = FALSE;
+
+ decoder->free_glyph_callback( face, &charstring, charstring_len );
+
+ if ( error )
+ goto Exit;
+ }
+
+ /* Restore the left side bearing, advance and glyph width */
+ /* of the base character. */
+ builder->left_bearing = left_bearing;
+ builder->advance = advance;
+ decoder->glyph_width = glyph_width;
+
+ builder->pos_x = 0;
+ builder->pos_y = 0;
+
+ Exit:
+ return error;
+ }
+
+#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /********** *********/
+ /********** *********/
+ /********** GENERIC CHARSTRING PARSING *********/
+ /********** *********/
+ /********** *********/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* cff_compute_bias */
+ /* */
+ /* <Description> */
+ /* Computes the bias value in dependence of the number of glyph */
+ /* subroutines. */
+ /* */
+ /* <Input> */
+ /* in_charstring_type :: The `CharstringType' value of the top DICT */
+ /* dictionary. */
+ /* */
+ /* num_subrs :: The number of glyph subroutines. */
+ /* */
+ /* <Return> */
+ /* The bias value. */
+ static FT_Int
+ cff_compute_bias( FT_Int in_charstring_type,
+ FT_UInt num_subrs )
+ {
+ FT_Int result;
+
+
+ if ( in_charstring_type == 1 )
+ result = 0;
+ else if ( num_subrs < 1240 )
+ result = 107;
+ else if ( num_subrs < 33900U )
+ result = 1131;
+ else
+ result = 32768U;
+
+ return result;
+ }
+
+
+ FT_LOCAL_DEF( FT_Int )
+ cff_lookup_glyph_by_stdcharcode( CFF_Font cff,
+ FT_Int charcode )
+ {
+ FT_UInt n;
+ FT_UShort glyph_sid;
+
+ FT_Service_CFFLoad cffload;
+
+
+ /* CID-keyed fonts don't have glyph names */
+ if ( !cff->charset.sids )
+ return -1;
+
+ /* check range of standard char code */
+ if ( charcode < 0 || charcode > 255 )
+ return -1;
+
+#if 0
+ /* retrieve cffload from list of current modules */
+ FT_Service_CFFLoad cffload;
+
+
+ FT_FACE_FIND_GLOBAL_SERVICE( face, cffload, CFF_LOAD );
+ if ( !cffload )
+ {
+ FT_ERROR(( "cff_lookup_glyph_by_stdcharcode:"
+ " the `cffload' module is not available\n" ));
+ return FT_THROW( Unimplemented_Feature );
+ }
+#endif
+
+ cffload = (FT_Service_CFFLoad)cff->cffload;
+
+ /* Get code to SID mapping from `cff_standard_encoding'. */
+ glyph_sid = cffload->get_standard_encoding( (FT_UInt)charcode );
+
+ for ( n = 0; n < cff->num_glyphs; n++ )
+ {
+ if ( cff->charset.sids[n] == glyph_sid )
+ return (FT_Int)n;
+ }
+
+ return -1;
+ }
+
+
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* cff_decoder_parse_charstrings */
+ /* */
+ /* <Description> */
+ /* Parses a given Type 2 charstrings program. */
+ /* */
+ /* <InOut> */
+ /* decoder :: The current Type 1 decoder. */
+ /* */
+ /* <Input> */
+ /* charstring_base :: The base of the charstring stream. */
+ /* */
+ /* charstring_len :: The length in bytes of the charstring stream. */
+ /* */
+ /* in_dict :: Set to 1 if function is called from top or */
+ /* private DICT (needed for Multiple Master CFFs). */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ cff_decoder_parse_charstrings( CFF_Decoder* decoder,
+ FT_Byte* charstring_base,
+ FT_ULong charstring_len,
+ FT_Bool in_dict )
+ {
+ FT_Error error;
+ CFF_Decoder_Zone* zone;
+ FT_Byte* ip;
+ FT_Byte* limit;
+ CFF_Builder* builder = &decoder->builder;
+ FT_Pos x, y;
+ FT_Fixed* stack;
+ FT_Int charstring_type =
+ decoder->cff->top_font.font_dict.charstring_type;
+ FT_UShort num_designs =
+ decoder->cff->top_font.font_dict.num_designs;
+ FT_UShort num_axes =
+ decoder->cff->top_font.font_dict.num_axes;
+
+ T2_Hints_Funcs hinter;
+
+
+ /* set default width */
+ decoder->num_hints = 0;
+ decoder->read_width = 1;
+
+ /* initialize the decoder */
+ decoder->top = decoder->stack;
+ decoder->zone = decoder->zones;
+ zone = decoder->zones;
+ stack = decoder->top;
+
+ hinter = (T2_Hints_Funcs)builder->hints_funcs;
+
+ builder->path_begun = 0;
+
+ zone->base = charstring_base;
+ limit = zone->limit = charstring_base + charstring_len;
+ ip = zone->cursor = zone->base;
+
+ error = FT_Err_Ok;
+
+ x = builder->pos_x;
+ y = builder->pos_y;
+
+ /* begin hints recording session, if any */
+ if ( hinter )
+ hinter->open( hinter->hints );
+
+ /* now execute loop */
+ while ( ip < limit )
+ {
+ CFF_Operator op;
+ FT_Byte v;
+
+
+ /********************************************************************/
+ /* */
+ /* Decode operator or operand */
+ /* */
+ v = *ip++;
+ if ( v >= 32 || v == 28 )
+ {
+ FT_Int shift = 16;
+ FT_Int32 val;
+
+
+ /* this is an operand, push it on the stack */
+
+ /* if we use shifts, all computations are done with unsigned */
+ /* values; the conversion to a signed value is the last step */
+ if ( v == 28 )
+ {
+ if ( ip + 1 >= limit )
+ goto Syntax_Error;
+ val = (FT_Short)( ( (FT_UShort)ip[0] << 8 ) | ip[1] );
+ ip += 2;
+ }
+ else if ( v < 247 )
+ val = (FT_Int32)v - 139;
+ else if ( v < 251 )
+ {
+ if ( ip >= limit )
+ goto Syntax_Error;
+ val = ( (FT_Int32)v - 247 ) * 256 + *ip++ + 108;
+ }
+ else if ( v < 255 )
+ {
+ if ( ip >= limit )
+ goto Syntax_Error;
+ val = -( (FT_Int32)v - 251 ) * 256 - *ip++ - 108;
+ }
+ else
+ {
+ if ( ip + 3 >= limit )
+ goto Syntax_Error;
+ val = (FT_Int32)( ( (FT_UInt32)ip[0] << 24 ) |
+ ( (FT_UInt32)ip[1] << 16 ) |
+ ( (FT_UInt32)ip[2] << 8 ) |
+ (FT_UInt32)ip[3] );
+ ip += 4;
+ if ( charstring_type == 2 )
+ shift = 0;
+ }
+ if ( decoder->top - stack >= CFF_MAX_OPERANDS )
+ goto Stack_Overflow;
+
+ val = (FT_Int32)( (FT_UInt32)val << shift );
+ *decoder->top++ = val;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( !( val & 0xFFFFL ) )
+ FT_TRACE4(( " %hd", (FT_Short)( (FT_UInt32)val >> 16 ) ));
+ else
+ FT_TRACE4(( " %.5f", val / 65536.0 ));
+#endif
+
+ }
+ else
+ {
+ /* The specification says that normally arguments are to be taken */
+ /* from the bottom of the stack. However, this seems not to be */
+ /* correct, at least for Acroread 7.0.8 on GNU/Linux: It pops the */
+ /* arguments similar to a PS interpreter. */
+
+ FT_Fixed* args = decoder->top;
+ FT_Int num_args = (FT_Int)( args - decoder->stack );
+ FT_Int req_args;
+
+
+ /* find operator */
+ op = cff_op_unknown;
+
+ switch ( v )
+ {
+ case 1:
+ op = cff_op_hstem;
+ break;
+ case 3:
+ op = cff_op_vstem;
+ break;
+ case 4:
+ op = cff_op_vmoveto;
+ break;
+ case 5:
+ op = cff_op_rlineto;
+ break;
+ case 6:
+ op = cff_op_hlineto;
+ break;
+ case 7:
+ op = cff_op_vlineto;
+ break;
+ case 8:
+ op = cff_op_rrcurveto;
+ break;
+ case 9:
+ op = cff_op_closepath;
+ break;
+ case 10:
+ op = cff_op_callsubr;
+ break;
+ case 11:
+ op = cff_op_return;
+ break;
+ case 12:
+ if ( ip >= limit )
+ goto Syntax_Error;
+ v = *ip++;
+
+ switch ( v )
+ {
+ case 0:
+ op = cff_op_dotsection;
+ break;
+ case 1: /* this is actually the Type1 vstem3 operator */
+ op = cff_op_vstem;
+ break;
+ case 2: /* this is actually the Type1 hstem3 operator */
+ op = cff_op_hstem;
+ break;
+ case 3:
+ op = cff_op_and;
+ break;
+ case 4:
+ op = cff_op_or;
+ break;
+ case 5:
+ op = cff_op_not;
+ break;
+ case 6:
+ op = cff_op_seac;
+ break;
+ case 7:
+ op = cff_op_sbw;
+ break;
+ case 8:
+ op = cff_op_store;
+ break;
+ case 9:
+ op = cff_op_abs;
+ break;
+ case 10:
+ op = cff_op_add;
+ break;
+ case 11:
+ op = cff_op_sub;
+ break;
+ case 12:
+ op = cff_op_div;
+ break;
+ case 13:
+ op = cff_op_load;
+ break;
+ case 14:
+ op = cff_op_neg;
+ break;
+ case 15:
+ op = cff_op_eq;
+ break;
+ case 16:
+ op = cff_op_callothersubr;
+ break;
+ case 17:
+ op = cff_op_pop;
+ break;
+ case 18:
+ op = cff_op_drop;
+ break;
+ case 20:
+ op = cff_op_put;
+ break;
+ case 21:
+ op = cff_op_get;
+ break;
+ case 22:
+ op = cff_op_ifelse;
+ break;
+ case 23:
+ op = cff_op_random;
+ break;
+ case 24:
+ op = cff_op_mul;
+ break;
+ case 26:
+ op = cff_op_sqrt;
+ break;
+ case 27:
+ op = cff_op_dup;
+ break;
+ case 28:
+ op = cff_op_exch;
+ break;
+ case 29:
+ op = cff_op_index;
+ break;
+ case 30:
+ op = cff_op_roll;
+ break;
+ case 33:
+ op = cff_op_setcurrentpoint;
+ break;
+ case 34:
+ op = cff_op_hflex;
+ break;
+ case 35:
+ op = cff_op_flex;
+ break;
+ case 36:
+ op = cff_op_hflex1;
+ break;
+ case 37:
+ op = cff_op_flex1;
+ break;
+ default:
+ FT_TRACE4(( " unknown op (12, %d)\n", v ));
+ break;
+ }
+ break;
+ case 13:
+ op = cff_op_hsbw;
+ break;
+ case 14:
+ op = cff_op_endchar;
+ break;
+ case 16:
+ op = cff_op_blend;
+ break;
+ case 18:
+ op = cff_op_hstemhm;
+ break;
+ case 19:
+ op = cff_op_hintmask;
+ break;
+ case 20:
+ op = cff_op_cntrmask;
+ break;
+ case 21:
+ op = cff_op_rmoveto;
+ break;
+ case 22:
+ op = cff_op_hmoveto;
+ break;
+ case 23:
+ op = cff_op_vstemhm;
+ break;
+ case 24:
+ op = cff_op_rcurveline;
+ break;
+ case 25:
+ op = cff_op_rlinecurve;
+ break;
+ case 26:
+ op = cff_op_vvcurveto;
+ break;
+ case 27:
+ op = cff_op_hhcurveto;
+ break;
+ case 29:
+ op = cff_op_callgsubr;
+ break;
+ case 30:
+ op = cff_op_vhcurveto;
+ break;
+ case 31:
+ op = cff_op_hvcurveto;
+ break;
+ default:
+ FT_TRACE4(( " unknown op (%d)\n", v ));
+ break;
+ }
+
+ if ( op == cff_op_unknown )
+ continue;
+
+ /* in Multiple Master CFFs, T2 charstrings can appear in */
+ /* dictionaries, but some operators are prohibited */
+ if ( in_dict )
+ {
+ switch ( op )
+ {
+ case cff_op_hstem:
+ case cff_op_vstem:
+ case cff_op_vmoveto:
+ case cff_op_rlineto:
+ case cff_op_hlineto:
+ case cff_op_vlineto:
+ case cff_op_rrcurveto:
+ case cff_op_hstemhm:
+ case cff_op_hintmask:
+ case cff_op_cntrmask:
+ case cff_op_rmoveto:
+ case cff_op_hmoveto:
+ case cff_op_vstemhm:
+ case cff_op_rcurveline:
+ case cff_op_rlinecurve:
+ case cff_op_vvcurveto:
+ case cff_op_hhcurveto:
+ case cff_op_vhcurveto:
+ case cff_op_hvcurveto:
+ case cff_op_hflex:
+ case cff_op_flex:
+ case cff_op_hflex1:
+ case cff_op_flex1:
+ case cff_op_callsubr:
+ case cff_op_callgsubr:
+ goto MM_Error;
+
+ default:
+ break;
+ }
+ }
+
+ /* check arguments */
+ req_args = cff_argument_counts[op];
+ if ( req_args & CFF_COUNT_CHECK_WIDTH )
+ {
+ if ( num_args > 0 && decoder->read_width )
+ {
+ /* If `nominal_width' is non-zero, the number is really a */
+ /* difference against `nominal_width'. Else, the number here */
+ /* is truly a width, not a difference against `nominal_width'. */
+ /* If the font does not set `nominal_width', then */
+ /* `nominal_width' defaults to zero, and so we can set */
+ /* `glyph_width' to `nominal_width' plus number on the stack */
+ /* -- for either case. */
+
+ FT_Int set_width_ok;
+
+
+ switch ( op )
+ {
+ case cff_op_hmoveto:
+ case cff_op_vmoveto:
+ set_width_ok = num_args & 2;
+ break;
+
+ case cff_op_hstem:
+ case cff_op_vstem:
+ case cff_op_hstemhm:
+ case cff_op_vstemhm:
+ case cff_op_rmoveto:
+ case cff_op_hintmask:
+ case cff_op_cntrmask:
+ set_width_ok = num_args & 1;
+ break;
+
+ case cff_op_endchar:
+ /* If there is a width specified for endchar, we either have */
+ /* 1 argument or 5 arguments. We like to argue. */
+ set_width_ok = in_dict
+ ? 0
+ : ( ( num_args == 5 ) || ( num_args == 1 ) );
+ break;
+
+ default:
+ set_width_ok = 0;
+ break;
+ }
+
+ if ( set_width_ok )
+ {
+ decoder->glyph_width = decoder->nominal_width +
+ ( stack[0] >> 16 );
+
+ if ( decoder->width_only )
+ {
+ /* we only want the advance width; stop here */
+ break;
+ }
+
+ /* Consumed an argument. */
+ num_args--;
+ }
+ }
+
+ decoder->read_width = 0;
+ req_args = 0;
+ }
+
+ req_args &= 0x000F;
+ if ( num_args < req_args )
+ goto Stack_Underflow;
+ args -= req_args;
+ num_args -= req_args;
+
+ /* At this point, `args' points to the first argument of the */
+ /* operand in case `req_args' isn't zero. Otherwise, we have */
+ /* to adjust `args' manually. */
+
+ /* Note that we only pop arguments from the stack which we */
+ /* really need and can digest so that we can continue in case */
+ /* of superfluous stack elements. */
+
+ switch ( op )
+ {
+ case cff_op_hstem:
+ case cff_op_vstem:
+ case cff_op_hstemhm:
+ case cff_op_vstemhm:
+ /* the number of arguments is always even here */
+ FT_TRACE4((
+ op == cff_op_hstem ? " hstem\n" :
+ ( op == cff_op_vstem ? " vstem\n" :
+ ( op == cff_op_hstemhm ? " hstemhm\n" : " vstemhm\n" ) ) ));
+
+ if ( hinter )
+ hinter->stems( hinter->hints,
+ ( op == cff_op_hstem || op == cff_op_hstemhm ),
+ num_args / 2,
+ args - ( num_args & ~1 ) );
+
+ decoder->num_hints += num_args / 2;
+ args = stack;
+ break;
+
+ case cff_op_hintmask:
+ case cff_op_cntrmask:
+ FT_TRACE4(( op == cff_op_hintmask ? " hintmask" : " cntrmask" ));
+
+ /* implement vstem when needed -- */
+ /* the specification doesn't say it, but this also works */
+ /* with the 'cntrmask' operator */
+ /* */
+ if ( num_args > 0 )
+ {
+ if ( hinter )
+ hinter->stems( hinter->hints,
+ 0,
+ num_args / 2,
+ args - ( num_args & ~1 ) );
+
+ decoder->num_hints += num_args / 2;
+ }
+
+ /* In a valid charstring there must be at least one byte */
+ /* after `hintmask' or `cntrmask' (e.g., for a `return' */
+ /* instruction). Additionally, there must be space for */
+ /* `num_hints' bits. */
+
+ if ( ( ip + ( ( decoder->num_hints + 7 ) >> 3 ) ) >= limit )
+ goto Syntax_Error;
+
+ if ( hinter )
+ {
+ if ( op == cff_op_hintmask )
+ hinter->hintmask( hinter->hints,
+ (FT_UInt)builder->current->n_points,
+ (FT_UInt)decoder->num_hints,
+ ip );
+ else
+ hinter->counter( hinter->hints,
+ (FT_UInt)decoder->num_hints,
+ ip );
+ }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ {
+ FT_UInt maskbyte;
+
+
+ FT_TRACE4(( " (maskbytes:" ));
+
+ for ( maskbyte = 0;
+ maskbyte < (FT_UInt)( ( decoder->num_hints + 7 ) >> 3 );
+ maskbyte++, ip++ )
+ FT_TRACE4(( " 0x%02X", *ip ));
+
+ FT_TRACE4(( ")\n" ));
+ }
+#else
+ ip += ( decoder->num_hints + 7 ) >> 3;
+#endif
+ args = stack;
+ break;
+
+ case cff_op_rmoveto:
+ FT_TRACE4(( " rmoveto\n" ));
+
+ cff_builder_close_contour( builder );
+ builder->path_begun = 0;
+ x = ADD_LONG( x, args[-2] );
+ y = ADD_LONG( y, args[-1] );
+ args = stack;
+ break;
+
+ case cff_op_vmoveto:
+ FT_TRACE4(( " vmoveto\n" ));
+
+ cff_builder_close_contour( builder );
+ builder->path_begun = 0;
+ y = ADD_LONG( y, args[-1] );
+ args = stack;
+ break;
+
+ case cff_op_hmoveto:
+ FT_TRACE4(( " hmoveto\n" ));
+
+ cff_builder_close_contour( builder );
+ builder->path_begun = 0;
+ x = ADD_LONG( x, args[-1] );
+ args = stack;
+ break;
+
+ case cff_op_rlineto:
+ FT_TRACE4(( " rlineto\n" ));
+
+ if ( cff_builder_start_point( builder, x, y ) ||
+ cff_check_points( builder, num_args / 2 ) )
+ goto Fail;
+
+ if ( num_args < 2 )
+ goto Stack_Underflow;
+
+ args -= num_args & ~1;
+ while ( args < decoder->top )
+ {
+ x = ADD_LONG( x, args[0] );
+ y = ADD_LONG( y, args[1] );
+ cff_builder_add_point( builder, x, y, 1 );
+ args += 2;
+ }
+ args = stack;
+ break;
+
+ case cff_op_hlineto:
+ case cff_op_vlineto:
+ {
+ FT_Int phase = ( op == cff_op_hlineto );
+
+
+ FT_TRACE4(( op == cff_op_hlineto ? " hlineto\n"
+ : " vlineto\n" ));
+
+ if ( num_args < 0 )
+ goto Stack_Underflow;
+
+ /* there exist subsetted fonts (found in PDFs) */
+ /* which call `hlineto' without arguments */
+ if ( num_args == 0 )
+ break;
+
+ if ( cff_builder_start_point( builder, x, y ) ||
+ cff_check_points( builder, num_args ) )
+ goto Fail;
+
+ args = stack;
+ while ( args < decoder->top )
+ {
+ if ( phase )
+ x = ADD_LONG( x, args[0] );
+ else
+ y = ADD_LONG( y, args[0] );
+
+ if ( cff_builder_add_point1( builder, x, y ) )
+ goto Fail;
+
+ args++;
+ phase ^= 1;
+ }
+ args = stack;
+ }
+ break;
+
+ case cff_op_rrcurveto:
+ {
+ FT_Int nargs;
+
+
+ FT_TRACE4(( " rrcurveto\n" ));
+
+ if ( num_args < 6 )
+ goto Stack_Underflow;
+
+ nargs = num_args - num_args % 6;
+
+ if ( cff_builder_start_point( builder, x, y ) ||
+ cff_check_points( builder, nargs / 2 ) )
+ goto Fail;
+
+ args -= nargs;
+ while ( args < decoder->top )
+ {
+ x = ADD_LONG( x, args[0] );
+ y = ADD_LONG( y, args[1] );
+ cff_builder_add_point( builder, x, y, 0 );
+
+ x = ADD_LONG( x, args[2] );
+ y = ADD_LONG( y, args[3] );
+ cff_builder_add_point( builder, x, y, 0 );
+
+ x = ADD_LONG( x, args[4] );
+ y = ADD_LONG( y, args[5] );
+ cff_builder_add_point( builder, x, y, 1 );
+
+ args += 6;
+ }
+ args = stack;
+ }
+ break;
+
+ case cff_op_vvcurveto:
+ {
+ FT_Int nargs;
+
+
+ FT_TRACE4(( " vvcurveto\n" ));
+
+ if ( num_args < 4 )
+ goto Stack_Underflow;
+
+ /* if num_args isn't of the form 4n or 4n+1, */
+ /* we enforce it by clearing the second bit */
+
+ nargs = num_args & ~2;
+
+ if ( cff_builder_start_point( builder, x, y ) )
+ goto Fail;
+
+ args -= nargs;
+
+ if ( nargs & 1 )
+ {
+ x = ADD_LONG( x, args[0] );
+ args++;
+ nargs--;
+ }
+
+ if ( cff_check_points( builder, 3 * ( nargs / 4 ) ) )
+ goto Fail;
+
+ while ( args < decoder->top )
+ {
+ y = ADD_LONG( y, args[0] );
+ cff_builder_add_point( builder, x, y, 0 );
+
+ x = ADD_LONG( x, args[1] );
+ y = ADD_LONG( y, args[2] );
+ cff_builder_add_point( builder, x, y, 0 );
+
+ y = ADD_LONG( y, args[3] );
+ cff_builder_add_point( builder, x, y, 1 );
+
+ args += 4;
+ }
+ args = stack;
+ }
+ break;
+
+ case cff_op_hhcurveto:
+ {
+ FT_Int nargs;
+
+
+ FT_TRACE4(( " hhcurveto\n" ));
+
+ if ( num_args < 4 )
+ goto Stack_Underflow;
+
+ /* if num_args isn't of the form 4n or 4n+1, */
+ /* we enforce it by clearing the second bit */
+
+ nargs = num_args & ~2;
+
+ if ( cff_builder_start_point( builder, x, y ) )
+ goto Fail;
+
+ args -= nargs;
+ if ( nargs & 1 )
+ {
+ y = ADD_LONG( y, args[0] );
+ args++;
+ nargs--;
+ }
+
+ if ( cff_check_points( builder, 3 * ( nargs / 4 ) ) )
+ goto Fail;
+
+ while ( args < decoder->top )
+ {
+ x = ADD_LONG( x, args[0] );
+ cff_builder_add_point( builder, x, y, 0 );
+
+ x = ADD_LONG( x, args[1] );
+ y = ADD_LONG( y, args[2] );
+ cff_builder_add_point( builder, x, y, 0 );
+
+ x = ADD_LONG( x, args[3] );
+ cff_builder_add_point( builder, x, y, 1 );
+
+ args += 4;
+ }
+ args = stack;
+ }
+ break;
+
+ case cff_op_vhcurveto:
+ case cff_op_hvcurveto:
+ {
+ FT_Int phase;
+ FT_Int nargs;
+
+
+ FT_TRACE4(( op == cff_op_vhcurveto ? " vhcurveto\n"
+ : " hvcurveto\n" ));
+
+ if ( cff_builder_start_point( builder, x, y ) )
+ goto Fail;
+
+ if ( num_args < 4 )
+ goto Stack_Underflow;
+
+ /* if num_args isn't of the form 8n, 8n+1, 8n+4, or 8n+5, */
+ /* we enforce it by clearing the second bit */
+
+ nargs = num_args & ~2;
+
+ args -= nargs;
+ if ( cff_check_points( builder, ( nargs / 4 ) * 3 ) )
+ goto Stack_Underflow;
+
+ phase = ( op == cff_op_hvcurveto );
+
+ while ( nargs >= 4 )
+ {
+ nargs -= 4;
+ if ( phase )
+ {
+ x = ADD_LONG( x, args[0] );
+ cff_builder_add_point( builder, x, y, 0 );
+
+ x = ADD_LONG( x, args[1] );
+ y = ADD_LONG( y, args[2] );
+ cff_builder_add_point( builder, x, y, 0 );
+
+ y = ADD_LONG( y, args[3] );
+ if ( nargs == 1 )
+ x = ADD_LONG( x, args[4] );
+ cff_builder_add_point( builder, x, y, 1 );
+ }
+ else
+ {
+ y = ADD_LONG( y, args[0] );
+ cff_builder_add_point( builder, x, y, 0 );
+
+ x = ADD_LONG( x, args[1] );
+ y = ADD_LONG( y, args[2] );
+ cff_builder_add_point( builder, x, y, 0 );
+
+ x = ADD_LONG( x, args[3] );
+ if ( nargs == 1 )
+ y = ADD_LONG( y, args[4] );
+ cff_builder_add_point( builder, x, y, 1 );
+ }
+ args += 4;
+ phase ^= 1;
+ }
+ args = stack;
+ }
+ break;
+
+ case cff_op_rlinecurve:
+ {
+ FT_Int num_lines;
+ FT_Int nargs;
+
+
+ FT_TRACE4(( " rlinecurve\n" ));
+
+ if ( num_args < 8 )
+ goto Stack_Underflow;
+
+ nargs = num_args & ~1;
+ num_lines = ( nargs - 6 ) / 2;
+
+ if ( cff_builder_start_point( builder, x, y ) ||
+ cff_check_points( builder, num_lines + 3 ) )
+ goto Fail;
+
+ args -= nargs;
+
+ /* first, add the line segments */
+ while ( num_lines > 0 )
+ {
+ x = ADD_LONG( x, args[0] );
+ y = ADD_LONG( y, args[1] );
+ cff_builder_add_point( builder, x, y, 1 );
+
+ args += 2;
+ num_lines--;
+ }
+
+ /* then the curve */
+ x = ADD_LONG( x, args[0] );
+ y = ADD_LONG( y, args[1] );
+ cff_builder_add_point( builder, x, y, 0 );
+
+ x = ADD_LONG( x, args[2] );
+ y = ADD_LONG( y, args[3] );
+ cff_builder_add_point( builder, x, y, 0 );
+
+ x = ADD_LONG( x, args[4] );
+ y = ADD_LONG( y, args[5] );
+ cff_builder_add_point( builder, x, y, 1 );
+
+ args = stack;
+ }
+ break;
+
+ case cff_op_rcurveline:
+ {
+ FT_Int num_curves;
+ FT_Int nargs;
+
+
+ FT_TRACE4(( " rcurveline\n" ));
+
+ if ( num_args < 8 )
+ goto Stack_Underflow;
+
+ nargs = num_args - 2;
+ nargs = nargs - nargs % 6 + 2;
+ num_curves = ( nargs - 2 ) / 6;
+
+ if ( cff_builder_start_point( builder, x, y ) ||
+ cff_check_points( builder, num_curves * 3 + 2 ) )
+ goto Fail;
+
+ args -= nargs;
+
+ /* first, add the curves */
+ while ( num_curves > 0 )
+ {
+ x = ADD_LONG( x, args[0] );
+ y = ADD_LONG( y, args[1] );
+ cff_builder_add_point( builder, x, y, 0 );
+
+ x = ADD_LONG( x, args[2] );
+ y = ADD_LONG( y, args[3] );
+ cff_builder_add_point( builder, x, y, 0 );
+
+ x = ADD_LONG( x, args[4] );
+ y = ADD_LONG( y, args[5] );
+ cff_builder_add_point( builder, x, y, 1 );
+
+ args += 6;
+ num_curves--;
+ }
+
+ /* then the final line */
+ x = ADD_LONG( x, args[0] );
+ y = ADD_LONG( y, args[1] );
+ cff_builder_add_point( builder, x, y, 1 );
+
+ args = stack;
+ }
+ break;
+
+ case cff_op_hflex1:
+ {
+ FT_Pos start_y;
+
+
+ FT_TRACE4(( " hflex1\n" ));
+
+ /* adding five more points: 4 control points, 1 on-curve point */
+ /* -- make sure we have enough space for the start point if it */
+ /* needs to be added */
+ if ( cff_builder_start_point( builder, x, y ) ||
+ cff_check_points( builder, 6 ) )
+ goto Fail;
+
+ /* record the starting point's y position for later use */
+ start_y = y;
+
+ /* first control point */
+ x = ADD_LONG( x, args[0] );
+ y = ADD_LONG( y, args[1] );
+ cff_builder_add_point( builder, x, y, 0 );
+
+ /* second control point */
+ x = ADD_LONG( x, args[2] );
+ y = ADD_LONG( y, args[3] );
+ cff_builder_add_point( builder, x, y, 0 );
+
+ /* join point; on curve, with y-value the same as the last */
+ /* control point's y-value */
+ x = ADD_LONG( x, args[4] );
+ cff_builder_add_point( builder, x, y, 1 );
+
+ /* third control point, with y-value the same as the join */
+ /* point's y-value */
+ x = ADD_LONG( x, args[5] );
+ cff_builder_add_point( builder, x, y, 0 );
+
+ /* fourth control point */
+ x = ADD_LONG( x, args[6] );
+ y = ADD_LONG( y, args[7] );
+ cff_builder_add_point( builder, x, y, 0 );
+
+ /* ending point, with y-value the same as the start */
+ x = ADD_LONG( x, args[8] );
+ y = start_y;
+ cff_builder_add_point( builder, x, y, 1 );
+
+ args = stack;
+ break;
+ }
+
+ case cff_op_hflex:
+ {
+ FT_Pos start_y;
+
+
+ FT_TRACE4(( " hflex\n" ));
+
+ /* adding six more points; 4 control points, 2 on-curve points */
+ if ( cff_builder_start_point( builder, x, y ) ||
+ cff_check_points( builder, 6 ) )
+ goto Fail;
+
+ /* record the starting point's y-position for later use */
+ start_y = y;
+
+ /* first control point */
+ x = ADD_LONG( x, args[0] );
+ cff_builder_add_point( builder, x, y, 0 );
+
+ /* second control point */
+ x = ADD_LONG( x, args[1] );
+ y = ADD_LONG( y, args[2] );
+ cff_builder_add_point( builder, x, y, 0 );
+
+ /* join point; on curve, with y-value the same as the last */
+ /* control point's y-value */
+ x = ADD_LONG( x, args[3] );
+ cff_builder_add_point( builder, x, y, 1 );
+
+ /* third control point, with y-value the same as the join */
+ /* point's y-value */
+ x = ADD_LONG( x, args[4] );
+ cff_builder_add_point( builder, x, y, 0 );
+
+ /* fourth control point */
+ x = ADD_LONG( x, args[5] );
+ y = start_y;
+ cff_builder_add_point( builder, x, y, 0 );
+
+ /* ending point, with y-value the same as the start point's */
+ /* y-value -- we don't add this point, though */
+ x = ADD_LONG( x, args[6] );
+ cff_builder_add_point( builder, x, y, 1 );
+
+ args = stack;
+ break;
+ }
+
+ case cff_op_flex1:
+ {
+ FT_Pos start_x, start_y; /* record start x, y values for */
+ /* alter use */
+ FT_Fixed dx = 0, dy = 0; /* used in horizontal/vertical */
+ /* algorithm below */
+ FT_Int horizontal, count;
+ FT_Fixed* temp;
+
+
+ FT_TRACE4(( " flex1\n" ));
+
+ /* adding six more points; 4 control points, 2 on-curve points */
+ if ( cff_builder_start_point( builder, x, y ) ||
+ cff_check_points( builder, 6 ) )
+ goto Fail;
+
+ /* record the starting point's x, y position for later use */
+ start_x = x;
+ start_y = y;
+
+ /* XXX: figure out whether this is supposed to be a horizontal */
+ /* or vertical flex; the Type 2 specification is vague... */
+
+ temp = args;
+
+ /* grab up to the last argument */
+ for ( count = 5; count > 0; count-- )
+ {
+ dx = ADD_LONG( dx, temp[0] );
+ dy = ADD_LONG( dy, temp[1] );
+ temp += 2;
+ }
+
+ if ( dx < 0 )
+ dx = -dx;
+ if ( dy < 0 )
+ dy = -dy;
+
+ /* strange test, but here it is... */
+ horizontal = ( dx > dy );
+
+ for ( count = 5; count > 0; count-- )
+ {
+ x = ADD_LONG( x, args[0] );
+ y = ADD_LONG( y, args[1] );
+ cff_builder_add_point( builder, x, y,
+ (FT_Bool)( count == 3 ) );
+ args += 2;
+ }
+
+ /* is last operand an x- or y-delta? */
+ if ( horizontal )
+ {
+ x = ADD_LONG( x, args[0] );
+ y = start_y;
+ }
+ else
+ {
+ x = start_x;
+ y = ADD_LONG( y, args[0] );
+ }
+
+ cff_builder_add_point( builder, x, y, 1 );
+
+ args = stack;
+ break;
+ }
+
+ case cff_op_flex:
+ {
+ FT_UInt count;
+
+
+ FT_TRACE4(( " flex\n" ));
+
+ if ( cff_builder_start_point( builder, x, y ) ||
+ cff_check_points( builder, 6 ) )
+ goto Fail;
+
+ for ( count = 6; count > 0; count-- )
+ {
+ x = ADD_LONG( x, args[0] );
+ y = ADD_LONG( y, args[1] );
+ cff_builder_add_point( builder, x, y,
+ (FT_Bool)( count == 4 || count == 1 ) );
+ args += 2;
+ }
+
+ args = stack;
+ }
+ break;
+
+ case cff_op_seac:
+ FT_TRACE4(( " seac\n" ));
+
+ error = cff_operator_seac( decoder,
+ args[0], args[1], args[2],
+ (FT_Int)( args[3] >> 16 ),
+ (FT_Int)( args[4] >> 16 ) );
+
+ /* add current outline to the glyph slot */
+ FT_GlyphLoader_Add( builder->loader );
+
+ /* return now! */
+ FT_TRACE4(( "\n" ));
+ return error;
+
+ case cff_op_endchar:
+ /* in dictionaries, `endchar' simply indicates end of data */
+ if ( in_dict )
+ return error;
+
+ FT_TRACE4(( " endchar\n" ));
+
+ /* We are going to emulate the seac operator. */
+ if ( num_args >= 4 )
+ {
+ /* Save glyph width so that the subglyphs don't overwrite it. */
+ FT_Pos glyph_width = decoder->glyph_width;
+
+
+ error = cff_operator_seac( decoder,
+ 0L, args[-4], args[-3],
+ (FT_Int)( args[-2] >> 16 ),
+ (FT_Int)( args[-1] >> 16 ) );
+
+ decoder->glyph_width = glyph_width;
+ }
+ else
+ {
+ cff_builder_close_contour( builder );
+
+ /* close hints recording session */
+ if ( hinter )
+ {
+ if ( hinter->close( hinter->hints,
+ (FT_UInt)builder->current->n_points ) )
+ goto Syntax_Error;
+
+ /* apply hints to the loaded glyph outline now */
+ error = hinter->apply( hinter->hints,
+ builder->current,
+ (PSH_Globals)builder->hints_globals,
+ decoder->hint_mode );
+ if ( error )
+ goto Fail;
+ }
+
+ /* add current outline to the glyph slot */
+ FT_GlyphLoader_Add( builder->loader );
+ }
+
+ /* return now! */
+ FT_TRACE4(( "\n" ));
+ return error;
+
+ case cff_op_abs:
+ FT_TRACE4(( " abs\n" ));
+
+ if ( args[0] < 0 )
+ {
+ if ( args[0] == FT_LONG_MIN )
+ args[0] = FT_LONG_MAX;
+ else
+ args[0] = -args[0];
+ }
+ args++;
+ break;
+
+ case cff_op_add:
+ FT_TRACE4(( " add\n" ));
+
+ args[0] = ADD_LONG( args[0], args[1] );
+ args++;
+ break;
+
+ case cff_op_sub:
+ FT_TRACE4(( " sub\n" ));
+
+ args[0] = SUB_LONG( args[0], args[1] );
+ args++;
+ break;
+
+ case cff_op_div:
+ FT_TRACE4(( " div\n" ));
+
+ args[0] = FT_DivFix( args[0], args[1] );
+ args++;
+ break;
+
+ case cff_op_neg:
+ FT_TRACE4(( " neg\n" ));
+
+ if ( args[0] == FT_LONG_MIN )
+ args[0] = FT_LONG_MAX;
+ args[0] = -args[0];
+ args++;
+ break;
+
+ case cff_op_random:
+ FT_TRACE4(( " random\n" ));
+
+ /* only use the lower 16 bits of `random' */
+ /* to generate a number in the range (0;1] */
+ args[0] = (FT_Fixed)
+ ( ( decoder->current_subfont->random & 0xFFFF ) + 1 );
+ args++;
+
+ decoder->current_subfont->random =
+ cff_random( decoder->current_subfont->random );
+ break;
+
+ case cff_op_mul:
+ FT_TRACE4(( " mul\n" ));
+
+ args[0] = FT_MulFix( args[0], args[1] );
+ args++;
+ break;
+
+ case cff_op_sqrt:
+ FT_TRACE4(( " sqrt\n" ));
+
+ if ( args[0] > 0 )
+ {
+ FT_Fixed root = args[0];
+ FT_Fixed new_root;
+
+
+ for (;;)
+ {
+ new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1;
+ if ( new_root == root )
+ break;
+ root = new_root;
+ }
+ args[0] = new_root;
+ }
+ else
+ args[0] = 0;
+ args++;
+ break;
+
+ case cff_op_drop:
+ /* nothing */
+ FT_TRACE4(( " drop\n" ));
+
+ break;
+
+ case cff_op_exch:
+ {
+ FT_Fixed tmp;
+
+
+ FT_TRACE4(( " exch\n" ));
+
+ tmp = args[0];
+ args[0] = args[1];
+ args[1] = tmp;
+ args += 2;
+ }
+ break;
+
+ case cff_op_index:
+ {
+ FT_Int idx = (FT_Int)( args[0] >> 16 );
+
+
+ FT_TRACE4(( " index\n" ));
+
+ if ( idx < 0 )
+ idx = 0;
+ else if ( idx > num_args - 2 )
+ idx = num_args - 2;
+ args[0] = args[-( idx + 1 )];
+ args++;
+ }
+ break;
+
+ case cff_op_roll:
+ {
+ FT_Int count = (FT_Int)( args[0] >> 16 );
+ FT_Int idx = (FT_Int)( args[1] >> 16 );
+
+
+ FT_TRACE4(( " roll\n" ));
+
+ if ( count <= 0 )
+ count = 1;
+
+ args -= count;
+ if ( args < stack )
+ goto Stack_Underflow;
+
+ if ( idx >= 0 )
+ {
+ while ( idx > 0 )
+ {
+ FT_Fixed tmp = args[count - 1];
+ FT_Int i;
+
+
+ for ( i = count - 2; i >= 0; i-- )
+ args[i + 1] = args[i];
+ args[0] = tmp;
+ idx--;
+ }
+ }
+ else
+ {
+ while ( idx < 0 )
+ {
+ FT_Fixed tmp = args[0];
+ FT_Int i;
+
+
+ for ( i = 0; i < count - 1; i++ )
+ args[i] = args[i + 1];
+ args[count - 1] = tmp;
+ idx++;
+ }
+ }
+ args += count;
+ }
+ break;
+
+ case cff_op_dup:
+ FT_TRACE4(( " dup\n" ));
+
+ args[1] = args[0];
+ args += 2;
+ break;
+
+ case cff_op_put:
+ {
+ FT_Fixed val = args[0];
+ FT_Int idx = (FT_Int)( args[1] >> 16 );
+
+
+ FT_TRACE4(( " put\n" ));
+
+ /* the Type2 specification before version 16-March-2000 */
+ /* didn't give a hard-coded size limit of the temporary */
+ /* storage array; instead, an argument of the */
+ /* `MultipleMaster' operator set the size */
+ if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS )
+ decoder->buildchar[idx] = val;
+ }
+ break;
+
+ case cff_op_get:
+ {
+ FT_Int idx = (FT_Int)( args[0] >> 16 );
+ FT_Fixed val = 0;
+
+
+ FT_TRACE4(( " get\n" ));
+
+ if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS )
+ val = decoder->buildchar[idx];
+
+ args[0] = val;
+ args++;
+ }
+ break;
+
+ case cff_op_store:
+ /* this operator was removed from the Type2 specification */
+ /* in version 16-March-2000 */
+
+ /* since we currently don't handle interpolation of multiple */
+ /* master fonts, this is a no-op */
+ FT_TRACE4(( " store\n" ));
+ break;
+
+ case cff_op_load:
+ /* this operator was removed from the Type2 specification */
+ /* in version 16-March-2000 */
+ {
+ FT_Int reg_idx = (FT_Int)args[0];
+ FT_Int idx = (FT_Int)args[1];
+ FT_Int count = (FT_Int)args[2];
+
+
+ FT_TRACE4(( " load\n" ));
+
+ /* since we currently don't handle interpolation of multiple */
+ /* master fonts, we store a vector [1 0 0 ...] in the */
+ /* temporary storage array regardless of the Registry index */
+ if ( reg_idx >= 0 && reg_idx <= 2 &&
+ idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS &&
+ count >= 0 && count <= num_axes )
+ {
+ FT_Int end, i;
+
+
+ end = FT_MIN( idx + count, CFF_MAX_TRANS_ELEMENTS );
+
+ if ( idx < end )
+ decoder->buildchar[idx] = 1 << 16;
+
+ for ( i = idx + 1; i < end; i++ )
+ decoder->buildchar[i] = 0;
+ }
+ }
+ break;
+
+ case cff_op_blend:
+ /* this operator was removed from the Type2 specification */
+ /* in version 16-March-2000 */
+ {
+ FT_Int num_results = (FT_Int)( args[0] >> 16 );
+
+
+ FT_TRACE4(( " blend\n" ));
+
+ if ( num_results < 0 )
+ goto Syntax_Error;
+
+ if ( num_results * (FT_Int)num_designs > num_args )
+ goto Stack_Underflow;
+
+ /* since we currently don't handle interpolation of multiple */
+ /* master fonts, return the `num_results' values of the */
+ /* first master */
+ args -= num_results * ( num_designs - 1 );
+ num_args -= num_results * ( num_designs - 1 );
+ }
+ break;
+
+ case cff_op_dotsection:
+ /* this operator is deprecated and ignored by the parser */
+ FT_TRACE4(( " dotsection\n" ));
+ break;
+
+ case cff_op_closepath:
+ /* this is an invalid Type 2 operator; however, there */
+ /* exist fonts which are incorrectly converted from probably */
+ /* Type 1 to CFF, and some parsers seem to accept it */
+
+ FT_TRACE4(( " closepath (invalid op)\n" ));
+
+ args = stack;
+ break;
+
+ case cff_op_hsbw:
+ /* this is an invalid Type 2 operator; however, there */
+ /* exist fonts which are incorrectly converted from probably */
+ /* Type 1 to CFF, and some parsers seem to accept it */
+
+ FT_TRACE4(( " hsbw (invalid op)\n" ));
+
+ decoder->glyph_width =
+ ADD_LONG( decoder->nominal_width, ( args[1] >> 16 ) );
+
+ decoder->builder.left_bearing.x = args[0];
+ decoder->builder.left_bearing.y = 0;
+
+ x = ADD_LONG( decoder->builder.pos_x, args[0] );
+ y = decoder->builder.pos_y;
+ args = stack;
+ break;
+
+ case cff_op_sbw:
+ /* this is an invalid Type 2 operator; however, there */
+ /* exist fonts which are incorrectly converted from probably */
+ /* Type 1 to CFF, and some parsers seem to accept it */
+
+ FT_TRACE4(( " sbw (invalid op)\n" ));
+
+ decoder->glyph_width =
+ ADD_LONG( decoder->nominal_width, ( args[2] >> 16 ) );
+
+ decoder->builder.left_bearing.x = args[0];
+ decoder->builder.left_bearing.y = args[1];
+
+ x = ADD_LONG( decoder->builder.pos_x, args[0] );
+ y = ADD_LONG( decoder->builder.pos_y, args[1] );
+ args = stack;
+ break;
+
+ case cff_op_setcurrentpoint:
+ /* this is an invalid Type 2 operator; however, there */
+ /* exist fonts which are incorrectly converted from probably */
+ /* Type 1 to CFF, and some parsers seem to accept it */
+
+ FT_TRACE4(( " setcurrentpoint (invalid op)\n" ));
+
+ x = ADD_LONG( decoder->builder.pos_x, args[0] );
+ y = ADD_LONG( decoder->builder.pos_y, args[1] );
+ args = stack;
+ break;
+
+ case cff_op_callothersubr:
+ /* this is an invalid Type 2 operator; however, there */
+ /* exist fonts which are incorrectly converted from probably */
+ /* Type 1 to CFF, and some parsers seem to accept it */
+
+ FT_TRACE4(( " callothersubr (invalid op)\n" ));
+
+ /* subsequent `pop' operands should add the arguments, */
+ /* this is the implementation described for `unknown' other */
+ /* subroutines in the Type1 spec. */
+ /* */
+ /* XXX Fix return arguments (see discussion below). */
+ args -= 2 + ( args[-2] >> 16 );
+ if ( args < stack )
+ goto Stack_Underflow;
+ break;
+
+ case cff_op_pop:
+ /* this is an invalid Type 2 operator; however, there */
+ /* exist fonts which are incorrectly converted from probably */
+ /* Type 1 to CFF, and some parsers seem to accept it */
+
+ FT_TRACE4(( " pop (invalid op)\n" ));
+
+ /* XXX Increasing `args' is wrong: After a certain number of */
+ /* `pop's we get a stack overflow. Reason for doing it is */
+ /* code like this (actually found in a CFF font): */
+ /* */
+ /* 17 1 3 callothersubr */
+ /* pop */
+ /* callsubr */
+ /* */
+ /* Since we handle `callothersubr' as a no-op, and */
+ /* `callsubr' needs at least one argument, `pop' can't be a */
+ /* no-op too as it basically should be. */
+ /* */
+ /* The right solution would be to provide real support for */
+ /* `callothersubr' as done in `t1decode.c', however, given */
+ /* the fact that CFF fonts with `pop' are invalid, it is */
+ /* questionable whether it is worth the time. */
+ args++;
+ break;
+
+ case cff_op_and:
+ {
+ FT_Fixed cond = ( args[0] && args[1] );
+
+
+ FT_TRACE4(( " and\n" ));
+
+ args[0] = cond ? 0x10000L : 0;
+ args++;
+ }
+ break;
+
+ case cff_op_or:
+ {
+ FT_Fixed cond = ( args[0] || args[1] );
+
+
+ FT_TRACE4(( " or\n" ));
+
+ args[0] = cond ? 0x10000L : 0;
+ args++;
+ }
+ break;
+
+ case cff_op_not:
+ {
+ FT_Fixed cond = !args[0];
+
+
+ FT_TRACE4(( " not\n" ));
+
+ args[0] = cond ? 0x10000L : 0;
+ args++;
+ }
+ break;
+
+ case cff_op_eq:
+ {
+ FT_Fixed cond = ( args[0] == args[1] );
+
+
+ FT_TRACE4(( " eq\n" ));
+
+ args[0] = cond ? 0x10000L : 0;
+ args++;
+ }
+ break;
+
+ case cff_op_ifelse:
+ {
+ FT_Fixed cond = ( args[2] <= args[3] );
+
+
+ FT_TRACE4(( " ifelse\n" ));
+
+ if ( !cond )
+ args[0] = args[1];
+ args++;
+ }
+ break;
+
+ case cff_op_callsubr:
+ {
+ FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) +
+ decoder->locals_bias );
+
+
+ FT_TRACE4(( " callsubr (idx %d, entering level %d)\n",
+ idx,
+ zone - decoder->zones + 1 ));
+
+ if ( idx >= decoder->num_locals )
+ {
+ FT_ERROR(( "cff_decoder_parse_charstrings:"
+ " invalid local subr index\n" ));
+ goto Syntax_Error;
+ }
+
+ if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
+ {
+ FT_ERROR(( "cff_decoder_parse_charstrings:"
+ " too many nested subrs\n" ));
+ goto Syntax_Error;
+ }
+
+ zone->cursor = ip; /* save current instruction pointer */
+
+ zone++;
+ zone->base = decoder->locals[idx];
+ zone->limit = decoder->locals[idx + 1];
+ zone->cursor = zone->base;
+
+ if ( !zone->base || zone->limit == zone->base )
+ {
+ FT_ERROR(( "cff_decoder_parse_charstrings:"
+ " invoking empty subrs\n" ));
+ goto Syntax_Error;
+ }
+
+ decoder->zone = zone;
+ ip = zone->base;
+ limit = zone->limit;
+ }
+ break;
+
+ case cff_op_callgsubr:
+ {
+ FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) +
+ decoder->globals_bias );
+
+
+ FT_TRACE4(( " callgsubr (idx %d, entering level %d)\n",
+ idx,
+ zone - decoder->zones + 1 ));
+
+ if ( idx >= decoder->num_globals )
+ {
+ FT_ERROR(( "cff_decoder_parse_charstrings:"
+ " invalid global subr index\n" ));
+ goto Syntax_Error;
+ }
+
+ if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
+ {
+ FT_ERROR(( "cff_decoder_parse_charstrings:"
+ " too many nested subrs\n" ));
+ goto Syntax_Error;
+ }
+
+ zone->cursor = ip; /* save current instruction pointer */
+
+ zone++;
+ zone->base = decoder->globals[idx];
+ zone->limit = decoder->globals[idx + 1];
+ zone->cursor = zone->base;
+
+ if ( !zone->base || zone->limit == zone->base )
+ {
+ FT_ERROR(( "cff_decoder_parse_charstrings:"
+ " invoking empty subrs\n" ));
+ goto Syntax_Error;
+ }
+
+ decoder->zone = zone;
+ ip = zone->base;
+ limit = zone->limit;
+ }
+ break;
+
+ case cff_op_return:
+ FT_TRACE4(( " return (leaving level %d)\n",
+ decoder->zone - decoder->zones ));
+
+ if ( decoder->zone <= decoder->zones )
+ {
+ FT_ERROR(( "cff_decoder_parse_charstrings:"
+ " unexpected return\n" ));
+ goto Syntax_Error;
+ }
+
+ decoder->zone--;
+ zone = decoder->zone;
+ ip = zone->cursor;
+ limit = zone->limit;
+ break;
+
+ default:
+ FT_ERROR(( "Unimplemented opcode: %d", ip[-1] ));
+
+ if ( ip[-1] == 12 )
+ FT_ERROR(( " %d", ip[0] ));
+ FT_ERROR(( "\n" ));
+
+ return FT_THROW( Unimplemented_Feature );
+ }
+
+ decoder->top = args;
+
+ if ( decoder->top - stack >= CFF_MAX_OPERANDS )
+ goto Stack_Overflow;
+
+ } /* general operator processing */
+
+ } /* while ip < limit */
+
+ FT_TRACE4(( "..end..\n\n" ));
+
+ Fail:
+ return error;
+
+ MM_Error:
+ FT_TRACE4(( "cff_decoder_parse_charstrings:"
+ " invalid opcode found in top DICT charstring\n"));
+ return FT_THROW( Invalid_File_Format );
+
+ Syntax_Error:
+ FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error\n" ));
+ return FT_THROW( Invalid_File_Format );
+
+ Stack_Underflow:
+ FT_TRACE4(( "cff_decoder_parse_charstrings: stack underflow\n" ));
+ return FT_THROW( Too_Few_Arguments );
+
+ Stack_Overflow:
+ FT_TRACE4(( "cff_decoder_parse_charstrings: stack overflow\n" ));
+ return FT_THROW( Stack_Overflow );
+ }
+
+#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* cff_decoder_init */
+ /* */
+ /* <Description> */
+ /* Initializes a given glyph decoder. */
+ /* */
+ /* <InOut> */
+ /* decoder :: A pointer to the glyph builder to initialize. */
+ /* */
+ /* <Input> */
+ /* face :: The current face object. */
+ /* */
+ /* size :: The current size object. */
+ /* */
+ /* slot :: The current glyph object. */
+ /* */
+ /* hinting :: Whether hinting is active. */
+ /* */
+ /* hint_mode :: The hinting mode. */
+ /* */
+ FT_LOCAL_DEF( void )
+ cff_decoder_init( CFF_Decoder* decoder,
+ TT_Face face,
+ CFF_Size size,
+ CFF_GlyphSlot slot,
+ FT_Bool hinting,
+ FT_Render_Mode hint_mode,
+ CFF_Decoder_Get_Glyph_Callback get_callback,
+ CFF_Decoder_Free_Glyph_Callback free_callback )
+ {
+ CFF_Font cff = (CFF_Font)face->extra.data;
+
+
+ /* clear everything */
+ FT_ZERO( decoder );
+
+ /* initialize builder */
+ cff_builder_init( &decoder->builder, face, size, slot, hinting );
+
+ /* initialize Type2 decoder */
+ decoder->cff = cff;
+ decoder->num_globals = cff->global_subrs_index.count;
+ decoder->globals = cff->global_subrs;
+ decoder->globals_bias = cff_compute_bias(
+ cff->top_font.font_dict.charstring_type,
+ decoder->num_globals );
+
+ decoder->hint_mode = hint_mode;
+
+ decoder->get_glyph_callback = get_callback;
+ decoder->free_glyph_callback = free_callback;
+ }
+
+
+ /* this function is used to select the subfont */
+ /* and the locals subrs array */
+ FT_LOCAL_DEF( FT_Error )
+ cff_decoder_prepare( CFF_Decoder* decoder,
+ CFF_Size size,
+ FT_UInt glyph_index )
+ {
+ CFF_Builder *builder = &decoder->builder;
+ CFF_Font cff = (CFF_Font)builder->face->extra.data;
+ CFF_SubFont sub = &cff->top_font;
+ FT_Error error = FT_Err_Ok;
+
+ FT_Service_CFFLoad cffload = (FT_Service_CFFLoad)cff->cffload;
+
+
+ /* manage CID fonts */
+ if ( cff->num_subfonts )
+ {
+ FT_Byte fd_index = cffload->fd_select_get( &cff->fd_select,
+ glyph_index );
+
+
+ if ( fd_index >= cff->num_subfonts )
+ {
+ FT_TRACE4(( "cff_decoder_prepare: invalid CID subfont index\n" ));
+ error = FT_THROW( Invalid_File_Format );
+ goto Exit;
+ }
+
+ FT_TRACE3(( " in subfont %d:\n", fd_index ));
+
+ sub = cff->subfonts[fd_index];
+
+ if ( builder->hints_funcs && size )
+ {
+ FT_Size ftsize = FT_SIZE( size );
+ CFF_Internal internal = (CFF_Internal)ftsize->internal->module_data;
+
+
+ /* for CFFs without subfonts, this value has already been set */
+ builder->hints_globals = (void *)internal->subfonts[fd_index];
+ }
+ }
+
+ decoder->num_locals = sub->local_subrs_index.count;
+ decoder->locals = sub->local_subrs;
+ decoder->locals_bias = cff_compute_bias(
+ decoder->cff->top_font.font_dict.charstring_type,
+ decoder->num_locals );
+
+ decoder->glyph_width = sub->private_dict.default_width;
+ decoder->nominal_width = sub->private_dict.nominal_width;
+
+ decoder->current_subfont = sub;
+
+ Exit:
+ return error;
+ }
+
+
+/* END */
diff --git a/thirdparty/freetype/src/psaux/cffdecode.h b/thirdparty/freetype/src/psaux/cffdecode.h
new file mode 100644
index 0000000000..0d4f5fef63
--- /dev/null
+++ b/thirdparty/freetype/src/psaux/cffdecode.h
@@ -0,0 +1,64 @@
+/***************************************************************************/
+/* */
+/* cffdecode.h */
+/* */
+/* PostScript CFF (Type 2) decoding routines (specification). */
+/* */
+/* Copyright 2017-2018 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef CFFDECODE_H_
+#define CFFDECODE_H_
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+
+
+FT_BEGIN_HEADER
+
+ FT_LOCAL( void )
+ cff_decoder_init( CFF_Decoder* decoder,
+ TT_Face face,
+ CFF_Size size,
+ CFF_GlyphSlot slot,
+ FT_Bool hinting,
+ FT_Render_Mode hint_mode,
+ CFF_Decoder_Get_Glyph_Callback get_callback,
+ CFF_Decoder_Free_Glyph_Callback free_callback );
+
+ FT_LOCAL( FT_Error )
+ cff_decoder_prepare( CFF_Decoder* decoder,
+ CFF_Size size,
+ FT_UInt glyph_index );
+
+
+ FT_LOCAL( FT_Int )
+ cff_lookup_glyph_by_stdcharcode( CFF_Font cff,
+ FT_Int charcode );
+
+
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+ FT_LOCAL( FT_Error )
+ cff_decoder_parse_charstrings( CFF_Decoder* decoder,
+ FT_Byte* charstring_base,
+ FT_ULong charstring_len,
+ FT_Bool in_dict );
+#endif
+
+
+FT_END_HEADER
+
+#endif
+
+
+/* END */
diff --git a/thirdparty/freetype/src/psaux/module.mk b/thirdparty/freetype/src/psaux/module.mk
index c70a227166..6584d075a2 100644
--- a/thirdparty/freetype/src/psaux/module.mk
+++ b/thirdparty/freetype/src/psaux/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2017 by
+# Copyright 1996-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/psaux/psarrst.c b/thirdparty/freetype/src/psaux/psarrst.c
new file mode 100644
index 0000000000..a8780947f9
--- /dev/null
+++ b/thirdparty/freetype/src/psaux/psarrst.c
@@ -0,0 +1,241 @@
+/***************************************************************************/
+/* */
+/* psarrst.c */
+/* */
+/* Adobe's code for Array Stacks (body). */
+/* */
+/* Copyright 2007-2013 Adobe Systems Incorporated. */
+/* */
+/* This software, and all works of authorship, whether in source or */
+/* object code form as indicated by the copyright notice(s) included */
+/* herein (collectively, the "Work") is made available, and may only be */
+/* used, modified, and distributed under the FreeType Project License, */
+/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
+/* FreeType Project License, each contributor to the Work hereby grants */
+/* to any individual or legal entity exercising permissions granted by */
+/* the FreeType Project License and this section (hereafter, "You" or */
+/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
+/* royalty-free, irrevocable (except as stated in this section) patent */
+/* license to make, have made, use, offer to sell, sell, import, and */
+/* otherwise transfer the Work, where such license applies only to those */
+/* patent claims licensable by such contributor that are necessarily */
+/* infringed by their contribution(s) alone or by combination of their */
+/* contribution(s) with the Work to which such contribution(s) was */
+/* submitted. If You institute patent litigation against any entity */
+/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
+/* the Work or a contribution incorporated within the Work constitutes */
+/* direct or contributory patent infringement, then any patent licenses */
+/* granted to You under this License for that Work shall terminate as of */
+/* the date such litigation is filed. */
+/* */
+/* By using, modifying, or distributing the Work you indicate that you */
+/* have read and understood the terms and conditions of the */
+/* FreeType Project License as well as those provided in this section, */
+/* and you accept them fully. */
+/* */
+/***************************************************************************/
+
+
+#include "psft.h"
+#include FT_INTERNAL_DEBUG_H
+
+#include "psglue.h"
+#include "psarrst.h"
+
+#include "pserror.h"
+
+
+ /*
+ * CF2_ArrStack uses an error pointer, to enable shared errors.
+ * Shared errors are necessary when multiple objects allow the program
+ * to continue after detecting errors. Only the first error should be
+ * recorded.
+ */
+
+ FT_LOCAL_DEF( void )
+ cf2_arrstack_init( CF2_ArrStack arrstack,
+ FT_Memory memory,
+ FT_Error* error,
+ size_t sizeItem )
+ {
+ FT_ASSERT( arrstack );
+
+ /* initialize the structure */
+ arrstack->memory = memory;
+ arrstack->error = error;
+ arrstack->sizeItem = sizeItem;
+ arrstack->allocated = 0;
+ arrstack->chunk = 10; /* chunks of 10 items */
+ arrstack->count = 0;
+ arrstack->totalSize = 0;
+ arrstack->ptr = NULL;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cf2_arrstack_finalize( CF2_ArrStack arrstack )
+ {
+ FT_Memory memory = arrstack->memory; /* for FT_FREE */
+
+
+ FT_ASSERT( arrstack );
+
+ arrstack->allocated = 0;
+ arrstack->count = 0;
+ arrstack->totalSize = 0;
+
+ /* free the data buffer */
+ FT_FREE( arrstack->ptr );
+ }
+
+
+ /* allocate or reallocate the buffer size; */
+ /* return false on memory error */
+ static FT_Bool
+ cf2_arrstack_setNumElements( CF2_ArrStack arrstack,
+ size_t numElements )
+ {
+ FT_ASSERT( arrstack );
+
+ {
+ FT_Error error = FT_Err_Ok; /* for FT_REALLOC */
+ FT_Memory memory = arrstack->memory; /* for FT_REALLOC */
+
+ size_t newSize = numElements * arrstack->sizeItem;
+
+
+ if ( numElements > FT_LONG_MAX / arrstack->sizeItem )
+ goto exit;
+
+
+ FT_ASSERT( newSize > 0 ); /* avoid realloc with zero size */
+
+ if ( !FT_REALLOC( arrstack->ptr, arrstack->totalSize, newSize ) )
+ {
+ arrstack->allocated = numElements;
+ arrstack->totalSize = newSize;
+
+ if ( arrstack->count > numElements )
+ {
+ /* we truncated the list! */
+ CF2_SET_ERROR( arrstack->error, Stack_Overflow );
+ arrstack->count = numElements;
+ return FALSE;
+ }
+
+ return TRUE; /* success */
+ }
+ }
+
+ exit:
+ /* if there's not already an error, store this one */
+ CF2_SET_ERROR( arrstack->error, Out_Of_Memory );
+
+ return FALSE;
+ }
+
+
+ /* set the count, ensuring allocation is sufficient */
+ FT_LOCAL_DEF( void )
+ cf2_arrstack_setCount( CF2_ArrStack arrstack,
+ size_t numElements )
+ {
+ FT_ASSERT( arrstack );
+
+ if ( numElements > arrstack->allocated )
+ {
+ /* expand the allocation first */
+ if ( !cf2_arrstack_setNumElements( arrstack, numElements ) )
+ return;
+ }
+
+ arrstack->count = numElements;
+ }
+
+
+ /* clear the count */
+ FT_LOCAL_DEF( void )
+ cf2_arrstack_clear( CF2_ArrStack arrstack )
+ {
+ FT_ASSERT( arrstack );
+
+ arrstack->count = 0;
+ }
+
+
+ /* current number of items */
+ FT_LOCAL_DEF( size_t )
+ cf2_arrstack_size( const CF2_ArrStack arrstack )
+ {
+ FT_ASSERT( arrstack );
+
+ return arrstack->count;
+ }
+
+
+ FT_LOCAL_DEF( void* )
+ cf2_arrstack_getBuffer( const CF2_ArrStack arrstack )
+ {
+ FT_ASSERT( arrstack );
+
+ return arrstack->ptr;
+ }
+
+
+ /* return pointer to the given element */
+ FT_LOCAL_DEF( void* )
+ cf2_arrstack_getPointer( const CF2_ArrStack arrstack,
+ size_t idx )
+ {
+ void* newPtr;
+
+
+ FT_ASSERT( arrstack );
+
+ if ( idx >= arrstack->count )
+ {
+ /* overflow */
+ CF2_SET_ERROR( arrstack->error, Stack_Overflow );
+ idx = 0; /* choose safe default */
+ }
+
+ newPtr = (FT_Byte*)arrstack->ptr + idx * arrstack->sizeItem;
+
+ return newPtr;
+ }
+
+
+ /* push (append) an element at the end of the list; */
+ /* return false on memory error */
+ /* TODO: should there be a length param for extra checking? */
+ FT_LOCAL_DEF( void )
+ cf2_arrstack_push( CF2_ArrStack arrstack,
+ const void* ptr )
+ {
+ FT_ASSERT( arrstack );
+
+ if ( arrstack->count == arrstack->allocated )
+ {
+ /* grow the buffer by one chunk */
+ if ( !cf2_arrstack_setNumElements(
+ arrstack, arrstack->allocated + arrstack->chunk ) )
+ {
+ /* on error, ignore the push */
+ return;
+ }
+ }
+
+ FT_ASSERT( ptr );
+
+ {
+ size_t offset = arrstack->count * arrstack->sizeItem;
+ void* newPtr = (FT_Byte*)arrstack->ptr + offset;
+
+
+ FT_MEM_COPY( newPtr, ptr, arrstack->sizeItem );
+ arrstack->count += 1;
+ }
+ }
+
+
+/* END */
diff --git a/thirdparty/freetype/src/psaux/psarrst.h b/thirdparty/freetype/src/psaux/psarrst.h
new file mode 100644
index 0000000000..b3568eb61f
--- /dev/null
+++ b/thirdparty/freetype/src/psaux/psarrst.h
@@ -0,0 +1,100 @@
+/***************************************************************************/
+/* */
+/* psarrst.h */
+/* */
+/* Adobe's code for Array Stacks (specification). */
+/* */
+/* Copyright 2007-2013 Adobe Systems Incorporated. */
+/* */
+/* This software, and all works of authorship, whether in source or */
+/* object code form as indicated by the copyright notice(s) included */
+/* herein (collectively, the "Work") is made available, and may only be */
+/* used, modified, and distributed under the FreeType Project License, */
+/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
+/* FreeType Project License, each contributor to the Work hereby grants */
+/* to any individual or legal entity exercising permissions granted by */
+/* the FreeType Project License and this section (hereafter, "You" or */
+/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
+/* royalty-free, irrevocable (except as stated in this section) patent */
+/* license to make, have made, use, offer to sell, sell, import, and */
+/* otherwise transfer the Work, where such license applies only to those */
+/* patent claims licensable by such contributor that are necessarily */
+/* infringed by their contribution(s) alone or by combination of their */
+/* contribution(s) with the Work to which such contribution(s) was */
+/* submitted. If You institute patent litigation against any entity */
+/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
+/* the Work or a contribution incorporated within the Work constitutes */
+/* direct or contributory patent infringement, then any patent licenses */
+/* granted to You under this License for that Work shall terminate as of */
+/* the date such litigation is filed. */
+/* */
+/* By using, modifying, or distributing the Work you indicate that you */
+/* have read and understood the terms and conditions of the */
+/* FreeType Project License as well as those provided in this section, */
+/* and you accept them fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef PSARRST_H_
+#define PSARRST_H_
+
+
+#include "pserror.h"
+
+
+FT_BEGIN_HEADER
+
+
+ /* need to define the struct here (not opaque) so it can be allocated by */
+ /* clients */
+ typedef struct CF2_ArrStackRec_
+ {
+ FT_Memory memory;
+ FT_Error* error;
+
+ size_t sizeItem; /* bytes per element */
+ size_t allocated; /* items allocated */
+ size_t chunk; /* allocation increment in items */
+ size_t count; /* number of elements allocated */
+ size_t totalSize; /* total bytes allocated */
+
+ void* ptr; /* ptr to data */
+
+ } CF2_ArrStackRec, *CF2_ArrStack;
+
+
+ FT_LOCAL( void )
+ cf2_arrstack_init( CF2_ArrStack arrstack,
+ FT_Memory memory,
+ FT_Error* error,
+ size_t sizeItem );
+ FT_LOCAL( void )
+ cf2_arrstack_finalize( CF2_ArrStack arrstack );
+
+ FT_LOCAL( void )
+ cf2_arrstack_setCount( CF2_ArrStack arrstack,
+ size_t numElements );
+ FT_LOCAL( void )
+ cf2_arrstack_clear( CF2_ArrStack arrstack );
+ FT_LOCAL( size_t )
+ cf2_arrstack_size( const CF2_ArrStack arrstack );
+
+ FT_LOCAL( void* )
+ cf2_arrstack_getBuffer( const CF2_ArrStack arrstack );
+ FT_LOCAL( void* )
+ cf2_arrstack_getPointer( const CF2_ArrStack arrstack,
+ size_t idx );
+
+ FT_LOCAL( void )
+ cf2_arrstack_push( CF2_ArrStack arrstack,
+ const void* ptr );
+
+
+FT_END_HEADER
+
+
+#endif /* PSARRST_H_ */
+
+
+/* END */
diff --git a/thirdparty/freetype/src/psaux/psaux.c b/thirdparty/freetype/src/psaux/psaux.c
index c373aa7d5b..fb447fcdbb 100644
--- a/thirdparty/freetype/src/psaux/psaux.c
+++ b/thirdparty/freetype/src/psaux/psaux.c
@@ -4,7 +4,7 @@
/* */
/* FreeType auxiliary PostScript driver component (body only). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -25,6 +25,17 @@
#include "psobjs.c"
#include "t1cmap.c"
#include "t1decode.c"
+#include "cffdecode.c"
+
+#include "psarrst.c"
+#include "psblues.c"
+#include "pserror.c"
+#include "psfont.c"
+#include "psft.c"
+#include "pshints.c"
+#include "psintrp.c"
+#include "psread.c"
+#include "psstack.c"
/* END */
diff --git a/thirdparty/freetype/src/psaux/psauxerr.h b/thirdparty/freetype/src/psaux/psauxerr.h
index 1d7ac6001b..cc33fd2eea 100644
--- a/thirdparty/freetype/src/psaux/psauxerr.h
+++ b/thirdparty/freetype/src/psaux/psauxerr.h
@@ -4,7 +4,7 @@
/* */
/* PS auxiliary module error codes (specification only). */
/* */
-/* Copyright 2001-2017 by */
+/* Copyright 2001-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/psaux/psauxmod.c b/thirdparty/freetype/src/psaux/psauxmod.c
index 1f589cefc2..ee497085cc 100644
--- a/thirdparty/freetype/src/psaux/psauxmod.c
+++ b/thirdparty/freetype/src/psaux/psauxmod.c
@@ -4,7 +4,7 @@
/* */
/* FreeType auxiliary PostScript module implementation (body). */
/* */
-/* Copyright 2000-2017 by */
+/* Copyright 2000-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -21,6 +21,8 @@
#include "psobjs.h"
#include "t1decode.h"
#include "t1cmap.h"
+#include "psft.h"
+#include "cffdecode.h"
#ifndef T1_CONFIG_OPTION_NO_AFM
#include "afmparse.h"
@@ -60,6 +62,14 @@
FT_CALLBACK_TABLE_DEF
+ const PS_Builder_FuncsRec ps_builder_funcs =
+ {
+ ps_builder_init, /* init */
+ ps_builder_done /* done */
+ };
+
+
+ FT_CALLBACK_TABLE_DEF
const T1_Builder_FuncsRec t1_builder_funcs =
{
t1_builder_init, /* init */
@@ -77,9 +87,14 @@
FT_CALLBACK_TABLE_DEF
const T1_Decoder_FuncsRec t1_decoder_funcs =
{
- t1_decoder_init, /* init */
- t1_decoder_done, /* done */
- t1_decoder_parse_charstrings /* parse_charstrings */
+ t1_decoder_init, /* init */
+ t1_decoder_done, /* done */
+#ifdef T1_CONFIG_OPTION_OLD_ENGINE
+ t1_decoder_parse_charstrings, /* parse_charstrings_old */
+#else
+ t1_decoder_parse_metrics, /* parse_metrics */
+#endif
+ cf2_decoder_parse_charstrings /* parse_charstrings */
};
@@ -104,6 +119,34 @@
};
+ FT_CALLBACK_TABLE_DEF
+ const CFF_Builder_FuncsRec cff_builder_funcs =
+ {
+ cff_builder_init, /* init */
+ cff_builder_done, /* done */
+
+ cff_check_points, /* check_points */
+ cff_builder_add_point, /* add_point */
+ cff_builder_add_point1, /* add_point1 */
+ cff_builder_add_contour, /* add_contour */
+ cff_builder_start_point, /* start_point */
+ cff_builder_close_contour /* close_contour */
+ };
+
+
+ FT_CALLBACK_TABLE_DEF
+ const CFF_Decoder_FuncsRec cff_decoder_funcs =
+ {
+ cff_decoder_init, /* init */
+ cff_decoder_prepare, /* prepare */
+
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+ cff_decoder_parse_charstrings, /* parse_charstrings_old */
+#endif
+ cf2_decoder_parse_charstrings /* parse_charstrings */
+ };
+
+
static
const PSAux_Interface psaux_interface =
{
@@ -112,6 +155,9 @@
&t1_builder_funcs,
&t1_decoder_funcs,
t1_decrypt,
+ cff_random,
+ ps_decoder_init,
+ t1_make_subfont,
(const T1_CMap_ClassesRec*) &t1_cmap_classes,
@@ -120,6 +166,8 @@
#else
0,
#endif
+
+ &cff_decoder_funcs,
};
diff --git a/thirdparty/freetype/src/psaux/psauxmod.h b/thirdparty/freetype/src/psaux/psauxmod.h
index 926f37eba5..f30978f022 100644
--- a/thirdparty/freetype/src/psaux/psauxmod.h
+++ b/thirdparty/freetype/src/psaux/psauxmod.h
@@ -4,7 +4,7 @@
/* */
/* FreeType auxiliary PostScript module implementation (specification). */
/* */
-/* Copyright 2000-2017 by */
+/* Copyright 2000-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -23,6 +23,8 @@
#include <ft2build.h>
#include FT_MODULE_H
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+
FT_BEGIN_HEADER
@@ -31,6 +33,13 @@ FT_BEGIN_HEADER
#endif
+ FT_CALLBACK_TABLE
+ const CFF_Builder_FuncsRec cff_builder_funcs;
+
+ FT_CALLBACK_TABLE
+ const PS_Builder_FuncsRec ps_builder_funcs;
+
+
FT_EXPORT_VAR( const FT_Module_Class ) psaux_driver_class;
diff --git a/thirdparty/freetype/src/psaux/psblues.c b/thirdparty/freetype/src/psaux/psblues.c
new file mode 100644
index 0000000000..ae39d03c77
--- /dev/null
+++ b/thirdparty/freetype/src/psaux/psblues.c
@@ -0,0 +1,582 @@
+/***************************************************************************/
+/* */
+/* psblues.c */
+/* */
+/* Adobe's code for handling Blue Zones (body). */
+/* */
+/* Copyright 2009-2014 Adobe Systems Incorporated. */
+/* */
+/* This software, and all works of authorship, whether in source or */
+/* object code form as indicated by the copyright notice(s) included */
+/* herein (collectively, the "Work") is made available, and may only be */
+/* used, modified, and distributed under the FreeType Project License, */
+/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
+/* FreeType Project License, each contributor to the Work hereby grants */
+/* to any individual or legal entity exercising permissions granted by */
+/* the FreeType Project License and this section (hereafter, "You" or */
+/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
+/* royalty-free, irrevocable (except as stated in this section) patent */
+/* license to make, have made, use, offer to sell, sell, import, and */
+/* otherwise transfer the Work, where such license applies only to those */
+/* patent claims licensable by such contributor that are necessarily */
+/* infringed by their contribution(s) alone or by combination of their */
+/* contribution(s) with the Work to which such contribution(s) was */
+/* submitted. If You institute patent litigation against any entity */
+/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
+/* the Work or a contribution incorporated within the Work constitutes */
+/* direct or contributory patent infringement, then any patent licenses */
+/* granted to You under this License for that Work shall terminate as of */
+/* the date such litigation is filed. */
+/* */
+/* By using, modifying, or distributing the Work you indicate that you */
+/* have read and understood the terms and conditions of the */
+/* FreeType Project License as well as those provided in this section, */
+/* and you accept them fully. */
+/* */
+/***************************************************************************/
+
+
+#include "psft.h"
+#include FT_INTERNAL_DEBUG_H
+
+#include "psblues.h"
+#include "pshints.h"
+#include "psfont.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_cf2blues
+
+
+ /*
+ * For blue values, the FreeType parser produces an array of integers,
+ * while the Adobe CFF engine produces an array of fixed.
+ * Define a macro to convert FreeType to fixed.
+ */
+#define cf2_blueToFixed( x ) cf2_intToFixed( x )
+
+
+ FT_LOCAL_DEF( void )
+ cf2_blues_init( CF2_Blues blues,
+ CF2_Font font )
+ {
+ /* pointer to parsed font object */
+ PS_Decoder* decoder = font->decoder;
+
+ CF2_Fixed zoneHeight;
+ CF2_Fixed maxZoneHeight = 0;
+ CF2_Fixed csUnitsPerPixel;
+
+ size_t numBlueValues;
+ size_t numOtherBlues;
+ size_t numFamilyBlues;
+ size_t numFamilyOtherBlues;
+
+ FT_Pos* blueValues;
+ FT_Pos* otherBlues;
+ FT_Pos* familyBlues;
+ FT_Pos* familyOtherBlues;
+
+ size_t i;
+ CF2_Fixed emBoxBottom, emBoxTop;
+
+#if 0
+ CF2_Int unitsPerEm = font->unitsPerEm;
+
+
+ if ( unitsPerEm == 0 )
+ unitsPerEm = 1000;
+#endif
+
+ FT_ZERO( blues );
+ blues->scale = font->innerTransform.d;
+
+ cf2_getBlueMetrics( decoder,
+ &blues->blueScale,
+ &blues->blueShift,
+ &blues->blueFuzz );
+
+ cf2_getBlueValues( decoder, &numBlueValues, &blueValues );
+ cf2_getOtherBlues( decoder, &numOtherBlues, &otherBlues );
+ cf2_getFamilyBlues( decoder, &numFamilyBlues, &familyBlues );
+ cf2_getFamilyOtherBlues( decoder, &numFamilyOtherBlues, &familyOtherBlues );
+
+ /*
+ * synthetic em box hint heuristic
+ *
+ * Apply this when ideographic dictionary (LanguageGroup 1) has no
+ * real alignment zones. Adobe tools generate dummy zones at -250 and
+ * 1100 for a 1000 unit em. Fonts with ICF-based alignment zones
+ * should not enable the heuristic. When the heuristic is enabled,
+ * the font's blue zones are ignored.
+ *
+ */
+
+ /* get em box from OS/2 typoAscender/Descender */
+ /* TODO: FreeType does not parse these metrics. Skip them for now. */
+#if 0
+ FCM_getHorizontalLineMetrics( &e,
+ font->font,
+ &ascender,
+ &descender,
+ &linegap );
+ if ( ascender - descender == unitsPerEm )
+ {
+ emBoxBottom = cf2_intToFixed( descender );
+ emBoxTop = cf2_intToFixed( ascender );
+ }
+ else
+#endif
+ {
+ emBoxBottom = CF2_ICF_Bottom;
+ emBoxTop = CF2_ICF_Top;
+ }
+
+ if ( cf2_getLanguageGroup( decoder ) == 1 &&
+ ( numBlueValues == 0 ||
+ ( numBlueValues == 4 &&
+ cf2_blueToFixed( blueValues[0] ) < emBoxBottom &&
+ cf2_blueToFixed( blueValues[1] ) < emBoxBottom &&
+ cf2_blueToFixed( blueValues[2] ) > emBoxTop &&
+ cf2_blueToFixed( blueValues[3] ) > emBoxTop ) ) )
+ {
+ /*
+ * Construct hint edges suitable for synthetic ghost hints at top
+ * and bottom of em box. +-CF2_MIN_COUNTER allows for unhinted
+ * features above or below the last hinted edge. This also gives a
+ * net 1 pixel boost to the height of ideographic glyphs.
+ *
+ * Note: Adjust synthetic hints outward by epsilon (0x.0001) to
+ * avoid interference. E.g., some fonts have real hints at
+ * 880 and -120.
+ */
+
+ blues->emBoxBottomEdge.csCoord = emBoxBottom - CF2_FIXED_EPSILON;
+ blues->emBoxBottomEdge.dsCoord = cf2_fixedRound(
+ FT_MulFix(
+ blues->emBoxBottomEdge.csCoord,
+ blues->scale ) ) -
+ CF2_MIN_COUNTER;
+ blues->emBoxBottomEdge.scale = blues->scale;
+ blues->emBoxBottomEdge.flags = CF2_GhostBottom |
+ CF2_Locked |
+ CF2_Synthetic;
+
+ blues->emBoxTopEdge.csCoord = emBoxTop + CF2_FIXED_EPSILON +
+ 2 * font->darkenY;
+ blues->emBoxTopEdge.dsCoord = cf2_fixedRound(
+ FT_MulFix(
+ blues->emBoxTopEdge.csCoord,
+ blues->scale ) ) +
+ CF2_MIN_COUNTER;
+ blues->emBoxTopEdge.scale = blues->scale;
+ blues->emBoxTopEdge.flags = CF2_GhostTop |
+ CF2_Locked |
+ CF2_Synthetic;
+
+ blues->doEmBoxHints = TRUE; /* enable the heuristic */
+
+ return;
+ }
+
+ /* copy `BlueValues' and `OtherBlues' to a combined array of top and */
+ /* bottom zones */
+ for ( i = 0; i < numBlueValues; i += 2 )
+ {
+ blues->zone[blues->count].csBottomEdge =
+ cf2_blueToFixed( blueValues[i] );
+ blues->zone[blues->count].csTopEdge =
+ cf2_blueToFixed( blueValues[i + 1] );
+
+ zoneHeight = SUB_INT32( blues->zone[blues->count].csTopEdge,
+ blues->zone[blues->count].csBottomEdge );
+
+ if ( zoneHeight < 0 )
+ {
+ FT_TRACE4(( "cf2_blues_init: ignoring negative zone height\n" ));
+ continue; /* reject this zone */
+ }
+
+ if ( zoneHeight > maxZoneHeight )
+ {
+ /* take maximum before darkening adjustment */
+ /* so overshoot suppression point doesn't change */
+ maxZoneHeight = zoneHeight;
+ }
+
+ /* adjust both edges of top zone upward by twice darkening amount */
+ if ( i != 0 )
+ {
+ blues->zone[blues->count].csTopEdge += 2 * font->darkenY;
+ blues->zone[blues->count].csBottomEdge += 2 * font->darkenY;
+ }
+
+ /* first `BlueValue' is bottom zone; others are top */
+ if ( i == 0 )
+ {
+ blues->zone[blues->count].bottomZone =
+ TRUE;
+ blues->zone[blues->count].csFlatEdge =
+ blues->zone[blues->count].csTopEdge;
+ }
+ else
+ {
+ blues->zone[blues->count].bottomZone =
+ FALSE;
+ blues->zone[blues->count].csFlatEdge =
+ blues->zone[blues->count].csBottomEdge;
+ }
+
+ blues->count += 1;
+ }
+
+ for ( i = 0; i < numOtherBlues; i += 2 )
+ {
+ blues->zone[blues->count].csBottomEdge =
+ cf2_blueToFixed( otherBlues[i] );
+ blues->zone[blues->count].csTopEdge =
+ cf2_blueToFixed( otherBlues[i + 1] );
+
+ zoneHeight = SUB_INT32( blues->zone[blues->count].csTopEdge,
+ blues->zone[blues->count].csBottomEdge );
+
+ if ( zoneHeight < 0 )
+ {
+ FT_TRACE4(( "cf2_blues_init: ignoring negative zone height\n" ));
+ continue; /* reject this zone */
+ }
+
+ if ( zoneHeight > maxZoneHeight )
+ {
+ /* take maximum before darkening adjustment */
+ /* so overshoot suppression point doesn't change */
+ maxZoneHeight = zoneHeight;
+ }
+
+ /* Note: bottom zones are not adjusted for darkening amount */
+
+ /* all OtherBlues are bottom zone */
+ blues->zone[blues->count].bottomZone =
+ TRUE;
+ blues->zone[blues->count].csFlatEdge =
+ blues->zone[blues->count].csTopEdge;
+
+ blues->count += 1;
+ }
+
+ /* Adjust for FamilyBlues */
+
+ /* Search for the nearest flat edge in `FamilyBlues' or */
+ /* `FamilyOtherBlues'. According to the Black Book, any matching edge */
+ /* must be within one device pixel */
+
+ csUnitsPerPixel = FT_DivFix( cf2_intToFixed( 1 ), blues->scale );
+
+ /* loop on all zones in this font */
+ for ( i = 0; i < blues->count; i++ )
+ {
+ size_t j;
+ CF2_Fixed minDiff;
+ CF2_Fixed flatFamilyEdge, diff;
+ /* value for this font */
+ CF2_Fixed flatEdge = blues->zone[i].csFlatEdge;
+
+
+ if ( blues->zone[i].bottomZone )
+ {
+ /* In a bottom zone, the top edge is the flat edge. */
+ /* Search `FamilyOtherBlues' for bottom zones; look for closest */
+ /* Family edge that is within the one pixel threshold. */
+
+ minDiff = CF2_FIXED_MAX;
+
+ for ( j = 0; j < numFamilyOtherBlues; j += 2 )
+ {
+ /* top edge */
+ flatFamilyEdge = cf2_blueToFixed( familyOtherBlues[j + 1] );
+
+ diff = cf2_fixedAbs( SUB_INT32( flatEdge, flatFamilyEdge ) );
+
+ if ( diff < minDiff && diff < csUnitsPerPixel )
+ {
+ blues->zone[i].csFlatEdge = flatFamilyEdge;
+ minDiff = diff;
+
+ if ( diff == 0 )
+ break;
+ }
+ }
+
+ /* check the first member of FamilyBlues, which is a bottom zone */
+ if ( numFamilyBlues >= 2 )
+ {
+ /* top edge */
+ flatFamilyEdge = cf2_blueToFixed( familyBlues[1] );
+
+ diff = cf2_fixedAbs( SUB_INT32( flatEdge, flatFamilyEdge ) );
+
+ if ( diff < minDiff && diff < csUnitsPerPixel )
+ blues->zone[i].csFlatEdge = flatFamilyEdge;
+ }
+ }
+ else
+ {
+ /* In a top zone, the bottom edge is the flat edge. */
+ /* Search `FamilyBlues' for top zones; skip first zone, which is a */
+ /* bottom zone; look for closest Family edge that is within the */
+ /* one pixel threshold */
+
+ minDiff = CF2_FIXED_MAX;
+
+ for ( j = 2; j < numFamilyBlues; j += 2 )
+ {
+ /* bottom edge */
+ flatFamilyEdge = cf2_blueToFixed( familyBlues[j] );
+
+ /* adjust edges of top zone upward by twice darkening amount */
+ flatFamilyEdge += 2 * font->darkenY; /* bottom edge */
+
+ diff = cf2_fixedAbs( SUB_INT32( flatEdge, flatFamilyEdge ) );
+
+ if ( diff < minDiff && diff < csUnitsPerPixel )
+ {
+ blues->zone[i].csFlatEdge = flatFamilyEdge;
+ minDiff = diff;
+
+ if ( diff == 0 )
+ break;
+ }
+ }
+ }
+ }
+
+ /* TODO: enforce separation of zones, including BlueFuzz */
+
+ /* Adjust BlueScale; similar to AdjustBlueScale() in coretype */
+ /* `bcsetup.c'. */
+
+ if ( maxZoneHeight > 0 )
+ {
+ if ( blues->blueScale > FT_DivFix( cf2_intToFixed( 1 ),
+ maxZoneHeight ) )
+ {
+ /* clamp at maximum scale */
+ blues->blueScale = FT_DivFix( cf2_intToFixed( 1 ),
+ maxZoneHeight );
+ }
+
+ /*
+ * TODO: Revisit the bug fix for 613448. The minimum scale
+ * requirement catches a number of library fonts. For
+ * example, with default BlueScale (.039625) and 0.4 minimum,
+ * the test below catches any font with maxZoneHeight < 10.1.
+ * There are library fonts ranging from 2 to 10 that get
+ * caught, including e.g., Eurostile LT Std Medium with
+ * maxZoneHeight of 6.
+ *
+ */
+#if 0
+ if ( blueScale < .4 / maxZoneHeight )
+ {
+ tetraphilia_assert( 0 );
+ /* clamp at minimum scale, per bug 0613448 fix */
+ blueScale = .4 / maxZoneHeight;
+ }
+#endif
+
+ }
+
+ /*
+ * Suppress overshoot and boost blue zones at small sizes. Boost
+ * amount varies linearly from 0.5 pixel near 0 to 0 pixel at
+ * blueScale cutoff.
+ * Note: This boost amount is different from the coretype heuristic.
+ *
+ */
+
+ if ( blues->scale < blues->blueScale )
+ {
+ blues->suppressOvershoot = TRUE;
+
+ /* Change rounding threshold for `dsFlatEdge'. */
+ /* Note: constant changed from 0.5 to 0.6 to avoid a problem with */
+ /* 10ppem Arial */
+
+ blues->boost = cf2_doubleToFixed( .6 ) -
+ FT_MulDiv( cf2_doubleToFixed ( .6 ),
+ blues->scale,
+ blues->blueScale );
+ if ( blues->boost > 0x7FFF )
+ {
+ /* boost must remain less than 0.5, or baseline could go negative */
+ blues->boost = 0x7FFF;
+ }
+ }
+
+ /* boost and darkening have similar effects; don't do both */
+ if ( font->stemDarkened )
+ blues->boost = 0;
+
+ /* set device space alignment for each zone; */
+ /* apply boost amount before rounding flat edge */
+
+ for ( i = 0; i < blues->count; i++ )
+ {
+ if ( blues->zone[i].bottomZone )
+ blues->zone[i].dsFlatEdge = cf2_fixedRound(
+ FT_MulFix(
+ blues->zone[i].csFlatEdge,
+ blues->scale ) -
+ blues->boost );
+ else
+ blues->zone[i].dsFlatEdge = cf2_fixedRound(
+ FT_MulFix(
+ blues->zone[i].csFlatEdge,
+ blues->scale ) +
+ blues->boost );
+ }
+ }
+
+
+ /*
+ * Check whether `stemHint' is captured by one of the blue zones.
+ *
+ * Zero, one or both edges may be valid; only valid edges can be
+ * captured. For compatibility with CoolType, search top and bottom
+ * zones in the same pass (see `BlueLock'). If a hint is captured,
+ * return true and position the edge(s) in one of 3 ways:
+ *
+ * 1) If `BlueScale' suppresses overshoot, position the captured edge
+ * at the flat edge of the zone.
+ * 2) If overshoot is not suppressed and `BlueShift' requires
+ * overshoot, position the captured edge a minimum of 1 device pixel
+ * from the flat edge.
+ * 3) If overshoot is not suppressed or required, position the captured
+ * edge at the nearest device pixel.
+ *
+ */
+ FT_LOCAL_DEF( FT_Bool )
+ cf2_blues_capture( const CF2_Blues blues,
+ CF2_Hint bottomHintEdge,
+ CF2_Hint topHintEdge )
+ {
+ /* TODO: validate? */
+ CF2_Fixed csFuzz = blues->blueFuzz;
+
+ /* new position of captured edge */
+ CF2_Fixed dsNew;
+
+ /* amount that hint is moved when positioned */
+ CF2_Fixed dsMove = 0;
+
+ FT_Bool captured = FALSE;
+ CF2_UInt i;
+
+
+ /* assert edge flags are consistent */
+ FT_ASSERT( !cf2_hint_isTop( bottomHintEdge ) &&
+ !cf2_hint_isBottom( topHintEdge ) );
+
+ /* TODO: search once without blue fuzz for compatibility with coretype? */
+ for ( i = 0; i < blues->count; i++ )
+ {
+ if ( blues->zone[i].bottomZone &&
+ cf2_hint_isBottom( bottomHintEdge ) )
+ {
+ if ( SUB_INT32( blues->zone[i].csBottomEdge, csFuzz ) <=
+ bottomHintEdge->csCoord &&
+ bottomHintEdge->csCoord <=
+ ADD_INT32( blues->zone[i].csTopEdge, csFuzz ) )
+ {
+ /* bottom edge captured by bottom zone */
+
+ if ( blues->suppressOvershoot )
+ dsNew = blues->zone[i].dsFlatEdge;
+
+ else if ( SUB_INT32( blues->zone[i].csTopEdge,
+ bottomHintEdge->csCoord ) >=
+ blues->blueShift )
+ {
+ /* guarantee minimum of 1 pixel overshoot */
+ dsNew = FT_MIN(
+ cf2_fixedRound( bottomHintEdge->dsCoord ),
+ blues->zone[i].dsFlatEdge - cf2_intToFixed( 1 ) );
+ }
+
+ else
+ {
+ /* simply round captured edge */
+ dsNew = cf2_fixedRound( bottomHintEdge->dsCoord );
+ }
+
+ dsMove = SUB_INT32( dsNew, bottomHintEdge->dsCoord );
+ captured = TRUE;
+
+ break;
+ }
+ }
+
+ if ( !blues->zone[i].bottomZone && cf2_hint_isTop( topHintEdge ) )
+ {
+ if ( SUB_INT32( blues->zone[i].csBottomEdge, csFuzz ) <=
+ topHintEdge->csCoord &&
+ topHintEdge->csCoord <=
+ ADD_INT32( blues->zone[i].csTopEdge, csFuzz ) )
+ {
+ /* top edge captured by top zone */
+
+ if ( blues->suppressOvershoot )
+ dsNew = blues->zone[i].dsFlatEdge;
+
+ else if ( SUB_INT32( topHintEdge->csCoord,
+ blues->zone[i].csBottomEdge ) >=
+ blues->blueShift )
+ {
+ /* guarantee minimum of 1 pixel overshoot */
+ dsNew = FT_MAX(
+ cf2_fixedRound( topHintEdge->dsCoord ),
+ blues->zone[i].dsFlatEdge + cf2_intToFixed( 1 ) );
+ }
+
+ else
+ {
+ /* simply round captured edge */
+ dsNew = cf2_fixedRound( topHintEdge->dsCoord );
+ }
+
+ dsMove = SUB_INT32( dsNew, topHintEdge->dsCoord );
+ captured = TRUE;
+
+ break;
+ }
+ }
+ }
+
+ if ( captured )
+ {
+ /* move both edges and flag them `locked' */
+ if ( cf2_hint_isValid( bottomHintEdge ) )
+ {
+ bottomHintEdge->dsCoord = ADD_INT32( bottomHintEdge->dsCoord,
+ dsMove );
+ cf2_hint_lock( bottomHintEdge );
+ }
+
+ if ( cf2_hint_isValid( topHintEdge ) )
+ {
+ topHintEdge->dsCoord = ADD_INT32( topHintEdge->dsCoord, dsMove );
+ cf2_hint_lock( topHintEdge );
+ }
+ }
+
+ return captured;
+ }
+
+
+/* END */
diff --git a/thirdparty/freetype/src/psaux/psblues.h b/thirdparty/freetype/src/psaux/psblues.h
new file mode 100644
index 0000000000..25ef6849c7
--- /dev/null
+++ b/thirdparty/freetype/src/psaux/psblues.h
@@ -0,0 +1,185 @@
+/***************************************************************************/
+/* */
+/* psblues.h */
+/* */
+/* Adobe's code for handling Blue Zones (specification). */
+/* */
+/* Copyright 2009-2013 Adobe Systems Incorporated. */
+/* */
+/* This software, and all works of authorship, whether in source or */
+/* object code form as indicated by the copyright notice(s) included */
+/* herein (collectively, the "Work") is made available, and may only be */
+/* used, modified, and distributed under the FreeType Project License, */
+/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
+/* FreeType Project License, each contributor to the Work hereby grants */
+/* to any individual or legal entity exercising permissions granted by */
+/* the FreeType Project License and this section (hereafter, "You" or */
+/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
+/* royalty-free, irrevocable (except as stated in this section) patent */
+/* license to make, have made, use, offer to sell, sell, import, and */
+/* otherwise transfer the Work, where such license applies only to those */
+/* patent claims licensable by such contributor that are necessarily */
+/* infringed by their contribution(s) alone or by combination of their */
+/* contribution(s) with the Work to which such contribution(s) was */
+/* submitted. If You institute patent litigation against any entity */
+/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
+/* the Work or a contribution incorporated within the Work constitutes */
+/* direct or contributory patent infringement, then any patent licenses */
+/* granted to You under this License for that Work shall terminate as of */
+/* the date such litigation is filed. */
+/* */
+/* By using, modifying, or distributing the Work you indicate that you */
+/* have read and understood the terms and conditions of the */
+/* FreeType Project License as well as those provided in this section, */
+/* and you accept them fully. */
+/* */
+/***************************************************************************/
+
+
+ /*
+ * A `CF2_Blues' object stores the blue zones (horizontal alignment
+ * zones) of a font. These are specified in the CFF private dictionary
+ * by `BlueValues', `OtherBlues', `FamilyBlues', and `FamilyOtherBlues'.
+ * Each zone is defined by a top and bottom edge in character space.
+ * Further, each zone is either a top zone or a bottom zone, as recorded
+ * by `bottomZone'.
+ *
+ * The maximum number of `BlueValues' and `FamilyBlues' is 7 each.
+ * However, these are combined to produce a total of 7 zones.
+ * Similarly, the maximum number of `OtherBlues' and `FamilyOtherBlues'
+ * is 5 and these are combined to produce an additional 5 zones.
+ *
+ * Blue zones are used to `capture' hints and force them to a common
+ * alignment point. This alignment is recorded in device space in
+ * `dsFlatEdge'. Except for this value, a `CF2_Blues' object could be
+ * constructed independently of scaling. Construction may occur once
+ * the matrix is known. Other features implemented in the Capture
+ * method are overshoot suppression, overshoot enforcement, and Blue
+ * Boost.
+ *
+ * Capture is determined by `BlueValues' and `OtherBlues', but the
+ * alignment point may be adjusted to the scaled flat edge of
+ * `FamilyBlues' or `FamilyOtherBlues'. No alignment is done to the
+ * curved edge of a zone.
+ *
+ */
+
+
+#ifndef PSBLUES_H_
+#define PSBLUES_H_
+
+
+#include "psglue.h"
+
+
+FT_BEGIN_HEADER
+
+
+ /*
+ * `CF2_Hint' is shared by `cf2hints.h' and
+ * `cf2blues.h', but `cf2blues.h' depends on
+ * `cf2hints.h', so define it here. Note: The typedef is in
+ * `cf2glue.h'.
+ *
+ */
+ enum
+ {
+ CF2_GhostBottom = 0x1, /* a single bottom edge */
+ CF2_GhostTop = 0x2, /* a single top edge */
+ CF2_PairBottom = 0x4, /* the bottom edge of a stem hint */
+ CF2_PairTop = 0x8, /* the top edge of a stem hint */
+ CF2_Locked = 0x10, /* this edge has been aligned */
+ /* by a blue zone */
+ CF2_Synthetic = 0x20 /* this edge was synthesized */
+ };
+
+
+ /*
+ * Default value for OS/2 typoAscender/Descender when their difference
+ * is not equal to `unitsPerEm'. The default is based on -250 and 1100
+ * in `CF2_Blues', assuming 1000 units per em here.
+ *
+ */
+ enum
+ {
+ CF2_ICF_Top = cf2_intToFixed( 880 ),
+ CF2_ICF_Bottom = cf2_intToFixed( -120 )
+ };
+
+
+ /*
+ * Constant used for hint adjustment and for synthetic em box hint
+ * placement.
+ */
+#define CF2_MIN_COUNTER cf2_doubleToFixed( 0.5 )
+
+
+ /* shared typedef is in cf2glue.h */
+ struct CF2_HintRec_
+ {
+ CF2_UInt flags; /* attributes of the edge */
+ size_t index; /* index in original stem hint array */
+ /* (if not synthetic) */
+ CF2_Fixed csCoord;
+ CF2_Fixed dsCoord;
+ CF2_Fixed scale;
+ };
+
+
+ typedef struct CF2_BlueRec_
+ {
+ CF2_Fixed csBottomEdge;
+ CF2_Fixed csTopEdge;
+ CF2_Fixed csFlatEdge; /* may be from either local or Family zones */
+ CF2_Fixed dsFlatEdge; /* top edge of bottom zone or bottom edge */
+ /* of top zone (rounded) */
+ FT_Bool bottomZone;
+
+ } CF2_BlueRec;
+
+
+ /* max total blue zones is 12 */
+ enum
+ {
+ CF2_MAX_BLUES = 7,
+ CF2_MAX_OTHERBLUES = 5
+ };
+
+
+ typedef struct CF2_BluesRec_
+ {
+ CF2_Fixed scale;
+ CF2_UInt count;
+ FT_Bool suppressOvershoot;
+ FT_Bool doEmBoxHints;
+
+ CF2_Fixed blueScale;
+ CF2_Fixed blueShift;
+ CF2_Fixed blueFuzz;
+
+ CF2_Fixed boost;
+
+ CF2_HintRec emBoxTopEdge;
+ CF2_HintRec emBoxBottomEdge;
+
+ CF2_BlueRec zone[CF2_MAX_BLUES + CF2_MAX_OTHERBLUES];
+
+ } CF2_BluesRec, *CF2_Blues;
+
+
+ FT_LOCAL( void )
+ cf2_blues_init( CF2_Blues blues,
+ CF2_Font font );
+ FT_LOCAL( FT_Bool )
+ cf2_blues_capture( const CF2_Blues blues,
+ CF2_Hint bottomHintEdge,
+ CF2_Hint topHintEdge );
+
+
+FT_END_HEADER
+
+
+#endif /* PSBLUES_H_ */
+
+
+/* END */
diff --git a/thirdparty/freetype/src/psaux/psconv.c b/thirdparty/freetype/src/psaux/psconv.c
index d125b0834a..a03385000d 100644
--- a/thirdparty/freetype/src/psaux/psconv.c
+++ b/thirdparty/freetype/src/psaux/psconv.c
@@ -4,7 +4,7 @@
/* */
/* Some convenience conversions (body). */
/* */
-/* Copyright 2006-2017 by */
+/* Copyright 2006-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/psaux/psconv.h b/thirdparty/freetype/src/psaux/psconv.h
index cab254ac5a..d643ffcfc2 100644
--- a/thirdparty/freetype/src/psaux/psconv.h
+++ b/thirdparty/freetype/src/psaux/psconv.h
@@ -4,7 +4,7 @@
/* */
/* Some convenience conversions (specification). */
/* */
-/* Copyright 2006-2017 by */
+/* Copyright 2006-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/psaux/pserror.c b/thirdparty/freetype/src/psaux/pserror.c
new file mode 100644
index 0000000000..9169e5222d
--- /dev/null
+++ b/thirdparty/freetype/src/psaux/pserror.c
@@ -0,0 +1,52 @@
+/***************************************************************************/
+/* */
+/* pserror.c */
+/* */
+/* Adobe's code for error handling (body). */
+/* */
+/* Copyright 2006-2013 Adobe Systems Incorporated. */
+/* */
+/* This software, and all works of authorship, whether in source or */
+/* object code form as indicated by the copyright notice(s) included */
+/* herein (collectively, the "Work") is made available, and may only be */
+/* used, modified, and distributed under the FreeType Project License, */
+/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
+/* FreeType Project License, each contributor to the Work hereby grants */
+/* to any individual or legal entity exercising permissions granted by */
+/* the FreeType Project License and this section (hereafter, "You" or */
+/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
+/* royalty-free, irrevocable (except as stated in this section) patent */
+/* license to make, have made, use, offer to sell, sell, import, and */
+/* otherwise transfer the Work, where such license applies only to those */
+/* patent claims licensable by such contributor that are necessarily */
+/* infringed by their contribution(s) alone or by combination of their */
+/* contribution(s) with the Work to which such contribution(s) was */
+/* submitted. If You institute patent litigation against any entity */
+/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
+/* the Work or a contribution incorporated within the Work constitutes */
+/* direct or contributory patent infringement, then any patent licenses */
+/* granted to You under this License for that Work shall terminate as of */
+/* the date such litigation is filed. */
+/* */
+/* By using, modifying, or distributing the Work you indicate that you */
+/* have read and understood the terms and conditions of the */
+/* FreeType Project License as well as those provided in this section, */
+/* and you accept them fully. */
+/* */
+/***************************************************************************/
+
+
+#include "psft.h"
+#include "pserror.h"
+
+
+ FT_LOCAL_DEF( void )
+ cf2_setError( FT_Error* error,
+ FT_Error value )
+ {
+ if ( error && !*error )
+ *error = value;
+ }
+
+
+/* END */
diff --git a/thirdparty/freetype/src/psaux/pserror.h b/thirdparty/freetype/src/psaux/pserror.h
new file mode 100644
index 0000000000..13d52062bf
--- /dev/null
+++ b/thirdparty/freetype/src/psaux/pserror.h
@@ -0,0 +1,119 @@
+/***************************************************************************/
+/* */
+/* pserror.h */
+/* */
+/* Adobe's code for error handling (specification). */
+/* */
+/* Copyright 2006-2013 Adobe Systems Incorporated. */
+/* */
+/* This software, and all works of authorship, whether in source or */
+/* object code form as indicated by the copyright notice(s) included */
+/* herein (collectively, the "Work") is made available, and may only be */
+/* used, modified, and distributed under the FreeType Project License, */
+/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
+/* FreeType Project License, each contributor to the Work hereby grants */
+/* to any individual or legal entity exercising permissions granted by */
+/* the FreeType Project License and this section (hereafter, "You" or */
+/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
+/* royalty-free, irrevocable (except as stated in this section) patent */
+/* license to make, have made, use, offer to sell, sell, import, and */
+/* otherwise transfer the Work, where such license applies only to those */
+/* patent claims licensable by such contributor that are necessarily */
+/* infringed by their contribution(s) alone or by combination of their */
+/* contribution(s) with the Work to which such contribution(s) was */
+/* submitted. If You institute patent litigation against any entity */
+/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
+/* the Work or a contribution incorporated within the Work constitutes */
+/* direct or contributory patent infringement, then any patent licenses */
+/* granted to You under this License for that Work shall terminate as of */
+/* the date such litigation is filed. */
+/* */
+/* By using, modifying, or distributing the Work you indicate that you */
+/* have read and understood the terms and conditions of the */
+/* FreeType Project License as well as those provided in this section, */
+/* and you accept them fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef PSERROR_H_
+#define PSERROR_H_
+
+
+#include FT_MODULE_ERRORS_H
+
+#undef FTERRORS_H_
+
+#undef FT_ERR_PREFIX
+#define FT_ERR_PREFIX CF2_Err_
+#define FT_ERR_BASE FT_Mod_Err_CF2
+
+
+#include FT_ERRORS_H
+#include "psft.h"
+
+
+FT_BEGIN_HEADER
+
+
+ /*
+ * A poor-man error facility.
+ *
+ * This code being written in vanilla C, doesn't have the luxury of a
+ * language-supported exception mechanism such as the one available in
+ * Java. Instead, we are stuck with using error codes that must be
+ * carefully managed and preserved. However, it is convenient for us to
+ * model our error mechanism on a Java-like exception mechanism.
+ * When we assign an error code we are thus `throwing' an error.
+ *
+ * The preservation of an error code is done by coding convention.
+ * Upon a function call if the error code is anything other than
+ * `FT_Err_Ok', which is guaranteed to be zero, we
+ * will return without altering that error. This will allow the
+ * error to propagate and be handled at the appropriate location in
+ * the code.
+ *
+ * This allows a style of code where the error code is initialized
+ * up front and a block of calls are made with the error code only
+ * being checked after the block. If a new error occurs, the original
+ * error will be preserved and a functional no-op should result in any
+ * subsequent function that has an initial error code not equal to
+ * `FT_Err_Ok'.
+ *
+ * Errors are encoded by calling the `FT_THROW' macro. For example,
+ *
+ * {
+ * FT_Error e;
+ *
+ *
+ * ...
+ * e = FT_THROW( Out_Of_Memory );
+ * }
+ *
+ */
+
+
+ /* Set error code to a particular value. */
+ FT_LOCAL( void )
+ cf2_setError( FT_Error* error,
+ FT_Error value );
+
+
+ /*
+ * A macro that conditionally sets an error code.
+ *
+ * This macro will first check whether `error' is set;
+ * if not, it will set it to `e'.
+ *
+ */
+#define CF2_SET_ERROR( error, e ) \
+ cf2_setError( error, FT_THROW( e ) )
+
+
+FT_END_HEADER
+
+
+#endif /* PSERROR_H_ */
+
+
+/* END */
diff --git a/thirdparty/freetype/src/psaux/psfixed.h b/thirdparty/freetype/src/psaux/psfixed.h
new file mode 100644
index 0000000000..219589e7fc
--- /dev/null
+++ b/thirdparty/freetype/src/psaux/psfixed.h
@@ -0,0 +1,95 @@
+/***************************************************************************/
+/* */
+/* psfixed.h */
+/* */
+/* Adobe's code for Fixed Point Mathematics (specification only). */
+/* */
+/* Copyright 2007-2013 Adobe Systems Incorporated. */
+/* */
+/* This software, and all works of authorship, whether in source or */
+/* object code form as indicated by the copyright notice(s) included */
+/* herein (collectively, the "Work") is made available, and may only be */
+/* used, modified, and distributed under the FreeType Project License, */
+/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
+/* FreeType Project License, each contributor to the Work hereby grants */
+/* to any individual or legal entity exercising permissions granted by */
+/* the FreeType Project License and this section (hereafter, "You" or */
+/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
+/* royalty-free, irrevocable (except as stated in this section) patent */
+/* license to make, have made, use, offer to sell, sell, import, and */
+/* otherwise transfer the Work, where such license applies only to those */
+/* patent claims licensable by such contributor that are necessarily */
+/* infringed by their contribution(s) alone or by combination of their */
+/* contribution(s) with the Work to which such contribution(s) was */
+/* submitted. If You institute patent litigation against any entity */
+/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
+/* the Work or a contribution incorporated within the Work constitutes */
+/* direct or contributory patent infringement, then any patent licenses */
+/* granted to You under this License for that Work shall terminate as of */
+/* the date such litigation is filed. */
+/* */
+/* By using, modifying, or distributing the Work you indicate that you */
+/* have read and understood the terms and conditions of the */
+/* FreeType Project License as well as those provided in this section, */
+/* and you accept them fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef PSFIXED_H_
+#define PSFIXED_H_
+
+
+FT_BEGIN_HEADER
+
+
+ /* rasterizer integer and fixed point arithmetic must be 32-bit */
+
+#define CF2_Fixed CF2_F16Dot16
+ typedef FT_Int32 CF2_Frac; /* 2.30 fixed point */
+
+
+#define CF2_FIXED_MAX ( (CF2_Fixed)0x7FFFFFFFL )
+#define CF2_FIXED_MIN ( (CF2_Fixed)0x80000000L )
+#define CF2_FIXED_ONE ( (CF2_Fixed)0x10000L )
+#define CF2_FIXED_EPSILON ( (CF2_Fixed)0x0001 )
+
+ /* in C 89, left and right shift of negative numbers is */
+ /* implementation specific behaviour in the general case */
+
+#define cf2_intToFixed( i ) \
+ ( (CF2_Fixed)( (FT_UInt32)(i) << 16 ) )
+#define cf2_fixedToInt( x ) \
+ ( (FT_Short)( ( (FT_UInt32)(x) + 0x8000U ) >> 16 ) )
+#define cf2_fixedRound( x ) \
+ ( (CF2_Fixed)( ( (FT_UInt32)(x) + 0x8000U ) & 0xFFFF0000UL ) )
+#define cf2_doubleToFixed( f ) \
+ ( (CF2_Fixed)( (f) * 65536.0 + 0.5 ) )
+#define cf2_fixedAbs( x ) \
+ ( (x) < 0 ? NEG_INT32( x ) : (x) )
+#define cf2_fixedFloor( x ) \
+ ( (CF2_Fixed)( (FT_UInt32)(x) & 0xFFFF0000UL ) )
+#define cf2_fixedFraction( x ) \
+ ( (x) - cf2_fixedFloor( x ) )
+#define cf2_fracToFixed( x ) \
+ ( (x) < 0 ? -( ( -(x) + 0x2000 ) >> 14 ) \
+ : ( ( (x) + 0x2000 ) >> 14 ) )
+
+
+ /* signed numeric types */
+ typedef enum CF2_NumberType_
+ {
+ CF2_NumberFixed, /* 16.16 */
+ CF2_NumberFrac, /* 2.30 */
+ CF2_NumberInt /* 32.0 */
+
+ } CF2_NumberType;
+
+
+FT_END_HEADER
+
+
+#endif /* PSFIXED_H_ */
+
+
+/* END */
diff --git a/thirdparty/freetype/src/psaux/psfont.c b/thirdparty/freetype/src/psaux/psfont.c
new file mode 100644
index 0000000000..dde67a739d
--- /dev/null
+++ b/thirdparty/freetype/src/psaux/psfont.c
@@ -0,0 +1,567 @@
+/***************************************************************************/
+/* */
+/* psfont.c */
+/* */
+/* Adobe's code for font instances (body). */
+/* */
+/* Copyright 2007-2014 Adobe Systems Incorporated. */
+/* */
+/* This software, and all works of authorship, whether in source or */
+/* object code form as indicated by the copyright notice(s) included */
+/* herein (collectively, the "Work") is made available, and may only be */
+/* used, modified, and distributed under the FreeType Project License, */
+/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
+/* FreeType Project License, each contributor to the Work hereby grants */
+/* to any individual or legal entity exercising permissions granted by */
+/* the FreeType Project License and this section (hereafter, "You" or */
+/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
+/* royalty-free, irrevocable (except as stated in this section) patent */
+/* license to make, have made, use, offer to sell, sell, import, and */
+/* otherwise transfer the Work, where such license applies only to those */
+/* patent claims licensable by such contributor that are necessarily */
+/* infringed by their contribution(s) alone or by combination of their */
+/* contribution(s) with the Work to which such contribution(s) was */
+/* submitted. If You institute patent litigation against any entity */
+/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
+/* the Work or a contribution incorporated within the Work constitutes */
+/* direct or contributory patent infringement, then any patent licenses */
+/* granted to You under this License for that Work shall terminate as of */
+/* the date such litigation is filed. */
+/* */
+/* By using, modifying, or distributing the Work you indicate that you */
+/* have read and understood the terms and conditions of the */
+/* FreeType Project License as well as those provided in this section, */
+/* and you accept them fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_CALC_H
+
+#include "psft.h"
+
+#include "psglue.h"
+#include "psfont.h"
+#include "pserror.h"
+#include "psintrp.h"
+
+
+ /* Compute a stem darkening amount in character space. */
+ static void
+ cf2_computeDarkening( CF2_Fixed emRatio,
+ CF2_Fixed ppem,
+ CF2_Fixed stemWidth,
+ CF2_Fixed* darkenAmount,
+ CF2_Fixed boldenAmount,
+ FT_Bool stemDarkened,
+ FT_Int* darkenParams )
+ {
+ /*
+ * Total darkening amount is computed in 1000 unit character space
+ * using the modified 5 part curve as Adobe's Avalon rasterizer.
+ * The darkening amount is smaller for thicker stems.
+ * It becomes zero when the stem is thicker than 2.333 pixels.
+ *
+ * By default, we use
+ *
+ * darkenAmount = 0.4 pixels if scaledStem <= 0.5 pixels,
+ * darkenAmount = 0.275 pixels if 1 <= scaledStem <= 1.667 pixels,
+ * darkenAmount = 0 pixel if scaledStem >= 2.333 pixels,
+ *
+ * and piecewise linear in-between:
+ *
+ *
+ * darkening
+ * ^
+ * |
+ * | (x1,y1)
+ * |--------+
+ * | \
+ * | \
+ * | \ (x3,y3)
+ * | +----------+
+ * | (x2,y2) \
+ * | \
+ * | \
+ * | +-----------------
+ * | (x4,y4)
+ * +---------------------------------------------> stem
+ * thickness
+ *
+ *
+ * This corresponds to the following values for the
+ * `darkening-parameters' property:
+ *
+ * (x1, y1) = (500, 400)
+ * (x2, y2) = (1000, 275)
+ * (x3, y3) = (1667, 275)
+ * (x4, y4) = (2333, 0)
+ *
+ */
+
+ /* Internal calculations are done in units per thousand for */
+ /* convenience. The x axis is scaled stem width in */
+ /* thousandths of a pixel. That is, 1000 is 1 pixel. */
+ /* The y axis is darkening amount in thousandths of a pixel.*/
+ /* In the code, below, dividing by ppem and */
+ /* adjusting for emRatio converts darkenAmount to character */
+ /* space (font units). */
+ CF2_Fixed stemWidthPer1000, scaledStem;
+ FT_Int logBase2;
+
+
+ *darkenAmount = 0;
+
+ if ( boldenAmount == 0 && !stemDarkened )
+ return;
+
+ /* protect against range problems and divide by zero */
+ if ( emRatio < cf2_doubleToFixed( .01 ) )
+ return;
+
+ if ( stemDarkened )
+ {
+ FT_Int x1 = darkenParams[0];
+ FT_Int y1 = darkenParams[1];
+ FT_Int x2 = darkenParams[2];
+ FT_Int y2 = darkenParams[3];
+ FT_Int x3 = darkenParams[4];
+ FT_Int y3 = darkenParams[5];
+ FT_Int x4 = darkenParams[6];
+ FT_Int y4 = darkenParams[7];
+
+
+ /* convert from true character space to 1000 unit character space; */
+ /* add synthetic emboldening effect */
+
+ /* `stemWidthPer1000' will not overflow for a legitimate font */
+
+ stemWidthPer1000 = FT_MulFix( stemWidth + boldenAmount, emRatio );
+
+ /* `scaledStem' can easily overflow, so we must clamp its maximum */
+ /* value; the test doesn't need to be precise, but must be */
+ /* conservative. The clamp value (default 2333) where */
+ /* `darkenAmount' is zero is well below the overflow value of */
+ /* 32767. */
+ /* */
+ /* FT_MSB computes the integer part of the base 2 logarithm. The */
+ /* number of bits for the product is 1 or 2 more than the sum of */
+ /* logarithms; remembering that the 16 lowest bits of the fraction */
+ /* are dropped this is correct to within a factor of almost 4. */
+ /* For example, 0x80.0000 * 0x80.0000 = 0x4000.0000 is 23+23 and */
+ /* is flagged as possible overflow because 0xFF.FFFF * 0xFF.FFFF = */
+ /* 0xFFFF.FE00 is also 23+23. */
+
+ logBase2 = FT_MSB( (FT_UInt32)stemWidthPer1000 ) +
+ FT_MSB( (FT_UInt32)ppem );
+
+ if ( logBase2 >= 46 )
+ /* possible overflow */
+ scaledStem = cf2_intToFixed( x4 );
+ else
+ scaledStem = FT_MulFix( stemWidthPer1000, ppem );
+
+ /* now apply the darkening parameters */
+
+ if ( scaledStem < cf2_intToFixed( x1 ) )
+ *darkenAmount = FT_DivFix( cf2_intToFixed( y1 ), ppem );
+
+ else if ( scaledStem < cf2_intToFixed( x2 ) )
+ {
+ FT_Int xdelta = x2 - x1;
+ FT_Int ydelta = y2 - y1;
+ FT_Int x = stemWidthPer1000 -
+ FT_DivFix( cf2_intToFixed( x1 ), ppem );
+
+
+ if ( !xdelta )
+ goto Try_x3;
+
+ *darkenAmount = FT_MulDiv( x, ydelta, xdelta ) +
+ FT_DivFix( cf2_intToFixed( y1 ), ppem );
+ }
+
+ else if ( scaledStem < cf2_intToFixed( x3 ) )
+ {
+ Try_x3:
+ {
+ FT_Int xdelta = x3 - x2;
+ FT_Int ydelta = y3 - y2;
+ FT_Int x = stemWidthPer1000 -
+ FT_DivFix( cf2_intToFixed( x2 ), ppem );
+
+
+ if ( !xdelta )
+ goto Try_x4;
+
+ *darkenAmount = FT_MulDiv( x, ydelta, xdelta ) +
+ FT_DivFix( cf2_intToFixed( y2 ), ppem );
+ }
+ }
+
+ else if ( scaledStem < cf2_intToFixed( x4 ) )
+ {
+ Try_x4:
+ {
+ FT_Int xdelta = x4 - x3;
+ FT_Int ydelta = y4 - y3;
+ FT_Int x = stemWidthPer1000 -
+ FT_DivFix( cf2_intToFixed( x3 ), ppem );
+
+
+ if ( !xdelta )
+ goto Use_y4;
+
+ *darkenAmount = FT_MulDiv( x, ydelta, xdelta ) +
+ FT_DivFix( cf2_intToFixed( y3 ), ppem );
+ }
+ }
+
+ else
+ {
+ Use_y4:
+ *darkenAmount = FT_DivFix( cf2_intToFixed( y4 ), ppem );
+ }
+
+ /* use half the amount on each side and convert back to true */
+ /* character space */
+ *darkenAmount = FT_DivFix( *darkenAmount, 2 * emRatio );
+ }
+
+ /* add synthetic emboldening effect in character space */
+ *darkenAmount += boldenAmount / 2;
+ }
+
+
+ /* set up values for the current FontDict and matrix; */
+ /* called for each glyph to be rendered */
+
+ /* caller's transform is adjusted for subpixel positioning */
+ static void
+ cf2_font_setup( CF2_Font font,
+ const CF2_Matrix* transform )
+ {
+ /* pointer to parsed font object */
+ PS_Decoder* decoder = font->decoder;
+
+ FT_Bool needExtraSetup = FALSE;
+
+ CFF_VStoreRec* vstore;
+ FT_Bool hasVariations = FALSE;
+
+ /* character space units */
+ CF2_Fixed boldenX = font->syntheticEmboldeningAmountX;
+ CF2_Fixed boldenY = font->syntheticEmboldeningAmountY;
+
+ CFF_SubFont subFont;
+ CF2_Fixed ppem;
+
+ CF2_UInt lenNormalizedV = 0;
+ FT_Fixed* normalizedV = NULL;
+
+ /* clear previous error */
+ font->error = FT_Err_Ok;
+
+ /* if a CID fontDict has changed, we need to recompute some cached */
+ /* data */
+ subFont = cf2_getSubfont( decoder );
+ if ( font->lastSubfont != subFont )
+ {
+ font->lastSubfont = subFont;
+ needExtraSetup = TRUE;
+ }
+
+ if ( !font->isT1 )
+ {
+ FT_Service_CFFLoad cffload = (FT_Service_CFFLoad)font->cffload;
+
+
+ /* check for variation vectors */
+ vstore = cf2_getVStore( decoder );
+ hasVariations = ( vstore->dataCount != 0 );
+
+ if ( hasVariations )
+ {
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+ /* check whether Private DICT in this subfont needs to be reparsed */
+ font->error = cf2_getNormalizedVector( decoder,
+ &lenNormalizedV,
+ &normalizedV );
+ if ( font->error )
+ return;
+
+ if ( cffload->blend_check_vector( &subFont->blend,
+ subFont->private_dict.vsindex,
+ lenNormalizedV,
+ normalizedV ) )
+ {
+ /* blend has changed, reparse */
+ cffload->load_private_dict( decoder->cff,
+ subFont,
+ lenNormalizedV,
+ normalizedV );
+ needExtraSetup = TRUE;
+ }
+#endif
+
+ /* copy from subfont */
+ font->blend.font = subFont->blend.font;
+
+ /* clear state of charstring blend */
+ font->blend.usedBV = FALSE;
+
+ /* initialize value for charstring */
+ font->vsindex = subFont->private_dict.vsindex;
+
+ /* store vector inputs for blends in charstring */
+ font->lenNDV = lenNormalizedV;
+ font->NDV = normalizedV;
+ }
+ }
+
+ /* if ppem has changed, we need to recompute some cached data */
+ /* note: because of CID font matrix concatenation, ppem and transform */
+ /* do not necessarily track. */
+ ppem = cf2_getPpemY( decoder );
+ if ( font->ppem != ppem )
+ {
+ font->ppem = ppem;
+ needExtraSetup = TRUE;
+ }
+
+ /* copy hinted flag on each call */
+ font->hinted = (FT_Bool)( font->renderingFlags & CF2_FlagsHinted );
+
+ /* determine if transform has changed; */
+ /* include Fontmatrix but ignore translation */
+ if ( ft_memcmp( transform,
+ &font->currentTransform,
+ 4 * sizeof ( CF2_Fixed ) ) != 0 )
+ {
+ /* save `key' information for `cache of one' matrix data; */
+ /* save client transform, without the translation */
+ font->currentTransform = *transform;
+ font->currentTransform.tx =
+ font->currentTransform.ty = cf2_intToFixed( 0 );
+
+ /* TODO: FreeType transform is simple scalar; for now, use identity */
+ /* for outer */
+ font->innerTransform = *transform;
+ font->outerTransform.a =
+ font->outerTransform.d = cf2_intToFixed( 1 );
+ font->outerTransform.b =
+ font->outerTransform.c = cf2_intToFixed( 0 );
+
+ needExtraSetup = TRUE;
+ }
+
+ /*
+ * font->darkened is set to true if there is a stem darkening request or
+ * the font is synthetic emboldened.
+ * font->darkened controls whether to adjust blue zones, winding order,
+ * and hinting.
+ *
+ */
+ if ( font->stemDarkened != ( font->renderingFlags & CF2_FlagsDarkened ) )
+ {
+ font->stemDarkened =
+ (FT_Bool)( font->renderingFlags & CF2_FlagsDarkened );
+
+ /* blue zones depend on darkened flag */
+ needExtraSetup = TRUE;
+ }
+
+ /* recompute variables that are dependent on transform or FontDict or */
+ /* darken flag */
+ if ( needExtraSetup )
+ {
+ /* StdVW is found in the private dictionary; */
+ /* recompute darkening amounts whenever private dictionary or */
+ /* transform change */
+ /* Note: a rendering flag turns darkening on or off, so we want to */
+ /* store the `on' amounts; */
+ /* darkening amount is computed in character space */
+ /* TODO: testing size-dependent darkening here; */
+ /* what to do for rotations? */
+
+ CF2_Fixed emRatio;
+ CF2_Fixed stdHW;
+ CF2_Int unitsPerEm = font->unitsPerEm;
+
+
+ if ( unitsPerEm == 0 )
+ unitsPerEm = 1000;
+
+ ppem = FT_MAX( cf2_intToFixed( 4 ),
+ font->ppem ); /* use minimum ppem of 4 */
+
+#if 0
+ /* since vstem is measured in the x-direction, we use the `a' member */
+ /* of the fontMatrix */
+ emRatio = cf2_fixedFracMul( cf2_intToFixed( 1000 ), fontMatrix->a );
+#endif
+
+ /* Freetype does not preserve the fontMatrix when parsing; use */
+ /* unitsPerEm instead. */
+ /* TODO: check precision of this */
+ emRatio = cf2_intToFixed( 1000 ) / unitsPerEm;
+ font->stdVW = cf2_getStdVW( decoder );
+
+ if ( font->stdVW <= 0 )
+ font->stdVW = FT_DivFix( cf2_intToFixed( 75 ), emRatio );
+
+ if ( boldenX > 0 )
+ {
+ /* Ensure that boldenX is at least 1 pixel for synthetic bold font */
+ /* (similar to what Avalon does) */
+ boldenX = FT_MAX( boldenX,
+ FT_DivFix( cf2_intToFixed( unitsPerEm ), ppem ) );
+
+ /* Synthetic emboldening adds at least 1 pixel to darkenX, while */
+ /* stem darkening adds at most half pixel. Since the purpose of */
+ /* stem darkening (readability at small sizes) is met with */
+ /* synthetic emboldening, no need to add stem darkening for a */
+ /* synthetic bold font. */
+ cf2_computeDarkening( emRatio,
+ ppem,
+ font->stdVW,
+ &font->darkenX,
+ boldenX,
+ FALSE,
+ font->darkenParams );
+ }
+ else
+ cf2_computeDarkening( emRatio,
+ ppem,
+ font->stdVW,
+ &font->darkenX,
+ 0,
+ font->stemDarkened,
+ font->darkenParams );
+
+#if 0
+ /* since hstem is measured in the y-direction, we use the `d' member */
+ /* of the fontMatrix */
+ /* TODO: use the same units per em as above; check this */
+ emRatio = cf2_fixedFracMul( cf2_intToFixed( 1000 ), fontMatrix->d );
+#endif
+
+ /* set the default stem width, because it must be the same for all */
+ /* family members; */
+ /* choose a constant for StdHW that depends on font contrast */
+ stdHW = cf2_getStdHW( decoder );
+
+ if ( stdHW > 0 && font->stdVW > MUL_INT32( 2, stdHW ) )
+ font->stdHW = FT_DivFix( cf2_intToFixed( 75 ), emRatio );
+ else
+ {
+ /* low contrast font gets less hstem darkening */
+ font->stdHW = FT_DivFix( cf2_intToFixed( 110 ), emRatio );
+ }
+
+ cf2_computeDarkening( emRatio,
+ ppem,
+ font->stdHW,
+ &font->darkenY,
+ boldenY,
+ font->stemDarkened,
+ font->darkenParams );
+
+ if ( font->darkenX != 0 || font->darkenY != 0 )
+ font->darkened = TRUE;
+ else
+ font->darkened = FALSE;
+
+ font->reverseWinding = FALSE; /* initial expectation is CCW */
+
+ /* compute blue zones for this instance */
+ cf2_blues_init( &font->blues, font );
+
+ } /* needExtraSetup */
+ }
+
+
+ /* equivalent to AdobeGetOutline */
+ FT_LOCAL_DEF( FT_Error )
+ cf2_getGlyphOutline( CF2_Font font,
+ CF2_Buffer charstring,
+ const CF2_Matrix* transform,
+ CF2_F16Dot16* glyphWidth )
+ {
+ FT_Error lastError = FT_Err_Ok;
+
+ FT_Vector translation;
+
+#if 0
+ FT_Vector advancePoint;
+#endif
+
+ CF2_Fixed advWidth = 0;
+ FT_Bool needWinding;
+
+
+ /* Note: use both integer and fraction for outlines. This allows bbox */
+ /* to come out directly. */
+
+ translation.x = transform->tx;
+ translation.y = transform->ty;
+
+ /* set up values based on transform */
+ cf2_font_setup( font, transform );
+ if ( font->error )
+ goto exit; /* setup encountered an error */
+
+ /* reset darken direction */
+ font->reverseWinding = FALSE;
+
+ /* winding order only affects darkening */
+ needWinding = font->darkened;
+
+ while ( 1 )
+ {
+ /* reset output buffer */
+ cf2_outline_reset( &font->outline );
+
+ /* build the outline, passing the full translation */
+ cf2_interpT2CharString( font,
+ charstring,
+ (CF2_OutlineCallbacks)&font->outline,
+ &translation,
+ FALSE,
+ 0,
+ 0,
+ &advWidth );
+
+ if ( font->error )
+ goto exit;
+
+ if ( !needWinding )
+ break;
+
+ /* check winding order */
+ if ( font->outline.root.windingMomentum >= 0 ) /* CFF is CCW */
+ break;
+
+ /* invert darkening and render again */
+ /* TODO: this should be a parameter to getOutline-computeOffset */
+ font->reverseWinding = TRUE;
+
+ needWinding = FALSE; /* exit after next iteration */
+ }
+
+ /* finish storing client outline */
+ cf2_outline_close( &font->outline );
+
+ exit:
+ /* FreeType just wants the advance width; there is no translation */
+ *glyphWidth = advWidth;
+
+ /* free resources and collect errors from objects we've used */
+ cf2_setError( &font->error, lastError );
+
+ return font->error;
+ }
+
+
+/* END */
diff --git a/thirdparty/freetype/src/psaux/psfont.h b/thirdparty/freetype/src/psaux/psfont.h
new file mode 100644
index 0000000000..e611ac4bdc
--- /dev/null
+++ b/thirdparty/freetype/src/psaux/psfont.h
@@ -0,0 +1,134 @@
+/***************************************************************************/
+/* */
+/* psfont.h */
+/* */
+/* Adobe's code for font instances (specification). */
+/* */
+/* Copyright 2007-2013 Adobe Systems Incorporated. */
+/* */
+/* This software, and all works of authorship, whether in source or */
+/* object code form as indicated by the copyright notice(s) included */
+/* herein (collectively, the "Work") is made available, and may only be */
+/* used, modified, and distributed under the FreeType Project License, */
+/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
+/* FreeType Project License, each contributor to the Work hereby grants */
+/* to any individual or legal entity exercising permissions granted by */
+/* the FreeType Project License and this section (hereafter, "You" or */
+/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
+/* royalty-free, irrevocable (except as stated in this section) patent */
+/* license to make, have made, use, offer to sell, sell, import, and */
+/* otherwise transfer the Work, where such license applies only to those */
+/* patent claims licensable by such contributor that are necessarily */
+/* infringed by their contribution(s) alone or by combination of their */
+/* contribution(s) with the Work to which such contribution(s) was */
+/* submitted. If You institute patent litigation against any entity */
+/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
+/* the Work or a contribution incorporated within the Work constitutes */
+/* direct or contributory patent infringement, then any patent licenses */
+/* granted to You under this License for that Work shall terminate as of */
+/* the date such litigation is filed. */
+/* */
+/* By using, modifying, or distributing the Work you indicate that you */
+/* have read and understood the terms and conditions of the */
+/* FreeType Project License as well as those provided in this section, */
+/* and you accept them fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef PSFONT_H_
+#define PSFONT_H_
+
+
+#include FT_SERVICE_CFF_TABLE_LOAD_H
+
+#include "psft.h"
+#include "psblues.h"
+
+
+FT_BEGIN_HEADER
+
+
+#define CF2_OPERAND_STACK_SIZE 48
+#define CF2_MAX_SUBR 16 /* maximum subroutine nesting; */
+ /* only 10 are allowed but there exist */
+ /* fonts like `HiraKakuProN-W3.ttf' */
+ /* (Hiragino Kaku Gothic ProN W3; */
+ /* 8.2d6e1; 2014-12-19) that exceed */
+ /* this limit */
+#define CF2_STORAGE_SIZE 32
+
+
+ /* typedef is in `cf2glue.h' */
+ struct CF2_FontRec_
+ {
+ FT_Memory memory;
+ FT_Error error; /* shared error for this instance */
+
+ FT_Bool isT1;
+ FT_Bool isCFF2;
+ CF2_RenderingFlags renderingFlags;
+
+ /* variables that depend on Transform: */
+ /* the following have zero translation; */
+ /* inner * outer = font * original */
+
+ CF2_Matrix currentTransform; /* original client matrix */
+ CF2_Matrix innerTransform; /* for hinting; erect, scaled */
+ CF2_Matrix outerTransform; /* post hinting; includes rotations */
+ CF2_Fixed ppem; /* transform-dependent */
+
+ /* variation data */
+ CFF_BlendRec blend; /* cached charstring blend vector */
+ CF2_UInt vsindex; /* current vsindex */
+ CF2_UInt lenNDV; /* current length NDV or zero */
+ FT_Fixed* NDV; /* ptr to current NDV or NULL */
+
+ CF2_Int unitsPerEm;
+
+ CF2_Fixed syntheticEmboldeningAmountX; /* character space units */
+ CF2_Fixed syntheticEmboldeningAmountY; /* character space units */
+
+ /* FreeType related members */
+ CF2_OutlineRec outline; /* freetype glyph outline functions */
+ PS_Decoder* decoder;
+ CFF_SubFont lastSubfont; /* FreeType parsed data; */
+ /* top font or subfont */
+
+ /* these flags can vary from one call to the next */
+ FT_Bool hinted;
+ FT_Bool darkened; /* true if stemDarkened or synthetic bold */
+ /* i.e. darkenX != 0 || darkenY != 0 */
+ FT_Bool stemDarkened;
+
+ FT_Int darkenParams[8]; /* 1000 unit character space */
+
+ /* variables that depend on both FontDict and Transform */
+ CF2_Fixed stdVW; /* in character space; depends on dict entry */
+ CF2_Fixed stdHW; /* in character space; depends on dict entry */
+ CF2_Fixed darkenX; /* character space units */
+ CF2_Fixed darkenY; /* depends on transform */
+ /* and private dict (StdVW) */
+ FT_Bool reverseWinding; /* darken assuming */
+ /* counterclockwise winding */
+
+ CF2_BluesRec blues; /* computed zone data */
+
+ FT_Service_CFFLoad cffload; /* pointer to cff functions */
+ };
+
+
+ FT_LOCAL( FT_Error )
+ cf2_getGlyphOutline( CF2_Font font,
+ CF2_Buffer charstring,
+ const CF2_Matrix* transform,
+ CF2_F16Dot16* glyphWidth );
+
+
+FT_END_HEADER
+
+
+#endif /* PSFONT_H_ */
+
+
+/* END */
diff --git a/thirdparty/freetype/src/psaux/psft.c b/thirdparty/freetype/src/psaux/psft.c
new file mode 100644
index 0000000000..1f750174a1
--- /dev/null
+++ b/thirdparty/freetype/src/psaux/psft.c
@@ -0,0 +1,890 @@
+/***************************************************************************/
+/* */
+/* psft.c */
+/* */
+/* FreeType Glue Component to Adobe's Interpreter (body). */
+/* */
+/* Copyright 2013-2014 Adobe Systems Incorporated. */
+/* */
+/* This software, and all works of authorship, whether in source or */
+/* object code form as indicated by the copyright notice(s) included */
+/* herein (collectively, the "Work") is made available, and may only be */
+/* used, modified, and distributed under the FreeType Project License, */
+/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
+/* FreeType Project License, each contributor to the Work hereby grants */
+/* to any individual or legal entity exercising permissions granted by */
+/* the FreeType Project License and this section (hereafter, "You" or */
+/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
+/* royalty-free, irrevocable (except as stated in this section) patent */
+/* license to make, have made, use, offer to sell, sell, import, and */
+/* otherwise transfer the Work, where such license applies only to those */
+/* patent claims licensable by such contributor that are necessarily */
+/* infringed by their contribution(s) alone or by combination of their */
+/* contribution(s) with the Work to which such contribution(s) was */
+/* submitted. If You institute patent litigation against any entity */
+/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
+/* the Work or a contribution incorporated within the Work constitutes */
+/* direct or contributory patent infringement, then any patent licenses */
+/* granted to You under this License for that Work shall terminate as of */
+/* the date such litigation is filed. */
+/* */
+/* By using, modifying, or distributing the Work you indicate that you */
+/* have read and understood the terms and conditions of the */
+/* FreeType Project License as well as those provided in this section, */
+/* and you accept them fully. */
+/* */
+/***************************************************************************/
+
+
+#include "psft.h"
+#include FT_INTERNAL_DEBUG_H
+
+#include "psfont.h"
+#include "pserror.h"
+#include "psobjs.h"
+#include "cffdecode.h"
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+#include FT_MULTIPLE_MASTERS_H
+#include FT_SERVICE_MULTIPLE_MASTERS_H
+#endif
+
+#include FT_SERVICE_CFF_TABLE_LOAD_H
+
+
+#define CF2_MAX_SIZE cf2_intToFixed( 2000 ) /* max ppem */
+
+
+ /*
+ * This check should avoid most internal overflow cases. Clients should
+ * generally respond to `Glyph_Too_Big' by getting a glyph outline
+ * at EM size, scaling it and filling it as a graphics operation.
+ *
+ */
+ static FT_Error
+ cf2_checkTransform( const CF2_Matrix* transform,
+ CF2_Int unitsPerEm )
+ {
+ CF2_Fixed maxScale;
+
+
+ FT_ASSERT( unitsPerEm > 0 );
+
+ if ( transform->a <= 0 || transform->d <= 0 )
+ return FT_THROW( Invalid_Size_Handle );
+
+ FT_ASSERT( transform->b == 0 && transform->c == 0 );
+ FT_ASSERT( transform->tx == 0 && transform->ty == 0 );
+
+ if ( unitsPerEm > 0x7FFF )
+ return FT_THROW( Glyph_Too_Big );
+
+ maxScale = FT_DivFix( CF2_MAX_SIZE, cf2_intToFixed( unitsPerEm ) );
+
+ if ( transform->a > maxScale || transform->d > maxScale )
+ return FT_THROW( Glyph_Too_Big );
+
+ return FT_Err_Ok;
+ }
+
+
+ static void
+ cf2_setGlyphWidth( CF2_Outline outline,
+ CF2_Fixed width )
+ {
+ PS_Decoder* decoder = outline->decoder;
+
+
+ FT_ASSERT( decoder );
+
+ if ( !decoder->builder.is_t1 )
+ *decoder->glyph_width = cf2_fixedToInt( width );
+ }
+
+
+ /* Clean up font instance. */
+ static void
+ cf2_free_instance( void* ptr )
+ {
+ CF2_Font font = (CF2_Font)ptr;
+
+
+ if ( font )
+ {
+ FT_Memory memory = font->memory;
+
+
+ FT_FREE( font->blend.lastNDV );
+ FT_FREE( font->blend.BV );
+ }
+ }
+
+
+ /********************************************/
+ /* */
+ /* functions for handling client outline; */
+ /* FreeType uses coordinates in 26.6 format */
+ /* */
+ /********************************************/
+
+ static void
+ cf2_builder_moveTo( CF2_OutlineCallbacks callbacks,
+ const CF2_CallbackParams params )
+ {
+ /* downcast the object pointer */
+ CF2_Outline outline = (CF2_Outline)callbacks;
+ PS_Builder* builder;
+
+ (void)params; /* only used in debug mode */
+
+
+ FT_ASSERT( outline && outline->decoder );
+ FT_ASSERT( params->op == CF2_PathOpMoveTo );
+
+ builder = &outline->decoder->builder;
+
+ /* note: two successive moves simply close the contour twice */
+ ps_builder_close_contour( builder );
+ builder->path_begun = 0;
+ }
+
+
+ static void
+ cf2_builder_lineTo( CF2_OutlineCallbacks callbacks,
+ const CF2_CallbackParams params )
+ {
+ FT_Error error;
+
+ /* downcast the object pointer */
+ CF2_Outline outline = (CF2_Outline)callbacks;
+ PS_Builder* builder;
+
+
+ FT_ASSERT( outline && outline->decoder );
+ FT_ASSERT( params->op == CF2_PathOpLineTo );
+
+ builder = &outline->decoder->builder;
+
+ if ( !builder->path_begun )
+ {
+ /* record the move before the line; also check points and set */
+ /* `path_begun' */
+ error = ps_builder_start_point( builder,
+ params->pt0.x,
+ params->pt0.y );
+ if ( error )
+ {
+ if ( !*callbacks->error )
+ *callbacks->error = error;
+ return;
+ }
+ }
+
+ /* `ps_builder_add_point1' includes a check_points call for one point */
+ error = ps_builder_add_point1( builder,
+ params->pt1.x,
+ params->pt1.y );
+ if ( error )
+ {
+ if ( !*callbacks->error )
+ *callbacks->error = error;
+ return;
+ }
+ }
+
+
+ static void
+ cf2_builder_cubeTo( CF2_OutlineCallbacks callbacks,
+ const CF2_CallbackParams params )
+ {
+ FT_Error error;
+
+ /* downcast the object pointer */
+ CF2_Outline outline = (CF2_Outline)callbacks;
+ PS_Builder* builder;
+
+
+ FT_ASSERT( outline && outline->decoder );
+ FT_ASSERT( params->op == CF2_PathOpCubeTo );
+
+ builder = &outline->decoder->builder;
+
+ if ( !builder->path_begun )
+ {
+ /* record the move before the line; also check points and set */
+ /* `path_begun' */
+ error = ps_builder_start_point( builder,
+ params->pt0.x,
+ params->pt0.y );
+ if ( error )
+ {
+ if ( !*callbacks->error )
+ *callbacks->error = error;
+ return;
+ }
+ }
+
+ /* prepare room for 3 points: 2 off-curve, 1 on-curve */
+ error = ps_builder_check_points( builder, 3 );
+ if ( error )
+ {
+ if ( !*callbacks->error )
+ *callbacks->error = error;
+ return;
+ }
+
+ ps_builder_add_point( builder,
+ params->pt1.x,
+ params->pt1.y, 0 );
+ ps_builder_add_point( builder,
+ params->pt2.x,
+ params->pt2.y, 0 );
+ ps_builder_add_point( builder,
+ params->pt3.x,
+ params->pt3.y, 1 );
+ }
+
+
+ static void
+ cf2_outline_init( CF2_Outline outline,
+ FT_Memory memory,
+ FT_Error* error )
+ {
+ FT_ZERO( outline );
+
+ outline->root.memory = memory;
+ outline->root.error = error;
+
+ outline->root.moveTo = cf2_builder_moveTo;
+ outline->root.lineTo = cf2_builder_lineTo;
+ outline->root.cubeTo = cf2_builder_cubeTo;
+ }
+
+
+ /* get scaling and hint flag from GlyphSlot */
+ static void
+ cf2_getScaleAndHintFlag( PS_Decoder* decoder,
+ CF2_Fixed* x_scale,
+ CF2_Fixed* y_scale,
+ FT_Bool* hinted,
+ FT_Bool* scaled )
+ {
+ FT_ASSERT( decoder && decoder->builder.glyph );
+
+ /* note: FreeType scale includes a factor of 64 */
+ *hinted = decoder->builder.glyph->hint;
+ *scaled = decoder->builder.glyph->scaled;
+
+ if ( *hinted )
+ {
+ *x_scale = ADD_INT32( decoder->builder.glyph->x_scale, 32 ) / 64;
+ *y_scale = ADD_INT32( decoder->builder.glyph->y_scale, 32 ) / 64;
+ }
+ else
+ {
+ /* for unhinted outlines, `cff_slot_load' does the scaling, */
+ /* thus render at `unity' scale */
+
+ *x_scale = 0x0400; /* 1/64 as 16.16 */
+ *y_scale = 0x0400;
+ }
+ }
+
+
+ /* get units per em from `FT_Face' */
+ /* TODO: should handle font matrix concatenation? */
+ static FT_UShort
+ cf2_getUnitsPerEm( PS_Decoder* decoder )
+ {
+ FT_ASSERT( decoder && decoder->builder.face );
+ FT_ASSERT( decoder->builder.face->units_per_EM );
+
+ return decoder->builder.face->units_per_EM;
+ }
+
+
+ /* Main entry point: Render one glyph. */
+ FT_LOCAL_DEF( FT_Error )
+ cf2_decoder_parse_charstrings( PS_Decoder* decoder,
+ FT_Byte* charstring_base,
+ FT_ULong charstring_len )
+ {
+ FT_Memory memory;
+ FT_Error error = FT_Err_Ok;
+ CF2_Font font;
+
+ FT_Bool is_t1 = decoder->builder.is_t1;
+
+
+ FT_ASSERT( decoder &&
+ ( is_t1 || decoder->cff ) );
+
+ if ( is_t1 && !decoder->current_subfont )
+ {
+ FT_ERROR(( "cf2_decoder_parse_charstrings (Type 1): "
+ "SubFont missing. Use `t1_make_subfont' first\n" ));
+ return FT_THROW( Invalid_Table );
+ }
+
+ memory = decoder->builder.memory;
+
+ /* CF2 data is saved here across glyphs */
+ font = (CF2_Font)decoder->cf2_instance->data;
+
+ /* on first glyph, allocate instance structure */
+ if ( !decoder->cf2_instance->data )
+ {
+ decoder->cf2_instance->finalizer =
+ (FT_Generic_Finalizer)cf2_free_instance;
+
+ if ( FT_ALLOC( decoder->cf2_instance->data,
+ sizeof ( CF2_FontRec ) ) )
+ return FT_THROW( Out_Of_Memory );
+
+ font = (CF2_Font)decoder->cf2_instance->data;
+
+ font->memory = memory;
+
+ if ( !is_t1 )
+ font->cffload = (FT_Service_CFFLoad)decoder->cff->cffload;
+
+ /* initialize a client outline, to be shared by each glyph rendered */
+ cf2_outline_init( &font->outline, font->memory, &font->error );
+ }
+
+ /* save decoder; it is a stack variable and will be different on each */
+ /* call */
+ font->decoder = decoder;
+ font->outline.decoder = decoder;
+
+ {
+ /* build parameters for Adobe engine */
+
+ PS_Builder* builder = &decoder->builder;
+ PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( builder->face );
+
+ FT_Bool no_stem_darkening_driver =
+ driver->no_stem_darkening;
+ FT_Char no_stem_darkening_font =
+ builder->face->internal->no_stem_darkening;
+
+ /* local error */
+ FT_Error error2 = FT_Err_Ok;
+ CF2_BufferRec buf;
+ CF2_Matrix transform;
+ CF2_F16Dot16 glyphWidth;
+
+ FT_Bool hinted;
+ FT_Bool scaled;
+
+
+ /* FreeType has already looked up the GID; convert to */
+ /* `RegionBuffer', assuming that the input has been validated */
+ FT_ASSERT( charstring_base + charstring_len >= charstring_base );
+
+ FT_ZERO( &buf );
+ buf.start =
+ buf.ptr = charstring_base;
+ buf.end = charstring_base + charstring_len;
+
+ FT_ZERO( &transform );
+
+ cf2_getScaleAndHintFlag( decoder,
+ &transform.a,
+ &transform.d,
+ &hinted,
+ &scaled );
+
+ if ( is_t1 )
+ font->isCFF2 = FALSE;
+ else
+ {
+ /* copy isCFF2 boolean from TT_Face to CF2_Font */
+ font->isCFF2 = ((TT_Face)builder->face)->is_cff2;
+ }
+ font->isT1 = is_t1;
+
+ font->renderingFlags = 0;
+ if ( hinted )
+ font->renderingFlags |= CF2_FlagsHinted;
+ if ( scaled && ( !no_stem_darkening_font ||
+ ( no_stem_darkening_font < 0 &&
+ !no_stem_darkening_driver ) ) )
+ font->renderingFlags |= CF2_FlagsDarkened;
+
+ font->darkenParams[0] = driver->darken_params[0];
+ font->darkenParams[1] = driver->darken_params[1];
+ font->darkenParams[2] = driver->darken_params[2];
+ font->darkenParams[3] = driver->darken_params[3];
+ font->darkenParams[4] = driver->darken_params[4];
+ font->darkenParams[5] = driver->darken_params[5];
+ font->darkenParams[6] = driver->darken_params[6];
+ font->darkenParams[7] = driver->darken_params[7];
+
+ /* now get an outline for this glyph; */
+ /* also get units per em to validate scale */
+ font->unitsPerEm = (CF2_Int)cf2_getUnitsPerEm( decoder );
+
+ if ( scaled )
+ {
+ error2 = cf2_checkTransform( &transform, font->unitsPerEm );
+ if ( error2 )
+ return error2;
+ }
+
+ error2 = cf2_getGlyphOutline( font, &buf, &transform, &glyphWidth );
+ if ( error2 )
+ return FT_ERR( Invalid_File_Format );
+
+ cf2_setGlyphWidth( &font->outline, glyphWidth );
+
+ return FT_Err_Ok;
+ }
+ }
+
+
+ /* get pointer to current FreeType subfont (based on current glyphID) */
+ FT_LOCAL_DEF( CFF_SubFont )
+ cf2_getSubfont( PS_Decoder* decoder )
+ {
+ FT_ASSERT( decoder && decoder->current_subfont );
+
+ return decoder->current_subfont;
+ }
+
+
+ /* get pointer to VStore structure */
+ FT_LOCAL_DEF( CFF_VStore )
+ cf2_getVStore( PS_Decoder* decoder )
+ {
+ FT_ASSERT( decoder && decoder->cff );
+
+ return &decoder->cff->vstore;
+ }
+
+
+ /* get maxstack value from CFF2 Top DICT */
+ FT_LOCAL_DEF( FT_UInt )
+ cf2_getMaxstack( PS_Decoder* decoder )
+ {
+ FT_ASSERT( decoder && decoder->cff );
+
+ return decoder->cff->top_font.font_dict.maxstack;
+ }
+
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+ /* Get normalized design vector for current render request; */
+ /* return pointer and length. */
+ /* */
+ /* Note: Uses FT_Fixed not CF2_Fixed for the vector. */
+ FT_LOCAL_DEF( FT_Error )
+ cf2_getNormalizedVector( PS_Decoder* decoder,
+ CF2_UInt *len,
+ FT_Fixed* *vec )
+ {
+ TT_Face face;
+ FT_Service_MultiMasters mm;
+
+
+ FT_ASSERT( decoder && decoder->builder.face );
+ FT_ASSERT( vec && len );
+ FT_ASSERT( !decoder->builder.is_t1 );
+
+ face = (TT_Face)decoder->builder.face;
+ mm = (FT_Service_MultiMasters)face->mm;
+
+ return mm->get_var_blend( FT_FACE( face ), len, NULL, vec, NULL );
+ }
+#endif
+
+
+ /* get `y_ppem' from `CFF_Size' */
+ FT_LOCAL_DEF( CF2_Fixed )
+ cf2_getPpemY( PS_Decoder* decoder )
+ {
+ FT_ASSERT( decoder &&
+ decoder->builder.face &&
+ decoder->builder.face->size );
+
+ /*
+ * Note that `y_ppem' can be zero if there wasn't a call to
+ * `FT_Set_Char_Size' or something similar. However, this isn't a
+ * problem since we come to this place in the code only if
+ * FT_LOAD_NO_SCALE is set (the other case gets caught by
+ * `cf2_checkTransform'). The ppem value is needed to compute the stem
+ * darkening, which is disabled for getting the unscaled outline.
+ *
+ */
+ return cf2_intToFixed(
+ decoder->builder.face->size->metrics.y_ppem );
+ }
+
+
+ /* get standard stem widths for the current subfont; */
+ /* FreeType stores these as integer font units */
+ /* (note: variable names seem swapped) */
+ FT_LOCAL_DEF( CF2_Fixed )
+ cf2_getStdVW( PS_Decoder* decoder )
+ {
+ FT_ASSERT( decoder && decoder->current_subfont );
+
+ return cf2_intToFixed(
+ decoder->current_subfont->private_dict.standard_height );
+ }
+
+
+ FT_LOCAL_DEF( CF2_Fixed )
+ cf2_getStdHW( PS_Decoder* decoder )
+ {
+ FT_ASSERT( decoder && decoder->current_subfont );
+
+ return cf2_intToFixed(
+ decoder->current_subfont->private_dict.standard_width );
+ }
+
+
+ /* note: FreeType stores 1000 times the actual value for `BlueScale' */
+ FT_LOCAL_DEF( void )
+ cf2_getBlueMetrics( PS_Decoder* decoder,
+ CF2_Fixed* blueScale,
+ CF2_Fixed* blueShift,
+ CF2_Fixed* blueFuzz )
+ {
+ FT_ASSERT( decoder && decoder->current_subfont );
+
+ *blueScale = FT_DivFix(
+ decoder->current_subfont->private_dict.blue_scale,
+ cf2_intToFixed( 1000 ) );
+ *blueShift = cf2_intToFixed(
+ decoder->current_subfont->private_dict.blue_shift );
+ *blueFuzz = cf2_intToFixed(
+ decoder->current_subfont->private_dict.blue_fuzz );
+ }
+
+
+ /* get blue values counts and arrays; the FreeType parser has validated */
+ /* the counts and verified that each is an even number */
+ FT_LOCAL_DEF( void )
+ cf2_getBlueValues( PS_Decoder* decoder,
+ size_t* count,
+ FT_Pos* *data )
+ {
+ FT_ASSERT( decoder && decoder->current_subfont );
+
+ *count = decoder->current_subfont->private_dict.num_blue_values;
+ *data = (FT_Pos*)
+ &decoder->current_subfont->private_dict.blue_values;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cf2_getOtherBlues( PS_Decoder* decoder,
+ size_t* count,
+ FT_Pos* *data )
+ {
+ FT_ASSERT( decoder && decoder->current_subfont );
+
+ *count = decoder->current_subfont->private_dict.num_other_blues;
+ *data = (FT_Pos*)
+ &decoder->current_subfont->private_dict.other_blues;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cf2_getFamilyBlues( PS_Decoder* decoder,
+ size_t* count,
+ FT_Pos* *data )
+ {
+ FT_ASSERT( decoder && decoder->current_subfont );
+
+ *count = decoder->current_subfont->private_dict.num_family_blues;
+ *data = (FT_Pos*)
+ &decoder->current_subfont->private_dict.family_blues;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cf2_getFamilyOtherBlues( PS_Decoder* decoder,
+ size_t* count,
+ FT_Pos* *data )
+ {
+ FT_ASSERT( decoder && decoder->current_subfont );
+
+ *count = decoder->current_subfont->private_dict.num_family_other_blues;
+ *data = (FT_Pos*)
+ &decoder->current_subfont->private_dict.family_other_blues;
+ }
+
+
+ FT_LOCAL_DEF( CF2_Int )
+ cf2_getLanguageGroup( PS_Decoder* decoder )
+ {
+ FT_ASSERT( decoder && decoder->current_subfont );
+
+ return decoder->current_subfont->private_dict.language_group;
+ }
+
+
+ /* convert unbiased subroutine index to `CF2_Buffer' and */
+ /* return 0 on success */
+ FT_LOCAL_DEF( CF2_Int )
+ cf2_initGlobalRegionBuffer( PS_Decoder* decoder,
+ CF2_Int subrNum,
+ CF2_Buffer buf )
+ {
+ CF2_UInt idx;
+
+
+ FT_ASSERT( decoder );
+
+ FT_ZERO( buf );
+
+ idx = (CF2_UInt)( subrNum + decoder->globals_bias );
+ if ( idx >= decoder->num_globals )
+ return TRUE; /* error */
+
+ FT_ASSERT( decoder->globals );
+
+ buf->start =
+ buf->ptr = decoder->globals[idx];
+ buf->end = decoder->globals[idx + 1];
+
+ return FALSE; /* success */
+ }
+
+
+ /* convert AdobeStandardEncoding code to CF2_Buffer; */
+ /* used for seac component */
+ FT_LOCAL_DEF( FT_Error )
+ cf2_getSeacComponent( PS_Decoder* decoder,
+ CF2_Int code,
+ CF2_Buffer buf )
+ {
+ CF2_Int gid;
+ FT_Byte* charstring;
+ FT_ULong len;
+ FT_Error error;
+
+
+ FT_ASSERT( decoder );
+ FT_ASSERT( !decoder->builder.is_t1 );
+
+ FT_ZERO( buf );
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+ /* Incremental fonts don't necessarily have valid charsets. */
+ /* They use the character code, not the glyph index, in this case. */
+ if ( decoder->builder.face->internal->incremental_interface )
+ gid = code;
+ else
+#endif /* FT_CONFIG_OPTION_INCREMENTAL */
+ {
+ gid = cff_lookup_glyph_by_stdcharcode( decoder->cff, code );
+ if ( gid < 0 )
+ return FT_THROW( Invalid_Glyph_Format );
+ }
+
+ error = decoder->get_glyph_callback( (TT_Face)decoder->builder.face,
+ (CF2_UInt)gid,
+ &charstring,
+ &len );
+ /* TODO: for now, just pass the FreeType error through */
+ if ( error )
+ return error;
+
+ /* assume input has been validated */
+ FT_ASSERT( charstring + len >= charstring );
+
+ buf->start = charstring;
+ buf->end = charstring + len;
+ buf->ptr = buf->start;
+
+ return FT_Err_Ok;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cf2_freeSeacComponent( PS_Decoder* decoder,
+ CF2_Buffer buf )
+ {
+ FT_ASSERT( decoder );
+ FT_ASSERT( !decoder->builder.is_t1 );
+
+ decoder->free_glyph_callback( (TT_Face)decoder->builder.face,
+ (FT_Byte**)&buf->start,
+ (FT_ULong)( buf->end - buf->start ) );
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ cf2_getT1SeacComponent( PS_Decoder* decoder,
+ FT_UInt glyph_index,
+ CF2_Buffer buf )
+ {
+ FT_Data glyph_data;
+ FT_Error error = FT_Err_Ok;
+ T1_Face face = (T1_Face)decoder->builder.face;
+ T1_Font type1 = &face->type1;
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+ FT_Incremental_InterfaceRec *inc =
+ face->root.internal->incremental_interface;
+
+
+ /* For incremental fonts get the character data using the */
+ /* callback function. */
+ if ( inc )
+ error = inc->funcs->get_glyph_data( inc->object,
+ glyph_index, &glyph_data );
+ else
+#endif
+ /* For ordinary fonts get the character data stored in the face record. */
+ {
+ glyph_data.pointer = type1->charstrings[glyph_index];
+ glyph_data.length = (FT_Int)type1->charstrings_len[glyph_index];
+ }
+
+ if ( !error )
+ {
+ FT_Byte* charstring_base = (FT_Byte*)glyph_data.pointer;
+ FT_ULong charstring_len = (FT_ULong)glyph_data.length;
+
+
+ FT_ASSERT( charstring_base + charstring_len >= charstring_base );
+
+ FT_ZERO( buf );
+ buf->start =
+ buf->ptr = charstring_base;
+ buf->end = charstring_base + charstring_len;
+ }
+
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cf2_freeT1SeacComponent( PS_Decoder* decoder,
+ CF2_Buffer buf )
+ {
+ T1_Face face;
+ FT_Data data;
+
+
+ FT_ASSERT( decoder );
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+ face = (T1_Face)decoder->builder.face;
+
+ data.pointer = buf->start;
+ data.length = (FT_Int)( buf->end - buf->start );
+
+ if ( face->root.internal->incremental_interface )
+ face->root.internal->incremental_interface->funcs->free_glyph_data(
+ face->root.internal->incremental_interface->object,
+ &data );
+#endif /* FT_CONFIG_OPTION_INCREMENTAL */
+ }
+
+
+ FT_LOCAL_DEF( CF2_Int )
+ cf2_initLocalRegionBuffer( PS_Decoder* decoder,
+ CF2_Int subrNum,
+ CF2_Buffer buf )
+ {
+ CF2_UInt idx;
+
+
+ FT_ASSERT( decoder );
+
+ FT_ZERO( buf );
+
+ idx = (CF2_UInt)( subrNum + decoder->locals_bias );
+ if ( idx >= decoder->num_locals )
+ return TRUE; /* error */
+
+ FT_ASSERT( decoder->locals );
+
+ buf->start = decoder->locals[idx];
+
+ if ( decoder->builder.is_t1 )
+ {
+ /* The Type 1 driver stores subroutines without the seed bytes. */
+ /* The CID driver stores subroutines with seed bytes. This */
+ /* case is taken care of when decoder->subrs_len == 0. */
+ if ( decoder->locals_len )
+ buf->end = buf->start + decoder->locals_len[idx];
+ else
+ {
+ /* We are using subroutines from a CID font. We must adjust */
+ /* for the seed bytes. */
+ buf->start += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 );
+ buf->end = decoder->locals[idx + 1];
+ }
+
+ if ( !buf->start )
+ {
+ FT_ERROR(( "cf2_initLocalRegionBuffer (Type 1 mode):"
+ " invoking empty subrs\n" ));
+ }
+ }
+ else
+ {
+ buf->end = decoder->locals[idx + 1];
+ }
+
+ buf->ptr = buf->start;
+
+ return FALSE; /* success */
+ }
+
+
+ FT_LOCAL_DEF( CF2_Fixed )
+ cf2_getDefaultWidthX( PS_Decoder* decoder )
+ {
+ FT_ASSERT( decoder && decoder->current_subfont );
+
+ return cf2_intToFixed(
+ decoder->current_subfont->private_dict.default_width );
+ }
+
+
+ FT_LOCAL_DEF( CF2_Fixed )
+ cf2_getNominalWidthX( PS_Decoder* decoder )
+ {
+ FT_ASSERT( decoder && decoder->current_subfont );
+
+ return cf2_intToFixed(
+ decoder->current_subfont->private_dict.nominal_width );
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cf2_outline_reset( CF2_Outline outline )
+ {
+ PS_Decoder* decoder = outline->decoder;
+
+
+ FT_ASSERT( decoder );
+
+ outline->root.windingMomentum = 0;
+
+ FT_GlyphLoader_Rewind( decoder->builder.loader );
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cf2_outline_close( CF2_Outline outline )
+ {
+ PS_Decoder* decoder = outline->decoder;
+
+
+ FT_ASSERT( decoder );
+
+ ps_builder_close_contour( &decoder->builder );
+
+ FT_GlyphLoader_Add( decoder->builder.loader );
+ }
+
+
+/* END */
diff --git a/thirdparty/freetype/src/psaux/psft.h b/thirdparty/freetype/src/psaux/psft.h
new file mode 100644
index 0000000000..ab172110bb
--- /dev/null
+++ b/thirdparty/freetype/src/psaux/psft.h
@@ -0,0 +1,167 @@
+/***************************************************************************/
+/* */
+/* psft.h */
+/* */
+/* FreeType Glue Component to Adobe's Interpreter (specification). */
+/* */
+/* Copyright 2013 Adobe Systems Incorporated. */
+/* */
+/* This software, and all works of authorship, whether in source or */
+/* object code form as indicated by the copyright notice(s) included */
+/* herein (collectively, the "Work") is made available, and may only be */
+/* used, modified, and distributed under the FreeType Project License, */
+/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
+/* FreeType Project License, each contributor to the Work hereby grants */
+/* to any individual or legal entity exercising permissions granted by */
+/* the FreeType Project License and this section (hereafter, "You" or */
+/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
+/* royalty-free, irrevocable (except as stated in this section) patent */
+/* license to make, have made, use, offer to sell, sell, import, and */
+/* otherwise transfer the Work, where such license applies only to those */
+/* patent claims licensable by such contributor that are necessarily */
+/* infringed by their contribution(s) alone or by combination of their */
+/* contribution(s) with the Work to which such contribution(s) was */
+/* submitted. If You institute patent litigation against any entity */
+/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
+/* the Work or a contribution incorporated within the Work constitutes */
+/* direct or contributory patent infringement, then any patent licenses */
+/* granted to You under this License for that Work shall terminate as of */
+/* the date such litigation is filed. */
+/* */
+/* By using, modifying, or distributing the Work you indicate that you */
+/* have read and understood the terms and conditions of the */
+/* FreeType Project License as well as those provided in this section, */
+/* and you accept them fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef PSFT_H_
+#define PSFT_H_
+
+
+#include "pstypes.h"
+
+
+ /* TODO: disable asserts for now */
+#define CF2_NDEBUG
+
+
+#include FT_SYSTEM_H
+
+#include "psglue.h"
+#include FT_INTERNAL_POSTSCRIPT_AUX_H /* for PS_Decoder */
+
+
+FT_BEGIN_HEADER
+
+
+ FT_LOCAL( FT_Error )
+ cf2_decoder_parse_charstrings( PS_Decoder* decoder,
+ FT_Byte* charstring_base,
+ FT_ULong charstring_len );
+
+ FT_LOCAL( CFF_SubFont )
+ cf2_getSubfont( PS_Decoder* decoder );
+
+ FT_LOCAL( CFF_VStore )
+ cf2_getVStore( PS_Decoder* decoder );
+
+ FT_LOCAL( FT_UInt )
+ cf2_getMaxstack( PS_Decoder* decoder );
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+ FT_LOCAL( FT_Error )
+ cf2_getNormalizedVector( PS_Decoder* decoder,
+ CF2_UInt *len,
+ FT_Fixed* *vec );
+#endif
+
+ FT_LOCAL( CF2_Fixed )
+ cf2_getPpemY( PS_Decoder* decoder );
+ FT_LOCAL( CF2_Fixed )
+ cf2_getStdVW( PS_Decoder* decoder );
+ FT_LOCAL( CF2_Fixed )
+ cf2_getStdHW( PS_Decoder* decoder );
+
+ FT_LOCAL( void )
+ cf2_getBlueMetrics( PS_Decoder* decoder,
+ CF2_Fixed* blueScale,
+ CF2_Fixed* blueShift,
+ CF2_Fixed* blueFuzz );
+ FT_LOCAL( void )
+ cf2_getBlueValues( PS_Decoder* decoder,
+ size_t* count,
+ FT_Pos* *data );
+ FT_LOCAL( void )
+ cf2_getOtherBlues( PS_Decoder* decoder,
+ size_t* count,
+ FT_Pos* *data );
+ FT_LOCAL( void )
+ cf2_getFamilyBlues( PS_Decoder* decoder,
+ size_t* count,
+ FT_Pos* *data );
+ FT_LOCAL( void )
+ cf2_getFamilyOtherBlues( PS_Decoder* decoder,
+ size_t* count,
+ FT_Pos* *data );
+
+ FT_LOCAL( CF2_Int )
+ cf2_getLanguageGroup( PS_Decoder* decoder );
+
+ FT_LOCAL( CF2_Int )
+ cf2_initGlobalRegionBuffer( PS_Decoder* decoder,
+ CF2_Int subrNum,
+ CF2_Buffer buf );
+ FT_LOCAL( FT_Error )
+ cf2_getSeacComponent( PS_Decoder* decoder,
+ CF2_Int code,
+ CF2_Buffer buf );
+ FT_LOCAL( void )
+ cf2_freeSeacComponent( PS_Decoder* decoder,
+ CF2_Buffer buf );
+ FT_LOCAL( CF2_Int )
+ cf2_initLocalRegionBuffer( PS_Decoder* decoder,
+ CF2_Int subrNum,
+ CF2_Buffer buf );
+
+ FT_LOCAL( CF2_Fixed )
+ cf2_getDefaultWidthX( PS_Decoder* decoder );
+ FT_LOCAL( CF2_Fixed )
+ cf2_getNominalWidthX( PS_Decoder* decoder );
+
+
+ FT_LOCAL( FT_Error )
+ cf2_getT1SeacComponent( PS_Decoder* decoder,
+ FT_UInt glyph_index,
+ CF2_Buffer buf );
+ FT_LOCAL( void )
+ cf2_freeT1SeacComponent( PS_Decoder* decoder,
+ CF2_Buffer buf );
+
+ /*
+ * FreeType client outline
+ *
+ * process output from the charstring interpreter
+ */
+ typedef struct CF2_OutlineRec_
+ {
+ CF2_OutlineCallbacksRec root; /* base class must be first */
+ PS_Decoder* decoder;
+
+ } CF2_OutlineRec, *CF2_Outline;
+
+
+ FT_LOCAL( void )
+ cf2_outline_reset( CF2_Outline outline );
+ FT_LOCAL( void )
+ cf2_outline_close( CF2_Outline outline );
+
+
+FT_END_HEADER
+
+
+#endif /* PSFT_H_ */
+
+
+/* END */
diff --git a/thirdparty/freetype/src/psaux/psglue.h b/thirdparty/freetype/src/psaux/psglue.h
new file mode 100644
index 0000000000..5545e12a5b
--- /dev/null
+++ b/thirdparty/freetype/src/psaux/psglue.h
@@ -0,0 +1,144 @@
+/***************************************************************************/
+/* */
+/* psglue.h */
+/* */
+/* Adobe's code for shared stuff (specification only). */
+/* */
+/* Copyright 2007-2013 Adobe Systems Incorporated. */
+/* */
+/* This software, and all works of authorship, whether in source or */
+/* object code form as indicated by the copyright notice(s) included */
+/* herein (collectively, the "Work") is made available, and may only be */
+/* used, modified, and distributed under the FreeType Project License, */
+/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
+/* FreeType Project License, each contributor to the Work hereby grants */
+/* to any individual or legal entity exercising permissions granted by */
+/* the FreeType Project License and this section (hereafter, "You" or */
+/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
+/* royalty-free, irrevocable (except as stated in this section) patent */
+/* license to make, have made, use, offer to sell, sell, import, and */
+/* otherwise transfer the Work, where such license applies only to those */
+/* patent claims licensable by such contributor that are necessarily */
+/* infringed by their contribution(s) alone or by combination of their */
+/* contribution(s) with the Work to which such contribution(s) was */
+/* submitted. If You institute patent litigation against any entity */
+/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
+/* the Work or a contribution incorporated within the Work constitutes */
+/* direct or contributory patent infringement, then any patent licenses */
+/* granted to You under this License for that Work shall terminate as of */
+/* the date such litigation is filed. */
+/* */
+/* By using, modifying, or distributing the Work you indicate that you */
+/* have read and understood the terms and conditions of the */
+/* FreeType Project License as well as those provided in this section, */
+/* and you accept them fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef PSGLUE_H_
+#define PSGLUE_H_
+
+
+/* common includes for other modules */
+#include "pserror.h"
+#include "psfixed.h"
+#include "psarrst.h"
+#include "psread.h"
+
+
+FT_BEGIN_HEADER
+
+
+ /* rendering parameters */
+
+ /* apply hints to rendered glyphs */
+#define CF2_FlagsHinted 1
+ /* for testing */
+#define CF2_FlagsDarkened 2
+
+ /* type for holding the flags */
+ typedef CF2_Int CF2_RenderingFlags;
+
+
+ /* elements of a glyph outline */
+ typedef enum CF2_PathOp_
+ {
+ CF2_PathOpMoveTo = 1, /* change the current point */
+ CF2_PathOpLineTo = 2, /* line */
+ CF2_PathOpQuadTo = 3, /* quadratic curve */
+ CF2_PathOpCubeTo = 4 /* cubic curve */
+
+ } CF2_PathOp;
+
+
+ /* a matrix of fixed point values */
+ typedef struct CF2_Matrix_
+ {
+ CF2_F16Dot16 a;
+ CF2_F16Dot16 b;
+ CF2_F16Dot16 c;
+ CF2_F16Dot16 d;
+ CF2_F16Dot16 tx;
+ CF2_F16Dot16 ty;
+
+ } CF2_Matrix;
+
+
+ /* these typedefs are needed by more than one header file */
+ /* and gcc compiler doesn't allow redefinition */
+ typedef struct CF2_FontRec_ CF2_FontRec, *CF2_Font;
+ typedef struct CF2_HintRec_ CF2_HintRec, *CF2_Hint;
+
+
+ /* A common structure for all callback parameters. */
+ /* */
+ /* Some members may be unused. For example, `pt0' is not used for */
+ /* `moveTo' and `pt3' is not used for `quadTo'. The initial point `pt0' */
+ /* is included for each path element for generality; curve conversions */
+ /* need it. The `op' parameter allows one function to handle multiple */
+ /* element types. */
+
+ typedef struct CF2_CallbackParamsRec_
+ {
+ FT_Vector pt0;
+ FT_Vector pt1;
+ FT_Vector pt2;
+ FT_Vector pt3;
+
+ CF2_Int op;
+
+ } CF2_CallbackParamsRec, *CF2_CallbackParams;
+
+
+ /* forward reference */
+ typedef struct CF2_OutlineCallbacksRec_ CF2_OutlineCallbacksRec,
+ *CF2_OutlineCallbacks;
+
+ /* callback function pointers */
+ typedef void
+ (*CF2_Callback_Type)( CF2_OutlineCallbacks callbacks,
+ const CF2_CallbackParams params );
+
+
+ struct CF2_OutlineCallbacksRec_
+ {
+ CF2_Callback_Type moveTo;
+ CF2_Callback_Type lineTo;
+ CF2_Callback_Type quadTo;
+ CF2_Callback_Type cubeTo;
+
+ CF2_Int windingMomentum; /* for winding order detection */
+
+ FT_Memory memory;
+ FT_Error* error;
+ };
+
+
+FT_END_HEADER
+
+
+#endif /* PSGLUE_H_ */
+
+
+/* END */
diff --git a/thirdparty/freetype/src/psaux/pshints.c b/thirdparty/freetype/src/psaux/pshints.c
new file mode 100644
index 0000000000..3615196425
--- /dev/null
+++ b/thirdparty/freetype/src/psaux/pshints.c
@@ -0,0 +1,1939 @@
+/***************************************************************************/
+/* */
+/* pshints.c */
+/* */
+/* Adobe's code for handling CFF hints (body). */
+/* */
+/* Copyright 2007-2014 Adobe Systems Incorporated. */
+/* */
+/* This software, and all works of authorship, whether in source or */
+/* object code form as indicated by the copyright notice(s) included */
+/* herein (collectively, the "Work") is made available, and may only be */
+/* used, modified, and distributed under the FreeType Project License, */
+/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
+/* FreeType Project License, each contributor to the Work hereby grants */
+/* to any individual or legal entity exercising permissions granted by */
+/* the FreeType Project License and this section (hereafter, "You" or */
+/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
+/* royalty-free, irrevocable (except as stated in this section) patent */
+/* license to make, have made, use, offer to sell, sell, import, and */
+/* otherwise transfer the Work, where such license applies only to those */
+/* patent claims licensable by such contributor that are necessarily */
+/* infringed by their contribution(s) alone or by combination of their */
+/* contribution(s) with the Work to which such contribution(s) was */
+/* submitted. If You institute patent litigation against any entity */
+/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
+/* the Work or a contribution incorporated within the Work constitutes */
+/* direct or contributory patent infringement, then any patent licenses */
+/* granted to You under this License for that Work shall terminate as of */
+/* the date such litigation is filed. */
+/* */
+/* By using, modifying, or distributing the Work you indicate that you */
+/* have read and understood the terms and conditions of the */
+/* FreeType Project License as well as those provided in this section, */
+/* and you accept them fully. */
+/* */
+/***************************************************************************/
+
+
+#include "psft.h"
+#include FT_INTERNAL_DEBUG_H
+
+#include "psglue.h"
+#include "psfont.h"
+#include "pshints.h"
+#include "psintrp.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_cf2hints
+
+
+ typedef struct CF2_HintMoveRec_
+ {
+ size_t j; /* index of upper hint map edge */
+ CF2_Fixed moveUp; /* adjustment to optimum position */
+
+ } CF2_HintMoveRec, *CF2_HintMove;
+
+
+ /* Compute angular momentum for winding order detection. It is called */
+ /* for all lines and curves, but not necessarily in element order. */
+ static CF2_Int
+ cf2_getWindingMomentum( CF2_Fixed x1,
+ CF2_Fixed y1,
+ CF2_Fixed x2,
+ CF2_Fixed y2 )
+ {
+ /* cross product of pt1 position from origin with pt2 position from */
+ /* pt1; we reduce the precision so that the result fits into 32 bits */
+
+ return ( x1 >> 16 ) * ( SUB_INT32( y2, y1 ) >> 16 ) -
+ ( y1 >> 16 ) * ( SUB_INT32( x2, x1 ) >> 16 );
+ }
+
+
+ /*
+ * Construct from a StemHint; this is used as a parameter to
+ * `cf2_blues_capture'.
+ * `hintOrigin' is the character space displacement of a seac accent.
+ * Adjust stem hint for darkening here.
+ *
+ */
+ static void
+ cf2_hint_init( CF2_Hint hint,
+ const CF2_ArrStack stemHintArray,
+ size_t indexStemHint,
+ const CF2_Font font,
+ CF2_Fixed hintOrigin,
+ CF2_Fixed scale,
+ FT_Bool bottom )
+ {
+ CF2_Fixed width;
+ const CF2_StemHintRec* stemHint;
+
+
+ FT_ZERO( hint );
+
+ stemHint = (const CF2_StemHintRec*)cf2_arrstack_getPointer(
+ stemHintArray,
+ indexStemHint );
+
+ width = SUB_INT32( stemHint->max, stemHint->min );
+
+ if ( width == cf2_intToFixed( -21 ) )
+ {
+ /* ghost bottom */
+
+ if ( bottom )
+ {
+ hint->csCoord = stemHint->max;
+ hint->flags = CF2_GhostBottom;
+ }
+ else
+ hint->flags = 0;
+ }
+
+ else if ( width == cf2_intToFixed( -20 ) )
+ {
+ /* ghost top */
+
+ if ( bottom )
+ hint->flags = 0;
+ else
+ {
+ hint->csCoord = stemHint->min;
+ hint->flags = CF2_GhostTop;
+ }
+ }
+
+ else if ( width < 0 )
+ {
+ /* inverted pair */
+
+ /*
+ * Hints with negative widths were produced by an early version of a
+ * non-Adobe font tool. The Type 2 spec allows edge (ghost) hints
+ * with negative widths, but says
+ *
+ * All other negative widths have undefined meaning.
+ *
+ * CoolType has a silent workaround that negates the hint width; for
+ * permissive mode, we do the same here.
+ *
+ * Note: Such fonts cannot use ghost hints, but should otherwise work.
+ * Note: Some poor hints in our faux fonts can produce negative
+ * widths at some blends. For example, see a light weight of
+ * `u' in ASerifMM.
+ *
+ */
+ if ( bottom )
+ {
+ hint->csCoord = stemHint->max;
+ hint->flags = CF2_PairBottom;
+ }
+ else
+ {
+ hint->csCoord = stemHint->min;
+ hint->flags = CF2_PairTop;
+ }
+ }
+
+ else
+ {
+ /* normal pair */
+
+ if ( bottom )
+ {
+ hint->csCoord = stemHint->min;
+ hint->flags = CF2_PairBottom;
+ }
+ else
+ {
+ hint->csCoord = stemHint->max;
+ hint->flags = CF2_PairTop;
+ }
+ }
+
+ /* Now that ghost hints have been detected, adjust this edge for */
+ /* darkening. Bottoms are not changed; tops are incremented by twice */
+ /* `darkenY'. */
+ if ( cf2_hint_isTop( hint ) )
+ hint->csCoord = ADD_INT32( hint->csCoord, 2 * font->darkenY );
+
+ hint->csCoord = ADD_INT32( hint->csCoord, hintOrigin );
+ hint->scale = scale;
+ hint->index = indexStemHint; /* index in original stem hint array */
+
+ /* if original stem hint has been used, use the same position */
+ if ( hint->flags != 0 && stemHint->used )
+ {
+ if ( cf2_hint_isTop( hint ) )
+ hint->dsCoord = stemHint->maxDS;
+ else
+ hint->dsCoord = stemHint->minDS;
+
+ cf2_hint_lock( hint );
+ }
+ else
+ hint->dsCoord = FT_MulFix( hint->csCoord, scale );
+ }
+
+
+ /* initialize an invalid hint map element */
+ static void
+ cf2_hint_initZero( CF2_Hint hint )
+ {
+ FT_ZERO( hint );
+ }
+
+
+ FT_LOCAL_DEF( FT_Bool )
+ cf2_hint_isValid( const CF2_Hint hint )
+ {
+ return (FT_Bool)( hint->flags != 0 );
+ }
+
+
+ static FT_Bool
+ cf2_hint_isPair( const CF2_Hint hint )
+ {
+ return (FT_Bool)( ( hint->flags &
+ ( CF2_PairBottom | CF2_PairTop ) ) != 0 );
+ }
+
+
+ static FT_Bool
+ cf2_hint_isPairTop( const CF2_Hint hint )
+ {
+ return (FT_Bool)( ( hint->flags & CF2_PairTop ) != 0 );
+ }
+
+
+ FT_LOCAL_DEF( FT_Bool )
+ cf2_hint_isTop( const CF2_Hint hint )
+ {
+ return (FT_Bool)( ( hint->flags &
+ ( CF2_PairTop | CF2_GhostTop ) ) != 0 );
+ }
+
+
+ FT_LOCAL_DEF( FT_Bool )
+ cf2_hint_isBottom( const CF2_Hint hint )
+ {
+ return (FT_Bool)( ( hint->flags &
+ ( CF2_PairBottom | CF2_GhostBottom ) ) != 0 );
+ }
+
+
+ static FT_Bool
+ cf2_hint_isLocked( const CF2_Hint hint )
+ {
+ return (FT_Bool)( ( hint->flags & CF2_Locked ) != 0 );
+ }
+
+
+ static FT_Bool
+ cf2_hint_isSynthetic( const CF2_Hint hint )
+ {
+ return (FT_Bool)( ( hint->flags & CF2_Synthetic ) != 0 );
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cf2_hint_lock( CF2_Hint hint )
+ {
+ hint->flags |= CF2_Locked;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cf2_hintmap_init( CF2_HintMap hintmap,
+ CF2_Font font,
+ CF2_HintMap initialMap,
+ CF2_ArrStack hintMoves,
+ CF2_Fixed scale )
+ {
+ FT_ZERO( hintmap );
+
+ /* copy parameters from font instance */
+ hintmap->hinted = font->hinted;
+ hintmap->scale = scale;
+ hintmap->font = font;
+ hintmap->initialHintMap = initialMap;
+ /* will clear in `cf2_hintmap_adjustHints' */
+ hintmap->hintMoves = hintMoves;
+ }
+
+
+ static FT_Bool
+ cf2_hintmap_isValid( const CF2_HintMap hintmap )
+ {
+ return hintmap->isValid;
+ }
+
+
+ static void
+ cf2_hintmap_dump( CF2_HintMap hintmap )
+ {
+#ifdef FT_DEBUG_LEVEL_TRACE
+ CF2_UInt i;
+
+
+ FT_TRACE6(( " index csCoord dsCoord scale flags\n" ));
+
+ for ( i = 0; i < hintmap->count; i++ )
+ {
+ CF2_Hint hint = &hintmap->edge[i];
+
+
+ FT_TRACE6(( " %3d %7.2f %7.2f %5d %s%s%s%s\n",
+ hint->index,
+ hint->csCoord / 65536.0,
+ hint->dsCoord / ( hint->scale * 1.0 ),
+ hint->scale,
+ ( cf2_hint_isPair( hint ) ? "p" : "g" ),
+ ( cf2_hint_isTop( hint ) ? "t" : "b" ),
+ ( cf2_hint_isLocked( hint ) ? "L" : ""),
+ ( cf2_hint_isSynthetic( hint ) ? "S" : "" ) ));
+ }
+#else
+ FT_UNUSED( hintmap );
+#endif
+ }
+
+
+ /* transform character space coordinate to device space using hint map */
+ static CF2_Fixed
+ cf2_hintmap_map( CF2_HintMap hintmap,
+ CF2_Fixed csCoord )
+ {
+ if ( hintmap->count == 0 || ! hintmap->hinted )
+ {
+ /* there are no hints; use uniform scale and zero offset */
+ return FT_MulFix( csCoord, hintmap->scale );
+ }
+ else
+ {
+ /* start linear search from last hit */
+ CF2_UInt i = hintmap->lastIndex;
+
+
+ FT_ASSERT( hintmap->lastIndex < CF2_MAX_HINT_EDGES );
+
+ /* search up */
+ while ( i < hintmap->count - 1 &&
+ csCoord >= hintmap->edge[i + 1].csCoord )
+ i += 1;
+
+ /* search down */
+ while ( i > 0 && csCoord < hintmap->edge[i].csCoord )
+ i -= 1;
+
+ hintmap->lastIndex = i;
+
+ if ( i == 0 && csCoord < hintmap->edge[0].csCoord )
+ {
+ /* special case for points below first edge: use uniform scale */
+ return ADD_INT32( FT_MulFix( SUB_INT32( csCoord,
+ hintmap->edge[0].csCoord ),
+ hintmap->scale ),
+ hintmap->edge[0].dsCoord );
+ }
+ else
+ {
+ /*
+ * Note: entries with duplicate csCoord are allowed.
+ * Use edge[i], the highest entry where csCoord >= entry[i].csCoord
+ */
+ return ADD_INT32( FT_MulFix( SUB_INT32( csCoord,
+ hintmap->edge[i].csCoord ),
+ hintmap->edge[i].scale ),
+ hintmap->edge[i].dsCoord );
+ }
+ }
+ }
+
+
+ /*
+ * This hinting policy moves a hint pair in device space so that one of
+ * its two edges is on a device pixel boundary (its fractional part is
+ * zero). `cf2_hintmap_insertHint' guarantees no overlap in CS
+ * space. Ensure here that there is no overlap in DS.
+ *
+ * In the first pass, edges are adjusted relative to adjacent hints.
+ * Those that are below have already been adjusted. Those that are
+ * above have not yet been adjusted. If a hint above blocks an
+ * adjustment to an optimal position, we will try again in a second
+ * pass. The second pass is top-down.
+ *
+ */
+
+ static void
+ cf2_hintmap_adjustHints( CF2_HintMap hintmap )
+ {
+ size_t i, j;
+
+
+ cf2_arrstack_clear( hintmap->hintMoves ); /* working storage */
+
+ /*
+ * First pass is bottom-up (font hint order) without look-ahead.
+ * Locked edges are already adjusted.
+ * Unlocked edges begin with dsCoord from `initialHintMap'.
+ * Save edges that are not optimally adjusted in `hintMoves' array,
+ * and process them in second pass.
+ */
+
+ for ( i = 0; i < hintmap->count; i++ )
+ {
+ FT_Bool isPair = cf2_hint_isPair( &hintmap->edge[i] );
+
+
+ /* index of upper edge (same value for ghost hint) */
+ j = isPair ? i + 1 : i;
+
+ FT_ASSERT( j < hintmap->count );
+ FT_ASSERT( cf2_hint_isValid( &hintmap->edge[i] ) );
+ FT_ASSERT( cf2_hint_isValid( &hintmap->edge[j] ) );
+ FT_ASSERT( cf2_hint_isLocked( &hintmap->edge[i] ) ==
+ cf2_hint_isLocked( &hintmap->edge[j] ) );
+
+ if ( !cf2_hint_isLocked( &hintmap->edge[i] ) )
+ {
+ /* hint edge is not locked, we can adjust it */
+ CF2_Fixed fracDown = cf2_fixedFraction( hintmap->edge[i].dsCoord );
+ CF2_Fixed fracUp = cf2_fixedFraction( hintmap->edge[j].dsCoord );
+
+ /* calculate all four possibilities; moves down are negative */
+ CF2_Fixed downMoveDown = 0 - fracDown;
+ CF2_Fixed upMoveDown = 0 - fracUp;
+ CF2_Fixed downMoveUp = ( fracDown == 0 )
+ ? 0
+ : cf2_intToFixed( 1 ) - fracDown;
+ CF2_Fixed upMoveUp = ( fracUp == 0 )
+ ? 0
+ : cf2_intToFixed( 1 ) - fracUp;
+
+ /* smallest move up */
+ CF2_Fixed moveUp = FT_MIN( downMoveUp, upMoveUp );
+ /* smallest move down */
+ CF2_Fixed moveDown = FT_MAX( downMoveDown, upMoveDown );
+
+ /* final amount to move edge or edge pair */
+ CF2_Fixed move;
+
+ CF2_Fixed downMinCounter = CF2_MIN_COUNTER;
+ CF2_Fixed upMinCounter = CF2_MIN_COUNTER;
+ FT_Bool saveEdge = FALSE;
+
+
+ /* minimum counter constraint doesn't apply when adjacent edges */
+ /* are synthetic */
+ /* TODO: doesn't seem a big effect; for now, reduce the code */
+#if 0
+ if ( i == 0 ||
+ cf2_hint_isSynthetic( &hintmap->edge[i - 1] ) )
+ downMinCounter = 0;
+
+ if ( j >= hintmap->count - 1 ||
+ cf2_hint_isSynthetic( &hintmap->edge[j + 1] ) )
+ upMinCounter = 0;
+#endif
+
+ /* is there room to move up? */
+ /* there is if we are at top of array or the next edge is at or */
+ /* beyond proposed move up? */
+ if ( j >= hintmap->count - 1 ||
+ hintmap->edge[j + 1].dsCoord >=
+ ADD_INT32( hintmap->edge[j].dsCoord,
+ moveUp + upMinCounter ) )
+ {
+ /* there is room to move up; is there also room to move down? */
+ if ( i == 0 ||
+ hintmap->edge[i - 1].dsCoord <=
+ ADD_INT32( hintmap->edge[i].dsCoord,
+ moveDown - downMinCounter ) )
+ {
+ /* move smaller absolute amount */
+ move = ( -moveDown < moveUp ) ? moveDown : moveUp; /* optimum */
+ }
+ else
+ move = moveUp;
+ }
+ else
+ {
+ /* is there room to move down? */
+ if ( i == 0 ||
+ hintmap->edge[i - 1].dsCoord <=
+ ADD_INT32( hintmap->edge[i].dsCoord,
+ moveDown - downMinCounter ) )
+ {
+ move = moveDown;
+ /* true if non-optimum move */
+ saveEdge = (FT_Bool)( moveUp < -moveDown );
+ }
+ else
+ {
+ /* no room to move either way without overlapping or reducing */
+ /* the counter too much */
+ move = 0;
+ saveEdge = TRUE;
+ }
+ }
+
+ /* Identify non-moves and moves down that aren't optimal, and save */
+ /* them for second pass. */
+ /* Do this only if there is an unlocked edge above (which could */
+ /* possibly move). */
+ if ( saveEdge &&
+ j < hintmap->count - 1 &&
+ !cf2_hint_isLocked( &hintmap->edge[j + 1] ) )
+ {
+ CF2_HintMoveRec savedMove;
+
+
+ savedMove.j = j;
+ /* desired adjustment in second pass */
+ savedMove.moveUp = moveUp - move;
+
+ cf2_arrstack_push( hintmap->hintMoves, &savedMove );
+ }
+
+ /* move the edge(s) */
+ hintmap->edge[i].dsCoord = ADD_INT32( hintmap->edge[i].dsCoord,
+ move );
+ if ( isPair )
+ hintmap->edge[j].dsCoord = ADD_INT32( hintmap->edge[j].dsCoord,
+ move );
+ }
+
+ /* assert there are no overlaps in device space */
+ FT_ASSERT( i == 0 ||
+ hintmap->edge[i - 1].dsCoord <= hintmap->edge[i].dsCoord );
+ FT_ASSERT( i < j ||
+ hintmap->edge[i].dsCoord <= hintmap->edge[j].dsCoord );
+
+ /* adjust the scales, avoiding divide by zero */
+ if ( i > 0 )
+ {
+ if ( hintmap->edge[i].csCoord != hintmap->edge[i - 1].csCoord )
+ hintmap->edge[i - 1].scale =
+ FT_DivFix( SUB_INT32( hintmap->edge[i].dsCoord,
+ hintmap->edge[i - 1].dsCoord ),
+ SUB_INT32( hintmap->edge[i].csCoord,
+ hintmap->edge[i - 1].csCoord ) );
+ }
+
+ if ( isPair )
+ {
+ if ( hintmap->edge[j].csCoord != hintmap->edge[j - 1].csCoord )
+ hintmap->edge[j - 1].scale =
+ FT_DivFix( SUB_INT32( hintmap->edge[j].dsCoord,
+ hintmap->edge[j - 1].dsCoord ),
+ SUB_INT32( hintmap->edge[j].csCoord,
+ hintmap->edge[j - 1].csCoord ) );
+
+ i += 1; /* skip upper edge on next loop */
+ }
+ }
+
+ /* second pass tries to move non-optimal hints up, in case there is */
+ /* room now */
+ for ( i = cf2_arrstack_size( hintmap->hintMoves ); i > 0; i-- )
+ {
+ CF2_HintMove hintMove = (CF2_HintMove)
+ cf2_arrstack_getPointer( hintmap->hintMoves, i - 1 );
+
+
+ j = hintMove->j;
+
+ /* this was tested before the push, above */
+ FT_ASSERT( j < hintmap->count - 1 );
+
+ /* is there room to move up? */
+ if ( hintmap->edge[j + 1].dsCoord >=
+ ADD_INT32( hintmap->edge[j].dsCoord,
+ hintMove->moveUp + CF2_MIN_COUNTER ) )
+ {
+ /* there is more room now, move edge up */
+ hintmap->edge[j].dsCoord = ADD_INT32( hintmap->edge[j].dsCoord,
+ hintMove->moveUp );
+
+ if ( cf2_hint_isPair( &hintmap->edge[j] ) )
+ {
+ FT_ASSERT( j > 0 );
+ hintmap->edge[j - 1].dsCoord =
+ ADD_INT32( hintmap->edge[j - 1].dsCoord, hintMove->moveUp );
+ }
+ }
+ }
+ }
+
+
+ /* insert hint edges into map, sorted by csCoord */
+ static void
+ cf2_hintmap_insertHint( CF2_HintMap hintmap,
+ CF2_Hint bottomHintEdge,
+ CF2_Hint topHintEdge )
+ {
+ CF2_UInt indexInsert;
+
+ /* set default values, then check for edge hints */
+ FT_Bool isPair = TRUE;
+ CF2_Hint firstHintEdge = bottomHintEdge;
+ CF2_Hint secondHintEdge = topHintEdge;
+
+
+ /* one or none of the input params may be invalid when dealing with */
+ /* edge hints; at least one edge must be valid */
+ FT_ASSERT( cf2_hint_isValid( bottomHintEdge ) ||
+ cf2_hint_isValid( topHintEdge ) );
+
+ /* determine how many and which edges to insert */
+ if ( !cf2_hint_isValid( bottomHintEdge ) )
+ {
+ /* insert only the top edge */
+ firstHintEdge = topHintEdge;
+ isPair = FALSE;
+ }
+ else if ( !cf2_hint_isValid( topHintEdge ) )
+ {
+ /* insert only the bottom edge */
+ isPair = FALSE;
+ }
+
+ /* paired edges must be in proper order */
+ if ( isPair &&
+ topHintEdge->csCoord < bottomHintEdge->csCoord )
+ return;
+
+ /* linear search to find index value of insertion point */
+ indexInsert = 0;
+ for ( ; indexInsert < hintmap->count; indexInsert++ )
+ {
+ if ( hintmap->edge[indexInsert].csCoord >= firstHintEdge->csCoord )
+ break;
+ }
+
+ FT_TRACE7(( " Got hint at %.2f (%.2f)\n",
+ firstHintEdge->csCoord / 65536.0,
+ firstHintEdge->dsCoord / 65536.0 ));
+ if ( isPair )
+ FT_TRACE7(( " Got hint at %.2f (%.2f)\n",
+ secondHintEdge->csCoord / 65536.0,
+ secondHintEdge->dsCoord / 65536.0 ));
+
+ /*
+ * Discard any hints that overlap in character space. Most often, this
+ * is while building the initial map, where captured hints from all
+ * zones are combined. Define overlap to include hints that `touch'
+ * (overlap zero). Hiragino Sans/Gothic fonts have numerous hints that
+ * touch. Some fonts have non-ideographic glyphs that overlap our
+ * synthetic hints.
+ *
+ * Overlap also occurs when darkening stem hints that are close.
+ *
+ */
+ if ( indexInsert < hintmap->count )
+ {
+ /* we are inserting before an existing edge: */
+ /* verify that an existing edge is not the same */
+ if ( hintmap->edge[indexInsert].csCoord == firstHintEdge->csCoord )
+ return; /* ignore overlapping stem hint */
+
+ /* verify that a new pair does not straddle the next edge */
+ if ( isPair &&
+ hintmap->edge[indexInsert].csCoord <= secondHintEdge->csCoord )
+ return; /* ignore overlapping stem hint */
+
+ /* verify that we are not inserting between paired edges */
+ if ( cf2_hint_isPairTop( &hintmap->edge[indexInsert] ) )
+ return; /* ignore overlapping stem hint */
+ }
+
+ /* recompute device space locations using initial hint map */
+ if ( cf2_hintmap_isValid( hintmap->initialHintMap ) &&
+ !cf2_hint_isLocked( firstHintEdge ) )
+ {
+ if ( isPair )
+ {
+ /* Use hint map to position the center of stem, and nominal scale */
+ /* to position the two edges. This preserves the stem width. */
+ CF2_Fixed midpoint =
+ cf2_hintmap_map(
+ hintmap->initialHintMap,
+ ADD_INT32( secondHintEdge->csCoord,
+ firstHintEdge->csCoord ) / 2 );
+ CF2_Fixed halfWidth =
+ FT_MulFix( SUB_INT32( secondHintEdge->csCoord,
+ firstHintEdge->csCoord ) / 2,
+ hintmap->scale );
+
+
+ firstHintEdge->dsCoord = SUB_INT32( midpoint, halfWidth );
+ secondHintEdge->dsCoord = ADD_INT32( midpoint, halfWidth );
+ }
+ else
+ firstHintEdge->dsCoord = cf2_hintmap_map( hintmap->initialHintMap,
+ firstHintEdge->csCoord );
+ }
+
+ /*
+ * Discard any hints that overlap in device space; this can occur
+ * because locked hints have been moved to align with blue zones.
+ *
+ * TODO: Although we might correct this later during adjustment, we
+ * don't currently have a way to delete a conflicting hint once it has
+ * been inserted. See v2.030 MinionPro-Regular, 12 ppem darkened,
+ * initial hint map for second path, glyph 945 (the perispomeni (tilde)
+ * in U+1F6E, Greek omega with psili and perispomeni). Darkening is
+ * 25. Pair 667,747 initially conflicts in design space with top edge
+ * 660. This is because 667 maps to 7.87, and the top edge was
+ * captured by a zone at 8.0. The pair is later successfully inserted
+ * in a zone without the top edge. In this zone it is adjusted to 8.0,
+ * and no longer conflicts with the top edge in design space. This
+ * means it can be included in yet a later zone which does have the top
+ * edge hint. This produces a small mismatch between the first and
+ * last points of this path, even though the hint masks are the same.
+ * The density map difference is tiny (1/256).
+ *
+ */
+
+ if ( indexInsert > 0 )
+ {
+ /* we are inserting after an existing edge */
+ if ( firstHintEdge->dsCoord < hintmap->edge[indexInsert - 1].dsCoord )
+ return;
+ }
+
+ if ( indexInsert < hintmap->count )
+ {
+ /* we are inserting before an existing edge */
+ if ( isPair )
+ {
+ if ( secondHintEdge->dsCoord > hintmap->edge[indexInsert].dsCoord )
+ return;
+ }
+ else
+ {
+ if ( firstHintEdge->dsCoord > hintmap->edge[indexInsert].dsCoord )
+ return;
+ }
+ }
+
+ /* make room to insert */
+ {
+ CF2_UInt iSrc = hintmap->count - 1;
+ CF2_UInt iDst = isPair ? hintmap->count + 1 : hintmap->count;
+
+ CF2_UInt count = hintmap->count - indexInsert;
+
+
+ if ( iDst >= CF2_MAX_HINT_EDGES )
+ {
+ FT_TRACE4(( "cf2_hintmap_insertHint: too many hintmaps\n" ));
+ return;
+ }
+
+ while ( count-- )
+ hintmap->edge[iDst--] = hintmap->edge[iSrc--];
+
+ /* insert first edge */
+ hintmap->edge[indexInsert] = *firstHintEdge; /* copy struct */
+ hintmap->count += 1;
+
+ FT_TRACE7(( " Inserting hint %.2f (%.2f)\n",
+ firstHintEdge->csCoord / 65536.0,
+ firstHintEdge->dsCoord / 65536.0 ));
+
+ if ( isPair )
+ {
+ /* insert second edge */
+ hintmap->edge[indexInsert + 1] = *secondHintEdge; /* copy struct */
+ hintmap->count += 1;
+
+ FT_TRACE7(( " Inserting hint %.2f (%.2f)\n",
+ secondHintEdge->csCoord / 65536.0,
+ secondHintEdge->dsCoord / 65536.0 ));
+
+ }
+ }
+
+ return;
+ }
+
+
+ /*
+ * Build a map from hints and mask.
+ *
+ * This function may recur one level if `hintmap->initialHintMap' is not yet
+ * valid.
+ * If `initialMap' is true, simply build initial map.
+ *
+ * Synthetic hints are used in two ways. A hint at zero is inserted, if
+ * needed, in the initial hint map, to prevent translations from
+ * propagating across the origin. If synthetic em box hints are enabled
+ * for ideographic dictionaries, then they are inserted in all hint
+ * maps, including the initial one.
+ *
+ */
+ FT_LOCAL_DEF( void )
+ cf2_hintmap_build( CF2_HintMap hintmap,
+ CF2_ArrStack hStemHintArray,
+ CF2_ArrStack vStemHintArray,
+ CF2_HintMask hintMask,
+ CF2_Fixed hintOrigin,
+ FT_Bool initialMap )
+ {
+ FT_Byte* maskPtr;
+
+ CF2_Font font = hintmap->font;
+ CF2_HintMaskRec tempHintMask;
+
+ size_t bitCount, i;
+ FT_Byte maskByte;
+
+
+ /* check whether initial map is constructed */
+ if ( !initialMap && !cf2_hintmap_isValid( hintmap->initialHintMap ) )
+ {
+ /* make recursive call with initialHintMap and temporary mask; */
+ /* temporary mask will get all bits set, below */
+ cf2_hintmask_init( &tempHintMask, hintMask->error );
+ cf2_hintmap_build( hintmap->initialHintMap,
+ hStemHintArray,
+ vStemHintArray,
+ &tempHintMask,
+ hintOrigin,
+ TRUE );
+ }
+
+ if ( !cf2_hintmask_isValid( hintMask ) )
+ {
+ /* without a hint mask, assume all hints are active */
+ cf2_hintmask_setAll( hintMask,
+ cf2_arrstack_size( hStemHintArray ) +
+ cf2_arrstack_size( vStemHintArray ) );
+ if ( !cf2_hintmask_isValid( hintMask ) )
+ {
+ if ( font->isT1 )
+ {
+ /* no error, just continue unhinted */
+ *hintMask->error = FT_Err_Ok;
+ hintmap->hinted = FALSE;
+ }
+ return; /* too many stem hints */
+ }
+ }
+
+ /* begin by clearing the map */
+ hintmap->count = 0;
+ hintmap->lastIndex = 0;
+
+ /* make a copy of the hint mask so we can modify it */
+ tempHintMask = *hintMask;
+ maskPtr = cf2_hintmask_getMaskPtr( &tempHintMask );
+
+ /* use the hStem hints only, which are first in the mask */
+ bitCount = cf2_arrstack_size( hStemHintArray );
+
+ /* Defense-in-depth. Should never return here. */
+ if ( bitCount > hintMask->bitCount )
+ return;
+
+ /* synthetic embox hints get highest priority */
+ if ( font->blues.doEmBoxHints )
+ {
+ CF2_HintRec dummy;
+
+
+ cf2_hint_initZero( &dummy ); /* invalid hint map element */
+
+ /* ghost bottom */
+ cf2_hintmap_insertHint( hintmap,
+ &font->blues.emBoxBottomEdge,
+ &dummy );
+ /* ghost top */
+ cf2_hintmap_insertHint( hintmap,
+ &dummy,
+ &font->blues.emBoxTopEdge );
+ }
+
+ /* insert hints captured by a blue zone or already locked (higher */
+ /* priority) */
+ for ( i = 0, maskByte = 0x80; i < bitCount; i++ )
+ {
+ if ( maskByte & *maskPtr )
+ {
+ /* expand StemHint into two `CF2_Hint' elements */
+ CF2_HintRec bottomHintEdge, topHintEdge;
+
+
+ cf2_hint_init( &bottomHintEdge,
+ hStemHintArray,
+ i,
+ font,
+ hintOrigin,
+ hintmap->scale,
+ TRUE /* bottom */ );
+ cf2_hint_init( &topHintEdge,
+ hStemHintArray,
+ i,
+ font,
+ hintOrigin,
+ hintmap->scale,
+ FALSE /* top */ );
+
+ if ( cf2_hint_isLocked( &bottomHintEdge ) ||
+ cf2_hint_isLocked( &topHintEdge ) ||
+ cf2_blues_capture( &font->blues,
+ &bottomHintEdge,
+ &topHintEdge ) )
+ {
+ /* insert captured hint into map */
+ cf2_hintmap_insertHint( hintmap, &bottomHintEdge, &topHintEdge );
+
+ *maskPtr &= ~maskByte; /* turn off the bit for this hint */
+ }
+ }
+
+ if ( ( i & 7 ) == 7 )
+ {
+ /* move to next mask byte */
+ maskPtr++;
+ maskByte = 0x80;
+ }
+ else
+ maskByte >>= 1;
+ }
+
+ /* initial hint map includes only captured hints plus maybe one at 0 */
+
+ /*
+ * TODO: There is a problem here because we are trying to build a
+ * single hint map containing all captured hints. It is
+ * possible for there to be conflicts between captured hints,
+ * either because of darkening or because the hints are in
+ * separate hint zones (we are ignoring hint zones for the
+ * initial map). An example of the latter is MinionPro-Regular
+ * v2.030 glyph 883 (Greek Capital Alpha with Psili) at 15ppem.
+ * A stem hint for the psili conflicts with the top edge hint
+ * for the base character. The stem hint gets priority because
+ * of its sort order. In glyph 884 (Greek Capital Alpha with
+ * Psili and Oxia), the top of the base character gets a stem
+ * hint, and the psili does not. This creates different initial
+ * maps for the two glyphs resulting in different renderings of
+ * the base character. Will probably defer this either as not
+ * worth the cost or as a font bug. I don't think there is any
+ * good reason for an accent to be captured by an alignment
+ * zone. -darnold 2/12/10
+ */
+
+ if ( initialMap )
+ {
+ /* Apply a heuristic that inserts a point for (0,0), unless it's */
+ /* already covered by a mapping. This locks the baseline for glyphs */
+ /* that have no baseline hints. */
+
+ if ( hintmap->count == 0 ||
+ hintmap->edge[0].csCoord > 0 ||
+ hintmap->edge[hintmap->count - 1].csCoord < 0 )
+ {
+ /* all edges are above 0 or all edges are below 0; */
+ /* construct a locked edge hint at 0 */
+
+ CF2_HintRec edge, invalid;
+
+
+ cf2_hint_initZero( &edge );
+
+ edge.flags = CF2_GhostBottom |
+ CF2_Locked |
+ CF2_Synthetic;
+ edge.scale = hintmap->scale;
+
+ cf2_hint_initZero( &invalid );
+ cf2_hintmap_insertHint( hintmap, &edge, &invalid );
+ }
+ }
+ else
+ {
+ /* insert remaining hints */
+
+ maskPtr = cf2_hintmask_getMaskPtr( &tempHintMask );
+
+ for ( i = 0, maskByte = 0x80; i < bitCount; i++ )
+ {
+ if ( maskByte & *maskPtr )
+ {
+ CF2_HintRec bottomHintEdge, topHintEdge;
+
+
+ cf2_hint_init( &bottomHintEdge,
+ hStemHintArray,
+ i,
+ font,
+ hintOrigin,
+ hintmap->scale,
+ TRUE /* bottom */ );
+ cf2_hint_init( &topHintEdge,
+ hStemHintArray,
+ i,
+ font,
+ hintOrigin,
+ hintmap->scale,
+ FALSE /* top */ );
+
+ cf2_hintmap_insertHint( hintmap, &bottomHintEdge, &topHintEdge );
+ }
+
+ if ( ( i & 7 ) == 7 )
+ {
+ /* move to next mask byte */
+ maskPtr++;
+ maskByte = 0x80;
+ }
+ else
+ maskByte >>= 1;
+ }
+ }
+
+ FT_TRACE6(( initialMap ? "flags: [p]air [g]host [t]op "
+ "[b]ottom [L]ocked [S]ynthetic\n"
+ "Initial hintmap\n"
+ : "Hints:\n" ));
+ cf2_hintmap_dump( hintmap );
+
+ /*
+ * Note: The following line is a convenient place to break when
+ * debugging hinting. Examine `hintmap->edge' for the list of
+ * enabled hints, then step over the call to see the effect of
+ * adjustment. We stop here first on the recursive call that
+ * creates the initial map, and then on each counter group and
+ * hint zone.
+ */
+
+ /* adjust positions of hint edges that are not locked to blue zones */
+ cf2_hintmap_adjustHints( hintmap );
+
+ FT_TRACE6(( "(adjusted)\n" ));
+ cf2_hintmap_dump( hintmap );
+
+ /* save the position of all hints that were used in this hint map; */
+ /* if we use them again, we'll locate them in the same position */
+ if ( !initialMap )
+ {
+ for ( i = 0; i < hintmap->count; i++ )
+ {
+ if ( !cf2_hint_isSynthetic( &hintmap->edge[i] ) )
+ {
+ /* Note: include both valid and invalid edges */
+ /* Note: top and bottom edges are copied back separately */
+ CF2_StemHint stemhint = (CF2_StemHint)
+ cf2_arrstack_getPointer( hStemHintArray,
+ hintmap->edge[i].index );
+
+
+ if ( cf2_hint_isTop( &hintmap->edge[i] ) )
+ stemhint->maxDS = hintmap->edge[i].dsCoord;
+ else
+ stemhint->minDS = hintmap->edge[i].dsCoord;
+
+ stemhint->used = TRUE;
+ }
+ }
+ }
+
+ /* hint map is ready to use */
+ hintmap->isValid = TRUE;
+
+ /* remember this mask has been used */
+ cf2_hintmask_setNew( hintMask, FALSE );
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cf2_glyphpath_init( CF2_GlyphPath glyphpath,
+ CF2_Font font,
+ CF2_OutlineCallbacks callbacks,
+ CF2_Fixed scaleY,
+ /* CF2_Fixed hShift, */
+ CF2_ArrStack hStemHintArray,
+ CF2_ArrStack vStemHintArray,
+ CF2_HintMask hintMask,
+ CF2_Fixed hintOriginY,
+ const CF2_Blues blues,
+ const FT_Vector* fractionalTranslation )
+ {
+ FT_ZERO( glyphpath );
+
+ glyphpath->font = font;
+ glyphpath->callbacks = callbacks;
+
+ cf2_arrstack_init( &glyphpath->hintMoves,
+ font->memory,
+ &font->error,
+ sizeof ( CF2_HintMoveRec ) );
+
+ cf2_hintmap_init( &glyphpath->initialHintMap,
+ font,
+ &glyphpath->initialHintMap,
+ &glyphpath->hintMoves,
+ scaleY );
+ cf2_hintmap_init( &glyphpath->firstHintMap,
+ font,
+ &glyphpath->initialHintMap,
+ &glyphpath->hintMoves,
+ scaleY );
+ cf2_hintmap_init( &glyphpath->hintMap,
+ font,
+ &glyphpath->initialHintMap,
+ &glyphpath->hintMoves,
+ scaleY );
+
+ glyphpath->scaleX = font->innerTransform.a;
+ glyphpath->scaleC = font->innerTransform.c;
+ glyphpath->scaleY = font->innerTransform.d;
+
+ glyphpath->fractionalTranslation = *fractionalTranslation;
+
+#if 0
+ glyphpath->hShift = hShift; /* for fauxing */
+#endif
+
+ glyphpath->hStemHintArray = hStemHintArray;
+ glyphpath->vStemHintArray = vStemHintArray;
+ glyphpath->hintMask = hintMask; /* ptr to current mask */
+ glyphpath->hintOriginY = hintOriginY;
+ glyphpath->blues = blues;
+ glyphpath->darken = font->darkened; /* TODO: should we make copies? */
+ glyphpath->xOffset = font->darkenX;
+ glyphpath->yOffset = font->darkenY;
+ glyphpath->miterLimit = 2 * FT_MAX(
+ cf2_fixedAbs( glyphpath->xOffset ),
+ cf2_fixedAbs( glyphpath->yOffset ) );
+
+ /* .1 character space unit */
+ glyphpath->snapThreshold = cf2_doubleToFixed( 0.1 );
+
+ glyphpath->moveIsPending = TRUE;
+ glyphpath->pathIsOpen = FALSE;
+ glyphpath->pathIsClosing = FALSE;
+ glyphpath->elemIsQueued = FALSE;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cf2_glyphpath_finalize( CF2_GlyphPath glyphpath )
+ {
+ cf2_arrstack_finalize( &glyphpath->hintMoves );
+ }
+
+
+ /*
+ * Hint point in y-direction and apply outerTransform.
+ * Input `current' hint map (which is actually delayed by one element).
+ * Input x,y point in Character Space.
+ * Output x,y point in Device Space, including translation.
+ */
+ static void
+ cf2_glyphpath_hintPoint( CF2_GlyphPath glyphpath,
+ CF2_HintMap hintmap,
+ FT_Vector* ppt,
+ CF2_Fixed x,
+ CF2_Fixed y )
+ {
+ FT_Vector pt; /* hinted point in upright DS */
+
+
+ pt.x = ADD_INT32( FT_MulFix( glyphpath->scaleX, x ),
+ FT_MulFix( glyphpath->scaleC, y ) );
+ pt.y = cf2_hintmap_map( hintmap, y );
+
+ ppt->x = ADD_INT32(
+ FT_MulFix( glyphpath->font->outerTransform.a, pt.x ),
+ ADD_INT32(
+ FT_MulFix( glyphpath->font->outerTransform.c, pt.y ),
+ glyphpath->fractionalTranslation.x ) );
+ ppt->y = ADD_INT32(
+ FT_MulFix( glyphpath->font->outerTransform.b, pt.x ),
+ ADD_INT32(
+ FT_MulFix( glyphpath->font->outerTransform.d, pt.y ),
+ glyphpath->fractionalTranslation.y ) );
+ }
+
+
+ /*
+ * From two line segments, (u1,u2) and (v1,v2), compute a point of
+ * intersection on the corresponding lines.
+ * Return false if no intersection is found, or if the intersection is
+ * too far away from the ends of the line segments, u2 and v1.
+ *
+ */
+ static FT_Bool
+ cf2_glyphpath_computeIntersection( CF2_GlyphPath glyphpath,
+ const FT_Vector* u1,
+ const FT_Vector* u2,
+ const FT_Vector* v1,
+ const FT_Vector* v2,
+ FT_Vector* intersection )
+ {
+ /*
+ * Let `u' be a zero-based vector from the first segment, `v' from the
+ * second segment.
+ * Let `w 'be the zero-based vector from `u1' to `v1'.
+ * `perp' is the `perpendicular dot product'; see
+ * https://mathworld.wolfram.com/PerpDotProduct.html.
+ * `s' is the parameter for the parametric line for the first segment
+ * (`u').
+ *
+ * See notation in
+ * http://softsurfer.com/Archive/algorithm_0104/algorithm_0104B.htm.
+ * Calculations are done in 16.16, but must handle the squaring of
+ * line lengths in character space. We scale all vectors by 1/32 to
+ * avoid overflow. This allows values up to 4095 to be squared. The
+ * scale factor cancels in the divide.
+ *
+ * TODO: the scale factor could be computed from UnitsPerEm.
+ *
+ */
+
+#define cf2_perp( a, b ) \
+ ( FT_MulFix( a.x, b.y ) - FT_MulFix( a.y, b.x ) )
+
+ /* round and divide by 32 */
+#define CF2_CS_SCALE( x ) \
+ ( ( (x) + 0x10 ) >> 5 )
+
+ FT_Vector u, v, w; /* scaled vectors */
+ CF2_Fixed denominator, s;
+
+
+ u.x = CF2_CS_SCALE( SUB_INT32( u2->x, u1->x ) );
+ u.y = CF2_CS_SCALE( SUB_INT32( u2->y, u1->y ) );
+ v.x = CF2_CS_SCALE( SUB_INT32( v2->x, v1->x ) );
+ v.y = CF2_CS_SCALE( SUB_INT32( v2->y, v1->y ) );
+ w.x = CF2_CS_SCALE( SUB_INT32( v1->x, u1->x ) );
+ w.y = CF2_CS_SCALE( SUB_INT32( v1->y, u1->y ) );
+
+ denominator = cf2_perp( u, v );
+
+ if ( denominator == 0 )
+ return FALSE; /* parallel or coincident lines */
+
+ s = FT_DivFix( cf2_perp( w, v ), denominator );
+
+ intersection->x = ADD_INT32( u1->x,
+ FT_MulFix( s, SUB_INT32( u2->x, u1->x ) ) );
+ intersection->y = ADD_INT32( u1->y,
+ FT_MulFix( s, SUB_INT32( u2->y, u1->y ) ) );
+
+
+ /*
+ * Special case snapping for horizontal and vertical lines.
+ * This cleans up intersections and reduces problems with winding
+ * order detection.
+ * Sample case is sbc cd KozGoPr6N-Medium.otf 20 16685.
+ * Note: these calculations are in character space.
+ *
+ */
+
+ if ( u1->x == u2->x &&
+ cf2_fixedAbs( SUB_INT32( intersection->x,
+ u1->x ) ) < glyphpath->snapThreshold )
+ intersection->x = u1->x;
+ if ( u1->y == u2->y &&
+ cf2_fixedAbs( SUB_INT32( intersection->y,
+ u1->y ) ) < glyphpath->snapThreshold )
+ intersection->y = u1->y;
+
+ if ( v1->x == v2->x &&
+ cf2_fixedAbs( SUB_INT32( intersection->x,
+ v1->x ) ) < glyphpath->snapThreshold )
+ intersection->x = v1->x;
+ if ( v1->y == v2->y &&
+ cf2_fixedAbs( SUB_INT32( intersection->y,
+ v1->y ) ) < glyphpath->snapThreshold )
+ intersection->y = v1->y;
+
+ /* limit the intersection distance from midpoint of u2 and v1 */
+ if ( cf2_fixedAbs( intersection->x - ADD_INT32( u2->x, v1->x ) / 2 ) >
+ glyphpath->miterLimit ||
+ cf2_fixedAbs( intersection->y - ADD_INT32( u2->y, v1->y ) / 2 ) >
+ glyphpath->miterLimit )
+ return FALSE;
+
+ return TRUE;
+ }
+
+
+ /*
+ * Push the cached element (glyphpath->prevElem*) to the outline
+ * consumer. When a darkening offset is used, the end point of the
+ * cached element may be adjusted to an intersection point or we may
+ * synthesize a connecting line to the current element. If we are
+ * closing a subpath, we may also generate a connecting line to the start
+ * point.
+ *
+ * This is where Character Space (CS) is converted to Device Space (DS)
+ * using a hint map. This calculation must use a HintMap that was valid
+ * at the time the element was saved. For the first point in a subpath,
+ * that is a saved HintMap. For most elements, it just means the caller
+ * has delayed building a HintMap from the current HintMask.
+ *
+ * Transform each point with outerTransform and call the outline
+ * callbacks. This is a general 3x3 transform:
+ *
+ * x' = a*x + c*y + tx, y' = b*x + d*y + ty
+ *
+ * but it uses 4 elements from CF2_Font and the translation part
+ * from CF2_GlyphPath.
+ *
+ */
+ static void
+ cf2_glyphpath_pushPrevElem( CF2_GlyphPath glyphpath,
+ CF2_HintMap hintmap,
+ FT_Vector* nextP0,
+ FT_Vector nextP1,
+ FT_Bool close )
+ {
+ CF2_CallbackParamsRec params;
+
+ FT_Vector* prevP0;
+ FT_Vector* prevP1;
+
+ FT_Vector intersection = { 0, 0 };
+ FT_Bool useIntersection = FALSE;
+
+
+ FT_ASSERT( glyphpath->prevElemOp == CF2_PathOpLineTo ||
+ glyphpath->prevElemOp == CF2_PathOpCubeTo );
+
+ if ( glyphpath->prevElemOp == CF2_PathOpLineTo )
+ {
+ prevP0 = &glyphpath->prevElemP0;
+ prevP1 = &glyphpath->prevElemP1;
+ }
+ else
+ {
+ prevP0 = &glyphpath->prevElemP2;
+ prevP1 = &glyphpath->prevElemP3;
+ }
+
+ /* optimization: if previous and next elements are offset by the same */
+ /* amount, then there will be no gap, and no need to compute an */
+ /* intersection. */
+ if ( prevP1->x != nextP0->x || prevP1->y != nextP0->y )
+ {
+ /* previous element does not join next element: */
+ /* adjust end point of previous element to the intersection */
+ useIntersection = cf2_glyphpath_computeIntersection( glyphpath,
+ prevP0,
+ prevP1,
+ nextP0,
+ &nextP1,
+ &intersection );
+ if ( useIntersection )
+ {
+ /* modify the last point of the cached element (either line or */
+ /* curve) */
+ *prevP1 = intersection;
+ }
+ }
+
+ params.pt0 = glyphpath->currentDS;
+
+ switch( glyphpath->prevElemOp )
+ {
+ case CF2_PathOpLineTo:
+ params.op = CF2_PathOpLineTo;
+
+ /* note: pt2 and pt3 are unused */
+
+ if ( close )
+ {
+ /* use first hint map if closing */
+ cf2_glyphpath_hintPoint( glyphpath,
+ &glyphpath->firstHintMap,
+ &params.pt1,
+ glyphpath->prevElemP1.x,
+ glyphpath->prevElemP1.y );
+ }
+ else
+ {
+ cf2_glyphpath_hintPoint( glyphpath,
+ hintmap,
+ &params.pt1,
+ glyphpath->prevElemP1.x,
+ glyphpath->prevElemP1.y );
+ }
+
+ /* output only non-zero length lines */
+ if ( params.pt0.x != params.pt1.x || params.pt0.y != params.pt1.y )
+ {
+ glyphpath->callbacks->lineTo( glyphpath->callbacks, &params );
+
+ glyphpath->currentDS = params.pt1;
+ }
+ break;
+
+ case CF2_PathOpCubeTo:
+ params.op = CF2_PathOpCubeTo;
+
+ /* TODO: should we intersect the interior joins (p1-p2 and p2-p3)? */
+ cf2_glyphpath_hintPoint( glyphpath,
+ hintmap,
+ &params.pt1,
+ glyphpath->prevElemP1.x,
+ glyphpath->prevElemP1.y );
+ cf2_glyphpath_hintPoint( glyphpath,
+ hintmap,
+ &params.pt2,
+ glyphpath->prevElemP2.x,
+ glyphpath->prevElemP2.y );
+ cf2_glyphpath_hintPoint( glyphpath,
+ hintmap,
+ &params.pt3,
+ glyphpath->prevElemP3.x,
+ glyphpath->prevElemP3.y );
+
+ glyphpath->callbacks->cubeTo( glyphpath->callbacks, &params );
+
+ glyphpath->currentDS = params.pt3;
+
+ break;
+ }
+
+ if ( !useIntersection || close )
+ {
+ /* insert connecting line between end of previous element and start */
+ /* of current one */
+ /* note: at the end of a subpath, we might do both, so use `nextP0' */
+ /* before we change it, below */
+
+ if ( close )
+ {
+ /* if we are closing the subpath, then nextP0 is in the first */
+ /* hint zone */
+ cf2_glyphpath_hintPoint( glyphpath,
+ &glyphpath->firstHintMap,
+ &params.pt1,
+ nextP0->x,
+ nextP0->y );
+ }
+ else
+ {
+ cf2_glyphpath_hintPoint( glyphpath,
+ hintmap,
+ &params.pt1,
+ nextP0->x,
+ nextP0->y );
+ }
+
+ if ( params.pt1.x != glyphpath->currentDS.x ||
+ params.pt1.y != glyphpath->currentDS.y )
+ {
+ /* length is nonzero */
+ params.op = CF2_PathOpLineTo;
+ params.pt0 = glyphpath->currentDS;
+
+ /* note: pt2 and pt3 are unused */
+ glyphpath->callbacks->lineTo( glyphpath->callbacks, &params );
+
+ glyphpath->currentDS = params.pt1;
+ }
+ }
+
+ if ( useIntersection )
+ {
+ /* return intersection point to caller */
+ *nextP0 = intersection;
+ }
+ }
+
+
+ /* push a MoveTo element based on current point and offset of current */
+ /* element */
+ static void
+ cf2_glyphpath_pushMove( CF2_GlyphPath glyphpath,
+ FT_Vector start )
+ {
+ CF2_CallbackParamsRec params;
+
+
+ params.op = CF2_PathOpMoveTo;
+ params.pt0 = glyphpath->currentDS;
+
+ /* Test if move has really happened yet; it would have called */
+ /* `cf2_hintmap_build' to set `isValid'. */
+ if ( !cf2_hintmap_isValid( &glyphpath->hintMap ) )
+ {
+ /* we are here iff first subpath is missing a moveto operator: */
+ /* synthesize first moveTo to finish initialization of hintMap */
+ cf2_glyphpath_moveTo( glyphpath,
+ glyphpath->start.x,
+ glyphpath->start.y );
+ }
+
+ cf2_glyphpath_hintPoint( glyphpath,
+ &glyphpath->hintMap,
+ &params.pt1,
+ start.x,
+ start.y );
+
+ /* note: pt2 and pt3 are unused */
+ glyphpath->callbacks->moveTo( glyphpath->callbacks, &params );
+
+ glyphpath->currentDS = params.pt1;
+ glyphpath->offsetStart0 = start;
+ }
+
+
+ /*
+ * All coordinates are in character space.
+ * On input, (x1, y1) and (x2, y2) give line segment.
+ * On output, (x, y) give offset vector.
+ * We use a piecewise approximation to trig functions.
+ *
+ * TODO: Offset true perpendicular and proper length
+ * supply the y-translation for hinting here, too,
+ * that adds yOffset unconditionally to *y.
+ */
+ static void
+ cf2_glyphpath_computeOffset( CF2_GlyphPath glyphpath,
+ CF2_Fixed x1,
+ CF2_Fixed y1,
+ CF2_Fixed x2,
+ CF2_Fixed y2,
+ CF2_Fixed* x,
+ CF2_Fixed* y )
+ {
+ CF2_Fixed dx = SUB_INT32( x2, x1 );
+ CF2_Fixed dy = SUB_INT32( y2, y1 );
+
+
+ /* note: negative offsets don't work here; negate deltas to change */
+ /* quadrants, below */
+ if ( glyphpath->font->reverseWinding )
+ {
+ dx = NEG_INT32( dx );
+ dy = NEG_INT32( dy );
+ }
+
+ *x = *y = 0;
+
+ if ( !glyphpath->darken )
+ return;
+
+ /* add momentum for this path element */
+ glyphpath->callbacks->windingMomentum =
+ ADD_INT32( glyphpath->callbacks->windingMomentum,
+ cf2_getWindingMomentum( x1, y1, x2, y2 ) );
+
+ /* note: allow mixed integer and fixed multiplication here */
+ if ( dx >= 0 )
+ {
+ if ( dy >= 0 )
+ {
+ /* first quadrant, +x +y */
+
+ if ( dx > MUL_INT32( 2, dy ) )
+ {
+ /* +x */
+ *x = 0;
+ *y = 0;
+ }
+ else if ( dy > MUL_INT32( 2, dx ) )
+ {
+ /* +y */
+ *x = glyphpath->xOffset;
+ *y = glyphpath->yOffset;
+ }
+ else
+ {
+ /* +x +y */
+ *x = FT_MulFix( cf2_doubleToFixed( 0.7 ),
+ glyphpath->xOffset );
+ *y = FT_MulFix( cf2_doubleToFixed( 1.0 - 0.7 ),
+ glyphpath->yOffset );
+ }
+ }
+ else
+ {
+ /* fourth quadrant, +x -y */
+
+ if ( dx > MUL_INT32( -2, dy ) )
+ {
+ /* +x */
+ *x = 0;
+ *y = 0;
+ }
+ else if ( NEG_INT32( dy ) > MUL_INT32( 2, dx ) )
+ {
+ /* -y */
+ *x = NEG_INT32( glyphpath->xOffset );
+ *y = glyphpath->yOffset;
+ }
+ else
+ {
+ /* +x -y */
+ *x = FT_MulFix( cf2_doubleToFixed( -0.7 ),
+ glyphpath->xOffset );
+ *y = FT_MulFix( cf2_doubleToFixed( 1.0 - 0.7 ),
+ glyphpath->yOffset );
+ }
+ }
+ }
+ else
+ {
+ if ( dy >= 0 )
+ {
+ /* second quadrant, -x +y */
+
+ if ( NEG_INT32( dx ) > MUL_INT32( 2, dy ) )
+ {
+ /* -x */
+ *x = 0;
+ *y = MUL_INT32( 2, glyphpath->yOffset );
+ }
+ else if ( dy > MUL_INT32( -2, dx ) )
+ {
+ /* +y */
+ *x = glyphpath->xOffset;
+ *y = glyphpath->yOffset;
+ }
+ else
+ {
+ /* -x +y */
+ *x = FT_MulFix( cf2_doubleToFixed( 0.7 ),
+ glyphpath->xOffset );
+ *y = FT_MulFix( cf2_doubleToFixed( 1.0 + 0.7 ),
+ glyphpath->yOffset );
+ }
+ }
+ else
+ {
+ /* third quadrant, -x -y */
+
+ if ( NEG_INT32( dx ) > MUL_INT32( -2, dy ) )
+ {
+ /* -x */
+ *x = 0;
+ *y = MUL_INT32( 2, glyphpath->yOffset );
+ }
+ else if ( NEG_INT32( dy ) > MUL_INT32( -2, dx ) )
+ {
+ /* -y */
+ *x = NEG_INT32( glyphpath->xOffset );
+ *y = glyphpath->yOffset;
+ }
+ else
+ {
+ /* -x -y */
+ *x = FT_MulFix( cf2_doubleToFixed( -0.7 ),
+ glyphpath->xOffset );
+ *y = FT_MulFix( cf2_doubleToFixed( 1.0 + 0.7 ),
+ glyphpath->yOffset );
+ }
+ }
+ }
+ }
+
+
+ /*
+ * The functions cf2_glyphpath_{moveTo,lineTo,curveTo,closeOpenPath} are
+ * called by the interpreter with Character Space (CS) coordinates. Each
+ * path element is placed into a queue of length one to await the
+ * calculation of the following element. At that time, the darkening
+ * offset of the following element is known and joins can be computed,
+ * including possible modification of this element, before mapping to
+ * Device Space (DS) and passing it on to the outline consumer.
+ *
+ */
+ FT_LOCAL_DEF( void )
+ cf2_glyphpath_moveTo( CF2_GlyphPath glyphpath,
+ CF2_Fixed x,
+ CF2_Fixed y )
+ {
+ cf2_glyphpath_closeOpenPath( glyphpath );
+
+ /* save the parameters of the move for later, when we'll know how to */
+ /* offset it; */
+ /* also save last move point */
+ glyphpath->currentCS.x = glyphpath->start.x = x;
+ glyphpath->currentCS.y = glyphpath->start.y = y;
+
+ glyphpath->moveIsPending = TRUE;
+
+ /* ensure we have a valid map with current mask */
+ if ( !cf2_hintmap_isValid( &glyphpath->hintMap ) ||
+ cf2_hintmask_isNew( glyphpath->hintMask ) )
+ cf2_hintmap_build( &glyphpath->hintMap,
+ glyphpath->hStemHintArray,
+ glyphpath->vStemHintArray,
+ glyphpath->hintMask,
+ glyphpath->hintOriginY,
+ FALSE );
+
+ /* save a copy of current HintMap to use when drawing initial point */
+ glyphpath->firstHintMap = glyphpath->hintMap; /* structure copy */
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cf2_glyphpath_lineTo( CF2_GlyphPath glyphpath,
+ CF2_Fixed x,
+ CF2_Fixed y )
+ {
+ CF2_Fixed xOffset, yOffset;
+ FT_Vector P0, P1;
+ FT_Bool newHintMap;
+
+ /*
+ * New hints will be applied after cf2_glyphpath_pushPrevElem has run.
+ * In case this is a synthesized closing line, any new hints should be
+ * delayed until this path is closed (`cf2_hintmask_isNew' will be
+ * called again before the next line or curve).
+ */
+
+ /* true if new hint map not on close */
+ newHintMap = cf2_hintmask_isNew( glyphpath->hintMask ) &&
+ !glyphpath->pathIsClosing;
+
+ /*
+ * Zero-length lines may occur in the charstring. Because we cannot
+ * compute darkening offsets or intersections from zero-length lines,
+ * it is best to remove them and avoid artifacts. However, zero-length
+ * lines in CS at the start of a new hint map can generate non-zero
+ * lines in DS due to hint substitution. We detect a change in hint
+ * map here and pass those zero-length lines along.
+ */
+
+ /*
+ * Note: Find explicitly closed paths here with a conditional
+ * breakpoint using
+ *
+ * !gp->pathIsClosing && gp->start.x == x && gp->start.y == y
+ *
+ */
+
+ if ( glyphpath->currentCS.x == x &&
+ glyphpath->currentCS.y == y &&
+ !newHintMap )
+ /*
+ * Ignore zero-length lines in CS where the hint map is the same
+ * because the line in DS will also be zero length.
+ *
+ * Ignore zero-length lines when we synthesize a closing line because
+ * the close will be handled in cf2_glyphPath_pushPrevElem.
+ */
+ return;
+
+ cf2_glyphpath_computeOffset( glyphpath,
+ glyphpath->currentCS.x,
+ glyphpath->currentCS.y,
+ x,
+ y,
+ &xOffset,
+ &yOffset );
+
+ /* construct offset points */
+ P0.x = ADD_INT32( glyphpath->currentCS.x, xOffset );
+ P0.y = ADD_INT32( glyphpath->currentCS.y, yOffset );
+ P1.x = ADD_INT32( x, xOffset );
+ P1.y = ADD_INT32( y, yOffset );
+
+ if ( glyphpath->moveIsPending )
+ {
+ /* emit offset 1st point as MoveTo */
+ cf2_glyphpath_pushMove( glyphpath, P0 );
+
+ glyphpath->moveIsPending = FALSE; /* adjust state machine */
+ glyphpath->pathIsOpen = TRUE;
+
+ glyphpath->offsetStart1 = P1; /* record second point */
+ }
+
+ if ( glyphpath->elemIsQueued )
+ {
+ FT_ASSERT( cf2_hintmap_isValid( &glyphpath->hintMap ) ||
+ glyphpath->hintMap.count == 0 );
+
+ cf2_glyphpath_pushPrevElem( glyphpath,
+ &glyphpath->hintMap,
+ &P0,
+ P1,
+ FALSE );
+ }
+
+ /* queue the current element with offset points */
+ glyphpath->elemIsQueued = TRUE;
+ glyphpath->prevElemOp = CF2_PathOpLineTo;
+ glyphpath->prevElemP0 = P0;
+ glyphpath->prevElemP1 = P1;
+
+ /* update current map */
+ if ( newHintMap )
+ cf2_hintmap_build( &glyphpath->hintMap,
+ glyphpath->hStemHintArray,
+ glyphpath->vStemHintArray,
+ glyphpath->hintMask,
+ glyphpath->hintOriginY,
+ FALSE );
+
+ glyphpath->currentCS.x = x; /* pre-offset current point */
+ glyphpath->currentCS.y = y;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cf2_glyphpath_curveTo( CF2_GlyphPath glyphpath,
+ CF2_Fixed x1,
+ CF2_Fixed y1,
+ CF2_Fixed x2,
+ CF2_Fixed y2,
+ CF2_Fixed x3,
+ CF2_Fixed y3 )
+ {
+ CF2_Fixed xOffset1, yOffset1, xOffset3, yOffset3;
+ FT_Vector P0, P1, P2, P3;
+
+
+ /* TODO: ignore zero length portions of curve?? */
+ cf2_glyphpath_computeOffset( glyphpath,
+ glyphpath->currentCS.x,
+ glyphpath->currentCS.y,
+ x1,
+ y1,
+ &xOffset1,
+ &yOffset1 );
+ cf2_glyphpath_computeOffset( glyphpath,
+ x2,
+ y2,
+ x3,
+ y3,
+ &xOffset3,
+ &yOffset3 );
+
+ /* add momentum from the middle segment */
+ glyphpath->callbacks->windingMomentum =
+ ADD_INT32( glyphpath->callbacks->windingMomentum,
+ cf2_getWindingMomentum( x1, y1, x2, y2 ) );
+
+ /* construct offset points */
+ P0.x = ADD_INT32( glyphpath->currentCS.x, xOffset1 );
+ P0.y = ADD_INT32( glyphpath->currentCS.y, yOffset1 );
+ P1.x = ADD_INT32( x1, xOffset1 );
+ P1.y = ADD_INT32( y1, yOffset1 );
+ /* note: preserve angle of final segment by using offset3 at both ends */
+ P2.x = ADD_INT32( x2, xOffset3 );
+ P2.y = ADD_INT32( y2, yOffset3 );
+ P3.x = ADD_INT32( x3, xOffset3 );
+ P3.y = ADD_INT32( y3, yOffset3 );
+
+ if ( glyphpath->moveIsPending )
+ {
+ /* emit offset 1st point as MoveTo */
+ cf2_glyphpath_pushMove( glyphpath, P0 );
+
+ glyphpath->moveIsPending = FALSE;
+ glyphpath->pathIsOpen = TRUE;
+
+ glyphpath->offsetStart1 = P1; /* record second point */
+ }
+
+ if ( glyphpath->elemIsQueued )
+ {
+ FT_ASSERT( cf2_hintmap_isValid( &glyphpath->hintMap ) ||
+ glyphpath->hintMap.count == 0 );
+
+ cf2_glyphpath_pushPrevElem( glyphpath,
+ &glyphpath->hintMap,
+ &P0,
+ P1,
+ FALSE );
+ }
+
+ /* queue the current element with offset points */
+ glyphpath->elemIsQueued = TRUE;
+ glyphpath->prevElemOp = CF2_PathOpCubeTo;
+ glyphpath->prevElemP0 = P0;
+ glyphpath->prevElemP1 = P1;
+ glyphpath->prevElemP2 = P2;
+ glyphpath->prevElemP3 = P3;
+
+ /* update current map */
+ if ( cf2_hintmask_isNew( glyphpath->hintMask ) )
+ cf2_hintmap_build( &glyphpath->hintMap,
+ glyphpath->hStemHintArray,
+ glyphpath->vStemHintArray,
+ glyphpath->hintMask,
+ glyphpath->hintOriginY,
+ FALSE );
+
+ glyphpath->currentCS.x = x3; /* pre-offset current point */
+ glyphpath->currentCS.y = y3;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cf2_glyphpath_closeOpenPath( CF2_GlyphPath glyphpath )
+ {
+ if ( glyphpath->pathIsOpen )
+ {
+ /*
+ * A closing line in Character Space line is always generated below
+ * with `cf2_glyphPath_lineTo'. It may be ignored later if it turns
+ * out to be zero length in Device Space.
+ */
+ glyphpath->pathIsClosing = TRUE;
+
+ cf2_glyphpath_lineTo( glyphpath,
+ glyphpath->start.x,
+ glyphpath->start.y );
+
+ /* empty the final element from the queue and close the path */
+ if ( glyphpath->elemIsQueued )
+ cf2_glyphpath_pushPrevElem( glyphpath,
+ &glyphpath->hintMap,
+ &glyphpath->offsetStart0,
+ glyphpath->offsetStart1,
+ TRUE );
+
+ /* reset state machine */
+ glyphpath->moveIsPending = TRUE;
+ glyphpath->pathIsOpen = FALSE;
+ glyphpath->pathIsClosing = FALSE;
+ glyphpath->elemIsQueued = FALSE;
+ }
+ }
+
+
+/* END */
diff --git a/thirdparty/freetype/src/psaux/pshints.h b/thirdparty/freetype/src/psaux/pshints.h
new file mode 100644
index 0000000000..92e37e98ae
--- /dev/null
+++ b/thirdparty/freetype/src/psaux/pshints.h
@@ -0,0 +1,288 @@
+/***************************************************************************/
+/* */
+/* pshints.h */
+/* */
+/* Adobe's code for handling CFF hints (body). */
+/* */
+/* Copyright 2007-2013 Adobe Systems Incorporated. */
+/* */
+/* This software, and all works of authorship, whether in source or */
+/* object code form as indicated by the copyright notice(s) included */
+/* herein (collectively, the "Work") is made available, and may only be */
+/* used, modified, and distributed under the FreeType Project License, */
+/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
+/* FreeType Project License, each contributor to the Work hereby grants */
+/* to any individual or legal entity exercising permissions granted by */
+/* the FreeType Project License and this section (hereafter, "You" or */
+/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
+/* royalty-free, irrevocable (except as stated in this section) patent */
+/* license to make, have made, use, offer to sell, sell, import, and */
+/* otherwise transfer the Work, where such license applies only to those */
+/* patent claims licensable by such contributor that are necessarily */
+/* infringed by their contribution(s) alone or by combination of their */
+/* contribution(s) with the Work to which such contribution(s) was */
+/* submitted. If You institute patent litigation against any entity */
+/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
+/* the Work or a contribution incorporated within the Work constitutes */
+/* direct or contributory patent infringement, then any patent licenses */
+/* granted to You under this License for that Work shall terminate as of */
+/* the date such litigation is filed. */
+/* */
+/* By using, modifying, or distributing the Work you indicate that you */
+/* have read and understood the terms and conditions of the */
+/* FreeType Project License as well as those provided in this section, */
+/* and you accept them fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef PSHINT_H_
+#define PSHINT_H_
+
+FT_BEGIN_HEADER
+
+
+ enum
+ {
+ CF2_MAX_HINTS = 96 /* maximum # of hints */
+ };
+
+
+ /*
+ * A HintMask object stores a bit mask that specifies which hints in the
+ * charstring are active at a given time. Hints in CFF must be declared
+ * at the start, before any drawing operators, with horizontal hints
+ * preceding vertical hints. The HintMask is ordered the same way, with
+ * horizontal hints immediately followed by vertical hints. Clients are
+ * responsible for knowing how many of each type are present.
+ *
+ * The maximum total number of hints is 96, as specified by the CFF
+ * specification.
+ *
+ * A HintMask is built 0 or more times while interpreting a charstring, by
+ * the HintMask operator. There is only one HintMask, but it is built or
+ * rebuilt each time there is a hint substitution (HintMask operator) in
+ * the charstring. A default HintMask with all bits set is built if there
+ * has been no HintMask operator prior to the first drawing operator.
+ *
+ */
+
+ typedef struct CF2_HintMaskRec_
+ {
+ FT_Error* error;
+
+ FT_Bool isValid;
+ FT_Bool isNew;
+
+ size_t bitCount;
+ size_t byteCount;
+
+ FT_Byte mask[( CF2_MAX_HINTS + 7 ) / 8];
+
+ } CF2_HintMaskRec, *CF2_HintMask;
+
+
+ typedef struct CF2_StemHintRec_
+ {
+ FT_Bool used; /* DS positions are valid */
+
+ CF2_Fixed min; /* original character space value */
+ CF2_Fixed max;
+
+ CF2_Fixed minDS; /* DS position after first use */
+ CF2_Fixed maxDS;
+
+ } CF2_StemHintRec, *CF2_StemHint;
+
+
+ /*
+ * A HintMap object stores a piecewise linear function for mapping
+ * y-coordinates from character space to device space, providing
+ * appropriate pixel alignment to stem edges.
+ *
+ * The map is implemented as an array of `CF2_Hint' elements, each
+ * representing an edge. When edges are paired, as from stem hints, the
+ * bottom edge must immediately precede the top edge in the array.
+ * Element character space AND device space positions must both increase
+ * monotonically in the array. `CF2_Hint' elements are also used as
+ * parameters to `cf2_blues_capture'.
+ *
+ * The `cf2_hintmap_build' method must be called before any drawing
+ * operation (beginning with a Move operator) and at each hint
+ * substitution (HintMask operator).
+ *
+ * The `cf2_hintmap_map' method is called to transform y-coordinates at
+ * each drawing operation (move, line, curve).
+ *
+ */
+
+ /* TODO: make this a CF2_ArrStack and add a deep copy method */
+ enum
+ {
+ CF2_MAX_HINT_EDGES = CF2_MAX_HINTS * 2
+ };
+
+
+ typedef struct CF2_HintMapRec_
+ {
+ CF2_Font font;
+
+ /* initial map based on blue zones */
+ struct CF2_HintMapRec_* initialHintMap;
+
+ /* working storage for 2nd pass adjustHints */
+ CF2_ArrStack hintMoves;
+
+ FT_Bool isValid;
+ FT_Bool hinted;
+
+ CF2_Fixed scale;
+ CF2_UInt count;
+
+ /* start search from this index */
+ CF2_UInt lastIndex;
+
+ CF2_HintRec edge[CF2_MAX_HINT_EDGES]; /* 192 */
+
+ } CF2_HintMapRec, *CF2_HintMap;
+
+
+ FT_LOCAL( FT_Bool )
+ cf2_hint_isValid( const CF2_Hint hint );
+ FT_LOCAL( FT_Bool )
+ cf2_hint_isTop( const CF2_Hint hint );
+ FT_LOCAL( FT_Bool )
+ cf2_hint_isBottom( const CF2_Hint hint );
+ FT_LOCAL( void )
+ cf2_hint_lock( CF2_Hint hint );
+
+
+ FT_LOCAL( void )
+ cf2_hintmap_init( CF2_HintMap hintmap,
+ CF2_Font font,
+ CF2_HintMap initialMap,
+ CF2_ArrStack hintMoves,
+ CF2_Fixed scale );
+ FT_LOCAL( void )
+ cf2_hintmap_build( CF2_HintMap hintmap,
+ CF2_ArrStack hStemHintArray,
+ CF2_ArrStack vStemHintArray,
+ CF2_HintMask hintMask,
+ CF2_Fixed hintOrigin,
+ FT_Bool initialMap );
+
+
+ /*
+ * GlyphPath is a wrapper for drawing operations that scales the
+ * coordinates according to the render matrix and HintMap. It also tracks
+ * open paths to control ClosePath and to insert MoveTo for broken fonts.
+ *
+ */
+ typedef struct CF2_GlyphPathRec_
+ {
+ /* TODO: gather some of these into a hinting context */
+
+ CF2_Font font; /* font instance */
+ CF2_OutlineCallbacks callbacks; /* outline consumer */
+
+
+ CF2_HintMapRec hintMap; /* current hint map */
+ CF2_HintMapRec firstHintMap; /* saved copy */
+ CF2_HintMapRec initialHintMap; /* based on all captured hints */
+
+ CF2_ArrStackRec hintMoves; /* list of hint moves for 2nd pass */
+
+ CF2_Fixed scaleX; /* matrix a */
+ CF2_Fixed scaleC; /* matrix c */
+ CF2_Fixed scaleY; /* matrix d */
+
+ FT_Vector fractionalTranslation; /* including deviceXScale */
+#if 0
+ CF2_Fixed hShift; /* character space horizontal shift */
+ /* (for fauxing) */
+#endif
+
+ FT_Bool pathIsOpen; /* true after MoveTo */
+ FT_Bool pathIsClosing; /* true when synthesizing closepath line */
+ FT_Bool darken; /* true if stem darkening */
+ FT_Bool moveIsPending; /* true between MoveTo and offset MoveTo */
+
+ /* references used to call `cf2_hintmap_build', if necessary */
+ CF2_ArrStack hStemHintArray;
+ CF2_ArrStack vStemHintArray;
+ CF2_HintMask hintMask; /* ptr to the current mask */
+ CF2_Fixed hintOriginY; /* copy of current origin */
+ const CF2_BluesRec* blues;
+
+ CF2_Fixed xOffset; /* character space offsets */
+ CF2_Fixed yOffset;
+
+ /* character space miter limit threshold */
+ CF2_Fixed miterLimit;
+ /* vertical/horizontal snap distance in character space */
+ CF2_Fixed snapThreshold;
+
+ FT_Vector offsetStart0; /* first and second points of first */
+ FT_Vector offsetStart1; /* element with offset applied */
+
+ /* current point, character space, before offset */
+ FT_Vector currentCS;
+ /* current point, device space */
+ FT_Vector currentDS;
+ /* start point of subpath, character space */
+ FT_Vector start;
+
+ /* the following members constitute the `queue' of one element */
+ FT_Bool elemIsQueued;
+ CF2_Int prevElemOp;
+
+ FT_Vector prevElemP0;
+ FT_Vector prevElemP1;
+ FT_Vector prevElemP2;
+ FT_Vector prevElemP3;
+
+ } CF2_GlyphPathRec, *CF2_GlyphPath;
+
+
+ FT_LOCAL( void )
+ cf2_glyphpath_init( CF2_GlyphPath glyphpath,
+ CF2_Font font,
+ CF2_OutlineCallbacks callbacks,
+ CF2_Fixed scaleY,
+ /* CF2_Fixed hShift, */
+ CF2_ArrStack hStemHintArray,
+ CF2_ArrStack vStemHintArray,
+ CF2_HintMask hintMask,
+ CF2_Fixed hintOrigin,
+ const CF2_Blues blues,
+ const FT_Vector* fractionalTranslation );
+ FT_LOCAL( void )
+ cf2_glyphpath_finalize( CF2_GlyphPath glyphpath );
+
+ FT_LOCAL( void )
+ cf2_glyphpath_moveTo( CF2_GlyphPath glyphpath,
+ CF2_Fixed x,
+ CF2_Fixed y );
+ FT_LOCAL( void )
+ cf2_glyphpath_lineTo( CF2_GlyphPath glyphpath,
+ CF2_Fixed x,
+ CF2_Fixed y );
+ FT_LOCAL( void )
+ cf2_glyphpath_curveTo( CF2_GlyphPath glyphpath,
+ CF2_Fixed x1,
+ CF2_Fixed y1,
+ CF2_Fixed x2,
+ CF2_Fixed y2,
+ CF2_Fixed x3,
+ CF2_Fixed y3 );
+ FT_LOCAL( void )
+ cf2_glyphpath_closeOpenPath( CF2_GlyphPath glyphpath );
+
+
+FT_END_HEADER
+
+
+#endif /* PSHINT_H_ */
+
+
+/* END */
diff --git a/thirdparty/freetype/src/psaux/psintrp.c b/thirdparty/freetype/src/psaux/psintrp.c
new file mode 100644
index 0000000000..da5a8dad1d
--- /dev/null
+++ b/thirdparty/freetype/src/psaux/psintrp.c
@@ -0,0 +1,3040 @@
+/***************************************************************************/
+/* */
+/* psintrp.c */
+/* */
+/* Adobe's CFF Interpreter (body). */
+/* */
+/* Copyright 2007-2014 Adobe Systems Incorporated. */
+/* */
+/* This software, and all works of authorship, whether in source or */
+/* object code form as indicated by the copyright notice(s) included */
+/* herein (collectively, the "Work") is made available, and may only be */
+/* used, modified, and distributed under the FreeType Project License, */
+/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
+/* FreeType Project License, each contributor to the Work hereby grants */
+/* to any individual or legal entity exercising permissions granted by */
+/* the FreeType Project License and this section (hereafter, "You" or */
+/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
+/* royalty-free, irrevocable (except as stated in this section) patent */
+/* license to make, have made, use, offer to sell, sell, import, and */
+/* otherwise transfer the Work, where such license applies only to those */
+/* patent claims licensable by such contributor that are necessarily */
+/* infringed by their contribution(s) alone or by combination of their */
+/* contribution(s) with the Work to which such contribution(s) was */
+/* submitted. If You institute patent litigation against any entity */
+/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
+/* the Work or a contribution incorporated within the Work constitutes */
+/* direct or contributory patent infringement, then any patent licenses */
+/* granted to You under this License for that Work shall terminate as of */
+/* the date such litigation is filed. */
+/* */
+/* By using, modifying, or distributing the Work you indicate that you */
+/* have read and understood the terms and conditions of the */
+/* FreeType Project License as well as those provided in this section, */
+/* and you accept them fully. */
+/* */
+/***************************************************************************/
+
+
+#include "psft.h"
+#include FT_INTERNAL_DEBUG_H
+#include FT_SERVICE_CFF_TABLE_LOAD_H
+
+#include "psglue.h"
+#include "psfont.h"
+#include "psstack.h"
+#include "pshints.h"
+#include "psintrp.h"
+
+#include "pserror.h"
+
+#include "psobjs.h" /* for cff_random */
+#include "t1decode.h" /* for t1 seac */
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_cf2interp
+
+
+ FT_LOCAL_DEF( void )
+ cf2_hintmask_init( CF2_HintMask hintmask,
+ FT_Error* error )
+ {
+ FT_ZERO( hintmask );
+
+ hintmask->error = error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Bool )
+ cf2_hintmask_isValid( const CF2_HintMask hintmask )
+ {
+ return hintmask->isValid;
+ }
+
+
+ FT_LOCAL_DEF( FT_Bool )
+ cf2_hintmask_isNew( const CF2_HintMask hintmask )
+ {
+ return hintmask->isNew;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cf2_hintmask_setNew( CF2_HintMask hintmask,
+ FT_Bool val )
+ {
+ hintmask->isNew = val;
+ }
+
+
+ /* clients call `getMaskPtr' in order to iterate */
+ /* through hint mask */
+
+ FT_LOCAL_DEF( FT_Byte* )
+ cf2_hintmask_getMaskPtr( CF2_HintMask hintmask )
+ {
+ return hintmask->mask;
+ }
+
+
+ static size_t
+ cf2_hintmask_setCounts( CF2_HintMask hintmask,
+ size_t bitCount )
+ {
+ if ( bitCount > CF2_MAX_HINTS )
+ {
+ /* total of h and v stems must be <= 96 */
+ CF2_SET_ERROR( hintmask->error, Invalid_Glyph_Format );
+ return 0;
+ }
+
+ hintmask->bitCount = bitCount;
+ hintmask->byteCount = ( hintmask->bitCount + 7 ) / 8;
+
+ hintmask->isValid = TRUE;
+ hintmask->isNew = TRUE;
+
+ return bitCount;
+ }
+
+
+ /* consume the hintmask bytes from the charstring, advancing the src */
+ /* pointer */
+ static void
+ cf2_hintmask_read( CF2_HintMask hintmask,
+ CF2_Buffer charstring,
+ size_t bitCount )
+ {
+ size_t i;
+
+#ifndef CF2_NDEBUG
+ /* these are the bits in the final mask byte that should be zero */
+ /* Note: this variable is only used in an assert expression below */
+ /* and then only if CF2_NDEBUG is not defined */
+ CF2_UInt mask = ( 1 << ( -(CF2_Int)bitCount & 7 ) ) - 1;
+#endif
+
+
+ /* initialize counts and isValid */
+ if ( cf2_hintmask_setCounts( hintmask, bitCount ) == 0 )
+ return;
+
+ FT_ASSERT( hintmask->byteCount > 0 );
+
+ FT_TRACE4(( " (maskbytes:" ));
+
+ /* set mask and advance interpreter's charstring pointer */
+ for ( i = 0; i < hintmask->byteCount; i++ )
+ {
+ hintmask->mask[i] = (FT_Byte)cf2_buf_readByte( charstring );
+ FT_TRACE4(( " 0x%02X", hintmask->mask[i] ));
+ }
+
+ FT_TRACE4(( ")\n" ));
+
+ /* assert any unused bits in last byte are zero unless there's a prior */
+ /* error */
+ /* bitCount -> mask, 0 -> 0, 1 -> 7f, 2 -> 3f, ... 6 -> 3, 7 -> 1 */
+#ifndef CF2_NDEBUG
+ FT_ASSERT( ( hintmask->mask[hintmask->byteCount - 1] & mask ) == 0 ||
+ *hintmask->error );
+#endif
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cf2_hintmask_setAll( CF2_HintMask hintmask,
+ size_t bitCount )
+ {
+ size_t i;
+ CF2_UInt mask = ( 1 << ( -(CF2_Int)bitCount & 7 ) ) - 1;
+
+
+ /* initialize counts and isValid */
+ if ( cf2_hintmask_setCounts( hintmask, bitCount ) == 0 )
+ return;
+
+ FT_ASSERT( hintmask->byteCount > 0 );
+ FT_ASSERT( hintmask->byteCount <=
+ sizeof ( hintmask->mask ) / sizeof ( hintmask->mask[0] ) );
+
+ /* set mask to all ones */
+ for ( i = 0; i < hintmask->byteCount; i++ )
+ hintmask->mask[i] = 0xFF;
+
+ /* clear unused bits */
+ /* bitCount -> mask, 0 -> 0, 1 -> 7f, 2 -> 3f, ... 6 -> 3, 7 -> 1 */
+ hintmask->mask[hintmask->byteCount - 1] &= ~mask;
+ }
+
+
+ /* Type2 charstring opcodes */
+ enum
+ {
+ cf2_cmdRESERVED_0, /* 0 */
+ cf2_cmdHSTEM, /* 1 */
+ cf2_cmdRESERVED_2, /* 2 */
+ cf2_cmdVSTEM, /* 3 */
+ cf2_cmdVMOVETO, /* 4 */
+ cf2_cmdRLINETO, /* 5 */
+ cf2_cmdHLINETO, /* 6 */
+ cf2_cmdVLINETO, /* 7 */
+ cf2_cmdRRCURVETO, /* 8 */
+ cf2_cmdCLOSEPATH, /* 9 T1 only */
+ cf2_cmdCALLSUBR, /* 10 */
+ cf2_cmdRETURN, /* 11 */
+ cf2_cmdESC, /* 12 */
+ cf2_cmdHSBW, /* 13 T1 only */
+ cf2_cmdENDCHAR, /* 14 */
+ cf2_cmdVSINDEX, /* 15 */
+ cf2_cmdBLEND, /* 16 */
+ cf2_cmdRESERVED_17, /* 17 */
+ cf2_cmdHSTEMHM, /* 18 */
+ cf2_cmdHINTMASK, /* 19 */
+ cf2_cmdCNTRMASK, /* 20 */
+ cf2_cmdRMOVETO, /* 21 */
+ cf2_cmdHMOVETO, /* 22 */
+ cf2_cmdVSTEMHM, /* 23 */
+ cf2_cmdRCURVELINE, /* 24 */
+ cf2_cmdRLINECURVE, /* 25 */
+ cf2_cmdVVCURVETO, /* 26 */
+ cf2_cmdHHCURVETO, /* 27 */
+ cf2_cmdEXTENDEDNMBR, /* 28 */
+ cf2_cmdCALLGSUBR, /* 29 */
+ cf2_cmdVHCURVETO, /* 30 */
+ cf2_cmdHVCURVETO /* 31 */
+ };
+
+ enum
+ {
+ cf2_escDOTSECTION, /* 0 */
+ cf2_escVSTEM3, /* 1 T1 only */
+ cf2_escHSTEM3, /* 2 T1 only */
+ cf2_escAND, /* 3 */
+ cf2_escOR, /* 4 */
+ cf2_escNOT, /* 5 */
+ cf2_escSEAC, /* 6 T1 only */
+ cf2_escSBW, /* 7 T1 only */
+ cf2_escRESERVED_8, /* 8 */
+ cf2_escABS, /* 9 */
+ cf2_escADD, /* 10 like otherADD */
+ cf2_escSUB, /* 11 like otherSUB */
+ cf2_escDIV, /* 12 */
+ cf2_escRESERVED_13, /* 13 */
+ cf2_escNEG, /* 14 */
+ cf2_escEQ, /* 15 */
+ cf2_escCALLOTHERSUBR,/* 16 T1 only */
+ cf2_escPOP, /* 17 T1 only */
+ cf2_escDROP, /* 18 */
+ cf2_escRESERVED_19, /* 19 */
+ cf2_escPUT, /* 20 like otherPUT */
+ cf2_escGET, /* 21 like otherGET */
+ cf2_escIFELSE, /* 22 like otherIFELSE */
+ cf2_escRANDOM, /* 23 like otherRANDOM */
+ cf2_escMUL, /* 24 like otherMUL */
+ cf2_escRESERVED_25, /* 25 */
+ cf2_escSQRT, /* 26 */
+ cf2_escDUP, /* 27 like otherDUP */
+ cf2_escEXCH, /* 28 like otherEXCH */
+ cf2_escINDEX, /* 29 */
+ cf2_escROLL, /* 30 */
+ cf2_escRESERVED_31, /* 31 */
+ cf2_escRESERVED_32, /* 32 */
+ cf2_escSETCURRENTPT, /* 33 T1 only */
+ cf2_escHFLEX, /* 34 */
+ cf2_escFLEX, /* 35 */
+ cf2_escHFLEX1, /* 36 */
+ cf2_escFLEX1, /* 37 */
+ cf2_escRESERVED_38 /* 38 & all higher */
+ };
+
+
+ /* `stemHintArray' does not change once we start drawing the outline. */
+ static void
+ cf2_doStems( const CF2_Font font,
+ CF2_Stack opStack,
+ CF2_ArrStack stemHintArray,
+ CF2_Fixed* width,
+ FT_Bool* haveWidth,
+ CF2_Fixed hintOffset )
+ {
+ CF2_UInt i;
+ CF2_UInt count = cf2_stack_count( opStack );
+ FT_Bool hasWidthArg = (FT_Bool)( count & 1 );
+
+ /* variable accumulates delta values from operand stack */
+ CF2_Fixed position = hintOffset;
+
+ if ( font->isT1 && !font->decoder->flex_state && !*haveWidth )
+ FT_ERROR(( "cf2_doStems (Type 1 mode):"
+ " No width. Use hsbw/sbw as first op\n" ));
+
+ if ( !font->isT1 && hasWidthArg && !*haveWidth )
+ *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
+ cf2_getNominalWidthX( font->decoder ) );
+
+ if ( font->decoder->width_only )
+ goto exit;
+
+ for ( i = hasWidthArg ? 1 : 0; i < count; i += 2 )
+ {
+ /* construct a CF2_StemHint and push it onto the list */
+ CF2_StemHintRec stemhint;
+
+
+ stemhint.min =
+ position = ADD_INT32( position,
+ cf2_stack_getReal( opStack, i ) );
+ stemhint.max =
+ position = ADD_INT32( position,
+ cf2_stack_getReal( opStack, i + 1 ) );
+
+ stemhint.used = FALSE;
+ stemhint.maxDS =
+ stemhint.minDS = 0;
+
+ cf2_arrstack_push( stemHintArray, &stemhint ); /* defer error check */
+ }
+
+ cf2_stack_clear( opStack );
+
+ exit:
+ /* cf2_doStems must define a width (may be default) */
+ *haveWidth = TRUE;
+ }
+
+
+ static void
+ cf2_doFlex( CF2_Stack opStack,
+ CF2_Fixed* curX,
+ CF2_Fixed* curY,
+ CF2_GlyphPath glyphPath,
+ const FT_Bool* readFromStack,
+ FT_Bool doConditionalLastRead )
+ {
+ CF2_Fixed vals[14];
+ CF2_UInt idx;
+ FT_Bool isHFlex;
+ CF2_Int top, i, j;
+
+
+ vals[0] = *curX;
+ vals[1] = *curY;
+ idx = 0;
+ isHFlex = FT_BOOL( readFromStack[9] == FALSE );
+ top = isHFlex ? 9 : 10;
+
+ for ( i = 0; i < top; i++ )
+ {
+ vals[i + 2] = vals[i];
+ if ( readFromStack[i] )
+ vals[i + 2] = ADD_INT32( vals[i + 2], cf2_stack_getReal( opStack,
+ idx++ ) );
+ }
+
+ if ( isHFlex )
+ vals[9 + 2] = *curY;
+
+ if ( doConditionalLastRead )
+ {
+ FT_Bool lastIsX = (FT_Bool)(
+ cf2_fixedAbs( SUB_INT32( vals[10], *curX ) ) >
+ cf2_fixedAbs( SUB_INT32( vals[11], *curY ) ) );
+ CF2_Fixed lastVal = cf2_stack_getReal( opStack, idx );
+
+
+ if ( lastIsX )
+ {
+ vals[12] = ADD_INT32( vals[10], lastVal );
+ vals[13] = *curY;
+ }
+ else
+ {
+ vals[12] = *curX;
+ vals[13] = ADD_INT32( vals[11], lastVal );
+ }
+ }
+ else
+ {
+ if ( readFromStack[10] )
+ vals[12] = ADD_INT32( vals[10],
+ cf2_stack_getReal( opStack, idx++ ) );
+ else
+ vals[12] = *curX;
+
+ if ( readFromStack[11] )
+ vals[13] = ADD_INT32( vals[11],
+ cf2_stack_getReal( opStack, idx ) );
+ else
+ vals[13] = *curY;
+ }
+
+ for ( j = 0; j < 2; j++ )
+ cf2_glyphpath_curveTo( glyphPath, vals[j * 6 + 2],
+ vals[j * 6 + 3],
+ vals[j * 6 + 4],
+ vals[j * 6 + 5],
+ vals[j * 6 + 6],
+ vals[j * 6 + 7] );
+
+ cf2_stack_clear( opStack );
+
+ *curX = vals[12];
+ *curY = vals[13];
+ }
+
+
+ /* Blend numOperands on the stack, */
+ /* store results into the first numBlends values, */
+ /* then pop remaining arguments. */
+ static void
+ cf2_doBlend( const CFF_Blend blend,
+ CF2_Stack opStack,
+ CF2_UInt numBlends )
+ {
+ CF2_UInt delta;
+ CF2_UInt base;
+ CF2_UInt i, j;
+ CF2_UInt numOperands = (CF2_UInt)( numBlends * blend->lenBV );
+
+
+ base = cf2_stack_count( opStack ) - numOperands;
+ delta = base + numBlends;
+
+ for ( i = 0; i < numBlends; i++ )
+ {
+ const CF2_Fixed* weight = &blend->BV[1];
+
+ /* start with first term */
+ CF2_Fixed sum = cf2_stack_getReal( opStack, i + base );
+
+
+ for ( j = 1; j < blend->lenBV; j++ )
+ sum = ADD_INT32( sum,
+ FT_MulFix( *weight++,
+ cf2_stack_getReal( opStack,
+ delta++ ) ) );
+
+ /* store blended result */
+ cf2_stack_setReal( opStack, i + base, sum );
+ }
+
+ /* leave only `numBlends' results on stack */
+ cf2_stack_pop( opStack, numOperands - numBlends );
+ }
+
+
+ /*
+ * `error' is a shared error code used by many objects in this
+ * routine. Before the code continues from an error, it must check and
+ * record the error in `*error'. The idea is that this shared
+ * error code will record the first error encountered. If testing
+ * for an error anyway, the cost of `goto exit' is small, so we do it,
+ * even if continuing would be safe. In this case, `lastError' is
+ * set, so the testing and storing can be done in one place, at `exit'.
+ *
+ * Continuing after an error is intended for objects which do their own
+ * testing of `*error', e.g., array stack functions. This allows us to
+ * avoid an extra test after the call.
+ *
+ * Unimplemented opcodes are ignored.
+ *
+ */
+ FT_LOCAL_DEF( void )
+ cf2_interpT2CharString( CF2_Font font,
+ CF2_Buffer buf,
+ CF2_OutlineCallbacks callbacks,
+ const FT_Vector* translation,
+ FT_Bool doingSeac,
+ CF2_Fixed curX,
+ CF2_Fixed curY,
+ CF2_Fixed* width )
+ {
+ /* lastError is used for errors that are immediately tested */
+ FT_Error lastError = FT_Err_Ok;
+
+ /* pointer to parsed font object */
+ PS_Decoder* decoder = font->decoder;
+
+ FT_Error* error = &font->error;
+ FT_Memory memory = font->memory;
+
+ CF2_Fixed scaleY = font->innerTransform.d;
+ CF2_Fixed nominalWidthX = cf2_getNominalWidthX( decoder );
+
+ /* stuff for Type 1 */
+ FT_Int known_othersubr_result_cnt = 0;
+ FT_Bool large_int = FALSE;
+ FT_Bool initial_map_ready = FALSE;
+
+#define PS_STORAGE_SIZE 3
+ CF2_F16Dot16 results[PS_STORAGE_SIZE]; /* for othersubr results */
+ FT_Int result_cnt = 0;
+
+ /* save this for hinting seac accents */
+ CF2_Fixed hintOriginY = curY;
+
+ CF2_Stack opStack = NULL;
+ FT_UInt stackSize;
+ FT_Byte op1; /* first opcode byte */
+
+ CF2_F16Dot16 storage[CF2_STORAGE_SIZE]; /* for `put' and `get' */
+ CF2_F16Dot16 flexStore[6]; /* for Type 1 flex */
+
+ /* instruction limit; 20,000,000 matches Avalon */
+ FT_UInt32 instructionLimit = 20000000UL;
+
+ CF2_ArrStackRec subrStack;
+
+ FT_Bool haveWidth;
+ CF2_Buffer charstring = NULL;
+
+ CF2_Int charstringIndex = -1; /* initialize to empty */
+
+ /* TODO: placeholders for hint structures */
+
+ /* objects used for hinting */
+ CF2_ArrStackRec hStemHintArray;
+ CF2_ArrStackRec vStemHintArray;
+
+ CF2_HintMaskRec hintMask;
+ CF2_GlyphPathRec glyphPath;
+
+
+ FT_ZERO( &storage );
+ FT_ZERO( &results );
+ FT_ZERO( &flexStore );
+
+ /* initialize the remaining objects */
+ cf2_arrstack_init( &subrStack,
+ memory,
+ error,
+ sizeof ( CF2_BufferRec ) );
+ cf2_arrstack_init( &hStemHintArray,
+ memory,
+ error,
+ sizeof ( CF2_StemHintRec ) );
+ cf2_arrstack_init( &vStemHintArray,
+ memory,
+ error,
+ sizeof ( CF2_StemHintRec ) );
+
+ /* initialize CF2_StemHint arrays */
+ cf2_hintmask_init( &hintMask, error );
+
+ /* initialize path map to manage drawing operations */
+
+ /* Note: last 4 params are used to handle `MoveToPermissive', which */
+ /* may need to call `hintMap.Build' */
+ /* TODO: MoveToPermissive is gone; are these still needed? */
+ cf2_glyphpath_init( &glyphPath,
+ font,
+ callbacks,
+ scaleY,
+ /* hShift, */
+ &hStemHintArray,
+ &vStemHintArray,
+ &hintMask,
+ hintOriginY,
+ &font->blues,
+ translation );
+
+ /*
+ * Initialize state for width parsing. From the CFF Spec:
+ *
+ * The first stack-clearing operator, which must be one of hstem,
+ * hstemhm, vstem, vstemhm, cntrmask, hintmask, hmoveto, vmoveto,
+ * rmoveto, or endchar, takes an additional argument - the width (as
+ * described earlier), which may be expressed as zero or one numeric
+ * argument.
+ *
+ * What we implement here uses the first validly specified width, but
+ * does not detect errors for specifying more than one width.
+ *
+ * If one of the above operators occurs without explicitly specifying
+ * a width, we assume the default width.
+ *
+ * CFF2 charstrings always return the default width (0).
+ *
+ */
+ haveWidth = font->isCFF2 ? TRUE : FALSE;
+ *width = cf2_getDefaultWidthX( decoder );
+
+ /*
+ * Note: At this point, all pointers to resources must be NULL
+ * and all local objects must be initialized.
+ * There must be no branches to `exit:' above this point.
+ *
+ */
+
+ /* allocate an operand stack */
+ stackSize = font->isCFF2 ? cf2_getMaxstack( decoder )
+ : CF2_OPERAND_STACK_SIZE;
+ opStack = cf2_stack_init( memory, error, stackSize );
+
+ if ( !opStack )
+ {
+ lastError = FT_THROW( Out_Of_Memory );
+ goto exit;
+ }
+
+ /* initialize subroutine stack by placing top level charstring as */
+ /* first element (max depth plus one for the charstring) */
+ /* Note: Caller owns and must finalize the first charstring. */
+ /* Our copy of it does not change that requirement. */
+ cf2_arrstack_setCount( &subrStack, CF2_MAX_SUBR + 1 );
+
+ charstring = (CF2_Buffer)cf2_arrstack_getBuffer( &subrStack );
+ *charstring = *buf; /* structure copy */
+
+ charstringIndex = 0; /* entry is valid now */
+
+ /* catch errors so far */
+ if ( *error )
+ goto exit;
+
+ /* main interpreter loop */
+ while ( 1 )
+ {
+ if ( font->isT1 )
+ FT_ASSERT( known_othersubr_result_cnt == 0 ||
+ result_cnt == 0 );
+
+ if ( cf2_buf_isEnd( charstring ) )
+ {
+ /* If we've reached the end of the charstring, simulate a */
+ /* cf2_cmdRETURN or cf2_cmdENDCHAR. */
+ /* We do this for both CFF and CFF2. */
+ if ( charstringIndex )
+ op1 = cf2_cmdRETURN; /* end of buffer for subroutine */
+ else
+ op1 = cf2_cmdENDCHAR; /* end of buffer for top level charstring */
+ }
+ else
+ {
+ op1 = (FT_Byte)cf2_buf_readByte( charstring );
+
+ /* Explicit RETURN and ENDCHAR in CFF2 should be ignored. */
+ /* Note: Trace message will report 0 instead of 11 or 14. */
+ if ( ( op1 == cf2_cmdRETURN || op1 == cf2_cmdENDCHAR ) &&
+ font->isCFF2 )
+ op1 = cf2_cmdRESERVED_0;
+ }
+
+ if ( font->isT1 )
+ {
+ if ( !initial_map_ready &&
+ !( op1 == cf2_cmdHSTEM ||
+ op1 == cf2_cmdVSTEM ||
+ op1 == cf2_cmdHSBW ||
+ op1 == cf2_cmdCALLSUBR ||
+ op1 == cf2_cmdRETURN ||
+ op1 == cf2_cmdESC ||
+ op1 == cf2_cmdENDCHAR ||
+ op1 >= 32 /* Numbers */ ) )
+ {
+ /* Skip outline commands first time round. */
+ /* `endchar' will trigger initial hintmap build */
+ /* and rewind the charstring. */
+ cf2_stack_clear( opStack );
+ continue;
+ }
+
+ if ( result_cnt > 0 &&
+ !( op1 == cf2_cmdCALLSUBR ||
+ op1 == cf2_cmdRETURN ||
+ op1 == cf2_cmdESC ||
+ op1 >= 32 /* Numbers */ ) )
+ {
+ /* all operands have been transferred by previous pops */
+ result_cnt = 0;
+ }
+
+ if ( large_int && !( op1 >= 32 || op1 == cf2_escDIV ) )
+ {
+ FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
+ " no `div' after large integer\n" ));
+
+ large_int = FALSE;
+ }
+ }
+
+ /* check for errors once per loop */
+ if ( *error )
+ goto exit;
+
+ instructionLimit--;
+ if ( instructionLimit == 0 )
+ {
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit;
+ }
+
+ switch( op1 )
+ {
+ case cf2_cmdRESERVED_0:
+ case cf2_cmdRESERVED_2:
+ case cf2_cmdRESERVED_17:
+ /* we may get here if we have a prior error */
+ FT_TRACE4(( " unknown op (%d)\n", op1 ));
+ break;
+
+ case cf2_cmdVSINDEX:
+ FT_TRACE4(( " vsindex\n" ));
+
+ if ( !font->isCFF2 )
+ break; /* clear stack & ignore */
+
+ if ( font->blend.usedBV )
+ {
+ /* vsindex not allowed after blend */
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit;
+ }
+
+ {
+ FT_Int temp = cf2_stack_popInt( opStack );
+
+
+ if ( temp >= 0 )
+ font->vsindex = (FT_UInt)temp;
+ }
+ break;
+
+ case cf2_cmdBLEND:
+ {
+ FT_UInt numBlends;
+
+
+ FT_TRACE4(( " blend\n" ));
+
+ if ( !font->isCFF2 )
+ break; /* clear stack & ignore */
+
+ /* do we have a `blend' op in a non-variant font? */
+ if ( !font->blend.font )
+ {
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit;
+ }
+
+ /* check cached blend vector */
+ if ( font->cffload->blend_check_vector( &font->blend,
+ font->vsindex,
+ font->lenNDV,
+ font->NDV ) )
+ {
+ lastError = font->cffload->blend_build_vector( &font->blend,
+ font->vsindex,
+ font->lenNDV,
+ font->NDV );
+ if ( lastError )
+ goto exit;
+ }
+
+ /* do the blend */
+ numBlends = (FT_UInt)cf2_stack_popInt( opStack );
+ if ( numBlends > stackSize )
+ {
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit;
+ }
+
+ cf2_doBlend( &font->blend, opStack, numBlends );
+
+ font->blend.usedBV = TRUE;
+ }
+ continue; /* do not clear the stack */
+
+ case cf2_cmdHSTEMHM:
+ case cf2_cmdHSTEM:
+ FT_TRACE4(( op1 == cf2_cmdHSTEMHM ? " hstemhm\n" : " hstem\n" ));
+
+ if ( !font->isT1 )
+ {
+ /* never add hints after the mask is computed */
+ /* except if in Type 1 mode (no hintmask op) */
+ if ( cf2_hintmask_isValid( &hintMask ) )
+ {
+ FT_TRACE4(( "cf2_interpT2CharString:"
+ " invalid horizontal hint mask\n" ));
+ break;
+ }
+ }
+
+ /* add left-sidebearing correction in Type 1 mode */
+ cf2_doStems( font,
+ opStack,
+ &hStemHintArray,
+ width,
+ &haveWidth,
+ font->isT1 ? decoder->builder.left_bearing->y
+ : 0 );
+
+ if ( decoder->width_only )
+ goto exit;
+
+ break;
+
+ case cf2_cmdVSTEMHM:
+ case cf2_cmdVSTEM:
+ FT_TRACE4(( op1 == cf2_cmdVSTEMHM ? " vstemhm\n" : " vstem\n" ));
+
+ if ( !font->isT1 )
+ {
+ /* never add hints after the mask is computed */
+ /* except if in Type 1 mode (no hintmask op) */
+ if ( cf2_hintmask_isValid( &hintMask ) )
+ {
+ FT_TRACE4(( "cf2_interpT2CharString:"
+ " invalid vertical hint mask\n" ));
+ break;
+ }
+ }
+
+ /* add left-sidebearing correction in Type 1 mode */
+ cf2_doStems( font,
+ opStack,
+ &vStemHintArray,
+ width,
+ &haveWidth,
+ font->isT1 ? decoder->builder.left_bearing->x
+ : 0 );
+
+ if ( decoder->width_only )
+ goto exit;
+
+ break;
+
+ case cf2_cmdVMOVETO:
+ FT_TRACE4(( " vmoveto\n" ));
+
+ if ( font->isT1 && !decoder->flex_state && !haveWidth )
+ FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
+ " No width. Use hsbw/sbw as first op\n" ));
+
+ if ( cf2_stack_count( opStack ) > 1 && !haveWidth )
+ *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
+ nominalWidthX );
+
+ /* width is defined or default after this */
+ haveWidth = TRUE;
+
+ if ( decoder->width_only )
+ goto exit;
+
+ curY = ADD_INT32( curY, cf2_stack_popFixed( opStack ) );
+
+ if ( !decoder->flex_state )
+ cf2_glyphpath_moveTo( &glyphPath, curX, curY );
+
+ break;
+
+ case cf2_cmdRLINETO:
+ {
+ CF2_UInt idx;
+ CF2_UInt count = cf2_stack_count( opStack );
+
+
+ FT_TRACE4(( " rlineto\n" ));
+
+ for ( idx = 0; idx < count; idx += 2 )
+ {
+ curX = ADD_INT32( curX, cf2_stack_getReal( opStack,
+ idx + 0 ) );
+ curY = ADD_INT32( curY, cf2_stack_getReal( opStack,
+ idx + 1 ) );
+
+ cf2_glyphpath_lineTo( &glyphPath, curX, curY );
+ }
+
+ cf2_stack_clear( opStack );
+ }
+ continue; /* no need to clear stack again */
+
+ case cf2_cmdHLINETO:
+ case cf2_cmdVLINETO:
+ {
+ CF2_UInt idx;
+ CF2_UInt count = cf2_stack_count( opStack );
+
+ FT_Bool isX = FT_BOOL( op1 == cf2_cmdHLINETO );
+
+
+ FT_TRACE4(( isX ? " hlineto\n" : " vlineto\n" ));
+
+ for ( idx = 0; idx < count; idx++ )
+ {
+ CF2_Fixed v = cf2_stack_getReal( opStack, idx );
+
+
+ if ( isX )
+ curX = ADD_INT32( curX, v );
+ else
+ curY = ADD_INT32( curY, v );
+
+ isX = !isX;
+
+ cf2_glyphpath_lineTo( &glyphPath, curX, curY );
+ }
+
+ cf2_stack_clear( opStack );
+ }
+ continue;
+
+ case cf2_cmdRCURVELINE:
+ case cf2_cmdRRCURVETO:
+ {
+ CF2_UInt count = cf2_stack_count( opStack );
+ CF2_UInt idx = 0;
+
+
+ FT_TRACE4(( op1 == cf2_cmdRCURVELINE ? " rcurveline\n"
+ : " rrcurveto\n" ));
+
+ while ( idx + 6 <= count )
+ {
+ CF2_Fixed x1, y1, x2, y2, x3, y3;
+
+
+ x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX );
+ y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), curY );
+ x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), x1 );
+ y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y1 );
+ x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 );
+ y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 5 ), y2 );
+
+ cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
+
+ curX = x3;
+ curY = y3;
+ idx += 6;
+ }
+
+ if ( op1 == cf2_cmdRCURVELINE )
+ {
+ curX = ADD_INT32( curX, cf2_stack_getReal( opStack,
+ idx + 0 ) );
+ curY = ADD_INT32( curY, cf2_stack_getReal( opStack,
+ idx + 1 ) );
+
+ cf2_glyphpath_lineTo( &glyphPath, curX, curY );
+ }
+
+ cf2_stack_clear( opStack );
+ }
+ continue; /* no need to clear stack again */
+
+ case cf2_cmdCLOSEPATH:
+ if ( !font->isT1 )
+ FT_TRACE4(( " unknown op (%d)\n", op1 ));
+ else
+ {
+ FT_TRACE4(( " closepath" ));
+
+ /* if there is no path, `closepath' is a no-op */
+ ps_builder_close_contour( &decoder->builder );
+
+ haveWidth = TRUE;
+ }
+ break;
+
+ case cf2_cmdCALLGSUBR:
+ case cf2_cmdCALLSUBR:
+ {
+ CF2_Int subrNum;
+
+
+ FT_TRACE4(( op1 == cf2_cmdCALLGSUBR ? " callgsubr"
+ : " callsubr" ));
+
+ if ( ( !font->isT1 && charstringIndex > CF2_MAX_SUBR ) ||
+ ( font->isT1 && charstringIndex > T1_MAX_SUBRS_CALLS ) )
+ {
+ /* max subr plus one for charstring */
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit; /* overflow of stack */
+ }
+
+ /* push our current CFF charstring region on subrStack */
+ charstring = (CF2_Buffer)
+ cf2_arrstack_getPointer(
+ &subrStack,
+ (size_t)charstringIndex + 1 );
+
+ /* set up the new CFF region and pointer */
+ subrNum = cf2_stack_popInt( opStack );
+
+ if ( font->isT1 && decoder->locals_hash )
+ {
+ size_t* val = ft_hash_num_lookup( subrNum,
+ decoder->locals_hash );
+
+
+ if ( val )
+ subrNum = *val;
+ else
+ subrNum = -1;
+ }
+
+ switch ( op1 )
+ {
+ case cf2_cmdCALLGSUBR:
+ FT_TRACE4(( " (idx %d, entering level %d)\n",
+ subrNum + decoder->globals_bias,
+ charstringIndex + 1 ));
+
+ if ( cf2_initGlobalRegionBuffer( decoder,
+ subrNum,
+ charstring ) )
+ {
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit; /* subroutine lookup or stream error */
+ }
+ break;
+
+ default:
+ /* cf2_cmdCALLSUBR */
+ FT_TRACE4(( " (idx %d, entering level %d)\n",
+ subrNum + decoder->locals_bias,
+ charstringIndex + 1 ));
+
+ if ( cf2_initLocalRegionBuffer( decoder,
+ subrNum,
+ charstring ) )
+ {
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit; /* subroutine lookup or stream error */
+ }
+ }
+
+ charstringIndex += 1; /* entry is valid now */
+ }
+ continue; /* do not clear the stack */
+
+ case cf2_cmdRETURN:
+ FT_TRACE4(( " return (leaving level %d)\n", charstringIndex ));
+
+ if ( charstringIndex < 1 )
+ {
+ /* Note: cannot return from top charstring */
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit; /* underflow of stack */
+ }
+
+ /* restore position in previous charstring */
+ charstring = (CF2_Buffer)
+ cf2_arrstack_getPointer(
+ &subrStack,
+ (CF2_UInt)--charstringIndex );
+ continue; /* do not clear the stack */
+
+ case cf2_cmdESC:
+ {
+ FT_Byte op2 = (FT_Byte)cf2_buf_readByte( charstring );
+
+
+ /* first switch for 2-byte operators handles CFF2 */
+ /* and opcodes that are reserved for both CFF and CFF2 */
+ switch ( op2 )
+ {
+ case cf2_escHFLEX:
+ {
+ static const FT_Bool readFromStack[12] =
+ {
+ TRUE /* dx1 */, FALSE /* dy1 */,
+ TRUE /* dx2 */, TRUE /* dy2 */,
+ TRUE /* dx3 */, FALSE /* dy3 */,
+ TRUE /* dx4 */, FALSE /* dy4 */,
+ TRUE /* dx5 */, FALSE /* dy5 */,
+ TRUE /* dx6 */, FALSE /* dy6 */
+ };
+
+
+ FT_TRACE4(( " hflex\n" ));
+
+ cf2_doFlex( opStack,
+ &curX,
+ &curY,
+ &glyphPath,
+ readFromStack,
+ FALSE /* doConditionalLastRead */ );
+ }
+ continue;
+
+ case cf2_escFLEX:
+ {
+ static const FT_Bool readFromStack[12] =
+ {
+ TRUE /* dx1 */, TRUE /* dy1 */,
+ TRUE /* dx2 */, TRUE /* dy2 */,
+ TRUE /* dx3 */, TRUE /* dy3 */,
+ TRUE /* dx4 */, TRUE /* dy4 */,
+ TRUE /* dx5 */, TRUE /* dy5 */,
+ TRUE /* dx6 */, TRUE /* dy6 */
+ };
+
+
+ FT_TRACE4(( " flex\n" ));
+
+ cf2_doFlex( opStack,
+ &curX,
+ &curY,
+ &glyphPath,
+ readFromStack,
+ FALSE /* doConditionalLastRead */ );
+ }
+ break; /* TODO: why is this not a continue? */
+
+ case cf2_escHFLEX1:
+ {
+ static const FT_Bool readFromStack[12] =
+ {
+ TRUE /* dx1 */, TRUE /* dy1 */,
+ TRUE /* dx2 */, TRUE /* dy2 */,
+ TRUE /* dx3 */, FALSE /* dy3 */,
+ TRUE /* dx4 */, FALSE /* dy4 */,
+ TRUE /* dx5 */, TRUE /* dy5 */,
+ TRUE /* dx6 */, FALSE /* dy6 */
+ };
+
+
+ FT_TRACE4(( " hflex1\n" ));
+
+ cf2_doFlex( opStack,
+ &curX,
+ &curY,
+ &glyphPath,
+ readFromStack,
+ FALSE /* doConditionalLastRead */ );
+ }
+ continue;
+
+ case cf2_escFLEX1:
+ {
+ static const FT_Bool readFromStack[12] =
+ {
+ TRUE /* dx1 */, TRUE /* dy1 */,
+ TRUE /* dx2 */, TRUE /* dy2 */,
+ TRUE /* dx3 */, TRUE /* dy3 */,
+ TRUE /* dx4 */, TRUE /* dy4 */,
+ TRUE /* dx5 */, TRUE /* dy5 */,
+ FALSE /* dx6 */, FALSE /* dy6 */
+ };
+
+
+ FT_TRACE4(( " flex1\n" ));
+
+ cf2_doFlex( opStack,
+ &curX,
+ &curY,
+ &glyphPath,
+ readFromStack,
+ TRUE /* doConditionalLastRead */ );
+ }
+ continue;
+
+ /* these opcodes are always reserved */
+ case cf2_escRESERVED_8:
+ case cf2_escRESERVED_13:
+ case cf2_escRESERVED_19:
+ case cf2_escRESERVED_25:
+ case cf2_escRESERVED_31:
+ case cf2_escRESERVED_32:
+ FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
+ break;
+
+ default:
+ {
+ if ( font->isCFF2 || op2 >= cf2_escRESERVED_38 )
+ FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
+ else if ( font->isT1 && result_cnt > 0 && op2 != cf2_escPOP )
+ {
+ /* all operands have been transferred by previous pops */
+ result_cnt = 0;
+ }
+ else
+ {
+ /* second switch for 2-byte operators handles */
+ /* CFF and Type 1 */
+ switch ( op2 )
+ {
+
+ case cf2_escDOTSECTION:
+ /* something about `flip type of locking' -- ignore it */
+ FT_TRACE4(( " dotsection\n" ));
+
+ break;
+
+ case cf2_escVSTEM3:
+ case cf2_escHSTEM3:
+ /*
+ * Type 1: Type 2:
+ * x0 dx0 x1 dx1 x2 dx2 vstem3 x dx {dxa dxb}* vstem
+ * y0 dy0 y1 dy1 y2 dy2 hstem3 y dy {dya dyb}* hstem
+ * relative to lsb point relative to zero
+ *
+ */
+ {
+ if ( !font->isT1 )
+ FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
+ else
+ {
+ CF2_F16Dot16 v0, v1, v2;
+
+ FT_Bool isV = FT_BOOL( op2 == cf2_escVSTEM3 );
+
+
+ FT_TRACE4(( isV ? " vstem3\n"
+ : " hstem3\n" ));
+
+ FT_ASSERT( cf2_stack_count( opStack ) == 6 );
+
+ v0 = cf2_stack_getReal( opStack, 0 );
+ v1 = cf2_stack_getReal( opStack, 2 );
+ v2 = cf2_stack_getReal( opStack, 4 );
+
+ cf2_stack_setReal(
+ opStack, 2,
+ SUB_INT32( SUB_INT32( v1, v0 ),
+ cf2_stack_getReal( opStack, 1 ) ) );
+ cf2_stack_setReal(
+ opStack, 4,
+ SUB_INT32( SUB_INT32( v2, v1 ),
+ cf2_stack_getReal( opStack, 3 ) ) );
+
+ /* add left-sidebearing correction */
+ cf2_doStems( font,
+ opStack,
+ isV ? &vStemHintArray : &hStemHintArray,
+ width,
+ &haveWidth,
+ isV ? decoder->builder.left_bearing->x
+ : decoder->builder.left_bearing->y );
+
+ if ( decoder->width_only )
+ goto exit;
+ }
+ }
+ break;
+
+ case cf2_escAND:
+ {
+ CF2_F16Dot16 arg1;
+ CF2_F16Dot16 arg2;
+
+
+ FT_TRACE4(( " and\n" ));
+
+ arg2 = cf2_stack_popFixed( opStack );
+ arg1 = cf2_stack_popFixed( opStack );
+
+ cf2_stack_pushInt( opStack, arg1 && arg2 );
+ }
+ continue; /* do not clear the stack */
+
+ case cf2_escOR:
+ {
+ CF2_F16Dot16 arg1;
+ CF2_F16Dot16 arg2;
+
+
+ FT_TRACE4(( " or\n" ));
+
+ arg2 = cf2_stack_popFixed( opStack );
+ arg1 = cf2_stack_popFixed( opStack );
+
+ cf2_stack_pushInt( opStack, arg1 || arg2 );
+ }
+ continue; /* do not clear the stack */
+
+ case cf2_escNOT:
+ {
+ CF2_F16Dot16 arg;
+
+
+ FT_TRACE4(( " not\n" ));
+
+ arg = cf2_stack_popFixed( opStack );
+
+ cf2_stack_pushInt( opStack, !arg );
+ }
+ continue; /* do not clear the stack */
+
+ case cf2_escSEAC:
+ if ( !font->isT1 )
+ FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
+ else
+ {
+ FT_Error error2;
+ CF2_Int bchar_index, achar_index;
+ FT_Vector left_bearing, advance;
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+ T1_Face face = (T1_Face)decoder->builder.face;
+#endif
+ CF2_BufferRec component;
+ CF2_Fixed dummyWidth;
+
+ CF2_Int achar = cf2_stack_popInt( opStack );
+ CF2_Int bchar = cf2_stack_popInt( opStack );
+
+ FT_Pos ady = cf2_stack_popFixed ( opStack );
+ FT_Pos adx = cf2_stack_popFixed ( opStack );
+ FT_Pos asb = cf2_stack_popFixed ( opStack );
+
+
+ FT_TRACE4(( " seac\n" ));
+
+ if ( doingSeac )
+ {
+ FT_ERROR(( " nested seac\n" ));
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit; /* nested seac */
+ }
+
+ if ( decoder->builder.metrics_only )
+ {
+ FT_ERROR(( " unexpected seac\n" ));
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit; /* unexpected seac */
+ }
+
+ /* `glyph_names' is set to 0 for CID fonts which do */
+ /* not include an encoding. How can we deal with */
+ /* these? */
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+ if ( decoder->glyph_names == 0 &&
+ !face->root.internal->incremental_interface )
+#else
+ if ( decoder->glyph_names == 0 )
+#endif /* FT_CONFIG_OPTION_INCREMENTAL */
+ {
+ FT_ERROR((
+ "cf2_interpT2CharString: (Type 1 seac)"
+ " glyph names table not available in this font\n" ));
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit;
+ }
+
+ /* seac weirdness */
+ adx += decoder->builder.left_bearing->x;
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+ if ( face->root.internal->incremental_interface )
+ {
+ /* the caller must handle the font encoding also */
+ bchar_index = bchar;
+ achar_index = achar;
+ }
+ else
+#endif
+ {
+ bchar_index = t1_lookup_glyph_by_stdcharcode_ps(
+ decoder, bchar );
+ achar_index = t1_lookup_glyph_by_stdcharcode_ps(
+ decoder, achar );
+ }
+
+ if ( bchar_index < 0 || achar_index < 0 )
+ {
+ FT_ERROR((
+ "cf2_interpT2CharString: (Type 1 seac)"
+ " invalid seac character code arguments\n" ));
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit;
+ }
+
+ /* if we are trying to load a composite glyph, */
+ /* do not load the accent character and return */
+ /* the array of subglyphs. */
+ if ( decoder->builder.no_recurse )
+ {
+ FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph;
+ FT_GlyphLoader loader = glyph->internal->loader;
+ FT_SubGlyph subg;
+
+
+ /* reallocate subglyph array if necessary */
+ error2 = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );
+ if ( error2 )
+ {
+ lastError = error2; /* pass FreeType error through */
+ goto exit;
+ }
+
+ subg = loader->current.subglyphs;
+
+ /* subglyph 0 = base character */
+ subg->index = bchar_index;
+ subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
+ FT_SUBGLYPH_FLAG_USE_MY_METRICS;
+ subg->arg1 = 0;
+ subg->arg2 = 0;
+ subg++;
+
+ /* subglyph 1 = accent character */
+ subg->index = achar_index;
+ subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
+ subg->arg1 = (FT_Int)FIXED_TO_INT( adx - asb );
+ subg->arg2 = (FT_Int)FIXED_TO_INT( ady );
+
+ /* set up remaining glyph fields */
+ glyph->num_subglyphs = 2;
+ glyph->subglyphs = loader->base.subglyphs;
+ glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
+
+ loader->current.num_subglyphs = 2;
+
+ goto exit;
+ }
+
+ /* First load `bchar' in builder */
+ /* now load the unscaled outline */
+
+ /* prepare loader */
+ FT_GlyphLoader_Prepare( decoder->builder.loader );
+
+ error2 = cf2_getT1SeacComponent( decoder,
+ (FT_UInt)bchar_index,
+ &component );
+ if ( error2 )
+ {
+ lastError = error2; /* pass FreeType error through */
+ goto exit;
+ }
+ cf2_interpT2CharString( font,
+ &component,
+ callbacks,
+ translation,
+ TRUE,
+ 0,
+ 0,
+ &dummyWidth );
+ cf2_freeT1SeacComponent( decoder, &component );
+
+ /* save the left bearing and width of the base */
+ /* character as they will be erased by the next load */
+
+ left_bearing = *decoder->builder.left_bearing;
+ advance = *decoder->builder.advance;
+
+ decoder->builder.left_bearing->x = 0;
+ decoder->builder.left_bearing->y = 0;
+
+ /* Now load `achar' on top of */
+ /* the base outline */
+
+ error2 = cf2_getT1SeacComponent( decoder,
+ (FT_UInt)achar_index,
+ &component );
+ if ( error2 )
+ {
+ lastError = error2; /* pass FreeType error through */
+ goto exit;
+ }
+ cf2_interpT2CharString( font,
+ &component,
+ callbacks,
+ translation,
+ TRUE,
+ adx - asb,
+ ady,
+ &dummyWidth );
+ cf2_freeT1SeacComponent( decoder, &component );
+
+ /* restore the left side bearing and */
+ /* advance width of the base character */
+
+ *decoder->builder.left_bearing = left_bearing;
+ *decoder->builder.advance = advance;
+
+ goto exit;
+ }
+ break;
+
+ case cf2_escSBW:
+ if ( !font->isT1 )
+ FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
+ else
+ {
+ CF2_Fixed lsb_x, lsb_y;
+ PS_Builder* builder;
+
+
+ FT_TRACE4(( " sbw" ));
+
+ builder = &decoder->builder;
+
+ builder->advance->y = cf2_stack_popFixed( opStack );
+ builder->advance->x = cf2_stack_popFixed( opStack );
+
+ lsb_y = cf2_stack_popFixed( opStack );
+ lsb_x = cf2_stack_popFixed( opStack );
+
+ builder->left_bearing->x =
+ ADD_INT32( builder->left_bearing->x, lsb_x );
+ builder->left_bearing->y =
+ ADD_INT32( builder->left_bearing->y, lsb_y );
+
+ haveWidth = TRUE;
+
+ /* the `metrics_only' indicates that we only want */
+ /* to compute the glyph's metrics (lsb + advance */
+ /* width), not load the rest of it; so exit */
+ /* immediately */
+ if ( builder->metrics_only )
+ goto exit;
+
+ if ( initial_map_ready )
+ {
+ curX = ADD_INT32( curX, lsb_x );
+ curY = ADD_INT32( curY, lsb_y );
+ }
+ }
+ break;
+
+ case cf2_escABS:
+ {
+ CF2_F16Dot16 arg;
+
+
+ FT_TRACE4(( " abs\n" ));
+
+ arg = cf2_stack_popFixed( opStack );
+
+ if ( arg < -CF2_FIXED_MAX )
+ cf2_stack_pushFixed( opStack, CF2_FIXED_MAX );
+ else
+ cf2_stack_pushFixed( opStack, FT_ABS( arg ) );
+ }
+ continue; /* do not clear the stack */
+
+ case cf2_escADD:
+ {
+ CF2_F16Dot16 summand1;
+ CF2_F16Dot16 summand2;
+
+
+ FT_TRACE4(( " add\n" ));
+
+ summand2 = cf2_stack_popFixed( opStack );
+ summand1 = cf2_stack_popFixed( opStack );
+
+ cf2_stack_pushFixed( opStack,
+ ADD_INT32( summand1,
+ summand2 ) );
+ }
+ continue; /* do not clear the stack */
+
+ case cf2_escSUB:
+ {
+ CF2_F16Dot16 minuend;
+ CF2_F16Dot16 subtrahend;
+
+
+ FT_TRACE4(( " sub\n" ));
+
+ subtrahend = cf2_stack_popFixed( opStack );
+ minuend = cf2_stack_popFixed( opStack );
+
+ cf2_stack_pushFixed( opStack,
+ SUB_INT32( minuend, subtrahend ) );
+ }
+ continue; /* do not clear the stack */
+
+ case cf2_escDIV:
+ {
+ CF2_F16Dot16 dividend;
+ CF2_F16Dot16 divisor;
+
+
+ FT_TRACE4(( " div\n" ));
+
+ if ( font->isT1 && large_int )
+ {
+ divisor = (CF2_F16Dot16)cf2_stack_popInt( opStack );
+ dividend = (CF2_F16Dot16)cf2_stack_popInt( opStack );
+
+ large_int = FALSE;
+ }
+ else
+ {
+ divisor = cf2_stack_popFixed( opStack );
+ dividend = cf2_stack_popFixed( opStack );
+ }
+
+ cf2_stack_pushFixed( opStack,
+ FT_DivFix( dividend, divisor ) );
+
+ }
+ continue; /* do not clear the stack */
+
+ case cf2_escNEG:
+ {
+ CF2_F16Dot16 arg;
+
+
+ FT_TRACE4(( " neg\n" ));
+
+ arg = cf2_stack_popFixed( opStack );
+
+ if ( arg < -CF2_FIXED_MAX )
+ cf2_stack_pushFixed( opStack, CF2_FIXED_MAX );
+ else
+ cf2_stack_pushFixed( opStack, -arg );
+ }
+ continue; /* do not clear the stack */
+
+ case cf2_escEQ:
+ {
+ CF2_F16Dot16 arg1;
+ CF2_F16Dot16 arg2;
+
+
+ FT_TRACE4(( " eq\n" ));
+
+ arg2 = cf2_stack_popFixed( opStack );
+ arg1 = cf2_stack_popFixed( opStack );
+
+ cf2_stack_pushInt( opStack, arg1 == arg2 );
+ }
+ continue; /* do not clear the stack */
+
+ case cf2_escCALLOTHERSUBR:
+ if ( !font->isT1 )
+ FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
+ else
+ {
+ CF2_Int subr_no;
+ CF2_Int arg_cnt;
+ CF2_UInt count;
+ CF2_UInt opIdx = 0;
+
+
+ FT_TRACE4(( " callothersubr\n" ));
+
+ subr_no = cf2_stack_popInt( opStack );
+ arg_cnt = cf2_stack_popInt( opStack );
+
+ /*******************************************************/
+ /* */
+ /* remove all operands to callothersubr from the stack */
+ /* */
+ /* for handled othersubrs, where we know the number of */
+ /* arguments, we increase the stack by the value of */
+ /* known_othersubr_result_cnt */
+ /* */
+ /* for unhandled othersubrs the following pops adjust */
+ /* the stack pointer as necessary */
+
+ count = cf2_stack_count( opStack );
+ FT_ASSERT( (CF2_UInt)arg_cnt <= count );
+
+ opIdx += count - (CF2_UInt)arg_cnt;
+
+ known_othersubr_result_cnt = 0;
+ result_cnt = 0;
+
+ /* XXX TODO: The checks to `arg_count == <whatever>' */
+ /* might not be correct; an othersubr expects a */
+ /* certain number of operands on the PostScript stack */
+ /* (as opposed to the T1 stack) but it doesn't have to */
+ /* put them there by itself; previous othersubrs might */
+ /* have left the operands there if they were not */
+ /* followed by an appropriate number of pops */
+ /* */
+ /* On the other hand, Adobe Reader 7.0.8 for Linux */
+ /* doesn't accept a font that contains charstrings */
+ /* like */
+ /* */
+ /* 100 200 2 20 callothersubr */
+ /* 300 1 20 callothersubr pop */
+ /* */
+ /* Perhaps this is the reason why BuildCharArray */
+ /* exists. */
+
+ switch ( subr_no )
+ {
+ case 0: /* end flex feature */
+ if ( arg_cnt != 3 )
+ goto Unexpected_OtherSubr;
+
+ if ( initial_map_ready &&
+ ( !decoder->flex_state ||
+ decoder->num_flex_vectors != 7 ) )
+ {
+ FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
+ " unexpected flex end\n" ));
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit;
+ }
+
+ /* the two `results' are popped */
+ /* by the following setcurrentpoint */
+ cf2_stack_pushFixed( opStack, curX );
+ cf2_stack_pushFixed( opStack, curY );
+ known_othersubr_result_cnt = 2;
+ break;
+
+ case 1: /* start flex feature */
+ if ( arg_cnt != 0 )
+ goto Unexpected_OtherSubr;
+
+ if ( !initial_map_ready )
+ break;
+
+ if ( ps_builder_check_points( &decoder->builder, 6 ) )
+ goto exit;
+
+ decoder->flex_state = 1;
+ decoder->num_flex_vectors = 0;
+ break;
+
+ case 2: /* add flex vectors */
+ {
+ FT_Int idx;
+ FT_Int idx2;
+
+
+ if ( arg_cnt != 0 )
+ goto Unexpected_OtherSubr;
+
+ if ( !initial_map_ready )
+ break;
+
+ if ( !decoder->flex_state )
+ {
+ FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
+ " missing flex start\n" ));
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit;
+ }
+
+ /* note that we should not add a point for */
+ /* index 0; this will move our current position */
+ /* to the flex point without adding any point */
+ /* to the outline */
+ idx = decoder->num_flex_vectors++;
+ if ( idx > 0 && idx < 7 )
+ {
+ /* in malformed fonts it is possible to have */
+ /* other opcodes in the middle of a flex (which */
+ /* don't increase `num_flex_vectors'); we thus */
+ /* have to check whether we can add a point */
+
+ if ( ps_builder_check_points( &decoder->builder,
+ 1 ) )
+ {
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit;
+ }
+
+ /* map: 1->2 2->4 3->6 4->2 5->4 6->6 */
+ idx2 = ( idx > 3 ? idx - 3 : idx ) * 2;
+
+ flexStore[idx2 - 2] = curX;
+ flexStore[idx2 - 1] = curY;
+
+ if ( idx == 3 || idx == 6 )
+ cf2_glyphpath_curveTo( &glyphPath,
+ flexStore[0],
+ flexStore[1],
+ flexStore[2],
+ flexStore[3],
+ flexStore[4],
+ flexStore[5] );
+ }
+ }
+ break;
+
+ case 3: /* change hints */
+ if ( arg_cnt != 1 )
+ goto Unexpected_OtherSubr;
+
+ if ( initial_map_ready )
+ {
+ /* do not clear hints if initial hintmap */
+ /* is not ready - we need to collate all */
+ cf2_arrstack_clear( &vStemHintArray );
+ cf2_arrstack_clear( &hStemHintArray );
+
+ cf2_hintmask_init( &hintMask, error );
+ hintMask.isValid = FALSE;
+ hintMask.isNew = TRUE;
+ }
+
+ known_othersubr_result_cnt = 1;
+ break;
+
+ case 12:
+ case 13:
+ /* counter control hints, clear stack */
+ cf2_stack_clear( opStack );
+ break;
+
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 18: /* multiple masters */
+ {
+ PS_Blend blend = decoder->blend;
+ FT_UInt num_points, nn, mm;
+ CF2_UInt delta;
+ CF2_UInt values;
+
+
+ if ( !blend )
+ {
+ FT_ERROR((
+ "cf2_interpT2CharString:"
+ " unexpected multiple masters operator\n" ));
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit;
+ }
+
+ num_points = (FT_UInt)subr_no - 13 +
+ ( subr_no == 18 );
+ if ( arg_cnt != (FT_Int)( num_points *
+ blend->num_designs ) )
+ {
+ FT_ERROR((
+ "cf2_interpT2CharString:"
+ " incorrect number of multiple masters arguments\n" ));
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit;
+ }
+
+ /* We want to compute */
+ /* */
+ /* a0*w0 + a1*w1 + ... + ak*wk */
+ /* */
+ /* but we only have a0, a1-a0, a2-a0, ..., ak-a0. */
+ /* */
+ /* However, given that w0 + w1 + ... + wk == 1, we */
+ /* can rewrite it easily as */
+ /* */
+ /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + ... + (ak-a0)*wk */
+ /* */
+ /* where k == num_designs-1. */
+ /* */
+ /* I guess that's why it's written in this `compact' */
+ /* form. */
+ /* */
+ delta = opIdx + num_points;
+ values = opIdx;
+ for ( nn = 0; nn < num_points; nn++ )
+ {
+ CF2_Fixed tmp = cf2_stack_getReal( opStack,
+ values );
+
+
+ for ( mm = 1; mm < blend->num_designs; mm++ )
+ tmp = ADD_INT32( tmp,
+ FT_MulFix(
+ cf2_stack_getReal( opStack,
+ delta++ ),
+ blend->weight_vector[mm] ) );
+
+ cf2_stack_setReal( opStack, values++, tmp );
+ }
+ cf2_stack_pop( opStack,
+ (CF2_UInt)arg_cnt - num_points );
+
+ known_othersubr_result_cnt = (FT_Int)num_points;
+ break;
+ }
+
+ case 19:
+ /* <idx> 1 19 callothersubr */
+ /* ==> replace elements starting from index */
+ /* cvi( <idx> ) of BuildCharArray with */
+ /* WeightVector */
+ {
+ FT_Int idx;
+ PS_Blend blend = decoder->blend;
+
+
+ if ( arg_cnt != 1 || !blend )
+ goto Unexpected_OtherSubr;
+
+ idx = cf2_stack_popInt( opStack );
+
+ if ( idx < 0 ||
+ (FT_UInt)idx + blend->num_designs >
+ decoder->len_buildchar )
+ goto Unexpected_OtherSubr;
+
+ ft_memcpy( &decoder->buildchar[idx],
+ blend->weight_vector,
+ blend->num_designs *
+ sizeof ( blend->weight_vector[0] ) );
+ }
+ break;
+
+ case 20:
+ /* <arg1> <arg2> 2 20 callothersubr pop */
+ /* ==> push <arg1> + <arg2> onto T1 stack */
+ {
+ CF2_F16Dot16 summand1;
+ CF2_F16Dot16 summand2;
+
+
+ if ( arg_cnt != 2 )
+ goto Unexpected_OtherSubr;
+
+ summand2 = cf2_stack_popFixed( opStack );
+ summand1 = cf2_stack_popFixed( opStack );
+
+ cf2_stack_pushFixed( opStack,
+ ADD_INT32( summand1,
+ summand2 ) );
+ known_othersubr_result_cnt = 1;
+ }
+ break;
+
+ case 21:
+ /* <arg1> <arg2> 2 21 callothersubr pop */
+ /* ==> push <arg1> - <arg2> onto T1 stack */
+ {
+ CF2_F16Dot16 minuend;
+ CF2_F16Dot16 subtrahend;
+
+
+ if ( arg_cnt != 2 )
+ goto Unexpected_OtherSubr;
+
+ subtrahend = cf2_stack_popFixed( opStack );
+ minuend = cf2_stack_popFixed( opStack );
+
+ cf2_stack_pushFixed( opStack,
+ SUB_INT32( minuend,
+ subtrahend ) );
+ known_othersubr_result_cnt = 1;
+ }
+ break;
+
+ case 22:
+ /* <arg1> <arg2> 2 22 callothersubr pop */
+ /* ==> push <arg1> * <arg2> onto T1 stack */
+ {
+ CF2_F16Dot16 factor1;
+ CF2_F16Dot16 factor2;
+
+
+ if ( arg_cnt != 2 )
+ goto Unexpected_OtherSubr;
+
+ factor2 = cf2_stack_popFixed( opStack );
+ factor1 = cf2_stack_popFixed( opStack );
+
+ cf2_stack_pushFixed( opStack,
+ FT_MulFix( factor1, factor2 ) );
+ known_othersubr_result_cnt = 1;
+ }
+ break;
+
+ case 23:
+ /* <arg1> <arg2> 2 23 callothersubr pop */
+ /* ==> push <arg1> / <arg2> onto T1 stack */
+ {
+ CF2_F16Dot16 dividend;
+ CF2_F16Dot16 divisor;
+
+
+ if ( arg_cnt != 2 )
+ goto Unexpected_OtherSubr;
+
+ divisor = cf2_stack_popFixed( opStack );
+ dividend = cf2_stack_popFixed( opStack );
+
+ if ( divisor == 0 )
+ goto Unexpected_OtherSubr;
+
+ cf2_stack_pushFixed( opStack,
+ FT_DivFix( dividend,
+ divisor ) );
+ known_othersubr_result_cnt = 1;
+ }
+ break;
+
+ case 24:
+ /* <val> <idx> 2 24 callothersubr */
+ /* ==> set BuildCharArray[cvi( <idx> )] = <val> */
+ {
+ CF2_Int idx;
+ PS_Blend blend = decoder->blend;
+
+
+ if ( arg_cnt != 2 || !blend )
+ goto Unexpected_OtherSubr;
+
+ idx = cf2_stack_popInt( opStack );
+
+ if ( idx < 0 ||
+ (FT_UInt)idx >= decoder->len_buildchar )
+ goto Unexpected_OtherSubr;
+
+ decoder->buildchar[idx] =
+ cf2_stack_popFixed( opStack );
+ }
+ break;
+
+ case 25:
+ /* <idx> 1 25 callothersubr pop */
+ /* ==> push BuildCharArray[cvi( idx )] */
+ /* onto T1 stack */
+ {
+ CF2_Int idx;
+ PS_Blend blend = decoder->blend;
+
+
+ if ( arg_cnt != 1 || !blend )
+ goto Unexpected_OtherSubr;
+
+ idx = cf2_stack_popInt( opStack );
+
+ if ( idx < 0 ||
+ (FT_UInt)idx >= decoder->len_buildchar )
+ goto Unexpected_OtherSubr;
+
+ cf2_stack_pushFixed( opStack,
+ decoder->buildchar[idx] );
+ known_othersubr_result_cnt = 1;
+ }
+ break;
+
+#if 0
+ case 26:
+ /* <val> mark <idx> */
+ /* ==> set BuildCharArray[cvi( <idx> )] = <val>, */
+ /* leave mark on T1 stack */
+ /* <val> <idx> */
+ /* ==> set BuildCharArray[cvi( <idx> )] = <val> */
+ XXX which routine has left its mark on the
+ XXX (PostScript) stack?;
+ break;
+#endif
+
+ case 27:
+ /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */
+ /* ==> push <res1> onto T1 stack if <val1> <= <val2>, */
+ /* otherwise push <res2> */
+ {
+ CF2_F16Dot16 arg1;
+ CF2_F16Dot16 arg2;
+ CF2_F16Dot16 cond1;
+ CF2_F16Dot16 cond2;
+
+
+ if ( arg_cnt != 4 )
+ goto Unexpected_OtherSubr;
+
+ cond2 = cf2_stack_popFixed( opStack );
+ cond1 = cf2_stack_popFixed( opStack );
+ arg2 = cf2_stack_popFixed( opStack );
+ arg1 = cf2_stack_popFixed( opStack );
+
+ cf2_stack_pushFixed( opStack,
+ cond1 <= cond2 ? arg1 : arg2 );
+ known_othersubr_result_cnt = 1;
+ }
+ break;
+
+ case 28:
+ /* 0 28 callothersubr pop */
+ /* ==> push random value from interval [0, 1) */
+ /* onto stack */
+ {
+ CF2_F16Dot16 r;
+
+
+ if ( arg_cnt != 0 )
+ goto Unexpected_OtherSubr;
+
+ /* only use the lower 16 bits of `random' */
+ /* to generate a number in the range (0;1] */
+ r = (CF2_F16Dot16)
+ ( ( decoder->current_subfont->random & 0xFFFF ) + 1 );
+
+ decoder->current_subfont->random =
+ cff_random( decoder->current_subfont->random );
+
+ cf2_stack_pushFixed( opStack, r );
+ known_othersubr_result_cnt = 1;
+ }
+ break;
+
+ default:
+ if ( arg_cnt >= 0 && subr_no >= 0 )
+ {
+ FT_Int i;
+
+
+ FT_ERROR((
+ "cf2_interpT2CharString (Type 1 mode):"
+ " unknown othersubr [%d %d], wish me luck\n",
+ arg_cnt, subr_no ));
+
+ /* store the unused args */
+ /* for this unhandled OtherSubr */
+
+ if ( arg_cnt > PS_STORAGE_SIZE )
+ arg_cnt = PS_STORAGE_SIZE;
+ result_cnt = arg_cnt;
+
+ for ( i = 1; i <= arg_cnt; i++ )
+ results[result_cnt - i] =
+ cf2_stack_popFixed( opStack );
+
+ break;
+ }
+ /* fall through */
+
+ Unexpected_OtherSubr:
+ FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
+ " invalid othersubr [%d %d]\n",
+ arg_cnt, subr_no ));
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit;
+ }
+ }
+ continue; /* do not clear the stack */
+
+ case cf2_escPOP:
+ if ( !font->isT1 )
+ FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
+ else
+ {
+ FT_TRACE4(( " pop" ));
+
+ if ( known_othersubr_result_cnt > 0 )
+ {
+ known_othersubr_result_cnt--;
+ /* ignore, we pushed the operands ourselves */
+ continue;
+ }
+
+ if ( result_cnt == 0 )
+ {
+ FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
+ " no more operands for othersubr\n" ));
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit;
+ }
+
+ result_cnt--;
+ cf2_stack_pushFixed( opStack, results[result_cnt] );
+ }
+ continue; /* do not clear the stack */
+
+ case cf2_escDROP:
+ FT_TRACE4(( " drop\n" ));
+
+ (void)cf2_stack_popFixed( opStack );
+ continue; /* do not clear the stack */
+
+ case cf2_escPUT:
+ {
+ CF2_F16Dot16 val;
+ CF2_Int idx;
+
+
+ FT_TRACE4(( " put\n" ));
+
+ idx = cf2_stack_popInt( opStack );
+ val = cf2_stack_popFixed( opStack );
+
+ if ( idx >= 0 && idx < CF2_STORAGE_SIZE )
+ storage[idx] = val;
+ }
+ continue; /* do not clear the stack */
+
+ case cf2_escGET:
+ {
+ CF2_Int idx;
+
+
+ FT_TRACE4(( " get\n" ));
+
+ idx = cf2_stack_popInt( opStack );
+
+ if ( idx >= 0 && idx < CF2_STORAGE_SIZE )
+ cf2_stack_pushFixed( opStack, storage[idx] );
+ }
+ continue; /* do not clear the stack */
+
+ case cf2_escIFELSE:
+ {
+ CF2_F16Dot16 arg1;
+ CF2_F16Dot16 arg2;
+ CF2_F16Dot16 cond1;
+ CF2_F16Dot16 cond2;
+
+
+ FT_TRACE4(( " ifelse\n" ));
+
+ cond2 = cf2_stack_popFixed( opStack );
+ cond1 = cf2_stack_popFixed( opStack );
+ arg2 = cf2_stack_popFixed( opStack );
+ arg1 = cf2_stack_popFixed( opStack );
+
+ cf2_stack_pushFixed( opStack,
+ cond1 <= cond2 ? arg1 : arg2 );
+ }
+ continue; /* do not clear the stack */
+
+ case cf2_escRANDOM: /* in spec */
+ {
+ CF2_F16Dot16 r;
+
+
+ FT_TRACE4(( " random\n" ));
+
+ /* only use the lower 16 bits of `random' */
+ /* to generate a number in the range (0;1] */
+ r = (CF2_F16Dot16)
+ ( ( decoder->current_subfont->random & 0xFFFF ) + 1 );
+
+ decoder->current_subfont->random =
+ cff_random( decoder->current_subfont->random );
+
+ cf2_stack_pushFixed( opStack, r );
+ }
+ continue; /* do not clear the stack */
+
+ case cf2_escMUL:
+ {
+ CF2_F16Dot16 factor1;
+ CF2_F16Dot16 factor2;
+
+
+ FT_TRACE4(( " mul\n" ));
+
+ factor2 = cf2_stack_popFixed( opStack );
+ factor1 = cf2_stack_popFixed( opStack );
+
+ cf2_stack_pushFixed( opStack,
+ FT_MulFix( factor1, factor2 ) );
+ }
+ continue; /* do not clear the stack */
+
+ case cf2_escSQRT:
+ {
+ CF2_F16Dot16 arg;
+
+
+ FT_TRACE4(( " sqrt\n" ));
+
+ arg = cf2_stack_popFixed( opStack );
+ if ( arg > 0 )
+ {
+ /* use a start value that doesn't make */
+ /* the algorithm's addition overflow */
+ FT_Fixed root = arg < 10 ? arg : arg >> 1;
+ FT_Fixed new_root;
+
+
+ /* Babylonian method */
+ for (;;)
+ {
+ new_root = ( root + FT_DivFix( arg, root ) + 1 ) >> 1;
+ if ( new_root == root )
+ break;
+ root = new_root;
+ }
+ arg = new_root;
+ }
+ else
+ arg = 0;
+
+ cf2_stack_pushFixed( opStack, arg );
+ }
+ continue; /* do not clear the stack */
+
+ case cf2_escDUP:
+ {
+ CF2_F16Dot16 arg;
+
+
+ FT_TRACE4(( " dup\n" ));
+
+ arg = cf2_stack_popFixed( opStack );
+
+ cf2_stack_pushFixed( opStack, arg );
+ cf2_stack_pushFixed( opStack, arg );
+ }
+ continue; /* do not clear the stack */
+
+ case cf2_escEXCH:
+ {
+ CF2_F16Dot16 arg1;
+ CF2_F16Dot16 arg2;
+
+
+ FT_TRACE4(( " exch\n" ));
+
+ arg2 = cf2_stack_popFixed( opStack );
+ arg1 = cf2_stack_popFixed( opStack );
+
+ cf2_stack_pushFixed( opStack, arg2 );
+ cf2_stack_pushFixed( opStack, arg1 );
+ }
+ continue; /* do not clear the stack */
+
+ case cf2_escINDEX:
+ {
+ CF2_Int idx;
+ CF2_UInt size;
+
+
+ FT_TRACE4(( " index\n" ));
+
+ idx = cf2_stack_popInt( opStack );
+ size = cf2_stack_count( opStack );
+
+ if ( size > 0 )
+ {
+ /* for `cf2_stack_getReal', */
+ /* index 0 is bottom of stack */
+ CF2_UInt gr_idx;
+
+
+ if ( idx < 0 )
+ gr_idx = size - 1;
+ else if ( (CF2_UInt)idx >= size )
+ gr_idx = 0;
+ else
+ gr_idx = size - 1 - (CF2_UInt)idx;
+
+ cf2_stack_pushFixed( opStack,
+ cf2_stack_getReal( opStack,
+ gr_idx ) );
+ }
+ }
+ continue; /* do not clear the stack */
+
+ case cf2_escROLL:
+ {
+ CF2_Int idx;
+ CF2_Int count;
+
+
+ FT_TRACE4(( " roll\n" ));
+
+ idx = cf2_stack_popInt( opStack );
+ count = cf2_stack_popInt( opStack );
+
+ cf2_stack_roll( opStack, count, idx );
+ }
+ continue; /* do not clear the stack */
+
+ case cf2_escSETCURRENTPT:
+ if ( !font->isT1 )
+ FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
+ else
+ {
+ FT_TRACE4(( " setcurrentpoint" ));
+
+ if ( !initial_map_ready )
+ break;
+
+ /* From the T1 specification, section 6.4: */
+ /* */
+ /* The setcurrentpoint command is used only in */
+ /* conjunction with results from OtherSubrs */
+ /* procedures. */
+
+ /* known_othersubr_result_cnt != 0 is already handled */
+ /* above. */
+
+ /* Note, however, that both Ghostscript and Adobe */
+ /* Distiller handle this situation by silently */
+ /* ignoring the inappropriate `setcurrentpoint' */
+ /* instruction. So we do the same. */
+#if 0
+
+ if ( decoder->flex_state != 1 )
+ {
+ FT_ERROR(( "cf2_interpT2CharString:"
+ " unexpected `setcurrentpoint'\n" ));
+ goto Syntax_Error;
+ }
+ else
+ ...
+#endif
+
+ curY = cf2_stack_popFixed( opStack );
+ curX = cf2_stack_popFixed( opStack );
+
+ decoder->flex_state = 0;
+ }
+ break;
+
+ } /* end of 2nd switch checking op2 */
+ }
+ }
+ } /* end of 1st switch checking op2 */
+ } /* case cf2_cmdESC */
+
+ break;
+
+ case cf2_cmdHSBW:
+ if ( !font->isT1 )
+ FT_TRACE4(( " unknown op (%d)\n", op1 ));
+ else
+ {
+ CF2_Fixed lsb_x;
+ PS_Builder* builder;
+
+
+ FT_TRACE4(( " hsbw" ));
+
+ builder = &decoder->builder;
+
+ builder->advance->x = cf2_stack_popFixed( opStack );
+ builder->advance->y = 0;
+
+ lsb_x = cf2_stack_popFixed( opStack );
+
+ builder->left_bearing->x = ADD_INT32( builder->left_bearing->x,
+ lsb_x );
+
+ haveWidth = TRUE;
+
+ /* the `metrics_only' indicates that we only want to compute */
+ /* the glyph's metrics (lsb + advance width), not load the */
+ /* rest of it; so exit immediately */
+ if ( builder->metrics_only )
+ goto exit;
+
+ if ( initial_map_ready )
+ curX = ADD_INT32( curX, lsb_x );
+ }
+ break;
+
+ case cf2_cmdENDCHAR:
+ FT_TRACE4(( " endchar\n" ));
+
+ if ( font->isT1 && !initial_map_ready )
+ {
+ FT_TRACE5(( "cf2_interpT2CharString (Type 1 mode): "
+ "Build initial hintmap, rewinding...\n" ));
+
+ /* trigger initial hintmap build */
+ cf2_glyphpath_moveTo( &glyphPath, curX, curY );
+
+ initial_map_ready = TRUE;
+
+ /* change hints routine - clear for rewind */
+ cf2_arrstack_clear( &vStemHintArray );
+ cf2_arrstack_clear( &hStemHintArray );
+
+ cf2_hintmask_init( &hintMask, error );
+ hintMask.isValid = FALSE;
+ hintMask.isNew = TRUE;
+
+ /* rewind charstring */
+ /* some charstrings use endchar from a final subroutine call */
+ /* without returning, detect these and exit to the top level */
+ /* charstring */
+ while ( charstringIndex > 0 )
+ {
+ FT_TRACE4(( " return (leaving level %d)\n", charstringIndex ));
+
+ /* restore position in previous charstring */
+ charstring = (CF2_Buffer)
+ cf2_arrstack_getPointer(
+ &subrStack,
+ (CF2_UInt)--charstringIndex );
+ }
+ charstring->ptr = charstring->start;
+
+ break;
+ }
+
+ if ( cf2_stack_count( opStack ) == 1 ||
+ cf2_stack_count( opStack ) == 5 )
+ {
+ if ( !haveWidth )
+ *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
+ nominalWidthX );
+ }
+
+ /* width is defined or default after this */
+ haveWidth = TRUE;
+
+ if ( decoder->width_only )
+ goto exit;
+
+ /* close path if still open */
+ cf2_glyphpath_closeOpenPath( &glyphPath );
+
+ /* disable seac for CFF2 and Type1 */
+ /* (charstring ending with args on stack) */
+ if ( !font->isCFF2 && !font->isT1 && cf2_stack_count( opStack ) > 1 )
+ {
+ /* must be either 4 or 5 -- */
+ /* this is a (deprecated) implied `seac' operator */
+
+ CF2_Int achar;
+ CF2_Int bchar;
+ CF2_BufferRec component;
+ CF2_Fixed dummyWidth; /* ignore component width */
+ FT_Error error2;
+
+
+ if ( doingSeac )
+ {
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit; /* nested seac */
+ }
+
+ achar = cf2_stack_popInt( opStack );
+ bchar = cf2_stack_popInt( opStack );
+
+ curY = cf2_stack_popFixed( opStack );
+ curX = cf2_stack_popFixed( opStack );
+
+ error2 = cf2_getSeacComponent( decoder, achar, &component );
+ if ( error2 )
+ {
+ lastError = error2; /* pass FreeType error through */
+ goto exit;
+ }
+ cf2_interpT2CharString( font,
+ &component,
+ callbacks,
+ translation,
+ TRUE,
+ curX,
+ curY,
+ &dummyWidth );
+ cf2_freeSeacComponent( decoder, &component );
+
+ error2 = cf2_getSeacComponent( decoder, bchar, &component );
+ if ( error2 )
+ {
+ lastError = error2; /* pass FreeType error through */
+ goto exit;
+ }
+ cf2_interpT2CharString( font,
+ &component,
+ callbacks,
+ translation,
+ TRUE,
+ 0,
+ 0,
+ &dummyWidth );
+ cf2_freeSeacComponent( decoder, &component );
+ }
+ goto exit;
+
+ case cf2_cmdCNTRMASK:
+ case cf2_cmdHINTMASK:
+ /* the final \n in the tracing message gets added in */
+ /* `cf2_hintmask_read' (which also traces the mask bytes) */
+ FT_TRACE4(( op1 == cf2_cmdCNTRMASK ? " cntrmask" : " hintmask" ));
+
+ /* never add hints after the mask is computed */
+ if ( cf2_stack_count( opStack ) > 1 &&
+ cf2_hintmask_isValid( &hintMask ) )
+ {
+ FT_TRACE4(( "cf2_interpT2CharString: invalid hint mask\n" ));
+ break;
+ }
+
+ /* if there are arguments on the stack, there this is an */
+ /* implied cf2_cmdVSTEMHM */
+ cf2_doStems( font,
+ opStack,
+ &vStemHintArray,
+ width,
+ &haveWidth,
+ 0 );
+
+ if ( decoder->width_only )
+ goto exit;
+
+ if ( op1 == cf2_cmdHINTMASK )
+ {
+ /* consume the hint mask bytes which follow the operator */
+ cf2_hintmask_read( &hintMask,
+ charstring,
+ cf2_arrstack_size( &hStemHintArray ) +
+ cf2_arrstack_size( &vStemHintArray ) );
+ }
+ else
+ {
+ /*
+ * Consume the counter mask bytes which follow the operator:
+ * Build a temporary hint map, just to place and lock those
+ * stems participating in the counter mask. These are most
+ * likely the dominant hstems, and are grouped together in a
+ * few counter groups, not necessarily in correspondence
+ * with the hint groups. This reduces the chances of
+ * conflicts between hstems that are initially placed in
+ * separate hint groups and then brought together. The
+ * positions are copied back to `hStemHintArray', so we can
+ * discard `counterMask' and `counterHintMap'.
+ *
+ */
+ CF2_HintMapRec counterHintMap;
+ CF2_HintMaskRec counterMask;
+
+
+ cf2_hintmap_init( &counterHintMap,
+ font,
+ &glyphPath.initialHintMap,
+ &glyphPath.hintMoves,
+ scaleY );
+ cf2_hintmask_init( &counterMask, error );
+
+ cf2_hintmask_read( &counterMask,
+ charstring,
+ cf2_arrstack_size( &hStemHintArray ) +
+ cf2_arrstack_size( &vStemHintArray ) );
+ cf2_hintmap_build( &counterHintMap,
+ &hStemHintArray,
+ &vStemHintArray,
+ &counterMask,
+ 0,
+ FALSE );
+ }
+ break;
+
+ case cf2_cmdRMOVETO:
+ FT_TRACE4(( " rmoveto\n" ));
+
+ if ( font->isT1 && !decoder->flex_state && !haveWidth )
+ FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
+ " No width. Use hsbw/sbw as first op\n" ));
+
+ if ( cf2_stack_count( opStack ) > 2 && !haveWidth )
+ *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
+ nominalWidthX );
+
+ /* width is defined or default after this */
+ haveWidth = TRUE;
+
+ if ( decoder->width_only )
+ goto exit;
+
+ curY = ADD_INT32( curY, cf2_stack_popFixed( opStack ) );
+ curX = ADD_INT32( curX, cf2_stack_popFixed( opStack ) );
+
+ if ( !decoder->flex_state )
+ cf2_glyphpath_moveTo( &glyphPath, curX, curY );
+
+ break;
+
+ case cf2_cmdHMOVETO:
+ FT_TRACE4(( " hmoveto\n" ));
+
+ if ( font->isT1 && !decoder->flex_state && !haveWidth )
+ FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
+ " No width. Use hsbw/sbw as first op\n" ));
+
+ if ( cf2_stack_count( opStack ) > 1 && !haveWidth )
+ *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
+ nominalWidthX );
+
+ /* width is defined or default after this */
+ haveWidth = TRUE;
+
+ if ( decoder->width_only )
+ goto exit;
+
+ curX = ADD_INT32( curX, cf2_stack_popFixed( opStack ) );
+
+ if ( !decoder->flex_state )
+ cf2_glyphpath_moveTo( &glyphPath, curX, curY );
+
+ break;
+
+ case cf2_cmdRLINECURVE:
+ {
+ CF2_UInt count = cf2_stack_count( opStack );
+ CF2_UInt idx = 0;
+
+
+ FT_TRACE4(( " rlinecurve\n" ));
+
+ while ( idx + 6 < count )
+ {
+ curX = ADD_INT32( curX, cf2_stack_getReal( opStack,
+ idx + 0 ) );
+ curY = ADD_INT32( curY, cf2_stack_getReal( opStack,
+ idx + 1 ) );
+
+ cf2_glyphpath_lineTo( &glyphPath, curX, curY );
+ idx += 2;
+ }
+
+ while ( idx < count )
+ {
+ CF2_Fixed x1, y1, x2, y2, x3, y3;
+
+
+ x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX );
+ y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), curY );
+ x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), x1 );
+ y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y1 );
+ x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 );
+ y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 5 ), y2 );
+
+ cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
+
+ curX = x3;
+ curY = y3;
+ idx += 6;
+ }
+
+ cf2_stack_clear( opStack );
+ }
+ continue; /* no need to clear stack again */
+
+ case cf2_cmdVVCURVETO:
+ {
+ CF2_UInt count, count1 = cf2_stack_count( opStack );
+ CF2_UInt idx = 0;
+
+
+ /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */
+ /* we enforce it by clearing the second bit */
+ /* (and sorting the stack indexing to suit) */
+ count = count1 & ~2U;
+ idx += count1 - count;
+
+ FT_TRACE4(( " vvcurveto\n" ));
+
+ while ( idx < count )
+ {
+ CF2_Fixed x1, y1, x2, y2, x3, y3;
+
+
+ if ( ( count - idx ) & 1 )
+ {
+ x1 = ADD_INT32( cf2_stack_getReal( opStack, idx ), curX );
+
+ idx++;
+ }
+ else
+ x1 = curX;
+
+ y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curY );
+ x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 );
+ y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 );
+ x3 = x2;
+ y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y2 );
+
+ cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
+
+ curX = x3;
+ curY = y3;
+ idx += 4;
+ }
+
+ cf2_stack_clear( opStack );
+ }
+ continue; /* no need to clear stack again */
+
+ case cf2_cmdHHCURVETO:
+ {
+ CF2_UInt count, count1 = cf2_stack_count( opStack );
+ CF2_UInt idx = 0;
+
+
+ /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */
+ /* we enforce it by clearing the second bit */
+ /* (and sorting the stack indexing to suit) */
+ count = count1 & ~2U;
+ idx += count1 - count;
+
+ FT_TRACE4(( " hhcurveto\n" ));
+
+ while ( idx < count )
+ {
+ CF2_Fixed x1, y1, x2, y2, x3, y3;
+
+
+ if ( ( count - idx ) & 1 )
+ {
+ y1 = ADD_INT32( cf2_stack_getReal( opStack, idx ), curY );
+
+ idx++;
+ }
+ else
+ y1 = curY;
+
+ x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX );
+ x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 );
+ y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 );
+ x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), x2 );
+ y3 = y2;
+
+ cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
+
+ curX = x3;
+ curY = y3;
+ idx += 4;
+ }
+
+ cf2_stack_clear( opStack );
+ }
+ continue; /* no need to clear stack again */
+
+ case cf2_cmdVHCURVETO:
+ case cf2_cmdHVCURVETO:
+ {
+ CF2_UInt count, count1 = cf2_stack_count( opStack );
+ CF2_UInt idx = 0;
+
+ FT_Bool alternate = FT_BOOL( op1 == cf2_cmdHVCURVETO );
+
+
+ /* if `cf2_stack_count' isn't of the form 8n, 8n+1, */
+ /* 8n+4, or 8n+5, we enforce it by clearing the */
+ /* second bit */
+ /* (and sorting the stack indexing to suit) */
+ count = count1 & ~2U;
+ idx += count1 - count;
+
+ FT_TRACE4(( alternate ? " hvcurveto\n" : " vhcurveto\n" ));
+
+ while ( idx < count )
+ {
+ CF2_Fixed x1, x2, x3, y1, y2, y3;
+
+
+ if ( alternate )
+ {
+ x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX );
+ y1 = curY;
+ x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 );
+ y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 );
+ y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y2 );
+
+ if ( count - idx == 5 )
+ {
+ x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 );
+
+ idx++;
+ }
+ else
+ x3 = x2;
+
+ alternate = FALSE;
+ }
+ else
+ {
+ x1 = curX;
+ y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curY );
+ x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 );
+ y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 );
+ x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), x2 );
+
+ if ( count - idx == 5 )
+ {
+ y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), y2 );
+
+ idx++;
+ }
+ else
+ y3 = y2;
+
+ alternate = TRUE;
+ }
+
+ cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
+
+ curX = x3;
+ curY = y3;
+ idx += 4;
+ }
+
+ cf2_stack_clear( opStack );
+ }
+ continue; /* no need to clear stack again */
+
+ case cf2_cmdEXTENDEDNMBR:
+ {
+ CF2_Int v;
+
+ CF2_Int byte1 = cf2_buf_readByte( charstring );
+ CF2_Int byte2 = cf2_buf_readByte( charstring );
+
+
+ v = (FT_Short)( ( byte1 << 8 ) |
+ byte2 );
+
+ FT_TRACE4(( " %d", v ));
+
+ cf2_stack_pushInt( opStack, v );
+ }
+ continue;
+
+ default:
+ /* numbers */
+ {
+ if ( /* op1 >= 32 && */ op1 <= 246 )
+ {
+ CF2_Int v;
+
+
+ v = op1 - 139;
+
+ FT_TRACE4(( " %d", v ));
+
+ /* -107 .. 107 */
+ cf2_stack_pushInt( opStack, v );
+ }
+
+ else if ( /* op1 >= 247 && */ op1 <= 250 )
+ {
+ CF2_Int v;
+
+
+ v = op1;
+ v -= 247;
+ v *= 256;
+ v += cf2_buf_readByte( charstring );
+ v += 108;
+
+ FT_TRACE4(( " %d", v ));
+
+ /* 108 .. 1131 */
+ cf2_stack_pushInt( opStack, v );
+ }
+
+ else if ( /* op1 >= 251 && */ op1 <= 254 )
+ {
+ CF2_Int v;
+
+
+ v = op1;
+ v -= 251;
+ v *= 256;
+ v += cf2_buf_readByte( charstring );
+ v = -v - 108;
+
+ FT_TRACE4(( " %d", v ));
+
+ /* -1131 .. -108 */
+ cf2_stack_pushInt( opStack, v );
+ }
+
+ else /* op1 == 255 */
+ {
+ CF2_Fixed v;
+
+ FT_UInt32 byte1 = (FT_UInt32)cf2_buf_readByte( charstring );
+ FT_UInt32 byte2 = (FT_UInt32)cf2_buf_readByte( charstring );
+ FT_UInt32 byte3 = (FT_UInt32)cf2_buf_readByte( charstring );
+ FT_UInt32 byte4 = (FT_UInt32)cf2_buf_readByte( charstring );
+
+
+ v = (CF2_Fixed)( ( byte1 << 24 ) |
+ ( byte2 << 16 ) |
+ ( byte3 << 8 ) |
+ byte4 );
+
+ /*
+ * For Type 1:
+ *
+ * According to the specification, values > 32000 or < -32000
+ * must be followed by a `div' operator to make the result be
+ * in the range [-32000;32000]. We expect that the second
+ * argument of `div' is not a large number. Additionally, we
+ * don't handle stuff like `<large1> <large2> <num> div <num>
+ * div' or <large1> <large2> <num> div div'. This is probably
+ * not allowed anyway.
+ *
+ * <large> <num> <num>+ div is not checked but should not be
+ * allowed as the large value remains untouched.
+ *
+ */
+ if ( font->isT1 )
+ {
+ if ( v > 32000 || v < -32000 )
+ {
+ if ( large_int )
+ FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
+ " no `div' after large integer\n" ));
+ else
+ large_int = TRUE;
+ }
+
+ FT_TRACE4(( " %d", v ));
+
+ cf2_stack_pushInt( opStack, (CF2_Int)v );
+ }
+ else
+ {
+ FT_TRACE4(( " %.5fF", v / 65536.0 ));
+
+ cf2_stack_pushFixed( opStack, v );
+ }
+ }
+ }
+ continue; /* don't clear stack */
+
+ } /* end of switch statement checking `op1' */
+
+ cf2_stack_clear( opStack );
+
+ } /* end of main interpreter loop */
+
+ /* we get here if the charstring ends without cf2_cmdENDCHAR */
+ FT_TRACE4(( "cf2_interpT2CharString:"
+ " charstring ends without ENDCHAR\n" ));
+
+ exit:
+ /* check whether last error seen is also the first one */
+ cf2_setError( error, lastError );
+
+ if ( *error )
+ FT_TRACE4(( "charstring error %d\n", *error ));
+
+ /* free resources from objects we've used */
+ cf2_glyphpath_finalize( &glyphPath );
+ cf2_arrstack_finalize( &vStemHintArray );
+ cf2_arrstack_finalize( &hStemHintArray );
+ cf2_arrstack_finalize( &subrStack );
+ cf2_stack_free( opStack );
+
+ FT_TRACE4(( "\n" ));
+
+ return;
+ }
+
+
+/* END */
diff --git a/thirdparty/freetype/src/psaux/psintrp.h b/thirdparty/freetype/src/psaux/psintrp.h
new file mode 100644
index 0000000000..4790aaa302
--- /dev/null
+++ b/thirdparty/freetype/src/psaux/psintrp.h
@@ -0,0 +1,83 @@
+/***************************************************************************/
+/* */
+/* psintrp.h */
+/* */
+/* Adobe's CFF Interpreter (specification). */
+/* */
+/* Copyright 2007-2013 Adobe Systems Incorporated. */
+/* */
+/* This software, and all works of authorship, whether in source or */
+/* object code form as indicated by the copyright notice(s) included */
+/* herein (collectively, the "Work") is made available, and may only be */
+/* used, modified, and distributed under the FreeType Project License, */
+/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
+/* FreeType Project License, each contributor to the Work hereby grants */
+/* to any individual or legal entity exercising permissions granted by */
+/* the FreeType Project License and this section (hereafter, "You" or */
+/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
+/* royalty-free, irrevocable (except as stated in this section) patent */
+/* license to make, have made, use, offer to sell, sell, import, and */
+/* otherwise transfer the Work, where such license applies only to those */
+/* patent claims licensable by such contributor that are necessarily */
+/* infringed by their contribution(s) alone or by combination of their */
+/* contribution(s) with the Work to which such contribution(s) was */
+/* submitted. If You institute patent litigation against any entity */
+/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
+/* the Work or a contribution incorporated within the Work constitutes */
+/* direct or contributory patent infringement, then any patent licenses */
+/* granted to You under this License for that Work shall terminate as of */
+/* the date such litigation is filed. */
+/* */
+/* By using, modifying, or distributing the Work you indicate that you */
+/* have read and understood the terms and conditions of the */
+/* FreeType Project License as well as those provided in this section, */
+/* and you accept them fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef PSINTRP_H_
+#define PSINTRP_H_
+
+
+#include "psft.h"
+#include "pshints.h"
+
+
+FT_BEGIN_HEADER
+
+
+ FT_LOCAL( void )
+ cf2_hintmask_init( CF2_HintMask hintmask,
+ FT_Error* error );
+ FT_LOCAL( FT_Bool )
+ cf2_hintmask_isValid( const CF2_HintMask hintmask );
+ FT_LOCAL( FT_Bool )
+ cf2_hintmask_isNew( const CF2_HintMask hintmask );
+ FT_LOCAL( void )
+ cf2_hintmask_setNew( CF2_HintMask hintmask,
+ FT_Bool val );
+ FT_LOCAL( FT_Byte* )
+ cf2_hintmask_getMaskPtr( CF2_HintMask hintmask );
+ FT_LOCAL( void )
+ cf2_hintmask_setAll( CF2_HintMask hintmask,
+ size_t bitCount );
+
+ FT_LOCAL( void )
+ cf2_interpT2CharString( CF2_Font font,
+ CF2_Buffer charstring,
+ CF2_OutlineCallbacks callbacks,
+ const FT_Vector* translation,
+ FT_Bool doingSeac,
+ CF2_Fixed curX,
+ CF2_Fixed curY,
+ CF2_Fixed* width );
+
+
+FT_END_HEADER
+
+
+#endif /* PSINTRP_H_ */
+
+
+/* END */
diff --git a/thirdparty/freetype/src/psaux/psobjs.c b/thirdparty/freetype/src/psaux/psobjs.c
index f04edea411..f54bc7e416 100644
--- a/thirdparty/freetype/src/psaux/psobjs.c
+++ b/thirdparty/freetype/src/psaux/psobjs.c
@@ -4,7 +4,7 @@
/* */
/* Auxiliary functions for PostScript fonts (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -20,11 +20,13 @@
#include FT_INTERNAL_POSTSCRIPT_AUX_H
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_CALC_H
+#include FT_DRIVER_H
#include "psobjs.h"
#include "psconv.h"
#include "psauxerr.h"
+#include "psauxmod.h"
/*************************************************************************/
@@ -1761,11 +1763,748 @@
/*************************************************************************/
/*************************************************************************/
/***** *****/
+ /***** CFF BUILDER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* cff_builder_init */
+ /* */
+ /* <Description> */
+ /* Initializes a given glyph builder. */
+ /* */
+ /* <InOut> */
+ /* builder :: A pointer to the glyph builder to initialize. */
+ /* */
+ /* <Input> */
+ /* face :: The current face object. */
+ /* */
+ /* size :: The current size object. */
+ /* */
+ /* glyph :: The current glyph object. */
+ /* */
+ /* hinting :: Whether hinting is active. */
+ /* */
+ FT_LOCAL_DEF( void )
+ cff_builder_init( CFF_Builder* builder,
+ TT_Face face,
+ CFF_Size size,
+ CFF_GlyphSlot glyph,
+ FT_Bool hinting )
+ {
+ builder->path_begun = 0;
+ builder->load_points = 1;
+
+ builder->face = face;
+ builder->glyph = glyph;
+ builder->memory = face->root.memory;
+
+ if ( glyph )
+ {
+ FT_GlyphLoader loader = glyph->root.internal->loader;
+
+
+ builder->loader = loader;
+ builder->base = &loader->base.outline;
+ builder->current = &loader->current.outline;
+ FT_GlyphLoader_Rewind( loader );
+
+ builder->hints_globals = NULL;
+ builder->hints_funcs = NULL;
+
+ if ( hinting && size )
+ {
+ FT_Size ftsize = FT_SIZE( size );
+ CFF_Internal internal = (CFF_Internal)ftsize->internal->module_data;
+
+ if ( internal )
+ {
+ builder->hints_globals = (void *)internal->topfont;
+ builder->hints_funcs = glyph->root.internal->glyph_hints;
+ }
+ }
+ }
+
+ builder->pos_x = 0;
+ builder->pos_y = 0;
+
+ builder->left_bearing.x = 0;
+ builder->left_bearing.y = 0;
+ builder->advance.x = 0;
+ builder->advance.y = 0;
+
+ builder->funcs = cff_builder_funcs;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* cff_builder_done */
+ /* */
+ /* <Description> */
+ /* Finalizes a given glyph builder. Its contents can still be used */
+ /* after the call, but the function saves important information */
+ /* within the corresponding glyph slot. */
+ /* */
+ /* <Input> */
+ /* builder :: A pointer to the glyph builder to finalize. */
+ /* */
+ FT_LOCAL_DEF( void )
+ cff_builder_done( CFF_Builder* builder )
+ {
+ CFF_GlyphSlot glyph = builder->glyph;
+
+
+ if ( glyph )
+ glyph->root.outline = *builder->base;
+ }
+
+
+ /* check that there is enough space for `count' more points */
+ FT_LOCAL_DEF( FT_Error )
+ cff_check_points( CFF_Builder* builder,
+ FT_Int count )
+ {
+ return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );
+ }
+
+
+ /* add a new point, do not check space */
+ FT_LOCAL_DEF( void )
+ cff_builder_add_point( CFF_Builder* builder,
+ FT_Pos x,
+ FT_Pos y,
+ FT_Byte flag )
+ {
+ FT_Outline* outline = builder->current;
+
+
+ if ( builder->load_points )
+ {
+ FT_Vector* point = outline->points + outline->n_points;
+ FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
+
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+ PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( builder->face );
+
+
+ if ( driver->hinting_engine == FT_HINTING_FREETYPE )
+ {
+ point->x = x >> 16;
+ point->y = y >> 16;
+ }
+ else
+#endif
+ {
+ /* cf2_decoder_parse_charstrings uses 16.16 coordinates */
+ point->x = x >> 10;
+ point->y = y >> 10;
+ }
+ *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
+ }
+
+ outline->n_points++;
+ }
+
+
+ /* check space for a new on-curve point, then add it */
+ FT_LOCAL_DEF( FT_Error )
+ cff_builder_add_point1( CFF_Builder* builder,
+ FT_Pos x,
+ FT_Pos y )
+ {
+ FT_Error error;
+
+
+ error = cff_check_points( builder, 1 );
+ if ( !error )
+ cff_builder_add_point( builder, x, y, 1 );
+
+ return error;
+ }
+
+
+ /* check space for a new contour, then add it */
+ FT_LOCAL_DEF( FT_Error )
+ cff_builder_add_contour( CFF_Builder* builder )
+ {
+ FT_Outline* outline = builder->current;
+ FT_Error error;
+
+
+ if ( !builder->load_points )
+ {
+ outline->n_contours++;
+ return FT_Err_Ok;
+ }
+
+ error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );
+ if ( !error )
+ {
+ if ( outline->n_contours > 0 )
+ outline->contours[outline->n_contours - 1] =
+ (short)( outline->n_points - 1 );
+
+ outline->n_contours++;
+ }
+
+ return error;
+ }
+
+
+ /* if a path was begun, add its first on-curve point */
+ FT_LOCAL_DEF( FT_Error )
+ cff_builder_start_point( CFF_Builder* builder,
+ FT_Pos x,
+ FT_Pos y )
+ {
+ FT_Error error = FT_Err_Ok;
+
+
+ /* test whether we are building a new contour */
+ if ( !builder->path_begun )
+ {
+ builder->path_begun = 1;
+ error = cff_builder_add_contour( builder );
+ if ( !error )
+ error = cff_builder_add_point1( builder, x, y );
+ }
+
+ return error;
+ }
+
+
+ /* close the current contour */
+ FT_LOCAL_DEF( void )
+ cff_builder_close_contour( CFF_Builder* builder )
+ {
+ FT_Outline* outline = builder->current;
+ FT_Int first;
+
+
+ if ( !outline )
+ return;
+
+ first = outline->n_contours <= 1
+ ? 0 : outline->contours[outline->n_contours - 2] + 1;
+
+ /* We must not include the last point in the path if it */
+ /* is located on the first point. */
+ if ( outline->n_points > 1 )
+ {
+ FT_Vector* p1 = outline->points + first;
+ FT_Vector* p2 = outline->points + outline->n_points - 1;
+ FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1;
+
+
+ /* `delete' last point only if it coincides with the first */
+ /* point and if it is not a control point (which can happen). */
+ if ( p1->x == p2->x && p1->y == p2->y )
+ if ( *control == FT_CURVE_TAG_ON )
+ outline->n_points--;
+ }
+
+ if ( outline->n_contours > 0 )
+ {
+ /* Don't add contours only consisting of one point, i.e., */
+ /* check whether begin point and last point are the same. */
+ if ( first == outline->n_points - 1 )
+ {
+ outline->n_contours--;
+ outline->n_points--;
+ }
+ else
+ outline->contours[outline->n_contours - 1] =
+ (short)( outline->n_points - 1 );
+ }
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** PS BUILDER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ps_builder_init */
+ /* */
+ /* <Description> */
+ /* Initializes a given glyph builder. */
+ /* */
+ /* <InOut> */
+ /* builder :: A pointer to the glyph builder to initialize. */
+ /* */
+ /* <Input> */
+ /* face :: The current face object. */
+ /* */
+ /* size :: The current size object. */
+ /* */
+ /* glyph :: The current glyph object. */
+ /* */
+ /* hinting :: Whether hinting should be applied. */
+ /* */
+ FT_LOCAL_DEF( void )
+ ps_builder_init( PS_Builder* ps_builder,
+ void* builder,
+ FT_Bool is_t1 )
+ {
+ FT_ZERO( ps_builder );
+
+ if ( is_t1 )
+ {
+ T1_Builder t1builder = (T1_Builder)builder;
+
+
+ ps_builder->memory = t1builder->memory;
+ ps_builder->face = (FT_Face)t1builder->face;
+ ps_builder->glyph = (CFF_GlyphSlot)t1builder->glyph;
+ ps_builder->loader = t1builder->loader;
+ ps_builder->base = t1builder->base;
+ ps_builder->current = t1builder->current;
+
+ ps_builder->pos_x = &t1builder->pos_x;
+ ps_builder->pos_y = &t1builder->pos_y;
+
+ ps_builder->left_bearing = &t1builder->left_bearing;
+ ps_builder->advance = &t1builder->advance;
+
+ ps_builder->bbox = &t1builder->bbox;
+ ps_builder->path_begun = 0;
+ ps_builder->load_points = t1builder->load_points;
+ ps_builder->no_recurse = t1builder->no_recurse;
+
+ ps_builder->metrics_only = t1builder->metrics_only;
+ }
+ else
+ {
+ CFF_Builder* cffbuilder = (CFF_Builder*)builder;
+
+
+ ps_builder->memory = cffbuilder->memory;
+ ps_builder->face = (FT_Face)cffbuilder->face;
+ ps_builder->glyph = cffbuilder->glyph;
+ ps_builder->loader = cffbuilder->loader;
+ ps_builder->base = cffbuilder->base;
+ ps_builder->current = cffbuilder->current;
+
+ ps_builder->pos_x = &cffbuilder->pos_x;
+ ps_builder->pos_y = &cffbuilder->pos_y;
+
+ ps_builder->left_bearing = &cffbuilder->left_bearing;
+ ps_builder->advance = &cffbuilder->advance;
+
+ ps_builder->bbox = &cffbuilder->bbox;
+ ps_builder->path_begun = cffbuilder->path_begun;
+ ps_builder->load_points = cffbuilder->load_points;
+ ps_builder->no_recurse = cffbuilder->no_recurse;
+
+ ps_builder->metrics_only = cffbuilder->metrics_only;
+ }
+
+ ps_builder->is_t1 = is_t1;
+ ps_builder->funcs = ps_builder_funcs;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ps_builder_done */
+ /* */
+ /* <Description> */
+ /* Finalizes a given glyph builder. Its contents can still be used */
+ /* after the call, but the function saves important information */
+ /* within the corresponding glyph slot. */
+ /* */
+ /* <Input> */
+ /* builder :: A pointer to the glyph builder to finalize. */
+ /* */
+ FT_LOCAL_DEF( void )
+ ps_builder_done( PS_Builder* builder )
+ {
+ CFF_GlyphSlot glyph = builder->glyph;
+
+
+ if ( glyph )
+ glyph->root.outline = *builder->base;
+ }
+
+
+ /* check that there is enough space for `count' more points */
+ FT_LOCAL_DEF( FT_Error )
+ ps_builder_check_points( PS_Builder* builder,
+ FT_Int count )
+ {
+ return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );
+ }
+
+
+ /* add a new point, do not check space */
+ FT_LOCAL_DEF( void )
+ ps_builder_add_point( PS_Builder* builder,
+ FT_Pos x,
+ FT_Pos y,
+ FT_Byte flag )
+ {
+ FT_Outline* outline = builder->current;
+
+
+ if ( builder->load_points )
+ {
+ FT_Vector* point = outline->points + outline->n_points;
+ FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
+
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+ PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( builder->face );
+
+
+ if ( !builder->is_t1 &&
+ driver->hinting_engine == FT_HINTING_FREETYPE )
+ {
+ point->x = x >> 16;
+ point->y = y >> 16;
+ }
+ else
+#endif
+#ifdef T1_CONFIG_OPTION_OLD_ENGINE
+#ifndef CFF_CONFIG_OPTION_OLD_ENGINE
+ PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( builder->face );
+#endif
+ if ( builder->is_t1 &&
+ driver->hinting_engine == FT_HINTING_FREETYPE )
+ {
+ point->x = FIXED_TO_INT( x );
+ point->y = FIXED_TO_INT( y );
+ }
+ else
+#endif
+ {
+ /* cf2_decoder_parse_charstrings uses 16.16 coordinates */
+ point->x = x >> 10;
+ point->y = y >> 10;
+ }
+ *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
+ }
+ outline->n_points++;
+ }
+
+
+ /* check space for a new on-curve point, then add it */
+ FT_LOCAL_DEF( FT_Error )
+ ps_builder_add_point1( PS_Builder* builder,
+ FT_Pos x,
+ FT_Pos y )
+ {
+ FT_Error error;
+
+
+ error = ps_builder_check_points( builder, 1 );
+ if ( !error )
+ ps_builder_add_point( builder, x, y, 1 );
+
+ return error;
+ }
+
+
+ /* check space for a new contour, then add it */
+ FT_LOCAL_DEF( FT_Error )
+ ps_builder_add_contour( PS_Builder* builder )
+ {
+ FT_Outline* outline = builder->current;
+ FT_Error error;
+
+
+ /* this might happen in invalid fonts */
+ if ( !outline )
+ {
+ FT_ERROR(( "ps_builder_add_contour: no outline to add points to\n" ));
+ return FT_THROW( Invalid_File_Format );
+ }
+
+ if ( !builder->load_points )
+ {
+ outline->n_contours++;
+ return FT_Err_Ok;
+ }
+
+ error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );
+ if ( !error )
+ {
+ if ( outline->n_contours > 0 )
+ outline->contours[outline->n_contours - 1] =
+ (short)( outline->n_points - 1 );
+
+ outline->n_contours++;
+ }
+
+ return error;
+ }
+
+
+ /* if a path was begun, add its first on-curve point */
+ FT_LOCAL_DEF( FT_Error )
+ ps_builder_start_point( PS_Builder* builder,
+ FT_Pos x,
+ FT_Pos y )
+ {
+ FT_Error error = FT_Err_Ok;
+
+
+ /* test whether we are building a new contour */
+ if ( !builder->path_begun )
+ {
+ builder->path_begun = 1;
+ error = ps_builder_add_contour( builder );
+ if ( !error )
+ error = ps_builder_add_point1( builder, x, y );
+ }
+
+ return error;
+ }
+
+
+ /* close the current contour */
+ FT_LOCAL_DEF( void )
+ ps_builder_close_contour( PS_Builder* builder )
+ {
+ FT_Outline* outline = builder->current;
+ FT_Int first;
+
+
+ if ( !outline )
+ return;
+
+ first = outline->n_contours <= 1
+ ? 0 : outline->contours[outline->n_contours - 2] + 1;
+
+ /* in malformed fonts it can happen that a contour was started */
+ /* but no points were added */
+ if ( outline->n_contours && first == outline->n_points )
+ {
+ outline->n_contours--;
+ return;
+ }
+
+ /* We must not include the last point in the path if it */
+ /* is located on the first point. */
+ if ( outline->n_points > 1 )
+ {
+ 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 *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* ps_decoder_init */
+ /* */
+ /* <Description> */
+ /* Creates a wrapper decoder for use in the combined */
+ /* Type 1 / CFF interpreter. */
+ /* */
+ /* <InOut> */
+ /* ps_decoder :: A pointer to the decoder to initialize. */
+ /* */
+ /* <Input> */
+ /* decoder :: A pointer to the original decoder. */
+ /* */
+ /* is_t1 :: Flag indicating Type 1 or CFF */
+ /* */
+ FT_LOCAL_DEF( void )
+ ps_decoder_init( PS_Decoder* ps_decoder,
+ void* decoder,
+ FT_Bool is_t1 )
+ {
+ FT_ZERO( ps_decoder );
+
+ if ( is_t1 )
+ {
+ T1_Decoder t1_decoder = (T1_Decoder)decoder;
+
+
+ ps_builder_init( &ps_decoder->builder,
+ &t1_decoder->builder,
+ is_t1 );
+
+ ps_decoder->cf2_instance = &t1_decoder->cf2_instance;
+ ps_decoder->psnames = t1_decoder->psnames;
+
+ ps_decoder->num_glyphs = t1_decoder->num_glyphs;
+ ps_decoder->glyph_names = t1_decoder->glyph_names;
+ ps_decoder->hint_mode = t1_decoder->hint_mode;
+ ps_decoder->blend = t1_decoder->blend;
+
+ ps_decoder->num_locals = (FT_UInt)t1_decoder->num_subrs;
+ ps_decoder->locals = t1_decoder->subrs;
+ ps_decoder->locals_len = t1_decoder->subrs_len;
+ ps_decoder->locals_hash = t1_decoder->subrs_hash;
+
+ ps_decoder->buildchar = t1_decoder->buildchar;
+ ps_decoder->len_buildchar = t1_decoder->len_buildchar;
+
+ ps_decoder->lenIV = t1_decoder->lenIV;
+ }
+ else
+ {
+ CFF_Decoder* cff_decoder = (CFF_Decoder*)decoder;
+
+
+ ps_builder_init( &ps_decoder->builder,
+ &cff_decoder->builder,
+ is_t1 );
+
+ ps_decoder->cff = cff_decoder->cff;
+ ps_decoder->cf2_instance = &cff_decoder->cff->cf2_instance;
+ ps_decoder->current_subfont = cff_decoder->current_subfont;
+
+ ps_decoder->num_globals = cff_decoder->num_globals;
+ ps_decoder->globals = cff_decoder->globals;
+ ps_decoder->globals_bias = cff_decoder->globals_bias;
+ ps_decoder->num_locals = cff_decoder->num_locals;
+ ps_decoder->locals = cff_decoder->locals;
+ ps_decoder->locals_bias = cff_decoder->locals_bias;
+
+ ps_decoder->glyph_width = &cff_decoder->glyph_width;
+ ps_decoder->width_only = cff_decoder->width_only;
+
+ ps_decoder->hint_mode = cff_decoder->hint_mode;
+
+ ps_decoder->get_glyph_callback = cff_decoder->get_glyph_callback;
+ ps_decoder->free_glyph_callback = cff_decoder->free_glyph_callback;
+ }
+ }
+
+
+ /* Synthesize a SubFont object for Type 1 fonts, for use in the */
+ /* new interpreter to access Private dict data. */
+ FT_LOCAL_DEF( void )
+ t1_make_subfont( FT_Face face,
+ PS_Private priv,
+ CFF_SubFont subfont )
+ {
+ CFF_Private cpriv = &subfont->private_dict;
+ FT_UInt n, count;
+
+
+ FT_ZERO( subfont );
+ FT_ZERO( cpriv );
+
+ count = cpriv->num_blue_values = priv->num_blue_values;
+ for ( n = 0; n < count; n++ )
+ cpriv->blue_values[n] = (FT_Pos)priv->blue_values[n];
+
+ count = cpriv->num_other_blues = priv->num_other_blues;
+ for ( n = 0; n < count; n++ )
+ cpriv->other_blues[n] = (FT_Pos)priv->other_blues[n];
+
+ count = cpriv->num_family_blues = priv->num_family_blues;
+ for ( n = 0; n < count; n++ )
+ cpriv->family_blues[n] = (FT_Pos)priv->family_blues[n];
+
+ count = cpriv->num_family_other_blues = priv->num_family_other_blues;
+ for ( n = 0; n < count; n++ )
+ cpriv->family_other_blues[n] = (FT_Pos)priv->family_other_blues[n];
+
+ cpriv->blue_scale = priv->blue_scale;
+ cpriv->blue_shift = (FT_Pos)priv->blue_shift;
+ cpriv->blue_fuzz = (FT_Pos)priv->blue_fuzz;
+
+ cpriv->standard_width = (FT_Pos)priv->standard_width[0];
+ cpriv->standard_height = (FT_Pos)priv->standard_height[0];
+
+ count = cpriv->num_snap_widths = priv->num_snap_widths;
+ for ( n = 0; n < count; n++ )
+ cpriv->snap_widths[n] = (FT_Pos)priv->snap_widths[n];
+
+ count = cpriv->num_snap_heights = priv->num_snap_heights;
+ for ( n = 0; n < count; n++ )
+ cpriv->snap_heights[n] = (FT_Pos)priv->snap_heights[n];
+
+ cpriv->force_bold = priv->force_bold;
+ cpriv->lenIV = priv->lenIV;
+ cpriv->language_group = priv->language_group;
+ cpriv->expansion_factor = priv->expansion_factor;
+
+ cpriv->subfont = subfont;
+
+
+ /* Initialize the random number generator. */
+ if ( face->internal->random_seed != -1 )
+ {
+ /* If we have a face-specific seed, use it. */
+ /* If non-zero, update it to a positive value. */
+ subfont->random = (FT_UInt32)face->internal->random_seed;
+ if ( face->internal->random_seed )
+ {
+ do
+ {
+ face->internal->random_seed = (FT_Int32)cff_random(
+ (FT_UInt32)face->internal->random_seed );
+
+ } while ( face->internal->random_seed < 0 );
+ }
+ }
+ if ( !subfont->random )
+ {
+ FT_UInt32 seed;
+
+
+ /* compute random seed from some memory addresses */
+ seed = (FT_UInt32)( (FT_Offset)(char*)&seed ^
+ (FT_Offset)(char*)&face ^
+ (FT_Offset)(char*)&subfont );
+ seed = seed ^ ( seed >> 10 ) ^ ( seed >> 20 );
+ if ( seed == 0 )
+ seed = 0x7384;
+
+ subfont->random = seed;
+ }
+ }
+
+
FT_LOCAL_DEF( void )
t1_decrypt( FT_Byte* buffer,
FT_Offset length,
@@ -1779,4 +2518,16 @@
}
+ FT_LOCAL_DEF( FT_UInt32 )
+ cff_random( FT_UInt32 r )
+ {
+ /* a 32bit version of the `xorshift' algorithm */
+ r ^= r << 13;
+ r ^= r >> 17;
+ r ^= r << 5;
+
+ return r;
+ }
+
+
/* END */
diff --git a/thirdparty/freetype/src/psaux/psobjs.h b/thirdparty/freetype/src/psaux/psobjs.h
index 202e5b2416..8e0fe5fa4c 100644
--- a/thirdparty/freetype/src/psaux/psobjs.h
+++ b/thirdparty/freetype/src/psaux/psobjs.h
@@ -4,7 +4,7 @@
/* */
/* Auxiliary functions for PostScript fonts (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -22,6 +22,7 @@
#include <ft2build.h>
#include FT_INTERNAL_POSTSCRIPT_AUX_H
+#include FT_INTERNAL_CFF_OBJECTS_TYPES_H
FT_BEGIN_HEADER
@@ -193,17 +194,117 @@ FT_BEGIN_HEADER
/*************************************************************************/
/*************************************************************************/
/***** *****/
+ /***** CFF BUILDER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL( void )
+ cff_builder_init( CFF_Builder* builder,
+ TT_Face face,
+ CFF_Size size,
+ CFF_GlyphSlot glyph,
+ FT_Bool hinting );
+
+ FT_LOCAL( void )
+ cff_builder_done( CFF_Builder* builder );
+
+ FT_LOCAL( FT_Error )
+ cff_check_points( CFF_Builder* builder,
+ FT_Int count );
+
+ FT_LOCAL( void )
+ cff_builder_add_point( CFF_Builder* builder,
+ FT_Pos x,
+ FT_Pos y,
+ FT_Byte flag );
+ FT_LOCAL( FT_Error )
+ cff_builder_add_point1( CFF_Builder* builder,
+ FT_Pos x,
+ FT_Pos y );
+ FT_LOCAL( FT_Error )
+ cff_builder_start_point( CFF_Builder* builder,
+ FT_Pos x,
+ FT_Pos y );
+ FT_LOCAL( void )
+ cff_builder_close_contour( CFF_Builder* builder );
+
+ FT_LOCAL( FT_Error )
+ cff_builder_add_contour( CFF_Builder* builder );
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** PS BUILDER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL( void )
+ ps_builder_init( PS_Builder* ps_builder,
+ void* builder,
+ FT_Bool is_t1 );
+
+
+ FT_LOCAL( void )
+ ps_builder_done( PS_Builder* builder );
+
+ FT_LOCAL( FT_Error )
+ ps_builder_check_points( PS_Builder* builder,
+ FT_Int count );
+
+ FT_LOCAL( void )
+ ps_builder_add_point( PS_Builder* builder,
+ FT_Pos x,
+ FT_Pos y,
+ FT_Byte flag );
+
+ FT_LOCAL( FT_Error )
+ ps_builder_add_point1( PS_Builder* builder,
+ FT_Pos x,
+ FT_Pos y );
+
+ FT_LOCAL( FT_Error )
+ ps_builder_add_contour( PS_Builder* builder );
+
+ FT_LOCAL( FT_Error )
+ ps_builder_start_point( PS_Builder* builder,
+ FT_Pos x,
+ FT_Pos y );
+
+ FT_LOCAL( void )
+ ps_builder_close_contour( PS_Builder* builder );
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
/***** OTHER *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
FT_LOCAL( void )
+ ps_decoder_init( PS_Decoder* ps_decoder,
+ void* decoder,
+ FT_Bool is_t1 );
+
+ FT_LOCAL( void )
+ t1_make_subfont( FT_Face face,
+ PS_Private priv,
+ CFF_SubFont subfont );
+
+ FT_LOCAL( void )
t1_decrypt( FT_Byte* buffer,
FT_Offset length,
FT_UShort seed );
+ FT_LOCAL( FT_UInt32 )
+ cff_random( FT_UInt32 r );
+
+
FT_END_HEADER
#endif /* PSOBJS_H_ */
diff --git a/thirdparty/freetype/src/psaux/psread.c b/thirdparty/freetype/src/psaux/psread.c
new file mode 100644
index 0000000000..719863ce17
--- /dev/null
+++ b/thirdparty/freetype/src/psaux/psread.c
@@ -0,0 +1,112 @@
+/***************************************************************************/
+/* */
+/* psread.c */
+/* */
+/* Adobe's code for stream handling (body). */
+/* */
+/* Copyright 2007-2013 Adobe Systems Incorporated. */
+/* */
+/* This software, and all works of authorship, whether in source or */
+/* object code form as indicated by the copyright notice(s) included */
+/* herein (collectively, the "Work") is made available, and may only be */
+/* used, modified, and distributed under the FreeType Project License, */
+/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
+/* FreeType Project License, each contributor to the Work hereby grants */
+/* to any individual or legal entity exercising permissions granted by */
+/* the FreeType Project License and this section (hereafter, "You" or */
+/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
+/* royalty-free, irrevocable (except as stated in this section) patent */
+/* license to make, have made, use, offer to sell, sell, import, and */
+/* otherwise transfer the Work, where such license applies only to those */
+/* patent claims licensable by such contributor that are necessarily */
+/* infringed by their contribution(s) alone or by combination of their */
+/* contribution(s) with the Work to which such contribution(s) was */
+/* submitted. If You institute patent litigation against any entity */
+/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
+/* the Work or a contribution incorporated within the Work constitutes */
+/* direct or contributory patent infringement, then any patent licenses */
+/* granted to You under this License for that Work shall terminate as of */
+/* the date such litigation is filed. */
+/* */
+/* By using, modifying, or distributing the Work you indicate that you */
+/* have read and understood the terms and conditions of the */
+/* FreeType Project License as well as those provided in this section, */
+/* and you accept them fully. */
+/* */
+/***************************************************************************/
+
+
+#include "psft.h"
+#include FT_INTERNAL_DEBUG_H
+
+#include "psglue.h"
+
+#include "pserror.h"
+
+
+ /* Define CF2_IO_FAIL as 1 to enable random errors and random */
+ /* value errors in I/O. */
+#define CF2_IO_FAIL 0
+
+
+#if CF2_IO_FAIL
+
+ /* set the .00 value to a nonzero probability */
+ static int
+ randomError2( void )
+ {
+ /* for region buffer ReadByte (interp) function */
+ return (double)rand() / RAND_MAX < .00;
+ }
+
+ /* set the .00 value to a nonzero probability */
+ static CF2_Int
+ randomValue()
+ {
+ return (double)rand() / RAND_MAX < .00 ? rand() : 0;
+ }
+
+#endif /* CF2_IO_FAIL */
+
+
+ /* Region Buffer */
+ /* */
+ /* Can be constructed from a copied buffer managed by */
+ /* `FCM_getDatablock'. */
+ /* Reads bytes with check for end of buffer. */
+
+ /* reading past the end of the buffer sets error and returns zero */
+ FT_LOCAL_DEF( CF2_Int )
+ cf2_buf_readByte( CF2_Buffer buf )
+ {
+ if ( buf->ptr < buf->end )
+ {
+#if CF2_IO_FAIL
+ if ( randomError2() )
+ {
+ CF2_SET_ERROR( buf->error, Invalid_Stream_Operation );
+ return 0;
+ }
+
+ return *(buf->ptr)++ + randomValue();
+#else
+ return *(buf->ptr)++;
+#endif
+ }
+ else
+ {
+ CF2_SET_ERROR( buf->error, Invalid_Stream_Operation );
+ return 0;
+ }
+ }
+
+
+ /* note: end condition can occur without error */
+ FT_LOCAL_DEF( FT_Bool )
+ cf2_buf_isEnd( CF2_Buffer buf )
+ {
+ return (FT_Bool)( buf->ptr >= buf->end );
+ }
+
+
+/* END */
diff --git a/thirdparty/freetype/src/psaux/psread.h b/thirdparty/freetype/src/psaux/psread.h
new file mode 100644
index 0000000000..464b29ba74
--- /dev/null
+++ b/thirdparty/freetype/src/psaux/psread.h
@@ -0,0 +1,68 @@
+/***************************************************************************/
+/* */
+/* psread.h */
+/* */
+/* Adobe's code for stream handling (specification). */
+/* */
+/* Copyright 2007-2013 Adobe Systems Incorporated. */
+/* */
+/* This software, and all works of authorship, whether in source or */
+/* object code form as indicated by the copyright notice(s) included */
+/* herein (collectively, the "Work") is made available, and may only be */
+/* used, modified, and distributed under the FreeType Project License, */
+/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
+/* FreeType Project License, each contributor to the Work hereby grants */
+/* to any individual or legal entity exercising permissions granted by */
+/* the FreeType Project License and this section (hereafter, "You" or */
+/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
+/* royalty-free, irrevocable (except as stated in this section) patent */
+/* license to make, have made, use, offer to sell, sell, import, and */
+/* otherwise transfer the Work, where such license applies only to those */
+/* patent claims licensable by such contributor that are necessarily */
+/* infringed by their contribution(s) alone or by combination of their */
+/* contribution(s) with the Work to which such contribution(s) was */
+/* submitted. If You institute patent litigation against any entity */
+/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
+/* the Work or a contribution incorporated within the Work constitutes */
+/* direct or contributory patent infringement, then any patent licenses */
+/* granted to You under this License for that Work shall terminate as of */
+/* the date such litigation is filed. */
+/* */
+/* By using, modifying, or distributing the Work you indicate that you */
+/* have read and understood the terms and conditions of the */
+/* FreeType Project License as well as those provided in this section, */
+/* and you accept them fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef PSREAD_H_
+#define PSREAD_H_
+
+
+FT_BEGIN_HEADER
+
+
+ typedef struct CF2_BufferRec_
+ {
+ FT_Error* error;
+ const FT_Byte* start;
+ const FT_Byte* end;
+ const FT_Byte* ptr;
+
+ } CF2_BufferRec, *CF2_Buffer;
+
+
+ FT_LOCAL( CF2_Int )
+ cf2_buf_readByte( CF2_Buffer buf );
+ FT_LOCAL( FT_Bool )
+ cf2_buf_isEnd( CF2_Buffer buf );
+
+
+FT_END_HEADER
+
+
+#endif /* PSREAD_H_ */
+
+
+/* END */
diff --git a/thirdparty/freetype/src/psaux/psstack.c b/thirdparty/freetype/src/psaux/psstack.c
new file mode 100644
index 0000000000..69d063349a
--- /dev/null
+++ b/thirdparty/freetype/src/psaux/psstack.c
@@ -0,0 +1,328 @@
+/***************************************************************************/
+/* */
+/* psstack.c */
+/* */
+/* Adobe's code for emulating a CFF stack (body). */
+/* */
+/* Copyright 2007-2013 Adobe Systems Incorporated. */
+/* */
+/* This software, and all works of authorship, whether in source or */
+/* object code form as indicated by the copyright notice(s) included */
+/* herein (collectively, the "Work") is made available, and may only be */
+/* used, modified, and distributed under the FreeType Project License, */
+/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
+/* FreeType Project License, each contributor to the Work hereby grants */
+/* to any individual or legal entity exercising permissions granted by */
+/* the FreeType Project License and this section (hereafter, "You" or */
+/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
+/* royalty-free, irrevocable (except as stated in this section) patent */
+/* license to make, have made, use, offer to sell, sell, import, and */
+/* otherwise transfer the Work, where such license applies only to those */
+/* patent claims licensable by such contributor that are necessarily */
+/* infringed by their contribution(s) alone or by combination of their */
+/* contribution(s) with the Work to which such contribution(s) was */
+/* submitted. If You institute patent litigation against any entity */
+/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
+/* the Work or a contribution incorporated within the Work constitutes */
+/* direct or contributory patent infringement, then any patent licenses */
+/* granted to You under this License for that Work shall terminate as of */
+/* the date such litigation is filed. */
+/* */
+/* By using, modifying, or distributing the Work you indicate that you */
+/* have read and understood the terms and conditions of the */
+/* FreeType Project License as well as those provided in this section, */
+/* and you accept them fully. */
+/* */
+/***************************************************************************/
+
+
+#include "psft.h"
+#include FT_INTERNAL_DEBUG_H
+
+#include "psglue.h"
+#include "psfont.h"
+#include "psstack.h"
+
+#include "pserror.h"
+
+
+ /* Allocate and initialize an instance of CF2_Stack. */
+ /* Note: This function returns NULL on error (does not set */
+ /* `error'). */
+ FT_LOCAL_DEF( CF2_Stack )
+ cf2_stack_init( FT_Memory memory,
+ FT_Error* e,
+ FT_UInt stackSize )
+ {
+ FT_Error error = FT_Err_Ok; /* for FT_NEW */
+
+ CF2_Stack stack = NULL;
+
+
+ if ( !FT_NEW( stack ) )
+ {
+ /* initialize the structure; FT_NEW zeroes it */
+ stack->memory = memory;
+ stack->error = e;
+ }
+
+ /* allocate the stack buffer */
+ if ( FT_NEW_ARRAY( stack->buffer, stackSize ) )
+ {
+ FT_FREE( stack );
+ return NULL;
+ }
+
+ stack->stackSize = stackSize;
+ stack->top = stack->buffer; /* empty stack */
+
+ return stack;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cf2_stack_free( CF2_Stack stack )
+ {
+ if ( stack )
+ {
+ FT_Memory memory = stack->memory;
+
+ /* free the buffer */
+ FT_FREE( stack->buffer );
+
+ /* free the main structure */
+ FT_FREE( stack );
+ }
+ }
+
+
+ FT_LOCAL_DEF( CF2_UInt )
+ cf2_stack_count( CF2_Stack stack )
+ {
+ return (CF2_UInt)( stack->top - stack->buffer );
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cf2_stack_pushInt( CF2_Stack stack,
+ CF2_Int val )
+ {
+ if ( stack->top == stack->buffer + stack->stackSize )
+ {
+ CF2_SET_ERROR( stack->error, Stack_Overflow );
+ return; /* stack overflow */
+ }
+
+ stack->top->u.i = val;
+ stack->top->type = CF2_NumberInt;
+ stack->top++;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cf2_stack_pushFixed( CF2_Stack stack,
+ CF2_Fixed val )
+ {
+ if ( stack->top == stack->buffer + stack->stackSize )
+ {
+ CF2_SET_ERROR( stack->error, Stack_Overflow );
+ return; /* stack overflow */
+ }
+
+ stack->top->u.r = val;
+ stack->top->type = CF2_NumberFixed;
+ stack->top++;
+ }
+
+
+ /* this function is only allowed to pop an integer type */
+ FT_LOCAL_DEF( CF2_Int )
+ cf2_stack_popInt( CF2_Stack stack )
+ {
+ if ( stack->top == stack->buffer )
+ {
+ CF2_SET_ERROR( stack->error, Stack_Underflow );
+ return 0; /* underflow */
+ }
+ if ( stack->top[-1].type != CF2_NumberInt )
+ {
+ CF2_SET_ERROR( stack->error, Syntax_Error );
+ return 0; /* type mismatch */
+ }
+
+ stack->top--;
+
+ return stack->top->u.i;
+ }
+
+
+ /* Note: type mismatch is silently cast */
+ /* TODO: check this */
+ FT_LOCAL_DEF( CF2_Fixed )
+ cf2_stack_popFixed( CF2_Stack stack )
+ {
+ if ( stack->top == stack->buffer )
+ {
+ CF2_SET_ERROR( stack->error, Stack_Underflow );
+ return cf2_intToFixed( 0 ); /* underflow */
+ }
+
+ stack->top--;
+
+ switch ( stack->top->type )
+ {
+ case CF2_NumberInt:
+ return cf2_intToFixed( stack->top->u.i );
+ case CF2_NumberFrac:
+ return cf2_fracToFixed( stack->top->u.f );
+ default:
+ return stack->top->u.r;
+ }
+ }
+
+
+ /* Note: type mismatch is silently cast */
+ /* TODO: check this */
+ FT_LOCAL_DEF( CF2_Fixed )
+ cf2_stack_getReal( CF2_Stack stack,
+ CF2_UInt idx )
+ {
+ FT_ASSERT( cf2_stack_count( stack ) <= stack->stackSize );
+
+ if ( idx >= cf2_stack_count( stack ) )
+ {
+ CF2_SET_ERROR( stack->error, Stack_Overflow );
+ return cf2_intToFixed( 0 ); /* bounds error */
+ }
+
+ switch ( stack->buffer[idx].type )
+ {
+ case CF2_NumberInt:
+ return cf2_intToFixed( stack->buffer[idx].u.i );
+ case CF2_NumberFrac:
+ return cf2_fracToFixed( stack->buffer[idx].u.f );
+ default:
+ return stack->buffer[idx].u.r;
+ }
+ }
+
+
+ /* provide random access to stack */
+ FT_LOCAL_DEF( void )
+ cf2_stack_setReal( CF2_Stack stack,
+ CF2_UInt idx,
+ CF2_Fixed val )
+ {
+ if ( idx > cf2_stack_count( stack ) )
+ {
+ CF2_SET_ERROR( stack->error, Stack_Overflow );
+ return;
+ }
+
+ stack->buffer[idx].u.r = val;
+ stack->buffer[idx].type = CF2_NumberFixed;
+ }
+
+
+ /* discard (pop) num values from stack */
+ FT_LOCAL_DEF( void )
+ cf2_stack_pop( CF2_Stack stack,
+ CF2_UInt num )
+ {
+ if ( num > cf2_stack_count( stack ) )
+ {
+ CF2_SET_ERROR( stack->error, Stack_Underflow );
+ return;
+ }
+ stack->top -= num;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cf2_stack_roll( CF2_Stack stack,
+ CF2_Int count,
+ CF2_Int shift )
+ {
+ /* we initialize this variable to avoid compiler warnings */
+ CF2_StackNumber last = { { 0 }, CF2_NumberInt };
+
+ CF2_Int start_idx, idx, i;
+
+
+ if ( count < 2 )
+ return; /* nothing to do (values 0 and 1), or undefined value */
+
+ if ( (CF2_UInt)count > cf2_stack_count( stack ) )
+ {
+ CF2_SET_ERROR( stack->error, Stack_Overflow );
+ return;
+ }
+
+ if ( shift < 0 )
+ shift = -( ( -shift ) % count );
+ else
+ shift %= count;
+
+ if ( shift == 0 )
+ return; /* nothing to do */
+
+ /* We use the following algorithm to do the rolling, */
+ /* which needs two temporary variables only. */
+ /* */
+ /* Example: */
+ /* */
+ /* count = 8 */
+ /* shift = 2 */
+ /* */
+ /* stack indices before roll: 7 6 5 4 3 2 1 0 */
+ /* stack indices after roll: 1 0 7 6 5 4 3 2 */
+ /* */
+ /* The value of index 0 gets moved to index 2, while */
+ /* the old value of index 2 gets moved to index 4, */
+ /* and so on. We thus have the following copying */
+ /* chains for shift value 2. */
+ /* */
+ /* 0 -> 2 -> 4 -> 6 -> 0 */
+ /* 1 -> 3 -> 5 -> 7 -> 1 */
+ /* */
+ /* If `count' and `shift' are incommensurable, we */
+ /* have a single chain only. Otherwise, increase */
+ /* the start index by 1 after the first chain, then */
+ /* do the next chain until all elements in all */
+ /* chains are handled. */
+
+ start_idx = -1;
+ idx = -1;
+ for ( i = 0; i < count; i++ )
+ {
+ CF2_StackNumber tmp;
+
+
+ if ( start_idx == idx )
+ {
+ start_idx++;
+ idx = start_idx;
+ last = stack->buffer[idx];
+ }
+
+ idx += shift;
+ if ( idx >= count )
+ idx -= count;
+ else if ( idx < 0 )
+ idx += count;
+
+ tmp = stack->buffer[idx];
+ stack->buffer[idx] = last;
+ last = tmp;
+ }
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cf2_stack_clear( CF2_Stack stack )
+ {
+ stack->top = stack->buffer;
+ }
+
+
+/* END */
diff --git a/thirdparty/freetype/src/psaux/psstack.h b/thirdparty/freetype/src/psaux/psstack.h
new file mode 100644
index 0000000000..38f7b41c68
--- /dev/null
+++ b/thirdparty/freetype/src/psaux/psstack.h
@@ -0,0 +1,121 @@
+/***************************************************************************/
+/* */
+/* psstack.h */
+/* */
+/* Adobe's code for emulating a CFF stack (specification). */
+/* */
+/* Copyright 2007-2013 Adobe Systems Incorporated. */
+/* */
+/* This software, and all works of authorship, whether in source or */
+/* object code form as indicated by the copyright notice(s) included */
+/* herein (collectively, the "Work") is made available, and may only be */
+/* used, modified, and distributed under the FreeType Project License, */
+/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
+/* FreeType Project License, each contributor to the Work hereby grants */
+/* to any individual or legal entity exercising permissions granted by */
+/* the FreeType Project License and this section (hereafter, "You" or */
+/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
+/* royalty-free, irrevocable (except as stated in this section) patent */
+/* license to make, have made, use, offer to sell, sell, import, and */
+/* otherwise transfer the Work, where such license applies only to those */
+/* patent claims licensable by such contributor that are necessarily */
+/* infringed by their contribution(s) alone or by combination of their */
+/* contribution(s) with the Work to which such contribution(s) was */
+/* submitted. If You institute patent litigation against any entity */
+/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
+/* the Work or a contribution incorporated within the Work constitutes */
+/* direct or contributory patent infringement, then any patent licenses */
+/* granted to You under this License for that Work shall terminate as of */
+/* the date such litigation is filed. */
+/* */
+/* By using, modifying, or distributing the Work you indicate that you */
+/* have read and understood the terms and conditions of the */
+/* FreeType Project License as well as those provided in this section, */
+/* and you accept them fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef PSSTACK_H_
+#define PSSTACK_H_
+
+
+FT_BEGIN_HEADER
+
+
+ /* CFF operand stack; specified maximum of 48 or 192 values */
+ typedef struct CF2_StackNumber_
+ {
+ union
+ {
+ CF2_Fixed r; /* 16.16 fixed point */
+ CF2_Frac f; /* 2.30 fixed point (for font matrix) */
+ CF2_Int i;
+ } u;
+
+ CF2_NumberType type;
+
+ } CF2_StackNumber;
+
+
+ typedef struct CF2_StackRec_
+ {
+ FT_Memory memory;
+ FT_Error* error;
+ CF2_StackNumber* buffer;
+ CF2_StackNumber* top;
+ FT_UInt stackSize;
+
+ } CF2_StackRec, *CF2_Stack;
+
+
+ FT_LOCAL( CF2_Stack )
+ cf2_stack_init( FT_Memory memory,
+ FT_Error* error,
+ FT_UInt stackSize );
+ FT_LOCAL( void )
+ cf2_stack_free( CF2_Stack stack );
+
+ FT_LOCAL( CF2_UInt )
+ cf2_stack_count( CF2_Stack stack );
+
+ FT_LOCAL( void )
+ cf2_stack_pushInt( CF2_Stack stack,
+ CF2_Int val );
+ FT_LOCAL( void )
+ cf2_stack_pushFixed( CF2_Stack stack,
+ CF2_Fixed val );
+
+ FT_LOCAL( CF2_Int )
+ cf2_stack_popInt( CF2_Stack stack );
+ FT_LOCAL( CF2_Fixed )
+ cf2_stack_popFixed( CF2_Stack stack );
+
+ FT_LOCAL( CF2_Fixed )
+ cf2_stack_getReal( CF2_Stack stack,
+ CF2_UInt idx );
+ FT_LOCAL( void )
+ cf2_stack_setReal( CF2_Stack stack,
+ CF2_UInt idx,
+ CF2_Fixed val );
+
+ FT_LOCAL( void )
+ cf2_stack_pop( CF2_Stack stack,
+ CF2_UInt num );
+
+ FT_LOCAL( void )
+ cf2_stack_roll( CF2_Stack stack,
+ CF2_Int count,
+ CF2_Int idx );
+
+ FT_LOCAL( void )
+ cf2_stack_clear( CF2_Stack stack );
+
+
+FT_END_HEADER
+
+
+#endif /* PSSTACK_H_ */
+
+
+/* END */
diff --git a/thirdparty/freetype/src/psaux/pstypes.h b/thirdparty/freetype/src/psaux/pstypes.h
new file mode 100644
index 0000000000..dfbaa3d475
--- /dev/null
+++ b/thirdparty/freetype/src/psaux/pstypes.h
@@ -0,0 +1,78 @@
+/***************************************************************************/
+/* */
+/* pstypes.h */
+/* */
+/* Adobe's code for defining data types (specification only). */
+/* */
+/* Copyright 2011-2013 Adobe Systems Incorporated. */
+/* */
+/* This software, and all works of authorship, whether in source or */
+/* object code form as indicated by the copyright notice(s) included */
+/* herein (collectively, the "Work") is made available, and may only be */
+/* used, modified, and distributed under the FreeType Project License, */
+/* LICENSE.TXT. Additionally, subject to the terms and conditions of the */
+/* FreeType Project License, each contributor to the Work hereby grants */
+/* to any individual or legal entity exercising permissions granted by */
+/* the FreeType Project License and this section (hereafter, "You" or */
+/* "Your") a perpetual, worldwide, non-exclusive, no-charge, */
+/* royalty-free, irrevocable (except as stated in this section) patent */
+/* license to make, have made, use, offer to sell, sell, import, and */
+/* otherwise transfer the Work, where such license applies only to those */
+/* patent claims licensable by such contributor that are necessarily */
+/* infringed by their contribution(s) alone or by combination of their */
+/* contribution(s) with the Work to which such contribution(s) was */
+/* submitted. If You institute patent litigation against any entity */
+/* (including a cross-claim or counterclaim in a lawsuit) alleging that */
+/* the Work or a contribution incorporated within the Work constitutes */
+/* direct or contributory patent infringement, then any patent licenses */
+/* granted to You under this License for that Work shall terminate as of */
+/* the date such litigation is filed. */
+/* */
+/* By using, modifying, or distributing the Work you indicate that you */
+/* have read and understood the terms and conditions of the */
+/* FreeType Project License as well as those provided in this section, */
+/* and you accept them fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef PSTYPES_H_
+#define PSTYPES_H_
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+
+ /*
+ * The data models that we expect to support are as follows:
+ *
+ * name char short int long long-long pointer example
+ * -----------------------------------------------------
+ * ILP32 8 16 32 32 64* 32 32-bit MacOS, x86
+ * LLP64 8 16 32 32 64 64 x64
+ * LP64 8 16 32 64 64 64 64-bit MacOS
+ *
+ * *) type may be supported by emulation on a 32-bit architecture
+ *
+ */
+
+
+ /* integers at least 32 bits wide */
+#define CF2_UInt FT_UFast
+#define CF2_Int FT_Fast
+
+
+ /* fixed-float numbers */
+ typedef FT_Int32 CF2_F16Dot16;
+
+
+FT_END_HEADER
+
+
+#endif /* PSTYPES_H_ */
+
+
+/* END */
diff --git a/thirdparty/freetype/src/psaux/rules.mk b/thirdparty/freetype/src/psaux/rules.mk
index 542ae12d2b..a87bfe9687 100644
--- a/thirdparty/freetype/src/psaux/rules.mk
+++ b/thirdparty/freetype/src/psaux/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2017 by
+# Copyright 1996-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
@@ -33,12 +33,25 @@ PSAUX_DRV_SRC := $(PSAUX_DIR)/psobjs.c \
$(PSAUX_DIR)/t1cmap.c \
$(PSAUX_DIR)/afmparse.c \
$(PSAUX_DIR)/psconv.c \
- $(PSAUX_DIR)/psauxmod.c
+ $(PSAUX_DIR)/psauxmod.c \
+ $(PSAUX_DIR)/psarrst.c \
+ $(PSAUX_DIR)/psblues.c \
+ $(PSAUX_DIR)/pserror.c \
+ $(PSAUX_DIR)/psfont.c \
+ $(PSAUX_DIR)/psft.c \
+ $(PSAUX_DIR)/pshints.c \
+ $(PSAUX_DIR)/psintrp.c \
+ $(PSAUX_DIR)/psread.c \
+ $(PSAUX_DIR)/psstack.c \
+ $(PSAUX_DIR)/cffdecode.c
# PSAUX driver headers
#
PSAUX_DRV_H := $(PSAUX_DRV_SRC:%c=%h) \
- $(PSAUX_DIR)/psauxerr.h
+ $(PSAUX_DIR)/psauxerr.h \
+ $(PSAUX_DIR)/psfixed.h \
+ $(PSAUX_DIR)/psglue.h \
+ $(PSAUX_DIR)/pstypes.h
# PSAUX driver object(s)
diff --git a/thirdparty/freetype/src/psaux/t1cmap.c b/thirdparty/freetype/src/psaux/t1cmap.c
index 45b713eb7b..112a7892ba 100644
--- a/thirdparty/freetype/src/psaux/t1cmap.c
+++ b/thirdparty/freetype/src/psaux/t1cmap.c
@@ -4,7 +4,7 @@
/* */
/* Type 1 character map support (body). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/psaux/t1cmap.h b/thirdparty/freetype/src/psaux/t1cmap.h
index 7870245a3a..4308e31d2d 100644
--- a/thirdparty/freetype/src/psaux/t1cmap.h
+++ b/thirdparty/freetype/src/psaux/t1cmap.h
@@ -4,7 +4,7 @@
/* */
/* Type 1 character map support (specification). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/psaux/t1decode.c b/thirdparty/freetype/src/psaux/t1decode.c
index 1250b53f5d..6ad145661f 100644
--- a/thirdparty/freetype/src/psaux/t1decode.c
+++ b/thirdparty/freetype/src/psaux/t1decode.c
@@ -4,7 +4,7 @@
/* */
/* PostScript Type 1 decoding routines (body). */
/* */
-/* Copyright 2000-2017 by */
+/* Copyright 2000-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -112,6 +112,56 @@
/*************************************************************************/
/* */
/* <Function> */
+ /* t1_lookup_glyph_by_stdcharcode_ps */
+ /* */
+ /* <Description> */
+ /* Looks up a given glyph by its StandardEncoding charcode. Used to */
+ /* implement the SEAC Type 1 operator in the Adobe engine */
+ /* */
+ /* <Input> */
+ /* face :: The current face object. */
+ /* */
+ /* charcode :: The character code to look for. */
+ /* */
+ /* <Return> */
+ /* A glyph index in the font face. Returns -1 if the corresponding */
+ /* glyph wasn't found. */
+ /* */
+ FT_LOCAL_DEF( FT_Int )
+ t1_lookup_glyph_by_stdcharcode_ps( PS_Decoder* decoder,
+ FT_Int charcode )
+ {
+ FT_UInt n;
+ const FT_String* glyph_name;
+ FT_Service_PsCMaps psnames = decoder->psnames;
+
+
+ /* check range of standard char code */
+ if ( charcode < 0 || charcode > 255 )
+ return -1;
+
+ glyph_name = psnames->adobe_std_strings(
+ psnames->adobe_std_encoding[charcode]);
+
+ for ( n = 0; n < decoder->num_glyphs; n++ )
+ {
+ FT_String* name = (FT_String*)decoder->glyph_names[n];
+
+
+ if ( name &&
+ name[0] == glyph_name[0] &&
+ ft_strcmp( name, glyph_name ) == 0 )
+ return (FT_Int)n;
+ }
+
+ return -1;
+ }
+
+
+#ifdef T1_CONFIG_OPTION_OLD_ENGINE
+ /*************************************************************************/
+ /* */
+ /* <Function> */
/* t1_lookup_glyph_by_stdcharcode */
/* */
/* <Description> */
@@ -158,6 +208,15 @@
}
+ /* parse a single Type 1 glyph */
+ FT_LOCAL_DEF( FT_Error )
+ t1_decoder_parse_glyph( T1_Decoder decoder,
+ FT_UInt glyph )
+ {
+ return decoder->parse_callback( decoder, glyph );
+ }
+
+
/*************************************************************************/
/* */
/* <Function> */
@@ -1579,14 +1638,286 @@
return FT_THROW( Stack_Underflow );
}
+#else /* T1_CONFIG_OPTION_OLD_ENGINE */
- /* parse a single Type 1 glyph */
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* t1_decoder_parse_metrics */
+ /* */
+ /* <Description> */
+ /* Parses a given Type 1 charstrings program to extract width */
+ /* */
+ /* <Input> */
+ /* decoder :: The current Type 1 decoder. */
+ /* */
+ /* charstring_base :: The base address of the charstring stream. */
+ /* */
+ /* charstring_len :: The length in bytes of the charstring stream. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
FT_LOCAL_DEF( FT_Error )
- t1_decoder_parse_glyph( T1_Decoder decoder,
- FT_UInt glyph )
+ t1_decoder_parse_metrics( T1_Decoder decoder,
+ FT_Byte* charstring_base,
+ FT_UInt charstring_len )
{
- return decoder->parse_callback( decoder, glyph );
+ T1_Decoder_Zone zone;
+ FT_Byte* ip;
+ FT_Byte* limit;
+ T1_Builder builder = &decoder->builder;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_Bool bol = TRUE;
+#endif
+
+
+ /* First of all, initialize the decoder */
+ decoder->top = decoder->stack;
+ decoder->zone = decoder->zones;
+ zone = decoder->zones;
+
+ builder->parse_state = T1_Parse_Start;
+
+ FT_TRACE4(( "\n"
+ "Start charstring: get width\n" ));
+
+ zone->base = charstring_base;
+ limit = zone->limit = charstring_base + charstring_len;
+ ip = zone->cursor = zone->base;
+
+ /* now, execute loop */
+ while ( ip < limit )
+ {
+ FT_Long* top = decoder->top;
+ T1_Operator op = op_none;
+ FT_Int32 value = 0;
+
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( bol )
+ {
+ FT_TRACE5(( " (%d)", decoder->top - decoder->stack ));
+ bol = FALSE;
+ }
+#endif
+
+ /*********************************************************************/
+ /* */
+ /* Decode operator or operand */
+ /* */
+ /* */
+
+ /* first of all, decompress operator or value */
+ switch ( *ip++ )
+ {
+ case 1:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 14:
+ case 15:
+ case 21:
+ case 22:
+ case 30:
+ case 31:
+ goto No_Width;
+
+ case 13:
+ op = op_hsbw;
+ break;
+
+ case 12:
+ if ( ip >= limit )
+ {
+ FT_ERROR(( "t1_decoder_parse_metrics:"
+ " invalid escape (12+EOF)\n" ));
+ goto Syntax_Error;
+ }
+
+ switch ( *ip++ )
+ {
+ case 7:
+ op = op_sbw;
+ break;
+
+ default:
+ goto No_Width;
+ }
+ break;
+
+ case 255: /* four bytes integer */
+ if ( ip + 4 > limit )
+ {
+ FT_ERROR(( "t1_decoder_parse_metrics:"
+ " unexpected EOF in integer\n" ));
+ goto Syntax_Error;
+ }
+
+ value = (FT_Int32)( ( (FT_UInt32)ip[0] << 24 ) |
+ ( (FT_UInt32)ip[1] << 16 ) |
+ ( (FT_UInt32)ip[2] << 8 ) |
+ (FT_UInt32)ip[3] );
+ ip += 4;
+
+ /* According to the specification, values > 32000 or < -32000 must */
+ /* be followed by a `div' operator to make the result be in the */
+ /* range [-32000;32000]. We expect that the second argument of */
+ /* `div' is not a large number. Additionally, we don't handle */
+ /* stuff like `<large1> <large2> <num> div <num> div' or */
+ /* <large1> <large2> <num> div div'. This is probably not allowed */
+ /* anyway. */
+ if ( value > 32000 || value < -32000 )
+ {
+ FT_ERROR(( "t1_decoder_parse_metrics:"
+ " large integer found for width\n" ));
+ goto Syntax_Error;
+ }
+ else
+ {
+ value = (FT_Int32)( (FT_UInt32)value << 16 );
+ }
+
+ break;
+
+ default:
+ if ( ip[-1] >= 32 )
+ {
+ if ( ip[-1] < 247 )
+ value = (FT_Int32)ip[-1] - 139;
+ else
+ {
+ if ( ++ip > limit )
+ {
+ FT_ERROR(( "t1_decoder_parse_metrics:"
+ " unexpected EOF in integer\n" ));
+ goto Syntax_Error;
+ }
+
+ if ( ip[-2] < 251 )
+ value = ( ( ip[-2] - 247 ) * 256 ) + ip[-1] + 108;
+ else
+ value = -( ( ( ip[-2] - 251 ) * 256 ) + ip[-1] + 108 );
+ }
+
+ value = (FT_Int32)( (FT_UInt32)value << 16 );
+ }
+ else
+ {
+ FT_ERROR(( "t1_decoder_parse_metrics:"
+ " invalid byte (%d)\n", ip[-1] ));
+ goto Syntax_Error;
+ }
+ }
+
+ /*********************************************************************/
+ /* */
+ /* Push value on stack, or process operator */
+ /* */
+ /* */
+ if ( op == op_none )
+ {
+ if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
+ {
+ FT_ERROR(( "t1_decoder_parse_metrics: stack overflow\n" ));
+ goto Syntax_Error;
+ }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_TRACE4(( " %d", value / 65536 ));
+#endif
+
+ *top++ = value;
+ decoder->top = top;
+ }
+ else /* general operator */
+ {
+ FT_Int num_args = t1_args_count[op];
+
+
+ FT_ASSERT( num_args >= 0 );
+
+ if ( top - decoder->stack < num_args )
+ goto Stack_Underflow;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+ if ( top - decoder->stack != num_args )
+ FT_TRACE0(( "t1_decoder_parse_metrics:"
+ " too much operands on the stack"
+ " (seen %d, expected %d)\n",
+ top - decoder->stack, num_args ));
+
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
+ top -= num_args;
+
+ switch ( op )
+ {
+ case op_hsbw:
+ FT_TRACE4(( " hsbw" ));
+
+ builder->parse_state = T1_Parse_Have_Width;
+
+ builder->left_bearing.x = ADD_LONG( builder->left_bearing.x,
+ top[0] );
+
+ builder->advance.x = top[1];
+ builder->advance.y = 0;
+
+ /* we only want to compute the glyph's metrics */
+ /* (lsb + advance width), not load the rest of */
+ /* it; so exit immediately */
+ return FT_Err_Ok;
+
+ case op_sbw:
+ FT_TRACE4(( " sbw" ));
+
+ builder->parse_state = T1_Parse_Have_Width;
+
+ builder->left_bearing.x = ADD_LONG( builder->left_bearing.x,
+ top[0] );
+ builder->left_bearing.y = ADD_LONG( builder->left_bearing.y,
+ top[1] );
+
+ builder->advance.x = top[2];
+ builder->advance.y = top[3];
+
+ /* we only want to compute the glyph's metrics */
+ /* (lsb + advance width), not load the rest of */
+ /* it; so exit immediately */
+ return FT_Err_Ok;
+
+ default:
+ FT_ERROR(( "t1_decoder_parse_metrics:"
+ " unhandled opcode %d\n", op ));
+ goto Syntax_Error;
+ }
+
+ } /* general operator processing */
+
+ } /* while ip < limit */
+
+ FT_TRACE4(( "..end..\n\n" ));
+
+ No_Width:
+ FT_ERROR(( "t1_decoder_parse_metrics:"
+ " no width, found op %d instead\n",
+ ip[-1] ));
+ Syntax_Error:
+ return FT_THROW( Syntax_Error );
+
+ Stack_Underflow:
+ return FT_THROW( Stack_Underflow );
}
+#endif /* T1_CONFIG_OPTION_OLD_ENGINE */
/* initialize T1 decoder */
@@ -1641,7 +1972,16 @@
FT_LOCAL_DEF( void )
t1_decoder_done( T1_Decoder decoder )
{
+ FT_Memory memory = decoder->builder.memory;
+
+
t1_builder_done( &decoder->builder );
+
+ if ( decoder->cf2_instance.finalizer )
+ {
+ decoder->cf2_instance.finalizer( decoder->cf2_instance.data );
+ FT_FREE( decoder->cf2_instance.data );
+ }
}
diff --git a/thirdparty/freetype/src/psaux/t1decode.h b/thirdparty/freetype/src/psaux/t1decode.h
index 12c27de775..1d9718d678 100644
--- a/thirdparty/freetype/src/psaux/t1decode.h
+++ b/thirdparty/freetype/src/psaux/t1decode.h
@@ -4,7 +4,7 @@
/* */
/* PostScript Type 1 decoding routines (specification). */
/* */
-/* Copyright 2000-2017 by */
+/* Copyright 2000-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -31,7 +31,11 @@ FT_BEGIN_HEADER
FT_CALLBACK_TABLE
const T1_Decoder_FuncsRec t1_decoder_funcs;
+ FT_LOCAL( FT_Int )
+ t1_lookup_glyph_by_stdcharcode_ps( PS_Decoder* decoder,
+ FT_Int charcode );
+#ifdef T1_CONFIG_OPTION_OLD_ENGINE
FT_LOCAL( FT_Error )
t1_decoder_parse_glyph( T1_Decoder decoder,
FT_UInt glyph_index );
@@ -40,6 +44,12 @@ FT_BEGIN_HEADER
t1_decoder_parse_charstrings( T1_Decoder decoder,
FT_Byte* base,
FT_UInt len );
+#else
+ FT_LOCAL( FT_Error )
+ t1_decoder_parse_metrics( T1_Decoder decoder,
+ FT_Byte* charstring_base,
+ FT_UInt charstring_len );
+#endif
FT_LOCAL( FT_Error )
t1_decoder_init( T1_Decoder decoder,
diff --git a/thirdparty/freetype/src/pshinter/module.mk b/thirdparty/freetype/src/pshinter/module.mk
index 77e35c4c10..06707be3b4 100644
--- a/thirdparty/freetype/src/pshinter/module.mk
+++ b/thirdparty/freetype/src/pshinter/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2017 by
+# Copyright 1996-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/pshinter/pshalgo.c b/thirdparty/freetype/src/pshinter/pshalgo.c
index 9ad1a3a02a..b98077c62e 100644
--- a/thirdparty/freetype/src/pshinter/pshalgo.c
+++ b/thirdparty/freetype/src/pshinter/pshalgo.c
@@ -4,7 +4,7 @@
/* */
/* PostScript hinting algorithm (body). */
/* */
-/* Copyright 2001-2017 by */
+/* Copyright 2001-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used */
@@ -26,7 +26,7 @@
#undef FT_COMPONENT
-#define FT_COMPONENT trace_pshalgo2
+#define FT_COMPONENT trace_pshalgo
#ifdef DEBUG_HINTER
diff --git a/thirdparty/freetype/src/pshinter/pshalgo.h b/thirdparty/freetype/src/pshinter/pshalgo.h
index 62e97d152b..c50683fbec 100644
--- a/thirdparty/freetype/src/pshinter/pshalgo.h
+++ b/thirdparty/freetype/src/pshinter/pshalgo.h
@@ -4,7 +4,7 @@
/* */
/* PostScript hinting algorithm (specification). */
/* */
-/* Copyright 2001-2017 by */
+/* Copyright 2001-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/pshinter/pshglob.c b/thirdparty/freetype/src/pshinter/pshglob.c
index c68770c73a..accc04921d 100644
--- a/thirdparty/freetype/src/pshinter/pshglob.c
+++ b/thirdparty/freetype/src/pshinter/pshglob.c
@@ -5,7 +5,7 @@
/* PostScript hinter global hinting management (body). */
/* Inspired by the new auto-hinter module. */
/* */
-/* Copyright 2001-2017 by */
+/* Copyright 2001-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used */
@@ -227,8 +227,8 @@
}
- /* Re-read blue zones from the original fonts and store them into out */
- /* private structure. This function re-orders, sanitizes and */
+ /* Re-read blue zones from the original fonts and store them into our */
+ /* private structure. This function re-orders, sanitizes, and */
/* fuzz-expands the zones as well. */
static void
psh_blues_set_zones( PSH_Blues target,
diff --git a/thirdparty/freetype/src/pshinter/pshglob.h b/thirdparty/freetype/src/pshinter/pshglob.h
index 8801cbada4..cf80bf40e6 100644
--- a/thirdparty/freetype/src/pshinter/pshglob.h
+++ b/thirdparty/freetype/src/pshinter/pshglob.h
@@ -4,7 +4,7 @@
/* */
/* PostScript hinter global hinting management. */
/* */
-/* Copyright 2001-2017 by */
+/* Copyright 2001-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/pshinter/pshinter.c b/thirdparty/freetype/src/pshinter/pshinter.c
index 13e07e1485..0eedac452d 100644
--- a/thirdparty/freetype/src/pshinter/pshinter.c
+++ b/thirdparty/freetype/src/pshinter/pshinter.c
@@ -4,7 +4,7 @@
/* */
/* FreeType PostScript Hinting module */
/* */
-/* Copyright 2001-2017 by */
+/* Copyright 2001-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/pshinter/pshmod.c b/thirdparty/freetype/src/pshinter/pshmod.c
index 860dc0ae82..0b8f6f99b8 100644
--- a/thirdparty/freetype/src/pshinter/pshmod.c
+++ b/thirdparty/freetype/src/pshinter/pshmod.c
@@ -4,7 +4,7 @@
/* */
/* FreeType PostScript hinter module implementation (body). */
/* */
-/* Copyright 2001-2017 by */
+/* Copyright 2001-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/pshinter/pshmod.h b/thirdparty/freetype/src/pshinter/pshmod.h
index 1d2b40fa13..556de2fbc0 100644
--- a/thirdparty/freetype/src/pshinter/pshmod.h
+++ b/thirdparty/freetype/src/pshinter/pshmod.h
@@ -4,7 +4,7 @@
/* */
/* PostScript hinter module interface (specification). */
/* */
-/* Copyright 2001-2017 by */
+/* Copyright 2001-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/pshinter/pshnterr.h b/thirdparty/freetype/src/pshinter/pshnterr.h
index 73d144e34c..b9d02d2956 100644
--- a/thirdparty/freetype/src/pshinter/pshnterr.h
+++ b/thirdparty/freetype/src/pshinter/pshnterr.h
@@ -4,7 +4,7 @@
/* */
/* PS Hinter error codes (specification only). */
/* */
-/* Copyright 2003-2017 by */
+/* Copyright 2003-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/pshinter/pshpic.c b/thirdparty/freetype/src/pshinter/pshpic.c
index c0d3a64f29..465ad31885 100644
--- a/thirdparty/freetype/src/pshinter/pshpic.c
+++ b/thirdparty/freetype/src/pshinter/pshpic.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for pshinter module. */
/* */
-/* Copyright 2009-2017 by */
+/* Copyright 2009-2018 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/pshinter/pshpic.h b/thirdparty/freetype/src/pshinter/pshpic.h
index 8d9a01c9c5..4469ba87c8 100644
--- a/thirdparty/freetype/src/pshinter/pshpic.h
+++ b/thirdparty/freetype/src/pshinter/pshpic.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for pshinter module. */
/* */
-/* Copyright 2009-2017 by */
+/* Copyright 2009-2018 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/pshinter/pshrec.c b/thirdparty/freetype/src/pshinter/pshrec.c
index fff6d34250..6648d13d60 100644
--- a/thirdparty/freetype/src/pshinter/pshrec.c
+++ b/thirdparty/freetype/src/pshinter/pshrec.c
@@ -4,7 +4,7 @@
/* */
/* FreeType PostScript hints recorder (body). */
/* */
-/* Copyright 2001-2017 by */
+/* Copyright 2001-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/pshinter/pshrec.h b/thirdparty/freetype/src/pshinter/pshrec.h
index e10bc2b120..7e3dfe0d53 100644
--- a/thirdparty/freetype/src/pshinter/pshrec.h
+++ b/thirdparty/freetype/src/pshinter/pshrec.h
@@ -4,7 +4,7 @@
/* */
/* Postscript (Type1/Type2) hints recorder (specification). */
/* */
-/* Copyright 2001-2017 by */
+/* Copyright 2001-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/pshinter/rules.mk b/thirdparty/freetype/src/pshinter/rules.mk
index 2be6404380..966690efc2 100644
--- a/thirdparty/freetype/src/pshinter/rules.mk
+++ b/thirdparty/freetype/src/pshinter/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 2001-2017 by
+# Copyright 2001-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/psnames/module.mk b/thirdparty/freetype/src/psnames/module.mk
index ddd22960c1..410f48a191 100644
--- a/thirdparty/freetype/src/psnames/module.mk
+++ b/thirdparty/freetype/src/psnames/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2017 by
+# Copyright 1996-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/psnames/psmodule.c b/thirdparty/freetype/src/psnames/psmodule.c
index 44ba9ec6ab..8929ebe751 100644
--- a/thirdparty/freetype/src/psnames/psmodule.c
+++ b/thirdparty/freetype/src/psnames/psmodule.c
@@ -4,7 +4,7 @@
/* */
/* PSNames module implementation (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/psnames/psmodule.h b/thirdparty/freetype/src/psnames/psmodule.h
index 6983b79234..3e94f8b437 100644
--- a/thirdparty/freetype/src/psnames/psmodule.h
+++ b/thirdparty/freetype/src/psnames/psmodule.h
@@ -4,7 +4,7 @@
/* */
/* High-level PSNames module interface (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/psnames/psnamerr.h b/thirdparty/freetype/src/psnames/psnamerr.h
index f90bf5ea43..14eb76c99c 100644
--- a/thirdparty/freetype/src/psnames/psnamerr.h
+++ b/thirdparty/freetype/src/psnames/psnamerr.h
@@ -4,7 +4,7 @@
/* */
/* PS names module error codes (specification only). */
/* */
-/* Copyright 2001-2017 by */
+/* Copyright 2001-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/psnames/psnames.c b/thirdparty/freetype/src/psnames/psnames.c
index 22466d6230..febb80d594 100644
--- a/thirdparty/freetype/src/psnames/psnames.c
+++ b/thirdparty/freetype/src/psnames/psnames.c
@@ -4,7 +4,7 @@
/* */
/* FreeType PSNames module component (body only). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/psnames/pspic.c b/thirdparty/freetype/src/psnames/pspic.c
index 8b9003439b..85a06f3603 100644
--- a/thirdparty/freetype/src/psnames/pspic.c
+++ b/thirdparty/freetype/src/psnames/pspic.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for psnames module. */
/* */
-/* Copyright 2009-2017 by */
+/* Copyright 2009-2018 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/psnames/pspic.h b/thirdparty/freetype/src/psnames/pspic.h
index 14497e73fa..889780cc03 100644
--- a/thirdparty/freetype/src/psnames/pspic.h
+++ b/thirdparty/freetype/src/psnames/pspic.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for psnames module. */
/* */
-/* Copyright 2009-2017 by */
+/* Copyright 2009-2018 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/psnames/pstables.h b/thirdparty/freetype/src/psnames/pstables.h
index 2a2b717d8f..79545ee039 100644
--- a/thirdparty/freetype/src/psnames/pstables.h
+++ b/thirdparty/freetype/src/psnames/pstables.h
@@ -4,7 +4,7 @@
/* */
/* PostScript glyph names. */
/* */
-/* Copyright 2005-2017 by */
+/* Copyright 2005-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/psnames/rules.mk b/thirdparty/freetype/src/psnames/rules.mk
index 69fa732200..4d629d841c 100644
--- a/thirdparty/freetype/src/psnames/rules.mk
+++ b/thirdparty/freetype/src/psnames/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2017 by
+# Copyright 1996-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/raster/ftmisc.h b/thirdparty/freetype/src/raster/ftmisc.h
index d1e6627ab4..7e40119071 100644
--- a/thirdparty/freetype/src/raster/ftmisc.h
+++ b/thirdparty/freetype/src/raster/ftmisc.h
@@ -5,7 +5,7 @@
/* Miscellaneous macros for stand-alone rasterizer (specification */
/* only). */
/* */
-/* Copyright 2005-2017 by */
+/* Copyright 2005-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used */
diff --git a/thirdparty/freetype/src/raster/ftraster.c b/thirdparty/freetype/src/raster/ftraster.c
index c5643f6334..4354730d54 100644
--- a/thirdparty/freetype/src/raster/ftraster.c
+++ b/thirdparty/freetype/src/raster/ftraster.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType glyph rasterizer (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/raster/ftraster.h b/thirdparty/freetype/src/raster/ftraster.h
index 6b3050cb3d..40b5d6d321 100644
--- a/thirdparty/freetype/src/raster/ftraster.h
+++ b/thirdparty/freetype/src/raster/ftraster.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType glyph rasterizer (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used */
diff --git a/thirdparty/freetype/src/raster/ftrend1.c b/thirdparty/freetype/src/raster/ftrend1.c
index 185a7f6fc2..a7ce9731d7 100644
--- a/thirdparty/freetype/src/raster/ftrend1.c
+++ b/thirdparty/freetype/src/raster/ftrend1.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType glyph rasterizer interface (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -97,12 +97,12 @@
FT_Render_Mode mode,
const FT_Vector* origin )
{
- FT_Error error;
- FT_Outline* outline;
- FT_BBox cbox, cbox0;
- FT_UInt width, height, pitch;
- FT_Bitmap* bitmap;
- FT_Memory memory;
+ FT_Error error = FT_Err_Ok;
+ FT_Outline* outline = &slot->outline;
+ FT_Bitmap* bitmap = &slot->bitmap;
+ FT_Memory memory = render->root.memory;
+ FT_Pos x_shift = 0;
+ FT_Pos y_shift = 0;
FT_Raster_Params params;
@@ -121,60 +121,6 @@
return FT_THROW( Cannot_Render_Glyph );
}
- outline = &slot->outline;
-
- /* translate the outline to the new origin if needed */
- if ( origin )
- FT_Outline_Translate( outline, origin->x, origin->y );
-
- /* compute the control box, and grid fit it */
- FT_Outline_Get_CBox( outline, &cbox0 );
-
- /* undocumented but confirmed: bbox values get rounded */
-#if 1
- cbox.xMin = FT_PIX_ROUND( cbox0.xMin );
- cbox.yMin = FT_PIX_ROUND( cbox0.yMin );
- cbox.xMax = FT_PIX_ROUND( cbox0.xMax );
- cbox.yMax = FT_PIX_ROUND( cbox0.yMax );
-#else
- cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
- cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
- cbox.xMax = FT_PIX_CEIL( cbox.xMax );
- cbox.yMax = FT_PIX_CEIL( cbox.yMax );
-#endif
-
- /* If either `width' or `height' round to 0, try */
- /* explicitly rounding up/down. In the case of */
- /* glyphs containing only one very narrow feature, */
- /* this gives the drop-out compensation in the scan */
- /* conversion code a chance to do its stuff. */
- width = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 );
- if ( width == 0 )
- {
- cbox.xMin = FT_PIX_FLOOR( cbox0.xMin );
- cbox.xMax = FT_PIX_CEIL( cbox0.xMax );
-
- width = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 );
- }
-
- height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 );
- if ( height == 0 )
- {
- cbox.yMin = FT_PIX_FLOOR( cbox0.yMin );
- cbox.yMax = FT_PIX_CEIL( cbox0.yMax );
-
- height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 );
- }
-
- if ( width > FT_USHORT_MAX || height > FT_USHORT_MAX )
- {
- error = FT_THROW( Invalid_Argument );
- goto Exit;
- }
-
- bitmap = &slot->bitmap;
- memory = render->root.memory;
-
/* release old bitmap buffer */
if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
{
@@ -182,39 +128,48 @@
slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
}
- pitch = ( ( width + 15 ) >> 4 ) << 1;
- bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
-
- bitmap->width = width;
- bitmap->rows = height;
- bitmap->pitch = (int)pitch;
+ ft_glyphslot_preset_bitmap( slot, mode, origin );
- if ( FT_ALLOC_MULT( bitmap->buffer, height, pitch ) )
+ /* allocate new one */
+ if ( FT_ALLOC_MULT( bitmap->buffer, bitmap->rows, bitmap->pitch ) )
goto Exit;
slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
+ x_shift = -slot->bitmap_left * 64;
+ y_shift = ( (FT_Int)bitmap->rows - slot->bitmap_top ) * 64;
+
+ if ( origin )
+ {
+ x_shift += origin->x;
+ y_shift += origin->y;
+ }
+
/* translate outline to render it into the bitmap */
- FT_Outline_Translate( outline, -cbox.xMin, -cbox.yMin );
+ if ( x_shift || y_shift )
+ FT_Outline_Translate( outline, x_shift, y_shift );
/* set up parameters */
params.target = bitmap;
params.source = outline;
- params.flags = 0;
+ params.flags = FT_RASTER_FLAG_DEFAULT;
/* render outline into the bitmap */
error = render->raster_render( render->raster, &params );
- FT_Outline_Translate( outline, cbox.xMin, cbox.yMin );
-
- if ( error )
- goto Exit;
+ Exit:
+ if ( !error )
+ /* everything is fine; the glyph is now officially a bitmap */
+ slot->format = FT_GLYPH_FORMAT_BITMAP;
+ else if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
+ {
+ FT_FREE( bitmap->buffer );
+ slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
+ }
- slot->format = FT_GLYPH_FORMAT_BITMAP;
- slot->bitmap_left = (FT_Int)( cbox.xMin >> 6 );
- slot->bitmap_top = (FT_Int)( cbox.yMax >> 6 );
+ if ( x_shift || y_shift )
+ FT_Outline_Translate( outline, -x_shift, -y_shift );
- Exit:
return error;
}
diff --git a/thirdparty/freetype/src/raster/ftrend1.h b/thirdparty/freetype/src/raster/ftrend1.h
index cff702d140..2abdf2d703 100644
--- a/thirdparty/freetype/src/raster/ftrend1.h
+++ b/thirdparty/freetype/src/raster/ftrend1.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType glyph rasterizer interface (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/raster/module.mk b/thirdparty/freetype/src/raster/module.mk
index aad39cb56a..b115f416b2 100644
--- a/thirdparty/freetype/src/raster/module.mk
+++ b/thirdparty/freetype/src/raster/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2017 by
+# Copyright 1996-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/raster/raster.c b/thirdparty/freetype/src/raster/raster.c
index 46a6690b17..76edd21e1e 100644
--- a/thirdparty/freetype/src/raster/raster.c
+++ b/thirdparty/freetype/src/raster/raster.c
@@ -4,7 +4,7 @@
/* */
/* FreeType monochrome rasterer module component (body only). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/raster/rasterrs.h b/thirdparty/freetype/src/raster/rasterrs.h
index 0d646908ad..22a3e15340 100644
--- a/thirdparty/freetype/src/raster/rasterrs.h
+++ b/thirdparty/freetype/src/raster/rasterrs.h
@@ -4,7 +4,7 @@
/* */
/* monochrome renderer error codes (specification only). */
/* */
-/* Copyright 2001-2017 by */
+/* Copyright 2001-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/raster/rastpic.c b/thirdparty/freetype/src/raster/rastpic.c
index 7085339b7b..1dc8981b8a 100644
--- a/thirdparty/freetype/src/raster/rastpic.c
+++ b/thirdparty/freetype/src/raster/rastpic.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for raster module. */
/* */
-/* Copyright 2009-2017 by */
+/* Copyright 2009-2018 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/raster/rastpic.h b/thirdparty/freetype/src/raster/rastpic.h
index dcd691310d..6d0877c423 100644
--- a/thirdparty/freetype/src/raster/rastpic.h
+++ b/thirdparty/freetype/src/raster/rastpic.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for raster module. */
/* */
-/* Copyright 2009-2017 by */
+/* Copyright 2009-2018 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/raster/rules.mk b/thirdparty/freetype/src/raster/rules.mk
index 0462c93177..9aef1f0bab 100644
--- a/thirdparty/freetype/src/raster/rules.mk
+++ b/thirdparty/freetype/src/raster/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2017 by
+# Copyright 1996-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/sfnt/module.mk b/thirdparty/freetype/src/sfnt/module.mk
index 81dea17de0..51ca67e784 100644
--- a/thirdparty/freetype/src/sfnt/module.mk
+++ b/thirdparty/freetype/src/sfnt/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2017 by
+# Copyright 1996-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/sfnt/pngshim.c b/thirdparty/freetype/src/sfnt/pngshim.c
index 560db4835a..16020266af 100644
--- a/thirdparty/freetype/src/sfnt/pngshim.c
+++ b/thirdparty/freetype/src/sfnt/pngshim.c
@@ -4,7 +4,7 @@
/* */
/* PNG Bitmap glyph support. */
/* */
-/* Copyright 2013-2017 by */
+/* Copyright 2013-2018 by */
/* Google, Inc. */
/* Written by Stuart Gill and Behdad Esfahbod. */
/* */
@@ -82,42 +82,45 @@
typedef unsigned short v82 __attribute__(( vector_size( 16 ) ));
- /* process blocks of 16 bytes in one rush, which gives a nice speed-up */
- limit = row_info->rowbytes - 16 + 1;
- for ( ; i < limit; i += 16 )
+ if ( row_info->rowbytes > 15 )
{
- unsigned char* base = &data[i];
+ /* process blocks of 16 bytes in one rush, which gives a nice speed-up */
+ limit = row_info->rowbytes - 16 + 1;
+ for ( ; i < limit; i += 16 )
+ {
+ unsigned char* base = &data[i];
- v82 s, s0, s1, a;
+ v82 s, s0, s1, a;
- /* clang <= 3.9 can't apply scalar values to vectors */
- /* (or rather, it needs a different syntax) */
- v82 n0x80 = { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 };
- v82 n0xFF = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
- v82 n8 = { 8, 8, 8, 8, 8, 8, 8, 8 };
+ /* clang <= 3.9 can't apply scalar values to vectors */
+ /* (or rather, it needs a different syntax) */
+ v82 n0x80 = { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 };
+ v82 n0xFF = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+ v82 n8 = { 8, 8, 8, 8, 8, 8, 8, 8 };
- v82 ma = { 1, 1, 3, 3, 5, 5, 7, 7 };
- v82 o1 = { 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF };
- v82 m0 = { 1, 0, 3, 2, 5, 4, 7, 6 };
+ v82 ma = { 1, 1, 3, 3, 5, 5, 7, 7 };
+ v82 o1 = { 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF };
+ v82 m0 = { 1, 0, 3, 2, 5, 4, 7, 6 };
- memcpy( &s, base, 16 ); /* RGBA RGBA RGBA RGBA */
- s0 = s & n0xFF; /* R B R B R B R B */
- s1 = s >> n8; /* G A G A G A G A */
+ ft_memcpy( &s, base, 16 ); /* RGBA RGBA RGBA RGBA */
+ s0 = s & n0xFF; /* R B R B R B R B */
+ s1 = s >> n8; /* G A G A G A G A */
- a = vector_shuffle( s1, ma ); /* A A A A A A A A */
- s1 |= o1; /* G 1 G 1 G 1 G 1 */
- s0 = vector_shuffle( s0, m0 ); /* B R B R B R B R */
+ a = vector_shuffle( s1, ma ); /* A A A A A A A A */
+ s1 |= o1; /* G 1 G 1 G 1 G 1 */
+ s0 = vector_shuffle( s0, m0 ); /* B R B R B R B R */
- s0 *= a;
- s1 *= a;
- s0 += n0x80;
- s1 += n0x80;
- s0 = ( s0 + ( s0 >> n8 ) ) >> n8;
- s1 = ( s1 + ( s1 >> n8 ) ) >> n8;
+ s0 *= a;
+ s1 *= a;
+ s0 += n0x80;
+ s1 += n0x80;
+ s0 = ( s0 + ( s0 >> n8 ) ) >> n8;
+ s1 = ( s1 + ( s1 >> n8 ) ) >> n8;
- s = s0 | ( s1 << n8 );
- memcpy( base, &s, 16 );
+ s = s0 | ( s1 << n8 );
+ ft_memcpy( base, &s, 16 );
+ }
}
#endif /* use `vector_size' */
@@ -234,7 +237,7 @@
return;
}
- memcpy( data, stream->cursor, length );
+ ft_memcpy( data, stream->cursor, length );
FT_FRAME_EXIT();
}
diff --git a/thirdparty/freetype/src/sfnt/pngshim.h b/thirdparty/freetype/src/sfnt/pngshim.h
index 344eceac12..194238c3a2 100644
--- a/thirdparty/freetype/src/sfnt/pngshim.h
+++ b/thirdparty/freetype/src/sfnt/pngshim.h
@@ -4,7 +4,7 @@
/* */
/* PNG Bitmap glyph support. */
/* */
-/* Copyright 2013-2017 by */
+/* Copyright 2013-2018 by */
/* Google, Inc. */
/* Written by Stuart Gill and Behdad Esfahbod. */
/* */
diff --git a/thirdparty/freetype/src/sfnt/rules.mk b/thirdparty/freetype/src/sfnt/rules.mk
index 230d56c946..83acc66a8f 100644
--- a/thirdparty/freetype/src/sfnt/rules.mk
+++ b/thirdparty/freetype/src/sfnt/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2017 by
+# Copyright 1996-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/sfnt/sfdriver.c b/thirdparty/freetype/src/sfnt/sfdriver.c
index 991433ee4c..303e1ca9f1 100644
--- a/thirdparty/freetype/src/sfnt/sfdriver.c
+++ b/thirdparty/freetype/src/sfnt/sfdriver.c
@@ -4,7 +4,7 @@
/* */
/* High-level SFNT driver interface (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -862,7 +862,8 @@
NULL,
&mm_var );
- if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) )
+ if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) &&
+ !FT_IS_VARIATION( FT_FACE( face ) ) )
{
SFNT_Service sfnt = (SFNT_Service)face->sfnt;
@@ -1029,7 +1030,9 @@
return face->postscript_name;
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- if ( face->blend )
+ if ( face->blend &&
+ ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ||
+ FT_IS_VARIATION( FT_FACE( face ) ) ) )
{
face->postscript_name = sfnt_get_var_ps_name( face );
return face->postscript_name;
diff --git a/thirdparty/freetype/src/sfnt/sfdriver.h b/thirdparty/freetype/src/sfnt/sfdriver.h
index 38710b60f2..81c22d2887 100644
--- a/thirdparty/freetype/src/sfnt/sfdriver.h
+++ b/thirdparty/freetype/src/sfnt/sfdriver.h
@@ -4,7 +4,7 @@
/* */
/* High-level SFNT driver interface (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/sfnt/sferrors.h b/thirdparty/freetype/src/sfnt/sferrors.h
index 3cf73d725d..74003d4b38 100644
--- a/thirdparty/freetype/src/sfnt/sferrors.h
+++ b/thirdparty/freetype/src/sfnt/sferrors.h
@@ -4,7 +4,7 @@
/* */
/* SFNT error codes (specification only). */
/* */
-/* Copyright 2001-2017 by */
+/* Copyright 2001-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/sfnt/sfnt.c b/thirdparty/freetype/src/sfnt/sfnt.c
index 6cf8c9ef30..8b9a6b345d 100644
--- a/thirdparty/freetype/src/sfnt/sfnt.c
+++ b/thirdparty/freetype/src/sfnt/sfnt.c
@@ -4,7 +4,7 @@
/* */
/* Single object library component. */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/sfnt/sfntpic.c b/thirdparty/freetype/src/sfnt/sfntpic.c
index 8eadd601fd..db2d816ce6 100644
--- a/thirdparty/freetype/src/sfnt/sfntpic.c
+++ b/thirdparty/freetype/src/sfnt/sfntpic.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for sfnt module. */
/* */
-/* Copyright 2009-2017 by */
+/* Copyright 2009-2018 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/sfnt/sfntpic.h b/thirdparty/freetype/src/sfnt/sfntpic.h
index 3afb668db0..8f43122d81 100644
--- a/thirdparty/freetype/src/sfnt/sfntpic.h
+++ b/thirdparty/freetype/src/sfnt/sfntpic.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for sfnt module. */
/* */
-/* Copyright 2009-2017 by */
+/* Copyright 2009-2018 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/sfnt/sfobjs.c b/thirdparty/freetype/src/sfnt/sfobjs.c
index 69bf0a5c3d..6ba8509f56 100644
--- a/thirdparty/freetype/src/sfnt/sfobjs.c
+++ b/thirdparty/freetype/src/sfnt/sfobjs.c
@@ -4,7 +4,7 @@
/* */
/* SFNT object management (base). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -962,8 +962,6 @@
FT_Byte* instance_values = NULL;
- face->is_default_instance = 1;
-
instance_index = FT_ABS( face_instance_index ) >> 16;
/* test whether current face is a GX font with named instances */
@@ -1146,6 +1144,8 @@
FT_Bool has_outline;
FT_Bool is_apple_sbit;
FT_Bool is_apple_sbix;
+ FT_Bool has_CBLC;
+ FT_Bool has_CBDT;
FT_Bool ignore_typographic_family = FALSE;
FT_Bool ignore_typographic_subfamily = FALSE;
@@ -1226,6 +1226,13 @@
goto Exit;
}
+ has_CBLC = !face->goto_table( face, TTAG_CBLC, stream, 0 );
+ has_CBDT = !face->goto_table( face, TTAG_CBDT, stream, 0 );
+
+ /* Ignore outlines for CBLC/CBDT fonts. */
+ if ( has_CBLC || has_CBDT )
+ has_outline = FALSE;
+
/* OpenType 1.8.2 introduced limits to this value; */
/* however, they make sense for older SFNT fonts also */
if ( face->header.Units_Per_EM < 16 ||
@@ -1686,9 +1693,9 @@
(FT_Short)( face->vertical_info ? face->vertical.advance_Height_Max
: root->height );
- /* See http://www.microsoft.com/OpenType/OTSpec/post.htm -- */
- /* Adjust underline position from top edge to centre of */
- /* stroke to convert TrueType meaning to FreeType meaning. */
+ /* See https://www.microsoft.com/typography/otspec/post.htm -- */
+ /* Adjust underline position from top edge to centre of */
+ /* stroke to convert TrueType meaning to FreeType meaning. */
root->underline_position = face->postscript.underlinePosition -
face->postscript.underlineThickness / 2;
root->underline_thickness = face->postscript.underlineThickness;
diff --git a/thirdparty/freetype/src/sfnt/sfobjs.h b/thirdparty/freetype/src/sfnt/sfobjs.h
index 705381459a..1b8d1be5b1 100644
--- a/thirdparty/freetype/src/sfnt/sfobjs.h
+++ b/thirdparty/freetype/src/sfnt/sfobjs.h
@@ -4,7 +4,7 @@
/* */
/* SFNT object management (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/sfnt/ttbdf.c b/thirdparty/freetype/src/sfnt/ttbdf.c
index 2196e3791e..534201f229 100644
--- a/thirdparty/freetype/src/sfnt/ttbdf.c
+++ b/thirdparty/freetype/src/sfnt/ttbdf.c
@@ -4,7 +4,7 @@
/* */
/* TrueType and OpenType embedded BDF properties (body). */
/* */
-/* Copyright 2005-2017 by */
+/* Copyright 2005-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/sfnt/ttbdf.h b/thirdparty/freetype/src/sfnt/ttbdf.h
index 398b620600..809a663001 100644
--- a/thirdparty/freetype/src/sfnt/ttbdf.h
+++ b/thirdparty/freetype/src/sfnt/ttbdf.h
@@ -4,7 +4,7 @@
/* */
/* TrueType and OpenType embedded BDF properties (specification). */
/* */
-/* Copyright 2005-2017 by */
+/* Copyright 2005-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -28,6 +28,8 @@
FT_BEGIN_HEADER
+#ifdef TT_CONFIG_OPTION_BDF
+
FT_LOCAL( void )
tt_face_free_bdf_props( TT_Face face );
@@ -37,6 +39,8 @@ FT_BEGIN_HEADER
const char* property_name,
BDF_PropertyRec *aprop );
+#endif /* TT_CONFIG_OPTION_BDF */
+
FT_END_HEADER
diff --git a/thirdparty/freetype/src/sfnt/ttcmap.c b/thirdparty/freetype/src/sfnt/ttcmap.c
index b995e5c050..996e66485f 100644
--- a/thirdparty/freetype/src/sfnt/ttcmap.c
+++ b/thirdparty/freetype/src/sfnt/ttcmap.c
@@ -4,7 +4,7 @@
/* */
/* TrueType character mapping table (cmap) support (body). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -222,10 +222,10 @@
/***** The following charmap lookup and iteration functions all *****/
/***** assume that the value `charcode' fulfills the following. *****/
/***** *****/
- /***** - For one byte characters, `charcode' is simply the *****/
+ /***** - For one-byte characters, `charcode' is simply the *****/
/***** character code. *****/
/***** *****/
- /***** - For two byte characters, `charcode' is the 2-byte *****/
+ /***** - For two-byte characters, `charcode' is the 2-byte *****/
/***** character code in big endian format. More precisely: *****/
/***** *****/
/***** (charcode >> 8) is the first byte value *****/
@@ -252,11 +252,11 @@
/* subs 518 SUBHEAD[NSUBS] sub-headers array */
/* glyph_ids 518+NSUB*8 USHORT[] glyph ID array */
/* */
- /* The `keys' table is used to map charcode high-bytes to sub-headers. */
+ /* The `keys' table is used to map charcode high bytes to sub-headers. */
/* The value of `NSUBS' is the number of sub-headers defined in the */
/* table and is computed by finding the maximum of the `keys' table. */
/* */
- /* Note that for any n, `keys[n]' is a byte offset within the `subs' */
+ /* Note that for any `n', `keys[n]' is a byte offset within the `subs' */
/* table, i.e., it is the corresponding sub-header index multiplied */
/* by 8. */
/* */
@@ -269,8 +269,8 @@
/* delta 4 SHORT see below */
/* offset 6 USHORT see below */
/* */
- /* A sub-header defines, for each high-byte, the range of valid */
- /* low-bytes within the charmap. Note that the range defined by `first' */
+ /* A sub-header defines, for each high byte, the range of valid */
+ /* low bytes within the charmap. Note that the range defined by `first' */
/* and `count' must be completely included in the interval [0..255] */
/* according to the specification. */
/* */
@@ -360,7 +360,7 @@
/* check range within 0..255 */
if ( valid->level >= FT_VALIDATE_PARANOID )
{
- if ( first_code >= 256 || first_code + code_count > 256 )
+ if ( first_code >= 256 || code_count > 256 - first_code )
FT_INVALID_DATA;
}
@@ -412,7 +412,7 @@
{
FT_UInt char_lo = (FT_UInt)( char_code & 0xFF );
FT_UInt char_hi = (FT_UInt)( char_code >> 8 );
- FT_Byte* p = table + 6; /* keys table */
+ FT_Byte* p = table + 6; /* keys table */
FT_Byte* subs = table + 518; /* subheaders table */
FT_Byte* sub;
@@ -425,8 +425,8 @@
sub = subs; /* jump to first sub-header */
/* check that the sub-header for this byte is 0, which */
- /* indicates that it is really a valid one-byte value */
- /* Otherwise, return 0 */
+ /* indicates that it is really a valid one-byte value; */
+ /* otherwise, return 0 */
/* */
p += char_lo * 2;
if ( TT_PEEK_USHORT( p ) != 0 )
@@ -445,6 +445,7 @@
if ( sub == subs )
goto Exit;
}
+
result = sub;
}
@@ -517,8 +518,19 @@
FT_UInt pos, idx;
+ if ( char_lo >= start + count && charcode <= 0xFF )
+ {
+ /* this happens only for a malformed cmap */
+ charcode = 0x100;
+ continue;
+ }
+
if ( offset == 0 )
+ {
+ if ( charcode == 0x100 )
+ goto Exit; /* this happens only for a malformed cmap */
goto Next_SubHeader;
+ }
if ( char_lo < start )
{
@@ -545,11 +557,20 @@
}
}
}
+
+ /* if unsuccessful, avoid `charcode' leaving */
+ /* the current 256-character block */
+ if ( count )
+ charcode--;
}
- /* jump to next sub-header, i.e. higher byte value */
+ /* If `charcode' is <= 0xFF, retry with `charcode + 1'. */
+ /* Otherwise jump to the next 256-character block and retry. */
Next_SubHeader:
- charcode = FT_PAD_FLOOR( charcode, 256 ) + 256;
+ if ( charcode <= 0xFF )
+ charcode++;
+ else
+ charcode = FT_PAD_FLOOR( charcode, 0x100 ) + 0x100;
}
Exit:
diff --git a/thirdparty/freetype/src/sfnt/ttcmap.h b/thirdparty/freetype/src/sfnt/ttcmap.h
index f7de0437b0..d264d99d2c 100644
--- a/thirdparty/freetype/src/sfnt/ttcmap.h
+++ b/thirdparty/freetype/src/sfnt/ttcmap.h
@@ -4,7 +4,7 @@
/* */
/* TrueType character mapping table (cmap) support (specification). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/sfnt/ttcmapc.h b/thirdparty/freetype/src/sfnt/ttcmapc.h
index 9a5e70825e..4980e9dd3d 100644
--- a/thirdparty/freetype/src/sfnt/ttcmapc.h
+++ b/thirdparty/freetype/src/sfnt/ttcmapc.h
@@ -4,7 +4,7 @@
/* */
/* TT CMAP classes definitions (specification only). */
/* */
-/* Copyright 2009-2017 by */
+/* Copyright 2009-2018 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/sfnt/ttkern.c b/thirdparty/freetype/src/sfnt/ttkern.c
index 53d2436ae5..68f15a2010 100644
--- a/thirdparty/freetype/src/sfnt/ttkern.c
+++ b/thirdparty/freetype/src/sfnt/ttkern.c
@@ -5,7 +5,7 @@
/* Load the basic TrueType kerning table. This doesn't handle */
/* kerning data within the GPOS table at the moment. */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/sfnt/ttkern.h b/thirdparty/freetype/src/sfnt/ttkern.h
index db1a30bdb0..4e45d0964b 100644
--- a/thirdparty/freetype/src/sfnt/ttkern.h
+++ b/thirdparty/freetype/src/sfnt/ttkern.h
@@ -5,7 +5,7 @@
/* Load the basic TrueType kerning table. This doesn't handle */
/* kerning data within the GPOS table at the moment. */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/sfnt/ttload.c b/thirdparty/freetype/src/sfnt/ttload.c
index df99baa53e..a86a546c3d 100644
--- a/thirdparty/freetype/src/sfnt/ttload.c
+++ b/thirdparty/freetype/src/sfnt/ttload.c
@@ -5,7 +5,7 @@
/* Load the basic TrueType tables, i.e., tables that can be either in */
/* TTF or OTF fonts (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -338,7 +338,7 @@
SFNT_HeaderRec sfnt;
FT_Error error;
FT_Memory memory = stream->memory;
- FT_UShort nn, valid_entries;
+ FT_UShort nn, valid_entries = 0;
static const FT_Frame_Field offset_table_fields[] =
{
diff --git a/thirdparty/freetype/src/sfnt/ttload.h b/thirdparty/freetype/src/sfnt/ttload.h
index 296da86ed3..f94be8b7bd 100644
--- a/thirdparty/freetype/src/sfnt/ttload.h
+++ b/thirdparty/freetype/src/sfnt/ttload.h
@@ -5,7 +5,7 @@
/* Load the basic TrueType tables, i.e., tables that can be either in */
/* TTF or OTF fonts (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/sfnt/ttmtx.c b/thirdparty/freetype/src/sfnt/ttmtx.c
index 394c6db85c..6ddda95b56 100644
--- a/thirdparty/freetype/src/sfnt/ttmtx.c
+++ b/thirdparty/freetype/src/sfnt/ttmtx.c
@@ -4,7 +4,7 @@
/* */
/* Load the metrics tables common to TTF and OTF fonts (body). */
/* */
-/* Copyright 2006-2017 by */
+/* Copyright 2006-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/sfnt/ttmtx.h b/thirdparty/freetype/src/sfnt/ttmtx.h
index 2b93ab2f0e..ab00acd795 100644
--- a/thirdparty/freetype/src/sfnt/ttmtx.h
+++ b/thirdparty/freetype/src/sfnt/ttmtx.h
@@ -4,7 +4,7 @@
/* */
/* Load the metrics tables common to TTF and OTF fonts (specification). */
/* */
-/* Copyright 2006-2017 by */
+/* Copyright 2006-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/sfnt/ttpost.c b/thirdparty/freetype/src/sfnt/ttpost.c
index 69929c8d45..6de99ef977 100644
--- a/thirdparty/freetype/src/sfnt/ttpost.c
+++ b/thirdparty/freetype/src/sfnt/ttpost.c
@@ -5,7 +5,7 @@
/* PostScript name table processing for TrueType and OpenType fonts */
/* (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -473,8 +473,8 @@
/* idx :: The glyph index. */
/* */
/* <InOut> */
- /* PSname :: The address of a string pointer. Will be NULL in case */
- /* of error, otherwise it is a pointer to the glyph name. */
+ /* PSname :: The address of a string pointer. Undefined in case of */
+ /* error, otherwise it is a pointer to the glyph name. */
/* */
/* You must not modify the returned string! */
/* */
diff --git a/thirdparty/freetype/src/sfnt/ttpost.h b/thirdparty/freetype/src/sfnt/ttpost.h
index 722485e32d..3bec07e445 100644
--- a/thirdparty/freetype/src/sfnt/ttpost.h
+++ b/thirdparty/freetype/src/sfnt/ttpost.h
@@ -5,7 +5,7 @@
/* PostScript name table processing for TrueType and OpenType fonts */
/* (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/sfnt/ttsbit.c b/thirdparty/freetype/src/sfnt/ttsbit.c
index f41847b0af..33b8640bc3 100644
--- a/thirdparty/freetype/src/sfnt/ttsbit.c
+++ b/thirdparty/freetype/src/sfnt/ttsbit.c
@@ -4,7 +4,7 @@
/* */
/* TrueType and OpenType embedded bitmap support (body). */
/* */
-/* Copyright 2005-2017 by */
+/* Copyright 2005-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* Copyright 2013 by Google, Inc. */
@@ -1007,8 +1007,9 @@
goto Fail;
}
- FT_TRACE3(( "tt_sbit_decoder_load_compound: loading %d components\n",
- num_components ));
+ FT_TRACE3(( "tt_sbit_decoder_load_compound: loading %d component%s\n",
+ num_components,
+ num_components == 1 ? "" : "s" ));
for ( nn = 0; nn < num_components; nn++ )
{
@@ -1513,7 +1514,7 @@
FT_FRAME_EXIT();
if ( glyph_start == glyph_end )
- return FT_THROW( Invalid_Argument );
+ return FT_THROW( Missing_Bitmap );
if ( glyph_start > glyph_end ||
glyph_end - glyph_start < 8 ||
face->ebdt_size - strike_offset < glyph_end )
diff --git a/thirdparty/freetype/src/sfnt/ttsbit.h b/thirdparty/freetype/src/sfnt/ttsbit.h
index e859ddda45..ce2af3c162 100644
--- a/thirdparty/freetype/src/sfnt/ttsbit.h
+++ b/thirdparty/freetype/src/sfnt/ttsbit.h
@@ -4,7 +4,7 @@
/* */
/* TrueType and OpenType embedded bitmap support (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/smooth/ftgrays.c b/thirdparty/freetype/src/smooth/ftgrays.c
index df645e66c9..803a19e415 100644
--- a/thirdparty/freetype/src/smooth/ftgrays.c
+++ b/thirdparty/freetype/src/smooth/ftgrays.c
@@ -4,7 +4,7 @@
/* */
/* A new `perfect' anti-aliasing renderer (body). */
/* */
-/* Copyright 2000-2017 by */
+/* Copyright 2000-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -370,7 +370,7 @@ typedef ptrdiff_t FT_PtrDist;
/* optimize a division and modulo operation on the same parameters */
/* into a single call to `__aeabi_idivmod'. See */
/* */
- /* http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43721 */
+ /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43721 */
#undef FT_DIV_MOD
#define FT_DIV_MOD( type, dividend, divisor, quotient, remainder ) \
FT_BEGIN_STMNT \
@@ -404,7 +404,7 @@ typedef ptrdiff_t FT_PtrDist;
/* need to define them to "float" or "double" when experimenting with */
/* new algorithms */
- typedef long TPos; /* sub-pixel coordinate */
+ typedef long TPos; /* subpixel coordinate */
typedef int TCoord; /* integer scanline/pixel coordinate */
typedef int TArea; /* cell areas, coordinate products */
@@ -582,8 +582,8 @@ typedef ptrdiff_t FT_PtrDist;
if ( ex < ras.min_ex )
ex = ras.min_ex - 1;
- /* record the current one if it is valid */
- if ( !ras.invalid )
+ /* record the current one if it is valid and substantial */
+ if ( !ras.invalid && ( ras.area || ras.cover ) )
gray_record_cell( RAS_VAR );
ras.area = 0;
@@ -1300,8 +1300,6 @@ typedef ptrdiff_t FT_PtrDist;
int y;
- FT_TRACE7(( "gray_sweep: start\n" ));
-
for ( y = ras.min_ey; y < ras.max_ey; y++ )
{
PCell cell = ras.ycells[y - ras.min_ey];
@@ -1327,8 +1325,6 @@ typedef ptrdiff_t FT_PtrDist;
if ( cover != 0 )
gray_hline( RAS_VAR_ x, y, cover, ras.max_ex - x );
}
-
- FT_TRACE7(( "gray_sweep: end\n" ));
}
@@ -1722,8 +1718,11 @@ typedef ptrdiff_t FT_PtrDist;
if ( !ras.invalid )
gray_record_cell( RAS_VAR );
- FT_TRACE7(( "band [%d..%d]: %d cells\n",
- ras.min_ey, ras.max_ey, ras.num_cells ));
+ FT_TRACE7(( "band [%d..%d]: %d cell%s\n",
+ ras.min_ey,
+ ras.max_ey,
+ ras.num_cells,
+ ras.num_cells == 1 ? "" : "s" ));
}
else
{
@@ -1740,35 +1739,43 @@ typedef ptrdiff_t FT_PtrDist;
static int
gray_convert_glyph( RAS_ARG )
{
+ const TCoord yMin = ras.min_ey;
+ const TCoord yMax = ras.max_ey;
+ const TCoord xMin = ras.min_ex;
+ const TCoord xMax = ras.max_ex;
+
TCell buffer[FT_MAX_GRAY_POOL];
- TCoord band_size = FT_MAX_GRAY_POOL / 8;
- TCoord count = ras.max_ey - ras.min_ey;
- int num_bands;
- TCoord min, max, max_y;
+ size_t height = (size_t)( yMax - yMin );
+ size_t n = FT_MAX_GRAY_POOL / 8;
+ TCoord y;
TCoord bands[32]; /* enough to accommodate bisections */
TCoord* band;
/* set up vertical bands */
- if ( count > band_size )
+ if ( height > n )
{
/* two divisions rounded up */
- num_bands = (int)( ( count + band_size - 1) / band_size );
- band_size = ( count + num_bands - 1 ) / num_bands;
+ n = ( height + n - 1 ) / n;
+ height = ( height + n - 1 ) / n;
}
- min = ras.min_ey;
- max_y = ras.max_ey;
+ /* memory management */
+ n = ( height * sizeof ( PCell ) + sizeof ( TCell ) - 1 ) / sizeof ( TCell );
- for ( ; min < max_y; min = max )
+ ras.cells = buffer + n;
+ ras.max_cells = (FT_PtrDist)( FT_MAX_GRAY_POOL - n );
+ ras.ycells = (PCell*)buffer;
+
+ for ( y = yMin; y < yMax; )
{
- max = min + band_size;
- if ( max > max_y )
- max = max_y;
+ ras.min_ey = y;
+ y += height;
+ ras.max_ey = FT_MIN( y, yMax );
band = bands;
- band[1] = min;
- band[0] = max;
+ band[1] = xMin;
+ band[0] = xMax;
do
{
@@ -1776,27 +1783,12 @@ typedef ptrdiff_t FT_PtrDist;
int error;
- /* memory management */
- {
- size_t ycount = (size_t)width;
- size_t cell_start;
-
-
- cell_start = ( ycount * sizeof ( PCell ) + sizeof ( TCell ) - 1 ) /
- sizeof ( TCell );
-
- ras.cells = buffer + cell_start;
- ras.max_cells = (FT_PtrDist)( FT_MAX_GRAY_POOL - cell_start );
- ras.num_cells = 0;
-
- ras.ycells = (PCell*)buffer;
- while ( ycount )
- ras.ycells[--ycount] = NULL;
- }
+ FT_MEM_ZERO( ras.ycells, height * sizeof ( PCell ) );
+ ras.num_cells = 0;
ras.invalid = 1;
- ras.min_ey = band[1];
- ras.max_ey = band[0];
+ ras.min_ex = band[1];
+ ras.max_ex = band[0];
error = gray_convert_glyph_inner( RAS_VAR );
@@ -1812,8 +1804,7 @@ typedef ptrdiff_t FT_PtrDist;
/* render pool overflow; we will reduce the render band by half */
width >>= 1;
- /* This is too complex for a single scanline; there must */
- /* be some problems. */
+ /* this should never happen even with tiny rendering pool */
if ( width == 0 )
{
FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" ));
diff --git a/thirdparty/freetype/src/smooth/ftgrays.h b/thirdparty/freetype/src/smooth/ftgrays.h
index a5447da1a9..9e11ca675e 100644
--- a/thirdparty/freetype/src/smooth/ftgrays.h
+++ b/thirdparty/freetype/src/smooth/ftgrays.h
@@ -4,7 +4,7 @@
/* */
/* FreeType smooth renderer declaration */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/smooth/ftsmerrs.h b/thirdparty/freetype/src/smooth/ftsmerrs.h
index a528c61832..226dc1b001 100644
--- a/thirdparty/freetype/src/smooth/ftsmerrs.h
+++ b/thirdparty/freetype/src/smooth/ftsmerrs.h
@@ -4,7 +4,7 @@
/* */
/* smooth renderer error codes (specification only). */
/* */
-/* Copyright 2001-2017 by */
+/* Copyright 2001-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/smooth/ftsmooth.c b/thirdparty/freetype/src/smooth/ftsmooth.c
index 963435de15..ef176bdf1e 100644
--- a/thirdparty/freetype/src/smooth/ftsmooth.c
+++ b/thirdparty/freetype/src/smooth/ftsmooth.c
@@ -4,7 +4,7 @@
/* */
/* Anti-aliasing renderer interface (body). */
/* */
-/* Copyright 2000-2017 by */
+/* Copyright 2000-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -97,74 +97,17 @@
const FT_Vector* origin,
FT_Render_Mode required_mode )
{
- FT_Error error;
+ FT_Error error = FT_Err_Ok;
FT_Outline* outline = &slot->outline;
FT_Bitmap* bitmap = &slot->bitmap;
FT_Memory memory = render->root.memory;
- FT_BBox cbox;
FT_Pos x_shift = 0;
FT_Pos y_shift = 0;
- FT_Pos x_left, y_top;
- FT_Pos width, height, pitch;
FT_Int hmul = ( mode == FT_RENDER_MODE_LCD );
FT_Int vmul = ( mode == FT_RENDER_MODE_LCD_V );
FT_Raster_Params params;
- FT_Bool have_outline_shifted = FALSE;
- FT_Bool have_buffer = FALSE;
-
-#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
-
- FT_LcdFiveTapFilter lcd_weights = { 0 };
- FT_Bool have_custom_weight = FALSE;
- FT_Bitmap_LcdFilterFunc lcd_filter_func = NULL;
-
-
- if ( slot->face )
- {
- FT_Char i;
-
-
- for ( i = 0; i < FT_LCD_FILTER_FIVE_TAPS; i++ )
- if ( slot->face->internal->lcd_weights[i] != 0 )
- {
- have_custom_weight = TRUE;
- break;
- }
- }
-
- /*
- * The LCD filter can be set library-wide and per-face. Face overrides
- * library. If the face filter weights are all zero (the default), it
- * means that the library default should be used.
- */
- if ( have_custom_weight )
- {
- /*
- * A per-font filter is set. It always uses the default 5-tap
- * in-place FIR filter.
- */
- ft_memcpy( lcd_weights,
- slot->face->internal->lcd_weights,
- FT_LCD_FILTER_FIVE_TAPS );
- lcd_filter_func = ft_lcd_filter_fir;
- }
- else
- {
- /*
- * The face's lcd_weights is {0, 0, 0, 0, 0}, meaning `use library
- * default'. If the library is set to use no LCD filtering
- * (lcd_filter_func == NULL), `lcd_filter_func' here is also set to
- * NULL and the tests further below pass over the filtering process.
- */
- ft_memcpy( lcd_weights,
- slot->library->lcd_weights,
- FT_LCD_FILTER_FIVE_TAPS );
- lcd_filter_func = slot->library->lcd_filter_func;
- }
-
-#endif /*FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
/* check glyph image format */
if ( slot->format != render->glyph_format )
@@ -180,100 +123,6 @@
goto Exit;
}
- if ( origin )
- {
- x_shift = origin->x;
- y_shift = origin->y;
- }
-
- /* compute the control box, and grid fit it */
- /* taking into account the origin shift */
- FT_Outline_Get_CBox( outline, &cbox );
-
-#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
-
- /* add minimal padding for LCD rendering */
- if ( hmul )
- {
- cbox.xMax += 21;
- cbox.xMin -= 21;
- }
-
- if ( vmul )
- {
- cbox.yMax += 21;
- cbox.yMin -= 21;
- }
-
-#else /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
-
- /* add minimal padding for LCD filter depending on specific weights */
- if ( lcd_filter_func )
- {
- if ( hmul )
- {
- cbox.xMax += lcd_weights[4] ? 43
- : lcd_weights[3] ? 22 : 0;
- cbox.xMin -= lcd_weights[0] ? 43
- : lcd_weights[1] ? 22 : 0;
- }
-
- if ( vmul )
- {
- cbox.yMax += lcd_weights[4] ? 43
- : lcd_weights[3] ? 22 : 0;
- cbox.yMin -= lcd_weights[0] ? 43
- : lcd_weights[1] ? 22 : 0;
- }
- }
-
-#endif /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
-
- cbox.xMin = FT_PIX_FLOOR( cbox.xMin + x_shift );
- cbox.yMin = FT_PIX_FLOOR( cbox.yMin + y_shift );
- cbox.xMax = FT_PIX_CEIL( cbox.xMax + x_shift );
- cbox.yMax = FT_PIX_CEIL( cbox.yMax + y_shift );
-
- x_shift -= cbox.xMin;
- y_shift -= cbox.yMin;
-
- x_left = cbox.xMin >> 6;
- y_top = cbox.yMax >> 6;
-
- width = (FT_ULong)( cbox.xMax - cbox.xMin ) >> 6;
- height = (FT_ULong)( cbox.yMax - cbox.yMin ) >> 6;
-
- pitch = width;
- if ( hmul )
- {
- width *= 3;
- pitch = FT_PAD_CEIL( width, 4 );
- }
-
- if ( vmul )
- height *= 3;
-
- /*
- * XXX: on 16bit system, we return an error for huge bitmap
- * to prevent an overflow.
- */
- if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX ||
- x_left < FT_INT_MIN || y_top < FT_INT_MIN )
- {
- error = FT_THROW( Invalid_Pixel_Size );
- goto Exit;
- }
-
- /* Required check is (pitch * height < FT_ULONG_MAX), */
- /* but we care realistic cases only. Always pitch <= width. */
- if ( width > 0x7FFF || height > 0x7FFF )
- {
- FT_ERROR(( "ft_smooth_render_generic: glyph too large: %u x %u\n",
- width, height ));
- error = FT_THROW( Raster_Overflow );
- goto Exit;
- }
-
/* release old bitmap buffer */
if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
{
@@ -281,30 +130,30 @@
slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
}
+ ft_glyphslot_preset_bitmap( slot, mode, origin );
+
/* allocate new one */
- if ( FT_ALLOC( bitmap->buffer, (FT_ULong)( pitch * height ) ) )
+ if ( FT_ALLOC_MULT( bitmap->buffer, bitmap->rows, bitmap->pitch ) )
goto Exit;
- else
- have_buffer = TRUE;
slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
- slot->format = FT_GLYPH_FORMAT_BITMAP;
- slot->bitmap_left = (FT_Int)x_left;
- slot->bitmap_top = (FT_Int)y_top;
+ x_shift = 64 * -slot->bitmap_left;
+ y_shift = 64 * -slot->bitmap_top;
+ if ( bitmap->pixel_mode == FT_PIXEL_MODE_LCD_V )
+ y_shift += 64 * (FT_Int)bitmap->rows / 3;
+ else
+ y_shift += 64 * (FT_Int)bitmap->rows;
- bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
- bitmap->num_grays = 256;
- bitmap->width = (unsigned int)width;
- bitmap->rows = (unsigned int)height;
- bitmap->pitch = pitch;
+ if ( origin )
+ {
+ x_shift += origin->x;
+ y_shift += origin->y;
+ }
/* translate outline to render it into the bitmap */
if ( x_shift || y_shift )
- {
FT_Outline_Translate( outline, x_shift, y_shift );
- have_outline_shifted = TRUE;
- }
/* set up parameters */
params.target = bitmap;
@@ -351,45 +200,68 @@
if ( error )
goto Exit;
- if ( lcd_filter_func )
- lcd_filter_func( bitmap, mode, lcd_weights );
+ /* finally apply filtering */
+ if ( hmul || vmul )
+ {
+ FT_Byte* lcd_weights;
+ FT_Bitmap_LcdFilterFunc lcd_filter_func;
+
+
+ /* Per-face LCD filtering takes priority if set up. */
+ if ( slot->face && slot->face->internal->lcd_filter_func )
+ {
+ lcd_weights = slot->face->internal->lcd_weights;
+ lcd_filter_func = slot->face->internal->lcd_filter_func;
+ }
+ else
+ {
+ lcd_weights = slot->library->lcd_weights;
+ lcd_filter_func = slot->library->lcd_filter_func;
+ }
+
+ if ( lcd_filter_func )
+ lcd_filter_func( bitmap, mode, lcd_weights );
+ }
#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
if ( hmul ) /* lcd */
{
FT_Byte* line;
- FT_Byte* temp;
- FT_Int i, j;
+ FT_Byte* temp = NULL;
+ FT_UInt i, j;
+
+ unsigned int height = bitmap->rows;
+ unsigned int width = bitmap->width;
+ int pitch = bitmap->pitch;
/* Render 3 separate monochrome bitmaps, shifting the outline */
/* by 1/3 pixel. */
width /= 3;
- FT_Outline_Translate( outline, 21, 0 );
+ bitmap->buffer += width;
error = render->raster_render( render->raster, &params );
if ( error )
goto Exit;
FT_Outline_Translate( outline, -21, 0 );
+ x_shift -= 21;
bitmap->buffer += width;
error = render->raster_render( render->raster, &params );
if ( error )
goto Exit;
- FT_Outline_Translate( outline, -21, 0 );
- bitmap->buffer += width;
+ FT_Outline_Translate( outline, 42, 0 );
+ x_shift += 42;
+ bitmap->buffer -= 2 * width;
error = render->raster_render( render->raster, &params );
if ( error )
goto Exit;
- FT_Outline_Translate( outline, 21, 0 );
- bitmap->buffer -= 2 * width;
-
/* XXX: Rearrange the bytes according to FT_PIXEL_MODE_LCD. */
/* XXX: It is more efficient to render every third byte above. */
@@ -398,7 +270,7 @@
for ( i = 0; i < height; i++ )
{
- line = bitmap->buffer + i * pitch;
+ line = bitmap->buffer + i * (FT_ULong)pitch;
for ( j = 0; j < width; j++ )
{
temp[3 * j ] = line[j];
@@ -412,60 +284,59 @@
}
else if ( vmul ) /* lcd_v */
{
+ int pitch = bitmap->pitch;
+
+
/* Render 3 separate monochrome bitmaps, shifting the outline */
/* by 1/3 pixel. Triple the pitch to render on each third row. */
bitmap->pitch *= 3;
bitmap->rows /= 3;
- FT_Outline_Translate( outline, 0, 21 );
- bitmap->buffer += 2 * pitch;
+ bitmap->buffer += pitch;
error = render->raster_render( render->raster, &params );
if ( error )
goto Exit;
- FT_Outline_Translate( outline, 0, -21 );
- bitmap->buffer -= pitch;
+ FT_Outline_Translate( outline, 0, 21 );
+ y_shift += 21;
+ bitmap->buffer += pitch;
error = render->raster_render( render->raster, &params );
if ( error )
goto Exit;
- FT_Outline_Translate( outline, 0, -21 );
- bitmap->buffer -= pitch;
+ FT_Outline_Translate( outline, 0, -42 );
+ y_shift -= 42;
+ bitmap->buffer -= 2 * pitch;
error = render->raster_render( render->raster, &params );
if ( error )
goto Exit;
- FT_Outline_Translate( outline, 0, 21 );
-
bitmap->pitch /= 3;
bitmap->rows *= 3;
}
else /* grayscale */
- {
error = render->raster_render( render->raster, &params );
- if ( error )
- goto Exit;
- }
#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
- /* everything is fine; don't deallocate buffer */
- have_buffer = FALSE;
-
- error = FT_Err_Ok;
-
Exit:
- if ( have_outline_shifted )
- FT_Outline_Translate( outline, -x_shift, -y_shift );
- if ( have_buffer )
+ if ( !error )
+ {
+ /* everything is fine; the glyph is now officially a bitmap */
+ slot->format = FT_GLYPH_FORMAT_BITMAP;
+ }
+ else if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
{
FT_FREE( bitmap->buffer );
slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
}
+ if ( x_shift || y_shift )
+ FT_Outline_Translate( outline, -x_shift, -y_shift );
+
return error;
}
@@ -492,14 +363,8 @@
FT_Render_Mode mode,
const FT_Vector* origin )
{
- FT_Error error;
-
- error = ft_smooth_render_generic( render, slot, mode, origin,
- FT_RENDER_MODE_LCD );
- if ( !error )
- slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD;
-
- return error;
+ return ft_smooth_render_generic( render, slot, mode, origin,
+ FT_RENDER_MODE_LCD );
}
@@ -510,14 +375,8 @@
FT_Render_Mode mode,
const FT_Vector* origin )
{
- FT_Error error;
-
- error = ft_smooth_render_generic( render, slot, mode, origin,
- FT_RENDER_MODE_LCD_V );
- if ( !error )
- slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD_V;
-
- return error;
+ return ft_smooth_render_generic( render, slot, mode, origin,
+ FT_RENDER_MODE_LCD_V );
}
diff --git a/thirdparty/freetype/src/smooth/ftsmooth.h b/thirdparty/freetype/src/smooth/ftsmooth.h
index 6dfd65726c..c76ffc5034 100644
--- a/thirdparty/freetype/src/smooth/ftsmooth.h
+++ b/thirdparty/freetype/src/smooth/ftsmooth.h
@@ -4,7 +4,7 @@
/* */
/* Anti-aliasing renderer interface (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/smooth/ftspic.c b/thirdparty/freetype/src/smooth/ftspic.c
index fb89be3488..10f04cf4cc 100644
--- a/thirdparty/freetype/src/smooth/ftspic.c
+++ b/thirdparty/freetype/src/smooth/ftspic.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for smooth module. */
/* */
-/* Copyright 2009-2017 by */
+/* Copyright 2009-2018 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/smooth/ftspic.h b/thirdparty/freetype/src/smooth/ftspic.h
index 9ddd1c7905..80fb64cff4 100644
--- a/thirdparty/freetype/src/smooth/ftspic.h
+++ b/thirdparty/freetype/src/smooth/ftspic.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for smooth module. */
/* */
-/* Copyright 2009-2017 by */
+/* Copyright 2009-2018 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/smooth/module.mk b/thirdparty/freetype/src/smooth/module.mk
index 804e9b1386..5b8bc3be3b 100644
--- a/thirdparty/freetype/src/smooth/module.mk
+++ b/thirdparty/freetype/src/smooth/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2017 by
+# Copyright 1996-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/smooth/rules.mk b/thirdparty/freetype/src/smooth/rules.mk
index dfdc9bc30f..f30824a367 100644
--- a/thirdparty/freetype/src/smooth/rules.mk
+++ b/thirdparty/freetype/src/smooth/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2017 by
+# Copyright 1996-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/smooth/smooth.c b/thirdparty/freetype/src/smooth/smooth.c
index e0460d9d46..5249a8931e 100644
--- a/thirdparty/freetype/src/smooth/smooth.c
+++ b/thirdparty/freetype/src/smooth/smooth.c
@@ -4,7 +4,7 @@
/* */
/* FreeType anti-aliasing rasterer module component (body only). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/truetype/module.mk b/thirdparty/freetype/src/truetype/module.mk
index 563c584e2b..16bc9c8b20 100644
--- a/thirdparty/freetype/src/truetype/module.mk
+++ b/thirdparty/freetype/src/truetype/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2017 by
+# Copyright 1996-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/truetype/rules.mk b/thirdparty/freetype/src/truetype/rules.mk
index ad3d007455..e16113f128 100644
--- a/thirdparty/freetype/src/truetype/rules.mk
+++ b/thirdparty/freetype/src/truetype/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2017 by
+# Copyright 1996-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/truetype/truetype.c b/thirdparty/freetype/src/truetype/truetype.c
index 301b82ad1c..484370975c 100644
--- a/thirdparty/freetype/src/truetype/truetype.c
+++ b/thirdparty/freetype/src/truetype/truetype.c
@@ -4,7 +4,7 @@
/* */
/* FreeType TrueType driver component (body only). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/truetype/ttdriver.c b/thirdparty/freetype/src/truetype/ttdriver.c
index a1653b241c..820cafbb8d 100644
--- a/thirdparty/freetype/src/truetype/ttdriver.c
+++ b/thirdparty/freetype/src/truetype/ttdriver.c
@@ -4,7 +4,7 @@
/* */
/* TrueType font driver implementation (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -31,7 +31,7 @@
#include FT_SERVICE_TRUETYPE_ENGINE_H
#include FT_SERVICE_TRUETYPE_GLYF_H
#include FT_SERVICE_PROPERTIES_H
-#include FT_TRUETYPE_DRIVER_H
+#include FT_DRIVER_H
#include "ttdriver.h"
#include "ttgload.h"
@@ -233,8 +233,8 @@
{
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
/* no fast retrieval for blended MM fonts without VVAR table */
- if ( !face->is_default_instance &&
- !( face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
+ if ( ( FT_IS_NAMED_INSTANCE( ttface ) || FT_IS_VARIATION( ttface ) ) &&
+ !( face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
return FT_THROW( Unimplemented_Feature );
#endif
@@ -253,8 +253,8 @@
{
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
/* no fast retrieval for blended MM fonts without HVAR table */
- if ( !face->is_default_instance &&
- !( face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
+ if ( ( FT_IS_NAMED_INSTANCE( ttface ) || FT_IS_VARIATION( ttface ) ) &&
+ !( face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
return FT_THROW( Unimplemented_Feature );
#endif
@@ -498,6 +498,7 @@
(FT_Get_MM_Var_Func) TT_Get_MM_Var, /* get_mm_var */
(FT_Set_Var_Design_Func)TT_Set_Var_Design, /* set_var_design */
(FT_Get_Var_Design_Func)TT_Get_Var_Design, /* get_var_design */
+ (FT_Set_Instance_Func) TT_Set_Named_Instance, /* set_instance */
(FT_Get_Var_Blend_Func) tt_get_var_blend, /* get_var_blend */
(FT_Done_Blend_Func) tt_done_blend /* done_blend */
diff --git a/thirdparty/freetype/src/truetype/ttdriver.h b/thirdparty/freetype/src/truetype/ttdriver.h
index 3bcba7f745..707aa68edf 100644
--- a/thirdparty/freetype/src/truetype/ttdriver.h
+++ b/thirdparty/freetype/src/truetype/ttdriver.h
@@ -4,7 +4,7 @@
/* */
/* High-level TrueType driver interface (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/truetype/tterrors.h b/thirdparty/freetype/src/truetype/tterrors.h
index a49f205156..88bca3a04a 100644
--- a/thirdparty/freetype/src/truetype/tterrors.h
+++ b/thirdparty/freetype/src/truetype/tterrors.h
@@ -4,7 +4,7 @@
/* */
/* TrueType error codes (specification only). */
/* */
-/* Copyright 2001-2017 by */
+/* Copyright 2001-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/truetype/ttgload.c b/thirdparty/freetype/src/truetype/ttgload.c
index 5e102c6151..39d9c3f736 100644
--- a/thirdparty/freetype/src/truetype/ttgload.c
+++ b/thirdparty/freetype/src/truetype/ttgload.c
@@ -4,7 +4,7 @@
/* */
/* TrueType Glyph Loader (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -24,7 +24,7 @@
#include FT_INTERNAL_SFNT_H
#include FT_TRUETYPE_TAGS_H
#include FT_OUTLINE_H
-#include FT_TRUETYPE_DRIVER_H
+#include FT_DRIVER_H
#include FT_LIST_H
#include "ttgload.h"
@@ -664,7 +664,52 @@
} while ( subglyph->flags & MORE_COMPONENTS );
gloader->current.num_subglyphs = num_subglyphs;
- FT_TRACE5(( " %d components\n", num_subglyphs ));
+ FT_TRACE5(( " %d component%s\n",
+ num_subglyphs,
+ num_subglyphs > 1 ? "s" : "" ));
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ {
+ FT_UInt i;
+
+
+ subglyph = gloader->current.subglyphs;
+
+ for ( i = 0; i < num_subglyphs; i++ )
+ {
+ if ( num_subglyphs > 1 )
+ FT_TRACE7(( " subglyph %d:\n", i ));
+
+ FT_TRACE7(( " glyph index: %d\n", subglyph->index ));
+
+ if ( subglyph->flags & ARGS_ARE_XY_VALUES )
+ FT_TRACE7(( " offset: x=%d, y=%d\n",
+ subglyph->arg1,
+ subglyph->arg2 ));
+ else
+ FT_TRACE7(( " matching points: base=%d, component=%d\n",
+ subglyph->arg1,
+ subglyph->arg2 ));
+
+ if ( subglyph->flags & WE_HAVE_A_SCALE )
+ FT_TRACE7(( " scaling: %f\n",
+ subglyph->transform.xx / 65536.0 ));
+ else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
+ FT_TRACE7(( " scaling: x=%f, y=%f\n",
+ subglyph->transform.xx / 65536.0,
+ subglyph->transform.yy / 65536.0 ));
+ else if ( subglyph->flags & WE_HAVE_A_2X2 )
+ FT_TRACE7(( " scaling: xx=%f, yx=%f\n"
+ " xy=%f, yy=%f\n",
+ subglyph->transform.xx / 65536.0,
+ subglyph->transform.yx / 65536.0,
+ subglyph->transform.xy / 65536.0,
+ subglyph->transform.yy / 65536.0 ));
+
+ subglyph++;
+ }
+ }
+#endif /* FT_DEBUG_LEVEL_TRACE */
#ifdef TT_USE_BYTECODE_INTERPRETER
@@ -756,7 +801,7 @@
{
FT_TRACE1(( "TT_Hint_Glyph: too long instructions" ));
FT_TRACE1(( " (0x%lx byte) is truncated\n",
- loader->glyph->control_len ));
+ loader->glyph->control_len ));
}
n_ins = loader->glyph->control_len;
@@ -889,7 +934,8 @@
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- if ( !loader->face->is_default_instance )
+ if ( FT_IS_NAMED_INSTANCE( FT_FACE( loader->face ) ) ||
+ FT_IS_VARIATION( FT_FACE( loader->face ) ) )
{
/* Deltas apply to the unscaled data. */
error = TT_Vary_Apply_Glyph_Deltas( loader->face,
@@ -991,9 +1037,24 @@
vec->x = FT_MulFix( vec->x, x_scale );
vec->y = FT_MulFix( vec->y, y_scale );
}
+ }
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+ /* if we have a HVAR table, `pp1' and/or `pp2' are already adjusted */
+ if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ||
+ !IS_HINTED( loader->load_flags ) )
+#endif
+ {
loader->pp1 = outline->points[n_points - 4];
loader->pp2 = outline->points[n_points - 3];
+ }
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+ /* if we have a VVAR table, `pp3' and/or `pp4' are already adjusted */
+ if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ||
+ !IS_HINTED( loader->load_flags ) )
+#endif
+ {
loader->pp3 = outline->points[n_points - 2];
loader->pp4 = outline->points[n_points - 1];
}
@@ -1145,8 +1206,28 @@
if ( subglyph->flags & ROUND_XY_TO_GRID )
{
- x = FT_PIX_ROUND( x );
- y = FT_PIX_ROUND( y );
+ TT_Face face = loader->face;
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
+
+
+ if ( IS_HINTED( loader->load_flags ) )
+ {
+ /*
+ * We round the horizontal offset only if there is hinting along
+ * the x axis; this corresponds to integer advance width values.
+ *
+ * Theoretically, a glyph's bytecode can toggle ClearType's
+ * `backward compatibility' mode, which would allow modification
+ * of the advance width. In reality, however, applications
+ * neither allow nor expect modified advance widths if subpixel
+ * rendering is active.
+ *
+ */
+ if ( driver->interpreter_version == TT_INTERPRETER_VERSION_35 )
+ x = FT_PIX_ROUND( x );
+
+ y = FT_PIX_ROUND( y );
+ }
}
}
}
@@ -1359,6 +1440,7 @@
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( loader->face );
#endif
+
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
{
@@ -1577,7 +1659,8 @@
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- if ( !loader->face->is_default_instance )
+ if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ||
+ FT_IS_VARIATION( FT_FACE( face ) ) )
{
/* a small outline structure with four elements for */
/* communication with `TT_Vary_Apply_Glyph_Deltas' */
@@ -1711,7 +1794,7 @@
/* clear the nodes filled by sibling chains */
node = ft_list_get_node_at( &loader->composites, recurse_count );
for ( node2 = node; node2; node2 = node2->next )
- node2->data = (void*)ULONG_MAX;
+ node2->data = (void*)FT_ULONG_MAX;
/* check whether we already have a composite glyph with this index */
if ( FT_List_Find( &loader->composites,
@@ -1751,7 +1834,8 @@
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- if ( !face->is_default_instance )
+ if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ||
+ FT_IS_VARIATION( FT_FACE( face ) ) )
{
short i, limit;
FT_SubGlyph subglyph;
@@ -2609,7 +2693,8 @@
TT_LoaderRec loader;
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
-#define IS_DEFAULT_INSTANCE ( ( (TT_Face)glyph->face )->is_default_instance )
+#define IS_DEFAULT_INSTANCE ( !( FT_IS_NAMED_INSTANCE( glyph->face ) || \
+ FT_IS_VARIATION( glyph->face ) ) )
#else
#define IS_DEFAULT_INSTANCE 1
#endif
@@ -2624,6 +2709,10 @@
( load_flags & FT_LOAD_NO_BITMAP ) == 0 &&
IS_DEFAULT_INSTANCE )
{
+ FT_Fixed x_scale = size->root.metrics.x_scale;
+ FT_Fixed y_scale = size->root.metrics.y_scale;
+
+
error = load_sbit_image( size, glyph, glyph_index, load_flags );
if ( FT_ERR_EQ( error, Missing_Bitmap ) )
{
@@ -2631,9 +2720,13 @@
/* if we have a bitmap-only font, return an empty glyph */
if ( !FT_IS_SCALABLE( glyph->face ) )
{
- TT_Face face = (TT_Face)glyph->face;
- FT_Short left_bearing = 0, top_bearing = 0;
- FT_UShort advance_width = 0, advance_height = 0;
+ TT_Face face = (TT_Face)glyph->face;
+
+ FT_Short left_bearing = 0;
+ FT_Short top_bearing = 0;
+
+ FT_UShort advance_width = 0;
+ FT_UShort advance_height = 0;
/* to return an empty glyph, however, we need metrics data */
@@ -2659,13 +2752,13 @@
glyph->metrics.width = 0;
glyph->metrics.height = 0;
- glyph->metrics.horiBearingX = left_bearing;
+ glyph->metrics.horiBearingX = FT_MulFix( left_bearing, x_scale );
glyph->metrics.horiBearingY = 0;
- glyph->metrics.horiAdvance = advance_width;
+ glyph->metrics.horiAdvance = FT_MulFix( advance_width, x_scale );
glyph->metrics.vertBearingX = 0;
- glyph->metrics.vertBearingY = top_bearing;
- glyph->metrics.vertAdvance = advance_height;
+ glyph->metrics.vertBearingY = FT_MulFix( top_bearing, y_scale );
+ glyph->metrics.vertAdvance = FT_MulFix( advance_height, y_scale );
glyph->format = FT_GLYPH_FORMAT_BITMAP;
glyph->bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
@@ -2696,13 +2789,11 @@
/* sanity checks: if `xxxAdvance' in the sbit metric */
/* structure isn't set, use `linearXXXAdvance' */
if ( !glyph->metrics.horiAdvance && glyph->linearHoriAdvance )
- glyph->metrics.horiAdvance =
- FT_MulFix( glyph->linearHoriAdvance,
- size->metrics->x_scale );
+ glyph->metrics.horiAdvance = FT_MulFix( glyph->linearHoriAdvance,
+ x_scale );
if ( !glyph->metrics.vertAdvance && glyph->linearVertAdvance )
- glyph->metrics.vertAdvance =
- FT_MulFix( glyph->linearVertAdvance,
- size->metrics->y_scale );
+ glyph->metrics.vertAdvance = FT_MulFix( glyph->linearVertAdvance,
+ y_scale );
}
return FT_Err_Ok;
diff --git a/thirdparty/freetype/src/truetype/ttgload.h b/thirdparty/freetype/src/truetype/ttgload.h
index 1dd6c841db..d237cfd284 100644
--- a/thirdparty/freetype/src/truetype/ttgload.h
+++ b/thirdparty/freetype/src/truetype/ttgload.h
@@ -4,7 +4,7 @@
/* */
/* TrueType Glyph Loader (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/truetype/ttgxvar.c b/thirdparty/freetype/src/truetype/ttgxvar.c
index 49aa53a687..29ab2a4efd 100644
--- a/thirdparty/freetype/src/truetype/ttgxvar.c
+++ b/thirdparty/freetype/src/truetype/ttgxvar.c
@@ -4,7 +4,7 @@
/* */
/* TrueType GX Font Variation loader */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -1043,10 +1043,11 @@
outerIndex,
innerIndex );
- FT_TRACE5(( "%s value %d adjusted by %d units (%s)\n",
+ FT_TRACE5(( "%s value %d adjusted by %d unit%s (%s)\n",
vertical ? "vertical height" : "horizontal width",
*avalue,
delta,
+ delta == 1 ? "" : "s",
vertical ? "VVAR" : "HVAR" ));
*avalue += delta;
@@ -1333,13 +1334,15 @@
if ( p )
{
- FT_TRACE5(( "value %c%c%c%c (%d units) adjusted by %d units (MVAR)\n",
+ FT_TRACE5(( "value %c%c%c%c (%d unit%s) adjusted by %d unit%s (MVAR)\n",
(FT_Char)( value->tag >> 24 ),
(FT_Char)( value->tag >> 16 ),
(FT_Char)( value->tag >> 8 ),
(FT_Char)( value->tag ),
value->unmodified,
- delta ));
+ value->unmodified == 1 ? "" : "s",
+ delta,
+ delta == 1 ? "" : "s" ));
/* since we handle both signed and unsigned values as FT_Short, */
/* ensure proper overflow arithmetic */
@@ -1499,8 +1502,10 @@
blend->gv_glyphcnt = gvar_head.glyphCount;
offsetToData = gvar_start + gvar_head.offsetToData;
- FT_TRACE5(( "gvar: there are %d shared coordinates:\n",
- blend->tuplecount ));
+ FT_TRACE5(( "gvar: there %s %d shared coordinate%s:\n",
+ blend->tuplecount == 1 ? "is" : "are",
+ blend->tuplecount,
+ blend->tuplecount == 1 ? "" : "s" ));
if ( FT_NEW_ARRAY( blend->glyphoffsets, blend->gv_glyphcnt + 1 ) )
goto Exit;
@@ -1728,15 +1733,13 @@
/* 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. */
- FT_TRACE5(( "design coordinates:\n" ));
-
a = mmvar->axis;
for ( i = 0; i < num_coords; i++, a++ )
{
FT_Fixed coord = coords[i];
- FT_TRACE5(( " %.5f\n", coord / 65536.0 ));
+ FT_TRACE5(( " %d: %.5f\n", i, coord / 65536.0 ));
if ( coord > a->maximum || coord < a->minimum )
{
FT_TRACE1((
@@ -1746,17 +1749,17 @@
a->minimum / 65536.0,
a->maximum / 65536.0 ));
- if ( coord > a->maximum)
+ if ( coord > a->maximum )
coord = a->maximum;
else
coord = a->minimum;
}
if ( coord < a->def )
- normalized[i] = -FT_DivFix( coords[i] - a->def,
+ normalized[i] = -FT_DivFix( coord - a->def,
a->minimum - a->def );
else if ( coord > a->def )
- normalized[i] = FT_DivFix( coords[i] - a->def,
+ normalized[i] = FT_DivFix( coord - a->def,
a->maximum - a->def );
else
normalized[i] = 0;
@@ -1822,16 +1825,8 @@
nc = blend->num_axis;
}
- if ( face->doblend )
- {
- for ( i = 0; i < nc; i++ )
- design[i] = coords[i];
- }
- else
- {
- for ( i = 0; i < nc; i++ )
- design[i] = 0;
- }
+ for ( i = 0; i < nc; i++ )
+ design[i] = coords[i];
for ( ; i < num_coords; i++ )
design[i] = 0;
@@ -1940,11 +1935,11 @@
TT_Get_MM_Var( TT_Face face,
FT_MM_Var* *master )
{
- FT_Stream stream = face->root.stream;
- FT_Memory memory = face->root.memory;
+ FT_Stream stream = face->root.stream;
+ FT_Memory memory = face->root.memory;
FT_ULong table_len;
- FT_Error error = FT_Err_Ok;
- FT_ULong fvar_start;
+ FT_Error error = FT_Err_Ok;
+ FT_ULong fvar_start = 0;
FT_UInt i, j;
FT_MM_Var* mmvar = NULL;
FT_Fixed* next_coords;
@@ -1954,10 +1949,20 @@
FT_Fixed* c;
FT_Var_Named_Style* ns;
GX_FVar_Head fvar_head;
- FT_Bool usePsName;
+ FT_Bool usePsName = 0;
FT_UInt num_instances;
+ FT_UInt num_axes;
FT_UShort* axis_flags;
+ FT_Offset mmvar_size;
+ FT_Offset axis_flags_size;
+ FT_Offset axis_size;
+ FT_Offset namedstyle_size;
+ FT_Offset next_coords_size;
+ FT_Offset next_name_size;
+
+ FT_Bool need_init;
+
static const FT_Frame_Field fvar_fields[] =
{
@@ -1995,7 +2000,9 @@
/* read the font data and set up the internal representation */
/* if not already done */
- if ( !face->blend )
+ need_init = !face->blend;
+
+ if ( need_init )
{
FT_TRACE2(( "FVAR " ));
@@ -2032,26 +2039,57 @@
FT_TRACE2(( "loaded\n" ));
- FT_TRACE5(( "number of GX style axes: %d\n", fvar_head.axisCount ));
+ FT_TRACE5(( "%d variation ax%s\n",
+ fvar_head.axisCount,
+ fvar_head.axisCount == 1 ? "is" : "es" ));
if ( FT_NEW( face->blend ) )
goto Exit;
- /* `num_instances' holds the number of all named instances, */
- /* including the default instance which might be missing */
- /* in fvar's table of named instances */
- num_instances = face->root.style_flags >> 16;
-
- /* prepare storage area for MM data; this cannot overflow */
- /* 32-bit arithmetic because of the size limits used in the */
- /* `fvar' table validity check in `sfnt_init_face' */
- face->blend->mmvar_len =
- sizeof ( FT_MM_Var ) +
- fvar_head.axisCount * sizeof ( FT_UShort ) +
- fvar_head.axisCount * sizeof ( FT_Var_Axis ) +
- num_instances * sizeof ( FT_Var_Named_Style ) +
- num_instances * fvar_head.axisCount * sizeof ( FT_Fixed ) +
- fvar_head.axisCount * 5;
+ num_axes = fvar_head.axisCount;
+ face->blend->num_axis = num_axes;
+ }
+ else
+ num_axes = face->blend->num_axis;
+
+ /* `num_instances' holds the number of all named instances, */
+ /* including the default instance which might be missing */
+ /* in fvar's table of named instances */
+ num_instances = (FT_UInt)face->root.style_flags >> 16;
+
+ /* prepare storage area for MM data; this cannot overflow */
+ /* 32-bit arithmetic because of the size limits used in the */
+ /* `fvar' table validity check in `sfnt_init_face' */
+
+ /* the various `*_size' variables, which we also use as */
+ /* offsets into the `mmlen' array, must be multiples of the */
+ /* pointer size (except the last one); without such an */
+ /* alignment there might be runtime errors due to */
+ /* misaligned addresses */
+#undef ALIGN_SIZE
+#define ALIGN_SIZE( n ) \
+ ( ( (n) + sizeof (void*) - 1 ) & ~( sizeof (void*) - 1 ) )
+
+ mmvar_size = ALIGN_SIZE( sizeof ( FT_MM_Var ) );
+ axis_flags_size = ALIGN_SIZE( num_axes *
+ sizeof ( FT_UShort ) );
+ axis_size = ALIGN_SIZE( num_axes *
+ sizeof ( FT_Var_Axis ) );
+ namedstyle_size = ALIGN_SIZE( num_instances *
+ sizeof ( FT_Var_Named_Style ) );
+ next_coords_size = ALIGN_SIZE( num_instances *
+ num_axes *
+ sizeof ( FT_Fixed ) );
+ next_name_size = num_axes * 5;
+
+ if ( need_init )
+ {
+ face->blend->mmvar_len = mmvar_size +
+ axis_flags_size +
+ axis_size +
+ namedstyle_size +
+ next_coords_size +
+ next_name_size;
if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) )
goto Exit;
@@ -2061,7 +2099,7 @@
/* the data gets filled in later on */
mmvar->num_axis =
- fvar_head.axisCount;
+ num_axes;
mmvar->num_designs =
~0U; /* meaningless in this context; each glyph */
/* may have a different number of designs */
@@ -2071,22 +2109,23 @@
/* alas, no public field in `FT_Var_Axis' for axis flags */
axis_flags =
- (FT_UShort*)&( mmvar[1] );
+ (FT_UShort*)( (char*)mmvar + mmvar_size );
mmvar->axis =
- (FT_Var_Axis*)&( axis_flags[fvar_head.axisCount] );
+ (FT_Var_Axis*)( (char*)axis_flags + axis_flags_size );
mmvar->namedstyle =
- (FT_Var_Named_Style*)&( mmvar->axis[fvar_head.axisCount] );
+ (FT_Var_Named_Style*)( (char*)mmvar->axis + axis_size );
- next_coords =
- (FT_Fixed*)&( mmvar->namedstyle[num_instances] );
+ next_coords = (FT_Fixed*)( (char*)mmvar->namedstyle +
+ namedstyle_size );
for ( i = 0; i < num_instances; i++ )
{
mmvar->namedstyle[i].coords = next_coords;
- next_coords += fvar_head.axisCount;
+ next_coords += num_axes;
}
- next_name = (FT_String*)next_coords;
- for ( i = 0; i < fvar_head.axisCount; i++ )
+ next_name = (FT_String*)( (char*)mmvar->namedstyle +
+ namedstyle_size + next_coords_size );
+ for ( i = 0; i < num_axes; i++ )
{
mmvar->axis[i].name = next_name;
next_name += 5;
@@ -2098,10 +2137,14 @@
goto Exit;
a = mmvar->axis;
- for ( i = 0; i < fvar_head.axisCount; i++ )
+ for ( i = 0; i < num_axes; i++ )
{
GX_FVar_Axis axis_rec;
+#ifdef FT_DEBUG_LEVEL_TRACE
+ int invalid = 0;
+#endif
+
if ( FT_STREAM_READ_FIELDS( fvaraxis_fields, &axis_rec ) )
goto Exit;
@@ -2122,22 +2165,31 @@
if ( a->minimum > a->def ||
a->def > a->maximum )
{
- FT_TRACE2(( "TT_Get_MM_Var:"
- " invalid \"%s\" axis record; disabling\n",
- a->name ));
-
a->minimum = a->def;
a->maximum = a->def;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ invalid = 1;
+#endif
}
- FT_TRACE5(( " \"%s\":"
- " minimum=%.5f, default=%.5f, maximum=%.5f,"
- " flags=0x%04X\n",
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( i == 0 )
+ FT_TRACE5(( " idx tag "
+ /* " XXX `XXXX'" */
+ " minimum default maximum flags\n" ));
+ /* " XXXX.XXXXX XXXX.XXXXX XXXX.XXXXX 0xXXXX" */
+
+ FT_TRACE5(( " %3d `%s'"
+ " %10.5f %10.5f %10.5f 0x%04X%s\n",
+ i,
a->name,
a->minimum / 65536.0,
a->def / 65536.0,
a->maximum / 65536.0,
- *axis_flags ));
+ *axis_flags,
+ invalid ? " (invalid, disabled)" : "" ));
+#endif
a++;
axis_flags++;
@@ -2148,7 +2200,7 @@
/* named instance coordinates are stored as design coordinates; */
/* we have to convert them to normalized coordinates also */
if ( FT_NEW_ARRAY( face->blend->normalized_stylecoords,
- fvar_head.axisCount * num_instances ) )
+ num_axes * num_instances ) )
goto Exit;
if ( fvar_head.instanceCount && !face->blend->avar_loaded )
@@ -2162,20 +2214,24 @@
goto Exit;
}
+ FT_TRACE5(( "%d instance%s\n",
+ fvar_head.instanceCount,
+ fvar_head.instanceCount == 1 ? "" : "s" ));
+
ns = mmvar->namedstyle;
nsc = face->blend->normalized_stylecoords;
for ( i = 0; i < fvar_head.instanceCount; i++, ns++ )
{
/* PostScript names add 2 bytes to the instance record size */
if ( FT_FRAME_ENTER( ( usePsName ? 6L : 4L ) +
- 4L * fvar_head.axisCount ) )
+ 4L * num_axes ) )
goto Exit;
ns->strid = FT_GET_USHORT();
(void) /* flags = */ FT_GET_USHORT();
c = ns->coords;
- for ( j = 0; j < fvar_head.axisCount; j++, c++ )
+ for ( j = 0; j < num_axes; j++, c++ )
*c = FT_GET_LONG();
/* valid psid values are 6, [256;32767], and 0xFFFF */
@@ -2184,11 +2240,54 @@
else
ns->psid = 0xFFFF;
- ft_var_to_normalized( face,
- fvar_head.axisCount,
- ns->coords,
- nsc );
- nsc += fvar_head.axisCount;
+#ifdef FT_DEBUG_LEVEL_TRACE
+ {
+ SFNT_Service sfnt = (SFNT_Service)face->sfnt;
+
+ FT_String* strname = NULL;
+ FT_String* psname = NULL;
+
+ FT_ULong pos;
+
+
+ pos = FT_STREAM_POS();
+
+ if ( ns->strid != 0xFFFF )
+ {
+ (void)sfnt->get_name( face,
+ (FT_UShort)ns->strid,
+ &strname );
+ if ( strname && !ft_strcmp( strname, ".notdef" ) )
+ strname = NULL;
+ }
+
+ if ( ns->psid != 0xFFFF )
+ {
+ (void)sfnt->get_name( face,
+ (FT_UShort)ns->psid,
+ &psname );
+ if ( psname && !ft_strcmp( psname, ".notdef" ) )
+ psname = NULL;
+ }
+
+ (void)FT_STREAM_SEEK( pos );
+
+ FT_TRACE5(( " instance %d (%s%s%s, %s%s%s)\n",
+ i,
+ strname ? "name: `" : "",
+ strname ? strname : "unnamed",
+ strname ? "'" : "",
+ psname ? "PS name: `" : "",
+ psname ? psname : "no PS name",
+ psname ? "'" : "" ));
+
+ FT_FREE( strname );
+ FT_FREE( psname );
+ }
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
+ ft_var_to_normalized( face, num_axes, ns->coords, nsc );
+ nsc += num_axes;
FT_FRAME_EXIT();
}
@@ -2237,7 +2336,7 @@
a = mmvar->axis;
c = ns->coords;
- for ( j = 0; j < fvar_head.axisCount; j++, a++, c++ )
+ for ( j = 0; j < num_axes; j++, a++, c++ )
*c = a->def;
}
}
@@ -2258,23 +2357,24 @@
FT_MEM_COPY( mmvar, face->blend->mmvar, face->blend->mmvar_len );
axis_flags =
- (FT_UShort*)&( mmvar[1] );
+ (FT_UShort*)( (char*)mmvar + mmvar_size );
mmvar->axis =
- (FT_Var_Axis*)&( axis_flags[mmvar->num_axis] );
+ (FT_Var_Axis*)( (char*)axis_flags + axis_flags_size );
mmvar->namedstyle =
- (FT_Var_Named_Style*)&( mmvar->axis[mmvar->num_axis] );
+ (FT_Var_Named_Style*)( (char*)mmvar->axis+ axis_size );
- next_coords =
- (FT_Fixed*)&( mmvar->namedstyle[mmvar->num_namedstyles] );
+ next_coords = (FT_Fixed*)( (char*)mmvar->namedstyle +
+ namedstyle_size );
for ( n = 0; n < mmvar->num_namedstyles; n++ )
{
mmvar->namedstyle[n].coords = next_coords;
- next_coords += mmvar->num_axis;
+ next_coords += num_axes;
}
a = mmvar->axis;
- next_name = (FT_String*)next_coords;
- for ( n = 0; n < mmvar->num_axis; n++ )
+ next_name = (FT_String*)( (char*)mmvar->namedstyle +
+ namedstyle_size + next_coords_size );
+ for ( n = 0; n < num_axes; n++ )
{
a->name = next_name;
@@ -2309,10 +2409,9 @@
FT_Error error = FT_Err_Ok;
GX_Blend blend;
FT_MM_Var* mmvar;
- FT_UInt i, j;
+ FT_UInt i;
- FT_Bool is_default_instance = TRUE;
- FT_Bool all_design_coords = FALSE;
+ FT_Bool all_design_coords = FALSE;
FT_Memory memory = face->root.memory;
@@ -2344,11 +2443,12 @@
num_coords = mmvar->num_axis;
}
- FT_TRACE5(( "normalized design coordinates:\n" ));
+ FT_TRACE5(( "TT_Set_MM_Blend:\n"
+ " normalized design coordinates:\n" ));
for ( i = 0; i < num_coords; i++ )
{
- FT_TRACE5(( " %.5f\n", coords[i] / 65536.0 ));
+ FT_TRACE5(( " %.5f\n", coords[i] / 65536.0 ));
if ( coords[i] < -0x00010000L || coords[i] > 0x00010000L )
{
FT_TRACE1(( "TT_Set_MM_Blend: normalized design coordinate %.5f\n"
@@ -2357,9 +2457,6 @@
error = FT_THROW( Invalid_Argument );
goto Exit;
}
-
- if ( coords[i] != 0 )
- is_default_instance = FALSE;
}
FT_TRACE5(( "\n" ));
@@ -2390,6 +2487,12 @@
}
else
{
+ FT_Bool have_diff = 0;
+ FT_UInt j;
+ FT_Fixed* c;
+ FT_Fixed* n;
+
+
manageCvt = mcvt_retain;
for ( i = 0; i < num_coords; i++ )
@@ -2397,10 +2500,34 @@
if ( blend->normalizedcoords[i] != coords[i] )
{
manageCvt = mcvt_load;
+ have_diff = 1;
break;
}
}
+ if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) )
+ {
+ FT_UInt idx = (FT_UInt)face->root.face_index >> 16;
+
+
+ c = blend->normalizedcoords + i;
+ n = blend->normalized_stylecoords + idx * mmvar->num_axis + i;
+ for ( j = i; j < mmvar->num_axis; j++, n++, c++ )
+ if ( *c != *n )
+ have_diff = 1;
+ }
+ else
+ {
+ c = blend->normalizedcoords + i;
+ for ( j = i; j < mmvar->num_axis; j++, c++ )
+ if ( *c != 0 )
+ have_diff = 1;
+ }
+
+ /* return value -1 indicates `no change' */
+ if ( !have_diff )
+ return -1;
+
for ( ; i < mmvar->num_axis; i++ )
{
if ( blend->normalizedcoords[i] != 0 )
@@ -2454,32 +2581,6 @@
}
}
- /* check whether the current variation tuple coincides */
- /* with a named instance */
-
- for ( i = 0; i < blend->mmvar->num_namedstyles; i++ )
- {
- FT_Fixed* nsc = blend->normalized_stylecoords + i * blend->num_axis;
- FT_Fixed* ns = blend->normalizedcoords;
-
-
- for ( j = 0; j < blend->num_axis; j++, nsc++, ns++ )
- {
- if ( *nsc != *ns )
- break;
- }
-
- if ( j == blend->num_axis )
- break;
- }
-
- /* adjust named instance index */
- face->root.face_index &= 0xFFFF;
- if ( i < blend->mmvar->num_namedstyles )
- face->root.face_index |= ( i + 1 ) << 16;
-
- face->is_default_instance = is_default_instance;
-
/* enforce recomputation of the PostScript name; */
FT_FREE( face->postscript_name );
face->postscript_name = NULL;
@@ -2519,7 +2620,19 @@
FT_UInt num_coords,
FT_Fixed* coords )
{
- return tt_set_mm_blend( face, num_coords, coords, 1 );
+ FT_Error error;
+
+
+ error = tt_set_mm_blend( face, num_coords, coords, 1 );
+ if ( error )
+ return error;
+
+ if ( num_coords )
+ face->root.face_flags |= FT_FACE_FLAG_VARIATION;
+ else
+ face->root.face_flags &= ~FT_FACE_FLAG_VARIATION;
+
+ return FT_Err_Ok;
}
@@ -2635,11 +2748,12 @@
FT_UInt i;
FT_Memory memory = face->root.memory;
- FT_Var_Axis* a;
- FT_Fixed* c;
-
+ FT_Fixed* c;
+ FT_Fixed* n;
FT_Fixed* normalized = NULL;
+ FT_Bool have_diff = 0;
+
if ( !face->blend )
{
@@ -2664,14 +2778,56 @@
goto Exit;
}
- FT_MEM_COPY( blend->coords,
- coords,
- num_coords * sizeof ( FT_Fixed ) );
+ c = blend->coords;
+ n = coords;
+ for ( i = 0; i < num_coords; i++, n++, c++ )
+ {
+ if ( *c != *n )
+ {
+ *c = *n;
+ have_diff = 1;
+ }
+ }
+
+ if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) )
+ {
+ FT_UInt instance_index;
+ FT_Var_Named_Style* named_style;
+
+
+ instance_index = (FT_UInt)face->root.face_index >> 16;
+ named_style = mmvar->namedstyle + instance_index - 1;
+
+ n = named_style->coords + num_coords;
+ for ( ; i < mmvar->num_axis; i++, n++, c++ )
+ {
+ if ( *c != *n )
+ {
+ *c = *n;
+ have_diff = 1;
+ }
+ }
+ }
+ else
+ {
+ FT_Var_Axis* a;
- a = mmvar->axis + num_coords;
- c = blend->coords + num_coords;
- for ( i = num_coords; i < mmvar->num_axis; i++, a++, c++ )
- *c = a->def;
+
+ a = mmvar->axis + num_coords;
+ for ( ; i < mmvar->num_axis; i++, a++, c++ )
+ {
+ if ( *c != a->def )
+ {
+ *c = a->def;
+ have_diff = 1;
+ }
+ }
+ }
+
+ /* return value -1 indicates `no change'; */
+ /* we can exit early if `normalizedcoords' is already computed */
+ if ( blend->normalizedcoords && !have_diff )
+ return -1;
if ( FT_NEW_ARRAY( normalized, mmvar->num_axis ) )
goto Exit;
@@ -2679,9 +2835,18 @@
if ( !face->blend->avar_loaded )
ft_var_load_avar( face );
+ FT_TRACE5(( "TT_Set_Var_Design:\n"
+ " normalized design coordinates:\n" ));
ft_var_to_normalized( face, num_coords, blend->coords, normalized );
error = tt_set_mm_blend( face, mmvar->num_axis, normalized, 0 );
+ if ( error )
+ goto Exit;
+
+ if ( num_coords )
+ face->root.face_flags |= FT_FACE_FLAG_VARIATION;
+ else
+ face->root.face_flags &= ~FT_FACE_FLAG_VARIATION;
Exit:
FT_FREE( normalized );
@@ -2765,6 +2930,90 @@
/*************************************************************************/
+ /* */
+ /* <Function> */
+ /* TT_Set_Named_Instance */
+ /* */
+ /* <Description> */
+ /* Set the given named instance, also resetting any further */
+ /* variation. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face. */
+ /* */
+ /* instance_index :: The instance index, starting with value 1. */
+ /* Value 0 indicates to not use an instance. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0~means success. */
+ /* */
+ FT_LOCAL_DEF( FT_Error )
+ TT_Set_Named_Instance( TT_Face face,
+ FT_UInt instance_index )
+ {
+ FT_Error error = FT_ERR( Invalid_Argument );
+ GX_Blend blend;
+ FT_MM_Var* mmvar;
+
+ FT_UInt num_instances;
+
+
+ if ( !face->blend )
+ {
+ if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) )
+ goto Exit;
+ }
+
+ blend = face->blend;
+ mmvar = blend->mmvar;
+
+ num_instances = (FT_UInt)face->root.style_flags >> 16;
+
+ /* `instance_index' starts with value 1, thus `>' */
+ if ( instance_index > num_instances )
+ goto Exit;
+
+ if ( instance_index > 0 && mmvar->namedstyle )
+ {
+ FT_Memory memory = face->root.memory;
+ SFNT_Service sfnt = (SFNT_Service)face->sfnt;
+
+ FT_Var_Named_Style* named_style;
+ FT_String* style_name;
+
+
+ named_style = mmvar->namedstyle + instance_index - 1;
+
+ error = sfnt->get_name( face,
+ (FT_UShort)named_style->strid,
+ &style_name );
+ if ( error )
+ goto Exit;
+
+ /* set (or replace) style name */
+ FT_FREE( face->root.style_name );
+ face->root.style_name = style_name;
+
+ /* finally, select the named instance */
+ error = TT_Set_Var_Design( face,
+ mmvar->num_axis,
+ named_style->coords );
+ if ( error )
+ goto Exit;
+ }
+ else
+ error = TT_Set_Var_Design( face, 0, NULL );
+
+ face->root.face_index = ( instance_index << 16 ) |
+ ( face->root.face_index & 0xFFFFL );
+ face->root.face_flags &= ~FT_FACE_FLAG_VARIATION;
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
/*************************************************************************/
/***** *****/
/***** GX VAR PARSING ROUTINES *****/
@@ -2810,8 +3059,10 @@
FT_Fixed* im_start_coords = NULL;
FT_Fixed* im_end_coords = NULL;
GX_Blend blend = face->blend;
- FT_UInt point_count;
- FT_UShort* localpoints;
+ FT_UInt point_count, spoint_count = 0;
+ FT_UShort* sharedpoints = NULL;
+ FT_UShort* localpoints = NULL;
+ FT_UShort* points;
FT_Short* deltas;
@@ -2880,11 +3131,24 @@
offsetToData += table_start;
- /* The documentation implies there are flags packed into */
- /* `tupleCount', but John Jenkins says that shared points don't apply */
- /* to `cvar', and no other flags are defined. */
+ if ( tupleCount & GX_TC_TUPLES_SHARE_POINT_NUMBERS )
+ {
+ here = FT_Stream_FTell( stream );
+
+ FT_Stream_SeekSet( stream, offsetToData );
- FT_TRACE5(( "cvar: there are %d tuples:\n", tupleCount & 0xFFF ));
+ sharedpoints = ft_var_readpackedpoints( stream,
+ table_len,
+ &spoint_count );
+ offsetToData = FT_Stream_FTell( stream );
+
+ FT_Stream_SeekSet( stream, here );
+ }
+
+ FT_TRACE5(( "cvar: there %s %d tuple%s:\n",
+ ( tupleCount & 0xFFF ) == 1 ? "is" : "are",
+ tupleCount & 0xFFF,
+ ( tupleCount & 0xFFF ) == 1 ? "" : "s" ));
for ( i = 0; i < ( tupleCount & 0xFFF ); i++ )
{
@@ -2898,26 +3162,25 @@
tupleDataSize = FT_GET_USHORT();
tupleIndex = FT_GET_USHORT();
- /* There is no provision here for a global tuple coordinate section, */
- /* so John says. There are no tuple indices, just embedded tuples. */
-
if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
{
for ( j = 0; j < blend->num_axis; j++ )
tuple_coords[j] = FT_GET_SHORT() * 4; /* convert from */
/* short frac to fixed */
}
- else
+ else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount )
{
- /* skip this tuple; it makes no sense */
-
- if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
- for ( j = 0; j < 2 * blend->num_axis; j++ )
- (void)FT_GET_SHORT();
+ FT_TRACE2(( "tt_face_vary_cvt:"
+ " invalid tuple index\n" ));
- offsetToData += tupleDataSize;
- continue;
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
}
+ else
+ FT_MEM_COPY(
+ tuple_coords,
+ &blend->tuplecoords[( tupleIndex & 0xFFF ) * blend->num_axis],
+ blend->num_axis * sizeof ( FT_Fixed ) );
if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
{
@@ -2932,11 +3195,8 @@
tuple_coords,
im_start_coords,
im_end_coords );
- if ( /* tuple isn't active for our blend */
- apply == 0 ||
- /* global points not allowed, */
- /* if they aren't local, makes no sense */
- !( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS ) )
+
+ if ( apply == 0 ) /* tuple isn't active for our blend */
{
offsetToData += tupleDataSize;
continue;
@@ -2946,14 +3206,27 @@
FT_Stream_SeekSet( stream, offsetToData );
- localpoints = ft_var_readpackedpoints( stream,
- table_len,
- &point_count );
- deltas = ft_var_readpackeddeltas( stream,
- table_len,
- point_count == 0 ? face->cvt_size
- : point_count );
- if ( !localpoints || !deltas )
+ if ( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS )
+ {
+ localpoints = ft_var_readpackedpoints( stream,
+ table_len,
+ &point_count );
+ points = localpoints;
+ }
+ else
+ {
+ points = sharedpoints;
+ point_count = spoint_count;
+ }
+
+ deltas = ft_var_readpackeddeltas( stream,
+ table_len,
+ point_count == 0 ? face->cvt_size
+ : point_count );
+
+ if ( !points ||
+ !deltas ||
+ ( localpoints == ALL_POINTS && point_count != face->cvt_size ) )
; /* failure, ignore it */
else if ( localpoints == ALL_POINTS )
@@ -3005,7 +3278,7 @@
FT_Long orig_cvt;
- pindex = localpoints[j];
+ pindex = points[j];
if ( (FT_ULong)pindex >= face->cvt_size )
continue;
@@ -3044,6 +3317,8 @@
FT_FRAME_EXIT();
Exit:
+ if ( sharedpoints != ALL_POINTS )
+ FT_FREE( sharedpoints );
FT_FREE( tuple_coords );
FT_FREE( im_start_coords );
FT_FREE( im_end_coords );
@@ -3330,7 +3605,6 @@
glyph_start = FT_Stream_FTell( stream );
/* each set of glyph variation data is formatted similarly to `cvar' */
- /* (except we get shared points and global tuples) */
if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis ) ||
FT_NEW_ARRAY( im_start_coords, blend->num_axis ) ||
@@ -3367,8 +3641,10 @@
FT_Stream_SeekSet( stream, here );
}
- FT_TRACE5(( "gvar: there are %d tuples:\n",
- tupleCount & GX_TC_TUPLE_COUNT_MASK ));
+ FT_TRACE5(( "gvar: there %s %d tuple%s:\n",
+ ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) == 1 ? "is" : "are",
+ tupleCount & GX_TC_TUPLE_COUNT_MASK,
+ ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) == 1 ? "" : "s" ));
for ( j = 0; j < n_points; j++ )
points_org[j] = outline->points[j];
@@ -3470,7 +3746,7 @@
FT_Pos delta_y = FT_MulFix( deltas_y[j], apply );
- if ( j < n_points - 3 )
+ if ( j < n_points - 4 )
{
outline->points[j].x += delta_x;
outline->points[j].y += delta_y;
@@ -3480,25 +3756,25 @@
/* To avoid double adjustment of advance width or height, */
/* adjust phantom points only if there is no HVAR or VVAR */
/* support, respectively. */
- if ( j == ( n_points - 3 ) &&
- !( face->variation_support &
- TT_FACE_FLAG_VAR_HADVANCE ) )
+ if ( j == ( n_points - 4 ) &&
+ !( face->variation_support &
+ TT_FACE_FLAG_VAR_LSB ) )
+ outline->points[j].x += delta_x;
+
+ else if ( j == ( n_points - 3 ) &&
+ !( face->variation_support &
+ TT_FACE_FLAG_VAR_HADVANCE ) )
outline->points[j].x += delta_x;
else if ( j == ( n_points - 2 ) &&
!( face->variation_support &
- TT_FACE_FLAG_VAR_LSB ) )
- outline->points[j].x += delta_x;
+ TT_FACE_FLAG_VAR_TSB ) )
+ outline->points[j].y += delta_y;
else if ( j == ( n_points - 1 ) &&
!( face->variation_support &
TT_FACE_FLAG_VAR_VADVANCE ) )
outline->points[j].y += delta_y;
-
- else if ( j == ( n_points - 0 ) &&
- !( face->variation_support &
- TT_FACE_FLAG_VAR_TSB ) )
- outline->points[j].y += delta_y;
}
#ifdef FT_DEBUG_LEVEL_TRACE
@@ -3565,8 +3841,36 @@
FT_Pos delta_y = points_out[j].y - points_org[j].y;
- outline->points[j].x += delta_x;
- outline->points[j].y += delta_y;
+ if ( j < n_points - 4 )
+ {
+ outline->points[j].x += delta_x;
+ outline->points[j].y += delta_y;
+ }
+ else
+ {
+ /* To avoid double adjustment of advance width or height, */
+ /* adjust phantom points only if there is no HVAR or VVAR */
+ /* support, respectively. */
+ if ( j == ( n_points - 4 ) &&
+ !( face->variation_support &
+ TT_FACE_FLAG_VAR_LSB ) )
+ outline->points[j].x += delta_x;
+
+ else if ( j == ( n_points - 3 ) &&
+ !( face->variation_support &
+ TT_FACE_FLAG_VAR_HADVANCE ) )
+ outline->points[j].x += delta_x;
+
+ else if ( j == ( n_points - 2 ) &&
+ !( face->variation_support &
+ TT_FACE_FLAG_VAR_TSB ) )
+ outline->points[j].y += delta_y;
+
+ else if ( j == ( n_points - 1 ) &&
+ !( face->variation_support &
+ TT_FACE_FLAG_VAR_VADVANCE ) )
+ outline->points[j].y += delta_y;
+ }
#ifdef FT_DEBUG_LEVEL_TRACE
if ( delta_x || delta_y )
diff --git a/thirdparty/freetype/src/truetype/ttgxvar.h b/thirdparty/freetype/src/truetype/ttgxvar.h
index 7e81719a3e..a37bb90266 100644
--- a/thirdparty/freetype/src/truetype/ttgxvar.h
+++ b/thirdparty/freetype/src/truetype/ttgxvar.h
@@ -4,7 +4,7 @@
/* */
/* TrueType GX Font Variation loader (specification) */
/* */
-/* Copyright 2004-2017 by */
+/* Copyright 2004-2018 by */
/* David Turner, Robert Wilhelm, Werner Lemberg and George Williams. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -27,6 +27,8 @@
FT_BEGIN_HEADER
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+
/*************************************************************************/
/* */
/* <Struct> */
@@ -402,6 +404,10 @@ FT_BEGIN_HEADER
FT_Fixed* coords );
FT_LOCAL( FT_Error )
+ TT_Set_Named_Instance( TT_Face face,
+ FT_UInt instance_index );
+
+ FT_LOCAL( FT_Error )
tt_face_vary_cvt( TT_Face face,
FT_Stream stream );
@@ -435,6 +441,8 @@ FT_BEGIN_HEADER
FT_LOCAL( void )
tt_done_blend( TT_Face face );
+#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
+
FT_END_HEADER
diff --git a/thirdparty/freetype/src/truetype/ttinterp.c b/thirdparty/freetype/src/truetype/ttinterp.c
index ddcc839bb3..da9b595aba 100644
--- a/thirdparty/freetype/src/truetype/ttinterp.c
+++ b/thirdparty/freetype/src/truetype/ttinterp.c
@@ -4,7 +4,7 @@
/* */
/* TrueType bytecode interpreter (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -25,7 +25,7 @@
#include FT_INTERNAL_CALC_H
#include FT_TRIGONOMETRY_H
#include FT_SYSTEM_H
-#include FT_TRUETYPE_DRIVER_H
+#include FT_DRIVER_H
#include FT_MULTIPLE_MASTERS_H
#include "ttinterp.h"
@@ -2165,7 +2165,7 @@
val = ADD_LONG( distance,
exc->threshold - exc->phase + compensation ) &
-exc->period;
- val += exc->phase;
+ val = ADD_LONG( val, exc->phase );
if ( val < 0 )
val = exc->phase;
}
@@ -2174,7 +2174,7 @@
val = NEG_LONG( SUB_LONG( exc->threshold - exc->phase + compensation,
distance ) &
-exc->period );
- val -= exc->phase;
+ val = SUB_LONG( val, exc->phase );
if ( val > 0 )
val = -exc->phase;
}
@@ -2216,7 +2216,7 @@
val = ( ADD_LONG( distance,
exc->threshold - exc->phase + compensation ) /
exc->period ) * exc->period;
- val += exc->phase;
+ val = ADD_LONG( val, exc->phase );
if ( val < 0 )
val = exc->phase;
}
@@ -2225,7 +2225,7 @@
val = NEG_LONG( ( SUB_LONG( exc->threshold - exc->phase + compensation,
distance ) /
exc->period ) * exc->period );
- val -= exc->phase;
+ val = SUB_LONG( val, exc->phase );
if ( val > 0 )
val = -exc->phase;
}
@@ -2954,7 +2954,7 @@
static void
Ins_CEILING( FT_Long* args )
{
- args[0] = FT_PIX_CEIL( args[0] );
+ args[0] = FT_PIX_CEIL_LONG( args[0] );
}
@@ -3289,7 +3289,10 @@
if ( args[0] < 0 )
exc->error = FT_THROW( Bad_Argument );
else
- exc->GS.loop = args[0];
+ {
+ /* we heuristically limit the number of loops to 16 bits */
+ exc->GS.loop = args[0] > 0xFFFFL ? 0xFFFFL : args[0];
+ }
}
@@ -5690,7 +5693,11 @@
( B1 & 63 ) != 0 &&
( B2 & 63 ) != 0 &&
B1 != B2 )
- Move_Zp2_Point( exc, point, -dx, -dy, TRUE );
+ Move_Zp2_Point( exc,
+ point,
+ NEG_LONG( dx ),
+ NEG_LONG( dy ),
+ TRUE );
}
}
else if ( exc->face->sph_compatibility_mode )
@@ -5722,7 +5729,7 @@
if ( ( B1 & 63 ) == 0 &&
( B2 & 63 ) != 0 &&
B1 != B2 )
- Move_Zp2_Point( exc, point, 0, -dy, TRUE );
+ Move_Zp2_Point( exc, point, 0, NEG_LONG( dy ), TRUE );
}
}
else if ( exc->sph_in_func_flags & SPH_FDEF_TYPEMAN_DIAGENDCTRL )
@@ -5778,6 +5785,7 @@
FT_F26Dot6 distance;
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
FT_F26Dot6 control_value_cutin = 0;
+ FT_F26Dot6 delta;
if ( SUBPIXEL_HINTING_INFINALITY )
@@ -5813,11 +5821,15 @@
distance = PROJECT( exc->zp1.cur + point, exc->zp0.cur + exc->GS.rp0 );
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+ delta = SUB_LONG( distance, args[1] );
+ if ( delta < 0 )
+ delta = NEG_LONG( delta );
+
/* subpixel hinting - make MSIRP respect CVT cut-in; */
- if ( SUBPIXEL_HINTING_INFINALITY &&
- exc->ignore_x_mode &&
- exc->GS.freeVector.x != 0 &&
- FT_ABS( SUB_LONG( distance, args[1] ) ) >= control_value_cutin )
+ if ( SUBPIXEL_HINTING_INFINALITY &&
+ exc->ignore_x_mode &&
+ exc->GS.freeVector.x != 0 &&
+ delta >= control_value_cutin )
distance = args[1];
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
@@ -5865,16 +5877,18 @@
if ( SUBPIXEL_HINTING_INFINALITY &&
exc->ignore_x_mode &&
exc->GS.freeVector.x != 0 )
- distance = Round_None(
- exc,
- cur_dist,
- exc->tt_metrics.compensations[0] ) - cur_dist;
+ distance = SUB_LONG(
+ Round_None( exc,
+ cur_dist,
+ exc->tt_metrics.compensations[0] ),
+ cur_dist );
else
#endif
- distance = exc->func_round(
- exc,
- cur_dist,
- exc->tt_metrics.compensations[0] ) - cur_dist;
+ distance = SUB_LONG(
+ exc->func_round( exc,
+ cur_dist,
+ exc->tt_metrics.compensations[0] ),
+ cur_dist );
}
else
distance = 0;
@@ -5974,7 +5988,14 @@
if ( ( exc->opcode & 1 ) != 0 ) /* rounding and control cut-in flag */
{
- if ( FT_ABS( distance - org_dist ) > control_value_cutin )
+ FT_F26Dot6 delta;
+
+
+ delta = SUB_LONG( distance, org_dist );
+ if ( delta < 0 )
+ delta = NEG_LONG( delta );
+
+ if ( delta > control_value_cutin )
distance = org_dist;
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
@@ -5991,7 +6012,7 @@
exc->tt_metrics.compensations[0] );
}
- exc->func_move( exc, &exc->zp0, point, distance - org_dist );
+ exc->func_move( exc, &exc->zp0, point, SUB_LONG( distance, org_dist ) );
Fail:
exc->GS.rp0 = point;
@@ -6074,8 +6095,12 @@
/* single width cut-in test */
- if ( FT_ABS( org_dist - exc->GS.single_width_value ) <
- exc->GS.single_width_cutin )
+ /* |org_dist - single_width_value| < single_width_cutin */
+ if ( exc->GS.single_width_cutin > 0 &&
+ org_dist < exc->GS.single_width_value +
+ exc->GS.single_width_cutin &&
+ org_dist > exc->GS.single_width_value -
+ exc->GS.single_width_cutin )
{
if ( org_dist >= 0 )
org_dist = exc->GS.single_width_value;
@@ -6168,7 +6193,7 @@
minimum_distance = exc->GS.minimum_distance;
control_value_cutin = exc->GS.control_value_cutin;
point = (FT_UShort)args[0];
- cvtEntry = (FT_ULong)( args[1] + 1 );
+ cvtEntry = (FT_ULong)( ADD_LONG( args[1], 1 ) );
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
if ( SUBPIXEL_HINTING_INFINALITY &&
@@ -6251,6 +6276,9 @@
if ( exc->GS.gep0 == exc->GS.gep1 )
{
+ FT_F26Dot6 delta;
+
+
/* XXX: According to Greg Hitchcock, the following wording is */
/* the right one: */
/* */
@@ -6263,7 +6291,11 @@
/* `ttinst2.doc', version 1.66, is thus incorrect since */
/* it implies `>=' instead of `>'. */
- if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin )
+ delta = SUB_LONG( cvt_dist, org_dist );
+ if ( delta < 0 )
+ delta = NEG_LONG( delta );
+
+ if ( delta > control_value_cutin )
cvt_dist = org_dist;
}
@@ -6281,7 +6313,14 @@
exc->ignore_x_mode &&
exc->GS.gep0 == exc->GS.gep1 )
{
- if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin )
+ FT_F26Dot6 delta;
+
+
+ delta = SUB_LONG( cvt_dist, org_dist );
+ if ( delta < 0 )
+ delta = NEG_LONG( delta );
+
+ if ( delta > control_value_cutin )
cvt_dist = org_dist;
}
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
@@ -7153,7 +7192,7 @@
SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP ) &&
( B1 & 63 ) != 0 &&
( B2 & 63 ) != 0 ) ) )
- exc->func_move( exc, &exc->zp0, A, -B );
+ exc->func_move( exc, &exc->zp0, A, NEG_LONG( B ) );
}
}
else
@@ -7524,8 +7563,16 @@
return;
}
- for ( i = 0; i < num_axes; i++ )
- args[i] = coords[i] >> 2; /* convert 16.16 to 2.14 format */
+ if ( coords )
+ {
+ for ( i = 0; i < num_axes; i++ )
+ args[i] = coords[i] >> 2; /* convert 16.16 to 2.14 format */
+ }
+ else
+ {
+ for ( i = 0; i < num_axes; i++ )
+ args[i] = 0;
+ }
}
@@ -8478,7 +8525,9 @@
} while ( !exc->instruction_trap );
LNo_Error_:
- FT_TRACE4(( " %d instructions executed\n", ins_counter ));
+ FT_TRACE4(( " %d instruction%s executed\n",
+ ins_counter,
+ ins_counter == 1 ? "" : "s" ));
return FT_Err_Ok;
LErrorCodeOverflow_:
diff --git a/thirdparty/freetype/src/truetype/ttinterp.h b/thirdparty/freetype/src/truetype/ttinterp.h
index abbecfcee3..2966439ea2 100644
--- a/thirdparty/freetype/src/truetype/ttinterp.h
+++ b/thirdparty/freetype/src/truetype/ttinterp.h
@@ -4,7 +4,7 @@
/* */
/* TrueType bytecode interpreter (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/truetype/ttobjs.c b/thirdparty/freetype/src/truetype/ttobjs.c
index 081fa2f1a5..6685dc8196 100644
--- a/thirdparty/freetype/src/truetype/ttobjs.c
+++ b/thirdparty/freetype/src/truetype/ttobjs.c
@@ -4,7 +4,7 @@
/* */
/* Objects manager (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -21,7 +21,7 @@
#include FT_INTERNAL_STREAM_H
#include FT_TRUETYPE_TAGS_H
#include FT_INTERNAL_SFNT_H
-#include FT_TRUETYPE_DRIVER_H
+#include FT_DRIVER_H
#include "ttgload.h"
#include "ttpload.h"
@@ -147,7 +147,7 @@
{
#define TRICK_NAMES_MAX_CHARACTERS 19
-#define TRICK_NAMES_COUNT 18
+#define TRICK_NAMES_COUNT 26
static const char trick_names[TRICK_NAMES_COUNT]
[TRICK_NAMES_MAX_CHARACTERS + 1] =
@@ -165,9 +165,17 @@
"cpop", /* dftt-p7.ttf; version 1.00, 1992 [DLJGyShoMedium] */
"DFGirl-W6-WIN-BF", /* dftt-h6.ttf; version 1.00, 1993 */
+ "DFGothic-EB", /* DynaLab Inc. 1992-1995 */
+ "DFGyoSho-Lt", /* DynaLab Inc. 1992-1995 */
+ "DFHei-Md-HK-BF", /* maybe DynaLab Inc. */
+ "DFHSGothic-W5", /* DynaLab Inc. 1992-1995 */
+ "DFHSMincho-W3", /* DynaLab Inc. 1992-1995 */
+ "DFHSMincho-W7", /* DynaLab Inc. 1992-1995 */
"DFKaiSho-SB", /* dfkaisb.ttf */
"DFKaiShu",
+ "DFKaiShu-Md-HK-BF", /* maybe DynaLab Inc. */
"DFKai-SB", /* kaiu.ttf; version 3.00, 1998 [DFKaiShu-SB-Estd-BF] */
+ "DFMing-Bd-HK-BF", /* maybe DynaLab Inc. */
"DLC", /* dftt-m7.ttf; version 1.00, 1993 [DLCMingBold] */
/* dftt-f5.ttf; version 1.00, 1993 [DLCFongSung] */
"DLCHayMedium", /* dftt-b5.ttf; version 1.00, 1993 */
@@ -265,7 +273,7 @@
tt_check_trickyness_sfnt_ids( TT_Face face )
{
#define TRICK_SFNT_IDS_PER_FACE 3
-#define TRICK_SFNT_IDS_NUM_FACES 19
+#define TRICK_SFNT_IDS_NUM_FACES 29
static const tt_sfnt_id_rec sfnt_id[TRICK_SFNT_IDS_NUM_FACES]
[TRICK_SFNT_IDS_PER_FACE] = {
@@ -284,6 +292,36 @@
{ 0x28233BF1UL, 0x000087C4UL }, /* fpgm */
{ 0xA344A1EBUL, 0x000001E1UL } /* prep */
},
+ { /* DFGothic-EB */
+ { 0x12C3EBB2UL, 0x00000350UL }, /* cvt */
+ { 0xB680EE64UL, 0x000087A7UL }, /* fpgm */
+ { 0xCE939563UL, 0x00000758UL } /* prep */
+ },
+ { /* DFGyoSho-Lt */
+ { 0x11E5EAD4UL, 0x00000350UL }, /* cvt */
+ { 0xCE5956E9UL, 0x0000BC85UL }, /* fpgm */
+ { 0x8272F416UL, 0x00000045UL } /* prep */
+ },
+ { /* DFHei-Md-HK-BF */
+ { 0x1257EB46UL, 0x00000350UL }, /* cvt */
+ { 0xF699D160UL, 0x0000715FUL }, /* fpgm */
+ { 0xD222F568UL, 0x000003BCUL } /* prep */
+ },
+ { /* DFHSGothic-W5 */
+ { 0x1262EB4EUL, 0x00000350UL }, /* cvt */
+ { 0xE86A5D64UL, 0x00007940UL }, /* fpgm */
+ { 0x7850F729UL, 0x000005FFUL } /* prep */
+ },
+ { /* DFHSMincho-W3 */
+ { 0x122DEB0AUL, 0x00000350UL }, /* cvt */
+ { 0x3D16328AUL, 0x0000859BUL }, /* fpgm */
+ { 0xA93FC33BUL, 0x000002CBUL } /* prep */
+ },
+ { /* DFHSMincho-W7 */
+ { 0x125FEB26UL, 0x00000350UL }, /* cvt */
+ { 0xA5ACC982UL, 0x00007EE1UL }, /* fpgm */
+ { 0x90999196UL, 0x0000041FUL } /* prep */
+ },
{ /* DFKaiShu */
{ 0x11E5EAD4UL, 0x00000350UL }, /* cvt */
{ 0x5A30CA3BUL, 0x00009063UL }, /* fpgm */
@@ -294,6 +332,26 @@
{ 0xA6E78C01UL, 0x00008998UL }, /* fpgm */
{ 0x13A42602UL, 0x0000007EUL } /* prep */
},
+ { /* DFKaiShu-Md-HK-BF */
+ { 0x11E5EAD4UL, 0x00000360UL }, /* cvt */
+ { 0x9DB282B2UL, 0x0000C06EUL }, /* fpgm */
+ { 0x53E6D7CAUL, 0x00000082UL } /* prep */
+ },
+ { /* DFMing-Bd-HK-BF */
+ { 0x1243EB18UL, 0x00000350UL }, /* cvt */
+ { 0xBA0A8C30UL, 0x000074ADUL }, /* fpgm */
+ { 0xF3D83409UL, 0x0000037BUL } /* prep */
+ },
+ { /* DLCLiShu */
+ { 0x07DCF546UL, 0x00000308UL }, /* cvt */
+ { 0x40FE7C90UL, 0x00008E2AUL }, /* fpgm */
+ { 0x608174B5UL, 0x0000007AUL } /* prep */
+ },
+ { /* DLCHayBold */
+ { 0xEB891238UL, 0x00000308UL }, /* cvt */
+ { 0xD2E4DCD4UL, 0x0000676FUL }, /* fpgm */
+ { 0x8EA5F293UL, 0x000003B8UL } /* prep */
+ },
{ /* HuaTianKaiTi */
{ 0xFFFBFFFCUL, 0x00000008UL }, /* cvt */
{ 0x9C9E48B8UL, 0x0000BEA2UL }, /* fpgm */
@@ -657,46 +715,17 @@
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
{
- FT_Int instance_index = face_index >> 16;
+ FT_UInt instance_index = (FT_UInt)face_index >> 16;
if ( FT_HAS_MULTIPLE_MASTERS( ttface ) &&
instance_index > 0 )
{
- error = TT_Get_MM_Var( face, NULL );
+ error = TT_Set_Named_Instance( face, instance_index );
if ( error )
goto Exit;
- if ( face->blend->mmvar->namedstyle )
- {
- FT_Memory memory = ttface->memory;
-
- FT_Var_Named_Style* named_style;
- FT_String* style_name;
-
-
- /* in `face_index', the instance index starts with value 1 */
- named_style = face->blend->mmvar->namedstyle + instance_index - 1;
- error = sfnt->get_name( face,
- (FT_UShort)named_style->strid,
- &style_name );
- if ( error )
- goto Exit;
-
- /* set style name; if already set, replace it */
- if ( face->root.style_name )
- FT_FREE( face->root.style_name );
- face->root.style_name = style_name;
-
- /* finally, select the named instance */
- error = TT_Set_Var_Design( face,
- face->blend->mmvar->num_axis,
- named_style->coords );
- if ( error )
- goto Exit;
-
- tt_apply_mvar( face );
- }
+ tt_apply_mvar( face );
}
}
diff --git a/thirdparty/freetype/src/truetype/ttobjs.h b/thirdparty/freetype/src/truetype/ttobjs.h
index cdacee75e5..38fa30e4e9 100644
--- a/thirdparty/freetype/src/truetype/ttobjs.h
+++ b/thirdparty/freetype/src/truetype/ttobjs.h
@@ -4,7 +4,7 @@
/* */
/* Objects manager (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/truetype/ttpic.c b/thirdparty/freetype/src/truetype/ttpic.c
index 66bd7e1934..cdbb80639e 100644
--- a/thirdparty/freetype/src/truetype/ttpic.c
+++ b/thirdparty/freetype/src/truetype/ttpic.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for truetype module. */
/* */
-/* Copyright 2009-2017 by */
+/* Copyright 2009-2018 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/truetype/ttpic.h b/thirdparty/freetype/src/truetype/ttpic.h
index 1410cd73c3..df878ae6f1 100644
--- a/thirdparty/freetype/src/truetype/ttpic.h
+++ b/thirdparty/freetype/src/truetype/ttpic.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for truetype module. */
/* */
-/* Copyright 2009-2017 by */
+/* Copyright 2009-2018 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/truetype/ttpload.c b/thirdparty/freetype/src/truetype/ttpload.c
index bcf6b34f67..d9526ad082 100644
--- a/thirdparty/freetype/src/truetype/ttpload.c
+++ b/thirdparty/freetype/src/truetype/ttpload.c
@@ -4,7 +4,7 @@
/* */
/* TrueType-specific tables loader (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/truetype/ttpload.h b/thirdparty/freetype/src/truetype/ttpload.h
index 79079f345a..fa12527247 100644
--- a/thirdparty/freetype/src/truetype/ttpload.h
+++ b/thirdparty/freetype/src/truetype/ttpload.h
@@ -4,7 +4,7 @@
/* */
/* TrueType-specific tables loader (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/truetype/ttsubpix.c b/thirdparty/freetype/src/truetype/ttsubpix.c
index 1c8cf01109..d94bcc8b50 100644
--- a/thirdparty/freetype/src/truetype/ttsubpix.c
+++ b/thirdparty/freetype/src/truetype/ttsubpix.c
@@ -4,7 +4,7 @@
/* */
/* TrueType Subpixel Hinting. */
/* */
-/* Copyright 2010-2017 by */
+/* Copyright 2010-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -22,7 +22,7 @@
#include FT_INTERNAL_SFNT_H
#include FT_TRUETYPE_TAGS_H
#include FT_OUTLINE_H
-#include FT_TRUETYPE_DRIVER_H
+#include FT_DRIVER_H
#include "ttsubpix.h"
@@ -753,24 +753,24 @@
/* Does font name match rule family? */
- if ( strcmp( detected_font_name, rule_font_name ) == 0 )
+ if ( ft_strcmp( detected_font_name, rule_font_name ) == 0 )
return TRUE;
/* Is font name a wildcard ""? */
- if ( strcmp( rule_font_name, "" ) == 0 )
+ if ( ft_strcmp( rule_font_name, "" ) == 0 )
return TRUE;
/* Is font name contained in a class list? */
for ( i = 0; i < FAMILY_CLASS_RULES_SIZE; i++ )
{
- if ( strcmp( FAMILY_CLASS_Rules[i].name, rule_font_name ) == 0 )
+ if ( ft_strcmp( FAMILY_CLASS_Rules[i].name, rule_font_name ) == 0 )
{
for ( j = 0; j < SPH_MAX_CLASS_MEMBERS; j++ )
{
- if ( strcmp( FAMILY_CLASS_Rules[i].member[j], "" ) == 0 )
+ if ( ft_strcmp( FAMILY_CLASS_Rules[i].member[j], "" ) == 0 )
continue;
- if ( strcmp( FAMILY_CLASS_Rules[i].member[j],
- detected_font_name ) == 0 )
+ if ( ft_strcmp( FAMILY_CLASS_Rules[i].member[j],
+ detected_font_name ) == 0 )
return TRUE;
}
}
@@ -788,24 +788,24 @@
/* Does font style match rule style? */
- if ( strcmp( detected_font_style, rule_font_style ) == 0 )
+ if ( ft_strcmp( detected_font_style, rule_font_style ) == 0 )
return TRUE;
/* Is font style a wildcard ""? */
- if ( strcmp( rule_font_style, "" ) == 0 )
+ if ( ft_strcmp( rule_font_style, "" ) == 0 )
return TRUE;
/* Is font style contained in a class list? */
for ( i = 0; i < STYLE_CLASS_RULES_SIZE; i++ )
{
- if ( strcmp( STYLE_CLASS_Rules[i].name, rule_font_style ) == 0 )
+ if ( ft_strcmp( STYLE_CLASS_Rules[i].name, rule_font_style ) == 0 )
{
for ( j = 0; j < SPH_MAX_CLASS_MEMBERS; j++ )
{
- if ( strcmp( STYLE_CLASS_Rules[i].member[j], "" ) == 0 )
+ if ( ft_strcmp( STYLE_CLASS_Rules[i].member[j], "" ) == 0 )
continue;
- if ( strcmp( STYLE_CLASS_Rules[i].member[j],
- detected_font_style ) == 0 )
+ if ( ft_strcmp( STYLE_CLASS_Rules[i].member[j],
+ detected_font_style ) == 0 )
return TRUE;
}
}
diff --git a/thirdparty/freetype/src/truetype/ttsubpix.h b/thirdparty/freetype/src/truetype/ttsubpix.h
index c68f97ff07..1070bb016f 100644
--- a/thirdparty/freetype/src/truetype/ttsubpix.h
+++ b/thirdparty/freetype/src/truetype/ttsubpix.h
@@ -4,7 +4,7 @@
/* */
/* TrueType Subpixel Hinting. */
/* */
-/* Copyright 2010-2017 by */
+/* Copyright 2010-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/type1/module.mk b/thirdparty/freetype/src/type1/module.mk
index f299d6fe88..3fea5cc16f 100644
--- a/thirdparty/freetype/src/type1/module.mk
+++ b/thirdparty/freetype/src/type1/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2017 by
+# Copyright 1996-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/type1/rules.mk b/thirdparty/freetype/src/type1/rules.mk
index 97bef288f0..cb1a142860 100644
--- a/thirdparty/freetype/src/type1/rules.mk
+++ b/thirdparty/freetype/src/type1/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2017 by
+# Copyright 1996-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/type1/t1afm.c b/thirdparty/freetype/src/type1/t1afm.c
index 11a2646fc2..61053d9a64 100644
--- a/thirdparty/freetype/src/type1/t1afm.c
+++ b/thirdparty/freetype/src/type1/t1afm.c
@@ -4,7 +4,7 @@
/* */
/* AFM support for Type 1 fonts (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/type1/t1afm.h b/thirdparty/freetype/src/type1/t1afm.h
index 9f62cd013d..cb8d302b4d 100644
--- a/thirdparty/freetype/src/type1/t1afm.h
+++ b/thirdparty/freetype/src/type1/t1afm.h
@@ -4,7 +4,7 @@
/* */
/* AFM support for Type 1 fonts (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/type1/t1driver.c b/thirdparty/freetype/src/type1/t1driver.c
index c2089947f9..029b410b47 100644
--- a/thirdparty/freetype/src/type1/t1driver.c
+++ b/thirdparty/freetype/src/type1/t1driver.c
@@ -4,7 +4,7 @@
/* */
/* Type 1 driver interface (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -30,6 +30,8 @@
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_HASH_H
+#include FT_INTERNAL_POSTSCRIPT_PROPS_H
+#include FT_DRIVER_H
#include FT_SERVICE_MULTIPLE_MASTERS_H
#include FT_SERVICE_GLYPH_DICT_H
@@ -37,6 +39,7 @@
#include FT_SERVICE_POSTSCRIPT_NAME_H
#include FT_SERVICE_POSTSCRIPT_CMAPS_H
#include FT_SERVICE_POSTSCRIPT_INFO_H
+#include FT_SERVICE_PROPERTIES_H
#include FT_SERVICE_KERNING_H
@@ -126,6 +129,7 @@
(FT_Get_MM_Var_Func) T1_Get_MM_Var, /* get_mm_var */
(FT_Set_Var_Design_Func)T1_Set_Var_Design, /* set_var_design */
(FT_Get_Var_Design_Func)T1_Get_Var_Design, /* get_var_design */
+ (FT_Set_Instance_Func) T1_Reset_MM_Blend, /* set_instance */
(FT_Get_Var_Blend_Func) NULL, /* get_var_blend */
(FT_Done_Blend_Func) T1_Done_Blend /* done_blend */
@@ -614,6 +618,18 @@
/*
+ * PROPERTY SERVICE
+ *
+ */
+
+ FT_DEFINE_SERVICE_PROPERTIESREC(
+ t1_service_properties,
+
+ (FT_Properties_SetFunc)ps_property_set, /* set_property */
+ (FT_Properties_GetFunc)ps_property_get ) /* get_property */
+
+
+ /*
* SERVICE LIST
*
*/
@@ -624,6 +640,7 @@
{ FT_SERVICE_ID_GLYPH_DICT, &t1_service_glyph_dict },
{ FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_TYPE_1 },
{ FT_SERVICE_ID_POSTSCRIPT_INFO, &t1_service_ps_info },
+ { FT_SERVICE_ID_PROPERTIES, &t1_service_properties },
#ifndef T1_CONFIG_OPTION_NO_AFM
{ FT_SERVICE_ID_KERNING, &t1_service_kerning },
@@ -713,7 +730,7 @@
FT_MODULE_DRIVER_SCALABLE |
FT_MODULE_DRIVER_HAS_HINTER,
- sizeof ( FT_DriverRec ),
+ sizeof ( PS_DriverRec ),
"type1",
0x10000L,
diff --git a/thirdparty/freetype/src/type1/t1driver.h b/thirdparty/freetype/src/type1/t1driver.h
index 292786448d..2b1507233d 100644
--- a/thirdparty/freetype/src/type1/t1driver.h
+++ b/thirdparty/freetype/src/type1/t1driver.h
@@ -4,7 +4,7 @@
/* */
/* High-level Type 1 driver interface (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/type1/t1errors.h b/thirdparty/freetype/src/type1/t1errors.h
index 492dbb4a42..9e0151b957 100644
--- a/thirdparty/freetype/src/type1/t1errors.h
+++ b/thirdparty/freetype/src/type1/t1errors.h
@@ -4,7 +4,7 @@
/* */
/* Type 1 error codes (specification only). */
/* */
-/* Copyright 2001-2017 by */
+/* Copyright 2001-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/type1/t1gload.c b/thirdparty/freetype/src/type1/t1gload.c
index aaf19b6dcc..87d40e7566 100644
--- a/thirdparty/freetype/src/type1/t1gload.c
+++ b/thirdparty/freetype/src/type1/t1gload.c
@@ -4,7 +4,7 @@
/* */
/* Type 1 Glyph Loader (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -23,6 +23,8 @@
#include FT_INTERNAL_STREAM_H
#include FT_OUTLINE_H
#include FT_INTERNAL_POSTSCRIPT_AUX_H
+#include FT_INTERNAL_CFF_TYPES_H
+#include FT_DRIVER_H
#include "t1errors.h"
@@ -37,37 +39,28 @@
#define FT_COMPONENT trace_t1gload
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
- /********** *********/
- /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
- /********** *********/
- /********** The following code is in charge of computing *********/
- /********** the maximum advance width of the font. It *********/
- /********** quickly processes each glyph charstring to *********/
- /********** extract the value from either a `sbw' or `seac' *********/
- /********** operator. *********/
- /********** *********/
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
-
-
static FT_Error
T1_Parse_Glyph_And_Get_Char_String( T1_Decoder decoder,
FT_UInt glyph_index,
- FT_Data* char_string )
+ FT_Data* char_string,
+ FT_Bool* force_scaling )
{
T1_Face face = (T1_Face)decoder->builder.face;
T1_Font type1 = &face->type1;
FT_Error error = FT_Err_Ok;
+ PSAux_Service psaux = (PSAux_Service)face->psaux;
+ const T1_Decoder_Funcs decoder_funcs = psaux->t1_decoder_funcs;
+ PS_Decoder psdecoder;
+
#ifdef FT_CONFIG_OPTION_INCREMENTAL
FT_Incremental_InterfaceRec *inc =
face->root.internal->incremental_interface;
#endif
+#ifdef T1_CONFIG_OPTION_OLD_ENGINE
+ PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( face );
+#endif
decoder->font_matrix = type1->font_matrix;
decoder->font_offset = type1->font_offset;
@@ -90,9 +83,56 @@
}
if ( !error )
- error = decoder->funcs.parse_charstrings(
- decoder, (FT_Byte*)char_string->pointer,
- (FT_UInt)char_string->length );
+ {
+ /* choose which renderer to use */
+#ifdef T1_CONFIG_OPTION_OLD_ENGINE
+ if ( driver->hinting_engine == FT_HINTING_FREETYPE ||
+ decoder->builder.metrics_only )
+ error = decoder_funcs->parse_charstrings_old(
+ decoder,
+ (FT_Byte*)char_string->pointer,
+ (FT_UInt)char_string->length );
+#else
+ if ( decoder->builder.metrics_only )
+ error = decoder_funcs->parse_metrics(
+ decoder,
+ (FT_Byte*)char_string->pointer,
+ (FT_UInt)char_string->length );
+#endif
+ else
+ {
+ CFF_SubFontRec subfont;
+
+
+ psaux->ps_decoder_init( &psdecoder, decoder, TRUE );
+
+ psaux->t1_make_subfont( FT_FACE( face ),
+ &face->type1.private_dict, &subfont );
+ psdecoder.current_subfont = &subfont;
+
+ error = decoder_funcs->parse_charstrings(
+ &psdecoder,
+ (FT_Byte*)char_string->pointer,
+ (FT_ULong)char_string->length );
+
+ /* Adobe's engine uses 16.16 numbers everywhere; */
+ /* as a consequence, glyphs larger than 2000ppem get rejected */
+ if ( FT_ERR_EQ( error, Glyph_Too_Big ) )
+ {
+ /* this time, we retry unhinted and scale up the glyph later on */
+ /* (the engine uses and sets the hardcoded value 0x10000 / 64 = */
+ /* 0x400 for both `x_scale' and `y_scale' in this case) */
+ ((T1_GlyphSlot)decoder->builder.glyph)->hint = FALSE;
+
+ *force_scaling = TRUE;
+
+ error = decoder_funcs->parse_charstrings(
+ &psdecoder,
+ (FT_Byte*)char_string->pointer,
+ (FT_ULong)char_string->length );
+ }
+ }
+ }
#ifdef FT_CONFIG_OPTION_INCREMENTAL
@@ -126,8 +166,10 @@
FT_UInt glyph_index )
{
FT_Data glyph_data;
- FT_Error error = T1_Parse_Glyph_And_Get_Char_String(
- decoder, glyph_index, &glyph_data );
+ FT_Bool force_scaling = FALSE;
+ FT_Error error = T1_Parse_Glyph_And_Get_Char_String(
+ decoder, glyph_index, &glyph_data,
+ &force_scaling );
#ifdef FT_CONFIG_OPTION_INCREMENTAL
@@ -149,6 +191,23 @@
}
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /********** *********/
+ /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
+ /********** *********/
+ /********** The following code is in charge of computing *********/
+ /********** the maximum advance width of the font. It *********/
+ /********** quickly processes each glyph charstring to *********/
+ /********** extract the value from either a `sbw' or `seac' *********/
+ /********** operator. *********/
+ /********** *********/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
FT_LOCAL_DEF( FT_Error )
T1_Compute_Max_Advance( T1_Face face,
FT_Pos* max_advance )
@@ -278,6 +337,8 @@
T1_DecoderRec decoder;
T1_Face face = (T1_Face)t1glyph->face;
FT_Bool hinting;
+ FT_Bool scaled;
+ FT_Bool force_scaling = FALSE;
T1_Font type1 = &face->type1;
PSAux_Service psaux = (PSAux_Service)face->psaux;
const T1_Decoder_Funcs decoder_funcs = psaux->t1_decoder_funcs;
@@ -325,7 +386,10 @@
hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 &&
( load_flags & FT_LOAD_NO_HINTING ) == 0 );
+ scaled = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 );
+ glyph->hint = hinting;
+ glyph->scaled = scaled;
t1glyph->format = FT_GLYPH_FORMAT_OUTLINE;
error = decoder_funcs->init( &decoder,
@@ -355,13 +419,15 @@
/* now load the unscaled outline */
error = T1_Parse_Glyph_And_Get_Char_String( &decoder, glyph_index,
- &glyph_data );
+ &glyph_data,
+ &force_scaling );
if ( error )
goto Exit;
#ifdef FT_CONFIG_OPTION_INCREMENTAL
glyph_data_loaded = 1;
#endif
+ hinting = glyph->hint;
font_matrix = decoder.font_matrix;
font_offset = decoder.font_offset;
@@ -451,7 +517,7 @@
}
#endif
- if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
+ if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || force_scaling )
{
/* scale the outline and the metrics */
FT_Int n;
diff --git a/thirdparty/freetype/src/type1/t1gload.h b/thirdparty/freetype/src/type1/t1gload.h
index cc4d5e734f..72ef76f6ae 100644
--- a/thirdparty/freetype/src/type1/t1gload.h
+++ b/thirdparty/freetype/src/type1/t1gload.h
@@ -4,7 +4,7 @@
/* */
/* Type 1 Glyph Loader (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/type1/t1load.c b/thirdparty/freetype/src/type1/t1load.c
index f569d6bec3..9dfa637a69 100644
--- a/thirdparty/freetype/src/type1/t1load.c
+++ b/thirdparty/freetype/src/type1/t1load.c
@@ -4,7 +4,7 @@
/* */
/* Type 1 font loader (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -366,14 +366,16 @@
}
- FT_LOCAL_DEF( FT_Error )
- T1_Set_MM_Blend( T1_Face face,
+ static FT_Error
+ t1_set_mm_blend( T1_Face face,
FT_UInt num_coords,
FT_Fixed* coords )
{
PS_Blend blend = face->blend;
FT_UInt n, m;
+ FT_Bool have_diff = 0;
+
if ( !blend )
return FT_THROW( Invalid_Argument );
@@ -405,9 +407,36 @@
result = FT_MulFix( result, factor );
}
- blend->weight_vector[n] = result;
+
+ if ( blend->weight_vector[n] != result )
+ {
+ blend->weight_vector[n] = result;
+ have_diff = 1;
+ }
}
+ /* return value -1 indicates `no change' */
+ return have_diff ? FT_Err_Ok : -1;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ T1_Set_MM_Blend( T1_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords )
+ {
+ FT_Error error;
+
+
+ error = t1_set_mm_blend( face, num_coords, coords );
+ if ( error )
+ return error;
+
+ if ( num_coords )
+ face->root.face_flags |= FT_FACE_FLAG_VARIATION;
+ else
+ face->root.face_flags &= ~FT_FACE_FLAG_VARIATION;
+
return FT_Err_Ok;
}
@@ -452,6 +481,7 @@
FT_UInt num_coords,
FT_Long* coords )
{
+ FT_Error error;
PS_Blend blend = face->blend;
FT_UInt n, p;
FT_Fixed final_blends[T1_MAX_MM_DESIGNS];
@@ -518,7 +548,28 @@
final_blends[n] = the_blend;
}
- return T1_Set_MM_Blend( face, blend->num_axis, final_blends );
+ error = t1_set_mm_blend( face, blend->num_axis, final_blends );
+ if ( error )
+ return error;
+
+ if ( num_coords )
+ face->root.face_flags |= FT_FACE_FLAG_VARIATION;
+ else
+ face->root.face_flags &= ~FT_FACE_FLAG_VARIATION;
+
+ return FT_Err_Ok;
+ }
+
+
+ /* MM fonts don't have named instances, so only the design is reset */
+
+ FT_LOCAL_DEF( FT_Error )
+ T1_Reset_MM_Blend( T1_Face face,
+ FT_UInt instance_index )
+ {
+ FT_UNUSED( instance_index );
+
+ return T1_Set_MM_Blend( face, 0, NULL );
}
@@ -1266,7 +1317,7 @@
if ( ft_isdigit( *cur ) || *cur == '[' )
{
T1_Encoding encode = &face->type1.encoding;
- FT_Int count, n;
+ FT_Int count, array_size, n;
PS_Table char_table = &loader->encoding_table;
FT_Memory memory = parser->root.memory;
FT_Error error;
@@ -1283,13 +1334,12 @@
else
count = (FT_Int)T1_ToInt( parser );
- /* only composite fonts (which we don't support) */
- /* can have larger values */
+ array_size = count;
if ( count > 256 )
{
- FT_ERROR(( "parse_encoding: invalid encoding array size\n" ));
- parser->root.error = FT_THROW( Invalid_File_Format );
- return;
+ FT_TRACE2(( "parse_encoding:"
+ " only using first 256 encoding array entries\n" ));
+ array_size = 256;
}
T1_Skip_Spaces( parser );
@@ -1305,18 +1355,18 @@
}
/* we use a T1_Table to store our charnames */
- loader->num_chars = encode->num_chars = count;
- if ( FT_NEW_ARRAY( encode->char_index, count ) ||
- FT_NEW_ARRAY( encode->char_name, count ) ||
+ loader->num_chars = encode->num_chars = array_size;
+ if ( FT_NEW_ARRAY( encode->char_index, array_size ) ||
+ FT_NEW_ARRAY( encode->char_name, array_size ) ||
FT_SET_ERROR( psaux->ps_table_funcs->init(
- char_table, count, memory ) ) )
+ char_table, array_size, memory ) ) )
{
parser->root.error = error;
return;
}
/* We need to `zero' out encoding_table.elements */
- for ( n = 0; n < count; n++ )
+ for ( n = 0; n < array_size; n++ )
{
char* notdef = (char *)".notdef";
@@ -1409,11 +1459,14 @@
len = (FT_UInt)( parser->root.cursor - cur );
- parser->root.error = T1_Add_Table( char_table, charcode,
- cur, len + 1 );
- if ( parser->root.error )
- return;
- char_table->elements[charcode][len] = '\0';
+ if ( n < array_size )
+ {
+ parser->root.error = T1_Add_Table( char_table, charcode,
+ cur, len + 1 );
+ if ( parser->root.error )
+ return;
+ char_table->elements[charcode][len] = '\0';
+ }
n++;
}
@@ -2440,6 +2493,24 @@
type1->encoding.num_chars = loader.num_chars;
}
+ /* some sanitizing to avoid overflows later on; */
+ /* the upper limits are ad-hoc values */
+ if ( priv->blue_shift > 1000 || priv->blue_shift < 0 )
+ {
+ FT_TRACE2(( "T1_Open_Face:"
+ " setting unlikely BlueShift value %d to default (7)\n",
+ priv->blue_shift ));
+ priv->blue_shift = 7;
+ }
+
+ if ( priv->blue_fuzz > 1000 || priv->blue_fuzz < 0 )
+ {
+ FT_TRACE2(( "T1_Open_Face:"
+ " setting unlikely BlueFuzz value %d to default (1)\n",
+ priv->blue_fuzz ));
+ priv->blue_fuzz = 1;
+ }
+
Exit:
t1_done_loader( &loader );
return error;
diff --git a/thirdparty/freetype/src/type1/t1load.h b/thirdparty/freetype/src/type1/t1load.h
index 2d86984f0e..03be3f7f93 100644
--- a/thirdparty/freetype/src/type1/t1load.h
+++ b/thirdparty/freetype/src/type1/t1load.h
@@ -4,7 +4,7 @@
/* */
/* Type 1 font loader (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -90,6 +90,10 @@ FT_BEGIN_HEADER
FT_Long* coords );
FT_LOCAL( FT_Error )
+ T1_Reset_MM_Blend( T1_Face face,
+ FT_UInt instance_index );
+
+ FT_LOCAL( FT_Error )
T1_Get_Var_Design( T1_Face face,
FT_UInt num_coords,
FT_Fixed* coords );
diff --git a/thirdparty/freetype/src/type1/t1objs.c b/thirdparty/freetype/src/type1/t1objs.c
index 5ac1292ae0..7333c4c958 100644
--- a/thirdparty/freetype/src/type1/t1objs.c
+++ b/thirdparty/freetype/src/type1/t1objs.c
@@ -4,7 +4,7 @@
/* */
/* Type 1 objects manager (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -21,6 +21,7 @@
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_STREAM_H
#include FT_TRUETYPE_IDS_H
+#include FT_DRIVER_H
#include "t1gload.h"
#include "t1load.h"
@@ -379,7 +380,7 @@
/* simplistic and might get some things wrong. For a full-featured */
/* algorithm you might have a look at the whitepaper given at */
/* */
- /* http://blogs.msdn.com/text/archive/2007/04/23/wpf-font-selection-model.aspx */
+ /* https://blogs.msdn.com/text/archive/2007/04/23/wpf-font-selection-model.aspx */
/* get style name -- be careful, some broken fonts only */
/* have a `/FontName' dictionary entry! */
@@ -578,9 +579,42 @@
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
- T1_Driver_Init( FT_Module driver )
+ T1_Driver_Init( FT_Module module )
{
- FT_UNUSED( driver );
+ PS_Driver driver = (PS_Driver)module;
+
+ FT_UInt32 seed;
+
+
+ /* set default property values, cf. `ftt1drv.h' */
+#ifdef T1_CONFIG_OPTION_OLD_ENGINE
+ driver->hinting_engine = FT_HINTING_FREETYPE;
+#else
+ driver->hinting_engine = FT_HINTING_ADOBE;
+#endif
+
+ driver->no_stem_darkening = TRUE;
+
+ driver->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1;
+ driver->darken_params[1] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1;
+ driver->darken_params[2] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2;
+ driver->darken_params[3] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2;
+ driver->darken_params[4] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3;
+ driver->darken_params[5] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3;
+ driver->darken_params[6] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4;
+ driver->darken_params[7] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4;
+
+ /* compute random seed from some memory addresses */
+ seed = (FT_UInt32)( (FT_Offset)(char*)&seed ^
+ (FT_Offset)(char*)&module ^
+ (FT_Offset)(char*)module->memory );
+ seed = seed ^ ( seed >> 10 ) ^ ( seed >> 20 );
+
+ driver->random_seed = (FT_Int32)seed;
+ if ( driver->random_seed < 0 )
+ driver->random_seed = -driver->random_seed;
+ else if ( driver->random_seed == 0 )
+ driver->random_seed = 123456789;
return FT_Err_Ok;
}
diff --git a/thirdparty/freetype/src/type1/t1objs.h b/thirdparty/freetype/src/type1/t1objs.h
index 39d26bf8b9..8298e036f4 100644
--- a/thirdparty/freetype/src/type1/t1objs.h
+++ b/thirdparty/freetype/src/type1/t1objs.h
@@ -4,7 +4,7 @@
/* */
/* Type 1 objects manager (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -120,12 +120,12 @@ FT_BEGIN_HEADER
FT_Bool hint;
FT_Bool scaled;
- FT_Int max_points;
- FT_Int max_contours;
-
FT_Fixed x_scale;
FT_Fixed y_scale;
+ FT_Int max_points;
+ FT_Int max_contours;
+
} T1_GlyphSlotRec;
diff --git a/thirdparty/freetype/src/type1/t1parse.c b/thirdparty/freetype/src/type1/t1parse.c
index 18dd26434c..8e201e5ef5 100644
--- a/thirdparty/freetype/src/type1/t1parse.c
+++ b/thirdparty/freetype/src/type1/t1parse.c
@@ -4,7 +4,7 @@
/* */
/* Type 1 parser (body). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/type1/t1parse.h b/thirdparty/freetype/src/type1/t1parse.h
index 3396680d1a..4ac82ae913 100644
--- a/thirdparty/freetype/src/type1/t1parse.h
+++ b/thirdparty/freetype/src/type1/t1parse.h
@@ -4,7 +4,7 @@
/* */
/* Type 1 parser (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/type1/t1tokens.h b/thirdparty/freetype/src/type1/t1tokens.h
index ca0c55f903..43a65d88ea 100644
--- a/thirdparty/freetype/src/type1/t1tokens.h
+++ b/thirdparty/freetype/src/type1/t1tokens.h
@@ -4,7 +4,7 @@
/* */
/* Type 1 tokenizer (specification). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/type1/type1.c b/thirdparty/freetype/src/type1/type1.c
index 81795376ef..72eff59bfe 100644
--- a/thirdparty/freetype/src/type1/type1.c
+++ b/thirdparty/freetype/src/type1/type1.c
@@ -4,7 +4,7 @@
/* */
/* FreeType Type 1 driver component (body only). */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/type42/module.mk b/thirdparty/freetype/src/type42/module.mk
index 2f52806808..3d4732bb6f 100644
--- a/thirdparty/freetype/src/type42/module.mk
+++ b/thirdparty/freetype/src/type42/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 2002-2017 by
+# Copyright 2002-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/type42/rules.mk b/thirdparty/freetype/src/type42/rules.mk
index d7e8965015..9325d3898f 100644
--- a/thirdparty/freetype/src/type42/rules.mk
+++ b/thirdparty/freetype/src/type42/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 2002-2017 by
+# Copyright 2002-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/type42/t42drivr.c b/thirdparty/freetype/src/type42/t42drivr.c
index 366cfb3a1d..f579b2708c 100644
--- a/thirdparty/freetype/src/type42/t42drivr.c
+++ b/thirdparty/freetype/src/type42/t42drivr.c
@@ -4,7 +4,7 @@
/* */
/* High-level Type 42 driver interface (body). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* Roberto Alameda. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/type42/t42drivr.h b/thirdparty/freetype/src/type42/t42drivr.h
index 1ac4a0a1a1..3667f3e066 100644
--- a/thirdparty/freetype/src/type42/t42drivr.h
+++ b/thirdparty/freetype/src/type42/t42drivr.h
@@ -4,7 +4,7 @@
/* */
/* High-level Type 42 driver interface (specification). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* Roberto Alameda. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/type42/t42error.h b/thirdparty/freetype/src/type42/t42error.h
index fda92abf57..e3978a7607 100644
--- a/thirdparty/freetype/src/type42/t42error.h
+++ b/thirdparty/freetype/src/type42/t42error.h
@@ -4,7 +4,7 @@
/* */
/* Type 42 error codes (specification only). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/type42/t42objs.c b/thirdparty/freetype/src/type42/t42objs.c
index 1c4ebd768a..66e5c40382 100644
--- a/thirdparty/freetype/src/type42/t42objs.c
+++ b/thirdparty/freetype/src/type42/t42objs.c
@@ -4,7 +4,7 @@
/* */
/* Type 42 objects manager (body). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* Roberto Alameda. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/type42/t42objs.h b/thirdparty/freetype/src/type42/t42objs.h
index eb4c5bf69f..3bad5135e0 100644
--- a/thirdparty/freetype/src/type42/t42objs.h
+++ b/thirdparty/freetype/src/type42/t42objs.h
@@ -4,7 +4,7 @@
/* */
/* Type 42 objects manager (specification). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* Roberto Alameda. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/type42/t42parse.c b/thirdparty/freetype/src/type42/t42parse.c
index e7c6770bd2..4813d1f3f9 100644
--- a/thirdparty/freetype/src/type42/t42parse.c
+++ b/thirdparty/freetype/src/type42/t42parse.c
@@ -4,7 +4,7 @@
/* */
/* Type 42 font parser (body). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* Roberto Alameda. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/type42/t42parse.h b/thirdparty/freetype/src/type42/t42parse.h
index 7a68606f2e..f35d23de63 100644
--- a/thirdparty/freetype/src/type42/t42parse.h
+++ b/thirdparty/freetype/src/type42/t42parse.h
@@ -4,7 +4,7 @@
/* */
/* Type 42 font parser (specification). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* Roberto Alameda. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/type42/t42types.h b/thirdparty/freetype/src/type42/t42types.h
index 2306ab6c77..d0aa2de570 100644
--- a/thirdparty/freetype/src/type42/t42types.h
+++ b/thirdparty/freetype/src/type42/t42types.h
@@ -4,7 +4,7 @@
/* */
/* Type 42 font data types (specification only). */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* Roberto Alameda. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/type42/type42.c b/thirdparty/freetype/src/type42/type42.c
index ae8ac26782..6a89cfbed1 100644
--- a/thirdparty/freetype/src/type42/type42.c
+++ b/thirdparty/freetype/src/type42/type42.c
@@ -4,7 +4,7 @@
/* */
/* FreeType Type 42 driver component. */
/* */
-/* Copyright 2002-2017 by */
+/* Copyright 2002-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/winfonts/fnterrs.h b/thirdparty/freetype/src/winfonts/fnterrs.h
index 4251021a70..3a86af5aac 100644
--- a/thirdparty/freetype/src/winfonts/fnterrs.h
+++ b/thirdparty/freetype/src/winfonts/fnterrs.h
@@ -4,7 +4,7 @@
/* */
/* Win FNT/FON error codes (specification only). */
/* */
-/* Copyright 2001-2017 by */
+/* Copyright 2001-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/thirdparty/freetype/src/winfonts/module.mk b/thirdparty/freetype/src/winfonts/module.mk
index ffc53a19f9..13f9077cfc 100644
--- a/thirdparty/freetype/src/winfonts/module.mk
+++ b/thirdparty/freetype/src/winfonts/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2017 by
+# Copyright 1996-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/winfonts/rules.mk b/thirdparty/freetype/src/winfonts/rules.mk
index 73e825d9ae..d694d1a771 100644
--- a/thirdparty/freetype/src/winfonts/rules.mk
+++ b/thirdparty/freetype/src/winfonts/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2017 by
+# Copyright 1996-2018 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/thirdparty/freetype/src/winfonts/winfnt.c b/thirdparty/freetype/src/winfonts/winfnt.c
index 4c47962319..36bd3148d5 100644
--- a/thirdparty/freetype/src/winfonts/winfnt.c
+++ b/thirdparty/freetype/src/winfonts/winfnt.c
@@ -4,7 +4,7 @@
/* */
/* FreeType font driver for Windows FNT/FON files */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* Copyright 2003 Huw D M Davies for Codeweavers */
/* Copyright 2007 Dmitry Timoshkov for Codeweavers */
diff --git a/thirdparty/freetype/src/winfonts/winfnt.h b/thirdparty/freetype/src/winfonts/winfnt.h
index 884b645a2d..4885c9d745 100644
--- a/thirdparty/freetype/src/winfonts/winfnt.h
+++ b/thirdparty/freetype/src/winfonts/winfnt.h
@@ -4,7 +4,7 @@
/* */
/* FreeType font driver for Windows FNT/FON files */
/* */
-/* Copyright 1996-2017 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* Copyright 2007 Dmitry Timoshkov for Codeweavers */
/* */
diff --git a/thirdparty/libvorbis/COPYING b/thirdparty/libvorbis/COPYING
index 8f1d18cc2b..153b926a15 100644
--- a/thirdparty/libvorbis/COPYING
+++ b/thirdparty/libvorbis/COPYING
@@ -1,4 +1,4 @@
-Copyright (c) 2002-2015 Xiph.org Foundation
+Copyright (c) 2002-2018 Xiph.org Foundation
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
diff --git a/thirdparty/libvorbis/analysis.c b/thirdparty/libvorbis/analysis.c
index 01aa6f30db..0e11a167be 100644
--- a/thirdparty/libvorbis/analysis.c
+++ b/thirdparty/libvorbis/analysis.c
@@ -11,7 +11,6 @@
********************************************************************
function: single-block PCM analysis mode dispatch
- last mod: $Id: analysis.c 16226 2009-07-08 06:43:49Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/backends.h b/thirdparty/libvorbis/backends.h
index ff5bcc95fe..22809d46d5 100644
--- a/thirdparty/libvorbis/backends.h
+++ b/thirdparty/libvorbis/backends.h
@@ -12,7 +12,6 @@
function: libvorbis backend and mapping structures; needed for
static mode headers
- last mod: $Id: backends.h 16962 2010-03-11 07:30:34Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/barkmel.c b/thirdparty/libvorbis/barkmel.c
index 37b6c4c7ba..4b19935f30 100644
--- a/thirdparty/libvorbis/barkmel.c
+++ b/thirdparty/libvorbis/barkmel.c
@@ -11,7 +11,6 @@
********************************************************************
function: bark scale utility
- last mod: $Id: barkmel.c 19454 2015-03-02 22:39:28Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/bitrate.c b/thirdparty/libvorbis/bitrate.c
index 3a71b1dc23..96055140f7 100644
--- a/thirdparty/libvorbis/bitrate.c
+++ b/thirdparty/libvorbis/bitrate.c
@@ -11,7 +11,6 @@
********************************************************************
function: bitrate tracking and management
- last mod: $Id: bitrate.c 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/bitrate.h b/thirdparty/libvorbis/bitrate.h
index db48fcb645..655a68cc09 100644
--- a/thirdparty/libvorbis/bitrate.h
+++ b/thirdparty/libvorbis/bitrate.h
@@ -11,7 +11,6 @@
********************************************************************
function: bitrate tracking and management
- last mod: $Id: bitrate.h 13293 2007-07-24 00:09:47Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/block.c b/thirdparty/libvorbis/block.c
index 345c042769..db245b3e69 100644
--- a/thirdparty/libvorbis/block.c
+++ b/thirdparty/libvorbis/block.c
@@ -11,7 +11,6 @@
********************************************************************
function: PCM data vector blocking, windowing and dis/reassembly
- last mod: $Id: block.c 19457 2015-03-03 00:15:29Z giles $
Handle windowing, overlap-add, etc of the PCM vectors. This is made
more amusing by Vorbis' current two allowed block sizes.
diff --git a/thirdparty/libvorbis/books/coupled/res_books_51.h b/thirdparty/libvorbis/books/coupled/res_books_51.h
index 93910ff481..47df4b221b 100644
--- a/thirdparty/libvorbis/books/coupled/res_books_51.h
+++ b/thirdparty/libvorbis/books/coupled/res_books_51.h
@@ -11,7 +11,6 @@
********************************************************************
*
* function: static codebooks for 5.1 surround
- * last modified: $Id: res_books_51.h 19057 2014-01-22 12:32:31Z xiphmont $
*
********************************************************************/
diff --git a/thirdparty/libvorbis/books/coupled/res_books_stereo.h b/thirdparty/libvorbis/books/coupled/res_books_stereo.h
index 9a9049f6ed..61d934046d 100644
--- a/thirdparty/libvorbis/books/coupled/res_books_stereo.h
+++ b/thirdparty/libvorbis/books/coupled/res_books_stereo.h
@@ -11,7 +11,6 @@
********************************************************************
function: static codebooks autogenerated by huff/huffbuld
- last modified: $Id: res_books_stereo.h 19057 2014-01-22 12:32:31Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/books/floor/floor_books.h b/thirdparty/libvorbis/books/floor/floor_books.h
index e925313f7b..67d5f31a3b 100644
--- a/thirdparty/libvorbis/books/floor/floor_books.h
+++ b/thirdparty/libvorbis/books/floor/floor_books.h
@@ -11,7 +11,6 @@
********************************************************************
function: static codebooks autogenerated by huff/huffbuld
- last modified: $Id: floor_books.h 19057 2014-01-22 12:32:31Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/books/uncoupled/res_books_uncoupled.h b/thirdparty/libvorbis/books/uncoupled/res_books_uncoupled.h
index 736353b675..3d658ec470 100644
--- a/thirdparty/libvorbis/books/uncoupled/res_books_uncoupled.h
+++ b/thirdparty/libvorbis/books/uncoupled/res_books_uncoupled.h
@@ -11,7 +11,6 @@
********************************************************************
function: static codebooks autogenerated by huff/huffbuld
- last modified: $Id: res_books_uncoupled.h 19057 2014-01-22 12:32:31Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/codebook.c b/thirdparty/libvorbis/codebook.c
index 72f8a17a35..78672e222d 100644
--- a/thirdparty/libvorbis/codebook.c
+++ b/thirdparty/libvorbis/codebook.c
@@ -11,7 +11,6 @@
********************************************************************
function: basic codebook pack/unpack/code/decode operations
- last mod: $Id: codebook.c 19457 2015-03-03 00:15:29Z giles $
********************************************************************/
@@ -387,7 +386,7 @@ long vorbis_book_decodevs_add(codebook *book,float *a,oggpack_buffer *b,int n){
t[i] = book->valuelist+entry[i]*book->dim;
}
for(i=0,o=0;i<book->dim;i++,o+=step)
- for (j=0;j<step;j++)
+ for (j=0;o+j<n && j<step;j++)
a[o+j]+=t[j][i];
}
return(0);
@@ -399,41 +398,12 @@ long vorbis_book_decodev_add(codebook *book,float *a,oggpack_buffer *b,int n){
int i,j,entry;
float *t;
- if(book->dim>8){
- for(i=0;i<n;){
- entry = decode_packed_entry_number(book,b);
- if(entry==-1)return(-1);
- t = book->valuelist+entry*book->dim;
- for (j=0;j<book->dim;)
- a[i++]+=t[j++];
- }
- }else{
- for(i=0;i<n;){
- entry = decode_packed_entry_number(book,b);
- if(entry==-1)return(-1);
- t = book->valuelist+entry*book->dim;
- j=0;
- switch((int)book->dim){
- case 8:
- a[i++]+=t[j++];
- case 7:
- a[i++]+=t[j++];
- case 6:
- a[i++]+=t[j++];
- case 5:
- a[i++]+=t[j++];
- case 4:
- a[i++]+=t[j++];
- case 3:
- a[i++]+=t[j++];
- case 2:
- a[i++]+=t[j++];
- case 1:
- a[i++]+=t[j++];
- case 0:
- break;
- }
- }
+ for(i=0;i<n;){
+ entry = decode_packed_entry_number(book,b);
+ if(entry==-1)return(-1);
+ t = book->valuelist+entry*book->dim;
+ for(j=0;i<n && j<book->dim;)
+ a[i++]+=t[j++];
}
}
return(0);
@@ -471,12 +441,13 @@ long vorbis_book_decodevv_add(codebook *book,float **a,long offset,int ch,
long i,j,entry;
int chptr=0;
if(book->used_entries>0){
- for(i=offset/ch;i<(offset+n)/ch;){
+ int m=(offset+n)/ch;
+ for(i=offset/ch;i<m;){
entry = decode_packed_entry_number(book,b);
if(entry==-1)return(-1);
{
const float *t = book->valuelist+entry*book->dim;
- for (j=0;j<book->dim;j++){
+ for (j=0;i<m && j<book->dim;j++){
a[chptr++][i]+=t[j];
if(chptr==ch){
chptr=0;
diff --git a/thirdparty/libvorbis/codebook.h b/thirdparty/libvorbis/codebook.h
index 537d6c12d3..08440c6962 100644
--- a/thirdparty/libvorbis/codebook.h
+++ b/thirdparty/libvorbis/codebook.h
@@ -11,7 +11,6 @@
********************************************************************
function: basic shared codebook operations
- last mod: $Id: codebook.h 19457 2015-03-03 00:15:29Z giles $
********************************************************************/
diff --git a/thirdparty/libvorbis/codec_internal.h b/thirdparty/libvorbis/codec_internal.h
index de1bccaedf..e522be18da 100644
--- a/thirdparty/libvorbis/codec_internal.h
+++ b/thirdparty/libvorbis/codec_internal.h
@@ -11,7 +11,6 @@
********************************************************************
function: libvorbis codec headers
- last mod: $Id: codec_internal.h 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/envelope.c b/thirdparty/libvorbis/envelope.c
index 010c66e2d6..da75237542 100644
--- a/thirdparty/libvorbis/envelope.c
+++ b/thirdparty/libvorbis/envelope.c
@@ -11,7 +11,6 @@
********************************************************************
function: PCM data envelope analysis
- last mod: $Id: envelope.c 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/envelope.h b/thirdparty/libvorbis/envelope.h
index fd15fb32a7..f466efde8a 100644
--- a/thirdparty/libvorbis/envelope.h
+++ b/thirdparty/libvorbis/envelope.h
@@ -11,7 +11,6 @@
********************************************************************
function: PCM data envelope analysis and manipulation
- last mod: $Id: envelope.h 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/floor0.c b/thirdparty/libvorbis/floor0.c
index 213cce4ec8..443c0e5a96 100644
--- a/thirdparty/libvorbis/floor0.c
+++ b/thirdparty/libvorbis/floor0.c
@@ -11,7 +11,6 @@
********************************************************************
function: floor backend 0 implementation
- last mod: $Id: floor0.c 19457 2015-03-03 00:15:29Z giles $
********************************************************************/
diff --git a/thirdparty/libvorbis/floor1.c b/thirdparty/libvorbis/floor1.c
index d8bd4645c1..673e954c53 100644
--- a/thirdparty/libvorbis/floor1.c
+++ b/thirdparty/libvorbis/floor1.c
@@ -11,7 +11,6 @@
********************************************************************
function: floor backend 1 implementation
- last mod: $Id: floor1.c 19457 2015-03-03 00:15:29Z giles $
********************************************************************/
diff --git a/thirdparty/libvorbis/highlevel.h b/thirdparty/libvorbis/highlevel.h
index e38f370fd6..337b75bfa4 100644
--- a/thirdparty/libvorbis/highlevel.h
+++ b/thirdparty/libvorbis/highlevel.h
@@ -11,7 +11,6 @@
********************************************************************
function: highlevel encoder setup struct separated out for vorbisenc clarity
- last mod: $Id: highlevel.h 17195 2010-05-05 21:49:51Z giles $
********************************************************************/
diff --git a/thirdparty/libvorbis/info.c b/thirdparty/libvorbis/info.c
index 8a2a001f99..3fbb7c757a 100644
--- a/thirdparty/libvorbis/info.c
+++ b/thirdparty/libvorbis/info.c
@@ -11,7 +11,6 @@
********************************************************************
function: maintain the info structure, info <-> header packets
- last mod: $Id: info.c 19441 2015-01-21 01:17:41Z xiphmont $
********************************************************************/
@@ -31,8 +30,8 @@
#include "misc.h"
#include "os.h"
-#define GENERAL_VENDOR_STRING "Xiph.Org libVorbis 1.3.5"
-#define ENCODE_VENDOR_STRING "Xiph.Org libVorbis I 20150105 (⛄⛄⛄⛄)"
+#define GENERAL_VENDOR_STRING "Xiph.Org libVorbis 1.3.6"
+#define ENCODE_VENDOR_STRING "Xiph.Org libVorbis I 20180316 (Now 100% fewer shells)"
/* helpers */
static void _v_writestring(oggpack_buffer *o,const char *s, int bytes){
@@ -65,11 +64,13 @@ void vorbis_comment_add(vorbis_comment *vc,const char *comment){
}
void vorbis_comment_add_tag(vorbis_comment *vc, const char *tag, const char *contents){
- char *comment=alloca(strlen(tag)+strlen(contents)+2); /* +2 for = and \0 */
+ /* Length for key and value +2 for = and \0 */
+ char *comment=_ogg_malloc(strlen(tag)+strlen(contents)+2);
strcpy(comment, tag);
strcat(comment, "=");
strcat(comment, contents);
vorbis_comment_add(vc, comment);
+ _ogg_free(comment);
}
/* This is more or less the same as strncasecmp - but that doesn't exist
@@ -88,27 +89,30 @@ char *vorbis_comment_query(vorbis_comment *vc, const char *tag, int count){
long i;
int found = 0;
int taglen = strlen(tag)+1; /* +1 for the = we append */
- char *fulltag = alloca(taglen+ 1);
+ char *fulltag = _ogg_malloc(taglen+1);
strcpy(fulltag, tag);
strcat(fulltag, "=");
for(i=0;i<vc->comments;i++){
if(!tagcompare(vc->user_comments[i], fulltag, taglen)){
- if(count == found)
+ if(count == found) {
/* We return a pointer to the data, not a copy */
- return vc->user_comments[i] + taglen;
- else
+ _ogg_free(fulltag);
+ return vc->user_comments[i] + taglen;
+ } else {
found++;
+ }
}
}
+ _ogg_free(fulltag);
return NULL; /* didn't find anything */
}
int vorbis_comment_query_count(vorbis_comment *vc, const char *tag){
int i,count=0;
int taglen = strlen(tag)+1; /* +1 for the = we append */
- char *fulltag = alloca(taglen+1);
+ char *fulltag = _ogg_malloc(taglen+1);
strcpy(fulltag,tag);
strcat(fulltag, "=");
@@ -117,6 +121,7 @@ int vorbis_comment_query_count(vorbis_comment *vc, const char *tag){
count++;
}
+ _ogg_free(fulltag);
return count;
}
@@ -206,9 +211,9 @@ static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){
vi->channels=oggpack_read(opb,8);
vi->rate=oggpack_read(opb,32);
- vi->bitrate_upper=oggpack_read(opb,32);
- vi->bitrate_nominal=oggpack_read(opb,32);
- vi->bitrate_lower=oggpack_read(opb,32);
+ vi->bitrate_upper=(ogg_int32_t)oggpack_read(opb,32);
+ vi->bitrate_nominal=(ogg_int32_t)oggpack_read(opb,32);
+ vi->bitrate_lower=(ogg_int32_t)oggpack_read(opb,32);
ci->blocksizes[0]=1<<oggpack_read(opb,4);
ci->blocksizes[1]=1<<oggpack_read(opb,4);
@@ -583,7 +588,8 @@ int vorbis_analysis_headerout(vorbis_dsp_state *v,
oggpack_buffer opb;
private_state *b=v->backend_state;
- if(!b||vi->channels<=0){
+ if(!b||vi->channels<=0||vi->channels>256){
+ b = NULL;
ret=OV_EFAULT;
goto err_out;
}
@@ -642,7 +648,7 @@ int vorbis_analysis_headerout(vorbis_dsp_state *v,
memset(op_code,0,sizeof(*op_code));
if(b){
- oggpack_writeclear(&opb);
+ if(vi->channels>0)oggpack_writeclear(&opb);
if(b->header)_ogg_free(b->header);
if(b->header1)_ogg_free(b->header1);
if(b->header2)_ogg_free(b->header2);
diff --git a/thirdparty/libvorbis/lookup.c b/thirdparty/libvorbis/lookup.c
index 3321ed3dbc..1cc1f88ee9 100644
--- a/thirdparty/libvorbis/lookup.c
+++ b/thirdparty/libvorbis/lookup.c
@@ -11,7 +11,6 @@
********************************************************************
function: lookup based functions
- last mod: $Id: lookup.c 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/lookup.h b/thirdparty/libvorbis/lookup.h
index f8b5b82730..4bc0f3a206 100644
--- a/thirdparty/libvorbis/lookup.h
+++ b/thirdparty/libvorbis/lookup.h
@@ -11,7 +11,6 @@
********************************************************************
function: lookup based functions
- last mod: $Id: lookup.h 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/lookup_data.h b/thirdparty/libvorbis/lookup_data.h
index 2424a1b386..5de3cfdc7e 100644
--- a/thirdparty/libvorbis/lookup_data.h
+++ b/thirdparty/libvorbis/lookup_data.h
@@ -11,7 +11,6 @@
********************************************************************
function: lookup data; generated by lookups.pl; edit there
- last mod: $Id: lookup_data.h 16037 2009-05-26 21:10:58Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/lpc.c b/thirdparty/libvorbis/lpc.c
index f5199ec235..798f4cf076 100644
--- a/thirdparty/libvorbis/lpc.c
+++ b/thirdparty/libvorbis/lpc.c
@@ -11,7 +11,6 @@
********************************************************************
function: LPC low level routines
- last mod: $Id: lpc.c 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/lpc.h b/thirdparty/libvorbis/lpc.h
index 39d237601b..9cc79451b6 100644
--- a/thirdparty/libvorbis/lpc.h
+++ b/thirdparty/libvorbis/lpc.h
@@ -11,7 +11,6 @@
********************************************************************
function: LPC low level routines
- last mod: $Id: lpc.h 16037 2009-05-26 21:10:58Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/lsp.c b/thirdparty/libvorbis/lsp.c
index 6a619f7b0c..8588054515 100644
--- a/thirdparty/libvorbis/lsp.c
+++ b/thirdparty/libvorbis/lsp.c
@@ -11,7 +11,6 @@
********************************************************************
function: LSP (also called LSF) conversion routines
- last mod: $Id: lsp.c 19453 2015-03-02 22:35:34Z xiphmont $
The LSP generation code is taken (with minimal modification and a
few bugfixes) from "On the Computation of the LSP Frequencies" by
diff --git a/thirdparty/libvorbis/lsp.h b/thirdparty/libvorbis/lsp.h
index bacfb0971f..8a8d10e978 100644
--- a/thirdparty/libvorbis/lsp.h
+++ b/thirdparty/libvorbis/lsp.h
@@ -11,7 +11,6 @@
********************************************************************
function: LSP (also called LSF) conversion routines
- last mod: $Id: lsp.h 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/mapping0.c b/thirdparty/libvorbis/mapping0.c
index 85c7d22d83..ccb4493d4c 100644
--- a/thirdparty/libvorbis/mapping0.c
+++ b/thirdparty/libvorbis/mapping0.c
@@ -11,7 +11,6 @@
********************************************************************
function: channel mapping 0 implementation
- last mod: $Id: mapping0.c 19441 2015-01-21 01:17:41Z xiphmont $
********************************************************************/
@@ -93,7 +92,6 @@ static vorbis_info_mapping *mapping0_unpack(vorbis_info *vi,oggpack_buffer *opb)
int i,b;
vorbis_info_mapping0 *info=_ogg_calloc(1,sizeof(*info));
codec_setup_info *ci=vi->codec_setup;
- memset(info,0,sizeof(*info));
if(vi->channels<=0)goto err_out;
b=oggpack_read(opb,1);
diff --git a/thirdparty/libvorbis/masking.h b/thirdparty/libvorbis/masking.h
index 3576ab7885..955e18c719 100644
--- a/thirdparty/libvorbis/masking.h
+++ b/thirdparty/libvorbis/masking.h
@@ -11,7 +11,6 @@
********************************************************************
function: masking curve data for psychoacoustics
- last mod: $Id: masking.h 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/mdct.c b/thirdparty/libvorbis/mdct.c
index 0816331805..f3f1ed805b 100644
--- a/thirdparty/libvorbis/mdct.c
+++ b/thirdparty/libvorbis/mdct.c
@@ -12,7 +12,6 @@
function: normalized modified discrete cosine transform
power of two length transform only [64 <= n ]
- last mod: $Id: mdct.c 16227 2009-07-08 06:58:46Z xiphmont $
Original algorithm adapted long ago from _The use of multirate filter
banks for coding of high quality digital audio_, by T. Sporer,
diff --git a/thirdparty/libvorbis/mdct.h b/thirdparty/libvorbis/mdct.h
index 3ed94333c5..3b8c9ba4a2 100644
--- a/thirdparty/libvorbis/mdct.h
+++ b/thirdparty/libvorbis/mdct.h
@@ -11,7 +11,6 @@
********************************************************************
function: modified discrete cosine transform prototypes
- last mod: $Id: mdct.h 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/misc.h b/thirdparty/libvorbis/misc.h
index 73b4519898..13788445a3 100644
--- a/thirdparty/libvorbis/misc.h
+++ b/thirdparty/libvorbis/misc.h
@@ -11,7 +11,6 @@
********************************************************************
function: miscellaneous prototypes
- last mod: $Id: misc.h 19457 2015-03-03 00:15:29Z giles $
********************************************************************/
diff --git a/thirdparty/libvorbis/modes/floor_all.h b/thirdparty/libvorbis/modes/floor_all.h
index 4292be326e..20928aac87 100644
--- a/thirdparty/libvorbis/modes/floor_all.h
+++ b/thirdparty/libvorbis/modes/floor_all.h
@@ -11,7 +11,6 @@
********************************************************************
function: key floor settings
- last mod: $Id: floor_all.h 17050 2010-03-26 01:34:42Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/modes/psych_11.h b/thirdparty/libvorbis/modes/psych_11.h
index 844a8ed3cd..cc5eea2402 100644
--- a/thirdparty/libvorbis/modes/psych_11.h
+++ b/thirdparty/libvorbis/modes/psych_11.h
@@ -11,7 +11,6 @@
********************************************************************
function: 11kHz settings
- last mod: $Id: psych_11.h 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/modes/psych_16.h b/thirdparty/libvorbis/modes/psych_16.h
index 1c10b3954e..477cb4d90f 100644
--- a/thirdparty/libvorbis/modes/psych_16.h
+++ b/thirdparty/libvorbis/modes/psych_16.h
@@ -11,7 +11,6 @@
********************************************************************
function: 16kHz settings
- last mod: $Id: psych_16.h 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/modes/psych_44.h b/thirdparty/libvorbis/modes/psych_44.h
index f05c032653..6c9eaa4e5f 100644
--- a/thirdparty/libvorbis/modes/psych_44.h
+++ b/thirdparty/libvorbis/modes/psych_44.h
@@ -11,7 +11,6 @@
********************************************************************
function: key psychoacoustic settings for 44.1/48kHz
- last mod: $Id: psych_44.h 16962 2010-03-11 07:30:34Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/modes/psych_8.h b/thirdparty/libvorbis/modes/psych_8.h
index 0e2dd57371..277db8436c 100644
--- a/thirdparty/libvorbis/modes/psych_8.h
+++ b/thirdparty/libvorbis/modes/psych_8.h
@@ -11,7 +11,6 @@
********************************************************************
function: 8kHz psychoacoustic settings
- last mod: $Id: psych_8.h 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/modes/residue_16.h b/thirdparty/libvorbis/modes/residue_16.h
index dcaca5451e..3e05471cec 100644
--- a/thirdparty/libvorbis/modes/residue_16.h
+++ b/thirdparty/libvorbis/modes/residue_16.h
@@ -11,7 +11,6 @@
********************************************************************
function: toplevel residue templates 16/22kHz
- last mod: $Id: residue_16.h 16962 2010-03-11 07:30:34Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/modes/residue_44.h b/thirdparty/libvorbis/modes/residue_44.h
index 236c18341b..e89bc0e486 100644
--- a/thirdparty/libvorbis/modes/residue_44.h
+++ b/thirdparty/libvorbis/modes/residue_44.h
@@ -11,7 +11,6 @@
********************************************************************
function: toplevel residue templates for 32/44.1/48kHz
- last mod: $Id: residue_44.h 16962 2010-03-11 07:30:34Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/modes/residue_44p51.h b/thirdparty/libvorbis/modes/residue_44p51.h
index a52cc5245e..7f33e250e2 100644
--- a/thirdparty/libvorbis/modes/residue_44p51.h
+++ b/thirdparty/libvorbis/modes/residue_44p51.h
@@ -11,7 +11,6 @@
********************************************************************
function: toplevel residue templates for 32/44.1/48kHz uncoupled
- last mod: $Id: residue_44p51.h 19013 2013-11-12 04:04:50Z giles $
********************************************************************/
diff --git a/thirdparty/libvorbis/modes/residue_44u.h b/thirdparty/libvorbis/modes/residue_44u.h
index 92c4a09ce3..e55ac12548 100644
--- a/thirdparty/libvorbis/modes/residue_44u.h
+++ b/thirdparty/libvorbis/modes/residue_44u.h
@@ -11,7 +11,6 @@
********************************************************************
function: toplevel residue templates for 32/44.1/48kHz uncoupled
- last mod: $Id: residue_44u.h 16962 2010-03-11 07:30:34Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/modes/residue_8.h b/thirdparty/libvorbis/modes/residue_8.h
index 94c6d84c44..ae123a276a 100644
--- a/thirdparty/libvorbis/modes/residue_8.h
+++ b/thirdparty/libvorbis/modes/residue_8.h
@@ -11,7 +11,6 @@
********************************************************************
function: toplevel residue templates 8/11kHz
- last mod: $Id: residue_8.h 16962 2010-03-11 07:30:34Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/modes/setup_11.h b/thirdparty/libvorbis/modes/setup_11.h
index 4c2d619ca2..0cbcaafcb2 100644
--- a/thirdparty/libvorbis/modes/setup_11.h
+++ b/thirdparty/libvorbis/modes/setup_11.h
@@ -11,7 +11,6 @@
********************************************************************
function: 11kHz settings
- last mod: $Id: setup_11.h 16894 2010-02-12 20:32:12Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/modes/setup_16.h b/thirdparty/libvorbis/modes/setup_16.h
index 336007f98e..d59ad70d2e 100644
--- a/thirdparty/libvorbis/modes/setup_16.h
+++ b/thirdparty/libvorbis/modes/setup_16.h
@@ -11,7 +11,6 @@
********************************************************************
function: 16kHz settings
- last mod: $Id: setup_16.h 16894 2010-02-12 20:32:12Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/modes/setup_22.h b/thirdparty/libvorbis/modes/setup_22.h
index 4fd5e57111..bc38af9630 100644
--- a/thirdparty/libvorbis/modes/setup_22.h
+++ b/thirdparty/libvorbis/modes/setup_22.h
@@ -11,7 +11,6 @@
********************************************************************
function: 22kHz settings
- last mod: $Id: setup_22.h 17026 2010-03-25 05:00:27Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/modes/setup_32.h b/thirdparty/libvorbis/modes/setup_32.h
index 2275ac9615..f66a0bcd00 100644
--- a/thirdparty/libvorbis/modes/setup_32.h
+++ b/thirdparty/libvorbis/modes/setup_32.h
@@ -11,7 +11,6 @@
********************************************************************
function: toplevel settings for 32kHz
- last mod: $Id: setup_32.h 16894 2010-02-12 20:32:12Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/modes/setup_44.h b/thirdparty/libvorbis/modes/setup_44.h
index 3b88a89ac5..a189b5fb95 100644
--- a/thirdparty/libvorbis/modes/setup_44.h
+++ b/thirdparty/libvorbis/modes/setup_44.h
@@ -11,7 +11,6 @@
********************************************************************
function: toplevel settings for 44.1/48kHz
- last mod: $Id: setup_44.h 16962 2010-03-11 07:30:34Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/modes/setup_44p51.h b/thirdparty/libvorbis/modes/setup_44p51.h
index 67d9979608..3bde7b340c 100644
--- a/thirdparty/libvorbis/modes/setup_44p51.h
+++ b/thirdparty/libvorbis/modes/setup_44p51.h
@@ -11,7 +11,6 @@
********************************************************************
function: toplevel settings for 44.1/48kHz 5.1 surround modes
- last mod: $Id: setup_44p51.h 19013 2013-11-12 04:04:50Z giles $
********************************************************************/
diff --git a/thirdparty/libvorbis/modes/setup_44u.h b/thirdparty/libvorbis/modes/setup_44u.h
index 568b5f8959..7ae3af6b2a 100644
--- a/thirdparty/libvorbis/modes/setup_44u.h
+++ b/thirdparty/libvorbis/modes/setup_44u.h
@@ -11,7 +11,6 @@
********************************************************************
function: toplevel settings for 44.1/48kHz uncoupled modes
- last mod: $Id: setup_44u.h 16962 2010-03-11 07:30:34Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/modes/setup_8.h b/thirdparty/libvorbis/modes/setup_8.h
index 14c48374fa..7502556879 100644
--- a/thirdparty/libvorbis/modes/setup_8.h
+++ b/thirdparty/libvorbis/modes/setup_8.h
@@ -11,7 +11,6 @@
********************************************************************
function: 8kHz settings
- last mod: $Id: setup_8.h 16894 2010-02-12 20:32:12Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/modes/setup_X.h b/thirdparty/libvorbis/modes/setup_X.h
index a69f5d40a2..2229a5ef2f 100644
--- a/thirdparty/libvorbis/modes/setup_X.h
+++ b/thirdparty/libvorbis/modes/setup_X.h
@@ -11,7 +11,6 @@
********************************************************************
function: catch-all toplevel settings for q modes only
- last mod: $Id: setup_X.h 16894 2010-02-12 20:32:12Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/os.h b/thirdparty/libvorbis/os.h
index 8bc3e5fe9c..416a401dd1 100644
--- a/thirdparty/libvorbis/os.h
+++ b/thirdparty/libvorbis/os.h
@@ -13,7 +13,6 @@
********************************************************************
function: #ifdef jail to whip a few platforms into the UNIX ideal.
- last mod: $Id: os.h 19457 2015-03-03 00:15:29Z giles $
********************************************************************/
@@ -31,7 +30,7 @@
# ifdef __GNUC__
# define STIN static __inline__
-# elif _WIN32
+# elif defined(_WIN32)
# define STIN static __inline
# else
# define STIN static
diff --git a/thirdparty/libvorbis/psy.c b/thirdparty/libvorbis/psy.c
index f7a44c6d00..422c6f1e41 100644
--- a/thirdparty/libvorbis/psy.c
+++ b/thirdparty/libvorbis/psy.c
@@ -11,7 +11,6 @@
********************************************************************
function: psychoacoustics not including preecho
- last mod: $Id: psy.c 18077 2011-09-02 02:49:00Z giles $
********************************************************************/
diff --git a/thirdparty/libvorbis/psy.h b/thirdparty/libvorbis/psy.h
index c1ea824401..ab2534db3a 100644
--- a/thirdparty/libvorbis/psy.h
+++ b/thirdparty/libvorbis/psy.h
@@ -11,7 +11,6 @@
********************************************************************
function: random psychoacoustics (not including preecho)
- last mod: $Id: psy.h 16946 2010-03-03 16:12:40Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/psytune.c b/thirdparty/libvorbis/psytune.c
index 64c13171f7..6952136c6b 100644
--- a/thirdparty/libvorbis/psytune.c
+++ b/thirdparty/libvorbis/psytune.c
@@ -12,7 +12,6 @@
function: simple utility that runs audio through the psychoacoustics
without encoding
- last mod: $Id: psytune.c 16037 2009-05-26 21:10:58Z xiphmont $
********************************************************************/
@@ -41,11 +40,11 @@
static vorbis_info_psy_global _psy_set0G={
0, /* decaydBpms */
8, /* lines per eighth octave */
-
+
/* thresh sample period, preecho clamp trigger threshhold, range, minenergy */
256, {26.f,26.f,26.f,30.f}, {-90.f,-90.f,-90.f,-90.f}, -90.f,
- -6.f,
-
+ -6.f,
+
0,
0.,
@@ -68,7 +67,7 @@ static vp_couple _vp_couple0[]={
static vorbis_info_psy _psy_set0={
ATH_Bark_dB_lineaggressive,
-
+
-100.f,
-140.f,
6.f, /* floor master att */
@@ -148,7 +147,7 @@ static vorbis_info_psy _psy_set0={
.900f, 0.f, /*11500*/
.900f, 1.f, /*16000*/
},
-
+
95.f, /* even decade + 5 is important; saves an rint() later in a
tight loop) */
-44.,
@@ -159,7 +158,7 @@ static vorbis_info_psy _psy_set0={
static vorbis_info_floor1 _floor_set0={1,
{0},
-
+
{32},
{0},
{0},
@@ -171,12 +170,12 @@ static vorbis_info_floor1 _floor_set0={1,
88,31,243,
14,54,143,460,
-
- 6,3,10, 22,18,26, 41,36,47,
- 69,61,78, 112,99,126, 185,162,211,
+
+ 6,3,10, 22,18,26, 41,36,47,
+ 69,61,78, 112,99,126, 185,162,211,
329,282,387, 672,553,825
},
-
+
60,30,400,
20,8,1,18.,
20,600,
@@ -184,8 +183,8 @@ static vorbis_info_floor1 _floor_set0={1,
static vorbis_info_mapping0 mapping_info={1,{0,1},{0},{0},{0},0, 1, {0},{1}};
-static codec_setup_info codec_setup0={ {0,0},
- 1,1,1,1,1,0,1,
+static codec_setup_info codec_setup0={ {0,0},
+ 1,1,1,1,1,0,1,
{NULL},
{0},{&mapping_info},
{0},{NULL},
@@ -194,7 +193,7 @@ static codec_setup_info codec_setup0={ {0,0},
{NULL},
{&_psy_set0},
&_psy_set0G};
-
+
static int noisy=0;
void analysis(char *base,int i,float *v,int n,int bark,int dB){
if(noisy){
@@ -212,7 +211,7 @@ void analysis(char *base,int i,float *v,int n,int bark,int dB){
fprintf(of,"%g ",toBARK(22050.f*j/n));
else
fprintf(of,"%g ",(float)j);
-
+
if(dB){
fprintf(of,"%g\n",todB(v+j));
}else{
@@ -269,7 +268,7 @@ int main(int argc,char *argv[]){
framesize=atoi(argv[0]);
argv++;
}
-
+
vi.channels=2;
vi.codec_setup=&codec_setup0;
@@ -292,7 +291,7 @@ int main(int argc,char *argv[]){
/* we cheat on the WAV header; we just bypass 44 bytes and never
verify that it matches 16bit/stereo/44.1kHz. */
-
+
fread(buffer,1,44,stdin);
fwrite(buffer,1,44,stdout);
memset(buffer,0,framesize*2);
@@ -302,10 +301,10 @@ int main(int argc,char *argv[]){
fprintf(stderr,"Processing for frame size %d...\n",framesize);
while(!eos){
- long bytes=fread(buffer2,1,framesize*2,stdin);
+ long bytes=fread(buffer2,1,framesize*2,stdin);
if(bytes<framesize*2)
memset(buffer2+bytes,0,framesize*2-bytes);
-
+
if(bytes!=0){
int nonzero[2];
@@ -316,10 +315,10 @@ int main(int argc,char *argv[]){
pcm[1][i]=((buffer[i*4+3]<<8)|
(0x00ff&(int)buffer[i*4+2]))/32768.f;
}
-
+
{
float secs=framesize/44100.;
-
+
ampmax+=secs*ampmax_att_per_sec;
if(ampmax<-9999)ampmax=-9999;
}
@@ -331,11 +330,11 @@ int main(int argc,char *argv[]){
float *logmdct=mdct+framesize/2;
analysis("pre",frameno+i,pcm[i],framesize,0,0);
-
+
/* fft and mdct transforms */
for(j=0;j<framesize;j++)
fft[j]=pcm[i][j]*=window[j];
-
+
drft_forward(&f_look,fft);
local_ampmax[i]=-9999.f;
@@ -347,7 +346,7 @@ int main(int argc,char *argv[]){
if(temp>local_ampmax[i])local_ampmax[i]=temp;
}
if(local_ampmax[i]>ampmax)ampmax=local_ampmax[i];
-
+
mdct_forward(&m_look,pcm[i],mdct);
for(j=0;j<framesize/2;j++)
logmdct[j]=todB(mdct+j);
@@ -391,7 +390,7 @@ int main(int argc,char *argv[]){
logmdct,
mask,
logmax,
-
+
flr[i]);
}
@@ -406,7 +405,7 @@ int main(int argc,char *argv[]){
for(j=0;j<framesize/2;j++)
if(fabs(pcm[i][j])>1500)
fprintf(stderr,"%ld ",frameno+i);
-
+
analysis("res",frameno+i,pcm[i],framesize/2,1,0);
analysis("codedflr",frameno+i,flr[i],framesize/2,1,1);
}
@@ -416,7 +415,7 @@ int main(int argc,char *argv[]){
&vi,
pcm,
nonzero);
-
+
for(i=0;i<2;i++)
analysis("quant",frameno+i,pcm[i],framesize/2,1,0);
@@ -426,7 +425,7 @@ int main(int argc,char *argv[]){
&mapping_info,
pcm,
nonzero);
-
+
for(i=0;i<2;i++)
analysis("coupled",frameno+i,pcm[i],framesize/2,1,0);
@@ -434,11 +433,11 @@ int main(int argc,char *argv[]){
for(i=mapping_info.coupling_steps-1;i>=0;i--){
float *pcmM=pcm[mapping_info.coupling_mag[i]];
float *pcmA=pcm[mapping_info.coupling_ang[i]];
-
+
for(j=0;j<framesize/2;j++){
float mag=pcmM[j];
float ang=pcmA[j];
-
+
if(mag>0)
if(ang>0){
pcmM[j]=mag;
@@ -457,7 +456,7 @@ int main(int argc,char *argv[]){
}
}
}
-
+
for(i=0;i<2;i++)
analysis("decoupled",frameno+i,pcm[i],framesize/2,1,0);
@@ -479,7 +478,7 @@ int main(int argc,char *argv[]){
}
-
+
/* write data. Use the part of buffer we're about to shift out */
for(i=0;i<2;i++){
char *ptr=buffer+i*2;
@@ -503,7 +502,7 @@ int main(int argc,char *argv[]){
ptr+=4;
}
}
-
+
fprintf(stderr,"*");
fwrite(buffer,1,framesize*2,stdout);
memmove(buffer,buffer2,framesize*2);
diff --git a/thirdparty/libvorbis/registry.c b/thirdparty/libvorbis/registry.c
index 3961ed1403..74f7ef0396 100644
--- a/thirdparty/libvorbis/registry.c
+++ b/thirdparty/libvorbis/registry.c
@@ -11,7 +11,6 @@
********************************************************************
function: registry for time, floor, res backends and channel mappings
- last mod: $Id: registry.c 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/registry.h b/thirdparty/libvorbis/registry.h
index 3ae04776d8..599d959942 100644
--- a/thirdparty/libvorbis/registry.h
+++ b/thirdparty/libvorbis/registry.h
@@ -11,7 +11,6 @@
********************************************************************
function: registry for time, floor, res backends and channel mappings
- last mod: $Id: registry.h 15531 2008-11-24 23:50:06Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/res0.c b/thirdparty/libvorbis/res0.c
index ec11488c2f..6d623d730f 100644
--- a/thirdparty/libvorbis/res0.c
+++ b/thirdparty/libvorbis/res0.c
@@ -11,7 +11,6 @@
********************************************************************
function: residue backend 0, 1 and 2 implementation
- last mod: $Id: res0.c 19441 2015-01-21 01:17:41Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/scales.h b/thirdparty/libvorbis/scales.h
index 613f796e77..18bc4e7518 100644
--- a/thirdparty/libvorbis/scales.h
+++ b/thirdparty/libvorbis/scales.h
@@ -11,7 +11,6 @@
********************************************************************
function: linear scale -> dB, Bark and Mel scales
- last mod: $Id: scales.h 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/sharedbook.c b/thirdparty/libvorbis/sharedbook.c
index 6bfdf7311e..4545d4f459 100644
--- a/thirdparty/libvorbis/sharedbook.c
+++ b/thirdparty/libvorbis/sharedbook.c
@@ -11,11 +11,11 @@
********************************************************************
function: basic shared codebook operations
- last mod: $Id: sharedbook.c 19457 2015-03-03 00:15:29Z giles $
********************************************************************/
#include <stdlib.h>
+#include <limits.h>
#include <math.h>
#include <string.h>
#include <ogg/ogg.h>
@@ -158,25 +158,34 @@ ogg_uint32_t *_make_words(char *l,long n,long sparsecount){
that's portable and totally safe against roundoff, but I haven't
thought of it. Therefore, we opt on the side of caution */
long _book_maptype1_quantvals(const static_codebook *b){
- long vals=floor(pow((float)b->entries,1.f/b->dim));
+ long vals;
+ if(b->entries<1){
+ return(0);
+ }
+ vals=floor(pow((float)b->entries,1.f/b->dim));
/* the above *should* be reliable, but we'll not assume that FP is
ever reliable when bitstream sync is at stake; verify via integer
means that vals really is the greatest value of dim for which
vals^b->bim <= b->entries */
/* treat the above as an initial guess */
+ if(vals<1){
+ vals=1;
+ }
while(1){
long acc=1;
long acc1=1;
int i;
for(i=0;i<b->dim;i++){
+ if(b->entries/vals<acc)break;
acc*=vals;
- acc1*=vals+1;
+ if(LONG_MAX/(vals+1)<acc1)acc1=LONG_MAX;
+ else acc1*=vals+1;
}
- if(acc<=b->entries && acc1>b->entries){
+ if(i>=b->dim && acc<=b->entries && acc1>b->entries){
return(vals);
}else{
- if(acc>b->entries){
+ if(i<b->dim || acc>b->entries){
vals--;
}else{
vals++;
diff --git a/thirdparty/libvorbis/smallft.c b/thirdparty/libvorbis/smallft.c
index ae2bc41b6b..6d528af423 100644
--- a/thirdparty/libvorbis/smallft.c
+++ b/thirdparty/libvorbis/smallft.c
@@ -11,7 +11,6 @@
********************************************************************
function: *unnormalized* fft transform
- last mod: $Id: smallft.c 16227 2009-07-08 06:58:46Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/smallft.h b/thirdparty/libvorbis/smallft.h
index 456497326c..9e867c67d2 100644
--- a/thirdparty/libvorbis/smallft.h
+++ b/thirdparty/libvorbis/smallft.h
@@ -11,7 +11,6 @@
********************************************************************
function: fft transform
- last mod: $Id: smallft.h 13293 2007-07-24 00:09:47Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/synthesis.c b/thirdparty/libvorbis/synthesis.c
index 932d271a63..5f6092c3d3 100644
--- a/thirdparty/libvorbis/synthesis.c
+++ b/thirdparty/libvorbis/synthesis.c
@@ -11,7 +11,6 @@
********************************************************************
function: single-block PCM synthesis
- last mod: $Id: synthesis.c 19441 2015-01-21 01:17:41Z xiphmont $
********************************************************************/
@@ -117,7 +116,7 @@ int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op){
if(!ci->mode_param[mode]){
return(OV_EBADPACKET);
}
-
+
vb->W=ci->mode_param[mode]->blockflag;
if(vb->W){
vb->lW=oggpack_read(opb,1);
diff --git a/thirdparty/libvorbis/tone.c b/thirdparty/libvorbis/tone.c
index 73afc67d4c..5b8b020604 100644
--- a/thirdparty/libvorbis/tone.c
+++ b/thirdparty/libvorbis/tone.c
@@ -12,7 +12,7 @@ int main (int argc,char *argv[]){
int i,j;
double *f;
double *amp;
-
+
if(argc<2)usage();
f=alloca(sizeof(*f)*(argc-1));
@@ -21,7 +21,7 @@ int main (int argc,char *argv[]){
i=0;
while(argv[i+1]){
char *pos=strchr(argv[i+1],',');
-
+
f[i]=atof(argv[i+1]);
if(pos)
amp[i]=atof(pos+1)*32767.f;
diff --git a/thirdparty/libvorbis/vorbis/codec.h b/thirdparty/libvorbis/vorbis/codec.h
index 999aa33510..42aa29138e 100644
--- a/thirdparty/libvorbis/vorbis/codec.h
+++ b/thirdparty/libvorbis/vorbis/codec.h
@@ -11,7 +11,6 @@
********************************************************************
function: libvorbis codec headers
- last mod: $Id: codec.h 17021 2010-03-24 09:29:41Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/vorbis/vorbisenc.h b/thirdparty/libvorbis/vorbis/vorbisenc.h
index 02332b50ca..55f3b4a667 100644
--- a/thirdparty/libvorbis/vorbis/vorbisenc.h
+++ b/thirdparty/libvorbis/vorbis/vorbisenc.h
@@ -11,7 +11,6 @@
********************************************************************
function: vorbis encode-engine setup
- last mod: $Id: vorbisenc.h 17021 2010-03-24 09:29:41Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/vorbis/vorbisfile.h b/thirdparty/libvorbis/vorbis/vorbisfile.h
index 9271331e72..56626119bb 100644
--- a/thirdparty/libvorbis/vorbis/vorbisfile.h
+++ b/thirdparty/libvorbis/vorbis/vorbisfile.h
@@ -11,7 +11,6 @@
********************************************************************
function: stdio-based convenience library for opening/seeking/decoding
- last mod: $Id: vorbisfile.h 17182 2010-04-29 03:48:32Z xiphmont $
********************************************************************/
diff --git a/thirdparty/libvorbis/vorbisenc.c b/thirdparty/libvorbis/vorbisenc.c
index b5d621e900..4a4607cb41 100644
--- a/thirdparty/libvorbis/vorbisenc.c
+++ b/thirdparty/libvorbis/vorbisenc.c
@@ -11,7 +11,6 @@
********************************************************************
function: simple programmatic interface for encoder mode setup
- last mod: $Id: vorbisenc.c 19457 2015-03-03 00:15:29Z giles $
********************************************************************/
diff --git a/thirdparty/libvorbis/vorbisfile.c b/thirdparty/libvorbis/vorbisfile.c
index fc0c86ff11..b570c3c5f6 100644
--- a/thirdparty/libvorbis/vorbisfile.c
+++ b/thirdparty/libvorbis/vorbisfile.c
@@ -11,7 +11,6 @@
********************************************************************
function: stdio-based convenience library for opening/seeking/decoding
- last mod: $Id: vorbisfile.c 19457 2015-03-03 00:15:29Z giles $
********************************************************************/
diff --git a/thirdparty/libvorbis/window.c b/thirdparty/libvorbis/window.c
index 0305b79297..b3b7ce0163 100644
--- a/thirdparty/libvorbis/window.c
+++ b/thirdparty/libvorbis/window.c
@@ -11,7 +11,6 @@
********************************************************************
function: window functions
- last mod: $Id: window.c 19028 2013-12-02 23:23:39Z tterribe $
********************************************************************/
diff --git a/thirdparty/libvorbis/window.h b/thirdparty/libvorbis/window.h
index 51f97599f5..6ac260749e 100644
--- a/thirdparty/libvorbis/window.h
+++ b/thirdparty/libvorbis/window.h
@@ -11,7 +11,6 @@
********************************************************************
function: window functions
- last mod: $Id: window.h 19028 2013-12-02 23:23:39Z tterribe $
********************************************************************/
diff --git a/thirdparty/libwebp/AUTHORS b/thirdparty/libwebp/AUTHORS
index 70423cb4dd..83c7b9c5eb 100644
--- a/thirdparty/libwebp/AUTHORS
+++ b/thirdparty/libwebp/AUTHORS
@@ -2,25 +2,38 @@ Contributors:
- Charles Munger (clm at google dot com)
- Christian Duvivier (cduvivier at google dot com)
- Djordje Pesut (djordje dot pesut at imgtec dot com)
+- Hui Su (huisu at google dot com)
- James Zern (jzern at google dot com)
- Jan Engelhardt (jengelh at medozas dot de)
+- Jehan (jehan at girinstud dot io)
- Johann (johann dot koenig at duck dot com)
- Jovan Zelincevic (jovan dot zelincevic at imgtec dot com)
- Jyrki Alakuijala (jyrki at google dot com)
-- levytamar82 (tamar dot levy at intel dot com)
+- Lode Vandevenne (lode at google dot com)
- Lou Quillio (louquillio at google dot com)
- Mans Rullgard (mans at mansr dot com)
+- Marcin Kowalczyk (qrczak at google dot com)
- Martin Olsson (mnemo at minimum dot se)
- Mikołaj Zalewski (mikolajz at google dot com)
+- Mislav Bradac (mislavm at google dot com)
+- Nico Weber (thakis at chromium dot org)
- Noel Chromium (noel at chromium dot org)
+- Owen Rodley (orodley at google dot com)
+- Parag Salasakar (img dot mips1 at gmail dot com)
- Pascal Massimino (pascal dot massimino at gmail dot com)
- Paweł Hajdan, Jr (phajdan dot jr at chromium dot org)
- Pierre Joye (pierre dot php at gmail dot com)
- Sam Clegg (sbc at chromium dot org)
+- Scott Hancher (seh at google dot com)
- Scott LaVarnway (slavarnway at google dot com)
- Scott Talbot (s at chikachow dot org)
- Slobodan Prijic (slobodan dot prijic at imgtec dot com)
- Somnath Banerjee (somnath dot banerjee at gmail dot com)
+- Sriraman Tallam (tmsriram at google dot com)
+- Tamar Levy (tamar dot levy at intel dot com)
- Timothy Gu (timothygu99 at gmail dot com)
- Urvang Joshi (urvang at google dot com)
- Vikas Arora (vikasa at google dot com)
+- Vincent Rabaud (vrabaud at google dot com)
+- Vlad Tsyrklevich (vtsyrklevich at chromium dot org)
+- Yang Zhang (yang dot zhang at arm dot com)
diff --git a/thirdparty/libwebp/src/dec/frame_dec.c b/thirdparty/libwebp/src/dec/frame_dec.c
index 517d0f5850..a9d5430d00 100644
--- a/thirdparty/libwebp/src/dec/frame_dec.c
+++ b/thirdparty/libwebp/src/dec/frame_dec.c
@@ -400,7 +400,9 @@ static void DitherRow(VP8Decoder* const dec) {
#define MACROBLOCK_VPOS(mb_y) ((mb_y) * 16) // vertical position of a MB
// Finalize and transmit a complete row. Return false in case of user-abort.
-static int FinishRow(VP8Decoder* const dec, VP8Io* const io) {
+static int FinishRow(void* arg1, void* arg2) {
+ VP8Decoder* const dec = (VP8Decoder*)arg1;
+ VP8Io* const io = (VP8Io*)arg2;
int ok = 1;
const VP8ThreadContext* const ctx = &dec->thread_ctx_;
const int cache_id = ctx->id_;
@@ -448,10 +450,9 @@ static int FinishRow(VP8Decoder* const dec, VP8Io* const io) {
if (y_end > io->crop_bottom) {
y_end = io->crop_bottom; // make sure we don't overflow on last row.
}
+ // If dec->alpha_data_ is not NULL, we have some alpha plane present.
io->a = NULL;
if (dec->alpha_data_ != NULL && y_start < y_end) {
- // TODO(skal): testing presence of alpha with dec->alpha_data_ is not a
- // good idea.
io->a = VP8DecompressAlphaRows(dec, io, y_start, y_end - y_start);
if (io->a == NULL) {
return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
@@ -558,7 +559,6 @@ VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io) {
if (io->bypass_filtering) {
dec->filter_type_ = 0;
}
- // TODO(skal): filter type / strength / sharpness forcing
// Define the area where we can skip in-loop filtering, in case of cropping.
//
@@ -569,8 +569,6 @@ VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io) {
// Means: there's a dependency chain that goes all the way up to the
// top-left corner of the picture (MB #0). We must filter all the previous
// macroblocks.
- // TODO(skal): add an 'approximate_decoding' option, that won't produce
- // a 1:1 bit-exactness for complex filtering?
{
const int extra_pixels = kFilterExtraRows[dec->filter_type_];
if (dec->filter_type_ == 2) {
@@ -651,7 +649,7 @@ static int InitThreadContext(VP8Decoder* const dec) {
}
worker->data1 = dec;
worker->data2 = (void*)&dec->thread_ctx_.io_;
- worker->hook = (WebPWorkerHook)FinishRow;
+ worker->hook = FinishRow;
dec->num_caches_ =
(dec->filter_type_ > 0) ? MT_CACHE_LINES : MT_CACHE_LINES - 1;
} else {
diff --git a/thirdparty/libwebp/src/dec/vp8_dec.c b/thirdparty/libwebp/src/dec/vp8_dec.c
index 6212efd179..c904b529f6 100644
--- a/thirdparty/libwebp/src/dec/vp8_dec.c
+++ b/thirdparty/libwebp/src/dec/vp8_dec.c
@@ -491,7 +491,7 @@ static int GetCoeffsAlt(VP8BitReader* const br,
return 16;
}
-WEBP_TSAN_IGNORE_FUNCTION static void InitGetCoeffs(void) {
+static WEBP_TSAN_IGNORE_FUNCTION void InitGetCoeffs(void) {
if (GetCoeffs == NULL) {
if (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kSlowSSSE3)) {
GetCoeffs = GetCoeffsAlt;
diff --git a/thirdparty/libwebp/src/dec/vp8i_dec.h b/thirdparty/libwebp/src/dec/vp8i_dec.h
index 28244d9d7a..c929933e1c 100644
--- a/thirdparty/libwebp/src/dec/vp8i_dec.h
+++ b/thirdparty/libwebp/src/dec/vp8i_dec.h
@@ -30,9 +30,9 @@ extern "C" {
// Various defines and enums
// version numbers
-#define DEC_MAJ_VERSION 0
-#define DEC_MIN_VERSION 6
-#define DEC_REV_VERSION 1
+#define DEC_MAJ_VERSION 1
+#define DEC_MIN_VERSION 0
+#define DEC_REV_VERSION 0
// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline).
// Constraints are: We need to store one 16x16 block of luma samples (y),
diff --git a/thirdparty/libwebp/src/dec/vp8l_dec.c b/thirdparty/libwebp/src/dec/vp8l_dec.c
index 42ea3b5e4c..0570f53a77 100644
--- a/thirdparty/libwebp/src/dec/vp8l_dec.c
+++ b/thirdparty/libwebp/src/dec/vp8l_dec.c
@@ -1643,17 +1643,17 @@ int VP8LDecodeImage(VP8LDecoder* const dec) {
#if !defined(WEBP_REDUCE_SIZE)
if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err;
-
- if (io->use_scaling || WebPIsPremultipliedMode(dec->output_->colorspace)) {
- // need the alpha-multiply functions for premultiplied output or rescaling
- WebPInitAlphaProcessing();
- }
#else
if (io->use_scaling) {
dec->status_ = VP8_STATUS_INVALID_PARAM;
goto Err;
}
#endif
+ if (io->use_scaling || WebPIsPremultipliedMode(dec->output_->colorspace)) {
+ // need the alpha-multiply functions for premultiplied output or rescaling
+ WebPInitAlphaProcessing();
+ }
+
if (!WebPIsRGBMode(dec->output_->colorspace)) {
WebPInitConvertARGBToYUV();
if (dec->output_->u.YUVA.a != NULL) WebPInitAlphaProcessing();
diff --git a/thirdparty/libwebp/src/demux/demux.c b/thirdparty/libwebp/src/demux/demux.c
index 79c24a5a7f..684215e3de 100644
--- a/thirdparty/libwebp/src/demux/demux.c
+++ b/thirdparty/libwebp/src/demux/demux.c
@@ -23,9 +23,9 @@
#include "src/webp/demux.h"
#include "src/webp/format_constants.h"
-#define DMUX_MAJ_VERSION 0
-#define DMUX_MIN_VERSION 3
-#define DMUX_REV_VERSION 3
+#define DMUX_MAJ_VERSION 1
+#define DMUX_MIN_VERSION 0
+#define DMUX_REV_VERSION 0
typedef struct {
size_t start_; // start location of the data
diff --git a/thirdparty/libwebp/src/dsp/alpha_processing.c b/thirdparty/libwebp/src/dsp/alpha_processing.c
index 590e3bc312..819d1391f2 100644
--- a/thirdparty/libwebp/src/dsp/alpha_processing.c
+++ b/thirdparty/libwebp/src/dsp/alpha_processing.c
@@ -366,6 +366,16 @@ static WEBP_INLINE uint32_t MakeARGB32(int a, int r, int g, int b) {
return (((uint32_t)a << 24) | (r << 16) | (g << 8) | b);
}
+#ifdef WORDS_BIGENDIAN
+static void PackARGB_C(const uint8_t* a, const uint8_t* r, const uint8_t* g,
+ const uint8_t* b, int len, uint32_t* out) {
+ int i;
+ for (i = 0; i < len; ++i) {
+ out[i] = MakeARGB32(a[4 * i], r[4 * i], g[4 * i], b[4 * i]);
+ }
+}
+#endif
+
static void PackRGB_C(const uint8_t* r, const uint8_t* g, const uint8_t* b,
int len, int step, uint32_t* out) {
int i, offset = 0;
@@ -381,6 +391,10 @@ int (*WebPDispatchAlpha)(const uint8_t*, int, int, int, uint8_t*, int);
void (*WebPDispatchAlphaToGreen)(const uint8_t*, int, int, int, uint32_t*, int);
int (*WebPExtractAlpha)(const uint8_t*, int, int, int, uint8_t*, int);
void (*WebPExtractGreen)(const uint32_t* argb, uint8_t* alpha, int size);
+#ifdef WORDS_BIGENDIAN
+void (*WebPPackARGB)(const uint8_t* a, const uint8_t* r, const uint8_t* g,
+ const uint8_t* b, int, uint32_t*);
+#endif
void (*WebPPackRGB)(const uint8_t* r, const uint8_t* g, const uint8_t* b,
int len, int step, uint32_t* out);
@@ -395,16 +409,14 @@ extern void WebPInitAlphaProcessingSSE2(void);
extern void WebPInitAlphaProcessingSSE41(void);
extern void WebPInitAlphaProcessingNEON(void);
-static volatile VP8CPUInfo alpha_processing_last_cpuinfo_used =
- (VP8CPUInfo)&alpha_processing_last_cpuinfo_used;
-
-WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessing(void) {
- if (alpha_processing_last_cpuinfo_used == VP8GetCPUInfo) return;
-
+WEBP_DSP_INIT_FUNC(WebPInitAlphaProcessing) {
WebPMultARGBRow = WebPMultARGBRow_C;
WebPMultRow = WebPMultRow_C;
WebPApplyAlphaMultiply4444 = ApplyAlphaMultiply_16b_C;
+#ifdef WORDS_BIGENDIAN
+ WebPPackARGB = PackARGB_C;
+#endif
WebPPackRGB = PackRGB_C;
#if !WEBP_NEON_OMIT_C_CODE
WebPApplyAlphaMultiply = ApplyAlphaMultiply_C;
@@ -451,9 +463,10 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessing(void) {
assert(WebPDispatchAlphaToGreen != NULL);
assert(WebPExtractAlpha != NULL);
assert(WebPExtractGreen != NULL);
+#ifdef WORDS_BIGENDIAN
+ assert(WebPPackARGB != NULL);
+#endif
assert(WebPPackRGB != NULL);
assert(WebPHasAlpha8b != NULL);
assert(WebPHasAlpha32b != NULL);
-
- alpha_processing_last_cpuinfo_used = VP8GetCPUInfo;
}
diff --git a/thirdparty/libwebp/src/dsp/alpha_processing_mips_dsp_r2.c b/thirdparty/libwebp/src/dsp/alpha_processing_mips_dsp_r2.c
index e0dc91bab9..0090e87cd1 100644
--- a/thirdparty/libwebp/src/dsp/alpha_processing_mips_dsp_r2.c
+++ b/thirdparty/libwebp/src/dsp/alpha_processing_mips_dsp_r2.c
@@ -125,6 +125,49 @@ static void MultARGBRow_MIPSdspR2(uint32_t* const ptr, int width,
}
}
+#ifdef WORDS_BIGENDIAN
+static void PackARGB_MIPSdspR2(const uint8_t* a, const uint8_t* r,
+ const uint8_t* g, const uint8_t* b, int len,
+ uint32_t* out) {
+ int temp0, temp1, temp2, temp3, offset;
+ const int rest = len & 1;
+ const uint32_t* const loop_end = out + len - rest;
+ const int step = 4;
+ __asm__ volatile (
+ "xor %[offset], %[offset], %[offset] \n\t"
+ "beq %[loop_end], %[out], 0f \n\t"
+ "2: \n\t"
+ "lbux %[temp0], %[offset](%[a]) \n\t"
+ "lbux %[temp1], %[offset](%[r]) \n\t"
+ "lbux %[temp2], %[offset](%[g]) \n\t"
+ "lbux %[temp3], %[offset](%[b]) \n\t"
+ "ins %[temp1], %[temp0], 16, 16 \n\t"
+ "ins %[temp3], %[temp2], 16, 16 \n\t"
+ "addiu %[out], %[out], 4 \n\t"
+ "precr.qb.ph %[temp0], %[temp1], %[temp3] \n\t"
+ "sw %[temp0], -4(%[out]) \n\t"
+ "addu %[offset], %[offset], %[step] \n\t"
+ "bne %[loop_end], %[out], 2b \n\t"
+ "0: \n\t"
+ "beq %[rest], $zero, 1f \n\t"
+ "lbux %[temp0], %[offset](%[a]) \n\t"
+ "lbux %[temp1], %[offset](%[r]) \n\t"
+ "lbux %[temp2], %[offset](%[g]) \n\t"
+ "lbux %[temp3], %[offset](%[b]) \n\t"
+ "ins %[temp1], %[temp0], 16, 16 \n\t"
+ "ins %[temp3], %[temp2], 16, 16 \n\t"
+ "precr.qb.ph %[temp0], %[temp1], %[temp3] \n\t"
+ "sw %[temp0], 0(%[out]) \n\t"
+ "1: \n\t"
+ : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
+ [temp3]"=&r"(temp3), [offset]"=&r"(offset), [out]"+&r"(out)
+ : [a]"r"(a), [r]"r"(r), [g]"r"(g), [b]"r"(b), [step]"r"(step),
+ [loop_end]"r"(loop_end), [rest]"r"(rest)
+ : "memory"
+ );
+}
+#endif // WORDS_BIGENDIAN
+
static void PackRGB_MIPSdspR2(const uint8_t* r, const uint8_t* g,
const uint8_t* b, int len, int step,
uint32_t* out) {
@@ -172,6 +215,9 @@ extern void WebPInitAlphaProcessingMIPSdspR2(void);
WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingMIPSdspR2(void) {
WebPDispatchAlpha = DispatchAlpha_MIPSdspR2;
WebPMultARGBRow = MultARGBRow_MIPSdspR2;
+#ifdef WORDS_BIGENDIAN
+ WebPPackARGB = PackARGB_MIPSdspR2;
+#endif
WebPPackRGB = PackRGB_MIPSdspR2;
}
diff --git a/thirdparty/libwebp/src/dsp/common_sse2.h b/thirdparty/libwebp/src/dsp/common_sse2.h
index 995d7cf4ea..e9f1ebff44 100644
--- a/thirdparty/libwebp/src/dsp/common_sse2.h
+++ b/thirdparty/libwebp/src/dsp/common_sse2.h
@@ -128,9 +128,9 @@ static WEBP_INLINE void VP8Transpose_2_4x4_16b(
// Pack the planar buffers
// rrrr... rrrr... gggg... gggg... bbbb... bbbb....
// triplet by triplet in the output buffer rgb as rgbrgbrgbrgb ...
-static WEBP_INLINE void VP8PlanarTo24b(__m128i* const in0, __m128i* const in1,
- __m128i* const in2, __m128i* const in3,
- __m128i* const in4, __m128i* const in5) {
+static WEBP_INLINE void VP8PlanarTo24b_SSE2(
+ __m128i* const in0, __m128i* const in1, __m128i* const in2,
+ __m128i* const in3, __m128i* const in4, __m128i* const in5) {
// The input is 6 registers of sixteen 8b but for the sake of explanation,
// let's take 6 registers of four 8b values.
// To pack, we will keep taking one every two 8b integer and move it
@@ -159,10 +159,10 @@ static WEBP_INLINE void VP8PlanarTo24b(__m128i* const in0, __m128i* const in1,
// Convert four packed four-channel buffers like argbargbargbargb... into the
// split channels aaaaa ... rrrr ... gggg .... bbbbb ......
-static WEBP_INLINE void VP8L32bToPlanar(__m128i* const in0,
- __m128i* const in1,
- __m128i* const in2,
- __m128i* const in3) {
+static WEBP_INLINE void VP8L32bToPlanar_SSE2(__m128i* const in0,
+ __m128i* const in1,
+ __m128i* const in2,
+ __m128i* const in3) {
// Column-wise transpose.
const __m128i A0 = _mm_unpacklo_epi8(*in0, *in1);
const __m128i A1 = _mm_unpackhi_epi8(*in0, *in1);
diff --git a/thirdparty/libwebp/src/dsp/common_sse41.h b/thirdparty/libwebp/src/dsp/common_sse41.h
new file mode 100644
index 0000000000..2f173c024a
--- /dev/null
+++ b/thirdparty/libwebp/src/dsp/common_sse41.h
@@ -0,0 +1,132 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// SSE4 code common to several files.
+//
+// Author: Vincent Rabaud (vrabaud@google.com)
+
+#ifndef WEBP_DSP_COMMON_SSE41_H_
+#define WEBP_DSP_COMMON_SSE41_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(WEBP_USE_SSE41)
+#include <smmintrin.h>
+
+//------------------------------------------------------------------------------
+// Channel mixing.
+// Shuffles the input buffer as A0 0 0 A1 0 0 A2 ...
+#define WEBP_SSE41_SHUFF(OUT, IN0, IN1) \
+ OUT##0 = _mm_shuffle_epi8(*IN0, shuff0); \
+ OUT##1 = _mm_shuffle_epi8(*IN0, shuff1); \
+ OUT##2 = _mm_shuffle_epi8(*IN0, shuff2); \
+ OUT##3 = _mm_shuffle_epi8(*IN1, shuff0); \
+ OUT##4 = _mm_shuffle_epi8(*IN1, shuff1); \
+ OUT##5 = _mm_shuffle_epi8(*IN1, shuff2);
+
+// Pack the planar buffers
+// rrrr... rrrr... gggg... gggg... bbbb... bbbb....
+// triplet by triplet in the output buffer rgb as rgbrgbrgbrgb ...
+static WEBP_INLINE void VP8PlanarTo24b_SSE41(
+ __m128i* const in0, __m128i* const in1, __m128i* const in2,
+ __m128i* const in3, __m128i* const in4, __m128i* const in5) {
+ __m128i R0, R1, R2, R3, R4, R5;
+ __m128i G0, G1, G2, G3, G4, G5;
+ __m128i B0, B1, B2, B3, B4, B5;
+
+ // Process R.
+ {
+ const __m128i shuff0 = _mm_set_epi8(
+ 5, -1, -1, 4, -1, -1, 3, -1, -1, 2, -1, -1, 1, -1, -1, 0);
+ const __m128i shuff1 = _mm_set_epi8(
+ -1, 10, -1, -1, 9, -1, -1, 8, -1, -1, 7, -1, -1, 6, -1, -1);
+ const __m128i shuff2 = _mm_set_epi8(
+ -1, -1, 15, -1, -1, 14, -1, -1, 13, -1, -1, 12, -1, -1, 11, -1);
+ WEBP_SSE41_SHUFF(R, in0, in1)
+ }
+
+ // Process G.
+ {
+ // Same as before, just shifted to the left by one and including the right
+ // padding.
+ const __m128i shuff0 = _mm_set_epi8(
+ -1, -1, 4, -1, -1, 3, -1, -1, 2, -1, -1, 1, -1, -1, 0, -1);
+ const __m128i shuff1 = _mm_set_epi8(
+ 10, -1, -1, 9, -1, -1, 8, -1, -1, 7, -1, -1, 6, -1, -1, 5);
+ const __m128i shuff2 = _mm_set_epi8(
+ -1, 15, -1, -1, 14, -1, -1, 13, -1, -1, 12, -1, -1, 11, -1, -1);
+ WEBP_SSE41_SHUFF(G, in2, in3)
+ }
+
+ // Process B.
+ {
+ const __m128i shuff0 = _mm_set_epi8(
+ -1, 4, -1, -1, 3, -1, -1, 2, -1, -1, 1, -1, -1, 0, -1, -1);
+ const __m128i shuff1 = _mm_set_epi8(
+ -1, -1, 9, -1, -1, 8, -1, -1, 7, -1, -1, 6, -1, -1, 5, -1);
+ const __m128i shuff2 = _mm_set_epi8(
+ 15, -1, -1, 14, -1, -1, 13, -1, -1, 12, -1, -1, 11, -1, -1, 10);
+ WEBP_SSE41_SHUFF(B, in4, in5)
+ }
+
+ // OR the different channels.
+ {
+ const __m128i RG0 = _mm_or_si128(R0, G0);
+ const __m128i RG1 = _mm_or_si128(R1, G1);
+ const __m128i RG2 = _mm_or_si128(R2, G2);
+ const __m128i RG3 = _mm_or_si128(R3, G3);
+ const __m128i RG4 = _mm_or_si128(R4, G4);
+ const __m128i RG5 = _mm_or_si128(R5, G5);
+ *in0 = _mm_or_si128(RG0, B0);
+ *in1 = _mm_or_si128(RG1, B1);
+ *in2 = _mm_or_si128(RG2, B2);
+ *in3 = _mm_or_si128(RG3, B3);
+ *in4 = _mm_or_si128(RG4, B4);
+ *in5 = _mm_or_si128(RG5, B5);
+ }
+}
+
+#undef WEBP_SSE41_SHUFF
+
+// Convert four packed four-channel buffers like argbargbargbargb... into the
+// split channels aaaaa ... rrrr ... gggg .... bbbbb ......
+static WEBP_INLINE void VP8L32bToPlanar_SSE41(__m128i* const in0,
+ __m128i* const in1,
+ __m128i* const in2,
+ __m128i* const in3) {
+ // aaaarrrrggggbbbb
+ const __m128i shuff0 =
+ _mm_set_epi8(15, 11, 7, 3, 14, 10, 6, 2, 13, 9, 5, 1, 12, 8, 4, 0);
+ const __m128i A0 = _mm_shuffle_epi8(*in0, shuff0);
+ const __m128i A1 = _mm_shuffle_epi8(*in1, shuff0);
+ const __m128i A2 = _mm_shuffle_epi8(*in2, shuff0);
+ const __m128i A3 = _mm_shuffle_epi8(*in3, shuff0);
+ // A0A1R0R1
+ // G0G1B0B1
+ // A2A3R2R3
+ // G0G1B0B1
+ const __m128i B0 = _mm_unpacklo_epi32(A0, A1);
+ const __m128i B1 = _mm_unpackhi_epi32(A0, A1);
+ const __m128i B2 = _mm_unpacklo_epi32(A2, A3);
+ const __m128i B3 = _mm_unpackhi_epi32(A2, A3);
+ *in3 = _mm_unpacklo_epi64(B0, B2);
+ *in2 = _mm_unpackhi_epi64(B0, B2);
+ *in1 = _mm_unpacklo_epi64(B1, B3);
+ *in0 = _mm_unpackhi_epi64(B1, B3);
+}
+
+#endif // WEBP_USE_SSE41
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // WEBP_DSP_COMMON_SSE41_H_
diff --git a/thirdparty/libwebp/src/dsp/cost.c b/thirdparty/libwebp/src/dsp/cost.c
index a732389d58..634ccc2085 100644
--- a/thirdparty/libwebp/src/dsp/cost.c
+++ b/thirdparty/libwebp/src/dsp/cost.c
@@ -378,12 +378,7 @@ extern void VP8EncDspCostInitMIPS32(void);
extern void VP8EncDspCostInitMIPSdspR2(void);
extern void VP8EncDspCostInitSSE2(void);
-static volatile VP8CPUInfo cost_last_cpuinfo_used =
- (VP8CPUInfo)&cost_last_cpuinfo_used;
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInit(void) {
- if (cost_last_cpuinfo_used == VP8GetCPUInfo) return;
-
+WEBP_DSP_INIT_FUNC(VP8EncDspCostInit) {
VP8GetResidualCost = GetResidualCost_C;
VP8SetResidualCoeffs = SetResidualCoeffs_C;
@@ -405,8 +400,6 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInit(void) {
}
#endif
}
-
- cost_last_cpuinfo_used = VP8GetCPUInfo;
}
//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/src/dsp/dec.c b/thirdparty/libwebp/src/dsp/dec.c
index 7e82407567..1119842dd3 100644
--- a/thirdparty/libwebp/src/dsp/dec.c
+++ b/thirdparty/libwebp/src/dsp/dec.c
@@ -741,12 +741,7 @@ extern void VP8DspInitMIPS32(void);
extern void VP8DspInitMIPSdspR2(void);
extern void VP8DspInitMSA(void);
-static volatile VP8CPUInfo dec_last_cpuinfo_used =
- (VP8CPUInfo)&dec_last_cpuinfo_used;
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8DspInit(void) {
- if (dec_last_cpuinfo_used == VP8GetCPUInfo) return;
-
+WEBP_DSP_INIT_FUNC(VP8DspInit) {
VP8InitClipTables();
#if !WEBP_NEON_OMIT_C_CODE
@@ -889,6 +884,4 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8DspInit(void) {
assert(VP8PredChroma8[5] != NULL);
assert(VP8PredChroma8[6] != NULL);
assert(VP8DitherCombine8x8 != NULL);
-
- dec_last_cpuinfo_used = VP8GetCPUInfo;
}
diff --git a/thirdparty/libwebp/src/dsp/dsp.h b/thirdparty/libwebp/src/dsp/dsp.h
index 99eefe092f..4ab77a5130 100644
--- a/thirdparty/libwebp/src/dsp/dsp.h
+++ b/thirdparty/libwebp/src/dsp/dsp.h
@@ -141,6 +141,42 @@ extern "C" {
#endif
#endif
+#if defined(WEBP_USE_THREAD) && !defined(_WIN32)
+#include <pthread.h> // NOLINT
+
+#define WEBP_DSP_INIT(func) do { \
+ static volatile VP8CPUInfo func ## _last_cpuinfo_used = \
+ (VP8CPUInfo)&func ## _last_cpuinfo_used; \
+ static pthread_mutex_t func ## _lock = PTHREAD_MUTEX_INITIALIZER; \
+ if (pthread_mutex_lock(&func ## _lock)) break; \
+ if (func ## _last_cpuinfo_used != VP8GetCPUInfo) func(); \
+ func ## _last_cpuinfo_used = VP8GetCPUInfo; \
+ (void)pthread_mutex_unlock(&func ## _lock); \
+} while (0)
+#else // !(defined(WEBP_USE_THREAD) && !defined(_WIN32))
+#define WEBP_DSP_INIT(func) do { \
+ static volatile VP8CPUInfo func ## _last_cpuinfo_used = \
+ (VP8CPUInfo)&func ## _last_cpuinfo_used; \
+ if (func ## _last_cpuinfo_used == VP8GetCPUInfo) break; \
+ func(); \
+ func ## _last_cpuinfo_used = VP8GetCPUInfo; \
+} while (0)
+#endif // defined(WEBP_USE_THREAD) && !defined(_WIN32)
+
+// Defines an Init + helper function that control multiple initialization of
+// function pointers / tables.
+/* Usage:
+ WEBP_DSP_INIT_FUNC(InitFunc) {
+ ...function body
+ }
+*/
+#define WEBP_DSP_INIT_FUNC(name) \
+ static WEBP_TSAN_IGNORE_FUNCTION void name ## _body(void); \
+ WEBP_TSAN_IGNORE_FUNCTION void name(void) { \
+ WEBP_DSP_INIT(name ## _body); \
+ } \
+ static WEBP_TSAN_IGNORE_FUNCTION void name ## _body(void)
+
#define WEBP_UBSAN_IGNORE_UNDEF
#define WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW
#if defined(__clang__) && defined(__has_attribute)
@@ -166,6 +202,13 @@ extern "C" {
#define WEBP_SWAP_16BIT_CSP 0
#endif
+// some endian fix (e.g.: mips-gcc doesn't define __BIG_ENDIAN__)
+#if !defined(WORDS_BIGENDIAN) && \
+ (defined(__BIG_ENDIAN__) || defined(_M_PPC) || \
+ (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)))
+#define WORDS_BIGENDIAN
+#endif
+
typedef enum {
kSSE2,
kSSE3,
@@ -189,7 +232,7 @@ WEBP_EXTERN VP8CPUInfo VP8GetCPUInfo;
// avoiding a compiler warning.
#define WEBP_DSP_INIT_STUB(func) \
extern void func(void); \
- WEBP_TSAN_IGNORE_FUNCTION void func(void) {}
+ void func(void) {}
//------------------------------------------------------------------------------
// Encoding
@@ -578,6 +621,13 @@ void WebPMultRow_C(uint8_t* const ptr, const uint8_t* const alpha,
int width, int inverse);
void WebPMultARGBRow_C(uint32_t* const ptr, int width, int inverse);
+#ifdef WORDS_BIGENDIAN
+// ARGB packing function: a/r/g/b input is rgba or bgra order.
+extern void (*WebPPackARGB)(const uint8_t* a, const uint8_t* r,
+ const uint8_t* g, const uint8_t* b, int len,
+ uint32_t* out);
+#endif
+
// RGB packing function. 'step' can be 3 or 4. r/g/b input is rgb or bgr order.
extern void (*WebPPackRGB)(const uint8_t* r, const uint8_t* g, const uint8_t* b,
int len, int step, uint32_t* out);
diff --git a/thirdparty/libwebp/src/dsp/enc.c b/thirdparty/libwebp/src/dsp/enc.c
index 1c807f1df7..fa23b40a30 100644
--- a/thirdparty/libwebp/src/dsp/enc.c
+++ b/thirdparty/libwebp/src/dsp/enc.c
@@ -740,12 +740,7 @@ extern void VP8EncDspInitMIPS32(void);
extern void VP8EncDspInitMIPSdspR2(void);
extern void VP8EncDspInitMSA(void);
-static volatile VP8CPUInfo enc_last_cpuinfo_used =
- (VP8CPUInfo)&enc_last_cpuinfo_used;
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInit(void) {
- if (enc_last_cpuinfo_used == VP8GetCPUInfo) return;
-
+WEBP_DSP_INIT_FUNC(VP8EncDspInit) {
VP8DspInit(); // common inverse transforms
InitTables();
@@ -838,6 +833,4 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInit(void) {
assert(VP8EncQuantizeBlockWHT != NULL);
assert(VP8Copy4x4 != NULL);
assert(VP8Copy16x8 != NULL);
-
- enc_last_cpuinfo_used = VP8GetCPUInfo;
}
diff --git a/thirdparty/libwebp/src/dsp/filters.c b/thirdparty/libwebp/src/dsp/filters.c
index ca5f877da7..069a22eaef 100644
--- a/thirdparty/libwebp/src/dsp/filters.c
+++ b/thirdparty/libwebp/src/dsp/filters.c
@@ -238,12 +238,7 @@ extern void VP8FiltersInitMSA(void);
extern void VP8FiltersInitNEON(void);
extern void VP8FiltersInitSSE2(void);
-static volatile VP8CPUInfo filters_last_cpuinfo_used =
- (VP8CPUInfo)&filters_last_cpuinfo_used;
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInit(void) {
- if (filters_last_cpuinfo_used == VP8GetCPUInfo) return;
-
+WEBP_DSP_INIT_FUNC(VP8FiltersInit) {
WebPUnfilters[WEBP_FILTER_NONE] = NULL;
#if !WEBP_NEON_OMIT_C_CODE
WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter_C;
@@ -289,6 +284,4 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInit(void) {
assert(WebPFilters[WEBP_FILTER_HORIZONTAL] != NULL);
assert(WebPFilters[WEBP_FILTER_VERTICAL] != NULL);
assert(WebPFilters[WEBP_FILTER_GRADIENT] != NULL);
-
- filters_last_cpuinfo_used = VP8GetCPUInfo;
}
diff --git a/thirdparty/libwebp/src/dsp/lossless.c b/thirdparty/libwebp/src/dsp/lossless.c
index 83f553d9ad..f9b3c182d3 100644
--- a/thirdparty/libwebp/src/dsp/lossless.c
+++ b/thirdparty/libwebp/src/dsp/lossless.c
@@ -577,9 +577,6 @@ extern void VP8LDspInitNEON(void);
extern void VP8LDspInitMIPSdspR2(void);
extern void VP8LDspInitMSA(void);
-static volatile VP8CPUInfo lossless_last_cpuinfo_used =
- (VP8CPUInfo)&lossless_last_cpuinfo_used;
-
#define COPY_PREDICTOR_ARRAY(IN, OUT) do { \
(OUT)[0] = IN##0_C; \
(OUT)[1] = IN##1_C; \
@@ -599,9 +596,7 @@ static volatile VP8CPUInfo lossless_last_cpuinfo_used =
(OUT)[15] = IN##0_C; \
} while (0);
-WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInit(void) {
- if (lossless_last_cpuinfo_used == VP8GetCPUInfo) return;
-
+WEBP_DSP_INIT_FUNC(VP8LDspInit) {
COPY_PREDICTOR_ARRAY(Predictor, VP8LPredictors)
COPY_PREDICTOR_ARRAY(Predictor, VP8LPredictors_C)
COPY_PREDICTOR_ARRAY(PredictorAdd, VP8LPredictorsAdd)
@@ -658,8 +653,6 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInit(void) {
assert(VP8LConvertBGRAToRGB565 != NULL);
assert(VP8LMapColor32b != NULL);
assert(VP8LMapColor8b != NULL);
-
- lossless_last_cpuinfo_used = VP8GetCPUInfo;
}
#undef COPY_PREDICTOR_ARRAY
diff --git a/thirdparty/libwebp/src/dsp/lossless.h b/thirdparty/libwebp/src/dsp/lossless.h
index a99dbda686..b2bbdfc93c 100644
--- a/thirdparty/libwebp/src/dsp/lossless.h
+++ b/thirdparty/libwebp/src/dsp/lossless.h
@@ -25,10 +25,6 @@
extern "C" {
#endif
-#ifdef WEBP_EXPERIMENTAL_FEATURES
-#include "src/enc/delta_palettization_enc.h"
-#endif // WEBP_EXPERIMENTAL_FEATURES
-
//------------------------------------------------------------------------------
// Decoding
diff --git a/thirdparty/libwebp/src/dsp/lossless_enc.c b/thirdparty/libwebp/src/dsp/lossless_enc.c
index 92ca3c0542..d608326fef 100644
--- a/thirdparty/libwebp/src/dsp/lossless_enc.c
+++ b/thirdparty/libwebp/src/dsp/lossless_enc.c
@@ -863,12 +863,7 @@ extern void VP8LEncDspInitMIPS32(void);
extern void VP8LEncDspInitMIPSdspR2(void);
extern void VP8LEncDspInitMSA(void);
-static volatile VP8CPUInfo lossless_enc_last_cpuinfo_used =
- (VP8CPUInfo)&lossless_enc_last_cpuinfo_used;
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInit(void) {
- if (lossless_enc_last_cpuinfo_used == VP8GetCPUInfo) return;
-
+WEBP_DSP_INIT_FUNC(VP8LEncDspInit) {
VP8LDspInit();
#if !WEBP_NEON_OMIT_C_CODE
@@ -1011,8 +1006,6 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInit(void) {
assert(VP8LPredictorsSub_C[13] != NULL);
assert(VP8LPredictorsSub_C[14] != NULL);
assert(VP8LPredictorsSub_C[15] != NULL);
-
- lossless_enc_last_cpuinfo_used = VP8GetCPUInfo;
}
//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/src/dsp/lossless_enc_sse2.c b/thirdparty/libwebp/src/dsp/lossless_enc_sse2.c
index 1eaf35ca8e..f84a9909e1 100644
--- a/thirdparty/libwebp/src/dsp/lossless_enc_sse2.c
+++ b/thirdparty/libwebp/src/dsp/lossless_enc_sse2.c
@@ -46,16 +46,14 @@ static void SubtractGreenFromBlueAndRed_SSE2(uint32_t* argb_data,
//------------------------------------------------------------------------------
// Color Transform
+#define MK_CST_16(HI, LO) \
+ _mm_set1_epi32((int)(((uint32_t)(HI) << 16) | ((LO) & 0xffff)))
+
static void TransformColor_SSE2(const VP8LMultipliers* const m,
uint32_t* argb_data, int num_pixels) {
- const __m128i mults_rb = _mm_set_epi16(
- CST_5b(m->green_to_red_), CST_5b(m->green_to_blue_),
- CST_5b(m->green_to_red_), CST_5b(m->green_to_blue_),
- CST_5b(m->green_to_red_), CST_5b(m->green_to_blue_),
- CST_5b(m->green_to_red_), CST_5b(m->green_to_blue_));
- const __m128i mults_b2 = _mm_set_epi16(
- CST_5b(m->red_to_blue_), 0, CST_5b(m->red_to_blue_), 0,
- CST_5b(m->red_to_blue_), 0, CST_5b(m->red_to_blue_), 0);
+ const __m128i mults_rb = MK_CST_16(CST_5b(m->green_to_red_),
+ CST_5b(m->green_to_blue_));
+ const __m128i mults_b2 = MK_CST_16(CST_5b(m->red_to_blue_), 0);
const __m128i mask_ag = _mm_set1_epi32(0xff00ff00); // alpha-green masks
const __m128i mask_rb = _mm_set1_epi32(0x00ff00ff); // red-blue masks
int i;
@@ -85,12 +83,8 @@ static void CollectColorBlueTransforms_SSE2(const uint32_t* argb, int stride,
int tile_width, int tile_height,
int green_to_blue, int red_to_blue,
int histo[]) {
- const __m128i mults_r = _mm_set_epi16(
- CST_5b(red_to_blue), 0, CST_5b(red_to_blue), 0,
- CST_5b(red_to_blue), 0, CST_5b(red_to_blue), 0);
- const __m128i mults_g = _mm_set_epi16(
- 0, CST_5b(green_to_blue), 0, CST_5b(green_to_blue),
- 0, CST_5b(green_to_blue), 0, CST_5b(green_to_blue));
+ const __m128i mults_r = MK_CST_16(CST_5b(red_to_blue), 0);
+ const __m128i mults_g = MK_CST_16(0, CST_5b(green_to_blue));
const __m128i mask_g = _mm_set1_epi32(0x00ff00); // green mask
const __m128i mask_b = _mm_set1_epi32(0x0000ff); // blue mask
int y;
@@ -135,9 +129,7 @@ static void CollectColorBlueTransforms_SSE2(const uint32_t* argb, int stride,
static void CollectColorRedTransforms_SSE2(const uint32_t* argb, int stride,
int tile_width, int tile_height,
int green_to_red, int histo[]) {
- const __m128i mults_g = _mm_set_epi16(
- 0, CST_5b(green_to_red), 0, CST_5b(green_to_red),
- 0, CST_5b(green_to_red), 0, CST_5b(green_to_red));
+ const __m128i mults_g = MK_CST_16(0, CST_5b(green_to_red));
const __m128i mask_g = _mm_set1_epi32(0x00ff00); // green mask
const __m128i mask = _mm_set1_epi32(0xff);
@@ -174,6 +166,7 @@ static void CollectColorRedTransforms_SSE2(const uint32_t* argb, int stride,
}
}
#undef SPAN
+#undef MK_CST_16
//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/src/dsp/lossless_enc_sse41.c b/thirdparty/libwebp/src/dsp/lossless_enc_sse41.c
index 3526a342d3..2e12a712eb 100644
--- a/thirdparty/libwebp/src/dsp/lossless_enc_sse41.c
+++ b/thirdparty/libwebp/src/dsp/lossless_enc_sse41.c
@@ -18,6 +18,9 @@
#include <smmintrin.h>
#include "src/dsp/lossless.h"
+// For sign-extended multiplying constants, pre-shifted by 5:
+#define CST_5b(X) (((int16_t)((uint16_t)(X) << 8)) >> 5)
+
//------------------------------------------------------------------------------
// Subtract-Green Transform
@@ -39,12 +42,103 @@ static void SubtractGreenFromBlueAndRed_SSE41(uint32_t* argb_data,
}
//------------------------------------------------------------------------------
+// Color Transform
+
+#define SPAN 8
+static void CollectColorBlueTransforms_SSE41(const uint32_t* argb, int stride,
+ int tile_width, int tile_height,
+ int green_to_blue, int red_to_blue,
+ int histo[]) {
+ const __m128i mults_r = _mm_set1_epi16(CST_5b(red_to_blue));
+ const __m128i mults_g = _mm_set1_epi16(CST_5b(green_to_blue));
+ const __m128i mask_g = _mm_set1_epi16(0xff00); // green mask
+ const __m128i mask_gb = _mm_set1_epi32(0xffff); // green/blue mask
+ const __m128i mask_b = _mm_set1_epi16(0x00ff); // blue mask
+ const __m128i shuffler_lo = _mm_setr_epi8(-1, 2, -1, 6, -1, 10, -1, 14, -1,
+ -1, -1, -1, -1, -1, -1, -1);
+ const __m128i shuffler_hi = _mm_setr_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 2, -1, 6, -1, 10, -1, 14);
+ int y;
+ for (y = 0; y < tile_height; ++y) {
+ const uint32_t* const src = argb + y * stride;
+ int i, x;
+ for (x = 0; x + SPAN <= tile_width; x += SPAN) {
+ uint16_t values[SPAN];
+ const __m128i in0 = _mm_loadu_si128((__m128i*)&src[x + 0]);
+ const __m128i in1 = _mm_loadu_si128((__m128i*)&src[x + SPAN / 2]);
+ const __m128i r0 = _mm_shuffle_epi8(in0, shuffler_lo);
+ const __m128i r1 = _mm_shuffle_epi8(in1, shuffler_hi);
+ const __m128i r = _mm_or_si128(r0, r1); // r 0
+ const __m128i gb0 = _mm_and_si128(in0, mask_gb);
+ const __m128i gb1 = _mm_and_si128(in1, mask_gb);
+ const __m128i gb = _mm_packus_epi32(gb0, gb1); // g b
+ const __m128i g = _mm_and_si128(gb, mask_g); // g 0
+ const __m128i A = _mm_mulhi_epi16(r, mults_r); // x dbr
+ const __m128i B = _mm_mulhi_epi16(g, mults_g); // x dbg
+ const __m128i C = _mm_sub_epi8(gb, B); // x b'
+ const __m128i D = _mm_sub_epi8(C, A); // x b''
+ const __m128i E = _mm_and_si128(D, mask_b); // 0 b''
+ _mm_storeu_si128((__m128i*)values, E);
+ for (i = 0; i < SPAN; ++i) ++histo[values[i]];
+ }
+ }
+ {
+ const int left_over = tile_width & (SPAN - 1);
+ if (left_over > 0) {
+ VP8LCollectColorBlueTransforms_C(argb + tile_width - left_over, stride,
+ left_over, tile_height,
+ green_to_blue, red_to_blue, histo);
+ }
+ }
+}
+
+static void CollectColorRedTransforms_SSE41(const uint32_t* argb, int stride,
+ int tile_width, int tile_height,
+ int green_to_red, int histo[]) {
+ const __m128i mults_g = _mm_set1_epi16(CST_5b(green_to_red));
+ const __m128i mask_g = _mm_set1_epi32(0x00ff00); // green mask
+ const __m128i mask = _mm_set1_epi16(0xff);
+
+ int y;
+ for (y = 0; y < tile_height; ++y) {
+ const uint32_t* const src = argb + y * stride;
+ int i, x;
+ for (x = 0; x + SPAN <= tile_width; x += SPAN) {
+ uint16_t values[SPAN];
+ const __m128i in0 = _mm_loadu_si128((__m128i*)&src[x + 0]);
+ const __m128i in1 = _mm_loadu_si128((__m128i*)&src[x + SPAN / 2]);
+ const __m128i g0 = _mm_and_si128(in0, mask_g); // 0 0 | g 0
+ const __m128i g1 = _mm_and_si128(in1, mask_g);
+ const __m128i g = _mm_packus_epi32(g0, g1); // g 0
+ const __m128i A0 = _mm_srli_epi32(in0, 16); // 0 0 | x r
+ const __m128i A1 = _mm_srli_epi32(in1, 16);
+ const __m128i A = _mm_packus_epi32(A0, A1); // x r
+ const __m128i B = _mm_mulhi_epi16(g, mults_g); // x dr
+ const __m128i C = _mm_sub_epi8(A, B); // x r'
+ const __m128i D = _mm_and_si128(C, mask); // 0 r'
+ _mm_storeu_si128((__m128i*)values, D);
+ for (i = 0; i < SPAN; ++i) ++histo[values[i]];
+ }
+ }
+ {
+ const int left_over = tile_width & (SPAN - 1);
+ if (left_over > 0) {
+ VP8LCollectColorRedTransforms_C(argb + tile_width - left_over, stride,
+ left_over, tile_height, green_to_red,
+ histo);
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
// Entry point
extern void VP8LEncDspInitSSE41(void);
WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitSSE41(void) {
VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed_SSE41;
+ VP8LCollectColorBlueTransforms = CollectColorBlueTransforms_SSE41;
+ VP8LCollectColorRedTransforms = CollectColorRedTransforms_SSE41;
}
#else // !WEBP_USE_SSE41
diff --git a/thirdparty/libwebp/src/dsp/lossless_sse2.c b/thirdparty/libwebp/src/dsp/lossless_sse2.c
index 653b466cd6..17d7576419 100644
--- a/thirdparty/libwebp/src/dsp/lossless_sse2.c
+++ b/thirdparty/libwebp/src/dsp/lossless_sse2.c
@@ -453,14 +453,11 @@ static void TransformColorInverse_SSE2(const VP8LMultipliers* const m,
int num_pixels, uint32_t* dst) {
// sign-extended multiplying constants, pre-shifted by 5.
#define CST(X) (((int16_t)(m->X << 8)) >> 5) // sign-extend
- const __m128i mults_rb = _mm_set_epi16(
- CST(green_to_red_), CST(green_to_blue_),
- CST(green_to_red_), CST(green_to_blue_),
- CST(green_to_red_), CST(green_to_blue_),
- CST(green_to_red_), CST(green_to_blue_));
- const __m128i mults_b2 = _mm_set_epi16(
- CST(red_to_blue_), 0, CST(red_to_blue_), 0,
- CST(red_to_blue_), 0, CST(red_to_blue_), 0);
+#define MK_CST_16(HI, LO) \
+ _mm_set1_epi32((int)(((uint32_t)(HI) << 16) | ((LO) & 0xffff)))
+ const __m128i mults_rb = MK_CST_16(CST(green_to_red_), CST(green_to_blue_));
+ const __m128i mults_b2 = MK_CST_16(CST(red_to_blue_), 0);
+#undef MK_CST_16
#undef CST
const __m128i mask_ag = _mm_set1_epi32(0xff00ff00); // alpha-green masks
int i;
@@ -503,11 +500,11 @@ static void ConvertBGRAToRGB_SSE2(const uint32_t* src, int num_pixels,
__m128i in5 = _mm_loadu_si128(in + 5);
__m128i in6 = _mm_loadu_si128(in + 6);
__m128i in7 = _mm_loadu_si128(in + 7);
- VP8L32bToPlanar(&in0, &in1, &in2, &in3);
- VP8L32bToPlanar(&in4, &in5, &in6, &in7);
+ VP8L32bToPlanar_SSE2(&in0, &in1, &in2, &in3);
+ VP8L32bToPlanar_SSE2(&in4, &in5, &in6, &in7);
// At this points, in1/in5 contains red only, in2/in6 green only ...
// Pack the colors in 24b RGB.
- VP8PlanarTo24b(&in1, &in5, &in2, &in6, &in3, &in7);
+ VP8PlanarTo24b_SSE2(&in1, &in5, &in2, &in6, &in3, &in7);
_mm_storeu_si128(out + 0, in1);
_mm_storeu_si128(out + 1, in5);
_mm_storeu_si128(out + 2, in2);
diff --git a/thirdparty/libwebp/src/dsp/rescaler.c b/thirdparty/libwebp/src/dsp/rescaler.c
index 4b6b7834e5..f307d35056 100644
--- a/thirdparty/libwebp/src/dsp/rescaler.c
+++ b/thirdparty/libwebp/src/dsp/rescaler.c
@@ -204,11 +204,7 @@ extern void WebPRescalerDspInitMIPSdspR2(void);
extern void WebPRescalerDspInitMSA(void);
extern void WebPRescalerDspInitNEON(void);
-static volatile VP8CPUInfo rescaler_last_cpuinfo_used =
- (VP8CPUInfo)&rescaler_last_cpuinfo_used;
-
-WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInit(void) {
- if (rescaler_last_cpuinfo_used == VP8GetCPUInfo) return;
+WEBP_DSP_INIT_FUNC(WebPRescalerDspInit) {
#if !defined(WEBP_REDUCE_SIZE)
#if !WEBP_NEON_OMIT_C_CODE
WebPRescalerExportRowExpand = WebPRescalerExportRowExpand_C;
@@ -253,5 +249,4 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInit(void) {
assert(WebPRescalerImportRowExpand != NULL);
assert(WebPRescalerImportRowShrink != NULL);
#endif // WEBP_REDUCE_SIZE
- rescaler_last_cpuinfo_used = VP8GetCPUInfo;
}
diff --git a/thirdparty/libwebp/src/dsp/rescaler_sse2.c b/thirdparty/libwebp/src/dsp/rescaler_sse2.c
index f93b204fe1..64c50deab5 100644
--- a/thirdparty/libwebp/src/dsp/rescaler_sse2.c
+++ b/thirdparty/libwebp/src/dsp/rescaler_sse2.c
@@ -36,7 +36,7 @@ static void LoadTwoPixels_SSE2(const uint8_t* const src, __m128i* out) {
}
// input: 8 bytes ABCDEFGH -> output: A0B0C0D0E0F0G0H0
-static void LoadHeightPixels_SSE2(const uint8_t* const src, __m128i* out) {
+static void LoadEightPixels_SSE2(const uint8_t* const src, __m128i* out) {
const __m128i zero = _mm_setzero_si128();
const __m128i A = _mm_loadl_epi64((const __m128i*)(src)); // ABCDEFGH
*out = _mm_unpacklo_epi8(A, zero);
@@ -50,13 +50,15 @@ static void RescalerImportRowExpand_SSE2(WebPRescaler* const wrk,
int accum = x_add;
__m128i cur_pixels;
+ // SSE2 implementation only works with 16b signed arithmetic at max.
+ if (wrk->src_width < 8 || accum >= (1 << 15)) {
+ WebPRescalerImportRowExpand_C(wrk, src);
+ return;
+ }
+
assert(!WebPRescalerInputDone(wrk));
assert(wrk->x_expand);
if (wrk->num_channels == 4) {
- if (wrk->src_width < 2) {
- WebPRescalerImportRowExpand_C(wrk, src);
- return;
- }
LoadTwoPixels_SSE2(src, &cur_pixels);
src += 4;
while (1) {
@@ -75,11 +77,7 @@ static void RescalerImportRowExpand_SSE2(WebPRescaler* const wrk,
} else {
int left;
const uint8_t* const src_limit = src + wrk->src_width - 8;
- if (wrk->src_width < 8) {
- WebPRescalerImportRowExpand_C(wrk, src);
- return;
- }
- LoadHeightPixels_SSE2(src, &cur_pixels);
+ LoadEightPixels_SSE2(src, &cur_pixels);
src += 7;
left = 7;
while (1) {
@@ -94,7 +92,7 @@ static void RescalerImportRowExpand_SSE2(WebPRescaler* const wrk,
if (--left) {
cur_pixels = _mm_srli_si128(cur_pixels, 2);
} else if (src <= src_limit) {
- LoadHeightPixels_SSE2(src, &cur_pixels);
+ LoadEightPixels_SSE2(src, &cur_pixels);
src += 7;
left = 7;
} else { // tail
diff --git a/thirdparty/libwebp/src/dsp/ssim.c b/thirdparty/libwebp/src/dsp/ssim.c
index dc1b518a33..989ce8254c 100644
--- a/thirdparty/libwebp/src/dsp/ssim.c
+++ b/thirdparty/libwebp/src/dsp/ssim.c
@@ -139,12 +139,7 @@ VP8AccumulateSSEFunc VP8AccumulateSSE;
extern void VP8SSIMDspInitSSE2(void);
-static volatile VP8CPUInfo ssim_last_cpuinfo_used =
- (VP8CPUInfo)&ssim_last_cpuinfo_used;
-
-WEBP_TSAN_IGNORE_FUNCTION void VP8SSIMDspInit(void) {
- if (ssim_last_cpuinfo_used == VP8GetCPUInfo) return;
-
+WEBP_DSP_INIT_FUNC(VP8SSIMDspInit) {
#if !defined(WEBP_REDUCE_SIZE)
VP8SSIMGetClipped = SSIMGetClipped_C;
VP8SSIMGet = SSIMGet_C;
@@ -161,6 +156,4 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8SSIMDspInit(void) {
}
#endif
}
-
- ssim_last_cpuinfo_used = VP8GetCPUInfo;
}
diff --git a/thirdparty/libwebp/src/dsp/upsampling.c b/thirdparty/libwebp/src/dsp/upsampling.c
index e72626a82a..9b60da5bbb 100644
--- a/thirdparty/libwebp/src/dsp/upsampling.c
+++ b/thirdparty/libwebp/src/dsp/upsampling.c
@@ -217,13 +217,9 @@ WebPYUV444Converter WebPYUV444Converters[MODE_LAST];
extern void WebPInitYUV444ConvertersMIPSdspR2(void);
extern void WebPInitYUV444ConvertersSSE2(void);
+extern void WebPInitYUV444ConvertersSSE41(void);
-static volatile VP8CPUInfo upsampling_last_cpuinfo_used1 =
- (VP8CPUInfo)&upsampling_last_cpuinfo_used1;
-
-WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444Converters(void) {
- if (upsampling_last_cpuinfo_used1 == VP8GetCPUInfo) return;
-
+WEBP_DSP_INIT_FUNC(WebPInitYUV444Converters) {
WebPYUV444Converters[MODE_RGBA] = WebPYuv444ToRgba_C;
WebPYUV444Converters[MODE_BGRA] = WebPYuv444ToBgra_C;
WebPYUV444Converters[MODE_RGB] = WebPYuv444ToRgb_C;
@@ -242,29 +238,29 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444Converters(void) {
WebPInitYUV444ConvertersSSE2();
}
#endif
+#if defined(WEBP_USE_SSE41)
+ if (VP8GetCPUInfo(kSSE4_1)) {
+ WebPInitYUV444ConvertersSSE41();
+ }
+#endif
#if defined(WEBP_USE_MIPS_DSP_R2)
if (VP8GetCPUInfo(kMIPSdspR2)) {
WebPInitYUV444ConvertersMIPSdspR2();
}
#endif
}
- upsampling_last_cpuinfo_used1 = VP8GetCPUInfo;
}
//------------------------------------------------------------------------------
// Main calls
extern void WebPInitUpsamplersSSE2(void);
+extern void WebPInitUpsamplersSSE41(void);
extern void WebPInitUpsamplersNEON(void);
extern void WebPInitUpsamplersMIPSdspR2(void);
extern void WebPInitUpsamplersMSA(void);
-static volatile VP8CPUInfo upsampling_last_cpuinfo_used2 =
- (VP8CPUInfo)&upsampling_last_cpuinfo_used2;
-
-WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplers(void) {
- if (upsampling_last_cpuinfo_used2 == VP8GetCPUInfo) return;
-
+WEBP_DSP_INIT_FUNC(WebPInitUpsamplers) {
#ifdef FANCY_UPSAMPLING
#if !WEBP_NEON_OMIT_C_CODE
WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair_C;
@@ -287,6 +283,11 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplers(void) {
WebPInitUpsamplersSSE2();
}
#endif
+#if defined(WEBP_USE_SSE41)
+ if (VP8GetCPUInfo(kSSE4_1)) {
+ WebPInitUpsamplersSSE41();
+ }
+#endif
#if defined(WEBP_USE_MIPS_DSP_R2)
if (VP8GetCPUInfo(kMIPSdspR2)) {
WebPInitUpsamplersMIPSdspR2();
@@ -310,6 +311,7 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplers(void) {
assert(WebPUpsamplers[MODE_BGRA] != NULL);
assert(WebPUpsamplers[MODE_rgbA] != NULL);
assert(WebPUpsamplers[MODE_bgrA] != NULL);
+#if !defined(WEBP_REDUCE_CSP) || !WEBP_NEON_OMIT_C_CODE
assert(WebPUpsamplers[MODE_RGB] != NULL);
assert(WebPUpsamplers[MODE_BGR] != NULL);
assert(WebPUpsamplers[MODE_ARGB] != NULL);
@@ -317,9 +319,9 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplers(void) {
assert(WebPUpsamplers[MODE_RGB_565] != NULL);
assert(WebPUpsamplers[MODE_Argb] != NULL);
assert(WebPUpsamplers[MODE_rgbA_4444] != NULL);
+#endif
#endif // FANCY_UPSAMPLING
- upsampling_last_cpuinfo_used2 = VP8GetCPUInfo;
}
//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/src/dsp/upsampling_msa.c b/thirdparty/libwebp/src/dsp/upsampling_msa.c
index 535ffb772c..99eea70e7d 100644
--- a/thirdparty/libwebp/src/dsp/upsampling_msa.c
+++ b/thirdparty/libwebp/src/dsp/upsampling_msa.c
@@ -264,6 +264,7 @@ static void YuvToBgr(int y, int u, int v, uint8_t* const bgr) {
bgr[2] = Clip8(r1 >> 6);
}
+#if !defined(WEBP_REDUCE_CSP)
static void YuvToRgb565(int y, int u, int v, uint8_t* const rgb) {
const int y1 = MultHi(y, 19077);
const int r1 = y1 + MultHi(v, 26149) - 14234;
@@ -306,6 +307,7 @@ static void YuvToArgb(uint8_t y, uint8_t u, uint8_t v, uint8_t* const argb) {
argb[0] = 0xff;
YuvToRgb(y, u, v, argb + 1);
}
+#endif // WEBP_REDUCE_CSP
static void YuvToBgra(uint8_t y, uint8_t u, uint8_t v, uint8_t* const bgra) {
YuvToBgr(y, u, v, bgra);
@@ -317,6 +319,7 @@ static void YuvToRgba(uint8_t y, uint8_t u, uint8_t v, uint8_t* const rgba) {
rgba[3] = 0xff;
}
+#if !defined(WEBP_REDUCE_CSP)
static void YuvToRgbLine(const uint8_t* y, const uint8_t* u,
const uint8_t* v, uint8_t* dst, int length) {
v16u8 R, G, B;
@@ -370,6 +373,7 @@ static void YuvToBgrLine(const uint8_t* y, const uint8_t* u,
memcpy(dst, temp, length * 3 * sizeof(*dst));
}
}
+#endif // WEBP_REDUCE_CSP
static void YuvToRgbaLine(const uint8_t* y, const uint8_t* u,
const uint8_t* v, uint8_t* dst, int length) {
@@ -427,6 +431,7 @@ static void YuvToBgraLine(const uint8_t* y, const uint8_t* u,
}
}
+#if !defined(WEBP_REDUCE_CSP)
static void YuvToArgbLine(const uint8_t* y, const uint8_t* u,
const uint8_t* v, uint8_t* dst, int length) {
v16u8 R, G, B;
@@ -526,6 +531,7 @@ static void YuvToRgb565Line(const uint8_t* y, const uint8_t* u,
memcpy(dst, temp, length * 2 * sizeof(*dst));
}
}
+#endif // WEBP_REDUCE_CSP
#define UPSAMPLE_32PIXELS(a, b, c, d) do { \
v16u8 s = __msa_aver_u_b(a, d); \
diff --git a/thirdparty/libwebp/src/dsp/upsampling_sse2.c b/thirdparty/libwebp/src/dsp/upsampling_sse2.c
index fd5d303982..340f1e2ac2 100644
--- a/thirdparty/libwebp/src/dsp/upsampling_sse2.c
+++ b/thirdparty/libwebp/src/dsp/upsampling_sse2.c
@@ -104,21 +104,6 @@ static void Upsample32Pixels_SSE2(const uint8_t r1[], const uint8_t r2[],
Upsample32Pixels_SSE2(r1, r2, out); \
}
-#define CONVERT2RGB(FUNC, XSTEP, top_y, bottom_y, \
- top_dst, bottom_dst, cur_x, num_pixels) { \
- int n; \
- for (n = 0; n < (num_pixels); ++n) { \
- FUNC((top_y)[(cur_x) + n], r_u[n], r_v[n], \
- (top_dst) + ((cur_x) + n) * (XSTEP)); \
- } \
- if ((bottom_y) != NULL) { \
- for (n = 0; n < (num_pixels); ++n) { \
- FUNC((bottom_y)[(cur_x) + n], r_u[64 + n], r_v[64 + n], \
- (bottom_dst) + ((cur_x) + n) * (XSTEP)); \
- } \
- } \
-}
-
#define CONVERT2RGB_32(FUNC, XSTEP, top_y, bottom_y, \
top_dst, bottom_dst, cur_x) do { \
FUNC##32_SSE2((top_y) + (cur_x), r_u, r_v, (top_dst) + (cur_x) * (XSTEP)); \
@@ -135,7 +120,7 @@ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
uint8_t* top_dst, uint8_t* bottom_dst, int len) { \
int uv_pos, pos; \
/* 16byte-aligned array to cache reconstructed u and v */ \
- uint8_t uv_buf[4 * 32 + 15]; \
+ uint8_t uv_buf[14 * 32 + 15] = { 0 }; \
uint8_t* const r_u = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \
uint8_t* const r_v = r_u + 32; \
\
@@ -160,11 +145,22 @@ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
} \
if (len > 1) { \
const int left_over = ((len + 1) >> 1) - (pos >> 1); \
+ uint8_t* const tmp_top_dst = r_u + 4 * 32; \
+ uint8_t* const tmp_bottom_dst = tmp_top_dst + 4 * 32; \
+ uint8_t* const tmp_top = tmp_bottom_dst + 4 * 32; \
+ uint8_t* const tmp_bottom = (bottom_y == NULL) ? NULL : tmp_top + 32; \
assert(left_over > 0); \
UPSAMPLE_LAST_BLOCK(top_u + uv_pos, cur_u + uv_pos, left_over, r_u); \
UPSAMPLE_LAST_BLOCK(top_v + uv_pos, cur_v + uv_pos, left_over, r_v); \
- CONVERT2RGB(FUNC, XSTEP, top_y, bottom_y, top_dst, bottom_dst, \
- pos, len - pos); \
+ memcpy(tmp_top, top_y + pos, len - pos); \
+ if (bottom_y != NULL) memcpy(tmp_bottom, bottom_y + pos, len - pos); \
+ CONVERT2RGB_32(FUNC, XSTEP, tmp_top, tmp_bottom, tmp_top_dst, \
+ tmp_bottom_dst, 0); \
+ memcpy(top_dst + pos * (XSTEP), tmp_top_dst, (len - pos) * (XSTEP)); \
+ if (bottom_y != NULL) { \
+ memcpy(bottom_dst + pos * (XSTEP), tmp_bottom_dst, \
+ (len - pos) * (XSTEP)); \
+ } \
} \
}
diff --git a/thirdparty/libwebp/src/dsp/upsampling_sse41.c b/thirdparty/libwebp/src/dsp/upsampling_sse41.c
new file mode 100644
index 0000000000..648d456027
--- /dev/null
+++ b/thirdparty/libwebp/src/dsp/upsampling_sse41.c
@@ -0,0 +1,239 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// SSE41 version of YUV to RGB upsampling functions.
+//
+// Author: somnath@google.com (Somnath Banerjee)
+
+#include "src/dsp/dsp.h"
+
+#if defined(WEBP_USE_SSE41)
+
+#include <assert.h>
+#include <smmintrin.h>
+#include <string.h>
+#include "src/dsp/yuv.h"
+
+#ifdef FANCY_UPSAMPLING
+
+#if !defined(WEBP_REDUCE_CSP)
+
+// We compute (9*a + 3*b + 3*c + d + 8) / 16 as follows
+// u = (9*a + 3*b + 3*c + d + 8) / 16
+// = (a + (a + 3*b + 3*c + d) / 8 + 1) / 2
+// = (a + m + 1) / 2
+// where m = (a + 3*b + 3*c + d) / 8
+// = ((a + b + c + d) / 2 + b + c) / 4
+//
+// Let's say k = (a + b + c + d) / 4.
+// We can compute k as
+// k = (s + t + 1) / 2 - ((a^d) | (b^c) | (s^t)) & 1
+// where s = (a + d + 1) / 2 and t = (b + c + 1) / 2
+//
+// Then m can be written as
+// m = (k + t + 1) / 2 - (((b^c) & (s^t)) | (k^t)) & 1
+
+// Computes out = (k + in + 1) / 2 - ((ij & (s^t)) | (k^in)) & 1
+#define GET_M(ij, in, out) do { \
+ const __m128i tmp0 = _mm_avg_epu8(k, (in)); /* (k + in + 1) / 2 */ \
+ const __m128i tmp1 = _mm_and_si128((ij), st); /* (ij) & (s^t) */ \
+ const __m128i tmp2 = _mm_xor_si128(k, (in)); /* (k^in) */ \
+ const __m128i tmp3 = _mm_or_si128(tmp1, tmp2); /* ((ij) & (s^t)) | (k^in) */\
+ const __m128i tmp4 = _mm_and_si128(tmp3, one); /* & 1 -> lsb_correction */ \
+ (out) = _mm_sub_epi8(tmp0, tmp4); /* (k + in + 1) / 2 - lsb_correction */ \
+} while (0)
+
+// pack and store two alternating pixel rows
+#define PACK_AND_STORE(a, b, da, db, out) do { \
+ const __m128i t_a = _mm_avg_epu8(a, da); /* (9a + 3b + 3c + d + 8) / 16 */ \
+ const __m128i t_b = _mm_avg_epu8(b, db); /* (3a + 9b + c + 3d + 8) / 16 */ \
+ const __m128i t_1 = _mm_unpacklo_epi8(t_a, t_b); \
+ const __m128i t_2 = _mm_unpackhi_epi8(t_a, t_b); \
+ _mm_store_si128(((__m128i*)(out)) + 0, t_1); \
+ _mm_store_si128(((__m128i*)(out)) + 1, t_2); \
+} while (0)
+
+// Loads 17 pixels each from rows r1 and r2 and generates 32 pixels.
+#define UPSAMPLE_32PIXELS(r1, r2, out) { \
+ const __m128i one = _mm_set1_epi8(1); \
+ const __m128i a = _mm_loadu_si128((const __m128i*)&(r1)[0]); \
+ const __m128i b = _mm_loadu_si128((const __m128i*)&(r1)[1]); \
+ const __m128i c = _mm_loadu_si128((const __m128i*)&(r2)[0]); \
+ const __m128i d = _mm_loadu_si128((const __m128i*)&(r2)[1]); \
+ \
+ const __m128i s = _mm_avg_epu8(a, d); /* s = (a + d + 1) / 2 */ \
+ const __m128i t = _mm_avg_epu8(b, c); /* t = (b + c + 1) / 2 */ \
+ const __m128i st = _mm_xor_si128(s, t); /* st = s^t */ \
+ \
+ const __m128i ad = _mm_xor_si128(a, d); /* ad = a^d */ \
+ const __m128i bc = _mm_xor_si128(b, c); /* bc = b^c */ \
+ \
+ const __m128i t1 = _mm_or_si128(ad, bc); /* (a^d) | (b^c) */ \
+ const __m128i t2 = _mm_or_si128(t1, st); /* (a^d) | (b^c) | (s^t) */ \
+ const __m128i t3 = _mm_and_si128(t2, one); /* (a^d) | (b^c) | (s^t) & 1 */ \
+ const __m128i t4 = _mm_avg_epu8(s, t); \
+ const __m128i k = _mm_sub_epi8(t4, t3); /* k = (a + b + c + d) / 4 */ \
+ __m128i diag1, diag2; \
+ \
+ GET_M(bc, t, diag1); /* diag1 = (a + 3b + 3c + d) / 8 */ \
+ GET_M(ad, s, diag2); /* diag2 = (3a + b + c + 3d) / 8 */ \
+ \
+ /* pack the alternate pixels */ \
+ PACK_AND_STORE(a, b, diag1, diag2, (out) + 0); /* store top */ \
+ PACK_AND_STORE(c, d, diag2, diag1, (out) + 2 * 32); /* store bottom */ \
+}
+
+// Turn the macro into a function for reducing code-size when non-critical
+static void Upsample32Pixels_SSE41(const uint8_t r1[], const uint8_t r2[],
+ uint8_t* const out) {
+ UPSAMPLE_32PIXELS(r1, r2, out);
+}
+
+#define UPSAMPLE_LAST_BLOCK(tb, bb, num_pixels, out) { \
+ uint8_t r1[17], r2[17]; \
+ memcpy(r1, (tb), (num_pixels)); \
+ memcpy(r2, (bb), (num_pixels)); \
+ /* replicate last byte */ \
+ memset(r1 + (num_pixels), r1[(num_pixels) - 1], 17 - (num_pixels)); \
+ memset(r2 + (num_pixels), r2[(num_pixels) - 1], 17 - (num_pixels)); \
+ /* using the shared function instead of the macro saves ~3k code size */ \
+ Upsample32Pixels_SSE41(r1, r2, out); \
+}
+
+#define CONVERT2RGB_32(FUNC, XSTEP, top_y, bottom_y, \
+ top_dst, bottom_dst, cur_x) do { \
+ FUNC##32_SSE41((top_y) + (cur_x), r_u, r_v, (top_dst) + (cur_x) * (XSTEP)); \
+ if ((bottom_y) != NULL) { \
+ FUNC##32_SSE41((bottom_y) + (cur_x), r_u + 64, r_v + 64, \
+ (bottom_dst) + (cur_x) * (XSTEP)); \
+ } \
+} while (0)
+
+#define SSE4_UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \
+static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
+ const uint8_t* top_u, const uint8_t* top_v, \
+ const uint8_t* cur_u, const uint8_t* cur_v, \
+ uint8_t* top_dst, uint8_t* bottom_dst, int len) { \
+ int uv_pos, pos; \
+ /* 16byte-aligned array to cache reconstructed u and v */ \
+ uint8_t uv_buf[14 * 32 + 15] = { 0 }; \
+ uint8_t* const r_u = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \
+ uint8_t* const r_v = r_u + 32; \
+ \
+ assert(top_y != NULL); \
+ { /* Treat the first pixel in regular way */ \
+ const int u_diag = ((top_u[0] + cur_u[0]) >> 1) + 1; \
+ const int v_diag = ((top_v[0] + cur_v[0]) >> 1) + 1; \
+ const int u0_t = (top_u[0] + u_diag) >> 1; \
+ const int v0_t = (top_v[0] + v_diag) >> 1; \
+ FUNC(top_y[0], u0_t, v0_t, top_dst); \
+ if (bottom_y != NULL) { \
+ const int u0_b = (cur_u[0] + u_diag) >> 1; \
+ const int v0_b = (cur_v[0] + v_diag) >> 1; \
+ FUNC(bottom_y[0], u0_b, v0_b, bottom_dst); \
+ } \
+ } \
+ /* For UPSAMPLE_32PIXELS, 17 u/v values must be read-able for each block */ \
+ for (pos = 1, uv_pos = 0; pos + 32 + 1 <= len; pos += 32, uv_pos += 16) { \
+ UPSAMPLE_32PIXELS(top_u + uv_pos, cur_u + uv_pos, r_u); \
+ UPSAMPLE_32PIXELS(top_v + uv_pos, cur_v + uv_pos, r_v); \
+ CONVERT2RGB_32(FUNC, XSTEP, top_y, bottom_y, top_dst, bottom_dst, pos); \
+ } \
+ if (len > 1) { \
+ const int left_over = ((len + 1) >> 1) - (pos >> 1); \
+ uint8_t* const tmp_top_dst = r_u + 4 * 32; \
+ uint8_t* const tmp_bottom_dst = tmp_top_dst + 4 * 32; \
+ uint8_t* const tmp_top = tmp_bottom_dst + 4 * 32; \
+ uint8_t* const tmp_bottom = (bottom_y == NULL) ? NULL : tmp_top + 32; \
+ assert(left_over > 0); \
+ UPSAMPLE_LAST_BLOCK(top_u + uv_pos, cur_u + uv_pos, left_over, r_u); \
+ UPSAMPLE_LAST_BLOCK(top_v + uv_pos, cur_v + uv_pos, left_over, r_v); \
+ memcpy(tmp_top, top_y + pos, len - pos); \
+ if (bottom_y != NULL) memcpy(tmp_bottom, bottom_y + pos, len - pos); \
+ CONVERT2RGB_32(FUNC, XSTEP, tmp_top, tmp_bottom, tmp_top_dst, \
+ tmp_bottom_dst, 0); \
+ memcpy(top_dst + pos * (XSTEP), tmp_top_dst, (len - pos) * (XSTEP)); \
+ if (bottom_y != NULL) { \
+ memcpy(bottom_dst + pos * (XSTEP), tmp_bottom_dst, \
+ (len - pos) * (XSTEP)); \
+ } \
+ } \
+}
+
+// SSE4 variants of the fancy upsampler.
+SSE4_UPSAMPLE_FUNC(UpsampleRgbLinePair_SSE41, VP8YuvToRgb, 3)
+SSE4_UPSAMPLE_FUNC(UpsampleBgrLinePair_SSE41, VP8YuvToBgr, 3)
+
+#undef GET_M
+#undef PACK_AND_STORE
+#undef UPSAMPLE_32PIXELS
+#undef UPSAMPLE_LAST_BLOCK
+#undef CONVERT2RGB
+#undef CONVERT2RGB_32
+#undef SSE4_UPSAMPLE_FUNC
+
+#endif // WEBP_REDUCE_CSP
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */];
+
+extern void WebPInitUpsamplersSSE41(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersSSE41(void) {
+#if !defined(WEBP_REDUCE_CSP)
+ WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair_SSE41;
+ WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair_SSE41;
+#endif // WEBP_REDUCE_CSP
+}
+
+#endif // FANCY_UPSAMPLING
+
+//------------------------------------------------------------------------------
+
+extern WebPYUV444Converter WebPYUV444Converters[/* MODE_LAST */];
+extern void WebPInitYUV444ConvertersSSE41(void);
+
+#define YUV444_FUNC(FUNC_NAME, CALL, CALL_C, XSTEP) \
+extern void CALL_C(const uint8_t* y, const uint8_t* u, const uint8_t* v, \
+ uint8_t* dst, int len); \
+static void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \
+ uint8_t* dst, int len) { \
+ int i; \
+ const int max_len = len & ~31; \
+ for (i = 0; i < max_len; i += 32) { \
+ CALL(y + i, u + i, v + i, dst + i * (XSTEP)); \
+ } \
+ if (i < len) { /* C-fallback */ \
+ CALL_C(y + i, u + i, v + i, dst + i * (XSTEP), len - i); \
+ } \
+}
+
+#if !defined(WEBP_REDUCE_CSP)
+YUV444_FUNC(Yuv444ToRgb_SSE41, VP8YuvToRgb32_SSE41, WebPYuv444ToRgb_C, 3);
+YUV444_FUNC(Yuv444ToBgr_SSE41, VP8YuvToBgr32_SSE41, WebPYuv444ToBgr_C, 3);
+#endif // WEBP_REDUCE_CSP
+
+WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444ConvertersSSE41(void) {
+#if !defined(WEBP_REDUCE_CSP)
+ WebPYUV444Converters[MODE_RGB] = Yuv444ToRgb_SSE41;
+ WebPYUV444Converters[MODE_BGR] = Yuv444ToBgr_SSE41;
+#endif // WEBP_REDUCE_CSP
+}
+
+#else
+
+WEBP_DSP_INIT_STUB(WebPInitYUV444ConvertersSSE41)
+
+#endif // WEBP_USE_SSE41
+
+#if !(defined(FANCY_UPSAMPLING) && defined(WEBP_USE_SSE41))
+WEBP_DSP_INIT_STUB(WebPInitUpsamplersSSE41)
+#endif
diff --git a/thirdparty/libwebp/src/dsp/yuv.c b/thirdparty/libwebp/src/dsp/yuv.c
index bddf81fe09..14e67fc28e 100644
--- a/thirdparty/libwebp/src/dsp/yuv.c
+++ b/thirdparty/libwebp/src/dsp/yuv.c
@@ -71,15 +71,11 @@ void WebPSamplerProcessPlane(const uint8_t* y, int y_stride,
WebPSamplerRowFunc WebPSamplers[MODE_LAST];
extern void WebPInitSamplersSSE2(void);
+extern void WebPInitSamplersSSE41(void);
extern void WebPInitSamplersMIPS32(void);
extern void WebPInitSamplersMIPSdspR2(void);
-static volatile VP8CPUInfo yuv_last_cpuinfo_used =
- (VP8CPUInfo)&yuv_last_cpuinfo_used;
-
-WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplers(void) {
- if (yuv_last_cpuinfo_used == VP8GetCPUInfo) return;
-
+WEBP_DSP_INIT_FUNC(WebPInitSamplers) {
WebPSamplers[MODE_RGB] = YuvToRgbRow;
WebPSamplers[MODE_RGBA] = YuvToRgbaRow;
WebPSamplers[MODE_BGR] = YuvToBgrRow;
@@ -99,6 +95,11 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplers(void) {
WebPInitSamplersSSE2();
}
#endif // WEBP_USE_SSE2
+#if defined(WEBP_USE_SSE41)
+ if (VP8GetCPUInfo(kSSE4_1)) {
+ WebPInitSamplersSSE41();
+ }
+#endif // WEBP_USE_SSE41
#if defined(WEBP_USE_MIPS32)
if (VP8GetCPUInfo(kMIPS32)) {
WebPInitSamplersMIPS32();
@@ -110,7 +111,6 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplers(void) {
}
#endif // WEBP_USE_MIPS_DSP_R2
}
- yuv_last_cpuinfo_used = VP8GetCPUInfo;
}
//-----------------------------------------------------------------------------
@@ -254,17 +254,13 @@ void (*WebPSharpYUVUpdateRGB)(const int16_t* ref, const int16_t* src,
void (*WebPSharpYUVFilterRow)(const int16_t* A, const int16_t* B, int len,
const uint16_t* best_y, uint16_t* out);
-static volatile VP8CPUInfo rgba_to_yuv_last_cpuinfo_used =
- (VP8CPUInfo)&rgba_to_yuv_last_cpuinfo_used;
-
extern void WebPInitConvertARGBToYUVSSE2(void);
+extern void WebPInitConvertARGBToYUVSSE41(void);
extern void WebPInitConvertARGBToYUVNEON(void);
extern void WebPInitSharpYUVSSE2(void);
extern void WebPInitSharpYUVNEON(void);
-WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUV(void) {
- if (rgba_to_yuv_last_cpuinfo_used == VP8GetCPUInfo) return;
-
+WEBP_DSP_INIT_FUNC(WebPInitConvertARGBToYUV) {
WebPConvertARGBToY = ConvertARGBToY_C;
WebPConvertARGBToUV = WebPConvertARGBToUV_C;
@@ -286,6 +282,11 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUV(void) {
WebPInitSharpYUVSSE2();
}
#endif // WEBP_USE_SSE2
+#if defined(WEBP_USE_SSE41)
+ if (VP8GetCPUInfo(kSSE4_1)) {
+ WebPInitConvertARGBToYUVSSE41();
+ }
+#endif // WEBP_USE_SSE41
}
#if defined(WEBP_USE_NEON)
@@ -304,6 +305,4 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUV(void) {
assert(WebPSharpYUVUpdateY != NULL);
assert(WebPSharpYUVUpdateRGB != NULL);
assert(WebPSharpYUVFilterRow != NULL);
-
- rgba_to_yuv_last_cpuinfo_used = VP8GetCPUInfo;
}
diff --git a/thirdparty/libwebp/src/dsp/yuv.h b/thirdparty/libwebp/src/dsp/yuv.h
index c8a55832d4..eb787270d2 100644
--- a/thirdparty/libwebp/src/dsp/yuv.h
+++ b/thirdparty/libwebp/src/dsp/yuv.h
@@ -166,6 +166,19 @@ void VP8YuvToRgb56532_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v,
#endif // WEBP_USE_SSE2
+//-----------------------------------------------------------------------------
+// SSE41 extra functions (mostly for upsampling_sse41.c)
+
+#if defined(WEBP_USE_SSE41)
+
+// Process 32 pixels and store the result (16b, 24b or 32b per pixel) in *dst.
+void VP8YuvToRgb32_SSE41(const uint8_t* y, const uint8_t* u, const uint8_t* v,
+ uint8_t* dst);
+void VP8YuvToBgr32_SSE41(const uint8_t* y, const uint8_t* u, const uint8_t* v,
+ uint8_t* dst);
+
+#endif // WEBP_USE_SSE41
+
//------------------------------------------------------------------------------
// RGB -> YUV conversion
diff --git a/thirdparty/libwebp/src/dsp/yuv_sse2.c b/thirdparty/libwebp/src/dsp/yuv_sse2.c
index 6810bf8d15..baa48d5371 100644
--- a/thirdparty/libwebp/src/dsp/yuv_sse2.c
+++ b/thirdparty/libwebp/src/dsp/yuv_sse2.c
@@ -180,7 +180,7 @@ static WEBP_INLINE void PlanarTo24b_SSE2(__m128i* const in0, __m128i* const in1,
// Repeat the same permutations twice more:
// r0r4g0g4 | b0b4r1r5 | g1g5b1b5 | r2r6g2g6 | b2b6r3r7 | g3g7b3b7
// r0g0b0r1 | g1b1r2g2 | b2r3g3b3 | r4g4b4r5 | g5b5r6g6 | b6r7g7b7
- VP8PlanarTo24b(in0, in1, in2, in3, in4, in5);
+ VP8PlanarTo24b_SSE2(in0, in1, in2, in3, in4, in5);
_mm_storeu_si128((__m128i*)(rgb + 0), *in0);
_mm_storeu_si128((__m128i*)(rgb + 16), *in1);
@@ -492,7 +492,7 @@ static WEBP_INLINE void RGB32PackedToPlanar_SSE2(const uint32_t* const argb,
__m128i a1 = LOAD_16(argb + 4);
__m128i a2 = LOAD_16(argb + 8);
__m128i a3 = LOAD_16(argb + 12);
- VP8L32bToPlanar(&a0, &a1, &a2, &a3);
+ VP8L32bToPlanar_SSE2(&a0, &a1, &a2, &a3);
rgb[0] = _mm_unpacklo_epi8(a1, zero);
rgb[1] = _mm_unpackhi_epi8(a1, zero);
rgb[2] = _mm_unpacklo_epi8(a2, zero);
diff --git a/thirdparty/libwebp/src/dsp/yuv_sse41.c b/thirdparty/libwebp/src/dsp/yuv_sse41.c
new file mode 100644
index 0000000000..579d1f7402
--- /dev/null
+++ b/thirdparty/libwebp/src/dsp/yuv_sse41.c
@@ -0,0 +1,613 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+//
+// YUV->RGB conversion functions
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "src/dsp/yuv.h"
+
+#if defined(WEBP_USE_SSE41)
+
+#include "src/dsp/common_sse41.h"
+#include <stdlib.h>
+#include <smmintrin.h>
+
+//-----------------------------------------------------------------------------
+// Convert spans of 32 pixels to various RGB formats for the fancy upsampler.
+
+// These constants are 14b fixed-point version of ITU-R BT.601 constants.
+// R = (19077 * y + 26149 * v - 14234) >> 6
+// G = (19077 * y - 6419 * u - 13320 * v + 8708) >> 6
+// B = (19077 * y + 33050 * u - 17685) >> 6
+static void ConvertYUV444ToRGB_SSE41(const __m128i* const Y0,
+ const __m128i* const U0,
+ const __m128i* const V0,
+ __m128i* const R,
+ __m128i* const G,
+ __m128i* const B) {
+ const __m128i k19077 = _mm_set1_epi16(19077);
+ const __m128i k26149 = _mm_set1_epi16(26149);
+ const __m128i k14234 = _mm_set1_epi16(14234);
+ // 33050 doesn't fit in a signed short: only use this with unsigned arithmetic
+ const __m128i k33050 = _mm_set1_epi16((short)33050);
+ const __m128i k17685 = _mm_set1_epi16(17685);
+ const __m128i k6419 = _mm_set1_epi16(6419);
+ const __m128i k13320 = _mm_set1_epi16(13320);
+ const __m128i k8708 = _mm_set1_epi16(8708);
+
+ const __m128i Y1 = _mm_mulhi_epu16(*Y0, k19077);
+
+ const __m128i R0 = _mm_mulhi_epu16(*V0, k26149);
+ const __m128i R1 = _mm_sub_epi16(Y1, k14234);
+ const __m128i R2 = _mm_add_epi16(R1, R0);
+
+ const __m128i G0 = _mm_mulhi_epu16(*U0, k6419);
+ const __m128i G1 = _mm_mulhi_epu16(*V0, k13320);
+ const __m128i G2 = _mm_add_epi16(Y1, k8708);
+ const __m128i G3 = _mm_add_epi16(G0, G1);
+ const __m128i G4 = _mm_sub_epi16(G2, G3);
+
+ // be careful with the saturated *unsigned* arithmetic here!
+ const __m128i B0 = _mm_mulhi_epu16(*U0, k33050);
+ const __m128i B1 = _mm_adds_epu16(B0, Y1);
+ const __m128i B2 = _mm_subs_epu16(B1, k17685);
+
+ // use logical shift for B2, which can be larger than 32767
+ *R = _mm_srai_epi16(R2, 6); // range: [-14234, 30815]
+ *G = _mm_srai_epi16(G4, 6); // range: [-10953, 27710]
+ *B = _mm_srli_epi16(B2, 6); // range: [0, 34238]
+}
+
+// Load the bytes into the *upper* part of 16b words. That's "<< 8", basically.
+static WEBP_INLINE __m128i Load_HI_16_SSE41(const uint8_t* src) {
+ const __m128i zero = _mm_setzero_si128();
+ return _mm_unpacklo_epi8(zero, _mm_loadl_epi64((const __m128i*)src));
+}
+
+// Load and replicate the U/V samples
+static WEBP_INLINE __m128i Load_UV_HI_8_SSE41(const uint8_t* src) {
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i tmp0 = _mm_cvtsi32_si128(*(const uint32_t*)src);
+ const __m128i tmp1 = _mm_unpacklo_epi8(zero, tmp0);
+ return _mm_unpacklo_epi16(tmp1, tmp1); // replicate samples
+}
+
+// Convert 32 samples of YUV444 to R/G/B
+static void YUV444ToRGB_SSE41(const uint8_t* const y,
+ const uint8_t* const u,
+ const uint8_t* const v,
+ __m128i* const R, __m128i* const G,
+ __m128i* const B) {
+ const __m128i Y0 = Load_HI_16_SSE41(y), U0 = Load_HI_16_SSE41(u),
+ V0 = Load_HI_16_SSE41(v);
+ ConvertYUV444ToRGB_SSE41(&Y0, &U0, &V0, R, G, B);
+}
+
+// Convert 32 samples of YUV420 to R/G/B
+static void YUV420ToRGB_SSE41(const uint8_t* const y,
+ const uint8_t* const u,
+ const uint8_t* const v,
+ __m128i* const R, __m128i* const G,
+ __m128i* const B) {
+ const __m128i Y0 = Load_HI_16_SSE41(y), U0 = Load_UV_HI_8_SSE41(u),
+ V0 = Load_UV_HI_8_SSE41(v);
+ ConvertYUV444ToRGB_SSE41(&Y0, &U0, &V0, R, G, B);
+}
+
+// Pack the planar buffers
+// rrrr... rrrr... gggg... gggg... bbbb... bbbb....
+// triplet by triplet in the output buffer rgb as rgbrgbrgbrgb ...
+static WEBP_INLINE void PlanarTo24b_SSE41(
+ __m128i* const in0, __m128i* const in1, __m128i* const in2,
+ __m128i* const in3, __m128i* const in4, __m128i* const in5,
+ uint8_t* const rgb) {
+ // The input is 6 registers of sixteen 8b but for the sake of explanation,
+ // let's take 6 registers of four 8b values.
+ // To pack, we will keep taking one every two 8b integer and move it
+ // around as follows:
+ // Input:
+ // r0r1r2r3 | r4r5r6r7 | g0g1g2g3 | g4g5g6g7 | b0b1b2b3 | b4b5b6b7
+ // Split the 6 registers in two sets of 3 registers: the first set as the even
+ // 8b bytes, the second the odd ones:
+ // r0r2r4r6 | g0g2g4g6 | b0b2b4b6 | r1r3r5r7 | g1g3g5g7 | b1b3b5b7
+ // Repeat the same permutations twice more:
+ // r0r4g0g4 | b0b4r1r5 | g1g5b1b5 | r2r6g2g6 | b2b6r3r7 | g3g7b3b7
+ // r0g0b0r1 | g1b1r2g2 | b2r3g3b3 | r4g4b4r5 | g5b5r6g6 | b6r7g7b7
+ VP8PlanarTo24b_SSE41(in0, in1, in2, in3, in4, in5);
+
+ _mm_storeu_si128((__m128i*)(rgb + 0), *in0);
+ _mm_storeu_si128((__m128i*)(rgb + 16), *in1);
+ _mm_storeu_si128((__m128i*)(rgb + 32), *in2);
+ _mm_storeu_si128((__m128i*)(rgb + 48), *in3);
+ _mm_storeu_si128((__m128i*)(rgb + 64), *in4);
+ _mm_storeu_si128((__m128i*)(rgb + 80), *in5);
+}
+
+void VP8YuvToRgb32_SSE41(const uint8_t* y, const uint8_t* u, const uint8_t* v,
+ uint8_t* dst) {
+ __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3;
+ __m128i rgb0, rgb1, rgb2, rgb3, rgb4, rgb5;
+
+ YUV444ToRGB_SSE41(y + 0, u + 0, v + 0, &R0, &G0, &B0);
+ YUV444ToRGB_SSE41(y + 8, u + 8, v + 8, &R1, &G1, &B1);
+ YUV444ToRGB_SSE41(y + 16, u + 16, v + 16, &R2, &G2, &B2);
+ YUV444ToRGB_SSE41(y + 24, u + 24, v + 24, &R3, &G3, &B3);
+
+ // Cast to 8b and store as RRRRGGGGBBBB.
+ rgb0 = _mm_packus_epi16(R0, R1);
+ rgb1 = _mm_packus_epi16(R2, R3);
+ rgb2 = _mm_packus_epi16(G0, G1);
+ rgb3 = _mm_packus_epi16(G2, G3);
+ rgb4 = _mm_packus_epi16(B0, B1);
+ rgb5 = _mm_packus_epi16(B2, B3);
+
+ // Pack as RGBRGBRGBRGB.
+ PlanarTo24b_SSE41(&rgb0, &rgb1, &rgb2, &rgb3, &rgb4, &rgb5, dst);
+}
+
+void VP8YuvToBgr32_SSE41(const uint8_t* y, const uint8_t* u, const uint8_t* v,
+ uint8_t* dst) {
+ __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3;
+ __m128i bgr0, bgr1, bgr2, bgr3, bgr4, bgr5;
+
+ YUV444ToRGB_SSE41(y + 0, u + 0, v + 0, &R0, &G0, &B0);
+ YUV444ToRGB_SSE41(y + 8, u + 8, v + 8, &R1, &G1, &B1);
+ YUV444ToRGB_SSE41(y + 16, u + 16, v + 16, &R2, &G2, &B2);
+ YUV444ToRGB_SSE41(y + 24, u + 24, v + 24, &R3, &G3, &B3);
+
+ // Cast to 8b and store as BBBBGGGGRRRR.
+ bgr0 = _mm_packus_epi16(B0, B1);
+ bgr1 = _mm_packus_epi16(B2, B3);
+ bgr2 = _mm_packus_epi16(G0, G1);
+ bgr3 = _mm_packus_epi16(G2, G3);
+ bgr4 = _mm_packus_epi16(R0, R1);
+ bgr5= _mm_packus_epi16(R2, R3);
+
+ // Pack as BGRBGRBGRBGR.
+ PlanarTo24b_SSE41(&bgr0, &bgr1, &bgr2, &bgr3, &bgr4, &bgr5, dst);
+}
+
+//-----------------------------------------------------------------------------
+// Arbitrary-length row conversion functions
+
+static void YuvToRgbRow_SSE41(const uint8_t* y,
+ const uint8_t* u, const uint8_t* v,
+ uint8_t* dst, int len) {
+ int n;
+ for (n = 0; n + 32 <= len; n += 32, dst += 32 * 3) {
+ __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3;
+ __m128i rgb0, rgb1, rgb2, rgb3, rgb4, rgb5;
+
+ YUV420ToRGB_SSE41(y + 0, u + 0, v + 0, &R0, &G0, &B0);
+ YUV420ToRGB_SSE41(y + 8, u + 4, v + 4, &R1, &G1, &B1);
+ YUV420ToRGB_SSE41(y + 16, u + 8, v + 8, &R2, &G2, &B2);
+ YUV420ToRGB_SSE41(y + 24, u + 12, v + 12, &R3, &G3, &B3);
+
+ // Cast to 8b and store as RRRRGGGGBBBB.
+ rgb0 = _mm_packus_epi16(R0, R1);
+ rgb1 = _mm_packus_epi16(R2, R3);
+ rgb2 = _mm_packus_epi16(G0, G1);
+ rgb3 = _mm_packus_epi16(G2, G3);
+ rgb4 = _mm_packus_epi16(B0, B1);
+ rgb5 = _mm_packus_epi16(B2, B3);
+
+ // Pack as RGBRGBRGBRGB.
+ PlanarTo24b_SSE41(&rgb0, &rgb1, &rgb2, &rgb3, &rgb4, &rgb5, dst);
+
+ y += 32;
+ u += 16;
+ v += 16;
+ }
+ for (; n < len; ++n) { // Finish off
+ VP8YuvToRgb(y[0], u[0], v[0], dst);
+ dst += 3;
+ y += 1;
+ u += (n & 1);
+ v += (n & 1);
+ }
+}
+
+static void YuvToBgrRow_SSE41(const uint8_t* y,
+ const uint8_t* u, const uint8_t* v,
+ uint8_t* dst, int len) {
+ int n;
+ for (n = 0; n + 32 <= len; n += 32, dst += 32 * 3) {
+ __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3;
+ __m128i bgr0, bgr1, bgr2, bgr3, bgr4, bgr5;
+
+ YUV420ToRGB_SSE41(y + 0, u + 0, v + 0, &R0, &G0, &B0);
+ YUV420ToRGB_SSE41(y + 8, u + 4, v + 4, &R1, &G1, &B1);
+ YUV420ToRGB_SSE41(y + 16, u + 8, v + 8, &R2, &G2, &B2);
+ YUV420ToRGB_SSE41(y + 24, u + 12, v + 12, &R3, &G3, &B3);
+
+ // Cast to 8b and store as BBBBGGGGRRRR.
+ bgr0 = _mm_packus_epi16(B0, B1);
+ bgr1 = _mm_packus_epi16(B2, B3);
+ bgr2 = _mm_packus_epi16(G0, G1);
+ bgr3 = _mm_packus_epi16(G2, G3);
+ bgr4 = _mm_packus_epi16(R0, R1);
+ bgr5 = _mm_packus_epi16(R2, R3);
+
+ // Pack as BGRBGRBGRBGR.
+ PlanarTo24b_SSE41(&bgr0, &bgr1, &bgr2, &bgr3, &bgr4, &bgr5, dst);
+
+ y += 32;
+ u += 16;
+ v += 16;
+ }
+ for (; n < len; ++n) { // Finish off
+ VP8YuvToBgr(y[0], u[0], v[0], dst);
+ dst += 3;
+ y += 1;
+ u += (n & 1);
+ v += (n & 1);
+ }
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void WebPInitSamplersSSE41(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplersSSE41(void) {
+ WebPSamplers[MODE_RGB] = YuvToRgbRow_SSE41;
+ WebPSamplers[MODE_BGR] = YuvToBgrRow_SSE41;
+}
+
+//------------------------------------------------------------------------------
+// RGB24/32 -> YUV converters
+
+// Load eight 16b-words from *src.
+#define LOAD_16(src) _mm_loadu_si128((const __m128i*)(src))
+// Store either 16b-words into *dst
+#define STORE_16(V, dst) _mm_storeu_si128((__m128i*)(dst), (V))
+
+#define WEBP_SSE41_SHUFF(OUT) do { \
+ const __m128i tmp0 = _mm_shuffle_epi8(A0, shuff0); \
+ const __m128i tmp1 = _mm_shuffle_epi8(A1, shuff1); \
+ const __m128i tmp2 = _mm_shuffle_epi8(A2, shuff2); \
+ const __m128i tmp3 = _mm_shuffle_epi8(A3, shuff0); \
+ const __m128i tmp4 = _mm_shuffle_epi8(A4, shuff1); \
+ const __m128i tmp5 = _mm_shuffle_epi8(A5, shuff2); \
+ \
+ /* OR everything to get one channel */ \
+ const __m128i tmp6 = _mm_or_si128(tmp0, tmp1); \
+ const __m128i tmp7 = _mm_or_si128(tmp3, tmp4); \
+ out[OUT + 0] = _mm_or_si128(tmp6, tmp2); \
+ out[OUT + 1] = _mm_or_si128(tmp7, tmp5); \
+} while (0);
+
+// Unpack the 8b input rgbrgbrgbrgb ... as contiguous registers:
+// rrrr... rrrr... gggg... gggg... bbbb... bbbb....
+// Similar to PlanarTo24bHelper(), but in reverse order.
+static WEBP_INLINE void RGB24PackedToPlanar_SSE41(
+ const uint8_t* const rgb, __m128i* const out /*out[6]*/) {
+ const __m128i A0 = _mm_loadu_si128((const __m128i*)(rgb + 0));
+ const __m128i A1 = _mm_loadu_si128((const __m128i*)(rgb + 16));
+ const __m128i A2 = _mm_loadu_si128((const __m128i*)(rgb + 32));
+ const __m128i A3 = _mm_loadu_si128((const __m128i*)(rgb + 48));
+ const __m128i A4 = _mm_loadu_si128((const __m128i*)(rgb + 64));
+ const __m128i A5 = _mm_loadu_si128((const __m128i*)(rgb + 80));
+
+ // Compute RR.
+ {
+ const __m128i shuff0 = _mm_set_epi8(
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, 12, 9, 6, 3, 0);
+ const __m128i shuff1 = _mm_set_epi8(
+ -1, -1, -1, -1, -1, 14, 11, 8, 5, 2, -1, -1, -1, -1, -1, -1);
+ const __m128i shuff2 = _mm_set_epi8(
+ 13, 10, 7, 4, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
+ WEBP_SSE41_SHUFF(0)
+ }
+ // Compute GG.
+ {
+ const __m128i shuff0 = _mm_set_epi8(
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, 10, 7, 4, 1);
+ const __m128i shuff1 = _mm_set_epi8(
+ -1, -1, -1, -1, -1, 15, 12, 9, 6, 3, 0, -1, -1, -1, -1, -1);
+ const __m128i shuff2 = _mm_set_epi8(
+ 14, 11, 8, 5, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
+ WEBP_SSE41_SHUFF(2)
+ }
+ // Compute BB.
+ {
+ const __m128i shuff0 = _mm_set_epi8(
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, 11, 8, 5, 2);
+ const __m128i shuff1 = _mm_set_epi8(
+ -1, -1, -1, -1, -1, -1, 13, 10, 7, 4, 1, -1, -1, -1, -1, -1);
+ const __m128i shuff2 = _mm_set_epi8(
+ 15, 12, 9, 6, 3, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
+ WEBP_SSE41_SHUFF(4)
+ }
+}
+
+#undef WEBP_SSE41_SHUFF
+
+// Convert 8 packed ARGB to r[], g[], b[]
+static WEBP_INLINE void RGB32PackedToPlanar_SSE41(
+ const uint32_t* const argb, __m128i* const rgb /*in[6]*/) {
+ const __m128i zero = _mm_setzero_si128();
+ __m128i a0 = LOAD_16(argb + 0);
+ __m128i a1 = LOAD_16(argb + 4);
+ __m128i a2 = LOAD_16(argb + 8);
+ __m128i a3 = LOAD_16(argb + 12);
+ VP8L32bToPlanar_SSE41(&a0, &a1, &a2, &a3);
+ rgb[0] = _mm_unpacklo_epi8(a1, zero);
+ rgb[1] = _mm_unpackhi_epi8(a1, zero);
+ rgb[2] = _mm_unpacklo_epi8(a2, zero);
+ rgb[3] = _mm_unpackhi_epi8(a2, zero);
+ rgb[4] = _mm_unpacklo_epi8(a3, zero);
+ rgb[5] = _mm_unpackhi_epi8(a3, zero);
+}
+
+// This macro computes (RG * MULT_RG + GB * MULT_GB + ROUNDER) >> DESCALE_FIX
+// It's a macro and not a function because we need to use immediate values with
+// srai_epi32, e.g.
+#define TRANSFORM(RG_LO, RG_HI, GB_LO, GB_HI, MULT_RG, MULT_GB, \
+ ROUNDER, DESCALE_FIX, OUT) do { \
+ const __m128i V0_lo = _mm_madd_epi16(RG_LO, MULT_RG); \
+ const __m128i V0_hi = _mm_madd_epi16(RG_HI, MULT_RG); \
+ const __m128i V1_lo = _mm_madd_epi16(GB_LO, MULT_GB); \
+ const __m128i V1_hi = _mm_madd_epi16(GB_HI, MULT_GB); \
+ const __m128i V2_lo = _mm_add_epi32(V0_lo, V1_lo); \
+ const __m128i V2_hi = _mm_add_epi32(V0_hi, V1_hi); \
+ const __m128i V3_lo = _mm_add_epi32(V2_lo, ROUNDER); \
+ const __m128i V3_hi = _mm_add_epi32(V2_hi, ROUNDER); \
+ const __m128i V5_lo = _mm_srai_epi32(V3_lo, DESCALE_FIX); \
+ const __m128i V5_hi = _mm_srai_epi32(V3_hi, DESCALE_FIX); \
+ (OUT) = _mm_packs_epi32(V5_lo, V5_hi); \
+} while (0)
+
+#define MK_CST_16(A, B) _mm_set_epi16((B), (A), (B), (A), (B), (A), (B), (A))
+static WEBP_INLINE void ConvertRGBToY_SSE41(const __m128i* const R,
+ const __m128i* const G,
+ const __m128i* const B,
+ __m128i* const Y) {
+ const __m128i kRG_y = MK_CST_16(16839, 33059 - 16384);
+ const __m128i kGB_y = MK_CST_16(16384, 6420);
+ const __m128i kHALF_Y = _mm_set1_epi32((16 << YUV_FIX) + YUV_HALF);
+
+ const __m128i RG_lo = _mm_unpacklo_epi16(*R, *G);
+ const __m128i RG_hi = _mm_unpackhi_epi16(*R, *G);
+ const __m128i GB_lo = _mm_unpacklo_epi16(*G, *B);
+ const __m128i GB_hi = _mm_unpackhi_epi16(*G, *B);
+ TRANSFORM(RG_lo, RG_hi, GB_lo, GB_hi, kRG_y, kGB_y, kHALF_Y, YUV_FIX, *Y);
+}
+
+static WEBP_INLINE void ConvertRGBToUV_SSE41(const __m128i* const R,
+ const __m128i* const G,
+ const __m128i* const B,
+ __m128i* const U,
+ __m128i* const V) {
+ const __m128i kRG_u = MK_CST_16(-9719, -19081);
+ const __m128i kGB_u = MK_CST_16(0, 28800);
+ const __m128i kRG_v = MK_CST_16(28800, 0);
+ const __m128i kGB_v = MK_CST_16(-24116, -4684);
+ const __m128i kHALF_UV = _mm_set1_epi32(((128 << YUV_FIX) + YUV_HALF) << 2);
+
+ const __m128i RG_lo = _mm_unpacklo_epi16(*R, *G);
+ const __m128i RG_hi = _mm_unpackhi_epi16(*R, *G);
+ const __m128i GB_lo = _mm_unpacklo_epi16(*G, *B);
+ const __m128i GB_hi = _mm_unpackhi_epi16(*G, *B);
+ TRANSFORM(RG_lo, RG_hi, GB_lo, GB_hi, kRG_u, kGB_u,
+ kHALF_UV, YUV_FIX + 2, *U);
+ TRANSFORM(RG_lo, RG_hi, GB_lo, GB_hi, kRG_v, kGB_v,
+ kHALF_UV, YUV_FIX + 2, *V);
+}
+
+#undef MK_CST_16
+#undef TRANSFORM
+
+static void ConvertRGB24ToY_SSE41(const uint8_t* rgb, uint8_t* y, int width) {
+ const int max_width = width & ~31;
+ int i;
+ for (i = 0; i < max_width; rgb += 3 * 16 * 2) {
+ __m128i rgb_plane[6];
+ int j;
+
+ RGB24PackedToPlanar_SSE41(rgb, rgb_plane);
+
+ for (j = 0; j < 2; ++j, i += 16) {
+ const __m128i zero = _mm_setzero_si128();
+ __m128i r, g, b, Y0, Y1;
+
+ // Convert to 16-bit Y.
+ r = _mm_unpacklo_epi8(rgb_plane[0 + j], zero);
+ g = _mm_unpacklo_epi8(rgb_plane[2 + j], zero);
+ b = _mm_unpacklo_epi8(rgb_plane[4 + j], zero);
+ ConvertRGBToY_SSE41(&r, &g, &b, &Y0);
+
+ // Convert to 16-bit Y.
+ r = _mm_unpackhi_epi8(rgb_plane[0 + j], zero);
+ g = _mm_unpackhi_epi8(rgb_plane[2 + j], zero);
+ b = _mm_unpackhi_epi8(rgb_plane[4 + j], zero);
+ ConvertRGBToY_SSE41(&r, &g, &b, &Y1);
+
+ // Cast to 8-bit and store.
+ STORE_16(_mm_packus_epi16(Y0, Y1), y + i);
+ }
+ }
+ for (; i < width; ++i, rgb += 3) { // left-over
+ y[i] = VP8RGBToY(rgb[0], rgb[1], rgb[2], YUV_HALF);
+ }
+}
+
+static void ConvertBGR24ToY_SSE41(const uint8_t* bgr, uint8_t* y, int width) {
+ const int max_width = width & ~31;
+ int i;
+ for (i = 0; i < max_width; bgr += 3 * 16 * 2) {
+ __m128i bgr_plane[6];
+ int j;
+
+ RGB24PackedToPlanar_SSE41(bgr, bgr_plane);
+
+ for (j = 0; j < 2; ++j, i += 16) {
+ const __m128i zero = _mm_setzero_si128();
+ __m128i r, g, b, Y0, Y1;
+
+ // Convert to 16-bit Y.
+ b = _mm_unpacklo_epi8(bgr_plane[0 + j], zero);
+ g = _mm_unpacklo_epi8(bgr_plane[2 + j], zero);
+ r = _mm_unpacklo_epi8(bgr_plane[4 + j], zero);
+ ConvertRGBToY_SSE41(&r, &g, &b, &Y0);
+
+ // Convert to 16-bit Y.
+ b = _mm_unpackhi_epi8(bgr_plane[0 + j], zero);
+ g = _mm_unpackhi_epi8(bgr_plane[2 + j], zero);
+ r = _mm_unpackhi_epi8(bgr_plane[4 + j], zero);
+ ConvertRGBToY_SSE41(&r, &g, &b, &Y1);
+
+ // Cast to 8-bit and store.
+ STORE_16(_mm_packus_epi16(Y0, Y1), y + i);
+ }
+ }
+ for (; i < width; ++i, bgr += 3) { // left-over
+ y[i] = VP8RGBToY(bgr[2], bgr[1], bgr[0], YUV_HALF);
+ }
+}
+
+static void ConvertARGBToY_SSE41(const uint32_t* argb, uint8_t* y, int width) {
+ const int max_width = width & ~15;
+ int i;
+ for (i = 0; i < max_width; i += 16) {
+ __m128i Y0, Y1, rgb[6];
+ RGB32PackedToPlanar_SSE41(&argb[i], rgb);
+ ConvertRGBToY_SSE41(&rgb[0], &rgb[2], &rgb[4], &Y0);
+ ConvertRGBToY_SSE41(&rgb[1], &rgb[3], &rgb[5], &Y1);
+ STORE_16(_mm_packus_epi16(Y0, Y1), y + i);
+ }
+ for (; i < width; ++i) { // left-over
+ const uint32_t p = argb[i];
+ y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff,
+ YUV_HALF);
+ }
+}
+
+// Horizontal add (doubled) of two 16b values, result is 16b.
+// in: A | B | C | D | ... -> out: 2*(A+B) | 2*(C+D) | ...
+static void HorizontalAddPack_SSE41(const __m128i* const A,
+ const __m128i* const B,
+ __m128i* const out) {
+ const __m128i k2 = _mm_set1_epi16(2);
+ const __m128i C = _mm_madd_epi16(*A, k2);
+ const __m128i D = _mm_madd_epi16(*B, k2);
+ *out = _mm_packs_epi32(C, D);
+}
+
+static void ConvertARGBToUV_SSE41(const uint32_t* argb,
+ uint8_t* u, uint8_t* v,
+ int src_width, int do_store) {
+ const int max_width = src_width & ~31;
+ int i;
+ for (i = 0; i < max_width; i += 32, u += 16, v += 16) {
+ __m128i rgb[6], U0, V0, U1, V1;
+ RGB32PackedToPlanar_SSE41(&argb[i], rgb);
+ HorizontalAddPack_SSE41(&rgb[0], &rgb[1], &rgb[0]);
+ HorizontalAddPack_SSE41(&rgb[2], &rgb[3], &rgb[2]);
+ HorizontalAddPack_SSE41(&rgb[4], &rgb[5], &rgb[4]);
+ ConvertRGBToUV_SSE41(&rgb[0], &rgb[2], &rgb[4], &U0, &V0);
+
+ RGB32PackedToPlanar_SSE41(&argb[i + 16], rgb);
+ HorizontalAddPack_SSE41(&rgb[0], &rgb[1], &rgb[0]);
+ HorizontalAddPack_SSE41(&rgb[2], &rgb[3], &rgb[2]);
+ HorizontalAddPack_SSE41(&rgb[4], &rgb[5], &rgb[4]);
+ ConvertRGBToUV_SSE41(&rgb[0], &rgb[2], &rgb[4], &U1, &V1);
+
+ U0 = _mm_packus_epi16(U0, U1);
+ V0 = _mm_packus_epi16(V0, V1);
+ if (!do_store) {
+ const __m128i prev_u = LOAD_16(u);
+ const __m128i prev_v = LOAD_16(v);
+ U0 = _mm_avg_epu8(U0, prev_u);
+ V0 = _mm_avg_epu8(V0, prev_v);
+ }
+ STORE_16(U0, u);
+ STORE_16(V0, v);
+ }
+ if (i < src_width) { // left-over
+ WebPConvertARGBToUV_C(argb + i, u, v, src_width - i, do_store);
+ }
+}
+
+// Convert 16 packed ARGB 16b-values to r[], g[], b[]
+static WEBP_INLINE void RGBA32PackedToPlanar_16b_SSE41(
+ const uint16_t* const rgbx,
+ __m128i* const r, __m128i* const g, __m128i* const b) {
+ const __m128i in0 = LOAD_16(rgbx + 0); // r0 | g0 | b0 |x| r1 | g1 | b1 |x
+ const __m128i in1 = LOAD_16(rgbx + 8); // r2 | g2 | b2 |x| r3 | g3 | b3 |x
+ const __m128i in2 = LOAD_16(rgbx + 16); // r4 | ...
+ const __m128i in3 = LOAD_16(rgbx + 24); // r6 | ...
+ // aarrggbb as 16-bit.
+ const __m128i shuff0 =
+ _mm_set_epi8(-1, -1, -1, -1, 13, 12, 5, 4, 11, 10, 3, 2, 9, 8, 1, 0);
+ const __m128i shuff1 =
+ _mm_set_epi8(13, 12, 5, 4, -1, -1, -1, -1, 11, 10, 3, 2, 9, 8, 1, 0);
+ const __m128i A0 = _mm_shuffle_epi8(in0, shuff0);
+ const __m128i A1 = _mm_shuffle_epi8(in1, shuff1);
+ const __m128i A2 = _mm_shuffle_epi8(in2, shuff0);
+ const __m128i A3 = _mm_shuffle_epi8(in3, shuff1);
+ // R0R1G0G1
+ // B0B1****
+ // R2R3G2G3
+ // B2B3****
+ // (OR is used to free port 5 for the unpack)
+ const __m128i B0 = _mm_unpacklo_epi32(A0, A1);
+ const __m128i B1 = _mm_or_si128(A0, A1);
+ const __m128i B2 = _mm_unpacklo_epi32(A2, A3);
+ const __m128i B3 = _mm_or_si128(A2, A3);
+ // Gather the channels.
+ *r = _mm_unpacklo_epi64(B0, B2);
+ *g = _mm_unpackhi_epi64(B0, B2);
+ *b = _mm_unpackhi_epi64(B1, B3);
+}
+
+static void ConvertRGBA32ToUV_SSE41(const uint16_t* rgb,
+ uint8_t* u, uint8_t* v, int width) {
+ const int max_width = width & ~15;
+ const uint16_t* const last_rgb = rgb + 4 * max_width;
+ while (rgb < last_rgb) {
+ __m128i r, g, b, U0, V0, U1, V1;
+ RGBA32PackedToPlanar_16b_SSE41(rgb + 0, &r, &g, &b);
+ ConvertRGBToUV_SSE41(&r, &g, &b, &U0, &V0);
+ RGBA32PackedToPlanar_16b_SSE41(rgb + 32, &r, &g, &b);
+ ConvertRGBToUV_SSE41(&r, &g, &b, &U1, &V1);
+ STORE_16(_mm_packus_epi16(U0, U1), u);
+ STORE_16(_mm_packus_epi16(V0, V1), v);
+ u += 16;
+ v += 16;
+ rgb += 2 * 32;
+ }
+ if (max_width < width) { // left-over
+ WebPConvertRGBA32ToUV_C(rgb, u, v, width - max_width);
+ }
+}
+
+//------------------------------------------------------------------------------
+
+extern void WebPInitConvertARGBToYUVSSE41(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUVSSE41(void) {
+ WebPConvertARGBToY = ConvertARGBToY_SSE41;
+ WebPConvertARGBToUV = ConvertARGBToUV_SSE41;
+
+ WebPConvertRGB24ToY = ConvertRGB24ToY_SSE41;
+ WebPConvertBGR24ToY = ConvertBGR24ToY_SSE41;
+
+ WebPConvertRGBA32ToUV = ConvertRGBA32ToUV_SSE41;
+}
+
+//------------------------------------------------------------------------------
+
+#else // !WEBP_USE_SSE41
+
+WEBP_DSP_INIT_STUB(WebPInitSamplersSSE41)
+WEBP_DSP_INIT_STUB(WebPInitConvertARGBToYUVSSE41)
+
+#endif // WEBP_USE_SSE41
diff --git a/thirdparty/libwebp/src/enc/alpha_enc.c b/thirdparty/libwebp/src/enc/alpha_enc.c
index 7e8d87f22e..dce9ca957d 100644
--- a/thirdparty/libwebp/src/enc/alpha_enc.c
+++ b/thirdparty/libwebp/src/enc/alpha_enc.c
@@ -361,7 +361,8 @@ static int EncodeAlpha(VP8Encoder* const enc,
//------------------------------------------------------------------------------
// Main calls
-static int CompressAlphaJob(VP8Encoder* const enc, void* dummy) {
+static int CompressAlphaJob(void* arg1, void* dummy) {
+ VP8Encoder* const enc = (VP8Encoder*)arg1;
const WebPConfig* config = enc->config_;
uint8_t* alpha_data = NULL;
size_t alpha_size = 0;
@@ -394,7 +395,7 @@ void VP8EncInitAlpha(VP8Encoder* const enc) {
WebPGetWorkerInterface()->Init(worker);
worker->data1 = enc;
worker->data2 = NULL;
- worker->hook = (WebPWorkerHook)CompressAlphaJob;
+ worker->hook = CompressAlphaJob;
}
}
diff --git a/thirdparty/libwebp/src/enc/analysis_enc.c b/thirdparty/libwebp/src/enc/analysis_enc.c
index 08f471f5f8..a47ff7d4e8 100644
--- a/thirdparty/libwebp/src/enc/analysis_enc.c
+++ b/thirdparty/libwebp/src/enc/analysis_enc.c
@@ -434,7 +434,9 @@ typedef struct {
} SegmentJob;
// main work call
-static int DoSegmentsJob(SegmentJob* const job, VP8EncIterator* const it) {
+static int DoSegmentsJob(void* arg1, void* arg2) {
+ SegmentJob* const job = (SegmentJob*)arg1;
+ VP8EncIterator* const it = (VP8EncIterator*)arg2;
int ok = 1;
if (!VP8IteratorIsDone(it)) {
uint8_t tmp[32 + WEBP_ALIGN_CST];
@@ -462,7 +464,7 @@ static void InitSegmentJob(VP8Encoder* const enc, SegmentJob* const job,
WebPGetWorkerInterface()->Init(&job->worker);
job->worker.data1 = job;
job->worker.data2 = &job->it;
- job->worker.hook = (WebPWorkerHook)DoSegmentsJob;
+ job->worker.hook = DoSegmentsJob;
VP8IteratorInit(enc, &job->it);
VP8IteratorSetRow(&job->it, start_row);
VP8IteratorSetCountDown(&job->it, (end_row - start_row) * enc->mb_w_);
diff --git a/thirdparty/libwebp/src/enc/frame_enc.c b/thirdparty/libwebp/src/enc/frame_enc.c
index 2b0dc66410..1aec376e44 100644
--- a/thirdparty/libwebp/src/enc/frame_enc.c
+++ b/thirdparty/libwebp/src/enc/frame_enc.c
@@ -198,7 +198,7 @@ static void SetSegmentProbas(VP8Encoder* const enc) {
for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) {
const VP8MBInfo* const mb = &enc->mb_info_[n];
- p[mb->segment_]++;
+ ++p[mb->segment_];
}
#if !defined(WEBP_DISABLE_STATS)
if (enc->pic_->stats != NULL) {
@@ -520,6 +520,14 @@ static void StoreSideInfo(const VP8EncIterator* const it) {
#endif
}
+static void ResetSideInfo(const VP8EncIterator* const it) {
+ VP8Encoder* const enc = it->enc_;
+ WebPPicture* const pic = enc->pic_;
+ if (pic->stats != NULL) {
+ memset(enc->block_count_, 0, sizeof(enc->block_count_));
+ }
+ ResetSSE(enc);
+}
#else // defined(WEBP_DISABLE_STATS)
static void ResetSSE(VP8Encoder* const enc) {
(void)enc;
@@ -528,10 +536,16 @@ static void StoreSideInfo(const VP8EncIterator* const it) {
VP8Encoder* const enc = it->enc_;
WebPPicture* const pic = enc->pic_;
if (pic->extra_info != NULL) {
- memset(pic->extra_info, 0,
- enc->mb_w_ * enc->mb_h_ * sizeof(*pic->extra_info));
+ if (it->x_ == 0 && it->y_ == 0) { // only do it once, at start
+ memset(pic->extra_info, 0,
+ enc->mb_w_ * enc->mb_h_ * sizeof(*pic->extra_info));
+ }
}
}
+
+static void ResetSideInfo(const VP8EncIterator* const it) {
+ (void)it;
+}
#endif // !defined(WEBP_DISABLE_STATS)
static double GetPSNR(uint64_t mse, uint64_t size) {
@@ -570,7 +584,7 @@ static uint64_t OneStatPass(VP8Encoder* const enc, VP8RDLevel rd_opt,
VP8IteratorImport(&it, NULL);
if (VP8Decimate(&it, &info, rd_opt)) {
// Just record the number of skips and act like skip_proba is not used.
- enc->proba_.nb_skip_++;
+ ++enc->proba_.nb_skip_;
}
RecordResiduals(&it, &info);
size += info.R + info.H;
@@ -841,6 +855,9 @@ int VP8EncTokenLoop(VP8Encoder* const enc) {
if (enc->max_i4_header_bits_ > 0 && size_p0 > PARTITION0_SIZE_LIMIT) {
++num_pass_left;
enc->max_i4_header_bits_ >>= 1; // strengthen header bit limitation...
+ if (is_last_pass) {
+ ResetSideInfo(&it);
+ }
continue; // ...and start over
}
if (is_last_pass) {
@@ -871,4 +888,3 @@ int VP8EncTokenLoop(VP8Encoder* const enc) {
#endif // DISABLE_TOKEN_BUFFER
//------------------------------------------------------------------------------
-
diff --git a/thirdparty/libwebp/src/enc/histogram_enc.c b/thirdparty/libwebp/src/enc/histogram_enc.c
index 056a972dda..9fdbc627a1 100644
--- a/thirdparty/libwebp/src/enc/histogram_enc.c
+++ b/thirdparty/libwebp/src/enc/histogram_enc.c
@@ -200,14 +200,9 @@ static WEBP_INLINE double BitsEntropyRefine(const VP8LBitEntropy* entropy) {
}
}
-double VP8LBitsEntropy(const uint32_t* const array, int n,
- uint32_t* const trivial_symbol) {
+double VP8LBitsEntropy(const uint32_t* const array, int n) {
VP8LBitEntropy entropy;
VP8LBitsEntropyUnrefined(array, n, &entropy);
- if (trivial_symbol != NULL) {
- *trivial_symbol =
- (entropy.nonzeros == 1) ? entropy.nonzero_code : VP8L_NON_TRIVIAL_SYM;
- }
return BitsEntropyRefine(&entropy);
}
@@ -605,7 +600,7 @@ static void HistogramCombineEntropyBin(VP8LHistogramSet* const image_histo,
}
// Implement a Lehmer random number generator with a multiplicative constant of
-// 48271 and a modulo constant of 2^31 − 1.
+// 48271 and a modulo constant of 2^31 - 1.
static uint32_t MyRand(uint32_t* const seed) {
*seed = (uint32_t)(((uint64_t)(*seed) * 48271u) % 2147483647u);
assert(*seed > 0);
@@ -1031,7 +1026,7 @@ int VP8LGetHistoImageSymbols(int xsize, int ysize,
}
}
- // TODO(vikasa): Optimize HistogramRemap for low-effort compression mode also.
+ // TODO(vrabaud): Optimize HistogramRemap for low-effort compression mode.
// Find the optimal map from original histograms to the final ones.
HistogramRemap(orig_histo, image_histo, histogram_symbols);
diff --git a/thirdparty/libwebp/src/enc/histogram_enc.h b/thirdparty/libwebp/src/enc/histogram_enc.h
index 15b1fbda34..e8c4c83f6f 100644
--- a/thirdparty/libwebp/src/enc/histogram_enc.h
+++ b/thirdparty/libwebp/src/enc/histogram_enc.h
@@ -109,10 +109,7 @@ int VP8LGetHistoImageSymbols(int xsize, int ysize,
uint16_t* const histogram_symbols);
// Returns the entropy for the symbols in the input array.
-// Also sets trivial_symbol to the code value, if the array has only one code
-// value. Otherwise, set it to VP8L_NON_TRIVIAL_SYM.
-double VP8LBitsEntropy(const uint32_t* const array, int n,
- uint32_t* const trivial_symbol);
+double VP8LBitsEntropy(const uint32_t* const array, int n);
// Estimate how many bits the combined entropy of literals and distance
// approximately maps to.
diff --git a/thirdparty/libwebp/src/enc/iterator_enc.c b/thirdparty/libwebp/src/enc/iterator_enc.c
index cfacfd2401..7c47d51272 100644
--- a/thirdparty/libwebp/src/enc/iterator_enc.c
+++ b/thirdparty/libwebp/src/enc/iterator_enc.c
@@ -26,6 +26,9 @@ static void InitLeft(VP8EncIterator* const it) {
memset(it->u_left_, 129, 8);
memset(it->v_left_, 129, 8);
it->left_nz_[8] = 0;
+ if (it->top_derr_ != NULL) {
+ memset(&it->left_derr_, 0, sizeof(it->left_derr_));
+ }
}
static void InitTop(VP8EncIterator* const it) {
@@ -33,6 +36,9 @@ static void InitTop(VP8EncIterator* const it) {
const size_t top_size = enc->mb_w_ * 16;
memset(enc->y_top_, 127, 2 * top_size);
memset(enc->nz_, 0, enc->mb_w_ * sizeof(*enc->nz_));
+ if (enc->top_derr_ != NULL) {
+ memset(enc->top_derr_, 0, enc->mb_w_ * sizeof(*enc->top_derr_));
+ }
}
void VP8IteratorSetRow(VP8EncIterator* const it, int y) {
@@ -76,6 +82,7 @@ void VP8IteratorInit(VP8Encoder* const enc, VP8EncIterator* const it) {
it->y_left_ = (uint8_t*)WEBP_ALIGN(it->yuv_left_mem_ + 1);
it->u_left_ = it->y_left_ + 16 + 16;
it->v_left_ = it->u_left_ + 16;
+ it->top_derr_ = enc->top_derr_;
VP8IteratorReset(it);
}
@@ -450,4 +457,3 @@ int VP8IteratorRotateI4(VP8EncIterator* const it,
}
//------------------------------------------------------------------------------
-
diff --git a/thirdparty/libwebp/src/enc/near_lossless_enc.c b/thirdparty/libwebp/src/enc/near_lossless_enc.c
index cadd14c664..5517a7e271 100644
--- a/thirdparty/libwebp/src/enc/near_lossless_enc.c
+++ b/thirdparty/libwebp/src/enc/near_lossless_enc.c
@@ -146,6 +146,6 @@ int VP8ApplyNearLossless(const WebPPicture* const picture, int quality,
// Define a stub to suppress compiler warnings.
extern void VP8LNearLosslessStub(void);
-WEBP_TSAN_IGNORE_FUNCTION void VP8LNearLosslessStub(void) {}
+void VP8LNearLosslessStub(void) {}
#endif // (WEBP_NEAR_LOSSLESS == 1)
diff --git a/thirdparty/libwebp/src/enc/picture_csp_enc.c b/thirdparty/libwebp/src/enc/picture_csp_enc.c
index d531dd0282..02d9df76d5 100644
--- a/thirdparty/libwebp/src/enc/picture_csp_enc.c
+++ b/thirdparty/libwebp/src/enc/picture_csp_enc.c
@@ -28,11 +28,11 @@
// If defined, use table to compute x / alpha.
#define USE_INVERSE_ALPHA_TABLE
-static const union {
- uint32_t argb;
- uint8_t bytes[4];
-} test_endian = { 0xff000000u };
-#define ALPHA_IS_LAST (test_endian.bytes[3] == 0xff)
+#ifdef WORDS_BIGENDIAN
+#define ALPHA_OFFSET 0 // uint32_t 0xff000000 is 0xff,00,00,00 in memory
+#else
+#define ALPHA_OFFSET 3 // uint32_t 0xff000000 is 0x00,00,00,ff in memory
+#endif
//------------------------------------------------------------------------------
// Detection of non-trivial transparency
@@ -61,7 +61,7 @@ int WebPPictureHasTransparency(const WebPPicture* picture) {
return CheckNonOpaque(picture->a, picture->width, picture->height,
1, picture->a_stride);
} else {
- const int alpha_offset = ALPHA_IS_LAST ? 3 : 0;
+ const int alpha_offset = ALPHA_OFFSET;
return CheckNonOpaque((const uint8_t*)picture->argb + alpha_offset,
picture->width, picture->height,
4, picture->argb_stride * sizeof(*picture->argb));
@@ -126,7 +126,7 @@ static WEBP_INLINE int LinearToGamma(uint32_t base_value, int shift) {
#else
-static WEBP_TSAN_IGNORE_FUNCTION void InitGammaTables(void) {}
+static void InitGammaTables(void) {}
static WEBP_INLINE uint32_t GammaToLinear(uint8_t v) { return v; }
static WEBP_INLINE int LinearToGamma(uint32_t base_value, int shift) {
return (int)(base_value << shift);
@@ -170,29 +170,33 @@ typedef uint16_t fixed_y_t; // unsigned type with extra SFIX precision for W
#if defined(USE_GAMMA_COMPRESSION)
-// float variant of gamma-correction
// We use tables of different size and precision for the Rec709 / BT2020
// transfer function.
#define kGammaF (1./0.45)
-static float kGammaToLinearTabF[MAX_Y_T + 1]; // size scales with Y_FIX
-static float kLinearToGammaTabF[kGammaTabSize + 2];
-static volatile int kGammaTablesFOk = 0;
-
-static WEBP_TSAN_IGNORE_FUNCTION void InitGammaTablesF(void) {
- if (!kGammaTablesFOk) {
+static uint32_t kLinearToGammaTabS[kGammaTabSize + 2];
+#define GAMMA_TO_LINEAR_BITS 14
+static uint32_t kGammaToLinearTabS[MAX_Y_T + 1]; // size scales with Y_FIX
+static volatile int kGammaTablesSOk = 0;
+
+static WEBP_TSAN_IGNORE_FUNCTION void InitGammaTablesS(void) {
+ assert(2 * GAMMA_TO_LINEAR_BITS < 32); // we use uint32_t intermediate values
+ if (!kGammaTablesSOk) {
int v;
const double norm = 1. / MAX_Y_T;
const double scale = 1. / kGammaTabSize;
const double a = 0.09929682680944;
const double thresh = 0.018053968510807;
+ const double final_scale = 1 << GAMMA_TO_LINEAR_BITS;
for (v = 0; v <= MAX_Y_T; ++v) {
const double g = norm * v;
+ double value;
if (g <= thresh * 4.5) {
- kGammaToLinearTabF[v] = (float)(g / 4.5);
+ value = g / 4.5;
} else {
const double a_rec = 1. / (1. + a);
- kGammaToLinearTabF[v] = (float)pow(a_rec * (g + a), kGammaF);
+ value = pow(a_rec * (g + a), kGammaF);
}
+ kGammaToLinearTabS[v] = (uint32_t)(value * final_scale + .5);
}
for (v = 0; v <= kGammaTabSize; ++v) {
const double g = scale * v;
@@ -202,37 +206,44 @@ static WEBP_TSAN_IGNORE_FUNCTION void InitGammaTablesF(void) {
} else {
value = (1. + a) * pow(g, 1. / kGammaF) - a;
}
- kLinearToGammaTabF[v] = (float)(MAX_Y_T * value);
+ // we already incorporate the 1/2 rounding constant here
+ kLinearToGammaTabS[v] =
+ (uint32_t)(MAX_Y_T * value) + (1 << GAMMA_TO_LINEAR_BITS >> 1);
}
// to prevent small rounding errors to cause read-overflow:
- kLinearToGammaTabF[kGammaTabSize + 1] = kLinearToGammaTabF[kGammaTabSize];
- kGammaTablesFOk = 1;
+ kLinearToGammaTabS[kGammaTabSize + 1] = kLinearToGammaTabS[kGammaTabSize];
+ kGammaTablesSOk = 1;
}
}
-static WEBP_INLINE float GammaToLinearF(int v) {
- return kGammaToLinearTabF[v];
+// return value has a fixed-point precision of GAMMA_TO_LINEAR_BITS
+static WEBP_INLINE uint32_t GammaToLinearS(int v) {
+ return kGammaToLinearTabS[v];
}
-static WEBP_INLINE int LinearToGammaF(float value) {
- const float v = value * kGammaTabSize;
- const int tab_pos = (int)v;
- const float x = v - (float)tab_pos; // fractional part
- const float v0 = kLinearToGammaTabF[tab_pos + 0];
- const float v1 = kLinearToGammaTabF[tab_pos + 1];
- const float y = v1 * x + v0 * (1.f - x); // interpolate
- return (int)(y + .5);
+static WEBP_INLINE uint32_t LinearToGammaS(uint32_t value) {
+ // 'value' is in GAMMA_TO_LINEAR_BITS fractional precision
+ const uint32_t v = value * kGammaTabSize;
+ const uint32_t tab_pos = v >> GAMMA_TO_LINEAR_BITS;
+ // fractional part, in GAMMA_TO_LINEAR_BITS fixed-point precision
+ const uint32_t x = v - (tab_pos << GAMMA_TO_LINEAR_BITS); // fractional part
+ // v0 / v1 are in GAMMA_TO_LINEAR_BITS fixed-point precision (range [0..1])
+ const uint32_t v0 = kLinearToGammaTabS[tab_pos + 0];
+ const uint32_t v1 = kLinearToGammaTabS[tab_pos + 1];
+ // Final interpolation. Note that rounding is already included.
+ const uint32_t v2 = (v1 - v0) * x; // note: v1 >= v0.
+ const uint32_t result = v0 + (v2 >> GAMMA_TO_LINEAR_BITS);
+ return result;
}
#else
-static WEBP_TSAN_IGNORE_FUNCTION void InitGammaTablesF(void) {}
-static WEBP_INLINE float GammaToLinearF(int v) {
- const float norm = 1.f / MAX_Y_T;
- return norm * v;
+static void InitGammaTablesS(void) {}
+static WEBP_INLINE uint32_t GammaToLinearS(int v) {
+ return (v << GAMMA_TO_LINEAR_BITS) / MAX_Y_T;
}
-static WEBP_INLINE int LinearToGammaF(float value) {
- return (int)(MAX_Y_T * value + .5);
+static WEBP_INLINE uint32_t LinearToGammaS(uint32_t value) {
+ return (MAX_Y_T * value) >> GAMMA_TO_LINEAR_BITS;
}
#endif // USE_GAMMA_COMPRESSION
@@ -254,26 +265,22 @@ static int RGBToGray(int r, int g, int b) {
return (luma >> YUV_FIX);
}
-static float RGBToGrayF(float r, float g, float b) {
- return (float)(0.2126 * r + 0.7152 * g + 0.0722 * b);
-}
-
-static int ScaleDown(int a, int b, int c, int d) {
- const float A = GammaToLinearF(a);
- const float B = GammaToLinearF(b);
- const float C = GammaToLinearF(c);
- const float D = GammaToLinearF(d);
- return LinearToGammaF(0.25f * (A + B + C + D));
+static uint32_t ScaleDown(int a, int b, int c, int d) {
+ const uint32_t A = GammaToLinearS(a);
+ const uint32_t B = GammaToLinearS(b);
+ const uint32_t C = GammaToLinearS(c);
+ const uint32_t D = GammaToLinearS(d);
+ return LinearToGammaS((A + B + C + D + 2) >> 2);
}
static WEBP_INLINE void UpdateW(const fixed_y_t* src, fixed_y_t* dst, int w) {
int i;
for (i = 0; i < w; ++i) {
- const float R = GammaToLinearF(src[0 * w + i]);
- const float G = GammaToLinearF(src[1 * w + i]);
- const float B = GammaToLinearF(src[2 * w + i]);
- const float Y = RGBToGrayF(R, G, B);
- dst[i] = (fixed_y_t)LinearToGammaF(Y);
+ const uint32_t R = GammaToLinearS(src[0 * w + i]);
+ const uint32_t G = GammaToLinearS(src[1 * w + i]);
+ const uint32_t B = GammaToLinearS(src[2 * w + i]);
+ const uint32_t Y = RGBToGray(R, G, B);
+ dst[i] = (fixed_y_t)LinearToGammaS(Y);
}
}
@@ -863,7 +870,7 @@ static int ImportYUVAFromRGBA(const uint8_t* r_ptr,
}
if (use_iterative_conversion) {
- InitGammaTablesF();
+ InitGammaTablesS();
if (!PreprocessARGB(r_ptr, g_ptr, b_ptr, step, rgb_stride, picture)) {
return 0;
}
@@ -990,10 +997,10 @@ static int PictureARGBToYUVA(WebPPicture* picture, WebPEncCSP colorspace,
return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION);
} else {
const uint8_t* const argb = (const uint8_t*)picture->argb;
- const uint8_t* const r = ALPHA_IS_LAST ? argb + 2 : argb + 1;
- const uint8_t* const g = ALPHA_IS_LAST ? argb + 1 : argb + 2;
- const uint8_t* const b = ALPHA_IS_LAST ? argb + 0 : argb + 3;
- const uint8_t* const a = ALPHA_IS_LAST ? argb + 3 : argb + 0;
+ const uint8_t* const a = argb + (0 ^ ALPHA_OFFSET);
+ const uint8_t* const r = argb + (1 ^ ALPHA_OFFSET);
+ const uint8_t* const g = argb + (2 ^ ALPHA_OFFSET);
+ const uint8_t* const b = argb + (3 ^ ALPHA_OFFSET);
picture->colorspace = WEBP_YUV420;
return ImportYUVAFromRGBA(r, g, b, a, 4, 4 * picture->argb_stride,
@@ -1044,7 +1051,8 @@ int WebPPictureYUVAToARGB(WebPPicture* picture) {
const int argb_stride = 4 * picture->argb_stride;
uint8_t* dst = (uint8_t*)picture->argb;
const uint8_t *cur_u = picture->u, *cur_v = picture->v, *cur_y = picture->y;
- WebPUpsampleLinePairFunc upsample = WebPGetLinePairConverter(ALPHA_IS_LAST);
+ WebPUpsampleLinePairFunc upsample =
+ WebPGetLinePairConverter(ALPHA_OFFSET > 0);
// First row, with replicated top samples.
upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, width);
@@ -1087,6 +1095,7 @@ static int Import(WebPPicture* const picture,
const uint8_t* rgb, int rgb_stride,
int step, int swap_rb, int import_alpha) {
int y;
+ // swap_rb -> b,g,r,a , !swap_rb -> r,g,b,a
const uint8_t* r_ptr = rgb + (swap_rb ? 2 : 0);
const uint8_t* g_ptr = rgb + 1;
const uint8_t* b_ptr = rgb + (swap_rb ? 0 : 2);
@@ -1104,19 +1113,32 @@ static int Import(WebPPicture* const picture,
WebPInitAlphaProcessing();
if (import_alpha) {
+ // dst[] byte order is {a,r,g,b} for big-endian, {b,g,r,a} for little endian
uint32_t* dst = picture->argb;
- const int do_copy =
- (!swap_rb && !ALPHA_IS_LAST) || (swap_rb && ALPHA_IS_LAST);
+ const int do_copy = (ALPHA_OFFSET == 3) && swap_rb;
assert(step == 4);
- for (y = 0; y < height; ++y) {
- if (do_copy) {
+ if (do_copy) {
+ for (y = 0; y < height; ++y) {
memcpy(dst, rgb, width * 4);
- } else {
+ rgb += rgb_stride;
+ dst += picture->argb_stride;
+ }
+ } else {
+ for (y = 0; y < height; ++y) {
+#ifdef WORDS_BIGENDIAN
+ // BGRA or RGBA input order.
+ const uint8_t* a_ptr = rgb + 3;
+ WebPPackARGB(a_ptr, r_ptr, g_ptr, b_ptr, width, dst);
+ r_ptr += rgb_stride;
+ g_ptr += rgb_stride;
+ b_ptr += rgb_stride;
+#else
// RGBA input order. Need to swap R and B.
VP8LConvertBGRAToRGBA((const uint32_t*)rgb, width, (uint8_t*)dst);
+#endif
+ rgb += rgb_stride;
+ dst += picture->argb_stride;
}
- rgb += rgb_stride;
- dst += picture->argb_stride;
}
} else {
uint32_t* dst = picture->argb;
diff --git a/thirdparty/libwebp/src/enc/picture_psnr_enc.c b/thirdparty/libwebp/src/enc/picture_psnr_enc.c
index 362a7c79be..1a2f0bef3e 100644
--- a/thirdparty/libwebp/src/enc/picture_psnr_enc.c
+++ b/thirdparty/libwebp/src/enc/picture_psnr_enc.c
@@ -18,6 +18,7 @@
#include <math.h>
#include <stdlib.h>
+#include "src/dsp/dsp.h"
#include "src/enc/vp8i_enc.h"
#include "src/utils/utils.h"
@@ -169,6 +170,12 @@ int WebPPlaneDistortion(const uint8_t* src, size_t src_stride,
return 1;
}
+#ifdef WORDS_BIGENDIAN
+#define BLUE_OFFSET 3 // uint32_t 0x000000ff is 0x00,00,00,ff in memory
+#else
+#define BLUE_OFFSET 0 // uint32_t 0x000000ff is 0xff,00,00,00 in memory
+#endif
+
int WebPPictureDistortion(const WebPPicture* src, const WebPPicture* ref,
int type, float results[5]) {
int w, h, c;
@@ -195,8 +202,10 @@ int WebPPictureDistortion(const WebPPicture* src, const WebPPicture* ref,
float distortion;
const size_t stride0 = 4 * (size_t)p0.argb_stride;
const size_t stride1 = 4 * (size_t)p1.argb_stride;
- if (!WebPPlaneDistortion((const uint8_t*)p0.argb + c, stride0,
- (const uint8_t*)p1.argb + c, stride1,
+ // results are reported as BGRA
+ const int offset = c ^ BLUE_OFFSET;
+ if (!WebPPlaneDistortion((const uint8_t*)p0.argb + offset, stride0,
+ (const uint8_t*)p1.argb + offset, stride1,
w, h, 4, type, &distortion, results + c)) {
goto Error;
}
@@ -214,6 +223,8 @@ int WebPPictureDistortion(const WebPPicture* src, const WebPPicture* ref,
return ok;
}
+#undef BLUE_OFFSET
+
#else // defined(WEBP_DISABLE_STATS)
int WebPPlaneDistortion(const uint8_t* src, size_t src_stride,
const uint8_t* ref, size_t ref_stride,
diff --git a/thirdparty/libwebp/src/enc/quant_enc.c b/thirdparty/libwebp/src/enc/quant_enc.c
index 3b1a3129b5..35bfaf21ef 100644
--- a/thirdparty/libwebp/src/enc/quant_enc.c
+++ b/thirdparty/libwebp/src/enc/quant_enc.c
@@ -826,6 +826,85 @@ static int ReconstructIntra4(VP8EncIterator* const it,
return nz;
}
+//------------------------------------------------------------------------------
+// DC-error diffusion
+
+// Diffusion weights. We under-correct a bit (15/16th of the error is actually
+// diffused) to avoid 'rainbow' chessboard pattern of blocks at q~=0.
+#define C1 7 // fraction of error sent to the 4x4 block below
+#define C2 8 // fraction of error sent to the 4x4 block on the right
+#define DSHIFT 4
+#define DSCALE 1 // storage descaling, needed to make the error fit int8_t
+
+// Quantize as usual, but also compute and return the quantization error.
+// Error is already divided by DSHIFT.
+static int QuantizeSingle(int16_t* const v, const VP8Matrix* const mtx) {
+ int V = *v;
+ const int sign = (V < 0);
+ if (sign) V = -V;
+ if (V > (int)mtx->zthresh_[0]) {
+ const int qV = QUANTDIV(V, mtx->iq_[0], mtx->bias_[0]) * mtx->q_[0];
+ const int err = (V - qV);
+ *v = sign ? -qV : qV;
+ return (sign ? -err : err) >> DSCALE;
+ }
+ *v = 0;
+ return (sign ? -V : V) >> DSCALE;
+}
+
+static void CorrectDCValues(const VP8EncIterator* const it,
+ const VP8Matrix* const mtx,
+ int16_t tmp[][16], VP8ModeScore* const rd) {
+ // | top[0] | top[1]
+ // --------+--------+---------
+ // left[0] | tmp[0] tmp[1] <-> err0 err1
+ // left[1] | tmp[2] tmp[3] err2 err3
+ //
+ // Final errors {err1,err2,err3} are preserved and later restored
+ // as top[]/left[] on the next block.
+ int ch;
+ for (ch = 0; ch <= 1; ++ch) {
+ const int8_t* const top = it->top_derr_[it->x_][ch];
+ const int8_t* const left = it->left_derr_[ch];
+ int16_t (* const c)[16] = &tmp[ch * 4];
+ int err0, err1, err2, err3;
+ c[0][0] += (C1 * top[0] + C2 * left[0]) >> (DSHIFT - DSCALE);
+ err0 = QuantizeSingle(&c[0][0], mtx);
+ c[1][0] += (C1 * top[1] + C2 * err0) >> (DSHIFT - DSCALE);
+ err1 = QuantizeSingle(&c[1][0], mtx);
+ c[2][0] += (C1 * err0 + C2 * left[1]) >> (DSHIFT - DSCALE);
+ err2 = QuantizeSingle(&c[2][0], mtx);
+ c[3][0] += (C1 * err1 + C2 * err2) >> (DSHIFT - DSCALE);
+ err3 = QuantizeSingle(&c[3][0], mtx);
+ // error 'err' is bounded by mtx->q_[0] which is 132 at max. Hence
+ // err >> DSCALE will fit in an int8_t type if DSCALE>=1.
+ assert(abs(err1) <= 127 && abs(err2) <= 127 && abs(err3) <= 127);
+ rd->derr[ch][0] = (int8_t)err1;
+ rd->derr[ch][1] = (int8_t)err2;
+ rd->derr[ch][2] = (int8_t)err3;
+ }
+}
+
+static void StoreDiffusionErrors(VP8EncIterator* const it,
+ const VP8ModeScore* const rd) {
+ int ch;
+ for (ch = 0; ch <= 1; ++ch) {
+ int8_t* const top = it->top_derr_[it->x_][ch];
+ int8_t* const left = it->left_derr_[ch];
+ left[0] = rd->derr[ch][0]; // restore err1
+ left[1] = 3 * rd->derr[ch][2] >> 2; // ... 3/4th of err3
+ top[0] = rd->derr[ch][1]; // ... err2
+ top[1] = rd->derr[ch][2] - left[1]; // ... 1/4th of err3.
+ }
+}
+
+#undef C1
+#undef C2
+#undef DSHIFT
+#undef DSCALE
+
+//------------------------------------------------------------------------------
+
static int ReconstructUV(VP8EncIterator* const it, VP8ModeScore* const rd,
uint8_t* const yuv_out, int mode) {
const VP8Encoder* const enc = it->enc_;
@@ -839,6 +918,8 @@ static int ReconstructUV(VP8EncIterator* const it, VP8ModeScore* const rd,
for (n = 0; n < 8; n += 2) {
VP8FTransform2(src + VP8ScanUV[n], ref + VP8ScanUV[n], tmp[n]);
}
+ if (it->top_derr_ != NULL) CorrectDCValues(it, &dqm->uv_, tmp, rd);
+
if (DO_TRELLIS_UV && it->do_trellis_) {
int ch, x, y;
for (ch = 0, n = 0; ch <= 2; ch += 2) {
@@ -1101,6 +1182,9 @@ static void PickBestUV(VP8EncIterator* const it, VP8ModeScore* const rd) {
CopyScore(&rd_best, &rd_uv);
rd->mode_uv = mode;
memcpy(rd->uv_levels, rd_uv.uv_levels, sizeof(rd->uv_levels));
+ if (it->top_derr_ != NULL) {
+ memcpy(rd->derr, rd_uv.derr, sizeof(rd_uv.derr));
+ }
SwapPtr(&dst, &tmp_dst);
}
}
@@ -1109,6 +1193,9 @@ static void PickBestUV(VP8EncIterator* const it, VP8ModeScore* const rd) {
if (dst != dst0) { // copy 16x8 block if needed
VP8Copy16x8(dst, dst0);
}
+ if (it->top_derr_ != NULL) { // store diffusion errors for next block
+ StoreDiffusionErrors(it, rd);
+ }
}
//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/src/enc/vp8i_enc.h b/thirdparty/libwebp/src/enc/vp8i_enc.h
index 3463491e9d..624e8f8e66 100644
--- a/thirdparty/libwebp/src/enc/vp8i_enc.h
+++ b/thirdparty/libwebp/src/enc/vp8i_enc.h
@@ -30,9 +30,9 @@ extern "C" {
// Various defines and enums
// version numbers
-#define ENC_MAJ_VERSION 0
-#define ENC_MIN_VERSION 6
-#define ENC_REV_VERSION 1
+#define ENC_MAJ_VERSION 1
+#define ENC_MIN_VERSION 0
+#define ENC_REV_VERSION 0
enum { MAX_LF_LEVELS = 64, // Maximum loop filter level
MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost
@@ -120,6 +120,9 @@ static WEBP_INLINE int QUANTDIV(uint32_t n, uint32_t iQ, uint32_t B) {
// Uncomment the following to remove token-buffer code:
// #define DISABLE_TOKEN_BUFFER
+// quality below which error-diffusion is enabled
+#define ERROR_DIFFUSION_QUALITY 98
+
//------------------------------------------------------------------------------
// Headers
@@ -201,6 +204,8 @@ typedef struct {
score_t i4_penalty_; // penalty for using Intra4
} VP8SegmentInfo;
+typedef int8_t DError[2 /* u/v */][2 /* top or left */];
+
// Handy transient struct to accumulate score and info during RD-optimization
// and mode evaluation.
typedef struct {
@@ -213,6 +218,7 @@ typedef struct {
uint8_t modes_i4[16]; // mode numbers for intra4 predictions
int mode_uv; // mode number of chroma prediction
uint32_t nz; // non-zero blocks
+ int8_t derr[2][3]; // DC diffusion errors for U/V for blocks #1/2/3
} VP8ModeScore;
// Iterator structure to iterate through macroblocks, pointing to the
@@ -242,6 +248,9 @@ typedef struct {
int count_down0_; // starting counter value (for progress)
int percent0_; // saved initial progress percent
+ DError left_derr_; // left error diffusion (u/v)
+ DError *top_derr_; // top diffusion error - NULL if disabled
+
uint8_t* y_left_; // left luma samples (addressable from index -1 to 15).
uint8_t* u_left_; // left u samples (addressable from index -1 to 7)
uint8_t* v_left_; // left v samples (addressable from index -1 to 7)
@@ -401,6 +410,7 @@ struct VP8Encoder {
uint8_t* uv_top_; // top u/v samples.
// U and V are packed into 16 bytes (8 U + 8 V)
LFStats* lf_stats_; // autofilter stats (if NULL, autofilter is off)
+ DError* top_derr_; // diffusion error (NULL if disabled)
};
//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/src/enc/vp8l_enc.c b/thirdparty/libwebp/src/enc/vp8l_enc.c
index 312e521906..a89184eb08 100644
--- a/thirdparty/libwebp/src/enc/vp8l_enc.c
+++ b/thirdparty/libwebp/src/enc/vp8l_enc.c
@@ -26,8 +26,6 @@
#include "src/utils/utils.h"
#include "src/webp/format_constants.h"
-#include "src/enc/delta_palettization_enc.h"
-
// Maximum number of histogram images (sub-blocks).
#define MAX_HUFF_IMAGE_SIZE 2600
@@ -259,7 +257,7 @@ static int AnalyzeEntropy(const uint32_t* argb,
++histo[kHistoAlphaPred * 256];
for (j = 0; j < kHistoTotal; ++j) {
- entropy_comp[j] = VP8LBitsEntropy(&histo[j * 256], 256, NULL);
+ entropy_comp[j] = VP8LBitsEntropy(&histo[j * 256], 256);
}
entropy[kDirect] = entropy_comp[kHistoAlpha] +
entropy_comp[kHistoRed] +
@@ -384,8 +382,7 @@ static int EncoderAnalyze(VP8LEncoder* const enc,
AnalyzeAndCreatePalette(pic, low_effort,
enc->palette_, &enc->palette_size_);
- // TODO(jyrki): replace the decision to be based on an actual estimate
- // of entropy, or even spatial variance of entropy.
+ // Empirical bit sizes.
enc->histo_bits_ = GetHistoBits(method, use_palette,
pic->width, pic->height);
enc->transform_bits_ = GetTransformBits(method, enc->histo_bits_);
@@ -756,7 +753,6 @@ static WebPEncodingError StoreImageToBitMask(
// Don't write the distance with the extra bits code since
// the distance can be up to 18 bits of extra bits, and the prefix
// 15 bits, totaling to 33, and our PutBits only supports up to 32 bits.
- // TODO(jyrki): optimize this further.
VP8LPrefixEncode(distance, &code, &n_bits, &bits);
WriteHuffmanCode(bw, codes + 4, code);
VP8LPutBits(bw, bits, n_bits);
@@ -1464,49 +1460,6 @@ static WebPEncodingError EncodePalette(VP8LBitWriter* const bw, int low_effort,
20 /* quality */, low_effort);
}
-#ifdef WEBP_EXPERIMENTAL_FEATURES
-
-static WebPEncodingError EncodeDeltaPalettePredictorImage(
- VP8LBitWriter* const bw, VP8LEncoder* const enc, int quality,
- int low_effort) {
- const WebPPicture* const pic = enc->pic_;
- const int width = pic->width;
- const int height = pic->height;
-
- const int pred_bits = 5;
- const int transform_width = VP8LSubSampleSize(width, pred_bits);
- const int transform_height = VP8LSubSampleSize(height, pred_bits);
- const int pred = 7; // default is Predictor7 (Top/Left Average)
- const int tiles_per_row = VP8LSubSampleSize(width, pred_bits);
- const int tiles_per_col = VP8LSubSampleSize(height, pred_bits);
- uint32_t* predictors;
- int tile_x, tile_y;
- WebPEncodingError err = VP8_ENC_OK;
-
- predictors = (uint32_t*)WebPSafeMalloc(tiles_per_col * tiles_per_row,
- sizeof(*predictors));
- if (predictors == NULL) return VP8_ENC_ERROR_OUT_OF_MEMORY;
-
- for (tile_y = 0; tile_y < tiles_per_col; ++tile_y) {
- for (tile_x = 0; tile_x < tiles_per_row; ++tile_x) {
- predictors[tile_y * tiles_per_row + tile_x] = 0xff000000u | (pred << 8);
- }
- }
-
- VP8LPutBits(bw, TRANSFORM_PRESENT, 1);
- VP8LPutBits(bw, PREDICTOR_TRANSFORM, 2);
- VP8LPutBits(bw, pred_bits - 2, 3);
- err = EncodeImageNoHuffman(
- bw, predictors, &enc->hash_chain_,
- (VP8LBackwardRefs*)&enc->refs_[0], // cast const away
- (VP8LBackwardRefs*)&enc->refs_[1],
- transform_width, transform_height, quality, low_effort);
- WebPSafeFree(predictors);
- return err;
-}
-
-#endif // WEBP_EXPERIMENTAL_FEATURES
-
// -----------------------------------------------------------------------------
// VP8LEncoder
@@ -1568,7 +1521,7 @@ static int EncodeStreamHook(void* input, void* data2) {
WebPEncodingError err = VP8_ENC_OK;
const int quality = (int)config->quality;
const int low_effort = (config->method == 0);
-#if (WEBP_NEAR_LOSSLESS == 1) || defined(WEBP_EXPERIMENTAL_FEATURES)
+#if (WEBP_NEAR_LOSSLESS == 1)
const int width = picture->width;
#endif
const int height = picture->height;
@@ -1627,29 +1580,6 @@ static int EncodeStreamHook(void* input, void* data2) {
enc->argb_content_ = kEncoderNone;
#endif
-#ifdef WEBP_EXPERIMENTAL_FEATURES
- if (config->use_delta_palette) {
- enc->use_predict_ = 1;
- enc->use_cross_color_ = 0;
- enc->use_subtract_green_ = 0;
- enc->use_palette_ = 1;
- if (enc->argb_content_ != kEncoderNearLossless &&
- enc->argb_content_ != kEncoderPalette) {
- err = MakeInputImageCopy(enc);
- if (err != VP8_ENC_OK) goto Error;
- }
- err = WebPSearchOptimalDeltaPalette(enc);
- if (err != VP8_ENC_OK) goto Error;
- if (enc->use_palette_) {
- err = AllocateTransformBuffer(enc, width, height);
- if (err != VP8_ENC_OK) goto Error;
- err = EncodeDeltaPalettePredictorImage(bw, enc, quality, low_effort);
- if (err != VP8_ENC_OK) goto Error;
- use_delta_palette = 1;
- }
- }
-#endif // WEBP_EXPERIMENTAL_FEATURES
-
// Encode palette
if (enc->use_palette_) {
err = EncodePalette(bw, low_effort, enc);
@@ -1822,7 +1752,7 @@ WebPEncodingError VP8LEncodeStream(const WebPConfig* const config,
worker_interface->Init(worker);
worker->data1 = param;
worker->data2 = NULL;
- worker->hook = (WebPWorkerHook)EncodeStreamHook;
+ worker->hook = EncodeStreamHook;
}
}
@@ -1944,7 +1874,6 @@ int VP8LEncodeImage(const WebPConfig* const config,
err = VP8LEncodeStream(config, picture, &bw, 1 /*use_cache*/);
if (err != VP8_ENC_OK) goto Error;
- // TODO(skal): have a fine-grained progress report in VP8LEncodeStream().
if (!WebPReportProgress(picture, 90, &percent)) goto UserAbort;
// Finish the RIFF chunk.
diff --git a/thirdparty/libwebp/src/enc/webp_enc.c b/thirdparty/libwebp/src/enc/webp_enc.c
index 283cda8e7b..9f4b10c26c 100644
--- a/thirdparty/libwebp/src/enc/webp_enc.c
+++ b/thirdparty/libwebp/src/enc/webp_enc.c
@@ -159,12 +159,16 @@ static VP8Encoder* InitVP8Encoder(const WebPConfig* const config,
+ WEBP_ALIGN_CST; // align all
const size_t lf_stats_size =
config->autofilter ? sizeof(*enc->lf_stats_) + WEBP_ALIGN_CST : 0;
+ const size_t top_derr_size =
+ (config->quality <= ERROR_DIFFUSION_QUALITY || config->pass > 1) ?
+ mb_w * sizeof(*enc->top_derr_) : 0;
uint8_t* mem;
const uint64_t size = (uint64_t)sizeof(*enc) // main struct
+ WEBP_ALIGN_CST // cache alignment
+ info_size // modes info
+ preds_size // prediction modes
+ samples_size // top/left samples
+ + top_derr_size // top diffusion error
+ nz_size // coeff context bits
+ lf_stats_size; // autofilter stats
@@ -175,11 +179,12 @@ static VP8Encoder* InitVP8Encoder(const WebPConfig* const config,
" info: %ld\n"
" preds: %ld\n"
" top samples: %ld\n"
+ " top diffusion: %ld\n"
" non-zero: %ld\n"
" lf-stats: %ld\n"
" total: %ld\n",
sizeof(*enc) + WEBP_ALIGN_CST, info_size,
- preds_size, samples_size, nz_size, lf_stats_size, size);
+ preds_size, samples_size, top_derr_size, nz_size, lf_stats_size, size);
printf("Transient object sizes:\n"
" VP8EncIterator: %ld\n"
" VP8ModeScore: %ld\n"
@@ -219,6 +224,8 @@ static VP8Encoder* InitVP8Encoder(const WebPConfig* const config,
enc->y_top_ = mem;
enc->uv_top_ = enc->y_top_ + top_stride;
mem += 2 * top_stride;
+ enc->top_derr_ = top_derr_size ? (DError*)mem : NULL;
+ mem += top_derr_size;
assert(mem <= (uint8_t*)enc + size);
enc->config_ = config;
diff --git a/thirdparty/libwebp/src/mux/muxi.h b/thirdparty/libwebp/src/mux/muxi.h
index b73e3fbd7a..6b57eea30f 100644
--- a/thirdparty/libwebp/src/mux/muxi.h
+++ b/thirdparty/libwebp/src/mux/muxi.h
@@ -26,9 +26,9 @@ extern "C" {
//------------------------------------------------------------------------------
// Defines and constants.
-#define MUX_MAJ_VERSION 0
-#define MUX_MIN_VERSION 4
-#define MUX_REV_VERSION 1
+#define MUX_MAJ_VERSION 1
+#define MUX_MIN_VERSION 0
+#define MUX_REV_VERSION 0
// Chunk object.
typedef struct WebPChunk WebPChunk;
diff --git a/thirdparty/libwebp/src/utils/endian_inl_utils.h b/thirdparty/libwebp/src/utils/endian_inl_utils.h
index 4b2f91dfb8..3630a293bf 100644
--- a/thirdparty/libwebp/src/utils/endian_inl_utils.h
+++ b/thirdparty/libwebp/src/utils/endian_inl_utils.h
@@ -19,13 +19,6 @@
#include "src/dsp/dsp.h"
#include "src/webp/types.h"
-// some endian fix (e.g.: mips-gcc doesn't define __BIG_ENDIAN__)
-#if !defined(WORDS_BIGENDIAN) && \
- (defined(__BIG_ENDIAN__) || defined(_M_PPC) || \
- (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)))
-#define WORDS_BIGENDIAN
-#endif
-
#if defined(WORDS_BIGENDIAN)
#define HToLE32 BSwap32
#define HToLE16 BSwap16
diff --git a/thirdparty/minizip/crypt.h b/thirdparty/minizip/crypt.h
index a01d08d932..1e9e8200b2 100644
--- a/thirdparty/minizip/crypt.h
+++ b/thirdparty/minizip/crypt.h
@@ -32,7 +32,7 @@
/***********************************************************************
* Return the next byte in the pseudo-random sequence
*/
-static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)
+static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab)
{
unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an
* unpredictable manner on 16-bit systems; not a problem
@@ -45,7 +45,7 @@ static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)
/***********************************************************************
* Update the encryption keys with the next byte of plain text
*/
-static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c)
+static int update_keys(unsigned long* pkeys,const z_crc_t* pcrc_32_tab,int c)
{
(*(pkeys+0)) = CRC32((*(pkeys+0)), c);
(*(pkeys+1)) += (*(pkeys+0)) & 0xff;
@@ -62,7 +62,7 @@ static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int
* Initialize the encryption keys and the random header according to
* the given password.
*/
-static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab)
+static void init_keys(const char* passwd,unsigned long* pkeys,const z_crc_t* pcrc_32_tab)
{
*(pkeys+0) = 305419896L;
*(pkeys+1) = 591751049L;
@@ -91,7 +91,7 @@ static int crypthead(const char* passwd, /* password string */
unsigned char* buf, /* where to write header */
int bufSize,
unsigned long* pkeys,
- const unsigned long* pcrc_32_tab,
+ const z_crc_t* pcrc_32_tab,
unsigned long crcForCrypting)
{
int n; /* index in random header */
diff --git a/thirdparty/minizip/godot-zlib-1.2.4-minizip-seek.patch b/thirdparty/minizip/godot-zlib-1.2.4-minizip-seek.patch
index 8e66416a43..2162bafbbc 100644
--- a/thirdparty/minizip/godot-zlib-1.2.4-minizip-seek.patch
+++ b/thirdparty/minizip/godot-zlib-1.2.4-minizip-seek.patch
@@ -96,8 +96,8 @@ index 7617f41f1..32e27bd65 100644
+/* GODOT end */
+
/*
- Close a ZipFile opened with unzipOpen.
- If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
+ Close a ZipFile opened with unzOpen.
+ If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
@@ -1018,10 +1034,20 @@ local int unz64local_GetCurrentFileInfoInternal (unzFile file,
if (lSeek!=0)
@@ -237,7 +237,7 @@ index 3183968b7..54e65ad8a 100644
--- a/thirdparty/minizip/unzip.h
+++ b/thirdparty/minizip/unzip.h
@@ -202,6 +202,10 @@ extern int ZEXPORT unzClose OF((unzFile file));
- these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
+ these files MUST be closed with unzCloseCurrentFile before call unzClose.
return UNZ_OK if there is no problem. */
+/* GODOT start */
diff --git a/thirdparty/minizip/ioapi.c b/thirdparty/minizip/ioapi.c
index 2b42df4abd..9cb27c16db 100644
--- a/thirdparty/minizip/ioapi.c
+++ b/thirdparty/minizip/ioapi.c
@@ -10,10 +10,22 @@
*/
-#if (defined(_WIN32))
+#if defined(_WIN32) && (!(defined(_CRT_SECURE_NO_WARNINGS)))
#define _CRT_SECURE_NO_WARNINGS
#endif
+#if defined(__APPLE__) || defined(IOAPI_NO_64)
+// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions
+#define FOPEN_FUNC(filename, mode) fopen(filename, mode)
+#define FTELLO_FUNC(stream) ftello(stream)
+#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin)
+#else
+#define FOPEN_FUNC(filename, mode) fopen64(filename, mode)
+#define FTELLO_FUNC(stream) ftello64(stream)
+#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin)
+#endif
+
+
#include "ioapi.h"
voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)
@@ -47,7 +59,7 @@ ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream
else
{
uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream);
- if ((tell_uLong) == ((uLong)-1))
+ if ((tell_uLong) == MAXU32)
return (ZPOS64_T)-1;
else
return tell_uLong;
@@ -119,7 +131,7 @@ static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename,
mode_fopen = "wb";
if ((filename!=NULL) && (mode_fopen != NULL))
- file = fopen64((const char*)filename, mode_fopen);
+ file = FOPEN_FUNC((const char*)filename, mode_fopen);
return file;
}
@@ -149,7 +161,7 @@ static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream)
static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream)
{
ZPOS64_T ret;
- ret = ftello64((FILE *)stream);
+ ret = FTELLO_FUNC((FILE *)stream);
return ret;
}
@@ -195,7 +207,7 @@ static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T
}
ret = 0;
- if(fseeko64((FILE *)stream, offset, fseek_origin) != 0)
+ if(FSEEKO_FUNC((FILE *)stream, offset, fseek_origin) != 0)
ret = -1;
return ret;
diff --git a/thirdparty/minizip/ioapi.h b/thirdparty/minizip/ioapi.h
index 6043d34cea..4011e9cabb 100644
--- a/thirdparty/minizip/ioapi.h
+++ b/thirdparty/minizip/ioapi.h
@@ -21,7 +21,7 @@
#ifndef _ZLIBIOAPI64_H
#define _ZLIBIOAPI64_H
-#if (!defined(_WIN32)) && (!defined(WIN32))
+#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__))
// Linux needs this to support file operation on files larger then 4+GB
// But might need better if/def to select just the platforms that needs them.
@@ -38,6 +38,7 @@
#ifndef _FILE_OFFSET_BIT
#define _FILE_OFFSET_BIT 64
#endif
+
#endif
#include <stdio.h>
@@ -65,6 +66,11 @@
#define ftello64 ftell
#define fseeko64 fseek
#else
+#ifdef __FreeBSD__
+#define fopen64 fopen
+#define ftello64 ftello
+#define fseeko64 fseeko
+#endif
#ifdef _MSC_VER
#define fopen64 fopen
#if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC)))
@@ -101,6 +107,8 @@ typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T;
typedef uint64_t ZPOS64_T;
#else
+/* Maximum unsigned 32-bit value used as placeholder for zip64 */
+#define MAXU32 0xffffffff
#if defined(_MSC_VER) || defined(__BORLANDC__)
typedef unsigned __int64 ZPOS64_T;
diff --git a/thirdparty/minizip/unzip.c b/thirdparty/minizip/unzip.c
index 32e27bd657..31f8a5ff47 100644
--- a/thirdparty/minizip/unzip.c
+++ b/thirdparty/minizip/unzip.c
@@ -191,7 +191,7 @@ typedef struct
# ifndef NOUNCRYPT
unsigned long keys[3]; /* keys defining the pseudo-random sequence */
- const unsigned long* pcrc_32_tab;
+ const z_crc_t* pcrc_32_tab;
# endif
} unz64_s;
@@ -203,7 +203,7 @@ typedef struct
/* ===========================================================================
Read a byte from a gz_stream; update next_in and avail_in. Return EOF
for end of file.
- IN assertion: the stream s has been sucessfully opened for reading.
+ IN assertion: the stream s has been successfully opened for reading.
*/
@@ -817,9 +817,9 @@ extern void* unzGetOpaque(unzFile file) {
/* GODOT end */
/*
- Close a ZipFile opened with unzipOpen.
- If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
- these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
+ Close a ZipFile opened with unzOpen.
+ If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
+ these files MUST be closed with unzCloseCurrentFile before call unzClose.
return UNZ_OK if there is no problem. */
extern int ZEXPORT unzClose (unzFile file)
{
@@ -1066,26 +1066,26 @@ local int unz64local_GetCurrentFileInfoInternal (unzFile file,
{
uLong uL;
- if(file_info.uncompressed_size == (ZPOS64_T)(unsigned long)-1)
+ if(file_info.uncompressed_size == MAXU32)
{
if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
err=UNZ_ERRNO;
}
- if(file_info.compressed_size == (ZPOS64_T)(unsigned long)-1)
+ if(file_info.compressed_size == MAXU32)
{
if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
err=UNZ_ERRNO;
}
- if(file_info_internal.offset_curfile == (ZPOS64_T)(unsigned long)-1)
+ if(file_info_internal.offset_curfile == MAXU32)
{
/* Relative Header offset */
if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
err=UNZ_ERRNO;
}
- if(file_info.disk_num_start == (unsigned long)-1)
+ if(file_info.disk_num_start == MAXU32)
{
/* Disk Start Number */
if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
@@ -1171,7 +1171,7 @@ extern int ZEXPORT unzGetCurrentFileInfo (unzFile file,
szFileName,fileNameBufferSize,
extraField,extraFieldBufferSize,
szComment,commentBufferSize);
- if (err==UNZ_OK)
+ if ((err==UNZ_OK) && (pfile_info != NULL))
{
pfile_info->version = file_info64.version;
pfile_info->version_needed = file_info64.version_needed;
@@ -1249,7 +1249,7 @@ extern int ZEXPORT unzGoToNextFile (unzFile file)
/*
Try locate the file szFileName in the zipfile.
- For the iCaseSensitivity signification, see unzipStringFileNameCompare
+ For the iCaseSensitivity signification, see unzStringFileNameCompare
return value :
UNZ_OK if the file is found. It becomes the current file.
@@ -1806,7 +1806,7 @@ extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len)
return UNZ_PARAMERROR;
- if ((pfile_in_zip_read_info->read_buffer == NULL))
+ if (pfile_in_zip_read_info->read_buffer == NULL)
return UNZ_END_OF_LIST_OF_FILE;
if (len==0)
return 0;
@@ -2108,7 +2108,7 @@ extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len)
}
/*
- Close the file in zip opened with unzipOpenCurrentFile
+ Close the file in zip opened with unzOpenCurrentFile
Return UNZ_CRCERROR if all the file was read but the CRC is not good
*/
extern int ZEXPORT unzCloseCurrentFile (unzFile file)
diff --git a/thirdparty/minizip/unzip.h b/thirdparty/minizip/unzip.h
index 54e65ad8ab..bab1cb939f 100644
--- a/thirdparty/minizip/unzip.h
+++ b/thirdparty/minizip/unzip.h
@@ -197,9 +197,9 @@ extern unzFile ZEXPORT unzOpen2_64 OF((const void *path,
extern int ZEXPORT unzClose OF((unzFile file));
/*
- Close a ZipFile opened with unzipOpen.
+ Close a ZipFile opened with unzOpen.
If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
- these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
+ these files MUST be closed with unzCloseCurrentFile before call unzClose.
return UNZ_OK if there is no problem. */
/* GODOT start */
diff --git a/thirdparty/minizip/zip.c b/thirdparty/minizip/zip.c
index d7093e7457..2936e2b5d9 100644
--- a/thirdparty/minizip/zip.c
+++ b/thirdparty/minizip/zip.c
@@ -15,7 +15,7 @@
Oct-2009 - Mathias Svensson - Did some code cleanup and refactoring to get better overview of some functions.
Oct-2009 - Mathias Svensson - Added zipRemoveExtraInfoBlock to strip extra field data from its ZIP64 data
It is used when recreting zip archive with RAW when deleting items from a zip.
- ZIP64 data is automaticly added to items that needs it, and existing ZIP64 data need to be removed.
+ ZIP64 data is automatically added to items that needs it, and existing ZIP64 data need to be removed.
Oct-2009 - Mathias Svensson - Added support for BZIP2 as compression mode (bzip2 lib is required)
Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer
@@ -116,7 +116,7 @@ typedef struct linkedlist_datablock_internal_s
struct linkedlist_datablock_internal_s* next_datablock;
uLong avail_in_this_block;
uLong filled_in_this_block;
- uLong unused; /* for future use and alignement */
+ uLong unused; /* for future use and alignment */
unsigned char data[SIZEDATA_INDATABLOCK];
} linkedlist_datablock_internal;
@@ -157,7 +157,7 @@ typedef struct
ZPOS64_T totalUncompressedData;
#ifndef NOCRYPT
unsigned long keys[3]; /* keys defining the pseudo-random sequence */
- const unsigned long* pcrc_32_tab;
+ const z_crc_t* pcrc_32_tab;
int crypt_header_size;
#endif
} curfile64_info;
@@ -171,7 +171,7 @@ typedef struct
curfile64_info ci; /* info on the file curretly writing */
ZPOS64_T begin_pos; /* position of the beginning of the zipfile */
- ZPOS64_T add_position_when_writting_offset;
+ ZPOS64_T add_position_when_writing_offset;
ZPOS64_T number_entry;
#ifndef NO_ADDFILEINEXISTINGZIP
@@ -807,7 +807,7 @@ int LoadCentralDirectoryRecord(zip64_internal* pziinit)
}
byte_before_the_zipfile = central_pos - (offset_central_dir+size_central_dir);
- pziinit->add_position_when_writting_offset = byte_before_the_zipfile;
+ pziinit->add_position_when_writing_offset = byte_before_the_zipfile;
{
ZPOS64_T size_central_dir_to_read = size_central_dir;
@@ -877,7 +877,7 @@ extern zipFile ZEXPORT zipOpen3 (const void *pathname, int append, zipcharpc* gl
ziinit.in_opened_file_inzip = 0;
ziinit.ci.stream_initialised = 0;
ziinit.number_entry = 0;
- ziinit.add_position_when_writting_offset = 0;
+ ziinit.add_position_when_writing_offset = 0;
init_linkedlist(&(ziinit.central_dir));
@@ -1069,6 +1069,7 @@ extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename,
int err = ZIP_OK;
# ifdef NOCRYPT
+ (crcForCrypting);
if (password != NULL)
return ZIP_PARAMERROR;
# endif
@@ -1116,9 +1117,9 @@ extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename,
zi->ci.flag = flagBase;
if ((level==8) || (level==9))
zi->ci.flag |= 2;
- if ((level==2))
+ if (level==2)
zi->ci.flag |= 4;
- if ((level==1))
+ if (level==1)
zi->ci.flag |= 6;
if (password != NULL)
zi->ci.flag |= 1;
@@ -1165,7 +1166,7 @@ extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename,
if(zi->ci.pos_local_header >= 0xffffffff)
zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)0xffffffff,4);
else
- zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header - zi->add_position_when_writting_offset,4);
+ zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header - zi->add_position_when_writing_offset,4);
for (i=0;i<size_filename;i++)
*(zi->ci.central_header+SIZECENTRALHEADER+i) = *(filename+i);
@@ -1714,7 +1715,7 @@ extern int ZEXPORT zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncompressed_s
if (err==ZIP_OK)
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */
- if(uncompressed_size >= 0xffffffff)
+ if(uncompressed_size >= 0xffffffff || compressed_size >= 0xffffffff )
{
if(zi->ci.pos_zip64extrainfo > 0)
{
@@ -1728,6 +1729,8 @@ extern int ZEXPORT zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncompressed_s
if (err==ZIP_OK) /* uncompressed size, unknown */
err = zip64local_putValue(&zi->z_filefunc, zi->filestream, compressed_size, 8);
}
+ else
+ err = ZIP_BADZIPFILE; // Caller passed zip64 = 0, so no room for zip64 info -> fatal
}
else
{
@@ -1756,7 +1759,7 @@ extern int ZEXPORT zipCloseFileInZip (zipFile file)
int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip)
{
int err = ZIP_OK;
- ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writting_offset;
+ ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writing_offset;
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDLOCHEADERMAGIC,4);
@@ -1809,7 +1812,7 @@ int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centra
if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */
{
- ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writting_offset;
+ ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset;
err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (ZPOS64_T)pos,8);
}
return err;
@@ -1850,13 +1853,13 @@ int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir,
if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */
{
- ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writting_offset;
+ ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset;
if(pos >= 0xffffffff)
{
err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)0xffffffff,4);
}
else
- err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4);
+ err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writing_offset),4);
}
return err;
@@ -1922,8 +1925,8 @@ extern int ZEXPORT zipClose (zipFile file, const char* global_comment)
}
free_linkedlist(&(zi->central_dir));
- pos = centraldir_pos_inzip - zi->add_position_when_writting_offset;
- if(pos >= 0xffffffff)
+ pos = centraldir_pos_inzip - zi->add_position_when_writing_offset;
+ if(pos >= 0xffffffff || zi->number_entry > 0xFFFF)
{
ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream);
Write_Zip64EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip);
diff --git a/thirdparty/misc/stb_truetype.h b/thirdparty/misc/stb_truetype.h
index cec2425471..e2efae2285 100644
--- a/thirdparty/misc/stb_truetype.h
+++ b/thirdparty/misc/stb_truetype.h
@@ -1,4 +1,4 @@
-// stb_truetype.h - v1.17 - public domain
+// stb_truetype.h - v1.19 - public domain
// authored from 2009-2016 by Sean Barrett / RAD Game Tools
//
// This library processes TrueType files:
@@ -22,41 +22,35 @@
// Mikko Mononen: compound shape support, more cmap formats
// Tor Andersson: kerning, subpixel rendering
// Dougall Johnson: OpenType / Type 2 font handling
+// Daniel Ribeiro Maciel: basic GPOS-based kerning
//
// Misc other:
// Ryan Gordon
// Simon Glass
// github:IntellectualKitty
// Imanol Celaya
+// Daniel Ribeiro Maciel
//
// Bug/warning reports/fixes:
-// "Zer" on mollyrocket
-// Cass Everitt
-// stoiko (Haemimont Games)
-// Brian Hook
-// Walter van Niftrik
-// David Gow
-// David Given
-// Ivan-Assen Ivanov
-// Anthony Pesch
-// Johan Duparc
-// Hou Qiming
-// Fabian "ryg" Giesen
-// Martins Mozeiko
-// Cap Petschulat
-// Omar Cornut
-// github:aloucks
-// Peter LaValle
-// Sergey Popov
-// Giumo X. Clanjor
-// Higor Euripedes
-// Thomas Fields
-// Derek Vinyard
-// Cort Stratton
-// github:oyvindjam
+// "Zer" on mollyrocket Fabian "ryg" Giesen
+// Cass Everitt Martins Mozeiko
+// stoiko (Haemimont Games) Cap Petschulat
+// Brian Hook Omar Cornut
+// Walter van Niftrik github:aloucks
+// David Gow Peter LaValle
+// David Given Sergey Popov
+// Ivan-Assen Ivanov Giumo X. Clanjor
+// Anthony Pesch Higor Euripedes
+// Johan Duparc Thomas Fields
+// Hou Qiming Derek Vinyard
+// Rob Loach Cort Stratton
+// Kenney Phillis Jr. github:oyvindjam
+// Brian Costabile github:vassvik
//
// VERSION HISTORY
//
+// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod
+// 1.18 (2018-01-29) add missing function
// 1.17 (2017-07-23) make more arguments const; doc fix
// 1.16 (2017-07-12) SDF support
// 1.15 (2017-03-03) make more arguments const
@@ -171,7 +165,7 @@
// measurement for describing font size, defined as 72 points per inch.
// stb_truetype provides a point API for compatibility. However, true
// "per inch" conventions don't make much sense on computer displays
-// since they different monitors have different number of pixels per
+// since different monitors have different number of pixels per
// inch. For example, Windows traditionally uses a convention that
// there are 96 pixels per inch, thus making 'inch' measurements have
// nothing to do with inches, and thus effectively defining a point to
@@ -181,6 +175,39 @@
// for non-commercial fonts, thus making fonts scaled in points
// according to the TrueType spec incoherently sized in practice.
//
+// DETAILED USAGE:
+//
+// Scale:
+// Select how high you want the font to be, in points or pixels.
+// Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute
+// a scale factor SF that will be used by all other functions.
+//
+// Baseline:
+// You need to select a y-coordinate that is the baseline of where
+// your text will appear. Call GetFontBoundingBox to get the baseline-relative
+// bounding box for all characters. SF*-y0 will be the distance in pixels
+// that the worst-case character could extend above the baseline, so if
+// you want the top edge of characters to appear at the top of the
+// screen where y=0, then you would set the baseline to SF*-y0.
+//
+// Current point:
+// Set the current point where the first character will appear. The
+// first character could extend left of the current point; this is font
+// dependent. You can either choose a current point that is the leftmost
+// point and hope, or add some padding, or check the bounding box or
+// left-side-bearing of the first character to be displayed and set
+// the current point based on that.
+//
+// Displaying a character:
+// Compute the bounding box of the character. It will contain signed values
+// relative to <current_point, baseline>. I.e. if it returns x0,y0,x1,y1,
+// then the character should be displayed in the rectangle from
+// <current_point+SF*x0, baseline+SF*y0> to <current_point+SF*x1,baseline+SF*y1).
+//
+// Advancing for the next character:
+// Call GlyphHMetrics, and compute 'current_point += SF * advance'.
+//
+//
// ADVANCED USAGE
//
// Quality:
@@ -224,7 +251,7 @@
// Curve tesselation 120 LOC \__ 550 LOC Bitmap creation
// Bitmap management 100 LOC /
// Baked bitmap interface 70 LOC /
-// Font name matching & access 150 LOC ---- 150
+// Font name matching & access 150 LOC ---- 150
// C runtime library abstraction 60 LOC ---- 60
//
//
@@ -317,7 +344,7 @@ int main(int argc, char **argv)
}
return 0;
}
-#endif
+#endif
//
// Output:
//
@@ -331,9 +358,9 @@ int main(int argc, char **argv)
// :@@. M@M
// @@@o@@@@
// :M@@V:@@.
-//
+//
//////////////////////////////////////////////////////////////////////////////
-//
+//
// Complete program: print "Hello World!" banner, with bugs
//
#if 0
@@ -387,7 +414,8 @@ int main(int arg, char **argv)
//// INTEGRATION WITH YOUR CODEBASE
////
//// The following sections allow you to supply alternate definitions
-//// of C library functions used by stb_truetype.
+//// of C library functions used by stb_truetype, e.g. if you don't
+//// link with the C runtime library.
#ifdef STB_TRUETYPE_IMPLEMENTATION
// #define your own (u)stbtt_int8/16/32 before including to override this
@@ -403,7 +431,7 @@ int main(int arg, char **argv)
typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1];
typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1];
- // #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h
+ // e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h
#ifndef STBTT_ifloor
#include <math.h>
#define STBTT_ifloor(x) ((int) floor(x))
@@ -416,15 +444,15 @@ int main(int arg, char **argv)
#define STBTT_pow(x,y) pow(x,y)
#endif
- #ifndef STBTT_cos
+ #ifndef STBTT_fmod
#include <math.h>
- #define STBTT_cos(x) cos(x)
- #define STBTT_acos(x) acos(x)
+ #define STBTT_fmod(x,y) fmod(x,y)
#endif
- #ifndef STBTT_fabs
+ #ifndef STBTT_cos
#include <math.h>
- #define STBTT_fabs(x) fabs(x)
+ #define STBTT_cos(x) cos(x)
+ #define STBTT_acos(x) acos(x)
#endif
#ifndef STBTT_fabs
@@ -625,7 +653,7 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, cons
// Calling these functions in sequence is roughly equivalent to calling
// stbtt_PackFontRanges(). If you more control over the packing of multiple
// fonts, or if you want to pack custom data into a font texture, take a look
-// at the source to of stbtt_PackFontRanges() and create a custom version
+// at the source to of stbtt_PackFontRanges() and create a custom version
// using these functions, e.g. call GatherRects multiple times,
// building up a single array of rects, then call PackRects once,
// then call RenderIntoRects repeatedly. This may result in a
@@ -676,7 +704,7 @@ struct stbtt_fontinfo
int numGlyphs; // number of glyphs, needed for range checking
- int loca,head,glyf,hhea,hmtx,kern; // table locations as offset from start of .ttf
+ int loca,head,glyf,hhea,hmtx,kern,gpos; // table locations as offset from start of .ttf
int index_map; // a cmap mapping for our chosen character encoding
int indexToLocFormat; // format needed to map from glyph index to glyph
@@ -931,7 +959,7 @@ STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, floa
// and computing from that can allow drop-out prevention).
//
// The algorithm has not been optimized at all, so expect it to be slow
-// if computing lots of characters or very large sizes.
+// if computing lots of characters or very large sizes.
@@ -1319,6 +1347,7 @@ static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, in
info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required
info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required
info->kern = stbtt__find_table(data, fontstart, "kern"); // not required
+ info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required
if (!cmap || !info->head || !info->hhea || !info->hmtx)
return 0;
@@ -1687,7 +1716,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
if (i != 0)
num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
- // now start the new one
+ // now start the new one
start_off = !(flags & 1);
if (start_off) {
// if we start off with an off-curve point, then when we need to find a point on the curve
@@ -1740,7 +1769,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
int comp_num_verts = 0, i;
stbtt_vertex *comp_verts = 0, *tmp = 0;
float mtx[6] = {1,0,0,1,0,0}, m, n;
-
+
flags = ttSHORT(comp); comp+=2;
gidx = ttSHORT(comp); comp+=2;
@@ -1770,7 +1799,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
mtx[2] = ttSHORT(comp)/16384.0f; comp+=2;
mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
}
-
+
// Find transformation scales.
m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
@@ -2172,7 +2201,7 @@ static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, st
// push immediate
if (b0 == 255) {
- f = (float)stbtt__buf_get32(&b) / 0x10000;
+ f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000;
} else {
stbtt__buf_skip(&b, -1);
f = (float)(stbtt_int16)stbtt__cff_int(&b);
@@ -2210,12 +2239,10 @@ static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, in
{
stbtt__csctx c = STBTT__CSCTX_INIT(1);
int r = stbtt__run_charstring(info, glyph_index, &c);
- if (x0) {
- *x0 = r ? c.min_x : 0;
- *y0 = r ? c.min_y : 0;
- *x1 = r ? c.max_x : 0;
- *y1 = r ? c.max_y : 0;
- }
+ if (x0) *x0 = r ? c.min_x : 0;
+ if (y0) *y0 = r ? c.min_y : 0;
+ if (x1) *x1 = r ? c.max_x : 0;
+ if (y1) *y1 = r ? c.max_y : 0;
return r ? c.num_vertices : 0;
}
@@ -2239,7 +2266,7 @@ STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_inde
}
}
-STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
+static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
{
stbtt_uint8 *data = info->data + info->kern;
stbtt_uint32 needle, straw;
@@ -2269,9 +2296,260 @@ STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1,
return 0;
}
+static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph)
+{
+ stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);
+ switch(coverageFormat) {
+ case 1: {
+ stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2);
+
+ // Binary search.
+ stbtt_int32 l=0, r=glyphCount-1, m;
+ int straw, needle=glyph;
+ while (l <= r) {
+ stbtt_uint8 *glyphArray = coverageTable + 4;
+ stbtt_uint16 glyphID;
+ m = (l + r) >> 1;
+ glyphID = ttUSHORT(glyphArray + 2 * m);
+ straw = glyphID;
+ if (needle < straw)
+ r = m - 1;
+ else if (needle > straw)
+ l = m + 1;
+ else {
+ return m;
+ }
+ }
+ } break;
+
+ case 2: {
+ stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);
+ stbtt_uint8 *rangeArray = coverageTable + 4;
+
+ // Binary search.
+ stbtt_int32 l=0, r=rangeCount-1, m;
+ int strawStart, strawEnd, needle=glyph;
+ while (l <= r) {
+ stbtt_uint8 *rangeRecord;
+ m = (l + r) >> 1;
+ rangeRecord = rangeArray + 6 * m;
+ strawStart = ttUSHORT(rangeRecord);
+ strawEnd = ttUSHORT(rangeRecord + 2);
+ if (needle < strawStart)
+ r = m - 1;
+ else if (needle > strawEnd)
+ l = m + 1;
+ else {
+ stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4);
+ return startCoverageIndex + glyph - strawStart;
+ }
+ }
+ } break;
+
+ default: {
+ // There are no other cases.
+ STBTT_assert(0);
+ } break;
+ }
+
+ return -1;
+}
+
+static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
+{
+ stbtt_uint16 classDefFormat = ttUSHORT(classDefTable);
+ switch(classDefFormat)
+ {
+ case 1: {
+ stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2);
+ stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4);
+ stbtt_uint8 *classDef1ValueArray = classDefTable + 6;
+
+ if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
+ return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
+
+ classDefTable = classDef1ValueArray + 2 * glyphCount;
+ } break;
+
+ case 2: {
+ stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
+ stbtt_uint8 *classRangeRecords = classDefTable + 4;
+
+ // Binary search.
+ stbtt_int32 l=0, r=classRangeCount-1, m;
+ int strawStart, strawEnd, needle=glyph;
+ while (l <= r) {
+ stbtt_uint8 *classRangeRecord;
+ m = (l + r) >> 1;
+ classRangeRecord = classRangeRecords + 6 * m;
+ strawStart = ttUSHORT(classRangeRecord);
+ strawEnd = ttUSHORT(classRangeRecord + 2);
+ if (needle < strawStart)
+ r = m - 1;
+ else if (needle > strawEnd)
+ l = m + 1;
+ else
+ return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
+ }
+
+ classDefTable = classRangeRecords + 6 * classRangeCount;
+ } break;
+
+ default: {
+ // There are no other cases.
+ STBTT_assert(0);
+ } break;
+ }
+
+ return -1;
+}
+
+// Define to STBTT_assert(x) if you want to break on unimplemented formats.
+#define STBTT_GPOS_TODO_assert(x)
+
+static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
+{
+ stbtt_uint16 lookupListOffset;
+ stbtt_uint8 *lookupList;
+ stbtt_uint16 lookupCount;
+ stbtt_uint8 *data;
+ stbtt_int32 i;
+
+ if (!info->gpos) return 0;
+
+ data = info->data + info->gpos;
+
+ if (ttUSHORT(data+0) != 1) return 0; // Major version 1
+ if (ttUSHORT(data+2) != 0) return 0; // Minor version 0
+
+ lookupListOffset = ttUSHORT(data+8);
+ lookupList = data + lookupListOffset;
+ lookupCount = ttUSHORT(lookupList);
+
+ for (i=0; i<lookupCount; ++i) {
+ stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i);
+ stbtt_uint8 *lookupTable = lookupList + lookupOffset;
+
+ stbtt_uint16 lookupType = ttUSHORT(lookupTable);
+ stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
+ stbtt_uint8 *subTableOffsets = lookupTable + 6;
+ switch(lookupType) {
+ case 2: { // Pair Adjustment Positioning Subtable
+ stbtt_int32 sti;
+ for (sti=0; sti<subTableCount; sti++) {
+ stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
+ stbtt_uint8 *table = lookupTable + subtableOffset;
+ stbtt_uint16 posFormat = ttUSHORT(table);
+ stbtt_uint16 coverageOffset = ttUSHORT(table + 2);
+ stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1);
+ if (coverageIndex == -1) continue;
+
+ switch (posFormat) {
+ case 1: {
+ stbtt_int32 l, r, m;
+ int straw, needle;
+ stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
+ stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
+ stbtt_int32 valueRecordPairSizeInBytes = 2;
+ stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
+ stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
+ stbtt_uint8 *pairValueTable = table + pairPosOffset;
+ stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
+ stbtt_uint8 *pairValueArray = pairValueTable + 2;
+ // TODO: Support more formats.
+ STBTT_GPOS_TODO_assert(valueFormat1 == 4);
+ if (valueFormat1 != 4) return 0;
+ STBTT_GPOS_TODO_assert(valueFormat2 == 0);
+ if (valueFormat2 != 0) return 0;
+
+ STBTT_assert(coverageIndex < pairSetCount);
+
+ needle=glyph2;
+ r=pairValueCount-1;
+ l=0;
+
+ // Binary search.
+ while (l <= r) {
+ stbtt_uint16 secondGlyph;
+ stbtt_uint8 *pairValue;
+ m = (l + r) >> 1;
+ pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;
+ secondGlyph = ttUSHORT(pairValue);
+ straw = secondGlyph;
+ if (needle < straw)
+ r = m - 1;
+ else if (needle > straw)
+ l = m + 1;
+ else {
+ stbtt_int16 xAdvance = ttSHORT(pairValue + 2);
+ return xAdvance;
+ }
+ }
+ } break;
+
+ case 2: {
+ stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
+ stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
+
+ stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);
+ stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);
+ int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);
+ int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2);
+
+ stbtt_uint16 class1Count = ttUSHORT(table + 12);
+ stbtt_uint16 class2Count = ttUSHORT(table + 14);
+ STBTT_assert(glyph1class < class1Count);
+ STBTT_assert(glyph2class < class2Count);
+
+ // TODO: Support more formats.
+ STBTT_GPOS_TODO_assert(valueFormat1 == 4);
+ if (valueFormat1 != 4) return 0;
+ STBTT_GPOS_TODO_assert(valueFormat2 == 0);
+ if (valueFormat2 != 0) return 0;
+
+ if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) {
+ stbtt_uint8 *class1Records = table + 16;
+ stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count);
+ stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class);
+ return xAdvance;
+ }
+ } break;
+
+ default: {
+ // There are no other cases.
+ STBTT_assert(0);
+ break;
+ };
+ }
+ }
+ break;
+ };
+
+ default:
+ // TODO: Implement other stuff.
+ break;
+ }
+ }
+
+ return 0;
+}
+
+STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2)
+{
+ int xAdvance = 0;
+
+ if (info->gpos)
+ xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2);
+
+ if (info->kern)
+ xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2);
+
+ return xAdvance;
+}
+
STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2)
{
- if (!info->kern) // if no kerning table, don't waste time looking up both codepoint->glyphs
+ if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs
return 0;
return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2));
}
@@ -2395,7 +2673,7 @@ static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata)
hh->num_remaining_in_head_chunk = count;
}
--hh->num_remaining_in_head_chunk;
- return (char *) (hh->head) + size * hh->num_remaining_in_head_chunk;
+ return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk;
}
}
@@ -2449,7 +2727,7 @@ static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, i
float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
STBTT_assert(z != NULL);
if (!z) return z;
-
+
// round dx down to avoid overshooting
if (dxdy < 0)
z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy);
@@ -2527,7 +2805,7 @@ static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__ac
}
}
}
-
+
e = e->next;
}
}
@@ -3229,8 +3507,9 @@ error:
STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata)
{
- float scale = scale_x > scale_y ? scale_y : scale_x;
- int winding_count, *winding_lengths;
+ float scale = scale_x > scale_y ? scale_y : scale_x;
+ int winding_count = 0;
+ int *winding_lengths = NULL;
stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);
if (windings) {
stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata);
@@ -3248,7 +3527,7 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info
{
int ix0,iy0,ix1,iy1;
stbtt__bitmap gbm;
- stbtt_vertex *vertices;
+ stbtt_vertex *vertices;
int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
if (scale_x == 0) scale_x = scale_y;
@@ -3271,7 +3550,7 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info
if (height) *height = gbm.h;
if (xoff ) *xoff = ix0;
if (yoff ) *yoff = iy0;
-
+
if (gbm.w && gbm.h) {
gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata);
if (gbm.pixels) {
@@ -3282,7 +3561,7 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info
}
STBTT_free(vertices, info->userdata);
return gbm.pixels;
-}
+}
STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff)
{
@@ -3294,7 +3573,7 @@ STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigne
int ix0,iy0;
stbtt_vertex *vertices;
int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
- stbtt__bitmap gbm;
+ stbtt__bitmap gbm;
stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0);
gbm.pixels = output;
@@ -3316,7 +3595,12 @@ STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *
STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
{
return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);
-}
+}
+
+STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint)
+{
+ stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint));
+}
STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint)
{
@@ -3326,7 +3610,7 @@ STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, uns
STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
{
return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff);
-}
+}
STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint)
{
@@ -3451,7 +3735,7 @@ static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *no
con->y = 0;
con->bottom_y = 0;
STBTT__NOTUSED(nodes);
- STBTT__NOTUSED(num_nodes);
+ STBTT__NOTUSED(num_nodes);
}
static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects)
@@ -3826,7 +4110,7 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char
n = 0;
for (i=0; i < num_ranges; ++i)
n += ranges[i].num_chars;
-
+
rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context);
if (rects == NULL)
return 0;
@@ -3837,7 +4121,7 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char
n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects);
stbtt_PackFontRangesPackRects(spc, rects, n);
-
+
return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects);
STBTT_free(rects, spc->user_allocator_context);
@@ -3909,7 +4193,7 @@ static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2],
float discr = b*b - a*c;
if (discr > 0.0) {
float rcpna = -1 / a;
- float d = (float) sqrt(discr);
+ float d = (float) STBTT_sqrt(discr);
s0 = (b+d) * rcpna;
s1 = (b-d) * rcpna;
if (s0 >= 0.0 && s0 <= 1.0)
@@ -3971,7 +4255,7 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex
orig[1] = y;
// make sure y never passes through a vertex of the shape
- y_frac = (float) fmod(y, 1.0f);
+ y_frac = (float) STBTT_fmod(y, 1.0f);
if (y_frac < 0.01f)
y += 0.01f;
else if (y_frac > 0.99f)
@@ -3985,7 +4269,7 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex
int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y;
if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
- if (x_inter < x)
+ if (x_inter < x)
winding += (y0 < y1) ? 1 : -1;
}
}
@@ -4011,7 +4295,7 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex
y1 = (int)verts[i ].y;
if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
- if (x_inter < x)
+ if (x_inter < x)
winding += (y0 < y1) ? 1 : -1;
}
} else {
@@ -4023,7 +4307,7 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex
if (hits[1][0] < 0)
winding += (hits[1][1] < 0 ? -1 : 1);
}
- }
+ }
}
}
return winding;
@@ -4104,7 +4388,7 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
// invert for y-downwards bitmaps
scale_y = -scale_y;
-
+
{
int x,y,i,j;
float *precompute;
@@ -4253,7 +4537,7 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
STBTT_free(verts, info->userdata);
}
return data;
-}
+}
STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff)
{
@@ -4271,7 +4555,7 @@ STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata)
//
// check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string
-static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2)
+static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2)
{
stbtt_int32 i=0;
@@ -4310,7 +4594,7 @@ static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, s
return i;
}
-static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2)
+static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2)
{
return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2);
}
@@ -4439,7 +4723,7 @@ STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset,
STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index)
{
- return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index);
+ return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index);
}
STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data)
@@ -4471,6 +4755,9 @@ STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const
// FULL VERSION HISTORY
//
+// 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod
+// 1.18 (2018-01-29) add missing function
+// 1.17 (2017-07-23) make more arguments const; doc fix
// 1.16 (2017-07-12) SDF support
// 1.15 (2017-03-03) make more arguments const
// 1.14 (2017-01-16) num-fonts-in-TTC function
@@ -4529,38 +4816,38 @@ This software is available under 2 licenses -- choose whichever you prefer.
------------------------------------------------------------------------------
ALTERNATIVE A - MIT License
Copyright (c) 2017 Sean Barrett
-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
+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
+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
+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.
------------------------------------------------------------------------------
ALTERNATIVE B - Public Domain (www.unlicense.org)
This is free and unencumbered software released into the public domain.
-Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
-software, either in source code form or as a compiled binary, for any purpose,
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
+software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
-In jurisdictions that recognize copyright laws, the author or authors of this
-software dedicate any and all copyright interest in the software to the public
-domain. We make this dedication for the benefit of the public at large and to
-the detriment of our heirs and successors. We intend this dedication to be an
-overt act of relinquishment in perpetuity of all present and future rights to
+In jurisdictions that recognize copyright laws, the author or authors of this
+software dedicate any and all copyright interest in the software to the public
+domain. We make this dedication for the benefit of the public at large and to
+the detriment of our heirs and successors. We intend this dedication to be an
+overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law.
-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 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
+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 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.
------------------------------------------------------------------------------
*/
diff --git a/thirdparty/misc/stb_vorbis.c b/thirdparty/misc/stb_vorbis.c
index 14cebbf87e..8edcf0f38a 100644
--- a/thirdparty/misc/stb_vorbis.c
+++ b/thirdparty/misc/stb_vorbis.c
@@ -1,11 +1,11 @@
-// Ogg Vorbis audio decoder - v1.11 - public domain
+// Ogg Vorbis audio decoder - v1.14 - public domain
// http://nothings.org/stb_vorbis/
//
// Original version written by Sean Barrett in 2007.
//
-// Originally sponsored by RAD Game Tools. Seeking sponsored
-// by Phillip Bennefall, Marc Andersen, Aaron Baker, Elias Software,
-// Aras Pranckevicius, and Sean Barrett.
+// Originally sponsored by RAD Game Tools. Seeking implementation
+// sponsored by Phillip Bennefall, Marc Andersen, Aaron Baker,
+// Elias Software, Aras Pranckevicius, and Sean Barrett.
//
// LICENSE
//
@@ -30,22 +30,26 @@
// Tom Beaumont Ingo Leitgeb Nicolas Guillemot
// Phillip Bennefall Rohit Thiago Goulart
// manxorist@github saga musix github:infatum
+// Timur Gagiev
//
// Partial history:
-// 1.11 - 2017/07/23 - fix MinGW compilation
-// 1.10 - 2017/03/03 - more robust seeking; fix negative ilog(); clear error in open_memory
-// 1.09 - 2016/04/04 - back out 'truncation of last frame' fix from previous version
-// 1.08 - 2016/04/02 - warnings; setup memory leaks; truncation of last frame
-// 1.07 - 2015/01/16 - fixes for crashes on invalid files; warning fixes; const
-// 1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson)
+// 1.14 - 2018-02-11 - delete bogus dealloca usage
+// 1.13 - 2018-01-29 - fix truncation of last frame (hopefully)
+// 1.12 - 2017-11-21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files
+// 1.11 - 2017-07-23 - fix MinGW compilation
+// 1.10 - 2017-03-03 - more robust seeking; fix negative ilog(); clear error in open_memory
+// 1.09 - 2016-04-04 - back out 'truncation of last frame' fix from previous version
+// 1.08 - 2016-04-02 - warnings; setup memory leaks; truncation of last frame
+// 1.07 - 2015-01-16 - fixes for crashes on invalid files; warning fixes; const
+// 1.06 - 2015-08-31 - full, correct support for seeking API (Dougall Johnson)
// some crash fixes when out of memory or with corrupt files
// fix some inappropriately signed shifts
-// 1.05 - 2015/04/19 - don't define __forceinline if it's redundant
-// 1.04 - 2014/08/27 - fix missing const-correct case in API
-// 1.03 - 2014/08/07 - warning fixes
-// 1.02 - 2014/07/09 - declare qsort comparison as explicitly _cdecl in Windows
-// 1.01 - 2014/06/18 - fix stb_vorbis_get_samples_float (interleaved was correct)
-// 1.0 - 2014/05/26 - fix memory leaks; fix warnings; fix bugs in >2-channel;
+// 1.05 - 2015-04-19 - don't define __forceinline if it's redundant
+// 1.04 - 2014-08-27 - fix missing const-correct case in API
+// 1.03 - 2014-08-07 - warning fixes
+// 1.02 - 2014-07-09 - declare qsort comparison as explicitly _cdecl in Windows
+// 1.01 - 2014-06-18 - fix stb_vorbis_get_samples_float (interleaved was correct)
+// 1.0 - 2014-05-26 - fix memory leaks; fix warnings; fix bugs in >2-channel;
// (API change) report sample rate for decode-full-file funcs
//
// See end of file for full version history.
@@ -816,7 +820,7 @@ struct stb_vorbis
int current_loc_valid;
// per-blocksize precomputed data
-
+
// twiddle factors
float *A[2],*B[2],*C[2];
float *window[2];
@@ -880,11 +884,7 @@ static int error(vorb *f, enum STBVorbisError e)
#define array_size_required(count,size) (count*(sizeof(void *)+(size)))
#define temp_alloc(f,size) (f->alloc.alloc_buffer ? setup_temp_malloc(f,size) : alloca(size))
-#ifdef dealloca
-#define temp_free(f,p) (f->alloc.alloc_buffer ? 0 : dealloca(size))
-#else
#define temp_free(f,p) 0
-#endif
#define temp_alloc_save(f) ((f)->temp_offset)
#define temp_alloc_restore(f,p) ((f)->temp_offset = (p))
@@ -1142,7 +1142,7 @@ static void compute_sorted_huffman(Codebook *c, uint8 *lengths, uint32 *values)
if (!c->sparse) {
int k = 0;
for (i=0; i < c->entries; ++i)
- if (include_in_sort(c, lengths[i]))
+ if (include_in_sort(c, lengths[i]))
c->sorted_codewords[k++] = bit_reverse(c->codewords[i]);
assert(k == c->sorted_entries);
} else {
@@ -1323,7 +1323,7 @@ static int getn(vorb *z, uint8 *data, int n)
return 1;
}
- #ifndef STB_VORBIS_NO_STDIO
+ #ifndef STB_VORBIS_NO_STDIO
if (fread(data, n, 1, z->f) == 1)
return 1;
else {
@@ -1403,7 +1403,7 @@ static int start_page_no_capturepattern(vorb *f)
// header flag
f->page_flag = get8(f);
// absolute granule position
- loc0 = get32(f);
+ loc0 = get32(f);
loc1 = get32(f);
// @TODO: validate loc0,loc1 as valid positions?
// stream serial number -- vorbis doesn't interleave, so discard
@@ -1888,69 +1888,69 @@ static int predict_point(int x, int x0, int x1, int y0, int y1)
// the following table is block-copied from the specification
static float inverse_db_table[256] =
{
- 1.0649863e-07f, 1.1341951e-07f, 1.2079015e-07f, 1.2863978e-07f,
- 1.3699951e-07f, 1.4590251e-07f, 1.5538408e-07f, 1.6548181e-07f,
- 1.7623575e-07f, 1.8768855e-07f, 1.9988561e-07f, 2.1287530e-07f,
- 2.2670913e-07f, 2.4144197e-07f, 2.5713223e-07f, 2.7384213e-07f,
- 2.9163793e-07f, 3.1059021e-07f, 3.3077411e-07f, 3.5226968e-07f,
- 3.7516214e-07f, 3.9954229e-07f, 4.2550680e-07f, 4.5315863e-07f,
- 4.8260743e-07f, 5.1396998e-07f, 5.4737065e-07f, 5.8294187e-07f,
- 6.2082472e-07f, 6.6116941e-07f, 7.0413592e-07f, 7.4989464e-07f,
- 7.9862701e-07f, 8.5052630e-07f, 9.0579828e-07f, 9.6466216e-07f,
- 1.0273513e-06f, 1.0941144e-06f, 1.1652161e-06f, 1.2409384e-06f,
- 1.3215816e-06f, 1.4074654e-06f, 1.4989305e-06f, 1.5963394e-06f,
- 1.7000785e-06f, 1.8105592e-06f, 1.9282195e-06f, 2.0535261e-06f,
- 2.1869758e-06f, 2.3290978e-06f, 2.4804557e-06f, 2.6416497e-06f,
- 2.8133190e-06f, 2.9961443e-06f, 3.1908506e-06f, 3.3982101e-06f,
- 3.6190449e-06f, 3.8542308e-06f, 4.1047004e-06f, 4.3714470e-06f,
- 4.6555282e-06f, 4.9580707e-06f, 5.2802740e-06f, 5.6234160e-06f,
- 5.9888572e-06f, 6.3780469e-06f, 6.7925283e-06f, 7.2339451e-06f,
- 7.7040476e-06f, 8.2047000e-06f, 8.7378876e-06f, 9.3057248e-06f,
- 9.9104632e-06f, 1.0554501e-05f, 1.1240392e-05f, 1.1970856e-05f,
- 1.2748789e-05f, 1.3577278e-05f, 1.4459606e-05f, 1.5399272e-05f,
- 1.6400004e-05f, 1.7465768e-05f, 1.8600792e-05f, 1.9809576e-05f,
- 2.1096914e-05f, 2.2467911e-05f, 2.3928002e-05f, 2.5482978e-05f,
- 2.7139006e-05f, 2.8902651e-05f, 3.0780908e-05f, 3.2781225e-05f,
- 3.4911534e-05f, 3.7180282e-05f, 3.9596466e-05f, 4.2169667e-05f,
- 4.4910090e-05f, 4.7828601e-05f, 5.0936773e-05f, 5.4246931e-05f,
- 5.7772202e-05f, 6.1526565e-05f, 6.5524908e-05f, 6.9783085e-05f,
- 7.4317983e-05f, 7.9147585e-05f, 8.4291040e-05f, 8.9768747e-05f,
- 9.5602426e-05f, 0.00010181521f, 0.00010843174f, 0.00011547824f,
- 0.00012298267f, 0.00013097477f, 0.00013948625f, 0.00014855085f,
- 0.00015820453f, 0.00016848555f, 0.00017943469f, 0.00019109536f,
- 0.00020351382f, 0.00021673929f, 0.00023082423f, 0.00024582449f,
- 0.00026179955f, 0.00027881276f, 0.00029693158f, 0.00031622787f,
- 0.00033677814f, 0.00035866388f, 0.00038197188f, 0.00040679456f,
- 0.00043323036f, 0.00046138411f, 0.00049136745f, 0.00052329927f,
- 0.00055730621f, 0.00059352311f, 0.00063209358f, 0.00067317058f,
- 0.00071691700f, 0.00076350630f, 0.00081312324f, 0.00086596457f,
- 0.00092223983f, 0.00098217216f, 0.0010459992f, 0.0011139742f,
- 0.0011863665f, 0.0012634633f, 0.0013455702f, 0.0014330129f,
- 0.0015261382f, 0.0016253153f, 0.0017309374f, 0.0018434235f,
- 0.0019632195f, 0.0020908006f, 0.0022266726f, 0.0023713743f,
- 0.0025254795f, 0.0026895994f, 0.0028643847f, 0.0030505286f,
- 0.0032487691f, 0.0034598925f, 0.0036847358f, 0.0039241906f,
- 0.0041792066f, 0.0044507950f, 0.0047400328f, 0.0050480668f,
- 0.0053761186f, 0.0057254891f, 0.0060975636f, 0.0064938176f,
- 0.0069158225f, 0.0073652516f, 0.0078438871f, 0.0083536271f,
- 0.0088964928f, 0.009474637f, 0.010090352f, 0.010746080f,
- 0.011444421f, 0.012188144f, 0.012980198f, 0.013823725f,
- 0.014722068f, 0.015678791f, 0.016697687f, 0.017782797f,
- 0.018938423f, 0.020169149f, 0.021479854f, 0.022875735f,
- 0.024362330f, 0.025945531f, 0.027631618f, 0.029427276f,
- 0.031339626f, 0.033376252f, 0.035545228f, 0.037855157f,
- 0.040315199f, 0.042935108f, 0.045725273f, 0.048696758f,
- 0.051861348f, 0.055231591f, 0.058820850f, 0.062643361f,
- 0.066714279f, 0.071049749f, 0.075666962f, 0.080584227f,
- 0.085821044f, 0.091398179f, 0.097337747f, 0.10366330f,
- 0.11039993f, 0.11757434f, 0.12521498f, 0.13335215f,
- 0.14201813f, 0.15124727f, 0.16107617f, 0.17154380f,
- 0.18269168f, 0.19456402f, 0.20720788f, 0.22067342f,
- 0.23501402f, 0.25028656f, 0.26655159f, 0.28387361f,
- 0.30232132f, 0.32196786f, 0.34289114f, 0.36517414f,
- 0.38890521f, 0.41417847f, 0.44109412f, 0.46975890f,
- 0.50028648f, 0.53279791f, 0.56742212f, 0.60429640f,
- 0.64356699f, 0.68538959f, 0.72993007f, 0.77736504f,
+ 1.0649863e-07f, 1.1341951e-07f, 1.2079015e-07f, 1.2863978e-07f,
+ 1.3699951e-07f, 1.4590251e-07f, 1.5538408e-07f, 1.6548181e-07f,
+ 1.7623575e-07f, 1.8768855e-07f, 1.9988561e-07f, 2.1287530e-07f,
+ 2.2670913e-07f, 2.4144197e-07f, 2.5713223e-07f, 2.7384213e-07f,
+ 2.9163793e-07f, 3.1059021e-07f, 3.3077411e-07f, 3.5226968e-07f,
+ 3.7516214e-07f, 3.9954229e-07f, 4.2550680e-07f, 4.5315863e-07f,
+ 4.8260743e-07f, 5.1396998e-07f, 5.4737065e-07f, 5.8294187e-07f,
+ 6.2082472e-07f, 6.6116941e-07f, 7.0413592e-07f, 7.4989464e-07f,
+ 7.9862701e-07f, 8.5052630e-07f, 9.0579828e-07f, 9.6466216e-07f,
+ 1.0273513e-06f, 1.0941144e-06f, 1.1652161e-06f, 1.2409384e-06f,
+ 1.3215816e-06f, 1.4074654e-06f, 1.4989305e-06f, 1.5963394e-06f,
+ 1.7000785e-06f, 1.8105592e-06f, 1.9282195e-06f, 2.0535261e-06f,
+ 2.1869758e-06f, 2.3290978e-06f, 2.4804557e-06f, 2.6416497e-06f,
+ 2.8133190e-06f, 2.9961443e-06f, 3.1908506e-06f, 3.3982101e-06f,
+ 3.6190449e-06f, 3.8542308e-06f, 4.1047004e-06f, 4.3714470e-06f,
+ 4.6555282e-06f, 4.9580707e-06f, 5.2802740e-06f, 5.6234160e-06f,
+ 5.9888572e-06f, 6.3780469e-06f, 6.7925283e-06f, 7.2339451e-06f,
+ 7.7040476e-06f, 8.2047000e-06f, 8.7378876e-06f, 9.3057248e-06f,
+ 9.9104632e-06f, 1.0554501e-05f, 1.1240392e-05f, 1.1970856e-05f,
+ 1.2748789e-05f, 1.3577278e-05f, 1.4459606e-05f, 1.5399272e-05f,
+ 1.6400004e-05f, 1.7465768e-05f, 1.8600792e-05f, 1.9809576e-05f,
+ 2.1096914e-05f, 2.2467911e-05f, 2.3928002e-05f, 2.5482978e-05f,
+ 2.7139006e-05f, 2.8902651e-05f, 3.0780908e-05f, 3.2781225e-05f,
+ 3.4911534e-05f, 3.7180282e-05f, 3.9596466e-05f, 4.2169667e-05f,
+ 4.4910090e-05f, 4.7828601e-05f, 5.0936773e-05f, 5.4246931e-05f,
+ 5.7772202e-05f, 6.1526565e-05f, 6.5524908e-05f, 6.9783085e-05f,
+ 7.4317983e-05f, 7.9147585e-05f, 8.4291040e-05f, 8.9768747e-05f,
+ 9.5602426e-05f, 0.00010181521f, 0.00010843174f, 0.00011547824f,
+ 0.00012298267f, 0.00013097477f, 0.00013948625f, 0.00014855085f,
+ 0.00015820453f, 0.00016848555f, 0.00017943469f, 0.00019109536f,
+ 0.00020351382f, 0.00021673929f, 0.00023082423f, 0.00024582449f,
+ 0.00026179955f, 0.00027881276f, 0.00029693158f, 0.00031622787f,
+ 0.00033677814f, 0.00035866388f, 0.00038197188f, 0.00040679456f,
+ 0.00043323036f, 0.00046138411f, 0.00049136745f, 0.00052329927f,
+ 0.00055730621f, 0.00059352311f, 0.00063209358f, 0.00067317058f,
+ 0.00071691700f, 0.00076350630f, 0.00081312324f, 0.00086596457f,
+ 0.00092223983f, 0.00098217216f, 0.0010459992f, 0.0011139742f,
+ 0.0011863665f, 0.0012634633f, 0.0013455702f, 0.0014330129f,
+ 0.0015261382f, 0.0016253153f, 0.0017309374f, 0.0018434235f,
+ 0.0019632195f, 0.0020908006f, 0.0022266726f, 0.0023713743f,
+ 0.0025254795f, 0.0026895994f, 0.0028643847f, 0.0030505286f,
+ 0.0032487691f, 0.0034598925f, 0.0036847358f, 0.0039241906f,
+ 0.0041792066f, 0.0044507950f, 0.0047400328f, 0.0050480668f,
+ 0.0053761186f, 0.0057254891f, 0.0060975636f, 0.0064938176f,
+ 0.0069158225f, 0.0073652516f, 0.0078438871f, 0.0083536271f,
+ 0.0088964928f, 0.009474637f, 0.010090352f, 0.010746080f,
+ 0.011444421f, 0.012188144f, 0.012980198f, 0.013823725f,
+ 0.014722068f, 0.015678791f, 0.016697687f, 0.017782797f,
+ 0.018938423f, 0.020169149f, 0.021479854f, 0.022875735f,
+ 0.024362330f, 0.025945531f, 0.027631618f, 0.029427276f,
+ 0.031339626f, 0.033376252f, 0.035545228f, 0.037855157f,
+ 0.040315199f, 0.042935108f, 0.045725273f, 0.048696758f,
+ 0.051861348f, 0.055231591f, 0.058820850f, 0.062643361f,
+ 0.066714279f, 0.071049749f, 0.075666962f, 0.080584227f,
+ 0.085821044f, 0.091398179f, 0.097337747f, 0.10366330f,
+ 0.11039993f, 0.11757434f, 0.12521498f, 0.13335215f,
+ 0.14201813f, 0.15124727f, 0.16107617f, 0.17154380f,
+ 0.18269168f, 0.19456402f, 0.20720788f, 0.22067342f,
+ 0.23501402f, 0.25028656f, 0.26655159f, 0.28387361f,
+ 0.30232132f, 0.32196786f, 0.34289114f, 0.36517414f,
+ 0.38890521f, 0.41417847f, 0.44109412f, 0.46975890f,
+ 0.50028648f, 0.53279791f, 0.56742212f, 0.60429640f,
+ 0.64356699f, 0.68538959f, 0.72993007f, 0.77736504f,
0.82788260f, 0.88168307f, 0.9389798f, 1.0f
};
@@ -2042,6 +2042,8 @@ static int residue_decode(vorb *f, Codebook *book, float *target, int offset, in
return TRUE;
}
+// n is 1/2 of the blocksize --
+// specification: "Correct per-vector decode length is [n]/2"
static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int rn, uint8 *do_not_decode)
{
int i,j,pass;
@@ -2049,7 +2051,10 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int
int rtype = f->residue_types[rn];
int c = r->classbook;
int classwords = f->codebooks[c].dimensions;
- int n_read = r->end - r->begin;
+ unsigned int actual_size = rtype == 2 ? n*2 : n;
+ unsigned int limit_r_begin = (r->begin < actual_size ? r->begin : actual_size);
+ unsigned int limit_r_end = (r->end < actual_size ? r->end : actual_size);
+ int n_read = limit_r_end - limit_r_begin;
int part_read = n_read / r->part_size;
int temp_alloc_point = temp_alloc_save(f);
#ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
@@ -2346,11 +2351,11 @@ void inverse_mdct_slow(float *buffer, int n, vorb *f, int blocktype)
#if LIBVORBIS_MDCT
// directly call the vorbis MDCT using an interface documented
// by Jeff Roberts... useful for performance comparison
-typedef struct
+typedef struct
{
int n;
int log2n;
-
+
float *trig;
int *bitrev;
@@ -2369,7 +2374,7 @@ void inverse_mdct(float *buffer, int n, vorb *f, int blocktype)
if (M1.n == n) M = &M1;
else if (M2.n == n) M = &M2;
else if (M1.n == 0) { mdct_init(&M1, n); M = &M1; }
- else {
+ else {
if (M2.n) __asm int 3;
mdct_init(&M2, n);
M = &M2;
@@ -2782,7 +2787,7 @@ static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype)
d1[0] = u[k4+1];
d0[1] = u[k4+2];
d0[0] = u[k4+3];
-
+
d0 -= 4;
d1 -= 4;
bitrev += 2;
@@ -2863,7 +2868,7 @@ static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype)
float p0,p1,p2,p3;
p3 = e[6]*B[7] - e[7]*B[6];
- p2 = -e[6]*B[6] - e[7]*B[7];
+ p2 = -e[6]*B[6] - e[7]*B[7];
d0[0] = p3;
d1[3] = - p3;
@@ -2871,7 +2876,7 @@ static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype)
d3[3] = p2;
p1 = e[4]*B[5] - e[5]*B[4];
- p0 = -e[4]*B[4] - e[5]*B[5];
+ p0 = -e[4]*B[4] - e[5]*B[5];
d0[1] = p1;
d1[2] = - p1;
@@ -2879,7 +2884,7 @@ static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype)
d3[2] = p0;
p3 = e[2]*B[3] - e[3]*B[2];
- p2 = -e[2]*B[2] - e[3]*B[3];
+ p2 = -e[2]*B[2] - e[3]*B[3];
d0[2] = p3;
d1[1] = - p3;
@@ -2887,7 +2892,7 @@ static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype)
d3[1] = p2;
p1 = e[0]*B[1] - e[1]*B[0];
- p0 = -e[0]*B[0] - e[1]*B[1];
+ p0 = -e[0]*B[0] - e[1]*B[1];
d0[3] = p1;
d1[0] = - p1;
@@ -3391,7 +3396,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start,
if (f->last_seg_which == f->end_seg_with_known_loc) {
// if we have a valid current loc, and this is final:
if (f->current_loc_valid && (f->page_flag & PAGEFLAG_last_page)) {
- uint32 current_end = f->known_loc_for_packet - (n-right_end);
+ uint32 current_end = f->known_loc_for_packet;
// then let's infer the size of the (probably) short final frame
if (current_end < f->current_loc + (right_end-left_start)) {
if (current_end < f->current_loc) {
@@ -3400,7 +3405,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start,
} else {
*len = current_end - f->current_loc;
}
- *len += left_start;
+ *len += left_start; // this doesn't seem right, but has no ill effect on my test files
if (*len > right_end) *len = right_end; // this should never happen
f->current_loc += *len;
return TRUE;
@@ -3521,7 +3526,7 @@ static int is_whole_packet_present(stb_vorbis *f, int end_page)
first = FALSE;
}
for (; s == -1;) {
- uint8 *q;
+ uint8 *q;
int n;
// check that we have the page header ready
@@ -3874,7 +3879,7 @@ static int start_decoder(vorb *f)
} else {
stbv__floor_ordering p[31*8+2];
Floor1 *g = &f->floor_config[i].floor1;
- int max_class = -1;
+ int max_class = -1;
g->partitions = get_bits(f, 5);
for (j=0; j < g->partitions; ++j) {
g->partition_class_list[j] = get_bits(f, 4);
@@ -3984,7 +3989,7 @@ static int start_decoder(vorb *f)
if (f->mapping == NULL) return error(f, VORBIS_outofmem);
memset(f->mapping, 0, f->mapping_count * sizeof(*f->mapping));
for (i=0; i < f->mapping_count; ++i) {
- Mapping *m = f->mapping + i;
+ Mapping *m = f->mapping + i;
int mapping_type = get_bits(f,16);
if (mapping_type != 0) return error(f, VORBIS_invalid_setup);
m->chan = (MappingChannel *) setup_malloc(f, f->channels * sizeof(*m->chan));
@@ -4050,6 +4055,7 @@ static int start_decoder(vorb *f)
f->previous_window[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2);
f->finalY[i] = (int16 *) setup_malloc(f, sizeof(int16) * longest_floorlist);
if (f->channel_buffers[i] == NULL || f->previous_window[i] == NULL || f->finalY[i] == NULL) return error(f, VORBIS_outofmem);
+ memset(f->channel_buffers[i], 0, sizeof(float) * f->blocksize_1);
#ifdef STB_VORBIS_NO_DEFER_FLOOR
f->floor_buffers[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2);
if (f->floor_buffers[i] == NULL) return error(f, VORBIS_outofmem);
@@ -4077,7 +4083,10 @@ static int start_decoder(vorb *f)
int i,max_part_read=0;
for (i=0; i < f->residue_count; ++i) {
Residue *r = f->residue_config + i;
- int n_read = r->end - r->begin;
+ unsigned int actual_size = f->blocksize_1 / 2;
+ unsigned int limit_r_begin = r->begin < actual_size ? r->begin : actual_size;
+ unsigned int limit_r_end = r->end < actual_size ? r->end : actual_size;
+ int n_read = limit_r_end - limit_r_begin;
int part_read = n_read / r->part_size;
if (part_read > max_part_read)
max_part_read = part_read;
@@ -4088,6 +4097,8 @@ static int start_decoder(vorb *f)
classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(int *));
#endif
+ // maximum reasonable partition size is f->blocksize_1
+
f->temp_memory_required = classify_mem;
if (imdct_mem > f->temp_memory_required)
f->temp_memory_required = imdct_mem;
@@ -4963,7 +4974,7 @@ stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, con
stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, const stb_vorbis_alloc *alloc)
{
FILE *f = fopen(filename, "rb");
- if (f)
+ if (f)
return stb_vorbis_open_file(f, TRUE, error, alloc);
if (error) *error = VORBIS_file_open_failure;
return NULL;
@@ -5026,7 +5037,7 @@ static int8 channel_position[7][6] =
#define MAGIC(SHIFT) (1.5f * (1 << (23-SHIFT)) + 0.5f/(1 << SHIFT))
#define ADDEND(SHIFT) (((150-SHIFT) << 23) + (1 << 22))
#define FAST_SCALED_FLOAT_TO_INT(temp,x,s) (temp.f = (x) + MAGIC(s), temp.i - ADDEND(s))
- #define check_endianness()
+ #define check_endianness()
#else
#define FAST_SCALED_FLOAT_TO_INT(temp,x,s) ((int) ((x) * (1 << (s))))
#define check_endianness()
@@ -5351,20 +5362,22 @@ int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, in
#endif // STB_VORBIS_NO_PULLDATA_API
/* Version history
- 1.10 - 2017/03/03 - more robust seeking; fix negative ilog(); clear error in open_memory
- 1.09 - 2016/04/04 - back out 'avoid discarding last frame' fix from previous version
- 1.08 - 2016/04/02 - fixed multiple warnings; fix setup memory leaks;
+ 1.12 - 2017-11-21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files
+ 1.11 - 2017-07-23 - fix MinGW compilation
+ 1.10 - 2017-03-03 - more robust seeking; fix negative ilog(); clear error in open_memory
+ 1.09 - 2016-04-04 - back out 'avoid discarding last frame' fix from previous version
+ 1.08 - 2016-04-02 - fixed multiple warnings; fix setup memory leaks;
avoid discarding last frame of audio data
- 1.07 - 2015/01/16 - fixed some warnings, fix mingw, const-correct API
- some more crash fixes when out of memory or with corrupt files
- 1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson)
+ 1.07 - 2015-01-16 - fixed some warnings, fix mingw, const-correct API
+ some more crash fixes when out of memory or with corrupt files
+ 1.06 - 2015-08-31 - full, correct support for seeking API (Dougall Johnson)
some crash fixes when out of memory or with corrupt files
- 1.05 - 2015/04/19 - don't define __forceinline if it's redundant
- 1.04 - 2014/08/27 - fix missing const-correct case in API
- 1.03 - 2014/08/07 - Warning fixes
- 1.02 - 2014/07/09 - Declare qsort compare function _cdecl on windows
- 1.01 - 2014/06/18 - fix stb_vorbis_get_samples_float
- 1.0 - 2014/05/26 - fix memory leaks; fix warnings; fix bugs in multichannel
+ 1.05 - 2015-04-19 - don't define __forceinline if it's redundant
+ 1.04 - 2014-08-27 - fix missing const-correct case in API
+ 1.03 - 2014-08-07 - Warning fixes
+ 1.02 - 2014-07-09 - Declare qsort compare function _cdecl on windows
+ 1.01 - 2014-06-18 - fix stb_vorbis_get_samples_float
+ 1.0 - 2014-05-26 - fix memory leaks; fix warnings; fix bugs in multichannel
(API change) report sample rate for decode-full-file funcs
0.99996 - bracket #include <malloc.h> for macintosh compilation by Laurent Gomila
0.99995 - use union instead of pointer-cast for fast-float-to-int to avoid alias-optimization problem
@@ -5412,38 +5425,38 @@ This software is available under 2 licenses -- choose whichever you prefer.
------------------------------------------------------------------------------
ALTERNATIVE A - MIT License
Copyright (c) 2017 Sean Barrett
-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
+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
+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
+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.
------------------------------------------------------------------------------
ALTERNATIVE B - Public Domain (www.unlicense.org)
This is free and unencumbered software released into the public domain.
-Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
-software, either in source code form or as a compiled binary, for any purpose,
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
+software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
-In jurisdictions that recognize copyright laws, the author or authors of this
-software dedicate any and all copyright interest in the software to the public
-domain. We make this dedication for the benefit of the public at large and to
-the detriment of our heirs and successors. We intend this dedication to be an
-overt act of relinquishment in perpetuity of all present and future rights to
+In jurisdictions that recognize copyright laws, the author or authors of this
+software dedicate any and all copyright interest in the software to the public
+domain. We make this dedication for the benefit of the public at large and to
+the detriment of our heirs and successors. We intend this dedication to be an
+overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law.
-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 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
+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 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.
------------------------------------------------------------------------------
*/
diff --git a/thirdparty/zstd/common/bitstream.h b/thirdparty/zstd/common/bitstream.h
index fcf3843079..f7f389fe0f 100644
--- a/thirdparty/zstd/common/bitstream.h
+++ b/thirdparty/zstd/common/bitstream.h
@@ -426,7 +426,7 @@ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)
* Refill `bitD` from buffer previously set in BIT_initDStream() .
* This function is safe, it guarantees it will not read beyond src buffer.
* @return : status of `BIT_DStream_t` internal register.
- * when status == BIT_DStream_unfinished, internal register is filled with at least 25 or 57 bits */
+ * when status == BIT_DStream_unfinished, internal register is filled with at least 25 or 57 bits */
MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
{
if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* overflow detected, like end of stream */
diff --git a/thirdparty/zstd/common/compiler.h b/thirdparty/zstd/common/compiler.h
index 3a7553c380..e90a3bcde3 100644
--- a/thirdparty/zstd/common/compiler.h
+++ b/thirdparty/zstd/common/compiler.h
@@ -63,6 +63,31 @@
# endif
#endif
+/* target attribute */
+#ifndef __has_attribute
+ #define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
+#endif
+#if defined(__GNUC__)
+# define TARGET_ATTRIBUTE(target) __attribute__((__target__(target)))
+#else
+# define TARGET_ATTRIBUTE(target)
+#endif
+
+/* Enable runtime BMI2 dispatch based on the CPU.
+ * Enabled for clang & gcc >=4.8 on x86 when BMI2 isn't enabled by default.
+ */
+#ifndef DYNAMIC_BMI2
+ #if (defined(__clang__) && __has_attribute(__target__)) \
+ || (defined(__GNUC__) \
+ && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) \
+ && (defined(__x86_64__) || defined(_M_X86)) \
+ && !defined(__BMI2__)
+ # define DYNAMIC_BMI2 1
+ #else
+ # define DYNAMIC_BMI2 0
+ #endif
+#endif
+
/* prefetch */
#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) /* _mm_prefetch() is not defined outside of x86/x64 */
# include <mmintrin.h> /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */
diff --git a/thirdparty/zstd/common/cpu.h b/thirdparty/zstd/common/cpu.h
new file mode 100644
index 0000000000..4eb48e39e1
--- /dev/null
+++ b/thirdparty/zstd/common/cpu.h
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2018-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+#ifndef ZSTD_COMMON_CPU_H
+#define ZSTD_COMMON_CPU_H
+
+/**
+ * Implementation taken from folly/CpuId.h
+ * https://github.com/facebook/folly/blob/master/folly/CpuId.h
+ */
+
+#include <string.h>
+
+#include "mem.h"
+
+#ifdef _MSC_VER
+#include <intrin.h>
+#endif
+
+typedef struct {
+ U32 f1c;
+ U32 f1d;
+ U32 f7b;
+ U32 f7c;
+} ZSTD_cpuid_t;
+
+MEM_STATIC ZSTD_cpuid_t ZSTD_cpuid(void) {
+ U32 f1c = 0;
+ U32 f1d = 0;
+ U32 f7b = 0;
+ U32 f7c = 0;
+#ifdef _MSC_VER
+ int reg[4];
+ __cpuid((int*)reg, 0);
+ {
+ int const n = reg[0];
+ if (n >= 1) {
+ __cpuid((int*)reg, 1);
+ f1c = (U32)reg[2];
+ f1d = (U32)reg[3];
+ }
+ if (n >= 7) {
+ __cpuidex((int*)reg, 7, 0);
+ f7b = (U32)reg[1];
+ f7c = (U32)reg[2];
+ }
+ }
+#elif defined(__i386__) && defined(__PIC__) && !defined(__clang__) && defined(__GNUC__)
+ /* The following block like the normal cpuid branch below, but gcc
+ * reserves ebx for use of its pic register so we must specially
+ * handle the save and restore to avoid clobbering the register
+ */
+ U32 n;
+ __asm__(
+ "pushl %%ebx\n\t"
+ "cpuid\n\t"
+ "popl %%ebx\n\t"
+ : "=a"(n)
+ : "a"(0)
+ : "ecx", "edx");
+ if (n >= 1) {
+ U32 f1a;
+ __asm__(
+ "pushl %%ebx\n\t"
+ "cpuid\n\t"
+ "popl %%ebx\n\t"
+ : "=a"(f1a), "=c"(f1c), "=d"(f1d)
+ : "a"(1)
+ :);
+ }
+ if (n >= 7) {
+ __asm__(
+ "pushl %%ebx\n\t"
+ "cpuid\n\t"
+ "movl %%ebx, %%eax\n\r"
+ "popl %%ebx"
+ : "=a"(f7b), "=c"(f7c)
+ : "a"(7), "c"(0)
+ : "edx");
+ }
+#elif defined(__x86_64__) || defined(_M_X64) || defined(__i386__)
+ U32 n;
+ __asm__("cpuid" : "=a"(n) : "a"(0) : "ebx", "ecx", "edx");
+ if (n >= 1) {
+ U32 f1a;
+ __asm__("cpuid" : "=a"(f1a), "=c"(f1c), "=d"(f1d) : "a"(1) : "ebx");
+ }
+ if (n >= 7) {
+ U32 f7a;
+ __asm__("cpuid"
+ : "=a"(f7a), "=b"(f7b), "=c"(f7c)
+ : "a"(7), "c"(0)
+ : "edx");
+ }
+#endif
+ {
+ ZSTD_cpuid_t cpuid;
+ cpuid.f1c = f1c;
+ cpuid.f1d = f1d;
+ cpuid.f7b = f7b;
+ cpuid.f7c = f7c;
+ return cpuid;
+ }
+}
+
+#define X(name, r, bit) \
+ MEM_STATIC int ZSTD_cpuid_##name(ZSTD_cpuid_t const cpuid) { \
+ return ((cpuid.r) & (1U << bit)) != 0; \
+ }
+
+/* cpuid(1): Processor Info and Feature Bits. */
+#define C(name, bit) X(name, f1c, bit)
+ C(sse3, 0)
+ C(pclmuldq, 1)
+ C(dtes64, 2)
+ C(monitor, 3)
+ C(dscpl, 4)
+ C(vmx, 5)
+ C(smx, 6)
+ C(eist, 7)
+ C(tm2, 8)
+ C(ssse3, 9)
+ C(cnxtid, 10)
+ C(fma, 12)
+ C(cx16, 13)
+ C(xtpr, 14)
+ C(pdcm, 15)
+ C(pcid, 17)
+ C(dca, 18)
+ C(sse41, 19)
+ C(sse42, 20)
+ C(x2apic, 21)
+ C(movbe, 22)
+ C(popcnt, 23)
+ C(tscdeadline, 24)
+ C(aes, 25)
+ C(xsave, 26)
+ C(osxsave, 27)
+ C(avx, 28)
+ C(f16c, 29)
+ C(rdrand, 30)
+#undef C
+#define D(name, bit) X(name, f1d, bit)
+ D(fpu, 0)
+ D(vme, 1)
+ D(de, 2)
+ D(pse, 3)
+ D(tsc, 4)
+ D(msr, 5)
+ D(pae, 6)
+ D(mce, 7)
+ D(cx8, 8)
+ D(apic, 9)
+ D(sep, 11)
+ D(mtrr, 12)
+ D(pge, 13)
+ D(mca, 14)
+ D(cmov, 15)
+ D(pat, 16)
+ D(pse36, 17)
+ D(psn, 18)
+ D(clfsh, 19)
+ D(ds, 21)
+ D(acpi, 22)
+ D(mmx, 23)
+ D(fxsr, 24)
+ D(sse, 25)
+ D(sse2, 26)
+ D(ss, 27)
+ D(htt, 28)
+ D(tm, 29)
+ D(pbe, 31)
+#undef D
+
+/* cpuid(7): Extended Features. */
+#define B(name, bit) X(name, f7b, bit)
+ B(bmi1, 3)
+ B(hle, 4)
+ B(avx2, 5)
+ B(smep, 7)
+ B(bmi2, 8)
+ B(erms, 9)
+ B(invpcid, 10)
+ B(rtm, 11)
+ B(mpx, 14)
+ B(avx512f, 16)
+ B(avx512dq, 17)
+ B(rdseed, 18)
+ B(adx, 19)
+ B(smap, 20)
+ B(avx512ifma, 21)
+ B(pcommit, 22)
+ B(clflushopt, 23)
+ B(clwb, 24)
+ B(avx512pf, 26)
+ B(avx512er, 27)
+ B(avx512cd, 28)
+ B(sha, 29)
+ B(avx512bw, 30)
+ B(avx512vl, 31)
+#undef B
+#define C(name, bit) X(name, f7c, bit)
+ C(prefetchwt1, 0)
+ C(avx512vbmi, 1)
+#undef C
+
+#undef X
+
+#endif /* ZSTD_COMMON_CPU_H */
diff --git a/thirdparty/zstd/common/error_private.c b/thirdparty/zstd/common/error_private.c
index 11f7cdab1c..d004ee636c 100644
--- a/thirdparty/zstd/common/error_private.c
+++ b/thirdparty/zstd/common/error_private.c
@@ -29,6 +29,7 @@ const char* ERR_getErrorString(ERR_enum code)
case PREFIX(parameter_outOfBound): return "Parameter is out of bound";
case PREFIX(init_missing): return "Context should be init first";
case PREFIX(memory_allocation): return "Allocation error : not enough memory";
+ case PREFIX(workSpace_tooSmall): return "workSpace buffer is not large enough";
case PREFIX(stage_wrong): return "Operation not authorized at current processing stage";
case PREFIX(tableLog_tooLarge): return "tableLog requires too much memory : unsupported";
case PREFIX(maxSymbolValue_tooLarge): return "Unsupported max Symbol Value : too large";
diff --git a/thirdparty/zstd/common/fse.h b/thirdparty/zstd/common/fse.h
index afd7801963..6a1d272be5 100644
--- a/thirdparty/zstd/common/fse.h
+++ b/thirdparty/zstd/common/fse.h
@@ -345,7 +345,7 @@ size_t FSE_countFast(unsigned* count, unsigned* maxSymbolValuePtr, const void* s
*/
size_t FSE_countFast_wksp(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned* workSpace);
-/*! FSE_count_simple
+/*! FSE_count_simple() :
* Same as FSE_countFast(), but does not use any additional memory (not even on stack).
* This function is unsafe, and will segfault if any value within `src` is `> *maxSymbolValuePtr` (presuming it's also the size of `count`).
*/
diff --git a/thirdparty/zstd/common/fse_decompress.c b/thirdparty/zstd/common/fse_decompress.c
index 8e3f0035f6..4c66c3b774 100644
--- a/thirdparty/zstd/common/fse_decompress.c
+++ b/thirdparty/zstd/common/fse_decompress.c
@@ -139,8 +139,8 @@ size_t FSE_buildDTable(FSE_DTable* dt, const short* normalizedCounter, unsigned
{ U32 u;
for (u=0; u<tableSize; u++) {
FSE_FUNCTION_TYPE const symbol = (FSE_FUNCTION_TYPE)(tableDecode[u].symbol);
- U16 nextState = symbolNext[symbol]++;
- tableDecode[u].nbBits = (BYTE) (tableLog - BIT_highbit32 ((U32)nextState) );
+ U32 const nextState = symbolNext[symbol]++;
+ tableDecode[u].nbBits = (BYTE) (tableLog - BIT_highbit32(nextState) );
tableDecode[u].newState = (U16) ( (nextState << tableDecode[u].nbBits) - tableSize);
} }
diff --git a/thirdparty/zstd/common/huf.h b/thirdparty/zstd/common/huf.h
index 522bf9b6c0..b4645b4e51 100644
--- a/thirdparty/zstd/common/huf.h
+++ b/thirdparty/zstd/common/huf.h
@@ -58,32 +58,32 @@ extern "C" {
#endif
-/* *** simple functions *** */
-/**
-HUF_compress() :
- Compress content from buffer 'src', of size 'srcSize', into buffer 'dst'.
- 'dst' buffer must be already allocated.
- Compression runs faster if `dstCapacity` >= HUF_compressBound(srcSize).
- `srcSize` must be <= `HUF_BLOCKSIZE_MAX` == 128 KB.
- @return : size of compressed data (<= `dstCapacity`).
- Special values : if return == 0, srcData is not compressible => Nothing is stored within dst !!!
- if return == 1, srcData is a single repeated byte symbol (RLE compression).
- if HUF_isError(return), compression failed (more details using HUF_getErrorName())
-*/
+/* ========================== */
+/* *** simple functions *** */
+/* ========================== */
+
+/** HUF_compress() :
+ * Compress content from buffer 'src', of size 'srcSize', into buffer 'dst'.
+ * 'dst' buffer must be already allocated.
+ * Compression runs faster if `dstCapacity` >= HUF_compressBound(srcSize).
+ * `srcSize` must be <= `HUF_BLOCKSIZE_MAX` == 128 KB.
+ * @return : size of compressed data (<= `dstCapacity`).
+ * Special values : if return == 0, srcData is not compressible => Nothing is stored within dst !!!
+ * if HUF_isError(return), compression failed (more details using HUF_getErrorName())
+ */
HUF_PUBLIC_API size_t HUF_compress(void* dst, size_t dstCapacity,
const void* src, size_t srcSize);
-/**
-HUF_decompress() :
- Decompress HUF data from buffer 'cSrc', of size 'cSrcSize',
- into already allocated buffer 'dst', of minimum size 'dstSize'.
- `originalSize` : **must** be the ***exact*** size of original (uncompressed) data.
- Note : in contrast with FSE, HUF_decompress can regenerate
- RLE (cSrcSize==1) and uncompressed (cSrcSize==dstSize) data,
- because it knows size to regenerate.
- @return : size of regenerated data (== originalSize),
- or an error code, which can be tested using HUF_isError()
-*/
+/** HUF_decompress() :
+ * Decompress HUF data from buffer 'cSrc', of size 'cSrcSize',
+ * into already allocated buffer 'dst', of minimum size 'dstSize'.
+ * `originalSize` : **must** be the ***exact*** size of original (uncompressed) data.
+ * Note : in contrast with FSE, HUF_decompress can regenerate
+ * RLE (cSrcSize==1) and uncompressed (cSrcSize==dstSize) data,
+ * because it knows size to regenerate (originalSize).
+ * @return : size of regenerated data (== originalSize),
+ * or an error code, which can be tested using HUF_isError()
+ */
HUF_PUBLIC_API size_t HUF_decompress(void* dst, size_t originalSize,
const void* cSrc, size_t cSrcSize);
@@ -100,39 +100,32 @@ HUF_PUBLIC_API const char* HUF_getErrorName(size_t code); /**< provides error c
/* *** Advanced function *** */
/** HUF_compress2() :
- * Same as HUF_compress(), but offers direct control over `maxSymbolValue` and `tableLog`.
- * `tableLog` must be `<= HUF_TABLELOG_MAX` . */
-HUF_PUBLIC_API size_t HUF_compress2 (void* dst, size_t dstCapacity, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog);
+ * Same as HUF_compress(), but offers control over `maxSymbolValue` and `tableLog`.
+ * `maxSymbolValue` must be <= HUF_SYMBOLVALUE_MAX .
+ * `tableLog` must be `<= HUF_TABLELOG_MAX` . */
+HUF_PUBLIC_API size_t HUF_compress2 (void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ unsigned maxSymbolValue, unsigned tableLog);
/** HUF_compress4X_wksp() :
* Same as HUF_compress2(), but uses externally allocated `workSpace`.
- * `workspace` must have minimum alignment of 4, and be at least as large as following macro */
+ * `workspace` must have minimum alignment of 4, and be at least as large as HUF_WORKSPACE_SIZE */
#define HUF_WORKSPACE_SIZE (6 << 10)
#define HUF_WORKSPACE_SIZE_U32 (HUF_WORKSPACE_SIZE / sizeof(U32))
-HUF_PUBLIC_API size_t HUF_compress4X_wksp (void* dst, size_t dstCapacity, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);
-
-/**
- * The minimum workspace size for the `workSpace` used in
- * HUF_readDTableX2_wksp() and HUF_readDTableX4_wksp().
- *
- * The space used depends on HUF_TABLELOG_MAX, ranging from ~1500 bytes when
- * HUF_TABLE_LOG_MAX=12 to ~1850 bytes when HUF_TABLE_LOG_MAX=15.
- * Buffer overflow errors may potentially occur if code modifications result in
- * a required workspace size greater than that specified in the following
- * macro.
- */
-#define HUF_DECOMPRESS_WORKSPACE_SIZE (2 << 10)
-#define HUF_DECOMPRESS_WORKSPACE_SIZE_U32 (HUF_DECOMPRESS_WORKSPACE_SIZE / sizeof(U32))
+HUF_PUBLIC_API size_t HUF_compress4X_wksp (void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ unsigned maxSymbolValue, unsigned tableLog,
+ void* workSpace, size_t wkspSize);
#endif /* HUF_H_298734234 */
/* ******************************************************************
* WARNING !!
* The following section contains advanced and experimental definitions
- * which shall never be used in the context of dll
+ * which shall never be used in the context of a dynamic library,
* because they are not guaranteed to remain stable in the future.
* Only consider them in association with static linking.
- *******************************************************************/
+ * *****************************************************************/
#if defined(HUF_STATIC_LINKING_ONLY) && !defined(HUF_H_HUF_STATIC_LINKING_ONLY)
#define HUF_H_HUF_STATIC_LINKING_ONLY
@@ -141,11 +134,11 @@ HUF_PUBLIC_API size_t HUF_compress4X_wksp (void* dst, size_t dstCapacity, const
/* *** Constants *** */
-#define HUF_TABLELOG_MAX 12 /* max configured tableLog (for static allocation); can be modified up to HUF_ABSOLUTEMAX_TABLELOG */
-#define HUF_TABLELOG_DEFAULT 11 /* tableLog by default, when not specified */
+#define HUF_TABLELOG_MAX 12 /* max runtime value of tableLog (due to static allocation); can be modified up to HUF_ABSOLUTEMAX_TABLELOG */
+#define HUF_TABLELOG_DEFAULT 11 /* default tableLog value when none specified */
#define HUF_SYMBOLVALUE_MAX 255
-#define HUF_TABLELOG_ABSOLUTEMAX 15 /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */
+#define HUF_TABLELOG_ABSOLUTEMAX 15 /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */
#if (HUF_TABLELOG_MAX > HUF_TABLELOG_ABSOLUTEMAX)
# error "HUF_TABLELOG_MAX is too large !"
#endif
@@ -192,24 +185,23 @@ size_t HUF_decompress4X4_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
/* ****************************************
-* HUF detailed API
-******************************************/
-/*!
-HUF_compress() does the following:
-1. count symbol occurrence from source[] into table count[] using FSE_count()
-2. (optional) refine tableLog using HUF_optimalTableLog()
-3. build Huffman table from count using HUF_buildCTable()
-4. save Huffman table to memory buffer using HUF_writeCTable()
-5. encode the data stream using HUF_compress4X_usingCTable()
-
-The following API allows targeting specific sub-functions for advanced tasks.
-For example, it's possible to compress several blocks using the same 'CTable',
-or to save and regenerate 'CTable' using external methods.
-*/
-/* FSE_count() : find it within "fse.h" */
+ * HUF detailed API
+ * ****************************************/
+
+/*! HUF_compress() does the following:
+ * 1. count symbol occurrence from source[] into table count[] using FSE_count() (exposed within "fse.h")
+ * 2. (optional) refine tableLog using HUF_optimalTableLog()
+ * 3. build Huffman table from count using HUF_buildCTable()
+ * 4. save Huffman table to memory buffer using HUF_writeCTable()
+ * 5. encode the data stream using HUF_compress4X_usingCTable()
+ *
+ * The following API allows targeting specific sub-functions for advanced tasks.
+ * For example, it's possible to compress several blocks using the same 'CTable',
+ * or to save and regenerate 'CTable' using external methods.
+ */
unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue);
typedef struct HUF_CElt_s HUF_CElt; /* incomplete type */
-size_t HUF_buildCTable (HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits);
+size_t HUF_buildCTable (HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits); /* @return : maxNbBits; CTable and count can overlap. In which case, CTable will overwrite count content */
size_t HUF_writeCTable (void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog);
size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable);
@@ -219,46 +211,65 @@ typedef enum {
HUF_repeat_valid /**< Can use the previous table and it is asumed to be valid */
} HUF_repeat;
/** HUF_compress4X_repeat() :
-* Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
-* If it uses hufTable it does not modify hufTable or repeat.
-* If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used.
-* If preferRepeat then the old table will always be used if valid. */
-size_t HUF_compress4X_repeat(void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize, HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat); /**< `workSpace` must be a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */
+ * Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
+ * If it uses hufTable it does not modify hufTable or repeat.
+ * If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used.
+ * If preferRepeat then the old table will always be used if valid. */
+size_t HUF_compress4X_repeat(void* dst, size_t dstSize,
+ const void* src, size_t srcSize,
+ unsigned maxSymbolValue, unsigned tableLog,
+ void* workSpace, size_t wkspSize, /**< `workSpace` must be aligned on 4-bytes boundaries, `wkspSize` must be >= HUF_WORKSPACE_SIZE */
+ HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2);
/** HUF_buildCTable_wksp() :
* Same as HUF_buildCTable(), but using externally allocated scratch buffer.
- * `workSpace` must be aligned on 4-bytes boundaries, and be at least as large as a table of 1024 unsigned.
+ * `workSpace` must be aligned on 4-bytes boundaries, and its size must be >= HUF_CTABLE_WORKSPACE_SIZE.
*/
+#define HUF_CTABLE_WORKSPACE_SIZE_U32 (2*HUF_SYMBOLVALUE_MAX +1 +1)
+#define HUF_CTABLE_WORKSPACE_SIZE (HUF_CTABLE_WORKSPACE_SIZE_U32 * sizeof(unsigned))
size_t HUF_buildCTable_wksp (HUF_CElt* tree, const U32* count, U32 maxSymbolValue, U32 maxNbBits, void* workSpace, size_t wkspSize);
/*! HUF_readStats() :
- Read compact Huffman tree, saved by HUF_writeCTable().
- `huffWeight` is destination buffer.
- @return : size read from `src` , or an error Code .
- Note : Needed by HUF_readCTable() and HUF_readDTableXn() . */
-size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
- U32* nbSymbolsPtr, U32* tableLogPtr,
+ * Read compact Huffman tree, saved by HUF_writeCTable().
+ * `huffWeight` is destination buffer.
+ * @return : size read from `src` , or an error Code .
+ * Note : Needed by HUF_readCTable() and HUF_readDTableXn() . */
+size_t HUF_readStats(BYTE* huffWeight, size_t hwSize,
+ U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr,
const void* src, size_t srcSize);
/** HUF_readCTable() :
-* Loading a CTable saved with HUF_writeCTable() */
+ * Loading a CTable saved with HUF_writeCTable() */
size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize);
/*
-HUF_decompress() does the following:
-1. select the decompression algorithm (X2, X4) based on pre-computed heuristics
-2. build Huffman table from save, using HUF_readDTableXn()
-3. decode 1 or 4 segments in parallel using HUF_decompressSXn_usingDTable
-*/
+ * HUF_decompress() does the following:
+ * 1. select the decompression algorithm (X2, X4) based on pre-computed heuristics
+ * 2. build Huffman table from save, using HUF_readDTableX?()
+ * 3. decode 1 or 4 segments in parallel using HUF_decompress?X?_usingDTable()
+ */
/** HUF_selectDecoder() :
-* Tells which decoder is likely to decode faster,
-* based on a set of pre-determined metrics.
-* @return : 0==HUF_decompress4X2, 1==HUF_decompress4X4 .
-* Assumption : 0 < cSrcSize < dstSize <= 128 KB */
+ * Tells which decoder is likely to decode faster,
+ * based on a set of pre-computed metrics.
+ * @return : 0==HUF_decompress4X2, 1==HUF_decompress4X4 .
+ * Assumption : 0 < dstSize <= 128 KB */
U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize);
+/**
+ * The minimum workspace size for the `workSpace` used in
+ * HUF_readDTableX2_wksp() and HUF_readDTableX4_wksp().
+ *
+ * The space used depends on HUF_TABLELOG_MAX, ranging from ~1500 bytes when
+ * HUF_TABLE_LOG_MAX=12 to ~1850 bytes when HUF_TABLE_LOG_MAX=15.
+ * Buffer overflow errors may potentially occur if code modifications result in
+ * a required workspace size greater than that specified in the following
+ * macro.
+ */
+#define HUF_DECOMPRESS_WORKSPACE_SIZE (2 << 10)
+#define HUF_DECOMPRESS_WORKSPACE_SIZE_U32 (HUF_DECOMPRESS_WORKSPACE_SIZE / sizeof(U32))
+
size_t HUF_readDTableX2 (HUF_DTable* DTable, const void* src, size_t srcSize);
size_t HUF_readDTableX2_wksp (HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize);
size_t HUF_readDTableX4 (HUF_DTable* DTable, const void* src, size_t srcSize);
@@ -269,17 +280,23 @@ size_t HUF_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* c
size_t HUF_decompress4X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
+/* ====================== */
/* single stream variants */
+/* ====================== */
size_t HUF_compress1X (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog);
size_t HUF_compress1X_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); /**< `workSpace` must be a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */
size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable);
/** HUF_compress1X_repeat() :
-* Same as HUF_compress1X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
-* If it uses hufTable it does not modify hufTable or repeat.
-* If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used.
-* If preferRepeat then the old table will always be used if valid. */
-size_t HUF_compress1X_repeat(void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize, HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat); /**< `workSpace` must be a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */
+ * Same as HUF_compress1X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
+ * If it uses hufTable it does not modify hufTable or repeat.
+ * If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used.
+ * If preferRepeat then the old table will always be used if valid. */
+size_t HUF_compress1X_repeat(void* dst, size_t dstSize,
+ const void* src, size_t srcSize,
+ unsigned maxSymbolValue, unsigned tableLog,
+ void* workSpace, size_t wkspSize, /**< `workSpace` must be aligned on 4-bytes boundaries, `wkspSize` must be >= HUF_WORKSPACE_SIZE */
+ HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2);
size_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* single-symbol decoder */
size_t HUF_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* double-symbol decoder */
@@ -295,6 +312,14 @@ size_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize, const void* cS
size_t HUF_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
size_t HUF_decompress1X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
+/* BMI2 variants.
+ * If the CPU has BMI2 support, pass bmi2=1, otherwise pass bmi2=0.
+ */
+size_t HUF_decompress1X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2);
+size_t HUF_decompress1X2_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2);
+size_t HUF_decompress4X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2);
+size_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2);
+
#endif /* HUF_STATIC_LINKING_ONLY */
#if defined (__cplusplus)
diff --git a/thirdparty/zstd/common/pool.c b/thirdparty/zstd/common/pool.c
index 98b109e72a..773488b072 100644
--- a/thirdparty/zstd/common/pool.c
+++ b/thirdparty/zstd/common/pool.c
@@ -12,6 +12,7 @@
/* ====== Dependencies ======= */
#include <stddef.h> /* size_t */
#include "pool.h"
+#include "zstd_internal.h" /* ZSTD_malloc, ZSTD_free */
/* ====== Compiler specifics ====== */
#if defined(_MSC_VER)
@@ -193,32 +194,54 @@ static int isQueueFull(POOL_ctx const* ctx) {
}
}
-void POOL_add(void* ctxVoid, POOL_function function, void *opaque) {
- POOL_ctx* const ctx = (POOL_ctx*)ctxVoid;
- if (!ctx) { return; }
+static void POOL_add_internal(POOL_ctx* ctx, POOL_function function, void *opaque)
+{
+ POOL_job const job = {function, opaque};
+ assert(ctx != NULL);
+ if (ctx->shutdown) return;
+
+ ctx->queueEmpty = 0;
+ ctx->queue[ctx->queueTail] = job;
+ ctx->queueTail = (ctx->queueTail + 1) % ctx->queueSize;
+ ZSTD_pthread_cond_signal(&ctx->queuePopCond);
+}
+
+void POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque)
+{
+ assert(ctx != NULL);
ZSTD_pthread_mutex_lock(&ctx->queueMutex);
- { POOL_job const job = {function, opaque};
+ /* Wait until there is space in the queue for the new job */
+ while (isQueueFull(ctx) && (!ctx->shutdown)) {
+ ZSTD_pthread_cond_wait(&ctx->queuePushCond, &ctx->queueMutex);
+ }
+ POOL_add_internal(ctx, function, opaque);
+ ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
+}
- /* Wait until there is space in the queue for the new job */
- while (isQueueFull(ctx) && !ctx->shutdown) {
- ZSTD_pthread_cond_wait(&ctx->queuePushCond, &ctx->queueMutex);
- }
- /* The queue is still going => there is space */
- if (!ctx->shutdown) {
- ctx->queueEmpty = 0;
- ctx->queue[ctx->queueTail] = job;
- ctx->queueTail = (ctx->queueTail + 1) % ctx->queueSize;
- }
+
+int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque)
+{
+ assert(ctx != NULL);
+ ZSTD_pthread_mutex_lock(&ctx->queueMutex);
+ if (isQueueFull(ctx)) {
+ ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
+ return 0;
}
+ POOL_add_internal(ctx, function, opaque);
ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
- ZSTD_pthread_cond_signal(&ctx->queuePopCond);
+ return 1;
}
+
#else /* ZSTD_MULTITHREAD not defined */
+
+/* ========================== */
/* No multi-threading support */
+/* ========================== */
-/* We don't need any data, but if it is empty malloc() might return NULL. */
+
+/* We don't need any data, but if it is empty, malloc() might return NULL. */
struct POOL_ctx_s {
int dummy;
};
@@ -240,9 +263,15 @@ void POOL_free(POOL_ctx* ctx) {
(void)ctx;
}
-void POOL_add(void* ctx, POOL_function function, void* opaque) {
+void POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque) {
+ (void)ctx;
+ function(opaque);
+}
+
+int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque) {
(void)ctx;
function(opaque);
+ return 1;
}
size_t POOL_sizeof(POOL_ctx* ctx) {
diff --git a/thirdparty/zstd/common/pool.h b/thirdparty/zstd/common/pool.h
index 08c63715aa..a57e9b4fab 100644
--- a/thirdparty/zstd/common/pool.h
+++ b/thirdparty/zstd/common/pool.h
@@ -17,7 +17,8 @@ extern "C" {
#include <stddef.h> /* size_t */
-#include "zstd_internal.h" /* ZSTD_customMem */
+#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_customMem */
+#include "zstd.h"
typedef struct POOL_ctx_s POOL_ctx;
@@ -27,35 +28,43 @@ typedef struct POOL_ctx_s POOL_ctx;
* The maximum number of queued jobs before blocking is `queueSize`.
* @return : POOL_ctx pointer on success, else NULL.
*/
-POOL_ctx *POOL_create(size_t numThreads, size_t queueSize);
+POOL_ctx* POOL_create(size_t numThreads, size_t queueSize);
-POOL_ctx *POOL_create_advanced(size_t numThreads, size_t queueSize, ZSTD_customMem customMem);
+POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize, ZSTD_customMem customMem);
/*! POOL_free() :
Free a thread pool returned by POOL_create().
*/
-void POOL_free(POOL_ctx *ctx);
+void POOL_free(POOL_ctx* ctx);
/*! POOL_sizeof() :
return memory usage of pool returned by POOL_create().
*/
-size_t POOL_sizeof(POOL_ctx *ctx);
+size_t POOL_sizeof(POOL_ctx* ctx);
/*! POOL_function :
The function type that can be added to a thread pool.
*/
-typedef void (*POOL_function)(void *);
+typedef void (*POOL_function)(void*);
/*! POOL_add_function :
The function type for a generic thread pool add function.
*/
-typedef void (*POOL_add_function)(void *, POOL_function, void *);
+typedef void (*POOL_add_function)(void*, POOL_function, void*);
/*! POOL_add() :
- Add the job `function(opaque)` to the thread pool.
+ Add the job `function(opaque)` to the thread pool. `ctx` must be valid.
Possibly blocks until there is room in the queue.
Note : The function may be executed asynchronously, so `opaque` must live until the function has been completed.
*/
-void POOL_add(void *ctx, POOL_function function, void *opaque);
+void POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque);
+
+
+/*! POOL_tryAdd() :
+ Add the job `function(opaque)` to the thread pool if a worker is available.
+ return immediately otherwise.
+ @return : 1 if successful, 0 if not.
+*/
+int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque);
#if defined (__cplusplus)
diff --git a/thirdparty/zstd/common/threading.h b/thirdparty/zstd/common/threading.h
index 197770db27..d806c89d01 100644
--- a/thirdparty/zstd/common/threading.h
+++ b/thirdparty/zstd/common/threading.h
@@ -45,15 +45,15 @@ extern "C" {
/* mutex */
#define ZSTD_pthread_mutex_t CRITICAL_SECTION
-#define ZSTD_pthread_mutex_init(a, b) (InitializeCriticalSection((a)), 0)
+#define ZSTD_pthread_mutex_init(a, b) ((void)(b), InitializeCriticalSection((a)), 0)
#define ZSTD_pthread_mutex_destroy(a) DeleteCriticalSection((a))
#define ZSTD_pthread_mutex_lock(a) EnterCriticalSection((a))
#define ZSTD_pthread_mutex_unlock(a) LeaveCriticalSection((a))
/* condition variable */
#define ZSTD_pthread_cond_t CONDITION_VARIABLE
-#define ZSTD_pthread_cond_init(a, b) (InitializeConditionVariable((a)), 0)
-#define ZSTD_pthread_cond_destroy(a) /* No delete */
+#define ZSTD_pthread_cond_init(a, b) ((void)(b), InitializeConditionVariable((a)), 0)
+#define ZSTD_pthread_cond_destroy(a) ((void)(a))
#define ZSTD_pthread_cond_wait(a, b) SleepConditionVariableCS((a), (b), INFINITE)
#define ZSTD_pthread_cond_signal(a) WakeConditionVariable((a))
#define ZSTD_pthread_cond_broadcast(a) WakeAllConditionVariable((a))
@@ -100,17 +100,17 @@ int ZSTD_pthread_join(ZSTD_pthread_t thread, void** value_ptr);
/* No multithreading support */
typedef int ZSTD_pthread_mutex_t;
-#define ZSTD_pthread_mutex_init(a, b) ((void)a, 0)
-#define ZSTD_pthread_mutex_destroy(a)
-#define ZSTD_pthread_mutex_lock(a)
-#define ZSTD_pthread_mutex_unlock(a)
+#define ZSTD_pthread_mutex_init(a, b) ((void)(a), (void)(b), 0)
+#define ZSTD_pthread_mutex_destroy(a) ((void)(a))
+#define ZSTD_pthread_mutex_lock(a) ((void)(a))
+#define ZSTD_pthread_mutex_unlock(a) ((void)(a))
typedef int ZSTD_pthread_cond_t;
-#define ZSTD_pthread_cond_init(a, b) ((void)a, 0)
-#define ZSTD_pthread_cond_destroy(a)
-#define ZSTD_pthread_cond_wait(a, b)
-#define ZSTD_pthread_cond_signal(a)
-#define ZSTD_pthread_cond_broadcast(a)
+#define ZSTD_pthread_cond_init(a, b) ((void)(a), (void)(b), 0)
+#define ZSTD_pthread_cond_destroy(a) ((void)(a))
+#define ZSTD_pthread_cond_wait(a, b) ((void)(a), (void)(b))
+#define ZSTD_pthread_cond_signal(a) ((void)(a))
+#define ZSTD_pthread_cond_broadcast(a) ((void)(a))
/* do not use ZSTD_pthread_t */
diff --git a/thirdparty/zstd/common/zstd_errors.h b/thirdparty/zstd/common/zstd_errors.h
index 4bcb7769fe..57533f2869 100644
--- a/thirdparty/zstd/common/zstd_errors.h
+++ b/thirdparty/zstd/common/zstd_errors.h
@@ -35,12 +35,20 @@ extern "C" {
# define ZSTDERRORLIB_API ZSTDERRORLIB_VISIBILITY
#endif
-/*-****************************************
- * error codes list
- * note : this API is still considered unstable
- * and shall not be used with a dynamic library.
- * only static linking is allowed
- ******************************************/
+/*-*********************************************
+ * Error codes list
+ *-*********************************************
+ * Error codes _values_ are pinned down since v1.3.1 only.
+ * Therefore, don't rely on values if you may link to any version < v1.3.1.
+ *
+ * Only values < 100 are considered stable.
+ *
+ * note 1 : this API shall be used with static linking only.
+ * dynamic linking is not yet officially supported.
+ * note 2 : Prefer relying on the enum than on its value whenever possible
+ * This is the only supported way to use the error list < v1.3.1
+ * note 3 : ZSTD_isError() is always correct, whatever the library version.
+ **********************************************/
typedef enum {
ZSTD_error_no_error = 0,
ZSTD_error_GENERIC = 1,
@@ -61,9 +69,10 @@ typedef enum {
ZSTD_error_stage_wrong = 60,
ZSTD_error_init_missing = 62,
ZSTD_error_memory_allocation = 64,
+ ZSTD_error_workSpace_tooSmall= 66,
ZSTD_error_dstSize_tooSmall = 70,
ZSTD_error_srcSize_wrong = 72,
- /* following error codes are not stable and may be removed or changed in a future version */
+ /* following error codes are __NOT STABLE__, they can be removed or changed in future versions */
ZSTD_error_frameIndex_tooLarge = 100,
ZSTD_error_seekableIO = 102,
ZSTD_error_maxCode = 120 /* never EVER use this value directly, it can change in future versions! Use ZSTD_isError() instead */
diff --git a/thirdparty/zstd/common/zstd_internal.h b/thirdparty/zstd/common/zstd_internal.h
index 5d2900eb76..65c08a8257 100644
--- a/thirdparty/zstd/common/zstd_internal.h
+++ b/thirdparty/zstd/common/zstd_internal.h
@@ -132,14 +132,15 @@ typedef enum { set_basic, set_rle, set_compressed, set_repeat } symbolEncodingTy
#define Litbits 8
#define MaxLit ((1<<Litbits) - 1)
-#define MaxML 52
-#define MaxLL 35
+#define MaxML 52
+#define MaxLL 35
#define DefaultMaxOff 28
-#define MaxOff 31
+#define MaxOff 31
#define MaxSeq MAX(MaxLL, MaxML) /* Assumption : MaxOff < MaxLL,MaxML */
#define MLFSELog 9
#define LLFSELog 9
#define OffFSELog 8
+#define MaxFSELog MAX(MAX(MLFSELog, LLFSELog), OffFSELog)
static const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -228,8 +229,6 @@ typedef struct {
BYTE* ofCode;
U32 longLengthID; /* 0 == no longLength; 1 == Lit.longLength; 2 == Match.longLength; */
U32 longLengthPos;
- U32 rep[ZSTD_REP_NUM];
- U32 repToConfirm[ZSTD_REP_NUM];
} seqStore_t;
const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx); /* compress & dictBuilder */
diff --git a/thirdparty/zstd/compress/fse_compress.c b/thirdparty/zstd/compress/fse_compress.c
index 549c115d42..cb8f1fa323 100644
--- a/thirdparty/zstd/compress/fse_compress.c
+++ b/thirdparty/zstd/compress/fse_compress.c
@@ -248,7 +248,7 @@ static size_t FSE_writeNCount_generic (void* header, size_t headerBufferSize,
bitCount -= (count<max);
previous0 = (count==1);
if (remaining<1) return ERROR(GENERIC);
- while (remaining<threshold) nbBits--, threshold>>=1;
+ while (remaining<threshold) { nbBits--; threshold>>=1; }
}
if (bitCount>16) {
if ((!writeIsSafe) && (out > oend - 2)) return ERROR(dstSize_tooSmall); /* Buffer overflow */
@@ -292,7 +292,7 @@ size_t FSE_writeNCount (void* buffer, size_t bufferSize, const short* normalized
It doesn't use any additional memory.
But this function is unsafe : it doesn't check that all values within `src` can fit into `count`.
For this reason, prefer using a table `count` with 256 elements.
- @return : count of most numerous element
+ @return : count of most numerous element.
*/
size_t FSE_count_simple(unsigned* count, unsigned* maxSymbolValuePtr,
const void* src, size_t srcSize)
@@ -305,7 +305,10 @@ size_t FSE_count_simple(unsigned* count, unsigned* maxSymbolValuePtr,
memset(count, 0, (maxSymbolValue+1)*sizeof(*count));
if (srcSize==0) { *maxSymbolValuePtr = 0; return 0; }
- while (ip<end) count[*ip++]++;
+ while (ip<end) {
+ assert(*ip <= maxSymbolValue);
+ count[*ip++]++;
+ }
while (!count[maxSymbolValue]) maxSymbolValue--;
*maxSymbolValuePtr = maxSymbolValue;
@@ -318,7 +321,8 @@ size_t FSE_count_simple(unsigned* count, unsigned* maxSymbolValuePtr,
/* FSE_count_parallel_wksp() :
* Same as FSE_count_parallel(), but using an externally provided scratch buffer.
- * `workSpace` size must be a minimum of `1024 * sizeof(unsigned)`` */
+ * `workSpace` size must be a minimum of `1024 * sizeof(unsigned)`.
+ * @return : largest histogram frequency, or an error code (notably when histogram would be larger than *maxSymbolValuePtr). */
static size_t FSE_count_parallel_wksp(
unsigned* count, unsigned* maxSymbolValuePtr,
const void* source, size_t sourceSize,
@@ -333,7 +337,7 @@ static size_t FSE_count_parallel_wksp(
U32* const Counting3 = Counting2 + 256;
U32* const Counting4 = Counting3 + 256;
- memset(Counting1, 0, 4*256*sizeof(unsigned));
+ memset(workSpace, 0, 4*256*sizeof(unsigned));
/* safety checks */
if (!sourceSize) {
@@ -379,7 +383,9 @@ static size_t FSE_count_parallel_wksp(
if (Counting1[s]) return ERROR(maxSymbolValue_tooSmall);
} }
- { U32 s; for (s=0; s<=maxSymbolValue; s++) {
+ { U32 s;
+ if (maxSymbolValue > 255) maxSymbolValue = 255;
+ for (s=0; s<=maxSymbolValue; s++) {
count[s] = Counting1[s] + Counting2[s] + Counting3[s] + Counting4[s];
if (count[s] > max) max = count[s];
} }
@@ -393,9 +399,11 @@ static size_t FSE_count_parallel_wksp(
* Same as FSE_countFast(), but using an externally provided scratch buffer.
* `workSpace` size must be table of >= `1024` unsigned */
size_t FSE_countFast_wksp(unsigned* count, unsigned* maxSymbolValuePtr,
- const void* source, size_t sourceSize, unsigned* workSpace)
+ const void* source, size_t sourceSize,
+ unsigned* workSpace)
{
- if (sourceSize < 1500) return FSE_count_simple(count, maxSymbolValuePtr, source, sourceSize);
+ if (sourceSize < 1500) /* heuristic threshold */
+ return FSE_count_simple(count, maxSymbolValuePtr, source, sourceSize);
return FSE_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, 0, workSpace);
}
@@ -540,7 +548,7 @@ static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count,
find max, then give all remaining points to max */
U32 maxV = 0, maxC = 0;
for (s=0; s<=maxSymbolValue; s++)
- if (count[s] > maxC) maxV=s, maxC=count[s];
+ if (count[s] > maxC) { maxV=s; maxC=count[s]; }
norm[maxV] += (short)ToDistribute;
return 0;
}
@@ -548,7 +556,7 @@ static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count,
if (total == 0) {
/* all of the symbols were low enough for the lowOne or lowThreshold */
for (s=0; ToDistribute > 0; s = (s+1)%(maxSymbolValue+1))
- if (norm[s] > 0) ToDistribute--, norm[s]++;
+ if (norm[s] > 0) { ToDistribute--; norm[s]++; }
return 0;
}
@@ -604,7 +612,7 @@ size_t FSE_normalizeCount (short* normalizedCounter, unsigned tableLog,
U64 restToBeat = vStep * rtbTable[proba];
proba += (count[s]*step) - ((U64)proba<<scale) > restToBeat;
}
- if (proba > largestP) largestP=proba, largest=s;
+ if (proba > largestP) { largestP=proba; largest=s; }
normalizedCounter[s] = proba;
stillToDistribute -= proba;
} }
diff --git a/thirdparty/zstd/compress/huf_compress.c b/thirdparty/zstd/compress/huf_compress.c
index 5692d56e00..83230b415f 100644
--- a/thirdparty/zstd/compress/huf_compress.c
+++ b/thirdparty/zstd/compress/huf_compress.c
@@ -46,6 +46,7 @@
#include <string.h> /* memcpy, memset */
#include <stdio.h> /* printf (debug) */
#include "bitstream.h"
+#include "compiler.h"
#define FSE_STATIC_LINKING_ONLY /* FSE_optimalTableLog_internal */
#include "fse.h" /* header compression */
#define HUF_STATIC_LINKING_ONLY
@@ -322,7 +323,10 @@ static void HUF_sort(nodeElt* huffNode, const U32* count, U32 maxSymbolValue)
U32 const c = count[n];
U32 const r = BIT_highbit32(c+1) + 1;
U32 pos = rank[r].current++;
- while ((pos > rank[r].base) && (c > huffNode[pos-1].count)) huffNode[pos]=huffNode[pos-1], pos--;
+ while ((pos > rank[r].base) && (c > huffNode[pos-1].count)) {
+ huffNode[pos] = huffNode[pos-1];
+ pos--;
+ }
huffNode[pos].count = c;
huffNode[pos].byte = (BYTE)n;
}
@@ -331,10 +335,10 @@ static void HUF_sort(nodeElt* huffNode, const U32* count, U32 maxSymbolValue)
/** HUF_buildCTable_wksp() :
* Same as HUF_buildCTable(), but using externally allocated scratch buffer.
- * `workSpace` must be aligned on 4-bytes boundaries, and be at least as large as a table of 1024 unsigned.
+ * `workSpace` must be aligned on 4-bytes boundaries, and be at least as large as a table of HUF_CTABLE_WORKSPACE_SIZE_U32 unsigned.
*/
#define STARTNODE (HUF_SYMBOLVALUE_MAX+1)
-typedef nodeElt huffNodeTable[2*HUF_SYMBOLVALUE_MAX+1 +1];
+typedef nodeElt huffNodeTable[HUF_CTABLE_WORKSPACE_SIZE_U32];
size_t HUF_buildCTable_wksp (HUF_CElt* tree, const U32* count, U32 maxSymbolValue, U32 maxNbBits, void* workSpace, size_t wkspSize)
{
nodeElt* const huffNode0 = (nodeElt*)workSpace;
@@ -345,9 +349,10 @@ size_t HUF_buildCTable_wksp (HUF_CElt* tree, const U32* count, U32 maxSymbolValu
U32 nodeRoot;
/* safety checks */
- if (wkspSize < sizeof(huffNodeTable)) return ERROR(GENERIC); /* workSpace is not large enough */
+ if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */
+ if (wkspSize < sizeof(huffNodeTable)) return ERROR(workSpace_tooSmall);
if (maxNbBits == 0) maxNbBits = HUF_TABLELOG_DEFAULT;
- if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(GENERIC);
+ if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(maxSymbolValue_tooLarge);
memset(huffNode0, 0, sizeof(huffNodeTable));
/* sort, decreasing order */
@@ -405,6 +410,7 @@ size_t HUF_buildCTable_wksp (HUF_CElt* tree, const U32* count, U32 maxSymbolValu
}
/** HUF_buildCTable() :
+ * @return : maxNbBits
* Note : count is used before tree is written, so they can safely overlap
*/
size_t HUF_buildCTable (HUF_CElt* tree, const U32* count, U32 maxSymbolValue, U32 maxNbBits)
@@ -432,13 +438,14 @@ static int HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, uns
return !bad;
}
-static void HUF_encodeSymbol(BIT_CStream_t* bitCPtr, U32 symbol, const HUF_CElt* CTable)
+size_t HUF_compressBound(size_t size) { return HUF_COMPRESSBOUND(size); }
+
+FORCE_INLINE_TEMPLATE void
+HUF_encodeSymbol(BIT_CStream_t* bitCPtr, U32 symbol, const HUF_CElt* CTable)
{
BIT_addBitsFast(bitCPtr, CTable[symbol].val, CTable[symbol].nbBits);
}
-size_t HUF_compressBound(size_t size) { return HUF_COMPRESSBOUND(size); }
-
#define HUF_FLUSHBITS(s) BIT_flushBits(s)
#define HUF_FLUSHBITS_1(stream) \
@@ -447,7 +454,10 @@ size_t HUF_compressBound(size_t size) { return HUF_COMPRESSBOUND(size); }
#define HUF_FLUSHBITS_2(stream) \
if (sizeof((stream)->bitContainer)*8 < HUF_TABLELOG_MAX*4+7) HUF_FLUSHBITS(stream)
-size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable)
+FORCE_INLINE_TEMPLATE size_t
+HUF_compress1X_usingCTable_internal_body(void* dst, size_t dstSize,
+ const void* src, size_t srcSize,
+ const HUF_CElt* CTable)
{
const BYTE* ip = (const BYTE*) src;
BYTE* const ostart = (BYTE*)dst;
@@ -491,8 +501,58 @@ size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, si
return BIT_closeCStream(&bitC);
}
+#if DYNAMIC_BMI2
-size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable)
+static TARGET_ATTRIBUTE("bmi2") size_t
+HUF_compress1X_usingCTable_internal_bmi2(void* dst, size_t dstSize,
+ const void* src, size_t srcSize,
+ const HUF_CElt* CTable)
+{
+ return HUF_compress1X_usingCTable_internal_body(dst, dstSize, src, srcSize, CTable);
+}
+
+static size_t
+HUF_compress1X_usingCTable_internal_default(void* dst, size_t dstSize,
+ const void* src, size_t srcSize,
+ const HUF_CElt* CTable)
+{
+ return HUF_compress1X_usingCTable_internal_body(dst, dstSize, src, srcSize, CTable);
+}
+
+static size_t
+HUF_compress1X_usingCTable_internal(void* dst, size_t dstSize,
+ const void* src, size_t srcSize,
+ const HUF_CElt* CTable, const int bmi2)
+{
+ if (bmi2) {
+ return HUF_compress1X_usingCTable_internal_bmi2(dst, dstSize, src, srcSize, CTable);
+ }
+ return HUF_compress1X_usingCTable_internal_default(dst, dstSize, src, srcSize, CTable);
+}
+
+#else
+
+static size_t
+HUF_compress1X_usingCTable_internal(void* dst, size_t dstSize,
+ const void* src, size_t srcSize,
+ const HUF_CElt* CTable, const int bmi2)
+{
+ (void)bmi2;
+ return HUF_compress1X_usingCTable_internal_body(dst, dstSize, src, srcSize, CTable);
+}
+
+#endif
+
+size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable)
+{
+ return HUF_compress1X_usingCTable_internal(dst, dstSize, src, srcSize, CTable, /* bmi2 */ 0);
+}
+
+
+static size_t
+HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize,
+ const void* src, size_t srcSize,
+ const HUF_CElt* CTable, int bmi2)
{
size_t const segmentSize = (srcSize+3)/4; /* first 3 segments */
const BYTE* ip = (const BYTE*) src;
@@ -505,28 +565,31 @@ size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, si
if (srcSize < 12) return 0; /* no saving possible : too small input */
op += 6; /* jumpTable */
- { CHECK_V_F(cSize, HUF_compress1X_usingCTable(op, oend-op, ip, segmentSize, CTable) );
+ { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, oend-op, ip, segmentSize, CTable, bmi2) );
if (cSize==0) return 0;
+ assert(cSize <= 65535);
MEM_writeLE16(ostart, (U16)cSize);
op += cSize;
}
ip += segmentSize;
- { CHECK_V_F(cSize, HUF_compress1X_usingCTable(op, oend-op, ip, segmentSize, CTable) );
+ { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, oend-op, ip, segmentSize, CTable, bmi2) );
if (cSize==0) return 0;
+ assert(cSize <= 65535);
MEM_writeLE16(ostart+2, (U16)cSize);
op += cSize;
}
ip += segmentSize;
- { CHECK_V_F(cSize, HUF_compress1X_usingCTable(op, oend-op, ip, segmentSize, CTable) );
+ { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, oend-op, ip, segmentSize, CTable, bmi2) );
if (cSize==0) return 0;
+ assert(cSize <= 65535);
MEM_writeLE16(ostart+4, (U16)cSize);
op += cSize;
}
ip += segmentSize;
- { CHECK_V_F(cSize, HUF_compress1X_usingCTable(op, oend-op, ip, iend-ip, CTable) );
+ { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, oend-op, ip, iend-ip, CTable, bmi2) );
if (cSize==0) return 0;
op += cSize;
}
@@ -534,15 +597,20 @@ size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, si
return op-ostart;
}
+size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable)
+{
+ return HUF_compress4X_usingCTable_internal(dst, dstSize, src, srcSize, CTable, /* bmi2 */ 0);
+}
+
static size_t HUF_compressCTable_internal(
BYTE* const ostart, BYTE* op, BYTE* const oend,
const void* src, size_t srcSize,
- unsigned singleStream, const HUF_CElt* CTable)
+ unsigned singleStream, const HUF_CElt* CTable, const int bmi2)
{
size_t const cSize = singleStream ?
- HUF_compress1X_usingCTable(op, oend - op, src, srcSize, CTable) :
- HUF_compress4X_usingCTable(op, oend - op, src, srcSize, CTable);
+ HUF_compress1X_usingCTable_internal(op, oend - op, src, srcSize, CTable, bmi2) :
+ HUF_compress4X_usingCTable_internal(op, oend - op, src, srcSize, CTable, bmi2);
if (HUF_isError(cSize)) { return cSize; }
if (cSize==0) { return 0; } /* uncompressible */
op += cSize;
@@ -551,86 +619,98 @@ static size_t HUF_compressCTable_internal(
return op-ostart;
}
+typedef struct {
+ U32 count[HUF_SYMBOLVALUE_MAX + 1];
+ HUF_CElt CTable[HUF_SYMBOLVALUE_MAX + 1];
+ huffNodeTable nodeTable;
+} HUF_compress_tables_t;
-/* `workSpace` must a table of at least 1024 unsigned */
+/* HUF_compress_internal() :
+ * `workSpace` must a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */
static size_t HUF_compress_internal (
void* dst, size_t dstSize,
const void* src, size_t srcSize,
unsigned maxSymbolValue, unsigned huffLog,
unsigned singleStream,
void* workSpace, size_t wkspSize,
- HUF_CElt* oldHufTable, HUF_repeat* repeat, int preferRepeat)
+ HUF_CElt* oldHufTable, HUF_repeat* repeat, int preferRepeat,
+ const int bmi2)
{
+ HUF_compress_tables_t* const table = (HUF_compress_tables_t*)workSpace;
BYTE* const ostart = (BYTE*)dst;
BYTE* const oend = ostart + dstSize;
BYTE* op = ostart;
- U32* count;
- size_t const countSize = sizeof(U32) * (HUF_SYMBOLVALUE_MAX + 1);
- HUF_CElt* CTable;
- size_t const CTableSize = sizeof(HUF_CElt) * (HUF_SYMBOLVALUE_MAX + 1);
-
/* checks & inits */
- if (wkspSize < sizeof(huffNodeTable) + countSize + CTableSize) return ERROR(GENERIC);
- if (!srcSize) return 0; /* Uncompressed (note : 1 means rle, so first byte must be correct) */
- if (!dstSize) return 0; /* cannot fit within dst budget */
+ if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */
+ if (wkspSize < sizeof(*table)) return ERROR(workSpace_tooSmall);
+ if (!srcSize) return 0; /* Uncompressed */
+ if (!dstSize) return 0; /* cannot fit anything within dst budget */
if (srcSize > HUF_BLOCKSIZE_MAX) return ERROR(srcSize_wrong); /* current block size limit */
if (huffLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);
+ if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(maxSymbolValue_tooLarge);
if (!maxSymbolValue) maxSymbolValue = HUF_SYMBOLVALUE_MAX;
if (!huffLog) huffLog = HUF_TABLELOG_DEFAULT;
- count = (U32*)workSpace;
- workSpace = (BYTE*)workSpace + countSize;
- wkspSize -= countSize;
- CTable = (HUF_CElt*)workSpace;
- workSpace = (BYTE*)workSpace + CTableSize;
- wkspSize -= CTableSize;
-
- /* Heuristic : If we don't need to check the validity of the old table use the old table for small inputs */
+ /* Heuristic : If old table is valid, use it for small inputs */
if (preferRepeat && repeat && *repeat == HUF_repeat_valid) {
- return HUF_compressCTable_internal(ostart, op, oend, src, srcSize, singleStream, oldHufTable);
+ return HUF_compressCTable_internal(ostart, op, oend,
+ src, srcSize,
+ singleStream, oldHufTable, bmi2);
}
/* Scan input and build symbol stats */
- { CHECK_V_F(largest, FSE_count_wksp (count, &maxSymbolValue, (const BYTE*)src, srcSize, (U32*)workSpace) );
+ { CHECK_V_F(largest, FSE_count_wksp (table->count, &maxSymbolValue, (const BYTE*)src, srcSize, table->count) );
if (largest == srcSize) { *ostart = ((const BYTE*)src)[0]; return 1; } /* single symbol, rle */
- if (largest <= (srcSize >> 7)+1) return 0; /* Fast heuristic : not compressible enough */
+ if (largest <= (srcSize >> 7)+1) return 0; /* heuristic : probably not compressible enough */
}
/* Check validity of previous table */
- if (repeat && *repeat == HUF_repeat_check && !HUF_validateCTable(oldHufTable, count, maxSymbolValue)) {
+ if ( repeat
+ && *repeat == HUF_repeat_check
+ && !HUF_validateCTable(oldHufTable, table->count, maxSymbolValue)) {
*repeat = HUF_repeat_none;
}
/* Heuristic : use existing table for small inputs */
if (preferRepeat && repeat && *repeat != HUF_repeat_none) {
- return HUF_compressCTable_internal(ostart, op, oend, src, srcSize, singleStream, oldHufTable);
+ return HUF_compressCTable_internal(ostart, op, oend,
+ src, srcSize,
+ singleStream, oldHufTable, bmi2);
}
/* Build Huffman Tree */
huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue);
- { CHECK_V_F(maxBits, HUF_buildCTable_wksp (CTable, count, maxSymbolValue, huffLog, workSpace, wkspSize) );
+ { CHECK_V_F(maxBits, HUF_buildCTable_wksp(table->CTable, table->count,
+ maxSymbolValue, huffLog,
+ table->nodeTable, sizeof(table->nodeTable)) );
huffLog = (U32)maxBits;
- /* Zero the unused symbols so we can check it for validity */
- memset(CTable + maxSymbolValue + 1, 0, CTableSize - (maxSymbolValue + 1) * sizeof(HUF_CElt));
+ /* Zero unused symbols in CTable, so we can check it for validity */
+ memset(table->CTable + (maxSymbolValue + 1), 0,
+ sizeof(table->CTable) - ((maxSymbolValue + 1) * sizeof(HUF_CElt)));
}
/* Write table description header */
- { CHECK_V_F(hSize, HUF_writeCTable (op, dstSize, CTable, maxSymbolValue, huffLog) );
- /* Check if using the previous table will be beneficial */
+ { CHECK_V_F(hSize, HUF_writeCTable (op, dstSize, table->CTable, maxSymbolValue, huffLog) );
+ /* Check if using previous huffman table is beneficial */
if (repeat && *repeat != HUF_repeat_none) {
- size_t const oldSize = HUF_estimateCompressedSize(oldHufTable, count, maxSymbolValue);
- size_t const newSize = HUF_estimateCompressedSize(CTable, count, maxSymbolValue);
+ size_t const oldSize = HUF_estimateCompressedSize(oldHufTable, table->count, maxSymbolValue);
+ size_t const newSize = HUF_estimateCompressedSize(table->CTable, table->count, maxSymbolValue);
if (oldSize <= hSize + newSize || hSize + 12 >= srcSize) {
- return HUF_compressCTable_internal(ostart, op, oend, src, srcSize, singleStream, oldHufTable);
- }
- }
- /* Use the new table */
+ return HUF_compressCTable_internal(ostart, op, oend,
+ src, srcSize,
+ singleStream, oldHufTable, bmi2);
+ } }
+
+ /* Use the new huffman table */
if (hSize + 12ul >= srcSize) { return 0; }
op += hSize;
if (repeat) { *repeat = HUF_repeat_none; }
- if (oldHufTable) { memcpy(oldHufTable, CTable, CTableSize); } /* Save the new table */
+ if (oldHufTable)
+ memcpy(oldHufTable, table->CTable, sizeof(table->CTable)); /* Save new table */
}
- return HUF_compressCTable_internal(ostart, op, oend, src, srcSize, singleStream, CTable);
+ return HUF_compressCTable_internal(ostart, op, oend,
+ src, srcSize,
+ singleStream, table->CTable, bmi2);
}
@@ -639,52 +719,70 @@ size_t HUF_compress1X_wksp (void* dst, size_t dstSize,
unsigned maxSymbolValue, unsigned huffLog,
void* workSpace, size_t wkspSize)
{
- return HUF_compress_internal(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, 1 /* single stream */, workSpace, wkspSize, NULL, NULL, 0);
+ return HUF_compress_internal(dst, dstSize, src, srcSize,
+ maxSymbolValue, huffLog, 1 /*single stream*/,
+ workSpace, wkspSize,
+ NULL, NULL, 0, 0 /*bmi2*/);
}
size_t HUF_compress1X_repeat (void* dst, size_t dstSize,
const void* src, size_t srcSize,
unsigned maxSymbolValue, unsigned huffLog,
void* workSpace, size_t wkspSize,
- HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat)
+ HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2)
{
- return HUF_compress_internal(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, 1 /* single stream */, workSpace, wkspSize, hufTable, repeat, preferRepeat);
+ return HUF_compress_internal(dst, dstSize, src, srcSize,
+ maxSymbolValue, huffLog, 1 /*single stream*/,
+ workSpace, wkspSize, hufTable,
+ repeat, preferRepeat, bmi2);
}
size_t HUF_compress1X (void* dst, size_t dstSize,
const void* src, size_t srcSize,
unsigned maxSymbolValue, unsigned huffLog)
{
- unsigned workSpace[1024];
+ unsigned workSpace[HUF_WORKSPACE_SIZE_U32];
return HUF_compress1X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(workSpace));
}
+/* HUF_compress4X_repeat():
+ * compress input using 4 streams.
+ * provide workspace to generate compression tables */
size_t HUF_compress4X_wksp (void* dst, size_t dstSize,
const void* src, size_t srcSize,
unsigned maxSymbolValue, unsigned huffLog,
void* workSpace, size_t wkspSize)
{
- return HUF_compress_internal(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, 0 /* 4 streams */, workSpace, wkspSize, NULL, NULL, 0);
+ return HUF_compress_internal(dst, dstSize, src, srcSize,
+ maxSymbolValue, huffLog, 0 /*4 streams*/,
+ workSpace, wkspSize,
+ NULL, NULL, 0, 0 /*bmi2*/);
}
+/* HUF_compress4X_repeat():
+ * compress input using 4 streams.
+ * re-use an existing huffman compression table */
size_t HUF_compress4X_repeat (void* dst, size_t dstSize,
const void* src, size_t srcSize,
unsigned maxSymbolValue, unsigned huffLog,
void* workSpace, size_t wkspSize,
- HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat)
+ HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2)
{
- return HUF_compress_internal(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, 0 /* 4 streams */, workSpace, wkspSize, hufTable, repeat, preferRepeat);
+ return HUF_compress_internal(dst, dstSize, src, srcSize,
+ maxSymbolValue, huffLog, 0 /* 4 streams */,
+ workSpace, wkspSize,
+ hufTable, repeat, preferRepeat, bmi2);
}
size_t HUF_compress2 (void* dst, size_t dstSize,
const void* src, size_t srcSize,
unsigned maxSymbolValue, unsigned huffLog)
{
- unsigned workSpace[1024];
+ unsigned workSpace[HUF_WORKSPACE_SIZE_U32];
return HUF_compress4X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(workSpace));
}
size_t HUF_compress (void* dst, size_t maxDstSize, const void* src, size_t srcSize)
{
- return HUF_compress2(dst, maxDstSize, src, (U32)srcSize, 255, HUF_TABLELOG_DEFAULT);
+ return HUF_compress2(dst, maxDstSize, src, srcSize, 255, HUF_TABLELOG_DEFAULT);
}
diff --git a/thirdparty/zstd/compress/zstd_compress.c b/thirdparty/zstd/compress/zstd_compress.c
index 8d1629246d..2aa26da4cd 100644
--- a/thirdparty/zstd/compress/zstd_compress.c
+++ b/thirdparty/zstd/compress/zstd_compress.c
@@ -21,6 +21,7 @@
* Dependencies
***************************************/
#include <string.h> /* memset */
+#include "cpu.h"
#include "mem.h"
#define FSE_STATIC_LINKING_ONLY /* FSE_encodeSymbol */
#include "fse.h"
@@ -49,7 +50,13 @@ struct ZSTD_CDict_s {
void* dictBuffer;
const void* dictContent;
size_t dictContentSize;
- ZSTD_CCtx* refContext;
+ void* workspace;
+ size_t workspaceSize;
+ ZSTD_matchState_t matchState;
+ ZSTD_compressedBlockState_t cBlockState;
+ ZSTD_compressionParameters cParams;
+ ZSTD_customMem customMem;
+ U32 dictID;
}; /* typedef'd to ZSTD_CDict within "zstd.h" */
ZSTD_CCtx* ZSTD_createCCtx(void)
@@ -59,18 +66,17 @@ ZSTD_CCtx* ZSTD_createCCtx(void)
ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem)
{
- ZSTD_CCtx* cctx;
-
- if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
-
- cctx = (ZSTD_CCtx*) ZSTD_calloc(sizeof(ZSTD_CCtx), customMem);
- if (!cctx) return NULL;
- cctx->customMem = customMem;
- cctx->requestedParams.compressionLevel = ZSTD_CLEVEL_DEFAULT;
- cctx->requestedParams.fParams.contentSizeFlag = 1;
ZSTD_STATIC_ASSERT(zcss_init==0);
ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN==(0ULL - 1));
- return cctx;
+ if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
+ { ZSTD_CCtx* const cctx = (ZSTD_CCtx*)ZSTD_calloc(sizeof(ZSTD_CCtx), customMem);
+ if (!cctx) return NULL;
+ cctx->customMem = customMem;
+ cctx->requestedParams.compressionLevel = ZSTD_CLEVEL_DEFAULT;
+ cctx->requestedParams.fParams.contentSizeFlag = 1;
+ cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
+ return cctx;
+ }
}
ZSTD_CCtx* ZSTD_initStaticCCtx(void *workspace, size_t workspaceSize)
@@ -83,11 +89,16 @@ ZSTD_CCtx* ZSTD_initStaticCCtx(void *workspace, size_t workspaceSize)
cctx->workSpace = (void*)(cctx+1);
cctx->workSpaceSize = workspaceSize - sizeof(ZSTD_CCtx);
- /* entropy space (never moves) */
- if (cctx->workSpaceSize < sizeof(ZSTD_entropyCTables_t)) return NULL;
+ /* statically sized space. entropyWorkspace never moves (but prev/next block swap places) */
+ if (cctx->workSpaceSize < HUF_WORKSPACE_SIZE + 2 * sizeof(ZSTD_compressedBlockState_t)) return NULL;
assert(((size_t)cctx->workSpace & (sizeof(void*)-1)) == 0); /* ensure correct alignment */
- cctx->entropy = (ZSTD_entropyCTables_t*)cctx->workSpace;
-
+ cctx->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)cctx->workSpace;
+ cctx->blockState.nextCBlock = cctx->blockState.prevCBlock + 1;
+ {
+ void* const ptr = cctx->blockState.nextCBlock + 1;
+ cctx->entropyWorkspace = (U32*)ptr;
+ }
+ cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
return cctx;
}
@@ -95,13 +106,10 @@ size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
{
if (cctx==NULL) return 0; /* support free on NULL */
if (cctx->staticSize) return ERROR(memory_allocation); /* not compatible with static CCtx */
- ZSTD_free(cctx->workSpace, cctx->customMem);
- cctx->workSpace = NULL;
- ZSTD_freeCDict(cctx->cdictLocal);
- cctx->cdictLocal = NULL;
+ ZSTD_free(cctx->workSpace, cctx->customMem); cctx->workSpace = NULL;
+ ZSTD_freeCDict(cctx->cdictLocal); cctx->cdictLocal = NULL;
#ifdef ZSTD_MULTITHREAD
- ZSTDMT_freeCCtx(cctx->mtctx);
- cctx->mtctx = NULL;
+ ZSTDMT_freeCCtx(cctx->mtctx); cctx->mtctx = NULL;
#endif
ZSTD_free(cctx, cctx->customMem);
return 0; /* reserved as a potential error code in the future */
@@ -122,10 +130,6 @@ static size_t ZSTD_sizeof_mtctx(const ZSTD_CCtx* cctx)
size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx)
{
if (cctx==NULL) return 0; /* support sizeof on NULL */
- DEBUGLOG(3, "sizeof(*cctx) : %u", (U32)sizeof(*cctx));
- DEBUGLOG(3, "workSpaceSize (including streaming buffers): %u", (U32)cctx->workSpaceSize);
- DEBUGLOG(3, "inner cdict : %u", (U32)ZSTD_sizeof_CDict(cctx->cdictLocal));
- DEBUGLOG(3, "inner MTCTX : %u", (U32)ZSTD_sizeof_mtctx(cctx));
return sizeof(*cctx) + cctx->workSpaceSize
+ ZSTD_sizeof_CDict(cctx->cdictLocal)
+ ZSTD_sizeof_mtctx(cctx);
@@ -139,37 +143,19 @@ size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs)
/* private API call, for dictBuilder only */
const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) { return &(ctx->seqStore); }
-#define ZSTD_CLEVEL_CUSTOM 999
-
-static ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
- ZSTD_CCtx_params CCtxParams, U64 srcSizeHint, size_t dictSize)
-{
- DEBUGLOG(4, "ZSTD_getCParamsFromCCtxParams: srcSize = %u, dictSize = %u",
- (U32)srcSizeHint, (U32)dictSize);
- return (CCtxParams.compressionLevel == ZSTD_CLEVEL_CUSTOM) ?
- CCtxParams.cParams :
- ZSTD_getCParams(CCtxParams.compressionLevel, srcSizeHint, dictSize);
-}
-
-static void ZSTD_cLevelToCCtxParams_srcSize(ZSTD_CCtx_params* CCtxParams, U64 srcSize)
-{
- DEBUGLOG(4, "ZSTD_cLevelToCCtxParams_srcSize: srcSize = %u",
- (U32)srcSize);
- CCtxParams->cParams = ZSTD_getCParamsFromCCtxParams(*CCtxParams, srcSize, 0);
- CCtxParams->compressionLevel = ZSTD_CLEVEL_CUSTOM;
-}
-
-static void ZSTD_cLevelToCParams(ZSTD_CCtx* cctx)
-{
- DEBUGLOG(4, "ZSTD_cLevelToCParams: level=%i", cctx->requestedParams.compressionLevel);
- ZSTD_cLevelToCCtxParams_srcSize(
- &cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1);
-}
-
-static void ZSTD_cLevelToCCtxParams(ZSTD_CCtx_params* CCtxParams)
-{
- DEBUGLOG(4, "ZSTD_cLevelToCCtxParams");
- ZSTD_cLevelToCCtxParams_srcSize(CCtxParams, ZSTD_CONTENTSIZE_UNKNOWN);
+ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
+ const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize)
+{
+ ZSTD_compressionParameters cParams = ZSTD_getCParams(CCtxParams->compressionLevel, srcSizeHint, dictSize);
+ if (CCtxParams->ldmParams.enableLdm) cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG;
+ if (CCtxParams->cParams.windowLog) cParams.windowLog = CCtxParams->cParams.windowLog;
+ if (CCtxParams->cParams.hashLog) cParams.hashLog = CCtxParams->cParams.hashLog;
+ if (CCtxParams->cParams.chainLog) cParams.chainLog = CCtxParams->cParams.chainLog;
+ if (CCtxParams->cParams.searchLog) cParams.searchLog = CCtxParams->cParams.searchLog;
+ if (CCtxParams->cParams.searchLength) cParams.searchLength = CCtxParams->cParams.searchLength;
+ if (CCtxParams->cParams.targetLength) cParams.targetLength = CCtxParams->cParams.targetLength;
+ if (CCtxParams->cParams.strategy) cParams.strategy = CCtxParams->cParams.strategy;
+ return cParams;
}
static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams(
@@ -178,7 +164,9 @@ static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams(
ZSTD_CCtx_params cctxParams;
memset(&cctxParams, 0, sizeof(cctxParams));
cctxParams.cParams = cParams;
- cctxParams.compressionLevel = ZSTD_CLEVEL_CUSTOM;
+ cctxParams.compressionLevel = ZSTD_CLEVEL_DEFAULT; /* should not matter, as all cParams are presumed properly defined */
+ assert(!ZSTD_checkCParams(cParams));
+ cctxParams.fParams.contentSizeFlag = 1;
return cctxParams;
}
@@ -192,6 +180,7 @@ static ZSTD_CCtx_params* ZSTD_createCCtxParams_advanced(
if (!params) { return NULL; }
params->customMem = customMem;
params->compressionLevel = ZSTD_CLEVEL_DEFAULT;
+ params->fParams.contentSizeFlag = 1;
return params;
}
@@ -207,36 +196,41 @@ size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params)
return 0;
}
-size_t ZSTD_resetCCtxParams(ZSTD_CCtx_params* params)
+size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params)
{
- return ZSTD_initCCtxParams(params, ZSTD_CLEVEL_DEFAULT);
+ return ZSTD_CCtxParams_init(params, ZSTD_CLEVEL_DEFAULT);
}
-size_t ZSTD_initCCtxParams(ZSTD_CCtx_params* cctxParams, int compressionLevel) {
+size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel) {
if (!cctxParams) { return ERROR(GENERIC); }
memset(cctxParams, 0, sizeof(*cctxParams));
cctxParams->compressionLevel = compressionLevel;
+ cctxParams->fParams.contentSizeFlag = 1;
return 0;
}
-size_t ZSTD_initCCtxParams_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params)
+size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params)
{
if (!cctxParams) { return ERROR(GENERIC); }
CHECK_F( ZSTD_checkCParams(params.cParams) );
memset(cctxParams, 0, sizeof(*cctxParams));
cctxParams->cParams = params.cParams;
cctxParams->fParams = params.fParams;
- cctxParams->compressionLevel = ZSTD_CLEVEL_CUSTOM;
+ cctxParams->compressionLevel = ZSTD_CLEVEL_DEFAULT; /* should not matter, as all cParams are presumed properly defined */
+ assert(!ZSTD_checkCParams(params.cParams));
return 0;
}
+/* ZSTD_assignParamsToCCtxParams() :
+ * params is presumed valid at this stage */
static ZSTD_CCtx_params ZSTD_assignParamsToCCtxParams(
ZSTD_CCtx_params cctxParams, ZSTD_parameters params)
{
ZSTD_CCtx_params ret = cctxParams;
ret.cParams = params.cParams;
ret.fParams = params.fParams;
- ret.compressionLevel = ZSTD_CLEVEL_CUSTOM;
+ ret.compressionLevel = ZSTD_CLEVEL_DEFAULT; /* should not matter, as all cParams are presumed properly defined */
+ assert(!ZSTD_checkCParams(params.cParams));
return ret;
}
@@ -245,10 +239,49 @@ static ZSTD_CCtx_params ZSTD_assignParamsToCCtxParams(
return ERROR(parameter_outOfBound); \
} }
+
+static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)
+{
+ switch(param)
+ {
+ case ZSTD_p_compressionLevel:
+ case ZSTD_p_hashLog:
+ case ZSTD_p_chainLog:
+ case ZSTD_p_searchLog:
+ case ZSTD_p_minMatch:
+ case ZSTD_p_targetLength:
+ case ZSTD_p_compressionStrategy:
+ case ZSTD_p_compressLiterals:
+ return 1;
+
+ case ZSTD_p_format:
+ case ZSTD_p_windowLog:
+ case ZSTD_p_contentSizeFlag:
+ case ZSTD_p_checksumFlag:
+ case ZSTD_p_dictIDFlag:
+ case ZSTD_p_forceMaxWindow :
+ case ZSTD_p_nbWorkers:
+ case ZSTD_p_jobSize:
+ case ZSTD_p_overlapSizeLog:
+ case ZSTD_p_enableLongDistanceMatching:
+ case ZSTD_p_ldmHashLog:
+ case ZSTD_p_ldmMinMatch:
+ case ZSTD_p_ldmBucketSizeLog:
+ case ZSTD_p_ldmHashEveryLog:
+ default:
+ return 0;
+ }
+}
+
size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, unsigned value)
{
DEBUGLOG(4, "ZSTD_CCtx_setParameter (%u, %u)", (U32)param, value);
- if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
+ if (cctx->streamStage != zcss_init) {
+ if (ZSTD_isUpdateAuthorized(param)) {
+ cctx->cParamsChanged = 1;
+ } else {
+ return ERROR(stage_wrong);
+ } }
switch(param)
{
@@ -267,9 +300,9 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, unsigned v
case ZSTD_p_targetLength:
case ZSTD_p_compressionStrategy:
if (cctx->cdict) return ERROR(stage_wrong);
- if (value>0) ZSTD_cLevelToCParams(cctx); /* Can optimize if srcSize is known */
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
+ case ZSTD_p_compressLiterals:
case ZSTD_p_contentSizeFlag:
case ZSTD_p_checksumFlag:
case ZSTD_p_dictIDFlag:
@@ -280,23 +313,17 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, unsigned v
* default : 0 when using a CDict, 1 when using a Prefix */
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
- case ZSTD_p_nbThreads:
- if ((value > 1) && cctx->staticSize) {
+ case ZSTD_p_nbWorkers:
+ if ((value>0) && cctx->staticSize) {
return ERROR(parameter_unsupported); /* MT not compatible with static alloc */
}
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
case ZSTD_p_jobSize:
- return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
-
case ZSTD_p_overlapSizeLog:
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
case ZSTD_p_enableLongDistanceMatching:
- if (cctx->cdict) return ERROR(stage_wrong);
- if (value>0) ZSTD_cLevelToCParams(cctx);
- return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
-
case ZSTD_p_ldmHashLog:
case ZSTD_p_ldmMinMatch:
case ZSTD_p_ldmBucketSizeLog:
@@ -320,69 +347,62 @@ size_t ZSTD_CCtxParam_setParameter(
CCtxParams->format = (ZSTD_format_e)value;
return (size_t)CCtxParams->format;
- case ZSTD_p_compressionLevel :
- if ((int)value > ZSTD_maxCLevel()) value = ZSTD_maxCLevel();
- if (value) /* 0 : does not change current level */
- CCtxParams->compressionLevel = value;
- return CCtxParams->compressionLevel;
+ case ZSTD_p_compressionLevel : {
+ int cLevel = (int)value; /* cast expected to restore negative sign */
+ if (cLevel > ZSTD_maxCLevel()) cLevel = ZSTD_maxCLevel();
+ if (cLevel) { /* 0 : does not change current level */
+ CCtxParams->disableLiteralCompression = (cLevel<0); /* negative levels disable huffman */
+ CCtxParams->compressionLevel = cLevel;
+ }
+ if (CCtxParams->compressionLevel >= 0) return CCtxParams->compressionLevel;
+ return 0; /* return type (size_t) cannot represent negative values */
+ }
case ZSTD_p_windowLog :
- DEBUGLOG(4, "ZSTD_CCtxParam_setParameter: set windowLog=%u", value);
- if (value) { /* 0 : does not change current windowLog */
+ if (value>0) /* 0 => use default */
CLAMPCHECK(value, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX);
- ZSTD_cLevelToCCtxParams(CCtxParams);
- CCtxParams->cParams.windowLog = value;
- }
+ CCtxParams->cParams.windowLog = value;
return CCtxParams->cParams.windowLog;
case ZSTD_p_hashLog :
- if (value) { /* 0 : does not change current hashLog */
+ if (value>0) /* 0 => use default */
CLAMPCHECK(value, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
- ZSTD_cLevelToCCtxParams(CCtxParams);
- CCtxParams->cParams.hashLog = value;
- }
+ CCtxParams->cParams.hashLog = value;
return CCtxParams->cParams.hashLog;
case ZSTD_p_chainLog :
- if (value) { /* 0 : does not change current chainLog */
+ if (value>0) /* 0 => use default */
CLAMPCHECK(value, ZSTD_CHAINLOG_MIN, ZSTD_CHAINLOG_MAX);
- ZSTD_cLevelToCCtxParams(CCtxParams);
- CCtxParams->cParams.chainLog = value;
- }
+ CCtxParams->cParams.chainLog = value;
return CCtxParams->cParams.chainLog;
case ZSTD_p_searchLog :
- if (value) { /* 0 : does not change current searchLog */
+ if (value>0) /* 0 => use default */
CLAMPCHECK(value, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
- ZSTD_cLevelToCCtxParams(CCtxParams);
- CCtxParams->cParams.searchLog = value;
- }
+ CCtxParams->cParams.searchLog = value;
return value;
case ZSTD_p_minMatch :
- if (value) { /* 0 : does not change current minMatch length */
+ if (value>0) /* 0 => use default */
CLAMPCHECK(value, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX);
- ZSTD_cLevelToCCtxParams(CCtxParams);
- CCtxParams->cParams.searchLength = value;
- }
+ CCtxParams->cParams.searchLength = value;
return CCtxParams->cParams.searchLength;
case ZSTD_p_targetLength :
- if (value) { /* 0 : does not change current sufficient_len */
- CLAMPCHECK(value, ZSTD_TARGETLENGTH_MIN, ZSTD_TARGETLENGTH_MAX);
- ZSTD_cLevelToCCtxParams(CCtxParams);
- CCtxParams->cParams.targetLength = value;
- }
+ /* all values are valid. 0 => use default */
+ CCtxParams->cParams.targetLength = value;
return CCtxParams->cParams.targetLength;
case ZSTD_p_compressionStrategy :
- if (value) { /* 0 : does not change currentstrategy */
+ if (value>0) /* 0 => use default */
CLAMPCHECK(value, (unsigned)ZSTD_fast, (unsigned)ZSTD_btultra);
- ZSTD_cLevelToCCtxParams(CCtxParams);
- CCtxParams->cParams.strategy = (ZSTD_strategy)value;
- }
+ CCtxParams->cParams.strategy = (ZSTD_strategy)value;
return (size_t)CCtxParams->cParams.strategy;
+ case ZSTD_p_compressLiterals:
+ CCtxParams->disableLiteralCompression = !value;
+ return !CCtxParams->disableLiteralCompression;
+
case ZSTD_p_contentSizeFlag :
/* Content size written in frame header _when known_ (default:1) */
DEBUGLOG(4, "set content size flag = %u", (value>0));
@@ -396,27 +416,25 @@ size_t ZSTD_CCtxParam_setParameter(
case ZSTD_p_dictIDFlag : /* When applicable, dictionary's dictID is provided in frame header (default:1) */
DEBUGLOG(4, "set dictIDFlag = %u", (value>0));
- CCtxParams->fParams.noDictIDFlag = (value == 0);
+ CCtxParams->fParams.noDictIDFlag = !value;
return !CCtxParams->fParams.noDictIDFlag;
case ZSTD_p_forceMaxWindow :
CCtxParams->forceWindow = (value > 0);
return CCtxParams->forceWindow;
- case ZSTD_p_nbThreads :
- if (value == 0) return CCtxParams->nbThreads;
+ case ZSTD_p_nbWorkers :
#ifndef ZSTD_MULTITHREAD
- if (value > 1) return ERROR(parameter_unsupported);
- return 1;
+ if (value>0) return ERROR(parameter_unsupported);
+ return 0;
#else
- return ZSTDMT_CCtxParam_setNbThreads(CCtxParams, value);
+ return ZSTDMT_CCtxParam_setNbWorkers(CCtxParams, value);
#endif
case ZSTD_p_jobSize :
#ifndef ZSTD_MULTITHREAD
return ERROR(parameter_unsupported);
#else
- if (CCtxParams->nbThreads <= 1) return ERROR(parameter_unsupported);
return ZSTDMT_CCtxParam_setMTCtxParameter(CCtxParams, ZSTDMT_p_jobSize, value);
#endif
@@ -424,44 +442,36 @@ size_t ZSTD_CCtxParam_setParameter(
#ifndef ZSTD_MULTITHREAD
return ERROR(parameter_unsupported);
#else
- if (CCtxParams->nbThreads <= 1) return ERROR(parameter_unsupported);
return ZSTDMT_CCtxParam_setMTCtxParameter(CCtxParams, ZSTDMT_p_overlapSectionLog, value);
#endif
case ZSTD_p_enableLongDistanceMatching :
- if (value) {
- ZSTD_cLevelToCCtxParams(CCtxParams);
- CCtxParams->cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG;
- }
- return ZSTD_ldm_initializeParameters(&CCtxParams->ldmParams, value);
+ CCtxParams->ldmParams.enableLdm = (value>0);
+ return CCtxParams->ldmParams.enableLdm;
case ZSTD_p_ldmHashLog :
- if (value) { /* 0 : does not change current ldmHashLog */
+ if (value>0) /* 0 ==> auto */
CLAMPCHECK(value, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
- CCtxParams->ldmParams.hashLog = value;
- }
+ CCtxParams->ldmParams.hashLog = value;
return CCtxParams->ldmParams.hashLog;
case ZSTD_p_ldmMinMatch :
- if (value) { /* 0 : does not change current ldmMinMatch */
+ if (value>0) /* 0 ==> default */
CLAMPCHECK(value, ZSTD_LDM_MINMATCH_MIN, ZSTD_LDM_MINMATCH_MAX);
- CCtxParams->ldmParams.minMatchLength = value;
- }
+ CCtxParams->ldmParams.minMatchLength = value;
return CCtxParams->ldmParams.minMatchLength;
case ZSTD_p_ldmBucketSizeLog :
- if (value > ZSTD_LDM_BUCKETSIZELOG_MAX) {
+ if (value > ZSTD_LDM_BUCKETSIZELOG_MAX)
return ERROR(parameter_outOfBound);
- }
CCtxParams->ldmParams.bucketSizeLog = value;
- return value;
+ return CCtxParams->ldmParams.bucketSizeLog;
case ZSTD_p_ldmHashEveryLog :
- if (value > ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN) {
+ if (value > ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN)
return ERROR(parameter_outOfBound);
- }
CCtxParams->ldmParams.hashEveryLog = value;
- return value;
+ return CCtxParams->ldmParams.hashEveryLog;
default: return ERROR(parameter_unsupported);
}
@@ -470,6 +480,9 @@ size_t ZSTD_CCtxParam_setParameter(
/** ZSTD_CCtx_setParametersUsingCCtxParams() :
* just applies `params` into `cctx`
* no action is performed, parameters are merely stored.
+ * If ZSTDMT is enabled, parameters are pushed to cctx->mtctx.
+ * This is possible even if a compression is ongoing.
+ * In which case, new parameters will be applied on the fly, starting with next compression job.
*/
size_t ZSTD_CCtx_setParametersUsingCCtxParams(
ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params)
@@ -478,7 +491,6 @@ size_t ZSTD_CCtx_setParametersUsingCCtxParams(
if (cctx->cdict) return ERROR(stage_wrong);
cctx->requestedParams = *params;
-
return 0;
}
@@ -492,7 +504,7 @@ ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long lo
size_t ZSTD_CCtx_loadDictionary_advanced(
ZSTD_CCtx* cctx, const void* dict, size_t dictSize,
- ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictMode_e dictMode)
+ ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType)
{
if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
if (cctx->staticSize) return ERROR(memory_allocation); /* no malloc for static CCtx */
@@ -503,10 +515,10 @@ size_t ZSTD_CCtx_loadDictionary_advanced(
cctx->cdict = NULL;
} else {
ZSTD_compressionParameters const cParams =
- ZSTD_getCParamsFromCCtxParams(cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1, dictSize);
+ ZSTD_getCParamsFromCCtxParams(&cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1, dictSize);
cctx->cdictLocal = ZSTD_createCDict_advanced(
dict, dictSize,
- dictLoadMethod, dictMode,
+ dictLoadMethod, dictContentType,
cParams, cctx->customMem);
cctx->cdict = cctx->cdictLocal;
if (cctx->cdictLocal == NULL)
@@ -519,13 +531,13 @@ ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_byReference(
ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
{
return ZSTD_CCtx_loadDictionary_advanced(
- cctx, dict, dictSize, ZSTD_dlm_byRef, ZSTD_dm_auto);
+ cctx, dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto);
}
ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
{
return ZSTD_CCtx_loadDictionary_advanced(
- cctx, dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dm_auto);
+ cctx, dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto);
}
@@ -539,17 +551,17 @@ size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize)
{
- return ZSTD_CCtx_refPrefix_advanced(cctx, prefix, prefixSize, ZSTD_dm_rawContent);
+ return ZSTD_CCtx_refPrefix_advanced(cctx, prefix, prefixSize, ZSTD_dct_rawContent);
}
size_t ZSTD_CCtx_refPrefix_advanced(
- ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictMode_e dictMode)
+ ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
{
if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
cctx->cdict = NULL; /* prefix discards any prior cdict */
cctx->prefixDict.dict = prefix;
cctx->prefixDict.dictSize = prefixSize;
- cctx->prefixDict.dictMode = dictMode;
+ cctx->prefixDict.dictContentType = dictContentType;
return 0;
}
@@ -577,7 +589,8 @@ size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams)
CLAMPCHECK(cParams.hashLog, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
CLAMPCHECK(cParams.searchLog, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
CLAMPCHECK(cParams.searchLength, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX);
- CLAMPCHECK(cParams.targetLength, ZSTD_TARGETLENGTH_MIN, ZSTD_TARGETLENGTH_MAX);
+ if ((U32)(cParams.targetLength) < ZSTD_TARGETLENGTH_MIN)
+ return ERROR(parameter_unsupported);
if ((U32)(cParams.strategy) > (U32)ZSTD_btultra)
return ERROR(parameter_unsupported);
return 0;
@@ -597,7 +610,7 @@ static ZSTD_compressionParameters ZSTD_clampCParams(ZSTD_compressionParameters c
CLAMP(cParams.hashLog, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
CLAMP(cParams.searchLog, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
CLAMP(cParams.searchLength, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX);
- CLAMP(cParams.targetLength, ZSTD_TARGETLENGTH_MIN, ZSTD_TARGETLENGTH_MAX);
+ if ((U32)(cParams.targetLength) < ZSTD_TARGETLENGTH_MIN) cParams.targetLength = ZSTD_TARGETLENGTH_MIN;
if ((U32)(cParams.strategy) > (U32)ZSTD_btultra) cParams.strategy = ZSTD_btultra;
return cParams;
}
@@ -653,36 +666,43 @@ ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, u
return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize);
}
+static size_t ZSTD_sizeof_matchState(ZSTD_compressionParameters const* cParams, const U32 forCCtx)
+{
+ size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog);
+ size_t const hSize = ((size_t)1) << cParams->hashLog;
+ U32 const hashLog3 = (forCCtx && cParams->searchLength==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;
+ size_t const h3Size = ((size_t)1) << hashLog3;
+ size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
+ size_t const optPotentialSpace = ((MaxML+1) + (MaxLL+1) + (MaxOff+1) + (1<<Litbits)) * sizeof(U32)
+ + (ZSTD_OPT_NUM+1) * (sizeof(ZSTD_match_t)+sizeof(ZSTD_optimal_t));
+ size_t const optSpace = (forCCtx && ((cParams->strategy == ZSTD_btopt) ||
+ (cParams->strategy == ZSTD_btultra)))
+ ? optPotentialSpace
+ : 0;
+ DEBUGLOG(4, "chainSize: %u - hSize: %u - h3Size: %u",
+ (U32)chainSize, (U32)hSize, (U32)h3Size);
+ return tableSpace + optSpace;
+}
+
size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params)
{
/* Estimate CCtx size is supported for single-threaded compression only. */
- if (params->nbThreads > 1) { return ERROR(GENERIC); }
+ if (params->nbWorkers > 0) { return ERROR(GENERIC); }
{ ZSTD_compressionParameters const cParams =
- ZSTD_getCParamsFromCCtxParams(*params, 0, 0);
+ ZSTD_getCParamsFromCCtxParams(params, 0, 0);
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
U32 const divider = (cParams.searchLength==3) ? 3 : 4;
size_t const maxNbSeq = blockSize / divider;
size_t const tokenSpace = blockSize + 11*maxNbSeq;
- size_t const chainSize =
- (cParams.strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams.chainLog);
- size_t const hSize = ((size_t)1) << cParams.hashLog;
- U32 const hashLog3 = (cParams.searchLength>3) ?
- 0 : MIN(ZSTD_HASHLOG3_MAX, cParams.windowLog);
- size_t const h3Size = ((size_t)1) << hashLog3;
- size_t const entropySpace = sizeof(ZSTD_entropyCTables_t);
- size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
+ size_t const entropySpace = HUF_WORKSPACE_SIZE;
+ size_t const blockStateSpace = 2 * sizeof(ZSTD_compressedBlockState_t);
+ size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 1);
- size_t const optBudget =
- ((MaxML+1) + (MaxLL+1) + (MaxOff+1) + (1<<Litbits))*sizeof(U32)
- + (ZSTD_OPT_NUM+1)*(sizeof(ZSTD_match_t) + sizeof(ZSTD_optimal_t));
- size_t const optSpace = ((cParams.strategy == ZSTD_btopt) || (cParams.strategy == ZSTD_btultra)) ? optBudget : 0;
+ size_t const ldmSpace = ZSTD_ldm_getTableSize(params->ldmParams);
+ size_t const ldmSeqSpace = ZSTD_ldm_getMaxNbSeq(params->ldmParams, blockSize) * sizeof(rawSeq);
- size_t const ldmSpace = params->ldmParams.enableLdm ?
- ZSTD_ldm_getTableSize(params->ldmParams.hashLog,
- params->ldmParams.bucketSizeLog) : 0;
-
- size_t const neededSpace = entropySpace + tableSpace + tokenSpace +
- optSpace + ldmSpace;
+ size_t const neededSpace = entropySpace + blockStateSpace + tokenSpace +
+ matchStateSize + ldmSpace + ldmSeqSpace;
DEBUGLOG(5, "sizeof(ZSTD_CCtx) : %u", (U32)sizeof(ZSTD_CCtx));
DEBUGLOG(5, "estimate workSpace : %u", (U32)neededSpace);
@@ -696,15 +716,26 @@ size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams)
return ZSTD_estimateCCtxSize_usingCCtxParams(&params);
}
-size_t ZSTD_estimateCCtxSize(int compressionLevel)
+static size_t ZSTD_estimateCCtxSize_internal(int compressionLevel)
{
ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, 0);
return ZSTD_estimateCCtxSize_usingCParams(cParams);
}
+size_t ZSTD_estimateCCtxSize(int compressionLevel)
+{
+ int level;
+ size_t memBudget = 0;
+ for (level=1; level<=compressionLevel; level++) {
+ size_t const newMB = ZSTD_estimateCCtxSize_internal(level);
+ if (newMB > memBudget) memBudget = newMB;
+ }
+ return memBudget;
+}
+
size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params)
{
- if (params->nbThreads > 1) { return ERROR(GENERIC); }
+ if (params->nbWorkers > 0) { return ERROR(GENERIC); }
{ size_t const CCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params);
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << params->cParams.windowLog);
size_t const inBuffSize = ((size_t)1 << params->cParams.windowLog) + blockSize;
@@ -721,11 +752,44 @@ size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams)
return ZSTD_estimateCStreamSize_usingCCtxParams(&params);
}
-size_t ZSTD_estimateCStreamSize(int compressionLevel) {
+static size_t ZSTD_estimateCStreamSize_internal(int compressionLevel) {
ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, 0);
return ZSTD_estimateCStreamSize_usingCParams(cParams);
}
+size_t ZSTD_estimateCStreamSize(int compressionLevel) {
+ int level;
+ size_t memBudget = 0;
+ for (level=1; level<=compressionLevel; level++) {
+ size_t const newMB = ZSTD_estimateCStreamSize_internal(level);
+ if (newMB > memBudget) memBudget = newMB;
+ }
+ return memBudget;
+}
+
+/* ZSTD_getFrameProgression():
+ * tells how much data has been consumed (input) and produced (output) for current frame.
+ * able to count progression inside worker threads (non-blocking mode).
+ */
+ZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx)
+{
+#ifdef ZSTD_MULTITHREAD
+ if (cctx->appliedParams.nbWorkers > 0) {
+ return ZSTDMT_getFrameProgression(cctx->mtctx);
+ }
+#endif
+ { ZSTD_frameProgression fp;
+ size_t const buffered = (cctx->inBuff == NULL) ? 0 :
+ cctx->inBuffPos - cctx->inToCompress;
+ if (buffered) assert(cctx->inBuffPos >= cctx->inToCompress);
+ assert(buffered <= ZSTD_BLOCKSIZE_MAX);
+ fp.ingested = cctx->consumedSrcSize + buffered;
+ fp.consumed = cctx->consumedSrcSize;
+ fp.produced = cctx->producedCSize;
+ return fp;
+} }
+
+
static U32 ZSTD_equivalentCParams(ZSTD_compressionParameters cParams1,
ZSTD_compressionParameters cParams2)
{
@@ -761,9 +825,9 @@ static U32 ZSTD_sufficientBuff(size_t bufferSize1, size_t blockSize1,
size_t const windowSize2 = MAX(1, (size_t)MIN(((U64)1 << cParams2.windowLog), pledgedSrcSize));
size_t const blockSize2 = MIN(ZSTD_BLOCKSIZE_MAX, windowSize2);
size_t const neededBufferSize2 = (buffPol2==ZSTDb_buffered) ? windowSize2 + blockSize2 : 0;
- DEBUGLOG(4, "ZSTD_sufficientBuff: windowSize2=%u from wlog=%u",
+ DEBUGLOG(4, "ZSTD_sufficientBuff: is windowSize2=%u <= wlog1=%u",
(U32)windowSize2, cParams2.windowLog);
- DEBUGLOG(4, "ZSTD_sufficientBuff: blockSize2 %u <=? blockSize1 %u",
+ DEBUGLOG(4, "ZSTD_sufficientBuff: is blockSize2=%u <= blockSize1=%u",
(U32)blockSize2, (U32)blockSize1);
return (blockSize2 <= blockSize1) /* seqStore space depends on blockSize */
& (neededBufferSize2 <= bufferSize1);
@@ -782,37 +846,101 @@ static U32 ZSTD_equivalentParams(ZSTD_CCtx_params params1,
ZSTD_sufficientBuff(buffSize1, blockSize1, buffPol2, params2.cParams, pledgedSrcSize);
}
+static void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs)
+{
+ int i;
+ for (i = 0; i < ZSTD_REP_NUM; ++i)
+ bs->rep[i] = repStartValue[i];
+ bs->entropy.hufCTable_repeatMode = HUF_repeat_none;
+ bs->entropy.offcode_repeatMode = FSE_repeat_none;
+ bs->entropy.matchlength_repeatMode = FSE_repeat_none;
+ bs->entropy.litlength_repeatMode = FSE_repeat_none;
+}
+
+/*! ZSTD_invalidateMatchState()
+ * Invalidate all the matches in the match finder tables.
+ * Requires nextSrc and base to be set (can be NULL).
+ */
+static void ZSTD_invalidateMatchState(ZSTD_matchState_t* ms)
+{
+ ZSTD_window_clear(&ms->window);
+
+ ms->nextToUpdate = ms->window.dictLimit + 1;
+ ms->loadedDictEnd = 0;
+ ms->opt.litLengthSum = 0; /* force reset of btopt stats */
+}
+
/*! ZSTD_continueCCtx() :
* reuse CCtx without reset (note : requires no dictionary) */
static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_CCtx_params params, U64 pledgedSrcSize)
{
- U32 const end = (U32)(cctx->nextSrc - cctx->base);
size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << params.cParams.windowLog), pledgedSrcSize));
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize);
- DEBUGLOG(4, "ZSTD_continueCCtx");
+ DEBUGLOG(4, "ZSTD_continueCCtx: re-use context in place");
cctx->blockSize = blockSize; /* previous block size could be different even for same windowLog, due to pledgedSrcSize */
cctx->appliedParams = params;
cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
cctx->consumedSrcSize = 0;
+ cctx->producedCSize = 0;
if (pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN)
cctx->appliedParams.fParams.contentSizeFlag = 0;
DEBUGLOG(4, "pledged content size : %u ; flag : %u",
(U32)pledgedSrcSize, cctx->appliedParams.fParams.contentSizeFlag);
- cctx->lowLimit = end;
- cctx->dictLimit = end;
- cctx->nextToUpdate = end+1;
cctx->stage = ZSTDcs_init;
cctx->dictID = 0;
- cctx->loadedDictEnd = 0;
- { int i; for (i=0; i<ZSTD_REP_NUM; i++) cctx->seqStore.rep[i] = repStartValue[i]; }
- cctx->optState.litLengthSum = 0; /* force reset of btopt stats */
+ if (params.ldmParams.enableLdm)
+ ZSTD_window_clear(&cctx->ldmState.window);
+ ZSTD_referenceExternalSequences(cctx, NULL, 0);
+ ZSTD_invalidateMatchState(&cctx->blockState.matchState);
+ ZSTD_reset_compressedBlockState(cctx->blockState.prevCBlock);
XXH64_reset(&cctx->xxhState, 0);
return 0;
}
typedef enum { ZSTDcrp_continue, ZSTDcrp_noMemset } ZSTD_compResetPolicy_e;
+static void* ZSTD_reset_matchState(ZSTD_matchState_t* ms, void* ptr, ZSTD_compressionParameters const* cParams, ZSTD_compResetPolicy_e const crp, U32 const forCCtx)
+{
+ size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog);
+ size_t const hSize = ((size_t)1) << cParams->hashLog;
+ U32 const hashLog3 = (forCCtx && cParams->searchLength==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;
+ size_t const h3Size = ((size_t)1) << hashLog3;
+ size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
+
+ assert(((size_t)ptr & 3) == 0);
+
+ ms->hashLog3 = hashLog3;
+ memset(&ms->window, 0, sizeof(ms->window));
+ ZSTD_invalidateMatchState(ms);
+
+ /* opt parser space */
+ if (forCCtx && ((cParams->strategy == ZSTD_btopt) | (cParams->strategy == ZSTD_btultra))) {
+ DEBUGLOG(4, "reserving optimal parser space");
+ ms->opt.litFreq = (U32*)ptr;
+ ms->opt.litLengthFreq = ms->opt.litFreq + (1<<Litbits);
+ ms->opt.matchLengthFreq = ms->opt.litLengthFreq + (MaxLL+1);
+ ms->opt.offCodeFreq = ms->opt.matchLengthFreq + (MaxML+1);
+ ptr = ms->opt.offCodeFreq + (MaxOff+1);
+ ms->opt.matchTable = (ZSTD_match_t*)ptr;
+ ptr = ms->opt.matchTable + ZSTD_OPT_NUM+1;
+ ms->opt.priceTable = (ZSTD_optimal_t*)ptr;
+ ptr = ms->opt.priceTable + ZSTD_OPT_NUM+1;
+ }
+
+ /* table Space */
+ DEBUGLOG(4, "reset table : %u", crp!=ZSTDcrp_noMemset);
+ assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
+ if (crp!=ZSTDcrp_noMemset) memset(ptr, 0, tableSpace); /* reset tables only */
+ ms->hashTable = (U32*)(ptr);
+ ms->chainTable = ms->hashTable + hSize;
+ ms->hashTable3 = ms->chainTable + chainSize;
+ ptr = ms->hashTable3 + h3Size;
+
+ assert(((size_t)ptr & 3) == 0);
+ return ptr;
+}
+
/*! ZSTD_resetCCtx_internal() :
note : `params` are assumed fully validated at this stage */
static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
@@ -830,19 +958,14 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
zbuff, pledgedSrcSize)) {
DEBUGLOG(4, "ZSTD_equivalentParams()==1 -> continue mode (wLog1=%u, blockSize1=%u)",
zc->appliedParams.cParams.windowLog, (U32)zc->blockSize);
- assert(!(params.ldmParams.enableLdm &&
- params.ldmParams.hashEveryLog == ZSTD_LDM_HASHEVERYLOG_NOTSET));
- zc->entropy->hufCTable_repeatMode = HUF_repeat_none;
- zc->entropy->offcode_repeatMode = FSE_repeat_none;
- zc->entropy->matchlength_repeatMode = FSE_repeat_none;
- zc->entropy->litlength_repeatMode = FSE_repeat_none;
return ZSTD_continueCCtx(zc, params, pledgedSrcSize);
} }
DEBUGLOG(4, "ZSTD_equivalentParams()==0 -> reset CCtx");
if (params.ldmParams.enableLdm) {
/* Adjust long distance matching parameters */
- ZSTD_ldm_adjustParameters(&params.ldmParams, params.cParams.windowLog);
+ params.ldmParams.windowLog = params.cParams.windowLog;
+ ZSTD_ldm_adjustParameters(&params.ldmParams, &params.cParams);
assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog);
assert(params.ldmParams.hashEveryLog < 32);
zc->ldmState.hashPower =
@@ -854,34 +977,25 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
U32 const divider = (params.cParams.searchLength==3) ? 3 : 4;
size_t const maxNbSeq = blockSize / divider;
size_t const tokenSpace = blockSize + 11*maxNbSeq;
- size_t const chainSize = (params.cParams.strategy == ZSTD_fast) ?
- 0 : ((size_t)1 << params.cParams.chainLog);
- size_t const hSize = ((size_t)1) << params.cParams.hashLog;
- U32 const hashLog3 = (params.cParams.searchLength>3) ?
- 0 : MIN(ZSTD_HASHLOG3_MAX, params.cParams.windowLog);
- size_t const h3Size = ((size_t)1) << hashLog3;
- size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
size_t const buffOutSize = (zbuff==ZSTDb_buffered) ? ZSTD_compressBound(blockSize)+1 : 0;
size_t const buffInSize = (zbuff==ZSTDb_buffered) ? windowSize + blockSize : 0;
+ size_t const matchStateSize = ZSTD_sizeof_matchState(&params.cParams, /* forCCtx */ 1);
+ size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(params.ldmParams, blockSize);
void* ptr;
/* Check if workSpace is large enough, alloc a new one if needed */
- { size_t const entropySpace = sizeof(ZSTD_entropyCTables_t);
- size_t const optPotentialSpace = ((MaxML+1) + (MaxLL+1) + (MaxOff+1) + (1<<Litbits)) * sizeof(U32)
- + (ZSTD_OPT_NUM+1) * (sizeof(ZSTD_match_t)+sizeof(ZSTD_optimal_t));
- size_t const optSpace = ( (params.cParams.strategy == ZSTD_btopt)
- || (params.cParams.strategy == ZSTD_btultra)) ?
- optPotentialSpace : 0;
+ { size_t const entropySpace = HUF_WORKSPACE_SIZE;
+ size_t const blockStateSpace = 2 * sizeof(ZSTD_compressedBlockState_t);
size_t const bufferSpace = buffInSize + buffOutSize;
- size_t const ldmSpace = params.ldmParams.enableLdm
- ? ZSTD_ldm_getTableSize(params.ldmParams.hashLog, params.ldmParams.bucketSizeLog)
- : 0;
- size_t const neededSpace = entropySpace + optSpace + ldmSpace +
- tableSpace + tokenSpace + bufferSpace;
- DEBUGLOG(4, "Need %uKB workspace, including %uKB for tables, and %uKB for buffers",
- (U32)(neededSpace>>10), (U32)(tableSpace>>10), (U32)(bufferSpace>>10));
- DEBUGLOG(4, "chainSize: %u - hSize: %u - h3Size: %u - windowSize: %u - blockSize: %u",
- (U32)chainSize, (U32)hSize, (U32)h3Size, (U32)windowSize, (U32)blockSize);
+ size_t const ldmSpace = ZSTD_ldm_getTableSize(params.ldmParams);
+ size_t const ldmSeqSpace = maxNbLdmSeq * sizeof(rawSeq);
+
+ size_t const neededSpace = entropySpace + blockStateSpace + ldmSpace +
+ ldmSeqSpace + matchStateSize + tokenSpace +
+ bufferSpace;
+ DEBUGLOG(4, "Need %uKB workspace, including %uKB for match state, and %uKB for buffers",
+ (U32)(neededSpace>>10), (U32)(matchStateSize>>10), (U32)(bufferSpace>>10));
+ DEBUGLOG(4, "windowSize: %u - blockSize: %u", (U32)windowSize, (U32)blockSize);
if (zc->workSpaceSize < neededSpace) { /* too small : resize */
DEBUGLOG(4, "Need to update workSpaceSize from %uK to %uK",
@@ -897,16 +1011,20 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
zc->workSpaceSize = neededSpace;
ptr = zc->workSpace;
- /* entropy space */
+ /* Statically sized space. entropyWorkspace never moves (but prev/next block swap places) */
assert(((size_t)zc->workSpace & 3) == 0); /* ensure correct alignment */
- assert(zc->workSpaceSize >= sizeof(ZSTD_entropyCTables_t));
- zc->entropy = (ZSTD_entropyCTables_t*)zc->workSpace;
+ assert(zc->workSpaceSize >= 2 * sizeof(ZSTD_compressedBlockState_t));
+ zc->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)zc->workSpace;
+ zc->blockState.nextCBlock = zc->blockState.prevCBlock + 1;
+ ptr = zc->blockState.nextCBlock + 1;
+ zc->entropyWorkspace = (U32*)ptr;
} }
/* init params */
zc->appliedParams = params;
zc->pledgedSrcSizePlusOne = pledgedSrcSize+1;
zc->consumedSrcSize = 0;
+ zc->producedCSize = 0;
if (pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN)
zc->appliedParams.fParams.contentSizeFlag = 0;
DEBUGLOG(4, "pledged content size : %u ; flag : %u",
@@ -916,37 +1034,10 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
XXH64_reset(&zc->xxhState, 0);
zc->stage = ZSTDcs_init;
zc->dictID = 0;
- zc->loadedDictEnd = 0;
- zc->entropy->hufCTable_repeatMode = HUF_repeat_none;
- zc->entropy->offcode_repeatMode = FSE_repeat_none;
- zc->entropy->matchlength_repeatMode = FSE_repeat_none;
- zc->entropy->litlength_repeatMode = FSE_repeat_none;
- zc->nextToUpdate = 1;
- zc->nextSrc = NULL;
- zc->base = NULL;
- zc->dictBase = NULL;
- zc->dictLimit = 0;
- zc->lowLimit = 0;
- { int i; for (i=0; i<ZSTD_REP_NUM; i++) zc->seqStore.rep[i] = repStartValue[i]; }
- zc->hashLog3 = hashLog3;
- zc->optState.litLengthSum = 0;
-
- ptr = zc->entropy + 1;
-
- /* opt parser space */
- if ((params.cParams.strategy == ZSTD_btopt) || (params.cParams.strategy == ZSTD_btultra)) {
- DEBUGLOG(4, "reserving optimal parser space");
- assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
- zc->optState.litFreq = (U32*)ptr;
- zc->optState.litLengthFreq = zc->optState.litFreq + (1<<Litbits);
- zc->optState.matchLengthFreq = zc->optState.litLengthFreq + (MaxLL+1);
- zc->optState.offCodeFreq = zc->optState.matchLengthFreq + (MaxML+1);
- ptr = zc->optState.offCodeFreq + (MaxOff+1);
- zc->optState.matchTable = (ZSTD_match_t*)ptr;
- ptr = zc->optState.matchTable + ZSTD_OPT_NUM+1;
- zc->optState.priceTable = (ZSTD_optimal_t*)ptr;
- ptr = zc->optState.priceTable + ZSTD_OPT_NUM+1;
- }
+
+ ZSTD_reset_compressedBlockState(zc->blockState.prevCBlock);
+
+ ptr = zc->entropyWorkspace + HUF_WORKSPACE_SIZE_U32;
/* ldm hash table */
/* initialize bucketOffsets table later for pointer alignment */
@@ -956,16 +1047,15 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
zc->ldmState.hashTable = (ldmEntry_t*)ptr;
ptr = zc->ldmState.hashTable + ldmHSize;
+ zc->ldmSequences = (rawSeq*)ptr;
+ ptr = zc->ldmSequences + maxNbLdmSeq;
+ zc->maxNbLdmSequences = maxNbLdmSeq;
+
+ memset(&zc->ldmState.window, 0, sizeof(zc->ldmState.window));
}
+ assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
- /* table Space */
- DEBUGLOG(4, "reset table : %u", crp!=ZSTDcrp_noMemset);
- if (crp!=ZSTDcrp_noMemset) memset(ptr, 0, tableSpace); /* reset tables only */
- assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
- zc->hashTable = (U32*)(ptr);
- zc->chainTable = zc->hashTable + hSize;
- zc->hashTable3 = zc->chainTable + chainSize;
- ptr = zc->hashTable3 + h3Size;
+ ptr = ZSTD_reset_matchState(&zc->blockState.matchState, ptr, &params.cParams, crp, /* forCCtx */ 1);
/* sequences storage */
zc->seqStore.sequencesStart = (seqDef*)ptr;
@@ -984,7 +1074,9 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
memset(ptr, 0, ldmBucketSize);
zc->ldmState.bucketOffsets = (BYTE*)ptr;
ptr = zc->ldmState.bucketOffsets + ldmBucketSize;
+ ZSTD_window_clear(&zc->ldmState.window);
}
+ ZSTD_referenceExternalSequences(zc, NULL, 0);
/* buffers */
zc->inBuffSize = buffInSize;
@@ -1002,9 +1094,61 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
* do not use with extDict variant ! */
void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx) {
int i;
- for (i=0; i<ZSTD_REP_NUM; i++) cctx->seqStore.rep[i] = 0;
+ for (i=0; i<ZSTD_REP_NUM; i++) cctx->blockState.prevCBlock->rep[i] = 0;
+ assert(!ZSTD_window_hasExtDict(cctx->blockState.matchState.window));
}
+static size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx,
+ const ZSTD_CDict* cdict,
+ unsigned windowLog,
+ ZSTD_frameParameters fParams,
+ U64 pledgedSrcSize,
+ ZSTD_buffered_policy_e zbuff)
+{
+ { ZSTD_CCtx_params params = cctx->requestedParams;
+ /* Copy only compression parameters related to tables. */
+ params.cParams = cdict->cParams;
+ if (windowLog) params.cParams.windowLog = windowLog;
+ params.fParams = fParams;
+ ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
+ ZSTDcrp_noMemset, zbuff);
+ assert(cctx->appliedParams.cParams.strategy == cdict->cParams.strategy);
+ assert(cctx->appliedParams.cParams.hashLog == cdict->cParams.hashLog);
+ assert(cctx->appliedParams.cParams.chainLog == cdict->cParams.chainLog);
+ }
+
+ /* copy tables */
+ { size_t const chainSize = (cdict->cParams.strategy == ZSTD_fast) ? 0 : ((size_t)1 << cdict->cParams.chainLog);
+ size_t const hSize = (size_t)1 << cdict->cParams.hashLog;
+ size_t const tableSpace = (chainSize + hSize) * sizeof(U32);
+ assert((U32*)cctx->blockState.matchState.chainTable == (U32*)cctx->blockState.matchState.hashTable + hSize); /* chainTable must follow hashTable */
+ assert((U32*)cctx->blockState.matchState.hashTable3 == (U32*)cctx->blockState.matchState.chainTable + chainSize);
+ assert((U32*)cdict->matchState.chainTable == (U32*)cdict->matchState.hashTable + hSize); /* chainTable must follow hashTable */
+ assert((U32*)cdict->matchState.hashTable3 == (U32*)cdict->matchState.chainTable + chainSize);
+ memcpy(cctx->blockState.matchState.hashTable, cdict->matchState.hashTable, tableSpace); /* presumes all tables follow each other */
+ }
+ /* Zero the hashTable3, since the cdict never fills it */
+ { size_t const h3Size = (size_t)1 << cctx->blockState.matchState.hashLog3;
+ assert(cdict->matchState.hashLog3 == 0);
+ memset(cctx->blockState.matchState.hashTable3, 0, h3Size * sizeof(U32));
+ }
+
+ /* copy dictionary offsets */
+ {
+ ZSTD_matchState_t const* srcMatchState = &cdict->matchState;
+ ZSTD_matchState_t* dstMatchState = &cctx->blockState.matchState;
+ dstMatchState->window = srcMatchState->window;
+ dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;
+ dstMatchState->nextToUpdate3= srcMatchState->nextToUpdate3;
+ dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;
+ }
+ cctx->dictID = cdict->dictID;
+
+ /* copy block state */
+ memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState));
+
+ return 0;
+}
/*! ZSTD_copyCCtx_internal() :
* Duplicate an existing context `srcCCtx` into another one `dstCCtx`.
@@ -1015,7 +1159,6 @@ void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx) {
* @return : 0, or an error code */
static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
const ZSTD_CCtx* srcCCtx,
- unsigned windowLog,
ZSTD_frameParameters fParams,
U64 pledgedSrcSize,
ZSTD_buffered_policy_e zbuff)
@@ -1027,41 +1170,39 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
{ ZSTD_CCtx_params params = dstCCtx->requestedParams;
/* Copy only compression parameters related to tables. */
params.cParams = srcCCtx->appliedParams.cParams;
- if (windowLog) params.cParams.windowLog = windowLog;
params.fParams = fParams;
ZSTD_resetCCtx_internal(dstCCtx, params, pledgedSrcSize,
ZSTDcrp_noMemset, zbuff);
+ assert(dstCCtx->appliedParams.cParams.windowLog == srcCCtx->appliedParams.cParams.windowLog);
+ assert(dstCCtx->appliedParams.cParams.strategy == srcCCtx->appliedParams.cParams.strategy);
+ assert(dstCCtx->appliedParams.cParams.hashLog == srcCCtx->appliedParams.cParams.hashLog);
+ assert(dstCCtx->appliedParams.cParams.chainLog == srcCCtx->appliedParams.cParams.chainLog);
+ assert(dstCCtx->blockState.matchState.hashLog3 == srcCCtx->blockState.matchState.hashLog3);
}
/* copy tables */
{ size_t const chainSize = (srcCCtx->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : ((size_t)1 << srcCCtx->appliedParams.cParams.chainLog);
size_t const hSize = (size_t)1 << srcCCtx->appliedParams.cParams.hashLog;
- size_t const h3Size = (size_t)1 << srcCCtx->hashLog3;
+ size_t const h3Size = (size_t)1 << srcCCtx->blockState.matchState.hashLog3;
size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
- assert((U32*)dstCCtx->chainTable == (U32*)dstCCtx->hashTable + hSize); /* chainTable must follow hashTable */
- assert((U32*)dstCCtx->hashTable3 == (U32*)dstCCtx->chainTable + chainSize);
- memcpy(dstCCtx->hashTable, srcCCtx->hashTable, tableSpace); /* presumes all tables follow each other */
+ assert((U32*)dstCCtx->blockState.matchState.chainTable == (U32*)dstCCtx->blockState.matchState.hashTable + hSize); /* chainTable must follow hashTable */
+ assert((U32*)dstCCtx->blockState.matchState.hashTable3 == (U32*)dstCCtx->blockState.matchState.chainTable + chainSize);
+ memcpy(dstCCtx->blockState.matchState.hashTable, srcCCtx->blockState.matchState.hashTable, tableSpace); /* presumes all tables follow each other */
}
/* copy dictionary offsets */
- dstCCtx->nextToUpdate = srcCCtx->nextToUpdate;
- dstCCtx->nextToUpdate3= srcCCtx->nextToUpdate3;
- dstCCtx->nextSrc = srcCCtx->nextSrc;
- dstCCtx->base = srcCCtx->base;
- dstCCtx->dictBase = srcCCtx->dictBase;
- dstCCtx->dictLimit = srcCCtx->dictLimit;
- dstCCtx->lowLimit = srcCCtx->lowLimit;
- dstCCtx->loadedDictEnd= srcCCtx->loadedDictEnd;
- dstCCtx->dictID = srcCCtx->dictID;
-
- /* copy entropy tables */
- memcpy(dstCCtx->entropy, srcCCtx->entropy, sizeof(ZSTD_entropyCTables_t));
- /* copy repcodes */
{
- int i;
- for (i = 0; i < ZSTD_REP_NUM; ++i)
- dstCCtx->seqStore.rep[i] = srcCCtx->seqStore.rep[i];
+ ZSTD_matchState_t const* srcMatchState = &srcCCtx->blockState.matchState;
+ ZSTD_matchState_t* dstMatchState = &dstCCtx->blockState.matchState;
+ dstMatchState->window = srcMatchState->window;
+ dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;
+ dstMatchState->nextToUpdate3= srcMatchState->nextToUpdate3;
+ dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;
}
+ dstCCtx->dictID = srcCCtx->dictID;
+
+ /* copy block state */
+ memcpy(dstCCtx->blockState.prevCBlock, srcCCtx->blockState.prevCBlock, sizeof(*srcCCtx->blockState.prevCBlock));
return 0;
}
@@ -1080,51 +1221,69 @@ size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx, unsigned long
fParams.contentSizeFlag = (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN);
return ZSTD_copyCCtx_internal(dstCCtx, srcCCtx,
- 0 /*windowLog from srcCCtx*/, fParams, pledgedSrcSize,
+ fParams, pledgedSrcSize,
zbuff);
}
+#define ZSTD_ROWSIZE 16
/*! ZSTD_reduceTable() :
- * reduce table indexes by `reducerValue` */
-static void ZSTD_reduceTable (U32* const table, U32 const size, U32 const reducerValue)
+ * reduce table indexes by `reducerValue`, or squash to zero.
+ * PreserveMark preserves "unsorted mark" for btlazy2 strategy.
+ * It must be set to a clear 0/1 value, to remove branch during inlining.
+ * Presume table size is a multiple of ZSTD_ROWSIZE
+ * to help auto-vectorization */
+FORCE_INLINE_TEMPLATE void
+ZSTD_reduceTable_internal (U32* const table, U32 const size, U32 const reducerValue, int const preserveMark)
+{
+ int const nbRows = (int)size / ZSTD_ROWSIZE;
+ int cellNb = 0;
+ int rowNb;
+ assert((size & (ZSTD_ROWSIZE-1)) == 0); /* multiple of ZSTD_ROWSIZE */
+ assert(size < (1U<<31)); /* can be casted to int */
+ for (rowNb=0 ; rowNb < nbRows ; rowNb++) {
+ int column;
+ for (column=0; column<ZSTD_ROWSIZE; column++) {
+ if (preserveMark) {
+ U32 const adder = (table[cellNb] == ZSTD_DUBT_UNSORTED_MARK) ? reducerValue : 0;
+ table[cellNb] += adder;
+ }
+ if (table[cellNb] < reducerValue) table[cellNb] = 0;
+ else table[cellNb] -= reducerValue;
+ cellNb++;
+ } }
+}
+
+static void ZSTD_reduceTable(U32* const table, U32 const size, U32 const reducerValue)
{
- U32 u;
- for (u=0 ; u < size ; u++) {
- if (table[u] < reducerValue) table[u] = 0;
- else table[u] -= reducerValue;
- }
+ ZSTD_reduceTable_internal(table, size, reducerValue, 0);
}
-/*! ZSTD_ldm_reduceTable() :
- * reduce table indexes by `reducerValue` */
-static void ZSTD_ldm_reduceTable(ldmEntry_t* const table, U32 const size,
- U32 const reducerValue)
+static void ZSTD_reduceTable_btlazy2(U32* const table, U32 const size, U32 const reducerValue)
{
- U32 u;
- for (u = 0; u < size; u++) {
- if (table[u].offset < reducerValue) table[u].offset = 0;
- else table[u].offset -= reducerValue;
- }
+ ZSTD_reduceTable_internal(table, size, reducerValue, 1);
}
/*! ZSTD_reduceIndex() :
* rescale all indexes to avoid future overflow (indexes are U32) */
static void ZSTD_reduceIndex (ZSTD_CCtx* zc, const U32 reducerValue)
{
- { U32 const hSize = (U32)1 << zc->appliedParams.cParams.hashLog;
- ZSTD_reduceTable(zc->hashTable, hSize, reducerValue); }
-
- { U32 const chainSize = (zc->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : ((U32)1 << zc->appliedParams.cParams.chainLog);
- ZSTD_reduceTable(zc->chainTable, chainSize, reducerValue); }
+ ZSTD_matchState_t* const ms = &zc->blockState.matchState;
+ { U32 const hSize = (U32)1 << zc->appliedParams.cParams.hashLog;
+ ZSTD_reduceTable(ms->hashTable, hSize, reducerValue);
+ }
- { U32 const h3Size = (zc->hashLog3) ? (U32)1 << zc->hashLog3 : 0;
- ZSTD_reduceTable(zc->hashTable3, h3Size, reducerValue); }
+ if (zc->appliedParams.cParams.strategy != ZSTD_fast) {
+ U32 const chainSize = (U32)1 << zc->appliedParams.cParams.chainLog;
+ if (zc->appliedParams.cParams.strategy == ZSTD_btlazy2)
+ ZSTD_reduceTable_btlazy2(ms->chainTable, chainSize, reducerValue);
+ else
+ ZSTD_reduceTable(ms->chainTable, chainSize, reducerValue);
+ }
- { if (zc->appliedParams.ldmParams.enableLdm) {
- U32 const ldmHSize = (U32)1 << zc->appliedParams.ldmParams.hashLog;
- ZSTD_ldm_reduceTable(zc->ldmState.hashTable, ldmHSize, reducerValue);
- }
+ if (ms->hashLog3) {
+ U32 const h3Size = (U32)1 << ms->hashLog3;
+ ZSTD_reduceTable(ms->hashTable3, h3Size, reducerValue);
}
}
@@ -1199,10 +1358,12 @@ static size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, cons
static size_t ZSTD_minGain(size_t srcSize) { return (srcSize >> 6) + 2; }
-static size_t ZSTD_compressLiterals (ZSTD_entropyCTables_t * entropy,
- ZSTD_strategy strategy,
+static size_t ZSTD_compressLiterals (ZSTD_entropyCTables_t const* prevEntropy,
+ ZSTD_entropyCTables_t* nextEntropy,
+ ZSTD_strategy strategy, int disableLiteralCompression,
void* dst, size_t dstCapacity,
- const void* src, size_t srcSize)
+ const void* src, size_t srcSize,
+ U32* workspace, const int bmi2)
{
size_t const minGain = ZSTD_minGain(srcSize);
size_t const lhSize = 3 + (srcSize >= 1 KB) + (srcSize >= 16 KB);
@@ -1211,34 +1372,51 @@ static size_t ZSTD_compressLiterals (ZSTD_entropyCTables_t * entropy,
symbolEncodingType_e hType = set_compressed;
size_t cLitSize;
+ DEBUGLOG(5,"ZSTD_compressLiterals (disableLiteralCompression=%i)",
+ disableLiteralCompression);
+
+ /* Prepare nextEntropy assuming reusing the existing table */
+ nextEntropy->hufCTable_repeatMode = prevEntropy->hufCTable_repeatMode;
+ memcpy(nextEntropy->hufCTable, prevEntropy->hufCTable,
+ sizeof(prevEntropy->hufCTable));
+
+ if (disableLiteralCompression)
+ return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
/* small ? don't even attempt compression (speed opt) */
-# define LITERAL_NOENTROPY 63
- { size_t const minLitSize = entropy->hufCTable_repeatMode == HUF_repeat_valid ? 6 : LITERAL_NOENTROPY;
+# define COMPRESS_LITERALS_SIZE_MIN 63
+ { size_t const minLitSize = (prevEntropy->hufCTable_repeatMode == HUF_repeat_valid) ? 6 : COMPRESS_LITERALS_SIZE_MIN;
if (srcSize <= minLitSize) return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
}
if (dstCapacity < lhSize+1) return ERROR(dstSize_tooSmall); /* not enough space for compression */
- { HUF_repeat repeat = entropy->hufCTable_repeatMode;
+ { HUF_repeat repeat = prevEntropy->hufCTable_repeatMode;
int const preferRepeat = strategy < ZSTD_lazy ? srcSize <= 1024 : 0;
if (repeat == HUF_repeat_valid && lhSize == 3) singleStream = 1;
cLitSize = singleStream ? HUF_compress1X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11,
- entropy->workspace, sizeof(entropy->workspace), (HUF_CElt*)entropy->hufCTable, &repeat, preferRepeat)
+ workspace, HUF_WORKSPACE_SIZE, (HUF_CElt*)nextEntropy->hufCTable, &repeat, preferRepeat, bmi2)
: HUF_compress4X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11,
- entropy->workspace, sizeof(entropy->workspace), (HUF_CElt*)entropy->hufCTable, &repeat, preferRepeat);
- if (repeat != HUF_repeat_none) { hType = set_repeat; } /* reused the existing table */
- else { entropy->hufCTable_repeatMode = HUF_repeat_check; } /* now have a table to reuse */
+ workspace, HUF_WORKSPACE_SIZE, (HUF_CElt*)nextEntropy->hufCTable, &repeat, preferRepeat, bmi2);
+ if (repeat != HUF_repeat_none) {
+ /* reused the existing table */
+ hType = set_repeat;
+ }
}
if ((cLitSize==0) | (cLitSize >= srcSize - minGain) | ERR_isError(cLitSize)) {
- entropy->hufCTable_repeatMode = HUF_repeat_none;
+ memcpy(nextEntropy->hufCTable, prevEntropy->hufCTable, sizeof(prevEntropy->hufCTable));
return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
}
if (cLitSize==1) {
- entropy->hufCTable_repeatMode = HUF_repeat_none;
+ memcpy(nextEntropy->hufCTable, prevEntropy->hufCTable, sizeof(prevEntropy->hufCTable));
return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize);
}
+ if (hType == set_compressed) {
+ /* using a newly constructed table */
+ nextEntropy->hufCTable_repeatMode = HUF_repeat_check;
+ }
+
/* Build header */
switch(lhSize)
{
@@ -1332,10 +1510,11 @@ symbolEncodingType_e ZSTD_selectEncodingType(
MEM_STATIC
size_t ZSTD_buildCTable(void* dst, size_t dstCapacity,
- FSE_CTable* CTable, U32 FSELog, symbolEncodingType_e type,
+ FSE_CTable* nextCTable, U32 FSELog, symbolEncodingType_e type,
U32* count, U32 max,
BYTE const* codeTable, size_t nbSeq,
S16 const* defaultNorm, U32 defaultNormLog, U32 defaultMax,
+ FSE_CTable const* prevCTable, size_t prevCTableSize,
void* workspace, size_t workspaceSize)
{
BYTE* op = (BYTE*)dst;
@@ -1344,12 +1523,13 @@ size_t ZSTD_buildCTable(void* dst, size_t dstCapacity,
switch (type) {
case set_rle:
*op = codeTable[0];
- CHECK_F(FSE_buildCTable_rle(CTable, (BYTE)max));
+ CHECK_F(FSE_buildCTable_rle(nextCTable, (BYTE)max));
return 1;
case set_repeat:
+ memcpy(nextCTable, prevCTable, prevCTableSize);
return 0;
case set_basic:
- CHECK_F(FSE_buildCTable_wksp(CTable, defaultNorm, defaultMax, defaultNormLog, workspace, workspaceSize)); /* note : could be pre-calculated */
+ CHECK_F(FSE_buildCTable_wksp(nextCTable, defaultNorm, defaultMax, defaultNormLog, workspace, workspaceSize)); /* note : could be pre-calculated */
return 0;
case set_compressed: {
S16 norm[MaxSeq + 1];
@@ -1363,7 +1543,7 @@ size_t ZSTD_buildCTable(void* dst, size_t dstCapacity,
CHECK_F(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max));
{ size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */
if (FSE_isError(NCountSize)) return NCountSize;
- CHECK_F(FSE_buildCTable_wksp(CTable, norm, max, tableLog, workspace, workspaceSize));
+ CHECK_F(FSE_buildCTable_wksp(nextCTable, norm, max, tableLog, workspace, workspaceSize));
return NCountSize;
}
}
@@ -1371,8 +1551,8 @@ size_t ZSTD_buildCTable(void* dst, size_t dstCapacity,
}
}
-MEM_STATIC
-size_t ZSTD_encodeSequences(
+FORCE_INLINE_TEMPLATE size_t
+ZSTD_encodeSequences_body(
void* dst, size_t dstCapacity,
FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
@@ -1419,7 +1599,8 @@ size_t ZSTD_encodeSequences(
DEBUGLOG(6, "encoding: litlen:%2u - matchlen:%2u - offCode:%7u",
sequences[n].litLength,
sequences[n].matchLength + MINMATCH,
- sequences[n].offset); /* 32b*/ /* 64b*/
+ sequences[n].offset);
+ /* 32b*/ /* 64b*/
/* (7)*/ /* (7)*/
FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode); /* 15 */ /* 15 */
FSE_encodeSymbol(&blockStream, &stateMatchLength, mlCode); /* 24 */ /* 24 */
@@ -1445,8 +1626,11 @@ size_t ZSTD_encodeSequences(
BIT_flushBits(&blockStream); /* (7)*/
} }
+ DEBUGLOG(6, "ZSTD_encodeSequences: flushing ML state with %u bits", stateMatchLength.stateLog);
FSE_flushCState(&blockStream, &stateMatchLength);
+ DEBUGLOG(6, "ZSTD_encodeSequences: flushing Off state with %u bits", stateOffsetBits.stateLog);
FSE_flushCState(&blockStream, &stateOffsetBits);
+ DEBUGLOG(6, "ZSTD_encodeSequences: flushing LL state with %u bits", stateLitLength.stateLog);
FSE_flushCState(&blockStream, &stateLitLength);
{ size_t const streamSize = BIT_closeCStream(&blockStream);
@@ -1455,16 +1639,77 @@ size_t ZSTD_encodeSequences(
}
}
+static size_t
+ZSTD_encodeSequences_default(
+ void* dst, size_t dstCapacity,
+ FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
+ FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
+ FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
+ seqDef const* sequences, size_t nbSeq, int longOffsets)
+{
+ return ZSTD_encodeSequences_body(dst, dstCapacity,
+ CTable_MatchLength, mlCodeTable,
+ CTable_OffsetBits, ofCodeTable,
+ CTable_LitLength, llCodeTable,
+ sequences, nbSeq, longOffsets);
+}
+
+
+#if DYNAMIC_BMI2
+
+static TARGET_ATTRIBUTE("bmi2") size_t
+ZSTD_encodeSequences_bmi2(
+ void* dst, size_t dstCapacity,
+ FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
+ FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
+ FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
+ seqDef const* sequences, size_t nbSeq, int longOffsets)
+{
+ return ZSTD_encodeSequences_body(dst, dstCapacity,
+ CTable_MatchLength, mlCodeTable,
+ CTable_OffsetBits, ofCodeTable,
+ CTable_LitLength, llCodeTable,
+ sequences, nbSeq, longOffsets);
+}
+
+#endif
+
+size_t ZSTD_encodeSequences(
+ void* dst, size_t dstCapacity,
+ FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
+ FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
+ FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
+ seqDef const* sequences, size_t nbSeq, int longOffsets, int bmi2)
+{
+#if DYNAMIC_BMI2
+ if (bmi2) {
+ return ZSTD_encodeSequences_bmi2(dst, dstCapacity,
+ CTable_MatchLength, mlCodeTable,
+ CTable_OffsetBits, ofCodeTable,
+ CTable_LitLength, llCodeTable,
+ sequences, nbSeq, longOffsets);
+ }
+#endif
+ (void)bmi2;
+ return ZSTD_encodeSequences_default(dst, dstCapacity,
+ CTable_MatchLength, mlCodeTable,
+ CTable_OffsetBits, ofCodeTable,
+ CTable_LitLength, llCodeTable,
+ sequences, nbSeq, longOffsets);
+}
+
MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
- ZSTD_entropyCTables_t* entropy,
- ZSTD_compressionParameters const* cParams,
- void* dst, size_t dstCapacity)
+ ZSTD_entropyCTables_t const* prevEntropy,
+ ZSTD_entropyCTables_t* nextEntropy,
+ ZSTD_CCtx_params const* cctxParams,
+ void* dst, size_t dstCapacity, U32* workspace,
+ const int bmi2)
{
- const int longOffsets = cParams->windowLog > STREAM_ACCUMULATOR_MIN;
+ const int longOffsets = cctxParams->cParams.windowLog > STREAM_ACCUMULATOR_MIN;
U32 count[MaxSeq+1];
- FSE_CTable* CTable_LitLength = entropy->litlengthCTable;
- FSE_CTable* CTable_OffsetBits = entropy->offcodeCTable;
- FSE_CTable* CTable_MatchLength = entropy->matchlengthCTable;
+ FSE_CTable* CTable_LitLength = nextEntropy->litlengthCTable;
+ FSE_CTable* CTable_OffsetBits = nextEntropy->offcodeCTable;
+ FSE_CTable* CTable_MatchLength = nextEntropy->matchlengthCTable;
U32 LLtype, Offtype, MLtype; /* compressed, raw or rle */
const seqDef* const sequences = seqStorePtr->sequencesStart;
const BYTE* const ofCodeTable = seqStorePtr->ofCode;
@@ -1476,13 +1721,17 @@ MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
size_t const nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart;
BYTE* seqHead;
- ZSTD_STATIC_ASSERT(sizeof(entropy->workspace) >= (1<<MAX(MLFSELog,LLFSELog)));
+ ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));
/* Compress literals */
{ const BYTE* const literals = seqStorePtr->litStart;
size_t const litSize = seqStorePtr->lit - literals;
size_t const cSize = ZSTD_compressLiterals(
- entropy, cParams->strategy, op, dstCapacity, literals, litSize);
+ prevEntropy, nextEntropy,
+ cctxParams->cParams.strategy, cctxParams->disableLiteralCompression,
+ op, dstCapacity,
+ literals, litSize,
+ workspace, bmi2);
if (ZSTD_isError(cSize))
return cSize;
assert(cSize <= dstCapacity);
@@ -1497,7 +1746,15 @@ MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2;
else
op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3;
- if (nbSeq==0) return op - ostart;
+ if (nbSeq==0) {
+ memcpy(nextEntropy->litlengthCTable, prevEntropy->litlengthCTable, sizeof(prevEntropy->litlengthCTable));
+ nextEntropy->litlength_repeatMode = prevEntropy->litlength_repeatMode;
+ memcpy(nextEntropy->offcodeCTable, prevEntropy->offcodeCTable, sizeof(prevEntropy->offcodeCTable));
+ nextEntropy->offcode_repeatMode = prevEntropy->offcode_repeatMode;
+ memcpy(nextEntropy->matchlengthCTable, prevEntropy->matchlengthCTable, sizeof(prevEntropy->matchlengthCTable));
+ nextEntropy->matchlength_repeatMode = prevEntropy->matchlength_repeatMode;
+ return op - ostart;
+ }
/* seqHead : flags for FSE encoding type */
seqHead = op++;
@@ -1506,36 +1763,42 @@ MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
ZSTD_seqToCodes(seqStorePtr);
/* build CTable for Literal Lengths */
{ U32 max = MaxLL;
- size_t const mostFrequent = FSE_countFast_wksp(count, &max, llCodeTable, nbSeq, entropy->workspace);
+ size_t const mostFrequent = FSE_countFast_wksp(count, &max, llCodeTable, nbSeq, workspace);
DEBUGLOG(5, "Building LL table");
- LLtype = ZSTD_selectEncodingType(&entropy->litlength_repeatMode, mostFrequent, nbSeq, LL_defaultNormLog, ZSTD_defaultAllowed);
+ nextEntropy->litlength_repeatMode = prevEntropy->litlength_repeatMode;
+ LLtype = ZSTD_selectEncodingType(&nextEntropy->litlength_repeatMode, mostFrequent, nbSeq, LL_defaultNormLog, ZSTD_defaultAllowed);
{ size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype,
count, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL,
- entropy->workspace, sizeof(entropy->workspace));
+ prevEntropy->litlengthCTable, sizeof(prevEntropy->litlengthCTable),
+ workspace, HUF_WORKSPACE_SIZE);
if (ZSTD_isError(countSize)) return countSize;
op += countSize;
} }
/* build CTable for Offsets */
{ U32 max = MaxOff;
- size_t const mostFrequent = FSE_countFast_wksp(count, &max, ofCodeTable, nbSeq, entropy->workspace);
+ size_t const mostFrequent = FSE_countFast_wksp(count, &max, ofCodeTable, nbSeq, workspace);
/* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */
ZSTD_defaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed;
DEBUGLOG(5, "Building OF table");
- Offtype = ZSTD_selectEncodingType(&entropy->offcode_repeatMode, mostFrequent, nbSeq, OF_defaultNormLog, defaultPolicy);
+ nextEntropy->offcode_repeatMode = prevEntropy->offcode_repeatMode;
+ Offtype = ZSTD_selectEncodingType(&nextEntropy->offcode_repeatMode, mostFrequent, nbSeq, OF_defaultNormLog, defaultPolicy);
{ size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype,
count, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
- entropy->workspace, sizeof(entropy->workspace));
+ prevEntropy->offcodeCTable, sizeof(prevEntropy->offcodeCTable),
+ workspace, HUF_WORKSPACE_SIZE);
if (ZSTD_isError(countSize)) return countSize;
op += countSize;
} }
/* build CTable for MatchLengths */
{ U32 max = MaxML;
- size_t const mostFrequent = FSE_countFast_wksp(count, &max, mlCodeTable, nbSeq, entropy->workspace);
+ size_t const mostFrequent = FSE_countFast_wksp(count, &max, mlCodeTable, nbSeq, workspace);
DEBUGLOG(5, "Building ML table");
- MLtype = ZSTD_selectEncodingType(&entropy->matchlength_repeatMode, mostFrequent, nbSeq, ML_defaultNormLog, ZSTD_defaultAllowed);
+ nextEntropy->matchlength_repeatMode = prevEntropy->matchlength_repeatMode;
+ MLtype = ZSTD_selectEncodingType(&nextEntropy->matchlength_repeatMode, mostFrequent, nbSeq, ML_defaultNormLog, ZSTD_defaultAllowed);
{ size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype,
count, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML,
- entropy->workspace, sizeof(entropy->workspace));
+ prevEntropy->matchlengthCTable, sizeof(prevEntropy->matchlengthCTable),
+ workspace, HUF_WORKSPACE_SIZE);
if (ZSTD_isError(countSize)) return countSize;
op += countSize;
} }
@@ -1548,7 +1811,7 @@ MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
CTable_OffsetBits, ofCodeTable,
CTable_LitLength, llCodeTable,
sequences, nbSeq,
- longOffsets);
+ longOffsets, bmi2);
if (ZSTD_isError(bitstreamSize)) return bitstreamSize;
op += bitstreamSize;
}
@@ -1557,48 +1820,40 @@ MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
}
MEM_STATIC size_t ZSTD_compressSequences(seqStore_t* seqStorePtr,
- ZSTD_entropyCTables_t* entropy,
- ZSTD_compressionParameters const* cParams,
+ ZSTD_entropyCTables_t const* prevEntropy,
+ ZSTD_entropyCTables_t* nextEntropy,
+ ZSTD_CCtx_params const* cctxParams,
void* dst, size_t dstCapacity,
- size_t srcSize)
+ size_t srcSize, U32* workspace, int bmi2)
{
- size_t const cSize = ZSTD_compressSequences_internal(seqStorePtr, entropy, cParams,
- dst, dstCapacity);
- /* If the srcSize <= dstCapacity, then there is enough space to write a
- * raw uncompressed block. Since we ran out of space, the block must not
- * be compressible, so fall back to a raw uncompressed block.
+ size_t const cSize = ZSTD_compressSequences_internal(
+ seqStorePtr, prevEntropy, nextEntropy, cctxParams, dst, dstCapacity,
+ workspace, bmi2);
+ /* When srcSize <= dstCapacity, there is enough space to write a raw uncompressed block.
+ * Since we ran out of space, block must be not compressible, so fall back to raw uncompressed block.
*/
- int const uncompressibleError = (cSize == ERROR(dstSize_tooSmall)) && (srcSize <= dstCapacity);
- if (ZSTD_isError(cSize) && !uncompressibleError)
- return cSize;
+ if ((cSize == ERROR(dstSize_tooSmall)) & (srcSize <= dstCapacity))
+ return 0; /* block not compressed */
+ if (ZSTD_isError(cSize)) return cSize;
+
+ /* Check compressibility */
+ { size_t const maxCSize = srcSize - ZSTD_minGain(srcSize); /* note : fixed formula, maybe should depend on compression level, or strategy */
+ if (cSize >= maxCSize) return 0; /* block not compressed */
+ }
+
/* We check that dictionaries have offset codes available for the first
* block. After the first block, the offcode table might not have large
* enough codes to represent the offsets in the data.
*/
- if (entropy->offcode_repeatMode == FSE_repeat_valid)
- entropy->offcode_repeatMode = FSE_repeat_check;
-
- /* Check compressibility */
- { size_t const minGain = ZSTD_minGain(srcSize); /* note : fixed formula, maybe should depend on compression level, or strategy */
- size_t const maxCSize = srcSize - minGain;
- if (cSize >= maxCSize || uncompressibleError) {
- entropy->hufCTable_repeatMode = HUF_repeat_none;
- entropy->offcode_repeatMode = FSE_repeat_none;
- entropy->matchlength_repeatMode = FSE_repeat_none;
- entropy->litlength_repeatMode = FSE_repeat_none;
- return 0; /* block not compressed */
- } }
- assert(!ZSTD_isError(cSize));
+ if (nextEntropy->offcode_repeatMode == FSE_repeat_valid)
+ nextEntropy->offcode_repeatMode = FSE_repeat_check;
- /* block is compressed => confirm repcodes in history */
- { int i; for (i=0; i<ZSTD_REP_NUM; i++) seqStorePtr->rep[i] = seqStorePtr->repToConfirm[i]; }
return cSize;
}
/* ZSTD_selectBlockCompressor() :
* Not static, but internal use only (used by long distance matcher)
* assumption : strat is a valid strategy */
-typedef size_t (*ZSTD_blockCompressor) (ZSTD_CCtx* ctx, const void* src, size_t srcSize);
ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict)
{
static const ZSTD_blockCompressor blockCompressor[2][(unsigned)ZSTD_btultra+1] = {
@@ -1632,32 +1887,83 @@ static void ZSTD_resetSeqStore(seqStore_t* ssPtr)
ssPtr->longLengthID = 0;
}
-static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
+static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize)
{
- DEBUGLOG(5, "ZSTD_compressBlock_internal : dstCapacity = %u", (U32)dstCapacity);
- if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1)
+ ZSTD_matchState_t* const ms = &zc->blockState.matchState;
+ DEBUGLOG(5, "ZSTD_compressBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)",
+ (U32)dstCapacity, ms->window.dictLimit, ms->nextToUpdate);
+ if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) {
+ ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.searchLength);
return 0; /* don't even attempt compression below a certain srcSize */
+ }
ZSTD_resetSeqStore(&(zc->seqStore));
/* limited update after a very long match */
- { const BYTE* const base = zc->base;
+ { const BYTE* const base = ms->window.base;
const BYTE* const istart = (const BYTE*)src;
const U32 current = (U32)(istart-base);
- if (current > zc->nextToUpdate + 384)
- zc->nextToUpdate = current - MIN(192, (U32)(current - zc->nextToUpdate - 384));
+ if (current > ms->nextToUpdate + 384)
+ ms->nextToUpdate = current - MIN(192, (U32)(current - ms->nextToUpdate - 384));
}
- /* find and store sequences */
- { U32 const extDict = zc->lowLimit < zc->dictLimit;
- const ZSTD_blockCompressor blockCompressor =
- zc->appliedParams.ldmParams.enableLdm
- ? (extDict ? ZSTD_compressBlock_ldm_extDict : ZSTD_compressBlock_ldm)
- : ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, extDict);
- size_t const lastLLSize = blockCompressor(zc, src, srcSize);
- const BYTE* const anchor = (const BYTE*)src + srcSize - lastLLSize;
- ZSTD_storeLastLiterals(&zc->seqStore, anchor, lastLLSize);
+
+ /* select and store sequences */
+ { U32 const extDict = ZSTD_window_hasExtDict(ms->window);
+ size_t lastLLSize;
+ { int i;
+ for (i = 0; i < ZSTD_REP_NUM; ++i)
+ zc->blockState.nextCBlock->rep[i] = zc->blockState.prevCBlock->rep[i];
+ }
+ if (zc->externSeqStore.pos < zc->externSeqStore.size) {
+ assert(!zc->appliedParams.ldmParams.enableLdm);
+ /* Updates ldmSeqStore.pos */
+ lastLLSize =
+ ZSTD_ldm_blockCompress(&zc->externSeqStore,
+ ms, &zc->seqStore,
+ zc->blockState.nextCBlock->rep,
+ &zc->appliedParams.cParams,
+ src, srcSize, extDict);
+ assert(zc->externSeqStore.pos <= zc->externSeqStore.size);
+ } else if (zc->appliedParams.ldmParams.enableLdm) {
+ rawSeqStore_t ldmSeqStore = {NULL, 0, 0, 0};
+
+ ldmSeqStore.seq = zc->ldmSequences;
+ ldmSeqStore.capacity = zc->maxNbLdmSequences;
+ /* Updates ldmSeqStore.size */
+ CHECK_F(ZSTD_ldm_generateSequences(&zc->ldmState, &ldmSeqStore,
+ &zc->appliedParams.ldmParams,
+ src, srcSize));
+ /* Updates ldmSeqStore.pos */
+ lastLLSize =
+ ZSTD_ldm_blockCompress(&ldmSeqStore,
+ ms, &zc->seqStore,
+ zc->blockState.nextCBlock->rep,
+ &zc->appliedParams.cParams,
+ src, srcSize, extDict);
+ assert(ldmSeqStore.pos == ldmSeqStore.size);
+ } else { /* not long range mode */
+ ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, extDict);
+ lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, &zc->appliedParams.cParams, src, srcSize);
+ }
+ { const BYTE* const lastLiterals = (const BYTE*)src + srcSize - lastLLSize;
+ ZSTD_storeLastLiterals(&zc->seqStore, lastLiterals, lastLLSize);
+ } }
+
+ /* encode sequences and literals */
+ { size_t const cSize = ZSTD_compressSequences(&zc->seqStore,
+ &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy,
+ &zc->appliedParams,
+ dst, dstCapacity,
+ srcSize, zc->entropyWorkspace, zc->bmi2);
+ if (ZSTD_isError(cSize) || cSize == 0) return cSize;
+ /* confirm repcodes and entropy tables */
+ { ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock;
+ zc->blockState.prevCBlock = zc->blockState.nextCBlock;
+ zc->blockState.nextCBlock = tmp;
+ }
+ return cSize;
}
- /* encode */
- return ZSTD_compressSequences(&zc->seqStore, zc->entropy, &zc->appliedParams.cParams, dst, dstCapacity, srcSize);
}
@@ -1686,54 +1992,27 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
XXH64_update(&cctx->xxhState, src, srcSize);
while (remaining) {
+ ZSTD_matchState_t* const ms = &cctx->blockState.matchState;
U32 const lastBlock = lastFrameChunk & (blockSize >= remaining);
if (dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE)
return ERROR(dstSize_tooSmall); /* not enough space to store compressed block */
if (remaining < blockSize) blockSize = remaining;
- /* preemptive overflow correction:
- * 1. correction is large enough:
- * lowLimit > (3<<29) ==> current > 3<<29 + 1<<windowLog - blockSize
- * 1<<windowLog <= newCurrent < 1<<chainLog + 1<<windowLog
- *
- * current - newCurrent
- * > (3<<29 + 1<<windowLog - blockSize) - (1<<windowLog + 1<<chainLog)
- * > (3<<29 - blockSize) - (1<<chainLog)
- * > (3<<29 - blockSize) - (1<<30) (NOTE: chainLog <= 30)
- * > 1<<29 - 1<<17
- *
- * 2. (ip+blockSize - cctx->base) doesn't overflow:
- * In 32 bit mode we limit windowLog to 30 so we don't get
- * differences larger than 1<<31-1.
- * 3. cctx->lowLimit < 1<<32:
- * windowLog <= 31 ==> 3<<29 + 1<<windowLog < 7<<29 < 1<<32.
- */
- if (cctx->lowLimit > (3U<<29)) {
- U32 const cycleMask = ((U32)1 << ZSTD_cycleLog(cctx->appliedParams.cParams.chainLog, cctx->appliedParams.cParams.strategy)) - 1;
- U32 const current = (U32)(ip - cctx->base);
- U32 const newCurrent = (current & cycleMask) + ((U32)1 << cctx->appliedParams.cParams.windowLog);
- U32 const correction = current - newCurrent;
+ if (ZSTD_window_needOverflowCorrection(ms->window, ip + blockSize)) {
+ U32 const cycleLog = ZSTD_cycleLog(cctx->appliedParams.cParams.chainLog, cctx->appliedParams.cParams.strategy);
+ U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, maxDist, ip);
ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
- assert(current > newCurrent);
- assert(correction > 1<<28); /* Loose bound, should be about 1<<29 */
+
ZSTD_reduceIndex(cctx, correction);
- cctx->base += correction;
- cctx->dictBase += correction;
- cctx->lowLimit -= correction;
- cctx->dictLimit -= correction;
- if (cctx->nextToUpdate < correction) cctx->nextToUpdate = 0;
- else cctx->nextToUpdate -= correction;
- DEBUGLOG(4, "Correction of 0x%x bytes to lowLimit=0x%x\n", correction, cctx->lowLimit);
- }
- /* enforce maxDist */
- if ((U32)(ip+blockSize - cctx->base) > cctx->loadedDictEnd + maxDist) {
- U32 const newLowLimit = (U32)(ip+blockSize - cctx->base) - maxDist;
- if (cctx->lowLimit < newLowLimit) cctx->lowLimit = newLowLimit;
- if (cctx->dictLimit < cctx->lowLimit) cctx->dictLimit = cctx->lowLimit;
+ if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;
+ else ms->nextToUpdate -= correction;
+ ms->loadedDictEnd = 0;
}
+ ZSTD_window_enforceMaxDist(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd);
+ if (ms->nextToUpdate < ms->window.lowLimit) ms->nextToUpdate = ms->window.lowLimit;
{ size_t cSize = ZSTD_compressBlock_internal(cctx,
op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize,
@@ -1810,16 +2089,44 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
return pos;
}
+/* ZSTD_writeLastEmptyBlock() :
+ * output an empty Block with end-of-frame mark to complete a frame
+ * @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h))
+ * or an error code if `dstCapcity` is too small (<ZSTD_blockHeaderSize)
+ */
+size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity)
+{
+ if (dstCapacity < ZSTD_blockHeaderSize) return ERROR(dstSize_tooSmall);
+ { U32 const cBlockHeader24 = 1 /*lastBlock*/ + (((U32)bt_raw)<<1); /* 0 size */
+ MEM_writeLE24(dst, cBlockHeader24);
+ return ZSTD_blockHeaderSize;
+ }
+}
+
+size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq)
+{
+ if (cctx->stage != ZSTDcs_init)
+ return ERROR(stage_wrong);
+ if (cctx->appliedParams.ldmParams.enableLdm)
+ return ERROR(parameter_unsupported);
+ cctx->externSeqStore.seq = seq;
+ cctx->externSeqStore.size = nbSeq;
+ cctx->externSeqStore.capacity = nbSeq;
+ cctx->externSeqStore.pos = 0;
+ return 0;
+}
+
static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
U32 frame, U32 lastFrameChunk)
{
- const BYTE* const ip = (const BYTE*) src;
+ ZSTD_matchState_t* ms = &cctx->blockState.matchState;
size_t fhSize = 0;
- DEBUGLOG(5, "ZSTD_compressContinue_internal, stage: %u", cctx->stage);
+ DEBUGLOG(5, "ZSTD_compressContinue_internal, stage: %u, srcSize: %u",
+ cctx->stage, (U32)srcSize);
if (cctx->stage==ZSTDcs_created) return ERROR(stage_wrong); /* missing init (ZSTD_compressBegin) */
if (frame && (cctx->stage==ZSTDcs_init)) {
@@ -1833,26 +2140,11 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
if (!srcSize) return fhSize; /* do not generate an empty block if no input */
- /* Check if blocks follow each other */
- if (src != cctx->nextSrc) {
- /* not contiguous */
- size_t const distanceFromBase = (size_t)(cctx->nextSrc - cctx->base);
- cctx->lowLimit = cctx->dictLimit;
- assert(distanceFromBase == (size_t)(U32)distanceFromBase); /* should never overflow */
- cctx->dictLimit = (U32)distanceFromBase;
- cctx->dictBase = cctx->base;
- cctx->base = ip - distanceFromBase;
- cctx->nextToUpdate = cctx->dictLimit;
- if (cctx->dictLimit - cctx->lowLimit < HASH_READ_SIZE) cctx->lowLimit = cctx->dictLimit; /* too small extDict */
- }
- cctx->nextSrc = ip + srcSize;
-
- /* if input and dictionary overlap : reduce dictionary (area presumed modified by input) */
- if ((ip+srcSize > cctx->dictBase + cctx->lowLimit) & (ip < cctx->dictBase + cctx->dictLimit)) {
- ptrdiff_t const highInputIdx = (ip + srcSize) - cctx->dictBase;
- U32 const lowLimitMax = (highInputIdx > (ptrdiff_t)cctx->dictLimit) ? cctx->dictLimit : (U32)highInputIdx;
- cctx->lowLimit = lowLimitMax;
+ if (!ZSTD_window_update(&ms->window, src, srcSize)) {
+ ms->nextToUpdate = ms->window.dictLimit;
}
+ if (cctx->appliedParams.ldmParams.enableLdm)
+ ZSTD_window_update(&cctx->ldmState.window, src, srcSize);
DEBUGLOG(5, "ZSTD_compressContinue_internal (blockSize=%u)", (U32)cctx->blockSize);
{ size_t const cSize = frame ?
@@ -1860,6 +2152,14 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize);
if (ZSTD_isError(cSize)) return cSize;
cctx->consumedSrcSize += srcSize;
+ cctx->producedCSize += (cSize + fhSize);
+ if (cctx->appliedParams.fParams.contentSizeFlag) { /* control src size */
+ if (cctx->consumedSrcSize+1 > cctx->pledgedSrcSizePlusOne) {
+ DEBUGLOG(4, "error : pledgedSrcSize = %u, while realSrcSize >= %u",
+ (U32)cctx->pledgedSrcSizePlusOne-1, (U32)cctx->consumedSrcSize);
+ return ERROR(srcSize_wrong);
+ }
+ }
return cSize + fhSize;
}
}
@@ -1868,14 +2168,15 @@ size_t ZSTD_compressContinue (ZSTD_CCtx* cctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize)
{
+ DEBUGLOG(5, "ZSTD_compressContinue (srcSize=%u)", (U32)srcSize);
return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 1 /* frame mode */, 0 /* last chunk */);
}
size_t ZSTD_getBlockSize(const ZSTD_CCtx* cctx)
{
- ZSTD_compressionParameters const cParams =
- ZSTD_getCParamsFromCCtxParams(cctx->appliedParams, 0, 0);
+ ZSTD_compressionParameters const cParams = cctx->appliedParams.cParams;
+ assert(!ZSTD_checkCParams(cParams));
return MIN (ZSTD_BLOCKSIZE_MAX, (U32)1 << cParams.windowLog);
}
@@ -1889,50 +2190,45 @@ size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const
/*! ZSTD_loadDictionaryContent() :
* @return : 0, or an error code
*/
-static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t srcSize)
+static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms, ZSTD_CCtx_params const* params, const void* src, size_t srcSize)
{
const BYTE* const ip = (const BYTE*) src;
const BYTE* const iend = ip + srcSize;
+ ZSTD_compressionParameters const* cParams = &params->cParams;
- /* input becomes current prefix */
- zc->lowLimit = zc->dictLimit;
- zc->dictLimit = (U32)(zc->nextSrc - zc->base);
- zc->dictBase = zc->base;
- zc->base = ip - zc->dictLimit;
- zc->nextToUpdate = zc->dictLimit;
- zc->loadedDictEnd = zc->appliedParams.forceWindow ? 0 : (U32)(iend - zc->base);
+ ZSTD_window_update(&ms->window, src, srcSize);
+ ms->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ms->window.base);
- zc->nextSrc = iend;
if (srcSize <= HASH_READ_SIZE) return 0;
- switch(zc->appliedParams.cParams.strategy)
+ switch(params->cParams.strategy)
{
case ZSTD_fast:
- ZSTD_fillHashTable (zc, iend, zc->appliedParams.cParams.searchLength);
+ ZSTD_fillHashTable(ms, cParams, iend);
break;
case ZSTD_dfast:
- ZSTD_fillDoubleHashTable (zc, iend, zc->appliedParams.cParams.searchLength);
+ ZSTD_fillDoubleHashTable(ms, cParams, iend);
break;
case ZSTD_greedy:
case ZSTD_lazy:
case ZSTD_lazy2:
if (srcSize >= HASH_READ_SIZE)
- ZSTD_insertAndFindFirstIndex(zc, iend-HASH_READ_SIZE, zc->appliedParams.cParams.searchLength);
+ ZSTD_insertAndFindFirstIndex(ms, cParams, iend-HASH_READ_SIZE);
break;
- case ZSTD_btlazy2:
+ case ZSTD_btlazy2: /* we want the dictionary table fully sorted */
case ZSTD_btopt:
case ZSTD_btultra:
if (srcSize >= HASH_READ_SIZE)
- ZSTD_updateTree(zc, iend-HASH_READ_SIZE, iend, (U32)1 << zc->appliedParams.cParams.searchLog, zc->appliedParams.cParams.searchLength);
+ ZSTD_updateTree(ms, cParams, iend-HASH_READ_SIZE, iend);
break;
default:
assert(0); /* not possible : not a valid strategy id */
}
- zc->nextToUpdate = (U32)(iend - zc->base);
+ ms->nextToUpdate = (U32)(iend - ms->window.base);
return 0;
}
@@ -1956,25 +2252,26 @@ static size_t ZSTD_checkDictNCount(short* normalizedCounter, unsigned dictMaxSym
* https://github.com/facebook/zstd/blob/master/doc/zstd_compression_format.md#dictionary-format
*/
/*! ZSTD_loadZstdDictionary() :
- * @return : 0, or an error code
+ * @return : dictID, or an error code
* assumptions : magic number supposed already checked
* dictSize supposed > 8
*/
-static size_t ZSTD_loadZstdDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
+static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, ZSTD_matchState_t* ms, ZSTD_CCtx_params const* params, const void* dict, size_t dictSize, void* workspace)
{
const BYTE* dictPtr = (const BYTE*)dict;
const BYTE* const dictEnd = dictPtr + dictSize;
short offcodeNCount[MaxOff+1];
unsigned offcodeMaxValue = MaxOff;
+ size_t dictID;
- ZSTD_STATIC_ASSERT(sizeof(cctx->entropy->workspace) >= (1<<MAX(MLFSELog,LLFSELog)));
+ ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));
dictPtr += 4; /* skip magic number */
- cctx->dictID = cctx->appliedParams.fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr);
+ dictID = params->fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr);
dictPtr += 4;
{ unsigned maxSymbolValue = 255;
- size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)cctx->entropy->hufCTable, &maxSymbolValue, dictPtr, dictEnd-dictPtr);
+ size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.hufCTable, &maxSymbolValue, dictPtr, dictEnd-dictPtr);
if (HUF_isError(hufHeaderSize)) return ERROR(dictionary_corrupted);
if (maxSymbolValue < 255) return ERROR(dictionary_corrupted);
dictPtr += hufHeaderSize;
@@ -1985,7 +2282,7 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_CCtx* cctx, const void* dict, size_t
if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
if (offcodeLog > OffFSELog) return ERROR(dictionary_corrupted);
/* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */
- CHECK_E( FSE_buildCTable_wksp(cctx->entropy->offcodeCTable, offcodeNCount, offcodeMaxValue, offcodeLog, cctx->entropy->workspace, sizeof(cctx->entropy->workspace)),
+ CHECK_E( FSE_buildCTable_wksp(bs->entropy.offcodeCTable, offcodeNCount, offcodeMaxValue, offcodeLog, workspace, HUF_WORKSPACE_SIZE),
dictionary_corrupted);
dictPtr += offcodeHeaderSize;
}
@@ -1997,7 +2294,7 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_CCtx* cctx, const void* dict, size_t
if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted);
/* Every match length code must have non-zero probability */
CHECK_F( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML));
- CHECK_E( FSE_buildCTable_wksp(cctx->entropy->matchlengthCTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog, cctx->entropy->workspace, sizeof(cctx->entropy->workspace)),
+ CHECK_E( FSE_buildCTable_wksp(bs->entropy.matchlengthCTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog, workspace, HUF_WORKSPACE_SIZE),
dictionary_corrupted);
dictPtr += matchlengthHeaderSize;
}
@@ -2009,15 +2306,15 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_CCtx* cctx, const void* dict, size_t
if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted);
/* Every literal length code must have non-zero probability */
CHECK_F( ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL));
- CHECK_E( FSE_buildCTable_wksp(cctx->entropy->litlengthCTable, litlengthNCount, litlengthMaxValue, litlengthLog, cctx->entropy->workspace, sizeof(cctx->entropy->workspace)),
+ CHECK_E( FSE_buildCTable_wksp(bs->entropy.litlengthCTable, litlengthNCount, litlengthMaxValue, litlengthLog, workspace, HUF_WORKSPACE_SIZE),
dictionary_corrupted);
dictPtr += litlengthHeaderSize;
}
if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);
- cctx->seqStore.rep[0] = MEM_readLE32(dictPtr+0);
- cctx->seqStore.rep[1] = MEM_readLE32(dictPtr+4);
- cctx->seqStore.rep[2] = MEM_readLE32(dictPtr+8);
+ bs->rep[0] = MEM_readLE32(dictPtr+0);
+ bs->rep[1] = MEM_readLE32(dictPtr+4);
+ bs->rep[2] = MEM_readLE32(dictPtr+8);
dictPtr += 12;
{ size_t const dictContentSize = (size_t)(dictEnd - dictPtr);
@@ -2031,50 +2328,55 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_CCtx* cctx, const void* dict, size_t
/* All repCodes must be <= dictContentSize and != 0*/
{ U32 u;
for (u=0; u<3; u++) {
- if (cctx->seqStore.rep[u] == 0) return ERROR(dictionary_corrupted);
- if (cctx->seqStore.rep[u] > dictContentSize) return ERROR(dictionary_corrupted);
+ if (bs->rep[u] == 0) return ERROR(dictionary_corrupted);
+ if (bs->rep[u] > dictContentSize) return ERROR(dictionary_corrupted);
} }
- cctx->entropy->hufCTable_repeatMode = HUF_repeat_valid;
- cctx->entropy->offcode_repeatMode = FSE_repeat_valid;
- cctx->entropy->matchlength_repeatMode = FSE_repeat_valid;
- cctx->entropy->litlength_repeatMode = FSE_repeat_valid;
- return ZSTD_loadDictionaryContent(cctx, dictPtr, dictContentSize);
+ bs->entropy.hufCTable_repeatMode = HUF_repeat_valid;
+ bs->entropy.offcode_repeatMode = FSE_repeat_valid;
+ bs->entropy.matchlength_repeatMode = FSE_repeat_valid;
+ bs->entropy.litlength_repeatMode = FSE_repeat_valid;
+ CHECK_F(ZSTD_loadDictionaryContent(ms, params, dictPtr, dictContentSize));
+ return dictID;
}
}
/** ZSTD_compress_insertDictionary() :
-* @return : 0, or an error code */
-static size_t ZSTD_compress_insertDictionary(ZSTD_CCtx* cctx,
+* @return : dictID, or an error code */
+static size_t ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs, ZSTD_matchState_t* ms,
+ ZSTD_CCtx_params const* params,
const void* dict, size_t dictSize,
- ZSTD_dictMode_e dictMode)
+ ZSTD_dictContentType_e dictContentType,
+ void* workspace)
{
DEBUGLOG(4, "ZSTD_compress_insertDictionary (dictSize=%u)", (U32)dictSize);
if ((dict==NULL) || (dictSize<=8)) return 0;
+ ZSTD_reset_compressedBlockState(bs);
+
/* dict restricted modes */
- if (dictMode==ZSTD_dm_rawContent)
- return ZSTD_loadDictionaryContent(cctx, dict, dictSize);
+ if (dictContentType == ZSTD_dct_rawContent)
+ return ZSTD_loadDictionaryContent(ms, params, dict, dictSize);
if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) {
- if (dictMode == ZSTD_dm_auto) {
+ if (dictContentType == ZSTD_dct_auto) {
DEBUGLOG(4, "raw content dictionary detected");
- return ZSTD_loadDictionaryContent(cctx, dict, dictSize);
+ return ZSTD_loadDictionaryContent(ms, params, dict, dictSize);
}
- if (dictMode == ZSTD_dm_fullDict)
+ if (dictContentType == ZSTD_dct_fullDict)
return ERROR(dictionary_wrong);
assert(0); /* impossible */
}
/* dict as full zstd dictionary */
- return ZSTD_loadZstdDictionary(cctx, dict, dictSize);
+ return ZSTD_loadZstdDictionary(bs, ms, params, dict, dictSize, workspace);
}
/*! ZSTD_compressBegin_internal() :
* @return : 0, or an error code */
size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
const void* dict, size_t dictSize,
- ZSTD_dictMode_e dictMode,
+ ZSTD_dictContentType_e dictContentType,
const ZSTD_CDict* cdict,
ZSTD_CCtx_params params, U64 pledgedSrcSize,
ZSTD_buffered_policy_e zbuff)
@@ -2086,19 +2388,26 @@ size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
if (cdict && cdict->dictContentSize>0) {
cctx->requestedParams = params;
- return ZSTD_copyCCtx_internal(cctx, cdict->refContext,
- params.cParams.windowLog, params.fParams, pledgedSrcSize,
- zbuff);
+ return ZSTD_resetCCtx_usingCDict(cctx, cdict, params.cParams.windowLog,
+ params.fParams, pledgedSrcSize, zbuff);
}
CHECK_F( ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
ZSTDcrp_continue, zbuff) );
- return ZSTD_compress_insertDictionary(cctx, dict, dictSize, dictMode);
+ {
+ size_t const dictID = ZSTD_compress_insertDictionary(
+ cctx->blockState.prevCBlock, &cctx->blockState.matchState,
+ &params, dict, dictSize, dictContentType, cctx->entropyWorkspace);
+ if (ZSTD_isError(dictID)) return dictID;
+ assert(dictID <= (size_t)(U32)-1);
+ cctx->dictID = (U32)dictID;
+ }
+ return 0;
}
size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,
const void* dict, size_t dictSize,
- ZSTD_dictMode_e dictMode,
+ ZSTD_dictContentType_e dictContentType,
const ZSTD_CDict* cdict,
ZSTD_CCtx_params params,
unsigned long long pledgedSrcSize)
@@ -2107,7 +2416,7 @@ size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,
/* compression parameters verification and optimization */
CHECK_F( ZSTD_checkCParams(params.cParams) );
return ZSTD_compressBegin_internal(cctx,
- dict, dictSize, dictMode,
+ dict, dictSize, dictContentType,
cdict,
params, pledgedSrcSize,
ZSTDb_not_buffered);
@@ -2122,18 +2431,18 @@ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx,
ZSTD_CCtx_params const cctxParams =
ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
return ZSTD_compressBegin_advanced_internal(cctx,
- dict, dictSize, ZSTD_dm_auto,
+ dict, dictSize, ZSTD_dct_auto,
NULL /*cdict*/,
cctxParams, pledgedSrcSize);
}
size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel)
{
- ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, dictSize);
+ ZSTD_parameters const params = ZSTD_getParams(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);
ZSTD_CCtx_params const cctxParams =
ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
- DEBUGLOG(4, "ZSTD_compressBegin_usingDict");
- return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dm_auto, NULL,
+ DEBUGLOG(4, "ZSTD_compressBegin_usingDict (dictSize=%u)", (U32)dictSize);
+ return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dct_auto, NULL,
cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, ZSTDb_not_buffered);
}
@@ -2152,7 +2461,7 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
BYTE* op = ostart;
size_t fhSize = 0;
- DEBUGLOG(5, "ZSTD_writeEpilogue");
+ DEBUGLOG(4, "ZSTD_writeEpilogue");
if (cctx->stage == ZSTDcs_created) return ERROR(stage_wrong); /* init missing */
/* special case : empty frame */
@@ -2176,6 +2485,7 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
if (cctx->appliedParams.fParams.checksumFlag) {
U32 const checksum = (U32) XXH64_digest(&cctx->xxhState);
if (dstCapacity<4) return ERROR(dstSize_tooSmall);
+ DEBUGLOG(4, "ZSTD_writeEpilogue: write checksum : %08X", checksum);
MEM_writeLE32(op, checksum);
op += 4;
}
@@ -2184,7 +2494,6 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
return op-ostart;
}
-
size_t ZSTD_compressEnd (ZSTD_CCtx* cctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize)
@@ -2242,25 +2551,27 @@ size_t ZSTD_compress_advanced_internal(
const void* dict,size_t dictSize,
ZSTD_CCtx_params params)
{
- DEBUGLOG(4, "ZSTD_compress_advanced_internal");
- CHECK_F( ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dm_auto, NULL,
+ DEBUGLOG(4, "ZSTD_compress_advanced_internal (srcSize:%u)",
+ (U32)srcSize);
+ CHECK_F( ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dct_auto, NULL,
params, srcSize, ZSTDb_not_buffered) );
return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
}
-size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize,
+size_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize,
const void* dict, size_t dictSize, int compressionLevel)
{
- ZSTD_parameters params = ZSTD_getParams(compressionLevel, srcSize ? srcSize : 1, dict ? dictSize : 0);
- params.fParams.contentSizeFlag = 1;
- DEBUGLOG(4, "ZSTD_compress_usingDict (level=%i, srcSize=%u, dictSize=%u)",
- compressionLevel, (U32)srcSize, (U32)dictSize);
- return ZSTD_compress_internal(ctx, dst, dstCapacity, src, srcSize, dict, dictSize, params);
+ ZSTD_parameters const params = ZSTD_getParams(compressionLevel, srcSize ? srcSize : 1, dict ? dictSize : 0);
+ ZSTD_CCtx_params cctxParams = ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
+ assert(params.fParams.contentSizeFlag == 1);
+ ZSTD_CCtxParam_setParameter(&cctxParams, ZSTD_p_compressLiterals, compressionLevel>=0);
+ return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, dict, dictSize, cctxParams);
}
-size_t ZSTD_compressCCtx (ZSTD_CCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, int compressionLevel)
+size_t ZSTD_compressCCtx (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, int compressionLevel)
{
- return ZSTD_compress_usingDict(ctx, dst, dstCapacity, src, srcSize, NULL, 0, compressionLevel);
+ DEBUGLOG(4, "ZSTD_compressCCtx (srcSize=%u)", (U32)srcSize);
+ return ZSTD_compress_usingDict(cctx, dst, dstCapacity, src, srcSize, NULL, 0, compressionLevel);
}
size_t ZSTD_compress(void* dst, size_t dstCapacity, const void* src, size_t srcSize, int compressionLevel)
@@ -2284,9 +2595,7 @@ size_t ZSTD_estimateCDictSize_advanced(
ZSTD_dictLoadMethod_e dictLoadMethod)
{
DEBUGLOG(5, "sizeof(ZSTD_CDict) : %u", (U32)sizeof(ZSTD_CDict));
- DEBUGLOG(5, "CCtx estimate : %u",
- (U32)ZSTD_estimateCCtxSize_usingCParams(cParams));
- return sizeof(ZSTD_CDict) + ZSTD_estimateCCtxSize_usingCParams(cParams)
+ return sizeof(ZSTD_CDict) + HUF_WORKSPACE_SIZE + ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0)
+ (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);
}
@@ -2300,23 +2609,24 @@ size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict)
{
if (cdict==NULL) return 0; /* support sizeof on NULL */
DEBUGLOG(5, "sizeof(*cdict) : %u", (U32)sizeof(*cdict));
- DEBUGLOG(5, "ZSTD_sizeof_CCtx : %u", (U32)ZSTD_sizeof_CCtx(cdict->refContext));
- return ZSTD_sizeof_CCtx(cdict->refContext) + (cdict->dictBuffer ? cdict->dictContentSize : 0) + sizeof(*cdict);
+ return cdict->workspaceSize + (cdict->dictBuffer ? cdict->dictContentSize : 0) + sizeof(*cdict);
}
static size_t ZSTD_initCDict_internal(
ZSTD_CDict* cdict,
const void* dictBuffer, size_t dictSize,
ZSTD_dictLoadMethod_e dictLoadMethod,
- ZSTD_dictMode_e dictMode,
+ ZSTD_dictContentType_e dictContentType,
ZSTD_compressionParameters cParams)
{
- DEBUGLOG(3, "ZSTD_initCDict_internal, mode %u", (U32)dictMode);
+ DEBUGLOG(3, "ZSTD_initCDict_internal, dictContentType %u", (U32)dictContentType);
+ assert(!ZSTD_checkCParams(cParams));
+ cdict->cParams = cParams;
if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dictBuffer) || (!dictSize)) {
cdict->dictBuffer = NULL;
cdict->dictContent = dictBuffer;
} else {
- void* const internalBuffer = ZSTD_malloc(dictSize, cdict->refContext->customMem);
+ void* const internalBuffer = ZSTD_malloc(dictSize, cdict->customMem);
cdict->dictBuffer = internalBuffer;
cdict->dictContent = internalBuffer;
if (!internalBuffer) return ERROR(memory_allocation);
@@ -2324,13 +2634,31 @@ static size_t ZSTD_initCDict_internal(
}
cdict->dictContentSize = dictSize;
- { ZSTD_CCtx_params cctxParams = cdict->refContext->requestedParams;
- cctxParams.cParams = cParams;
- CHECK_F( ZSTD_compressBegin_internal(cdict->refContext,
- cdict->dictContent, dictSize, dictMode,
- NULL,
- cctxParams, ZSTD_CONTENTSIZE_UNKNOWN,
- ZSTDb_not_buffered) );
+ /* Reset the state to no dictionary */
+ ZSTD_reset_compressedBlockState(&cdict->cBlockState);
+ { void* const end = ZSTD_reset_matchState(
+ &cdict->matchState,
+ (U32*)cdict->workspace + HUF_WORKSPACE_SIZE_U32,
+ &cParams, ZSTDcrp_continue, /* forCCtx */ 0);
+ assert(end == (char*)cdict->workspace + cdict->workspaceSize);
+ (void)end;
+ }
+ /* (Maybe) load the dictionary
+ * Skips loading the dictionary if it is <= 8 bytes.
+ */
+ { ZSTD_CCtx_params params;
+ memset(&params, 0, sizeof(params));
+ params.compressionLevel = ZSTD_CLEVEL_DEFAULT;
+ params.fParams.contentSizeFlag = 1;
+ params.cParams = cParams;
+ { size_t const dictID = ZSTD_compress_insertDictionary(
+ &cdict->cBlockState, &cdict->matchState, &params,
+ cdict->dictContent, cdict->dictContentSize,
+ dictContentType, cdict->workspace);
+ if (ZSTD_isError(dictID)) return dictID;
+ assert(dictID <= (size_t)(U32)-1);
+ cdict->dictID = (U32)dictID;
+ }
}
return 0;
@@ -2338,24 +2666,27 @@ static size_t ZSTD_initCDict_internal(
ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,
ZSTD_dictLoadMethod_e dictLoadMethod,
- ZSTD_dictMode_e dictMode,
+ ZSTD_dictContentType_e dictContentType,
ZSTD_compressionParameters cParams, ZSTD_customMem customMem)
{
- DEBUGLOG(3, "ZSTD_createCDict_advanced, mode %u", (U32)dictMode);
+ DEBUGLOG(3, "ZSTD_createCDict_advanced, mode %u", (U32)dictContentType);
if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
{ ZSTD_CDict* const cdict = (ZSTD_CDict*)ZSTD_malloc(sizeof(ZSTD_CDict), customMem);
- ZSTD_CCtx* const cctx = ZSTD_createCCtx_advanced(customMem);
+ size_t const workspaceSize = HUF_WORKSPACE_SIZE + ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0);
+ void* const workspace = ZSTD_malloc(workspaceSize, customMem);
- if (!cdict || !cctx) {
+ if (!cdict || !workspace) {
ZSTD_free(cdict, customMem);
- ZSTD_freeCCtx(cctx);
+ ZSTD_free(workspace, customMem);
return NULL;
}
- cdict->refContext = cctx;
+ cdict->customMem = customMem;
+ cdict->workspace = workspace;
+ cdict->workspaceSize = workspaceSize;
if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
dictBuffer, dictSize,
- dictLoadMethod, dictMode,
+ dictLoadMethod, dictContentType,
cParams) )) {
ZSTD_freeCDict(cdict);
return NULL;
@@ -2369,7 +2700,7 @@ ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionL
{
ZSTD_compressionParameters cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
return ZSTD_createCDict_advanced(dict, dictSize,
- ZSTD_dlm_byCopy, ZSTD_dm_auto,
+ ZSTD_dlm_byCopy, ZSTD_dct_auto,
cParams, ZSTD_defaultCMem);
}
@@ -2377,15 +2708,15 @@ ZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int
{
ZSTD_compressionParameters cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
return ZSTD_createCDict_advanced(dict, dictSize,
- ZSTD_dlm_byRef, ZSTD_dm_auto,
+ ZSTD_dlm_byRef, ZSTD_dct_auto,
cParams, ZSTD_defaultCMem);
}
size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
{
if (cdict==NULL) return 0; /* support free on NULL */
- { ZSTD_customMem const cMem = cdict->refContext->customMem;
- ZSTD_freeCCtx(cdict->refContext);
+ { ZSTD_customMem const cMem = cdict->customMem;
+ ZSTD_free(cdict->workspace, cMem);
ZSTD_free(cdict->dictBuffer, cMem);
ZSTD_free(cdict, cMem);
return 0;
@@ -2405,18 +2736,18 @@ size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
* Note : there is no corresponding "free" function.
* Since workspace was allocated externally, it must be freed externally.
*/
-ZSTD_CDict* ZSTD_initStaticCDict(void* workspace, size_t workspaceSize,
+const ZSTD_CDict* ZSTD_initStaticCDict(
+ void* workspace, size_t workspaceSize,
const void* dict, size_t dictSize,
ZSTD_dictLoadMethod_e dictLoadMethod,
- ZSTD_dictMode_e dictMode,
+ ZSTD_dictContentType_e dictContentType,
ZSTD_compressionParameters cParams)
{
- size_t const cctxSize = ZSTD_estimateCCtxSize_usingCParams(cParams);
+ size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0);
size_t const neededSize = sizeof(ZSTD_CDict) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize)
- + cctxSize;
+ + HUF_WORKSPACE_SIZE + matchStateSize;
ZSTD_CDict* const cdict = (ZSTD_CDict*) workspace;
void* ptr;
- DEBUGLOG(4, "(size_t)workspace & 7 : %u", (U32)(size_t)workspace & 7);
if ((size_t)workspace & 7) return NULL; /* 8-aligned */
DEBUGLOG(4, "(workspaceSize < neededSize) : (%u < %u) => %u",
(U32)workspaceSize, (U32)neededSize, (U32)(workspaceSize < neededSize));
@@ -2429,19 +2760,22 @@ ZSTD_CDict* ZSTD_initStaticCDict(void* workspace, size_t workspaceSize,
} else {
ptr = cdict+1;
}
- cdict->refContext = ZSTD_initStaticCCtx(ptr, cctxSize);
+ cdict->workspace = ptr;
+ cdict->workspaceSize = HUF_WORKSPACE_SIZE + matchStateSize;
if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
dict, dictSize,
- ZSTD_dlm_byRef, dictMode,
+ ZSTD_dlm_byRef, dictContentType,
cParams) ))
return NULL;
return cdict;
}
-ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict) {
- return cdict->refContext->appliedParams.cParams;
+ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict)
+{
+ assert(cdict != NULL);
+ return cdict->cParams;
}
/* ZSTD_compressBegin_usingCDict_advanced() :
@@ -2454,9 +2788,18 @@ size_t ZSTD_compressBegin_usingCDict_advanced(
if (cdict==NULL) return ERROR(dictionary_wrong);
{ ZSTD_CCtx_params params = cctx->requestedParams;
params.cParams = ZSTD_getCParamsFromCDict(cdict);
+ /* Increase window log to fit the entire dictionary and source if the
+ * source size is known. Limit the increase to 19, which is the
+ * window log for compression level 1 with the largest source size.
+ */
+ if (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN) {
+ U32 const limitedSrcSize = (U32)MIN(pledgedSrcSize, 1U << 19);
+ U32 const limitedSrcLog = limitedSrcSize > 1 ? ZSTD_highbit32(limitedSrcSize - 1) + 1 : 1;
+ params.cParams.windowLog = MAX(params.cParams.windowLog, limitedSrcLog);
+ }
params.fParams = fParams;
return ZSTD_compressBegin_internal(cctx,
- NULL, 0, ZSTD_dm_auto,
+ NULL, 0, ZSTD_dct_auto,
cdict,
params, pledgedSrcSize,
ZSTDb_not_buffered);
@@ -2534,29 +2877,30 @@ size_t ZSTD_CStreamOutSize(void)
return ZSTD_compressBound(ZSTD_BLOCKSIZE_MAX) + ZSTD_blockHeaderSize + 4 /* 32-bits hash */ ;
}
-static size_t ZSTD_resetCStream_internal(ZSTD_CStream* zcs,
- const void* const dict, size_t const dictSize, ZSTD_dictMode_e const dictMode,
+static size_t ZSTD_resetCStream_internal(ZSTD_CStream* cctx,
+ const void* const dict, size_t const dictSize, ZSTD_dictContentType_e const dictContentType,
const ZSTD_CDict* const cdict,
ZSTD_CCtx_params const params, unsigned long long const pledgedSrcSize)
{
- DEBUGLOG(4, "ZSTD_resetCStream_internal");
+ DEBUGLOG(4, "ZSTD_resetCStream_internal (disableLiteralCompression=%i)",
+ params.disableLiteralCompression);
/* params are supposed to be fully validated at this point */
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
assert(!((dict) && (cdict))); /* either dict or cdict, not both */
- CHECK_F( ZSTD_compressBegin_internal(zcs,
- dict, dictSize, dictMode,
+ CHECK_F( ZSTD_compressBegin_internal(cctx,
+ dict, dictSize, dictContentType,
cdict,
params, pledgedSrcSize,
ZSTDb_buffered) );
- zcs->inToCompress = 0;
- zcs->inBuffPos = 0;
- zcs->inBuffTarget = zcs->blockSize
- + (zcs->blockSize == pledgedSrcSize); /* for small input: avoid automatic flush on reaching end of block, since it would require to add a 3-bytes null block to end frame */
- zcs->outBuffContentSize = zcs->outBuffFlushedSize = 0;
- zcs->streamStage = zcss_load;
- zcs->frameEnded = 0;
+ cctx->inToCompress = 0;
+ cctx->inBuffPos = 0;
+ cctx->inBuffTarget = cctx->blockSize
+ + (cctx->blockSize == pledgedSrcSize); /* for small input: avoid automatic flush on reaching end of block, since it would require to add a 3-bytes null block to end frame */
+ cctx->outBuffContentSize = cctx->outBuffFlushedSize = 0;
+ cctx->streamStage = zcss_load;
+ cctx->frameEnded = 0;
return 0; /* ready to go */
}
@@ -2568,8 +2912,8 @@ size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize)
DEBUGLOG(4, "ZSTD_resetCStream: pledgedSrcSize = %u", (U32)pledgedSrcSize);
if (pledgedSrcSize==0) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN;
params.fParams.contentSizeFlag = 1;
- params.cParams = ZSTD_getCParamsFromCCtxParams(params, pledgedSrcSize, 0);
- return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dm_auto, zcs->cdict, params, pledgedSrcSize);
+ params.cParams = ZSTD_getCParamsFromCCtxParams(&params, pledgedSrcSize, 0);
+ return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dct_auto, zcs->cdict, params, pledgedSrcSize);
}
/*! ZSTD_initCStream_internal() :
@@ -2592,7 +2936,7 @@ size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
}
ZSTD_freeCDict(zcs->cdictLocal);
zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize,
- ZSTD_dlm_byCopy, ZSTD_dm_auto,
+ ZSTD_dlm_byCopy, ZSTD_dct_auto,
params.cParams, zcs->customMem);
zcs->cdict = zcs->cdictLocal;
if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
@@ -2605,10 +2949,7 @@ size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
zcs->cdict = cdict;
}
- params.compressionLevel = ZSTD_CLEVEL_CUSTOM; /* enforce usage of cParams, instead of a dynamic derivation from cLevel (but does that happen ?) */
- zcs->requestedParams = params;
-
- return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dm_auto, zcs->cdict, params, pledgedSrcSize);
+ return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dct_auto, zcs->cdict, params, pledgedSrcSize);
}
/* ZSTD_initCStream_usingCDict_advanced() :
@@ -2637,20 +2978,22 @@ size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)
return ZSTD_initCStream_usingCDict_advanced(zcs, cdict, fParams, ZSTD_CONTENTSIZE_UNKNOWN); /* note : will check that cdict != NULL */
}
+
/* ZSTD_initCStream_advanced() :
- * pledgedSrcSize must be correct.
+ * pledgedSrcSize must be exact.
* if srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN.
* dict is loaded with default parameters ZSTD_dm_auto and ZSTD_dlm_byCopy. */
size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
const void* dict, size_t dictSize,
ZSTD_parameters params, unsigned long long pledgedSrcSize)
{
- ZSTD_CCtx_params const cctxParams = ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
DEBUGLOG(4, "ZSTD_initCStream_advanced: pledgedSrcSize=%u, flag=%u",
(U32)pledgedSrcSize, params.fParams.contentSizeFlag);
CHECK_F( ZSTD_checkCParams(params.cParams) );
if ((pledgedSrcSize==0) && (params.fParams.contentSizeFlag==0)) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN; /* for compatibility with older programs relying on this behavior. Users should now specify ZSTD_CONTENTSIZE_UNKNOWN. This line will be removed in the future. */
- return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL /*cdict*/, cctxParams, pledgedSrcSize);
+ { ZSTD_CCtx_params const cctxParams = ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
+ return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL /*cdict*/, cctxParams, pledgedSrcSize);
+ }
}
size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel)
@@ -2687,7 +3030,7 @@ MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity,
/** ZSTD_compressStream_generic():
* internal function for all *compressStream*() variants and *compress_generic()
- * non-static, because can be called from zstdmt.c
+ * non-static, because can be called from zstdmt_compress.c
* @return : hint size for next input */
size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
ZSTD_outBuffer* output,
@@ -2862,46 +3205,56 @@ size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
DEBUGLOG(4, "ZSTD_compress_generic : transparent init stage");
if (endOp == ZSTD_e_end) cctx->pledgedSrcSizePlusOne = input->size + 1; /* auto-fix pledgedSrcSize */
params.cParams = ZSTD_getCParamsFromCCtxParams(
- cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1, 0 /*dictSize*/);
+ &cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1, 0 /*dictSize*/);
#ifdef ZSTD_MULTITHREAD
- if ((cctx->pledgedSrcSizePlusOne-1) <= ZSTDMT_JOBSIZE_MIN)
- params.nbThreads = 1; /* do not invoke multi-threading when src size is too small */
- if (params.nbThreads > 1) {
- if (cctx->mtctx == NULL || (params.nbThreads != ZSTDMT_getNbThreads(cctx->mtctx))) {
- DEBUGLOG(4, "ZSTD_compress_generic: creating new mtctx for nbThreads=%u (previous: %u)",
- params.nbThreads, ZSTDMT_getNbThreads(cctx->mtctx));
+ if ((cctx->pledgedSrcSizePlusOne-1) <= ZSTDMT_JOBSIZE_MIN) {
+ params.nbWorkers = 0; /* do not invoke multi-threading when src size is too small */
+ }
+ if (params.nbWorkers > 0) {
+ /* mt context creation */
+ if (cctx->mtctx == NULL || (params.nbWorkers != ZSTDMT_getNbWorkers(cctx->mtctx))) {
+ DEBUGLOG(4, "ZSTD_compress_generic: creating new mtctx for nbWorkers=%u",
+ params.nbWorkers);
+ if (cctx->mtctx != NULL)
+ DEBUGLOG(4, "ZSTD_compress_generic: previous nbWorkers was %u",
+ ZSTDMT_getNbWorkers(cctx->mtctx));
ZSTDMT_freeCCtx(cctx->mtctx);
- cctx->mtctx = ZSTDMT_createCCtx_advanced(params.nbThreads, cctx->customMem);
+ cctx->mtctx = ZSTDMT_createCCtx_advanced(params.nbWorkers, cctx->customMem);
if (cctx->mtctx == NULL) return ERROR(memory_allocation);
}
- DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbThreads=%u", params.nbThreads);
+ /* mt compression */
+ DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbWorkers=%u", params.nbWorkers);
CHECK_F( ZSTDMT_initCStream_internal(
cctx->mtctx,
- prefixDict.dict, prefixDict.dictSize, ZSTD_dm_rawContent,
+ prefixDict.dict, prefixDict.dictSize, ZSTD_dct_rawContent,
cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) );
cctx->streamStage = zcss_load;
- cctx->appliedParams.nbThreads = params.nbThreads;
+ cctx->appliedParams.nbWorkers = params.nbWorkers;
} else
#endif
- { CHECK_F( ZSTD_resetCStream_internal(
- cctx, prefixDict.dict, prefixDict.dictSize,
- prefixDict.dictMode, cctx->cdict, params,
- cctx->pledgedSrcSizePlusOne-1) );
+ { CHECK_F( ZSTD_resetCStream_internal(cctx,
+ prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType,
+ cctx->cdict,
+ params, cctx->pledgedSrcSizePlusOne-1) );
assert(cctx->streamStage == zcss_load);
- assert(cctx->appliedParams.nbThreads <= 1);
+ assert(cctx->appliedParams.nbWorkers == 0);
} }
/* compression stage */
#ifdef ZSTD_MULTITHREAD
- if (cctx->appliedParams.nbThreads > 1) {
- size_t const flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);
- if ( ZSTD_isError(flushMin)
- || (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */
- ZSTD_startNewCompression(cctx);
+ if (cctx->appliedParams.nbWorkers > 0) {
+ if (cctx->cParamsChanged) {
+ ZSTDMT_updateCParams_whileCompressing(cctx->mtctx, &cctx->requestedParams);
+ cctx->cParamsChanged = 0;
}
- return flushMin;
- }
+ { size_t const flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);
+ if ( ZSTD_isError(flushMin)
+ || (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */
+ ZSTD_startNewCompression(cctx);
+ }
+ return flushMin;
+ } }
#endif
CHECK_F( ZSTD_compressStream_generic(cctx, output, input, endOp) );
DEBUGLOG(5, "completed ZSTD_compress_generic");
@@ -2927,7 +3280,7 @@ size_t ZSTD_compress_generic_simpleArgs (
/*====== Finalize ======*/
/*! ZSTD_flushStream() :
-* @return : amount of data remaining to flush */
+ * @return : amount of data remaining to flush */
size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
{
ZSTD_inBuffer input = { NULL, 0, 0 };
@@ -2959,11 +3312,11 @@ int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; }
static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = {
{ /* "default" - guarantees a monotonically increasing memory budget */
/* W, C, H, S, L, TL, strat */
- { 18, 12, 12, 1, 7, 16, ZSTD_fast }, /* level 0 - never used */
- { 19, 13, 14, 1, 7, 16, ZSTD_fast }, /* level 1 */
- { 19, 15, 16, 1, 6, 16, ZSTD_fast }, /* level 2 */
- { 20, 16, 17, 1, 5, 16, ZSTD_dfast }, /* level 3 */
- { 20, 17, 18, 1, 5, 16, ZSTD_dfast }, /* level 4 */
+ { 19, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */
+ { 19, 13, 14, 1, 7, 1, ZSTD_fast }, /* level 1 */
+ { 19, 15, 16, 1, 6, 1, ZSTD_fast }, /* level 2 */
+ { 20, 16, 17, 1, 5, 8, ZSTD_dfast }, /* level 3 */
+ { 20, 17, 18, 1, 5, 8, ZSTD_dfast }, /* level 4 */
{ 20, 17, 18, 2, 5, 16, ZSTD_greedy }, /* level 5 */
{ 21, 17, 19, 2, 5, 16, ZSTD_lazy }, /* level 6 */
{ 21, 18, 19, 3, 5, 16, ZSTD_lazy }, /* level 7 */
@@ -2972,9 +3325,9 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
{ 21, 19, 21, 4, 5, 16, ZSTD_lazy2 }, /* level 10 */
{ 22, 20, 22, 4, 5, 16, ZSTD_lazy2 }, /* level 11 */
{ 22, 20, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 12 */
- { 22, 21, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 13 */
- { 22, 21, 22, 6, 5, 16, ZSTD_lazy2 }, /* level 14 */
- { 22, 21, 22, 4, 5, 16, ZSTD_btlazy2 }, /* level 15 */
+ { 22, 21, 22, 4, 5, 32, ZSTD_btlazy2 }, /* level 13 */
+ { 22, 21, 22, 5, 5, 32, ZSTD_btlazy2 }, /* level 14 */
+ { 22, 22, 22, 6, 5, 32, ZSTD_btlazy2 }, /* level 15 */
{ 22, 21, 22, 4, 5, 48, ZSTD_btopt }, /* level 16 */
{ 23, 22, 22, 4, 4, 48, ZSTD_btopt }, /* level 17 */
{ 23, 22, 22, 5, 3, 64, ZSTD_btopt }, /* level 18 */
@@ -2985,8 +3338,8 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
},
{ /* for srcSize <= 256 KB */
/* W, C, H, S, L, T, strat */
- { 0, 0, 0, 0, 0, 0, ZSTD_fast }, /* level 0 - not used */
- { 18, 13, 14, 1, 6, 8, ZSTD_fast }, /* level 1 */
+ { 18, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
+ { 18, 13, 14, 1, 6, 1, ZSTD_fast }, /* level 1 */
{ 18, 14, 13, 1, 5, 8, ZSTD_dfast }, /* level 2 */
{ 18, 16, 15, 1, 5, 8, ZSTD_dfast }, /* level 3 */
{ 18, 15, 17, 1, 5, 8, ZSTD_greedy }, /* level 4.*/
@@ -2997,8 +3350,8 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
{ 18, 17, 17, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */
{ 18, 17, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */
{ 18, 18, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 11.*/
- { 18, 18, 17, 7, 4, 8, ZSTD_lazy2 }, /* level 12.*/
- { 18, 19, 17, 6, 4, 8, ZSTD_btlazy2 }, /* level 13 */
+ { 18, 18, 17, 5, 4, 8, ZSTD_btlazy2 }, /* level 12.*/
+ { 18, 19, 17, 7, 4, 8, ZSTD_btlazy2 }, /* level 13 */
{ 18, 18, 18, 4, 4, 16, ZSTD_btopt }, /* level 14.*/
{ 18, 18, 18, 4, 3, 16, ZSTD_btopt }, /* level 15.*/
{ 18, 19, 18, 6, 3, 32, ZSTD_btopt }, /* level 16.*/
@@ -3011,9 +3364,9 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
},
{ /* for srcSize <= 128 KB */
/* W, C, H, S, L, T, strat */
- { 17, 12, 12, 1, 7, 8, ZSTD_fast }, /* level 0 - not used */
- { 17, 12, 13, 1, 6, 8, ZSTD_fast }, /* level 1 */
- { 17, 13, 16, 1, 5, 8, ZSTD_fast }, /* level 2 */
+ { 17, 12, 12, 1, 5, 1, ZSTD_fast }, /* level 0 - not used */
+ { 17, 12, 13, 1, 6, 1, ZSTD_fast }, /* level 1 */
+ { 17, 13, 16, 1, 5, 1, ZSTD_fast }, /* level 2 */
{ 17, 16, 16, 2, 5, 8, ZSTD_dfast }, /* level 3 */
{ 17, 13, 15, 3, 4, 8, ZSTD_greedy }, /* level 4 */
{ 17, 15, 17, 4, 4, 8, ZSTD_greedy }, /* level 5 */
@@ -3037,9 +3390,9 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
},
{ /* for srcSize <= 16 KB */
/* W, C, H, S, L, T, strat */
- { 14, 12, 12, 1, 7, 6, ZSTD_fast }, /* level 0 - not used */
- { 14, 14, 14, 1, 6, 6, ZSTD_fast }, /* level 1 */
- { 14, 14, 14, 1, 4, 6, ZSTD_fast }, /* level 2 */
+ { 14, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
+ { 14, 14, 14, 1, 6, 1, ZSTD_fast }, /* level 1 */
+ { 14, 14, 14, 1, 4, 1, ZSTD_fast }, /* level 2 */
{ 14, 14, 14, 1, 4, 6, ZSTD_dfast }, /* level 3.*/
{ 14, 14, 14, 4, 4, 6, ZSTD_greedy }, /* level 4.*/
{ 14, 14, 14, 3, 4, 6, ZSTD_lazy }, /* level 5.*/
@@ -3063,47 +3416,22 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
},
};
-#if defined(ZSTD_DEBUG) && (ZSTD_DEBUG>=1)
-/* This function just controls
- * the monotonic memory budget increase of ZSTD_defaultCParameters[0].
- * Run once, on first ZSTD_getCParams() usage, if ZSTD_DEBUG is enabled
- */
-MEM_STATIC void ZSTD_check_compressionLevel_monotonicIncrease_memoryBudget(void)
-{
- int level;
- for (level=1; level<ZSTD_maxCLevel(); level++) {
- ZSTD_compressionParameters const c1 = ZSTD_defaultCParameters[0][level];
- ZSTD_compressionParameters const c2 = ZSTD_defaultCParameters[0][level+1];
- assert(c1.windowLog <= c2.windowLog);
-# define ZSTD_TABLECOST(h,c) ((1<<(h)) + (1<<(c)))
- assert(ZSTD_TABLECOST(c1.hashLog, c1.chainLog) <= ZSTD_TABLECOST(c2.hashLog, c2.chainLog));
- }
-}
-#endif
-
/*! ZSTD_getCParams() :
-* @return ZSTD_compressionParameters structure for a selected compression level, `srcSize` and `dictSize`.
+* @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize.
* Size values are optional, provide 0 if not known or unused */
ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize)
{
size_t const addedSize = srcSizeHint ? 0 : 500;
U64 const rSize = srcSizeHint+dictSize ? srcSizeHint+dictSize+addedSize : (U64)-1;
U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB); /* intentional underflow for srcSizeHint == 0 */
-
-#if defined(ZSTD_DEBUG) && (ZSTD_DEBUG>=1)
- static int g_monotonicTest = 1;
- if (g_monotonicTest) {
- ZSTD_check_compressionLevel_monotonicIncrease_memoryBudget();
- g_monotonicTest=0;
- }
-#endif
-
- DEBUGLOG(4, "ZSTD_getCParams: cLevel=%i, srcSize=%u, dictSize=%u => table %u",
- compressionLevel, (U32)srcSizeHint, (U32)dictSize, tableID);
- if (compressionLevel <= 0) compressionLevel = ZSTD_CLEVEL_DEFAULT; /* 0 == default; no negative compressionLevel yet */
- if (compressionLevel > ZSTD_MAX_CLEVEL) compressionLevel = ZSTD_MAX_CLEVEL;
- { ZSTD_compressionParameters const cp = ZSTD_defaultCParameters[tableID][compressionLevel];
- return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize); }
+ int row = compressionLevel;
+ DEBUGLOG(5, "ZSTD_getCParams (cLevel=%i)", compressionLevel);
+ if (compressionLevel == 0) row = ZSTD_CLEVEL_DEFAULT; /* 0 == default */
+ if (compressionLevel < 0) row = 0; /* entry 0 is baseline for fast mode */
+ if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL;
+ { ZSTD_compressionParameters cp = ZSTD_defaultCParameters[tableID][row];
+ if (compressionLevel < 0) cp.targetLength = (unsigned)(-compressionLevel); /* acceleration factor */
+ return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize); }
}
@@ -3113,6 +3441,7 @@ ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long l
ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) {
ZSTD_parameters params;
ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, srcSizeHint, dictSize);
+ DEBUGLOG(5, "ZSTD_getParams (cLevel=%i)", compressionLevel);
memset(&params, 0, sizeof(params));
params.cParams = cParams;
params.fParams.contentSizeFlag = 1;
diff --git a/thirdparty/zstd/compress/zstd_compress_internal.h b/thirdparty/zstd/compress/zstd_compress_internal.h
index f104fe981e..81f12ca6df 100644
--- a/thirdparty/zstd/compress/zstd_compress_internal.h
+++ b/thirdparty/zstd/compress/zstd_compress_internal.h
@@ -30,8 +30,14 @@ extern "C" {
/*-*************************************
* Constants
***************************************/
-static const U32 g_searchStrength = 8;
-#define HASH_READ_SIZE 8
+#define kSearchStrength 8
+#define HASH_READ_SIZE 8
+#define ZSTD_DUBT_UNSORTED_MARK 1 /* For btlazy2 strategy, index 1 now means "unsorted".
+ It could be confused for a real successor at index "1", if sorted as larger than its predecessor.
+ It's not a big deal though : candidate will just be sorted again.
+ Additionnally, candidate position 1 will be lost.
+ But candidate 1 cannot hide a large tree of candidates, so it's a minimal loss.
+ The benefit is that ZSTD_DUBT_UNSORTED_MARK cannot be misdhandled after table re-use with a different strategy */
/*-*************************************
@@ -43,7 +49,7 @@ typedef enum { zcss_init=0, zcss_load, zcss_flush } ZSTD_cStreamStage;
typedef struct ZSTD_prefixDict_s {
const void* dict;
size_t dictSize;
- ZSTD_dictMode_e dictMode;
+ ZSTD_dictContentType_e dictContentType;
} ZSTD_prefixDict;
typedef struct {
@@ -51,7 +57,6 @@ typedef struct {
FSE_CTable offcodeCTable[FSE_CTABLE_SIZE_U32(OffFSELog, MaxOff)];
FSE_CTable matchlengthCTable[FSE_CTABLE_SIZE_U32(MLFSELog, MaxML)];
FSE_CTable litlengthCTable[FSE_CTABLE_SIZE_U32(LLFSELog, MaxLL)];
- U32 workspace[HUF_WORKSPACE_SIZE_U32];
HUF_repeat hufCTable_repeatMode;
FSE_repeat offcode_repeatMode;
FSE_repeat matchlength_repeatMode;
@@ -94,11 +99,43 @@ typedef struct {
} optState_t;
typedef struct {
+ ZSTD_entropyCTables_t entropy;
+ U32 rep[ZSTD_REP_NUM];
+} ZSTD_compressedBlockState_t;
+
+typedef struct {
+ BYTE const* nextSrc; /* next block here to continue on current prefix */
+ BYTE const* base; /* All regular indexes relative to this position */
+ BYTE const* dictBase; /* extDict indexes relative to this position */
+ U32 dictLimit; /* below that point, need extDict */
+ U32 lowLimit; /* below that point, no more data */
+} ZSTD_window_t;
+
+typedef struct {
+ ZSTD_window_t window; /* State for window round buffer management */
+ U32 loadedDictEnd; /* index of end of dictionary */
+ U32 nextToUpdate; /* index from which to continue table update */
+ U32 nextToUpdate3; /* index from which to continue table update */
+ U32 hashLog3; /* dispatch table : larger == faster, more memory */
+ U32* hashTable;
+ U32* hashTable3;
+ U32* chainTable;
+ optState_t opt; /* optimal parser state */
+} ZSTD_matchState_t;
+
+typedef struct {
+ ZSTD_compressedBlockState_t* prevCBlock;
+ ZSTD_compressedBlockState_t* nextCBlock;
+ ZSTD_matchState_t matchState;
+} ZSTD_blockState_t;
+
+typedef struct {
U32 offset;
U32 checksum;
} ldmEntry_t;
typedef struct {
+ ZSTD_window_t window; /* State for the window round buffer management */
ldmEntry_t* hashTable;
BYTE* bucketOffsets; /* Next position in bucket to insert entry */
U64 hashPower; /* Used to compute the rolling hash.
@@ -111,60 +148,68 @@ typedef struct {
U32 bucketSizeLog; /* Log bucket size for collision resolution, at most 8 */
U32 minMatchLength; /* Minimum match length */
U32 hashEveryLog; /* Log number of entries to skip */
+ U32 windowLog; /* Window log for the LDM */
} ldmParams_t;
+typedef struct {
+ U32 offset;
+ U32 litLength;
+ U32 matchLength;
+} rawSeq;
+
+typedef struct {
+ rawSeq* seq; /* The start of the sequences */
+ size_t pos; /* The position where reading stopped. <= size. */
+ size_t size; /* The number of sequences. <= capacity. */
+ size_t capacity; /* The capacity of the `seq` pointer */
+} rawSeqStore_t;
+
struct ZSTD_CCtx_params_s {
ZSTD_format_e format;
ZSTD_compressionParameters cParams;
ZSTD_frameParameters fParams;
int compressionLevel;
- U32 forceWindow; /* force back-references to respect limit of
+ int disableLiteralCompression;
+ int forceWindow; /* force back-references to respect limit of
* 1<<wLog, even for dictionary */
/* Multithreading: used to pass parameters to mtctx */
- U32 nbThreads;
+ unsigned nbWorkers;
unsigned jobSize;
unsigned overlapSizeLog;
/* Long distance matching parameters */
ldmParams_t ldmParams;
- /* For use with createCCtxParams() and freeCCtxParams() only */
+ /* Internal use, for createCCtxParams() and freeCCtxParams() only */
ZSTD_customMem customMem;
-
}; /* typedef'd to ZSTD_CCtx_params within "zstd.h" */
struct ZSTD_CCtx_s {
- const BYTE* nextSrc; /* next block here to continue on current prefix */
- const BYTE* base; /* All regular indexes relative to this position */
- const BYTE* dictBase; /* extDict indexes relative to this position */
- U32 dictLimit; /* below that point, need extDict */
- U32 lowLimit; /* below that point, no more data */
- U32 nextToUpdate; /* index from which to continue dictionary update */
- U32 nextToUpdate3; /* index from which to continue dictionary update */
- U32 hashLog3; /* dispatch table : larger == faster, more memory */
- U32 loadedDictEnd; /* index of end of dictionary */
ZSTD_compressionStage_e stage;
- U32 dictID;
+ int cParamsChanged; /* == 1 if cParams(except wlog) or compression level are changed in requestedParams. Triggers transmission of new params to ZSTDMT (if available) then reset to 0. */
+ int bmi2; /* == 1 if the CPU supports BMI2 and 0 otherwise. CPU support is determined dynamically once per context lifetime. */
ZSTD_CCtx_params requestedParams;
ZSTD_CCtx_params appliedParams;
+ U32 dictID;
void* workSpace;
size_t workSpaceSize;
size_t blockSize;
- U64 pledgedSrcSizePlusOne; /* this way, 0 (default) == unknown */
- U64 consumedSrcSize;
+ unsigned long long pledgedSrcSizePlusOne; /* this way, 0 (default) == unknown */
+ unsigned long long consumedSrcSize;
+ unsigned long long producedCSize;
XXH64_state_t xxhState;
ZSTD_customMem customMem;
size_t staticSize;
- seqStore_t seqStore; /* sequences storage ptrs */
- optState_t optState;
- ldmState_t ldmState; /* long distance matching state */
- U32* hashTable;
- U32* hashTable3;
- U32* chainTable;
- ZSTD_entropyCTables_t* entropy;
+ seqStore_t seqStore; /* sequences storage ptrs */
+ ldmState_t ldmState; /* long distance matching state */
+ rawSeq* ldmSequences; /* Storage for the ldm output sequences */
+ size_t maxNbLdmSequences;
+ rawSeqStore_t externSeqStore; /* Mutable reference to external sequences */
+ ZSTD_blockState_t blockState;
+ U32* entropyWorkspace; /* entropy workspace of HUF_WORKSPACE_SIZE bytes */
/* streaming */
char* inBuff;
@@ -191,6 +236,12 @@ struct ZSTD_CCtx_s {
};
+typedef size_t (*ZSTD_blockCompressor) (
+ ZSTD_matchState_t* bs, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict);
+
+
MEM_STATIC U32 ZSTD_LLcode(U32 litLength)
{
static const BYTE LL_Code[64] = { 0, 1, 2, 3, 4, 5, 6, 7,
@@ -359,10 +410,12 @@ MEM_STATIC size_t ZSTD_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* co
}
/** ZSTD_count_2segments() :
-* can count match length with `ip` & `match` in 2 different segments.
-* convention : on reaching mEnd, match count continue starting from iStart
-*/
-MEM_STATIC size_t ZSTD_count_2segments(const BYTE* ip, const BYTE* match, const BYTE* iEnd, const BYTE* mEnd, const BYTE* iStart)
+ * can count match length with `ip` & `match` in 2 different segments.
+ * convention : on reaching mEnd, match count continue starting from iStart
+ */
+MEM_STATIC size_t
+ZSTD_count_2segments(const BYTE* ip, const BYTE* match,
+ const BYTE* iEnd, const BYTE* mEnd, const BYTE* iStart)
{
const BYTE* const vEnd = MIN( ip + (mEnd - match), iEnd);
size_t const matchLength = ZSTD_count(ip, match, vEnd);
@@ -372,8 +425,8 @@ MEM_STATIC size_t ZSTD_count_2segments(const BYTE* ip, const BYTE* match, const
/*-*************************************
-* Hashes
-***************************************/
+ * Hashes
+ ***************************************/
static const U32 prime3bytes = 506832829U;
static U32 ZSTD_hash3(U32 u, U32 h) { return ((u << (32-24)) * prime3bytes) >> (32-h) ; }
MEM_STATIC size_t ZSTD_hash3Ptr(const void* ptr, U32 h) { return ZSTD_hash3(MEM_readLE32(ptr), h); } /* only in zstd_opt.h */
@@ -411,6 +464,171 @@ MEM_STATIC size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls)
}
}
+/*-*************************************
+* Round buffer management
+***************************************/
+/* Max current allowed */
+#define ZSTD_CURRENT_MAX ((3U << 29) + (1U << ZSTD_WINDOWLOG_MAX))
+/* Maximum chunk size before overflow correction needs to be called again */
+#define ZSTD_CHUNKSIZE_MAX \
+ ( ((U32)-1) /* Maximum ending current index */ \
+ - ZSTD_CURRENT_MAX) /* Maximum beginning lowLimit */
+
+/**
+ * ZSTD_window_clear():
+ * Clears the window containing the history by simply setting it to empty.
+ */
+MEM_STATIC void ZSTD_window_clear(ZSTD_window_t* window)
+{
+ size_t const endT = (size_t)(window->nextSrc - window->base);
+ U32 const end = (U32)endT;
+
+ window->lowLimit = end;
+ window->dictLimit = end;
+}
+
+/**
+ * ZSTD_window_hasExtDict():
+ * Returns non-zero if the window has a non-empty extDict.
+ */
+MEM_STATIC U32 ZSTD_window_hasExtDict(ZSTD_window_t const window)
+{
+ return window.lowLimit < window.dictLimit;
+}
+
+/**
+ * ZSTD_window_needOverflowCorrection():
+ * Returns non-zero if the indices are getting too large and need overflow
+ * protection.
+ */
+MEM_STATIC U32 ZSTD_window_needOverflowCorrection(ZSTD_window_t const window,
+ void const* srcEnd)
+{
+ U32 const current = (U32)((BYTE const*)srcEnd - window.base);
+ return current > ZSTD_CURRENT_MAX;
+}
+
+/**
+ * ZSTD_window_correctOverflow():
+ * Reduces the indices to protect from index overflow.
+ * Returns the correction made to the indices, which must be applied to every
+ * stored index.
+ *
+ * The least significant cycleLog bits of the indices must remain the same,
+ * which may be 0. Every index up to maxDist in the past must be valid.
+ * NOTE: (maxDist & cycleMask) must be zero.
+ */
+MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog,
+ U32 maxDist, void const* src)
+{
+ /* preemptive overflow correction:
+ * 1. correction is large enough:
+ * lowLimit > (3<<29) ==> current > 3<<29 + 1<<windowLog
+ * 1<<windowLog <= newCurrent < 1<<chainLog + 1<<windowLog
+ *
+ * current - newCurrent
+ * > (3<<29 + 1<<windowLog) - (1<<windowLog + 1<<chainLog)
+ * > (3<<29) - (1<<chainLog)
+ * > (3<<29) - (1<<30) (NOTE: chainLog <= 30)
+ * > 1<<29
+ *
+ * 2. (ip+ZSTD_CHUNKSIZE_MAX - cctx->base) doesn't overflow:
+ * After correction, current is less than (1<<chainLog + 1<<windowLog).
+ * In 64-bit mode we are safe, because we have 64-bit ptrdiff_t.
+ * In 32-bit mode we are safe, because (chainLog <= 29), so
+ * ip+ZSTD_CHUNKSIZE_MAX - cctx->base < 1<<32.
+ * 3. (cctx->lowLimit + 1<<windowLog) < 1<<32:
+ * windowLog <= 31 ==> 3<<29 + 1<<windowLog < 7<<29 < 1<<32.
+ */
+ U32 const cycleMask = (1U << cycleLog) - 1;
+ U32 const current = (U32)((BYTE const*)src - window->base);
+ U32 const newCurrent = (current & cycleMask) + maxDist;
+ U32 const correction = current - newCurrent;
+ assert((maxDist & cycleMask) == 0);
+ assert(current > newCurrent);
+ /* Loose bound, should be around 1<<29 (see above) */
+ assert(correction > 1<<28);
+
+ window->base += correction;
+ window->dictBase += correction;
+ window->lowLimit -= correction;
+ window->dictLimit -= correction;
+
+ DEBUGLOG(4, "Correction of 0x%x bytes to lowLimit=0x%x", correction,
+ window->lowLimit);
+ return correction;
+}
+
+/**
+ * ZSTD_window_enforceMaxDist():
+ * Updates lowLimit so that:
+ * (srcEnd - base) - lowLimit == maxDist + loadedDictEnd
+ * This allows a simple check that index >= lowLimit to see if index is valid.
+ * This must be called before a block compression call, with srcEnd as the block
+ * source end.
+ * If loadedDictEndPtr is not NULL, we set it to zero once we update lowLimit.
+ * This is because dictionaries are allowed to be referenced as long as the last
+ * byte of the dictionary is in the window, but once they are out of range,
+ * they cannot be referenced. If loadedDictEndPtr is NULL, we use
+ * loadedDictEnd == 0.
+ */
+MEM_STATIC void ZSTD_window_enforceMaxDist(ZSTD_window_t* window,
+ void const* srcEnd, U32 maxDist,
+ U32* loadedDictEndPtr)
+{
+ U32 const current = (U32)((BYTE const*)srcEnd - window->base);
+ U32 loadedDictEnd = loadedDictEndPtr != NULL ? *loadedDictEndPtr : 0;
+ if (current > maxDist + loadedDictEnd) {
+ U32 const newLowLimit = current - maxDist;
+ if (window->lowLimit < newLowLimit) window->lowLimit = newLowLimit;
+ if (window->dictLimit < window->lowLimit) {
+ DEBUGLOG(5, "Update dictLimit from %u to %u", window->dictLimit,
+ window->lowLimit);
+ window->dictLimit = window->lowLimit;
+ }
+ if (loadedDictEndPtr)
+ *loadedDictEndPtr = 0;
+ }
+}
+
+/**
+ * ZSTD_window_update():
+ * Updates the window by appending [src, src + srcSize) to the window.
+ * If it is not contiguous, the current prefix becomes the extDict, and we
+ * forget about the extDict. Handles overlap of the prefix and extDict.
+ * Returns non-zero if the segment is contiguous.
+ */
+MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window,
+ void const* src, size_t srcSize)
+{
+ BYTE const* const ip = (BYTE const*)src;
+ U32 contiguous = 1;
+ /* Check if blocks follow each other */
+ if (src != window->nextSrc) {
+ /* not contiguous */
+ size_t const distanceFromBase = (size_t)(window->nextSrc - window->base);
+ DEBUGLOG(5, "Non contiguous blocks, new segment starts at %u",
+ window->dictLimit);
+ window->lowLimit = window->dictLimit;
+ assert(distanceFromBase == (size_t)(U32)distanceFromBase); /* should never overflow */
+ window->dictLimit = (U32)distanceFromBase;
+ window->dictBase = window->base;
+ window->base = ip - distanceFromBase;
+ // ms->nextToUpdate = window->dictLimit;
+ if (window->dictLimit - window->lowLimit < HASH_READ_SIZE) window->lowLimit = window->dictLimit; /* too small extDict */
+ contiguous = 0;
+ }
+ window->nextSrc = ip + srcSize;
+ /* if input and dictionary overlap : reduce dictionary (area presumed modified by input) */
+ if ( (ip+srcSize > window->dictBase + window->lowLimit)
+ & (ip < window->dictBase + window->dictLimit)) {
+ ptrdiff_t const highInputIdx = (ip + srcSize) - window->dictBase;
+ U32 const lowLimitMax = (highInputIdx > (ptrdiff_t)window->dictLimit) ? window->dictLimit : (U32)highInputIdx;
+ window->lowLimit = lowLimitMax;
+ }
+ return contiguous;
+}
+
#if defined (__cplusplus)
}
#endif
@@ -421,6 +639,13 @@ MEM_STATIC size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls)
* These prototypes shall only be called from within lib/compress
* ============================================================== */
+/* ZSTD_getCParamsFromCCtxParams() :
+ * cParams are built depending on compressionLevel, src size hints,
+ * LDM and manually set compression parameters.
+ */
+ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
+ const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize);
+
/*! ZSTD_initCStream_internal() :
* Private use only. Init streaming operation.
* expects params to be valid.
@@ -446,7 +671,7 @@ ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict);
* Private use only. To be called from zstdmt_compress.c. */
size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,
const void* dict, size_t dictSize,
- ZSTD_dictMode_e dictMode,
+ ZSTD_dictContentType_e dictContentType,
const ZSTD_CDict* cdict,
ZSTD_CCtx_params params,
unsigned long long pledgedSrcSize);
@@ -459,4 +684,26 @@ size_t ZSTD_compress_advanced_internal(ZSTD_CCtx* cctx,
const void* dict,size_t dictSize,
ZSTD_CCtx_params params);
+
+/* ZSTD_writeLastEmptyBlock() :
+ * output an empty Block with end-of-frame mark to complete a frame
+ * @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h))
+ * or an error code if `dstCapcity` is too small (<ZSTD_blockHeaderSize)
+ */
+size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity);
+
+
+/* ZSTD_referenceExternalSequences() :
+ * Must be called before starting a compression operation.
+ * seqs must parse a prefix of the source.
+ * This cannot be used when long range matching is enabled.
+ * Zstd will use these sequences, and pass the literals to a secondary block
+ * compressor.
+ * @return : An error code on failure.
+ * NOTE: seqs are not verified! Invalid sequences can cause out-of-bounds memory
+ * access and data corruption.
+ */
+size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq);
+
+
#endif /* ZSTD_COMPRESS_H */
diff --git a/thirdparty/zstd/compress/zstd_double_fast.c b/thirdparty/zstd/compress/zstd_double_fast.c
index fee5127c35..86e6b39621 100644
--- a/thirdparty/zstd/compress/zstd_double_fast.c
+++ b/thirdparty/zstd/compress/zstd_double_fast.c
@@ -12,44 +12,58 @@
#include "zstd_double_fast.h"
-void ZSTD_fillDoubleHashTable(ZSTD_CCtx* cctx, const void* end, const U32 mls)
+void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms,
+ ZSTD_compressionParameters const* cParams,
+ void const* end)
{
- U32* const hashLarge = cctx->hashTable;
- U32 const hBitsL = cctx->appliedParams.cParams.hashLog;
- U32* const hashSmall = cctx->chainTable;
- U32 const hBitsS = cctx->appliedParams.cParams.chainLog;
- const BYTE* const base = cctx->base;
- const BYTE* ip = base + cctx->nextToUpdate;
+ U32* const hashLarge = ms->hashTable;
+ U32 const hBitsL = cParams->hashLog;
+ U32 const mls = cParams->searchLength;
+ U32* const hashSmall = ms->chainTable;
+ U32 const hBitsS = cParams->chainLog;
+ const BYTE* const base = ms->window.base;
+ const BYTE* ip = base + ms->nextToUpdate;
const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE;
- const size_t fastHashFillStep = 3;
-
- while(ip <= iend) {
- hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip - base);
- hashLarge[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip - base);
- ip += fastHashFillStep;
+ const U32 fastHashFillStep = 3;
+
+ /* Always insert every fastHashFillStep position into the hash tables.
+ * Insert the other positions into the large hash table if their entry
+ * is empty.
+ */
+ for (; ip + fastHashFillStep - 1 <= iend; ip += fastHashFillStep) {
+ U32 const current = (U32)(ip - base);
+ U32 i;
+ for (i = 0; i < fastHashFillStep; ++i) {
+ size_t const smHash = ZSTD_hashPtr(ip + i, hBitsS, mls);
+ size_t const lgHash = ZSTD_hashPtr(ip + i, hBitsL, 8);
+ if (i == 0)
+ hashSmall[smHash] = current + i;
+ if (i == 0 || hashLarge[lgHash] == 0)
+ hashLarge[lgHash] = current + i;
+ }
}
}
FORCE_INLINE_TEMPLATE
-size_t ZSTD_compressBlock_doubleFast_generic(ZSTD_CCtx* cctx,
- const void* src, size_t srcSize,
- const U32 mls)
+size_t ZSTD_compressBlock_doubleFast_generic(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize,
+ U32 const mls /* template */)
{
- U32* const hashLong = cctx->hashTable;
- const U32 hBitsL = cctx->appliedParams.cParams.hashLog;
- U32* const hashSmall = cctx->chainTable;
- const U32 hBitsS = cctx->appliedParams.cParams.chainLog;
- seqStore_t* seqStorePtr = &(cctx->seqStore);
- const BYTE* const base = cctx->base;
+ U32* const hashLong = ms->hashTable;
+ const U32 hBitsL = cParams->hashLog;
+ U32* const hashSmall = ms->chainTable;
+ const U32 hBitsS = cParams->chainLog;
+ const BYTE* const base = ms->window.base;
const BYTE* const istart = (const BYTE*)src;
const BYTE* ip = istart;
const BYTE* anchor = istart;
- const U32 lowestIndex = cctx->dictLimit;
+ const U32 lowestIndex = ms->window.dictLimit;
const BYTE* const lowest = base + lowestIndex;
const BYTE* const iend = istart + srcSize;
const BYTE* const ilimit = iend - HASH_READ_SIZE;
- U32 offset_1=seqStorePtr->rep[0], offset_2=seqStorePtr->rep[1];
+ U32 offset_1=rep[0], offset_2=rep[1];
U32 offsetSaved = 0;
/* init */
@@ -76,7 +90,7 @@ size_t ZSTD_compressBlock_doubleFast_generic(ZSTD_CCtx* cctx,
/* favor repcode */
mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
ip++;
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
+ ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
} else {
U32 offset;
if ( (matchIndexL > lowestIndex) && (MEM_read64(matchLong) == MEM_read64(ip)) ) {
@@ -99,14 +113,14 @@ size_t ZSTD_compressBlock_doubleFast_generic(ZSTD_CCtx* cctx,
while (((ip>anchor) & (match>lowest)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
}
} else {
- ip += ((ip-anchor) >> g_searchStrength) + 1;
+ ip += ((ip-anchor) >> kSearchStrength) + 1;
continue;
}
offset_2 = offset_1;
offset_1 = offset;
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
+ ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
}
/* match found */
@@ -129,61 +143,63 @@ size_t ZSTD_compressBlock_doubleFast_generic(ZSTD_CCtx* cctx,
{ U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; } /* swap offset_2 <=> offset_1 */
hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip-base);
hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip-base);
- ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, rLength-MINMATCH);
+ ZSTD_storeSeq(seqStore, 0, anchor, 0, rLength-MINMATCH);
ip += rLength;
anchor = ip;
continue; /* faster when present ... (?) */
} } }
/* save reps for next block */
- seqStorePtr->repToConfirm[0] = offset_1 ? offset_1 : offsetSaved;
- seqStorePtr->repToConfirm[1] = offset_2 ? offset_2 : offsetSaved;
+ rep[0] = offset_1 ? offset_1 : offsetSaved;
+ rep[1] = offset_2 ? offset_2 : offsetSaved;
/* Return the last literals size */
return iend - anchor;
}
-size_t ZSTD_compressBlock_doubleFast(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
+size_t ZSTD_compressBlock_doubleFast(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
{
- const U32 mls = ctx->appliedParams.cParams.searchLength;
+ const U32 mls = cParams->searchLength;
switch(mls)
{
default: /* includes case 3 */
case 4 :
- return ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 4);
+ return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, cParams, src, srcSize, 4);
case 5 :
- return ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 5);
+ return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, cParams, src, srcSize, 5);
case 6 :
- return ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 6);
+ return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, cParams, src, srcSize, 6);
case 7 :
- return ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 7);
+ return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, cParams, src, srcSize, 7);
}
}
-static size_t ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx* ctx,
- const void* src, size_t srcSize,
- const U32 mls)
+static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize,
+ U32 const mls /* template */)
{
- U32* const hashLong = ctx->hashTable;
- U32 const hBitsL = ctx->appliedParams.cParams.hashLog;
- U32* const hashSmall = ctx->chainTable;
- U32 const hBitsS = ctx->appliedParams.cParams.chainLog;
- seqStore_t* seqStorePtr = &(ctx->seqStore);
- const BYTE* const base = ctx->base;
- const BYTE* const dictBase = ctx->dictBase;
+ U32* const hashLong = ms->hashTable;
+ U32 const hBitsL = cParams->hashLog;
+ U32* const hashSmall = ms->chainTable;
+ U32 const hBitsS = cParams->chainLog;
+ const BYTE* const base = ms->window.base;
+ const BYTE* const dictBase = ms->window.dictBase;
const BYTE* const istart = (const BYTE*)src;
const BYTE* ip = istart;
const BYTE* anchor = istart;
- const U32 lowestIndex = ctx->lowLimit;
+ const U32 lowestIndex = ms->window.lowLimit;
const BYTE* const dictStart = dictBase + lowestIndex;
- const U32 dictLimit = ctx->dictLimit;
+ const U32 dictLimit = ms->window.dictLimit;
const BYTE* const lowPrefixPtr = base + dictLimit;
const BYTE* const dictEnd = dictBase + dictLimit;
const BYTE* const iend = istart + srcSize;
const BYTE* const ilimit = iend - 8;
- U32 offset_1=seqStorePtr->rep[0], offset_2=seqStorePtr->rep[1];
+ U32 offset_1=rep[0], offset_2=rep[1];
/* Search Loop */
while (ip < ilimit) { /* < instead of <=, because (ip+1) */
@@ -209,7 +225,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx* ctx,
const BYTE* repMatchEnd = repIndex < dictLimit ? dictEnd : iend;
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, lowPrefixPtr) + 4;
ip++;
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
+ ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
} else {
if ((matchLongIndex > lowestIndex) && (MEM_read64(matchLong) == MEM_read64(ip))) {
const BYTE* matchEnd = matchLongIndex < dictLimit ? dictEnd : iend;
@@ -220,7 +236,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx* ctx,
while (((ip>anchor) & (matchLong>lowMatchPtr)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */
offset_2 = offset_1;
offset_1 = offset;
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
+ ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
} else if ((matchIndex > lowestIndex) && (MEM_read32(match) == MEM_read32(ip))) {
size_t const h3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
@@ -245,10 +261,10 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx* ctx,
}
offset_2 = offset_1;
offset_1 = offset;
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
+ ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
} else {
- ip += ((ip-anchor) >> g_searchStrength) + 1;
+ ip += ((ip-anchor) >> kSearchStrength) + 1;
continue;
} }
@@ -272,7 +288,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx* ctx,
const BYTE* const repEnd2 = repIndex2 < dictLimit ? dictEnd : iend;
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, lowPrefixPtr) + 4;
U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
- ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, repLength2-MINMATCH);
+ ZSTD_storeSeq(seqStore, 0, anchor, 0, repLength2-MINMATCH);
hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2;
hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2;
ip += repLength2;
@@ -283,27 +299,29 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx* ctx,
} } }
/* save reps for next block */
- seqStorePtr->repToConfirm[0] = offset_1; seqStorePtr->repToConfirm[1] = offset_2;
+ rep[0] = offset_1;
+ rep[1] = offset_2;
/* Return the last literals size */
return iend - anchor;
}
-size_t ZSTD_compressBlock_doubleFast_extDict(ZSTD_CCtx* ctx,
- const void* src, size_t srcSize)
+size_t ZSTD_compressBlock_doubleFast_extDict(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
{
- U32 const mls = ctx->appliedParams.cParams.searchLength;
+ U32 const mls = cParams->searchLength;
switch(mls)
{
default: /* includes case 3 */
case 4 :
- return ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 4);
+ return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, cParams, src, srcSize, 4);
case 5 :
- return ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 5);
+ return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, cParams, src, srcSize, 5);
case 6 :
- return ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 6);
+ return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, cParams, src, srcSize, 6);
case 7 :
- return ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 7);
+ return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, cParams, src, srcSize, 7);
}
}
diff --git a/thirdparty/zstd/compress/zstd_double_fast.h b/thirdparty/zstd/compress/zstd_double_fast.h
index 75e0415809..6d80b2774c 100644
--- a/thirdparty/zstd/compress/zstd_double_fast.h
+++ b/thirdparty/zstd/compress/zstd_double_fast.h
@@ -16,11 +16,18 @@ extern "C" {
#endif
#include "mem.h" /* U32 */
-#include "zstd.h" /* ZSTD_CCtx, size_t */
+#include "zstd_compress_internal.h" /* ZSTD_CCtx, size_t */
+
+void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms,
+ ZSTD_compressionParameters const* cParams,
+ void const* end);
+size_t ZSTD_compressBlock_doubleFast(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_doubleFast_extDict(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
-void ZSTD_fillDoubleHashTable(ZSTD_CCtx* cctx, const void* end, const U32 mls);
-size_t ZSTD_compressBlock_doubleFast(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
-size_t ZSTD_compressBlock_doubleFast_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
#if defined (__cplusplus)
}
diff --git a/thirdparty/zstd/compress/zstd_fast.c b/thirdparty/zstd/compress/zstd_fast.c
index 7b56c3d6ad..df4d28b340 100644
--- a/thirdparty/zstd/compress/zstd_fast.c
+++ b/thirdparty/zstd/compress/zstd_fast.c
@@ -12,39 +12,48 @@
#include "zstd_fast.h"
-void ZSTD_fillHashTable (ZSTD_CCtx* zc, const void* end, const U32 mls)
+void ZSTD_fillHashTable(ZSTD_matchState_t* ms,
+ ZSTD_compressionParameters const* cParams,
+ void const* end)
{
- U32* const hashTable = zc->hashTable;
- U32 const hBits = zc->appliedParams.cParams.hashLog;
- const BYTE* const base = zc->base;
- const BYTE* ip = base + zc->nextToUpdate;
+ U32* const hashTable = ms->hashTable;
+ U32 const hBits = cParams->hashLog;
+ U32 const mls = cParams->searchLength;
+ const BYTE* const base = ms->window.base;
+ const BYTE* ip = base + ms->nextToUpdate;
const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE;
- const size_t fastHashFillStep = 3;
+ const U32 fastHashFillStep = 3;
- while(ip <= iend) {
- hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip - base);
- ip += fastHashFillStep;
+ /* Always insert every fastHashFillStep position into the hash table.
+ * Insert the other positions if their hash entry is empty.
+ */
+ for (; ip + fastHashFillStep - 1 <= iend; ip += fastHashFillStep) {
+ U32 const current = (U32)(ip - base);
+ U32 i;
+ for (i = 0; i < fastHashFillStep; ++i) {
+ size_t const hash = ZSTD_hashPtr(ip + i, hBits, mls);
+ if (i == 0 || hashTable[hash] == 0)
+ hashTable[hash] = current + i;
+ }
}
}
-
FORCE_INLINE_TEMPLATE
-size_t ZSTD_compressBlock_fast_generic(ZSTD_CCtx* cctx,
- const void* src, size_t srcSize,
- const U32 mls)
+size_t ZSTD_compressBlock_fast_generic(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize,
+ U32 const hlog, U32 const stepSize, U32 const mls)
{
- U32* const hashTable = cctx->hashTable;
- U32 const hBits = cctx->appliedParams.cParams.hashLog;
- seqStore_t* seqStorePtr = &(cctx->seqStore);
- const BYTE* const base = cctx->base;
+ U32* const hashTable = ms->hashTable;
+ const BYTE* const base = ms->window.base;
const BYTE* const istart = (const BYTE*)src;
const BYTE* ip = istart;
const BYTE* anchor = istart;
- const U32 lowestIndex = cctx->dictLimit;
+ const U32 lowestIndex = ms->window.dictLimit;
const BYTE* const lowest = base + lowestIndex;
const BYTE* const iend = istart + srcSize;
const BYTE* const ilimit = iend - HASH_READ_SIZE;
- U32 offset_1=seqStorePtr->rep[0], offset_2=seqStorePtr->rep[1];
+ U32 offset_1=rep[0], offset_2=rep[1];
U32 offsetSaved = 0;
/* init */
@@ -57,7 +66,7 @@ size_t ZSTD_compressBlock_fast_generic(ZSTD_CCtx* cctx,
/* Main Search Loop */
while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
size_t mLength;
- size_t const h = ZSTD_hashPtr(ip, hBits, mls);
+ size_t const h = ZSTD_hashPtr(ip, hlog, mls);
U32 const current = (U32)(ip-base);
U32 const matchIndex = hashTable[h];
const BYTE* match = base + matchIndex;
@@ -66,21 +75,21 @@ size_t ZSTD_compressBlock_fast_generic(ZSTD_CCtx* cctx,
if ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1))) {
mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
ip++;
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
+ ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
} else {
- U32 offset;
- if ( (matchIndex <= lowestIndex) || (MEM_read32(match) != MEM_read32(ip)) ) {
- ip += ((ip-anchor) >> g_searchStrength) + 1;
+ if ( (matchIndex <= lowestIndex)
+ || (MEM_read32(match) != MEM_read32(ip)) ) {
+ assert(stepSize >= 1);
+ ip += ((ip-anchor) >> kSearchStrength) + stepSize;
continue;
}
mLength = ZSTD_count(ip+4, match+4, iend) + 4;
- offset = (U32)(ip-match);
- while (((ip>anchor) & (match>lowest)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
- offset_2 = offset_1;
- offset_1 = offset;
-
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
- }
+ { U32 const offset = (U32)(ip-match);
+ while (((ip>anchor) & (match>lowest)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
+ offset_2 = offset_1;
+ offset_1 = offset;
+ ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
+ } }
/* match found */
ip += mLength;
@@ -88,8 +97,8 @@ size_t ZSTD_compressBlock_fast_generic(ZSTD_CCtx* cctx,
if (ip <= ilimit) {
/* Fill Table */
- hashTable[ZSTD_hashPtr(base+current+2, hBits, mls)] = current+2; /* here because current+2 could be > iend-8 */
- hashTable[ZSTD_hashPtr(ip-2, hBits, mls)] = (U32)(ip-2-base);
+ hashTable[ZSTD_hashPtr(base+current+2, hlog, mls)] = current+2; /* here because current+2 could be > iend-8 */
+ hashTable[ZSTD_hashPtr(ip-2, hlog, mls)] = (U32)(ip-2-base);
/* check immediate repcode */
while ( (ip <= ilimit)
&& ( (offset_2>0)
@@ -97,65 +106,67 @@ size_t ZSTD_compressBlock_fast_generic(ZSTD_CCtx* cctx,
/* store sequence */
size_t const rLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
{ U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; } /* swap offset_2 <=> offset_1 */
- hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip-base);
- ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, rLength-MINMATCH);
+ hashTable[ZSTD_hashPtr(ip, hlog, mls)] = (U32)(ip-base);
+ ZSTD_storeSeq(seqStore, 0, anchor, 0, rLength-MINMATCH);
ip += rLength;
anchor = ip;
continue; /* faster when present ... (?) */
} } }
/* save reps for next block */
- seqStorePtr->repToConfirm[0] = offset_1 ? offset_1 : offsetSaved;
- seqStorePtr->repToConfirm[1] = offset_2 ? offset_2 : offsetSaved;
+ rep[0] = offset_1 ? offset_1 : offsetSaved;
+ rep[1] = offset_2 ? offset_2 : offsetSaved;
/* Return the last literals size */
return iend - anchor;
}
-size_t ZSTD_compressBlock_fast(ZSTD_CCtx* ctx,
- const void* src, size_t srcSize)
+size_t ZSTD_compressBlock_fast(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
{
- const U32 mls = ctx->appliedParams.cParams.searchLength;
+ U32 const hlog = cParams->hashLog;
+ U32 const mls = cParams->searchLength;
+ U32 const stepSize = cParams->targetLength;
switch(mls)
{
default: /* includes case 3 */
case 4 :
- return ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 4);
+ return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, hlog, stepSize, 4);
case 5 :
- return ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 5);
+ return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, hlog, stepSize, 5);
case 6 :
- return ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 6);
+ return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, hlog, stepSize, 6);
case 7 :
- return ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 7);
+ return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, hlog, stepSize, 7);
}
}
-static size_t ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
- const void* src, size_t srcSize,
- const U32 mls)
+static size_t ZSTD_compressBlock_fast_extDict_generic(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize,
+ U32 const hlog, U32 const stepSize, U32 const mls)
{
- U32* hashTable = ctx->hashTable;
- const U32 hBits = ctx->appliedParams.cParams.hashLog;
- seqStore_t* seqStorePtr = &(ctx->seqStore);
- const BYTE* const base = ctx->base;
- const BYTE* const dictBase = ctx->dictBase;
+ U32* hashTable = ms->hashTable;
+ const BYTE* const base = ms->window.base;
+ const BYTE* const dictBase = ms->window.dictBase;
const BYTE* const istart = (const BYTE*)src;
const BYTE* ip = istart;
const BYTE* anchor = istart;
- const U32 lowestIndex = ctx->lowLimit;
+ const U32 lowestIndex = ms->window.lowLimit;
const BYTE* const dictStart = dictBase + lowestIndex;
- const U32 dictLimit = ctx->dictLimit;
+ const U32 dictLimit = ms->window.dictLimit;
const BYTE* const lowPrefixPtr = base + dictLimit;
const BYTE* const dictEnd = dictBase + dictLimit;
const BYTE* const iend = istart + srcSize;
const BYTE* const ilimit = iend - 8;
- U32 offset_1=seqStorePtr->rep[0], offset_2=seqStorePtr->rep[1];
+ U32 offset_1=rep[0], offset_2=rep[1];
/* Search Loop */
while (ip < ilimit) { /* < instead of <=, because (ip+1) */
- const size_t h = ZSTD_hashPtr(ip, hBits, mls);
+ const size_t h = ZSTD_hashPtr(ip, hlog, mls);
const U32 matchIndex = hashTable[h];
const BYTE* matchBase = matchIndex < dictLimit ? dictBase : base;
const BYTE* match = matchBase + matchIndex;
@@ -171,11 +182,12 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
const BYTE* repMatchEnd = repIndex < dictLimit ? dictEnd : iend;
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, lowPrefixPtr) + 4;
ip++;
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
+ ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
} else {
if ( (matchIndex < lowestIndex) ||
(MEM_read32(match) != MEM_read32(ip)) ) {
- ip += ((ip-anchor) >> g_searchStrength) + 1;
+ assert(stepSize >= 1);
+ ip += ((ip-anchor) >> kSearchStrength) + stepSize;
continue;
}
{ const BYTE* matchEnd = matchIndex < dictLimit ? dictEnd : iend;
@@ -186,7 +198,7 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
offset = current - matchIndex;
offset_2 = offset_1;
offset_1 = offset;
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
+ ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
} }
/* found a match : store it */
@@ -195,8 +207,8 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
if (ip <= ilimit) {
/* Fill Table */
- hashTable[ZSTD_hashPtr(base+current+2, hBits, mls)] = current+2;
- hashTable[ZSTD_hashPtr(ip-2, hBits, mls)] = (U32)(ip-2-base);
+ hashTable[ZSTD_hashPtr(base+current+2, hlog, mls)] = current+2;
+ hashTable[ZSTD_hashPtr(ip-2, hlog, mls)] = (U32)(ip-2-base);
/* check immediate repcode */
while (ip <= ilimit) {
U32 const current2 = (U32)(ip-base);
@@ -207,8 +219,8 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
const BYTE* const repEnd2 = repIndex2 < dictLimit ? dictEnd : iend;
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, lowPrefixPtr) + 4;
U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
- ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, repLength2-MINMATCH);
- hashTable[ZSTD_hashPtr(ip, hBits, mls)] = current2;
+ ZSTD_storeSeq(seqStore, 0, anchor, 0, repLength2-MINMATCH);
+ hashTable[ZSTD_hashPtr(ip, hlog, mls)] = current2;
ip += repLength2;
anchor = ip;
continue;
@@ -217,27 +229,31 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
} } }
/* save reps for next block */
- seqStorePtr->repToConfirm[0] = offset_1; seqStorePtr->repToConfirm[1] = offset_2;
+ rep[0] = offset_1;
+ rep[1] = offset_2;
/* Return the last literals size */
return iend - anchor;
}
-size_t ZSTD_compressBlock_fast_extDict(ZSTD_CCtx* ctx,
- const void* src, size_t srcSize)
+size_t ZSTD_compressBlock_fast_extDict(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
{
- U32 const mls = ctx->appliedParams.cParams.searchLength;
+ U32 const hlog = cParams->hashLog;
+ U32 const mls = cParams->searchLength;
+ U32 const stepSize = cParams->targetLength;
switch(mls)
{
default: /* includes case 3 */
case 4 :
- return ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 4);
+ return ZSTD_compressBlock_fast_extDict_generic(ms, seqStore, rep, src, srcSize, hlog, stepSize, 4);
case 5 :
- return ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 5);
+ return ZSTD_compressBlock_fast_extDict_generic(ms, seqStore, rep, src, srcSize, hlog, stepSize, 5);
case 6 :
- return ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 6);
+ return ZSTD_compressBlock_fast_extDict_generic(ms, seqStore, rep, src, srcSize, hlog, stepSize, 6);
case 7 :
- return ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 7);
+ return ZSTD_compressBlock_fast_extDict_generic(ms, seqStore, rep, src, srcSize, hlog, stepSize, 7);
}
}
diff --git a/thirdparty/zstd/compress/zstd_fast.h b/thirdparty/zstd/compress/zstd_fast.h
index d8b7771954..f0438ad5b4 100644
--- a/thirdparty/zstd/compress/zstd_fast.h
+++ b/thirdparty/zstd/compress/zstd_fast.h
@@ -16,13 +16,17 @@ extern "C" {
#endif
#include "mem.h" /* U32 */
-#include "zstd.h" /* ZSTD_CCtx, size_t */
+#include "zstd_compress_internal.h"
-void ZSTD_fillHashTable(ZSTD_CCtx* zc, const void* end, const U32 mls);
-size_t ZSTD_compressBlock_fast(ZSTD_CCtx* ctx,
- const void* src, size_t srcSize);
-size_t ZSTD_compressBlock_fast_extDict(ZSTD_CCtx* ctx,
- const void* src, size_t srcSize);
+void ZSTD_fillHashTable(ZSTD_matchState_t* ms,
+ ZSTD_compressionParameters const* cParams,
+ void const* end);
+size_t ZSTD_compressBlock_fast(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_fast_extDict(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
#if defined (__cplusplus)
}
diff --git a/thirdparty/zstd/compress/zstd_lazy.c b/thirdparty/zstd/compress/zstd_lazy.c
index 6d4804961d..9f158123f0 100644
--- a/thirdparty/zstd/compress/zstd_lazy.c
+++ b/thirdparty/zstd/compress/zstd_lazy.c
@@ -15,76 +15,90 @@
/*-*************************************
* Binary Tree search
***************************************/
-/** ZSTD_insertBt1() : add one or multiple positions to tree.
- * ip : assumed <= iend-8 .
- * @return : nb of positions added */
-static U32 ZSTD_insertBt1(ZSTD_CCtx* zc,
- const BYTE* const ip, const BYTE* const iend,
- U32 nbCompares, U32 const mls, U32 const extDict)
+
+void ZSTD_updateDUBT(
+ ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
+ const BYTE* ip, const BYTE* iend,
+ U32 mls)
{
- U32* const hashTable = zc->hashTable;
- U32 const hashLog = zc->appliedParams.cParams.hashLog;
- size_t const h = ZSTD_hashPtr(ip, hashLog, mls);
- U32* const bt = zc->chainTable;
- U32 const btLog = zc->appliedParams.cParams.chainLog - 1;
+ U32* const hashTable = ms->hashTable;
+ U32 const hashLog = cParams->hashLog;
+
+ U32* const bt = ms->chainTable;
+ U32 const btLog = cParams->chainLog - 1;
+ U32 const btMask = (1 << btLog) - 1;
+
+ const BYTE* const base = ms->window.base;
+ U32 const target = (U32)(ip - base);
+ U32 idx = ms->nextToUpdate;
+
+ if (idx != target)
+ DEBUGLOG(7, "ZSTD_updateDUBT, from %u to %u (dictLimit:%u)",
+ idx, target, ms->window.dictLimit);
+ assert(ip + 8 <= iend); /* condition for ZSTD_hashPtr */
+ (void)iend;
+
+ assert(idx >= ms->window.dictLimit); /* condition for valid base+idx */
+ for ( ; idx < target ; idx++) {
+ size_t const h = ZSTD_hashPtr(base + idx, hashLog, mls); /* assumption : ip + 8 <= iend */
+ U32 const matchIndex = hashTable[h];
+
+ U32* const nextCandidatePtr = bt + 2*(idx&btMask);
+ U32* const sortMarkPtr = nextCandidatePtr + 1;
+
+ DEBUGLOG(8, "ZSTD_updateDUBT: insert %u", idx);
+ hashTable[h] = idx; /* Update Hash Table */
+ *nextCandidatePtr = matchIndex; /* update BT like a chain */
+ *sortMarkPtr = ZSTD_DUBT_UNSORTED_MARK;
+ }
+ ms->nextToUpdate = target;
+}
+
+
+/** ZSTD_insertDUBT1() :
+ * sort one already inserted but unsorted position
+ * assumption : current >= btlow == (current - btmask)
+ * doesn't fail */
+static void ZSTD_insertDUBT1(
+ ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
+ U32 current, const BYTE* inputEnd,
+ U32 nbCompares, U32 btLow, int extDict)
+{
+ U32* const bt = ms->chainTable;
+ U32 const btLog = cParams->chainLog - 1;
U32 const btMask = (1 << btLog) - 1;
- U32 matchIndex = hashTable[h];
size_t commonLengthSmaller=0, commonLengthLarger=0;
- const BYTE* const base = zc->base;
- const BYTE* const dictBase = zc->dictBase;
- const U32 dictLimit = zc->dictLimit;
+ const BYTE* const base = ms->window.base;
+ const BYTE* const dictBase = ms->window.dictBase;
+ const U32 dictLimit = ms->window.dictLimit;
+ const BYTE* const ip = (current>=dictLimit) ? base + current : dictBase + current;
+ const BYTE* const iend = (current>=dictLimit) ? inputEnd : dictBase + dictLimit;
const BYTE* const dictEnd = dictBase + dictLimit;
const BYTE* const prefixStart = base + dictLimit;
const BYTE* match;
- const U32 current = (U32)(ip-base);
- const U32 btLow = btMask >= current ? 0 : current - btMask;
U32* smallerPtr = bt + 2*(current&btMask);
U32* largerPtr = smallerPtr + 1;
+ U32 matchIndex = *smallerPtr;
U32 dummy32; /* to be nullified at the end */
- U32 const windowLow = zc->lowLimit;
- U32 matchEndIdx = current+8+1;
- size_t bestLength = 8;
-#ifdef ZSTD_C_PREDICT
- U32 predictedSmall = *(bt + 2*((current-1)&btMask) + 0);
- U32 predictedLarge = *(bt + 2*((current-1)&btMask) + 1);
- predictedSmall += (predictedSmall>0);
- predictedLarge += (predictedLarge>0);
-#endif /* ZSTD_C_PREDICT */
-
- DEBUGLOG(8, "ZSTD_insertBt1 (%u)", current);
+ U32 const windowLow = ms->window.lowLimit;
- assert(ip <= iend-8); /* required for h calculation */
- hashTable[h] = current; /* Update Hash Table */
+ DEBUGLOG(8, "ZSTD_insertDUBT1(%u) (dictLimit=%u, lowLimit=%u)",
+ current, dictLimit, windowLow);
+ assert(current >= btLow);
+ assert(ip < iend); /* condition for ZSTD_count */
while (nbCompares-- && (matchIndex > windowLow)) {
U32* const nextPtr = bt + 2*(matchIndex & btMask);
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
assert(matchIndex < current);
-#ifdef ZSTD_C_PREDICT /* note : can create issues when hlog small <= 11 */
- const U32* predictPtr = bt + 2*((matchIndex-1) & btMask); /* written this way, as bt is a roll buffer */
- if (matchIndex == predictedSmall) {
- /* no need to check length, result known */
- *smallerPtr = matchIndex;
- if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
- smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
- matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
- predictedSmall = predictPtr[1] + (predictPtr[1]>0);
- continue;
- }
- if (matchIndex == predictedLarge) {
- *largerPtr = matchIndex;
- if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
- largerPtr = nextPtr;
- matchIndex = nextPtr[0];
- predictedLarge = predictPtr[0] + (predictPtr[0]>0);
- continue;
- }
-#endif
-
- if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
- assert(matchIndex+matchLength >= dictLimit); /* might be wrong if extDict is incorrectly set to 0 */
- match = base + matchIndex;
+ if ( (!extDict)
+ || (matchIndex+matchLength >= dictLimit) /* both in current segment*/
+ || (current < dictLimit) /* both in extDict */) {
+ const BYTE* const mBase = !extDict || ((matchIndex+matchLength) >= dictLimit) ? base : dictBase;
+ assert( (matchIndex+matchLength >= dictLimit) /* might be wrong if extDict is incorrectly set to 0 */
+ || (current < dictLimit) );
+ match = mBase + matchIndex;
matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend);
} else {
match = dictBase + matchIndex;
@@ -93,11 +107,8 @@ static U32 ZSTD_insertBt1(ZSTD_CCtx* zc,
match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
}
- if (matchLength > bestLength) {
- bestLength = matchLength;
- if (matchLength > matchEndIdx - matchIndex)
- matchEndIdx = matchIndex + (U32)matchLength;
- }
+ DEBUGLOG(8, "ZSTD_insertDUBT1: comparing %u with %u : found %u common bytes ",
+ current, matchIndex, (U32)matchLength);
if (ip+matchLength == iend) { /* equal : no way to know if inf or sup */
break; /* drop , to guarantee consistency ; miss a bit of compression, but other solutions can corrupt tree */
@@ -108,6 +119,8 @@ static U32 ZSTD_insertBt1(ZSTD_CCtx* zc,
*smallerPtr = matchIndex; /* update smaller idx */
commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop searching */
+ DEBUGLOG(8, "ZSTD_insertDUBT1: %u (>btLow=%u) is smaller : next => %u",
+ matchIndex, btLow, nextPtr[1]);
smallerPtr = nextPtr+1; /* new "candidate" => larger than match, which was smaller than target */
matchIndex = nextPtr[1]; /* new matchIndex, larger than previous and closer to current */
} else {
@@ -115,184 +128,205 @@ static U32 ZSTD_insertBt1(ZSTD_CCtx* zc,
*largerPtr = matchIndex;
commonLengthLarger = matchLength;
if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop searching */
+ DEBUGLOG(8, "ZSTD_insertDUBT1: %u (>btLow=%u) is larger => %u",
+ matchIndex, btLow, nextPtr[0]);
largerPtr = nextPtr;
matchIndex = nextPtr[0];
} }
*smallerPtr = *largerPtr = 0;
- if (bestLength > 384) return MIN(192, (U32)(bestLength - 384)); /* speed optimization */
- assert(matchEndIdx > current + 8);
- return matchEndIdx - (current + 8);
}
-FORCE_INLINE_TEMPLATE
-void ZSTD_updateTree_internal(ZSTD_CCtx* zc,
- const BYTE* const ip, const BYTE* const iend,
- const U32 nbCompares, const U32 mls, const U32 extDict)
-{
- const BYTE* const base = zc->base;
- U32 const target = (U32)(ip - base);
- U32 idx = zc->nextToUpdate;
- DEBUGLOG(7, "ZSTD_updateTree_internal, from %u to %u (extDict:%u)",
- idx, target, extDict);
-
- while(idx < target)
- idx += ZSTD_insertBt1(zc, base+idx, iend, nbCompares, mls, extDict);
- zc->nextToUpdate = target;
-}
-void ZSTD_updateTree(ZSTD_CCtx* zc,
- const BYTE* const ip, const BYTE* const iend,
- const U32 nbCompares, const U32 mls)
+static size_t ZSTD_DUBT_findBestMatch (
+ ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
+ const BYTE* const ip, const BYTE* const iend,
+ size_t* offsetPtr,
+ U32 const mls,
+ U32 const extDict)
{
- ZSTD_updateTree_internal(zc, ip, iend, nbCompares, mls, 0 /*extDict*/);
-}
-
-void ZSTD_updateTree_extDict(ZSTD_CCtx* zc,
- const BYTE* const ip, const BYTE* const iend,
- const U32 nbCompares, const U32 mls)
-{
- ZSTD_updateTree_internal(zc, ip, iend, nbCompares, mls, 1 /*extDict*/);
-}
+ U32* const hashTable = ms->hashTable;
+ U32 const hashLog = cParams->hashLog;
+ size_t const h = ZSTD_hashPtr(ip, hashLog, mls);
+ U32 matchIndex = hashTable[h];
+ const BYTE* const base = ms->window.base;
+ U32 const current = (U32)(ip-base);
+ U32 const windowLow = ms->window.lowLimit;
-static size_t ZSTD_insertBtAndFindBestMatch (
- ZSTD_CCtx* zc,
- const BYTE* const ip, const BYTE* const iend,
- size_t* offsetPtr,
- U32 nbCompares, const U32 mls,
- U32 extDict)
-{
- U32* const hashTable = zc->hashTable;
- U32 const hashLog = zc->appliedParams.cParams.hashLog;
- size_t const h = ZSTD_hashPtr(ip, hashLog, mls);
- U32* const bt = zc->chainTable;
- U32 const btLog = zc->appliedParams.cParams.chainLog - 1;
+ U32* const bt = ms->chainTable;
+ U32 const btLog = cParams->chainLog - 1;
U32 const btMask = (1 << btLog) - 1;
- U32 matchIndex = hashTable[h];
- size_t commonLengthSmaller=0, commonLengthLarger=0;
- const BYTE* const base = zc->base;
- const BYTE* const dictBase = zc->dictBase;
- const U32 dictLimit = zc->dictLimit;
- const BYTE* const dictEnd = dictBase + dictLimit;
- const BYTE* const prefixStart = base + dictLimit;
- const U32 current = (U32)(ip-base);
- const U32 btLow = btMask >= current ? 0 : current - btMask;
- const U32 windowLow = zc->lowLimit;
- U32* smallerPtr = bt + 2*(current&btMask);
- U32* largerPtr = bt + 2*(current&btMask) + 1;
- U32 matchEndIdx = current+8+1;
- U32 dummy32; /* to be nullified at the end */
- size_t bestLength = 0;
+ U32 const btLow = (btMask >= current) ? 0 : current - btMask;
+ U32 const unsortLimit = MAX(btLow, windowLow);
+
+ U32* nextCandidate = bt + 2*(matchIndex&btMask);
+ U32* unsortedMark = bt + 2*(matchIndex&btMask) + 1;
+ U32 nbCompares = 1U << cParams->searchLog;
+ U32 nbCandidates = nbCompares;
+ U32 previousCandidate = 0;
+ DEBUGLOG(7, "ZSTD_DUBT_findBestMatch (%u) ", current);
assert(ip <= iend-8); /* required for h calculation */
- hashTable[h] = current; /* Update Hash Table */
- while (nbCompares-- && (matchIndex > windowLow)) {
- U32* const nextPtr = bt + 2*(matchIndex & btMask);
- size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
- const BYTE* match;
+ /* reach end of unsorted candidates list */
+ while ( (matchIndex > unsortLimit)
+ && (*unsortedMark == ZSTD_DUBT_UNSORTED_MARK)
+ && (nbCandidates > 1) ) {
+ DEBUGLOG(8, "ZSTD_DUBT_findBestMatch: candidate %u is unsorted",
+ matchIndex);
+ *unsortedMark = previousCandidate;
+ previousCandidate = matchIndex;
+ matchIndex = *nextCandidate;
+ nextCandidate = bt + 2*(matchIndex&btMask);
+ unsortedMark = bt + 2*(matchIndex&btMask) + 1;
+ nbCandidates --;
+ }
- if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
- match = base + matchIndex;
- matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend);
- } else {
- match = dictBase + matchIndex;
- matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
- if (matchIndex+matchLength >= dictLimit)
- match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
- }
+ if ( (matchIndex > unsortLimit)
+ && (*unsortedMark==ZSTD_DUBT_UNSORTED_MARK) ) {
+ DEBUGLOG(7, "ZSTD_DUBT_findBestMatch: nullify last unsorted candidate %u",
+ matchIndex);
+ *nextCandidate = *unsortedMark = 0; /* nullify next candidate if it's still unsorted (note : simplification, detrimental to compression ratio, beneficial for speed) */
+ }
+
+ /* batch sort stacked candidates */
+ matchIndex = previousCandidate;
+ while (matchIndex) { /* will end on matchIndex == 0 */
+ U32* const nextCandidateIdxPtr = bt + 2*(matchIndex&btMask) + 1;
+ U32 const nextCandidateIdx = *nextCandidateIdxPtr;
+ ZSTD_insertDUBT1(ms, cParams, matchIndex, iend,
+ nbCandidates, unsortLimit, extDict);
+ matchIndex = nextCandidateIdx;
+ nbCandidates++;
+ }
- if (matchLength > bestLength) {
- if (matchLength > matchEndIdx - matchIndex)
- matchEndIdx = matchIndex + (U32)matchLength;
- if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(current-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) )
- bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + current - matchIndex;
- if (ip+matchLength == iend) { /* equal : no way to know if inf or sup */
- break; /* drop, to guarantee consistency (miss a little bit of compression) */
+ /* find longest match */
+ { size_t commonLengthSmaller=0, commonLengthLarger=0;
+ const BYTE* const dictBase = ms->window.dictBase;
+ const U32 dictLimit = ms->window.dictLimit;
+ const BYTE* const dictEnd = dictBase + dictLimit;
+ const BYTE* const prefixStart = base + dictLimit;
+ U32* smallerPtr = bt + 2*(current&btMask);
+ U32* largerPtr = bt + 2*(current&btMask) + 1;
+ U32 matchEndIdx = current+8+1;
+ U32 dummy32; /* to be nullified at the end */
+ size_t bestLength = 0;
+
+ matchIndex = hashTable[h];
+ hashTable[h] = current; /* Update Hash Table */
+
+ while (nbCompares-- && (matchIndex > windowLow)) {
+ U32* const nextPtr = bt + 2*(matchIndex & btMask);
+ size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
+ const BYTE* match;
+
+ if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
+ match = base + matchIndex;
+ matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend);
+ } else {
+ match = dictBase + matchIndex;
+ matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
+ if (matchIndex+matchLength >= dictLimit)
+ match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
}
- }
- if (match[matchLength] < ip[matchLength]) {
- /* match is smaller than current */
- *smallerPtr = matchIndex; /* update smaller idx */
- commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
- if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
- smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
- matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
- } else {
- /* match is larger than current */
- *largerPtr = matchIndex;
- commonLengthLarger = matchLength;
- if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
- largerPtr = nextPtr;
- matchIndex = nextPtr[0];
- } }
+ if (matchLength > bestLength) {
+ if (matchLength > matchEndIdx - matchIndex)
+ matchEndIdx = matchIndex + (U32)matchLength;
+ if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(current-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) )
+ bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + current - matchIndex;
+ if (ip+matchLength == iend) { /* equal : no way to know if inf or sup */
+ break; /* drop, to guarantee consistency (miss a little bit of compression) */
+ }
+ }
- *smallerPtr = *largerPtr = 0;
+ if (match[matchLength] < ip[matchLength]) {
+ /* match is smaller than current */
+ *smallerPtr = matchIndex; /* update smaller idx */
+ commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
+ if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
+ smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
+ matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
+ } else {
+ /* match is larger than current */
+ *largerPtr = matchIndex;
+ commonLengthLarger = matchLength;
+ if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
+ largerPtr = nextPtr;
+ matchIndex = nextPtr[0];
+ } }
+
+ *smallerPtr = *largerPtr = 0;
- assert(matchEndIdx > current+8);
- zc->nextToUpdate = matchEndIdx - 8; /* skip repetitive patterns */
- return bestLength;
+ assert(matchEndIdx > current+8); /* ensure nextToUpdate is increased */
+ ms->nextToUpdate = matchEndIdx - 8; /* skip repetitive patterns */
+ if (bestLength >= MINMATCH) {
+ U32 const mIndex = current - ((U32)*offsetPtr - ZSTD_REP_MOVE); (void)mIndex;
+ DEBUGLOG(8, "ZSTD_DUBT_findBestMatch(%u) : found match of length %u and offsetCode %u (pos %u)",
+ current, (U32)bestLength, (U32)*offsetPtr, mIndex);
+ }
+ return bestLength;
+ }
}
/** ZSTD_BtFindBestMatch() : Tree updater, providing best match */
static size_t ZSTD_BtFindBestMatch (
- ZSTD_CCtx* zc,
+ ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
const BYTE* const ip, const BYTE* const iLimit,
size_t* offsetPtr,
- const U32 maxNbAttempts, const U32 mls)
+ const U32 mls /* template */)
{
- if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
- ZSTD_updateTree(zc, ip, iLimit, maxNbAttempts, mls);
- return ZSTD_insertBtAndFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, mls, 0);
+ DEBUGLOG(7, "ZSTD_BtFindBestMatch");
+ if (ip < ms->window.base + ms->nextToUpdate) return 0; /* skipped area */
+ ZSTD_updateDUBT(ms, cParams, ip, iLimit, mls);
+ return ZSTD_DUBT_findBestMatch(ms, cParams, ip, iLimit, offsetPtr, mls, 0);
}
static size_t ZSTD_BtFindBestMatch_selectMLS (
- ZSTD_CCtx* zc, /* Index table will be updated */
+ ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
const BYTE* ip, const BYTE* const iLimit,
- size_t* offsetPtr,
- const U32 maxNbAttempts, const U32 matchLengthSearch)
+ size_t* offsetPtr)
{
- switch(matchLengthSearch)
+ switch(cParams->searchLength)
{
default : /* includes case 3 */
- case 4 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4);
- case 5 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5);
+ case 4 : return ZSTD_BtFindBestMatch(ms, cParams, ip, iLimit, offsetPtr, 4);
+ case 5 : return ZSTD_BtFindBestMatch(ms, cParams, ip, iLimit, offsetPtr, 5);
case 7 :
- case 6 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6);
+ case 6 : return ZSTD_BtFindBestMatch(ms, cParams, ip, iLimit, offsetPtr, 6);
}
}
/** Tree updater, providing best match */
static size_t ZSTD_BtFindBestMatch_extDict (
- ZSTD_CCtx* zc,
+ ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
const BYTE* const ip, const BYTE* const iLimit,
size_t* offsetPtr,
- const U32 maxNbAttempts, const U32 mls)
+ const U32 mls)
{
- if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
- ZSTD_updateTree_extDict(zc, ip, iLimit, maxNbAttempts, mls);
- return ZSTD_insertBtAndFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, mls, 1);
+ DEBUGLOG(7, "ZSTD_BtFindBestMatch_extDict");
+ if (ip < ms->window.base + ms->nextToUpdate) return 0; /* skipped area */
+ ZSTD_updateDUBT(ms, cParams, ip, iLimit, mls);
+ return ZSTD_DUBT_findBestMatch(ms, cParams, ip, iLimit, offsetPtr, mls, 1);
}
static size_t ZSTD_BtFindBestMatch_selectMLS_extDict (
- ZSTD_CCtx* zc, /* Index table will be updated */
+ ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
const BYTE* ip, const BYTE* const iLimit,
- size_t* offsetPtr,
- const U32 maxNbAttempts, const U32 matchLengthSearch)
+ size_t* offsetPtr)
{
- switch(matchLengthSearch)
+ switch(cParams->searchLength)
{
default : /* includes case 3 */
- case 4 : return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4);
- case 5 : return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5);
+ case 4 : return ZSTD_BtFindBestMatch_extDict(ms, cParams, ip, iLimit, offsetPtr, 4);
+ case 5 : return ZSTD_BtFindBestMatch_extDict(ms, cParams, ip, iLimit, offsetPtr, 5);
case 7 :
- case 6 : return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6);
+ case 6 : return ZSTD_BtFindBestMatch_extDict(ms, cParams, ip, iLimit, offsetPtr, 6);
}
}
@@ -305,15 +339,17 @@ static size_t ZSTD_BtFindBestMatch_selectMLS_extDict (
/* Update chains up to ip (excluded)
Assumption : always within prefix (i.e. not within extDict) */
-U32 ZSTD_insertAndFindFirstIndex (ZSTD_CCtx* zc, const BYTE* ip, U32 mls)
+static U32 ZSTD_insertAndFindFirstIndex_internal(
+ ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
+ const BYTE* ip, U32 const mls)
{
- U32* const hashTable = zc->hashTable;
- const U32 hashLog = zc->appliedParams.cParams.hashLog;
- U32* const chainTable = zc->chainTable;
- const U32 chainMask = (1 << zc->appliedParams.cParams.chainLog) - 1;
- const BYTE* const base = zc->base;
+ U32* const hashTable = ms->hashTable;
+ const U32 hashLog = cParams->hashLog;
+ U32* const chainTable = ms->chainTable;
+ const U32 chainMask = (1 << cParams->chainLog) - 1;
+ const BYTE* const base = ms->window.base;
const U32 target = (U32)(ip - base);
- U32 idx = zc->nextToUpdate;
+ U32 idx = ms->nextToUpdate;
while(idx < target) { /* catch up */
size_t const h = ZSTD_hashPtr(base+idx, hashLog, mls);
@@ -322,35 +358,42 @@ U32 ZSTD_insertAndFindFirstIndex (ZSTD_CCtx* zc, const BYTE* ip, U32 mls)
idx++;
}
- zc->nextToUpdate = target;
+ ms->nextToUpdate = target;
return hashTable[ZSTD_hashPtr(ip, hashLog, mls)];
}
+U32 ZSTD_insertAndFindFirstIndex(
+ ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
+ const BYTE* ip)
+{
+ return ZSTD_insertAndFindFirstIndex_internal(ms, cParams, ip, cParams->searchLength);
+}
+
/* inlining is important to hardwire a hot branch (template emulation) */
FORCE_INLINE_TEMPLATE
size_t ZSTD_HcFindBestMatch_generic (
- ZSTD_CCtx* zc, /* Index table will be updated */
+ ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
const BYTE* const ip, const BYTE* const iLimit,
size_t* offsetPtr,
- const U32 maxNbAttempts, const U32 mls, const U32 extDict)
+ const U32 mls, const U32 extDict)
{
- U32* const chainTable = zc->chainTable;
- const U32 chainSize = (1 << zc->appliedParams.cParams.chainLog);
+ U32* const chainTable = ms->chainTable;
+ const U32 chainSize = (1 << cParams->chainLog);
const U32 chainMask = chainSize-1;
- const BYTE* const base = zc->base;
- const BYTE* const dictBase = zc->dictBase;
- const U32 dictLimit = zc->dictLimit;
+ const BYTE* const base = ms->window.base;
+ const BYTE* const dictBase = ms->window.dictBase;
+ const U32 dictLimit = ms->window.dictLimit;
const BYTE* const prefixStart = base + dictLimit;
const BYTE* const dictEnd = dictBase + dictLimit;
- const U32 lowLimit = zc->lowLimit;
+ const U32 lowLimit = ms->window.lowLimit;
const U32 current = (U32)(ip-base);
const U32 minChain = current > chainSize ? current - chainSize : 0;
- int nbAttempts=maxNbAttempts;
+ U32 nbAttempts = 1U << cParams->searchLog;
size_t ml=4-1;
/* HC4 match finder */
- U32 matchIndex = ZSTD_insertAndFindFirstIndex (zc, ip, mls);
+ U32 matchIndex = ZSTD_insertAndFindFirstIndex_internal(ms, cParams, ip, mls);
for ( ; (matchIndex>lowLimit) & (nbAttempts>0) ; nbAttempts--) {
size_t currentMl=0;
@@ -381,35 +424,33 @@ size_t ZSTD_HcFindBestMatch_generic (
FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_selectMLS (
- ZSTD_CCtx* zc,
+ ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
const BYTE* ip, const BYTE* const iLimit,
- size_t* offsetPtr,
- const U32 maxNbAttempts, const U32 matchLengthSearch)
+ size_t* offsetPtr)
{
- switch(matchLengthSearch)
+ switch(cParams->searchLength)
{
default : /* includes case 3 */
- case 4 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4, 0);
- case 5 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5, 0);
+ case 4 : return ZSTD_HcFindBestMatch_generic(ms, cParams, ip, iLimit, offsetPtr, 4, 0);
+ case 5 : return ZSTD_HcFindBestMatch_generic(ms, cParams, ip, iLimit, offsetPtr, 5, 0);
case 7 :
- case 6 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6, 0);
+ case 6 : return ZSTD_HcFindBestMatch_generic(ms, cParams, ip, iLimit, offsetPtr, 6, 0);
}
}
FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_extDict_selectMLS (
- ZSTD_CCtx* const zc,
+ ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
const BYTE* ip, const BYTE* const iLimit,
- size_t* const offsetPtr,
- U32 const maxNbAttempts, U32 const matchLengthSearch)
+ size_t* const offsetPtr)
{
- switch(matchLengthSearch)
+ switch(cParams->searchLength)
{
default : /* includes case 3 */
- case 4 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4, 1);
- case 5 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5, 1);
+ case 4 : return ZSTD_HcFindBestMatch_generic(ms, cParams, ip, iLimit, offsetPtr, 4, 1);
+ case 5 : return ZSTD_HcFindBestMatch_generic(ms, cParams, ip, iLimit, offsetPtr, 5, 1);
case 7 :
- case 6 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6, 1);
+ case 6 : return ZSTD_HcFindBestMatch_generic(ms, cParams, ip, iLimit, offsetPtr, 6, 1);
}
}
@@ -418,30 +459,29 @@ FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_extDict_selectMLS (
* Common parser - lazy strategy
*********************************/
FORCE_INLINE_TEMPLATE
-size_t ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
- const void* src, size_t srcSize,
- const U32 searchMethod, const U32 depth)
+size_t ZSTD_compressBlock_lazy_generic(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore,
+ U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams,
+ const void* src, size_t srcSize,
+ const U32 searchMethod, const U32 depth)
{
- seqStore_t* seqStorePtr = &(ctx->seqStore);
const BYTE* const istart = (const BYTE*)src;
const BYTE* ip = istart;
const BYTE* anchor = istart;
const BYTE* const iend = istart + srcSize;
const BYTE* const ilimit = iend - 8;
- const BYTE* const base = ctx->base + ctx->dictLimit;
+ const BYTE* const base = ms->window.base + ms->window.dictLimit;
- U32 const maxSearches = 1 << ctx->appliedParams.cParams.searchLog;
- U32 const mls = ctx->appliedParams.cParams.searchLength;
-
- typedef size_t (*searchMax_f)(ZSTD_CCtx* zc, const BYTE* ip, const BYTE* iLimit,
- size_t* offsetPtr,
- U32 maxNbAttempts, U32 matchLengthSearch);
+ typedef size_t (*searchMax_f)(
+ ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
+ const BYTE* ip, const BYTE* iLimit, size_t* offsetPtr);
searchMax_f const searchMax = searchMethod ? ZSTD_BtFindBestMatch_selectMLS : ZSTD_HcFindBestMatch_selectMLS;
- U32 offset_1 = seqStorePtr->rep[0], offset_2 = seqStorePtr->rep[1], savedOffset=0;
+ U32 offset_1 = rep[0], offset_2 = rep[1], savedOffset=0;
/* init */
ip += (ip==base);
- ctx->nextToUpdate3 = ctx->nextToUpdate;
+ ms->nextToUpdate3 = ms->nextToUpdate;
{ U32 const maxRep = (U32)(ip-base);
if (offset_2 > maxRep) savedOffset = offset_2, offset_2 = 0;
if (offset_1 > maxRep) savedOffset = offset_1, offset_1 = 0;
@@ -462,13 +502,13 @@ size_t ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
/* first search (depth 0) */
{ size_t offsetFound = 99999999;
- size_t const ml2 = searchMax(ctx, ip, iend, &offsetFound, maxSearches, mls);
+ size_t const ml2 = searchMax(ms, cParams, ip, iend, &offsetFound);
if (ml2 > matchLength)
matchLength = ml2, start = ip, offset=offsetFound;
}
if (matchLength < 4) {
- ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */
+ ip += ((ip-anchor) >> kSearchStrength) + 1; /* jump faster over incompressible sections */
continue;
}
@@ -484,7 +524,7 @@ size_t ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
matchLength = mlRep, offset = 0, start = ip;
}
{ size_t offset2=99999999;
- size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
+ size_t const ml2 = searchMax(ms, cParams, ip, iend, &offset2);
int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 4);
if ((ml2 >= 4) && (gain2 > gain1)) {
@@ -503,7 +543,7 @@ size_t ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
matchLength = ml2, offset = 0, start = ip;
}
{ size_t offset2=99999999;
- size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
+ size_t const ml2 = searchMax(ms, cParams, ip, iend, &offset2);
int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 7);
if ((ml2 >= 4) && (gain2 > gain1)) {
@@ -528,7 +568,7 @@ size_t ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
/* store sequence */
_storeSequence:
{ size_t const litLength = start - anchor;
- ZSTD_storeSeq(seqStorePtr, litLength, anchor, (U32)offset, matchLength-MINMATCH);
+ ZSTD_storeSeq(seqStore, litLength, anchor, (U32)offset, matchLength-MINMATCH);
anchor = ip = start + matchLength;
}
@@ -538,73 +578,80 @@ _storeSequence:
/* store sequence */
matchLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap repcodes */
- ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, matchLength-MINMATCH);
+ ZSTD_storeSeq(seqStore, 0, anchor, 0, matchLength-MINMATCH);
ip += matchLength;
anchor = ip;
continue; /* faster when present ... (?) */
} }
/* Save reps for next block */
- seqStorePtr->repToConfirm[0] = offset_1 ? offset_1 : savedOffset;
- seqStorePtr->repToConfirm[1] = offset_2 ? offset_2 : savedOffset;
+ rep[0] = offset_1 ? offset_1 : savedOffset;
+ rep[1] = offset_2 ? offset_2 : savedOffset;
/* Return the last literals size */
return iend - anchor;
}
-size_t ZSTD_compressBlock_btlazy2(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
+size_t ZSTD_compressBlock_btlazy2(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
{
- return ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 1, 2);
+ return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, cParams, src, srcSize, 1, 2);
}
-size_t ZSTD_compressBlock_lazy2(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
+size_t ZSTD_compressBlock_lazy2(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
{
- return ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 2);
+ return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, cParams, src, srcSize, 0, 2);
}
-size_t ZSTD_compressBlock_lazy(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
+size_t ZSTD_compressBlock_lazy(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
{
- return ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 1);
+ return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, cParams, src, srcSize, 0, 1);
}
-size_t ZSTD_compressBlock_greedy(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
+size_t ZSTD_compressBlock_greedy(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
{
- return ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 0);
+ return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, cParams, src, srcSize, 0, 0);
}
FORCE_INLINE_TEMPLATE
-size_t ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
- const void* src, size_t srcSize,
- const U32 searchMethod, const U32 depth)
+size_t ZSTD_compressBlock_lazy_extDict_generic(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore,
+ U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams,
+ const void* src, size_t srcSize,
+ const U32 searchMethod, const U32 depth)
{
- seqStore_t* seqStorePtr = &(ctx->seqStore);
const BYTE* const istart = (const BYTE*)src;
const BYTE* ip = istart;
const BYTE* anchor = istart;
const BYTE* const iend = istart + srcSize;
const BYTE* const ilimit = iend - 8;
- const BYTE* const base = ctx->base;
- const U32 dictLimit = ctx->dictLimit;
- const U32 lowestIndex = ctx->lowLimit;
+ const BYTE* const base = ms->window.base;
+ const U32 dictLimit = ms->window.dictLimit;
+ const U32 lowestIndex = ms->window.lowLimit;
const BYTE* const prefixStart = base + dictLimit;
- const BYTE* const dictBase = ctx->dictBase;
+ const BYTE* const dictBase = ms->window.dictBase;
const BYTE* const dictEnd = dictBase + dictLimit;
- const BYTE* const dictStart = dictBase + ctx->lowLimit;
+ const BYTE* const dictStart = dictBase + lowestIndex;
- const U32 maxSearches = 1 << ctx->appliedParams.cParams.searchLog;
- const U32 mls = ctx->appliedParams.cParams.searchLength;
-
- typedef size_t (*searchMax_f)(ZSTD_CCtx* zc, const BYTE* ip, const BYTE* iLimit,
- size_t* offsetPtr,
- U32 maxNbAttempts, U32 matchLengthSearch);
+ typedef size_t (*searchMax_f)(
+ ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
+ const BYTE* ip, const BYTE* iLimit, size_t* offsetPtr);
searchMax_f searchMax = searchMethod ? ZSTD_BtFindBestMatch_selectMLS_extDict : ZSTD_HcFindBestMatch_extDict_selectMLS;
- U32 offset_1 = seqStorePtr->rep[0], offset_2 = seqStorePtr->rep[1];
+ U32 offset_1 = rep[0], offset_2 = rep[1];
/* init */
- ctx->nextToUpdate3 = ctx->nextToUpdate;
+ ms->nextToUpdate3 = ms->nextToUpdate;
ip += (ip == prefixStart);
/* Match Loop */
@@ -628,13 +675,13 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
/* first search (depth 0) */
{ size_t offsetFound = 99999999;
- size_t const ml2 = searchMax(ctx, ip, iend, &offsetFound, maxSearches, mls);
+ size_t const ml2 = searchMax(ms, cParams, ip, iend, &offsetFound);
if (ml2 > matchLength)
matchLength = ml2, start = ip, offset=offsetFound;
}
if (matchLength < 4) {
- ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */
+ ip += ((ip-anchor) >> kSearchStrength) + 1; /* jump faster over incompressible sections */
continue;
}
@@ -661,7 +708,7 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
/* search match, depth 1 */
{ size_t offset2=99999999;
- size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
+ size_t const ml2 = searchMax(ms, cParams, ip, iend, &offset2);
int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 4);
if ((ml2 >= 4) && (gain2 > gain1)) {
@@ -691,7 +738,7 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
/* search match, depth 2 */
{ size_t offset2=99999999;
- size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
+ size_t const ml2 = searchMax(ms, cParams, ip, iend, &offset2);
int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 7);
if ((ml2 >= 4) && (gain2 > gain1)) {
@@ -713,7 +760,7 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
/* store sequence */
_storeSequence:
{ size_t const litLength = start - anchor;
- ZSTD_storeSeq(seqStorePtr, litLength, anchor, (U32)offset, matchLength-MINMATCH);
+ ZSTD_storeSeq(seqStore, litLength, anchor, (U32)offset, matchLength-MINMATCH);
anchor = ip = start + matchLength;
}
@@ -728,7 +775,7 @@ _storeSequence:
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
matchLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;
offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap offset history */
- ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, matchLength-MINMATCH);
+ ZSTD_storeSeq(seqStore, 0, anchor, 0, matchLength-MINMATCH);
ip += matchLength;
anchor = ip;
continue; /* faster when present ... (?) */
@@ -737,29 +784,41 @@ _storeSequence:
} }
/* Save reps for next block */
- seqStorePtr->repToConfirm[0] = offset_1; seqStorePtr->repToConfirm[1] = offset_2;
+ rep[0] = offset_1;
+ rep[1] = offset_2;
/* Return the last literals size */
return iend - anchor;
}
-size_t ZSTD_compressBlock_greedy_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
+size_t ZSTD_compressBlock_greedy_extDict(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
{
- return ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 0);
+ return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, cParams, src, srcSize, 0, 0);
}
-size_t ZSTD_compressBlock_lazy_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
+size_t ZSTD_compressBlock_lazy_extDict(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
+
{
- return ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 1);
+ return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, cParams, src, srcSize, 0, 1);
}
-size_t ZSTD_compressBlock_lazy2_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
+size_t ZSTD_compressBlock_lazy2_extDict(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
+
{
- return ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 2);
+ return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, cParams, src, srcSize, 0, 2);
}
-size_t ZSTD_compressBlock_btlazy2_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
+size_t ZSTD_compressBlock_btlazy2_extDict(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
+
{
- return ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 1, 2);
+ return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, cParams, src, srcSize, 1, 2);
}
diff --git a/thirdparty/zstd/compress/zstd_lazy.h b/thirdparty/zstd/compress/zstd_lazy.h
index 74e1fd6970..bda064f199 100644
--- a/thirdparty/zstd/compress/zstd_lazy.h
+++ b/thirdparty/zstd/compress/zstd_lazy.h
@@ -15,22 +15,39 @@
extern "C" {
#endif
-#include "mem.h" /* U32 */
-#include "zstd.h" /* ZSTD_CCtx, size_t */
-
-U32 ZSTD_insertAndFindFirstIndex (ZSTD_CCtx* zc, const BYTE* ip, U32 mls);
-void ZSTD_updateTree(ZSTD_CCtx* zc, const BYTE* const ip, const BYTE* const iend, const U32 nbCompares, const U32 mls);
-void ZSTD_updateTree_extDict(ZSTD_CCtx* zc, const BYTE* const ip, const BYTE* const iend, const U32 nbCompares, const U32 mls);
-
-size_t ZSTD_compressBlock_btlazy2(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
-size_t ZSTD_compressBlock_lazy2(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
-size_t ZSTD_compressBlock_lazy(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
-size_t ZSTD_compressBlock_greedy(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
-
-size_t ZSTD_compressBlock_greedy_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
-size_t ZSTD_compressBlock_lazy_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
-size_t ZSTD_compressBlock_lazy2_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
-size_t ZSTD_compressBlock_btlazy2_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
+#include "zstd_compress_internal.h"
+
+U32 ZSTD_insertAndFindFirstIndex(
+ ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
+ const BYTE* ip);
+
+void ZSTD_preserveUnsortedMark (U32* const table, U32 const size, U32 const reducerValue); /*! used in ZSTD_reduceIndex(). pre-emptively increase value of ZSTD_DUBT_UNSORTED_MARK */
+
+size_t ZSTD_compressBlock_btlazy2(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_lazy2(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_lazy(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_greedy(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+
+size_t ZSTD_compressBlock_greedy_extDict(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_lazy_extDict(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_lazy2_extDict(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_btlazy2_extDict(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
#if defined (__cplusplus)
}
diff --git a/thirdparty/zstd/compress/zstd_ldm.c b/thirdparty/zstd/compress/zstd_ldm.c
index be50872cf7..bffd8a3dfa 100644
--- a/thirdparty/zstd/compress/zstd_ldm.c
+++ b/thirdparty/zstd/compress/zstd_ldm.c
@@ -17,36 +17,45 @@
#define LDM_HASH_RLOG 7
#define LDM_HASH_CHAR_OFFSET 10
-size_t ZSTD_ldm_initializeParameters(ldmParams_t* params, U32 enableLdm)
+void ZSTD_ldm_adjustParameters(ldmParams_t* params,
+ ZSTD_compressionParameters const* cParams)
{
+ U32 const windowLog = cParams->windowLog;
ZSTD_STATIC_ASSERT(LDM_BUCKET_SIZE_LOG <= ZSTD_LDM_BUCKETSIZELOG_MAX);
- params->enableLdm = enableLdm>0;
- params->hashLog = 0;
- params->bucketSizeLog = LDM_BUCKET_SIZE_LOG;
- params->minMatchLength = LDM_MIN_MATCH_LENGTH;
- params->hashEveryLog = ZSTD_LDM_HASHEVERYLOG_NOTSET;
- return 0;
-}
-
-void ZSTD_ldm_adjustParameters(ldmParams_t* params, U32 windowLog)
-{
+ DEBUGLOG(4, "ZSTD_ldm_adjustParameters");
+ if (!params->bucketSizeLog) params->bucketSizeLog = LDM_BUCKET_SIZE_LOG;
+ if (!params->minMatchLength) params->minMatchLength = LDM_MIN_MATCH_LENGTH;
+ if (cParams->strategy >= ZSTD_btopt) {
+ /* Get out of the way of the optimal parser */
+ U32 const minMatch = MAX(cParams->targetLength, params->minMatchLength);
+ assert(minMatch >= ZSTD_LDM_MINMATCH_MIN);
+ assert(minMatch <= ZSTD_LDM_MINMATCH_MAX);
+ params->minMatchLength = minMatch;
+ }
if (params->hashLog == 0) {
params->hashLog = MAX(ZSTD_HASHLOG_MIN, windowLog - LDM_HASH_RLOG);
assert(params->hashLog <= ZSTD_HASHLOG_MAX);
}
- if (params->hashEveryLog == ZSTD_LDM_HASHEVERYLOG_NOTSET) {
+ if (params->hashEveryLog == 0) {
params->hashEveryLog =
windowLog < params->hashLog ? 0 : windowLog - params->hashLog;
}
params->bucketSizeLog = MIN(params->bucketSizeLog, params->hashLog);
}
-size_t ZSTD_ldm_getTableSize(U32 hashLog, U32 bucketSizeLog) {
- size_t const ldmHSize = ((size_t)1) << hashLog;
- size_t const ldmBucketSizeLog = MIN(bucketSizeLog, hashLog);
+size_t ZSTD_ldm_getTableSize(ldmParams_t params)
+{
+ size_t const ldmHSize = ((size_t)1) << params.hashLog;
+ size_t const ldmBucketSizeLog = MIN(params.bucketSizeLog, params.hashLog);
size_t const ldmBucketSize =
- ((size_t)1) << (hashLog - ldmBucketSizeLog);
- return ldmBucketSize + (ldmHSize * (sizeof(ldmEntry_t)));
+ ((size_t)1) << (params.hashLog - ldmBucketSizeLog);
+ size_t const totalSize = ldmBucketSize + ldmHSize * sizeof(ldmEntry_t);
+ return params.enableLdm ? totalSize : 0;
+}
+
+size_t ZSTD_ldm_getMaxNbSeq(ldmParams_t params, size_t maxChunkSize)
+{
+ return params.enableLdm ? (maxChunkSize / params.minMatchLength) : 0;
}
/** ZSTD_ldm_getSmallHash() :
@@ -167,6 +176,7 @@ static U64 ZSTD_ldm_ipow(U64 base, U64 exp)
}
U64 ZSTD_ldm_getHashPower(U32 minMatchLength) {
+ DEBUGLOG(4, "ZSTD_ldm_getHashPower: mml=%u", minMatchLength);
assert(minMatchLength >= ZSTD_LDM_MINMATCH_MIN);
return ZSTD_ldm_ipow(prime8bytes, minMatchLength - 1);
}
@@ -205,21 +215,22 @@ static size_t ZSTD_ldm_countBackwardsMatch(
*
* The tables for the other strategies are filled within their
* block compressors. */
-static size_t ZSTD_ldm_fillFastTables(ZSTD_CCtx* zc, const void* end)
+static size_t ZSTD_ldm_fillFastTables(ZSTD_matchState_t* ms,
+ ZSTD_compressionParameters const* cParams,
+ void const* end)
{
const BYTE* const iend = (const BYTE*)end;
- const U32 mls = zc->appliedParams.cParams.searchLength;
- switch(zc->appliedParams.cParams.strategy)
+ switch(cParams->strategy)
{
case ZSTD_fast:
- ZSTD_fillHashTable(zc, iend, mls);
- zc->nextToUpdate = (U32)(iend - zc->base);
+ ZSTD_fillHashTable(ms, cParams, iend);
+ ms->nextToUpdate = (U32)(iend - ms->window.base);
break;
case ZSTD_dfast:
- ZSTD_fillDoubleHashTable(zc, iend, mls);
- zc->nextToUpdate = (U32)(iend - zc->base);
+ ZSTD_fillDoubleHashTable(ms, cParams, iend);
+ ms->nextToUpdate = (U32)(iend - ms->window.base);
break;
case ZSTD_greedy:
@@ -268,69 +279,62 @@ static U64 ZSTD_ldm_fillLdmHashTable(ldmState_t* state,
* Sets cctx->nextToUpdate to a position corresponding closer to anchor
* if it is far way
* (after a long match, only update tables a limited amount). */
-static void ZSTD_ldm_limitTableUpdate(ZSTD_CCtx* cctx, const BYTE* anchor)
+static void ZSTD_ldm_limitTableUpdate(ZSTD_matchState_t* ms, const BYTE* anchor)
{
- U32 const current = (U32)(anchor - cctx->base);
- if (current > cctx->nextToUpdate + 1024) {
- cctx->nextToUpdate =
- current - MIN(512, current - cctx->nextToUpdate - 1024);
+ U32 const current = (U32)(anchor - ms->window.base);
+ if (current > ms->nextToUpdate + 1024) {
+ ms->nextToUpdate =
+ current - MIN(512, current - ms->nextToUpdate - 1024);
}
}
-typedef size_t (*ZSTD_blockCompressor) (ZSTD_CCtx* ctx, const void* src, size_t srcSize);
-/* defined in zstd_compress.c */
-ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict);
-
-FORCE_INLINE_TEMPLATE
-size_t ZSTD_compressBlock_ldm_generic(ZSTD_CCtx* cctx,
- const void* src, size_t srcSize)
+static size_t ZSTD_ldm_generateSequences_internal(
+ ldmState_t* ldmState, rawSeqStore_t* rawSeqStore,
+ ldmParams_t const* params, void const* src, size_t srcSize)
{
- ldmState_t* const ldmState = &(cctx->ldmState);
- const ldmParams_t ldmParams = cctx->appliedParams.ldmParams;
- const U64 hashPower = ldmState->hashPower;
- const U32 hBits = ldmParams.hashLog - ldmParams.bucketSizeLog;
- const U32 ldmBucketSize = ((U32)1 << ldmParams.bucketSizeLog);
- const U32 ldmTagMask = ((U32)1 << ldmParams.hashEveryLog) - 1;
- seqStore_t* const seqStorePtr = &(cctx->seqStore);
- const BYTE* const base = cctx->base;
- const BYTE* const istart = (const BYTE*)src;
- const BYTE* ip = istart;
- const BYTE* anchor = istart;
- const U32 lowestIndex = cctx->dictLimit;
- const BYTE* const lowest = base + lowestIndex;
- const BYTE* const iend = istart + srcSize;
- const BYTE* const ilimit = iend - MAX(ldmParams.minMatchLength, HASH_READ_SIZE);
-
- const ZSTD_blockCompressor blockCompressor =
- ZSTD_selectBlockCompressor(cctx->appliedParams.cParams.strategy, 0);
- U32* const repToConfirm = seqStorePtr->repToConfirm;
- U32 savedRep[ZSTD_REP_NUM];
+ /* LDM parameters */
+ int const extDict = ZSTD_window_hasExtDict(ldmState->window);
+ U32 const minMatchLength = params->minMatchLength;
+ U64 const hashPower = ldmState->hashPower;
+ U32 const hBits = params->hashLog - params->bucketSizeLog;
+ U32 const ldmBucketSize = 1U << params->bucketSizeLog;
+ U32 const hashEveryLog = params->hashEveryLog;
+ U32 const ldmTagMask = (1U << params->hashEveryLog) - 1;
+ /* Prefix and extDict parameters */
+ U32 const dictLimit = ldmState->window.dictLimit;
+ U32 const lowestIndex = extDict ? ldmState->window.lowLimit : dictLimit;
+ BYTE const* const base = ldmState->window.base;
+ BYTE const* const dictBase = extDict ? ldmState->window.dictBase : NULL;
+ BYTE const* const dictStart = extDict ? dictBase + lowestIndex : NULL;
+ BYTE const* const dictEnd = extDict ? dictBase + dictLimit : NULL;
+ BYTE const* const lowPrefixPtr = base + dictLimit;
+ /* Input bounds */
+ BYTE const* const istart = (BYTE const*)src;
+ BYTE const* const iend = istart + srcSize;
+ BYTE const* const ilimit = iend - MAX(minMatchLength, HASH_READ_SIZE);
+ /* Input positions */
+ BYTE const* anchor = istart;
+ BYTE const* ip = istart;
+ /* Rolling hash */
+ BYTE const* lastHashed = NULL;
U64 rollingHash = 0;
- const BYTE* lastHashed = NULL;
- size_t i, lastLiterals;
- /* Save seqStorePtr->rep and copy repToConfirm */
- for (i = 0; i < ZSTD_REP_NUM; i++)
- savedRep[i] = repToConfirm[i] = seqStorePtr->rep[i];
-
- /* Main Search Loop */
- while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
+ while (ip <= ilimit) {
size_t mLength;
U32 const current = (U32)(ip - base);
size_t forwardMatchLength = 0, backwardMatchLength = 0;
ldmEntry_t* bestEntry = NULL;
if (ip != istart) {
rollingHash = ZSTD_ldm_updateHash(rollingHash, lastHashed[0],
- lastHashed[ldmParams.minMatchLength],
+ lastHashed[minMatchLength],
hashPower);
} else {
- rollingHash = ZSTD_ldm_getRollingHash(ip, ldmParams.minMatchLength);
+ rollingHash = ZSTD_ldm_getRollingHash(ip, minMatchLength);
}
lastHashed = ip;
/* Do not insert and do not look for a match */
- if (ZSTD_ldm_getTag(rollingHash, hBits, ldmParams.hashEveryLog) !=
- ldmTagMask) {
+ if (ZSTD_ldm_getTag(rollingHash, hBits, hashEveryLog) != ldmTagMask) {
ip++;
continue;
}
@@ -340,27 +344,49 @@ size_t ZSTD_compressBlock_ldm_generic(ZSTD_CCtx* cctx,
ldmEntry_t* const bucket =
ZSTD_ldm_getBucket(ldmState,
ZSTD_ldm_getSmallHash(rollingHash, hBits),
- ldmParams);
+ *params);
ldmEntry_t* cur;
size_t bestMatchLength = 0;
U32 const checksum = ZSTD_ldm_getChecksum(rollingHash, hBits);
for (cur = bucket; cur < bucket + ldmBucketSize; ++cur) {
- const BYTE* const pMatch = cur->offset + base;
size_t curForwardMatchLength, curBackwardMatchLength,
curTotalMatchLength;
if (cur->checksum != checksum || cur->offset <= lowestIndex) {
continue;
}
-
- curForwardMatchLength = ZSTD_count(ip, pMatch, iend);
- if (curForwardMatchLength < ldmParams.minMatchLength) {
- continue;
+ if (extDict) {
+ BYTE const* const curMatchBase =
+ cur->offset < dictLimit ? dictBase : base;
+ BYTE const* const pMatch = curMatchBase + cur->offset;
+ BYTE const* const matchEnd =
+ cur->offset < dictLimit ? dictEnd : iend;
+ BYTE const* const lowMatchPtr =
+ cur->offset < dictLimit ? dictStart : lowPrefixPtr;
+
+ curForwardMatchLength = ZSTD_count_2segments(
+ ip, pMatch, iend,
+ matchEnd, lowPrefixPtr);
+ if (curForwardMatchLength < minMatchLength) {
+ continue;
+ }
+ curBackwardMatchLength =
+ ZSTD_ldm_countBackwardsMatch(ip, anchor, pMatch,
+ lowMatchPtr);
+ curTotalMatchLength = curForwardMatchLength +
+ curBackwardMatchLength;
+ } else { /* !extDict */
+ BYTE const* const pMatch = base + cur->offset;
+ curForwardMatchLength = ZSTD_count(ip, pMatch, iend);
+ if (curForwardMatchLength < minMatchLength) {
+ continue;
+ }
+ curBackwardMatchLength =
+ ZSTD_ldm_countBackwardsMatch(ip, anchor, pMatch,
+ lowPrefixPtr);
+ curTotalMatchLength = curForwardMatchLength +
+ curBackwardMatchLength;
}
- curBackwardMatchLength = ZSTD_ldm_countBackwardsMatch(
- ip, anchor, pMatch, lowest);
- curTotalMatchLength = curForwardMatchLength +
- curBackwardMatchLength;
if (curTotalMatchLength > bestMatchLength) {
bestMatchLength = curTotalMatchLength;
@@ -375,7 +401,7 @@ size_t ZSTD_compressBlock_ldm_generic(ZSTD_CCtx* cctx,
if (bestEntry == NULL) {
ZSTD_ldm_makeEntryAndInsertByTag(ldmState, rollingHash,
hBits, current,
- ldmParams);
+ *params);
ip++;
continue;
}
@@ -384,324 +410,244 @@ size_t ZSTD_compressBlock_ldm_generic(ZSTD_CCtx* cctx,
mLength = forwardMatchLength + backwardMatchLength;
ip -= backwardMatchLength;
- /* Call the block compressor on the remaining literals */
{
+ /* Store the sequence:
+ * ip = current - backwardMatchLength
+ * The match is at (bestEntry->offset - backwardMatchLength)
+ */
U32 const matchIndex = bestEntry->offset;
- const BYTE* const match = base + matchIndex - backwardMatchLength;
- U32 const offset = (U32)(ip - match);
-
- /* Overwrite rep codes */
- for (i = 0; i < ZSTD_REP_NUM; i++)
- seqStorePtr->rep[i] = repToConfirm[i];
-
- /* Fill tables for block compressor */
- ZSTD_ldm_limitTableUpdate(cctx, anchor);
- ZSTD_ldm_fillFastTables(cctx, anchor);
-
- /* Call block compressor and get remaining literals */
- lastLiterals = blockCompressor(cctx, anchor, ip - anchor);
- cctx->nextToUpdate = (U32)(ip - base);
-
- /* Update repToConfirm with the new offset */
- for (i = ZSTD_REP_NUM - 1; i > 0; i--)
- repToConfirm[i] = repToConfirm[i-1];
- repToConfirm[0] = offset;
-
- /* Store the sequence with the leftover literals */
- ZSTD_storeSeq(seqStorePtr, lastLiterals, ip - lastLiterals,
- offset + ZSTD_REP_MOVE, mLength - MINMATCH);
+ U32 const offset = current - matchIndex;
+ rawSeq* const seq = rawSeqStore->seq + rawSeqStore->size;
+
+ /* Out of sequence storage */
+ if (rawSeqStore->size == rawSeqStore->capacity)
+ return ERROR(dstSize_tooSmall);
+ seq->litLength = (U32)(ip - anchor);
+ seq->matchLength = (U32)mLength;
+ seq->offset = offset;
+ rawSeqStore->size++;
}
/* Insert the current entry into the hash table */
ZSTD_ldm_makeEntryAndInsertByTag(ldmState, rollingHash, hBits,
(U32)(lastHashed - base),
- ldmParams);
+ *params);
assert(ip + backwardMatchLength == lastHashed);
/* Fill the hash table from lastHashed+1 to ip+mLength*/
/* Heuristic: don't need to fill the entire table at end of block */
- if (ip + mLength < ilimit) {
+ if (ip + mLength <= ilimit) {
rollingHash = ZSTD_ldm_fillLdmHashTable(
ldmState, rollingHash, lastHashed,
- ip + mLength, base, hBits, ldmParams);
+ ip + mLength, base, hBits, *params);
lastHashed = ip + mLength - 1;
}
ip += mLength;
anchor = ip;
- /* Check immediate repcode */
- while ( (ip < ilimit)
- && ( (repToConfirm[1] > 0) && (repToConfirm[1] <= (U32)(ip-lowest))
- && (MEM_read32(ip) == MEM_read32(ip - repToConfirm[1])) )) {
-
- size_t const rLength = ZSTD_count(ip+4, ip+4-repToConfirm[1],
- iend) + 4;
- /* Swap repToConfirm[1] <=> repToConfirm[0] */
- {
- U32 const tmpOff = repToConfirm[1];
- repToConfirm[1] = repToConfirm[0];
- repToConfirm[0] = tmpOff;
- }
-
- ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, rLength-MINMATCH);
-
- /* Fill the hash table from lastHashed+1 to ip+rLength*/
- if (ip + rLength < ilimit) {
- rollingHash = ZSTD_ldm_fillLdmHashTable(
- ldmState, rollingHash, lastHashed,
- ip + rLength, base, hBits, ldmParams);
- lastHashed = ip + rLength - 1;
- }
- ip += rLength;
- anchor = ip;
- }
}
-
- /* Overwrite rep */
- for (i = 0; i < ZSTD_REP_NUM; i++)
- seqStorePtr->rep[i] = repToConfirm[i];
-
- ZSTD_ldm_limitTableUpdate(cctx, anchor);
- ZSTD_ldm_fillFastTables(cctx, anchor);
-
- lastLiterals = blockCompressor(cctx, anchor, iend - anchor);
- cctx->nextToUpdate = (U32)(iend - base);
-
- /* Restore seqStorePtr->rep */
- for (i = 0; i < ZSTD_REP_NUM; i++)
- seqStorePtr->rep[i] = savedRep[i];
-
- /* Return the last literals size */
- return lastLiterals;
+ return iend - anchor;
}
-size_t ZSTD_compressBlock_ldm(ZSTD_CCtx* ctx,
- const void* src, size_t srcSize)
+/*! ZSTD_ldm_reduceTable() :
+ * reduce table indexes by `reducerValue` */
+static void ZSTD_ldm_reduceTable(ldmEntry_t* const table, U32 const size,
+ U32 const reducerValue)
{
- return ZSTD_compressBlock_ldm_generic(ctx, src, srcSize);
+ U32 u;
+ for (u = 0; u < size; u++) {
+ if (table[u].offset < reducerValue) table[u].offset = 0;
+ else table[u].offset -= reducerValue;
+ }
}
-static size_t ZSTD_compressBlock_ldm_extDict_generic(
- ZSTD_CCtx* ctx,
- const void* src, size_t srcSize)
+size_t ZSTD_ldm_generateSequences(
+ ldmState_t* ldmState, rawSeqStore_t* sequences,
+ ldmParams_t const* params, void const* src, size_t srcSize)
{
- ldmState_t* const ldmState = &(ctx->ldmState);
- const ldmParams_t ldmParams = ctx->appliedParams.ldmParams;
- const U64 hashPower = ldmState->hashPower;
- const U32 hBits = ldmParams.hashLog - ldmParams.bucketSizeLog;
- const U32 ldmBucketSize = ((U32)1 << ldmParams.bucketSizeLog);
- const U32 ldmTagMask = ((U32)1 << ldmParams.hashEveryLog) - 1;
- seqStore_t* const seqStorePtr = &(ctx->seqStore);
- const BYTE* const base = ctx->base;
- const BYTE* const dictBase = ctx->dictBase;
- const BYTE* const istart = (const BYTE*)src;
- const BYTE* ip = istart;
- const BYTE* anchor = istart;
- const U32 lowestIndex = ctx->lowLimit;
- const BYTE* const dictStart = dictBase + lowestIndex;
- const U32 dictLimit = ctx->dictLimit;
- const BYTE* const lowPrefixPtr = base + dictLimit;
- const BYTE* const dictEnd = dictBase + dictLimit;
- const BYTE* const iend = istart + srcSize;
- const BYTE* const ilimit = iend - MAX(ldmParams.minMatchLength, HASH_READ_SIZE);
-
- const ZSTD_blockCompressor blockCompressor =
- ZSTD_selectBlockCompressor(ctx->appliedParams.cParams.strategy, 1);
- U32* const repToConfirm = seqStorePtr->repToConfirm;
- U32 savedRep[ZSTD_REP_NUM];
- U64 rollingHash = 0;
- const BYTE* lastHashed = NULL;
- size_t i, lastLiterals;
-
- /* Save seqStorePtr->rep and copy repToConfirm */
- for (i = 0; i < ZSTD_REP_NUM; i++) {
- savedRep[i] = repToConfirm[i] = seqStorePtr->rep[i];
- }
-
- /* Search Loop */
- while (ip < ilimit) { /* < instead of <=, because (ip+1) */
- size_t mLength;
- const U32 current = (U32)(ip-base);
- size_t forwardMatchLength = 0, backwardMatchLength = 0;
- ldmEntry_t* bestEntry = NULL;
- if (ip != istart) {
- rollingHash = ZSTD_ldm_updateHash(rollingHash, lastHashed[0],
- lastHashed[ldmParams.minMatchLength],
- hashPower);
+ U32 const maxDist = 1U << params->windowLog;
+ BYTE const* const istart = (BYTE const*)src;
+ BYTE const* const iend = istart + srcSize;
+ size_t const kMaxChunkSize = 1 << 20;
+ size_t const nbChunks = (srcSize / kMaxChunkSize) + ((srcSize % kMaxChunkSize) != 0);
+ size_t chunk;
+ size_t leftoverSize = 0;
+
+ assert(ZSTD_CHUNKSIZE_MAX >= kMaxChunkSize);
+ /* Check that ZSTD_window_update() has been called for this chunk prior
+ * to passing it to this function.
+ */
+ assert(ldmState->window.nextSrc >= (BYTE const*)src + srcSize);
+ /* The input could be very large (in zstdmt), so it must be broken up into
+ * chunks to enforce the maximmum distance and handle overflow correction.
+ */
+ assert(sequences->pos <= sequences->size);
+ assert(sequences->size <= sequences->capacity);
+ for (chunk = 0; chunk < nbChunks && sequences->size < sequences->capacity; ++chunk) {
+ BYTE const* const chunkStart = istart + chunk * kMaxChunkSize;
+ size_t const remaining = (size_t)(iend - chunkStart);
+ BYTE const *const chunkEnd =
+ (remaining < kMaxChunkSize) ? iend : chunkStart + kMaxChunkSize;
+ size_t const chunkSize = chunkEnd - chunkStart;
+ size_t newLeftoverSize;
+ size_t const prevSize = sequences->size;
+
+ assert(chunkStart < iend);
+ /* 1. Perform overflow correction if necessary. */
+ if (ZSTD_window_needOverflowCorrection(ldmState->window, chunkEnd)) {
+ U32 const ldmHSize = 1U << params->hashLog;
+ U32 const correction = ZSTD_window_correctOverflow(
+ &ldmState->window, /* cycleLog */ 0, maxDist, src);
+ ZSTD_ldm_reduceTable(ldmState->hashTable, ldmHSize, correction);
+ }
+ /* 2. We enforce the maximum offset allowed.
+ *
+ * kMaxChunkSize should be small enough that we don't lose too much of
+ * the window through early invalidation.
+ * TODO: * Test the chunk size.
+ * * Try invalidation after the sequence generation and test the
+ * the offset against maxDist directly.
+ */
+ ZSTD_window_enforceMaxDist(&ldmState->window, chunkEnd, maxDist, NULL);
+ /* 3. Generate the sequences for the chunk, and get newLeftoverSize. */
+ newLeftoverSize = ZSTD_ldm_generateSequences_internal(
+ ldmState, sequences, params, chunkStart, chunkSize);
+ if (ZSTD_isError(newLeftoverSize))
+ return newLeftoverSize;
+ /* 4. We add the leftover literals from previous iterations to the first
+ * newly generated sequence, or add the `newLeftoverSize` if none are
+ * generated.
+ */
+ /* Prepend the leftover literals from the last call */
+ if (prevSize < sequences->size) {
+ sequences->seq[prevSize].litLength += (U32)leftoverSize;
+ leftoverSize = newLeftoverSize;
} else {
- rollingHash = ZSTD_ldm_getRollingHash(ip, ldmParams.minMatchLength);
+ assert(newLeftoverSize == chunkSize);
+ leftoverSize += chunkSize;
}
- lastHashed = ip;
+ }
+ return 0;
+}
- if (ZSTD_ldm_getTag(rollingHash, hBits, ldmParams.hashEveryLog) !=
- ldmTagMask) {
- /* Don't insert and don't look for a match */
- ip++;
- continue;
+void ZSTD_ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, U32 const minMatch) {
+ while (srcSize > 0 && rawSeqStore->pos < rawSeqStore->size) {
+ rawSeq* seq = rawSeqStore->seq + rawSeqStore->pos;
+ if (srcSize <= seq->litLength) {
+ /* Skip past srcSize literals */
+ seq->litLength -= (U32)srcSize;
+ return;
}
-
- /* Get the best entry and compute the match lengths */
- {
- ldmEntry_t* const bucket =
- ZSTD_ldm_getBucket(ldmState,
- ZSTD_ldm_getSmallHash(rollingHash, hBits),
- ldmParams);
- ldmEntry_t* cur;
- size_t bestMatchLength = 0;
- U32 const checksum = ZSTD_ldm_getChecksum(rollingHash, hBits);
-
- for (cur = bucket; cur < bucket + ldmBucketSize; ++cur) {
- const BYTE* const curMatchBase =
- cur->offset < dictLimit ? dictBase : base;
- const BYTE* const pMatch = curMatchBase + cur->offset;
- const BYTE* const matchEnd =
- cur->offset < dictLimit ? dictEnd : iend;
- const BYTE* const lowMatchPtr =
- cur->offset < dictLimit ? dictStart : lowPrefixPtr;
- size_t curForwardMatchLength, curBackwardMatchLength,
- curTotalMatchLength;
-
- if (cur->checksum != checksum || cur->offset <= lowestIndex) {
- continue;
- }
-
- curForwardMatchLength = ZSTD_count_2segments(
- ip, pMatch, iend,
- matchEnd, lowPrefixPtr);
- if (curForwardMatchLength < ldmParams.minMatchLength) {
- continue;
- }
- curBackwardMatchLength = ZSTD_ldm_countBackwardsMatch(
- ip, anchor, pMatch, lowMatchPtr);
- curTotalMatchLength = curForwardMatchLength +
- curBackwardMatchLength;
-
- if (curTotalMatchLength > bestMatchLength) {
- bestMatchLength = curTotalMatchLength;
- forwardMatchLength = curForwardMatchLength;
- backwardMatchLength = curBackwardMatchLength;
- bestEntry = cur;
+ srcSize -= seq->litLength;
+ seq->litLength = 0;
+ if (srcSize < seq->matchLength) {
+ /* Skip past the first srcSize of the match */
+ seq->matchLength -= (U32)srcSize;
+ if (seq->matchLength < minMatch) {
+ /* The match is too short, omit it */
+ if (rawSeqStore->pos + 1 < rawSeqStore->size) {
+ seq[1].litLength += seq[0].matchLength;
}
+ rawSeqStore->pos++;
}
+ return;
}
+ srcSize -= seq->matchLength;
+ seq->matchLength = 0;
+ rawSeqStore->pos++;
+ }
+}
- /* No match found -- continue searching */
- if (bestEntry == NULL) {
- ZSTD_ldm_makeEntryAndInsertByTag(ldmState, rollingHash, hBits,
- (U32)(lastHashed - base),
- ldmParams);
- ip++;
- continue;
+/**
+ * If the sequence length is longer than remaining then the sequence is split
+ * between this block and the next.
+ *
+ * Returns the current sequence to handle, or if the rest of the block should
+ * be literals, it returns a sequence with offset == 0.
+ */
+static rawSeq maybeSplitSequence(rawSeqStore_t* rawSeqStore,
+ U32 const remaining, U32 const minMatch)
+{
+ rawSeq sequence = rawSeqStore->seq[rawSeqStore->pos];
+ assert(sequence.offset > 0);
+ /* Likely: No partial sequence */
+ if (remaining >= sequence.litLength + sequence.matchLength) {
+ rawSeqStore->pos++;
+ return sequence;
+ }
+ /* Cut the sequence short (offset == 0 ==> rest is literals). */
+ if (remaining <= sequence.litLength) {
+ sequence.offset = 0;
+ } else if (remaining < sequence.litLength + sequence.matchLength) {
+ sequence.matchLength = remaining - sequence.litLength;
+ if (sequence.matchLength < minMatch) {
+ sequence.offset = 0;
}
+ }
+ /* Skip past `remaining` bytes for the future sequences. */
+ ZSTD_ldm_skipSequences(rawSeqStore, remaining, minMatch);
+ return sequence;
+}
- /* Match found */
- mLength = forwardMatchLength + backwardMatchLength;
- ip -= backwardMatchLength;
-
- /* Call the block compressor on the remaining literals */
- {
- /* ip = current - backwardMatchLength
- * The match is at (bestEntry->offset - backwardMatchLength) */
- U32 const matchIndex = bestEntry->offset;
- U32 const offset = current - matchIndex;
-
- /* Overwrite rep codes */
- for (i = 0; i < ZSTD_REP_NUM; i++)
- seqStorePtr->rep[i] = repToConfirm[i];
-
- /* Fill the hash table for the block compressor */
- ZSTD_ldm_limitTableUpdate(ctx, anchor);
- ZSTD_ldm_fillFastTables(ctx, anchor);
+size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize,
+ int const extDict)
+{
+ unsigned const minMatch = cParams->searchLength;
+ ZSTD_blockCompressor const blockCompressor =
+ ZSTD_selectBlockCompressor(cParams->strategy, extDict);
+ BYTE const* const base = ms->window.base;
+ /* Input bounds */
+ BYTE const* const istart = (BYTE const*)src;
+ BYTE const* const iend = istart + srcSize;
+ /* Input positions */
+ BYTE const* ip = istart;
+
+ assert(rawSeqStore->pos <= rawSeqStore->size);
+ assert(rawSeqStore->size <= rawSeqStore->capacity);
+ /* Loop through each sequence and apply the block compressor to the lits */
+ while (rawSeqStore->pos < rawSeqStore->size && ip < iend) {
+ /* maybeSplitSequence updates rawSeqStore->pos */
+ rawSeq const sequence = maybeSplitSequence(rawSeqStore,
+ (U32)(iend - ip), minMatch);
+ int i;
+ /* End signal */
+ if (sequence.offset == 0)
+ break;
- /* Call block compressor and get remaining literals */
- lastLiterals = blockCompressor(ctx, anchor, ip - anchor);
- ctx->nextToUpdate = (U32)(ip - base);
+ assert(sequence.offset <= (1U << cParams->windowLog));
+ assert(ip + sequence.litLength + sequence.matchLength <= iend);
- /* Update repToConfirm with the new offset */
+ /* Fill tables for block compressor */
+ ZSTD_ldm_limitTableUpdate(ms, ip);
+ ZSTD_ldm_fillFastTables(ms, cParams, ip);
+ /* Run the block compressor */
+ {
+ size_t const newLitLength =
+ blockCompressor(ms, seqStore, rep, cParams, ip,
+ sequence.litLength);
+ ip += sequence.litLength;
+ ms->nextToUpdate = (U32)(ip - base);
+ /* Update the repcodes */
for (i = ZSTD_REP_NUM - 1; i > 0; i--)
- repToConfirm[i] = repToConfirm[i-1];
- repToConfirm[0] = offset;
-
- /* Store the sequence with the leftover literals */
- ZSTD_storeSeq(seqStorePtr, lastLiterals, ip - lastLiterals,
- offset + ZSTD_REP_MOVE, mLength - MINMATCH);
- }
-
- /* Insert the current entry into the hash table */
- ZSTD_ldm_makeEntryAndInsertByTag(ldmState, rollingHash, hBits,
- (U32)(lastHashed - base),
- ldmParams);
-
- /* Fill the hash table from lastHashed+1 to ip+mLength */
- assert(ip + backwardMatchLength == lastHashed);
- if (ip + mLength < ilimit) {
- rollingHash = ZSTD_ldm_fillLdmHashTable(
- ldmState, rollingHash, lastHashed,
- ip + mLength, base, hBits,
- ldmParams);
- lastHashed = ip + mLength - 1;
- }
- ip += mLength;
- anchor = ip;
-
- /* check immediate repcode */
- while (ip < ilimit) {
- U32 const current2 = (U32)(ip-base);
- U32 const repIndex2 = current2 - repToConfirm[1];
- const BYTE* repMatch2 = repIndex2 < dictLimit ?
- dictBase + repIndex2 : base + repIndex2;
- if ( (((U32)((dictLimit-1) - repIndex2) >= 3) &
- (repIndex2 > lowestIndex)) /* intentional overflow */
- && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
- const BYTE* const repEnd2 = repIndex2 < dictLimit ?
- dictEnd : iend;
- size_t const repLength2 =
- ZSTD_count_2segments(ip+4, repMatch2+4, iend,
- repEnd2, lowPrefixPtr) + 4;
-
- U32 tmpOffset = repToConfirm[1];
- repToConfirm[1] = repToConfirm[0];
- repToConfirm[0] = tmpOffset;
-
- ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, repLength2-MINMATCH);
-
- /* Fill the hash table from lastHashed+1 to ip+repLength2*/
- if (ip + repLength2 < ilimit) {
- rollingHash = ZSTD_ldm_fillLdmHashTable(
- ldmState, rollingHash, lastHashed,
- ip + repLength2, base, hBits,
- ldmParams);
- lastHashed = ip + repLength2 - 1;
- }
- ip += repLength2;
- anchor = ip;
- continue;
- }
- break;
+ rep[i] = rep[i-1];
+ rep[0] = sequence.offset;
+ /* Store the sequence */
+ ZSTD_storeSeq(seqStore, newLitLength, ip - newLitLength,
+ sequence.offset + ZSTD_REP_MOVE,
+ sequence.matchLength - MINMATCH);
+ ip += sequence.matchLength;
}
}
-
- /* Overwrite rep */
- for (i = 0; i < ZSTD_REP_NUM; i++)
- seqStorePtr->rep[i] = repToConfirm[i];
-
- ZSTD_ldm_limitTableUpdate(ctx, anchor);
- ZSTD_ldm_fillFastTables(ctx, anchor);
-
- /* Call the block compressor one last time on the last literals */
- lastLiterals = blockCompressor(ctx, anchor, iend - anchor);
- ctx->nextToUpdate = (U32)(iend - base);
-
- /* Restore seqStorePtr->rep */
- for (i = 0; i < ZSTD_REP_NUM; i++)
- seqStorePtr->rep[i] = savedRep[i];
-
- /* Return the last literals size */
- return lastLiterals;
-}
-
-size_t ZSTD_compressBlock_ldm_extDict(ZSTD_CCtx* ctx,
- const void* src, size_t srcSize)
-{
- return ZSTD_compressBlock_ldm_extDict_generic(ctx, src, srcSize);
+ /* Fill the tables for the block compressor */
+ ZSTD_ldm_limitTableUpdate(ms, ip);
+ ZSTD_ldm_fillFastTables(ms, cParams, ip);
+ /* Compress the last literals */
+ {
+ size_t const lastLiterals = blockCompressor(ms, seqStore, rep, cParams,
+ ip, iend - ip);
+ ms->nextToUpdate = (U32)(iend - base);
+ return lastLiterals;
+ }
}
diff --git a/thirdparty/zstd/compress/zstd_ldm.h b/thirdparty/zstd/compress/zstd_ldm.h
index 8f12c677aa..0c3789ff13 100644
--- a/thirdparty/zstd/compress/zstd_ldm.h
+++ b/thirdparty/zstd/compress/zstd_ldm.h
@@ -22,32 +22,71 @@ extern "C" {
***************************************/
#define ZSTD_LDM_DEFAULT_WINDOW_LOG ZSTD_WINDOWLOG_DEFAULTMAX
-#define ZSTD_LDM_HASHEVERYLOG_NOTSET 9999
-/** ZSTD_compressBlock_ldm_generic() :
+/**
+ * ZSTD_ldm_generateSequences():
*
- * This is a block compressor intended for long distance matching.
+ * Generates the sequences using the long distance match finder.
+ * Generates long range matching sequences in `sequences`, which parse a prefix
+ * of the source. `sequences` must be large enough to store every sequence,
+ * which can be checked with `ZSTD_ldm_getMaxNbSeq()`.
+ * @returns 0 or an error code.
*
- * The function searches for matches of length at least
- * ldmParams.minMatchLength using a hash table in cctx->ldmState.
- * Matches can be at a distance of up to cParams.windowLog.
+ * NOTE: The user must have called ZSTD_window_update() for all of the input
+ * they have, even if they pass it to ZSTD_ldm_generateSequences() in chunks.
+ * NOTE: This function returns an error if it runs out of space to store
+ * sequences.
+ */
+size_t ZSTD_ldm_generateSequences(
+ ldmState_t* ldms, rawSeqStore_t* sequences,
+ ldmParams_t const* params, void const* src, size_t srcSize);
+
+/**
+ * ZSTD_ldm_blockCompress():
+ *
+ * Compresses a block using the predefined sequences, along with a secondary
+ * block compressor. The literals section of every sequence is passed to the
+ * secondary block compressor, and those sequences are interspersed with the
+ * predefined sequences. Returns the length of the last literals.
+ * Updates `rawSeqStore.pos` to indicate how many sequences have been consumed.
+ * `rawSeqStore.seq` may also be updated to split the last sequence between two
+ * blocks.
+ * @return The length of the last literals.
+ *
+ * NOTE: The source must be at most the maximum block size, but the predefined
+ * sequences can be any size, and may be longer than the block. In the case that
+ * they are longer than the block, the last sequences may need to be split into
+ * two. We handle that case correctly, and update `rawSeqStore` appropriately.
+ * NOTE: This function does not return any errors.
+ */
+size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams,
+ void const* src, size_t srcSize,
+ int const extDict);
+
+/**
+ * ZSTD_ldm_skipSequences():
*
- * Upon finding a match, the unmatched literals are compressed using a
- * ZSTD_blockCompressor (depending on the strategy in the compression
- * parameters), which stores the matched sequences. The "long distance"
- * match is then stored with the remaining literals from the
- * ZSTD_blockCompressor. */
-size_t ZSTD_compressBlock_ldm(ZSTD_CCtx* cctx, const void* src, size_t srcSize);
-size_t ZSTD_compressBlock_ldm_extDict(ZSTD_CCtx* ctx,
- const void* src, size_t srcSize);
+ * Skip past `srcSize` bytes worth of sequences in `rawSeqStore`.
+ * Avoids emitting matches less than `minMatch` bytes.
+ * Must be called for data with is not passed to ZSTD_ldm_blockCompress().
+ */
+void ZSTD_ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize,
+ U32 const minMatch);
-/** ZSTD_ldm_initializeParameters() :
- * Initialize the long distance matching parameters to their default values. */
-size_t ZSTD_ldm_initializeParameters(ldmParams_t* params, U32 enableLdm);
/** ZSTD_ldm_getTableSize() :
- * Estimate the space needed for long distance matching tables. */
-size_t ZSTD_ldm_getTableSize(U32 hashLog, U32 bucketSizeLog);
+ * Estimate the space needed for long distance matching tables or 0 if LDM is
+ * disabled.
+ */
+size_t ZSTD_ldm_getTableSize(ldmParams_t params);
+
+/** ZSTD_ldm_getSeqSpace() :
+ * Return an upper bound on the number of sequences that can be produced by
+ * the long distance matcher, or 0 if LDM is disabled.
+ */
+size_t ZSTD_ldm_getMaxNbSeq(ldmParams_t params, size_t maxChunkSize);
/** ZSTD_ldm_getTableSize() :
* Return prime8bytes^(minMatchLength-1) */
@@ -58,8 +97,12 @@ U64 ZSTD_ldm_getHashPower(U32 minMatchLength);
* windowLog and params->hashLog.
*
* Ensures that params->bucketSizeLog is <= params->hashLog (setting it to
- * params->hashLog if it is not). */
-void ZSTD_ldm_adjustParameters(ldmParams_t* params, U32 windowLog);
+ * params->hashLog if it is not).
+ *
+ * Ensures that the minMatchLength >= targetLength during optimal parsing.
+ */
+void ZSTD_ldm_adjustParameters(ldmParams_t* params,
+ ZSTD_compressionParameters const* cParams);
#if defined (__cplusplus)
}
diff --git a/thirdparty/zstd/compress/zstd_opt.c b/thirdparty/zstd/compress/zstd_opt.c
index 7171ff5373..f63f0c5852 100644
--- a/thirdparty/zstd/compress/zstd_opt.c
+++ b/thirdparty/zstd/compress/zstd_opt.c
@@ -10,7 +10,6 @@
#include "zstd_compress_internal.h"
#include "zstd_opt.h"
-#include "zstd_lazy.h" /* ZSTD_updateTree, ZSTD_updateTree_extDict */
#define ZSTD_LITFREQ_ADD 2 /* scaling factor for litFreq, so that frequencies adapt faster to new stats. Also used for matchSum (?) */
@@ -244,14 +243,15 @@ MEM_STATIC U32 ZSTD_readMINMATCH(const void* memPtr, U32 length)
/* Update hashTable3 up to ip (excluded)
Assumption : always within prefix (i.e. not within extDict) */
-static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_CCtx* const cctx, const BYTE* const ip)
+static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms, const BYTE* const ip)
{
- U32* const hashTable3 = cctx->hashTable3;
- U32 const hashLog3 = cctx->hashLog3;
- const BYTE* const base = cctx->base;
- U32 idx = cctx->nextToUpdate3;
- U32 const target = cctx->nextToUpdate3 = (U32)(ip - base);
+ U32* const hashTable3 = ms->hashTable3;
+ U32 const hashLog3 = ms->hashLog3;
+ const BYTE* const base = ms->window.base;
+ U32 idx = ms->nextToUpdate3;
+ U32 const target = ms->nextToUpdate3 = (U32)(ip - base);
size_t const hash3 = ZSTD_hash3Ptr(ip, hashLog3);
+ assert(hashLog3 > 0);
while(idx < target) {
hashTable3[ZSTD_hash3Ptr(base+idx, hashLog3)] = idx;
@@ -265,36 +265,173 @@ static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_CCtx* const cctx, const BYTE*
/*-*************************************
* Binary Tree search
***************************************/
+/** ZSTD_insertBt1() : add one or multiple positions to tree.
+ * ip : assumed <= iend-8 .
+ * @return : nb of positions added */
+static U32 ZSTD_insertBt1(
+ ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
+ const BYTE* const ip, const BYTE* const iend,
+ U32 const mls, U32 const extDict)
+{
+ U32* const hashTable = ms->hashTable;
+ U32 const hashLog = cParams->hashLog;
+ size_t const h = ZSTD_hashPtr(ip, hashLog, mls);
+ U32* const bt = ms->chainTable;
+ U32 const btLog = cParams->chainLog - 1;
+ U32 const btMask = (1 << btLog) - 1;
+ U32 matchIndex = hashTable[h];
+ size_t commonLengthSmaller=0, commonLengthLarger=0;
+ const BYTE* const base = ms->window.base;
+ const BYTE* const dictBase = ms->window.dictBase;
+ const U32 dictLimit = ms->window.dictLimit;
+ const BYTE* const dictEnd = dictBase + dictLimit;
+ const BYTE* const prefixStart = base + dictLimit;
+ const BYTE* match;
+ const U32 current = (U32)(ip-base);
+ const U32 btLow = btMask >= current ? 0 : current - btMask;
+ U32* smallerPtr = bt + 2*(current&btMask);
+ U32* largerPtr = smallerPtr + 1;
+ U32 dummy32; /* to be nullified at the end */
+ U32 const windowLow = ms->window.lowLimit;
+ U32 matchEndIdx = current+8+1;
+ size_t bestLength = 8;
+ U32 nbCompares = 1U << cParams->searchLog;
+#ifdef ZSTD_C_PREDICT
+ U32 predictedSmall = *(bt + 2*((current-1)&btMask) + 0);
+ U32 predictedLarge = *(bt + 2*((current-1)&btMask) + 1);
+ predictedSmall += (predictedSmall>0);
+ predictedLarge += (predictedLarge>0);
+#endif /* ZSTD_C_PREDICT */
+
+ DEBUGLOG(8, "ZSTD_insertBt1 (%u)", current);
+
+ assert(ip <= iend-8); /* required for h calculation */
+ hashTable[h] = current; /* Update Hash Table */
+
+ while (nbCompares-- && (matchIndex > windowLow)) {
+ U32* const nextPtr = bt + 2*(matchIndex & btMask);
+ size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
+ assert(matchIndex < current);
+
+#ifdef ZSTD_C_PREDICT /* note : can create issues when hlog small <= 11 */
+ const U32* predictPtr = bt + 2*((matchIndex-1) & btMask); /* written this way, as bt is a roll buffer */
+ if (matchIndex == predictedSmall) {
+ /* no need to check length, result known */
+ *smallerPtr = matchIndex;
+ if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
+ smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
+ matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
+ predictedSmall = predictPtr[1] + (predictPtr[1]>0);
+ continue;
+ }
+ if (matchIndex == predictedLarge) {
+ *largerPtr = matchIndex;
+ if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
+ largerPtr = nextPtr;
+ matchIndex = nextPtr[0];
+ predictedLarge = predictPtr[0] + (predictPtr[0]>0);
+ continue;
+ }
+#endif
+
+ if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
+ assert(matchIndex+matchLength >= dictLimit); /* might be wrong if extDict is incorrectly set to 0 */
+ match = base + matchIndex;
+ matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend);
+ } else {
+ match = dictBase + matchIndex;
+ matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
+ if (matchIndex+matchLength >= dictLimit)
+ match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
+ }
+
+ if (matchLength > bestLength) {
+ bestLength = matchLength;
+ if (matchLength > matchEndIdx - matchIndex)
+ matchEndIdx = matchIndex + (U32)matchLength;
+ }
+
+ if (ip+matchLength == iend) { /* equal : no way to know if inf or sup */
+ break; /* drop , to guarantee consistency ; miss a bit of compression, but other solutions can corrupt tree */
+ }
+
+ if (match[matchLength] < ip[matchLength]) { /* necessarily within buffer */
+ /* match is smaller than current */
+ *smallerPtr = matchIndex; /* update smaller idx */
+ commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
+ if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop searching */
+ smallerPtr = nextPtr+1; /* new "candidate" => larger than match, which was smaller than target */
+ matchIndex = nextPtr[1]; /* new matchIndex, larger than previous and closer to current */
+ } else {
+ /* match is larger than current */
+ *largerPtr = matchIndex;
+ commonLengthLarger = matchLength;
+ if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop searching */
+ largerPtr = nextPtr;
+ matchIndex = nextPtr[0];
+ } }
+
+ *smallerPtr = *largerPtr = 0;
+ if (bestLength > 384) return MIN(192, (U32)(bestLength - 384)); /* speed optimization */
+ assert(matchEndIdx > current + 8);
+ return matchEndIdx - (current + 8);
+}
+
+FORCE_INLINE_TEMPLATE
+void ZSTD_updateTree_internal(
+ ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
+ const BYTE* const ip, const BYTE* const iend,
+ const U32 mls, const U32 extDict)
+{
+ const BYTE* const base = ms->window.base;
+ U32 const target = (U32)(ip - base);
+ U32 idx = ms->nextToUpdate;
+ DEBUGLOG(7, "ZSTD_updateTree_internal, from %u to %u (extDict:%u)",
+ idx, target, extDict);
+
+ while(idx < target)
+ idx += ZSTD_insertBt1(ms, cParams, base+idx, iend, mls, extDict);
+ ms->nextToUpdate = target;
+}
+
+void ZSTD_updateTree(
+ ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
+ const BYTE* ip, const BYTE* iend)
+{
+ ZSTD_updateTree_internal(ms, cParams, ip, iend, cParams->searchLength, 0 /*extDict*/);
+}
+
FORCE_INLINE_TEMPLATE
U32 ZSTD_insertBtAndGetAllMatches (
- ZSTD_CCtx* zc,
+ ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
const BYTE* const ip, const BYTE* const iLimit, int const extDict,
- U32 nbCompares, U32 const mls, U32 const sufficient_len,
U32 rep[ZSTD_REP_NUM], U32 const ll0,
- ZSTD_match_t* matches, const U32 lengthToBeat)
+ ZSTD_match_t* matches, const U32 lengthToBeat, U32 const mls /* template */)
{
- const BYTE* const base = zc->base;
+ U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1);
+ const BYTE* const base = ms->window.base;
U32 const current = (U32)(ip-base);
- U32 const hashLog = zc->appliedParams.cParams.hashLog;
+ U32 const hashLog = cParams->hashLog;
U32 const minMatch = (mls==3) ? 3 : 4;
- U32* const hashTable = zc->hashTable;
+ U32* const hashTable = ms->hashTable;
size_t const h = ZSTD_hashPtr(ip, hashLog, mls);
U32 matchIndex = hashTable[h];
- U32* const bt = zc->chainTable;
- U32 const btLog = zc->appliedParams.cParams.chainLog - 1;
+ U32* const bt = ms->chainTable;
+ U32 const btLog = cParams->chainLog - 1;
U32 const btMask= (1U << btLog) - 1;
size_t commonLengthSmaller=0, commonLengthLarger=0;
- const BYTE* const dictBase = zc->dictBase;
- U32 const dictLimit = zc->dictLimit;
+ const BYTE* const dictBase = ms->window.dictBase;
+ U32 const dictLimit = ms->window.dictLimit;
const BYTE* const dictEnd = dictBase + dictLimit;
const BYTE* const prefixStart = base + dictLimit;
U32 const btLow = btMask >= current ? 0 : current - btMask;
- U32 const windowLow = zc->lowLimit;
+ U32 const windowLow = ms->window.lowLimit;
U32* smallerPtr = bt + 2*(current&btMask);
U32* largerPtr = bt + 2*(current&btMask) + 1;
U32 matchEndIdx = current+8+1; /* farthest referenced position of any match => detects repetitive patterns */
U32 dummy32; /* to be nullified at the end */
U32 mnum = 0;
+ U32 nbCompares = 1U << cParams->searchLog;
size_t bestLength = lengthToBeat-1;
DEBUGLOG(7, "ZSTD_insertBtAndGetAllMatches");
@@ -335,7 +472,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
/* HC3 match finder */
if ((mls == 3) /*static*/ && (bestLength < mls)) {
- U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3 (zc, ip);
+ U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(ms, ip);
if ((matchIndex3 > windowLow)
& (current - matchIndex3 < (1<<18)) /*heuristic : longer distance likely too expensive*/ ) {
size_t mlen;
@@ -359,7 +496,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
mnum = 1;
if ( (mlen > sufficient_len) |
(ip+mlen == iLimit) ) { /* best possible length */
- zc->nextToUpdate = current+1; /* skip insertion */
+ ms->nextToUpdate = current+1; /* skip insertion */
return 1;
} } } }
@@ -416,30 +553,29 @@ U32 ZSTD_insertBtAndGetAllMatches (
*smallerPtr = *largerPtr = 0;
assert(matchEndIdx > current+8);
- zc->nextToUpdate = matchEndIdx - 8; /* skip repetitive patterns */
+ ms->nextToUpdate = matchEndIdx - 8; /* skip repetitive patterns */
return mnum;
}
FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
- ZSTD_CCtx* zc, /* Index table will be updated */
+ ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
const BYTE* ip, const BYTE* const iHighLimit, int const extDict,
- U32 const maxNbAttempts, U32 const matchLengthSearch, U32 const sufficient_len,
U32 rep[ZSTD_REP_NUM], U32 const ll0,
ZSTD_match_t* matches, U32 const lengthToBeat)
{
+ U32 const matchLengthSearch = cParams->searchLength;
DEBUGLOG(7, "ZSTD_BtGetAllMatches");
- if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
- if (extDict) ZSTD_updateTree_extDict(zc, ip, iHighLimit, maxNbAttempts, matchLengthSearch);
- else ZSTD_updateTree(zc, ip, iHighLimit, maxNbAttempts, matchLengthSearch);
+ if (ip < ms->window.base + ms->nextToUpdate) return 0; /* skipped area */
+ ZSTD_updateTree_internal(ms, cParams, ip, iHighLimit, matchLengthSearch, extDict);
switch(matchLengthSearch)
{
- case 3 : return ZSTD_insertBtAndGetAllMatches(zc, ip, iHighLimit, extDict, maxNbAttempts, 3, sufficient_len, rep, ll0, matches, lengthToBeat);
+ case 3 : return ZSTD_insertBtAndGetAllMatches(ms, cParams, ip, iHighLimit, extDict, rep, ll0, matches, lengthToBeat, 3);
default :
- case 4 : return ZSTD_insertBtAndGetAllMatches(zc, ip, iHighLimit, extDict, maxNbAttempts, 4, sufficient_len, rep, ll0, matches, lengthToBeat);
- case 5 : return ZSTD_insertBtAndGetAllMatches(zc, ip, iHighLimit, extDict, maxNbAttempts, 5, sufficient_len, rep, ll0, matches, lengthToBeat);
+ case 4 : return ZSTD_insertBtAndGetAllMatches(ms, cParams, ip, iHighLimit, extDict, rep, ll0, matches, lengthToBeat, 4);
+ case 5 : return ZSTD_insertBtAndGetAllMatches(ms, cParams, ip, iHighLimit, extDict, rep, ll0, matches, lengthToBeat, 5);
case 7 :
- case 6 : return ZSTD_insertBtAndGetAllMatches(zc, ip, iHighLimit, extDict, maxNbAttempts, 6, sufficient_len, rep, ll0, matches, lengthToBeat);
+ case 6 : return ZSTD_insertBtAndGetAllMatches(ms, cParams, ip, iHighLimit, extDict, rep, ll0, matches, lengthToBeat, 6);
}
}
@@ -527,36 +663,33 @@ static int ZSTD_literalsContribution_cached(
}
FORCE_INLINE_TEMPLATE
-size_t ZSTD_compressBlock_opt_generic(ZSTD_CCtx* ctx,
+size_t ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,seqStore_t* seqStore,
+ U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams,
const void* src, size_t srcSize,
const int optLevel, const int extDict)
{
- seqStore_t* const seqStorePtr = &(ctx->seqStore);
- optState_t* const optStatePtr = &(ctx->optState);
+ optState_t* const optStatePtr = &ms->opt;
const BYTE* const istart = (const BYTE*)src;
const BYTE* ip = istart;
const BYTE* anchor = istart;
const BYTE* const iend = istart + srcSize;
const BYTE* const ilimit = iend - 8;
- const BYTE* const base = ctx->base;
- const BYTE* const prefixStart = base + ctx->dictLimit;
+ const BYTE* const base = ms->window.base;
+ const BYTE* const prefixStart = base + ms->window.dictLimit;
- U32 const maxSearches = 1U << ctx->appliedParams.cParams.searchLog;
- U32 const sufficient_len = MIN(ctx->appliedParams.cParams.targetLength, ZSTD_OPT_NUM -1);
- U32 const mls = ctx->appliedParams.cParams.searchLength;
- U32 const minMatch = (ctx->appliedParams.cParams.searchLength == 3) ? 3 : 4;
+ U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1);
+ U32 const minMatch = (cParams->searchLength == 3) ? 3 : 4;
ZSTD_optimal_t* const opt = optStatePtr->priceTable;
ZSTD_match_t* const matches = optStatePtr->matchTable;
cachedLiteralPrice_t cachedLitPrice;
- U32 rep[ZSTD_REP_NUM];
/* init */
DEBUGLOG(5, "ZSTD_compressBlock_opt_generic");
- ctx->nextToUpdate3 = ctx->nextToUpdate;
+ ms->nextToUpdate3 = ms->nextToUpdate;
ZSTD_rescaleFreqs(optStatePtr, (const BYTE*)src, srcSize);
ip += (ip==prefixStart);
- { int i; for (i=0; i<ZSTD_REP_NUM; i++) rep[i]=seqStorePtr->rep[i]; }
memset(&cachedLitPrice, 0, sizeof(cachedLitPrice));
/* Match Loop */
@@ -567,7 +700,7 @@ size_t ZSTD_compressBlock_opt_generic(ZSTD_CCtx* ctx,
/* find first match */
{ U32 const litlen = (U32)(ip - anchor);
U32 const ll0 = !litlen;
- U32 const nbMatches = ZSTD_BtGetAllMatches(ctx, ip, iend, extDict, maxSearches, mls, sufficient_len, rep, ll0, matches, minMatch);
+ U32 const nbMatches = ZSTD_BtGetAllMatches(ms, cParams, ip, iend, extDict, rep, ll0, matches, minMatch);
if (!nbMatches) { ip++; continue; }
/* initialize opt[0] */
@@ -653,7 +786,7 @@ size_t ZSTD_compressBlock_opt_generic(ZSTD_CCtx* ctx,
U32 const litlen = (opt[cur].mlen == 1) ? opt[cur].litlen : 0;
U32 const previousPrice = (cur > litlen) ? opt[cur-litlen].price : 0;
U32 const basePrice = previousPrice + ZSTD_fullLiteralsCost(inr-litlen, litlen, optStatePtr);
- U32 const nbMatches = ZSTD_BtGetAllMatches(ctx, inr, iend, extDict, maxSearches, mls, sufficient_len, opt[cur].rep, ll0, matches, minMatch);
+ U32 const nbMatches = ZSTD_BtGetAllMatches(ms, cParams, inr, iend, extDict, opt[cur].rep, ll0, matches, minMatch);
U32 matchNb;
if (!nbMatches) continue;
@@ -749,37 +882,42 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
}
ZSTD_updateStats(optStatePtr, llen, anchor, offset, mlen);
- ZSTD_storeSeq(seqStorePtr, llen, anchor, offset, mlen-MINMATCH);
+ ZSTD_storeSeq(seqStore, llen, anchor, offset, mlen-MINMATCH);
anchor = ip;
} }
ZSTD_setLog2Prices(optStatePtr);
} /* while (ip < ilimit) */
- /* Save reps for next block */
- { int i; for (i=0; i<ZSTD_REP_NUM; i++) seqStorePtr->repToConfirm[i] = rep[i]; }
-
/* Return the last literals size */
return iend - anchor;
}
-size_t ZSTD_compressBlock_btopt(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
+size_t ZSTD_compressBlock_btopt(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
{
DEBUGLOG(5, "ZSTD_compressBlock_btopt");
- return ZSTD_compressBlock_opt_generic(ctx, src, srcSize, 0 /*optLevel*/, 0 /*extDict*/);
+ return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, cParams, src, srcSize, 0 /*optLevel*/, 0 /*extDict*/);
}
-size_t ZSTD_compressBlock_btultra(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
+size_t ZSTD_compressBlock_btultra(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
{
- return ZSTD_compressBlock_opt_generic(ctx, src, srcSize, 2 /*optLevel*/, 0 /*extDict*/);
+ return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, cParams, src, srcSize, 2 /*optLevel*/, 0 /*extDict*/);
}
-size_t ZSTD_compressBlock_btopt_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
+size_t ZSTD_compressBlock_btopt_extDict(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
{
- return ZSTD_compressBlock_opt_generic(ctx, src, srcSize, 0 /*optLevel*/, 1 /*extDict*/);
+ return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, cParams, src, srcSize, 0 /*optLevel*/, 1 /*extDict*/);
}
-size_t ZSTD_compressBlock_btultra_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
+size_t ZSTD_compressBlock_btultra_extDict(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
{
- return ZSTD_compressBlock_opt_generic(ctx, src, srcSize, 2 /*optLevel*/, 1 /*extDict*/);
+ return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, cParams, src, srcSize, 2 /*optLevel*/, 1 /*extDict*/);
}
diff --git a/thirdparty/zstd/compress/zstd_opt.h b/thirdparty/zstd/compress/zstd_opt.h
index 82e810c293..b8dc389f31 100644
--- a/thirdparty/zstd/compress/zstd_opt.h
+++ b/thirdparty/zstd/compress/zstd_opt.h
@@ -15,13 +15,25 @@
extern "C" {
#endif
-#include "zstd.h" /* ZSTD_CCtx, size_t */
+#include "zstd_compress_internal.h"
-size_t ZSTD_compressBlock_btopt(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
-size_t ZSTD_compressBlock_btultra(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
+void ZSTD_updateTree(
+ ZSTD_matchState_t* ms, ZSTD_compressionParameters const* cParams,
+ const BYTE* ip, const BYTE* iend); /* used in ZSTD_loadDictionaryContent() */
-size_t ZSTD_compressBlock_btopt_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
-size_t ZSTD_compressBlock_btultra_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize);
+size_t ZSTD_compressBlock_btopt(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_btultra(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+
+size_t ZSTD_compressBlock_btopt_extDict(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_btultra_extDict(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
#if defined (__cplusplus)
}
diff --git a/thirdparty/zstd/compress/zstdmt_compress.c b/thirdparty/zstd/compress/zstdmt_compress.c
index e51edf124f..c7a205d8c7 100644
--- a/thirdparty/zstd/compress/zstdmt_compress.c
+++ b/thirdparty/zstd/compress/zstdmt_compress.c
@@ -10,7 +10,8 @@
/* ====== Tuning parameters ====== */
-#define ZSTDMT_NBTHREADS_MAX 200
+#define ZSTDMT_NBWORKERS_MAX 200
+#define ZSTDMT_JOBSIZE_MAX (MEM_32bits() ? (512 MB) : (2 GB)) /* note : limited by `jobSize` type, which is `unsigned` */
#define ZSTDMT_OVERLAPLOG_DEFAULT 6
@@ -22,11 +23,18 @@
/* ====== Dependencies ====== */
#include <string.h> /* memcpy, memset */
+#include <limits.h> /* INT_MAX */
#include "pool.h" /* threadpool */
#include "threading.h" /* mutex */
#include "zstd_compress_internal.h" /* MIN, ERROR, ZSTD_*, ZSTD_highbit32 */
+#include "zstd_ldm.h"
#include "zstdmt_compress.h"
+/* Guards code to support resizing the SeqPool.
+ * We will want to resize the SeqPool to save memory in the future.
+ * Until then, comment the code out since it is unused.
+ */
+#define ZSTD_RESIZE_SEQPOOL 0
/* ====== Debug ====== */
#if defined(ZSTD_DEBUG) && (ZSTD_DEBUG>=2)
@@ -81,7 +89,7 @@ static unsigned long long GetCurrentClockTimeMicroseconds(void)
typedef struct buffer_s {
void* start;
- size_t size;
+ size_t capacity;
} buffer_t;
static const buffer_t g_nullBuffer = { NULL, 0 };
@@ -95,9 +103,9 @@ typedef struct ZSTDMT_bufferPool_s {
buffer_t bTable[1]; /* variable size */
} ZSTDMT_bufferPool;
-static ZSTDMT_bufferPool* ZSTDMT_createBufferPool(unsigned nbThreads, ZSTD_customMem cMem)
+static ZSTDMT_bufferPool* ZSTDMT_createBufferPool(unsigned nbWorkers, ZSTD_customMem cMem)
{
- unsigned const maxNbBuffers = 2*nbThreads + 3;
+ unsigned const maxNbBuffers = 2*nbWorkers + 3;
ZSTDMT_bufferPool* const bufPool = (ZSTDMT_bufferPool*)ZSTD_calloc(
sizeof(ZSTDMT_bufferPool) + (maxNbBuffers-1) * sizeof(buffer_t), cMem);
if (bufPool==NULL) return NULL;
@@ -129,17 +137,21 @@ static void ZSTDMT_freeBufferPool(ZSTDMT_bufferPool* bufPool)
static size_t ZSTDMT_sizeof_bufferPool(ZSTDMT_bufferPool* bufPool)
{
size_t const poolSize = sizeof(*bufPool)
- + (bufPool->totalBuffers - 1) * sizeof(buffer_t);
+ + (bufPool->totalBuffers - 1) * sizeof(buffer_t);
unsigned u;
size_t totalBufferSize = 0;
ZSTD_pthread_mutex_lock(&bufPool->poolMutex);
for (u=0; u<bufPool->totalBuffers; u++)
- totalBufferSize += bufPool->bTable[u].size;
+ totalBufferSize += bufPool->bTable[u].capacity;
ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
return poolSize + totalBufferSize;
}
+/* ZSTDMT_setBufferSize() :
+ * all future buffers provided by this buffer pool will have _at least_ this size
+ * note : it's better for all buffers to have same size,
+ * as they become freely interchangeable, reducing malloc/free usages and memory fragmentation */
static void ZSTDMT_setBufferSize(ZSTDMT_bufferPool* const bufPool, size_t const bSize)
{
ZSTD_pthread_mutex_lock(&bufPool->poolMutex);
@@ -149,7 +161,9 @@ static void ZSTDMT_setBufferSize(ZSTDMT_bufferPool* const bufPool, size_t const
}
/** ZSTDMT_getBuffer() :
- * assumption : bufPool must be valid */
+ * assumption : bufPool must be valid
+ * @return : a buffer, with start pointer and size
+ * note: allocation may fail, in this case, start==NULL and size==0 */
static buffer_t ZSTDMT_getBuffer(ZSTDMT_bufferPool* bufPool)
{
size_t const bSize = bufPool->bufferSize;
@@ -157,12 +171,12 @@ static buffer_t ZSTDMT_getBuffer(ZSTDMT_bufferPool* bufPool)
ZSTD_pthread_mutex_lock(&bufPool->poolMutex);
if (bufPool->nbBuffers) { /* try to use an existing buffer */
buffer_t const buf = bufPool->bTable[--(bufPool->nbBuffers)];
- size_t const availBufferSize = buf.size;
+ size_t const availBufferSize = buf.capacity;
bufPool->bTable[bufPool->nbBuffers] = g_nullBuffer;
if ((availBufferSize >= bSize) & ((availBufferSize>>3) <= bSize)) {
/* large enough, but not too much */
DEBUGLOG(5, "ZSTDMT_getBuffer: provide buffer %u of size %u",
- bufPool->nbBuffers, (U32)buf.size);
+ bufPool->nbBuffers, (U32)buf.capacity);
ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
return buf;
}
@@ -176,12 +190,42 @@ static buffer_t ZSTDMT_getBuffer(ZSTDMT_bufferPool* bufPool)
{ buffer_t buffer;
void* const start = ZSTD_malloc(bSize, bufPool->cMem);
buffer.start = start; /* note : start can be NULL if malloc fails ! */
- buffer.size = (start==NULL) ? 0 : bSize;
- DEBUGLOG(5, "ZSTDMT_getBuffer: created buffer of size %u", (U32)bSize);
+ buffer.capacity = (start==NULL) ? 0 : bSize;
+ if (start==NULL) {
+ DEBUGLOG(5, "ZSTDMT_getBuffer: buffer allocation failure !!");
+ } else {
+ DEBUGLOG(5, "ZSTDMT_getBuffer: created buffer of size %u", (U32)bSize);
+ }
return buffer;
}
}
+#if ZSTD_RESIZE_SEQPOOL
+/** ZSTDMT_resizeBuffer() :
+ * assumption : bufPool must be valid
+ * @return : a buffer that is at least the buffer pool buffer size.
+ * If a reallocation happens, the data in the input buffer is copied.
+ */
+static buffer_t ZSTDMT_resizeBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buffer)
+{
+ size_t const bSize = bufPool->bufferSize;
+ if (buffer.capacity < bSize) {
+ void* const start = ZSTD_malloc(bSize, bufPool->cMem);
+ buffer_t newBuffer;
+ newBuffer.start = start;
+ newBuffer.capacity = start == NULL ? 0 : bSize;
+ if (start != NULL) {
+ assert(newBuffer.capacity >= buffer.capacity);
+ memcpy(newBuffer.start, buffer.start, buffer.capacity);
+ DEBUGLOG(5, "ZSTDMT_resizeBuffer: created buffer of size %u", (U32)bSize);
+ return newBuffer;
+ }
+ DEBUGLOG(5, "ZSTDMT_resizeBuffer: buffer allocation failure !!");
+ }
+ return buffer;
+}
+#endif
+
/* store buffer for later re-use, up to pool capacity */
static void ZSTDMT_releaseBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buf)
{
@@ -191,7 +235,7 @@ static void ZSTDMT_releaseBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buf)
if (bufPool->nbBuffers < bufPool->totalBuffers) {
bufPool->bTable[bufPool->nbBuffers++] = buf; /* stored for later use */
DEBUGLOG(5, "ZSTDMT_releaseBuffer: stored buffer of size %u in slot %u",
- (U32)buf.size, (U32)(bufPool->nbBuffers-1));
+ (U32)buf.capacity, (U32)(bufPool->nbBuffers-1));
ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
return;
}
@@ -201,21 +245,73 @@ static void ZSTDMT_releaseBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buf)
ZSTD_free(buf.start, bufPool->cMem);
}
-/* Sets parameters relevant to the compression job, initializing others to
- * default values. Notably, nbThreads should probably be zero. */
-static ZSTD_CCtx_params ZSTDMT_makeJobCCtxParams(ZSTD_CCtx_params const params)
+
+/* ===== Seq Pool Wrapper ====== */
+
+static rawSeqStore_t kNullRawSeqStore = {NULL, 0, 0, 0};
+
+typedef ZSTDMT_bufferPool ZSTDMT_seqPool;
+
+static size_t ZSTDMT_sizeof_seqPool(ZSTDMT_seqPool* seqPool)
+{
+ return ZSTDMT_sizeof_bufferPool(seqPool);
+}
+
+static rawSeqStore_t bufferToSeq(buffer_t buffer)
{
- ZSTD_CCtx_params jobParams;
- memset(&jobParams, 0, sizeof(jobParams));
+ rawSeqStore_t seq = {NULL, 0, 0, 0};
+ seq.seq = (rawSeq*)buffer.start;
+ seq.capacity = buffer.capacity / sizeof(rawSeq);
+ return seq;
+}
- jobParams.cParams = params.cParams;
- jobParams.fParams = params.fParams;
- jobParams.compressionLevel = params.compressionLevel;
+static buffer_t seqToBuffer(rawSeqStore_t seq)
+{
+ buffer_t buffer;
+ buffer.start = seq.seq;
+ buffer.capacity = seq.capacity * sizeof(rawSeq);
+ return buffer;
+}
- jobParams.ldmParams = params.ldmParams;
- return jobParams;
+static rawSeqStore_t ZSTDMT_getSeq(ZSTDMT_seqPool* seqPool)
+{
+ if (seqPool->bufferSize == 0) {
+ return kNullRawSeqStore;
+ }
+ return bufferToSeq(ZSTDMT_getBuffer(seqPool));
}
+#if ZSTD_RESIZE_SEQPOOL
+static rawSeqStore_t ZSTDMT_resizeSeq(ZSTDMT_seqPool* seqPool, rawSeqStore_t seq)
+{
+ return bufferToSeq(ZSTDMT_resizeBuffer(seqPool, seqToBuffer(seq)));
+}
+#endif
+
+static void ZSTDMT_releaseSeq(ZSTDMT_seqPool* seqPool, rawSeqStore_t seq)
+{
+ ZSTDMT_releaseBuffer(seqPool, seqToBuffer(seq));
+}
+
+static void ZSTDMT_setNbSeq(ZSTDMT_seqPool* const seqPool, size_t const nbSeq)
+{
+ ZSTDMT_setBufferSize(seqPool, nbSeq * sizeof(rawSeq));
+}
+
+static ZSTDMT_seqPool* ZSTDMT_createSeqPool(unsigned nbWorkers, ZSTD_customMem cMem)
+{
+ ZSTDMT_seqPool* seqPool = ZSTDMT_createBufferPool(nbWorkers, cMem);
+ ZSTDMT_setNbSeq(seqPool, 0);
+ return seqPool;
+}
+
+static void ZSTDMT_freeSeqPool(ZSTDMT_seqPool* seqPool)
+{
+ ZSTDMT_freeBufferPool(seqPool);
+}
+
+
+
/* ===== CCtx Pool ===== */
/* a single CCtx Pool can be invoked from multiple threads in parallel */
@@ -238,23 +334,24 @@ static void ZSTDMT_freeCCtxPool(ZSTDMT_CCtxPool* pool)
}
/* ZSTDMT_createCCtxPool() :
- * implies nbThreads >= 1 , checked by caller ZSTDMT_createCCtx() */
-static ZSTDMT_CCtxPool* ZSTDMT_createCCtxPool(unsigned nbThreads,
+ * implies nbWorkers >= 1 , checked by caller ZSTDMT_createCCtx() */
+static ZSTDMT_CCtxPool* ZSTDMT_createCCtxPool(unsigned nbWorkers,
ZSTD_customMem cMem)
{
ZSTDMT_CCtxPool* const cctxPool = (ZSTDMT_CCtxPool*) ZSTD_calloc(
- sizeof(ZSTDMT_CCtxPool) + (nbThreads-1)*sizeof(ZSTD_CCtx*), cMem);
+ sizeof(ZSTDMT_CCtxPool) + (nbWorkers-1)*sizeof(ZSTD_CCtx*), cMem);
+ assert(nbWorkers > 0);
if (!cctxPool) return NULL;
if (ZSTD_pthread_mutex_init(&cctxPool->poolMutex, NULL)) {
ZSTD_free(cctxPool, cMem);
return NULL;
}
cctxPool->cMem = cMem;
- cctxPool->totalCCtx = nbThreads;
+ cctxPool->totalCCtx = nbWorkers;
cctxPool->availCCtx = 1; /* at least one cctx for single-thread mode */
cctxPool->cctx[0] = ZSTD_createCCtx_advanced(cMem);
if (!cctxPool->cctx[0]) { ZSTDMT_freeCCtxPool(cctxPool); return NULL; }
- DEBUGLOG(3, "cctxPool created, with %u threads", nbThreads);
+ DEBUGLOG(3, "cctxPool created, with %u workers", nbWorkers);
return cctxPool;
}
@@ -262,15 +359,16 @@ static ZSTDMT_CCtxPool* ZSTDMT_createCCtxPool(unsigned nbThreads,
static size_t ZSTDMT_sizeof_CCtxPool(ZSTDMT_CCtxPool* cctxPool)
{
ZSTD_pthread_mutex_lock(&cctxPool->poolMutex);
- { unsigned const nbThreads = cctxPool->totalCCtx;
+ { unsigned const nbWorkers = cctxPool->totalCCtx;
size_t const poolSize = sizeof(*cctxPool)
- + (nbThreads-1)*sizeof(ZSTD_CCtx*);
+ + (nbWorkers-1) * sizeof(ZSTD_CCtx*);
unsigned u;
size_t totalCCtxSize = 0;
- for (u=0; u<nbThreads; u++) {
+ for (u=0; u<nbWorkers; u++) {
totalCCtxSize += ZSTD_sizeof_CCtx(cctxPool->cctx[u]);
}
ZSTD_pthread_mutex_unlock(&cctxPool->poolMutex);
+ assert(nbWorkers > 0);
return poolSize + totalCCtxSize;
}
}
@@ -297,111 +395,318 @@ static void ZSTDMT_releaseCCtx(ZSTDMT_CCtxPool* pool, ZSTD_CCtx* cctx)
if (pool->availCCtx < pool->totalCCtx)
pool->cctx[pool->availCCtx++] = cctx;
else {
- /* pool overflow : should not happen, since totalCCtx==nbThreads */
- DEBUGLOG(5, "CCtx pool overflow : free cctx");
+ /* pool overflow : should not happen, since totalCCtx==nbWorkers */
+ DEBUGLOG(4, "CCtx pool overflow : free cctx");
ZSTD_freeCCtx(cctx);
}
ZSTD_pthread_mutex_unlock(&pool->poolMutex);
}
+/* ==== Serial State ==== */
-/* ===== Thread worker ===== */
+typedef struct {
+ void const* start;
+ size_t size;
+} range_t;
typedef struct {
- buffer_t src;
- const void* srcStart;
- size_t prefixSize;
- size_t srcSize;
- buffer_t dstBuff;
- size_t cSize;
- size_t dstFlushed;
- unsigned firstChunk;
- unsigned lastChunk;
- unsigned jobCompleted;
- unsigned jobScanned;
- ZSTD_pthread_mutex_t* jobCompleted_mutex;
- ZSTD_pthread_cond_t* jobCompleted_cond;
+ /* All variables in the struct are protected by mutex. */
+ ZSTD_pthread_mutex_t mutex;
+ ZSTD_pthread_cond_t cond;
ZSTD_CCtx_params params;
- const ZSTD_CDict* cdict;
- ZSTDMT_CCtxPool* cctxPool;
- ZSTDMT_bufferPool* bufPool;
- unsigned long long fullFrameSize;
+ ldmState_t ldmState;
+ XXH64_state_t xxhState;
+ unsigned nextJobID;
+ /* Protects ldmWindow.
+ * Must be acquired after the main mutex when acquiring both.
+ */
+ ZSTD_pthread_mutex_t ldmWindowMutex;
+ ZSTD_pthread_cond_t ldmWindowCond; /* Signaled when ldmWindow is udpated */
+ ZSTD_window_t ldmWindow; /* A thread-safe copy of ldmState.window */
+} serialState_t;
+
+static int ZSTDMT_serialState_reset(serialState_t* serialState, ZSTDMT_seqPool* seqPool, ZSTD_CCtx_params params)
+{
+ /* Adjust parameters */
+ if (params.ldmParams.enableLdm) {
+ DEBUGLOG(4, "LDM window size = %u KB", (1U << params.cParams.windowLog) >> 10);
+ params.ldmParams.windowLog = params.cParams.windowLog;
+ ZSTD_ldm_adjustParameters(&params.ldmParams, &params.cParams);
+ assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog);
+ assert(params.ldmParams.hashEveryLog < 32);
+ serialState->ldmState.hashPower =
+ ZSTD_ldm_getHashPower(params.ldmParams.minMatchLength);
+ } else {
+ memset(&params.ldmParams, 0, sizeof(params.ldmParams));
+ }
+ serialState->nextJobID = 0;
+ if (params.fParams.checksumFlag)
+ XXH64_reset(&serialState->xxhState, 0);
+ if (params.ldmParams.enableLdm) {
+ ZSTD_customMem cMem = params.customMem;
+ unsigned const hashLog = params.ldmParams.hashLog;
+ size_t const hashSize = ((size_t)1 << hashLog) * sizeof(ldmEntry_t);
+ unsigned const bucketLog =
+ params.ldmParams.hashLog - params.ldmParams.bucketSizeLog;
+ size_t const bucketSize = (size_t)1 << bucketLog;
+ unsigned const prevBucketLog =
+ serialState->params.ldmParams.hashLog -
+ serialState->params.ldmParams.bucketSizeLog;
+ /* Size the seq pool tables */
+ ZSTDMT_setNbSeq(seqPool, ZSTD_ldm_getMaxNbSeq(params.ldmParams, params.jobSize));
+ /* Reset the window */
+ ZSTD_window_clear(&serialState->ldmState.window);
+ serialState->ldmWindow = serialState->ldmState.window;
+ /* Resize tables and output space if necessary. */
+ if (serialState->ldmState.hashTable == NULL || serialState->params.ldmParams.hashLog < hashLog) {
+ ZSTD_free(serialState->ldmState.hashTable, cMem);
+ serialState->ldmState.hashTable = (ldmEntry_t*)ZSTD_malloc(hashSize, cMem);
+ }
+ if (serialState->ldmState.bucketOffsets == NULL || prevBucketLog < bucketLog) {
+ ZSTD_free(serialState->ldmState.bucketOffsets, cMem);
+ serialState->ldmState.bucketOffsets = (BYTE*)ZSTD_malloc(bucketSize, cMem);
+ }
+ if (!serialState->ldmState.hashTable || !serialState->ldmState.bucketOffsets)
+ return 1;
+ /* Zero the tables */
+ memset(serialState->ldmState.hashTable, 0, hashSize);
+ memset(serialState->ldmState.bucketOffsets, 0, bucketSize);
+ }
+ serialState->params = params;
+ return 0;
+}
+
+static int ZSTDMT_serialState_init(serialState_t* serialState)
+{
+ int initError = 0;
+ memset(serialState, 0, sizeof(*serialState));
+ initError |= ZSTD_pthread_mutex_init(&serialState->mutex, NULL);
+ initError |= ZSTD_pthread_cond_init(&serialState->cond, NULL);
+ initError |= ZSTD_pthread_mutex_init(&serialState->ldmWindowMutex, NULL);
+ initError |= ZSTD_pthread_cond_init(&serialState->ldmWindowCond, NULL);
+ return initError;
+}
+
+static void ZSTDMT_serialState_free(serialState_t* serialState)
+{
+ ZSTD_customMem cMem = serialState->params.customMem;
+ ZSTD_pthread_mutex_destroy(&serialState->mutex);
+ ZSTD_pthread_cond_destroy(&serialState->cond);
+ ZSTD_pthread_mutex_destroy(&serialState->ldmWindowMutex);
+ ZSTD_pthread_cond_destroy(&serialState->ldmWindowCond);
+ ZSTD_free(serialState->ldmState.hashTable, cMem);
+ ZSTD_free(serialState->ldmState.bucketOffsets, cMem);
+}
+
+static void ZSTDMT_serialState_update(serialState_t* serialState,
+ ZSTD_CCtx* jobCCtx, rawSeqStore_t seqStore,
+ range_t src, unsigned jobID)
+{
+ /* Wait for our turn */
+ ZSTD_PTHREAD_MUTEX_LOCK(&serialState->mutex);
+ while (serialState->nextJobID < jobID) {
+ ZSTD_pthread_cond_wait(&serialState->cond, &serialState->mutex);
+ }
+ /* A future job may error and skip our job */
+ if (serialState->nextJobID == jobID) {
+ /* It is now our turn, do any processing necessary */
+ if (serialState->params.ldmParams.enableLdm) {
+ size_t error;
+ assert(seqStore.seq != NULL && seqStore.pos == 0 &&
+ seqStore.size == 0 && seqStore.capacity > 0);
+ ZSTD_window_update(&serialState->ldmState.window, src.start, src.size);
+ error = ZSTD_ldm_generateSequences(
+ &serialState->ldmState, &seqStore,
+ &serialState->params.ldmParams, src.start, src.size);
+ /* We provide a large enough buffer to never fail. */
+ assert(!ZSTD_isError(error)); (void)error;
+ /* Update ldmWindow to match the ldmState.window and signal the main
+ * thread if it is waiting for a buffer.
+ */
+ ZSTD_PTHREAD_MUTEX_LOCK(&serialState->ldmWindowMutex);
+ serialState->ldmWindow = serialState->ldmState.window;
+ ZSTD_pthread_cond_signal(&serialState->ldmWindowCond);
+ ZSTD_pthread_mutex_unlock(&serialState->ldmWindowMutex);
+ }
+ if (serialState->params.fParams.checksumFlag && src.size > 0)
+ XXH64_update(&serialState->xxhState, src.start, src.size);
+ }
+ /* Now it is the next jobs turn */
+ serialState->nextJobID++;
+ ZSTD_pthread_cond_broadcast(&serialState->cond);
+ ZSTD_pthread_mutex_unlock(&serialState->mutex);
+
+ if (seqStore.size > 0) {
+ size_t const err = ZSTD_referenceExternalSequences(
+ jobCCtx, seqStore.seq, seqStore.size);
+ assert(serialState->params.ldmParams.enableLdm);
+ assert(!ZSTD_isError(err));
+ (void)err;
+ }
+}
+
+static void ZSTDMT_serialState_ensureFinished(serialState_t* serialState,
+ unsigned jobID, size_t cSize)
+{
+ ZSTD_PTHREAD_MUTEX_LOCK(&serialState->mutex);
+ if (serialState->nextJobID <= jobID) {
+ assert(ZSTD_isError(cSize)); (void)cSize;
+ DEBUGLOG(5, "Skipping past job %u because of error", jobID);
+ serialState->nextJobID = jobID + 1;
+ ZSTD_pthread_cond_broadcast(&serialState->cond);
+
+ ZSTD_PTHREAD_MUTEX_LOCK(&serialState->ldmWindowMutex);
+ ZSTD_window_clear(&serialState->ldmWindow);
+ ZSTD_pthread_cond_signal(&serialState->ldmWindowCond);
+ ZSTD_pthread_mutex_unlock(&serialState->ldmWindowMutex);
+ }
+ ZSTD_pthread_mutex_unlock(&serialState->mutex);
+
+}
+
+
+/* ------------------------------------------ */
+/* ===== Worker thread ===== */
+/* ------------------------------------------ */
+
+static const range_t kNullRange = { NULL, 0 };
+
+typedef struct {
+ size_t consumed; /* SHARED - set0 by mtctx, then modified by worker AND read by mtctx */
+ size_t cSize; /* SHARED - set0 by mtctx, then modified by worker AND read by mtctx, then set0 by mtctx */
+ ZSTD_pthread_mutex_t job_mutex; /* Thread-safe - used by mtctx and worker */
+ ZSTD_pthread_cond_t job_cond; /* Thread-safe - used by mtctx and worker */
+ ZSTDMT_CCtxPool* cctxPool; /* Thread-safe - used by mtctx and (all) workers */
+ ZSTDMT_bufferPool* bufPool; /* Thread-safe - used by mtctx and (all) workers */
+ ZSTDMT_seqPool* seqPool; /* Thread-safe - used by mtctx and (all) workers */
+ serialState_t* serial; /* Thread-safe - used by mtctx and (all) workers */
+ buffer_t dstBuff; /* set by worker (or mtctx), then read by worker & mtctx, then modified by mtctx => no barrier */
+ range_t prefix; /* set by mtctx, then read by worker & mtctx => no barrier */
+ range_t src; /* set by mtctx, then read by worker & mtctx => no barrier */
+ unsigned jobID; /* set by mtctx, then read by worker => no barrier */
+ unsigned firstJob; /* set by mtctx, then read by worker => no barrier */
+ unsigned lastJob; /* set by mtctx, then read by worker => no barrier */
+ ZSTD_CCtx_params params; /* set by mtctx, then read by worker => no barrier */
+ const ZSTD_CDict* cdict; /* set by mtctx, then read by worker => no barrier */
+ unsigned long long fullFrameSize; /* set by mtctx, then read by worker => no barrier */
+ size_t dstFlushed; /* used only by mtctx */
+ unsigned frameChecksumNeeded; /* used only by mtctx */
} ZSTDMT_jobDescription;
-/* ZSTDMT_compressChunk() : POOL_function type */
-void ZSTDMT_compressChunk(void* jobDescription)
+/* ZSTDMT_compressionJob() is a POOL_function type */
+void ZSTDMT_compressionJob(void* jobDescription)
{
ZSTDMT_jobDescription* const job = (ZSTDMT_jobDescription*)jobDescription;
+ ZSTD_CCtx_params jobParams = job->params; /* do not modify job->params ! copy it, modify the copy */
ZSTD_CCtx* const cctx = ZSTDMT_getCCtx(job->cctxPool);
- const void* const src = (const char*)job->srcStart + job->prefixSize;
+ rawSeqStore_t rawSeqStore = ZSTDMT_getSeq(job->seqPool);
buffer_t dstBuff = job->dstBuff;
- DEBUGLOG(5, "ZSTDMT_compressChunk: job (first:%u) (last:%u) : prefixSize %u, srcSize %u ",
- job->firstChunk, job->lastChunk, (U32)job->prefixSize, (U32)job->srcSize);
+ /* Don't compute the checksum for chunks, since we compute it externally,
+ * but write it in the header.
+ */
+ if (job->jobID != 0) jobParams.fParams.checksumFlag = 0;
+ /* Don't run LDM for the chunks, since we handle it externally */
+ jobParams.ldmParams.enableLdm = 0;
+
+ /* ressources */
if (cctx==NULL) {
job->cSize = ERROR(memory_allocation);
goto _endJob;
}
-
- if (dstBuff.start == NULL) {
+ if (dstBuff.start == NULL) { /* streaming job : doesn't provide a dstBuffer */
dstBuff = ZSTDMT_getBuffer(job->bufPool);
if (dstBuff.start==NULL) {
job->cSize = ERROR(memory_allocation);
goto _endJob;
}
- job->dstBuff = dstBuff;
- DEBUGLOG(5, "ZSTDMT_compressChunk: received dstBuff of size %u", (U32)dstBuff.size);
+ job->dstBuff = dstBuff; /* this value can be read in ZSTDMT_flush, when it copies the whole job */
}
+ /* init */
if (job->cdict) {
- size_t const initError = ZSTD_compressBegin_advanced_internal(cctx, NULL, 0, ZSTD_dm_auto, job->cdict, job->params, job->fullFrameSize);
- DEBUGLOG(4, "ZSTDMT_compressChunk: init using CDict (windowLog=%u)", job->params.cParams.windowLog);
- assert(job->firstChunk); /* only allowed for first job */
+ size_t const initError = ZSTD_compressBegin_advanced_internal(cctx, NULL, 0, ZSTD_dct_auto, job->cdict, jobParams, job->fullFrameSize);
+ assert(job->firstJob); /* only allowed for first job */
if (ZSTD_isError(initError)) { job->cSize = initError; goto _endJob; }
} else { /* srcStart points at reloaded section */
- U64 const pledgedSrcSize = job->firstChunk ? job->fullFrameSize : ZSTD_CONTENTSIZE_UNKNOWN;
- ZSTD_CCtx_params jobParams = job->params; /* do not modify job->params ! copy it, modify the copy */
- size_t const forceWindowError = ZSTD_CCtxParam_setParameter(&jobParams, ZSTD_p_forceMaxWindow, !job->firstChunk);
- if (ZSTD_isError(forceWindowError)) {
- DEBUGLOG(5, "ZSTD_CCtxParam_setParameter error : %s ", ZSTD_getErrorName(forceWindowError));
- job->cSize = forceWindowError;
- goto _endJob;
- }
- DEBUGLOG(5, "ZSTDMT_compressChunk: invoking ZSTD_compressBegin_advanced_internal with windowLog = %u ", jobParams.cParams.windowLog);
+ U64 const pledgedSrcSize = job->firstJob ? job->fullFrameSize : job->src.size;
+ { size_t const forceWindowError = ZSTD_CCtxParam_setParameter(&jobParams, ZSTD_p_forceMaxWindow, !job->firstJob);
+ if (ZSTD_isError(forceWindowError)) {
+ job->cSize = forceWindowError;
+ goto _endJob;
+ } }
{ size_t const initError = ZSTD_compressBegin_advanced_internal(cctx,
- job->srcStart, job->prefixSize, ZSTD_dm_rawContent, /* load dictionary in "content-only" mode (no header analysis) */
- NULL,
+ job->prefix.start, job->prefix.size, ZSTD_dct_rawContent, /* load dictionary in "content-only" mode (no header analysis) */
+ NULL, /*cdict*/
jobParams, pledgedSrcSize);
if (ZSTD_isError(initError)) {
- DEBUGLOG(5, "ZSTD_compressBegin_advanced_internal error : %s ", ZSTD_getErrorName(initError));
job->cSize = initError;
goto _endJob;
- } }
- }
- if (!job->firstChunk) { /* flush and overwrite frame header when it's not first job */
- size_t const hSize = ZSTD_compressContinue(cctx, dstBuff.start, dstBuff.size, src, 0);
+ } } }
+
+ /* Perform serial step as early as possible, but after CCtx initialization */
+ ZSTDMT_serialState_update(job->serial, cctx, rawSeqStore, job->src, job->jobID);
+
+ if (!job->firstJob) { /* flush and overwrite frame header when it's not first job */
+ size_t const hSize = ZSTD_compressContinue(cctx, dstBuff.start, dstBuff.capacity, job->src.start, 0);
if (ZSTD_isError(hSize)) { job->cSize = hSize; /* save error code */ goto _endJob; }
+ DEBUGLOG(5, "ZSTDMT_compressionJob: flush and overwrite %u bytes of frame header (not first job)", (U32)hSize);
ZSTD_invalidateRepCodes(cctx);
}
- DEBUGLOG(5, "Compressing into dstBuff of size %u", (U32)dstBuff.size);
- DEBUG_PRINTHEX(6, job->srcStart, 12);
- job->cSize = (job->lastChunk) ?
- ZSTD_compressEnd (cctx, dstBuff.start, dstBuff.size, src, job->srcSize) :
- ZSTD_compressContinue(cctx, dstBuff.start, dstBuff.size, src, job->srcSize);
- DEBUGLOG(5, "compressed %u bytes into %u bytes (first:%u) (last:%u) ",
- (unsigned)job->srcSize, (unsigned)job->cSize, job->firstChunk, job->lastChunk);
- DEBUGLOG(5, "dstBuff.size : %u ; => %s ", (U32)dstBuff.size, ZSTD_getErrorName(job->cSize));
+ /* compress */
+ { size_t const chunkSize = 4*ZSTD_BLOCKSIZE_MAX;
+ int const nbChunks = (int)((job->src.size + (chunkSize-1)) / chunkSize);
+ const BYTE* ip = (const BYTE*) job->src.start;
+ BYTE* const ostart = (BYTE*)dstBuff.start;
+ BYTE* op = ostart;
+ BYTE* oend = op + dstBuff.capacity;
+ int chunkNb;
+ if (sizeof(size_t) > sizeof(int)) assert(job->src.size < ((size_t)INT_MAX) * chunkSize); /* check overflow */
+ DEBUGLOG(5, "ZSTDMT_compressionJob: compress %u bytes in %i blocks", (U32)job->src.size, nbChunks);
+ assert(job->cSize == 0);
+ for (chunkNb = 1; chunkNb < nbChunks; chunkNb++) {
+ size_t const cSize = ZSTD_compressContinue(cctx, op, oend-op, ip, chunkSize);
+ if (ZSTD_isError(cSize)) { job->cSize = cSize; goto _endJob; }
+ ip += chunkSize;
+ op += cSize; assert(op < oend);
+ /* stats */
+ ZSTD_PTHREAD_MUTEX_LOCK(&job->job_mutex);
+ job->cSize += cSize;
+ job->consumed = chunkSize * chunkNb;
+ DEBUGLOG(5, "ZSTDMT_compressionJob: compress new block : cSize==%u bytes (total: %u)",
+ (U32)cSize, (U32)job->cSize);
+ ZSTD_pthread_cond_signal(&job->job_cond); /* warns some more data is ready to be flushed */
+ ZSTD_pthread_mutex_unlock(&job->job_mutex);
+ }
+ /* last block */
+ assert(chunkSize > 0); assert((chunkSize & (chunkSize - 1)) == 0); /* chunkSize must be power of 2 for mask==(chunkSize-1) to work */
+ if ((nbChunks > 0) | job->lastJob /*must output a "last block" flag*/ ) {
+ size_t const lastBlockSize1 = job->src.size & (chunkSize-1);
+ size_t const lastBlockSize = ((lastBlockSize1==0) & (job->src.size>=chunkSize)) ? chunkSize : lastBlockSize1;
+ size_t const cSize = (job->lastJob) ?
+ ZSTD_compressEnd (cctx, op, oend-op, ip, lastBlockSize) :
+ ZSTD_compressContinue(cctx, op, oend-op, ip, lastBlockSize);
+ if (ZSTD_isError(cSize)) { job->cSize = cSize; goto _endJob; }
+ /* stats */
+ ZSTD_PTHREAD_MUTEX_LOCK(&job->job_mutex);
+ job->cSize += cSize;
+ ZSTD_pthread_mutex_unlock(&job->job_mutex);
+ } }
_endJob:
+ ZSTDMT_serialState_ensureFinished(job->serial, job->jobID, job->cSize);
+ if (job->prefix.size > 0)
+ DEBUGLOG(5, "Finished with prefix: %zx", (size_t)job->prefix.start);
+ DEBUGLOG(5, "Finished with source: %zx", (size_t)job->src.start);
+ /* release resources */
+ ZSTDMT_releaseSeq(job->seqPool, rawSeqStore);
ZSTDMT_releaseCCtx(job->cctxPool, cctx);
- ZSTDMT_releaseBuffer(job->bufPool, job->src);
- job->src = g_nullBuffer; job->srcStart = NULL;
- ZSTD_PTHREAD_MUTEX_LOCK(job->jobCompleted_mutex);
- job->jobCompleted = 1;
- job->jobScanned = 0;
- ZSTD_pthread_cond_signal(job->jobCompleted_cond);
- ZSTD_pthread_mutex_unlock(job->jobCompleted_mutex);
+ /* report */
+ ZSTD_PTHREAD_MUTEX_LOCK(&job->job_mutex);
+ job->consumed = job->src.size;
+ ZSTD_pthread_cond_signal(&job->job_cond);
+ ZSTD_pthread_mutex_unlock(&job->job_mutex);
}
@@ -410,109 +715,141 @@ _endJob:
/* ------------------------------------------ */
typedef struct {
+ range_t prefix; /* read-only non-owned prefix buffer */
buffer_t buffer;
size_t filled;
} inBuff_t;
+typedef struct {
+ BYTE* buffer; /* The round input buffer. All jobs get references
+ * to pieces of the buffer. ZSTDMT_tryGetInputRange()
+ * handles handing out job input buffers, and makes
+ * sure it doesn't overlap with any pieces still in use.
+ */
+ size_t capacity; /* The capacity of buffer. */
+ size_t pos; /* The position of the current inBuff in the round
+ * buffer. Updated past the end if the inBuff once
+ * the inBuff is sent to the worker thread.
+ * pos <= capacity.
+ */
+} roundBuff_t;
+
+static const roundBuff_t kNullRoundBuff = {NULL, 0, 0};
+
struct ZSTDMT_CCtx_s {
POOL_ctx* factory;
ZSTDMT_jobDescription* jobs;
ZSTDMT_bufferPool* bufPool;
ZSTDMT_CCtxPool* cctxPool;
- ZSTD_pthread_mutex_t jobCompleted_mutex;
- ZSTD_pthread_cond_t jobCompleted_cond;
+ ZSTDMT_seqPool* seqPool;
ZSTD_CCtx_params params;
size_t targetSectionSize;
- size_t inBuffSize;
- size_t dictSize;
- size_t targetDictSize;
+ size_t targetPrefixSize;
+ roundBuff_t roundBuff;
inBuff_t inBuff;
- XXH64_state_t xxhState;
- unsigned singleThreaded;
+ int jobReady; /* 1 => one job is already prepared, but pool has shortage of workers. Don't create another one. */
+ serialState_t serial;
+ unsigned singleBlockingThread;
unsigned jobIDMask;
unsigned doneJobID;
unsigned nextJobID;
unsigned frameEnded;
unsigned allJobsCompleted;
unsigned long long frameContentSize;
+ unsigned long long consumed;
+ unsigned long long produced;
ZSTD_customMem cMem;
ZSTD_CDict* cdictLocal;
const ZSTD_CDict* cdict;
};
-static ZSTDMT_jobDescription* ZSTDMT_allocJobsTable(U32* nbJobsPtr, ZSTD_customMem cMem)
+static void ZSTDMT_freeJobsTable(ZSTDMT_jobDescription* jobTable, U32 nbJobs, ZSTD_customMem cMem)
+{
+ U32 jobNb;
+ if (jobTable == NULL) return;
+ for (jobNb=0; jobNb<nbJobs; jobNb++) {
+ ZSTD_pthread_mutex_destroy(&jobTable[jobNb].job_mutex);
+ ZSTD_pthread_cond_destroy(&jobTable[jobNb].job_cond);
+ }
+ ZSTD_free(jobTable, cMem);
+}
+
+/* ZSTDMT_allocJobsTable()
+ * allocate and init a job table.
+ * update *nbJobsPtr to next power of 2 value, as size of table */
+static ZSTDMT_jobDescription* ZSTDMT_createJobsTable(U32* nbJobsPtr, ZSTD_customMem cMem)
{
U32 const nbJobsLog2 = ZSTD_highbit32(*nbJobsPtr) + 1;
U32 const nbJobs = 1 << nbJobsLog2;
+ U32 jobNb;
+ ZSTDMT_jobDescription* const jobTable = (ZSTDMT_jobDescription*)
+ ZSTD_calloc(nbJobs * sizeof(ZSTDMT_jobDescription), cMem);
+ int initError = 0;
+ if (jobTable==NULL) return NULL;
*nbJobsPtr = nbJobs;
- return (ZSTDMT_jobDescription*) ZSTD_calloc(
- nbJobs * sizeof(ZSTDMT_jobDescription), cMem);
+ for (jobNb=0; jobNb<nbJobs; jobNb++) {
+ initError |= ZSTD_pthread_mutex_init(&jobTable[jobNb].job_mutex, NULL);
+ initError |= ZSTD_pthread_cond_init(&jobTable[jobNb].job_cond, NULL);
+ }
+ if (initError != 0) {
+ ZSTDMT_freeJobsTable(jobTable, nbJobs, cMem);
+ return NULL;
+ }
+ return jobTable;
}
-/* ZSTDMT_CCtxParam_setNbThreads():
+/* ZSTDMT_CCtxParam_setNbWorkers():
* Internal use only */
-size_t ZSTDMT_CCtxParam_setNbThreads(ZSTD_CCtx_params* params, unsigned nbThreads)
+size_t ZSTDMT_CCtxParam_setNbWorkers(ZSTD_CCtx_params* params, unsigned nbWorkers)
{
- if (nbThreads > ZSTDMT_NBTHREADS_MAX) nbThreads = ZSTDMT_NBTHREADS_MAX;
- if (nbThreads < 1) nbThreads = 1;
- params->nbThreads = nbThreads;
+ if (nbWorkers > ZSTDMT_NBWORKERS_MAX) nbWorkers = ZSTDMT_NBWORKERS_MAX;
+ params->nbWorkers = nbWorkers;
params->overlapSizeLog = ZSTDMT_OVERLAPLOG_DEFAULT;
params->jobSize = 0;
- return nbThreads;
-}
-
-/* ZSTDMT_getNbThreads():
- * @return nb threads currently active in mtctx.
- * mtctx must be valid */
-size_t ZSTDMT_getNbThreads(const ZSTDMT_CCtx* mtctx)
-{
- assert(mtctx != NULL);
- return mtctx->params.nbThreads;
+ return nbWorkers;
}
-ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbThreads, ZSTD_customMem cMem)
+ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem)
{
ZSTDMT_CCtx* mtctx;
- U32 nbJobs = nbThreads + 2;
- DEBUGLOG(3, "ZSTDMT_createCCtx_advanced (nbThreads = %u)", nbThreads);
+ U32 nbJobs = nbWorkers + 2;
+ int initError;
+ DEBUGLOG(3, "ZSTDMT_createCCtx_advanced (nbWorkers = %u)", nbWorkers);
- if (nbThreads < 1) return NULL;
- nbThreads = MIN(nbThreads , ZSTDMT_NBTHREADS_MAX);
+ if (nbWorkers < 1) return NULL;
+ nbWorkers = MIN(nbWorkers , ZSTDMT_NBWORKERS_MAX);
if ((cMem.customAlloc!=NULL) ^ (cMem.customFree!=NULL))
/* invalid custom allocator */
return NULL;
mtctx = (ZSTDMT_CCtx*) ZSTD_calloc(sizeof(ZSTDMT_CCtx), cMem);
if (!mtctx) return NULL;
- ZSTDMT_CCtxParam_setNbThreads(&mtctx->params, nbThreads);
+ ZSTDMT_CCtxParam_setNbWorkers(&mtctx->params, nbWorkers);
mtctx->cMem = cMem;
mtctx->allJobsCompleted = 1;
- mtctx->factory = POOL_create_advanced(nbThreads, 0, cMem);
- mtctx->jobs = ZSTDMT_allocJobsTable(&nbJobs, cMem);
+ mtctx->factory = POOL_create_advanced(nbWorkers, 0, cMem);
+ mtctx->jobs = ZSTDMT_createJobsTable(&nbJobs, cMem);
+ assert(nbJobs > 0); assert((nbJobs & (nbJobs - 1)) == 0); /* ensure nbJobs is a power of 2 */
mtctx->jobIDMask = nbJobs - 1;
- mtctx->bufPool = ZSTDMT_createBufferPool(nbThreads, cMem);
- mtctx->cctxPool = ZSTDMT_createCCtxPool(nbThreads, cMem);
- if (!mtctx->factory | !mtctx->jobs | !mtctx->bufPool | !mtctx->cctxPool) {
+ mtctx->bufPool = ZSTDMT_createBufferPool(nbWorkers, cMem);
+ mtctx->cctxPool = ZSTDMT_createCCtxPool(nbWorkers, cMem);
+ mtctx->seqPool = ZSTDMT_createSeqPool(nbWorkers, cMem);
+ initError = ZSTDMT_serialState_init(&mtctx->serial);
+ mtctx->roundBuff = kNullRoundBuff;
+ if (!mtctx->factory | !mtctx->jobs | !mtctx->bufPool | !mtctx->cctxPool | !mtctx->seqPool | initError) {
ZSTDMT_freeCCtx(mtctx);
return NULL;
}
- if (ZSTD_pthread_mutex_init(&mtctx->jobCompleted_mutex, NULL)) {
- ZSTDMT_freeCCtx(mtctx);
- return NULL;
- }
- if (ZSTD_pthread_cond_init(&mtctx->jobCompleted_cond, NULL)) {
- ZSTDMT_freeCCtx(mtctx);
- return NULL;
- }
- DEBUGLOG(3, "mt_cctx created, for %u threads", nbThreads);
+ DEBUGLOG(3, "mt_cctx created, for %u threads", nbWorkers);
return mtctx;
}
-ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbThreads)
+ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbWorkers)
{
- return ZSTDMT_createCCtx_advanced(nbThreads, ZSTD_defaultCMem);
+ return ZSTDMT_createCCtx_advanced(nbWorkers, ZSTD_defaultCMem);
}
+
/* ZSTDMT_releaseAllJobResources() :
* note : ensure all workers are killed first ! */
static void ZSTDMT_releaseAllJobResources(ZSTDMT_CCtx* mtctx)
@@ -523,29 +860,26 @@ static void ZSTDMT_releaseAllJobResources(ZSTDMT_CCtx* mtctx)
DEBUGLOG(4, "job%02u: release dst address %08X", jobID, (U32)(size_t)mtctx->jobs[jobID].dstBuff.start);
ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[jobID].dstBuff);
mtctx->jobs[jobID].dstBuff = g_nullBuffer;
- DEBUGLOG(4, "job%02u: release src address %08X", jobID, (U32)(size_t)mtctx->jobs[jobID].src.start);
- ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[jobID].src);
- mtctx->jobs[jobID].src = g_nullBuffer;
+ mtctx->jobs[jobID].cSize = 0;
}
memset(mtctx->jobs, 0, (mtctx->jobIDMask+1)*sizeof(ZSTDMT_jobDescription));
- DEBUGLOG(4, "input: release address %08X", (U32)(size_t)mtctx->inBuff.buffer.start);
- ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->inBuff.buffer);
mtctx->inBuff.buffer = g_nullBuffer;
+ mtctx->inBuff.filled = 0;
mtctx->allJobsCompleted = 1;
}
-static void ZSTDMT_waitForAllJobsCompleted(ZSTDMT_CCtx* zcs)
+static void ZSTDMT_waitForAllJobsCompleted(ZSTDMT_CCtx* mtctx)
{
DEBUGLOG(4, "ZSTDMT_waitForAllJobsCompleted");
- while (zcs->doneJobID < zcs->nextJobID) {
- unsigned const jobID = zcs->doneJobID & zcs->jobIDMask;
- ZSTD_PTHREAD_MUTEX_LOCK(&zcs->jobCompleted_mutex);
- while (zcs->jobs[jobID].jobCompleted==0) {
- DEBUGLOG(5, "waiting for jobCompleted signal from chunk %u", zcs->doneJobID); /* we want to block when waiting for data to flush */
- ZSTD_pthread_cond_wait(&zcs->jobCompleted_cond, &zcs->jobCompleted_mutex);
+ while (mtctx->doneJobID < mtctx->nextJobID) {
+ unsigned const jobID = mtctx->doneJobID & mtctx->jobIDMask;
+ ZSTD_PTHREAD_MUTEX_LOCK(&mtctx->jobs[jobID].job_mutex);
+ while (mtctx->jobs[jobID].consumed < mtctx->jobs[jobID].src.size) {
+ DEBUGLOG(5, "waiting for jobCompleted signal from job %u", mtctx->doneJobID); /* we want to block when waiting for data to flush */
+ ZSTD_pthread_cond_wait(&mtctx->jobs[jobID].job_cond, &mtctx->jobs[jobID].job_mutex);
}
- ZSTD_pthread_mutex_unlock(&zcs->jobCompleted_mutex);
- zcs->doneJobID++;
+ ZSTD_pthread_mutex_unlock(&mtctx->jobs[jobID].job_mutex);
+ mtctx->doneJobID++;
}
}
@@ -554,12 +888,14 @@ size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx)
if (mtctx==NULL) return 0; /* compatible with free on NULL */
POOL_free(mtctx->factory); /* stop and free worker threads */
ZSTDMT_releaseAllJobResources(mtctx); /* release job resources into pools first */
- ZSTD_free(mtctx->jobs, mtctx->cMem);
+ ZSTDMT_freeJobsTable(mtctx->jobs, mtctx->jobIDMask+1, mtctx->cMem);
ZSTDMT_freeBufferPool(mtctx->bufPool);
ZSTDMT_freeCCtxPool(mtctx->cctxPool);
+ ZSTDMT_freeSeqPool(mtctx->seqPool);
+ ZSTDMT_serialState_free(&mtctx->serial);
ZSTD_freeCDict(mtctx->cdictLocal);
- ZSTD_pthread_mutex_destroy(&mtctx->jobCompleted_mutex);
- ZSTD_pthread_cond_destroy(&mtctx->jobCompleted_cond);
+ if (mtctx->roundBuff.buffer)
+ ZSTD_free(mtctx->roundBuff.buffer, mtctx->cMem);
ZSTD_free(mtctx, mtctx->cMem);
return 0;
}
@@ -572,7 +908,9 @@ size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx)
+ ZSTDMT_sizeof_bufferPool(mtctx->bufPool)
+ (mtctx->jobIDMask+1) * sizeof(ZSTDMT_jobDescription)
+ ZSTDMT_sizeof_CCtxPool(mtctx->cctxPool)
- + ZSTD_sizeof_CDict(mtctx->cdictLocal);
+ + ZSTDMT_sizeof_seqPool(mtctx->seqPool)
+ + ZSTD_sizeof_CDict(mtctx->cdictLocal)
+ + mtctx->roundBuff.capacity;
}
/* Internal only */
@@ -612,133 +950,224 @@ size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter,
}
}
+/* Sets parameters relevant to the compression job,
+ * initializing others to default values. */
+static ZSTD_CCtx_params ZSTDMT_initJobCCtxParams(ZSTD_CCtx_params const params)
+{
+ ZSTD_CCtx_params jobParams;
+ memset(&jobParams, 0, sizeof(jobParams));
+
+ jobParams.cParams = params.cParams;
+ jobParams.fParams = params.fParams;
+ jobParams.compressionLevel = params.compressionLevel;
+ jobParams.disableLiteralCompression = params.disableLiteralCompression;
+
+ return jobParams;
+}
+
+/*! ZSTDMT_updateCParams_whileCompressing() :
+ * Updates only a selected set of compression parameters, to remain compatible with current frame.
+ * New parameters will be applied to next compression job. */
+void ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_params* cctxParams)
+{
+ U32 const saved_wlog = mtctx->params.cParams.windowLog; /* Do not modify windowLog while compressing */
+ int const compressionLevel = cctxParams->compressionLevel;
+ DEBUGLOG(5, "ZSTDMT_updateCParams_whileCompressing (level:%i)",
+ compressionLevel);
+ mtctx->params.compressionLevel = compressionLevel;
+ { ZSTD_compressionParameters cParams = ZSTD_getCParamsFromCCtxParams(cctxParams, 0, 0);
+ cParams.windowLog = saved_wlog;
+ mtctx->params.cParams = cParams;
+ }
+}
+
+/* ZSTDMT_getNbWorkers():
+ * @return nb threads currently active in mtctx.
+ * mtctx must be valid */
+unsigned ZSTDMT_getNbWorkers(const ZSTDMT_CCtx* mtctx)
+{
+ assert(mtctx != NULL);
+ return mtctx->params.nbWorkers;
+}
+
+/* ZSTDMT_getFrameProgression():
+ * tells how much data has been consumed (input) and produced (output) for current frame.
+ * able to count progression inside worker threads.
+ * Note : mutex will be acquired during statistics collection. */
+ZSTD_frameProgression ZSTDMT_getFrameProgression(ZSTDMT_CCtx* mtctx)
+{
+ ZSTD_frameProgression fps;
+ DEBUGLOG(6, "ZSTDMT_getFrameProgression");
+ fps.consumed = mtctx->consumed;
+ fps.produced = mtctx->produced;
+ fps.ingested = mtctx->consumed + mtctx->inBuff.filled;
+ { unsigned jobNb;
+ unsigned lastJobNb = mtctx->nextJobID + mtctx->jobReady; assert(mtctx->jobReady <= 1);
+ DEBUGLOG(6, "ZSTDMT_getFrameProgression: jobs: from %u to <%u (jobReady:%u)",
+ mtctx->doneJobID, lastJobNb, mtctx->jobReady)
+ for (jobNb = mtctx->doneJobID ; jobNb < lastJobNb ; jobNb++) {
+ unsigned const wJobID = jobNb & mtctx->jobIDMask;
+ ZSTD_pthread_mutex_lock(&mtctx->jobs[wJobID].job_mutex);
+ { size_t const cResult = mtctx->jobs[wJobID].cSize;
+ size_t const produced = ZSTD_isError(cResult) ? 0 : cResult;
+ fps.consumed += mtctx->jobs[wJobID].consumed;
+ fps.ingested += mtctx->jobs[wJobID].src.size;
+ fps.produced += produced;
+ }
+ ZSTD_pthread_mutex_unlock(&mtctx->jobs[wJobID].job_mutex);
+ }
+ }
+ return fps;
+}
+
+
/* ------------------------------------------ */
/* ===== Multi-threaded compression ===== */
/* ------------------------------------------ */
-static unsigned computeNbChunks(size_t srcSize, unsigned windowLog, unsigned nbThreads) {
- size_t const chunkSizeTarget = (size_t)1 << (windowLog + 2);
- size_t const chunkMaxSize = chunkSizeTarget << 2;
- size_t const passSizeMax = chunkMaxSize * nbThreads;
- unsigned const multiplier = (unsigned)(srcSize / passSizeMax) + 1;
- unsigned const nbChunksLarge = multiplier * nbThreads;
- unsigned const nbChunksMax = (unsigned)(srcSize / chunkSizeTarget) + 1;
- unsigned const nbChunksSmall = MIN(nbChunksMax, nbThreads);
- return (multiplier>1) ? nbChunksLarge : nbChunksSmall;
+static size_t ZSTDMT_computeTargetJobLog(ZSTD_CCtx_params const params)
+{
+ if (params.ldmParams.enableLdm)
+ return MAX(21, params.cParams.chainLog + 4);
+ return MAX(20, params.cParams.windowLog + 2);
+}
+
+static size_t ZSTDMT_computeOverlapLog(ZSTD_CCtx_params const params)
+{
+ unsigned const overlapRLog = (params.overlapSizeLog>9) ? 0 : 9-params.overlapSizeLog;
+ if (params.ldmParams.enableLdm)
+ return (MIN(params.cParams.windowLog, ZSTDMT_computeTargetJobLog(params) - 2) - overlapRLog);
+ return overlapRLog >= 9 ? 0 : (params.cParams.windowLog - overlapRLog);
}
+static unsigned ZSTDMT_computeNbJobs(ZSTD_CCtx_params params, size_t srcSize, unsigned nbWorkers) {
+ assert(nbWorkers>0);
+ { size_t const jobSizeTarget = (size_t)1 << ZSTDMT_computeTargetJobLog(params);
+ size_t const jobMaxSize = jobSizeTarget << 2;
+ size_t const passSizeMax = jobMaxSize * nbWorkers;
+ unsigned const multiplier = (unsigned)(srcSize / passSizeMax) + 1;
+ unsigned const nbJobsLarge = multiplier * nbWorkers;
+ unsigned const nbJobsMax = (unsigned)(srcSize / jobSizeTarget) + 1;
+ unsigned const nbJobsSmall = MIN(nbJobsMax, nbWorkers);
+ return (multiplier>1) ? nbJobsLarge : nbJobsSmall;
+} }
+
+/* ZSTDMT_compress_advanced_internal() :
+ * This is a blocking function : it will only give back control to caller after finishing its compression job.
+ */
static size_t ZSTDMT_compress_advanced_internal(
ZSTDMT_CCtx* mtctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const ZSTD_CDict* cdict,
- ZSTD_CCtx_params const params)
+ ZSTD_CCtx_params params)
{
- ZSTD_CCtx_params const jobParams = ZSTDMT_makeJobCCtxParams(params);
- unsigned const overlapRLog = (params.overlapSizeLog>9) ? 0 : 9-params.overlapSizeLog;
- size_t const overlapSize = (overlapRLog>=9) ? 0 : (size_t)1 << (params.cParams.windowLog - overlapRLog);
- unsigned nbChunks = computeNbChunks(srcSize, params.cParams.windowLog, params.nbThreads);
- size_t const proposedChunkSize = (srcSize + (nbChunks-1)) / nbChunks;
- size_t const avgChunkSize = (((proposedChunkSize-1) & 0x1FFFF) < 0x7FFF) ? proposedChunkSize + 0xFFFF : proposedChunkSize; /* avoid too small last block */
+ ZSTD_CCtx_params const jobParams = ZSTDMT_initJobCCtxParams(params);
+ size_t const overlapSize = (size_t)1 << ZSTDMT_computeOverlapLog(params);
+ unsigned const nbJobs = ZSTDMT_computeNbJobs(params, srcSize, params.nbWorkers);
+ size_t const proposedJobSize = (srcSize + (nbJobs-1)) / nbJobs;
+ size_t const avgJobSize = (((proposedJobSize-1) & 0x1FFFF) < 0x7FFF) ? proposedJobSize + 0xFFFF : proposedJobSize; /* avoid too small last block */
const char* const srcStart = (const char*)src;
size_t remainingSrcSize = srcSize;
- unsigned const compressWithinDst = (dstCapacity >= ZSTD_compressBound(srcSize)) ? nbChunks : (unsigned)(dstCapacity / ZSTD_compressBound(avgChunkSize)); /* presumes avgChunkSize >= 256 KB, which should be the case */
+ unsigned const compressWithinDst = (dstCapacity >= ZSTD_compressBound(srcSize)) ? nbJobs : (unsigned)(dstCapacity / ZSTD_compressBound(avgJobSize)); /* presumes avgJobSize >= 256 KB, which should be the case */
size_t frameStartPos = 0, dstBufferPos = 0;
- XXH64_state_t xxh64;
- assert(jobParams.nbThreads == 0);
- assert(mtctx->cctxPool->totalCCtx == params.nbThreads);
+ assert(jobParams.nbWorkers == 0);
+ assert(mtctx->cctxPool->totalCCtx == params.nbWorkers);
- DEBUGLOG(4, "ZSTDMT_compress_advanced_internal: nbChunks=%2u (rawSize=%u bytes; fixedSize=%u) ",
- nbChunks, (U32)proposedChunkSize, (U32)avgChunkSize);
- if (nbChunks==1) { /* fallback to single-thread mode */
+ params.jobSize = (U32)avgJobSize;
+ DEBUGLOG(4, "ZSTDMT_compress_advanced_internal: nbJobs=%2u (rawSize=%u bytes; fixedSize=%u) ",
+ nbJobs, (U32)proposedJobSize, (U32)avgJobSize);
+
+ if ((nbJobs==1) | (params.nbWorkers<=1)) { /* fallback to single-thread mode : this is a blocking invocation anyway */
ZSTD_CCtx* const cctx = mtctx->cctxPool->cctx[0];
+ DEBUGLOG(4, "ZSTDMT_compress_advanced_internal: fallback to single-thread mode");
if (cdict) return ZSTD_compress_usingCDict_advanced(cctx, dst, dstCapacity, src, srcSize, cdict, jobParams.fParams);
return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, NULL, 0, jobParams);
}
- assert(avgChunkSize >= 256 KB); /* condition for ZSTD_compressBound(A) + ZSTD_compressBound(B) <= ZSTD_compressBound(A+B), which is required for compressWithinDst */
- ZSTDMT_setBufferSize(mtctx->bufPool, ZSTD_compressBound(avgChunkSize) );
- XXH64_reset(&xxh64, 0);
- if (nbChunks > mtctx->jobIDMask+1) { /* enlarge job table */
- U32 nbJobs = nbChunks;
- ZSTD_free(mtctx->jobs, mtctx->cMem);
+ assert(avgJobSize >= 256 KB); /* condition for ZSTD_compressBound(A) + ZSTD_compressBound(B) <= ZSTD_compressBound(A+B), required to compress directly into Dst (no additional buffer) */
+ ZSTDMT_setBufferSize(mtctx->bufPool, ZSTD_compressBound(avgJobSize) );
+ if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params))
+ return ERROR(memory_allocation);
+
+ if (nbJobs > mtctx->jobIDMask+1) { /* enlarge job table */
+ U32 jobsTableSize = nbJobs;
+ ZSTDMT_freeJobsTable(mtctx->jobs, mtctx->jobIDMask+1, mtctx->cMem);
mtctx->jobIDMask = 0;
- mtctx->jobs = ZSTDMT_allocJobsTable(&nbJobs, mtctx->cMem);
+ mtctx->jobs = ZSTDMT_createJobsTable(&jobsTableSize, mtctx->cMem);
if (mtctx->jobs==NULL) return ERROR(memory_allocation);
- mtctx->jobIDMask = nbJobs - 1;
+ assert((jobsTableSize != 0) && ((jobsTableSize & (jobsTableSize - 1)) == 0)); /* ensure jobsTableSize is a power of 2 */
+ mtctx->jobIDMask = jobsTableSize - 1;
}
{ unsigned u;
- for (u=0; u<nbChunks; u++) {
- size_t const chunkSize = MIN(remainingSrcSize, avgChunkSize);
- size_t const dstBufferCapacity = ZSTD_compressBound(chunkSize);
+ for (u=0; u<nbJobs; u++) {
+ size_t const jobSize = MIN(remainingSrcSize, avgJobSize);
+ size_t const dstBufferCapacity = ZSTD_compressBound(jobSize);
buffer_t const dstAsBuffer = { (char*)dst + dstBufferPos, dstBufferCapacity };
buffer_t const dstBuffer = u < compressWithinDst ? dstAsBuffer : g_nullBuffer;
size_t dictSize = u ? overlapSize : 0;
- mtctx->jobs[u].src = g_nullBuffer;
- mtctx->jobs[u].srcStart = srcStart + frameStartPos - dictSize;
- mtctx->jobs[u].prefixSize = dictSize;
- mtctx->jobs[u].srcSize = chunkSize;
+ mtctx->jobs[u].prefix.start = srcStart + frameStartPos - dictSize;
+ mtctx->jobs[u].prefix.size = dictSize;
+ mtctx->jobs[u].src.start = srcStart + frameStartPos;
+ mtctx->jobs[u].src.size = jobSize; assert(jobSize > 0); /* avoid job.src.size == 0 */
+ mtctx->jobs[u].consumed = 0;
+ mtctx->jobs[u].cSize = 0;
mtctx->jobs[u].cdict = (u==0) ? cdict : NULL;
mtctx->jobs[u].fullFrameSize = srcSize;
mtctx->jobs[u].params = jobParams;
/* do not calculate checksum within sections, but write it in header for first section */
- if (u!=0) mtctx->jobs[u].params.fParams.checksumFlag = 0;
mtctx->jobs[u].dstBuff = dstBuffer;
mtctx->jobs[u].cctxPool = mtctx->cctxPool;
mtctx->jobs[u].bufPool = mtctx->bufPool;
- mtctx->jobs[u].firstChunk = (u==0);
- mtctx->jobs[u].lastChunk = (u==nbChunks-1);
- mtctx->jobs[u].jobCompleted = 0;
- mtctx->jobs[u].jobCompleted_mutex = &mtctx->jobCompleted_mutex;
- mtctx->jobs[u].jobCompleted_cond = &mtctx->jobCompleted_cond;
-
- if (params.fParams.checksumFlag) {
- XXH64_update(&xxh64, srcStart + frameStartPos, chunkSize);
- }
+ mtctx->jobs[u].seqPool = mtctx->seqPool;
+ mtctx->jobs[u].serial = &mtctx->serial;
+ mtctx->jobs[u].jobID = u;
+ mtctx->jobs[u].firstJob = (u==0);
+ mtctx->jobs[u].lastJob = (u==nbJobs-1);
- DEBUGLOG(5, "ZSTDMT_compress_advanced_internal: posting job %u (%u bytes)", u, (U32)chunkSize);
- DEBUG_PRINTHEX(6, mtctx->jobs[u].srcStart, 12);
- POOL_add(mtctx->factory, ZSTDMT_compressChunk, &mtctx->jobs[u]);
+ DEBUGLOG(5, "ZSTDMT_compress_advanced_internal: posting job %u (%u bytes)", u, (U32)jobSize);
+ DEBUG_PRINTHEX(6, mtctx->jobs[u].prefix.start, 12);
+ POOL_add(mtctx->factory, ZSTDMT_compressionJob, &mtctx->jobs[u]);
- frameStartPos += chunkSize;
+ frameStartPos += jobSize;
dstBufferPos += dstBufferCapacity;
- remainingSrcSize -= chunkSize;
+ remainingSrcSize -= jobSize;
} }
/* collect result */
{ size_t error = 0, dstPos = 0;
- unsigned chunkID;
- for (chunkID=0; chunkID<nbChunks; chunkID++) {
- DEBUGLOG(5, "waiting for chunk %u ", chunkID);
- ZSTD_PTHREAD_MUTEX_LOCK(&mtctx->jobCompleted_mutex);
- while (mtctx->jobs[chunkID].jobCompleted==0) {
- DEBUGLOG(5, "waiting for jobCompleted signal from chunk %u", chunkID);
- ZSTD_pthread_cond_wait(&mtctx->jobCompleted_cond, &mtctx->jobCompleted_mutex);
+ unsigned jobID;
+ for (jobID=0; jobID<nbJobs; jobID++) {
+ DEBUGLOG(5, "waiting for job %u ", jobID);
+ ZSTD_PTHREAD_MUTEX_LOCK(&mtctx->jobs[jobID].job_mutex);
+ while (mtctx->jobs[jobID].consumed < mtctx->jobs[jobID].src.size) {
+ DEBUGLOG(5, "waiting for jobCompleted signal from job %u", jobID);
+ ZSTD_pthread_cond_wait(&mtctx->jobs[jobID].job_cond, &mtctx->jobs[jobID].job_mutex);
}
- ZSTD_pthread_mutex_unlock(&mtctx->jobCompleted_mutex);
- DEBUGLOG(5, "ready to write chunk %u ", chunkID);
+ ZSTD_pthread_mutex_unlock(&mtctx->jobs[jobID].job_mutex);
+ DEBUGLOG(5, "ready to write job %u ", jobID);
- mtctx->jobs[chunkID].srcStart = NULL;
- { size_t const cSize = mtctx->jobs[chunkID].cSize;
+ { size_t const cSize = mtctx->jobs[jobID].cSize;
if (ZSTD_isError(cSize)) error = cSize;
if ((!error) && (dstPos + cSize > dstCapacity)) error = ERROR(dstSize_tooSmall);
- if (chunkID) { /* note : chunk 0 is written directly at dst, which is correct position */
+ if (jobID) { /* note : job 0 is written directly at dst, which is correct position */
if (!error)
- memmove((char*)dst + dstPos, mtctx->jobs[chunkID].dstBuff.start, cSize); /* may overlap when chunk compressed within dst */
- if (chunkID >= compressWithinDst) { /* chunk compressed into its own buffer, which must be released */
- DEBUGLOG(5, "releasing buffer %u>=%u", chunkID, compressWithinDst);
- ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[chunkID].dstBuff);
+ memmove((char*)dst + dstPos, mtctx->jobs[jobID].dstBuff.start, cSize); /* may overlap when job compressed within dst */
+ if (jobID >= compressWithinDst) { /* job compressed into its own buffer, which must be released */
+ DEBUGLOG(5, "releasing buffer %u>=%u", jobID, compressWithinDst);
+ ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[jobID].dstBuff);
} }
- mtctx->jobs[chunkID].dstBuff = g_nullBuffer;
+ mtctx->jobs[jobID].dstBuff = g_nullBuffer;
+ mtctx->jobs[jobID].cSize = 0;
dstPos += cSize ;
}
- } /* for (chunkID=0; chunkID<nbChunks; chunkID++) */
+ } /* for (jobID=0; jobID<nbJobs; jobID++) */
DEBUGLOG(4, "checksumFlag : %u ", params.fParams.checksumFlag);
if (params.fParams.checksumFlag) {
- U32 const checksum = (U32)XXH64_digest(&xxh64);
+ U32 const checksum = (U32)XXH64_digest(&mtctx->serial.xxhState);
if (dstPos + 4 > dstCapacity) {
error = ERROR(dstSize_tooSmall);
} else {
@@ -756,7 +1185,7 @@ size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const ZSTD_CDict* cdict,
- ZSTD_parameters const params,
+ ZSTD_parameters params,
unsigned overlapLog)
{
ZSTD_CCtx_params cctxParams = mtctx->params;
@@ -787,66 +1216,104 @@ size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
/* ====================================== */
size_t ZSTDMT_initCStream_internal(
- ZSTDMT_CCtx* zcs,
- const void* dict, size_t dictSize, ZSTD_dictMode_e dictMode,
+ ZSTDMT_CCtx* mtctx,
+ const void* dict, size_t dictSize, ZSTD_dictContentType_e dictContentType,
const ZSTD_CDict* cdict, ZSTD_CCtx_params params,
unsigned long long pledgedSrcSize)
{
- DEBUGLOG(4, "ZSTDMT_initCStream_internal (pledgedSrcSize=%u)", (U32)pledgedSrcSize);
+ DEBUGLOG(4, "ZSTDMT_initCStream_internal (pledgedSrcSize=%u, nbWorkers=%u, cctxPool=%u, disableLiteralCompression=%i)",
+ (U32)pledgedSrcSize, params.nbWorkers, mtctx->cctxPool->totalCCtx, params.disableLiteralCompression);
/* params are supposed to be fully validated at this point */
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
assert(!((dict) && (cdict))); /* either dict or cdict, not both */
- assert(zcs->cctxPool->totalCCtx == params.nbThreads);
- zcs->singleThreaded = (params.nbThreads==1) | (pledgedSrcSize <= ZSTDMT_JOBSIZE_MIN); /* do not trigger multi-threading when srcSize is too small */
-
- if (zcs->singleThreaded) {
- ZSTD_CCtx_params const singleThreadParams = ZSTDMT_makeJobCCtxParams(params);
- DEBUGLOG(4, "single thread mode");
- assert(singleThreadParams.nbThreads == 0);
- return ZSTD_initCStream_internal(zcs->cctxPool->cctx[0],
+ assert(mtctx->cctxPool->totalCCtx == params.nbWorkers);
+
+ /* init */
+ if (params.jobSize == 0) {
+ params.jobSize = 1U << ZSTDMT_computeTargetJobLog(params);
+ }
+ if (params.jobSize > ZSTDMT_JOBSIZE_MAX) params.jobSize = ZSTDMT_JOBSIZE_MAX;
+
+ mtctx->singleBlockingThread = (pledgedSrcSize <= ZSTDMT_JOBSIZE_MIN); /* do not trigger multi-threading when srcSize is too small */
+ if (mtctx->singleBlockingThread) {
+ ZSTD_CCtx_params const singleThreadParams = ZSTDMT_initJobCCtxParams(params);
+ DEBUGLOG(5, "ZSTDMT_initCStream_internal: switch to single blocking thread mode");
+ assert(singleThreadParams.nbWorkers == 0);
+ return ZSTD_initCStream_internal(mtctx->cctxPool->cctx[0],
dict, dictSize, cdict,
singleThreadParams, pledgedSrcSize);
}
- DEBUGLOG(4, "multi-threading mode (%u threads)", params.nbThreads);
- if (zcs->allJobsCompleted == 0) { /* previous compression not correctly finished */
- ZSTDMT_waitForAllJobsCompleted(zcs);
- ZSTDMT_releaseAllJobResources(zcs);
- zcs->allJobsCompleted = 1;
+ DEBUGLOG(4, "ZSTDMT_initCStream_internal: %u workers", params.nbWorkers);
+
+ if (mtctx->allJobsCompleted == 0) { /* previous compression not correctly finished */
+ ZSTDMT_waitForAllJobsCompleted(mtctx);
+ ZSTDMT_releaseAllJobResources(mtctx);
+ mtctx->allJobsCompleted = 1;
}
- zcs->params = params;
- zcs->frameContentSize = pledgedSrcSize;
+ mtctx->params = params;
+ mtctx->frameContentSize = pledgedSrcSize;
if (dict) {
- ZSTD_freeCDict(zcs->cdictLocal);
- zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize,
- ZSTD_dlm_byCopy, dictMode, /* note : a loadPrefix becomes an internal CDict */
- params.cParams, zcs->cMem);
- zcs->cdict = zcs->cdictLocal;
- if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
+ ZSTD_freeCDict(mtctx->cdictLocal);
+ mtctx->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize,
+ ZSTD_dlm_byCopy, dictContentType, /* note : a loadPrefix becomes an internal CDict */
+ params.cParams, mtctx->cMem);
+ mtctx->cdict = mtctx->cdictLocal;
+ if (mtctx->cdictLocal == NULL) return ERROR(memory_allocation);
} else {
- ZSTD_freeCDict(zcs->cdictLocal);
- zcs->cdictLocal = NULL;
- zcs->cdict = cdict;
+ ZSTD_freeCDict(mtctx->cdictLocal);
+ mtctx->cdictLocal = NULL;
+ mtctx->cdict = cdict;
}
- assert(params.overlapSizeLog <= 9);
- zcs->targetDictSize = (params.overlapSizeLog==0) ? 0 : (size_t)1 << (params.cParams.windowLog - (9 - params.overlapSizeLog));
- DEBUGLOG(4, "overlapLog=%u => %u KB", params.overlapSizeLog, (U32)(zcs->targetDictSize>>10));
- zcs->targetSectionSize = params.jobSize ? params.jobSize : (size_t)1 << (params.cParams.windowLog + 2);
- if (zcs->targetSectionSize < ZSTDMT_JOBSIZE_MIN) zcs->targetSectionSize = ZSTDMT_JOBSIZE_MIN;
- if (zcs->targetSectionSize < zcs->targetDictSize) zcs->targetSectionSize = zcs->targetDictSize; /* job size must be >= overlap size */
- DEBUGLOG(4, "Job Size : %u KB (note : set to %u)", (U32)(zcs->targetSectionSize>>10), params.jobSize);
- zcs->inBuffSize = zcs->targetDictSize + zcs->targetSectionSize;
- DEBUGLOG(4, "inBuff Size : %u KB", (U32)(zcs->inBuffSize>>10));
- ZSTDMT_setBufferSize(zcs->bufPool, MAX(zcs->inBuffSize, ZSTD_compressBound(zcs->targetSectionSize)) );
- zcs->inBuff.buffer = g_nullBuffer;
- zcs->dictSize = 0;
- zcs->doneJobID = 0;
- zcs->nextJobID = 0;
- zcs->frameEnded = 0;
- zcs->allJobsCompleted = 0;
- if (params.fParams.checksumFlag) XXH64_reset(&zcs->xxhState, 0);
+ mtctx->targetPrefixSize = (size_t)1 << ZSTDMT_computeOverlapLog(params);
+ DEBUGLOG(4, "overlapLog=%u => %u KB", params.overlapSizeLog, (U32)(mtctx->targetPrefixSize>>10));
+ mtctx->targetSectionSize = params.jobSize;
+ if (mtctx->targetSectionSize < ZSTDMT_JOBSIZE_MIN) mtctx->targetSectionSize = ZSTDMT_JOBSIZE_MIN;
+ if (mtctx->targetSectionSize < mtctx->targetPrefixSize) mtctx->targetSectionSize = mtctx->targetPrefixSize; /* job size must be >= overlap size */
+ DEBUGLOG(4, "Job Size : %u KB (note : set to %u)", (U32)(mtctx->targetSectionSize>>10), params.jobSize);
+ DEBUGLOG(4, "inBuff Size : %u KB", (U32)(mtctx->targetSectionSize>>10));
+ ZSTDMT_setBufferSize(mtctx->bufPool, ZSTD_compressBound(mtctx->targetSectionSize));
+ {
+ /* If ldm is enabled we need windowSize space. */
+ size_t const windowSize = mtctx->params.ldmParams.enableLdm ? (1U << mtctx->params.cParams.windowLog) : 0;
+ /* Two buffers of slack, plus extra space for the overlap
+ * This is the minimum slack that LDM works with. One extra because
+ * flush might waste up to targetSectionSize-1 bytes. Another extra
+ * for the overlap (if > 0), then one to fill which doesn't overlap
+ * with the LDM window.
+ */
+ size_t const nbSlackBuffers = 2 + (mtctx->targetPrefixSize > 0);
+ size_t const slackSize = mtctx->targetSectionSize * nbSlackBuffers;
+ /* Compute the total size, and always have enough slack */
+ size_t const nbWorkers = MAX(mtctx->params.nbWorkers, 1);
+ size_t const sectionsSize = mtctx->targetSectionSize * nbWorkers;
+ size_t const capacity = MAX(windowSize, sectionsSize) + slackSize;
+ if (mtctx->roundBuff.capacity < capacity) {
+ if (mtctx->roundBuff.buffer)
+ ZSTD_free(mtctx->roundBuff.buffer, mtctx->cMem);
+ mtctx->roundBuff.buffer = (BYTE*)ZSTD_malloc(capacity, mtctx->cMem);
+ if (mtctx->roundBuff.buffer == NULL) {
+ mtctx->roundBuff.capacity = 0;
+ return ERROR(memory_allocation);
+ }
+ mtctx->roundBuff.capacity = capacity;
+ }
+ }
+ DEBUGLOG(4, "roundBuff capacity : %u KB", (U32)(mtctx->roundBuff.capacity>>10));
+ mtctx->roundBuff.pos = 0;
+ mtctx->inBuff.buffer = g_nullBuffer;
+ mtctx->inBuff.filled = 0;
+ mtctx->inBuff.prefix = kNullRange;
+ mtctx->doneJobID = 0;
+ mtctx->nextJobID = 0;
+ mtctx->frameEnded = 0;
+ mtctx->allJobsCompleted = 0;
+ mtctx->consumed = 0;
+ mtctx->produced = 0;
+ if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params))
+ return ERROR(memory_allocation);
return 0;
}
@@ -855,11 +1322,11 @@ size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* mtctx,
ZSTD_parameters params,
unsigned long long pledgedSrcSize)
{
- ZSTD_CCtx_params cctxParams = mtctx->params;
- DEBUGLOG(5, "ZSTDMT_initCStream_advanced (pledgedSrcSize=%u)", (U32)pledgedSrcSize);
+ ZSTD_CCtx_params cctxParams = mtctx->params; /* retrieve sticky params */
+ DEBUGLOG(4, "ZSTDMT_initCStream_advanced (pledgedSrcSize=%u)", (U32)pledgedSrcSize);
cctxParams.cParams = params.cParams;
cctxParams.fParams = params.fParams;
- return ZSTDMT_initCStream_internal(mtctx, dict, dictSize, ZSTD_dm_auto, NULL,
+ return ZSTDMT_initCStream_internal(mtctx, dict, dictSize, ZSTD_dct_auto, NULL,
cctxParams, pledgedSrcSize);
}
@@ -869,10 +1336,10 @@ size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
unsigned long long pledgedSrcSize)
{
ZSTD_CCtx_params cctxParams = mtctx->params;
+ if (cdict==NULL) return ERROR(dictionary_wrong); /* method incompatible with NULL cdict */
cctxParams.cParams = ZSTD_getCParamsFromCDict(cdict);
cctxParams.fParams = fParams;
- if (cdict==NULL) return ERROR(dictionary_wrong); /* method incompatible with NULL cdict */
- return ZSTDMT_initCStream_internal(mtctx, NULL, 0 /*dictSize*/, ZSTD_dm_auto, cdict,
+ return ZSTDMT_initCStream_internal(mtctx, NULL, 0 /*dictSize*/, ZSTD_dct_auto, cdict,
cctxParams, pledgedSrcSize);
}
@@ -881,148 +1348,358 @@ size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
* pledgedSrcSize can be zero == unknown (for the time being)
* prefer using ZSTD_CONTENTSIZE_UNKNOWN,
* as `0` might mean "empty" in the future */
-size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* zcs, unsigned long long pledgedSrcSize)
+size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* mtctx, unsigned long long pledgedSrcSize)
{
if (!pledgedSrcSize) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN;
- if (zcs->params.nbThreads==1)
- return ZSTD_resetCStream(zcs->cctxPool->cctx[0], pledgedSrcSize);
- return ZSTDMT_initCStream_internal(zcs, NULL, 0, ZSTD_dm_auto, 0, zcs->params,
+ return ZSTDMT_initCStream_internal(mtctx, NULL, 0, ZSTD_dct_auto, 0, mtctx->params,
pledgedSrcSize);
}
-size_t ZSTDMT_initCStream(ZSTDMT_CCtx* zcs, int compressionLevel) {
- ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, 0);
- ZSTD_CCtx_params cctxParams = zcs->params;
+size_t ZSTDMT_initCStream(ZSTDMT_CCtx* mtctx, int compressionLevel) {
+ ZSTD_parameters const params = ZSTD_getParams(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0);
+ ZSTD_CCtx_params cctxParams = mtctx->params; /* retrieve sticky params */
+ DEBUGLOG(4, "ZSTDMT_initCStream (cLevel=%i)", compressionLevel);
cctxParams.cParams = params.cParams;
cctxParams.fParams = params.fParams;
- return ZSTDMT_initCStream_internal(zcs, NULL, 0, ZSTD_dm_auto, NULL, cctxParams, ZSTD_CONTENTSIZE_UNKNOWN);
-}
-
-
-static size_t ZSTDMT_createCompressionJob(ZSTDMT_CCtx* zcs, size_t srcSize, unsigned endFrame)
-{
- unsigned const jobID = zcs->nextJobID & zcs->jobIDMask;
-
- DEBUGLOG(5, "ZSTDMT_createCompressionJob: preparing job %u to compress %u bytes with %u preload ",
- zcs->nextJobID, (U32)srcSize, (U32)zcs->dictSize);
- zcs->jobs[jobID].src = zcs->inBuff.buffer;
- zcs->jobs[jobID].srcStart = zcs->inBuff.buffer.start;
- zcs->jobs[jobID].srcSize = srcSize;
- zcs->jobs[jobID].prefixSize = zcs->dictSize;
- assert(zcs->inBuff.filled >= srcSize + zcs->dictSize);
- zcs->jobs[jobID].params = zcs->params;
- /* do not calculate checksum within sections, but write it in header for first section */
- if (zcs->nextJobID) zcs->jobs[jobID].params.fParams.checksumFlag = 0;
- zcs->jobs[jobID].cdict = zcs->nextJobID==0 ? zcs->cdict : NULL;
- zcs->jobs[jobID].fullFrameSize = zcs->frameContentSize;
- zcs->jobs[jobID].dstBuff = g_nullBuffer;
- zcs->jobs[jobID].cctxPool = zcs->cctxPool;
- zcs->jobs[jobID].bufPool = zcs->bufPool;
- zcs->jobs[jobID].firstChunk = (zcs->nextJobID==0);
- zcs->jobs[jobID].lastChunk = endFrame;
- zcs->jobs[jobID].jobCompleted = 0;
- zcs->jobs[jobID].dstFlushed = 0;
- zcs->jobs[jobID].jobCompleted_mutex = &zcs->jobCompleted_mutex;
- zcs->jobs[jobID].jobCompleted_cond = &zcs->jobCompleted_cond;
-
- if (zcs->params.fParams.checksumFlag)
- XXH64_update(&zcs->xxhState, (const char*)zcs->inBuff.buffer.start + zcs->dictSize, srcSize);
-
- /* get a new buffer for next input */
- if (!endFrame) {
- size_t const newDictSize = MIN(srcSize + zcs->dictSize, zcs->targetDictSize);
- zcs->inBuff.buffer = ZSTDMT_getBuffer(zcs->bufPool);
- if (zcs->inBuff.buffer.start == NULL) { /* not enough memory to allocate next input buffer */
- zcs->jobs[jobID].jobCompleted = 1;
- zcs->nextJobID++;
- ZSTDMT_waitForAllJobsCompleted(zcs);
- ZSTDMT_releaseAllJobResources(zcs);
- return ERROR(memory_allocation);
+ return ZSTDMT_initCStream_internal(mtctx, NULL, 0, ZSTD_dct_auto, NULL, cctxParams, ZSTD_CONTENTSIZE_UNKNOWN);
+}
+
+
+/* ZSTDMT_writeLastEmptyBlock()
+ * Write a single empty block with an end-of-frame to finish a frame.
+ * Job must be created from streaming variant.
+ * This function is always successfull if expected conditions are fulfilled.
+ */
+static void ZSTDMT_writeLastEmptyBlock(ZSTDMT_jobDescription* job)
+{
+ assert(job->lastJob == 1);
+ assert(job->src.size == 0); /* last job is empty -> will be simplified into a last empty block */
+ assert(job->firstJob == 0); /* cannot be first job, as it also needs to create frame header */
+ assert(job->dstBuff.start == NULL); /* invoked from streaming variant only (otherwise, dstBuff might be user's output) */
+ job->dstBuff = ZSTDMT_getBuffer(job->bufPool);
+ if (job->dstBuff.start == NULL) {
+ job->cSize = ERROR(memory_allocation);
+ return;
+ }
+ assert(job->dstBuff.capacity >= ZSTD_blockHeaderSize); /* no buffer should ever be that small */
+ job->src = kNullRange;
+ job->cSize = ZSTD_writeLastEmptyBlock(job->dstBuff.start, job->dstBuff.capacity);
+ assert(!ZSTD_isError(job->cSize));
+ assert(job->consumed == 0);
+}
+
+static size_t ZSTDMT_createCompressionJob(ZSTDMT_CCtx* mtctx, size_t srcSize, ZSTD_EndDirective endOp)
+{
+ unsigned const jobID = mtctx->nextJobID & mtctx->jobIDMask;
+ int const endFrame = (endOp == ZSTD_e_end);
+
+ if (mtctx->nextJobID > mtctx->doneJobID + mtctx->jobIDMask) {
+ DEBUGLOG(5, "ZSTDMT_createCompressionJob: will not create new job : table is full");
+ assert((mtctx->nextJobID & mtctx->jobIDMask) == (mtctx->doneJobID & mtctx->jobIDMask));
+ return 0;
+ }
+
+ if (!mtctx->jobReady) {
+ BYTE const* src = (BYTE const*)mtctx->inBuff.buffer.start;
+ DEBUGLOG(5, "ZSTDMT_createCompressionJob: preparing job %u to compress %u bytes with %u preload ",
+ mtctx->nextJobID, (U32)srcSize, (U32)mtctx->inBuff.prefix.size);
+ mtctx->jobs[jobID].src.start = src;
+ mtctx->jobs[jobID].src.size = srcSize;
+ assert(mtctx->inBuff.filled >= srcSize);
+ mtctx->jobs[jobID].prefix = mtctx->inBuff.prefix;
+ mtctx->jobs[jobID].consumed = 0;
+ mtctx->jobs[jobID].cSize = 0;
+ mtctx->jobs[jobID].params = mtctx->params;
+ mtctx->jobs[jobID].cdict = mtctx->nextJobID==0 ? mtctx->cdict : NULL;
+ mtctx->jobs[jobID].fullFrameSize = mtctx->frameContentSize;
+ mtctx->jobs[jobID].dstBuff = g_nullBuffer;
+ mtctx->jobs[jobID].cctxPool = mtctx->cctxPool;
+ mtctx->jobs[jobID].bufPool = mtctx->bufPool;
+ mtctx->jobs[jobID].seqPool = mtctx->seqPool;
+ mtctx->jobs[jobID].serial = &mtctx->serial;
+ mtctx->jobs[jobID].jobID = mtctx->nextJobID;
+ mtctx->jobs[jobID].firstJob = (mtctx->nextJobID==0);
+ mtctx->jobs[jobID].lastJob = endFrame;
+ mtctx->jobs[jobID].frameChecksumNeeded = endFrame && (mtctx->nextJobID>0) && mtctx->params.fParams.checksumFlag;
+ mtctx->jobs[jobID].dstFlushed = 0;
+
+ /* Update the round buffer pos and clear the input buffer to be reset */
+ mtctx->roundBuff.pos += srcSize;
+ mtctx->inBuff.buffer = g_nullBuffer;
+ mtctx->inBuff.filled = 0;
+ /* Set the prefix */
+ if (!endFrame) {
+ size_t const newPrefixSize = MIN(srcSize, mtctx->targetPrefixSize);
+ mtctx->inBuff.prefix.start = src + srcSize - newPrefixSize;
+ mtctx->inBuff.prefix.size = newPrefixSize;
+ } else { /* endFrame==1 => no need for another input buffer */
+ mtctx->inBuff.prefix = kNullRange;
+ mtctx->frameEnded = endFrame;
+ if (mtctx->nextJobID == 0) {
+ /* single job exception : checksum is already calculated directly within worker thread */
+ mtctx->params.fParams.checksumFlag = 0;
+ } }
+
+ if ( (srcSize == 0)
+ && (mtctx->nextJobID>0)/*single job must also write frame header*/ ) {
+ DEBUGLOG(5, "ZSTDMT_createCompressionJob: creating a last empty block to end frame");
+ assert(endOp == ZSTD_e_end); /* only possible case : need to end the frame with an empty last block */
+ ZSTDMT_writeLastEmptyBlock(mtctx->jobs + jobID);
+ mtctx->nextJobID++;
+ return 0;
}
- zcs->inBuff.filled -= srcSize + zcs->dictSize - newDictSize;
- memmove(zcs->inBuff.buffer.start,
- (const char*)zcs->jobs[jobID].srcStart + zcs->dictSize + srcSize - newDictSize,
- zcs->inBuff.filled);
- zcs->dictSize = newDictSize;
- } else { /* if (endFrame==1) */
- zcs->inBuff.buffer = g_nullBuffer;
- zcs->inBuff.filled = 0;
- zcs->dictSize = 0;
- zcs->frameEnded = 1;
- if (zcs->nextJobID == 0) {
- /* single chunk exception : checksum is calculated directly within worker thread */
- zcs->params.fParams.checksumFlag = 0;
- } }
+ }
- DEBUGLOG(5, "ZSTDMT_createCompressionJob: posting job %u : %u bytes (end:%u) (note : doneJob = %u=>%u)",
- zcs->nextJobID,
- (U32)zcs->jobs[jobID].srcSize,
- zcs->jobs[jobID].lastChunk,
- zcs->doneJobID,
- zcs->doneJobID & zcs->jobIDMask);
- POOL_add(zcs->factory, ZSTDMT_compressChunk, &zcs->jobs[jobID]); /* this call is blocking when thread worker pool is exhausted */
- zcs->nextJobID++;
+ DEBUGLOG(5, "ZSTDMT_createCompressionJob: posting job %u : %u bytes (end:%u, jobNb == %u (mod:%u))",
+ mtctx->nextJobID,
+ (U32)mtctx->jobs[jobID].src.size,
+ mtctx->jobs[jobID].lastJob,
+ mtctx->nextJobID,
+ jobID);
+ if (POOL_tryAdd(mtctx->factory, ZSTDMT_compressionJob, &mtctx->jobs[jobID])) {
+ mtctx->nextJobID++;
+ mtctx->jobReady = 0;
+ } else {
+ DEBUGLOG(5, "ZSTDMT_createCompressionJob: no worker available for job %u", mtctx->nextJobID);
+ mtctx->jobReady = 1;
+ }
return 0;
}
-/* ZSTDMT_flushNextJob() :
- * output : will be updated with amount of data flushed .
- * blockToFlush : if >0, the function will block and wait if there is no data available to flush .
- * @return : amount of data remaining within internal buffer, 1 if unknown but > 0, 0 if no more, or an error code */
-static size_t ZSTDMT_flushNextJob(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output, unsigned blockToFlush)
+/*! ZSTDMT_flushProduced() :
+ * `output` : `pos` will be updated with amount of data flushed .
+ * `blockToFlush` : if >0, the function will block and wait if there is no data available to flush .
+ * @return : amount of data remaining within internal buffer, 0 if no more, 1 if unknown but > 0, or an error code */
+static size_t ZSTDMT_flushProduced(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, unsigned blockToFlush, ZSTD_EndDirective end)
{
- unsigned const wJobID = zcs->doneJobID & zcs->jobIDMask;
- DEBUGLOG(5, "ZSTDMT_flushNextJob");
- if (zcs->doneJobID == zcs->nextJobID) return 0; /* all flushed ! */
- ZSTD_PTHREAD_MUTEX_LOCK(&zcs->jobCompleted_mutex);
- while (zcs->jobs[wJobID].jobCompleted==0) {
- DEBUGLOG(5, "waiting for jobCompleted signal from job %u", zcs->doneJobID);
- if (!blockToFlush) { ZSTD_pthread_mutex_unlock(&zcs->jobCompleted_mutex); return 0; } /* nothing ready to be flushed => skip */
- ZSTD_pthread_cond_wait(&zcs->jobCompleted_cond, &zcs->jobCompleted_mutex); /* block when nothing available to flush */
+ unsigned const wJobID = mtctx->doneJobID & mtctx->jobIDMask;
+ DEBUGLOG(5, "ZSTDMT_flushProduced (blocking:%u , job %u <= %u)",
+ blockToFlush, mtctx->doneJobID, mtctx->nextJobID);
+ assert(output->size >= output->pos);
+
+ ZSTD_PTHREAD_MUTEX_LOCK(&mtctx->jobs[wJobID].job_mutex);
+ if ( blockToFlush
+ && (mtctx->doneJobID < mtctx->nextJobID) ) {
+ assert(mtctx->jobs[wJobID].dstFlushed <= mtctx->jobs[wJobID].cSize);
+ while (mtctx->jobs[wJobID].dstFlushed == mtctx->jobs[wJobID].cSize) { /* nothing to flush */
+ if (mtctx->jobs[wJobID].consumed == mtctx->jobs[wJobID].src.size) {
+ DEBUGLOG(5, "job %u is completely consumed (%u == %u) => don't wait for cond, there will be none",
+ mtctx->doneJobID, (U32)mtctx->jobs[wJobID].consumed, (U32)mtctx->jobs[wJobID].src.size);
+ break;
+ }
+ DEBUGLOG(5, "waiting for something to flush from job %u (currently flushed: %u bytes)",
+ mtctx->doneJobID, (U32)mtctx->jobs[wJobID].dstFlushed);
+ ZSTD_pthread_cond_wait(&mtctx->jobs[wJobID].job_cond, &mtctx->jobs[wJobID].job_mutex); /* block when nothing to flush but some to come */
+ } }
+
+ /* try to flush something */
+ { size_t cSize = mtctx->jobs[wJobID].cSize; /* shared */
+ size_t const srcConsumed = mtctx->jobs[wJobID].consumed; /* shared */
+ size_t const srcSize = mtctx->jobs[wJobID].src.size; /* read-only, could be done after mutex lock, but no-declaration-after-statement */
+ ZSTD_pthread_mutex_unlock(&mtctx->jobs[wJobID].job_mutex);
+ if (ZSTD_isError(cSize)) {
+ DEBUGLOG(5, "ZSTDMT_flushProduced: job %u : compression error detected : %s",
+ mtctx->doneJobID, ZSTD_getErrorName(cSize));
+ ZSTDMT_waitForAllJobsCompleted(mtctx);
+ ZSTDMT_releaseAllJobResources(mtctx);
+ return cSize;
+ }
+ /* add frame checksum if necessary (can only happen once) */
+ assert(srcConsumed <= srcSize);
+ if ( (srcConsumed == srcSize) /* job completed -> worker no longer active */
+ && mtctx->jobs[wJobID].frameChecksumNeeded ) {
+ U32 const checksum = (U32)XXH64_digest(&mtctx->serial.xxhState);
+ DEBUGLOG(4, "ZSTDMT_flushProduced: writing checksum : %08X \n", checksum);
+ MEM_writeLE32((char*)mtctx->jobs[wJobID].dstBuff.start + mtctx->jobs[wJobID].cSize, checksum);
+ cSize += 4;
+ mtctx->jobs[wJobID].cSize += 4; /* can write this shared value, as worker is no longer active */
+ mtctx->jobs[wJobID].frameChecksumNeeded = 0;
+ }
+ if (cSize > 0) { /* compression is ongoing or completed */
+ size_t const toFlush = MIN(cSize - mtctx->jobs[wJobID].dstFlushed, output->size - output->pos);
+ DEBUGLOG(5, "ZSTDMT_flushProduced: Flushing %u bytes from job %u (completion:%u/%u, generated:%u)",
+ (U32)toFlush, mtctx->doneJobID, (U32)srcConsumed, (U32)srcSize, (U32)cSize);
+ assert(mtctx->doneJobID < mtctx->nextJobID);
+ assert(cSize >= mtctx->jobs[wJobID].dstFlushed);
+ assert(mtctx->jobs[wJobID].dstBuff.start != NULL);
+ memcpy((char*)output->dst + output->pos,
+ (const char*)mtctx->jobs[wJobID].dstBuff.start + mtctx->jobs[wJobID].dstFlushed,
+ toFlush);
+ output->pos += toFlush;
+ mtctx->jobs[wJobID].dstFlushed += toFlush; /* can write : this value is only used by mtctx */
+
+ if ( (srcConsumed == srcSize) /* job completed */
+ && (mtctx->jobs[wJobID].dstFlushed == cSize) ) { /* output buffer fully flushed => free this job position */
+ DEBUGLOG(5, "Job %u completed (%u bytes), moving to next one",
+ mtctx->doneJobID, (U32)mtctx->jobs[wJobID].dstFlushed);
+ ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[wJobID].dstBuff);
+ mtctx->jobs[wJobID].dstBuff = g_nullBuffer;
+ mtctx->jobs[wJobID].cSize = 0; /* ensure this job slot is considered "not started" in future check */
+ mtctx->consumed += srcSize;
+ mtctx->produced += cSize;
+ mtctx->doneJobID++;
+ } }
+
+ /* return value : how many bytes left in buffer ; fake it to 1 when unknown but >0 */
+ if (cSize > mtctx->jobs[wJobID].dstFlushed) return (cSize - mtctx->jobs[wJobID].dstFlushed);
+ if (srcSize > srcConsumed) return 1; /* current job not completely compressed */
}
- ZSTD_pthread_mutex_unlock(&zcs->jobCompleted_mutex);
- /* compression job completed : output can be flushed */
- { ZSTDMT_jobDescription job = zcs->jobs[wJobID];
- if (!job.jobScanned) {
- if (ZSTD_isError(job.cSize)) {
- DEBUGLOG(5, "job %u : compression error detected : %s",
- zcs->doneJobID, ZSTD_getErrorName(job.cSize));
- ZSTDMT_waitForAllJobsCompleted(zcs);
- ZSTDMT_releaseAllJobResources(zcs);
- return job.cSize;
+ if (mtctx->doneJobID < mtctx->nextJobID) return 1; /* some more jobs ongoing */
+ if (mtctx->jobReady) return 1; /* one job is ready to push, just not yet in the list */
+ if (mtctx->inBuff.filled > 0) return 1; /* input is not empty, and still needs to be converted into a job */
+ mtctx->allJobsCompleted = mtctx->frameEnded; /* all jobs are entirely flushed => if this one is last one, frame is completed */
+ if (end == ZSTD_e_end) return !mtctx->frameEnded; /* for ZSTD_e_end, question becomes : is frame completed ? instead of : are internal buffers fully flushed ? */
+ return 0; /* internal buffers fully flushed */
+}
+
+/**
+ * Returns the range of data used by the earliest job that is not yet complete.
+ * If the data of the first job is broken up into two segments, we cover both
+ * sections.
+ */
+static range_t ZSTDMT_getInputDataInUse(ZSTDMT_CCtx* mtctx)
+{
+ unsigned const firstJobID = mtctx->doneJobID;
+ unsigned const lastJobID = mtctx->nextJobID;
+ unsigned jobID;
+
+ for (jobID = firstJobID; jobID < lastJobID; ++jobID) {
+ unsigned const wJobID = jobID & mtctx->jobIDMask;
+ size_t consumed;
+
+ ZSTD_PTHREAD_MUTEX_LOCK(&mtctx->jobs[wJobID].job_mutex);
+ consumed = mtctx->jobs[wJobID].consumed;
+ ZSTD_pthread_mutex_unlock(&mtctx->jobs[wJobID].job_mutex);
+
+ if (consumed < mtctx->jobs[wJobID].src.size) {
+ range_t range = mtctx->jobs[wJobID].prefix;
+ if (range.size == 0) {
+ /* Empty prefix */
+ range = mtctx->jobs[wJobID].src;
}
- DEBUGLOG(5, "zcs->params.fParams.checksumFlag : %u ", zcs->params.fParams.checksumFlag);
- if (zcs->params.fParams.checksumFlag) {
- if (zcs->frameEnded && (zcs->doneJobID+1 == zcs->nextJobID)) { /* write checksum at end of last section */
- U32 const checksum = (U32)XXH64_digest(&zcs->xxhState);
- DEBUGLOG(5, "writing checksum : %08X \n", checksum);
- MEM_writeLE32((char*)job.dstBuff.start + job.cSize, checksum);
- job.cSize += 4;
- zcs->jobs[wJobID].cSize += 4;
- } }
- zcs->jobs[wJobID].jobScanned = 1;
+ /* Job source in multiple segments not supported yet */
+ assert(range.start <= mtctx->jobs[wJobID].src.start);
+ return range;
}
- { size_t const toWrite = MIN(job.cSize - job.dstFlushed, output->size - output->pos);
- DEBUGLOG(5, "Flushing %u bytes from job %u ", (U32)toWrite, zcs->doneJobID);
- memcpy((char*)output->dst + output->pos, (const char*)job.dstBuff.start + job.dstFlushed, toWrite);
- output->pos += toWrite;
- job.dstFlushed += toWrite;
+ }
+ return kNullRange;
+}
+
+/**
+ * Returns non-zero iff buffer and range overlap.
+ */
+static int ZSTDMT_isOverlapped(buffer_t buffer, range_t range)
+{
+ BYTE const* const bufferStart = (BYTE const*)buffer.start;
+ BYTE const* const bufferEnd = bufferStart + buffer.capacity;
+ BYTE const* const rangeStart = (BYTE const*)range.start;
+ BYTE const* const rangeEnd = rangeStart + range.size;
+
+ if (rangeStart == NULL || bufferStart == NULL)
+ return 0;
+ /* Empty ranges cannot overlap */
+ if (bufferStart == bufferEnd || rangeStart == rangeEnd)
+ return 0;
+
+ return bufferStart < rangeEnd && rangeStart < bufferEnd;
+}
+
+static int ZSTDMT_doesOverlapWindow(buffer_t buffer, ZSTD_window_t window)
+{
+ range_t extDict;
+ range_t prefix;
+
+ extDict.start = window.dictBase + window.lowLimit;
+ extDict.size = window.dictLimit - window.lowLimit;
+
+ prefix.start = window.base + window.dictLimit;
+ prefix.size = window.nextSrc - (window.base + window.dictLimit);
+ DEBUGLOG(5, "extDict [0x%zx, 0x%zx)",
+ (size_t)extDict.start,
+ (size_t)extDict.start + extDict.size);
+ DEBUGLOG(5, "prefix [0x%zx, 0x%zx)",
+ (size_t)prefix.start,
+ (size_t)prefix.start + prefix.size);
+
+ return ZSTDMT_isOverlapped(buffer, extDict)
+ || ZSTDMT_isOverlapped(buffer, prefix);
+}
+
+static void ZSTDMT_waitForLdmComplete(ZSTDMT_CCtx* mtctx, buffer_t buffer)
+{
+ if (mtctx->params.ldmParams.enableLdm) {
+ ZSTD_pthread_mutex_t* mutex = &mtctx->serial.ldmWindowMutex;
+ DEBUGLOG(5, "source [0x%zx, 0x%zx)",
+ (size_t)buffer.start,
+ (size_t)buffer.start + buffer.capacity);
+ ZSTD_PTHREAD_MUTEX_LOCK(mutex);
+ while (ZSTDMT_doesOverlapWindow(buffer, mtctx->serial.ldmWindow)) {
+ DEBUGLOG(6, "Waiting for LDM to finish...");
+ ZSTD_pthread_cond_wait(&mtctx->serial.ldmWindowCond, mutex);
}
- if (job.dstFlushed == job.cSize) { /* output buffer fully flushed => move to next one */
- ZSTDMT_releaseBuffer(zcs->bufPool, job.dstBuff);
- zcs->jobs[wJobID].dstBuff = g_nullBuffer;
- zcs->jobs[wJobID].jobCompleted = 0;
- zcs->doneJobID++;
- } else {
- zcs->jobs[wJobID].dstFlushed = job.dstFlushed;
+ DEBUGLOG(6, "Done waiting for LDM to finish");
+ ZSTD_pthread_mutex_unlock(mutex);
+ }
+}
+
+/**
+ * Attempts to set the inBuff to the next section to fill.
+ * If any part of the new section is still in use we give up.
+ * Returns non-zero if the buffer is filled.
+ */
+static int ZSTDMT_tryGetInputRange(ZSTDMT_CCtx* mtctx)
+{
+ range_t const inUse = ZSTDMT_getInputDataInUse(mtctx);
+ size_t const spaceLeft = mtctx->roundBuff.capacity - mtctx->roundBuff.pos;
+ size_t const target = mtctx->targetSectionSize;
+ buffer_t buffer;
+
+ assert(mtctx->inBuff.buffer.start == NULL);
+ assert(mtctx->roundBuff.capacity >= target);
+
+ if (spaceLeft < target) {
+ /* ZSTD_invalidateRepCodes() doesn't work for extDict variants.
+ * Simply copy the prefix to the beginning in that case.
+ */
+ BYTE* const start = (BYTE*)mtctx->roundBuff.buffer;
+ size_t const prefixSize = mtctx->inBuff.prefix.size;
+
+ buffer.start = start;
+ buffer.capacity = prefixSize;
+ if (ZSTDMT_isOverlapped(buffer, inUse)) {
+ DEBUGLOG(6, "Waiting for buffer...");
+ return 0;
}
- /* return value : how many bytes left in buffer ; fake it to 1 if unknown but >0 */
- if (job.cSize > job.dstFlushed) return (job.cSize - job.dstFlushed);
- if (zcs->doneJobID < zcs->nextJobID) return 1; /* still some buffer to flush */
- zcs->allJobsCompleted = zcs->frameEnded; /* frame completed and entirely flushed */
- return 0; /* everything flushed */
-} }
+ ZSTDMT_waitForLdmComplete(mtctx, buffer);
+ memmove(start, mtctx->inBuff.prefix.start, prefixSize);
+ mtctx->inBuff.prefix.start = start;
+ mtctx->roundBuff.pos = prefixSize;
+ }
+ buffer.start = mtctx->roundBuff.buffer + mtctx->roundBuff.pos;
+ buffer.capacity = target;
+
+ if (ZSTDMT_isOverlapped(buffer, inUse)) {
+ DEBUGLOG(6, "Waiting for buffer...");
+ return 0;
+ }
+ assert(!ZSTDMT_isOverlapped(buffer, mtctx->inBuff.prefix));
+
+ ZSTDMT_waitForLdmComplete(mtctx, buffer);
+
+ DEBUGLOG(5, "Using prefix range [%zx, %zx)",
+ (size_t)mtctx->inBuff.prefix.start,
+ (size_t)mtctx->inBuff.prefix.start + mtctx->inBuff.prefix.size);
+ DEBUGLOG(5, "Using source range [%zx, %zx)",
+ (size_t)buffer.start,
+ (size_t)buffer.start + buffer.capacity);
+
+
+ mtctx->inBuff.buffer = buffer;
+ mtctx->inBuff.filled = 0;
+ assert(mtctx->roundBuff.pos + buffer.capacity <= mtctx->roundBuff.capacity);
+ return 1;
+}
/** ZSTDMT_compressStream_generic() :
@@ -1034,13 +1711,13 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
ZSTD_inBuffer* input,
ZSTD_EndDirective endOp)
{
- size_t const newJobThreshold = mtctx->dictSize + mtctx->targetSectionSize;
unsigned forwardInputProgress = 0;
- DEBUGLOG(5, "ZSTDMT_compressStream_generic ");
+ DEBUGLOG(5, "ZSTDMT_compressStream_generic (endOp=%u, srcSize=%u)",
+ (U32)endOp, (U32)(input->size - input->pos));
assert(output->pos <= output->size);
assert(input->pos <= input->size);
- if (mtctx->singleThreaded) { /* delegate to single-thread (synchronous) */
+ if (mtctx->singleBlockingThread) { /* delegate to single-thread (synchronous) */
return ZSTD_compressStream_generic(mtctx->cctxPool->cctx[0], output, input, endOp);
}
@@ -1050,10 +1727,11 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
}
/* single-pass shortcut (note : synchronous-mode) */
- if ( (mtctx->nextJobID == 0) /* just started */
- && (mtctx->inBuff.filled == 0) /* nothing buffered */
- && (endOp == ZSTD_e_end) /* end order */
- && (output->size - output->pos >= ZSTD_compressBound(input->size - input->pos)) ) { /* enough room */
+ if ( (mtctx->nextJobID == 0) /* just started */
+ && (mtctx->inBuff.filled == 0) /* nothing buffered */
+ && (!mtctx->jobReady) /* no job already created */
+ && (endOp == ZSTD_e_end) /* end order */
+ && (output->size - output->pos >= ZSTD_compressBound(input->size - input->pos)) ) { /* enough space in dst */
size_t const cSize = ZSTDMT_compress_advanced_internal(mtctx,
(char*)output->dst + output->pos, output->size - output->pos,
(const char*)input->src + input->pos, input->size - input->pos,
@@ -1061,89 +1739,93 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
if (ZSTD_isError(cSize)) return cSize;
input->pos = input->size;
output->pos += cSize;
- ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->inBuff.buffer); /* was allocated in initStream */
mtctx->allJobsCompleted = 1;
mtctx->frameEnded = 1;
return 0;
}
/* fill input buffer */
- if (input->size > input->pos) { /* support NULL input */
+ if ( (!mtctx->jobReady)
+ && (input->size > input->pos) ) { /* support NULL input */
if (mtctx->inBuff.buffer.start == NULL) {
- mtctx->inBuff.buffer = ZSTDMT_getBuffer(mtctx->bufPool); /* note : may fail, in which case, no forward input progress */
- mtctx->inBuff.filled = 0;
+ assert(mtctx->inBuff.filled == 0); /* Can't fill an empty buffer */
+ if (!ZSTDMT_tryGetInputRange(mtctx)) {
+ /* It is only possible for this operation to fail if there are
+ * still compression jobs ongoing.
+ */
+ assert(mtctx->doneJobID != mtctx->nextJobID);
+ }
}
- if (mtctx->inBuff.buffer.start) {
- size_t const toLoad = MIN(input->size - input->pos, mtctx->inBuffSize - mtctx->inBuff.filled);
- DEBUGLOG(5, "inBuff:%08X; inBuffSize=%u; ToCopy=%u", (U32)(size_t)mtctx->inBuff.buffer.start, (U32)mtctx->inBuffSize, (U32)toLoad);
+ if (mtctx->inBuff.buffer.start != NULL) {
+ size_t const toLoad = MIN(input->size - input->pos, mtctx->targetSectionSize - mtctx->inBuff.filled);
+ assert(mtctx->inBuff.buffer.capacity >= mtctx->targetSectionSize);
+ DEBUGLOG(5, "ZSTDMT_compressStream_generic: adding %u bytes on top of %u to buffer of size %u",
+ (U32)toLoad, (U32)mtctx->inBuff.filled, (U32)mtctx->targetSectionSize);
memcpy((char*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled, (const char*)input->src + input->pos, toLoad);
input->pos += toLoad;
mtctx->inBuff.filled += toLoad;
forwardInputProgress = toLoad>0;
- } }
+ }
+ if ((input->pos < input->size) && (endOp == ZSTD_e_end))
+ endOp = ZSTD_e_flush; /* can't end now : not all input consumed */
+ }
- if ( (mtctx->inBuff.filled >= newJobThreshold) /* filled enough : let's compress */
- && (mtctx->nextJobID <= mtctx->doneJobID + mtctx->jobIDMask) ) { /* avoid overwriting job round buffer */
- CHECK_F( ZSTDMT_createCompressionJob(mtctx, mtctx->targetSectionSize, 0 /* endFrame */) );
+ if ( (mtctx->jobReady)
+ || (mtctx->inBuff.filled >= mtctx->targetSectionSize) /* filled enough : let's compress */
+ || ((endOp != ZSTD_e_continue) && (mtctx->inBuff.filled > 0)) /* something to flush : let's go */
+ || ((endOp == ZSTD_e_end) && (!mtctx->frameEnded)) ) { /* must finish the frame with a zero-size block */
+ size_t const jobSize = mtctx->inBuff.filled;
+ assert(mtctx->inBuff.filled <= mtctx->targetSectionSize);
+ CHECK_F( ZSTDMT_createCompressionJob(mtctx, jobSize, endOp) );
}
/* check for potential compressed data ready to be flushed */
- CHECK_F( ZSTDMT_flushNextJob(mtctx, output, !forwardInputProgress /* blockToFlush */) ); /* block if there was no forward input progress */
-
- if (input->pos < input->size) /* input not consumed : do not flush yet */
- endOp = ZSTD_e_continue;
-
- switch(endOp)
- {
- case ZSTD_e_flush:
- return ZSTDMT_flushStream(mtctx, output);
- case ZSTD_e_end:
- return ZSTDMT_endStream(mtctx, output);
- case ZSTD_e_continue:
- return 1;
- default:
- return ERROR(GENERIC); /* invalid endDirective */
+ { size_t const remainingToFlush = ZSTDMT_flushProduced(mtctx, output, !forwardInputProgress, endOp); /* block if there was no forward input progress */
+ if (input->pos < input->size) return MAX(remainingToFlush, 1); /* input not consumed : do not end flush yet */
+ return remainingToFlush;
}
}
-size_t ZSTDMT_compressStream(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
+size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
{
- CHECK_F( ZSTDMT_compressStream_generic(zcs, output, input, ZSTD_e_continue) );
+ CHECK_F( ZSTDMT_compressStream_generic(mtctx, output, input, ZSTD_e_continue) );
/* recommended next input size : fill current input buffer */
- return zcs->inBuffSize - zcs->inBuff.filled; /* note : could be zero when input buffer is fully filled and no more availability to create new job */
+ return mtctx->targetSectionSize - mtctx->inBuff.filled; /* note : could be zero when input buffer is fully filled and no more availability to create new job */
}
-static size_t ZSTDMT_flushStream_internal(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, unsigned endFrame)
+static size_t ZSTDMT_flushStream_internal(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_EndDirective endFrame)
{
- size_t const srcSize = mtctx->inBuff.filled - mtctx->dictSize;
+ size_t const srcSize = mtctx->inBuff.filled;
DEBUGLOG(5, "ZSTDMT_flushStream_internal");
- if ( ((srcSize > 0) || (endFrame && !mtctx->frameEnded))
- && (mtctx->nextJobID <= mtctx->doneJobID + mtctx->jobIDMask) ) {
- DEBUGLOG(5, "ZSTDMT_flushStream_internal : create a new job");
+ if ( mtctx->jobReady /* one job ready for a worker to pick up */
+ || (srcSize > 0) /* still some data within input buffer */
+ || ((endFrame==ZSTD_e_end) && !mtctx->frameEnded)) { /* need a last 0-size block to end frame */
+ DEBUGLOG(5, "ZSTDMT_flushStream_internal : create a new job (%u bytes, end:%u)",
+ (U32)srcSize, (U32)endFrame);
CHECK_F( ZSTDMT_createCompressionJob(mtctx, srcSize, endFrame) );
}
/* check if there is any data available to flush */
- return ZSTDMT_flushNextJob(mtctx, output, 1 /* blockToFlush */);
+ return ZSTDMT_flushProduced(mtctx, output, 1 /* blockToFlush */, endFrame);
}
size_t ZSTDMT_flushStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output)
{
DEBUGLOG(5, "ZSTDMT_flushStream");
- if (mtctx->singleThreaded)
+ if (mtctx->singleBlockingThread)
return ZSTD_flushStream(mtctx->cctxPool->cctx[0], output);
- return ZSTDMT_flushStream_internal(mtctx, output, 0 /* endFrame */);
+ return ZSTDMT_flushStream_internal(mtctx, output, ZSTD_e_flush);
}
size_t ZSTDMT_endStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output)
{
DEBUGLOG(4, "ZSTDMT_endStream");
- if (mtctx->singleThreaded)
+ if (mtctx->singleBlockingThread)
return ZSTD_endStream(mtctx->cctxPool->cctx[0], output);
- return ZSTDMT_flushStream_internal(mtctx, output, 1 /* endFrame */);
+ return ZSTDMT_flushStream_internal(mtctx, output, ZSTD_e_end);
}
diff --git a/thirdparty/zstd/compress/zstdmt_compress.h b/thirdparty/zstd/compress/zstdmt_compress.h
index d12f0adb8d..f79e3b4418 100644
--- a/thirdparty/zstd/compress/zstdmt_compress.h
+++ b/thirdparty/zstd/compress/zstdmt_compress.h
@@ -30,15 +30,15 @@
/* === Memory management === */
typedef struct ZSTDMT_CCtx_s ZSTDMT_CCtx;
-ZSTDLIB_API ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbThreads);
-ZSTDLIB_API ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbThreads,
+ZSTDLIB_API ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbWorkers);
+ZSTDLIB_API ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers,
ZSTD_customMem cMem);
ZSTDLIB_API size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx);
ZSTDLIB_API size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx);
-/* === Simple buffer-to-butter one-pass function === */
+/* === Simple one-pass compression function === */
ZSTDLIB_API size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
void* dst, size_t dstCapacity,
@@ -50,7 +50,7 @@ ZSTDLIB_API size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
/* === Streaming functions === */
ZSTDLIB_API size_t ZSTDMT_initCStream(ZSTDMT_CCtx* mtctx, int compressionLevel);
-ZSTDLIB_API size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* mtctx, unsigned long long pledgedSrcSize); /**< if srcSize is not known at reset time, use ZSTD_CONTENTSIZE_UNKNOWN. Note: for compatibility with older programs, 0 means the same as ZSTD_CONTENTSIZE_UNKNOWN, but it may change in the future, to mean "empty" */
+ZSTDLIB_API size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* mtctx, unsigned long long pledgedSrcSize); /**< if srcSize is not known at reset time, use ZSTD_CONTENTSIZE_UNKNOWN. Note: for compatibility with older programs, 0 means the same as ZSTD_CONTENTSIZE_UNKNOWN, but it will change in the future to mean "empty" */
ZSTDLIB_API size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
@@ -68,7 +68,7 @@ ZSTDLIB_API size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const ZSTD_CDict* cdict,
- ZSTD_parameters const params,
+ ZSTD_parameters params,
unsigned overlapLog);
ZSTDLIB_API size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* mtctx,
@@ -85,7 +85,7 @@ ZSTDLIB_API size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
* List of parameters that can be set using ZSTDMT_setMTCtxParameter() */
typedef enum {
ZSTDMT_p_jobSize, /* Each job is compressed in parallel. By default, this value is dynamically determined depending on compression parameters. Can be set explicitly here. */
- ZSTDMT_p_overlapSectionLog /* Each job may reload a part of previous job to enhance compressionr ratio; 0 == no overlap, 6(default) == use 1/8th of window, >=9 == use full window */
+ ZSTDMT_p_overlapSectionLog /* Each job may reload a part of previous job to enhance compressionr ratio; 0 == no overlap, 6(default) == use 1/8th of window, >=9 == use full window. This is a "sticky" parameter : its value will be re-used on next compression job */
} ZSTDMT_parameter;
/* ZSTDMT_setMTCtxParameter() :
@@ -97,30 +97,46 @@ ZSTDLIB_API size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter
/*! ZSTDMT_compressStream_generic() :
- * Combines ZSTDMT_compressStream() with ZSTDMT_flushStream() or ZSTDMT_endStream()
+ * Combines ZSTDMT_compressStream() with optional ZSTDMT_flushStream() or ZSTDMT_endStream()
* depending on flush directive.
* @return : minimum amount of data still to be flushed
* 0 if fully flushed
- * or an error code */
+ * or an error code
+ * note : needs to be init using any ZSTD_initCStream*() variant */
ZSTDLIB_API size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
ZSTD_outBuffer* output,
ZSTD_inBuffer* input,
ZSTD_EndDirective endOp);
-/* === Private definitions; never ever use directly === */
+/* ========================================================
+ * === Private interface, for use by ZSTD_compress.c ===
+ * === Not exposed in libzstd. Never invoke directly ===
+ * ======================================================== */
size_t ZSTDMT_CCtxParam_setMTCtxParameter(ZSTD_CCtx_params* params, ZSTDMT_parameter parameter, unsigned value);
-/* ZSTDMT_CCtxParam_setNbThreads()
- * Set nbThreads, and clamp it correctly,
- * also reset jobSize and overlapLog */
-size_t ZSTDMT_CCtxParam_setNbThreads(ZSTD_CCtx_params* params, unsigned nbThreads);
+/* ZSTDMT_CCtxParam_setNbWorkers()
+ * Set nbWorkers, and clamp it.
+ * Also reset jobSize and overlapLog */
+size_t ZSTDMT_CCtxParam_setNbWorkers(ZSTD_CCtx_params* params, unsigned nbWorkers);
-/* ZSTDMT_getNbThreads():
+/*! ZSTDMT_updateCParams_whileCompressing() :
+ * Updates only a selected set of compression parameters, to remain compatible with current frame.
+ * New parameters will be applied to next compression job. */
+void ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_params* cctxParams);
+
+/* ZSTDMT_getNbWorkers():
* @return nb threads currently active in mtctx.
* mtctx must be valid */
-size_t ZSTDMT_getNbThreads(const ZSTDMT_CCtx* mtctx);
+unsigned ZSTDMT_getNbWorkers(const ZSTDMT_CCtx* mtctx);
+
+/* ZSTDMT_getFrameProgression():
+ * tells how much data has been consumed (input) and produced (output) for current frame.
+ * able to count progression inside worker threads.
+ */
+ZSTD_frameProgression ZSTDMT_getFrameProgression(ZSTDMT_CCtx* mtctx);
+
/*! ZSTDMT_initCStream_internal() :
* Private use only. Init streaming operation.
@@ -128,7 +144,7 @@ size_t ZSTDMT_getNbThreads(const ZSTDMT_CCtx* mtctx);
* must receive dict, or cdict, or none, but not both.
* @return : 0, or an error code */
size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* zcs,
- const void* dict, size_t dictSize, ZSTD_dictMode_e dictMode,
+ const void* dict, size_t dictSize, ZSTD_dictContentType_e dictContentType,
const ZSTD_CDict* cdict,
ZSTD_CCtx_params params, unsigned long long pledgedSrcSize);
diff --git a/thirdparty/zstd/decompress/huf_decompress.c b/thirdparty/zstd/decompress/huf_decompress.c
index 79ded96bf6..73f5c46c06 100644
--- a/thirdparty/zstd/decompress/huf_decompress.c
+++ b/thirdparty/zstd/decompress/huf_decompress.c
@@ -49,18 +49,19 @@
****************************************************************/
#define HUF_isError ERR_isError
#define HUF_STATIC_ASSERT(c) { enum { HUF_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
+#define CHECK_F(f) { size_t const err_ = (f); if (HUF_isError(err_)) return err_; }
/* **************************************************************
* Byte alignment for workSpace management
****************************************************************/
-#define HUF_ALIGN(x, a) HUF_ALIGN_MASK((x), (a) - 1)
+#define HUF_ALIGN(x, a) HUF_ALIGN_MASK((x), (a) - 1)
#define HUF_ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
+
/*-***************************/
/* generic DTableDesc */
/*-***************************/
-
typedef struct { BYTE maxTableLog; BYTE tableType; BYTE tableLog; BYTE reserved; } DTableDesc;
static DTableDesc HUF_getDTableDesc(const HUF_DTable* table)
@@ -74,7 +75,6 @@ static DTableDesc HUF_getDTableDesc(const HUF_DTable* table)
/*-***************************/
/* single-symbol decoding */
/*-***************************/
-
typedef struct { BYTE byte; BYTE nbBits; } HUF_DEltX2; /* single-symbol decoding */
size_t HUF_readDTableX2_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize)
@@ -94,10 +94,7 @@ size_t HUF_readDTableX2_wksp(HUF_DTable* DTable, const void* src, size_t srcSize
huffWeight = (BYTE *)((U32 *)workSpace + spaceUsed32);
spaceUsed32 += HUF_ALIGN(HUF_SYMBOLVALUE_MAX + 1, sizeof(U32)) >> 2;
- if ((spaceUsed32 << 2) > wkspSize)
- return ERROR(tableLog_tooLarge);
- workSpace = (U32 *)workSpace + spaceUsed32;
- wkspSize -= (spaceUsed32 << 2);
+ if ((spaceUsed32 << 2) > wkspSize) return ERROR(tableLog_tooLarge);
HUF_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(HUF_DTable));
/* memset(huffWeight, 0, sizeof(huffWeight)); */ /* is not necessary, even though some analyzer complain ... */
@@ -144,8 +141,10 @@ size_t HUF_readDTableX2(HUF_DTable* DTable, const void* src, size_t srcSize)
workSpace, sizeof(workSpace));
}
+typedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUF_DEltX4; /* double-symbols decoding */
-static BYTE HUF_decodeSymbolX2(BIT_DStream_t* Dstream, const HUF_DEltX2* dt, const U32 dtLog)
+FORCE_INLINE_TEMPLATE BYTE
+HUF_decodeSymbolX2(BIT_DStream_t* Dstream, const HUF_DEltX2* dt, const U32 dtLog)
{
size_t const val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */
BYTE const c = dt[val].byte;
@@ -156,7 +155,7 @@ static BYTE HUF_decodeSymbolX2(BIT_DStream_t* Dstream, const HUF_DEltX2* dt, con
#define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \
*ptr++ = HUF_decodeSymbolX2(DStreamPtr, dt, dtLog)
-#define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \
+#define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \
if (MEM_64bits() || (HUF_TABLELOG_MAX<=12)) \
HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr)
@@ -164,30 +163,33 @@ static BYTE HUF_decodeSymbolX2(BIT_DStream_t* Dstream, const HUF_DEltX2* dt, con
if (MEM_64bits()) \
HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr)
-HINT_INLINE size_t HUF_decodeStreamX2(BYTE* p, BIT_DStream_t* const bitDPtr, BYTE* const pEnd, const HUF_DEltX2* const dt, const U32 dtLog)
+HINT_INLINE size_t
+HUF_decodeStreamX2(BYTE* p, BIT_DStream_t* const bitDPtr, BYTE* const pEnd, const HUF_DEltX2* const dt, const U32 dtLog)
{
BYTE* const pStart = p;
/* up to 4 symbols at a time */
- while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-4)) {
+ while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-3)) {
HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
HUF_DECODE_SYMBOLX2_1(p, bitDPtr);
HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
}
- /* closer to the end */
- while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd))
- HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
+ /* [0-3] symbols remaining */
+ if (MEM_32bits())
+ while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd))
+ HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
- /* no more data to retrieve from bitstream, hence no need to reload */
+ /* no more data to retrieve from bitstream, no need to reload */
while (p < pEnd)
HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
return pEnd-pStart;
}
-static size_t HUF_decompress1X2_usingDTable_internal(
+FORCE_INLINE_TEMPLATE size_t
+HUF_decompress1X2_usingDTable_internal_body(
void* dst, size_t dstSize,
const void* cSrc, size_t cSrcSize,
const HUF_DTable* DTable)
@@ -200,58 +202,17 @@ static size_t HUF_decompress1X2_usingDTable_internal(
DTableDesc const dtd = HUF_getDTableDesc(DTable);
U32 const dtLog = dtd.tableLog;
- { size_t const errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize);
- if (HUF_isError(errorCode)) return errorCode; }
+ CHECK_F( BIT_initDStream(&bitD, cSrc, cSrcSize) );
HUF_decodeStreamX2(op, &bitD, oend, dt, dtLog);
- /* check */
if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected);
return dstSize;
}
-size_t HUF_decompress1X2_usingDTable(
- void* dst, size_t dstSize,
- const void* cSrc, size_t cSrcSize,
- const HUF_DTable* DTable)
-{
- DTableDesc dtd = HUF_getDTableDesc(DTable);
- if (dtd.tableType != 0) return ERROR(GENERIC);
- return HUF_decompress1X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
-}
-
-size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize,
- const void* cSrc, size_t cSrcSize,
- void* workSpace, size_t wkspSize)
-{
- const BYTE* ip = (const BYTE*) cSrc;
-
- size_t const hSize = HUF_readDTableX2_wksp(DCtx, cSrc, cSrcSize, workSpace, wkspSize);
- if (HUF_isError(hSize)) return hSize;
- if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
- ip += hSize; cSrcSize -= hSize;
-
- return HUF_decompress1X2_usingDTable_internal (dst, dstSize, ip, cSrcSize, DCtx);
-}
-
-
-size_t HUF_decompress1X2_DCtx(HUF_DTable* DCtx, void* dst, size_t dstSize,
- const void* cSrc, size_t cSrcSize)
-{
- U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
- return HUF_decompress1X2_DCtx_wksp(DCtx, dst, dstSize, cSrc, cSrcSize,
- workSpace, sizeof(workSpace));
-}
-
-size_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
-{
- HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX);
- return HUF_decompress1X2_DCtx (DTable, dst, dstSize, cSrc, cSrcSize);
-}
-
-
-static size_t HUF_decompress4X2_usingDTable_internal(
+FORCE_INLINE_TEMPLATE size_t
+HUF_decompress4X2_usingDTable_internal_body(
void* dst, size_t dstSize,
const void* cSrc, size_t cSrcSize,
const HUF_DTable* DTable)
@@ -286,23 +247,19 @@ static size_t HUF_decompress4X2_usingDTable_internal(
BYTE* op2 = opStart2;
BYTE* op3 = opStart3;
BYTE* op4 = opStart4;
- U32 endSignal;
+ U32 endSignal = BIT_DStream_unfinished;
DTableDesc const dtd = HUF_getDTableDesc(DTable);
U32 const dtLog = dtd.tableLog;
if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */
- { size_t const errorCode = BIT_initDStream(&bitD1, istart1, length1);
- if (HUF_isError(errorCode)) return errorCode; }
- { size_t const errorCode = BIT_initDStream(&bitD2, istart2, length2);
- if (HUF_isError(errorCode)) return errorCode; }
- { size_t const errorCode = BIT_initDStream(&bitD3, istart3, length3);
- if (HUF_isError(errorCode)) return errorCode; }
- { size_t const errorCode = BIT_initDStream(&bitD4, istart4, length4);
- if (HUF_isError(errorCode)) return errorCode; }
+ CHECK_F( BIT_initDStream(&bitD1, istart1, length1) );
+ CHECK_F( BIT_initDStream(&bitD2, istart2, length2) );
+ CHECK_F( BIT_initDStream(&bitD3, istart3, length3) );
+ CHECK_F( BIT_initDStream(&bitD4, istart4, length4) );
- /* 16-32 symbols per loop (4-8 symbols per stream) */
+ /* up to 16 symbols per loop (4 symbols per stream) in 64-bit mode */
endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
- for ( ; (endSignal==BIT_DStream_unfinished) && (op4<(oend-7)) ; ) {
+ while ( (endSignal==BIT_DStream_unfinished) && (op4<(oend-3)) ) {
HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
@@ -319,10 +276,15 @@ static size_t HUF_decompress4X2_usingDTable_internal(
HUF_DECODE_SYMBOLX2_0(op2, &bitD2);
HUF_DECODE_SYMBOLX2_0(op3, &bitD3);
HUF_DECODE_SYMBOLX2_0(op4, &bitD4);
- endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
+ BIT_reloadDStream(&bitD1);
+ BIT_reloadDStream(&bitD2);
+ BIT_reloadDStream(&bitD3);
+ BIT_reloadDStream(&bitD4);
}
/* check corruption */
+ /* note : should not be necessary : op# advance in lock step, and we control op4.
+ * but curiously, binary generated by gcc 7.2 & 7.3 with -mbmi2 runs faster when >=1 test is present */
if (op1 > opStart2) return ERROR(corruption_detected);
if (op2 > opStart3) return ERROR(corruption_detected);
if (op3 > opStart4) return ERROR(corruption_detected);
@@ -335,8 +297,8 @@ static size_t HUF_decompress4X2_usingDTable_internal(
HUF_decodeStreamX2(op4, &bitD4, oend, dt, dtLog);
/* check */
- endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
- if (!endSignal) return ERROR(corruption_detected);
+ { U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
+ if (!endCheck) return ERROR(corruption_detected); }
/* decoded size */
return dstSize;
@@ -344,30 +306,309 @@ static size_t HUF_decompress4X2_usingDTable_internal(
}
-size_t HUF_decompress4X2_usingDTable(
+FORCE_INLINE_TEMPLATE U32
+HUF_decodeSymbolX4(void* op, BIT_DStream_t* DStream, const HUF_DEltX4* dt, const U32 dtLog)
+{
+ size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */
+ memcpy(op, dt+val, 2);
+ BIT_skipBits(DStream, dt[val].nbBits);
+ return dt[val].length;
+}
+
+FORCE_INLINE_TEMPLATE U32
+HUF_decodeLastSymbolX4(void* op, BIT_DStream_t* DStream, const HUF_DEltX4* dt, const U32 dtLog)
+{
+ size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */
+ memcpy(op, dt+val, 1);
+ if (dt[val].length==1) BIT_skipBits(DStream, dt[val].nbBits);
+ else {
+ if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) {
+ BIT_skipBits(DStream, dt[val].nbBits);
+ if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))
+ /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */
+ DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);
+ } }
+ return 1;
+}
+
+#define HUF_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \
+ ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
+
+#define HUF_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \
+ if (MEM_64bits() || (HUF_TABLELOG_MAX<=12)) \
+ ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
+
+#define HUF_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \
+ if (MEM_64bits()) \
+ ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
+
+HINT_INLINE size_t
+HUF_decodeStreamX4(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd,
+ const HUF_DEltX4* const dt, const U32 dtLog)
+{
+ BYTE* const pStart = p;
+
+ /* up to 8 symbols at a time */
+ while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-(sizeof(bitDPtr->bitContainer)-1))) {
+ HUF_DECODE_SYMBOLX4_2(p, bitDPtr);
+ HUF_DECODE_SYMBOLX4_1(p, bitDPtr);
+ HUF_DECODE_SYMBOLX4_2(p, bitDPtr);
+ HUF_DECODE_SYMBOLX4_0(p, bitDPtr);
+ }
+
+ /* closer to end : up to 2 symbols at a time */
+ while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p <= pEnd-2))
+ HUF_DECODE_SYMBOLX4_0(p, bitDPtr);
+
+ while (p <= pEnd-2)
+ HUF_DECODE_SYMBOLX4_0(p, bitDPtr); /* no need to reload : reached the end of DStream */
+
+ if (p < pEnd)
+ p += HUF_decodeLastSymbolX4(p, bitDPtr, dt, dtLog);
+
+ return p-pStart;
+}
+
+FORCE_INLINE_TEMPLATE size_t
+HUF_decompress1X4_usingDTable_internal_body(
+ void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize,
+ const HUF_DTable* DTable)
+{
+ BIT_DStream_t bitD;
+
+ /* Init */
+ CHECK_F( BIT_initDStream(&bitD, cSrc, cSrcSize) );
+
+ /* decode */
+ { BYTE* const ostart = (BYTE*) dst;
+ BYTE* const oend = ostart + dstSize;
+ const void* const dtPtr = DTable+1; /* force compiler to not use strict-aliasing */
+ const HUF_DEltX4* const dt = (const HUF_DEltX4*)dtPtr;
+ DTableDesc const dtd = HUF_getDTableDesc(DTable);
+ HUF_decodeStreamX4(ostart, &bitD, oend, dt, dtd.tableLog);
+ }
+
+ /* check */
+ if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected);
+
+ /* decoded size */
+ return dstSize;
+}
+
+
+FORCE_INLINE_TEMPLATE size_t
+HUF_decompress4X4_usingDTable_internal_body(
+ void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize,
+ const HUF_DTable* DTable)
+{
+ if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */
+
+ { const BYTE* const istart = (const BYTE*) cSrc;
+ BYTE* const ostart = (BYTE*) dst;
+ BYTE* const oend = ostart + dstSize;
+ const void* const dtPtr = DTable+1;
+ const HUF_DEltX4* const dt = (const HUF_DEltX4*)dtPtr;
+
+ /* Init */
+ BIT_DStream_t bitD1;
+ BIT_DStream_t bitD2;
+ BIT_DStream_t bitD3;
+ BIT_DStream_t bitD4;
+ size_t const length1 = MEM_readLE16(istart);
+ size_t const length2 = MEM_readLE16(istart+2);
+ size_t const length3 = MEM_readLE16(istart+4);
+ size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);
+ const BYTE* const istart1 = istart + 6; /* jumpTable */
+ const BYTE* const istart2 = istart1 + length1;
+ const BYTE* const istart3 = istart2 + length2;
+ const BYTE* const istart4 = istart3 + length3;
+ size_t const segmentSize = (dstSize+3) / 4;
+ BYTE* const opStart2 = ostart + segmentSize;
+ BYTE* const opStart3 = opStart2 + segmentSize;
+ BYTE* const opStart4 = opStart3 + segmentSize;
+ BYTE* op1 = ostart;
+ BYTE* op2 = opStart2;
+ BYTE* op3 = opStart3;
+ BYTE* op4 = opStart4;
+ U32 endSignal;
+ DTableDesc const dtd = HUF_getDTableDesc(DTable);
+ U32 const dtLog = dtd.tableLog;
+
+ if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */
+ CHECK_F( BIT_initDStream(&bitD1, istart1, length1) );
+ CHECK_F( BIT_initDStream(&bitD2, istart2, length2) );
+ CHECK_F( BIT_initDStream(&bitD3, istart3, length3) );
+ CHECK_F( BIT_initDStream(&bitD4, istart4, length4) );
+
+ /* 16-32 symbols per loop (4-8 symbols per stream) */
+ endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
+ for ( ; (endSignal==BIT_DStream_unfinished) & (op4<(oend-(sizeof(bitD4.bitContainer)-1))) ; ) {
+ HUF_DECODE_SYMBOLX4_2(op1, &bitD1);
+ HUF_DECODE_SYMBOLX4_2(op2, &bitD2);
+ HUF_DECODE_SYMBOLX4_2(op3, &bitD3);
+ HUF_DECODE_SYMBOLX4_2(op4, &bitD4);
+ HUF_DECODE_SYMBOLX4_1(op1, &bitD1);
+ HUF_DECODE_SYMBOLX4_1(op2, &bitD2);
+ HUF_DECODE_SYMBOLX4_1(op3, &bitD3);
+ HUF_DECODE_SYMBOLX4_1(op4, &bitD4);
+ HUF_DECODE_SYMBOLX4_2(op1, &bitD1);
+ HUF_DECODE_SYMBOLX4_2(op2, &bitD2);
+ HUF_DECODE_SYMBOLX4_2(op3, &bitD3);
+ HUF_DECODE_SYMBOLX4_2(op4, &bitD4);
+ HUF_DECODE_SYMBOLX4_0(op1, &bitD1);
+ HUF_DECODE_SYMBOLX4_0(op2, &bitD2);
+ HUF_DECODE_SYMBOLX4_0(op3, &bitD3);
+ HUF_DECODE_SYMBOLX4_0(op4, &bitD4);
+
+ endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
+ }
+
+ /* check corruption */
+ if (op1 > opStart2) return ERROR(corruption_detected);
+ if (op2 > opStart3) return ERROR(corruption_detected);
+ if (op3 > opStart4) return ERROR(corruption_detected);
+ /* note : op4 already verified within main loop */
+
+ /* finish bitStreams one by one */
+ HUF_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog);
+ HUF_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog);
+ HUF_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog);
+ HUF_decodeStreamX4(op4, &bitD4, oend, dt, dtLog);
+
+ /* check */
+ { U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
+ if (!endCheck) return ERROR(corruption_detected); }
+
+ /* decoded size */
+ return dstSize;
+ }
+}
+
+
+typedef size_t (*HUF_decompress_usingDTable_t)(void *dst, size_t dstSize,
+ const void *cSrc,
+ size_t cSrcSize,
+ const HUF_DTable *DTable);
+#if DYNAMIC_BMI2
+
+#define X(fn) \
+ \
+ static size_t fn##_default( \
+ void* dst, size_t dstSize, \
+ const void* cSrc, size_t cSrcSize, \
+ const HUF_DTable* DTable) \
+ { \
+ return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable); \
+ } \
+ \
+ static TARGET_ATTRIBUTE("bmi2") size_t fn##_bmi2( \
+ void* dst, size_t dstSize, \
+ const void* cSrc, size_t cSrcSize, \
+ const HUF_DTable* DTable) \
+ { \
+ return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable); \
+ } \
+ \
+ static size_t fn(void* dst, size_t dstSize, void const* cSrc, \
+ size_t cSrcSize, HUF_DTable const* DTable, int bmi2) \
+ { \
+ if (bmi2) { \
+ return fn##_bmi2(dst, dstSize, cSrc, cSrcSize, DTable); \
+ } \
+ return fn##_default(dst, dstSize, cSrc, cSrcSize, DTable); \
+ }
+
+#else
+
+#define X(fn) \
+ static size_t fn(void* dst, size_t dstSize, void const* cSrc, \
+ size_t cSrcSize, HUF_DTable const* DTable, int bmi2) \
+ { \
+ (void)bmi2; \
+ return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable); \
+ }
+
+#endif
+
+X(HUF_decompress1X2_usingDTable_internal)
+X(HUF_decompress4X2_usingDTable_internal)
+X(HUF_decompress1X4_usingDTable_internal)
+X(HUF_decompress4X4_usingDTable_internal)
+
+#undef X
+
+
+size_t HUF_decompress1X2_usingDTable(
void* dst, size_t dstSize,
const void* cSrc, size_t cSrcSize,
const HUF_DTable* DTable)
{
DTableDesc dtd = HUF_getDTableDesc(DTable);
if (dtd.tableType != 0) return ERROR(GENERIC);
- return HUF_decompress4X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
+ return HUF_decompress1X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
}
-
-size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
+size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize,
const void* cSrc, size_t cSrcSize,
void* workSpace, size_t wkspSize)
{
const BYTE* ip = (const BYTE*) cSrc;
+ size_t const hSize = HUF_readDTableX2_wksp(DCtx, cSrc, cSrcSize, workSpace, wkspSize);
+ if (HUF_isError(hSize)) return hSize;
+ if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
+ ip += hSize; cSrcSize -= hSize;
+
+ return HUF_decompress1X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx, /* bmi2 */ 0);
+}
+
+
+size_t HUF_decompress1X2_DCtx(HUF_DTable* DCtx, void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize)
+{
+ U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
+ return HUF_decompress1X2_DCtx_wksp(DCtx, dst, dstSize, cSrc, cSrcSize,
+ workSpace, sizeof(workSpace));
+}
+
+size_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
+{
+ HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX);
+ return HUF_decompress1X2_DCtx (DTable, dst, dstSize, cSrc, cSrcSize);
+}
+
+size_t HUF_decompress4X2_usingDTable(
+ void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize,
+ const HUF_DTable* DTable)
+{
+ DTableDesc dtd = HUF_getDTableDesc(DTable);
+ if (dtd.tableType != 0) return ERROR(GENERIC);
+ return HUF_decompress4X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
+}
+
+static size_t HUF_decompress4X2_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize,
+ void* workSpace, size_t wkspSize, int bmi2)
+{
+ const BYTE* ip = (const BYTE*) cSrc;
+
size_t const hSize = HUF_readDTableX2_wksp (dctx, cSrc, cSrcSize,
workSpace, wkspSize);
if (HUF_isError(hSize)) return hSize;
if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
ip += hSize; cSrcSize -= hSize;
- return HUF_decompress4X2_usingDTable_internal (dst, dstSize, ip, cSrcSize, dctx);
+ return HUF_decompress4X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2);
+}
+
+size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize,
+ void* workSpace, size_t wkspSize)
+{
+ return HUF_decompress4X2_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, 0);
}
@@ -387,8 +628,6 @@ size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cS
/* *************************/
/* double-symbols decoding */
/* *************************/
-typedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUF_DEltX4; /* double-symbols decoding */
-
typedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t;
/* HUF_fillDTableX4Level2() :
@@ -508,10 +747,7 @@ size_t HUF_readDTableX4_wksp(HUF_DTable* DTable, const void* src,
weightList = (BYTE *)((U32 *)workSpace + spaceUsed32);
spaceUsed32 += HUF_ALIGN(HUF_SYMBOLVALUE_MAX + 1, sizeof(U32)) >> 2;
- if ((spaceUsed32 << 2) > wkspSize)
- return ERROR(tableLog_tooLarge);
- workSpace = (U32 *)workSpace + spaceUsed32;
- wkspSize -= (spaceUsed32 << 2);
+ if ((spaceUsed32 << 2) > wkspSize) return ERROR(tableLog_tooLarge);
rankStart = rankStart0 + 1;
memset(rankStats, 0, sizeof(U32) * (2 * HUF_TABLELOG_MAX + 2 + 1));
@@ -588,95 +824,6 @@ size_t HUF_readDTableX4(HUF_DTable* DTable, const void* src, size_t srcSize)
workSpace, sizeof(workSpace));
}
-static U32 HUF_decodeSymbolX4(void* op, BIT_DStream_t* DStream, const HUF_DEltX4* dt, const U32 dtLog)
-{
- size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */
- memcpy(op, dt+val, 2);
- BIT_skipBits(DStream, dt[val].nbBits);
- return dt[val].length;
-}
-
-static U32 HUF_decodeLastSymbolX4(void* op, BIT_DStream_t* DStream, const HUF_DEltX4* dt, const U32 dtLog)
-{
- size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */
- memcpy(op, dt+val, 1);
- if (dt[val].length==1) BIT_skipBits(DStream, dt[val].nbBits);
- else {
- if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) {
- BIT_skipBits(DStream, dt[val].nbBits);
- if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))
- /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */
- DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);
- } }
- return 1;
-}
-
-
-#define HUF_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \
- ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
-
-#define HUF_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \
- if (MEM_64bits() || (HUF_TABLELOG_MAX<=12)) \
- ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
-
-#define HUF_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \
- if (MEM_64bits()) \
- ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
-
-HINT_INLINE size_t HUF_decodeStreamX4(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd, const HUF_DEltX4* const dt, const U32 dtLog)
-{
- BYTE* const pStart = p;
-
- /* up to 8 symbols at a time */
- while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-(sizeof(bitDPtr->bitContainer)-1))) {
- HUF_DECODE_SYMBOLX4_2(p, bitDPtr);
- HUF_DECODE_SYMBOLX4_1(p, bitDPtr);
- HUF_DECODE_SYMBOLX4_2(p, bitDPtr);
- HUF_DECODE_SYMBOLX4_0(p, bitDPtr);
- }
-
- /* closer to end : up to 2 symbols at a time */
- while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p <= pEnd-2))
- HUF_DECODE_SYMBOLX4_0(p, bitDPtr);
-
- while (p <= pEnd-2)
- HUF_DECODE_SYMBOLX4_0(p, bitDPtr); /* no need to reload : reached the end of DStream */
-
- if (p < pEnd)
- p += HUF_decodeLastSymbolX4(p, bitDPtr, dt, dtLog);
-
- return p-pStart;
-}
-
-
-static size_t HUF_decompress1X4_usingDTable_internal(
- void* dst, size_t dstSize,
- const void* cSrc, size_t cSrcSize,
- const HUF_DTable* DTable)
-{
- BIT_DStream_t bitD;
-
- /* Init */
- { size_t const errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize);
- if (HUF_isError(errorCode)) return errorCode;
- }
-
- /* decode */
- { BYTE* const ostart = (BYTE*) dst;
- BYTE* const oend = ostart + dstSize;
- const void* const dtPtr = DTable+1; /* force compiler to not use strict-aliasing */
- const HUF_DEltX4* const dt = (const HUF_DEltX4*)dtPtr;
- DTableDesc const dtd = HUF_getDTableDesc(DTable);
- HUF_decodeStreamX4(ostart, &bitD, oend, dt, dtd.tableLog);
- }
-
- /* check */
- if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected);
-
- /* decoded size */
- return dstSize;
-}
-
size_t HUF_decompress1X4_usingDTable(
void* dst, size_t dstSize,
const void* cSrc, size_t cSrcSize,
@@ -684,7 +831,7 @@ size_t HUF_decompress1X4_usingDTable(
{
DTableDesc dtd = HUF_getDTableDesc(DTable);
if (dtd.tableType != 1) return ERROR(GENERIC);
- return HUF_decompress1X4_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
+ return HUF_decompress1X4_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
}
size_t HUF_decompress1X4_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize,
@@ -699,7 +846,7 @@ size_t HUF_decompress1X4_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize,
if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
ip += hSize; cSrcSize -= hSize;
- return HUF_decompress1X4_usingDTable_internal (dst, dstSize, ip, cSrcSize, DCtx);
+ return HUF_decompress1X4_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx, /* bmi2 */ 0);
}
@@ -717,99 +864,6 @@ size_t HUF_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cS
return HUF_decompress1X4_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);
}
-static size_t HUF_decompress4X4_usingDTable_internal(
- void* dst, size_t dstSize,
- const void* cSrc, size_t cSrcSize,
- const HUF_DTable* DTable)
-{
- if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */
-
- { const BYTE* const istart = (const BYTE*) cSrc;
- BYTE* const ostart = (BYTE*) dst;
- BYTE* const oend = ostart + dstSize;
- const void* const dtPtr = DTable+1;
- const HUF_DEltX4* const dt = (const HUF_DEltX4*)dtPtr;
-
- /* Init */
- BIT_DStream_t bitD1;
- BIT_DStream_t bitD2;
- BIT_DStream_t bitD3;
- BIT_DStream_t bitD4;
- size_t const length1 = MEM_readLE16(istart);
- size_t const length2 = MEM_readLE16(istart+2);
- size_t const length3 = MEM_readLE16(istart+4);
- size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);
- const BYTE* const istart1 = istart + 6; /* jumpTable */
- const BYTE* const istart2 = istart1 + length1;
- const BYTE* const istart3 = istart2 + length2;
- const BYTE* const istart4 = istart3 + length3;
- size_t const segmentSize = (dstSize+3) / 4;
- BYTE* const opStart2 = ostart + segmentSize;
- BYTE* const opStart3 = opStart2 + segmentSize;
- BYTE* const opStart4 = opStart3 + segmentSize;
- BYTE* op1 = ostart;
- BYTE* op2 = opStart2;
- BYTE* op3 = opStart3;
- BYTE* op4 = opStart4;
- U32 endSignal;
- DTableDesc const dtd = HUF_getDTableDesc(DTable);
- U32 const dtLog = dtd.tableLog;
-
- if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */
- { size_t const errorCode = BIT_initDStream(&bitD1, istart1, length1);
- if (HUF_isError(errorCode)) return errorCode; }
- { size_t const errorCode = BIT_initDStream(&bitD2, istart2, length2);
- if (HUF_isError(errorCode)) return errorCode; }
- { size_t const errorCode = BIT_initDStream(&bitD3, istart3, length3);
- if (HUF_isError(errorCode)) return errorCode; }
- { size_t const errorCode = BIT_initDStream(&bitD4, istart4, length4);
- if (HUF_isError(errorCode)) return errorCode; }
-
- /* 16-32 symbols per loop (4-8 symbols per stream) */
- endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
- for ( ; (endSignal==BIT_DStream_unfinished) & (op4<(oend-(sizeof(bitD4.bitContainer)-1))) ; ) {
- HUF_DECODE_SYMBOLX4_2(op1, &bitD1);
- HUF_DECODE_SYMBOLX4_2(op2, &bitD2);
- HUF_DECODE_SYMBOLX4_2(op3, &bitD3);
- HUF_DECODE_SYMBOLX4_2(op4, &bitD4);
- HUF_DECODE_SYMBOLX4_1(op1, &bitD1);
- HUF_DECODE_SYMBOLX4_1(op2, &bitD2);
- HUF_DECODE_SYMBOLX4_1(op3, &bitD3);
- HUF_DECODE_SYMBOLX4_1(op4, &bitD4);
- HUF_DECODE_SYMBOLX4_2(op1, &bitD1);
- HUF_DECODE_SYMBOLX4_2(op2, &bitD2);
- HUF_DECODE_SYMBOLX4_2(op3, &bitD3);
- HUF_DECODE_SYMBOLX4_2(op4, &bitD4);
- HUF_DECODE_SYMBOLX4_0(op1, &bitD1);
- HUF_DECODE_SYMBOLX4_0(op2, &bitD2);
- HUF_DECODE_SYMBOLX4_0(op3, &bitD3);
- HUF_DECODE_SYMBOLX4_0(op4, &bitD4);
-
- endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
- }
-
- /* check corruption */
- if (op1 > opStart2) return ERROR(corruption_detected);
- if (op2 > opStart3) return ERROR(corruption_detected);
- if (op3 > opStart4) return ERROR(corruption_detected);
- /* note : op4 already verified within main loop */
-
- /* finish bitStreams one by one */
- HUF_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog);
- HUF_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog);
- HUF_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog);
- HUF_decodeStreamX4(op4, &bitD4, oend, dt, dtLog);
-
- /* check */
- { U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
- if (!endCheck) return ERROR(corruption_detected); }
-
- /* decoded size */
- return dstSize;
- }
-}
-
-
size_t HUF_decompress4X4_usingDTable(
void* dst, size_t dstSize,
const void* cSrc, size_t cSrcSize,
@@ -817,13 +871,12 @@ size_t HUF_decompress4X4_usingDTable(
{
DTableDesc dtd = HUF_getDTableDesc(DTable);
if (dtd.tableType != 1) return ERROR(GENERIC);
- return HUF_decompress4X4_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
+ return HUF_decompress4X4_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
}
-
-size_t HUF_decompress4X4_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
+static size_t HUF_decompress4X4_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize,
const void* cSrc, size_t cSrcSize,
- void* workSpace, size_t wkspSize)
+ void* workSpace, size_t wkspSize, int bmi2)
{
const BYTE* ip = (const BYTE*) cSrc;
@@ -833,7 +886,14 @@ size_t HUF_decompress4X4_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
ip += hSize; cSrcSize -= hSize;
- return HUF_decompress4X4_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx);
+ return HUF_decompress4X4_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2);
+}
+
+size_t HUF_decompress4X4_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize,
+ void* workSpace, size_t wkspSize)
+{
+ return HUF_decompress4X4_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, /* bmi2 */ 0);
}
@@ -861,8 +921,8 @@ size_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize,
const HUF_DTable* DTable)
{
DTableDesc const dtd = HUF_getDTableDesc(DTable);
- return dtd.tableType ? HUF_decompress1X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable) :
- HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable);
+ return dtd.tableType ? HUF_decompress1X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0) :
+ HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
}
size_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize,
@@ -870,8 +930,8 @@ size_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize,
const HUF_DTable* DTable)
{
DTableDesc const dtd = HUF_getDTableDesc(DTable);
- return dtd.tableType ? HUF_decompress4X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable) :
- HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable);
+ return dtd.tableType ? HUF_decompress4X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0) :
+ HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
}
@@ -898,21 +958,22 @@ static const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, qu
};
/** HUF_selectDecoder() :
-* Tells which decoder is likely to decode faster,
-* based on a set of pre-determined metrics.
-* @return : 0==HUF_decompress4X2, 1==HUF_decompress4X4 .
-* Assumption : 0 < cSrcSize, dstSize <= 128 KB */
+ * Tells which decoder is likely to decode faster,
+ * based on a set of pre-computed metrics.
+ * @return : 0==HUF_decompress4X2, 1==HUF_decompress4X4 .
+ * Assumption : 0 < dstSize <= 128 KB */
U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize)
{
+ assert(dstSize > 0);
+ assert(dstSize <= 128 KB);
/* decoder timing evaluation */
- U32 const Q = cSrcSize >= dstSize ? 15 : (U32)(cSrcSize * 16 / dstSize); /* Q < 16 */
- U32 const D256 = (U32)(dstSize >> 8);
- U32 const DTime0 = algoTime[Q][0].tableTime + (algoTime[Q][0].decode256Time * D256);
- U32 DTime1 = algoTime[Q][1].tableTime + (algoTime[Q][1].decode256Time * D256);
- DTime1 += DTime1 >> 3; /* advantage to algorithm using less memory, for cache eviction */
-
- return DTime1 < DTime0;
-}
+ { U32 const Q = (cSrcSize >= dstSize) ? 15 : (U32)(cSrcSize * 16 / dstSize); /* Q < 16 */
+ U32 const D256 = (U32)(dstSize >> 8);
+ U32 const DTime0 = algoTime[Q][0].tableTime + (algoTime[Q][0].decode256Time * D256);
+ U32 DTime1 = algoTime[Q][1].tableTime + (algoTime[Q][1].decode256Time * D256);
+ DTime1 += DTime1 >> 3; /* advantage to algorithm using less memory, to reduce cache eviction */
+ return DTime1 < DTime0;
+} }
typedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);
@@ -994,3 +1055,42 @@ size_t HUF_decompress1X_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize,
return HUF_decompress1X_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize,
workSpace, sizeof(workSpace));
}
+
+
+size_t HUF_decompress1X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2)
+{
+ DTableDesc const dtd = HUF_getDTableDesc(DTable);
+ return dtd.tableType ? HUF_decompress1X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2) :
+ HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
+}
+
+size_t HUF_decompress1X2_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2)
+{
+ const BYTE* ip = (const BYTE*) cSrc;
+
+ size_t const hSize = HUF_readDTableX2_wksp(dctx, cSrc, cSrcSize, workSpace, wkspSize);
+ if (HUF_isError(hSize)) return hSize;
+ if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
+ ip += hSize; cSrcSize -= hSize;
+
+ return HUF_decompress1X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2);
+}
+
+size_t HUF_decompress4X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2)
+{
+ DTableDesc const dtd = HUF_getDTableDesc(DTable);
+ return dtd.tableType ? HUF_decompress4X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2) :
+ HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
+}
+
+size_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2)
+{
+ /* validation checks */
+ if (dstSize == 0) return ERROR(dstSize_tooSmall);
+ if (cSrcSize == 0) return ERROR(corruption_detected);
+
+ { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
+ return algoNb ? HUF_decompress4X4_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2) :
+ HUF_decompress4X2_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2);
+ }
+}
diff --git a/thirdparty/zstd/decompress/zstd_decompress.c b/thirdparty/zstd/decompress/zstd_decompress.c
index a59d944112..3ec6a1cb32 100644
--- a/thirdparty/zstd/decompress/zstd_decompress.c
+++ b/thirdparty/zstd/decompress/zstd_decompress.c
@@ -14,8 +14,9 @@
*****************************************************************/
/*!
* HEAPMODE :
- * Select how default decompression function ZSTD_decompress() will allocate memory,
- * in memory stack (0), or in memory heap (1, requires malloc())
+ * Select how default decompression function ZSTD_decompress() allocates its context,
+ * on stack (0), or into heap (1, default; requires malloc()).
+ * Note that functions with explicit context such as ZSTD_decompressDCtx() are unaffected.
*/
#ifndef ZSTD_HEAPMODE
# define ZSTD_HEAPMODE 1
@@ -23,17 +24,18 @@
/*!
* LEGACY_SUPPORT :
-* if set to 1, ZSTD_decompress() can decode older formats (v0.1+)
+* if set to 1+, ZSTD_decompress() can decode older formats (v0.1+)
*/
#ifndef ZSTD_LEGACY_SUPPORT
# define ZSTD_LEGACY_SUPPORT 0
#endif
/*!
-* MAXWINDOWSIZE_DEFAULT :
-* maximum window size accepted by DStream, by default.
-* Frames requiring more memory will be rejected.
-*/
+ * MAXWINDOWSIZE_DEFAULT :
+ * maximum window size accepted by DStream __by default__.
+ * Frames requiring more memory will be rejected.
+ * It's possible to set a different limit using ZSTD_DCtx_setMaxWindowSize().
+ */
#ifndef ZSTD_MAXWINDOWSIZE_DEFAULT
# define ZSTD_MAXWINDOWSIZE_DEFAULT (((U32)1 << ZSTD_WINDOWLOG_DEFAULTMAX) + 1)
#endif
@@ -43,6 +45,7 @@
* Dependencies
*********************************************************/
#include <string.h> /* memcpy, memmove, memset */
+#include "cpu.h"
#include "mem.h" /* low level memory routines */
#define FSE_STATIC_LINKING_ONLY
#include "fse.h"
@@ -80,10 +83,25 @@ typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,
typedef enum { zdss_init=0, zdss_loadHeader,
zdss_read, zdss_load, zdss_flush } ZSTD_dStreamStage;
+
+typedef struct {
+ U32 fastMode;
+ U32 tableLog;
+} ZSTD_seqSymbol_header;
+
+typedef struct {
+ U16 nextState;
+ BYTE nbAdditionalBits;
+ BYTE nbBits;
+ U32 baseValue;
+} ZSTD_seqSymbol;
+
+#define SEQSYMBOL_TABLE_SIZE(log) (1 + (1 << (log)))
+
typedef struct {
- FSE_DTable LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];
- FSE_DTable OFTable[FSE_DTABLE_SIZE_U32(OffFSELog)];
- FSE_DTable MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)];
+ ZSTD_seqSymbol LLTable[SEQSYMBOL_TABLE_SIZE(LLFSELog)];
+ ZSTD_seqSymbol OFTable[SEQSYMBOL_TABLE_SIZE(OffFSELog)];
+ ZSTD_seqSymbol MLTable[SEQSYMBOL_TABLE_SIZE(MLFSELog)];
HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)]; /* can accommodate HUF_decompress4X */
U32 workspace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
U32 rep[ZSTD_REP_NUM];
@@ -91,9 +109,9 @@ typedef struct {
struct ZSTD_DCtx_s
{
- const FSE_DTable* LLTptr;
- const FSE_DTable* MLTptr;
- const FSE_DTable* OFTptr;
+ const ZSTD_seqSymbol* LLTptr;
+ const ZSTD_seqSymbol* MLTptr;
+ const ZSTD_seqSymbol* OFTptr;
const HUF_DTable* HUFptr;
ZSTD_entropyDTables_t entropy;
const void* previousDstEnd; /* detect continuity */
@@ -116,6 +134,7 @@ struct ZSTD_DCtx_s
size_t litSize;
size_t rleSize;
size_t staticSize;
+ int bmi2; /* == 1 if the CPU supports BMI2 and 0 otherwise. CPU support is determined dynamically once per context lifetime. */
/* streaming */
ZSTD_DDict* ddictLocal;
@@ -173,6 +192,7 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
dctx->inBuffSize = 0;
dctx->outBuffSize = 0;
dctx->streamStage = zdss_init;
+ dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
}
ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
@@ -204,6 +224,7 @@ ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
ZSTD_DCtx* ZSTD_createDCtx(void)
{
+ DEBUGLOG(3, "ZSTD_createDCtx");
return ZSTD_createDCtx_advanced(ZSTD_defaultCMem);
}
@@ -234,8 +255,8 @@ void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
/*-*************************************************************
-* Decompression section
-***************************************************************/
+ * Frame header decoding
+ ***************************************************************/
/*! ZSTD_isFrame() :
* Tells if the content of `buffer` starts with a valid Frame Identifier.
@@ -257,7 +278,7 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size)
/** ZSTD_frameHeaderSize_internal() :
* srcSize must be large enough to reach header size fields.
- * note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless
+ * note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless.
* @return : size of the Frame Header
* or an error code, which can be tested with ZSTD_isError() */
static size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZSTD_format_e format)
@@ -480,6 +501,10 @@ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t he
}
+/*-*************************************************************
+ * Block decoding
+ ***************************************************************/
+
/*! ZSTD_getcBlockSize() :
* Provides the size of compressed block from block header `src` */
size_t ZSTD_getcBlockSize(const void* src, size_t srcSize,
@@ -566,13 +591,13 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
if (HUF_isError((litEncType==set_repeat) ?
( singleStream ?
- HUF_decompress1X_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->HUFptr) :
- HUF_decompress4X_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->HUFptr) ) :
+ HUF_decompress1X_usingDTable_bmi2(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->HUFptr, dctx->bmi2) :
+ HUF_decompress4X_usingDTable_bmi2(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->HUFptr, dctx->bmi2) ) :
( singleStream ?
- HUF_decompress1X2_DCtx_wksp(dctx->entropy.hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize,
- dctx->entropy.workspace, sizeof(dctx->entropy.workspace)) :
- HUF_decompress4X_hufOnly_wksp(dctx->entropy.hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize,
- dctx->entropy.workspace, sizeof(dctx->entropy.workspace)))))
+ HUF_decompress1X2_DCtx_wksp_bmi2(dctx->entropy.hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize,
+ dctx->entropy.workspace, sizeof(dctx->entropy.workspace), dctx->bmi2) :
+ HUF_decompress4X_hufOnly_wksp_bmi2(dctx->entropy.hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize,
+ dctx->entropy.workspace, sizeof(dctx->entropy.workspace), dctx->bmi2))))
return ERROR(corruption_detected);
dctx->litPtr = dctx->litBuffer;
@@ -647,115 +672,268 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
}
}
-
-typedef union {
- FSE_decode_t realData;
- U32 alignedBy4;
-} FSE_decode_t4;
+/* Default FSE distribution tables.
+ * These are pre-calculated FSE decoding tables using default distributions as defined in specification :
+ * https://github.com/facebook/zstd/blob/master/doc/zstd_compression_format.md#default-distributions
+ * They were generated programmatically with following method :
+ * - start from default distributions, present in /lib/common/zstd_internal.h
+ * - generate tables normally, using ZSTD_buildFSETable()
+ * - printout the content of tables
+ * - pretify output, report below, test with fuzzer to ensure it's correct */
/* Default FSE distribution table for Literal Lengths */
-static const FSE_decode_t4 LL_defaultDTable[(1<<LL_DEFAULTNORMLOG)+1] = {
- { { LL_DEFAULTNORMLOG, 1, 1 } }, /* header : tableLog, fastMode, fastMode */
- /* base, symbol, bits */
- { { 0, 0, 4 } }, { { 16, 0, 4 } }, { { 32, 1, 5 } }, { { 0, 3, 5 } },
- { { 0, 4, 5 } }, { { 0, 6, 5 } }, { { 0, 7, 5 } }, { { 0, 9, 5 } },
- { { 0, 10, 5 } }, { { 0, 12, 5 } }, { { 0, 14, 6 } }, { { 0, 16, 5 } },
- { { 0, 18, 5 } }, { { 0, 19, 5 } }, { { 0, 21, 5 } }, { { 0, 22, 5 } },
- { { 0, 24, 5 } }, { { 32, 25, 5 } }, { { 0, 26, 5 } }, { { 0, 27, 6 } },
- { { 0, 29, 6 } }, { { 0, 31, 6 } }, { { 32, 0, 4 } }, { { 0, 1, 4 } },
- { { 0, 2, 5 } }, { { 32, 4, 5 } }, { { 0, 5, 5 } }, { { 32, 7, 5 } },
- { { 0, 8, 5 } }, { { 32, 10, 5 } }, { { 0, 11, 5 } }, { { 0, 13, 6 } },
- { { 32, 16, 5 } }, { { 0, 17, 5 } }, { { 32, 19, 5 } }, { { 0, 20, 5 } },
- { { 32, 22, 5 } }, { { 0, 23, 5 } }, { { 0, 25, 4 } }, { { 16, 25, 4 } },
- { { 32, 26, 5 } }, { { 0, 28, 6 } }, { { 0, 30, 6 } }, { { 48, 0, 4 } },
- { { 16, 1, 4 } }, { { 32, 2, 5 } }, { { 32, 3, 5 } }, { { 32, 5, 5 } },
- { { 32, 6, 5 } }, { { 32, 8, 5 } }, { { 32, 9, 5 } }, { { 32, 11, 5 } },
- { { 32, 12, 5 } }, { { 0, 15, 6 } }, { { 32, 17, 5 } }, { { 32, 18, 5 } },
- { { 32, 20, 5 } }, { { 32, 21, 5 } }, { { 32, 23, 5 } }, { { 32, 24, 5 } },
- { { 0, 35, 6 } }, { { 0, 34, 6 } }, { { 0, 33, 6 } }, { { 0, 32, 6 } },
+static const ZSTD_seqSymbol LL_defaultDTable[(1<<LL_DEFAULTNORMLOG)+1] = {
+ { 1, 1, 1, LL_DEFAULTNORMLOG}, /* header : fastMode, tableLog */
+ /* nextState, nbAddBits, nbBits, baseVal */
+ { 0, 0, 4, 0}, { 16, 0, 4, 0},
+ { 32, 0, 5, 1}, { 0, 0, 5, 3},
+ { 0, 0, 5, 4}, { 0, 0, 5, 6},
+ { 0, 0, 5, 7}, { 0, 0, 5, 9},
+ { 0, 0, 5, 10}, { 0, 0, 5, 12},
+ { 0, 0, 6, 14}, { 0, 1, 5, 16},
+ { 0, 1, 5, 20}, { 0, 1, 5, 22},
+ { 0, 2, 5, 28}, { 0, 3, 5, 32},
+ { 0, 4, 5, 48}, { 32, 6, 5, 64},
+ { 0, 7, 5, 128}, { 0, 8, 6, 256},
+ { 0, 10, 6, 1024}, { 0, 12, 6, 4096},
+ { 32, 0, 4, 0}, { 0, 0, 4, 1},
+ { 0, 0, 5, 2}, { 32, 0, 5, 4},
+ { 0, 0, 5, 5}, { 32, 0, 5, 7},
+ { 0, 0, 5, 8}, { 32, 0, 5, 10},
+ { 0, 0, 5, 11}, { 0, 0, 6, 13},
+ { 32, 1, 5, 16}, { 0, 1, 5, 18},
+ { 32, 1, 5, 22}, { 0, 2, 5, 24},
+ { 32, 3, 5, 32}, { 0, 3, 5, 40},
+ { 0, 6, 4, 64}, { 16, 6, 4, 64},
+ { 32, 7, 5, 128}, { 0, 9, 6, 512},
+ { 0, 11, 6, 2048}, { 48, 0, 4, 0},
+ { 16, 0, 4, 1}, { 32, 0, 5, 2},
+ { 32, 0, 5, 3}, { 32, 0, 5, 5},
+ { 32, 0, 5, 6}, { 32, 0, 5, 8},
+ { 32, 0, 5, 9}, { 32, 0, 5, 11},
+ { 32, 0, 5, 12}, { 0, 0, 6, 15},
+ { 32, 1, 5, 18}, { 32, 1, 5, 20},
+ { 32, 2, 5, 24}, { 32, 2, 5, 28},
+ { 32, 3, 5, 40}, { 32, 4, 5, 48},
+ { 0, 16, 6,65536}, { 0, 15, 6,32768},
+ { 0, 14, 6,16384}, { 0, 13, 6, 8192},
}; /* LL_defaultDTable */
+/* Default FSE distribution table for Offset Codes */
+static const ZSTD_seqSymbol OF_defaultDTable[(1<<OF_DEFAULTNORMLOG)+1] = {
+ { 1, 1, 1, OF_DEFAULTNORMLOG}, /* header : fastMode, tableLog */
+ /* nextState, nbAddBits, nbBits, baseVal */
+ { 0, 0, 5, 0}, { 0, 6, 4, 61},
+ { 0, 9, 5, 509}, { 0, 15, 5,32765},
+ { 0, 21, 5,2097149}, { 0, 3, 5, 5},
+ { 0, 7, 4, 125}, { 0, 12, 5, 4093},
+ { 0, 18, 5,262141}, { 0, 23, 5,8388605},
+ { 0, 5, 5, 29}, { 0, 8, 4, 253},
+ { 0, 14, 5,16381}, { 0, 20, 5,1048573},
+ { 0, 2, 5, 1}, { 16, 7, 4, 125},
+ { 0, 11, 5, 2045}, { 0, 17, 5,131069},
+ { 0, 22, 5,4194301}, { 0, 4, 5, 13},
+ { 16, 8, 4, 253}, { 0, 13, 5, 8189},
+ { 0, 19, 5,524285}, { 0, 1, 5, 1},
+ { 16, 6, 4, 61}, { 0, 10, 5, 1021},
+ { 0, 16, 5,65533}, { 0, 28, 5,268435453},
+ { 0, 27, 5,134217725}, { 0, 26, 5,67108861},
+ { 0, 25, 5,33554429}, { 0, 24, 5,16777213},
+}; /* OF_defaultDTable */
+
+
/* Default FSE distribution table for Match Lengths */
-static const FSE_decode_t4 ML_defaultDTable[(1<<ML_DEFAULTNORMLOG)+1] = {
- { { ML_DEFAULTNORMLOG, 1, 1 } }, /* header : tableLog, fastMode, fastMode */
- /* base, symbol, bits */
- { { 0, 0, 6 } }, { { 0, 1, 4 } }, { { 32, 2, 5 } }, { { 0, 3, 5 } },
- { { 0, 5, 5 } }, { { 0, 6, 5 } }, { { 0, 8, 5 } }, { { 0, 10, 6 } },
- { { 0, 13, 6 } }, { { 0, 16, 6 } }, { { 0, 19, 6 } }, { { 0, 22, 6 } },
- { { 0, 25, 6 } }, { { 0, 28, 6 } }, { { 0, 31, 6 } }, { { 0, 33, 6 } },
- { { 0, 35, 6 } }, { { 0, 37, 6 } }, { { 0, 39, 6 } }, { { 0, 41, 6 } },
- { { 0, 43, 6 } }, { { 0, 45, 6 } }, { { 16, 1, 4 } }, { { 0, 2, 4 } },
- { { 32, 3, 5 } }, { { 0, 4, 5 } }, { { 32, 6, 5 } }, { { 0, 7, 5 } },
- { { 0, 9, 6 } }, { { 0, 12, 6 } }, { { 0, 15, 6 } }, { { 0, 18, 6 } },
- { { 0, 21, 6 } }, { { 0, 24, 6 } }, { { 0, 27, 6 } }, { { 0, 30, 6 } },
- { { 0, 32, 6 } }, { { 0, 34, 6 } }, { { 0, 36, 6 } }, { { 0, 38, 6 } },
- { { 0, 40, 6 } }, { { 0, 42, 6 } }, { { 0, 44, 6 } }, { { 32, 1, 4 } },
- { { 48, 1, 4 } }, { { 16, 2, 4 } }, { { 32, 4, 5 } }, { { 32, 5, 5 } },
- { { 32, 7, 5 } }, { { 32, 8, 5 } }, { { 0, 11, 6 } }, { { 0, 14, 6 } },
- { { 0, 17, 6 } }, { { 0, 20, 6 } }, { { 0, 23, 6 } }, { { 0, 26, 6 } },
- { { 0, 29, 6 } }, { { 0, 52, 6 } }, { { 0, 51, 6 } }, { { 0, 50, 6 } },
- { { 0, 49, 6 } }, { { 0, 48, 6 } }, { { 0, 47, 6 } }, { { 0, 46, 6 } },
+static const ZSTD_seqSymbol ML_defaultDTable[(1<<ML_DEFAULTNORMLOG)+1] = {
+ { 1, 1, 1, ML_DEFAULTNORMLOG}, /* header : fastMode, tableLog */
+ /* nextState, nbAddBits, nbBits, baseVal */
+ { 0, 0, 6, 3}, { 0, 0, 4, 4},
+ { 32, 0, 5, 5}, { 0, 0, 5, 6},
+ { 0, 0, 5, 8}, { 0, 0, 5, 9},
+ { 0, 0, 5, 11}, { 0, 0, 6, 13},
+ { 0, 0, 6, 16}, { 0, 0, 6, 19},
+ { 0, 0, 6, 22}, { 0, 0, 6, 25},
+ { 0, 0, 6, 28}, { 0, 0, 6, 31},
+ { 0, 0, 6, 34}, { 0, 1, 6, 37},
+ { 0, 1, 6, 41}, { 0, 2, 6, 47},
+ { 0, 3, 6, 59}, { 0, 4, 6, 83},
+ { 0, 7, 6, 131}, { 0, 9, 6, 515},
+ { 16, 0, 4, 4}, { 0, 0, 4, 5},
+ { 32, 0, 5, 6}, { 0, 0, 5, 7},
+ { 32, 0, 5, 9}, { 0, 0, 5, 10},
+ { 0, 0, 6, 12}, { 0, 0, 6, 15},
+ { 0, 0, 6, 18}, { 0, 0, 6, 21},
+ { 0, 0, 6, 24}, { 0, 0, 6, 27},
+ { 0, 0, 6, 30}, { 0, 0, 6, 33},
+ { 0, 1, 6, 35}, { 0, 1, 6, 39},
+ { 0, 2, 6, 43}, { 0, 3, 6, 51},
+ { 0, 4, 6, 67}, { 0, 5, 6, 99},
+ { 0, 8, 6, 259}, { 32, 0, 4, 4},
+ { 48, 0, 4, 4}, { 16, 0, 4, 5},
+ { 32, 0, 5, 7}, { 32, 0, 5, 8},
+ { 32, 0, 5, 10}, { 32, 0, 5, 11},
+ { 0, 0, 6, 14}, { 0, 0, 6, 17},
+ { 0, 0, 6, 20}, { 0, 0, 6, 23},
+ { 0, 0, 6, 26}, { 0, 0, 6, 29},
+ { 0, 0, 6, 32}, { 0, 16, 6,65539},
+ { 0, 15, 6,32771}, { 0, 14, 6,16387},
+ { 0, 13, 6, 8195}, { 0, 12, 6, 4099},
+ { 0, 11, 6, 2051}, { 0, 10, 6, 1027},
}; /* ML_defaultDTable */
-/* Default FSE distribution table for Offset Codes */
-static const FSE_decode_t4 OF_defaultDTable[(1<<OF_DEFAULTNORMLOG)+1] = {
- { { OF_DEFAULTNORMLOG, 1, 1 } }, /* header : tableLog, fastMode, fastMode */
- /* base, symbol, bits */
- { { 0, 0, 5 } }, { { 0, 6, 4 } },
- { { 0, 9, 5 } }, { { 0, 15, 5 } },
- { { 0, 21, 5 } }, { { 0, 3, 5 } },
- { { 0, 7, 4 } }, { { 0, 12, 5 } },
- { { 0, 18, 5 } }, { { 0, 23, 5 } },
- { { 0, 5, 5 } }, { { 0, 8, 4 } },
- { { 0, 14, 5 } }, { { 0, 20, 5 } },
- { { 0, 2, 5 } }, { { 16, 7, 4 } },
- { { 0, 11, 5 } }, { { 0, 17, 5 } },
- { { 0, 22, 5 } }, { { 0, 4, 5 } },
- { { 16, 8, 4 } }, { { 0, 13, 5 } },
- { { 0, 19, 5 } }, { { 0, 1, 5 } },
- { { 16, 6, 4 } }, { { 0, 10, 5 } },
- { { 0, 16, 5 } }, { { 0, 28, 5 } },
- { { 0, 27, 5 } }, { { 0, 26, 5 } },
- { { 0, 25, 5 } }, { { 0, 24, 5 } },
-}; /* OF_defaultDTable */
+
+static void ZSTD_buildSeqTable_rle(ZSTD_seqSymbol* dt, U32 baseValue, U32 nbAddBits)
+{
+ void* ptr = dt;
+ ZSTD_seqSymbol_header* const DTableH = (ZSTD_seqSymbol_header*)ptr;
+ ZSTD_seqSymbol* const cell = dt + 1;
+
+ DTableH->tableLog = 0;
+ DTableH->fastMode = 0;
+
+ cell->nbBits = 0;
+ cell->nextState = 0;
+ assert(nbAddBits < 255);
+ cell->nbAdditionalBits = (BYTE)nbAddBits;
+ cell->baseValue = baseValue;
+}
+
+
+/* ZSTD_buildFSETable() :
+ * generate FSE decoding table for one symbol (ll, ml or off) */
+static void
+ZSTD_buildFSETable(ZSTD_seqSymbol* dt,
+ const short* normalizedCounter, unsigned maxSymbolValue,
+ const U32* baseValue, const U32* nbAdditionalBits,
+ unsigned tableLog)
+{
+ ZSTD_seqSymbol* const tableDecode = dt+1;
+ U16 symbolNext[MaxSeq+1];
+
+ U32 const maxSV1 = maxSymbolValue + 1;
+ U32 const tableSize = 1 << tableLog;
+ U32 highThreshold = tableSize-1;
+
+ /* Sanity Checks */
+ assert(maxSymbolValue <= MaxSeq);
+ assert(tableLog <= MaxFSELog);
+
+ /* Init, lay down lowprob symbols */
+ { ZSTD_seqSymbol_header DTableH;
+ DTableH.tableLog = tableLog;
+ DTableH.fastMode = 1;
+ { S16 const largeLimit= (S16)(1 << (tableLog-1));
+ U32 s;
+ for (s=0; s<maxSV1; s++) {
+ if (normalizedCounter[s]==-1) {
+ tableDecode[highThreshold--].baseValue = s;
+ symbolNext[s] = 1;
+ } else {
+ if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0;
+ symbolNext[s] = normalizedCounter[s];
+ } } }
+ memcpy(dt, &DTableH, sizeof(DTableH));
+ }
+
+ /* Spread symbols */
+ { U32 const tableMask = tableSize-1;
+ U32 const step = FSE_TABLESTEP(tableSize);
+ U32 s, position = 0;
+ for (s=0; s<maxSV1; s++) {
+ int i;
+ for (i=0; i<normalizedCounter[s]; i++) {
+ tableDecode[position].baseValue = s;
+ position = (position + step) & tableMask;
+ while (position > highThreshold) position = (position + step) & tableMask; /* lowprob area */
+ } }
+ assert(position == 0); /* position must reach all cells once, otherwise normalizedCounter is incorrect */
+ }
+
+ /* Build Decoding table */
+ { U32 u;
+ for (u=0; u<tableSize; u++) {
+ U32 const symbol = tableDecode[u].baseValue;
+ U32 const nextState = symbolNext[symbol]++;
+ tableDecode[u].nbBits = (BYTE) (tableLog - BIT_highbit32(nextState) );
+ tableDecode[u].nextState = (U16) ( (nextState << tableDecode[u].nbBits) - tableSize);
+ assert(nbAdditionalBits[symbol] < 255);
+ tableDecode[u].nbAdditionalBits = (BYTE)nbAdditionalBits[symbol];
+ tableDecode[u].baseValue = baseValue[symbol];
+ } }
+}
+
/*! ZSTD_buildSeqTable() :
* @return : nb bytes read from src,
- * or an error code if it fails, testable with ZSTD_isError()
- */
-static size_t ZSTD_buildSeqTable(FSE_DTable* DTableSpace, const FSE_DTable** DTablePtr,
+ * or an error code if it fails */
+static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymbol** DTablePtr,
symbolEncodingType_e type, U32 max, U32 maxLog,
const void* src, size_t srcSize,
- const FSE_decode_t4* defaultTable, U32 flagRepeatTable)
+ const U32* baseValue, const U32* nbAdditionalBits,
+ const ZSTD_seqSymbol* defaultTable, U32 flagRepeatTable)
{
- const void* const tmpPtr = defaultTable; /* bypass strict aliasing */
switch(type)
{
case set_rle :
if (!srcSize) return ERROR(srcSize_wrong);
if ( (*(const BYTE*)src) > max) return ERROR(corruption_detected);
- FSE_buildDTable_rle(DTableSpace, *(const BYTE*)src);
+ { U32 const symbol = *(const BYTE*)src;
+ U32 const baseline = baseValue[symbol];
+ U32 const nbBits = nbAdditionalBits[symbol];
+ ZSTD_buildSeqTable_rle(DTableSpace, baseline, nbBits);
+ }
*DTablePtr = DTableSpace;
return 1;
case set_basic :
- *DTablePtr = (const FSE_DTable*)tmpPtr;
+ *DTablePtr = defaultTable;
return 0;
case set_repeat:
if (!flagRepeatTable) return ERROR(corruption_detected);
return 0;
- default : /* impossible */
case set_compressed :
{ U32 tableLog;
S16 norm[MaxSeq+1];
size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize);
if (FSE_isError(headerSize)) return ERROR(corruption_detected);
if (tableLog > maxLog) return ERROR(corruption_detected);
- FSE_buildDTable(DTableSpace, norm, max, tableLog);
+ ZSTD_buildFSETable(DTableSpace, norm, max, baseValue, nbAdditionalBits, tableLog);
*DTablePtr = DTableSpace;
return headerSize;
- } }
+ }
+ default : /* impossible */
+ assert(0);
+ return ERROR(GENERIC);
+ }
}
+static const U32 LL_base[MaxLL+1] = {
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 18, 20, 22, 24, 28, 32, 40,
+ 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,
+ 0x2000, 0x4000, 0x8000, 0x10000 };
+
+static const U32 OF_base[MaxOff+1] = {
+ 0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D,
+ 0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD,
+ 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,
+ 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD, 0x1FFFFFFD, 0x3FFFFFFD, 0x7FFFFFFD };
+
+static const U32 OF_bits[MaxOff+1] = {
+ 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 };
+
+static const U32 ML_base[MaxML+1] = {
+ 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, 37, 39, 41, 43, 47, 51, 59,
+ 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803,
+ 0x1003, 0x2003, 0x4003, 0x8003, 0x10003 };
+
+
size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
const void* src, size_t srcSize)
{
@@ -792,19 +970,27 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
/* Build DTables */
{ size_t const llhSize = ZSTD_buildSeqTable(dctx->entropy.LLTable, &dctx->LLTptr,
LLtype, MaxLL, LLFSELog,
- ip, iend-ip, LL_defaultDTable, dctx->fseEntropy);
+ ip, iend-ip,
+ LL_base, LL_bits,
+ LL_defaultDTable, dctx->fseEntropy);
if (ZSTD_isError(llhSize)) return ERROR(corruption_detected);
ip += llhSize;
}
+
{ size_t const ofhSize = ZSTD_buildSeqTable(dctx->entropy.OFTable, &dctx->OFTptr,
OFtype, MaxOff, OffFSELog,
- ip, iend-ip, OF_defaultDTable, dctx->fseEntropy);
+ ip, iend-ip,
+ OF_base, OF_bits,
+ OF_defaultDTable, dctx->fseEntropy);
if (ZSTD_isError(ofhSize)) return ERROR(corruption_detected);
ip += ofhSize;
}
+
{ size_t const mlhSize = ZSTD_buildSeqTable(dctx->entropy.MLTable, &dctx->MLTptr,
MLtype, MaxML, MLFSELog,
- ip, iend-ip, ML_defaultDTable, dctx->fseEntropy);
+ ip, iend-ip,
+ ML_base, ML_bits,
+ ML_defaultDTable, dctx->fseEntropy);
if (ZSTD_isError(mlhSize)) return ERROR(corruption_detected);
ip += mlhSize;
}
@@ -822,10 +1008,15 @@ typedef struct {
} seq_t;
typedef struct {
+ size_t state;
+ const ZSTD_seqSymbol* table;
+} ZSTD_fseState;
+
+typedef struct {
BIT_DStream_t DStream;
- FSE_DState_t stateLL;
- FSE_DState_t stateOffb;
- FSE_DState_t stateML;
+ ZSTD_fseState stateLL;
+ ZSTD_fseState stateOffb;
+ ZSTD_fseState stateML;
size_t prevOffset[ZSTD_REP_NUM];
const BYTE* prefixStart;
const BYTE* dictEnd;
@@ -880,118 +1071,6 @@ size_t ZSTD_execSequenceLast7(BYTE* op,
}
-typedef enum { ZSTD_lo_isRegularOffset, ZSTD_lo_isLongOffset=1 } ZSTD_longOffset_e;
-
-/* We need to add at most (ZSTD_WINDOWLOG_MAX_32 - 1) bits to read the maximum
- * offset bits. But we can only read at most (STREAM_ACCUMULATOR_MIN_32 - 1)
- * bits before reloading. This value is the maximum number of bytes we read
- * after reloading when we are decoding long offets.
- */
-#define LONG_OFFSETS_MAX_EXTRA_BITS_32 \
- (ZSTD_WINDOWLOG_MAX_32 > STREAM_ACCUMULATOR_MIN_32 \
- ? ZSTD_WINDOWLOG_MAX_32 - STREAM_ACCUMULATOR_MIN_32 \
- : 0)
-
-static seq_t ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets)
-{
- seq_t seq;
-
- U32 const llCode = FSE_peekSymbol(&seqState->stateLL);
- U32 const mlCode = FSE_peekSymbol(&seqState->stateML);
- U32 const ofCode = FSE_peekSymbol(&seqState->stateOffb); /* <= MaxOff, by table construction */
-
- U32 const llBits = LL_bits[llCode];
- U32 const mlBits = ML_bits[mlCode];
- U32 const ofBits = ofCode;
- U32 const totalBits = llBits+mlBits+ofBits;
-
- static const U32 LL_base[MaxLL+1] = {
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 18, 20, 22, 24, 28, 32, 40,
- 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,
- 0x2000, 0x4000, 0x8000, 0x10000 };
-
- static const U32 ML_base[MaxML+1] = {
- 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, 37, 39, 41, 43, 47, 51, 59,
- 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803,
- 0x1003, 0x2003, 0x4003, 0x8003, 0x10003 };
-
- static const U32 OF_base[MaxOff+1] = {
- 0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D,
- 0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD,
- 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,
- 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD, 0x1FFFFFFD, 0x3FFFFFFD, 0x7FFFFFFD };
-
- /* sequence */
- { size_t offset;
- if (!ofCode)
- offset = 0;
- else {
- ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1);
- ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5);
- assert(ofBits <= MaxOff);
- if (MEM_32bits() && longOffsets) {
- U32 const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN_32-1);
- offset = OF_base[ofCode] + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits);
- if (MEM_32bits() || extraBits) BIT_reloadDStream(&seqState->DStream);
- if (extraBits) offset += BIT_readBitsFast(&seqState->DStream, extraBits);
- } else {
- offset = OF_base[ofCode] + BIT_readBitsFast(&seqState->DStream, ofBits); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
- if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);
- }
- }
-
- if (ofCode <= 1) {
- offset += (llCode==0);
- if (offset) {
- size_t temp = (offset==3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset];
- temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */
- if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1];
- seqState->prevOffset[1] = seqState->prevOffset[0];
- seqState->prevOffset[0] = offset = temp;
- } else {
- offset = seqState->prevOffset[0];
- }
- } else {
- seqState->prevOffset[2] = seqState->prevOffset[1];
- seqState->prevOffset[1] = seqState->prevOffset[0];
- seqState->prevOffset[0] = offset;
- }
- seq.offset = offset;
- }
-
- seq.matchLength = ML_base[mlCode]
- + ((mlCode>31) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <= 16 bits */
- if (MEM_32bits() && (mlBits+llBits >= STREAM_ACCUMULATOR_MIN_32-LONG_OFFSETS_MAX_EXTRA_BITS_32))
- BIT_reloadDStream(&seqState->DStream);
- if (MEM_64bits() && (totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog)))
- BIT_reloadDStream(&seqState->DStream);
- /* Verify that there is enough bits to read the rest of the data in 64-bit mode. */
- ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64);
-
- seq.litLength = LL_base[llCode]
- + ((llCode>15) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <= 16 bits */
- if (MEM_32bits())
- BIT_reloadDStream(&seqState->DStream);
-
- DEBUGLOG(6, "seq: litL=%u, matchL=%u, offset=%u",
- (U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset);
-
- /* ANS state update */
- FSE_updateState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */
- FSE_updateState(&seqState->stateML, &seqState->DStream); /* <= 9 bits */
- if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */
- FSE_updateState(&seqState->stateOffb, &seqState->DStream); /* <= 8 bits */
-
- return seq;
-}
-
-
HINT_INLINE
size_t ZSTD_execSequence(BYTE* op,
BYTE* const oend, seq_t sequence,
@@ -1073,10 +1152,199 @@ size_t ZSTD_execSequence(BYTE* op,
}
-static size_t ZSTD_decompressSequences(
- ZSTD_DCtx* dctx,
+HINT_INLINE
+size_t ZSTD_execSequenceLong(BYTE* op,
+ BYTE* const oend, seq_t sequence,
+ const BYTE** litPtr, const BYTE* const litLimit,
+ const BYTE* const prefixStart, const BYTE* const dictStart, const BYTE* const dictEnd)
+{
+ BYTE* const oLitEnd = op + sequence.litLength;
+ size_t const sequenceLength = sequence.litLength + sequence.matchLength;
+ BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
+ BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH;
+ const BYTE* const iLitEnd = *litPtr + sequence.litLength;
+ const BYTE* match = sequence.match;
+
+ /* check */
+ if (oMatchEnd > oend) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
+ if (iLitEnd > litLimit) return ERROR(corruption_detected); /* over-read beyond lit buffer */
+ if (oLitEnd > oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, prefixStart, dictStart, dictEnd);
+
+ /* copy Literals */
+ ZSTD_copy8(op, *litPtr); /* note : op <= oLitEnd <= oend_w == oend - 8 */
+ if (sequence.litLength > 8)
+ ZSTD_wildcopy(op+8, (*litPtr)+8, sequence.litLength - 8); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
+ op = oLitEnd;
+ *litPtr = iLitEnd; /* update for next sequence */
+
+ /* copy Match */
+ if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {
+ /* offset beyond prefix */
+ if (sequence.offset > (size_t)(oLitEnd - dictStart)) return ERROR(corruption_detected);
+ if (match + sequence.matchLength <= dictEnd) {
+ memmove(oLitEnd, match, sequence.matchLength);
+ return sequenceLength;
+ }
+ /* span extDict & currentPrefixSegment */
+ { size_t const length1 = dictEnd - match;
+ memmove(oLitEnd, match, length1);
+ op = oLitEnd + length1;
+ sequence.matchLength -= length1;
+ match = prefixStart;
+ if (op > oend_w || sequence.matchLength < MINMATCH) {
+ U32 i;
+ for (i = 0; i < sequence.matchLength; ++i) op[i] = match[i];
+ return sequenceLength;
+ }
+ } }
+ assert(op <= oend_w);
+ assert(sequence.matchLength >= MINMATCH);
+
+ /* match within prefix */
+ if (sequence.offset < 8) {
+ /* close range match, overlap */
+ static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
+ static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */
+ int const sub2 = dec64table[sequence.offset];
+ op[0] = match[0];
+ op[1] = match[1];
+ op[2] = match[2];
+ op[3] = match[3];
+ match += dec32table[sequence.offset];
+ ZSTD_copy4(op+4, match);
+ match -= sub2;
+ } else {
+ ZSTD_copy8(op, match);
+ }
+ op += 8; match += 8;
+
+ if (oMatchEnd > oend-(16-MINMATCH)) {
+ if (op < oend_w) {
+ ZSTD_wildcopy(op, match, oend_w - op);
+ match += oend_w - op;
+ op = oend_w;
+ }
+ while (op < oMatchEnd) *op++ = *match++;
+ } else {
+ ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8); /* works even if matchLength < 8 */
+ }
+ return sequenceLength;
+}
+
+static void
+ZSTD_initFseState(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD, const ZSTD_seqSymbol* dt)
+{
+ const void* ptr = dt;
+ const ZSTD_seqSymbol_header* const DTableH = (const ZSTD_seqSymbol_header*)ptr;
+ DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog);
+ DEBUGLOG(6, "ZSTD_initFseState : val=%u using %u bits",
+ (U32)DStatePtr->state, DTableH->tableLog);
+ BIT_reloadDStream(bitD);
+ DStatePtr->table = dt + 1;
+}
+
+FORCE_INLINE_TEMPLATE void
+ZSTD_updateFseState(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD)
+{
+ ZSTD_seqSymbol const DInfo = DStatePtr->table[DStatePtr->state];
+ U32 const nbBits = DInfo.nbBits;
+ size_t const lowBits = BIT_readBits(bitD, nbBits);
+ DStatePtr->state = DInfo.nextState + lowBits;
+}
+
+/* We need to add at most (ZSTD_WINDOWLOG_MAX_32 - 1) bits to read the maximum
+ * offset bits. But we can only read at most (STREAM_ACCUMULATOR_MIN_32 - 1)
+ * bits before reloading. This value is the maximum number of bytes we read
+ * after reloading when we are decoding long offets.
+ */
+#define LONG_OFFSETS_MAX_EXTRA_BITS_32 \
+ (ZSTD_WINDOWLOG_MAX_32 > STREAM_ACCUMULATOR_MIN_32 \
+ ? ZSTD_WINDOWLOG_MAX_32 - STREAM_ACCUMULATOR_MIN_32 \
+ : 0)
+
+typedef enum { ZSTD_lo_isRegularOffset, ZSTD_lo_isLongOffset=1 } ZSTD_longOffset_e;
+
+FORCE_INLINE_TEMPLATE seq_t
+ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets)
+{
+ seq_t seq;
+ U32 const llBits = seqState->stateLL.table[seqState->stateLL.state].nbAdditionalBits;
+ U32 const mlBits = seqState->stateML.table[seqState->stateML.state].nbAdditionalBits;
+ U32 const ofBits = seqState->stateOffb.table[seqState->stateOffb.state].nbAdditionalBits;
+ U32 const totalBits = llBits+mlBits+ofBits;
+ U32 const llBase = seqState->stateLL.table[seqState->stateLL.state].baseValue;
+ U32 const mlBase = seqState->stateML.table[seqState->stateML.state].baseValue;
+ U32 const ofBase = seqState->stateOffb.table[seqState->stateOffb.state].baseValue;
+
+ /* sequence */
+ { size_t offset;
+ if (!ofBits)
+ offset = 0;
+ else {
+ ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1);
+ ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5);
+ assert(ofBits <= MaxOff);
+ if (MEM_32bits() && longOffsets && (ofBits >= STREAM_ACCUMULATOR_MIN_32)) {
+ U32 const extraBits = ofBits - MIN(ofBits, 32 - seqState->DStream.bitsConsumed);
+ offset = ofBase + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits);
+ BIT_reloadDStream(&seqState->DStream);
+ if (extraBits) offset += BIT_readBitsFast(&seqState->DStream, extraBits);
+ assert(extraBits <= LONG_OFFSETS_MAX_EXTRA_BITS_32); /* to avoid another reload */
+ } else {
+ offset = ofBase + BIT_readBitsFast(&seqState->DStream, ofBits/*>0*/); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
+ if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);
+ }
+ }
+
+ if (ofBits <= 1) {
+ offset += (llBase==0);
+ if (offset) {
+ size_t temp = (offset==3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset];
+ temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */
+ if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1];
+ seqState->prevOffset[1] = seqState->prevOffset[0];
+ seqState->prevOffset[0] = offset = temp;
+ } else { /* offset == 0 */
+ offset = seqState->prevOffset[0];
+ }
+ } else {
+ seqState->prevOffset[2] = seqState->prevOffset[1];
+ seqState->prevOffset[1] = seqState->prevOffset[0];
+ seqState->prevOffset[0] = offset;
+ }
+ seq.offset = offset;
+ }
+
+ seq.matchLength = mlBase
+ + ((mlBits>0) ? BIT_readBitsFast(&seqState->DStream, mlBits/*>0*/) : 0); /* <= 16 bits */
+ if (MEM_32bits() && (mlBits+llBits >= STREAM_ACCUMULATOR_MIN_32-LONG_OFFSETS_MAX_EXTRA_BITS_32))
+ BIT_reloadDStream(&seqState->DStream);
+ if (MEM_64bits() && (totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog)))
+ BIT_reloadDStream(&seqState->DStream);
+ /* Ensure there are enough bits to read the rest of data in 64-bit mode. */
+ ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64);
+
+ seq.litLength = llBase
+ + ((llBits>0) ? BIT_readBitsFast(&seqState->DStream, llBits/*>0*/) : 0); /* <= 16 bits */
+ if (MEM_32bits())
+ BIT_reloadDStream(&seqState->DStream);
+
+ DEBUGLOG(6, "seq: litL=%u, matchL=%u, offset=%u",
+ (U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset);
+
+ /* ANS state update */
+ ZSTD_updateFseState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */
+ ZSTD_updateFseState(&seqState->stateML, &seqState->DStream); /* <= 9 bits */
+ if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */
+ ZSTD_updateFseState(&seqState->stateOffb, &seqState->DStream); /* <= 8 bits */
+
+ return seq;
+}
+
+FORCE_INLINE_TEMPLATE size_t
+ZSTD_decompressSequences_body( ZSTD_DCtx* dctx,
void* dst, size_t maxDstSize,
- const void* seqStart, size_t seqSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
const ZSTD_longOffset_e isLongOffset)
{
const BYTE* ip = (const BYTE*)seqStart;
@@ -1089,26 +1357,17 @@ static size_t ZSTD_decompressSequences(
const BYTE* const base = (const BYTE*) (dctx->base);
const BYTE* const vBase = (const BYTE*) (dctx->vBase);
const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
- int nbSeq;
DEBUGLOG(5, "ZSTD_decompressSequences");
- /* Build Decoding Tables */
- { size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, seqSize);
- DEBUGLOG(5, "ZSTD_decodeSeqHeaders: size=%u, nbSeq=%i",
- (U32)seqHSize, nbSeq);
- if (ZSTD_isError(seqHSize)) return seqHSize;
- ip += seqHSize;
- }
-
/* Regen sequences */
if (nbSeq) {
seqState_t seqState;
dctx->fseEntropy = 1;
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend-ip), corruption_detected);
- FSE_initDState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
- FSE_initDState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
- FSE_initDState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
+ ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
+ ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
+ ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && nbSeq ; ) {
nbSeq--;
@@ -1120,7 +1379,7 @@ static size_t ZSTD_decompressSequences(
} }
/* check if reached exact end */
- DEBUGLOG(5, "after decode loop, remaining nbSeq : %i", nbSeq);
+ DEBUGLOG(5, "ZSTD_decompressSequences: after decode loop, remaining nbSeq : %i", nbSeq);
if (nbSeq) return ERROR(corruption_detected);
/* save reps for next block */
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }
@@ -1136,46 +1395,32 @@ static size_t ZSTD_decompressSequences(
return op-ostart;
}
-
-HINT_INLINE
-seq_t ZSTD_decodeSequenceLong(seqState_t* seqState, ZSTD_longOffset_e const longOffsets)
+static size_t
+ZSTD_decompressSequences_default(ZSTD_DCtx* dctx,
+ void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset)
{
- seq_t seq;
+ return ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
+}
- U32 const llCode = FSE_peekSymbol(&seqState->stateLL);
- U32 const mlCode = FSE_peekSymbol(&seqState->stateML);
- U32 const ofCode = FSE_peekSymbol(&seqState->stateOffb); /* <= MaxOff, by table construction */
- U32 const llBits = LL_bits[llCode];
- U32 const mlBits = ML_bits[mlCode];
- U32 const ofBits = ofCode;
- U32 const totalBits = llBits+mlBits+ofBits;
- static const U32 LL_base[MaxLL+1] = {
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 18, 20, 22, 24, 28, 32, 40,
- 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,
- 0x2000, 0x4000, 0x8000, 0x10000 };
-
- static const U32 ML_base[MaxML+1] = {
- 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, 37, 39, 41, 43, 47, 51, 59,
- 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803,
- 0x1003, 0x2003, 0x4003, 0x8003, 0x10003 };
-
- static const U32 OF_base[MaxOff+1] = {
- 0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D,
- 0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD,
- 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,
- 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD, 0x1FFFFFFD, 0x3FFFFFFD, 0x7FFFFFFD };
+FORCE_INLINE_TEMPLATE seq_t
+ZSTD_decodeSequenceLong(seqState_t* seqState, ZSTD_longOffset_e const longOffsets)
+{
+ seq_t seq;
+ U32 const llBits = seqState->stateLL.table[seqState->stateLL.state].nbAdditionalBits;
+ U32 const mlBits = seqState->stateML.table[seqState->stateML.state].nbAdditionalBits;
+ U32 const ofBits = seqState->stateOffb.table[seqState->stateOffb.state].nbAdditionalBits;
+ U32 const totalBits = llBits+mlBits+ofBits;
+ U32 const llBase = seqState->stateLL.table[seqState->stateLL.state].baseValue;
+ U32 const mlBase = seqState->stateML.table[seqState->stateML.state].baseValue;
+ U32 const ofBase = seqState->stateOffb.table[seqState->stateOffb.state].baseValue;
/* sequence */
{ size_t offset;
- if (!ofCode)
+ if (!ofBits)
offset = 0;
else {
ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1);
@@ -1183,17 +1428,17 @@ seq_t ZSTD_decodeSequenceLong(seqState_t* seqState, ZSTD_longOffset_e const long
assert(ofBits <= MaxOff);
if (MEM_32bits() && longOffsets) {
U32 const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN_32-1);
- offset = OF_base[ofCode] + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits);
+ offset = ofBase + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits);
if (MEM_32bits() || extraBits) BIT_reloadDStream(&seqState->DStream);
if (extraBits) offset += BIT_readBitsFast(&seqState->DStream, extraBits);
} else {
- offset = OF_base[ofCode] + BIT_readBitsFast(&seqState->DStream, ofBits); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
+ offset = ofBase + BIT_readBitsFast(&seqState->DStream, ofBits); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);
}
}
- if (ofCode <= 1) {
- offset += (llCode==0);
+ if (ofBits <= 1) {
+ offset += (llBase==0);
if (offset) {
size_t temp = (offset==3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset];
temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */
@@ -1211,7 +1456,7 @@ seq_t ZSTD_decodeSequenceLong(seqState_t* seqState, ZSTD_longOffset_e const long
seq.offset = offset;
}
- seq.matchLength = ML_base[mlCode] + ((mlCode>31) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <= 16 bits */
+ seq.matchLength = mlBase + ((mlBits>0) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <= 16 bits */
if (MEM_32bits() && (mlBits+llBits >= STREAM_ACCUMULATOR_MIN_32-LONG_OFFSETS_MAX_EXTRA_BITS_32))
BIT_reloadDStream(&seqState->DStream);
if (MEM_64bits() && (totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog)))
@@ -1219,7 +1464,7 @@ seq_t ZSTD_decodeSequenceLong(seqState_t* seqState, ZSTD_longOffset_e const long
/* Verify that there is enough bits to read the rest of the data in 64-bit mode. */
ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64);
- seq.litLength = LL_base[llCode] + ((llCode>15) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <= 16 bits */
+ seq.litLength = llBase + ((llBits>0) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <= 16 bits */
if (MEM_32bits())
BIT_reloadDStream(&seqState->DStream);
@@ -1231,98 +1476,19 @@ seq_t ZSTD_decodeSequenceLong(seqState_t* seqState, ZSTD_longOffset_e const long
}
/* ANS state update */
- FSE_updateState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */
- FSE_updateState(&seqState->stateML, &seqState->DStream); /* <= 9 bits */
+ ZSTD_updateFseState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */
+ ZSTD_updateFseState(&seqState->stateML, &seqState->DStream); /* <= 9 bits */
if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */
- FSE_updateState(&seqState->stateOffb, &seqState->DStream); /* <= 8 bits */
+ ZSTD_updateFseState(&seqState->stateOffb, &seqState->DStream); /* <= 8 bits */
return seq;
}
-
-HINT_INLINE
-size_t ZSTD_execSequenceLong(BYTE* op,
- BYTE* const oend, seq_t sequence,
- const BYTE** litPtr, const BYTE* const litLimit,
- const BYTE* const prefixStart, const BYTE* const dictStart, const BYTE* const dictEnd)
-{
- BYTE* const oLitEnd = op + sequence.litLength;
- size_t const sequenceLength = sequence.litLength + sequence.matchLength;
- BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
- BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH;
- const BYTE* const iLitEnd = *litPtr + sequence.litLength;
- const BYTE* match = sequence.match;
-
- /* check */
- if (oMatchEnd > oend) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
- if (iLitEnd > litLimit) return ERROR(corruption_detected); /* over-read beyond lit buffer */
- if (oLitEnd > oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, prefixStart, dictStart, dictEnd);
-
- /* copy Literals */
- ZSTD_copy8(op, *litPtr); /* note : op <= oLitEnd <= oend_w == oend - 8 */
- if (sequence.litLength > 8)
- ZSTD_wildcopy(op+8, (*litPtr)+8, sequence.litLength - 8); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
- op = oLitEnd;
- *litPtr = iLitEnd; /* update for next sequence */
-
- /* copy Match */
- if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {
- /* offset beyond prefix */
- if (sequence.offset > (size_t)(oLitEnd - dictStart)) return ERROR(corruption_detected);
- if (match + sequence.matchLength <= dictEnd) {
- memmove(oLitEnd, match, sequence.matchLength);
- return sequenceLength;
- }
- /* span extDict & currentPrefixSegment */
- { size_t const length1 = dictEnd - match;
- memmove(oLitEnd, match, length1);
- op = oLitEnd + length1;
- sequence.matchLength -= length1;
- match = prefixStart;
- if (op > oend_w || sequence.matchLength < MINMATCH) {
- U32 i;
- for (i = 0; i < sequence.matchLength; ++i) op[i] = match[i];
- return sequenceLength;
- }
- } }
- assert(op <= oend_w);
- assert(sequence.matchLength >= MINMATCH);
-
- /* match within prefix */
- if (sequence.offset < 8) {
- /* close range match, overlap */
- static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
- static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */
- int const sub2 = dec64table[sequence.offset];
- op[0] = match[0];
- op[1] = match[1];
- op[2] = match[2];
- op[3] = match[3];
- match += dec32table[sequence.offset];
- ZSTD_copy4(op+4, match);
- match -= sub2;
- } else {
- ZSTD_copy8(op, match);
- }
- op += 8; match += 8;
-
- if (oMatchEnd > oend-(16-MINMATCH)) {
- if (op < oend_w) {
- ZSTD_wildcopy(op, match, oend_w - op);
- match += oend_w - op;
- op = oend_w;
- }
- while (op < oMatchEnd) *op++ = *match++;
- } else {
- ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8); /* works even if matchLength < 8 */
- }
- return sequenceLength;
-}
-
-static size_t ZSTD_decompressSequencesLong(
+FORCE_INLINE_TEMPLATE size_t
+ZSTD_decompressSequencesLong_body(
ZSTD_DCtx* dctx,
void* dst, size_t maxDstSize,
- const void* seqStart, size_t seqSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
const ZSTD_longOffset_e isLongOffset)
{
const BYTE* ip = (const BYTE*)seqStart;
@@ -1335,13 +1501,6 @@ static size_t ZSTD_decompressSequencesLong(
const BYTE* const prefixStart = (const BYTE*) (dctx->base);
const BYTE* const dictStart = (const BYTE*) (dctx->vBase);
const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
- int nbSeq;
-
- /* Build Decoding Tables */
- { size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, seqSize);
- if (ZSTD_isError(seqHSize)) return seqHSize;
- ip += seqHSize;
- }
/* Regen sequences */
if (nbSeq) {
@@ -1358,18 +1517,18 @@ static size_t ZSTD_decompressSequencesLong(
seqState.pos = (size_t)(op-prefixStart);
seqState.dictEnd = dictEnd;
CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend-ip), corruption_detected);
- FSE_initDState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
- FSE_initDState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
- FSE_initDState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
+ ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
+ ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
+ ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
/* prepare in advance */
- for (seqNb=0; (BIT_reloadDStream(&seqState.DStream) <= BIT_DStream_completed) && seqNb<seqAdvance; seqNb++) {
+ for (seqNb=0; (BIT_reloadDStream(&seqState.DStream) <= BIT_DStream_completed) && (seqNb<seqAdvance); seqNb++) {
sequences[seqNb] = ZSTD_decodeSequenceLong(&seqState, isLongOffset);
}
if (seqNb<seqAdvance) return ERROR(corruption_detected);
/* decode and decompress */
- for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && seqNb<nbSeq ; seqNb++) {
+ for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && (seqNb<nbSeq) ; seqNb++) {
seq_t const sequence = ZSTD_decodeSequenceLong(&seqState, isLongOffset);
size_t const oneSeqSize = ZSTD_execSequenceLong(op, oend, sequences[(seqNb-ADVANCED_SEQS) & STOSEQ_MASK], &litPtr, litEnd, prefixStart, dictStart, dictEnd);
if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
@@ -1389,6 +1548,9 @@ static size_t ZSTD_decompressSequencesLong(
/* save reps for next block */
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }
+#undef STORED_SEQS
+#undef STOSEQ_MASK
+#undef ADVANCED_SEQS
}
/* last literal segment */
@@ -1401,6 +1563,96 @@ static size_t ZSTD_decompressSequencesLong(
return op-ostart;
}
+static size_t
+ZSTD_decompressSequencesLong_default(ZSTD_DCtx* dctx,
+ void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset)
+{
+ return ZSTD_decompressSequencesLong_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
+}
+
+
+
+#if DYNAMIC_BMI2
+
+static TARGET_ATTRIBUTE("bmi2") size_t
+ZSTD_decompressSequences_bmi2(ZSTD_DCtx* dctx,
+ void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset)
+{
+ return ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
+}
+
+static TARGET_ATTRIBUTE("bmi2") size_t
+ZSTD_decompressSequencesLong_bmi2(ZSTD_DCtx* dctx,
+ void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset)
+{
+ return ZSTD_decompressSequencesLong_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
+}
+
+#endif
+
+typedef size_t (*ZSTD_decompressSequences_t)(
+ ZSTD_DCtx *dctx, void *dst, size_t maxDstSize,
+ const void *seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset);
+
+static size_t ZSTD_decompressSequences(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset)
+{
+ DEBUGLOG(5, "ZSTD_decompressSequences");
+#if DYNAMIC_BMI2
+ if (dctx->bmi2) {
+ return ZSTD_decompressSequences_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
+ }
+#endif
+ return ZSTD_decompressSequences_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
+}
+
+static size_t ZSTD_decompressSequencesLong(ZSTD_DCtx* dctx,
+ void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset)
+{
+ DEBUGLOG(5, "ZSTD_decompressSequencesLong");
+#if DYNAMIC_BMI2
+ if (dctx->bmi2) {
+ return ZSTD_decompressSequencesLong_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
+ }
+#endif
+ return ZSTD_decompressSequencesLong_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
+}
+
+/* ZSTD_getLongOffsetsShare() :
+ * condition : offTable must be valid
+ * @return : "share" of long offsets (arbitrarily defined as > (1<<23))
+ * compared to maximum possible of (1<<OffFSELog) */
+static unsigned
+ZSTD_getLongOffsetsShare(const ZSTD_seqSymbol* offTable)
+{
+ const void* ptr = offTable;
+ U32 const tableLog = ((const ZSTD_seqSymbol_header*)ptr)[0].tableLog;
+ const ZSTD_seqSymbol* table = offTable + 1;
+ U32 const max = 1 << tableLog;
+ U32 u, total = 0;
+ DEBUGLOG(5, "ZSTD_getLongOffsetsShare: (tableLog=%u)", tableLog);
+
+ assert(max <= (1 << OffFSELog)); /* max not too large */
+ for (u=0; u<max; u++) {
+ if (table[u].nbAdditionalBits > 22) total += 1;
+ }
+
+ assert(tableLog <= OffFSELog);
+ total <<= (OffFSELog - tableLog); /* scale to OffFSELog */
+
+ return total;
+}
+
static size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
void* dst, size_t dstCapacity,
@@ -1410,13 +1662,9 @@ static size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
/* isLongOffset must be true if there are long offsets.
* Offsets are long if they are larger than 2^STREAM_ACCUMULATOR_MIN.
* We don't expect that to be the case in 64-bit mode.
- * If we are in block mode we don't know the window size, so we have to be
- * conservative.
+ * In block mode, window size is not known, so we have to be conservative. (note: but it could be evaluated from current-lowLimit)
*/
ZSTD_longOffset_e const isLongOffset = (ZSTD_longOffset_e)(MEM_32bits() && (!frame || dctx->fParams.windowSize > (1ULL << STREAM_ACCUMULATOR_MIN)));
- /* windowSize could be any value at this point, since it is only validated
- * in the streaming API.
- */
DEBUGLOG(5, "ZSTD_decompressBlock_internal (size : %u)", (U32)srcSize);
if (srcSize >= ZSTD_BLOCKSIZE_MAX) return ERROR(srcSize_wrong);
@@ -1428,9 +1676,24 @@ static size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
ip += litCSize;
srcSize -= litCSize;
}
- if (frame && dctx->fParams.windowSize > (1<<23))
- return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize, isLongOffset);
- return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize, isLongOffset);
+
+ /* Build Decoding Tables */
+ { int nbSeq;
+ size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, srcSize);
+ if (ZSTD_isError(seqHSize)) return seqHSize;
+ ip += seqHSize;
+ srcSize -= seqHSize;
+
+ if ( (!frame || dctx->fParams.windowSize > (1<<24))
+ && (nbSeq>0) ) { /* could probably use a larger nbSeq limit */
+ U32 const shareLongOffsets = ZSTD_getLongOffsetsShare(dctx->OFTptr);
+ U32 const minShare = MEM_64bits() ? 7 : 20; /* heuristic values, correspond to 2.73% and 7.81% */
+ if (shareLongOffsets >= minShare)
+ return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset);
+ }
+
+ return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset);
+ }
}
@@ -1758,7 +2021,7 @@ static int ZSTD_isSkipFrame(ZSTD_DCtx* dctx) { return dctx->stage == ZSTDds_skip
* or an error code, which can be tested using ZSTD_isError() */
size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
{
- DEBUGLOG(5, "ZSTD_decompressContinue");
+ DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (U32)srcSize);
/* Sanity check */
if (srcSize != dctx->expected) return ERROR(srcSize_wrong); /* not allowed */
if (dstCapacity) ZSTD_checkContinuity(dctx, dst);
@@ -1819,12 +2082,12 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
case ZSTDds_decompressLastBlock:
case ZSTDds_decompressBlock:
- DEBUGLOG(5, "case ZSTDds_decompressBlock");
+ DEBUGLOG(5, "ZSTD_decompressContinue: case ZSTDds_decompressBlock");
{ size_t rSize;
switch(dctx->bType)
{
case bt_compressed:
- DEBUGLOG(5, "case bt_compressed");
+ DEBUGLOG(5, "ZSTD_decompressContinue: case bt_compressed");
rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1);
break;
case bt_raw :
@@ -1838,12 +2101,12 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
return ERROR(corruption_detected);
}
if (ZSTD_isError(rSize)) return rSize;
- DEBUGLOG(5, "decoded size from block : %u", (U32)rSize);
+ DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (U32)rSize);
dctx->decodedSize += rSize;
if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, dst, rSize);
if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */
- DEBUGLOG(4, "decoded size from frame : %u", (U32)dctx->decodedSize);
+ DEBUGLOG(4, "ZSTD_decompressContinue: decoded size from frame : %u", (U32)dctx->decodedSize);
if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
if (dctx->decodedSize != dctx->fParams.frameContentSize) {
return ERROR(corruption_detected);
@@ -1867,7 +2130,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
assert(srcSize == 4); /* guaranteed by dctx->expected */
{ U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
U32 const check32 = MEM_readLE32(src);
- DEBUGLOG(4, "checksum : calculated %08X :: %08X read", h32, check32);
+ DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", h32, check32);
if (check32 != h32) return ERROR(checksum_wrong);
dctx->expected = 0;
dctx->stage = ZSTDds_getFrameHeaderSize;
@@ -1925,8 +2188,12 @@ static size_t ZSTD_loadEntropy(ZSTD_entropyDTables_t* entropy, const void* const
U32 offcodeMaxValue = MaxOff, offcodeLog;
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
+ if (offcodeMaxValue > MaxOff) return ERROR(dictionary_corrupted);
if (offcodeLog > OffFSELog) return ERROR(dictionary_corrupted);
- CHECK_E(FSE_buildDTable(entropy->OFTable, offcodeNCount, offcodeMaxValue, offcodeLog), dictionary_corrupted);
+ ZSTD_buildFSETable(entropy->OFTable,
+ offcodeNCount, offcodeMaxValue,
+ OF_base, OF_bits,
+ offcodeLog);
dictPtr += offcodeHeaderSize;
}
@@ -1934,8 +2201,12 @@ static size_t ZSTD_loadEntropy(ZSTD_entropyDTables_t* entropy, const void* const
unsigned matchlengthMaxValue = MaxML, matchlengthLog;
size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
+ if (matchlengthMaxValue > MaxML) return ERROR(dictionary_corrupted);
if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted);
- CHECK_E(FSE_buildDTable(entropy->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog), dictionary_corrupted);
+ ZSTD_buildFSETable(entropy->MLTable,
+ matchlengthNCount, matchlengthMaxValue,
+ ML_base, ML_bits,
+ matchlengthLog);
dictPtr += matchlengthHeaderSize;
}
@@ -1943,8 +2214,12 @@ static size_t ZSTD_loadEntropy(ZSTD_entropyDTables_t* entropy, const void* const
unsigned litlengthMaxValue = MaxLL, litlengthLog;
size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
+ if (litlengthMaxValue > MaxLL) return ERROR(dictionary_corrupted);
if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted);
- CHECK_E(FSE_buildDTable(entropy->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog), dictionary_corrupted);
+ ZSTD_buildFSETable(entropy->LLTable,
+ litlengthNCount, litlengthMaxValue,
+ LL_base, LL_bits,
+ litlengthLog);
dictPtr += litlengthHeaderSize;
}
@@ -2062,13 +2337,23 @@ size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dstDCtx, const ZSTD_DDict* ddi
return 0;
}
-static size_t ZSTD_loadEntropy_inDDict(ZSTD_DDict* ddict)
+static size_t ZSTD_loadEntropy_inDDict(ZSTD_DDict* ddict, ZSTD_dictContentType_e dictContentType)
{
ddict->dictID = 0;
ddict->entropyPresent = 0;
- if (ddict->dictSize < 8) return 0;
+ if (dictContentType == ZSTD_dct_rawContent) return 0;
+
+ if (ddict->dictSize < 8) {
+ if (dictContentType == ZSTD_dct_fullDict)
+ return ERROR(dictionary_corrupted); /* only accept specified dictionaries */
+ return 0; /* pure content mode */
+ }
{ U32 const magic = MEM_readLE32(ddict->dictContent);
- if (magic != ZSTD_MAGIC_DICTIONARY) return 0; /* pure content mode */
+ if (magic != ZSTD_MAGIC_DICTIONARY) {
+ if (dictContentType == ZSTD_dct_fullDict)
+ return ERROR(dictionary_corrupted); /* only accept specified dictionaries */
+ return 0; /* pure content mode */
+ }
}
ddict->dictID = MEM_readLE32((const char*)ddict->dictContent + ZSTD_frameIdSize);
@@ -2079,7 +2364,10 @@ static size_t ZSTD_loadEntropy_inDDict(ZSTD_DDict* ddict)
}
-static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod)
+static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict,
+ const void* dict, size_t dictSize,
+ ZSTD_dictLoadMethod_e dictLoadMethod,
+ ZSTD_dictContentType_e dictContentType)
{
if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dict) || (!dictSize)) {
ddict->dictBuffer = NULL;
@@ -2095,12 +2383,15 @@ static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict, const void* dict, size_
ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
/* parse dictionary content */
- CHECK_F( ZSTD_loadEntropy_inDDict(ddict) );
+ CHECK_F( ZSTD_loadEntropy_inDDict(ddict, dictContentType) );
return 0;
}
-ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_customMem customMem)
+ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize,
+ ZSTD_dictLoadMethod_e dictLoadMethod,
+ ZSTD_dictContentType_e dictContentType,
+ ZSTD_customMem customMem)
{
if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
@@ -2108,7 +2399,7 @@ ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, ZSTD_di
if (!ddict) return NULL;
ddict->cMem = customMem;
- if (ZSTD_isError( ZSTD_initDDict_internal(ddict, dict, dictSize, dictLoadMethod) )) {
+ if (ZSTD_isError( ZSTD_initDDict_internal(ddict, dict, dictSize, dictLoadMethod, dictContentType) )) {
ZSTD_freeDDict(ddict);
return NULL;
}
@@ -2124,7 +2415,7 @@ ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, ZSTD_di
ZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize)
{
ZSTD_customMem const allocator = { NULL, NULL, NULL };
- return ZSTD_createDDict_advanced(dict, dictSize, ZSTD_dlm_byCopy, allocator);
+ return ZSTD_createDDict_advanced(dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto, allocator);
}
/*! ZSTD_createDDict_byReference() :
@@ -2134,13 +2425,15 @@ ZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize)
ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize)
{
ZSTD_customMem const allocator = { NULL, NULL, NULL };
- return ZSTD_createDDict_advanced(dictBuffer, dictSize, ZSTD_dlm_byRef, allocator);
+ return ZSTD_createDDict_advanced(dictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, allocator);
}
-ZSTD_DDict* ZSTD_initStaticDDict(void* workspace, size_t workspaceSize,
- const void* dict, size_t dictSize,
- ZSTD_dictLoadMethod_e dictLoadMethod)
+const ZSTD_DDict* ZSTD_initStaticDDict(
+ void* workspace, size_t workspaceSize,
+ const void* dict, size_t dictSize,
+ ZSTD_dictLoadMethod_e dictLoadMethod,
+ ZSTD_dictContentType_e dictContentType)
{
size_t const neededSpace =
sizeof(ZSTD_DDict) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);
@@ -2153,7 +2446,7 @@ ZSTD_DDict* ZSTD_initStaticDDict(void* workspace, size_t workspaceSize,
memcpy(ddict+1, dict, dictSize); /* local copy */
dict = ddict+1;
}
- if (ZSTD_isError( ZSTD_initDDict_internal(ddict, dict, dictSize, ZSTD_dlm_byRef) ))
+ if (ZSTD_isError( ZSTD_initDDict_internal(ddict, dict, dictSize, ZSTD_dlm_byRef, dictContentType) ))
return NULL;
return ddict;
}
@@ -2247,6 +2540,7 @@ size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
ZSTD_DStream* ZSTD_createDStream(void)
{
+ DEBUGLOG(3, "ZSTD_createDStream");
return ZSTD_createDStream_advanced(ZSTD_defaultCMem);
}
@@ -2271,58 +2565,99 @@ size_t ZSTD_freeDStream(ZSTD_DStream* zds)
size_t ZSTD_DStreamInSize(void) { return ZSTD_BLOCKSIZE_MAX + ZSTD_blockHeaderSize; }
size_t ZSTD_DStreamOutSize(void) { return ZSTD_BLOCKSIZE_MAX; }
-size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize)
+size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType)
{
- zds->streamStage = zdss_loadHeader;
- zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
- ZSTD_freeDDict(zds->ddictLocal);
+ if (dctx->streamStage != zdss_init) return ERROR(stage_wrong);
+ ZSTD_freeDDict(dctx->ddictLocal);
if (dict && dictSize >= 8) {
- zds->ddictLocal = ZSTD_createDDict(dict, dictSize);
- if (zds->ddictLocal == NULL) return ERROR(memory_allocation);
- } else zds->ddictLocal = NULL;
- zds->ddict = zds->ddictLocal;
- zds->legacyVersion = 0;
- zds->hostageByte = 0;
+ dctx->ddictLocal = ZSTD_createDDict_advanced(dict, dictSize, dictLoadMethod, dictContentType, dctx->customMem);
+ if (dctx->ddictLocal == NULL) return ERROR(memory_allocation);
+ } else {
+ dctx->ddictLocal = NULL;
+ }
+ dctx->ddict = dctx->ddictLocal;
+ return 0;
+}
+
+size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
+{
+ return ZSTD_DCtx_loadDictionary_advanced(dctx, dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto);
+}
+
+size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
+{
+ return ZSTD_DCtx_loadDictionary_advanced(dctx, dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto);
+}
+
+size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
+{
+ return ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType);
+}
+
+size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize)
+{
+ return ZSTD_DCtx_refPrefix_advanced(dctx, prefix, prefixSize, ZSTD_dct_rawContent);
+}
+
+
+/* ZSTD_initDStream_usingDict() :
+ * return : expected size, aka ZSTD_frameHeaderSize_prefix.
+ * this function cannot fail */
+size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize)
+{
+ DEBUGLOG(4, "ZSTD_initDStream_usingDict");
+ zds->streamStage = zdss_init;
+ CHECK_F( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) );
return ZSTD_frameHeaderSize_prefix;
}
/* note : this variant can't fail */
size_t ZSTD_initDStream(ZSTD_DStream* zds)
{
+ DEBUGLOG(4, "ZSTD_initDStream");
return ZSTD_initDStream_usingDict(zds, NULL, 0);
}
+size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
+{
+ if (dctx->streamStage != zdss_init) return ERROR(stage_wrong);
+ dctx->ddict = ddict;
+ return 0;
+}
+
/* ZSTD_initDStream_usingDDict() :
* ddict will just be referenced, and must outlive decompression session
* this function cannot fail */
-size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict)
+size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
{
- size_t const initResult = ZSTD_initDStream(zds);
- zds->ddict = ddict;
+ size_t const initResult = ZSTD_initDStream(dctx);
+ dctx->ddict = ddict;
return initResult;
}
-size_t ZSTD_resetDStream(ZSTD_DStream* zds)
+/* ZSTD_resetDStream() :
+ * return : expected size, aka ZSTD_frameHeaderSize_prefix.
+ * this function cannot fail */
+size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
{
- zds->streamStage = zdss_loadHeader;
- zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
- zds->legacyVersion = 0;
- zds->hostageByte = 0;
+ DEBUGLOG(4, "ZSTD_resetDStream");
+ dctx->streamStage = zdss_loadHeader;
+ dctx->lhSize = dctx->inPos = dctx->outStart = dctx->outEnd = 0;
+ dctx->legacyVersion = 0;
+ dctx->hostageByte = 0;
return ZSTD_frameHeaderSize_prefix;
}
-size_t ZSTD_setDStreamParameter(ZSTD_DStream* zds,
+size_t ZSTD_setDStreamParameter(ZSTD_DStream* dctx,
ZSTD_DStreamParameter_e paramType, unsigned paramValue)
{
- ZSTD_STATIC_ASSERT((unsigned)zdss_loadHeader >= (unsigned)zdss_init);
- if ((unsigned)zds->streamStage > (unsigned)zdss_loadHeader)
- return ERROR(stage_wrong);
+ if (dctx->streamStage != zdss_init) return ERROR(stage_wrong);
switch(paramType)
{
default : return ERROR(parameter_unsupported);
case DStream_p_maxWindowSize :
DEBUGLOG(4, "setting maxWindowSize = %u KB", paramValue >> 10);
- zds->maxWindowSize = paramValue ? paramValue : (U32)(-1);
+ dctx->maxWindowSize = paramValue ? paramValue : (U32)(-1);
break;
}
return 0;
@@ -2330,9 +2665,7 @@ size_t ZSTD_setDStreamParameter(ZSTD_DStream* zds,
size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)
{
- ZSTD_STATIC_ASSERT((unsigned)zdss_loadHeader >= (unsigned)zdss_init);
- if ((unsigned)dctx->streamStage > (unsigned)zdss_loadHeader)
- return ERROR(stage_wrong);
+ if (dctx->streamStage != zdss_init) return ERROR(stage_wrong);
dctx->maxWindowSize = maxWindowSize;
return 0;
}
@@ -2340,17 +2673,15 @@ size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)
size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format)
{
DEBUGLOG(4, "ZSTD_DCtx_setFormat : %u", (unsigned)format);
- ZSTD_STATIC_ASSERT((unsigned)zdss_loadHeader >= (unsigned)zdss_init);
- if ((unsigned)dctx->streamStage > (unsigned)zdss_loadHeader)
- return ERROR(stage_wrong);
+ if (dctx->streamStage != zdss_init) return ERROR(stage_wrong);
dctx->format = format;
return 0;
}
-size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds)
+size_t ZSTD_sizeof_DStream(const ZSTD_DStream* dctx)
{
- return ZSTD_sizeof_DCtx(zds);
+ return ZSTD_sizeof_DCtx(dctx);
}
size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize)
@@ -2417,23 +2748,25 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
}
DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos));
-#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
- if (zds->legacyVersion) {
- /* legacy support is incompatible with static dctx */
- if (zds->staticSize) return ERROR(memory_allocation);
- return ZSTD_decompressLegacyStream(zds->legacyContext, zds->legacyVersion, output, input);
- }
-#endif
-
while (someMoreWork) {
switch(zds->streamStage)
{
case zdss_init :
+ DEBUGLOG(5, "stage zdss_init => transparent reset ");
ZSTD_resetDStream(zds); /* transparent reset on starting decoding a new frame */
/* fall-through */
case zdss_loadHeader :
DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip));
+#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
+ if (zds->legacyVersion) {
+ /* legacy support is incompatible with static dctx */
+ if (zds->staticSize) return ERROR(memory_allocation);
+ { size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, zds->legacyVersion, output, input);
+ if (hint==0) zds->streamStage = zdss_init;
+ return hint;
+ } }
+#endif
{ size_t const hSize = ZSTD_getFrameHeader_internal(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format);
DEBUGLOG(5, "header size : %u", (U32)hSize);
if (ZSTD_isError(hSize)) {
@@ -2442,14 +2775,17 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
if (legacyVersion) {
const void* const dict = zds->ddict ? zds->ddict->dictContent : NULL;
size_t const dictSize = zds->ddict ? zds->ddict->dictSize : 0;
+ DEBUGLOG(5, "ZSTD_decompressStream: detected legacy version v0.%u", legacyVersion);
/* legacy support is incompatible with static dctx */
if (zds->staticSize) return ERROR(memory_allocation);
CHECK_F(ZSTD_initLegacyStream(&zds->legacyContext,
zds->previousLegacyVersion, legacyVersion,
dict, dictSize));
zds->legacyVersion = zds->previousLegacyVersion = legacyVersion;
- return ZSTD_decompressLegacyStream(zds->legacyContext, legacyVersion, output, input);
- }
+ { size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, legacyVersion, output, input);
+ if (hint==0) zds->streamStage = zdss_init; /* or stay in stage zdss_loadHeader */
+ return hint;
+ } }
#endif
return hSize; /* error */
}
@@ -2559,6 +2895,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
if (ip==iend) { someMoreWork = 0; break; } /* no more input */
zds->streamStage = zdss_load;
/* fall-through */
+
case zdss_load:
{ size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);
size_t const toLoad = neededInSize - zds->inPos;
@@ -2585,6 +2922,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
} }
zds->streamStage = zdss_flush;
/* fall-through */
+
case zdss_flush:
{ size_t const toFlushSize = zds->outEnd - zds->outStart;
size_t const flushedSize = ZSTD_limitCopy(op, oend-op, zds->outBuff + zds->outStart, toFlushSize);
@@ -2631,8 +2969,8 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
return 1;
} /* nextSrcSizeHint==0 */
nextSrcSizeHint += ZSTD_blockHeaderSize * (ZSTD_nextInputType(zds) == ZSTDnit_block); /* preload header of next block */
- if (zds->inPos > nextSrcSizeHint) return ERROR(GENERIC); /* should never happen */
- nextSrcSizeHint -= zds->inPos; /* already loaded*/
+ assert(zds->inPos <= nextSrcSizeHint);
+ nextSrcSizeHint -= zds->inPos; /* part already loaded*/
return nextSrcSizeHint;
}
}
diff --git a/thirdparty/zstd/zstd.h b/thirdparty/zstd/zstd.h
index 9ac0a73dce..6405da602e 100644
--- a/thirdparty/zstd/zstd.h
+++ b/thirdparty/zstd/zstd.h
@@ -45,11 +45,11 @@ extern "C" {
Levels >= 20, labeled `--ultra`, should be used with caution, as they require more memory.
Compression can be done in:
- a single step (described as Simple API)
- - a single step, reusing a context (described as Explicit memory management)
+ - a single step, reusing a context (described as Explicit context)
- unbounded multiple steps (described as Streaming compression)
The compression ratio achievable on small data can be highly improved using a dictionary in:
- a single step (described as Simple dictionary API)
- - a single step, reusing a dictionary (described as Fast dictionary API)
+ - a single step, reusing a dictionary (described as Bulk-processing dictionary API)
Advanced experimental functions can be accessed using #define ZSTD_STATIC_LINKING_ONLY before including zstd.h.
Advanced experimental APIs shall never be used with a dynamic library.
@@ -59,7 +59,7 @@ extern "C" {
/*------ Version ------*/
#define ZSTD_VERSION_MAJOR 1
#define ZSTD_VERSION_MINOR 3
-#define ZSTD_VERSION_RELEASE 3
+#define ZSTD_VERSION_RELEASE 4
#define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)
ZSTDLIB_API unsigned ZSTD_versionNumber(void); /**< useful to check dll version */
@@ -68,7 +68,7 @@ ZSTDLIB_API unsigned ZSTD_versionNumber(void); /**< useful to check dll versio
#define ZSTD_QUOTE(str) #str
#define ZSTD_EXPAND_AND_QUOTE(str) ZSTD_QUOTE(str)
#define ZSTD_VERSION_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_LIB_VERSION)
-ZSTDLIB_API const char* ZSTD_versionString(void); /* v1.3.0 */
+ZSTDLIB_API const char* ZSTD_versionString(void); /* added in v1.3.0 */
/***************************************
@@ -92,7 +92,7 @@ ZSTDLIB_API size_t ZSTD_compress( void* dst, size_t dstCapacity,
ZSTDLIB_API size_t ZSTD_decompress( void* dst, size_t dstCapacity,
const void* src, size_t compressedSize);
-/*! ZSTD_getFrameContentSize() : v1.3.0
+/*! ZSTD_getFrameContentSize() : added in v1.3.0
* `src` should point to the start of a ZSTD encoded frame.
* `srcSize` must be at least as large as the frame header.
* hint : any size >= `ZSTD_frameHeaderSize_max` is large enough.
@@ -120,26 +120,24 @@ ZSTDLIB_API unsigned long long ZSTD_getFrameContentSize(const void *src, size_t
/*! ZSTD_getDecompressedSize() :
* NOTE: This function is now obsolete, in favor of ZSTD_getFrameContentSize().
- * Both functions work the same way,
- * but ZSTD_getDecompressedSize() blends
- * "empty", "unknown" and "error" results in the same return value (0),
- * while ZSTD_getFrameContentSize() distinguishes them.
- *
- * 'src' is the start of a zstd compressed frame.
- * @return : content size to be decompressed, as a 64-bits value _if known and not empty_, 0 otherwise. */
+ * Both functions work the same way, but ZSTD_getDecompressedSize() blends
+ * "empty", "unknown" and "error" results to the same return value (0),
+ * while ZSTD_getFrameContentSize() gives them separate return values.
+ * `src` is the start of a zstd compressed frame.
+ * @return : content size to be decompressed, as a 64-bits value _if known and not empty_, 0 otherwise. */
ZSTDLIB_API unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize);
/*====== Helper functions ======*/
#define ZSTD_COMPRESSBOUND(srcSize) ((srcSize) + ((srcSize)>>8) + (((srcSize) < (128<<10)) ? (((128<<10) - (srcSize)) >> 11) /* margin, from 64 to 0 */ : 0)) /* this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB */
-ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case scenario */
+ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */
ZSTDLIB_API unsigned ZSTD_isError(size_t code); /*!< tells if a `size_t` function result is an error code */
ZSTDLIB_API const char* ZSTD_getErrorName(size_t code); /*!< provides readable string from an error code */
ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compression level available */
/***************************************
-* Explicit memory management
+* Explicit context
***************************************/
/*= Compression context
* When compressing many times,
@@ -345,7 +343,7 @@ ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output
* *******************************************************************************/
typedef ZSTD_DCtx ZSTD_DStream; /**< DCtx and DStream are now effectively same object (>= v1.3.0) */
- /* Continue to distinguish them for compatibility with versions <= v1.2.0 */
+ /* For compatibility with versions <= v1.2.0, continue to consider them separated. */
/*===== ZSTD_DStream management functions =====*/
ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream(void);
ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream* zds);
@@ -375,23 +373,24 @@ ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output
/* --- Constants ---*/
#define ZSTD_MAGICNUMBER 0xFD2FB528 /* >= v0.8.0 */
#define ZSTD_MAGIC_SKIPPABLE_START 0x184D2A50U
-#define ZSTD_MAGIC_DICTIONARY 0xEC30A437 /* v0.7+ */
+#define ZSTD_MAGIC_DICTIONARY 0xEC30A437 /* >= v0.7.0 */
#define ZSTD_WINDOWLOG_MAX_32 30
#define ZSTD_WINDOWLOG_MAX_64 31
#define ZSTD_WINDOWLOG_MAX ((unsigned)(sizeof(size_t) == 4 ? ZSTD_WINDOWLOG_MAX_32 : ZSTD_WINDOWLOG_MAX_64))
#define ZSTD_WINDOWLOG_MIN 10
-#define ZSTD_HASHLOG_MAX MIN(ZSTD_WINDOWLOG_MAX, 30)
+#define ZSTD_HASHLOG_MAX ((ZSTD_WINDOWLOG_MAX < 30) ? ZSTD_WINDOWLOG_MAX : 30)
#define ZSTD_HASHLOG_MIN 6
-#define ZSTD_CHAINLOG_MAX MIN(ZSTD_WINDOWLOG_MAX+1, 30)
+#define ZSTD_CHAINLOG_MAX_32 29
+#define ZSTD_CHAINLOG_MAX_64 30
+#define ZSTD_CHAINLOG_MAX ((unsigned)(sizeof(size_t) == 4 ? ZSTD_CHAINLOG_MAX_32 : ZSTD_CHAINLOG_MAX_64))
#define ZSTD_CHAINLOG_MIN ZSTD_HASHLOG_MIN
#define ZSTD_HASHLOG3_MAX 17
#define ZSTD_SEARCHLOG_MAX (ZSTD_WINDOWLOG_MAX-1)
#define ZSTD_SEARCHLOG_MIN 1
#define ZSTD_SEARCHLENGTH_MAX 7 /* only for ZSTD_fast, other strategies are limited to 6 */
#define ZSTD_SEARCHLENGTH_MIN 3 /* only for ZSTD_btopt, other strategies are limited to 4 */
-#define ZSTD_TARGETLENGTH_MIN 4 /* only useful for btopt */
-#define ZSTD_TARGETLENGTH_MAX 999 /* only useful for btopt */
+#define ZSTD_TARGETLENGTH_MIN 1 /* only used by btopt, btultra and btfast */
#define ZSTD_LDM_MINMATCH_MIN 4
#define ZSTD_LDM_MINMATCH_MAX 4096
#define ZSTD_LDM_BUCKETSIZELOG_MAX 8
@@ -432,12 +431,17 @@ typedef struct {
typedef struct ZSTD_CCtx_params_s ZSTD_CCtx_params;
-/*--- Custom memory allocation functions ---*/
-typedef void* (*ZSTD_allocFunction) (void* opaque, size_t size);
-typedef void (*ZSTD_freeFunction) (void* opaque, void* address);
-typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; void* opaque; } ZSTD_customMem;
-/* use this constant to defer to stdlib's functions */
-static ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL };
+typedef enum {
+ ZSTD_dct_auto=0, /* dictionary is "full" when starting with ZSTD_MAGIC_DICTIONARY, otherwise it is "rawContent" */
+ ZSTD_dct_rawContent, /* ensures dictionary is always loaded as rawContent, even if it starts with ZSTD_MAGIC_DICTIONARY */
+ ZSTD_dct_fullDict /* refuses to load a dictionary if it does not respect Zstandard's specification */
+} ZSTD_dictContentType_e;
+
+typedef enum {
+ ZSTD_dlm_byCopy = 0, /**< Copy dictionary content internally */
+ ZSTD_dlm_byRef, /**< Reference dictionary content -- the dictionary buffer must outlive its users. */
+} ZSTD_dictLoadMethod_e;
+
/***************************************
@@ -483,12 +487,12 @@ ZSTDLIB_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize);
/***************************************
-* Context memory usage
+* Memory management
***************************************/
/*! ZSTD_sizeof_*() :
* These functions give the current memory usage of selected object.
- * Object memory usage can evolve when re-used multiple times. */
+ * Object memory usage can evolve when re-used. */
ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx);
ZSTDLIB_API size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx);
ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);
@@ -503,8 +507,8 @@ ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
* It will also consider src size to be arbitrarily "large", which is worst case.
* If srcSize is known to always be small, ZSTD_estimateCCtxSize_usingCParams() can provide a tighter estimation.
* ZSTD_estimateCCtxSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel.
- * ZSTD_estimateCCtxSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParam_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_p_nbThreads is > 1.
- * Note : CCtx estimation is only correct for single-threaded compression */
+ * ZSTD_estimateCCtxSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParam_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_p_nbWorkers is >= 1.
+ * Note : CCtx size estimation is only correct for single-threaded compression. */
ZSTDLIB_API size_t ZSTD_estimateCCtxSize(int compressionLevel);
ZSTDLIB_API size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams);
ZSTDLIB_API size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params);
@@ -515,8 +519,8 @@ ZSTDLIB_API size_t ZSTD_estimateDCtxSize(void);
* It will also consider src size to be arbitrarily "large", which is worst case.
* If srcSize is known to always be small, ZSTD_estimateCStreamSize_usingCParams() can provide a tighter estimation.
* ZSTD_estimateCStreamSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel.
- * ZSTD_estimateCStreamSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParam_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_p_nbThreads is set to a value > 1.
- * Note : CStream estimation is only correct for single-threaded compression.
+ * ZSTD_estimateCStreamSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParam_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_p_nbWorkers is >= 1.
+ * Note : CStream size estimation is only correct for single-threaded compression.
* ZSTD_DStream memory budget depends on window Size.
* This information can be passed manually, using ZSTD_estimateDStreamSize,
* or deducted from a valid frame Header, using ZSTD_estimateDStreamSize_fromFrame();
@@ -529,84 +533,92 @@ ZSTDLIB_API size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_para
ZSTDLIB_API size_t ZSTD_estimateDStreamSize(size_t windowSize);
ZSTDLIB_API size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize);
-typedef enum {
- ZSTD_dlm_byCopy = 0, /**< Copy dictionary content internally */
- ZSTD_dlm_byRef, /**< Reference dictionary content -- the dictionary buffer must outlive its users. */
-} ZSTD_dictLoadMethod_e;
-
/*! ZSTD_estimate?DictSize() :
* ZSTD_estimateCDictSize() will bet that src size is relatively "small", and content is copied, like ZSTD_createCDict().
- * ZSTD_estimateCStreamSize_advanced_usingCParams() makes it possible to control precisely compression parameters, like ZSTD_createCDict_advanced().
- * Note : dictionary created by reference using ZSTD_dlm_byRef are smaller
+ * ZSTD_estimateCDictSize_advanced() makes it possible to control compression parameters precisely, like ZSTD_createCDict_advanced().
+ * Note : dictionaries created by reference (`ZSTD_dlm_byRef`) are logically smaller.
*/
ZSTDLIB_API size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel);
ZSTDLIB_API size_t ZSTD_estimateCDictSize_advanced(size_t dictSize, ZSTD_compressionParameters cParams, ZSTD_dictLoadMethod_e dictLoadMethod);
ZSTDLIB_API size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod);
-
-/***************************************
-* Advanced compression functions
-***************************************/
-/*! ZSTD_createCCtx_advanced() :
- * Create a ZSTD compression context using external alloc and free functions */
-ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem);
-
-/*! ZSTD_initStaticCCtx() : initialize a fixed-size zstd compression context
- * workspace: The memory area to emplace the context into.
- * Provided pointer must 8-bytes aligned.
- * It must outlive context usage.
- * workspaceSize: Use ZSTD_estimateCCtxSize() or ZSTD_estimateCStreamSize()
- * to determine how large workspace must be to support scenario.
- * @return : pointer to ZSTD_CCtx* (same address as workspace, but different type),
- * or NULL if error (typically size too small)
- * Note : zstd will never resize nor malloc() when using a static cctx.
- * If it needs more memory than available, it will simply error out.
+/*! ZSTD_initStatic*() :
+ * Initialize an object using a pre-allocated fixed-size buffer.
+ * workspace: The memory area to emplace the object into.
+ * Provided pointer *must be 8-bytes aligned*.
+ * Buffer must outlive object.
+ * workspaceSize: Use ZSTD_estimate*Size() to determine
+ * how large workspace must be to support target scenario.
+ * @return : pointer to object (same address as workspace, just different type),
+ * or NULL if error (size too small, incorrect alignment, etc.)
+ * Note : zstd will never resize nor malloc() when using a static buffer.
+ * If the object requires more memory than available,
+ * zstd will just error out (typically ZSTD_error_memory_allocation).
* Note 2 : there is no corresponding "free" function.
- * Since workspace was allocated externally, it must be freed externally too.
- * Limitation 1 : currently not compatible with internal CDict creation, such as
- * ZSTD_CCtx_loadDictionary() or ZSTD_initCStream_usingDict().
- * Limitation 2 : currently not compatible with multi-threading
+ * Since workspace is allocated externally, it must be freed externally too.
+ * Note 3 : cParams : use ZSTD_getCParams() to convert a compression level
+ * into its associated cParams.
+ * Limitation 1 : currently not compatible with internal dictionary creation, triggered by
+ * ZSTD_CCtx_loadDictionary(), ZSTD_initCStream_usingDict() or ZSTD_initDStream_usingDict().
+ * Limitation 2 : static cctx currently not compatible with multi-threading.
+ * Limitation 3 : static dctx is incompatible with legacy support.
*/
-ZSTDLIB_API ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize);
+ZSTDLIB_API ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize);
+ZSTDLIB_API ZSTD_CStream* ZSTD_initStaticCStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticCCtx() */
+ZSTDLIB_API ZSTD_DCtx* ZSTD_initStaticDCtx(void* workspace, size_t workspaceSize);
+ZSTDLIB_API ZSTD_DStream* ZSTD_initStaticDStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticDCtx() */
-/*! ZSTD_createCDict_byReference() :
- * Create a digested dictionary for compression
- * Dictionary content is simply referenced, and therefore stays in dictBuffer.
- * It is important that dictBuffer outlives CDict, it must remain read accessible throughout the lifetime of CDict */
-ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel);
+ZSTDLIB_API const ZSTD_CDict* ZSTD_initStaticCDict(
+ void* workspace, size_t workspaceSize,
+ const void* dict, size_t dictSize,
+ ZSTD_dictLoadMethod_e dictLoadMethod,
+ ZSTD_dictContentType_e dictContentType,
+ ZSTD_compressionParameters cParams);
+
+ZSTDLIB_API const ZSTD_DDict* ZSTD_initStaticDDict(
+ void* workspace, size_t workspaceSize,
+ const void* dict, size_t dictSize,
+ ZSTD_dictLoadMethod_e dictLoadMethod,
+ ZSTD_dictContentType_e dictContentType);
+
+/*! Custom memory allocation :
+ * These prototypes make it possible to pass your own allocation/free functions.
+ * ZSTD_customMem is provided at creation time, using ZSTD_create*_advanced() variants listed below.
+ * All allocation/free operations will be completed using these custom variants instead of regular <stdlib.h> ones.
+ */
+typedef void* (*ZSTD_allocFunction) (void* opaque, size_t size);
+typedef void (*ZSTD_freeFunction) (void* opaque, void* address);
+typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; void* opaque; } ZSTD_customMem;
+static ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; /**< this constant defers to stdlib's functions */
+
+ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem);
+ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem);
+ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem);
+ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem);
-typedef enum { ZSTD_dm_auto=0, /* dictionary is "full" if it starts with ZSTD_MAGIC_DICTIONARY, otherwise it is "rawContent" */
- ZSTD_dm_rawContent, /* ensures dictionary is always loaded as rawContent, even if it starts with ZSTD_MAGIC_DICTIONARY */
- ZSTD_dm_fullDict /* refuses to load a dictionary if it does not respect Zstandard's specification */
-} ZSTD_dictMode_e;
-/*! ZSTD_createCDict_advanced() :
- * Create a ZSTD_CDict using external alloc and free, and customized compression parameters */
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize,
ZSTD_dictLoadMethod_e dictLoadMethod,
- ZSTD_dictMode_e dictMode,
+ ZSTD_dictContentType_e dictContentType,
ZSTD_compressionParameters cParams,
ZSTD_customMem customMem);
-/*! ZSTD_initStaticCDict() :
- * Generate a digested dictionary in provided memory area.
- * workspace: The memory area to emplace the dictionary into.
- * Provided pointer must 8-bytes aligned.
- * It must outlive dictionary usage.
- * workspaceSize: Use ZSTD_estimateCDictSize()
- * to determine how large workspace must be.
- * cParams : use ZSTD_getCParams() to transform a compression level
- * into its relevants cParams.
- * @return : pointer to ZSTD_CDict* (same address as workspace, but different type),
- * or NULL if error (typically, size too small).
- * Note : there is no corresponding "free" function.
- * Since workspace was allocated externally, it must be freed externally.
- */
-ZSTDLIB_API ZSTD_CDict* ZSTD_initStaticCDict(
- void* workspace, size_t workspaceSize,
- const void* dict, size_t dictSize,
- ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictMode_e dictMode,
- ZSTD_compressionParameters cParams);
+ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize,
+ ZSTD_dictLoadMethod_e dictLoadMethod,
+ ZSTD_dictContentType_e dictContentType,
+ ZSTD_customMem customMem);
+
+
+
+/***************************************
+* Advanced compression functions
+***************************************/
+
+/*! ZSTD_createCDict_byReference() :
+ * Create a digested dictionary for compression
+ * Dictionary content is simply referenced, and therefore stays in dictBuffer.
+ * It is important that dictBuffer outlives CDict, it must remain read accessible throughout the lifetime of CDict */
+ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel);
/*! ZSTD_getCParams() :
* @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize.
@@ -652,28 +664,6 @@ ZSTDLIB_API size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
* Note 3 : Skippable Frame Identifiers are considered valid. */
ZSTDLIB_API unsigned ZSTD_isFrame(const void* buffer, size_t size);
-/*! ZSTD_createDCtx_advanced() :
- * Create a ZSTD decompression context using external alloc and free functions */
-ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem);
-
-/*! ZSTD_initStaticDCtx() : initialize a fixed-size zstd decompression context
- * workspace: The memory area to emplace the context into.
- * Provided pointer must 8-bytes aligned.
- * It must outlive context usage.
- * workspaceSize: Use ZSTD_estimateDCtxSize() or ZSTD_estimateDStreamSize()
- * to determine how large workspace must be to support scenario.
- * @return : pointer to ZSTD_DCtx* (same address as workspace, but different type),
- * or NULL if error (typically size too small)
- * Note : zstd will never resize nor malloc() when using a static dctx.
- * If it needs more memory than available, it will simply error out.
- * Note 2 : static dctx is incompatible with legacy support
- * Note 3 : there is no corresponding "free" function.
- * Since workspace was allocated externally, it must be freed externally.
- * Limitation : currently not compatible with internal DDict creation,
- * such as ZSTD_initDStream_usingDict().
- */
-ZSTDLIB_API ZSTD_DCtx* ZSTD_initStaticDCtx(void* workspace, size_t workspaceSize);
-
/*! ZSTD_createDDict_byReference() :
* Create a digested dictionary, ready to start decompression operation without startup delay.
* Dictionary content is referenced, and therefore stays in dictBuffer.
@@ -681,26 +671,6 @@ ZSTDLIB_API ZSTD_DCtx* ZSTD_initStaticDCtx(void* workspace, size_t workspaceSize
* it must remain read accessible throughout the lifetime of DDict */
ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize);
-/*! ZSTD_createDDict_advanced() :
- * Create a ZSTD_DDict using external alloc and free, optionally by reference */
-ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize,
- ZSTD_dictLoadMethod_e dictLoadMethod,
- ZSTD_customMem customMem);
-
-/*! ZSTD_initStaticDDict() :
- * Generate a digested dictionary in provided memory area.
- * workspace: The memory area to emplace the dictionary into.
- * Provided pointer must 8-bytes aligned.
- * It must outlive dictionary usage.
- * workspaceSize: Use ZSTD_estimateDDictSize()
- * to determine how large workspace must be.
- * @return : pointer to ZSTD_DDict*, or NULL if error (size too small)
- * Note : there is no corresponding "free" function.
- * Since workspace was allocated externally, it must be freed externally.
- */
-ZSTDLIB_API ZSTD_DDict* ZSTD_initStaticDDict(void* workspace, size_t workspaceSize,
- const void* dict, size_t dictSize,
- ZSTD_dictLoadMethod_e dictLoadMethod);
/*! ZSTD_getDictID_fromDict() :
* Provides the dictID stored within dictionary.
@@ -732,8 +702,6 @@ ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
********************************************************************/
/*===== Advanced Streaming compression functions =====*/
-ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem);
-ZSTDLIB_API ZSTD_CStream* ZSTD_initStaticCStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticCCtx() */
ZSTDLIB_API size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize); /**< pledgedSrcSize must be correct. If it is not known at init time, use ZSTD_CONTENTSIZE_UNKNOWN. Note that, for compatibility with older programs, "0" also disables frame content size field. It may be enabled in the future. */
ZSTDLIB_API size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel); /**< creates of an internal CDict (incompatible with static CCtx), except if dict == NULL or dictSize < 8, in which case no dict is used. Note: dict is loaded with ZSTD_dm_auto (treated as a full zstd dictionary if it begins with ZSTD_MAGIC_DICTIONARY, else as raw content) and ZSTD_dlm_byCopy.*/
ZSTDLIB_API size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, const void* dict, size_t dictSize,
@@ -748,14 +716,28 @@ ZSTDLIB_API size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, const
* If pledgedSrcSize is not known at reset time, use macro ZSTD_CONTENTSIZE_UNKNOWN.
* If pledgedSrcSize > 0, its value must be correct, as it will be written in header, and controlled at the end.
* For the time being, pledgedSrcSize==0 is interpreted as "srcSize unknown" for compatibility with older programs,
- * but it may change to mean "empty" in some future version, so prefer using macro ZSTD_CONTENTSIZE_UNKNOWN.
+ * but it will change to mean "empty" in future version, so use macro ZSTD_CONTENTSIZE_UNKNOWN instead.
* @return : 0, or an error code (which can be tested using ZSTD_isError()) */
ZSTDLIB_API size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize);
+typedef struct {
+ unsigned long long ingested;
+ unsigned long long consumed;
+ unsigned long long produced;
+} ZSTD_frameProgression;
+
+/* ZSTD_getFrameProgression():
+ * tells how much data has been ingested (read from input)
+ * consumed (input actually compressed) and produced (output) for current frame.
+ * Therefore, (ingested - consumed) is amount of input data buffered internally, not yet compressed.
+ * Can report progression inside worker threads (multi-threading and non-blocking mode).
+ */
+ZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx);
+
+
+
/*===== Advanced Streaming decompression functions =====*/
-ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem);
-ZSTDLIB_API ZSTD_DStream* ZSTD_initStaticDStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticDCtx() */
typedef enum { DStream_p_maxWindowSize } ZSTD_DStreamParameter_e;
ZSTDLIB_API size_t ZSTD_setDStreamParameter(ZSTD_DStream* zds, ZSTD_DStreamParameter_e paramType, unsigned paramValue); /* obsolete : this API will be removed in a future version */
ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize); /**< note: no dictionary will be used if dict == NULL or dictSize < 8 */
@@ -924,10 +906,8 @@ ZSTDLIB_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx);
* and then applied on all subsequent compression jobs.
* When no parameter is ever provided, CCtx is created with compression level ZSTD_CLEVEL_DEFAULT.
*
- * This API is intended to replace all others experimental API.
- * It can basically do all other use cases, and even new ones.
- * In constrast with _advanced() variants, it stands a reasonable chance to become "stable",
- * after a good testing period.
+ * This API is intended to replace all others advanced / experimental API entry points.
+ * But it stands a reasonable chance to become "stable", after a reasonable testing period.
*/
/* note on naming convention :
@@ -944,12 +924,12 @@ ZSTDLIB_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx);
* All enum will be pinned to explicit values before reaching "stable API" status */
typedef enum {
- /* Question : should we have a format ZSTD_f_auto ?
- * For the time being, it would mean exactly the same as ZSTD_f_zstd1.
- * But, in the future, should several formats be supported,
+ /* Opened question : should we have a format ZSTD_f_auto ?
+ * Today, it would mean exactly the same as ZSTD_f_zstd1.
+ * But, in the future, should several formats become supported,
* on the compression side, it would mean "default format".
- * On the decompression side, it would mean "multi format",
- * and ZSTD_f_zstd1 could be reserved to mean "accept *only* zstd frames".
+ * On the decompression side, it would mean "automatic format detection",
+ * so that ZSTD_f_zstd1 would mean "accept *only* zstd frames".
* Since meaning is a little different, another option could be to define different enums for compression and decompression.
* This question could be kept for later, when there are actually multiple formats to support,
* but there is also the question of pinning enum values, and pinning value `0` is especially important */
@@ -967,42 +947,76 @@ typedef enum {
/* compression parameters */
ZSTD_p_compressionLevel=100, /* Update all compression parameters according to pre-defined cLevel table
* Default level is ZSTD_CLEVEL_DEFAULT==3.
- * Special: value 0 means "do not change cLevel". */
+ * Special: value 0 means "do not change cLevel".
+ * Note 1 : it's possible to pass a negative compression level by casting it to unsigned type.
+ * Note 2 : setting a level sets all default values of other compression parameters.
+ * Note 3 : setting compressionLevel automatically updates ZSTD_p_compressLiterals. */
ZSTD_p_windowLog, /* Maximum allowed back-reference distance, expressed as power of 2.
* Must be clamped between ZSTD_WINDOWLOG_MIN and ZSTD_WINDOWLOG_MAX.
- * Special: value 0 means "do not change windowLog".
+ * Special: value 0 means "use default windowLog".
* Note: Using a window size greater than ZSTD_MAXWINDOWSIZE_DEFAULT (default: 2^27)
- * requires setting the maximum window size at least as large during decompression. */
+ * requires explicitly allowing such window size during decompression stage. */
ZSTD_p_hashLog, /* Size of the probe table, as a power of 2.
* Resulting table size is (1 << (hashLog+2)).
* Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX.
* Larger tables improve compression ratio of strategies <= dFast,
* and improve speed of strategies > dFast.
- * Special: value 0 means "do not change hashLog". */
+ * Special: value 0 means "use default hashLog". */
ZSTD_p_chainLog, /* Size of the full-search table, as a power of 2.
* Resulting table size is (1 << (chainLog+2)).
* Larger tables result in better and slower compression.
* This parameter is useless when using "fast" strategy.
- * Special: value 0 means "do not change chainLog". */
+ * Special: value 0 means "use default chainLog". */
ZSTD_p_searchLog, /* Number of search attempts, as a power of 2.
* More attempts result in better and slower compression.
* This parameter is useless when using "fast" and "dFast" strategies.
- * Special: value 0 means "do not change searchLog". */
+ * Special: value 0 means "use default searchLog". */
ZSTD_p_minMatch, /* Minimum size of searched matches (note : repCode matches can be smaller).
* Larger values make faster compression and decompression, but decrease ratio.
* Must be clamped between ZSTD_SEARCHLENGTH_MIN and ZSTD_SEARCHLENGTH_MAX.
* Note that currently, for all strategies < btopt, effective minimum is 4.
- * Note that currently, for all strategies > fast, effective maximum is 6.
- * Special: value 0 means "do not change minMatchLength". */
- ZSTD_p_targetLength, /* Only useful for strategies >= btopt.
- * Length of Match considered "good enough" to stop search.
- * Larger values make compression stronger and slower.
- * Special: value 0 means "do not change targetLength". */
+ * , for all strategies > fast, effective maximum is 6.
+ * Special: value 0 means "use default minMatchLength". */
+ ZSTD_p_targetLength, /* Impact of this field depends on strategy.
+ * For strategies btopt & btultra:
+ * Length of Match considered "good enough" to stop search.
+ * Larger values make compression stronger, and slower.
+ * For strategy fast:
+ * Distance between match sampling.
+ * Larger values make compression faster, and weaker.
+ * Special: value 0 means "use default targetLength". */
ZSTD_p_compressionStrategy, /* See ZSTD_strategy enum definition.
* Cast selected strategy as unsigned for ZSTD_CCtx_setParameter() compatibility.
* The higher the value of selected strategy, the more complex it is,
* resulting in stronger and slower compression.
- * Special: value 0 means "do not change strategy". */
+ * Special: value 0 means "use default strategy". */
+
+ ZSTD_p_enableLongDistanceMatching=160, /* Enable long distance matching.
+ * This parameter is designed to improve compression ratio
+ * for large inputs, by finding large matches at long distance.
+ * It increases memory usage and window size.
+ * Note: enabling this parameter increases ZSTD_p_windowLog to 128 MB
+ * except when expressly set to a different value. */
+ ZSTD_p_ldmHashLog, /* Size of the table for long distance matching, as a power of 2.
+ * Larger values increase memory usage and compression ratio,
+ * but decrease compression speed.
+ * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX
+ * default: windowlog - 7.
+ * Special: value 0 means "automatically determine hashlog". */
+ ZSTD_p_ldmMinMatch, /* Minimum match size for long distance matcher.
+ * Larger/too small values usually decrease compression ratio.
+ * Must be clamped between ZSTD_LDM_MINMATCH_MIN and ZSTD_LDM_MINMATCH_MAX.
+ * Special: value 0 means "use default value" (default: 64). */
+ ZSTD_p_ldmBucketSizeLog, /* Log size of each bucket in the LDM hash table for collision resolution.
+ * Larger values improve collision resolution but decrease compression speed.
+ * The maximum value is ZSTD_LDM_BUCKETSIZELOG_MAX .
+ * Special: value 0 means "use default value" (default: 3). */
+ ZSTD_p_ldmHashEveryLog, /* Frequency of inserting/looking up entries in the LDM hash table.
+ * Must be clamped between 0 and (ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN).
+ * Default is MAX(0, (windowLog - ldmHashLog)), optimizing hash table usage.
+ * Larger values improve compression speed.
+ * Deviating far from default value will likely result in a compression ratio decrease.
+ * Special: value 0 means "automatically determine hashEveryLog". */
/* frame parameters */
ZSTD_p_contentSizeFlag=200, /* Content size will be written into frame header _whenever known_ (default:1)
@@ -1012,58 +1026,45 @@ typedef enum {
ZSTD_p_dictIDFlag, /* When applicable, dictionary's ID is written into frame header (default:1) */
/* multi-threading parameters */
- ZSTD_p_nbThreads=400, /* Select how many threads a compression job can spawn (default:1)
- * More threads improve speed, but also increase memory usage.
- * Can only receive a value > 1 if ZSTD_MULTITHREAD is enabled.
- * Special: value 0 means "do not change nbThreads" */
- ZSTD_p_jobSize, /* Size of a compression job. This value is only enforced in streaming (non-blocking) mode.
- * Each compression job is completed in parallel, so indirectly controls the nb of active threads.
+ /* These parameters are only useful if multi-threading is enabled (ZSTD_MULTITHREAD).
+ * They return an error otherwise. */
+ ZSTD_p_nbWorkers=400, /* Select how many threads will be spawned to compress in parallel.
+ * When nbWorkers >= 1, triggers asynchronous mode :
+ * ZSTD_compress_generic() consumes some input, flush some output if possible, and immediately gives back control to caller,
+ * while compression work is performed in parallel, within worker threads.
+ * (note : a strong exception to this rule is when first invocation sets ZSTD_e_end : it becomes a blocking call).
+ * More workers improve speed, but also increase memory usage.
+ * Default value is `0`, aka "single-threaded mode" : no worker is spawned, compression is performed inside Caller's thread, all invocations are blocking */
+ ZSTD_p_jobSize, /* Size of a compression job. This value is enforced only in non-blocking mode.
+ * Each compression job is completed in parallel, so this value indirectly controls the nb of active threads.
* 0 means default, which is dynamically determined based on compression parameters.
- * Job size must be a minimum of overlapSize, or 1 KB, whichever is largest
+ * Job size must be a minimum of overlapSize, or 1 MB, whichever is largest.
* The minimum size is automatically and transparently enforced */
ZSTD_p_overlapSizeLog, /* Size of previous input reloaded at the beginning of each job.
* 0 => no overlap, 6(default) => use 1/8th of windowSize, >=9 => use full windowSize */
- /* advanced parameters - may not remain available after API update */
+ /* =================================================================== */
+ /* experimental parameters - no stability guaranteed */
+ /* =================================================================== */
+
+ ZSTD_p_compressLiterals=1000, /* control huffman compression of literals (enabled) by default.
+ * disabling it improves speed and decreases compression ratio by a large amount.
+ * note : this setting is automatically updated when changing compression level.
+ * positive compression levels set ZSTD_p_compressLiterals to 1.
+ * negative compression levels set ZSTD_p_compressLiterals to 0. */
+
ZSTD_p_forceMaxWindow=1100, /* Force back-reference distances to remain < windowSize,
* even when referencing into Dictionary content (default:0) */
- ZSTD_p_enableLongDistanceMatching=1200, /* Enable long distance matching.
- * This parameter is designed to improve the compression
- * ratio for large inputs with long distance matches.
- * This increases the memory usage as well as window size.
- * Note: setting this parameter sets all the LDM parameters
- * as well as ZSTD_p_windowLog. It should be set after
- * ZSTD_p_compressionLevel and before ZSTD_p_windowLog and
- * other LDM parameters. Setting the compression level
- * after this parameter overrides the window log, though LDM
- * will remain enabled until explicitly disabled. */
- ZSTD_p_ldmHashLog, /* Size of the table for long distance matching, as a power of 2.
- * Larger values increase memory usage and compression ratio, but decrease
- * compression speed.
- * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX
- * (default: windowlog - 7). */
- ZSTD_p_ldmMinMatch, /* Minimum size of searched matches for long distance matcher.
- * Larger/too small values usually decrease compression ratio.
- * Must be clamped between ZSTD_LDM_MINMATCH_MIN
- * and ZSTD_LDM_MINMATCH_MAX (default: 64). */
- ZSTD_p_ldmBucketSizeLog, /* Log size of each bucket in the LDM hash table for collision resolution.
- * Larger values usually improve collision resolution but may decrease
- * compression speed.
- * The maximum value is ZSTD_LDM_BUCKETSIZELOG_MAX (default: 3). */
- ZSTD_p_ldmHashEveryLog, /* Frequency of inserting/looking up entries in the LDM hash table.
- * The default is MAX(0, (windowLog - ldmHashLog)) to
- * optimize hash table usage.
- * Larger values improve compression speed. Deviating far from the
- * default value will likely result in a decrease in compression ratio.
- * Must be clamped between 0 and ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN. */
} ZSTD_cParameter;
/*! ZSTD_CCtx_setParameter() :
* Set one compression parameter, selected by enum ZSTD_cParameter.
+ * Setting a parameter is generally only possible during frame initialization (before starting compression),
+ * except for a few exceptions which can be updated during compression: compressionLevel, hashLog, chainLog, searchLog, minMatch, targetLength and strategy.
* Note : when `value` is an enum, cast it to unsigned for proper type checking.
- * @result : informational value (typically, the one being set, possibly corrected),
+ * @result : informational value (typically, value being set clamped correctly),
* or an error code (which can be tested with ZSTD_isError()). */
ZSTDLIB_API size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, unsigned value);
@@ -1079,26 +1080,24 @@ ZSTDLIB_API size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param
ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize);
/*! ZSTD_CCtx_loadDictionary() :
- * Create an internal CDict from dict buffer.
- * Decompression will have to use same buffer.
+ * Create an internal CDict from `dict` buffer.
+ * Decompression will have to use same dictionary.
* @result : 0, or an error code (which can be tested with ZSTD_isError()).
- * Special : Adding a NULL (or 0-size) dictionary invalidates any previous dictionary,
- * meaning "return to no-dictionary mode".
- * Note 1 : `dict` content will be copied internally. Use
- * ZSTD_CCtx_loadDictionary_byReference() to reference dictionary
- * content instead. The dictionary buffer must then outlive its
- * users.
+ * Special: Adding a NULL (or 0-size) dictionary invalidates previous dictionary,
+ * meaning "return to no-dictionary mode".
+ * Note 1 : Dictionary will be used for all future compression jobs.
+ * To return to "no-dictionary" situation, load a NULL dictionary
* Note 2 : Loading a dictionary involves building tables, which are dependent on compression parameters.
* For this reason, compression parameters cannot be changed anymore after loading a dictionary.
- * It's also a CPU-heavy operation, with non-negligible impact on latency.
- * Note 3 : Dictionary will be used for all future compression jobs.
- * To return to "no-dictionary" situation, load a NULL dictionary
- * Note 5 : Use ZSTD_CCtx_loadDictionary_advanced() to select how dictionary
- * content will be interpreted.
- */
+ * It's also a CPU consuming operation, with non-negligible impact on latency.
+ * Note 3 :`dict` content will be copied internally.
+ * Use ZSTD_CCtx_loadDictionary_byReference() to reference dictionary content instead.
+ * In such a case, dictionary buffer must outlive its users.
+ * Note 4 : Use ZSTD_CCtx_loadDictionary_advanced()
+ * to precisely select how dictionary content must be interpreted. */
ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);
ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_byReference(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);
-ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictMode_e dictMode);
+ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType);
/*! ZSTD_CCtx_refCDict() :
@@ -1110,8 +1109,7 @@ ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_advanced(ZSTD_CCtx* cctx, const void
* Special : adding a NULL CDict means "return to no-dictionary mode".
* Note 1 : Currently, only one dictionary can be managed.
* Adding a new dictionary effectively "discards" any previous one.
- * Note 2 : CDict is just referenced, its lifetime must outlive CCtx.
- */
+ * Note 2 : CDict is just referenced, its lifetime must outlive CCtx. */
ZSTDLIB_API size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);
/*! ZSTD_CCtx_refPrefix() :
@@ -1121,20 +1119,29 @@ ZSTDLIB_API size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);
* Subsequent compression jobs will be done without prefix (if none is explicitly referenced).
* If there is a need to use same prefix multiple times, consider embedding it into a ZSTD_CDict instead.
* @result : 0, or an error code (which can be tested with ZSTD_isError()).
- * Special : Adding any prefix (including NULL) invalidates any previous prefix or dictionary
+ * Special: Adding any prefix (including NULL) invalidates any previous prefix or dictionary
* Note 1 : Prefix buffer is referenced. It must outlive compression job.
* Note 2 : Referencing a prefix involves building tables, which are dependent on compression parameters.
- * It's a CPU-heavy operation, with non-negligible impact on latency.
- * Note 3 : By default, the prefix is treated as raw content
- * (ZSTD_dm_rawContent). Use ZSTD_CCtx_refPrefix_advanced() to alter
- * dictMode. */
+ * It's a CPU consuming operation, with non-negligible impact on latency.
+ * Note 3 : By default, the prefix is treated as raw content (ZSTD_dm_rawContent).
+ * Use ZSTD_CCtx_refPrefix_advanced() to alter dictMode. */
ZSTDLIB_API size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize);
-ZSTDLIB_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictMode_e dictMode);
+ZSTDLIB_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType);
+
+/*! ZSTD_CCtx_reset() :
+ * Return a CCtx to clean state.
+ * Useful after an error, or to interrupt an ongoing compression job and start a new one.
+ * Any internal data not yet flushed is cancelled.
+ * Dictionary (if any) is dropped.
+ * All parameters are back to default values.
+ * It's possible to modify compression parameters after a reset.
+ */
+ZSTDLIB_API void ZSTD_CCtx_reset(ZSTD_CCtx* cctx);
typedef enum {
- ZSTD_e_continue=0, /* collect more data, encoder transparently decides when to output result, for optimal conditions */
+ ZSTD_e_continue=0, /* collect more data, encoder decides when to output compressed result, for optimal conditions */
ZSTD_e_flush, /* flush any data provided so far - frame will continue, future data can still reference previous data for better compression */
ZSTD_e_end /* flush any remaining data and close current frame. Any additional data starts a new frame. */
} ZSTD_EndDirective;
@@ -1150,10 +1157,11 @@ typedef enum {
* and then immediately returns, just indicating that there is some data remaining to be flushed.
* The function nonetheless guarantees forward progress : it will return only after it reads or write at least 1+ byte.
* - Exception : in multi-threading mode, if the first call requests a ZSTD_e_end directive, it is blocking : it will complete compression before giving back control to caller.
- * - @return provides the minimum amount of data remaining to be flushed from internal buffers
+ * - @return provides a minimum amount of data remaining to be flushed from internal buffers
* or an error code, which can be tested using ZSTD_isError().
* if @return != 0, flush is not fully completed, there is still some data left within internal buffers.
- * This is useful to determine if a ZSTD_e_flush or ZSTD_e_end directive is completed.
+ * This is useful for ZSTD_e_flush, since in this case more flushes are necessary to empty all buffers.
+ * For ZSTD_e_end, @return == 0 when internal buffers are fully flushed and frame is completed.
* - after a ZSTD_e_end directive, if internal buffer is not fully flushed (@return != 0),
* only ZSTD_e_end or ZSTD_e_flush operations are allowed.
* Before starting a new compression job, or changing compression parameters,
@@ -1164,16 +1172,6 @@ ZSTDLIB_API size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
ZSTD_inBuffer* input,
ZSTD_EndDirective endOp);
-/*! ZSTD_CCtx_reset() :
- * Return a CCtx to clean state.
- * Useful after an error, or to interrupt an ongoing compression job and start a new one.
- * Any internal data not yet flushed is cancelled.
- * Dictionary (if any) is dropped.
- * All parameters are back to default values.
- * It's possible to modify compression parameters after a reset.
- */
-ZSTDLIB_API void ZSTD_CCtx_reset(ZSTD_CCtx* cctx); /* Not ready yet ! */
-
/*! ZSTD_compress_generic_simpleArgs() :
* Same as ZSTD_compress_generic(),
@@ -1207,25 +1205,26 @@ ZSTDLIB_API size_t ZSTD_compress_generic_simpleArgs (
* for static allocation for single-threaded compression.
*/
ZSTDLIB_API ZSTD_CCtx_params* ZSTD_createCCtxParams(void);
+ZSTDLIB_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params);
-/*! ZSTD_resetCCtxParams() :
- * Reset params to default, with the default compression level.
+
+/*! ZSTD_CCtxParams_reset() :
+ * Reset params to default values.
*/
-ZSTDLIB_API size_t ZSTD_resetCCtxParams(ZSTD_CCtx_params* params);
+ZSTDLIB_API size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params);
-/*! ZSTD_initCCtxParams() :
+/*! ZSTD_CCtxParams_init() :
* Initializes the compression parameters of cctxParams according to
* compression level. All other parameters are reset to their default values.
*/
-ZSTDLIB_API size_t ZSTD_initCCtxParams(ZSTD_CCtx_params* cctxParams, int compressionLevel);
+ZSTDLIB_API size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel);
-/*! ZSTD_initCCtxParams_advanced() :
+/*! ZSTD_CCtxParams_init_advanced() :
* Initializes the compression and frame parameters of cctxParams according to
* params. All other parameters are reset to their default values.
*/
-ZSTDLIB_API size_t ZSTD_initCCtxParams_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params);
+ZSTDLIB_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params);
-ZSTDLIB_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params);
/*! ZSTD_CCtxParam_setParameter() :
* Similar to ZSTD_CCtx_setParameter.
@@ -1238,9 +1237,10 @@ ZSTDLIB_API size_t ZSTD_CCtxParam_setParameter(ZSTD_CCtx_params* params, ZSTD_cP
/*! ZSTD_CCtx_setParametersUsingCCtxParams() :
* Apply a set of ZSTD_CCtx_params to the compression context.
- * This must be done before the dictionary is loaded.
- * The pledgedSrcSize is treated as unknown.
- * Multithreading parameters are applied only if nbThreads > 1.
+ * This can be done even after compression is started,
+ * if nbWorkers==0, this will have no impact until a new compression is started.
+ * if nbWorkers>=1, new parameters will be picked up at next job,
+ * with a few restrictions (windowLog, pledgedSrcSize, nbWorkers, jobSize, and overlapLog are not updated).
*/
ZSTDLIB_API size_t ZSTD_CCtx_setParametersUsingCCtxParams(
ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params);
@@ -1267,9 +1267,9 @@ ZSTDLIB_API size_t ZSTD_CCtx_setParametersUsingCCtxParams(
* Note 3 : Use ZSTD_DCtx_loadDictionary_advanced() to select
* how dictionary content will be interpreted and loaded.
*/
-ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); /* not implemented */
-ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); /* not implemented */
-ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictMode_e dictMode); /* not implemented */
+ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
+ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
+ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType);
/*! ZSTD_DCtx_refDDict() :
@@ -1281,7 +1281,7 @@ ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, const void
* Special : adding a NULL DDict means "return to no-dictionary mode".
* Note 2 : DDict is just referenced, its lifetime must outlive its usage from DCtx.
*/
-ZSTDLIB_API size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict); /* not implemented */
+ZSTDLIB_API size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);
/*! ZSTD_DCtx_refPrefix() :
@@ -1295,8 +1295,8 @@ ZSTDLIB_API size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);
* Use ZSTD_CCtx_refPrefix_advanced() to alter dictMode.
* Note 4 : Referencing a raw content prefix has almost no cpu nor memory cost.
*/
-ZSTDLIB_API size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize); /* not implemented */
-ZSTDLIB_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictMode_e dictMode); /* not implemented */
+ZSTDLIB_API size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize);
+ZSTDLIB_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType);
/*! ZSTD_DCtx_setMaxWindowSize() :
@@ -1389,7 +1389,7 @@ ZSTDLIB_API void ZSTD_DCtx_reset(ZSTD_DCtx* dctx);
ZSTDLIB_API size_t ZSTD_getBlockSize (const ZSTD_CCtx* cctx);
ZSTDLIB_API size_t ZSTD_compressBlock (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
ZSTDLIB_API size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
-ZSTDLIB_API size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize); /**< insert uncompressed block into `dctx` history. Useful for multi-blocks decompression */
+ZSTDLIB_API size_t ZSTD_insertBlock (ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize); /**< insert uncompressed block into `dctx` history. Useful for multi-blocks decompression. */
#endif /* ZSTD_H_ZSTD_STATIC_LINKING_ONLY */